Commit 28c2d926 by Liu

feat: token校验

parent c1b6b8a5
......@@ -328,6 +328,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
if (res?.data?.conversationId) {
const conversationId = res.data.conversationId
// 使用获取到的会话ID调用历史会话
await waitForToken()
const qaRes = await fetchUserQaRecordPage(conversationId, '')
console.log('qaRes chatEditor11111', qaRes)
// 通过自定义事件将历史记录数据传递给父组件进行渲染
......@@ -375,6 +376,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
if (res?.data?.conversationId) {
const conversationId = res.data.conversationId
// 使用获取到的会话ID调用历史会话
await waitForToken()
const qaRes = await fetchUserQaRecordPage(conversationId, tool.toolId)
console.log('qaRes chatEditor11111', qaRes)
// 通过自定义事件将历史记录数据传递给父组件进行渲染
......
......@@ -15,7 +15,7 @@ import { fetchUserQaRecordPage } from '@/api/conversation'
import { fetchCheckTokenApi, fetchStreamResponse } from '@/api/chat'
import { fetchToolList } from '@/api/home'
import { clearCurrentToolId, clearShouldSendQuestion, fetchConversations, setCurrentToolId } from '@/store/conversationSlice'
import { getUserRolesForApi, safeSessionStorageGetItem } from '@/lib/utils'
import { getUserRolesForApi, safeSessionStorageGetItem, waitForToken } from '@/lib/utils'
import type { RootState } from '@/store'
import { useAppDispatch, useAppSelector } from '@/store/hook'
import ScrollBtoIcon from '@/assets/svg/scrollBto.svg?react'
......@@ -314,6 +314,7 @@ export const Chat: React.FC = () => {
console.log('[Chat] refreshQuestionsFromCollect 事件已触发')
}, 100)
}
await waitForToken()
const res = await fetchUserQaRecordPage(conversationId, toolId || '')
console.log('qaRes chatEditor2222222', res)
const qaRecords = res.data || []
......@@ -424,84 +425,6 @@ export const Chat: React.FC = () => {
scrollableRef.current.scrollTo(scrollableRef.current.scrollHeight, { behavior: 'smooth' })
}
/** 等待 token 就绪,确保登录接口返回后才继续 */
const waitForToken = async (maxWaitTime = 3000): Promise<boolean> => {
const startTime = Date.now()
let initialToken = ''
// 先获取初始 token 值
try {
const initialTokenStr = window.localStorage.getItem('__TOKEN__') || '""'
initialToken = JSON.parse(initialTokenStr) || ''
}
catch {
initialToken = ''
}
// 如果初始没有 token,等待 token 出现(从无到有,说明登录完成)
if (!initialToken) {
while (Date.now() - startTime < maxWaitTime) {
const tokenStr = window.localStorage.getItem('__TOKEN__') || '""'
let token = ''
try {
token = JSON.parse(tokenStr) || ''
}
catch {
token = ''
}
if (token) {
// token 从无到有,说明登录完成,再等待一小段时间确保写入完成
await new Promise(resolve => setTimeout(resolve, 200))
return true
}
// 等待 100ms 后再次检查
await new Promise(resolve => setTimeout(resolve, 100))
}
return false
}
// 如果初始有 token,可能是旧 token 或新 token
// 等待一小段时间,确保登录流程有足够时间完成(登录接口可能会更新 token)
// 同时监听 token 变化
let tokenChanged = false
const checkTokenChange = () => {
try {
const currentTokenStr = window.localStorage.getItem('__TOKEN__') || '""'
const currentToken = JSON.parse(currentTokenStr) || ''
if (currentToken && currentToken !== initialToken) {
tokenChanged = true
}
}
catch {
// 忽略解析错误
}
}
// 监听 storage 事件(跨标签页)
window.addEventListener('storage', checkTokenChange)
// 轮询检查(同标签页)
const interval = setInterval(checkTokenChange, 100)
// 等待最多 1 秒,检测 token 是否变化
const waitForChange = new Promise<void>((resolve) => {
setTimeout(() => {
window.removeEventListener('storage', checkTokenChange)
clearInterval(interval)
resolve()
}, 1000)
})
await waitForChange
// 如果 token 变化了,说明登录完成,再等待一小段时间确保写入完成
if (tokenChanged) {
await new Promise(resolve => setTimeout(resolve, 200))
return true
}
// 如果 token 没有变化,可能是已经登录完成,但为了确保登录流程完成,再等待一小段时间
await new Promise(resolve => setTimeout(resolve, 300))
return true
}
useEffect(() => {
if (id) {
// 检查是否已通过 toolHistoryLoaded 事件加载过相同会话的数据
......
......@@ -23,7 +23,7 @@ import ScrollBtoIcon from '@/assets/svg/scrollBto.svg?react'
import { setIsAsking } from '@/store/chatSlice'
import SdreamLoading from '@/components/SdreamLoading'
import useToast from '@/hooks/useToast'
import { safeLocalStorageGetItem } from '@/lib/utils'
import { safeLocalStorageGetItem, waitForToken } from '@/lib/utils'
export const TacticsChat: React.FC = () => {
const { id } = useParams<{ id: string }>()
......@@ -537,6 +537,7 @@ export const TacticsChat: React.FC = () => {
// 在异步操作开始前保存 createdFromClearRef 的值,避免在异步过程中被其他逻辑修改
const wasCreatedFromClear = createdFromClearRef.current
try {
await waitForToken()
const res = await fetchTacticsQaRecordPage(conversationId)
const qaRecords = res.data || []
const hasHistoryFlag = qaRecords.length > 0
......
......@@ -3,6 +3,7 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { processConversationData } from './conversationSlice.helper'
import type { Conversation, ConversationState } from '@/types/conversation'
import { fetchCreateConversation, fetchDeleteUserConversation, fetchQueryUserConversationPage } from '@/api/conversation'
import { waitForToken } from '@/lib/utils'
const initialState: ConversationState = {
conversations: [],
......@@ -18,6 +19,7 @@ export const fetchConversations = createAsyncThunk(
'conversation/fetchConversations',
async (_, { rejectWithValue }) => {
try {
await waitForToken()
// 调用真实接口获取会话列表
const response = await fetchQueryUserConversationPage({
pageNum: 1,
......@@ -41,6 +43,7 @@ export const deleteConversations = createAsyncThunk<
'conversation/deleteConversations',
async (conversationIds, { dispatch, rejectWithValue }) => {
try {
await waitForToken()
// 调用删除会话的 API,传入 ID 集合
await fetchDeleteUserConversation(conversationIds)
......@@ -63,6 +66,7 @@ export const createConversation = createAsyncThunk<
>(
'conversation/createConversation',
async ({ conversationData, shouldNavigate, shouldSendQuestion }, { dispatch }) => {
await waitForToken()
// 从缓存中获取 toolId 作为 busiId
const cachedToolId = typeof window !== 'undefined' ? sessionStorage.getItem('currentToolId') : null
const busiId = cachedToolId || ''
......
......@@ -3,6 +3,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import type { TacticsConversation, TacticsConversationState } from '@/types/tactics'
import { fetchCreateTacticsConversation, fetchDeleteTacticsConversation } from '@/api/tactics'
import { waitForToken } from '@/lib/utils'
const initialState: TacticsConversationState = {
conversations: [],
......@@ -29,6 +30,7 @@ export const deleteTacticsConversations = createAsyncThunk<
'tactics/deleteTacticsConversations',
async (conversationIds, { dispatch, rejectWithValue }) => {
try {
await waitForToken()
await fetchDeleteTacticsConversation(conversationIds)
await dispatch(fetchTacticsConversations())
return true
......@@ -46,6 +48,7 @@ export const createTacticsConversation = createAsyncThunk<
>(
'tactics/createTacticsConversation',
async ({ conversationData, shouldNavigate, shouldSendQuestion }, { dispatch }) => {
await waitForToken()
const response = await fetchCreateTacticsConversation(conversationData)
const newConversation = response.data
......
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