Commit 2514136e by Liu

fix:sso

parent 0526f0f1
...@@ -42,6 +42,9 @@ function getAnimationProps(delay: number) { ...@@ -42,6 +42,9 @@ function getAnimationProps(delay: number) {
} }
} }
// 使用 sessionStorage 作为标志,防止跨组件重复执行 SSO 登录
const SSO_LOGIN_FLAG = 'sso_login_fetched'
export const Home: React.FC = () => { export const Home: React.FC = () => {
const viteOutputObj = import.meta.env.VITE_OUTPUT_OBJ || 'open' const viteOutputObj = import.meta.env.VITE_OUTPUT_OBJ || 'open'
const [isLoading, _setIsLoading] = useState(false) const [isLoading, _setIsLoading] = useState(false)
...@@ -241,26 +244,31 @@ export const Home: React.FC = () => { ...@@ -241,26 +244,31 @@ export const Home: React.FC = () => {
}, [_handleToolClick, isToolBtnActive, shouldChangeStyle, dispatch]) }, [_handleToolClick, isToolBtnActive, shouldChangeStyle, dispatch])
const login = useCallback(async () => { const login = useCallback(async () => {
// 防止重复调用 // 防止重复调用(使用 sessionStorage,跨组件共享)
if (sessionStorage.getItem(SSO_LOGIN_FLAG) === 'true') {
return
}
// 防止重复调用(组件级别保护)
if (hasFetched.current) { if (hasFetched.current) {
return return
} }
hasFetched.current = true
const url = new URL(window.location.href) const url = new URL(window.location.href)
// 获取查询参数 // 获取查询参数
const searchParams = new URLSearchParams(url.search) const searchParams = new URLSearchParams(url.search)
const from = searchParams.get('from')
const _loginCode = searchParams.get('loginCode') const _loginCode = searchParams.get('loginCode')
let res = {} as any
if (viteOutputObj === 'inner') { // 如果有 loginCode,执行 SSO 登录(包括 from=tactics 的情况)
if (_loginCode) { if (_loginCode && viteOutputObj === 'inner') {
// 立即设置标志,防止重复执行
sessionStorage.setItem(SSO_LOGIN_FLAG, 'true')
hasFetched.current = true
// 每次进入页面调用 sso_login 时,先清空 sessionStorage 中的 currentToolId // 每次进入页面调用 sso_login 时,先清空 sessionStorage 中的 currentToolId
// 避免关闭标签页后再次打开时使用上次的历史 toolId // 避免关闭标签页后再次打开时使用上次的历史 toolId
safeSessionStorageRemoveItem('currentToolId') safeSessionStorageRemoveItem('currentToolId')
res = await fetchLoginByToken(_loginCode) try {
const res = await fetchLoginByToken(_loginCode)
if (res.data) { if (res.data) {
// 登录成功后先打印完整的原始链接(删除之前)
// eslint-disable-next-line no-console
console.log('20251211登录成功,删除前完整链接:', window.location.href)
// 登录成功后先清理旧状态,避免沿用上一次的工具模式 // 登录成功后先清理旧状态,避免沿用上一次的工具模式
dispatch(clearCurrentToolId()) dispatch(clearCurrentToolId())
safeSessionStorageRemoveItem('currentToolId') safeSessionStorageRemoveItem('currentToolId')
...@@ -270,9 +278,6 @@ export const Home: React.FC = () => { ...@@ -270,9 +278,6 @@ export const Home: React.FC = () => {
// 使用 replace 避免产生新的历史记录 // 使用 replace 避免产生新的历史记录
window.history.replaceState({}, '', currentUrl.toString()) window.history.replaceState({}, '', currentUrl.toString())
} }
// 删除后打印链接
// eslint-disable-next-line no-console
console.log('20251211登录成功,删除后完整链接:', window.location.href)
setToken(res.data.token) setToken(res.data.token)
// 主动触发 storage 事件,确保其他组件能监听到变化 // 主动触发 storage 事件,确保其他组件能监听到变化
window.dispatchEvent( window.dispatchEvent(
...@@ -284,6 +289,8 @@ export const Home: React.FC = () => { ...@@ -284,6 +289,8 @@ export const Home: React.FC = () => {
storageArea: localStorage, storageArea: localStorage,
}), }),
) )
// 如果是 from=tactics,只执行登录,不执行其他业务逻辑(由 TacticsHome 处理)
if (from !== 'tactics') {
// 触发自定义事件,通知 ChatEditor 强制重置为制度活化 // 触发自定义事件,通知 ChatEditor 强制重置为制度活化
window.dispatchEvent(new CustomEvent('forceResetToGeneralMode')) window.dispatchEvent(new CustomEvent('forceResetToGeneralMode'))
getSessionConversationId() getSessionConversationId()
...@@ -292,14 +299,26 @@ export const Home: React.FC = () => { ...@@ -292,14 +299,26 @@ export const Home: React.FC = () => {
_handleToolClick(false, '', true) _handleToolClick(false, '', true)
} }
} }
else { }
catch (error) {
console.error('SSO 登录失败:', error)
// 登录失败时清除标志,允许重试
sessionStorage.removeItem(SSO_LOGIN_FLAG)
hasFetched.current = false
}
return
}
// 如果没有 loginCode,执行其他逻辑(非 from=tactics 的情况)
if (from !== 'tactics') {
hasFetched.current = true
if (viteOutputObj === 'inner') {
getSessionConversationId() getSessionConversationId()
dispatch(fetchConversations()) dispatch(fetchConversations())
} }
}
else { else {
// 模拟登录 可以用来测试 // 模拟登录 可以用来测试
res = await fetchLoginByUid('123123') const res = await fetchLoginByUid('123123')
if (res.data) { if (res.data) {
// 登录成功后先清理旧状态,避免沿用上一次的工具模式 // 登录成功后先清理旧状态,避免沿用上一次的工具模式
dispatch(clearCurrentToolId()) dispatch(clearCurrentToolId())
...@@ -328,6 +347,7 @@ export const Home: React.FC = () => { ...@@ -328,6 +347,7 @@ export const Home: React.FC = () => {
_handleToolClick(false, '', true) _handleToolClick(false, '', true)
} }
} }
}
}, [setToken, dispatch]) }, [setToken, dispatch])
// 监听路由参数变化,提取 userRoles(确保路由参数被正确解析) // 监听路由参数变化,提取 userRoles(确保路由参数被正确解析)
...@@ -337,6 +357,8 @@ export const Home: React.FC = () => { ...@@ -337,6 +357,8 @@ export const Home: React.FC = () => {
useEffect(() => { useEffect(() => {
login() login()
// eslint-disable-next-line no-console
console.log('login useEffect11111', token)
}, []) // 依赖数组为空,只在组件挂载时执行一次 }, []) // 依赖数组为空,只在组件挂载时执行一次
useEffect(() => { useEffect(() => {
......
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