ywyonui ee7de58ba4 1、调整websocket的初始化
2、完善支付的倒计时
2025-07-21 14:34:20 +08:00

217 lines
4.5 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>
<view class="payment-page">
<!-- 倒计时区域 -->
<view class="countdown-section">
<view class="countdown-icon">
<u-icon name="clock" size="22" color="#fff"></u-icon>
</view>
<view class="countdown-text">待支付</view>
<view class="countdown-timer">
<text>剩余</text>
<text class="time-value">{{ countdownTime }}</text>
</view>
</view>
<view class="scrollable-content">
<web-view :src="payUrl" style="flex: 1;"></web-view>
</view>
<!-- 底部支付区域 -->
<view class="payment-footer">
<view class="action-buttons">
<view class="cancel-btn" @click="cancelRegistration">取消报名</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { onLoad } from "@dcloudio/uni-app";
import { jzGetQkExpiredTime, jzXkCancelApi } from "@/api/base/server";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
const { getCurXs, getUser, setWsCallback } = useUserStore();
const { getData } = useDataStore();
const payUrl = ref("");
setWsCallback((type: string, res: any) => {
console.log('收到WebSocket消息:', type, res.data);
// 将data从字符串转为对象
const dataObj = JSON.parse(res.data);
if (dataObj.action === 'pay') {
uni.showToast({
title: '支付成功',
icon: 'success',
});
setWsCallback((type: string, res: any) => {})
// 跳转到支付成功页面
setTimeout(() => {
uni.reLaunch({
url: "/pages/base/course-selection/payment-success",
});
}, 1000)
}
});
// 倒计时
const countdownTime = ref("1分20秒");
let timer: any = null;
let seconds = 1 * 60 + 20; // 1分20秒
// 开始倒计时
const startCountdown = () => {
timer = setInterval(() => {
seconds--;
if (seconds <= 0) {
clearInterval(timer);
uni.showModal({
title: "支付超时",
content: "支付已超时,请重新选课",
showCancel: false,
success: () => {
cancelRegistration();
},
});
return;
}
const minutes = Math.floor(seconds / 60);
const remainSeconds = seconds % 60;
countdownTime.value = `${minutes}${remainSeconds}`;
}, 1000);
};
// 返回上一页
const goBack = () => {
uni.reLaunch({
url: getData.backUrl
});
};
// 取消报名
const cancelRegistration = () => {
uni.showModal({
title: "取消报名",
content: "确定要取消报名吗?",
success: async (res) => {
if (res.confirm) {
await jzXkCancelApi({
xsId: getData.xsId,
xkId: getData.xkId
});
uni.showToast({
title: "已取消报名",
icon: "success",
});
goBack();
}
},
});
};
onLoad(async (options: any) => {
if (options.payUrl) {
payUrl.value = decodeURIComponent(options.payUrl);
const res = await jzGetQkExpiredTime({ xsId: getCurXs.id} );
seconds = res.result;
startCountdown();
} else {
uni.showToast({ title: '缺少支付地址', icon: 'none' })
setTimeout(() => {
uni.navigateBack()
}, 1000)
}
});
onBeforeUnmount(() => {
if (timer) {
clearInterval(timer);
}
});
</script>
<style lang="scss" scoped>
.payment-page {
min-height: 100%;
background-color: #f5f7fa;
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
// 可滚动内容区域样式
.scrollable-content {
flex: 1;
display: flex;
position: relative;
}
.countdown-section {
display: flex;
align-items: center;
padding: 15px;
background-color: #2879ff;
.countdown-icon {
margin-right: 10px;
}
.countdown-text {
font-size: 16px;
font-weight: 500;
color: #fff;
margin-right: auto;
}
.countdown-timer {
font-size: 15px;
color: #fff;
.time-value {
color: #ff4d4f;
font-weight: 500;
}
}
}
.payment-footer {
position: sticky;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
padding: 15px;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
.total-amount {
display: flex;
align-items: center;
margin-bottom: 15px;
font-size: 15px;
color: #333;
.amount-value {
color: #ff6b00;
font-size: 20px;
font-weight: 500;
}
}
.action-buttons {
.cancel-btn {
height: 44px;
line-height: 44px;
text-align: center;
border-radius: 22px;
font-size: 16px;
background-color: #fff;
color: #333;
border: 1px solid #ddd;
}
}
}
</style>