124 lines
3.3 KiB
TypeScript
124 lines
3.3 KiB
TypeScript
'use client';
|
|
|
|
import { create } from 'zustand';
|
|
import { loadServerData } from '@/lib/server-data';
|
|
import type { Member } from '@/lib/members';
|
|
import { useMemberStore } from './useMemberStore';
|
|
|
|
interface AuthUser {
|
|
id: string;
|
|
name: string;
|
|
roleId: string;
|
|
departmentId: string;
|
|
phone: string;
|
|
email: string;
|
|
}
|
|
|
|
interface AuthState {
|
|
user: AuthUser | null;
|
|
isAuthenticated: boolean;
|
|
login: (phone: string, password: string, remember: boolean) => Promise<boolean>;
|
|
logout: () => void;
|
|
checkAuth: () => void;
|
|
refreshUser: () => Promise<void>;
|
|
}
|
|
|
|
interface StoredMembersData {
|
|
members: Member[];
|
|
}
|
|
|
|
const SESSION_KEY = 'ftb_auth_session';
|
|
const PERSIST_KEY = 'ftb_auth_persist';
|
|
|
|
const FALLBACK_MEMBERS: Member[] = [
|
|
{
|
|
id: 'm-8',
|
|
name: '\u8d85\u7ea7\u7ba1\u7406\u5458',
|
|
departmentId: 'dept-1',
|
|
roleId: 'role-admin',
|
|
phone: '13200132008',
|
|
email: 'chenshi@company.com',
|
|
password: 'Ftb@2024',
|
|
createdAt: '2024-01-01',
|
|
},
|
|
];
|
|
|
|
async function loadMembersForAuth(): Promise<Member[]> {
|
|
try {
|
|
const stored = await loadServerData<StoredMembersData>('members');
|
|
if (stored?.members?.length) return stored.members;
|
|
} catch {}
|
|
|
|
const inMemoryMembers = useMemberStore.getState().members;
|
|
return inMemoryMembers.length > 0 ? inMemoryMembers : FALLBACK_MEMBERS;
|
|
}
|
|
|
|
function toAuthUser(member: Member): AuthUser {
|
|
return {
|
|
id: member.id,
|
|
name: member.name,
|
|
roleId: member.roleId,
|
|
departmentId: member.departmentId,
|
|
phone: member.phone,
|
|
email: member.email,
|
|
};
|
|
}
|
|
|
|
export const useAuthStore = create<AuthState>((set) => ({
|
|
user: null,
|
|
isAuthenticated: false,
|
|
|
|
login: async (phone, password, remember) => {
|
|
const members = await loadMembersForAuth();
|
|
const member = members.find((m) => m.phone === phone && (m.password || 'Ftb@2024') === password);
|
|
if (!member) return false;
|
|
|
|
const user = toAuthUser(member);
|
|
set({ user, isAuthenticated: true });
|
|
sessionStorage.setItem(SESSION_KEY, JSON.stringify(user));
|
|
if (remember) {
|
|
localStorage.setItem(PERSIST_KEY, JSON.stringify(user));
|
|
}
|
|
return true;
|
|
},
|
|
|
|
logout: () => {
|
|
set({ user: null, isAuthenticated: false });
|
|
sessionStorage.removeItem(SESSION_KEY);
|
|
localStorage.removeItem(PERSIST_KEY);
|
|
},
|
|
|
|
checkAuth: () => {
|
|
const session = sessionStorage.getItem(SESSION_KEY);
|
|
if (session) {
|
|
set({ user: JSON.parse(session), isAuthenticated: true });
|
|
return;
|
|
}
|
|
const persist = localStorage.getItem(PERSIST_KEY);
|
|
if (persist) {
|
|
const user = JSON.parse(persist);
|
|
set({ user, isAuthenticated: true });
|
|
sessionStorage.setItem(SESSION_KEY, JSON.stringify(user));
|
|
return;
|
|
}
|
|
},
|
|
|
|
refreshUser: async () => {
|
|
const cur = useAuthStore.getState().user;
|
|
if (!cur) return;
|
|
try {
|
|
const memoryMember = useMemberStore.getState().members.find((x) => x.id === cur.id);
|
|
const members = memoryMember ? [memoryMember] : await loadMembersForAuth();
|
|
const member = members.find((x) => x.id === cur.id);
|
|
if (!member) return;
|
|
|
|
const next = toAuthUser(member);
|
|
useAuthStore.setState({ user: next });
|
|
sessionStorage.setItem(SESSION_KEY, JSON.stringify(next));
|
|
if (localStorage.getItem(PERSIST_KEY)) {
|
|
localStorage.setItem(PERSIST_KEY, JSON.stringify(next));
|
|
}
|
|
} catch {}
|
|
},
|
|
}));
|