API 文档管理系统

Scalar + swagger-jsdoc + 覆盖率检测 + 角色 Token 注入

目录
1. 系统概览 2. 技术架构 3. API 端点注解规范 4. 自动扫描与录入机制 5. 覆盖率检测系统 6. 角色 Token 自动注入 7. 日常开发工作流 8. 关键文件清单 9. 常用命令
1. 系统概览 当前状态
660
API 端点总数
100%
文档覆盖率
92
API 源文件
3
测试角色

Celoria 后端使用 Scalar API Reference 作为 API 文档浏览器,通过 swagger-jsdoc 从源码中的 @swagger 注解自动生成 OpenAPI 3.0 规范。配套的 覆盖率检测脚本 确保每个端点都有文档,Token 自动注入 支持在文档页面快速切换角色测试 API。

Scalar API Reference swagger-jsdoc OpenAPI 3.0 覆盖率检测 RBAC Token 注入
访问地址:http://localhost:3000/api-docs(本地开发环境)
2. 技术架构
graph TB
    subgraph 源码层
        A["backend/api/*.js (92个文件)"] -->|"@swagger 注解"| B[swagger-jsdoc]
        C["swagger.config.js (全局配置)"] --> B
    end

    subgraph 运行时
        B -->|生成| D["OpenAPI 3.0 Spec (/api-docs.json)"]
        D --> E["Scalar API Reference (/api-docs)"]
        F["scalar-login-inject.js (Token注入)"] --> E
    end

    subgraph 检测层
        A --> G["check-api-docs.js (覆盖率检测)"]
        D --> G
        G -->|"API 端点"| H["/api/docs-coverage (实时接口)"]
        H --> E
    end

    style A fill:#0f3460,stroke:#00d4ff,color:#eee
    style D fill:#0f3460,stroke:#10b981,color:#eee
    style E fill:#0f3460,stroke:#f59e0b,color:#eee
    style G fill:#0f3460,stroke:#e94560,color:#eee
    

数据流

1
开发者在 API 路由文件中编写 @swagger JSDoc 注解
2
swagger-jsdoc 在后端启动时扫描所有 API 文件,合并生成完整的 OpenAPI 3.0 spec
3
Scalar 从 /api-docs.json 加载 spec,渲染为交互式文档页面
4
scalar-login-inject.js 注入到页面,提供快速登录按钮和覆盖率检查入口
5
点击 Coverage 按钮时,前端调用 /api/docs-coverage,后端实时执行检测脚本返回结果
3. API 端点注解规范 手动编写

每个路由定义(router.get/post/put/delete)前必须添加 @swagger JSDoc 注释块。swagger-jsdoc 会自动扫描并提取这些注解。

标准模板

/**
 * @swagger
 * /api/appointments/{id}:
 *   get:
 *     summary: 获取预约详情
 *     tags: [Appointments]
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: string
 *         description: 预约 ID
 *     responses:
 *       200:
 *         description: 成功返回预约详情
 *       401:
 *         description: 未认证
 *       404:
 *         description: 预约不存在
 *       500:
 *         description: 服务器错误
 */
router.get('/:id', async (req, res) => { ... });

注解字段说明

字段必填说明
路径完整的 API 路径,如 /api/appointments/{id},路径参数用 {param} 格式
HTTP 方法get / post / put / patch / delete
summary端点简要描述(一句话)
tags分类标签,决定在 Scalar 左侧栏的分组
security视情况需要认证的端点添加 bearerAuth;公开端点(如注册登录)不加
parameters视情况路径参数 / 查询参数
requestBody视情况POST/PUT 请求体
responses至少包含成功响应和主要错误码
路径注意事项:注解中的路径必须是完整路径(含挂载前缀),不是路由文件中的相对路径。例如 api/appointments.js 中的 router.get('/:id'),注解路径应写 /api/appointments/{id},而不是 /{id}

常见 Tags

Appointments Shopping Cart Payment Guests Services Employees Guest Auth Time Clock Payroll Reports Public Booking Platform Settings Marketing Automation Voice Calls
4. 自动扫描与录入机制 自动

端点录入到文档系统是半自动的:注解需要手动编写,但扫描和发布是全自动的。

