feat: 新增首页和图片资源

This commit is contained in:
JiaJun
2026-04-24 18:02:42 +08:00
parent bd92f10b83
commit 9127a06d4a
179 changed files with 3424 additions and 101 deletions

View File

@@ -0,0 +1,143 @@
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'
import { AUTH_STORAGE_KEY } from '@/constants'
export type AuthStatus = 'anonymous' | 'authenticated' | 'restoring'
export interface AuthUser {
email?: string
id: string
name?: string
roles?: string[]
}
export interface AuthSessionInput {
accessToken: string
currentUser?: AuthUser | null
refreshToken?: string | null
}
interface PersistedAuthState {
accessToken: string | null
currentUser: AuthUser | null
refreshToken: string | null
}
interface AuthState extends PersistedAuthState {
clearAccessToken: () => void
clearSession: () => void
finishHydration: () => void
isHydrated: boolean
lastUnauthorizedAt: string | null
markUnauthorized: () => void
setAccessToken: (token: string) => void
setCurrentUser: (user: AuthUser | null) => void
startSession: (session: AuthSessionInput) => void
status: AuthStatus
updateTokens: (tokens: {
accessToken: string
refreshToken?: string | null
}) => void
}
function resolveAuthStatus(accessToken: string | null): AuthStatus {
return accessToken ? 'authenticated' : 'anonymous'
}
const initialPersistedState: PersistedAuthState = {
accessToken: null,
refreshToken: null,
currentUser: null,
}
export const useAuthStore = create<AuthState>()(
persist(
(set) => ({
...initialPersistedState,
status: 'restoring',
isHydrated: false,
lastUnauthorizedAt: null,
setAccessToken: (token) => {
set({
accessToken: token,
status: 'authenticated',
isHydrated: true,
})
},
setCurrentUser: (currentUser) => {
set((state) => ({
currentUser,
status: resolveAuthStatus(state.accessToken),
}))
},
startSession: ({
accessToken,
currentUser = null,
refreshToken = null,
}) => {
set({
accessToken,
currentUser,
refreshToken,
status: 'authenticated',
isHydrated: true,
})
},
updateTokens: ({ accessToken, refreshToken }) => {
set((state) => ({
accessToken,
refreshToken: refreshToken ?? state.refreshToken,
status: 'authenticated',
isHydrated: true,
}))
},
finishHydration: () => {
set((state) => ({
isHydrated: true,
status: resolveAuthStatus(state.accessToken),
}))
},
clearAccessToken: () => {
set({
accessToken: null,
status: 'anonymous',
isHydrated: true,
})
},
clearSession: () => {
set({
...initialPersistedState,
status: 'anonymous',
isHydrated: true,
})
},
markUnauthorized: () => {
set({
...initialPersistedState,
status: 'anonymous',
isHydrated: true,
lastUnauthorizedAt: new Date().toISOString(),
})
},
}),
{
name: AUTH_STORAGE_KEY,
storage: createJSONStorage(() => sessionStorage),
partialize: (state) => ({
accessToken: state.accessToken,
currentUser: state.currentUser,
refreshToken: state.refreshToken,
}),
onRehydrateStorage: () => (state, error) => {
if (error) {
state?.clearSession()
return
}
state?.finishHydration()
},
},
),
)