Commit 762d6fff by Liu

fix:切换工具按钮时重复调用接口问题

parent 7a18d17c
...@@ -15,7 +15,7 @@ import { fetchUserQaRecordPage } from '@/api/conversation' ...@@ -15,7 +15,7 @@ import { fetchUserQaRecordPage } from '@/api/conversation'
import { fetchCheckTokenApi, fetchStreamResponse } from '@/api/chat' import { fetchCheckTokenApi, fetchStreamResponse } from '@/api/chat'
import { fetchToolList } from '@/api/home' import { fetchToolList } from '@/api/home'
import { clearCurrentToolId, clearShouldSendQuestion, fetchConversations, setCurrentToolId } from '@/store/conversationSlice' import { clearCurrentToolId, clearShouldSendQuestion, fetchConversations, setCurrentToolId } from '@/store/conversationSlice'
import { getUserRolesForApi } from '@/lib/utils' import { getUserRolesForApi, safeSessionStorageGetItem } from '@/lib/utils'
import type { RootState } from '@/store' import type { RootState } from '@/store'
import { useAppDispatch, useAppSelector } from '@/store/hook' import { useAppDispatch, useAppSelector } from '@/store/hook'
import ScrollBtoIcon from '@/assets/svg/scrollBto.svg?react' import ScrollBtoIcon from '@/assets/svg/scrollBto.svg?react'
...@@ -47,6 +47,8 @@ export const Chat: React.FC = () => { ...@@ -47,6 +47,8 @@ export const Chat: React.FC = () => {
const [currentToolName, setCurrentToolName] = useState<string | undefined>(undefined) const [currentToolName, setCurrentToolName] = useState<string | undefined>(undefined)
// 使用 ref 保存从 location.state 传递的 toolId,避免被异步操作覆盖 // 使用 ref 保存从 location.state 传递的 toolId,避免被异步操作覆盖
const toolIdFromStateRef = useRef<string | null | undefined>(undefined) const toolIdFromStateRef = useRef<string | null | undefined>(undefined)
// 标记是否已通过 toolHistoryLoaded 事件加载数据,避免重复调用接口
const toolHistoryLoadedRef = useRef<{ conversationId: string | null }>({ conversationId: null })
// 当外部系统直接以 /chat/:id 链接进入(没有 location.state,且 URL 中也没有 toolId)时, // 当外部系统直接以 /chat/:id 链接进入(没有 location.state,且 URL 中也没有 toolId)时,
// 视为一次新的会话入口:重置为制度活化,清除历史遗留的工具模式状态 // 视为一次新的会话入口:重置为制度活化,清除历史遗留的工具模式状态
...@@ -291,6 +293,15 @@ export const Chat: React.FC = () => { ...@@ -291,6 +293,15 @@ export const Chat: React.FC = () => {
try { try {
// 检测是否从收藏页返回 // 检测是否从收藏页返回
const fromCollect = location.state?.fromCollect const fromCollect = location.state?.fromCollect
// 如果从收藏页返回,触发事件通知 HomeNew 刷新问题列表
if (fromCollect) {
window.dispatchEvent(new CustomEvent('refreshQuestionsFromCollect', {
detail: {
toolId: toolId || currentToolId || safeSessionStorageGetItem('currentToolId') || '',
},
}))
}
const res = await fetchUserQaRecordPage(conversationId, toolId || '') const res = await fetchUserQaRecordPage(conversationId, toolId || '')
console.log('qaRes chatEditor2222222', res) console.log('qaRes chatEditor2222222', res)
const qaRecords = res.data || [] const qaRecords = res.data || []
...@@ -481,6 +492,16 @@ export const Chat: React.FC = () => { ...@@ -481,6 +492,16 @@ export const Chat: React.FC = () => {
useEffect(() => { useEffect(() => {
if (id) { if (id) {
// 检查是否已通过 toolHistoryLoaded 事件加载过相同会话的数据
// 如果已加载,跳过接口调用,避免重复请求
if (toolHistoryLoadedRef.current.conversationId === id) {
// 已加载,清除标记,避免影响后续正常的路由切换
toolHistoryLoadedRef.current.conversationId = null
// 更新 currentIdRef,确保状态一致
currentIdRef.current = id
return
}
// 停止之前的请求 // 停止之前的请求
if (abortControllerRef.current) { if (abortControllerRef.current) {
abortControllerRef.current.abort() abortControllerRef.current.abort()
...@@ -572,6 +593,8 @@ export const Chat: React.FC = () => { ...@@ -572,6 +593,8 @@ export const Chat: React.FC = () => {
const { conversationId, toolId, toolName, qaRecords } = event.detail const { conversationId, toolId, toolName, qaRecords } = event.detail
setIsLoading(true) setIsLoading(true)
try { try {
// 标记已通过事件加载数据,避免 useEffect 重复调用接口
toolHistoryLoadedRef.current.conversationId = conversationId
// 更新当前会话ID // 更新当前会话ID
currentIdRef.current = conversationId currentIdRef.current = conversationId
// 处理历史记录数据 // 处理历史记录数据
......
...@@ -14,7 +14,7 @@ import SdreamLoading from '@/components/SdreamLoading' ...@@ -14,7 +14,7 @@ import SdreamLoading from '@/components/SdreamLoading'
import { fetchLoginByToken, fetchLoginByUid } from '@/api/common' import { fetchLoginByToken, fetchLoginByUid } from '@/api/common'
import { fetchSessionConversationId } from '@/api/conversation' import { fetchSessionConversationId } from '@/api/conversation'
import { fetchCheckTokenApi } from '@/api/chat' import { fetchCheckTokenApi } from '@/api/chat'
import { getUserRolesFromRoute, safeLocalStorageGetItem, safeSessionStorageGetItem, safeSessionStorageRemoveItem } from '@/lib/utils' import { getUserRolesFromRoute, safeLocalStorageGetItem, safeSessionStorageGetItem, safeSessionStorageRemoveItem, safeSessionStorageSetItem } from '@/lib/utils'
// 从 localStorage 获取 token 的辅助函数 // 从 localStorage 获取 token 的辅助函数
function getTokenFromStorage(): string | null { function getTokenFromStorage(): string | null {
...@@ -69,6 +69,7 @@ export const Home: React.FC = () => { ...@@ -69,6 +69,7 @@ export const Home: React.FC = () => {
const location = useLocation() const location = useLocation()
const hasFetched = useRef(false) const hasFetched = useRef(false)
const hasCalledBusinessApis = useRef(false) // 防止业务接口重复调用 const hasCalledBusinessApis = useRef(false) // 防止业务接口重复调用
const prevPathRef = useRef<string>(location.pathname) // 记录上一次路径,用于检测从收藏页面返回
// 使用 useState // 使用 useState
const [otherQuestions, setOtherQuestions] = useState<any>({ content: [] }) const [otherQuestions, setOtherQuestions] = useState<any>({ content: [] })
const [isToolBtnActive, setIsToolBtnActive] = useState<boolean>(false) const [isToolBtnActive, setIsToolBtnActive] = useState<boolean>(false)
...@@ -215,6 +216,23 @@ export const Home: React.FC = () => { ...@@ -215,6 +216,23 @@ export const Home: React.FC = () => {
} }
}, [_handleToolClick, isToolBtnActive, shouldChangeStyle, dispatch]) }, [_handleToolClick, isToolBtnActive, shouldChangeStyle, dispatch])
// 监听从收藏返回时刷新问题列表的事件
useEffect(() => {
const handleRefreshQuestionsFromCollect = (event: CustomEvent) => {
const { toolId } = event.detail
// 如果传递了 toolId,先更新 sessionStorage,确保刷新时使用正确的 toolId
if (toolId) {
safeSessionStorageSetItem('currentToolId', toolId)
}
// 刷新问题列表,会调用 generate_question 接口
handleRefreshQuestions()
}
window.addEventListener('refreshQuestionsFromCollect', handleRefreshQuestionsFromCollect as EventListener)
return () => {
window.removeEventListener('refreshQuestionsFromCollect', handleRefreshQuestionsFromCollect as EventListener)
}
}, [handleRefreshQuestions])
const login = useCallback(async () => { const login = useCallback(async () => {
// 防止重复调用(组件级别保护,每次组件挂载时会重置,确保每次打开链接都能调用) // 防止重复调用(组件级别保护,每次组件挂载时会重置,确保每次打开链接都能调用)
if (hasFetched.current) { if (hasFetched.current) {
...@@ -379,6 +397,23 @@ export const Home: React.FC = () => { ...@@ -379,6 +397,23 @@ export const Home: React.FC = () => {
dispatch(clearCurrentToolId()) dispatch(clearCurrentToolId())
}, [token, dispatch]) }, [token, dispatch])
// 监听路径变化,检测从收藏页面返回时刷新问题列表
useEffect(() => {
const currentPath = location.pathname
const prevPath = prevPathRef.current
// 检测从收藏页面返回到首页(避免首次挂载误触发)
if (prevPath && prevPath !== currentPath && prevPath === '/collect' && (currentPath === '/' || currentPath === '/home')) {
// 确保已登录后再调用接口
if (token) {
handleRefreshQuestions()
}
}
// 更新上一次路径
prevPathRef.current = currentPath
}, [location.pathname, token, handleRefreshQuestions])
return ( return (
<div className={styles.homePage}> <div className={styles.homePage}>
{isLoading && ( {isLoading && (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment