Files
gongxue-base/docs/superpowers/specs/2026-07-10-fix-student-import-name-design.md

2.8 KiB
Raw Blame History

修复学生导入:姓名与账号字段 — 设计文档

日期2026-07-10
状态:已确认
关联PRD 钉钉集成批次 2


1. 背景

batchImportStudents 创建 Student 时:

  • name 填的是占位符 dd_${dingUserId}
  • phone 未设置

正确行为:

  • name = 钉钉用户真实姓名
  • phone = 钉钉用户手机号;无手机号时填 dt_${dingUserId}

2. 方案:前端传用户信息

前端组织架构树已有 { userid, name, mobile } 数据(来自 getDeptUsers),导入时直接传给后端,零额外钉钉 API 调用。

3. 改动清单

3.1 后端 DTO

文件: apps/server/src/classes/dto/class.dto.ts

BatchImportStudentsDto:

// 旧
export class BatchImportStudentsDto {
  dingUserIds: string[];
}

// 新
export class BatchImportStudentsDto {
  @IsArray() @ArrayNotEmpty()
  users: Array<{ dingUserId: string; name: string; mobile?: string }>;
}

CreateClassDto.dingUserIds 同改为 users 字段。

3.2 后端 Service

文件: apps/server/src/classes/classes.service.ts

batchImportStudents 签名改为:

async batchImportStudents(classId: number, users: Array<{
  dingUserId: string; name: string; mobile?: string;
}>): Promise<{ imported: number; skipped: number }>

创建 Student 时:

this.studentRepo.create({
  name: u.name,
  phone: u.mobile || `dt_${u.dingUserId}`,
  status: 'active',
})

create() 方法中 dingUserIdsusers 透传。

3.3 后端 Controller

文件: apps/server/src/classes/classes.controller.ts

batchImportStudents 端点传参改为:

return this.service.batchImportStudents(+id, dto.users);

3.4 前端

文件: apps/admin/src/pages/IntegrationConfig/index.tsx

handleJoinClasshandleCreateClass:从 checkedKeys 反查 orgTree 提取完整用户信息,不再只传 ID。

// 旧
const userIds = checkedKeys.filter(...).map(k => k.replace('user-', ''));
api.post('/classes/.../import', { dingUserIds: userIds });

// 新
const checkedUsers = extractCheckedUsers(checkedKeys, orgTree);
api.post('/classes/.../import', { users: checkedUsers });

extractCheckedUsers 工具函数遍历 orgTree,匹配 checkedKeys 中的 user 节点,返回 { dingUserId, name, mobile }[]

4. 不改的

  • DingTalkService.syncOneUser / syncAll — 不受影响
  • Student entity — 字段不变
  • 数据库 schema — 不变
  • StudentDingMapping — 不受影响

5. 验收标准

  1. 导入新用户后Student.name 为真实姓名,非 dd_xxx
  2. 有手机号的用户Student.phone = 手机号
  3. 无手机号的用户Student.phone = dt_<dingUserId>
  4. 已存在 mapping 的用户跳过,不重复创建
  5. 班级创建时传入 users 同样生效
  6. tsc --noEmit 编译通过