feat: select dataset

This commit is contained in:
archer 2023-09-10 14:30:32 +08:00
parent ce47c96b9f
commit b40561ad37
No known key found for this signature in database
GPG Key ID: 569A5660D2379E28
18 changed files with 347 additions and 198 deletions

View File

@ -23,6 +23,7 @@ import { QuoteItemType } from '@/types/chat';
/* knowledge base */
export const getKbList = (parentId?: string) =>
GET<KbListItemType[]>(`/plugins/kb/list`, { parentId });
export const getAllDataset = () => GET<KbListItemType[]>(`/plugins/kb/allDataset`);
export const getKbPaths = (parentId?: string) =>
GET<KbPathItemType[]>('/plugins/kb/paths', { parentId });

View File

@ -12,7 +12,7 @@ import {
import MyModal from '../MyModal';
import { useTranslation } from 'next-i18next';
import { useQuery } from '@tanstack/react-query';
import { useUserStore } from '@/store/user';
import { useDatasetStore } from '@/store/dataset';
import { useToast } from '@/hooks/useToast';
import Avatar from '../Avatar';
import MyIcon from '@/components/Icon';
@ -29,7 +29,7 @@ const SelectDataset = ({
const theme = useTheme();
const { isPc } = useGlobalStore();
const { toast } = useToast();
const { myKbList, loadKbList } = useUserStore();
const { myKbList, loadKbList } = useDatasetStore();
const [selectedId, setSelectedId] = useState<string>();
useQuery(['loadKbList'], () => loadKbList());

View File

@ -0,0 +1,34 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, KB } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { getVectorModel } from '@/service/utils/data';
import { KbListItemType } from '@/types/plugin';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
// 凭证校验
const { userId } = await authUser({ req, authToken: true });
await connectToDatabase();
const kbList = await KB.find({
userId,
type: 'dataset'
});
const data = kbList.map((item) => ({
...item.toJSON(),
vectorModel: getVectorModel(item.vectorModel)
}));
jsonRes<KbListItemType[]>(res, {
data
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
import { NodeProps } from 'reactflow';
import { FlowModuleItemType } from '@/types/flow';
import { Flex, Box, Button, useTheme, useDisclosure, Grid } from '@chakra-ui/react';
import { useUserStore } from '@/store/user';
import { useDatasetStore } from '@/store/dataset';
import { useQuery } from '@tanstack/react-query';
import NodeCard from '../modules/NodeCard';
import Divider from '../modules/Divider';
@ -21,7 +21,7 @@ const KBSelect = ({
onChange: (e: SelectedKbType) => void;
}) => {
const theme = useTheme();
const { myKbList, loadKbList } = useUserStore();
const { datasets, loadAllDatasets } = useDatasetStore();
const {
isOpen: isOpenKbSelect,
onOpen: onOpenKbSelect,
@ -29,11 +29,11 @@ const KBSelect = ({
} = useDisclosure();
const showKbList = useMemo(
() => myKbList.filter((item) => activeKbs.find((kb) => kb.kbId === item._id)),
[myKbList, activeKbs]
() => datasets.filter((item) => activeKbs.find((kb) => kb.kbId === item._id)),
[datasets, activeKbs]
);
useQuery(['initkb'], () => loadKbList());
useQuery(['loadAllDatasets'], loadAllDatasets);
return (
<>
@ -58,12 +58,7 @@ const KBSelect = ({
))}
</Grid>
{isOpenKbSelect && (
<KBSelectModal
kbList={myKbList}
activeKbs={activeKbs}
onChange={onChange}
onClose={onCloseKbSelect}
/>
<KBSelectModal activeKbs={activeKbs} onChange={onChange} onClose={onCloseKbSelect} />
)}
</>
);

View File

@ -56,18 +56,21 @@ import MyIcon from '@/components/Icon';
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
import { addVariable } from '../VariableEditModal';
import { KBSelectModal, KbParamsModal } from '../KBSelectModal';
import { KbParamsModal } from '../KBSelectModal';
import { AppTypeEnum } from '@/constants/app';
import { useDatasetStore } from '@/store/dataset';
const VariableEditModal = dynamic(() => import('../VariableEditModal'));
const InfoModal = dynamic(() => import('../InfoModal'));
const KBSelectModal = dynamic(() => import('../KBSelectModal'));
const Settings = ({ appId }: { appId: string }) => {
const theme = useTheme();
const router = useRouter();
const { t } = useTranslation();
const { toast } = useToast();
const { appDetail, updateAppDetail, loadKbList, myKbList } = useUserStore();
const { appDetail, updateAppDetail } = useUserStore();
const { loadAllDatasets, datasets } = useDatasetStore();
const { isPc } = useGlobalStore();
const [editVariable, setEditVariable] = useState<VariableItemType>();
@ -122,8 +125,8 @@ const Settings = ({ appId }: { appId: string }) => {
);
}, [getValues, refresh]);
const selectedKbList = useMemo(
() => myKbList.filter((item) => kbList.find((kb) => kb.kbId === item._id)),
[myKbList, kbList]
() => datasets.filter((item) => kbList.find((kb) => kb.kbId === item._id)),
[datasets, kbList]
);
/* 点击删除 */
@ -167,7 +170,7 @@ const Settings = ({ appId }: { appId: string }) => {
appModule2Form();
}, [appModule2Form]);
useQuery(['initkb', appId], () => loadKbList());
useQuery(['loadAllDatasets'], loadAllDatasets);
const BoxStyles: BoxProps = {
bg: 'myWhite.200',
@ -304,6 +307,23 @@ const Settings = ({ appId }: { appId: string }) => {
</Button>
</Flex>
{/* welcome */}
<Box mt={5} {...BoxStyles}>
<Flex alignItems={'center'}>
<Avatar src={'/imgs/module/userGuide.png'} w={'18px'} />
<Box mx={2}></Box>
<MyTooltip label={welcomeTextTip} forceShow>
<QuestionOutlineIcon />
</MyTooltip>
</Flex>
<Textarea
mt={2}
rows={5}
placeholder={welcomeTextTip}
borderColor={'myGray.100'}
{...register('guide.welcome.text')}
/>
</Box>
{/* variable */}
<Box mt={2} {...BoxStyles}>
<Flex alignItems={'center'}>
@ -498,24 +518,6 @@ const Settings = ({ appId }: { appId: string }) => {
</Grid>
</Box>
{/* welcome */}
<Box mt={5} {...BoxStyles}>
<Flex alignItems={'center'}>
<Avatar src={'/imgs/module/userGuide.png'} w={'18px'} />
<Box mx={2}></Box>
<MyTooltip label={welcomeTextTip} forceShow>
<QuestionOutlineIcon />
</MyTooltip>
</Flex>
<Textarea
mt={2}
rows={5}
placeholder={welcomeTextTip}
borderColor={'myGray.100'}
{...register('guide.welcome.text')}
/>
</Box>
<ConfirmSaveModal />
<ConfirmDelModal />
{settingAppInfo && (
@ -548,7 +550,6 @@ const Settings = ({ appId }: { appId: string }) => {
)}
{isOpenKbSelect && (
<KBSelectModal
kbList={myKbList}
activeKbs={selectedKbList.map((item) => ({
kbId: item._id,
vectorModel: item.vectorModel

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useMemo, useState } from 'react';
import {
Card,
Flex,
@ -8,18 +8,25 @@ import {
ModalHeader,
ModalFooter,
useTheme,
Textarea
Textarea,
Grid,
Divider
} from '@chakra-ui/react';
import { getKbPaths } from '@/api/plugins/kb';
import Avatar from '@/components/Avatar';
import { useForm } from 'react-hook-form';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import type { KbListItemType, SelectedKbType } from '@/types/plugin';
import type { SelectedKbType } from '@/types/plugin';
import { useGlobalStore } from '@/store/global';
import { useToast } from '@/hooks/useToast';
import MySlider from '@/components/Slider';
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 { useDatasetStore } from '@/store/dataset';
export type KbParamsType = {
searchSimilarity: number;
@ -28,20 +35,42 @@ export type KbParamsType = {
};
export const KBSelectModal = ({
kbList,
activeKbs = [],
onChange,
onClose
}: {
kbList: KbListItemType[];
activeKbs: SelectedKbType;
onChange: (e: SelectedKbType) => void;
onClose: () => void;
}) => {
const { t } = useTranslation();
const theme = useTheme();
const [selectedKbList, setSelectedKbList] = useState<SelectedKbType>(activeKbs);
const { isPc } = useGlobalStore();
const { toast } = useToast();
const [parentId, setParentId] = useState<string>();
const { myKbList, loadKbList, datasets, loadAllDatasets } = useDatasetStore();
const { data } = useQuery(['loadKbList', parentId], () => {
return Promise.all([loadKbList(parentId), getKbPaths(parentId)]);
});
useQuery(['loadAllDatasets'], loadAllDatasets);
const paths = useMemo(
() => [
{
parentId: '',
parentName: t('kb.My Dataset')
},
...(data?.[1] || [])
],
[data, t]
);
const filterKbList = useMemo(() => {
return {
selected: datasets.filter((item) => selectedKbList.find((kb) => kb.kbId === item._id)),
unSelected: myKbList.filter((item) => !selectedKbList.find((kb) => kb.kbId === item._id))
};
}, [myKbList, datasets, selectedKbList]);
return (
<MyModal
@ -53,10 +82,43 @@ export const KBSelectModal = ({
>
<Flex flexDirection={'column'} h={['90vh', 'auto']}>
<ModalHeader>
<Box>({selectedKbList.length})</Box>
<Box fontSize={'sm'} color={'myGray.500'} fontWeight={'normal'}>
</Box>
{!!parentId ? (
<Flex flex={1}>
{paths.map((item, i) => (
<Flex key={item.parentId} mr={2} alignItems={'center'}>
<Box
fontSize={'lg'}
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'} />
)}
</Flex>
))}
</Flex>
) : (
<Box>({selectedKbList.length})</Box>
)}
{isPc && (
<Box fontSize={'sm'} color={'myGray.500'} fontWeight={'normal'}>
</Box>
)}
</ModalHeader>
<ModalBody
@ -64,72 +126,119 @@ export const KBSelectModal = ({
maxH={'80vh'}
overflowY={'auto'}
display={'grid'}
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)', 'repeat(3,1fr)']}
gridGap={3}
userSelect={'none'}
>
{kbList.map((item) =>
(() => {
const selected = !!selectedKbList.find((kb) => kb.kbId === item._id);
const active = !!activeKbs.find((kb) => kb.kbId === item._id);
return (
<Card
key={item._id}
p={3}
border={theme.borders.base}
boxShadow={'sm'}
h={'80px'}
cursor={'pointer'}
order={active ? 0 : 1}
_hover={{
boxShadow: 'md'
}}
{...(selected
? {
bg: 'myBlue.300'
}
: {})}
onClick={() => {
if (selected) {
setSelectedKbList((state) => state.filter((kb) => kb.kbId !== item._id));
} else {
const vectorModel = selectedKbList[0]?.vectorModel?.model;
<Grid
h={'auto'}
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)', 'repeat(3,1fr)']}
gridGap={3}
>
{filterKbList.selected.map((item) =>
(() => {
return (
<Card
key={item._id}
p={3}
border={theme.borders.base}
boxShadow={'sm'}
bg={'myBlue.300'}
>
<Flex alignItems={'center'} h={'38px'}>
<Avatar src={item.avatar} w={['24px', '28px']}></Avatar>
<Box flex={'1 0 0'} mx={3}>
{item.name}
</Box>
<MyIcon
name={'delete'}
w={'14px'}
cursor={'pointer'}
_hover={{ color: 'red.500' }}
onClick={() => {
setSelectedKbList((state) => state.filter((kb) => kb.kbId !== item._id));
}}
/>
</Flex>
</Card>
);
})()
)}
</Grid>
if (vectorModel && vectorModel !== item.vectorModel.model) {
return toast({
status: 'warning',
title: '仅能选择同一个索引模型的知识库'
});
{filterKbList.selected.length > 0 && <Divider my={3} />}
<Grid
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)', 'repeat(3,1fr)']}
gridGap={3}
>
{filterKbList.unSelected.map((item) =>
(() => {
return (
<Card
key={item._id}
p={3}
border={theme.borders.base}
boxShadow={'sm'}
h={'80px'}
cursor={'pointer'}
_hover={{
boxShadow: 'md'
}}
onClick={() => {
if (item.type === KbTypeEnum.folder) {
setParentId(item._id);
} else if (item.type === KbTypeEnum.dataset) {
const vectorModel = selectedKbList[0]?.vectorModel?.model;
if (vectorModel && vectorModel !== item.vectorModel.model) {
return toast({
status: 'warning',
title: '仅能选择同一个索引模型的知识库'
});
}
setSelectedKbList((state) => [
...state,
{ kbId: item._id, vectorModel: item.vectorModel }
]);
}
setSelectedKbList((state) => [
...state,
{ kbId: item._id, vectorModel: item.vectorModel }
]);
}
}}
>
<Flex alignItems={'center'} h={'38px'}>
<Avatar src={item.avatar} w={['24px', '28px', '32px']}></Avatar>
<Box ml={3} fontWeight={'bold'} fontSize={['md', 'lg', 'xl']}>
{item.name}
</Box>
</Flex>
<Flex justifyContent={'flex-end'} alignItems={'center'} fontSize={'sm'}>
<MyIcon mr={1} name="kbTest" w={'12px'} />
<Box color={'myGray.500'}>{item.vectorModel.name}</Box>
</Flex>
</Card>
);
})()
}}
>
<Flex alignItems={'center'} h={'38px'}>
<Avatar src={item.avatar} w={['24px', '28px', '32px']}></Avatar>
<Box 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>
);
})()
)}
</Grid>
{filterKbList.unSelected.length === 0 && (
<Flex mt={5} flexDirection={'column'} alignItems={'center'}>
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
<Box mt={2} color={'myGray.500'}>
西~
</Box>
</Flex>
)}
</ModalBody>
<ModalFooter>
<Button
onClick={() => {
// filter out the kb that is not in the kbList
// filter out the kb that is not in the kList
const filterKbList = selectedKbList.filter((kb) => {
return kbList.find((item) => item._id === kb.kbId);
return datasets.find((item) => item._id === kb.kbId);
});
onClose();

View File

@ -26,12 +26,12 @@ import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { TrainingModeEnum } from '@/constants/plugin';
import FileSelect, { type FileItemType } from './FileSelect';
import { useUserStore } from '@/store/user';
import { useDatasetStore } from '@/store/dataset';
const fileExtension = '.txt, .doc, .docx, .pdf, .md';
const ChunkImport = ({ kbId }: { kbId: string }) => {
const { kbDetail } = useUserStore();
const { kbDetail } = useDatasetStore();
const vectorModel = kbDetail.vectorModel;
const unitPrice = vectorModel?.price || 0.2;

View File

@ -10,12 +10,12 @@ import DeleteIcon, { hoverDeleteStyles } from '@/components/Icon/delete';
import { TrainingModeEnum } from '@/constants/plugin';
import FileSelect, { type FileItemType } from './FileSelect';
import { useRouter } from 'next/router';
import { useUserStore } from '@/store/user';
import { useDatasetStore } from '@/store/dataset';
const fileExtension = '.csv';
const CsvImport = ({ kbId }: { kbId: string }) => {
const { kbDetail } = useUserStore();
const { kbDetail } = useDatasetStore();
const maxToken = kbDetail.vectorModel?.maxToken || 2000;
const theme = useTheme();

View File

@ -19,7 +19,7 @@ import dynamic from 'next/dynamic';
import MyTooltip from '@/components/MyTooltip';
import { FetchResultItem, DatasetItemType } from '@/types/plugin';
import { getErrText } from '@/utils/tools';
import { useUserStore } from '@/store/user';
import { useDatasetStore } from '@/store/dataset';
const UrlFetchModal = dynamic(() => import('./UrlFetchModal'));
const CreateFileModal = dynamic(() => import('./CreateFileModal'));
@ -55,7 +55,7 @@ const FileSelect = ({
showCreateFile = true,
...props
}: Props) => {
const { kbDetail } = useUserStore();
const { kbDetail } = useDatasetStore();
const { Loading: FileSelectLoading } = useLoading();
const { t } = useTranslation();

View File

@ -6,14 +6,14 @@ import { useRequest } from '@/hooks/useRequest';
import { getErrText } from '@/utils/tools';
import { postKbDataFromList } from '@/api/plugins/kb';
import { TrainingModeEnum } from '@/constants/plugin';
import { useUserStore } from '@/store/user';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { useDatasetStore } from '@/store/dataset';
type ManualFormType = { q: string; a: string };
const ManualImport = ({ kbId }: { kbId: string }) => {
const { kbDetail } = useUserStore();
const { kbDetail } = useDatasetStore();
const maxToken = kbDetail.vectorModel?.maxToken || 2000;
const { register, handleSubmit, reset } = useForm({

View File

@ -12,7 +12,7 @@ import { QuestionOutlineIcon, DeleteIcon } from '@chakra-ui/icons';
import { delKbById, putKbById } from '@/api/plugins/kb';
import { useSelectFile } from '@/hooks/useSelectFile';
import { useToast } from '@/hooks/useToast';
import { useUserStore } from '@/store/user';
import { useDatasetStore } from '@/store/dataset';
import { useConfirm } from '@/hooks/useConfirm';
import { UseFormReturn } from 'react-hook-form';
import { compressImg } from '@/utils/file';
@ -47,7 +47,7 @@ const Info = (
multiple: false
});
const { kbDetail, getKbDetail, loadKbList, myKbList } = useUserStore();
const { kbDetail, getKbDetail, loadKbList } = useDatasetStore();
/* 点击删除 */
const onclickDelKb = useCallback(async () => {

View File

@ -9,10 +9,10 @@ import MyIcon from '@/components/Icon';
import MyModal from '@/components/MyModal';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { useUserStore } from '@/store/user';
import { useQuery } from '@tanstack/react-query';
import { DatasetItemType } from '@/types/plugin';
import { useTranslation } from 'react-i18next';
import { useDatasetStore } from '@/store/dataset';
export type FormData = { dataId?: string } & DatasetItemType;
@ -36,7 +36,7 @@ const InputDataModal = ({
const [loading, setLoading] = useState(false);
const { toast } = useToast();
const { kbDetail, getKbDetail } = useUserStore();
const { kbDetail, getKbDetail } = useDatasetStore();
const { getValues, register, handleSubmit, reset } = useForm<FormData>({
defaultValues

View File

@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react';
import { Box, Textarea, Button, Flex, useTheme, Grid, Progress } from '@chakra-ui/react';
import { useKbStore } from '@/store/kb';
import { useDatasetStore } from '@/store/dataset';
import type { KbTestItemType } from '@/types/plugin';
import { searchText, getKbDataItemById } from '@/api/plugins/kb';
import MyIcon from '@/components/Icon';
@ -13,16 +13,14 @@ import { useToast } from '@/hooks/useToast';
import { customAlphabet } from 'nanoid';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { useUserStore } from '@/store/user';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
const Test = ({ kbId }: { kbId: string }) => {
const { kbDetail } = useUserStore();
const theme = useTheme();
const { toast } = useToast();
const { setLoading } = useGlobalStore();
const { kbTestList, pushKbTestItem, delKbTestItemById, updateKbItemById } = useKbStore();
const { kbDetail, kbTestList, pushKbTestItem, delKbTestItemById, updateKbItemById } =
useDatasetStore();
const [inputText, setInputText] = useState('');
const [kbTestItem, setKbTestItem] = useState<KbTestItemType>();
const [editData, setEditData] = useState<FormData>();

View File

@ -4,7 +4,6 @@ import { Box, Flex, IconButton, useTheme } from '@chakra-ui/react';
import { useToast } from '@/hooks/useToast';
import { useForm } from 'react-hook-form';
import { useQuery } from '@tanstack/react-query';
import { useUserStore } from '@/store/user';
import { KbItemType } from '@/types/plugin';
import { getErrText } from '@/utils/tools';
import { useGlobalStore } from '@/store/global';
@ -24,6 +23,7 @@ import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { feConfigs } from '@/store/static';
import Script from 'next/script';
import FileCard from './components/FileCard';
import { useDatasetStore } from '@/store/dataset';
const DataCard = dynamic(() => import('./components/DataCard'), {
ssr: false
@ -50,7 +50,7 @@ const Detail = ({ kbId, currentTab }: { kbId: string; currentTab: `${TabEnum}` }
const { toast } = useToast();
const router = useRouter();
const { isPc } = useGlobalStore();
const { kbDetail, getKbDetail } = useUserStore();
const { kbDetail, getKbDetail } = useDatasetStore();
const tabList = useRef([
{ label: '数据集', id: TabEnum.dataset, icon: 'overviewLight' },

View File

@ -11,7 +11,7 @@ import {
Image
} from '@chakra-ui/react';
import { useRouter } from 'next/router';
import { useUserStore } from '@/store/user';
import { useDatasetStore } from '@/store/dataset';
import PageContainer from '@/components/PageContainer';
import { useConfirm } from '@/hooks/useConfirm';
import { AddIcon } from '@chakra-ui/icons';
@ -49,7 +49,7 @@ const Kb = () => {
title: t('common.Delete Warning'),
content: ''
});
const { myKbList, loadKbList, setKbList } = useUserStore();
const { myKbList, loadKbList, setKbList } = useDatasetStore();
const {
isOpen: isOpenCreateModal,

View File

@ -0,0 +1,86 @@
import { create } from 'zustand';
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 { defaultKbDetail } from '@/constants/kb';
type State = {
datasets: KbListItemType[];
loadAllDatasets: () => Promise<KbListItemType[]>;
myKbList: KbListItemType[];
loadKbList: (parentId?: string) => Promise<any>;
setKbList(val: KbListItemType[]): void;
kbDetail: KbItemType;
getKbDetail: (id: string, init?: boolean) => Promise<KbItemType>;
kbTestList: KbTestItemType[];
pushKbTestItem: (data: KbTestItemType) => void;
delKbTestItemById: (id: string) => void;
updateKbItemById: (data: KbTestItemType) => void;
};
export const useDatasetStore = create<State>()(
devtools(
persist(
immer((set, get) => ({
datasets: [],
async loadAllDatasets() {
const res = await getAllDataset();
set((state) => {
state.datasets = res;
});
return res;
},
myKbList: [],
async loadKbList(parentId) {
const res = await getKbList(parentId);
set((state) => {
state.myKbList = res;
});
return res;
},
setKbList(val) {
set((state) => {
state.myKbList = val;
});
},
kbDetail: defaultKbDetail,
async getKbDetail(id: string, init = false) {
if (id === get().kbDetail._id && !init) return get().kbDetail;
const data = await getKbById(id);
set((state) => {
state.kbDetail = data;
});
return data;
},
kbTestList: [],
pushKbTestItem(data) {
set((state) => {
state.kbTestList = [data, ...state.kbTestList].slice(0, 500);
});
},
delKbTestItemById(id) {
set((state) => {
state.kbTestList = state.kbTestList.filter((item) => item.id !== id);
});
},
updateKbItemById(data: KbTestItemType) {
set((state) => {
state.kbTestList = state.kbTestList.map((item) => (item.id === data.id ? data : item));
});
}
})),
{
name: 'kbStore',
partialize: (state) => ({
kbTestList: state.kbTestList
})
}
)
)
);

View File

@ -1,42 +0,0 @@
import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
import { type KbTestItemType } from '@/types/plugin';
type State = {
kbTestList: KbTestItemType[];
pushKbTestItem: (data: KbTestItemType) => void;
delKbTestItemById: (id: string) => void;
updateKbItemById: (data: KbTestItemType) => void;
};
export const useKbStore = create<State>()(
devtools(
persist(
immer((set, get) => ({
kbTestList: [],
pushKbTestItem(data) {
set((state) => {
state.kbTestList = [data, ...state.kbTestList].slice(0, 500);
});
},
delKbTestItemById(id) {
set((state) => {
state.kbTestList = state.kbTestList.filter((item) => item.id !== id);
});
},
updateKbItemById(data: KbTestItemType) {
set((state) => {
state.kbTestList = state.kbTestList.map((item) => (item.id === data.id ? data : item));
});
}
})),
{
name: 'kbStore',
partialize: (state) => ({
kbTestList: state.kbTestList
})
}
)
)
);

View File

@ -7,9 +7,7 @@ import { formatPrice } from '@/utils/user';
import { getTokenLogin, putUserInfo } from '@/api/user';
import { defaultApp } from '@/constants/model';
import { AppListItemType, AppUpdateParams } from '@/types/app';
import type { KbItemType, KbListItemType } from '@/types/plugin';
import { getKbList, getKbById, putKbById } from '@/api/plugins/kb';
import { defaultKbDetail } from '@/constants/kb';
import type { AppSchema } from '@/types/mongoSchema';
type State = {
@ -24,12 +22,6 @@ type State = {
loadAppDetail: (id: string, init?: boolean) => Promise<AppSchema>;
updateAppDetail(appId: string, data: AppUpdateParams): Promise<void>;
clearAppModules(): void;
// kb
myKbList: KbListItemType[];
loadKbList: (parentId?: string) => Promise<any>;
setKbList(val: KbListItemType[]): void;
kbDetail: KbItemType;
getKbDetail: (id: string, init?: boolean) => Promise<KbItemType>;
};
export const useUserStore = create<State>()(
@ -106,31 +98,6 @@ export const useUserStore = create<State>()(
modules: []
};
});
},
myKbList: [],
async loadKbList(parentId) {
const res = await getKbList(parentId);
set((state) => {
state.myKbList = res;
});
return res;
},
setKbList(val) {
set((state) => {
state.myKbList = val;
});
},
kbDetail: defaultKbDetail,
async getKbDetail(id: string, init = false) {
if (id === get().kbDetail._id && !init) return get().kbDetail;
const data = await getKbById(id);
set((state) => {
state.kbDetail = data;
});
return data;
}
})),
{