"use client" import { getUserGroupTree } from "@/components/label/api/user" import { Organization } from "@/components/label/api/user/typing" import useAuth from "@/components/label/hooks/useAuth" import { useAllUserStore } from "@/components/label/store/auth" import { ActionIcon, Button, Group, Paper, ScrollArea, Stack, Text, TextInput, } from "@mantine/core" import { notifications } from "@mantine/notifications" import { IconPlus, IconRefresh, IconSearch, IconUserCircle, } from "@tabler/icons-react" import { useCallback, useEffect, useMemo, useState } from "react" import CreateModal from "./components/CreateModal" type NodeItem = { key: string name: string isUser?: boolean isManager?: boolean children: NodeItem[] } function toNodeTree(data: Organization.Response[]): NodeItem[] { return (data ?? []).map((item) => { const children: NodeItem[] = [] if (Array.isArray(item.children) && item.children.length > 0) { children.push(...toNodeTree(item.children)) } if (item.leader_uid && item.leader_name) { children.push({ key: `${item.group_uuid}/${item.leader_uid}`, name: item.leader_name, isUser: true, isManager: true, children: [], }) } if (Array.isArray(item.members) && item.members.length > 0) { item.members.forEach((member) => { if (member.id === item.leader_uid) return children.push({ key: `${item.group_uuid}/${member.id}`, name: member.name, isUser: true, children: [], }) }) } return { key: item.group_uuid, name: item.name, children, } }) } function filterTree(nodes: NodeItem[], keyword: string): NodeItem[] { if (!keyword.trim()) return nodes const lower = keyword.trim().toLowerCase() return nodes .map((node) => { const matched = node.name.toLowerCase().includes(lower) const children = filterTree(node.children, keyword) if (!matched && children.length === 0) return null return { ...node, children } }) .filter((n): n is NodeItem => !!n) } type FlatNode = NodeItem & { depth: number } function flattenTree(nodes: NodeItem[], depth = 0): FlatNode[] { const list: FlatNode[] = [] nodes.forEach((node) => { list.push({ ...node, depth }) if (node.children.length > 0) { list.push(...flattenTree(node.children, depth + 1)) } }) return list } function HighlightText(props: { text: string; keyword: string }) { const { text, keyword } = props if (!keyword.trim()) return <>{text} const index = text.toLowerCase().indexOf(keyword.trim().toLowerCase()) if (index < 0) return <>{text} const before = text.slice(0, index) const match = text.slice(index, index + keyword.length) const after = text.slice(index + keyword.length) return ( <> {before} {match} {after} ) } export default function TeamOrganizationPage() { const { isShow } = useAuth() const setFlag = useAllUserStore((s) => s.setFlag) const [open, setOpen] = useState(false) const [groupName, setGroupName] = useState("") const [data, setData] = useState([]) const [loading, setLoading] = useState(false) const load = useCallback(async () => { try { setLoading(true) const res = await getUserGroupTree() setData(toNodeTree(res ?? [])) } catch (e) { setData([]) notifications.show({ color: "red", title: "加载失败", message: e instanceof Error ? e.message : "请求失败", }) } finally { setLoading(false) } }, []) useEffect(() => { queueMicrotask(load) }, [load]) const rows = useMemo(() => { const filtered = filterTree(data, groupName) return flattenTree(filtered) }, [data, groupName]) return ( } value={groupName} onChange={(e) => setGroupName(e.currentTarget.value)} style={{ minWidth: 360 }} /> {isShow("group_add") ? ( ) : null} {rows.map((node) => { return ( {node.isUser ? : null} {!node.isUser && node.children.length > 0 ? `(${node.children.length})` : ""} {node.isManager ? ( 负责人 ) : null} ) })} {rows.length === 0 ? ( 暂无匹配数据 ) : null} { setOpen(false) if (refresh) { setFlag(true) load() } }} /> ) }