Files
online_sys/frontend_智能开发/数据架构与替换指南.md
KQL a7242f0c69 Initial commit: 教务系统在线平台
- 包含4个产业方向的前端项目:智能开发、智能制造、大健康、财经商贸
- 已清理node_modules、.yoyo等大文件,项目大小从2.6GB优化至631MB
- 配置完善的.gitignore文件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 18:16:55 +08:00

57 KiB
Raw Blame History

教务系统数据架构与产业替换指南

核心原则 ⚠️

🔴 绝对不可修改的内容

  1. 页面样式和布局 - 保持所有CSS类名、样式文件完全不变
  2. 组件结构 - 不改动React组件的结构和渲染逻辑
  3. 数据处理逻辑 - 保留所有数据转换、过滤、排序等处理函数
  4. 字段名称 - 保持JSON和对象的所有字段名不变包括中文字段名
  5. 数据流向 - 维持组件间的数据传递方式和状态管理

只替换以下内容

  1. 具体数据值 - 学生姓名、课程名称、岗位名称等实际内容
  2. 图片URL - 头像、海报、背景图等资源链接
  3. 文本内容 - 简历内容、项目描述、面试题等文字
  4. 数值数据 - 学分、排名、薪资等数值

📋 替换原则总结

保持框架不变,只换内容
保持逻辑不变,只换数据
保持样式不变,只换文字
保持结构不变,只换数值

一、系统整体数据架构

核心数据文件结构

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.jsdashboardStatistics.ranking.topStudents
  • 学习进度: mockData.jsdashboardStatistics.learningProgress
  • 推荐岗位: mockData.jsdashboardStatistics.recommendedJobs
  • 用户信息: mockData.jspersonalProfile

数据流:

// mockData.js 中的数据结构
dashboardStatistics: {
  ranking: {
    currentRank: 2,        // 当前排名
    totalStudents: 45,     // 总人数
    topStudents: [...]     // 前10名学生数据
  },
  learningProgress: {...},
  recommendedJobs: [...]
}

替换要点:

  1. 更新 topStudents 数组中的学生信息
  2. 保持数据结构不变,只替换内容
  3. 不修改任何样式和组件逻辑

2. 个人档案页面 (PersonalProfile)

文件位置: src/pages/PersonalProfilePage/index.jsx

数据来源:

  • 个人信息: mockData.jspersonalProfile
  • 班级排名: mockData.jspersonalProfile.classRanking
  • 学习记录: mockData.jspersonalProfile.learningRecords

数据流:

personalProfile: {
  basicInfo: {
    name: "王强",
    studentId: "2325010211",
    school: "苏州健雄职业技术学院",
    major: "模具设计与制造",
    // ...
  },
  classRanking: [...],
  credits: 95
}

替换要点:

  1. 从产业个人档案JSON导入数据
  2. 更新头像路径
  3. 保持MBTI等个性化数据
  4. 不修改页面布局和CSS样式
  5. 保留所有数据处理逻辑

3. 简历与面试页面 (ResumeInterview)

文件位置: src/pages/ResumeInterviewPage/index.jsx

数据来源:

  • 岗位群数据: resumeInterviewMock.jsindustries
  • 岗位列表: resumeInterviewMock.jsindustries[].positions
  • 简历模板: resumeInterviewMock.jsresumeTemplates
  • 面试题: resumeInterviewMock.jsindustries[].questions
  • 修改版标记: 页面内 hasRealModifiedVersion() 函数

数据结构:

// resumeInterviewMock.js
industries: [
  {
    id: "manufacturing_1",
    name: "3D打印工艺",
    positions: [...],     // 该岗位群下的所有岗位
    questions: [...]      // 该岗位群的面试题
  }
]

resumeTemplates: {
  "3D打印工艺": [
    {
      position: "3D打印工程师",
      content: {
        original: "原始版简历内容",
        modified: "修改版简历内容"
      }
    }
  ]
}

