Skip to content

通知中心

本页描述 Zenith Admin 当前通知中心实现:通知事件目录、notify() 统一派发、站内信/邮件/短信/App 推送/Webhook/聊天卡片渠道、偏好矩阵、免打扰、摘要与投递留痕。事实来源以 packages\shared\src\messagingpackages\server\src\services\messagingpackages\server\src\lib\notificationpackages\server\src\routes\messaging 为准。

模块边界

位置职责
事件与类型packages\shared\src\messaging\notification-events.tsconstants.tstypes.ts通知事件目录、渠道枚举、收件人类型、偏好/策略/派发日志契约
派发入口packages\server\src\services\messaging\notification-outbox.service.tsnotify()notifyWithin()、Outbox、补投、摘要聚合
派发引擎packages\server\src\lib\notification策略解析、免打扰/摘要/频控、渠道适配器注册与实际投递
业务渠道packages\server\src\services\messaging邮件、短信、站内信、公告、频道、客服、策略与偏好服务
HTTP 路由packages\server\src\routes\messaging/api/notification-*/api/in-app-*/api/email-*/api/sms-*/api/channels/api/announcements
前端页面packages\web\src\pages\system、聊天相关页面通知策略、偏好、模板、收件记录、频道管理、客服工作台、公告等

统一通知模型

通知中心采用“事件声明 + Outbox + 渠道适配器”的模型:

  1. 业务域只调用 notify(eventKey, input) 或在事务中调用 notifyWithin(executor, eventKey, input)
  2. eventKey 必须存在于 NOTIFICATION_EVENTS,变量形状由 TypeScript 约束。
  3. notifyWithin() 写入 notification_outbox;事务回滚时通知不会发出。
  4. 非定时通知在写入后调用 flushNotification(id) 异步派发;定时、免打扰延后与摘要行由系统任务扫描。
  5. 派发时展开为“收件人 × 渠道”,每个结论写入 notification_dispatches
  6. 单个渠道或收件人失败不影响同一事件的其他渠道/收件人。

NotificationRecipient 支持:

  • { type: 'user'; id }:管理端用户,参与偏好与免打扰。
  • { type: 'member'; id }:会员身份,参与偏好与免打扰。
  • { type: 'external'; channel; address }:外部邮箱或 Webhook 地址,不绑定账号,不读取个人偏好,只按指定渠道投递。

NotificationChannelPolicy 可通过 onlyenabledisable 调整单次派发候选渠道,常用于流程通知渠道、告警规则渠道等管理员配置场景。

事件目录

事件目录是代码中的唯一事实源,不落库;数据库只存管理员覆盖与用户偏好。事件定义包含分组、中文名、级别、默认渠道、可选渠道、必达、免打扰穿透、模板 code、频控与变量类型。

分组与事件

分组事件 key
知识中心 wikiwiki.doc.publishedwiki.doc.commentedwiki.doc.mentionedwiki.doc.reviewedwiki.governance.maintenance_duewiki.governance.review_due
工作流 workflowworkflow.task.createdworkflow.task.ccworkflow.task.urgedworkflow.task.transferredworkflow.instance.approvedworkflow.instance.rejectedworkflow.instance.withdrawnworkflow.instance.returnedworkflow.consult.invitedworkflow.consult.repliedworkflow.comment.mentionedworkflow.node.exceptionworkflow.automation.message
组织与租户 identityidentity.tenant.expiringidentity.tenant.expired
运维与告警 opsops.monitor.alertops.monitor.alert_testops.error.alertops.scheduler.job_failedops.scheduler.task_alertops.license.expiringops.license.invalid
开放平台 open-platformopen-platform.app.review_requestedopen-platform.app.reviewedopen-platform.webhook.delivery_failedopen-platform.quota.threshold_exceeded
报表中心 reportreport.dashboard.mentioned
平台服务 platformplatform.feedback.handledplatform.export.finished
通知中心 messagingmessaging.digest(隐藏元事件,用于摘要邮件)

级别与规则

字段当前含义
severitynormalimportantcriticalcritical 默认穿透免打扰
defaultChannels收件人未配置偏好时默认开启的渠道
availableChannels偏好矩阵允许用户开关的渠道;省略时等于默认渠道
mandatory必达事件,用户不可关闭,派发时跳过个人偏好;仍允许管理员通过覆盖调整渠道
bypassQuietHours直接投递,不受免打扰时段影响
templates渠道模板 code;未配置时使用事件自带 title/content 模板
rateLimit同一收件人、同一事件、同一渠道在窗口内的成功投递上限
hidden不出现在偏好矩阵,例如 messaging.digest

