update
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 10m49s

This commit is contained in:
2026-09-03 09:28:28 +08:00
parent dbfeeee253
commit 370fd3e67f
150 changed files with 64402 additions and 247 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-08-31

View File

@@ -0,0 +1,33 @@
## Context
个人客户通知已有隔离、已读和投递能力,物流换货已有状态机。弹窗配置不能替代通知事实,风险换卡不能另建待处理记录。
## Decisions
- 新增运营弹窗配置及版本/投放去重事实;候选查询在同一资产上下文计算风险优先级和配置匹配,创建/复用个人通知。
- 风险地址提交以客户+旧资产唯一约束和事务创建物流换货单,地址写入换货单而不单独建表。
- 频率去重使用客户、配置版本、资产/日期键;通知内容冻结在投放时,已读复用现有服务。
- 后台仅管理配置,不得写任意 URLH5 只接收受控目标类型。
## 后台与 H5 动作契约
### 运营弹窗配置
- `POST /h5-popup-configurations`:仅超级管理员、平台用户。请求 `title`1100 字符)、`content`12000 字符)、`starts_at``ends_at``enabled``priority``pages`(首页/资产详情/套餐购买/资产钱包充值)、可选店铺/设备类型/卡类型集合、`frequency``once`/`daily`)和可选 `action_type``package_purchase`/`asset_wallet_recharge`)。结束时间不得早于开始时间;不接受 URL、前端路由或任意动作参数。
- `PUT /h5-popup-configurations/:id` 更新时递增配置版本;旧版本通知不改写。`POST /:id/enable``/disable` 仅影响后续候选;全部成功写操作记录操作者、前后值、版本和时间。
### H5 候选查询与风险换卡
- `GET /api/c/v1/popup-candidates`:当前个人客户必须提交 `page` 和当前资产标识;首页也必须先由客户选定当前资产。服务校验该资产属于当前客户或其既有授权范围,否则按资源不可见返回。
- 查询先判断广电卡、运营商扩展状态风险停机、无活动物流换货单、未提交风险地址和“客户+资产+上海自然日”未展示;命中时创建/复用风险通知并只返回风险换卡候选。关闭或稍后处理只调用既有通知已读,不修改风险资格,次日允许再次投放。
- 未命中风险时,按当前时间、启用状态、页面、店铺/设备类型/卡类型范围和频率匹配运营配置;同维度多值取任一命中,无配置即全量。只返回优先级最高一条,同优先级取最近更新时间;以客户、配置版本、资产、日期/一次性键创建或复用通知。
### 风险地址提交与通知读取
- `POST /api/c/v1/risk-exchanges/:asset_id/address`:当前个人客户提交 `recipient_name``recipient_phone``recipient_address`;均必填且沿用既有换货地址字段长度校验。事务中锁定客户和旧资产,复核风险资格,以客户+旧资产唯一约束创建物流换货单,`migrate_data=false`;重复提交返回首次创建的换货单与首次地址,禁止覆盖。
- 弹窗通知内容、配置版本、资产和受控动作在投放时冻结并写个人站内通知,保留 90 天。候选查询不标记已读;关闭、点击受控操作、进入通知详情仅通过既有 `PUT /api/c/v1/notifications/:id/read` 幂等标记当前客户自己的通知。
- 通知受控操作只返回类型与资产关联,不返回 URL前端按白名单映射页面。客户读取他人通知或不属于其资产的风险换卡均按既有隔离规则不可见。
## Migration Plan
新增成对迁移和索引;隔离库验证风险条件、每日限制、地址幂等、优先级、版本重投、范围匹配、通知隔离及 up/down/up。

View File

@@ -0,0 +1,25 @@
## Scope
- 迭代编号:`AUG26-007`
## Why
风险停机客户需在 H5 自助留下换卡地址,运营也需可控的资产定向弹窗;两者都必须保留投放事实且不预生成无访问客户的通知。
## What Changes
- 新增风险换卡候选与地址提交,幂等创建物流换货单。
- 新增运营弹窗配置、范围/优先级/频率/版本投放和受控动作。
- 复用个人客户通知保存快照、已读和 90 天历史。
## Capabilities
### New Capabilities
- `h5-popup-notification`: H5 风险换卡和运营弹窗。
### Modified Capabilities
- 无。
## Impact
影响 H5、个人通知、资产/换货查询、后台配置、审计和 Schema。

