diff --git a/src/components/PublicCourseList/index.css b/src/components/PublicCourseList/index.css new file mode 100644 index 0000000..73eda9e --- /dev/null +++ b/src/components/PublicCourseList/index.css @@ -0,0 +1,167 @@ +.public-course-list { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + background: #fff; + border-radius: 8px; + overflow: hidden; +} + +.course-list-header { + padding: 16px 20px; + border-bottom: 1px solid #e5e6eb; + background: #fafafa; +} + +.course-list-header h3 { + margin: 0; + font-size: 16px; + font-weight: 500; + color: #1d2129; +} + +.course-list-collapse { + flex: 1; + overflow-y: auto; + padding: 12px; +} + +.course-list-collapse .arco-collapse-item { + margin-bottom: 8px; + border: 1px solid #e5e6eb; + border-radius: 4px; + overflow: hidden; +} + +.course-list-collapse .arco-collapse-item-header { + background: #f7f8fa; + padding: 12px 16px; +} + +.unit-header { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; +} + +.unit-name { + font-size: 14px; + font-weight: 500; + color: #1d2129; +} + +.unit-course-count { + font-size: 12px; + color: #86909c; + margin-right: 20px; +} + +.course-timeline { + padding: 16px 0; +} + +.timeline-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: #e5e6eb; +} + +.timeline-dot.completed { + background: #00b42a; +} + +.timeline-dot.current { + background: #ff7d00; + box-shadow: 0 0 0 4px rgba(255, 125, 0, 0.2); +} + +.timeline-dot.upcoming { + background: #165dff; +} + +.course-item { + padding: 12px; + background: #f7f8fa; + border-radius: 4px; + cursor: pointer; + transition: all 0.3s; + display: flex; + justify-content: space-between; + align-items: center; +} + +.course-item:hover { + background: #e8f3ff; + transform: translateX(4px); +} + +.course-item.selected { + background: #e8f3ff; + border-left: 3px solid #165dff; +} + +.course-item.completed { + opacity: 0.7; +} + +.course-info { + flex: 1; +} + +.course-name { + font-size: 14px; + font-weight: 500; + color: #1d2129; + margin-bottom: 4px; +} + +.course-meta { + display: flex; + gap: 16px; + font-size: 12px; + color: #86909c; +} + +.course-status { + padding: 2px 8px; + border-radius: 12px; + font-size: 12px; + white-space: nowrap; +} + +.course-status.completed { + background: #e8ffea; + color: #00b42a; +} + +.course-status.current { + background: #fff7e8; + color: #ff7d00; +} + +.course-status.upcoming { + background: #e8f3ff; + color: #165dff; +} + +/* 自定义滚动条 */ +.course-list-collapse::-webkit-scrollbar { + width: 6px; +} + +.course-list-collapse::-webkit-scrollbar-track { + background: #f2f3f5; + border-radius: 3px; +} + +.course-list-collapse::-webkit-scrollbar-thumb { + background: #c9cdd4; + border-radius: 3px; +} + +.course-list-collapse::-webkit-scrollbar-thumb:hover { + background: #86909c; +} \ No newline at end of file diff --git a/src/components/PublicCourseList/index.jsx b/src/components/PublicCourseList/index.jsx new file mode 100644 index 0000000..bd91c58 --- /dev/null +++ b/src/components/PublicCourseList/index.jsx @@ -0,0 +1,156 @@ +import { useState, useEffect } from "react"; +import { Collapse, Timeline, Spin } from "@arco-design/web-react"; +import { getPublicCourseLiveList } from "@/services/courseLive"; +import "./index.css"; + +const TimelineItem = Timeline.Item; +const CollapseItem = Collapse.Item; + +const PublicCourseList = ({ 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 getPublicCourseLiveList(); + 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("Failed to fetch course list:", error); + } finally { + setLoading(false); + } + }; + + const handleCourseClick = (course, unitName) => { + setSelectedCourseId(course.courseId); + if (onCourseClick) { + onCourseClick({ + ...course, + unitName: unitName + }); + } + }; + + const renderCourseStatus = (course) => { + if (course.completed) { + return 已完成; + } else if (course.current) { + return 正在进行; + } else if (course.upcoming) { + return 即将开始; + } + return null; + }; + + return ( +