feat: display all pdf pages

This commit is contained in:
billchen 2024-03-01 11:26:22 +08:00
parent a6ae5b77d2
commit 82ea4ae6df
9 changed files with 133 additions and 40 deletions

40
web/package-lock.json generated
View file

@ -9,6 +9,7 @@
"@ant-design/icons": "^5.2.6",
"@ant-design/pro-components": "^2.6.46",
"@ant-design/pro-layout": "^7.17.16",
"ahooks": "^3.7.10",
"antd": "^5.12.7",
"axios": "^1.6.3",
"classnames": "^2.5.1",
@ -4763,6 +4764,27 @@
"node": ">=8"
}
},
"node_modules/ahooks": {
"version": "3.7.10",
"resolved": "https://registry.npmmirror.com/ahooks/-/ahooks-3.7.10.tgz",
"integrity": "sha512-/HLYif7sFA/5qSuWKrwvjDbf3bq+sdaMrUWS7XGCDRWdC2FrG/i+u5LZdakMYc6UIgJTMQ7tGiJCV7sdU4kSIw==",
"dependencies": {
"@babel/runtime": "^7.21.0",
"dayjs": "^1.9.1",
"intersection-observer": "^0.12.0",
"js-cookie": "^2.x.x",
"lodash": "^4.17.21",
"resize-observer-polyfill": "^1.5.1",
"screenfull": "^5.0.0",
"tslib": "^2.4.1"
},
"engines": {
"node": ">=8.0.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
@ -9843,6 +9865,11 @@
"node": ">= 0.4"
}
},
"node_modules/intersection-observer": {
"version": "0.12.2",
"resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz",
"integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg=="
},
"node_modules/intl": {
"version": "1.2.5",
"resolved": "https://registry.npmmirror.com/intl/-/intl-1.2.5.tgz",
@ -10730,6 +10757,11 @@
"resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.5.tgz",
"integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA=="
},
"node_modules/js-cookie": {
"version": "2.2.1",
"resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-2.2.1.tgz",
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
@ -15550,6 +15582,14 @@
"node": ">= 10.13.0"
}
},
"node_modules/screenfull": {
"version": "5.2.0",
"resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-5.2.0.tgz",
"integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/scroll-into-view-if-needed": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz",

View file

@ -13,6 +13,7 @@
"@ant-design/icons": "^5.2.6",
"@ant-design/pro-components": "^2.6.46",
"@ant-design/pro-layout": "^7.17.16",
"ahooks": "^3.7.10",
"antd": "^5.12.7",
"axios": "^1.6.3",
"classnames": "^2.5.1",

View file

@ -0,0 +1,20 @@
import { useSize } from 'ahooks';
import { useCallback, useEffect, useState } from 'react';
export const useDocumentResizeObserver = () => {
const [containerWidth, setContainerWidth] = useState<number>();
const [containerRef, setContainerRef] = useState<HTMLElement | null>(null);
const size = useSize(containerRef);
const onResize = useCallback((width?: number) => {
if (width) {
setContainerWidth(width);
}
}, []);
useEffect(() => {
onResize(size?.width);
}, [size?.width, onResize]);
return { containerWidth, setContainerRef };
};

View file

@ -0,0 +1,6 @@
.documentContainer {
width: 100%;
height: calc(100vh - 284px);
overflow-y: auto;
overflow-x: hidden;
}

View file

@ -1,59 +1,72 @@
import { useGetKnowledgeSearchParams } from '@/hooks/knowledgeHook';
import { getDocumentFile } from '@/services/kbService';
import { api_host } from '@/utils/api';
import { useCallback, useEffect, useState } from 'react';
import { useMemo, useState } from 'react';
import { Document, Page, pdfjs } from 'react-pdf';
import { useDispatch } from 'umi';
type PDFFile = string | File | null;
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
import 'react-pdf/dist/esm/Page/TextLayer.css';
import { useDocumentResizeObserver } from './hooks';
import styles from './index.less';
// type PDFFile = string | File | null;
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.min.js',
import.meta.url,
).toString();
// const options = {
// cMapUrl: '/cmaps/',
// standardFontDataUrl: '/standard_fonts/',
// };
const DocumentPreview = () => {
const [numPages, setNumPages] = useState<number>();
const [pageNumber, setPageNumber] = useState<number>(1);
const { documentId } = useGetKnowledgeSearchParams();
const dispatch = useDispatch();
const [file, setFile] = useState<PDFFile>(null);
// const [file, setFile] = useState<PDFFile>(null);
const { containerWidth, setContainerRef } = useDocumentResizeObserver();
function onDocumentLoadSuccess({ numPages }: { numPages: number }): void {
setNumPages(numPages);
}
const handleChange = (e: any) => {
console.info(e.files);
setFile(e.target.files[0] || null);
};
// const handleChange = (e: any) => {
// console.info(e.files);
// setFile(e.target.files[0] || null);
// };
const url = `${api_host}/document/get/${documentId}`;
const fetch_document_file = useCallback(async () => {
const ret: Blob = await getDocumentFile(documentId);
console.info(ret);
const f = new File([ret], 'xx.pdf', { type: ret.type });
// console.info(f);
setFile(f);
const url = useMemo(() => {
return `${api_host}/document/get/${documentId}`;
}, [documentId]);
useEffect(() => {
// dispatch({ type: 'kFModel/fetch_document_file', payload: documentId });
fetch_document_file();
}, [fetch_document_file]);
// const fetch_document_file = useCallback(async () => {
// const ret: Blob = await getDocumentFile(documentId);
// console.info(ret);
// const f = new File([ret], 'xx.pdf', { type: ret.type });
// setFile(f);
// }, [documentId]);
// useEffect(() => {
// // dispatch({ type: 'kFModel/fetch_document_file', payload: documentId });
// fetch_document_file();
// }, [fetch_document_file]);
return (
<div>
{file && (
<Document file={file} onLoadSuccess={onDocumentLoadSuccess}>
<Page pageNumber={pageNumber} />
</Document>
)}
<p>
Page {pageNumber} of {numPages}
</p>
<div ref={setContainerRef} className={styles.documentContainer}>
<Document
file={url}
onLoadSuccess={onDocumentLoadSuccess}
// options={options}
>
{Array.from(new Array(numPages), (el, index) => (
<Page
key={`page_${index + 1}`}
pageNumber={index + 1}
width={containerWidth}
/>
))}
</Document>
{/* <input type="file" onChange={handleChange} /> */}
</div>
);

View file

@ -0,0 +1,9 @@
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
import { useSelector } from 'umi';
export const useSelectDocumentInfo = () => {
const documentInfo: IKnowledgeFile = useSelector(
(state: any) => state.chunkModel.documentInfo,
);
return documentInfo;
};

View file

@ -24,8 +24,7 @@
}
.documentPreview {
width: 30%;
overflow: auto;
width: 40%;
height: 100%;
}

View file

@ -9,6 +9,7 @@ import { useDeleteChunkByIds } from '@/hooks/knowledgeHook';
import ChunkCard from './components/chunk-card';
import ChunkToolBar from './components/chunk-toolbar';
import DocumentPreview from './components/document-preview';
import { useSelectDocumentInfo } from './hooks';
import styles from './index.less';
import { ChunkModelState } from './model';
@ -34,6 +35,7 @@ const Chunk = () => {
const documentId: string = searchParams.get('doc_id') || '';
const [chunkId, setChunkId] = useState<string | undefined>();
const { removeChunk } = useDeleteChunkByIds();
const documentInfo = useSelectDocumentInfo();
const getChunkList = useCallback(() => {
const payload: PayloadType = {
@ -197,9 +199,12 @@ const Chunk = () => {
/>
</div>
</Flex>
<section className={styles.documentPreview}>
<DocumentPreview></DocumentPreview>
</section>
{documentInfo.type === 'pdf' && (
<section className={styles.documentPreview}>
<DocumentPreview></DocumentPreview>
</section>
)}
</Flex>
</div>
<CreatingModal doc_id={documentId} chunkId={chunkId} />

View file

@ -13,7 +13,7 @@ export interface ChunkModelState extends BaseState {
chunk_id: string;
doc_id: string;
chunkInfo: any;
documentInfo: Partial<IKnowledgeFile>;
documentInfo: IKnowledgeFile;
available?: number;
}
@ -26,7 +26,7 @@ const model: DvaModel<ChunkModelState> = {
chunk_id: '',
doc_id: '',
chunkInfo: {},
documentInfo: {},
documentInfo: {} as IKnowledgeFile,
pagination: {
current: 1,
pageSize: 10,