diff --git a/docker/nginx/ragflow.conf b/docker/nginx/ragflow.conf index 545a74e3..f3769d6a 100644 --- a/docker/nginx/ragflow.conf +++ b/docker/nginx/ragflow.conf @@ -15,9 +15,6 @@ server { include proxy.conf; } - location /HPImageArchive { - proxy_pass https://cn.bing.com; - } location / { index index.html; diff --git a/web/src/pages/search/hooks.ts b/web/src/pages/search/hooks.ts index 57441fe3..0b4d5957 100644 --- a/web/src/pages/search/hooks.ts +++ b/web/src/pages/search/hooks.ts @@ -1,4 +1,5 @@ import { useFetchMindMap, useFetchRelatedQuestions } from '@/hooks/chat-hooks'; +import { useSetModalState } from '@/hooks/common-hooks'; import { useTestChunkRetrieval } from '@/hooks/knowledge-hooks'; import { useGetPaginationWithRouter, @@ -7,7 +8,13 @@ import { import { IAnswer } from '@/interfaces/database/chat'; import api from '@/utils/api'; import { get, isEmpty, trim } from 'lodash'; -import { ChangeEventHandler, useCallback, useEffect, useState } from 'react'; +import { + ChangeEventHandler, + useCallback, + useEffect, + useRef, + useState, +} from 'react'; export const useSendQuestion = (kbIds: string[]) => { const { send, answer, done } = useSendMessageWithSse(api.ask); @@ -16,11 +23,6 @@ export const useSendQuestion = (kbIds: string[]) => { const [currentAnswer, setCurrentAnswer] = useState({} as IAnswer); const { fetchRelatedQuestions, data: relatedQuestions } = useFetchRelatedQuestions(); - const { - fetchMindMap, - data: mindMap, - loading: mindMapLoading, - } = useFetchMindMap(); const [searchStr, setSearchStr] = useState(''); const [isFirstRender, setIsFirstRender] = useState(true); const [selectedDocumentIds, setSelectedDocumentIds] = useState([]); @@ -43,10 +45,7 @@ export const useSendQuestion = (kbIds: string[]) => { page: 1, size: pagination.pageSize, }); - fetchMindMap({ - question: q, - kb_ids: kbIds, - }); + fetchRelatedQuestions(q); }, [ @@ -54,7 +53,6 @@ export const useSendQuestion = (kbIds: string[]) => { testChunk, kbIds, fetchRelatedQuestions, - fetchMindMap, setPagination, pagination.pageSize, ], @@ -117,11 +115,10 @@ export const useSendQuestion = (kbIds: string[]) => { sendingLoading, answer: currentAnswer, relatedQuestions: relatedQuestions?.slice(0, 5) ?? [], - mindMap, - mindMapLoading, searchStr, isFirstRender, selectedDocumentIds, + isSearchStrEmpty: isEmpty(trim(searchStr)), }; }; @@ -191,3 +188,51 @@ export const useTestRetrieval = ( setSelectedDocumentIds, }; }; + +export const useShowMindMapDrawer = (kbIds: string[], question: string) => { + const { visible, showModal, hideModal } = useSetModalState(); + + const { + fetchMindMap, + data: mindMap, + loading: mindMapLoading, + } = useFetchMindMap(); + + const handleShowModal = useCallback(() => { + fetchMindMap({ question: trim(question), kb_ids: kbIds }); + showModal(); + }, [fetchMindMap, showModal, question, kbIds]); + + return { + mindMap, + mindMapVisible: visible, + mindMapLoading, + showMindMapModal: handleShowModal, + hideMindMapModal: hideModal, + }; +}; + +export const usePendingMindMap = () => { + const [count, setCount] = useState(0); + const ref = useRef(); + + const setCountInterval = useCallback(() => { + ref.current = setInterval(() => { + setCount((pre) => { + if (pre > 40) { + clearInterval(ref?.current); + } + return pre + 1; + }); + }, 1000); + }, []); + + useEffect(() => { + setCountInterval(); + return () => { + clearInterval(ref?.current); + }; + }, [setCountInterval]); + + return Number(((count / 43) * 100).toFixed(0)); +}; diff --git a/web/src/pages/search/index.less b/web/src/pages/search/index.less index f953d7c6..0f67cc83 100644 --- a/web/src/pages/search/index.less +++ b/web/src/pages/search/index.less @@ -16,17 +16,19 @@ cursor: pointer; } - .mainLayout { - background: transparent; - } + // .mainLayout { + // background: transparent; + // } } -.transparentSearchSide { - background-color: rgb(251 251 251 / 88%) !important; -} +// .transparentSearchSide { +// background-color: rgb(251 251 251 / 88%) !important; +// } .searchSide { position: relative; + max-width: 400px !important; + min-width: auto !important; :global(.ant-layout-sider-children) { height: auto; @@ -45,19 +47,19 @@ .list { padding-top: 10px; width: 100%; - // height: 100%; height: calc(100vh - 76px); overflow: auto; - background-color: transparent; - &::-webkit-scrollbar-track { - background: transparent; - } + // background-color: transparent; + // &::-webkit-scrollbar-track { + // background: transparent; + // } } .checkbox { width: 100%; } .knowledgeName { width: 116px; + max-width: 270px; } .embeddingId { width: 170px; @@ -70,27 +72,17 @@ .content { height: 100%; + overflow: auto; + width: 100%; + padding: 20px 16% 10px; .hide { display: none; } - .mainMixin() { - overflow: auto; - padding: 20px 10px 10px; - } - - .largeMain { - width: 100%; - .mainMixin(); - } .main { - width: 60%; - .mainMixin(); - } - - .graph { - width: 40%; - padding: 20px 10px 10px; + margin: 0 auto; + width: 100%; + max-width: 1200px; } .highlightContent { @@ -103,6 +95,9 @@ .documentReference { cursor: pointer; } + .pagination { + padding-bottom: 16px; + } } .answerWrapper { margin-top: 16px; @@ -122,9 +117,9 @@ border-start-start-radius: 30px !important; border-end-start-radius: 30px !important; } - :global(.ant-input-group-addon) { - background-color: transparent; - } + // :global(.ant-input-group-addon) { + // background-color: transparent; + // } input { height: 40px; } @@ -138,7 +133,7 @@ .globalInput { width: 600px; position: sticky; - top: 0; + top: 30%; z-index: 1; .input(); } @@ -187,3 +182,12 @@ max-height: 40vh; overflow: auto; } + +.mindMapFloatButton { + top: 20%; + width: 60px; + height: 60px; + :global(.ant-float-btn-content, .ant-float-btn-icon) { + width: auto !important; + } +} diff --git a/web/src/pages/search/index.tsx b/web/src/pages/search/index.tsx index f40b417a..4100579c 100644 --- a/web/src/pages/search/index.tsx +++ b/web/src/pages/search/index.tsx @@ -1,10 +1,10 @@ import FileIcon from '@/components/file-icon'; import HightLightMarkdown from '@/components/highlight-markdown'; import { ImageWithPopover } from '@/components/image'; -import IndentedTree from '@/components/indented-tree/indented-tree'; import PdfDrawer from '@/components/pdf-drawer'; import { useClickDrawer } from '@/components/pdf-drawer/hooks'; import RetrievalDocuments from '@/components/retrieval-documents'; +import SvgIcon from '@/components/svg-icon'; import { useNextFetchKnowledgeList, useSelectTestingResult, @@ -15,6 +15,7 @@ import { Card, Divider, Flex, + FloatButton, Input, Layout, List, @@ -25,14 +26,16 @@ import { Space, Spin, Tag, + Tooltip, } from 'antd'; import DOMPurify from 'dompurify'; import { isEmpty } from 'lodash'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import MarkdownContent from '../chat/markdown-content'; -import { useFetchBackgroundImage, useSendQuestion } from './hooks'; +import { useSendQuestion, useShowMindMapDrawer } from './hooks'; import styles from './index.less'; +import MindMapDrawer from './mindmap-drawer'; import SearchSidebar from './sidebar'; const { Content } = Layout; @@ -56,29 +59,28 @@ const SearchPage = () => { answer, sendingLoading, relatedQuestions, - mindMap, searchStr, loading, isFirstRender, selectedDocumentIds, + isSearchStrEmpty, } = useSendQuestion(checkedWithoutEmbeddingIdList); const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = useClickDrawer(); - const imgUrl = useFetchBackgroundImage(); const { pagination } = useGetPaginationWithRouter(); + const { + mindMapVisible, + hideMindMapModal, + showMindMapModal, + mindMapLoading, + mindMap, + } = useShowMindMapDrawer(checkedWithoutEmbeddingIdList, searchStr); const onChange: PaginationProps['onChange'] = (pageNumber, pageSize) => { pagination.onChange?.(pageNumber, pageSize); handleTestChunk(selectedDocumentIds, pageNumber, pageSize); }; - const isMindMapEmpty = useMemo(() => { - return ( - (Array.isArray(mindMap?.children) && mindMap.children.length === 0) || - !Array.isArray(mindMap?.children) - ); - }, [mindMap]); - const InputSearch = ( { return ( <> - + { {isFirstRender ? ( - + {InputSearch} ) : ( -
+
{InputSearch} { {...pagination} total={total} onChange={onChange} + className={styles.pagination} />
-
- -
)} - + {!isFirstRender && + !isSearchStrEmpty && + !isEmpty(checkedWithoutEmbeddingIdList) && ( + + + } + /> + + )} + {visible && ( + + )} + {mindMapVisible && ( + + )} ); }; diff --git a/web/src/pages/search/mindmap-drawer.tsx b/web/src/pages/search/mindmap-drawer.tsx new file mode 100644 index 00000000..43ac8eb1 --- /dev/null +++ b/web/src/pages/search/mindmap-drawer.tsx @@ -0,0 +1,36 @@ +import IndentedTree from '@/components/indented-tree/indented-tree'; +import { IModalProps } from '@/interfaces/common'; +import { Drawer, Flex, Progress } from 'antd'; +import { useTranslation } from 'react-i18next'; +import { usePendingMindMap } from './hooks'; + +interface IProps extends IModalProps { + data: any; +} + +const MindMapDrawer = ({ data, hideModal, visible, loading }: IProps) => { + const { t } = useTranslation(); + const percent = usePendingMindMap(); + return ( + + {loading ? ( + + + + ) : ( + + )} + + ); +}; + +export default MindMapDrawer; diff --git a/web/src/pages/search/sidebar.tsx b/web/src/pages/search/sidebar.tsx index 535875a2..4641460e 100644 --- a/web/src/pages/search/sidebar.tsx +++ b/web/src/pages/search/sidebar.tsx @@ -138,7 +138,7 @@ const SearchSidebar = ({ [styles.transparentSearchSide]: isFirstRender, })} theme={'light'} - width={240} + width={'20%'} >