From a2f9c03a95c6b74ab4896a89d30949e504811cd6 Mon Sep 17 00:00:00 2001 From: balibabu Date: Fri, 11 Oct 2024 08:45:10 +0800 Subject: [PATCH] fix: Change document status with @tanstack/react-query #13306 (#2788) ### What problem does this PR solve? fix: Change document status with @tanstack/react-query #13306 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [ ] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe): --- web/.umirc.ts | 3 +- .../components/chunk-method-modal/index.tsx | 8 +- web/src/components/file-icon/index.tsx | 12 +- web/src/components/message-item/index.tsx | 8 +- web/src/hooks/document-hooks.ts | 461 ++++++++++-------- web/src/hooks/file-manager-hooks.ts | 3 +- web/src/hooks/knowledge-hooks.ts | 61 +-- web/src/hooks/logic-hooks.ts | 60 +-- web/src/hooks/store-hooks.ts | 11 - web/src/interfaces/database/document.ts | 12 +- .../knowledge-file/document-toolbar.tsx | 50 +- .../components/knowledge-file/hooks.ts | 175 ++----- .../components/knowledge-file/index.tsx | 26 +- .../components/knowledge-file/model.ts | 276 ----------- .../parsing-action-cell/index.tsx | 10 +- .../parsing-status-cell/index.tsx | 6 +- web/src/pages/add-knowledge/index.tsx | 23 +- web/src/pages/chat/markdown-content/index.tsx | 10 +- web/src/pages/file-manager/file-toolbar.tsx | 10 +- web/typings.d.ts | 15 - 20 files changed, 375 insertions(+), 865 deletions(-) delete mode 100644 web/src/hooks/store-hooks.ts delete mode 100644 web/src/pages/add-knowledge/components/knowledge-file/model.ts diff --git a/web/.umirc.ts b/web/.umirc.ts index bcdae7c74..80cb6c8e9 100644 --- a/web/.umirc.ts +++ b/web/.umirc.ts @@ -18,8 +18,7 @@ export default defineConfig({ history: { type: 'browser', }, - plugins: ['@react-dev-inspector/umi4-plugin', '@umijs/plugins/dist/dva'], - dva: {}, + plugins: ['@react-dev-inspector/umi4-plugin'], jsMinifier: 'terser', lessLoader: { modifyVars: { diff --git a/web/src/components/chunk-method-modal/index.tsx b/web/src/components/chunk-method-modal/index.tsx index 876de5e0f..cea88b905 100644 --- a/web/src/components/chunk-method-modal/index.tsx +++ b/web/src/components/chunk-method-modal/index.tsx @@ -1,7 +1,5 @@ import MaxTokenNumber from '@/components/max-token-number'; import { IModalManagerChildrenProps } from '@/components/modal-manager'; -import { IKnowledgeFileParserConfig } from '@/interfaces/database/knowledge'; -import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; import { MinusCircleOutlined, PlusOutlined, @@ -22,6 +20,8 @@ import React, { useEffect, useMemo } from 'react'; import { useFetchParserListOnMount } from './hooks'; import { useTranslate } from '@/hooks/common-hooks'; +import { IParserConfig } from '@/interfaces/database/document'; +import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; import Delimiter from '../delimiter'; import EntityTypesItem from '../entity-types-item'; import ExcelToHtml from '../excel-to-html'; @@ -39,7 +39,7 @@ interface IProps extends Omit { ) => void; showModal?(): void; parserId: string; - parserConfig: IKnowledgeFileParserConfig; + parserConfig: IParserConfig; documentExtension: string; documentId: string; } @@ -115,7 +115,7 @@ const ChunkMethodModal: React.FC = ({ useEffect(() => { if (visible) { const pages = - parserConfig.pages?.map((x) => ({ from: x[0], to: x[1] })) ?? []; + parserConfig?.pages?.map((x) => ({ from: x[0], to: x[1] })) ?? []; form.setFieldsValue({ pages: pages.length > 0 ? pages : [{ from: 1, to: 1024 }], parser_config: omit(parserConfig, 'pages'), diff --git a/web/src/components/file-icon/index.tsx b/web/src/components/file-icon/index.tsx index 6a84fc78e..e63b91126 100644 --- a/web/src/components/file-icon/index.tsx +++ b/web/src/components/file-icon/index.tsx @@ -1,7 +1,8 @@ import { getExtension } from '@/utils/document-util'; import SvgIcon from '../svg-icon'; -import { useSelectFileThumbnails } from '@/hooks/knowledge-hooks'; +import { useFetchDocumentThumbnailsByIds } from '@/hooks/document-hooks'; +import { useEffect } from 'react'; import styles from './index.less'; interface IProps { @@ -11,10 +12,15 @@ interface IProps { const FileIcon = ({ name, id }: IProps) => { const fileExtension = getExtension(name); - // TODO: replace this line with react query - const fileThumbnails = useSelectFileThumbnails(); + + const { data: fileThumbnails, setDocumentIds } = + useFetchDocumentThumbnailsByIds(); const fileThumbnail = fileThumbnails[id]; + useEffect(() => { + setDocumentIds([id]); + }, [id, setDocumentIds]); + return fileThumbnail ? ( ) : ( diff --git a/web/src/components/message-item/index.tsx b/web/src/components/message-item/index.tsx index 25e6ddc49..bd2db7a4b 100644 --- a/web/src/components/message-item/index.tsx +++ b/web/src/components/message-item/index.tsx @@ -1,7 +1,6 @@ import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg'; import { MessageType } from '@/constants/chat'; import { useSetModalState } from '@/hooks/common-hooks'; -import { useSelectFileThumbnails } from '@/hooks/knowledge-hooks'; import { IReference } from '@/interfaces/database/chat'; import { IChunk } from '@/interfaces/database/knowledge'; import classNames from 'classnames'; @@ -50,7 +49,6 @@ const MessageItem = ({ }: IProps) => { const isAssistant = item.role === MessageType.Assistant; const isUser = item.role === MessageType.User; - const fileThumbnails = useSelectFileThumbnails(); const { data: documentList, setDocumentIds } = useFetchDocumentInfosByIds(); const { data: documentThumbnails, setDocumentIds: setIds } = useFetchDocumentThumbnailsByIds(); @@ -77,12 +75,12 @@ const MessageItem = ({ const ids = item?.doc_ids ?? []; if (ids.length) { setDocumentIds(ids); - const documentIds = ids.filter((x) => !(x in fileThumbnails)); + const documentIds = ids.filter((x) => !(x in documentThumbnails)); if (documentIds.length) { setIds(documentIds); } } - }, [item.doc_ids, setDocumentIds, setIds, fileThumbnails]); + }, [item.doc_ids, setDocumentIds, setIds, documentThumbnails]); return (
{ // TODO: const fileThumbnail = - documentThumbnails[item.id] || fileThumbnails[item.id]; + documentThumbnails[item.id] || documentThumbnails[item.id]; const fileExtension = getExtension(item.name); return ( diff --git a/web/src/hooks/document-hooks.ts b/web/src/hooks/document-hooks.ts index 8f41a049b..8c952e258 100644 --- a/web/src/hooks/document-hooks.ts +++ b/web/src/hooks/document-hooks.ts @@ -1,17 +1,24 @@ import { IDocumentInfo } from '@/interfaces/database/document'; -import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge'; +import { IChunk } from '@/interfaces/database/knowledge'; import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; +import i18n from '@/locales/config'; import chatService from '@/services/chat-service'; import kbService from '@/services/knowledge-service'; import { api_host } from '@/utils/api'; import { buildChunkHighlights } from '@/utils/document-util'; -import { useMutation, useQuery } from '@tanstack/react-query'; -import { UploadFile } from 'antd'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { UploadFile, message } from 'antd'; +import { get } from 'lodash'; import { useCallback, useMemo, useState } from 'react'; import { IHighlight } from 'react-pdf-highlighter'; -import { useDispatch, useSelector } from 'umi'; -import { useGetKnowledgeSearchParams } from './route-hook'; -import { useOneNamespaceEffectsLoading } from './store-hooks'; +import { + useGetPaginationWithRouter, + useHandleSearchChange, +} from './logic-hooks'; +import { + useGetKnowledgeSearchParams, + useSetPaginationParams, +} from './route-hook'; export const useGetDocumentUrl = (documentId?: string) => { const getDocumentUrl = useCallback( @@ -43,219 +50,284 @@ export const useGetChunkHighlights = (selectedChunk: IChunk) => { return { highlights, setWidthAndHeight }; }; -export const useFetchDocumentList = () => { +export const useFetchNextDocumentList = () => { const { knowledgeId } = useGetKnowledgeSearchParams(); + const { searchString, handleInputChange } = useHandleSearchChange(); + const { pagination, setPagination } = useGetPaginationWithRouter(); - const dispatch = useDispatch(); - - const fetchKfList = useCallback(() => { - return dispatch({ - type: 'kFModel/getKfList', - payload: { + const { data, isFetching: loading } = useQuery<{ + docs: IDocumentInfo[]; + total: number; + }>({ + queryKey: ['fetchDocumentList', searchString, pagination], + initialData: { docs: [], total: 0 }, + refetchInterval: 15000, + queryFn: async () => { + const ret = await kbService.get_document_list({ kb_id: knowledgeId, - }, - }); - }, [dispatch, knowledgeId]); - - return fetchKfList; -}; - -export const useSetDocumentStatus = () => { - const dispatch = useDispatch(); - const { knowledgeId } = useGetKnowledgeSearchParams(); - - const setDocumentStatus = useCallback( - (status: boolean, documentId: string) => { - dispatch({ - type: 'kFModel/updateDocumentStatus', - payload: { - doc_id: documentId, - status: Number(status), - kb_id: knowledgeId, - }, + keywords: searchString, + page_size: pagination.pageSize, + page: pagination.current, }); + if (ret.data.retcode === 0) { + return ret.data.data; + } + + return { + docs: [], + total: 0, + }; }, - [dispatch, knowledgeId], + }); + + const onInputChange: React.ChangeEventHandler = useCallback( + (e) => { + setPagination({ page: 1 }); + handleInputChange(e); + }, + [handleInputChange, setPagination], ); - return setDocumentStatus; + return { + loading, + searchString, + documents: data.docs, + pagination: { ...pagination, total: data?.total }, + handleInputChange: onInputChange, + setPagination, + }; }; -export const useSelectDocumentList = () => { - const list: IKnowledgeFile[] = useSelector( - (state: any) => state.kFModel.data, - ); - return list; -}; +export const useSetNextDocumentStatus = () => { + const queryClient = useQueryClient(); -export const useSaveDocumentName = () => { - const dispatch = useDispatch(); - const { knowledgeId } = useGetKnowledgeSearchParams(); - - const saveName = useCallback( - (documentId: string, name: string) => { - return dispatch({ - type: 'kFModel/document_rename', - payload: { - doc_id: documentId, - name: name, - kb_id: knowledgeId, - }, + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: ['updateDocumentStatus'], + mutationFn: async ({ + status, + documentId, + }: { + status: boolean; + documentId: string; + }) => { + const { data } = await kbService.document_change_status({ + doc_id: documentId, + status: Number(status), }); + if (data.retcode === 0) { + message.success(i18n.t('message.modified')); + queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); + } + return data; }, - [dispatch, knowledgeId], - ); + }); - return saveName; + return { setDocumentStatus: mutateAsync, data, loading }; }; -export const useCreateDocument = () => { - const dispatch = useDispatch(); +export const useSaveNextDocumentName = () => { + const queryClient = useQueryClient(); + + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: ['saveDocumentName'], + mutationFn: async ({ + name, + documentId, + }: { + name: string; + documentId: string; + }) => { + const { data } = await kbService.document_rename({ + doc_id: documentId, + name: name, + }); + if (data.retcode === 0) { + message.success(i18n.t('message.renamed')); + queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); + } + return data.retcode; + }, + }); + + return { loading, saveName: mutateAsync, data }; +}; + +export const useCreateNextDocument = () => { + const { knowledgeId } = useGetKnowledgeSearchParams(); + const { setPaginationParams, page } = useSetPaginationParams(); + const queryClient = useQueryClient(); + + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: ['createDocument'], + mutationFn: async (name: string) => { + const { data } = await kbService.document_create({ + name, + kb_id: knowledgeId, + }); + if (data.retcode === 0) { + if (page === 1) { + queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); + } else { + setPaginationParams(); // fetch document list + } + + message.success(i18n.t('message.created')); + } + return data.retcode; + }, + }); + + return { createDocument: mutateAsync, loading, data }; +}; + +export const useSetNextDocumentParser = () => { + const queryClient = useQueryClient(); + + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: ['setDocumentParser'], + mutationFn: async ({ + parserId, + documentId, + parserConfig, + }: { + parserId: string; + documentId: string; + parserConfig: IChangeParserConfigRequestBody; + }) => { + const { data } = await kbService.document_change_parser({ + parser_id: parserId, + doc_id: documentId, + parser_config: parserConfig, + }); + if (data.retcode === 0) { + queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); + + message.success(i18n.t('message.modified')); + } + return data.retcode; + }, + }); + + return { setDocumentParser: mutateAsync, data, loading }; +}; + +export const useUploadNextDocument = () => { + const queryClient = useQueryClient(); const { knowledgeId } = useGetKnowledgeSearchParams(); - const createDocument = useCallback( - (name: string) => { + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: ['uploadDocument'], + mutationFn: async (fileList: UploadFile[]) => { + const formData = new FormData(); + formData.append('kb_id', knowledgeId); + fileList.forEach((file: any) => { + formData.append('file', file); + }); + try { - return dispatch({ - type: 'kFModel/document_create', - payload: { - name, - kb_id: knowledgeId, - }, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); + const ret = await kbService.document_upload(formData); + const retcode = get(ret, 'data.retcode'); + if (retcode === 0) { + message.success(i18n.t('message.uploaded')); + } + + if (retcode === 0 || retcode === 500) { + queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); + } + return ret?.data; + } catch (error) { + console.warn(error); + return {}; } }, - [dispatch, knowledgeId], - ); + }); - return createDocument; + return { uploadDocument: mutateAsync, loading, data }; }; -export const useSetDocumentParser = () => { - const dispatch = useDispatch(); +export const useNextWebCrawl = () => { const { knowledgeId } = useGetKnowledgeSearchParams(); - const setDocumentParser = useCallback( - ( - parserId: string, - documentId: string, - parserConfig: IChangeParserConfigRequestBody, - ) => { - try { - return dispatch({ - type: 'kFModel/document_change_parser', - payload: { - parser_id: parserId, - doc_id: documentId, - kb_id: knowledgeId, - parser_config: parserConfig, - }, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }, - [dispatch, knowledgeId], - ); + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: ['webCrawl'], + mutationFn: async ({ name, url }: { name: string; url: string }) => { + const formData = new FormData(); + formData.append('name', name); + formData.append('url', url); + formData.append('kb_id', knowledgeId); - return setDocumentParser; + const ret = await kbService.web_crawl(formData); + const retcode = get(ret, 'data.retcode'); + if (retcode === 0) { + message.success(i18n.t('message.uploaded')); + } + + return retcode; + }, + }); + + return { + data, + loading, + webCrawl: mutateAsync, + }; }; -export const useRemoveDocument = () => { - const dispatch = useDispatch(); - const { knowledgeId } = useGetKnowledgeSearchParams(); +export const useRunNextDocument = () => { + const queryClient = useQueryClient(); - const removeDocument = useCallback( - (documentIds: string[]) => { - try { - return dispatch({ - type: 'kFModel/document_rm', - payload: { - doc_id: documentIds, - kb_id: knowledgeId, - }, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: ['runDocumentByIds'], + mutationFn: async ({ + documentIds, + run, + }: { + documentIds: string[]; + run: number; + }) => { + const ret = await kbService.document_run({ + doc_ids: documentIds, + run, + }); + const retcode = get(ret, 'data.retcode'); + if (retcode === 0) { + queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); + message.success(i18n.t('message.operated')); } + + return retcode; }, - [dispatch, knowledgeId], - ); + }); - return removeDocument; -}; - -export const useUploadDocument = () => { - const dispatch = useDispatch(); - const { knowledgeId } = useGetKnowledgeSearchParams(); - - const uploadDocument = useCallback( - (fileList: UploadFile[]) => { - try { - return dispatch({ - type: 'kFModel/upload_document', - payload: { - fileList, - kb_id: knowledgeId, - }, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }, - [dispatch, knowledgeId], - ); - - return uploadDocument; -}; - -export const useWebCrawl = () => { - const dispatch = useDispatch(); - const { knowledgeId } = useGetKnowledgeSearchParams(); - return useCallback( - (name: string, url: string) => { - try { - return dispatch({ - type: 'kFModel/web_crawl', - payload: { - name, - url, - kb_id: knowledgeId, - }, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }, - [dispatch], - ); -}; - -export const useRunDocument = () => { - const dispatch = useDispatch(); - - const runDocumentByIds = useCallback( - (payload: any) => { - try { - return dispatch({ - type: 'kFModel/document_run', - payload, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }, - [dispatch], - ); - - return runDocumentByIds; -}; - -export const useSelectRunDocumentLoading = () => { - const loading = useOneNamespaceEffectsLoading('kFModel', ['document_run']); - return loading; + return { runDocumentByIds: mutateAsync, loading, data }; }; export const useFetchDocumentInfosByIds = () => { @@ -296,19 +368,20 @@ export const useFetchDocumentThumbnailsByIds = () => { }; export const useRemoveNextDocument = () => { - // const queryClient = useQueryClient(); + const queryClient = useQueryClient(); const { data, isPending: loading, mutateAsync, } = useMutation({ mutationKey: ['removeDocument'], - mutationFn: async (documentId: string) => { - const data = await kbService.document_rm({ doc_id: documentId }); - // if (data.retcode === 0) { - // queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] }); - // } - return data; + mutationFn: async (documentIds: string | string[]) => { + const { data } = await kbService.document_rm({ doc_id: documentIds }); + if (data.retcode === 0) { + message.success(i18n.t('message.deleted')); + queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); + } + return data.retcode; }, }); diff --git a/web/src/hooks/file-manager-hooks.ts b/web/src/hooks/file-manager-hooks.ts index 8e79e72ff..1ae86786d 100644 --- a/web/src/hooks/file-manager-hooks.ts +++ b/web/src/hooks/file-manager-hooks.ts @@ -61,8 +61,7 @@ export const useFetchFileList = (): ResponseType & IListResult => { ], initialData: {}, gcTime: 0, - queryFn: async (params: any) => { - console.info(params); + queryFn: async () => { const { data } = await fileManagerService.listFile({ parent_id: id, keywords: searchString, diff --git a/web/src/hooks/knowledge-hooks.ts b/web/src/hooks/knowledge-hooks.ts index 103260047..69cd1e946 100644 --- a/web/src/hooks/knowledge-hooks.ts +++ b/web/src/hooks/knowledge-hooks.ts @@ -1,4 +1,3 @@ -import { useShowDeleteConfirm } from '@/hooks/common-hooks'; import { ResponsePostType } from '@/interfaces/database/base'; import { IKnowledge, ITestingResult } from '@/interfaces/database/knowledge'; import i18n from '@/locales/config'; @@ -11,8 +10,7 @@ import { useQueryClient, } from '@tanstack/react-query'; import { message } from 'antd'; -import { useCallback, useEffect } from 'react'; -import { useDispatch, useSearchParams, useSelector } from 'umi'; +import { useSearchParams } from 'umi'; import { useSetPaginationParams } from './route-hook'; export const useKnowledgeBaseId = (): string => { @@ -22,32 +20,6 @@ export const useKnowledgeBaseId = (): string => { return knowledgeBaseId || ''; }; -export const useDeleteDocumentById = (): { - removeDocument: (documentId: string) => Promise; -} => { - const dispatch = useDispatch(); - const knowledgeBaseId = useKnowledgeBaseId(); - const showDeleteConfirm = useShowDeleteConfirm(); - - const removeDocument = (documentId: string) => () => { - return dispatch({ - type: 'kFModel/document_rm', - payload: { - doc_id: documentId, - kb_id: knowledgeBaseId, - }, - }); - }; - - const onRmDocument = (documentId: string): Promise => { - return showDeleteConfirm({ onOk: removeDocument(documentId) }); - }; - - return { - removeDocument: onRmDocument, - }; -}; - export const useFetchKnowledgeBaseConfiguration = () => { const knowledgeBaseId = useKnowledgeBaseId(); @@ -132,37 +104,6 @@ export const useDeleteKnowledge = () => { return { data, loading, deleteKnowledge: mutateAsync }; }; -export const useSelectFileThumbnails = () => { - const fileThumbnails: Record = useSelector( - (state: any) => state.kFModel.fileThumbnails, - ); - - return fileThumbnails; -}; - -export const useFetchFileThumbnails = (docIds?: Array) => { - const dispatch = useDispatch(); - const fileThumbnails = useSelectFileThumbnails(); - - const fetchFileThumbnails = useCallback( - (docIds: Array) => { - dispatch({ - type: 'kFModel/fetch_document_thumbnails', - payload: { doc_ids: docIds.join(',') }, - }); - }, - [dispatch], - ); - - useEffect(() => { - if (docIds) { - fetchFileThumbnails(docIds); - } - }, [docIds, fetchFileThumbnails]); - - return { fileThumbnails, fetchFileThumbnails }; -}; - //#region knowledge configuration export const useUpdateKnowledge = () => { diff --git a/web/src/hooks/logic-hooks.ts b/web/src/hooks/logic-hooks.ts index 957de7931..a2199637d 100644 --- a/web/src/hooks/logic-hooks.ts +++ b/web/src/hooks/logic-hooks.ts @@ -1,11 +1,9 @@ import { Authorization } from '@/constants/authorization'; import { MessageType } from '@/constants/chat'; import { LanguageTranslationMap } from '@/constants/common'; -import { Pagination } from '@/interfaces/common'; import { ResponseType } from '@/interfaces/database/base'; import { IAnswer, Message } from '@/interfaces/database/chat'; import { IKnowledgeFile } from '@/interfaces/database/knowledge'; -import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; import { IClientConversation, IMessage } from '@/pages/chat/interface'; import api from '@/utils/api'; import { getAuthorization } from '@/utils/authorization-util'; @@ -23,45 +21,11 @@ import { useState, } from 'react'; import { useTranslation } from 'react-i18next'; -import { useDispatch } from 'umi'; import { v4 as uuid } from 'uuid'; -import { useSetModalState, useTranslate } from './common-hooks'; -import { useSetDocumentParser } from './document-hooks'; +import { useTranslate } from './common-hooks'; import { useSetPaginationParams } from './route-hook'; -import { useOneNamespaceEffectsLoading } from './store-hooks'; import { useFetchTenantInfo, useSaveSetting } from './user-setting-hooks'; -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 = () => { const [currentRecord, setCurrentRecord] = useState({} as T); @@ -170,28 +134,6 @@ export const useGetPagination = () => { }; }; -export const useSetPagination = (namespace: string) => { - const dispatch = useDispatch(); - - const setPagination = useCallback( - (pageNumber = 1, pageSize?: number) => { - const pagination: Pagination = { - current: pageNumber, - } as Pagination; - if (pageSize) { - pagination.pageSize = pageSize; - } - dispatch({ - type: `${namespace}/setPagination`, - payload: pagination, - }); - }, - [dispatch, namespace], - ); - - return setPagination; -}; - export interface AppConf { appName: string; } diff --git a/web/src/hooks/store-hooks.ts b/web/src/hooks/store-hooks.ts deleted file mode 100644 index ddd332dc0..000000000 --- a/web/src/hooks/store-hooks.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { getOneNamespaceEffectsLoading } from '@/utils/store-util'; -import { useSelector } from 'umi'; - -// Get the loading status of given effects under a certain namespace -export const useOneNamespaceEffectsLoading = ( - namespace: string, - effectNames: Array, -) => { - const effects = useSelector((state: any) => state.loading.effects); - return getOneNamespaceEffectsLoading(namespace, effects, effectNames); -}; diff --git a/web/src/interfaces/database/document.ts b/web/src/interfaces/database/document.ts index 626aea4ec..7b1bce95e 100644 --- a/web/src/interfaces/database/document.ts +++ b/web/src/interfaces/database/document.ts @@ -1,3 +1,5 @@ +import { RunningStatus } from '@/constants/knowledge'; + export interface IDocumentInfo { chunk_num: number; create_date: string; @@ -7,13 +9,13 @@ export interface IDocumentInfo { kb_id: string; location: string; name: string; - parser_config: Parserconfig; + parser_config: IParserConfig; parser_id: string; process_begin_at: null; process_duation: number; progress: number; progress_msg: string; - run: string; + run: RunningStatus; size: number; source_type: string; status: string; @@ -24,9 +26,11 @@ export interface IDocumentInfo { update_time: number; } -interface Parserconfig { - chunk_token_num: number; +export interface IParserConfig { + delimiter: string; + html4excel: boolean; layout_recognize: boolean; + pages: any[]; raptor: Raptor; } diff --git a/web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx b/web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx index f9457ac85..0b003f103 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx @@ -5,11 +5,10 @@ import { ReactComponent as EnableIcon } from '@/assets/svg/enable.svg'; import { ReactComponent as RunIcon } from '@/assets/svg/run.svg'; import { useShowDeleteConfirm, useTranslate } from '@/hooks/common-hooks'; import { - useRemoveDocument, - useRunDocument, - useSetDocumentStatus, + useRemoveNextDocument, + useRunNextDocument, + useSetNextDocumentStatus, } from '@/hooks/document-hooks'; -import { useGetKnowledgeSearchParams } from '@/hooks/route-hook'; import { DownOutlined, FileOutlined, @@ -19,11 +18,7 @@ import { } from '@ant-design/icons'; import { Button, Dropdown, Flex, Input, MenuProps, Space } from 'antd'; import { useCallback, useMemo } from 'react'; -import { - useFetchDocumentListOnMount, - useGetPagination, - useHandleSearchChange, -} from './hooks'; + import styles from './index.less'; interface IProps { @@ -31,23 +26,22 @@ interface IProps { showCreateModal(): void; showWebCrawlModal(): void; showDocumentUploadModal(): void; + searchString: string; + handleInputChange: React.ChangeEventHandler; } const DocumentToolbar = ({ + searchString, selectedRowKeys, showCreateModal, - showWebCrawlModal, showDocumentUploadModal, + handleInputChange, }: IProps) => { const { t } = useTranslate('knowledgeDetails'); - const { fetchDocumentList } = useFetchDocumentListOnMount(); - const { setPagination, searchString } = useGetPagination(fetchDocumentList); - const { handleInputChange } = useHandleSearchChange(setPagination); - const removeDocument = useRemoveDocument(); + const { removeDocument } = useRemoveNextDocument(); const showDeleteConfirm = useShowDeleteConfirm(); - const runDocumentByIds = useRunDocument(); - const { knowledgeId } = useGetKnowledgeSearchParams(); - const changeStatus = useSetDocumentStatus(); + const { runDocumentByIds } = useRunNextDocument(); + const { setDocumentStatus } = useSetNextDocumentStatus(); const actionItems: MenuProps['items'] = useMemo(() => { return [ @@ -66,19 +60,6 @@ const DocumentToolbar = ({ ), }, { type: 'divider' }, - // { - // key: '2', - // onClick: showWebCrawlModal, - // label: ( - //
- // - //
- // ), - // }, - { type: 'divider' }, { key: '3', onClick: showCreateModal, @@ -105,12 +86,11 @@ const DocumentToolbar = ({ const runDocument = useCallback( (run: number) => { runDocumentByIds({ - doc_ids: selectedRowKeys, + documentIds: selectedRowKeys, run, - knowledgeBaseId: knowledgeId, }); }, - [runDocumentByIds, selectedRowKeys, knowledgeId], + [runDocumentByIds, selectedRowKeys], ); const handleRunClick = useCallback(() => { @@ -124,10 +104,10 @@ const DocumentToolbar = ({ const onChangeStatus = useCallback( (enabled: boolean) => { selectedRowKeys.forEach((id) => { - changeStatus(enabled, id); + setDocumentStatus({ status: enabled, documentId: id }); }); }, - [selectedRowKeys, changeStatus], + [selectedRowKeys, setDocumentStatus], ); const handleEnableClick = useCallback(() => { diff --git a/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts b/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts index f4d6ec921..1d1c79739 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts +++ b/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts @@ -1,104 +1,20 @@ -import { useSetModalState, useTranslate } from '@/hooks/common-hooks'; +import { useSetModalState } from '@/hooks/common-hooks'; import { - useCreateDocument, - useFetchDocumentList, - useRunDocument, - useSaveDocumentName, - useSelectRunDocumentLoading, - useSetDocumentParser, - useUploadDocument, - useWebCrawl, + useCreateNextDocument, + useNextWebCrawl, + useRunNextDocument, + useSaveNextDocumentName, + useSetNextDocumentParser, + useUploadNextDocument, } from '@/hooks/document-hooks'; import { useGetKnowledgeSearchParams } from '@/hooks/route-hook'; -import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks'; -import { Pagination } from '@/interfaces/common'; import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; import { getUnSupportedFilesCount } from '@/utils/document-util'; -import { PaginationProps, UploadFile } from 'antd'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { useDispatch, useNavigate, useSelector } from 'umi'; +import { UploadFile } from 'antd'; +import { useCallback, useState } from 'react'; +import { useNavigate } from 'umi'; import { KnowledgeRouteKey } from './constant'; -export const useFetchDocumentListOnMount = () => { - const { knowledgeId } = useGetKnowledgeSearchParams(); - const fetchDocumentList = useFetchDocumentList(); - const dispatch = useDispatch(); - - useEffect(() => { - if (knowledgeId) { - fetchDocumentList(); - dispatch({ - type: 'kFModel/pollGetDocumentList-start', - payload: knowledgeId, - }); - } - return () => { - dispatch({ - type: 'kFModel/pollGetDocumentList-stop', - }); - }; - }, [knowledgeId, dispatch, fetchDocumentList]); - - return { fetchDocumentList }; -}; - -export const useGetPagination = (fetchDocumentList: () => void) => { - const dispatch = useDispatch(); - const kFModel = useSelector((state: any) => state.kFModel); - const { t } = useTranslate('common'); - - const setPagination = useCallback( - (pageNumber = 1, pageSize?: number) => { - const pagination: Pagination = { - current: pageNumber, - } as Pagination; - if (pageSize) { - pagination.pageSize = pageSize; - } - dispatch({ - type: 'kFModel/setPagination', - payload: pagination, - }); - }, - [dispatch], - ); - - const onPageChange: PaginationProps['onChange'] = useCallback( - (pageNumber: number, pageSize: number) => { - setPagination(pageNumber, pageSize); - fetchDocumentList(); - }, - [fetchDocumentList, setPagination], - ); - - const pagination: PaginationProps = useMemo(() => { - return { - showQuickJumper: true, - total: kFModel.total, - showSizeChanger: true, - current: kFModel.pagination.current, - pageSize: kFModel.pagination.pageSize, - pageSizeOptions: [1, 2, 10, 20, 50, 100], - onChange: onPageChange, - showTotal: (total) => `${t('total')} ${total}`, - }; - }, [kFModel, onPageChange, t]); - - return { - pagination, - setPagination, - total: kFModel.total, - searchString: kFModel.searchString, - }; -}; - -export const useSelectDocumentListLoading = () => { - return useOneNamespaceEffectsLoading('kFModel', [ - 'getKfList', - 'updateDocumentStatus', - ]); -}; - export const useNavigateToOtherPage = () => { const navigate = useNavigate(); const { knowledgeId } = useGetKnowledgeSearchParams(); @@ -119,43 +35,18 @@ export const useNavigateToOtherPage = () => { return { linkToUploadPage, toChunk }; }; -export const useHandleSearchChange = (setPagination: () => void) => { - const dispatch = useDispatch(); - const { knowledgeId } = useGetKnowledgeSearchParams(); - - const throttledGetDocumentList = useCallback(() => { - dispatch({ - type: 'kFModel/throttledGetDocumentList', - payload: knowledgeId, - }); - }, [dispatch, knowledgeId]); - - const handleInputChange = useCallback( - (e: React.ChangeEvent) => { - const value = e.target.value; - dispatch({ type: 'kFModel/setSearchString', payload: value }); - setPagination(); - throttledGetDocumentList(); - }, - [setPagination, throttledGetDocumentList, dispatch], - ); - - return { handleInputChange }; -}; - export const useRenameDocument = (documentId: string) => { - const saveName = useSaveDocumentName(); + const { saveName, loading } = useSaveNextDocumentName(); const { visible: renameVisible, hideModal: hideRenameModal, showModal: showRenameModal, } = useSetModalState(); - const loading = useOneNamespaceEffectsLoading('kFModel', ['document_rename']); const onRenameOk = useCallback( async (name: string) => { - const ret = await saveName(documentId, name); + const ret = await saveName({ documentId, name }); if (ret === 0) { hideRenameModal(); } @@ -173,14 +64,13 @@ export const useRenameDocument = (documentId: string) => { }; export const useCreateEmptyDocument = () => { - const createDocument = useCreateDocument(); + const { createDocument, loading } = useCreateNextDocument(); const { visible: createVisible, hideModal: hideCreateModal, showModal: showCreateModal, } = useSetModalState(); - const loading = useOneNamespaceEffectsLoading('kFModel', ['document_create']); const onCreateOk = useCallback( async (name: string) => { @@ -202,20 +92,21 @@ export const useCreateEmptyDocument = () => { }; export const useChangeDocumentParser = (documentId: string) => { - const setDocumentParser = useSetDocumentParser(); + const { setDocumentParser, loading } = useSetNextDocumentParser(); 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); + const ret = await setDocumentParser({ + parserId, + documentId, + parserConfig, + }); if (ret === 0) { hideChangeParserModal(); } @@ -251,18 +142,21 @@ export const useHandleUploadDocument = () => { hideModal: hideDocumentUploadModal, showModal: showDocumentUploadModal, } = useSetModalState(); - const uploadDocument = useUploadDocument(); + const { uploadDocument, loading } = useUploadNextDocument(); const onDocumentUploadOk = useCallback( async (fileList: UploadFile[]): Promise => { if (fileList.length > 0) { const ret: any = await uploadDocument(fileList); - const count = getUnSupportedFilesCount(ret.retmsg); + if (typeof ret?.retmsg !== 'string') { + return; + } + const count = getUnSupportedFilesCount(ret?.retmsg); /// 500 error code indicates that some file types are not supported - let retcode = ret.retcode; + let retcode = ret?.retcode; if ( - ret.retcode === 0 || - (ret.retcode === 500 && count !== fileList.length) // Some files were not uploaded successfully, but some were uploaded successfully. + ret?.retcode === 0 || + (ret?.retcode === 500 && count !== fileList.length) // Some files were not uploaded successfully, but some were uploaded successfully. ) { retcode = 0; hideDocumentUploadModal(); @@ -273,8 +167,6 @@ export const useHandleUploadDocument = () => { [uploadDocument, hideDocumentUploadModal], ); - const loading = useOneNamespaceEffectsLoading('kFModel', ['upload_document']); - return { documentUploadLoading: loading, onDocumentUploadOk, @@ -290,11 +182,11 @@ export const useHandleWebCrawl = () => { hideModal: hideWebCrawlUploadModal, showModal: showWebCrawlUploadModal, } = useSetModalState(); - const webCrawl = useWebCrawl(); + const { webCrawl, loading } = useNextWebCrawl(); const onWebCrawlUploadOk = useCallback( async (name: string, url: string) => { - const ret = await webCrawl(name, url); + const ret = await webCrawl({ name, url }); if (ret === 0) { hideWebCrawlUploadModal(); return 0; @@ -304,8 +196,6 @@ export const useHandleWebCrawl = () => { [webCrawl, hideWebCrawlUploadModal], ); - const loading = useOneNamespaceEffectsLoading('kFModel', ['web_crawl']); - return { webCrawlUploadLoading: loading, onWebCrawlUploadOk, @@ -316,14 +206,12 @@ export const useHandleWebCrawl = () => { }; export const useHandleRunDocumentByIds = (id: string) => { - const loading = useSelectRunDocumentLoading(); - const runDocumentByIds = useRunDocument(); + const { runDocumentByIds, loading } = useRunNextDocument(); const [currentId, setCurrentId] = useState(''); const isLoading = loading && currentId !== '' && currentId === id; const handleRunDocumentByIds = async ( documentId: string, - knowledgeBaseId: string, isRunning: boolean, ) => { if (isLoading) { @@ -332,9 +220,8 @@ export const useHandleRunDocumentByIds = (id: string) => { setCurrentId(documentId); try { await runDocumentByIds({ - doc_ids: [documentId], + documentIds: [documentId], run: isRunning ? 2 : 1, - knowledgeBaseId, }); setCurrentId(''); } catch (error) { diff --git a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx index fc8e8c0c9..fa60adf30 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx @@ -1,12 +1,11 @@ import ChunkMethodModal from '@/components/chunk-method-modal'; import SvgIcon from '@/components/svg-icon'; import { - useSelectDocumentList, - useSetDocumentStatus, + useFetchNextDocumentList, + useSetNextDocumentStatus, } from '@/hooks/document-hooks'; import { useSetSelectedRecord } from '@/hooks/logic-hooks'; import { useSelectParserList } from '@/hooks/user-setting-hooks'; -import { IKnowledgeFile } from '@/interfaces/database/knowledge'; import { getExtension } from '@/utils/document-util'; import { Divider, Flex, Switch, Table, Typography } from 'antd'; import type { ColumnsType } from 'antd/es/table'; @@ -16,8 +15,6 @@ import DocumentToolbar from './document-toolbar'; import { useChangeDocumentParser, useCreateEmptyDocument, - useFetchDocumentListOnMount, - useGetPagination, useGetRowSelection, useHandleUploadDocument, useHandleWebCrawl, @@ -30,19 +27,19 @@ import RenameModal from './rename-modal'; import WebCrawlModal from './web-crawl-modal'; import FileUploadModal from '@/components/file-upload-modal'; +import { IDocumentInfo } from '@/interfaces/database/document'; import { formatDate } from '@/utils/date'; import styles from './index.less'; const { Text } = Typography; const KnowledgeFile = () => { - const data = useSelectDocumentList(); - const { fetchDocumentList } = useFetchDocumentListOnMount(); + const { searchString, documents, pagination, handleInputChange } = + useFetchNextDocumentList(); const parserList = useSelectParserList(); - const { pagination } = useGetPagination(fetchDocumentList); - const onChangeStatus = useSetDocumentStatus(); + const { setDocumentStatus } = useSetNextDocumentStatus(); const { toChunk } = useNavigateToOtherPage(); - const { currentRecord, setRecord } = useSetSelectedRecord(); + const { currentRecord, setRecord } = useSetSelectedRecord(); const { renameLoading, onRenameOk, @@ -84,7 +81,7 @@ const KnowledgeFile = () => { const rowSelection = useGetRowSelection(); - const columns: ColumnsType = [ + const columns: ColumnsType = [ { title: t('name'), dataIndex: 'name', @@ -138,7 +135,7 @@ const KnowledgeFile = () => { { - onChangeStatus(e, id); + setDocumentStatus({ status: e, documentId: id }); }} /> @@ -181,12 +178,13 @@ const KnowledgeFile = () => { showCreateModal={showCreateModal} showWebCrawlModal={showWebCrawlUploadModal} showDocumentUploadModal={showDocumentUploadModal} + searchString={searchString} + handleInputChange={handleInputChange} > ; - fileThumbnails: Record; -} - -const model: DvaModel = { - namespace: 'kFModel', - state: { - tenantIfo: {}, - data: [], - total: 0, - currentRecord: null, - searchString: '', - pagination: { - current: 1, - pageSize: 10, - }, - fileThumbnails: {} as Record, - }, - reducers: { - updateState(state, { payload }) { - return { - ...state, - ...payload, - }; - }, - - setCurrentRecord(state, { payload }) { - return { ...state, currentRecord: payload }; - }, - setSearchString(state, { payload }) { - return { ...state, searchString: payload }; - }, - setPagination(state, { payload }) { - return { ...state, pagination: { ...state.pagination, ...payload } }; - }, - setFileThumbnails(state, { payload }) { - return { ...state, fileThumbnails: payload }; - }, - }, - effects: { - *createKf({ payload = {} }, { call }) { - const { data } = yield call(kbService.createKb, payload); - const { retcode } = data; - if (retcode === 0) { - message.success(i18n.t('message.created')); - } - }, - *updateKf({ payload = {} }, { call }) { - const { data } = yield call(kbService.updateKb, payload); - const { retcode } = data; - if (retcode === 0) { - message.success(i18n.t('message.modified')); - } - }, - *getKfDetail({ payload = {} }, { call }) { - const { data } = yield call(kbService.get_kb_detail, payload); - }, - *getKfList({ payload = {} }, { call, put, select }) { - const state: KFModelState = yield select((state: any) => state.kFModel); - const requestBody = { - ...payload, - page: state.pagination.current, - page_size: state.pagination.pageSize, - }; - if (state.searchString) { - requestBody['keywords'] = state.searchString; - } - const { data } = yield call(kbService.get_document_list, requestBody); - const { retcode, data: res } = data; - - if (retcode === 0) { - yield put({ - type: 'updateState', - payload: { - data: res.docs, - total: res.total, - }, - }); - } - }, - throttledGetDocumentList: [ - function* ({ payload }, { call, put }) { - yield put({ type: 'getKfList', payload: { kb_id: payload } }); - }, - { type: 'throttle', ms: 1000 }, // TODO: Provide type support for this effect - ], - pollGetDocumentList: [ - function* ({ payload }, { call, put }) { - yield put({ type: 'getKfList', payload: { kb_id: payload } }); - }, - { type: 'poll', delay: 15000 }, // TODO: Provide type support for this effect - ], - *updateDocumentStatus({ payload = {} }, { call, put }) { - const { data } = yield call( - kbService.document_change_status, - pick(payload, ['doc_id', 'status']), - ); - const { retcode } = data; - if (retcode === 0) { - message.success(i18n.t('message.modified')); - yield put({ - type: 'getKfList', - payload: { kb_id: payload.kb_id }, - }); - } - }, - *document_rm({ payload = {} }, { call, put }) { - const { data } = yield call(kbService.document_rm, { - doc_id: payload.doc_id, - }); - const { retcode } = data; - if (retcode === 0) { - message.success(i18n.t('message.deleted')); - yield put({ - type: 'getKfList', - payload: { kb_id: payload.kb_id }, - }); - } - return retcode; - }, - *document_rename({ payload = {} }, { call, put }) { - const { data } = yield call( - kbService.document_rename, - omit(payload, ['kb_id']), - ); - const { retcode } = data; - if (retcode === 0) { - message.success(i18n.t('message.renamed')); - - yield put({ - type: 'getKfList', - payload: { kb_id: payload.kb_id }, - }); - } - - return retcode; - }, - *document_create({ payload = {} }, { call, put }) { - const { data } = yield call(kbService.document_create, payload); - const { retcode } = data; - if (retcode === 0) { - yield put({ - type: 'getKfList', - payload: { kb_id: payload.kb_id }, - }); - - message.success(i18n.t('message.created')); - } - return retcode; - }, - *document_run({ payload = {} }, { call, put }) { - const { data } = yield call( - kbService.document_run, - omit(payload, ['knowledgeBaseId']), - ); - const { retcode } = data; - if (retcode === 0) { - if (payload.knowledgeBaseId) { - yield put({ - type: 'getKfList', - payload: { kb_id: payload.knowledgeBaseId }, - }); - } - message.success(i18n.t('message.operated')); - } - return retcode; - }, - *document_change_parser({ payload = {} }, { call, put }) { - const { data } = yield call( - kbService.document_change_parser, - omit(payload, ['kb_id']), - ); - const { retcode } = data; - if (retcode === 0) { - yield put({ - type: 'getKfList', - payload: { kb_id: payload.kb_id }, - }); - - message.success(i18n.t('message.modified')); - } - return retcode; - }, - *fetch_document_thumbnails({ payload = {} }, { call, put }) { - const { data } = yield call(kbService.document_thumbnails, payload); - if (data.retcode === 0) { - yield put({ type: 'setFileThumbnails', payload: data.data }); - } - }, - *fetch_document_file({ payload = {} }, { call }) { - const documentId = payload; - try { - const ret = yield call(getDocumentFile, documentId); - return ret; - } catch (error) { - console.warn(error); - } - }, - *upload_document({ payload = {} }, { call, put }) { - const fileList = payload.fileList; - const formData = new FormData(); - formData.append('kb_id', payload.kb_id); - fileList.forEach((file: any) => { - formData.append('file', file); - }); - - const ret = yield call(kbService.document_upload, formData); - - const succeed = ret?.data?.retcode === 0; - - if (succeed) { - message.success(i18n.t('message.uploaded')); - } - if (succeed || ret?.data?.retcode === 500) { - yield put({ - type: 'getKfList', - payload: { kb_id: payload.kb_id }, - }); - } - return ret?.data; - }, - *web_crawl({ payload = {} }, { call, put }) { - const formData = new FormData(); - formData.append('name', payload.name); - formData.append('url', payload.url); - formData.append('kb_id', payload.kb_id); - - const { data } = yield call(kbService.web_crawl, formData); - - const succeed = data.retcode === 0; - - if (succeed) { - message.success(i18n.t('message.uploaded')); - } - if (succeed || data.retcode === 500) { - yield put({ - type: 'getKfList', - payload: { kb_id: payload.kb_id }, - }); - } - return data.retcode; - }, - }, - subscriptions: { - setup({ dispatch, history }) { - history.listen(({ location }) => { - const state: { from: string } = (location.state ?? { - from: '', - }) as { from: string }; - if ( - state.from === '/knowledge' || // TODO: Just directly determine whether the current page is on the knowledge list page. - location.pathname === '/knowledge/dataset/upload' - ) { - dispatch({ - type: 'setPagination', - payload: { current: 1, pageSize: 10 }, - }); - } - }); - }, - }, -}; -export default model; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx index ad431ba4e..c520be1a7 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx @@ -1,6 +1,6 @@ import { useShowDeleteConfirm, useTranslate } from '@/hooks/common-hooks'; -import { useRemoveDocument } from '@/hooks/document-hooks'; -import { IKnowledgeFile } from '@/interfaces/database/knowledge'; +import { useRemoveNextDocument } from '@/hooks/document-hooks'; +import { IDocumentInfo } from '@/interfaces/database/document'; import { api_host } from '@/utils/api'; import { downloadFile } from '@/utils/file-util'; import { @@ -15,8 +15,8 @@ import { isParserRunning } from '../utils'; import styles from './index.less'; interface IProps { - record: IKnowledgeFile; - setCurrentRecord: (record: IKnowledgeFile) => void; + record: IDocumentInfo; + setCurrentRecord: (record: IDocumentInfo) => void; showRenameModal: () => void; showChangeParserModal: () => void; } @@ -30,7 +30,7 @@ const ParsingActionCell = ({ const documentId = record.id; const isRunning = isParserRunning(record.run); const { t } = useTranslate('knowledgeDetails'); - const removeDocument = useRemoveDocument(); + const { removeDocument } = useRemoveNextDocument(); const showDeleteConfirm = useShowDeleteConfirm(); const onRmDocument = () => { diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx index 1592c417b..ff4a5fb9b 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx @@ -2,7 +2,7 @@ import { ReactComponent as CancelIcon } from '@/assets/svg/cancel.svg'; import { ReactComponent as RefreshIcon } from '@/assets/svg/refresh.svg'; import { ReactComponent as RunIcon } from '@/assets/svg/run.svg'; import { useTranslate } from '@/hooks/common-hooks'; -import { IKnowledgeFile } from '@/interfaces/database/knowledge'; +import { IDocumentInfo } from '@/interfaces/database/document'; import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd'; import classNames from 'classnames'; import { useTranslation } from 'react-i18next'; @@ -21,7 +21,7 @@ const iconMap = { }; interface IProps { - record: IKnowledgeFile; + record: IDocumentInfo; } const PopoverContent = ({ record }: IProps) => { @@ -93,7 +93,7 @@ export const ParsingStatusCell = ({ record }: IProps) => { const label = t(`knowledgeDetails.runningStatus${text}`); const handleOperationIconClick = () => { - handleRunDocumentByIds(record.id, record.kb_id, isRunning); + handleRunDocumentByIds(record.id, isRunning); }; return ( diff --git a/web/src/pages/add-knowledge/index.tsx b/web/src/pages/add-knowledge/index.tsx index 89223ef20..18187cf4e 100644 --- a/web/src/pages/add-knowledge/index.tsx +++ b/web/src/pages/add-knowledge/index.tsx @@ -6,19 +6,17 @@ import { } from '@/hooks/route-hook'; import { Breadcrumb } from 'antd'; import { ItemType } from 'antd/es/breadcrumb/Breadcrumb'; -import { useEffect, useMemo } from 'react'; +import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { Link, Outlet, useDispatch, useLocation } from 'umi'; +import { Link, Outlet } from 'umi'; import Siderbar from './components/knowledge-sidebar'; import { KnowledgeDatasetRouteKey, KnowledgeRouteKey } from './constant'; import styles from './index.less'; const KnowledgeAdding = () => { - const dispatch = useDispatch(); const knowledgeBaseId = useKnowledgeBaseId(); const { t } = useTranslation(); - const location = useLocation(); const activeKey: KnowledgeRouteKey = (useSecondPathName() as KnowledgeRouteKey) || KnowledgeRouteKey.Dataset; @@ -58,23 +56,6 @@ const KnowledgeAdding = () => { return items; }, [activeKey, datasetActiveKey, gotoList, knowledgeBaseId, t]); - useEffect(() => { - const search: string = location.search.slice(1); - const map = search.split('&').reduce>((obj, cur) => { - const [key, value] = cur.split('='); - obj[key] = value; - return obj; - }, {}); - - dispatch({ - type: 'kAModel/updateState', - payload: { - doc_id: undefined, - ...map, - }, - }); - }, [location, dispatch]); - return ( <>
diff --git a/web/src/pages/chat/markdown-content/index.tsx b/web/src/pages/chat/markdown-content/index.tsx index a992d0457..12cc3d005 100644 --- a/web/src/pages/chat/markdown-content/index.tsx +++ b/web/src/pages/chat/markdown-content/index.tsx @@ -1,19 +1,19 @@ import Image from '@/components/image'; import SvgIcon from '@/components/svg-icon'; -import { useSelectFileThumbnails } from '@/hooks/knowledge-hooks'; import { IReference } from '@/interfaces/database/chat'; import { IChunk } from '@/interfaces/database/knowledge'; import { getExtension } from '@/utils/document-util'; import { InfoCircleOutlined } from '@ant-design/icons'; import { Button, Flex, Popover, Space } from 'antd'; import DOMPurify from 'dompurify'; -import { useCallback, useMemo } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import Markdown from 'react-markdown'; import reactStringReplace from 'react-string-replace'; import SyntaxHighlighter from 'react-syntax-highlighter'; import remarkGfm from 'remark-gfm'; import { visitParents } from 'unist-util-visit-parents'; +import { useFetchDocumentThumbnailsByIds } from '@/hooks/document-hooks'; import { useTranslation } from 'react-i18next'; import styles from './index.less'; @@ -34,6 +34,8 @@ const MarkdownContent = ({ clickDocumentButton?: (documentId: string, chunk: IChunk) => void; }) => { const { t } = useTranslation(); + const { setDocumentIds, data: fileThumbnails } = + useFetchDocumentThumbnailsByIds(); const contentWithCursor = useMemo(() => { let text = content; if (text === '') { @@ -42,7 +44,9 @@ const MarkdownContent = ({ return loading ? text?.concat('~~2$$') : text; }, [content, loading, t]); - const fileThumbnails = useSelectFileThumbnails(); + useEffect(() => { + setDocumentIds(reference?.doc_aggs.map((x) => x.doc_id) ?? []); + }, [reference, setDocumentIds]); const handleDocumentButtonClick = useCallback( (documentId: string, chunk: IChunk, isPdf: boolean) => () => { diff --git a/web/src/pages/file-manager/file-toolbar.tsx b/web/src/pages/file-manager/file-toolbar.tsx index cf50de1aa..387cc393b 100644 --- a/web/src/pages/file-manager/file-toolbar.tsx +++ b/web/src/pages/file-manager/file-toolbar.tsx @@ -1,5 +1,10 @@ import { ReactComponent as DeleteIcon } from '@/assets/svg/delete.svg'; +import SvgIcon from '@/components/svg-icon'; import { useTranslate } from '@/hooks/common-hooks'; +import { + IListResult, + useFetchParentFolderList, +} from '@/hooks/file-manager-hooks'; import { DownOutlined, FileTextOutlined, @@ -24,11 +29,6 @@ import { useSelectBreadcrumbItems, } from './hooks'; -import SvgIcon from '@/components/svg-icon'; -import { - IListResult, - useFetchParentFolderList, -} from '@/hooks/file-manager-hooks'; import styles from './index.less'; interface IProps diff --git a/web/typings.d.ts b/web/typings.d.ts index 3741b020f..bd56ed098 100644 --- a/web/typings.d.ts +++ b/web/typings.d.ts @@ -1,20 +1,5 @@ -import { KFModelState } from '@/pages/add-knowledge/components/knowledge-file/model'; - declare module 'lodash'; -function useSelector( - selector: (state: TState) => TSelected, - equalityFn?: (left: TSelected, right: TSelected) => boolean, -): TSelected; - -export interface RootState { - kFModel: KFModelState; -} - declare global { type Nullable = T | null; } - -declare module 'umi' { - export { useSelector }; -}