feat: initial project setup with core infrastructure and api clients

- Add environment configs for dev/staging/prod environments
- Implement centralized axios request utility with standardized error handling
- Add shared TypeScript types for API responses and requests
- Create comprehensive API client modules for all core endpoints
- Configure vue router with all application page routes
- Add icon fonts, static assets, and loading animations
- Set up project documentation and collaboration guidelines
- Remove deprecated uni-app bridge component files
This commit is contained in:
duanshuwen
2026-05-26 21:42:36 +08:00
parent ad93ca5e8e
commit 548df7020c
30 changed files with 1213 additions and 560 deletions

View File

@@ -0,0 +1,205 @@
# 统一请求库封装计划src/utils/request.ts 版)
## Summary
目标:把统一请求库集中封装在 `src/utils/request.ts`,类型集中在 `src/shared/`,实现:
- baseURL/timeout/取消请求Axios Web
- 默认 header 注入AuthorizationBearer、clientId、X-Latitude、X-Longitude、language
- 业务错误/网络错误/HTTP 错误的统一归一化(只抛错,不做 Toast/跳转)
- 输出说明文档到 `docs/request.md`
## Current State Analysis以实际仓库为准
已确认的事实:
- 依赖中已包含 `axios`,但 `src/` 内暂无 axios 的实际封装与使用。
- `src/utils/request.ts` 存在但为空文件,且命名疑似历史遗留。
- 代码中存在大量“缺失模块引用”(详见文末“历史遗留问题清单”),其中 `@/request/api/*` 属于最集中、最影响后续迁移的一类。
结论:
- 本次统一请求库规划要做到“新增即可用、可渐进替换”不依赖现有缺失的API 模块结构。
## Assumptions & Decisions你已确认
- 底层实现AxiosWeb
- baseURL`import.meta.env` 的环境变量读取(本计划固定变量名为 `VITE_API_BASE_URL`
- header 值来源:全局上下文注入(内存态),由登录/定位/语言切换时写入
- Authorization`Bearer <token>`token 为空则不带 Authorization
- 错误处理:请求库只做错误标准化并抛错,不做 Toast/跳转
- header 字段:`Authorization``clientId``X-Latitude``X-Longitude``language`
## 为什么不拆得更细(回答你的问题)
可以都放在 `src/utils/request.ts` 里完成,且更适合你现在“先落地一个可用的统一入口”的诉求:
- 单文件落地成本低:少目录、少入口、少导出点,替换/回滚都更直接
- 不牺牲可维护性:在单文件里用“内部分区函数 + 类型从 shared 引入”的方式,同样能保持边界清晰
- 何时再拆分:当出现“单文件 > 300~500 行、多人同时改动频繁、需要独立单测/Mock”的情况再把 errors/context/http 拆出去更合理
因此本计划采用:**实现集中在 request.ts类型抽到 shared** 的折中方案。
## Proposed Changes全新规划
### 1) 新增类型目录:`src/shared/`
新增目录:`src/shared/`
新增文件(建议):
- `src/shared/request-types.ts`
包含的类型定义(稳定、可复用):
- `export interface ApiResponse<T> { code: number; message?: string; data: T }`
- `export interface RequestOptions { signal?: AbortSignal; headers?: Record<string, string>; skipAuth?: boolean }`
- `export type RequestContext = { token: string | null; clientId: string | null; latitude: number | null; longitude: number | null; language: string | null }`
- `export type NormalizedErrorKind = "business" | "http" | "network" | "unknown"`
- `export interface NormalizedError extends Error { kind: NormalizedErrorKind; code?: number; httpStatus?: number; response?: unknown }`
### 2) 统一请求实现:`src/utils/request.ts`
新增文件:`src/utils/request.ts`
职责(全部在一个文件内完成):
#### 2.1 上下文容器(内存态)
提供以下导出函数(由业务在合适时机调用):
- `setAuthToken(token: string | null): void`
- `setClientId(clientId: string | null): void`
- `setLocation(latitude: number | null, longitude: number | null): void`
- `setLanguage(language: string | null): void`
- `getRequestContext(): RequestContext`
默认值策略:
- `language`:如果未显式设置,尝试读取 `src/i18n/index.ts``getCurrentLocale()`(读取失败则不注入 language header
#### 2.2 Axios 实例创建与默认配置
- `baseURL``import.meta.env.VITE_API_BASE_URL`
- 若缺失:直接抛出清晰错误(提示需要配置 baseURL
- `timeout`:可选 `import.meta.env.VITE_API_TIMEOUT_MS`,缺失则默认 15000
#### 2.3 请求拦截器header 注入)
组装 headers 规则:
- 合并顺序:`默认headers < 上下文headers < 调用方options.headers`
- `Authorization`:仅当 token 存在时注入 `Bearer <token>`;当 `options.skipAuth === true` 时跳过
- `clientId`:存在则注入
- `X-Latitude` / `X-Longitude`:存在则注入(数值转字符串)
- `language`:存在则注入
#### 2.4 响应处理(业务码 + 错误归一化)
1. 正常响应:
- 若响应体符合 `ApiResponse<T>``code === 0`:返回整个 `ApiResponse<T>`
- 若响应体符合 `ApiResponse<T>``code !== 0`:抛出 `NormalizedError(kind="business", code, message, response)`
2. 异常响应axios error
-`response.status`:抛 `NormalizedError(kind="http", httpStatus, response)`
-`response`:抛 `NormalizedError(kind="network")`
对外导出(建议最小集合):
- `export async function request<T>(config, options?: RequestOptions): Promise<ApiResponse<T>>`
- 可选:`export async function requestData<T>(...): Promise<T>`(内部调用 request 并返回 `data`,用于未来更干净的调用风格)
### 3) 文档输出到 `docs/`
新增目录:`docs/`
新增文档:`docs/request.md`(必须包含):
- 环境变量约定:`VITE_API_BASE_URL``VITE_API_TIMEOUT_MS`(可选)
- 上下文写入时机:
- 登录成功:`setAuthToken(token)`
- 应用初始化:`setClientId(clientId)`
- 定位成功:`setLocation(lat, lng)`
- 语言切换:`setLanguage(locale)`(或依赖默认读取 i18n
- 使用方式:
- 旧代码风格兼容:`const res = await request<T>(); res.data...`
- 新代码推荐:`const data = await requestData<T>()`
- 错误处理示例:区分 business/http/network/unknown 并给出上层建议策略
## 历史遗留问题清单(独立梳理,方便逐个替换)
说明:以下均为“当前仓库扫描可证实”的问题点,按模块引用位置列出,便于你后续按优先级逐个替换/补齐。
### A. `@/request/api/*` 悬空引用13 个文件)
- `src/pages/quick/index.vue`
- `src/components/Feedback/index.vue`
- `src/components/CreateServiceOrder/index.vue`
- `src/pages/service/order/components/OrderCard/index.vue`
- `src/pages/booking/components/FooterSection/index.vue`
- `src/pages/goods/index.vue`
- `src/pages/order/order/components/FooterSection/index.vue`
- `src/pages/quick/components/Tabs/index.vue`
- `src/pages/order/order/list.vue`
- `src/pages/service/order/index.vue`
- `src/pages/booking/index.vue`
- `src/pages/login/index.vue`
- `src/pages/order/order/detail.vue`
建议后续替换策略:
1. 先确定“这些 API 模块的真实来源”(是否在其它分支/其它仓库/尚未迁入)。
2. 如果确认不会迁回,则逐文件把 `@/request/api/*` 替换为基于 `src/utils/request.ts` 的真实调用(需要你提供具体 URL/参数约定)。
### B. `@/utils` 目录级导入缺失6 个文件)
当前仓库没有 `src/utils/index.*`,但以下文件在导入 `@/utils`
- `src/pages/quick/index.vue`
- `src/pages/booking/components/FooterSection/index.vue`
- `src/pages/goods/index.vue`
- `src/pages/order/order/components/FooterSection/index.vue`
- `src/pages/booking/index.vue`
- `src/pages/home/index.vue`
### C. `@/store` 与实际目录 `src/stores/` 命名不一致6 个文件)
- `src/components/ImageSwiper/index.vue`
- `src/pages/quick/components/Card/index.vue`
- `src/pages/goods/album/index.vue`
- `src/pages/goods/index.vue`
- `src/pages/booking/index.vue`
- `src/pages/home/index.vue`
### D. `@/hooks/*` 缺失3 个文件)
- `src/components/SwipeCards/index.vue`
- `src/pages/login/index.vue`
- `src/pages/home/index.vue`
### E. `@/constant/*` 缺失6 个文件)
- `src/components/ModuleTitle/index.vue`
- `src/components/Feedback/index.vue`
- `src/components/SurveyQuestionnaire/index.vue`
- `src/components/CreateServiceOrder/index.vue`
- `src/pages/booking/index.vue`
- `src/pages/login/index.vue`
### F. `src/utils/request.ts`(空文件 + 疑似拼写问题)
- 该文件当前为空,且命名疑似应为 `requests``request`
- 建议后续统一策略:保留/替换/删除前先全仓搜索确认是否在其它分支被引用
## Verification执行阶段你手动确认运行
你在实现完成后手动执行:
- `yarn typecheck`
- `yarn build`
- 如有用例:`yarn test`
验收标准:
- `src/utils/request.ts` + `src/shared/request-types.ts` 编译通过
- 发起请求时能注入 headersAuthorization/clientId/X-Latitude/X-Longitude/language
- `code !== 0` 时抛出稳定结构的错误对象(上层可根据 kind 做统一处理)