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());
+ }
+};