chore(init): 初始化解忧商行项目并完成 Phase 0 基座
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import { create } from 'zustand'
|
||||
|
||||
import { unwrapData } from '@/shared/api/client'
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import type { ApiResponse, AuthUser, LoginData } from '@/shared/api/types'
|
||||
import {
|
||||
clearAuthSession,
|
||||
getAccessToken,
|
||||
getAuthUser,
|
||||
setAuthSession,
|
||||
setAuthUser,
|
||||
} from '@/shared/auth/storage'
|
||||
|
||||
interface SessionState {
|
||||
user: AuthUser | null
|
||||
token: string
|
||||
hydrated: boolean
|
||||
login: (phone: string, password: string) => Promise<void>
|
||||
logout: () => Promise<void>
|
||||
hydrate: () => void
|
||||
loadMe: () => Promise<void>
|
||||
}
|
||||
|
||||
export const useSessionStore = create<SessionState>((set, get) => ({
|
||||
user: null,
|
||||
token: '',
|
||||
hydrated: false,
|
||||
|
||||
hydrate() {
|
||||
set({
|
||||
user: getAuthUser(),
|
||||
token: getAccessToken(),
|
||||
hydrated: true,
|
||||
})
|
||||
},
|
||||
|
||||
async login(phone, password) {
|
||||
const data = await unwrapData<LoginData>(
|
||||
apiClient.post<ApiResponse<LoginData>>('/auth/password/login', { phone, password })
|
||||
)
|
||||
setAuthSession(data.tokens, data.user)
|
||||
set({ user: data.user, token: data.tokens.access_token, hydrated: true })
|
||||
},
|
||||
|
||||
async logout() {
|
||||
try {
|
||||
await apiClient.post('/auth/logout', undefined, {
|
||||
skipErrorHandler: true,
|
||||
skipAuthRefresh: true,
|
||||
} as never)
|
||||
} catch {
|
||||
// 本地退出优先,服务端 token 失效不影响清理。
|
||||
}
|
||||
clearAuthSession()
|
||||
set({ user: null, token: '', hydrated: true })
|
||||
},
|
||||
|
||||
async loadMe() {
|
||||
if (!get().token) return
|
||||
const user = await unwrapData<AuthUser>(apiClient.get<ApiResponse<AuthUser>>('/me'))
|
||||
setAuthUser(user)
|
||||
set({ user })
|
||||
},
|
||||
}))
|
||||
Reference in New Issue
Block a user