balibabu
commited on
Commit
·
f422a06
1
Parent(s):
e4e6a45
feat: add Preview with react-pdf-highlighter (#89)
Browse files* feat: add selected style to chunk item
* feat: hightlight pdf
* feat: add Preview with react-pdf-highlighter
- web/package-lock.json +96 -2
- web/package.json +1 -0
- web/src/less/variable.less +1 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.less +4 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx +12 -3
- web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/hightlights.ts +33 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/hooks.ts +36 -1
- web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/index.less +7 -2
- web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/index.tsx +12 -28
- web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/preview.tsx +189 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts +24 -1
- web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx +9 -3
- web/src/pages/add-knowledge/components/knowledge-chunk/model.ts +2 -2
web/package-lock.json
CHANGED
|
@@ -24,6 +24,7 @@
|
|
| 24 |
"react-infinite-scroll-component": "^6.1.0",
|
| 25 |
"react-markdown": "^9.0.1",
|
| 26 |
"react-pdf": "^7.7.1",
|
|
|
|
| 27 |
"react-string-replace": "^1.1.1",
|
| 28 |
"umi": "^4.0.90",
|
| 29 |
"umi-request": "^1.4.0",
|
|
@@ -7264,6 +7265,12 @@
|
|
| 7264 |
"node": ">= 4"
|
| 7265 |
}
|
| 7266 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7267 |
"node_modules/domutils": {
|
| 7268 |
"version": "2.8.0",
|
| 7269 |
"resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz",
|
|
@@ -8562,6 +8569,11 @@
|
|
| 8562 |
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
| 8563 |
"peer": true
|
| 8564 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8565 |
"node_modules/fast-redact": {
|
| 8566 |
"version": "3.3.0",
|
| 8567 |
"resolved": "https://registry.npmmirror.com/fast-redact/-/fast-redact-3.3.0.tgz",
|
|
@@ -11209,8 +11221,7 @@
|
|
| 11209 |
"node_modules/lodash.debounce": {
|
| 11210 |
"version": "4.0.8",
|
| 11211 |
"resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
| 11212 |
-
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
|
| 11213 |
-
"dev": true
|
| 11214 |
},
|
| 11215 |
"node_modules/lodash.merge": {
|
| 11216 |
"version": "4.6.2",
|
|
@@ -14417,6 +14428,18 @@
|
|
| 14417 |
"react-dom": "*"
|
| 14418 |
}
|
| 14419 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14420 |
"node_modules/react": {
|
| 14421 |
"version": "18.2.0",
|
| 14422 |
"resolved": "https://registry.npmmirror.com/react/-/react-18.2.0.tgz",
|
|
@@ -14736,6 +14759,27 @@
|
|
| 14736 |
"react": "^18.2.0"
|
| 14737 |
}
|
| 14738 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14739 |
"node_modules/react-error-overlay": {
|
| 14740 |
"version": "6.0.9",
|
| 14741 |
"resolved": "https://registry.npmmirror.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
|
@@ -14872,6 +14916,37 @@
|
|
| 14872 |
}
|
| 14873 |
}
|
| 14874 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14875 |
"node_modules/react-refresh": {
|
| 14876 |
"version": "0.14.0",
|
| 14877 |
"resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.14.0.tgz",
|
|
@@ -14880,6 +14955,25 @@
|
|
| 14880 |
"node": ">=0.10.0"
|
| 14881 |
}
|
| 14882 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14883 |
"node_modules/react-router": {
|
| 14884 |
"version": "6.3.0",
|
| 14885 |
"resolved": "https://registry.npmmirror.com/react-router/-/react-router-6.3.0.tgz",
|
|
|
|
| 24 |
"react-infinite-scroll-component": "^6.1.0",
|
| 25 |
"react-markdown": "^9.0.1",
|
| 26 |
"react-pdf": "^7.7.1",
|
| 27 |
+
"react-pdf-highlighter": "^6.1.0",
|
| 28 |
"react-string-replace": "^1.1.1",
|
| 29 |
"umi": "^4.0.90",
|
| 30 |
"umi-request": "^1.4.0",
|
|
|
|
| 7265 |
"node": ">= 4"
|
| 7266 |
}
|
| 7267 |
},
|
| 7268 |
+
"node_modules/dommatrix": {
|
| 7269 |
+
"version": "1.0.3",
|
| 7270 |
+
"resolved": "https://registry.npmmirror.com/dommatrix/-/dommatrix-1.0.3.tgz",
|
| 7271 |
+
"integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==",
|
| 7272 |
+
"deprecated": "dommatrix is no longer maintained. Please use @thednp/dommatrix."
|
| 7273 |
+
},
|
| 7274 |
"node_modules/domutils": {
|
| 7275 |
"version": "2.8.0",
|
| 7276 |
"resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz",
|
|
|
|
| 8569 |
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
| 8570 |
"peer": true
|
| 8571 |
},
|
| 8572 |
+
"node_modules/fast-memoize": {
|
| 8573 |
+
"version": "2.5.2",
|
| 8574 |
+
"resolved": "https://registry.npmmirror.com/fast-memoize/-/fast-memoize-2.5.2.tgz",
|
| 8575 |
+
"integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw=="
|
| 8576 |
+
},
|
| 8577 |
"node_modules/fast-redact": {
|
| 8578 |
"version": "3.3.0",
|
| 8579 |
"resolved": "https://registry.npmmirror.com/fast-redact/-/fast-redact-3.3.0.tgz",
|
|
|
|
| 11221 |
"node_modules/lodash.debounce": {
|
| 11222 |
"version": "4.0.8",
|
| 11223 |
"resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
| 11224 |
+
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
|
|
|
|
| 11225 |
},
|
| 11226 |
"node_modules/lodash.merge": {
|
| 11227 |
"version": "4.6.2",
|
|
|
|
| 14428 |
"react-dom": "*"
|
| 14429 |
}
|
| 14430 |
},
|
| 14431 |
+
"node_modules/re-resizable": {
|
| 14432 |
+
"version": "6.9.6",
|
| 14433 |
+
"resolved": "https://registry.npmmirror.com/re-resizable/-/re-resizable-6.9.6.tgz",
|
| 14434 |
+
"integrity": "sha512-0xYKS5+Z0zk+vICQlcZW+g54CcJTTmHluA7JUUgvERDxnKAnytylcyPsA+BSFi759s5hPlHmBRegFrwXs2FuBQ==",
|
| 14435 |
+
"dependencies": {
|
| 14436 |
+
"fast-memoize": "^2.5.1"
|
| 14437 |
+
},
|
| 14438 |
+
"peerDependencies": {
|
| 14439 |
+
"react": "^16.13.1 || ^17.0.0 || ^18.0.0",
|
| 14440 |
+
"react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0"
|
| 14441 |
+
}
|
| 14442 |
+
},
|
| 14443 |
"node_modules/react": {
|
| 14444 |
"version": "18.2.0",
|
| 14445 |
"resolved": "https://registry.npmmirror.com/react/-/react-18.2.0.tgz",
|
|
|
|
| 14759 |
"react": "^18.2.0"
|
| 14760 |
}
|
| 14761 |
},
|
| 14762 |
+
"node_modules/react-draggable": {
|
| 14763 |
+
"version": "4.4.5",
|
| 14764 |
+
"resolved": "https://registry.npmmirror.com/react-draggable/-/react-draggable-4.4.5.tgz",
|
| 14765 |
+
"integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==",
|
| 14766 |
+
"dependencies": {
|
| 14767 |
+
"clsx": "^1.1.1",
|
| 14768 |
+
"prop-types": "^15.8.1"
|
| 14769 |
+
},
|
| 14770 |
+
"peerDependencies": {
|
| 14771 |
+
"react": ">= 16.3.0",
|
| 14772 |
+
"react-dom": ">= 16.3.0"
|
| 14773 |
+
}
|
| 14774 |
+
},
|
| 14775 |
+
"node_modules/react-draggable/node_modules/clsx": {
|
| 14776 |
+
"version": "1.2.1",
|
| 14777 |
+
"resolved": "https://registry.npmmirror.com/clsx/-/clsx-1.2.1.tgz",
|
| 14778 |
+
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
| 14779 |
+
"engines": {
|
| 14780 |
+
"node": ">=6"
|
| 14781 |
+
}
|
| 14782 |
+
},
|
| 14783 |
"node_modules/react-error-overlay": {
|
| 14784 |
"version": "6.0.9",
|
| 14785 |
"resolved": "https://registry.npmmirror.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
|
|
|
| 14916 |
}
|
| 14917 |
}
|
| 14918 |
},
|
| 14919 |
+
"node_modules/react-pdf-highlighter": {
|
| 14920 |
+
"version": "6.1.0",
|
| 14921 |
+
"resolved": "https://registry.npmmirror.com/react-pdf-highlighter/-/react-pdf-highlighter-6.1.0.tgz",
|
| 14922 |
+
"integrity": "sha512-PD7l+0q1v+pZahLA/2AeWIb0n8d1amL6o+mOKnldIqtyChBHSE3gfnY5ZNMSFrhWXdlM6l4Eet+aydnYo6Skow==",
|
| 14923 |
+
"dependencies": {
|
| 14924 |
+
"lodash.debounce": "^4.0.8",
|
| 14925 |
+
"pdfjs-dist": "2.16.105",
|
| 14926 |
+
"react-rnd": "^10.1.10"
|
| 14927 |
+
},
|
| 14928 |
+
"peerDependencies": {
|
| 14929 |
+
"react": ">=18.0.0",
|
| 14930 |
+
"react-dom": ">=18.0.0"
|
| 14931 |
+
}
|
| 14932 |
+
},
|
| 14933 |
+
"node_modules/react-pdf-highlighter/node_modules/pdfjs-dist": {
|
| 14934 |
+
"version": "2.16.105",
|
| 14935 |
+
"resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz",
|
| 14936 |
+
"integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==",
|
| 14937 |
+
"dependencies": {
|
| 14938 |
+
"dommatrix": "^1.0.3",
|
| 14939 |
+
"web-streams-polyfill": "^3.2.1"
|
| 14940 |
+
},
|
| 14941 |
+
"peerDependencies": {
|
| 14942 |
+
"worker-loader": "^3.0.8"
|
| 14943 |
+
},
|
| 14944 |
+
"peerDependenciesMeta": {
|
| 14945 |
+
"worker-loader": {
|
| 14946 |
+
"optional": true
|
| 14947 |
+
}
|
| 14948 |
+
}
|
| 14949 |
+
},
|
| 14950 |
"node_modules/react-refresh": {
|
| 14951 |
"version": "0.14.0",
|
| 14952 |
"resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.14.0.tgz",
|
|
|
|
| 14955 |
"node": ">=0.10.0"
|
| 14956 |
}
|
| 14957 |
},
|
| 14958 |
+
"node_modules/react-rnd": {
|
| 14959 |
+
"version": "10.4.1",
|
| 14960 |
+
"resolved": "https://registry.npmmirror.com/react-rnd/-/react-rnd-10.4.1.tgz",
|
| 14961 |
+
"integrity": "sha512-0m887AjQZr6p2ADLNnipquqsDq4XJu/uqVqI3zuoGD19tRm6uB83HmZWydtkilNp5EWsOHbLGF4IjWMdd5du8Q==",
|
| 14962 |
+
"dependencies": {
|
| 14963 |
+
"re-resizable": "6.9.6",
|
| 14964 |
+
"react-draggable": "4.4.5",
|
| 14965 |
+
"tslib": "2.3.1"
|
| 14966 |
+
},
|
| 14967 |
+
"peerDependencies": {
|
| 14968 |
+
"react": ">=16.3.0",
|
| 14969 |
+
"react-dom": ">=16.3.0"
|
| 14970 |
+
}
|
| 14971 |
+
},
|
| 14972 |
+
"node_modules/react-rnd/node_modules/tslib": {
|
| 14973 |
+
"version": "2.3.1",
|
| 14974 |
+
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.1.tgz",
|
| 14975 |
+
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
|
| 14976 |
+
},
|
| 14977 |
"node_modules/react-router": {
|
| 14978 |
"version": "6.3.0",
|
| 14979 |
"resolved": "https://registry.npmmirror.com/react-router/-/react-router-6.3.0.tgz",
|
web/package.json
CHANGED
|
@@ -28,6 +28,7 @@
|
|
| 28 |
"react-infinite-scroll-component": "^6.1.0",
|
| 29 |
"react-markdown": "^9.0.1",
|
| 30 |
"react-pdf": "^7.7.1",
|
|
|
|
| 31 |
"react-string-replace": "^1.1.1",
|
| 32 |
"umi": "^4.0.90",
|
| 33 |
"umi-request": "^1.4.0",
|
|
|
|
| 28 |
"react-infinite-scroll-component": "^6.1.0",
|
| 29 |
"react-markdown": "^9.0.1",
|
| 30 |
"react-pdf": "^7.7.1",
|
| 31 |
+
"react-pdf-highlighter": "^6.1.0",
|
| 32 |
"react-string-replace": "^1.1.1",
|
| 33 |
"umi": "^4.0.90",
|
| 34 |
"umi-request": "^1.4.0",
|
web/src/less/variable.less
CHANGED
|
@@ -7,6 +7,7 @@
|
|
| 7 |
@gray8: rgba(165, 163, 169, 1);
|
| 8 |
@gray11: rgba(232, 232, 234, 1);
|
| 9 |
@purple: rgba(127, 86, 217, 1);
|
|
|
|
| 10 |
|
| 11 |
@fontSize12: 12px;
|
| 12 |
@fontSize14: 14px;
|
|
|
|
| 7 |
@gray8: rgba(165, 163, 169, 1);
|
| 8 |
@gray11: rgba(232, 232, 234, 1);
|
| 9 |
@purple: rgba(127, 86, 217, 1);
|
| 10 |
+
@selectedBackgroundColor: rgba(239, 248, 255, 1);
|
| 11 |
|
| 12 |
@fontSize12: 12px;
|
| 13 |
@fontSize14: 14px;
|
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.less
CHANGED
|
@@ -14,3 +14,7 @@
|
|
| 14 |
font-style: normal;
|
| 15 |
}
|
| 16 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
font-style: normal;
|
| 15 |
}
|
| 16 |
}
|
| 17 |
+
|
| 18 |
+
.cardSelected {
|
| 19 |
+
background-color: @selectedBackgroundColor;
|
| 20 |
+
}
|
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx
CHANGED
|
@@ -10,6 +10,8 @@ interface IProps {
|
|
| 10 |
switchChunk: (available?: number, chunkIds?: string[]) => void;
|
| 11 |
editChunk: (chunkId: string) => void;
|
| 12 |
handleCheckboxClick: (chunkId: string, checked: boolean) => void;
|
|
|
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
const ChunkCard = ({
|
|
@@ -18,6 +20,8 @@ const ChunkCard = ({
|
|
| 18 |
handleCheckboxClick,
|
| 19 |
editChunk,
|
| 20 |
switchChunk,
|
|
|
|
|
|
|
| 21 |
}: IProps) => {
|
| 22 |
const available = Number(item.available_int);
|
| 23 |
const [enabled, setEnabled] = useState(available === 1);
|
|
@@ -31,13 +35,17 @@ const ChunkCard = ({
|
|
| 31 |
handleCheckboxClick(item.chunk_id, e.target.checked);
|
| 32 |
};
|
| 33 |
|
| 34 |
-
const
|
| 35 |
editChunk(item.chunk_id);
|
| 36 |
};
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
return (
|
| 39 |
<div>
|
| 40 |
-
<Card>
|
| 41 |
<Flex gap={'middle'} justify={'space-between'}>
|
| 42 |
<Checkbox onChange={handleCheck} checked={checked}></Checkbox>
|
| 43 |
{item.img_id && (
|
|
@@ -52,7 +60,8 @@ const ChunkCard = ({
|
|
| 52 |
)}
|
| 53 |
|
| 54 |
<section
|
| 55 |
-
onDoubleClick={
|
|
|
|
| 56 |
className={styles.content}
|
| 57 |
dangerouslySetInnerHTML={{ __html: item.content_with_weight }}
|
| 58 |
>
|
|
|
|
| 10 |
switchChunk: (available?: number, chunkIds?: string[]) => void;
|
| 11 |
editChunk: (chunkId: string) => void;
|
| 12 |
handleCheckboxClick: (chunkId: string, checked: boolean) => void;
|
| 13 |
+
selected: boolean;
|
| 14 |
+
clickChunkCard: (chunkId: string) => void;
|
| 15 |
}
|
| 16 |
|
| 17 |
const ChunkCard = ({
|
|
|
|
| 20 |
handleCheckboxClick,
|
| 21 |
editChunk,
|
| 22 |
switchChunk,
|
| 23 |
+
selected,
|
| 24 |
+
clickChunkCard,
|
| 25 |
}: IProps) => {
|
| 26 |
const available = Number(item.available_int);
|
| 27 |
const [enabled, setEnabled] = useState(available === 1);
|
|
|
|
| 35 |
handleCheckboxClick(item.chunk_id, e.target.checked);
|
| 36 |
};
|
| 37 |
|
| 38 |
+
const handleContentDoubleClick = () => {
|
| 39 |
editChunk(item.chunk_id);
|
| 40 |
};
|
| 41 |
|
| 42 |
+
const handleContentClick = () => {
|
| 43 |
+
clickChunkCard(item.chunk_id);
|
| 44 |
+
};
|
| 45 |
+
|
| 46 |
return (
|
| 47 |
<div>
|
| 48 |
+
<Card className={selected ? styles.cardSelected : ''}>
|
| 49 |
<Flex gap={'middle'} justify={'space-between'}>
|
| 50 |
<Checkbox onChange={handleCheck} checked={checked}></Checkbox>
|
| 51 |
{item.img_id && (
|
|
|
|
| 60 |
)}
|
| 61 |
|
| 62 |
<section
|
| 63 |
+
onDoubleClick={handleContentDoubleClick}
|
| 64 |
+
onClick={handleContentClick}
|
| 65 |
className={styles.content}
|
| 66 |
dangerouslySetInnerHTML={{ __html: item.content_with_weight }}
|
| 67 |
>
|
web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/hightlights.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const testHighlights = [
|
| 2 |
+
{
|
| 3 |
+
content: {
|
| 4 |
+
text: '实验证明,由氧氯化锆锂和高镍三元正极组成的全固态锂电池展示了极为优异的性能:在12 分钟快速充电的条件下,该电池仍然成功地在室温稳定循环2000 圈以上。',
|
| 5 |
+
},
|
| 6 |
+
position: {
|
| 7 |
+
boundingRect: {
|
| 8 |
+
x1: 219.7,
|
| 9 |
+
y1: 204.3,
|
| 10 |
+
x2: 547.0,
|
| 11 |
+
y2: 264.0,
|
| 12 |
+
width: 849,
|
| 13 |
+
height: 1200,
|
| 14 |
+
},
|
| 15 |
+
rects: [
|
| 16 |
+
{
|
| 17 |
+
x1: 219.7,
|
| 18 |
+
y1: 204.3,
|
| 19 |
+
x2: 547.0,
|
| 20 |
+
y2: 264.0,
|
| 21 |
+
width: 849,
|
| 22 |
+
height: 1200,
|
| 23 |
+
},
|
| 24 |
+
],
|
| 25 |
+
pageNumber: 9,
|
| 26 |
+
},
|
| 27 |
+
comment: {
|
| 28 |
+
text: 'Flow or TypeScript?',
|
| 29 |
+
emoji: '🔥',
|
| 30 |
+
},
|
| 31 |
+
id: '8245652131754351',
|
| 32 |
+
},
|
| 33 |
+
];
|
web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/hooks.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
|
|
|
|
|
| 1 |
import { useSize } from 'ahooks';
|
| 2 |
-
import {
|
|
|
|
| 3 |
|
| 4 |
export const useDocumentResizeObserver = () => {
|
| 5 |
const [containerWidth, setContainerWidth] = useState<number>();
|
|
@@ -18,3 +21,35 @@ export const useDocumentResizeObserver = () => {
|
|
| 18 |
|
| 19 |
return { containerWidth, setContainerRef };
|
| 20 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useGetKnowledgeSearchParams } from '@/hooks/knowledgeHook';
|
| 2 |
+
import { api_host } from '@/utils/api';
|
| 3 |
import { useSize } from 'ahooks';
|
| 4 |
+
import { CustomTextRenderer } from 'node_modules/react-pdf/dist/esm/shared/types';
|
| 5 |
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
| 6 |
|
| 7 |
export const useDocumentResizeObserver = () => {
|
| 8 |
const [containerWidth, setContainerWidth] = useState<number>();
|
|
|
|
| 21 |
|
| 22 |
return { containerWidth, setContainerRef };
|
| 23 |
};
|
| 24 |
+
|
| 25 |
+
function highlightPattern(text: string, pattern: string, pageNumber: number) {
|
| 26 |
+
if (pageNumber === 2) {
|
| 27 |
+
return `<mark>${text}</mark>`;
|
| 28 |
+
}
|
| 29 |
+
if (text.trim() !== '' && pattern.match(text)) {
|
| 30 |
+
// return pattern.replace(text, (value) => `<mark>${value}</mark>`);
|
| 31 |
+
return `<mark>${text}</mark>`;
|
| 32 |
+
}
|
| 33 |
+
return text.replace(pattern, (value) => `<mark>${value}</mark>`);
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
export const useHighlightText = (searchText: string = '') => {
|
| 37 |
+
const textRenderer: CustomTextRenderer = useCallback(
|
| 38 |
+
(textItem) => {
|
| 39 |
+
return highlightPattern(textItem.str, searchText, textItem.pageNumber);
|
| 40 |
+
},
|
| 41 |
+
[searchText],
|
| 42 |
+
);
|
| 43 |
+
|
| 44 |
+
return textRenderer;
|
| 45 |
+
};
|
| 46 |
+
|
| 47 |
+
export const useGetDocumentUrl = () => {
|
| 48 |
+
const { documentId } = useGetKnowledgeSearchParams();
|
| 49 |
+
|
| 50 |
+
const url = useMemo(() => {
|
| 51 |
+
return `${api_host}/document/get/${documentId}`;
|
| 52 |
+
}, [documentId]);
|
| 53 |
+
|
| 54 |
+
return url;
|
| 55 |
+
};
|
web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/index.less
CHANGED
|
@@ -1,6 +1,11 @@
|
|
| 1 |
.documentContainer {
|
| 2 |
width: 100%;
|
| 3 |
height: calc(100vh - 284px);
|
| 4 |
-
overflow-y: auto;
|
| 5 |
-
overflow-x: hidden;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
}
|
|
|
|
| 1 |
.documentContainer {
|
| 2 |
width: 100%;
|
| 3 |
height: calc(100vh - 284px);
|
| 4 |
+
// overflow-y: auto;
|
| 5 |
+
// overflow-x: hidden;
|
| 6 |
+
position: relative;
|
| 7 |
+
:global(.PdfHighlighter) {
|
| 8 |
+
overflow-x: hidden;
|
| 9 |
+
// left: 0;
|
| 10 |
+
}
|
| 11 |
}
|
web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/index.tsx
CHANGED
|
@@ -5,69 +5,53 @@ import { Document, Page, pdfjs } from 'react-pdf';
|
|
| 5 |
|
| 6 |
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
|
| 7 |
import 'react-pdf/dist/esm/Page/TextLayer.css';
|
| 8 |
-
import { useDocumentResizeObserver } from './hooks';
|
| 9 |
|
|
|
|
|
|
|
| 10 |
import styles from './index.less';
|
| 11 |
|
| 12 |
-
// type PDFFile = string | File | null;
|
| 13 |
-
|
| 14 |
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
| 15 |
'pdfjs-dist/build/pdf.worker.min.js',
|
| 16 |
import.meta.url,
|
| 17 |
).toString();
|
| 18 |
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
// };
|
| 23 |
|
| 24 |
-
const DocumentPreview = () => {
|
| 25 |
const [numPages, setNumPages] = useState<number>();
|
| 26 |
const { documentId } = useGetKnowledgeSearchParams();
|
| 27 |
-
// const [file, setFile] = useState<PDFFile>(null);
|
| 28 |
const { containerWidth, setContainerRef } = useDocumentResizeObserver();
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
function onDocumentLoadSuccess({ numPages }: { numPages: number }): void {
|
| 31 |
setNumPages(numPages);
|
| 32 |
}
|
| 33 |
|
| 34 |
-
// const handleChange = (e: any) => {
|
| 35 |
-
// console.info(e.files);
|
| 36 |
-
// setFile(e.target.files[0] || null);
|
| 37 |
-
// };
|
| 38 |
-
|
| 39 |
const url = useMemo(() => {
|
| 40 |
return `${api_host}/document/get/${documentId}`;
|
| 41 |
}, [documentId]);
|
| 42 |
|
| 43 |
-
// const fetch_document_file = useCallback(async () => {
|
| 44 |
-
// const ret: Blob = await getDocumentFile(documentId);
|
| 45 |
-
// console.info(ret);
|
| 46 |
-
// const f = new File([ret], 'xx.pdf', { type: ret.type });
|
| 47 |
-
// setFile(f);
|
| 48 |
-
// }, [documentId]);
|
| 49 |
-
|
| 50 |
-
// useEffect(() => {
|
| 51 |
-
// // dispatch({ type: 'kFModel/fetch_document_file', payload: documentId });
|
| 52 |
-
// fetch_document_file();
|
| 53 |
-
// }, [fetch_document_file]);
|
| 54 |
-
|
| 55 |
return (
|
| 56 |
<div ref={setContainerRef} className={styles.documentContainer}>
|
| 57 |
<Document
|
| 58 |
file={url}
|
| 59 |
onLoadSuccess={onDocumentLoadSuccess}
|
| 60 |
-
|
| 61 |
>
|
| 62 |
{Array.from(new Array(numPages), (el, index) => (
|
| 63 |
<Page
|
| 64 |
key={`page_${index + 1}`}
|
| 65 |
pageNumber={index + 1}
|
| 66 |
width={containerWidth}
|
|
|
|
| 67 |
/>
|
| 68 |
))}
|
| 69 |
</Document>
|
| 70 |
-
{/* <input type="file" onChange={handleChange} /> */}
|
| 71 |
</div>
|
| 72 |
);
|
| 73 |
};
|
|
|
|
| 5 |
|
| 6 |
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
|
| 7 |
import 'react-pdf/dist/esm/Page/TextLayer.css';
|
| 8 |
+
import { useDocumentResizeObserver, useHighlightText } from './hooks';
|
| 9 |
|
| 10 |
+
import { Spin } from 'antd';
|
| 11 |
+
import { useGetSelectedChunk } from '../../hooks';
|
| 12 |
import styles from './index.less';
|
| 13 |
|
|
|
|
|
|
|
| 14 |
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
| 15 |
'pdfjs-dist/build/pdf.worker.min.js',
|
| 16 |
import.meta.url,
|
| 17 |
).toString();
|
| 18 |
|
| 19 |
+
interface IProps {
|
| 20 |
+
selectedChunkId: string;
|
| 21 |
+
}
|
|
|
|
| 22 |
|
| 23 |
+
const DocumentPreview = ({ selectedChunkId }: IProps) => {
|
| 24 |
const [numPages, setNumPages] = useState<number>();
|
| 25 |
const { documentId } = useGetKnowledgeSearchParams();
|
|
|
|
| 26 |
const { containerWidth, setContainerRef } = useDocumentResizeObserver();
|
| 27 |
+
const selectedChunk = useGetSelectedChunk(selectedChunkId);
|
| 28 |
+
console.info(selectedChunk?.content_with_weight);
|
| 29 |
+
const textRenderer = useHighlightText(selectedChunk?.content_with_weight);
|
| 30 |
|
| 31 |
function onDocumentLoadSuccess({ numPages }: { numPages: number }): void {
|
| 32 |
setNumPages(numPages);
|
| 33 |
}
|
| 34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
const url = useMemo(() => {
|
| 36 |
return `${api_host}/document/get/${documentId}`;
|
| 37 |
}, [documentId]);
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
return (
|
| 40 |
<div ref={setContainerRef} className={styles.documentContainer}>
|
| 41 |
<Document
|
| 42 |
file={url}
|
| 43 |
onLoadSuccess={onDocumentLoadSuccess}
|
| 44 |
+
loading={<Spin></Spin>}
|
| 45 |
>
|
| 46 |
{Array.from(new Array(numPages), (el, index) => (
|
| 47 |
<Page
|
| 48 |
key={`page_${index + 1}`}
|
| 49 |
pageNumber={index + 1}
|
| 50 |
width={containerWidth}
|
| 51 |
+
customTextRenderer={textRenderer}
|
| 52 |
/>
|
| 53 |
))}
|
| 54 |
</Document>
|
|
|
|
| 55 |
</div>
|
| 56 |
);
|
| 57 |
};
|
web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/preview.tsx
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Spin } from 'antd';
|
| 2 |
+
import { useRef, useState } from 'react';
|
| 3 |
+
import type { NewHighlight } from 'react-pdf-highlighter';
|
| 4 |
+
import {
|
| 5 |
+
AreaHighlight,
|
| 6 |
+
Highlight,
|
| 7 |
+
PdfHighlighter,
|
| 8 |
+
PdfLoader,
|
| 9 |
+
Popup,
|
| 10 |
+
Tip,
|
| 11 |
+
} from 'react-pdf-highlighter';
|
| 12 |
+
import { useGetSelectedChunk } from '../../hooks';
|
| 13 |
+
import { testHighlights } from './hightlights';
|
| 14 |
+
import { useGetDocumentUrl } from './hooks';
|
| 15 |
+
|
| 16 |
+
import styles from './index.less';
|
| 17 |
+
|
| 18 |
+
interface IProps {
|
| 19 |
+
selectedChunkId: string;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
const getNextId = () => String(Math.random()).slice(2);
|
| 23 |
+
|
| 24 |
+
const HighlightPopup = ({
|
| 25 |
+
comment,
|
| 26 |
+
}: {
|
| 27 |
+
comment: { text: string; emoji: string };
|
| 28 |
+
}) =>
|
| 29 |
+
comment.text ? (
|
| 30 |
+
<div className="Highlight__popup">
|
| 31 |
+
{comment.emoji} {comment.text}
|
| 32 |
+
</div>
|
| 33 |
+
) : null;
|
| 34 |
+
|
| 35 |
+
const Preview = ({ selectedChunkId }: IProps) => {
|
| 36 |
+
const url = useGetDocumentUrl();
|
| 37 |
+
const selectedChunk = useGetSelectedChunk(selectedChunkId);
|
| 38 |
+
|
| 39 |
+
const [state, setState] = useState<any>(testHighlights);
|
| 40 |
+
const ref = useRef((highlight: any) => {});
|
| 41 |
+
|
| 42 |
+
const parseIdFromHash = () =>
|
| 43 |
+
document.location.hash.slice('#highlight-'.length);
|
| 44 |
+
|
| 45 |
+
const resetHash = () => {
|
| 46 |
+
document.location.hash = '';
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
const getHighlightById = (id: string) => {
|
| 50 |
+
const highlights = state;
|
| 51 |
+
|
| 52 |
+
return highlights.find((highlight: any) => highlight.id === id);
|
| 53 |
+
};
|
| 54 |
+
|
| 55 |
+
// let scrollViewerTo = (highlight: any) => {};
|
| 56 |
+
|
| 57 |
+
let scrollToHighlightFromHash = () => {
|
| 58 |
+
const highlight = getHighlightById(parseIdFromHash());
|
| 59 |
+
|
| 60 |
+
if (highlight) {
|
| 61 |
+
ref.current(highlight);
|
| 62 |
+
}
|
| 63 |
+
};
|
| 64 |
+
|
| 65 |
+
const addHighlight = (highlight: NewHighlight) => {
|
| 66 |
+
const highlights = state;
|
| 67 |
+
|
| 68 |
+
console.log('Saving highlight', highlight);
|
| 69 |
+
|
| 70 |
+
setState([{ ...highlight, id: getNextId() }, ...highlights]);
|
| 71 |
+
};
|
| 72 |
+
|
| 73 |
+
const updateHighlight = (
|
| 74 |
+
highlightId: string,
|
| 75 |
+
position: Object,
|
| 76 |
+
content: Object,
|
| 77 |
+
) => {
|
| 78 |
+
console.log('Updating highlight', highlightId, position, content);
|
| 79 |
+
|
| 80 |
+
setState(
|
| 81 |
+
state.map((h: any) => {
|
| 82 |
+
const {
|
| 83 |
+
id,
|
| 84 |
+
position: originalPosition,
|
| 85 |
+
content: originalContent,
|
| 86 |
+
...rest
|
| 87 |
+
} = h;
|
| 88 |
+
return id === highlightId
|
| 89 |
+
? {
|
| 90 |
+
id,
|
| 91 |
+
position: { ...originalPosition, ...position },
|
| 92 |
+
content: { ...originalContent, ...content },
|
| 93 |
+
...rest,
|
| 94 |
+
}
|
| 95 |
+
: h;
|
| 96 |
+
}),
|
| 97 |
+
);
|
| 98 |
+
};
|
| 99 |
+
|
| 100 |
+
// useEffect(() => {
|
| 101 |
+
// ref.current(testHighlights[0]);
|
| 102 |
+
// }, [selectedChunk]);
|
| 103 |
+
|
| 104 |
+
return (
|
| 105 |
+
<div className={styles.documentContainer}>
|
| 106 |
+
<PdfLoader url={url} beforeLoad={<Spin />}>
|
| 107 |
+
{(pdfDocument) => (
|
| 108 |
+
<PdfHighlighter
|
| 109 |
+
pdfDocument={pdfDocument}
|
| 110 |
+
enableAreaSelection={(event) => event.altKey}
|
| 111 |
+
onScrollChange={resetHash}
|
| 112 |
+
// pdfScaleValue="page-width"
|
| 113 |
+
|
| 114 |
+
scrollRef={(scrollTo) => {
|
| 115 |
+
// scrollViewerTo = scrollTo;
|
| 116 |
+
ref.current = scrollTo;
|
| 117 |
+
|
| 118 |
+
scrollToHighlightFromHash();
|
| 119 |
+
}}
|
| 120 |
+
onSelectionFinished={(
|
| 121 |
+
position,
|
| 122 |
+
content,
|
| 123 |
+
hideTipAndSelection,
|
| 124 |
+
transformSelection,
|
| 125 |
+
) => (
|
| 126 |
+
<Tip
|
| 127 |
+
onOpen={transformSelection}
|
| 128 |
+
onConfirm={(comment) => {
|
| 129 |
+
addHighlight({ content, position, comment });
|
| 130 |
+
|
| 131 |
+
hideTipAndSelection();
|
| 132 |
+
}}
|
| 133 |
+
/>
|
| 134 |
+
)}
|
| 135 |
+
highlightTransform={(
|
| 136 |
+
highlight,
|
| 137 |
+
index,
|
| 138 |
+
setTip,
|
| 139 |
+
hideTip,
|
| 140 |
+
viewportToScaled,
|
| 141 |
+
screenshot,
|
| 142 |
+
isScrolledTo,
|
| 143 |
+
) => {
|
| 144 |
+
const isTextHighlight = !Boolean(
|
| 145 |
+
highlight.content && highlight.content.image,
|
| 146 |
+
);
|
| 147 |
+
|
| 148 |
+
const component = isTextHighlight ? (
|
| 149 |
+
<Highlight
|
| 150 |
+
isScrolledTo={isScrolledTo}
|
| 151 |
+
position={highlight.position}
|
| 152 |
+
comment={highlight.comment}
|
| 153 |
+
/>
|
| 154 |
+
) : (
|
| 155 |
+
<AreaHighlight
|
| 156 |
+
isScrolledTo={isScrolledTo}
|
| 157 |
+
highlight={highlight}
|
| 158 |
+
onChange={(boundingRect) => {
|
| 159 |
+
updateHighlight(
|
| 160 |
+
highlight.id,
|
| 161 |
+
{ boundingRect: viewportToScaled(boundingRect) },
|
| 162 |
+
{ image: screenshot(boundingRect) },
|
| 163 |
+
);
|
| 164 |
+
}}
|
| 165 |
+
/>
|
| 166 |
+
);
|
| 167 |
+
|
| 168 |
+
return (
|
| 169 |
+
<Popup
|
| 170 |
+
popupContent={<HighlightPopup {...highlight} />}
|
| 171 |
+
onMouseOver={(popupContent) =>
|
| 172 |
+
setTip(highlight, (highlight: any) => popupContent)
|
| 173 |
+
}
|
| 174 |
+
onMouseOut={hideTip}
|
| 175 |
+
key={index}
|
| 176 |
+
>
|
| 177 |
+
{component}
|
| 178 |
+
</Popup>
|
| 179 |
+
);
|
| 180 |
+
}}
|
| 181 |
+
highlights={state}
|
| 182 |
+
/>
|
| 183 |
+
)}
|
| 184 |
+
</PdfLoader>
|
| 185 |
+
</div>
|
| 186 |
+
);
|
| 187 |
+
};
|
| 188 |
+
|
| 189 |
+
export default Preview;
|
web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
-
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
|
|
|
|
| 2 |
import { useSelector } from 'umi';
|
| 3 |
|
| 4 |
export const useSelectDocumentInfo = () => {
|
|
@@ -7,3 +8,25 @@ export const useSelectDocumentInfo = () => {
|
|
| 7 |
);
|
| 8 |
return documentInfo;
|
| 9 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
|
| 2 |
+
import { useCallback, useState } from 'react';
|
| 3 |
import { useSelector } from 'umi';
|
| 4 |
|
| 5 |
export const useSelectDocumentInfo = () => {
|
|
|
|
| 8 |
);
|
| 9 |
return documentInfo;
|
| 10 |
};
|
| 11 |
+
|
| 12 |
+
export const useSelectChunkList = () => {
|
| 13 |
+
const chunkList: IChunk[] = useSelector(
|
| 14 |
+
(state: any) => state.chunkModel.data,
|
| 15 |
+
);
|
| 16 |
+
return chunkList;
|
| 17 |
+
};
|
| 18 |
+
|
| 19 |
+
export const useHandleChunkCardClick = () => {
|
| 20 |
+
const [selectedChunkId, setSelectedChunkId] = useState<string>('');
|
| 21 |
+
|
| 22 |
+
const handleChunkCardClick = useCallback((chunkId: string) => {
|
| 23 |
+
setSelectedChunkId(chunkId);
|
| 24 |
+
}, []);
|
| 25 |
+
|
| 26 |
+
return { handleChunkCardClick, selectedChunkId };
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
export const useGetSelectedChunk = (selectedChunkId: string) => {
|
| 30 |
+
const chunkList: IChunk[] = useSelectChunkList();
|
| 31 |
+
return chunkList.find((x) => x.chunk_id === selectedChunkId);
|
| 32 |
+
};
|
web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
CHANGED
|
@@ -8,8 +8,9 @@ import CreatingModal from './components/chunk-creating-modal';
|
|
| 8 |
import { useDeleteChunkByIds } from '@/hooks/knowledgeHook';
|
| 9 |
import ChunkCard from './components/chunk-card';
|
| 10 |
import ChunkToolBar from './components/chunk-toolbar';
|
| 11 |
-
import DocumentPreview from './components/document-preview';
|
| 12 |
-
import
|
|
|
|
| 13 |
import styles from './index.less';
|
| 14 |
import { ChunkModelState } from './model';
|
| 15 |
|
|
@@ -36,6 +37,7 @@ const Chunk = () => {
|
|
| 36 |
const [chunkId, setChunkId] = useState<string | undefined>();
|
| 37 |
const { removeChunk } = useDeleteChunkByIds();
|
| 38 |
const documentInfo = useSelectDocumentInfo();
|
|
|
|
| 39 |
|
| 40 |
const getChunkList = useCallback(() => {
|
| 41 |
const payload: PayloadType = {
|
|
@@ -180,6 +182,8 @@ const Chunk = () => {
|
|
| 180 |
)}
|
| 181 |
handleCheckboxClick={handleSingleCheckboxClick}
|
| 182 |
switchChunk={switchChunk}
|
|
|
|
|
|
|
| 183 |
></ChunkCard>
|
| 184 |
))}
|
| 185 |
</Space>
|
|
@@ -202,7 +206,9 @@ const Chunk = () => {
|
|
| 202 |
|
| 203 |
{documentInfo.type === 'pdf' && (
|
| 204 |
<section className={styles.documentPreview}>
|
| 205 |
-
<DocumentPreview
|
|
|
|
|
|
|
| 206 |
</section>
|
| 207 |
)}
|
| 208 |
</Flex>
|
|
|
|
| 8 |
import { useDeleteChunkByIds } from '@/hooks/knowledgeHook';
|
| 9 |
import ChunkCard from './components/chunk-card';
|
| 10 |
import ChunkToolBar from './components/chunk-toolbar';
|
| 11 |
+
// import DocumentPreview from './components/document-preview';
|
| 12 |
+
import DocumentPreview from './components/document-preview/preview';
|
| 13 |
+
import { useHandleChunkCardClick, useSelectDocumentInfo } from './hooks';
|
| 14 |
import styles from './index.less';
|
| 15 |
import { ChunkModelState } from './model';
|
| 16 |
|
|
|
|
| 37 |
const [chunkId, setChunkId] = useState<string | undefined>();
|
| 38 |
const { removeChunk } = useDeleteChunkByIds();
|
| 39 |
const documentInfo = useSelectDocumentInfo();
|
| 40 |
+
const { handleChunkCardClick, selectedChunkId } = useHandleChunkCardClick();
|
| 41 |
|
| 42 |
const getChunkList = useCallback(() => {
|
| 43 |
const payload: PayloadType = {
|
|
|
|
| 182 |
)}
|
| 183 |
handleCheckboxClick={handleSingleCheckboxClick}
|
| 184 |
switchChunk={switchChunk}
|
| 185 |
+
clickChunkCard={handleChunkCardClick}
|
| 186 |
+
selected={item.chunk_id === selectedChunkId}
|
| 187 |
></ChunkCard>
|
| 188 |
))}
|
| 189 |
</Space>
|
|
|
|
| 206 |
|
| 207 |
{documentInfo.type === 'pdf' && (
|
| 208 |
<section className={styles.documentPreview}>
|
| 209 |
+
<DocumentPreview
|
| 210 |
+
selectedChunkId={selectedChunkId}
|
| 211 |
+
></DocumentPreview>
|
| 212 |
</section>
|
| 213 |
)}
|
| 214 |
</Flex>
|
web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
import { BaseState } from '@/interfaces/common';
|
| 2 |
-
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
|
| 3 |
import kbService from '@/services/kbService';
|
| 4 |
import { message } from 'antd';
|
| 5 |
import { pick } from 'lodash';
|
|
@@ -7,7 +7,7 @@ import { pick } from 'lodash';
|
|
| 7 |
import { DvaModel } from 'umi';
|
| 8 |
|
| 9 |
export interface ChunkModelState extends BaseState {
|
| 10 |
-
data:
|
| 11 |
total: number;
|
| 12 |
isShowCreateModal: boolean;
|
| 13 |
chunk_id: string;
|
|
|
|
| 1 |
import { BaseState } from '@/interfaces/common';
|
| 2 |
+
import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
|
| 3 |
import kbService from '@/services/kbService';
|
| 4 |
import { message } from 'antd';
|
| 5 |
import { pick } from 'lodash';
|
|
|
|
| 7 |
import { DvaModel } from 'umi';
|
| 8 |
|
| 9 |
export interface ChunkModelState extends BaseState {
|
| 10 |
+
data: IChunk[];
|
| 11 |
total: number;
|
| 12 |
isShowCreateModal: boolean;
|
| 13 |
chunk_id: string;
|