From 57720f5787a2d6abd2420eaa94389de7a353d96a Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:27:56 +0800 Subject: [PATCH 01/11] refactor(auth): split types.ts from auth.ts --- apps/web/src/api/auth/types.ts | 82 ++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 apps/web/src/api/auth/types.ts diff --git a/apps/web/src/api/auth/types.ts b/apps/web/src/api/auth/types.ts new file mode 100644 index 000000000..023e0fa32 --- /dev/null +++ b/apps/web/src/api/auth/types.ts @@ -0,0 +1,82 @@ +/** + * 认证相关类型定义 + */ + +export interface LoginRequest { + email: string + password: string +} + +export interface LoginResponse { + access_token: string + refresh_token?: string | null + token_type: string + expires_in: number + user_id: string + email: string + username: string + display_name: string +} + +export interface RegisterRequest { + email: string + password: string + username: string + display_name?: string +} + +export interface User { + id: string + user_id: string + email: string + username: string + display_name: string + is_email_verified: boolean + email_verified: boolean + created_at?: string +} + +export interface UserResponse { + id?: string + user_id?: string + email: string + username: string + display_name: string + is_email_verified?: boolean + email_verified?: boolean + created_at?: string +} + +export interface WechatAuthUrlResponse { + auth_url: string + state: string +} + +export interface WechatCallbackResponse { + access_token: string + refresh_token?: string | null + user_id: string + display_name: string + avatar_url: string + is_new_user: boolean + binding_complete: boolean + expires_in: number +} + +export interface SendVerificationCodeRequest { + target: "email" | "phone" + value: string + purpose: "bind" | "login" | "reset_password" +} + +export interface BindContactRequest { + email?: string + email_code?: string + phone?: string + phone_code?: string +} + +export interface BindContactResponse { + success: boolean + user: User +} -- 2.54.0 From f68eb996d223296448498984141d2aaffe7ad9ab Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:27:57 +0800 Subject: [PATCH 02/11] refactor(auth): split user.ts from auth.ts --- apps/web/src/api/auth/user.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 apps/web/src/api/auth/user.ts diff --git a/apps/web/src/api/auth/user.ts b/apps/web/src/api/auth/user.ts new file mode 100644 index 000000000..5c345e3b5 --- /dev/null +++ b/apps/web/src/api/auth/user.ts @@ -0,0 +1,20 @@ +import type { User, UserResponse } from "./types" + +/** + * 规范化用户数据,兼容不同后端返回格式 + */ +export const normalizeUser = (data: UserResponse): User => { + const userId = data.id ?? data.user_id ?? "" + const emailVerified = data.is_email_verified ?? data.email_verified ?? false + + return { + id: userId, + user_id: userId, + email: data.email, + username: data.username, + display_name: data.display_name, + is_email_verified: emailVerified, + email_verified: emailVerified, + created_at: data.created_at, + } +} -- 2.54.0 From 070cc72719804c1cead88d3011443ed0175fd6d2 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:27:57 +0800 Subject: [PATCH 03/11] refactor(auth): split login.ts from auth.ts --- apps/web/src/api/auth/login.ts | 37 ++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 apps/web/src/api/auth/login.ts diff --git a/apps/web/src/api/auth/login.ts b/apps/web/src/api/auth/login.ts new file mode 100644 index 000000000..09887a1b8 --- /dev/null +++ b/apps/web/src/api/auth/login.ts @@ -0,0 +1,37 @@ +import axios from "axios" +import apiClient from "../client" +import type { LoginRequest, LoginResponse, RegisterRequest } from "./types" + +/** + * 登录 + */ +export const login = async (data: LoginRequest): Promise => { + const response = await apiClient.post("/auth/login", data) + return response.data +} + +/** + * 刷新 access_token(使用裸 axios 避免拦截器递归) + */ +export const refreshAccessToken = async (refreshToken: string): Promise => { + const baseURL = apiClient.defaults.baseURL ?? "" + const response = await axios.post(`${baseURL}/auth/refresh`, { + refresh_token: refreshToken, + }) + return response.data +} + +/** + * 注册 + */ +export const register = async (data: RegisterRequest): Promise<{ message: string }> => { + const response = await apiClient.post("/auth/register", data) + return response.data +} + +/** + * 登出 + */ +export const logout = async (): Promise => { + await apiClient.post("/auth/logout") +} -- 2.54.0 From 70200220bf46647627b3ab8022f2b7244380ef36 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:27:58 +0800 Subject: [PATCH 04/11] refactor(auth): split currentUser.ts from auth.ts --- apps/web/src/api/auth/currentUser.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 apps/web/src/api/auth/currentUser.ts diff --git a/apps/web/src/api/auth/currentUser.ts b/apps/web/src/api/auth/currentUser.ts new file mode 100644 index 000000000..a31922de1 --- /dev/null +++ b/apps/web/src/api/auth/currentUser.ts @@ -0,0 +1,11 @@ +import apiClient from "../client" +import type { User, UserResponse } from "./types" +import { normalizeUser } from "./user" + +/** + * 获取当前用户 + */ +export const getCurrentUser = async (): Promise => { + const response = await apiClient.get("/auth/me") + return normalizeUser(response.data) +} -- 2.54.0 From 0ef6b0a4a3f1184a7eaa05b99fddb7e7c42f9696 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:27:59 +0800 Subject: [PATCH 05/11] refactor(auth): split password.ts from auth.ts --- apps/web/src/api/auth/password.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 apps/web/src/api/auth/password.ts diff --git a/apps/web/src/api/auth/password.ts b/apps/web/src/api/auth/password.ts new file mode 100644 index 000000000..4791d129c --- /dev/null +++ b/apps/web/src/api/auth/password.ts @@ -0,0 +1,23 @@ +import apiClient from "../client" + +/** + * 请求密码重置 + */ +export const requestPasswordReset = async (email: string): Promise<{ message: string }> => { + const response = await apiClient.post("/auth/forgot-password", { email }) + return response.data +} + +/** + * 重置密码 + */ +export const resetPassword = async ( + token: string, + newPassword: string, +): Promise<{ message: string }> => { + const response = await apiClient.post("/auth/reset-password", { + token, + new_password: newPassword, + }) + return response.data +} -- 2.54.0 From 0b88552fb9e51d5989f49e26ba2c27a2709db2c5 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:27:59 +0800 Subject: [PATCH 06/11] refactor(auth): split email.ts from auth.ts --- apps/web/src/api/auth/email.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 apps/web/src/api/auth/email.ts diff --git a/apps/web/src/api/auth/email.ts b/apps/web/src/api/auth/email.ts new file mode 100644 index 000000000..ade0be2d2 --- /dev/null +++ b/apps/web/src/api/auth/email.ts @@ -0,0 +1,9 @@ +import apiClient from "../client" + +/** + * 验证邮箱 + */ +export const verifyEmail = async (token: string): Promise<{ message: string }> => { + const response = await apiClient.post("/auth/verify-email", { token }) + return response.data +} -- 2.54.0 From 5033185fb3877daa30f2491b241688cc036d38b5 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:28:00 +0800 Subject: [PATCH 07/11] refactor(auth): split wechat.ts from auth.ts --- apps/web/src/api/auth/wechat.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/web/src/api/auth/wechat.ts diff --git a/apps/web/src/api/auth/wechat.ts b/apps/web/src/api/auth/wechat.ts new file mode 100644 index 000000000..1e41a8844 --- /dev/null +++ b/apps/web/src/api/auth/wechat.ts @@ -0,0 +1,21 @@ +import apiClient from "../client" +import type { WechatAuthUrlResponse, WechatCallbackResponse } from "./types" + +/** + * 获取微信授权链接 + */ +export const getWechatAuthUrl = async (): Promise => { + const response = await apiClient.get("/auth/wechat/url") + return response.data +} + +/** + * 微信回调登录 + */ +export const wechatCallback = async ( + code: string, + state: string, +): Promise => { + const response = await apiClient.post("/auth/wechat/callback", { code, state }) + return response.data +} -- 2.54.0 From 4b4df21b5c0e1530a4c68e6f34fd054391cfdafb Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:28:01 +0800 Subject: [PATCH 08/11] refactor(auth): split contact.ts from auth.ts --- apps/web/src/api/auth/contact.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 apps/web/src/api/auth/contact.ts diff --git a/apps/web/src/api/auth/contact.ts b/apps/web/src/api/auth/contact.ts new file mode 100644 index 000000000..feb846965 --- /dev/null +++ b/apps/web/src/api/auth/contact.ts @@ -0,0 +1,20 @@ +import apiClient from "../client" +import type { SendVerificationCodeRequest, BindContactRequest, BindContactResponse } from "./types" + +/** + * 发送验证码 + */ +export const sendVerificationCode = async ( + data: SendVerificationCodeRequest, +): Promise<{ message: string }> => { + const response = await apiClient.post("/auth/send-verification-code", data) + return response.data +} + +/** + * 绑定联系方式 + */ +export const bindContact = async (data: BindContactRequest): Promise => { + const response = await apiClient.post("/auth/bind-contact", data) + return response.data +} -- 2.54.0 From 404d15fe02964824e10108ddfda5227785111d45 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:28:02 +0800 Subject: [PATCH 09/11] refactor(auth): split index.ts from auth.ts --- apps/web/src/api/auth/index.ts | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 apps/web/src/api/auth/index.ts diff --git a/apps/web/src/api/auth/index.ts b/apps/web/src/api/auth/index.ts new file mode 100644 index 000000000..966c92c44 --- /dev/null +++ b/apps/web/src/api/auth/index.ts @@ -0,0 +1,39 @@ +/** + * 认证相关 API + * 保持向后兼容,从子模块 re-export + */ + +// 类型 +export type { + LoginRequest, + LoginResponse, + RegisterRequest, + User, + UserResponse, + WechatAuthUrlResponse, + WechatCallbackResponse, + SendVerificationCodeRequest, + BindContactRequest, + BindContactResponse, +} from "./types" + +// 用户工具函数 +export { normalizeUser } from "./user" + +// 登录/注册/登出/刷新 +export { login, refreshAccessToken, register, logout } from "./login" + +// 当前用户 +export { getCurrentUser } from "./currentUser" + +// 密码重置 +export { requestPasswordReset, resetPassword } from "./password" + +// 邮箱验证 +export { verifyEmail } from "./email" + +// 微信登录 +export { getWechatAuthUrl, wechatCallback } from "./wechat" + +// 联系方式 +export { sendVerificationCode, bindContact } from "./contact" -- 2.54.0 From 08bf93d6ad3725b8d34969d34feb06a043ded0e4 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:28:10 +0800 Subject: [PATCH 10/11] refactor(auth): remove old auth.ts (moved to auth/ directory) --- apps/web/src/api/auth.ts | 188 --------------------------------------- 1 file changed, 188 deletions(-) delete mode 100644 apps/web/src/api/auth.ts diff --git a/apps/web/src/api/auth.ts b/apps/web/src/api/auth.ts deleted file mode 100644 index da6e6340f..000000000 --- a/apps/web/src/api/auth.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** - * 认证相关 API - */ -import axios from "axios" -import apiClient from "./client" - -// 类型定义 -export interface LoginRequest { - email: string - password: string -} - -export interface LoginResponse { - access_token: string - refresh_token?: string | null - token_type: string - expires_in: number - user_id: string - email: string - username: string - display_name: string -} - -export interface RegisterRequest { - email: string - password: string - username: string - display_name?: string -} - -export interface User { - id: string - user_id: string - email: string - username: string - display_name: string - is_email_verified: boolean - email_verified: boolean - created_at?: string -} - -export interface UserResponse { - id?: string - user_id?: string - email: string - username: string - display_name: string - is_email_verified?: boolean - email_verified?: boolean - created_at?: string -} - -export const normalizeUser = (data: UserResponse): User => { - const userId = data.id ?? data.user_id ?? "" - const emailVerified = data.is_email_verified ?? data.email_verified ?? false - - return { - id: userId, - user_id: userId, - email: data.email, - username: data.username, - display_name: data.display_name, - is_email_verified: emailVerified, - email_verified: emailVerified, - created_at: data.created_at, - } -} - -// 登录 -export const login = async (data: LoginRequest): Promise => { - const response = await apiClient.post("/auth/login", data) - return response.data -} - -// 刷新 access_token(使用裸 axios 避免拦截器递归) -export const refreshAccessToken = async (refreshToken: string): Promise => { - const baseURL = apiClient.defaults.baseURL ?? "" - const response = await axios.post(`${baseURL}/auth/refresh`, { - refresh_token: refreshToken, - }) - return response.data -} - -// 注册 -export const register = async (data: RegisterRequest): Promise<{ message: string }> => { - const response = await apiClient.post("/auth/register", data) - return response.data -} - -// 登出 -export const logout = async (): Promise => { - await apiClient.post("/auth/logout") -} - -// 获取当前用户 -export const getCurrentUser = async (): Promise => { - const response = await apiClient.get("/auth/me") - return normalizeUser(response.data) -} - -// 请求密码重置 -export const requestPasswordReset = async (email: string): Promise<{ message: string }> => { - const response = await apiClient.post("/auth/forgot-password", { email }) - return response.data -} - -// 重置密码 -export const resetPassword = async ( - token: string, - newPassword: string, -): Promise<{ message: string }> => { - const response = await apiClient.post("/auth/reset-password", { - token, - new_password: newPassword, - }) - return response.data -} - -// 验证邮箱 -export const verifyEmail = async (token: string): Promise<{ message: string }> => { - const response = await apiClient.post("/auth/verify-email", { token }) - return response.data -} - -/* ========== 微信登录 ========== */ - -export interface WechatAuthUrlResponse { - auth_url: string - state: string -} - -export interface WechatCallbackResponse { - access_token: string - refresh_token?: string | null - user_id: string - display_name: string - avatar_url: string - is_new_user: boolean - binding_complete: boolean - expires_in: number -} - -export interface SendVerificationCodeRequest { - target: "email" | "phone" - value: string - purpose: "bind" | "login" | "reset_password" -} - -export interface BindContactRequest { - email?: string - email_code?: string - phone?: string - phone_code?: string -} - -export interface BindContactResponse { - success: boolean - user: User -} - -// 获取微信授权链接 -export const getWechatAuthUrl = async (): Promise => { - const response = await apiClient.get("/auth/wechat/url") - return response.data -} - -// 微信回调登录 -export const wechatCallback = async ( - code: string, - state: string, -): Promise => { - const response = await apiClient.post("/auth/wechat/callback", { code, state }) - return response.data -} - -// 发送验证码 -export const sendVerificationCode = async ( - data: SendVerificationCodeRequest, -): Promise<{ message: string }> => { - const response = await apiClient.post("/auth/send-verification-code", data) - return response.data -} - -// 绑定联系方式 -export const bindContact = async (data: BindContactRequest): Promise => { - const response = await apiClient.post("/auth/bind-contact", data) - return response.data -} -- 2.54.0 From f50e90c8c4d191824ed421b6410677620f7c4221 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 30 Jul 2026 00:55:07 +0800 Subject: [PATCH 11/11] =?UTF-8?q?test(auth):=20=E6=9B=B4=E6=96=B0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=96=87=E4=BB=B6=E5=A4=B4=E6=B3=A8=E9=87=8A=EF=BC=8C?= =?UTF-8?q?=E9=80=82=E9=85=8Dauth=E7=9B=AE=E5=BD=95=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/test/api/auth.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/web/src/test/api/auth.test.ts b/apps/web/src/test/api/auth.test.ts index 86b0a0116..4331a130a 100644 --- a/apps/web/src/test/api/auth.test.ts +++ b/apps/web/src/test/api/auth.test.ts @@ -1,3 +1,7 @@ +/** + * Auth API 测试 + * 对应 api/auth/ 目录化后的模块 + */ import { describe, expect, it, vi, beforeEach } from "vitest" import { normalizeUser, @@ -10,7 +14,6 @@ import { resetPassword, verifyEmail, } from "@/api/auth" - const mockPost = vi.fn() const mockGet = vi.fn() const mockAxiosPost = vi.fn() -- 2.54.0