Admin POST/PUT + admin.cms.write/审计;C 端 GET /home/banners;首页投影回退静态 homeFeeds;migration 000051;不碰 FeedSlot/支付/UGC。 Co-authored-by: Cursor <cursoragent@cursor.com>
113 lines
5.0 KiB
Markdown
113 lines
5.0 KiB
Markdown
# 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-banner.md)(只读基线)· [ops-content.md](ops-content.md) · [home.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`
|