sequenceDiagram
    participant Dev as 开发者
    participant Code as API 文件
    participant SJSD as swagger-jsdoc
    participant Spec as OpenAPI Spec
    participant Scalar as Scalar UI

    Dev->>Code: 编写 @swagger 注解
    Note over Dev,Code: 手动步骤
    Dev->>Code: 重启后端 / 热重载
    Code->>SJSD: 自动扫描所有 api/*.js
    SJSD->>Spec: 生成 /api-docs.json
    Scalar->>Spec: 加载 spec
    Scalar->>Scalar: 渲染文档页面
    Note over SJSD,Scalar: 全自动
    

swagger-jsdoc 扫描配置

// backend/swagger.config.js
const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'Celoria API 文档',
      version: '2.0.0',
    },
    components: {
      securitySchemes: {
        bearerAuth: { type: 'http', scheme: 'bearer' },
        guestBearerAuth: { type: 'http', scheme: 'bearer' },
      }
    }
  },
  apis: [
    './api/**/*.js',      // 所有 API 路由文件
    './server.js',         // server.js 中的内联路由
  ],
};
关键点:只要 @swagger 注解写在被 apis glob 覆盖的文件中,后端启动时就会自动被收录到 OpenAPI spec 中。不需要额外注册或配置。
5. 覆盖率检测系统 核心

覆盖率检测脚本 scripts/check-api-docs.js 负责对比源码中的实际路由与 OpenAPI spec 中的文档化端点,计算覆盖率。

检测原理

graph LR
    A["扫描源码 (提取路由定义)"] --> B["解析挂载前缀 (组合完整路径)"]
    B --> C["生成 OpenAPI Spec (文档化端点)"]
    C --> D["逐一对比 (source vs spec)"]
    D --> E["输出覆盖率报告 (未文档化列表)"]

    style A fill:#0f3460,stroke:#00d4ff,color:#eee
    style B fill:#0f3460,stroke:#f59e0b,color:#eee
    style C fill:#0f3460,stroke:#10b981,color:#eee
    style D fill:#0f3460,stroke:#e94560,color:#eee
    style E fill:#0f3460,stroke:#00d4ff,color:#eee
    

三级前缀解析策略

脚本需要知道每个 API 文件的挂载前缀才能组合完整路径。采用三级策略逐步解析:

优先级策略来源示例
1 (最高) 解析 server.js 中的 app.use() app.use('/api/appointments', router) api/appointments.js/api/appointments
2 解析 index.js 子路由的 router.use() router.use('/calls', callsRouter) api/voice/calls.js/api/voice/calls
3 (兜底) 从文件内的 @swagger 注解反推 对比注解路径与路由路径的差值 注解 /api/cart/active - 路由 /active = /api/cart

覆盖率报告输出

$ npm run check:api-docs

File                              Total  Documented  Coverage
──────────────────────────────────────────────────────────────
admin/audit.js                        6           6      100%
admin/permissions.js                 13          13      100%
appointments.js                       9           9      100%
guest-auth.js                        13          13      100%
payment.js                           32          32      100%
voice/calls.js                        9           9      100%
...
──────────────────────────────────────────────────────────────
Total                               660         660      100%

页面内覆盖率检查

Scalar 页面右上角的 Coverage 按钮可以实时触发覆盖率检测:

1
点击 Coverage 按钮
2
前端调用 GET /api/docs-coverage
3
后端执行 node scripts/check-api-docs.js --json(实时扫描源码)
4
弹窗展示覆盖率摘要 + 文件明细表 + 未文档化端点列表
实时性:每次点击都会重新扫描文件系统,所以你刚加了新端点(即使没重启后端),覆盖率变化也能立即反映。

CI/CD 集成(严格模式)

# 覆盖率低于 95% 时 exit code 1,可用于 CI 流水线
npm run check:api-docs:strict

# 自定义阈值
node scripts/check-api-docs.js --strict --threshold 90

# JSON 输出(供工具消费)
node scripts/check-api-docs.js --json
6. 角色 Token 自动注入 RBAC

Scalar 页面右上角提供三个快速登录按钮,一键获取不同角色的 JWT Token 用于 API 测试。

可用角色

按钮测试账号角色权限来源
管理员登录 test.admin@qqnails.com admin RBAC 系统中该账号被分配的权限
超级管理员 test.superadmin@qqnails.com super_admin 自动跳过权限检查(全部权限)
客户登录 guest@test.com guest Guest Auth 系统,仅访问 /api/guest-* 端点
重要:Token 权限取决于 RBAC 配置。管理员按钮登录的是 test.admin@qqnails.com 这个具体账号,它的 Token 权限由 RBAC 系统中该账号被分配的角色和权限决定。不同管理员账号可以有不同权限。只有超级管理员会自动跳过权限检查。

