feat: move dataset (#277)

This commit is contained in:
Archer
2023-09-11 18:23:51 +08:00
committed by GitHub
parent ae2887e956
commit b46048609c
17 changed files with 422 additions and 60 deletions

View File

@@ -5,7 +5,9 @@
"Create New": "Create",
"Dataset": "Dataset",
"Folder": "Folder",
"Move": "Move",
"Name": "Name",
"Rename": "Rename",
"Running": "Running",
"Select value is empty": "Select value is empty",
"UnKnow": "UnKnow",
@@ -163,6 +165,7 @@
},
"kb": {
"Chunk Length": "Chunk Length",
"Confirm move the folder": "Confirm Move",
"Confirm to delete the file": "Are you sure to delete the file and all its data?",
"Create Folder": "Create Folder",
"Delete Dataset Error": "Delete dataset failed",
@@ -171,7 +174,9 @@
"Filename": "Filename",
"Files": "{{total}} Files",
"Folder Name": "Input folder name",
"Move Failed": "Move Failed",
"My Dataset": "My Dataset",
"No Folder": "No Folder",
"Other Data": "Other Data",
"Select Dataset": "Select Dataset",
"Select Folder": "Enter folder",

View File

@@ -5,7 +5,9 @@
"Create New": "新建",
"Dataset": "知识库",
"Folder": "文件夹",
"Move": "移动",
"Name": "名称",
"Rename": "重命名",
"Running": "运行中",
"Select value is empty": "选择的内容为空",
"UnKnow": "未知",
@@ -163,6 +165,7 @@
},
"kb": {
"Chunk Length": "数据总量",
"Confirm move the folder": "确认移动到该目录",
"Confirm to delete the file": "确认删除该文件及其所有数据?",
"Create Folder": "创建文件夹",
"Delete Dataset Error": "删除知识库异常",
@@ -171,7 +174,9 @@
"Filename": "文件名",
"Files": "文件: {{total}}个",
"Folder Name": "输入文件夹名称",
"Move Failed": "移动出现错误~",
"My Dataset": "我的知识库",
"No Folder": "没有子目录了~",
"Other Data": "其他数据",
"Select Dataset": "选择该知识库",
"Select Folder": "进入文件夹",

View File

@@ -19,10 +19,11 @@ import {
import { Props as UpdateDataProps } from '@/pages/api/openapi/kb/updateData';
import type { KbUpdateParams, CreateKbParams, GetKbDataListProps } from '../request/kb';
import { QuoteItemType } from '@/types/chat';
import { KbTypeEnum } from '@/constants/kb';
/* knowledge base */
export const getKbList = (parentId?: string) =>
GET<KbListItemType[]>(`/plugins/kb/list`, { parentId });
export const getKbList = (data: { parentId?: string; type?: `${KbTypeEnum}` }) =>
GET<KbListItemType[]>(`/plugins/kb/list`, data);
export const getAllDataset = () => GET<KbListItemType[]>(`/plugins/kb/allDataset`);
export const getKbPaths = (parentId?: string) =>

View File

@@ -3,6 +3,7 @@ import type { RequestPaging } from '@/types';
export type KbUpdateParams = {
id: string;
parentId?: string;
tags?: string;
name?: string;
avatar?: string;

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1694403033666" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4053" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M1016.32 494.08l-143.872-143.36c-9.728-9.728-26.112-9.728-35.84 0-9.728 9.728-9.728 26.112 0 35.84L936.96 486.4h-399.36V87.04l99.84 100.352c9.728 9.728 26.112 9.728 35.84 0 9.728-9.728 9.728-26.112 0-35.84l-143.36-143.872c-9.728-9.728-26.112-9.728-35.84 0l-143.36 143.872c-9.728 9.728-9.728 26.112 0 35.84 9.728 9.728 26.112 9.728 35.84 0L486.4 87.04v399.36H87.04l100.352-99.84c9.728-9.728 9.728-26.112 0-35.84-9.728-9.728-26.112-9.728-35.84 0l-143.872 143.36c-9.728 9.728-9.728 26.112 0 35.84l143.872 143.36c9.728 9.728 26.112 9.728 35.84 0 9.728-9.728 9.728-26.112 0-35.84L87.04 537.6h399.36v399.36l-99.84-100.352c-9.728-9.728-26.112-9.728-35.84 0-9.728 9.728-9.728 26.112 0 35.84l143.36 143.872c9.728 9.728 26.112 9.728 35.84 0l143.36-143.872c9.728-9.728 9.728-26.112 0-35.84-9.728-9.728-26.112-9.728-35.84 0L537.6 936.96v-399.36h399.36l-100.352 99.84c-9.728 9.728-9.728 26.112 0 35.84 9.728 9.728 26.112 9.728 35.84 0l143.872-143.36c10.24-9.728 10.24-26.112 0-35.84z" p-id="4054"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24">
<svg viewBox="0 0 24 24">
<path d="M8.3 5.7a1 1 0 011.4-1.4l7.71 7.7-7.7 7.7a1 1 0 11-1.42-1.4l6.3-6.3-6.3-6.3z" fill-rule="nonzero"></path>
</svg>

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 151 B

View File

@@ -83,7 +83,8 @@ const map = {
retryLight: require('./icons/light/retry.svg').default,
rightArrowLight: require('./icons/light/rightArrow.svg').default,
searchLight: require('./icons/light/search.svg').default,
plusFill: require('./icons/fill/plus.svg').default
plusFill: require('./icons/fill/plus.svg').default,
moveLight: require('./icons/light/move.svg').default
};
export type IconName = keyof typeof map;

View File

@@ -8,7 +8,7 @@ interface Props {
menuList: {
isActive?: boolean;
child: React.ReactNode;
onClick: () => void;
onClick: () => any;
}[];
}
@@ -37,7 +37,10 @@ const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
<MenuItem
key={i}
{...menuItemStyles}
onClick={item.onClick}
onClick={(e) => {
e.stopPropagation();
item.onClick && item.onClick();
}}
color={item.isActive ? 'hover.blue' : ''}
>
{item.child}

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useRef, useState } from 'react';
import React, { useCallback, useRef } from 'react';
import { ModalFooter, ModalBody, Input, useDisclosure, Button } from '@chakra-ui/react';
import MyModal from '@/components/MyModal';
@@ -39,6 +39,7 @@ export const useEditInfo = ({
try {
const val = inputRef.current.value;
await onSuccessCb.current?.(val);
onClose();
} catch (err) {
onErrorCb.current?.(err);

View File

@@ -4,10 +4,11 @@ import { connectToDatabase, KB } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { getVectorModel } from '@/service/utils/data';
import { KbListItemType } from '@/types/plugin';
import { KbTypeEnum } from '@/constants/kb';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const { parentId } = req.query as { parentId: string };
const { parentId, type } = req.query as { parentId?: string; type?: `${KbTypeEnum}` };
// 凭证校验
const { userId } = await authUser({ req, authToken: true });
@@ -15,7 +16,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const kbList = await KB.find({
userId,
parentId: parentId || null
...(parentId !== undefined && { parentId: parentId || null }),
...(type && { type })
}).sort({ updateTime: -1 });
const data = await Promise.all(

View File

@@ -6,9 +6,9 @@ import type { KbUpdateParams } from '@/api/request/kb';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const { id, name, avatar, tags = '' } = req.body as KbUpdateParams;
const { id, parentId, name, avatar, tags } = req.body as KbUpdateParams;
if (!id || !name) {
if (!id) {
throw new Error('缺少参数');
}
@@ -23,9 +23,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
userId
},
{
...(parentId !== undefined && { parentId: parentId || null }),
...(name && { name }),
...(avatar && { avatar }),
tags: tags.split(' ').filter((item) => item)
...(typeof tags === 'string' && {
tags: tags.split(' ').filter((item) => item)
})
}
);

View File

@@ -83,7 +83,13 @@ export const KBSelectModal = ({
<Flex flexDirection={'column'} h={['90vh', 'auto']}>
<ModalHeader>
{!!parentId ? (
<Flex flex={1}>
<Flex
flex={1}
userSelect={'none'}
fontSize={['sm', 'lg']}
fontWeight={'normal'}
color={'myGray.900'}
>
{paths.map((item, i) => (
<Flex key={item.parentId} mr={2} alignItems={'center'}>
<Box
@@ -106,7 +112,7 @@ export const KBSelectModal = ({
{item.parentName}
</Box>
{i !== paths.length - 1 && (
<MyIcon name={'rightArrowLight'} color={'myGray.500'} />
<MyIcon name={'rightArrowLight'} color={'myGray.500'} w={['18px', '24px']} />
)}
</Flex>
))}

View File

@@ -1,17 +1,16 @@
import { Box, Flex, Button, Image } from '@chakra-ui/react';
import React from 'react';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { feConfigs } from '@/store/static';
import { useGlobalStore } from '@/store/global';
import MyIcon from '@/components/Icon';
import { useRouter } from 'next/router';
import { useToast } from '@/hooks/useToast';
const Hero = () => {
const router = useRouter();
const { toast } = useToast();
const { t } = useTranslation();
const { isPc, gitStar } = useGlobalStore();
const [showVideo, setShowVide] = useState(false);
return (
<Flex flexDirection={'column'} pt={['24px', '50px']} alignItems={'center'} userSelect={'none'}>
@@ -62,6 +61,7 @@ const Hero = () => {
mx={['-10%', 'auto']}
maxW={['120%', '1000px']}
alt=""
draggable={false}
/>
<MyIcon
name={'playFill'}
@@ -72,13 +72,42 @@ const Hero = () => {
top={'50%'}
color={'#363c42b8'}
transform={['translate(-50%,5px)', 'translate(-50%,40px)']}
onClick={() => {
toast({
title: '录制中~'
});
}}
onClick={() => setShowVide(true)}
/>
</Box>
{showVideo && (
<Flex
position={'fixed'}
zIndex={99}
top={0}
left={0}
right={0}
bottom={0}
alignItems={'center'}
justifyContent={'center'}
bg={'rgba(255,255,255,0.4)'}
onClick={() => setShowVide(false)}
>
<Box
w={['100vw', '50%']}
borderRadius={'lg'}
overflow={'hidden'}
onClick={(e) => e.preventDefault()}
>
<video
style={{
margin: 'auto'
}}
onClick={(e) => {
e.stopPropagation();
}}
src={'https://otnvvf-imgs.oss.laf.run/fastgpt.mp4'}
controls
autoPlay
/>
</Box>
</Flex>
)}
</Flex>
);
};

View File

@@ -145,7 +145,7 @@ const FileCard = ({ kbId }: { kbId: string }) => {
cursor={'pointer'}
title={'点击查看数据详情'}
onClick={() =>
router.push({
router.replace({
query: {
kbId,
fileId: file.id,

View File

@@ -0,0 +1,181 @@
import React, { useMemo, useState } from 'react';
import {
Card,
Flex,
Box,
Button,
ModalBody,
ModalHeader,
ModalFooter,
useTheme,
Grid
} from '@chakra-ui/react';
import { getKbPaths } from '@/api/plugins/kb';
import Avatar from '@/components/Avatar';
import MyTooltip from '@/components/MyTooltip';
import MyModal from '@/components/MyModal';
import MyIcon from '@/components/Icon';
import { KbTypeEnum } from '@/constants/kb';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import { getKbList, putKbById } from '@/api/plugins/kb';
import { useRequest } from '@/hooks/useRequest';
const MoveModal = ({
onClose,
onSuccess,
moveDataId
}: {
onClose: () => void;
onSuccess: () => void;
moveDataId: string;
}) => {
const { t } = useTranslation();
const theme = useTheme();
const [parentId, setParentId] = useState<string>('');
const { data } = useQuery(['getKbList', parentId], () => {
return Promise.all([getKbList({ parentId, type: 'folder' }), getKbPaths(parentId)]);
});
const paths = useMemo(
() => [
{
parentId: '',
parentName: t('kb.My Dataset')
},
...(data?.[1] || [])
],
[data, t]
);
const folderList = useMemo(
() => (data?.[0] || []).filter((item) => item._id !== moveDataId),
[moveDataId, data]
);
const { mutate, isLoading } = useRequest({
mutationFn: () => putKbById({ id: moveDataId, parentId }),
onSuccess,
errorToast: t('kb.Move Failed')
});
return (
<MyModal isOpen={true} maxW={['90vw', '800px']} w={'800px'} onClose={onClose}>
<Flex flexDirection={'column'} h={['90vh', 'auto']}>
<ModalHeader>
{!!parentId ? (
<Flex flex={1} userSelect={'none'} fontSize={['sm', 'lg']} fontWeight={'normal'}>
{paths.map((item, i) => (
<Flex key={item.parentId} mr={2} alignItems={'center'}>
<Box
borderRadius={'md'}
{...(i === paths.length - 1
? {
cursor: 'default'
}
: {
cursor: 'pointer',
_hover: {
color: 'myBlue.600'
},
onClick: () => {
setParentId(item.parentId);
}
})}
>
{item.parentName}
</Box>
{i !== paths.length - 1 && (
<MyIcon name={'rightArrowLight'} color={'myGray.500'} w={['18px', '24px']} />
)}
</Flex>
))}
</Flex>
) : (
<Box></Box>
)}
</ModalHeader>
<ModalBody
flex={['1 0 0', '0 0 auto']}
maxH={'80vh'}
overflowY={'auto'}
display={'grid'}
userSelect={'none'}
>
<Grid
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)', 'repeat(3,1fr)']}
gridGap={3}
>
{folderList.map((item) =>
(() => {
return (
<MyTooltip
key={item._id}
label={
item.type === KbTypeEnum.dataset
? t('kb.Select Dataset')
: t('kb.Select Folder')
}
>
<Card
p={3}
border={theme.borders.base}
boxShadow={'sm'}
h={'80px'}
cursor={'pointer'}
_hover={{
boxShadow: 'md'
}}
onClick={() => {
setParentId(item._id);
}}
>
<Flex alignItems={'center'} h={'38px'}>
<Avatar src={item.avatar} w={['24px', '28px']}></Avatar>
<Box
className="textEllipsis"
ml={3}
fontWeight={'bold'}
fontSize={['md', 'lg', 'xl']}
>
{item.name}
</Box>
</Flex>
<Flex justifyContent={'flex-end'} alignItems={'center'} fontSize={'sm'}>
{item.type === KbTypeEnum.folder ? (
<Box color={'myGray.500'}>{t('Folder')}</Box>
) : (
<>
<MyIcon mr={1} name="kbTest" w={'12px'} />
<Box color={'myGray.500'}>{item.vectorModel.name}</Box>
</>
)}
</Flex>
</Card>
</MyTooltip>
);
})()
)}
</Grid>
{folderList.length === 0 && (
<Flex mt={5} flexDirection={'column'} alignItems={'center'}>
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
<Box mt={2} color={'myGray.500'}>
{t('kb.No Folder')}
</Box>
</Flex>
)}
</ModalBody>
<ModalFooter>
<Button isLoading={isLoading} onClick={mutate}>
{t('kb.Confirm move the folder')}
</Button>
</ModalFooter>
</Flex>
</MyModal>
);
};
export default MoveModal;

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import React, { useMemo, useRef, useState } from 'react';
import {
Box,
Flex,
@@ -6,7 +6,6 @@ import {
useTheme,
useDisclosure,
Card,
IconButton,
MenuButton,
Image
} from '@chakra-ui/react';
@@ -16,8 +15,7 @@ import PageContainer from '@/components/PageContainer';
import { useConfirm } from '@/hooks/useConfirm';
import { AddIcon } from '@chakra-ui/icons';
import { useQuery } from '@tanstack/react-query';
import { useToast } from '@/hooks/useToast';
import { delKbById, getKbPaths } from '@/api/plugins/kb';
import { delKbById, getKbPaths, putKbById } from '@/api/plugins/kb';
import { useTranslation } from 'react-i18next';
import Avatar from '@/components/Avatar';
import MyIcon from '@/components/Icon';
@@ -28,16 +26,17 @@ import Tag from '@/components/Tag';
import MyMenu from '@/components/MyMenu';
import { useRequest } from '@/hooks/useRequest';
import { useGlobalStore } from '@/store/global';
import { useEditInfo } from '@/hooks/useEditInfo';
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 { toast } = useToast();
const { setLoading } = useGlobalStore();
const DeleteTipsMap = useRef({
@@ -49,7 +48,13 @@ const Kb = () => {
title: t('common.Delete Warning'),
content: ''
});
const { myKbList, loadKbList, setKbList } = useDatasetStore();
const { myKbList, loadKbList, setKbList, updateDataset } = useDatasetStore();
const { onOpenModal: onOpenTitleModal, EditModal: EditTitleModal } = useEditInfo({
title: t('Rename')
});
const [moveDataId, setMoveDataId] = useState<string>();
const [dragStartId, setDragStartId] = useState<string>();
const [dragTargetId, setDragTargetId] = useState<string>();
const {
isOpen: isOpenCreateModal,
@@ -102,8 +107,8 @@ const Kb = () => {
{paths.map((item, i) => (
<Flex key={item.parentId} mr={2} alignItems={'center'}>
<Box
fontSize={'lg'}
px={2}
fontSize={['sm', 'lg']}
px={[0, 2]}
py={1}
borderRadius={'md'}
{...(i === paths.length - 1
@@ -126,7 +131,9 @@ const Kb = () => {
>
{item.parentName}
</Box>
{i !== paths.length - 1 && <MyIcon name={'rightArrowLight'} color={'myGray.500'} />}
{i !== paths.length - 1 && (
<MyIcon name={'rightArrowLight'} color={'myGray.500'} w={['18px', '24px']} />
)}
</Flex>
))}
</Flex>
@@ -184,6 +191,7 @@ const Kb = () => {
p={5}
gridTemplateColumns={['1fr', 'repeat(3,1fr)', 'repeat(4,1fr)', 'repeat(5,1fr)']}
gridGap={5}
userSelect={'none'}
>
{myKbList.map((kb) => (
<Card
@@ -196,8 +204,36 @@ const Kb = () => {
h={'130px'}
border={theme.borders.md}
boxShadow={'none'}
userSelect={'none'}
position={'relative'}
data-drag-id={kb.type === KbTypeEnum.folder ? kb._id : undefined}
borderColor={dragTargetId === kb._id ? 'myBlue.600' : ''}
draggable
onDragStart={(e) => {
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',
@@ -223,33 +259,85 @@ const Kb = () => {
}
}}
>
<MyMenu
offset={[-30, 10]}
width={120}
Button={
<MenuButton
position={'absolute'}
top={3}
right={3}
w={'22px'}
h={'22px'}
borderRadius={'md'}
_hover={{
color: 'myBlue.600',
'& .icon': {
bg: 'myGray.100'
}
}}
onClick={(e) => {
e.stopPropagation();
}}
>
<MyIcon
className="icon"
name={'more'}
h={'16px'}
w={'16px'}
px={1}
py={1}
borderRadius={'md'}
cursor={'pointer'}
/>
</MenuButton>
}
menuList={[
{
child: (
<Flex alignItems={'center'}>
<MyIcon name={'edit'} w={'14px'} mr={2} />
{t('Rename')}
</Flex>
),
onClick: () =>
onOpenTitleModal({
defaultVal: kb.name,
onSuccess: (val) => {
if (val === kb.name || !val) return;
updateDataset({ id: kb._id, name: val });
}
})
},
{
child: (
<Flex alignItems={'center'}>
<MyIcon name={'moveLight'} w={'14px'} mr={2} />
{t('Move')}
</Flex>
),
onClick: () => setMoveDataId(kb._id)
},
{
child: (
<Flex alignItems={'center'}>
<MyIcon name={'delete'} w={'14px'} mr={2} />
{t('common.Delete')}
</Flex>
),
onClick: () => {
openConfirm(
() => onclickDelKb(kb._id),
undefined,
DeleteTipsMap.current[kb.type]
)();
}
}
]}
/>
<Flex alignItems={'center'} h={'38px'}>
<Avatar src={kb.avatar} borderRadius={'lg'} w={'28px'} />
<Box ml={3}>{kb.name}</Box>
<IconButton
className="delete"
position={'absolute'}
top={4}
right={4}
size={'sm'}
icon={<MyIcon name={'delete'} w={'14px'} />}
variant={'base'}
borderRadius={'md'}
aria-label={'delete'}
display={['', 'none']}
_hover={{
bg: 'red.100'
}}
onClick={(e) => {
e.stopPropagation();
openConfirm(
() => onclickDelKb(kb._id),
undefined,
DeleteTipsMap.current[kb.type]
)();
}}
/>
</Flex>
<Box flex={'1 0 0'} overflow={'hidden'} pt={2}>
<Flex>
@@ -282,6 +370,7 @@ const Kb = () => {
</Flex>
)}
<ConfirmModal />
<EditTitleModal />
{isOpenCreateModal && <CreateModal onClose={onCloseCreateModal} parentId={parentId} />}
{!!editFolderData && (
<EditFolderModal
@@ -291,6 +380,16 @@ const Kb = () => {
{...editFolderData}
/>
)}
{!!moveDataId && (
<MoveModal
moveDataId={moveDataId}
onClose={() => setMoveDataId('')}
onSuccess={() => {
refetch();
setMoveDataId('');
}}
/>
)}
</PageContainer>
);
};

View File

@@ -3,8 +3,9 @@ import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
import { type KbTestItemType } from '@/types/plugin';
import type { KbItemType, KbListItemType } from '@/types/plugin';
import { getKbList, getKbById, getAllDataset } from '@/api/plugins/kb';
import { getKbList, getKbById, getAllDataset, putKbById } from '@/api/plugins/kb';
import { defaultKbDetail } from '@/constants/kb';
import { KbUpdateParams } from '@/api/request/kb';
type State = {
datasets: KbListItemType[];
@@ -14,6 +15,7 @@ type State = {
setKbList(val: KbListItemType[]): void;
kbDetail: KbItemType;
getKbDetail: (id: string, init?: boolean) => Promise<KbItemType>;
updateDataset: (data: KbUpdateParams) => Promise<any>;
kbTestList: KbTestItemType[];
pushKbTestItem: (data: KbTestItemType) => void;
@@ -34,8 +36,8 @@ export const useDatasetStore = create<State>()(
return res;
},
myKbList: [],
async loadKbList(parentId) {
const res = await getKbList(parentId);
async loadKbList(parentId = '') {
const res = await getKbList({ parentId });
set((state) => {
state.myKbList = res;
});
@@ -58,6 +60,28 @@ export const useDatasetStore = create<State>()(
return data;
},
async updateDataset(data) {
if (get().kbDetail._id === data.id) {
set((state) => {
state.kbDetail = {
...state.kbDetail,
...data
};
});
}
set((state) => {
state.myKbList = state.myKbList = state.myKbList.map((item) =>
item._id === data.id
? {
...item,
...data,
tags: data.tags?.split(' ') || []
}
: item
);
});
await putKbById(data);
},
kbTestList: [],
pushKbTestItem(data) {
set((state) => {