From 7b71fb2db602641d06e743d4dab154515ce5f081 Mon Sep 17 00:00:00 2001
From: balibabu <cike8899@users.noreply.github.com>
Date: Fri, 2 Feb 2024 18:49:54 +0800
Subject: [PATCH] feat: modify routing to nested mode and rename document (#52)

* feat: modify routing to nested mode

* feat: rename document
---
 .../components/deleting-confirm/index.less    |   0
 web/src/components/deleting-confirm/index.tsx |  28 ++++
 web/src/components/modal-manager.tsx          |  24 +++
 web/src/constants/knowledge.ts                |  10 +-
 web/src/hooks/knowledgeHook.ts                |   8 +
 web/src/hooks/routeHook.ts                    |  21 +++
 web/src/interfaces/database/knowledge.ts      |  26 +++
 .../components/knowledge-chunk/index.tsx      |  24 ++-
 .../components/knowledge-dataset/index.less   |   0
 .../components/knowledge-dataset/index.tsx    |   7 +
 .../knowledge-upload-file/index.tsx           |   5 +
 .../components/knowledge-file/constant.ts     |  17 ++
 .../knowledge-file/createEFileModal.tsx       |  19 ++-
 .../components/knowledge-file/index.less      |  38 +++--
 .../components/knowledge-file/index.tsx       | 150 ++++++++++--------
 .../components/knowledge-file/model.ts        |  35 +++-
 .../parsing-action-cell/index.tsx             |  88 ++++++++++
 .../parsing-status-cell/index.less            |   3 +
 .../parsing-status-cell/index.tsx             |  68 ++++++++
 .../knowledge-file/rename-modal/index.tsx     |  88 ++++++++++
 .../knowledge-file/segmentSetModal.tsx        |   1 -
 .../components/knowledge-search/index.tsx     |  19 ++-
 .../components/knowledge-setting/index.tsx    |  23 +--
 .../components/knowledge-sidebar/index.tsx    |  10 +-
 web/src/pages/add-knowledge/constant.ts       |  12 +-
 web/src/pages/add-knowledge/index.less        |   3 +
 web/src/pages/add-knowledge/index.tsx         |  66 ++++----
 web/src/pages/knowledge/index.tsx             |  18 ++-
 .../pages/knowledge/knowledge-card/index.less |   2 +-
 web/src/routes.ts                             |  31 +++-
 web/src/services/kbService.ts                 |   5 +
 web/src/utils/api.ts                          |   3 +-
 web/typings.d.ts                              |   4 +-
 33 files changed, 681 insertions(+), 175 deletions(-)
 create mode 100644 web/src/components/deleting-confirm/index.less
 create mode 100644 web/src/components/deleting-confirm/index.tsx
 create mode 100644 web/src/components/modal-manager.tsx
 create mode 100644 web/src/hooks/knowledgeHook.ts
 create mode 100644 web/src/hooks/routeHook.ts
 create mode 100644 web/src/interfaces/database/knowledge.ts
 create mode 100644 web/src/pages/add-knowledge/components/knowledge-dataset/index.less
 create mode 100644 web/src/pages/add-knowledge/components/knowledge-dataset/index.tsx
 create mode 100644 web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx
 create mode 100644 web/src/pages/add-knowledge/components/knowledge-file/constant.ts
 create mode 100644 web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx
 create mode 100644 web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less
 create mode 100644 web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx
 create mode 100644 web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx

diff --git a/web/src/components/deleting-confirm/index.less b/web/src/components/deleting-confirm/index.less
new file mode 100644
index 0000000..e69de29
diff --git a/web/src/components/deleting-confirm/index.tsx b/web/src/components/deleting-confirm/index.tsx
new file mode 100644
index 0000000..38a205b
--- /dev/null
+++ b/web/src/components/deleting-confirm/index.tsx
@@ -0,0 +1,28 @@
+import { ExclamationCircleFilled } from '@ant-design/icons';
+import { Modal } from 'antd';
+
+const { confirm } = Modal;
+
+interface IProps {
+  onOk?: (...args: any[]) => any;
+  onCancel?: (...args: any[]) => any;
+}
+
+export const showDeleteConfirm = ({ onOk, onCancel }: IProps) => {
+  confirm({
+    title: 'Are you sure delete this item?',
+    icon: <ExclamationCircleFilled />,
+    content: 'Some descriptions',
+    okText: 'Yes',
+    okType: 'danger',
+    cancelText: 'No',
+    onOk() {
+      onOk?.();
+    },
+    onCancel() {
+      onCancel?.();
+    },
+  });
+};
+
+export default showDeleteConfirm;
diff --git a/web/src/components/modal-manager.tsx b/web/src/components/modal-manager.tsx
new file mode 100644
index 0000000..14aec07
--- /dev/null
+++ b/web/src/components/modal-manager.tsx
@@ -0,0 +1,24 @@
+import { useState } from 'react';
+
+interface IProps {
+  children: (props: {
+    showModal(): void;
+    hideModal(): void;
+    visible: boolean;
+  }) => React.ReactNode;
+}
+
+const ModalManager = ({ children }: IProps) => {
+  const [visible, setVisible] = useState(false);
+
+  const showModal = () => {
+    setVisible(true);
+  };
+  const hideModal = () => {
+    setVisible(false);
+  };
+
+  return children({ visible, showModal, hideModal });
+};
+
+export default ModalManager;
diff --git a/web/src/constants/knowledge.ts b/web/src/constants/knowledge.ts
index 52fae77..cf117d3 100644
--- a/web/src/constants/knowledge.ts
+++ b/web/src/constants/knowledge.ts
@@ -1,5 +1,13 @@
 export enum KnowledgeRouteKey {
   Dataset = 'dataset',
   Testing = 'testing',
-  Configration = 'configration',
+  Configuration = 'configuration',
+}
+
+export enum RunningStatus {
+  UNSTART = '0',
+  RUNNING = '1',
+  CANCEL = '2',
+  DONE = '3',
+  FAIL = '4',
 }
diff --git a/web/src/hooks/knowledgeHook.ts b/web/src/hooks/knowledgeHook.ts
new file mode 100644
index 0000000..5ce7bd2
--- /dev/null
+++ b/web/src/hooks/knowledgeHook.ts
@@ -0,0 +1,8 @@
+import { useSearchParams } from 'umi';
+
+export const useKnowledgeBaseId = (): string => {
+  const [searchParams] = useSearchParams();
+  const knowledgeBaseId = searchParams.get('id');
+
+  return knowledgeBaseId || '';
+};
diff --git a/web/src/hooks/routeHook.ts b/web/src/hooks/routeHook.ts
new file mode 100644
index 0000000..e51983c
--- /dev/null
+++ b/web/src/hooks/routeHook.ts
@@ -0,0 +1,21 @@
+import { useLocation } from 'umi';
+
+export enum SegmentIndex {
+  Second = '2',
+  Third = '3',
+}
+
+export const useSegmentedPathName = (index: SegmentIndex) => {
+  const { pathname } = useLocation();
+
+  const pathArray = pathname.split('/');
+  return pathArray[index] || '';
+};
+
+export const useSecondPathName = () => {
+  return useSegmentedPathName(SegmentIndex.Second);
+};
+
+export const useThirdPathName = () => {
+  return useSegmentedPathName(SegmentIndex.Third);
+};
diff --git a/web/src/interfaces/database/knowledge.ts b/web/src/interfaces/database/knowledge.ts
new file mode 100644
index 0000000..c8a952a
--- /dev/null
+++ b/web/src/interfaces/database/knowledge.ts
@@ -0,0 +1,26 @@
+import { RunningStatus } from '@/constants/knowledge';
+
+export interface IKnowledgeFile {
+  chunk_num: number;
+  create_date: string;
+  create_time: number;
+  created_by: string;
+  id: string;
+  kb_id: string;
+  location: string;
+  name: string;
+  parser_id: string;
+  process_begin_at?: any;
+  process_duation: number;
+  progress: number; // parsing process
+  progress_msg: string; // parsing log
+  run: RunningStatus; // parsing status
+  size: number;
+  source_type: string;
+  status: string; // enabled
+  thumbnail?: any; // base64
+  token_num: number;
+  type: string;
+  update_date: string;
+  update_time: number;
+}
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
index 291876f..b997ccb 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
@@ -14,11 +14,11 @@ import {
   Spin,
   Switch,
 } from 'antd';
+import { debounce } from 'lodash';
 import React, { useCallback, useEffect, useState } from 'react';
-import { useDispatch, useNavigate, useSelector } from 'umi';
+import { useDispatch, useSearchParams, useSelector } from 'umi';
 import CreateModal from './components/createModal';
 
-import { debounce } from 'lodash';
 import styles from './index.less';
 
 interface PayloadType {
@@ -27,18 +27,13 @@ interface PayloadType {
   available_int?: number;
 }
 
-interface IProps {
-  doc_id: string;
-}
-
-const Chunk = ({ doc_id }: IProps) => {
+const Chunk = () => {
   const dispatch = useDispatch();
   const chunkModel = useSelector((state: any) => state.chunkModel);
   const [keywords, SetKeywords] = useState('');
   const [available_int, setAvailableInt] = useState(-1);
-  const navigate = useNavigate();
+  const [searchParams] = useSearchParams();
   const [pagination, setPagination] = useState({ page: 1, size: 30 });
-  // const [datas, setDatas] = useState(data)
   const { data = [], total, chunk_id, isShowCreateModal } = chunkModel;
   const effects = useSelector((state: any) => state.loading.effects);
   const loading = getOneNamespaceEffectsLoading('chunkModel', effects, [
@@ -46,10 +41,11 @@ const Chunk = ({ doc_id }: IProps) => {
     'chunk_list',
     'switch_chunk',
   ]);
+  const documentId: string = searchParams.get('doc_id') || '';
 
   const getChunkList = (value?: string) => {
     const payload: PayloadType = {
-      doc_id,
+      doc_id: documentId,
       keywords: value || keywords,
       available_int,
     };
@@ -81,7 +77,7 @@ const Chunk = ({ doc_id }: IProps) => {
       payload: {
         isShowCreateModal: true,
         chunk_id,
-        doc_id,
+        doc_id: documentId,
       },
     });
     getChunkList();
@@ -100,7 +96,7 @@ const Chunk = ({ doc_id }: IProps) => {
       payload: {
         chunk_ids: [id],
         available_int: Number(available_int),
-        doc_id,
+        doc_id: documentId,
       },
     });
 
@@ -109,7 +105,7 @@ const Chunk = ({ doc_id }: IProps) => {
 
   useEffect(() => {
     getChunkList();
-  }, [doc_id, available_int, pagination]);
+  }, [documentId, available_int, pagination]);
 
   const debounceChange = debounce(getChunkList, 300);
   const debounceCallback = useCallback(
@@ -270,7 +266,7 @@ const Chunk = ({ doc_id }: IProps) => {
         </div>
       </div>
       <CreateModal
-        doc_id={doc_id}
+        doc_id={documentId}
         isShowCreateModal={isShowCreateModal}
         chunk_id={chunk_id}
         getChunkList={getChunkList}
diff --git a/web/src/pages/add-knowledge/components/knowledge-dataset/index.less b/web/src/pages/add-knowledge/components/knowledge-dataset/index.less
new file mode 100644
index 0000000..e69de29
diff --git a/web/src/pages/add-knowledge/components/knowledge-dataset/index.tsx b/web/src/pages/add-knowledge/components/knowledge-dataset/index.tsx
new file mode 100644
index 0000000..15328de
--- /dev/null
+++ b/web/src/pages/add-knowledge/components/knowledge-dataset/index.tsx
@@ -0,0 +1,7 @@
+import { Outlet } from 'umi';
+
+export const KnowledgeDataset = () => {
+  return <Outlet></Outlet>;
+};
+
+export default KnowledgeDataset;
diff --git a/web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx b/web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx
new file mode 100644
index 0000000..e2b5109
--- /dev/null
+++ b/web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx
@@ -0,0 +1,5 @@
+const KnowledgeUploadFile = () => {
+  return <div>KnowledgeUploadFile</div>;
+};
+
+export default KnowledgeUploadFile;
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/constant.ts b/web/src/pages/add-knowledge/components/knowledge-file/constant.ts
new file mode 100644
index 0000000..426a8eb
--- /dev/null
+++ b/web/src/pages/add-knowledge/components/knowledge-file/constant.ts
@@ -0,0 +1,17 @@
+import { RunningStatus } from '@/constants/knowledge';
+
+export const RunningStatusMap = {
+  [RunningStatus.UNSTART]: {
+    label: 'UNSTART',
+    color: 'cyan',
+  },
+  [RunningStatus.RUNNING]: {
+    label: 'Parsing',
+    color: 'blue',
+  },
+  [RunningStatus.CANCEL]: { label: 'CANCEL', color: 'orange' },
+  [RunningStatus.DONE]: { label: 'SUCCESS', color: 'geekblue' },
+  [RunningStatus.FAIL]: { label: 'FAIL', color: 'red' },
+};
+
+export * from '@/constants/knowledge';
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx b/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx
index b26269d..3447f20 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx
@@ -13,9 +13,9 @@ interface kFProps {
 
 const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
   const dispatch = useDispatch();
+  const [form] = Form.useForm();
   const kFModel = useSelector((state: any) => state.kFModel);
   const { isShowCEFwModal } = kFModel;
-  const [form] = Form.useForm();
   const { t } = useTranslation();
 
   const handleCancel = () => {
@@ -26,7 +26,8 @@ const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
       },
     });
   };
-  const handleOk = async () => {
+
+  const createDocument = async () => {
     try {
       const values = await form.validateFields();
       const retcode = await dispatch<any>({
@@ -44,9 +45,13 @@ const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
     }
   };
 
+  const handleOk = async () => {
+    createDocument();
+  };
+
   return (
     <Modal
-      title="Basic Modal"
+      title="File Name"
       open={isShowCEFwModal}
       onOk={handleOk}
       onCancel={handleCancel}
@@ -54,15 +59,15 @@ const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
       <Form
         form={form}
         name="validateOnly"
-        labelCol={{ span: 8 }}
-        wrapperCol={{ span: 16 }}
+        labelCol={{ span: 4 }}
+        wrapperCol={{ span: 20 }}
         style={{ maxWidth: 600 }}
         autoComplete="off"
       >
         <Form.Item<FieldType>
-          label="文件名"
+          label="File Name"
           name="name"
-          rules={[{ required: true, message: 'Please input value!' }]}
+          rules={[{ required: true, message: 'Please input name!' }]}
         >
           <Input />
         </Form.Item>
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/index.less b/web/src/pages/add-knowledge/components/knowledge-file/index.less
index bf3d89d..52e8955 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/index.less
+++ b/web/src/pages/add-knowledge/components/knowledge-file/index.less
@@ -1,28 +1,34 @@
+.datasetWrapper {
+  padding: 30px;
+  flex: 1;
+}
+
 .filter {
-    height: 32px;
-    display: flex;
-    margin: 10px 0;
-    justify-content: space-between;
+  height: 32px;
+  display: flex;
+  margin: 10px 0;
+  justify-content: space-between;
+  padding: 24px 20px;
 
-    .search {
-        flex: 1;
-    }
+  //   .search {
+  //     flex: 1;
+  //   }
 
-    .operate {
-        width: 200px;
-    }
+  //   .operate {
+  //     width: 200px;
+  //   }
 }
 
 .img {
-    height: 16px;
-    width: 16px;
-    margin-right: 6px;
+  height: 16px;
+  width: 16px;
+  margin-right: 6px;
 }
 
 .column {
-    min-width: 200px
+  min-width: 200px;
 }
 
 .tochunks {
-    cursor: pointer;
-}
\ No newline at end of file
+  cursor: pointer;
+}
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx
index 16f304d..aa8d18a 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx
@@ -1,37 +1,38 @@
 import { KnowledgeRouteKey } from '@/constants/knowledge';
+import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
+import { IKnowledgeFile } from '@/interfaces/database/knowledge';
 import { getOneNamespaceEffectsLoading } from '@/utils/stroreUtil';
-import { DownOutlined } from '@ant-design/icons';
+import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
 import type { MenuProps } from 'antd';
-import { Button, Dropdown, Input, Space, Switch, Table } from 'antd';
+import {
+  Button,
+  Divider,
+  Dropdown,
+  Input,
+  Space,
+  Switch,
+  Table,
+  Tag,
+} from 'antd';
 import type { ColumnsType } from 'antd/es/table';
 import { debounce } from 'lodash';
 import React, { useCallback, useEffect, useMemo, useState } from 'react';
 import { useDispatch, useNavigate, useSelector } from 'umi';
 import CreateEPModal from './createEFileModal';
 import styles from './index.less';
+import ParsingActionCell from './parsing-action-cell';
+import ParsingStatusCell from './parsing-status-cell';
+import RenameModal from './rename-modal';
 import SegmentSetModal from './segmentSetModal';
 import UploadFile from './upload';
 
-interface DataType {
-  name: string;
-  chunk_num: string;
-  token_num: number;
-  update_date: string;
-  size: string;
-  status: string;
-  id: string;
-  parser_id: string;
-}
-
-interface KFProps {
-  kb_id: string;
-}
-
-const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
+const KnowledgeFile = () => {
   const dispatch = useDispatch();
   const kFModel = useSelector((state: any) => state.kFModel);
   const effects = useSelector((state: any) => state.loading.effects);
   const { data } = kFModel;
+  const knowledgeBaseId = useKnowledgeBaseId();
+
   const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
     'getKfList',
     'updateDocumentStatus',
@@ -43,7 +44,7 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
 
   const getKfList = (keywords?: string) => {
     const payload = {
-      kb_id,
+      kb_id: knowledgeBaseId,
       keywords,
     };
     if (!keywords) {
@@ -56,10 +57,10 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
   };
 
   useEffect(() => {
-    if (kb_id) {
+    if (knowledgeBaseId) {
       getKfList();
     }
-  }, [kb_id]);
+  }, [knowledgeBaseId]);
 
   const debounceChange = debounce(getKfList, 300);
   const debounceCallback = useCallback(
@@ -79,7 +80,7 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
       payload: {
         doc_id,
         status: Number(e),
-        kb_id,
+        kb_id: knowledgeBaseId,
       },
     });
   };
@@ -88,7 +89,7 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
       type: 'kFModel/document_rm',
       payload: {
         doc_id,
-        kb_id,
+        kb_id: knowledgeBaseId,
       },
     });
   };
@@ -109,13 +110,14 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
       },
     });
   };
