From 5e8ff94b7aeac32d9548e83cf9787dc3065a1217 Mon Sep 17 00:00:00 2001 From: sexygoat <1538832180@qq.com> Date: Tue, 14 Apr 2026 12:12:57 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=AF=E4=BB=98/=E9=92=B1=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/FunctionCard.vue | 4 +- pages/my-wallet/my-wallet.vue | 307 +++++++++++++++++++++++++++++++++- 2 files changed, 306 insertions(+), 5 deletions(-) diff --git a/components/FunctionCard.vue b/components/FunctionCard.vue index 2ae53c8..7ec88c4 100644 --- a/components/FunctionCard.vue +++ b/components/FunctionCard.vue @@ -53,7 +53,7 @@ {{ alreadyBindPhone ? '已绑定' : '绑定手机号' }} - + 更换手机号 @@ -65,7 +65,7 @@ 设备换货 - + 我的钱包 diff --git a/pages/my-wallet/my-wallet.vue b/pages/my-wallet/my-wallet.vue index 66434fb..c8bf976 100644 --- a/pages/my-wallet/my-wallet.vue +++ b/pages/my-wallet/my-wallet.vue @@ -2,7 +2,10 @@ - 账户余额(元) + + 账户余额(元) + + {{ formatMoney(walletDetail.balance) }} @@ -13,11 +16,55 @@ 更新时间 - {{ walletDetail.updated_at }} + {{ formatDateTime(walletDetail.updated_at) }} + + + + + 账户充值 + × + + + + + ¥{{ item.label }} + + + 自定义 + + + + + 请输入充值金额(元) + + + + + + + + + + @@ -142,6 +189,17 @@ return (amount / 100).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ','); }; + const formatDateTime = (dateStr) => { + if (!dateStr) return '-'; + const date = new Date(dateStr); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hour = String(date.getHours()).padStart(2, '0'); + const minute = String(date.getMinutes()).padStart(2, '0'); + return `${year}-${month}-${day} ${hour}:${minute}`; + }; + let walletDetail = reactive({ balance: 0, frozen_balance: 0, @@ -160,6 +218,129 @@ let transactionPage = ref(1); const transactionPageSize = 5; + let showRechargeModal = ref(false); + let selectedAmount = ref(null); + let isCustomAmount = ref(false); + let customAmount = ref(''); + const rechargeAmounts = [ + { value: 1000, label: '10' }, + { value: 2000, label: '20' }, + { value: 5000, label: '50' }, + { value: 10000, label: '100' }, + { value: 20000, label: '200' }, + { value: 50000, label: '500' } + ]; + + const selectAmount = (value) => { + selectedAmount.value = value; + isCustomAmount.value = false; + customAmount.value = ''; + }; + + const selectCustomAmount = () => { + isCustomAmount.value = true; + selectedAmount.value = null; + }; + + const confirmRecharge = async () => { + let amount = 0; + + if (isCustomAmount.value) { + // 自定义金额 + const customAmountNum = parseFloat(customAmount.value); + if (!customAmountNum || customAmountNum < 0.01) { + uni.showToast({ title: '请输入正确的充值金额', icon: 'none' }); + return; + } + amount = Math.round(customAmountNum * 100); // 转换为分 + } else if (selectedAmount.value) { + // 预设金额 + amount = selectedAmount.value; + } else { + uni.showToast({ title: '请选择充值金额', icon: 'none' }); + return; + } + + uni.showLoading({ title: '处理中...', mask: true }); + + try { + // 第一步:充值前校验 + const checkData = await walletApi.rechargeCheck(userStore.state.identifier); + + // 如果需要强制充值且金额小于强制充值金额 + if (checkData.need_force_recharge && amount < checkData.force_recharge_amount) { + uni.hideLoading(); + uni.showModal({ + title: '提示', + content: `${checkData.message || '当前需充值最低金额'} ¥${(checkData.force_recharge_amount / 100).toFixed(2)}`, + showCancel: false + }); + return; + } + + // 检查金额范围 + if (amount < checkData.min_amount || amount > checkData.max_amount) { + uni.hideLoading(); + uni.showToast({ + title: `充值金额范围:¥${(checkData.min_amount / 100).toFixed(2)} - ¥${(checkData.max_amount / 100).toFixed(2)}`, + icon: 'none', + duration: 2500 + }); + return; + } + + // 第二步:创建充值订单 + const rechargeData = await walletApi.recharge( + userStore.state.identifier, + amount, + 'wechat' + ); + + uni.hideLoading(); + showRechargeModal.value = false; + + // 验证支付配置 + if (!rechargeData.pay_config || !rechargeData.pay_config.package) { + uni.showToast({ title: '支付参数获取失败', icon: 'none' }); + return; + } + + // 第三步:调起微信支付 + uni.requestPayment({ + timeStamp: rechargeData.pay_config.timestamp, + nonceStr: rechargeData.pay_config.nonce_str, + package: rechargeData.pay_config.package, + signType: rechargeData.pay_config.sign_type, + paySign: rechargeData.pay_config.pay_sign, + success: (res) => { + console.log('支付成功', res); + uni.showToast({ title: '充值成功', icon: 'success' }); + setTimeout(() => { + // 刷新钱包余额和充值记录 + loadWalletDetail(); + rechargePage.value = 1; + rechargeNoMore.value = false; + loadRechargeList(); + }, 1500); + }, + fail: (err) => { + console.error('支付失败', err); + if (err.errMsg && (err.errMsg.includes('cancel') || err.errMsg.includes('用户取消'))) { + uni.showToast({ title: '已取消支付', icon: 'none' }); + } else { + uni.showToast({ title: '支付失败', icon: 'none' }); + } + } + }); + + } catch (e) { + uni.hideLoading(); + console.error('充值失败', e); + const errorMsg = e.msg || e.message || '充值失败,请稍后重试'; + uni.showToast({ title: errorMsg, icon: 'none' }); + } + }; + const getRechargeStatusClass = (status) => { const classMap = { '0': 'tag-warning', @@ -284,7 +465,23 @@ .balance-section { margin-bottom: 28rpx; - .balance-label { font-size: 24rpx; opacity: 0.75; margin-bottom: 8rpx; } + .balance-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8rpx; + .balance-label { font-size: 24rpx; opacity: 0.75; } + .btn-recharge { + background: rgba(255, 255, 255, 0.25); + border: 1rpx solid rgba(255, 255, 255, 0.5); + color: #fff; + font-size: 24rpx; + padding: 8rpx 24rpx; + border-radius: 40rpx; + font-weight: 500; + &::after { border: none; } + } + } .balance-amount { font-size: 72rpx; font-weight: 700; letter-spacing: -2rpx; } } @@ -394,4 +591,108 @@ color: var(--text-tertiary); font-size: 24rpx; } + + .recharge-popup { + width: 600rpx; + background: var(--bg-primary); + border-radius: var(--radius-large); + overflow: hidden; + + .popup-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 30rpx; + border-bottom: 1rpx solid var(--border-light); + + .popup-title { + font-size: 32rpx; + font-weight: 600; + color: var(--text-primary); + } + + .popup-close { + width: 48rpx; + height: 48rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 40rpx; + color: var(--text-tertiary); + cursor: pointer; + } + } + + .recharge-amounts { + padding: 30rpx; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20rpx; + + .amount-item { + height: 88rpx; + display: flex; + align-items: center; + justify-content: center; + border: 2rpx solid var(--border-light); + border-radius: var(--radius-medium); + cursor: pointer; + transition: all 0.3s; + + &.active { + border-color: var(--primary); + background: rgba(0, 122, 255, 0.05); + + .amount-value { + color: var(--primary); + font-weight: 600; + } + } + + .amount-value { + font-size: 28rpx; + color: var(--text-primary); + } + } + } + + .custom-input { + padding: 0 30rpx 30rpx; + + .input-label { + font-size: 26rpx; + color: var(--text-secondary); + margin-bottom: 16rpx; + } + } + + .popup-footer { + display: flex; + gap: 20rpx; + padding: 30rpx; + border-top: 1rpx solid var(--border-light); + + .btn-apple { + flex: 1; + height: 88rpx; + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-medium); + font-size: 28rpx; + font-weight: 500; + border: none; + + &.btn-secondary { + background: var(--gray-200); + color: var(--text-primary); + } + + &.btn-primary { + background: var(--primary); + color: #fff; + } + } + } + } \ No newline at end of file