217 lines
4.5 KiB
Vue
Raw Normal View History

<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) => {
2025-07-01 20:54:38 +08:00
console.log('收到WebSocket消息:', type, res.data);
// 将data从字符串转为对象
const dataObj = JSON.parse(res.data);
if (dataObj.action === 'pay') {
uni.showToast({
title: '支付成功',
icon: 'success',
2025-07-01 20:54:38 +08:00
});
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)
}
});
2025-07-01 20:54:38 +08:00
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>