service.xpcool.com/docs/change-log/2026-09-14.md
夏犀麟 e79690518e
Some checks failed
Build and Deploy (service.xpcool.com) / build-and-deploy (push) Failing after 54s
fix(notice): 修复通知历史状态回填与配置占位符问题
- 修正 status 列默认值为 0,避免历史失败记录被误标为成功
- 历史数据回填改为幂等更新,可重复执行
- 过滤未解析的 ${...} 配置占位符,优化 Bark 推送错误提示
- LogDetail 记录不存在时统一返回参数错误,避免暴露 SQL 细节
2026-09-14 23:53:56 +08:00

7.5 KiB
Raw Blame History

变更日志 — 2026-09-14

请求

通知模块新增「通知历史记录」表格界面:有分页、有查询,记录每次通知的渠道、类型、分组、详细内容等。 前端项目 E:\Project\admin.xpcool.com 一起实现并联调。

变更

后端 —— 通知历史记录能力扩展

  • api/notice/notice.go — 通知历史记录契约扩展:
    • NoticeLogItem 由 11 字段扩到 27 字段(新增 batchId/ruleName/eventName/noticeType/typeName/ group/groupName/channelName/userName/status/statusName/retryCount/durationMs/source/remark)。
    • NoticeLogListReq 新增 keyword/noticeType/group/userId/batchId/status/orderBy/orderDir NoticeLogListRes 新增 stats 统计概览。
    • 新增端点:POST /notice/log/detail(详情)、/notice/log/delete(批量删除)、 /notice/log/clear(按保留天数/时间范围清空)、/notice/log/options(字典选项)。
  • internal/model/dto/notice_meta.go新增)— 通知字典渠道bark/pushplus/webhook/email/internal、 事件7 种、类型job/security/recruit/test/manual/system、分组auto_job/server/recruitment/system 的编码常量 + 中文名映射 + 选项下发 + 事件/类型/分组三级推导函数。
  • internal/model/dto/notice.goNoticeLogVO/NoticeLogFilter 同步扩展,并新增 Normalize() 归一化分页/排序(Status 与兼容字段 Result 的优先级合并)。
  • internal/model/entity/notice.gointernal/model/do/notice.goNoticeLog 新增 batch_id/status/retry_count/duration_ms/source/remark 六个字段。
  • internal/service/notice/notice.go
    • LogList:重写为多维筛选(关键字/类型/分组/事件/渠道/接收人/批次/状态/时间范围/排序)+ 统计概览, 列表与统计共用同一套 logQuery 条件保证口径一致;批量补齐规则名与接收人(避免 N+1
    • 新增 LogDetail/LogDelete/LogClear
    • Send 引入 batchId(同一次业务触发的多条投递共用);deliver/Test 记录耗时、来源、状态、备注。
    • 写库统一改用 do.NoticeLog / do.NoticeRule / do.NoticeChannel(原先用 map[string]interface{} 不符合 AGENTS.md「数据库操作必须用 DO 对象」)。
  • internal/controller/notice/notice.go — 新增 LogDetail/LogDelete/LogClear/MetaOptions 并抽出 toLogItem/toMetaItems 做 dto → 契约转换。
  • manifest/sql/017_notice_log_enhance.sql新增)— notice_log 加 6 列 + 3 个索引; 按旧字段 result 回填 status;菜单 982 改名「通知历史」;新增 5 条 type=2 接口权限 notice:log:list/detail/delete/clear/options);超管角色绑定。

前端 —— E:\Project\admin.xpcool.com

  • apps/web-tdesign/src/api/notice.ts — 通知历史记录 API 客户端:类型与查询参数扩展, 新增 getNoticeLogDetail / deleteNoticeLog / clearNoticeLog / getNoticeMetaOptions 以及 NOTICE_STATUS_OPTIONS / noticeStatusTheme 等展示辅助。
  • apps/web-tdesign/src/views/system/notice/log/index.vue重写为完整「通知历史」页面:
    • 顶部 4 张统计卡(总数/成功/失败/成功率),随筛选条件同步刷新;
    • 筛选区 9 个条件(时间范围、关键字、分组、类型、事件、渠道、接收人、状态、排序);
    • vxe 表格:多选列 + 通知时间/分组/类型/事件/渠道/接收人/标题/详细内容/结果/耗时/错误 + 行操作;
    • 详情抽屉(基本信息 + 标题/内容/目标/错误分区展示,均支持一键复制);
    • 批量删除、清空历史(可选「保留最近 N 天」);按权限码控制按钮显隐。

