-
-
-
+
+
+
+
+
+
+ {{ paymentData.pointsAmount }}
+
+
+
+
+

+
{{ paymentData.beansAmount }}
+
+
-
+
+
+
+ {{ paymentData.beansAmount }}
+
+
+
+ {{ paymentData.pointsAmount }}
-
-
-
-
- {{ paymentData.pointsAmount || 0 }}
-
-
+
-
-

-
{{ paymentData.beansAmount || 0 }}
-
-
-
-
-
-
-
- {{ paymentData.totalAmount || 0 }}
@@ -158,7 +128,7 @@
- {{ item.points || item.price }}
+ {{ item.points }}
@@ -172,7 +142,9 @@
支付方式
+
+
+
积分+融豆
使用积分和融豆组合支付
- 余额不足(当前:{{ userBalance.points + userBalance.beans }})
+ 余额不足(当前:融豆{{ userBalance.beans }} + 积分{{ userBalance.points }})
@@ -241,31 +217,31 @@
实付:
-
-
-
+
+
+
+
+
+
+ {{ paymentData.pointsAmount }}
+
+
+
+
+

+
{{ paymentData.beansAmount }}
+
+
-
+
+
+
+ {{ paymentData.beansAmount }}
+
+
+
+ {{ paymentData.pointsAmount }}
-
-
-
-
- {{ paymentData.pointsAmount || 0 }}
-
-
+
-
-

