生产管理系统 - 将用户基础数据同步到zustand

This commit is contained in:
2025-11-04 20:32:28 +08:00
parent e92be97393
commit c386350df5
4 changed files with 102 additions and 149 deletions

View File

@@ -8,7 +8,7 @@
'use client';
import { Card } from '@/components/ui/card';
import { Building2, Users, Layers } from 'lucide-react';
import { Building2, Layers, GitBranch } from 'lucide-react';
import { DepartmentStats } from '../types';
interface DepartmentStatsCardsProps {
@@ -31,7 +31,7 @@ export function DepartmentStatsCards({
{
label: '二级部门',
value: stats.level2,
icon: <Users className="w-5 h-5" />,
icon: <GitBranch className="w-5 h-5" />,
color: 'text-green-600 dark:text-green-400',
bg: 'bg-green-50 dark:bg-green-950',
},

View File

@@ -171,21 +171,33 @@ export default function DepartmentManagementPage() {
}
};
// 统计部门数量
// 统计部门数量(递归计算所有层级)
const countDepartments = (depts: Department[]): { level1: number; level2: number; total: number } => {
let level1 = 0;
let level2 = 0;
let total = 0;
depts.forEach(dept => {
if (!dept.parentId) {
level1++;
if (dept.children) {
level2 += dept.children.length;
const countRecursive = (departments: Department[]) => {
departments.forEach(dept => {
total++; // 每个部门都计入总数
// 根据level字段统计各级部门
if (dept.level === 1) {
level1++; // 统计一级部门
} else if (dept.level === 2) {
level2++; // 统计二级部门
}
// 递归计算子部门
if (dept.children && dept.children.length > 0) {
countRecursive(dept.children);
}
});
};
return { level1, level2, total: level1 + level2 };
countRecursive(depts);
return { level1, level2, total };
};
const stats = countDepartments(state.departments);

View File

@@ -2,6 +2,7 @@
import React, { createContext, useContext, useState, ReactNode, useRef } from 'react';
import { getCurrentUserInfoApiV1AuthMeGet, refreshTokenApiV1AuthRefreshPost } from '@/lib/api/sdk.gen';
import { setAuthUser, getAuthUser, AuthUser } from '@/stores/modules/auth';
// Cookie 操作工具
const setTokenCookie = (token: string) => {
@@ -216,7 +217,11 @@ export function AuthProvider({ children }: AuthProviderProps) {
...response.data, // 合并最新的用户信息
};
setUser(updatedUserData);
// 存储到 Zustand store
setAuthUser(response.data);
console.log('✅ 用户验证成功,最新用户信息:', response.data);
console.log('📦 从 Zustand store 取出的用户数据:', getAuthUser());
// 验证成功后,启动 token 自动刷新定时器
startTokenRefresh();

View File

@@ -1,150 +1,86 @@
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import { User, LoginRequest, PhoneLoginRequest, LoginResponse } from '@api/modules/auth'
import { authApi } from '@api'
import { create } from 'zustand';
import { getCurrentUserInfoApiV1AuthMeGet } from '@/lib/api/sdk.gen';
interface AuthState {
user: User | null
token: string | null
refreshToken: string | null
isAuthenticated: boolean
isLoading: boolean
error: string | null
// Auth user interface definition
export interface AuthUser {
email: string;
username: string;
full_name: string | null;
phone: string;
id: string;
tenant_id: string;
is_active: boolean;
is_superuser: boolean;
is_verified: boolean;
created_at: string;
updated_at: string;
last_login_at: string;
avatar_url: string | null;
bio: string | null;
display_name: string;
department_id: string | null;
department_name: string | null;
}
interface AuthActions {
login: (credentials: LoginRequest) => Promise<void>
loginByPhone: (credentials: PhoneLoginRequest) => Promise<void>
logout: () => void
refreshToken: () => Promise<void>
getUserInfo: () => Promise<void>
updateUserInfo: (data: Partial<User>) => Promise<void>
clearError: () => void
setLoading: (loading: boolean) => void
// Auth state interface
export interface AuthState {
user: AuthUser | null;
setAuthUser: (user: AuthUser | null) => void;
getAuthUser: () => AuthUser | null;
}
export const useAuthStore = create<AuthState & AuthActions>()(
persist(
(set, get) => ({
// State
// Create auth store
export const useAuthStore = create<AuthState>((set, get) => ({
user: null,
token: null,
refreshToken: null,
isAuthenticated: false,
isLoading: false,
error: null,
// Actions
login: async (credentials) => {
setAuthUser: (user: AuthUser | null) => {
set({ user });
},
getAuthUser: () => {
return get().user;
},
}));
// Export functions for direct usage
export const setAuthUser = (user: AuthUser | null) => {
useAuthStore.getState().setAuthUser(user);
};
export const getAuthUser = (): AuthUser | null => {
return useAuthStore.getState().getAuthUser();
};
// Validate and update user info from API
export const validateAndUpdateUser = async (token: string): Promise<boolean> => {
try {
set({ isLoading: true, error: null })
const response = await authApi.login(credentials)
const { token, refreshToken, user } = response.data
// 使用 SDK 调用 /api/v1/auth/me 验证用户信息
const response = await getCurrentUserInfoApiV1AuthMeGet({
headers: {
'Authorization': `Bearer ${token}`,
},
});
localStorage.setItem('token', token)
localStorage.setItem('refreshToken', refreshToken)
if (response.data) {
// 更新用户信息(可能包含最新的权限、角色等)
const currentUser = getAuthUser();
if (currentUser) {
const updatedUserData = {
...currentUser,
...response.data, // 合并最新的用户信息
};
setAuthUser(updatedUserData);
set({
user,
token,
refreshToken,
isAuthenticated: true,
isLoading: false
})
// 打印存储后的用户数据,用于调试
console.log('从Zustand取出的用户数据:', getAuthUser());
}
return true;
}
return false;
} catch (error) {
set({
error: error instanceof Error ? error.message : '登录失败',
isLoading: false
})
console.error('Failed to validate user info:', error);
return false;
}
},
};
loginByPhone: async (credentials) => {
try {
set({ isLoading: true, error: null })
const response = await authApi.loginByPhone(credentials)
const { token, refreshToken, user } = response.data
localStorage.setItem('token', token)
localStorage.setItem('refreshToken', refreshToken)
set({
user,
token,
refreshToken,
isAuthenticated: true,
isLoading: false
})
} catch (error) {
set({
error: error instanceof Error ? error.message : '登录失败',
isLoading: false
})
}
},
logout: () => {
localStorage.removeItem('token')
localStorage.removeItem('refreshToken')
set({
user: null,
token: null,
refreshToken: null,
isAuthenticated: false,
error: null
})
},
refreshToken: async () => {
try {
const { refreshToken } = get()
if (!refreshToken) {
get().logout()
return
}
const response = await authApi.refreshToken(refreshToken)
const { token } = response.data
localStorage.setItem('token', token)
set({ token })
} catch (error) {
get().logout()
}
},
getUserInfo: async () => {
try {
const response = await authApi.getUserInfo()
set({ user: response.data })
} catch (error) {
console.error('获取用户信息失败:', error)
}
},
updateUserInfo: async (data) => {
try {
const response = await authApi.updateUserInfo(data)
set({ user: response.data })
} catch (error) {
set({
error: error instanceof Error ? error.message : '更新用户信息失败'
})
}
},
clearError: () => set({ error: null }),
setLoading: (loading) => set({ isLoading: loading })
}),
{
name: 'auth-storage',
partialize: (state) => ({
user: state.user,
token: state.token,
refreshToken: state.refreshToken,
isAuthenticated: state.isAuthenticated
})
}
)
)
export default useAuthStore;