balibabu commited on
Commit
7b71fb2
·
1 Parent(s): 503735c

feat: modify routing to nested mode and rename document (#52)

Browse files

* feat: modify routing to nested mode

* feat: rename document

Files changed (33) hide show
  1. web/src/components/deleting-confirm/index.less +0 -0
  2. web/src/components/deleting-confirm/index.tsx +28 -0
  3. web/src/components/modal-manager.tsx +24 -0
  4. web/src/constants/knowledge.ts +9 -1
  5. web/src/hooks/knowledgeHook.ts +8 -0
  6. web/src/hooks/routeHook.ts +21 -0
  7. web/src/interfaces/database/knowledge.ts +26 -0
  8. web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx +10 -14
  9. web/src/pages/add-knowledge/components/knowledge-dataset/index.less +0 -0
  10. web/src/pages/add-knowledge/components/knowledge-dataset/index.tsx +7 -0
  11. web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx +5 -0
  12. web/src/pages/add-knowledge/components/knowledge-file/constant.ts +17 -0
  13. web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx +12 -7
  14. web/src/pages/add-knowledge/components/knowledge-file/index.less +22 -16
  15. web/src/pages/add-knowledge/components/knowledge-file/index.tsx +82 -68
  16. web/src/pages/add-knowledge/components/knowledge-file/model.ts +34 -1
  17. web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx +88 -0
  18. web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less +3 -0
  19. web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx +68 -0
  20. web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx +88 -0
  21. web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx +0 -1
  22. web/src/pages/add-knowledge/components/knowledge-search/index.tsx +9 -10
  23. web/src/pages/add-knowledge/components/knowledge-setting/index.tsx +12 -11
  24. web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx +5 -5
  25. web/src/pages/add-knowledge/constant.ts +11 -1
  26. web/src/pages/add-knowledge/index.less +3 -0
  27. web/src/pages/add-knowledge/index.tsx +36 -30
  28. web/src/pages/knowledge/index.tsx +12 -6
  29. web/src/pages/knowledge/knowledge-card/index.less +1 -1
  30. web/src/routes.ts +30 -1
  31. web/src/services/kbService.ts +5 -0
  32. web/src/utils/api.ts +2 -1
  33. web/typings.d.ts +3 -1
web/src/components/deleting-confirm/index.less ADDED
File without changes
web/src/components/deleting-confirm/index.tsx ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ExclamationCircleFilled } from '@ant-design/icons';
2
+ import { Modal } from 'antd';
3
+
4
+ const { confirm } = Modal;
5
+
6
+ interface IProps {
7
+ onOk?: (...args: any[]) => any;
8
+ onCancel?: (...args: any[]) => any;
9
+ }
10
+
11
+ export const showDeleteConfirm = ({ onOk, onCancel }: IProps) => {
12
+ confirm({
13
+ title: 'Are you sure delete this item?',
14
+ icon: <ExclamationCircleFilled />,
15
+ content: 'Some descriptions',
16
+ okText: 'Yes',
17
+ okType: 'danger',
18
+ cancelText: 'No',
19
+ onOk() {
20
+ onOk?.();
21
+ },
22
+ onCancel() {
23
+ onCancel?.();
24
+ },
25
+ });
26
+ };
27
+
28
+ export default showDeleteConfirm;
web/src/components/modal-manager.tsx ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from 'react';
2
+
3
+ interface IProps {
4
+ children: (props: {
5
+ showModal(): void;
6
+ hideModal(): void;
7
+ visible: boolean;
8
+ }) => React.ReactNode;
9
+ }
10
+
11
+ const ModalManager = ({ children }: IProps) => {
12
+ const [visible, setVisible] = useState(false);
13
+
14
+ const showModal = () => {
15
+ setVisible(true);
16
+ };
17
+ const hideModal = () => {
18
+ setVisible(false);
19
+ };
20
+
21
+ return children({ visible, showModal, hideModal });
22
+ };
23
+
24
+ export default ModalManager;
web/src/constants/knowledge.ts CHANGED
@@ -1,5 +1,13 @@
1
  export enum KnowledgeRouteKey {
2
  Dataset = 'dataset',
3
  Testing = 'testing',
4
- Configration = 'configration',
 
 
 
 
 
 
 
 
5
  }
 
1
  export enum KnowledgeRouteKey {
2
  Dataset = 'dataset',
3
  Testing = 'testing',
4
+ Configuration = 'configuration',
5
+ }
6
+
7
+ export enum RunningStatus {
8
+ UNSTART = '0',
9
+ RUNNING = '1',
10
+ CANCEL = '2',
11
+ DONE = '3',
12
+ FAIL = '4',
13
  }
web/src/hooks/knowledgeHook.ts ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import { useSearchParams } from 'umi';
2
+
3
+ export const useKnowledgeBaseId = (): string => {
4
+ const [searchParams] = useSearchParams();
5
+ const knowledgeBaseId = searchParams.get('id');
6
+
7
+ return knowledgeBaseId || '';
8
+ };
web/src/hooks/routeHook.ts ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useLocation } from 'umi';
2
+
3
+ export enum SegmentIndex {
4
+ Second = '2',
5
+ Third = '3',
6
+ }
7
+
8
+ export const useSegmentedPathName = (index: SegmentIndex) => {
9
+ const { pathname } = useLocation();
10
+
11
+ const pathArray = pathname.split('/');
12
+ return pathArray[index] || '';
13
+ };
14
+
15
+ export const useSecondPathName = () => {
16
+ return useSegmentedPathName(SegmentIndex.Second);
17
+ };
18
+
19
+ export const useThirdPathName = () => {
20
+ return useSegmentedPathName(SegmentIndex.Third);
21
+ };
web/src/interfaces/database/knowledge.ts ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { RunningStatus } from '@/constants/knowledge';
2
+
3
+ export interface IKnowledgeFile {
4
+ chunk_num: number;
5
+ create_date: string;
6
+ create_time: number;
7
+ created_by: string;
8
+ id: string;
9
+ kb_id: string;
10
+ location: string;
11
+ name: string;
12
+ parser_id: string;
13
+ process_begin_at?: any;
14
+ process_duation: number;
15
+ progress: number; // parsing process
16
+ progress_msg: string; // parsing log
17
+ run: RunningStatus; // parsing status
18
+ size: number;
19
+ source_type: string;
20
+ status: string; // enabled
21
+ thumbnail?: any; // base64
22
+ token_num: number;
23
+ type: string;
24
+ update_date: string;
25
+ update_time: number;
26
+ }
web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx CHANGED
@@ -14,11 +14,11 @@ import {
14
  Spin,
15
  Switch,
16
  } from 'antd';
 
17
  import React, { useCallback, useEffect, useState } from 'react';
18
- import { useDispatch, useNavigate, useSelector } from 'umi';
19
  import CreateModal from './components/createModal';
20
 
21
- import { debounce } from 'lodash';
22
  import styles from './index.less';
23
 
