feat(auth): 添加OAuth登录状态持久化功能

实现OAuth登录状态的保存、加载和清除功能,包括:
- 添加三个新的API接口用于状态管理
- 创建useOAuthPersist hook处理状态持久化逻辑
- 在登录流程中自动保存状态
- 在应用启动时自动恢复登录状态
This commit is contained in:
Yukino_fox
2026-04-16 20:51:45 +08:00
parent c58ae5c731
commit 2ef088def5
5 changed files with 332 additions and 1 deletions
+24 -1
View File
@@ -131,7 +131,30 @@ export function OAuthLogin({ visible, onClose, onSuccess }: OAuthLoginProps) {
return
}
console.log("[OAuth] 登录成功,清理资源...")
console.log("[OAuth] 登录成功,保存登录状态...")
// 保存登录状态到本地
const loginState = {
access_token: tokenRes.data.access_token,
refresh_token: tokenRes.data.refresh_token,
token_type: tokenRes.data.token_type,
expires_in: tokenRes.data.expires_in,
user_id: userRes.data.user_id,
email: userRes.data.email,
name: userRes.data.name,
github_username: userRes.data.github_username,
permission: userRes.data.permission,
login_time: new Date().toISOString(),
}
try {
await api.oauthSaveLoginState(loginState)
console.log("[OAuth] 登录状态已保存")
} catch (saveError) {
console.error("[OAuth] 保存登录状态失败:", saveError)
}
console.log("[OAuth] 清理资源...")
await api.oauthStopCallbackServer()
clearExpectedState()
sessionStorage.removeItem("oauth_code_verifier")
+142
View File
@@ -0,0 +1,142 @@
/**
* OAuth 登录状态持久化 Hook
* 用于保存、恢复和清除 OAuth 登录状态
*/
import { useState, useEffect, useCallback } from "react"
export interface OAuthUserInfo {
user_id: string
email: string
name: string
github_username?: string
permission: number
}
export interface OAuthLoginState {
access_token: string
refresh_token: string
token_type: string
expires_in: number
user_id: string
email: string
name: string
github_username?: string
permission: number
login_time: string
}
export function useOAuthPersist() {
const [isAuthenticated, setIsAuthenticated] = useState(false)
const [isLoading, setIsLoading] = useState(true)
const [userInfo, setUserInfo] = useState<OAuthUserInfo | null>(null)
const [loginState, setLoginState] = useState<OAuthLoginState | null>(null)
// 初始化时尝试恢复登录状态
useEffect(() => {
const initAuth = async () => {
try {
const api = (window as any).api
if (!api) {
console.error("[OAuth Persist] API 不可用")
setIsLoading(false)
return
}
console.log("[OAuth Persist] 尝试恢复登录状态...")
const result = await api.oauthLoadLoginState()
if (result.success && result.data) {
console.log("[OAuth Persist] 找到保存的登录状态:", result.data.user_id)
setLoginState(result.data)
setUserInfo({
user_id: result.data.user_id,
email: result.data.email,
name: result.data.name,
github_username: result.data.github_username,
permission: result.data.permission,
})
setIsAuthenticated(true)
} else {
console.log("[OAuth Persist] 没有找到登录状态")
}
} catch (error) {
console.error("[OAuth Persist] 恢复登录状态失败:", error)
} finally {
setIsLoading(false)
}
}
initAuth()
}, [])
// 保存登录状态
const saveLoginState = useCallback(
async (
tokenData: {
access_token: string
refresh_token: string
token_type: string
expires_in: number
},
userData: OAuthUserInfo
) => {
try {
const api = (window as any).api
if (!api) {
console.error("[OAuth Persist] API 不可用")
return
}
const state: OAuthLoginState = {
...tokenData,
...userData,
login_time: new Date().toISOString(),
}
await api.oauthSaveLoginState(state)
setLoginState(state)
setUserInfo(userData)
setIsAuthenticated(true)
console.log("[OAuth Persist] 登录状态已保存")
} catch (error) {
console.error("[OAuth Persist] 保存登录状态失败:", error)
}
},
[]
)
// 清除登录状态
const clearLoginState = useCallback(async () => {
try {
const api = (window as any).api
if (!api) {
console.error("[OAuth Persist] API 不可用")
return
}
await api.oauthClearLoginState()
setLoginState(null)
setUserInfo(null)
setIsAuthenticated(false)
console.log("[OAuth Persist] 登录状态已清除")
} catch (error) {
console.error("[OAuth Persist] 清除登录状态失败:", error)
}
}, [])
// 登出
const logout = useCallback(async () => {
await clearLoginState()
}, [clearLoginState])
return {
isAuthenticated,
isLoading,
userInfo,
loginState,
saveLoginState,
clearLoginState,
logout,
}
}
+35
View File
@@ -565,6 +565,41 @@ const api = {
data: string
message?: string
}> => invoke("oauth_get_device_uuid"),
oauthSaveLoginState: (state: {
access_token: string
refresh_token: string
token_type: string
expires_in: number
user_id: string
email: string
name: string
github_username?: string
permission: number
login_time: string
}): Promise<{
success: boolean
message?: string
}> => invoke("oauth_save_login_state", { stateData: state }),
oauthLoadLoginState: (): Promise<{
success: boolean
data?: {
access_token: string
refresh_token: string
token_type: string
expires_in: number
user_id: string
email: string
name: string
github_username?: string
permission: number
login_time: string
} | null
message?: string
}> => invoke("oauth_load_login_state"),
oauthClearLoginState: (): Promise<{
success: boolean
message?: string
}> => invoke("oauth_clear_login_state"),
// Data import/export
exportDataJson: (): Promise<{ success: boolean; data: string }> => invoke("data_export_json"),