View File

@@ -0,0 +1,30 @@
## Purpose
在客户实际访问 H5 时,按当前资产事实投放风险换卡或运营弹窗,并将投放内容作为个人客户通知留存,避免预生成通知或开放任意跳转链接。
## ADDED Requirements
### Requirement: 风险换卡候选与地址提交
系统 SHALL 仅在当前 H5 客户访问的资产为广电卡、运营商扩展状态为风险停机、且不存在待填写信息、待发货、已发货待确认或已完成物流换货单时返回风险换卡弹窗。同一客户同一资产每天至多展示一次;稍后处理仅抑制当天,次日仍可命中。风险换卡优先级固定高于运营弹窗。
客户提交收货人姓名、收货手机号和完整地址文本后,系统 MUST 幂等创建关联旧资产的物流换货单;首次地址锁定,客户不得修改。自动换货单不预设业务数据迁移,发货选择新资产时仍由后台按既有换货流程决定。风险条件不再成立或地址已提交后停止新投放,已投放通知保留 90 天。
#### Scenario: 重复提交风险地址
- **WHEN** 客户对同一风险资产重复提交收货地址
- **THEN** 系统保留首次地址和唯一物流换货单,不创建第二张换货单
### Requirement: 运营弹窗实时匹配
系统 SHALL 允许超级管理员和平台用户管理全局运营弹窗的标题、内容、有效期、启停、优先级、店铺/设备类型/卡类型范围、四种页面首页、资产详情、套餐购买、资产钱包充值、频率和一个可选受控操作。范围同一维度多选为任一匹配未配置范围即全量H5 请求必须携带当前页面资产标识,首页使用当前选中资产。操作仅可为套餐购买或资产钱包充值,不得配置任意 URL。
运营弹窗仅在客户请求候选时实时匹配并创建或复用通知;每客户每配置支持仅一次或每天一次。候选只返回优先级最高一条,同优先级取最近更新时间最新;配置修改形成新版本,既有通知保留快照,修改后的仅一次配置可向原命中客户重新投放。配置到期/停用停止新投放,历史通知保留 90 天。
#### Scenario: 风险与运营候选同时命中
- **WHEN** 当前资产同时满足风险换卡和多个运营弹窗条件
- **THEN** 系统仅返回风险换卡候选,并保持通知未读
### Requirement: 通知留存与已读
弹窗投放 SHALL 复用个人客户站内通知,保存投放时内容、配置版本、资产和受控操作快照,并同时出现在通知列表。创建或返回候选不得自动已读;客户关闭、点击操作或进入通知详情后通过既有已读接口幂等标记已读。通知读取必须维持个人客户隔离。
#### Scenario: 关闭弹窗
- **WHEN** 当前个人客户关闭其未读弹窗
- **THEN** 系统仅标记该客户该通知已读,不影响其他客户或未来符合条件的投放

View File

@@ -0,0 +1,13 @@
## 1. 数据与配置
- [ ] 1.1 追踪个人通知、资产风险状态、物流换货、H5 认证和既有已读链路。
- [ ] 1.2 新增弹窗配置、版本/投放去重所需成对迁移、模型、范围和索引。
- [ ] 1.3 实现管理端配置 CRUD、启停、受控页面/动作/频率校验和审计。
## 2. H5 行为
- [ ] 2.1 实现携带资产标识的候选接口:风险条件、每日限制、运营范围/优先级/版本匹配和个人通知创建/复用。
- [ ] 2.2 实现风险地址提交、唯一物流换货单创建、首次地址锁定及数据迁移默认边界。
- [ ] 2.3 接入既有个人通知列表和已读,注册路由/OpenAPI。
## 3. 验证
- [ ] 3.1 隔离库验证风险/运营优先级、频率、范围、版本、地址重复提交、通知隔离及迁移 up/down/up。
- [ ] 3.2 运行 `gofmt -w``go build ./cmd/api ./cmd/worker``go run cmd/gendocs/main.go``openspec validate add-h5-risk-exchange-notifications --strict``openspec doctor --json`;自动化测试按项目决策为 N/A。