Skip to content

站内信 ​

这篇解决什么 ​

业务要给管理员或会员塞一条站内通知:改文案、测发送、在顶栏铃铛里看见未读。读完能新增模板、用 NotifyMessageSendApi 发信,并分清「只落库」和「落库后再 WebSocket 推一把」。

默认端口 48080,管理端前缀 /admin-api。PC 开发页 http://127.0.0.1:5800。站内信在 yudao-module-system,不经过短信网关或 SMTP。

示意图:业务先写模板、再插消息表;统一消息中心这条路径才会再推 type=notify。

名称说明仓库路径
模板接口@RequestMapping("/system/notify-template")ruoyi-office/yudao-module-system/.../controller/admin/notify/NotifyTemplateController.java
消息接口@RequestMapping("/system/notify-message")同目录 NotifyMessageController.java
跨模块发送Feign:/rpc-api/system/notify/sendyudao-module-system-api/.../api/notify/NotifyMessageSendApi.java
发送实现校验模板、格式化、落库.../service/notify/NotifySendServiceImpl.java
模板页菜单「模板管理」,路由 /system/messages/notify/notify-templateruoyi-office-vben/apps/web-antd/src/views/system/notify/template/
记录页菜单「消息记录」,路由 /system/messages/notify/notify-message同目录 message/
我的站内信隐藏路由 /system/notify-message,顶栏「查看所有」同目录 my/,路由名 MyNotifyMessage

官方菜单:父级 2739 消息中心,2144 站内信管理,2145 模板管理,2151 消息记录。我的站内信不进菜单树,写在 web-antd/src/router/routes/modules/system.ts。

三个页面 ​

管理后台能看见三块:模板、全站发送记录、当前登录人的收件箱。后两块读的是同一张 system_notify_message,过滤条件不同。

站内信模板列表

本系统截图:系统管理 → 消息中心 → 站内信管理 → 模板管理。列是编码、发送人、内容、类型、状态。

站内信消息记录

本系统截图:同级菜单「消息记录」。按用户编号、用户类型、模板编码查全站已发。

我的站内信

本系统截图:顶栏铃铛 → 查看所有,路由 /system/notify-message。只能看自己的信,可单条或全部标已读。

名称说明仓库路径
模板 CRUD / 测试发送权限 system:notify-template:create 等,测试要 send-notifyNotifyTemplateController
记录分页GET /system/notify-message/pageNotifyMessageController#getNotifyMessagePage
我的分页GET /my-page,强制当前 userId + ADMIN同上 #getMyMyNotifyMessagePage
未读列表 / 数量GET /get-unread-list、/get-unread-count顶栏铃铛调用
标已读PUT /update-read、/update-all-read只能改自己的未读行

get-unread-count 标了 @ApiAccessLog(enable = false)。顶栏两分钟轮询一次,记访问日志没有意义。

为什么要模板

产品改发送人昵称或正文时,改 system_notify_template 一行即可。业务代码只认 code,不必重新发版。

表与字段 ​

模板一张表、消息一张表。消息把发送当时的编码、类型、发送人、渲染后正文和参数都冗余下来,以后改模板不影响历史信。

示意图:模板按 code 被发送接口引用;消息行是一次投递的快照。

NotifyTemplateDO 上 @TableName("system_notify_template"),并加了 @TenantIgnore。NotifyMessageDO 上 @TableName("system_notify_message"),走租户插件,表里有 tenant_id。

名称说明仓库路径
code业务调用时的唯一键,租户间也共用.../dal/dataobject/notify/NotifyTemplateDO.java
nickname收件箱里显示的发件人,不是系统用户同上
content占位符写成 {name},保存时抽出 params同上
paramsJacksonTypeHandler 存 List<String>同上
type字典 system_notify_template_type:1 通知公告,2 系统消息NotifyTemplateTypeEnum
statusCommonStatusEnum。停用后发送只打日志、返回 nullNotifyTemplateDO
userType1 会员,2 管理员NotifyMessageDO + UserTypeEnum
templateContent已经 StrUtil.format 过的正文NotifyMessageDO
templateParams当时传入的 Map同上
readStatus / readTime标已读时一起写NotifyMessageMapper#updateListRead

模板没有租户列

@TenantIgnore 表示所有租户读同一套 code。两个租户不要抢同一个编码;消息行仍按当前租户隔离。

缓存名 notify_template,按 code 做 @Cacheable。改、删模板会 @CacheEvict(allEntries = true),因为主键不是缓存键。

模板怎么配 ​

打开模板管理,点新增或编辑。code 给 API 用,nickname 给收件人看,content 里用花括号包参数名。

修改站内信模板

本系统截图:培训证书模板。编码 hrm-training-cert-issued,正文含 {certName}、{certNo}。

保存时 parseTemplateContentParams 用正则 \{(.*?)\} 抽出参数名,写入 params。发送时 formatNotifyTemplateContent 走 Hutool StrUtil.format,{certName} 换成传入 Map 里的值。

名称说明仓库路径
抽出参数ReUtil.findAllGroup1NotifyTemplateServiceImpl#parseTemplateContentParams
渲染正文StrUtil.format(content, params)同上 #formatNotifyTemplateContent
编码重复NOTIFY_TEMPLATE_CODE_DUPLICATEErrorCodeConstants
字典system_notify_template_type静态数据 id 167

