feat(套餐真流量预警): AUG26-004 真流量预警规则、达量扫描通知与导出

新增 000228 迁移:规则表 tb_package_traffic_alert_rule(每套餐商品至多一条,无软删除,package_id
非部分唯一约束)、达量预警快照表 tb_package_traffic_alert(以主套餐使用记录 + 阈值快照为唯一键,
触发时冻结用量、额度、比例、阈值、到期时间、归属与资产快照),并为 tb_package_usage 新增扫描
范围部分索引 idx_package_usage_alert_scope;down 在预警表存在数据时阻断回滚。

新增规则维护接口 GET/POST/PUT /api/admin/package-traffic-alert-rules(仅超级管理员与平台账号):
创建校验套餐存在且真流量额度大于零,阈值为 1%~100% 的两位小数;修改只影响后续扫描,不回填也
不改写既有预警快照;全部写操作记录操作者、前后值与时间。

新增每日 06:00(Asia/Shanghai)扫描任务 package:traffic:alert:scan,与套餐临期扫描共用 data_cleanup
队列:按资产汇总当前有效套餐的真流量,分子取使用记录真已用量、分母取使用记录真总量快照,命中
主套餐规则阈值时在同一事务创建预警与可靠通知事件;重复执行以唯一冲突视为已处理,不重复投递,
不建停机锁、不调用运营商。

新增预警列表、详情与异步导出 GET /api/admin/package-traffic-alerts、GET /api/admin/package-traffic-alerts/:id、
POST /api/admin/package-traffic-alerts/export,列表与详情一律读冻结快照;新增通知类型
package.traffic.alert 与受控目标 package_traffic_alert_detail,目标解析仅对超级管理员与平台账号
返回可跳转,越权与不存在统一按资源不可见处理。

同步 OpenAPI(cmd/gendocs、cmd/api/docs.go、pkg/openapi/handlers.go)、审计动作与资源注册、上下文
健康检查证据;归档变更并同步 package-traffic-alert 主 Spec。
This commit is contained in:
2026-09-16 17:05:55 +08:00
parent ef4d3696d4
commit d5bcda94fe
46 changed files with 3679 additions and 100 deletions

View File

