feat(next-search): Implements document preview functionality #3221 (#9465)

### What problem does this PR solve?

feat(next-search): Implements document preview functionality

- Adds a new document preview modal component
- Implements document preview page logic
- Adds document preview-related hooks
- Optimizes document preview rendering logic
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
chanx
2025-08-14 12:11:53 +08:00
committed by GitHub
parent b55c3d07dc
commit b1baa91ff0
29 changed files with 1336 additions and 122 deletions

View File

@ -3,7 +3,6 @@ import { Spin } from '@/components/ui/spin';
import request from '@/utils/request';
import classNames from 'classnames';
import React, { useEffect, useRef, useState } from 'react';
import { useGetDocumentUrl } from './hooks';
interface CSVData {
rows: string[][];
@ -12,13 +11,14 @@ interface CSVData {
interface FileViewerProps {
className?: string;
url: string;
}
const CSVFileViewer: React.FC<FileViewerProps> = () => {
const CSVFileViewer: React.FC<FileViewerProps> = ({ url }) => {
const [data, setData] = useState<CSVData | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const containerRef = useRef<HTMLDivElement>(null);
const url = useGetDocumentUrl();
// const url = useGetDocumentUrl();
const parseCSV = (csvText: string): CSVData => {
console.log('Parsing CSV data:', csvText);
const lines = csvText.split('\n');

View File

@ -4,14 +4,17 @@ import request from '@/utils/request';
import classNames from 'classnames';
import mammoth from 'mammoth';
import { useEffect, useState } from 'react';
import { useGetDocumentUrl } from './hooks';
interface DocPreviewerProps {
className?: string;
url: string;
}
export const DocPreviewer: React.FC<DocPreviewerProps> = ({ className }) => {
const url = useGetDocumentUrl();
export const DocPreviewer: React.FC<DocPreviewerProps> = ({
className,
url,
}) => {
// const url = useGetDocumentUrl();
const [htmlContent, setHtmlContent] = useState<string>('');
const [loading, setLoading] = useState(false);
const fetchDocument = async () => {

View File

@ -1,15 +1,16 @@
import { useFetchExcel } from '@/pages/document-viewer/hooks';
import classNames from 'classnames';
import { useGetDocumentUrl } from './hooks';
interface ExcelCsvPreviewerProps {
className?: string;
url: string;
}
export const ExcelCsvPreviewer: React.FC<ExcelCsvPreviewerProps> = ({
className,
url,
}) => {
const url = useGetDocumentUrl();
// const url = useGetDocumentUrl();
const { containerRef } = useFetchExcel(url);
return (

View File

@ -3,16 +3,17 @@ import { Spin } from '@/components/ui/spin';
import request from '@/utils/request';
import classNames from 'classnames';
import { useEffect, useState } from 'react';
import { useGetDocumentUrl } from './hooks';
interface ImagePreviewerProps {
className?: string;
url: string;
}
export const ImagePreviewer: React.FC<ImagePreviewerProps> = ({
className,
url,
}) => {
const url = useGetDocumentUrl();
// const url = useGetDocumentUrl();
const [imageSrc, setImageSrc] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);

View File

@ -12,12 +12,14 @@ import { TxtPreviewer } from './txt-preview';
type PreviewProps = {
fileType: string;
className?: string;
url: string;
};
const Preview = ({
fileType,
className,
highlights,
setWidthAndHeight,
url,
}: PreviewProps & Partial<IProps>) => {
return (
<>
@ -26,37 +28,38 @@ const Preview = ({
<PdfPreviewer
highlights={highlights}
setWidthAndHeight={setWidthAndHeight}
url={url}
></PdfPreviewer>
</section>
)}
{['doc', 'docx'].indexOf(fileType) > -1 && (
<section>
<DocPreviewer className={className} />
<DocPreviewer className={className} url={url} />
</section>
)}
{['txt', 'md'].indexOf(fileType) > -1 && (
<section>
<TxtPreviewer className={className} />
<TxtPreviewer className={className} url={url} />
</section>
)}
{['visual'].indexOf(fileType) > -1 && (
<section>
<ImagePreviewer className={className} />
<ImagePreviewer className={className} url={url} />
</section>
)}
{['pptx'].indexOf(fileType) > -1 && (
<section>
<PptPreviewer className={className} />
<PptPreviewer className={className} url={url} />
</section>
)}
{['xlsx'].indexOf(fileType) > -1 && (
<section>
<ExcelCsvPreviewer className={className} />
<ExcelCsvPreviewer className={className} url={url} />
</section>
)}
{['csv'].indexOf(fileType) > -1 && (
<section>
<CSVFileViewer className={className} />
<CSVFileViewer className={className} url={url} />
</section>
)}
</>

View File

@ -7,7 +7,6 @@ import {
PdfLoader,
Popup,
} from 'react-pdf-highlighter';
import { useGetDocumentUrl } from './hooks';
import { useCatchDocumentError } from '@/components/pdf-previewer/hooks';
import { Spin } from '@/components/ui/spin';
@ -17,6 +16,7 @@ import styles from './index.less';
export interface IProps {
highlights: IHighlight[];
setWidthAndHeight: (width: number, height: number) => void;
url: string;
}
const HighlightPopup = ({
comment,
@ -30,8 +30,8 @@ const HighlightPopup = ({
) : null;
// TODO: merge with DocumentPreviewer
const PdfPreview = ({ highlights: state, setWidthAndHeight }: IProps) => {
const url = useGetDocumentUrl();
const PdfPreview = ({ highlights: state, setWidthAndHeight, url }: IProps) => {
// const url = useGetDocumentUrl();
const ref = useRef<(highlight: IHighlight) => void>(() => {});
const error = useCatchDocumentError(url);

View File

@ -3,13 +3,16 @@ import request from '@/utils/request';
import classNames from 'classnames';
import { init } from 'pptx-preview';
import { useEffect, useRef } from 'react';
import { useGetDocumentUrl } from './hooks';
interface PptPreviewerProps {
className?: string;
url: string;
}
export const PptPreviewer: React.FC<PptPreviewerProps> = ({ className }) => {
const url = useGetDocumentUrl();
export const PptPreviewer: React.FC<PptPreviewerProps> = ({
className,
url,
}) => {
// const url = useGetDocumentUrl();
const wrapper = useRef<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const fetchDocument = async () => {

View File

@ -3,11 +3,10 @@ import { Spin } from '@/components/ui/spin';
import request from '@/utils/request';
import classNames from 'classnames';
import { useEffect, useState } from 'react';
import { useGetDocumentUrl } from './hooks';
type TxtPreviewerProps = { className?: string };
export const TxtPreviewer = ({ className }: TxtPreviewerProps) => {
const url = useGetDocumentUrl();
type TxtPreviewerProps = { className?: string; url: string };
export const TxtPreviewer = ({ className, url }: TxtPreviewerProps) => {
// const url = useGetDocumentUrl();
const [loading, setLoading] = useState(false);
const [data, setData] = useState<string>('');
const fetchTxt = async () => {

View File

@ -40,6 +40,7 @@ import {
useNavigatePage,
} from '@/hooks/logic-hooks/navigate-hooks';
import { useFetchKnowledgeBaseConfiguration } from '@/hooks/use-knowledge-request';
import { useGetDocumentUrl } from '../../../knowledge-chunk/components/document-preview/hooks';
import styles from './index.less';
const Chunk = () => {
@ -73,6 +74,7 @@ const Chunk = () => {
} = useUpdateChunk();
const { navigateToDataset, getQueryString, navigateToDatasetList } =
useNavigatePage();
const fileUrl = useGetDocumentUrl();
useEffect(() => {
setChunkList(data);
}, [data]);
@ -212,6 +214,7 @@ const Chunk = () => {
fileType={fileType}
highlights={highlights}
setWidthAndHeight={setWidthAndHeight}
url={fileUrl}
></DocumentPreview>
</section>
</div>