Files
AIclinicalresearch/docs/04-开发规范/02-API设计规范.md
HaHafeng 66255368b7 feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
2026-01-16 13:42:10 +08:00

11 KiB
Raw Permalink Blame History

API设计规范

版本: v2.0
最后更新: 2025-11-06
API风格 RESTful API
基础URL http://localhost:3001/api/v1
适用范围: 平台层 + 能力层 + 业务模块层


📋 设计原则

API First原则

  • 先设计API再实现功能
  • API是前后端的契约
  • API变更需要版本控制
  • 所有API都要有文档

RESTful设计

  • 使用HTTP动词表示操作GET、POST、PUT、DELETE
  • URL表示资源不表示动作
  • 使用复数名词表示资源集合
  • 嵌套资源不超过2层
  • 使用HTTP状态码表示结果

命名规范

  • URL使用小写字母和连字符kebab-case
  • 查询参数使用驼峰命名camelCase
  • JSON字段使用驼峰命名camelCase

🎯 URL设计规范

路径格式

/api/v{version}/{module}/{resource}/{id?}/{action?}

示例:
/api/v1/literature/projects               # 获取文献项目列表
/api/v1/literature/projects/123           # 获取ID=123的项目
/api/v1/literature/projects/123/export    # 导出项目(动作)

模块前缀

模块 路由前缀 示例
认证 /auth /api/v1/auth/login
用户 /users /api/v1/users/me
AI问答 /chat /api/v1/chat/conversations
智能体 /agents /api/v1/agents
AI文献 /literature /api/v1/literature/projects
知识库 /knowledge-bases /api/v1/knowledge-bases
数据清洗 /data-cleaning /api/v1/data-cleaning/projects
统计分析 /analysis /api/v1/analysis/projects
统计工具 /tools /api/v1/tools
稿件审查 /review /api/v1/review/tasks
LLM网关 /llm /api/v1/llm/chat
管理端 /admin /api/v1/admin/users

资源命名

正确示例:

GET    /api/v1/literature/projects          # 获取列表
GET    /api/v1/literature/projects/:id      # 获取详情
POST   /api/v1/literature/projects          # 创建
PUT    /api/v1/literature/projects/:id      # 更新
DELETE /api/v1/literature/projects/:id      # 删除

GET    /api/v1/literature/projects/:id/items              # 获取项目下的文献
POST   /api/v1/literature/projects/:id/items/import       # 导入文献
POST   /api/v1/literature/projects/:id/screening/execute  # 执行筛选

错误示例:

POST /api/v1/literature/getProjects          # 使用动词
POST /api/v1/literature/createProject        # 使用动词
GET  /api/v1/literature/project              # 单数形式
GET  /api/v1/literatureProjectList           # 驼峰命名

🔧 HTTP方法规范

方法使用

方法 用途 是否幂等 是否安全
GET 获取资源
POST 创建资源
PUT 完整更新资源
PATCH 部分更新资源
DELETE 删除资源

方法示例

# 获取资源列表
GET /api/v1/literature/projects

# 获取单个资源
GET /api/v1/literature/projects/123

# 创建资源
POST /api/v1/literature/projects
Content-Type: application/json
{ "name": "新项目", "description": "..." }

# 完整更新资源(所有字段)
PUT /api/v1/literature/projects/123
Content-Type: application/json
{ "name": "更新", "description": "..." }

# 部分更新资源(部分字段)
PATCH /api/v1/literature/projects/123
Content-Type: application/json
{ "name": "只更新名称" }

# 删除资源
DELETE /api/v1/literature/projects/123

📊 状态码规范

标准状态码

状态码 含义 使用场景
200 OK 成功返回数据
201 Created 成功创建资源
204 No Content 成功但无返回数据(如删除)
400 Bad Request 请求参数错误
401 Unauthorized 未认证没有Token或Token过期
403 Forbidden 无权限(已认证但权限不足)
404 Not Found 资源不存在
409 Conflict 资源冲突(如重复创建)
422 Unprocessable Entity 语义错误(如验证失败)
429 Too Many Requests 请求过于频繁(限流)
500 Internal Server Error 服务器错误

状态码使用示例

// 200 OK - 成功获取数据
res.status(200).json({ success: true, data: projects });

// 201 Created - 成功创建资源
res.status(201).json({ success: true, data: newProject });

// 204 No Content - 成功删除(无内容返回)
res.status(204).send();

// 400 Bad Request - 参数错误
res.status(400).json({ 
  success: false, 
  error: { code: 'INVALID_PARAMS', message: '参数错误' } 
});

// 401 Unauthorized - 未认证
res.status(401).json({ 
  success: false, 
  error: { code: 'UNAUTHORIZED', message: '请先登录' } 
});

// 403 Forbidden - 无权限
res.status(403).json({ 
  success: false, 
  error: { code: 'FORBIDDEN', message: '无权访问' } 
});

// 404 Not Found - 资源不存在
res.status(404).json({ 
  success: false, 
  error: { code: 'NOT_FOUND', message: '资源不存在' } 
});

