diff --git a/packages/web/hooks/useLinkedScroll.tsx b/packages/web/hooks/useLinkedScroll.tsx index d612a1cad..f48658c68 100644 --- a/packages/web/hooks/useLinkedScroll.tsx +++ b/packages/web/hooks/useLinkedScroll.tsx @@ -211,7 +211,7 @@ export function useLinkedScroll< // 初始加载 useEffect(() => { if (canLoadData) { - // 重置初始滚动状态 + setInitialLoadDone(false); hasScrolledToInitial.current = false; loadData({ @@ -225,10 +225,10 @@ export function useLinkedScroll< // 监听初始加载完成,执行初始滚动 useEffect(() => { if (initialLoadDone && dataList.length > 0 && !hasScrolledToInitial.current) { - hasScrolledToInitial.current = true; const foundIndex = dataList.findIndex((item) => item._id === initialId); if (foundIndex >= 0) { + hasScrolledToInitial.current = true; setTimeout(() => { scrollToItem(foundIndex); }, 200); @@ -299,7 +299,6 @@ export function useLinkedScroll< setDataList, isLoading, loadData, - initialLoadDone, ScrollData, itemRefs, scrollToItem diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 628de16a0..816d1355a 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -457,6 +457,7 @@ "core.chat.quote.Read Quote": "View Quote", "core.chat.quote.afterUpdate": "After update", "core.chat.quote.beforeUpdate": "Before update", + "core.chat.quote.source": "From: {{source}}", "core.chat.response.Complete Response": "Complete Response", "core.chat.response.Extension model": "Question Optimization Model", "core.chat.response.Read complete response": "View Details", diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index 909e1adba..d46f77878 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -460,6 +460,7 @@ "core.chat.quote.Read Quote": "查看引用", "core.chat.quote.afterUpdate": "更新后", "core.chat.quote.beforeUpdate": "更新前", + "core.chat.quote.source": "来源:{{source}}", "core.chat.response.Complete Response": "完整响应", "core.chat.response.Extension model": "问题优化模型", "core.chat.response.Read complete response": "查看详情", diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index 027ca0505..226fee291 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -456,6 +456,7 @@ "core.chat.quote.Read Quote": "檢視引用", "core.chat.quote.afterUpdate": "更新後", "core.chat.quote.beforeUpdate": "更新前", + "core.chat.quote.source": "來源:{{source}}", "core.chat.response.Complete Response": "完整回應", "core.chat.response.Extension model": "問題最佳化模型", "core.chat.response.Read complete response": "檢視詳細資料", diff --git a/projects/app/src/components/SideBar/index.tsx b/projects/app/src/components/SideBar/index.tsx index 3af058e14..c9a516fb5 100644 --- a/projects/app/src/components/SideBar/index.tsx +++ b/projects/app/src/components/SideBar/index.tsx @@ -1,35 +1,26 @@ -import React, { useState, useEffect, useRef } from 'react'; +import React from 'react'; import { Box, Flex } from '@chakra-ui/react'; import type { BoxProps } from '@chakra-ui/react'; import MyIcon from '@fastgpt/web/components/common/Icon'; interface Props extends BoxProps { - externalTrigger?: Boolean; + isFolded?: boolean; + onFoldChange?: (isFolded: boolean) => void; } const SideBar = (e?: Props) => { const { w = ['100%', '0 0 250px', '0 0 250px', '0 0 270px', '0 0 290px'], children, - externalTrigger, + isFolded = false, + onFoldChange, ...props } = e || {}; - const [isFolded, setIsFolded] = useState(false); - - const prevExternalTriggerRef = useRef(undefined); - - useEffect(() => { - if (externalTrigger && !prevExternalTriggerRef.current && !isFolded) { - setIsFolded(true); - } - - prevExternalTriggerRef.current = externalTrigger; - }, [externalTrigger, isFolded]); - const handleToggle = () => { - const newFolded = !isFolded; - setIsFolded(newFolded); + if (onFoldChange) { + onFoldChange(!isFolded); + } }; return ( diff --git a/projects/app/src/pageComponents/chat/ChatQuoteList/CollectionQuoteItem.tsx b/projects/app/src/pageComponents/chat/ChatQuoteList/CollectionQuoteItem.tsx index 4d0285467..4a0915b5e 100644 --- a/projects/app/src/pageComponents/chat/ChatQuoteList/CollectionQuoteItem.tsx +++ b/projects/app/src/pageComponents/chat/ChatQuoteList/CollectionQuoteItem.tsx @@ -77,20 +77,18 @@ const CollectionQuoteItem = ({ }} > {updated && ( - - - {t('common:core.dataset.data.Updated')} + + + {t('common:core.dataset.data.Updated')} + + )} diff --git a/projects/app/src/pageComponents/chat/ChatQuoteList/CollectionQuoteReader.tsx b/projects/app/src/pageComponents/chat/ChatQuoteList/CollectionQuoteReader.tsx index 32a290a88..82e0ec7d3 100644 --- a/projects/app/src/pageComponents/chat/ChatQuoteList/CollectionQuoteReader.tsx +++ b/projects/app/src/pageComponents/chat/ChatQuoteList/CollectionQuoteReader.tsx @@ -18,7 +18,6 @@ import { GetCollectionQuoteDataProps } from '@/web/core/chat/context/chatItemCon import { useUserStore } from '@/web/support/user/useUserStore'; import { getCollectionQuote } from '@/web/core/chat/api'; import MyIconButton from '@fastgpt/web/components/common/Icon/button'; -import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import MyBox from '@fastgpt/web/components/common/MyBox'; import { getCollectionSourceAndOpen } from '@/web/core/dataset/hooks/readCollectionSource'; import { QuoteDataItemType } from '@/service/core/chat/constants'; @@ -40,10 +39,10 @@ const CollectionReader = ({ const [quoteIndex, setQuoteIndex] = useState(0); // Get dataset permission - const { data: permissionData, loading: isPermissionLoading } = useRequest2( + const { data: datasetData, loading: isPermissionLoading } = useRequest2( async () => await getDatasetDataPermission(datasetId), { - manual: !userInfo && !datasetId, + manual: !userInfo || !datasetId, refreshDeps: [datasetId, userInfo] } ); @@ -167,21 +166,7 @@ const CollectionReader = ({ > {sourceName || t('common:common.UnKnow Source')} - {!!userInfo && permissionData?.permission?.hasReadPer && ( - - { - router.push( - `/dataset/detail?datasetId=${datasetId}¤tTab=dataCard&collectionId=${collectionId}` - ); - }} - /> - - )} - + - - {t('common:core.chat.quote.Quote Tip')} - + {!isPermissionLoading && ( + { + if (!!userInfo && datasetData?.permission?.hasReadPer) { + router.push( + `/dataset/detail?datasetId=${datasetId}¤tTab=dataCard&collectionId=${collectionId}` + ); + } + }} + {...(!!userInfo && datasetData?.permission?.hasReadPer + ? { + cursor: 'pointer', + _hover: { color: 'primary.600', textDecoration: 'underline' } + } + : {})} + > + {t('common:core.chat.quote.source', { + source: datasetData?.datasetName + })} + + )} {/* header control */} {datasetDataList.length > 0 && ( - - {/* 引用序号 */} - - - {t('common:core.chat.Quote')} {quoteIndex + 1} - - - / - - - {filterResults.length} - + + + {/* 引用序号 */} + + + {t('common:core.chat.Quote')} {quoteIndex + 1} + + + / + + + {filterResults.length} + + + + {/* 检索分数 */} + {!loading && + (!isDeleted ? ( + + ) : ( + + + {t('chat:chat.quote.deleted')} + + ))} + + + + {/* 检索按钮 */} + + handleNavigate(quoteIndex - 1)} + /> + handleNavigate(quoteIndex + 1)} + /> + - - {/* 检索分数 */} - {!loading && - (!isDeleted ? ( - - ) : ( - - - {t('chat:chat.quote.deleted')} - - ))} - - - - {/* 检索按钮 */} - - handleNavigate(quoteIndex - 1)} - /> - handleNavigate(quoteIndex + 1)} - /> - - + + {t('common:core.chat.quote.Quote Tip')} + + )} {/* quote list */} @@ -282,7 +292,7 @@ const CollectionReader = ({ a={item.a} dataId={item._id} collectionId={collectionId} - canEdit={!!userInfo && !!permissionData?.permission?.hasWritePer} + canEdit={!!userInfo && !!datasetData?.permission?.hasWritePer} /> ))} diff --git a/projects/app/src/pageComponents/chat/ChatQuoteList/DownloadButton.tsx b/projects/app/src/pageComponents/chat/ChatQuoteList/DownloadButton.tsx index 0dd3e8b8f..27d962deb 100644 --- a/projects/app/src/pageComponents/chat/ChatQuoteList/DownloadButton.tsx +++ b/projects/app/src/pageComponents/chat/ChatQuoteList/DownloadButton.tsx @@ -17,7 +17,17 @@ const DownloadButton = ({ return ( } + Button={ + + } menuList={[ { children: [ diff --git a/projects/app/src/pageComponents/chat/ChatQuoteList/index.tsx b/projects/app/src/pageComponents/chat/ChatQuoteList/index.tsx index cc580f213..9103e9c70 100644 --- a/projects/app/src/pageComponents/chat/ChatQuoteList/index.tsx +++ b/projects/app/src/pageComponents/chat/ChatQuoteList/index.tsx @@ -1,9 +1,8 @@ import React from 'react'; import { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; -import { ChatItemContext, GetQuoteProps } from '@/web/core/chat/context/chatItemContext'; +import { GetQuoteProps } from '@/web/core/chat/context/chatItemContext'; import CollectionQuoteReader from './CollectionQuoteReader'; import QuoteReader from './QuoteReader'; -import { useContextSelector } from 'use-context-selector'; const ChatQuoteList = ({ rawSearch = [], @@ -14,8 +13,6 @@ const ChatQuoteList = ({ metadata: GetQuoteProps; onClose: () => void; }) => { - const isShowReadRawSource = useContextSelector(ChatItemContext, (v) => v.isShowReadRawSource); - return ( <> {'collectionId' in metadata && ( diff --git a/projects/app/src/pages/api/core/dataset/data/getPermission.ts b/projects/app/src/pages/api/core/dataset/data/getPermission.ts index 16191e9ec..b0a014a8c 100644 --- a/projects/app/src/pages/api/core/dataset/data/getPermission.ts +++ b/projects/app/src/pages/api/core/dataset/data/getPermission.ts @@ -6,6 +6,7 @@ import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset'; export type GetQuotePermissionResponse = | { + datasetName: string; permission: { hasWritePer: boolean; hasReadPer: boolean; @@ -22,7 +23,7 @@ async function handler(req: NextApiRequest): Promise } try { - const { permission } = await authDataset({ + const { permission, dataset } = await authDataset({ req, authToken: true, authApiKey: true, @@ -31,6 +32,7 @@ async function handler(req: NextApiRequest): Promise }); return { + datasetName: dataset.name, permission: { hasReadPer: permission.hasReadPer, hasWritePer: permission.hasWritePer @@ -39,6 +41,7 @@ async function handler(req: NextApiRequest): Promise } catch (error) { if (error === DatasetErrEnum.unAuthDataset) { return { + datasetName: '', permission: { hasWritePer: false, hasReadPer: false diff --git a/projects/app/src/pages/chat/index.tsx b/projects/app/src/pages/chat/index.tsx index 31a1da1d6..ca4972b18 100644 --- a/projects/app/src/pages/chat/index.tsx +++ b/projects/app/src/pages/chat/index.tsx @@ -65,6 +65,14 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => { const chatRecords = useContextSelector(ChatRecordContext, (v) => v.chatRecords); const totalRecordsCount = useContextSelector(ChatRecordContext, (v) => v.totalRecordsCount); + const [sidebarFolded, setSidebarFolded] = useState(false); + + useEffect(() => { + if (quoteData) { + setSidebarFolded(true); + } + }, [quoteData]); + // Load chat init data const { loading } = useRequest2( async () => { @@ -148,7 +156,9 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => { ); return isPc || !appId ? ( - {Children} + + {Children} + ) : ( { {Children} ); - }, [t, isPc, appId, isOpenSlider, onCloseSlider, quoteData]); + }, [t, isPc, appId, isOpenSlider, onCloseSlider, sidebarFolded]); return ( diff --git a/projects/app/src/pages/chat/share.tsx b/projects/app/src/pages/chat/share.tsx index 558357edd..a8d7191d4 100644 --- a/projects/app/src/pages/chat/share.tsx +++ b/projects/app/src/pages/chat/share.tsx @@ -90,6 +90,14 @@ const OutLink = (props: Props) => { const totalRecordsCount = useContextSelector(ChatRecordContext, (v) => v.totalRecordsCount); const isChatRecordsLoaded = useContextSelector(ChatRecordContext, (v) => v.isChatRecordsLoaded); + const [sidebarFolded, setSidebarFolded] = useState(false); + + useEffect(() => { + if (quoteData) { + setSidebarFolded(true); + } + }, [quoteData]); + const initSign = useRef(false); const { data, loading } = useRequest2( async () => { @@ -221,7 +229,9 @@ const OutLink = (props: Props) => { if (showHistory !== '1') return null; return isPc ? ( - {Children} + + {Children} + ) : ( { ); - }, [isOpenSlider, isPc, onCloseSlider, quoteData, showHistory, t]); + }, [isOpenSlider, isPc, onCloseSlider, showHistory, t, sidebarFolded]); return ( <> diff --git a/projects/app/src/pages/chat/team.tsx b/projects/app/src/pages/chat/team.tsx index dc871a0ea..b42efd5f5 100644 --- a/projects/app/src/pages/chat/team.tsx +++ b/projects/app/src/pages/chat/team.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import NextHead from '@/components/common/NextHead'; import { getTeamChatInfo } from '@/web/core/chat/api'; import { useRouter } from 'next/router'; @@ -70,6 +70,14 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => { const chatRecords = useContextSelector(ChatRecordContext, (v) => v.chatRecords); const totalRecordsCount = useContextSelector(ChatRecordContext, (v) => v.totalRecordsCount); + const [sidebarFolded, setSidebarFolded] = useState(false); + + useEffect(() => { + if (quoteData) { + setSidebarFolded(true); + } + }, [quoteData]); + // get chat app info const { loading } = useRequest2( async () => { @@ -166,7 +174,9 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => { ); return isPc || !appId ? ( - {Children} + + {Children} + ) : ( { {Children} ); - }, [appId, isOpenSlider, isPc, onCloseSlider, quoteData, t]); + }, [appId, isOpenSlider, isPc, onCloseSlider, t, sidebarFolded]); return ( diff --git a/projects/app/src/service/core/dataset/data/controller.ts b/projects/app/src/service/core/dataset/data/controller.ts index a2dae3e14..cb8e4c8e5 100644 --- a/projects/app/src/service/core/dataset/data/controller.ts +++ b/projects/app/src/service/core/dataset/data/controller.ts @@ -221,6 +221,7 @@ export async function updateData2Dataset({ } // 4. Update mongo updateTime(便于脏数据检查器识别) + const updateTime = mongoData.updateTime; mongoData.updateTime = new Date(); await mongoData.save(); @@ -258,7 +259,7 @@ export async function updateData2Dataset({ { q: mongoData.q, a: mongoData.a, - updateTime: new Date() + updateTime: updateTime }, ...(mongoData.history?.slice(0, 9) || []) ]