1、调整websocket的初始化
2、完善支付的倒计时
This commit is contained in:
parent
47bf0977cc
commit
ee7de58ba4
@ -101,6 +101,12 @@ export const xsKscjApi = async (params: any) => {
|
||||
export const jzXkQkjApi = async (params: any) => {
|
||||
return await post("/mobile/jz/xk/qk", params);
|
||||
};
|
||||
/**
|
||||
* 家长获取抢课到期时间
|
||||
*/
|
||||
export const jzGetQkExpiredTime = async (params: any) => {
|
||||
return await get("/mobile/jz/xk/getQkExpiredTime", params);
|
||||
};
|
||||
/**
|
||||
* 家长发起缴费
|
||||
*/
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
{ active: zc.djz === curZc.djz },
|
||||
]" @click="selectWeek(zc)">
|
||||
<text>{{ zc.mc }}</text>
|
||||
<text v-if="zc.djz === curZc.djz" class="current-tag">当前周</text>
|
||||
<text v-if="zc.dnDjz === dnDjz" class="current-tag">当前周</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@ -63,16 +63,27 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, onMounted, nextTick } from "vue";
|
||||
import { dqpkApi, drpkkbApi, gzlGetDqXqAndZcApi } from "@/api/base/server";
|
||||
import { dqpkApi, drpkkbApi } from "@/api/base/server";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
const { getCurXs } = useUserStore();
|
||||
import dayjs from "dayjs";
|
||||
import "dayjs/locale/zh-cn";
|
||||
import weekOfYear from "dayjs/plugin/weekOfYear";
|
||||
import isoWeek from "dayjs/plugin/isoWeek";
|
||||
|
||||
dayjs.locale("zh-cn");
|
||||
dayjs.extend(weekOfYear);
|
||||
dayjs.extend(isoWeek);
|
||||
|
||||
let dqZc = 0;
|
||||
let xqId = '';
|
||||
|
||||
// 当前周次
|
||||
// 这是当年的第几周
|
||||
const dnDjz = ref(dayjs().isoWeek());
|
||||
|
||||
// 当前选中周次
|
||||
const curZc = ref<any>({});
|
||||
// 当前日期序号
|
||||
// 当前选中日期序号
|
||||
const curRqIndex = ref(0)
|
||||
// 周次列表
|
||||
const zcList = ref<any>([])
|
||||
|
||||
@ -1,17 +1,40 @@
|
||||
<template>
|
||||
<view class="wh-full">
|
||||
<web-view :src="payUrl"></web-view>
|
||||
<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 { useWebSocket } from '@/utils/webSocket/webSocket'
|
||||
import { jzGetQkExpiredTime, jzXkCancelApi } from "@/api/base/server";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
const { getUser } = useUserStore();
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
const { getCurXs, getUser, setWsCallback } = useUserStore();
|
||||
const { getData } = useDataStore();
|
||||
|
||||
const payUrl = ref("");
|
||||
const ws = useWebSocket(`/zhxy/webSocket/${getUser.userId}`, (type: string, res: any) => {
|
||||
setWsCallback((type: string, res: any) => {
|
||||
console.log('收到WebSocket消息:', type, res.data);
|
||||
// 将data从字符串转为对象
|
||||
const dataObj = JSON.parse(res.data);
|
||||
@ -20,7 +43,7 @@ const ws = useWebSocket(`/zhxy/webSocket/${getUser.userId}`, (type: string, res:
|
||||
title: '支付成功',
|
||||
icon: 'success',
|
||||
});
|
||||
ws.closeConnect();
|
||||
setWsCallback((type: string, res: any) => {})
|
||||
// 跳转到支付成功页面
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
@ -29,10 +52,70 @@ const ws = useWebSocket(`/zhxy/webSocket/${getUser.userId}`, (type: string, res:
|
||||
}, 1000)
|
||||
}
|
||||
});
|
||||
onLoad((options: any) => {
|
||||
|
||||
// 倒计时
|
||||
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);
|
||||
ws.reconnect();
|
||||
const res = await jzGetQkExpiredTime({ xsId: getCurXs.id} );
|
||||
seconds = res.result;
|
||||
startCountdown();
|
||||
} else {
|
||||
uni.showToast({ title: '缺少支付地址', icon: 'none' })
|
||||
setTimeout(() => {
|
||||
@ -42,8 +125,92 @@ onLoad((options: any) => {
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
ws.closeConnect();
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<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>
|
||||
|
||||
@ -6,17 +6,21 @@
|
||||
<u-icon name="clock" size="22" color="#fff"></u-icon>
|
||||
</view>
|
||||
<view class="countdown-text">待支付</view>
|
||||
<!-- <view class="countdown-timer">
|
||||
<view class="countdown-timer">
|
||||
<text>剩余:</text>
|
||||
<text class="time-value">{{ countdownTime }}</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 学生信息卡片 -->
|
||||
<XkPayXs />
|
||||
<view class="scrollable-content">
|
||||
|
||||
<!-- 课程信息卡片 -->
|
||||
<XkPayXkqd />
|
||||
<!-- 学生信息卡片 -->
|
||||
<XkPayXs />
|
||||
|
||||
<!-- 课程信息卡片 -->
|
||||
<XkPayXkqd />
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 底部支付区域 -->
|
||||
<view class="payment-footer">
|
||||
@ -36,7 +40,7 @@
|
||||
<script setup lang="ts">
|
||||
import XkPayXs from "@/pages/base/components/XkPayXs/index.vue"
|
||||
import XkPayXkqd from "@/pages/base/components/XkPayXkqd/index.vue"
|
||||
import { jzXkCancelApi, jzXkFqJfjApi } from "@/api/base/server";
|
||||
import { jzGetQkExpiredTime, jzXkCancelApi, jzXkFqJfjApi } from "@/api/base/server";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
const { getCurXs, getUser } = useUserStore();
|
||||
@ -60,32 +64,32 @@ const totalJe = computed(() => {
|
||||
});
|
||||
|
||||
// 倒计时
|
||||
// const countdownTime = ref("1分20秒");
|
||||
// let timer: any = null;
|
||||
// let seconds = 1 * 60 + 20; // 1分20秒
|
||||
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: () => {
|
||||
// goBack();
|
||||
// },
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
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 minutes = Math.floor(seconds / 60);
|
||||
const remainSeconds = seconds % 60;
|
||||
countdownTime.value = `${minutes}分${remainSeconds}秒`;
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
@ -117,49 +121,40 @@ const cancelRegistration = () => {
|
||||
|
||||
// 立即支付
|
||||
const payNow = async () => {
|
||||
const res = await jzXkFqJfjApi({
|
||||
xsId: getData.xsId,
|
||||
xkId: getData.xkId,
|
||||
jffs: "四川农信", // TODO: 目前只支持四川农信
|
||||
jzId: getUser.jzId,
|
||||
userId: getUser.userId,
|
||||
openId: getUser.openId,
|
||||
});
|
||||
// const res = {
|
||||
// resultCode: 1,
|
||||
// result: "https://pay.weixin.qq.com/wxpay/pay.action?prepay_id=wx20191018103005f5c0c0f5c0c"
|
||||
// }
|
||||
if (res.resultCode === 1 && res.result) {
|
||||
try {
|
||||
const res = await jzXkFqJfjApi({
|
||||
xsId: getData.xsId,
|
||||
xkId: getData.xkId,
|
||||
jffs: "四川农信", // TODO: 目前只支持四川农信
|
||||
jzId: getUser.jzId,
|
||||
userId: getUser.userId,
|
||||
openId: getUser.openId,
|
||||
});
|
||||
if (res.resultCode === 1 && res.result) {
|
||||
uni.redirectTo({
|
||||
url: `/pages/base/course-selection/pay-wait?payUrl=${encodeURIComponent(res.result)}`
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
const url = "https://www.baidu.com";
|
||||
uni.redirectTo({
|
||||
url: `/pages/base/course-selection/pay-wait?payUrl=${encodeURIComponent(res.result)}`
|
||||
url: `/pages/base/course-selection/pay-wait?payUrl=${encodeURIComponent(url)}`
|
||||
});
|
||||
}
|
||||
|
||||
// uni.showLoading({
|
||||
// title: "支付中...",
|
||||
// });
|
||||
|
||||
// // 模拟支付过程
|
||||
// setTimeout(() => {
|
||||
// uni.hideLoading();
|
||||
|
||||
// uni.redirectTo({
|
||||
// url: "/pages/base/course-selection/payment-success",
|
||||
// });
|
||||
// // uni.redirectTo({
|
||||
// // url: "/pages/base/course-selection/payment-fail",
|
||||
// // });
|
||||
// }, 2000);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// startCountdown();
|
||||
onMounted(async() => {
|
||||
const res = await jzGetQkExpiredTime({ xsId: getCurXs.id} );
|
||||
console.log('获取倒计时', res);
|
||||
seconds = res.result;
|
||||
startCountdown();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// if (timer) {
|
||||
// clearInterval(timer);
|
||||
// }
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -167,34 +162,17 @@ onUnmounted(() => {
|
||||
.payment-page {
|
||||
min-height: 100%;
|
||||
background-color: #f5f7fa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 15px;
|
||||
height: 44px;
|
||||
background-color: #2879ff;
|
||||
|
||||
.nav-left {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
width: 40px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
// 可滚动内容区域样式
|
||||
.scrollable-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch; // 增强iOS滚动体验
|
||||
}
|
||||
|
||||
.countdown-section {
|
||||
@ -226,10 +204,10 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.payment-footer {
|
||||
position: fixed;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||
|
||||
@ -2,12 +2,15 @@ import { defineStore } from "pinia";
|
||||
import { authenticationApi, loginCode, loginPass, weChatLogin } from "@/api/system/login";
|
||||
import { AUTH_KEY } from "@/config";
|
||||
import { imagUrl } from "@/utils";
|
||||
import { useWebSocket } from '@/utils/webSocket/webSocket'
|
||||
|
||||
interface UserState {
|
||||
userdata: any;
|
||||
curXs: any;
|
||||
token: string;
|
||||
auth: string[]
|
||||
auth: string[],
|
||||
ws: any,
|
||||
wsCallback: any
|
||||
}
|
||||
|
||||
export const useUserStore = defineStore({
|
||||
@ -20,7 +23,9 @@ export const useUserStore = defineStore({
|
||||
// token
|
||||
token: '',
|
||||
//用户注册信息
|
||||
auth: []
|
||||
auth: [],
|
||||
ws: null,
|
||||
wsCallback: (type: string, res: any) => {}
|
||||
}),
|
||||
getters: {
|
||||
getToken(): string {
|
||||
@ -49,6 +54,9 @@ export const useUserStore = defineStore({
|
||||
setAuth(data: string[]) {
|
||||
this.auth = data;
|
||||
},
|
||||
setWsCallback(callback: any) {
|
||||
this.wsCallback = callback;
|
||||
},
|
||||
/**
|
||||
* @description: 验证码登录
|
||||
*/
|
||||
@ -99,6 +107,15 @@ export const useUserStore = defineStore({
|
||||
if (value[AUTH_KEY]) {
|
||||
this.setToken(value[AUTH_KEY])
|
||||
}
|
||||
if (!this.ws) {
|
||||
this.ws = useWebSocket(`/zhxy/webSocket/${value.userId}`, (type: string, res: any) => {
|
||||
// 判断this.wsCallback是函数,调用
|
||||
if (typeof this.wsCallback === "function") {
|
||||
this.wsCallback(type, res);
|
||||
}
|
||||
});
|
||||
this.ws.reconnect();
|
||||
}
|
||||
authenticationApi({ userId: value.userId }).then(({ result }) => {
|
||||
if (result) {
|
||||
this.setAuth(result)
|
||||
@ -113,6 +130,11 @@ export const useUserStore = defineStore({
|
||||
this.setUser('')
|
||||
this.setCurXs({})
|
||||
this.setAuth([])
|
||||
if (this.ws) {
|
||||
this.ws.closeConnect();
|
||||
this.ws = null;
|
||||
}
|
||||
this.wsCallback((type: string, res: any) => {});
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user