perf: usages list;perf: move components (#3654)

* perf: usages list

* team sub plan load

* perf: usage dashboard code

* perf: dashboard ui

* perf: move components
This commit is contained in:
Archer
2025-01-23 17:29:39 +08:00
committed by archer
parent e4b85ffada
commit 5a04d015f9
271 changed files with 9981 additions and 4025 deletions

View File

@@ -0,0 +1,159 @@
import {
Box,
Button,
Flex,
Table,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr
} from '@chakra-ui/react';
import { formatNumber } from '@fastgpt/global/common/math/tools';
import { UsageSourceMap } from '@fastgpt/global/support/wallet/usage/constants';
import { UsageItemType } from '@fastgpt/global/support/wallet/usage/type';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import MyBox from '@fastgpt/web/components/common/MyBox';
import dayjs from 'dayjs';
import { useTranslation } from 'next-i18next';
import React, { useMemo, useState } from 'react';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { usePagination } from '@fastgpt/web/hooks/usePagination';
import { getUserUsages } from '@/web/support/wallet/usage/api';
import { addDays } from 'date-fns';
import dynamic from 'next/dynamic';
import { UsageFilterParams } from './type';
import PopoverConfirm from '@fastgpt/web/components/common/MyPopover/PopoverConfirm';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { downloadFetch } from '@/web/common/system/utils';
const UsageDetail = dynamic(() => import('./UsageDetail'));
const UsageTableList = ({
filterParams,
Tabs,
Selectors
}: {
Tabs: React.ReactNode;
Selectors: React.ReactNode;
filterParams: UsageFilterParams;
}) => {
const { t } = useTranslation();
const { dateRange, selectTmbIds, isSelectAllTmb, usageSources, isSelectAllSource, projectName } =
filterParams;
const requestParans = useMemo(
() => ({
dateStart: dateRange.from || new Date(),
dateEnd: addDays(dateRange.to || new Date(), 1),
sources: isSelectAllSource ? undefined : usageSources,
teamMemberIds: isSelectAllTmb ? undefined : selectTmbIds,
projectName
}),
[
dateRange.from,
dateRange.to,
isSelectAllSource,
isSelectAllTmb,
projectName,
selectTmbIds,
usageSources
]
);
const {
data: usages,
isLoading,
Pagination,
total
} = usePagination(getUserUsages, {
pageSize: 20,
params: requestParans,
refreshDeps: [requestParans]
});
const [usageDetail, setUsageDetail] = useState<UsageItemType>();
const { runAsync: exportUsage } = useRequest2(
async () => {
await downloadFetch({
url: `/api/proApi/support/wallet/usage/exportUsage`,
filename: `usage.csv`,
body: requestParans
});
},
{
refreshDeps: [requestParans]
}
);
return (
<>
<Box>{Tabs}</Box>
<Flex mt={4} w={'100%'}>
<Box>{Selectors}</Box>
<Box flex={'1'} />
<PopoverConfirm
Trigger={<Button size={'md'}>{t('common:Export')}</Button>}
showCancel
content={t('account_usage:export_confirm_tip', { total })}
onConfirm={exportUsage}
/>
</Flex>
<MyBox position={'relative'} overflowY={'auto'} mt={3} flex={1} isLoading={isLoading}>
<TableContainer>
<Table>
<Thead>
<Tr>
<Th>{t('common:user.Time')}</Th>
<Th>{t('account_usage:member')}</Th>
<Th>{t('account_usage:user_type')}</Th>
<Th>{t('account_usage:project_name')}</Th>
<Th>{t('account_usage:total_points')}</Th>
<Th></Th>
</Tr>
</Thead>
<Tbody fontSize={'sm'}>
{usages.map((item) => (
<Tr key={item.id}>
<Td>{dayjs(item.time).format('YYYY/MM/DD HH:mm:ss')}</Td>
<Td>
<Flex alignItems={'center'} color={'myGray.500'}>
<Avatar src={item.sourceMember.avatar} w={'20px'} mr={1} rounded={'full'} />
{item.sourceMember.name}
</Flex>
</Td>
<Td>{t(UsageSourceMap[item.source]?.label as any) || '-'}</Td>
<Td>{t(item.appName as any) || '-'}</Td>
<Td>{formatNumber(item.totalPoints) || 0}</Td>
<Td>
<Button
size={'sm'}
variant={'whitePrimary'}
onClick={() => setUsageDetail(item)}
>
{t('account_usage:details')}
</Button>
</Td>
</Tr>
))}
</Tbody>
</Table>
{!isLoading && usages.length === 0 && (
<EmptyTip text={t('account_usage:no_usage_records')}></EmptyTip>
)}
</TableContainer>
</MyBox>
<Flex mt={3} justifyContent={'center'}>
<Pagination />
</Flex>
{!!usageDetail && (
<UsageDetail usage={usageDetail} onClose={() => setUsageDetail(undefined)} />
)}
</>
);
};
export default React.memo(UsageTableList);