Files
我是个攻城狮 c3f5f13bb3 all
2026-05-27 16:01:15 +08:00

336 lines
9.3 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="pay-container">
<view class="pay_title">请扫码付款</view>
<!-- 支付方式切换 -->
<view class="tab-wrap">
<view
:class="['tab-item', payType === 'alipay' ? 'active' : '']"
@tap="handlePayTypeChange('alipay')"
>
<image src="../../static/img/member/zfbx.png" class="pay-icon" v-if="payType==='alipay'"/>
<image src="../../static/img/member/zfb.png" class="pay-icon" v-else/>
<text>支付宝</text>
</view>
<view
:class="['tab-item', payType === 'wechat' ? 'active' : '']"
@tap="handlePayTypeChange('wechat')"
>
<image src="../../static/img/member/wxx.png" class="pay-icon" v-if="payType==='wechat'" />
<image src="../../static/img/member/wx.png" class="pay-icon" v-else/>
<text>微信</text>
</view>
</view>
<!-- 二维码区 -->
<view class="qr-section">
<image
:src="alipayQrcode"
class="qr-img"
mode="aspectFit"
alt="扫码二维码"
/>
<view class="tip">
<span v-if="leftSeconds > 0">
剩余支付时间
<span class="countdown">
{{ Math.floor(leftSeconds / 60) }}:{{ (leftSeconds % 60).toString().padStart(2, '0') }}
</span>
</span>
<span v-else>
二维码已过期请刷新页面获取新的二维码
</span>
<br/>
</view>
</view>
<!-- 售后说明区 -->
<view class="after-sale">
<view class="as-title">售后说明</view>
<view class="as-item">付款后1个工作日内出具评估报告报告可下载</view>
<view class="as-item">可申请退款售后每笔订单只可申请一次退款</view>
<view class="as-item">我们将跟踪贷款业务结果贷款未成功将自动退款</view>
<view class="as-item">客服电话400-xxxx-xxxx</view>
</view>
</view>
</template>
<script>
export default {
props: {
orderId: {
type: [String, Number],
required: true
}
},
data() {
return {
payType: 'alipay', // 当前选择的支付方式
alipayQrcode: require('../../static/img/member/code.png'),
qrcodeLoaded: false,
endtime: 0, // 服务器返回的结束时刻(时间戳,秒)
leftSeconds: 0,
order_no: '',
payTimer: null, // 定时查询支付状态的timer
countdownTimer: null // 倒计时timer
};
},
watch: {
orderId: {
immediate: true,
handler(newVal) {
// 当 orderId 变化时重新拉取二维码
if (newVal) {
this.resetTimers();
this.qrcodeLoaded = false;
this.alipayQrcode = require('../../static/img/member/code.png');
this.leftSeconds = 0;
this.endtime = 0;
}
}
}
},
created() {
// 组件加载时自动拉取 orderId 的二维码
if (this.orderId) {
this.getQrcode('alipay');
}
},
beforeDestroy() {
// 组件销毁时,清理所有定时器
this.resetTimers();
},
methods: {
resetTimers() {
if (this.payTimer) {
clearInterval(this.payTimer);
this.payTimer = null;
}
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
this.countdownTimer = null;
}
},
async handlePayTypeChange(type) {
if (this.payType === type) return; // 避免重复拉取
this.payType = type;
this.resetTimers();
this.leftSeconds = 0;
this.endtime = 0;
this.alipayQrcode = require('../../static/img/member/code.png');
this.getQrcode(type);
},
// 切换支付方式时,调用后端接口获取二维码
async getQrcode(type) {
if (!this.orderId) return;
this.resetTimers(); // 切换支付方式/刷新二维码前先清理所有定时器
this._post(
'/asset.Asset/pay',
{
pay_type: type === 'alipay' ? 30 : 20,
id: this.orderId
},
res => {
// 正常会有服务端传回支付二维码、截止时间、订单号
this.alipayQrcode = res.data.qr_code_url;
this.order_no = res.data.order_no;
// 假设服务端返回剩余秒数,推荐直接返回leftSeconds,否则自己算
// 兼容两种情况:res.data.leftSeconds 或 res.data.pay_end_time
if (typeof res.data.leftSeconds !== 'undefined') {
this.leftSeconds = res.data.leftSeconds;
this.endtime = Math.floor(Date.now() / 1000) + this.leftSeconds;
} else if (typeof res.data.pay_end_time !== 'undefined') {
this.endtime = res.data.pay_end_time;
this.leftSeconds = this.endtime - Math.floor(Date.now() / 1000);
} else {
// fallback3分钟过期
this.leftSeconds = 180;
this.endtime = Math.floor(Date.now() / 1000) + 180;
}
this.startCountdownAndPayCheck();
},
err => {
this.resetTimers();
// 生成失败时隐藏支付弹窗并提示
this.$emit('close'); // 通知父组件关闭弹窗
const msg = (err && err.data && err.data.msg) ? err.data.msg : '获取二维码失败';
this.$message.error(msg);
}
);
},
startCountdownAndPayCheck() {
// 安全起见再次清理
this.resetTimers();
// 设置倒计时定时器,精确倒计时
this.countdownTimer = setInterval(() => {
if (this.leftSeconds > 0) {
this.leftSeconds -= 1;
}
if (this.leftSeconds <= 0) {
this.leftSeconds = 0;
this.resetTimers();
// 自动关闭弹窗
this.$emit('close');
this.$message.error('二维码已过期,请刷新页面获取新的二维码。');
}
}, 1000);
// 设置支付状态查询定时器
this.payTimer = setInterval(() => {
if (this.order_no && this.leftSeconds > 0) {
this._post(
'/asset.Asset/payStatus',
{
order_no: this.order_no
},
res => {
// 如果支付成功,根据业务逻辑刷新页面/跳转/弹窗...
if (res.data && res.data.pay_status === 20) {
this.resetTimers();
this.$emit('pay-success', this.order_no);
this.$message.success('支付成功');
//支付成功后关闭弹窗,强制刷新页面
this.$emit('close');
this.$nextTick(() => {
window.location.reload();
});
}
// 若未支付则轮询,不需要额外处理
},
err => {
// 支付状态查询失败,也需要轮询,不紧急关闭
// 但你可以根据实际业务在失败次数过多时终止(此处只做错误提示)
// this.$message.error('支付状态查询失败');
}
);
}
}, 3000);
}
}
};
</script>
<style lang="scss">
.pay-container {
width: 65vh;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
margin-top: -30px;
}
.pay_title{
font-family: Source Han Sans, Source Han Sans;
font-weight: 700;
font-size: 18px;
color: #3D3D3D;
line-height: 22px;
text-align: center;
font-style: normal;
text-transform: none;
margin-bottom: 24px;
}
.tab-wrap {
width: 100%;
display: flex;
justify-content: center;
margin-bottom: 28px;
.tab-item {
width: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 19px;
font-family: Source Han Sans, Source Han Sans;
font-weight: 400;
font-size: 16px;
color: #767676;
border-radius: 6px 6px 0 0;
padding: 12px 38px;
cursor: pointer;
border-bottom: 2px solid #e4e4e4;
.pay-icon {
width: 18px;
height: 18px;
margin-right: 8px;
}
}
.tab-item:last-child {
margin-right: 0;
}
.tab-item.active {
border-bottom: 2px solid #f48612;
box-shadow: 0 6px 18px 0 rgba(244, 134, 18, 0.04);
font-family: Source Han Sans, Source Han Sans;
font-weight: 500;
font-size: 16px;
color: #F78A30;
line-height: 22px;
}
}
.qr-section {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 24px;
.qr-img {
width: 160px;
height: 160px;
border: 1px solid #f2f2f2;
border-radius: 8px;
background: #fcfcfc;
margin-bottom: 14px;
}
.remark {
display: flex;
align-items: center;
font-size: 16px;
color: #666;
margin-bottom: 15px;
.remark-icon {
width: 18px;
height: 18px;
margin-right: 7px;
}
text {
font-size: 16px;
}
}
.tip {
width: 100%;
text-align: center;
font-family: Source Han Sans, Source Han Sans;
font-weight: 400;
font-size: 12px;
color: #767676;
line-height: 22px;
margin-top: 2px;
}
}
.after-sale {
width: 100%;
padding: 20px 0 0 0;
.as-title {
margin-bottom: 7px;
font-family: Source Han Sans, Source Han Sans;
font-weight: 500;
font-size: 14px;
color: #3D3D3D;
}
.as-item {
margin-bottom: 4px;
font-family: Source Han Sans, Source Han Sans;
font-weight: 400;
font-size: 12px;
color: #767676;
line-height: 22px;
text-align: left;
}
}
/* 可以根据实际图片和页面风格微调样式 */
</style>