渠道

通知中心渠道枚举为 inappemailsmspushwebhookchat。适配器通过 registerNotificationAdapter() 集中注册,未注册渠道会留下 channel_unavailable 结论,不会静默丢弃。

渠道当前实现
inapp写入 in_app_messages,支持模板、已读、批量已读、删除、管理端查看;消息可带 link 深链
email使用 email_configs 的 SMTP 配置发送,支持 email_templatesemail_send_logs;退订链接通过邮件渠道提供
sms支持阿里云、腾讯云配置与模板,发送记录写 sms_send_logs;模板变量可显式指定以避免 JSON 键序影响服务商位置参数
pushApp 推送,经聚合供应商(极光)投递到移动/桌面客户端,按收件人查统一设备中心的在活绑定设备,发送记录写 push_send_logs,详见 App 推送
webhook通过 channelOptions.webhook.url/body 投递,适合告警和外部接收人
chat作为聊天卡片渠道接入通知适配器;系统调度告警等事件可声明可用

旧的独立能力仍保留:邮件模板/日志、短信模板/日志、站内信模板/收件记录、公告、频道与客服工作台。这些能力与通知中心共用消息域,但 notify() 是跨业务事件通知的统一入口。

偏好、策略、免打扰与摘要

策略覆盖

管理员通过 /api/notification-policies/events 读取事件目录与当前作用域覆盖,通过 /api/notification-policies/overrides 保存覆盖,通过 /api/notification-policies/overrides/reset 恢复默认。

覆盖存储在 notification_event_overrides,是稀疏表:只保存与代码默认值不同的 eventKey + channeltenantId = null 表示平台级覆盖;租户视图读取平台覆盖与本租户覆盖,租户覆盖优先。locked = true 时用户偏好不能关闭该渠道。

个人偏好

用户通过 /api/notification-preferences/matrix 读取偏好矩阵,通过同路径 PUT 保存开关;全局设置由 /api/notification-preferences/settings 读写。

偏好存储在 notification_preferences,也是稀疏表:保存值等于“事件默认 + 平台/租户覆盖”的生效默认时会删行。全局设置存 notification_recipient_settings

  • globalMuted:全局免打扰,非必达事件被抑制。
  • timezone:免打扰和每日摘要按收件人本地时区计算,默认 Asia/Shanghai
  • quietStart / quietEndHH:mm,支持跨零点窗口;命中时写 deferred 并按结束时间重投。
  • digestModerealtimehourlydaily
  • digestHour:每日摘要投递小时,默认 9。

摘要只作用于邮件渠道,且不作用于必达或穿透免打扰的事件。摘要行带 digestKey,由 aggregateNotificationDigests() 聚合后通过 notify('messaging.digest') 发送一封邮件。

派发归因

notification_dispatches 记录所有“收件人 × 渠道”的结果,包括成功、抑制、延后、去重和失败。决策与原因如下:

decision含义
sent已投递
suppressed被偏好、全局免打扰、渠道不可用、不可达或频控抑制
deferred因免打扰或摘要延后
deduped幂等键命中,重复投递被忽略
failed渠道投递失败
reasonCode含义
preference_off收件人关闭该事件/渠道,或 external 收件人与候选渠道不匹配
globally_muted收件人开启全局免打扰
channel_unavailable渠道未启用或没有适配器
unreachable收件人缺少邮箱、手机号、Webhook 地址等可达地址
rate_limited触发事件频控
quiet_hours命中免打扰时段
digest进入摘要队列
delivery_error渠道发送异常

GET /api/notification-policies/dispatches 可按事件、渠道、决策、收件人类型、收件人 ID 与派发时间查询日志。

独立通知能力

站内信

说明
in_app_templates模板:code、title、content、type、variables、status、remark、tenantId
in_app_messages收件记录:templateId、userId、title、content、type、isRead、readAt、source、senderId、link、dedupeKey、tenantId

