fix(data): 清理旧数据并保护服务端写入

This commit is contained in:
Script Generator
2026-07-02 09:30:50 +08:00
parent 28e0c6de19
commit 916bd17a48
38 changed files with 1346 additions and 194 deletions

View File

@@ -3,14 +3,15 @@
import { create } from 'zustand';
import { loadServerData } from '@/lib/server-data';
import type { Member } from '@/lib/members';
import { ensureMemberUsernames } from '@/lib/members';
import { SYSTEM_ADMIN_MEMBER, ensureSystemAdminMember } from '@/lib/member-system';
import { resolveAuthUserFromMembers, toAuthUser, type AuthUser } from '@/lib/auth-user';
import { findMemberByUsernameCredentials, resolveAuthUserFromMembers, toAuthUser, type AuthUser } from '@/lib/auth-user';
import { useMemberStore } from './useMemberStore';
interface AuthState {
user: AuthUser | null;
isAuthenticated: boolean;
login: (phone: string, password: string, remember: boolean) => Promise<boolean>;
login: (username: string, password: string, remember: boolean) => Promise<boolean>;
logout: () => void;
checkAuth: () => void;
refreshUser: () => Promise<void>;
@@ -40,11 +41,15 @@ function clearAuthStorage() {
async function loadMembersForAuth(): Promise<Member[]> {
try {
const stored = await loadServerData<StoredMembersData>('members');
if (stored?.members?.length) return ensureSystemAdminMember(stored.members).members;
if (stored?.members?.length) {
const ensured = ensureSystemAdminMember(stored.members);
return ensureMemberUsernames(ensured.members).members;
}
} catch {}
const inMemoryMembers = useMemberStore.getState().members;
return inMemoryMembers.length > 0 ? ensureSystemAdminMember(inMemoryMembers).members : FALLBACK_MEMBERS;
const members = inMemoryMembers.length > 0 ? ensureSystemAdminMember(inMemoryMembers).members : FALLBACK_MEMBERS;
return ensureMemberUsernames(members).members;
}
async function refreshStoredAuthUser(user: AuthUser, remember: boolean, set: (state: Partial<AuthState>) => void) {
@@ -65,9 +70,9 @@ export const useAuthStore = create<AuthState>((set) => ({
user: null,
isAuthenticated: false,
login: async (phone, password, remember) => {
login: async (username, password, remember) => {
const members = await loadMembersForAuth();
const member = members.find((m) => m.phone === phone && (m.password || 'Ftb@2024') === password);
const member = findMemberByUsernameCredentials(username, password, members);
if (!member) return false;
const user = toAuthUser(member);

View File

@@ -1,7 +1,7 @@
'use client';
import { create } from 'zustand';
import type { Department, Member, RoleItem, PasswordRule } from '@/lib/members';
import { DEFAULT_PASSWORD_RULE, generatePassword } from '@/lib/members';
import { DEFAULT_PASSWORD_RULE, ensureMemberUsernames, generatePassword, generateUsernameFromName } from '@/lib/members';
import {
SYSTEM_ADMIN_MEMBER,
SYSTEM_ADMIN_ROLE_ID,
@@ -87,14 +87,15 @@ export const useMemberStore = create<MemberState>((set, get) => ({
roles.length !== rolesWithNewDefaults.length ||
roles.some((role, index) => JSON.stringify(role) !== JSON.stringify(rolesWithNewDefaults[index]));
const ensured = ensureSystemAdminMember(cached.members);
const usernameEnsured = ensureMemberUsernames(ensured.members);
const next = {
departments: cached.departments,
members: ensured.members,
members: usernameEnsured.members,
roles,
passwordRule: cached.passwordRule || DEFAULT_PASSWORD_RULE,
};
set(next);
if (ensured.changed || rolesChanged) saveStored(next);
if (ensured.changed || usernameEnsured.changed || rolesChanged) saveStored(next);
}
},
@@ -121,7 +122,13 @@ export const useMemberStore = create<MemberState>((set, get) => ({
},
createMember: (data) => {
const member: Member = { ...data, id: `m-${Date.now()}`, createdAt: new Date().toISOString().slice(0, 10) };
const member: Member = {
...data,
username: data.username || generateUsernameFromName(data.name, get().members.map((m) => m.username ?? '')),
phone: data.phone ?? '',
id: `m-${Date.now()}`,
createdAt: new Date().toISOString().slice(0, 10),
};
const members = [...get().members, member];
set({ members });
saveStored({ departments: get().departments, members, roles: get().roles, passwordRule: get().passwordRule });