生产管理系统前端 - 瓦力提交代码&文档更新
This commit is contained in:
@@ -1,15 +1,5 @@
|
||||
import { createContext, useContext, useState, useEffect, ReactNode } from 'react';
|
||||
import { User, AuthState } from '../../types/auth';
|
||||
import {
|
||||
getToken,
|
||||
getUser,
|
||||
saveToken,
|
||||
saveUser,
|
||||
clearAuth,
|
||||
isTokenExpired,
|
||||
refreshAuthToken,
|
||||
generateToken,
|
||||
} from '../../lib/authStorage';
|
||||
|
||||
interface AuthContextType {
|
||||
authState: AuthState;
|
||||
@@ -28,18 +18,38 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
token: null,
|
||||
refreshToken: null,
|
||||
});
|
||||
|
||||
const [isInitialized, setIsInitialized] = useState(false);
|
||||
|
||||
// 初始化时检查登录状态
|
||||
useEffect(() => {
|
||||
const initAuth = async () => {
|
||||
const token = getToken();
|
||||
const user = getUser();
|
||||
// 确保在浏览器环境中执行
|
||||
if (typeof window === 'undefined') {
|
||||
setIsInitialized(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// 延迟执行以避免构造函数错误
|
||||
const timer = setTimeout(() => {
|
||||
initAuth();
|
||||
}, 0);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const initAuth = async () => {
|
||||
try {
|
||||
// 动态导入以避免模块初始化时的错误
|
||||
const authStorage = await import('../../lib/authStorage');
|
||||
|
||||
const token = authStorage.getToken();
|
||||
const user = authStorage.getUser();
|
||||
|
||||
if (token && user) {
|
||||
// 检查token是否过期
|
||||
if (isTokenExpired()) {
|
||||
if (authStorage.isTokenExpired()) {
|
||||
// 尝试刷新token
|
||||
const refreshed = await refreshAuthToken();
|
||||
const refreshed = await authStorage.refreshAuthToken();
|
||||
if (refreshed) {
|
||||
setAuthState({
|
||||
isAuthenticated: true,
|
||||
@@ -56,29 +66,42 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
isAuthenticated: true,
|
||||
user,
|
||||
token,
|
||||
refreshToken: getToken(),
|
||||
refreshToken: authStorage.getRefreshToken() || token,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 没有登录信息,自动使用默认账号登录
|
||||
await autoLoginWithDefaultAccount();
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Auth initialization error:', error);
|
||||
// 初始化失败时设置为未登录状态
|
||||
setAuthState({
|
||||
isAuthenticated: false,
|
||||
user: null,
|
||||
token: null,
|
||||
refreshToken: null,
|
||||
});
|
||||
} finally {
|
||||
setIsInitialized(true);
|
||||
}
|
||||
};
|
||||
|
||||
// 自动登录默认账号
|
||||
const autoLoginWithDefaultAccount = async () => {
|
||||
// 动态导入避免循环依赖
|
||||
const { validatePasswordLogin } = await import('../../lib/authStorage');
|
||||
// 自动登录默认账号
|
||||
const autoLoginWithDefaultAccount = async () => {
|
||||
try {
|
||||
// 动态导入避免循环依赖和模块初始化错误
|
||||
const authStorage = await import('../../lib/authStorage');
|
||||
|
||||
// 使用默认管理员账号自动登录
|
||||
const result = await validatePasswordLogin('admin', 'admin123', 'AUTO');
|
||||
const result = await authStorage.validatePasswordLogin('admin', 'admin123', 'AUTO');
|
||||
|
||||
if (result.success && result.user) {
|
||||
const newToken = generateToken();
|
||||
const newRefreshToken = generateToken();
|
||||
const newToken = authStorage.generateToken();
|
||||
const newRefreshToken = authStorage.generateToken();
|
||||
|
||||
saveToken(newToken, newRefreshToken);
|
||||
saveUser(result.user);
|
||||
authStorage.saveToken(newToken, newRefreshToken);
|
||||
authStorage.saveUser(result.user);
|
||||
|
||||
setAuthState({
|
||||
isAuthenticated: true,
|
||||
@@ -95,70 +118,111 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
refreshToken: null,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
initAuth();
|
||||
}, []);
|
||||
} catch (error) {
|
||||
console.error('Auto login error:', error);
|
||||
setAuthState({
|
||||
isAuthenticated: false,
|
||||
user: null,
|
||||
token: null,
|
||||
refreshToken: null,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 定期检查token有效性
|
||||
useEffect(() => {
|
||||
if (!authState.isAuthenticated) return;
|
||||
if (!authState.isAuthenticated || !isInitialized) return;
|
||||
|
||||
const interval = setInterval(async () => {
|
||||
if (isTokenExpired()) {
|
||||
const refreshed = await refreshAuthToken();
|
||||
if (refreshed) {
|
||||
setAuthState(prev => ({
|
||||
...prev,
|
||||
token: refreshed.token,
|
||||
refreshToken: refreshed.refreshToken,
|
||||
}));
|
||||
} else {
|
||||
logout();
|
||||
try {
|
||||
const authStorage = await import('../../lib/authStorage');
|
||||
|
||||
if (authStorage.isTokenExpired()) {
|
||||
const refreshed = await authStorage.refreshAuthToken();
|
||||
if (refreshed) {
|
||||
setAuthState(prev => ({
|
||||
...prev,
|
||||
token: refreshed.token,
|
||||
refreshToken: refreshed.refreshToken,
|
||||
}));
|
||||
} else {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Token refresh error:', error);
|
||||
}
|
||||
}, 5 * 60 * 1000); // 每5分钟检查一次
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [authState.isAuthenticated]);
|
||||
}, [authState.isAuthenticated, isInitialized]);
|
||||
|
||||
const login = (user: User) => {
|
||||
const token = generateToken();
|
||||
const refreshToken = generateToken();
|
||||
const login = async (user: User) => {
|
||||
try {
|
||||
const authStorage = await import('../../lib/authStorage');
|
||||
const token = authStorage.generateToken();
|
||||
const refreshToken = authStorage.generateToken();
|
||||
|
||||
saveToken(token, refreshToken);
|
||||
saveUser(user);
|
||||
authStorage.saveToken(token, refreshToken);
|
||||
authStorage.saveUser(user);
|
||||
|
||||
setAuthState({
|
||||
isAuthenticated: true,
|
||||
user,
|
||||
token,
|
||||
refreshToken,
|
||||
});
|
||||
setAuthState({
|
||||
isAuthenticated: true,
|
||||
user,
|
||||
token,
|
||||
refreshToken,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
clearAuth();
|
||||
setAuthState({
|
||||
isAuthenticated: false,
|
||||
user: null,
|
||||
token: null,
|
||||
refreshToken: null,
|
||||
});
|
||||
const logout = async () => {
|
||||
try {
|
||||
const authStorage = await import('../../lib/authStorage');
|
||||
authStorage.clearAuth();
|
||||
|
||||
setAuthState({
|
||||
isAuthenticated: false,
|
||||
user: null,
|
||||
token: null,
|
||||
refreshToken: null,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Logout error:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const updateUser = (user: User) => {
|
||||
saveUser(user);
|
||||
setAuthState(prev => ({
|
||||
...prev,
|
||||
user,
|
||||
}));
|
||||
const updateUser = async (user: User) => {
|
||||
try {
|
||||
const authStorage = await import('../../lib/authStorage');
|
||||
authStorage.saveUser(user);
|
||||
|
||||
setAuthState(prev => ({
|
||||
...prev,
|
||||
user,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Update user error:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const checkAuth = (): boolean => {
|
||||
return authState.isAuthenticated && !isTokenExpired();
|
||||
return authState.isAuthenticated;
|
||||
};
|
||||
|
||||
// 在初始化完成前显示加载状态
|
||||
if (!isInitialized) {
|
||||
return (
|
||||
<div className="h-screen flex items-center justify-center bg-gray-50">
|
||||
<div className="text-center">
|
||||
<div className="inline-block h-12 w-12 animate-spin rounded-full border-4 border-solid border-green-600 border-r-transparent mb-4"></div>
|
||||
<p className="text-gray-600">正在加载...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ authState, login, logout, updateUser, checkAuth }}>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user