Feature Spec: OpsCMS · Banner 写面(Ops · ECR-041)
Status: Active(ECR-041 Closed · Feature Complete)
Map: §7 运营后台 · Capability: OpsCMS · BC: Ops_CMS_NoUGC
Parent: WAVE0-FROZEN · Write-Wave: docs/WAVE0/WRITE_WAVE_AUTHORIZATION.md
Predecessor: ECR-024 Closed(Banner 只读)
关联:ops-banner.md(只读基线)· ops-content.md · home.md
1. 目标
让运营可 创建 / 更新 / 上下架 Banner;C 端首页对 placement=home 的 active Banner 生效;写操作鉴权 + 审计;失败可回退静态。
验证 Write-Wave 首刀闭环,不做 FeedSlot、真支付、UGC。
2. In / Out
| In |
Out |
Admin:Banner create / update / 设 active |
FeedSlot 一切写与 API |
加法权限 admin.cms.write(既有 RBAC) |
soft-delete 物理删行(system=true 禁止删) |
C 端:GET active banners(至少 placement=home) |
ScheduledPublication 写 · 外链任意 URL |
首页推荐区:API Banner 投影优先,空则回退静态 homeFeeds |
把 FeedSlot 与 Banner 合并为一 ECR |
admin_audit_logs 记录写操作 |
Crisis / Handoff / ContentSafety 写 · 真支付 · UGC |
| OpenAPI · contract_diff · integration |
新权限子系统 · 改引擎分层 |
与 homeFeeds 的关系(诚实边界)
- ECR-008 将「首页 Feeds CMS」后置;表意信息流位属 FeedSlot(ECR-025 只读,写面另 ECR)。
- 本切片:用 Banner(placement=home) 驱动首页推荐区展示(投影字段见下);不写
ops_feed_slots。
- 完整 Feeds 槽位运营(多 slot、排期)→ 后续 FeedSlot 写面 ECR。
3. Domain
| 概念 |
语义 |
Banner |
code 唯一;placement ∈ {home,explore,ask};active;system |
| 写语义 |
upsert 字段;active=false = 下架;禁止 soft-delete 列/物理删 system 行 |
| C 端投影 |
仅 active=true;按 sort_order 升序 |
首页投影映射(Banner → 原 homeFeeds 卡)
| homeFeeds 字段 |
来源 |
to |
link_path(须站内 / 相对路径) |
title |
title |
meta |
可选:无则空串或固定「运营推荐」 |
icon / tone / stat / tag |
本切片可用缺省;不扩表除非 migration 明确(默认缺省,避免 scope creep) |
4. API
Admin(既有前缀 /api/v1/admin/cms)
| Method |
Path |
权限 |
语义 |
| GET |
/banners · /banners/{id} |
admin.cms.read |
保持 ECR-024 |
| POST |
/banners |
admin.cms.write |
创建(code 唯一) |
| PUT |
/banners/{id} |
admin.cms.write |
更新 title/placement/image_url/link_path/sort_order/active |
| — |
DELETE |
— |
不做(下架用 active=false) |
校验:link_path 若非空须以 / 开头、禁 http(s):;placement 枚举;system=true 行不可改 code、不可删。
C 端
| Method |
Path |
Auth |
语义 |
| GET |
/api/v1/home/banners |
DeviceAuth(与 /home/tools 同级) |
仅 active;query placement 默认 home |
5. Permission / Audit
- Migration 授予
super_admin:admin.cms.write(加法码,非新 RBAC 模型)。
- 每次 POST/PUT 写
admin_audit_logs(actor · action · target id/code · diff 摘要)。
6. Migration
- 若仅需权限种子:
000051_ops_banner_write(以 TRACEABILITY Max+1 为准,编码时再锁)。
- 表结构:默认复用
ops_banners;本切片 不为 FeedSlot 改表。若投影缺省不够且 Human 未扩 scope,不得私自加列。
7. UI
| 端 |
行为 |
admin-h5 /cms |
Banner 列表 + 新建/编辑/上下架(只动 Banner;FeedSlot 仍只读展示可保留) |
| user-h5 首页 |
GET /home/banners → 推荐区;失败或空 → 静态 homeFeeds |
8. AC
| ID |
Then |
| AC-F-01 |
POST 合法 Banner → list/get 可见 |
| AC-F-02 |
PUT active=false → C 端 list 不含 |
| AC-F-03 |
PUT active=true + placement=home → GET /home/banners 含该项 |
| AC-F-04 |
重复 code → 4xx |
| AC-F-05 |
非法 link_path(外链)→ 4xx |
| AC-S-01 |
无 Admin → 401 |
| AC-S-02 |
仅 read 无 write → POST/PUT 403 |
| AC-A-01 |
写操作产生审计行 |
| AC-C-01 |
H5 首页:有 active home Banner 时推荐区非纯静态 |
| AC-C-02 |
API 失败时首页不白屏(回退静态) |
| AC-O-01 |
不触碰 FeedSlot 写路径 · 无 soft-delete · 无支付 |
9. Non-goals(STOP 对齐)
FeedSlot 写 · ScheduledPublication 写 · UGC · 真支付 · soft-delete · Crisis/Handoff/ContentSafety 写 · 扩大为本 ECR 合并多概念。
10. Trace
- ECR:
docs/ECR/ECR-041-banner-write.md
- BD:
docs/BACKEND_DESIGN/BD-2026-041-banner-write.md
- PRODUCT_SPEC · CONTRACT_DIFF · TEST_REPORT · CODE_REVIEW(实现阶段)
- Auth:
docs/WAVE0/WRITE_WAVE_AUTHORIZATION.md