李富豪 преди 10 месеца
родител
ревизия
740b32f58b

+ 46 - 0
src/apis/index.ts

@@ -6,16 +6,32 @@ export type LoginApiParams = {
     password: string,
 };
 
+export type FetchAppListApiParams = {
+    pageNumber: number,
+    pageSize: number,
+};
+
 export type FetchKnowledgeLibListApiParams = {
     pageNumber: number,
     pageSize: number,
 };
 
+export type CreateOrModifyKnowledgeLibApiParams = {
+    name: string,
+    embeddingId: string,
+    description: string,
+};
+
 // Api函数类型
 export type LoginApi = (data: LoginApiParams) => Promise<any>;
 export type LogoutApi = () => Promise<any>;
+export type FetchAppListApi = (data: FetchAppListApiParams) => Promise<any>;
 export type FetchKnowledgeLibListApi = (data: FetchKnowledgeLibListApiParams) => Promise<any>;
+export type FetchEmbeddingListApi = () => Promise<any>;
+export type CreateKnowledgeLibApi = (data: CreateOrModifyKnowledgeLibApiParams) => Promise<any>;
+export type ModifyKnowledgeLibApi = (knowledgeId: string, data: CreateOrModifyKnowledgeLibApiParams) => Promise<any>;
 export type DeleteKnowledgeLibApi = (knowledgeId: string) => Promise<any>;
