905 lines
23 KiB
Vue
Raw Normal View History

2025-07-30 20:23:38 +08:00
<template>
<view class="interest-course">
<!-- 选课信息头部 - 固定部分 -->
<view class="selection-header">
<view class="header-content">
<view class="title-section" @click="clickShowXkSelector">
<view class="title">
<text v-if="xkData && xkData.xkmc">{{ xkData.xkmc }}</text>
<text v-else>巡查选课</text>
</view>
<view class="switch-btn" v-if="xkList.length > 1">切换</view>
</view>
</view>
</view>
<!-- 可滚动的内容区域 -->
<view class="scrollable-content">
<!-- 课程网格列表 -->
<view class="course-list" v-if="xkkcList && xkkcList.length > 0">
<view
v-for="(xkkc, index) in xkkcList"
:key="xkkc.id || index"
class="course-item"
>
2025-09-19 09:47:19 +08:00
<!-- 巡查状态标识 -->
<view class="course-status" :class="xkkc.sfxc === '是' ? 'status-done' : 'status-pending'">
{{ xkkc.sfxc === '是' ? '已巡查' : '待巡查' }}
2025-07-30 20:23:38 +08:00
</view>
2025-09-19 09:47:19 +08:00
<view class="course-name">{{ xkkc.kcmc }}</view>
<!-- 第一行上课周期开课年级 -->
<view class="course-info-row">
<view class="course-info-item">
<view class="info-label">上课周期</view>
<view class="info-data">{{ xkkc.skzqmc }}</view>
</view>
<view class="course-info-item">
<view class="info-label">开课年级</view>
<view class="info-data">{{ xkkc.njname || '暂无' }}</view>
</view>
2025-09-12 11:20:21 +08:00
</view>
2025-09-19 09:47:19 +08:00
<!-- 第二行授课教师开课地点 -->
<view class="course-info-row">
<view class="course-info-item">
<view class="info-label">授课教师</view>
<view class="info-data">{{ xkkc.jsName || '暂无' }}</view>
</view>
<view class="course-info-item">
<view class="info-label">开课地点</view>
<view class="info-data">{{ xkkc.kcdd }}</view>
</view>
2025-09-06 21:46:10 +08:00
</view>
2025-08-11 21:11:19 +08:00
<view class="separator-line"></view>
2025-07-30 20:23:38 +08:00
<view class="course-btn-group">
<view class="xc-btn" @click.stop="goXc(xkkc)">巡查</view>
2025-08-11 21:11:19 +08:00
<view class="record-btn" @click.stop="goRecord(xkkc)">巡查记录</view>
2025-07-30 20:23:38 +08:00
</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>
<view>
<!-- 选课选择弹窗 -->
<u-popup
:show="showXkFlag"
@close="showXkFlag = false"
mode="bottom"
round="10"
>
<view class="xk-selector">
<view class="selector-header">
<text class="selector-title">选择俱乐部</text>
<u-icon name="close" size="20" @click="showXkFlag = false"></u-icon>
</view>
<view class="xk-list">
<view
v-for="(xk, index) in xkList"
:key="index"
class="xk-item"
:class="{
'xk-item-active': xkData.id === xk.id,
}"
@click="switchXk(xk)"
>
<view class="xk-info">
<text class="xk-name">{{ xk.xkmc }}</text>
<text class="xk-type">{{ xk.xkmc }}</text>
</view>
<u-icon
v-if="xkData.id === xk.id"
name="checkmark"
color="#409EFF"
size="20"
></u-icon>
</view>
</view>
</view>
</u-popup>
</view>
</view>
</template>
<script setup lang="ts">
import { jsdXkListApi } from "@/api/base/server";
2025-09-15 15:36:11 +08:00
import { getXcCourseListApi } from "@/api/base/pbApi";
2025-07-30 20:23:38 +08:00
import { useDataStore } from "@/store/modules/data";
import { useUserStore } from "@/store/modules/user";
import { onBeforeUnmount, onMounted, ref } from "vue";
2025-08-11 21:11:19 +08:00
import dayjs from "dayjs";
2025-07-30 20:23:38 +08:00
const { getJs } = useUserStore();
2025-09-12 11:20:21 +08:00
const dataStore = useDataStore();
2025-07-30 20:23:38 +08:00
const wdNameList = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
2025-09-19 09:47:19 +08:00
// 检查当前时间是否符合课程时间安排
const isCurrentTimeMatch = (xkkc: any) => {
const now = dayjs();
let wDay = now.day();
if (wDay === 0) {
wDay = 7; // 将周日从0改为7
}
let mDay = now.date(); // 当前日期1-31
// 判断周期类型
switch (xkkc.skzqlx) {
case '每天':
return true; // 每天都可以巡查
case '每周':
if (!xkkc.skzq) return false;
const daysOfWeek = xkkc.skzq.split(',').map(Number);
return daysOfWeek.includes(wDay);
case '每月':
if (!xkkc.skzq) return false;
const daysOfMonth = xkkc.skzq.split(',').map(Number);
return daysOfMonth.includes(mDay);
default:
return false;
}
};
2025-07-30 20:23:38 +08:00
// 控制选择器显示状态
const showXkFlag = ref(false);
const xkList = ref<any>([]);
const xkData = ref();
// 课程列表数据
const xkkcList = ref<any[]>([]);
const xcBeforeMinute = ref<number>(0);
onMounted(async () => {
uni.showLoading({
title: "加载中...",
});
2025-09-12 11:20:21 +08:00
// 检查是否从排班页面跳转过来
const pbData = dataStore.getData;
2025-09-19 09:47:19 +08:00
if (pbData && pbData.pbId) {
2025-09-12 11:20:21 +08:00
// 检查是否是课程数据包含kcmc字段
if (pbData.kcmc) {
// 这是课程数据,需要重建排班数据
const reconstructedPbData = {
2025-09-19 09:47:19 +08:00
pbId: pbData.pbId, // 使用pbId作为排班ID
2025-09-12 11:20:21 +08:00
status: 'A',
njIds: pbData.njIds || '',
bjIds: pbData.bjIds || '',
xcbt: pbData.xcbt,
xclx: pbData.xclx,
xqId: pbData.xqId,
xqmc: pbData.xqmc,
xcstime: pbData.xcstime,
xcjstime: pbData.xcjstime,
pk: pbData.pk
};
dataStore.setGlobal(reconstructedPbData);
await loadXcCourseList(reconstructedPbData);
} else {
2025-09-19 09:47:19 +08:00
// 这是排班数据确保有pbId字段
const pbDataWithPbId = {
...pbData,
pbId: pbData.pbId || pbData.id
};
delete pbDataWithPbId.id; // 移除原始的id字段
dataStore.setGlobal(pbDataWithPbId);
await loadXcCourseList(pbDataWithPbId);
2025-09-12 11:20:21 +08:00
}
} else {
// 正常加载课程列表
await loadCourseList();
}
2025-09-19 09:47:19 +08:00
// 监听刷新事件
uni.$on('refreshCourseList', async () => {
console.log('收到刷新事件,重新加载课程列表');
await refreshCourseList();
});
2025-07-30 20:23:38 +08:00
uni.hideLoading();
});
// 加载课程列表
const loadCourseList = async () => {
const res = await jsdXkListApi({
jsId: getJs.id,
});
if (res.resultCode == 1) {
if (res.result && res.result.length) {
xkList.value = res.result;
switchXk(res.result[0]);
} else {
xkList.value = [];
xkData.value = {};
xkkcList.value = [];
}
}
};
2025-09-19 09:47:19 +08:00
// 刷新课程列表
const refreshCourseList = async () => {
try {
uni.showLoading({
title: "刷新中...",
});
// 检查是否有排班数据
const pbData = dataStore.getGlobal;
if (pbData && pbData.pbId) {
// 重新加载巡查课程列表
await loadXcCourseList(pbData);
} else {
// 重新加载普通课程列表
await loadCourseList();
}
uni.hideLoading();
uni.showToast({
title: "刷新成功",
icon: "success",
duration: 1000
});
} catch (error) {
console.error('刷新课程列表失败:', error);
uni.hideLoading();
uni.showToast({
title: "刷新失败",
icon: "none"
});
}
};
2025-09-12 11:20:21 +08:00
// 加载巡查课程列表
const loadXcCourseList = async (pbData: any) => {
try {
const res = await getXcCourseListApi({
jsId: getJs.id,
2025-09-19 09:47:19 +08:00
pbId: pbData.pbId,
2025-09-12 11:20:21 +08:00
xclx: pbData.xclx
});
if (res && res.resultCode == 1) {
const list = res.result || [];
2025-09-19 09:47:19 +08:00
// 先映射数据,然后进行时间过滤
let mappedList = [];
2025-09-12 11:20:21 +08:00
if (pbData.xclx === 'A') {
// 类型A直接使用返回的课程数据
2025-09-19 09:47:19 +08:00
mappedList = list.map((item: any) => ({
2025-09-12 11:20:21 +08:00
id: item.id,
kcmc: item.kcmc,
skzqmc: item.skzqmc || '每周',
skkstime: item.skkstime,
skjstime: item.skjstime,
kcdd: item.kcdd || '暂无',
njname: item.njname || '暂无',
hasNum: item.hasNum || 0,
maxNum: item.maxNum || 0,
skzqlx: item.skzqlx,
skzq: item.skzq,
2025-09-13 18:25:33 +08:00
jsName: item.jsName,
2025-09-19 09:47:19 +08:00
kcjsId: item.kcjsId, // 添加开课教师ID字段
2025-09-13 18:25:33 +08:00
jxjh: item.jxjh, // 添加教学计划字段
2025-09-19 09:47:19 +08:00
jxll: item.jxll, // 添加教学理论字段
pbLxId: item.pbLxId, // 添加排班类型ID字段
sfxc: item.sfxc || '否' // 添加是否巡查字段
2025-09-12 11:20:21 +08:00
}));
} else if (pbData.xclx === 'B') {
// 类型B直接使用返回的课程数据
2025-09-19 09:47:19 +08:00
mappedList = list.map((item: any) => ({
2025-09-12 11:20:21 +08:00
id: item.id,
kcmc: item.kcmc,
skzqmc: item.skzqmc || '每周',
skkstime: item.skkstime,
skjstime: item.skjstime,
kcdd: item.kcdd || '暂无',
njname: item.njname || '暂无',
hasNum: item.hasNum || 0,
maxNum: item.maxNum || 0,
skzqlx: item.skzqlx,
skzq: item.skzq,
2025-09-13 18:25:33 +08:00
jsName: item.jsName,
2025-09-19 09:47:19 +08:00
kcjsId: item.kcjsId || item.jsId, // 添加开课教师ID字段
2025-09-13 18:25:33 +08:00
jxjh: item.jxjh, // 添加教学计划字段
2025-09-19 09:47:19 +08:00
jxll: item.jxll, // 添加教学理论字段
pbLxId: item.pbLxId, // 添加排班类型ID字段
sfxc: item.sfxc || '否' // 添加是否巡查字段
2025-09-12 11:20:21 +08:00
}));
}
2025-09-19 09:47:19 +08:00
// 过滤出当前时间符合的课程
xkkcList.value = mappedList.filter((xkkc: any) => isCurrentTimeMatch(xkkc));
2025-09-12 11:20:21 +08:00
// 处理课程周期显示
for (let i = 0; i < xkkcList.value.length; i++) {
let xkkc = xkkcList.value[i];
// 判断周期
switch (xkkc.skzqlx) {
case '每天':
xkkc.skzqmc = "每天";
break;
case '每周':
const daysOfWeek = xkkc.skzq.split(',').map(Number);
// 从wdNameList读取daysOfWeek对应的周几
xkkc.skzqmc = daysOfWeek.map((day: number) => wdNameList[day - 1]).join(',');
break;
case '每月':
const daysOfMonth = xkkc.skzq.split(',').map(Number);
// 从根据编号加
xkkc.skzqmc = daysOfMonth.map((day: number) => day + "号").join(',');
break;
}
}
} else {
xkkcList.value = [];
uni.showToast({
title: (res as any).resultMessage || '获取巡查课程失败',
icon: 'none'
});
}
} catch (error) {
console.error('加载巡查课程失败:', error);
xkkcList.value = [];
uni.showToast({
title: '加载巡查课程失败',
icon: 'none'
});
}
};
2025-07-30 20:23:38 +08:00
// 显示选课选择器
function clickShowXkSelector() {
if (xkList.value.length > 1) {
showXkFlag.value = true;
}
}
// 切换选课
function switchXk(xk: any) {
xkData.value = xk;
xkkcList.value = xk.xkkcs;
showXkFlag.value = false;
for (let i = 0; i < xk.xkkcs.length; i++) {
let xkkc = xk.xkkcs[i];
// 判断周期
switch (xkkc.skzqlx) {
case "每天":
xkkc.skzqmc = "每天";
break;
case "每周":
const daysOfWeek = xkkc.skzq.split(",").map(Number);
xkkc.skzqmc = daysOfWeek
.map((day: number) => wdNameList[day - 1])
.join(",");
break;
case "每月":
const daysOfMonth = xkkc.skzq.split(",").map(Number);
xkkc.skzqmc = daysOfMonth.map((day: number) => day + "号").join(",");
break;
}
}
// 显示切换成功提示
uni.showToast({
title: `已切换到${xk.xkmc}`,
icon: "none",
});
}
// 跳转到巡查
const goXc = (xkkc: any) => {
2025-09-12 11:20:21 +08:00
// 直接从global获取排班数据
const pbData = dataStore.getGlobal;
// 检查排班数据是否有效
2025-09-19 09:47:19 +08:00
if (!pbData || !pbData.pbId || !pbData.xcbt) {
2025-09-13 18:25:33 +08:00
console.log('排班数据检查失败:', pbData);
2025-09-12 11:20:21 +08:00
uni.showToast({
title: '数据异常,请重新选择排班',
icon: 'none'
});
return;
}
// 合并排班数据和课程数据
const combinedData = {
...xkkc,
id: xkkc.id, // 课程记录ID
2025-09-19 09:47:19 +08:00
pbId: pbData.pbId, // 排班ID - 确保使用正确的排班ID
pbLxId: xkkc.pbLxId || pbData.pbLxId, // 传递 pbLxId优先使用课程中的 pbLxId
kcjsId: xkkc.kcjsId , // 传递开课教师ID
2025-09-12 11:20:21 +08:00
xclx: pbData.xclx,
xcbt: pbData.xcbt,
xqmc: pbData.xqmc
};
2025-09-19 09:47:19 +08:00
2025-09-12 11:20:21 +08:00
dataStore.setData(combinedData);
2025-07-30 20:23:38 +08:00
uni.navigateTo({
url: `/pages/view/routine/kefuxuncha/xcXkkcDetail`,
});
};
2025-08-11 21:11:19 +08:00
// 跳转到巡查记录
const goRecord = (xkkc: any) => {
2025-09-12 11:20:21 +08:00
// 直接从global获取排班数据
const pbData = dataStore.getGlobal;
// 检查排班数据是否有效
2025-09-19 09:47:19 +08:00
if (!pbData || !pbData.pbId || !pbData.xcbt) {
2025-09-13 18:25:33 +08:00
console.log('排班数据检查失败:', pbData);
2025-09-12 11:20:21 +08:00
uni.showToast({
title: '数据异常,请重新选择排班',
icon: 'none'
});
return;
}
// 合并排班数据和课程数据
const combinedData = {
...xkkc,
id: xkkc.id, // 课程记录ID
2025-09-19 09:47:19 +08:00
pbId: pbData.pbId, // 排班ID - 确保使用正确的排班ID
2025-09-12 11:20:21 +08:00
xclx: pbData.xclx,
xcbt: pbData.xcbt,
xqmc: pbData.xqmc
};
dataStore.setData(combinedData);
2025-08-11 21:11:19 +08:00
uni.navigateTo({
url: `/pages/view/routine/kefuxuncha/xcRecord`,
});
};
// 格式化课程时间
const formatClassTime = (startTime: string, endTime: string) => {
if (!startTime || !endTime) {
return '';
}
try {
// 尝试解析时间,支持多种格式
let start, end;
// 如果是时间格式HH:mm:ss 或 HH:mm
if (startTime.includes(':') && !startTime.includes('-') && !startTime.includes('/')) {
start = startTime;
end = endTime;
} else {
// 尝试用 dayjs 解析
const startDate = dayjs(startTime);
const endDate = dayjs(endTime);
if (startDate.isValid() && endDate.isValid()) {
start = startDate.format('HH:mm:ss');
end = endDate.format('HH:mm:ss');
} else {
// 如果解析失败,直接返回原始值
return `${startTime}~${endTime}`;
}
}
return `${start}~${end}`;
} catch (error) {
console.error('时间格式化错误:', error);
// 如果出错,返回原始值
return `${startTime}~${endTime}`;
}
};
2025-09-19 09:47:19 +08:00
// 页面卸载前清除定时器和事件监听器
onBeforeUnmount(() => {
// 移除事件监听器
uni.$off('refreshCourseList');
});
2025-07-30 20:23:38 +08:00
</script>
<style lang="scss" scoped>
.interest-course {
min-height: 100%;
2025-08-11 21:11:19 +08:00
background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);
2025-07-30 20:23:38 +08:00
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
.selection-header {
2025-08-11 21:11:19 +08:00
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 25px 20px;
2025-07-30 20:23:38 +08:00
color: #fff;
2025-08-11 21:11:19 +08:00
border-radius: 0 0 20px 20px;
box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
2025-07-30 20:23:38 +08:00
position: sticky;
top: 0;
left: 0;
right: 0;
z-index: 10;
2025-08-11 21:11:19 +08:00
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, rgba(255, 255, 255, 0.1) 0%, transparent 50%, rgba(255, 255, 255, 0.05) 100%);
pointer-events: none;
}
2025-07-30 20:23:38 +08:00
.header-content {
display: flex;
flex-direction: column;
gap: 15px;
2025-08-11 21:11:19 +08:00
position: relative;
z-index: 1;
2025-07-30 20:23:38 +08:00
.title-section {
display: flex;
align-items: center;
2025-08-11 21:11:19 +08:00
justify-content: space-between;
cursor: pointer;
2025-07-30 20:23:38 +08:00
.title {
2025-08-11 21:11:19 +08:00
font-size: 20px;
font-weight: 700;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
letter-spacing: 0.5px;
2025-07-30 20:23:38 +08:00
}
.switch-btn {
2025-08-11 21:11:19 +08:00
padding: 8px 16px;
2025-07-30 20:23:38 +08:00
background-color: rgba(255, 255, 255, 0.2);
color: #fff;
2025-08-11 21:11:19 +08:00
border-radius: 20px;
font-size: 14px;
font-weight: 500;
transition: all 0.3s ease;
&:hover {
background-color: rgba(255, 255, 255, 0.3);
transform: translateY(-1px);
}
2025-07-30 20:23:38 +08:00
}
}
}
}
// 可滚动内容区域样式
.scrollable-content {
flex: 1;
overflow-y: auto;
2025-08-11 21:11:19 +08:00
-webkit-overflow-scrolling: touch; // 增强iOS滚动体验
2025-07-30 20:23:38 +08:00
}
.course-list {
padding: 15px 15px 0 15px;
.course-item {
position: relative;
width: 100%;
2025-08-11 21:11:19 +08:00
margin-bottom: 20px;
2025-07-30 20:23:38 +08:00
background-color: #fff;
2025-08-11 21:11:19 +08:00
border-radius: 12px;
padding: 20px;
2025-07-30 20:23:38 +08:00
box-sizing: border-box;
2025-08-11 21:11:19 +08:00
border: 1px solid #f0f0f0;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
animation: fadeInUp 0.6s ease-out;
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
border-color: #e8e8e8;
}
2025-07-30 20:23:38 +08:00
&.selected {
2025-08-11 21:11:19 +08:00
border: 2px solid #3fbf72;
background-color: rgba(63, 191, 114, 0.02);
box-shadow: 0 4px 20px rgba(63, 191, 114, 0.15);
2025-07-30 20:23:38 +08:00
}
2025-09-19 09:47:19 +08:00
.course-status {
position: absolute;
top: 15px;
right: 15px;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
z-index: 2;
animation: fadeInRight 0.5s ease-out 0.2s both;
&.status-done {
background: linear-gradient(135deg, #67c23a, #85ce61);
color: #fff;
box-shadow: 0 2px 8px rgba(103, 194, 58, 0.3);
}
&.status-pending {
background: linear-gradient(135deg, #e6a23c, #f0c78a);
color: #fff;
box-shadow: 0 2px 8px rgba(230, 162, 60, 0.3);
}
}
2025-07-30 20:23:38 +08:00
.course-name {
2025-08-11 21:11:19 +08:00
font-size: 17px;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 15px;
line-height: 1.4;
animation: fadeInLeft 0.5s ease-out 0.1s both;
2025-09-19 09:47:19 +08:00
padding-right: 80px; // 为状态标识留出空间
2025-07-30 20:23:38 +08:00
}
.course-btn-group {
display: flex;
2025-08-11 21:11:19 +08:00
justify-content: flex-end;
gap: 10px; // Added gap for spacing between buttons
2025-07-30 20:23:38 +08:00
.xc-btn {
display: inline-block;
2025-08-11 21:11:19 +08:00
color: #ff6b35;
2025-07-30 20:23:38 +08:00
font-size: 14px;
2025-08-11 21:11:19 +08:00
font-weight: 600;
padding: 8px 18px;
border-radius: 8px;
background: linear-gradient(135deg, rgba(255, 107, 53, 0.1), rgba(255, 107, 53, 0.05));
border: 1px solid #ff6b35;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 2px 8px rgba(255, 107, 53, 0.15);
animation: fadeInUp 0.5s ease-out 0.3s both;
&:hover {
background: linear-gradient(135deg, rgba(255, 107, 53, 0.15), rgba(255, 107, 53, 0.1));
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(255, 107, 53, 0.25);
}
&:active {
background: linear-gradient(135deg, rgba(255, 107, 53, 0.2), rgba(255, 107, 53, 0.15));
transform: translateY(0);
box-shadow: 0 2px 8px rgba(255, 107, 53, 0.2);
}
}
.record-btn {
display: inline-block;
color: #409EFF;
font-size: 14px;
font-weight: 600;
padding: 8px 18px;
border-radius: 8px;
background: linear-gradient(135deg, rgba(64, 158, 255, 0.1), rgba(64, 158, 255, 0.05));
border: 1px solid #409EFF;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
animation: fadeInUp 0.5s ease-out 0.3s both;
&:hover {
background: linear-gradient(135deg, rgba(64, 158, 255, 0.15), rgba(64, 158, 255, 0.1));
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(64, 158, 255, 0.25);
}
&:active {
background: linear-gradient(135deg, rgba(64, 158, 255, 0.2), rgba(64, 158, 255, 0.15));
transform: translateY(0);
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}
2025-07-30 20:23:38 +08:00
}
}
2025-09-19 09:47:19 +08:00
.course-info-row {
2025-07-30 20:23:38 +08:00
display: flex;
2025-08-11 21:11:19 +08:00
margin-bottom: 14px;
2025-09-19 09:47:19 +08:00
gap: 20px;
animation: fadeInUp 0.5s ease-out 0.15s both;
}
.course-info-item {
display: flex;
flex: 1;
2025-08-11 21:11:19 +08:00
font-size: 13px;
align-items: center;
2025-07-30 20:23:38 +08:00
.info-label {
2025-08-11 21:11:19 +08:00
color: #666;
2025-09-19 09:47:19 +08:00
flex: 0 0 70px;
2025-08-11 21:11:19 +08:00
font-weight: 500;
2025-09-19 09:47:19 +08:00
margin-right: 5px;
2025-07-30 20:23:38 +08:00
}
.info-data {
2025-09-19 09:47:19 +08:00
flex: 1;
2025-08-11 21:11:19 +08:00
color: #333;
font-weight: 400;
2025-09-19 09:47:19 +08:00
word-break: break-all;
2025-07-30 20:23:38 +08:00
}
}
2025-08-11 21:11:19 +08:00
.separator-line {
height: 1px;
background: linear-gradient(90deg, transparent, #e8e8e8, transparent);
margin: 18px 0;
opacity: 0.8;
animation: fadeIn 0.5s ease-out 0.25s both;
}
}
}
// 添加动画关键帧
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInLeft {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
2025-07-30 20:23:38 +08:00
}
}
2025-08-11 21:11:19 +08:00
@keyframes fadeInRight {
from {
opacity: 0;
transform: translateX(20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* 全局图片样式 */
.w-full {
width: 100%;
}
.h-full {
height: 100%;
}
// 暂无数据样式
.empty-course-list {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 80px 20px;
text-align: center;
.empty-icon {
margin-bottom: 25px;
background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
width: 90px;
height: 90px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
border: 2px solid rgba(255, 255, 255, 0.8);
}
.empty-text {
font-size: 18px;
font-weight: 600;
color: #475569;
margin-bottom: 8px;
letter-spacing: 0.3px;
}
.empty-desc {
font-size: 14px;
color: #64748b;
max-width: 80%;
line-height: 1.6;
}
}
/* 选课选择弹窗样式 */
2025-07-30 20:23:38 +08:00
.xk-selector {
background-color: #ffffff;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
padding-bottom: 20px;
.selector-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
border-bottom: 1px solid #f2f2f2;
.selector-title {
font-size: 16px;
font-weight: 500;
color: #303133;
}
}
.xk-list {
padding: 0 15px;
.xk-item {
display: flex;
align-items: center;
padding: 15px 0;
border-bottom: 1px solid #f2f2f2;
2025-08-11 21:11:19 +08:00
transition: all 0.3s ease;
2025-07-30 20:23:38 +08:00
&:last-child {
border-bottom: none;
}
&-active {
background-color: rgba(64, 158, 255, 0.05);
}
2025-08-11 21:11:19 +08:00
&:hover {
background-color: rgba(64, 158, 255, 0.02);
}
2025-07-30 20:23:38 +08:00
.xk-info {
flex: 1;
margin-left: 12px;
.xk-name {
font-size: 15px;
font-weight: 500;
color: #303133;
margin-bottom: 4px;
}
.xk-type {
font-size: 13px;
color: #303133;
margin-bottom: 4px;
}
.xk-class {
font-size: 13px;
color: #606266;
}
}
}
}
}
</style>