实时消息与角标
Trix 的实时消息能力独立于通知下拉组件存在。后端注入配置后,前端会启动统一的 realtime 服务;通知铃铛、自定义导航项、菜单角标都从同一份通知状态读取数量。
配置结构
后端注入的 realtime 配置会传给 useNotificationRealtime():
json
{
"enabled": true,
"driver": "polling",
"polling": {
"api": "/notifications/poll",
"interval": 15000
},
"websocket": {
"url": ""
},
"enableNotification": true,
"behaviors": {
"audit.pending": {
"notify": false,
"actions": [
{ "type": "sound", "src": "/sounds/audit.mp3", "times": 3 },
{ "type": "notification", "title": "新的审核任务" }
]
}
}
}driver 支持:
polling:按间隔请求polling.api,请求参数会带since_id。ws:连接websocket.url,收到{ "type": "notification", "data": {...} }时处理新消息。
消息数据
一条消息至少应包含:
json
{
"id": 1001,
"type": "audit.pending",
"title": "新的审核任务",
"content": "用户提交了实名审核",
"isRead": false,
"createdAt": "2026-07-03 10:00:00",
"extra": {
"actions": [
{ "type": "sound", "src": "/sounds/audit.mp3", "times": 3 }
]
}
}若消息自身的 extra.actions 存在,会优先使用它;否则使用 realtime.behaviors[type].actions。
行为动作
内置动作:
sound:播放src指定的声音,times控制播放次数,范围 1 到 10。notification:弹出 Naive UI notification,可覆盖title、content、duration。
业务也可以注册自定义动作:
typescript
import { useNotificationRealtime } from '@/service/notification/realtime'
useNotificationRealtime().registerBehaviorAction('openRoute', async (action, message) => {
// 根据 action 或 message 执行业务逻辑
})浏览器通常要求用户先与页面交互后才能播放声音。Trix 启动时会安装 audio unlock 监听,在首次 pointerdown、keydown、touchstart 或 click 后解锁;解锁前到达的声音会进入队列,解锁后按顺序播放。
角标统计
菜单和自定义导航项的角标统一使用 badge 配置:
json
{
"badge": {
"source": "notification",
"types": ["audit.pending"],
"mode": "count",
"max": 99,
"color": "#f5222d"
}
}source: "notification" 时,数量来自 realtime 返回的 unread_count_by_type,不是当前通知列表分页结果,因此不会因分页只加载一部分数据而统计错误。处理完业务后,后端应在下一次轮询或 WebSocket 推送中返回新的未读计数;前端也可调用 useNotificationRealtime().refresh() 主动刷新。
自定义导航项跳转
自定义导航项支持:
click: "route":后台内部路由跳转,效果与点击菜单一致。click: "link":打开链接;target: "_blank"新标签页,target: "_self"当前页。click: "modal"/click: "drawer":保留给 schema 内容交互。schema_api:接口返回任意 schema 节点,由导航项位置渲染。
内部路由建议配置为最终路由路径,例如 /finance/recharges。如果后端菜单生成时已经带模块前缀,不要在前端或配置中再重复拼接模块名。