Files
nianxx-h5/.trae/documents/统一请求库封装计划.md
duanshuwen 548df7020c 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
2026-05-26 21:42:36 +08:00

8.5 KiB
Raw Permalink Blame History

统一请求库封装计划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
  • baseURLimport.meta.env 的环境变量读取(本计划固定变量名为 VITE_API_BASE_URL
  • header 值来源:全局上下文注入(内存态),由登录/定位/语言切换时写入
  • AuthorizationBearer <token>token 为空则不带 Authorization
  • 错误处理:请求库只做错误标准化并抛错,不做 Toast/跳转
  • header 字段:AuthorizationclientIdX-LatitudeX-Longitudelanguage

为什么不拆得更细(回答你的问题)

可以都放在 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.tsgetCurrentLocale()(读取失败则不注入 language header

2.2 Axios 实例创建与默认配置

  • baseURLimport.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_URLVITE_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(空文件 + 疑似拼写问题)

  • 该文件当前为空,且命名疑似应为 requestsrequest
  • 建议后续统一策略:保留/替换/删除前先全仓搜索确认是否在其它分支被引用

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 做统一处理)