import { useUserStore } from '@/web/support/user/useUserStore'; import { Box, Divider, Flex, HStack, Table, TableContainer, Tag, Tbody, Td, Th, Thead, Tr, VStack } from '@chakra-ui/react'; import type { OrgType } from '@fastgpt/global/support/user/team/org/type'; import Avatar from '@fastgpt/web/components/common/Avatar'; import MyIcon from '@fastgpt/web/components/common/Icon'; import type { IconNameType } from '@fastgpt/web/components/common/Icon/type'; import MyMenu from '@fastgpt/web/components/common/MyMenu'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useTranslation } from 'next-i18next'; import { useMemo, useState } from 'react'; import { useContextSelector } from 'use-context-selector'; import MemberTag from '@/components/support/user/team/Info/MemberTag'; import { TeamContext } from '../context'; import { deleteOrg, deleteOrgMember, getOrgList } from '@/web/support/user/team/org/api'; import IconButton from './IconButton'; import { defaultOrgForm, type OrgFormType } from './OrgInfoModal'; import dynamic from 'next/dynamic'; import MyBox from '@fastgpt/web/components/common/MyBox'; import Path from '@/components/common/folder/Path'; import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type'; import { getOrgChildrenPath } from '@fastgpt/global/support/user/team/org/constant'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { delRemoveMember } from '@/web/support/user/team/api'; import SearchInput from '@fastgpt/web/components/common/Input/SearchInput'; const OrgInfoModal = dynamic(() => import('./OrgInfoModal')); const OrgMemberManageModal = dynamic(() => import('./OrgMemberManageModal')); const OrgMoveModal = dynamic(() => import('./OrgMoveModal')); function ActionButton({ icon, text, onClick }: { icon: IconNameType; text: string; onClick: () => void; }) { return ( {text} ); } function OrgTable({ Tabs }: { Tabs: React.ReactNode }) { const { t } = useTranslation(); const { userInfo, isTeamAdmin } = useUserStore(); const [searchOrg, setSearchOrg] = useState(''); const { members, MemberScrollData, refetchMembers } = useContextSelector(TeamContext, (v) => v); const { feConfigs } = useSystemStore(); const isSyncMember = feConfigs.register_method?.includes('sync'); const [parentPath, setParentPath] = useState(''); const { data: orgs = [], loading: isLoadingOrgs, refresh: refetchOrgs } = useRequest2(getOrgList, { manual: false, refreshDeps: [userInfo?.team?.teamId] }); const currentOrgs = useMemo(() => { if (orgs.length === 0) return []; if (parentPath === '') { const rootOrg = orgs.find((org) => org.path === ''); if (rootOrg) { setParentPath(getOrgChildrenPath(rootOrg)); } return []; } return orgs .filter((org) => org.path === parentPath) .map((item) => { return { ...item, // Member + org count: item.members.length + orgs.filter((org) => org.path === getOrgChildrenPath(item)).length }; }); }, [orgs, parentPath]); const currentOrg = useMemo(() => { const splitPath = parentPath.split('/'); const currentOrgId = splitPath[splitPath.length - 1]; if (!currentOrgId) return; return orgs.find((org) => org.pathId === currentOrgId); }, [orgs, parentPath]); const paths = useMemo(() => { const splitPath = parentPath.split('/').filter(Boolean); return splitPath .map((id) => { const org = orgs.find((org) => org.pathId === id)!; if (org?.path === '') return; return { parentId: getOrgChildrenPath(org), parentName: org.name }; }) .filter(Boolean) as ParentTreePathItemType[]; }, [parentPath, orgs]); const [editOrg, setEditOrg] = useState(); const [manageMemberOrg, setManageMemberOrg] = useState(); const [movingOrg, setMovingOrg] = useState(); // Delete org const { ConfirmModal: ConfirmDeleteOrgModal, openConfirm: openDeleteOrgModal } = useConfirm({ type: 'delete', content: t('account_team:confirm_delete_org') }); const deleteOrgHandler = (orgId: string) => openDeleteOrgModal(() => deleteOrgReq(orgId))(); const { runAsync: deleteOrgReq } = useRequest2(deleteOrg, { onSuccess: () => { refetchOrgs(); } }); // Delete member const { ConfirmModal: ConfirmDeleteMemberFromOrg, openConfirm: openDeleteMemberFromOrgModal } = useConfirm({ type: 'delete' }); const { ConfirmModal: ConfirmDeleteMemberFromTeam, openConfirm: openDeleteMemberFromTeamModal } = useConfirm({ type: 'delete' }); const { runAsync: deleteMemberReq } = useRequest2(deleteOrgMember, { onSuccess: () => { refetchOrgs(); } }); const { runAsync: deleteMemberFromTeamReq } = useRequest2(delRemoveMember, { onSuccess: () => { refetchOrgs(); refetchMembers(); } }); const searchedOrgs = useMemo(() => { if (!searchOrg) return []; return orgs .filter((org) => org.name.includes(searchOrg)) .map((org) => ({ ...org, count: org.members.length + orgs.filter((org) => org.path === getOrgChildrenPath(org)).length })); }, [orgs, searchOrg]); return ( <> {Tabs} setSearchOrg(e.target.value)} /> {/* Table */} {searchedOrgs.map((org) => ( setParentPath(getOrgChildrenPath(org))} > ))} {!searchOrg && currentOrgs.map((org) => ( {isTeamAdmin && !isSyncMember && ( )} ))} {!searchOrg && currentOrg?.members.map((member) => { const memberInfo = members.find((m) => m.tmbId === member.tmbId); if (!memberInfo) return null; return ( ); })}
{t('common:Name')} {t('common:common.Action')}
{ setParentPath(getOrgChildrenPath(org)); setSearchOrg(''); }} > {org.count}
{ setParentPath(getOrgChildrenPath(org)); setSearchOrg(''); }} > {org.count} } menuList={[ { children: [ { icon: 'edit', label: t('account_team:edit_info'), onClick: () => setEditOrg(org) }, { icon: 'common/file/move', label: t('common:Move'), onClick: () => setMovingOrg(org) }, { icon: 'delete', label: t('account_team:delete'), type: 'danger', onClick: () => deleteOrgHandler(org._id) } ] } ]} />
{isTeamAdmin && ( } menuList={[ { children: [ { menuItemStyles: { _hover: { color: 'red.600', backgroundColor: 'red.50' } }, label: t('account_team:delete_from_team', { username: memberInfo.memberName }), onClick: () => { openDeleteMemberFromTeamModal( () => deleteMemberFromTeamReq(member.tmbId), undefined, t('account_team:confirm_delete_from_team', { username: memberInfo.memberName }) )(); } }, ...(isSyncMember ? [] : [ { menuItemStyles: { _hover: { color: 'red.600', bgColor: 'red.50' } }, label: t('account_team:delete_from_org'), onClick: () => openDeleteMemberFromOrgModal( () => deleteMemberReq(currentOrg._id, member.tmbId), undefined, t('account_team:confirm_delete_from_org', { username: memberInfo.memberName }) )() } ]) ] } ]} /> )}
{/* Slider */} {!isSyncMember && ( {currentOrg?.name} {currentOrg?.path !== '' && ( setEditOrg(currentOrg)} /> )} {currentOrg?.description || t('common:common.no_intro')} {t('common:common.Action')} {currentOrg && isTeamAdmin && ( { setEditOrg({ ...defaultOrgForm, parentId: currentOrg?._id }); }} /> setManageMemberOrg(currentOrg)} /> {currentOrg?.path !== '' && ( <> setMovingOrg(currentOrg)} /> deleteOrgHandler(currentOrg._id)} /> )} )} )}
{!!editOrg && ( setEditOrg(undefined)} onSuccess={refetchOrgs} /> )} {!!movingOrg && ( setMovingOrg(undefined)} onSuccess={refetchOrgs} /> )} {!!manageMemberOrg && ( setManageMemberOrg(undefined)} /> )} ); } export default OrgTable;