From ed3116773e855f67c71c34acc696d7df58fa2fa9 Mon Sep 17 00:00:00 2001
From: dzl <786316265@qq.com>
Date: Mon, 1 Sep 2025 13:39:34 +0800
Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=9F=8E=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/MyProfile.vue | 91 +++++++++++++++++++++-
src/views/Orders.vue | 42 +++++-----
src/views/Pay.vue | 167 +++++++++++++++++++++++-----------------
3 files changed, 208 insertions(+), 92 deletions(-)
diff --git a/src/views/MyProfile.vue b/src/views/MyProfile.vue
index b2b7fbb..eb10e07 100644
--- a/src/views/MyProfile.vue
+++ b/src/views/MyProfile.vue
@@ -68,6 +68,15 @@
{{ Math.abs(accountInfo.balance) }}
+
+ 默认自动匹配
+
@@ -136,7 +145,7 @@ export default {
const avatarUrl = ref('');
const newAvatar = ref('');
const showAvatarUpload = ref(false);
- const accountInfo = ref({ balance: '0.00' });
+ const accountInfo = ref({ balance: '0.00', is_distribute: false });
const isLoading = ref(false);
const settings = ref([
{text:'账号安全',path:'/editpasswordpage'},
@@ -160,7 +169,12 @@ export default {
const response = await api.get(`/user/profile`);
console.log(response.data);
if (response.data.success) {
- accountInfo.value = response.data.user || { balance: '0.00' };
+ accountInfo.value = {
+ ...accountInfo.value,
+ ...response.data.user,
+ balance: response.data.user?.balance || '0.00',
+ is_distribute: response.data.user?.is_distribute || false
+ };
// 确保加载头像
if (response.data.user?.avatar) {
avatarUrl.value = response.data.data.avatar;
@@ -176,6 +190,44 @@ export default {
}
};
+ // 处理默认自动匹配状态变化
+ const handleDistributeChange = async (value) => {
+ try {
+ const action = value ? '开启' : '关闭';
+ await ElMessageBox.confirm(
+ `确定要${action}默认自动匹配功能吗?`,
+ '确认操作',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning'
+ }
+ );
+
+ const response = await api.put(`/user/${userStore.user.id}/distribute`, {
+ is_distribute: value
+ });
+
+ if (response.data.success) {
+ ElMessage.success('默认自动匹配状态更新成功');
+ } else {
+ // 如果更新失败,恢复原状态
+ accountInfo.value.is_distribute = !value;
+ ElMessage.error(response.data.message || '默认自动匹配状态更新失败');
+ }
+ } catch (error) {
+ if (error === 'cancel') {
+ // 用户取消操作,恢复原状态
+ accountInfo.value.is_distribute = !value;
+ } else {
+ console.error('更新默认自动匹配状态失败:', error);
+ // 如果请求失败,恢复原状态
+ accountInfo.value.is_distribute = !value;
+ ElMessage.error('默认自动匹配状态更新失败');
+ }
+ }
+ };
+
// 头像上传前的验证
const beforeAvatarUpload = (file) => {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
@@ -290,6 +342,7 @@ export default {
uploadAvatar,
confirmAvatarUpload,
handleLogout,
+ handleDistributeChange,
userStore
};
}
@@ -486,6 +539,7 @@ export default {
display: flex;
flex-direction: column;
gap: 8px;
+ flex: 1;
}
.balance-label {
@@ -495,6 +549,39 @@ export default {
font-weight: 400;
}
+.distribute-checkbox {
+ color: white;
+}
+
+.distribute-checkbox :deep(.el-checkbox__label) {
+ color: rgba(255, 255, 255, 0.9);
+ font-size: 12px;
+}
+
+.distribute-checkbox :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
+ background-color: rgba(255, 255, 255, 0.9) !important;
+ border-color: rgba(255, 255, 255, 0.9) !important;
+}
+
+.distribute-checkbox :deep(.el-checkbox__input.is-checked .el-checkbox__inner::after) {
+ border-color: #2f89ff !important;
+}
+
+.distribute-checkbox :deep(.el-checkbox__inner) {
+ border-color: rgba(255, 255, 255, 0.6) !important;
+ background-color: transparent !important;
+}
+
+.distribute-checkbox :deep(.el-checkbox__input.is-checked) {
+ .el-checkbox__inner {
+ background-color: rgba(255, 255, 255, 0.9) !important;
+ border-color: rgba(255, 255, 255, 0.9) !important;
+ }
+ .el-checkbox__inner::after {
+ border-color: #2f89ff !important;
+ }
+}
+
.balance-value {
font-size: 28px;
font-weight: 600;
diff --git a/src/views/Orders.vue b/src/views/Orders.vue
index 1acc35a..320e4ed 100644
--- a/src/views/Orders.vue
+++ b/src/views/Orders.vue
@@ -47,7 +47,7 @@
-
+
x{{ item.quantity }}
@@ -100,10 +95,6 @@
{{ order.totalPoints }}
-
+
-
-
{{ order.totalRongdou }}
-
@@ -111,6 +102,14 @@
+
+ 立即支付
+
{{ item.points }}
-
+
-
{{ item.rongdouPrice }}
x {{ item.quantity }}
@@ -279,8 +276,6 @@
{{ orderDetail.totalPoints }}
- +
-
{{ orderDetail.totalRongdou }}
@@ -289,8 +284,6 @@
{{ orderDetail.totalPoints }}
- +
-
{{ orderDetail.totalRongdou }}
@@ -333,7 +326,7 @@ const submittingReview = ref(false)
// 状态标签
const statusTabs = ref([
{ label: '全部', value: 'all', count: 0 },
- { label: '待发货', value: 'pending', count: 0 },
+ { label: '待支付', value: 'pending', count: 0 },
{ label: '已发货', value: 'shipped', count: 0 },
{ label: '已完成', value: 'completed', count: 0 },
{ label: '已取消', value: 'cancelled', count: 0 }
@@ -355,7 +348,7 @@ const selectStatus = (status) => {
const getEmptyText = () => {
const textMap = {
all: '暂无订单',
- pending: '暂无待发货订单',
+ pending: '暂无待支付订单',
shipped: '暂无已发货订单',
completed: '暂无已完成订单',
cancelled: '暂无已取消订单'
@@ -386,7 +379,7 @@ const mapOrderStatus = (backendStatus) => {
const getStatusText = (status) => {
const textMap = {
- pending: '待发货',
+ pending: '待支付',
shipped: '已发货',
completed: '已完成',
cancelled: '已取消'
@@ -411,6 +404,10 @@ const goToProduct = (productId) => {
router.push(`/product/${productId}`)
}
+const goToPay = (orderId) => {
+ router.push(`/pay/${orderId}`)
+}
+
const cancelOrder = async (orderId) => {
try {
await ElMessageBox.confirm('确定要取消这个订单吗?', '确认取消', {
@@ -720,7 +717,12 @@ onMounted(() => {
.orders-list {
display: flex;
flex-direction: column;
- gap: 16px;
+}
+
+.orders-container {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
}
.order-card {
diff --git a/src/views/Pay.vue b/src/views/Pay.vue
index ec15865..f22c1ec 100644
--- a/src/views/Pay.vue
+++ b/src/views/Pay.vue
@@ -69,8 +69,8 @@
支付
-
-
+
+
-
+
{{ paymentData.beansAmount }}
-
+
{{ paymentData.pointsAmount }}
+
+
+ 请选择支付方式
+
-
+
积分:{{ paymentData.pointsAmount }}
@@ -142,9 +146,9 @@
支付方式
-
+
-
+
0 && paymentData.beansAmount > 0"
+ v-if="shouldShowPaymentMethod('mixed')"
class="payment-option"
:class="{
active: selectedPaymentMethod === 'mixed',
@@ -217,8 +221,8 @@
实付:
-
-
+
+
-
+
{{ paymentData.beansAmount }}
-
+
{{ paymentData.pointsAmount }}
+
+
+ -
+
{
- 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
- }
+ // 仅基于商品的points_price价值总和计算支付总额
+ const totalPointsPrice = paymentData.value.items.reduce((sum, item) => sum + (item.points_price * item.quantity), 0)
+ const EXCHANGE_RATE = 10000 // 1融豆 = 10000积分
// 检查支付方式是否可用
if (!isPaymentMethodAvailable(method)) {
let message = ''
if (method === 'beans') {
- if (totalBeansPrice === 0) {
- message = '该订单不支持融豆支付'
- } else {
- message = `融豆余额不足,当前余额:${userBalance.value.beans},需要:${totalBeansPrice}`
- }
+ const requiredBeans = Math.ceil(totalPointsPrice / EXCHANGE_RATE)
+ message = `融豆余额不足,当前余额:${userBalance.value.beans},需要:${requiredBeans}`
} else if (method === 'points') {
- if (totalPointsPrice === 0) {
- message = '该订单不支持积分支付'
- } else {
- message = `积分余额不足,当前余额:${userBalance.value.points},需要:${totalPointsPrice}`
- }
+ message = `积分余额不足,当前余额:${userBalance.value.points},需要:${totalPointsPrice}`
} else if (method === 'mixed') {
- if (totalPointsPrice === 0 && totalBeansPrice === 0) {
- message = '该订单不支持混合支付'
- } else {
- message = `余额不足,当前余额:融豆${userBalance.value.beans},积分${userBalance.value.points},需要:融豆${totalBeansPrice},积分${totalPointsPrice}`
- }
+ message = `余额不足,无法完成支付`
}
ElMessage.warning(message)
return
@@ -346,17 +330,27 @@ const selectPaymentMethod = async (method) => {
// 根据选择的支付方式更新显示的金额
if (method === 'beans') {
- paymentData.value.totalAmount = totalBeansPrice
+ // 融豆支付:按积分/10000计算所需融豆
+ const requiredBeans = Math.ceil(totalPointsPrice / EXCHANGE_RATE)
+ paymentData.value.totalAmount = totalPointsPrice
paymentData.value.pointsAmount = 0
- paymentData.value.beansAmount = totalBeansPrice
+ paymentData.value.beansAmount = requiredBeans
} 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
+ // 积分+融豆支付:积分必须是10000的倍数,按(总积分-当前积分)/10000计算所需融豆
+ let availablePoints = Math.min(userBalance.value.points, totalPointsPrice)
+ // 确保积分是10000的倍数
+ availablePoints = Math.floor(availablePoints / 10000) * 10000
+ const remainingPoints = totalPointsPrice - availablePoints
+ const requiredBeans = Math.ceil(remainingPoints / EXCHANGE_RATE)
+
+ paymentData.value.totalAmount = totalPointsPrice
+ paymentData.value.pointsAmount = availablePoints
+ paymentData.value.beansAmount = requiredBeans
}
}
@@ -427,31 +421,56 @@ const fetchUserBalance = async () => {
// 检查支付方式是否可用
const isPaymentMethodAvailable = (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)
+ // 仅基于商品的points_price价值总和计算
+ const totalPointsPrice = paymentData.value.items.reduce((sum, item) => sum + (item.points_price * item.quantity), 0)
+ const EXCHANGE_RATE = 10000 // 1融豆 = 10000积分
switch (method) {
case 'beans':
- // 如果所有商品的融豆价格总和为0,则不能选择融豆支付
- if (totalBeansPrice === 0) return false
- return userBalance.value.beans >= totalBeansPrice
+ // 融豆支付:检查总积分是否大于等于10000且融豆是否足够支付总积分价值
+ if (totalPointsPrice < 10000) {
+ return false
+ }
+ const requiredBeans = Math.ceil(totalPointsPrice / EXCHANGE_RATE)
+ return userBalance.value.beans >= requiredBeans
case 'points':
- // 如果所有商品的积分价格总和为0,则不能选择积分支付
- if (totalPointsPrice === 0) return false
+ // 积分支付:检查积分是否足够
return userBalance.value.points >= totalPointsPrice
case 'mixed':
- // 如果积分价格和融豆价格都为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
+ // 混合支付:检查积分+融豆换算后是否足够
+ const totalUserBalanceInPoints = userBalance.value.points + (userBalance.value.beans * EXCHANGE_RATE)
+ return totalUserBalanceInPoints >= totalPointsPrice
default:
return true
}
}
+// 检查支付方式是否应该显示
+const shouldShowPaymentMethod = (method) => {
+ // 仅基于商品的points_price价值总和计算
+ const totalPointsPrice = paymentData.value.items.reduce((sum, item) => sum + (item.points_price * item.quantity), 0)
+ const EXCHANGE_RATE = 10000 // 1融豆 = 10000积分
+
+ switch (method) {
+ case 'beans':
+ // 当总积分大于等于10000且用户融豆足够支付总积分价值时显示融豆支付选项
+ if (totalPointsPrice < 10000) {
+ return false
+ }
+ const requiredBeans = Math.ceil(totalPointsPrice / EXCHANGE_RATE)
+ return totalPointsPrice > 0 && userBalance.value.beans >= requiredBeans
+ case 'points':
+ // 当用户积分足够支付时显示积分支付选项
+ return totalPointsPrice > 0 && userBalance.value.points >= totalPointsPrice
+ case 'mixed':
+ // 当用户积分不够但积分+融豆换算足够时显示混合支付选项
+ const pointsNotEnough = totalPointsPrice > 0 && userBalance.value.points < totalPointsPrice
+ return pointsNotEnough && isPaymentMethodAvailable('mixed')
+ default:
+ return false
+ }
+}
+
const fetchPaymentData = async () => {
try {
loading.value = true
@@ -479,6 +498,7 @@ const fetchPaymentData = async () => {
name: item.product_name,
image: item.image_url,
points: item.points_price,
+ points_price: item.points_price, // 添加points_price字段
price: item.price,
rongdouPrice: item.rongdou_price,
quantity: item.quantity,
@@ -499,14 +519,15 @@ const fetchPaymentData = async () => {
items: items
}
- // 根据价格自动选择支付方式
- if (totalPointsPrice === 0 && totalBeansPrice > 0) {
+ // 根据用户余额自动选择支付方式
+ if (shouldShowPaymentMethod('beans')) {
await selectPaymentMethod('beans')
- } else if (totalBeansPrice === 0 && totalPointsPrice > 0) {
+ } else if (shouldShowPaymentMethod('points')) {
await selectPaymentMethod('points')
- } else if (totalPointsPrice > 0 && totalBeansPrice > 0) {
+ } else if (shouldShowPaymentMethod('mixed')) {
await selectPaymentMethod('mixed')
}
+ // 如果没有可用的支付方式,不自动选择,让用户看到所有选项都不可用
} else {
throw new Error(response.data.message || '获取订单信息失败')
}
@@ -520,7 +541,7 @@ const fetchPaymentData = async () => {
const handleGoBack = async () => {
try {
await ElMessageBox.confirm(
- '确认要取消订单吗?取消后将无法恢复。',
+ '确认要取消订单吗?取消后可以在个人中心-我的订单里查看。',
'取消订单',
{
confirmButtonText: '确认取消',
@@ -577,13 +598,17 @@ const confirmPayment = async () => {
const orderData = {
orderId: paymentData.value.orderId,
addressId: selectedAddress.value.id,
- paymentMethod: selectedPaymentMethod.value
+ paymentMethod: selectedPaymentMethod.value,
+ pointsAmount: paymentData.value.pointsAmount,
+ beansAmount: paymentData.value.beansAmount
}
// 向后端发送订单支付请求
const response = await api.post('/orders/confirm-payment', orderData)
+ console.log(orderData)
if (response.data.success) {
+ console.log(orderData)
ElMessage.success('订单创建成功!')
// 跳转到PayLoading页面,传递订单ID
@@ -594,9 +619,11 @@ const confirmPayment = async () => {
}
})
} else {
+ console.log(orderData)
throw new Error(response.data.message || '创建订单失败')
}
} catch (error) {
+ console.log(orderData)
if (error !== 'cancel') {
ElMessage.error(error.message || '创建订单失败,请重试')
}