/** * 认证相关 Hooks */ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query" import { useNavigate } from "react-router-dom" import * as authApi from "@/api/auth" import { useAuthStore } from "@/store/authStore" // 登录 Hook export const useLogin = () => { const navigate = useNavigate() const setAuth = useAuthStore((state) => state.setAuth) const mutation = useMutation({ mutationFn: authApi.login, }) // 手动处理成功后的逻辑 const login = async (credentials: Parameters[0]) => { const data = await mutation.mutateAsync(credentials) const refreshToken = data.refresh_token ?? null // 先存 token 到 localStorage,确保后续请求拦截器能取到 // (apiClient 拦截器从 localStorage 读 access_token) localStorage.setItem("access_token", data.access_token) if (refreshToken) { localStorage.setItem("refresh_token", refreshToken) } // 再获取用户信息(这时候请求带 Authorization header) const user = await authApi.getCurrentUser() setAuth(user, data.access_token, refreshToken) // 跳转到登录前页面或首页 const redirect = localStorage.getItem("login_redirect") || "/" localStorage.removeItem("login_redirect") navigate(redirect, { replace: true }) return data } return { ...mutation, mutateAsync: login } } // 微信登录 Hook(用于回调后处理登录状态) export const useWechatCallback = () => { const navigate = useNavigate() const setAuth = useAuthStore((state) => state.setAuth) const setUser = useAuthStore((state) => state.setUser) const mutation = useMutation({ mutationFn: ({ code, state }: { code: string; state: string }) => authApi.wechatCallback(code, state), }) const handleCallback = async (code: string, state: string) => { // 校验 state const savedState = localStorage.getItem("wechat_state") if (!savedState || savedState !== state) { throw new Error("安全校验失败") } localStorage.removeItem("wechat_state") const result = await mutation.mutateAsync({ code, state }) // 先存 token 到 localStorage,确保后续请求拦截器能取到 // (apiClient 拦截器从 localStorage 读 access_token) localStorage.setItem("access_token", result.access_token) if (result.refresh_token) { localStorage.setItem("refresh_token", result.refresh_token) } // 再获取用户信息(这时候请求带 Authorization header) const user = await authApi.getCurrentUser() setAuth(user, result.access_token, result.refresh_token) return { ...result, user } } // 绑定成功后跳转 const finishLogin = () => { const redirect = localStorage.getItem("login_redirect") || "/" localStorage.removeItem("login_redirect") navigate(redirect, { replace: true }) } return { ...mutation, handleCallback, finishLogin, setUser } } // 注册 Hook export const useRegister = () => { const navigate = useNavigate() const mutation = useMutation({ mutationFn: authApi.register, }) const register = async (data: Parameters[0]) => { const result = await mutation.mutateAsync(data) navigate("/login", { state: { message: "注册成功!请查收验证邮件。" }, }) return result } return { ...mutation, mutateAsync: register } } // 登出 Hook export const useLogout = () => { const navigate = useNavigate() const clearAuth = useAuthStore((state) => state.clearAuth) const queryClient = useQueryClient() const mutation = useMutation({ mutationFn: authApi.logout, }) const logout = async () => { try { await mutation.mutateAsync() } catch (error) { // 即使登出失败也清除本地状态 } finally { clearAuth() queryClient.clear() navigate("/") } } return { ...mutation, mutateAsync: logout } } // 获取当前用户 Hook export const useCurrentUser = () => { const isAuthenticated = useAuthStore((state) => state.isAuthenticated) return useQuery({ queryKey: ["currentUser"], queryFn: authApi.getCurrentUser, enabled: isAuthenticated, }) }