替换要点:

  1. 替换岗位群名称和ID
  2. 更新每个岗位的详细信息
  3. 替换简历内容(保持original和modified结构
  4. 更新面试题内容
  5. 修改 hasRealModifiedVersion 函数中的岗位列表
  6. 绝不改动组件渲染逻辑和样式

4. 企业内推岗位页面 (CompanyJobs)

文件位置: src/pages/CompanyJobsPage/index.jsx

数据来源:

  • 岗位列表: companyJobsNew.json
  • 面试状态: interviewStatus.json
  • 岗位详情: companyJobsNew.json → 各岗位的详细字段

数据结构:

// companyJobsNew.json
[
  {
    "公司名称": "苏州某科技有限公司",
    "查询岗位名称": "PLC控制工程师",
    "招聘人数": "2人",
    "学历要求": "大专及以上",
    "薪资": "8-12K",
    // ...
  }
]

// interviewStatus.json
[
  {
    "查询岗位名称": "PLC控制工程师",
    "阶段日期": "收到Offer2025/9/14 16:17",
    "面试状态": "已收到Offer请于2天内答复"
  }
]

替换要点:

  1. 保持JSON字段名不变中文字段名
  2. 更新岗位内容为新产业岗位
  3. 同步更新面试状态数据
  4. 不修改页面交互逻辑
  5. 保持原有动画效果

5. 项目库页面 (ProjectLibrary)

文件位置: src/pages/ProjectLibraryPage/index.jsx

数据来源:

  • 项目列表: projectLibraryMock.jsprojects
  • 项目详情: projectLibraryMock.jsprojects[].details
  • 适用岗位: projectLibraryMock.jsprojects[].suitablePositions
  • 对应单元: projectLibraryMock.jsprojects[].relatedUnit

数据结构:

// projectLibraryMock.js
projects: [
  {
    id: 1,
    title: "90°弯管液压歧管3D打印项目",
    category: "3D打印工艺",
    suitablePositions: ["3D打印工程师", "3D打印产品设计师"],
    relatedUnit: "单元一",
    details: {
      background: "项目背景...",
      objectives: ["目标1", "目标2"],
      // ...
    }
  }
]

替换要点:

  1. 更新项目名称和分类
  2. 替换适用岗位列表
  3. 更新项目详情内容
  4. 保持单元映射关系
  5. 不改动模态框和卡片组件

6. 课程直播间页面 (CourseLive)

文件位置: src/pages/CourseLivePage/index.jsx

数据来源:

  • 课程列表: mockData.jscourseLiveList (复合能力课)
  • 垂直课程: mockData.jsverticalCourseLiveList
  • 公共课程: mockData.jspublicCourseLiveList
  • 单元海报: courseLiveDataImport.jsunitPosters

数据流:

// 从智能制造课程日历.json生成
courseLiveList: generateCourseLiveListFromCalendar('compound-skill')
verticalCourseLiveList: generateCourseLiveListFromCalendar('vertical-skill')

// 单元海报映射
unitPosters: {
  "单元一": "https://xxx.com/unit1.jpg",
  // ...
}

替换要点:

  1. 更新课程日历JSON文件
  2. 更新单元背景JSON文件
  3. 确保课程类型字段正确(复合课阶段/垂直课阶段)
  4. 保持课程卡片样式不变
  5. 不修改数据转换函数

7. 日历页面 (Calendar)

文件位置: src/pages/CalendarPage/index.jsx

数据来源:

  • 日历事件: mockData.jscalendarEvents
  • 源数据: 智能制造课程日历.json

数据转换流程:

// courseLiveDataImport.js
智能制造课程日历.json  transformCalendarCourses()  calendarEvents

// 事件类型判断
课程阶段个人课程包含"复合"  type: 'compound-skill'
课程阶段个人课程包含"垂直"  type: 'vertical-skill'
公共课字段有值  type: 'public'

替换要点:

  1. 更新课程日历JSON
  2. 保持日期格式YYYY/M/D
  3. 正确设置课程类型字段
  4. 不改动日历组件和事件渲染

8. 课程作业页面 (Homework)

文件位置: src/pages/HomeworkPage/index.jsx

数据来源:

  • 作业列表: mockData.jshomework
  • 动态生成: 从 courseLiveList 自动生成

数据生成逻辑:

// mockData.js 中的动态生成
if (mockData.homework && mockData.homework[0]) {
  // 从courseLiveList生成复合能力课作业
  mockData.courseLiveList.forEach(unit => {
    unit.courses.forEach(course => {
      // 生成作业项
    });
  });
}

替换要点:

  1. 作业内容自动从课程列表生成
  2. 无需手动更新作业数据
  3. 保持作业卡片样式
  4. 不修改生成逻辑

9. 岗位攻略详情页 (JobStrategyDetail)

文件位置: src/pages/JobStrategyDetailPage/index.jsx

数据来源:

  • 岗位详情: 从URL参数获取岗位匹配 companyJobsNew.json
  • 优先级数据: 页面内定义

替换要点:

  1. 更新岗位优先级列表
  2. 更新岗位分析内容
  3. 保持图表和可视化组件不变

10. 专家支持中心 (ExpertSupport)

文件位置: src/pages/ExpertSupportPage/index.jsx

数据来源:

  • 问答数据: expertSupportData.js
  • 聊天记录: expertSupportData.jschatMessages

数据结构:

// expertSupportData.js
export const expertSupportData = {
  faqs: [...],
  chatMessages: [...],
  expertProfiles: [...]
}

替换要点:

  1. 更新FAQ内容
  2. 更新预设的聊天消息
  3. 更新专家信息
  4. 保持聊天界面样式
  5. 不修改消息处理逻辑

三、导师信息替换专项指南

导师数据结构说明

导师信息存储在 src/data/mockData.jsteacherData 对象中,通过 updateTeacherCourses 函数与课程日历事件关联。

导师类型分类

  1. 复合课导师 - 产业专属,需要替换
  2. 公共课导师 - 通用导师,保持不变
  3. AI课导师 - 通用导师,保持不变
  4. 企业资深HR - 通用导师,保持不变

替换步骤

  1. 识别需要替换的导师

    • 查找所有 type: "复合课导师" 的导师
    • 这些是产业相关的专业导师
  2. 准备新导师数据

    • 从"导师信息(通用).json"中选择新产业相关导师
    • 确保导师的垂直方向与产业匹配
  3. 更新导师信息

    // 示例:智能制造产业导师
    "王军": {
      name: "王军",
      introduction: "导师介绍内容...",
      specialties: ["30年研发专家", "主导国标制定", "资深机械结构专家", "单产品创收百万"],
      avatar: "https://头像URL",
      type: "复合课导师",
      verticalDirection: "机械加工工艺",
      courses: []  // 自动由updateTeacherCourses函数填充
    }
    
  4. 垂直方向对应关系

    • 智能制造:机械加工工艺、智能机械产品结构与外观设计、智能制造非标自动化产线搭建、自动化设备智能调试
    • 文旅:项目经营管理、商业活动策划、文化服务
    • 其他产业:根据实际垂直方向设置
  5. 注意事项

    • ⚠️ 保持导师对象的键名与name属性一致
    • ⚠️ courses数组留空由系统自动填充
    • ⚠️ 不要修改updateTeacherCourses函数逻辑
    • ⚠️ 保留所有公共课导师、AI课导师和HR导师

导师信息验证

  1. 检查导师是否在课程播放器中正确显示
  2. 验证导师的课程列表是否自动更新
  3. 确认导师头像URL可访问

四、各页面详细替换步骤指南

📌 页面1主页 (Dashboard)

步骤流程:

  1. 准备数据

    • 从新产业个人档案JSON获取前10名学生数据
    • 准备学生头像图片URL
  2. 修改文件: src/data/mockData.js

    // 找到 dashboardStatistics.ranking.topStudents
    // 替换为新的学生数组,格式如下:
    topStudents: [
      {
        rank: 1,
        name: "新学生名",
        studentId: "新学号",
        school: "新学校",
        major: "新专业",
        credits: 97,
        avatar: "/images/avatars/新头像.jpg"
      },
      // ... 继续添加前10名
    ]
    
  3. 验证要点

    • 确保rank从1到10递增
    • 学分按降序排列
    • 头像路径正确可访问
    • 不要修改字段名称
    • 不要改动组件样式

📌 页面2个人档案 (PersonalProfile)

步骤流程:

  1. 选择目标学生

    • 从个人档案JSON中选择一个学生如排名第2的学生
  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: [/* 可选:更新学习记录 */]
    }
    
  3. 同步更新侧边栏

    • 确保Sidebar组件引用的是同一个personalProfile数据
  4. 验证要点

    • 个人信息与选定学生一致
    • 班级排名数据与Dashboard同步
    • 不要修改组件结构

