crush-level-web/src/hooks/auth.ts

196 lines
5.5 KiB
TypeScript
Raw Normal View History

2025-11-13 08:38:25 +00:00
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { authService, CheckNicknameRequest, CompleteUserInfoRequest, UpdateUserInfoRequest, type LoginRequest, type LoginResponse } from "@/services/auth"
import { authKeys, userKeys } from "@/lib/query-keys"
import { tokenManager } from "@/lib/auth/token"
import { toast } from "sonner"
import type { ApiError } from "@/types/api"
import { useRouter } from "next/navigation"
import { userService } from "@/services/user"
export function useLogin() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (data: LoginRequest): Promise<LoginResponse> => authService.login(data),
onSuccess: (response: LoginResponse) => {
// 保存token到cookie
tokenManager.setToken(response.token)
// 刷新当前用户信息
queryClient.invalidateQueries({
queryKey: authKeys.currentUser()
})
},
})
}
export function useToken() {
return {
isLogin: tokenManager.isAuthenticated(),
token: tokenManager.getToken(),
getLoginStatus: () => {
return tokenManager.isAuthenticated()
}
}
}
export function useLogout() {
const queryClient = useQueryClient()
const router = useRouter()
return useMutation({
mutationFn: () => authService.logout(),
onSuccess: () => {
// 清除token
tokenManager.removeToken()
// 显示成功提示
toast.success("Log out successful!")
// 清除所有查询缓存
queryClient.clear()
router.push('/')
},
onError: (error: ApiError) => {
// 即使登出接口失败也要清除本地token
tokenManager.removeToken()
queryClient.clear()
// 跳转到登录页
router.push('/')
}
})
}
export function useCurrentUser() {
return useQuery({
queryKey: authKeys.currentUser(),
queryFn: () => authService.getCurrentUser(),
// 只有在有token的情况下才请求
enabled: tokenManager.isAuthenticated(),
// 如果获取用户信息失败,根据错误码处理
retry: (failureCount, error: ApiError) => {
// 如果是认证相关错误不重试并清除token
if (error.errorCode === 'AUTH_TOKEN_EXPIRED' ||
error.errorCode === 'AUTH_TOKEN_INVALID' ||
error.errorCode === 'AUTH_UNAUTHORIZED') {
tokenManager.removeToken()
return false
}
return failureCount < 1
},
})
}
export function useCompleteUser() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (data: CompleteUserInfoRequest) => authService.completeUserInfo(data),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: authKeys.currentUser()
})
},
})
}
export function useUpdateUser() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (data: UpdateUserInfoRequest) => authService.updateUserInfo(data),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: authKeys.currentUser()
})
},
})
}
export function useDeleteUser() {
const queryClient = useQueryClient()
const router = useRouter()
return useMutation({
mutationFn: () => authService.deleteUser(),
onSuccess: () => {
tokenManager.removeToken()
queryClient.clear()
router.push('/login')
}
})
}
// 注册功能暂未实现,保留接口定义
export function useRegister() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (data: any) => {
// TODO: 实现注册接口
throw new Error('注册功能暂未实现')
},
onSuccess: (response: LoginResponse) => {
// 注册成功后自动登录
tokenManager.setToken(response.token)
toast.success("Successful registration!")
queryClient.invalidateQueries({
queryKey: authKeys.currentUser()
})
},
onError: (error: ApiError) => {
console.error('注册失败:', {
errorCode: error.errorCode,
errorMsg: error.errorMsg,
traceId: error.traceId
})
toast.error("Registration failed.", {
description: error.errorMsg || "请稍后重试"
})
}
})
}
// 检查是否已登录的hook
export function useIsAuthenticated() {
return tokenManager.isAuthenticated()
}
export function useCheckNickname({
onError
}: {
onError?: (error: ApiError) => void
}) {
return useMutation({
mutationFn: (data: CheckNicknameRequest) => authService.checkNickname(data),
onError: onError,
})
}
export function useCheckText() {
return useMutation({
mutationFn: async (data: { content: string }) => {
const result = await authService.checkText(data)
if (result) {
return `"${result}" 词汇涉嫌违规,请修改后再试`
}
return ''
},
})
}
export function useUserNoticeStat() {
return useQuery({
queryKey: userKeys.noticeStat(),
queryFn: () => userService.getUserNoticeStat(),
enabled: tokenManager.isAuthenticated(),
})
}
export function useUserNoticeListInfinite(pageSize: number = 20, enabled: boolean = true) {
return useInfiniteQuery({
queryKey: userKeys.noticeList({ page: { pn: 1, ps: pageSize } }),
queryFn: ({ pageParam = 1 }) =>
userService.getUserNoticeList({ page: { pn: pageParam, ps: pageSize } }),
getNextPageParam: (lastPage, allPages) => {
const totalPages = Math.ceil((lastPage.tc || 0) / pageSize);
const nextPage = allPages.length + 1;
return nextPage <= totalPages ? nextPage : undefined;
},
initialPageParam: 1,
enabled, // 只有在启用时才执行查询
})
}