fix: by obtaining the width and height of the pdf and passing it to b… (#151)

* fix: by obtaining the width and height of the pdf and passing it to boundingRect, the problem of inaccurate positioning of file highlighting is fixed

* feat: remove actualPositions from buildChunkHighlights
This commit is contained in:
balibabu 2024-03-26 14:51:34 +08:00 committed by GitHub
parent 0dd5b58d03
commit 75f7c6da2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 167 additions and 129 deletions

View File

@ -35,7 +35,7 @@ const HighlightPopup = ({
const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => { const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => {
const url = useGetDocumentUrl(documentId); const url = useGetDocumentUrl(documentId);
const state = useGetChunkHighlights(chunk); const { highlights: state, setWidthAndHeight } = useGetChunkHighlights(chunk);
const ref = useRef<(highlight: IHighlight) => void>(() => {}); const ref = useRef<(highlight: IHighlight) => void>(() => {});
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
@ -59,59 +59,68 @@ const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => {
beforeLoad={<Skeleton active />} beforeLoad={<Skeleton active />}
workerSrc="/pdfjs-dist/pdf.worker.min.js" workerSrc="/pdfjs-dist/pdf.worker.min.js"
> >
{(pdfDocument) => ( {(pdfDocument) => {
<PdfHighlighter pdfDocument.getPage(1).then((page) => {
pdfDocument={pdfDocument} const viewport = page.getViewport({ scale: 1 });
enableAreaSelection={(event) => event.altKey} const width = viewport.width;
onScrollChange={resetHash} const height = viewport.height;
scrollRef={(scrollTo) => { setWidthAndHeight(width, height);
ref.current = scrollTo; });
setLoaded(true);
}}
onSelectionFinished={() => null}
highlightTransform={(
highlight,
index,
setTip,
hideTip,
viewportToScaled,
screenshot,
isScrolledTo,
) => {
const isTextHighlight = !Boolean(
highlight.content && highlight.content.image,
);
const component = isTextHighlight ? ( return (
<Highlight <PdfHighlighter
isScrolledTo={isScrolledTo} pdfDocument={pdfDocument}
position={highlight.position} enableAreaSelection={(event) => event.altKey}
comment={highlight.comment} onScrollChange={resetHash}
/> scrollRef={(scrollTo) => {
) : ( ref.current = scrollTo;
<AreaHighlight setLoaded(true);
isScrolledTo={isScrolledTo} }}
highlight={highlight} onSelectionFinished={() => null}
onChange={() => {}} highlightTransform={(
/> highlight,
); index,
setTip,
hideTip,
viewportToScaled,
screenshot,
isScrolledTo,
) => {
const isTextHighlight = !Boolean(
highlight.content && highlight.content.image,
);
return ( const component = isTextHighlight ? (
<Popup <Highlight
popupContent={<HighlightPopup {...highlight} />} isScrolledTo={isScrolledTo}
onMouseOver={(popupContent) => position={highlight.position}
setTip(highlight, () => popupContent) comment={highlight.comment}
} />
onMouseOut={hideTip} ) : (
key={index} <AreaHighlight
> isScrolledTo={isScrolledTo}
{component} highlight={highlight}
</Popup> onChange={() => {}}
); />
}} );
highlights={state}
/> return (
)} <Popup
popupContent={<HighlightPopup {...highlight} />}
onMouseOver={(popupContent) =>
setTip(highlight, () => popupContent)
}
onMouseOut={hideTip}
key={index}
>
{component}
</Popup>
);
}}
highlights={state}
/>
);
}}
</PdfLoader> </PdfLoader>
</div> </div>
); );

View File

@ -2,7 +2,7 @@ import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
import { api_host } from '@/utils/api'; import { api_host } from '@/utils/api';
import { buildChunkHighlights } from '@/utils/documentUtils'; import { buildChunkHighlights } from '@/utils/documentUtils';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { IHighlight } from 'react-pdf-highlighter'; import { IHighlight } from 'react-pdf-highlighter';
import { useDispatch, useSelector } from 'umi'; import { useDispatch, useSelector } from 'umi';
import { useGetKnowledgeSearchParams } from './routeHook'; import { useGetKnowledgeSearchParams } from './routeHook';
@ -15,12 +15,23 @@ export const useGetDocumentUrl = (documentId: string) => {
return url; return url;
}; };
export const useGetChunkHighlights = (selectedChunk: IChunk): IHighlight[] => { export const useGetChunkHighlights = (selectedChunk: IChunk) => {
const highlights: IHighlight[] = useMemo(() => { const [size, setSize] = useState({ width: 849, height: 1200 });
return buildChunkHighlights(selectedChunk);
}, [selectedChunk]);
return highlights; const highlights: IHighlight[] = useMemo(() => {
return buildChunkHighlights(selectedChunk, size);
}, [selectedChunk, size]);
const setWidthAndHeight = (width: number, height: number) => {
setSize((pre) => {
if (pre.height !== height || pre.width !== width) {
return { height, width };
}
return pre;
});
};
return { highlights, setWidthAndHeight };
}; };
export const useFetchDocumentList = () => { export const useFetchDocumentList = () => {

View File

@ -9,11 +9,11 @@
caption { caption {
color: @blurBackground; color: @blurBackground;
font-size: 20px; font-size: 14px;
height: 50px; height: 20px;
line-height: 50px; line-height: 20px;
font-weight: 600; font-weight: 600;
margin-bottom: 10px; margin-bottom: 6px;
} }
th { th {

View File

@ -30,7 +30,8 @@ const HighlightPopup = ({
// TODO: merge with DocumentPreviewer // TODO: merge with DocumentPreviewer
const Preview = ({ selectedChunkId }: IProps) => { const Preview = ({ selectedChunkId }: IProps) => {
const url = useGetDocumentUrl(); const url = useGetDocumentUrl();
const state = useGetChunkHighlights(selectedChunkId); const { highlights: state, setWidthAndHeight } =
useGetChunkHighlights(selectedChunkId);
const ref = useRef<(highlight: IHighlight) => void>(() => {}); const ref = useRef<(highlight: IHighlight) => void>(() => {});
const resetHash = () => {}; const resetHash = () => {};
@ -48,58 +49,67 @@ const Preview = ({ selectedChunkId }: IProps) => {
beforeLoad={<Skeleton active />} beforeLoad={<Skeleton active />}
workerSrc="/pdfjs-dist/pdf.worker.min.js" workerSrc="/pdfjs-dist/pdf.worker.min.js"
> >
{(pdfDocument) => ( {(pdfDocument) => {
<PdfHighlighter pdfDocument.getPage(1).then((page) => {
pdfDocument={pdfDocument} const viewport = page.getViewport({ scale: 1 });
enableAreaSelection={(event) => event.altKey} const width = viewport.width;
onScrollChange={resetHash} const height = viewport.height;
scrollRef={(scrollTo) => { setWidthAndHeight(width, height);
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 (
<Highlight <PdfHighlighter
isScrolledTo={isScrolledTo} pdfDocument={pdfDocument}
position={highlight.position} enableAreaSelection={(event) => event.altKey}
comment={highlight.comment} onScrollChange={resetHash}
/> scrollRef={(scrollTo) => {
) : ( ref.current = scrollTo;
<AreaHighlight }}
isScrolledTo={isScrolledTo} onSelectionFinished={() => null}
highlight={highlight} highlightTransform={(
onChange={() => {}} highlight,
/> index,
); setTip,
hideTip,
viewportToScaled,
screenshot,
isScrolledTo,
) => {
const isTextHighlight = !Boolean(
highlight.content && highlight.content.image,
);
return ( const component = isTextHighlight ? (
<Popup <Highlight
popupContent={<HighlightPopup {...highlight} />} isScrolledTo={isScrolledTo}
onMouseOver={(popupContent) => position={highlight.position}
setTip(highlight, () => popupContent) comment={highlight.comment}
} />
onMouseOut={hideTip} ) : (
key={index} <AreaHighlight
> isScrolledTo={isScrolledTo}
{component} highlight={highlight}
</Popup> onChange={() => {}}
); />
}} );
highlights={state}
/> return (
)} <Popup
popupContent={<HighlightPopup {...highlight} />}
onMouseOver={(popupContent) =>
setTip(highlight, () => popupContent)
}
onMouseOut={hideTip}
key={index}
>
{component}
</Popup>
);
}}
highlights={state}
/>
);
}}
</PdfLoader> </PdfLoader>
</div> </div>
); );

View File

@ -36,16 +36,24 @@ export const useGetSelectedChunk = (selectedChunkId: string) => {
); );
}; };
export const useGetChunkHighlights = ( export const useGetChunkHighlights = (selectedChunkId: string) => {
selectedChunkId: string, const [size, setSize] = useState({ width: 849, height: 1200 });
): IHighlight[] => {
const selectedChunk: IChunk = useGetSelectedChunk(selectedChunkId); const selectedChunk: IChunk = useGetSelectedChunk(selectedChunkId);
const highlights: IHighlight[] = useMemo(() => { const highlights: IHighlight[] = useMemo(() => {
return buildChunkHighlights(selectedChunk); return buildChunkHighlights(selectedChunk, size);
}, [selectedChunk]); }, [selectedChunk, size]);
return highlights; const setWidthAndHeight = (width: number, height: number) => {
setSize((pre) => {
if (pre.height !== height || pre.width !== width) {
return { height, width };
}
return pre;
});
};
return { highlights, setWidthAndHeight };
}; };
export const useSelectChunkListLoading = () => { export const useSelectChunkListLoading = () => {

View File

@ -2,20 +2,20 @@ import { IChunk } from '@/interfaces/database/knowledge';
import { UploadFile } from 'antd'; import { UploadFile } from 'antd';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
export const buildChunkHighlights = (selectedChunk: IChunk) => { export const buildChunkHighlights = (
selectedChunk: IChunk,
size: { width: number; height: number },
) => {
return Array.isArray(selectedChunk?.positions) && return Array.isArray(selectedChunk?.positions) &&
selectedChunk.positions.every((x) => Array.isArray(x)) selectedChunk.positions.every((x) => Array.isArray(x))
? selectedChunk?.positions?.map((x) => { ? selectedChunk?.positions?.map((x) => {
const actualPositions = x.map((y, index) =>
index !== 0 ? y / 0.7 : y,
);
const boundingRect = { const boundingRect = {
width: 849, width: size.width,
height: 1200, height: size.height,
x1: actualPositions[1], x1: x[1],
x2: actualPositions[2], x2: x[2],
y1: actualPositions[3], y1: x[3],
y2: actualPositions[4], y2: x[4],
}; };
return { return {
id: uuid(), id: uuid(),