📌 页面3简历与面试 (ResumeInterview)

步骤流程:

  1. 准备简历数据

    • 整理新产业的岗位群和岗位列表
    • 准备每个岗位的原始版和修改版简历
  2. 修改文件: 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一致
        // ... 其他个人信息
      }
    }
    
  3. 修改页面文件: src/pages/ResumeInterviewPage/index.jsx

    // 更新 hasRealModifiedVersion 函数
    const hasRealModifiedVersion = (positionTitle) => {
      const modifiedPositions = [
        "新岗位1",
        "新岗位2",
        // ... 有修改版的岗位列表
      ];
      return modifiedPositions.includes(positionTitle);
    };
    
  4. 验证要点

    • 岗位群和岗位数据完整
    • 简历内容格式正确Markdown
    • 修改版标记正确显示
    • 不要改动Tab切换逻辑

📌 页面4企业内推岗位 (CompanyJobs)

步骤流程:

  1. 准备岗位数据

    • 整理新产业的企业岗位信息
    • 准备对应的面试状态数据
  2. 修改文件: src/data/companyJobsNew.json

    [
      {
        "公司名称": "苏州某科技有限公司",
        "查询岗位名称": "PLC控制工程师",
        "招聘人数": "2人",
        "学历要求": "大专及以上",
        "薪资": "8-12K",
        "工作地点": "苏州工业园区",
        "岗位职责": ["职责1", "职责2"],
        "任职要求": ["要求1", "要求2"]
      }
      // ... 更多岗位
    ]
    
  3. 修改文件: src/data/interviewStatus.json

    [
      {
        "查询岗位名称": "PLC控制工程师",
        "阶段日期": "收到Offer2025/9/14 16:17",
        "面试状态": "已收到Offer请于2天内答复"
      }
      // ... 更多状态
    ]
    
  4. 修改简历模态框默认值: src/pages/CompanyJobsPage/components/ResumeInfoModal/index.jsx

    education: [{
      school: '新学校名称',
      major: '新专业名称',
      period: '2020.9-2023.6'
    }]
    
  5. 验证要点

    • 岗位信息字段完整
    • 面试状态与岗位对应
    • 保持中文字段名
    • 不要修改动画效果

