# 公告状态迁移说明

> 最后更新日期：2025-12-20

本文档说明公告状态相关迁移的目的、数据变化与回滚策略。

## 迁移列表

1. `20251220160000_AddTenantAnnouncementStatusAndPublisher.cs`
2. `20251220183000_GrantAnnouncementPermissionsToSuperAdmin.cs`

## 迁移目的

- 引入公告状态机（`Status`）与发布者信息（`PublisherScope/PublisherUserId`）。
- 增加目标受众字段（`TargetType/TargetParameters`）。
- 增加 `RowVersion` 以支持乐观并发。
- 预置公告相关权限到超级管理员角色。

## 数据结构变化

### 迁移前（tenant_announcements）

| 字段 | 说明 |
| --- | --- |
| `IsActive` | 是否启用（旧字段） |
| `EffectiveFrom` / `EffectiveTo` | 生效区间 |
| 其他基础字段 | 标题、内容、类型等 |

### 迁移后（新增字段）

| 字段 | 说明 |
| --- | --- |
| `Status` | 公告状态（Draft/Published/Revoked） |
| `PublisherScope` | 发布者范围（Platform/Tenant） |
| `PublisherUserId` | 发布者用户 ID |
| `PublishedAt` / `RevokedAt` | 实际发布时间/撤销时间 |
| `ScheduledPublishAt` | 预定发布时间（暂未使用） |
| `TargetType` / `TargetParameters` | 目标受众筛选 |
| `RowVersion` | 并发控制版本 |

### 索引新增

- `IX_tenant_announcements_TenantId_Status_EffectiveFrom`
- `IX_tenant_announcements_Status_EffectiveFrom_Platform`（TenantId=0）

## 数据迁移逻辑

迁移中将历史 `IsActive` 映射到 `Status`：

```sql
UPDATE tenant_announcements
SET "Status" = CASE WHEN "IsActive" THEN 1 ELSE 0 END;
```

## 权限迁移逻辑

迁移会为以下角色自动授予公告相关权限：

- `super-admin`
- `SUPER_ADMIN`
- `PlatformAdmin`
- `platform-admin`

并插入权限码：
`platform-announcement:create`、`platform-announcement:publish`、`platform-announcement:revoke`、
`tenant-announcement:publish`、`tenant-announcement:revoke`。

## 回滚策略

1. **应用数据库（公告表）**
   - 回滚到迁移前版本：
     ```bash
     dotnet ef database update <上一个迁移>
     ```
   - 删除新增字段与索引（由 `Down` 执行）。

2. **身份数据库（权限）**
   - 回滚迁移后，权限仅从 `role_permissions` 中删除，`permissions` 记录保留（符合当前 Down 逻辑）。

## 数据修复脚本（回滚后）

如需恢复旧逻辑，可手动同步 `IsActive`：

```sql
UPDATE tenant_announcements
SET "IsActive" = CASE WHEN "Status" = 1 THEN TRUE ELSE FALSE END;
```

```mermaid
flowchart TD
  Start[备份数据库] --> M1[执行迁移 20251220160000]
  M1 --> M2[执行迁移 20251220183000]
  M2 --> Check[验证状态/权限]
  Check -->|失败| Rollback[回滚并修复数据]
  Check -->|成功| Done[发布]
```

> 建议在生产环境迁移前进行全量备份，并在灰度环境验证数据一致性。
