From 01294f58b14c6e059cc5ad80a257d5663838f0d4 Mon Sep 17 00:00:00 2001 From: dayjoy Date: Thu, 11 Sep 2025 10:31:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(client):=20=E6=B7=BB=E5=8A=A0=E5=AF=B9auth?= =?UTF-8?q?Token=E7=9A=84=E5=A4=84=E7=90=86=20&=20=E5=B0=81=E8=A3=85?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=A4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/client/src/App.tsx | 8 +++- packages/client/src/api/index.ts | 80 ++++++++++++++++++++++++++++++- packages/client/src/utils/auth.ts | 48 +++++++++++++++++++ 3 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 packages/client/src/utils/auth.ts diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx index cad8da0..ca1e24e 100644 --- a/packages/client/src/App.tsx +++ b/packages/client/src/App.tsx @@ -1,8 +1,14 @@ import "./App.css"; -import React from "react"; +import React, { useEffect } from "react"; import { Routes } from "react-router-dom"; +import { handleAuthTokenFromUrl } from "./utils/auth"; const App: React.FC = () => { + useEffect(() => { + // 在组件挂载时处理URL中的authToken + handleAuthTokenFromUrl(); + }, []); + return (
diff --git a/packages/client/src/api/index.ts b/packages/client/src/api/index.ts index ff8b4c5..3a7adf0 100644 --- a/packages/client/src/api/index.ts +++ b/packages/client/src/api/index.ts @@ -1 +1,79 @@ -export default {}; +import { getAuthToken } from '../utils/auth'; + +interface RequestOptions extends RequestInit { + headers?: Record; +} + +/** + * 统一的fetch请求封装 + * 自动添加Authorization头部 + */ +export const apiRequest = async ( + endpoint: string, + options: RequestOptions = {} +): Promise => { + const authToken = getAuthToken(); + + const url = endpoint; + + // 准备请求头 + const headers: Record = { + 'Content-Type': 'application/json', + ...options.headers, + }; + + // 如果有authToken,添加Authorization头 + if (authToken) { + headers.authorization = `Bearer ${authToken}`; + } + + // 发起请求 + const response = await fetch(url, { + ...options, + headers, + }); + + // 处理响应 + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + // 尝试解析JSON,如果失败则返回响应对象 + try { + return await response.json(); + } catch { + return response as any; + } +}; + +// 便捷的HTTP方法封装 +export const api = { + get: (endpoint: string, options?: RequestOptions): Promise => + apiRequest(endpoint, { ...options, method: 'GET' }), + + post: (endpoint: string, data?: any, options?: RequestOptions): Promise => + apiRequest(endpoint, { + ...options, + method: 'POST', + body: data ? JSON.stringify(data) : undefined, + }), + + put: (endpoint: string, data?: any, options?: RequestOptions): Promise => + apiRequest(endpoint, { + ...options, + method: 'PUT', + body: data ? JSON.stringify(data) : undefined, + }), + + patch: (endpoint: string, data?: any, options?: RequestOptions): Promise => + apiRequest(endpoint, { + ...options, + method: 'PATCH', + body: data ? JSON.stringify(data) : undefined, + }), + + delete: (endpoint: string, options?: RequestOptions): Promise => + apiRequest(endpoint, { ...options, method: 'DELETE' }), +}; + +export default api; diff --git a/packages/client/src/utils/auth.ts b/packages/client/src/utils/auth.ts new file mode 100644 index 0000000..89f2b93 --- /dev/null +++ b/packages/client/src/utils/auth.ts @@ -0,0 +1,48 @@ +// 处理认证相关的工具函数 + +const AUTH_TOKEN_KEY = 'authToken'; + +/** + * 从URL搜索参数中获取authToken + */ +export const getAuthTokenFromUrl = (): string | null => { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.get('authToken'); +}; + +/** + * 保存authToken到localStorage + */ +export const saveAuthToken = (token: string): void => { + localStorage.setItem(AUTH_TOKEN_KEY, token); +}; + +/** + * 从localStorage获取authToken + */ +export const getAuthToken = (): string | null => { + return localStorage.getItem(AUTH_TOKEN_KEY); +}; + +/** + * 清除authToken + */ +export const clearAuthToken = (): void => { + localStorage.removeItem(AUTH_TOKEN_KEY); +}; + +/** + * 检查并处理URL中的authToken + * 如果URL中有authToken参数,则保存到localStorage并从URL中移除 + */ +export const handleAuthTokenFromUrl = (): void => { + const tokenFromUrl = getAuthTokenFromUrl(); + if (tokenFromUrl) { + saveAuthToken(tokenFromUrl); + + // 从URL中移除authToken参数 + const url = new URL(window.location.href); + url.searchParams.delete('authToken'); + window.history.replaceState({}, '', url.toString()); + } +};