import React, { useMemo, useRef, useState } from 'react'; import { Box, Flex, Grid, useTheme, useDisclosure, Card, MenuButton, Image } from '@chakra-ui/react'; import { useRouter } from 'next/router'; import { useDatasetStore } from '@/store/dataset'; import PageContainer from '@/components/PageContainer'; import { useConfirm } from '@/hooks/useConfirm'; import { AddIcon } from '@chakra-ui/icons'; import { useQuery } from '@tanstack/react-query'; import { delKbById, exportDataset, getKbPaths, putKbById } from '@/api/plugins/kb'; import { useTranslation } from 'react-i18next'; import Avatar from '@/components/Avatar'; import MyIcon from '@/components/Icon'; import { serviceSideProps } from '@/utils/i18n'; import dynamic from 'next/dynamic'; import { FolderAvatarSrc, KbTypeEnum } from '@/constants/kb'; import Tag from '@/components/Tag'; import MyMenu from '@/components/MyMenu'; import { useRequest } from '@/hooks/useRequest'; import { useGlobalStore } from '@/store/global'; import { useEditTitle } from '@/hooks/useEditTitle'; import { feConfigs } from '@/store/static'; const CreateModal = dynamic(() => import('./component/CreateModal'), { ssr: false }); const EditFolderModal = dynamic(() => import('./component/EditFolderModal'), { ssr: false }); const MoveModal = dynamic(() => import('./component/MoveModal'), { ssr: false }); const Kb = () => { const { t } = useTranslation(); const theme = useTheme(); const router = useRouter(); const { parentId } = router.query as { parentId: string }; const { setLoading } = useGlobalStore(); const DeleteTipsMap = useRef({ [KbTypeEnum.folder]: t('kb.deleteFolderTips'), [KbTypeEnum.dataset]: t('kb.deleteDatasetTips') }); const { openConfirm, ConfirmModal } = useConfirm({ title: t('common.Delete Warning'), content: '' }); const { myKbList, loadKbList, setKbList, updateDataset } = useDatasetStore(); const { onOpenModal: onOpenTitleModal, EditModal: EditTitleModal } = useEditTitle({ title: t('Rename') }); const [moveDataId, setMoveDataId] = useState(); const [dragStartId, setDragStartId] = useState(); const [dragTargetId, setDragTargetId] = useState(); const { isOpen: isOpenCreateModal, onOpen: onOpenCreateModal, onClose: onCloseCreateModal } = useDisclosure(); const [editFolderData, setEditFolderData] = useState<{ id?: string; name?: string; }>(); /* 点击删除 */ const { mutate: onclickDelKb } = useRequest({ mutationFn: async (id: string) => { setLoading(true); await delKbById(id); return id; }, onSuccess(id: string) { setKbList(myKbList.filter((item) => item._id !== id)); }, onSettled() { setLoading(false); }, successToast: t('common.Delete Success'), errorToast: t('kb.Delete Dataset Error') }); // export dataset to csv const { mutate: onclickExport } = useRequest({ mutationFn: (kbId: string) => { setLoading(true); return exportDataset({ kbId }); }, onSettled() { setLoading(false); }, successToast: `导出成功,下次导出需要 ${feConfigs?.limit?.exportLimitMinutes} 分钟后`, errorToast: '导出异常' }); const { data, refetch } = useQuery(['loadDataset', parentId], () => { return Promise.all([loadKbList(parentId), getKbPaths(parentId)]); }); const paths = useMemo( () => [ { parentId: '', parentName: t('kb.My Dataset') }, ...(data?.[1] || []) ], [data, t] ); return ( {/* url path */} {!!parentId ? ( {paths.map((item, i) => ( { router.push({ query: { parentId: item.parentId } }); } })} > {item.parentName} {i !== paths.length - 1 && ( )} ))} ) : ( 我的知识库 )} {t('Create New')} } menuList={[ { child: ( {''} {t('Folder')} ), onClick: () => setEditFolderData({}) }, { child: ( {''} {t('Dataset')} ), onClick: onOpenCreateModal } ]} /> {myKbList.map((kb) => ( { setDragStartId(kb._id); }} onDragOver={(e) => { e.preventDefault(); const targetId = e.currentTarget.getAttribute('data-drag-id'); if (!targetId) return; KbTypeEnum.folder && setDragTargetId(targetId); }} onDragLeave={(e) => { e.preventDefault(); setDragTargetId(undefined); }} onDrop={async (e) => { e.preventDefault(); if (!dragTargetId || !dragStartId || dragTargetId === dragStartId) return; // update parentId try { await putKbById({ id: dragStartId, parentId: dragTargetId }); refetch(); } catch (error) {} setDragTargetId(undefined); }} _hover={{ boxShadow: '1px 1px 10px rgba(0,0,0,0.2)', borderColor: 'transparent', '& .delete': { display: 'block' } }} onClick={() => { if (kb.type === KbTypeEnum.folder) { router.push({ pathname: '/kb/list', query: { parentId: kb._id } }); } else if (kb.type === KbTypeEnum.dataset) { router.push({ pathname: '/kb/detail', query: { kbId: kb._id } }); } }} > { e.stopPropagation(); }} > } menuList={[ { child: ( {t('Rename')} ), onClick: () => onOpenTitleModal({ defaultVal: kb.name, onSuccess: (val) => { if (val === kb.name || !val) return; updateDataset({ id: kb._id, name: val }); } }) }, { child: ( {t('Move')} ), onClick: () => setMoveDataId(kb._id) }, { child: ( {t('Export')} ), onClick: () => onclickExport(kb._id) }, { child: ( {t('common.Delete')} ), onClick: () => { openConfirm( () => onclickDelKb(kb._id), undefined, DeleteTipsMap.current[kb.type] )(); } } ]} /> {kb.name} {kb.tags.map((tag, i) => ( {tag} ))} {kb.type === KbTypeEnum.folder ? ( {t('Folder')} ) : ( <> {kb.vectorModel.name} )} ))} {myKbList.length === 0 && ( 还没有知识库,快去创建一个吧! )} {isOpenCreateModal && } {!!editFolderData && ( setEditFolderData(undefined)} onSuccess={refetch} parentId={parentId} {...editFolderData} /> )} {!!moveDataId && ( setMoveDataId('')} onSuccess={() => { refetch(); setMoveDataId(''); }} /> )} ); }; export async function getServerSideProps(content: any) { return { props: { ...(await serviceSideProps(content)) } }; } export default Kb;