refactor(layout): 重构应用布局结构

- 将原有布局中的侧边栏和头部组件拆分为独立的 AppSidebar 和 AppHeader 组件
- 移除内联的导航逻辑和样式,交由专用组件管理
- 更新图标库,优化部分图标的显示效果
- 简化认证存储逻辑,增强状态持久化与安全性
- 优化侧边栏状态管理机制,提高响应式体验
- 改进登录流程错误处理,增加网络异常提示
- 调整路由组件结构,提升代码可维护性
This commit is contained in:
Chaos
2025-11-24 07:17:12 +08:00
parent 71f19b658c
commit 3515faa814
16 changed files with 431 additions and 315 deletions

View File

@@ -1,48 +1,62 @@
import {api} from '$lib/api/httpClient.ts'
import type { AuthResponse, LoginPayload } from '$lib/types/auth.ts';
import { browser } from '$app/environment';
import { authStore } from '$lib/stores/authStore.ts';
import { userService } from '$lib/api/services/userService.ts';
import { userStore } from '$lib/stores/userStore.ts';
import { api } from '$lib/api/httpClient'; // 通常不需要 .ts 后缀
import type { AuthResponse, LoginPayload } from '$lib/types/auth';
import { authStore } from '$lib/stores/authStore';
import { userService } from '$lib/api/services/userService';
import { toast } from '$lib/stores/toastStore';
import { get } from 'svelte/store';
export const authService = {
/**
* 登录流程
*/
login: async (payload: LoginPayload): Promise<AuthResponse> => {
// 1. 调用登录接口
const response = await api.post<AuthResponse>('/auth/login', payload);
if (response.code != 200 || !response.data){
throw new Error(response.msg);
}
if (browser){
authService._setToken(response.data.token, response.data.tokenHead)
if (response.code !== 200 || !response.data) {
throw new Error(response.msg || '登录失败');
}
const userProfile = await userService.getUserProfile();
const { token, tokenHead } = response.data;
if (browser){
userStore.set(userProfile)
// 2. 临时设置 Token 到 Store
// 这一步是必须的,因为接下来的 userService.getUserProfile()
// 里的 API 请求拦截器需要读取 Store 中的 Token 才能通过鉴权。
// 我们先以“部分登录”的状态更新 Store。
authStore.update(s => ({ ...s, token, tokenHead, isAuthenticated: true }));
try {
// 3. 获取用户信息
const userProfile = await userService.getUserProfile();
// 4. 最终确认登录状态(更新完整信息并持久化)
// 这里调用 Store 封装好的 login 方法,它会负责写入 localStorage
authStore.login({
token,
tokenHead,
user: userProfile
});
return response.data;
} catch (error) {
// 5. 安全回滚
// 如果获取用户信息失败(比如 Token 虽然返回了但无效,或者网络波动),
// 我们应该立即清除刚才设置的临时 Token防止应用处于中间状态。
console.error('获取用户信息失败,回滚登录状态', error);
authStore.logout();
throw error; // 继续抛出错误给 UI 层处理
}
return response.data;
},
/**
* 登出流程
*/
logout: async () => {
// 逻辑大大简化:只负责调用 Store 和 UI 反馈
authStore.logout();
toast.success('退出登录成功');
if (browser){
authStore.clear();
userStore.clear();
localStorage.removeItem('auth_token');
localStorage.removeItem('auth_token_head');
return true;
}else {
return false;
}
},
_setToken: (token:string ,tokenHead: string)=> {
authStore.set({ token, tokenHead, isAuthenticated: true });
localStorage.setItem('auth_token', token);
localStorage.setItem('auth_token_head', tokenHead);
// 如果需要调用后端登出接口(使 Token 失效),在这里 await api.post('/auth/logout')
}
}
};