Эх сурвалжийг харах

DeepSeek RAG 后台管理代码提交

S0025136190 7 сар өмнө
parent
commit
aa2e54b2a6
37 өөрчлөгдсөн 4541 нэмэгдсэн , 19 устгасан
  1. 191 0
      src/apis/index.ts
  2. 37 3
      src/pages/layout/components/Header.tsx
  3. 59 2
      src/pages/layout/components/Nav.tsx
  4. 142 0
      src/pages/layout/components/NavDeepSeek.tsx
  5. 48 13
      src/pages/layout/index.tsx
  6. 5 0
      src/pages/layout/store.ts
  7. 1 0
      src/pages/layout/types.ts
  8. 2 1
      src/pages/login/store.tsx
  9. 165 0
      src/pages/takai/dataExport/components/InfoModal.tsx
  10. 98 0
      src/pages/takai/dataExport/components/Search.tsx
  11. 130 0
      src/pages/takai/dataExport/index.tsx
  12. 147 0
      src/pages/takai/dataExport/store.ts
  13. 14 0
      src/pages/takai/dataExport/style.less
  14. 44 0
      src/pages/takai/dataExport/types.ts
  15. 117 0
      src/pages/takai/knowledgeLib/detail/components/InfoModal.tsx
  16. 177 0
      src/pages/takai/knowledgeLib/detail/components/InfoModalSetting.tsx
  17. 302 0
      src/pages/takai/knowledgeLib/detail/index.tsx
  18. 264 0
      src/pages/takai/knowledgeLib/detail/store.ts
  19. 6 0
      src/pages/takai/knowledgeLib/detail/style.less
  20. 69 0
      src/pages/takai/knowledgeLib/detail/types.ts
  21. 165 0
      src/pages/takai/knowledgeLib/list/components/InfoModal.tsx
  22. 194 0
      src/pages/takai/knowledgeLib/list/index.tsx
  23. 204 0
      src/pages/takai/knowledgeLib/list/store.ts
  24. 14 0
      src/pages/takai/knowledgeLib/list/style.less
  25. 50 0
      src/pages/takai/knowledgeLib/list/types.ts
  26. 122 0
      src/pages/takai/knowledgeLib/slice/detail/index.tsx
  27. 215 0
      src/pages/takai/knowledgeLib/slice/index.tsx
  28. 235 0
      src/pages/takai/knowledgeLib/slice/store.ts
  29. 33 0
      src/pages/takai/knowledgeLib/slice/style.less
  30. 61 0
      src/pages/takai/knowledgeLib/slice/types.ts
  31. 738 0
      src/pages/takai/questionAnswer/info/index.tsx
  32. 47 0
      src/pages/takai/questionAnswer/info/store.ts
  33. 18 0
      src/pages/takai/questionAnswer/info/style.less
  34. 19 0
      src/pages/takai/questionAnswer/info/types.ts
  35. 283 0
      src/pages/takai/questionAnswer/list/index.tsx
  36. 33 0
      src/pages/takai/questionAnswer/list/style.less
  37. 92 0
      src/router.tsx

+ 191 - 0
src/apis/index.ts

@@ -1,3 +1,4 @@
+import exp from 'constants';
 import api from './api';
 
 // Api参数类型
@@ -79,6 +80,27 @@ export type FetchChatHistoryListApiParams = Partial<{
     pageSize: number,
 }>;
 
+export type ModifyDocumentSettingApiParams = {
+    knowledgeId: string,
+    documentId: string,
+    setSlice: string,
+    setAnalyze: string,
+};
+
+export type FetchSliceListApiParams = {
+    knowledge_id: string,
+    document_id: string,
+    text: string,
+    pageNum: number,
+    pageSize: number,
+};
+
+export type ModifySliceApiParams = {
+    knowledgeId: string,
+    sliceId: string,
+    sliceText: string,
+};
+
 // Api函数类型
 export type LoginApi = (data: LoginApiParams) => Promise<any>;
 export type LogoutApi = () => Promise<any>;
@@ -104,6 +126,30 @@ export type DeleteDocumentLibApi = (id: string) => Promise<any>;
 export type FetchApplicationListApi = () => Promise<any>;
 export type FetchChatHistoryListApi = (data: FetchChatHistoryListApiParams) => Promise<any>;
 export type ExportChatHistoryApi = (id: string) => Promise<any>;
