perf: page ui (#5469)

* perf: page ui

* fix: icon

* limit chat items

* limit chat items
This commit is contained in:
Archer
2025-08-15 17:56:49 +08:00
committed by GitHub
parent 76dc23c2e4
commit ce36230285
36 changed files with 619 additions and 322 deletions
@@ -60,9 +60,10 @@ const BillTable = () => {
isLoading,
Pagination,
getData,
total
total,
pageSize
} = usePagination(getBills, {
pageSize: 20,
defaultPageSize: 20,
params: {
type: billType
},
@@ -95,8 +96,8 @@ const BillTable = () => {
}, [billType]);
return (
<MyBox isLoading={isLoading} position={'relative'} h={'100%'} minH={'50vh'}>
<TableContainer>
<MyBox isLoading={isLoading} display={'flex'} flexDir={'column'} h={'100%'}>
<TableContainer flex={'1 0 0'} h={0} overflowY={'auto'}>
<Table>
<Thead>
<Tr>
@@ -147,11 +148,6 @@ const BillTable = () => {
))}
</Tbody>
</Table>
{total >= 20 && (
<Flex mt={3} justifyContent={'flex-end'}>
<Pagination />
</Flex>
)}
{!isLoading && bills.length === 0 && (
<Flex
mt={'20vh'}
@@ -167,6 +163,11 @@ const BillTable = () => {
)}
</TableContainer>
{total >= pageSize && (
<Flex mt={3} justifyContent={'center'}>
<Pagination />
</Flex>
)}
{!!billDetail && (
<BillDetailModal bill={billDetail} onClose={() => setBillDetail(undefined)} />
)}
@@ -32,14 +32,15 @@ const InvoiceTable = () => {
data: invoices,
isLoading,
Pagination,
total
total,
pageSize
} = usePagination(getInvoiceRecords, {
pageSize: 20
defaultPageSize: 10
});
return (
<MyBox isLoading={isLoading} position={'relative'} h={'100%'} overflow={'overlay'}>
<TableContainer minH={'50vh'}>
<MyBox isLoading={isLoading} position={'relative'} minH={'50vh'} overflow={'overlay'}>
<TableContainer>
<Table>
<Thead h="3rem">
<Tr>
@@ -101,11 +102,6 @@ const InvoiceTable = () => {
))}
</Tbody>
</Table>
{total >= 20 && (
<Flex mt={3} justifyContent={'flex-end'}>
<Pagination />
</Flex>
)}
{!isLoading && invoices.length === 0 && (
<Flex
mt={'20vh'}
@@ -120,6 +116,11 @@ const InvoiceTable = () => {
</Flex>
)}
</TableContainer>
{total >= pageSize && (
<Flex mt={3} justifyContent={'center'}>
<Pagination />
</Flex>
)}
{!!invoiceDetailData && (
<InvoiceDetailModal invoice={invoiceDetailData} onClose={() => setInvoiceDetailData('')} />
)}
@@ -68,7 +68,7 @@ const UsageTableList = ({
Pagination,
total
} = usePagination(getUserUsages, {
pageSize: 20,
defaultPageSize: 20,
params: requestParams,
refreshDeps: [requestParams]
});
@@ -111,7 +111,7 @@ const UsageTableList = ({
);
return (
<>
<MyBox display={'flex'} flexDirection={'column'} h={'100%'} isLoading={isLoading}>
<Box>{Tabs}</Box>
<Flex mt={4} w={'100%'}>
<Box>{Selectors}</Box>
@@ -123,54 +123,46 @@ const UsageTableList = ({
onConfirm={exportUsage}
/>
</Flex>
<MyBox mt={3} flex={'1 0 0'} h={0} isLoading={isLoading}>
<Box h={'100%'} overflow={'auto'}>
<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 className="textEllipsis" maxW={'400px'} title={t(item.appName as any)}>
{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>
</Box>
</MyBox>
<TableContainer mt={3} flex={'1 0 0'} h={0} overflowY={'auto'}>
<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 className="textEllipsis" maxW={'400px'} title={t(item.appName as any)}>
{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>
<Flex mt={3} justifyContent={'center'}>
<Pagination />
</Flex>
@@ -178,7 +170,7 @@ const UsageTableList = ({
{!!usageDetail && (
<UsageDetail usage={usageDetail} onClose={() => setUsageDetail(undefined)} />
)}
</>
</MyBox>
);
};
@@ -42,6 +42,7 @@ import {
} from '@fastgpt/global/core/app/logs/constants';
import { formatDateByTimespan } from '@fastgpt/global/core/app/logs/utils';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import MyBox from '@fastgpt/web/components/common/MyBox';
export type HeaderControlProps = {
appId: string;
@@ -149,7 +150,7 @@ const LogChart = ({
const [offset, setOffset] = useState<string>(offsetOptions[0].value);
const { data: chartData } = useRequest2(
const { data: chartData, loading } = useRequest2(
async () => {
return getAppChartData({
appId,
@@ -331,7 +332,7 @@ const LogChart = ({
]);
return (
<Flex flexDir={'column'} h={'full'}>
<MyBox isLoading={loading} display={'flex'} flexDir={'column'} h={'full'}>
<HeaderControl
appId={appId}
chatSources={chatSources}
@@ -751,7 +752,7 @@ const LogChart = ({
</AccordionItem>
</Accordion>
</Flex>
</Flex>
</MyBox>
);
};
@@ -49,6 +49,7 @@ import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import dynamic from 'next/dynamic';
import type { HeaderControlProps } from './LogChart';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import MyBox from '@fastgpt/web/components/common/MyBox';
const DetailLogsModal = dynamic(() => import('./DetailLogsModal'));
@@ -196,9 +197,10 @@ const LogTable = ({
Pagination,
getData,
pageNum,
total
total,
pageSize
} = usePagination(getAppChatLogs, {
pageSize: 20,
defaultPageSize: 20,
params,
refreshDeps: [params]
});
@@ -338,7 +340,7 @@ const LogTable = ({
});
return (
<Flex flexDir={'column'} h={'full'} overflow={'auto'} px={[4, 8]}>
<MyBox isLoading={isLoading} display={'flex'} flexDir={'column'} h={'full'} px={[4, 8]}>
<Flex alignItems={'center'} gap={3} flexWrap={'wrap'}>
{showSourceSelector && (
<Flex>
@@ -465,7 +467,7 @@ const LogTable = ({
/>
</Flex>
<TableContainer mt={[2, 4]} flex={['', '1 0 0']} h={['auto', 0]} overflowY={'auto'}>
<TableContainer mt={[2, 4]} flex={'1 0 0'} overflowY={'auto'}>
<Table variant={'simple'} fontSize={'sm'}>
<Thead>
<Tr>
@@ -496,9 +498,11 @@ const LogTable = ({
{logs.length === 0 && !isLoading && <EmptyTip text={t('app:logs_empty')}></EmptyTip>}
</TableContainer>
<HStack w={'100%'} mt={3} justifyContent={'center'}>
<Pagination />
</HStack>
{total >= pageSize && (
<Flex mt={3} justifyContent={'center'}>
<Pagination />
</Flex>
)}
{!!detailLogsId && (
<DetailLogsModal
@@ -510,7 +514,7 @@ const LogTable = ({
}}
/>
)}
</Flex>
</MyBox>
);
};
@@ -149,11 +149,12 @@ const Header = () => {
p={0.5}
borderRadius={'sm'}
>
<MyIcon
name={'common/leftArrowLight'}
w={6}
cursor={'pointer'}
onClick={isSaved ? onBack : onOpenBackConfirm}
<IconButton
icon={<MyIcon name={'common/leftArrowLight'} color={'myGray.600'} w={'0.8rem'} />}
aria-label={''}
size={'xs'}
w={'1rem'}
variant={'ghost'}
/>
</Box>
@@ -213,8 +214,6 @@ const Header = () => {
isPc,
currentTab,
isSaved,
onBack,
onOpenBackConfirm,
isV2Workflow,
t,
showHistoryModal,
@@ -149,11 +149,12 @@ const Header = () => {
p={0.5}
borderRadius={'sm'}
>
<MyIcon
name={'common/leftArrowLight'}
w={6}
cursor={'pointer'}
onClick={isSaved ? onBack : onOpenBackConfirm}
<IconButton
icon={<MyIcon name={'common/leftArrowLight'} color={'myGray.600'} w={'0.8rem'} />}
aria-label={''}
size={'xs'}
w={'1rem'}
variant={'ghost'}
/>
</Box>
@@ -213,8 +214,6 @@ const Header = () => {
isPc,
currentTab,
isSaved,
onBack,
onOpenBackConfirm,
isV2Workflow,
t,
showHistoryModal,
@@ -97,9 +97,11 @@ const EvaluationDetailModal = ({
const {
data: evalItemsList,
Pagination,
pageSize,
total,
getData: fetchData
} = usePagination(getEvalItemsList, {
pageSize: 10,
defaultPageSize: 20,
params: {
evalId: evalDetail._id
},
@@ -440,9 +442,11 @@ const EvaluationDetailModal = ({
})}
</Box>
<Box px={6} py={3}>
<Pagination />
</Box>
{total >= pageSize && (
<Flex my={3} justifyContent={'center'}>
<Pagination />
</Flex>
)}
</Box>
</Flex>
{evalItem ? (
@@ -128,7 +128,7 @@ const CollectionPageContextProvider = ({ children }: { children: ReactNode }) =>
pageNum,
pageSize
} = usePagination(getDatasetCollections, {
pageSize: 20,
defaultPageSize: 20,
params: {
datasetId,
parentId,
@@ -10,14 +10,16 @@ import {
Td,
Tbody,
MenuButton,
Switch
Switch,
Checkbox,
HStack,
Button
} from '@chakra-ui/react';
import {
delDatasetCollectionById,
putDatasetCollectionById,
postLinkCollectionSync
} from '@/web/core/dataset/api';
import { useQuery } from '@tanstack/react-query';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import { useTranslation } from 'next-i18next';
import MyIcon from '@fastgpt/web/components/common/Icon';
@@ -49,6 +51,7 @@ import { useFolderDrag } from '@/components/common/folder/useFolderDrag';
import TagsPopOver from './TagsPopOver';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import TrainingStates from './TrainingStates';
import { useTableMultipleSelect } from '@fastgpt/web/hooks/useTableMultipleSelect';
const Header = dynamic(() => import('./Header'));
const EmptyCollectionTip = dynamic(() => import('./EmptyCollectionTip'));
@@ -103,6 +106,19 @@ const CollectionCard = () => {
[collections, t]
);
const {
selectedItems,
toggleSelect,
isSelected,
setSelectedItems,
FloatingActionBar,
isSelecteAll,
selectAllTrigger
} = useTableMultipleSelect({
list: formatCollections,
getItemId: (e) => e._id
});
const [moveCollectionData, setMoveCollectionData] = useState<{ collectionId: string }>();
const { onOpenModal: onOpenEditTitleModal, EditModal: EditTitleModal } = useEditTitle({
@@ -123,9 +139,9 @@ const CollectionCard = () => {
type: 'delete'
});
const { runAsync: onDelCollection } = useRequest2(
(collectionId: string) => {
(collectionIds: string[]) => {
return delDatasetCollectionById({
id: collectionId
collectionIds
});
},
{
@@ -156,18 +172,17 @@ const CollectionCard = () => {
[formatCollections]
);
useQuery(
['refreshCollection'],
() => {
useRequest2(
async () => {
if (!hasTrainingData && datasetDetail.status === DatasetStatusEnum.active) return;
getData(pageNum);
if (datasetDetail.status !== DatasetStatusEnum.active) {
loadDatasetDetail(datasetDetail._id);
}
return null;
},
{
refetchInterval: 6000,
enabled: hasTrainingData || datasetDetail.status !== DatasetStatusEnum.active
retryInterval: 6000,
refreshDeps: [hasTrainingData, datasetDetail.status]
}
);
@@ -186,21 +201,25 @@ const CollectionCard = () => {
}
});
const isLoading =
isUpdating || isSyncing || (isGetting && collections.length === 0) || isDropping;
const isLoading = isUpdating || isSyncing || isGetting || isDropping;
return (
<MyBox isLoading={isLoading} h={'100%'} py={[2, 4]}>
<MyBox isLoading={isLoading} h={'100%'} py={[2, 4]} overflow={'hidden'}>
<Flex ref={BoxRef} flexDirection={'column'} py={[1, 0]} h={'100%'} px={[2, 6]}>
{/* header */}
<Header hasTrainingData={hasTrainingData} />
{/* collection table */}
<TableContainer mt={3} overflowY={'auto'} fontSize={'sm'}>
<TableContainer mt={3} overflowY={'auto'} fontSize={'sm'} flex={'1 0 0'} h={0}>
<Table variant={'simple'} draggable={false}>
<Thead draggable={false}>
<Tr>
<Th py={4}>{t('common:Name')}</Th>
<Th py={4}>
<HStack>
<Checkbox isChecked={isSelecteAll} onChange={selectAllTrigger} />
<Box>{t('common:Name')}</Box>
</HStack>
</Th>
<Th py={4}>{t('dataset:collection.training_type')}</Th>
<Th py={4}>{t('dataset:collection_data_count')}</Th>
<Th py={4}>{t('dataset:collection.Create update time')}</Th>
@@ -241,17 +260,27 @@ const CollectionCard = () => {
}}
>
<Td minW={'150px'} maxW={['200px', '300px']} draggable py={2}>
<Flex alignItems={'center'}>
<MyIcon name={collection.icon as any} w={'1.25rem'} mr={2} />
<MyTooltip label={t('common:click_drag_tip')} shouldWrapChildren={false}>
<Box color={'myGray.900'} fontWeight={'500'} className="textEllipsis">
{collection.name}
</Box>
</MyTooltip>
</Flex>
{feConfigs?.isPlus && !!collection.tags?.length && (
<TagsPopOver currentCollection={collection} />
)}
<HStack>
<Box onClick={(e) => e.stopPropagation()}>
<Checkbox
isChecked={isSelected(collection)}
onChange={(e) => toggleSelect(collection)}
/>
</Box>
<Box>
<Flex alignItems={'center'}>
<MyIcon name={collection.icon as any} w={'1.25rem'} mr={2} />
<MyTooltip label={t('common:click_drag_tip')} shouldWrapChildren={false}>
<Box color={'myGray.900'} fontWeight={'500'} className="textEllipsis">
{collection.name}
</Box>
</MyTooltip>
</Flex>
{feConfigs?.isPlus && !!collection.tags?.length && (
<TagsPopOver currentCollection={collection} />
)}
</Box>
</HStack>
</Td>
<Td py={2}>
{collection.trainingType
@@ -394,7 +423,7 @@ const CollectionCard = () => {
type: 'danger',
onClick: () =>
openDeleteConfirm(
() => onDelCollection(collection._id),
() => onDelCollection([collection._id]),
undefined,
collection.type === DatasetCollectionTypeEnum.folder
? t('common:dataset.collections.Confirm to delete the folder')
@@ -411,13 +440,39 @@ const CollectionCard = () => {
))}
</Tbody>
</Table>
{total === 0 && <EmptyCollectionTip />}
</TableContainer>
<FloatingActionBar
Controler={
<HStack>
<Button
variant={'whiteBase'}
onClick={() =>
openDeleteConfirm(
() =>
onDelCollection(selectedItems.map((e) => e._id)).then(() =>
setSelectedItems([])
),
undefined,
t('dataset:confirm_delete_collection', {
num: selectedItems.length
})
)()
}
>
{t('dataset:batch_delete')}
</Button>
</HStack>
}
>
{total > pageSize && (
<Flex mt={2} justifyContent={'center'}>
<Flex justifyContent={'center'}>
<Pagination />
</Flex>
)}
{total === 0 && <EmptyCollectionTip />}
</TableContainer>
</FloatingActionBar>
<ConfirmDeleteModal />
<ConfirmSyncModal />
@@ -27,9 +27,10 @@ const BillAndInvoice = () => {
return (
<AccountContainer>
<Box p={['1rem', '2rem']}>
<Flex h={'100%'} flexDirection={'column'} p={['2', '4']}>
<Flex justifyContent={'space-between'} alignItems={'center'} pb={'0.75rem'}>
<FillRowTabs
py={1}
list={[
{ label: t('account_bill:bill_record'), value: InvoiceTabEnum.bill },
{
@@ -61,7 +62,7 @@ const BillAndInvoice = () => {
</Button>
)}
</Flex>
<Box h={'100%'}>
<Box flex={'1 0 0'} h={0} overflow={'auto'}>
{invoiceTab === InvoiceTabEnum.bill && <BillTable />}
{invoiceTab === InvoiceTabEnum.invoice && <InvoiceTable />}
{invoiceTab === InvoiceTabEnum.invoiceHeader && <InvoiceHeaderForm />}
@@ -73,7 +74,7 @@ const BillAndInvoice = () => {
}}
/>
)}
</Box>
</Flex>
</AccountContainer>
);
};
+2 -2
View File
@@ -44,7 +44,7 @@ const InformTable = () => {
getData,
pageNum
} = usePagination(getInforms, {
pageSize: 20
defaultPageSize: 20
});
return (
@@ -147,7 +147,7 @@ const InformTable = () => {
)}
{total > pageSize && (
<Flex w="100%" mt={4} px={[3, 8]} justifyContent="flex-end">
<Flex mt={4} justifyContent="center">
<Pagination />
</Flex>
)}
+2 -2
View File
@@ -43,7 +43,7 @@ const Promotion = () => {
pageSize,
Pagination
} = usePagination(getPromotionRecords, {
pageSize: 20
defaultPageSize: 20
});
const { data: { invitedAmount = 0, earningsAmount = 0 } = {} } = useQuery(
@@ -131,7 +131,7 @@ const Promotion = () => {
<EmptyTip text={t('account_promotion:no_invite_records')}></EmptyTip>
)}
{total > pageSize && (
<Flex mt={4} justifyContent={'flex-end'}>
<Flex mt={3} justifyContent={'center'}>
<Pagination />
</Flex>
)}
@@ -7,6 +7,7 @@ import { MongoAppChatLog } from '@fastgpt/service/core/app/logs/chatLogsSchema';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { addLog } from '@fastgpt/service/common/system/log';
import type { ChatSchemaType } from '@fastgpt/global/core/chat/type';
import { surrenderProcess } from '@fastgpt/service/common/system/tools';
export type SyncAppChatLogQuery = {};
@@ -63,7 +64,9 @@ async function handler(
async function processChatRecord(chat: ChatSchemaType) {
async function calculateChatItemStats() {
const chatItems = await MongoChatItem.find({ appId: chat.appId, chatId: chat.chatId }).lean();
const chatItems = await MongoChatItem.find({ appId: chat.appId, chatId: chat.chatId })
.limit(1000)
.lean();
let chatItemCount = chatItems.length;
let errorCount = 0;
@@ -73,6 +76,8 @@ async function processChatRecord(chat: ChatSchemaType) {
let totalResponseTime = 0;
for (const item of chatItems) {
await surrenderProcess();
const itemData = item as any;
if (itemData.userGoodFeedback && itemData.userGoodFeedback.trim() !== '') {
@@ -1,4 +1,3 @@
import type { NextApiRequest } from 'next';
import { findCollectionAndChild } from '@fastgpt/service/core/dataset/collection/utils';
import { delCollection } from '@fastgpt/service/core/dataset/collection/controller';
import { authDatasetCollection } from '@fastgpt/service/support/permission/dataset/auth';
@@ -9,28 +8,50 @@ import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { addAuditLog } from '@fastgpt/service/support/user/audit/util';
import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/user/audit/util';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
async function handler(req: NextApiRequest) {
const { id: collectionId } = req.query as { id: string };
export type DelCollectionBody = {
collectionIds: string[];
};
if (!collectionId) {
async function handler(req: ApiRequestProps<DelCollectionBody>) {
const { collectionIds } = req.body;
if (!collectionIds) {
return Promise.reject(CommonErrEnum.missingParams);
}
const { teamId, collection, tmbId } = await authDatasetCollection({
req,
authToken: true,
authApiKey: true,
collectionId,
per: WritePermissionVal
});
const [{ teamId, collection, tmbId }] = await Promise.all(
collectionIds.map(async (collectionId) => {
return await authDatasetCollection({
req,
authToken: true,
authApiKey: true,
collectionId,
per: WritePermissionVal
});
})
);
// find all delete id
const collections = await findCollectionAndChild({
teamId,
datasetId: collection.datasetId,
collectionId,
fields: '_id teamId datasetId fileId metadata'
const collections = await Promise.all(
collectionIds.map(async (collectionId) => {
return await findCollectionAndChild({
teamId,
datasetId: collection.datasetId,
collectionId,
fields: '_id teamId datasetId fileId metadata'
});
})
).then((res) => {
const flattened = res.flat();
console.log(flattened.length, 22);
// Remove duplicates based on _id
const uniqueCollections = flattened.filter(
(collection, index, arr) =>
arr.findIndex((item) => item._id.toString() === collection._id.toString()) === index
);
return uniqueCollections;
});
// delete
@@ -23,7 +23,7 @@ async function handler(req: NextApiRequest) {
simple = false
} = req.body as any;
searchText = searchText?.replace(/'/g, '');
pageSize = Math.min(pageSize, 30);
pageSize = Math.min(pageSize, 100);
// auth dataset and get my role
const { teamId, permission } = await authDataset({
@@ -28,7 +28,7 @@ async function handler(
simple = false
} = req.body as GetDatasetCollectionsProps;
let { pageSize, offset } = parsePaginationRequest(req);
pageSize = Math.min(pageSize, 30);
pageSize = Math.min(pageSize, 100);
searchText = searchText?.replace(/'/g, '');
// auth dataset and get my role
@@ -46,9 +46,11 @@ const Evaluation = () => {
const {
data: evaluationList,
Pagination,
getData: fetchData
getData: fetchData,
total,
pageSize
} = usePagination(getEvaluationList, {
pageSize: 20,
defaultPageSize: 20,
pollingInterval,
pollingWhenHidden: true,
params: {
@@ -185,90 +187,90 @@ const Evaluation = () => {
<Flex h={'full'} bg={'white'} p={6} flexDirection="column">
{renderHeader(MenuIcon)}
<MyBox flex={'1 0 0'} overflow="auto">
<TableContainer mt={3} fontSize={'sm'}>
<Table variant={'simple'}>
<Thead>
<Tr color={'myGray.600'}>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Task_name')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Progress')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Executor')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Evaluation_app')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Start_end_time')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Overall_score')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Action')}</Th>
</Tr>
</Thead>
<Tbody>
<Tr h={'5px'} />
{evaluationList.map((item) => {
return (
<Tr key={item._id}>
<Td fontWeight={'medium'} color={'myGray.900'}>
{item.name}
</Td>
<Td>{renderProgress(item)}</Td>
<Td>
<Flex alignItems={'center'} gap={1.5}>
<Avatar
src={item.executorAvatar}
w={5}
borderRadius={'full'}
border={'1px solid'}
borderColor={'myGray.200'}
/>
<Box color={'myGray.900'}>{item.executorName}</Box>
</Flex>
</Td>
<Td>
<Flex alignItems={'center'} gap={1.5}>
<Avatar src={item.appAvatar} w={5} borderRadius={'4px'} />
<Box color={'myGray.900'}>{item.appName}</Box>
</Flex>
</Td>
<Td color={'myGray.900'}>
<Box>{formatTime2YMDHM(item.createTime)}</Box>
<Box>{formatTime2YMDHM(item.finishTime)}</Box>
</Td>
<Td color={item.score ? 'myGray.600' : 'myGray.900'}>
{typeof item.score === 'number' ? (item.score * 100).toFixed(2) : '-'}
</Td>
<Td>
<Button
variant={'whiteBase'}
leftIcon={<MyIcon name={'common/detail'} w={4} />}
fontSize={'12px'}
fontWeight={'medium'}
mr={2}
onClick={() => setEvalDetailId(item._id)}
>
{t('dashboard_evaluation:detail')}
</Button>
<PopoverConfirm
type="delete"
Trigger={
<IconButton
aria-label="delete"
size={'mdSquare'}
variant={'whiteDanger'}
icon={<MyIcon name={'delete'} w={4} />}
/>
}
content={t('dashboard_evaluation:comfirm_delete_task')}
onConfirm={() => onDeleteEval({ evalId: item._id })}
<TableContainer mt={3} fontSize={'sm'} flex={'1 0 0'} overflowY="auto">
<Table variant={'simple'}>
<Thead>
<Tr color={'myGray.600'}>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Task_name')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Progress')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Executor')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Evaluation_app')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Start_end_time')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Overall_score')}</Th>
<Th fontWeight={'400'}>{t('dashboard_evaluation:Action')}</Th>
</Tr>
</Thead>
<Tbody>
<Tr h={'5px'} />
{evaluationList.map((item) => {
return (
<Tr key={item._id}>
<Td fontWeight={'medium'} color={'myGray.900'}>
{item.name}
</Td>
<Td>{renderProgress(item)}</Td>
<Td>
<Flex alignItems={'center'} gap={1.5}>
<Avatar
src={item.executorAvatar}
w={5}
borderRadius={'full'}
border={'1px solid'}
borderColor={'myGray.200'}
/>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</TableContainer>
</MyBox>
<Flex mt={4} justifyContent="center">
<Pagination />
</Flex>
<Box color={'myGray.900'}>{item.executorName}</Box>
</Flex>
</Td>
<Td>
<Flex alignItems={'center'} gap={1.5}>
<Avatar src={item.appAvatar} w={5} borderRadius={'4px'} />
<Box color={'myGray.900'}>{item.appName}</Box>
</Flex>
</Td>
<Td color={'myGray.900'}>
<Box>{formatTime2YMDHM(item.createTime)}</Box>
<Box>{formatTime2YMDHM(item.finishTime)}</Box>
</Td>
<Td color={item.score ? 'myGray.600' : 'myGray.900'}>
{typeof item.score === 'number' ? (item.score * 100).toFixed(2) : '-'}
</Td>
<Td>
<Button
variant={'whiteBase'}
leftIcon={<MyIcon name={'common/detail'} w={4} />}
fontSize={'12px'}
fontWeight={'medium'}
mr={2}
onClick={() => setEvalDetailId(item._id)}
>
{t('dashboard_evaluation:detail')}
</Button>
<PopoverConfirm
type="delete"
Trigger={
<IconButton
aria-label="delete"
size={'mdSquare'}
variant={'whiteDanger'}
icon={<MyIcon name={'delete'} w={4} />}
/>
}
content={t('dashboard_evaluation:comfirm_delete_task')}
onConfirm={() => onDeleteEval({ evalId: item._id })}
/>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</TableContainer>
{total >= pageSize && (
<Flex mt={4} justifyContent="center">
<Pagination />
</Flex>
)}
</Flex>
)}
</DashboardContainer>
+3 -2
View File
@@ -79,6 +79,7 @@ import type {
GetApiDatasetPathBody,
GetApiDatasetPathResponse
} from '@/pages/api/core/dataset/apiDataset/getPathNames';
import type { DelCollectionBody } from '@/pages/api/core/dataset/collection/delete';
/* ======================== dataset ======================= */
export const getDatasets = (data: GetDatasetListBody) =>
@@ -216,8 +217,8 @@ export const postCreateDatasetApiDatasetCollection = (
export const putDatasetCollectionById = (data: UpdateDatasetCollectionParams) =>
POST(`/core/dataset/collection/update`, data);
export const delDatasetCollectionById = (params: { id: string }) =>
DELETE(`/core/dataset/collection/delete`, params);
export const delDatasetCollectionById = (params: DelCollectionBody) =>
POST(`/core/dataset/collection/delete`, params);
export const postLinkCollectionSync = (collectionId: string) =>
POST<DatasetCollectionSyncResultEnum>(`/core/dataset/collection/sync`, {
collectionId