Token 注入流程

sequenceDiagram
    participant User as 用户
    participant UI as Scalar 页面
    participant Inject as scalar-login-inject.js
    participant API as 后端 API

    User->>UI: 点击"管理员登录"
    Inject->>API: GET /api/test-accounts
    API-->>Inject: 返回测试账号信息
    Inject->>API: POST /api/auth/employee/login
    API-->>Inject: 返回 JWT Token
    Inject->>Inject: 存储到 localStorage
    Inject->>UI: 显示"已登录"状态
    Note over User,UI: 后续在 Scalar 中测试 API 时需手动复制 Token

    User->>UI: 点击"客户登录"
    Inject->>API: POST /api/guest-auth/login
    alt 账号不存在
        API-->>Inject: 404
        Inject->>API: POST /api/guest-auth/register (自动注册)
        API-->>Inject: 返回 Guest Token
    else 账号存在
        API-->>Inject: 返回 Guest Token
    end
    Inject->>Inject: 存储 + 标记 token_type=guest
    

Token 持久化

Token 保存在浏览器 localStorage 中,刷新页面后自动恢复登录状态:

Key用途
scalar_tokenJWT Token 字符串
scalar_user当前登录的用户名
scalar_token_typeToken 类型(guest 或空)

使用场景

三个按钮主要用于快速切换角色来测试 API 权限行为:

1
超级管理员登录,验证端点功能是否正常(全权限)
2
切换到管理员,验证 RBAC 权限是否正确限制了访问
3
切换到客户,验证 Guest Token 只能访问公开端点
7. 日常开发工作流

新增 API 端点

graph TD
    A["编写路由代码 (router.get/post)"] --> B["添加 @swagger 注解"]
    B --> C["重启后端"]
    C --> D["访问 /api-docs 确认"]
    D --> E["点击 Coverage 确认 100%"]

    style A fill:#0f3460,stroke:#00d4ff,color:#eee
    style B fill:#0f3460,stroke:#f59e0b,color:#eee
    style C fill:#0f3460,stroke:#10b981,color:#eee
    style D fill:#0f3460,stroke:#00d4ff,color:#eee
    style E fill:#0f3460,stroke:#10b981,color:#eee
    

忘记写注解怎么办?

1
点击 Coverage 按钮 → 弹窗会显示哪个文件覆盖率不是 100%
2
底部展开"未文档化端点"列表 → 显示具体是 GET /api/xxx 缺文档
3
回到源码补上 @swagger 注解 → 重启 → 再次点击 Coverage 确认

CI 自动检查

推荐配置:在 CI 流水线中添加 npm run check:api-docs:strict,覆盖率低于 95% 自动失败。防止团队成员提交未文档化的端点。
8. 关键文件清单
backend/
├── swagger.config.js — OpenAPI 全局配置(info, tags, securitySchemes)
├── server.js — Scalar 页面挂载 + /api/docs-coverage 端点
├── public/
│   └── scalar-login-inject.js — 登录按钮 + Coverage 按钮 + 弹窗 UI
├── api/ — 92 个 API 路由文件(含 @swagger 注解)
│   ├── appointments.js
│   ├── guest-auth.js
│   ├── payment.js
│   ├── admin/ — 管理端点
│   ├── mobile/ — 移动端端点
│   ├── platform/ — 平台管理端点
│   ├── reports/ — 报表端点
│   ├── voice/ — 语音 AI 端点
│   └── ...

scripts/
└── check-api-docs.js — 覆盖率检测脚本(CLI + JSON 输出)

package.json — npm 快捷命令
9. 常用命令
命令说明
npm run check:api-docs 运行覆盖率检查,输出表格报告
npm run check:api-docs:strict 严格模式:覆盖率 < 95% 则 exit code 1(用于 CI)
node scripts/check-api-docs.js --json JSON 格式输出(供工具消费)
node scripts/check-api-docs.js --verbose 详细模式:列出所有端点(含已文档化的)
node scripts/check-api-docs.js --threshold 90 自定义阈值(默认 80%)
curl localhost:3000/api-docs.json 导出完整 OpenAPI spec(可导入 Postman)
curl localhost:3000/api/docs-coverage 获取覆盖率 JSON(和 Coverage 按钮一样的数据)
Postman 导入:在 Postman 中选择 Import → Link → 粘贴 http://localhost:3000/api-docs.json,即可导入全部 660 个端点的定义。