# HTTP 请求封装

<cite>
**本文引用的文件**
- [src/libs/http.js](file://src/libs/http.js)
- [packages/index.js](file://packages/index.js)
- [packages/libs/request.js](file://packages/libs/request.js)
- [packages/libs/util.js](file://packages/libs/util.js)
- [packages/core/src/libs/request.js](file://packages/core/src/libs/request.js)
- [packages/core/src/index.js](file://packages/core/src/index.js)
- [src/views/Home.vue](file://src/views/Home.vue)
- [packages/components/ProTable.vue](file://packages/components/ProTable.vue)
- [package.json](file://package.json)
- [src/main.js](file://src/main.js)
- [vite.config.js](file://vite.config.js)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本技术文档围绕基于 Axios 的 HTTP 请求封装进行系统性说明，涵盖请求拦截器、响应处理器、错误处理机制、请求配置选项（URL 参数替换、数据过滤、请求方法选择）、与 Vue 3 组件实例的集成方式（全局属性注入与实例访问）、API 使用示例（字符串配置、对象配置、函数配置）、请求头处理与 Token 认证、URL 动态替换等高级特性，并提供错误处理策略、性能优化建议与最佳实践。

## 项目结构
该项目采用多包结构，HTTP 封装主要分布在两处：
- 应用侧封装：在 src/libs/http.js 中对 axios 进行默认配置与拦截器注册，便于全局统一处理。
- 组件库封装：在 packages/libs/request.js 提供可复用的请求适配器，支持字符串、对象与函数三种调用方式，并内置 URL 动态替换、请求头合并、数据筛选等能力。

```mermaid
graph TB
subgraph "应用层"
A_main["src/main.js"]
A_http["src/libs/http.js"]
end
subgraph "组件库"
P_index["packages/index.js"]
P_core_index["packages/core/src/index.js"]
P_req["packages/libs/request.js"]
P_core_req["packages/core/src/libs/request.js"]
P_util["packages/libs/util.js"]
end
subgraph "第三方"
AX["axios"]
VUE["vue"]
MSG["view-ui-plus Message"]
QS["qs"]
LODASH["lodash-es"]
end
A_main --> A_http
A_http --> AX
A_http --> MSG
P_index --> VUE
P_core_index --> VUE
P_index --> AX
P_core_index --> AX
P_req --> AX
P_req --> QS
P_req --> LODASH
P_core_req --> AX
P_core_req --> QS
P_core_req --> LODASH
P_util --> LODASH
```

图表来源
- [src/main.js:1-14](file://src/main.js#L1-L14)
- [src/libs/http.js:1-70](file://src/libs/http.js#L1-L70)
- [packages/index.js:1-69](file://packages/index.js#L1-L69)
- [packages/core/src/index.js:1-84](file://packages/core/src/index.js#L1-L84)
- [packages/libs/request.js:1-78](file://packages/libs/request.js#L1-L78)
- [packages/core/src/libs/request.js:1-77](file://packages/core/src/libs/request.js#L1-L77)
- [packages/libs/util.js:1-110](file://packages/libs/util.js#L1-L110)

章节来源
- [src/main.js:1-14](file://src/main.js#L1-L14)
- [src/libs/http.js:1-70](file://src/libs/http.js#L1-L70)
- [packages/index.js:1-69](file://packages/index.js#L1-L69)
- [packages/core/src/index.js:1-84](file://packages/core/src/index.js#L1-L84)
- [packages/libs/request.js:1-78](file://packages/libs/request.js#L1-L78)
- [packages/core/src/libs/request.js:1-77](file://packages/core/src/libs/request.js#L1-L77)
- [packages/libs/util.js:1-110](file://packages/libs/util.js#L1-L110)

## 核心组件
- 应用级 HTTP 封装（src/libs/http.js）
  - 默认超时时间设置
  - 请求拦截器：自动注入 Authorization 头（来自本地存储），统一 Content-Type
  - 响应拦截器：根据状态码与自定义标志处理消息提示，统一返回数据结构
- 组件库请求适配器（packages/libs/request.js）
  - 支持三种调用方式：字符串 URL、对象配置、函数回调
  - URL 动态替换：使用占位符语法进行参数替换
  - 数据筛选：按 keys 仅取需要字段，区分 GET/POST 参数与 body
  - 请求头合并：从查询参数读取 token 并与传入 headers 合并
  - 实例访问：优先使用组件实例上下文中的 $http，否则回退到 Axios
- 全局属性注入（packages/index.js 与 packages/core/src/index.js）
  - 在插件 install 阶段向 app.config.globalProperties 注入 $http，默认指向 axios；可通过 opts.http.axios 覆盖
- 工具函数（packages/libs/util.js）
  - 提供模板渲染、JSON 序列化/反序列化、函数转换等工具，辅助复杂场景

章节来源
- [src/libs/http.js:1-70](file://src/libs/http.js#L1-L70)
- [packages/libs/request.js:1-78](file://packages/libs/request.js#L1-L78)
- [packages/index.js:12-20](file://packages/index.js#L12-L20)
- [packages/core/src/index.js:13-20](file://packages/core/src/index.js#L13-L20)
- [packages/libs/util.js:1-110](file://packages/libs/util.js#L1-L110)

## 架构总览
整体架构由“应用层封装 + 组件库适配器 + 插件注入”构成，组件库内部通过统一的请求适配器完成不同调用方式的兼容与增强，同时通过全局属性注入实现跨组件一致的访问入口。

```mermaid
graph TB
subgraph "应用启动"
M["src/main.js<br/>导入并挂载插件"]
H["src/libs/http.js<br/>axios 默认配置与拦截器"]
end
subgraph "插件注入"
PI["packages/index.js<br/>install 注入 $http"]
PC["packages/core/src/index.js<br/>install 注入 $http"]
end
subgraph "请求适配"
R["packages/libs/request.js<br/>字符串/对象/函数三种调用"]
CR["packages/core/src/libs/request.js<br/>核心版本适配器"]
U["packages/libs/util.js<br/>工具函数"]
end
subgraph "第三方依赖"
AX["axios"]
VUE["vue"]
QS["qs"]
MSG["view-ui-plus Message"]
end
M --> H
PI --> VUE
PC --> VUE
R --> AX
R --> QS
R --> VUE
CR --> AX
CR --> QS
CR --> VUE
H --> AX
H --> MSG
U --> VUE
```

图表来源
- [src/main.js:1-14](file://src/main.js#L1-L14)
- [src/libs/http.js:1-70](file://src/libs/http.js#L1-L70)
- [packages/index.js:12-20](file://packages/index.js#L12-L20)
- [packages/core/src/index.js:13-20](file://packages/core/src/index.js#L13-L20)
- [packages/libs/request.js:1-78](file://packages/libs/request.js#L1-L78)
- [packages/core/src/libs/request.js:1-77](file://packages/core/src/libs/request.js#L1-L77)
- [packages/libs/util.js:1-110](file://packages/libs/util.js#L1-L110)

## 详细组件分析

### 应用级 HTTP 封装（src/libs/http.js）
- 默认配置
  - 设置默认超时时间
  - 配置消息组件显示时长
- 请求拦截器
  - 从本地存储读取 token 并写入 Authorization 头
  - 强制 Content-Type 为 application/json
  - 拦截超时错误并提示
- 响应拦截器
  - 根据响应状态码与自定义标志决定是否展示错误消息
  - 统一将成功响应包装为 { success: true, ...data } 结构
  - 错误分类处理：服务端异常、超时、其他错误

```mermaid
sequenceDiagram
participant C as "调用方"
participant AX as "axios 实例"
participant REQ as "请求拦截器"
participant RES as "响应拦截器"
C->>AX : 发起请求
AX->>REQ : 进入请求拦截器
REQ-->>AX : 返回配置(含Authorization/Content-Type)
AX-->>C : 返回响应
AX->>RES : 进入响应拦截器
RES-->>C : 成功时返回 {success : true, ...data}<br/>失败时根据状态码提示错误
```

图表来源
- [src/libs/http.js:12-67](file://src/libs/http.js#L12-L67)

章节来源
- [src/libs/http.js:1-70](file://src/libs/http.js#L1-L70)

### 组件库请求适配器（packages/libs/request.js）
- 调用方式
  - 字符串：直接传入 URL，内部自动拼接 params/data
  - 对象：支持 request/url、method、keys、headers 等字段，支持函数式 request
  - 函数：直接传入函数，由调用方自行处理
- URL 动态替换
  - 使用占位符语法进行替换，容错处理避免异常
- 数据筛选
  - GET 使用 params，非 GET 使用 data
  - 可通过 keys 限定字段集合
- 请求头合并
  - 从查询参数读取 token，与传入 headers 合并
- 实例访问
  - 优先使用组件实例上下文中的 $http，否则回退到 Axios

```mermaid
flowchart TD
S["开始"] --> T{"request 类型？"}
T --> |字符串| STR["构造 axios(config)<br/>动态替换URL<br/>按方法拆分 params/data<br/>合并 headers"]
T --> |对象| OBJ["解析 keys/method/url/request<br/>若为函数则直接调用<br/>否则动态替换URL<br/>构造 axios 实例"]
T --> |函数| FN["直接调用函数"]
T --> |其他| ERR["返回错误结构"]
STR --> E["结束"]
OBJ --> E
FN --> E
ERR --> E
```

图表来源
- [packages/libs/request.js:39-77](file://packages/libs/request.js#L39-L77)

章节来源
- [packages/libs/request.js:1-78](file://packages/libs/request.js#L1-L78)

### 全局属性注入（packages/index.js 与 packages/core/src/index.js）
- 在插件 install 阶段向 app.config.globalProperties 注入 $http
- 默认值为 axios，可通过 opts.http.axios 覆盖
- 同时注入 $dayjs、$_、$PRO_IVIEW 等全局属性

```mermaid
sequenceDiagram
participant APP as "Vue 应用"
participant PLG as "插件 install"
participant CFG as "globalProperties"
APP->>PLG : use(ProComponents)
PLG->>CFG : 设置 $http = opts.http.axios || axios
CFG-->>APP : 注入完成
```

图表来源
- [packages/index.js:12-20](file://packages/index.js#L12-L20)
- [packages/core/src/index.js:13-20](file://packages/core/src/index.js#L13-L20)

章节来源
- [packages/index.js:12-20](file://packages/index.js#L12-L20)
- [packages/core/src/index.js:13-20](file://packages/core/src/index.js#L13-L20)

### 工具函数（packages/libs/util.js）
- 模板渲染：支持占位符替换与非法标识符校验
- JSON 序列化/反序列化：处理函数与 undefined 的丢失问题
- 字符串转函数：支持格式化与链式处理

章节来源
- [packages/libs/util.js:1-110](file://packages/libs/util.js#L1-L110)

### 在组件中的使用示例
- 组件库内部使用
  - ProTable 内部通过 customRequest 发起请求，支持字符串、对象与函数三种方式
  - 示例路径：[packages/components/ProTable.vue:571-572](file://packages/components/ProTable.vue#L571-L572)、[packages/components/ProTable.vue:688-689](file://packages/components/ProTable.vue#L688-L689)、[packages/components/ProTable.vue](file://packages/components/ProTable.vue#L808-...)
- 应用侧直接使用 $http
  - 在组件中通过 this.$http 或全局注入的 $http 访问
  - 示例路径：[src/views/Home.vue:196-203](file://src/views/Home.vue#L196-L203)

章节来源
- [packages/components/ProTable.vue:571-572](file://packages/components/ProTable.vue#L571-L572)
- [packages/components/ProTable.vue:688-689](file://packages/components/ProTable.vue#L688-L689)
- [packages/components/ProTable.vue:808-808](file://packages/components/ProTable.vue#L808-L808)
- [src/views/Home.vue:196-203](file://src/views/Home.vue#L196-L203)

## 依赖关系分析
- 第三方依赖
  - axios：HTTP 请求核心
  - vue：组件实例访问与全局属性注入
  - lodash-es：数据处理与工具函数
  - qs：查询参数解析
  - view-ui-plus：消息提示组件
- 构建配置
  - vite 配置中对 axios、qs、dayjs 等进行全局变量映射，减少打包体积

```mermaid
graph LR
PKG["package.json 依赖"] --> AX["axios"]
PKG --> VUE["vue"]
PKG --> LODASH["lodash-es"]
PKG --> QS["qs"]
PKG --> MSG["view-ui-plus"]
PKG --> DAY["dayjs"]
VC["vite.config.js"] --> AX
VC --> QS
VC --> DAY
```

图表来源
- [package.json:20-32](file://package.json#L20-L32)
- [vite.config.js:61-69](file://vite.config.js#L61-L69)

章节来源
- [package.json:20-32](file://package.json#L20-L32)
- [vite.config.js:61-69](file://vite.config.js#L61-L69)

## 性能考虑
- 请求拦截器与响应拦截器仅做必要处理，避免额外计算开销
- 数据筛选 keys 仅在需要时生效，减少传输体积
- URL 动态替换与 headers 合并均为轻量操作
- 建议在高频请求场景中启用缓存策略或合并请求，避免重复网络开销
- 对于大型表格或列表，优先使用分页与懒加载，降低一次性请求压力

## 故障排查指南
- 请求未携带 Authorization
  - 检查本地存储是否存在 token
  - 确认请求拦截器是否正确注入
- 响应未按预期返回
  - 检查响应拦截器中的状态码分支与 nomsg 标志
  - 确认后端返回结构是否符合预期
- URL 占位符未替换
  - 检查占位符语法与传入数据键名是否一致
  - 确认动态替换函数的容错逻辑
- 超时或连接中断
  - 检查默认超时时间与网络状况
  - 关注拦截器中的超时提示逻辑

章节来源
- [src/libs/http.js:12-67](file://src/libs/http.js#L12-L67)
- [packages/libs/request.js:23-31](file://packages/libs/request.js#L23-L31)

## 结论
该 HTTP 请求封装模块通过应用级默认配置与拦截器、组件库适配器与全局属性注入，实现了统一、灵活且易用的请求体验。其支持多种调用方式、动态 URL 替换、数据筛选与请求头合并，适用于复杂业务场景。配合错误处理与性能优化建议，可在保证开发效率的同时提升系统稳定性与用户体验。

## 附录
- API 使用示例（路径参考）
  - 字符串配置：[packages/components/ProTable.vue:571-572](file://packages/components/ProTable.vue#L571-L572)
  - 对象配置：[packages/components/ProTable.vue:688-689](file://packages/components/ProTable.vue#L688-L689)
  - 函数配置：[packages/components/ProTable.vue](file://packages/components/ProTable.vue#L808-...)
  - 应用侧直接使用 $http：[src/views/Home.vue:196-203](file://src/views/Home.vue#L196-L203)