From 5808aef28cff1f9d3f0560a276884b91fbc92bf6 Mon Sep 17 00:00:00 2001 From: chanx <1243304602@qq.com> Date: Mon, 18 Aug 2025 14:50:29 +0800 Subject: [PATCH] Fix (search): Optimize the search page functionality and UI #3221 (#9525) ### What problem does this PR solve? Fix (search): Optimize the search page functionality and UI #3221 - Add a search list component - Implement search settings - Optimize search result display - Add related search functionality - Adjust the search input box style - Unify internationalized text ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --- web/src/components/ragflow-avatar.tsx | 2 +- web/src/locales/en.ts | 18 ++ web/src/locales/zh-traditional.ts | 6 + web/src/locales/zh.ts | 18 ++ web/src/pages/home/applications.tsx | 2 + web/src/pages/home/search-list.tsx | 15 ++ web/src/pages/next-search/embed-app-modal.tsx | 38 ++-- web/src/pages/next-search/hooks.ts | 13 ++ web/src/pages/next-search/index.tsx | 23 ++- web/src/pages/next-search/search-home.tsx | 8 +- web/src/pages/next-search/search-setting.tsx | 51 ++--- web/src/pages/next-search/search-view.tsx | 174 +++++++++--------- web/src/pages/next-search/searching.tsx | 3 - web/src/pages/next-search/share/index.tsx | 25 ++- 14 files changed, 237 insertions(+), 159 deletions(-) create mode 100644 web/src/pages/home/search-list.tsx diff --git a/web/src/components/ragflow-avatar.tsx b/web/src/components/ragflow-avatar.tsx index 63f492fd3..ab46f9f73 100644 --- a/web/src/components/ragflow-avatar.tsx +++ b/web/src/components/ragflow-avatar.tsx @@ -49,7 +49,7 @@ export const RAGFlowAvatar = memo( const initials = getInitials(name); const { from, to } = name ? getColorForName(name) - : { from: 'hsl(0, 0%, 80%)', to: 'hsl(0, 0%, 30%)' }; + : { from: 'hsl(0, 0%, 30%)', to: 'hsl(0, 0%, 80%)' }; const fallbackRef = useRef(null); const [fontSize, setFontSize] = useState('0.875rem'); diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index a23d2c5b0..fc90c4f95 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -1419,6 +1419,24 @@ This delimiter is used to split the input text into several text pieces echo of search: { createSearch: 'Create Search', searchGreeting: 'How can I help you today ?', + profile: 'Hide Profile', + locale: 'Locale', + embedCode: 'Embed code', + id: 'ID', + copySuccess: 'Copy Success', + welcomeBack: 'Welcome back', + searchSettings: 'Search Settings', + name: 'Name', + avatar: 'Avatar', + description: 'Description', + datasets: 'Datasets', + rerankModel: 'Rerank Model', + AISummary: 'AI Summary', + enableWebSearch: 'Enable Web Search', + enableRelatedSearch: 'Enable Related Search', + showQueryMindmap: 'Show Query Mindmap', + embedApp: 'Embed App', + relatedSearch: 'Related Search', }, }, }; diff --git a/web/src/locales/zh-traditional.ts b/web/src/locales/zh-traditional.ts index c91f49aa3..37a783687 100644 --- a/web/src/locales/zh-traditional.ts +++ b/web/src/locales/zh-traditional.ts @@ -1192,6 +1192,12 @@ export default { search: { createSearch: '新建查詢', searchGreeting: '今天我能為你做些什麽?', + profile: '隱藏個人資料', + locale: '語言', + embedCode: '嵌入代碼', + id: 'ID', + copySuccess: '複製成功', + welcomeBack: '歡迎回來', }, }, }; diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index 3b37c3ba2..aa2251534 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -1323,6 +1323,24 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 search: { createSearch: '新建查询', searchGreeting: '今天我能为你做些什么?', + profile: '隐藏个人资料', + locale: '语言', + embedCode: '嵌入代码', + id: 'ID', + copySuccess: '复制成功', + welcomeBack: '欢迎回来', + searchSettings: '搜索设置', + name: '姓名', + avatar: '头像', + description: '描述', + datasets: '数据集', + rerankModel: 'rerank 模型', + AISummary: 'AI 总结', + enableWebSearch: '启用网页搜索', + enableRelatedSearch: '启用相关搜索', + showQueryMindmap: '显示查询思维导图', + embedApp: '嵌入网站', + relatedSearch: '相关搜索', }, }, }; diff --git a/web/src/pages/home/applications.tsx b/web/src/pages/home/applications.tsx index 60ccba714..2b4fa37f6 100644 --- a/web/src/pages/home/applications.tsx +++ b/web/src/pages/home/applications.tsx @@ -7,6 +7,7 @@ import { useNavigate } from 'umi'; import { Agents } from './agent-list'; import { SeeAllAppCard } from './application-card'; import { ChatList } from './chat-list'; +import { SearchList } from './search-list'; const IconMap = { [Routes.Chats]: 'chat', @@ -56,6 +57,7 @@ export function Applications() {
{val === Routes.Agents && } {val === Routes.Chats && } + {val === Routes.Searches && } {}
diff --git a/web/src/pages/home/search-list.tsx b/web/src/pages/home/search-list.tsx new file mode 100644 index 000000000..af22ab5f0 --- /dev/null +++ b/web/src/pages/home/search-list.tsx @@ -0,0 +1,15 @@ +import { useFetchSearchList } from '../next-searches/hooks'; +import { ApplicationCard } from './application-card'; + +export function SearchList() { + const { data } = useFetchSearchList(); + + return data?.data.search_apps + .slice(0, 10) + .map((x) => ( + + )); +} diff --git a/web/src/pages/next-search/embed-app-modal.tsx b/web/src/pages/next-search/embed-app-modal.tsx index 83ad52940..9907a636b 100644 --- a/web/src/pages/next-search/embed-app-modal.tsx +++ b/web/src/pages/next-search/embed-app-modal.tsx @@ -7,21 +7,28 @@ import { LanguageAbbreviationMap, } from '@/constants/common'; import { useTranslate } from '@/hooks/common-hooks'; -import { useCallback, useMemo, useState } from 'react'; +import { message } from 'antd'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useFetchTokenListBeforeOtherStep } from '../agent/hooks/use-show-dialog'; type IEmbedAppModalProps = { open: any; url: string; token: string; from: string; - beta: string; setOpen: (e: any) => void; tenantId: string; }; const EmbedAppModal = (props: IEmbedAppModalProps) => { - const { t } = useTranslate('chat'); - const { open, setOpen, token = '', from, beta = '', url, tenantId } = props; + const { t } = useTranslate('search'); + const { open, setOpen, token = '', from, url, tenantId } = props; + const { beta, handleOperate } = useFetchTokenListBeforeOtherStep(); + useEffect(() => { + if (open && !beta) { + handleOperate(); + } + }, [handleOperate, open, beta]); const [hideAvatar, setHideAvatar] = useState(false); const [locale, setLocale] = useState(''); @@ -69,7 +76,7 @@ const EmbedAppModal = (props: IEmbedAppModalProps) => { {/* Hide Avatar Toggle */}
{ {/* Locale Select */}
- + {
{/* Embed Code */}
- + {/*
*/} {/*
{text}
*/} {text} @@ -102,18 +113,21 @@ const EmbedAppModal = (props: IEmbedAppModalProps) => { {/* ID Field */}
- -
+ +
{!isSearching && ( @@ -130,7 +135,9 @@ export default function SearchPage() { onClick={() => setOpenSetting(!openSetting)} > -
Search Settings
+
+ {t('search.searchSettings')} +
)} diff --git a/web/src/pages/next-search/search-home.tsx b/web/src/pages/next-search/search-home.tsx index 1ea626d0e..37f9ceeec 100644 --- a/web/src/pages/next-search/search-home.tsx +++ b/web/src/pages/next-search/search-home.tsx @@ -3,6 +3,7 @@ import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; import { cn } from '@/lib/utils'; import { Search } from 'lucide-react'; import { Dispatch, SetStateAction } from 'react'; +import { useTranslation } from 'react-i18next'; import './index.less'; import Spotlight from './spotlight'; @@ -18,6 +19,7 @@ export default function SearchPage({ setSearchText: Dispatch>; }) { const { data: userInfo } = useFetchUserInfo(); + const { t } = useTranslation(); return (
@@ -36,14 +38,14 @@ export default function SearchPage({ <>

👋 Hi there

- Welcome back, {userInfo?.nickname} + {t('search.welcomeBack')}, {userInfo?.nickname}

)}
{ @@ -57,7 +59,7 @@ export default function SearchPage({ /> - +
diff --git a/web/src/pages/next-search/search-view.tsx b/web/src/pages/next-search/search-view.tsx index 19b2826e4..bcc80283a 100644 --- a/web/src/pages/next-search/search-view.tsx +++ b/web/src/pages/next-search/search-view.tsx @@ -9,13 +9,11 @@ import { } from '@/components/ui/popover'; import { RAGFlowPagination } from '@/components/ui/ragflow-pagination'; import { Skeleton } from '@/components/ui/skeleton'; -import { Spin } from '@/components/ui/spin'; import { IReference } from '@/interfaces/database/chat'; import { cn } from '@/lib/utils'; import DOMPurify from 'dompurify'; -import { TFunction } from 'i18next'; import { isEmpty } from 'lodash'; -import { BrainCircuit, Search, Square, X } from 'lucide-react'; +import { BrainCircuit, Search, X } from 'lucide-react'; import { Dispatch, SetStateAction, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ISearchAppDetailProps } from '../next-searches/hooks'; @@ -35,7 +33,6 @@ export default function SearchingView({ answer, sendingLoading, relatedQuestions, - loading, isFirstRender, selectedDocumentIds, isSearchStrEmpty, @@ -56,19 +53,17 @@ export default function SearchingView({ handleSearch, pagination, onChange, - t, }: ISearchReturnProps & { setIsSearching?: Dispatch>; searchData: ISearchAppDetailProps; - t: TFunction<'translation', undefined>; }) { - const { t: tt, i18n } = useTranslation(); - useEffect(() => { - const changeLanguage = async () => { - await i18n.changeLanguage('zh'); - }; - changeLanguage(); - }, [i18n]); + const { t } = useTranslation(); + // useEffect(() => { + // const changeLanguage = async () => { + // await i18n.changeLanguage('zh'); + // }; + // changeLanguage(); + // }, [i18n]); const [searchtext, setSearchtext] = useState(''); useEffect(() => { @@ -105,9 +100,9 @@ export default function SearchingView({
{ @@ -122,16 +117,17 @@ export default function SearchingView({ />
{ + setSearchtext(''); handleClickRelatedQuestion(''); }} /> - | + | - ))} -
-
+
+ clickDocumentButton(chunk.doc_id, chunk as any) + } + > + + {chunk.docnm_kwd} +
+
+ {index < chunks.length - 1 && ( +
+ )} + + ); + })} + )} + {relatedQuestions?.length > 0 && + searchData.search_config.related_search && ( +
+

+ {t('relatedSearch')} +

+
+ {relatedQuestions?.map((x, idx) => ( + + ))} +
+
+ )}
diff --git a/web/src/pages/next-search/searching.tsx b/web/src/pages/next-search/searching.tsx index d4036a4e8..cd2436589 100644 --- a/web/src/pages/next-search/searching.tsx +++ b/web/src/pages/next-search/searching.tsx @@ -1,5 +1,4 @@ import { Dispatch, SetStateAction } from 'react'; -import { useTranslation } from 'react-i18next'; import { ISearchAppDetailProps } from '../next-searches/hooks'; import { useSearching } from './hooks'; import './index.less'; @@ -21,13 +20,11 @@ export default function SearchingPage({ setIsSearching, setSearchText, }); - const { t } = useTranslation(); return ( ); } diff --git a/web/src/pages/next-search/share/index.tsx b/web/src/pages/next-search/share/index.tsx index 9ecf8788e..23409b9bb 100644 --- a/web/src/pages/next-search/share/index.tsx +++ b/web/src/pages/next-search/share/index.tsx @@ -1,6 +1,6 @@ +import { RAGFlowAvatar } from '@/components/ragflow-avatar'; import i18n from '@/locales/config'; import { useEffect } from 'react'; -import { useTranslation } from 'react-i18next'; import { ISearchAppDetailProps, useFetchSearchDetail, @@ -9,7 +9,7 @@ import { useGetSharedSearchParams, useSearching } from '../hooks'; import '../index.less'; import SearchingView from '../search-view'; export default function SearchingPage() { - const { tenantId, locale } = useGetSharedSearchParams(); + const { tenantId, locale, visibleAvatar } = useGetSharedSearchParams(); const { data: searchData = { search_config: { kb_ids: [] }, @@ -18,18 +18,25 @@ export default function SearchingPage() { const searchingParam = useSearching({ data: searchData, }); - const { t } = useTranslation(); - // useEffect(() => { - // if (locale) { - // i18n.changeLanguage(locale); - // } - // }, [locale, i18n]); useEffect(() => { console.log('locale', locale, i18n.language); if (locale && i18n.language !== locale) { i18n.changeLanguage(locale); } }, [locale]); - return ; + return ( + <> + {visibleAvatar && ( +
+ +
{searchData.name}
+
+ )} + ; + + ); }