diff --git a/docs/superpowers/specs/2026-07-09-student-ding-mapping-design.md b/docs/superpowers/specs/2026-07-09-student-ding-mapping-design.md new file mode 100644 index 0000000..d18fb07 --- /dev/null +++ b/docs/superpowers/specs/2026-07-09-student-ding-mapping-design.md @@ -0,0 +1,56 @@ +# 组织同步重构:Student 独立实体 + Drawer 批量操作 + +**日期**:2026-07-09 +**范围**:数据模型、同步、导入、前端 Drawer + +## 背景 + +Student 是独立业务实体,不参与 RBAC,不与 User 挂钩。当前同步链路 `dingUserId → User → Student.userId` 应改为 `dingUserId → Student`。 + +## 需求 + +### 数据模型 + +- **新增** `StudentDingMapping`:`ding_user_id`(UNIQUE) + `student_id`(UNIQUE) + `created_at` +- **废弃** `UserDingMapping`:删 entity、删所有引用、删表 + +### 同步 (`syncAll`) + +不再创建 User,直接创建 Student + StudentDingMapping。同步进来的全是学生。 + +### 组织树 (`fetchOrgTreeWithUsers`) + +恢复全量返回,去掉最深两层过滤,去掉 `getDeptDepthMap`。 + +### 批量导入 (`POST /classes/:id/students/import`) + +接收 `{ dingUserIds: string[] }`,逐个:无则创建 Student + StudentDingMapping,有则跳过 → 创建 ClassStudent。 + +### 班级创建 + +`POST /classes` 扩展可选 `dingUserIds`,创建班级后自动导入。 + +### 前端 Drawer(IntegrationConfig 同步用户 tab) + +左右分栏: +- **左栏**:Ant Design ``,完整钉钉组织树,部门+用户均可勾选,级联 +- **右栏**:已有班级列表(名称+班型),选中高亮 + "创建班级"按钮 +- **底部**:"加入选中的班级" / "创建班级" + +两个操作: +| 操作 | 前提 | 动作 | +|---|---|---| +| 加入班级 | 勾选用户 + 选中班级 | POST /classes/:id/students/import | +| 创建班级 | 勾选用户 + 勾选部门 | 弹出班级表单 → POST /classes + 关联学生 | + +### 删除 + +- 逐用户 teacher/student toggle +- "标记为班级" modal +- 最深两层过滤 + +## 不受影响 + +- `fetchOrgTree`(dept picker) +- 考勤导入(`DingAttendanceRaw.dingUserId` → `StudentDingMapping`) +- 排班同步(教师逻辑后续处理,本轮不碰)