|
|
|
@ -0,0 +1,699 @@
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
|
|
<view class="container">
|
|
|
|
|
|
|
|
<!-- 顶部余额显示 -->
|
|
|
|
|
|
|
|
<view class="balance-section">
|
|
|
|
|
|
|
|
<view class="balance-card">
|
|
|
|
|
|
|
|
<view class="balance-info">
|
|
|
|
|
|
|
|
<view class="balance-label">当前余额</view>
|
|
|
|
|
|
|
|
<view class="balance-amount">¥{{ currentBalance }}</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<view class="balance-icon">
|
|
|
|
|
|
|
|
<uv-icon name="empty-coupon" color="#4285f4" size="40"></uv-icon>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 充值金额选择 -->
|
|
|
|
|
|
|
|
<view class="recharge-section">
|
|
|
|
|
|
|
|
<view class="section-title">选择充值金额</view>
|
|
|
|
|
|
|
|
<view class="amount-grid">
|
|
|
|
|
|
|
|
<view
|
|
|
|
|
|
|
|
class="amount-item"
|
|
|
|
|
|
|
|
:class="{ active: selectedAmount === item.value }"
|
|
|
|
|
|
|
|
v-for="item in rechargeAmounts"
|
|
|
|
|
|
|
|
:key="item.value"
|
|
|
|
|
|
|
|
@click="selectAmount(item.value)"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<view class="amount-value">¥{{ item.value }}</view>
|
|
|
|
|
|
|
|
<view v-if="item.bonus" class="amount-bonus">送{{ item.bonus }}元</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 自定义金额 -->
|
|
|
|
|
|
|
|
<view class="custom-amount">
|
|
|
|
|
|
|
|
<view class="custom-label">自定义金额</view>
|
|
|
|
|
|
|
|
<view class="custom-input">
|
|
|
|
|
|
|
|
<text class="currency">¥</text>
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
|
|
|
class="amount-input"
|
|
|
|
|
|
|
|
v-model="customAmount"
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
placeholder="请输入充值金额"
|
|
|
|
|
|
|
|
@input="onCustomAmountInput"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<view class="amount-tips">充值金额范围:¥1 - ¥50000</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 支付方式 -->
|
|
|
|
|
|
|
|
<view class="payment-section">
|
|
|
|
|
|
|
|
<view class="section-title">选择支付方式</view>
|
|
|
|
|
|
|
|
<view class="payment-list">
|
|
|
|
|
|
|
|
<!-- 微信支付 -->
|
|
|
|
|
|
|
|
<view
|
|
|
|
|
|
|
|
class="payment-item"
|
|
|
|
|
|
|
|
:class="{ active: selectedPayment === 'wechat' }"
|
|
|
|
|
|
|
|
@click="selectPayment('wechat')"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<view class="payment-info">
|
|
|
|
|
|
|
|
<uv-icon name="weixin-fill" color="#07c160" size="28"></uv-icon>
|
|
|
|
|
|
|
|
<view class="payment-details">
|
|
|
|
|
|
|
|
<view class="payment-name">微信支付</view>
|
|
|
|
|
|
|
|
<view class="payment-desc">安全快捷,支持零钱和银行卡</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<uv-icon
|
|
|
|
|
|
|
|
name="checkmark-circle-fill"
|
|
|
|
|
|
|
|
:color="selectedPayment === 'wechat' ? '#4285f4' : '#ccc'"
|
|
|
|
|
|
|
|
size="20"
|
|
|
|
|
|
|
|
></uv-icon>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 支付宝支付 - 仅H5显示 -->
|
|
|
|
|
|
|
|
<view
|
|
|
|
|
|
|
|
v-if="showAlipay"
|
|
|
|
|
|
|
|
class="payment-item"
|
|
|
|
|
|
|
|
:class="{ active: selectedPayment === 'alipay' }"
|
|
|
|
|
|
|
|
@click="selectPayment('alipay')"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<view class="payment-info">
|
|
|
|
|
|
|
|
<uv-icon name="alipay-circle-fill" color="#1677ff" size="28"></uv-icon>
|
|
|
|
|
|
|
|
<view class="payment-details">
|
|
|
|
|
|
|
|
<view class="payment-name">支付宝</view>
|
|
|
|
|
|
|
|
<view class="payment-desc">便民生活,轻松支付</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<uv-icon
|
|
|
|
|
|
|
|
name="checkmark-circle-fill"
|
|
|
|
|
|
|
|
:color="selectedPayment === 'alipay' ? '#4285f4' : '#ccc'"
|
|
|
|
|
|
|
|
size="20"
|
|
|
|
|
|
|
|
></uv-icon>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 充值说明 -->
|
|
|
|
|
|
|
|
<view class="notice-section">
|
|
|
|
|
|
|
|
<view class="section-title">充值说明</view>
|
|
|
|
|
|
|
|
<view class="notice-list">
|
|
|
|
|
|
|
|
<view class="notice-item">
|
|
|
|
|
|
|
|
<uv-icon name="info-circle" color="#999" size="16"></uv-icon>
|
|
|
|
|
|
|
|
<text class="notice-text">充值金额将实时到账,可用于购买会员服务</text>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<view class="notice-item">
|
|
|
|
|
|
|
|
<uv-icon name="info-circle" color="#999" size="16"></uv-icon>
|
|
|
|
|
|
|
|
<text class="notice-text">充值金额不可提现,请根据需要合理充值</text>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<view class="notice-item">
|
|
|
|
|
|
|
|
<uv-icon name="info-circle" color="#999" size="16"></uv-icon>
|
|
|
|
|
|
|
|
<text class="notice-text">如有疑问,请联系客服处理</text>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部充值按钮 -->
|
|
|
|
|
|
|
|
<view class="bottom-section">
|
|
|
|
|
|
|
|
<view class="recharge-info">
|
|
|
|
|
|
|
|
<text class="recharge-text">充值金额:¥{{ finalAmount }}</text>
|
|
|
|
|
|
|
|
<text v-if="bonusAmount > 0" class="bonus-text">(含赠送¥{{ bonusAmount }})</text>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<uv-button
|
|
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
|
|
size="large"
|
|
|
|
|
|
|
|
@click="confirmRecharge"
|
|
|
|
|
|
|
|
:loading="recharging"
|
|
|
|
|
|
|
|
:disabled="finalAmount <= 0"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
立即充值
|
|
|
|
|
|
|
|
</uv-button>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
|
|
import { ref, computed, onMounted } from "vue";
|
|
|
|
|
|
|
|
import { onShow } from "@dcloudio/uni-app";
|
|
|
|
|
|
|
|
import { useAuthStore, useUserStore } from "@/store";
|
|
|
|
|
|
|
|
import RPC from "@/utils/request";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const authStore = useAuthStore();
|
|
|
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 响应式数据
|
|
|
|
|
|
|
|
const currentBalance = ref(50.00);
|
|
|
|
|
|
|
|
const selectedAmount = ref(0);
|
|
|
|
|
|
|
|
const customAmount = ref('');
|
|
|
|
|
|
|
|
const selectedPayment = ref('wechat');
|
|
|
|
|
|
|
|
const recharging = ref(false);
|
|
|
|
|
|
|
|
const showAlipay = ref(true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 充值金额选项
|
|
|
|
|
|
|
|
const rechargeAmounts = ref([
|
|
|
|
|
|
|
|
{ value: 10, bonus: 0 },
|
|
|
|
|
|
|
|
{ value: 50, bonus: 0 },
|
|
|
|
|
|
|
|
{ value: 100, bonus: 5 },
|
|
|
|
|
|
|
|
{ value: 200, bonus: 15 },
|
|
|
|
|
|
|
|
{ value: 500, bonus: 50 },
|
|
|
|
|
|
|
|
{ value: 1000, bonus: 120 }
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算最终充值金额
|
|
|
|
|
|
|
|
const finalAmount = computed(() => {
|
|
|
|
|
|
|
|
if (customAmount.value && parseFloat(customAmount.value) > 0) {
|
|
|
|
|
|
|
|
return parseFloat(customAmount.value);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return selectedAmount.value;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算赠送金额
|
|
|
|
|
|
|
|
const bonusAmount = computed(() => {
|
|
|
|
|
|
|
|
if (selectedAmount.value > 0) {
|
|
|
|
|
|
|
|
const selected = rechargeAmounts.value.find(item => item.value === selectedAmount.value);
|
|
|
|
|
|
|
|
return selected ? selected.bonus : 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 选择充值金额
|
|
|
|
|
|
|
|
const selectAmount = (amount) => {
|
|
|
|
|
|
|
|
selectedAmount.value = amount;
|
|
|
|
|
|
|
|
customAmount.value = '';
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 自定义金额输入
|
|
|
|
|
|
|
|
const onCustomAmountInput = () => {
|
|
|
|
|
|
|
|
selectedAmount.value = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 限制输入范围
|
|
|
|
|
|
|
|
const amount = parseFloat(customAmount.value);
|
|
|
|
|
|
|
|
if (amount > 50000) {
|
|
|
|
|
|
|
|
customAmount.value = '50000';
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: '充值金额不能超过50000元',
|
|
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 选择支付方式
|
|
|
|
|
|
|
|
const selectPayment = (payment) => {
|
|
|
|
|
|
|
|
selectedPayment.value = payment;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查环境
|
|
|
|
|
|
|
|
const checkEnvironment = () => {
|
|
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
|
|
|
// 微信小程序环境,隐藏支付宝选项
|
|
|
|
|
|
|
|
showAlipay.value = false;
|
|
|
|
|
|
|
|
selectedPayment.value = 'wechat';
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
|
|
// H5环境,显示所有支付选项
|
|
|
|
|
|
|
|
showAlipay.value = true;
|
|
|
|
|
|
|
|
// 如果在微信浏览器内,默认选择微信支付
|
|
|
|
|
|
|
|
const ua = navigator.userAgent.toLowerCase();
|
|
|
|
|
|
|
|
const isWechat = ua.indexOf('micromessenger') !== -1;
|
|
|
|
|
|
|
|
selectedPayment.value = isWechat ? 'wechat' : 'alipay';
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 微信支付
|
|
|
|
|
|
|
|
const wechatPay = async (orderInfo) => {
|
|
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
|
|
|
// 微信小程序支付
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const paymentResult = await uni.requestPayment({
|
|
|
|
|
|
|
|
provider: 'wxpay',
|
|
|
|
|
|
|
|
timeStamp: orderInfo.timeStamp,
|
|
|
|
|
|
|
|
nonceStr: orderInfo.nonceStr,
|
|
|
|
|
|
|
|
package: orderInfo.package,
|
|
|
|
|
|
|
|
signType: orderInfo.signType,
|
|
|
|
|
|
|
|
paySign: orderInfo.paySign
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('微信支付成功:', paymentResult);
|
|
|
|
|
|
|
|
return { success: true, data: paymentResult };
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error('微信支付失败:', error);
|
|
|
|
|
|
|
|
if (error.errMsg === 'requestPayment:fail cancel') {
|
|
|
|
|
|
|
|
throw new Error('用户取消支付');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error('微信支付失败');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
|
|
// H5微信支付
|
|
|
|
|
|
|
|
if (typeof WeixinJSBridge !== 'undefined') {
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
|
|
WeixinJSBridge.invoke('getBrandWCPayRequest', {
|
|
|
|
|
|
|
|
appId: orderInfo.appId,
|
|
|
|
|
|
|
|
timeStamp: orderInfo.timeStamp,
|
|
|
|
|
|
|
|
nonceStr: orderInfo.nonceStr,
|
|
|
|
|
|
|
|
package: orderInfo.package,
|
|
|
|
|
|
|
|
signType: orderInfo.signType,
|
|
|
|
|
|
|
|
paySign: orderInfo.paySign
|
|
|
|
|
|
|
|
}, (res) => {
|
|
|
|
|
|
|
|
if (res.err_msg === 'get_brand_wcpay_request:ok') {
|
|
|
|
|
|
|
|
resolve({ success: true, data: res });
|
|
|
|
|
|
|
|
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
|
|
|
|
|
|
|
|
reject(new Error('用户取消支付'));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
reject(new Error('微信支付失败'));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 不在微信环境,跳转到支付页面
|
|
|
|
|
|
|
|
const payUrl = orderInfo.mwebUrl;
|
|
|
|
|
|
|
|
window.location.href = payUrl;
|
|
|
|
|
|
|
|
return { success: true, redirect: true };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 支付宝支付(仅H5环境)
|
|
|
|
|
|
|
|
const alipayPay = async (orderInfo) => {
|
|
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
|
|
// H5支付宝支付
|
|
|
|
|
|
|
|
const payUrl = orderInfo.payUrl;
|
|
|
|
|
|
|
|
window.location.href = payUrl;
|
|
|
|
|
|
|
|
return { success: true, redirect: true };
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 确认充值
|
|
|
|
|
|
|
|
const confirmRecharge = async () => {
|
|
|
|
|
|
|
|
if (finalAmount.value <= 0) {
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: '请选择充值金额',
|
|
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (finalAmount.value < 1) {
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: '充值金额不能少于1元',
|
|
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!selectedPayment.value) {
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: '请选择支付方式',
|
|
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
recharging.value = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// 创建充值订单参数
|
|
|
|
|
|
|
|
const orderParams = {
|
|
|
|
|
|
|
|
type: 'recharge',
|
|
|
|
|
|
|
|
amount: finalAmount.value,
|
|
|
|
|
|
|
|
bonusAmount: bonusAmount.value,
|
|
|
|
|
|
|
|
paymentMethod: selectedPayment.value,
|
|
|
|
|
|
|
|
userId: userStore.userInfo?.id || 'mock_user_id',
|
|
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
|
|
|
platform: 'mp-weixin',
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
|
|
platform: 'h5',
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
|
|
|
title: '正在创建订单...'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 调用后端创建充值订单API
|
|
|
|
|
|
|
|
// const orderResult = await RPC.post('/api/recharge/create', orderParams);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 模拟创建订单返回的数据
|
|
|
|
|
|
|
|
const orderResult = {
|
|
|
|
|
|
|
|
orderId: 'RECHARGE_' + Date.now(),
|
|
|
|
|
|
|
|
amount: orderParams.amount,
|
|
|
|
|
|
|
|
// 微信支付参数
|
|
|
|
|
|
|
|
wechatPayInfo: {
|
|
|
|
|
|
|
|
appId: 'wx1234567890',
|
|
|
|
|
|
|
|
timeStamp: String(Date.now()),
|
|
|
|
|
|
|
|
nonceStr: 'random_string_' + Date.now(),
|
|
|
|
|
|
|
|
package: 'prepay_id=wx_prepay_id_123456',
|
|
|
|
|
|
|
|
signType: 'RSA',
|
|
|
|
|
|
|
|
paySign: 'mock_pay_sign_123456',
|
|
|
|
|
|
|
|
mwebUrl: 'https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx_prepay_id_123456'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
// 支付宝支付参数
|
|
|
|
|
|
|
|
alipayInfo: {
|
|
|
|
|
|
|
|
payUrl: 'https://openapi.alipay.com/gateway.do?mock_recharge_url'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 根据支付方式调用对应的支付方法
|
|
|
|
|
|
|
|
let paymentResult;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (selectedPayment.value === 'wechat') {
|
|
|
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
|
|
|
title: '正在跳转微信支付...'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
paymentResult = await wechatPay(orderResult.wechatPayInfo);
|
|
|
|
|
|
|
|
} else if (selectedPayment.value === 'alipay') {
|
|
|
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
|
|
|
title: '正在跳转支付宝...'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
paymentResult = await alipayPay(orderResult.alipayInfo);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 处理支付结果
|
|
|
|
|
|
|
|
if (paymentResult.success) {
|
|
|
|
|
|
|
|
if (paymentResult.redirect) {
|
|
|
|
|
|
|
|
// H5跳转支付
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: '正在跳转支付页面...',
|
|
|
|
|
|
|
|
icon: 'loading',
|
|
|
|
|
|
|
|
duration: 2000
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 支付成功
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: '充值成功',
|
|
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新余额
|
|
|
|
|
|
|
|
currentBalance.value += finalAmount.value + bonusAmount.value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 重置选择
|
|
|
|
|
|
|
|
selectedAmount.value = 0;
|
|
|
|
|
|
|
|
customAmount.value = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 延迟返回上一页
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
|
|
uni.navigateBack();
|
|
|
|
|
|
|
|
}, 1500);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
|
|
console.error('充值失败:', error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let errorMessage = '充值失败,请重试';
|
|
|
|
|
|
|
|
if (error.message === '用户取消支付') {
|
|
|
|
|
|
|
|
errorMessage = '支付已取消';
|
|
|
|
|
|
|
|
} else if (error.message) {
|
|
|
|
|
|
|
|
errorMessage = error.message;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: errorMessage,
|
|
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
recharging.value = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 处理支付回调
|
|
|
|
|
|
|
|
const handlePaymentCallback = () => {
|
|
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
|
|
|
|
|
|
const orderId = urlParams.get('orderId');
|
|
|
|
|
|
|
|
const payResult = urlParams.get('payResult');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (orderId && payResult) {
|
|
|
|
|
|
|
|
// 清理URL参数
|
|
|
|
|
|
|
|
const url = new URL(window.location);
|
|
|
|
|
|
|
|
url.searchParams.delete('orderId');
|
|
|
|
|
|
|
|
url.searchParams.delete('payResult');
|
|
|
|
|
|
|
|
window.history.replaceState({}, document.title, url.pathname + url.search);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查支付结果
|
|
|
|
|
|
|
|
if (payResult === 'success') {
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: '充值成功',
|
|
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 刷新余额
|
|
|
|
|
|
|
|
loadUserBalance();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 重置选择
|
|
|
|
|
|
|
|
selectedAmount.value = 0;
|
|
|
|
|
|
|
|
customAmount.value = '';
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
|
|
title: '充值失败或取消',
|
|
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 加载用户余额
|
|
|
|
|
|
|
|
const loadUserBalance = async () => {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// 调用获取用户余额API
|
|
|
|
|
|
|
|
// const result = await RPC.get('/api/user/balance');
|
|
|
|
|
|
|
|
// currentBalance.value = result.data.balance;
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error('加载余额失败:', error);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
|
|
checkEnvironment();
|
|
|
|
|
|
|
|
loadUserBalance();
|
|
|
|
|
|
|
|
handlePaymentCallback();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onShow(() => {
|
|
|
|
|
|
|
|
handlePaymentCallback();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
|
|
.container {
|
|
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
|
|
background-color: #f8f8f8;
|
|
|
|
|
|
|
|
padding-bottom: 120px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.balance-section {
|
|
|
|
|
|
|
|
padding: 20px 16px;
|
|
|
|
|
|
|
|
background: linear-gradient(135deg, #4285f4 0%, #6fa8f5 100%);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.balance-card {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.balance-info {
|
|
|
|
|
|
|
|
.balance-label {
|
|
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.8);
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.balance-amount {
|
|
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
|
|
font-size: 32px;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.balance-icon {
|
|
|
|
|
|
|
|
opacity: 0.8;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.recharge-section,
|
|
|
|
|
|
|
|
.payment-section,
|
|
|
|
|
|
|
|
.notice-section {
|
|
|
|
|
|
|
|
margin: 16px;
|
|
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.amount-grid {
|
|
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
|
|
grid-template-columns: repeat(3, 1fr);
|
|
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.amount-item {
|
|
|
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
|
|
|
border: 2px solid transparent;
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
padding: 16px 8px;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
|
|
border-color: #4285f4;
|
|
|
|
|
|
|
|
background-color: #f0f7ff;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.amount-value {
|
|
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.amount-bonus {
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.custom-amount {
|
|
|
|
|
|
|
|
.custom-label {
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.custom-input {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
padding: 0 16px;
|
|
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.currency {
|
|
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.amount-input {
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
height: 48px;
|
|
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.amount-tips {
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.payment-list {
|
|
|
|
|
|
|
|
.payment-item {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
border: 1px solid #e5e5e5;
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
|
|
border-color: #4285f4;
|
|
|
|
|
|
|
|
background-color: #f0f7ff;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.payment-info {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.payment-details {
|
|
|
|
|
|
|
|
.payment-name {
|
|
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.payment-desc {
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.notice-list {
|
|
|
|
|
|
|
|
.notice-item {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.notice-text {
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.bottom-section {
|
|
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
border-top: 1px solid #e5e5e5;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.recharge-info {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.recharge-text {
|
|
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.bonus-text {
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
|
|
|
margin-left: 4px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|