+
   const actionItems: MenuProps['items'] = useMemo(() => {
     return [
       {
         key: '1',
         label: (
           <div>
-            <UploadFile kb_id={kb_id} getKfList={getKfList} />
+            <UploadFile kb_id={knowledgeBaseId} getKfList={getKfList} />
           </div>
         ),
       },
@@ -132,7 +134,7 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
         // disabled: true,
       },
     ];
-  }, [kb_id]);
+  }, [knowledgeBaseId]);
   const chunkItems: MenuProps['items'] = [
     {
       key: '1',
@@ -158,14 +160,21 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
       // disabled: true,
     },
   ];
+
   const toChunk = (id: string) => {
     navigate(
-      `/knowledge/${KnowledgeRouteKey.Dataset}?id=${kb_id}&doc_id=${id}`,
+      `/knowledge/${KnowledgeRouteKey.Dataset}/chunk?id=${knowledgeBaseId}&doc_id=${id}`,
     );
   };
-  const columns: ColumnsType<DataType> = [
+
+  const setDocumentAndParserId = (record: IKnowledgeFile) => () => {
+    setDocId(record.id);
+    setParserId(record.parser_id);
+  };
+
+  const columns: ColumnsType<IKnowledgeFile> = [
     {
-      title: '名称',
+      title: 'Name',
       dataIndex: 'name',
       key: 'name',
       render: (text: any, { id }) => (
@@ -178,32 +187,30 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
           {text}
         </div>
       ),
-      className: `${styles.column}`,
     },
     {
-      title: '数据总量',
+      title: 'Chunk Number',
       dataIndex: 'chunk_num',
       key: 'chunk_num',
-      className: `${styles.column}`,
     },
     {
-      title: 'Tokens',
-      dataIndex: 'token_num',
-      key: 'token_num',
-      className: `${styles.column}`,
+      title: 'Upload Date',
+      dataIndex: 'create_date',
+      key: 'create_date',
     },
     {
-      title: '文件大小',
-      dataIndex: 'size',
-      key: 'size',
-      className: `${styles.column}`,
+      title: 'Parsing Status',
+      dataIndex: 'run',
+      key: 'run',
+      render: (text, record) => {
+        return <ParsingStatusCell record={record}></ParsingStatusCell>;
+      },
     },
     {
-      title: '状态',
+      title: 'Enabled',
       key: 'status',
       dataIndex: 'status',
-      className: `${styles.column}`,
-      render: (_, { status: string, id }) => (
+      render: (_, { status, id }) => (
         <>
           <Switch
             defaultChecked={status === '1'}
@@ -217,58 +224,65 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
     {
       title: 'Action',
       key: 'action',
-      className: `${styles.column}`,
       render: (_, record) => (
-        <Space size="middle">
-          <Dropdown menu={{ items: chunkItems }} trigger={['click']}>
-            <a
-              onClick={() => {
-                setDocId(record.id);
-                setParserId(record.parser_id);
-              }}
-            >
-              分段设置 <DownOutlined />
-            </a>
-          </Dropdown>
-        </Space>
+        <ParsingActionCell
+          documentId={doc_id}
+          knowledgeBaseId={knowledgeBaseId}
+          setDocumentAndParserId={setDocumentAndParserId(record)}
+          record={record}
+        ></ParsingActionCell>
       ),
     },
   ];
+
+  const finalColumns = columns.map((x) => ({
+    ...x,
+    className: `${styles.column}`,
+  }));
+
   return (
-    <>
+    <div className={styles.datasetWrapper}>
+      <h3>Dataset</h3>
+      <p>Hey, don't forget to adjust the chunk after adding the dataset! 😉</p>
+      <Divider></Divider>
       <div className={styles.filter}>
-        <div className="search">
+        <Space>
+          <h3>Total</h3>
+          <Tag color="purple">100 files</Tag>
+        </Space>
+        <Space>
           <Input
-            placeholder="搜索"
+            placeholder="Seach your files"
             value={inputValue}
             style={{ width: 220 }}
             allowClear
             onChange={handleInputChange}
+            prefix={<SearchOutlined />}
           />
-        </div>
-        <div className="operate">
+
           <Dropdown menu={{ items: actionItems }} trigger={['click']}>
-            <a>
-              导入文件 <DownOutlined />
-            </a>
+            <Button type="primary" icon={<PlusOutlined />}>
+              Add file
+            </Button>
           </Dropdown>
-        </div>
+        </Space>
       </div>
       <Table
         rowKey="id"
-        columns={columns}
+        columns={finalColumns}
         dataSource={data}
         loading={loading}
         pagination={false}
-        scroll={{ scrollToFirstRowOnChange: true, x: true }}
+        scroll={{ scrollToFirstRowOnChange: true, x: true, y: 'fill' }}
       />
-      <CreateEPModal getKfList={getKfList} kb_id={kb_id} />
+      <CreateEPModal getKfList={getKfList} kb_id={knowledgeBaseId} />
       <SegmentSetModal
         getKfList={getKfList}
         parser_id={parser_id}
         doc_id={doc_id}
       />
-    </>
+      <RenameModal></RenameModal>
+    </div>
   );
 };
 
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/model.ts b/web/src/pages/add-knowledge/components/knowledge-file/model.ts
index d193b1a..9b5ff2b 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/model.ts
+++ b/web/src/pages/add-knowledge/components/knowledge-file/model.ts
@@ -1,14 +1,19 @@
+import { IKnowledgeFile } from '@/interfaces/database/knowledge';
 import kbService from '@/services/kbService';
 import { message } from 'antd';
+import omit from 'lodash/omit';
 import pick from 'lodash/pick';
+import { Nullable } from 'typings';
 import { DvaModel } from 'umi';
 
 export interface KFModelState {
   isShowCEFwModal: boolean;
   isShowTntModal: boolean;
   isShowSegmentSetModal: boolean;
+  isShowRenameModal: boolean;
   tenantIfo: any;
-  data: any[];
+  data: IKnowledgeFile[];
+  currentRecord: Nullable<IKnowledgeFile>;
 }
 
 const model: DvaModel<KFModelState> = {
@@ -17,8 +22,10 @@ const model: DvaModel<KFModelState> = {
     isShowCEFwModal: false,
     isShowTntModal: false,
     isShowSegmentSetModal: false,
+    isShowRenameModal: false,
     tenantIfo: {},
     data: [],
+    currentRecord: null,
   },
   reducers: {
     updateState(state, { payload }) {
@@ -27,6 +34,12 @@ const model: DvaModel<KFModelState> = {
         ...payload,
       };
     },
+    setIsShowRenameModal(state, { payload }) {
+      return { ...state, isShowRenameModal: payload };
+    },
+    setCurrentRecord(state, { payload }) {
+      return { ...state, currentRecord: payload };
+    },
   },
   subscriptions: {
     setup({ dispatch, history }) {
@@ -99,6 +112,26 @@ const model: DvaModel<KFModelState> = {
         });
       }
     },
+    *document_rename({ payload = {} }, { call, put }) {
+      const { data } = yield call(
+        kbService.document_rename,
+        omit(payload, ['kb_id']),
+      );
+      const { retcode, data: res, retmsg } = data;
+      if (retcode === 0) {
+        message.success('rename success!');
+        yield put({
+          type: 'setIsShowRenameModal',
+          payload: false,
+        });
+        yield put({
+          type: 'getKfList',
+          payload: { kb_id: payload.kb_id },
+        });
+      }
+
+      return retcode;
+    },
     *document_create({ payload = {} }, { call, put }) {
       const { data, response } = yield call(kbService.document_create, payload);
       const { retcode, data: res, retmsg } = data;
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx
new file mode 100644
index 0000000..08ccb5d
--- /dev/null
+++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx
@@ -0,0 +1,88 @@
+import showDeleteConfirm from '@/components/deleting-confirm';
+import { IKnowledgeFile } from '@/interfaces/database/knowledge';
+import { DeleteOutlined, EditOutlined, ToolOutlined } from '@ant-design/icons';
+import { Button, Dropdown, MenuProps, Space, Tooltip } from 'antd';
+import { useDispatch } from 'umi';
+
+interface IProps {
+  documentId: string;
+  knowledgeBaseId: string;
+  record: IKnowledgeFile;
+  setDocumentAndParserId: () => void;
+}
+
+const ParsingActionCell = ({
+  documentId,
+  knowledgeBaseId,
+  record,
+  setDocumentAndParserId,
+}: IProps) => {
+  const dispatch = useDispatch();
+
+  const removeDocument = () => {
+    dispatch({
+      type: 'kFModel/document_rm',
+      payload: {
+        doc_id: documentId,
+        kb_id: knowledgeBaseId,
+      },
+    });
+  };
+
+  const onRmDocument = () => {
+    showDeleteConfirm({ onOk: removeDocument });
+  };
+
+  const setCurrentRecord = () => {
+    dispatch({
+      type: 'kFModel/setCurrentRecord',
+      payload: record,
+    });
+  };
+
+  const showSegmentSetModal = () => {
+    dispatch({
+      type: 'kFModel/updateState',
+      payload: {
+        isShowSegmentSetModal: true,
+      },
+    });
+  };
+
+  const showRenameModal = () => {
+    setCurrentRecord();
+    dispatch({
+      type: 'kFModel/setIsShowRenameModal',
+      payload: true,
+    });
+  };
+
+  const onRename = () => {};
+
+  const chunkItems: MenuProps['items'] = [
+    {
+      key: '1',
+      label: (
+        <div>
+          <Button type="link" onClick={showSegmentSetModal}>
+            分段设置
+          </Button>
+        </div>
+      ),
+    },
+  ];
+
+  return (
+    <Space size={'middle'}>
+      <Dropdown menu={{ items: chunkItems }} trigger={['click']}>
+        <ToolOutlined size={20} onClick={setDocumentAndParserId} />
+      </Dropdown>
+      <Tooltip title="Rename">
+        <EditOutlined size={20} onClick={showRenameModal} />
+      </Tooltip>
+      <DeleteOutlined size={20} onClick={onRmDocument} />
+    </Space>
+  );
+};
+
+export default ParsingActionCell;
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less b/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less
new file mode 100644
index 0000000..b595d95
--- /dev/null
+++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less
@@ -0,0 +1,3 @@
+.popover-content {
+  width: 300px;
+}
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx
new file mode 100644
index 0000000..55a450a
--- /dev/null
+++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx
@@ -0,0 +1,68 @@
+import { IKnowledgeFile } from '@/interfaces/database/knowledge';
+import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd';
+import { RunningStatus, RunningStatusMap } from '../constant';
+
+import styles from './index.less';
+
+interface IProps {
+  record: IKnowledgeFile;
+}
+
+const PopoverContent = ({ record }: IProps) => {
+  const items: DescriptionsProps['items'] = [
+    {
+      key: 'process_begin_at',
+      label: 'Process Begin At',
+      children: record.process_begin_at,
+    },
+    {
+      key: 'process_duation',
+      label: 'Process Duration',
+      children: record.process_duation,
+    },
+    {
+      key: 'progress_msg',
+      label: 'Progress Msg',
+      children: record.progress_msg,
+    },
+  ];
+
+  return (
+    <Flex vertical className={styles['popover-content']}>
+      {items.map((x) => {
+        return (
+          <div>
+            <b>{x.label}:</b>
+            <p>{x.children}</p>
+          </div>
+        );
+      })}
+    </Flex>
+  );
+};
+
+export const ParsingStatusCell = ({ record }: IProps) => {
+  const text = record.run;
+  const runningStatus = RunningStatusMap[text];
+
+  const isRunning = text === RunningStatus.RUNNING;
+
+  return (
+    <Popover
+      content={isRunning && <PopoverContent record={record}></PopoverContent>}
+    >
+      <Tag color={runningStatus.color}>
+        {isRunning ? (
+          <Space>
+            <Badge color={runningStatus.color} />
+            `${runningStatus.label}${record.progress * 100}%`
+          </Space>
+        ) : (
+          runningStatus.label
+        )}
+      </Tag>
+    </Popover>
+  );
+};
+
+export default ParsingStatusCell;
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx
new file mode 100644
index 0000000..19cff26
--- /dev/null
+++ b/web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx
@@ -0,0 +1,88 @@
+import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
+import { Form, Input, Modal } from 'antd';
+import { useEffect } from 'react';
+import { useDispatch, useSelector } from 'umi';
+
+const RenameModal = () => {
+  const [form] = Form.useForm();
+  const dispatch = useDispatch();
+  const kFModel = useSelector((state: any) => state.kFModel);
+  const loading = useSelector(
+    (state: any) => state.loading.effects['kFModel/document_rename'],
+  );
+  const knowledgeBaseId = useKnowledgeBaseId();
+  const isModalOpen = kFModel.isShowRenameModal;
+  const initialName = kFModel.currentRecord?.name;
+  const documentId = kFModel.currentRecord?.id;
+
+  type FieldType = {
+    name?: string;
+  };
+
+  const closeModal = () => {
+    dispatch({
+      type: 'kFModel/setIsShowRenameModal',
+      payload: false,
+    });
+  };
+
+  const handleOk = async () => {
+    const ret = await form.validateFields();
+
+    dispatch({
+      type: 'kFModel/document_rename',
+      payload: {
+        doc_id: documentId,
+        name: ret.name,
+        kb_id: knowledgeBaseId,
+      },
+    });
+  };
+
+  const handleCancel = () => {
+    closeModal();
+  };
+
+  const onFinish = (values: any) => {
+    console.log('Success:', values);
+  };
+
+  const onFinishFailed = (errorInfo: any) => {
+    console.log('Failed:', errorInfo);
+  };
+
+  useEffect(() => {
+    form.setFieldValue('name', initialName);
+  }, [initialName, documentId]);
+
+  return (
+    <Modal
+      title="Rename"
+      open={isModalOpen}
+      onOk={handleOk}
+      onCancel={handleCancel}
+      okButtonProps={{ loading }}
+    >
+      <Form
+        name="basic"
+        labelCol={{ span: 4 }}
+        wrapperCol={{ span: 20 }}
+        style={{ maxWidth: 600 }}
+        onFinish={onFinish}
+        onFinishFailed={onFinishFailed}
+        autoComplete="off"
+        form={form}
+      >
+        <Form.Item<FieldType>
+          label="Name"
+          name="name"
+          rules={[{ required: true, message: 'Please input name!' }]}
+        >
+          <Input />
+        </Form.Item>
+      </Form>
+    </Modal>
+  );
+};
+
+export default RenameModal;
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx b/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx
index 5da38b8..23b07e1 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx
@@ -41,7 +41,6 @@ const SegmentSetModal: React.FC<kFProps> = ({
   };
 
   const handleOk = async () => {
-    console.log(1111, selectedTag);
     const retcode = await dispatch<any>({
       type: 'kFModel/document_change_parser',
       payload: {
diff --git a/web/src/pages/add-knowledge/components/knowledge-search/index.tsx b/web/src/pages/add-knowledge/components/knowledge-search/index.tsx
index 0635fac..170e9fb 100644
--- a/web/src/pages/add-knowledge/components/knowledge-search/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-search/index.tsx
@@ -1,3 +1,5 @@
+import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
+import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
 import { api_host } from '@/utils/api';
 import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons';
 import type { PaginationProps } from 'antd';
@@ -12,18 +14,14 @@ import {
   Spin,
   Switch,
 } from 'antd';
+import { debounce } from 'lodash';
 import React, { useCallback, useEffect } from 'react';
 import { useDispatch, useSelector } from 'umi';
 import CreateModal from '../knowledge-chunk/components/createModal';
 
-import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
-import { debounce } from 'lodash';
 import styles from './index.less';
-interface chunkProps {
-  kb_id: string;
-}
 
-const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
+const KnowledgeSearching = () => {
   const dispatch = useDispatch();
   const kSearchModel = useSelector((state: any) => state.kSearchModel);
   const chunkModel = useSelector((state: any) => state.chunkModel);
@@ -31,6 +29,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
     'chunk_list',
     'switch_chunk',
   ]);
+  const knowledgeBaseId = useKnowledgeBaseId();
 
   const {
     data = [],
@@ -46,7 +45,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
     dispatch({
       type: 'kSearchModel/chunk_list',
       payload: {
-        kb_id,
+        kb_id: knowledgeBaseId,
       },
     });
   };
@@ -55,7 +54,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
       type: 'kSearchModel/rm_chunk',
       payload: {
         chunk_ids: [id],
-        kb_id,
+        kb_id: knowledgeBaseId,
       },
     });
   };
@@ -93,7 +92,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
     dispatch({
       type: 'kSearchModel/getKfList',
       payload: {
-        kb_id,
+        kb_id: knowledgeBaseId,
       },
     });
   }, []);
@@ -106,7 +105,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
         chunk_ids: [chunk_id],
         doc_id,
         available_int,
-        kb_id,
+        kb_id: knowledgeBaseId,
       },
     });
   };
diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx b/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx
index 0a43c52..47dd4aa 100644
--- a/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx
@@ -1,6 +1,7 @@
 import { KnowledgeRouteKey } from '@/constants/knowledge';
+import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
 import { Button, Form, Input, Radio, Select, Space, Tag } from 'antd';
-import React, { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
 import { useDispatch, useNavigate, useSelector } from 'umi';
 import styles from './index.less';
 
@@ -13,10 +14,7 @@ const layout = {
 const { Option } = Select;
 /* eslint-disable no-template-curly-in-string */
 
-interface kSProps {
-  kb_id: string;
-}
-const KnowledgeSetting: React.FC<kSProps> = ({ kb_id }) => {
+const KnowledgeSetting = () => {
   const dispatch = useDispatch();
   const settingModel = useSelector((state: any) => state.settingModel);
   let navigate = useNavigate();
@@ -25,17 +23,18 @@ const KnowledgeSetting: React.FC<kSProps> = ({ kb_id }) => {
   const [form] = Form.useForm();
   const [selectedTag, setSelectedTag] = useState('');
   const values = Form.useWatch([], form);
+  const knowledgeBaseId = useKnowledgeBaseId();
 
   const getTenantInfo = useCallback(async () => {
     dispatch({
       type: 'settingModel/getTenantInfo',
       payload: {},
     });
-    if (kb_id) {
+    if (knowledgeBaseId) {
       const data = await dispatch<any>({
         type: 'kSModel/getKbDetail',
         payload: {
-          kb_id,
+          kb_id: knowledgeBaseId,
         },
       });
       if (data.retcode === 0) {
@@ -44,19 +43,19 @@ const KnowledgeSetting: React.FC<kSProps> = ({ kb_id }) => {
         setSelectedTag(data.data.parser_id);
       }
     }
-  }, [kb_id]);
+  }, [knowledgeBaseId]);
 
   const onFinish = async () => {
     try {
       await form.validateFields();
 
-      if (kb_id) {
+      if (knowledgeBaseId) {
         dispatch({
           type: 'kSModel/updateKb',
           payload: {
             ...values,
             parser_id: selectedTag,
-            kb_id,
+            kb_id: knowledgeBaseId,
             embd_id: undefined,
           },
         });
@@ -69,7 +68,9 @@ const KnowledgeSetting: React.FC<kSProps> = ({ kb_id }) => {
           },
         });
         retcode === 0 &&
-          navigate(`/knowledge/${KnowledgeRouteKey.Dataset}?id=${kb_id}`);
+          navigate(
+            `/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`,
+          );
       }
     } catch (error) {
       console.warn(error);
diff --git a/web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx b/web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx
index fda6c3d..e02c24f 100644
--- a/web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx
@@ -1,12 +1,13 @@
 import { ReactComponent as ConfigrationIcon } from '@/assets/svg/knowledge-configration.svg';
 import { ReactComponent as DatasetIcon } from '@/assets/svg/knowledge-dataset.svg';
 import { ReactComponent as TestingIcon } from '@/assets/svg/knowledge-testing.svg';
+import { useSecondPathName } from '@/hooks/routeHook';
 import { getWidth } from '@/utils';
 import { AntDesignOutlined } from '@ant-design/icons';
 import { Avatar, Menu, MenuProps, Space } from 'antd';
 import classNames from 'classnames';
 import { useEffect, useMemo, useState } from 'react';
-import { useNavigate, useParams, useSelector } from 'umi';
+import { useNavigate, useSelector } from 'umi';
 import { KnowledgeRouteKey, routeMap } from '../../constant';
 import styles from './index.less';
 
@@ -14,8 +15,7 @@ const KnowledgeSidebar = () => {
   const kAModel = useSelector((state: any) => state.kAModel);
   const { id } = kAModel;
   let navigate = useNavigate();
-  const params = useParams();
-  const activeKey = params.module || KnowledgeRouteKey.Dataset;
+  const activeKey = useSecondPathName();
 
   const [windowWidth, setWindowWidth] = useState(getWidth());
   const [collapsed, setCollapsed] = useState(false);
@@ -56,8 +56,8 @@ const KnowledgeSidebar = () => {
         <TestingIcon />,
       ),
       getItem(
-        routeMap[KnowledgeRouteKey.Configration],
-        KnowledgeRouteKey.Configration,
+        routeMap[KnowledgeRouteKey.Configuration],
+        KnowledgeRouteKey.Configuration,
         <ConfigrationIcon />,
       ),
     ];
diff --git a/web/src/pages/add-knowledge/constant.ts b/web/src/pages/add-knowledge/constant.ts
index c918a3a..f68a7d0 100644
--- a/web/src/pages/add-knowledge/constant.ts
+++ b/web/src/pages/add-knowledge/constant.ts
@@ -3,7 +3,17 @@ import { KnowledgeRouteKey } from '@/constants/knowledge';
 export const routeMap = {
   [KnowledgeRouteKey.Dataset]: 'Dataset',
   [KnowledgeRouteKey.Testing]: 'Retrieval testing',
-  [KnowledgeRouteKey.Configration]: 'Configuration',
+  [KnowledgeRouteKey.Configuration]: 'Configuration',
+};
+
+export enum KnowledgeDatasetRouteKey {
+  Chunk = 'chunk',
+  File = 'file',
+}
+
+export const datasetRouteMap = {
+  [KnowledgeDatasetRouteKey.Chunk]: 'Chunk',
+  [KnowledgeDatasetRouteKey.File]: 'File Upload',
 };
 
 export * from '@/constants/knowledge';
diff --git a/web/src/pages/add-knowledge/index.less b/web/src/pages/add-knowledge/index.less
index d94c573..78534ef 100644
--- a/web/src/pages/add-knowledge/index.less
+++ b/web/src/pages/add-knowledge/index.less
@@ -7,9 +7,12 @@
     height: 100%;
     background-color: rgba(247, 248, 250, 1);
     padding: 16px 20px 28px 40px;
+    display: flex;
+    flex-direction: column;
   }
   .content {
     background-color: white;
     margin-top: 16px;
+    // flex: 1;
   }
 }
diff --git a/web/src/pages/add-knowledge/index.tsx b/web/src/pages/add-knowledge/index.tsx
index 74942e7..370d115 100644
--- a/web/src/pages/add-knowledge/index.tsx
+++ b/web/src/pages/add-knowledge/index.tsx
@@ -1,45 +1,60 @@
+import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
+import { useSecondPathName, useThirdPathName } from '@/hooks/routeHook';
 import { Breadcrumb } from 'antd';
+import { ItemType } from 'antd/es/breadcrumb/Breadcrumb';
 import { useEffect, useMemo } from 'react';
-import {
-  useDispatch,
-  useLocation,
-  useNavigate,
-  useParams,
-  useSelector,
-} from 'umi';
-import Chunk from './components/knowledge-chunk';
-import File from './components/knowledge-file';
-import Search from './components/knowledge-search';
-import Setting from './components/knowledge-setting';
+import { Link, Outlet, useDispatch, useLocation, useNavigate } from 'umi';
 import Siderbar from './components/knowledge-sidebar';
-import { KnowledgeRouteKey, routeMap } from './constant';
+import {
+  KnowledgeDatasetRouteKey,
+  KnowledgeRouteKey,
+  datasetRouteMap,
+  routeMap,
+} from './constant';
 import styles from './index.less';
 
 const KnowledgeAdding = () => {
   const dispatch = useDispatch();
-  const kAModel = useSelector((state: any) => state.kAModel);
   const navigate = useNavigate();
-  const { id, doc_id } = kAModel;
+  const knowledgeBaseId = useKnowledgeBaseId();
 
   const location = useLocation();
-  const params = useParams();
   const activeKey: KnowledgeRouteKey =
-    (params.module as KnowledgeRouteKey) || KnowledgeRouteKey.Dataset;
+    (useSecondPathName() as KnowledgeRouteKey) || KnowledgeRouteKey.Dataset;
+
+  const datasetActiveKey: KnowledgeDatasetRouteKey =
+    useThirdPathName() as KnowledgeDatasetRouteKey;
 
   const gotoList = () => {
     navigate('/knowledge');
   };
 
-  const breadcrumbItems = useMemo(() => {
-    return [
+  const breadcrumbItems: ItemType[] = useMemo(() => {
+    const items: ItemType[] = [
       {
         title: <a onClick={gotoList}>Knowledge Base</a>,
       },
       {
-        title: routeMap[activeKey],
+        title: datasetActiveKey ? (
+          <Link
+            to={`/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`}
+          >
+            {routeMap[activeKey]}
+          </Link>
+        ) : (
+          routeMap[activeKey]
+        ),
       },
     ];
-  }, [activeKey]);
+
+    if (datasetActiveKey) {
+      items.push({
+        title: datasetRouteMap[datasetActiveKey],
+      });
+    }
+
+    return items;
+  }, [activeKey, datasetActiveKey]);
 
   useEffect(() => {
     const search: string = location.search.slice(1);
@@ -65,16 +80,7 @@ const KnowledgeAdding = () => {
         <div className={styles.contentWrapper}>
           <Breadcrumb items={breadcrumbItems} />
           <div className={styles.content}>
-            {activeKey === KnowledgeRouteKey.Dataset && !doc_id && (
-              <File kb_id={id} />
-            )}
-            {activeKey === KnowledgeRouteKey.Configration && (
-              <Setting kb_id={id} />
-            )}
-            {activeKey === KnowledgeRouteKey.Testing && <Search kb_id={id} />}
-            {activeKey === KnowledgeRouteKey.Dataset && !!doc_id && (
-              <Chunk doc_id={doc_id} />
-            )}
+            <Outlet></Outlet>
           </div>
         </div>
       </div>
diff --git a/web/src/pages/knowledge/index.tsx b/web/src/pages/knowledge/index.tsx
index 234a9a4..d15cca1 100644
--- a/web/src/pages/knowledge/index.tsx
+++ b/web/src/pages/knowledge/index.tsx
@@ -1,6 +1,7 @@
 import { ReactComponent as FilterIcon } from '@/assets/filter.svg';
+import { KnowledgeRouteKey } from '@/constants/knowledge';
 import { PlusOutlined } from '@ant-design/icons';
-import { Button, Col, Row, Space } from 'antd';
+import { Button, Flex, Space } from 'antd';
 import { useCallback, useEffect } from 'react';
 import { useDispatch, useNavigate, useSelector } from 'umi';
 import styles from './index.less';
@@ -20,7 +21,7 @@ const Knowledge = () => {
   }, []);
 
   const handleAddKnowledge = () => {
-    navigate(`add/setting`);
+    navigate(`/knowledge/${KnowledgeRouteKey.Configuration}`);
   };
 
   useEffect(() => {
@@ -50,7 +51,7 @@ const Knowledge = () => {
           </Button>
         </Space>
       </div>
-      <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
+      {/* <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
         {data.map((item: any) => {
           return (
             <Col
@@ -58,14 +59,19 @@ const Knowledge = () => {
               key={item.name}
               xs={24}
               sm={12}
-              md={8}
-              lg={6}
+              md={10}
+              lg={8}
             >
               <KnowledgeCard item={item}></KnowledgeCard>
             </Col>
           );
         })}
-      </Row>
+      </Row> */}
+      <Flex gap="large" wrap="wrap">
+        {data.map((item: any) => {
+          return <KnowledgeCard item={item} key={item.name}></KnowledgeCard>;
+        })}
+      </Flex>
     </div>
   );
 };
diff --git a/web/src/pages/knowledge/knowledge-card/index.less b/web/src/pages/knowledge/knowledge-card/index.less
index 17b6bb6..cf2aa02 100644
--- a/web/src/pages/knowledge/knowledge-card/index.less
+++ b/web/src/pages/knowledge/knowledge-card/index.less
@@ -26,7 +26,7 @@
   border: 1px solid rgba(234, 236, 240, 1);
   box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
   padding: 24px;
-  min-width: 300px;
+  max-width: 300px;
   cursor: pointer;
 
   .titleWrapper {
diff --git a/web/src/routes.ts b/web/src/routes.ts
index 8e2e5b1..2b7a251 100644
--- a/web/src/routes.ts
+++ b/web/src/routes.ts
@@ -16,8 +16,37 @@ const routes = [
         component: '@/pages/knowledge',
       },
       {
-        path: '/knowledge/:module',
+        path: '/knowledge',
         component: '@/pages/add-knowledge',
+        routes: [
+          {
+            path: '/knowledge/dataset',
+            component: '@/pages/add-knowledge/components/knowledge-dataset',
+            routes: [
+              {
+                path: '/knowledge/dataset',
+                component: '@/pages/add-knowledge/components/knowledge-file',
+              },
+              {
+                path: '/knowledge/dataset/upload',
+                component:
+                  '@/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file',
+              },
+              {
+                path: '/knowledge/dataset/chunk',
+                component: '@/pages/add-knowledge/components/knowledge-chunk',
+              },
+            ],
+          },
+          {
+            path: '/knowledge/configuration',
+            component: '@/pages/add-knowledge/components/knowledge-setting',
+          },
+          {
+            path: '/knowledge/testing',
+            component: '@/pages/add-knowledge/components/knowledge-search',
+          },
+        ],
       },
       {
         path: '/chat',
diff --git a/web/src/services/kbService.ts b/web/src/services/kbService.ts
index 0fa0254..d0d6c91 100644
--- a/web/src/services/kbService.ts
+++ b/web/src/services/kbService.ts
@@ -20,6 +20,7 @@ const {
   switch_chunk,
   rm_chunk,
   retrieval_test,
+  document_rename,
 } = api;
 
 const methods = {
@@ -57,6 +58,10 @@ const methods = {
     url: document_rm,
     method: 'post',
   },
+  document_rename: {
+    url: document_rename,
+    method: 'post',
+  },
   document_create: {
     url: document_create,
     method: 'post',
diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts
index 70b4f06..fb5adcb 100644
--- a/web/src/utils/api.ts
+++ b/web/src/utils/api.ts
@@ -33,11 +33,12 @@ export default {
   rm_chunk: `${api_host}/chunk/rm`,
   retrieval_test: `${api_host}/chunk/retrieval_test`,
 
-  // 上传
+  // 文件管理
   upload: `${api_host}/document/upload`,
   get_document_list: `${api_host}/document/list`,
   document_change_status: `${api_host}/document/change_status`,
   document_rm: `${api_host}/document/rm`,
+  document_rename: `${api_host}/document/rename`,
   document_create: `${api_host}/document/create`,
   document_change_parser: `${api_host}/document/change_parser`,
 };
diff --git a/web/typings.d.ts b/web/typings.d.ts
index 8fb5f3e..632c633 100644
--- a/web/typings.d.ts
+++ b/web/typings.d.ts
@@ -1,2 +1,4 @@
 import 'umi/typings';
-declare module 'lodash'
\ No newline at end of file
+declare module 'lodash';
+
+export type Nullable<T> = T | null;
-- 
GitLab