已有 ApiRequestLogMiddleware 全量采集 Web API 至 sys_api_request_log(path、query、request_body、response_body、user_id、username、create_at 等)。operlog/list 将上述数据适配为 RuoYi OperLogVO,权限为 admin/super_admin,CRM 详情 Tab 已调用但未按业务实体过滤。
约束:MySQL 5.7、租户隔离、数据权限、Fresh Mint UI(P01 列表)、中间件与 ApiCryptoMiddleware 顺序不变(Crypto 外层、RequestLog 内层,记录明文 JSON)。
Goals:
business_id 关联单据@oper_log 声明;未声明接口保留路径推断兜底Non-Goals:
sys_oper_log 数据合并@oper_log 覆盖所有写接口在 sys_api_request_log 扩展列,中间件继续全量采集;语义由 @oper_log + ContextVar 注入。理由:基础设施已存在,改动面可控。
| 列 | 说明 |
|---|---|
tenant_no |
租户隔离 |
business_title |
模块,如 CRM客户管理 |
business_type |
tinyint,对齐 sys_oper_type(0其他 1新增 2修改 3删除 5导出 6导入) |
business_id |
业务主键,可空 |
oper_summary |
人读摘要,如 修改客户【杭州某某化工】 |
展示优先级:oper_summary 用于列表摘要;title/businessType 映射 operlog API 字段。
@oper_log 在 handler 执行前/包装器内设置 ContextVarcall_next 完成 → 中间件 finally 读 ContextVar,与 JWT 字段一并 _persist_logbusiness_title/business_type 由 oper_log.py 现有路径规则在读时兜底(落库可为 NULL,或中间件落库时同步写推断值——实现取落库时写推断值以减少读时计算)JWT payload 已有 real_name(nick_name)。中间件 _claims_from_auth 扩展解析并写入 create_name;username 仍为 user_no。
{动词}{对象}【{显示名或编号}】,动词与 business_type 一致。装饰器可传 summary 或模板参数;Service 层可在执行业务后更新摘要(二期可选)。
operlog/list:DB 层筛选 tenant_no、语义字段;数据权限仍按 user_idsystem:operlog:list;仅 admin/super_admin(与现 monitor API 一致)business_id + 可选 business_title 精确过滤客户若后续要求「仅写操作」,通过 API_REQUEST_LOG_EXCLUDE_PATHS 配置扩展(本期仅预留 settings 字段,默认空)。
表 sys_api_request_log_his 已存在;本期迁移脚本扩展同名列。定时归档任务记入 tasks 后续项,不阻塞主功能。
| 风险 | 缓解 |
|---|---|
| 日志量膨胀 | 后续归档 + 可选排除只读路径 |
| 未注解接口语义弱 | 路径推断兜底 + 逐步补注解 |
| 响应体含 PII | 保持脱敏;详情仅授权角色可见 |
| ContextVar 在子线程丢失 | 落库用 asyncio.to_thread 时传入已收集的 dict,不依赖子线程读 ContextVar |
docs/sql/migrations/2026-06-29-operation-audit.sqlAPI_REQUEST_LOG_ENABLED=true@oper_log