24
  interface PayloadType {
@@ -27,18 +27,13 @@ interface PayloadType {
27
  available_int?: number;
28
  }
29
 
30
- interface IProps {
31
- doc_id: string;
32
- }
33
-
34
- const Chunk = ({ doc_id }: IProps) => {
35
  const dispatch = useDispatch();
36
  const chunkModel = useSelector((state: any) => state.chunkModel);
37
  const [keywords, SetKeywords] = useState('');
38
  const [available_int, setAvailableInt] = useState(-1);
39
- const navigate = useNavigate();
40
  const [pagination, setPagination] = useState({ page: 1, size: 30 });
41
- // const [datas, setDatas] = useState(data)
42
  const { data = [], total, chunk_id, isShowCreateModal } = chunkModel;
43
  const effects = useSelector((state: any) => state.loading.effects);
44
  const loading = getOneNamespaceEffectsLoading('chunkModel', effects, [
@@ -46,10 +41,11 @@ const Chunk = ({ doc_id }: IProps) => {
46
  'chunk_list',
47
  'switch_chunk',
48
  ]);
 
49
 
50
  const getChunkList = (value?: string) => {
51
  const payload: PayloadType = {
52
- doc_id,
53
  keywords: value || keywords,
54
  available_int,
55
  };
@@ -81,7 +77,7 @@ const Chunk = ({ doc_id }: IProps) => {
81
  payload: {
82
  isShowCreateModal: true,
83
  chunk_id,
84
- doc_id,
85
  },
86
  });
87
  getChunkList();
@@ -100,7 +96,7 @@ const Chunk = ({ doc_id }: IProps) => {
100
  payload: {
101
  chunk_ids: [id],
102
  available_int: Number(available_int),
103
- doc_id,
104
  },
105
  });
106
 
@@ -109,7 +105,7 @@ const Chunk = ({ doc_id }: IProps) => {
109
 
110
  useEffect(() => {
111
  getChunkList();
112
- }, [doc_id, available_int, pagination]);
113
 
114
  const debounceChange = debounce(getChunkList, 300);
115
  const debounceCallback = useCallback(
@@ -270,7 +266,7 @@ const Chunk = ({ doc_id }: IProps) => {
270
  </div>
271
  </div>
272
  <CreateModal
273
- doc_id={doc_id}
274
  isShowCreateModal={isShowCreateModal}
275
  chunk_id={chunk_id}
276
  getChunkList={getChunkList}
 
14
  Spin,
15
  Switch,
16
  } from 'antd';
17
+ import { debounce } from 'lodash';
18
  import React, { useCallback, useEffect, useState } from 'react';
19
+ import { useDispatch, useSearchParams, useSelector } from 'umi';
20
  import CreateModal from './components/createModal';
21
 
 
22
  import styles from './index.less';
23
 
24
  interface PayloadType {
 
27
  available_int?: number;
28
  }
29
 
30
+ const Chunk = () => {
 
 
 
 
31
  const dispatch = useDispatch();
32
  const chunkModel = useSelector((state: any) => state.chunkModel);
33
  const [keywords, SetKeywords] = useState('');
34
  const [available_int, setAvailableInt] = useState(-1);
35
+ const [searchParams] = useSearchParams();
36
  const [pagination, setPagination] = useState({ page: 1, size: 30 });
 
37
  const { data = [], total, chunk_id, isShowCreateModal } = chunkModel;
38
  const effects = useSelector((state: any) => state.loading.effects);
39
  const loading = getOneNamespaceEffectsLoading('chunkModel', effects, [
 
41
  'chunk_list',
42
  'switch_chunk',
43
  ]);
44
+ const documentId: string = searchParams.get('doc_id') || '';
45
 
46
  const getChunkList = (value?: string) => {
47
  const payload: PayloadType = {
48
+ doc_id: documentId,
49
  keywords: value || keywords,
50
  available_int,
51
  };
 
77
  payload: {
78
  isShowCreateModal: true,
79
  chunk_id,
80
+ doc_id: documentId,
81
  },
82
  });
83
  getChunkList();
 
96
  payload: {
97
  chunk_ids: [id],
98
  available_int: Number(available_int),
99
+ doc_id: documentId,
100
  },
101
  });
102
 
 
105
 
106
  useEffect(() => {
107
  getChunkList();
108
+ }, [documentId, available_int, pagination]);
109
 
110
  const debounceChange = debounce(getChunkList, 300);
111
  const debounceCallback = useCallback(
 
266
  </div>
267
  </div>
268
  <CreateModal
269
+ doc_id={documentId}
270
  isShowCreateModal={isShowCreateModal}
271
  chunk_id={chunk_id}
272
  getChunkList={getChunkList}
web/src/pages/add-knowledge/components/knowledge-dataset/index.less ADDED
File without changes
web/src/pages/add-knowledge/components/knowledge-dataset/index.tsx ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import { Outlet } from 'umi';
2
+
3
+ export const KnowledgeDataset = () => {
4
+ return <Outlet></Outlet>;
5
+ };
6
+
7
+ export default KnowledgeDataset;
web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ const KnowledgeUploadFile = () => {
2
+ return <div>KnowledgeUploadFile</div>;
3
+ };
4
+
5
+ export default KnowledgeUploadFile;
web/src/pages/add-knowledge/components/knowledge-file/constant.ts ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { RunningStatus } from '@/constants/knowledge';
2
+
3
+ export const RunningStatusMap = {
4
+ [RunningStatus.UNSTART]: {
5
+ label: 'UNSTART',
6
+ color: 'cyan',
7
+ },
8
+ [RunningStatus.RUNNING]: {
9
+ label: 'Parsing',
10
+ color: 'blue',
11
+ },
12
+ [RunningStatus.CANCEL]: { label: 'CANCEL', color: 'orange' },
13
+ [RunningStatus.DONE]: { label: 'SUCCESS', color: 'geekblue' },
14
+ [RunningStatus.FAIL]: { label: 'FAIL', color: 'red' },
15
+ };
16
+
17
+ export * from '@/constants/knowledge';
web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx CHANGED
@@ -13,9 +13,9 @@ interface kFProps {
13
 
14
  const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
15
  const dispatch = useDispatch();
 
16
  const kFModel = useSelector((state: any) => state.kFModel);
17
  const { isShowCEFwModal } = kFModel;
18
- const [form] = Form.useForm();
19
  const { t } = useTranslation();
20
 
21
  const handleCancel = () => {
@@ -26,7 +26,8 @@ const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
26
  },
27
  });
28
  };
29
- const handleOk = async () => {
 
30
  try {
31
  const values = await form.validateFields();
32
  const retcode = await dispatch<any>({
@@ -44,9 +45,13 @@ const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
44
  }
45
  };
46
 
 
 
 
 
47
  return (
48
  <Modal
49
- title="Basic Modal"
50
  open={isShowCEFwModal}
51
  onOk={handleOk}
52
  onCancel={handleCancel}
@@ -54,15 +59,15 @@ const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
54
  <Form
55
  form={form}
56
  name="validateOnly"
57
- labelCol={{ span: 8 }}
58
- wrapperCol={{ span: 16 }}
59
  style={{ maxWidth: 600 }}
60
  autoComplete="off"
61
  >
62
  <Form.Item<FieldType>
63
- label="文件名"
64
  name="name"
65
- rules={[{ required: true, message: 'Please input value!' }]}
66
  >
67
  <Input />
68
  </Form.Item>
 
13
 
14
  const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
15
  const dispatch = useDispatch();
16
+ const [form] = Form.useForm();
17
  const kFModel = useSelector((state: any) => state.kFModel);
18
  const { isShowCEFwModal } = kFModel;
 
19
  const { t } = useTranslation();
20
 
21
  const handleCancel = () => {
 
26
  },
27
  });
28
  };
29
+
30
+ const createDocument = async () => {
31
  try {
32
  const values = await form.validateFields();
33
  const retcode = await dispatch<any>({
 
45
  }
46
  };
47
 
48
+ const handleOk = async () => {
49
+ createDocument();
50
+ };
51
+
52
  return (
53
  <Modal
54
+ title="File Name"
55
  open={isShowCEFwModal}
56
  onOk={handleOk}
57
  onCancel={handleCancel}
 
59
  <Form
60
  form={form}
61
  name="validateOnly"
62
+ labelCol={{ span: 4 }}
63
+ wrapperCol={{ span: 20 }}
64
  style={{ maxWidth: 600 }}
65
  autoComplete="off"
66
  >
67
  <Form.Item<FieldType>
68
+ label="File Name"
69
  name="name"
70
+ rules={[{ required: true, message: 'Please input name!' }]}
71
  >
72
  <Input />
73
  </Form.Item>
web/src/pages/add-knowledge/components/knowledge-file/index.less CHANGED
@@ -1,28 +1,34 @@
 
 
 
 
 
1
  .filter {
2
- height: 32px;
3
- display: flex;
4
- margin: 10px 0;
5
- justify-content: space-between;
 
6
 
7
- .search {
8
- flex: 1;
9
- }
10
 
11
- .operate {
12
- width: 200px;
13
- }
14
  }
15
 
16
  .img {
17
- height: 16px;
18
- width: 16px;
19
- margin-right: 6px;
20
  }
21
 
22
  .column {
23
- min-width: 200px
24
  }
25
 
26
  .tochunks {
27
- cursor: pointer;
28
- }
 
1
+ .datasetWrapper {
2
+ padding: 30px;
3
+ flex: 1;
4
+ }
5
+
6
  .filter {
7
+ height: 32px;
8
+ display: flex;
9
+ margin: 10px 0;
10
+ justify-content: space-between;
11
+ padding: 24px 20px;
12
 
13
+ // .search {
14
+ // flex: 1;
15
+ // }
16
 
17
+ // .operate {
18
+ // width: 200px;
19
+ // }
20
  }
21
 
22
  .img {
23
+ height: 16px;
24
+ width: 16px;
25
+ margin-right: 6px;
26
  }
27
 
28
  .column {
29
+ min-width: 200px;
30
  }
31
 
32
  .tochunks {
33
+ cursor: pointer;
34
+ }
web/src/pages/add-knowledge/components/knowledge-file/index.tsx CHANGED
@@ -1,37 +1,38 @@
1
  import { KnowledgeRouteKey } from '@/constants/knowledge';
 
 
2
  import { getOneNamespaceEffectsLoading } from '@/utils/stroreUtil';
3
- import { DownOutlined } from '@ant-design/icons';
4
  import type { MenuProps } from 'antd';
5
- import { Button, Dropdown, Input, Space, Switch, Table } from 'antd';
 
 
 
 
 
 
 
 
 
6
  import type { ColumnsType } from 'antd/es/table';
7
  import { debounce } from 'lodash';
8
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
9
  import { useDispatch, useNavigate, useSelector } from 'umi';
10
  import CreateEPModal from './createEFileModal';
11
  import styles from './index.less';
 
 
 
12
  import SegmentSetModal from './segmentSetModal';
13
  import UploadFile from './upload';
14
 
15
- interface DataType {
16
- name: string;
17
- chunk_num: string;
18
- token_num: number;
19
- update_date: string;
20
- size: string;
21
- status: string;
22
- id: string;
23
- parser_id: string;
24
- }
25
-
26
- interface KFProps {
27
- kb_id: string;
28
- }
29
-
30
- const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
31
  const dispatch = useDispatch();
32
  const kFModel = useSelector((state: any) => state.kFModel);
33
  const effects = useSelector((state: any) => state.loading.effects);
34
  const { data } = kFModel;
 
 
35
  const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
36
  'getKfList',
37
  'updateDocumentStatus',
@@ -43,7 +44,7 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
43
 
44
  const getKfList = (keywords?: string) => {
45
  const payload = {
46
- kb_id,
47
  keywords,
48
  };
49
  if (!keywords) {
@@ -56,10 +57,10 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
56
  };
57
 
58
  useEffect(() => {
59
- if (kb_id) {
60
  getKfList();
61
  }
62
- }, [kb_id]);
63
 
64
  const debounceChange = debounce(getKfList, 300);
65
  const debounceCallback = useCallback(
@@ -79,7 +80,7 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
79
  payload: {
80
  doc_id,
81
  status: Number(e),
82
- kb_id,
83
  },
84
  });
85
  };
@@ -88,7 +89,7 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
88
  type: 'kFModel/document_rm',
89
  payload: {
90
  doc_id,
91
- kb_id,
92
  },
93
  });
94
  };
