Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sdream-ai-fe
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
侯明涛
sdream-ai-fe
Commits
de73cb84
Commit
de73cb84
authored
Jan 07, 2026
by
Liu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: 优化工具函数、首页和路由处理逻辑
parent
1084a561
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
68 additions
and
14 deletions
+68
-14
src/lib/utils.ts
+17
-4
src/pages/Home/HomeNew.tsx
+45
-5
src/routes/RouteChangeHandler.tsx
+1
-2
src/utils/request.ts
+5
-3
No files found.
src/lib/utils.ts
View file @
de73cb84
...
@@ -74,6 +74,19 @@ export function safeLocalStorageSetItem(key: string, value: string): void {
...
@@ -74,6 +74,19 @@ export function safeLocalStorageSetItem(key: string, value: string): void {
}
}
}
}
/**
* 安全地清除 localStorage
* 在无痕模式或存储被禁用时静默失败
*/
export
function
safeLocalStorageClear
():
void
{
try
{
localStorage
.
clear
()
}
catch
{
// 在无痕模式或存储被禁用时,静默失败
}
}
const
USER_ROLES_STORAGE_KEY
=
'__USER_ROLES__'
const
USER_ROLES_STORAGE_KEY
=
'__USER_ROLES__'
/**
/**
...
@@ -294,9 +307,9 @@ export function getUserRolesForApi(): string[] {
...
@@ -294,9 +307,9 @@ export function getUserRolesForApi(): string[] {
export
async
function
waitForToken
(
maxWaitTime
=
3000
):
Promise
<
boolean
>
{
export
async
function
waitForToken
(
maxWaitTime
=
3000
):
Promise
<
boolean
>
{
const
startTime
=
Date
.
now
()
const
startTime
=
Date
.
now
()
let
initialToken
=
''
let
initialToken
=
''
// 先获取初始 token 值
// 先获取初始 token 值
(使用安全函数)
try
{
try
{
const
initialTokenStr
=
window
.
localStorage
.
g
etItem
(
'__TOKEN__'
)
||
'""'
const
initialTokenStr
=
safeLocalStorageG
etItem
(
'__TOKEN__'
)
||
'""'
initialToken
=
JSON
.
parse
(
initialTokenStr
)
||
''
initialToken
=
JSON
.
parse
(
initialTokenStr
)
||
''
}
}
catch
{
catch
{
...
@@ -306,7 +319,7 @@ export async function waitForToken(maxWaitTime = 3000): Promise<boolean> {
...
@@ -306,7 +319,7 @@ export async function waitForToken(maxWaitTime = 3000): Promise<boolean> {
// 如果初始没有 token,等待 token 出现(从无到有,说明登录完成)
// 如果初始没有 token,等待 token 出现(从无到有,说明登录完成)
if
(
!
initialToken
)
{
if
(
!
initialToken
)
{
while
(
Date
.
now
()
-
startTime
<
maxWaitTime
)
{
while
(
Date
.
now
()
-
startTime
<
maxWaitTime
)
{
const
tokenStr
=
window
.
localStorage
.
g
etItem
(
'__TOKEN__'
)
||
'""'
const
tokenStr
=
safeLocalStorageG
etItem
(
'__TOKEN__'
)
||
'""'
let
token
=
''
let
token
=
''
try
{
try
{
token
=
JSON
.
parse
(
tokenStr
)
||
''
token
=
JSON
.
parse
(
tokenStr
)
||
''
...
@@ -331,7 +344,7 @@ export async function waitForToken(maxWaitTime = 3000): Promise<boolean> {
...
@@ -331,7 +344,7 @@ export async function waitForToken(maxWaitTime = 3000): Promise<boolean> {
let
tokenChanged
=
false
let
tokenChanged
=
false
const
checkTokenChange
=
()
=>
{
const
checkTokenChange
=
()
=>
{
try
{
try
{
const
currentTokenStr
=
window
.
localStorage
.
g
etItem
(
'__TOKEN__'
)
||
'""'
const
currentTokenStr
=
safeLocalStorageG
etItem
(
'__TOKEN__'
)
||
'""'
const
currentToken
=
JSON
.
parse
(
currentTokenStr
)
||
''
const
currentToken
=
JSON
.
parse
(
currentTokenStr
)
||
''
if
(
currentToken
&&
currentToken
!==
initialToken
)
{
if
(
currentToken
&&
currentToken
!==
initialToken
)
{
tokenChanged
=
true
tokenChanged
=
true
...
...
src/pages/Home/HomeNew.tsx
View file @
de73cb84
...
@@ -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
,
safeSessionStorageSetItem
,
waitForToken
}
from
'@/lib/utils'
import
{
getUserRolesFromRoute
,
safeLocalStorageGetItem
,
safe
LocalStorageSetItem
,
safe
SessionStorageGetItem
,
safeSessionStorageRemoveItem
,
safeSessionStorageSetItem
,
waitForToken
}
from
'@/lib/utils'
// 从 localStorage 获取 token 的辅助函数
// 从 localStorage 获取 token 的辅助函数
function
getTokenFromStorage
():
string
|
null
{
function
getTokenFromStorage
():
string
|
null
{
...
@@ -281,12 +281,32 @@ export const Home: React.FC = () => {
...
@@ -281,12 +281,32 @@ export const Home: React.FC = () => {
// 使用 replace 避免产生新的历史记录
// 使用 replace 避免产生新的历史记录
window
.
history
.
replaceState
({},
''
,
currentUrl
.
toString
())
window
.
history
.
replaceState
({},
''
,
currentUrl
.
toString
())
}
}
setToken
(
res
.
data
.
token
)
// 尝试使用 useLocalStorageState 设置 token,如果失败则使用降级方案
try
{
setToken
(
res
.
data
.
token
)
}
catch
(
error
)
{
// localStorage 被阻止时,使用安全函数降级存储
console
.
warn
(
'setToken 失败,使用降级方案:'
,
error
)
safeLocalStorageSetItem
(
'__TOKEN__'
,
JSON
.
stringify
(
res
.
data
.
token
))
}
if
(
res
.
data
.
userName
)
{
if
(
res
.
data
.
userName
)
{
setUserName
(
res
.
data
.
userName
)
try
{
setUserName
(
res
.
data
.
userName
)
}
catch
{
// userName 存储失败时使用降级方案
safeLocalStorageSetItem
(
'__USER_NAME__'
,
JSON
.
stringify
(
res
.
data
.
userName
))
}
}
}
// 确保 token 已写入 localStorage(useLocalStorageState 是同步的,但为了保险起见,使用微任务确保写入完成)
// 确保 token 已写入 localStorage(useLocalStorageState 是同步的,但为了保险起见,使用微任务确保写入完成)
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
0
))
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
0
))
// 验证 token 是否真正写入,如果没有则使用降级方案
const
verifyToken
=
getTokenFromStorage
()
if
(
!
verifyToken
)
{
// 如果 useLocalStorageState 写入失败,使用安全函数再次尝试
safeLocalStorageSetItem
(
'__TOKEN__'
,
JSON
.
stringify
(
res
.
data
.
token
))
}
window
.
dispatchEvent
(
window
.
dispatchEvent
(
new
StorageEvent
(
'storage'
,
{
new
StorageEvent
(
'storage'
,
{
key
:
'__TOKEN__'
,
key
:
'__TOKEN__'
,
...
@@ -358,12 +378,32 @@ export const Home: React.FC = () => {
...
@@ -358,12 +378,32 @@ export const Home: React.FC = () => {
currentUrl
.
searchParams
.
delete
(
'toolId'
)
currentUrl
.
searchParams
.
delete
(
'toolId'
)
window
.
history
.
replaceState
({},
''
,
currentUrl
.
toString
())
window
.
history
.
replaceState
({},
''
,
currentUrl
.
toString
())
}
}
setToken
(
res
.
data
.
token
)
// 尝试使用 useLocalStorageState 设置 token,如果失败则使用降级方案
try
{
setToken
(
res
.
data
.
token
)
}
catch
(
error
)
{
// localStorage 被阻止时,使用安全函数降级存储
console
.
warn
(
'setToken 失败,使用降级方案:'
,
error
)
safeLocalStorageSetItem
(
'__TOKEN__'
,
JSON
.
stringify
(
res
.
data
.
token
))
}
if
(
res
.
data
.
userName
)
{
if
(
res
.
data
.
userName
)
{
setUserName
(
res
.
data
.
userName
)
try
{
setUserName
(
res
.
data
.
userName
)
}
catch
{
// userName 存储失败时使用降级方案
safeLocalStorageSetItem
(
'__USER_NAME__'
,
JSON
.
stringify
(
res
.
data
.
userName
))
}
}
}
// 确保 token 已写入 localStorage(useLocalStorageState 是同步的,但为了保险起见,使用微任务确保写入完成)
// 确保 token 已写入 localStorage(useLocalStorageState 是同步的,但为了保险起见,使用微任务确保写入完成)
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
0
))
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
0
))
// 验证 token 是否真正写入,如果没有则使用降级方案
const
verifyToken
=
getTokenFromStorage
()
if
(
!
verifyToken
)
{
// 如果 useLocalStorageState 写入失败,使用安全函数再次尝试
safeLocalStorageSetItem
(
'__TOKEN__'
,
JSON
.
stringify
(
res
.
data
.
token
))
}
// 主动触发 storage 事件,确保其他组件能监听到变化
// 主动触发 storage 事件,确保其他组件能监听到变化
window
.
dispatchEvent
(
window
.
dispatchEvent
(
new
StorageEvent
(
'storage'
,
{
new
StorageEvent
(
'storage'
,
{
...
...
src/routes/RouteChangeHandler.tsx
View file @
de73cb84
...
@@ -5,7 +5,6 @@ import { clearCurrentTacticsConversation, setCurrentTacticsConversation } from '
...
@@ -5,7 +5,6 @@ import { clearCurrentTacticsConversation, setCurrentTacticsConversation } from '
import
{
useAppDispatch
,
useAppSelector
}
from
'@/store/hook'
import
{
useAppDispatch
,
useAppSelector
}
from
'@/store/hook'
import
{
setIsAsking
}
from
'@/store/chatSlice'
import
{
setIsAsking
}
from
'@/store/chatSlice'
import
type
{
RootState
}
from
'@/store'
import
type
{
RootState
}
from
'@/store'
import
{
safeLocalStorageGetItem
}
from
'@/lib/utils'
export
function
withRouteChangeHandler
(
WrappedComponent
:
React
.
ComponentType
)
{
export
function
withRouteChangeHandler
(
WrappedComponent
:
React
.
ComponentType
)
{
let
beforeLocationPathName
=
''
let
beforeLocationPathName
=
''
...
@@ -38,7 +37,7 @@ export function withRouteChangeHandler(WrappedComponent: React.ComponentType) {
...
@@ -38,7 +37,7 @@ export function withRouteChangeHandler(WrappedComponent: React.ComponentType) {
if
(
location
.
pathname
===
'/'
)
{
if
(
location
.
pathname
===
'/'
)
{
// 如果 localStorage 中有 conversationId,不清除,让恢复逻辑处理
// 如果 localStorage 中有 conversationId,不清除,让恢复逻辑处理
// 这样可以保留上一次的历史记录
// 这样可以保留上一次的历史记录
const
savedConversationId
=
safeLocalStorageG
etItem
(
'currentConversationId'
)
const
savedConversationId
=
window
.
localStorage
.
g
etItem
(
'currentConversationId'
)
if
(
!
savedConversationId
)
{
if
(
!
savedConversationId
)
{
dispatch
(
clearCurrentConversation
())
dispatch
(
clearCurrentConversation
())
}
}
...
...
src/utils/request.ts
View file @
de73cb84
...
@@ -7,6 +7,7 @@ import type {
...
@@ -7,6 +7,7 @@ import type {
}
from
'axios'
}
from
'axios'
import
type
{
EnvConfKey
}
from
'@/config/env'
import
type
{
EnvConfKey
}
from
'@/config/env'
import
{
envConf
}
from
'@/config/env'
import
{
envConf
}
from
'@/config/env'
import
{
safeLocalStorageClear
,
safeLocalStorageGetItem
}
from
'@/lib/utils'
export
interface
Response
<
T
>
{
export
interface
Response
<
T
>
{
data
:
T
data
:
T
...
@@ -31,7 +32,8 @@ service.interceptors.request.use(
...
@@ -31,7 +32,8 @@ service.interceptors.request.use(
(
config
:
any
)
=>
{
(
config
:
any
)
=>
{
let
token
=
''
let
token
=
''
try
{
try
{
const
tokenStr
=
window
.
localStorage
.
getItem
(
'__TOKEN__'
)
// 使用安全函数获取 token,避免在第三方页面中访问 localStorage 被阻止
const
tokenStr
=
safeLocalStorageGetItem
(
'__TOKEN__'
)
if
(
tokenStr
)
{
if
(
tokenStr
)
{
// useLocalStorageState 会将值序列化为 JSON,需要解析
// useLocalStorageState 会将值序列化为 JSON,需要解析
token
=
JSON
.
parse
(
tokenStr
)
||
''
token
=
JSON
.
parse
(
tokenStr
)
||
''
...
@@ -70,8 +72,8 @@ service.interceptors.response.use(
...
@@ -70,8 +72,8 @@ service.interceptors.response.use(
return
response
.
data
return
response
.
data
}
}
else
if
(
code
===
'00000005'
)
{
else
if
(
code
===
'00000005'
)
{
// 处理登录失效
// 处理登录失效
(使用安全函数,避免在第三方页面中被阻止)
window
.
localStorage
.
c
lear
()
safeLocalStorageC
lear
()
}
}
else
{
else
{
return
Promise
.
reject
(
new
Error
(
message
))
return
Promise
.
reject
(
new
Error
(
message
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment