2025-05-07 09:44:23 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="interest-course">
|
2025-05-16 16:16:41 +08:00
|
|
|
|
<!-- 选课信息头部 - 固定部分 -->
|
2025-05-07 09:44:23 +08:00
|
|
|
|
<view class="selection-header">
|
|
|
|
|
|
<view class="header-content">
|
2025-06-29 19:24:41 +08:00
|
|
|
|
<!-- 选课类型选择部分 -->
|
|
|
|
|
|
<XkPicker xklx-id="816059832" :xs-id="curXs.id" :nj-id="curXs.njId" @change="switchXk" />
|
2025-05-16 16:16:41 +08:00
|
|
|
|
<!-- 学生选择部分 -->
|
2025-06-29 19:24:41 +08:00
|
|
|
|
<XsPicker :is-bar="true" />
|
|
|
|
|
|
<!-- 倒计时-->
|
|
|
|
|
|
<XkCountdown :xk="curXk" @over="xkTimeOver" />
|
2025-05-07 09:44:23 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
2025-05-16 16:16:41 +08:00
|
|
|
|
<!-- 可滚动的内容区域 -->
|
|
|
|
|
|
<view class="scrollable-content">
|
|
|
|
|
|
<!-- 课程网格列表 -->
|
2025-06-29 19:24:41 +08:00
|
|
|
|
<view class="course-grid" v-if="courseListData.length > 0">
|
2025-05-16 16:16:41 +08:00
|
|
|
|
<view
|
2025-06-29 19:24:41 +08:00
|
|
|
|
v-for="(course, index) in courseListData"
|
2025-05-16 16:16:41 +08:00
|
|
|
|
:key="course.id || index"
|
|
|
|
|
|
class="course-item"
|
|
|
|
|
|
:class="{ selected: course.isSelected }"
|
2025-05-07 09:44:23 +08:00
|
|
|
|
>
|
2025-05-16 16:16:41 +08:00
|
|
|
|
<view class="course-name">{{ course.kcmc }}</view>
|
|
|
|
|
|
<view class="register-info">
|
2025-06-29 19:24:41 +08:00
|
|
|
|
<text>上课人数:</text>
|
2025-05-16 16:16:41 +08:00
|
|
|
|
<text class="register-count">{{ course.ybmr }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="detail-btn" @click.stop="viewCourseDetail(course)"
|
|
|
|
|
|
>详情</view
|
|
|
|
|
|
>
|
|
|
|
|
|
<view v-if="course.isSelected" class="selected-mark">
|
|
|
|
|
|
<uni-icons
|
|
|
|
|
|
type="checkbox-filled"
|
|
|
|
|
|
color="#3FBF72"
|
|
|
|
|
|
size="22"
|
|
|
|
|
|
></uni-icons>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 暂无数据提示 -->
|
|
|
|
|
|
<view v-else class="empty-course-list">
|
|
|
|
|
|
<view class="empty-icon">
|
|
|
|
|
|
<u-icon name="list" size="50" color="#C8C9CC"></u-icon>
|
2025-05-07 09:44:23 +08:00
|
|
|
|
</view>
|
2025-05-16 16:16:41 +08:00
|
|
|
|
<view class="empty-text">暂无课程数据</view>
|
2025-05-07 09:44:23 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-06-29 19:24:41 +08:00
|
|
|
|
|
|
|
|
|
|
</view>
|
2025-05-07 09:44:23 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2025-06-29 19:24:41 +08:00
|
|
|
|
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
|
|
|
|
|
|
import XkPicker from "@/pages/base/components/XkPicker/index.vue"
|
|
|
|
|
|
import XkCountdown from "@/pages/base/components/XkCountdown/index.vue"
|
2025-05-16 16:16:41 +08:00
|
|
|
|
import { useUserStore } from "@/store/modules/user";
|
|
|
|
|
|
import { useDataStore } from "@/store/modules/data";
|
|
|
|
|
|
|
2025-06-29 19:24:41 +08:00
|
|
|
|
const { getCurXs } = useUserStore();
|
|
|
|
|
|
const { setKcData } = useDataStore();
|
2025-05-16 16:16:41 +08:00
|
|
|
|
|
2025-06-29 19:24:41 +08:00
|
|
|
|
const curXs = computed(() => getCurXs);
|
2025-05-16 16:16:41 +08:00
|
|
|
|
|
2025-06-29 19:24:41 +08:00
|
|
|
|
const curXk = ref();
|
2025-05-16 16:16:41 +08:00
|
|
|
|
const kcStatus = ref(false);
|
|
|
|
|
|
|
2025-06-29 19:24:41 +08:00
|
|
|
|
const courseInfo = ref<any>({});
|
|
|
|
|
|
// 切换选课
|
|
|
|
|
|
const switchXk = (xk: any) => {
|
|
|
|
|
|
curXk.value = xk;
|
2025-05-16 16:16:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-29 19:24:41 +08:00
|
|
|
|
// 选课时间结束
|
|
|
|
|
|
const xkTimeOver = (val: any) => {
|
|
|
|
|
|
console.log(val);
|
2025-05-16 16:16:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 从课程数据中提取课程列表
|
|
|
|
|
|
const displayCourseList = computed(() => {
|
|
|
|
|
|
if (
|
2025-06-29 19:24:41 +08:00
|
|
|
|
!curXk.value ||
|
|
|
|
|
|
!curXk.value.xkkcs ||
|
|
|
|
|
|
!Array.isArray(curXk.value.xkkcs)
|
2025-05-16 16:16:41 +08:00
|
|
|
|
) {
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取本地存储的已选课程ID数组
|
|
|
|
|
|
const selectedCourseIds = uni.getStorageSync("selectedCourseIds") || [];
|
|
|
|
|
|
|
|
|
|
|
|
// 为课程添加选中状态属性
|
2025-06-29 19:24:41 +08:00
|
|
|
|
return curXk.value.xkkcs.map((course: any) => ({
|
2025-05-16 16:16:41 +08:00
|
|
|
|
...course,
|
|
|
|
|
|
isSelected: selectedCourseIds.includes(course.id),
|
|
|
|
|
|
}));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 可修改的课程列表数据
|
2025-06-29 19:24:41 +08:00
|
|
|
|
const courseListData = ref<any[]>([]);
|
2025-05-16 16:16:41 +08:00
|
|
|
|
|
2025-05-30 17:22:30 +08:00
|
|
|
|
// 计算已选择的课程数量
|
|
|
|
|
|
const selectedCoursesCount = computed(() => {
|
2025-06-29 19:24:41 +08:00
|
|
|
|
return courseListData.value.filter((course: any) => course.isSelected).length;
|
2025-05-30 17:22:30 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-05-16 16:16:41 +08:00
|
|
|
|
// 监听计算属性变化,更新可修改的数据
|
|
|
|
|
|
watch(
|
|
|
|
|
|
displayCourseList,
|
|
|
|
|
|
(newVal) => {
|
2025-06-29 19:24:41 +08:00
|
|
|
|
courseListData.value = JSON.parse(JSON.stringify(newVal));
|
2025-05-30 17:22:30 +08:00
|
|
|
|
|
2025-06-29 19:24:41 +08:00
|
|
|
|
// 初始化时,将已选课程的全部信息存入courseInfo
|
2025-05-30 17:22:30 +08:00
|
|
|
|
const selectedCourseIds = uni.getStorageSync("selectedCourseIds") || [];
|
|
|
|
|
|
if (selectedCourseIds.length > 0) {
|
|
|
|
|
|
const selectedCourses = newVal.filter((course: any) =>
|
|
|
|
|
|
selectedCourseIds.includes(course.id)
|
|
|
|
|
|
);
|
2025-06-29 19:24:41 +08:00
|
|
|
|
courseInfo.value = selectedCourses;
|
2025-05-30 17:22:30 +08:00
|
|
|
|
}
|
2025-05-16 16:16:41 +08:00
|
|
|
|
},
|
|
|
|
|
|
{ immediate: true }
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 查看课程详情
|
|
|
|
|
|
const viewCourseDetail = (course: any) => {
|
|
|
|
|
|
setKcData(course);
|
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
|
url: `/pages/base/course-selection/detail`,
|
2025-05-07 09:44:23 +08:00
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-05-16 16:16:41 +08:00
|
|
|
|
// 页面卸载前清除定时器
|
|
|
|
|
|
onBeforeUnmount(() => {
|
2025-05-07 09:44:23 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.interest-course {
|
2025-05-16 16:16:41 +08:00
|
|
|
|
min-height: 100%;
|
2025-05-07 09:44:23 +08:00
|
|
|
|
background-color: #f5f7fa;
|
2025-05-16 16:16:41 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
overflow: hidden;
|
2025-05-07 09:44:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-bar {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
height: 44px;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
|
|
|
|
|
|
.nav-left {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-title {
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-right {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.selection-header {
|
2025-05-16 16:16:41 +08:00
|
|
|
|
background: linear-gradient(135deg, #4a90e2, #2879ff);
|
2025-05-07 09:44:23 +08:00
|
|
|
|
padding: 20px 15px;
|
2025-05-16 16:16:41 +08:00
|
|
|
|
color: #fff;
|
|
|
|
|
|
border-radius: 0 0 15px 15px;
|
|
|
|
|
|
box-shadow: 0 4px 12px rgba(40, 121, 255, 0.2);
|
|
|
|
|
|
position: sticky;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
z-index: 10;
|
2025-05-07 09:44:23 +08:00
|
|
|
|
|
|
|
|
|
|
.header-content {
|
|
|
|
|
|
display: flex;
|
2025-05-16 16:16:41 +08:00
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 15px;
|
2025-05-07 09:44:23 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
2025-05-16 16:16:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 可滚动内容区域样式
|
|
|
|
|
|
.scrollable-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
-webkit-overflow-scrolling: touch; // 增强iOS滚动体验
|
2025-05-07 09:44:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.course-grid {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
2025-05-16 16:16:41 +08:00
|
|
|
|
padding: 15px 15px 0 15px;
|
2025-05-07 09:44:23 +08:00
|
|
|
|
|
|
|
|
|
|
.course-item {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
width: calc(50% - 10px);
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
box-sizing: border-box;
|
2025-05-16 16:16:41 +08:00
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
|
transition: all 0.3s ease;
|
2025-05-07 09:44:23 +08:00
|
|
|
|
|
|
|
|
|
|
&:nth-child(odd) {
|
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:nth-child(even) {
|
|
|
|
|
|
margin-left: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.selected {
|
|
|
|
|
|
border: 1px solid #3fbf72;
|
2025-05-16 16:16:41 +08:00
|
|
|
|
background-color: rgba(63, 191, 114, 0.05);
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(63, 191, 114, 0.15);
|
2025-05-07 09:44:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.course-name {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.register-info {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
|
|
|
|
.register-count {
|
|
|
|
|
|
color: #2879ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.detail-btn {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
color: #2879ff;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.selected-mark {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: -6px;
|
|
|
|
|
|
right: -6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.register-btn-container {
|
2025-05-16 16:16:41 +08:00
|
|
|
|
position: sticky;
|
2025-05-07 09:44:23 +08:00
|
|
|
|
bottom: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
background-color: #fff;
|
2025-05-16 16:16:41 +08:00
|
|
|
|
z-index: 10;
|
|
|
|
|
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
|
2025-05-07 09:44:23 +08:00
|
|
|
|
.register-btn {
|
|
|
|
|
|
height: 50px;
|
|
|
|
|
|
line-height: 50px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
background-color: #2879ff;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
border-radius: 25px;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
2025-05-16 16:16:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 暂无数据样式
|
|
|
|
|
|
.empty-course-list {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 60px 20px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
|
|
|
|
.empty-icon {
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
background-color: #f5f6f7;
|
|
|
|
|
|
width: 80px;
|
|
|
|
|
|
height: 80px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-text {
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-desc {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
max-width: 80%;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 选课已结束样式 */
|
|
|
|
|
|
.enrollment-ended {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
background-color: rgba(255, 255, 255, 0.2);
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 12px 15px;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
gap: 8px;
|
2025-05-07 09:44:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|