📌 页面5项目库 (ProjectLibrary)

步骤流程:

  1. 准备项目数据

    • 整理新产业的项目案例
    • 确定项目与岗位的映射关系
  2. 修改文件: src/mocks/projectLibraryMock.js

    projects: [
      {
        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"]
        }
      }
      // ... 更多项目
    ]
    
  3. 验证要点

    • 项目详情结构完整
    • 岗位名称与简历页面一致
    • 不要修改卡片组件样式

📌 页面6课程直播间 (CourseLive)

步骤流程:

  1. 准备课程数据

    • 整理课程日历JSON
    • 准备单元背景图片
  2. 更新数据文件:

    • 将新的课程日历JSON放到 src/data/[产业名称]课程日历.json
    • 将单元背景JSON放到 src/data/[产业名称]单元背景.json
  3. 修改导入配置: src/data/courseLiveDataImport.js

    // 修改导入路径
    import calendarData from './[产业名称]课程日历.json';
    import unitPostersData from './[产业名称]单元背景.json';
    
    // 数据会自动通过transformCalendarCourses转换
    
  4. 数据格式要求

    // 课程日历JSON格式
    {
      "个人课程表": "课程名称",
      "课程阶段(个人课程)": "复合课阶段/垂直课阶段",
      "所属单元(个人课程)": "单元一",
      "日期": "2024/7/15"
    }
    
  5. 更新导师信息: src/data/mockData.js

    • 在teacherData对象中替换导师信息
    • 复合课导师需要替换为新产业相关导师
    • 公共课导师、AI课导师、HR导师保持不变
    teacherData: updateTeacherCourses({
      "导师名": {
        name: "导师名",
        introduction: "导师介绍...",
        specialties: ["特长1", "特长2", "特长3", "特长4"],
        avatar: "头像URL",
        type: "复合课导师/公共课导师/AI课导师/企业资深HR",
        verticalDirection: "垂直方向",
        courses: []
      },
      // ... 更多导师
    }, allCalendarEvents)
    
  6. 验证要点

    • 课程正确分类(复合/垂直)
    • 单元海报URL可访问
    • 公共课保持不变
    • 导师信息与产业匹配
    • 不要修改课程卡片样式
    • 不要修改导师卡片组件

