Skip to content

系统消息中心 - 使用指南

面向:业务后端开发(怎么发消息)、前端开发(怎么收消息) 代码位置:hiapi-cloud-public/hiapi-system-basic-core/hiapi-system-basic-message-{entity,service,api} 网关前缀:/cloud-api/** → hiapi-cloud-public 更新:2026-07-18(阶段2:公告广播 + 事件接入)


一、两种模型,别用错

通知 Notification(推)公告 Announcement(拉)
模型每接收者一行(hiapi_msg_notification)一条公告一行,全体可见(hiapi_msg_announcement)
适用定向:支付成功、审核结果、单发/群发运营消息广播:版本公告、活动通知、维护公告
已读逐条 readFlag + Redis 未读计数个人已读游标(hiapi_msg_announcement_cursor),read-all 推进,不逐条
禁忌别拿它做全员广播(会 fan-out 爆表)别拿它做定向消息(没有接收者维度)

分类枚举(两者共用):TRADE / DEVICE / AUDIT / SECURITY / SYSTEM / MARKETING


二、后端怎么发一条定向消息(三种方式)

方式1(推荐):发 NotifyEvent 事件,解耦

任何服务注入 EventPublisher,发到 SYSTEM_NOTIFY,消息中心 EventSystemNotifyListener 落库:

java
eventPublisher.publish(MsgRoutingKey.SYSTEM_NOTIFY, BaseEvent.builder()
        .eventType(MsgRoutingKey.SYSTEM_NOTIFY)
        .payload(NotifyEvent.builder()
                .mid(mid)
                .receiverType("user")          // user / merchant / channel / platform
                .receiverId(uid)
                .category(MsgCategory.AUDIT.name())
                .templateCode("WITHDRAW_PASS") // 与 bizId 联合幂等,可空
                .bizId(withdrawNo)             // 可空;两者都传才去重
                .title("提现审核通过")
                .content("你的提现申请已通过,金额将在24小时内到账。")
                .extra(...)                    // 跳转上下文 {route,bizType,bizId},透传不解析
                .build())
        .build());

幂等:templateCode + bizId + receiverType + receiverId 存在即跳过,MQ 重投/Outbox 重发都安全。

方式2:已接入的自动事件(业务方零改动)

业务事件生产方(已在发)落信
PaymentSuccessEvent(finance.pay.success.#)finance FinancePaymentLogic(Outbox)用户 TRADE「支付成功」,bizId=payCode
UserRegisterEvent(user.register)user UserAccountService用户 SYSTEM「欢迎加入」,bizId=uid

方式3:商户后台手动发

POST /cloud-api/merchant/message/notification/send,体 {receiverIds:[uid], title, content, category?}(缺省 MARKETING)。不做幂等,每次调用都新增。入口:后台会员列表页勾选群发/行内单发。


三、公告(广播)怎么用

商户后台管理(页面:会员管理 → 公告消息 /user/announcement)

/cloud-api/merchant/message/announcement:

端点说明
GET /query?page=&size=&title=&category=&status=分页(BasicQuery 规范)
POST /add发布。字段:title(必填)/category(缺省 SYSTEM)/content/extra/status(缺省1)/startTime(缺省立即)/endTime(<=0 或不传=永久,落库转哨兵 4102415999000)/sort
POST /edit编辑,{id, ...};status 1/0 即上/下架;mid/receiverType/created 不可改
DELETE|GET /delete?id=删除

用户端读取

/cloud-api/user/message/announcement:

端点说明
GET /query?page=&size=&category=只返回生效中(上架+在生效期)的公告,每条带 readFlag(created<=个人游标)
POST /read-all全部已读(推进游标;进入公告列表页时调用)
GET /unread-count{announcement: n}

GET /cloud-api/user/message/notification/unread-count 现在返回 {notification: n, announcement: n} 两个真实值,铃铛角标建议取两者之和。

平台向下广播(platform → merchant / channel,全局,mid 固定 0)

发布(平台后台「公告管理」/platform/announcement):/cloud-api/platform/message/announcement,POST /addreceiverType 必填选 merchantchannel,mid 固定 0,发布后 receiverType 不可改。CRUD 端点同商户侧。

接收:

  • 商户读:/cloud-api/merchant/message/platform-announcement(GET /queryPOST /read-allGET /unread-count)
  • 渠道读:/cloud-api/channel/message/platform-announcement(同上)

注意:这两个接收端点与 /merchant\|channel/message/notification/unread-count 里的 announcement 字段互不相通——后者查询固定用"自己的 mid"(对应 merchant→user 场景的公告),平台公告 mid=0,不会被那个字段捕获到。要展示平台公告未读数,前端需单独调 platform-announcement/unread-count 再和铃铛数字相加。

不支持 channel→merchant(渠道只广播给自己名下商户)——ChannelMerchant(channelId+mid)关系表虽存在,但要做到"仅本渠道商户可见"需要给 MsgAnnouncement 加 channelId 维度,目前未做。


四、收件箱接口(四账户通用,阶段0 已有)

/cloud-api/{merchant|channel|platform|user}/message/notification: GET /query(category/readFlag 过滤)、POST /read {ids:[]}POST /read-allGET /unread-count

商户侧另有 GET /sent?page=&size=&title=&category=:本商户发给用户的定向消息记录(手动 send + 自动事件),后台「公告消息 → 发送记录」Tab 在用。


五、接入新事件监听(消息中心侧开发规范)

  1. 监听器放 hiapi-system-basic-message-serviceevent/ 包(该模块已依赖 hiapi-core-event-sdk 且是 boot 期依赖)。
  2. 实现 IEventMessageListener<XxxEvent>,队列名 hiapi-cloud-public-message-<语义>
  3. 禁止构造器/字段注入业务 Service——RabbitConfig 在 BeanDefinitionRegistryPostProcessor 阶段就实例化监听器,统一在 onMessagedispatchContext.getServiceOne(...)
  4. 禁止用 Spring @EventListener 收跨服务事件(本地事件收不到 MQ,阶段2 修过这个 bug)。
  5. 落库统一走 MsgNotificationService.saveNotification,尽量带 templateCode+bizId 拿幂等。

六、用户端 widget(hiapi-cloud-public-web,装修组件体系)

用错项目会白做:消息中心属于 hiapi-cloud-public 服务,组件家目录是 hiapi-cloud-public/hiapi-cloud-public-web/src/components/hiapi-public/(appId: 'A-10000')。 不是 顶层 uniapp-design/ 文件夹——那个文件夹的 package.json name 实际是 hiapi-cloud-vem,是 VEM 项目的装修组件源。

已提供两个 widget(src/components/index.ts 已注册):

Widget数据源说明
hiapi-public-message-entry/user/message/notification/unread-count图标+标题+未读红点(notification+announcement 求和),点击跳 /pages/user-center/message
hiapi-public-announcement-bar/user/message/announcement/query滚动展示生效中公告,点击跳 /pages/user-center/message?mode=announcement

配套页面 src/pages/user-center/message.vue:「消息/公告」双 Tab,?mode=announcement 可直达公告 Tab。该页此前请求前缀写的是不存在的 /cloud-message,已修复为 /cloud-api——如果你在其它项目复制过这个页面的旧版本,记得同步修这个 bug。

七、已知边界

  • 提现审核等 finance 事件未发布,接入先补事件(见 hiapi-cloud-finance/docs/completion-plan.md §P3 第11项)。
  • channel→merchant(渠道只广播给自己名下商户)未做,需要 MsgAnnouncement 加 channelId 维度。
  • 平台公告(mid=0)的未读数不在通用铃铛聚合接口里,需单独拉取,见 §三"平台向下广播"。
  • user 服务旧 Notify{Body,Target,Type} 已删除(2026-07-18),新功能一律走本消息中心。
  • hiapi-cloud-public-web 本地缺 @uni-helper/uni-types 等类型包,vue-tsc 跑不通(环境问题,与消息中心功能无关)。