Files
TakeoutSaaS.AdminApi/docs/api/announcements-api.md
MSuMshk 857f776447 feat: 实现完整的多租户公告管理系统
核心功能:
- 公告状态机(草稿/已发布/已撤销)支持发布、撤销和重新发布
- 发布者范围区分平台级和租户级公告
- 目标受众定向推送(全部租户/指定角色/指定用户)
- 平台管理、租户管理和应用端查询API
- 已读/未读管理和未读统计

技术实现:
- CQRS+DDD架构,清晰的领域边界和事件驱动
- 查询性能优化:数据库端排序和限制,估算策略减少内存占用
- 并发控制:修复RowVersion配置(IsRowVersion→IsConcurrencyToken)
- 完整的FluentValidation验证器和输入保护

测试验证:
- 36个测试全部通过(27单元+9集成)
- 性能测试达标(1000条数据<5秒)
- 代码质量评级A(优秀)

文档:
- 完整的ADR、API文档和迁移指南
- 交付报告和技术债务记录
2025-12-20 19:57:09 +08:00

8.7 KiB
Raw Blame History

公告管理 API 文档

最后更新日期2025-12-20

本文档覆盖公告管理相关 API包括平台公告、租户公告管理端接口以及应用端已认证用户接口。

统一约定

  • 认证方式:Authorization: Bearer <JWT>
  • 时间字段均为 UTCISO 8601
  • 雪花 ID 以字符串形式序列化返回。
  • 统一响应结构:ApiResponse<T>
{
  "success": true,
  "code": 200,
  "message": "操作成功",
  "data": {},
  "errors": null,
  "traceId": "01JH...",
  "timestamp": "2025-12-20T12:00:00Z"
}

分页结构:

{
  "items": [],
  "page": 1,
  "pageSize": 20,
  "totalCount": 0,
  "totalPages": 0
}

关键枚举与字段

  • AnnouncementStatusDraft(0)Published(1)Revoked(2)
  • TenantAnnouncementTypeSystem(0)Billing(1)Operation(2)SYSTEM_PLATFORM_UPDATE(3)SYSTEM_SECURITY_NOTICE(4)SYSTEM_COMPLIANCE(5)TENANT_INTERNAL(6)TENANT_FINANCE(7)TENANT_OPERATION(8)
  • PublisherScopePlatform(0)Tenant(1)(只读字段)
  • RowVersion并发控制字段Base64 字符串)。

目标受众TargetType / TargetParameters

系统使用 TargetType(不区分大小写)+ TargetParameters(JSON) 过滤可见公告:

  • ALL_TENANTS:平台全量(可带约束)
  • TENANT_ALL:单租户全量
  • SPECIFIC_TENANTS
  • USERS / SPECIFIC_USERS / USER_IDS
  • ROLES / ROLE
  • PERMISSIONS / PERMISSION
  • MERCHANTS / MERCHANT_IDS

TargetParameters 示例:

{
  "tenantIds": [100000000000000001],
  "userIds": [200000000000000001],
  "merchantIds": [300000000000000001],
  "roles": ["OpsManager"],
  "permissions": ["tenant-announcement:read"],
  "departments": ["NorthRegion"]
}

注意:TargetParameters 为字符串 JSON解析失败会导致公告对该用户不可见失败即隐藏

数据流(示意)

flowchart LR
  Client[客户端] --> API[API Controller]
  API --> Mediator[MediatR]
  Mediator --> Handler[Query/Command Handler]
  Handler --> Repo[Repository]
  Repo --> DB[(PostgreSQL)]

平台公告 API

路由前缀:/api/platform/announcements(无版本前缀)

1) 创建平台公告

  • 方法POST
  • 路径/api/platform/announcements
  • 权限platform-announcement:create
  • 请求体CreateTenantAnnouncementCommand
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码400 / 403

请求示例:

{
  "title": "平台升级通知",
  "content": "系统将于今晚 23:00 维护。",
  "announcementType": 0,
  "priority": 10,
  "effectiveFrom": "2025-12-20T00:00:00Z",
  "effectiveTo": null,
  "targetType": "all_tenants",
  "targetParameters": null
}

响应示例:

{
  "success": true,
  "code": 200,
  "data": {
    "id": "900123456789012345",
    "tenantId": "0",
    "title": "平台升级通知",
    "status": "Draft"
  }
}

2) 查询平台公告列表

  • 方法GET
  • 路径/api/platform/announcements
  • 权限platform-announcement:create
  • 查询参数
    • page / pageSize
    • statusDraft/Published/Revoked
    • announcementType
    • isActive
    • effectiveFrom / effectiveTo
    • onlyEffective
  • 响应ApiResponse<PagedResult<TenantAnnouncementDto>>
  • 错误码403

示例:GET /api/platform/announcements?page=1&pageSize=20&status=Published

