feat: 完善课程列表和直播纪要功能
- 使用CSV数据更新课程列表,支持多单元和课程状态显示 - 添加"即将开始"状态判断逻辑(今天或明天的课程) - 删除直播纪要的"直播中"图标 - 修复时间轴排序,确保从早到晚显示 - 修复项目案例详情内容左对齐样式 - 修复组件语法错误和重复代码问题 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,10 @@
|
||||
"mcp__serena__get_symbols_overview",
|
||||
"mcp__serena__create_text_file",
|
||||
"Bash(git remote add:*)",
|
||||
"Bash(git add:*)"
|
||||
"Bash(git add:*)",
|
||||
"Bash(git remote remove:*)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git push:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
||||
Binary file not shown.
@@ -83,6 +83,14 @@
|
||||
background-image: url("@/assets/images/Common/time_line_clock_icon.png");
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.time-line-lock-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-image: url("@/assets/images/Common/time_line_lock_icon.png");
|
||||
background-size: 100% 100%;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.time-line-item {
|
||||
width: 248px;
|
||||
height: 74px;
|
||||
@@ -148,6 +156,19 @@
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
.pending {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
|
||||
> p {
|
||||
color: #86909c;
|
||||
}
|
||||
|
||||
.time-line-item-info {
|
||||
color: #86909c;
|
||||
}
|
||||
}
|
||||
|
||||
.coming {
|
||||
&::before {
|
||||
content: "即将开始";
|
||||
|
||||
@@ -1,10 +1,74 @@
|
||||
import { Collapse, Timeline } from "@arco-design/web-react";
|
||||
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 = "" }) => {
|
||||
const [courseLiveList, setCourseLiveList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fetchCourseList();
|
||||
}, []);
|
||||
|
||||
const fetchCourseList = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await getCourseLiveList();
|
||||
if (res.success) {
|
||||
setCourseLiveList(res.data || []);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取课程列表失败:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 判断课程状态
|
||||
const getCourseStatus = (course) => {
|
||||
if (course.completed) return "finish";
|
||||
if (course.current) return "active";
|
||||
|
||||
// 判断是否为即将开始(今天或明天的课程)
|
||||
const courseDate = new Date(course.date);
|
||||
const today = new Date();
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
|
||||
// 重置时间部分只比较日期
|
||||
courseDate.setHours(0, 0, 0, 0);
|
||||
today.setHours(0, 0, 0, 0);
|
||||
tomorrow.setHours(0, 0, 0, 0);
|
||||
|
||||
if (courseDate.getTime() === today.getTime() || courseDate.getTime() === tomorrow.getTime()) {
|
||||
return "coming";
|
||||
}
|
||||
|
||||
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>
|
||||
@@ -14,39 +78,34 @@ const CourseList = ({ className = "" }) => {
|
||||
className="course-list"
|
||||
bordered={false}
|
||||
expandIconPosition="right"
|
||||
defaultActiveKey={["1"]}
|
||||
>
|
||||
<CollapseItem
|
||||
header="课程单元1"
|
||||
name="1"
|
||||
className="course-list-item"
|
||||
>
|
||||
<Timeline>
|
||||
<TimelineItem
|
||||
dot={<div className="time-line-dot-icon" />}
|
||||
lineType="dashed"
|
||||
>
|
||||
<div className="time-line-item finish">
|
||||
<p>终生学习系统</p>
|
||||
<div className="time-line-item-info">
|
||||
<span>张老师</span>
|
||||
<span>2023-01-01</span>
|
||||
</div>
|
||||
</div>
|
||||
</TimelineItem>
|
||||
<TimelineItem
|
||||
dot={<div className="time-line-clock-icon" />}
|
||||
lineType="dashed"
|
||||
>
|
||||
<div className="time-line-item active">
|
||||
<p>终生学习系统</p>
|
||||
<div className="time-line-item-info">
|
||||
<span>张老师</span>
|
||||
<span>2023-01-01</span>
|
||||
</div>
|
||||
</div>
|
||||
</TimelineItem>
|
||||
</Timeline>
|
||||
</CollapseItem>
|
||||
{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)}`}>
|
||||
<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>
|
||||
|
||||
@@ -35,16 +35,7 @@
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 10px;
|
||||
width: 62px;
|
||||
height: 20px;
|
||||
background-image: url("@/assets/images/CoursesVideoPlayer/living_icon.png");
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
}
|
||||
.live-summary-list {
|
||||
width: 100%;
|
||||
|
||||
@@ -10,8 +10,15 @@ const LiveSummary = ({ className = "", showBtn = false, isLiving = true }) => {
|
||||
navigate("/job-strategy-detail");
|
||||
};
|
||||
|
||||
// 根据type分组keyPoints
|
||||
const groupedPoints = jobStrategyNotes.keyPoints.reduce((acc, point) => {
|
||||
// 按时间排序keyPoints(从早到晚)
|
||||
const sortedPoints = [...jobStrategyNotes.keyPoints].sort((a, b) => {
|
||||
const timeA = a.time.split(':').map(Number);
|
||||
const timeB = b.time.split(':').map(Number);
|
||||
return (timeA[0] * 60 + timeA[1]) - (timeB[0] * 60 + timeB[1]);
|
||||
});
|
||||
|
||||
// 根据type分组排序后的keyPoints
|
||||
const groupedPoints = sortedPoints.reduce((acc, point) => {
|
||||
const typeMap = {
|
||||
strategy: "策略建议",
|
||||
advice: "专家建议",
|
||||
|
||||
@@ -4517,4 +4517,118 @@ mockData.profileOverview = {
|
||||
},
|
||||
};
|
||||
|
||||
// 课程直播间的课程列表数据
|
||||
mockData.courseLiveList = [
|
||||
{
|
||||
unitId: "unit1",
|
||||
unitName: "岗位体系认知",
|
||||
courses: [
|
||||
{ courseId: "c1-1", courseName: "教育体系认知", teacherName: "李老师", date: "2025-08-20", completed: true, current: false },
|
||||
{ courseId: "c1-2", courseName: "现代文旅类企业的管理体系", teacherName: "王老师", date: "2025-08-21", completed: true, current: false },
|
||||
{ courseId: "c1-3", courseName: "专科生的职业规划", teacherName: "张老师", date: "2025-08-22", completed: true, current: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
unitId: "unit2",
|
||||
unitName: "产业认知课",
|
||||
courses: [
|
||||
{ courseId: "c2-1", courseName: "文旅产业认知课", teacherName: "陈老师", date: "2025-08-23", completed: true, current: false },
|
||||
{ courseId: "c2-2", courseName: "行业详解:旅游行业", teacherName: "赵老师", date: "2025-08-24", completed: true, current: false },
|
||||
{ courseId: "c2-3", courseName: "行业详解:酒店与民宿行业", teacherName: "刘老师", date: "2025-08-25", completed: true, current: false },
|
||||
{ courseId: "c2-4", courseName: "行业详解:活动与会展行业", teacherName: "周老师", date: "2025-08-26", completed: true, current: false },
|
||||
{ courseId: "c2-5", courseName: "行业详解:文化服务行业", teacherName: "吴老师", date: "2025-08-27", completed: false, current: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
unitId: "unit3",
|
||||
unitName: "旅游产业全景与文旅基础知识",
|
||||
courses: [
|
||||
{ courseId: "c3-1", courseName: "现代文旅产业生态图谱", teacherName: "郑老师", date: "2025-08-28", completed: false, current: false },
|
||||
{ courseId: "c3-2", courseName: "文旅政策法规与风险管理", teacherName: "王老师", date: "2025-08-29", completed: false, current: false },
|
||||
{ courseId: "c3-3", courseName: "旅游产品与旅游资源", teacherName: "李老师", date: "2025-08-30", completed: false, current: false },
|
||||
{ courseId: "c3-4", courseName: "游客行为心理学基础", teacherName: "张老师", date: "2025-08-31", completed: false, current: false },
|
||||
{ courseId: "c3-5", courseName: "可持续旅游发展", teacherName: "陈老师", date: "2025-09-01", completed: false, current: false },
|
||||
{ courseId: "c3-6", courseName: "单元小结", teacherName: "赵老师", date: "2025-09-02", completed: false, current: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
unitId: "unit4",
|
||||
unitName: "文旅服务:形象、沟通与体验的融合艺术",
|
||||
courses: [
|
||||
{ courseId: "c4-1", courseName: "文旅场景职业形象IP塑造", teacherName: "刘老师", date: "2025-09-03", completed: false, current: false },
|
||||
{ courseId: "c4-2", courseName: "情境化服务体验设计", teacherName: "周老师", date: "2025-09-04", completed: false, current: false },
|
||||
{ courseId: "c4-3", courseName: "政务商务接待专项礼仪", teacherName: "吴老师", date: "2025-09-05", completed: false, current: false },
|
||||
{ courseId: "c4-4", courseName: "文旅服务中的非语言表达", teacherName: "郑老师", date: "2025-09-06", completed: false, current: false },
|
||||
{ courseId: "c4-5", courseName: "服务沟通技巧与表达训练", teacherName: "王老师", date: "2025-09-07", completed: false, current: false },
|
||||
{ courseId: "c4-6", courseName: "多元文化下的服务表达差异", teacherName: "李老师", date: "2025-09-08", completed: false, current: false },
|
||||
{ courseId: "c4-7", courseName: "单元小结", teacherName: "张老师", date: "2025-09-09", completed: false, current: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
unitId: "unit5",
|
||||
unitName: "文旅与供应链基础",
|
||||
courses: [
|
||||
{ courseId: "c5-1", courseName: "供应链管理的内容", teacherName: "陈老师", date: "2025-09-10", completed: false, current: false },
|
||||
{ courseId: "c5-2", courseName: "文旅资源调度", teacherName: "赵老师", date: "2025-09-11", completed: false, current: false },
|
||||
{ courseId: "c5-3", courseName: "文旅产品全生命周期管理", teacherName: "刘老师", date: "2025-09-12", completed: false, current: false },
|
||||
{ courseId: "c5-4", courseName: "文旅商品供应链", teacherName: "周老师", date: "2025-09-13", completed: false, current: false },
|
||||
{ courseId: "c5-5", courseName: "住宿业资源协同", teacherName: "吴老师", date: "2025-09-14", completed: false, current: false },
|
||||
{ courseId: "c5-6", courseName: "小型文旅项目的供应链角色模拟", teacherName: "郑老师", date: "2025-09-15", completed: false, current: false },
|
||||
{ courseId: "c5-7", courseName: "文旅项目供应链特征", teacherName: "王老师", date: "2025-09-16", completed: false, current: false },
|
||||
{ courseId: "c5-8", courseName: "文旅供应链中的B2B与B2C模式", teacherName: "李老师", date: "2025-09-17", completed: false, current: false },
|
||||
{ courseId: "c5-9", courseName: "单元小结", teacherName: "张老师", date: "2025-09-18", completed: false, current: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
unitId: "unit6",
|
||||
unitName: "商业设计基础",
|
||||
courses: [
|
||||
{ courseId: "c6-1", courseName: "现代设计行业的发展现状", teacherName: "陈老师", date: "2025-09-19", completed: false, current: false },
|
||||
{ courseId: "c6-2", courseName: "设计基础", teacherName: "赵老师", date: "2025-09-20", completed: false, current: false },
|
||||
{ courseId: "c6-3", courseName: "字体设计与中文字体情绪表达", teacherName: "刘老师", date: "2025-09-21", completed: false, current: false },
|
||||
{ courseId: "c6-4", courseName: "商业平面色彩搭配", teacherName: "周老师", date: "2025-09-22", completed: false, current: false },
|
||||
{ courseId: "c6-5", courseName: "平面设计构图", teacherName: "吴老师", date: "2025-09-23", completed: false, current: false },
|
||||
{ courseId: "c6-6", courseName: "图像编辑工具:Photoshop", teacherName: "郑老师", date: "2025-09-24", completed: false, current: false },
|
||||
{ courseId: "c6-7", courseName: "矢量与标志设计:Illustrator", teacherName: "王老师", date: "2025-09-25", completed: false, current: false },
|
||||
{ courseId: "c6-8", courseName: "快速设计工具使用:Canva", teacherName: "李老师", date: "2025-09-26", completed: false, current: false },
|
||||
{ courseId: "c6-9", courseName: "移动端视觉原型设计:Figma", teacherName: "张老师", date: "2025-09-27", completed: false, current: false },
|
||||
{ courseId: "c6-10", courseName: "视频剪辑入门:剪映", teacherName: "陈老师", date: "2025-09-28", completed: false, current: false },
|
||||
{ courseId: "c6-11", courseName: "单元小结", teacherName: "赵老师", date: "2025-09-29", completed: false, current: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
unitId: "unit7",
|
||||
unitName: "AIGC人工智能生成内容",
|
||||
courses: [
|
||||
{ courseId: "c7-1", courseName: "AIGC发展简史与基本逻辑", teacherName: "刘老师", date: "2025-09-30", completed: false, current: false },
|
||||
{ courseId: "c7-2", courseName: "AIGC的基本概念与各领域的应用", teacherName: "周老师", date: "2025-10-01", completed: false, current: false },
|
||||
{ courseId: "c7-3", courseName: "AIGC语言模型:chatgpt的灵活应用", teacherName: "吴老师", date: "2025-10-02", completed: false, current: false },
|
||||
{ courseId: "c7-4", courseName: "AIGC生成内容的版权问题与合规使用", teacherName: "郑老师", date: "2025-10-03", completed: false, current: false },
|
||||
{ courseId: "c7-5", courseName: "AIGC图像生成模型:Stable Diffusion AI摄影和平面设计", teacherName: "王老师", date: "2025-10-04", completed: false, current: false },
|
||||
{ courseId: "c7-6", courseName: "AIGC图像生成模型:Stable Diffusion的应用操作", teacherName: "李老师", date: "2025-10-05", completed: false, current: false },
|
||||
{ courseId: "c7-7", courseName: "AIGC视频应用:音视频生成与AI自动剪辑", teacherName: "张老师", date: "2025-10-06", completed: false, current: false },
|
||||
{ courseId: "c7-8", courseName: "AI词曲创作:suno", teacherName: "陈老师", date: "2025-10-07", completed: false, current: false },
|
||||
{ courseId: "c7-9", courseName: "单元小结", teacherName: "赵老师", date: "2025-10-08", completed: false, current: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
unitId: "unit8",
|
||||
unitName: "全栈新媒体运营赋能文旅营销",
|
||||
courses: [
|
||||
{ courseId: "c8-1", courseName: "新媒体应用传播学", teacherName: "刘老师", date: "2025-10-09", completed: false, current: false },
|
||||
{ courseId: "c8-2", courseName: "新媒体故事结构入门", teacherName: "周老师", date: "2025-10-10", completed: false, current: false },
|
||||
{ courseId: "c8-3", courseName: "新媒体产品策划", teacherName: "吴老师", date: "2025-10-11", completed: false, current: false },
|
||||
{ courseId: "c8-4", courseName: "平台账号经营与内容赛道", teacherName: "郑老师", date: "2025-10-12", completed: false, current: false },
|
||||
{ courseId: "c8-5", courseName: "各平台变现方式与具体方法", teacherName: "王老师", date: "2025-10-13", completed: false, current: false },
|
||||
{ courseId: "c8-6", courseName: "内容运营:短视频的制作工具", teacherName: "李老师", date: "2025-10-14", completed: false, current: false },
|
||||
{ courseId: "c8-7", courseName: "内容运营:短视频制作内容对标", teacherName: "张老师", date: "2025-10-15", completed: false, current: false },
|
||||
{ courseId: "c8-8", courseName: "直播运营:直播间的搭建", teacherName: "陈老师", date: "2025-10-16", completed: false, current: false },
|
||||
{ courseId: "c8-9", courseName: "品牌运营:当地文化IP数字化传播", teacherName: "赵老师", date: "2025-10-17", completed: false, current: false },
|
||||
{ courseId: "c8-10", courseName: "品牌运营:跨界营销创新", teacherName: "刘老师", date: "2025-10-18", completed: false, current: false },
|
||||
{ courseId: "c8-11", courseName: "私域运营:私域流量池的运营", teacherName: "周老师", date: "2025-10-19", completed: false, current: false },
|
||||
{ courseId: "c8-12", courseName: "单元小结", teacherName: "吴老师", date: "2025-10-20", completed: false, current: false }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// 模拟数据加载完成
|
||||
|
||||
@@ -275,6 +275,7 @@
|
||||
color: #1d2129;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
text-align: left;
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #1d2129;
|
||||
@@ -293,6 +294,7 @@
|
||||
p {
|
||||
margin: 8px 0;
|
||||
line-height: 1.6;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
@@ -303,6 +305,7 @@
|
||||
li {
|
||||
margin: 4px 0;
|
||||
line-height: 1.6;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul li {
|
||||
|
||||
39
src/services/courseLive.js
Normal file
39
src/services/courseLive.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { mockData } from "@/data/mockData";
|
||||
|
||||
// 获取课程直播列表
|
||||
export async function getCourseLiveList() {
|
||||
// 模拟异步请求
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
data: mockData.courseLiveList || [],
|
||||
});
|
||||
}
|
||||
|
||||
// 获取课程详情
|
||||
export async function getCourseDetail(courseId) {
|
||||
// 模拟异步请求
|
||||
const allCourses = [];
|
||||
mockData.courseLiveList?.forEach(unit => {
|
||||
allCourses.push(...unit.courses);
|
||||
});
|
||||
|
||||
const course = allCourses.find(c => c.courseId === courseId);
|
||||
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
data: course || null,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新课程进度
|
||||
export async function updateCourseProgress(courseId, progress) {
|
||||
// 模拟异步请求
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
data: {
|
||||
courseId,
|
||||
progress,
|
||||
message: "进度更新成功",
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user