balibabu
commited on
Commit
·
31c7dca
1
Parent(s):
d3812ff
fix: by obtaining the width and height of the pdf and passing it to b… (#151)
Browse files* 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
- web/src/components/pdf-previewer/index.tsx +61 -52
- web/src/hooks/documentHooks.ts +16 -5
- web/src/less/mixins.less +4 -4
- web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/preview.tsx +61 -51
- web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts +14 -6
- web/src/utils/documentUtils.ts +10 -10
web/src/components/pdf-previewer/index.tsx
CHANGED
@@ -35,7 +35,7 @@ const HighlightPopup = ({
|
|
35 |
|
36 |
const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => {
|
37 |
const url = useGetDocumentUrl(documentId);
|
38 |
-
const state = useGetChunkHighlights(chunk);
|
39 |
const ref = useRef<(highlight: IHighlight) => void>(() => {});
|
40 |
const [loaded, setLoaded] = useState(false);
|
41 |
|
@@ -59,59 +59,68 @@ const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => {
|
|
59 |
beforeLoad={<Skeleton active />}
|
60 |
workerSrc="/pdfjs-dist/pdf.worker.min.js"
|
61 |
>
|
62 |
-
{(pdfDocument) =>
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
setLoaded(true);
|
70 |
-
}}
|
71 |
-
onSelectionFinished={() => null}
|
72 |
-
highlightTransform={(
|
73 |
-
highlight,
|
74 |
-
index,
|
75 |
-
setTip,
|
76 |
-
hideTip,
|
77 |
-
viewportToScaled,
|
78 |
-
screenshot,
|
79 |
-
isScrolledTo,
|
80 |
-
) => {
|
81 |
-
const isTextHighlight = !Boolean(
|
82 |
-
highlight.content && highlight.content.image,
|
83 |
-
);
|
84 |
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
</PdfLoader>
|
116 |
</div>
|
117 |
);
|
|
|
35 |
|
36 |
const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => {
|
37 |
const url = useGetDocumentUrl(documentId);
|
38 |
+
const { highlights: state, setWidthAndHeight } = useGetChunkHighlights(chunk);
|
39 |
const ref = useRef<(highlight: IHighlight) => void>(() => {});
|
40 |
const [loaded, setLoaded] = useState(false);
|
41 |
|
|
|
59 |
beforeLoad={<Skeleton active />}
|
60 |
workerSrc="/pdfjs-dist/pdf.worker.min.js"
|
61 |
>
|
62 |
+
{(pdfDocument) => {
|
63 |
+
pdfDocument.getPage(1).then((page) => {
|
64 |
+
const viewport = page.getViewport({ scale: 1 });
|
65 |
+
const width = viewport.width;
|
66 |
+
const height = viewport.height;
|
67 |
+
setWidthAndHeight(width, height);
|
68 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
|
70 |
+
return (
|
71 |
+
<PdfHighlighter
|
72 |
+
pdfDocument={pdfDocument}
|
73 |
+
enableAreaSelection={(event) => event.altKey}
|
74 |
+
onScrollChange={resetHash}
|
75 |
+
scrollRef={(scrollTo) => {
|
76 |
+
ref.current = scrollTo;
|
77 |
+
setLoaded(true);
|
78 |
+
}}
|
79 |
+
onSelectionFinished={() => null}
|
80 |
+
highlightTransform={(
|
81 |
+
highlight,
|
82 |
+
index,
|
83 |
+
setTip,
|
84 |
+
hideTip,
|
85 |
+
viewportToScaled,
|
86 |
+
screenshot,
|
87 |
+
isScrolledTo,
|
88 |
+
) => {
|
89 |
+
const isTextHighlight = !Boolean(
|
90 |
+
highlight.content && highlight.content.image,
|
91 |
+
);
|
92 |
|
93 |
+
const component = isTextHighlight ? (
|
94 |
+
<Highlight
|
95 |
+
isScrolledTo={isScrolledTo}
|
96 |
+
position={highlight.position}
|
97 |
+
comment={highlight.comment}
|
98 |
+
/>
|
99 |
+
) : (
|
100 |
+
<AreaHighlight
|
101 |
+
isScrolledTo={isScrolledTo}
|
102 |
+
highlight={highlight}
|
103 |
+
onChange={() => {}}
|
104 |
+
/>
|
105 |
+
);
|
106 |
+
|
107 |
+
return (
|
108 |
+
<Popup
|
109 |
+
popupContent={<HighlightPopup {...highlight} />}
|
110 |
+
onMouseOver={(popupContent) =>
|
111 |
+
setTip(highlight, () => popupContent)
|
112 |
+
}
|
113 |
+
onMouseOut={hideTip}
|
114 |
+
key={index}
|
115 |
+
>
|
116 |
+
{component}
|
117 |
+
</Popup>
|
118 |
+
);
|
119 |
+
}}
|
120 |
+
highlights={state}
|
121 |
+
/>
|
122 |
+
);
|
123 |
+
}}
|
124 |
</PdfLoader>
|
125 |
</div>
|
126 |
);
|
web/src/hooks/documentHooks.ts
CHANGED
@@ -2,7 +2,7 @@ import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
|
|
2 |
import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
|
3 |
import { api_host } from '@/utils/api';
|
4 |
import { buildChunkHighlights } from '@/utils/documentUtils';
|
5 |
-
import { useCallback, useMemo } from 'react';
|
6 |
import { IHighlight } from 'react-pdf-highlighter';
|
7 |
import { useDispatch, useSelector } from 'umi';
|
8 |
import { useGetKnowledgeSearchParams } from './routeHook';
|
@@ -15,12 +15,23 @@ export const useGetDocumentUrl = (documentId: string) => {
|
|
15 |
return url;
|
16 |
};
|
17 |
|
18 |
-
export const useGetChunkHighlights = (selectedChunk: IChunk)
|
|
|
|
|
19 |
const highlights: IHighlight[] = useMemo(() => {
|
20 |
-
return buildChunkHighlights(selectedChunk);
|
21 |
-
}, [selectedChunk]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
-
return highlights;
|
24 |
};
|
25 |
|
26 |
export const useFetchDocumentList = () => {
|
|
|
2 |
import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
|
3 |
import { api_host } from '@/utils/api';
|
4 |
import { buildChunkHighlights } from '@/utils/documentUtils';
|
5 |
+
import { useCallback, useMemo, useState } from 'react';
|
6 |
import { IHighlight } from 'react-pdf-highlighter';
|
7 |
import { useDispatch, useSelector } from 'umi';
|
8 |
import { useGetKnowledgeSearchParams } from './routeHook';
|
|
|
15 |
return url;
|
16 |
};
|
17 |
|
18 |
+
export const useGetChunkHighlights = (selectedChunk: IChunk) => {
|
19 |
+
const [size, setSize] = useState({ width: 849, height: 1200 });
|
20 |
+
|
21 |
const highlights: IHighlight[] = useMemo(() => {
|
22 |
+
return buildChunkHighlights(selectedChunk, size);
|
23 |
+
}, [selectedChunk, size]);
|
24 |
+
|
25 |
+
const setWidthAndHeight = (width: number, height: number) => {
|
26 |
+
setSize((pre) => {
|
27 |
+
if (pre.height !== height || pre.width !== width) {
|
28 |
+
return { height, width };
|
29 |
+
}
|
30 |
+
return pre;
|
31 |
+
});
|
32 |
+
};
|
33 |
|
34 |
+
return { highlights, setWidthAndHeight };
|
35 |
};
|
36 |
|
37 |
export const useFetchDocumentList = () => {
|
web/src/less/mixins.less
CHANGED
@@ -9,11 +9,11 @@
|
|
9 |
|
10 |
caption {
|
11 |
color: @blurBackground;
|
12 |
-
font-size:
|
13 |
-
height:
|
14 |
-
line-height:
|
15 |
font-weight: 600;
|
16 |
-
margin-bottom:
|
17 |
}
|
18 |
|
19 |
th {
|
|
|
9 |
|
10 |
caption {
|
11 |
color: @blurBackground;
|
12 |
+
font-size: 14px;
|
13 |
+
height: 20px;
|
14 |
+
line-height: 20px;
|
15 |
font-weight: 600;
|
16 |
+
margin-bottom: 6px;
|
17 |
}
|
18 |
|
19 |
th {
|
web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/preview.tsx
CHANGED
@@ -30,7 +30,8 @@ const HighlightPopup = ({
|
|
30 |
// TODO: merge with DocumentPreviewer
|
31 |
const Preview = ({ selectedChunkId }: IProps) => {
|
32 |
const url = useGetDocumentUrl();
|
33 |
-
const state =
|
|
|
34 |
const ref = useRef<(highlight: IHighlight) => void>(() => {});
|
35 |
|
36 |
const resetHash = () => {};
|
@@ -48,58 +49,67 @@ const Preview = ({ selectedChunkId }: IProps) => {
|
|
48 |
beforeLoad={<Skeleton active />}
|
49 |
workerSrc="/pdfjs-dist/pdf.worker.min.js"
|
50 |
>
|
51 |
-
{(pdfDocument) =>
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
}}
|
59 |
-
onSelectionFinished={() => null}
|
60 |
-
highlightTransform={(
|
61 |
-
highlight,
|
62 |
-
index,
|
63 |
-
setTip,
|
64 |
-
hideTip,
|
65 |
-
viewportToScaled,
|
66 |
-
screenshot,
|
67 |
-
isScrolledTo,
|
68 |
-
) => {
|
69 |
-
const isTextHighlight = !Boolean(
|
70 |
-
highlight.content && highlight.content.image,
|
71 |
-
);
|
72 |
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
</PdfLoader>
|
104 |
</div>
|
105 |
);
|
|
|
30 |
// TODO: merge with DocumentPreviewer
|
31 |
const Preview = ({ selectedChunkId }: IProps) => {
|
32 |
const url = useGetDocumentUrl();
|
33 |
+
const { highlights: state, setWidthAndHeight } =
|
34 |
+
useGetChunkHighlights(selectedChunkId);
|
35 |
const ref = useRef<(highlight: IHighlight) => void>(() => {});
|
36 |
|
37 |
const resetHash = () => {};
|
|
|
49 |
beforeLoad={<Skeleton active />}
|
50 |
workerSrc="/pdfjs-dist/pdf.worker.min.js"
|
51 |
>
|
52 |
+
{(pdfDocument) => {
|
53 |
+
pdfDocument.getPage(1).then((page) => {
|
54 |
+
const viewport = page.getViewport({ scale: 1 });
|
55 |
+
const width = viewport.width;
|
56 |
+
const height = viewport.height;
|
57 |
+
setWidthAndHeight(width, height);
|
58 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
|
60 |
+
return (
|
61 |
+
<PdfHighlighter
|
62 |
+
pdfDocument={pdfDocument}
|
63 |
+
enableAreaSelection={(event) => event.altKey}
|
64 |
+
onScrollChange={resetHash}
|
65 |
+
scrollRef={(scrollTo) => {
|
66 |
+
ref.current = scrollTo;
|
67 |
+
}}
|
68 |
+
onSelectionFinished={() => null}
|
69 |
+
highlightTransform={(
|
70 |
+
highlight,
|
71 |
+
index,
|
72 |
+
setTip,
|
73 |
+
hideTip,
|
74 |
+
viewportToScaled,
|
75 |
+
screenshot,
|
76 |
+
isScrolledTo,
|
77 |
+
) => {
|
78 |
+
const isTextHighlight = !Boolean(
|
79 |
+
highlight.content && highlight.content.image,
|
80 |
+
);
|
81 |
|
82 |
+
const component = isTextHighlight ? (
|
83 |
+
<Highlight
|
84 |
+
isScrolledTo={isScrolledTo}
|
85 |
+
position={highlight.position}
|
86 |
+
comment={highlight.comment}
|
87 |
+
/>
|
88 |
+
) : (
|
89 |
+
<AreaHighlight
|
90 |
+
isScrolledTo={isScrolledTo}
|
91 |
+
highlight={highlight}
|
92 |
+
onChange={() => {}}
|
93 |
+
/>
|
94 |
+
);
|
95 |
+
|
96 |
+
return (
|
97 |
+
<Popup
|
98 |
+
popupContent={<HighlightPopup {...highlight} />}
|
99 |
+
onMouseOver={(popupContent) =>
|
100 |
+
setTip(highlight, () => popupContent)
|
101 |
+
}
|
102 |
+
onMouseOut={hideTip}
|
103 |
+
key={index}
|
104 |
+
>
|
105 |
+
{component}
|
106 |
+
</Popup>
|
107 |
+
);
|
108 |
+
}}
|
109 |
+
highlights={state}
|
110 |
+
/>
|
111 |
+
);
|
112 |
+
}}
|
113 |
</PdfLoader>
|
114 |
</div>
|
115 |
);
|
web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts
CHANGED
@@ -36,16 +36,24 @@ export const useGetSelectedChunk = (selectedChunkId: string) => {
|
|
36 |
);
|
37 |
};
|
38 |
|
39 |
-
export const useGetChunkHighlights = (
|
40 |
-
|
41 |
-
): IHighlight[] => {
|
42 |
const selectedChunk: IChunk = useGetSelectedChunk(selectedChunkId);
|
43 |
|
44 |
const highlights: IHighlight[] = useMemo(() => {
|
45 |
-
return buildChunkHighlights(selectedChunk);
|
46 |
-
}, [selectedChunk]);
|
47 |
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
};
|
50 |
|
51 |
export const useSelectChunkListLoading = () => {
|
|
|
36 |
);
|
37 |
};
|
38 |
|
39 |
+
export const useGetChunkHighlights = (selectedChunkId: string) => {
|
40 |
+
const [size, setSize] = useState({ width: 849, height: 1200 });
|
|
|
41 |
const selectedChunk: IChunk = useGetSelectedChunk(selectedChunkId);
|
42 |
|
43 |
const highlights: IHighlight[] = useMemo(() => {
|
44 |
+
return buildChunkHighlights(selectedChunk, size);
|
45 |
+
}, [selectedChunk, size]);
|
46 |
|
47 |
+
const setWidthAndHeight = (width: number, height: number) => {
|
48 |
+
setSize((pre) => {
|
49 |
+
if (pre.height !== height || pre.width !== width) {
|
50 |
+
return { height, width };
|
51 |
+
}
|
52 |
+
return pre;
|
53 |
+
});
|
54 |
+
};
|
55 |
+
|
56 |
+
return { highlights, setWidthAndHeight };
|
57 |
};
|
58 |
|
59 |
export const useSelectChunkListLoading = () => {
|
web/src/utils/documentUtils.ts
CHANGED
@@ -2,20 +2,20 @@ import { IChunk } from '@/interfaces/database/knowledge';
|
|
2 |
import { UploadFile } from 'antd';
|
3 |
import { v4 as uuid } from 'uuid';
|
4 |
|
5 |
-
export const buildChunkHighlights = (
|
|
|
|
|
|
|
6 |
return Array.isArray(selectedChunk?.positions) &&
|
7 |
selectedChunk.positions.every((x) => Array.isArray(x))
|
8 |
? selectedChunk?.positions?.map((x) => {
|
9 |
-
const actualPositions = x.map((y, index) =>
|
10 |
-
index !== 0 ? y / 0.7 : y,
|
11 |
-
);
|
12 |
const boundingRect = {
|
13 |
-
width:
|
14 |
-
height:
|
15 |
-
x1:
|
16 |
-
x2:
|
17 |
-
y1:
|
18 |
-
y2:
|
19 |
};
|
20 |
return {
|
21 |
id: uuid(),
|
|
|
2 |
import { UploadFile } from 'antd';
|
3 |
import { v4 as uuid } from 'uuid';
|
4 |
|
5 |
+
export const buildChunkHighlights = (
|
6 |
+
selectedChunk: IChunk,
|
7 |
+
size: { width: number; height: number },
|
8 |
+
) => {
|
9 |
return Array.isArray(selectedChunk?.positions) &&
|
10 |
selectedChunk.positions.every((x) => Array.isArray(x))
|
11 |
? selectedChunk?.positions?.map((x) => {
|
|
|
|
|
|
|
12 |
const boundingRect = {
|
13 |
+
width: size.width,
|
14 |
+
height: size.height,
|
15 |
+
x1: x[1],
|
16 |
+
x2: x[2],
|
17 |
+
y1: x[3],
|
18 |
+
y2: x[4],
|
19 |
};
|
20 |
return {
|
21 |
id: uuid(),
|