forked from wangziqi/gongxue-base
feat(sync): add ImportClassItemDto and expose deptIds in org-tree-with-users
This commit is contained in:
@@ -78,7 +78,12 @@ export interface DingOrgTreeNodeWithUsers {
|
||||
name: string;
|
||||
parentId: number;
|
||||
children: DingOrgTreeNodeWithUsers[];
|
||||
users: Array<{ userid: string; name: string; mobile: string }>;
|
||||
users: Array<{
|
||||
userid: string;
|
||||
name: string;
|
||||
mobile: string;
|
||||
deptIds: number[];
|
||||
}>;
|
||||
}
|
||||
|
||||
// ── 考勤排班 API 类型 ──
|
||||
@@ -477,6 +482,9 @@ export class DingTalkService {
|
||||
|
||||
// 拉每个部门详情
|
||||
const nodes: DingOrgTreeNodeWithUsers[] = [];
|
||||
// Before dedup: collect deptIds per user
|
||||
const userDeptMap = new Map<string, number[]>();
|
||||
|
||||
for (let i = 0; i < deptIds.length; i++) {
|
||||
if (i > 0) await this.delay(i);
|
||||
const detail = await this.getDeptDetail(token, deptIds[i]);
|
||||
@@ -494,18 +502,32 @@ export class DingTalkService {
|
||||
userid: u.userid,
|
||||
name: u.name,
|
||||
mobile: u.mobile,
|
||||
deptIds: [],
|
||||
})),
|
||||
});
|
||||
|
||||
// Record which departments each user belongs to
|
||||
for (const u of dingUsers) {
|
||||
if (!userDeptMap.has(u.userid)) {
|
||||
userDeptMap.set(u.userid, []);
|
||||
}
|
||||
userDeptMap.get(u.userid)!.push(detail.dept_id);
|
||||
}
|
||||
}
|
||||
|
||||
// 全局去重:同一个 dingUserId 可能在多个部门出现
|
||||
const seenUserIds = new Set<string>();
|
||||
for (const node of nodes) {
|
||||
node.users = node.users.filter((u) => {
|
||||
if (seenUserIds.has(u.userid)) return false;
|
||||
seenUserIds.add(u.userid);
|
||||
return true;
|
||||
});
|
||||
node.users = node.users
|
||||
.filter((u) => {
|
||||
if (seenUserIds.has(u.userid)) return false;
|
||||
seenUserIds.add(u.userid);
|
||||
return true;
|
||||
})
|
||||
.map((u) => ({
|
||||
...u,
|
||||
deptIds: userDeptMap.get(u.userid) || [],
|
||||
}));
|
||||
}
|
||||
|
||||
// 组装成树
|
||||
|
||||
@@ -20,9 +20,49 @@ export class ImportUserItemDto {
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
roleId: number | null;
|
||||
|
||||
@IsArray()
|
||||
@IsNumber({}, { each: true })
|
||||
dingDeptIds: number[];
|
||||
}
|
||||
|
||||
export class ImportClassItemDto {
|
||||
@IsNumber()
|
||||
deptId: number;
|
||||
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@IsString()
|
||||
code: string;
|
||||
|
||||
@IsString()
|
||||
classType: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
startDate?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
endDate?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
maxStudents?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export class ImportUsersDto {
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => ImportClassItemDto)
|
||||
classes?: ImportClassItemDto[];
|
||||
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => ImportUserItemDto)
|
||||
|
||||
Reference in New Issue
Block a user