2025-10-22 23:06:43 +08:00

321 lines
9.2 KiB
Vue
Raw 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>
<s-layout title="支付结果" :bgStyle="{ color: '#FFF' }">
<view class="pay-result-box ss-flex-col ss-row-center ss-col-center">
<view class="pay-waiting ss-m-b-30" v-if="payResult === 'waiting'"> </view>
<image
class="pay-img ss-m-b-30"
v-if="payResult === 'success'"
:src="sheep.$url.static('/assets/addons/shopro/uniapp/order/order_pay_success.gif')"
></image>
<image
class="pay-img ss-m-b-30"
v-if="['failed', 'closed'].includes(payResult)"
:src="sheep.$url.static('/assets/addons/shopro/uniapp/order/order_paty_fail.gif')"
></image>
<view class="tip-text ss-m-b-30" v-if="payResult == 'success'">{{
state.orderInfo.pay_mode === 'offline' ? '下单成功' : '支付成功'
}}</view>
<view class="tip-text ss-m-b-30" v-if="payResult == 'failed'">支付失败</view>
<view class="tip-text ss-m-b-30" v-if="payResult == 'closed'">该订单已关闭</view>
<view class="tip-text ss-m-b-30" v-if="payResult == 'waiting'">检测支付结果...</view>
<view class="pay-total-num ss-flex" v-if="payResult === 'success'">
<view>{{ state.orderInfo.pay_fee }}</view>
<view v-if="state.orderInfo.score_amount">+</view>
<view class="price-text ss-flex ss-col-center" v-if="state.orderInfo.score_amount">
<image
:src="sheep.$url.static('/assets/addons/shopro/uniapp/goods/score1.svg')"
class="score-img"
></image>
<view>{{ state.orderInfo.score_amount }}</view>
</view>
</view>
<view class="btn-box ss-flex ss-row-center ss-m-t-50">
<button class="back-btn ss-reset-button" @tap="sheep.$router.go('/pages/index/index')">
返回首页
</button>
<button
class="check-btn ss-reset-button"
v-if="payResult === 'failed'"
@tap="sheep.$router.redirect('/pages/pay/index', { orderSN: state.orderId })"
>
重新支付
</button>
<button class="check-btn ss-reset-button" v-if="payResult === 'success'" @tap="onOrder">
查看订单
</button>
<button
class="check-btn ss-reset-button"
v-if="
payResult === 'success' &&
['groupon', 'groupon_ladder'].includes(state.orderInfo.activity_type)
"
@tap="sheep.$router.redirect('/pages/activity/groupon/order')"
>
我的拼团
</button>
</view>
<!-- #ifdef MP -->
<view class="subscribe-box ss-flex ss-m-t-44">
<image
class="subscribe-img"
:src="sheep.$url.static('/assets/addons/shopro/uniapp/order/cargo.png')"
></image>
<view class="subscribe-title ss-m-r-48 ss-m-l-16">获取实时发货信息与订单状态</view>
<view class="subscribe-start" @tap="subscribeMessage">立即订阅</view>
</view>
<!-- #endif -->
</view>
</s-layout>
</template>
<script setup>
import { onLoad, onHide, onShow } from '@dcloudio/uni-app';
import { reactive, computed } from 'vue';
import { isEmpty } from 'lodash';
import sheep from '@/sheep';
const state = reactive({
orderId: 0,
orderType: 'goods',
result: 'unpaid', // 支付状态
orderInfo: {}, // 订单详情
counter: 0, // 获取结果次数
});
const payResult = computed(() => {
if (state.result === 'unpaid') {
return 'waiting';
}
if (state.result === 'paid') {
return 'success';
}
if (state.result === 'failed') {
return 'failed';
}
if (state.result === 'closed') {
return 'closed';
}
});
function showRepayModal() {
if (state.result !== 'failed') return;
uni.showModal({
title: '确认支付',
content: '未检测到您的支付结果,请确认您是否已经支付完成?',
cancelText: '取消',
confirmText: '我已支付',
success: function (res) {
if (res.confirm) {
state.counter = 0;
setTimeout(() => {
getOrderInfo(state.orderId);
}, 100);
}
},
});
}
async function getOrderInfo(orderId) {
let checkPayResult;
state.counter++;
console.log(`[支付结果] 查询订单状态 ${state.counter}/5 次, orderId:`, orderId);
if (state.orderType === 'recharge') {
checkPayResult = sheep.$api.trade.order;
} else {
checkPayResult = sheep.$api.order.detail;
}
try {
const { data, code } = await checkPayResult(orderId);
console.log('[支付结果] 订单查询结果:', { code, status: data?.status });
if (code === 1 && data) {
state.orderInfo = data;
if (state.orderInfo.status === 'closed') {
console.log('[支付结果] 订单已关闭');
state.result = 'closed';
return;
}
if (state.orderInfo.status !== 'unpaid') {
console.log('[支付结果] 订单已支付,状态:', state.orderInfo.status);
state.result = 'paid';
// #ifdef MP
subscribeMessage();
// #endif
return;
}
console.log('[支付结果] 订单仍未支付');
} else {
console.error('[支付结果] 查询订单失败:', code);
}
} catch (error) {
console.error('[支付结果] 查询订单异常:', error);
}
if (state.counter < 5 && state.result === 'unpaid') {
console.log('[支付结果] 1.5秒后继续查询...');
setTimeout(() => {
getOrderInfo(orderId);
}, 1500);
}
// 超过五次检测才判断为支付失败
if (state.counter >= 5 && state.result === 'unpaid') {
console.warn('[支付结果] 轮询5次后仍未支付判定为失败');
state.result = 'failed';
showRepayModal();
}
}
function onOrder() {
if (state.orderType === 'recharge') {
sheep.$router.redirect('/pages/pay/recharge-log');
} else {
sheep.$router.redirect('/pages/order/list');
}
}
// #ifdef MP
function subscribeMessage() {
let event = ['order_dispatched'];
if (['groupon', 'groupon_ladder'].includes(state.orderInfo.activity_type)) {
event.push('groupon_finish');
event.push('groupon_fail');
}
sheep.$platform.useProvider('wechat').subscribeMessage(event);
}
// #endif
onLoad(async (options) => {
console.log('[支付结果] onLoad 参数:', options);
let id = '';
// 支付订单号
if (options.orderSN) {
id = options.orderSN;
}
if (options.id) {
id = options.id;
}
state.orderId = id;
if (options.orderType === 'recharge') {
state.orderType = 'recharge';
}
// 支付结果传值过来是失败,则直接显示失败界面
if (options.payState === 'fail') {
console.log('[支付结果] 支付失败,直接显示失败界面');
state.result = 'failed';
} else if (options.payState === 'success') {
// 支付成功,立即查询一次
console.log('[支付结果] 支付成功,开始查询订单状态');
getOrderInfo(state.orderId);
} else {
// 其他情况也查询
console.log('[支付结果] 未知支付状态,开始查询订单');
getOrderInfo(state.orderId);
}
});
onShow(() => {
if (isEmpty(state.orderInfo)) return;
getOrderInfo(state.orderId);
});
onHide(() => {
state.result = 'unpaid';
state.counter = 0;
});
</script>
<style lang="scss" scoped>
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.score-img {
width: 36rpx;
height: 36rpx;
margin: 0 4rpx;
}
.pay-result-box {
padding: 60rpx 0;
.pay-waiting {
margin-top: 20rpx;
width: 60rpx;
height: 60rpx;
border: 10rpx solid rgb(233, 231, 231);
border-bottom-color: rgb(204, 204, 204);
border-radius: 50%;
display: inline-block;
// -webkit-animation: rotation 1s linear infinite;
animation: rotation 1s linear infinite;
}
.pay-img {
width: 130rpx;
height: 130rpx;
}
.tip-text {
font-size: 30rpx;
font-weight: bold;
color: #333333;
}
.pay-total-num {
font-size: 36rpx;
font-weight: 500;
color: #333333;
font-family: OPPOSANS;
}
.btn-box {
width: 100%;
.back-btn {
width: 190rpx;
height: 70rpx;
font-size: 28rpx;
border: 2rpx solid #dfdfdf;
border-radius: 35rpx;
font-weight: 400;
color: #595959;
}
.check-btn {
width: 190rpx;
height: 70rpx;
font-size: 28rpx;
border: 2rpx solid #dfdfdf;
border-radius: 35rpx;
font-weight: 400;
color: #595959;
margin-left: 32rpx;
}
}
.subscribe-box {
.subscribe-img {
width: 44rpx;
height: 44rpx;
}
.subscribe-title {
font-weight: 500;
font-size: 32rpx;
line-height: 36rpx;
color: #434343;
}
.subscribe-start {
color: var(--ui-BG-Main);
font-weight: 700;
font-size: 32rpx;
line-height: 36rpx;
}
}
}
</style>