数据迁移方案 v1(leifeng-miniapp → 泽湖成长平台)¶
作者:🤖 Harness 通道(2026-08-15,M0 前置准备,配合 Codex 车道 B D3 任务) 用途:Codex D3 实现数据迁移脚本(
server/scripts/)时的直接依据 旧库:C:\Users\lvxin\OneDrive\Desktop\leifeng-miniapp(微信云开发,schema 见database/schema.md) 新库:泽湖server/prisma/schema.prisma(对齐docs/06-数据模型.md) ⚠️ 禁区:迁移脚本只读旧库导出数据(JSON),不直接操作云开发 xb_* 云函数;旧库仅导出,不修改。
1. 集合映射总览¶
| 旧集合(leifeng) | 新模型(泽湖) | 迁移方式 | 说明 |
|---|---|---|---|
students |
User(role=student)+ 历史快照 |
主迁移 | 学生主体 |
classes |
Class |
主迁移 | 班级 + 班主任 |
users |
User(parent/teacher/admin) |
主迁移 | 家长/教师/管理员 |
logs |
EvaluationRecord |
全量或快照(见 §5 决策) | 成长记录核心 |
checkins |
可选(新签到体系待定) | 归档不迁移 | 建议导出备份 |
settings.dimensions |
EvaluationPoint(映射) |
生成种子 | 五维定义对照 |
2. 五维 code 映射(关键)¶
| 旧 code | 旧名称 | 新 dimension | 新 EvaluationPoint 前缀 |
|---|---|---|---|
de |
德 | moral 思想品德 |
p_moral_* |
zhi |
智 | academic 学业水平 |
p_academic_* |
ti |
体 | health 身心健康 |
p_health_* |
mei |
美 | art 艺术素养 |
p_art_* |
lao |
劳 | practice 劳动与社会实践 |
p_practice_* |
3. 字段映射(students → User)¶
| 旧字段 | 新字段 | 转换规则 |
|---|---|---|
_id |
(保留旧 ID 到新 ID 映射表) | 迁移脚本维护 oldId→newId map,供 logs 关联回填 |
name |
User.name |
直拷 |
classId |
User.classId |
经 classes 映射表转换 |
openid |
User.identifier |
platform=wechat,identifier=openid |
parentOpenid |
UserRelation(parent→student) |
生成 parent User(若不存在)+ UserRelation |
scores.{de,zhi,ti,mei,lao} |
历史快照 → TermReport 或首条 EvaluationRecord |
见 §5 |
total |
(不迁移,新系统重算) | 丢弃 |
stage/badgeCount/weekScore/monthScore/checkinStreak |
归档导出 | 不作为新系统主数据 |
4. 字段映射(classes/users/logs)¶
classes → Class
| 旧 | 新 | 规则 |
|---|---|---|
| name("望城一小·三(1)班") | Class.name + grade | 解析:grade=年级段(如"三(1)班"),name 全名 |
| schoolType | (映射到 School 或忽略) | 旧小学/中学 → 新单校 MVP 可忽略 |
| teacherOpenid | Class.classTeacherId | 经 teacher User 映射 |
| studentCount/totalScore | 冗余重建 | 迁移后重算 |
users → User
| 旧 | 新 | 规则 |
|---|---|---|
| _openid | User.identifier | platform=wechat |
| role | User.role | 映射:admin→schoolAdmin、其余直拷(student/parent/teacher) |
| classId/studentId | User.classId / UserRelation | 经映射表 |
| isApproved | User.isApproved | 直拷 |
logs → EvaluationRecord
| 旧 | 新 | 规则 |
|---|---|---|
| studentId | EvaluationRecord.studentId | 经学生映射表 |
| classId | EvaluationRecord.schoolId+(term 推导) | schoolId=迁移目标学校 |
| dimension(de/zhi/...) | dimension(moral/...) | 按 §2 映射 |
| delta | score + level | 规则:delta>0 累计 → score;level 由 score 区间映射(A≥90/B≥80/C≥70/D) |
| reason | comment | 直拷 |
| type(award/checkin/badge) | 附注到 comment 或新增 type 字段 | 建议保留类型标记 |
| teacherOpenid/teacherName | evaluatorId | 经教师映射表 |
| createdAt | evaluatedAt | 直拷(保留历史时间,不归一到今天) |
5. 迁移策略决策点(请 Claude 拍板 / Codex 执行)¶
方案 A:全量逐条迁移(推荐)
- 所有 logs 逐条 → EvaluationRecord,保留历史时间和教师
- 优点:历史可回溯、报告单有真实数据
- 代价:量大(估计几千~几万条),需分批导入;termId 需按 created_at 归类到学期
方案 B:快照迁移(轻量)
- 只迁移 students.scores 五维汇总为一条"历史快照"记录/或首期 TermReport
- 优点:快、稳;缺点:丢历史明细
建议:MVP 阶段用 方案 B 快照(学生主体 + 当前五维分数迁入,logs 导出归档);后续 M2 如需历史回溯再做 A。理由:新平台评价点体系(30 点)与旧日志(5 维加减分)颗粒度不一致,全量逐条映射语义会失真。
6. 迁移脚本骨架(Node 零依赖,供 Codex D3 填充)¶
server/scripts/migrate.js
1. 读取旧库导出 JSON(export/students.json、classes.json、users.json、logs.json)
2. 建立映射表:classOld→classNew、userOld→userNew、studentOld→userNew
3. 按顺序:School → Classes → Users(teacher/parent/admin) → Students → UserRelation → EvaluationRecord/快照
4. 输出:写入新库(或生成 SQL/Prisma seed)
5. 校验:迁移前后计数对比 + 抽查
- 旧库导出方式:云开发控制台导出集合 JSON(需董事长/Claude 在微信开发者工具操作,或 Codex 写云函数导出)
- 迁移目标:本地 MySQL(先本地验证)→ 生产云托管
7. 风险与注意事项¶
- ID 映射表:新旧 ID 必须全量映射,logs 关联才能回填正确
- 班级名解析:旧 name 格式多样("望城一小·三(1)班"),解析规则要覆盖所有变体
- openid 隐私:迁移文档/日志禁止明文打印 openid(合规:未成年人数据 + 家长授权字段 birthDate 需按 PRD 补)
- 时间保留:历史 createdAt/evaluatedAt 必须保留,不能覆盖为迁移日期
- 幂等:迁移脚本应支持断点续跑(按映射表跳过已迁)
- xb_* 云函数数据(宠物/商店/任务):不迁移(新平台无对应体系),导出归档即可
- schoolId:新库单租户,迁移时统一写入目标 schoolId
本文档为设计依据;Codex D3 实现细节可在此方案上调整,调整后回写本文件或在新文档标注。