From eb517f310622edc56a47798f5b2560d4ec04ad6f Mon Sep 17 00:00:00 2001 From: balibabu Date: Tue, 27 Feb 2024 19:05:50 +0800 Subject: [PATCH] feat: add file icon and add message popover content (#77) * feat: add message popover content * feat: add file icon --- web/src/assets/svg/file-icon/aep.svg | 10 ++ web/src/assets/svg/file-icon/ai.svg | 10 ++ web/src/assets/svg/file-icon/avi.svg | 10 ++ web/src/assets/svg/file-icon/css.svg | 10 ++ web/src/assets/svg/file-icon/csv.svg | 10 ++ web/src/assets/svg/file-icon/dmg.svg | 10 ++ web/src/assets/svg/file-icon/doc.svg | 10 ++ web/src/assets/svg/file-icon/docx.svg | 10 ++ web/src/assets/svg/file-icon/eps.svg | 10 ++ web/src/assets/svg/file-icon/exe.svg | 10 ++ web/src/assets/svg/file-icon/fig.svg | 10 ++ web/src/assets/svg/file-icon/gif.svg | 10 ++ web/src/assets/svg/file-icon/html.svg | 10 ++ web/src/assets/svg/file-icon/indd.svg | 10 ++ web/src/assets/svg/file-icon/java.svg | 10 ++ web/src/assets/svg/file-icon/jpeg.svg | 10 ++ web/src/assets/svg/file-icon/jpg.svg | 10 ++ web/src/assets/svg/file-icon/js.svg | 10 ++ web/src/assets/svg/file-icon/json.svg | 10 ++ web/src/assets/svg/file-icon/mkv.svg | 10 ++ web/src/assets/svg/file-icon/mp3.svg | 10 ++ web/src/assets/svg/file-icon/mp4.svg | 10 ++ web/src/assets/svg/file-icon/mpeg.svg | 10 ++ web/src/assets/svg/file-icon/pdf.svg | 10 ++ web/src/assets/svg/file-icon/png.svg | 10 ++ web/src/assets/svg/file-icon/ppt.svg | 10 ++ web/src/assets/svg/file-icon/pptx.svg | 10 ++ web/src/assets/svg/file-icon/psd.svg | 10 ++ web/src/assets/svg/file-icon/rss.svg | 10 ++ web/src/assets/svg/file-icon/sql.svg | 10 ++ web/src/assets/svg/file-icon/svg.svg | 10 ++ web/src/assets/svg/file-icon/tiff.svg | 10 ++ web/src/assets/svg/file-icon/txt.svg | 10 ++ web/src/assets/svg/file-icon/wav.svg | 10 ++ web/src/assets/svg/file-icon/webp.svg | 0 web/src/assets/svg/file-icon/xls.svg | 10 ++ web/src/assets/svg/file-icon/xlsx.svg | 10 ++ web/src/assets/svg/file-icon/xml.svg | 10 ++ web/src/components/new-document-link.tsx | 20 +++ web/src/components/svg-icon.tsx | 34 +++++ web/src/constants/common.ts | 40 ++++++ web/src/hooks/commonHooks.ts | 36 +++++ web/src/interfaces/database/chat.ts | 2 +- .../components/chunk-card/index.tsx | 6 - .../testing-result/select-files.tsx | 10 +- web/src/pages/add-knowledge/index.tsx | 10 +- web/src/pages/chat/chat-container/index.less | 8 ++ web/src/pages/chat/chat-container/index.tsx | 131 ++++++++++++++---- web/src/pages/chat/hooks.ts | 38 ++++- web/src/utils/domUtils.ts | 3 + web/src/utils/index.ts | 3 + web/src/utils/request.ts | 1 - 52 files changed, 667 insertions(+), 45 deletions(-) create mode 100644 web/src/assets/svg/file-icon/aep.svg create mode 100644 web/src/assets/svg/file-icon/ai.svg create mode 100644 web/src/assets/svg/file-icon/avi.svg create mode 100644 web/src/assets/svg/file-icon/css.svg create mode 100644 web/src/assets/svg/file-icon/csv.svg create mode 100644 web/src/assets/svg/file-icon/dmg.svg create mode 100644 web/src/assets/svg/file-icon/doc.svg create mode 100644 web/src/assets/svg/file-icon/docx.svg create mode 100644 web/src/assets/svg/file-icon/eps.svg create mode 100644 web/src/assets/svg/file-icon/exe.svg create mode 100644 web/src/assets/svg/file-icon/fig.svg create mode 100644 web/src/assets/svg/file-icon/gif.svg create mode 100644 web/src/assets/svg/file-icon/html.svg create mode 100644 web/src/assets/svg/file-icon/indd.svg create mode 100644 web/src/assets/svg/file-icon/java.svg create mode 100644 web/src/assets/svg/file-icon/jpeg.svg create mode 100644 web/src/assets/svg/file-icon/jpg.svg create mode 100644 web/src/assets/svg/file-icon/js.svg create mode 100644 web/src/assets/svg/file-icon/json.svg create mode 100644 web/src/assets/svg/file-icon/mkv.svg create mode 100644 web/src/assets/svg/file-icon/mp3.svg create mode 100644 web/src/assets/svg/file-icon/mp4.svg create mode 100644 web/src/assets/svg/file-icon/mpeg.svg create mode 100644 web/src/assets/svg/file-icon/pdf.svg create mode 100644 web/src/assets/svg/file-icon/png.svg create mode 100644 web/src/assets/svg/file-icon/ppt.svg create mode 100644 web/src/assets/svg/file-icon/pptx.svg create mode 100644 web/src/assets/svg/file-icon/psd.svg create mode 100644 web/src/assets/svg/file-icon/rss.svg create mode 100644 web/src/assets/svg/file-icon/sql.svg create mode 100644 web/src/assets/svg/file-icon/svg.svg create mode 100644 web/src/assets/svg/file-icon/tiff.svg create mode 100644 web/src/assets/svg/file-icon/txt.svg create mode 100644 web/src/assets/svg/file-icon/wav.svg create mode 100644 web/src/assets/svg/file-icon/webp.svg create mode 100644 web/src/assets/svg/file-icon/xls.svg create mode 100644 web/src/assets/svg/file-icon/xlsx.svg create mode 100644 web/src/assets/svg/file-icon/xml.svg create mode 100644 web/src/components/new-document-link.tsx create mode 100644 web/src/components/svg-icon.tsx create mode 100644 web/src/utils/domUtils.ts diff --git a/web/src/assets/svg/file-icon/aep.svg b/web/src/assets/svg/file-icon/aep.svg new file mode 100644 index 000000000..fcf26db8a --- /dev/null +++ b/web/src/assets/svg/file-icon/aep.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/ai.svg b/web/src/assets/svg/file-icon/ai.svg new file mode 100644 index 000000000..4e2bf68aa --- /dev/null +++ b/web/src/assets/svg/file-icon/ai.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/avi.svg b/web/src/assets/svg/file-icon/avi.svg new file mode 100644 index 000000000..7225956cf --- /dev/null +++ b/web/src/assets/svg/file-icon/avi.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/css.svg b/web/src/assets/svg/file-icon/css.svg new file mode 100644 index 000000000..506a853c4 --- /dev/null +++ b/web/src/assets/svg/file-icon/css.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/csv.svg b/web/src/assets/svg/file-icon/csv.svg new file mode 100644 index 000000000..ad691e0d4 --- /dev/null +++ b/web/src/assets/svg/file-icon/csv.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/dmg.svg b/web/src/assets/svg/file-icon/dmg.svg new file mode 100644 index 000000000..4755f46fa --- /dev/null +++ b/web/src/assets/svg/file-icon/dmg.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/doc.svg b/web/src/assets/svg/file-icon/doc.svg new file mode 100644 index 000000000..2e68655ca --- /dev/null +++ b/web/src/assets/svg/file-icon/doc.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/docx.svg b/web/src/assets/svg/file-icon/docx.svg new file mode 100644 index 000000000..dd4325489 --- /dev/null +++ b/web/src/assets/svg/file-icon/docx.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/eps.svg b/web/src/assets/svg/file-icon/eps.svg new file mode 100644 index 000000000..4f2a66b1a --- /dev/null +++ b/web/src/assets/svg/file-icon/eps.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/exe.svg b/web/src/assets/svg/file-icon/exe.svg new file mode 100644 index 000000000..fbaea17f1 --- /dev/null +++ b/web/src/assets/svg/file-icon/exe.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/fig.svg b/web/src/assets/svg/file-icon/fig.svg new file mode 100644 index 000000000..7a500cdae --- /dev/null +++ b/web/src/assets/svg/file-icon/fig.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/gif.svg b/web/src/assets/svg/file-icon/gif.svg new file mode 100644 index 000000000..ff4e02455 --- /dev/null +++ b/web/src/assets/svg/file-icon/gif.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/html.svg b/web/src/assets/svg/file-icon/html.svg new file mode 100644 index 000000000..8d157fe68 --- /dev/null +++ b/web/src/assets/svg/file-icon/html.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/indd.svg b/web/src/assets/svg/file-icon/indd.svg new file mode 100644 index 000000000..b86688b66 --- /dev/null +++ b/web/src/assets/svg/file-icon/indd.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/java.svg b/web/src/assets/svg/file-icon/java.svg new file mode 100644 index 000000000..bea4ca9cc --- /dev/null +++ b/web/src/assets/svg/file-icon/java.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/jpeg.svg b/web/src/assets/svg/file-icon/jpeg.svg new file mode 100644 index 000000000..490a29226 --- /dev/null +++ b/web/src/assets/svg/file-icon/jpeg.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/jpg.svg b/web/src/assets/svg/file-icon/jpg.svg new file mode 100644 index 000000000..035ef810c --- /dev/null +++ b/web/src/assets/svg/file-icon/jpg.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/js.svg b/web/src/assets/svg/file-icon/js.svg new file mode 100644 index 000000000..3791ff50a --- /dev/null +++ b/web/src/assets/svg/file-icon/js.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/json.svg b/web/src/assets/svg/file-icon/json.svg new file mode 100644 index 000000000..5ead80c1e --- /dev/null +++ b/web/src/assets/svg/file-icon/json.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/mkv.svg b/web/src/assets/svg/file-icon/mkv.svg new file mode 100644 index 000000000..2b00a8ece --- /dev/null +++ b/web/src/assets/svg/file-icon/mkv.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/mp3.svg b/web/src/assets/svg/file-icon/mp3.svg new file mode 100644 index 000000000..b311e4d53 --- /dev/null +++ b/web/src/assets/svg/file-icon/mp3.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/mp4.svg b/web/src/assets/svg/file-icon/mp4.svg new file mode 100644 index 000000000..4f5f79dc3 --- /dev/null +++ b/web/src/assets/svg/file-icon/mp4.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/mpeg.svg b/web/src/assets/svg/file-icon/mpeg.svg new file mode 100644 index 000000000..23c01e866 --- /dev/null +++ b/web/src/assets/svg/file-icon/mpeg.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/pdf.svg b/web/src/assets/svg/file-icon/pdf.svg new file mode 100644 index 000000000..6e1a5f060 --- /dev/null +++ b/web/src/assets/svg/file-icon/pdf.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/png.svg b/web/src/assets/svg/file-icon/png.svg new file mode 100644 index 000000000..d581915bd --- /dev/null +++ b/web/src/assets/svg/file-icon/png.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/ppt.svg b/web/src/assets/svg/file-icon/ppt.svg new file mode 100644 index 000000000..365c32de3 --- /dev/null +++ b/web/src/assets/svg/file-icon/ppt.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/pptx.svg b/web/src/assets/svg/file-icon/pptx.svg new file mode 100644 index 000000000..09894ce2a --- /dev/null +++ b/web/src/assets/svg/file-icon/pptx.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/psd.svg b/web/src/assets/svg/file-icon/psd.svg new file mode 100644 index 000000000..0aa30c0cf --- /dev/null +++ b/web/src/assets/svg/file-icon/psd.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/rss.svg b/web/src/assets/svg/file-icon/rss.svg new file mode 100644 index 000000000..b4114c7b2 --- /dev/null +++ b/web/src/assets/svg/file-icon/rss.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/sql.svg b/web/src/assets/svg/file-icon/sql.svg new file mode 100644 index 000000000..0368a502c --- /dev/null +++ b/web/src/assets/svg/file-icon/sql.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/svg.svg b/web/src/assets/svg/file-icon/svg.svg new file mode 100644 index 000000000..0957124cf --- /dev/null +++ b/web/src/assets/svg/file-icon/svg.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/tiff.svg b/web/src/assets/svg/file-icon/tiff.svg new file mode 100644 index 000000000..de818515a --- /dev/null +++ b/web/src/assets/svg/file-icon/tiff.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/txt.svg b/web/src/assets/svg/file-icon/txt.svg new file mode 100644 index 000000000..0a4fe6fae --- /dev/null +++ b/web/src/assets/svg/file-icon/txt.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/wav.svg b/web/src/assets/svg/file-icon/wav.svg new file mode 100644 index 000000000..d2b018eef --- /dev/null +++ b/web/src/assets/svg/file-icon/wav.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/webp.svg b/web/src/assets/svg/file-icon/webp.svg new file mode 100644 index 000000000..e69de29bb diff --git a/web/src/assets/svg/file-icon/xls.svg b/web/src/assets/svg/file-icon/xls.svg new file mode 100644 index 000000000..7fe4a5c70 --- /dev/null +++ b/web/src/assets/svg/file-icon/xls.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/xlsx.svg b/web/src/assets/svg/file-icon/xlsx.svg new file mode 100644 index 000000000..544a1384a --- /dev/null +++ b/web/src/assets/svg/file-icon/xlsx.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/file-icon/xml.svg b/web/src/assets/svg/file-icon/xml.svg new file mode 100644 index 000000000..4e61546c2 --- /dev/null +++ b/web/src/assets/svg/file-icon/xml.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/web/src/components/new-document-link.tsx b/web/src/components/new-document-link.tsx new file mode 100644 index 000000000..84c0c9378 --- /dev/null +++ b/web/src/components/new-document-link.tsx @@ -0,0 +1,20 @@ +import { api_host } from '@/utils/api'; +import React from 'react'; + +interface IProps extends React.PropsWithChildren { + documentId: string; +} + +const NewDocumentLink = ({ children, documentId }: IProps) => { + return ( + + {children} + + ); +}; + +export default NewDocumentLink; diff --git a/web/src/components/svg-icon.tsx b/web/src/components/svg-icon.tsx new file mode 100644 index 000000000..d7c16f478 --- /dev/null +++ b/web/src/components/svg-icon.tsx @@ -0,0 +1,34 @@ +import { + UseDynamicSVGImportOptions, + useDynamicSVGImport, +} from '@/hooks/commonHooks'; + +interface IconProps extends React.SVGProps { + name: string; + onCompleted?: UseDynamicSVGImportOptions['onCompleted']; + onError?: UseDynamicSVGImportOptions['onError']; +} + +const SvgIcon: React.FC = ({ + name, + onCompleted, + onError, + ...rest +}): React.ReactNode | null => { + const { error, loading, SvgIcon } = useDynamicSVGImport(name, { + onCompleted, + onError, + }); + if (error) { + return error.message; + } + if (loading) { + return 'Loading...'; + } + if (SvgIcon) { + return ; + } + return null; +}; + +export default SvgIcon; diff --git a/web/src/constants/common.ts b/web/src/constants/common.ts index e69de29bb..d315cf175 100644 --- a/web/src/constants/common.ts +++ b/web/src/constants/common.ts @@ -0,0 +1,40 @@ +export const fileIconMap = { + aep: 'aep.svg', + ai: 'ai.svg', + avi: 'avi.svg', + css: 'css.svg', + csv: 'csv.svg', + dmg: 'dmg.svg', + doc: 'doc.svg', + docx: 'docx.svg', + eps: 'eps.svg', + exe: 'exe.svg', + fig: 'fig.svg', + gif: 'gif.svg', + html: 'html.svg', + indd: 'indd.svg', + java: 'java.svg', + jpeg: 'jpeg.svg', + jpg: 'jpg.svg', + js: 'js.svg', + json: 'json.svg', + mkv: 'mkv.svg', + mp3: 'mp3.svg', + mp4: 'mp4.svg', + mpeg: 'mpeg.svg', + pdf: 'pdf.svg', + png: 'png.svg', + ppt: 'ppt.svg', + pptx: 'pptx.svg', + psd: 'psd.svg', + rss: 'rss.svg', + sql: 'sql.svg', + svg: 'svg.svg', + tiff: 'tiff.svg', + txt: 'txt.svg', + wav: 'wav.svg', + webp: 'webp.svg', + xls: 'xls.svg', + xlsx: 'xlsx.svg', + xml: 'xml.svg', +}; diff --git a/web/src/hooks/commonHooks.ts b/web/src/hooks/commonHooks.ts index e4361cd29..6cbf10e89 100644 --- a/web/src/hooks/commonHooks.ts +++ b/web/src/hooks/commonHooks.ts @@ -32,3 +32,39 @@ export const useDeepCompareEffect = ( }; }, []); }; + +export interface UseDynamicSVGImportOptions { + onCompleted?: ( + name: string, + SvgIcon: React.FC> | undefined, + ) => void; + onError?: (err: Error) => void; +} + +export function useDynamicSVGImport( + name: string, + options: UseDynamicSVGImportOptions = {}, +) { + const ImportedIconRef = useRef>>(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(); + + const { onCompleted, onError } = options; + useEffect(() => { + setLoading(true); + const importIcon = async (): Promise => { + try { + ImportedIconRef.current = (await import(name)).ReactComponent; + onCompleted?.(name, ImportedIconRef.current); + } catch (err: any) { + onError?.(err); + setError(err); + } finally { + setLoading(false); + } + }; + importIcon(); + }, [name, onCompleted, onError]); + + return { error, loading, SvgIcon: ImportedIconRef.current }; +} diff --git a/web/src/interfaces/database/chat.ts b/web/src/interfaces/database/chat.ts index eb4ec51f3..af6b12c90 100644 --- a/web/src/interfaces/database/chat.ts +++ b/web/src/interfaces/database/chat.ts @@ -71,7 +71,7 @@ export interface IReference { total: number; } -interface Docagg { +export interface Docagg { count: number; doc_id: string; doc_name: string; diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx index 89af5283b..e509ec0cb 100644 --- a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx @@ -1,6 +1,5 @@ import Image from '@/components/image'; import { IChunk } from '@/interfaces/database/knowledge'; -import { api_host } from '@/utils/api'; import { Card, Checkbox, CheckboxProps, Flex, Popover, Switch } from 'antd'; import { useState } from 'react'; import styles from './index.less'; @@ -48,11 +47,6 @@ const ChunkCard = ({ } > - )} diff --git a/web/src/pages/add-knowledge/components/knowledge-testing/testing-result/select-files.tsx b/web/src/pages/add-knowledge/components/knowledge-testing/testing-result/select-files.tsx index ab5d06c9c..cb80d0175 100644 --- a/web/src/pages/add-knowledge/components/knowledge-testing/testing-result/select-files.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-testing/testing-result/select-files.tsx @@ -1,6 +1,6 @@ import { ReactComponent as NavigationPointerIcon } from '@/assets/svg/navigation-pointer.svg'; +import NewDocumentLink from '@/components/new-document-link'; import { ITestingDocument } from '@/interfaces/database/knowledge'; -import { api_host } from '@/utils/api'; import { Table, TableProps } from 'antd'; import { useDispatch, useSelector } from 'umi'; @@ -34,13 +34,9 @@ const SelectFiles = ({ handleTesting }: IProps) => { key: 'view', width: 50, render: (_, { doc_id }) => ( - + - + ), }, ]; diff --git a/web/src/pages/add-knowledge/index.tsx b/web/src/pages/add-knowledge/index.tsx index 370d1150f..ec4ba5df6 100644 --- a/web/src/pages/add-knowledge/index.tsx +++ b/web/src/pages/add-knowledge/index.tsx @@ -2,7 +2,7 @@ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook'; import { useSecondPathName, useThirdPathName } from '@/hooks/routeHook'; import { Breadcrumb } from 'antd'; import { ItemType } from 'antd/es/breadcrumb/Breadcrumb'; -import { useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { Link, Outlet, useDispatch, useLocation, useNavigate } from 'umi'; import Siderbar from './components/knowledge-sidebar'; import { @@ -25,9 +25,9 @@ const KnowledgeAdding = () => { const datasetActiveKey: KnowledgeDatasetRouteKey = useThirdPathName() as KnowledgeDatasetRouteKey; - const gotoList = () => { + const gotoList = useCallback(() => { navigate('/knowledge'); - }; + }, [navigate]); const breadcrumbItems: ItemType[] = useMemo(() => { const items: ItemType[] = [ @@ -54,7 +54,7 @@ const KnowledgeAdding = () => { } return items; - }, [activeKey, datasetActiveKey]); + }, [activeKey, datasetActiveKey, gotoList, knowledgeBaseId]); useEffect(() => { const search: string = location.search.slice(1); @@ -71,7 +71,7 @@ const KnowledgeAdding = () => { ...map, }, }); - }, [location]); + }, [location, dispatch]); return ( <> diff --git a/web/src/pages/chat/chat-container/index.less b/web/src/pages/chat/chat-container/index.less index c0ce04b55..1eba20a51 100644 --- a/web/src/pages/chat/chat-container/index.less +++ b/web/src/pages/chat/chat-container/index.less @@ -39,3 +39,11 @@ .messageItemRight { text-align: right; } + +.referencePopoverWrapper { + width: 50vw; +} + +.referenceChunkImage { + width: 10vw; +} diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx index 31d939ff5..4c0704f7b 100644 --- a/web/src/pages/chat/chat-container/index.tsx +++ b/web/src/pages/chat/chat-container/index.tsx @@ -3,18 +3,38 @@ import { MessageType } from '@/constants/chat'; import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; import { useSelectUserInfo } from '@/hooks/userSettingHook'; import { IReference, Message } from '@/interfaces/database/chat'; -import { Avatar, Button, Flex, Input, Popover } from 'antd'; +import { + Avatar, + Button, + Flex, + Input, + List, + Popover, + Space, + Typography, +} from 'antd'; import classNames from 'classnames'; import { ChangeEventHandler, useCallback, useMemo, useState } from 'react'; import reactStringReplace from 'react-string-replace'; -import { useFetchConversation, useSendMessage } from '../hooks'; +import { + useFetchConversation, + useGetFileIcon, + useScrollToBottom, + useSendMessage, +} from '../hooks'; import { IClientConversation } from '../interface'; +import Image from '@/components/image'; +import NewDocumentLink from '@/components/new-document-link'; import { InfoCircleOutlined } from '@ant-design/icons'; import Markdown from 'react-markdown'; import { visitParents } from 'unist-util-visit-parents'; import styles from './index.less'; +const reg = /(#{2}\d+\${2})/g; + +const getChunkIndex = (match: string) => Number(match.slice(2, 3)); + const rehypeWrapReference = () => { return function wrapTextTransform(tree: any) { visitParents(tree, 'text', (node, ancestors) => { @@ -28,32 +48,69 @@ const rehypeWrapReference = () => { }; }; -const MessageItem = ({ item }: { item: Message; references: IReference[] }) => { +const MessageItem = ({ + item, + reference, +}: { + item: Message; + reference: IReference; +}) => { const userInfo = useSelectUserInfo(); - const popoverContent = useMemo( - () => ( -
-

Content

-

Content

-
- ), - [], + const isAssistant = item.role === MessageType.Assistant; + + const getFileIcon = useGetFileIcon(); + + const getPopoverContent = useCallback( + (chunkIndex: number) => { + const chunks = reference?.chunks ?? []; + const chunkItem = chunks[chunkIndex]; + const document = reference?.doc_aggs.find( + (x) => x?.doc_id === chunkItem?.doc_id, + ); + const documentId = document?.doc_id; + return ( + + + +
{chunkItem?.content_with_weight}
+ {documentId && ( + + {document?.doc_name} + + )} +
+
+ ); + }, + [reference], ); const renderReference = useCallback( (text: string) => { - return reactStringReplace(text, /#{2}\d{1,}\${2}/g, (match, i) => { + return reactStringReplace(text, reg, (match, i) => { + const chunkIndex = getChunkIndex(match); return ( - + ); }); }, - [popoverContent], + [getPopoverContent], ); + const referenceDocumentList = useMemo(() => { + return reference?.doc_aggs ?? []; + }, [reference?.doc_aggs]); + return (
{ )} - - {item.role === MessageType.Assistant ? 'Resume Assistant' : 'You'} - + {isAssistant ? 'Resume Assistant' : 'You'}
{ {item.content}
+ {isAssistant && referenceDocumentList.length > 0 && ( + ( + + + {/* */} + + + {item.doc_name} + + + )} + /> + )}
@@ -117,6 +188,8 @@ const ChatContainer = () => { 'completeConversation', 'getConversation', ]); + const ref = useScrollToBottom(); + useGetFileIcon(); const handlePressEnter = () => { setValue(''); @@ -131,14 +204,24 @@ const ChatContainer = () => {
- {conversation?.message?.map((message) => ( - - ))} + {conversation?.message?.map((message) => { + const assistantMessages = conversation?.message + ?.filter((x) => x.role === MessageType.Assistant) + .slice(1); + const referenceIndex = assistantMessages.findIndex( + (x) => x.id === message.id, + ); + const reference = conversation.reference[referenceIndex]; + return ( + + ); + })}
+
{ return { sendMessage: handleSendMessage }; }; +export const useScrollToBottom = () => { + const ref = useRef(null); + let chatModel: ChatModelState = useSelector((state: any) => state.chatModel); + const { currentConversation } = chatModel; + + const scrollToBottom = useCallback(() => { + if (currentConversation.id) { + ref.current?.scrollIntoView({ behavior: 'instant' }); + } + }, [currentConversation]); + + useEffect(() => { + scrollToBottom(); + }, [scrollToBottom]); + + return ref; +}; + +export const useGetFileIcon = () => { + // const req = require.context('@/assets/svg/file-icon'); + // const ret = req.keys().map(req); + // console.info(ret); + // useEffect(() => {}, []); + + const getFileIcon = (filename: string) => { + const ext: string = getFileExtension(filename); + const iconPath = fileIconMap[ext as keyof typeof fileIconMap]; + // const x = require(`@/assets/svg/file-icon/${iconPath}`); + return `@/assets/svg/file-icon/${iconPath}`; + }; + + return getFileIcon; +}; + //#endregion diff --git a/web/src/utils/domUtils.ts b/web/src/utils/domUtils.ts new file mode 100644 index 000000000..8710ec707 --- /dev/null +++ b/web/src/utils/domUtils.ts @@ -0,0 +1,3 @@ +export const scrollToBottom = (element: HTMLElement) => { + element.scrollTo(0, element.scrollHeight); +}; diff --git a/web/src/utils/index.ts b/web/src/utils/index.ts index f27890471..d0cdcef72 100644 --- a/web/src/utils/index.ts +++ b/web/src/utils/index.ts @@ -25,3 +25,6 @@ export default { getWidth, rsaPsw, }; + +export const getFileExtension = (filename: string) => + filename.slice(filename.lastIndexOf('.') + 1).toLowerCase(); diff --git a/web/src/utils/request.ts b/web/src/utils/request.ts index 2005a8218..b04bd54df 100644 --- a/web/src/utils/request.ts +++ b/web/src/utils/request.ts @@ -107,7 +107,6 @@ request.interceptors.request.use((url: string, options: any) => { * */ request.interceptors.response.use(async (response: any, request) => { - console.log(response, request); const data: ResponseType = await response.clone().json(); // response 拦截