联调

  • 本地库执行 017_notice_log_enhance.sqlnotice_log 现 17 列、3 个新索引; 菜单 982 / 9821-9825 就位14 条历史失败记录 status 正确回填为 2。
  • 后端 5 个新接口 + 原有 list 全部通过 RBAC 权限映射,返回 code=0
  • 真实投递一条测试通知,验证 batchId / durationMs / source / userName / target / remark 六项新字段正确落库与回显;统计概览 1/0/1 与筛选条件联动正确。
  • 经前端 Vite 代理20100 → 10100完整跑通 登录 → 字典选项 → 分页列表 → 详情。
  • 前端 vue-tsc 类型检查、oxfmt 格式检查、oxlint 全部 0 错误。
  • 联调中修复 1 个缺陷LogDetail 对不存在的 ID 会把 sql.ErrNoRows 包装上抛, 被 gf 归为内部错误 code=50 并回显 SQL 细节;改为与项目既有写法一致 (忽略 Scan 错误、以 Id==0 判定),现返回 code=10001「通知记录不存在」。

决策与理由

  • 类型/分组不落库,由 event_type 派生:二者与事件是一对多的确定映射,落库会引入双写不一致; 改为只存事件编码,展示与筛选在服务层推导(NoticeEventToType / NoticeTypeToGroup)。
  • status 与旧的 result 并存result 是已有数据在用的字段1成功/0失败直接改语义会破坏历史数据。 新增 status0待发送/1成功/2失败表达三态查询时用 (status=1 OR (status=0 AND result=1)) 兼容历史行。
  • 字典选项由后端 /notice/log/options 统一下发:前端原先把事件类型硬编码在页面里 NOTICE_EVENT_OPTIONS 只有 4 项,且与 notice_rule.event_type 种子语义有偏差), 新增事件就要改两处;改为后端单一事实源,前端只做渲染。
  • 清空提供「保留最近 N 天」而非纯全清:历史记录是排查问题的依据,全清不可逆; 默认保留 30 天,keepDays=0 才真正全清,属于对误操作的兜底。
  • 列表与统计共用 logQuery:避免"列表按分组筛选、统计按全量"这类口径不一致, 前端统计卡与表格永远对同一批数据。
  • 迁移脚本中 status 默认值取 0 而非 1ALTER TABLE ADD COLUMN ... DEFAULT 1 会把所有历史行 一并置为 1含失败记录造成"历史失败记录显示成功"。改为默认 0 后按 result 回填,语义正确且可重跑。
  • 提示文案与枚举中文名收口到 dto:中文名映射只在 notice_meta.go 定义一次, API、服务、前端展示三处复用避免同义词漂移。

待办与风险

  • ⚠️ internal/service/recruitment/noise_test.go 是 0 字节空文件(未跟踪),会让 go build ./...go test ./... 直接报 expected 'package', found 'EOF'。 本次联调为编译通过曾临时移走,已原样还原;需删除该文件或补上包声明。
  • ⚠️ 工作区另有他人未提交改动:internal/service/recruitment/bark.go 修改、 live_diag_test.gotestdata/rszk.html 删除;前端 api/wallpaper.tsviews/wallpaper/* 处于暂存状态。均非本次范围。
  • 手动「测试发送」在目标凭据为空时会直接返回参数错误、不写历史记录(沿用原有行为)。 若希望失败尝试也可追溯,需在 Test 的提前返回分支补记日志。
  • 历史记录只增不减,长期需要定期清理策略(目前靠页面「清空」手动处理), 后续可考虑挂到 auto_job 定时任务上。
  • 本地联调环境Node 22.22.2 + corepack pnpm@11.16.0;后端 10100、前端 dev 20100 前端 vite.config.ts 已把 /api/service 代理到 http://localhost:10100