@@ -109,13 +110,14 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
109
  },
110
  });
111
  };
 
112
  const actionItems: MenuProps['items'] = useMemo(() => {
113
  return [
114
  {
115
  key: '1',
116
  label: (
117
  <div>
118
- <UploadFile kb_id={kb_id} getKfList={getKfList} />
119
  </div>
120
  ),
121
  },
@@ -132,7 +134,7 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
132
  // disabled: true,
133
  },
134
  ];
135
- }, [kb_id]);
136
  const chunkItems: MenuProps['items'] = [
137
  {
138
  key: '1',
@@ -158,14 +160,21 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
158
  // disabled: true,
159
  },
160
  ];
 
161
  const toChunk = (id: string) => {
162
  navigate(
163
- `/knowledge/${KnowledgeRouteKey.Dataset}?id=${kb_id}&doc_id=${id}`,
164
  );
165
  };
166
- const columns: ColumnsType<DataType> = [
 
 
 
 
 
 
167
  {
168
- title: '名称',
169
  dataIndex: 'name',
170
  key: 'name',
171
  render: (text: any, { id }) => (
@@ -178,32 +187,30 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
178
  {text}
179
  </div>
180
  ),
181
- className: `${styles.column}`,
182
  },
183
  {
184
- title: '数据总量',
185
  dataIndex: 'chunk_num',
186
  key: 'chunk_num',
187
- className: `${styles.column}`,
188
  },
189
  {
190
- title: 'Tokens',
191
- dataIndex: 'token_num',
192
- key: 'token_num',
193
- className: `${styles.column}`,
194
  },
195
  {
196
- title: '文件大小',
197
- dataIndex: 'size',
198
- key: 'size',
199
- className: `${styles.column}`,
 
 
200
  },
201
  {
202
- title: '状态',
203
  key: 'status',
204
  dataIndex: 'status',
205
- className: `${styles.column}`,
206
- render: (_, { status: string, id }) => (
207
  <>
208
  <Switch
209
  defaultChecked={status === '1'}
@@ -217,58 +224,65 @@ const KnowledgeFile: React.FC<KFProps> = ({ kb_id }) => {
217
  {
218
  title: 'Action',
219
  key: 'action',
220
- className: `${styles.column}`,
221
  render: (_, record) => (
222
- <Space size="middle">
223
- <Dropdown menu={{ items: chunkItems }} trigger={['click']}>
224
- <a
225
- onClick={() => {
226
- setDocId(record.id);
227
- setParserId(record.parser_id);
228
- }}
229
- >
230
- 分段设置 <DownOutlined />
231
- </a>
232
- </Dropdown>
233
- </Space>
234
  ),
235
  },
236
  ];
 
 
 
 
 
 
237
  return (
238
- <>
 
 
 
239
  <div className={styles.filter}>
240
- <div className="search">
 
 
 
 
241
  <Input
242
- placeholder="搜索"
243
  value={inputValue}
244
  style={{ width: 220 }}
245
  allowClear
246
  onChange={handleInputChange}
 
247
  />
248
- </div>
249
- <div className="operate">
250
  <Dropdown menu={{ items: actionItems }} trigger={['click']}>
251
- <a>
252
- 导入文件 <DownOutlined />
253
- </a>
254
  </Dropdown>
255
- </div>
256
  </div>
257
  <Table
258
  rowKey="id"
259
- columns={columns}
260
  dataSource={data}
261
  loading={loading}
262
  pagination={false}
263
- scroll={{ scrollToFirstRowOnChange: true, x: true }}
264
  />
265
- <CreateEPModal getKfList={getKfList} kb_id={kb_id} />
266
  <SegmentSetModal
267
  getKfList={getKfList}
268
  parser_id={parser_id}
269
  doc_id={doc_id}
270
  />
271
- </>
 
272
  );
273
  };
274
 
 
1
  import { KnowledgeRouteKey } from '@/constants/knowledge';
2
+ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
3
+ import { IKnowledgeFile } from '@/interfaces/database/knowledge';
4
  import { getOneNamespaceEffectsLoading } from '@/utils/stroreUtil';
5
+ import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
6
  import type { MenuProps } from 'antd';
7
+ import {
8
+ Button,
9
+ Divider,
10
+ Dropdown,
11
+ Input,
12
+ Space,
13
+ Switch,
14
+ Table,
15
+ Tag,
16
+ } from 'antd';
17
  import type { ColumnsType } from 'antd/es/table';
18
  import { debounce } from 'lodash';
19
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
20
  import { useDispatch, useNavigate, useSelector } from 'umi';
21
  import CreateEPModal from './createEFileModal';
22
  import styles from './index.less';
23
+ import ParsingActionCell from './parsing-action-cell';
24
+ import ParsingStatusCell from './parsing-status-cell';
25
+ import RenameModal from './rename-modal';
26
  import SegmentSetModal from './segmentSetModal';
27
  import UploadFile from './upload';
28
 
29
+ const KnowledgeFile = () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  const dispatch = useDispatch();
31
  const kFModel = useSelector((state: any) => state.kFModel);
32
  const effects = useSelector((state: any) => state.loading.effects);
33
  const { data } = kFModel;
34
+ const knowledgeBaseId = useKnowledgeBaseId();
35
+
36
  const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
37
  'getKfList',
38
  'updateDocumentStatus',
 
44
 
45
  const getKfList = (keywords?: string) => {
46
  const payload = {
47
+ kb_id: knowledgeBaseId,
48
  keywords,
49
  };
50
  if (!keywords) {
 
57
  };
58
 
59
  useEffect(() => {
60
+ if (knowledgeBaseId) {
61
  getKfList();
62
  }
63
+ }, [knowledgeBaseId]);
64
 
65
  const debounceChange = debounce(getKfList, 300);
66
  const debounceCallback = useCallback(
 
80
  payload: {
81
  doc_id,
82
  status: Number(e),
83
+ kb_id: knowledgeBaseId,
84
  },
85
  });
86
  };
 
89
  type: 'kFModel/document_rm',
90
  payload: {
91
  doc_id,
92
+ kb_id: knowledgeBaseId,
93
  },
94
  });
