// app/stores/auth.ts - 用户登录状态管理 import { defineStore } from "pinia"; import { authClient } from "@/utils/auth"; /** 当前登录用户信息,apiToken 用于 OCS 油猴脚本配置 */ interface AuthUser { id: string; name: string; email: string; /** 油猴脚本使用此 token 在 body 中传递身份 */ apiToken?: string | null; } export const useAuthStore = defineStore("auth", () => { const user = ref(null); const loading = ref(false); const error = ref(""); /** session 是否已完成首次加载,用于区分"未登录"和"尚未检查" */ const initialized = ref(false); /** 已登录且 session 已初始化完成 */ const isOnline = computed(() => initialized.value && user.value !== null); // 用于对并发调用去重,避免同一时刻发起多次 get-session 请求 let _fetchPromise: Promise | null = null; /** 从服务端拉取当前 session;已在请求中时复用同一 Promise,已初始化时直接跳过 */ const fetchSession = async () => { if (initialized.value) return; if (_fetchPromise) return _fetchPromise; _fetchPromise = (async () => { loading.value = true; error.value = ""; try { const session = await authClient.getSession(); user.value = session.data?.user ? { id: session.data.user.id, name: session.data.user.name, email: session.data.user.email, apiToken: (session.data.user as { apiToken?: string | null }) .apiToken } : null; } catch { user.value = null; } finally { loading.value = false; initialized.value = true; _fetchPromise = null; } })(); return _fetchPromise; }; /** 从 better-auth 返回的 user 对象中提取并写入 store */ const _setUserFromResult = (u: { id: string; name: string; email: string; apiToken?: string | null; }) => { user.value = { id: u.id, name: u.name, email: u.email, apiToken: u.apiToken ?? null }; initialized.value = true; }; /** 邮箱密码登录 */ const signIn = async (email: string, password: string) => { loading.value = true; error.value = ""; try { const result = await authClient.signIn.email({ email, password }); if (result.error) { error.value = "邮箱或密码错误"; return false; } // 直接使用登录响应中的用户数据,无需重复请求 get-session if (result.data?.user) { _setUserFromResult( result.data.user as Parameters[0] ); } return true; } catch { error.value = "登录失败,请重试"; return false; } finally { loading.value = false; } }; /** 注册新账号 */ const signUp = async (name: string, email: string, password: string) => { loading.value = true; error.value = ""; try { const result = await authClient.signUp.email({ name, email, password }); if (result.error) { error.value = "注册失败,邮箱可能已被使用"; return false; } if (result.data?.user) { _setUserFromResult( result.data.user as Parameters[0] ); } return true; } catch { error.value = "注册失败,请重试"; return false; } finally { loading.value = false; } }; /** 退出登录 */ const signOut = async () => { await authClient.signOut(); user.value = null; initialized.value = false; }; /** 刷新当前用户的 apiToken;成功后同步更新 store */ const refreshApiToken = async (): Promise => { loading.value = true; error.value = ""; try { const res = await $fetch<{ success: boolean; msg: string; apiToken?: string }>( "/api/user/refresh-token", { method: "POST" } ); if (res.success && res.apiToken && user.value) { user.value = { ...user.value, apiToken: res.apiToken }; return true; } error.value = res.msg || "刷新失败"; return false; } catch { error.value = "刷新失败,请重试"; return false; } finally { loading.value = false; } }; return { user, loading, error, initialized, isOnline, fetchSession, signIn, signUp, signOut, refreshApiToken }; });