diff --git a/courseLiveListData.json b/courseLiveListData.json
new file mode 100644
index 0000000..bc44226
--- /dev/null
+++ b/courseLiveListData.json
@@ -0,0 +1,964 @@
+{
+ "courseLiveList": [
+ {
+ "unitId": "unit1",
+ "unitName": "岗位体系认知",
+ "courses": [
+ {
+ "courseId": "c1-1",
+ "courseName": "教育体系认知",
+ "teacherName": "刘杰",
+ "date": "2025-03-04",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c1-2",
+ "courseName": "现代文旅类企业的管理体系",
+ "teacherName": "刘杰",
+ "date": "2025-03-05",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c1-3",
+ "courseName": "专科生的职业规划",
+ "teacherName": "刘杰",
+ "date": "2025-03-06",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit2",
+ "unitName": "产业认知课",
+ "courses": [
+ {
+ "courseId": "c2-1",
+ "courseName": "文旅产业认知课",
+ "teacherName": "刘杰",
+ "date": "2025-03-11",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c2-2",
+ "courseName": "行业详解:旅游行业",
+ "teacherName": "刘杰",
+ "date": "2025-03-12",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c2-3",
+ "courseName": "行业详解:酒店与民宿行业",
+ "teacherName": "刘杰",
+ "date": "2025-03-13",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c2-4",
+ "courseName": "行业详解:活动与会展行业",
+ "teacherName": "刘杰",
+ "date": "2025-03-18",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c2-5",
+ "courseName": "行业详解:文化服务行业",
+ "teacherName": "刘杰",
+ "date": "2025-03-19",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit3",
+ "unitName": "旅游产业全景与文旅基础知识",
+ "courses": [
+ {
+ "courseId": "c3-1",
+ "courseName": "现代文旅产业生态图谱",
+ "teacherName": "刘杰",
+ "date": "2025-03-20",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c3-2",
+ "courseName": "文旅政策法规与风险管理",
+ "teacherName": "刘杰",
+ "date": "2025-03-25",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c3-3",
+ "courseName": "旅游产品与旅游资源",
+ "teacherName": "刘杰",
+ "date": "2025-03-26",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c3-4",
+ "courseName": "游客行为心理学基础",
+ "teacherName": "刘杰",
+ "date": "2025-03-27",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c3-5",
+ "courseName": "可持续旅游发展",
+ "teacherName": "刘杰",
+ "date": "2025-04-01",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c3-6",
+ "courseName": "单元小结",
+ "teacherName": "刘杰",
+ "date": "2025-04-02",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit4",
+ "unitName": "文旅服务:形象、沟通与体验的融合艺术",
+ "courses": [
+ {
+ "courseId": "c4-1",
+ "courseName": "文旅场景职业形象IP塑造",
+ "teacherName": "郭建辉",
+ "date": "2025-04-03",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c4-2",
+ "courseName": "情境化服务体验设计",
+ "teacherName": "郭建辉",
+ "date": "2025-04-08",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c4-3",
+ "courseName": "政务商务接待专项礼仪",
+ "teacherName": "郭建辉",
+ "date": "2025-04-09",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c4-4",
+ "courseName": "文旅服务中的非语言表达",
+ "teacherName": "郭建辉",
+ "date": "2025-04-10",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c4-5",
+ "courseName": "服务沟通技巧与表达训练",
+ "teacherName": "郭建辉",
+ "date": "2025-04-15",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c4-6",
+ "courseName": "多元文化下的服务表达差异",
+ "teacherName": "郭建辉",
+ "date": "2025-04-16",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c4-7",
+ "courseName": "单元小结",
+ "teacherName": "郭建辉",
+ "date": "2025-04-17",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit5",
+ "unitName": "文旅与供应链基础",
+ "courses": [
+ {
+ "courseId": "c5-1",
+ "courseName": "供应链管理的内容",
+ "teacherName": "赵志强",
+ "date": "2025-04-22",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c5-2",
+ "courseName": "文旅资源调度",
+ "teacherName": "赵志强",
+ "date": "2025-04-23",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c5-3",
+ "courseName": "文旅产品全生命周期管理",
+ "teacherName": "赵志强",
+ "date": "2025-04-24",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c5-4",
+ "courseName": "文旅商品供应链",
+ "teacherName": "赵志强",
+ "date": "2025-04-29",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c5-5",
+ "courseName": "住宿业资源协同",
+ "teacherName": "赵志强",
+ "date": "2025-04-30",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c5-6",
+ "courseName": "小型文旅项目的供应链角色模拟",
+ "teacherName": "赵志强",
+ "date": "2025-05-01",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c5-7",
+ "courseName": "文旅项目供应链特征",
+ "teacherName": "赵志强",
+ "date": "2025-05-06",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c5-8",
+ "courseName": "文旅供应链中的B2B与B2C模式",
+ "teacherName": "赵志强",
+ "date": "2025-05-07",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c5-9",
+ "courseName": "单元小结",
+ "teacherName": "赵志强",
+ "date": "2025-05-08",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit6",
+ "unitName": "商业设计基础",
+ "courses": [
+ {
+ "courseId": "c6-1",
+ "courseName": "现代设计行业的发展现状",
+ "teacherName": "赵志强",
+ "date": "2025-05-13",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-2",
+ "courseName": "设计基础",
+ "teacherName": "赵志强",
+ "date": "2025-05-14",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-3",
+ "courseName": "字体设计与中文字体情绪表达",
+ "teacherName": "赵志强",
+ "date": "2025-05-15",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-4",
+ "courseName": "商业平面色彩搭配",
+ "teacherName": "赵志强",
+ "date": "2025-05-20",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-5",
+ "courseName": "平面设计构图",
+ "teacherName": "赵志强",
+ "date": "2025-05-21",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-6",
+ "courseName": "图像编辑工具:Photoshop",
+ "teacherName": "赵志强",
+ "date": "2025-05-22",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-7",
+ "courseName": "图像编辑工具:Photoshop",
+ "teacherName": "赵志强",
+ "date": "2025-05-27",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-8",
+ "courseName": "矢量与标志设计:Illustrator",
+ "teacherName": "赵志强",
+ "date": "2025-05-28",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-9",
+ "courseName": "矢量与标志设计:Illustrator",
+ "teacherName": "赵志强",
+ "date": "2025-05-29",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-10",
+ "courseName": "快速设计工具使用:Canva",
+ "teacherName": "赵志强",
+ "date": "2025-06-03",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-11",
+ "courseName": "快速设计工具使用:Canva",
+ "teacherName": "赵志强",
+ "date": "2025-06-04",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-12",
+ "courseName": "移动端视觉原型设计:Figma",
+ "teacherName": "赵志强",
+ "date": "2025-06-05",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-13",
+ "courseName": "移动端视觉原型设计:Figma",
+ "teacherName": "赵志强",
+ "date": "2025-06-10",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-14",
+ "courseName": "视频剪辑入门:剪映",
+ "teacherName": "赵志强",
+ "date": "2025-06-11",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-15",
+ "courseName": "视频剪辑入门:剪映",
+ "teacherName": "赵志强",
+ "date": "2025-06-12",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c6-16",
+ "courseName": "单元小结",
+ "teacherName": "赵志强",
+ "date": "2025-06-17",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit7",
+ "unitName": "AIGC人工智能生成内容",
+ "courses": [
+ {
+ "courseId": "c7-1",
+ "courseName": "AIGC发展简史与基本逻辑",
+ "teacherName": "赵志强",
+ "date": "2025-09-02",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-2",
+ "courseName": "AIGC的基本概念与各领域的应用",
+ "teacherName": "赵志强",
+ "date": "2025-09-03",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-3",
+ "courseName": "AIGC语言模型:chatgpt的灵活应...",
+ "teacherName": "赵志强",
+ "date": "2025-09-04",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-4",
+ "courseName": "AIGC生成内容的版权问题与合规使用",
+ "teacherName": "刘杰",
+ "date": "2025-09-09",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-5",
+ "courseName": "AIGC图像生成模型:Stable Di...",
+ "teacherName": "刘杰",
+ "date": "2025-09-10",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-6",
+ "courseName": "AIGC图像生成模型:Stable Di...",
+ "teacherName": "刘杰",
+ "date": "2025-09-11",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-7",
+ "courseName": "AIGC图像生成模型:Stable Di...",
+ "teacherName": "刘杰",
+ "date": "2025-09-16",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-8",
+ "courseName": "AIGC图像生成模型:Stable Di...",
+ "teacherName": "刘杰",
+ "date": "2025-09-17",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-9",
+ "courseName": "AIGC视频应用:音视频生成与AI自动剪...",
+ "teacherName": "赵志强",
+ "date": "2025-09-18",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-10",
+ "courseName": "AIGC视频应用:音视频生成与AI自动剪...",
+ "teacherName": "赵志强",
+ "date": "2025-09-23",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-11",
+ "courseName": "AI词曲创作:suno",
+ "teacherName": "赵志强",
+ "date": "2025-09-24",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-12",
+ "courseName": "AI词曲创作:suno",
+ "teacherName": "赵志强",
+ "date": "2025-09-25",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c7-13",
+ "courseName": "单元小结",
+ "teacherName": "赵志强",
+ "date": "2025-09-30",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit8",
+ "unitName": " 全栈新媒体运营赋能文旅营销",
+ "courses": [
+ {
+ "courseId": "c8-1",
+ "courseName": "新媒体应用传播学",
+ "teacherName": "赵志强",
+ "date": "2025-10-01",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-2",
+ "courseName": "新媒体故事结构入门",
+ "teacherName": "赵志强",
+ "date": "2025-10-02",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-3",
+ "courseName": "新媒体产品策划",
+ "teacherName": "赵志强",
+ "date": "2025-10-07",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-4",
+ "courseName": "平台账号经营与内容赛道",
+ "teacherName": "赵志强",
+ "date": "2025-10-08",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-5",
+ "courseName": "各平台变现方式与具体方法",
+ "teacherName": "赵志强",
+ "date": "2025-10-09",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-6",
+ "courseName": "内容运营:短视频的制作工具",
+ "teacherName": "赵志强",
+ "date": "2025-10-14",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-7",
+ "courseName": "内容运营:短视频的制作工具",
+ "teacherName": "赵志强",
+ "date": "2025-10-15",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-8",
+ "courseName": "内容运营:短视频的制作工具",
+ "teacherName": "赵志强",
+ "date": "2025-10-16",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-9",
+ "courseName": "内容运营:短视频的制作工具",
+ "teacherName": "赵志强",
+ "date": "2025-10-21",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-10",
+ "courseName": "内容运营:短视频制作内容对标",
+ "teacherName": "刘杰",
+ "date": "2025-10-22",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-11",
+ "courseName": "内容运营:短视频制作内容对标",
+ "teacherName": "刘杰",
+ "date": "2025-10-23",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-12",
+ "courseName": "直播运营:直播间的搭建",
+ "teacherName": "刘杰",
+ "date": "2025-10-28",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-13",
+ "courseName": "直播运营:直播间的搭建",
+ "teacherName": "刘杰",
+ "date": "2025-10-29",
+ "completed": true,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-14",
+ "courseName": "品牌运营:当地文化IP数字化传播",
+ "teacherName": "刘杰",
+ "date": "2025-10-30",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-15",
+ "courseName": "品牌运营:当地文化IP数字化传播",
+ "teacherName": "刘杰",
+ "date": "2025-11-04",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-16",
+ "courseName": "品牌运营:跨界营销创新",
+ "teacherName": "赵志强",
+ "date": "2025-11-05",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-17",
+ "courseName": "品牌运营:跨界营销创新",
+ "teacherName": "赵志强",
+ "date": "2025-11-06",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-18",
+ "courseName": "私域运营:私域流量池的运营",
+ "teacherName": "赵志强",
+ "date": "2025-11-11",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-19",
+ "courseName": "私域运营:私域流量池的运营",
+ "teacherName": "赵志强",
+ "date": "2025-11-12",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c8-20",
+ "courseName": "单元小结",
+ "teacherName": "赵志强",
+ "date": "2025-11-13",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit9",
+ "unitName": "活动策划基础",
+ "courses": [
+ {
+ "courseId": "c9-1",
+ "courseName": "活动类型与功能认知",
+ "teacherName": "郭建辉",
+ "date": "2025-11-18",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-2",
+ "courseName": "受众定位与主题创意方法",
+ "teacherName": "郭建辉",
+ "date": "2025-11-19",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-3",
+ "courseName": "活动宣传渠道与推广方式",
+ "teacherName": "郭建辉",
+ "date": "2025-11-20",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-4",
+ "courseName": "活动宣传渠道与推广方式",
+ "teacherName": "郭建辉",
+ "date": "2025-11-25",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-5",
+ "courseName": "活动文案写作与表达技巧",
+ "teacherName": "郭建辉",
+ "date": "2025-11-26",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-6",
+ "courseName": "活动文案写作与表达技巧",
+ "teacherName": "郭建辉",
+ "date": "2025-11-27",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-7",
+ "courseName": "活动流程设计与时间节点把控",
+ "teacherName": "郭建辉",
+ "date": "2025-12-02",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-8",
+ "courseName": "活动流程设计与时间节点把控",
+ "teacherName": "郭建辉",
+ "date": "2025-12-03",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-9",
+ "courseName": "活动场地选择与布置基础",
+ "teacherName": "郭建辉",
+ "date": "2025-12-04",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-10",
+ "courseName": "活动预算与资源统筹",
+ "teacherName": "赵志强",
+ "date": "2025-12-09",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-11",
+ "courseName": "应急预案与活动风险管理",
+ "teacherName": "赵志强",
+ "date": "2025-12-10",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-12",
+ "courseName": "活动复盘报告撰写与数据分析方法",
+ "teacherName": "赵志强",
+ "date": "2025-12-11",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-13",
+ "courseName": "活动复盘报告撰写与数据分析方法",
+ "teacherName": "赵志强",
+ "date": "2025-12-16",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c9-14",
+ "courseName": "单元小结",
+ "teacherName": "赵志强",
+ "date": "2025-12-17",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ },
+ {
+ "unitId": "unit10",
+ "unitName": "智慧文旅应用",
+ "courses": [
+ {
+ "courseId": "c10-1",
+ "courseName": "智慧文旅概论",
+ "teacherName": "赵志强",
+ "date": "2025-12-18",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c10-2",
+ "courseName": "OTA平台运营",
+ "teacherName": "赵志强",
+ "date": "2025-12-23",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c10-3",
+ "courseName": "票务分销平台",
+ "teacherName": "刘杰",
+ "date": "2025-12-24",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c10-4",
+ "courseName": "景区智能导览系统",
+ "teacherName": "赵志强",
+ "date": "2025-12-25",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c10-5",
+ "courseName": "智能导览设备运用",
+ "teacherName": "刘杰",
+ "date": "2025-12-30",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c10-6",
+ "courseName": "智慧酒店/智慧景区体验场景模拟",
+ "teacherName": "刘杰",
+ "date": "2025-12-31",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ },
+ {
+ "courseId": "c10-7",
+ "courseName": "单元小结",
+ "teacherName": "刘杰",
+ "date": "2026-01-01",
+ "completed": false,
+ "current": false,
+ "upcoming": false
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/generateCourseLiveList.js b/generateCourseLiveList.js
new file mode 100644
index 0000000..2963ea3
--- /dev/null
+++ b/generateCourseLiveList.js
@@ -0,0 +1,127 @@
+import fs from 'fs';
+
+// 读取CSV文件
+const csvContent = fs.readFileSync('日历课程表.csv', 'utf-8');
+const lines = csvContent.split('\n');
+
+// 课程单元映射
+const unitMap = {
+ '岗位体系认知': 'unit1',
+ '产业认知课': 'unit2',
+ '旅游产业全景与文旅基础知识': 'unit3',
+ '文旅服务:形象、沟通与体验的融合艺术': 'unit4',
+ '文旅与供应链基础': 'unit5',
+ '商业设计基础': 'unit6',
+ 'AIGC人工智能生成内容': 'unit7',
+ ' 全栈新媒体运营赋能文旅营销': 'unit8', // 注意CSV中前面有个空格
+ '活动策划基础': 'unit9',
+ '智慧文旅应用': 'unit10'
+};
+
+// 初始化课程列表结构
+const courseLiveList = [];
+const unitCoursesMap = new Map();
+
+// 处理每一行数据(跳过标题行)
+for (let i = 1; i < lines.length; i++) {
+ const line = lines[i].trim();
+ if (!line) continue;
+
+ const parts = line.split(',');
+ if (parts.length < 10) continue;
+
+ const date = parts[0];
+ const courseStatus = parts[2];
+ const courseName = parts[3];
+ const teacher = parts[6];
+ let unit = parts[7]; // 使用 let 以便可以重新赋值
+ const status = parts[8];
+
+ // 特殊处理:6月17日的单元小结应该属于商业设计基础(unit6)
+ if (date === '2025/6/17' && courseName === '单元小结') {
+ unit = '商业设计基础';
+ }
+
+ // 只处理有课的数据
+ if (courseStatus === '有课' && courseName && unit && unitMap[unit]) {
+ if (!unitCoursesMap.has(unit)) {
+ unitCoursesMap.set(unit, {
+ unitId: unitMap[unit],
+ unitName: unit,
+ courses: []
+ });
+ }
+
+ const unitData = unitCoursesMap.get(unit);
+
+ // 检查是否已存在相同课程(去重)
+ const existingCourse = unitData.courses.find(c =>
+ c.courseName === courseName && c.date === date
+ );
+
+ if (!existingCourse) {
+ const [year, month, day] = date.split('/');
+ const formattedDate = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;
+
+ // 判断课程状态
+ const today = new Date();
+ today.setHours(0, 0, 0, 0); // 重置时间部分,只比较日期
+ const courseDate = new Date(year, parseInt(month) - 1, parseInt(day));
+ courseDate.setHours(0, 0, 0, 0);
+
+ const timeDiff = courseDate - today;
+ const daysDiff = Math.floor(timeDiff / (24 * 60 * 60 * 1000));
+
+ // 判断课程状态:
+ // - 已完成:状态为"已结束"或日期在今天之前
+ // - 直播中(current):今天的课程
+ // - 即将开始(upcoming):未来7天内的课程(在组件中会显示为"即将开始")
+ const isCompleted = status === '已结束' || daysDiff < 0;
+ const isCurrent = daysDiff === 0; // 今天的课程设为直播中
+ const isUpcoming = !isCompleted && !isCurrent && daysDiff > 0 && daysDiff <= 7; // 未来7天内
+
+ unitData.courses.push({
+ courseId: `c${unitData.unitId.replace('unit', '')}-${unitData.courses.length + 1}`,
+ courseName: courseName.length > 20 ? courseName.substring(0, 20) + '...' : courseName,
+ teacherName: teacher || '未知老师',
+ date: formattedDate,
+ completed: isCompleted,
+ current: isCurrent && !isCompleted,
+ upcoming: isUpcoming // 添加即将开始标识
+ });
+ }
+ }
+}
+
+// 按单元顺序组装数据
+const orderedUnits = [
+ '岗位体系认知',
+ '产业认知课',
+ '旅游产业全景与文旅基础知识',
+ '文旅服务:形象、沟通与体验的融合艺术',
+ '文旅与供应链基础',
+ '商业设计基础',
+ 'AIGC人工智能生成内容',
+ ' 全栈新媒体运营赋能文旅营销', // 注意CSV中前面有个空格
+ '活动策划基础',
+ '智慧文旅应用'
+];
+
+orderedUnits.forEach(unitName => {
+ if (unitCoursesMap.has(unitName)) {
+ const unitData = unitCoursesMap.get(unitName);
+ // 按日期排序课程
+ unitData.courses.sort((a, b) => a.date.localeCompare(b.date));
+ courseLiveList.push(unitData);
+ }
+});
+
+// 输出结果
+console.log('// 课程直播间的课程列表数据(从CSV生成)');
+console.log('mockData.courseLiveList =', JSON.stringify(courseLiveList, null, 2), ';');
+
+// 写入到文件
+fs.writeFileSync('courseLiveListData.json', JSON.stringify({ courseLiveList }, null, 2));
+console.log('\n✅ 课程列表数据已生成');
+console.log(`📚 共${courseLiveList.length}个单元`);
+console.log(`📖 共${courseLiveList.reduce((acc, unit) => acc + unit.courses.length, 0)}门课程`);
\ No newline at end of file
diff --git a/src/components/ClassRank/index.jsx b/src/components/ClassRank/index.jsx
new file mode 100644
index 0000000..a228121
--- /dev/null
+++ b/src/components/ClassRank/index.jsx
@@ -0,0 +1,81 @@
+import { Avatar, Spin, Empty } from "@arco-design/web-react";
+import IconFont from "@/components/IconFont";
+import "./index.css";
+
+const positions = ["item2", "item1", "item3"];
+const icons = ["icon2", "icon1", "icon3"];
+
+const Rank = ({ className, data, loading }) => {
+ const rankings = data?.rankings?.slice(0, 6) || [];
+
+ // 安全处理领奖台学生,确保至少有3个位置
+ const podiumStudents = [
+ rankings[1] || null, // 第2名
+ rankings[0] || null, // 第1名
+ rankings[2] || null, // 第3名
+ ];
+
+ const listStudents = rankings.slice(3);
+
+ return (
+
+
+
+ 班级排名
+
+ {loading ? (
+
+ ) : !data || !data?.rankings || data?.rankings?.length === 0 ? (
+
+ ) : (
+ <>
+
+ {podiumStudents.map((student, index) => {
+ return student ? (
+ -
+
+ {student.avatar ? (
+
+ ) : (
+ student.studentName?.charAt(0) || "?"
+ )}
+
+
+ {student.studentName || "未知"}
+
+
+
+ ) : (
+ -
+
+ -
+
+
+ );
+ })}
+
+
+ >
+ )}
+
+ );
+};
+
+export default Rank;
diff --git a/src/components/CoursesVideoPlayer/index.css b/src/components/CoursesVideoPlayer/index.css
index d0404eb..d5627cd 100644
--- a/src/components/CoursesVideoPlayer/index.css
+++ b/src/components/CoursesVideoPlayer/index.css
@@ -14,7 +14,7 @@
height: 545px;
box-sizing: border-box;
padding: 16px;
- border-radius: 8px;
+ border-radius: 16px;
background-color: #fff;
border: 1px solid #fff;
@@ -51,6 +51,12 @@
width: 100%;
height: 100%;
}
+
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ }
}
}
.courses-video-player-info {
@@ -58,7 +64,7 @@
width: 100%;
height: 234px;
border: 2px solid #fff;
- border-radius: 8px;
+ border-radius: 16px;
box-sizing: border-box;
padding: 16px;
background-image: linear-gradient(180deg, #daecff, #ffffff);
@@ -80,16 +86,35 @@
width: 64px;
height: 64px;
position: relative;
+ border-radius: 50%;
+ overflow: hidden;
- &::after {
- content: "";
+ img {
+ width: 150%;
+ height: 150%;
+ object-fit: cover;
+ object-position: center 30%;
position: absolute;
- left: 0;
- bottom: -5px;
+ left: 50%;
+ top: 2%;
+ transform: translateX(-50%);
+ }
+ }
+
+ .avatar-wrapper {
+ position: relative;
+ width: 64px;
+ height: 64px;
+
+ .living-icon {
+ position: absolute;
+ left: 1px;
+ bottom: -8px;
width: 62px;
height: 20px;
background-image: url("@/assets/images/CoursesVideoPlayer/living_icon.png");
background-size: 100% 100%;
+ z-index: 10;
}
}
@@ -120,7 +145,7 @@
align-items: center;
.living-data-item {
- width: 78px;
+ min-width: 78px;
height: 100%;
text-align: center;
display: flex;
@@ -137,6 +162,11 @@
color: #1d2129;
font-size: 16px;
font-weight: 600;
+ white-space: nowrap;
+ }
+
+ &:first-child {
+ min-width: 100px;
}
}
}
@@ -155,42 +185,44 @@
font-size: 16px;
font-weight: 600;
color: #1d2129;
- box-sizing: border-box;
- padding-left: 25px;
text-align: left;
+ display: flex;
+ align-items: center;
- &::before {
- content: "";
- position: absolute;
- left: 0;
- top: 0;
+ .title-icon {
width: 20px;
height: 20px;
- background-size: 100% 100%;
+ margin-right: 10px;
+ }
+ }
+
+ .teacher-introduce {
+ width: 100%;
+ min-height: 84px;
+ max-height: 120px;
+ overflow-y: auto;
+ font-size: 12px;
+ line-height: 18px;
+ color: #4e5969;
+
+ &::-webkit-scrollbar {
+ width: 4px;
+ }
+
+ &::-webkit-scrollbar-track {
+ background: #f2f3f5;
+ border-radius: 2px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: #c9cdd4;
border-radius: 2px;
}
}
-
- .icon1 {
- &::before {
- background-image: url("@/assets/images/CoursesVideoPlayer/hat_icon.png");
- }
- }
-
- .icon2 {
- &::before {
- background-image: url("@/assets/images/CoursesVideoPlayer/blank_icon.png");
- }
- }
- .teacher-introduce {
- width: 100%;
- height: 84px;
- overflow: hidden;
- }
.courses-video-player-teacher-introduce {
width: 100%;
- height: 100px;
- margin-bottom: 20px;
+ min-height: 100px;
+ margin-bottom: 10px;
}
.courses-video-player-teacher-tags {
width: 100%;
@@ -209,13 +241,13 @@
> li {
box-sizing: border-box;
- padding: 0 10px;
- background-color: #f2f3f5;
- color: #1d2129;
+ padding: 2px 8px;
+ background-color: #e5f1ff;
+ color: #0077ff;
font-size: 14px;
- font-weight: 600;
+ font-weight: 400;
margin-right: 10px;
- border-radius: 2px;
+ border-radius: 4px;
flex-shrink: 0;
flex-wrap: nowrap;
}
diff --git a/src/components/CoursesVideoPlayer/index.jsx b/src/components/CoursesVideoPlayer/index.jsx
index cb78fd6..099319a 100644
--- a/src/components/CoursesVideoPlayer/index.jsx
+++ b/src/components/CoursesVideoPlayer/index.jsx
@@ -2,11 +2,65 @@ import { Avatar } from "@arco-design/web-react";
import Locked from "@/components/Locked";
import "./index.css";
-export default ({ className = "", isLock = false }) => {
+export default ({ className = "", isLock = false, selectedCourse, teacherData, unitPosters }) => {
const handleClickBtn = (item) => {
console.log(item);
};
+ // 获取当前课程的导师信息
+ const currentTeacher = selectedCourse && teacherData
+ ? teacherData[selectedCourse.teacherName]
+ : teacherData?.["魏立慧"] || {
+ name: "魏立慧",
+ introduction: "企业资深一线HR,专注于为求职者提供一对一的个性化指导。通过真实招聘视角,深入剖析个人优势与短板、传授面试技巧、规划职业定位与发展路径,帮助学生快速提升求职竞争力。求职策略以实用落地为核心,注重互动交流与角色定位,让学员在轻松氛围中获得直击痛点的求职策略。",
+ specialties: ["深谙用人逻辑", "擅长挖掘优势", "沟通真诚自然", "点评直击要害"],
+ avatar: "//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp",
+ type: "企业资深HR"
+ };
+
+ // 需要调整头像位置的导师
+ const needsAdjustment = ["赵志强", "魏立慧", "郭建辉"].includes(currentTeacher.name);
+
+ // 根据导师设置不同的背景色 - 这些颜色提取自实际的PNG图片背景
+ const getAvatarBackground = (name) => {
+ const backgrounds = {
+ "刘杰": "#E3E2E0", // 浅灰色
+ "郭建辉": "#E0D9D3", // 米灰色
+ "赵志强": "#E3E2E0", // 浅灰色
+ "孙应战": "#E3E2E0", // 浅灰色
+ "魏立慧": "#DCD8D4" // 灰褐色
+ };
+ return backgrounds[name] || "#E3E2E0";
+ };
+
+ console.log("当前导师:", currentTeacher.name, "需要调整:", needsAdjustment);
+
+ // 获取当前课程信息
+ const courseName = selectedCourse?.courseName || "钢铁是怎样炼成的";
+ const courseDate = selectedCourse?.date || "09.01";
+ const unitName = selectedCourse?.unitName || "教育体系认知";
+
+ // 格式化日期时间
+ const formatDateTime = (date) => {
+ // 将 "2025-09-02" 格式转换为 "09.02"
+ if (date && date.includes('-')) {
+ const parts = date.split('-');
+ if (parts.length === 3) {
+ return `${parts[1]}.${parts[2]}`;
+ }
+ }
+ // 将 "9/1" 格式转换为 "09.01"
+ if (date && date.includes('/')) {
+ const parts = date.split('/');
+ if (parts.length === 2) {
+ const month = parts[0].padStart(2, '0');
+ const day = parts[1].padStart(2, '0');
+ return `${month}.${day}`;
+ }
+ }
+ return date;
+ };
+
return (
{/* 直播板块 */}
@@ -22,12 +76,20 @@ export default ({ className = "", isLock = false }) => {
handleClickBtn(1)}>< 上一集
- 钢铁是怎样炼成的
+ {courseName}
handleClickBtn(2)}>下一集 >
-
+ {selectedCourse?.current ? (
+
+ ) : (
+

+ )}
>
)}
@@ -35,18 +97,24 @@ export default ({ className = "", isLock = false }) => {
{/* 直播观众信息 */}
-
-
-
-
魏立慧
-
教育体系认知
+
+
+
+
+ {selectedCourse?.current &&
}
+
+
{currentTeacher.name}老师
+
{unitName}
开始
- 9/1 10:00
+ {formatDateTime(courseDate)} - 14:00
时长
@@ -63,16 +131,15 @@ export default ({ className = "", isLock = false }) => {
导师介绍
- 企业资深一线HR,专注于为求职者提供一对一的个性化指导。通过真实招聘视角,深入剖析个人优势与短板、传授面试技巧、规划职业定位与发展路径,帮助学生快速提升求职竞争力。求职策略以实用落地为核心,注重互动交流与角色定位,让学员在轻松氛围中获得直击痛点的求职策略。
+ {currentTeacher.introduction}
教师专长
- - 深谙用人逻辑
- - 擅长挖掘优势
- - 沟通真诚自然
- - 点评直击要害
+ {currentTeacher.specialties.map((specialty, index) => (
+ - {specialty}
+ ))}
diff --git a/src/components/EchartsProgress/index.jsx b/src/components/EchartsProgress/index.jsx
new file mode 100644
index 0000000..78a3306
--- /dev/null
+++ b/src/components/EchartsProgress/index.jsx
@@ -0,0 +1,109 @@
+import { useEffect, useRef } from "react";
+import * as echarts from "echarts";
+
+const EchartsProgress = ({
+ percent = 0,
+ strokeWidth = 20,
+ progressColor = new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+ { offset: 0, color: "#0275F2" },
+ { offset: 1, color: "#389CFA" },
+ ]), // 进度条颜色,默认为渐变色
+ backgroundColor = "#FFF", // 背景颜色
+}) => {
+ const chartRef = useRef(null);
+ const chartInstance = useRef(null);
+
+ useEffect(() => {
+ // 初始化图表
+ if (chartRef.current && !chartInstance.current) {
+ chartInstance.current = echarts.init(chartRef.current);
+ }
+
+ // 配置图表选项 - 得分环
+ const option = {
+ series: [
+ {
+ type: "gauge",
+ startAngle: 90,
+ radius: "100%",
+ endAngle: -270,
+ pointer: {
+ show: false,
+ },
+ progress: {
+ show: true,
+ overlap: false,
+ roundCap: true,
+ clip: false,
+ itemStyle: {
+ borderWidth: 0,
+ color: progressColor, // 设置进度条颜色
+ },
+ },
+ axisLine: {
+ lineStyle: {
+ width: strokeWidth,
+ color: [
+ [1, backgroundColor], // 背景颜色
+ ],
+ },
+ },
+ splitLine: {
+ show: false,
+ distance: 0,
+ length: 10,
+ },
+ axisTick: {
+ show: false,
+ },
+ axisLabel: {
+ show: false,
+ distance: 50,
+ },
+ data: [
+ {
+ value: percent,
+ detail: {
+ valueAnimation: true,
+ offsetCenter: ["0%", "0%"],
+ },
+ },
+ ],
+ detail: {
+ formatter: "{a|{value}%}\n{c| }\n{b|整体课程完成进度}",
+ rich: {
+ a: {
+ color: "#0077FF",
+ fontSize: 40,
+ align: "center",
+ },
+ c: { color: "transparent", lineHeight: 20 }, // 透明占位行
+ b: {
+ color: "#4E5969",
+ fontSize: 20,
+ align: "center",
+ },
+ },
+ },
+ },
+ ],
+ };
+
+ // 设置图表选项
+ chartInstance.current.setOption(option);
+
+ // 响应窗口大小变化
+ const resizeHandler = () => {
+ chartInstance.current.resize();
+ };
+
+ window.addEventListener("resize", resizeHandler);
+ return () => {
+ window.removeEventListener("resize", resizeHandler);
+ };
+ }, [backgroundColor, percent, progressColor, strokeWidth]);
+
+ return
;
+};
+
+export default EchartsProgress;
diff --git a/src/pages/Dashboard/components/CalendarTaskModule/index.css b/src/pages/Dashboard/components/CalendarTaskModule/index.css
index bb57347..66dd4b5 100644
--- a/src/pages/Dashboard/components/CalendarTaskModule/index.css
+++ b/src/pages/Dashboard/components/CalendarTaskModule/index.css
@@ -1,21 +1,28 @@
.module-calendar-task-wrapper {
- width: 360px;
- height: 508px;
- background-color: #fff;
+ width: 100%;
+ height: 393px;
border-radius: 16px;
- border: 1px solid #fff;
+ border-bottom: 1px solid #fff;
flex-shrink: 0;
box-sizing: border-box;
padding: 20px;
+ position: relative;
+ z-index: 1;
- .module-calendar-task-title {
- height: 30px;
- width: 100%;
- font-size: 20px;
- font-weight: 500;
- line-height: 30px;
- color: #262626;
- margin-bottom: 20px;
+ &::after {
+ content: "";
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ width: 160px;
+ height: 160px;
+ background-image: url("@/assets/images/Dashboard/CalendarTaskModule/calendar_task_bg.png");
+ background-size: 100% 100%;
+ z-index: -1;
+ }
+ .arco-calendar {
+ background-color: transparent;
}
.arco-calendar-header {
height: 50px;
@@ -46,10 +53,23 @@
align-items: center;
justify-content: center;
cursor: pointer;
-
&.is-today {
.date-number {
- background-color: rgb(0, 119, 255);
+ background-color: rgb(0, 119, 255) !important;
+ color: white;
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-weight: 500;
+ }
+ }
+
+ &.is-current-day {
+ .date-number {
+ background-color: rgba(10, 216, 239, 0.696);
color: white;
width: 28px;
height: 28px;
diff --git a/src/pages/Dashboard/components/CalendarTaskModule/index.jsx b/src/pages/Dashboard/components/CalendarTaskModule/index.jsx
index 4b047af..9e2e41d 100644
--- a/src/pages/Dashboard/components/CalendarTaskModule/index.jsx
+++ b/src/pages/Dashboard/components/CalendarTaskModule/index.jsx
@@ -1,31 +1,30 @@
+import dayjs from "dayjs";
+import { Calendar } from "@arco-design/web-react";
import "./index.css";
-import { Calendar, Skeleton } from "@arco-design/web-react";
-
-const CalendarTaskModule = ({ tasks = [], selectedDate, onDateChange, loading }) => {
- if (loading) {
- return (
-
- );
- }
+const CalendarTaskModule = ({ tasks = [], selectedDate, onDateChange }) => {
// 格式化今天的日期
const today = new Date();
- const formattedToday = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}-${String(today.getDate()).padStart(2, "0")}`;
-
+ const formattedToday = `${today.getFullYear()}-${String(
+ today.getMonth() + 1
+ ).padStart(2, "0")}-${String(today.getDate()).padStart(2, "0")}`;
+
// 获取有任务的日期集合
- const datesWithTasks = new Set(tasks?.map(task => task.date) || []);
-
+ const datesWithTasks = new Set(tasks?.map((task) => task.date) || []);
+
// 日历单元格渲染函数
const dateRender = (current) => {
- const dateStr = current.format('YYYY-MM-DD');
- const hasTasks = datesWithTasks.has(dateStr);
+ const dateStr = current.format("YYYY-MM-DD");
+ const hasTasks = datesWithTasks.has(dateStr); // 存在任务
+ const isCurrentDay = dateStr === dayjs(selectedDate).format("YYYY-MM-DD");
const isToday = dateStr === formattedToday;
-
+
return (
-
+
{current.date()}
{hasTasks &&
}
@@ -37,14 +36,14 @@ const CalendarTaskModule = ({ tasks = [], selectedDate, onDateChange, loading })
// Arco Calendar passes a dayjs object
if (date && date.format) {
// Convert dayjs to Date object
- const dateStr = date.format('YYYY-MM-DD');
- const dateObj = new Date(dateStr + 'T00:00:00');
+ const dateStr = date.format("YYYY-MM-DD");
+ const dateObj = new Date(dateStr + "T00:00:00");
if (!isNaN(dateObj.getTime())) {
onDateChange(dateObj);
}
} else if (dateString) {
// Fallback to dateString if available
- const dateObj = new Date(dateString + 'T00:00:00');
+ const dateObj = new Date(dateString + "T00:00:00");
if (!isNaN(dateObj.getTime())) {
onDateChange(dateObj);
}
@@ -54,12 +53,15 @@ const CalendarTaskModule = ({ tasks = [], selectedDate, onDateChange, loading })
return (
-
日历
{
const navigate = useNavigate();
@@ -12,41 +29,24 @@ const QuickAccess = () => {
};
return (
-
快捷入口
+
+
+ 快捷入口
+
- - handleClick("/expert-support")}
- >
-
- 专家支持中心
-
- - handleClick("/live")}
- >
-
- 课程直播间
-
- - handleClick("/career-tree")}
- >
-
- 就业管家知识树
-
+ {QuickAccessArray.map((item, index) => (
+ - handleClick(item.route)}
+ >
+
+
{item.name}
+
+ ))}
);
diff --git a/src/pages/Dashboard/components/StartClass/index.css b/src/pages/Dashboard/components/StartClass/index.css
index f973e8f..e1955e0 100644
--- a/src/pages/Dashboard/components/StartClass/index.css
+++ b/src/pages/Dashboard/components/StartClass/index.css
@@ -1,15 +1,15 @@
.start-class-wrapper {
- width: 455px;
- height: 508px;
- margin-right: 20px;
+ width: 100%;
+ height: 325px;
border-radius: 16px;
border: 1px solid #fff;
flex-shrink: 0;
background-position: 50% 30%;
box-sizing: border-box;
- padding: 20px;
+ padding: 10px 20px;
background-color: #e2edff;
position: relative;
+ overflow: hidden;
&::after {
content: "";
@@ -23,75 +23,108 @@
}
.start-class-title {
- height: 30px;
width: 100%;
+ height: 27px;
font-size: 20px;
- font-weight: 500;
- line-height: 30px;
- color: #262626;
- margin-bottom: 20px;
+ font-weight: 700;
+ line-height: 27px;
+ color: #1d2129;
position: relative;
box-sizing: border-box;
- padding-left: 30px;
+ margin-bottom: 10px;
+ display: flex;
+ align-items: center;
- &::before {
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
+ .title-icon {
width: 24px;
height: 24px;
- content: "";
- background-image: url("@/assets/images/Dashboard/StartClass/start_class_title_icon.png");
- background-size: 100% 100%;
+ margin-right: 10px;
}
}
.start-class-content {
- height: 421px;
width: 100%;
- overflow-y: auto;
+ height: 246px;
+ overflow-y: hidden;
display: flex;
- justify-content: flex-start;
+ justify-content: space-between;
align-items: center;
- flex-direction: column;
- .start-class-item {
- margin-bottom: 15px;
- width: 100%;
+ .start-class-item-left {
+ width: 357px;
+ height: 100%;
display: flex;
- justify-content: flex-start;
+ justify-content: space-between;
align-items: center;
flex-direction: column;
- border-radius: 12px;
- background-color: #fff;
- box-sizing: border-box;
- padding: 15px;
- z-index: 1;
+ > li {
+ width: 100%;
+ height: 117px;
+ border-radius: 12px;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ flex-direction: column;
+ background-color: #fff;
+ box-sizing: border-box;
+ padding: 15px;
+ z-index: 1;
+ }
+ }
+
+ .start-class-item-right {
+ width: 357px;
+ height: 100%;
+
+ > li {
+ width: 100%;
+ height: 100%;
+ border-radius: 12px;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ flex-direction: column;
+ background-color: #fff;
+ box-sizing: border-box;
+ padding: 15px;
+ z-index: 1;
+ }
+ }
+
+ .start-class-item {
.start-class-item-title {
width: 100%;
- height: 27px;
- line-height: 27px;
- font-size: 20px;
- font-weight: 500;
- color: #262626;
+ height: 25px;
+ line-height: 25px;
+ font-size: 18px;
+ font-weight: 700;
+ color: #1d2129;
text-align: left;
box-sizing: border-box;
- padding-left: 15px;
position: relative;
margin-bottom: 10px;
+ display: flex;
+ align-items: center;
- &::before {
- content: "";
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
- width: 4px;
- height: 16px;
- background-color: #0275f2;
- border-radius: 100px;
+ .title-icon {
+ width: 20px;
+ height: 20px;
+ margin-right: 5px;
+ }
+ > .num {
+ margin-left: 10px;
+ width: 18px;
+ height: 18px;
+ text-align: center;
+ line-height: 15px;
+ box-sizing: border-box;
+ border-radius: 4px;
+ font-size: 12px;
+ font-weight: 400;
+ color: #0077ff;
+ background-color: rgba(0, 119, 255, 0.1);
+ border: 1px solid rgba(0, 119, 255, 0.2);
}
}
@@ -101,10 +134,11 @@
justify-content: flex-start;
align-items: center;
flex-direction: column;
+ overflow-y: auto;
.start-class-item-list-item {
width: 100%;
- color: #616065;
+ color: #86909c;
font-size: 14px;
text-align: left;
margin-top: 5px;
diff --git a/src/pages/Dashboard/components/StartClass/index.jsx b/src/pages/Dashboard/components/StartClass/index.jsx
index 6823073..19fc570 100644
--- a/src/pages/Dashboard/components/StartClass/index.jsx
+++ b/src/pages/Dashboard/components/StartClass/index.jsx
@@ -1,4 +1,5 @@
import { Skeleton } from "@arco-design/web-react";
+import IconFont from "@/components/IconFont";
import "./index.css";
const StartClass = ({ courses, tasks, loading }) => {
@@ -12,20 +13,23 @@ const StartClass = ({ courses, tasks, loading }) => {
}
// 获取待办任务
- const pendingTasks = tasks?.allTasks?.filter(task =>
- task.status === 'PENDING' || task.status === 'IN_PROGRESS'
- ).slice(0, 5) || [];
+ const pendingTasks =
+ tasks?.allTasks
+ ?.filter(
+ (task) => task.status === "PENDING" || task.status === "IN_PROGRESS"
+ )
+ .slice(0, 5) || [];
// 格式化日期显示
const formatCourseDate = (dateStr) => {
const date = new Date(dateStr);
const today = new Date();
const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);
-
+
if (date.toDateString() === today.toDateString()) {
- return '今日已上';
+ return "今日已上";
} else if (date.toDateString() === yesterday.toDateString()) {
- return '昨日已上';
+ return "昨日已上";
} else {
return `${date.getMonth() + 1}/${date.getDate()}已上`;
}
@@ -33,60 +37,73 @@ const StartClass = ({ courses, tasks, loading }) => {
return (
-
开始上课
+
+
+ 开始上课
+
- -
-
最近课程
-
- {courses?.recentCourses?.length > 0 ? (
- courses.recentCourses.slice(0, 3).map((course, index) => (
- -
- {formatCourseDate(course.date)}《{course.courseName}》
+
+
-
+
+
+ 下次上课
+ {courses?.nextCourse?.length || 0}
+
+
+ {courses?.nextCourse ? (
+ -
+ 《{courses.nextCourse.courseName}》
+ {courses.nextCourse.classroom && (
+
+ - {courses.nextCourse.classroom}
+
+ )}
- ))
- ) : (
- - 暂无最近课程记录
- )}
- {courses?.todaysCourses?.length > 0 && (
- courses.todaysCourses.slice(0, 2).map((course, index) => (
- -
- 今日计划《{course.courseName}》
-
- ))
- )}
-
-
-
-
-
下次上课
-
- {courses?.nextCourse ? (
- -
- 《{courses.nextCourse.courseName}》
- {courses.nextCourse.classroom && (
- - {courses.nextCourse.classroom}
- )}
-
- ) : (
- - 暂无安排课程
- )}
-
-
-
-
-
- 待办事项({pendingTasks.length})
-
-
- {pendingTasks.length > 0 ? (
- pendingTasks.map((task) => (
- -
- 《{task.courseName}》{task.title}
-
- ))
- ) : (
- - 暂无待办事项
- )}
-
-
+ ) : (
+
- 暂无安排课程
+ )}
+
+
+
-
+
+
+ 待办事项
+ {pendingTasks.length || 0}
+
+
+ {pendingTasks.length > 0 ? (
+ pendingTasks.map((task) => (
+ -
+ 《{task.courseName}》{task.title}
+
+ ))
+ ) : (
+ - 暂无待办事项
+ )}
+
+
+
+
+
+
-
+
+
+ 最近课程
+ {courses?.recentCourses?.length || 0}
+
+
+ {courses?.recentCourses?.length > 0 ? (
+ courses?.recentCourses?.map((course, index) => (
+ -
+ {formatCourseDate(course.date)}《{course.courseName}》
+
+ ))
+ ) : (
+ - 暂无最近课程记录
+ )}
+
+
+
);
diff --git a/src/pages/Dashboard/components/StudyStatus/index.css b/src/pages/Dashboard/components/StudyStatus/index.css
index 1adb598..b53c1fc 100644
--- a/src/pages/Dashboard/components/StudyStatus/index.css
+++ b/src/pages/Dashboard/components/StudyStatus/index.css
@@ -1,16 +1,15 @@
.module-study-status-wrapper {
- width: 360px;
- height: 413px;
- margin-right: 20px;
+ width: 373px;
+ height: 420px;
border-radius: 16px;
border: 1px solid #fff;
+ overflow: hidden;
flex-shrink: 0;
background-size: 150% 120%;
background-position: 50% 30%;
box-sizing: border-box;
padding: 20px;
background-color: #e8f6ff;
- margin-top: 20px;
display: flex;
flex-direction: column;
align-items: center;
@@ -38,18 +37,13 @@
margin-bottom: 20px;
position: relative;
box-sizing: border-box;
- padding-left: 30px;
+ display: flex;
+ align-items: center;
- &::before {
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
+ .title-icon {
width: 24px;
height: 24px;
- content: "";
- background-image: url("@/assets/images/Dashboard/StudyStatus/study-status_title_icon.png");
- background-size: 100% 100%;
+ margin-right: 10px;
}
}
diff --git a/src/pages/Dashboard/components/StudyStatus/index.jsx b/src/pages/Dashboard/components/StudyStatus/index.jsx
index 6a94ca7..3903343 100644
--- a/src/pages/Dashboard/components/StudyStatus/index.jsx
+++ b/src/pages/Dashboard/components/StudyStatus/index.jsx
@@ -1,25 +1,16 @@
-import EchartsProgress from "../EchartsProgress";
-import { Skeleton } from "@arco-design/web-react";
+import EchartsProgress from "@/components/EchartsProgress";
+import IconFont from "@/components/IconFont";
import "./index.css";
-const StudyStatus = ({ progress = 0, loading }) => {
- if (loading) {
- return (
-
- );
- }
-
+const StudyStatus = ({ progress = 0 }) => {
return (
-
学习情况
+
+
+ 学习情况
+
-
- 整体课程完成进度 ({progress || 0}%)
-
);
diff --git a/src/pages/Dashboard/components/TaskList/index.css b/src/pages/Dashboard/components/TaskList/index.css
index e2b0f0a..3ac01b5 100644
--- a/src/pages/Dashboard/components/TaskList/index.css
+++ b/src/pages/Dashboard/components/TaskList/index.css
@@ -1,6 +1,5 @@
.module-tasks-wrapper {
- width: 360px;
- height: 413px;
+ width: 100%;
background-color: #fff;
border-radius: 16px;
border: 1px solid #fff;
@@ -12,6 +11,18 @@
flex-direction: column;
align-items: center;
justify-content: flex-start;
+ position: relative;
+
+ &::after {
+ content: "";
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 127px;
+ height: 95px;
+ background-image: url("@/assets/images/Dashboard/TaskList/task_list_bg.png");
+ background-size: 100% 100%;
+ }
.module-tasks-title {
height: 30px;
@@ -20,23 +31,22 @@
font-weight: 500;
display: flex;
align-items: center;
- justify-content: space-between;
- .task-count {
- font-size: 14px;
- color: #86909c;
- font-weight: normal;
+ .title-icon {
+ width: 24px;
+ height: 24px;
+ margin-right: 10px;
}
}
.no-tasks {
+ margin-top: 130px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
-
.task-type {
font-weight: bold;
color: #1d2129;
@@ -47,36 +57,29 @@
padding: 2px 6px;
border-radius: 4px;
margin-left: 8px;
-
+
&.status-pending {
background-color: #fff3cd;
color: #856404;
}
-
+
&.status-in_progress {
background-color: #d1ecf1;
color: #0c5460;
}
-
+
&.status-completed {
background-color: #d4edda;
color: #155724;
}
}
- .classroom {
- color: #86909c;
- font-size: 12px;
- line-height: 30px;
- color: #262626;
- }
-
.module-tasks-list {
margin-top: 20px;
width: 100%;
- height: 326px;
+ height: 452px;
box-sizing: border-box;
- padding: 0 20px;
+
display: flex;
flex-direction: column;
align-items: center;
@@ -122,7 +125,7 @@
}
.module-tasks-item-content {
- width: 294;
+ width: 100%;
height: 64px;
margin-top: 5px;
margin-left: 16px;
@@ -156,12 +159,13 @@
}
.module-tasks-item-content-info {
- width: 287px;
+ width: 100%;
height: 58px;
border-radius: 8px;
background-color: #fafafa;
padding: 10px;
box-sizing: border-box;
+ position: relative;
> p {
font-size: 10px;
color: #616065;
@@ -178,7 +182,7 @@
.module-tasks-item-content-info-duration {
position: absolute;
- right: 0;
+ right: 20px;
top: 50%;
transform: translateY(-50%);
font-size: 10px;
diff --git a/src/pages/Dashboard/components/TaskList/index.jsx b/src/pages/Dashboard/components/TaskList/index.jsx
index 485e971..237ef07 100644
--- a/src/pages/Dashboard/components/TaskList/index.jsx
+++ b/src/pages/Dashboard/components/TaskList/index.jsx
@@ -1,107 +1,87 @@
-import { Avatar, Empty, Skeleton } from "@arco-design/web-react";
-import "./index.css";
-
-const TaskList = ({ tasks = [], selectedDate, loading }) => {
- if (loading) {
- return (
-
- );
- }
-
- const formatDate = (date) => {
- return date.toLocaleDateString("zh-CN", {
- year: "numeric",
- month: "long",
- day: "numeric",
- });
- };
-
- const getTaskTypeText = (type) => {
- const typeMap = {
- HOMEWORK: "作业",
- PROJECT: "项目",
- REPORT: "报告",
- INTERVIEW: "面试",
- OTHER: "其他",
- };
- return typeMap[type] || type;
- };
-
- // const getPriorityClass = (priority) => {
- // const classMap = {
- // URGENT: "urgent",
- // HIGH: "high",
- // MEDIUM: "medium",
- // LOW: "low",
- // };
- // return classMap[priority] || "medium";
- // };
-
- return (
-
-
- 事项 - {formatDate(selectedDate)}
- {tasks.length > 0 && (
- ({tasks.length})
- )}
-
-
- {tasks.length === 0 ? (
-
-
-
- ) : (
-
- {tasks.map((item, index) => (
- -
-
-
- {item?.teacherAvatar ? (
-
- ) : (
- item?.teacherName?.charAt(0) || "T"
- )}
-
-
- {item?.teacherName || "未知教师"}
-
-
-
-
-
-
- {getTaskTypeText(item.type)}:
-
- {item?.title}
-
-
- 课程名称:{item?.courseName}
-
- {item?.duration}
-
- {/*
- {item.status === 'PENDING' ? '待完成' :
- item.status === 'IN_PROGRESS' ? '进行中' :
- item.status === 'COMPLETED' ? '已完成' : '未知'}
- */}
-
-
-
-
- ))}
-
- )}
-
- );
-};
-
-export default TaskList;
+import { Avatar, Skeleton, Empty } from "@arco-design/web-react";
+import IconFont from "@/components/IconFont";
+import "./index.css";
+
+const TaskList = ({ tasks = [], loading }) => {
+ if (loading) {
+ return (
+
+ );
+ }
+
+ const getTaskTypeText = (type) => {
+ const typeMap = {
+ HOMEWORK: "作业",
+ PROJECT: "项目",
+ REPORT: "报告",
+ INTERVIEW: "面试",
+ OTHER: "其他",
+ };
+ return typeMap[type] || type;
+ };
+
+ return (
+
+
+
+ 当日事项
+
+ {tasks.length === 0 ? (
+
+
+
+ ) : (
+
+ {tasks.map((item, index) => (
+ -
+
+
+ {item?.teacherAvatar ? (
+
+ ) : (
+ item?.teacherName?.charAt(0) || "T"
+ )}
+
+
+ {item?.teacherName || "未知教师"}
+
+
+
+
+
+
+ {getTaskTypeText(item.type)}:
+
+ {item?.title}
+
+
+ 课程名称:{item?.courseName}
+
+ {item?.duration}
+
+ {/*
+ {item.status === 'PENDING' ? '待完成' :
+ item.status === 'IN_PROGRESS' ? '进行中' :
+ item.status === 'COMPLETED' ? '已完成' : '未知'}
+ */}
+
+
+
+
+ ))}
+
+ )}
+
+ );
+};
+
+export default TaskList;
diff --git a/src/pages/Dashboard/index.css b/src/pages/Dashboard/index.css
index e5334c2..f07cb45 100644
--- a/src/pages/Dashboard/index.css
+++ b/src/pages/Dashboard/index.css
@@ -14,15 +14,51 @@
.dashboard {
width: 100%;
animation: fadeIn 0.3s ease-in-out;
-}
-/* Dashboard网格布局 - 按用户要求的两排布局 */
-.dashboard-grid {
- display: flex;
- justify-content: flex-start;
- align-items: flex-start;
- flex-wrap: wrap;
- flex-shrink: 0;
- box-sizing: border-box;
- padding: 20px;
+ .dashboard-wrapper {
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ flex-wrap: wrap;
+ box-sizing: border-box;
+ padding: 20px;
+
+ .dashboard-left-content {
+ width: 766px;
+ height: 966px;
+ flex-shrink: 0;
+
+ .status-rank-wrapper {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 20px;
+
+ .class-rank-wrapper {
+ height: 420px;
+ }
+ }
+ }
+
+ .dashboard-right-content {
+ flex: 1;
+ height: 966px;
+ margin-left: 20px;
+ background-color: #ffffff;
+ border-radius: 16px;
+ position: relative;
+
+ &::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100px;
+ background-image: url("@/assets/images/Dashboard/right_content_bg.png");
+ background-size: 100% 100%;
+ }
+ }
+ }
}
diff --git a/src/pages/Dashboard/index.jsx b/src/pages/Dashboard/index.jsx
index e94f4a7..e1cd1cd 100644
--- a/src/pages/Dashboard/index.jsx
+++ b/src/pages/Dashboard/index.jsx
@@ -3,7 +3,7 @@ import StartClass from "./components/StartClass";
import QuickAccess from "./components/QuickAccess";
import CalendarTaskModule from "./components/CalendarTaskModule";
import StudyStatus from "./components/StudyStatus";
-import Rank from "@/components/Rank";
+import ClassRank from "@/components/ClassRank";
import StageProgress from "@/components/StageProgress";
import TaskList from "./components/TaskList";
import { getDashboardStatistics } from "@/services";
@@ -52,38 +52,39 @@ const Dashboard = () => {
-
);
diff --git a/src/pages/LivePage/index.jsx b/src/pages/LivePage/index.jsx
index 2eeeeda..75cbef4 100644
--- a/src/pages/LivePage/index.jsx
+++ b/src/pages/LivePage/index.jsx
@@ -1,15 +1,23 @@
+import { useState } from "react";
import CoursesVideoPlayer from "@/components/CoursesVideoPlayer";
import CourseList from "@/components/CourseList";
import StageProgress from "@/components/StageProgress";
+import { mockData } from "@/data/mockData";
import "./index.css";
const LivePage = () => {
+ const [selectedCourse, setSelectedCourse] = useState(null);
+
+ const handleCourseClick = (course) => {
+ setSelectedCourse(course);
+ };
+
return (
);
diff --git a/src/pages/PersonalProfile/components/AttendanceRingChart/index.jsx b/src/pages/PersonalProfile/components/AttendanceRingChart/index.jsx
index 8eed572..cc7c767 100644
--- a/src/pages/PersonalProfile/components/AttendanceRingChart/index.jsx
+++ b/src/pages/PersonalProfile/components/AttendanceRingChart/index.jsx
@@ -73,16 +73,16 @@ const AttendanceRingChart = ({
{centerContent && (
{
const studentInfo = useSelector((state) => state.student.studentInfo);
-
return (
@@ -47,29 +47,43 @@ const ProfileCard = () => {
-
-
+
学校
{studentInfo?.school || "-"}
-
-
+
专业
{studentInfo?.major || "-"}
-
-
- 班级
+
+
+ 就业管家课程
+
{studentInfo?.className || "-"}
-
-
- 学习阶段
+
+ 垂直方向
{studentInfo?.stageName || "-"}
diff --git a/src/pages/PersonalProfile/components/ScoreRingChart/index.jsx b/src/pages/PersonalProfile/components/ScoreRingChart/index.jsx
index 6bb212c..37abc6d 100644
--- a/src/pages/PersonalProfile/components/ScoreRingChart/index.jsx
+++ b/src/pages/PersonalProfile/components/ScoreRingChart/index.jsx
@@ -1,12 +1,10 @@
-import React, { useRef, useEffect } from "react";
+import { useRef, useEffect } from "react";
import * as echarts from "echarts";
-const screenWidth = window.screen.width; // 物理屏幕宽度(单位:像素)
const ScoreRingChart = ({
className = "",
ringData = [], // 数据
- title = "",
- bgColor = "#F7F8FA", // 未填充部分背景色
+ bgColor = "#EDF4FF", // 未填充部分背景色
}) => {
// 创建图表容器引用
const chartRef = useRef(null);
@@ -44,7 +42,7 @@ const ScoreRingChart = ({
},
axisLine: {
lineStyle: {
- width: 10,
+ width: 20,
color: [[1, bgColor]],
},
},
@@ -58,23 +56,13 @@ const ScoreRingChart = ({
show: false,
},
data: [ringData[0]],
- title: {
- fontSize: 14,
- },
- detail: {
- fontSize: 16,
- color: "#1D2129",
- formatter: title,
- lineHeight: 20,
- height: 40,
- offsetCenter: [0, 0],
- },
+ detail: false,
},
{
type: "gauge",
startAngle: 90,
endAngle: -270,
- radius: "80%",
+ radius: "70%",
pointer: {
show: false,
},
@@ -86,7 +74,7 @@ const ScoreRingChart = ({
},
axisLine: {
lineStyle: {
- width: 10,
+ width: 20,
color: [[1, bgColor]],
},
},
@@ -126,7 +114,7 @@ const ScoreRingChart = ({
chartInstance.current = null;
}
};
- }, [ringData, title, bgColor]);
+ }, [ringData, bgColor]);
return ;
};
diff --git a/src/pages/PersonalProfile/components/StudyStudes/index.css b/src/pages/PersonalProfile/components/StudyStudes/index.css
index d454ede..df3f099 100644
--- a/src/pages/PersonalProfile/components/StudyStudes/index.css
+++ b/src/pages/PersonalProfile/components/StudyStudes/index.css
@@ -1,14 +1,16 @@
.study-studes-card-wrapper {
width: 100%;
height: 100%;
- border-radius: 8px;
- background-color: #fff;
+ border-radius: 16px;
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
box-sizing: border-box;
padding: 20px;
+ position: relative;
+ z-index: 1;
+ overflow: hidden;
.study-studes-card-title {
height: 30px;
@@ -18,7 +20,16 @@
line-height: 30px;
color: #262626;
margin-bottom: 20px;
+ display: flex;
+ align-items: center;
+
+ .title-icon {
+ width: 24px;
+ height: 24px;
+ margin-right: 10px;
+ }
}
+
.study-studes-card-spin {
margin: auto;
}
@@ -27,164 +38,208 @@
width: 100%;
height: 100%;
display: flex;
- justify-content: flex-start;
+ justify-content: space-around;
align-items: flex-start;
flex-wrap: wrap;
.study-studes-card-study-info {
+ width: 356px;
+ height: 310px;
flex-shrink: 0;
- width: 338px;
- height: 308px;
+ border-radius: 12px;
position: relative;
- background-image: url("@/assets/images/PersonalProfile/study_study_bg.png");
- background-size: 100% 100%;
+ background-color: rgba(255, 255, 255, 0.6);
+ border: 2px solid rgba(255, 255, 255, 0.8);
+ box-sizing: border-box;
+ padding: 10px 0;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-direction: column;
.study-studes-card-time-wrapper {
- position: absolute;
- bottom: 20px;
- left: 50%;
- transform: translateX(-50%);
border-radius: 8px;
border: 1px solid #fff;
- width: 314px;
- height: 156px;
+ width: 324px;
+ height: 133px;
background-color: #fff;
- box-shadow: 2px 2px 16.4px 0px rgba(103, 162, 247, 0.25);
box-sizing: border-box;
- padding: 20px;
- .study-studes-card-study-time-wrapper {
+ padding: 20px 10px;
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ flex-direction: column;
+
+ .study-studes-card-study-info-title {
width: 100%;
- height: 60px;
- display: flex;
- justify-content: flex-start;
- align-items: flex-start;
- flex-direction: column;
+ height: 24px;
+ font-size: 16px;
+ font-weight: 400;
+ color: #1d2129;
+ position: relative;
+ box-sizing: border-box;
+ padding-left: 30px;
- .study-studes-card-study-info-title {
- font-size: 14px;
- font-weight: 600;
- color: #4e5969;
- margin-bottom: 10px;
+ &::before {
+ content: "";
+ width: 24px;
+ height: 24px;
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ background-image: url("@/assets/images/PersonalProfile/title_icon.png");
+ background-size: 100% 100%;
}
+ }
- .study-studes-card-study-time-line-class {
- > i {
- background: linear-gradient(
- to right,
- #4564ff,
- #ab2cff
- ) !important;
- }
- }
- .study-studes-card-study-time-line {
- width: 265px;
- height: 10px;
+ .study-studes-card-study-time-line {
+ width: 290px;
+ height: 12px;
+ border-radius: 12px;
+ background-color: #f4f7f9;
+ position: relative;
+ margin-bottom: 10px;
+ > i {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
border-radius: 12px;
- background-color: #cedefa;
- position: relative;
- > i {
+ > span {
position: absolute;
- top: 0;
- left: 0;
- height: 100%;
- border-radius: 12px;
- background: linear-gradient(to right, #2c7aff, #00aeff);
-
- > span {
- position: absolute;
- display: block;
- right: 0;
- top: 30%;
- transform: translate(50%, 30%);
- font-style: normal;
- width: 38px;
- height: 21px;
- line-height: 22px;
- text-align: center;
- font-size: 12px;
- font-weight: 600;
- color: #2358ed;
- background-image: url("@/assets/images/PersonalProfile/line_icon.png");
- background-size: 100% 100%;
- }
+ display: block;
+ right: 0;
+ top: -25px;
+ transform: translateX(50%);
+ font-style: normal;
+ width: 46px;
+ height: 24px;
+ line-height: 20px;
+ text-align: center;
+ font-size: 14px;
+ font-weight: 700;
+ color: #fff;
+ background-size: 100% 100%;
}
+
+ .icon1 {
+ background-image: url("@/assets/images/PersonalProfile/line_icon1.png");
+ }
+ .icon2 {
+ background-image: url("@/assets/images/PersonalProfile/line_icon2.png");
+ }
+ }
+ .line1 {
+ background: linear-gradient(to right, #2c7dff, #2da7ff);
+ }
+ .line2 {
+ background: linear-gradient(to right, #37c850, #86e263);
}
}
}
}
.study-studes-card-study-progress {
+ height: 310px;
+ width: 356px;
+ box-sizing: border-box;
+ border-radius: 12px;
+ background-color: rgba(255, 255, 255, 0.6);
+ border: 2px solid rgba(255, 255, 255, 0.8);
display: flex;
- justify-content: flex-start;
+ justify-content: center;
align-items: center;
- flex-direction: column;
- height: 308px;
- width: 330px;
- border-radius: 8px;
- margin-left: 20px;
-
- .study-studes-card-study-progress-chart {
- width: 250px;
- height: 250px;
- margin-top: 50px;
- margin-bottom: 20px;
- }
-
- .study-studes-card-study-progress-title {
- color: #1d2129;
- font-size: 16px;
- font-weight: 600;
- margin-top: 20px;
- }
- }
- .study-studes-card-curriculum-homework {
- margin-left: 40px;
- margin-right: 40px;
+ margin-left: 15px;
+ margin-bottom: 20px;
}
+
.study-studes-card-curriculum {
- width: 194px;
- height: 350px;
+ width: 232px;
+ height: 390px;
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
- margin-top: 20px;
+ box-sizing: border-box;
+ border-radius: 12px;
+ background-color: rgba(255, 255, 255, 0.6);
+ border: 2px solid rgba(255, 255, 255, 0.8);
+ padding: 10px;
+
+ .study-studes-card-curriculum-title {
+ width: 100%;
+ height: 24px;
+ font-size: 16px;
+ font-weight: 400;
+ color: #1d2129;
+ position: relative;
+ box-sizing: border-box;
+ padding-left: 30px;
+ margin-bottom: 10px;
+
+ &::before {
+ content: "";
+ width: 24px;
+ height: 24px;
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ background-image: url("@/assets/images/PersonalProfile/title_icon.png");
+ background-size: 100% 100%;
+ }
+ }
.study-studes-card-curriculum-chart {
- width: 194px;
- height: 200px;
- margin-bottom: 30px;
+ width: 180px;
+ height: 180px;
+ margin-bottom: 10px;
}
.study-studes-card-curriculum-info:last-child {
margin-bottom: 0;
}
.study-studes-card-curriculum-info {
- width: 194px;
- height: 69px;
- border-radius: 8px;
- background-color: #f7f8fa;
+ width: 200px;
+ height: 73px;
+ border-radius: 12px;
+ background-color: #ffffff;
box-sizing: border-box;
padding: 10px;
- margin-bottom: 20px;
+ margin-bottom: 10px;
> p {
- font-size: 14px;
- font-weight: 400;
- color: #4e5969;
+ width: 100%;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ > i {
+ width: 12px;
+ height: 12px;
+ border-radius: 3px;
+ margin-right: 5px;
+ }
+ .my-i {
+ background-image: linear-gradient(0deg, #2c7aff, #2cb1ff);
+ }
+ .class-i {
+ background-image: linear-gradient(0deg, #25c343, #99e869);
+ }
+ .loss-i {
+ background-image: linear-gradient(0deg, #ff9a2d, #ffc02d);
+ }
+ > span {
+ font-size: 14px;
+ font-weight: 400;
+ color: #1d2129;
+ }
}
> span {
font-size: 20px;
- font-weight: 600;
- }
- .study-studes-card-curriculum-info-span1 {
- color: #0aa4ff;
- }
- .study-studes-card-curriculum-info-span2 {
- color: #5e57ff;
- }
- .study-studes-card-curriculum-info-span3 {
- color: #ff9d2c;
+ font-weight: 900;
+ font-family: "HarmonyOS Sans TC";
+ color: #1d2129;
}
}
}
diff --git a/src/pages/PersonalProfile/components/StudyStudes/index.jsx b/src/pages/PersonalProfile/components/StudyStudes/index.jsx
index f17565b..1aa9cb9 100644
--- a/src/pages/PersonalProfile/components/StudyStudes/index.jsx
+++ b/src/pages/PersonalProfile/components/StudyStudes/index.jsx
@@ -1,7 +1,8 @@
import * as echarts from "echarts";
import { useSelector } from "react-redux";
import { Spin } from "@arco-design/web-react";
-import StudyProgress from "../StudyProgress";
+import IconFont from "@/components/IconFont";
+import EchartsProgress from "@/components/EchartsProgress";
import ScoreRingChart from "../ScoreRingChart";
import AttendanceRingChart from "../AttendanceRingChart";
import "./index.css";
@@ -28,27 +29,27 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading }) => {
const courseRingData = [
{
value: personalCourseProgress,
- name: "我的",
- title: {
- offsetCenter: ["-30%", "-90%"],
- },
+ // name: "我的",
+ // title: {
+ // offsetCenter: ["-30%", "-90%"],
+ // },
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
{ offset: 0, color: "#2C7AFF" },
- { offset: 1, color: "#00AEFF" },
+ { offset: 1, color: "#2CB9FF" },
]),
},
},
{
value: classAverageCourseProgress,
- name: "班级",
- title: {
- offsetCenter: ["-60%", "-90%"],
- },
+ // name: "班级",
+ // title: {
+ // offsetCenter: ["-60%", "-90%"],
+ // },
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
- { offset: 0, color: "#4564FF" },
- { offset: 1, color: "#AB2CFF" },
+ { offset: 0, color: "#25C343" },
+ { offset: 1, color: "#A3EB6C" },
]),
},
},
@@ -57,27 +58,27 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading }) => {
const homeworkRingData = [
{
value: personalHomeworkProgress,
- name: "我的",
- title: {
- offsetCenter: ["-30%", "-90%"],
- },
+ // name: "我的",
+ // title: {
+ // offsetCenter: ["-30%", "-90%"],
+ // },
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
{ offset: 0, color: "#2C7AFF" },
- { offset: 1, color: "#00AEFF" },
+ { offset: 1, color: "#2CB9FF" },
]),
},
},
{
value: classAverageHomeworkProgress,
- name: "班级",
- title: {
- offsetCenter: ["-60%", "-90%"],
- },
+ // name: "班级",
+ // title: {
+ // offsetCenter: ["-60%", "-90%"],
+ // },
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
- { offset: 0, color: "#4564FF" },
- { offset: 1, color: "#AB2CFF" },
+ { offset: 0, color: "#25C343" },
+ { offset: 1, color: "#A3EB6C" },
]),
},
},
@@ -90,16 +91,28 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading }) => {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
{ offset: 0, color: "#2C7AFF" },
- { offset: 1, color: "#00D5FF" },
+ { offset: 1, color: "#2CB9FF" },
+ ]),
+ },
+ },
+ {
+ name: "缺勤率",
+ value: absenceRate,
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
+ { offset: 0, color: "#FF9A2D" },
+ { offset: 1, color: "#FFC02D" },
]),
},
},
- { name: "缺勤率", value: absenceRate, itemStyle: { color: "#FF9D2C" } },
];
return (
-
学习情况
+
+
+ 学习情况
+
{loading ? (
) : (
@@ -107,87 +120,90 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading }) => {
{/* 时长 */}
-
-
-
- 个人学习时长(h)
-
-
-
- {personalStudyHours}
-
-
-
-
-
- 班级平均学习时长(h)
-
-
-
- {classAverageStudyHours}
-
-
-
+
+ 个人学习时长(h)
+
+
+
+ {personalStudyHours}
+
+
+
+
+
+ 班级平均学习时长(h)
+
+
+
+ {classAverageStudyHours}
+
+
{/* 进度 */}
-
-
-
- 整体课程完成进度
-
+
{/* 课程整体完成情况 */}
-
+
+ 整体课程完成情况
+
-
班级平均进度
-
- {classAverageCourseProgress}%
-
+
+
+ 我的进度
+
+
{personalCourseProgress}%
-
我的进度
-
- {personalCourseProgress}%
-
+
+
+ 班级平均进度
+
+
{classAverageCourseProgress}%
{/* 课后作业完成情况 */}
-
+
+ 课后作业完成情况
+
-
班级平均进度
-
- {classAverageHomeworkProgress}%
-
+
+
+ 我的进度
+
+
{personalHomeworkProgress}%
-
我的进度
-
- {personalHomeworkProgress}%
-
+
+
+ 班级平均进度
+
+
{classAverageHomeworkProgress}%
{/* 考勤情况 */}
-
+
考勤情况
{
/>
-
出勤率
-
- {attendanceRate}%
-
+
+
+ 出勤率
+
+
{attendanceRate}%
-
缺勤率
-
- {absenceRate}%
-
+
+
+ 缺勤率
+
+
{absenceRate}%
diff --git a/src/pages/PersonalProfile/index.css b/src/pages/PersonalProfile/index.css
index c8d91fa..d780243 100644
--- a/src/pages/PersonalProfile/index.css
+++ b/src/pages/PersonalProfile/index.css
@@ -19,23 +19,37 @@
margin-top: 20px;
.unified-profile-left {
- width: 360px;
+ width: 373px;
height: 100%;
+ margin-right: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
.unified-profile-rank {
- height: 385px;
+ height: 420px;
margin-right: 0;
}
}
.unified-profile-right {
- width: 744px;
- height: 781px;
- border-radius: 8px;
- background-color: #fff;
+ flex: 1;
+ height: 100%;
+ border-radius: 16px;
+ background-color: #e8f6ff;
+ position: relative;
+ border: 2px solid #fff;
+
+ &::after {
+ content: "";
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 100%;
+ height: 100px;
+ background-image: url("@/assets/images/PersonalProfile/unified_profile_right_bg.png");
+ background-size: 100% 100%;
+ }
}
}
diff --git a/src/pages/PersonalProfile/index.jsx b/src/pages/PersonalProfile/index.jsx
index 0928da1..76a5e30 100644
--- a/src/pages/PersonalProfile/index.jsx
+++ b/src/pages/PersonalProfile/index.jsx
@@ -1,7 +1,7 @@
import { useState, useEffect } from "react";
import { useDispatch } from "react-redux";
import ProfileCard from "./components/ProfileCard";
-import Rank from "@/components/Rank";
+import ClassRank from "@/components/ClassRank";
import StageProgress from "@/components/StageProgress";
import StudyStudes from "./components/StudyStudes";
import { updateStudentInfo } from "@/store/slices/studentSlice";
@@ -26,13 +26,7 @@ const PersonalProfile = () => {
// 更新Redux中的学生信息
const studentInfo = {
...data.studentInfo,
- realName: data.studentInfo.name,
- studentNo: data.studentInfo.studentId,
- mbtiType: data.studentInfo.mbti || 'ENFJ',
- myRank: {
- ...data.ranking.myRank,
- score: data.studentInfo.credits,
- },
+ myRank: data.ranking.myRank,
classInfo: data.ranking.classInfo,
};
@@ -58,7 +52,7 @@ const PersonalProfile = () => {