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

113 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 修复学生导入:姓名与账号字段 — 设计文档
> 日期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`:
```typescript
// 旧
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` 签名改为:
```typescript
async batchImportStudents(classId: number, users: Array<{
dingUserId: string; name: string; mobile?: string;
}>): Promise<{ imported: number; skipped: number }>
```
创建 Student 时:
```typescript
this.studentRepo.create({
name: u.name,
phone: u.mobile || `dt_${u.dingUserId}`,
status: 'active',
})
```
`create()` 方法中 `dingUserIds``users` 透传。
### 3.3 后端 Controller
**文件:** `apps/server/src/classes/classes.controller.ts`
`batchImportStudents` 端点传参改为:
```typescript
return this.service.batchImportStudents(+id, dto.users);
```
### 3.4 前端
**文件:** `apps/admin/src/pages/IntegrationConfig/index.tsx`
`handleJoinClass``handleCreateClass`:从 `checkedKeys` 反查 `orgTree` 提取完整用户信息,不再只传 ID。
```typescript
// 旧
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` 编译通过