Files
2026-06-29 11:15:39 +08:00

5.1 KiB
Raw Permalink Blame History

ADDED Requirements

Requirement: API 请求全量采集

系统 SHALL 通过 ApiRequestLogMiddleware 记录经 FastAPI 处理的 API 请求,并写入 sys_api_request_log。每条记录 SHALL 包含 HTTP 方法、路径(接口地址)、Query 字符串、请求体、响应体、HTTP 状态码、耗时、IP、User-Agent、请求时间(create_at)、用户 ID、用户账号(user_no)及用户姓名(nick_name → create_name)。

Scenario: 记录业务 API 入参与出参

  • WHEN 已认证用户调用 JSON 业务接口(如 POST /api/web/crm/customer/update)
  • THEN 系统持久化 path、query_string、request_body、response_body
  • AND create_at 为请求完成时刻
  • AND create_name 为 JWT 中的 real_name

Scenario: 敏感字段脱敏

  • WHEN 请求或响应 JSON 包含 password、token、authorization 等敏感键
  • THEN 落库值 SHALL 为 *** 而非明文

Scenario: 跳过高噪与健康检查路径

  • WHEN 请求为 OPTIONS 或路径为 /health、/docs、/openapi.json
  • THEN 系统 SHALL 不写入 sys_api_request_log

Scenario: 文件上传不记录文件体

  • WHEN 请求 Content-Type 为 multipart/form-data
  • THEN request_body SHALL 标记为省略说明而非文件二进制内容

Requirement: 业务语义字段落库

系统 SHALL 在 sys_api_request_log 存储业务语义列:tenant_no、business_title、business_type、business_id、oper_summary。写操作接口 SHOULD 通过 @oper_log 声明上述字段;未声明时系统 SHALL 使用路径与方法推断规则填充 business_title 与 business_type(business_id 与 oper_summary 可为空)。

Scenario: 装饰器声明修改客户

  • WHEN 带 @oper_log(title="CRM客户管理", business_type=2, business_id_param="id", summary="修改客户【{name}】") 的更新接口被调用且 ContextVar 已设置
  • THEN 落库 business_title=CRM客户管理、business_type=2
  • AND business_id 为请求中的客户 id
  • AND oper_summary 为可读摘要文本

Scenario: 只读列表无装饰器

  • WHEN 用户调用客户列表 GET 接口且路由无 @oper_log
  • THEN 系统仍记录 path 与入参出参
  • AND business_title 由路径推断(如 CRM客户管理)
  • AND business_type 为 0(其他)

Scenario: business_type 枚举

  • WHEN 系统写入 business_type
  • THEN 值 SHALL 属于:0其他、1新增、2修改、3删除、5导出、6导入(与 sys_oper_type 字典一致)

Requirement: 租户隔离

操作日志查询 SHALL 按当前用户 tenant_no 过滤 sys_api_request_log.tenant_no。中间件落库时 SHALL 从 JWT 写入 tenant_no。

Scenario: 租户数据不可见

  • WHEN 租户 A 的管理员查询操作日志
  • THEN 结果 SHALL 不包含租户 B 的记录

Requirement: 操作日志查询 API

系统 SHALL 提供 POST /api/web/monitor/operlog/list 与 POST /api/web/monitor/operlog/detail,将日志适配为 RuoYi OperLogVO 结构:operUrl(path)、operParam(request_body)、jsonResult(response_body)、operName(create_name 优先)、operTime、title(business_title)、businessType。

Scenario: 列表筛选业务实体

  • WHEN 请求体包含 businessId 与可选 businessTitle
  • THEN 返回匹配 business_id 的日志分页列表

Scenario: 详情含完整入参出参

  • WHEN 管理员请求某条日志详情
  • THEN 响应 SHALL 包含完整 operParam 与 jsonResult(受库内截断上限约束)

Scenario: 数据权限

  • WHEN 非 super_admin 用户查询列表
  • THEN 结果 SHALL 受数据权限约束(按操作人 user_id 范围)

Scenario: 访问控制

  • WHEN 非 admin/super_admin 用户调用 operlog API
  • THEN 系统 SHALL 拒绝访问

Requirement: 操作日志管理页

web-admin SHALL 提供操作日志标准列表页(界面模式 P01),支持按模块、操作类型、操作人、状态、时间范围筛选;详情展示接口地址、入参、出参与摘要。按钮与表格 SHALL 符合 Fresh Mint 与 web-admin-crud-dialog 规范。

Scenario: 管理员查看日志列表

  • WHEN 已授权的 admin 用户打开操作日志页
  • THEN 展示分页列表,列含模块、类型、操作人、时间、摘要、状态
  • AND 可打开详情查看 operParam 与 jsonResult

Requirement: CRM 业务详情操作日志 Tab

CRM 客户详情与合同详情中的操作日志 Tab SHALL 按 business_id 调用 operlog 列表,不再拉取全量日志后前端过滤。

Scenario: 客户详情日志

  • WHEN 用户在某客户详情打开「操作日志」Tab
  • THEN 仅展示 business_id 等于该客户 id 的日志

Requirement: 配置与生产开关

API_REQUEST_LOG_ENABLED 在生产环境 SHALL 为 true。body 截断上限 SHALL 保持可配置(API_REQUEST_LOG_MAX_BODY、API_REQUEST_LOG_MAX_BODY_BYTES)。

Scenario: 关闭采集

  • WHEN API_REQUEST_LOG_ENABLED=false
  • THEN 中间件 SHALL 不写入数据库