95
  };
 
110
  },
111
  });
112
  };
113
+
114
  const actionItems: MenuProps['items'] = useMemo(() => {
115
  return [
116
  {
117
  key: '1',
118
  label: (
119
  <div>
120
+ <UploadFile kb_id={knowledgeBaseId} getKfList={getKfList} />
121
  </div>
122
  ),
123
  },
 
134
  // disabled: true,
135
  },
136
  ];
137
+ }, [knowledgeBaseId]);
138
  const chunkItems: MenuProps['items'] = [
139
  {
140
  key: '1',
 
160
  // disabled: true,
161
  },
162
  ];
163
+
164
  const toChunk = (id: string) => {
165
  navigate(
166
+ `/knowledge/${KnowledgeRouteKey.Dataset}/chunk?id=${knowledgeBaseId}&doc_id=${id}`,
167
  );
168
  };
169
+
170
+ const setDocumentAndParserId = (record: IKnowledgeFile) => () => {
171
+ setDocId(record.id);
172
+ setParserId(record.parser_id);
173
+ };
174
+
175
+ const columns: ColumnsType<IKnowledgeFile> = [
176
  {
177
+ title: 'Name',
178
  dataIndex: 'name',
179
  key: 'name',
180
  render: (text: any, { id }) => (
 
187
  {text}
188
  </div>
189
  ),
 
190
  },
191
  {
192
+ title: 'Chunk Number',
193
  dataIndex: 'chunk_num',
194
  key: 'chunk_num',
 
195
  },
196
  {
197
+ title: 'Upload Date',
198
+ dataIndex: 'create_date',
199
+ key: 'create_date',
 
200
  },
201
  {
202
+ title: 'Parsing Status',
203
+ dataIndex: 'run',
204
+ key: 'run',
205
+ render: (text, record) => {
206
+ return <ParsingStatusCell record={record}></ParsingStatusCell>;
207
+ },
208
  },
209
  {
210
+ title: 'Enabled',
211
  key: 'status',
212
  dataIndex: 'status',
213
+ render: (_, { status, id }) => (
 
214
  <>
215
  <Switch
216
  defaultChecked={status === '1'}
 
224
  {
225
  title: 'Action',
226
  key: 'action',
 
227
  render: (_, record) => (
228
+ <ParsingActionCell
229
+ documentId={doc_id}
230
+ knowledgeBaseId={knowledgeBaseId}
231
+ setDocumentAndParserId={setDocumentAndParserId(record)}
232
+ record={record}
233
+ ></ParsingActionCell>
 
 
 
 
 
 
234
  ),
235
  },
236
  ];
237
+
238
+ const finalColumns = columns.map((x) => ({
239
+ ...x,
240
+ className: `${styles.column}`,
241
+ }));
242
+
243
  return (
244
+ <div className={styles.datasetWrapper}>
245
+ <h3>Dataset</h3>
246
+ <p>Hey, don't forget to adjust the chunk after adding the dataset! 😉</p>
247
+ <Divider></Divider>
248
  <div className={styles.filter}>
249
+ <Space>
250
+ <h3>Total</h3>
251
+ <Tag color="purple">100 files</Tag>
252
+ </Space>
253
+ <Space>
254
  <Input
255
+ placeholder="Seach your files"
256
  value={inputValue}
257
  style={{ width: 220 }}
258
  allowClear
259
  onChange={handleInputChange}
260
+ prefix={<SearchOutlined />}
261
  />
262
+
 
263
  <Dropdown menu={{ items: actionItems }} trigger={['click']}>
264
+ <Button type="primary" icon={<PlusOutlined />}>
265
+ Add file
266
+ </Button>
267
  </Dropdown>
268
+ </Space>
269
  </div>
270
  <Table
271
  rowKey="id"
272
+ columns={finalColumns}
273
  dataSource={data}
274
  loading={loading}
275
  pagination={false}
276
+ scroll={{ scrollToFirstRowOnChange: true, x: true, y: 'fill' }}
277
  />
278
+ <CreateEPModal getKfList={getKfList} kb_id={knowledgeBaseId} />
279
  <SegmentSetModal
280
  getKfList={getKfList}
281
  parser_id={parser_id}
282
  doc_id={doc_id}
283
  />
284
+ <RenameModal></RenameModal>
285
+ </div>
286
  );
287
  };
288
 
web/src/pages/add-knowledge/components/knowledge-file/model.ts CHANGED
@@ -1,14 +1,19 @@
 
1
  import kbService from '@/services/kbService';
2
  import { message } from 'antd';
 
3
  import pick from 'lodash/pick';
 
4
  import { DvaModel } from 'umi';
5
 
6
  export interface KFModelState {
7
  isShowCEFwModal: boolean;
8
  isShowTntModal: boolean;
9
  isShowSegmentSetModal: boolean;
 
10
  tenantIfo: any;
11
- data: any[];
 
12
  }
13
 
14
  const model: DvaModel<KFModelState> = {
@@ -17,8 +22,10 @@ const model: DvaModel<KFModelState> = {
17
  isShowCEFwModal: false,
18
  isShowTntModal: false,
19
  isShowSegmentSetModal: false,
 
20
  tenantIfo: {},
21
  data: [],
 
22
  },
23
  reducers: {
24
  updateState(state, { payload }) {
@@ -27,6 +34,12 @@ const model: DvaModel<KFModelState> = {
27
  ...payload,
28
  };
29
  },
 
 
 
 
 
 
30
  },
31
  subscriptions: {
32
  setup({ dispatch, history }) {
@@ -99,6 +112,26 @@ const model: DvaModel<KFModelState> = {
99
  });
100
  }
101
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  *document_create({ payload = {} }, { call, put }) {
103
  const { data, response } = yield call(kbService.document_create, payload);
104
  const { retcode, data: res, retmsg } = data;
 
1
+ import { IKnowledgeFile } from '@/interfaces/database/knowledge';
2
  import kbService from '@/services/kbService';
3
  import { message } from 'antd';
4
+ import omit from 'lodash/omit';
5
  import pick from 'lodash/pick';
6
+ import { Nullable } from 'typings';
7
  import { DvaModel } from 'umi';
8
 
9
  export interface KFModelState {
10
  isShowCEFwModal: boolean;
11
  isShowTntModal: boolean;
12
  isShowSegmentSetModal: boolean;
13
+ isShowRenameModal: boolean;
14
  tenantIfo: any;
15
+ data: IKnowledgeFile[];
16
+ currentRecord: Nullable<IKnowledgeFile>;
17
  }
18
 
19
  const model: DvaModel<KFModelState> = {
 
22
  isShowCEFwModal: false,
23
  isShowTntModal: false,
24
  isShowSegmentSetModal: false,
25
+ isShowRenameModal: false,
26
  tenantIfo: {},
27
  data: [],
28
+ currentRecord: null,
29
  },
30
  reducers: {
31
  updateState(state, { payload }) {
 
34
  ...payload,
35
  };
36
  },
37
+ setIsShowRenameModal(state, { payload }) {
38
+ return { ...state, isShowRenameModal: payload };
39
+ },
40
+ setCurrentRecord(state, { payload }) {
41
+ return { ...state, currentRecord: payload };
42
+ },
43
  },
44
  subscriptions: {
45
  setup({ dispatch, history }) {
 
112
  });
113
  }
114
  },