用户侧接口:GET /api/in-app-messagesGET /api/in-app-messages/unread-countGET /api/in-app-messages/{id}POST /api/in-app-messages/sendPOST /api/in-app-messages/{id}/readPOST /api/in-app-messages/read-allPOST /api/in-app-messages/batch-readDELETE /api/in-app-messages/{id}DELETE /api/in-app-messages/batch。管理端接口:GET /api/in-app-messages/adminPOST /api/in-app-messages/admin/read-allPOST /api/in-app-messages/admin/{id}/readDELETE /api/in-app-messages/admin/{id}

公告

说明
announcementstitle、content、type、publishStatus、priority、targetType、publishTime、createBy、tenantId
announcement_recipients定向公告接收人:userroledept
announcement_reads用户已读记录

用户侧接口:GET /api/announcements/publishedGET /api/announcements/unread-countGET /api/announcements/inboxPOST /api/announcements/{id}/readPOST /api/announcements/read-all。管理端接口:GET /api/announcementsGET /api/announcements/{id}GET /api/announcements/{id}/read-statsPOST /api/announcementsPUT /api/announcements/{id}DELETE /api/announcements/{id}DELETE /api/announcements/batch

邮件与短信

能力API权限
邮件配置GET /api/email-configPUT /api/email-configPOST /api/email-config/testsystem:email-config:viewsystem:email-config:update
邮件模板GET/POST /api/email-templatesGET/PUT/DELETE /api/email-templates/{id}system:email-template:*
邮件日志GET /api/email-send-logsDELETE /api/email-send-logs/{id}POST /api/email-send-logs/test-sendsystem:email-send-log:listsystem:email-send-log:deletesystem:email-config:update
短信配置GET/POST /api/sms-configsGET/PUT/DELETE /api/sms-configs/{id}POST /api/sms-configs/{id}/defaultsystem:sms-config:*
短信模板GET/POST /api/sms-templatesGET/PUT/DELETE /api/sms-templates/{id}system:sms-template:*
短信日志GET /api/sms-send-logsDELETE /api/sms-send-logs/{id}POST /api/sms-send-logs/test-sendsystem:sms-send-log:*

频道、客服与数据看板

频道体系使用 channelschannel_messageschannel_subscriptionschannel_message_targetschannel_menuschannel_auto_replieschannel_quick_replieschannel_conversationschannel_message_templates

主要能力:

  • 用户侧:我的频道、频道消息、已读、可订阅频道、订阅/退订、用户向频道发消息、会话评价。
  • 管理侧:频道 CRUD、订阅者管理、菜单配置、自动回复、群发、草稿/定时/撤回、消息模板、测试发送、受众估算。
  • 客服侧:可服务频道、会话聚合、对话消息、回复、指派/转接、解决、标签、快捷回复、绩效统计。
  • 看板:运营号数量、订阅数、消息数、今日推送、待处理会话、平均响应时长、趋势、已读率、排行、评分与自动回复命中分布。

主要权限:channel:channel:listchannel:channel:createchannel:channel:updatechannel:channel:deletechannel:message:publishchannel:menu:savechannel:reply:listchannel:reply:savechannel:reply:deletechannel:cschannel:dashboard

API 一览

根路径主要能力
/api/notification-preferencesGET/PUT /matrixGET/PUT /settings
/api/notification-policiesGET /eventsPUT /overridesPOST /overrides/resetGET /dispatches
/api/notification-unsubscribe/{token}邮件退订页面读取与提交
/api/in-app-templates站内信模板列表、详情、创建、更新、删除
/api/in-app-messages我的站内信、未读数、已读、批量已读、删除、管理端收件记录
/api/email-configSMTP 配置读取、保存、测试
/api/email-templates邮件模板 CRUD
/api/email-send-logs邮件发送记录、删除、测试发送
/api/sms-configs短信配置 CRUD、设为默认
/api/sms-templates短信模板 CRUD
/api/sms-send-logs短信发送记录、删除、测试发送
/api/announcements公告发布、收件箱、已读、统计、管理 CRUD
/api/channels频道、订阅、消息、菜单、自动回复、客服工作台、消息模板、看板、受众估算

维护要求

  • 新通知事件只改 NOTIFICATION_EVENTS 并在业务代码调用 notify() / notifyWithin()
  • 新渠道必须补充 NotificationChannelAdapter 并注册,否则只会留下 channel_unavailable 留痕。
  • 管理员覆盖与个人偏好保持稀疏存储,不全量物化事件矩阵。
  • 业务域不要直接调用邮件、短信、站内信发送函数来绕过通知中心。

Built with VitePress for local documentation preview.