主要更新: - 面试模拟页:移除上滑查看评价,添加渐进式评分(72→81→89) - 简历面试页:添加岗位头像、标签背景、面试题加粗等视觉优化 - 项目库页:添加"我完成的项目库"板块,增加hover效果 - 求职策略详情页:优化圆柱体和矩形对齐,添加CSV岗位数据,调整批次文字位置 - 企业岗位列表页:添加返回按钮功能 - 全局:统一岗位级别术语(普通岗/技术骨干岗/储备干部岗) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
177 lines
5.6 KiB
JavaScript
177 lines
5.6 KiB
JavaScript
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 style={{
|
||
overflow: 'visible',
|
||
textOverflow: 'unset',
|
||
whiteSpace: 'normal',
|
||
wordBreak: 'break-word',
|
||
WebkitLineClamp: 'unset',
|
||
WebkitBoxOrient: 'unset',
|
||
display: 'block',
|
||
maxWidth: 'calc(100% - 70px)'
|
||
}}>{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;
|