📌 页面7日历 (Calendar)

步骤流程:

  1. 准备日历数据文件

    • 创建智能开发课程日历.json智能开发单元背景.json
    • 确保日期格式为 YYYY/M/D
  2. 创建数据转换脚本 convertCalendarData.cjs

    const 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');
    
  3. 更新mockData.js导入路径

    // 必须更新这两行导入!
    import calendarCoursesData from './智能开发课程日历.json';
    import intelligentManufacturingUnitData from './智能开发单元背景.json';
    
  4. 更新导师头像映射

    const teacherAvatars = {
      // 原有导师...
      // 新增智能开发产业导师
      "谢宇程": "头像URL",
      "何思远": "头像URL",
      // ...
    };
    
  5. 验证要点

    • mockData.js导入路径已更新
    • JSON文件已复制到src/data
    • 日期格式转换正确
    • 课程类型判断准确
    • 导师头像映射完整
    • 不要修改日历组件
    • 不要修改transformCalendarCourses函数

📌 页面8课程作业 (Homework)

步骤流程:

  1. 自动生成机制

    • 作业从courseLiveList自动生成
    • 无需手动修改
  2. 验证生成逻辑: src/data/mockData.js

    // 检查动态生成代码是否正常工作
    if (mockData.homework && mockData.homework[0]) {
      // 复合能力课作业生成
      // 垂直能力课作业生成
    }
    
  3. 验证要点

    • 作业与课程对应
    • 单元分组正确
    • 不要修改作业卡片

📌 页面9岗位攻略详情 (JobStrategyDetail)

步骤流程:

  1. 更新岗位分析数据

    • 岗位数据从companyJobsNew.json读取
    • 可在页面内更新优先级分析
  2. 修改页面文件(如需要): src/pages/JobStrategyDetailPage/index.jsx

    // 更新岗位优先级数据
    const jobPriorities = [
      { name: '新岗位1', priority: 'high' },
      { name: '新岗位2', priority: 'medium' },
      // ...
    ];
    
  3. 验证要点

    • 岗位详情正确显示
    • 图表数据更新
    • 不要修改图表组件

📌 页面10专家支持中心 (ExpertSupport)

步骤流程:

  1. 准备FAQ和聊天数据

    • 整理新产业相关的常见问题
    • 准备预设聊天消息
  2. 修改文件: src/data/expertSupportData.js

    export const expertSupportData = {
      faqs: [
        {
          question: "新产业相关问题1",
          answer: "答案1"
        }
        // ... 更多FAQ
      ],
      chatMessages: [
        {
          type: 'expert',
          content: '欢迎咨询新产业相关问题',
          time: '10:00'
        }
        // ... 预设消息
      ],
      expertProfiles: [
        {
          name: "专家名",
          title: "新产业专家",
          expertise: ["领域1", "领域2"]
        }
      ]
    }
    
  3. 验证要点

    • FAQ内容相关
    • 聊天消息合理
    • 不要修改聊天界面

三、产业数据替换步骤指南