115
+ *document_rename({ payload = {} }, { call, put }) {
116
+ const { data } = yield call(
117
+ kbService.document_rename,
118
+ omit(payload, ['kb_id']),
119
+ );
120
+ const { retcode, data: res, retmsg } = data;
121
+ if (retcode === 0) {
122
+ message.success('rename success!');
123
+ yield put({
124
+ type: 'setIsShowRenameModal',
125
+ payload: false,
126
+ });
127
+ yield put({
128
+ type: 'getKfList',
129
+ payload: { kb_id: payload.kb_id },
130
+ });
131
+ }
132
+
133
+ return retcode;
134
+ },
135
  *document_create({ payload = {} }, { call, put }) {
136
  const { data, response } = yield call(kbService.document_create, payload);
137
  const { retcode, data: res, retmsg } = data;
web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import showDeleteConfirm from '@/components/deleting-confirm';
2
+ import { IKnowledgeFile } from '@/interfaces/database/knowledge';
3
+ import { DeleteOutlined, EditOutlined, ToolOutlined } from '@ant-design/icons';
4
+ import { Button, Dropdown, MenuProps, Space, Tooltip } from 'antd';
5
+ import { useDispatch } from 'umi';
6
+
7
+ interface IProps {
8
+ documentId: string;
9
+ knowledgeBaseId: string;
10
+ record: IKnowledgeFile;
11
+ setDocumentAndParserId: () => void;
12
+ }
13
+
14
+ const ParsingActionCell = ({
15
+ documentId,
16
+ knowledgeBaseId,
17
+ record,
18
+ setDocumentAndParserId,
19
+ }: IProps) => {
20
+ const dispatch = useDispatch();
21
+
22
+ const removeDocument = () => {
23
+ dispatch({
24
+ type: 'kFModel/document_rm',
25
+ payload: {
26
+ doc_id: documentId,
27
+ kb_id: knowledgeBaseId,
28
+ },
29
+ });
30
+ };
31
+
32
+ const onRmDocument = () => {
33
+ showDeleteConfirm({ onOk: removeDocument });
34
+ };
35
+
36
+ const setCurrentRecord = () => {
37
+ dispatch({
38
+ type: 'kFModel/setCurrentRecord',
39
+ payload: record,
40
+ });
41
+ };
42
+
43
+ const showSegmentSetModal = () => {
44
+ dispatch({
45
+ type: 'kFModel/updateState',
46
+ payload: {
47
+ isShowSegmentSetModal: true,
48
+ },
49
+ });
50
+ };
51
+
52
+ const showRenameModal = () => {
53
+ setCurrentRecord();
54
+ dispatch({
55
+ type: 'kFModel/setIsShowRenameModal',
56
+ payload: true,
57
+ });
58
+ };
59
+
60
+ const onRename = () => {};
61
+
62
+ const chunkItems: MenuProps['items'] = [
63
+ {
64
+ key: '1',
65
+ label: (
66
+ <div>
67
+ <Button type="link" onClick={showSegmentSetModal}>
68
+ 分段设置
69
+ </Button>
70
+ </div>
71
+ ),
72
+ },
73
+ ];
74
+
75
+ return (
76
+ <Space size={'middle'}>
77
+ <Dropdown menu={{ items: chunkItems }} trigger={['click']}>
78
+ <ToolOutlined size={20} onClick={setDocumentAndParserId} />
79
+ </Dropdown>
80
+ <Tooltip title="Rename">
81
+ <EditOutlined size={20} onClick={showRenameModal} />
82
+ </Tooltip>
83
+ <DeleteOutlined size={20} onClick={onRmDocument} />
84
+ </Space>
85
+ );
86
+ };
87
+
88
+ export default ParsingActionCell;
web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .popover-content {
2
+ width: 300px;
3
+ }
web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { IKnowledgeFile } from '@/interfaces/database/knowledge';
2
+ import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd';
3
+ import { RunningStatus, RunningStatusMap } from '../constant';
4
+
5
+ import styles from './index.less';
6
+
7
+ interface IProps {
8
+ record: IKnowledgeFile;
9
+ }
10
+
11
+ const PopoverContent = ({ record }: IProps) => {
12
+ const items: DescriptionsProps['items'] = [
13
+ {
14
+ key: 'process_begin_at',
15
+ label: 'Process Begin At',
16
+ children: record.process_begin_at,
17
+ },
18
+ {
19
+ key: 'process_duation',
20
+ label: 'Process Duration',
21
+ children: record.process_duation,
22
+ },
23
+ {
24
+ key: 'progress_msg',
25
+ label: 'Progress Msg',
26
+ children: record.progress_msg,
27
+ },
28
+ ];
29
+
30
+ return (
31
+ <Flex vertical className={styles['popover-content']}>
32
+ {items.map((x) => {
33
+ return (
34
+ <div>
35
+ <b>{x.label}:</b>
36
+ <p>{x.children}</p>
37
+ </div>
38
+ );
39
+ })}
40
+ </Flex>
41
+ );
42
+ };
43
+
44
+ export const ParsingStatusCell = ({ record }: IProps) => {
45
+ const text = record.run;
46
+ const runningStatus = RunningStatusMap[text];
47
+
48
+ const isRunning = text === RunningStatus.RUNNING;
49
+
50
+ return (
51
+ <Popover
52
+ content={isRunning && <PopoverContent record={record}></PopoverContent>}
53
+ >
54
+ <Tag color={runningStatus.color}>
55
+ {isRunning ? (
56
+ <Space>
57
+ <Badge color={runningStatus.color} />
58
+ `${runningStatus.label}${record.progress * 100}%`
59
+ </Space>
60
+ ) : (
61
+ runningStatus.label
62
+ )}
63
+ </Tag>
64
+ </Popover>
65
+ );
66
+ };
67
+
68
+ export default ParsingStatusCell;
web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
2
+ import { Form, Input, Modal } from 'antd';
3
+ import { useEffect } from 'react';
4
+ import { useDispatch, useSelector } from 'umi';
5
+
6
+ const RenameModal = () => {
7
+ const [form] = Form.useForm();
8
+ const dispatch = useDispatch();
9
+ const kFModel = useSelector((state: any) => state.kFModel);
10
+ const loading = useSelector(
11
+ (state: any) => state.loading.effects['kFModel/document_rename'],
12
+ );
13
+ const knowledgeBaseId = useKnowledgeBaseId();
14
+ const isModalOpen = kFModel.isShowRenameModal;
15
+ const initialName = kFModel.currentRecord?.name;
16
+ const documentId = kFModel.currentRecord?.id;
17
+
18
+ type FieldType = {
19
+ name?: string;
20
+ };
21
+
22
+ const closeModal = () => {
23
+ dispatch({
24
+ type: 'kFModel/setIsShowRenameModal',
25
+ payload: false,
26
+ });
27
+ };
28
+
29
+ const handleOk = async () => {
30
+ const ret = await form.validateFields();
31
+
32
+ dispatch({
33
+ type: 'kFModel/document_rename',
34
+ payload: {
35
+ doc_id: documentId,
36
+ name: ret.name,
37
+ kb_id: knowledgeBaseId,
38
+ },
39
+ });
40
+ };
41
+
42
+ const handleCancel = () => {
43
+ closeModal();
44
+ };
45
+
46
+ const onFinish = (values: any) => {
47
+ console.log('Success:', values);
48
+ };
49
+
50
+ const onFinishFailed = (errorInfo: any) => {
51
+ console.log('Failed:', errorInfo);
52
+ };
53
+
54
+ useEffect(() => {
55
+ form.setFieldValue('name', initialName);
56
+ }, [initialName, documentId]);
57
+
58
+ return (
59
+ <Modal
60
+ title="Rename"
61
+ open={isModalOpen}
62
+ onOk={handleOk}
63
+ onCancel={handleCancel}
64
+ okButtonProps={{ loading }}
65
+ >
66
+ <Form
67
+ name="basic"
68
+ labelCol={{ span: 4 }}
69
+ wrapperCol={{ span: 20 }}
70
+ style={{ maxWidth: 600 }}
71
+ onFinish={onFinish}
72
+ onFinishFailed={onFinishFailed}
73
+ autoComplete="off"
74
+ form={form}
75
+ >
76
+ <Form.Item<FieldType>
77
+ label="Name"
78
+ name="name"
79
+ rules={[{ required: true, message: 'Please input name!' }]}
80
+ >
81
+ <Input />
82
+ </Form.Item>
83
+ </Form>
84
+ </Modal>
85
+ );
86
+ };
87
+
88
+ export default RenameModal;
web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx CHANGED
@@ -41,7 +41,6 @@ const SegmentSetModal: React.FC<kFProps> = ({
41
  };
42
 
43
  const handleOk = async () => {
44
- console.log(1111, selectedTag);
45
  const retcode = await dispatch<any>({
46
  type: 'kFModel/document_change_parser',
47
  payload: {
 
41
  };
42
 
43
  const handleOk = async () => {
 
44
  const retcode = await dispatch<any>({
45
  type: 'kFModel/document_change_parser',
46
  payload: {
web/src/pages/add-knowledge/components/knowledge-search/index.tsx CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import { api_host } from '@/utils/api';
2
  import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons';
3
  import type { PaginationProps } from 'antd';
@@ -12,18 +14,14 @@ import {
12
  Spin,
13
  Switch,
14
  } from 'antd';
 
15
  import React, { useCallback, useEffect } from 'react';
16
  import { useDispatch, useSelector } from 'umi';
17
  import CreateModal from '../knowledge-chunk/components/createModal';
18
 
19
- import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
20
- import { debounce } from 'lodash';
21
  import styles from './index.less';
22
- interface chunkProps {
23
- kb_id: string;
24
- }
25
 
26
- const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
27
  const dispatch = useDispatch();
28
  const kSearchModel = useSelector((state: any) => state.kSearchModel);
29
  const chunkModel = useSelector((state: any) => state.chunkModel);
@@ -31,6 +29,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
31
  'chunk_list',
32
  'switch_chunk',
33
  ]);
 
34
 
35
  const {
36
  data = [],
@@ -46,7 +45,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
46
  dispatch({
47
  type: 'kSearchModel/chunk_list',
48
  payload: {
49
- kb_id,
50
  },
51
  });
52
  };
@@ -55,7 +54,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
55
  type: 'kSearchModel/rm_chunk',
56
  payload: {
57
  chunk_ids: [id],
58
- kb_id,
59
  },
60
  });
61
  };
@@ -93,7 +92,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
93
  dispatch({
94
  type: 'kSearchModel/getKfList',
95
  payload: {
96
- kb_id,
97
  },
98
  });
99
  }, []);
@@ -106,7 +105,7 @@ const KnowledgeSearching: React.FC<chunkProps> = ({ kb_id }) => {
106
  chunk_ids: [chunk_id],
107
  doc_id,
108
  available_int,
109
- kb_id,
110
  },
111
  });