// 422 Unprocessable Entity - 验证失败
res.status(422).json({ 
  success: false, 
  error: { 
    code: 'VALIDATION_ERROR', 
    message: '参数验证失败',
    details: [...]
  } 
});

📝 响应格式规范

统一响应格式 必须遵守

成功响应:

{
  "success": true,
  "data": {
    // 实际数据
  },
  "message": "操作成功"
}

错误响应:

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "错误信息",
    "details": [...]  // 可选,详细错误信息
  }
}

列表数据响应

{
  "success": true,
  "data": {
    "items": [
      { "id": 1, "name": "项目1" },
      { "id": 2, "name": "项目2" }
    ],
    "pagination": {
      "page": 1,
      "pageSize": 10,
      "total": 100,
      "totalPages": 10,
      "hasNext": true,
      "hasPrev": false
    }
  },
  "message": "获取成功"
}

验证错误响应

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "参数验证失败",
    "details": [
      {
        "field": "email",
        "message": "邮箱格式不正确"
      },
      {
        "field": "password",
        "message": "密码长度必须大于6位"
      }
    ]
  }
}

🔑 认证与授权规范

JWT认证

1. 登录获取Token

POST /api/v1/auth/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "password123"
}

# Response
{
  "success": true,
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresIn": 604800,  // 7天
    "user": {
      "id": 123,
      "email": "user@example.com",
      "name": "张三",
      "role": "user"
    }
  }
}

2. 使用Token访问API

GET /api/v1/literature/projects
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

3. Token过期处理

# Token过期返回401
{
  "success": false,
  "error": {
    "code": "TOKEN_EXPIRED",
    "message": "Token已过期请重新登录"
  }
}

# 使用refreshToken刷新
POST /api/v1/auth/refresh
Content-Type: application/json

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

权限控制

端点类型 需要认证 角色要求
公开端点
用户端点 user
管理端点 admin

示例:

// 公开端点(无需认证)
POST /api/v1/auth/login
POST /api/v1/auth/register

// 用户端点需要认证user角色
GET  /api/v1/literature/projects
POST /api/v1/literature/projects

// 管理端点需要认证admin角色
GET  /api/v1/admin/users
POST /api/v1/admin/users/:id/disable

📄 分页规范

请求参数

GET /api/v1/literature/projects?page=1&pageSize=20&sortBy=createdAt&sortOrder=desc

Query参数
- page: 页码默认1
- pageSize: 每页数量默认10最大100
- sortBy: 排序字段默认createdAt
- sortOrder: 排序方向asc/desc默认desc

响应格式

{
  "success": true,
  "data": {
    "items": [...],
    "pagination": {
      "page": 1,
      "pageSize": 20,
      "total": 100,
      "totalPages": 5,
      "hasNext": true,
      "hasPrev": false
    }
  }
}

🔍 筛选与搜索规范

筛选参数

GET /api/v1/literature/projects?status=active&keyword=骨质疏松

Query参数
- status: 状态筛选active/inactive
- keyword: 关键词搜索搜索name和description字段
- userId: 用户ID筛选管理端
- startDate/endDate: 日期范围筛选

搜索响应

{
  "success": true,
  "data": {
    "items": [...],
    "pagination": {...},
    "filters": {
      "status": "active",
      "keyword": "骨质疏松"
    }
  }
}

⚠️ 错误码设计

标准错误码

错误码 HTTP状态 说明
VALIDATION_ERROR 422 参数验证失败
UNAUTHORIZED 401 未认证
TOKEN_EXPIRED 401 Token过期
FORBIDDEN 403 无权限
NOT_FOUND 404 资源不存在
ALREADY_EXISTS 409 资源已存在
QUOTA_EXCEEDED 429 配额超限
INTERNAL_ERROR 500 服务器错误

业务错误码

// 模块特定错误码(前缀区分)
ASL_IMPORT_FAILED          // AI文献导入失败
ASL_SCREENING_IN_PROGRESS  // AI文献筛选进行中
PKB_QUOTA_EXCEEDED         // 知识库:配额超限
LLM_QUOTA_EXCEEDED         // LLM配额超限

🚀 性能优化规范

1. 分页必须

所有列表接口必须支持分页:
- 默认pageSize=10
- 最大pageSize=100
- 禁止一次性返回全部数据

2. 字段过滤

GET /api/v1/users/me?fields=id,name,email

只返回需要的字段,减少数据传输

3. 缓存策略

# 设置缓存头
Cache-Control: public, max-age=300

# 使用ETag
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
# 返回304 Not Modified

检查清单

设计新API时必须检查

  • URL符合RESTful规范使用名词+复数)
  • 使用正确的HTTP方法GET/POST/PUT/DELETE
  • 使用正确的HTTP状态码
  • 响应格式符合统一规范success + data/error
  • 需要认证的接口检查JWT Token
  • 需要权限的接口检查用户角色
  • 列表接口支持分页
  • 列表接口支持排序
  • 错误响应包含明确的错误码和错误信息
  • 所有API都有文档说明

🔗 相关文档

总览:

模板:

各模块设计:


最后更新: 2025-11-06
维护人: 技术架构师
版本: v2.0