SSE 实时流。先用登录态申请一次性票据,再用票据连接。票据 30 秒有效,只能使用一次。不要把 access token 放进查询参数。
POST /api/notifications/stream-ticket
Authorization: Bearer <access_token>
{ "ticket": "<one-time>", "expiresIn": 30 }
GET /api/notifications/stream?ticket=<one-time>
Content-Type: text/event-stream
消息示例:
data: {"event":"connected"}
data: {"event":"assignment.create","id":"...","title":"你获得了新的域名权限","content":"...","level":"info","read":false,"createdAt":"...","metadata":{...}}
每用户最多约 5 路并发 SSE。
需登录。当前用户站内信列表。
{
"notifications": [
{
"id": "uuid",
"event": "assignment.create",
"title": "你获得了新的域名权限",
"content": "管理员已为你分配 blog.example.com(所属域名 example.com),权限:可编辑。",
"level": "info",
"metadata": {
"type": "assignment",
"domainId": "...",
"domainName": "example.com",
"subdomainPattern": "blog",
"host": "blog.example.com"
},
"createdAt": "2026-07-25T00:00:00.000Z",
"read": false
}
],
"unreadCount": 1
}存储在服务端内存,进程重启后清空。
标记单条已读。
全部已读。
删除单条。
清空全部站内信。
创建外部渠道配置(钉钉 / 飞书 / email / webhook / web)。
{
"channel": "dingtalk",
"name": "运维群",
"config": {
"webhookUrl": "https://oapi.dingtalk.com/robot/send?access_token=xxx",
"secret": "SEC..."
},
"events": ["domain.expiring", "domain.expired"],
"enabled": true
}通过 PUT /api/auth/me/profile:
{
"notificationsEnabled": true,
"emailNotificationsEnabled": false
}| 字段 | 默认 | 说明 |
|---|---|---|
notificationsEnabled |
true | 站内信 / SSE |
emailNotificationsEnabled |
false | 可选邮件(需邮箱 + SMTP) |
| event | 说明 |
|---|---|
assignment.create |
管理员分配域名 |
assignment.delete |
移除分配 |
assignment.request |
新申请(管理员) |
assignment.approve |
申请通过 |
assignment.reject |
申请拒绝 |