spec.md 13 KB

新增页面操作审计日志并优化页面视觉样式

status: applied created: 2026-07-07 complexity: 🟡中等

1. 背景与目标

当前操作日志只记录基础接口请求信息,缺少页面维度、操作人真实姓名、操作内容摘要、前后数据快照/差异展示和导出配置。需要在复用现有 sys_operation_log@OperationLog 的基础上增强页面审计能力,并把 /system/operation-log 页面改造成更适合审计筛选和详情核查的视觉体验。

完成后可验证结果:

  • 页面请求自动带上当前页面路径和页面标题,后台对变更类操作写入操作日志。
  • 操作日志记录账号、操作人、时间、页面、类型、内容、IP、请求/响应和差异快照字段。
  • /system/operation-log 支持按账号、操作人、页面、类型、状态、IP、URL、内容、时间筛选,支持导出。
  • 详情弹窗以审计视角展示用户、页面、请求、数据差异和环境信息,页面样式更清晰紧凑。

2. 代码现状(Research Findings)

2.1 相关入口与链路

  • forge-admin-ui/src/utils/http/interceptors.js:reqResolve 是前端统一请求拦截器,当前已写入 traceIdAuthorization、防重放头,但未写入当前页面路径/标题。
  • forge-server/forge-framework/forge-starter-parent/forge-starter-log/src/main/java/com/mdframe/forge/starter/log/aspect/OperationLogAspect.java:around 拦截 Controller 请求,构造 OperationLogInfo 并异步保存。
  • forge-server/forge-framework/forge-plugin-parent/forge-plugin-system/src/main/java/com/mdframe/forge/plugin/system/service/impl/SystemLogServiceImpl.java:saveOperationLogOperationLogInfo 转为 SysOperationLog 入库。
  • forge-admin-ui/src/views/system/operation-log.vue 是现有操作日志页面,使用 AiCrudPage 和自定义详情弹窗。

2.2 现有实现

  • sys_operation_log 已有字段:tenant_id, user_id, username, operation_module, operation_type, operation_desc, request_method, request_url, request_params, response_result, error_msg, operation_status, operation_ip, operation_location, user_agent, execute_time, operation_time
  • SysOperationLogController.page 当前直接使用 LambdaQueryWrapper 写查询条件,不符合 AGENTS.md 第 5.1 条“查询 SQL 必须写 XML”。
  • 通用 Excel 导出由 GenericExportController + DynamicExportEngine 提供,导出配置来自 sys_excel_export_configsys_excel_column_config
  • AiCrudPage 已支持 showExportapiConfig.export,可复用 POST /api/excel/export/{configKey}

2.3 发现与风险

  • 通用切面无法自动知道所有业务表的数据库变更前快照。必须提供审计快照字段,并通过上下文扩展支持业务代码后续主动设置;默认从请求参数/响应结果生成可追溯快照,避免阻塞当前全局页面审计上线。
  • 部分接口未显式 @OperationLog,当前切面会根据 API 配置兜底。页面维度应在切面统一补齐,不要求逐个 Controller 改造。
  • sys_operation_type 历史字典可能存在 INSERT 而非 ADD,本次迁移补齐 ADD,避免新增操作标签不显示。

3. 功能点

  • SDD 文档:建立本变更 spec.mdtasks.mdtest-spec.mdexecution-log.md
  • 日志字段增强:为 sys_operation_log 增加页面、操作人、操作内容、前后快照和差异字段。
  • 前端页面头注入:统一请求头写入 X-Page-PathX-Page-Title
  • 后端切面采集OperationLogAspect 读取页面头,填充审计字段,并提供默认操作内容/快照兜底。
  • 查询与导出:新增 SysOperationLogService、Query DTO 和 Mapper XML 查询,支持导出列表。
  • 页面视觉优化:重做 /system/operation-log 列表字段、筛选项、详情弹窗和导出入口。
  • 操作类型归一:统一历史 INSERT 与现行 ADD 新增类型,避免页面“操作类型”下拉展示两个“新增”。