第一步:准备源数据文件

  1. 创建产业数据文件夹

    网页未导入数据/[产业名称]/
    ├── [产业名称]个人档案.json
    ├── [产业名称]课程日历.json
    ├── [产业名称]单元背景.json
    ├── [产业名称]岗位面试状态.json
    └── [产业名称]修改版简历/
        ├── 岗位1.md
        ├── 岗位2.md
        └── ...
    
  2. 数据格式要求

    • 个人档案:包含学生信息、学校、专业、学分、排名等
    • 课程日历:包含日期、课程名称、课程阶段、所属单元等
    • 单元背景包含单元名称和海报URL
    • 岗位面试状态:包含岗位名称、面试阶段、状态描述

第二步:更新核心数据文件

  1. 更新 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)
    
  2. 更新 resumeInterviewMock.js

    • 替换 industries 数组(岗位群)
    • 替换 resumeTemplates 对象(简历内容)
    • 更新 myResume 对象(个人简历)
  3. 更新 projectLibraryMock.js

    • 替换 projects 数组
    • 更新项目与岗位的映射关系
  4. 更新其他JSON文件

    • companyJobsNew.json企业岗位数据
    • interviewStatus.json面试状态数据

第三步:更新页面特定逻辑

  1. ResumeInterviewPage

    // 更新修改版岗位列表
    const hasRealModifiedVersion = (positionTitle) => {
      const modifiedPositions = [
        // 新产业的岗位列表
      ];
      return modifiedPositions.includes(positionTitle);
    };
    
  2. ResumeInfoModal

    // 更新默认教育经历
    education: [{
      school: '新学校名称',
      major: '新专业名称',
      period: '2020.9-2023.6'
    }]
    

第四步:验证数据完整性

  1. 检查清单

    • 个人信息是否正确显示
    • 班级排名数据是否同步
    • 课程列表是否正确分类
    • 岗位和简历是否匹配
    • 项目库内容是否更新
    • 面试状态是否正确
    • 修改版标记是否显示
  2. 常见问题排查

    • 数据不显示检查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数据不显示

症状:页面空白或数据缺失 解决

  1. 检查import路径是否正确
  2. 确认JSON文件格式无误
  3. 查看浏览器控制台错误

问题2样式错乱

症状:布局混乱或样式丢失 原因可能修改了CSS类名或组件结构 解决:恢复原始组件代码,只修改数据

问题3修改版标记不显示

症状:简历页面修改版标记缺失 解决

  1. 检查hasRealModifiedVersion函数
  2. 确认岗位名称完全匹配
  3. 验证modified字段有内容

问题4课程分类错误

症状:复合课和垂直课混淆 解决

  1. 检查"课程阶段(个人课程)"字段
  2. 确认包含"复合"或"垂直"关键字
  3. 验证transformCalendarCourses函数

问题5作业不生成

症状:作业页面为空 解决

  1. 确认courseLiveList有数据
  2. 检查动态生成代码执行
  3. 验证课程类型判断逻辑

问题6头像不显示

症状学生头像404 解决

  1. 将头像文件放到public/images/avatars/
  2. 使用正确的相对路径
  3. 确认文件名大小写匹配

问题7日期格式错误

症状:日历事件不显示 解决

  1. 使用YYYY/M/D格式斜杠分隔
  2. 不要补零7/15而非07/15
  3. 检查日期字段名称

问题8中文字段名问题

症状:数据读取失败 解决

  1. 保持原有中文字段名
  2. 不要改为英文
  3. 注意字段名完全匹配

问题9日历页面数据未更新

症状日历页面仍显示原始数据即使已替换了课程日历JSON文件 原因mockData.js中的导入路径未更新 解决

  1. 检查src/data/mockData.js中的导入语句:
    // 错误:仍然导入旧的智能制造数据
    import calendarCoursesData from './intelligentManufacturingCalendar.json';
    import intelligentManufacturingUnitData from '../../网页未导入数据/智能制造产业/智能制造单元背景.json';
    
    // 正确:导入新的产业数据
    import calendarCoursesData from './智能开发课程日历.json';
    import intelligentManufacturingUnitData from './智能开发单元背景.json';
    
  2. 确保新的JSON文件已复制到src/data/目录
  3. 更新teacherAvatars映射添加新产业的导师头像
  4. 验证transformCalendarCourses函数能处理新的数据格式

