refactor(workspace): enforce layered crate boundaries

This commit is contained in:
elky
2026-07-15 23:47:19 +08:00
parent a728c090a9
commit 8616fe6ee2
969 changed files with 40187 additions and 27240 deletions
+84 -20
View File
@@ -7,6 +7,8 @@ import { parseApiError } from '@/utils/errorParser'
import { getErrorStatus } from '@/types/api-error'
export const useAuthStore = defineStore('auth', () => {
const CURRENT_USER_FAILURE_BACKOFF_MS = 15_000
// 初始化时从 localStorage 恢复 token
const storedToken = apiClient.getToken()
@@ -14,6 +16,21 @@ export const useAuthStore = defineStore('auth', () => {
const token = ref<string | null>(storedToken)
const loading = ref(false)
const error = ref<string | null>(null)
let fetchCurrentUserPromise: Promise<User | null> | null = null
let fetchCurrentUserToken: string | null = null
let lastCurrentUserFailureAt = 0
let lastCurrentUserFailureToken: string | null = null
let authStateVersion = 0
function resetCurrentUserFailure() {
lastCurrentUserFailureAt = 0
lastCurrentUserFailureToken = null
}
function markAuthStateChanged() {
authStateVersion += 1
resetCurrentUserFailure()
}
const isAuthenticated = computed(() => {
// 使用 store 中的 token 状态判断认证状态
@@ -29,6 +46,7 @@ export const useAuthStore = defineStore('auth', () => {
const currentToken = apiClient.getToken()
if (token.value !== currentToken) {
token.value = currentToken
markAuthStateChanged()
}
}
const isAdmin = computed(() => user.value?.role === 'admin')
@@ -43,10 +61,12 @@ export const useAuthStore = defineStore('auth', () => {
try {
const response = await authApi.login({ email, password, auth_type: authType })
token.value = response.access_token
markAuthStateChanged()
// 获取用户信息
const userInfo = await authApi.getCurrentUser()
user.value = userInfo
resetCurrentUserFailure()
return true
} catch (err: unknown) {
@@ -73,6 +93,7 @@ export const useAuthStore = defineStore('auth', () => {
async function logout() {
user.value = null
token.value = null
markAuthStateChanged()
await authApi.logout()
}
@@ -80,32 +101,75 @@ export const useAuthStore = defineStore('auth', () => {
user.value = null
token.value = null
error.value = null
markAuthStateChanged()
}
async function fetchCurrentUser() {
try {
const userInfo = await authApi.getCurrentUser()
user.value = userInfo
return userInfo
} catch (err: unknown) {
log.error('Failed to fetch user info', err)
syncToken()
if (!token.value) {
user.value = null
}
// 根据用户要求,不管什么错误都不清除状态
// 保持登录状态,除非用户手动退出
log.info('Keeping session despite error, as per user requirement')
return null
function fetchCurrentUser(): Promise<User | null> {
const requestToken = token.value || apiClient.getToken()
if (!requestToken) {
user.value = null
return Promise.resolve(null)
}
// 路由守卫、App 初始化和认证同步可能同时触发,复用同一个请求。
if (fetchCurrentUserPromise && fetchCurrentUserToken === requestToken) {
return fetchCurrentUserPromise
}
// 后端暂时不可用时,不要让每一次导航都重新等待全局请求超时。
if (
lastCurrentUserFailureToken === requestToken &&
Date.now() - lastCurrentUserFailureAt < CURRENT_USER_FAILURE_BACKOFF_MS
) {
return Promise.resolve(null)
}
fetchCurrentUserToken = requestToken
const requestAuthStateVersion = authStateVersion
const request = (async () => {
try {
const userInfo = await authApi.getCurrentUser()
if (requestAuthStateVersion !== authStateVersion || !token.value) {
return null
}
user.value = userInfo
resetCurrentUserFailure()
return userInfo
} catch (err: unknown) {
log.error('Failed to fetch user info', err)
if (requestAuthStateVersion !== authStateVersion) {
return null
}
syncToken()
if (requestAuthStateVersion !== authStateVersion) {
if (!token.value) user.value = null
return null
}
if (!token.value) {
user.value = null
} else {
lastCurrentUserFailureAt = Date.now()
lastCurrentUserFailureToken = token.value
}
// 保留登录状态;短暂退避后允许再次校验。
log.info('Keeping session despite error, as per user requirement')
return null
} finally {
if (fetchCurrentUserPromise === request) {
fetchCurrentUserPromise = null
fetchCurrentUserToken = null
}
}
})()
fetchCurrentUserPromise = request
return request
}
async function checkAuth() {
const storedToken = apiClient.getToken()
if (storedToken) {
token.value = storedToken
// 即使获取用户信息失败,也保留 token
// 只有 401 错误才表示 token 真正失效
syncToken()
if (token.value && !user.value) {
// 即使获取用户信息失败,也保留 token。
await fetchCurrentUser()
}
}