核心功能: - 公告状态机(草稿/已发布/已撤销)支持发布、撤销和重新发布 - 发布者范围区分平台级和租户级公告 - 目标受众定向推送(全部租户/指定角色/指定用户) - 平台管理、租户管理和应用端查询API - 已读/未读管理和未读统计 技术实现: - CQRS+DDD架构,清晰的领域边界和事件驱动 - 查询性能优化:数据库端排序和限制,估算策略减少内存占用 - 并发控制:修复RowVersion配置(IsRowVersion→IsConcurrencyToken) - 完整的FluentValidation验证器和输入保护 测试验证: - 36个测试全部通过(27单元+9集成) - 性能测试达标(1000条数据<5秒) - 代码质量评级A(优秀) 文档: - 完整的ADR、API文档和迁移指南 - 交付报告和技术债务记录
8.7 KiB
8.7 KiB
公告管理 API 文档
最后更新日期:2025-12-20
本文档覆盖公告管理相关 API,包括平台公告、租户公告管理端接口,以及应用端(已认证用户)接口。
统一约定
- 认证方式:
Authorization: Bearer <JWT> - 时间字段均为 UTC(ISO 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
}
关键枚举与字段
AnnouncementStatus:Draft(0)、Published(1)、Revoked(2)TenantAnnouncementType:System(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)PublisherScope:Platform(0)、Tenant(1)(只读字段)RowVersion:并发控制字段(Base64 字符串)。
目标受众(TargetType / TargetParameters)
系统使用 TargetType(不区分大小写)+ TargetParameters(JSON) 过滤可见公告:
ALL_TENANTS:平台全量(可带约束)TENANT_ALL:单租户全量SPECIFIC_TENANTSUSERS/SPECIFIC_USERS/USER_IDSROLES/ROLEPERMISSIONS/PERMISSIONMERCHANTS/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/pageSizestatus(Draft/Published/Revoked)announcementTypeisActiveeffectiveFrom/effectiveToonlyEffective
- 响应:
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/pageSizestatus/announcementTypeisActive/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和中间件统一返回。