+export type FetchKnowledgeLibDetailApi = (knowledgeId: string) => Promise<any>;
 
 // 登录
 const loginApi: LoginApi = async (data) => {
@@ -27,19 +43,49 @@ const logoutApi: LogoutApi = async () => {
     return api.post('/logout', {});
 };
 
+// 获取应用列表
+const fetchAppListApi: FetchAppListApi = async (data) => {
+    return api.post('/bigmodel/api/getApplicationList', data);
+};
+
 // 获取知识库列表
 const fetchKnowledgeLibListApi: FetchKnowledgeLibListApi = async (data) => {
     return api.post('bigmodel/api/knowledgeList', data);
 };
 
+// 获取向量化模型列表
+const fetchEmbeddingListApi: FetchEmbeddingListApi = async () => {
+    return api.get('bigmodel/api/embedding');
+};
+
+// 创建知识库
+const createKnowledgeLibApi: CreateKnowledgeLibApi = async (data) => {
+    return api.post('bigmodel/api/createKnowledge', data);
+};
+
+// 修改知识库
+const modifyKnowledgeLibApi: ModifyKnowledgeLibApi = async (knowledgeId, data) => {
+    return api.put(`bigmodel/api/updateKnowledge/${knowledgeId}`, data);
+};
+
 // 删除知识库
 const deleteKnowledgeLibApi: DeleteKnowledgeLibApi = async (knowledgeId) => {
     return api.delete(`bigmodel/api/delKnowledge/${knowledgeId}`);
 };
 
+// 获取知识库详情
+const fetchKnowledgeLibDetailApi: FetchKnowledgeLibDetailApi = async (knowledgeId) => {
+    return api.get(`bigmodel/api/detailKnowledge/${knowledgeId}`);
+};
+
 export const apis = {
     login: loginApi,
     logout: logoutApi,
+    fetchAppList: fetchAppListApi,
     fetchKnowledgeLibList: fetchKnowledgeLibListApi,
+    fetchEmbeddingList: fetchEmbeddingListApi,
+    createKnowledgeLib: createKnowledgeLibApi,
+    modifyKnowledgeLib: modifyKnowledgeLibApi,
     deleteKnowledgeLib: deleteKnowledgeLibApi,
+    fetchKnowledgeLibDetail: fetchKnowledgeLibDetailApi,
 };

+ 3 - 4
src/pages/knowledgeLib/info/index.tsx → src/pages/knowledgeLib/detail/index.tsx

@@ -1,5 +1,5 @@
 import * as React from 'react';
-import { useLocation } from 'react-router-dom';
+import { useParams } from 'react-router-dom';
 import { observer } from 'mobx-react';
 import store from './store';
 import './style.less';
@@ -14,11 +14,10 @@ const KnowledgeLibInfo: React.FC = () => {
         pageLoading
     } = state;
 
-    const location = useLocation();
+    const params = useParams();
 
     React.useEffect(() => {
-        const { knowledgeId } = location.state;
-        init(knowledgeId);
+        init(params.knowledgeId);
         return () => reset();
     }, []);
 

+ 0 - 0
src/pages/knowledgeLib/info/store.ts → src/pages/knowledgeLib/detail/store.ts


+ 0 - 0
src/pages/knowledgeLib/info/style.less → src/pages/knowledgeLib/detail/style.less


+ 0 - 0
src/pages/knowledgeLib/info/types.ts → src/pages/knowledgeLib/detail/types.ts


+ 155 - 0
src/pages/knowledgeLib/list/components/InfoModal.tsx

@@ -0,0 +1,155 @@
+import * as React from 'react';
+import { Modal, Spin, Form, Input, Select, message } from 'antd';
+import { apis, CreateOrModifyKnowledgeLibApiParams } from '@/apis';
+
+const FormItem = Form.Item;
+const { Option } = Select;
+const { TextArea } = Input;
+
+interface Props {
+    id: string,
+    open: boolean,
+    onClickConfirm: (id: string, data: CreateOrModifyKnowledgeLibApiParams) => Promise<any>,
+    onClickCancel: () => void,
+};
+
+const InfoModal: React.FC<Props> = (props: Props) => {
+    const {
+        id,
+        open,
+        onClickConfirm,
+        onClickCancel
+    } = props;
+
+    const [form] = Form.useForm();
+
+    const [loading, setLoading] = React.useState<boolean>(false);
+
+    type EmbeddingList = {
+        label: string,
+        value: string,
+    }[];
+
+    const [embeddingList, setEmbeddingList] = React.useState<EmbeddingList>([]);
+
+    const getTitle = () => {
+        if (id) {
+            return '修改知识库';
+        } else {
+            return '创建知识库';
+        }
+    };
+
+    // 获取向量化模型列表
+    const fetchEmbeddingList = async () => {
+        try {
+            const res = await apis.fetchEmbeddingList();
+            const list = res.data.list.map((item: any) => {
+                return {
+                    label: item.name,
+                    value: item.id,
+                }
+            });
+            setEmbeddingList(list);
+        } catch (error: any) {
+            console.error(error);
+        }
+    }
+
+    // 获取知识库详情
+    const fetchDetail = async () => {
+        try {
+            const res = await apis.fetchKnowledgeLibDetail(props.id);
+            const { name, embedding_id, description } = res.data.detail;
+            form.setFieldsValue({
+                name: name,
+                embeddingId: embedding_id,
+                description: description,
+            });
+        } catch (error: any) {
+            message.error(error.msg);
+        }
+    };
+
+    const init = async () => {
+        setLoading(true);
+        await fetchEmbeddingList();
+        if (props.id) {
+            await fetchDetail();
+        }
+        setLoading(false);
+    };
+
+    React.useEffect(() => {
+        init();
+    }, []);
+
+    // 点击确定
+    const handleClickConfirm = () => {
+        form.validateFields().then(async (values) => {
+            const data = { ...values };
+            await onClickConfirm(props.id, data);
+        }).catch((error) => {
+            console.error(error);
+        });
+    };
+
+    return (
+        <Modal
+            width={500}
+            title={getTitle()}
+            destroyOnClose={true}
+            maskClosable={false}
+            centered={true}
+            open={open}
+            onOk={handleClickConfirm}
+            onCancel={onClickCancel}
+        >
+            <Spin spinning={loading}>
+                <Form form={form} layout='vertical'>
+                    <FormItem
+                        label='知识库名称'
+                        name='name'
+                        rules={[{ required: true, message: '知识库名称不能为空', whitespace: true }]}
+                    >
+                        <Input placeholder='请输入知识库名称' />
+                    </FormItem>
+                    <FormItem
+                        label='向量化模型'
+                        name='embeddingId'
+                        rules={[{ required: true, message: '向量化模型不能为空' }]}
+                    >
+                        <Select
+                            style={{ width: '100%' }}
+                            placeholder='请选择向量化模型'
+                            allowClear={true}
+                        >
+                            {
+                                embeddingList.map((item, index) => {
+                                    return <Option value={item.value} key={index}>
+                                        {item.label}
+                                    </Option>
+                                })
+                            }
+                        </Select>
+                    </FormItem>
+                    <FormItem
+                        label='知识库描述'
+                        name='description'
+                        rules={[{ required: true, message: '知识库描述不能为空', whitespace: true }]}
+                    >
+                        <TextArea
+                            placeholder='知识库描述需要描述清楚知识库中的文件内容,搭建应用时模型会将此作为判断是否获取知识库内容的依据'
+                            showCount={true}
+                            rows={4}
+                            maxLength={100}
+                        />
+                    </FormItem>
+                    <div style={{ width: '100%', height: 10 }}></div>
+                </Form>
+            </Spin>
+        </Modal>
+    );
+};
+
+export default InfoModal;

+ 30 - 12
src/pages/knowledgeLib/list/index.tsx

@@ -1,7 +1,9 @@
 import * as React from 'react';
+import { Link } from 'react-router-dom';
 import { observer } from 'mobx-react';
 import { Button, Table, TableColumnsType, Modal, TablePaginationConfig } from 'antd';
 import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
+import InfoModal from './components/InfoModal';
 import router from '@/router';
 import dayjs from 'dayjs';
 import store from './store';
@@ -12,6 +14,10 @@ const KnowledgeLibList: React.FC = () => {
     const {
         state,
         onChangePagination,
+        onClickCreate,
+        onClickModify,
+        infoModalOnClickConfirm,
+        infoModalOnClickCancel,
         onClickDelete,
         init,
         reset
@@ -19,6 +25,8 @@ const KnowledgeLibList: React.FC = () => {
     const {
         listLoading,
         list,
+        infoModalId,
+        infoModalOpen,
         page
     } = state;
 
@@ -36,13 +44,16 @@ const KnowledgeLibList: React.FC = () => {
                 return index + 1;
             }
         },
-        {
-            title: 'ID',
-            dataIndex: 'id',
-        },
         {
             title: '知识库名称',
             dataIndex: 'name',
+            render: (text, record) => {
+                return (
+                    <Link to={{ pathname: `/knowledgeLib/${record.knowledgeId}` }} >
+                        {text}
+                    </Link>
+                )
+            }
         },
         {
             title: '使用空间',
@@ -54,14 +65,14 @@ const KnowledgeLibList: React.FC = () => {
         },
         {
             title: '字符数量',
-            dataIndex: 'word_num',
+            dataIndex: 'wordNum',
             render: (text) => {
                 return `${text}字`;
             }
         },
         {
             title: '文件数量',
-            dataIndex: 'document_size',
+            dataIndex: 'documentSize',
         },
         {
             title: '创建时间',
@@ -98,7 +109,7 @@ const KnowledgeLibList: React.FC = () => {
                         <a
                             style={{ marginRight: 16 }}
                             onClick={() => {
-                                router.navigate({ pathname: '/knowledgeLib/modify' }, { state: { knowledgeId: record.id } });
+                                onClickModify(record.knowledgeId);
                             }}
                         >
                             <EditOutlined />
@@ -111,7 +122,7 @@ const KnowledgeLibList: React.FC = () => {
                                     content: `确定删除知识库名称${record.name}吗?`,
                                     okType: 'danger',
                                     onOk: async () => {
-                                        await onClickDelete(record.id);
+                                        await onClickDelete(record.knowledgeId);
                                     }
                                 });
                             }}
@@ -149,21 +160,28 @@ const KnowledgeLibList: React.FC = () => {
                 <Button
                     type='primary'
                     icon={<PlusOutlined />}
-                    onClick={() => {
-                        router.navigate({ pathname: '/knowledgeLib/create' });
-                    }}
+                    onClick={onClickCreate}
                 >
                     创建知识库
                 </Button>
             </div>
             <Table
                 scroll={{ x: 'max-content' }}
-                rowKey={(record) => record.id}
+                rowKey={(record) => record.knowledgeId}
                 loading={listLoading}
                 columns={columns}
                 dataSource={list}
                 pagination={paginationConfig}
             />
+            {
+                infoModalOpen &&
+                <InfoModal
+                    id={infoModalId}
+                    open={infoModalOpen}
+                    onClickConfirm={infoModalOnClickConfirm}
+                    onClickCancel={infoModalOnClickCancel}
+                />
+            }
         </div>
     );
 };

+ 75 - 1
src/pages/knowledgeLib/list/store.ts

@@ -1,12 +1,14 @@
 import { makeAutoObservable } from 'mobx';
 import { message } from 'antd';
-import { apis } from '@/apis';
+import { apis, CreateOrModifyKnowledgeLibApiParams } from '@/apis';
 import { State, ReadonlyState, StateAction, KnowledgeLibListStore } from './types';
 
 // 定义状态
 const stateGenerator = (): ReadonlyState => ({
     listLoading: false,
     list: [],
+    infoModalId: '',
+    infoModalOpen: false,
     page: {
         pageNumber: 1,
         pageSize: 10,
@@ -23,6 +25,12 @@ const stateActionsGenerator = (state: State): StateAction => {
         setList: (list) => {
             state.list = list;
         },
+        setInfoModalId: (id) => {
+            state.infoModalId = id;
+        },
+        setInfoModalOpen: (open) => {
+            state.infoModalOpen = open;
+        },
         setPage: (page) => {
             state.page = page;
         },
@@ -55,6 +63,28 @@ const useKnowledgeLibListStore = (): KnowledgeLibListStore => {
                 actions.setListLoading(false);
             }
         },
+        // 创建知识库
+        createKnowledgeLib: async (data: CreateOrModifyKnowledgeLibApiParams) => {
+            try {
+                await apis.createKnowledgeLib(data);
+                // 获取知识库列表
+                await api.fetchKnowledgeLibList();
+                message.success('创建成功');
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+        // 修改知识库
+        modifyKnowledgeLib: async (knowledgeId: string, data: CreateOrModifyKnowledgeLibApiParams) => {
+            try {
+                await apis.modifyKnowledgeLib(knowledgeId, data);
+                // 获取知识库列表
+                await api.fetchKnowledgeLibList();
+                message.success('修改成功');
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
         // 删除知识库
         deleteKnowledgeLib: async (knowledgeId: string) => {
             try {
@@ -79,6 +109,42 @@ const useKnowledgeLibListStore = (): KnowledgeLibListStore => {
         await api.fetchKnowledgeLibList();
     }
 
+    // 点击创建
+    const onClickCreate: KnowledgeLibListStore['onClickCreate'] = () => {
+        const initialInfoModalId = stateGenerator().infoModalId;
+
+        actions.setInfoModalId(initialInfoModalId);
+        actions.setInfoModalOpen(true);
+    }
+
+    // 点击修改
+    const onClickModify: KnowledgeLibListStore['onClickModify'] = (knowledgeId) => {
+        actions.setInfoModalId(knowledgeId);
+        actions.setInfoModalOpen(true);
+    }
+
+    // 信息弹出层-点击确定
+    const infoModalOnClickConfirm: KnowledgeLibListStore['infoModalOnClickConfirm'] = async (knowledgeId, data) => {
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
+
+        actions.setInfoModalOpen(initialInfoModalOpen);
+
+        if (knowledgeId) {
+            // 修改知识库
+            await api.modifyKnowledgeLib(knowledgeId, data);
+        } else {
+            // 创建知识库
+            await api.createKnowledgeLib(data);
+        }
+    }
+
+    // 信息弹出层-点击取消
+    const infoModalOnClickCancel: KnowledgeLibListStore['infoModalOnClickCancel'] = () => {
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
+
+        actions.setInfoModalOpen(initialInfoModalOpen);
+    }
+
     // 点击删除
     const onClickDelete: KnowledgeLibListStore['onClickDelete'] = async (knowledgeId) => {
         // 删除知识库
@@ -95,16 +161,24 @@ const useKnowledgeLibListStore = (): KnowledgeLibListStore => {
     const reset: KnowledgeLibListStore['reset'] = () => {
         const initialListLoading = stateGenerator().listLoading;
         const initialList = stateGenerator().list;
+        const initialInfoModalId = stateGenerator().infoModalId;
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
         const initialPage = stateGenerator().page;
 
         actions.setListLoading(initialListLoading);
         actions.setList(initialList);
+        actions.setInfoModalId(initialInfoModalId);
+        actions.setInfoModalOpen(initialInfoModalOpen);
         actions.setPage(initialPage);
     }
 
     return {
         state,
         onChangePagination,
+        onClickCreate,
+        onClickModify,
+        infoModalOnClickConfirm,
+        infoModalOnClickCancel,
         onClickDelete,
         init,
         reset

+ 13 - 3
src/pages/knowledgeLib/list/types.ts

@@ -1,9 +1,11 @@
+import { CreateOrModifyKnowledgeLibApiParams } from '@/apis';
+
 export type Record = {
-    id: string,
+    knowledgeId: string,
     name: string,// 知识库名称
     length: number,// 使用空间
-    word_num: number,// 字符数量
-    document_size: number,// 文件数量
+    wordNum: number,// 字符数量
+    documentSize: number,// 文件数量
     createTime: string,// 创建时间
     updateTime: string,// 更新时间
 };
@@ -12,6 +14,8 @@ export type Record = {
 export type State = {
     listLoading: boolean,
     list: Record[],
+    infoModalId: string,
+    infoModalOpen: boolean,
     page: {
         pageNumber: number,
         pageSize: number,
@@ -26,6 +30,8 @@ export type ReadonlyState = Readonly<State>;
 export type StateAction = {
     setListLoading: (loading: State['listLoading']) => void,
     setList: (list: State['list']) => void,
+    setInfoModalId: (id: State['infoModalId']) => void,
+    setInfoModalOpen: (open: State['infoModalOpen']) => void,
     setPage: (page: State['page']) => void,
 };
 
@@ -33,6 +39,10 @@ export type StateAction = {
 export type KnowledgeLibListStore = {
     state: ReadonlyState,
     onChangePagination: (pageNumber: number, pageSize: number) => Promise<any>,
+    onClickCreate: () => void,
+    onClickModify: (knowledgeId: string) => void,
+    infoModalOnClickConfirm: (knowledgeId: string, data: CreateOrModifyKnowledgeLibApiParams) => Promise<any>,
+    infoModalOnClickCancel: () => void,
     onClickDelete: (knowledgeId: string) => Promise<any>,
     init: () => Promise<any>,
     reset: () => void,

+ 4 - 12
src/router.tsx

@@ -72,21 +72,13 @@ const routerList: RouteObject[] = [
                         index: true,
                         element: lazyLoad(() => import('@/pages/knowledgeLib/list/index')),
                     },
-                    {   /* 知识库-创建知识库 */
-                        path: '/knowledgeLib/create',
+                    {   /* 知识库-知识库详情 */
+                        path: '/knowledgeLib/:knowledgeId',
                         handle: {
                             menuLevel: 1,
-                            breadcrumbName: '创建知识库',
+                            breadcrumbName: '知识库详情',
                         },
-                        element: lazyLoad(() => import('@/pages/knowledgeLib/info/index')),
-                    },
-                    {   /* 知识库-修改知识库 */
-                        path: '/knowledgeLib/modify',
-                        handle: {
-                            menuLevel: 1,
-                            breadcrumbName: '修改知识库',
-                        },
-                        element: lazyLoad(() => import('@/pages/knowledgeLib/info/index')),
+                        element: lazyLoad(() => import('@/pages/knowledgeLib/detail/index')),
                     },
                 ]
             },

+ 0 - 12
src/utils/index.ts

@@ -1,16 +1,4 @@
 // 正则表达式
 export const regex = {
     password: /^[a-zA-Z0-9]{6,16}$/,// 密码
-};
-
-// 下载文件
-export const downloadFile = (blob: Blob, fileName: string) => {
-    const downUrl = window.URL.createObjectURL(new Blob([blob]));
-    const elementA = document.createElement('a');
-    elementA.href = downUrl;
-    elementA.download = fileName;
-    elementA.style.display = 'none';
-    document.body.appendChild(elementA);
-    elementA.click();
-    document.body.removeChild(elementA);
 };