feat: 实现安全存储和批量导入功能增强

refactor(前端): 重构认证和存储逻辑使用secureStorage
feat(前端): 添加安全存储工具和日志工具
feat(前端): 增强批量导入功能支持服务器和交换机设备
fix(后端): 改进设备端口和网卡批量导入接口
docs: 更新导入模板和操作说明
This commit is contained in:
zhangbing
2026-03-29 10:06:32 +08:00
parent 63f0cb570e
commit 1d815b812e
22 changed files with 1326 additions and 214 deletions
+17 -32
View File
@@ -1,5 +1,6 @@
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { authAPI } from '../api';
import secureStorage, { TOKEN_KEY, USER_KEY } from '../utils/secureStorage';
const AuthContext = createContext(null);
@@ -14,41 +15,24 @@ export const useAuth = () => {
export const AuthProvider = ({ children }) => {
console.log('[AuthContext] Initializing...');
const savedToken = localStorage.getItem('token');
const savedUser = localStorage.getItem('user');
const savedToken = secureStorage.get(TOKEN_KEY);
const savedUser = secureStorage.get(USER_KEY);
console.log('[AuthContext] Saved token:', savedToken ? 'exists' : 'null');
console.log('[AuthContext] Saved user:', savedUser ? 'exists' : 'null');
const [user, setUser] = useState(() => {
try {
if (savedUser) {
return JSON.parse(savedUser);
}
} catch (e) {
console.error('[AuthContext] Parse user error:', e);
}
return null;
});
const [user, setUser] = useState(() => savedUser || null);
const [token, setToken] = useState(() => savedToken);
const [loading, setLoading] = useState(false);
const [initialized, setInitialized] = useState(false);
useEffect(() => {
const currentToken = localStorage.getItem('token');
const currentUser = localStorage.getItem('user');
const currentToken = secureStorage.get(TOKEN_KEY);
const currentUser = secureStorage.get(USER_KEY);
if (currentToken && currentToken === token) {
if (currentUser) {
try {
const parsedUser = JSON.parse(currentUser);
if (JSON.stringify(parsedUser) !== JSON.stringify(user)) {
setUser(parsedUser);
}
} catch (e) {
console.error('[AuthContext] Parse user error:', e);
}
if (currentUser && JSON.stringify(currentUser) !== JSON.stringify(user)) {
setUser(currentUser);
}
setInitialized(true);
} else if (!currentToken) {
@@ -62,7 +46,7 @@ export const AuthProvider = ({ children }) => {
}, []);
const fetchProfile = useCallback(async () => {
const currentToken = localStorage.getItem('token');
const currentToken = secureStorage.get(TOKEN_KEY);
if (!currentToken) {
setLoading(false);
return;
@@ -72,6 +56,7 @@ export const AuthProvider = ({ children }) => {
const response = await authAPI.getProfile();
if (response.success) {
setUser(response.data.user);
secureStorage.set(USER_KEY, response.data.user);
}
} catch (error) {
console.error('获取用户信息失败:', error);
@@ -85,8 +70,8 @@ export const AuthProvider = ({ children }) => {
const response = await authAPI.login({ username, password });
if (response.success) {
const { token: newToken, user: userData } = response.data;
localStorage.setItem('token', newToken);
localStorage.setItem('user', JSON.stringify(userData));
secureStorage.set(TOKEN_KEY, newToken);
secureStorage.set(USER_KEY, userData);
setToken(newToken);
setUser(userData);
return { success: true };
@@ -103,8 +88,8 @@ export const AuthProvider = ({ children }) => {
if (response.success) {
const { token: newToken, user: newUser, isFirstUser, pendingApproval } = response.data;
if (newToken) {
localStorage.setItem('token', newToken);
localStorage.setItem('user', JSON.stringify(newUser));
secureStorage.set(TOKEN_KEY, newToken);
secureStorage.set(USER_KEY, newUser);
setToken(newToken);
setUser(newUser);
}
@@ -117,8 +102,8 @@ export const AuthProvider = ({ children }) => {
};
const logout = useCallback(() => {
localStorage.removeItem('token');
localStorage.removeItem('user');
secureStorage.remove(TOKEN_KEY);
secureStorage.remove(USER_KEY);
setToken(null);
setUser(null);
}, []);
@@ -126,7 +111,7 @@ export const AuthProvider = ({ children }) => {
const updateUser = newUserData => {
const updatedUser = { ...user, ...newUserData };
setUser(updatedUser);
localStorage.setItem('user', JSON.stringify(updatedUser));
secureStorage.set(USER_KEY, updatedUser);
};
const hasPermission = permission => {