预防措施

  • 创建数据转换脚本时同时更新mockData.js的导入路径
  • 使用脚本自动复制数据文件到正确位置
  • 在转换脚本中添加导入路径更新逻辑

问题10面试题卡片显示异常

症状:一个岗位群显示多个面试题卡片,而不是一个卡片包含所有问题 原因:面试题数据结构不正确,每个问题被创建为独立卡片 解决

  1. 确保每个岗位群只有一个面试题对象:

    // 错误:为每个问题创建独立卡片
    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' }
      ]
    }]
    
  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函数包含了所有岗位名称 解决

  1. 检查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);
    };
    
  2. 验证修改版文件是否存在:

    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 对应单元分类错误

原因:使用简单的关键词匹配而不是正确的映射函数 错误做法:尝试通过判断单元名称中是否包含"复合"或"垂直"来分类 正确做法

  1. 创建projectUnitsMapping.js文件定义项目与单元的映射关系
  2. 导入并使用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格式未正确处理 解决

  1. 创建处理函数清理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();
    }
    
  2. 在导入修改版简历时应用处理:

    modifiedFiles.forEach(file => {
      const content = fs.readFileSync(filePath, 'utf-8');
      const processedContent = processModifiedResume(content);
      modifiedResumes[positionName] = processedContent;
    });
    

预防措施

  • 制定修改版简历的格式规范
  • 在数据导入时统一处理格式
  • 保留原始内容和处理后内容的对照

问题12岗位等级标签未显示

症状:简历页面的岗位卡片没有显示等级标签(储备干部岗/技术骨干岗/普通岗) 原因joblevel.json文件未更新或数据不匹配 解决

  1. 更新src/data/joblevel.json文件:

    {
      "data": {
        "high": {
          "name": "储备干部岗",
          "list": [
            {
              "position_name": "岗位名称",
              "img": "头像URL"
            }
            // ... 所有储备干部岗位
          ]
        },
        "middle": {
          "name": "技术骨干岗",
          "list": [/* ... */]
        },
        "ordinary": {
          "name": "普通岗",
          "list": [/* ... */]
        }
      }
    }
    
  2. 确保岗位名称完全匹配:

    • resumeInterviewMock.js中的position.title
    • joblevel.json中的position_name
    • 名称必须一字不差
  3. 创建更新脚本自动生成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准备数据文件

  1. 获取项目案例JSON数据

    • 确保JSON使用正确的字段名如"案例名称"而非"项目名称"
    • 验证所有必需字段存在
  2. 创建项目单元映射文件

    // src/data/projectUnitsMapping.js
    export const projectUnitsMapping = {
      "项目名称": {
        "compoundUnits": ["复合能力课1", "复合能力课2"],
        "verticalUnits": ["垂直能力课1", "垂直能力课2"]
      }
    };
    

步骤2更新Mock文件

  1. 使用正确的字段名

    // 解析JSON时使用实际的字段名
    title: project['案例名称'] + '详情',  // 不是'项目名称'
    
  2. 正确设置岗位等级

    applicablePositions: [
      { level: '基础岗', position: '岗位名' },      // 不是'普通岗'
      { level: '技术骨干岗', position: '岗位名' },
      { level: '储备干部岗', position: '岗位名' }
    ]
    

