From 316dd9b6bf2ef27dc6ce79a320c7d9a4a3b2eaad Mon Sep 17 00:00:00 2001 From: KQL Date: Tue, 2 Sep 2025 22:09:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E8=AF=BE=E7=A8=8B?= =?UTF-8?q?=E7=9B=B4=E6=92=AD=E9=A1=B5=E9=9D=A2=E5=92=8C=E9=A6=96=E9=A1=B5?= =?UTF-8?q?Dashboard=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复6月17日单元小结归属问题,正确归入商业设计基础单元 - 添加单元海报功能,非直播状态显示单元海报图片 - 更新首页Dashboard开始上课和当日事项板块数据 - 实现课程数据与Dashboard数据自动同步 - 优化课程列表显示,包含完整100门课程数据 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- courseLiveListData.json | 964 ++++++++++++++++++ generateCourseLiveList.js | 127 +++ src/components/ClassRank/index.jsx | 81 ++ src/components/CoursesVideoPlayer/index.css | 110 +- src/components/CoursesVideoPlayer/index.jsx | 101 +- src/components/EchartsProgress/index.jsx | 109 ++ .../components/CalendarTaskModule/index.css | 48 +- .../components/CalendarTaskModule/index.jsx | 50 +- .../components/QuickAccess/index.css | 50 +- .../components/QuickAccess/index.jsx | 74 +- .../Dashboard/components/StartClass/index.css | 130 ++- .../Dashboard/components/StartClass/index.jsx | 133 +-- .../components/StudyStatus/index.css | 20 +- .../components/StudyStatus/index.jsx | 23 +- .../Dashboard/components/TaskList/index.css | 50 +- .../Dashboard/components/TaskList/index.jsx | 194 ++-- src/pages/Dashboard/index.css | 56 +- src/pages/Dashboard/index.jsx | 67 +- src/pages/LivePage/index.jsx | 12 +- .../components/AttendanceRingChart/index.jsx | 8 +- .../components/ProfileCard/index.css | 40 +- .../components/ProfileCard/index.jsx | 28 +- .../components/ScoreRingChart/index.jsx | 26 +- .../components/StudyStudes/index.css | 279 +++-- .../components/StudyStudes/index.jsx | 188 ++-- src/pages/PersonalProfile/index.css | 26 +- src/pages/PersonalProfile/index.jsx | 12 +- 27 files changed, 2287 insertions(+), 719 deletions(-) create mode 100644 courseLiveListData.json create mode 100644 generateCourseLiveList.js create mode 100644 src/components/ClassRank/index.jsx create mode 100644 src/components/EchartsProgress/index.jsx 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 ? ( + avatar + ) : ( + student.studentName?.charAt(0) || "?" + )} + + + {student.studentName || "未知"} + + +
  • + ) : ( +
  • +
    + - +
    +
  • + ); + })} +
+
    + {listStudents.map((student, index) => ( +
  • + {index + 4} +

    {student.studentName || "未知"}

    + {student.score}分 +
  • + ))} +
+ + )} +
+ ); +}; + +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 ? ( + + ) : ( + {unitName} + )}
)} @@ -35,18 +97,24 @@ export default ({ className = "", isLock = false }) => {
{/* 直播观众信息 */}
- - avatar - - 魏立慧 - 教育体系认知 +
+ + avatar + + {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")} - > - icon1 -

    专家支持中心

    -
  • -
  • handleClick("/live")} - > - icon1 -

    课程直播间

    -
  • -
  • handleClick("/career-tree")} - > - icon1 -

    就业管家知识树

    -
  • + {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 ? ( - avatar - ) : ( - 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 ? ( + avatar + ) : ( + 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 = () => {
    -