4. 业务规则

  • 操作账号使用 username,操作人使用 operator_name,从 sys_user.real_name 补齐;为空时回退用户名。
  • 操作页面同时记录页面路径 operation_page 和页面标题 operation_page_title
  • 操作内容优先使用 @OperationLog.desc,无注解时使用 API 配置名称;再拼接请求方法和 URL 形成可读摘要。
  • 操作日志默认只记录变更类操作:ADDUPDATEDELETEIMPORTEXPORTOTHER,以及未显式标注但 HTTP 方法为 POSTPUTPATCHDELETE 的接口。
  • 查询类操作默认不落库:显式 OperationType.QUERY、API 配置识别为 QUERY、未显式标注且 HTTP 方法为 GETHEADOPTIONS 的接口直接放行;/page/list/tree/detail/getById/options/profile/query 等 POST 查询兼容接口也按查询放行。
  • before_dataafter_datadiff_data 支持审计上下文主动写入;未主动写入时:
    • 新增/修改/删除/导入/导出类操作以请求参数作为提交快照,以响应结果作为结果快照。
  • 加密请求体被切面替换为 [DECRYPTED_REQUEST_BODY_OMITTED] 时,不允许把该占位符写入 after_data;需要精确快照的业务接口通过 OperationAuditContext 主动写入脱敏后的前后数据。
  • 用户管理主操作(新增、修改、删除、批量删除、状态、解锁、重置密码、个人资料)主动写入脱敏快照和字段 diff;密码值不进入请求参数和快照。
  • 操作类型以 OperationType.ADDADD 作为新增操作标准值;历史 INSERT 日志和字典值迁移归一到 ADD。页面展示时将 INSERT 兼容映射为 ADD,筛选 ADD 时兼容查询迁移前的 INSERT 数据。
  • 操作日志表属于审计日志,普通行级删除不在本需求新增;历史留存清理可由专用任务按策略物理清理。
  • 页面视觉遵循后台审计工具风格:克制、密集、可扫描,不做营销式 Hero 或大面积装饰。

5. 数据变更

操作 表名 字段/索引 说明
修改 sys_operation_log operator_name 操作人真实姓名
修改 sys_operation_log operation_page, operation_page_title 页面路径和页面标题
修改 sys_operation_log operation_content 操作内容摘要
修改 sys_operation_log before_data, after_data, diff_data 前后快照与差异
修改 sys_operation_log idx_operation_page_time, idx_operator_name 查询优化
新增/补齐 sys_dict_data sys_operation_type=ADD 兼容 OperationType.ADD
修改 sys_operation_log, sys_dict_data INSERTADD 统一新增操作类型,避免 INSERT/ADD 同时显示为两个“新增”
新增 sys_excel_export_config, sys_excel_column_config sys_operation_log_export 操作日志导出配置
修改 sys_resource 操作日志菜单名称/权限 菜单展示为页面操作审计日志并补导出权限

6. 接口变更

操作 接口 方法 变更内容
修改 /system/operationLog/page GET 增加页面、操作人、操作内容筛选,后端改为 XML 查询
修改 /system/operationLog/{id} GET 返回新增审计字段
复用 /api/excel/export/sys_operation_log_export POST 导出筛选后的操作日志

7. 影响范围

  • 后端:forge-starter-logforge-plugin-system、Flyway 迁移脚本。
  • 前端:统一请求拦截器、/system/operation-log 页面。
  • 数据:sys_operation_log 增加字段;历史数据字段为空,不影响既有查询。

8. 风险与关注点

  • ⚠️ 审计日志可能包含请求参数和响应结果,切面已有 @ApiDecrypt 请求体省略逻辑;本次继续沿用截断和脱敏边界,避免扩大敏感数据暴露面。
  • ⚠️ 通用切面无法对所有业务表自动生成数据库级前后差异;本次通过字段和上下文扩展提供能力,默认记录请求/响应快照,后续高风险业务可主动写入精确差异。
  • ⚠️ 导出数据需受现有登录和权限体系保护,复用通用 Excel 导出接口和菜单权限配置。

8.5 测试策略

  • 测试范围:SQL 迁移静态检查、后端模块编译、前端构建、页面字段/导出配置静态校验。
  • 覆盖率目标:本轮以编译和关键链路静态验证为主;若本地数据库和服务可用,再做登录后页面/导出联调。
  • 独立 Test Spec:是。

9. 待澄清

  • 用户已明确“按照 SDD 开发,我睡觉了”,本轮不阻塞等待确认。

10. 技术决策

  • 复用现有 sys_operation_log,不新建 page_audit_log 表,避免日志链路分叉。
  • 前端统一请求头注入页面元信息,不逐页手工传参。
  • 查询 SQL 迁移到 SysOperationLogMapper.xml,修正当前 Controller 内查询问题。
  • 操作日志导出复用平台动态 Excel 能力。
  • 切面在解析注解/API 配置后先判断是否为查询类操作,查询直接执行业务方法并清理审计上下文,不创建 traceId,不异步保存日志。

