* 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-filetags/v0.1.0
| import { | |||||
| useFetchTenantInfo, | |||||
| useSelectParserList, | |||||
| } from '@/hooks/userSettingHook'; | |||||
| import { useEffect, useMemo, useState } from 'react'; | |||||
| const ParserListMap = new Map([ | |||||
| [ | |||||
| ['pdf'], | |||||
| [ | |||||
| 'naive', | |||||
| 'resume', | |||||
| 'manual', | |||||
| 'paper', | |||||
| 'book', | |||||
| 'laws', | |||||
| 'presentation', | |||||
| 'one', | |||||
| ], | |||||
| ], | |||||
| [ | |||||
| ['doc', 'docx'], | |||||
| ['naive', 'resume', 'book', 'laws', 'one'], | |||||
| ], | |||||
| [ | |||||
| ['xlsx', 'xls'], | |||||
| ['naive', 'qa', 'table', 'one'], | |||||
| ], | |||||
| [['ppt', 'pptx'], ['presentation']], | |||||
| [ | |||||
| ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tif', 'tiff', 'webp', 'svg', 'ico'], | |||||
| ['picture'], | |||||
| ], | |||||
| [['txt'], ['naive', 'resume', 'book', 'laws', 'one', 'qa', 'table']], | |||||
| [['csv'], ['naive', 'resume', 'book', 'laws', 'one', 'qa', 'table']], | |||||
| ]); | |||||
| const getParserList = ( | |||||
| values: string[], | |||||
| parserList: Array<{ | |||||
| value: string; | |||||
| label: string; | |||||
| }>, | |||||
| ) => { | |||||
| return parserList.filter((x) => values?.some((y) => y === x.value)); | |||||
| }; | |||||
| export const useFetchParserListOnMount = ( | |||||
| parserId: string, | |||||
| documentExtension: string, | |||||
| ) => { | |||||
| const [selectedTag, setSelectedTag] = useState(''); | |||||
| const parserList = useSelectParserList(); | |||||
| const nextParserList = useMemo(() => { | |||||
| const key = [...ParserListMap.keys()].find((x) => | |||||
| x.some((y) => y === documentExtension), | |||||
| ); | |||||
| if (key) { | |||||
| const values = ParserListMap.get(key); | |||||
| return getParserList(values ?? [], parserList); | |||||
| } | |||||
| return getParserList( | |||||
| ['naive', 'resume', 'book', 'laws', 'one', 'qa', 'table'], | |||||
| parserList, | |||||
| ); | |||||
| }, [parserList, documentExtension]); | |||||
| useFetchTenantInfo(); | |||||
| useEffect(() => { | |||||
| setSelectedTag(parserId); | |||||
| }, [parserId]); | |||||
| const handleChange = (tag: string, checked: boolean) => { | |||||
| const nextSelectedTag = checked ? tag : selectedTag; | |||||
| setSelectedTag(nextSelectedTag); | |||||
| }; | |||||
| return { parserList: nextParserList, handleChange, selectedTag }; | |||||
| }; |
| .pageInputNumber { | |||||
| width: 220px; | |||||
| } | |||||
| .questionIcon { | |||||
| margin-inline-start: 4px; | |||||
| color: rgba(0, 0, 0, 0.45); | |||||
| cursor: help; | |||||
| writing-mode: horizontal-tb; | |||||
| } |
| showModal?(): void; | showModal?(): void; | ||||
| parserId: string; | parserId: string; | ||||
| parserConfig: IKnowledgeFileParserConfig; | parserConfig: IKnowledgeFileParserConfig; | ||||
| documentType: string; | |||||
| documentExtension: string; | |||||
| } | } | ||||
| const hidePagesChunkMethods = ['qa', 'table', 'picture', 'resume', 'one']; | const hidePagesChunkMethods = ['qa', 'table', 'picture', 'resume', 'one']; | ||||
| onOk, | onOk, | ||||
| hideModal, | hideModal, | ||||
| visible, | visible, | ||||
| documentType, | |||||
| documentExtension, | |||||
| parserConfig, | parserConfig, | ||||
| }) => { | }) => { | ||||
| const { parserList, handleChange, selectedTag } = | |||||
| useFetchParserListOnMount(parserId); | |||||
| const { parserList, handleChange, selectedTag } = useFetchParserListOnMount( | |||||
| parserId, | |||||
| documentExtension, | |||||
| ); | |||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| const handleOk = async () => { | const handleOk = async () => { | ||||
| }; | }; | ||||
| const showPages = useMemo(() => { | const showPages = useMemo(() => { | ||||
| return ( | |||||
| documentType === 'pdf' && | |||||
| hidePagesChunkMethods.every((x) => x !== selectedTag) | |||||
| ); | |||||
| }, [documentType, selectedTag]); | |||||
| return hidePagesChunkMethods.every((x) => x !== selectedTag); | |||||
| }, [selectedTag]); | |||||
| const showOne = useMemo(() => { | const showOne = useMemo(() => { | ||||
| return showPages || selectedTag === 'one'; | return showPages || selectedTag === 'one'; | ||||
| </Space> | </Space> | ||||
| <Divider></Divider> | <Divider></Divider> | ||||
| { | |||||
| {documentExtension === 'pdf' && ( | |||||
| <Form name="dynamic_form_nest_item" autoComplete="off" form={form}> | <Form name="dynamic_form_nest_item" autoComplete="off" form={form}> | ||||
| {showPages && ( | {showPages && ( | ||||
| <> | <> | ||||
| {selectedTag === 'naive' && <MaxTokenNumber></MaxTokenNumber>} | {selectedTag === 'naive' && <MaxTokenNumber></MaxTokenNumber>} | ||||
| </Form> | </Form> | ||||
| } | |||||
| )} | |||||
| </Modal> | </Modal> | ||||
| ); | ); | ||||
| }; | }; |
| import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; | import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; | ||||
| import { api_host } from '@/utils/api'; | import { api_host } from '@/utils/api'; | ||||
| import { buildChunkHighlights } from '@/utils/documentUtils'; | import { buildChunkHighlights } from '@/utils/documentUtils'; | ||||
| import { UploadFile } from 'antd'; | |||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||
| import { IHighlight } from 'react-pdf-highlighter'; | import { IHighlight } from 'react-pdf-highlighter'; | ||||
| import { useDispatch, useSelector } from 'umi'; | import { useDispatch, useSelector } from 'umi'; | ||||
| return removeDocument; | return removeDocument; | ||||
| }; | }; | ||||
| export const useUploadDocument = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const { knowledgeId } = useGetKnowledgeSearchParams(); | |||||
| const uploadDocument = useCallback( | |||||
| (file: UploadFile) => { | |||||
| try { | |||||
| return dispatch<any>({ | |||||
| type: 'kFModel/upload_document', | |||||
| payload: { | |||||
| file, | |||||
| kb_id: knowledgeId, | |||||
| }, | |||||
| }); | |||||
| } catch (errorInfo) { | |||||
| console.log('Failed:', errorInfo); | |||||
| } | |||||
| }, | |||||
| [dispatch, knowledgeId], | |||||
| ); | |||||
| return uploadDocument; | |||||
| }; | |||||
| export const useRunDocument = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const runDocumentByIds = useCallback( | |||||
| (ids: string[]) => { | |||||
| try { | |||||
| return dispatch<any>({ | |||||
| type: 'kFModel/document_run', | |||||
| payload: { doc_ids: ids, run: 1 }, | |||||
| }); | |||||
| } catch (errorInfo) { | |||||
| console.log('Failed:', errorInfo); | |||||
| } | |||||
| }, | |||||
| [dispatch], | |||||
| ); | |||||
| return runDocumentByIds; | |||||
| }; |
| import { IKnowledgeFile } from '@/interfaces/database/knowledge'; | |||||
| import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; | |||||
| import { useCallback, useState } from 'react'; | |||||
| import { useSetModalState } from './commonHooks'; | |||||
| import { useSetDocumentParser } from './documentHooks'; | |||||
| import { useOneNamespaceEffectsLoading } from './storeHooks'; | |||||
| export const useChangeDocumentParser = (documentId: string) => { | |||||
| const setDocumentParser = useSetDocumentParser(); | |||||
| const { | |||||
| visible: changeParserVisible, | |||||
| hideModal: hideChangeParserModal, | |||||
| showModal: showChangeParserModal, | |||||
| } = useSetModalState(); | |||||
| const loading = useOneNamespaceEffectsLoading('kFModel', [ | |||||
| 'document_change_parser', | |||||
| ]); | |||||
| const onChangeParserOk = useCallback( | |||||
| async (parserId: string, parserConfig: IChangeParserConfigRequestBody) => { | |||||
| const ret = await setDocumentParser(parserId, documentId, parserConfig); | |||||
| if (ret === 0) { | |||||
| hideChangeParserModal(); | |||||
| } | |||||
| }, | |||||
| [hideChangeParserModal, setDocumentParser, documentId], | |||||
| ); | |||||
| return { | |||||
| changeParserLoading: loading, | |||||
| onChangeParserOk, | |||||
| changeParserVisible, | |||||
| hideChangeParserModal, | |||||
| showChangeParserModal, | |||||
| }; | |||||
| }; | |||||
| export const useSetSelectedRecord = <T = IKnowledgeFile>() => { | |||||
| const [currentRecord, setCurrentRecord] = useState<T>({} as T); | |||||
| const setRecord = (record: T) => { | |||||
| setCurrentRecord(record); | |||||
| }; | |||||
| return { currentRecord, setRecord }; | |||||
| }; |
| import { ReactComponent as SelectFilesEndIcon } from '@/assets/svg/select-files-end.svg'; | import { ReactComponent as SelectFilesEndIcon } from '@/assets/svg/select-files-end.svg'; | ||||
| import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg'; | import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg'; | ||||
| import ChunkMethodModal from '@/components/chunk-method-modal'; | |||||
| import { KnowledgeRouteKey } from '@/constants/knowledge'; | import { KnowledgeRouteKey } from '@/constants/knowledge'; | ||||
| import { | |||||
| useRunDocument, | |||||
| useSelectDocumentList, | |||||
| useUploadDocument, | |||||
| } from '@/hooks/documentHooks'; | |||||
| import { | import { | ||||
| useDeleteDocumentById, | useDeleteDocumentById, | ||||
| useFetchKnowledgeDetail, | useFetchKnowledgeDetail, | ||||
| useGetDocumentDefaultParser, | |||||
| useKnowledgeBaseId, | useKnowledgeBaseId, | ||||
| } from '@/hooks/knowledgeHook'; | } from '@/hooks/knowledgeHook'; | ||||
| import { | import { | ||||
| useFetchTenantInfo, | |||||
| useSelectParserList, | |||||
| } from '@/hooks/userSettingHook'; | |||||
| import uploadService from '@/services/uploadService'; | |||||
| import { isFileUploadDone } from '@/utils/documentUtils'; | |||||
| useChangeDocumentParser, | |||||
| useSetSelectedRecord, | |||||
| } from '@/hooks/logicHooks'; | |||||
| import { useFetchTenantInfo } from '@/hooks/userSettingHook'; | |||||
| import { IKnowledgeFile } from '@/interfaces/database/knowledge'; | |||||
| import { getExtension, isFileUploadDone } from '@/utils/documentUtils'; | |||||
| import { | import { | ||||
| ArrowLeftOutlined, | ArrowLeftOutlined, | ||||
| CloudUploadOutlined, | CloudUploadOutlined, | ||||
| Button, | Button, | ||||
| Card, | Card, | ||||
| Flex, | Flex, | ||||
| Popover, | |||||
| Progress, | Progress, | ||||
| Radio, | |||||
| RadioChangeEvent, | |||||
| Space, | Space, | ||||
| Upload, | Upload, | ||||
| UploadFile, | UploadFile, | ||||
| UploadProps, | UploadProps, | ||||
| } from 'antd'; | } from 'antd'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { | |||||
| ReactElement, | |||||
| useCallback, | |||||
| useEffect, | |||||
| useMemo, | |||||
| useRef, | |||||
| useState, | |||||
| } from 'react'; | |||||
| import { Link, useDispatch, useNavigate } from 'umi'; | |||||
| import { ReactElement, useCallback, useMemo, useRef, useState } from 'react'; | |||||
| import { Link, useNavigate } from 'umi'; | |||||
| import { useSetDocumentParser } from '@/hooks/documentHooks'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const { Dragger } = Upload; | const { Dragger } = Upload; | ||||
| file, | file, | ||||
| isUpload, | isUpload, | ||||
| remove, | remove, | ||||
| handleEdit, | |||||
| }: { | }: { | ||||
| isUpload: boolean; | isUpload: boolean; | ||||
| originNode: ReactElement; | originNode: ReactElement; | ||||
| file: UploadFile; | file: UploadFile; | ||||
| fileList: object[]; | fileList: object[]; | ||||
| showModal: () => void; | |||||
| remove: (id: string) => void; | remove: (id: string) => void; | ||||
| setRecord: (record: IKnowledgeFile) => void; | |||||
| handleEdit: (id: string) => void; | |||||
| }) => { | }) => { | ||||
| const { parserConfig, defaultParserId } = useGetDocumentDefaultParser(); | |||||
| const { removeDocument } = useDeleteDocumentById(); | const { removeDocument } = useDeleteDocumentById(); | ||||
| const [value, setValue] = useState(defaultParserId); | |||||
| const setDocumentParser = useSetDocumentParser(); | |||||
| const documentId = file?.response?.id; | const documentId = file?.response?.id; | ||||
| const parserList = useSelectParserList(); | |||||
| const saveParser = (parserId: string) => { | |||||
| setDocumentParser(parserId, documentId, parserConfig as any); | |||||
| }; | |||||
| const onChange = (e: RadioChangeEvent) => { | |||||
| const val = e.target.value; | |||||
| setValue(val); | |||||
| saveParser(val); | |||||
| }; | |||||
| const content = ( | |||||
| <Radio.Group onChange={onChange} value={value}> | |||||
| <Space direction="vertical"> | |||||
| {parserList.map( | |||||
| ( | |||||
| x, // value is lowercase, key is uppercase | |||||
| ) => ( | |||||
| <Radio value={x.value} key={x.value}> | |||||
| {x.label} | |||||
| </Radio> | |||||
| ), | |||||
| )} | |||||
| </Space> | |||||
| </Radio.Group> | |||||
| ); | |||||
| const handleRemove = async () => { | const handleRemove = async () => { | ||||
| if (file.status === 'error') { | if (file.status === 'error') { | ||||
| remove(documentId); | remove(documentId); | ||||
| } | } | ||||
| }; | }; | ||||
| useEffect(() => { | |||||
| setValue(defaultParserId); | |||||
| }, [defaultParserId]); | |||||
| const handleEditClick = () => { | |||||
| if (file.status === 'done') { | |||||
| handleEdit(documentId); | |||||
| } | |||||
| }; | |||||
| return ( | return ( | ||||
| <Card className={styles.uploaderItem}> | <Card className={styles.uploaderItem}> | ||||
| onClick={handleRemove} | onClick={handleRemove} | ||||
| /> | /> | ||||
| ) : ( | ) : ( | ||||
| <Popover content={content} placement="bottom"> | |||||
| <EditOutlined /> | |||||
| </Popover> | |||||
| <EditOutlined onClick={handleEditClick} /> | |||||
| )} | )} | ||||
| </Flex> | </Flex> | ||||
| <Flex> | <Flex> | ||||
| const KnowledgeUploadFile = () => { | const KnowledgeUploadFile = () => { | ||||
| const knowledgeBaseId = useKnowledgeBaseId(); | const knowledgeBaseId = useKnowledgeBaseId(); | ||||
| const [isUpload, setIsUpload] = useState(true); | const [isUpload, setIsUpload] = useState(true); | ||||
| const dispatch = useDispatch(); | |||||
| const [uploadedFileIds, setUploadedFileIds] = useState<string[]>([]); | const [uploadedFileIds, setUploadedFileIds] = useState<string[]>([]); | ||||
| const fileListRef = useRef<UploadFile[]>([]); | const fileListRef = useRef<UploadFile[]>([]); | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const { currentRecord, setRecord } = useSetSelectedRecord(); | |||||
| const { | |||||
| changeParserLoading, | |||||
| onChangeParserOk, | |||||
| changeParserVisible, | |||||
| hideChangeParserModal, | |||||
| showChangeParserModal, | |||||
| } = useChangeDocumentParser(currentRecord.id); | |||||
| const documentList = useSelectDocumentList(); | |||||
| const runDocumentByIds = useRunDocument(); | |||||
| const uploadDocument = useUploadDocument(); | |||||
| const enabled = useMemo(() => { | const enabled = useMemo(() => { | ||||
| if (isUpload) { | if (isUpload) { | ||||
| onError, | onError, | ||||
| // onProgress, | // onProgress, | ||||
| }) { | }) { | ||||
| const ret = await uploadService.uploadFile(file, knowledgeBaseId); | |||||
| const data = ret?.data; | |||||
| const data = await uploadDocument(file as UploadFile); | |||||
| if (data?.retcode === 0) { | if (data?.retcode === 0) { | ||||
| setUploadedFileIds((pre) => { | setUploadedFileIds((pre) => { | ||||
| return pre.concat(data.data.id); | return pre.concat(data.data.id); | ||||
| }); | }); | ||||
| }, []); | }, []); | ||||
| const handleItemEdit = useCallback( | |||||
| (id: string) => { | |||||
| const document = documentList.find((x) => x.id === id); | |||||
| if (document) { | |||||
| setRecord(document); | |||||
| } | |||||
| showChangeParserModal(); | |||||
| }, | |||||
| [documentList, showChangeParserModal, setRecord], | |||||
| ); | |||||
| const props: UploadProps = { | const props: UploadProps = { | ||||
| name: 'file', | name: 'file', | ||||
| multiple: true, | multiple: true, | ||||
| fileList={fileList} | fileList={fileList} | ||||
| originNode={originNode} | originNode={originNode} | ||||
| remove={remove} | remove={remove} | ||||
| showModal={showChangeParserModal} | |||||
| setRecord={setRecord} | |||||
| handleEdit={handleItemEdit} | |||||
| ></UploaderItem> | ></UploaderItem> | ||||
| ); | ); | ||||
| }, | }, | ||||
| const runSelectedDocument = () => { | const runSelectedDocument = () => { | ||||
| const ids = fileListRef.current.map((x) => x.response.id); | const ids = fileListRef.current.map((x) => x.response.id); | ||||
| dispatch({ | |||||
| type: 'kFModel/document_run', | |||||
| payload: { doc_ids: ids, run: 1 }, | |||||
| }); | |||||
| runDocumentByIds(ids); | |||||
| }; | }; | ||||
| const handleNextClick = () => { | const handleNextClick = () => { | ||||
| useFetchKnowledgeDetail(); | useFetchKnowledgeDetail(); | ||||
| return ( | return ( | ||||
| <div className={styles.uploadWrapper}> | |||||
| <section> | |||||
| <Space className={styles.backToList}> | |||||
| <ArrowLeftOutlined /> | |||||
| <Link to={`/knowledge/dataset?id=${knowledgeBaseId}`}> | |||||
| Back to select files | |||||
| </Link> | |||||
| </Space> | |||||
| <div className={styles.progressWrapper}> | |||||
| <Flex align="center" justify="center"> | |||||
| <SelectFilesStartIcon></SelectFilesStartIcon> | |||||
| <Progress | |||||
| percent={100} | |||||
| showInfo={false} | |||||
| className={styles.progress} | |||||
| strokeColor=" | |||||
| rgba(127, 86, 217, 1) | |||||
| " | |||||
| /> | |||||
| <SelectFilesEndIcon></SelectFilesEndIcon> | |||||
| </Flex> | |||||
| <Flex justify="space-around"> | |||||
| <p className={styles.selectFilesText}> | |||||
| <b>Select files</b> | |||||
| <> | |||||
| <div className={styles.uploadWrapper}> | |||||
| <section> | |||||
| <Space className={styles.backToList}> | |||||
| <ArrowLeftOutlined /> | |||||
| <Link to={`/knowledge/dataset?id=${knowledgeBaseId}`}> | |||||
| Back to select files | |||||
| </Link> | |||||
| </Space> | |||||
| <div className={styles.progressWrapper}> | |||||
| <Flex align="center" justify="center"> | |||||
| <SelectFilesStartIcon></SelectFilesStartIcon> | |||||
| <Progress | |||||
| percent={100} | |||||
| showInfo={false} | |||||
| className={styles.progress} | |||||
| strokeColor=" | |||||
| rgba(127, 86, 217, 1) | |||||
| " | |||||
| /> | |||||
| <SelectFilesEndIcon></SelectFilesEndIcon> | |||||
| </Flex> | |||||
| <Flex justify="space-around"> | |||||
| <p className={styles.selectFilesText}> | |||||
| <b>Select files</b> | |||||
| </p> | |||||
| <p className={styles.changeSpecificCategoryText}> | |||||
| <b>Change specific category</b> | |||||
| </p> | |||||
| </Flex> | |||||
| </div> | |||||
| </section> | |||||
| <section className={styles.uploadContent}> | |||||
| <Dragger | |||||
| {...props} | |||||
| className={classNames(styles.uploader, { | |||||
| [styles.hiddenUploader]: !isUpload, | |||||
| })} | |||||
| > | |||||
| <Button className={styles.uploaderButton}> | |||||
| <CloudUploadOutlined className={styles.uploaderIcon} /> | |||||
| </Button> | |||||
| <p className="ant-upload-text"> | |||||
| Click or drag file to this area to upload | |||||
| </p> | </p> | ||||
| <p className={styles.changeSpecificCategoryText}> | |||||
| <b>Change specific category</b> | |||||
| <p className="ant-upload-hint"> | |||||
| Support for a single or bulk upload. Strictly prohibited from | |||||
| uploading company data or other banned files. | |||||
| </p> | </p> | ||||
| </Flex> | |||||
| </div> | |||||
| </section> | |||||
| <section className={styles.uploadContent}> | |||||
| <Dragger | |||||
| {...props} | |||||
| className={classNames(styles.uploader, { | |||||
| [styles.hiddenUploader]: !isUpload, | |||||
| })} | |||||
| > | |||||
| <Button className={styles.uploaderButton}> | |||||
| <CloudUploadOutlined className={styles.uploaderIcon} /> | |||||
| </Dragger> | |||||
| </section> | |||||
| <section className={styles.footer}> | |||||
| <Button | |||||
| type="primary" | |||||
| // className={styles.nextButton} | |||||
| onClick={handleNextClick} | |||||
| disabled={!enabled} | |||||
| > | |||||
| Next | |||||
| </Button> | </Button> | ||||
| <p className="ant-upload-text"> | |||||
| Click or drag file to this area to upload | |||||
| </p> | |||||
| <p className="ant-upload-hint"> | |||||
| Support for a single or bulk upload. Strictly prohibited from | |||||
| uploading company data or other banned files. | |||||
| </p> | |||||
| </Dragger> | |||||
| </section> | |||||
| <section className={styles.footer}> | |||||
| <Button | |||||
| type="primary" | |||||
| // className={styles.nextButton} | |||||
| onClick={handleNextClick} | |||||
| disabled={!enabled} | |||||
| > | |||||
| Next | |||||
| </Button> | |||||
| </section> | |||||
| </div> | |||||
| </section> | |||||
| </div> | |||||
| <ChunkMethodModal | |||||
| parserId={currentRecord.parser_id} | |||||
| parserConfig={currentRecord.parser_config} | |||||
| documentExtension={getExtension(currentRecord.name)} | |||||
| onOk={onChangeParserOk} | |||||
| visible={changeParserVisible} | |||||
| hideModal={hideChangeParserModal} | |||||
| loading={changeParserLoading} | |||||
| /> | |||||
| </> | |||||
| ); | ); | ||||
| }; | }; | ||||
| } from '@/hooks/documentHooks'; | } from '@/hooks/documentHooks'; | ||||
| import { useGetKnowledgeSearchParams } from '@/hooks/routeHook'; | import { useGetKnowledgeSearchParams } from '@/hooks/routeHook'; | ||||
| import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; | import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; | ||||
| import { | |||||
| useFetchTenantInfo, | |||||
| useSelectParserList, | |||||
| } from '@/hooks/userSettingHook'; | |||||
| import { useFetchTenantInfo } from '@/hooks/userSettingHook'; | |||||
| import { Pagination } from '@/interfaces/common'; | import { Pagination } from '@/interfaces/common'; | ||||
| import { IKnowledgeFile } from '@/interfaces/database/knowledge'; | import { IKnowledgeFile } from '@/interfaces/database/knowledge'; | ||||
| import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; | import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; | ||||
| showChangeParserModal, | showChangeParserModal, | ||||
| }; | }; | ||||
| }; | }; | ||||
| export const useFetchParserListOnMount = (parserId: string) => { | |||||
| const [selectedTag, setSelectedTag] = useState(''); | |||||
| const parserList = useSelectParserList(); | |||||
| useFetchTenantInfo(); | |||||
| useEffect(() => { | |||||
| setSelectedTag(parserId); | |||||
| }, [parserId]); | |||||
| const handleChange = (tag: string, checked: boolean) => { | |||||
| const nextSelectedTag = checked ? tag : selectedTag; | |||||
| setSelectedTag(nextSelectedTag); | |||||
| }; | |||||
| return { parserList, handleChange, selectedTag }; | |||||
| }; |
| } from 'antd'; | } from 'antd'; | ||||
| import type { ColumnsType } from 'antd/es/table'; | import type { ColumnsType } from 'antd/es/table'; | ||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
| import ChunkMethodModal from './chunk-method-modal'; | |||||
| import CreateFileModal from './create-file-modal'; | import CreateFileModal from './create-file-modal'; | ||||
| import { | import { | ||||
| useChangeDocumentParser, | useChangeDocumentParser, | ||||
| import ParsingStatusCell from './parsing-status-cell'; | import ParsingStatusCell from './parsing-status-cell'; | ||||
| import RenameModal from './rename-modal'; | import RenameModal from './rename-modal'; | ||||
| import ChunkMethodModal from '@/components/chunk-method-modal'; | |||||
| import { getExtension } from '@/utils/documentUtils'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const KnowledgeFile = () => { | const KnowledgeFile = () => { | ||||
| <ChunkMethodModal | <ChunkMethodModal | ||||
| parserId={currentRecord.parser_id} | parserId={currentRecord.parser_id} | ||||
| parserConfig={currentRecord.parser_config} | parserConfig={currentRecord.parser_config} | ||||
| documentType={currentRecord.type} | |||||
| documentExtension={getExtension(currentRecord.name)} | |||||
| onOk={onChangeParserOk} | onOk={onChangeParserOk} | ||||
| visible={changeParserVisible} | visible={changeParserVisible} | ||||
| hideModal={hideChangeParserModal} | hideModal={hideChangeParserModal} |
| console.warn(error); | console.warn(error); | ||||
| } | } | ||||
| }, | }, | ||||
| *upload_document({ payload = {} }, { call, put }) { | |||||
| const formData = new FormData(); | |||||
| formData.append('file', payload.file); | |||||
| formData.append('kb_id', payload.kb_id); | |||||
| const { data } = yield call(kbService.document_upload, formData); | |||||
| if (data.retcode === 0) { | |||||
| yield put({ | |||||
| type: 'getKfList', | |||||
| payload: { kb_id: payload.kb_id }, | |||||
| }); | |||||
| } | |||||
| return data; | |||||
| }, | |||||
| }, | }, | ||||
| }; | }; | ||||
| export default model; | export default model; |
| import { useKnowledgeBaseId } from '@/hooks/knowledgeHook'; | |||||
| import uploadService from '@/services/uploadService'; | |||||
| import type { UploadProps } from 'antd'; | |||||
| import React from 'react'; | |||||
| import { Link } from 'umi'; | |||||
| interface PropsType { | |||||
| kb_id: string; | |||||
| getKfList: () => void; | |||||
| } | |||||
| type UploadRequestOption = Parameters< | |||||
| NonNullable<UploadProps['customRequest']> | |||||
| >[0]; | |||||
| const FileUpload: React.FC<PropsType> = ({ kb_id, getKfList }) => { | |||||
| const knowledgeBaseId = useKnowledgeBaseId(); | |||||
| const createRequest: (props: UploadRequestOption) => void = async function ({ | |||||
| file, | |||||
| onSuccess, | |||||
| onError, | |||||
| }) { | |||||
| const { retcode, data } = await uploadService.uploadFile(file, kb_id); | |||||
| if (retcode === 0) { | |||||
| onSuccess && onSuccess(data, file); | |||||
| } else { | |||||
| onError && onError(data); | |||||
| } | |||||
| getKfList && getKfList(); | |||||
| }; | |||||
| const uploadProps: UploadProps = { | |||||
| customRequest: createRequest, | |||||
| showUploadList: false, | |||||
| }; | |||||
| return ( | |||||
| // <Upload {...uploadProps}> | |||||
| <Link to={`/knowledge/dataset/upload?id=${knowledgeBaseId}`}>导入文件</Link> | |||||
| // </Upload> | |||||
| ); | |||||
| }; | |||||
| export default FileUpload; |
| document_rename, | document_rename, | ||||
| document_run, | document_run, | ||||
| get_document_file, | get_document_file, | ||||
| document_upload, | |||||
| } = api; | } = api; | ||||
| const methods = { | const methods = { | ||||
| url: document_thumbnails, | url: document_thumbnails, | ||||
| method: 'get', | method: 'get', | ||||
| }, | }, | ||||
| document_upload: { | |||||
| url: document_upload, | |||||
| method: 'post', | |||||
| }, | |||||
| // chunk管理 | // chunk管理 | ||||
| chunk_list: { | chunk_list: { | ||||
| url: chunk_list, | url: chunk_list, |
| import api from '@/utils/api'; | |||||
| import request from '@/utils/request'; | |||||
| const { upload } = api; | |||||
| const uploadService = { | |||||
| uploadFile: function (file: any, kb_id: string) { | |||||
| const formData = new FormData(); | |||||
| formData.append('file', file); | |||||
| formData.append('kb_id', kb_id); | |||||
| const options = { | |||||
| method: 'post', | |||||
| data: formData, | |||||
| }; | |||||
| return request(upload, options); | |||||
| }, | |||||
| }; | |||||
| export default uploadService; |
| document_change_parser: `${api_host}/document/change_parser`, | document_change_parser: `${api_host}/document/change_parser`, | ||||
| document_thumbnails: `${api_host}/document/thumbnails`, | document_thumbnails: `${api_host}/document/thumbnails`, | ||||
| get_document_file: `${api_host}/document/get`, | get_document_file: `${api_host}/document/get`, | ||||
| document_upload: `${api_host}/document/upload`, | |||||
| setDialog: `${api_host}/dialog/set`, | setDialog: `${api_host}/dialog/set`, | ||||
| getDialog: `${api_host}/dialog/get`, | getDialog: `${api_host}/dialog/get`, |
| }; | }; | ||||
| export const isFileUploadDone = (file: UploadFile) => file.status === 'done'; | export const isFileUploadDone = (file: UploadFile) => file.status === 'done'; | ||||
| export const getExtension = (name: string) => | |||||
| name?.slice(name.lastIndexOf('.') + 1).toLowerCase() ?? ''; |