Commit 28c2d926 by Liu

feat: token校验

parent c1b6b8a5
...@@ -328,6 +328,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth, ...@@ -328,6 +328,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
if (res?.data?.conversationId) { if (res?.data?.conversationId) {
const conversationId = res.data.conversationId const conversationId = res.data.conversationId
// 使用获取到的会话ID调用历史会话 // 使用获取到的会话ID调用历史会话
await waitForToken()
const qaRes = await fetchUserQaRecordPage(conversationId, '') const qaRes = await fetchUserQaRecordPage(conversationId, '')
console.log('qaRes chatEditor11111', qaRes) console.log('qaRes chatEditor11111', qaRes)
// 通过自定义事件将历史记录数据传递给父组件进行渲染 // 通过自定义事件将历史记录数据传递给父组件进行渲染
...@@ -375,6 +376,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth, ...@@ -375,6 +376,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
if (res?.data?.conversationId) { if (res?.data?.conversationId) {
const conversationId = res.data.conversationId const conversationId = res.data.conversationId
// 使用获取到的会话ID调用历史会话 // 使用获取到的会话ID调用历史会话
await waitForToken()
const qaRes = await fetchUserQaRecordPage(conversationId, tool.toolId) const qaRes = await fetchUserQaRecordPage(conversationId, tool.toolId)
console.log('qaRes chatEditor11111', qaRes) console.log('qaRes chatEditor11111', qaRes)
// 通过自定义事件将历史记录数据传递给父组件进行渲染 // 通过自定义事件将历史记录数据传递给父组件进行渲染
......
...@@ -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, safeSessionStorageGetItem } from '@/lib/utils' import { getUserRolesForApi, safeSessionStorageGetItem, waitForToken } 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'
...@@ -314,6 +314,7 @@ export const Chat: React.FC = () => { ...@@ -314,6 +314,7 @@ export const Chat: React.FC = () => {
console.log('[Chat] refreshQuestionsFromCollect 事件已触发') console.log('[Chat] refreshQuestionsFromCollect 事件已触发')
}, 100) }, 100)
} }
await waitForToken()
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 || []
...@@ -424,84 +425,6 @@ export const Chat: React.FC = () => { ...@@ -424,84 +425,6 @@ export const Chat: React.FC = () => {
scrollableRef.current.scrollTo(scrollableRef.current.scrollHeight, { behavior: 'smooth' }) 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(() => { useEffect(() => {
if (id) { if (id) {
// 检查是否已通过 toolHistoryLoaded 事件加载过相同会话的数据 // 检查是否已通过 toolHistoryLoaded 事件加载过相同会话的数据
......
...@@ -23,7 +23,7 @@ import ScrollBtoIcon from '@/assets/svg/scrollBto.svg?react' ...@@ -23,7 +23,7 @@ import ScrollBtoIcon from '@/assets/svg/scrollBto.svg?react'
import { setIsAsking } from '@/store/chatSlice' import { setIsAsking } from '@/store/chatSlice'
import SdreamLoading from '@/components/SdreamLoading' import SdreamLoading from '@/components/SdreamLoading'
import useToast from '@/hooks/useToast' import useToast from '@/hooks/useToast'
import { safeLocalStorageGetItem } from '@/lib/utils' import { safeLocalStorageGetItem, waitForToken } from '@/lib/utils'
export const TacticsChat: React.FC = () => { export const TacticsChat: React.FC = () => {
const { id } = useParams<{ id: string }>() const { id } = useParams<{ id: string }>()
...@@ -537,6 +537,7 @@ export const TacticsChat: React.FC = () => { ...@@ -537,6 +537,7 @@ export const TacticsChat: React.FC = () => {
// 在异步操作开始前保存 createdFromClearRef 的值,避免在异步过程中被其他逻辑修改 // 在异步操作开始前保存 createdFromClearRef 的值,避免在异步过程中被其他逻辑修改
const wasCreatedFromClear = createdFromClearRef.current const wasCreatedFromClear = createdFromClearRef.current
try { try {
await waitForToken()
const res = await fetchTacticsQaRecordPage(conversationId) const res = await fetchTacticsQaRecordPage(conversationId)
const qaRecords = res.data || [] const qaRecords = res.data || []
const hasHistoryFlag = qaRecords.length > 0 const hasHistoryFlag = qaRecords.length > 0
......
...@@ -3,6 +3,7 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit' ...@@ -3,6 +3,7 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { processConversationData } from './conversationSlice.helper' import { processConversationData } from './conversationSlice.helper'
import type { Conversation, ConversationState } from '@/types/conversation' import type { Conversation, ConversationState } from '@/types/conversation'
import { fetchCreateConversation, fetchDeleteUserConversation, fetchQueryUserConversationPage } from '@/api/conversation' import { fetchCreateConversation, fetchDeleteUserConversation, fetchQueryUserConversationPage } from '@/api/conversation'
import { waitForToken } from '@/lib/utils'
const initialState: ConversationState = { const initialState: ConversationState = {
conversations: [], conversations: [],
...@@ -18,6 +19,7 @@ export const fetchConversations = createAsyncThunk( ...@@ -18,6 +19,7 @@ export const fetchConversations = createAsyncThunk(
'conversation/fetchConversations', 'conversation/fetchConversations',
async (_, { rejectWithValue }) => { async (_, { rejectWithValue }) => {
try { try {
await waitForToken()
// 调用真实接口获取会话列表 // 调用真实接口获取会话列表
const response = await fetchQueryUserConversationPage({ const response = await fetchQueryUserConversationPage({
pageNum: 1, pageNum: 1,
...@@ -41,6 +43,7 @@ export const deleteConversations = createAsyncThunk< ...@@ -41,6 +43,7 @@ export const deleteConversations = createAsyncThunk<
'conversation/deleteConversations', 'conversation/deleteConversations',
async (conversationIds, { dispatch, rejectWithValue }) => { async (conversationIds, { dispatch, rejectWithValue }) => {
try { try {
await waitForToken()
// 调用删除会话的 API,传入 ID 集合 // 调用删除会话的 API,传入 ID 集合
await fetchDeleteUserConversation(conversationIds) await fetchDeleteUserConversation(conversationIds)
...@@ -63,6 +66,7 @@ export const createConversation = createAsyncThunk< ...@@ -63,6 +66,7 @@ export const createConversation = createAsyncThunk<
>( >(
'conversation/createConversation', 'conversation/createConversation',
async ({ conversationData, shouldNavigate, shouldSendQuestion }, { dispatch }) => { async ({ conversationData, shouldNavigate, shouldSendQuestion }, { dispatch }) => {
await waitForToken()
// 从缓存中获取 toolId 作为 busiId // 从缓存中获取 toolId 作为 busiId
const cachedToolId = typeof window !== 'undefined' ? sessionStorage.getItem('currentToolId') : null const cachedToolId = typeof window !== 'undefined' ? sessionStorage.getItem('currentToolId') : null
const busiId = cachedToolId || '' const busiId = cachedToolId || ''
......
...@@ -3,6 +3,7 @@ import type { PayloadAction } from '@reduxjs/toolkit' ...@@ -3,6 +3,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit' import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import type { TacticsConversation, TacticsConversationState } from '@/types/tactics' import type { TacticsConversation, TacticsConversationState } from '@/types/tactics'
import { fetchCreateTacticsConversation, fetchDeleteTacticsConversation } from '@/api/tactics' import { fetchCreateTacticsConversation, fetchDeleteTacticsConversation } from '@/api/tactics'
import { waitForToken } from '@/lib/utils'
const initialState: TacticsConversationState = { const initialState: TacticsConversationState = {
conversations: [], conversations: [],
...@@ -29,6 +30,7 @@ export const deleteTacticsConversations = createAsyncThunk< ...@@ -29,6 +30,7 @@ export const deleteTacticsConversations = createAsyncThunk<
'tactics/deleteTacticsConversations', 'tactics/deleteTacticsConversations',
async (conversationIds, { dispatch, rejectWithValue }) => { async (conversationIds, { dispatch, rejectWithValue }) => {
try { try {
await waitForToken()
await fetchDeleteTacticsConversation(conversationIds) await fetchDeleteTacticsConversation(conversationIds)
await dispatch(fetchTacticsConversations()) await dispatch(fetchTacticsConversations())
return true return true
...@@ -46,6 +48,7 @@ export const createTacticsConversation = createAsyncThunk< ...@@ -46,6 +48,7 @@ export const createTacticsConversation = createAsyncThunk<
>( >(
'tactics/createTacticsConversation', 'tactics/createTacticsConversation',
async ({ conversationData, shouldNavigate, shouldSendQuestion }, { dispatch }) => { async ({ conversationData, shouldNavigate, shouldSendQuestion }, { dispatch }) => {
await waitForToken()
const response = await fetchCreateTacticsConversation(conversationData) const response = await fetchCreateTacticsConversation(conversationData)
const newConversation = response.data 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