11. 执行日志

Task 状态 实际改动文件 备注
SDD 文档 已完成 spec.md, tasks.md, test-spec.md, execution-log.md 本轮创建
Task 1 已完成 V1.0.14__enhance_operation_log_page_audit.sql 新增审计字段、索引、字典、导出配置和资源权限
Task 2 已完成 OperationAuditContext.java, OperationLogInfo.java, OperationLogAspect.java 统一采集页面头、操作内容和审计快照
Task 3 已完成 SysOperationLogQuery.java, ISysOperationLogService.java, SysOperationLogServiceImpl.java, SysOperationLogMapper.java, SysOperationLogMapper.xml, SysOperationLogController.java 查询迁移到 XML SQL 并支持导出
Task 4 已完成 interceptors.js 所有请求自动携带页面路径和页面标题
Task 5 已完成 operation-log.vue 审计列表、筛选、导出和详情弹窗视觉优化
Task 6 已完成 test-spec.md, execution-log.md 后端编译、前端构建和静态校验通过
增量修正 已完成 OperationLogAspect.java, spec.md, tasks.md, test-spec.md, execution-log.md 查询类操作不再落库,只记录变更类操作
增量修正 已完成 interceptors.js, OperationLogAspect.java, SysUserController.java, spec.md, tasks.md, test-spec.md, execution-log.md 修正页面标题/模块兜底和用户管理快照,避免加密体占位符进入数据快照
增量修正 已完成 operation-log.vue, SysOperationLogMapper.xml, V1.0.15__normalize_operation_type_add_dict.sql, spec.md, tasks.md, test-spec.md, execution-log.md 修复操作类型两个“新增”,统一 INSERTADD

12. 审查结论

已完成实现与验证。git diff --check 通过;Flyway 占位符扫描无 ${...}SysOperationLogMapper.xml 通过 xmllint --nooutforge-admin-server 依赖编译通过;pnpm --dir forge-admin-ui build 通过。前端构建中存在既有动态导入、CSS // 注释和 chunk size 类 warning,未阻断本次变更。未启动后端和真实数据库做页面联调,原因是本轮以代码实现、迁移脚本和构建验证为主,未引入本地服务启动。

2026-07-08 增量修正:按用户确认调整为只记录变更类操作。OperationType.QUERY 和只读 HTTP 方法默认不落库;ADD/UPDATE/DELETE/IMPORT/EXPORT/OTHER 继续记录。git diff --checkmvn -q -pl forge-admin-server -am compile -DskipTests 已通过。

2026-07-08 Flyway 修复:sys_dict_data 补齐 ADD 字典的派生表漏写 dict_label 别名,导致 Unknown column 'seed.dict_label' in 'field list'。已补为 '新增' dict_label,并通过 git diff --check 与静态别名检查。

2026-07-08 页面审计展示修复:请求头页面标题改为优先从菜单/页签解析,避免只写入基础系统名;后端模块为空时使用有效页面标题兜底;加密请求体占位符不再作为 after_data;用户管理主操作补充脱敏前后快照与 diff。git diff --checkmvn -q -pl forge-admin-server -am compile -DskipTestspnpm --dir forge-admin-ui build 已通过。

2026-07-08 操作类型去重修复:旧基线字典存在 INSERT=新增,本变更补齐 ADD=新增 后页面会出现两个“新增”。已在前端将 INSERT 归一展示为 ADD,在 Mapper XML 中让 operationType=ADD 兼容历史 INSERT,并新增 V1.0.15__normalize_operation_type_add_dict.sql 迁移历史日志和字典。迁移脚本避开 sys_dict_data(tenant_id, dict_type, dict_value) 唯一键冲突:有 ADD 时禁用 INSERT,无 ADD 时才将 INSERT 改为 ADDgit diff --check、Flyway 占位符扫描、xmllint --nooutmvn -q -pl forge-admin-server -am compile -DskipTestspnpm --dir forge-admin-ui build 已通过;未启动 MySQL 实跑 Flyway。

13. 确认记录(HARD-GATE)

  • 确认时间:2026-07-07
  • 确认人:用户本轮明确授权“按照 SDD 开发,我睡觉了”