61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import { create } from 'zustand';
|
||
import { persist, createJSONStorage } from 'zustand/middleware';
|
||
import type { AdminInfo } from '@/lib/types';
|
||
|
||
const TOKEN_COOKIE = process.env.NEXT_PUBLIC_TOKEN_KEY ?? 'admin_token';
|
||
const TOKEN_LS_KEY = TOKEN_COOKIE; // 文档要求:JWT 仅前端 localStorage 存储
|
||
|
||
/** 把 token 同步到 Cookie,便于 Edge middleware 在 SSR 前拦截 */
|
||
function syncCookie(token: string | null): void {
|
||
if (typeof document === 'undefined') return;
|
||
if (token) {
|
||
const expires = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toUTCString();
|
||
document.cookie = `${TOKEN_COOKIE}=${encodeURIComponent(token)}; expires=${expires}; path=/; SameSite=Lax`;
|
||
} else {
|
||
document.cookie = `${TOKEN_COOKIE}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;`;
|
||
}
|
||
}
|
||
|
||
/** 同步到 localStorage,axios 拦截器从这里取 */
|
||
function syncLocalStorage(token: string | null): void {
|
||
if (typeof window === 'undefined') return;
|
||
if (token) {
|
||
window.localStorage.setItem(TOKEN_LS_KEY, token);
|
||
} else {
|
||
window.localStorage.removeItem(TOKEN_LS_KEY);
|
||
}
|
||
}
|
||
|
||
interface AdminState {
|
||
token: string | null;
|
||
admin: AdminInfo | null;
|
||
setLogin: (token: string, admin: AdminInfo) => void;
|
||
logout: () => void;
|
||
hasAuth: () => boolean;
|
||
}
|
||
|
||
export const useAdminStore = create<AdminState>()(
|
||
persist(
|
||
(set, get) => ({
|
||
token: null,
|
||
admin: null,
|
||
setLogin: (token, admin) => {
|
||
syncLocalStorage(token);
|
||
syncCookie(token);
|
||
set({ token, admin });
|
||
},
|
||
logout: () => {
|
||
syncLocalStorage(null);
|
||
syncCookie(null);
|
||
set({ token: null, admin: null });
|
||
},
|
||
hasAuth: () => Boolean(get().token),
|
||
}),
|
||
{
|
||
name: 'corp_admin_session',
|
||
storage: createJSONStorage(() => localStorage),
|
||
partialize: (s) => ({ token: s.token, admin: s.admin }),
|
||
},
|
||
),
|
||
);
|