From 5d0981d046655e6915691935e221fa2b6b07a0b0 Mon Sep 17 00:00:00 2001 From: chanx <1243304602@qq.com> Date: Tue, 25 Nov 2025 19:13:00 +0800 Subject: [PATCH] Refactoring: Integrating the file preview component (#11523) ### What problem does this PR solve? Refactoring: Integrating the file preview component ### Type of change - [x] Refactoring --- .../document-preview/csv-preview.tsx | 0 .../document-preview/doc-preview.tsx | 3 + .../document-preview/document-header.tsx | 0 .../document-preview/excel-preview.tsx | 3 +- .../document-preview}/hooks.ts | 60 +++- .../document-preview/image-preview.tsx | 3 + .../components/document-preview/index.less | 0 .../components/document-preview/index.tsx | 11 +- .../document-preview}/md/index.tsx | 20 +- .../document-preview/pdf-preview.tsx | 36 ++- .../document-preview/ppt-preview.tsx | 0 .../document-preview/txt-preview.tsx | 0 .../document-preview/video-preview.tsx | 0 web/src/constants/common.ts | 2 +- .../components/chunk-result-bar/index.tsx | 80 +++-- .../document-preview/document-header.tsx | 21 -- .../document-preview/excel-preview.tsx | 25 -- .../components/document-preview/hooks.ts | 55 ---- .../document-preview/image-preview.tsx | 74 ----- .../components/knowledge-chunk/index.tsx | 9 +- .../document-preview/csv-preview.tsx | 114 ------- .../document-preview/doc-preview.tsx | 70 ----- .../components/document-preview/hooks.ts | 60 ---- .../components/document-preview/index.less | 13 - .../components/document-preview/index.tsx | 67 ----- .../document-preview/pdf-preview.tsx | 127 -------- .../document-preview/ppt-preview.tsx | 70 ----- .../document-preview/txt-preview.tsx | 56 ---- web/src/pages/dataflow-result/index.tsx | 9 +- web/src/pages/document-viewer/docx/index.less | 282 ------------------ web/src/pages/document-viewer/docx/index.tsx | 25 -- web/src/pages/document-viewer/excel/index.tsx | 19 -- .../document-viewer/file-error/index.less | 4 - .../document-viewer/file-error/index.tsx | 18 +- web/src/pages/document-viewer/index.tsx | 46 +-- web/src/pages/document-viewer/text/index.tsx | 32 -- .../document-preview-modal/index.tsx | 2 +- .../pages/user-setting/data-source/hooks.ts | 22 +- 38 files changed, 216 insertions(+), 1222 deletions(-) rename web/src/{pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk => }/components/document-preview/csv-preview.tsx (100%) rename web/src/{pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk => }/components/document-preview/doc-preview.tsx (91%) rename web/src/{pages/dataflow-result => }/components/document-preview/document-header.tsx (100%) rename web/src/{pages/dataflow-result => }/components/document-preview/excel-preview.tsx (83%) rename web/src/{pages/document-viewer => components/document-preview}/hooks.ts (62%) rename web/src/{pages/dataflow-result => }/components/document-preview/image-preview.tsx (91%) rename web/src/{pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk => }/components/document-preview/index.less (100%) rename web/src/{pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk => }/components/document-preview/index.tsx (90%) rename web/src/{pages/document-viewer => components/document-preview}/md/index.tsx (55%) rename web/src/{pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk => }/components/document-preview/pdf-preview.tsx (79%) rename web/src/{pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk => }/components/document-preview/ppt-preview.tsx (100%) rename web/src/{pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk => }/components/document-preview/txt-preview.tsx (100%) rename web/src/{pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk => }/components/document-preview/video-preview.tsx (100%) delete mode 100644 web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/document-header.tsx delete mode 100644 web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/excel-preview.tsx delete mode 100644 web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/hooks.ts delete mode 100644 web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/image-preview.tsx delete mode 100644 web/src/pages/dataflow-result/components/document-preview/csv-preview.tsx delete mode 100644 web/src/pages/dataflow-result/components/document-preview/doc-preview.tsx delete mode 100644 web/src/pages/dataflow-result/components/document-preview/hooks.ts delete mode 100644 web/src/pages/dataflow-result/components/document-preview/index.less delete mode 100644 web/src/pages/dataflow-result/components/document-preview/index.tsx delete mode 100644 web/src/pages/dataflow-result/components/document-preview/pdf-preview.tsx delete mode 100644 web/src/pages/dataflow-result/components/document-preview/ppt-preview.tsx delete mode 100644 web/src/pages/dataflow-result/components/document-preview/txt-preview.tsx delete mode 100644 web/src/pages/document-viewer/docx/index.less delete mode 100644 web/src/pages/document-viewer/docx/index.tsx delete mode 100644 web/src/pages/document-viewer/excel/index.tsx delete mode 100644 web/src/pages/document-viewer/file-error/index.less delete mode 100644 web/src/pages/document-viewer/text/index.tsx diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/csv-preview.tsx b/web/src/components/document-preview/csv-preview.tsx similarity index 100% rename from web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/csv-preview.tsx rename to web/src/components/document-preview/csv-preview.tsx diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/doc-preview.tsx b/web/src/components/document-preview/doc-preview.tsx similarity index 91% rename from web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/doc-preview.tsx rename to web/src/components/document-preview/doc-preview.tsx index 845f0374e..470765f6e 100644 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/doc-preview.tsx +++ b/web/src/components/document-preview/doc-preview.tsx @@ -1,5 +1,7 @@ import message from '@/components/ui/message'; import { Spin } from '@/components/ui/spin'; +import { Authorization } from '@/constants/authorization'; +import { getAuthorization } from '@/utils/authorization-util'; import request from '@/utils/request'; import classNames from 'classnames'; import mammoth from 'mammoth'; @@ -22,6 +24,7 @@ export const DocPreviewer: React.FC = ({ const res = await request(url, { method: 'GET', responseType: 'blob', + headers: { [Authorization]: getAuthorization() }, onError: () => { message.error('Document parsing failed'); console.error('Error loading document:', url); diff --git a/web/src/pages/dataflow-result/components/document-preview/document-header.tsx b/web/src/components/document-preview/document-header.tsx similarity index 100% rename from web/src/pages/dataflow-result/components/document-preview/document-header.tsx rename to web/src/components/document-preview/document-header.tsx diff --git a/web/src/pages/dataflow-result/components/document-preview/excel-preview.tsx b/web/src/components/document-preview/excel-preview.tsx similarity index 83% rename from web/src/pages/dataflow-result/components/document-preview/excel-preview.tsx rename to web/src/components/document-preview/excel-preview.tsx index c86e0462c..252eb38ac 100644 --- a/web/src/pages/dataflow-result/components/document-preview/excel-preview.tsx +++ b/web/src/components/document-preview/excel-preview.tsx @@ -1,5 +1,6 @@ -import { useFetchExcel } from '@/pages/document-viewer/hooks'; +// import { useFetchExcel } from '@/pages/document-viewer/hooks'; import classNames from 'classnames'; +import { useFetchExcel } from './hooks'; interface ExcelCsvPreviewerProps { className?: string; diff --git a/web/src/pages/document-viewer/hooks.ts b/web/src/components/document-preview/hooks.ts similarity index 62% rename from web/src/pages/document-viewer/hooks.ts rename to web/src/components/document-preview/hooks.ts index 637699b83..097185b24 100644 --- a/web/src/pages/document-viewer/hooks.ts +++ b/web/src/components/document-preview/hooks.ts @@ -1,9 +1,67 @@ import { Authorization } from '@/constants/authorization'; +import { useGetKnowledgeSearchParams } from '@/hooks/route-hook'; +import { useGetPipelineResultSearchParams } from '@/pages/dataflow-result/hooks'; +import api, { api_host } from '@/utils/api'; import { getAuthorization } from '@/utils/authorization-util'; import jsPreviewExcel from '@js-preview/excel'; +import { useSize } from 'ahooks'; import axios from 'axios'; import mammoth from 'mammoth'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; + +export const useDocumentResizeObserver = () => { + const [containerWidth, setContainerWidth] = useState(); + const [containerRef, setContainerRef] = useState(null); + const size = useSize(containerRef); + + const onResize = useCallback((width?: number) => { + if (width) { + setContainerWidth(width); + } + }, []); + + useEffect(() => { + onResize(size?.width); + }, [size?.width, onResize]); + + return { containerWidth, setContainerRef }; +}; + +function highlightPattern(text: string, pattern: string, pageNumber: number) { + if (pageNumber === 2) { + return `${text}`; + } + if (text.trim() !== '' && pattern.match(text)) { + // return pattern.replace(text, (value) => `${value}`); + return `${text}`; + } + return text.replace(pattern, (value) => `${value}`); +} + +export const useHighlightText = (searchText: string = '') => { + const textRenderer = useCallback( + (textItem: any) => { + return highlightPattern(textItem.str, searchText, textItem.pageNumber); + }, + [searchText], + ); + + return textRenderer; +}; + +export const useGetDocumentUrl = (isAgent: boolean) => { + const { documentId } = useGetKnowledgeSearchParams(); + const { createdBy, documentId: id } = useGetPipelineResultSearchParams(); + + const url = useMemo(() => { + if (isAgent) { + return api.downloadFile + `?id=${id}&created_by=${createdBy}`; + } + return `${api_host}/document/get/${documentId}`; + }, [createdBy, documentId, id, isAgent]); + + return url; +}; export const useCatchError = (api: string) => { const [error, setError] = useState(''); diff --git a/web/src/pages/dataflow-result/components/document-preview/image-preview.tsx b/web/src/components/document-preview/image-preview.tsx similarity index 91% rename from web/src/pages/dataflow-result/components/document-preview/image-preview.tsx rename to web/src/components/document-preview/image-preview.tsx index 80e796a54..3b922f58c 100644 --- a/web/src/pages/dataflow-result/components/document-preview/image-preview.tsx +++ b/web/src/components/document-preview/image-preview.tsx @@ -1,5 +1,7 @@ import message from '@/components/ui/message'; import { Spin } from '@/components/ui/spin'; +import { Authorization } from '@/constants/authorization'; +import { getAuthorization } from '@/utils/authorization-util'; import request from '@/utils/request'; import classNames from 'classnames'; import { useEffect, useState } from 'react'; @@ -22,6 +24,7 @@ export const ImagePreviewer: React.FC = ({ const res = await request(url, { method: 'GET', responseType: 'blob', + headers: { [Authorization]: getAuthorization() }, onError: () => { message.error('Failed to load image'); setIsLoading(false); diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/index.less b/web/src/components/document-preview/index.less similarity index 100% rename from web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/index.less rename to web/src/components/document-preview/index.less diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/index.tsx b/web/src/components/document-preview/index.tsx similarity index 90% rename from web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/index.tsx rename to web/src/components/document-preview/index.tsx index b778067a6..7937fcd31 100644 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/index.tsx +++ b/web/src/components/document-preview/index.tsx @@ -4,7 +4,7 @@ import CSVFileViewer from './csv-preview'; import { DocPreviewer } from './doc-preview'; import { ExcelCsvPreviewer } from './excel-preview'; import { ImagePreviewer } from './image-preview'; -import styles from './index.less'; +import { Md } from './md'; import PdfPreviewer, { IProps } from './pdf-preview'; import { PptPreviewer } from './ppt-preview'; import { TxtPreviewer } from './txt-preview'; @@ -25,7 +25,7 @@ const Preview = ({ return ( <> {fileType === 'pdf' && highlights && setWidthAndHeight && ( -
+
)} - {['txt', 'md'].indexOf(fileType) > -1 && ( + {['txt'].indexOf(fileType) > -1 && (
@@ -82,6 +82,11 @@ const Preview = ({
)} + {['md'].indexOf(fileType) > -1 && ( +
+ +
+ )} ); }; diff --git a/web/src/pages/document-viewer/md/index.tsx b/web/src/components/document-preview/md/index.tsx similarity index 55% rename from web/src/pages/document-viewer/md/index.tsx rename to web/src/components/document-preview/md/index.tsx index 6715107d3..bdc30f91b 100644 --- a/web/src/pages/document-viewer/md/index.tsx +++ b/web/src/components/document-preview/md/index.tsx @@ -1,31 +1,39 @@ +import { Authorization } from '@/constants/authorization'; +import { cn } from '@/lib/utils'; +import FileError from '@/pages/document-viewer/file-error'; +import { getAuthorization } from '@/utils/authorization-util'; import React, { useEffect, useState } from 'react'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; -import FileError from '../file-error'; interface MdProps { - filePath: string; + // filePath: string; + className?: string; + url: string; } -const Md: React.FC = ({ filePath }) => { +export const Md: React.FC = ({ url, className }) => { const [content, setContent] = useState(''); const [error, setError] = useState(null); useEffect(() => { setError(null); - fetch(filePath) + fetch(url, { headers: { [Authorization]: getAuthorization() } }) .then((res) => { if (!res.ok) throw new Error('Failed to fetch markdown file'); return res.text(); }) .then((text) => setContent(text)) .catch((err) => setError(err.message)); - }, [filePath]); + }, [url]); if (error) return {error}; return ( -
+
{content}
); diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/pdf-preview.tsx b/web/src/components/document-preview/pdf-preview.tsx similarity index 79% rename from web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/pdf-preview.tsx rename to web/src/components/document-preview/pdf-preview.tsx index 79b1c54ae..07653f0af 100644 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/pdf-preview.tsx +++ b/web/src/components/document-preview/pdf-preview.tsx @@ -10,13 +10,21 @@ import { import { useCatchDocumentError } from '@/components/pdf-previewer/hooks'; import { Spin } from '@/components/ui/spin'; +// import FileError from '@/pages/document-viewer/file-error'; +import { Authorization } from '@/constants/authorization'; import FileError from '@/pages/document-viewer/file-error'; +import { getAuthorization } from '@/utils/authorization-util'; import styles from './index.less'; +type PdfLoaderProps = React.ComponentProps & { + httpHeaders?: Record; +}; +const Loader = PdfLoader as React.ComponentType; export interface IProps { - highlights: IHighlight[]; - setWidthAndHeight: (width: number, height: number) => void; + highlights?: IHighlight[]; + setWidthAndHeight?: (width: number, height: number) => void; url: string; + className?: string; } const HighlightPopup = ({ comment, @@ -30,7 +38,12 @@ const HighlightPopup = ({ ) : null; // TODO: merge with DocumentPreviewer -const PdfPreview = ({ highlights: state, setWidthAndHeight, url }: IProps) => { +const PdfPreview = ({ + highlights: state, + setWidthAndHeight, + url, + className, +}: IProps) => { // const url = useGetDocumentUrl(); const ref = useRef<(highlight: IHighlight) => void>(() => {}); @@ -39,17 +52,22 @@ const PdfPreview = ({ highlights: state, setWidthAndHeight, url }: IProps) => { const resetHash = () => {}; useEffect(() => { - if (state.length > 0) { + if (state?.length && state?.length > 0) { ref?.current(state[0]); } }, [state]); + const httpHeaders = { + [Authorization]: getAuthorization(), + }; + return (
- @@ -63,7 +81,7 @@ const PdfPreview = ({ highlights: state, setWidthAndHeight, url }: IProps) => { const viewport = page.getViewport({ scale: 1 }); const width = viewport.width; const height = viewport.height; - setWidthAndHeight(width, height); + setWidthAndHeight?.(width, height); }); return ( @@ -115,11 +133,11 @@ const PdfPreview = ({ highlights: state, setWidthAndHeight, url }: IProps) => { ); }} - highlights={state} + highlights={state || []} /> ); }} - +
); }; diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/ppt-preview.tsx b/web/src/components/document-preview/ppt-preview.tsx similarity index 100% rename from web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/ppt-preview.tsx rename to web/src/components/document-preview/ppt-preview.tsx diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/txt-preview.tsx b/web/src/components/document-preview/txt-preview.tsx similarity index 100% rename from web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/txt-preview.tsx rename to web/src/components/document-preview/txt-preview.tsx diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/video-preview.tsx b/web/src/components/document-preview/video-preview.tsx similarity index 100% rename from web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/video-preview.tsx rename to web/src/components/document-preview/video-preview.tsx diff --git a/web/src/constants/common.ts b/web/src/constants/common.ts index 37c71a24c..b761da6e5 100644 --- a/web/src/constants/common.ts +++ b/web/src/constants/common.ts @@ -148,7 +148,7 @@ export const Images = [ ]; // Without FileViewer -export const ExceptiveType = ['xlsx', 'xls', 'pdf', 'docx', ...Images]; +export const ExceptiveType = ['xlsx', 'xls', 'pdf', 'docx', 'md', ...Images]; export const SupportedPreviewDocumentTypes = [...ExceptiveType]; //#endregion diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-result-bar/index.tsx b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-result-bar/index.tsx index 2d392ead6..2de814b58 100644 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-result-bar/index.tsx +++ b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-result-bar/index.tsx @@ -1,14 +1,13 @@ -import { Input } from '@/components/originui/input'; import { Button } from '@/components/ui/button'; +import { SearchInput } from '@/components/ui/input'; import { Popover, PopoverContent, PopoverTrigger, } from '@/components/ui/popover'; import { Radio } from '@/components/ui/radio'; +import { Segmented } from '@/components/ui/segmented'; import { useTranslate } from '@/hooks/common-hooks'; -import { cn } from '@/lib/utils'; -import { SearchOutlined } from '@ant-design/icons'; import { ListFilter, Plus } from 'lucide-react'; import { useState } from 'react'; import { ChunkTextMode } from '../../constant'; @@ -61,46 +60,43 @@ export default ({ }; return (
-
- {textSelectOptions.map((option) => ( -
changeTextSelectValue(option.value)} - > - {option.label} -
- ))} -
-
- } - onChange={handleInputChange} - value={searchString} + -
- - - - - - {filterContent} - - -
- +
+
+ } + onChange={handleInputChange} + value={searchString} + /> + + + + + + {filterContent} + + + +
+ {/*
+
*/}
); }; diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/document-header.tsx b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/document-header.tsx deleted file mode 100644 index 88391f8c0..000000000 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/document-header.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { formatDate } from '@/utils/date'; -import { formatBytes } from '@/utils/file-util'; - -type Props = { - size: number; - name: string; - create_date: string; -}; - -export default ({ size, name, create_date }: Props) => { - const sizeName = formatBytes(size); - const dateStr = formatDate(create_date); - return ( -
-

{name}

-
- Size:{sizeName} Uploaded Time:{dateStr} -
-
- ); -}; diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/excel-preview.tsx b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/excel-preview.tsx deleted file mode 100644 index c86e0462c..000000000 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/excel-preview.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useFetchExcel } from '@/pages/document-viewer/hooks'; -import classNames from 'classnames'; - -interface ExcelCsvPreviewerProps { - className?: string; - url: string; -} - -export const ExcelCsvPreviewer: React.FC = ({ - className, - url, -}) => { - // const url = useGetDocumentUrl(); - const { containerRef } = useFetchExcel(url); - - return ( -
- ); -}; diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/hooks.ts b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/hooks.ts deleted file mode 100644 index fcf6a01ba..000000000 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/hooks.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { useGetKnowledgeSearchParams } from '@/hooks/route-hook'; -import { api_host } from '@/utils/api'; -import { useSize } from 'ahooks'; -import { CustomTextRenderer } from 'node_modules/react-pdf/dist/esm/shared/types'; -import { useCallback, useEffect, useMemo, useState } from 'react'; - -export const useDocumentResizeObserver = () => { - const [containerWidth, setContainerWidth] = useState(); - const [containerRef, setContainerRef] = useState(null); - const size = useSize(containerRef); - - const onResize = useCallback((width?: number) => { - if (width) { - setContainerWidth(width); - } - }, []); - - useEffect(() => { - onResize(size?.width); - }, [size?.width, onResize]); - - return { containerWidth, setContainerRef }; -}; - -function highlightPattern(text: string, pattern: string, pageNumber: number) { - if (pageNumber === 2) { - return `${text}`; - } - if (text.trim() !== '' && pattern.match(text)) { - // return pattern.replace(text, (value) => `${value}`); - return `${text}`; - } - return text.replace(pattern, (value) => `${value}`); -} - -export const useHighlightText = (searchText: string = '') => { - const textRenderer: CustomTextRenderer = useCallback( - (textItem) => { - return highlightPattern(textItem.str, searchText, textItem.pageNumber); - }, - [searchText], - ); - - return textRenderer; -}; - -export const useGetDocumentUrl = () => { - const { documentId } = useGetKnowledgeSearchParams(); - - const url = useMemo(() => { - return `${api_host}/document/get/${documentId}`; - }, [documentId]); - - return url; -}; diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/image-preview.tsx b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/image-preview.tsx deleted file mode 100644 index bec4ae75e..000000000 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/image-preview.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import message from '@/components/ui/message'; -import { Spin } from '@/components/ui/spin'; -import request from '@/utils/request'; -import classNames from 'classnames'; -import { useCallback, useEffect, useState } from 'react'; - -interface ImagePreviewerProps { - className?: string; - url: string; -} - -export const ImagePreviewer: React.FC = ({ - className, - url, -}) => { - // const url = useGetDocumentUrl(); - const [imageSrc, setImageSrc] = useState(null); - const [isLoading, setIsLoading] = useState(true); - - const fetchImage = useCallback(async () => { - setIsLoading(true); - const res = await request(url, { - method: 'GET', - responseType: 'blob', - onError: () => { - message.error('Failed to load image'); - setIsLoading(false); - }, - }); - const objectUrl = URL.createObjectURL(res.data); - setImageSrc(objectUrl); - setIsLoading(false); - }, [url]); - - useEffect(() => { - if (url) { - fetchImage(); - } - }, [url, fetchImage]); - - useEffect(() => { - return () => { - if (imageSrc) { - URL.revokeObjectURL(imageSrc); - } - }; - }, [imageSrc]); - - return ( -
- {isLoading && ( -
- -
- )} - - {!isLoading && imageSrc && ( -
- {'image'} URL.revokeObjectURL(imageSrc!)} - /> -
- )} -
- ); -}; diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/index.tsx b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/index.tsx index 7aff9e993..afe568d2a 100644 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/index.tsx +++ b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/index.tsx @@ -7,7 +7,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import ChunkCard from './components/chunk-card'; import CreatingModal from './components/chunk-creating-modal'; -import DocumentPreview from './components/document-preview'; import { useChangeChunkTextMode, useDeleteChunkByIds, @@ -18,8 +17,11 @@ import { import ChunkResultBar from './components/chunk-result-bar'; import CheckboxSets from './components/chunk-result-bar/checkbox-sets'; -import DocumentHeader from './components/document-preview/document-header'; +// import DocumentHeader from './components/document-preview/document-header'; +import DocumentPreview from '@/components/document-preview'; +import DocumentHeader from '@/components/document-preview/document-header'; +import { useGetDocumentUrl } from '@/components/document-preview/hooks'; import { PageHeader } from '@/components/page-header'; import { Breadcrumb, @@ -40,7 +42,6 @@ import { useNavigatePage, } from '@/hooks/logic-hooks/navigate-hooks'; import { useFetchKnowledgeBaseConfiguration } from '@/hooks/use-knowledge-request'; -import { useGetDocumentUrl } from './components/document-preview/hooks'; import styles from './index.less'; const Chunk = () => { @@ -74,7 +75,7 @@ const Chunk = () => { } = useUpdateChunk(); const { navigateToDataFile, getQueryString, navigateToDatasetList } = useNavigatePage(); - const fileUrl = useGetDocumentUrl(); + const fileUrl = useGetDocumentUrl(false); useEffect(() => { setChunkList(data); }, [data]); diff --git a/web/src/pages/dataflow-result/components/document-preview/csv-preview.tsx b/web/src/pages/dataflow-result/components/document-preview/csv-preview.tsx deleted file mode 100644 index 45b05454e..000000000 --- a/web/src/pages/dataflow-result/components/document-preview/csv-preview.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import message from '@/components/ui/message'; -import { Spin } from '@/components/ui/spin'; -import request from '@/utils/request'; -import classNames from 'classnames'; -import React, { useEffect, useRef, useState } from 'react'; - -interface CSVData { - rows: string[][]; - headers: string[]; -} - -interface FileViewerProps { - className?: string; - url: string; -} - -const CSVFileViewer: React.FC = ({ url }) => { - const [data, setData] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const containerRef = useRef(null); - // const url = useGetDocumentUrl(); - const parseCSV = (csvText: string): CSVData => { - console.log('Parsing CSV data:', csvText); - const lines = csvText.split('\n'); - const headers = lines[0].split(',').map((header) => header.trim()); - const rows = lines - .slice(1) - .map((line) => line.split(',').map((cell) => cell.trim())); - - return { headers, rows }; - }; - - useEffect(() => { - const loadCSV = async () => { - try { - const res = await request(url, { - method: 'GET', - responseType: 'blob', - onError: () => { - message.error('file load failed'); - setIsLoading(false); - }, - }); - - // parse CSV file - const reader = new FileReader(); - reader.readAsText(res.data); - reader.onload = () => { - const parsedData = parseCSV(reader.result as string); - console.log('file loaded successfully', reader.result); - setData(parsedData); - }; - } catch (error) { - message.error('CSV file parse failed'); - console.error('Error loading CSV file:', error); - } finally { - setIsLoading(false); - } - }; - - loadCSV(); - - return () => { - setData(null); - }; - }, [url]); - - return ( -
- {isLoading ? ( -
- -
- ) : data ? ( - - - - {data.headers.map((header, index) => ( - - ))} - - - - {data.rows.map((row, rowIndex) => ( - - {row.map((cell, cellIndex) => ( - - ))} - - ))} - -
- {header} -
- {cell || '-'} -
- ) : null} -
- ); -}; - -export default CSVFileViewer; diff --git a/web/src/pages/dataflow-result/components/document-preview/doc-preview.tsx b/web/src/pages/dataflow-result/components/document-preview/doc-preview.tsx deleted file mode 100644 index 845f0374e..000000000 --- a/web/src/pages/dataflow-result/components/document-preview/doc-preview.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import message from '@/components/ui/message'; -import { Spin } from '@/components/ui/spin'; -import request from '@/utils/request'; -import classNames from 'classnames'; -import mammoth from 'mammoth'; -import { useEffect, useState } from 'react'; - -interface DocPreviewerProps { - className?: string; - url: string; -} - -export const DocPreviewer: React.FC = ({ - className, - url, -}) => { - // const url = useGetDocumentUrl(); - const [htmlContent, setHtmlContent] = useState(''); - const [loading, setLoading] = useState(false); - const fetchDocument = async () => { - setLoading(true); - const res = await request(url, { - method: 'GET', - responseType: 'blob', - onError: () => { - message.error('Document parsing failed'); - console.error('Error loading document:', url); - }, - }); - try { - const arrayBuffer = await res.data.arrayBuffer(); - const result = await mammoth.convertToHtml( - { arrayBuffer }, - { includeDefaultStyleMap: true }, - ); - - const styledContent = result.value - .replace(/

/g, '

') - .replace(//g, ''); - - setHtmlContent(styledContent); - } catch (err) { - message.error('Document parsing failed'); - console.error('Error parsing document:', err); - } - setLoading(false); - }; - - useEffect(() => { - if (url) { - fetchDocument(); - } - }, [url]); - return ( -

- {loading && ( -
- -
- )} - - {!loading &&
} -
- ); -}; diff --git a/web/src/pages/dataflow-result/components/document-preview/hooks.ts b/web/src/pages/dataflow-result/components/document-preview/hooks.ts deleted file mode 100644 index 30e5887d8..000000000 --- a/web/src/pages/dataflow-result/components/document-preview/hooks.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { useGetKnowledgeSearchParams } from '@/hooks/route-hook'; -import api, { api_host } from '@/utils/api'; -import { useSize } from 'ahooks'; -import { CustomTextRenderer } from 'node_modules/react-pdf/dist/esm/shared/types'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { useGetPipelineResultSearchParams } from '../../hooks'; - -export const useDocumentResizeObserver = () => { - const [containerWidth, setContainerWidth] = useState(); - const [containerRef, setContainerRef] = useState(null); - const size = useSize(containerRef); - - const onResize = useCallback((width?: number) => { - if (width) { - setContainerWidth(width); - } - }, []); - - useEffect(() => { - onResize(size?.width); - }, [size?.width, onResize]); - - return { containerWidth, setContainerRef }; -}; - -function highlightPattern(text: string, pattern: string, pageNumber: number) { - if (pageNumber === 2) { - return `${text}`; - } - if (text.trim() !== '' && pattern.match(text)) { - // return pattern.replace(text, (value) => `${value}`); - return `${text}`; - } - return text.replace(pattern, (value) => `${value}`); -} - -export const useHighlightText = (searchText: string = '') => { - const textRenderer: CustomTextRenderer = useCallback( - (textItem) => { - return highlightPattern(textItem.str, searchText, textItem.pageNumber); - }, - [searchText], - ); - - return textRenderer; -}; - -export const useGetDocumentUrl = (isAgent: boolean) => { - const { documentId } = useGetKnowledgeSearchParams(); - const { createdBy, documentId: id } = useGetPipelineResultSearchParams(); - - const url = useMemo(() => { - if (isAgent) { - return api.downloadFile + `?id=${id}&created_by=${createdBy}`; - } - return `${api_host}/document/get/${documentId}`; - }, [createdBy, documentId, id, isAgent]); - - return url; -}; diff --git a/web/src/pages/dataflow-result/components/document-preview/index.less b/web/src/pages/dataflow-result/components/document-preview/index.less deleted file mode 100644 index 8f456af5a..000000000 --- a/web/src/pages/dataflow-result/components/document-preview/index.less +++ /dev/null @@ -1,13 +0,0 @@ -.documentContainer { - width: 100%; - // height: calc(100vh - 284px); - height: calc(100vh - 180px); - position: relative; - :global(.PdfHighlighter) { - overflow-x: hidden; - } - :global(.Highlight--scrolledTo .Highlight__part) { - overflow-x: hidden; - background-color: rgba(255, 226, 143, 1); - } -} diff --git a/web/src/pages/dataflow-result/components/document-preview/index.tsx b/web/src/pages/dataflow-result/components/document-preview/index.tsx deleted file mode 100644 index 0a5cf08e8..000000000 --- a/web/src/pages/dataflow-result/components/document-preview/index.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { memo } from 'react'; - -import CSVFileViewer from './csv-preview'; -import { DocPreviewer } from './doc-preview'; -import { ExcelCsvPreviewer } from './excel-preview'; -import { ImagePreviewer } from './image-preview'; -import PdfPreviewer, { IProps } from './pdf-preview'; -import { PptPreviewer } from './ppt-preview'; -import { TxtPreviewer } from './txt-preview'; - -type PreviewProps = { - fileType: string; - className?: string; - url: string; -}; -const Preview = ({ - fileType, - className, - highlights, - setWidthAndHeight, - url, -}: PreviewProps & Partial) => { - return ( - <> - {fileType === 'pdf' && highlights && setWidthAndHeight && ( -
- -
- )} - {['doc', 'docx'].indexOf(fileType) > -1 && ( -
- -
- )} - {['txt', 'md'].indexOf(fileType) > -1 && ( -
- -
- )} - {['visual'].indexOf(fileType) > -1 && ( -
- -
- )} - {['pptx'].indexOf(fileType) > -1 && ( -
- -
- )} - {['xlsx'].indexOf(fileType) > -1 && ( -
- -
- )} - {['csv'].indexOf(fileType) > -1 && ( -
- -
- )} - - ); -}; -export default memo(Preview); diff --git a/web/src/pages/dataflow-result/components/document-preview/pdf-preview.tsx b/web/src/pages/dataflow-result/components/document-preview/pdf-preview.tsx deleted file mode 100644 index 79b1c54ae..000000000 --- a/web/src/pages/dataflow-result/components/document-preview/pdf-preview.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { memo, useEffect, useRef } from 'react'; -import { - AreaHighlight, - Highlight, - IHighlight, - PdfHighlighter, - PdfLoader, - Popup, -} from 'react-pdf-highlighter'; - -import { useCatchDocumentError } from '@/components/pdf-previewer/hooks'; -import { Spin } from '@/components/ui/spin'; -import FileError from '@/pages/document-viewer/file-error'; -import styles from './index.less'; - -export interface IProps { - highlights: IHighlight[]; - setWidthAndHeight: (width: number, height: number) => void; - url: string; -} -const HighlightPopup = ({ - comment, -}: { - comment: { text: string; emoji: string }; -}) => - comment.text ? ( -
- {comment.emoji} {comment.text} -
- ) : null; - -// TODO: merge with DocumentPreviewer -const PdfPreview = ({ highlights: state, setWidthAndHeight, url }: IProps) => { - // const url = useGetDocumentUrl(); - - const ref = useRef<(highlight: IHighlight) => void>(() => {}); - const error = useCatchDocumentError(url); - - const resetHash = () => {}; - - useEffect(() => { - if (state.length > 0) { - ref?.current(state[0]); - } - }, [state]); - - return ( -
- - -
- } - workerSrc="/pdfjs-dist/pdf.worker.min.js" - errorMessage={{error}} - > - {(pdfDocument) => { - pdfDocument.getPage(1).then((page) => { - const viewport = page.getViewport({ scale: 1 }); - const width = viewport.width; - const height = viewport.height; - setWidthAndHeight(width, height); - }); - - return ( - event.altKey} - onScrollChange={resetHash} - scrollRef={(scrollTo) => { - ref.current = scrollTo; - }} - onSelectionFinished={() => null} - highlightTransform={( - highlight, - index, - setTip, - hideTip, - viewportToScaled, - screenshot, - isScrolledTo, - ) => { - const isTextHighlight = !Boolean( - highlight.content && highlight.content.image, - ); - - const component = isTextHighlight ? ( - - ) : ( - {}} - /> - ); - - return ( - } - onMouseOver={(popupContent) => - setTip(highlight, () => popupContent) - } - onMouseOut={hideTip} - key={index} - > - {component} - - ); - }} - highlights={state} - /> - ); - }} - -
- ); -}; - -export default memo(PdfPreview); diff --git a/web/src/pages/dataflow-result/components/document-preview/ppt-preview.tsx b/web/src/pages/dataflow-result/components/document-preview/ppt-preview.tsx deleted file mode 100644 index 7786c48c3..000000000 --- a/web/src/pages/dataflow-result/components/document-preview/ppt-preview.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import message from '@/components/ui/message'; -import request from '@/utils/request'; -import classNames from 'classnames'; -import { init } from 'pptx-preview'; -import { useEffect, useRef } from 'react'; -interface PptPreviewerProps { - className?: string; - url: string; -} - -export const PptPreviewer: React.FC = ({ - className, - url, -}) => { - // const url = useGetDocumentUrl(); - const wrapper = useRef(null); - const containerRef = useRef(null); - const fetchDocument = async () => { - const res = await request(url, { - method: 'GET', - responseType: 'blob', - onError: () => { - message.error('Document parsing failed'); - console.error('Error loading document:', url); - }, - }); - console.log(res); - try { - const arrayBuffer = await res.data.arrayBuffer(); - - if (containerRef.current) { - let width = 500; - let height = 900; - if (containerRef.current) { - width = containerRef.current.clientWidth - 50; - height = containerRef.current.clientHeight - 50; - } - let pptxPrviewer = init(containerRef.current, { - width: width, - height: height, - }); - pptxPrviewer.preview(arrayBuffer); - } - } catch (err) { - message.error('ppt parse failed'); - } - }; - - useEffect(() => { - if (url) { - fetchDocument(); - } - }, [url]); - - return ( -
-
-
-
-
-
-
- ); -}; diff --git a/web/src/pages/dataflow-result/components/document-preview/txt-preview.tsx b/web/src/pages/dataflow-result/components/document-preview/txt-preview.tsx deleted file mode 100644 index cf6649e34..000000000 --- a/web/src/pages/dataflow-result/components/document-preview/txt-preview.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import message from '@/components/ui/message'; -import { Spin } from '@/components/ui/spin'; -import request from '@/utils/request'; -import classNames from 'classnames'; -import { useEffect, useState } from 'react'; - -type TxtPreviewerProps = { className?: string; url: string }; -export const TxtPreviewer = ({ className, url }: TxtPreviewerProps) => { - // const url = useGetDocumentUrl(); - const [loading, setLoading] = useState(false); - const [data, setData] = useState(''); - const fetchTxt = async () => { - setLoading(true); - const res = await request(url, { - method: 'GET', - responseType: 'blob', - onError: (err: any) => { - message.error('Failed to load file'); - console.error('Error loading file:', err); - }, - }); - // blob to string - const reader = new FileReader(); - reader.readAsText(res.data); - reader.onload = () => { - setData(reader.result as string); - setLoading(false); - console.log('file loaded successfully', reader.result); - }; - console.log('file data:', res); - }; - useEffect(() => { - if (url) { - fetchTxt(); - } else { - setLoading(false); - setData(''); - } - }, [url]); - return ( -
- {loading && ( -
- -
- )} - - {!loading &&
{data}
} -
- ); -}; diff --git a/web/src/pages/dataflow-result/index.tsx b/web/src/pages/dataflow-result/index.tsx index c15f71c66..ae43ad852 100644 --- a/web/src/pages/dataflow-result/index.tsx +++ b/web/src/pages/dataflow-result/index.tsx @@ -1,7 +1,7 @@ +import DocumentPreview from '@/components/document-preview'; import { useFetchNextChunkList } from '@/hooks/use-chunk-request'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import DocumentPreview from './components/document-preview'; import { useFetchPipelineFileLogDetail, useFetchPipelineResult, @@ -13,8 +13,9 @@ import { useTimelineDataFlow, } from './hooks'; -import DocumentHeader from './components/document-preview/document-header'; +import DocumentHeader from '@/components/document-preview/document-header'; +import { useGetDocumentUrl } from '@/components/document-preview/hooks'; import { TimelineNode } from '@/components/originui/timeline'; import { PageHeader } from '@/components/page-header'; import Spotlight from '@/components/spotlight'; @@ -32,7 +33,6 @@ import { AgentCategory } from '@/constants/agent'; import { Images } from '@/constants/common'; import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; import { useGetKnowledgeSearchParams } from '@/hooks/route-hook'; -import { useGetDocumentUrl } from './components/document-preview/hooks'; import TimelineDataFlow from './components/time-line'; import { TimelineNodeType } from './constant'; import styles from './index.less'; @@ -76,13 +76,14 @@ const Chunk = () => { const fileType = useMemo(() => { if (isAgent) { return Images.some((x) => x === documentExtension) - ? 'visual' + ? documentInfo?.name.split('.').pop() || 'visual' : documentExtension; } switch (documentInfo?.type) { case 'doc': return documentInfo?.name.split('.').pop() || 'doc'; case 'visual': + return documentInfo?.name.split('.').pop() || 'visual'; case 'docx': case 'txt': case 'md': diff --git a/web/src/pages/document-viewer/docx/index.less b/web/src/pages/document-viewer/docx/index.less deleted file mode 100644 index 62e750554..000000000 --- a/web/src/pages/document-viewer/docx/index.less +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright (c) 2017 PlanGrid, Inc. - -.docxViewerWrapper { - overflow-y: scroll; - height: 100%; - width: 100%; - - .box { - width: 100%; - height: 100%; - } - - :global(.document-container) { - padding: 30px; - width: 700px; - background: rgba(255, 255, 255, 0.1); - - margin: auto; - } - - html, - bodyaddress, - blockquote, - body, - dd, - div, - dl, - dt, - fieldset, - form, - frame, - frameset, - h1, - h2, - h3, - h4, - h5, - h6, - noframes, - ol, - p, - ul, - center, - dir, - hr, - menu, - pre { - display: block; - unicode-bidi: embed; - } - li { - display: list-item; - list-style-type: disc; - } - head { - display: none; - } - table { - display: table; - } - img { - width: 100%; - } - tr { - display: table-row; - } - thead { - display: table-header-group; - } - tbody { - display: table-row-group; - } - tfoot { - display: table-footer-group; - } - col { - display: table-column; - } - colgroup { - display: table-column-group; - } - th { - display: table-cell; - } - td { - display: table-cell; - border-bottom: 1px solid #ccc; - border-right: 1px solid #ccc; - padding: 0.2em 0.5em; - } - caption { - display: table-caption; - } - th { - font-weight: bolder; - text-align: center; - } - caption { - text-align: center; - } - body { - margin: 8px; - } - h1 { - font-size: 2em; - margin: 0.67em 0; - } - h2 { - font-size: 1.5em; - margin: 0.75em 0; - } - h3 { - font-size: 1.17em; - margin: 0.83em 0; - } - h4, - p, - blockquote, - ul, - fieldset, - form, - ol, - dl, - dir, - menu { - margin: 1.12em 0; - } - h5 { - font-size: 0.83em; - margin: 1.5em 0; - } - h6 { - font-size: 0.75em; - margin: 1.67em 0; - } - h1, - h2, - h3, - h4, - h5, - h6, - b, - strong { - font-weight: bolder; - } - blockquote { - margin-left: 40px; - margin-right: 40px; - } - i, - cite, - em, - var, - address { - font-style: italic; - } - pre, - tt, - code, - kbd, - samp { - font-family: monospace; - } - pre { - white-space: pre; - } - button, - textarea, - input, - select { - display: inline-block; - } - big { - font-size: 1.17em; - } - small, - sub, - sup { - font-size: 0.83em; - } - sub { - vertical-align: sub; - } - sup { - vertical-align: super; - } - table { - border-spacing: 2px; - } - thead, - tbody, - tfoot { - vertical-align: middle; - } - td, - th, - tr { - vertical-align: inherit; - } - s, - strike, - del { - text-decoration: line-through; - } - hr { - border: 1px inset; - } - ol, - ul, - dir, - menu, - dd { - margin-left: 40px; - } - ol { - list-style-type: decimal; - } - ol ul, - ol ul, - ul ol, - ul ol, - ul ul, - ul ul, - ol ol, - ol ol { - margin-top: 0; - margin-bottom: 0; - } - u, - ins { - text-decoration: underline; - } - br:before { - content: '\A'; - white-space: pre-line; - } - center { - text-align: center; - } - :link, - :visited { - text-decoration: underline; - } - :focus { - outline: thin dotted invert; - } - /* Begin bidirectionality settings (do not change) */ - BDO[DIR='ltr'] { - direction: ltr; - unicode-bidi: bidi-override; - } - BDO[DIR='rtl'] { - direction: rtl; - unicode-bidi: bidi-override; - } - *[DIR='ltr'] { - direction: ltr; - unicode-bidi: embed; - } - *[DIR='rtl'] { - direction: rtl; - unicode-bidi: embed; - } - @media print { - h1 { - page-break-before: always; - } - h1, - h2, - h3, - h4, - h5, - h6 { - page-break-after: avoid; - } - ul, - ol, - dl { - page-break-before: avoid; - } - } -} diff --git a/web/src/pages/document-viewer/docx/index.tsx b/web/src/pages/document-viewer/docx/index.tsx deleted file mode 100644 index 60f0d4fd0..000000000 --- a/web/src/pages/document-viewer/docx/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Spin } from 'antd'; -import FileError from '../file-error'; - -import { useFetchDocx } from '../hooks'; -import styles from './index.less'; - -const Docx = ({ filePath }: { filePath: string }) => { - const { succeed, containerRef, error } = useFetchDocx(filePath); - - return ( - <> - {succeed ? ( -
-
- -
-
- ) : ( - {error} - )} - - ); -}; - -export default Docx; diff --git a/web/src/pages/document-viewer/excel/index.tsx b/web/src/pages/document-viewer/excel/index.tsx deleted file mode 100644 index 99c9d3469..000000000 --- a/web/src/pages/document-viewer/excel/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import '@js-preview/excel/lib/index.css'; -import FileError from '../file-error'; -import { useFetchExcel } from '../hooks'; - -const Excel = ({ filePath }: { filePath: string }) => { - const { status, containerRef, error } = useFetchExcel(filePath); - - return ( -
- {status || {error}} -
- ); -}; - -export default Excel; diff --git a/web/src/pages/document-viewer/file-error/index.less b/web/src/pages/document-viewer/file-error/index.less deleted file mode 100644 index fc971162a..000000000 --- a/web/src/pages/document-viewer/file-error/index.less +++ /dev/null @@ -1,4 +0,0 @@ -.errorWrapper { - width: 100%; - height: 100%; -} diff --git a/web/src/pages/document-viewer/file-error/index.tsx b/web/src/pages/document-viewer/file-error/index.tsx index 7ee4dc6b7..cef454816 100644 --- a/web/src/pages/document-viewer/file-error/index.tsx +++ b/web/src/pages/document-viewer/file-error/index.tsx @@ -1,18 +1,18 @@ -import { Alert, Flex } from 'antd'; - import { useTranslate } from '@/hooks/common-hooks'; import React from 'react'; -import styles from './index.less'; const FileError = ({ children }: React.PropsWithChildren) => { const { t } = useTranslate('fileManager'); return ( - - {children || t('fileError')}} - > - +
+
+
+
+ {children || t('fileError')} +
+
+
+
); }; diff --git a/web/src/pages/document-viewer/index.tsx b/web/src/pages/document-viewer/index.tsx index fae52cc70..a56a2cec2 100644 --- a/web/src/pages/document-viewer/index.tsx +++ b/web/src/pages/document-viewer/index.tsx @@ -1,16 +1,22 @@ import { Images } from '@/constants/common'; import { api_host } from '@/utils/api'; -import { Flex } from 'antd'; +// import { Flex } from 'antd'; import { useParams, useSearchParams } from 'umi'; -import Docx from './docx'; -import Excel from './excel'; -import Image from './image'; -import Md from './md'; -import Pdf from './pdf'; -import Text from './text'; +// import Docx from './docx'; +// import Excel from './excel'; +// import Image from './image'; +// import Md from './md'; +// import Pdf from './pdf'; +// import Text from './text'; +import { DocPreviewer } from '@/components/document-preview/doc-preview'; +import { ExcelCsvPreviewer } from '@/components/document-preview/excel-preview'; +import { ImagePreviewer } from '@/components/document-preview/image-preview'; +import Md from '@/components/document-preview/md'; +import PdfPreview from '@/components/document-preview/pdf-preview'; +import { TxtPreviewer } from '@/components/document-preview/txt-preview'; import { previewHtmlFile } from '@/utils/file-util'; -import styles from './index.less'; +// import styles from './index.less'; // TODO: The interface returns an incorrect content-type for the SVG. @@ -20,6 +26,7 @@ const DocumentViewer = () => { const ext = currentQueryParameters.get('ext'); const prefix = currentQueryParameters.get('prefix'); const api = `${api_host}/${prefix || 'file'}/get/${documentId}`; + // request.head if (ext === 'html' && documentId) { previewHtmlFile(documentId); @@ -27,19 +34,24 @@ const DocumentViewer = () => { } return ( -
+
{Images.includes(ext!) && ( - - - +
+ {/* */} + +
)} - {ext === 'md' && } - {ext === 'txt' && } + {ext === 'md' && } + {ext === 'txt' && } - {ext === 'pdf' && } - {(ext === 'xlsx' || ext === 'xls') && } + {ext === 'pdf' && ( + + )} + {(ext === 'xlsx' || ext === 'xls') && ( + + )} - {ext === 'docx' && } + {ext === 'docx' && }
); }; diff --git a/web/src/pages/document-viewer/text/index.tsx b/web/src/pages/document-viewer/text/index.tsx deleted file mode 100644 index bda46d74c..000000000 --- a/web/src/pages/document-viewer/text/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import FileError from '../file-error'; - -interface TxtProps { - filePath: string; -} - -const Md: React.FC = ({ filePath }) => { - const [content, setContent] = useState(''); - const [error, setError] = useState(null); - - useEffect(() => { - setError(null); - fetch(filePath) - .then((res) => { - if (!res.ok) throw new Error('Failed to fetch text file'); - return res.text(); - }) - .then((text) => setContent(text)) - .catch((err) => setError(err.message)); - }, [filePath]); - - if (error) return {error}; - - return ( -
- {content} -
- ); -}; - -export default Md; diff --git a/web/src/pages/next-search/document-preview-modal/index.tsx b/web/src/pages/next-search/document-preview-modal/index.tsx index 8e3419d73..2019cfe7c 100644 --- a/web/src/pages/next-search/document-preview-modal/index.tsx +++ b/web/src/pages/next-search/document-preview-modal/index.tsx @@ -1,3 +1,4 @@ +import DocumentPreview from '@/components/document-preview'; import { FileIcon } from '@/components/icon-font'; import { Modal } from '@/components/ui/modal/modal'; import { @@ -7,7 +8,6 @@ import { import { IModalProps } from '@/interfaces/common'; import { IReferenceChunk } from '@/interfaces/database/chat'; import { IChunk } from '@/interfaces/database/knowledge'; -import DocumentPreview from '@/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview'; import { useEffect, useState } from 'react'; interface IProps extends IModalProps { diff --git a/web/src/pages/user-setting/data-source/hooks.ts b/web/src/pages/user-setting/data-source/hooks.ts index 966b2b8c4..63b2f1a80 100644 --- a/web/src/pages/user-setting/data-source/hooks.ts +++ b/web/src/pages/user-setting/data-source/hooks.ts @@ -45,21 +45,23 @@ export const useListDataSource = () => { const updatedDataSourceTemplates = useMemo(() => { const categorizedData = categorizeDataBySource(list || []); - let sourcelist: Array }> = + let sourceList: Array }> = []; Object.keys(categorizedData).forEach((key: string) => { const k = key as DataSourceKey; - sourcelist.push({ - id: k, - name: DataSourceInfo[k].name, - description: DataSourceInfo[k].description, - icon: DataSourceInfo[k].icon, - list: categorizedData[k] || [], - }); + if (DataSourceInfo[k]) { + sourceList.push({ + id: k, + name: DataSourceInfo[k].name, + description: DataSourceInfo[k].description, + icon: DataSourceInfo[k].icon, + list: categorizedData[k] || [], + }); + } }); - console.log('🚀 ~ useListDataSource ~ sourcelist:', sourcelist); - return sourcelist; + console.log('🚀 ~ useListDataSource ~ sourceList:', sourceList); + return sourceList; }, [list]); return { list, categorizedList: updatedDataSourceTemplates, isFetching };