更新:课程与图书下单支付功能初步完成
This commit is contained in:
@@ -307,7 +307,7 @@ function closePurchasePopup() {
|
||||
// 处理购买
|
||||
function handlePurchase() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/book/order?id=${bookId.value}`
|
||||
url: `/pages/order/goodsConfirm?goods=${bookId.value}`
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -454,18 +454,8 @@ const confirmPurchase = () => {
|
||||
showProtocol.value = false
|
||||
|
||||
// 跳转到确认订单页
|
||||
const orderData = {
|
||||
goods: [{ ...selectedGoods.value, productAmount: 1 }],
|
||||
// typeId: 0,
|
||||
// navTitle: courseDetail.value?.title,
|
||||
// title: courseDetail.value?.title,
|
||||
// isFudu: isFudu.value,
|
||||
// fuduId: isFudu.value ? fuduCatalogueId.value : undefined
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
// url: `/pages/order/confirmOrder?data=${encodeURIComponent(JSON.stringify(orderData))}`
|
||||
url: `/pages/order/confirmOrder?goods=${selectedGoods.value.productId}`
|
||||
url: `/pages/order/goodsConfirm?goods=${selectedGoods.value.productId}`
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,672 +0,0 @@
|
||||
<template>
|
||||
<view class="course-order-page">
|
||||
<!-- 自定义导航栏 -->
|
||||
<nav-bar :title="$t('courseOrder.orderTitle')" />
|
||||
|
||||
<!-- 页面内容 -->
|
||||
<view class="page-content">
|
||||
<!-- 商品列表 -->
|
||||
<view class="goods-section">
|
||||
<view class="section-title">商品信息</view>
|
||||
<view
|
||||
v-for="(item, index) in goodsList"
|
||||
:key="index"
|
||||
class="goods-item"
|
||||
>
|
||||
<view class="goods-image">
|
||||
<!-- VIP优惠标签 -->
|
||||
<view
|
||||
v-if="item.isVipPrice === 1 && item.vipPrice"
|
||||
class="vip-badge"
|
||||
>
|
||||
VIP优惠
|
||||
</view>
|
||||
<image
|
||||
:src="item.productImages || '/static/nobg.jpg'"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="goods-info">
|
||||
<text class="goods-name">{{ item.productName }}</text>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="price-info">
|
||||
<!-- VIP优惠价 -->
|
||||
<view v-if="item.isVipPrice === 1 && item.vipPrice" class="price-row">
|
||||
<text class="vip-price">¥{{ item.vipPrice.toFixed(2) }}</text>
|
||||
<text class="vip-label">VIP到手价</text>
|
||||
<text class="original-price">¥{{ item.price.toFixed(2) }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 活动价 -->
|
||||
<view v-else-if="item.activityPrice && item.activityPrice > 0" class="price-row">
|
||||
<text class="activity-price">¥{{ item.activityPrice.toFixed(2) }}</text>
|
||||
<text class="activity-label">活动价</text>
|
||||
<text class="original-price">¥{{ item.price.toFixed(2) }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 普通价格 -->
|
||||
<view v-else class="price-row">
|
||||
<text class="normal-price">¥{{ item.price.toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数量 -->
|
||||
<view class="quantity">
|
||||
<text>数量:{{ item.productAmount || 1 }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收货地址(仅实体商品显示) -->
|
||||
<view v-if="!isHideAddress" class="address-section">
|
||||
<view class="section-title">收货地址</view>
|
||||
<view v-if="selectedAddress" class="address-info" @click="selectAddress">
|
||||
<view class="address-row">
|
||||
<text class="name">{{ selectedAddress.name }}</text>
|
||||
<text class="phone">{{ selectedAddress.phone }}</text>
|
||||
</view>
|
||||
<view class="address-detail">
|
||||
{{ selectedAddress.province }} {{ selectedAddress.city }} {{ selectedAddress.district }} {{ selectedAddress.detail }}
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="no-address" @click="selectAddress">
|
||||
<wd-icon name="add-circle" size="24px" />
|
||||
<text>添加收货地址</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="order-info-section">
|
||||
<view class="info-row">
|
||||
<text class="label">商品金额</text>
|
||||
<text class="value">¥{{ goodsAmount.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view v-if="!isHideAddress" class="info-row">
|
||||
<text class="label">运费</text>
|
||||
<text class="value">¥{{ freight.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view v-if="availablePoints > 0" class="info-row">
|
||||
<text class="label">可用积分</text>
|
||||
<text class="value">{{ availablePoints }} 分(可抵扣 ¥{{ pointsDiscount.toFixed(2) }})</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单总价 -->
|
||||
<view class="total-section">
|
||||
<view class="total-row">
|
||||
<text class="label">订单总价</text>
|
||||
<text class="value">¥{{ totalAmount.toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作栏 -->
|
||||
<view class="bottom-bar">
|
||||
<view class="total-info">
|
||||
<text class="label">合计:</text>
|
||||
<text class="amount">¥{{ totalAmount.toFixed(2) }}</text>
|
||||
</view>
|
||||
<wd-button
|
||||
type="primary"
|
||||
:loading="submitting"
|
||||
@click="submitOrder"
|
||||
>
|
||||
提交订单
|
||||
</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import type { IOrderGoods, IOrderInitData } from '@/types/course'
|
||||
|
||||
interface OrderData {
|
||||
goods: IOrderGoods[]
|
||||
typeId?: number
|
||||
navTitle?: string
|
||||
title?: string
|
||||
isFudu?: boolean
|
||||
fuduId?: number
|
||||
isVip?: boolean
|
||||
}
|
||||
|
||||
// Stores
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 页面数据
|
||||
const orderData = ref<OrderData>({
|
||||
goods: []
|
||||
})
|
||||
const goodsList = ref<IOrderGoods[]>([])
|
||||
const initData = ref<IOrderInitData | null>(null)
|
||||
const selectedAddress = ref<any>(null)
|
||||
const isHideAddress = ref(false)
|
||||
const availablePoints = ref(0)
|
||||
const freight = ref(0)
|
||||
const submitting = ref(false)
|
||||
|
||||
/**
|
||||
* 商品金额
|
||||
*/
|
||||
const goodsAmount = computed(() => {
|
||||
return goodsList.value.reduce((sum, item) => {
|
||||
const price = item.isVipPrice === 1 && item.vipPrice
|
||||
? item.vipPrice
|
||||
: item.activityPrice || item.price
|
||||
return sum + price * (item.productAmount || 1)
|
||||
}, 0)
|
||||
})
|
||||
|
||||
/**
|
||||
* 积分抵扣金额
|
||||
*/
|
||||
const pointsDiscount = computed(() => {
|
||||
// 假设100积分可抵扣1元
|
||||
return Math.min(availablePoints.value / 100, goodsAmount.value * 0.1)
|
||||
})
|
||||
|
||||
/**
|
||||
* 订单总价
|
||||
*/
|
||||
const totalAmount = computed(() => {
|
||||
return Math.max(0, goodsAmount.value + freight.value - pointsDiscount.value)
|
||||
})
|
||||
|
||||
/**
|
||||
* 页面加载
|
||||
*/
|
||||
onLoad(async (options: any) => {
|
||||
if (options.data) {
|
||||
try {
|
||||
orderData.value = JSON.parse(decodeURIComponent(options.data))
|
||||
goodsList.value = orderData.value.goods || []
|
||||
|
||||
await initOrder()
|
||||
} catch (error) {
|
||||
console.error('解析订单数据失败:', error)
|
||||
uni.showToast({
|
||||
title: '订单数据错误',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化订单
|
||||
*/
|
||||
const initOrder = async () => {
|
||||
try {
|
||||
uni.showLoading({ title: '加载中...' })
|
||||
|
||||
// 根据订单类型调用不同的初始化接口
|
||||
if (orderData.value.isVip) {
|
||||
// VIP订单
|
||||
await initVipOrder()
|
||||
} else if (orderData.value.isFudu) {
|
||||
// 复读订单
|
||||
await initFuduOrder()
|
||||
} else {
|
||||
// 普通订单
|
||||
await initNormalOrder()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化订单失败:', error)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化普通订单
|
||||
*/
|
||||
const initNormalOrder = async () => {
|
||||
try {
|
||||
const res = await uni.request({
|
||||
url: uni.getStorageSync('baseURL') + 'common/buyOrder/initPrepareOrder',
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'token': userStore.token
|
||||
},
|
||||
data: {
|
||||
uid: userStore.userInfo.id,
|
||||
productList: goodsList.value.map(item => ({
|
||||
productId: item.productId,
|
||||
quantity: item.productAmount || 1
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
const data = res.data as any
|
||||
if (data.code === 0 && data.data) {
|
||||
initData.value = data.data
|
||||
isHideAddress.value = data.data.is_course || false
|
||||
availablePoints.value = data.data.user?.jf || 0
|
||||
|
||||
// 如果有默认地址,设置为选中地址
|
||||
if (data.data.addressList && data.data.addressList.length > 0) {
|
||||
selectedAddress.value = data.data.addressList.find((addr: any) => addr.isDefault === 1)
|
||||
|| data.data.addressList[0]
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化普通订单失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化复读订单
|
||||
*/
|
||||
const initFuduOrder = async () => {
|
||||
// 复读订单不需要地址
|
||||
isHideAddress.value = true
|
||||
|
||||
// 获取用户信息
|
||||
try {
|
||||
const res = await uni.request({
|
||||
url: uni.getStorageSync('baseURL') + 'common/user/getUserInfo',
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'token': userStore.token
|
||||
},
|
||||
data: {}
|
||||
})
|
||||
|
||||
const data = res.data as any
|
||||
if (data.code === 0 && data.result) {
|
||||
initData.value = {
|
||||
user: data.result,
|
||||
is_course: true
|
||||
}
|
||||
availablePoints.value = data.result.jf || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化VIP订单
|
||||
*/
|
||||
const initVipOrder = async () => {
|
||||
// VIP订单不需要地址
|
||||
isHideAddress.value = true
|
||||
|
||||
// 获取用户信息
|
||||
try {
|
||||
const res = await uni.request({
|
||||
url: uni.getStorageSync('baseURL') + 'common/user/getUserInfo',
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'token': userStore.token
|
||||
},
|
||||
data: {}
|
||||
})
|
||||
|
||||
const data = res.data as any
|
||||
if (data.code === 0 && data.result) {
|
||||
initData.value = {
|
||||
user: data.result,
|
||||
is_course: true
|
||||
}
|
||||
// VIP订单不使用积分
|
||||
availablePoints.value = 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择地址
|
||||
*/
|
||||
const selectAddress = () => {
|
||||
// 跳转到地址选择页面
|
||||
uni.navigateTo({
|
||||
url: '/pages/user/address/list'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交订单
|
||||
*/
|
||||
const submitOrder = async () => {
|
||||
// 验证
|
||||
if (!isHideAddress.value && !selectedAddress.value) {
|
||||
uni.showToast({
|
||||
title: '请选择收货地址',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
submitting.value = true
|
||||
|
||||
let orderUrl = ''
|
||||
let orderParams: any = {}
|
||||
|
||||
if (orderData.value.isVip) {
|
||||
// VIP订单
|
||||
orderUrl = 'common/userVip/placeVipOrder'
|
||||
orderParams = {
|
||||
vipConfigId: goodsList.value[0].productId,
|
||||
payType: 1 // 默认支付方式
|
||||
}
|
||||
} else if (orderData.value.isFudu) {
|
||||
// 复读订单
|
||||
orderUrl = 'common/courseRelearn/relearnSave'
|
||||
orderParams = {
|
||||
catalogueId: orderData.value.fuduId,
|
||||
productId: goodsList.value[0].productId,
|
||||
quantity: 1
|
||||
}
|
||||
} else {
|
||||
// 普通订单
|
||||
orderUrl = 'book/buyOrder/placeOrder'
|
||||
orderParams = {
|
||||
uid: userStore.userInfo.id,
|
||||
addressId: selectedAddress.value?.id,
|
||||
productList: goodsList.value.map(item => ({
|
||||
productId: item.productId,
|
||||
quantity: item.productAmount || 1
|
||||
})),
|
||||
usePoints: pointsDiscount.value > 0
|
||||
}
|
||||
}
|
||||
|
||||
const res = await uni.request({
|
||||
url: uni.getStorageSync('baseURL') + orderUrl,
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'token': userStore.token
|
||||
},
|
||||
data: orderParams
|
||||
})
|
||||
|
||||
const data = res.data as any
|
||||
if (data.code === 0) {
|
||||
uni.showToast({
|
||||
title: '订单创建成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 跳转到支付页面或订单详情
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
url: `/pages/user/order/index`
|
||||
})
|
||||
}, 1500)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: data.errMsg || '订单创建失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提交订单失败:', error)
|
||||
uni.showToast({
|
||||
title: '提交失败',
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.course-order-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.goods-section {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.goods-item {
|
||||
display: flex;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.goods-image {
|
||||
position: relative;
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.vip-badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 4rpx 10rpx;
|
||||
background-color: #f94f04;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
border-radius: 8rpx 0 8rpx 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.goods-name {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.price-info {
|
||||
.price-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 10rpx;
|
||||
|
||||
.vip-price,
|
||||
.activity-price {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #e97512;
|
||||
}
|
||||
|
||||
.normal-price {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.vip-label {
|
||||
font-size: 22rpx;
|
||||
color: #fa2d12;
|
||||
}
|
||||
|
||||
.activity-label {
|
||||
font-size: 22rpx;
|
||||
color: #613804;
|
||||
}
|
||||
|
||||
.original-price {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.quantity {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.address-section {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.address-info {
|
||||
padding: 20rpx;
|
||||
background-color: #f7f8f9;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.address-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.phone {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.address-detail {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.no-address {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
padding: 40rpx 20rpx;
|
||||
background-color: #f7f8f9;
|
||||
border-radius: 8rpx;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.order-info-section {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 15rpx 0;
|
||||
font-size: 28rpx;
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.total-section {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
|
||||
.total-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.label {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 36rpx;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.1);
|
||||
z-index: 999;
|
||||
|
||||
.total-info {
|
||||
flex: 1;
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 36rpx;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
239
pages/order/goodsConfirm.vue
Normal file
239
pages/order/goodsConfirm.vue
Normal file
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 自定义导航栏 -->
|
||||
<nav-bar :title="$t('order.confirmTitle')" />
|
||||
|
||||
<!-- 确认订单组件 -->
|
||||
<Confirm :goodsList="goodsList" :userInfo="userInfo">
|
||||
<template #goodsList>
|
||||
<!-- 商品列表内容 -->
|
||||
<view
|
||||
v-for="(item, index) in goodsList"
|
||||
:key="index"
|
||||
class="goods-item"
|
||||
>
|
||||
<!-- VIP优惠标签 -->
|
||||
<wd-tag v-if="item.isVipPrice === 1 && item.vipPrice" type="danger" mark custom-class="vip-badge">{{ $t('order.vipLabel') }}</wd-tag>
|
||||
|
||||
<!-- 商品图片 -->
|
||||
<view class="goods-image">
|
||||
<image
|
||||
:src="item.productImages || '/static/nobg.jpg'"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<view class="goods-info">
|
||||
<text class="goods-name">{{ item.productName }}</text>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="price-info">
|
||||
<!-- VIP优惠价 -->
|
||||
<!-- <view v-if="item.isVipPrice === 1 && item.vipPrice" class="price-row">
|
||||
<text class="vip-price">¥{{ item.vipPrice.toFixed(2) }}</text>
|
||||
<text class="vip-label">{{ $t('order.vipPriceLabel') }}</text>
|
||||
<text class="original-price">¥{{ item.price.toFixed(2) }}</text>
|
||||
</view> -->
|
||||
|
||||
<!-- 活动价 -->
|
||||
<!-- <view v-else-if="item.activityPrice && item.activityPrice > 0" class="price-row">
|
||||
<text class="activity-price">¥{{ item.activityPrice.toFixed(2) }}</text>
|
||||
<text class="activity-label">{{ $t('order.activityLabel') }}</text>
|
||||
<text class="original-price">¥{{ item.price.toFixed(2) }}</text>
|
||||
</view> -->
|
||||
|
||||
<!-- 普通价格 -->
|
||||
<view class="price-row">
|
||||
<text class="normal-price">{{ item.price.toFixed(2) }} 天医币</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数量 -->
|
||||
<!-- <view class="quantity-row">
|
||||
<text class="quantity-label">{{ $t('order.quantity') }}:</text>
|
||||
<view v-if="showNumber" class="quantity-control">
|
||||
<wd-number-box
|
||||
v-model="item.productAmount"
|
||||
:min="1"
|
||||
@change="handleQuantityChange(item, $event)"
|
||||
/>
|
||||
</view>
|
||||
<text v-else>X {{ item.productAmount }}</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Confirm>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { orderApi } from '@/api/modules/order'
|
||||
import Confirm from '@/components/order/Confirm.vue';
|
||||
import type { IOrderGoods } from '@/types/order'
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
const userInfo = ref(null)
|
||||
const getUserInfo = async () => {
|
||||
try {
|
||||
const res = await orderApi.getUserInfo()
|
||||
if (res.code === 0) {
|
||||
userInfo.value = res.result || {}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品列表
|
||||
*/
|
||||
const goodsIds = ref<string>('')
|
||||
const goodsList = ref<IOrderGoods[]>([])
|
||||
const getGoodsList = async () => {
|
||||
try {
|
||||
// 获取商品详情
|
||||
const res = await orderApi.getShopProductListByIds(goodsIds.value)
|
||||
|
||||
if (res.code === 0 && res.shopProductList?.length > 0) {
|
||||
goodsList.value = res.shopProductList
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取商品列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面加载
|
||||
*/
|
||||
onLoad(async (options: any) => {
|
||||
if (options.goods) {
|
||||
try {
|
||||
// 获取用户信息
|
||||
await getUserInfo()
|
||||
|
||||
// 根据商品ID获取商品详细信息
|
||||
goodsIds.value = options.goods || ''
|
||||
getGoodsList()
|
||||
} catch (error) {
|
||||
console.error('解析商品数据失败:', error)
|
||||
uni.showToast({
|
||||
title: '商品数据错误',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.vip-badge {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.goods-image {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.goods-name {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.price-info {
|
||||
.price-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 10rpx;
|
||||
|
||||
.vip-price,
|
||||
.activity-price {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #e97512;
|
||||
}
|
||||
|
||||
.normal-price {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.vip-label {
|
||||
font-size: 22rpx;
|
||||
color: #fa2d12;
|
||||
}
|
||||
|
||||
.activity-label {
|
||||
font-size: 22rpx;
|
||||
color: #613804;
|
||||
}
|
||||
|
||||
.original-price {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.quantity-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
|
||||
.quantity-label {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.quantity-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user