主要内容: - 包含12个产业的完整教务系统前端代码 - 智能启动脚本 (start-industry.sh) - 可视化产业导航页面 (index.html) - 项目文档 (README.md) 优化内容: - 删除所有node_modules和.yoyo文件夹,从7.5GB减少到2.7GB - 添加.gitignore文件避免上传不必要的文件 - 自动依赖管理和智能启动系统 产业列表: 1. 文旅产业 (5150) 2. 智能制造 (5151) 3. 智能开发 (5152) 4. 财经商贸 (5153) 5. 视觉设计 (5154) 6. 交通物流 (5155) 7. 大健康 (5156) 8. 土木水利 (5157) 9. 食品产业 (5158) 10. 化工产业 (5159) 11. 能源产业 (5160) 12. 环保产业 (5161) 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
57 KiB
教务系统数据架构与产业替换指南
核心原则 ⚠️
🔴 绝对不可修改的内容
- 页面样式和布局 - 保持所有CSS类名、样式文件完全不变
- 组件结构 - 不改动React组件的结构和渲染逻辑
- 数据处理逻辑 - 保留所有数据转换、过滤、排序等处理函数
- 字段名称 - 保持JSON和对象的所有字段名不变(包括中文字段名)
- 数据流向 - 维持组件间的数据传递方式和状态管理
✅ 只替换以下内容
- 具体数据值 - 学生姓名、课程名称、岗位名称等实际内容
- 图片URL - 头像、海报、背景图等资源链接
- 文本内容 - 简历内容、项目描述、面试题等文字
- 数值数据 - 学分、排名、薪资等数值
📋 替换原则总结
保持框架不变,只换内容
保持逻辑不变,只换数据
保持样式不变,只换文字
保持结构不变,只换数值
一、系统整体数据架构
核心数据文件结构
src/
├── data/
│ ├── mockData.js # 中央数据存储(最重要)
│ ├── courseLiveDataImport.js # 课程数据导入配置
│ ├── companyJobsNew.json # 企业内推岗位数据
│ ├── interviewStatus.json # 岗位面试状态
│ ├── expertSupportData.js # 专家支持中心数据
│ ├── joblevel.json # 岗位级别分类
│ ├── 智能制造课程日历.json # 课程日历源数据
│ └── 智能制造单元背景.json # 单元海报数据
├── mocks/
│ ├── resumeInterviewMock.js # 简历与面试页面数据
│ └── projectLibraryMock.js # 项目库数据
└── 网页未导入数据/
└── 智能制造产业/
├── 智能制造个人档案.json # 学生个人信息
├── 智能制造岗位面试状态.json # 面试状态数据
└── 智能制造修改版简历/ # 修改版简历文件夹
二、各页面详细数据逻辑
1. 主页 (Dashboard)
文件位置: src/pages/DashboardPage/index.jsx
数据来源:
- 班级排名:
mockData.js→dashboardStatistics.ranking.topStudents - 学习进度:
mockData.js→dashboardStatistics.learningProgress - 推荐岗位:
mockData.js→dashboardStatistics.recommendedJobs - 用户信息:
mockData.js→personalProfile
数据流:
// mockData.js 中的数据结构
dashboardStatistics: {
ranking: {
currentRank: 2, // 当前排名
totalStudents: 45, // 总人数
topStudents: [...] // 前10名学生数据
},
learningProgress: {...},
recommendedJobs: [...]
}
替换要点:
- 更新
topStudents数组中的学生信息 - 保持数据结构不变,只替换内容
- 不修改任何样式和组件逻辑
2. 个人档案页面 (PersonalProfile)
文件位置: src/pages/PersonalProfilePage/index.jsx
数据来源:
- 个人信息:
mockData.js→personalProfile - 班级排名:
mockData.js→personalProfile.classRanking - 学习记录:
mockData.js→personalProfile.learningRecords
数据流:
personalProfile: {
basicInfo: {
name: "王强",
studentId: "2325010211",
school: "苏州健雄职业技术学院",
major: "模具设计与制造",
// ...
},
classRanking: [...],
credits: 95
}
替换要点:
- 从产业个人档案JSON导入数据
- 更新头像路径
- 保持MBTI等个性化数据
- 不修改页面布局和CSS样式
- 保留所有数据处理逻辑
3. 简历与面试页面 (ResumeInterview)
文件位置: src/pages/ResumeInterviewPage/index.jsx
数据来源:
- 岗位群数据:
resumeInterviewMock.js→industries - 岗位列表:
resumeInterviewMock.js→industries[].positions - 简历模板:
resumeInterviewMock.js→resumeTemplates - 面试题:
resumeInterviewMock.js→industries[].questions - 修改版标记: 页面内
hasRealModifiedVersion()函数
数据结构:
// resumeInterviewMock.js
industries: [
{
id: "manufacturing_1",
name: "3D打印工艺",
positions: [...], // 该岗位群下的所有岗位
questions: [...] // 该岗位群的面试题
}
]
resumeTemplates: {
"3D打印工艺": [
{
position: "3D打印工程师",
content: {
original: "原始版简历内容",
modified: "修改版简历内容"
}
}
]
}
替换要点:
- 替换岗位群名称和ID
- 更新每个岗位的详细信息
- 替换简历内容(保持original和modified结构)
- 更新面试题内容
- 修改
hasRealModifiedVersion函数中的岗位列表 - 绝不改动组件渲染逻辑和样式
4. 企业内推岗位页面 (CompanyJobs)
文件位置: src/pages/CompanyJobsPage/index.jsx
数据来源:
- 岗位列表:
companyJobsNew.json - 面试状态:
interviewStatus.json - 岗位详情:
companyJobsNew.json→ 各岗位的详细字段
数据结构:
// companyJobsNew.json
[
{
"公司名称": "苏州某科技有限公司",
"查询岗位名称": "PLC控制工程师",
"招聘人数": "2人",
"学历要求": "大专及以上",
"薪资": "8-12K",
// ...
}
]
// interviewStatus.json
[
{
"查询岗位名称": "PLC控制工程师",
"阶段日期": "收到Offer:2025/9/14 16:17",
"面试状态": "已收到Offer,请于2天内答复"
}
]
替换要点:
- 保持JSON字段名不变(中文字段名)
- 更新岗位内容为新产业岗位
- 同步更新面试状态数据
- 不修改页面交互逻辑
- 保持原有动画效果
5. 项目库页面 (ProjectLibrary)
文件位置: src/pages/ProjectLibraryPage/index.jsx
数据来源:
- 项目列表:
projectLibraryMock.js→projects - 项目详情:
projectLibraryMock.js→projects[].details - 适用岗位:
projectLibraryMock.js→projects[].suitablePositions - 对应单元:
projectLibraryMock.js→projects[].relatedUnit
数据结构:
// projectLibraryMock.js
projects: [
{
id: 1,
title: "90°弯管液压歧管3D打印项目",
category: "3D打印工艺",
suitablePositions: ["3D打印工程师", "3D打印产品设计师"],
relatedUnit: "单元一",
details: {
background: "项目背景...",
objectives: ["目标1", "目标2"],
// ...
}
}
]
替换要点:
- 更新项目名称和分类
- 替换适用岗位列表
- 更新项目详情内容
- 保持单元映射关系
- 不改动模态框和卡片组件
6. 课程直播间页面 (CourseLive)
文件位置: src/pages/CourseLivePage/index.jsx
数据来源:
- 课程列表:
mockData.js→courseLiveList(复合能力课) - 垂直课程:
mockData.js→verticalCourseLiveList - 公共课程:
mockData.js→publicCourseLiveList - 单元海报:
courseLiveDataImport.js→unitPosters
数据流:
// 从智能制造课程日历.json生成
courseLiveList: generateCourseLiveListFromCalendar('compound-skill')
verticalCourseLiveList: generateCourseLiveListFromCalendar('vertical-skill')
// 单元海报映射
unitPosters: {
"单元一": "https://xxx.com/unit1.jpg",
// ...
}
替换要点:
- 更新课程日历JSON文件
- 更新单元背景JSON文件
- 确保课程类型字段正确(复合课阶段/垂直课阶段)
- 保持课程卡片样式不变
- 不修改数据转换函数
7. 日历页面 (Calendar)
文件位置: src/pages/CalendarPage/index.jsx
数据来源:
- 日历事件:
mockData.js→calendarEvents - 源数据:
智能制造课程日历.json
数据转换流程:
// courseLiveDataImport.js
智能制造课程日历.json → transformCalendarCourses() → calendarEvents
// 事件类型判断
课程阶段(个人课程)包含"复合" → type: 'compound-skill'
课程阶段(个人课程)包含"垂直" → type: 'vertical-skill'
公共课字段有值 → type: 'public'
替换要点:
- 更新课程日历JSON
- 保持日期格式(YYYY/M/D)
- 正确设置课程类型字段
- 不改动日历组件和事件渲染
8. 课程作业页面 (Homework)
文件位置: src/pages/HomeworkPage/index.jsx
数据来源:
- 作业列表:
mockData.js→homework - 动态生成: 从
courseLiveList自动生成
数据生成逻辑:
// mockData.js 中的动态生成
if (mockData.homework && mockData.homework[0]) {
// 从courseLiveList生成复合能力课作业
mockData.courseLiveList.forEach(unit => {
unit.courses.forEach(course => {
// 生成作业项
});
});
}
替换要点:
- 作业内容自动从课程列表生成
- 无需手动更新作业数据
- 保持作业卡片样式
- 不修改生成逻辑
9. 岗位攻略详情页 (JobStrategyDetail)
文件位置: src/pages/JobStrategyDetailPage/index.jsx
数据来源:
- 岗位详情: 从URL参数获取岗位,匹配
companyJobsNew.json - 优先级数据: 页面内定义
替换要点:
- 更新岗位优先级列表
- 更新岗位分析内容
- 保持图表和可视化组件不变
10. 专家支持中心 (ExpertSupport)
文件位置: src/pages/ExpertSupportPage/index.jsx
数据来源:
- 问答数据:
expertSupportData.js - 聊天记录:
expertSupportData.js→chatMessages
数据结构:
// expertSupportData.js
export const expertSupportData = {
faqs: [...],
chatMessages: [...],
expertProfiles: [...]
}
替换要点:
- 更新FAQ内容
- 更新预设的聊天消息
- 更新专家信息
- 保持聊天界面样式
- 不修改消息处理逻辑
三、导师信息替换专项指南
导师数据结构说明
导师信息存储在 src/data/mockData.js 的 teacherData 对象中,通过 updateTeacherCourses 函数与课程日历事件关联。
导师类型分类
- 复合课导师 - 产业专属,需要替换
- 公共课导师 - 通用导师,保持不变
- AI课导师 - 通用导师,保持不变
- 企业资深HR - 通用导师,保持不变
替换步骤
-
识别需要替换的导师
- 查找所有
type: "复合课导师"的导师 - 这些是产业相关的专业导师
- 查找所有
-
准备新导师数据
- 从"导师信息(通用).json"中选择新产业相关导师
- 确保导师的垂直方向与产业匹配
-
更新导师信息
// 示例:智能制造产业导师 "王军": { name: "王军", introduction: "导师介绍内容...", specialties: ["30年研发专家", "主导国标制定", "资深机械结构专家", "单产品创收百万"], avatar: "https://头像URL", type: "复合课导师", verticalDirection: "机械加工工艺", courses: [] // 自动由updateTeacherCourses函数填充 } -
垂直方向对应关系
- 智能制造:机械加工工艺、智能机械产品结构与外观设计、智能制造非标自动化产线搭建、自动化设备智能调试
- 文旅:项目经营管理、商业活动策划、文化服务
- 其他产业:根据实际垂直方向设置
-
注意事项
- ⚠️ 保持导师对象的键名与name属性一致
- ⚠️ courses数组留空,由系统自动填充
- ⚠️ 不要修改updateTeacherCourses函数逻辑
- ⚠️ 保留所有公共课导师、AI课导师和HR导师
导师信息验证
- 检查导师是否在课程播放器中正确显示
- 验证导师的课程列表是否自动更新
- 确认导师头像URL可访问
四、各页面详细替换步骤指南
📌 页面1:主页 (Dashboard)
步骤流程:
-
准备数据
- 从新产业个人档案JSON获取前10名学生数据
- 准备学生头像图片URL
-
修改文件:
src/data/mockData.js// 找到 dashboardStatistics.ranking.topStudents // 替换为新的学生数组,格式如下: topStudents: [ { rank: 1, name: "新学生名", studentId: "新学号", school: "新学校", major: "新专业", credits: 97, avatar: "/images/avatars/新头像.jpg" }, // ... 继续添加前10名 ] -
验证要点
- ✅ 确保rank从1到10递增
- ✅ 学分按降序排列
- ✅ 头像路径正确可访问
- ❌ 不要修改字段名称
- ❌ 不要改动组件样式
📌 页面2:个人档案 (PersonalProfile)
步骤流程:
-
选择目标学生
- 从个人档案JSON中选择一个学生(如排名第2的学生)
-
修改文件:
src/data/mockData.js// 找到 personalProfile 对象 personalProfile: { basicInfo: { name: "王强", // 替换为新学生名 studentId: "2325010211", // 新学号 school: "苏州健雄职业技术学院", // 新学校 major: "模具设计与制造", // 新专业 class: "智能制造1班", // 新班级 credits: 95, // 新学分 ranking: 2, // 新排名 avatar: "/images/avatars/wangqiang.jpg", // 新头像 mbti: "ESTJ", // 保持或更新MBTI direction: "自动化设备智能调试" // 新方向 }, classRanking: [/* 更新为新的前10名数组 */], learningRecords: [/* 可选:更新学习记录 */] } -
同步更新侧边栏
- 确保Sidebar组件引用的是同一个personalProfile数据
-
验证要点
- ✅ 个人信息与选定学生一致
- ✅ 班级排名数据与Dashboard同步
- ❌ 不要修改组件结构
📌 页面3:简历与面试 (ResumeInterview)
步骤流程:
-
准备简历数据
- 整理新产业的岗位群和岗位列表
- 准备每个岗位的原始版和修改版简历
-
修改文件:
src/mocks/resumeInterviewMock.js// 1. 更新 industries 数组 industries: [ { id: "manufacturing_1", name: "3D打印工艺", // 新岗位群名称 icon: "🖨️", // 可选:更新图标 positions: [ { id: "3d_engineer", title: "3D打印工程师", // 新岗位名称 company: "苏州某科技", // 新公司 salary: "8-12K", // 新薪资 requirements: ["要求1", "要求2"] // 新要求 } // ... 更多岗位 ], questions: [/* 新的面试题 */] } // ... 更多岗位群 ] // 2. 更新 resumeTemplates resumeTemplates: { "3D打印工艺": [ { position: "3D打印工程师", content: { original: "# 原始简历内容\n...", modified: "# 修改版简历内容\n..." } } ] } // 3. 更新 myResume myResume: { personalInfo: { name: "王强", // 与personalProfile一致 // ... 其他个人信息 } } -
修改页面文件:
src/pages/ResumeInterviewPage/index.jsx// 更新 hasRealModifiedVersion 函数 const hasRealModifiedVersion = (positionTitle) => { const modifiedPositions = [ "新岗位1", "新岗位2", // ... 有修改版的岗位列表 ]; return modifiedPositions.includes(positionTitle); }; -
验证要点
- ✅ 岗位群和岗位数据完整
- ✅ 简历内容格式正确(Markdown)
- ✅ 修改版标记正确显示
- ❌ 不要改动Tab切换逻辑
📌 页面4:企业内推岗位 (CompanyJobs)
步骤流程:
-
准备岗位数据
- 整理新产业的企业岗位信息
- 准备对应的面试状态数据
-
修改文件:
src/data/companyJobsNew.json[ { "公司名称": "苏州某科技有限公司", "查询岗位名称": "PLC控制工程师", "招聘人数": "2人", "学历要求": "大专及以上", "薪资": "8-12K", "工作地点": "苏州工业园区", "岗位职责": ["职责1", "职责2"], "任职要求": ["要求1", "要求2"] } // ... 更多岗位 ] -
修改文件:
src/data/interviewStatus.json[ { "查询岗位名称": "PLC控制工程师", "阶段日期": "收到Offer:2025/9/14 16:17", "面试状态": "已收到Offer,请于2天内答复" } // ... 更多状态 ] -
修改简历模态框默认值:
src/pages/CompanyJobsPage/components/ResumeInfoModal/index.jsxeducation: [{ school: '新学校名称', major: '新专业名称', period: '2020.9-2023.6' }] -
验证要点
- ✅ 岗位信息字段完整
- ✅ 面试状态与岗位对应
- ✅ 保持中文字段名
- ❌ 不要修改动画效果
📌 页面5:项目库 (ProjectLibrary)
步骤流程:
-
准备项目数据
- 整理新产业的项目案例
- 确定项目与岗位的映射关系
-
修改文件:
src/mocks/projectLibraryMock.jsprojects: [ { id: 1, title: "90°弯管液压歧管3D打印项目", // 新项目名 category: "3D打印工艺", // 新分类 suitablePositions: ["3D打印工程师", "产品设计师"], // 适用岗位 relatedUnit: "单元一", // 对应单元 details: { background: "项目背景描述...", objectives: ["目标1", "目标2"], requirements: ["需求1", "需求2"], process: ["步骤1", "步骤2"], results: ["成果1", "成果2"], skills: ["技能1", "技能2"] } } // ... 更多项目 ] -
验证要点
- ✅ 项目详情结构完整
- ✅ 岗位名称与简历页面一致
- ❌ 不要修改卡片组件样式
📌 页面6:课程直播间 (CourseLive)
步骤流程:
-
准备课程数据
- 整理课程日历JSON
- 准备单元背景图片
-
更新数据文件:
- 将新的课程日历JSON放到
src/data/[产业名称]课程日历.json - 将单元背景JSON放到
src/data/[产业名称]单元背景.json
- 将新的课程日历JSON放到
-
修改导入配置:
src/data/courseLiveDataImport.js// 修改导入路径 import calendarData from './[产业名称]课程日历.json'; import unitPostersData from './[产业名称]单元背景.json'; // 数据会自动通过transformCalendarCourses转换 -
数据格式要求
// 课程日历JSON格式 { "个人课程表": "课程名称", "课程阶段(个人课程)": "复合课阶段/垂直课阶段", "所属单元(个人课程)": "单元一", "日期": "2024/7/15" } -
更新导师信息:
src/data/mockData.js- 在teacherData对象中替换导师信息
- 复合课导师需要替换为新产业相关导师
- 公共课导师、AI课导师、HR导师保持不变
teacherData: updateTeacherCourses({ "导师名": { name: "导师名", introduction: "导师介绍...", specialties: ["特长1", "特长2", "特长3", "特长4"], avatar: "头像URL", type: "复合课导师/公共课导师/AI课导师/企业资深HR", verticalDirection: "垂直方向", courses: [] }, // ... 更多导师 }, allCalendarEvents) -
验证要点
- ✅ 课程正确分类(复合/垂直)
- ✅ 单元海报URL可访问
- ✅ 公共课保持不变
- ✅ 导师信息与产业匹配
- ❌ 不要修改课程卡片样式
- ❌ 不要修改导师卡片组件
📌 页面7:日历 (Calendar)
步骤流程:
-
准备日历数据文件
- 创建
智能开发课程日历.json和智能开发单元背景.json - 确保日期格式为 YYYY/M/D
- 创建
-
创建数据转换脚本
convertCalendarData.cjsconst fs = require('fs'); // 读取课程日历和单元背景数据 const calendarData = JSON.parse( fs.readFileSync('./网页未导入数据/智能开发产业/智能开发课程日历.json', 'utf-8') ); // 转换日期格式和课程类型 const allCalendarEvents = []; calendarData.forEach(item => { // 日期转换:YYYY/M/D → YYYY-MM-DD const dateParts = item['日期'].split('/'); const formattedDate = `${dateParts[0]}-${dateParts[1].padStart(2, '0')}-${dateParts[2].padStart(2, '0')}`; // 处理各类课程 if (item['个人课程表']) { allCalendarEvents.push({ title: item['个人课程表'], startTime: `${formattedDate} ${startTime}`, endTime: `${formattedDate} ${endTime}`, type: courseType.includes('复合') ? 'compound-skill' : 'vertical-skill', // ... }); } }); // 复制文件到src/data目录 fs.copyFileSync('./网页未导入数据/智能开发产业/智能开发课程日历.json', './src/data/智能开发课程日历.json'); -
更新mockData.js导入路径
// 必须更新这两行导入! import calendarCoursesData from './智能开发课程日历.json'; import intelligentManufacturingUnitData from './智能开发单元背景.json'; -
更新导师头像映射
const teacherAvatars = { // 原有导师... // 新增智能开发产业导师 "谢宇程": "头像URL", "何思远": "头像URL", // ... }; -
验证要点
- ✅ mockData.js导入路径已更新
- ✅ JSON文件已复制到src/data
- ✅ 日期格式转换正确
- ✅ 课程类型判断准确
- ✅ 导师头像映射完整
- ❌ 不要修改日历组件
- ❌ 不要修改transformCalendarCourses函数
📌 页面8:课程作业 (Homework)
步骤流程:
-
自动生成机制
- 作业从courseLiveList自动生成
- 无需手动修改
-
验证生成逻辑:
src/data/mockData.js// 检查动态生成代码是否正常工作 if (mockData.homework && mockData.homework[0]) { // 复合能力课作业生成 // 垂直能力课作业生成 } -
验证要点
- ✅ 作业与课程对应
- ✅ 单元分组正确
- ❌ 不要修改作业卡片
📌 页面9:岗位攻略详情 (JobStrategyDetail)
步骤流程:
-
更新岗位分析数据
- 岗位数据从companyJobsNew.json读取
- 可在页面内更新优先级分析
-
修改页面文件(如需要):
src/pages/JobStrategyDetailPage/index.jsx// 更新岗位优先级数据 const jobPriorities = [ { name: '新岗位1', priority: 'high' }, { name: '新岗位2', priority: 'medium' }, // ... ]; -
验证要点
- ✅ 岗位详情正确显示
- ✅ 图表数据更新
- ❌ 不要修改图表组件
📌 页面10:专家支持中心 (ExpertSupport)
步骤流程:
-
准备FAQ和聊天数据
- 整理新产业相关的常见问题
- 准备预设聊天消息
-
修改文件:
src/data/expertSupportData.jsexport const expertSupportData = { faqs: [ { question: "新产业相关问题1?", answer: "答案1" } // ... 更多FAQ ], chatMessages: [ { type: 'expert', content: '欢迎咨询新产业相关问题', time: '10:00' } // ... 预设消息 ], expertProfiles: [ { name: "专家名", title: "新产业专家", expertise: ["领域1", "领域2"] } ] } -
验证要点
- ✅ FAQ内容相关
- ✅ 聊天消息合理
- ❌ 不要修改聊天界面
三、产业数据替换步骤指南
第一步:准备源数据文件
-
创建产业数据文件夹
网页未导入数据/[产业名称]/ ├── [产业名称]个人档案.json ├── [产业名称]课程日历.json ├── [产业名称]单元背景.json ├── [产业名称]岗位面试状态.json └── [产业名称]修改版简历/ ├── 岗位1.md ├── 岗位2.md └── ... -
数据格式要求
- 个人档案:包含学生信息、学校、专业、学分、排名等
- 课程日历:包含日期、课程名称、课程阶段、所属单元等
- 单元背景:包含单元名称和海报URL
- 岗位面试状态:包含岗位名称、面试阶段、状态描述
第二步:更新核心数据文件
-
更新 mockData.js
// 1. 导入新的数据文件 import personalData from "@/data/[产业名称]个人档案.json"; import calendarData from "@/data/[产业名称]课程日历.json"; // 2. 更新personalProfile const targetStudent = personalData[1]; // 选择目标学生 mockData.personalProfile = { basicInfo: { name: targetStudent.学员名称, studentId: targetStudent.学号, // ... } }; // 3. 更新班级排名 mockData.dashboardStatistics.ranking.topStudents = personalData.slice(0, 10); // 4. 更新导师信息(替换复合课导师) teacherData: updateTeacherCourses({ "新导师名": { name: "新导师名", introduction: "导师介绍...", specialties: ["特长1", "特长2", "特长3", "特长4"], avatar: "头像URL", type: "复合课导师", verticalDirection: "产业相关方向", courses: [] }, // ... 保留公共课导师、AI课导师、HR导师 }, allCalendarEvents) -
更新 resumeInterviewMock.js
- 替换 industries 数组(岗位群)
- 替换 resumeTemplates 对象(简历内容)
- 更新 myResume 对象(个人简历)
-
更新 projectLibraryMock.js
- 替换 projects 数组
- 更新项目与岗位的映射关系
-
更新其他JSON文件
- companyJobsNew.json:企业岗位数据
- interviewStatus.json:面试状态数据
第三步:更新页面特定逻辑
-
ResumeInterviewPage
// 更新修改版岗位列表 const hasRealModifiedVersion = (positionTitle) => { const modifiedPositions = [ // 新产业的岗位列表 ]; return modifiedPositions.includes(positionTitle); }; -
ResumeInfoModal
// 更新默认教育经历 education: [{ school: '新学校名称', major: '新专业名称', period: '2020.9-2023.6' }]
第四步:验证数据完整性
-
检查清单
- 个人信息是否正确显示
- 班级排名数据是否同步
- 课程列表是否正确分类
- 岗位和简历是否匹配
- 项目库内容是否更新
- 面试状态是否正确
- 修改版标记是否显示
-
常见问题排查
- 数据不显示:检查import路径
- 类型错误:检查数据格式
- 样式错乱:保持原有CSS类名
四、数据更新注意事项
1. 🔴 绝对禁止的操作
- 禁止修改任何CSS文件或样式
- 禁止改动组件的JSX结构
- 禁止修改数据处理函数逻辑
- 禁止重命名任何变量或函数
- 禁止改变文件目录结构
2. 保持数据结构一致性
- 不要修改字段名称
- 不要改变数据层级结构
- 只替换具体内容值
- 保留所有原始的数据处理逻辑
3. 中文字段名处理
// 保持中文字段名不变
{
"查询岗位名称": "新岗位名", // ✓ 正确
"jobName": "新岗位名" // ✗ 错误,不要改字段名
}
4. 图片资源处理
- 使用CDN链接或public目录
- 保持相同的图片尺寸比例
- 优化图片大小(建议<500KB)
5. 日期格式统一
// 课程日历:YYYY/M/D
"日期": "2024/7/15"
// 面试状态:YYYY/M/D H:mm
"阶段日期": "2025/9/14 16:17"
6. 备份原数据
# 备份命令
cp src/data/mockData.js src/data/mockData.js.backup_$(date +%Y%m%d_%H%M%S)
五、快速替换脚本示例
// updateIndustryData.js
import fs from 'fs';
import path from 'path';
const updateIndustryData = (industryName) => {
// 1. 读取新产业数据
const personalData = JSON.parse(
fs.readFileSync(`网页未导入数据/${industryName}/${industryName}个人档案.json`)
);
// 2. 更新mockData.js
// ... 更新逻辑
// 3. 更新其他文件
// ... 更新逻辑
console.log(`✅ 已更新为${industryName}产业数据`);
};
// 使用
updateIndustryData('智能制造');
六、数据流程图
graph TD
A[产业源数据] --> B[数据导入层]
B --> C[mockData.js]
B --> D[resumeInterviewMock.js]
B --> E[projectLibraryMock.js]
C --> F[Dashboard]
C --> G[PersonalProfile]
C --> H[Calendar]
C --> I[CourseLive]
C --> J[Homework]
D --> K[ResumeInterview]
E --> L[ProjectLibrary]
M[companyJobsNew.json] --> N[CompanyJobs]
O[interviewStatus.json] --> N
P[expertSupportData.js] --> Q[ExpertSupport]
七、完整替换流程检查清单
✅ 替换前准备
- 备份所有将要修改的文件
- 准备完整的产业数据文件
- 确认数据格式符合要求
- 测试环境可正常运行
✅ 数据替换检查
- mockData.js
- personalProfile 更新完成
- dashboardStatistics 更新完成
- 班级排名数据同步
- teacherData 导师信息更新
- 复合课导师替换为产业相关导师
- 公共课导师保持不变
- resumeInterviewMock.js
- industries 数组替换
- resumeTemplates 更新
- myResume 信息同步
- projectLibraryMock.js
- projects 数组更新
- 岗位映射关系正确
- companyJobsNew.json
- 岗位信息完整
- 字段名保持中文
- interviewStatus.json
- 面试状态对应
- 日期格式正确
- 课程相关数据
- 课程日历JSON导入
- 单元背景JSON配置
- 课程分类正确
✅ 页面功能验证
- 主页班级排名显示正确
- 个人档案信息一致
- 简历修改版标记显示
- 企业岗位列表完整
- 项目库内容更新
- 课程直播间分类正确
- 课程直播间导师信息显示
- 导师头像正常加载
- 导师课程列表自动更新
- 日历事件显示正常
- 作业自动生成成功
- 岗位攻略数据准确
- 专家支持内容相关
✅ 数据一致性检查
- 学生姓名全局一致
- 学号信息匹配
- 学校专业同步
- 岗位名称统一
- 课程类型分类正确
八、常见问题与解决方案
问题1:数据不显示
症状:页面空白或数据缺失 解决:
- 检查import路径是否正确
- 确认JSON文件格式无误
- 查看浏览器控制台错误
问题2:样式错乱
症状:布局混乱或样式丢失 原因:可能修改了CSS类名或组件结构 解决:恢复原始组件代码,只修改数据
问题3:修改版标记不显示
症状:简历页面修改版标记缺失 解决:
- 检查hasRealModifiedVersion函数
- 确认岗位名称完全匹配
- 验证modified字段有内容
问题4:课程分类错误
症状:复合课和垂直课混淆 解决:
- 检查"课程阶段(个人课程)"字段
- 确认包含"复合"或"垂直"关键字
- 验证transformCalendarCourses函数
问题5:作业不生成
症状:作业页面为空 解决:
- 确认courseLiveList有数据
- 检查动态生成代码执行
- 验证课程类型判断逻辑
问题6:头像不显示
症状:学生头像404 解决:
- 将头像文件放到public/images/avatars/
- 使用正确的相对路径
- 确认文件名大小写匹配
问题7:日期格式错误
症状:日历事件不显示 解决:
- 使用YYYY/M/D格式(斜杠分隔)
- 不要补零(7/15而非07/15)
- 检查日期字段名称
问题8:中文字段名问题
症状:数据读取失败 解决:
- 保持原有中文字段名
- 不要改为英文
- 注意字段名完全匹配
问题9:日历页面数据未更新
症状:日历页面仍显示原始数据,即使已替换了课程日历JSON文件 原因:mockData.js中的导入路径未更新 解决:
- 检查
src/data/mockData.js中的导入语句:// 错误:仍然导入旧的智能制造数据 import calendarCoursesData from './intelligentManufacturingCalendar.json'; import intelligentManufacturingUnitData from '../../网页未导入数据/智能制造产业/智能制造单元背景.json'; // 正确:导入新的产业数据 import calendarCoursesData from './智能开发课程日历.json'; import intelligentManufacturingUnitData from './智能开发单元背景.json'; - 确保新的JSON文件已复制到
src/data/目录 - 更新teacherAvatars映射,添加新产业的导师头像
- 验证transformCalendarCourses函数能处理新的数据格式
预防措施:
- 创建数据转换脚本时,同时更新mockData.js的导入路径
- 使用脚本自动复制数据文件到正确位置
- 在转换脚本中添加导入路径更新逻辑
问题10:面试题卡片显示异常
症状:一个岗位群显示多个面试题卡片,而不是一个卡片包含所有问题 原因:面试题数据结构不正确,每个问题被创建为独立卡片 解决:
-
确保每个岗位群只有一个面试题对象:
// 错误:为每个问题创建独立卡片 questions: [ { id: 'q1', question: '问题1', answer: '答案1' }, { id: 'q2', question: '问题2', answer: '答案2' } ] // 正确:一个卡片包含所有问题 questions: [{ id: 'group_q1', question: '岗位群面试题', subQuestions: [ { id: 'q1', question: '问题1', answer: '答案1' }, { id: 'q2', question: '问题2', answer: '答案2' } ] }] -
在数据转换脚本中正确处理面试题:
// 收集所有子问题 const allSubQuestions = []; // ... 解析面试题内容 // 创建单个面试题卡片 if (allSubQuestions.length > 0) { questions.push({ id: 'group_q1', question: `${groupName}面试题`, subQuestions: allSubQuestions.slice(0, 10) // 限制最多10个问题 }); }
预防措施:
- 每个岗位群的questions数组应只包含一个对象
- 使用subQuestions字段包含所有具体问题
- 限制每个卡片最多显示10个问题,避免内容过多
问题11:所有岗位都显示修改版标记
症状:简历页面所有岗位都有绿色的"修改版"样式,即使没有修改版简历 原因:hasRealModifiedVersion函数包含了所有岗位名称 解决:
-
检查
src/pages/ResumeInterviewPage/index.jsx中的函数:// 错误:包含所有岗位 const hasRealModifiedVersion = (positionTitle) => { const modifiedPositions = [/* 47个岗位名称 */]; return modifiedPositions.includes(positionTitle); }; // 正确:只包含真正有修改版的岗位 const hasRealModifiedVersion = (positionTitle) => { const modifiedPositions = [ "AI算法工程师", "AI前端工程师", // ... 只列出实际有修改版文件的岗位 ]; return modifiedPositions.includes(positionTitle); }; -
验证修改版文件是否存在:
ls 网页未导入数据/智能开发产业/智能开发修改版简历/
预防措施:
- 在数据转换脚本中自动检测修改版文件
- 只为实际存在修改版文件的岗位添加标记
- 保持hasRealModifiedVersion函数与实际文件同步
问题13:项目库页面数据引用错误合集
症状:项目库页面出现多个数据显示和功能问题 解决过程记录:
13.1 项目名称显示为undefined
原因:使用了错误的字段名"项目名称",实际JSON中使用的是"案例名称" 错误代码:
// 错误:使用不存在的字段名
const projectDetails = {};
projectsData.forEach((project, index) => {
projectDetails[index + 1] = {
title: project['项目名称'] + '详情', // undefined
};
});
正确代码:
// 正确:使用实际存在的字段名
const projectDetails = {};
projectsData.forEach((project, index) => {
projectDetails[index + 1] = {
title: project['案例名称'] + '详情', // 正确显示
};
});
13.2 岗位等级标签颜色错误
原因:className判断条件使用了错误的等级名称 错误代码:
// 错误:使用"普通岗"
<span className={pos.level === '普通岗' ? 'low' : pos.level === '技术骨干岗' ? 'medium' : 'high'}>
正确代码:
// 正确:使用"基础岗"
<span className={pos.level === '基础岗' ? 'low' : pos.level === '技术骨干岗' ? 'medium' : 'high'}>
13.3 对应单元分类错误
原因:使用简单的关键词匹配而不是正确的映射函数 错误做法:尝试通过判断单元名称中是否包含"复合"或"垂直"来分类 正确做法:
- 创建projectUnitsMapping.js文件定义项目与单元的映射关系
- 导入并使用getCompoundUnits和getVerticalUnits函数
import { getCompoundUnits, getVerticalUnits } from '@/data/projectUnitsMapping';
// 使用映射函数获取正确的单元分类
{getCompoundUnits(data?.title).map((unit, index) => (...))}
{getVerticalUnits(data?.title).map((unit, index) => (...))}
13.4 单元点击功能缺失
原因:没有实现handleUnitClick函数,没有添加点击事件 解决方案:
// 添加单元点击处理函数
const handleUnitClick = (unitName, isCompound) => {
onClose(); // 关闭模态框
const params = new URLSearchParams();
params.append('courseTitle', unitName);
params.append('courseType', isCompound ? 'compound-skill' : 'vertical-skill');
navigate(`/live?${params.toString()}`);
};
13.5 单元hover效果缺失
原因:缺少clickable-unit类名 解决方案:
// 添加clickable-unit类名
<li className="class-list-item clickable-unit" onClick={() => handleUnitClick(unit, true)}>
13.6 适用岗位未排序
原因:没有根据岗位等级进行排序 解决方案:
{data?.applicablePositions?.sort((a, b) => {
const levelOrder = {
'基础岗': 1,
'技术骨干岗': 2,
'储备干部岗': 3
};
return (levelOrder[a.level] || 999) - (levelOrder[b.level] || 999);
}).map((pos, index) => (...))}
13.7 Markdown内容多余标题
原因:项目流程和关键技术点内容中包含重复的标题 解决方案:
const formatMarkdownContent = (content) => {
if (!content) return "";
let formattedContent = content.replace(/\\n/g, '\n');
// 移除多余标题
formattedContent = formattedContent.replace(/^#\s*二、\s*项目整体流程介绍\s*\n*/m, '');
formattedContent = formattedContent.replace(/^#\s*三、\s*项目案例关键技术点\s*\n*/m, '');
return formattedContent.trim();
};
13.8 Mock文件语法错误
原因:attachments数组后有多余的]符号 错误代码:
attachments: []
] // 多余的]
},
正确代码:
attachments: []
},
问题14:修改版简历格式处理错误
症状:修改版简历中包含删除线符号(~~)和加粗符号(**) 原因:Markdown格式未正确处理 解决:
-
创建处理函数清理Markdown格式:
function processModifiedResume(content) { // 1. 删除所有删除线内容(包括符号和内容) content = content.replace(/~~[^~]+~~/g, ''); // 2. 去掉加粗符号但保留内容 content = content.replace(/\*\*([^*]+)\*\*/g, '$1'); // 3. 清理多余的空行 content = content.replace(/\n\s*\n\s*\n/g, '\n\n'); // 4. 清理行尾空格 content = content.replace(/ +$/gm, ''); return content.trim(); } -
在导入修改版简历时应用处理:
modifiedFiles.forEach(file => { const content = fs.readFileSync(filePath, 'utf-8'); const processedContent = processModifiedResume(content); modifiedResumes[positionName] = processedContent; });
预防措施:
- 制定修改版简历的格式规范
- 在数据导入时统一处理格式
- 保留原始内容和处理后内容的对照
问题12:岗位等级标签未显示
症状:简历页面的岗位卡片没有显示等级标签(储备干部岗/技术骨干岗/普通岗) 原因:joblevel.json文件未更新或数据不匹配 解决:
-
更新
src/data/joblevel.json文件:{ "data": { "high": { "name": "储备干部岗", "list": [ { "position_name": "岗位名称", "img": "头像URL" } // ... 所有储备干部岗位 ] }, "middle": { "name": "技术骨干岗", "list": [/* ... */] }, "ordinary": { "name": "普通岗", "list": [/* ... */] } } } -
确保岗位名称完全匹配:
- resumeInterviewMock.js中的position.title
- joblevel.json中的position_name
- 名称必须一字不差
-
创建更新脚本自动生成joblevel.json:
const updateJobLevel = () => { const jobLevelData = { data: { high: { name: "储备干部岗", list: [] }, middle: { name: "技术骨干岗", list: [] }, ordinary: { name: "普通岗", list: [] } } }; // 根据岗位等级标签分类 positions.forEach(pos => { const level = pos['岗位等级标签']; const data = { position_name: pos['岗位名称'], img: pos['简历头像url'] }; if (level === '储备干部岗') { jobLevelData.data.high.list.push(data); } else if (level === '技术骨干岗') { jobLevelData.data.middle.list.push(data); } else { jobLevelData.data.ordinary.list.push(data); } }); fs.writeFileSync('./src/data/joblevel.json', JSON.stringify(jobLevelData, null, 2)); };
预防措施:
- 在主数据转换脚本中同时更新joblevel.json
- 确保所有相关文件的岗位名称保持一致
- 使用脚本自动化更新,避免手动错误
九、项目库页面正确数据替换流程总结
步骤1:准备数据文件
-
获取项目案例JSON数据
- 确保JSON使用正确的字段名(如"案例名称"而非"项目名称")
- 验证所有必需字段存在
-
创建项目单元映射文件
// src/data/projectUnitsMapping.js export const projectUnitsMapping = { "项目名称": { "compoundUnits": ["复合能力课1", "复合能力课2"], "verticalUnits": ["垂直能力课1", "垂直能力课2"] } };
步骤2:更新Mock文件
-
使用正确的字段名
// 解析JSON时使用实际的字段名 title: project['案例名称'] + '详情', // 不是'项目名称' -
正确设置岗位等级
applicablePositions: [ { level: '基础岗', position: '岗位名' }, // 不是'普通岗' { level: '技术骨干岗', position: '岗位名' }, { level: '储备干部岗', position: '岗位名' } ]
步骤3:更新组件逻辑
-
导入映射函数
import { getCompoundUnits, getVerticalUnits } from '@/data/projectUnitsMapping'; -
添加单元点击处理
const handleUnitClick = (unitName, isCompound) => { onClose(); const params = new URLSearchParams(); params.append('courseTitle', unitName); params.append('courseType', isCompound ? 'compound-skill' : 'vertical-skill'); navigate(`/live?${params.toString()}`); }; -
处理Markdown内容
const formatMarkdownContent = (content) => { if (!content) return ""; let formattedContent = content.replace(/\\n/g, '\n'); // 移除重复标题 formattedContent = formattedContent.replace(/^#\s*二、.*\n*/m, ''); formattedContent = formattedContent.replace(/^#\s*三、.*\n*/m, ''); return formattedContent.trim(); };
步骤4:添加样式类
-
确保hover效果
<li className="class-list-item clickable-unit"> -
正确的等级样式判断
className={pos.level === '基础岗' ? 'low' : pos.level === '技术骨干岗' ? 'medium' : 'high'}
步骤5:数据验证
-
检查语法错误
node -c src/mocks/projectLibraryMock.js -
验证数据完整性
- 项目名称正确显示
- 岗位等级标签颜色正确
- 单元分类准确
- 点击功能正常
- hover效果存在
- 岗位按等级排序
- 附件显示"暂无附件"
关键要点总结
- 永远不要假设字段名 - 始终检查实际JSON的字段名
- 保持数据一致性 - 等级名称、岗位名称必须全局一致
- 使用映射而非硬编码 - 通过映射文件管理项目与单元关系
- 处理数据格式 - 正确处理Markdown、换行符等格式问题
- 验证每一步 - 每次修改后立即验证,不要累积问题
十、测试验证方法
1. 单元测试
// 测试数据完整性
describe('产业数据完整性测试', () => {
test('个人信息应包含必要字段', () => {
expect(mockData.personalProfile.basicInfo).toHaveProperty('name');
expect(mockData.personalProfile.basicInfo).toHaveProperty('studentId');
});
});
2. 集成测试
- 访问每个页面检查数据显示
- 测试数据交互功能
- 验证数据同步性
3. 数据一致性检查
// 检查学生姓名是否全局一致
const checkNameConsistency = () => {
const name1 = mockData.personalProfile.basicInfo.name;
const name2 = resumeInterviewMock.myResume.personalInfo.name;
const name3 = mockData.dashboardStatistics.ranking.topStudents[1].name;
return name1 === name2 && name2 === name3;
};
十、快速命令参考
备份命令
# 备份核心文件
cp src/data/mockData.js src/data/mockData.js.backup_$(date +%Y%m%d_%H%M%S)
cp src/mocks/resumeInterviewMock.js src/mocks/resumeInterviewMock.js.backup_$(date +%Y%m%d_%H%M%S)
cp src/mocks/projectLibraryMock.js src/mocks/projectLibraryMock.js.backup_$(date +%Y%m%d_%H%M%S)
语法检查
# 检查JavaScript语法
node -c src/data/mockData.js
node -c src/mocks/resumeInterviewMock.js
开发服务器
# 启动开发服务器
npm run dev
# 清理缓存后启动
rm -rf node_modules/.vite
npm run dev
Git操作
# 查看修改的文件
git status
# 查看具体修改内容
git diff src/data/mockData.js
# 提交更改
git add .
git commit -m "feat: 替换为[产业名称]产业数据"
十一、数据替换最佳实践
👍 推荐做法
- 分步替换:先替换一个页面,测试后再继续
- 版本控制:每完成一个模块就提交一次
- 注释标记:在修改处添加注释说明
- 数据验证:使用console.log验证数据加载
- 团队协作:记录修改内容供团队参考
👎 避免做法
- 批量替换:不要使用全局查找替换
- 跳过备份:不要直接修改无备份文件
- 忽略错误:不要忽视控制台警告
- 修改框架:不要改动React组件逻辑
- 更改样式:不要修改CSS文件
十二、产业切换总结
核心要点回顾
- 数据与逻辑分离:只替换数据,保持逻辑
- 结构保持一致:维护原有数据结构
- 样式不做修改:保留所有样式文件
- 字段名不改变:特别是中文字段名
- 测试验证充分:每步都要验证结果
成功标准
- ✅ 所有页面正常显示
- ✅ 数据内容正确更新
- ✅ 功能交互正常工作
- ✅ 样式布局保持原样
- ✅ 无控制台错误警告
最后更新时间: 2025年9月16日 当前产业: 智能开发 维护人员: System Admin 文档版本: v2.4
十三、"我完成的项目"板块数据替换实战指南
问题描述与解决历程
遇到的问题
- 初始问题:购物网站项目点击后显示的是班级项目库的内容,而不是本地定义的内容
- 根本原因:数据结构不匹配、组件内外定义混乱、handleProjectClick逻辑错误
解决过程记录
尝试1:修改handleProjectClick函数(失败)
// 错误的尝试:添加detailContent判断
if (item?.isClickable && (item?.detailContent || item?.content)) {
setModalData(item?.detailContent || item?.content);
}
问题:数据结构本身有问题,修改判断逻辑无效
尝试2:移动clickableProjects到组件外部(失败)
// 尝试像智能制造项目那样定义在组件外
const clickableProjects = [...];
const ProjectLibraryPage = () => {...}
问题:没有解决根本的数据结构问题
最终解决方案:参考智能制造项目的完整结构
- 删除原有的错误结构
- 复制智能制造项目的数据格式
- 使用正确的content字段结构
正确的实现方式
1. 数据结构(参考智能制造项目)
const clickableProjects = [
{
id: "clickable-1",
name: "项目完整名称", // 显示在卡片上的名称
unitName: "对应单元", // 单元标签
isClickable: true, // 标记为可点击
content: { // 直接使用content字段
title: "项目标题",
description: "项目描述",
images: [ // 项目效果图数组
{ url: "图片路径", title: "图片说明" }
],
sections: [ // 内容章节
{
title: "章节标题",
content: "章节内容(支持Markdown)"
}
]
}
}
];
2. handleProjectClick函数逻辑
const handleProjectClick = async (item) => {
// 如果是普通的"我的项目",不允许点击
if (item?.isMyProject && !item?.isClickable) {
return;
}
// 如果是可点击的特殊项目,直接显示内容
if (item?.isClickable && item?.content) {
setModalData(item.content); // 使用content字段
setProjectCasesModalVisible(true);
return;
}
// 只有班级项目库的项目才调用API
if (item?.id && !item?.isClickable) {
const res = await getProjectsdetail(item.id);
// ...
}
};
3. ProjectCasesModal组件处理
Modal组件会根据data.sections判断使用哪种渲染方式:
- 有sections:使用新格式渲染(支持Markdown)
- 无sections:使用旧格式渲染(兼容班级项目库)
数据替换步骤(以购物网站项目为例)
步骤1:准备项目数据
- 读取项目MD文件
- 准备项目效果图列表
- 确定单元标签
步骤2:构建数据结构
{
id: "clickable-1",
name: "购物网站前端展示页面开发项目",
unitName: "智能前端项目",
isClickable: true,
content: {
title: "购物网站前端展示页面开发项目",
description: "项目描述...",
images: [
{ url: "/网页未导入数据/.../图片.jpg", title: "首页展示" },
// ... 更多图片
],
sections: [
{
title: "一、项目背景",
content: "内容文本\n\n支持Markdown格式"
},
// ... 更多章节
]
}
}
步骤3:处理Markdown内容
- 使用
\n表示换行(在字符串中) - 支持Markdown语法(加粗、表格、列表等)
- 处理特殊字符转义
关键注意事项
✅ 正确做法
- 使用content字段,不要使用detailContent
- 保持数据结构一致,参考智能制造项目
- 设置isClickable: true,标记为可点击项目
- sections数组格式,每个section有title和content
❌ 错误做法
- 不要在content中嵌套多余的字段
- 不要混用content和detailContent
- 不要忘记设置isClickable标志
- 不要修改Modal组件的渲染逻辑
问题排查清单
- clickableProjects数组定义位置正确(组件内部)
- 数据结构使用content字段(不是detailContent)
- isClickable设置为true
- handleProjectClick函数检查isClickable和content
- sections数组格式正确
- Markdown内容正确转义(\n表示换行)
- 图片路径正确且可访问
功能说明
"我完成的项目库"是项目库页面中的特殊板块,展示学生已完成的项目列表。这些项目显示为灰色、不可点击的样式,表示已完成但不提供详情查看。
数据结构
// src/pages/ProjectLibraryPage/index.jsx
const myProjectsData = [
{
unitName: "单元名称",
projects: ["项目1", "项目2", ...]
},
// ... 更多单元
];
通用替换方法
步骤1:分析数据源格式
检查原始JSON数据的字段结构,识别关键字段:
- 产业/方向标识字段
- 单元名称字段
- 项目列表字段
步骤2:创建数据转换脚本
基本脚本结构:
const fs = require('fs');
// 1. 读取源数据
const sourceData = JSON.parse(fs.readFileSync('数据源路径', 'utf-8'));
// 2. 筛选目标数据
const filteredData = sourceData.filter(item => {
// 根据产业特征筛选
return item['产业字段'] === '目标产业';
});
// 3. 转换数据格式
const formattedData = filteredData.map(item => ({
unitName: item['单元字段'],
projects: item['项目字段']
.filter(p => p && p.trim() !== '')
.map(p => {
// 清理项目名称格式(去除序号等)
return p.replace(/^\d+\.\s*/, '');
})
}));
// 4. 替换页面数据
const targetFile = './src/pages/ProjectLibraryPage/index.jsx';
let fileContent = fs.readFileSync(targetFile, 'utf-8');
fileContent = fileContent.replace(
/const myProjectsData = \[\s*[\s\S]*?\];/,
`const myProjectsData = ${JSON.stringify(formattedData, null, 2)};`
);
fs.writeFileSync(targetFile, fileContent);
步骤3:数据格式化处理
常见的格式处理需求:
- 去除项目名称前的序号
- 过滤空项目
- 统一单元名称格式
- 处理特殊字符
数据要求
必要字段
- unitName: 单元名称(与课程系统对应)
- projects: 项目名称数组
格式规范
- 单元名称需与课程单元系统保持一致
- 项目名称应简洁明确
- 避免重复的序号或标记
验证要点
-
数据完整性
- 确认所有单元都有对应的项目
- 检查项目数量是否合理
-
格式一致性
- 单元名称格式统一
- 项目名称无多余格式符号
-
显示效果
- 项目正确分组显示
- 样式为灰色不可点击状态
常见问题处理
问题:数据未显示
- 检查筛选条件是否正确
- 验证字段名称匹配
- 确认数据路径正确
问题:格式异常
- 检查正则表达式处理逻辑
- 验证JSON格式正确性
- 确认字符编码一致
问题:单元分组错误
- 核对单元名称映射
- 检查数据分组逻辑
- 验证源数据结构
与系统其他部分的关联
- 课程系统: 单元名称需保持一致
- 个人档案: 可作为学习成果展示
- 可点击项目: 两者独立,互不影响
版本更新记录
- v2.5 (2025-09-16): 重构第十三节为"我完成的项目"板块数据替换实战指南
- 记录完整的问题解决历程和多次尝试过程
- 提供正确的clickableProjects数据结构示例
- 详细说明handleProjectClick函数逻辑
- 明确content字段vs detailContent字段的使用
- 添加问题排查清单和注意事项
- v2.4 (2025-09-16): 新增第十四节:"我完成的项目库"板块数据逻辑与替换指南
- 说明通用的数据结构和替换方法
- 提供脚本模板和处理流程
- 列出常见问题的通用解决方案
- v2.3 (2025-09-16): 添加项目库页面数据替换详细问题记录和解决方案
- 问题13:项目库页面数据引用错误合集(8个子问题)
- 13.1:项目名称显示undefined - 字段名错误
- 13.2:岗位等级标签颜色错误 - 等级名称不匹配
- 13.3:对应单元分类错误 - 缺少映射函数
- 13.4:单元点击功能缺失 - 未实现handleUnitClick
- 13.5:单元hover效果缺失 - 缺少CSS类名
- 13.6:适用岗位未排序 - 缺少排序逻辑
- 13.7:Markdown内容多余标题 - 格式处理不当
- 13.8:Mock文件语法错误 - 多余的]符号
- 新增第九节:项目库页面正确数据替换流程总结
- 问题14:修改版简历格式处理错误
- 问题13:项目库页面数据引用错误合集(8个子问题)
- v2.2 (2025-09-15): 完善常见问题部分,添加问题10-12的详细解决方案
- 问题10:面试题卡片显示异常的解决方案
- 问题11:修改版标记显示错误的处理方法
- 问题12:岗位等级标签配置指南
- v2.1 (2025-09-15): 添加日历数据替换问题及解决方案,更新为智能开发产业
- v2.0 (2024-09-15): 完善数据架构文档,添加详细替换步骤
- v1.0 (2024-09-01): 初始版本