112
  };
 
1
+ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
2
+ import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
3
  import { api_host } from '@/utils/api';
4
  import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons';
5
  import type { PaginationProps } from 'antd';
 
14
  Spin,
15
  Switch,
16
  } from 'antd';
17
+ import { debounce } from 'lodash';
18
  import React, { useCallback, useEffect } from 'react';
19
  import { useDispatch, useSelector } from 'umi';
20
  import CreateModal from '../knowledge-chunk/components/createModal';
21
 
 
 
22
  import styles from './index.less';
 
 
 
23
 
24
+ const KnowledgeSearching = () => {
25
  const dispatch = useDispatch();
26
  const kSearchModel = useSelector((state: any) => state.kSearchModel);
27
  const chunkModel = useSelector((state: any) => state.chunkModel);
 
29
  'chunk_list',
30
  'switch_chunk',
31
  ]);
32
+ const knowledgeBaseId = useKnowledgeBaseId();
33
 
34
  const {
35
  data = [],
 
45
  dispatch({
46
  type: 'kSearchModel/chunk_list',
47
  payload: {
48
+ kb_id: knowledgeBaseId,
49
  },
50
  });
51
  };
 
54
  type: 'kSearchModel/rm_chunk',
55
  payload: {
56
  chunk_ids: [id],
57
+ kb_id: knowledgeBaseId,
58
  },
59
  });
60
  };
 
92
  dispatch({
93
  type: 'kSearchModel/getKfList',
94
  payload: {
95
+ kb_id: knowledgeBaseId,
96
  },
97
  });
98
  }, []);
 
105
  chunk_ids: [chunk_id],
106
  doc_id,
107
  available_int,
108
+ kb_id: knowledgeBaseId,
109
  },
110
  });
111
  };
web/src/pages/add-knowledge/components/knowledge-setting/index.tsx CHANGED
@@ -1,6 +1,7 @@
1
  import { KnowledgeRouteKey } from '@/constants/knowledge';
 
2
  import { Button, Form, Input, Radio, Select, Space, Tag } from 'antd';
3
- import React, { useCallback, useEffect, useState } from 'react';
4
  import { useDispatch, useNavigate, useSelector } from 'umi';
5
  import styles from './index.less';
6
 
