From fb8c897b4fd92b68db83a5bed0babd7b55a75d2d Mon Sep 17 00:00:00 2001 From: wangziqi Date: Thu, 9 Jul 2026 11:32:01 +0800 Subject: [PATCH] fix: disable import button when roles not loaded (null defaultTeacherRoleId guard) --- .../src/pages/IntegrationConfig/index.tsx | 401 +++++++++++++++--- 1 file changed, 346 insertions(+), 55 deletions(-) diff --git a/apps/admin/src/pages/IntegrationConfig/index.tsx b/apps/admin/src/pages/IntegrationConfig/index.tsx index 9c530f7..ea8b562 100644 --- a/apps/admin/src/pages/IntegrationConfig/index.tsx +++ b/apps/admin/src/pages/IntegrationConfig/index.tsx @@ -1,10 +1,13 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useState, useMemo } from 'react'; import { Card, Form, Input, Button, Space, message, Spin, Switch, Alert, Descriptions, Tag, + Tabs, Drawer, Tree, Checkbox, Select, TreeSelect, } from 'antd'; import { SaveOutlined, ApiOutlined, CheckCircleOutlined, CloseCircleOutlined, + SyncOutlined, ReloadOutlined, } from '@ant-design/icons'; +import type { DataNode } from 'antd/es/tree'; import api from '../../api'; interface DingTalkConfig { @@ -14,11 +17,68 @@ interface DingTalkConfig { startEnable: boolean; } -/** Utility: recursively flatten org tree nodes to extract user ids (for import guard) */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const getAllUsers = (nodes: any[]): Array<{ userid: string }> => { - return nodes.flatMap((n) => [...(n.users ?? []), ...getAllUsers(n.children ?? [])]); -}; +interface DingOrgTreeNodeExt { + id: number; + name: string; + parentId: number; + children: DingOrgTreeNodeExt[]; + users: Array<{ userid: string; name: string; mobile: string }>; +} + +interface RoleItem { + id: number; + name: string; + status: number; +} + +interface OrgTreeNodeRaw { + id: number; + name: string; + children?: OrgTreeNodeRaw[]; +} + +interface OrgTreeResponse { + success: boolean; + data: OrgTreeNodeRaw[]; +} + +interface OrgTreeWithUsersResponse { + success: boolean; + data: DingOrgTreeNodeExt[]; +} + +interface ImportUsersResponse { + teacherCount: number; + studentCount: number; + skipped: number; +} + +const UserTreeNode: React.FC<{ + u: { userid: string; name: string; mobile: string }; + isTeacher: boolean; + onToggle: () => void; + roleId: number | undefined; + defaultRoleId: number | null; + roles: Array<{ id: number; name: string }>; + onRoleChange: (roleId: number) => void; +}> = React.memo(({ u, isTeacher, onToggle, roleId, defaultRoleId, roles, onRoleChange }) => ( + + 老师 + {u.name} + {u.mobile && {u.mobile}} + {isTeacher && ( + + + + + + + + + + + + + + + + + + ), + }, + ...syncTabItems, + ]; + return ( @@ -90,54 +428,7 @@ const IntegrationConfigPage: React.FC = () => { {verified === false && } color="error">未连接} }> - - {config && ( - - {config.corpId || '-'} - {config.agentId || '-'} - - - {config.startEnable ? '已启用' : '未启用'} - - - - )} - - - -
- - - - - - - - - - - - - - - - -
-
+ ); };