完整的教务系统前端项目 - 包含所有修复和9月份数据
This commit is contained in:
167
src/components/CourseList/index.jsx
Normal file
167
src/components/CourseList/index.jsx
Normal file
@@ -0,0 +1,167 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Collapse, Timeline, Spin } from "@arco-design/web-react";
|
||||
import { getCourseLiveList } from "@/services/courseLive";
|
||||
import "./index.css";
|
||||
|
||||
const TimelineItem = Timeline.Item;
|
||||
const CollapseItem = Collapse.Item;
|
||||
|
||||
const CourseList = ({ className = "", onCourseClick }) => {
|
||||
const [courseLiveList, setCourseLiveList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [selectedCourseId, setSelectedCourseId] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchCourseList();
|
||||
}, []);
|
||||
|
||||
const fetchCourseList = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await getCourseLiveList();
|
||||
if (res.success) {
|
||||
const courseList = res.data || [];
|
||||
setCourseLiveList(courseList);
|
||||
|
||||
// 设置默认选中今天的课程(如果有)
|
||||
const todayStr = new Date().toISOString().split('T')[0];
|
||||
let foundTodayCourse = false;
|
||||
|
||||
for (const unit of courseList) {
|
||||
const todayCourse = unit.courses.find(c => c.date === todayStr);
|
||||
if (todayCourse) {
|
||||
setSelectedCourseId(todayCourse.courseId);
|
||||
// 触发课程选择事件
|
||||
if (onCourseClick) {
|
||||
onCourseClick({
|
||||
...todayCourse,
|
||||
unitName: unit.unitName
|
||||
});
|
||||
}
|
||||
foundTodayCourse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有今天的课程,选中第一个current或upcoming的课程
|
||||
if (!foundTodayCourse) {
|
||||
for (const unit of courseList) {
|
||||
const activeCourse = unit.courses.find(c => c.current || c.upcoming);
|
||||
if (activeCourse) {
|
||||
setSelectedCourseId(activeCourse.courseId);
|
||||
if (onCourseClick) {
|
||||
onCourseClick({
|
||||
...activeCourse,
|
||||
unitName: unit.unitName
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取课程列表失败:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 判断课程状态
|
||||
const getCourseStatus = (course) => {
|
||||
if (course.completed) return "finish";
|
||||
if (course.current) return "active";
|
||||
|
||||
// 判断未来课程的具体状态
|
||||
if (course.upcoming) {
|
||||
const courseDate = new Date(course.date);
|
||||
const today = new Date();
|
||||
|
||||
// 重置时间部分只比较日期
|
||||
courseDate.setHours(0, 0, 0, 0);
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
const timeDiff = courseDate - today;
|
||||
const daysDiff = Math.floor(timeDiff / (24 * 60 * 60 * 1000));
|
||||
|
||||
// 未来7天内的课程显示为"即将开始"
|
||||
if (daysDiff > 0 && daysDiff <= 7) {
|
||||
return "coming";
|
||||
}
|
||||
// 7天后的课程显示为"未开始"
|
||||
return "not-started";
|
||||
}
|
||||
|
||||
// 默认状态
|
||||
return "pending";
|
||||
};
|
||||
|
||||
// 获取图标类型
|
||||
const getDotIcon = (course) => {
|
||||
if (course.completed) return <div className="time-line-dot-icon" />;
|
||||
if (course.current) return <div className="time-line-clock-icon" />;
|
||||
return <div className="time-line-lock-icon" />;
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className={`${className} course-list-wrapper`}>
|
||||
<p className="course-list-title">课程列表</p>
|
||||
<div className="course-list-content">
|
||||
<Spin />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${className} course-list-wrapper`}>
|
||||
<p className="course-list-title">课程列表</p>
|
||||
<div className="course-list-content">
|
||||
<Collapse
|
||||
lazyload
|
||||
className="course-list"
|
||||
bordered={false}
|
||||
expandIconPosition="right"
|
||||
defaultActiveKey={["1"]}
|
||||
>
|
||||
{courseLiveList.map((unit, index) => (
|
||||
<CollapseItem
|
||||
key={unit.unitId}
|
||||
header={unit.unitName}
|
||||
name={String(index + 1)}
|
||||
className="course-list-item"
|
||||
>
|
||||
<Timeline>
|
||||
{unit.courses.map((course) => (
|
||||
<TimelineItem
|
||||
key={course.courseId}
|
||||
dot={getDotIcon(course)}
|
||||
lineType="dashed"
|
||||
>
|
||||
<div
|
||||
className={`time-line-item ${getCourseStatus(course)} ${selectedCourseId === course.courseId ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setSelectedCourseId(course.courseId);
|
||||
onCourseClick && onCourseClick({ ...course, unitName: unit.unitName });
|
||||
}}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<p>{course.courseName}</p>
|
||||
<div className="time-line-item-info">
|
||||
<span>{course.teacherName}</span>
|
||||
<span>{course.date}</span>
|
||||
</div>
|
||||
</div>
|
||||
</TimelineItem>
|
||||
))}
|
||||
</Timeline>
|
||||
</CollapseItem>
|
||||
))}
|
||||
</Collapse>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CourseList;
|
||||
Reference in New Issue
Block a user