balibabu commited on
Commit
71b7e06
·
1 Parent(s): adb65d7

feat: select the corresponding parsing method according to the file type and after the document is successfully uploaded, use the ChunkMethodModal to select the parsing method. and remove ChunkMethodModal from knowledge-file (#158)

Browse files

* feat: select the corresponding parsing method according to the file type

* feat: after the document is successfully uploaded, use the ChunkMethodModal to select the parsing method.

* feat: add pdf types to ParserListMap

* feat: remove ChunkMethodModal from knowledge-file

web/src/components/chunk-method-modal/hooks.ts ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import {
2
+ useFetchTenantInfo,
3
+ useSelectParserList,
4
+ } from '@/hooks/userSettingHook';
5
+ import { useEffect, useMemo, useState } from 'react';
6
+
7
+ const ParserListMap = new Map([
8
+ [
9
+ ['pdf'],
10
+ [
11
+ 'naive',
12
+ 'resume',
13
+ 'manual',
14
+ 'paper',
15
+ 'book',
16
+ 'laws',
17
+ 'presentation',
18
+ 'one',
19
+ ],
20
+ ],
21
+ [
22
+ ['doc', 'docx'],
23
+ ['naive', 'resume', 'book', 'laws', 'one'],
24
+ ],
25
+ [
26
+ ['xlsx', 'xls'],
27
+ ['naive', 'qa', 'table', 'one'],
28
+ ],
29
+ [['ppt', 'pptx'], ['presentation']],
30
+ [
31
+ ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tif', 'tiff', 'webp', 'svg', 'ico'],
32
+ ['picture'],
33
+ ],
34
+ [['txt'], ['naive', 'resume', 'book', 'laws', 'one', 'qa', 'table']],
35
+ [['csv'], ['naive', 'resume', 'book', 'laws', 'one', 'qa', 'table']],
36
+ ]);
37
+
38
+ const getParserList = (
39
+ values: string[],
40
+ parserList: Array<{
41
+ value: string;
42
+ label: string;
43
+ }>,
44
+ ) => {
45
+ return parserList.filter((x) => values?.some((y) => y === x.value));
46
+ };
47
+
48
+ export const useFetchParserListOnMount = (
49
+ parserId: string,
50
+ documentExtension: string,
51
+ ) => {
52
+ const [selectedTag, setSelectedTag] = useState('');
53
+ const parserList = useSelectParserList();
54
+
55
+ const nextParserList = useMemo(() => {
56
+ const key = [...ParserListMap.keys()].find((x) =>
57
+ x.some((y) => y === documentExtension),
58
+ );
59
+ if (key) {
60
+ const values = ParserListMap.get(key);
61
+ return getParserList(values ?? [], parserList);
62
+ }
63
+
64
+ return getParserList(
65
+ ['naive', 'resume', 'book', 'laws', 'one', 'qa', 'table'],
66
+ parserList,
67
+ );
68
+ }, [parserList, documentExtension]);
69
+
70
+ useFetchTenantInfo();
71
+
72
+ useEffect(() => {
73
+ setSelectedTag(parserId);
74
+ }, [parserId]);
75
+
76
+ const handleChange = (tag: string, checked: boolean) => {
77
+ const nextSelectedTag = checked ? tag : selectedTag;
78
+ setSelectedTag(nextSelectedTag);
79
+ };
80
+
81
+ return { parserList: nextParserList, handleChange, selectedTag };
82
+ };
web/src/components/chunk-method-modal/index.less ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ .pageInputNumber {
2
+ width: 220px;
3
+ }
4
+
5
+ .questionIcon {
6
+ margin-inline-start: 4px;
7
+ color: rgba(0, 0, 0, 0.45);
8
+ cursor: help;
9
+ writing-mode: horizontal-tb;
10
+ }
web/src/{pages/add-knowledge/components/knowledge-file/chunk-method-modal.tsx → components/chunk-method-modal/index.tsx} RENAMED
@@ -35,7 +35,7 @@ interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> {
35
  showModal?(): void;
36
  parserId: string;
37
  parserConfig: IKnowledgeFileParserConfig;
38
- documentType: string;
39
  }
40
 
41
  const hidePagesChunkMethods = ['qa', 'table', 'picture', 'resume', 'one'];
@@ -45,11 +45,13 @@ const ChunkMethodModal: React.FC<IProps> = ({
45
  onOk,
46
  hideModal,
47
  visible,
48
- documentType,
49
  parserConfig,
50
  }) => {
51
- const { parserList, handleChange, selectedTag } =
52
- useFetchParserListOnMount(parserId);
 
 
53
  const [form] = Form.useForm();
54
 
55
  const handleOk = async () => {
@@ -62,11 +64,8 @@ const ChunkMethodModal: React.FC<IProps> = ({
62
  };
63
 
64
  const showPages = useMemo(() => {
65
- return (
66
- documentType === 'pdf' &&
67
- hidePagesChunkMethods.every((x) => x !== selectedTag)
68
- );
69
- }, [documentType, selectedTag]);
70
 
71
  const showOne = useMemo(() => {
72
  return showPages || selectedTag === 'one';
@@ -114,7 +113,7 @@ const ChunkMethodModal: React.FC<IProps> = ({
114
  </Space>
115
  <Divider></Divider>
116
 
117
- {
118
  <Form name="dynamic_form_nest_item" autoComplete="off" form={form}>
119
  {showPages && (
120
  <>
@@ -271,7 +270,7 @@ const ChunkMethodModal: React.FC<IProps> = ({
271
 
272
  {selectedTag === 'naive' && <MaxTokenNumber></MaxTokenNumber>}
273
  </Form>
274
- }
275
  </Modal>
276
  );
277
  };
 
35
  showModal?(): void;
36
  parserId: string;
37
  parserConfig: IKnowledgeFileParserConfig;
38
+ documentExtension: string;
39
  }
40
 
41
  const hidePagesChunkMethods = ['qa', 'table', 'picture', 'resume', 'one'];
 
45
  onOk,
46
  hideModal,
47
  visible,
48
+ documentExtension,
49
  parserConfig,
50
  }) => {
51
+ const { parserList, handleChange, selectedTag } = useFetchParserListOnMount(
52
+ parserId,
53
+ documentExtension,
54
+ );
55
  const [form] = Form.useForm();
56
 
57
  const handleOk = async () => {
 
64
  };
65
 
66
  const showPages = useMemo(() => {
67
+ return hidePagesChunkMethods.every((x) => x !== selectedTag);
68
+ }, [selectedTag]);
 
 
 
69
 
70
  const showOne = useMemo(() => {
71
  return showPages || selectedTag === 'one';
 
113
  </Space>
114
  <Divider></Divider>
115
 
116
+ {documentExtension === 'pdf' && (
117
  <Form name="dynamic_form_nest_item" autoComplete="off" form={form}>
118
  {showPages && (
119
  <>
 
270
 
271
  {selectedTag === 'naive' && <MaxTokenNumber></MaxTokenNumber>}
272
  </Form>
273
+ )}
274
  </Modal>
275
  );
276
  };
web/src/hooks/documentHooks.ts CHANGED
@@ -2,6 +2,7 @@ import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
2
  import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
3
  import { api_host } from '@/utils/api';
4
  import { buildChunkHighlights } from '@/utils/documentUtils';
 
5
  import { useCallback, useMemo, useState } from 'react';
6
  import { IHighlight } from 'react-pdf-highlighter';
7
  import { useDispatch, useSelector } from 'umi';
@@ -174,3 +175,47 @@ export const useRemoveDocument = (documentId: string) => {
174
 
175
  return removeDocument;
176
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
3
  import { api_host } from '@/utils/api';
4
  import { buildChunkHighlights } from '@/utils/documentUtils';
5
+ import { UploadFile } from 'antd';
6
  import { useCallback, useMemo, useState } from 'react';
7
  import { IHighlight } from 'react-pdf-highlighter';
8
  import { useDispatch, useSelector } from 'umi';
 
175
 
176
  return removeDocument;
177
  };
178
+
179
+ export const useUploadDocument = () => {
180
+ const dispatch = useDispatch();
181
+ const { knowledgeId } = useGetKnowledgeSearchParams();
182
+
183
+ const uploadDocument = useCallback(
184
+ (file: UploadFile) => {
185
+ try {
186
+ return dispatch<any>({
187
+ type: 'kFModel/upload_document',
188
+ payload: {
189
+ file,
190
+ kb_id: knowledgeId,
191
+ },
192
+ });
193
+ } catch (errorInfo) {
194
+ console.log('Failed:', errorInfo);
195
+ }
196
+ },
197
+ [dispatch, knowledgeId],
198
+ );
199
+
200
+ return uploadDocument;
201
+ };
202
+
203
+ export const useRunDocument = () => {
204
+ const dispatch = useDispatch();
205
+
206
+ const runDocumentByIds = useCallback(
207
+ (ids: string[]) => {
208
+ try {
209
+ return dispatch<any>({
210
+ type: 'kFModel/document_run',
211
+ payload: { doc_ids: ids, run: 1 },
212
+ });
213
+ } catch (errorInfo) {
214
+ console.log('Failed:', errorInfo);
215
+ }
216
+ },
217
+ [dispatch],
218
+ );
219
+
220
+ return runDocumentByIds;
221
+ };
web/src/hooks/logicHooks.ts ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { IKnowledgeFile } from '@/interfaces/database/knowledge';
2
+ import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
3
+ import { useCallback, useState } from 'react';
4
+ import { useSetModalState } from './commonHooks';
5
+ import { useSetDocumentParser } from './documentHooks';
6
+ import { useOneNamespaceEffectsLoading } from './storeHooks';
7
+
8
+ export const useChangeDocumentParser = (documentId: string) => {
9
+ const setDocumentParser = useSetDocumentParser();
10
+
11
+ const {
12
+ visible: changeParserVisible,
13
+ hideModal: hideChangeParserModal,
14
+ showModal: showChangeParserModal,
15
+ } = useSetModalState();
16
+ const loading = useOneNamespaceEffectsLoading('kFModel', [
17
+ 'document_change_parser',
18
+ ]);
19
+
20
+ const onChangeParserOk = useCallback(
21
+ async (parserId: string, parserConfig: IChangeParserConfigRequestBody) => {
22
+ const ret = await setDocumentParser(parserId, documentId, parserConfig);
23
+ if (ret === 0) {
24
+ hideChangeParserModal();
25
+ }
26
+ },
27
+ [hideChangeParserModal, setDocumentParser, documentId],
28
+ );
29
+
30
+ return {
31
+ changeParserLoading: loading,
32
+ onChangeParserOk,
33
+ changeParserVisible,
34
+ hideChangeParserModal,
35
+ showChangeParserModal,
36
+ };
37
+ };
38
+
39
+ export const useSetSelectedRecord = <T = IKnowledgeFile>() => {
40
+ const [currentRecord, setCurrentRecord] = useState<T>({} as T);
41
+
42
+ const setRecord = (record: T) => {
43
+ setCurrentRecord(record);
44
+ };
45
+
46
+ return { currentRecord, setRecord };
47
+ };
web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx CHANGED
@@ -1,18 +1,24 @@
1
  import { ReactComponent as SelectFilesEndIcon } from '@/assets/svg/select-files-end.svg';
2
  import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg';
 
3
  import { KnowledgeRouteKey } from '@/constants/knowledge';
 
 
 
 
 
4
  import {
5
  useDeleteDocumentById,
6
  useFetchKnowledgeDetail,
7
- useGetDocumentDefaultParser,
8
  useKnowledgeBaseId,
9
  } from '@/hooks/knowledgeHook';
10
  import {
11
- useFetchTenantInfo,
12
- useSelectParserList,
13
- } from '@/hooks/userSettingHook';
14
- import uploadService from '@/services/uploadService';
15
- import { isFileUploadDone } from '@/utils/documentUtils';
 
16
  import {
17
  ArrowLeftOutlined,
18
  CloudUploadOutlined,
@@ -24,27 +30,16 @@ import {
24
  Button,
25
  Card,
26
  Flex,
27
- Popover,
28
  Progress,
29
- Radio,
30
- RadioChangeEvent,
31
  Space,
32
  Upload,
33
  UploadFile,
34
  UploadProps,
35
  } from 'antd';
36
  import classNames from 'classnames';
37
- import {
38
- ReactElement,
39
- useCallback,
40
- useEffect,
41
- useMemo,
42
- useRef,
43
- useState,
44
- } from 'react';
45
- import { Link, useDispatch, useNavigate } from 'umi';
46
 
47
- import { useSetDocumentParser } from '@/hooks/documentHooks';
48
  import styles from './index.less';
49
 
50
  const { Dragger } = Upload;
@@ -57,48 +52,21 @@ const UploaderItem = ({
57
  file,
58
  isUpload,
59
  remove,
 
60
  }: {
61
  isUpload: boolean;
62
  originNode: ReactElement;
63
  file: UploadFile;
64
  fileList: object[];
 
65
  remove: (id: string) => void;
 
 
66
  }) => {
67
- const { parserConfig, defaultParserId } = useGetDocumentDefaultParser();
68
  const { removeDocument } = useDeleteDocumentById();
69
- const [value, setValue] = useState(defaultParserId);
70
- const setDocumentParser = useSetDocumentParser();
71
 
72
  const documentId = file?.response?.id;
73
 
74
- const parserList = useSelectParserList();
75
-
76
- const saveParser = (parserId: string) => {
77
- setDocumentParser(parserId, documentId, parserConfig as any);
78
- };
79
-
80
- const onChange = (e: RadioChangeEvent) => {
81
- const val = e.target.value;
82
- setValue(val);
83
- saveParser(val);
84
- };
85
-
86
- const content = (
87
- <Radio.Group onChange={onChange} value={value}>
88
- <Space direction="vertical">
89
- {parserList.map(
90
- (
91
- x, // value is lowercase, key is uppercase
92
- ) => (
93
- <Radio value={x.value} key={x.value}>
94
- {x.label}
95
- </Radio>
96
- ),
97
- )}
98
- </Space>
99
- </Radio.Group>
100
- );
101
-
102
  const handleRemove = async () => {
103
  if (file.status === 'error') {
104
  remove(documentId);
@@ -110,9 +78,11 @@ const UploaderItem = ({
110
  }
111
  };
112
 
113
- useEffect(() => {
114
- setValue(defaultParserId);
115
- }, [defaultParserId]);
 
 
116
 
117
  return (
118
  <Card className={styles.uploaderItem}>
@@ -130,9 +100,7 @@ const UploaderItem = ({
130
  onClick={handleRemove}
131
  />
132
  ) : (
133
- <Popover content={content} placement="bottom">
134
- <EditOutlined />
135
- </Popover>
136
  )}
137
  </Flex>
138
  <Flex>
@@ -153,10 +121,20 @@ const UploaderItem = ({
153
  const KnowledgeUploadFile = () => {
154
  const knowledgeBaseId = useKnowledgeBaseId();
155
  const [isUpload, setIsUpload] = useState(true);
156
- const dispatch = useDispatch();
157
  const [uploadedFileIds, setUploadedFileIds] = useState<string[]>([]);
158
  const fileListRef = useRef<UploadFile[]>([]);
159
  const navigate = useNavigate();
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  const enabled = useMemo(() => {
162
  if (isUpload) {
@@ -175,8 +153,7 @@ const KnowledgeUploadFile = () => {
175
  onError,
176
  // onProgress,
177
  }) {
178
- const ret = await uploadService.uploadFile(file, knowledgeBaseId);
179
- const data = ret?.data;
180
  if (data?.retcode === 0) {
181
  setUploadedFileIds((pre) => {
182
  return pre.concat(data.data.id);
@@ -197,6 +174,17 @@ const KnowledgeUploadFile = () => {
197
  });
198
  }, []);
199
 
 
 
 
 
 
 
 
 
 
 
 
200
  const props: UploadProps = {
201
  name: 'file',
202
  multiple: true,
@@ -215,6 +203,9 @@ const KnowledgeUploadFile = () => {
215
  fileList={fileList}
216
  originNode={originNode}
217
  remove={remove}
 
 
 
218
  ></UploaderItem>
219
  );
220
  },
@@ -226,10 +217,7 @@ const KnowledgeUploadFile = () => {
226
 
227
  const runSelectedDocument = () => {
228
  const ids = fileListRef.current.map((x) => x.response.id);
229
- dispatch({
230
- type: 'kFModel/document_run',
231
- payload: { doc_ids: ids, run: 1 },
232
- });
233
  };
234
 
235
  const handleNextClick = () => {
@@ -245,67 +233,78 @@ const KnowledgeUploadFile = () => {
245
  useFetchKnowledgeDetail();
246
 
247
  return (
248
- <div className={styles.uploadWrapper}>
249
- <section>
250
- <Space className={styles.backToList}>
251
- <ArrowLeftOutlined />
252
- <Link to={`/knowledge/dataset?id=${knowledgeBaseId}`}>
253
- Back to select files
254
- </Link>
255
- </Space>
256
- <div className={styles.progressWrapper}>
257
- <Flex align="center" justify="center">
258
- <SelectFilesStartIcon></SelectFilesStartIcon>
259
- <Progress
260
- percent={100}
261
- showInfo={false}
262
- className={styles.progress}
263
- strokeColor="
264
- rgba(127, 86, 217, 1)
265
- "
266
- />
267
- <SelectFilesEndIcon></SelectFilesEndIcon>
268
- </Flex>
269
- <Flex justify="space-around">
270
- <p className={styles.selectFilesText}>
271
- <b>Select files</b>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  </p>
273
- <p className={styles.changeSpecificCategoryText}>
274
- <b>Change specific category</b>
 
275
  </p>
276
- </Flex>
277
- </div>
278
- </section>
279
- <section className={styles.uploadContent}>
280
- <Dragger
281
- {...props}
282
- className={classNames(styles.uploader, {
283
- [styles.hiddenUploader]: !isUpload,
284
- })}
285
- >
286
- <Button className={styles.uploaderButton}>
287
- <CloudUploadOutlined className={styles.uploaderIcon} />
288
  </Button>
289
- <p className="ant-upload-text">
290
- Click or drag file to this area to upload
291
- </p>
292
- <p className="ant-upload-hint">
293
- Support for a single or bulk upload. Strictly prohibited from
294
- uploading company data or other banned files.
295
- </p>
296
- </Dragger>
297
- </section>
298
- <section className={styles.footer}>
299
- <Button
300
- type="primary"
301
- // className={styles.nextButton}
302
- onClick={handleNextClick}
303
- disabled={!enabled}
304
- >
305
- Next
306
- </Button>
307
- </section>
308
- </div>
309
  );
310
  };
311
 
 
1
  import { ReactComponent as SelectFilesEndIcon } from '@/assets/svg/select-files-end.svg';
2
  import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg';
3
+ import ChunkMethodModal from '@/components/chunk-method-modal';
4
  import { KnowledgeRouteKey } from '@/constants/knowledge';
5
+ import {
6
+ useRunDocument,
7
+ useSelectDocumentList,
8
+ useUploadDocument,
9
+ } from '@/hooks/documentHooks';
10
  import {
11
  useDeleteDocumentById,
12
  useFetchKnowledgeDetail,
 
13
  useKnowledgeBaseId,
14
  } from '@/hooks/knowledgeHook';
15
  import {
16
+ useChangeDocumentParser,
17
+ useSetSelectedRecord,
18
+ } from '@/hooks/logicHooks';
19
+ import { useFetchTenantInfo } from '@/hooks/userSettingHook';
20
+ import { IKnowledgeFile } from '@/interfaces/database/knowledge';
21
+ import { getExtension, isFileUploadDone } from '@/utils/documentUtils';
22
  import {
23
  ArrowLeftOutlined,
24
  CloudUploadOutlined,
 
30
  Button,
31
  Card,
32
  Flex,
 
33
  Progress,
 
 
34
  Space,
35
  Upload,
36
  UploadFile,
37
  UploadProps,
38
  } from 'antd';
39
  import classNames from 'classnames';
40
+ import { ReactElement, useCallback, useMemo, useRef, useState } from 'react';
41
+ import { Link, useNavigate } from 'umi';
 
 
 
 
 
 
 
42
 
 
43
  import styles from './index.less';
44
 
45
  const { Dragger } = Upload;
 
52
  file,
53
  isUpload,
54
  remove,
55
+ handleEdit,
56
  }: {
57
  isUpload: boolean;
58
  originNode: ReactElement;
59
  file: UploadFile;
60
  fileList: object[];
61
+ showModal: () => void;
62
  remove: (id: string) => void;
63
+ setRecord: (record: IKnowledgeFile) => void;
64
+ handleEdit: (id: string) => void;
65
  }) => {
 
66
  const { removeDocument } = useDeleteDocumentById();
 
 
67
 
68
  const documentId = file?.response?.id;
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  const handleRemove = async () => {
71
  if (file.status === 'error') {
72
  remove(documentId);
 
78
  }
79
  };
80
 
81
+ const handleEditClick = () => {
82
+ if (file.status === 'done') {
83
+ handleEdit(documentId);
84
+ }
85
+ };
86
 
87
  return (
88
  <Card className={styles.uploaderItem}>
 
100
  onClick={handleRemove}
101
  />
102
  ) : (
103
+ <EditOutlined onClick={handleEditClick} />
 
 
104
  )}
105
  </Flex>
106
  <Flex>
 
121
  const KnowledgeUploadFile = () => {
122
  const knowledgeBaseId = useKnowledgeBaseId();
123
  const [isUpload, setIsUpload] = useState(true);
 
124
  const [uploadedFileIds, setUploadedFileIds] = useState<string[]>([]);
125
  const fileListRef = useRef<UploadFile[]>([]);
126
  const navigate = useNavigate();
127
+ const { currentRecord, setRecord } = useSetSelectedRecord();
128
+ const {
129
+ changeParserLoading,
130
+ onChangeParserOk,
131
+ changeParserVisible,
132
+ hideChangeParserModal,
133
+ showChangeParserModal,
134
+ } = useChangeDocumentParser(currentRecord.id);
135
+ const documentList = useSelectDocumentList();
136
+ const runDocumentByIds = useRunDocument();
137
+ const uploadDocument = useUploadDocument();
138
 
139
  const enabled = useMemo(() => {
140
  if (isUpload) {
 
153
  onError,
154
  // onProgress,
155
  }) {
156
+ const data = await uploadDocument(file as UploadFile);
 
157
  if (data?.retcode === 0) {
158
  setUploadedFileIds((pre) => {
159
  return pre.concat(data.data.id);
 
174
  });
175
  }, []);
176
 
177
+ const handleItemEdit = useCallback(
178
+ (id: string) => {
179
+ const document = documentList.find((x) => x.id === id);
180
+ if (document) {
181
+ setRecord(document);
182
+ }
183
+ showChangeParserModal();
184
+ },
185
+ [documentList, showChangeParserModal, setRecord],
186
+ );
187
+
188
  const props: UploadProps = {
189
  name: 'file',
190
  multiple: true,
 
203
  fileList={fileList}
204
  originNode={originNode}
205
  remove={remove}
206
+ showModal={showChangeParserModal}
207
+ setRecord={setRecord}
208
+ handleEdit={handleItemEdit}
209
  ></UploaderItem>
210
  );
211
  },
 
217
 
218
  const runSelectedDocument = () => {
219
  const ids = fileListRef.current.map((x) => x.response.id);
220
+ runDocumentByIds(ids);
 
 
 
221
  };
222
 
223
  const handleNextClick = () => {
 
233
  useFetchKnowledgeDetail();
234
 
235
  return (
236
+ <>
237
+ <div className={styles.uploadWrapper}>
238
+ <section>
239
+ <Space className={styles.backToList}>
240
+ <ArrowLeftOutlined />
241
+ <Link to={`/knowledge/dataset?id=${knowledgeBaseId}`}>
242
+ Back to select files
243
+ </Link>
244
+ </Space>
245
+ <div className={styles.progressWrapper}>
246
+ <Flex align="center" justify="center">
247
+ <SelectFilesStartIcon></SelectFilesStartIcon>
248
+ <Progress
249
+ percent={100}
250
+ showInfo={false}
251
+ className={styles.progress}
252
+ strokeColor="
253
+ rgba(127, 86, 217, 1)
254
+ "
255
+ />
256
+ <SelectFilesEndIcon></SelectFilesEndIcon>
257
+ </Flex>
258
+ <Flex justify="space-around">
259
+ <p className={styles.selectFilesText}>
260
+ <b>Select files</b>
261
+ </p>
262
+ <p className={styles.changeSpecificCategoryText}>
263
+ <b>Change specific category</b>
264
+ </p>
265
+ </Flex>
266
+ </div>
267
+ </section>
268
+ <section className={styles.uploadContent}>
269
+ <Dragger
270
+ {...props}
271
+ className={classNames(styles.uploader, {
272
+ [styles.hiddenUploader]: !isUpload,
273
+ })}
274
+ >
275
+ <Button className={styles.uploaderButton}>
276
+ <CloudUploadOutlined className={styles.uploaderIcon} />
277
+ </Button>
278
+ <p className="ant-upload-text">
279
+ Click or drag file to this area to upload
280
  </p>
281
+ <p className="ant-upload-hint">
282
+ Support for a single or bulk upload. Strictly prohibited from
283
+ uploading company data or other banned files.
284
  </p>
285
+ </Dragger>
286
+ </section>
287
+ <section className={styles.footer}>
288
+ <Button
289
+ type="primary"
290
+ // className={styles.nextButton}
291
+ onClick={handleNextClick}
292
+ disabled={!enabled}
293
+ >
294
+ Next
 
 
295
  </Button>
296
+ </section>
297
+ </div>
298
+ <ChunkMethodModal
299
+ parserId={currentRecord.parser_id}
300
+ parserConfig={currentRecord.parser_config}
301
+ documentExtension={getExtension(currentRecord.name)}
302
+ onOk={onChangeParserOk}
303
+ visible={changeParserVisible}
304
+ hideModal={hideChangeParserModal}
305
+ loading={changeParserLoading}
306
+ />
307
+ </>
 
 
 
 
 
 
 
 
308
  );
309
  };
310
 
web/src/pages/add-knowledge/components/knowledge-file/hooks.ts CHANGED
@@ -7,10 +7,7 @@ import {
7
  } from '@/hooks/documentHooks';
8
  import { useGetKnowledgeSearchParams } from '@/hooks/routeHook';
9
  import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
10
- import {
11
- useFetchTenantInfo,
12
- useSelectParserList,
13
- } from '@/hooks/userSettingHook';
14
  import { Pagination } from '@/interfaces/common';
15
  import { IKnowledgeFile } from '@/interfaces/database/knowledge';
16
  import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
@@ -243,21 +240,3 @@ export const useChangeDocumentParser = (documentId: string) => {
243
  showChangeParserModal,
244
  };
245
  };
246
-
247
- export const useFetchParserListOnMount = (parserId: string) => {
248
- const [selectedTag, setSelectedTag] = useState('');
249
- const parserList = useSelectParserList();
250
-
251
- useFetchTenantInfo();
252
-
253
- useEffect(() => {
254
- setSelectedTag(parserId);
255
- }, [parserId]);
256
-
257
- const handleChange = (tag: string, checked: boolean) => {
258
- const nextSelectedTag = checked ? tag : selectedTag;
259
- setSelectedTag(nextSelectedTag);
260
- };
261
-
262
- return { parserList, handleChange, selectedTag };
263
- };
 
7
  } from '@/hooks/documentHooks';
8
  import { useGetKnowledgeSearchParams } from '@/hooks/routeHook';
9
  import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
10
+ import { useFetchTenantInfo } from '@/hooks/userSettingHook';
 
 
 
11
  import { Pagination } from '@/interfaces/common';
12
  import { IKnowledgeFile } from '@/interfaces/database/knowledge';
13
  import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
 
240
  showChangeParserModal,
241
  };
242
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
web/src/pages/add-knowledge/components/knowledge-file/index.tsx CHANGED
@@ -23,7 +23,6 @@ import {
23
  } from 'antd';
24
  import type { ColumnsType } from 'antd/es/table';
25
  import { useMemo } from 'react';
26
- import ChunkMethodModal from './chunk-method-modal';
27
  import CreateFileModal from './create-file-modal';
28
  import {
29
  useChangeDocumentParser,
@@ -39,6 +38,8 @@ import ParsingActionCell from './parsing-action-cell';
39
  import ParsingStatusCell from './parsing-status-cell';
40
  import RenameModal from './rename-modal';
41
 
 
 
42
  import styles from './index.less';
43
 
44
  const KnowledgeFile = () => {
@@ -227,7 +228,7 @@ const KnowledgeFile = () => {
227
  <ChunkMethodModal
228
  parserId={currentRecord.parser_id}
229
  parserConfig={currentRecord.parser_config}
230
- documentType={currentRecord.type}
231
  onOk={onChangeParserOk}
232
  visible={changeParserVisible}
233
  hideModal={hideChangeParserModal}
 
23
  } from 'antd';
24
  import type { ColumnsType } from 'antd/es/table';
25
  import { useMemo } from 'react';
 
26
  import CreateFileModal from './create-file-modal';
27
  import {
28
  useChangeDocumentParser,
 
38
  import ParsingStatusCell from './parsing-status-cell';
39
  import RenameModal from './rename-modal';
40
 
41
+ import ChunkMethodModal from '@/components/chunk-method-modal';
42
+ import { getExtension } from '@/utils/documentUtils';
43
  import styles from './index.less';
44
 
45
  const KnowledgeFile = () => {
 
228
  <ChunkMethodModal
229
  parserId={currentRecord.parser_id}
230
  parserConfig={currentRecord.parser_config}
231
+ documentExtension={getExtension(currentRecord.name)}
232
  onOk={onChangeParserOk}
233
  visible={changeParserVisible}
234
  hideModal={hideChangeParserModal}
web/src/pages/add-knowledge/components/knowledge-file/model.ts CHANGED
@@ -209,6 +209,19 @@ const model: DvaModel<KFModelState> = {
209
  console.warn(error);
210
  }
211
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  },
213
  };
214
  export default model;
 
209
  console.warn(error);
210
  }
211
  },
212
+ *upload_document({ payload = {} }, { call, put }) {
213
+ const formData = new FormData();
214
+ formData.append('file', payload.file);
215
+ formData.append('kb_id', payload.kb_id);
216
+ const { data } = yield call(kbService.document_upload, formData);
217
+ if (data.retcode === 0) {
218
+ yield put({
219
+ type: 'getKfList',
220
+ payload: { kb_id: payload.kb_id },
221
+ });
222
+ }
223
+ return data;
224
+ },
225
  },
226
  };
227
  export default model;
web/src/pages/add-knowledge/components/knowledge-file/upload.tsx DELETED
@@ -1,42 +0,0 @@
1
- import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
2
- import uploadService from '@/services/uploadService';
3
- import type { UploadProps } from 'antd';
4
- import React from 'react';
5
- import { Link } from 'umi';
6
- interface PropsType {
7
- kb_id: string;
8
- getKfList: () => void;
9
- }
10
-
11
- type UploadRequestOption = Parameters<
12
- NonNullable<UploadProps['customRequest']>
13
- >[0];
14
-
15
- const FileUpload: React.FC<PropsType> = ({ kb_id, getKfList }) => {
16
- const knowledgeBaseId = useKnowledgeBaseId();
17
-
18
- const createRequest: (props: UploadRequestOption) => void = async function ({
19
- file,
20
- onSuccess,
21
- onError,
22
- }) {
23
- const { retcode, data } = await uploadService.uploadFile(file, kb_id);
24
- if (retcode === 0) {
25
- onSuccess && onSuccess(data, file);
26
- } else {
27
- onError && onError(data);
28
- }
29
- getKfList && getKfList();
30
- };
31
- const uploadProps: UploadProps = {
32
- customRequest: createRequest,
33
- showUploadList: false,
34
- };
35
- return (
36
- // <Upload {...uploadProps}>
37
- <Link to={`/knowledge/dataset/upload?id=${knowledgeBaseId}`}>导入文件</Link>
38
- // </Upload>
39
- );
40
- };
41
-
42
- export default FileUpload;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
web/src/services/kbService.ts CHANGED
@@ -25,6 +25,7 @@ const {
25
  document_rename,
26
  document_run,
27
  get_document_file,
 
28
  } = api;
29
 
30
  const methods = {
@@ -82,6 +83,10 @@ const methods = {
82
  url: document_thumbnails,
83
  method: 'get',
84
  },
 
 
 
 
85
  // chunk管理
86
  chunk_list: {
87
  url: chunk_list,
 
25
  document_rename,
26
  document_run,
27
  get_document_file,
28
+ document_upload,
29
  } = api;
30
 
31
  const methods = {
 
83
  url: document_thumbnails,
84
  method: 'get',
85
  },
86
+ document_upload: {
87
+ url: document_upload,
88
+ method: 'post',
89
+ },
90
  // chunk管理
91
  chunk_list: {
92
  url: chunk_list,
web/src/services/uploadService.ts DELETED
@@ -1,21 +0,0 @@
1
- import api from '@/utils/api';
2
- import request from '@/utils/request';
3
-
4
- const { upload } = api;
5
-
6
- const uploadService = {
7
- uploadFile: function (file: any, kb_id: string) {
8
- const formData = new FormData();
9
- formData.append('file', file);
10
- formData.append('kb_id', kb_id);
11
-
12
- const options = {
13
- method: 'post',
14
- data: formData,
15
- };
16
-
17
- return request(upload, options);
18
- },
19
- };
20
-
21
- export default uploadService;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
web/src/utils/api.ts CHANGED
@@ -45,6 +45,7 @@ export default {
45
  document_change_parser: `${api_host}/document/change_parser`,
46
  document_thumbnails: `${api_host}/document/thumbnails`,
47
  get_document_file: `${api_host}/document/get`,
 
48
 
49
  setDialog: `${api_host}/dialog/set`,
50
  getDialog: `${api_host}/dialog/get`,
 
45
  document_change_parser: `${api_host}/document/change_parser`,
46
  document_thumbnails: `${api_host}/document/thumbnails`,
47
  get_document_file: `${api_host}/document/get`,
48
+ document_upload: `${api_host}/document/upload`,
49
 
50
  setDialog: `${api_host}/dialog/set`,
51
  getDialog: `${api_host}/dialog/get`,
web/src/utils/documentUtils.ts CHANGED
@@ -35,3 +35,6 @@ export const buildChunkHighlights = (
35
  };
36
 
37
  export const isFileUploadDone = (file: UploadFile) => file.status === 'done';
 
 
 
 
35
  };
36
 
37
  export const isFileUploadDone = (file: UploadFile) => file.status === 'done';
38
+
39
+ export const getExtension = (name: string) =>
40
+ name?.slice(name.lastIndexOf('.') + 1).toLowerCase() ?? '';