步骤3更新组件逻辑

  1. 导入映射函数

    import { getCompoundUnits, getVerticalUnits } from '@/data/projectUnitsMapping';
    
  2. 添加单元点击处理

    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()}`);
    };
    
  3. 处理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添加样式类

  1. 确保hover效果

    <li className="class-list-item clickable-unit">
    
  2. 正确的等级样式判断

    className={pos.level === '基础岗' ? 'low' :
               pos.level === '技术骨干岗' ? 'medium' : 'high'}
    

步骤5数据验证

  1. 检查语法错误

    node -c src/mocks/projectLibraryMock.js
    
  2. 验证数据完整性

    • 项目名称正确显示
    • 岗位等级标签颜色正确
    • 单元分类准确
    • 点击功能正常
    • hover效果存在
    • 岗位按等级排序
    • 附件显示"暂无附件"

关键要点总结

  1. 永远不要假设字段名 - 始终检查实际JSON的字段名
  2. 保持数据一致性 - 等级名称、岗位名称必须全局一致
  3. 使用映射而非硬编码 - 通过映射文件管理项目与单元关系
  4. 处理数据格式 - 正确处理Markdown、换行符等格式问题
  5. 验证每一步 - 每次修改后立即验证,不要累积问题

十、测试验证方法

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: 替换为[产业名称]产业数据"

十一、数据替换最佳实践

👍 推荐做法

  1. 分步替换:先替换一个页面,测试后再继续
  2. 版本控制:每完成一个模块就提交一次
  3. 注释标记:在修改处添加注释说明
  4. 数据验证使用console.log验证数据加载
  5. 团队协作:记录修改内容供团队参考

👎 避免做法

  1. 批量替换:不要使用全局查找替换
  2. 跳过备份:不要直接修改无备份文件
  3. 忽略错误:不要忽视控制台警告
  4. 修改框架不要改动React组件逻辑
  5. 更改样式不要修改CSS文件

十二、产业切换总结

核心要点回顾

  1. 数据与逻辑分离:只替换数据,保持逻辑
  2. 结构保持一致:维护原有数据结构
  3. 样式不做修改:保留所有样式文件
  4. 字段名不改变:特别是中文字段名
  5. 测试验证充分:每步都要验证结果

成功标准

  • 所有页面正常显示
  • 数据内容正确更新
  • 功能交互正常工作
  • 样式布局保持原样
  • 无控制台错误警告

最后更新时间: 2025年9月16日 当前产业: 智能开发 维护人员: System Admin 文档版本: v2.4

十三、"我完成的项目"板块数据替换实战指南

问题描述与解决历程

遇到的问题

  1. 初始问题:购物网站项目点击后显示的是班级项目库的内容,而不是本地定义的内容
  2. 根本原因数据结构不匹配、组件内外定义混乱、handleProjectClick逻辑错误

解决过程记录

尝试1修改handleProjectClick函数失败
// 错误的尝试添加detailContent判断
if (item?.isClickable && (item?.detailContent || item?.content)) {
  setModalData(item?.detailContent || item?.content);
}

问题:数据结构本身有问题,修改判断逻辑无效

尝试2移动clickableProjects到组件外部失败
// 尝试像智能制造项目那样定义在组件外
const clickableProjects = [...];
const ProjectLibraryPage = () => {...}

问题:没有解决根本的数据结构问题

最终解决方案:参考智能制造项目的完整结构
  1. 删除原有的错误结构
  2. 复制智能制造项目的数据格式
  3. 使用正确的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准备项目数据

  1. 读取项目MD文件
  2. 准备项目效果图列表
  3. 确定单元标签

步骤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语法加粗、表格、列表等)
  • 处理特殊字符转义

关键注意事项

正确做法

  1. 使用content字段不要使用detailContent
  2. 保持数据结构一致,参考智能制造项目
  3. 设置isClickable: true,标记为可点击项目
  4. sections数组格式每个section有title和content

错误做法

  1. 不要在content中嵌套多余的字段
  2. 不要混用content和detailContent
  3. 不要忘记设置isClickable标志
  4. 不要修改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: 项目名称数组

格式规范

  • 单元名称需与课程单元系统保持一致
  • 项目名称应简洁明确
  • 避免重复的序号或标记

验证要点

  1. 数据完整性

    • 确认所有单元都有对应的项目
    • 检查项目数量是否合理
  2. 格式一致性

    • 单元名称格式统一
    • 项目名称无多余格式符号
  3. 显示效果

    • 项目正确分组显示
    • 样式为灰色不可点击状态

常见问题处理

问题:数据未显示

  • 检查筛选条件是否正确
  • 验证字段名称匹配
  • 确认数据路径正确

问题:格式异常

  • 检查正则表达式处理逻辑
  • 验证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.7Markdown内容多余标题 - 格式处理不当
      • 13.8Mock文件语法错误 - 多余的]符号
    • 新增第九节:项目库页面正确数据替换流程总结
    • 问题14修改版简历格式处理错误
  • 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): 初始版本