3) 获取平台公告详情

  • 方法GET
  • 路径/api/platform/announcements/{announcementId}
  • 权限platform-announcement:create
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404

4) 更新平台公告(仅草稿)

  • 方法PUT
  • 路径/api/platform/announcements/{announcementId}
  • 权限platform-announcement:create
  • 请求体UpdateTenantAnnouncementCommand
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404 / 409

请求示例:

{
  "title": "平台升级通知(更新)",
  "content": "维护时间调整为 23:30。",
  "targetType": "all_tenants",
  "targetParameters": null,
  "rowVersion": "AAAAAAAAB9E="
}

5) 发布平台公告

  • 方法POST
  • 路径/api/platform/announcements/{announcementId}/publish
  • 权限platform-announcement:publish
  • 请求体PublishAnnouncementCommand
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404 / 409

请求示例:

{ "rowVersion": "AAAAAAAAB9E=" }

6) 撤销平台公告

  • 方法POST
  • 路径/api/platform/announcements/{announcementId}/revoke
  • 权限platform-announcement:revoke
  • 请求体RevokeAnnouncementCommand
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404 / 409

请求示例:

{ "rowVersion": "AAAAAAAAB9E=" }

租户公告管理 API管理端

路由前缀:/api/admin/v{version}/tenants/{tenantId}/announcements

1) 查询租户公告列表

  • 方法GET
  • 路径/api/admin/v1/tenants/{tenantId}/announcements
  • 权限tenant-announcement:read
  • 查询参数
    • page / pageSize
    • status / announcementType
    • isActive / effectiveFrom / effectiveTo / onlyEffective
  • 响应ApiResponse<PagedResult<TenantAnnouncementDto>>
  • 错误码403

2) 获取租户公告详情

  • 方法GET
  • 路径/api/admin/v1/tenants/{tenantId}/announcements/{announcementId}
  • 权限tenant-announcement:read
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404

3) 创建租户公告

  • 方法POST
  • 路径/api/admin/v1/tenants/{tenantId}/announcements
  • 权限tenant-announcement:create
  • 请求体CreateTenantAnnouncementCommand
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码400 / 403

请求示例:

{
  "title": "租户公告",
  "content": "新品上线提醒",
  "announcementType": 0,
  "priority": 5,
  "effectiveFrom": "2025-12-20T00:00:00Z",
  "targetType": "roles",
  "targetParameters": "{\"roles\":[\"OpsManager\"]}"
}

4) 更新租户公告(仅草稿)

  • 方法PUT
  • 路径/api/admin/v1/tenants/{tenantId}/announcements/{announcementId}
  • 权限tenant-announcement:update
  • 请求体UpdateTenantAnnouncementCommand
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404 / 409

5) 发布租户公告

  • 方法POST
  • 路径/api/admin/v1/tenants/{tenantId}/announcements/{announcementId}/publish
  • 权限tenant-announcement:publish
  • 请求体PublishAnnouncementCommand
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404 / 409

6) 撤销租户公告

  • 方法POST
  • 路径/api/admin/v1/tenants/{tenantId}/announcements/{announcementId}/revoke
  • 权限tenant-announcement:revoke
  • 请求体RevokeAnnouncementCommand
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404 / 409

7) 删除租户公告

  • 方法DELETE
  • 路径/api/admin/v1/tenants/{tenantId}/announcements/{announcementId}
  • 权限tenant-announcement:delete
  • 响应ApiResponse<bool>
  • 错误码403

8) 标记公告已读(兼容旧路径)

  • 方法POST
  • 路径/api/admin/v1/tenants/{tenantId}/announcements/{announcementId}/read
  • 权限tenant-announcement:read
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码403 / 404

应用端公告 API已认证用户

路由前缀:/api/app/announcements(目前挂载在 AdminApi

1) 获取可见公告列表

  • 方法GET
  • 路径/api/app/announcements
  • 权限:登录即可
  • 查询参数page / pageSize(其他筛选参数会被覆盖为已发布与有效期内)
  • 响应ApiResponse<PagedResult<TenantAnnouncementDto>>
  • 错误码401

2) 获取未读公告列表

  • 方法GET
  • 路径/api/app/announcements/unread
  • 权限:登录即可
  • 查询参数page / pageSize
  • 响应ApiResponse<PagedResult<TenantAnnouncementDto>>
  • 错误码401

3) 标记公告已读

  • 方法POST
  • 路径/api/app/announcements/{announcementId}/mark-read
  • 权限:登录即可
  • 请求体:无
  • 响应ApiResponse<TenantAnnouncementDto>
  • 错误码401 / 404

常见错误码

  • 400:参数验证失败
  • 401:未认证
  • 403:无权限
  • 404:公告不存在或不可见
  • 409:状态冲突(例如已发布不可编辑)

提示:实际错误码与消息由 BusinessException 和中间件统一返回。