跳转抢课的逻辑

This commit is contained in:
ywyonui 2025-09-02 15:45:06 +08:00
parent b9e009e945
commit 542f7878bb
28 changed files with 720 additions and 547 deletions

View File

@ -40,11 +40,6 @@ export const gzlGetDqXqAndZcApi = async () => {
return await get("/api/gzl/getDqXqAndZc");
};
// 获取配置:家长端是否显示分钟数
export const getJzdShowFs = async () => {
return await get("/api/comConfig/getJzdShowFs");
};
/**
*
*/

View File

@ -2,17 +2,17 @@
import { get, post } from "@/utils/request";
/**
*
*
*/
export const xsKxApi = async (params: any) => {
return await get("/mobile/jz/xkkc/list", params);
export const checkXsXkApi = async (params: any) => {
return await get("/mobile/jz/checkXsXk", params);
};
/**
*
*/
export const xsYxListApi = async (params: any) => {
return await get("/mobile/jz/xsxk/list", params);
export const getXsXkListApi = async (params: any) => {
return await get("/mobile/jz/getXsXkList", params);
};
/**

View File

@ -1,5 +1,5 @@
// const ip: string = "127.0.0.1:8897";
const ip: string = "lzcxsx.cn";
const ip: string = "127.0.0.1:8897";
// const ip: string = "lzcxsx.cn";
const fwqip: string = "lzcxsx.cn";
//const ip: string = "zhxy.yufangzc.com";
//const fwqip: string = "zhxy.yufangzc.com";

View File

@ -143,6 +143,13 @@
"enablePullDownRefresh": false
}
},
{
"path": "pages/base/xk/index",
"style": {
"navigationBarTitleText": "选课信息",
"enablePullDownRefresh": false
}
},
{
"path": "pages/base/xk/xqk",
"style": {
@ -199,6 +206,13 @@
"enablePullDownRefresh": false
}
},
{
"path": "pages/base/xk/qk/index",
"style": {
"navigationBarTitleText": "抢课",
"enablePullDownRefresh": false
}
},
{
"path": "pages/base/xk/qk/xqk",
"style": {

View File

@ -84,8 +84,9 @@ import { getNoticeListApi } from "@/api/base/notice";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import { hasPermission } from "@/utils/permission";
import { PageUtils } from "@/utils/pageUtil";
const { getCurXs, toHome } = useUserStore();
const { getCurXs } = useUserStore();
const { setData, getAppCode, setGlobal } = useDataStore();
//
@ -220,21 +221,21 @@ const menuItems = ref([
icon: "/static/base/home/file-text-line.png",
path: "/pages/base/gzs/xkXqk",
permissionKey: "school-xqkxk", //
type: 1,
lxId: '962488654',
},
{
title: "俱乐部选课",
icon: "/static/base/home/contacts-book-3-line.png",
path: "/pages/base/gzs/xkJlb",
permissionKey: "school-jlbxk", //
type: 2,
lxId: '816059832',
},
{
title: "就餐缴费",
icon: "/static/base/home/contacts-book-3-line.png",
path: "/pages/base/gzs/jc",
permissionKey: "school-jcjf",
type: 3,
lxId: 'JC',
},
]);
@ -277,13 +278,13 @@ const goToGlxs = () => {
//
function handleMenuClick(item: any) {
if (item.path) {
if (!item.type) {
if (!item.lxId) {
uni.navigateTo({
url: item.path,
});
} else {
setGlobal({ type: item.type });
toHome(item.type);
setGlobal({ lxId: item.lxId });
PageUtils.toHome(item.lxId);
}
}
}

View File

@ -15,21 +15,15 @@
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
import { useDataStore } from "@/store/modules/data";
import { useUserStore } from "@/store/modules/user";
import { PageUtils } from "@/utils/pageUtil";
const { getGlobal } = useDataStore();
const { checkXqk, checkJlb, checkJc, setXsPickerInitialized } = useUserStore();
const { setXsPickerInitialized } = useUserStore();
const switchXs = (xs: any) => {
//
setXsPickerInitialized(true);
if (getGlobal.type == 1) {
checkXqk();
} else if (getGlobal.type == 2) {
checkJlb();
} else if (getGlobal.type == 3) {
checkJc();
} else {
}
//
PageUtils.checkLogicPage(xs.lxId);
}
</script>

View File

@ -169,7 +169,7 @@ const startCountdown = () => {
//
const goBack = () => {
uni.reLaunch({
url: getData.backUrl
url: '/pages/base/home/index'
});
};

View File

@ -1,22 +1,22 @@
<template>
<view class="xkqd-list">
<!-- 课程信息卡片 -->
<view class="info-card" v-for="(xkkc, index) in xkkcList" :key="index">
<view class="info-card" v-for="(item, index) in dataList" :key="index">
<view class="card-title">课程信息</view>
<view class="divider"></view>
<view class="course-info">
<image
class="course-image"
:src="xkkc.lxtp ? imagUrl(xkkc.lxtp) : '/static/base/home/11222.png'"
:src="item.lxtp ? imagUrl(item.lxtp) : '/static/base/home/11222.png'"
mode="aspectFill"
></image>
<view class="course-details">
<view class="course-name">{{ xkkc.kcmc }}</view>
<view class="course-teacher">开课老师{{ xkkc.jsName }}</view>
<view class="course-location">上课地点{{ xkkc.kcdd }}</view>
<view class="course-name">{{ item.kcmc }}</view>
<view class="course-teacher">开课老师{{ item.jsName }}</view>
<view class="course-location">上课地点{{ item.kcdd }}</view>
<view class="course-price"
>金额<text class="price-value">¥{{ xkkc.kcje }}</text></view
>金额<text class="price-value">¥{{ item.kcje || item.jfje }}</text></view
>
</view>
</view>
@ -26,35 +26,12 @@
<script setup lang="ts">
import { imagUrl } from "@/utils";
import { useCommonStore } from "@/store/modules/common";
const { getAllXkkcLx } = useCommonStore();
//
const props = defineProps<{
xk: any
dataList: any
}>();
const xkkcLxList = ref<any>([]);
//
const xkkcList = computed(() => {
const xk = props.xk || {};
const xkkcs = xk.xkkcs || [];
return xkkcs.map((xkkc:any) => {
const lx = xkkcLxList.value.find((item: any) => item.id === xkkc.lxId) || {};
return {
...xkkc,
lxtp: lx.lxtp || '',
lxmc: lx.lxmc || ''
};
});
});
onMounted(async () => {
const res = await getAllXkkcLx();
xkkcLxList.value = res.result;
});
</script>
<style lang="scss" scoped>

View File

@ -47,12 +47,12 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { xsKxApi, xsYxListApi } from "@/api/base/xkApi";
import { checkXsXkApi, getXsXkListApi } from "@/api/base/xkApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
const { getCurXs } = useUserStore();
const { setData } = useDataStore();
const { setData, getQk } = useDataStore();
//
const props = defineProps<{
@ -94,8 +94,7 @@ const loadXkList = async () => {
xklxId: props.xklxId,
};
if (!props.isQk) {
const res = await xsYxListApi(params);
uni.hideLoading();
const res = await getXsXkListApi(params);
if (res.resultCode === 1 && res.result && res.result.length) {
xkList.value = res.result;
switchXk(res.result[0]);
@ -104,28 +103,33 @@ const loadXkList = async () => {
switchXk({});
}
} else {
const res = await xsKxApi(params);
uni.hideLoading();
if (res.resultCode === 1) {
const result = res.result || {};
if (result.type === 1) {
//
setData(result);
uni.reLaunch({
url: "/pages/base/xk/pay/index",
});
return;
} else if (result.type === 2 || result.type === 3) {
//
if (result.xkList && result.xkList.length) {
xkList.value = result.xkList;
switchXk(result.xkList[0]);
const qk = getQk || {};
if (props.xsId === qk.xsId && qk.xklxId === props.xklxId && qk.xsXkStatus === "KQK") {
} else {
const res = await getXsXkListApi(params);
if (res.resultCode === 1) {
const result = res.result || {};
if (result.type === 1) {
//
setData(result);
uni.reLaunch({
url: "/pages/base/xk/pay/index",
});
return;
} else if (result.type === 2 || result.type === 3) {
//
if (result.xkList && result.xkList.length) {
xkList.value = result.xkList;
switchXk(result.xkList[0]);
return;
}
}
}
}
goToWks();
}
// goToWks();
}
uni.hideLoading();
};
//

122
src/pages/base/xk/index.vue Normal file
View File

@ -0,0 +1,122 @@
<template>
<view class="interest-course">
<!-- 选课信息头部 - 固定部分 -->
<view class="selection-header">
<view class="header-content">
<!-- 选课类型选择部分 -->
<XkPicker :title="title" :is-qk="false" :xklx-id="xklxId" :xs-id="curXs.id" @change="switchXk" />
<!-- 学生选择部分 -->
<XsPicker :is-bar="true" />
</view>
</view>
<!-- 可滚动的内容区域 -->
<view class="scrollable-content">
<XkkcList :xk="curXk" />
</view>
</view>
</template>
<script setup lang="ts">
import { onLoad } from "@dcloudio/uni-app";
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
import XkPicker from "@/pages/base/xk/components/XkPicker/index.vue"
import XkkcList from "@/pages/base/xk/components/XkkcList/index.vue"
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
const { getCurXs } = useUserStore();
const { getGlobal } = useDataStore();
const curXs = computed(() => getCurXs);
const curXk = ref<any>({});
const title = ref("");
const xklxId = ref("");
//
const switchXk = (xk: any) => {
curXk.value = xk;
}
onLoad((options:any) => {
xklxId.value = options.xklxId || '';
switch(xklxId.value) {
case '962488654': { title.value = '兴趣课信息'; } break;
case '816059832': { title.value = '俱乐部信息'; } break;
default: {
uni.reLaunch({ url: '/pages/base/home/index' });
}
}
});
</script>
<style lang="scss" scoped>
.interest-course {
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: #fff;
.nav-left {
width: 40px;
height: 40px;
display: flex;
align-items: center;
}
.nav-title {
font-size: 18px;
font-weight: 500;
color: #333;
}
.nav-right {
width: 40px;
display: flex;
justify-content: flex-end;
}
}
.selection-header {
background: linear-gradient(135deg, #4a90e2, #2879ff);
padding: 20px 15px;
color: #fff;
border-radius: 0 0 15px 15px;
box-shadow: 0 4px 12px rgba(40, 121, 255, 0.2);
position: sticky;
top: 0;
left: 0;
right: 0;
z-index: 10;
.header-content {
display: flex;
flex-direction: column;
gap: 15px;
}
}
//
.scrollable-content {
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch; // iOS
}
</style>

View File

@ -20,8 +20,8 @@
<script setup lang="ts">
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
import XkPicker from "@/pages/base/components/XkPicker/index.vue"
import XkkcList from "@/pages/base/components/XkkcList/index.vue"
import XkPicker from "@/pages/base/xk/components/XkPicker/index.vue"
import XkkcList from "@/pages/base/xk/components/XkkcList/index.vue"
import { useUserStore } from "@/store/modules/user";
const { getCurXs } = useUserStore();

View File

@ -40,8 +40,8 @@
</template>
<script setup lang="ts">
import XkPayXs from "@/pages/base/components/XkPayXs/index.vue"
import XkPayXkqd from "@/pages/base/components/XkPayXkqd/index.vue"
import XkPayXs from "@/pages/base/xk/components/XkPayXs/index.vue"
import XkPayXkqd from "@/pages/base/xk/components/XkPayXkqd/index.vue"
import { jzGetQkExpiredTime, jzXkCancelApi, jzXkFqJfjApi } from "@/api/base/xkApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
@ -79,11 +79,13 @@ const openPaymentPage = (payUrl: string) => {
try {
// 使 uni.openUrl (uni-app )
// @ts-expect-error
if (typeof uni.openUrl === 'function') {
console.log('使用 uni.openUrl 打开支付页面:', payUrl);
// @ts-expect-error
uni.openUrl({
url: payUrl,
fail: (err) => {
fail: (err:any) => {
console.log('uni.openUrl 失败:', err);
// plus.runtime.openURL
if (typeof (window as any).plus !== 'undefined' && (window as any).plus.runtime && (window as any).plus.runtime.openURL) {

View File

@ -21,7 +21,7 @@
<XkPayXs />
<!-- 课程信息卡片 -->
<XkPaySuccessXkkc :xk="xk" />
<XkPaySuccessXkkc :dataList="dataList" />
</view>
<template #bottom>
@ -41,36 +41,54 @@
<script setup lang="ts">
import { onLoad } from "@dcloudio/uni-app";
import XkPayXs from "@/pages/base/components/XkPayXs/index.vue"
import XkPaySuccessXkkc from "@/pages/base/components/XkPaySuccessXkkc/index.vue"
import { xsYxListApi } from "@/api/base/xkApi";
import XkPayXs from "@/pages/base/xk/components/XkPayXs/index.vue"
import XkPaySuccessXkkc from "@/pages/base/xk/components/XkPaySuccessXkkc/index.vue"
import { getXsXkListApi } from "@/api/base/xkApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import { useCommonStore } from "@/store/modules/common";
const { getCurXs } = useUserStore();
const { setData } = useDataStore();
const { getQk } = useDataStore();
const { getAllXkkcLx } = useCommonStore();
const xk = ref<any>({});
const dataList = ref<any>([]);
//
//
const goBack = () => {
uni.navigateBack();
uni.reLaunch({ url: "/pages/base/home/index" });
};
const loadYxXkList = async (xklxId:string) => {
const res = await xsYxListApi({
xsId: getCurXs.id,
njmcId: getCurXs.njmcId,
xklxId: xklxId,
});
const xkList = res.result || [];
xk.value = xkList[0] || {};
const qk = getQk || {};
if (qk.xklxId === xklxId) {
dataList.value = qk.xkqdList;
console.log('loadYxXkList', qk.xkqdList);
} else {
const resLx = await getAllXkkcLx();
const lxList = resLx.result;
const res = await getXsXkListApi({
xsId: getCurXs.id,
njmcId: getCurXs.njmcId,
xklxId: xklxId,
});
const xkList = res.result || [];
const xk = xkList[0] || {};
const xkkcList = xk.xkkcList || [];
dataList.value = xkkcList.map((xkkc:any) => {
const lx = lxList.value.find((item: any) => item.id === xkkc.lxId) || {};
return {
...xkkc,
lxtp: lx.lxtp || '',
lxmc: lx.lxmc || ''
};
});
}
};
onLoad((options:any) => {
loadYxXkList(options.xklxId);
});
</script>
<style lang="scss" scoped>

View File

@ -175,7 +175,7 @@ const startCountdown = () => {
//
const goBack = () => {
uni.reLaunch({
url: getData.backUrl
url: '/pages/base/home/index'
});
};

View File

@ -0,0 +1,309 @@
<template>
<view class="interest-course">
<!-- 选课信息头部 - 固定部分 -->
<view class="selection-header">
<view class="header-content">
<!-- 第一行选课类型选择 -->
<view class="top-row" v-if="!xsFlag">
<XkPicker :title="title" :is-qk="true" :xklx-id="xklxId" :xs-id="curXs.id" @change="switchXk" />
</view>
<!-- 第二行学生选择和倒计时 -->
<view class="bottom-row">
<XsPicker :is-bar="true" @change="switchXs" />
<XkCountdown :xk="curXk" @over="xkTimeOver" v-if="curXk && curXk.id" />
</view>
</view>
</view>
<!-- 可滚动的内容区域 -->
<view class="scrollable-content">
<!-- 显示课程列表 -->
<XkkcList :xk="curXk" :can-selected="true" :multiple="curXk.kxNum > 1" @change="changeXkkc" />
</view>
<!-- 底部报名按钮 - 固定部分 -->
<view class="register-btn-container" v-if="curXk && curXk.id">
<view class="selected-count-info" v-if="selectedXkkcIds && selectedXkkcIds.length > 0">
已选 {{ selectedXkkcIds.length }} 门课程
</view>
<view class="register-btn" @click="submit">点击报名</view>
</view>
</view>
</template>
<script setup lang="ts">
import { onLoad } from "@dcloudio/uni-app";
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
import XkPicker from "@/pages/base/xk/components/XkPicker/index.vue"
import XkCountdown from "@/pages/base/xk/components/XkCountdown/index.vue"
import XkkcList from "@/pages/base/xk/components/XkkcList/index.vue"
import { jzXkQkjApi } from "@/api/base/xkApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import dayjs from "dayjs";
const { getCurXs, getUser } = useUserStore();
const { setData, getData } = useDataStore();
const { sign_file } = getData;
const title = ref("");
const xklxId = ref("");
const curXs = computed(() => getCurXs);
const curXk = ref<any>({});
const selectedXkkcIds = ref<any>([]);
const xsFlag = ref(true);
//
const checkEnrollmentStatus = (xk: any) => {
if (!xk || !xk.xkjstime) return;
const now = new Date().getTime();
const endTime = new Date(xk.xkjstime).getTime();
if (now > endTime) {
//
const courseInfo = encodeURIComponent(JSON.stringify(xk));
uni.navigateTo({
url: `/pages/base/xk/qk/yjz?courseInfo=${courseInfo}`
});
return true;
}
return false;
};
//
const switchXk = (xk: any) => {
curXk.value = xk;
//
selectedXkkcIds.value = [];
uni.setStorageSync("selectedXkkcIds", []);
//
if (checkEnrollmentStatus(xk)) {
return;
}
}
const switchXs = (xs: any) => {
xsFlag.value = false;
}
//
const xkTimeOver = (val: any) => {
console.log('选课时间结束:', val);
//
//
}
//
const changeXkkc = (ids: any) => {
selectedXkkcIds.value = ids;
}
//
const submit = async () => {
//
if (selectedXkkcIds.value.length === 0) {
uni.showToast({
title: "请选择课程!",
icon: "none",
});
return;
}
//
if (curXk.value && curXk.value.xkkstime) {
const now = dayjs().valueOf();
const startTime = dayjs(curXk.value.xkkstime).valueOf();
if (now < startTime) {
uni.showToast({
title: "选课还未开始,请耐心等待!",
icon: "none",
});
return;
}
}
uni.showLoading({
title: "抢课中...",
});
const params = {
xsId: curXs.value.id,
xm: curXs.value.xm,
njmc: curXs.value.njmc,
njmcId: curXs.value.njmcId,
njId: curXs.value.njId,
bc: (curXs.value.njbc || '') + (curXs.value.bjmc || ''),
xkId: curXk.value.id,
xkkcIds: selectedXkkcIds.value,
jzId: getUser.jzId,
qmFile: sign_file ? sign_file.value : "",
};
const res = await jzXkQkjApi(params);
uni.hideLoading();
if (res.resultCode === 1) {
selectedXkkcIds.value = [];
uni.setStorageSync("selectedXkkcIds", []);
setData(res.result);
xsFlag.value = true;
setTimeout(() => {
xsFlag.value = false;
}, 1000);
if (curXk.value.sfjf === 1) {
//
uni.navigateTo({
url: "/pages/base/xk/pay/index",
});
} else {
//
uni.navigateTo({
url: "/pages/base/xk/pay/success?xklxId=" + xklxId.value,
});
}
} else {
uni.showToast({
title: res.message,
icon: "none",
});
}
}
onLoad((options:any) => {
xklxId.value = options.xklxId || '';
switch(xklxId.value) {
case '962488654': { title.value = '兴趣课信息'; } break;
case '816059832': { title.value = '俱乐部信息'; } break;
default: {
uni.reLaunch({ url: '/pages/base/home/index' });
}
}
});
</script>
<style lang="scss" scoped>
.interest-course {
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: #fff;
.nav-left {
width: 40px;
height: 40px;
display: flex;
align-items: center;
}
.nav-title {
font-size: 18px;
font-weight: 500;
color: #333;
}
.nav-right {
width: 40px;
display: flex;
justify-content: flex-end;
}
}
.selection-header {
background: linear-gradient(135deg, #4a90e2, #2879ff);
padding: 20px 15px;
color: #fff;
border-radius: 0 0 15px 15px;
box-shadow: 0 4px 12px rgba(40, 121, 255, 0.2);
position: sticky;
top: 0;
left: 0;
right: 0;
z-index: 10;
.header-content {
display: flex;
flex-direction: column;
gap: 15px;
.top-row {
display: flex;
align-items: center;
:deep(.title-section) {
width: 100%;
}
}
.bottom-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 15px;
//
:deep(.xs-bar) {
flex: 1;
min-width: 0;
}
//
:deep(.countdown-section) {
flex-shrink: 0;
background: rgba(255, 255, 255, 0.1);
border-radius: 6px;
padding: 6px 10px;
backdrop-filter: blur(10px);
}
}
}
}
//
.scrollable-content {
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch; // iOS
}
.register-btn-container {
position: sticky;
bottom: 0;
left: 0;
right: 0;
padding: 15px;
background-color: #fff;
z-index: 1;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
.selected-count-info {
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.register-btn {
height: 50px;
line-height: 50px;
text-align: center;
background-color: #2879ff;
color: #fff;
border-radius: 25px;
font-size: 16px;
font-weight: 500;
}
}
</style>

View File

@ -33,9 +33,9 @@
<script setup lang="ts">
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
import XkPicker from "@/pages/base/components/XkPicker/index.vue"
import XkCountdown from "@/pages/base/components/XkCountdown/index.vue"
import XkkcList from "@/pages/base/components/XkkcList/index.vue"
import XkPicker from "@/pages/base/xk/components/XkPicker/index.vue"
import XkCountdown from "@/pages/base/xk/components/XkCountdown/index.vue"
import XkkcList from "@/pages/base/xk/components/XkkcList/index.vue"
import { jzXkQkjApi } from "@/api/base/xkApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
@ -143,7 +143,6 @@ const submit = async () => {
if (res.resultCode === 1) {
selectedXkkcIds.value = [];
uni.setStorageSync("selectedXkkcIds", []);
res.result.backUrl = "/pages/base/xk/qk/jlb";
setData(res.result);
xsFlag.value = true;
setTimeout(() => {

View File

@ -33,9 +33,9 @@
<script setup lang="ts">
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
import XkPicker from "@/pages/base/components/XkPicker/index.vue"
import XkCountdown from "@/pages/base/components/XkCountdown/index.vue"
import XkkcList from "@/pages/base/components/XkkcList/index.vue"
import XkPicker from "@/pages/base/xk/components/XkPicker/index.vue"
import XkCountdown from "@/pages/base/xk/components/XkCountdown/index.vue"
import XkkcList from "@/pages/base/xk/components/XkkcList/index.vue"
import { jzXkQkjApi } from "@/api/base/xkApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
@ -143,7 +143,6 @@ const submit = async () => {
if (res.resultCode === 1) {
selectedXkkcIds.value = [];
uni.setStorageSync("selectedXkkcIds", []);
res.result.backUrl = "/pages/base/xk/qk/xqk";
setData(res.result);
xsFlag.value = true;
setTimeout(() => {

View File

@ -20,8 +20,8 @@
<script setup lang="ts">
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
import XkPicker from "@/pages/base/components/XkPicker/index.vue"
import XkkcList from "@/pages/base/components/XkkcList/index.vue"
import XkPicker from "@/pages/base/xk/components/XkPicker/index.vue"
import XkkcList from "@/pages/base/xk/components/XkkcList/index.vue"
import { useUserStore } from "@/store/modules/user";
const { getCurXs } = useUserStore();

View File

@ -17,6 +17,7 @@ import { useDataStore } from "@/store/modules/data";
import { useUserStore } from "@/store/modules/user";
import { checkOpenId } from "@/api/system/login";
import { refreshPermissionCache } from "@/utils/permission";
import { PageUtils } from "@/utils/pageUtil";
const { setGlobal } = useDataStore();
const userStore = useUserStore();
@ -28,18 +29,41 @@ const toLogin = () => {
});
};
//
const initGlobalData = (data: any) => {
let gData = data || {};
let lxId = gData.lxId;
//
if (!lxId && gData.type) {
switch (gData.type + '') {
case "1":
lxId = '962488654';
break;
case "2":
lxId = '816059832';
break;
case "3":
lxId = 'JC';
break;
}
}
gData.lxId = lxId;
setGlobal(gData);
return gData;
}
onLoad(async (data: any) => {
setGlobal(data);
if (data && data.openId) {
const gData = initGlobalData(data);
if (gData.openId) {
try {
const res = await checkOpenId({ openId: data.openId, appCode: "JZ" });
const res = await checkOpenId({ openId: gData.openId, appCode: "JZ" });
if (res.resultCode == 1 && res.result) {
//
userStore.afterLoginAction(res.result);
// changeTime
if (data.changeTime) {
if (gData.changeTime) {
const currentPermissions = userStore.getAuth;
if (currentPermissions && currentPermissions.length > 0) {
@ -47,7 +71,7 @@ onLoad(async (data: any) => {
}
}
//
userStore.toHome(data.type);
PageUtils.toHome(gData.lxId);
return;
}
} catch (err) {

View File

@ -131,6 +131,7 @@ import { useDataStore } from "@/store/modules/data";
import { useDicStore } from "@/store/modules/dic";
import { imagUrl } from "@/utils";
import { refreshPermissionCache } from "@/utils/permission";
import { PageUtils } from "@/utils/pageUtil";
const dicOptions = ref<any>([[[]]]);
const dicPickerRef = ref();
@ -308,7 +309,7 @@ async function submit() {
refreshPermissionCache(currentPermissions, res.result.changeTime);
}
}
userStore.toHome(getGlobal.type);
PageUtils.toHome(getGlobal.lxId);
} else {
showToast({ title: res.message || "提交失败", icon: "none" });
}

View File

@ -9,7 +9,8 @@ export const useDataStore = defineStore({
global: {},
file: {},
params: {},
appCode: "JZ"
appCode: "JZ",
qk: {}
}),
getters: {
getData(): any {
@ -33,6 +34,9 @@ export const useDataStore = defineStore({
getAppCode(): string {
return this.appCode;
},
getQk(): any {
return this.qk;
}
},
actions: {
setData(data: any) {
@ -53,6 +57,9 @@ export const useDataStore = defineStore({
setParams(data: any) {
this.params = data;
},
setQk(data: any) {
this.qk = data;
},
},
persist: {
enabled: true,

View File

@ -1,8 +1,5 @@
import { defineStore } from "pinia";
import { authenticationApi, loginCode, loginPass, weChatLogin, checkOpenId } from "@/api/system/login";
import { checkXsXkByTypeApi, xsKxApi } from "@/api/base/xkApi";
import { getLatestInterestCourseApi } from "@/api/base/server";
import { jcGetJcBzListApi } from "@/api/base/jcApi";
import { AUTH_KEY } from "@/config";
import { imagUrl } from "@/utils";
import { useWebSocket } from '@/utils/webSocket/webSocket'
@ -212,334 +209,6 @@ export const useUserStore = defineStore({
}
})
},
/**
*
* @param type
*/
async toHome(type: number) {
if (type == 1) {
// 兴趣课逻辑: 判断当前学生列表
if (this.userdata.xsList && this.userdata.xsList.length === 1) {
this.checkXqk();
} else if (this.userdata.xsList && this.userdata.xsList.length > 1) {
uni.reLaunch({
url: "/pages/base/home/xsXz",
});
}
} else if (type == 2) {
// 俱乐部逻辑: 判断当前学生列表
if (this.userdata.xsList && this.userdata.xsList.length == 1) {
this.checkJlb();
} else if (this.userdata.xsList && this.userdata.xsList.length > 1) {
uni.reLaunch({
url: "/pages/base/home/xsXz",
});
}
} else if (type == 3) {
// 俱乐部逻辑: 判断当前学生列表
if (this.userdata.xsList && this.userdata.xsList.length == 1) {
this.checkJc();
} else if (this.userdata.xsList && this.userdata.xsList.length > 1) {
uni.reLaunch({
url: "/pages/base/home/xsXz",
});
}
} else {
uni.reLaunch({
url: "/pages/base/home/index",
});
}
},
// 验证选课状态(时间验证)- 通用版本
async validateEnrollmentStatus(xklxId: string, courseType: string = '兴趣课') {
try {
// 获取选课信息进行验证
const res = await getLatestInterestCourseApi({ xklxId });
const xkInfo = res.result;
if (!xkInfo) {
uni.showToast({
title: '获取选课信息失败',
icon: 'none'
});
return false;
}
// 检查选课状态:如果 xkzt 等于 0表示未发布
if (xkInfo.xkzt === 0) {
// 选课未发布,跳转到课程报名尚未开放页面
uni.setStorageSync('title', courseType);
uni.reLaunch({
url: "/pages/base/xk/qk/wks",
});
return false;
}
// 检查选课是否已结束
if (xkInfo.xkjstime) {
const now = new Date().getTime();
const endTime = new Date(xkInfo.xkjstime).getTime();
if (now > endTime) {
// 选课已结束,跳转到结束页面
const courseInfo = encodeURIComponent(JSON.stringify(xkInfo));
uni.navigateTo({
url: `/pages/base/xk/qk/yjz?courseInfo=${courseInfo}`
});
return false;
}
}
// 所有验证通过
return true;
} catch (error) {
console.error('验证选课状态失败:', error);
uni.showToast({
title: '验证选课状态失败',
icon: 'none'
});
return false;
}
},
// 验证兴趣课选课状态(保持向后兼容)
async validateInterestCourseEnrollmentStatus() {
return this.validateEnrollmentStatus("962488654", "兴趣课");
},
// 验证俱乐部选课状态
async validateClubEnrollmentStatus() {
return this.validateEnrollmentStatus("816059832", "俱乐部");
},
// 校验兴趣课 - 优化版本
async checkXqk() {
try {
// 先验证选课状态(时间验证)
const validateResult = await this.validateInterestCourseEnrollmentStatus();
if (!validateResult) {
return; // 验证失败,已处理跳转
}
// 使用getXsKx接口获取详细选课信息
const res = await xsKxApi({
xsId: this.curXs.id,
njmcId: this.curXs.njmcId,
xklxId: "962488654" // 兴趣课类型ID
});
if (res.resultCode === 1) {
const data = res.result;
const type = data.type;
switch (type) {
case 1: // 待支付
uni.reLaunch({
url: "/pages/base/xk/pay/index",
});
return;
case 2: // 可选课列表 - 跳转到告知书页
uni.reLaunch({
url: "/pages/base/gzs/xkXqk",
});
return;
case 3: // 已支付 - 跳转到详情页
uni.reLaunch({
url: "/pages/base/xk/pay/success?xklxId=962488654",
});
return;
default:
// 默认跳转到告知书页面
uni.reLaunch({
url: "/pages/base/gzs/xkXqk",
});
return;
}
}
// 接口调用失败,使用备用方案
this.checkXqkFallback();
} catch (error) {
console.error("查询兴趣课状态失败:", error);
// 异常情况,使用备用方案
this.checkXqkFallback();
}
},
// 兴趣课备用检查方案
async checkXqkFallback() {
try {
const res = await checkXsXkByTypeApi({
xsId: this.curXs.id,
xklxId: "962488654" // 兴趣课类型ID
});
if (res.resultCode === 1) {
const checkResult = res.result;
if (checkResult === 1) {
uni.reLaunch({
url: "/pages/base/xk/pay/index",
});
return;
} else if (checkResult === 2) {
uni.reLaunch({
url: "/pages/base/xk/xqk",
});
return;
}
}
uni.reLaunch({
url: "/pages/base/gzs/xkXqk",
});
} catch (error) {
console.error("备用方案也失败:", error);
uni.reLaunch({
url: "/pages/base/gzs/xkXqk",
});
}
},
// 校验俱乐部 - 优化版本
async checkJlb() {
try {
// 先验证俱乐部选课状态(时间验证)
const validateResult = await this.validateClubEnrollmentStatus();
if (!validateResult) {
return; // 验证失败,已处理跳转
}
// 使用getXsKx接口获取详细选课信息
const res = await xsKxApi({
xsId: this.curXs.id,
njmcId: this.curXs.njmcId,
xklxId: "816059832" // 俱乐部类型ID
});
if (res.resultCode === 1) {
const data = res.result;
const type = data.type;
switch (type) {
case 1: // 待支付
uni.reLaunch({
url: "/pages/base/xk/pay/index",
});
return;
case 2: // 可选课列表 - 跳转到告知书
uni.reLaunch({
url: "/pages/base/gzs/xkJlb",
});
return;
case 3: // 已支付 - 跳转到详情页
uni.reLaunch({
url: "/pages/base/xk/pay/success?xklxId=816059832",
});
return;
default:
// 默认跳转到告知书页面
uni.reLaunch({
url: "/pages/base/gzs/xkJlb",
});
return;
}
}
// 接口调用失败,使用备用方案
this.checkJlbFallback();
} catch (error) {
console.error("查询俱乐部状态失败:", error);
// 异常情况,使用备用方案
this.checkJlbFallback();
}
},
// 俱乐部备用检查方案
async checkJlbFallback() {
try {
const res = await checkXsXkByTypeApi({
xsId: this.curXs.id,
xklxId: "816059832" // 俱乐部类型ID
});
if (res.resultCode === 1) {
const checkResult = res.result;
if (checkResult === 1) {
uni.reLaunch({
url: "/pages/base/xk/pay/index",
});
return;
} else if (checkResult === 2) {
uni.reLaunch({
url: "/pages/base/xk/jlb",
});
return;
}
}
uni.reLaunch({
url: "/pages/base/gzs/xkJlb",
});
} catch (error) {
console.error("备用方案也失败:", error);
uni.reLaunch({
url: "/pages/base/gzs/xkJlb",
});
}
},
// 就餐查询 - 优化版本
async checkJc() {
try {
// 使用getJcBzList接口获取详细就餐信息
const res = await jcGetJcBzListApi({
xsId: this.curXs.id
});
if (res.resultCode === 1) {
const data = res.result;
const type = data.type;
// 根据返回的数据类型进行页面跳转
switch (type) {
case 1: // 未选择(返回可选标准列表)- 跳转到报名页面
uni.reLaunch({
url: "/pages/base/jc/bm",
});
return;
case 2: // 待支付 - 跳转到支付页面
uni.reLaunch({
url: "/pages/base/jc/pay/index",
});
return;
case 3: // 已支付 - 跳转到已选择页面
uni.reLaunch({
url: "/pages/base/jc/index",
});
return;
default:
// 默认跳转到告知书页面
uni.reLaunch({
url: "/pages/base/gzs/jc",
});
return;
}
}
// 接口调用失败,使用备用方案
this.checkJcFallback();
} catch (error) {
console.error("查询就餐状态失败:", error);
// 异常情况,使用备用方案
this.checkJcFallback();
}
},
// 就餐备用检查方案
async checkJcFallback() {
try {
// 备用方案:直接跳转到报名页面
uni.reLaunch({
url: "/pages/base/gzs/jc",
});
} catch (error) {
console.error("备用方案也失败:", error);
uni.reLaunch({
url: "/pages/base/gzs/jc",
});
}
},
/**
* @description:
*/

133
src/utils/pageUtil.ts Normal file
View File

@ -0,0 +1,133 @@
import { checkXsXkApi } from "@/api/base/xkApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
const userStore = useUserStore();
const dataStore = useDataStore();
const devFlag = true;
/**
*
*/
export const PageUtils = {
/**
*
* @param lxId JC: 就餐816059832: 俱乐部962488654: 兴趣课
*/
async toHome(lxId: string) {
// 没有类型,则跳转首页
if (!lxId) {
uni.reLaunch({
url: "/pages/base/home/index",
});
return;
}
// 判断当前学生列表如果大于1则跳转学生选择页面
const xsList = userStore.getUser.xsList;
if (devFlag) {
userStore.setCurXs(xsList[0]);
} else {
if (xsList && xsList.length > 1) {
uni.reLaunch({
url: "/pages/base/home/xsXz",
});
return;
}
}
// 判断业务逻辑,并跳转界面
await this.checkLogicPage(lxId);
},
/**
*
*/
async checkLogicPage(lxId: string) {
switch (lxId) {
// 就餐逻辑单独处理
case "JC": {
} break;
// 默认当作 选课的选课类型IDxkLxId处理
default: {
await this.checkQkLogic(lxId);
}
}
},
/**
*
* @param xklxId
*/
async checkQkLogic(xklxId: string) {
const res: any = await checkXsXkApi({
xsId: userStore.getCurXs.id,
njmcId: userStore.getCurXs.njmcId,
xklxId: xklxId,
});
console.log('checkQkLogic', res);
if (res.resultCode != 1) {
uni.showToast({
title: res.message,
icon: 'none'
});
uni.reLaunch({
url: "/pages/base/home/xsXz",
});
return;
}
const result = res.result || {};
// 记录到缓存数据中
dataStore.setQk(result);
// 状态判断
switch (result.xsXkStatus) {
case 'KQK': { // KQK可抢课
uni.reLaunch({
url: "/pages/base/xk/qk/index?xklxId=" + xklxId,
});
} break;
case 'QKZ': { // QKZ抢课中
} break;
case 'YQK': { // YQK已选课
} break;
case 'DZF': { // DZF待支付
} break;
case 'YZF': { // YZF已支付
uni.reLaunch({
url: "/pages/base/xk/pay/success?xklxId=" + xklxId,
});
} break;
}
},
/**
*
*/
toGzs(lxId: string) {
let url = '';
switch (lxId) {
case "JC": {
url = "/pages/base/jc/gzs/jc";
} break;
case "816059832": {
url = "/pages/base/xk/gzs/xkJlb";
} break;
case "962488654": {
url = "/pages/base/xk/gzs/xkXqk";
} break;
}
if (url) {
uni.navigateTo({
url,
});
} else {
uni.showToast({
title: '类型异常,无法跳转到告知书',
icon: 'none'
});
}
},
/**
*
*/
}

View File

@ -1,95 +0,0 @@
import { getXsXkStatusApi } from "@/api/base/xkApi";
import { useUserStore } from "@/store/modules/user";
/**
*
*/
export class XkUtils {
/**
*
* @param xklxId ID
* @returns
*/
static async checkXkStatus(xklxId: string) {
const userStore = useUserStore();
const curXs = userStore.getCurXs;
try {
const res = await getXsXkStatusApi({
xsId: curXs.id,
njmcId: curXs.njmcId,
xklxId: xklxId
});
if (res.resultCode === 1) {
return res.result;
}
return null;
} catch (error) {
console.error("检查选课状态失败:", error);
return null;
}
}
/**
*
* @param type
* @returns
*/
static getStatusDescription(type: number): string {
switch (type) {
case 1:
return "有待支付的选课,请先完成支付";
case 2:
return "可以选择的课程";
case 3:
return "已选择并完成支付的选课";
default:
return "暂无可选课程";
}
}
/**
*
* @param xkList
* @returns
*/
static canQk(xkList: any[]): boolean {
if (!xkList || xkList.length === 0) {
return false;
}
// 检查是否有可选的课程
return xkList.some((xk: any) => {
return !xk.selected && xk.xkkcs && xk.xkkcs.length > 0;
});
}
/**
*
* @param xkList
* @returns
*/
static getAvailableXkList(xkList: any[]): any[] {
if (!xkList || xkList.length === 0) {
return [];
}
return xkList.filter((xk: any) => {
return !xk.selected && xk.xkkcs && xk.xkkcs.length > 0;
});
}
/**
*
* @param xkList
* @returns
*/
static getSelectedXk(xkList: any[]): any | null {
if (!xkList || xkList.length === 0) {
return null;
}
return xkList.find((xk: any) => xk.selected) || null;
}
}