+export type FetchTakaiAppListApi = (data: FetchAppListApiParams) => Promise<any>;
+export type FetchTakaiApplicationDetailApi = (appId: string) => Promise<any>;
+export type CreateTakaiApplicationLibApi = (data: CreateOrModifyApplicationApiParams) => Promise<any>;
+export type ModifyTakaiApplicationLibApi = (appId: string, data: CreateOrModifyApplicationApiParams) => Promise<any>;
+export type DeleteTakaiApplicationLibApi = (appId: string) => Promise<any>;
+export type FetchTakaiAppIndexApi = (data: FetchAppIndexParams) => Promise<any>;
+export type FetchTakaiKnowledgeApiListApi = () => Promise<any>;
+export type FetchTakaiKnowledgeLibListApi = (data: FetchKnowledgeLibListApiParams) => Promise<any>;
+export type FetchTakaiKnowledgeLibDetailApi = (knowledgeId: string) => Promise<any>;
+export type ModifyTakaiKnowledgeLibApi = (knowledgeId: string, data: CreateOrModifyKnowledgeLibApiParams) => Promise<any>;
+export type CreateTakaiKnowledgeLibApi = (data: CreateOrModifyKnowledgeLibApiParams) => Promise<any>;
+export type DeleteTakaiKnowledgeLibApi = (knowledgeId: string) => Promise<any>;
+export type FetchTakaiDocumentLibListApi = (data: FetchDocumentLibListApiParams) => Promise<any>;
+export type FetchTakaiDocumentLibApi = (id: string) => Promise<any>;
+export type ModifyTakaiDocumentLibApi = (id: string, data: ModifyDocumentApiParams) => Promise<any>;
+export type DeleteTakaiDocumentLibApi = (id: string) => Promise<any>;
+export type FetchTakaiDocumentSettingLibApi = (id: string) => Promise<any>;
+export type ModifyTakaiDocumentSettingLibApi = (id: string, data: ModifyDocumentSettingApiParams) => Promise<any>;
+export type FetchTakaiSliceListApi = (data: FetchSliceListApiParams) => Promise<any>;
+export type deleteTakaiSliceLibApi = (sliceId: string, knowledgeId: string) => Promise<any>;
+export type FetchTakaiSliceDetailLibApi = (sliceId: string, knowledgeId: string) => Promise<any>;
+export type modifyTakaiSliceInfoLibApi = (data: ModifySliceApiParams) => Promise<any>;
+export type FetchTakaiChatHistoryListApi = (data: FetchChatHistoryListApiParams) => Promise<any>;
+export type ExportTakaiChatHistoryApi = (id: string) => Promise<any>;
 
 // 登录
 const loginApi: LoginApi = async (data) => {
@@ -225,6 +271,127 @@ const exportChatHistoryApi: ExportChatHistoryApi = async (id) => {
     return api.post(`bigmodel/api/dialog/export/${id}`, {}, { responseType: 'blob' });
 };
 
+// 获取takai应用列表
+const fetchTakaiAppListApi: FetchTakaiAppListApi = async (data) => {
+    return api.post('/takai/api/getApplicationList', data);
+};
+
+// 获取takai应用详情
+const fetchTakaiApplicationDetailApi: FetchTakaiApplicationDetailApi = async (appId) => {
+    return api.get(`/takai/api/selectApplication/${appId}`);
+};
+
+// 创建takai应用
+const createTakaiApplicationLibApi: CreateTakaiApplicationLibApi = async (data) => {
+    return api.post('/takai/api/createApplication', data);
+};
+
+// 编辑takai应用
+const modifyTakaiApplicationLibApi: ModifyTakaiApplicationLibApi = async (appId, data) => {
+    return api.put(`/takai/api/updateApplication/${appId}`, data);
+};
+
+// 删除takai应用
+const deleteTakaiApplicationLibApi: DeleteTakaiApplicationLibApi = async (appId) => {
+    return api.delete(`/takai/api/delApplication/${appId}`);
+};
+
+// 获取首页信息
+const fetchTakaiIndexApi: FetchTakaiAppIndexApi = async (data) => {
+    return api.post('/takai/api/index', data);
+};
+
+// takai知识库列表
+const fetchTakaiKnowledgeListApi: FetchTakaiKnowledgeApiListApi = async () => {
+    return api.get('/takai/api/knowledgeList');
+};
+
+// 获取takai知识库列表
+const fetchTakaiKnowledgeLibListApi: FetchTakaiKnowledgeLibListApi = async (data) => {
+    return api.post('/takai/api/getKnowledgeList', data);
+};
+
+// 获取takai知识库详情
+const fetchTakaiKnowledgeLibDetailApi: FetchTakaiKnowledgeLibDetailApi = async (knowledgeId) => {
+    return api.get(`/takai/api/detailKnowledge/${knowledgeId}`);
+};
+
+// 修改takai知识库
+const modifyTakaiKnowledgeLibApi: ModifyTakaiKnowledgeLibApi = async (knowledgeId, data) => {
+    return api.put(`/takai/api/updateKnowledge/${knowledgeId}`, data);
+};
+
+// 创建takai知识库
+const createTakaiKnowledgeLibApi: CreateTakaiKnowledgeLibApi = async (data) => {
+    return api.post('/takai/api/createKnowledge', data);
+};
+
+// 删除takai知识库
+const deleteTakaiKnowledgeLibApi: DeleteTakaiKnowledgeLibApi = async (knowledgeId) => {
+    return api.delete(`/takai/api/delKnowledge/${knowledgeId}`);
+};
+
+// 获取takai知识列表
+const fetchTakaiDocumentLibListApi: FetchTakaiDocumentLibListApi = async (data) => {
+    return api.post('/takai/api/documentList', data);
+};
+
+// takai知识详情
+const fetchTakaiDocumentLibApi: FetchTakaiDocumentLibApi = async (id) => {
+    return api.get(`/takai/api/documentDetail/${id}`);
+};
+
+// 修改takai知识
+const modifyTakaiDocumentApi: ModifyTakaiDocumentLibApi = async (id, data) => {
+    return api.put(`/takai/api/updateDocument/${id}`, data);
+};
+
+// 删除takai知识文件
+const deleteTakaiDocumentApi: DeleteTakaiDocumentLibApi = async (id) => {
+    return api.delete(`/takai/api/delDocument/${id}`);
+};
+
+// takai知识配置详情
+const fetchTakaiDocumentSettingLibApi: FetchTakaiDocumentSettingLibApi = async (id) => {
+    return api.get(`/takai/api/documentSetting/${id}`);
+};
+
+// 修改takai知识配置
+const modifyTakaiDocumentSettingApi: ModifyTakaiDocumentSettingLibApi = async (id, data) => {
+    return api.put(`/takai/api/updateDocumentSetting/${id}`, data);
+};
+
+// 获取takai切片列表
+const fetchTakaiSliceListApi: FetchTakaiSliceListApi = async (data) => {
+    return api.post(`/takai/api/getSliceList`, data);
+};
+
+// 获取takai切片列表
+const deleteTakaiSliceApi: deleteTakaiSliceLibApi = async (sliceId, knowledgeId) => {
+    return api.delete(`/takai/api/deleteSlice/${sliceId}/${knowledgeId}`);
+};
+
+// 获取takai切片详情
+const fetchTakaiSliceDetailApi: FetchTakaiSliceDetailLibApi = async (sliceId, knowledgeId) => {
+    return api.get(`/takai/api/getSliceDetail/${sliceId}/${knowledgeId}`);
+};
+
+// 修改takai切片详情
+const modifyTakaiSliceInfoApi: modifyTakaiSliceInfoLibApi = async (data) => {
+    return api.put(`/takai/api/updateSliceInfo/`, data);
+};
+
+// 获取takai聊天记录列表
+const fetchTakaiChatHistoryListApi: FetchTakaiChatHistoryListApi = async (data) => {
+    return api.post('/takai/api/chatHistory/list', data);
+};
+
+// 导出takai聊天记录
+const exportTakaiChatHistoryApi: ExportTakaiChatHistoryApi = async (id) => {
+    return api.post(`/takai/api/dialog/export/${id}`, {}, { responseType: 'blob' });
+};
+
+
 export const apis = {
     login: loginApi,
     logout: logoutApi,
@@ -250,4 +417,28 @@ export const apis = {
     fetchApplicationList: fetchApplicationListApi,
     fetchChatHistoryList: fetchChatHistoryListApi,
     exportChatHistory: exportChatHistoryApi,
+    fetchTakaiAppList: fetchTakaiAppListApi,
+    fetchTakaiApplicationDetail: fetchTakaiApplicationDetailApi,
+    createTakaiApplicationApi: createTakaiApplicationLibApi,
+    modifyTakaiApplicationApi: modifyTakaiApplicationLibApi,
+    deleteTakaiApplicationApi: deleteTakaiApplicationLibApi,
+    fetchTakaiIndexCount: fetchTakaiIndexApi,
+    fetchTakaiKnowledgeList: fetchTakaiKnowledgeListApi,
+    fetchTakaiKnowledgeLibList: fetchTakaiKnowledgeLibListApi,
+    fetchTakaiKnowledgeLibDetail: fetchTakaiKnowledgeLibDetailApi,
+    modifyTakaiKnowledgeLib: modifyTakaiKnowledgeLibApi,
+    createTakaiKnowledgeLib: createTakaiKnowledgeLibApi,
+    deleteTakaiKnowledgeLib: deleteTakaiKnowledgeLibApi,
+    fetchTakaiDocumentLibListApi: fetchTakaiDocumentLibListApi,
+    fetchTakaiDocumentDetailLibApi: fetchTakaiDocumentLibApi,
+    modifyTakaiDocumentLibApi: modifyTakaiDocumentApi,
+    deleteTakaiDocumentLibApi: deleteTakaiDocumentApi,
+    fetchTakaiDocumentSettingLibApi: fetchTakaiDocumentSettingLibApi,
+    modifyTakaiDocumentSettingLibApi: modifyTakaiDocumentSettingApi,
+    fetchTakaiSliceList: fetchTakaiSliceListApi,
+    deleteTakaiSlice: deleteTakaiSliceApi,
+    fetchTakaiSliceDetail: fetchTakaiSliceDetailApi,
+    modifyTakaiSliceInfo: modifyTakaiSliceInfoApi,
+    fetchTakaiChatHistoryList: fetchTakaiChatHistoryListApi,
+    exportTakaiChatHistory: exportTakaiChatHistoryApi,
 };

+ 37 - 3
src/pages/layout/components/Header.tsx

@@ -1,5 +1,5 @@
 import * as React from 'react';
-import { Layout, MenuProps, Modal, Dropdown } from 'antd';
+import { Layout, MenuProps, Modal, Dropdown, Select } from 'antd';
 import { CaretDownOutlined, PoweroffOutlined } from '@ant-design/icons';
 import logoSrc from '@/assets/public/logo.png';
 import router from '@/router';
@@ -9,12 +9,14 @@ const { Header: AntdHeader } = Layout;
 interface Props {
     userName: string,
     onClickLogout: () => Promise<any>,
+    onSelectChange: (value: number) => void; // 新增回调函数
 };
 
 const Header: React.FC<Props> = (props: Props) => {
     const {
         userName,
-        onClickLogout
+        onClickLogout,
+        onSelectChange,
     } = props;
 
     const items: MenuProps['items'] = [
@@ -37,16 +39,48 @@ const Header: React.FC<Props> = (props: Props) => {
         }
     ];
 
+    const [selectedFruit, setSelectedFruit] = React.useState(1); // 默认选中
+
+    const fruits = [
+        { id: 1, name: 'DeepSeek' },
+        { id: 2, name: '智普' },
+    ];
+
+    const onChange = (value: number) => {
+        setSelectedFruit(value);
+        onSelectChange(value); // 调用回调函数通知父组件
+    };
+
+    React.useEffect(() => {
+        const currentPath = window.location.pathname;
+        if (currentPath.startsWith('/takai')) {
+            setSelectedFruit(1);
+        } else {
+            setSelectedFruit(2);
+        }
+    }, [window.location.pathname]);
+
     return (
         <AntdHeader className='header'>
             <div className='header-logo' onClick={() => {
-                router.navigate({ pathname: '/' });
+                router.navigate({ pathname: '/takai/questionAnswer' });
             }}>
                 <img className='header-logo-picture' src={logoSrc} />
                 <div className='header-logo-text'>
                     建科•小智后台管理系统
                 </div>
+                <Select style={{ width: 200, marginLeft: 20 }}
+                    value={selectedFruit}
+                    onChange={onChange}
+                >
+                    {fruits.map(fruit => (
+                        <option key={fruit.id} value={fruit.id}>
+                            {fruit.name}
+                        </option>
+                    ))}
+                </Select>
             </div>
+
             <Dropdown menu={{ items }}>
                 <div className='header-operation'>
                     <div className='header-operation-picture'>

+ 59 - 2
src/pages/layout/components/Nav.tsx

@@ -8,8 +8,17 @@ import {
     MenuUnfoldOutlined
 } from '@ant-design/icons';
 import router from '@/router';
+import { JSX } from 'react/jsx-runtime';
 
 const Sider = Layout.Sider;
+// const { Option } = Select;
+
+interface MenuItem {
+    key: string;
+    icon: JSX.Element;
+    label: string;
+    onClick: () => void;
+}
 
 interface Props {
     selectedKey: string,
@@ -21,6 +30,7 @@ interface Props {
 };
 
 const Nav: React.FC<Props> = (props: Props) => {
+
     const {
         selectedKey,
         onChangeSelectedKey,
@@ -30,7 +40,28 @@ const Nav: React.FC<Props> = (props: Props) => {
         onClickCollapsed
     } = props;
 
-    const items = [
+    // const dsItems: MenuItem[] = [
+    //     {
+    //         key: '/takai/questionAnswer',
+    //         icon: <RobotOutlined />,
+    //         label: 'DeepSeek问答应用',
+    //         onClick: () => { router.navigate({ pathname: '/takai/questionAnswer' }) }
+    //     },
+    //     {
+    //         key: '/takai/knowledgeLib',
+    //         icon: <ReadOutlined />,
+    //         label: 'DeepSeek知识库',
+    //         onClick: () => { router.navigate({ pathname: '/takai/knowledgeLib' }) }
+    //     },
+    //     {
+    //         key: '/takai/dataExport',
+    //         icon: <FileSearchOutlined />,
+    //         label: 'DeepSeek数据导出',
+    //         onClick: () => { router.navigate({ pathname: '/takai/dataExport' }) }
+    //     },
+    // ];
+
+    const zpItems: MenuItem[] = [
         {
             key: '/questionAnswer',
             icon: <RobotOutlined />,
@@ -49,7 +80,33 @@ const Nav: React.FC<Props> = (props: Props) => {
             label: '数据导出',
             onClick: () => { router.navigate({ pathname: '/dataExport' }) }
         }
-    ]
+    ];
+
+    const [items, setItems] = React.useState<MenuItem[]>(zpItems);
+    // const [selectedFruit, setSelectedFruit] = React.useState(2); // 默认选中
+
+    const fruits = [
+        { id: 1, name: 'DeepSeek' },
+        { id: 2, name: '智普' },
+    ];
+
+    // const onChange = (value: number) => {
+    //     console.log(value, 'value');
+    //     if (value === 1) {
+    //         setSelectedFruit(1);
+    //         setItems(dsItems);
+    //         router.navigate({ pathname: '/takai/questionAnswer' });
+    //     } else {
+    //         setSelectedFruit(2);
+    //         setItems(zpItems);
+    //         router.navigate({ pathname: '/questionAnswer' });
+    //     }
+    // };
+
+    React.useEffect(() => {
+        router.navigate({ pathname: '/questionAnswer' });
+    }, []);
+
 
     return (
         <Sider

+ 142 - 0
src/pages/layout/components/NavDeepSeek.tsx

@@ -0,0 +1,142 @@
+import * as React from 'react';
+import { Layout, Menu, Button, Select } from 'antd';
+import {
+    RobotOutlined,
+    ReadOutlined,
+    FileSearchOutlined,
+    MenuFoldOutlined,
+    MenuUnfoldOutlined
+} from '@ant-design/icons';
+import router from '@/router';
+import { JSX } from 'react/jsx-runtime';
+
+const Sider = Layout.Sider;
+const { Option } = Select;
+
+interface MenuItem {
+    key: string;
+    icon: JSX.Element;
+    label: string;
+    onClick: () => void;
+}
+
+interface Props {
+    selectedKey: string,
+    onChangeSelectedKey: (path: string, menuLevel: number) => void,
+    openKeys: string[],
+    onOpenChange: (openKeys: string[]) => void,
+    collapsed: boolean,
+    onClickCollapsed: () => void,
+};
+
+const Nav: React.FC<Props> = (props: Props) => {
+
+    const {
+        selectedKey,
+        onChangeSelectedKey,
+        openKeys,
+        onOpenChange,
+        collapsed,
+        onClickCollapsed
+    } = props;
+
+    const dsItems: MenuItem[] = [
+        {
+            key: '/takai/questionAnswer',
+            icon: <RobotOutlined />,
+            label: 'DeepSeek问答应用',
+            onClick: () => { router.navigate({ pathname: '/takai/questionAnswer' }) }
+        },
+        {
+            key: '/takai/knowledgeLib',
+            icon: <ReadOutlined />,
+            label: 'DeepSeek知识库',
+            onClick: () => { router.navigate({ pathname: '/takai/knowledgeLib' }) }
+        },
+        {
+            key: '/takai/dataExport',
+            icon: <FileSearchOutlined />,
+            label: 'DeepSeek数据导出',
+            onClick: () => { router.navigate({ pathname: '/takai/dataExport' }) }
+        },
+    ];
+
+    // const zpItems: MenuItem[] = [
+    //     {
+    //         key: '/questionAnswer',
+    //         icon: <RobotOutlined />,
+    //         label: '问答应用',
+    //         onClick: () => { router.navigate({ pathname: '/questionAnswer' }) }
+    //     },
+    //     {
+    //         key: '/knowledgeLib',
+    //         icon: <ReadOutlined />,
+    //         label: '知识库',
+    //         onClick: () => { router.navigate({ pathname: '/knowledgeLib' }) }
+    //     },
+    //     {
+    //         key: '/dataExport',
+    //         icon: <FileSearchOutlined />,
+    //         label: '数据导出',
+    //         onClick: () => { router.navigate({ pathname: '/dataExport' }) }
+    //     }
+    // ];
+
+    const [items, setItems] = React.useState<MenuItem[]>(dsItems);
+    // const [selectedFruit, setSelectedFruit] = React.useState(1); // 默认选中
+
+    const fruits = [
+        { id: 1, name: 'DeepSeek' },
+        { id: 2, name: '智普' },
+    ];
+
+    // const onChange = (value: number) => {
+    //     console.log(value, 'value');
+    //     if (value === 1) {
+    //         setSelectedFruit(1);
+    //         setItems(dsItems);
+    //         router.navigate({ pathname: '/takai/questionAnswer' });
+    //     } else {
+    //         setSelectedFruit(2);
+    //         setItems(zpItems);
+    //         router.navigate({ pathname: '/questionAnswer' });
+    //     }
+    // };
+
+    React.useEffect(() => {
+        router.navigate({ pathname: '/takai/questionAnswer' });
+    }, []);
+
+
+    return (
+        <Sider
+            className='nav'
+            collapsed={collapsed}
+        >
+            <div className='nav-menu'>
+                <Menu
+                    mode='inline'
+                    selectedKeys={[selectedKey]}
+                    onSelect={(item) => {
+                        const menuLevel = item.keyPath.length > 1 ? 2 : 1;
+                        onChangeSelectedKey(item.key, menuLevel);
+                    }}
+                    openKeys={openKeys}
+                    onOpenChange={(keys) => {
+                        // 点击菜单,收起其他展开的所有菜单
+                        const latestOpenKey = keys.find((key) => openKeys.indexOf(key) === -1);
+                        onOpenChange(latestOpenKey ? [latestOpenKey] : []);
+                    }}
+                    items={items}
+                />
+            </div>
+            <div className='nav-bottom'>
+                <Button type='primary' onClick={onClickCollapsed}>
+                    {collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
+                </Button>
+            </div>
+        </Sider>
+    );
+};
+
+export default Nav;

+ 48 - 13
src/pages/layout/index.tsx

@@ -4,9 +4,11 @@ import { observer } from 'mobx-react';
 import { Layout } from 'antd';
 import Header from './components/Header';
 import Nav from './components/Nav';
+import NavDeepSeek from './components/NavDeepSeek';
 import Breadcrumb from './components/Breadcrumb';
 import store from './store';
 import './style.less';
+import router from '@/router';
 
 const { Content } = Layout;
 
@@ -25,7 +27,7 @@ const LayoutApp: React.FC = () => {
         userName,
         collapsed,
         selectedKey,
-        openKeys
+        openKeys,
     } = state;
 
     const matches = useMatches();
@@ -46,21 +48,54 @@ const LayoutApp: React.FC = () => {
         return () => reset();
     }, []);
 
+    const [selectedValue, setSelectedValue] = React.useState(1);
+
+    const handleSelectChange = (value: number) => {
+        setSelectedValue(value);
+    };
+
+    React.useEffect(() => {
+        const currentPath = location.pathname;
+        if (currentPath.startsWith('/takai')) {
+            setSelectedValue(1);
+        } else {
+            setSelectedValue(2);
+        }
+    }, [location.pathname]);
+
     return (
         <Layout style={{ height: '100vh' }}>
-            <Header
-                userName={userName}
-                onClickLogout={onClickLogout}
-            />
-            <Layout>
-                <Nav
-                    selectedKey={selectedKey}
-                    onChangeSelectedKey={onChangeSelectedKey}
-                    openKeys={openKeys}
-                    onOpenChange={onOpenChange}
-                    collapsed={collapsed}
-                    onClickCollapsed={onClickCollapsed}
+            <div>
+                <Header
+                    userName={userName}
+                    onClickLogout={onClickLogout}
+                    onSelectChange={handleSelectChange} // 传递回调函数
                 />
+            </div>
+
+            <Layout>
+                {
+                    selectedValue === 1 ? (
+                        <NavDeepSeek
+                            selectedKey={selectedKey}
+                            onChangeSelectedKey={onChangeSelectedKey}
+                            openKeys={openKeys}
+                            onOpenChange={onOpenChange}
+                            collapsed={collapsed}
+                            onClickCollapsed={onClickCollapsed}
+                        />
+                    ) : (
+                        <Nav
+                            selectedKey={selectedKey}
+                            onChangeSelectedKey={onChangeSelectedKey}
+                            openKeys={openKeys}
+                            onOpenChange={onOpenChange}
+                            collapsed={collapsed}
+                            onClickCollapsed={onClickCollapsed}
+                        />
+                    )
+                }
+
                 <Layout>
                     {
                         location.pathname === '/404' ?

+ 5 - 0
src/pages/layout/store.ts

@@ -86,6 +86,10 @@ const useLayoutStore = (): LayoutStore => {
         actions.setCollapsed(!state.collapsed);
     }
 
+    const handleSelectChange = ( menuLevel: number) => {
+        
+    }
+
     // 初始渲染
     const init: LayoutStore['init'] = (list) => {
         const userInfo = LocalStorage.getUserInfo();
@@ -121,6 +125,7 @@ const useLayoutStore = (): LayoutStore => {
         onOpenChange,
         onClickCollapsed,
         init,
+        handleSelectChange,
         reset
     };
 };

+ 1 - 0
src/pages/layout/types.ts

@@ -32,4 +32,5 @@ export type LayoutStore = {
     onClickCollapsed: () => void,
     init: (list: State['routerMatchList']) => void,
     reset: () => void,
+    handleSelectChange: (selectedKeys: number) => void,
 };

+ 2 - 1
src/pages/login/store.tsx

@@ -44,7 +44,8 @@ const useLoginStore = (): LoginStore => {
                 } else {// 不记住密码
                     LocalStorage.setAccountPassword(undefined);
                 }
-                router.navigate({ pathname: '/' }, { replace: true });
+                router.navigate({ pathname: '/takai/questionAnswer' }, { replace: true });
+                // router.navigate({ pathname: '/' }, { replace: true });
                 message.success('登录成功');
             } catch (error: any) {
                 LocalStorage.clear();

+ 165 - 0
src/pages/takai/dataExport/components/InfoModal.tsx

@@ -0,0 +1,165 @@
+import * as React from 'react';
+import { Modal, Spin, Form, Input, Select, message } from 'antd';
+import { apis, CreateOrModifyUserApiParams } from '@/apis';
+import { regex } from '@/utils';
+
+const FormItem = Form.Item;
+const { Option } = Select;
+
+interface Props {
+    id: string,
+    open: boolean,
+    onClickConfirm: (id: string, data: CreateOrModifyUserApiParams) => 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);
+
+    const getTitle = () => {
+        if (id) {
+            return '修改用户';
+        } else {
+            return '创建用户';
+        }
+    };
+
+    const fetchDetail = async () => {
+        try {
+            const res = await apis.fetchUserDetail(props.id);
+            form.setFieldsValue(res.data);
+        } catch (error: any) {
+            message.error(error.msg);
+        }
+    };
+
+    const init = async () => {
+        setLoading(true);
+        if (props.id) {
+            await fetchDetail();
+        }
+        setLoading(false);
+    };
+
+    React.useEffect(() => {
+        init();
+    }, []);
+
+    // 检查手机号码
+    const checkPhoneNumber = (rule: any, value: string) => {
+        if (value) {
+            const phoneNumberRegex = new RegExp(regex.phoneNumber);
+            if (phoneNumberRegex.test(value)) {
+                return Promise.resolve();
+            } else {
+                return Promise.reject(new Error('手机号码格式不正确'));
+            }
+        } else {
+            return Promise.reject('手机号码不能为空');
+        }
+    };
+
+    // 检查登录密码
+    const checkPassword = (rule: any, value: string) => {
+        if (value) {
+            const passwordRegex = new RegExp(regex.password);
+            if (passwordRegex.test(value)) {
+                return Promise.resolve();
+            } else {
+                return Promise.reject('登录密码格式不正确');
+            }
+        } else {
+            return Promise.reject('登录密码不能为空');
+        }
+    };
+
+    // 点击确定
+    const handleClickConfirm = () => {
+        form.validateFields().then(async (values) => {
+            const data = { ...values };
+            await onClickConfirm(props.id, data);
+        }).catch((error) => {
+            console.error(error);
+        });
+    };
+
+    return (
+        <Modal
+            width={600}
+            title={getTitle()}
+            destroyOnClose={true}
+            maskClosable={false}
+            centered={true}
+            open={open}
+            onOk={handleClickConfirm}
+            onCancel={onClickCancel}
+        >
+            <div className='infoModal'>
+                <Spin spinning={loading}>
+                    <Form form={form} layout='vertical'>
+                        <FormItem
+                            label='姓名'
+                            name='user_name'
+                            rules={[{ required: true, message: '姓名不能为空', whitespace: true }]}
+                        >
+                            <Input
+                                style={{ width: '100%' }}
+                                placeholder='请输入姓名'
+                            />
+                        </FormItem>
+                        <FormItem
+                            label='手机号码'
+                            name='phone_number'
+                            rules={[{ validator: checkPhoneNumber, required: true }]}
+                        >
+                            <Input
+                                style={{ width: '100%' }}
+                                placeholder='请输入手机号码'
+                                maxLength={11}
+                            />
+                        </FormItem>
+                        <FormItem
+                            label='登录密码'
+                            name='password'
+                            rules={[{ validator: checkPassword, required: true }]}
+                        >
+                            <Input.Password
+                                style={{ width: '100%' }}
+                                placeholder='6-16位字母或数字组合'
+                            />
+                        </FormItem>
+                        <FormItem
+                            label='角色'
+                            name='role'
+                            rules={[{ required: true, message: '角色不能为空' }]}
+                        >
+                            <Select
+                                style={{ width: '100%' }}
+                                placeholder='请选择角色'
+                                allowClear={true}
+                            >
+                                <Option value='USER'>
+                                    用户
+                                </Option>
+                                <Option value='ADMIN'>
+                                    管理员
+                                </Option>
+                            </Select>
+                        </FormItem>
+                    </Form>
+                </Spin>
+            </div>
+        </Modal>
+    );
+};
+
+export default InfoModal;

+ 98 - 0
src/pages/takai/dataExport/components/Search.tsx

@@ -0,0 +1,98 @@
+import * as React from 'react';
+import { Form, Select, Button } from 'antd';
+import { apis } from '@/apis';
+import { Query } from '../types';
+
+const FormItem = Form.Item;
+const { Option } = Select;
+
+interface Props {
+    onClickSearch: (query: Query) => Promise<any>,
+    onClickReset: (query: Query) => Promise<any>,
+};
+
+const Search: React.FC<Props> = (props: Props) => {
+    const {
+        onClickSearch,
+        onClickReset
+    } = props;
+
+    const [form] = Form.useForm();
+
+    type ApplicationList = {
+        label: string,
+        value: string,
+    }[];
+
+    const [applicationList, setApplicationList] = React.useState<ApplicationList>([]);
+
+    const fetchApplicationList = async () => {
+        try {
+            const res = await apis.fetchApplicationList();
+            const list = res.data.map((item: any) => {
+                return {
+                    label: item.name,
+                    value: item.appId,
+                }
+            });
+            setApplicationList(list);
+        } catch (error: any) {
+            console.error(error);
+        }
+    }
+
+    const init = async () => {
+        await fetchApplicationList();
+    };
+
+    React.useEffect(() => {
+        init();
+    }, []);
+
+    // 点击查询
+    const handleClickSearch = async () => {
+        const values = form.getFieldsValue();
+        await onClickSearch(values);
+    };
+
+    // 点击重置
+    const handleClickReset = async () => {
+        form.resetFields();
+        const values = form.getFieldsValue();
+        await onClickReset(values);
+    };
+
+    return (
+        <Form form={form} layout='inline' colon={false}>
+            <FormItem label='应用' name='appId'>
+                <Select
+                    style={{ width: 200 }}
+                    placeholder='全部'
+                    allowClear={true}
+                >
+                    {
+                        applicationList.map((item, index) => {
+                            return <Option value={item.value} key={index}>
+                                {item.label}
+                            </Option>
+                        })
+                    }
+                </Select>
+            </FormItem>
+            <FormItem>
+                <Button
+                    style={{ marginRight: 16 }}
+                    type='primary'
+                    onClick={handleClickSearch}
+                >
+                    查询
+                </Button>
+                <Button onClick={handleClickReset}>
+                    重置
+                </Button>
+            </FormItem>
+        </Form>
+    );
+};
+
+export default Search;

+ 130 - 0
src/pages/takai/dataExport/index.tsx

@@ -0,0 +1,130 @@
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { Table, TableColumnsType, TablePaginationConfig, Modal } from 'antd';
+import { DownloadOutlined } from '@ant-design/icons';
+import Search from './components/Search';
+import dayjs from 'dayjs';
+import store from './store';
+import { Record } from './types';
+import './style.less';
+
+const DataExport: React.FC = () => {
+    const {
+        state,
+        onClickSearch,
+        onClickReset,
+        onChangePagination,
+        onClickDownload,
+        init,
+        reset
+    } = store;
+    const {
+        listLoading,
+        list,
+        page
+    } = state;
+
+    React.useEffect(() => {
+        init();
+        return () => reset();
+    }, []);
+
+    const columns: TableColumnsType<Record> = [
+        {
+            title: '序号',
+            dataIndex: 'index',
+            width: 80,
+            render: (text, record, index) => {
+                return index + 1;
+            }
+        },
+        {
+            title: '聊天标题',
+            dataIndex: 'dialog_name',
+        },
+        {
+            title: '消息长度',
+            dataIndex: 'length',
+            render: (text) => {
+                return text + '条';
+            }
+        },
+        {
+            title: '聊天时间',
+            dataIndex: 'create_time',
+            width: 200,
+            render: (text) => {
+                if (text) {
+                    return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
+                } else {
+                    return '--';
+                }
+            }
+        },
+        {
+            title: '操作',
+            dataIndex: 'operation',
+            width: 80,
+            fixed: 'right',
+            render: (text, record) => {
+                return (
+                    <a
+                        onClick={() => {
+                            Modal.confirm({
+                                title: '导出',
+                                content: '确定导出Excel吗?',
+                                onOk: async () => {
+                                    await onClickDownload(record.id, record.dialog_name);
+                                }
+                            });
+                        }}
+                    >
+                        <DownloadOutlined />
+                    </a >
+                )
+            }
+        }
+    ];
+
+    const paginationConfig: TablePaginationConfig = {
+        // 显示数据总量
+        showTotal: (total: number) => {
+            return `共 ${total} 条`;
+        },
+        // 展示分页条数切换
+        showSizeChanger: true,
+        // 指定每页显示条数
+        pageSizeOptions: ['10', '20', '50', '100'],
+        // 快速跳转至某页
+        showQuickJumper: true,
+        current: page.pageNumber,
+        pageSize: page.pageSize,
+        total: page.total,
+        onChange: async (page, pageSize) => {
+            await onChangePagination(page, pageSize);
+        },
+    };
+
+    return (
+        <div className='dataExport'>
+            <div className='dataExport-search'>
+                <Search
+                    onClickSearch={onClickSearch}
+                    onClickReset={onClickReset}
+                />
+            </div>
+            <div className='dataExport-table'>
+                <Table
+                    scroll={{ x: 'max-content' }}
+                    rowKey={(record) => record.id}
+                    loading={listLoading}
+                    columns={columns}
+                    dataSource={list}
+                    pagination={paginationConfig}
+                />
+            </div>
+        </div>
+    );
+};
+
+export default observer(DataExport);

+ 147 - 0
src/pages/takai/dataExport/store.ts

@@ -0,0 +1,147 @@
+import { makeAutoObservable } from 'mobx';
+import { message } from 'antd';
+import { apis } from '@/apis';
+import { downloadFile } from '@/utils';
+import { State, ReadonlyState, StateAction, DataExportStore } from './types';
+
+// 定义状态
+const stateGenerator = (): ReadonlyState => ({
+    query: undefined,
+    listLoading: false,
+    list: [],
+    page: {
+        pageNumber: 1,
+        pageSize: 10,
+        total: 0,
+    },
+});
+
+// 修改状态
+const stateActionsGenerator = (state: State): StateAction => {
+    return {
+        setQuery: (query) => {
+            state.query = query;
+        },
+        setListLoading: (loading) => {
+            state.listLoading = loading;
+        },
+        setList: (list) => {
+            state.list = list;
+        },
+        setPage: (page) => {
+            state.page = page;
+        },
+    };
+};
+
+// 使用仓库
+const useDataExportStore = (): DataExportStore => {
+    const state = makeAutoObservable(stateGenerator());
+    const actions = stateActionsGenerator(state);
+
+    const api = {
+        // 获取聊天记录列表
+        fetchChatHistoryList: async () => {
+            actions.setListLoading(true);
+            try {
+                const data = {
+                    ...state.query,
+                    pageNumber: state.page.pageNumber,
+                    pageSize: state.page.pageSize,
+                };
+                const res = await apis.fetchTakaiChatHistoryList(data);
+                actions.setList(res.rows);
+                actions.setPage({
+                    ...state.page,
+                    total: res.total,
+                });
+            } catch (error: any) {
+                console.error(error);
+            } finally {
+                actions.setListLoading(false);
+            }
+        },
+        // 导出聊天记录
+        exportChatHistory: async (id: string, fileName: string) => {
+            try {
+                const blob = await apis.exportTakaiChatHistory(id);
+                fileName = `${fileName}.xlsx`;
+                downloadFile(blob, fileName);
+                message.success('导出成功');
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+    }
+
+    // 点击查询
+    const onClickSearch: DataExportStore['onClickSearch'] = async (query) => {
+        const initialPageNumber = stateGenerator().page.pageNumber;
+
+        actions.setQuery(query);
+        actions.setPage({
+            ...state.page,
+            pageNumber: initialPageNumber,
+        });
+        // 获取聊天记录列表
+        await api.fetchChatHistoryList();
+    }
+
+    // 点击重置
+    const onClickReset: DataExportStore['onClickReset'] = async (query) => {
+        const initialPage = stateGenerator().page;
+
+        actions.setQuery(query);
+        actions.setPage(initialPage);
+        // 获取聊天记录列表
+        await api.fetchChatHistoryList();
+    }
+
+    // 更改分页
+    const onChangePagination: DataExportStore['onChangePagination'] = async (pageNumber, pageSize) => {
+        actions.setPage({
+            ...state.page,
+            pageNumber: pageNumber,
+            pageSize: pageSize,
+        });
+        // 获取聊天记录列表
+        await api.fetchChatHistoryList();
+    }
+
+    // 点击导出
+    const onClickDownload: DataExportStore['onClickDownload'] = async (id, name) => {
+        // 导出聊天记录
+        await api.exportChatHistory(id, name);
+    }
+
+    // 初始渲染
+    const init: DataExportStore['init'] = async () => {
+        // 获取聊天记录列表
+        await api.fetchChatHistoryList();
+    }
+
+    // 状态重置
+    const reset: DataExportStore['reset'] = () => {
+        const initialQuery = stateGenerator().query;
+        const initialListLoading = stateGenerator().listLoading;
+        const initialList = stateGenerator().list;
+        const initialPage = stateGenerator().page;
+
+        actions.setQuery(initialQuery);
+        actions.setListLoading(initialListLoading);
+        actions.setList(initialList);
+        actions.setPage(initialPage);
+    }
+
+    return {
+        state,
+        onClickSearch,
+        onClickReset,
+        onChangePagination,
+        onClickDownload,
+        init,
+        reset
+    };
+};
+
+export default useDataExportStore();

+ 14 - 0
src/pages/takai/dataExport/style.less

@@ -0,0 +1,14 @@
+.dataExport {
+  &-search {
+    padding: 20px 20px 4px;
+    background: #FFFFFF;
+    border-radius: @border-radius-base;
+    margin-bottom: 20px;
+  }
+
+  &-table {
+    padding: 20px;
+    background: #FFFFFF;
+    border-radius: @border-radius-base;
+  }
+}

+ 44 - 0
src/pages/takai/dataExport/types.ts

@@ -0,0 +1,44 @@
+export type Query = Partial<{
+    appId: string,
+}>;
+
+export type Record = {
+    id: string,
+    dialog_name: string,
+    length: number,
+    create_time: string
+};
+
+// 定义状态
+export type State = {
+    query?: Query,
+    listLoading: boolean,
+    list: Record[],
+    page: {
+        pageNumber: number,
+        pageSize: number,
+        total: number,
+    },
+};
+
+// 只读状态
+export type ReadonlyState = Readonly<State>;
+
+// 修改状态
+export type StateAction = {
+    setQuery: (query: State['query']) => void,
+    setListLoading: (loading: State['listLoading']) => void,
+    setList: (list: State['list']) => void,
+    setPage: (page: State['page']) => void,
+};
+
+// 仓库类型
+export type DataExportStore = {
+    state: ReadonlyState,
+    onClickSearch: (query: Query) => Promise<any>,
+    onClickReset: (query: Query) => Promise<any>,
+    onChangePagination: (pageNumber: number, pageSize: number) => Promise<any>,
+    onClickDownload: (id: string, name: string) => Promise<any>,
+    init: () => Promise<any>,
+    reset: () => void,
+};

+ 117 - 0
src/pages/takai/knowledgeLib/detail/components/InfoModal.tsx

@@ -0,0 +1,117 @@
+import * as React from 'react';
+import { Modal, Spin, Form, Input, Select, message } from 'antd';
+import { apis, ModifyDocumentApiParams } from '@/apis';
+
+const FormItem = Form.Item;
+const { Option } = Select;
+
+interface Props {
+    id: string,
+    open: boolean,
+    onClickConfirm: (id: string, data: ModifyDocumentApiParams) => 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);
+
+    // 获取知识详情
+    const fetchDetail = async () => {
+        try {
+            const res = await apis.fetchTakaiDocumentDetailLibApi(props.id);
+            const { id, name, knowledge_type, custom_separator, sentence_size } = res.data;
+            form.setFieldsValue({
+                id: id,
+                name: name,
+                knowledge_type: knowledge_type,
+                custom_separator: custom_separator,
+                sentence_size: sentence_size,
+            });
+        } catch (error: any) {
+            message.error(error.msg);
+        }
+    };
+
+    const init = async () => {
+        setLoading(true);
+        if (props.id) {
+            await fetchDetail();
+        }
+        setLoading(false);
+    };
+
+    React.useEffect(() => {
+        init();
+    }, []);
+
+    // 点击确定
+    const handleClickConfirm = () => {
+        form.validateFields().then(async (values) => {
+            const data = { ...values };
+            if(values.knowledge_type === '5'){
+                data.custom_separator = [ '"\\n"'];
+                data.sentence_size = 300;
+            }else{
+                data.sentence_size = 20;
+                data.custom_separator = [ '"\\n"'];
+            }
+            console.log(data, 'data');
+            await onClickConfirm(props.id, data);
+        }).catch((error) => {
+            console.error(error);
+        });
+    };
+
+    return (
+        <Modal
+            width={500}
+            title='重命名'
+            destroyOnClose={true}
+            maskClosable={false}
+            centered={true}
+            open={open}
+            onOk={handleClickConfirm}
+            onCancel={onClickCancel}
+        >
+            <Spin spinning={loading}>
+                <Form form={form} layout='vertical'>
+                    <FormItem
+                        label='文件名称'
+                        name='name'
+                    >
+                        <Input placeholder='请输入知识库名称' />
+                    </FormItem>
+                    {/* <FormItem
+                        label='知识类型'
+                        name='knowledge_type'
+                        rules={[{ required: true, message: '知识类型不能为空' }]}
+                    >
+                        <Select
+                            style={{ width: '100%' }}
+                            placeholder='请选择知识类型'
+                            allowClear={true}
+                        >
+                            <Option value='1'>1:文章知识:支持pdf,url,docx</Option>
+                            <Option value='2'>2:问答知识-文档:支持pdf,url,docx</Option>
+                            <Option value='3'>3:问答知识-表格:支持xlsx</Option>
+                            <Option value='4'>4:商品库-表格:支持xlsx</Option>
+                            <Option value='5'>5:自定义:支持pdf,url,docx</Option>
+                        </Select>
+                    </FormItem> */}
+                    <div style={{ width: '100%', height: 10 }}></div>
+                </Form>
+            </Spin>
+        </Modal>
+    );
+};
+
+export default InfoModal;

+ 177 - 0
src/pages/takai/knowledgeLib/detail/components/InfoModalSetting.tsx

@@ -0,0 +1,177 @@
+import * as React from 'react';
+import { Modal, Spin, Form, Input, Select, message, Checkbox, GetProp } from 'antd';
+import { apis, ModifyDocumentSettingApiParams } from '@/apis';
+
+const FormItem = Form.Item;
+const { Option } = Select;
+
+
+interface Props {
+    id: string,
+    open: boolean,
+    onClickConfirm: (id: string, data: ModifyDocumentSettingApiParams) => Promise<any>,
+    onClickCancel: () => void,
+};
+
+const InfoModalSetting: React.FC<Props> = (props: Props) => {
+    const {
+        id,
+        open,
+        onClickConfirm,
+        onClickCancel
+    } = props;
+
+    const [form] = Form.useForm();
+
+    const [loading, setLoading] = React.useState<boolean>(false);
+
+    const [isVisibleSlice, setIsVisibleSlice] = React.useState(false);
+    const [isVisibleSeparator, setIsVisibleSeparator] = React.useState(false);
+    const options = [
+        { label: '身份证', value: 'ID' },
+        { label: '手机号', value: 'Phone' },
+        { label: '银行卡', value: 'Car' },
+        { label: '自定义', value: 'Custom' },
+      ];
+
+    // 获取知识设置详情
+    const fetchDetail = async () => {
+        try {
+            const res = await apis.fetchTakaiDocumentSettingLibApi(props.id);
+            console.log(res.data, 'res.data');
+            const { knowledgeId, documentId, setSlice, setAnalyze, sliceValue } = res.data;
+            if(res.data.setSlice === '3'){
+                setIsVisibleSlice(!isVisibleSlice);
+            }
+            form.setFieldsValue({
+                knowledgeId: knowledgeId,
+                documentId: documentId,
+                setSlice: setSlice,
+                setAnalyze: setAnalyze,
+                sliceValue: sliceValue,
+            });
+        } catch (error: any) {
+            message.error(error.msg);
+        }
+    };
+
+    const onChangeF = (value: string) => {
+        if (value === '3') {
+            setIsVisibleSlice(!isVisibleSlice);
+        } else {
+            setIsVisibleSlice(false);
+        }
+    };
+
+    const init = async () => {
+        setLoading(true);
+        if (props.id) {
+            await fetchDetail();
+        }
+        setLoading(false);
+    };
+
+    React.useEffect(() => {
+        init();
+    }, []);
+
+    // 点击确定
+    const handleClickConfirm = () => {
+        form.validateFields().then(async (values) => {
+            const data = { ...values };
+            // if (values.knowledge_type === '5') {
+            //     data.custom_separator = ['"\\n"'];
+            //     data.sentence_size = 300;
+            // } else {
+            //     data.sentence_size = 20;
+            //     data.custom_separator = ['"\\n"'];
+            // }
+            console.log(data, 'data');
+            await onClickConfirm(props.id, data);
+        }).catch((error) => {
+            console.error(error);
+        });
+    };
+
+    return (
+        <Modal
+            width={600}
+            title='知识设置'
+            destroyOnClose={true}
+            maskClosable={false}
+            centered={true}
+            open={open}
+            onOk={handleClickConfirm}
+            onCancel={onClickCancel}
+        >
+            <Spin spinning={loading}>
+                <Form form={form} layout='vertical'>
+                    <FormItem
+                        label='切片设置'
+                        name='setSlice'
+                    >
+                        {/* <Input placeholder='请输入知识库名称' /> */}
+                        <Select
+                            style={{ width: '100%' }}
+                            allowClear={true}
+                            placeholder='请选择切片设置'
+                            onChange={onChangeF}
+                        >
+                            <Option value='0'>按标题段落切片</Option>
+                            <Option value='1'>按页切片</Option>
+                            <Option value='2'>按问答对切片</Option>
+                            <Option value='3'>自定义切片</Option>
+                        </Select>
+                    </FormItem>
+
+                    {isVisibleSlice &&
+                        <FormItem
+                        label='分隔符'
+                        name='sliceValue'
+                        rules={[{ required: true, message: '自定义切片设置不能为空' }]}
+                    >
+                        <Input max={1024} 
+                        />
+                    </FormItem>
+                    }
+
+                    <FormItem
+                        label='解析设置'
+                        name='setAnalyze'
+                    >
+                        <Select
+                            style={{ width: '100%' }}
+                            placeholder='请选择解析设置'
+                            allowClear={true}
+                        >
+                            {/* <Option value='0'>过滤图片</Option> */}
+                            <Option value='1'>图片转换成标识符</Option>
+                            {/* <Option value='2'>多模态图片理解</Option> */}
+                        </Select>
+                    </FormItem>
+                    
+                    {/* <FormItem
+                        label='隐藏敏感信息'
+                        name=''
+                    >
+                        <Checkbox.Group options={options} onChange={onChange} />
+
+                        {isVisibleSeparator &&
+                        <FormItem
+                        label=''
+                        name=''
+                        rules={[{ required: true, message: '问答应用名称不能为空' }]}
+                    >
+                        <Input max={1024} 
+                        />
+                    </FormItem>
+                    }
+                    </FormItem> */}
+                    <div style={{ width: '100%', height: 10 }}></div>
+                </Form>
+            </Spin>
+        </Modal>
+    );
+};
+
+export default InfoModalSetting;

+ 302 - 0
src/pages/takai/knowledgeLib/detail/index.tsx

@@ -0,0 +1,302 @@
+import * as React from 'react';
+import { useParams, Link } from 'react-router-dom';
+import { observer } from 'mobx-react';
+import store from './store';
+import './style.less';
+import { Button, Table, TableColumnsType, Modal, TablePaginationConfig, Upload, UploadProps, message, Spin } from 'antd';
+import { EditOutlined, DeleteOutlined, InboxOutlined, PlusOutlined, FileOutlined } from '@ant-design/icons';
+import InfoModal from './components/InfoModal';
+import InfoModalSetting from './components/InfoModalSetting';
+import router from '@/router';
+
+import { Record, RecordKonwledge } from './types';
+import dayjs from 'dayjs';
+import { set } from 'mobx';
+
+const { Dragger } = Upload;
+
+const KnowledgeLibInfo: React.FC = () => {
+
+    const {
+        state,
+        init,
+        onClickModify,
+        onClickDelete,
+        onChangePagination,
+        onClickDocumentDetail,
+        infoModalOnClickConfirm,
+        infoModalOnClickCancel,
+        infoModalSettingOnClickConfirm,
+        infoModalSettingOnClickCancel,
+        onClickSettings,
+        reset
+    } = store;
+    const {
+        knowledge_id,
+        listLoading,
+        page,
+        list,
+        infoModalOpen,
+        infoModalId,
+        infoModalSettingOpen,
+        infoModalSettingId,
+        knowledgeDetail,
+    } = state;
+
+    const [uploadLoading, setUploadLoading] = React.useState(false);
+
+    const params = useParams();
+
+    const props: UploadProps = {
+        name: 'file',
+        multiple: true,
+        action: '/api/takai/api/uploadDocument/' + params.knowledgeId,
+
+        beforeUpload(file, fileList) {
+            setUploadLoading(true);
+            // 自定义上传逻辑
+            if (fileList.length > 1) {
+                setUploadLoading(false);
+                message.error('一次只能上传一个文件');
+                return false;
+            }
+            if (file.name.split('.').pop() !== 'pdf') {
+                setUploadLoading(false);
+                message.error('仅支持上传pdf文档');
+                return false;
+            }
+        },
+        onChange(info) {
+            const { status } = info.file;
+
+            if (status !== 'uploading') {
+                console.log(status, 'status--uploading');
+            }
+            if (status === 'done') {
+                console.log(status, 'status--done');
+                console.info(info.file.response, 'info.file.response.data');
+                if (info.file.response.code === 200 && info.file.response.data === 1) {
+                    message.success(`${info.file.name} file uploaded successfully.`);
+                    init(params.knowledgeId);
+                }
+                setUploadLoading(false);
+            } else if (status === 'error') {
+                console.log(status, 'status--error');
+                message.error(`${info.file.name} file upload failed.`);
+                setUploadLoading(false);
+            }
+        },
+        onDrop(e) {
+            console.log('Dropped files', e.dataTransfer.files);
+        },
+    };
+
+    React.useEffect(() => {
+        init(params.knowledgeId);
+        return () => reset();
+    }, []);
+
+    const columns: TableColumnsType<Record> = [
+        {
+            title: '序号',
+            dataIndex: 'index',
+            width: 80,
+            render: (text, record, index) => {
+                return index + 1;
+            }
+        },
+        {
+            title: '文件名',
+            dataIndex: 'name',
+            width: 300,
+            render: (text, record) => {
+                return (
+                    `${text}`
+                )
+            }
+        },
+        {
+            title: '文件大小',
+            dataIndex: 'length',
+            width: 100,
+            render: (text) => {
+                if (text) {
+                    const size = (text / 1024 / 1024).toFixed(2);
+                    return `${size}M`;
+                }
+            }
+        },
+        {
+            title: '分段',
+            dataIndex: 'custom_separator',
+            width: 100,
+            render: (text) => {
+                if (text) {
+                    return `${text}`;
+                } else {
+                    return '--';
+                }
+            }
+        },
+        {
+            title: '上传时间',
+            dataIndex: 'createTime',
+            width: 180,
+            render: (text) => {
+                if (text) {
+                    return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
+                } else {
+                    return '--';
+                }
+            }
+        },
+        {
+            title: '更新时间',
+            dataIndex: 'updateTime',
+            width: 180,
+            render: (text) => {
+                if (text) {
+                    return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
+                } else {
+                    return '--';
+                }
+            }
+        },
+        {
+            title: '操作',
+            dataIndex: 'operation',
+            width: 180,
+            fixed: 'right',
+            render: (text, record) => {
+                return (
+                    <>
+                        <a style={{ marginRight: 16 }}
+                            onClick={() => {
+                                router.navigate({ pathname: '/takai/knowledgeLib/slice/' + record.documentId + '/' + params.knowledgeId + '/' + state.knowledgeDetail.embeddingId });
+                            }}>
+                            切片
+                        </a>
+                        <a
+                            style={{ marginRight: 16 }}
+                            onClick={() => {
+                                onClickSettings(record.documentId);
+                            }}
+                        >
+                            配置
+                        </a>
+
+                        <a
+                            style={{ marginRight: 16 }}
+                            onClick={() => {
+                                onClickModify(record.documentId);
+                            }}>
+                            <EditOutlined />
+                        </a>
+
+                        <a
+                            className='text-error'
+                            onClick={() => {
+                                Modal.confirm({
+                                    title: '删除',
+                                    content: `确定删除知识文件:${record.name}吗?`,
+                                    okType: 'danger',
+                                    onOk: async () => {
+                                        await onClickDelete(record.documentId);
+                                    }
+                                });
+                            }}
+                        >
+                            <DeleteOutlined />
+                        </a>
+                    </>
+                )
+            }
+        }
+    ];
+
+    const paginationConfig: TablePaginationConfig = {
+        // 显示数据总量
+        showTotal: (total: number) => {
+            return `共 ${total} 条`;
+        },
+        // 展示分页条数切换
+        showSizeChanger: true,
+        // 指定每页显示条数
+        pageSizeOptions: ['10', '20', '50', '100'],
+        // 快速跳转至某页
+        showQuickJumper: true,
+        current: page.page,
+        pageSize: page.size,
+        total: page.total,
+        onChange: async (page, pageSize) => {
+            await onChangePagination(page, pageSize);
+        },
+    };
+
+    return (
+        <div className='knowledgeLibInfo'>
+            <Spin spinning={uploadLoading || listLoading}>
+                <div className='knowledgeLibList-operation'>
+                    {
+                        page.total === 0 &&
+                        <>
+                            <div style={{ marginTop: 20, width: '100%', height: '200px' }}>
+                                <Dragger {...props}>
+                                    <p className="ant-upload-drag-icon">
+                                        <InboxOutlined />
+                                    </p>
+                                    <p >
+                                        点击上传,或拖放文件到此处
+                                    </p >
+                                    <p className="ant-upload-hint">
+                                        仅支持上传pdf文档,文档大小不超过50M.
+                                    </p>
+                                </Dragger>
+                            </div>
+                        </>
+                    }
+                </div>
+                {
+                    page.total > 0 &&
+                    <>
+                        <div>
+                            <Upload {...props}>
+                                <Button type='primary' icon={<PlusOutlined />}>上传知识文件</Button>
+                            </Upload>
+                        </div>
+
+                        <Table
+                            scroll={{ x: 'max-content' }}
+                            rowKey={(record) => record.documentId}
+                            loading={listLoading}
+                            columns={columns}
+                            dataSource={list}
+                            pagination={paginationConfig}
+                        />
+                        {
+                            infoModalOpen &&
+                            <InfoModal
+                                id={infoModalId}
+                                open={infoModalOpen}
+                                onClickConfirm={infoModalOnClickConfirm}
+                                onClickCancel={infoModalOnClickCancel}
+                            />
+                        }
+
+                        {
+                            infoModalSettingOpen &&
+                            <InfoModalSetting
+                                id={infoModalSettingId}
+                                open={infoModalSettingOpen}
+                                onClickConfirm={infoModalSettingOnClickConfirm}
+                                onClickCancel={infoModalSettingOnClickCancel}
+                            />
+                        }
+                    </>
+                }
+            </Spin>
+        </div>
+    );
+};
+
+export default observer(KnowledgeLibInfo);

+ 264 - 0
src/pages/takai/knowledgeLib/detail/store.ts

@@ -0,0 +1,264 @@
+import { action, makeAutoObservable } from 'mobx';
+import { message } from 'antd';
+import { apis, ModifyDocumentApiParams, ModifyDocumentSettingApiParams } from '@/apis';
+import { State, ReadonlyState, StateAction, DocumentLibInfoStore } from './types';
+
+// 定义状态
+const stateGenerator = (): ReadonlyState => ({
+    knowledge_id: '',
+    listLoading: false,
+    list: [],
+    infoModalId: '',
+    infoModalOpen: false,
+    infoModalSettingId: '',
+    infoModalSettingOpen: false,
+    page: {
+        page: 1,
+        size: 10,
+        total: 0,
+    },
+    knowledgeDetail: {
+        knowledgeId: '',
+        embeddingId: '',
+        name: '',
+    },
+});
+
+// 修改状态
+const stateActionsGenerator = (state: State): StateAction => {
+    return {
+        setknowledge_id(knowledge_id) {
+            state.knowledge_id = knowledge_id;
+        },
+        setListLoading: (loading) => {
+            state.listLoading = loading;
+        },
+        setList: (list) => {
+            state.list = list;
+        },
+        setInfoModalId: (id) => {
+            state.infoModalId = id;
+        },
+        setInfoModalOpen: (open) => {
+            state.infoModalOpen = open;
+        },
+        setPage: (page) => {
+            state.page = page;
+        },
+        setInfoModalSettingOpen: (open) => {
+            state.infoModalSettingOpen = open;
+        },
+        setInfoModalSettingId: (id) => {
+            state.infoModalSettingId = id;
+        },
+        setKnowledgeDetail: (knowledgeDetail) => {
+            state.knowledgeDetail = knowledgeDetail;
+        },
+    };
+};
+
+// 使用仓库
+const useKnowledgeLibInfoStore = (): DocumentLibInfoStore => {
+    const state = makeAutoObservable(stateGenerator());
+    const actions = stateActionsGenerator(state);
+
+    const api = {
+        // 获取知识列表
+        fetchDocumentLibList: async () => {
+            actions.setListLoading(true);
+            try {
+                const data = {
+                    knowledge_id: state.knowledge_id,
+                    page: state.page.page,
+                    size: state.page.size,
+                };
+                const res = await apis.fetchTakaiDocumentLibListApi(data);
+                actions.setList(res.rows);
+                actions.setPage({
+                    ...state.page,
+                    total: res.total,
+                });
+            } catch (error: any) {
+                console.error(error);
+            } finally {
+                actions.setListLoading(false);
+            }
+        },
+        // 修改知识
+        modifyDocumentLib: async (id: string, data: ModifyDocumentApiParams) => {
+            try {
+                await apis.modifyTakaiDocumentLibApi(id, data);
+                // 获取知识列表
+                api.fetchDocumentLibList();
+                message.success('修改成功');
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+        // 删除知识
+        deleteDocumentLib: async (id: string) => {
+            try {
+                await apis.deleteTakaiDocumentLibApi(id);
+                // 获取知识列表
+                api.fetchDocumentLibList();
+                message.success('删除成功');
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+
+        // 修改知识配置
+        modifyDocumentSettingLib: async (id: string, data: ModifyDocumentSettingApiParams) => {
+            try {
+                const res = await apis.modifyTakaiDocumentSettingLibApi(id, data);
+                if (res.data === 1) {
+                    // 获取知识列表
+                    api.fetchDocumentLibList();
+                    message.success('修改成功');
+                } else {
+                    message.success('修改失败');
+                }
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+
+        // 获取知识库详情
+        fetchKnowledgeLibDetail: async () => {
+            try {
+                const res = await apis.fetchTakaiKnowledgeLibDetail(state.knowledge_id);
+                const { knowledgeId, embeddingId, name } = res.data;
+                actions.setKnowledgeDetail({
+                    knowledgeId: knowledgeId,
+                    embeddingId: embeddingId,
+                    name: name,
+                });
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        }
+    }
+
+    // 更改分页
+    const onChangePagination: DocumentLibInfoStore['onChangePagination'] = async (page, size) => {
+        actions.setPage({
+            ...state.page,
+            page: page,
+            size: size,
+        });
+        // 获取知识列表
+        api.fetchDocumentLibList();
+    }
+
+    // 点击上传文件
+    const onClickDocumentDetail: DocumentLibInfoStore['onClickDocumentDetail'] = () => {
+        api.fetchDocumentLibList();
+    }
+
+    // 点击修改
+    const onClickModify: DocumentLibInfoStore['onClickModify'] = (id) => {
+        actions.setInfoModalId(id);
+        actions.setInfoModalOpen(true);
+    }
+
+    // 点击配置
+    const onClickSettings: DocumentLibInfoStore['onClickSettings'] = (id) => {
+        actions.setInfoModalSettingId(id);
+        actions.setInfoModalSettingOpen(true);
+    }
+
+    // 信息弹出层-点击确定
+    const infoModalOnClickConfirm: DocumentLibInfoStore['infoModalOnClickConfirm'] = async (id, data) => {
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
+
+        actions.setInfoModalOpen(initialInfoModalOpen);
+
+        if (id) {
+            // 修改知识数据
+            api.modifyDocumentLib(id, data);
+        }
+    }
+
+    // 信息弹出层-点击取消
+    const infoModalOnClickCancel: DocumentLibInfoStore['infoModalOnClickCancel'] = () => {
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
+
+        actions.setInfoModalOpen(initialInfoModalOpen);
+    }
+
+    // 知识配置信息弹出层-点击确定
+    const infoModalSettingOnClickConfirm: DocumentLibInfoStore['infoModalSettingOnClickConfirm'] = async (id, data) => {
+        const initialInfoModalSettingOpen = stateGenerator().infoModalSettingOpen;
+
+        actions.setInfoModalSettingOpen(initialInfoModalSettingOpen);
+
+        if (id) {
+            // 修改知识数据
+            api.modifyDocumentSettingLib(id, data);
+        }
+    }
+
+    // 只是配置信息弹出层-点击取消
+    const infoModalSettingOnClickCancel: DocumentLibInfoStore['infoModalSettingOnClickCancel'] = () => {
+        const initialInfoModalSettingOpen = stateGenerator().infoModalSettingOpen;
+
+        actions.setInfoModalSettingOpen(initialInfoModalSettingOpen);
+    }
+
+    // 点击删除
+    const onClickDelete: DocumentLibInfoStore['onClickDelete'] = async (id) => {
+        // 删除知识文件
+        await api.deleteDocumentLib(id);
+    }
+
+
+    // 初始渲染
+    const init: DocumentLibInfoStore['init'] = (id) => {
+        // 获取知识列表
+        if (id) {
+            actions.setknowledge_id(id);
+            api.fetchDocumentLibList();
+            api.fetchKnowledgeLibDetail();
+        }
+    }
+
+    // 状态重置
+    const reset: DocumentLibInfoStore['reset'] = () => {
+        const initialListLoading = stateGenerator().listLoading;
+        const initialList = stateGenerator().list;
+        const initialInfoModalId = stateGenerator().infoModalId;
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
+        const initialPage = stateGenerator().page;
+        const knowledge_id = stateGenerator().knowledge_id;
+        const initialInfoModalSettingId = stateGenerator().infoModalSettingId;
+        const initialInfoModalSettingOpen = stateGenerator().infoModalSettingOpen;
+        const initialKnowledgeDetail = stateGenerator().knowledgeDetail;
+
+        actions.setListLoading(initialListLoading);
+        actions.setList(initialList);
+        actions.setInfoModalId(initialInfoModalId);
+        actions.setInfoModalOpen(initialInfoModalOpen);
+        actions.setPage(initialPage);
+        actions.setknowledge_id(knowledge_id);
+        actions.setInfoModalSettingId(initialInfoModalSettingId);
+        actions.setInfoModalSettingOpen(initialInfoModalSettingOpen);
+        actions.setKnowledgeDetail(initialKnowledgeDetail);
+    }
+
+    return {
+        state,
+        onChangePagination,
+        onClickDocumentDetail,
+        onClickModify,
+        infoModalOnClickConfirm,
+        infoModalOnClickCancel,
+        onClickDelete,
+        init,
+        onClickSettings,
+        infoModalSettingOnClickConfirm,
+        infoModalSettingOnClickCancel,
+        reset
+    };
+};
+
+export default useKnowledgeLibInfoStore();

+ 6 - 0
src/pages/takai/knowledgeLib/detail/style.less

@@ -0,0 +1,6 @@
+.knowledgeLibInfo {
+  width: 100%;
+  height: 100%;
+  background: #FFFFFF;
+  border-radius: @border-radius-base;
+}

+ 69 - 0
src/pages/takai/knowledgeLib/detail/types.ts

@@ -0,0 +1,69 @@
+import { ModifyDocumentApiParams, ModifyDocumentSettingApiParams } from '@/apis';
+
+export type Record = {
+    documentId: string,
+    name: string,
+    url: string,
+    length: number,
+    sentence_size: number,
+    knowledge_type: number,
+    custom_separator: string[],
+    embedding_stat: number,
+    word_num: number,
+    parse_image: number
+};
+
+export type RecordKonwledge = {
+    knowledgeId: string,
+    embeddingId: string,
+    name: string,
+};
+
+// 定义状态
+export type State = {
+    knowledge_id: string,
+    listLoading: boolean,
+    list: Record[],
+    infoModalId: string,
+    infoModalOpen: boolean,
+    infoModalSettingId: string,
+    infoModalSettingOpen: boolean,
+    page: {
+        page: number,
+        size: number,
+        total: number,
+    },
+    knowledgeDetail: RecordKonwledge,
+};
+
+// 只读状态
+export type ReadonlyState = Readonly<State>;
+
+// 修改状态
+export type StateAction = {
+    setknowledge_id(knowledge_id: string): unknown;
+    setListLoading: (loading: State['listLoading']) => void,
+    setList: (list: State['list']) => void,
+    setInfoModalId: (id: State['infoModalId']) => void,
+    setInfoModalOpen: (open: State['infoModalOpen']) => void,
+    setInfoModalSettingId: (id: State['infoModalSettingId']) => void,
+    setInfoModalSettingOpen: (open: State['infoModalSettingOpen']) => void,
+    setPage: (page: State['page']) => void,
+    setKnowledgeDetail: (knowledgeDetail: State['knowledgeDetail']) => void,
+};
+
+// 仓库类型
+export type DocumentLibInfoStore = {
+    state: ReadonlyState,
+    init: (knowledgeId?: string) => void,
+    onChangePagination: (page: number, size: number) => Promise<any>,
+    onClickDocumentDetail: (knowledgeId?: string) => void,
+    onClickModify: (id: string) => void,
+    infoModalOnClickConfirm: (id: string, data: ModifyDocumentApiParams) => Promise<any>,
+    infoModalOnClickCancel: () => void,
+    onClickDelete: (id: string) => Promise<any>,
+    onClickSettings: (id: string) => void,
+    infoModalSettingOnClickConfirm: (id: string, data: ModifyDocumentSettingApiParams) => Promise<any>,
+    infoModalSettingOnClickCancel: () => void,
+    reset: () => void,
+};

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

@@ -0,0 +1,165 @@
+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.fetchTakaiKnowledgeLibDetail(props.id);
+            const { name, embeddingId, description } = res.data;
+            form.setFieldsValue({
+                name: name,
+                embeddingId: embeddingId,
+                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: '向量化模型不能为空' }]}
+                    >
+                        {
+                            getTitle() === '创建知识库' &&
+                            <Select
+                                style={{ width: '100%' }}
+                                placeholder='请选择向量化模型'
+                                allowClear={true}
+                            >
+                                <Option value='multilingual-e5-large-instruct'>multilingual-e5-large-instruct</Option>
+                            </Select>
+                        }
+
+                        {
+                            getTitle() === '修改知识库' &&
+                            <Select
+                                style={{ width: '100%' }}
+                                placeholder='请选择向量化模型'
+                                allowClear={true}
+                                disabled={true}
+                            >
+                                <Option value='multilingual-e5-large-instruct'>multilingual-e5-large-instruct</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;

+ 194 - 0
src/pages/takai/knowledgeLib/list/index.tsx

@@ -0,0 +1,194 @@
+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 dayjs from 'dayjs';
+import store from './store';
+import { Record } from './types';
+import './style.less';
+
+const KnowledgeLibList: React.FC = () => {
+    const {
+        state,
+        onChangePagination,
+        onClickCreate,
+        onClickModify,
+        infoModalOnClickConfirm,
+        infoModalOnClickCancel,
+        onClickDelete,
+        init,
+        reset
+    } = store;
+    const {
+        listLoading,
+        list,
+        infoModalId,
+        infoModalOpen,
+        page
+    } = state;
+
+    React.useEffect(() => {
+        init();
+        return () => reset();
+    }, []);
+
+    const columns: TableColumnsType<Record> = [
+        {
+            title: '序号',
+            dataIndex: 'index',
+            width: 80,
+            render: (text, record, index) => {
+                return index + 1;
+            }
+        },
+        {
+            title: '知识库名称',
+            dataIndex: 'name',
+            render: (text, record) => {
+                return (
+                    <Link to={{ pathname: `/takai/knowledgeLib/${record.knowledgeId}` }} >
+                        {text}
+                    </Link>
+                )
+            }
+        },
+        {
+            title: '使用空间',
+            dataIndex: 'length',
+            render: (text) => {
+                const size = (text / 1024).toFixed(2);
+                return `${size}M`;
+            }
+        },
+        {
+            title: '字符数量',
+            dataIndex: 'wordNum',
+            render: (text) => {
+                if(text){
+                    return `${text}字`;
+                }else{
+                    return '--';
+                }
+            }
+        },
+        {
+            title: '文件数量',
+            dataIndex: 'documentSize',
+        },
+        {
+            title: '创建时间',
+            dataIndex: 'createTime',
+            width: 200,
+            render: (text) => {
+                if (text) {
+                    return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
+                } else {
+                    return '--';
+                }
+            }
+        },
+        {
+            title: '更新时间',
+            dataIndex: 'updateTime',
+            width: 200,
+            render: (text) => {
+                if (text) {
+                    return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
+                } else {
+                    return '--';
+                }
+            }
+        },
+        {
+            title: '操作',
+            dataIndex: 'operation',
+            width: 150,
+            fixed: 'right',
+            render: (text, record) => {
+                return (
+                    <>
+                        <a
+                            style={{ marginRight: 16 }}
+                            onClick={() => {
+                                onClickModify(record.knowledgeId);
+                            }}
+                        >
+                            <EditOutlined />
+                        </a >
+                        <a
+                            className='text-error'
+                            onClick={() => {
+                                Modal.confirm({
+                                    title: '删除',
+                                    content: `确定删除知识库名称${record.name}吗?`,
+                                    okType: 'danger',
+                                    onOk: async () => {
+                                        await onClickDelete(record.knowledgeId);
+                                    }
+                                });
+                            }}
+                        >
+                            <DeleteOutlined />
+                        </a>
+                    </>
+                )
+            }
+        }
+    ];
+
+    const paginationConfig: TablePaginationConfig = {
+        // 显示数据总量
+        showTotal: (total: number) => {
+            return `共 ${total} 条`;
+        },
+        // 展示分页条数切换
+        showSizeChanger: true,
+        // 指定每页显示条数
+        pageSizeOptions: ['10', '20', '50', '100'],
+        // 快速跳转至某页
+        showQuickJumper: true,
+        current: page.pageNumber,
+        pageSize: page.pageSize,
+        total: page.total,
+        onChange: async (page, pageSize) => {
+            await onChangePagination(page, pageSize);
+        },
+    };
+
+    return (
+        <div className='knowledgeLibList'>
+            <div className='knowledgeLibList-operation'>
+                <Button
+                    type='primary'
+                    icon={<PlusOutlined />}
+                    onClick={onClickCreate}
+                >
+                    创建知识库
+                </Button>
+            </div>
+            <div className='knowledgeLibList-table'>
+                <Table
+                    scroll={{ x: 'max-content' }}
+                    rowKey={(record) => record.knowledgeId}
+                    loading={listLoading}
+                    columns={columns}
+                    dataSource={list}
+                    pagination={paginationConfig}
+                />
+            </div>
+            {
+                infoModalOpen &&
+                <InfoModal
+                    id={infoModalId}
+                    open={infoModalOpen}
+                    onClickConfirm={infoModalOnClickConfirm}
+                    onClickCancel={infoModalOnClickCancel}
+                />
+            }
+        </div>
+    );
+};
+
+export default observer(KnowledgeLibList);

+ 204 - 0
src/pages/takai/knowledgeLib/list/store.ts

@@ -0,0 +1,204 @@
+import { makeAutoObservable } from 'mobx';
+import { message } from 'antd';
+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,
+        total: 0,
+    },
+});
+
+// 修改状态
+const stateActionsGenerator = (state: State): StateAction => {
+    return {
+        setListLoading: (loading) => {
+            state.listLoading = loading;
+        },
+        setList: (list) => {
+            state.list = list;
+        },
+        setInfoModalId: (id) => {
+            state.infoModalId = id;
+        },
+        setInfoModalOpen: (open) => {
+            state.infoModalOpen = open;
+        },
+        setPage: (page) => {
+            state.page = page;
+        },
+    };
+};
+
+// 使用仓库
+const useKnowledgeLibListStore = (): KnowledgeLibListStore => {
+    const state = makeAutoObservable(stateGenerator());
+    const actions = stateActionsGenerator(state);
+
+    const api = {
+        // 获取知识库列表
+        fetchKnowledgeLibList: async () => {
+            actions.setListLoading(true);
+            try {
+                const data = {
+                    pageNumber: state.page.pageNumber,
+                    pageSize: state.page.pageSize,
+                };
+                const res = await apis.fetchTakaiKnowledgeLibList(data);
+                console.log(res, 'res');
+                actions.setList(res.rows);
+                actions.setPage({
+                    ...state.page,
+                    total: res.total,
+                });
+            } catch (error: any) {
+                console.error(error);
+            } finally {
+                actions.setListLoading(false);
+            }
+        },
+        // 创建知识库
+        createKnowledgeLib: async (data: CreateOrModifyKnowledgeLibApiParams) => {
+            actions.setListLoading(true);
+            try {
+                const res =await apis.createTakaiKnowledgeLib(data);
+                // 获取知识库列表
+                api.fetchKnowledgeLibList();
+                if(res.data === 1 && res.code === 200){
+                    message.success('创建成功');
+                }else{
+                    message.error('创建失败');
+                }
+            } catch (error: any) {
+                message.error(error.msg);
+            }finally{
+                actions.setListLoading(false);
+            }
+        },
+        // 修改知识库
+        modifyKnowledgeLib: async (knowledgeId: string, data: CreateOrModifyKnowledgeLibApiParams) => {
+            try {
+                const res = await apis.modifyTakaiKnowledgeLib(knowledgeId, data);
+                // 获取知识库列表
+                api.fetchKnowledgeLibList();
+                if(res.data === 1 && res.code === 200){
+                    message.success('修改成功');
+                }else{
+                    message.error('修改失败');
+                }
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+        // 删除知识库
+        deleteKnowledgeLib: async (knowledgeId: string) => {
+            try {
+                const res = await apis.deleteTakaiKnowledgeLib(knowledgeId);
+                // 获取知识库列表
+                api.fetchKnowledgeLibList();
+                if(res.data === 1 && res.code === 200){
+                    message.success('删除成功');
+                }else{
+                    message.error('删除失败');
+                }
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+    }
+
+    // 更改分页
+    const onChangePagination: KnowledgeLibListStore['onChangePagination'] = async (pageNumber, pageSize) => {
+        actions.setPage({
+            ...state.page,
+            pageNumber: pageNumber,
+            pageSize: pageSize,
+        });
+        // 获取知识库列表
+        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) => {
+        // 删除知识库
+        await api.deleteKnowledgeLib(knowledgeId);
+    }
+
+    // 初始渲染
+    const init: KnowledgeLibListStore['init'] = async () => {
+        // 获取知识库列表
+        await api.fetchKnowledgeLibList();
+    }
+
+    // 状态重置
+    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
+    };
+};
+
+export default useKnowledgeLibListStore();

+ 14 - 0
src/pages/takai/knowledgeLib/list/style.less

@@ -0,0 +1,14 @@
+.knowledgeLibList {
+  &-operation {
+    padding: 20px;
+    background: #FFFFFF;
+    border-radius: @border-radius-base;
+    margin-bottom: 20px;
+  }
+
+  &-table {
+    padding: 20px;
+    background: #FFFFFF;
+    border-radius: @border-radius-base;
+  }
+}

+ 50 - 0
src/pages/takai/knowledgeLib/list/types.ts

@@ -0,0 +1,50 @@
+import { CreateOrModifyKnowledgeLibApiParams } from '@/apis';
+
+export type Record = {
+    [x: string]: any;
+    knowledgeId: string,
+    name: string,// 知识库名称
+    length: number,// 使用空间
+    wordNum: number,// 字符数量
+    documentSize: number,// 文件数量
+    createTime: string,// 创建时间
+    updateTime: string,// 更新时间
+};
+
+// 定义状态
+export type State = {
+    listLoading: boolean,
+    list: Record[],
+    infoModalId: string,
+    infoModalOpen: boolean,
+    page: {
+        pageNumber: number,
+        pageSize: number,
+        total: number,
+    },
+};
+
+// 只读状态
+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,
+};
+
+// 仓库类型
+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,
+};

+ 122 - 0
src/pages/takai/knowledgeLib/slice/detail/index.tsx

@@ -0,0 +1,122 @@
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { useParams } from 'react-router-dom';
+import { Form, Input, Button, message } from 'antd';
+import { apis } from '@/apis';
+import router from '@/router';
+
+const { TextArea } = Input;
+
+const FormItem = Form.Item;
+
+interface TakaiSliceDetailRequest {
+    knowledgeId: string,
+    sliceId: string,
+    sliceText: string,
+}
+const SliceDetail: React.FC = () => {
+
+    const [form] = Form.useForm();
+
+    const params = useParams();
+
+    const [listLoading, setListLoading] = React.useState(false);
+
+    const appApi = {
+        fetchList: async () => {
+            setListLoading(true);
+            try {
+                if (!params.sliceId || !params.knowledgeId) {
+                    throw new Error('参数错误');
+                }
+                const res = await apis.fetchTakaiSliceDetail(params.sliceId, params.knowledgeId);
+                const info = res.data.data;
+                form.setFieldsValue({
+                    slice_id: info.slice_id,
+                    slice_text: info.slice_text,
+                    document_id: info.document_id,
+                })
+                console.log(res, 'info');
+            } catch (error) {
+                console.error(error);
+            } finally {
+                setListLoading(false);
+            }
+        }
+    };
+
+    const init = async () => {
+        await appApi.fetchList();
+    }
+
+    React.useEffect(() => {
+        init();
+    }, [])
+
+    return (
+        <div>
+            <div className='questionAnswerList'>
+                <div style={{ overflow: 'hidden' }}>
+                    <Form
+                        style={{ paddingTop: '20px', height: '100%' }}
+                        form={form}
+                        layout='vertical'
+                    >
+                        <FormItem
+                            name="slice_text"
+                            rules={[{ required: true, message: '切片内容不能为空' }]}>
+                            <TextArea
+                                style={{
+                                    width: '50%',
+                                    height: '200px',
+                                    overflow: 'auto',
+                                    resize: 'both',
+                                    boxSizing: 'border-box',
+
+                                }}
+                                placeholder=""
+                                autoSize={{ minRows: 20, maxRows: 5000 }}
+                            />
+                        </FormItem>
+
+                        <Button
+                            type='primary'
+                            onClick={() => {
+                                form.validateFields().then(async (values) => {
+                                    // 验证参数是否存在
+                                    if (!params.knowledgeId || !params.sliceId) {
+                                        message.error('知识库ID或切片ID无效');
+                                        return;
+                                    }
+                                    const data = values;
+                                    const info = {
+                                        knowledgeId: params.knowledgeId,
+                                        sliceId: params.sliceId,
+                                        sliceText: values.slice_text,
+                                    };
+                                    // 编辑应用
+                                    const res = await apis.modifyTakaiSliceInfo(info);
+                                    if (res.code === 200 && res.data === 1) {
+                                        const info = {
+                                            text: '',
+                                            pageNum: 1,
+                                            pageSize: 10,
+                                        }
+                                        // 刷新列表
+                                        await router.navigate({ pathname: '/takai/knowledgeLib/slice/' + params.documentId + '/' + params.knowledgeId + '/' + params.embeddingId });
+                                        await apis.fetchTakaiSliceList(info);
+                                        message.success('修改成功');
+                                    }
+                                }).catch((error) => {
+                                    console.error(error);
+                                });
+                            }}
+                        >保存</Button>
+                    </Form>
+                </div>
+            </div>
+        </div>
+    )
+};
+
+export default observer(SliceDetail);

+ 215 - 0
src/pages/takai/knowledgeLib/slice/index.tsx

@@ -0,0 +1,215 @@
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { useParams } from 'react-router-dom';
+import { List, Button, Divider, Empty, Modal, Form, Input, message } from 'antd';
+import { SettingOutlined, DeleteOutlined } from '@ant-design/icons';
+import { apis } from '@/apis';
+import { PaginationConfig } from 'antd/es/pagination';
+import router from '@/router';
+import './style.less';
+
+const FormItem = Form.Item;
+const SliceList: React.FC = () => {
+
+    const [form] = Form.useForm();
+
+    const params = useParams();
+
+    interface Item {
+        slice_id: string,
+        document_id: string,
+        slice_text: number,
+    };
+
+    interface PageInfo {
+        pageNum: number,
+        pageSize: number,
+        total: number,
+    };
+
+    const [listLoading, setListLoading] = React.useState(false);
+    const [list, setList] = React.useState<Item[]>([]);
+    const [page, setPage] = React.useState<PageInfo>({
+        pageNum: 1,
+        pageSize: 10,
+        total: 0,
+    });
+
+    const appApi = {
+        fetchList: async (p0: { searchText: string; }) => {
+            setListLoading(true);
+            try {
+                const res = await apis.fetchTakaiSliceList({
+                    knowledge_id: params.knowledgeId || '',
+                    document_id: params.documentId || '',
+                    text: p0.searchText,
+                    pageSize: page.pageSize,
+                    pageNum: page.pageNum
+                })
+                const list = res.data.rows.map((item: any) => {
+                    return {
+                        slice_id: item.slice_id,
+                        document_id: item.document_id,
+                        slice_text: item.slice_text,
+                    }
+                });
+                setList(list);
+                setPage({
+                    pageNum: page.pageNum,
+                    pageSize: page.pageSize,
+                    total: res.data.total,
+                });
+            } catch (error) {
+                console.error(error);
+            } finally {
+                setListLoading(false);
+            }
+        },
+
+    };
+
+    const handleClickSearch = () => {
+        const values = form.getFieldsValue();
+        appApi.fetchList({ searchText: values.text });
+    }
+    const handleClickReset = () => {
+        form.resetFields();
+        appApi.fetchList({ searchText: '' });
+    }
+
+    const deleteSlice = async (slice_id: string, knowledgeId: string) => {
+        try {
+            if (!params.knowledgeId) {
+                throw new Error('知识库ID未定义,请检查路由参数');
+            }
+            const res = await apis.deleteTakaiSlice(slice_id, params.knowledgeId);
+            if (res.code === 200 && res.data === 1) {
+                appApi.fetchList({ searchText: '' });
+                message.success('删除切片成功');
+            }
+        } catch (error) {
+            console.error('删除切片失败:', error);
+        }
+    }
+
+    const init = async () => {
+        console.log('params', params.knowledgeId);
+        await appApi.fetchList({ searchText: '' });
+    }
+
+    React.useEffect(() => {
+        init();
+    }, [page.pageSize, page.pageNum])
+
+    const paginationConfig: PaginationConfig = {
+        // 显示数据总量
+        showTotal: (total: number) => {
+            return `共 ${total} 条`;
+        },
+        // 展示分页条数切换
+        showSizeChanger: true,
+        // 指定每页显示条数
+        // pageSizeOptions: ['2', '20', '50', '100'],
+        // 快速跳转至某页
+        showQuickJumper: true,
+        current: page.pageNum,
+        pageSize: page.pageSize,
+        total: page.total,
+        onChange: (pageNum, pageSize) => {
+            setPage({
+                pageNum: pageNum,
+                pageSize: pageSize,
+                total: page.total,
+            });
+        },
+    };
+
+    return (
+        <div>
+            <div className='dataExport-search'>
+                <Form form={form} layout='inline' colon={false}>
+                    <FormItem label='切片' name='text'>
+                        <Input />
+                    </FormItem>
+                    <FormItem>
+                        <Button
+                            style={{ marginRight: 16 }}
+                            type='primary'
+                            onClick={handleClickSearch}
+                        >
+                            查询
+                        </Button>
+                        <Button onClick={handleClickReset}>
+                            重置
+                        </Button>
+                    </FormItem>
+                </Form>
+            </div>
+            {
+                list.length
+                    ?
+                    <div className='questionAnswerList'>
+
+                        <div className='applicationList'>
+                            <List style={{ height: 400 }}
+                                grid={{
+                                    gutter: 16,
+                                    xs: 1,
+                                    sm: 2,
+                                    md: 4,
+                                    lg: 4,
+                                    xl: 6,
+                                    xxl: 3, // 展示的列数
+                                }}
+                                dataSource={list}
+                                renderItem={(item) => (
+                                    <List.Item>
+                                        <div className='card'>
+                                            <div style={{ height: 80, overflow: 'auto' }}>
+                                                {
+                                                    item.slice_text
+                                                }
+                                            </div>
+
+                                            <Divider plain></Divider>
+                                            <div style={{ display: 'flex', justifyContent: 'space-between', overflow: 'auto' }}>
+                                                <div style={{ overflow: 'auto' }}>
+                                                    <a style={{ marginRight: 20 }} onClick={() => {
+                                                        router.navigate({
+                                                            pathname: '/takai/knowledgeLib/slice/detail/' + item.slice_id + '/' + params.knowledgeId + '/' + params.documentId + '/'
+                                                                + params.embeddingId
+                                                        });
+                                                    }}>
+                                                        <SettingOutlined /> 编辑
+                                                    </a>
+                                                    <a className='text-error' onClick={() => {
+                                                        Modal.confirm({
+                                                            title: '删除',
+                                                            content: `确定删除切片: ` + item.slice_id + ` 吗?`,
+                                                            okType: 'danger',
+                                                            onOk: async () => {
+                                                                const knowledgeId = params.knowledgeId || ''; // 提供默认值
+                                                                await deleteSlice(item.slice_id, knowledgeId);
+                                                            }
+                                                        });
+                                                    }}>
+                                                        <DeleteOutlined /> 删除
+                                                    </a>
+                                                </div>
+                                            </div>
+
+                                        </div>
+                                    </List.Item>
+                                )}
+                                pagination={paginationConfig} // 分页 
+                            />
+                        </div>
+                    </div>
+                    :
+                    <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+            }
+        </div >
+    )
+};
+
+export default observer(SliceList);

+ 235 - 0
src/pages/takai/knowledgeLib/slice/store.ts

@@ -0,0 +1,235 @@
+import { action, makeAutoObservable } from 'mobx';
+import { message } from 'antd';
+import { apis, ModifyDocumentApiParams, ModifyDocumentSettingApiParams } from '@/apis';
+import { State, ReadonlyState, StateAction, DocumentLibInfoStore } from './types';
+
+// 定义状态
+const stateGenerator = (): ReadonlyState => ({
+    knowledge_id: '',
+    listLoading: false,
+    list: [],
+    infoModalId: '',
+    infoModalOpen: false,
+    infoModalSettingId: '',
+    infoModalSettingOpen: false,
+    page: {
+        page: 1,
+        size: 10,
+        total: 0,
+    },
+});
+
+// 修改状态
+const stateActionsGenerator = (state: State): StateAction => {
+    return {
+        setknowledge_id(knowledge_id) {
+            state.knowledge_id = knowledge_id;
+        },
+        setListLoading: (loading) => {
+            state.listLoading = loading;
+        },
+        setList: (list) => {
+            state.list = list;
+        },
+        setInfoModalId: (id) => {
+            state.infoModalId = id;
+        },
+        setInfoModalOpen: (open) => {
+            state.infoModalOpen = open;
+        },
+        setPage: (page) => {
+            state.page = page;
+        },
+        setInfoModalSettingOpen : (open) => {
+            state.infoModalSettingOpen = open;
+        },
+        setInfoModalSettingId: (id) => {
+            state.infoModalSettingId = id;
+        },
+    };
+};
+
+// 使用仓库
+const useKnowledgeLibInfoStore = (): DocumentLibInfoStore => {
+    const state = makeAutoObservable(stateGenerator());
+    const actions = stateActionsGenerator(state);
+
+    const api = {
+        // 获取知识列表
+        fetchDocumentLibList: async () => {
+            actions.setListLoading(true);
+            try {
+                console.log('state.knowledge_id', state.knowledge_id);
+                const data = {
+                    knowledge_id: state.knowledge_id,
+                    page: state.page.page,
+                    size: state.page.size,
+                };
+                const res = await apis.fetchTakaiDocumentLibListApi(data);
+                actions.setList(res.rows);
+                actions.setPage({
+                    ...state.page,
+                    total: res.total,
+                });
+            } catch (error: any) {
+                console.error(error);
+            } finally {
+                actions.setListLoading(false);
+            }
+        },
+        // 修改知识
+        modifyDocumentLib: async (id: string, data: ModifyDocumentApiParams) => {
+            try {
+                await apis.modifyTakaiDocumentLibApi(id, data);
+                // 获取知识列表
+                api.fetchDocumentLibList();
+                message.success('修改成功');
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+        // 删除知识
+        deleteDocumentLib: async (id: string) => {
+            try {
+                await apis.deleteTakaiDocumentLibApi(id);
+                // 获取知识列表
+                api.fetchDocumentLibList();
+                message.success('删除成功');
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+
+        // 修改知识配置
+        modifyDocumentSettingLib: async (id: string, data: ModifyDocumentSettingApiParams) => {
+            try {
+                await apis.modifyTakaiDocumentSettingLibApi(id, data);
+                // 获取知识列表
+                api.fetchDocumentLibList();
+                message.success('修改成功');
+            } catch (error: any) {
+                message.error(error.msg);
+            }
+        },
+    }
+
+    // 更改分页
+    const onChangePagination: DocumentLibInfoStore['onChangePagination'] = async (page, size) => {
+        actions.setPage({
+            ...state.page,
+            page: page,
+            size: size,
+        });
+        // 获取知识列表
+        api.fetchDocumentLibList();
+    }
+
+    // 点击上传文件
+    const onClickDocumentDetail: DocumentLibInfoStore['onClickDocumentDetail'] = () => {
+        api.fetchDocumentLibList();
+    }
+
+    // 点击修改
+    const onClickModify: DocumentLibInfoStore['onClickModify'] = (id) => {
+        actions.setInfoModalId(id);
+        actions.setInfoModalOpen(true);
+    }
+
+    // 点击配置
+    const onClickSettings: DocumentLibInfoStore['onClickSettings'] = (id) => {
+        actions.setInfoModalSettingId(id);
+        actions.setInfoModalSettingOpen(true);
+    }
+
+    // 信息弹出层-点击确定
+    const infoModalOnClickConfirm: DocumentLibInfoStore['infoModalOnClickConfirm'] = async (id, data) => {
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
+
+        actions.setInfoModalOpen(initialInfoModalOpen);
+
+        if (id) {
+            // 修改知识数据
+            api.modifyDocumentLib(id, data);
+        }
+    }
+
+    // 信息弹出层-点击取消
+    const infoModalOnClickCancel: DocumentLibInfoStore['infoModalOnClickCancel'] = () => {
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
+
+        actions.setInfoModalOpen(initialInfoModalOpen);
+    }
+
+    // 知识配置信息弹出层-点击确定
+    const infoModalSettingOnClickConfirm: DocumentLibInfoStore['infoModalSettingOnClickConfirm'] = async (id, data) => {
+        const initialInfoModalSettingOpen = stateGenerator().infoModalSettingOpen;
+
+        actions.setInfoModalSettingOpen(initialInfoModalSettingOpen);
+
+        if (id) {
+            // 修改知识数据
+            api.modifyDocumentSettingLib(id, data);
+        }
+    }
+
+    // 只是配置信息弹出层-点击取消
+    const infoModalSettingOnClickCancel: DocumentLibInfoStore['infoModalSettingOnClickCancel'] = () => {
+        const initialInfoModalSettingOpen = stateGenerator().infoModalSettingOpen;
+
+        actions.setInfoModalSettingOpen(initialInfoModalSettingOpen);
+    }
+
+    // 点击删除
+    const onClickDelete: DocumentLibInfoStore['onClickDelete'] = async (id) => {
+        // 删除知识文件
+        await api.deleteDocumentLib(id);
+    }
+
+
+    // 初始渲染
+    const init: DocumentLibInfoStore['init'] = (id) => {
+        // 获取知识列表
+        if(id){
+            actions.setknowledge_id(id);
+            api.fetchDocumentLibList();
+        }
+    }
+
+    // 状态重置
+    const reset: DocumentLibInfoStore['reset'] = () => {
+        const initialListLoading = stateGenerator().listLoading;
+        const initialList = stateGenerator().list;
+        const initialInfoModalId = stateGenerator().infoModalId;
+        const initialInfoModalOpen = stateGenerator().infoModalOpen;
+        const initialPage = stateGenerator().page;
+        const knowledge_id = stateGenerator().knowledge_id;
+        const initialInfoModalSettingId = stateGenerator().infoModalSettingId;
+        const initialInfoModalSettingOpen = stateGenerator().infoModalSettingOpen;
+
+        actions.setListLoading(initialListLoading);
+        actions.setList(initialList);
+        actions.setInfoModalId(initialInfoModalId);
+        actions.setInfoModalOpen(initialInfoModalOpen);
+        actions.setPage(initialPage);
+        actions.setknowledge_id(knowledge_id);
+        actions.setInfoModalSettingId(initialInfoModalSettingId);
+        actions.setInfoModalSettingOpen(initialInfoModalSettingOpen);
+    }
+
+    return {
+        state,
+        onChangePagination,
+        onClickDocumentDetail,
+        onClickModify,
+        infoModalOnClickConfirm,
+        infoModalOnClickCancel,
+        onClickDelete,
+        init,
+        onClickSettings,
+        infoModalSettingOnClickConfirm,
+        infoModalSettingOnClickCancel,
+        reset
+    };
+};
+
+export default useKnowledgeLibInfoStore();

+ 33 - 0
src/pages/takai/knowledgeLib/slice/style.less

@@ -0,0 +1,33 @@
+.questionAnswerList {
+  width: 100%;
+  height: 100%;
+  background: #FFFFFF;
+  border-radius: @border-radius-base;
+}
+
+.applicationList {
+  width: 100%;
+  height: 400px;
+  padding-top: 10px;
+}
+
+.card{
+  padding: 20px;
+  border: 1px solid @border-color;
+  border-radius: @border-radius-base;
+  height: 200px;
+  overflow: auto;
+}
+.card:hover{
+  border-color:@primary-color ;
+}
+
+.desc {
+  height: 35px;
+  overflow: auto;
+}
+
+.info-head {
+  width: 100%;
+  height: 35%;
+}

+ 61 - 0
src/pages/takai/knowledgeLib/slice/types.ts

@@ -0,0 +1,61 @@
+import { ModifyDocumentApiParams, ModifyDocumentSettingApiParams } from '@/apis';
+
+export type Record = {
+    documentId: string,
+    name: string,
+    url: string,
+    length: number,
+    sentence_size: number,
+    knowledge_type: number,
+    custom_separator: string[],
+    embedding_stat: number,
+    word_num: number,
+    parse_image: number
+};
+
+// 定义状态
+export type State = {
+    knowledge_id: string,
+    listLoading: boolean,
+    list: Record[],
+    infoModalId: string,
+    infoModalOpen: boolean,
+    infoModalSettingId: string,
+    infoModalSettingOpen: boolean,
+    page: {
+        page: number,
+        size: number,
+        total: number,
+    },
+};
+
+// 只读状态
+export type ReadonlyState = Readonly<State>;
+
+// 修改状态
+export type StateAction = {
+    setknowledge_id(knowledge_id: string): unknown;
+    setListLoading: (loading: State['listLoading']) => void,
+    setList: (list: State['list']) => void,
+    setInfoModalId: (id: State['infoModalId']) => void,
+    setInfoModalOpen: (open: State['infoModalOpen']) => void,
+    setInfoModalSettingId: (id: State['infoModalSettingId']) => void,
+    setInfoModalSettingOpen: (open: State['infoModalSettingOpen']) => void,
+    setPage: (page: State['page']) => void,
+};
+
+// 仓库类型
+export type DocumentLibInfoStore = {
+    state: ReadonlyState,
+    init: (knowledgeId?: string) => void,
+    onChangePagination: (page: number, size: number) => Promise<any>,
+    onClickDocumentDetail: (knowledgeId?: string) => void,
+    onClickModify: (id: string) => void,
+    infoModalOnClickConfirm: (id: string, data: ModifyDocumentApiParams) => Promise<any>,
+    infoModalOnClickCancel: () => void,
+    onClickDelete: (id: string) => Promise<any>,
+    onClickSettings: (id: string) => void,
+    infoModalSettingOnClickConfirm: (id: string, data: ModifyDocumentSettingApiParams) => Promise<any>,
+    infoModalSettingOnClickCancel: () => void,
+    reset: () => void,
+};

+ 738 - 0
src/pages/takai/questionAnswer/info/index.tsx

@@ -0,0 +1,738 @@
+import * as React from 'react';
+import { useLocation } from 'react-router-dom';
+import { observer } from 'mobx-react';
+import './style.less';
+import {
+    Button, Input, Form, Divider, Splitter, Select, InputNumber, InputNumberProps,
+    Radio, Switch, Row, Col, Slider, Space, RadioChangeEvent,
+    Spin, message
+} from 'antd';
+import { PlusCircleOutlined, MinusCircleOutlined } from '@ant-design/icons';
+import { apis } from '@/apis';
+import router from '@/router';
+
+const { TextArea } = Input;
+const FormItem = Form.Item;
+const { Option } = Select;
+const MAX_COUNT = 10;
+const Index = 1;
+
+const QuestionAnswerInfo: React.FC = () => {
+
+    const [form] = Form.useForm();
+
+    // top_p
+    const [topPValue, setTopPValue] = React.useState(0.1);
+    const TopPDecimalStep: React.FC = () => {
+
+        const onChange: InputNumberProps['onChange'] = (value) => {
+            if (Number.isNaN(value)) {
+                return;
+            }
+            setTopPValue(value as number);
+        };
+
+        return (
+            <Row>
+                <Col span={12}>
+                    <Slider
+                        min={0}
+                        max={1}
+                        onChange={onChange}
+                        // value={typeof topPValue === 'number' ? topPValue : 0}
+                        value = {topPValue}
+                        step={0.1}
+                    />
+                </Col>
+                <Col span={4}>
+                    <InputNumber
+                        min={0}
+                        max={1}
+                        style={{ margin: '0 16px', width: '100px' }}
+                        step={0.01}
+                        value={topPValue}
+                        onChange={onChange}
+                    />
+                </Col>
+            </Row>
+        );
+    };
+    const [tempValue, setTempValue] = React.useState(0.01);
+    // temperature
+    const TempDecimalStep: React.FC = () => {
+        const onChange: InputNumberProps['onChange'] = (value) => {
+            if (Number.isNaN(value)) {
+                return;
+            }
+            setTempValue(value as number);
+        };
+
+        return (
+            <Row>
+                <Col span={12}>
+                    <Slider
+                        min={0}
+                        max={1}
+                        onChange={onChange}
+                        // value={typeof tempValue === 'number' ? tempValue : 0}
+                        value={tempValue}
+                        step={0.01}
+                    />
+                </Col>
+                <Col span={4}>
+                    <InputNumber
+                        min={0}
+                        max={1}
+                        style={{ margin: '0 16px', width: '100px' }}
+                        step={0.01}
+                        value={tempValue}
+                        onChange={onChange}
+                    />
+                </Col>
+            </Row>
+        );
+    };
+
+    type ModelList = {
+        label: string,
+        value: string,
+    }[];
+    type KnowledgeList = {
+        label: string,
+        value: string,
+    }[];
+
+    const [step, setStep] = React.useState(1);
+    const [pageLoading, setPageLoading] = React.useState(false);
+    const [modelList, setModelList] = React.useState<ModelList>([]);
+    const [knowledgeList, setKnowledgeList] = React.useState<KnowledgeList>([]);
+    const [isVisible, setIsVisible] = React.useState(false);
+    const [isVisibleCus, setIsVisibleCus] = React.useState(false);
+    const [isVisibleSlice, setIsVisibleSlice] = React.useState(false);
+    const [isVisibleRerank, setIsVisibleRerank] = React.useState(false);
+    const [name, setName] = React.useState('');
+
+    const style: React.CSSProperties = {
+        display: 'flex',
+        flexDirection: 'column',
+        gap: 8,
+        width: 300,
+    };
+
+    const location = useLocation();
+
+    const init = async (id: string) => {
+        await Promise.all([
+            api.fetchKnowlegde(),
+            // api.fetchModelList(),
+        ])
+        if (id) {
+            await api.fetchDetail(id);
+        }
+    }
+
+    React.useEffect(() => {
+        const id = location?.state?.id;
+        init(id)
+    }, []);
+
+    // 定义一个状态来存储输入框数组
+    const [inputs, setInputs] = React.useState([{ id: 1, value: '' }]);
+
+    // 添加新输入框的函数
+    const addInput = () => {
+        const newId = inputs.length + 1; // 生成新的唯一ID
+        setInputs([...inputs, { id: newId, value: '' }]);
+    };
+
+    const delInput = () => {
+        const newId = inputs.length - 1; // 生成新的唯一ID
+        setInputs(inputs.slice(0, inputs.length - 1));
+    };
+
+    // 处理输入变更的函数
+    const handleChange = (id: number, value: string) => {
+        setInputs(inputs.map(input => (input.id === id ? { ...input, value } : input)));
+    };
+
+    // const onChange: InputNumberProps['onChange'] = (value) => {
+    //     console.log('changed', value);
+    // };
+
+    const onChangeShow = (checked: boolean) => {
+        console.log(`switch to ${checked}`);
+    };
+
+    const onChangeModel = (checked: boolean) => {
+        setIsVisibleRerank(!isVisibleRerank);
+    };
+
+    const onChangeCount = (value: string) => {
+        if (value === 'fixed') {
+            setIsVisibleSlice(!isVisibleSlice);
+        } else {
+            setIsVisibleSlice(false);
+        }
+    };
+
+    // 召回方式
+    const onChangeRecallMethod = (e: RadioChangeEvent) => {
+
+    };
+
+    // 获取应用详情
+    const api = {
+        fetchDetail: async (app_id: string) => {
+            setPageLoading(true);
+            try {
+                const res = await apis.fetchTakaiApplicationDetail(app_id)
+                console.log(res.data);
+                const sd = res.data.questionlist.map((item: any, index: number) => {
+                    return {
+                        "id": index + 1,
+                        "value": item.question,
+                    }
+                });
+
+                const info = res.data.detail;
+
+                setTopPValue(info.topP as number);
+                setTempValue(info.temperature as number);
+                setName(info.name);
+
+                interface Item2 {
+                    index_type_id: number,
+                    knowledge_id: string
+                }
+
+                interface Item {
+                    show_recall_result: boolean,
+                    recall_method: string,
+                    rerank_status: boolean,
+                    slice_config_type: string,
+                    slice_count: number,
+                    recall_slice_splicing_method: string,
+                    param_desc: string,
+                    rerank_model_name: string,
+                    rerank_index_type_list: [Item2],
+                    recall_index_type_list: [Item2]
+                }
+
+                const data_info: Item = JSON.parse(info.knowledgeInfo);
+
+                if (data_info.param_desc === 'custom') {
+
+                    setIsVisibleCus(!isVisibleCus);    //自定义回答风格
+                }
+                if (data_info.rerank_status === true) {
+                    setIsVisibleRerank(!isVisibleRerank) //模型
+                }
+                //召回切片数量
+                if (data_info.slice_config_type === 'fixed') {
+                    setIsVisibleSlice(!isVisibleSlice);
+                } else {
+                    setIsVisibleSlice(false);
+                }
+
+                form.setFieldsValue({
+                    id: info.id,
+                    name: info.name,  //应用名称
+                    desc: info.desc,  //应用描述
+                    prompt: info.prompt, //应用提示语
+                    top_p: info.topP as number, //topP
+                    temperature: info.temperature as number, //温度
+                    knowledge_ids: info.knowledgeIds,
+                    model: info.model,
+                    icon_color: info.icon_color,
+                    icon_type: info.icon_type,
+                    questionList: sd, //问题列表
+                    max_token: info.maxToken, //应用最大token
+                    updateDate: info.updateDate, // 更新时间
+
+                    param_desc: data_info.param_desc, //回答风格
+                    show_recall_result: data_info.show_recall_result, //是否展示召回结果
+                    recall_method: data_info.recall_method, //召回方式
+                    rerank_status: data_info.rerank_status, //开启rerank
+                    rerank_model_name: data_info.rerank_model_name, //模型名称
+                    slice_config_type: data_info.slice_config_type, // 召回切片数量
+                    slice_count: data_info.slice_count, // 切片数量
+                    recall_slice_splicing_method: data_info.recall_slice_splicing_method, // 切片内容
+
+                    // rerank_status = 1 rerank_index_type_list
+                    // recall_method = 'embedding' || 'mixed'  recall_index_type_list
+                    //recall_index_type_list: info.recall_index_type_list, //知识库id
+                    //rerank_index_type_list: info.rerank_index_type_list, //知识库id
+                })
+                if (sd.length > 0) {
+                    setInputs(sd);
+                }
+            } catch (error) {
+                console.error(error);
+            } finally {
+                setPageLoading(false);
+            }
+        },
+
+        //获取知识库列表
+        fetchKnowlegde: async () => {
+            try {
+                const res = await apis.fetchTakaiKnowledgeList();
+                const list = res.data.map((item: any) => {
+                    return {
+                        label: item.name,
+                        value: item.knowledgeId,
+                    }
+                });
+                setKnowledgeList(list);
+            } catch (error: any) {
+                console.error(error);
+            }
+        },
+
+        // 获取模型列表
+        fetchModelList: async () => {
+            try {
+                const res = await apis.fetchModelList();
+                const list = res.data.data.map((item: any) => {
+                    return {
+                        label: item.modelName,
+                        value: item.modelCode,
+                    }
+                });
+                setModelList(list);
+            } catch (error: any) {
+                console.error(error);
+            }
+        },
+
+    }
+
+    const handleRedioClick = (value: string) => {
+        setIsVisibleCus(false);
+        if (value === 'strict') {
+            setTopPValue(0.5);
+            setTempValue(0.10);
+        } else if (value === 'moderate') {
+            setTopPValue(0.7);
+            setTempValue(0.50);
+        } else if (value === 'flexib') {
+            setTopPValue(0.9);
+            setTempValue(0.90);
+        } 
+    }
+
+    return (
+        <div className='questionAnswerInfo'>
+            <Spin spinning={pageLoading}>
+                <Form
+                    form={form}
+                    layout='vertical'
+                    initialValues={{
+                        max_token: 1024
+                    }}
+                >
+                    <div style={{ display: step === 1 ? 'block' : 'none' }} className='questionAnswerInfo-content'>
+                        <FormItem
+                            label='问答应用名称'
+                            name='name'
+                            rules={[{ required: true, message: '问答应用名称不能为空' }]}
+                        >
+                            <Input placeholder="应用名称" style={{ width: 646, padding: 8 }} />
+                        </FormItem>
+
+                        <FormItem
+                            label='问答应用描述'
+                            name='desc'
+                            rules={[{ required: true, message: '问答应用描述不能为空' }]}
+                        >
+                            <TextArea
+                                showCount
+                                maxLength={500}
+                                placeholder="请输入描述"
+                                style={{ height: 120, resize: 'none', width: 646 }}
+                            />
+                        </FormItem>
+
+                        <div>
+                            <h4>添加预设问题</h4>
+                            <div>
+                                {
+                                    inputs.map(input => (
+                                        <div key={input.id} style={{ paddingTop: '10px' }}>
+                                            <label>问题 {input.id}</label>
+                                            <Input
+                                                style={{ width: 300, paddingTop: 8, marginLeft: 20 }}
+                                                type="text"
+                                                value={input.value}
+                                                onChange={e => handleChange(input.id, e.target.value)}
+                                            />
+                                            <PlusCircleOutlined style={{ marginLeft: 20 }} onClick={addInput} />
+                                            <MinusCircleOutlined style={{ marginLeft: 20 }} onClick={delInput} />
+                                        </div>
+                                    ))}
+                            </div>
+                        </div>
+                        <br />
+                        <Button type='primary' onClick={() => {
+                            form.validateFields(['name', 'desc']).then(async (values) => {
+                                setStep(2);
+                                setInputs(inputs);
+                            }).catch((error) => {
+                                console.error(error);
+                            });
+                        }} >
+                            下一步
+                        </Button>
+                    </div>
+
+                    <div style={{ display: step === 2 ? 'block' : 'none' }} className='questionAnswerInfo-content'>
+                        <div style={{ paddingBottom: '10px', display: 'flex', justifyContent: 'flex-end' }}>
+                            <div>
+                                <Button
+                                    style={{ background: '#f5f5f5' }}
+                                    onClick={() => {
+                                        setStep(1);
+                                    }}
+                                >
+                                    上一步
+                                </Button>
+                                <Button
+                                    type='primary'
+                                    onClick={() => {
+                                        form.validateFields().then(async (values) => {
+                                            const data = values;
+                                            console.log(values, 'values');
+                                            // 问题列表
+                                            const question: string[] = [];
+                                            if (inputs) {
+                                                inputs.map((item, index) => {
+                                                    question.push(item.value);
+                                                });
+                                            }
+                                            console.log(question, 'question');
+                                            interface Item {
+                                                index_type_id: number,
+                                                knowledge_id: string
+                                            }
+                                            const indexTypeList: Item[] = [];
+                                            if (values.knowledge_ids && values.knowledge_ids.length > 0) {
+                                                const index_type: Item = {
+                                                    index_type_id: 0,
+                                                    knowledge_id: values.knowledge_ids
+                                                };
+                                                indexTypeList.push(index_type);
+                                            }
+
+                                            const data_info = {
+                                                param_desc: values.param_desc, //回答风格
+                                                show_recall_result: values.show_recall_result, //是否展示召回结果
+                                                recall_method: values.recall_method, //召回方式
+                                                rerank_status: values.rerank_status, //开启rerank
+                                                rerank_model_name: values.rerank_model_name, //模型名称
+                                                slice_config_type: values.slice_config_type, // 召回切片数量
+                                                slice_count: values.slice_count, // 切片数量
+                                                recall_slice_splicing_method: values.recall_slice_splicing_method, // 切片内容
+                                                rerank_index_type_list: values.rerank_status === true ? indexTypeList : [], //知识库id
+                                                recall_index_type_list: values.recall_method === 'embedding' || 'mixed' ? indexTypeList : []
+                                                // rerank_status = 1 rerank_index_type_list
+                                                // recall_method = 'embedding' || 'embedding'  recall_index_type_list
+                                            };
+                                            // const knowledgeIds: string[] = [];
+                                            // knowledgeIds.push(values.knowledge_ids);
+                                            const info = {
+                                                id: values.id,
+                                                name: values.name,  //应用名称
+                                                desc: values.desc,  //应用描述
+                                                prompt: values.prompt, //应用提示语
+                                                top_p: topPValue.toString(), //topP
+                                                temperature: tempValue.toString(), //温度
+                                                knowledge_ids: values.knowledge_ids,
+                                                slice_count: values.slice_count,
+                                                model: values.model,
+                                                icon_color: values.icon_color,
+                                                icon_type: values.icon_type,
+                                                questionList: question,
+                                                knowledge_info: JSON.stringify(data_info),
+                                                max_token: values.max_token, //应用最大token
+                                            };
+                                            const id = location?.state?.id;
+                                            let res = null;
+                                            if (id) {
+                                                // 编辑应用
+                                                console.log(info, 'info data');
+                                                res = await apis.modifyTakaiApplicationApi(id, info);
+                                            } else {
+                                                // 创建应用
+                                                res = await await apis.createTakaiApplicationApi(info);
+                                            }
+                                            if (res.code !== 200) {
+                                                message.error(res.data.message);
+                                            } else {
+                                                message.success('操作成功')
+                                                router.navigate({ pathname: '/takai/questionAnswer' });
+                                            }
+                                        }).catch((error) => {
+                                            console.error(error);
+                                        });
+                                    }}
+                                >发布应用</Button>
+                            </div>
+                        </div>
+                        <Splitter style={{ height: '100%', boxShadow: '0 0 10px rgba(0, 0, 0, 0.1)' }}>
+                            <Splitter.Panel defaultSize="40%">
+                                <div style={{ width: '100%', height: '100%' }}>
+                                    <h2>Prompt编写</h2>
+                                    <div style={{ paddingTop: '20px' }}>
+                                        <TextArea
+                                            autoSize
+                                            readOnly
+                                            placeholder="编写Prompt过程中可以引入2项变量:{{知识}} 代表知识库中检索到的知识内容, {{用户}}代表用户输入的内容。您可以在编写Prompt过程中将变量拼接在合适的位置。插入:{{知识}} 插入:{{用户}}"
+                                            style={{ width: '100%', height: '300px' }}
+                                        />
+                                    </div>
+                                    <Divider plain></Divider>
+                                    <div >
+                                        <FormItem name='prompt'
+                                            rules={[{ required: true, message: '提示词不能为空' }]}>
+                                            <TextArea
+                                                placeholder="提示词"
+                                                rows={50}
+                                            />
+                                        </FormItem>
+                                    </div>
+                                </div>
+
+                            </Splitter.Panel>
+                            <Splitter.Panel defaultSize="60%">
+                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', background: '#f5f5f5', width: '100%', height: '100%' }}>
+                                    <div style={{ width: '50%', height: '100%' }}>
+                                        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', paddingTop: '50px', fontSize: '16px' }}>
+                                            欢迎使用 {name}
+                                        </div>
+
+                                        <div style={{
+                                            display: 'flex', justifyContent: 'center', alignItems: 'center',
+                                            paddingTop: '20px'
+                                        }}>
+                                            <FormItem
+                                                label='引用知识库'
+                                                name='knowledge_ids'
+                                                rules={[{ required: true, message: '知识库不能为空' }]}>
+                                                <Select
+                                                    // mode='multiple'
+                                                    // maxCount={MAX_COUNT}
+                                                    // suffixIcon={suffix}
+                                                    style={{ width: '300px', height: '48px' }}
+                                                    placeholder='请选择知识库'
+                                                >
+                                                    {
+                                                        knowledgeList.map((item, index) => {
+                                                            return <Option value={item.value} key={index}>
+                                                                {item.label}
+                                                            </Option>
+                                                        })
+                                                    }
+                                                </Select>
+                                            </FormItem>
+                                        </div>
+                                        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                            <FormItem
+                                                label='调用模型'
+                                                name="model"
+                                                rules={[{ required: true, message: '模型不能为空' }]}>
+                                                <Select
+                                                    placeholder='请选择模型'
+                                                    allowClear={true}
+                                                    style={{ width: '300px', height: '48px' }}
+                                                >
+                                                    <Option value='DeepSeek-R1-Distill-Qwen-14B'>DeepSeek-R1-Distill-Qwen-14B</Option>
+                                                    {/* {
+                                                        modelList.map((item, index) => {
+                                                            return <Option value={item.value} key={index}>
+                                                                {item.label}
+                                                            </Option>
+                                                        })
+                                                    } */}
+                                                </Select>
+                                            </FormItem>
+                                        </div>
+                                        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                            <FormItem
+                                                label='max token'
+                                                name='max_token'
+                                                rules={[{ required: true, message: 'max token不能为空' }]}>
+                                                <InputNumber
+                                                    className='questionAnswerInfo-content-title'
+                                                />
+                                            </FormItem>
+                                        </div>
+
+                                        {
+                                            !isVisible &&
+                                            <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                <a onClick={() => {
+                                                    setIsVisible(!isVisible);
+                                                }} className='questionAnswerInfo-content-title'>
+                                                    更多设置
+                                                </a>
+                                            </div>
+
+                                        }
+
+                                        {isVisible &&
+                                            <div>
+                                                {isVisibleCus &&
+                                                    <Space style={{ width: '100%' }} direction="vertical">
+                                                        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                            <FormItem
+                                                                label='Top-p'
+                                                                name='topP'
+                                                                style={{ width: '300px' }}
+                                                            >
+                                                                <TopPDecimalStep />
+                                                            </FormItem>
+                                                        </div>
+                                                        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                            <FormItem
+                                                                label='Temperature'
+                                                                name='temperature'
+                                                                style={{ width: '300px' }}
+                                                            >
+                                                                <TempDecimalStep />
+                                                            </FormItem>
+                                                        </div>
+                                                    </Space >
+                                                }
+
+                                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                    <FormItem
+                                                        label='回答风格'
+                                                        name='param_desc'
+                                                        rules={[{ required: true, message: '回答风格不能为空' }]}>
+                                                        <Radio.Group buttonStyle="solid"
+                                                            className='questionAnswerInfo-content-title'>
+                                                            <Radio.Button onClick={() => {
+                                                                handleRedioClick('strict')
+                                                            }} value='strict'>严谨</Radio.Button>
+                                                            <Radio.Button onClick={() => {
+                                                                handleRedioClick('moderate')
+                                                            }} value='moderate'>适中</Radio.Button>
+                                                            <Radio.Button onClick={() => {
+                                                                handleRedioClick('flexib')
+                                                            }} value='flexib'>发散</Radio.Button>
+                                                            <Radio.Button value='custom'
+                                                                onClick={() => {
+                                                                    setIsVisibleCus(!isVisibleCus);
+                                                                    setTopPValue(0.1);
+                                                                    setTempValue(0.01);
+                                                                }}
+                                                            >自定义
+                                                            </Radio.Button>
+                                                        </Radio.Group>
+                                                    </FormItem>
+                                                </div>
+                                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                    <FormItem
+                                                        label='展示引用知识'
+                                                        name='show_recall_result'
+                                                        className='questionAnswerInfo-content-title'>
+                                                        <Switch onChange={onChangeShow} />
+                                                    </FormItem>
+                                                </div>
+                                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                    <FormItem
+                                                        label='召回方式'
+                                                        name='recall_method'
+                                                        rules={[{ required: true, message: '召回方式不能为空' }]}>
+
+                                                        <Radio.Group
+                                                            style={style}
+                                                            onChange={onChangeRecallMethod}
+                                                            options={[
+                                                                { value: 'embedding', label: '向量化检索' },
+                                                                { value: 'keyword', label: '关键词检索' },
+                                                                { value: 'mixed', label: '混合检索' },
+                                                            ]}
+                                                        />
+                                                    </FormItem>
+                                                </div>
+                                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                    <div className='questionAnswerInfo-content-title'>重排方式</div>
+                                                </div>
+                                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                    <FormItem
+                                                        label='Rerank模型'
+                                                        name='rerank_status'
+                                                        valuePropName='checked'
+                                                        className='questionAnswerInfo-content-title'
+                                                    >
+                                                        <Switch onChange={onChangeModel} />
+                                                    </FormItem>
+                                                </div>
+                                                {isVisibleRerank &&
+                                                    <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                        <FormItem
+                                                            label='模型选择'
+                                                            name='rerank_model_name'
+                                                        >
+                                                            <Select
+                                                                style={{ width: '300px', height: '48px' }}
+                                                                placeholder='请选择模型'
+                                                            // defaultValue={'rerank'}
+                                                            >
+                                                                <Option value='rerank'>默认rerank模型</Option>
+                                                            </Select>
+                                                        </FormItem>
+                                                    </div>
+                                                }
+                                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                    <FormItem
+                                                        label='召回切片数量'
+                                                        name='slice_config_type'
+                                                        rules={[{ required: true, message: '召回方式不能为空' }]}>
+                                                        <Select
+                                                            style={{ width: '300px', height: '48px' }}
+                                                            placeholder='请选择'
+                                                            onChange={onChangeCount}>
+                                                            <Option value="fixed">手动设置</Option>
+                                                            <Option value="customized">自动设置</Option>
+                                                        </Select>
+                                                    </FormItem>
+                                                </div>
+
+                                                {isVisibleSlice &&
+                                                    <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                        <FormItem
+                                                            label='召回切片数'
+                                                            name='slice_count'
+                                                            rules={[{ required: true, message: '切片数不能为空' }]}>
+                                                            <InputNumber max={1024} changeOnWheel className='questionAnswerInfo-content-title' />
+                                                        </FormItem>
+                                                    </div>
+                                                }
+                                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                                                    <FormItem
+                                                        label='召回切片拼接方式'
+                                                        name='recall_slice_splicing_method'
+                                                    >
+                                                        <TextArea
+                                                            rows={4}
+                                                            className='questionAnswerInfo-content-title'
+                                                            placeholder="请输入内容"
+                                                        />
+                                                    </FormItem>
+                                                </div>
+                                            </div>
+                                        }
+                                    </div>
+                                </div>
+                            </Splitter.Panel>
+                        </Splitter>
+                    </div>
+                </Form>
+            </Spin>
+        </div>
+    );
+};
+
+export default observer(QuestionAnswerInfo);

+ 47 - 0
src/pages/takai/questionAnswer/info/store.ts

@@ -0,0 +1,47 @@
+import { makeAutoObservable } from 'mobx';
+import { apis } from '@/apis';
+import { State, ReadonlyState, StateAction, QuestionAnswerInfoStore } from './types';
+
+// 定义状态
+const stateGenerator = (): ReadonlyState => ({
+    pageLoading: false,
+});
+
+// 修改状态
+const stateActionsGenerator = (state: State): StateAction => {
+    return {
+        setPageLoading: (loading) => {
+            state.pageLoading = loading;
+        },
+    };
+};
+
+// 使用仓库
+const useQuestionAnswerInfoStore = (): QuestionAnswerInfoStore => {
+    const state = makeAutoObservable(stateGenerator());
+    const actions = stateActionsGenerator(state);
+
+    const api = {
+
+    }
+
+    // 初始渲染
+    const init = () => {
+
+    }
+
+    // 状态重置
+    const reset = () => {
+        const initialPageLoading = stateGenerator().pageLoading;
+
+        actions.setPageLoading(initialPageLoading);
+    }
+
+    return {
+        state,
+        init,
+        reset
+    };
+};
+
+export default useQuestionAnswerInfoStore();

+ 18 - 0
src/pages/takai/questionAnswer/info/style.less

@@ -0,0 +1,18 @@
+.questionAnswerInfo {
+  width: 100%;
+  height: 100%;
+  background: #FFFFFF;
+  border-radius: @border-radius-base;
+}
+
+.questionAnswerInfo-content {
+  width: 100%;
+  height: 100%;
+  background: #FFFFFF;
+  padding: 10px;
+}
+
+.questionAnswerInfo-content-title {
+  width: 300px;
+  height: 48px;
+}

+ 19 - 0
src/pages/takai/questionAnswer/info/types.ts

@@ -0,0 +1,19 @@
+// 定义状态
+export type State = {
+    pageLoading: boolean,
+};
+
+// 只读状态
+export type ReadonlyState = Readonly<State>;
+
+// 修改状态
+export type StateAction = {
+    setPageLoading: (loading: boolean) => void,
+};
+
+// 仓库类型
+export type QuestionAnswerInfoStore = {
+    state: ReadonlyState,
+    init: () => void,
+    reset: () => void,
+};

+ 283 - 0
src/pages/takai/questionAnswer/list/index.tsx

@@ -0,0 +1,283 @@
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { List, Button, Divider, Flex, Layout, Empty, Image, Modal } from 'antd';
+import { PlusOutlined, FileOutlined, SettingOutlined, DeleteOutlined } from '@ant-design/icons';
+import { apis } from '@/apis';
+import './style.less';
+import { PaginationConfig } from 'antd/es/pagination';
+import router from '@/router';
+
+const { Header, Footer, Sider, Content } = Layout;
+
+const headerStyle: React.CSSProperties = {
+    textAlign: 'center',
+    height: 24,
+    paddingInline: 48,
+    lineHeight: '30px',
+    backgroundColor: '#fff',
+};
+
+const contentStyle: React.CSSProperties = {
+    textAlign: 'center',
+    lineHeight: '40px',
+    backgroundColor: '#fff',
+};
+
+const siderStyle: React.CSSProperties = {
+    paddingLeft: 30,
+    paddingTop: 30,
+    height: 80,
+    backgroundColor: '#fff',
+};
+
+const footerStyle: React.CSSProperties = {
+    textAlign: 'center',
+    color: '#fff',
+    height: 24,
+    backgroundColor: '#4096ff',
+};
+
+const layoutStyle = {
+    borderRadius: 8,
+    overflow: 'hidden',
+    width: 'calc(10% - 8px)',
+    maxWidth: 'calc(20% - 8px)',
+};
+const QuestionAnswerList: React.FC = () => {
+    interface Item {
+        name: string,
+        desc: string,
+        appId: number,
+        createBy: string,
+    };
+
+    interface PageInfo {
+        pageNumber: number,
+        pageSize: number,
+        total: number,
+    };
+
+    const [listLoading, setListLoading] = React.useState(false);
+    const [list, setList] = React.useState<Item[]>([]);
+    const [page, setPage] = React.useState<PageInfo>({
+        pageNumber: 1,
+        pageSize: 10,
+        total: 0,
+    });
+    const [appCount, setAppCount] = React.useState<string>();
+    const [knowCount, setKnowCount] = React.useState<string>();
+    const { Header, Footer, Sider, Content } = Layout;
+
+    const appApi = {
+        fetchList: async () => {
+            setListLoading(true);
+            try {
+                const res = await apis.fetchTakaiAppList({
+                    pageSize: page.pageSize,
+                    pageNumber: page.pageNumber
+                })
+                console.log(res.rows, 'fetchTakaiAppList');
+                const list = res.rows.map((item: any) => {
+                    return {
+                        name: item.name,
+                        desc: item.desc,
+                        appId: item.appId,
+                        createBy: item.createBy
+                    }
+                });
+                setList(list);
+                setPage({
+                    pageNumber: page.pageNumber,
+                    pageSize: page.pageSize,
+                    total: res.total,
+                });
+                console.log(page, 'res.data.total');
+            } catch (error) {
+                console.error(error);
+            } finally {
+                setListLoading(false);
+            }
+        }
+    };
+
+    // 删除应用
+    const delApplication = async (appId: string) => {
+        try {
+            await apis.deleteTakaiApplicationApi(appId);
+            await appApi.fetchList();
+        } catch (error) {
+            console.error(error);
+        }
+    }
+
+    const indexApi = {
+        fetchIndex: async () => {
+            try {
+                const res = await apis.fetchTakaiIndexCount({
+                    pageSize: page.pageSize,
+                    pageNumber: page.pageNumber
+                })
+                setAppCount(res.data.applicationCount);
+                setKnowCount(res.data.knowledgeCount);
+                // setPage({
+                //     pageNumber: page.pageNumber,
+                //     pageSize: page.pageSize,
+                //     total: res.data.total,
+                // });
+            } catch (error) {
+                console.error(error);
+            } finally {
+                setListLoading(false);
+            }
+        }
+    }
+
+    const init = async () => {
+        await appApi.fetchList();
+        await indexApi.fetchIndex();
+    }
+
+    React.useEffect(() => {
+        init();
+    }, [page.pageSize, page.pageNumber])
+
+    const paginationConfig: PaginationConfig = {
+        // 显示数据总量
+        showTotal: (total: number) => {
+            return `共 ${total} 条`;
+        },
+        // 展示分页条数切换
+        showSizeChanger: true,
+        // 指定每页显示条数
+        // pageSizeOptions: ['2', '20', '50', '100'],
+        // 快速跳转至某页
+        showQuickJumper: true,
+        current: page.pageNumber,
+        pageSize: page.pageSize,
+        total: page.total,
+        onChange: (pageNumber, pageSize) => {
+            setPage({
+                pageNumber: pageNumber,
+                pageSize: pageSize,
+                total: page.total,
+            });
+        },
+    };
+
+
+    return (
+        <div>
+            {
+                list.length
+                    ?
+                    <div className='questionAnswerList'>
+                        <div style={{ overflow: 'auto' }}>
+                            <Flex gap="middle" wrap>
+                                <Layout style={layoutStyle}>
+                                    <Sider width="25%" style={siderStyle}>
+                                        <FileOutlined />
+                                    </Sider>
+                                    <Layout>
+                                        <Header style={headerStyle}>问答应用总数</Header>
+                                        <Content style={contentStyle}>{appCount}个</Content>
+                                    </Layout>
+                                </Layout>
+                                <Layout style={layoutStyle}>
+                                    <Sider width="25%" style={siderStyle}>
+                                        <FileOutlined />
+                                    </Sider>
+                                    <Layout>
+                                        <Header style={headerStyle}>知识库总数</Header>
+                                        <Content style={contentStyle}>{knowCount} 个</Content>
+                                    </Layout>
+                                </Layout>
+                            </Flex>
+                        </div>
+                        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
+                            <div>所有问答应用</div>
+                            <Button type='primary'
+                                icon={<PlusOutlined />}
+                                onClick={() => {
+                                    router.navigate({ pathname: '/takai/questionAnswer/create' });
+                                }}>创建问答应用</Button>
+                        </div>
+                        <div className='applicationList'>
+                            <List style={{ height: 400 }}
+                                grid={{
+                                    gutter: 16,
+                                    xs: 1,
+                                    sm: 2,
+                                    md: 4,
+                                    lg: 4,
+                                    xl: 6,
+                                    xxl: 2, // 展示的列数
+                                }}
+                                dataSource={list}
+                                renderItem={(item) => (
+                                    <List.Item>
+                                        <div className='card'>
+                                            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', overflow: 'auto' }}>
+                                                <div style={{ display: 'flex', alignItems: 'center', overflow: 'auto' }}>
+                                                    <div style={{ marginRight: 10, overflow: 'auto' }}>
+                                                        <Image
+                                                            width={30}
+                                                            height={30}
+                                                            src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
+                                                        />
+                                                    </div>
+                                                    <div style={{ overflow: 'auto' }}>
+                                                        {item.name}
+                                                    </div>
+                                                </div>
+                                                <div >{item.createBy}</div>
+                                            </div>
+                                            <Divider plain></Divider>
+                                            <div className='desc'>
+                                                {
+                                                    item.desc !== '' && item.desc !== null && item.desc.length > 35 ? item.desc.substring(0, 35) + '......' : item.desc
+                                                }
+                                            </div>
+                                            <div style={{ display: 'flex', justifyContent: 'space-between', overflow: 'auto' }}>
+                                                <div style={{ overflow: 'auto' }}>
+                                                    <a style={{ marginRight: 16 }} onClick={() => {
+                                                        router.navigate({ pathname: '/takai/questionAnswer/modify' }, { state: { id: item.appId } });
+                                                    }}>
+                                                        <SettingOutlined /> 编辑
+                                                    </a>
+                                                    <a className='text-error' onClick={() => {
+                                                        Modal.confirm({
+                                                            title: '删除',
+                                                            content: `确定删除应用名称: ` + item.name + ` 吗?`,
+                                                            okType: 'danger',
+                                                            onOk: async () => {
+                                                                await delApplication(item.appId.toString());
+                                                            }
+                                                        });
+                                                    }}>
+                                                        <DeleteOutlined /> 删除
+                                                    </a>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </List.Item>
+                                )}
+                                pagination={paginationConfig} // 分页 
+                            />
+                        </div>
+                    </div>
+                    :
+                    <div>
+                        <Button type='primary'
+                                icon={<PlusOutlined />}
+                                onClick={() => {
+                                    router.navigate({ pathname: '/takai/questionAnswer/create' });
+                                }}>创建问答应用</Button>
+                        <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+                    </div>
+
+            }
+        </div>
+    )
+};
+
+export default observer(QuestionAnswerList);

+ 33 - 0
src/pages/takai/questionAnswer/list/style.less

@@ -0,0 +1,33 @@
+.questionAnswerList {
+  width: 100%;
+  height: 100%;
+  background: #FFFFFF;
+  border-radius: @border-radius-base;
+}
+
+.applicationList {
+  width: 100%;
+  height: 400px;
+  padding-top: 10px;
+}
+
+.card{
+  padding: 20px;
+  border: 1px solid @border-color;
+  border-radius: @border-radius-base;
+  height: 200px;
+  overflow: auto;
+}
+.card:hover{
+  border-color:@primary-color ;
+}
+
+.desc {
+  height: 35px;
+  overflow: auto;
+}
+
+.info-head {
+  width: 100%;
+  height: 35%;
+}

+ 92 - 0
src/router.tsx

@@ -24,6 +24,98 @@ const lazyLoad = (loader: () => Promise<any>) => {
 
 // React-Router-Dom@v6 路由表
 const routerList: RouteObject[] = [
+    {
+        path: '/',
+        element: lazyLoad(() => import('@/pages/layout/index')),
+        children: [
+            {
+                index: true,
+                element: <Navigate to='/takai/questionAnswer' />,
+            },
+            {   /* 问答应用 */
+                path: '/takai/questionAnswer',
+                handle: {
+                    menuLevel: 1,
+                    breadcrumbName: '问答应用',
+                },
+                children: [
+                    {
+                        index: true,
+                        element: lazyLoad(() => import('@/pages/takai/questionAnswer/list/index')),
+                    },
+                    {   /* 问答应用-创建应用 */
+                        path: '/takai/questionAnswer/create',
+                        handle: {
+                            menuLevel: 1,
+                            breadcrumbName: '创建应用',
+                        },
+                        element: lazyLoad(() => import('@/pages/takai/questionAnswer/info/index')),
+                    },
+                    {   /* 问答应用-修改应用 */
+                        path: '/takai/questionAnswer/modify',
+                        handle: {
+                            menuLevel: 1,
+                            breadcrumbName: '修改应用',
+                        },
+                        element: lazyLoad(() => import('@/pages/takai/questionAnswer/info/index')),
+                    },
+                ]
+            },
+            {   /* 知识库 */
+                path: '/takai/knowledgeLib',
+                handle: {
+                    menuLevel: 1,
+                    breadcrumbName: '知识库',
+                },
+                children: [
+                    {
+                        index: true,
+                        element: lazyLoad(() => import('@/pages/takai/knowledgeLib/list/index')),
+                    },
+                    {   /* 知识库-知识库详情 */
+                        path: '/takai/knowledgeLib/:knowledgeId',
+                        handle: {
+                            menuLevel: 1,
+                            breadcrumbName: '知识库详情',
+                        },
+                        element: lazyLoad(() => import('@/pages/takai/knowledgeLib/detail/index')),
+                    },
+                    {   /* 知识库-知识-切片信息 */
+                        path: '/takai/knowledgeLib/slice/:documentId/:knowledgeId/:embeddingId',
+                        handle: {
+                            menuLevel: 1,
+                            breadcrumbName: '切片信息',
+                        },
+                        element: lazyLoad(() => import('@/pages/takai/knowledgeLib/slice/index')),
+                    },
+                    {   /* 知识库-知识-切片详情 */
+                        path: '/takai/knowledgeLib/slice/detail/:sliceId/:knowledgeId/:documentId/:embeddingId',
+                        handle: {
+                            menuLevel: 1,
+                            breadcrumbName: '切片详情',
+                        },
+                        element: lazyLoad(() => import('@/pages/takai/knowledgeLib/slice/detail/index')),
+                    }
+                ]
+            },
+            {   /* 数据导出 */
+                path: '/takai/dataExport',
+                handle: {
+                    menuLevel: 1,
+                    breadcrumbName: '数据导出',
+                },
+                element: lazyLoad(() => import('@/pages/takai/dataExport/index')),
+            },
+            {   /* 404 */
+                path: '/404',
+                element: lazyLoad(() => import('@/components/404/index')),
+            },
+            {   /* 路由不存在重定向404 */
+                path: '/*',
+                element: <Navigate to='/404' replace={true} />,
+            },
+        ]
+    },
     {
         path: '/',
         element: lazyLoad(() => import('@/pages/layout/index')),