@@ -13,10 +14,7 @@ const layout = {
13
  const { Option } = Select;
14
  /* eslint-disable no-template-curly-in-string */
15
 
16
- interface kSProps {
17
- kb_id: string;
18
- }
19
- const KnowledgeSetting: React.FC<kSProps> = ({ kb_id }) => {
20
  const dispatch = useDispatch();
21
  const settingModel = useSelector((state: any) => state.settingModel);
22
  let navigate = useNavigate();
@@ -25,17 +23,18 @@ const KnowledgeSetting: React.FC<kSProps> = ({ kb_id }) => {
25
  const [form] = Form.useForm();
26
  const [selectedTag, setSelectedTag] = useState('');
27
  const values = Form.useWatch([], form);
 
28
 
29
  const getTenantInfo = useCallback(async () => {
30
  dispatch({
31
  type: 'settingModel/getTenantInfo',
32
  payload: {},
33
  });
34
- if (kb_id) {
35
  const data = await dispatch<any>({
36
  type: 'kSModel/getKbDetail',
37
  payload: {
38
- kb_id,
39
  },
40
  });
41
  if (data.retcode === 0) {
@@ -44,19 +43,19 @@ const KnowledgeSetting: React.FC<kSProps> = ({ kb_id }) => {
44
  setSelectedTag(data.data.parser_id);
45
  }
46
  }
47
- }, [kb_id]);
48
 
49
  const onFinish = async () => {
50
  try {
51
  await form.validateFields();
52
 
53
- if (kb_id) {
54
  dispatch({
55
  type: 'kSModel/updateKb',
56
  payload: {
57
  ...values,
58
  parser_id: selectedTag,
59
- kb_id,
60
  embd_id: undefined,
61
  },
62
  });
@@ -69,7 +68,9 @@ const KnowledgeSetting: React.FC<kSProps> = ({ kb_id }) => {
69
  },
70
  });
71
  retcode === 0 &&
72
- navigate(`/knowledge/${KnowledgeRouteKey.Dataset}?id=${kb_id}`);
 
 
73
  }
74
  } catch (error) {
75
  console.warn(error);
 
1
  import { KnowledgeRouteKey } from '@/constants/knowledge';
2
+ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
3
  import { Button, Form, Input, Radio, Select, Space, Tag } from 'antd';
4
+ import { useCallback, useEffect, useState } from 'react';
5
  import { useDispatch, useNavigate, useSelector } from 'umi';
6
  import styles from './index.less';
7
 
 
14
  const { Option } = Select;
15
  /* eslint-disable no-template-curly-in-string */
16
 
17
+ const KnowledgeSetting = () => {
 
 
 
18
  const dispatch = useDispatch();
19
  const settingModel = useSelector((state: any) => state.settingModel);
20
  let navigate = useNavigate();
 
23
  const [form] = Form.useForm();
24
  const [selectedTag, setSelectedTag] = useState('');
25
  const values = Form.useWatch([], form);
26
+ const knowledgeBaseId = useKnowledgeBaseId();
27
 
28
  const getTenantInfo = useCallback(async () => {
29
  dispatch({
30
  type: 'settingModel/getTenantInfo',
31
  payload: {},
32
  });
33
+ if (knowledgeBaseId) {
34
  const data = await dispatch<any>({
35
  type: 'kSModel/getKbDetail',
36
  payload: {
37
+ kb_id: knowledgeBaseId,
38
  },
39
  });
40
  if (data.retcode === 0) {
 
43
  setSelectedTag(data.data.parser_id);
44
  }
45
  }
46
+ }, [knowledgeBaseId]);
47
 
48
  const onFinish = async () => {
49
  try {
50
  await form.validateFields();
51
 
52
+ if (knowledgeBaseId) {
53
  dispatch({
54
  type: 'kSModel/updateKb',
55
  payload: {
56
  ...values,
57
  parser_id: selectedTag,
58
+ kb_id: knowledgeBaseId,
59
  embd_id: undefined,
60
  },
61
  });
 
68
  },
69
  });
70
  retcode === 0 &&
71
+ navigate(
72
+ `/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`,
73
+ );
74
  }
75
  } catch (error) {
76
  console.warn(error);
web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx CHANGED
@@ -1,12 +1,13 @@
1
  import { ReactComponent as ConfigrationIcon } from '@/assets/svg/knowledge-configration.svg';
2
  import { ReactComponent as DatasetIcon } from '@/assets/svg/knowledge-dataset.svg';
3
  import { ReactComponent as TestingIcon } from '@/assets/svg/knowledge-testing.svg';
 
4
  import { getWidth } from '@/utils';
5
  import { AntDesignOutlined } from '@ant-design/icons';
6
  import { Avatar, Menu, MenuProps, Space } from 'antd';
7
  import classNames from 'classnames';
8
  import { useEffect, useMemo, useState } from 'react';
9
- import { useNavigate, useParams, useSelector } from 'umi';
10
  import { KnowledgeRouteKey, routeMap } from '../../constant';
11
  import styles from './index.less';
12
 
@@ -14,8 +15,7 @@ const KnowledgeSidebar = () => {
14
  const kAModel = useSelector((state: any) => state.kAModel);
15
  const { id } = kAModel;
16
  let navigate = useNavigate();
17
- const params = useParams();
18
- const activeKey = params.module || KnowledgeRouteKey.Dataset;
19
 
20
  const [windowWidth, setWindowWidth] = useState(getWidth());
21
  const [collapsed, setCollapsed] = useState(false);
@@ -56,8 +56,8 @@ const KnowledgeSidebar = () => {
56
  <TestingIcon />,
57
  ),
58
  getItem(
59
- routeMap[KnowledgeRouteKey.Configration],
60
- KnowledgeRouteKey.Configration,
61
  <ConfigrationIcon />,
62
  ),
63
  ];
 
1
  import { ReactComponent as ConfigrationIcon } from '@/assets/svg/knowledge-configration.svg';
2
  import { ReactComponent as DatasetIcon } from '@/assets/svg/knowledge-dataset.svg';
3
  import { ReactComponent as TestingIcon } from '@/assets/svg/knowledge-testing.svg';
4
+ import { useSecondPathName } from '@/hooks/routeHook';
5
  import { getWidth } from '@/utils';
6
  import { AntDesignOutlined } from '@ant-design/icons';
7
  import { Avatar, Menu, MenuProps, Space } from 'antd';
8
  import classNames from 'classnames';
9
  import { useEffect, useMemo, useState } from 'react';
10
+ import { useNavigate, useSelector } from 'umi';
11
  import { KnowledgeRouteKey, routeMap } from '../../constant';
12
  import styles from './index.less';
13
 
 
15
  const kAModel = useSelector((state: any) => state.kAModel);
16
  const { id } = kAModel;
17
  let navigate = useNavigate();
18
+ const activeKey = useSecondPathName();
 
19
 
20
  const [windowWidth, setWindowWidth] = useState(getWidth());
21
  const [collapsed, setCollapsed] = useState(false);
 
56
  <TestingIcon />,
57
  ),
58
  getItem(
59
+ routeMap[KnowledgeRouteKey.Configuration],
60
+ KnowledgeRouteKey.Configuration,
61
  <ConfigrationIcon />,
62
  ),
63
  ];
web/src/pages/add-knowledge/constant.ts CHANGED
@@ -3,7 +3,17 @@ import { KnowledgeRouteKey } from '@/constants/knowledge';
3
  export const routeMap = {
4
  [KnowledgeRouteKey.Dataset]: 'Dataset',
5
  [KnowledgeRouteKey.Testing]: 'Retrieval testing',
6
- [KnowledgeRouteKey.Configration]: 'Configuration',
 
 
 
 
 
 
 
 
 
 
7
  };
8
 
9
  export * from '@/constants/knowledge';
 
3
  export const routeMap = {
4
  [KnowledgeRouteKey.Dataset]: 'Dataset',
5
  [KnowledgeRouteKey.Testing]: 'Retrieval testing',
6
+ [KnowledgeRouteKey.Configuration]: 'Configuration',
7
+ };
8
+
9
+ export enum KnowledgeDatasetRouteKey {
10
+ Chunk = 'chunk',
11
+ File = 'file',
12
+ }
13
+
14
+ export const datasetRouteMap = {
15
+ [KnowledgeDatasetRouteKey.Chunk]: 'Chunk',
16
+ [KnowledgeDatasetRouteKey.File]: 'File Upload',
17
  };
18
 
19
  export * from '@/constants/knowledge';
web/src/pages/add-knowledge/index.less CHANGED
@@ -7,9 +7,12 @@
7
  height: 100%;
8
  background-color: rgba(247, 248, 250, 1);
9
  padding: 16px 20px 28px 40px;
 
 
10
  }
11
  .content {
12
  background-color: white;
13
  margin-top: 16px;
 
14
  }
15
  }
 
7
  height: 100%;
8
  background-color: rgba(247, 248, 250, 1);
9
  padding: 16px 20px 28px 40px;
10
+ display: flex;
11
+ flex-direction: column;
12
  }
13
  .content {
14
  background-color: white;
15
  margin-top: 16px;
16
+ // flex: 1;
17
  }
18
  }
web/src/pages/add-knowledge/index.tsx CHANGED
@@ -1,45 +1,60 @@
 
 
1
  import { Breadcrumb } from 'antd';
 
2
  import { useEffect, useMemo } from 'react';
3
- import {
4
- useDispatch,
5
- useLocation,
6
- useNavigate,
7
- useParams,
8
- useSelector,
9
- } from 'umi';
10
- import Chunk from './components/knowledge-chunk';
11
- import File from './components/knowledge-file';
12
- import Search from './components/knowledge-search';
13
- import Setting from './components/knowledge-setting';
14
  import Siderbar from './components/knowledge-sidebar';
15
- import { KnowledgeRouteKey, routeMap } from './constant';
 
 
 
 
 
16
  import styles from './index.less';
17
 
