import React, { useCallback, useState, useRef, useMemo } from 'react'; import { Box, Card, IconButton, Flex, Grid, Button, useTheme, Drawer, DrawerBody, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerContent, useDisclosure } from '@chakra-ui/react'; import { usePagination } from '@/web/common/hooks/usePagination'; import { getDatasetDataList, delOneDatasetDataById, getDatasetCollectionById } from '@/web/core/dataset/api'; import { DeleteIcon } from '@chakra-ui/icons'; import { useQuery } from '@tanstack/react-query'; import { useToast } from '@/web/common/hooks/useToast'; import { debounce } from 'lodash'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { useConfirm } from '@/web/common/hooks/useConfirm'; import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; import MyIcon from '@/components/Icon'; import MyInput from '@/components/MyInput'; import { useLoading } from '@/web/common/hooks/useLoading'; import InputDataModal, { RawSourceText, type InputDataType } from '../components/InputDataModal'; import type { DatasetDataListItemType } from '@/global/core/dataset/type.d'; import { TabEnum } from '..'; import { useUserStore } from '@/web/support/user/useUserStore'; import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant'; import { getDefaultIndex } from '@fastgpt/global/core/dataset/utils'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { DatasetCollectionTypeMap, DatasetCollectionTrainingTypeMap } from '@fastgpt/global/core/dataset/constant'; import { formatTime2YMDHM } from '@fastgpt/global/common/string/time'; import { formatFileSize } from '@fastgpt/global/common/file/tools'; import { getFileAndOpen } from '@/web/core/dataset/utils'; import MyTooltip from '@/components/MyTooltip'; const DataCard = () => { const BoxRef = useRef(null); const theme = useTheme(); const lastSearch = useRef(''); const router = useRouter(); const { userInfo } = useUserStore(); const { isPc } = useSystemStore(); const { collectionId = '', datasetId } = router.query as { collectionId: string; datasetId: string; }; const { Loading, setIsLoading } = useLoading({ defaultLoading: true }); const { t } = useTranslation(); const [searchText, setSearchText] = useState(''); const { toast } = useToast(); const { openConfirm, ConfirmModal } = useConfirm({ content: t('dataset.Confirm to delete the data') }); const { isOpen, onOpen, onClose } = useDisclosure(); const { data: datasetDataList, Pagination, total, getData, pageNum, pageSize } = usePagination({ api: getDatasetDataList, pageSize: 24, params: { collectionId, searchText }, onChange() { setIsLoading(false); if (BoxRef.current) { BoxRef.current.scrollTop = 0; } } }); const [editInputData, setEditInputData] = useState(); // get first page data const getFirstData = useCallback( debounce(() => { getData(1); lastSearch.current = searchText; }, 300), [] ); // get file info const { data: collection } = useQuery( ['getDatasetCollectionById', collectionId], () => getDatasetCollectionById(collectionId), { onError: () => { router.replace({ query: { datasetId } }); } } ); const canWrite = useMemo( () => userInfo?.team?.role !== TeamMemberRoleEnum.visitor && !!collection?.canWrite, [collection?.canWrite, userInfo?.team?.role] ); const metadataList = useMemo( () => collection ? [ { label: t('core.dataset.collection.metadata.source'), value: t(DatasetCollectionTypeMap[collection.type]?.name) }, { label: t('core.dataset.collection.metadata.source name'), value: collection.file?.filename || collection?.rawLink || collection?.name }, { label: t('core.dataset.collection.metadata.source size'), value: collection.file ? formatFileSize(collection.file.length) : '-' }, { label: t('core.dataset.collection.metadata.Createtime'), value: formatTime2YMDHM(collection.createTime) }, { label: t('core.dataset.collection.metadata.Updatetime'), value: formatTime2YMDHM(collection.updateTime) }, { label: t('core.dataset.collection.metadata.Training Type'), value: t(DatasetCollectionTrainingTypeMap[collection.trainingType]?.label) }, { label: t('core.dataset.collection.metadata.Chunk Size'), value: collection.chunkSize || '-' } ] : [], [collection, t] ); return ( } bg={'white'} boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'} size={'sm'} borderRadius={'50%'} aria-label={''} onClick={() => router.replace({ query: { datasetId: router.query.datasetId, parentId: router.query.parentId, currentTab: TabEnum.collectionCard } }) } /> 文件ID:{' '} {collection?._id} {canWrite && ( )} {isPc && ( } aria-label={''} onClick={onOpen} /> )} {total}组 } w={['200px', '300px']} placeholder="根据匹配知识,预期答案和来源进行搜索" value={searchText} onChange={(e) => { setSearchText(e.target.value); getFirstData(); }} onBlur={() => { if (searchText === lastSearch.current) return; getFirstData(); }} onKeyDown={(e) => { if (searchText === lastSearch.current) return; if (e.key === 'Enter') { getFirstData(); } }} /> {datasetDataList.map((item, index) => ( { if (!collection) return; setEditInputData({ id: item._id, q: item.q, a: item.a, indexes: item.indexes }); }} > # {index + 1} ID:{item._id} {item.q} {item.a} {item.q.length + (item.a?.length || 0)} {canWrite && ( } variant={'base'} colorScheme={'gray'} aria-label={'delete'} size={'xs'} borderRadius={'md'} _hover={{ color: 'red.600' }} onClick={(e) => { e.stopPropagation(); openConfirm(async () => { try { setIsLoading(true); await delOneDatasetDataById(item._id); getData(pageNum); } catch (error) { toast({ title: getErrText(error), status: 'error' }); } setIsLoading(false); })(); }} /> )} ))} {/* metadata drawer */} {t('core.dataset.collection.metadata.metadata')} {metadataList.map((item) => ( {item.label} {item.value} ))} {collection?.sourceId && ( )} {total > pageSize && ( )} {total === 0 && ( 内容空空的,快创建一个吧! )} {editInputData !== undefined && collection && ( setEditInputData(undefined)} onSuccess={() => getData(pageNum)} onDelete={() => getData(pageNum)} /> )} ); }; export default React.memo(DataCard);