feat: add fetchOrgTreeWithUsers to DingTalkService
This commit is contained in:
@@ -72,6 +72,15 @@ export interface DingOrgTreeNode {
|
||||
children: DingOrgTreeNode[];
|
||||
}
|
||||
|
||||
/** 钉钉部门树节点(含用户),供同步用户选择器使用 */
|
||||
export interface DingOrgTreeNodeWithUsers {
|
||||
id: number;
|
||||
name: string;
|
||||
parentId: number;
|
||||
children: DingOrgTreeNodeWithUsers[];
|
||||
users: Array<{ userid: string; name: string; mobile: string }>;
|
||||
}
|
||||
|
||||
// ── 考勤排班 API 类型 ──
|
||||
|
||||
/** 班次卡段打卡时间 */
|
||||
@@ -455,6 +464,65 @@ export class DingTalkService {
|
||||
return roots;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取钉钉组织部门树(含用户),供前端同步用户选择器使用。
|
||||
* 返回从指定 rootDeptId 开始的树,每个部门节点含 users 数组。
|
||||
*/
|
||||
async fetchOrgTreeWithUsers(rootDeptId = 1): Promise<DingOrgTreeNodeWithUsers[]> {
|
||||
if (!this.configured) {
|
||||
throw new ServiceUnavailableException('钉钉未配置');
|
||||
}
|
||||
const token = await this.getAccessToken();
|
||||
const deptIds = await this.getAllDeptIds(token, rootDeptId);
|
||||
|
||||
// 拉每个部门详情
|
||||
const nodes: DingOrgTreeNodeWithUsers[] = [];
|
||||
for (let i = 0; i < deptIds.length; i++) {
|
||||
if (i > 0) await this.delay(i);
|
||||
const detail = await this.getDeptDetail(token, deptIds[i]);
|
||||
if (!detail) continue;
|
||||
|
||||
// 拉该部门下的用户
|
||||
const dingUsers = await this.getDeptUsers(token, deptIds[i]);
|
||||
|
||||
nodes.push({
|
||||
id: detail.dept_id,
|
||||
name: detail.name,
|
||||
parentId: detail.parent_id,
|
||||
children: [],
|
||||
users: dingUsers.map((u) => ({
|
||||
userid: u.userid,
|
||||
name: u.name,
|
||||
mobile: u.mobile,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
// 全局去重:同一个 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;
|
||||
});
|
||||
}
|
||||
|
||||
// 组装成树
|
||||
const map = new Map<number, DingOrgTreeNodeWithUsers>();
|
||||
nodes.forEach((n) => map.set(n.id, n));
|
||||
const roots: DingOrgTreeNodeWithUsers[] = [];
|
||||
for (const node of nodes) {
|
||||
const parent = map.get(node.parentId);
|
||||
if (parent && node.id !== rootDeptId) {
|
||||
parent.children.push(node);
|
||||
} else {
|
||||
roots.push(node);
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// Sync one user (with mapping)
|
||||
// ═══════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user