interface User { id: number; username: string; email: string | null; nickname: string | null; avatar: string | null; role: string; createdAt?: number; } interface CaptchaData { token: string; image: string; } interface ApiResponse { code: number; message: string; data: T | null; } export function useAuth() { const user = useState("auth-user", () => null); const loading = ref(false); async function loadUser() { try { const res = await $fetch>("/api/auth/me", { headers: process.server ? useRequestHeaders(["cookie"]) : {}, }); if (res.code === 0 && res.data?.user) { user.value = res.data.user; } } catch { // 未登录时静默处理 } } async function register(username: string, password: string, captchaToken: string, captchaCode: string) { loading.value = true; try { const res = await $fetch>("/api/auth/register", { method: "POST", body: { username, password, captchaToken, captchaCode }, }); if (res.code !== 0) { return { success: false as const, message: res.message || "注册失败" }; } await loadUser(); return { success: true as const }; } catch { return { success: false as const, message: "网络错误,请重试" }; } finally { loading.value = false; } } async function login(username: string, password: string, captchaToken: string, captchaCode: string) { loading.value = true; try { const res = await $fetch>("/api/auth/login", { method: "POST", body: { username, password, captchaToken, captchaCode }, }); if (res.code !== 0) { return { success: false as const, message: res.message || "登录失败" }; } await loadUser(); return { success: true as const }; } catch { return { success: false as const, message: "网络错误,请重试" }; } finally { loading.value = false; } } async function logout() { await $fetch("/api/auth/logout", { method: "POST" }); user.value = null; } async function fetchCaptcha(): Promise { const res = await $fetch>("/api/auth/captcha", { method: "POST", }); if (res.code === 0 && res.data) { return res.data; } return null; } const isLoggedIn = computed(() => !!user.value); return { user, loading, isLoggedIn, loadUser, register, login, logout, fetchCaptcha }; }