perf: Team org ui (#3499)

* perf: org ui

* perf: org ui
This commit is contained in:
Archer
2024-12-30 20:49:11 +08:00
committed by archer
parent 1fc77a126a
commit efecfd44c3
21 changed files with 505 additions and 563 deletions

View File

@@ -1,114 +1,101 @@
import { Box, HStack, Text, VStack } from '@chakra-ui/react';
import { Box, HStack, 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 { useToggle } from 'ahooks';
import { useMemo, useState } from 'react';
import { useMemo } from 'react';
import IconButton from './IconButton';
function OrgTreeNode({
org,
list,
selectedOrg,
selectOrg,
indent = 0
setSelectedOrg,
index = 0
}: {
org: OrgType;
list: OrgType[];
selectedOrg?: OrgType;
selectOrg?: (org?: OrgType) => void;
indent?: number;
setSelectedOrg: (org?: OrgType) => void;
index?: number;
}) {
const children = useMemo(
() => list.filter((item) => item.path === `${org.path}/${org._id}`),
[org, list]
);
const [isExpanded, toggleIsExpanded] = useToggle(false);
const [isExpanded, toggleIsExpanded] = useToggle(index === 0);
return (
<VStack alignItems={'start'} w="full" gap={'8px'}>
<Box userSelect={'none'}>
<HStack
w="full"
_hover={{ bgColor: selectedOrg === org ? 'blue.200' : 'gray.100' }}
borderRadius="4px"
boxSizing="border-box"
py="4px"
pl={`calc(${indent}rem + 4px)`}
transition={'background 0.1s'}
{...(selectedOrg === org ? { bgColor: 'blue.100' } : {})}
borderRadius="sm"
_hover={{ bg: 'myGray.100' }}
py={1}
pr={2}
pl={index === 0 ? '0.5rem' : `${1.75 * (index - 1) + 0.5}rem`}
cursor={'pointer'}
{...(selectedOrg === org
? {
bg: 'primary.50 !important',
onClick: () => setSelectedOrg(undefined)
}
: {
onClick: () => setSelectedOrg(org)
})}
>
{children.length > 0 ? (
{index > 0 && (
<IconButton
name={isExpanded ? 'common/downArrowFill' : 'common/rightArrowFill'}
onClick={() => toggleIsExpanded.toggle()}
color={'myGray.500'}
p={0}
w={'1.25rem'}
visibility={children.length > 0 ? 'visible' : 'hidden'}
onClick={(e) => {
e.stopPropagation();
toggleIsExpanded.toggle();
}}
/>
) : (
<Box w={'1rem'} h={'1rem'} m="1" />
)}
<HStack onClick={() => selectOrg?.(org)} cursor="pointer">
<Avatar src={org.avatar} w="20px" h="20px" rounded={'50%'} />
<Text>{org.name}</Text>
<HStack
flex={'1 0 0'}
onClick={() => setSelectedOrg(org)}
cursor={'pointer'}
borderRadius={'xs'}
>
<Avatar src={org.avatar} w={'1.25rem'} borderRadius={'xs'} />
<Box>{org.name}</Box>
</HStack>
</HStack>
{isExpanded &&
children.length > 0 &&
children.map((child) => (
<OrgTreeNode
key={child._id}
org={child}
indent={indent + 1}
list={list}
selectedOrg={selectedOrg}
selectOrg={selectOrg}
/>
<Box key={child._id} mt={0.5}>
<OrgTreeNode
org={child}
index={index + 1}
list={list}
selectedOrg={selectedOrg}
setSelectedOrg={setSelectedOrg}
/>
</Box>
))}
</VStack>
</Box>
);
}
function OrgTree({
orgs,
teamName,
teamAvatar,
selectedOrg,
selectOrg
setSelectedOrg
}: {
orgs: OrgType[];
teamAvatar: string;
teamName: string;
selectedOrg?: OrgType;
selectOrg?: (org?: OrgType) => void;
setSelectedOrg: (org?: OrgType) => void;
}) {
const root = orgs[0];
if (!root) return null;
const children = useMemo(
() => orgs.filter((item) => item.path === `${root.path}/${root._id}`),
[root, orgs]
);
if (!root) return;
return (
<VStack alignItems={'start'} gap={'8px'}>
<HStack
w="full"
onClick={() => selectOrg?.(root)}
cursor="pointer"
_hover={{ bgColor: selectedOrg === root ? 'blue.200' : 'gray.100' }}
borderRadius="4px"
p="4px"
transition={'background 0.1s'}
{...(selectedOrg === root ? { bgColor: 'blue.100' } : {})}
>
<Avatar src={teamAvatar} w="20px" h="20px" rounded={'50%'} />
<Text>{teamName}</Text>
</HStack>
{children.map((child) => (
<OrgTreeNode
key={child._id}
org={child}
list={orgs}
selectOrg={selectOrg}
selectedOrg={selectedOrg}
/>
))}
</VStack>
<OrgTreeNode org={root} list={orgs} setSelectedOrg={setSelectedOrg} selectedOrg={selectedOrg} />
);
}