提现
This commit is contained in:
parent
d22acd005c
commit
eefe1e37f6
@ -19,3 +19,12 @@ export const xkXkqdApi = async (params: any) => {
|
|||||||
export const kcjhFindKcjhByKcIdApi = async (params: any) => {
|
export const kcjhFindKcjhByKcIdApi = async (params: any) => {
|
||||||
return await get("/api/kcjh/findKcjhByKcId", params);
|
return await get("/api/kcjh/findKcjhByKcId", params);
|
||||||
};
|
};
|
||||||
|
export const xkgzsApi = async (params: any) => {
|
||||||
|
return await get("/api/gzs/findPage", params);
|
||||||
|
};
|
||||||
|
export const xkxkbmInfoApi = async (params: any) => {
|
||||||
|
return await get("/mobile/xk/xkbmInfo", params);
|
||||||
|
};
|
||||||
|
export const xkqddeleteApi = async (params: any) => {
|
||||||
|
return await post("/api/xkqd/delete?ids=" + params.ids);
|
||||||
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// const ip: string = "119.29.194.155:8893";
|
const ip: string = "119.29.194.155:8893";
|
||||||
const ip: string = "yufangzc.com";
|
// const ip: string = "yufangzc.com";
|
||||||
const fwqip: string = "yufangzc.com";
|
const fwqip: string = "yufangzc.com";
|
||||||
//打包服务器接口代理标识
|
//打包服务器接口代理标识
|
||||||
const SERVERAGENT: string = "/jzd-api";
|
const SERVERAGENT: string = "/jzd-api";
|
||||||
@ -7,11 +7,11 @@ const SERVERAGENT: string = "/jzd-api";
|
|||||||
export const HOMEAGENT: string = "";
|
export const HOMEAGENT: string = "";
|
||||||
// 接口地址
|
// 接口地址
|
||||||
export const BASE_URL: string =
|
export const BASE_URL: string =
|
||||||
process.env.NODE_ENV == "development" ? `https://${ip}/zhxy` : SERVERAGENT;
|
process.env.NODE_ENV == "development" ? `http://${ip}/zhxy` : SERVERAGENT;
|
||||||
// WebSocket地址
|
// WebSocket地址
|
||||||
export const BASE_WS_URL: string = `wss://${ip}`;
|
export const BASE_WS_URL: string = `wss://${ip}`;
|
||||||
//图片地址
|
//图片地址
|
||||||
export const BASE_IMAGE_URL: string = process.env.NODE_ENV == "development" ? `https://${ip}` : `https://${fwqip}`;
|
export const BASE_IMAGE_URL: string = process.env.NODE_ENV == "development" ? `http://${ip}` : `http://${fwqip}`;
|
||||||
//存token的key
|
//存token的key
|
||||||
export const AUTH_KEY: string = "satoken";
|
export const AUTH_KEY: string = "satoken";
|
||||||
//token过期返回状态码
|
//token过期返回状态码
|
||||||
|
|||||||
@ -215,6 +215,11 @@
|
|||||||
"navigationBarTitleText": "uni-app",
|
"navigationBarTitleText": "uni-app",
|
||||||
"navigationBarBackgroundColor": "#fff",
|
"navigationBarBackgroundColor": "#fff",
|
||||||
"backgroundColor": "#F8F8F8",
|
"backgroundColor": "#F8F8F8",
|
||||||
"orientation": "portrait"
|
"orientation": "portrait",
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"app-plus": {
|
||||||
|
"background": "#efeff4",
|
||||||
|
"titleView": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1026
src/pages/base/course-selection/club-selection copy.vue
Normal file
1026
src/pages/base/course-selection/club-selection copy.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -97,10 +97,12 @@
|
|||||||
|
|
||||||
<!-- 底部报名按钮 - 固定部分 -->
|
<!-- 底部报名按钮 - 固定部分 -->
|
||||||
<view class="register-btn-container">
|
<view class="register-btn-container">
|
||||||
<view class="selected-count-info" v-if="getSelectedCount > 0">
|
<view class="register-btn" @click="submitRegistration">
|
||||||
已选 {{ getSelectedCount }} 门课程
|
<text v-if="selectedCoursesCount > 0">
|
||||||
|
点击报名 (已选{{ selectedCoursesCount }}门)
|
||||||
|
</text>
|
||||||
|
<text v-else>点击报名</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="register-btn" @click="submitRegistration">点击报名</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view>
|
<view>
|
||||||
@ -157,15 +159,26 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { navigateTo } from "@/utils/uniapp";
|
import {
|
||||||
import { ref, computed, reactive, onBeforeUnmount, watch } from "vue";
|
ref,
|
||||||
|
computed,
|
||||||
|
reactive,
|
||||||
|
onBeforeUnmount,
|
||||||
|
watch,
|
||||||
|
onMounted,
|
||||||
|
} from "vue";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
import { xkAddXkqdApi, xkListApi, xkXkqdApi } from "@/api/base/server";
|
import {
|
||||||
|
xkAddXkqdApi,
|
||||||
|
xkListApi,
|
||||||
|
xkxkbmInfoApi,
|
||||||
|
xkXkqdApi,
|
||||||
|
} from "@/api/base/server";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const { getUser } = useUserStore();
|
const { getUser } = useUserStore();
|
||||||
const { getData, setKcData } = useDataStore();
|
const { getData, setKcData, setData } = useDataStore();
|
||||||
const { sign_file } = getData;
|
const { sign_file } = getData;
|
||||||
|
|
||||||
// 倒计时相关
|
// 倒计时相关
|
||||||
@ -204,6 +217,11 @@ const kcStatus = ref(false);
|
|||||||
// 添加选课是否已结束的标记
|
// 添加选课是否已结束的标记
|
||||||
const isEnrollmentEnded = ref(false);
|
const isEnrollmentEnded = ref(false);
|
||||||
|
|
||||||
|
// 添加轮询定时器变量
|
||||||
|
let pollTimer: number | null = null;
|
||||||
|
|
||||||
|
const courseInfo = ref({});
|
||||||
|
|
||||||
// 封装检查学生报名状态的通用方法
|
// 封装检查学生报名状态的通用方法
|
||||||
function checkStudentEnrollmentApi(student: any): Promise<boolean> {
|
function checkStudentEnrollmentApi(student: any): Promise<boolean> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -213,16 +231,32 @@ function checkStudentEnrollmentApi(student: any): Promise<boolean> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查kcData是否已加载
|
||||||
|
if (!kcData.value || !kcData.value.id) {
|
||||||
|
console.error("课程数据未加载:", kcData.value);
|
||||||
|
resolve(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 调用选课签到接口检查学生是否已报名
|
// 调用选课签到接口检查学生是否已报名
|
||||||
xkXkqdApi({
|
xkXkqdApi({
|
||||||
njId: student.njId,
|
njId: student.njId,
|
||||||
xsId: student.id,
|
xsId: student.id,
|
||||||
xklxId: "962488654", // 课程类型ID
|
xklxId: "816059832", // 课程类型ID
|
||||||
|
xkId: kcData.value.id,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
console.log(1122, res);
|
||||||
|
|
||||||
// 根据接口返回的result判断是否已报名
|
// 根据接口返回的result判断是否已报名
|
||||||
if (res && res.resultCode === 1) {
|
if (res && res.resultCode === 1) {
|
||||||
resolve(!!res.result); // 转换为布尔值返回
|
setData({
|
||||||
|
...getData,
|
||||||
|
kcData,
|
||||||
|
studentInfo: student,
|
||||||
|
enrolledCourse: res.result,
|
||||||
|
});
|
||||||
|
resolve(res.result.length > 0); // 转换为布尔值返回
|
||||||
} else {
|
} else {
|
||||||
// 接口调用成功但返回错误
|
// 接口调用成功但返回错误
|
||||||
console.warn("检查报名状态接口返回错误:", res);
|
console.warn("检查报名状态接口返回错误:", res);
|
||||||
@ -237,14 +271,76 @@ function checkStudentEnrollmentApi(student: any): Promise<boolean> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 轮询获取课程报名人数
|
||||||
|
const pollEnrollmentCount = () => {
|
||||||
|
xkxkbmInfoApi({ xkId: kcData.value.id })
|
||||||
|
.then((res) => {
|
||||||
|
if (res && res.resultCode === 1 && Array.isArray(res.result)) {
|
||||||
|
updateEnrollmentCount(res.result);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("获取报名人数失败:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新课程报名人数
|
||||||
|
const updateEnrollmentCount = (
|
||||||
|
data: Array<{ xkkcId: string; bmrs: number }>
|
||||||
|
) => {
|
||||||
|
if (!Array.isArray(courseListData.value) || courseListData.value.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let hasUpdates = false;
|
||||||
|
|
||||||
|
courseListData.value.forEach((course) => {
|
||||||
|
const newCount = data.find((item) => item.xkkcId === course.id);
|
||||||
|
if (newCount && course.ybmr !== newCount.bmrs) {
|
||||||
|
course.ybmr = newCount.bmrs;
|
||||||
|
hasUpdates = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果有更新,强制重新渲染列表
|
||||||
|
if (hasUpdates) {
|
||||||
|
courseListData.value = [...courseListData.value];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启动轮询
|
||||||
|
const startPolling = (interval = 5000) => {
|
||||||
|
// 清除可能存在的旧定时器
|
||||||
|
stopPolling();
|
||||||
|
|
||||||
|
// 立即执行一次
|
||||||
|
pollEnrollmentCount();
|
||||||
|
|
||||||
|
// 设置定时器定期执行
|
||||||
|
pollTimer = setInterval(pollEnrollmentCount, interval) as unknown as number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 停止轮询
|
||||||
|
const stopPolling = () => {
|
||||||
|
if (pollTimer) {
|
||||||
|
clearInterval(pollTimer);
|
||||||
|
pollTimer = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 在组件挂载时开始轮询
|
||||||
|
onMounted(() => {
|
||||||
|
// 当课程列表加载完成后启动轮询
|
||||||
|
watch(courseListData, (newVal) => {
|
||||||
|
if (newVal.length > 0 && !pollTimer) {
|
||||||
|
startPolling();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// 页面初始化时检查当前学生是否已报名
|
// 页面初始化时检查当前学生是否已报名
|
||||||
const checkInitialEnrollment = (currentStudent: any) => {
|
const checkInitialEnrollment = (currentStudent: any) => {
|
||||||
if (!currentStudent) return;
|
if (!currentStudent) return;
|
||||||
|
|
||||||
uni.showLoading({
|
|
||||||
title: "加载中...",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 使用封装的API函数检查学生报名状态
|
// 使用封装的API函数检查学生报名状态
|
||||||
checkStudentEnrollmentApi(currentStudent)
|
checkStudentEnrollmentApi(currentStudent)
|
||||||
.then((isEnrolled) => {
|
.then((isEnrolled) => {
|
||||||
@ -253,22 +349,14 @@ const checkInitialEnrollment = (currentStudent: any) => {
|
|||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: `/pages/base/course-selection/enrolled`,
|
url: `/pages/base/course-selection/enrolled`,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
loadCourseList(currentStudent);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
uni.hideLoading();
|
// 检查失败时不做特殊处理,继续正常流程
|
||||||
loadCourseList(currentStudent);
|
console.log("检查学生报名状态失败,继续正常流程");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (studentList.value.length > 0 && studentList.value.length === 1) {
|
|
||||||
currentStudent.value = studentList.value[0];
|
|
||||||
// 检查当前学生是否已报名
|
|
||||||
checkInitialEnrollment(currentStudent.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载课程列表
|
// 加载课程列表
|
||||||
const loadCourseList = (currentStudent: any) => {
|
const loadCourseList = (currentStudent: any) => {
|
||||||
if (!currentStudent) {
|
if (!currentStudent) {
|
||||||
@ -278,10 +366,9 @@ const loadCourseList = (currentStudent: any) => {
|
|||||||
|
|
||||||
xkListApi({
|
xkListApi({
|
||||||
njId: currentStudent.njId,
|
njId: currentStudent.njId,
|
||||||
xklxId: "962488654",
|
xklxId: "816059832",
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
uni.hideLoading();
|
|
||||||
if (res.resultCode == 1) {
|
if (res.resultCode == 1) {
|
||||||
if (res.result) {
|
if (res.result) {
|
||||||
kcData.value = res.result;
|
kcData.value = res.result;
|
||||||
@ -308,11 +395,15 @@ const loadCourseList = (currentStudent: any) => {
|
|||||||
kcStatus.value = true;
|
kcStatus.value = true;
|
||||||
startCountdown(xkjstime);
|
startCountdown(xkjstime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 课程数据加载完成后,检查学生报名状态
|
||||||
|
checkInitialEnrollment(currentStudent);
|
||||||
} else {
|
} else {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: "/pages/base/course-selection/notopen",
|
url: "/pages/base/course-selection/notopen",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
uni.hideLoading();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@ -320,6 +411,15 @@ const loadCourseList = (currentStudent: any) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (studentList.value.length > 0 && studentList.value.length === 1) {
|
||||||
|
currentStudent.value = studentList.value[0];
|
||||||
|
// 先加载课程列表,不立即检查报名状态
|
||||||
|
uni.showLoading({
|
||||||
|
title: "加载中...",
|
||||||
|
});
|
||||||
|
loadCourseList(currentStudent.value);
|
||||||
|
}
|
||||||
|
|
||||||
// 显示学生选择器
|
// 显示学生选择器
|
||||||
function showStudentSelector() {
|
function showStudentSelector() {
|
||||||
if (studentList.value.length > 1) {
|
if (studentList.value.length > 1) {
|
||||||
@ -337,38 +437,14 @@ function switchStudent(student: any) {
|
|||||||
title: "加载中...",
|
title: "加载中...",
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用封装的API函数检查学生是否已报名
|
// 显示切换成功提示
|
||||||
checkStudentEnrollmentApi(student)
|
uni.showToast({
|
||||||
.then((isEnrolled) => {
|
title: `已切换到${student.xm}`,
|
||||||
uni.hideLoading();
|
icon: "none",
|
||||||
|
});
|
||||||
|
|
||||||
if (isEnrolled) {
|
// 先加载当前学生的课程列表,课程数据加载完成后会自动检查报名状态
|
||||||
// 如果已报名,跳转到已报名页面
|
loadCourseList(student);
|
||||||
uni.navigateTo({
|
|
||||||
url: `/pages/base/course-selection/enrolled?studentId=${student.id}`,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 未报名,显示切换成功提示并刷新课程列表
|
|
||||||
uni.showToast({
|
|
||||||
title: `已切换到${student.xm}`,
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 加载当前学生的课程列表
|
|
||||||
loadCourseList(student);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
uni.hideLoading();
|
|
||||||
uni.showToast({
|
|
||||||
title: `已切换到${student.xm}`,
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
console.error("检查学生报名状态出错:", error);
|
|
||||||
|
|
||||||
// 出错时也加载课程列表
|
|
||||||
loadCourseList(student);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动倒计时
|
// 启动倒计时
|
||||||
@ -461,11 +537,25 @@ const displayCourseList = computed(() => {
|
|||||||
// 可修改的课程列表数据
|
// 可修改的课程列表数据
|
||||||
const courseListData = ref<any[]>([]);
|
const courseListData = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 计算已选择的课程数量
|
||||||
|
const selectedCoursesCount = computed(() => {
|
||||||
|
return courseListData.value.filter((course: any) => course.isSelected).length;
|
||||||
|
});
|
||||||
|
|
||||||
// 监听计算属性变化,更新可修改的数据
|
// 监听计算属性变化,更新可修改的数据
|
||||||
watch(
|
watch(
|
||||||
displayCourseList,
|
displayCourseList,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
courseListData.value = JSON.parse(JSON.stringify(newVal));
|
courseListData.value = JSON.parse(JSON.stringify(newVal));
|
||||||
|
|
||||||
|
// 初始化时,将已选课程的全部信息存入courseInfo
|
||||||
|
const selectedCourseIds = uni.getStorageSync("selectedCourseIds") || [];
|
||||||
|
if (selectedCourseIds.length > 0) {
|
||||||
|
const selectedCourses = newVal.filter((course: any) =>
|
||||||
|
selectedCourseIds.includes(course.id)
|
||||||
|
);
|
||||||
|
courseInfo.value = selectedCourses;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
@ -490,23 +580,33 @@ const toggleSelection = (course: any) => {
|
|||||||
courseListData.value[courseIndex].isSelected =
|
courseListData.value[courseIndex].isSelected =
|
||||||
!courseListData.value[courseIndex].isSelected;
|
!courseListData.value[courseIndex].isSelected;
|
||||||
|
|
||||||
// 获取本地存储的已选课程ID数组
|
// 获取所有选中的课程ID
|
||||||
let selectedCourseIds = uni.getStorageSync("selectedCourseIds") || [];
|
const selectedCourseIds = courseListData.value
|
||||||
|
.filter((item: any) => item.isSelected)
|
||||||
|
.map((item: any) => item.id);
|
||||||
|
|
||||||
if (courseListData.value[courseIndex].isSelected) {
|
// 存储选中的课程ID数组
|
||||||
// 添加到已选数组
|
|
||||||
if (!selectedCourseIds.includes(course.id)) {
|
|
||||||
selectedCourseIds.push(course.id);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 从已选数组中移除
|
|
||||||
selectedCourseIds = selectedCourseIds.filter(
|
|
||||||
(id: string) => id !== course.id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新本地存储
|
|
||||||
uni.setStorageSync("selectedCourseIds", selectedCourseIds);
|
uni.setStorageSync("selectedCourseIds", selectedCourseIds);
|
||||||
|
|
||||||
|
// 更新courseInfo为所有选中的课程
|
||||||
|
courseInfo.value = courseListData.value.filter(
|
||||||
|
(item: any) => item.isSelected
|
||||||
|
);
|
||||||
|
|
||||||
|
// 显示提示
|
||||||
|
if (courseListData.value[courseIndex].isSelected) {
|
||||||
|
uni.showToast({
|
||||||
|
title: `已选择 ${course.kcmc}`,
|
||||||
|
icon: "none",
|
||||||
|
duration: 1500,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: `已取消选择 ${course.kcmc}`,
|
||||||
|
icon: "none",
|
||||||
|
duration: 1500,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 查看课程详情
|
// 查看课程详情
|
||||||
@ -561,73 +661,58 @@ const submitRegistration = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查所有选中的课程是否有已满的
|
// 检查选中的课程是否有已满的
|
||||||
const fullCourses = selectedCourses.filter(
|
const fullCourses = selectedCourses.filter(
|
||||||
(course) => course.ybmr >= course.maxNum
|
(course) => course.ybmr >= course.maxNum
|
||||||
);
|
);
|
||||||
if (fullCourses.length > 0) {
|
if (fullCourses.length > 0) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: `"${fullCourses[0].kcmc}"名额已满,请重新选择!`,
|
title: `课程"${fullCourses[0].kcmc}"名额已满,请重新选择!`,
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建课程名称列表用于显示
|
// 构建课程名称列表用于确认弹窗
|
||||||
const courseNames = selectedCourses
|
const courseNames = selectedCourses.map((course) => course.kcmc).join("、");
|
||||||
.map((course) => `"${course.kcmc}"`)
|
|
||||||
.join("、");
|
|
||||||
|
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: "确认报名",
|
title: "确认报名",
|
||||||
content: `您确定要为${currentStudent.value.xm}报名以下课程吗?\n${courseNames}`,
|
content: `您确定要为${currentStudent.value.xm}报名以下课程吗?\n\n${courseNames}`,
|
||||||
success: async (res) => {
|
success: async (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
uni.showLoading({
|
uni.showLoading({
|
||||||
title: "报名中...",
|
title: "报名中...",
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
// 将选中的课程ID用逗号隔开
|
||||||
// 依次提交每个选中的课程
|
const selectedCourseIds = selectedCourses
|
||||||
for (const course of selectedCourses) {
|
.map((course) => course.id)
|
||||||
const result = await xkAddXkqdApi({
|
.join(",");
|
||||||
njId: currentStudent.value.njId,
|
|
||||||
xsId: currentStudent.value.id,
|
|
||||||
xklxId: course.id,
|
|
||||||
sign_file,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.resultCode !== 1) {
|
const res = await xkAddXkqdApi({
|
||||||
throw new Error(
|
xsId: currentStudent.value.id,
|
||||||
`课程"${course.kcmc}"报名失败: ${result.message || "未知错误"}`
|
xkkcId: selectedCourseIds,
|
||||||
);
|
qmFile: sign_file,
|
||||||
}
|
xklxId: "816059832",
|
||||||
}
|
});
|
||||||
|
uni.hideLoading();
|
||||||
// 全部成功报名
|
if (res.resultCode == 1) {
|
||||||
uni.hideLoading();
|
setData({
|
||||||
uni.showToast({
|
...getData,
|
||||||
title: "报名成功!",
|
kcData,
|
||||||
icon: "success",
|
studentInfo: currentStudent.value,
|
||||||
duration: 2000,
|
enrolledCourse: res.result,
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "报名成功",
|
||||||
|
icon: "none",
|
||||||
});
|
});
|
||||||
|
|
||||||
// 清除选课记录
|
|
||||||
uni.removeStorageSync("selectedCourseIds");
|
|
||||||
|
|
||||||
// 延迟后跳转到已报名页面
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: `/pages/base/course-selection/enrolled`,
|
url: `/pages/base/course-selection/enrolled`,
|
||||||
});
|
});
|
||||||
}, 2000);
|
}, 1500);
|
||||||
} catch (error: any) {
|
|
||||||
uni.hideLoading();
|
|
||||||
uni.showToast({
|
|
||||||
title: error.message || "报名失败,请稍后重试",
|
|
||||||
icon: "none",
|
|
||||||
duration: 3000,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -640,11 +725,8 @@ onBeforeUnmount(() => {
|
|||||||
clearInterval(countdownTimer);
|
clearInterval(countdownTimer);
|
||||||
countdownTimer = null;
|
countdownTimer = null;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// 计算已选课程数量
|
stopPolling();
|
||||||
const getSelectedCount = computed(() => {
|
|
||||||
return courseListData.value.filter((course) => course.isSelected).length;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -875,12 +957,6 @@ const getSelectedCount = computed(() => {
|
|||||||
z-index: 10;
|
z-index: 10;
|
||||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
.selected-count-info {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #666;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.register-btn {
|
.register-btn {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
@ -891,12 +967,6 @@ const getSelectedCount = computed(() => {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multi-select-tip {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #909399;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 学生选择器弹窗样式 */
|
/* 学生选择器弹窗样式 */
|
||||||
|
|||||||
@ -31,73 +31,111 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 已报名课程信息 -->
|
<!-- 已报名课程列表 -->
|
||||||
<view class="info-card">
|
<view class="info-card">
|
||||||
<view class="card-title">已报名课程</view>
|
<view class="card-title"
|
||||||
|
>已报名课程 ({{ enrolledCourse.length }}门)</view
|
||||||
|
>
|
||||||
<view class="divider"></view>
|
<view class="divider"></view>
|
||||||
|
|
||||||
<view class="course-info">
|
<!-- 课程列表 -->
|
||||||
<image
|
<view class="course-list">
|
||||||
class="course-image"
|
<view
|
||||||
:src="enrolledCourse.image || '/static/base/home/2211.png'"
|
v-for="(item, index) in enrolledCourse"
|
||||||
mode="aspectFill"
|
:key="item.id"
|
||||||
></image>
|
class="course-item"
|
||||||
<view class="course-details">
|
:class="{ 'last-item': index === enrolledCourse.length - 1 }"
|
||||||
<view class="course-name">{{ enrolledCourse.title }}</view>
|
>
|
||||||
<view class="course-teacher"
|
<view class="course-header">
|
||||||
>开课老师:{{ enrolledCourse.teacher }}</view
|
<view class="course-name">{{ item.title }}</view>
|
||||||
>
|
<view class="course-fee">¥{{ item.fee }}</view>
|
||||||
<view class="course-time">上课时间:{{ enrolledCourse.time }}</view>
|
</view>
|
||||||
<view class="course-location"
|
|
||||||
>上课地点:{{ enrolledCourse.location }}</view
|
|
||||||
>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 报名信息 -->
|
<view class="course-details">
|
||||||
<view class="enrollment-info">
|
<view class="detail-row">
|
||||||
<view class="info-item">
|
<view class="detail-item">
|
||||||
<text class="info-label">报名时间:</text>
|
<u-icon name="account" size="14" color="#666"></u-icon>
|
||||||
<text class="info-value">{{ enrolledCourse.enrollDate }}</text>
|
<text>{{ item.teacher }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-item">
|
<view class="detail-item">
|
||||||
<text class="info-label">课程费用:</text>
|
<u-icon name="clock" size="14" color="#666"></u-icon>
|
||||||
<text class="info-value highlight">¥{{ enrolledCourse.fee }}</text>
|
<text>{{ item.time }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-item">
|
</view>
|
||||||
<text class="info-label">支付状态:</text>
|
|
||||||
<text
|
<view class="detail-row">
|
||||||
class="info-value"
|
<view class="detail-item">
|
||||||
:class="enrolledCourse.isPaid ? 'paid' : 'unpaid'"
|
<u-icon name="map" size="14" color="#666"></u-icon>
|
||||||
>
|
<text>{{ item.location }}</text>
|
||||||
{{ enrolledCourse.isPaid ? "已支付" : "未支付" }}
|
</view>
|
||||||
</text>
|
<view class="detail-item">
|
||||||
|
<u-icon name="calendar" size="14" color="#666"></u-icon>
|
||||||
|
<text>{{ formatDate(item.enrollDate) }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="course-actions" v-if="!isAllPaid">
|
||||||
|
<u-button
|
||||||
|
text="取消报名"
|
||||||
|
size="mini"
|
||||||
|
:plain="true"
|
||||||
|
@click="cancelRegistration(item.id)"
|
||||||
|
></u-button>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 温馨提示 -->
|
<!-- 支付状态卡片 -->
|
||||||
<!-- <view class="notice-card">
|
<view
|
||||||
<view class="notice-title">
|
class="payment-status-card"
|
||||||
<u-icon name="info-circle" size="18" color="#2879FF"></u-icon>
|
:class="{ paid: isAllPaid, unpaid: !isAllPaid }"
|
||||||
<text>温馨提示</text>
|
>
|
||||||
|
<view class="status-header">
|
||||||
|
<view class="status-icon">
|
||||||
|
<u-icon
|
||||||
|
:name="isAllPaid ? 'checkmark-circle' : 'clock'"
|
||||||
|
size="24"
|
||||||
|
:color="isAllPaid ? '#3FBF72' : '#FF9900'"
|
||||||
|
></u-icon>
|
||||||
|
</view>
|
||||||
|
<view class="status-text">
|
||||||
|
<text class="status-title">{{
|
||||||
|
isAllPaid ? "支付完成" : "待支付"
|
||||||
|
}}</text>
|
||||||
|
<text class="status-desc">{{
|
||||||
|
isAllPaid ? "所有课程费用已支付" : "请完成课程费用支付"
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="notice-content">
|
|
||||||
<text>1. 课程一经报名成功,不可取消或更换;</text>
|
<view class="payment-details">
|
||||||
<text>2. 如有特殊情况需要请假,请提前与老师联系;</text>
|
<view class="detail-item">
|
||||||
<text>3. 请按时上课,迟到将影响学习效果。</text>
|
<text class="detail-label">课程总数</text>
|
||||||
|
<text class="detail-value">{{ enrolledCourse.length }}门</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-item">
|
||||||
|
<text class="detail-label">总费用</text>
|
||||||
|
<text class="detail-value amount">¥{{ totalAmount }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-item" v-if="!isAllPaid">
|
||||||
|
<text class="detail-label">待支付</text>
|
||||||
|
<text class="detail-value unpaid-amount">¥{{ totalAmount }}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view> -->
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<view class="bottom-actions" v-if="!enrolledCourse.isPaid">
|
<view class="bottom-actions" v-if="!isAllPaid">
|
||||||
<u-button text="继续支付" type="primary" @click="goPay"></u-button>
|
<view class="payment-info">
|
||||||
<!-- <u-button
|
<text class="payment-label">待支付:</text>
|
||||||
text="返回选课"
|
<text class="payment-amount">¥{{ totalAmount }}</text>
|
||||||
:plain="true"
|
</view>
|
||||||
@click="goBack"
|
<view class="payment-button">
|
||||||
></u-button> -->
|
<u-button text="立即支付" type="primary" @click="goPay"></u-button>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</BasicLayout>
|
</BasicLayout>
|
||||||
@ -106,110 +144,100 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, computed } from "vue";
|
import { ref, onMounted, computed } from "vue";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { xkqddeleteApi } from "@/api/base/server";
|
||||||
|
import { map } from "lodash";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const { getUser } = useUserStore();
|
const { getUser } = useUserStore();
|
||||||
|
|
||||||
// 获取路由参数
|
// 获取路由参数
|
||||||
const studentId = ref("");
|
onMounted(() => {});
|
||||||
onMounted(() => {
|
|
||||||
const pages = getCurrentPages();
|
const useData = useDataStore();
|
||||||
const currentPage = pages[pages.length - 1];
|
const { getData } = storeToRefs(useData);
|
||||||
// @ts-ignore
|
|
||||||
const options = currentPage.$page?.options;
|
|
||||||
if (options && options.studentId) {
|
|
||||||
studentId.value = options.studentId;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 当前学生信息
|
// 当前学生信息
|
||||||
const studentInfo = ref({
|
const studentInfo = ref({
|
||||||
id: "",
|
id: getData.value.studentInfo.id,
|
||||||
xm: "加载中...",
|
xm: getData.value.studentInfo.xm,
|
||||||
njmc: "",
|
njmc: getData.value.studentInfo.njmc,
|
||||||
bjmc: "",
|
bjmc: getData.value.studentInfo.bjmc,
|
||||||
avatar: "",
|
avatar: getData.value.studentInfo.avatar,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 已报名课程信息
|
// 已报名课程信息
|
||||||
const enrolledCourse = ref({
|
const enrolledCourse = ref();
|
||||||
id: "",
|
|
||||||
title: "少儿声乐",
|
enrolledCourse.value = map(getData.value.enrolledCourse, (item) => {
|
||||||
image: "",
|
return {
|
||||||
teacher: "张老师",
|
id: item.id,
|
||||||
time: "每周一 16:00-17:30",
|
title: item.xkmc,
|
||||||
location: "艺术楼 203教室",
|
image: item.image,
|
||||||
enrollDate: "2023-09-15 14:30:45",
|
teacher: item.jsxm,
|
||||||
fee: 420,
|
time: item.studyTime,
|
||||||
isPaid: false,
|
location: item.kcdd,
|
||||||
|
enrollDate: item.createdTime,
|
||||||
|
fee: item.jfje || 0,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取学生信息
|
// 整体支付状态(假设从后端获取或本地存储)
|
||||||
const fetchStudentInfo = () => {
|
const isAllPaid = ref(enrolledCourse.value[0].jfzt == "B"); // 这里可以根据实际业务逻辑设置
|
||||||
// 在实际应用中,这里应该从学生列表中找到对应ID的学生
|
|
||||||
// 或者调用接口获取详细信息
|
|
||||||
const student = getUser.xsList.find((s: any) => s.id === studentId.value);
|
|
||||||
if (student) {
|
|
||||||
studentInfo.value = student;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 添加实际的接口调用
|
// 计算费用汇总
|
||||||
// const url = '/api/student/detail';
|
const totalAmount = computed(() => {
|
||||||
// const params = { studentId: studentId.value };
|
return enrolledCourse.value.reduce(
|
||||||
// return new Promise((resolve) => {
|
(sum: number, course: any) => sum + course.fee,
|
||||||
// // 模拟API调用
|
0
|
||||||
// setTimeout(() => {
|
);
|
||||||
// resolve();
|
});
|
||||||
// }, 500);
|
|
||||||
// });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取已报名课程信息
|
// 格式化日期
|
||||||
const fetchEnrolledCourse = () => {
|
const formatDate = (dateStr: string) => {
|
||||||
// TODO: 添加实际的接口调用
|
if (!dateStr) return "未知";
|
||||||
// const url = '/api/course/enrolled';
|
return dayjs(dateStr).format("YYYY-MM-DD HH:mm");
|
||||||
// const params = { studentId: studentId.value };
|
|
||||||
// return new Promise((resolve) => {
|
|
||||||
// // 模拟API调用
|
|
||||||
// setTimeout(() => {
|
|
||||||
// resolve();
|
|
||||||
// }, 500);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// 模拟数据
|
|
||||||
setTimeout(() => {
|
|
||||||
enrolledCourse.value = {
|
|
||||||
id: "course123",
|
|
||||||
title: "少儿声乐",
|
|
||||||
image: "/static/base/home/2211.png",
|
|
||||||
teacher: "张老师",
|
|
||||||
time: "每周一 16:00-17:30",
|
|
||||||
location: "艺术楼 203教室",
|
|
||||||
enrollDate: "2023-09-15 14:30:45",
|
|
||||||
fee: 420,
|
|
||||||
isPaid: Math.random() > 0.5, // 随机生成支付状态
|
|
||||||
};
|
|
||||||
}, 500);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 去支付
|
// 去支付
|
||||||
const goPay = () => {
|
const goPay = () => {};
|
||||||
uni.navigateTo({
|
|
||||||
url: `/pages/base/course-selection/payment?courseId=${enrolledCourse.value.id}&studentId=${studentId.value}`,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 返回选课页面
|
const cancelRegistration = async (id: string) => {
|
||||||
const goBack = () => {
|
uni.showModal({
|
||||||
uni.navigateBack();
|
title: "确认取消",
|
||||||
|
content: "确定要取消该课程的报名吗?",
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showLoading({ title: "处理中..." });
|
||||||
|
try {
|
||||||
|
await xkqddeleteApi({
|
||||||
|
ids: id,
|
||||||
|
});
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: "取消成功",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: `/pages/base/course-selection/index`,
|
||||||
|
});
|
||||||
|
}, 1500);
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: "取消失败",
|
||||||
|
icon: "error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
uni.showLoading({ title: "加载中..." });
|
|
||||||
|
|
||||||
// 获取学生信息和已报名课程信息
|
|
||||||
Promise.all([fetchStudentInfo(), fetchEnrolledCourse()]).finally(() => {
|
|
||||||
uni.hideLoading();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -217,6 +245,7 @@ onMounted(() => {
|
|||||||
.enrolled-page {
|
.enrolled-page {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
padding-bottom: 80px; /* 为底部固定按钮留出空间 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-card {
|
.status-card {
|
||||||
@ -310,72 +339,151 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-info {
|
.course-list {
|
||||||
display: flex;
|
.course-item {
|
||||||
margin-bottom: 15px;
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
|
||||||
.course-image {
|
&.last-item {
|
||||||
width: 100px;
|
border-bottom: none;
|
||||||
height: 100px;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin-right: 15px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.course-details {
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
.course-name {
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-teacher,
|
.course-header {
|
||||||
.course-time,
|
display: flex;
|
||||||
.course-location {
|
justify-content: space-between;
|
||||||
font-size: 14px;
|
align-items: center;
|
||||||
color: #666;
|
margin-bottom: 12px;
|
||||||
margin-bottom: 5px;
|
|
||||||
|
.course-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-fee {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ff6b01;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-details {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-left: 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
:deep(.u-button) {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.enrollment-info {
|
.payment-status-card {
|
||||||
background-color: #f9f9f9;
|
background-color: #fff;
|
||||||
border-radius: 8px;
|
border-radius: 12px;
|
||||||
padding: 12px;
|
padding: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||||
|
border-left: 4px solid #ddd;
|
||||||
|
|
||||||
.info-item {
|
&.paid {
|
||||||
|
border-left-color: #3fbf72;
|
||||||
|
background: linear-gradient(135deg, #f0f9ff, #e6f7ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.unpaid {
|
||||||
|
border-left-color: #ff9900;
|
||||||
|
background: linear-gradient(135deg, #fff9f0, #fff2e6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
align-items: center;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 15px;
|
||||||
|
|
||||||
&:last-child {
|
.status-icon {
|
||||||
margin-bottom: 0;
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-label {
|
.status-text {
|
||||||
color: #666;
|
flex: 1;
|
||||||
font-size: 14px;
|
|
||||||
|
.status-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-desc {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.info-value {
|
.payment-details {
|
||||||
font-size: 14px;
|
.detail-item {
|
||||||
color: #333;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
&.highlight {
|
&:last-child {
|
||||||
color: #ff6b01;
|
margin-bottom: 0;
|
||||||
font-weight: 500;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.paid {
|
.detail-label {
|
||||||
color: #3fbf72;
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.unpaid {
|
.detail-value {
|
||||||
color: #ff5252;
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
&.amount {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.unpaid-amount {
|
||||||
|
color: #ff5252;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,14 +523,62 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bottom-actions {
|
.bottom-actions {
|
||||||
padding: 15px;
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 12px 20px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
z-index: 100;
|
||||||
|
safe-area-inset-bottom: env(safe-area-inset-bottom);
|
||||||
|
|
||||||
|
.payment-info {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.payment-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-amount {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ff6b01;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-button {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.u-button) {
|
:deep(.u-button) {
|
||||||
flex: 1;
|
width: 120px !important;
|
||||||
margin: 0 5px;
|
height: 40px !important;
|
||||||
|
border-radius: 20px !important;
|
||||||
|
font-size: 15px !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
|
||||||
|
.u-button__text {
|
||||||
|
font-size: 15px !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.u-button--primary {
|
||||||
|
background-color: #2879ff !important;
|
||||||
|
border-color: #2879ff !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -155,14 +155,26 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { navigateTo } from "@/utils/uniapp";
|
import { navigateTo } from "@/utils/uniapp";
|
||||||
import { ref, computed, reactive, onBeforeUnmount, watch, onMounted } from "vue";
|
import {
|
||||||
|
ref,
|
||||||
|
computed,
|
||||||
|
reactive,
|
||||||
|
onBeforeUnmount,
|
||||||
|
watch,
|
||||||
|
onMounted,
|
||||||
|
} from "vue";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
import { xkAddXkqdApi, xkListApi, xkXkqdApi } from "@/api/base/server";
|
import {
|
||||||
|
xkAddXkqdApi,
|
||||||
|
xkListApi,
|
||||||
|
xkxkbmInfoApi,
|
||||||
|
xkXkqdApi,
|
||||||
|
} from "@/api/base/server";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const { getUser } = useUserStore();
|
const { getUser } = useUserStore();
|
||||||
const { getData, setKcData } = useDataStore();
|
const { getData, setKcData, setData } = useDataStore();
|
||||||
const { sign_file } = getData;
|
const { sign_file } = getData;
|
||||||
|
|
||||||
// 倒计时相关
|
// 倒计时相关
|
||||||
@ -204,6 +216,8 @@ const isEnrollmentEnded = ref(false);
|
|||||||
// 添加轮询定时器变量
|
// 添加轮询定时器变量
|
||||||
let pollTimer: number | null = null;
|
let pollTimer: number | null = null;
|
||||||
|
|
||||||
|
const courseInfo = ref({});
|
||||||
|
|
||||||
// 封装检查学生报名状态的通用方法
|
// 封装检查学生报名状态的通用方法
|
||||||
function checkStudentEnrollmentApi(student: any): Promise<boolean> {
|
function checkStudentEnrollmentApi(student: any): Promise<boolean> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -213,16 +227,32 @@ function checkStudentEnrollmentApi(student: any): Promise<boolean> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查kcData是否已加载
|
||||||
|
if (!kcData.value || !kcData.value.id) {
|
||||||
|
console.error("课程数据未加载:", kcData.value);
|
||||||
|
resolve(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 调用选课签到接口检查学生是否已报名
|
// 调用选课签到接口检查学生是否已报名
|
||||||
xkXkqdApi({
|
xkXkqdApi({
|
||||||
njId: student.njId,
|
njId: student.njId,
|
||||||
xsId: student.id,
|
xsId: student.id,
|
||||||
xklxId: "962488654", // 课程类型ID
|
xklxId: "962488654", // 课程类型ID
|
||||||
|
xkId: kcData.value.id,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
console.log(1122,res);
|
||||||
|
|
||||||
// 根据接口返回的result判断是否已报名
|
// 根据接口返回的result判断是否已报名
|
||||||
if (res && res.resultCode === 1) {
|
if (res && res.resultCode === 1) {
|
||||||
resolve(!!res.result); // 转换为布尔值返回
|
setData({
|
||||||
|
...getData,
|
||||||
|
kcData,
|
||||||
|
studentInfo: student,
|
||||||
|
enrolledCourse: res.result,
|
||||||
|
});
|
||||||
|
resolve(res.result.length > 0); // 转换为布尔值返回
|
||||||
} else {
|
} else {
|
||||||
// 接口调用成功但返回错误
|
// 接口调用成功但返回错误
|
||||||
console.warn("检查报名状态接口返回错误:", res);
|
console.warn("检查报名状态接口返回错误:", res);
|
||||||
@ -239,45 +269,34 @@ function checkStudentEnrollmentApi(student: any): Promise<boolean> {
|
|||||||
|
|
||||||
// 轮询获取课程报名人数
|
// 轮询获取课程报名人数
|
||||||
const pollEnrollmentCount = () => {
|
const pollEnrollmentCount = () => {
|
||||||
// 预留接口调用
|
xkxkbmInfoApi({ xkId: kcData.value.id })
|
||||||
// 假设接口名为 getEnrollmentCountApi
|
.then((res) => {
|
||||||
/*
|
if (res && res.resultCode === 1 && Array.isArray(res.result)) {
|
||||||
getEnrollmentCountApi().then(res => {
|
updateEnrollmentCount(res.result);
|
||||||
if (res && res.resultCode === 1 && Array.isArray(res.result)) {
|
}
|
||||||
updateEnrollmentCount(res.result);
|
})
|
||||||
}
|
.catch((error) => {
|
||||||
}).catch(error => {
|
console.error("获取报名人数失败:", error);
|
||||||
console.error('获取报名人数失败:', error);
|
});
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: 接口对接后替换上面注释的代码
|
|
||||||
// console.log('轮询更新报名人数');
|
|
||||||
|
|
||||||
// 模拟数据结构,接口实现后可删除
|
|
||||||
const mockData = [
|
|
||||||
{ id: '111B98397A08E8DA20D', ybmr: 10 },
|
|
||||||
{ id: '74ECFE7249A54FE9B98397A08E8DA20D', ybmr: 15 }
|
|
||||||
];
|
|
||||||
|
|
||||||
// 测试更新逻辑
|
|
||||||
updateEnrollmentCount(mockData);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新课程报名人数
|
// 更新课程报名人数
|
||||||
const updateEnrollmentCount = (data: Array<{id: string, ybmr: number}>) => {
|
const updateEnrollmentCount = (
|
||||||
if (!Array.isArray(courseListData.value) || courseListData.value.length === 0) return;
|
data: Array<{ xkkcId: string; bmrs: number }>
|
||||||
|
) => {
|
||||||
|
if (!Array.isArray(courseListData.value) || courseListData.value.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
let hasUpdates = false;
|
let hasUpdates = false;
|
||||||
|
|
||||||
courseListData.value.forEach(course => {
|
courseListData.value.forEach((course) => {
|
||||||
const newCount = data.find(item => item.id === course.id);
|
const newCount = data.find((item) => item.xkkcId === course.id);
|
||||||
if (newCount && course.ybmr !== newCount.ybmr) {
|
if (newCount && course.ybmr !== newCount.bmrs) {
|
||||||
course.ybmr = newCount.ybmr;
|
course.ybmr = newCount.bmrs;
|
||||||
hasUpdates = true;
|
hasUpdates = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 如果有更新,强制重新渲染列表
|
// 如果有更新,强制重新渲染列表
|
||||||
if (hasUpdates) {
|
if (hasUpdates) {
|
||||||
courseListData.value = [...courseListData.value];
|
courseListData.value = [...courseListData.value];
|
||||||
@ -288,10 +307,10 @@ const updateEnrollmentCount = (data: Array<{id: string, ybmr: number}>) => {
|
|||||||
const startPolling = (interval = 5000) => {
|
const startPolling = (interval = 5000) => {
|
||||||
// 清除可能存在的旧定时器
|
// 清除可能存在的旧定时器
|
||||||
stopPolling();
|
stopPolling();
|
||||||
|
|
||||||
// 立即执行一次
|
// 立即执行一次
|
||||||
pollEnrollmentCount();
|
pollEnrollmentCount();
|
||||||
|
|
||||||
// 设置定时器定期执行
|
// 设置定时器定期执行
|
||||||
pollTimer = setInterval(pollEnrollmentCount, interval) as unknown as number;
|
pollTimer = setInterval(pollEnrollmentCount, interval) as unknown as number;
|
||||||
};
|
};
|
||||||
@ -318,10 +337,6 @@ onMounted(() => {
|
|||||||
const checkInitialEnrollment = (currentStudent: any) => {
|
const checkInitialEnrollment = (currentStudent: any) => {
|
||||||
if (!currentStudent) return;
|
if (!currentStudent) return;
|
||||||
|
|
||||||
uni.showLoading({
|
|
||||||
title: "加载中...",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 使用封装的API函数检查学生报名状态
|
// 使用封装的API函数检查学生报名状态
|
||||||
checkStudentEnrollmentApi(currentStudent)
|
checkStudentEnrollmentApi(currentStudent)
|
||||||
.then((isEnrolled) => {
|
.then((isEnrolled) => {
|
||||||
@ -330,22 +345,14 @@ const checkInitialEnrollment = (currentStudent: any) => {
|
|||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: `/pages/base/course-selection/enrolled`,
|
url: `/pages/base/course-selection/enrolled`,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
loadCourseList(currentStudent);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
uni.hideLoading();
|
// 检查失败时不做特殊处理,继续正常流程
|
||||||
loadCourseList(currentStudent);
|
console.log("检查学生报名状态失败,继续正常流程");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (studentList.value.length > 0 && studentList.value.length === 1) {
|
|
||||||
currentStudent.value = studentList.value[0];
|
|
||||||
// 检查当前学生是否已报名
|
|
||||||
checkInitialEnrollment(currentStudent.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载课程列表
|
// 加载课程列表
|
||||||
const loadCourseList = (currentStudent: any) => {
|
const loadCourseList = (currentStudent: any) => {
|
||||||
if (!currentStudent) {
|
if (!currentStudent) {
|
||||||
@ -358,7 +365,6 @@ const loadCourseList = (currentStudent: any) => {
|
|||||||
xklxId: "962488654",
|
xklxId: "962488654",
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
uni.hideLoading();
|
|
||||||
if (res.resultCode == 1) {
|
if (res.resultCode == 1) {
|
||||||
if (res.result) {
|
if (res.result) {
|
||||||
kcData.value = res.result;
|
kcData.value = res.result;
|
||||||
@ -385,11 +391,15 @@ const loadCourseList = (currentStudent: any) => {
|
|||||||
kcStatus.value = true;
|
kcStatus.value = true;
|
||||||
startCountdown(xkjstime);
|
startCountdown(xkjstime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 课程数据加载完成后,检查学生报名状态
|
||||||
|
checkInitialEnrollment(currentStudent);
|
||||||
} else {
|
} else {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: "/pages/base/course-selection/notopen",
|
url: "/pages/base/course-selection/notopen",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
uni.hideLoading();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@ -397,6 +407,15 @@ const loadCourseList = (currentStudent: any) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (studentList.value.length > 0 && studentList.value.length === 1) {
|
||||||
|
currentStudent.value = studentList.value[0];
|
||||||
|
// 先加载课程列表,不立即检查报名状态
|
||||||
|
uni.showLoading({
|
||||||
|
title: "加载中...",
|
||||||
|
});
|
||||||
|
loadCourseList(currentStudent.value);
|
||||||
|
}
|
||||||
|
|
||||||
// 显示学生选择器
|
// 显示学生选择器
|
||||||
function showStudentSelector() {
|
function showStudentSelector() {
|
||||||
if (studentList.value.length > 1) {
|
if (studentList.value.length > 1) {
|
||||||
@ -414,38 +433,14 @@ function switchStudent(student: any) {
|
|||||||
title: "加载中...",
|
title: "加载中...",
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用封装的API函数检查学生是否已报名
|
// 显示切换成功提示
|
||||||
checkStudentEnrollmentApi(student)
|
uni.showToast({
|
||||||
.then((isEnrolled) => {
|
title: `已切换到${student.xm}`,
|
||||||
uni.hideLoading();
|
icon: "none",
|
||||||
|
});
|
||||||
|
|
||||||
if (isEnrolled) {
|
// 先加载当前学生的课程列表,课程数据加载完成后会自动检查报名状态
|
||||||
// 如果已报名,跳转到已报名页面
|
loadCourseList(student);
|
||||||
uni.navigateTo({
|
|
||||||
url: `/pages/base/course-selection/enrolled?studentId=${student.id}`,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 未报名,显示切换成功提示并刷新课程列表
|
|
||||||
uni.showToast({
|
|
||||||
title: `已切换到${student.xm}`,
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 加载当前学生的课程列表
|
|
||||||
loadCourseList(student);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
uni.hideLoading();
|
|
||||||
uni.showToast({
|
|
||||||
title: `已切换到${student.xm}`,
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
console.error("检查学生报名状态出错:", error);
|
|
||||||
|
|
||||||
// 出错时也加载课程列表
|
|
||||||
loadCourseList(student);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动倒计时
|
// 启动倒计时
|
||||||
@ -543,6 +538,17 @@ watch(
|
|||||||
displayCourseList,
|
displayCourseList,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
courseListData.value = JSON.parse(JSON.stringify(newVal));
|
courseListData.value = JSON.parse(JSON.stringify(newVal));
|
||||||
|
|
||||||
|
// 初始化时,将已选课程的全部信息存入courseInfo
|
||||||
|
const selectedCourseId = uni.getStorageSync("selectedCourseId");
|
||||||
|
if (selectedCourseId) {
|
||||||
|
const selectedCourse = newVal.find(
|
||||||
|
(course: any) => course.id === selectedCourseId
|
||||||
|
);
|
||||||
|
if (selectedCourse) {
|
||||||
|
courseInfo.value = selectedCourse;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
@ -575,6 +581,7 @@ const toggleSelection = (course: any) => {
|
|||||||
courseListData.value[courseIndex].isSelected = true;
|
courseListData.value[courseIndex].isSelected = true;
|
||||||
// 存储当前选中的课程ID
|
// 存储当前选中的课程ID
|
||||||
uni.setStorageSync("selectedCourseId", course.id);
|
uni.setStorageSync("selectedCourseId", course.id);
|
||||||
|
courseInfo.value = course;
|
||||||
} else {
|
} else {
|
||||||
// 取消选择提示
|
// 取消选择提示
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@ -659,36 +666,29 @@ const submitRegistration = () => {
|
|||||||
title: "报名中...",
|
title: "报名中...",
|
||||||
});
|
});
|
||||||
const res = await xkAddXkqdApi({
|
const res = await xkAddXkqdApi({
|
||||||
njId: currentStudent.value.njId,
|
|
||||||
xsId: currentStudent.value.id,
|
xsId: currentStudent.value.id,
|
||||||
xklxId: selectedCourse.id,
|
xkkcId: selectedCourse.id,
|
||||||
sign_file
|
qmFile: sign_file,
|
||||||
|
xklxId: "962488654",
|
||||||
});
|
});
|
||||||
// TODO: 替换为实际的报名接口
|
uni.hideLoading();
|
||||||
// 下面是模拟报名请求
|
if (res.resultCode == 1) {
|
||||||
// setTimeout(() => {
|
setData({
|
||||||
// uni.hideLoading();
|
...getData,
|
||||||
|
kcData,
|
||||||
// // 存储选课信息到全局状态或本地存储
|
studentInfo: currentStudent.value,
|
||||||
// uni.setStorageSync(
|
enrolledCourse: res.result,
|
||||||
// "enrolledCourse",
|
});
|
||||||
// JSON.stringify({
|
uni.showToast({
|
||||||
// courseId: selectedCourse.id,
|
title: "报名成功",
|
||||||
// courseName: selectedCourse.kcmc,
|
icon: "none",
|
||||||
// studentId: currentStudent.value.id,
|
});
|
||||||
// studentName: currentStudent.value.xm,
|
setTimeout(() => {
|
||||||
// enrollTime: new Date().toISOString(),
|
uni.reLaunch({
|
||||||
// // 其他需要传递的信息
|
url: `/pages/base/course-selection/enrolled`,
|
||||||
// fee: selectedCourse.kcje || 0,
|
});
|
||||||
// location: selectedCourse.kcdd || "",
|
}, 1500);
|
||||||
// teacher: selectedCourse.jsName || "",
|
}
|
||||||
// studyTime: selectedCourse.studyTime || "",
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // 跳转到支付页面
|
|
||||||
// navigateTo("/pages/base/course-selection/payment");
|
|
||||||
// }, 1500);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -700,7 +700,7 @@ onBeforeUnmount(() => {
|
|||||||
clearInterval(countdownTimer);
|
clearInterval(countdownTimer);
|
||||||
countdownTimer = null;
|
countdownTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
stopPolling();
|
stopPolling();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasicLayout>
|
<BasicLayout>
|
||||||
<view class="p-15">
|
<view class="p-15">
|
||||||
<view class="white-bg-color p-15 r-md">
|
<view class="white-bg-color p-15 r-md" v-if="notice">
|
||||||
<view> 各位家长:</view>
|
<view> 各位家长:</view>
|
||||||
<view class="notice-text">
|
<view class="notice-text">
|
||||||
随着素质教育的不断深入,学生各项素质、能力的培养越来越受到学校、家庭的重视。我校根据教育局的有关精神,继续举办兴趣班。请各位家长根据实际情况,遵照"孩子自主,家长自愿"的原则,选择兴趣班,请点击下一步确认知晓告知内容。
|
{{ notice }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<BasicSign ref="signCompRef" title="签名"></BasicSign>
|
<BasicSign ref="signCompRef" title="签名"></BasicSign>
|
||||||
@ -25,13 +25,23 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { xkListApi } from "@/api/base/server";
|
import { xkgzsApi } from "@/api/base/server";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { showLoading } from "@/utils/uniapp";
|
||||||
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
|
|
||||||
const signCompRef = ref<any>(null);
|
const signCompRef = ref<any>(null);
|
||||||
const sign_file = ref<any>(null);
|
const sign_file = ref<any>(null);
|
||||||
const { setData, getGlobal } = useDataStore();
|
const { setData, getGlobal } = useDataStore();
|
||||||
|
|
||||||
|
const notice = ref("");
|
||||||
|
onLoad(async () => {
|
||||||
|
showLoading({ title: "加载中..." });
|
||||||
|
const res = await xkgzsApi({ kcLx: "兴趣课" });
|
||||||
|
notice.value = res.rows?.[0]?.content || "";
|
||||||
|
uni.hideLoading();
|
||||||
|
});
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
// 显示加载中
|
// 显示加载中
|
||||||
const data = await signCompRef.value.getSyncSignature();
|
const data = await signCompRef.value.getSyncSignature();
|
||||||
|
|||||||
@ -6,10 +6,10 @@
|
|||||||
<u-icon name="clock" size="22" color="#fff"></u-icon>
|
<u-icon name="clock" size="22" color="#fff"></u-icon>
|
||||||
</view>
|
</view>
|
||||||
<view class="countdown-text">待支付</view>
|
<view class="countdown-text">待支付</view>
|
||||||
<view class="countdown-timer">
|
<!-- <view class="countdown-timer">
|
||||||
<text>剩余:</text>
|
<text>剩余:</text>
|
||||||
<text class="time-value">{{ countdownTime }}</text>
|
<text class="time-value">{{ countdownTime }}</text>
|
||||||
</view>
|
</view> -->
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 学生信息卡片 -->
|
<!-- 学生信息卡片 -->
|
||||||
@ -26,18 +26,11 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="student-details">
|
<view class="student-details">
|
||||||
<view class="student-name">
|
<view class="student-name">
|
||||||
{{ student.name }}
|
{{ student.xm }}
|
||||||
<view class="gender-icon">
|
|
||||||
<u-icon
|
|
||||||
v-if="student.gender === '男'"
|
|
||||||
name="man"
|
|
||||||
color="#2879ff"
|
|
||||||
size="18"
|
|
||||||
></u-icon>
|
|
||||||
<u-icon v-else name="woman" color="#ff6b9d" size="18"></u-icon>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="student-class">{{ student.class }}</view>
|
<view class="student-class"
|
||||||
|
>{{ student.njmc }}{{ student.bjmc }}</view
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -50,15 +43,15 @@
|
|||||||
<view class="course-info">
|
<view class="course-info">
|
||||||
<image
|
<image
|
||||||
class="course-image"
|
class="course-image"
|
||||||
:src="course.image"
|
:src="imagUrl(course.xkkcImg)"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
></image>
|
></image>
|
||||||
<view class="course-details">
|
<view class="course-details">
|
||||||
<view class="course-name">{{ course.title }}</view>
|
<view class="course-name">{{ course.kcmc }}</view>
|
||||||
<view class="course-teacher">开课老师:{{ course.teacher }}</view>
|
<view class="course-teacher">开课老师:{{ course.jsName }}</view>
|
||||||
<view class="course-location">上课地点:{{ course.location }}</view>
|
<view class="course-location">上课地点:{{ course.kcdd }}</view>
|
||||||
<view class="course-price"
|
<view class="course-price"
|
||||||
>金额:<text class="price-value">¥{{ course.price }}</text></view
|
>金额:<text class="price-value">¥{{ course.kcje }}</text></view
|
||||||
>
|
>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -68,7 +61,7 @@
|
|||||||
<view class="payment-footer">
|
<view class="payment-footer">
|
||||||
<view class="total-amount">
|
<view class="total-amount">
|
||||||
<text>总金额:</text>
|
<text>总金额:</text>
|
||||||
<text class="amount-value">¥{{ course.price }}</text>
|
<text class="amount-value">¥{{ course.kcje }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="action-buttons">
|
<view class="action-buttons">
|
||||||
@ -80,52 +73,47 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { xkqddeleteApi } from "@/api/base/server";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { imagUrl } from "@/utils";
|
||||||
import { ref, onMounted, onUnmounted } from "vue";
|
import { ref, onMounted, onUnmounted } from "vue";
|
||||||
|
const useData = useDataStore();
|
||||||
|
const { getData } = storeToRefs(useData);
|
||||||
|
|
||||||
// 倒计时
|
// 倒计时
|
||||||
const countdownTime = ref("1分20秒");
|
// const countdownTime = ref("1分20秒");
|
||||||
let timer: any = null;
|
// let timer: any = null;
|
||||||
let seconds = 1 * 60 + 20; // 1分20秒
|
// let seconds = 1 * 60 + 20; // 1分20秒
|
||||||
|
|
||||||
// 学生信息
|
// 学生信息
|
||||||
const student = ref({
|
const student = ref(getData.value.studentInfo);
|
||||||
name: "何明远",
|
|
||||||
gender: "男",
|
|
||||||
class: "三年级2班",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 课程信息
|
// 课程信息
|
||||||
const course = ref({
|
const course = ref(getData.value.enrolledCourse);
|
||||||
id: 2,
|
console.log(course.value);
|
||||||
title: "机器人创客",
|
|
||||||
teacher: "叶老师",
|
|
||||||
location: "第一教学楼302",
|
|
||||||
price: 142,
|
|
||||||
image: "/static/images/robot-course.jpg",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 开始倒计时
|
// 开始倒计时
|
||||||
const startCountdown = () => {
|
// const startCountdown = () => {
|
||||||
timer = setInterval(() => {
|
// timer = setInterval(() => {
|
||||||
seconds--;
|
// seconds--;
|
||||||
if (seconds <= 0) {
|
// if (seconds <= 0) {
|
||||||
clearInterval(timer);
|
// clearInterval(timer);
|
||||||
uni.showModal({
|
// uni.showModal({
|
||||||
title: "支付超时",
|
// title: "支付超时",
|
||||||
content: "支付已超时,请重新选课",
|
// content: "支付已超时,请重新选课",
|
||||||
showCancel: false,
|
// showCancel: false,
|
||||||
success: () => {
|
// success: () => {
|
||||||
goBack();
|
// goBack();
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const minutes = Math.floor(seconds / 60);
|
// const minutes = Math.floor(seconds / 60);
|
||||||
const remainSeconds = seconds % 60;
|
// const remainSeconds = seconds % 60;
|
||||||
countdownTime.value = `${minutes}分${remainSeconds}秒`;
|
// countdownTime.value = `${minutes}分${remainSeconds}秒`;
|
||||||
}, 1000);
|
// }, 1000);
|
||||||
};
|
// };
|
||||||
|
|
||||||
// 返回上一页
|
// 返回上一页
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
@ -137,8 +125,12 @@ const cancelRegistration = () => {
|
|||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: "取消报名",
|
title: "取消报名",
|
||||||
content: "确定要取消报名吗?",
|
content: "确定要取消报名吗?",
|
||||||
success: (res) => {
|
success: async (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
|
await xkqddeleteApi({
|
||||||
|
id: course.value.id,
|
||||||
|
});
|
||||||
|
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: "已取消报名",
|
title: "已取消报名",
|
||||||
icon: "success",
|
icon: "success",
|
||||||
@ -157,32 +149,27 @@ const payNow = () => {
|
|||||||
title: "支付中...",
|
title: "支付中...",
|
||||||
});
|
});
|
||||||
|
|
||||||
// 模拟支付过程
|
// // 模拟支付过程
|
||||||
setTimeout(() => {
|
// setTimeout(() => {
|
||||||
uni.hideLoading();
|
// uni.hideLoading();
|
||||||
|
|
||||||
uni.redirectTo({
|
// uni.redirectTo({
|
||||||
url: "/pages/base/course-selection/payment-success",
|
// url: "/pages/base/course-selection/payment-success",
|
||||||
});
|
// });
|
||||||
// uni.redirectTo({
|
// // uni.redirectTo({
|
||||||
// url: "/pages/base/course-selection/payment-fail",
|
// // url: "/pages/base/course-selection/payment-fail",
|
||||||
// });
|
// // });
|
||||||
}, 2000);
|
// }, 2000);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
startCountdown();
|
// startCountdown();
|
||||||
|
|
||||||
// 实际应用中,应从页面参数或缓存获取课程和学生信息
|
|
||||||
// const courseId = uni.getStorageSync('selectedCourseId');
|
|
||||||
// const studentId = uni.getStorageSync('currentStudentId');
|
|
||||||
// fetchPaymentInfo(courseId, studentId);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (timer) {
|
// if (timer) {
|
||||||
clearInterval(timer);
|
// clearInterval(timer);
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,61 +1,68 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="home-page">
|
<view class="home-page">
|
||||||
<!-- 自定义导航栏 -->
|
|
||||||
<view class="custom-navbar">
|
|
||||||
<text class="page-title">智慧校园</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="content-container">
|
<view class="content-container">
|
||||||
<!-- 用户信息卡片 -->
|
<!-- 用户信息卡片 -->
|
||||||
<view class="user-info-card">
|
<view class="user-info-card">
|
||||||
<view class="user-avatar-placeholder">
|
<view class="user-content">
|
||||||
<image :src="currentStudent.avatar" class="w-full h-full"></image>
|
<view class="user-avatar">
|
||||||
</view>
|
<image :src="currentStudent.avatar || '/static/base/home/11222.png'" class="avatar-img"></image>
|
||||||
<!-- <view-->
|
<view class="avatar-ring"></view>
|
||||||
<!-- class="user-details"-->
|
</view>
|
||||||
<!-- @click="navigateTo('/pages/system/login/login')"-->
|
<view class="user-details">
|
||||||
<!-- >-->
|
<text class="user-name">{{ currentStudent.name }}</text>
|
||||||
<view
|
<view class="user-class-container">
|
||||||
class="user-details"
|
<view class="class-tag">
|
||||||
>
|
<text class="user-class">{{ currentStudent.grade }} {{ currentStudent.class }}</text>
|
||||||
<text class="user-name">{{ currentStudent.name }}</text>
|
</view>
|
||||||
<view class="user-class-container">
|
</view>
|
||||||
<text class="user-class"
|
</view>
|
||||||
>{{ currentStudent.grade }} {{ currentStudent.class }}</text
|
<view class="switch-btn" @click="showStudentSelector">
|
||||||
>
|
<u-icon name="arrow-down" size="12" color="#fff"></u-icon>
|
||||||
<u-icon name="edit-pen" size="14" color="#909399"></u-icon>
|
<text>切换</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="switch-btn" @click="showStudentSelector">切换</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 学校横幅 -->
|
<!-- 学校横幅 -->
|
||||||
<view class="school-banner">
|
<view class="school-banner">
|
||||||
<view class="banner-placeholder">
|
<view class="banner-content">
|
||||||
<image src="/static/base/home/2211.png" class="w-full h-full"></image>
|
<image src="/static/base/home/2211.png" class="banner-img"></image>
|
||||||
|
<view class="banner-overlay">
|
||||||
|
<view class="banner-text">
|
||||||
|
<text class="banner-title">智慧校园</text>
|
||||||
|
<text class="banner-subtitle">让教育更智能,让成长更精彩</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 功能菜单 -->
|
<!-- 功能菜单 -->
|
||||||
<view class="grid-menu">
|
<view class="menu-section">
|
||||||
<view
|
<view class="section-title">
|
||||||
v-for="(item, index) in menuItems"
|
<text class="title-text">校园服务</text>
|
||||||
:key="index"
|
<view class="title-line"></view>
|
||||||
class="grid-item"
|
</view>
|
||||||
@click="handleMenuClick(item)"
|
<view class="grid-menu">
|
||||||
>
|
<view
|
||||||
<view class="grid-icon-placeholder">
|
v-for="(item, index) in menuItems"
|
||||||
<image :src="item.icon" class="w-full h-full"></image>
|
:key="index"
|
||||||
|
class="grid-item"
|
||||||
|
@click="handleMenuClick(item)"
|
||||||
|
>
|
||||||
|
<view class="grid-icon-container">
|
||||||
|
<view class="icon-background"></view>
|
||||||
|
<image :src="item.icon" class="grid-icon"></image>
|
||||||
|
</view>
|
||||||
|
<text class="grid-text">{{ item.title }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="grid-text">{{ item.title }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 通知公告 -->
|
<!-- 通知公告 -->
|
||||||
<view class="notice-section">
|
<view class="notice-section">
|
||||||
<view class="section-header">
|
<view class="section-title">
|
||||||
<view class="blue-dot"></view>
|
<text class="title-text">通知公告</text>
|
||||||
<text class="section-title">通知公告</text>
|
<view class="title-line"></view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="notice-list">
|
<view class="notice-list">
|
||||||
@ -65,11 +72,18 @@
|
|||||||
class="notice-item"
|
class="notice-item"
|
||||||
@click="navigateTo('/pages/base/home/detail')"
|
@click="navigateTo('/pages/base/home/detail')"
|
||||||
>
|
>
|
||||||
<view class="notice-img-placeholder"></view>
|
<view class="notice-icon">
|
||||||
|
<u-icon name="bell" size="20" color="#4A90E2"></u-icon>
|
||||||
|
</view>
|
||||||
<view class="notice-content">
|
<view class="notice-content">
|
||||||
<text class="notice-title">{{ notice.title }}</text>
|
<text class="notice-title">{{ notice.title }}</text>
|
||||||
<text class="notice-desc">{{ notice.description }}</text>
|
<text class="notice-desc">{{ notice.description }}</text>
|
||||||
<text class="notice-date">{{ notice.date }}</text>
|
<view class="notice-footer">
|
||||||
|
<text class="notice-date">{{ notice.date }}</text>
|
||||||
|
<view class="notice-arrow">
|
||||||
|
<u-icon name="arrow-right" size="12" color="#C8C9CC"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -81,12 +95,14 @@
|
|||||||
:show="showSelector"
|
:show="showSelector"
|
||||||
@close="showSelector = false"
|
@close="showSelector = false"
|
||||||
mode="bottom"
|
mode="bottom"
|
||||||
round="10"
|
round="20"
|
||||||
>
|
>
|
||||||
<view class="student-selector">
|
<view class="student-selector">
|
||||||
<view class="selector-header">
|
<view class="selector-header">
|
||||||
<text class="selector-title">选择学生</text>
|
<text class="selector-title">选择学生</text>
|
||||||
<u-icon name="close" size="20" @click="showSelector = false"></u-icon>
|
<view class="close-btn" @click="showSelector = false">
|
||||||
|
<u-icon name="close" size="18" color="#909399"></u-icon>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="student-list">
|
<view class="student-list">
|
||||||
<view
|
<view
|
||||||
@ -96,19 +112,16 @@
|
|||||||
:class="{ 'student-item-active': currentStudent.id === student.id }"
|
:class="{ 'student-item-active': currentStudent.id === student.id }"
|
||||||
@click="switchStudent(student)"
|
@click="switchStudent(student)"
|
||||||
>
|
>
|
||||||
<view class="student-avatar-placeholder"></view>
|
<view class="student-avatar">
|
||||||
|
<image :src="student.avatar || '/static/base/home/11222.png'" class="avatar-img"></image>
|
||||||
|
</view>
|
||||||
<view class="student-info">
|
<view class="student-info">
|
||||||
<text class="student-name">{{ student.name }}</text>
|
<text class="student-name">{{ student.name }}</text>
|
||||||
<text class="student-class"
|
<text class="student-class">{{ student.grade }} {{ student.class }}</text>
|
||||||
>{{ student.grade }} {{ student.class }}</text
|
</view>
|
||||||
>
|
<view class="check-icon" v-if="currentStudent.id === student.id">
|
||||||
|
<u-icon name="checkmark" color="#4A90E2" size="18"></u-icon>
|
||||||
</view>
|
</view>
|
||||||
<u-icon
|
|
||||||
v-if="currentStudent.id === student.id"
|
|
||||||
name="checkmark"
|
|
||||||
color="#409EFF"
|
|
||||||
size="20"
|
|
||||||
></u-icon>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -117,8 +130,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {navigateTo} from "@/utils/uniapp";
|
import { navigateTo } from "@/utils/uniapp";
|
||||||
import {ref} from "vue";
|
import { ref } from "vue";
|
||||||
// 菜单项数据
|
// 菜单项数据
|
||||||
const menuItems = ref([
|
const menuItems = ref([
|
||||||
{
|
{
|
||||||
@ -236,213 +249,398 @@ function switchStudent(student: any) {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.home-page {
|
.home-page {
|
||||||
background-color: #f8f8f8;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 自定义导航栏 */
|
|
||||||
.custom-navbar {
|
|
||||||
height: 44px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
padding: 0 15px;
|
|
||||||
padding-top: var(--status-bar-height);
|
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
min-height: 100vh;
|
||||||
.page-title {
|
position: relative;
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #303133;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-right {
|
|
||||||
position: absolute;
|
|
||||||
right: 15px;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
height: 44px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-container {
|
.content-container {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 用户信息卡片 */
|
/* 用户信息卡片 */
|
||||||
.user-info-card {
|
.user-info-card {
|
||||||
display: flex;
|
position: relative;
|
||||||
align-items: center;
|
background: linear-gradient(135deg, #ffffff 0%, #f8faff 100%);
|
||||||
background-color: #ffffff;
|
border-radius: 20px;
|
||||||
border-radius: 12px;
|
padding: 20px;
|
||||||
padding: 12px 15px;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 15px;
|
margin-top: 20px;
|
||||||
|
box-shadow: 0 12px 40px rgba(74, 144, 226, 0.25);
|
||||||
.user-avatar-placeholder {
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||||
width: 60px;
|
overflow: hidden;
|
||||||
height: 60px;
|
|
||||||
border-radius: 50%;
|
.user-content {
|
||||||
border: 1px dashed #d0d0d0;
|
display: flex;
|
||||||
flex-shrink: 0;
|
align-items: center;
|
||||||
}
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
.user-details {
|
|
||||||
flex: 1;
|
.user-avatar {
|
||||||
margin-left: 12px;
|
position: relative;
|
||||||
|
width: 70px;
|
||||||
.user-name {
|
height: 70px;
|
||||||
font-size: 16px;
|
border-radius: 50%;
|
||||||
font-weight: 500;
|
overflow: hidden;
|
||||||
color: #303133;
|
box-shadow: 0 4px 16px rgba(74, 144, 226, 0.3);
|
||||||
margin-bottom: 6px;
|
border: 3px solid #ffffff;
|
||||||
}
|
flex-shrink: 0;
|
||||||
|
|
||||||
.user-class-container {
|
.avatar-img {
|
||||||
display: flex;
|
width: 100%;
|
||||||
align-items: center;
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
.user-class {
|
}
|
||||||
font-size: 13px;
|
|
||||||
color: #606266;
|
.avatar-ring {
|
||||||
margin-right: 5px;
|
position: absolute;
|
||||||
|
top: -3px;
|
||||||
|
left: -3px;
|
||||||
|
width: calc(100% + 6px);
|
||||||
|
height: calc(100% + 6px);
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid rgba(74, 144, 226, 0.3);
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-class-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.class-tag {
|
||||||
|
background: linear-gradient(135deg, #4A90E2 0%, #357ABD 100%);
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
box-shadow: 0 2px 8px rgba(74, 144, 226, 0.3);
|
||||||
|
|
||||||
|
.user-class {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background: linear-gradient(135deg, #4A90E2 0%, #357ABD 100%);
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
box-shadow: 0 4px 12px rgba(74, 144, 226, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
flex-shrink: 0;
|
||||||
|
min-width: 60px;
|
||||||
|
height: 16px;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.switch-btn {
|
|
||||||
padding: 4px 12px;
|
|
||||||
background-color: rgba(64, 158, 255, 0.05);
|
|
||||||
color: #409eff;
|
|
||||||
border: 1px solid #409eff;
|
|
||||||
border-radius: 20px;
|
|
||||||
font-size: 13px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 学校横幅 */
|
/* 学校横幅 */
|
||||||
.school-banner {
|
.school-banner {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 25px;
|
||||||
border-radius: 12px;
|
border-radius: 16px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
box-shadow: 0 10px 32px rgba(0, 0, 0, 0.15);
|
||||||
.banner-placeholder {
|
|
||||||
|
.banner-content {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 150px;
|
height: 160px;
|
||||||
border: 1px dashed #d0d0d0;
|
|
||||||
display: flex;
|
.banner-img {
|
||||||
align-items: center;
|
width: 100%;
|
||||||
justify-content: center;
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, rgba(74, 144, 226, 0.8) 0%, rgba(53, 122, 189, 0.9) 100%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.banner-text {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.banner-title {
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 功能菜单 */
|
/* 功能菜单 */
|
||||||
.grid-menu {
|
.menu-section {
|
||||||
display: flex;
|
margin-bottom: 25px;
|
||||||
flex-wrap: wrap;
|
|
||||||
background-color: #ffffff;
|
.section-title {
|
||||||
border-radius: 12px;
|
|
||||||
padding: 10px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.grid-item {
|
|
||||||
width: 33.33%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 15px 0;
|
margin-bottom: 20px;
|
||||||
|
padding: 0 5px;
|
||||||
.grid-icon-placeholder {
|
|
||||||
width: 40px;
|
.title-text {
|
||||||
height: 40px;
|
font-size: 18px;
|
||||||
border-radius: 6px;
|
font-weight: 600;
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-text {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #303133;
|
color: #303133;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 12px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 4px;
|
||||||
|
height: 16px;
|
||||||
|
background: linear-gradient(135deg, #4A90E2 0%, #357ABD 100%);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-line {
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(90deg, #e0e6ed 0%, transparent 100%);
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-menu {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 0;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #f8faff 100%);
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 8px 32px rgba(74, 144, 226, 0.2);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||||
|
|
||||||
|
.grid-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px 10px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 12px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background-color: rgba(74, 144, 226, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-icon-container {
|
||||||
|
position: relative;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.icon-background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: linear-gradient(135deg, #f0f4ff 0%, #e6f0ff 100%);
|
||||||
|
box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-icon {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-text {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 通知公告 */
|
/* 通知公告 */
|
||||||
.notice-section {
|
.notice-section {
|
||||||
.section-header {
|
.section-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 20px;
|
||||||
|
padding: 0 5px;
|
||||||
.blue-dot {
|
|
||||||
width: 8px;
|
.title-text {
|
||||||
height: 8px;
|
font-size: 18px;
|
||||||
border-radius: 50%;
|
font-weight: 600;
|
||||||
background-color: #1976d2;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #303133;
|
color: #303133;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 12px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 4px;
|
||||||
|
height: 16px;
|
||||||
|
background: linear-gradient(135deg, #4A90E2 0%, #357ABD 100%);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-line {
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(90deg, #e0e6ed 0%, transparent 100%);
|
||||||
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice-list {
|
.notice-list {
|
||||||
border-radius: 12px;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.notice-item {
|
.notice-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #ffffff;
|
align-items: flex-start;
|
||||||
padding: 15px;
|
background: linear-gradient(135deg, #ffffff 0%, #f8faff 100%);
|
||||||
margin-bottom: 10px;
|
padding: 18px;
|
||||||
border-radius: 12px;
|
margin-bottom: 12px;
|
||||||
|
border-radius: 16px;
|
||||||
.notice-img-placeholder {
|
box-shadow: 0 8px 24px rgba(74, 144, 226, 0.18);
|
||||||
width: 80px;
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||||
height: 80px;
|
transition: all 0.3s ease;
|
||||||
background-color: #f0f0f0;
|
|
||||||
border: 1px dashed #d0d0d0;
|
&:active {
|
||||||
border-radius: 8px;
|
transform: translateY(-2px);
|
||||||
margin-right: 12px;
|
box-shadow: 0 12px 36px rgba(74, 144, 226, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notice-icon {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
background: linear-gradient(135deg, #f0f4ff 0%, #e6f0ff 100%);
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-right: 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.notice-content {
|
.notice-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
.notice-title {
|
.notice-title {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 1;
|
-webkit-line-clamp: 1;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice-desc {
|
.notice-desc {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #909399;
|
color: #606266;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice-date {
|
.notice-footer {
|
||||||
font-size: 12px;
|
display: flex;
|
||||||
color: #c0c4cc;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.notice-date {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-arrow {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,68 +649,160 @@ function switchStudent(student: any) {
|
|||||||
|
|
||||||
/* 学生选择器弹窗样式 */
|
/* 学生选择器弹窗样式 */
|
||||||
.student-selector {
|
.student-selector {
|
||||||
background-color: #ffffff;
|
background: linear-gradient(135deg, #ffffff 0%, #f8faff 100%);
|
||||||
border-top-left-radius: 12px;
|
border-top-left-radius: 20px;
|
||||||
border-top-right-radius: 12px;
|
border-top-right-radius: 20px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 30px;
|
||||||
|
|
||||||
.selector-header {
|
.selector-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 15px;
|
padding: 20px;
|
||||||
border-bottom: 1px solid #f2f2f2;
|
border-bottom: 1px solid #f0f2f5;
|
||||||
|
|
||||||
.selector-title {
|
.selector-title {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.9);
|
||||||
|
background-color: #e6e8eb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.student-list {
|
.student-list {
|
||||||
padding: 0 15px;
|
padding: 0 20px;
|
||||||
|
|
||||||
.student-item {
|
.student-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 15px 0;
|
padding: 16px 0;
|
||||||
border-bottom: 1px solid #f2f2f2;
|
border-bottom: 1px solid #f5f7fa;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-active {
|
&-active {
|
||||||
background-color: rgba(64, 158, 255, 0.05);
|
background: linear-gradient(135deg, rgba(74, 144, 226, 0.08) 0%, rgba(53, 122, 189, 0.05) 100%);
|
||||||
|
padding: 16px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.student-avatar-placeholder {
|
.student-avatar {
|
||||||
width: 45px;
|
width: 50px;
|
||||||
height: 45px;
|
height: 50px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #f0f0f0;
|
overflow: hidden;
|
||||||
border: 1px dashed #d0d0d0;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15);
|
||||||
|
border: 2px solid #ffffff;
|
||||||
|
|
||||||
|
.avatar-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.student-info {
|
.student-info {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-left: 12px;
|
margin-left: 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
.student-name {
|
.student-name {
|
||||||
font-size: 15px;
|
font-size: 16px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.student-class {
|
.student-class {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #606266;
|
color: #606266;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.check-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #4A90E2 0%, #357ABD 100%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 2px 8px rgba(74, 144, 226, 0.3);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 动画效果 */
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.05);
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式优化 */
|
||||||
|
@media (max-width: 375px) {
|
||||||
|
.content-container {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info-card .user-content .user-avatar {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-menu .grid-item {
|
||||||
|
padding: 15px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="interest-class-page">
|
<view class="interest-class-page">
|
||||||
<u-navbar title="兴趣课" :autoBack="true"></u-navbar>
|
|
||||||
|
|
||||||
<view class="content-container">
|
<view class="content-container">
|
||||||
<!-- 顶部蓝色背景横幅 -->
|
<!-- 顶部蓝色背景横幅 -->
|
||||||
|
|||||||
@ -34,7 +34,6 @@ function toHome(data: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onLoad(async (data: any) => {
|
onLoad(async (data: any) => {
|
||||||
console.log(data);
|
|
||||||
setGlobal(data);
|
setGlobal(data);
|
||||||
if (data && data.openId) {
|
if (data && data.openId) {
|
||||||
checkOpenId({ openId: data.openId, appCode: "JZ" })
|
checkOpenId({ openId: data.openId, appCode: "JZ" })
|
||||||
|
|||||||
@ -112,7 +112,7 @@ import { useDataStore } from "@/store/modules/data";
|
|||||||
const [register, { getValue }] = useForm({
|
const [register, { getValue }] = useForm({
|
||||||
formsProps: { labelWidth: 100 },
|
formsProps: { labelWidth: 100 },
|
||||||
schema: [
|
schema: [
|
||||||
{ title: "监督人信息" },
|
{ title: "监护人信息" },
|
||||||
{
|
{
|
||||||
field: "jzxsgxId",
|
field: "jzxsgxId",
|
||||||
label: "与学生关系",
|
label: "与学生关系",
|
||||||
|
|||||||
@ -1,133 +1,189 @@
|
|||||||
import {AUTH_KEY, BASE_URL, HOMEAGENT, RESULT_CODE_NOT_LOGIN} from "@/config";
|
import { AUTH_KEY, BASE_URL, HOMEAGENT, RESULT_CODE_NOT_LOGIN } from "@/config";
|
||||||
import {useUserStore} from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import {getLogin} from "../permission";
|
import { getLogin } from "../permission";
|
||||||
import {request} from "@/utils/request/request";
|
import { request } from "@/utils/request/request";
|
||||||
import {showToast} from "@/utils/uniapp";
|
import { showToast } from "@/utils/uniapp";
|
||||||
|
|
||||||
let count: boolean = false;
|
let count: boolean = false;
|
||||||
|
|
||||||
function _loginExpiredModal() {
|
function _loginExpiredModal() {
|
||||||
const store = useUserStore();
|
const store = useUserStore();
|
||||||
store.logout()
|
store.logout();
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: "提示",
|
||||||
content: '登录过期,请重新登录',
|
content: "登录过期,请重新登录",
|
||||||
showCancel: false,
|
showCancel: false,
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
count = false
|
count = false;
|
||||||
getLogin()
|
getLogin();
|
||||||
} else if (res.cancel) {
|
} else if (res.cancel) {
|
||||||
count = false
|
count = false;
|
||||||
uni.navigateBack({
|
uni.navigateBack({
|
||||||
delta: 1,
|
delta: 1,
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
console.log(err)
|
console.log(err);
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
baseUrl: process.env.NODE_ENV == 'development' ? HOMEAGENT ? '/base' : BASE_URL : BASE_URL,
|
baseUrl:
|
||||||
header: {}
|
process.env.NODE_ENV == "development"
|
||||||
}
|
? HOMEAGENT
|
||||||
|
? "/base"
|
||||||
|
: BASE_URL
|
||||||
|
: BASE_URL,
|
||||||
|
header: {},
|
||||||
|
};
|
||||||
export const interceptor = {
|
export const interceptor = {
|
||||||
request: (config: UniNamespace.UploadFileOption | UniNamespace.RequestOptions) => {
|
request: (
|
||||||
const store = useUserStore();
|
config: UniNamespace.UploadFileOption | UniNamespace.RequestOptions
|
||||||
if (store.getToken) {
|
) => {
|
||||||
config.header = {
|
const store = useUserStore();
|
||||||
[AUTH_KEY]: store.getToken
|
if (store.getToken) {
|
||||||
};
|
config.header = {
|
||||||
}
|
[AUTH_KEY]: store.getToken,
|
||||||
},
|
};
|
||||||
response: (response: any) => {
|
|
||||||
if (response.data && RESULT_CODE_NOT_LOGIN == response.data.resultCode) {
|
|
||||||
if (!count) {
|
|
||||||
_loginExpiredModal()
|
|
||||||
}
|
|
||||||
count = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (response.config.name === "files") {
|
|
||||||
return JSON.parse(response.data);
|
|
||||||
}
|
|
||||||
if (response.data) {
|
|
||||||
return response.data;
|
|
||||||
} else {
|
|
||||||
console.log('接口无返回值', response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
response: (response: any) => {
|
||||||
|
if (response.data && RESULT_CODE_NOT_LOGIN == response.data.resultCode) {
|
||||||
|
if (!count) {
|
||||||
|
_loginExpiredModal();
|
||||||
|
}
|
||||||
|
count = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (response.config.name === "files") {
|
||||||
|
return JSON.parse(response.data);
|
||||||
|
}
|
||||||
|
if (response.data) {
|
||||||
|
return response.data;
|
||||||
|
} else {
|
||||||
|
console.log("接口无返回值", response);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function get<T = any>(
|
||||||
|
url: string,
|
||||||
|
data?: any,
|
||||||
|
options?: UniNamespace.RequestOptions
|
||||||
|
): Promise<Requests<T>> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request(
|
||||||
|
Object.assign(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
url,
|
||||||
|
data,
|
||||||
|
method: "GET",
|
||||||
|
dataType: "json",
|
||||||
|
responseType: "text",
|
||||||
|
},
|
||||||
|
options
|
||||||
|
)
|
||||||
|
).then((res) => {
|
||||||
|
if (res.resultCode == 1) {
|
||||||
|
resolve(res);
|
||||||
|
} else {
|
||||||
|
if (res.resultCode) {
|
||||||
|
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
||||||
|
showToast(res.message || "接口异常");
|
||||||
|
reject(res);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (res.rows) {
|
||||||
|
resolve(res);
|
||||||
|
} else {
|
||||||
|
showToast(res.message || "接口异常");
|
||||||
|
reject(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get<T = any>(url: string, data?: any, options?: UniNamespace.RequestOptions): Promise<Requests<T>> {
|
export function post<T = any>(
|
||||||
return new Promise((resolve, reject) => {
|
url: string,
|
||||||
request(Object.assign({}, {
|
data?: any,
|
||||||
url,
|
options?: UniNamespace.RequestOptions
|
||||||
data,
|
): Promise<Requests<T>> {
|
||||||
method: 'GET',
|
return new Promise((resolve, reject) => {
|
||||||
dataType: 'json',
|
request(
|
||||||
responseType: 'text',
|
Object.assign(
|
||||||
}, options)).then(res => {
|
{},
|
||||||
if (res.resultCode == 1) {
|
{
|
||||||
resolve(res)
|
url,
|
||||||
} else {
|
data,
|
||||||
if (res.resultCode) {
|
method: "POST",
|
||||||
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
dataType: "json",
|
||||||
showToast(res.message || '接口异常')
|
responseType: "text",
|
||||||
reject(res)
|
},
|
||||||
}
|
options
|
||||||
} else {
|
)
|
||||||
if (res.rows) {
|
).then((res) => {
|
||||||
resolve(res)
|
if (res.resultCode == 1) {
|
||||||
} else {
|
resolve(res);
|
||||||
showToast(res.message || '接口异常')
|
} else {
|
||||||
reject(res)
|
if (res.resultCode) {
|
||||||
}
|
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
||||||
}
|
showToast(res.message || "接口异常");
|
||||||
}
|
reject(res);
|
||||||
})
|
}
|
||||||
})
|
} else {
|
||||||
|
if (res.rows) {
|
||||||
|
resolve(res);
|
||||||
|
} else {
|
||||||
|
showToast(res.message || "接口异常");
|
||||||
|
reject(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function file(
|
||||||
export function post<T = any>(url: string, data?: any, options?: UniNamespace.RequestOptions): Promise<Requests<T>> {
|
url: string,
|
||||||
return new Promise((resolve, reject) => {
|
data: Blob,
|
||||||
request(Object.assign({}, {
|
options?: UniNamespace.UploadFileOption
|
||||||
url,
|
) {
|
||||||
data,
|
return new Promise((resolve, reject) => {
|
||||||
method: 'POST',
|
request(
|
||||||
dataType: 'json',
|
Object.assign(
|
||||||
responseType: 'text',
|
{},
|
||||||
}, options)).then(res => {
|
{
|
||||||
if (res.resultCode == 1) {
|
url,
|
||||||
resolve(res)
|
filePath: data,
|
||||||
} else {
|
name: "files",
|
||||||
if (res.resultCode) {
|
},
|
||||||
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
options
|
||||||
showToast(res.message || '接口异常')
|
),
|
||||||
reject(res)
|
true
|
||||||
}
|
).then((res) => {
|
||||||
} else {
|
if (res.resultCode == 1) {
|
||||||
if (res.rows) {
|
resolve(res);
|
||||||
resolve(res)
|
} else {
|
||||||
} else {
|
if (res.resultCode) {
|
||||||
showToast(res.message || '接口异常')
|
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
||||||
reject(res)
|
showToast(res.message || "接口异常");
|
||||||
}
|
reject(res);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
})
|
if (res.rows) {
|
||||||
})
|
resolve(res);
|
||||||
|
} else {
|
||||||
|
showToast(res.message || "接口异常");
|
||||||
|
reject(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function file(url: string, data: Blob, options?: UniNamespace.UploadFileOption) {
|
|
||||||
return request(Object.assign({}, {
|
|
||||||
url,
|
|
||||||
filePath: data,
|
|
||||||
name: 'files',
|
|
||||||
}, options), true)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user