@@ -11,7 +11,7 @@ type NotificationUnreadCountResponse struct {
// NotificationListRequest 是后台通知基础分页参数。
type NotificationListRequest struct {
Category string `json:"category" query:"category" validate:"omitempty,oneof=approval expiry sync system" enums:"approval,expiry,sync,system" description:"通知类别 (approval:审批, expiry:临期, sync:同步, system:系统)"`
Type string `json:"type" query:"type" validate:"omitempty,oneof=system.notice package.expiring agent.recharge.completed refund.completed exchange.shipping.created agent.main_wallet.low_balance h5.popup.risk_exchange h5.popup.operation" enums:"system.notice,package.expiring,agent.recharge.completed,refund.completed,exchange.shipping.created,agent.main_wallet.low_balance,h5.popup.risk_exchange,h5.popup.operation" description:"稳定通知类型 (system.notice:系统通知, package.expiring:套餐临期, agent.recharge.completed:店铺充值入账, refund.completed:店铺退款完成, exchange.shipping.created:换货申请待处理, agent.main_wallet.low_balance:主钱包低余额, h5.popup.risk_exchange:风险换卡弹窗, h5.popup.operation:运营弹窗)"`
Type string `json:"type" query:"type" validate:"omitempty,oneof=system.notice package.expiring agent.recharge.completed refund.completed exchange.shipping.created agent.main_wallet.low_balance h5.popup.risk_exchange h5.popup.operation package.traffic.alert" enums:"system.notice,package.expiring,agent.recharge.completed,refund.completed,exchange.shipping.created,agent.main_wallet.low_balance,h5.popup.risk_exchange,h5.popup.operation,package.traffic.alert" description:"稳定通知类型 (system.notice:系统通知, package.expiring:套餐临期, agent.recharge.completed:店铺充值入账, refund.completed:店铺退款完成, exchange.shipping.created:换货申请待处理, agent.main_wallet.low_balance:主钱包低余额, h5.popup.risk_exchange:风险换卡弹窗, h5.popup.operation:运营弹窗, package.traffic.alert:套餐真流量达量预警)"`
Severity string `json:"severity" query:"severity" validate:"omitempty,oneof=info warning error critical" enums:"info,warning,error,critical" description:"通知级别 (info:提示, warning:警告, error:错误, critical:严重)"`
IsRead *bool `json:"is_read" query:"is_read" description:"已读状态;不传时查询全部"`
Page int `json:"page" query:"page" validate:"omitempty,min=1,max=10000" minimum:"1" maximum:"10000" description:"页码,默认 1最大 10000"`
@@ -22,11 +22,11 @@ type NotificationListRequest struct {
type NotificationItem struct {
ID uint `json:"id" description:"通知ID"`
Category string `json:"category" enums:"approval,expiry,sync,system" description:"通知类别 (approval:审批, expiry:临期, sync:同步, system:系统)"`
Type string `json:"type" enums:"system.notice,package.expiring,agent.recharge.completed,refund.completed,exchange.shipping.created,agent.main_wallet.low_balance,h5.popup.risk_exchange,h5.popup.operation" description:"稳定通知类型 (system.notice:系统通知, package.expiring:套餐临期, agent.recharge.completed:店铺充值入账, refund.completed:店铺退款完成, exchange.shipping.created:换货申请待处理, agent.main_wallet.low_balance:主钱包低余额, h5.popup.risk_exchange:风险换卡弹窗, h5.popup.operation:运营弹窗)"`
Type string `json:"type" enums:"system.notice,package.expiring,agent.recharge.completed,refund.completed,exchange.shipping.created,agent.main_wallet.low_balance,h5.popup.risk_exchange,h5.popup.operation,package.traffic.alert" description:"稳定通知类型 (system.notice:系统通知, package.expiring:套餐临期, agent.recharge.completed:店铺充值入账, refund.completed:店铺退款完成, exchange.shipping.created:换货申请待处理, agent.main_wallet.low_balance:主钱包低余额, h5.popup.risk_exchange:风险换卡弹窗, h5.popup.operation:运营弹窗, package.traffic.alert:套餐真流量达量预警)"`
Severity string `json:"severity" enums:"info,warning,error,critical" description:"通知级别 (info:提示, warning:警告, error:错误, critical:严重)"`
Title string `json:"title" description:"纯文本标题"`
Body string `json:"body" description:"纯文本正文"`
RefType string `json:"ref_type" description:"受控资源类型可能为空。可选值及含义system_config:系统配置, integration_log:外部集成日志, package:套餐, asset:C端资产, refund:退款, agent_recharge:代理充值, wecom_approval:企微审批, iot_card:物联网卡, device:设备, expiring_asset:临期资产列表, shop_fund:店铺资金概况, card_sync:卡同步记录。后台点击通知应调用目标解析接口,不得直接拼接路由"`
RefType string `json:"ref_type" description:"受控资源类型可能为空。可选值及含义system_config:系统配置, integration_log:外部集成日志, package:套餐, asset:C端资产, refund:退款, agent_recharge:代理充值, wecom_approval:企微审批, iot_card:物联网卡, device:设备, expiring_asset:临期资产列表, shop_fund:店铺资金概况, card_sync:卡同步记录, package_traffic_alert:套餐真流量达量预警。后台点击通知应调用目标解析接口,不得直接拼接路由"`
RefID string `json:"ref_id" description:"受控资源数字ID的十进制字符串可能为空。refund、agent_recharge、wecom_approval、iot_card、device、expiring_asset、shop_fund、asset 等类型使用仅用于资源定位不是前端URL"`
RefKey string `json:"ref_key" description:"受控资源稳定Key或展示快照可能为空。system_config 为配置Keyintegration_log/card_sync 为集成标识asset 为资产标识快照仅用于定位或展示不是前端URL"`
IsRead bool `json:"is_read" description:"是否已读"`
@@ -65,7 +65,7 @@ type NotificationReadResponse struct {
// NotificationTargetResponse 是通知受控目标解析结果,不包含任意 URL。
type NotificationTargetResponse struct {
TargetType string `json:"target_type" description:"前端白名单目标类型空表示不支持跳转。可选值refund_detail、agent_recharge_detail、wecom_approval_detail、iot_card_detail、device_detail、expiring_asset_list、shop_fund_summary、integration_log、system_config"`
TargetType string `json:"target_type" description:"前端白名单目标类型空表示不支持跳转。可选值refund_detail、agent_recharge_detail、wecom_approval_detail、iot_card_detail、device_detail、expiring_asset_list、shop_fund_summary、integration_log、system_config、package_traffic_alert_detail"`
TargetID *uint `json:"target_id,omitempty" description:"ID型目标的业务主键前端按 target_type 映射受控页面不得自行拼接任意URL"`
TargetKey string `json:"target_key,omitempty" description:"Key型目标的稳定定位值仅用于 integration_log 或 system_config 等白名单目标"`
Available bool `json:"available" description:"当前账号是否仍可访问目标false 时只展示通知正文,不执行跳转"`