-
{{ paymentData.beansAmount || 0 }}
-
-
-
-
-
-
-
- {{ paymentData.totalAmount || 0 }}
- {{ timeLeft <= 0 ? '支付超时' : paying ? '支付中...' : '确认支付' }}
+ {{ paying ? '支付中...' : '确认支付' }}
@@ -301,6 +277,7 @@ const router = useRouter()
// 响应式数据
const loading = ref(false)
const paying = ref(false)
+
const selectedPaymentMethod = ref('') // 当前选择的支付方式
const paymentData = ref({
totalAmount: 0,
@@ -322,15 +299,44 @@ const selectedAddress = ref(null)
// 方法
const selectPaymentMethod = async (method) => {
+ const totalPointsPrice = paymentData.value.items.reduce((sum, item) => sum + (item.points * item.quantity), 0)
+ const totalBeansPrice = paymentData.value.items.reduce((sum, item) => sum + (item.rongdouPrice * item.quantity), 0)
+
+ // 检查支付方式是否符合商品价格要求
+ if (method === 'beans' && totalPointsPrice > 0) {
+ ElMessage.warning('此订单包含积分商品,不能仅使用融豆支付')
+ return
+ }
+ if (method === 'points' && totalBeansPrice > 0) {
+ ElMessage.warning('此订单包含融豆商品,不能仅使用积分支付')
+ return
+ }
+ if (method === 'mixed' && (totalPointsPrice === 0 || totalBeansPrice === 0)) {
+ ElMessage.warning('此订单不支持混合支付')
+ return
+ }
+
// 检查支付方式是否可用
if (!isPaymentMethodAvailable(method)) {
let message = ''
if (method === 'beans') {
- message = `融豆余额不足,当前余额:${userBalance.value.beans},需要:${paymentData.value.totalAmount}`
+ if (totalBeansPrice === 0) {
+ message = '该订单不支持融豆支付'
+ } else {
+ message = `融豆余额不足,当前余额:${userBalance.value.beans},需要:${totalBeansPrice}`
+ }
} else if (method === 'points') {
- message = `积分余额不足,当前余额:${userBalance.value.points},需要:${paymentData.value.totalAmount}`
+ if (totalPointsPrice === 0) {
+ message = '该订单不支持积分支付'
+ } else {
+ message = `积分余额不足,当前余额:${userBalance.value.points},需要:${totalPointsPrice}`
+ }
} else if (method === 'mixed') {
- message = `融豆和积分余额不足,当前余额:融豆${userBalance.value.beans} + 积分${userBalance.value.points} = ${userBalance.value.beans + userBalance.value.points},需要:${paymentData.value.totalAmount}`
+ if (totalPointsPrice === 0 && totalBeansPrice === 0) {
+ message = '该订单不支持混合支付'
+ } else {
+ message = `余额不足,当前余额:融豆${userBalance.value.beans},积分${userBalance.value.points},需要:融豆${totalBeansPrice},积分${totalPointsPrice}`
+ }
}
ElMessage.warning(message)
return
@@ -338,32 +344,19 @@ const selectPaymentMethod = async (method) => {
selectedPaymentMethod.value = method
- // 当切换支付方式时,向后端获取对应的支付金额
- if (paymentData.value.orderId) {
- await fetchPaymentAmountByMethod(method)
- }
-}
-
-// 根据支付方式获取支付金额
-const fetchPaymentAmountByMethod = async (paymentMethod) => {
- try {
- const response = await api.post('/payment/calculate', {
- orderId: paymentData.value.orderId,
- paymentMethod: paymentMethod
- })
-
- if (response.data.success) {
- const data = response.data.data
- // 更新支付数据
- paymentData.value.totalAmount = data.totalAmount || 0
- paymentData.value.pointsAmount = data.pointsAmount || 0
- paymentData.value.beansAmount = data.beansAmount || 0
- } else {
- ElMessage.error(response.data.message || '获取支付金额失败')
- }
- } catch (error) {
- console.error('获取支付金额失败:', error)
- ElMessage.error('获取支付金额失败,请重试')
+ // 根据选择的支付方式更新显示的金额
+ if (method === 'beans') {
+ paymentData.value.totalAmount = totalBeansPrice
+ paymentData.value.pointsAmount = 0
+ paymentData.value.beansAmount = totalBeansPrice
+ } else if (method === 'points') {
+ paymentData.value.totalAmount = totalPointsPrice
+ paymentData.value.pointsAmount = totalPointsPrice
+ paymentData.value.beansAmount = 0
+ } else if (method === 'mixed') {
+ paymentData.value.totalAmount = totalPointsPrice + totalBeansPrice
+ paymentData.value.pointsAmount = totalPointsPrice
+ paymentData.value.beansAmount = totalBeansPrice
}
}
@@ -420,10 +413,10 @@ const fetchUserBalance = async () => {
const pointsResponse = await api.get('/user/points')
userBalance.value.points = pointsResponse.data?.currentPoints ?? pointsResponse.data?.points ?? 0
- // 获取用户融豆(从用户资料接口获取)
+ // 获取用户融豆(从用户资料接口获取,需要取反)
const profileResponse = await api.get('/user/profile')
if (profileResponse.data.success && profileResponse.data.user) {
- userBalance.value.beans = parseFloat(profileResponse.data.user.balance) || 0
+ userBalance.value.beans = -(parseFloat(profileResponse.data.user.balance) || 0)
}
} catch (error) {
console.error('获取用户余额失败:', error)
@@ -434,16 +427,26 @@ const fetchUserBalance = async () => {
// 检查支付方式是否可用
const isPaymentMethodAvailable = (method) => {
- const totalAmount = paymentData.value.totalAmount
+ // 计算商品的总积分价格和总融豆价格
+ const totalPointsPrice = paymentData.value.items.reduce((sum, item) => sum + (item.points * item.quantity), 0)
+ const totalBeansPrice = paymentData.value.items.reduce((sum, item) => sum + (item.rongdouPrice * item.quantity), 0)
switch (method) {
case 'beans':
- return userBalance.value.beans >= totalAmount
+ // 如果所有商品的融豆价格总和为0,则不能选择融豆支付
+ if (totalBeansPrice === 0) return false
+ return userBalance.value.beans >= totalBeansPrice
case 'points':
- return userBalance.value.points >= totalAmount
+ // 如果所有商品的积分价格总和为0,则不能选择积分支付
+ if (totalPointsPrice === 0) return false
+ return userBalance.value.points >= totalPointsPrice
case 'mixed':
- // 融豆和积分总和是否足够(1积分=1融豆)
- return (userBalance.value.beans + userBalance.value.points) >= totalAmount
+ // 如果积分价格和融豆价格都为0,则不能选择混合支付
+ if (totalPointsPrice === 0 && totalBeansPrice === 0) return false
+ // 检查用户余额是否足够支付
+ const hasEnoughPoints = totalPointsPrice === 0 || userBalance.value.points >= totalPointsPrice
+ const hasEnoughBeans = totalBeansPrice === 0 || userBalance.value.beans >= totalBeansPrice
+ return hasEnoughPoints && hasEnoughBeans
default:
return true
}
@@ -453,6 +456,12 @@ const fetchPaymentData = async () => {
try {
loading.value = true
+ // 从路由参数获取订单ID
+ const orderId = route.params.orderId
+ if (!orderId) {
+ throw new Error('订单ID不存在')
+ }
+
// 先获取用户余额信息
await fetchUserBalance()
@@ -460,84 +469,74 @@ const fetchPaymentData = async () => {
await getAddressList()
// 从后端获取当前用户的待支付订单信息
- const response = await api.get('/order/pending-payment')
+ const response = await api.get(`/orders/pending-payment/${orderId}`)
if (response.data.success) {
const data = response.data.data
+ const items = (data.items || []).map(item => ({
+ id: item.id,
+ productId: item.product_id,
+ name: item.product_name,
+ image: item.image_url,
+ points: item.points_price,
+ price: item.price,
+ rongdouPrice: item.rongdou_price,
+ quantity: item.quantity,
+ description: item.description,
+ specInfo: item.spec_info
+ }))
+
+ // 计算总积分价格和总融豆价格
+ const totalPointsPrice = items.reduce((sum, item) => sum + (item.points * item.quantity), 0)
+ const totalBeansPrice = items.reduce((sum, item) => sum + (item.rongdouPrice * item.quantity), 0)
+
paymentData.value = {
- totalAmount: data.totalAmount || 0,
- pointsAmount: data.pointsAmount || 0,
- beansAmount: data.beansAmount || 0,
- orderId: data.orderId || null,
- items: data.items || []
+ totalAmount: 0, // 初始不设置总金额,等用户选择支付方式后再设置
+ pointsAmount: totalPointsPrice, // 积分金额
+ beansAmount: totalBeansPrice, // 融豆金额
+ orderId: data.id || null, // 订单ID
+ orderNo: data.order_no || '', // 订单号
+ items: items
+ }
+
+ // 根据价格自动选择支付方式
+ if (totalPointsPrice === 0 && totalBeansPrice > 0) {
+ await selectPaymentMethod('beans')
+ } else if (totalBeansPrice === 0 && totalPointsPrice > 0) {
+ await selectPaymentMethod('points')
+ } else if (totalPointsPrice > 0 && totalBeansPrice > 0) {
+ await selectPaymentMethod('mixed')
}
} else {
throw new Error(response.data.message || '获取订单信息失败')
}
} catch (error) {
ElMessage.error(error.message || '获取订单信息失败')
- router.go(-1)
} finally {
loading.value = false
}
}
const handleGoBack = async () => {
- // 如果倒计时还在进行中,显示确认弹窗
- if (timeLeft.value > 0) {
- try {
- await ElMessageBox.confirm(
- '确认要放弃付款吗?',
- '提示',
- {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning'
- }
- )
-
- // 用户确认放弃付款,先保存订单数据到后端,然后跳转到PayFailed页面
- try {
- if (paymentData.value.orderId) {
- // 将当前支付数据保存为失败订单
- await api.post('/order/save-failed', {
- orderId: paymentData.value.orderId,
- orderData: {
- orderNumber: 'ORD' + Date.now(),
- createTime: new Date().toISOString(),
- totalAmount: paymentData.value.totalAmount,
- subtotal: paymentData.value.totalAmount - 10, // 假设运费为10元
- shippingFee: 10,
- cartItems: paymentData.value.items,
- status: 'failed'
- }
- })
- }
- } catch (error) {
- console.error('保存失败订单数据失败:', error)
+ try {
+ await ElMessageBox.confirm(
+ '确认要取消订单吗?取消后将无法恢复。',
+ '取消订单',
+ {
+ confirmButtonText: '确认取消',
+ cancelButtonText: '继续支付',
+ type: 'warning'
}
-
- // 跳转到PayFailed页面,传递orderId参数
- if (paymentData.value.orderId) {
- router.push(`/payfailed?orderId=${paymentData.value.orderId}`)
- } else {
- router.push(`/payfailed`)
- }
- } catch {
- // 用户取消,什么都不做,留在当前页面
- }
- } else {
- // 倒计时已结束,直接返回
+ )
+
+ // 用户确认取消订单
router.go(-1)
+ } catch {
+ // 用户取消,什么都不做,留在当前页面
}
}
const confirmPayment = async () => {
- if (timeLeft.value <= 0) {
- ElMessage.error('支付超时,请重新下单')
- return
- }
-
if (!selectedPaymentMethod.value) {
ElMessage.error('请选择支付方式')
return
@@ -549,8 +548,21 @@ const confirmPayment = async () => {
}
try {
+ // 根据商品价格显示确认信息
+ let confirmMessage = ''
+ const totalPoints = paymentData.value.pointsAmount
+ const totalRongdou = paymentData.value.beansAmount
+
+ if (totalPoints > 0 && totalRongdou > 0) {
+ confirmMessage = `确认支付 ${totalPoints} 积分 + ${totalRongdou} 融豆?`
+ } else if (totalPoints === 0 && totalRongdou > 0) {
+ confirmMessage = `确认支付 ${totalRongdou} 融豆?`
+ } else if (totalRongdou === 0 && totalPoints > 0) {
+ confirmMessage = `确认支付 ${totalPoints} 积分?`
+ }
+
await ElMessageBox.confirm(
- `确定要支付 ¥${paymentData.value.totalAmount} 吗?`,
+ confirmMessage,
'确认支付',
{
confirmButtonText: '确定支付',
@@ -563,22 +575,13 @@ const confirmPayment = async () => {
// 创建订单数据
const orderData = {
- items: paymentData.value.items,
- paymentMethod: selectedPaymentMethod.value,
- totalAmount: paymentData.value.totalAmount,
+ orderId: paymentData.value.orderId,
addressId: selectedAddress.value.id,
- address: {
- recipientName: selectedAddress.value.recipientName,
- recipientPhone: selectedAddress.value.recipientPhone,
- province: selectedAddress.value.province,
- city: selectedAddress.value.city,
- district: selectedAddress.value.district,
- detailAddress: selectedAddress.value.detailAddress
- }
+ paymentMethod: selectedPaymentMethod.value
}
- // 向后端发送创建订单请求
- const response = await api.post('/orders/create', orderData)
+ // 向后端发送订单支付请求
+ const response = await api.post('/orders/confirm-payment', orderData)
if (response.data.success) {
ElMessage.success('订单创建成功!')
@@ -587,7 +590,7 @@ const confirmPayment = async () => {
router.push({
path: '/payloading',
query: {
- orderId: response.data.data.orderId
+ orderId: paymentData.value.orderId
}
})
} else {
@@ -1063,78 +1066,7 @@ onMounted(() => {
margin-top: 16px;
}
-.order-items-section .item-card {
- display: flex;
- align-items: center;
- padding: 16px 0;
- border-bottom: 1px solid #f0f0f0;
-}
-.order-items-section .item-card:last-child {
- border-bottom: none;
-}
-
-.order-items-section .item-image {
- width: 80px;
- height: 80px;
- margin-right: 16px;
- border-radius: 8px;
- overflow: hidden;
-}
-
-.order-items-section .item-image img {
- width: 100%;
- height: 100%;
- object-fit: cover;
-}
-
-.order-items-section .item-info {
- flex: 1;
- margin-right: 16px;
-}
-
-.order-items-section .item-name {
- font-size: 16px;
- font-weight: 500;
- color: #333;
- margin-bottom: 8px;
- line-height: 1.4;
-}
-
-.item-specs {
- font-size: 14px;
- color: #666;
- margin-bottom: 8px;
-}
-
-.item-price-quantity {
- display: flex;
- align-items: center;
- gap: 16px;
-}
-
-.item-price-quantity .price {
- color: #409eff;
- font-weight: 500;
-}
-
-.item-price-quantity .quantity {
- color: #666;
- font-size: 14px;
-}
-
-.order-items-section .item-total {
- font-size: 16px;
- font-weight: 500;
- color: #409eff;
- text-align: right;
-}
-
-.order-items-section .no-items {
- text-align: center;
- padding: 40px 20px;
- color: #999;
-}
.payment-icon {
color: #ffae00;
diff --git a/src/views/PayLoading.vue b/src/views/PayLoading.vue
index a692702..872b70c 100644
--- a/src/views/PayLoading.vue
+++ b/src/views/PayLoading.vue
@@ -62,10 +62,14 @@
{{ item.name }}
{{ item.specification || '默认规格' }}
-
¥{{ item.price }} × {{ item.quantity }}
+
+
+ {{ item.price }} × {{ item.quantity }}
+
- ¥{{ (item.price * item.quantity).toFixed(2) }}
+
+ {{ (item.price * item.quantity) }}