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 => { // 1. 调用登录接口 const response = await api.post('/auth/login', payload); if (response.code !== 200 || !response.data) { throw new Error(response.msg || '登录失败'); } const { token, tokenHead } = response.data; // 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 层处理 } }, /** * 登出流程 */ logout: async () => { // 逻辑大大简化:只负责调用 Store 和 UI 反馈 authStore.logout(); toast.success('退出登录成功'); // 如果需要调用后端登出接口(使 Token 失效),在这里 await api.post('/auth/logout') } };