227 lines
5.1 KiB
Vue
Raw Normal View History

2025-06-29 21:31:05 +08:00
<template>
<view>
<!-- 课程网格列表 -->
<view class="course-grid" v-if="xkkcList.length > 0">
<view
v-for="(xkkc, index) in xkkcList"
:key="xkkc.id || index"
class="course-item"
:class="{ selected: xkkc.isSelected }"
@click="toggleSelection(xkkc)"
>
<view class="course-name">{{ xkkc.kcmc }}</view>
<view class="register-info">
<text>报名情况</text>
<text class="register-count">{{ xkkc.hasNum || 0 }}</text>
<text> | {{ xkkc.maxNum || 0 }}</text>
</view>
<view class="detail-btn" @click.stop="goToDetail(xkkc)"
>详情</view
>
<view v-if="xkkc.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>
</view>
<view class="empty-text">暂无课程数据</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import { useDataStore } from "@/store/modules/data";
const { setKcData } = useDataStore();
// 接收外部传入属性
const props = defineProps<{
xk: any,
canSelected: boolean,
}>();
// 定义一个上级传入的emit响应事件用于接收数据变更
const emit = defineEmits(['change'])
// 学生列表数据
const xkkcList = ref<any>([]);
// 切换选课课程
const toggleSelection = (xkkc: any) => {
if (!props.canSelected) {
return;
}
// 获取本地存储的已选课程ID数组
let selectedXkkcIds = uni.getStorageSync("selectedXkkcIds") || [];
if (xkkc.isSelected) {
// 从已选数组中移除
selectedXkkcIds = selectedXkkcIds.filter(
(id: string) => id !== xkkc.id
);
xkkc.isSelected = false;
// xkkc.hasNum--;
} else {
// 如果是未选中,判断是否已选满
const maxNum = xkkc.maxNum || 0;
const hasNum = xkkc.hasNum || 0;
if (maxNum > hasNum) {
xkkc.isSelected = true;
// 添加到已选数组
if (!selectedXkkcIds.includes(xkkc.id)) {
selectedXkkcIds.push(xkkc.id);
// xkkc.hasNum++;
}
}
}
// 更新本地存储
uni.setStorageSync("selectedXkkcIds", selectedXkkcIds);
emit("change", selectedXkkcIds);
}
const goToDetail = (xkkc: any) => {
setKcData(xkkc);
uni.navigateTo({
url: `/pages/base/course-selection/detail`,
});
};
const switchXk = (xk: any) => {
xkkcList.value = xk.xkkcs;
if (!props.canSelected) {
return;
}
// 获取本地存储的已选课程ID数组
let selectedXkkcIds = uni.getStorageSync("selectedXkkcIds") || [];
let newSelectedXkkcIds = [];
for (let i = 0; i < xkkcList.value.length; i++) {
const xkkc = xkkcList.value[i];
if (selectedXkkcIds.includes(xkkc.id)) {
xkkc.isSelected = true;
newSelectedXkkcIds.push(xkkc.id);
} else {
xkkc.isSelected = false;
}
}
uni.setStorageSync("selectedXkkcIds", newSelectedXkkcIds);
}
// 监听当前学生信息变更
watch(() => props.xk, (newVal) => {
if (newVal && newVal.xkkcs) {
switchXk(newVal);
}
});
// 初始化
if (props.xk && props.xk.xkkcs) {
switchXk(props.xk);
}
</script>
<style lang="scss" scoped>
.course-grid {
display: flex;
flex-wrap: wrap;
padding: 15px 15px 0 15px;
.course-item {
position: relative;
width: calc(50% - 10px);
margin-bottom: 15px;
background-color: #fff;
border-radius: 8px;
padding: 15px;
box-sizing: border-box;
border: 1px solid transparent;
transition: all 0.3s ease;
&:nth-child(odd) {
margin-right: 10px;
}
&:nth-child(even) {
margin-left: 10px;
}
&.selected {
border: 1px solid #3fbf72;
background-color: rgba(63, 191, 114, 0.05);
box-shadow: 0 2px 8px rgba(63, 191, 114, 0.15);
}
.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;
}
}
}
// 暂无数据样式
.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;
}
}
</style>