18
  const KnowledgeAdding = () => {
19
  const dispatch = useDispatch();
20
- const kAModel = useSelector((state: any) => state.kAModel);
21
  const navigate = useNavigate();
22
- const { id, doc_id } = kAModel;
23
 
24
  const location = useLocation();
25
- const params = useParams();
26
  const activeKey: KnowledgeRouteKey =
27
- (params.module as KnowledgeRouteKey) || KnowledgeRouteKey.Dataset;
 
 
 
28
 
29
  const gotoList = () => {
30
  navigate('/knowledge');
31
  };
32
 
33
- const breadcrumbItems = useMemo(() => {
34
- return [
35
  {
36
  title: <a onClick={gotoList}>Knowledge Base</a>,
37
  },
38
  {
39
- title: routeMap[activeKey],
 
 
 
 
 
 
 
 
40
  },
41
  ];
42
- }, [activeKey]);
 
 
 
 
 
 
 
 
43
 
44
  useEffect(() => {
45
  const search: string = location.search.slice(1);
@@ -65,16 +80,7 @@ const KnowledgeAdding = () => {
65
  <div className={styles.contentWrapper}>
66
  <Breadcrumb items={breadcrumbItems} />
67
  <div className={styles.content}>
68
- {activeKey === KnowledgeRouteKey.Dataset && !doc_id && (
69
- <File kb_id={id} />
70
- )}
71
- {activeKey === KnowledgeRouteKey.Configration && (
72
- <Setting kb_id={id} />
73
- )}
74
- {activeKey === KnowledgeRouteKey.Testing && <Search kb_id={id} />}
75
- {activeKey === KnowledgeRouteKey.Dataset && !!doc_id && (
76
- <Chunk doc_id={doc_id} />
77
- )}
78
  </div>
79
  </div>
80
  </div>
 
1
+ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
2
+ import { useSecondPathName, useThirdPathName } from '@/hooks/routeHook';
3
  import { Breadcrumb } from 'antd';
4
+ import { ItemType } from 'antd/es/breadcrumb/Breadcrumb';
5
  import { useEffect, useMemo } from 'react';
6
+ import { Link, Outlet, useDispatch, useLocation, useNavigate } from 'umi';
 
 
 
 
 
 
 
 
 
 
7
  import Siderbar from './components/knowledge-sidebar';
8
+ import {
9
+ KnowledgeDatasetRouteKey,
10
+ KnowledgeRouteKey,
11
+ datasetRouteMap,
12
+ routeMap,
13
+ } from './constant';
14
  import styles from './index.less';
15
 
16
  const KnowledgeAdding = () => {
17
  const dispatch = useDispatch();
 
18
  const navigate = useNavigate();
19
+ const knowledgeBaseId = useKnowledgeBaseId();
20
 
21
  const location = useLocation();
 
22
  const activeKey: KnowledgeRouteKey =
23
+ (useSecondPathName() as KnowledgeRouteKey) || KnowledgeRouteKey.Dataset;
24
+
25
+ const datasetActiveKey: KnowledgeDatasetRouteKey =
26
+ useThirdPathName() as KnowledgeDatasetRouteKey;
27
 
28
  const gotoList = () => {
29
  navigate('/knowledge');
30
  };
31
 
32
+ const breadcrumbItems: ItemType[] = useMemo(() => {
33
+ const items: ItemType[] = [
34
  {
35
  title: <a onClick={gotoList}>Knowledge Base</a>,
36
  },
37
  {
38
+ title: datasetActiveKey ? (
39
+ <Link
40
+ to={`/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`}
41
+ >
42
+ {routeMap[activeKey]}
43
+ </Link>
44
+ ) : (
45
+ routeMap[activeKey]
46
+ ),
47
  },
48
  ];
49
+
50
+ if (datasetActiveKey) {
51
+ items.push({
52
+ title: datasetRouteMap[datasetActiveKey],
53
+ });
54
+ }
55
+
56
+ return items;
57
+ }, [activeKey, datasetActiveKey]);
58
 
59
  useEffect(() => {
60
  const search: string = location.search.slice(1);
 
80
  <div className={styles.contentWrapper}>
81
  <Breadcrumb items={breadcrumbItems} />
82
  <div className={styles.content}>
83
+ <Outlet></Outlet>
 
 
 
 
 
 
 
 
 
84
  </div>
85
  </div>
86
  </div>
web/src/pages/knowledge/index.tsx CHANGED
@@ -1,6 +1,7 @@
1
  import { ReactComponent as FilterIcon } from '@/assets/filter.svg';
 
2
  import { PlusOutlined } from '@ant-design/icons';
3
- import { Button, Col, Row, Space } from 'antd';
4
  import { useCallback, useEffect } from 'react';
5
  import { useDispatch, useNavigate, useSelector } from 'umi';
6
  import styles from './index.less';
@@ -20,7 +21,7 @@ const Knowledge = () => {
20
  }, []);
21
 
22
  const handleAddKnowledge = () => {
23
- navigate(`add/setting`);
24
  };
25
 
26
  useEffect(() => {
@@ -50,7 +51,7 @@ const Knowledge = () => {
50
  </Button>
51
  </Space>
52
  </div>
53
- <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
54
  {data.map((item: any) => {
55
  return (
56
  <Col
@@ -58,14 +59,19 @@ const Knowledge = () => {
58
  key={item.name}
59
  xs={24}
60
  sm={12}
61
- md={8}
62
- lg={6}
63
  >
64
  <KnowledgeCard item={item}></KnowledgeCard>
65
  </Col>
66
  );
67
  })}
68
- </Row>
 
 
 
 
 
69
  </div>
70
  );
71
  };
 
1
  import { ReactComponent as FilterIcon } from '@/assets/filter.svg';
2
+ import { KnowledgeRouteKey } from '@/constants/knowledge';
3
  import { PlusOutlined } from '@ant-design/icons';
4
+ import { Button, Flex, Space } from 'antd';
5
  import { useCallback, useEffect } from 'react';
6
  import { useDispatch, useNavigate, useSelector } from 'umi';
7
  import styles from './index.less';
 
21
  }, []);
22
 
23
  const handleAddKnowledge = () => {
24
+ navigate(`/knowledge/${KnowledgeRouteKey.Configuration}`);
25
  };
26
 
27
  useEffect(() => {
 
51
  </Button>
52
  </Space>
53
  </div>
54
+ {/* <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
55
  {data.map((item: any) => {
56
  return (
57
  <Col
 
59
  key={item.name}
60
  xs={24}
61
  sm={12}
62
+ md={10}
63
+ lg={8}
64
  >
65
  <KnowledgeCard item={item}></KnowledgeCard>
66
  </Col>
67
  );
68
  })}
69
+ </Row> */}
70
+ <Flex gap="large" wrap="wrap">
71
+ {data.map((item: any) => {
72
+ return <KnowledgeCard item={item} key={item.name}></KnowledgeCard>;
73
+ })}
74
+ </Flex>
75
  </div>
76
  );
77
  };
web/src/pages/knowledge/knowledge-card/index.less CHANGED
@@ -26,7 +26,7 @@
26
  border: 1px solid rgba(234, 236, 240, 1);
27
  box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
28
  padding: 24px;
29
- min-width: 300px;
30
  cursor: pointer;
31
 
32
  .titleWrapper {
 
26
  border: 1px solid rgba(234, 236, 240, 1);
27
  box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
28
  padding: 24px;
29
+ max-width: 300px;
30
  cursor: pointer;
31
 
32
  .titleWrapper {
web/src/routes.ts CHANGED
@@ -16,8 +16,37 @@ const routes = [
16
  component: '@/pages/knowledge',
17
  },
18
  {
19
- path: '/knowledge/:module',
20
  component: '@/pages/add-knowledge',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  },
22
  {
23
  path: '/chat',
 
16
  component: '@/pages/knowledge',
17
  },
18
  {
19
+ path: '/knowledge',
20
  component: '@/pages/add-knowledge',
21
+ routes: [
22
+ {
23
+ path: '/knowledge/dataset',
24
+ component: '@/pages/add-knowledge/components/knowledge-dataset',
25
+ routes: [
26
+ {
27
+ path: '/knowledge/dataset',
28
+ component: '@/pages/add-knowledge/components/knowledge-file',
29
+ },
30
+ {
31
+ path: '/knowledge/dataset/upload',
32
+ component:
33
+ '@/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file',
34
+ },
35
+ {
36
+ path: '/knowledge/dataset/chunk',
37
+ component: '@/pages/add-knowledge/components/knowledge-chunk',
38
+ },
39
+ ],
40
+ },
41
+ {
42
+ path: '/knowledge/configuration',
43
+ component: '@/pages/add-knowledge/components/knowledge-setting',
44
+ },
45
+ {
46
+ path: '/knowledge/testing',
47
+ component: '@/pages/add-knowledge/components/knowledge-search',
48
+ },
49
+ ],
50
  },
51
  {
52
  path: '/chat',
web/src/services/kbService.ts CHANGED
@@ -20,6 +20,7 @@ const {
20
  switch_chunk,
21
  rm_chunk,
22
  retrieval_test,
 
23
  } = api;
24
 
25
  const methods = {
@@ -57,6 +58,10 @@ const methods = {
57
  url: document_rm,
58
  method: 'post',
59
  },
 
 
 
 
60
  document_create: {
61
  url: document_create,
62
  method: 'post',
 
20
  switch_chunk,
21
  rm_chunk,
22
  retrieval_test,
23
+ document_rename,
24
  } = api;
25
 
26
  const methods = {
 
58
  url: document_rm,
59
  method: 'post',
60
  },
61
+ document_rename: {
62
+ url: document_rename,
63
+ method: 'post',
64
+ },
65
  document_create: {
66
  url: document_create,
67
  method: 'post',
web/src/utils/api.ts CHANGED
@@ -33,11 +33,12 @@ export default {
33
  rm_chunk: `${api_host}/chunk/rm`,
34
  retrieval_test: `${api_host}/chunk/retrieval_test`,
35
 
36
- // 上传
37
  upload: `${api_host}/document/upload`,
38
  get_document_list: `${api_host}/document/list`,
39
  document_change_status: `${api_host}/document/change_status`,
40
  document_rm: `${api_host}/document/rm`,
 
41
  document_create: `${api_host}/document/create`,
42
  document_change_parser: `${api_host}/document/change_parser`,
43
  };
 
33
  rm_chunk: `${api_host}/chunk/rm`,
34
  retrieval_test: `${api_host}/chunk/retrieval_test`,
35
 
36
+ // 文件管理
37
  upload: `${api_host}/document/upload`,
38
  get_document_list: `${api_host}/document/list`,
39
  document_change_status: `${api_host}/document/change_status`,
40
  document_rm: `${api_host}/document/rm`,
41
+ document_rename: `${api_host}/document/rename`,
42
  document_create: `${api_host}/document/create`,
43
  document_change_parser: `${api_host}/document/change_parser`,
44
  };
web/typings.d.ts CHANGED
@@ -1,2 +1,4 @@
1
  import 'umi/typings';
2
- declare module 'lodash'
 
 
 
1
  import 'umi/typings';
2
+ declare module 'lodash';
3
+
4
+ export type Nullable<T> = T | null;