前端表单在 template/data.ts。类型下拉读 DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE。状态默认启用。

测试发送 ​

模板行上的「测试」打开发送弹窗。选用户类型、接收人,按 params 动态补输入框,再 POST /system/notify-template/send-notify。

测试发送站内信

本系统截图:用户类型默认会员;选管理员后接收人变成用户下拉。参数名来自模板 params。

发完到「消息记录」核对;接收人打开顶栏铃铛,或进「我的站内信」。

顶栏未读站内信

本系统截图:工作台右上角铃铛。上半是聊天会话,下半「通知」是站内信,标题用 templateNickname,正文用 templateContent。

名称说明仓库路径
测试 VOuserId、userType、templateCode、templateParams.../vo/template/NotifyTemplateSendReqVO.java
测试页按 params 拼 param_{name}web-antd/.../template/modules/send-form.vue
顶栏拉取getUnreadNotifyMessageList + 两分钟轮询未读数web-antd/src/layouts/basic.vue
跳转详情templateCode 以 bpm_ 开头,或参数里有 detailUrlweb-antd/src/views/oa/im/helper.ts

模板不存在时报的是公告错误码

validateNotifyTemplate 缓存未命中时抛 NOTICE_NOT_FOUND(「当前通知公告不存在」),不是 NOTIFY_TEMPLATE_NOT_EXISTS。对日志和前端提示时按这句文案排,不要去找公告表。

模板停用:sendSingleNotify 打 info 日志后返回 null,不抛异常。调用方不要把 null 当成已写入的消息 id。

缺参数:params 里某个键在 Map 中为 null,抛 NOTIFY_SEND_TEMPLATE_PARAM_MISS。

sendBatchNotify 默认抛 UnsupportedOperationException。要群发就自己循环 sendSingleNotifyToAdmin。

业务怎么发 ​

其它模块不要直接插 system_notify_message。注入 NotifyMessageSendApi,按用户类型选方法。

java
@Resource
private NotifyMessageSendApi notifyMessageSendApi;

public void send(Long userId, String templateCode, Map<String, Object> params) {
    NotifySendSingleToUserReqDTO req = new NotifySendSingleToUserReqDTO();
    req.setUserId(userId);
    req.setTemplateCode(templateCode);
    req.setTemplateParams(params);
    notifyMessageSendApi.sendSingleMessageToAdmin(req);
}

培训模块就是这样发的:TrainingNotifyHelper。合同到期、项目超期、工单 SLA 也走同一接口。

名称说明仓库路径
发给管理员POST .../send-single-adminNotifyMessageSendApi#sendSingleMessageToAdmin
发给会员POST .../send-single-member#sendSingleMessageToMember
入参userId、templateCode 必填.../api/notify/dto/NotifySendSingleToUserReqDTO.java
落地转 NotifySendService.../api/notify/NotifyMessageSendApiImpl.java
微服务声明@EnableFeignClients 列出该 APIyudao-module-oa-server、yudao-module-project-server 的 RpcConfiguration

单体启动时实现类是 @RestController,本地就能调。微服务要把 system-server 当 Feign 名,路径前缀 /rpc-api/system。

BPM 审批信的 templateCode 建议以 bpm_ 开头,并在 templateParams 里带 processInstanceId 或 detailUrl。顶栏和「我的站内信」会用 parseNotifyNavigationMeta 拼跳转。

实时推送 ​

NotifyMessageSendApi 只落库。顶栏未读数靠轮询,打开铃铛再拉最近 10 条。要立刻弹到在线用户,走统一消息中心的站内信渠道。

示意图:渠道适配器先保证消息 id 写入,再尽力推 WebSocket;推失败只打 warn。

名称说明仓库路径
渠道MsgChannelEnum.NOTIFY = 1.../service/msg/channel/NotifyChannelAdapter.java
帧类型常量 WS_MESSAGE_TYPE = "notify"同上
载荷id、title、content、detailUrl同上
发送器跨模块 WebSocketSenderApiyudao-module-infra-api
原生模板消息中心复用 system_notify_template.../service/msg/core/NativeTemplateResolver.java

顶栏那条 /infra/ws 目前只解析 im.message.receive / im.conversation.update,用来刷聊天角标。type=notify 的帧要自己在页面里听;站内信角标仍以 get-unread-count 为准。

直接调发送 API 不会推 WebSocket

NotifySendServiceImpl 没有 WebSocketSenderApi。培训、合同 Job 发出去的信,接收人可能要等下一次轮询或手动打开铃铛才看见。需要秒达就走消息中心渠道,或自己在业务里补一次 sendObject。

WebSocket 路径、集群 sender-type、握手鉴权见 WebSocket。

配置与操作 ​

管理员在 消息中心 → 站内信 → 模板管理 写编码和内容,保存后业务按编码推送。员工看顶栏铃铛或「我的站内信」页(该页在源码里,dump 未必有菜单)。

改模板只影响之后发送的行。已发出的 system_notify_message 不会回写。开启见 系统功能设计。截图见上文模板和消息列表。

相关篇 ​

联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版