diff --git a/docs/plans/2026-09-28-广告位轮播-设计方案.md b/docs/plans/2026-09-28-广告位轮播-设计方案.md index 1100257..18ab470 100644 --- a/docs/plans/2026-09-28-广告位轮播-设计方案.md +++ b/docs/plans/2026-09-28-广告位轮播-设计方案.md @@ -64,6 +64,7 @@ model ads_ov { sortOrder Int albumIds Json? entityVersion Int + createdAt DateTime @db.DateTime(6) // 排序 tie-break(§5.2:sortOrder 并列时按它稳定排序) updatedAt DateTime @db.DateTime(6) } ``` @@ -80,7 +81,8 @@ model ads_ov { staging 键 `photo-live/{env}/ads/staging/{cuid}.{ext}`(presignPut 现签)。 2. 客户端 PUT 直传 OSS(裸 fetch,Content-Type 与申明一致)。 3. `POST /v1/admin/ads` / `PATCH /v1/admin/ads/{id}` 携带 `imageStagingKey`: - 服务端同事务内 `head()` 核验(存在 + bytes 一致)→ `copyIfAbsent()` 到终键 + 服务端同事务内 `head()` 核验(存在 + bytes + contentType 与申明一致,banner + complete 同口径)→ `copyIfAbsent()` 到终键 `ads/{adId}.{ext}`(禁止覆盖语义天然防重复)→ 落库 + 写 outbox。 编辑换图:新终键生效,旧终键对象不回收(OSS 生命周期兜底,与 banner 流同款)。 @@ -91,11 +93,11 @@ model ads_ov { | 环节 | 改动 | 模板 | | --- | --- | --- | -| 契约 events.ts | type 联合加 `'ad.updated' \| 'ad.deleted'`;`AdUpdatedPayload`(全量快照:adId/imageObjectKey/linkUrl/enabled/sortOrder/albumIds/entityVersion);`isTombstoneOutboxType` 加 ad.deleted | category.* | -| outbox 写入 | albumId 列 NOT NULL,**全局广告无相册 → 写空串 `''`**(约定登记;不动账本表结构) | — | +| 契约 events.ts | type 联合加 `'ad.updated' \| 'ad.deleted'`;`AdUpdatedPayload`(全量快照:adId/imageObjectKey/linkUrl/enabled/sortOrder/albumIds/entityVersion/createdAt);`isTombstoneOutboxType` 加 ad.deleted | category.* | +| outbox 写入 | albumId 列 NOT NULL——**ad.* 事件 albumId 恒写空串 `''`(定向广告亦然,绑定关系在载荷 albumIds)**(约定登记;不动账本表结构) | — | | sender | `syncEntityTypeOfOutboxType`:ad.* → `'ad'`;entityId 从载荷 `adId` 推导 | slot-state 分支 | | 线格式 | internal-sync entityType 联合加 `'ad'` | slot-state | -| ov inbox | sync-inbox.service 加 `'ad'` 分支:tombstone→删 ads_ov;否则 upsert(eventId 幂等 + entityVersion 单调由通用逻辑承担) | slot-state→embed_slots_ov | +| ov inbox | sync-inbox.service 加 `'ad'` 分支:`tombstone ∨ enabled=false → 删 ads_ov 行`(disabled=公开不可见=无投影行,§2.2);否则 upsert(eventId 幂等 + entityVersion 单调由通用逻辑承担) | slot-state→embed_slots_ov | | 对账 | cn sync.service 对账清单加 `'ad'` 当前态清扫(albumId='';ads 全表量小) | category 分支 | ## 5. API 契约(openapi.yaml 新增,`pnpm gen` 再生类型)