# ADR 0001:公告状态机与多租户平台公告方案 > 最后更新日期:2025-12-20 ## Context 公告模块需要支持草稿、发布、撤销等完整生命周期,且平台与租户公告必须在同一数据模型中统一管理。同时要支持并发更新与审计追踪,避免已发布公告被“悄然修改”引发合规风险。 ## Decision 1. 使用 `Status` 枚举替代 `IsActive` 布尔值作为主状态字段(Draft / Published / Revoked)。 2. `Published` 状态不可变:已发布公告不允许编辑,需先撤销再重新发布。 3. 使用 `TenantId = 0` 表示平台公告,统一在 `tenant_announcements` 表中存储。 4. 使用 `RowVersion` 字段进行乐观并发控制。 ```csharp public enum AnnouncementStatus { Draft = 0, Published = 1, Revoked = 2 } ``` ```mermaid stateDiagram-v2 [*] --> Draft Draft --> Published: publish Published --> Revoked: revoke Revoked --> Published: republish ``` ## Consequences - **优点**: - 状态语义清晰,支持审计与合规追踪。 - 平台与租户公告统一查询与筛选逻辑(`TenantId IN (current, 0)`)。 - `RowVersion` 能防止并发覆盖更新。 - **代价**: - 需要迁移与兼容历史 `IsActive` 字段。 - 已发布公告不可编辑,操作流程增加一步(撤销后重发)。 ## Alternatives Considered 1. **继续使用 `IsActive`** - 问题:无法表达撤销、草稿等状态,审计语义不足。 2. **平台公告单独表** - 问题:跨表查询复杂,重复实现过滤与排序。 3. **使用悲观锁或数据库触发器** - 问题:增加数据库负担,难以跨服务扩展。 > 该 ADR 对应迁移:`20251220160000_AddTenantAnnouncementStatusAndPublisher`。