- 暂时移除未使用的变量

- 配置项目依赖
- 组织项目基础结构
- 完成auth页面书写

Change-Id: I132c32f131111121619eb69240ece0a39e295c36
diff --git a/src/api/authApi.ts b/src/api/authApi.ts
new file mode 100644
index 0000000..b28b04f
--- /dev/null
+++ b/src/api/authApi.ts
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/api/client.ts b/src/api/client.ts
new file mode 100644
index 0000000..623ee78
--- /dev/null
+++ b/src/api/client.ts
@@ -0,0 +1,148 @@
+type RequestOptions = {
+    method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
+    headers?: Record<string, string>;
+    body?: unknown;
+    queryParams?: Record<string, string | number>;
+};
+  
+type Interceptor = {
+    request?: (config: RequestInit) => RequestInit;
+    requestError?: (error: unknown) => Promise<never>; // 错误拦截器应始终抛出
+    response?: (response: Response) => Response | Promise<Response>;
+    // 错误拦截器必须抛出或返回与请求相同类型的结果
+    responseError?: <T>(error: unknown) => Promise<T>;
+};
+  
+export class HttpClient {
+    private static instance: HttpClient;
+    private baseUrl: string;
+    private interceptors: Interceptor[] = [];
+  
+    private constructor(baseUrl: string) {
+      this.baseUrl = baseUrl;
+    }
+  
+    public static getInstance(baseUrl: string): HttpClient {
+      if (!HttpClient.instance) {
+        HttpClient.instance = new HttpClient(baseUrl);
+      }
+      return HttpClient.instance;
+    }
+  
+    // 添加拦截器
+    addInterceptor(interceptor: Interceptor) {
+      this.interceptors.push(interceptor);
+      return this; // 支持链式调用
+    }
+  
+    async request<T>(endpoint: string, options: RequestOptions = {}): Promise<T> {
+      const { 
+        method = 'GET', 
+        headers = {}, 
+        body, 
+        queryParams = {} 
+      } = options;
+  
+      const url = new URL(`${this.baseUrl}${endpoint}`);
+      Object.entries(queryParams).forEach(([key, value]) => {
+        url.searchParams.append(key, String(value));
+      });
+  
+      let config: RequestInit = {
+        method,
+        headers: {
+          'Content-Type': 'application/json',
+          ...headers
+        }
+      };
+  
+      if (body) {
+        config.body = JSON.stringify(body);
+      }
+  
+      // 请求拦截器处理
+      for (const interceptor of this.interceptors) {
+        if (interceptor.request) {
+          config = interceptor.request(config);
+        }
+      }
+  
+      try {
+        let response = await fetch(url.toString(), config);
+        
+        // 响应拦截器处理
+        for (const interceptor of this.interceptors) {
+          if (interceptor.response) {
+            response = await interceptor.response(response);
+          }
+        }
+  
+        if (!response.ok) {
+          const errorData = await response.json();
+          throw new Error(`HTTP error! Status: ${response.status}, Message: ${errorData.message || 'Unknown error'}`);
+        }
+  
+        return await response.json();
+      } catch (error) {
+        // 改进的错误拦截器处理
+        let lastError = error;
+        
+        for (const interceptor of this.interceptors) {
+          if (interceptor.responseError) {
+            try {
+              // 错误拦截器必须返回Promise<T>或抛出
+              return await interceptor.responseError<T>(lastError);
+            } catch (e) {
+              // 保存最新错误并继续下一个拦截器
+              lastError = e;
+              console.error('Interceptor error:', e);
+            }
+          }
+        }
+        
+        // 如果所有拦截器都未能处理错误,则抛出最后一个错误
+        throw lastError;
+      }
+    }
+    get<T>(endpoint: string, queryParams?: Record<string, string | number>) {
+      return this.request<T>(endpoint, { queryParams });
+    }
+  
+    post<T>(endpoint: string, body?: unknown, headers?: Record<string, string>) {
+      return this.request<T>(endpoint, { method: 'POST', body, headers });
+    }
+  
+    put<T>(endpoint: string, body?: unknown, headers?: Record<string, string>) {
+      return this.request<T>(endpoint, { method: 'PUT', body, headers });
+    }
+  
+    delete<T>(endpoint: string, headers?: Record<string, string>) {
+      return this.request<T>(endpoint, { method: 'DELETE', headers });
+    }
+}
+  
+const client = HttpClient.getInstance('http://localhost:8080/');
+// 添加Token注入拦截器
+client.addInterceptor({
+    request: (config) => {
+      const token = localStorage.getItem('token'); // 从存储中获取token
+      if (token) {
+        config.headers = {
+          ...config.headers,
+          'Authorization': `Bearer ${token}`
+        };
+      }
+      return config;
+    },
+    responseError: async (error) => {
+        if (error instanceof Error && error.message.includes('401')) {
+          console.log('Token expired, redirecting to login...');
+          // 示例:重定向到登录页
+          window.location.href = '/login';
+          // 必须返回Promise<never>或抛出
+          return new Promise(() => {}); // 永远不解决的Promise
+        }
+        throw error;
+      }
+});
+export default client as HttpClient;
\ No newline at end of file
diff --git a/src/api/type.ts b/src/api/type.ts
new file mode 100644
index 0000000..a5dd1ca
--- /dev/null
+++ b/src/api/type.ts
@@ -0,0 +1,10 @@
+export interface LoginRequest {
+    email: string;
+    password: string;
+}
+  
+export interface LoginResponse {
+    user: string;
+    token: string;
+    refreshToken: string;
+}
\ No newline at end of file