topfans/docs/frontend-api-consistency-audit.md
2026-06-09 12:38:12 +08:00

9.2 KiB
Raw Blame History

前端 API 接口格式统一性审查报告

审查时间:2026-06-09 范围:frontend/ 下所有源码(unpackage/dist 等编译产物已排除) 核心封装器:frontend/utils/api.jsrequest(options)


0. TL;DR

整体架构是统一的:所有 JSON 接口走同一 request() 入口,token 注入、401 跳转、响应解析、Mock 短路都集中在 utils/api.js

主要问题不在封装本身,而在一批"绕过封装"的散点:

  • OSS 上传/下载没有沉淀到 api.js,导致 5 个页面 + 3 个 utils 各自实现一遍
  • 20+ 处业务侧重复判断 code === 200(封装器已保证)
  • 2 处历史遗留 URL 仍走旧版 /api/user/*(无 /v1)
  • 3 个模块 自己造了 request 风格的 uni.request 轮子

优先级 P0:把 OSS 直传抽到 utils/api.js,可一次性消掉 30+ 处重复代码。


1. 已统一的良好部分

1.1 入口封装 — 95% 的 JSON 接口走 request()

  • 唯一封装器:frontend/utils/api.jsrequest(options)(L53L134)
  • frontend/utils/api.js 内 60+ 个 API + frontend/utils/task-api.js 的 11 个 API 全部走 request()
  • 全项目 46 个文件 直接 import @/utils/api@/utils/task-api,无相对路径污染

1.2 Token 注入

  • 自动从 uni.getStorageSync('access_token') 读取
  • Header 格式统一为 Authorization: Bearer <token>
  • 白名单(不注入 token):/api/v1/auth/login|register|send-code|verify-code

1.3 业务响应结构

后端约定:{ code, message, data },封装器在 request() 内统一处理:

输入 行为
HTTP 200/202 + code === 200 resolve 整体响应
HTTP 200/202 + code === 401/400/403 清 token + 跳登录 + reject
HTTP 200/202 + 其他 code reject(Error(message))
HTTP 200/202 + 无 code 字段 resolve(res.data) ← 兜底
HTTP 401 清 token + 跳登录 + reject
其他 HTTP 状态码 reject(`Error(message

1.4 环境与 Mock 开关

  • VITE_API_BASE_URL / VITE_USE_MOCK_API 集中读取
  • IS_MOCK_API 暴露给业务做短路
  • getWebSocketBaseUrl / getSegmentApiBaseUrl / getLaserApiBaseUrl 三个 baseURL 工厂统一

1.5 Dashboard 模块有专门封装

dashboardApi 对象 + dashboardRequest() 工厂(utils/api.js L999L1007),统一了 mock 短路与 baseURL 前缀。

1.6 WebSocket 入口统一

utils/socket/SocketManager.js 通过 getWebSocketBaseUrl() 工厂函数拿到 baseURL(L48L49),token 拼在 query 上(?token=Bearer_<token>),鉴权方式与 HTTP 通道保持一致。


2. 不一致点(按严重度排序)

🔴 严重:页面层直连 uni.request / uni.uploadFile / fetch

下列文件绕过了 request() 封装,需要各自维护 token 注入、超时、错误处理、401 跳转。表中行号定位到调用点。

文件 行号 用途 风险点
pages/discover/discover.vue L101, L134 OSS PostObject 重复实现 fetch + uploadFile 分支
pages/discover/generation-result.vue L316, L418, L495, L653 OSS + 上传 4 处独立直传,逻辑高度相似
pages/castlove/index.vue L261, L409 图片下载/上传 自行处理 token
pages/castlove/create.vue L430, L527, L540, L569, L614 全链路直传 5 处,逻辑重复
pages/castlove/lenticular/lenticular-create.vue L331, L427, L440, L468, L512 全链路直传 5 处
pages/castlove/lenticular/lenticular-result.vue L217, L319, L396, L554 全链路直传 4 处
pages/square/components/WaterfallGrid.vue L712, L735, L777, L832 业务请求 4 处 res.code === 200
pages/square/components/HotCategoryBlock.vue L193 业务请求 code === 200 重复判断
pages/profile/profile.vue L1187 头像上传 自处理 statusCode
pages/profile/setNickname.vue L183 头像上传 自处理 statusCode,无 token 注入
pages/starbook/items.vue L136 业务请求 response.code === 200

🟡 中等:业务侧重复判断 code === 200

request() 已经对 code === 200 resolve 整体,业务侧不应再判断。下列位置违反封装契约:

utils/progress-manager.js:180
utils/activity-config.js:46, 69, 87, 105, 126
utils/craftMintSubmit.js:481, 510, 627, 690
pages/square/components/WaterfallGrid.vue:712, 735, 777, 832
pages/square/components/HotCategoryBlock.vue:193
pages/starbook/items.vue:136
pages/discover/discover.vue:195, 223
pages/discover/generation-result.vue:284
composables/useLaserMint.js:42

🟡 中等:部分模块自己造 request 风格轮子

文件 位置 说明
composables/useLaserDifyGenerate.js L19L47 独立 laserRequest(),自行注入 token、超时、状态码判断,文件内注释自承 "返回格式与 api.js 的 request() 一致"
utils/laser-card/segmentationCloud.js L21L39 uniRequest() 重复实现,仅做状态码判断
utils/laser-card/aliyunPortraitUni.js L273 uni.request 走 OSS PostObject,因 OSS 协议需要单独处理 x-oss-date 等特殊头
utils/craftMintSubmit.js L21, L57, L70, L399, L407, L423, L451 5 处 uni.uploadFile/fetch 混用,H5/App 分支自管

这些位置有合理理由绕过 request()(OSS 直传需自定义头、需 multipart/form-data),但应抽到 utils/api.js 而不是散布在业务模块。

🟡 中等:URL 风格不一致

虽然都带 /api/v1 前缀,但功能模块 URL 风格混乱:

  • 资源 URL:/api/v1/mygalleries(无 /me 也没有 /users)vs /api/v1/galleries/:uid vs /api/v1/galleries/random(utils/api.js L431L452)
  • 历史遗留:updateUserInfoApi L215 仍走 /api/user/update(无 /v1),deleteAccountApi L276 走 /api/user/delete-account
  • 单复数、是否用 /me 表示当前用户不统一:
    • /api/v1/auth/me
    • /api/v1/me/nickname
    • /api/v1/me/avatar
    • /api/v1/me/liked-assets
    • /api/v1/me/exhibited-assets
    • /api/v1/users/:uid/liked-assets

🟢 轻微:拼装 URL 的方式不统一

  • 多数用模板字符串拼在 url 内(/api/v1/social/users?page=${page}&page_size=${pageSize},utils/api.js L226)
  • 也有用 data 字段传 query 的(GET 请求,如 task-api.js L15 getDailyTasksstar_iddata 字段,uni.request 在 GET 下会拼到 query)
  • 统一规范缺失,新人很容易混用

🟢 轻微:request 默认 timeout 与 uni.uploadFile 超时不一致

  • request() 默认 60000ms(L78)
  • segmentPortraitApi 用 120000ms(L749)
  • downloadToLocal 用 120000ms(composables/useLaserSegment.js L29)
  • 没有集中常量

3. 统计摘要

指标 数值
直接 import @/utils/api 的文件 46
仍走 uni.request 直连的文件 7
仍走 uni.uploadFile 直连的文件 8
仍走 fetch() 直连的文件 5
业务侧 code === 200 二次判断处 20+
URL 路径里残留 /api/user/* 旧接口 2
重复实现的 request 风格封装 3(laserRequestuniRequestlaserRequest)

4. 修复建议(按 ROI 排序)

P0 — 把"绕过封装"的 OSS 直传抽到 api.js

新增一组 OSS 专用工具到 utils/api.js:

// 上传 OSS (H5: fetch + FormData / App: uni.uploadFile)
export function uploadToOss({ host, dir, filePath, policy, signature, ... }) { ... }

// 下载 OSS (H5: fetch + blob URL / App: uni.downloadFile)
export function downloadFromOss(signedUrl) { ... }

收益:消掉 5 个页面、3 个 utils 中重复的 30+ 处直传代码;统一 token 注入;统一超时;统一错误处理。

P1 — 修复 /api/user/* 旧路径

  • updateUserInfoApi(L215):/api/user/update → 对应的 v1 路径
  • deleteAccountApi(L276):/api/user/delete-account/api/v1/me/account 之类

P1 — 业务侧禁用 code === 200 二次判断

封装器已经处理,业务层应只 try/catch。可在 request() 里加注释:

// 业务侧请勿重复判断 code === 200,封装器已保证 resolve 时 code === 200

P2 — URL 风格规范化

建议对齐:

  • 当前用户 → /me(已用):/api/v1/me/liked-assets/api/v1/me/exhibited-assets 等等
  • 指定用户 → /users/:uid:/api/v1/users/:uid/liked-assets
  • 收藏/资源 → 单数主语,操作作子路径:/api/v1/galleries/... 而不是 /api/v1/mygalleries

P2 — 提取 api.js 默认 timeout 常量

const DEFAULT_TIMEOUT = 60000
const UPLOAD_TIMEOUT = 120000
export const API_TIMEOUT = {
  default: DEFAULT_TIMEOUT,
  upload: UPLOAD_TIMEOUT,
  download: UPLOAD_TIMEOUT,
}

P3 — 拼装 query 的工具函数

export function buildQuery(params) {
  return '?' + new URLSearchParams(params).toString()
}

让所有 getXxxApi 走同一方式,而非分散在 url/data 两处。


5. 后续 Action Items

优先级 任务 涉及文件数 预估工时
P0 把 OSS 上传/下载抽到 utils/api.js 8 4h
P1 修复 /api/user/* 旧路径 2 0.5h
P1 业务侧清除 20+ 处 code === 200 二次判断 10+ 1h
P2 URL 风格规范化 + /me 对齐 20+ 2h
P2 提取 API_TIMEOUT 常量 3 0.5h
P3 引入 buildQuery 工具函数 30+ 1h