# 后端接口契约 · tool.xpcool.com 本文档定义工具箱「在线服务」分类所有工具的后端接口规范。 前端已通过 `src/api/client.ts` 统一请求,**后端按本文档实现接口即可直接接入**,前端无需改动。 ## 通用约定 - **Base URL**:前端通过环境变量 `VITE_API_BASE` 配置(如 `https://api.xpcool.com`),未配置时页面显示「后端未接入」。 - **统一响应格式**(所有接口): ```json { "code": 0, "message": "ok", "data": { ... } } ``` - `code = 0` 成功;非 0 失败,`message` 为可读错误信息(前端直接展示给用户)。 - **编码**:UTF-8;GET 参数走 Query String,POST 走 JSON Body,无需鉴权(公开工具站)。 - **CORS**:需要允许前端域名跨域(`Access-Control-Allow-Origin: *`)。 - 建议实现限流(如单 IP 每分钟 60 次),防止免费接口被刷。 ## 接口一览 | # | 接口 | 说明 | | --- | --- | --- | | 1 | `GET /api/tools/exchange-rate` | 汇率换算 | | 2 | `GET /api/tools/express-query` | 快递查询 | | 3 | `GET /api/tools/phone-locate` | 手机号归属地 | | 4 | `GET /api/tools/ip-info` | IP 信息查询 | | 5 | `POST /api/tools/network-test` | 网络测试(ping / tcp / dns) | | 6 | `GET /api/tools/speedtest/download` | 下载测速(返回随机二进制流) | | 7 | `POST /api/tools/speedtest/upload` | 上传测速(接收二进制流) | --- ## 1. 汇率换算 `GET /api/tools/exchange-rate` **参数**:`from`(源货币代码,如 CNY)、`to`(目标货币代码,如 USD)、`amount`(金额,可选,默认 1) **响应 data** ```json { "from": "CNY", "to": "USD", "rate": 0.1398, "amount": 100, "result": 13.98, "updated_at": "2026-08-24 17:00" } ``` ## 3. 快递查询 `GET /api/tools/express-query` **参数**:`no`(快递单号) **响应 data** ```json { "no": "SF1234567890", "company": "顺丰速运", "status": "在途", "traces": [ { "time": "2026-08-24 15:32", "desc": "快件已到达【深圳中转场】" }, { "time": "2026-08-24 09:10", "desc": "快件已从【杭州】发出" } ] } ``` ## 4. 手机号归属地 `GET /api/tools/phone-locate` **参数**:`phone`(11 位手机号) **响应 data** ```json { "phone": "13800138000", "area": "北京", "carrier": "中国移动", "postcode": "100000", "updated_at": "2026-08-24 17:00" } ``` ## 5. IP 信息查询 `GET /api/tools/ip-info` **参数**:`ip`(IPv4,可选;不传则查询请求方 IP) **响应 data** ```json { "ip": "1.2.3.4", "country": "中国", "province": "广东", "city": "深圳", "isp": "电信", "updated_at": "2026-08-24 17:00" } ``` ## 6. 网络测试 `POST /api/tools/network-test` **请求体** ```json { "type": "ping", "host": "baidu.com", "port": null, "timeout": 5000 } ``` | 字段 | 必填 | 说明 | | --- | --- | --- | | type | 是 | `ping` / `tcp` / `dns` | | host | 是 | 主机名或 IP | | port | tcp 必填 | 目标端口(1-65535),其他类型传 null | | timeout | 否 | 超时毫秒,默认 5000 | **响应 data** ```json { "type": "ping", "host": "baidu.com", "port": null, "reachable": true, "latency_ms": 23.5, "detail": { "min_ms": 20.1, "avg_ms": 23.5, "max_ms": 28.3, "loss_pct": 0 } } ``` 各类型 `detail` 字段约定: | type | detail 字段 | 说明 | | --- | --- | --- | | ping | `min_ms` / `avg_ms` / `max_ms` / `loss_pct` | 3 次探测的最小/平均/最大延迟(ms)与丢包率(0-100) | | tcp | `tcp_connect_ms` | TCP 握手耗时(ms) | | dns | `dns_resolve_ms` / `ip` | 解析耗时与解析出的 IP | `reachable=false` 时 `latency_ms` 传 0,`detail` 传 `{ "error": "错误描述" }`。 ## 7. 网络测速 ### 下载测速 `GET /api/tools/speedtest/download?size=10485760` - 返回 **200 + `application/octet-stream` 随机字节流**(不是 JSON),响应头需带 `Content-Length`(前端据此显示进度)。 - `size` 为请求的字节数(建议支持 5MB ~ 50MB)。 - 前端流式读取并按耗时计算下载 Mbps,无需后端返回额外数据。 ### 上传测速 `POST /api/tools/speedtest/upload` - 请求体:`application/octet-stream` 原始二进制(前端生成随机数据上传)。 - 响应 JSON: ```json { "code": 0, "message": "ok", "data": { "bytes": 5242880, "duration_ms": 812, "speed_mbps": 51.6 } } ``` | 字段 | 说明 | | --- | --- | | bytes | 实际接收字节数 | | duration_ms | 接收耗时(ms) | | speed_mbps | 后端计算的上传速度(Mbps) | > 建议:下载测速时每次生成新的随机数据(`crypto/rand`),避免被缓存/CDN 命中导致测速失真;响应头 `Cache-Control: no-store`。 --- ## 错误示例 ```json { "code": 40001, "message": "城市不存在,请检查输入", "data": null } ``` | code | 含义 | | --- | --- | | 40001 | 参数不合法(如城市不存在、单号格式错误) | | 50001 | 上游数据源异常 | | 50002 | 频率限制,请稍后重试 | ## 前端接入说明 1. 复制 `.env.example` 为 `.env`,填写 `VITE_API_BASE=https://api.xpcool.com` 2. 重启 `pnpm dev`,在线服务分类的工具即可请求 3. 后端实现时对照各接口的响应 `data` 字段,字段名保持一致即可(前端已按契约类型化)