Merge branch 'main' into dev

# Conflicts:
#	docs/backstage/IM-Kafka接入方案.md
#	docs/backstage/IM-Kafka接入范围识别.md
#	server/api/admin/imconfiginternal/im_config.go
#	server/api/admin/imuser/im_user.go
#	server/internal/consts/im_kafka.go
#	server/internal/controller/admin/sys/im_user.go
#	server/internal/controller/internalapi/imconfig/im_config.go
#	server/internal/library/imadmin/client.go
#	server/internal/library/imadmin/client_test.go
#	server/internal/library/imadmin/internal.go
#	server/internal/library/imkafka/command.go
#	server/internal/library/imtenant/db.go
#	server/internal/library/imtenant/db_test.go
#	server/internal/library/queue/kafkamq.go
#	server/internal/library/queue/queue.go
#	server/internal/logic/admin/member.go
#	server/internal/logic/sys/im_dead_letter.go
#	server/internal/logic/sys/im_group.go
#	server/internal/logic/sys/im_invite.go
#	server/internal/logic/sys/im_kafka_audit.go
#	server/internal/logic/sys/im_kafka_command.go
#	server/internal/logic/sys/im_tenant.go
#	server/internal/logic/sys/im_user.go
#	server/internal/model/input/sysin/im_group.go
#	server/internal/model/input/sysin/im_invite.go
#	server/internal/model/input/sysin/im_user.go
#	server/internal/queues/im_admin_command_result.go
#	server/internal/queues/im_audit_event.go
#	server/internal/queues/im_dead_letter.go
#	server/internal/service/sys.go
#	server/manifest/config/config.example.yaml
#	server/storage/data/generate/im_group_menu.sql
#	server/storage/data/generate/im_user_menu.sql
#	server/storage/data/im_registration_invite_hotgo.sql
#	web/src/views/im/registrationInvite/BatchViewModal.vue
#	web/src/views/im/registrationInvite/index.vue
#	web/src/views/im/registrationInvite/model.ts
#	web/src/views/imDeadLetter/index.vue
#	web/src/views/imDeadLetter/model.ts
#	web/src/views/imGroup/governance.vue
#	web/src/views/imGroup/members.vue
#	web/src/views/imKafkaAudit/model.ts
#	web/src/views/imKafkaAudit/view.vue
#	web/src/views/imKafkaCommand/index.vue
#	web/src/views/imKafkaCommand/model.ts
#	web/src/views/imKafkaCommand/view.vue
#	web/src/views/imUser/ResetPasswordModal.vue
#	web/src/views/imUser/governance.vue
#	web/src/views/imUser/index.vue
#	web/src/views/imUser/model.ts
#	web/src/views/imUser/view.vue
This commit is contained in:
richjohnrambo
2026-09-13 23:43:51 +08:00
444 changed files with 46212 additions and 2158 deletions
@@ -0,0 +1,582 @@
# IM Admin 内部查询接口缺口清单
> 目标:梳理 HotGo/Admin 迁移到“Admin 只访问 hotgo,IM Server 只访问租户库”后,IM Server 需要补齐的 `/internal/admin-query/*` 只读接口。
> 当前日期:2026-08-27
> 适用项目:`im_manager` Admin 后台、`im_server` IM 服务端。
## 1. 背景
Kafka 写链路已经在 Admin 侧补齐:Admin 写操作落 `im_admin_commands`、`im_admin_outbox`,通过 Kafka 发给 IM Server,IM Server 执行业务后回传 `im.admin.command.result`。
查询链路还没有完全隔离。Admin 当前仍有不少页面通过 `imtenant.DB()` 或 `resolveImTenantDB()` 直连租户库。若要严格满足目标架构,Admin 查询租户业务数据时应调用 IM Server 的内部只读接口:
```text
GET /internal/admin-query/tenants/{tenant_code}/...
```
IM Server 当前已经具备部分内部查询接口,但还不能覆盖 Admin 后台页面。
## 2. 已有接口
以下接口在 IM Server 当前实现中已经存在,可供 Admin 先迁移:
| 接口 | 用途 | 备注 |
|---|---|---|
| `GET /internal/admin-query/tenants/{tenant_code}/users/{user_id}` | 用户详情 | 需要增强字段,见 P0。 |
| `GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}` | 群详情和治理配置 | 需要增强 topic 基础字段,见 P0。 |
| `GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}/members` | 群成员列表 | 当前偏 cursor 分页,Admin 表格还需要 total。 |
| `GET /internal/admin-query/tenants/{tenant_code}/messages/{topic}/{seq_id}` | 消息详情 | 当前 Admin 暂未完整迁移消息页面。 |
| `GET /internal/admin-query/tenants/{tenant_code}/files/{file_id}` | 文件详情 | 还缺文件列表和引用列表。 |
| `GET /internal/admin-query/tenants/{tenant_code}/kafka/dead-letters` | Kafka 死信列表 | Admin 已接入。 |
| `GET /internal/admin-query/tenants/{tenant_code}/kafka/dead-letters/{dead_id}` | Kafka 死信详情 | Admin 已接入。 |
## 3. 统一约定
### 3.1 鉴权
沿用 IM Server 内部 API HMAC 鉴权:
```text
X-Service-Name
X-Timestamp
X-Nonce
X-Signature
```
服务端需要校验:
1. service 是否存在。
2. service 是否包含 `admin_query` capability。
3. timestamp 是否在允许窗口内。
4. nonce 是否防重放。
5. 签名是否匹配。
### 3.2 分页返回
Admin 的 `BasicTable` 更适合 page/per_page/total 格式。建议所有列表接口统一返回:
```json
{
"code": 0,
"data": {
"items": [],
"total": 0,
"page": 1,
"per_page": 20
}
}
```
如果 IM Server 内部更适合 cursor,也建议同时返回:
```json
{
"code": 0,
"data": {
"items": [],
"total": 0,
"page": 1,
"per_page": 20,
"next_cursor": "",
"has_more": false
}
}
```
### 3.3 详情返回
详情接口统一返回:
```json
{
"code": 0,
"data": {}
}
```
### 3.4 时间与 ID
1. 时间统一返回 RFC3339/RFC3339Nano 字符串。
2. 雪花 ID、Tinode 用户 ID、19 位整数 ID 建议以字符串返回,避免前端丢精度。
3. 入参同时兼容字符串 ID 和纯数字 ID 时,IM Server 内部自行解析。
## 4. P0:优先补齐
P0 是 Admin 当前核心页面迁移所需接口,补完后可以先迁移用户、群组、文件等高频页面。
### 4.1 用户列表
```text
GET /internal/admin-query/tenants/{tenant_code}/users
```
用途:IM 用户管理列表。
建议查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| `user_id` | string | 用户 ID,支持精确查询。 |
| `nickname` | string | 昵称模糊查询。 |
| `auth_name` | string | 登录标识,匹配 username/phone/email/凭证。 |
| `state` | int | 用户状态。 |
| `created_at_start` | string | 创建时间开始。 |
| `created_at_end` | string | 创建时间结束。 |
| `last_seen_start` | string | 最后在线开始。 |
| `last_seen_end` | string | 最后在线结束。 |
| `page` | int | 页码。 |
| `per_page` | int | 每页数量,最大建议 200。 |
建议返回字段:
| 字段 | 说明 |
|---|---|
| `user_id` | 字符串用户 ID。 |
| `username` | 用户名。 |
| `phone` | 手机号。 |
| `nickname` | 昵称。 |
| `public_account` | 公开账号。 |
| `state` | 用户状态。 |
| `gender` | 性别。 |
| `region` | 地区。 |
| `auth_names` | 登录标识摘要。 |
| `credentials` | 凭证摘要。 |
| `auth_version` | 鉴权版本。 |
| `password_updated_at` | 密码更新时间。 |
| `last_seen` | 最后在线时间。 |
| `user_agent` | 最后设备 UA。 |
| `created_at` | 创建时间。 |
| `updated_at` | 更新时间。 |
当前 Admin 直连涉及表:`im_users`、`im_user_profiles`、`im_user_security`、`im_credentials`。
### 4.2 用户详情增强
现有接口:
```text
GET /internal/admin-query/tenants/{tenant_code}/users/{user_id}
```
建议增强返回字段:
| 字段 | 说明 |
|---|---|
| `profile` | 结构化用户资料。 |
| `public` | Tinode public JSON。 |
| `trusted` | Tinode trusted JSON。 |
| `access` | 访问权限 JSON。 |
| `tags` | 标签。 |
| `security` | `auth_version/password_updated_at` 等安全信息。 |
| `credentials` | 凭证列表,包含 method/value/done。 |
### 4.3 用户设备列表
```text
GET /internal/admin-query/tenants/{tenant_code}/users/{user_id}/devices
```
用途:用户详情中的登录设备列表。
建议查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| `device_id` | string | 设备 ID。 |
| `platform` | string | 平台。 |
| `page` | int | 页码。 |
| `per_page` | int | 每页数量。 |
建议返回字段:
| 字段 | 说明 |
|---|---|
| `device_id` | 设备 ID。 |
| `platform` | 平台。 |
| `user_agent` | UA。 |
| `last_seen` | 最后在线。 |
| `created_at` | 创建时间。 |
| `updated_at` | 更新时间。 |
当前 Admin 直连涉及表:`im_devices`。
### 4.4 群列表
```text
GET /internal/admin-query/tenants/{tenant_code}/groups
```
用途:IM 群组管理列表。
建议查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| `topic` | string | 群 Topic。 |
| `owner_id` | string | 群主 ID。 |
| `state` | int | Tinode topic 状态。 |
| `group_status` | string | 业务群状态。 |
| `created_at_start` | string | 创建时间开始。 |
| `created_at_end` | string | 创建时间结束。 |
| `touched_at_start` | string | 活跃时间开始。 |
| `touched_at_end` | string | 活跃时间结束。 |
| `page` | int | 页码。 |
| `per_page` | int | 每页数量。 |
建议返回字段:
| 字段 | 说明 |
|---|---|
| `topic` | 群 Topic。 |
| `state` | Tinode 状态。 |
| `owner_id` | 群主 ID。 |
| `seq_id` | 最新消息序号。 |
| `del_id` | 删除序号。 |
| `sub_count` | Tinode 订阅成员数。 |
| `touched_at` | 活跃时间。 |
| `created_at` | 创建时间。 |
| `updated_at` | 更新时间。 |
| `public` | Tinode public JSON。 |
| `trusted` | Tinode trusted JSON。 |
| `tags` | 标签。 |
| `aux` | 辅助 JSON。 |
| `group_name` | 群名称。 |
| `avatar_file_id` | 群头像文件 ID。 |
| `description` | 群简介。 |
| `group_status` | 业务群状态。 |
| `join_approval` | 入群审批开关。 |
| `mute_all` | 全员禁言。 |
| `member_upload_files` | 成员上传文件。 |
| `member_private_chat` | 成员私聊。 |
| `member_invite` | 成员邀请。 |
| `max_member_count` | 最大成员数。 |
| `max_admin_count` | 最大管理员数。 |
| `business_member_count` | 业务成员数。 |
| `settings_version` | 治理配置版本。 |
| `settings_updated_at` | 治理配置更新时间。 |
当前 Admin 直连涉及表:`im_topics`、`im_group_settings`。
### 4.5 群详情增强
现有接口:
```text
GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}
```
当前接口主要返回 `im_group_settings`。建议增强 Tinode topic 基础字段:
| 字段 | 说明 |
|---|---|
| `state` | Topic 状态。 |
| `seq_id` | 最新消息序号。 |
| `del_id` | 删除序号。 |
| `sub_count` | 订阅数量。 |
| `public` | public JSON。 |
| `trusted` | trusted JSON。 |
| `access` | access JSON。 |
| `tags` | tags JSON。 |
| `aux` | aux JSON。 |
| `touched_at` | 活跃时间。 |
### 4.6 群成员列表增强
现有接口:
```text
GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}/members
```
建议增强查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| `user_id` | string | 用户 ID 精确过滤。 |
| `role` | string | `owner/admin/member`。 |
| `member_status` | string | 成员状态。 |
| `q` | string | 昵称、公开账号等关键词。 |
| `eligible_role` | string | 候选角色筛选。 |
| `page` | int | 页码。 |
| `per_page` | int | 每页数量。 |
| `cursor` | string | 兼容 cursor 分页。 |
| `limit` | int | 兼容 cursor 分页。 |
建议增强返回:
| 字段 | 说明 |
|---|---|
| `total` | 总数,Admin 表格需要。 |
| `items[].user_id` | 用户 ID。 |
| `items[].nickname` | 昵称。 |
| `items[].state` | 用户状态。 |
| `items[].mode_want` | 期望权限。 |
| `items[].mode_given` | 授予权限。 |
| `items[].recv_seq_id` | 接收序号。 |
| `items[].read_seq_id` | 已读序号。 |
| `items[].del_id` | 删除序号。 |
| `items[].role` | 业务角色。 |
| `items[].member_status` | 成员状态。 |
| `items[].group_nickname` | 群昵称。 |
| `items[].pinned` | 置顶。 |
| `items[].mute_notifications` | 免打扰。 |
| `items[].join_source` | 加入来源。 |
| `items[].joined_by` | 邀请或处理人。 |
| `items[].joined_at` | 加入时间。 |
| `items[].left_at` | 离开时间。 |
| `items[].removed_by` | 移除人。 |
| `items[].version` | 版本。 |
当前 Admin 直连涉及表:`im_group_members`、`im_subscriptions`、`im_users`、`im_user_profiles`。
### 4.7 入群申请列表
```text
GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}/join-requests
```
建议查询参数:`status`、`applicant_user_id`、`page`、`per_page`。
建议返回字段:`request_id`、`topic`、`applicant_user_id`、`inviter_user_id`、`source`、`message`、`status`、`reject_reason`、`handled_by`、`handled_at`、`expires_at`、`version`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_group_join_requests`。
### 4.8 群邀请列表
```text
GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}/invitations
```
建议查询参数:`status`、`target_user_id`、`inviter_user_id`、`page`、`per_page`。
建议返回字段:`invitation_id`、`topic`、`inviter_user_id`、`target_user_id`、`message`、`status`、`result`、`join_request_id`、`expires_at`、`handled_at`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_group_invitations`。
### 4.9 群公告列表
```text
GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}/announcements
```
建议查询参数:`status`、`page`、`per_page`。
建议返回字段:`announcement_id`、`topic`、`author_user_id`、`content`、`status`、`version`、`published_at`、`deleted_by`、`deleted_at`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_group_announcements`。
### 4.10 群禁言列表
```text
GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}/mutes
```
建议查询参数:`status`、`user_id`、`page`、`per_page`。
建议返回字段:`topic`、`user_id`、`muted_by`、`muted_at`、`expires_at`、`reason`、`status`、`revoked_by`、`revoked_at`、`version`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_group_mutes`。
### 4.11 群管理日志
```text
GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}/admin-logs
```
建议查询参数:`action`、`operator_id`、`page`、`per_page`。
建议返回字段:`log_id`、`topic`、`operator_id`、`target_user_id`、`action`、`object_type`、`object_id`、`before_data`、`after_data`、`request_id`、`idempotency_key`、`created_at`。
当前 Admin 直连涉及表:`im_group_admin_logs`。
### 4.12 群文件列表
```text
GET /internal/admin-query/tenants/{tenant_code}/groups/{topic}/files
```
用途:群治理页面中的群文件列表。不要和已有单文件详情接口混淆。
建议查询参数:`status`、`file_type`、`file_name`、`uploader_id`、`page`、`per_page`。
建议返回字段:`group_file_id`、`topic`、`file_id`、`source_topic`、`source_seq`、`uploader_id`、`file_name`、`mime_type`、`file_type`、`file_size`、`status`、`deleted_by`、`deleted_at`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_group_files`。
### 4.13 文件列表
```text
GET /internal/admin-query/tenants/{tenant_code}/files
```
用途:IM 文件管理列表。
建议查询参数:`file_id`、`user_id`、`status`、`mime_type`、`created_at_start`、`created_at_end`、`page`、`per_page`。
建议返回字段:`id`、`file_id`、`user_id`、`mime_type`、`file_size`、`file_name`、`location`、`etag`、`status`、`quarantine_reason`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_fileuploads`。
### 4.14 文件引用列表
```text
GET /internal/admin-query/tenants/{tenant_code}/files/{file_id}/links
```
用途:文件详情中展示消息引用。
建议返回字段:`topic`、`seq_id`、`user_id`、`created_at`。
当前 Admin 直连涉及表:`im_filemsglinks`。
## 5. P1:后台审核和运营页面
### 5.1 审计日志
```text
GET /internal/admin-query/tenants/{tenant_code}/audit-logs
GET /internal/admin-query/tenants/{tenant_code}/audit-logs/{id}
```
建议查询参数:`actor_user_id`、`action`、`target_type`、`target_id`、`created_at_start`、`created_at_end`、`page`、`per_page`。
建议返回字段:`id`、`request_id`、`actor_user_id`、`action`、`target_type`、`target_id`、`ip`、`user_agent`、`detail`、`created_at`。
当前 Admin 直连涉及表:`im_audit_logs`。
### 5.2 实名审核
```text
GET /internal/admin-query/tenants/{tenant_code}/realname-verifications
GET /internal/admin-query/tenants/{tenant_code}/realname-verifications/{id}
```
建议查询参数:`user_id`、`status`、`real_name`、`created_at_start`、`created_at_end`、`page`、`per_page`。
建议返回字段:`id`、`user_id`、`real_name`、`id_card_no_masked`、`front_file_id`、`back_file_id`、`status`、`reject_reason`、`reviewed_by`、`reviewed_at`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_realname_verifications`。
### 5.3 举报工单
```text
GET /internal/admin-query/tenants/{tenant_code}/abuse-reports
GET /internal/admin-query/tenants/{tenant_code}/abuse-reports/{id}
GET /internal/admin-query/tenants/{tenant_code}/reports/abuse/{report_id}/target
```
建议查询参数:`reporter_user_id`、`target_type`、`target_id`、`status`、`created_at_start`、`created_at_end`、`page`、`per_page`。
建议返回字段:`id`、`report_id`、`reporter_user_id`、`target_type`、`target_id`、`reason_code`、`description`、`evidence_file_ids`、`status`、`handler_id`、`handled_at`、`handle_result`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_abuse_reports`。
### 5.4 意见反馈
```text
GET /internal/admin-query/tenants/{tenant_code}/feedback-submissions
GET /internal/admin-query/tenants/{tenant_code}/feedback-submissions/{id}
```
建议查询参数:`user_id`、`category`、`status`、`created_at_start`、`created_at_end`、`page`、`per_page`。
建议返回字段:`id`、`feedback_id`、`user_id`、`category`、`content`、`contact`、`file_ids`、`status`、`handler_id`、`handled_at`、`reply`、`created_at`、`updated_at`。
当前 Admin 直连涉及表:`im_feedback_submissions`。
### 5.5 业务 Outbox
```text
GET /internal/admin-query/tenants/{tenant_code}/outbox/business-events
GET /internal/admin-query/tenants/{tenant_code}/outbox/group-events
GET /internal/admin-query/tenants/{tenant_code}/outbox/business-events/{id}
GET /internal/admin-query/tenants/{tenant_code}/outbox/group-events/{id}
```
建议查询参数:`event_type`、`status`、`target_type`、`target`、`created_at_start`、`created_at_end`、`page`、`per_page`。
当前 Admin 直连涉及表:`im_business_events_outbox`、`im_group_events_outbox`。
## 6. P2:如果要完全消除租户库直连
这些不是 Kafka 联调第一优先级,但如果最终要求 Admin 完全不碰租户库,也需要 IM Server 提供内部查询或改为 hotgo 摘要表。
### 6.1 组织架构
```text
GET /internal/admin-query/tenants/{tenant_code}/org/departments
GET /internal/admin-query/tenants/{tenant_code}/org/members
```
当前 Admin 直连涉及表:`im_org_departments`、`im_org_members`、`im_users`。
### 6.2 工作台应用
```text
GET /internal/admin-query/tenants/{tenant_code}/workbench/apps
```
当前 Admin 直连涉及工作台相关租户表。
### 6.3 租户任务看板摘要
```text
GET /internal/admin-query/tenants/{tenant_code}/dashboard/summary
```
当前 Admin 会统计多个租户库中的待处理实名、举报、反馈、Outbox 等数量。
### 6.4 租户配置类查询
如果这些配置仍放在租户库,也需要补接口;如果后续迁到 hotgo 控制库,则不需要通过 IM Server 查询。
```text
GET /internal/admin-query/tenants/{tenant_code}/feedback-config
GET /internal/admin-query/tenants/{tenant_code}/mailbox-config
GET /internal/admin-query/tenants/{tenant_code}/abuse-reasons
GET /internal/admin-query/tenants/{tenant_code}/app-releases
```
涉及模块:反馈配置、总经理信箱配置、举报原因、App 发布策略。
## 7. Admin 侧迁移建议
### 7.1 第一批迁移
在 IM Server 补完 P0 后,Admin 优先迁移:
1. 用户列表、用户详情、用户设备。
2. 群列表、群详情、群成员。
3. 群入群申请、邀请、公告、禁言、管理日志、群文件。
4. 文件列表、文件详情、文件引用。
### 7.2 第二批迁移
在 IM Server 补完 P1 后,Admin 再迁移:
1. 审计日志。
2. 实名审核。
3. 举报工单。
4. 意见反馈。
5. 业务 Outbox。
### 7.3 保留 hotgo 查询的范围
以下数据天然属于 hotgo 控制库,Admin 可继续查 hotgo,不需要走 IM Server:
1. 租户表和租户绑定表。
2. Admin 命令表:`im_admin_commands`。
3. Admin Outbox 表:`im_admin_outbox`。
4. Admin Kafka 审计事件表:`im_audit_events`。
5. 菜单、角色、管理员、系统配置、字典等 HotGo 系统表。
## 8. 验收标准
1. Admin 查询租户业务数据时,不再出现新的 `imtenant.DB()` 调用。
2. Admin 查询 IM Server 内部接口时,统一使用 HMAC 签名。
3. 列表接口支持 `page/per_page/total`,兼容后台表格分页。
4. 详情接口返回结构化 JSON,不返回数据库内部敏感字段。
5. 用户 ID、雪花 ID 等大整数以字符串返回。
6. IM Server 为内部查询写审计日志,至少包含 `tenant_code`、`service_name`、`path`、`query`、`trace_id`、`status`、`duration_ms`。
7. 关闭 IM Server 内部查询能力时,Admin 应得到明确错误,不泄露租户库信息。
+51 -2
View File
@@ -1,7 +1,7 @@
# IM Kafka 接入方案
> 日期:2026-08-26
> 关联文档:[IM Kafka 接入范围识别](./IM-Kafka接入范围识别.md)、[IM 前后端逐图对接协议](./IM-前后端对接文档.md)
> 日期:2026-08-26
> 关联文档:[IM Kafka 接入范围识别](./IM-Kafka接入范围识别.md)、[IM 前后端逐图对接协议](./IM-前后端对接文档.md)
> 目标:明确 Admin 后台、IM 服务、HotGo 控制库、租户业务库之间的 Kafka 接入边界、查询方式、鉴权方式和首批落地范围。
## 0. 与范围识别文档的关系
@@ -786,6 +786,55 @@ Admin 处理命令:
2. IM 按死信记录中的 `source_topic` 重新投递原 envelope。
3. 投递成功后把死信标记为 `replayed`,并累计 `replay_count`。
4. 如果重放后仍失败,普通消费者会再次写入新的 dead 记录,保留完整处理痕迹。
### 11.12 IM Server 已接入的用户治理命令
IM Server 已在 `im.admin.command` 中接入用户治理类后台动作。Admin 侧写 hotgo 操作单并发送 Kafka Command,IM 消费后修改租户库用户状态、踢在线连接、清理缓存并回传 `im.admin.command.result`。
支持命令:
| `event_type` | 行为 | Payload 关键字段 |
| --- | --- | --- |
| `user.ban` | 封禁用户,设置 `StateSuspended` 并踢所有在线会话。 | `actor_user_id`、`user_id` 或 `target_user_id`、`reason` |
| `user.unban` | 解封用户,设置 `StateOK`。 | `actor_user_id`、`user_id` 或 `target_user_id`、`reason` |
| `user.freeze` | 冻结账号,设置 `StateSuspended` 并踢所有在线会话。 | `actor_user_id`、`user_id` 或 `target_user_id`、`reason` |
| `user.unfreeze` | 恢复账号,设置 `StateOK`。 | `actor_user_id`、`user_id` 或 `target_user_id`、`reason` |
| `user.device.kick` | 踢指定设备在线连接,并删除设备推送记录。 | `actor_user_id`、`user_id` 或 `target_user_id`、`device_id`、`reason` |
| `user.logout_all` | 踢用户所有在线连接,不修改账号状态。 | `actor_user_id`、`user_id` 或 `target_user_id`、`reason` |
| `user.account.cancel` | 注销账号,默认软删除;`hard=true` 时硬删除。 | `actor_user_id`、`user_id` 或 `target_user_id`、`hard`、`reason` |
| `user.account.delete` | 删除账号,按硬删除处理。 | `actor_user_id`、`user_id` 或 `target_user_id`、`reason` |
命令示例:
```json
{
"event_id": "admin:user:ban:default:usrabc:001",
"tenant_code": "default",
"source_service": "hotgo-admin",
"target_service": "im-server",
"event_type": "user.ban",
"biz_type": "user_governance",
"biz_id": "usrabc",
"idempotency_key": "admin-operation-id",
"occurred_at": "2026-08-26T10:10:00.000Z",
"payload": {
"command_id": "admin-operation-id",
"actor_user_id": "usrAdmin",
"user_id": "usrabc",
"reason": "违规处理"
}
}
```
处理说明:
1. 封禁/冻结共用 Tinode 用户状态 `StateSuspended`;解封/恢复共用 `StateOK`。
2. 状态变更后 IM 会清理用户缓存,并向本节点 Hub 投递用户状态变更。
3. 踢设备只影响匹配 `device_id` 的在线连接,同时删除该设备 Push token 记录。
4. 全端登出只踢在线连接,不修改用户状态。
5. 注销/删除会停止用户相关 Topic、清理缓存并调用 `store.Users.Delete`。
6. 命令执行成功后统一回传 `im.admin.command.result`,并写入 `im.audit.event`。
7. 群消息消费成功后继续写入 Redis 热消息缓存,便于 24 小时内热点拉取。
事件示例:
File diff suppressed because it is too large Load Diff
+3 -10
View File
@@ -1,7 +1,7 @@
# IM Kafka 接入范围识别
> 日期:2026-08-26
> 依据:[IM 前后端逐图对接协议](./IM-前后端对接文档.md)
> 日期:2026-08-26
> 依据:[IM 前后端逐图对接协议](./IM-前后端对接文档.md)
> 目标:从前后端对接文档逐章识别适合接入 Kafka 的链路,明确 Kafka 与 WebSocket、Redis、MySQL、OSS 的边界。
## 1. 总体边界
@@ -73,14 +73,7 @@ Kafka 消息统一携带 `event_id`、`trace_id`、`tenant_code`、`biz_type`、
3. 总经理信箱提交生产 `im.workbench.event` 和 `im.audit.event`,后台处理结果再回推 C 端。
4. 工作台模块配置变更生产 `im.cache.invalidate`,IM 节点刷新进程内配置缓存。
## 7. 已补充:缓存失效与 Admin 配置查询
1. `im.cache.invalidate` 已接入 IM 消费端,支持租户、注册短信、第三方配置、字典配置、Redis 对象缓存、群热消息缓存失效。
2. IM 已增加 Admin 内部配置查询客户端,开启 `admin_internal_api.enabled=true` 后优先通过 Admin 查询 hotgo 侧配置,旧数据库读取作为灰度兜底。
3. Admin 侧需要补齐 `/internal/im-config/*` 只读接口,并与 IM 使用同一套 HMAC 签名密钥。
4. Kafka 死信已补齐查询、忽略、解决、重放闭环:查询走 IM 内部 API,处理走 `im.admin.command`。
## 8. 首批建议实现
## 7. 首批建议实现
1. 先实现 Kafka 基础生产者、消费者、配置、健康检查和消费幂等表。
2. 接入 `im.group.admin.event`,解决 Admin 后台群操作通过 Kafka 投递到 C 端。
@@ -0,0 +1,570 @@
# IM 后台全量需求文档
> 版本:V1.0 草案
> 编写日期:2026-08-21
> 适用范围:HotGo 管理后台、IM 服务端、IM 客户端动态配置、控制库、租户业务库
> 输入来源:`docs/im/IM-前后端对接文档.md`、`docs/im/IM-注册、邀请码与认证数据模型改造需求文档.md`、`docs/im/IM-HotGo注册短信开关与邀请码管理改造交接文档.md`、`docs/backstage/IM-后台需求文档.md`
## 1. 文档目标
本文从前后端对接协议、注册/邀请码/认证改造文档中,完整识别 IM 项目需要由后台管理系统承载的能力,包括:
1. 后台页面和业务管理模块。
2. 平台级、租户级开关和配置。
3. 后端统一维护、前端动态加载的字典枚举。
4. 定时任务、Outbox、异步投递、重试和补偿任务。
5. 客户端通过 `bootstrap`、配置接口、字典接口动态渲染的 UI 能力。
6. 权限、审计、日志脱敏、导出和安全边界。
本文是后台全量需求盘点,不替代具体接口设计和数据库迁移 SQL。后续开发时,应按 HotGo 项目规范拆成独立 CRUD 模块、配置模块、任务模块和权限菜单。
## 2. 基础原则
### 2.1 多租户边界
当前多租户采用“一个 HotGo 控制库 + 每租户一个 IM 独立业务库”方案。
| 数据类型 | 存储位置 | 是否带 `tenant_id` | 说明 |
| --- | --- | --- | --- |
| 租户元数据 | HotGo 控制库 | 是 | `im_tenant`、租户配置、平台审计、邀请码主数据 |
| 平台全局配置 | HotGo 控制库 | 否或按配置域区分 | 例如 `hg_sys_config.group=im` |
| 邀请码批次和主表 | HotGo 控制库 | 是 | 后台生成、查询、撤销、导出 |
| 租户用户、群、消息、文件、组织、工单 | 租户 IM 业务库 | 否 | 通过登录态租户上下文选择库,不在业务表里保存 `tenant_id` |
| 租户内使用事实和业务 Outbox | 租户 IM 业务库 | 否 | 例如 `im_registration_invite_uses`、`im_business_events_outbox` |
浏览器不能传入可信 `tenant_id`、`db_name`、`db_dsn`。平台管理员跨租户操作时,由后端基于登录身份和权限选择租户;租户管理员只能使用自身绑定的租户上下文。
### 2.2 HotGo 与 IM 服务职责
| 系统 | 职责 |
| --- | --- |
| HotGo 后台 | 菜单权限、后台页面、平台控制库、租户元数据、平台配置、邀请码管理、运维诊断、后台审计 |
| IM 服务端 | 客户端注册登录、实时消息、业务状态机、租户业务库事务、WebSocket、Outbox 消费、客户端动态配置下发 |
| 客户端 | 根据服务端返回的配置、权限、字典和策略动态渲染,不硬编码业务开关和枚举 |
原则上,租户内用户、群、文件、实名、举报、反馈等业务状态变更优先通过 IM 服务端管理 API 或受控业务通道完成,避免绕过 IM 的状态机和审计。当前注册邀请码和密码重置存在明确的 HotGo 直连数据库边界,必须严格按交接文档执行。
### 2.3 配置分层
| 层级 | 示例 | 管理入口 |
| --- | --- | --- |
| 平台全局配置 | 注册短信发送开关、短信服务商、对象存储默认配置、通用风控模板 | 平台后台 |
| 租户基础配置 | 租户状态、企业码、名称、数据库、配额、品牌、终端地址 | 平台后台,部分租户只读 |
| 租户业务策略 | 消息策略、文件策略、群治理、隐私默认值、工作台模块 | 企业后台 |
| 用户个人配置 | 隐私开关、青少年模式状态、设备推送 Token | 客户端为主,后台只读或安全处置 |
| 前端动态 UI 配置 | `bootstrap.features`、`settings_menu`、`workbench.modules`、原因字典 | IM 服务端返回,来源于后台配置和权限 |
## 3. 后台全量模块总览
| 模块 | 平台后台 | 企业后台 | 类型 | 优先级 |
| --- | --- | --- | --- | --- |
| 租户生命周期 | 是 | 否 | 管理页面、任务、审计 | P0 |
| 租户配置与配额 | 是 | 部分只读或申请变更 | 配置、开关、动态 UI | P0 |
| 注册短信开关 | 是 | 否 | 全局开关、审计 | P0 |
| 邀请码管理 | 平台可代管 | 是 | CRUD、导出、审计 | P0 |
| 管理员、角色、权限 | 是 | 是 | 权限、字典、审计 | P0 |
| 用户与账号安全 | 平台可运维 | 是 | 管理页面、Outbox | P0 |
| 组织架构 | 否 | 是 | CRUD、导入导出、动态 UI | P1 |
| 群治理 | 平台可审计 | 是 | 配置、管理页面、字典 | P1 |
| 消息策略与系统消息 | 平台模板 | 租户配置 | 配置、模板、任务 | P1 |
| 文件、收藏、搜索治理 | 平台运维 | 是 | 配置、任务、审计 | P1 |
| Push、短信、TURN、对象存储 | 是 | 租户专属配置 | 敏感配置、状态检查 | P1 |
| 工作台应用 | 平台模板 | 是 | 动态 UI 配置 | P2 |
| 会议 | 平台审计 | 是 | 管理页面、提醒任务 | P2 |
| 日报、月报 | 平台审计 | 是 | 模板、统计、提醒任务 | P2 |
| 总经理信箱 | 平台审计 | 是 | 配置、工单、动态文案 | P2 |
| 实名认证 | 平台审计 | 是 | 审核、策略、字典 | P2 |
| 青少年模式 | 平台模板 | 是 | 策略、动态文案、限制 | P2 |
| 反诈与内容审核 | 平台策略 | 租户策略与处置 | 风控、字典、审计 | P2 |
| 举报与反馈 | 平台可审计 | 是 | 原因字典、工单、导出 | P2 |
| App 版本更新 | 是 | 可按租户覆盖 | 配置、动态 UI | P2 |
| Outbox 与后台任务 | 是 | 只读本租户 | 运维、重试、死信 | P0 |
| 审计与日志脱敏 | 是 | 只读本租户 | 安全基础能力 | P0 |
## 4. 开关与配置清单
### 4.1 平台全局开关
| 配置键 | 类型 | 默认 | 管理权限 | 使用方 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `im.register_sms_enabled` | bool | true | 平台超级管理员 | IM 注册发码接口 | 控制注册验证码是否真实发送;关闭时仍返回倒计时,不暴露给客户端 |
| `im.invite_batch_max_quantity` | int | 1000 | 平台管理员 | HotGo 邀请码管理 | 单批邀请码生成数量上限 |
| `im.invite_export_max_rows` | int | 待定 | 平台管理员 | HotGo 导出 | 防止明文邀请码大批量泄露 |
| `im.sms_provider_enabled` | bool | true | 平台管理员 | IM 发码服务 | 是否启用短信服务商,不等同于注册短信业务开关 |
| `im.audit_retention_days` | int | 待定 | 平台管理员 | 审计任务 | 平台审计保留期 |
| `im.outbox_retry_enabled` | bool | true | 平台运维 | Outbox 任务 | 是否自动重试平台/租户 Outbox |
`register_sms_enabled` 存在 HotGo `hg_sys_config`,真实值必须保存为 `1/0`。前端复用 `sys_switch` 时要显式映射:UI `1=开启`、`2=关闭`,不能把 `2` 直接写成 bool。
### 4.2 租户基础配置
| 配置 | 类型 | 是否动态下发 | 管理入口 | 说明 |
| --- | --- | --- | --- | --- |
| 租户状态 | enum | 是 | 平台后台 | `provisioning/active/suspended/deleting/deleted` |
| 企业码 | string | 登录前解析 | 平台后台 | 客户端 `tenants/resolve` 使用 |
| 租户名称、Logo、品牌色 | string/file | 是 | 平台后台 | 登录页、工作台、关于页展示 |
| `db_name/db_dsn` | string | 否 | 平台后台 | 只允许后端使用,不给浏览器 |
| 用户配额 | int | 是 | 平台后台 | 注册、导入用户、邀请加入时强校验 |
| 群数量配额 | int | 是 | 平台后台 | 建群时校验 |
| 群成员上限 | int | 是 | 平台/企业后台 | 建群、邀请、审批通过时校验 |
| 文件存储配额 | int64 | 是 | 平台/企业后台 | 上传、转发、收藏、群文件共用 |
| 终端 API 地址 | url | 登录前解析 | 平台后台 | HTTP、WebSocket、文件服务地址 |
| 可用登录方式 | array enum | 登录前解析 | 平台后台 | 密码、手机号、企业码等 |
| 密码策略 | json | 登录/注册/改密 | 平台/企业后台 | 长度、复杂度、历史密码、过期策略 |
| App 更新策略 | json | 是 | 平台后台 | platform/channel 维度版本策略 |
### 4.3 客户端 Bootstrap 动态配置
`GET /v1/im/bootstrap` 是客户端登录后的 UI 和能力裁剪总入口,后台必须为以下字段提供配置来源。
| 字段 | 后台配置项 | 客户端影响 |
| --- | --- | --- |
| `features.create_group` | 是否允许用户建群 | 隐藏或禁用建群入口 |
| `features.user_search` | 是否允许搜索用户 | 隐藏添加好友搜索入口 |
| `features.scan_qr` | 是否启用扫码 | 隐藏二维码/扫码入口 |
| `features.system_notifications` | 系统通知开关 | 展示系统通知 Topic |
| `features.message_recall` | 消息撤回开关 | 长按菜单是否显示撤回 |
| `features.message_edit` | 消息编辑开关 | 长按菜单是否显示编辑 |
| `features.organization` | 组织架构开关 | 工作台/通讯录组织入口 |
| `features.meetings` | 会议开关 | 工作台会议入口 |
| `features.daily_report/monthly_report` | 日报/月报开关 | 工作台报表入口 |
| `features.executive_mailbox` | 总经理信箱开关 | 工作台信箱入口 |
| `message_policy.recall_window_seconds` | 撤回时间窗口 | 超时隐藏操作 |
| `message_policy.edit_window_seconds` | 编辑时间窗口 | 超时隐藏操作 |
| `message_policy.supported_actions` | 消息操作集合 | 转发、收藏、复制、删除等 |
| `limits.max_file_size` | 单文件大小 | 上传前校验 |
| `limits.max_text_length` | 文本最大长度 | 输入框限制 |
| `limits.max_forward_targets` | 转发目标上限 | 多选转发限制 |
| `settings_menu` | 设置菜单配置 | iOS/Android 设置页动态入口 |
| `workbench.modules` | 工作台模块配置 | 工作台排序、图标、路由、角标 |
### 4.4 注册、认证与邀请码配置
| 配置 | 作用 | 后台入口 | 备注 |
| --- | --- | --- | --- |
| 注册短信发送 | 是否真实调用短信服务商 | 平台后台“IM 注册” | 全局开关 |
| 用户名正则 | 普通用户名规则 | 平台只读配置或代码常量 | 当前固定 `^[a-z0-9]{1,10}$` |
| 固定国家号 | 手机号补 `+86` | 平台只读配置 | 本期固定中国 |
| 邀请码长度和字符集 | 生成规则 | 平台只读配置 | 当前固定 5 位 `[A-Za-z]` |
| 邀请码批量上限 | 批量生成限制 | 平台后台 | 默认 1000 |
| 邀请码有效期 | 单批/单码字段 | 企业后台 | 创建时必填,必须晚于当前时间 |
| 邀请码明文查看权限 | 控制列表/详情是否显示明文 | 菜单权限 | 查看、查询、导出需独立审计 |
| 密码重置策略 | 管理员重置密码规则 | 企业后台 | 写 `security.password_reset` Outbox |
| 登录 Token 失效策略 | `auth_version` 校验 | 后台只读/运维 | 重置密码后清退旧会话 |
### 4.5 消息与会话策略
| 配置 | 类型 | 说明 |
| --- | --- | --- |
| 文本最大长度 | int | 输入框、服务端发送校验 |
| 消息撤回开关和时间窗 | bool/int | P2P、群聊均需服务端校验 |
| 消息编辑开关和时间窗 | bool/int | 编辑后产生版本或审计 |
| 多选转发目标上限 | int | 单选、多选、合并转发共用 |
| 支持消息操作 | array enum | copy、forward、favorite、recall、edit、delete |
| 已读回执策略 | enum/bool | 可受隐私和企业强制策略影响 |
| 链接识别与风险检测 | bool/json | URL 发送前后检查,触发反诈挑战 |
| 系统通知 Topic | string/json | 系统消息列表和角标 |
| 消息频控 | json | 防刷、风控、举报联动 |
### 4.6 通讯录、好友与隐私策略
| 配置 | 类型 | 客户端影响 |
| --- | --- | --- |
| 是否允许添加好友 | bool | 添加好友入口 |
| 是否允许精准账号搜索 | bool | 用户 ID/用户名/手机号搜索 |
| 添加我的方式 | enum array | 账号、手机号、二维码、群聊 |
| 好友申请验证策略 | enum | 直接添加、需要验证、禁止 |
| 黑名单能力 | bool | 黑名单入口和服务端拦截 |
| 资料可见性默认值 | enum | 主页字段裁剪 |
| 最近在线可见性 | enum | 会话状态展示 |
| 已读回执默认值 | bool | 会话回执 |
| 企业强制隐私字段 | json | `editable=false` 时前端禁用 |
### 4.7 群治理配置
| 配置 | 类型 | 说明 |
| --- | --- | --- |
| 是否允许建群 | bool | bootstrap 和建群接口 |
| 群成员上限 | int | 加群、邀请、审批事务内校验 |
| 入群策略 | enum | free、approval、invite_only |
| 成员邀请权限 | enum/bool | 群成员是否可邀请别人 |
| 成员上传文件 | bool | 群文件上传入口 |
| 成员私聊 | bool | 群成员主页是否允许发起会话 |
| 成员互加好友 | bool | 群资料页添加好友入口 |
| 全员禁言 | bool | 输入框禁用 |
| 成员禁言时长 | enum/int | 后台和群管理员使用 |
| 管理员数量上限 | int | 添加管理员时校验 |
| 群二维码有效期 | int | 二维码页和失效任务 |
| 群公告策略 | json | 发布、置顶、已读统计 |
### 4.8 文件、收藏与搜索策略
| 配置 | 类型 | 说明 |
| --- | --- | --- |
| 单文件大小上限 | int64 | 上传前后校验 |
| 允许 MIME/扩展名 | array | 图片、视频、语音、普通文件按 purpose 区分 |
| 文件 purpose 策略 | json | avatar、chat、group_file、report、abuse_evidence、feedback |
| 文件保留期 | int | 过期清理任务 |
| 孤儿文件清理时间窗 | int | 上传未绑定业务时清理 |
| 文件病毒扫描 | bool/json | 同步拦截或异步隔离 |
| 收藏总量/容量上限 | int/int64 | 收藏入口和服务端校验 |
| 搜索开关 | bool | 聊天记录、文件、链接搜索入口 |
| 搜索索引策略 | json | 重建、增量、失败重试 |
### 4.9 通话、Push 和外部服务配置
| 配置 | 类型 | 说明 |
| --- | --- | --- |
| 音视频通话开关 | bool | 呼叫入口 |
| 通话超时 | int | invite 超时时间 |
| TURN/STUN 服务器 | secret/json | WebRTC ICE 配置 |
| 通话记录保留期 | int | 后台查询和清理 |
| APNS/FCM 配置 | secret/json | 推送服务 |
| Push 锁屏隐私 | enum/bool | 通知内容是否显示明文 |
| Push 模板 | json | 系统消息、好友申请、会议提醒等 |
| 短信服务商配置 | secret/json | 验证码、通知短信 |
| 对象存储配置 | secret/json | 文件服务 |
| 外部 REST 插件配置 | secret/json | 扩展业务调用 |
### 4.10 办公协同配置
| 模块 | 配置 | 说明 |
| --- | --- | --- |
| 工作台 | 模块 code、名称、图标、路由、排序、启用、权限 | `GET /v1/im/workbench` 动态返回 |
| 组织架构 | 组织可见范围、是否允许跨部门搜索 | 通讯录和工作台组织入口 |
| 会议 | 是否启用、提醒提前量、可见范围、取消策略 | 会议通知和提醒任务 |
| 日报 | 模板、必填规则、最大长度、补交天数、提醒时间 | 普通用户和管理员统计 |
| 月报 | 模板、必填规则、最大长度、重开流程 | 月报统计和详情 |
| 总经理信箱 | 是否启用、匿名、必填字段、最大长度、附件策略、提示文案 | 文案必须服务端下发,不由客户端硬编码 |
### 4.11 安全、审核、举报与反馈配置
| 模块 | 配置 | 说明 |
| --- | --- | --- |
| 实名认证 | 是否强制、允许跳过、提醒周期、重复身份策略、审核字段 | 影响 `bootstrap.security.realname` |
| 青少年模式 | 策略版本、限制集合、提示文案、是否可启用 | 客户端确认时携带 `policy_version` |
| 反诈风控 | 高风险动作、提示文案、二次确认、阻断策略、Token TTL | 返回 `RISK_CONFIRMATION_REQUIRED` |
| 内容审核 | 审核模式、词库、插件、异步处置 | sync_block、async_hold、async_post_audit |
| 举报 | target_type 原因字典、证据规则、合并策略、限频 | `GET /v1/im/reports/abuse/reasons` |
| 反馈 | 类别、最大长度、联系方式、附件策略、诊断授权文案 | `GET /v1/im/feedback/config` |
### 4.12 App 更新配置
| 配置 | 类型 | 说明 |
| --- | --- | --- |
| platform | enum | ios、android、desktop 等 |
| channel | string/enum | stable、beta、enterprise |
| latest_version | string | 最新版本 |
| min_supported | string | 最低支持版本 |
| update_type | enum | none、optional、recommended、force |
| package_url/store_url | url | 安装来源 |
| release_notes | text | 更新说明 |
| remind_after_seconds | int | 非强制更新再次提醒间隔 |
## 5. 字典与枚举清单
后台新增枚举必须由后端统一注册字典,前端通过字典接口加载,不能在页面硬编码文本。
### 5.1 平台与租户
| 字典键建议 | 枚举 |
| --- | --- |
| `im_tenant_status` | provisioning、active、suspended、deleting、deleted |
| `im_tenant_plan` | free、standard、enterprise、custom |
| `im_tenant_config_scope` | platform、tenant、user |
| `im_operation_result` | success、failed、partial |
### 5.2 注册、认证、邀请码
| 字典键建议 | 枚举 |
| --- | --- |
| `im_register_sms_status` | enabled、disabled |
| `im_invite_status` | active、expired、revoked |
| `im_invite_action` | create、batch_create、view、query_exact、revoke、batch_revoke、export |
| `im_auth_scene` | register、login、forgot_password、bind_phone、close_youth_mode |
| `im_auth_channel` | sms、password、independent_password |
| `im_challenge_status` | pending、verified、expired、consumed、failed |
| `im_user_status` | normal、disabled、locked、deleted |
| `im_auth_level` | anonymous、authenticated、admin |
### 5.3 好友、群与消息
| 字典键建议 | 枚举 |
| --- | --- |
| `im_friend_request_status` | pending、accepted、rejected、expired、cancelled |
| `im_friend_add_method` | account、phone、qr、group |
| `im_profile_visibility` | public、friends、none |
| `im_group_role` | owner、admin、member |
| `im_group_join_policy` | free、approval、invite_only |
| `im_group_request_status` | pending、approved、rejected、expired |
| `im_group_mute_type` | all、member |
| `im_message_action` | copy、forward、favorite、recall、edit、delete、multi_select |
| `im_message_content_type` | text、image、audio、video、file、card、link、system |
| `im_read_state` | unread、read |
### 5.4 文件、搜索、通话
| 字典键建议 | 枚举 |
| --- | --- |
| `im_file_purpose` | chat、user_avatar、group_avatar、group_file、daily_report、monthly_report、abuse_evidence、feedback |
| `im_file_status` | uploaded、bound、quarantined、deleted、expired |
| `im_file_scan_status` | pending、clean、risky、failed |
| `im_search_index_status` | pending、indexed、failed、deleted |
| `im_call_type` | audio、video |
| `im_call_status` | ringing、accepted、declined、missed、cancelled、ended、timeout |
### 5.5 办公协同
| 字典键建议 | 枚举 |
| --- | --- |
| `im_workbench_module_status` | enabled、disabled |
| `im_meeting_status` | scheduled、cancelled、finished |
| `im_meeting_response` | pending、accepted、declined、tentative |
| `im_report_type` | daily、monthly |
| `im_report_status` | draft、submitted、reopened、archived |
| `im_mailbox_submission_status` | received、assigned、replied、closed |
### 5.6 安全、审核、举报、反馈
| 字典键建议 | 枚举 |
| --- | --- |
| `im_realname_status` | unverified、pending、approved、rejected |
| `im_youth_restriction` | night_quiet、content_filter、payment_guard、contact_limit |
| `im_risk_level` | low、medium、high |
| `im_risk_decision` | continue、cancel |
| `im_moderation_mode` | off、sync_block、async_hold、async_post_audit |
| `im_moderation_status` | pending、passed、blocked、removed |
| `im_abuse_target_type` | user、group、message |
| `im_abuse_report_status` | received、processing、resolved、rejected、merged |
| `im_abuse_reason` | fraud、harassment、pornography、violence、spam、other |
| `im_feedback_category` | bug、suggestion、complaint、other |
| `im_feedback_status` | received、processing、resolved、closed |
### 5.7 终端、外部服务与错误
| 字典键建议 | 枚举 |
| --- | --- |
| `im_app_platform` | ios、android、desktop、web |
| `im_app_channel` | stable、beta、enterprise |
| `im_update_type` | none、optional、recommended、force |
| `im_push_provider` | apns、fcm、vendor |
| `im_outbox_status` | pending、processing、done、failed、dead |
| `im_error_reason` | TENANT_UNAVAILABLE、TENANT_MISMATCH、AUTH_FAILED、TOKEN_EXPIRED、ACCOUNT_DISABLED、RATE_LIMITED、VALIDATION_FAILED、IDEMPOTENCY_CONFLICT、RESOURCE_NOT_FOUND、FORBIDDEN、FRIEND_RELATION_REQUIRED、MESSAGE_NOT_ALLOWED、GROUP_MUTED、GROUP_MEMBER_LIMIT_EXCEEDED、TENANT_USER_QUOTA_EXCEEDED、TENANT_GROUP_QUOTA_EXCEEDED、FILE_TOO_LARGE、FILE_FORBIDDEN、FILE_UNAVAILABLE、STORAGE_QUOTA_EXCEEDED、REALNAME_REQUIRED、YOUTH_MODE_RESTRICTED、RISK_CONFIRMATION_REQUIRED、RISK_ACTION_BLOCKED、REPORT_RATE_LIMITED |
## 6. 定时任务与异步任务
### 6.1 P0 基础任务
| 任务 | 触发方式 | 作用 | 后台能力 |
| --- | --- | --- | --- |
| 租户业务库初始化 | 创建租户后异步执行 | 创建库、执行 schema、初始化系统数据 | 进度、失败原因、重试 |
| 租户健康检查 | 定时 | 检查 DB 连接、schema version、基础 Topic | 状态看板、告警 |
| Outbox 消费状态巡检 | 定时 | 检查积压、失败、死信 | 列表、重试、死信 |
| `security.password_reset` 消费 | IM 轮询或 Kafka | 清退会话、拒绝旧 Token | 事件查询、重试 |
| 注册邀请码使用投影 | IM Outbox 或投影任务 | 将租户库 `invite_uses` 汇总到控制库主表 | 使用次数、最后使用时间、幂等补偿 |
| 审计日志脱敏与落库 | 同步/异步 | 保存操作审计,避免明文泄露 | 查询、导出、保留期 |
### 6.2 业务任务
| 任务 | 说明 |
| --- | --- |
| 邀请码过期状态刷新 | 邀请码可查询时实时判断过期;可增加定时任务做状态冗余和统计,不作为注册校验唯一依据 |
| 邀请码批量生成 | 大批量生成应可异步化,支持进度、失败重试、幂等键 |
| 文件孤儿清理 | 上传后未绑定业务的文件定期清理 |
| 文件过期清理 | 按 purpose 和保留期清理 |
| 病毒扫描和隔离处理 | 异步扫描结果更新文件状态并通知用户 |
| 搜索索引重建 | 消息、文件、链接索引的全量/增量重建 |
| 系统通知投递 | 系统消息、公告、风控提醒、会议提醒的 Push 和站内信投递 |
| Push 重试和死信 | 第三方推送失败后的重试、死信、凭证异常告警 |
| 会议提醒 | 按会议配置提醒参会人,支持提醒未响应者 |
| 日报/月报提醒 | 按租户配置提醒未提交者,生成统计 |
| 总经理信箱通知 | 新提交、分派、回复、关闭通知 |
| 实名审核超时提醒 | 提醒审核员处理 |
| 风控 challenge 过期 | 清理过期 challenge,记录取消/过期审计 |
| 举报和反馈 SLA 提醒 | 超时未处理提醒,支持工单状态流转 |
| App 更新配置缓存刷新 | 版本策略变更后刷新缓存 |
### 6.3 任务后台需求
1. 任务列表:任务名、租户、状态、进度、最近执行时间、耗时、错误原因。
2. 任务详情:输入参数、幂等键、关联审计、关联 Outbox、重试次数。
3. 操作:手动重试、暂停、恢复、标记死信、导出错误明细。
4. 安全:租户管理员只能看本租户任务;平台运维可跨租户查看但必须审计。
## 7. 前端 UI 动态配置需求
### 7.1 客户端动态 UI
客户端不能硬编码以下 UI 能力,必须由服务端返回:
1. 登录前:租户品牌、企业码解析结果、终端地址、认证方式、密码策略、App 更新策略。
2. 登录后:首页入口、`features`、`permissions`、`settings_menu`、工作台模块、系统通知 Topic。
3. 聊天页:可执行消息操作、撤回/编辑时间窗、上传限制、转发上限、已读回执策略。
4. 通讯录:组织架构入口、用户搜索入口、添加我的方式、黑名单入口。
5. 群聊:入群策略、群文件入口、群成员私聊、成员邀请、禁言状态、管理员入口。
6. 工作台:模块名称、图标、路由、排序、角标、启用状态和权限。
7. 日报/月报:模板、校验、补交天数、是否展示管理员统计。
8. 总经理信箱:提示文案、匿名说明、必填字段、附件规则。
9. 实名、青少年模式、反诈:策略版本、提示文案、限制集合、确认 Token。
10. 举报与反馈:原因、类别、最大长度、附件规则、诊断授权文案。
### 7.2 HotGo 管理后台动态 UI
HotGo 后台自身也需要动态化:
1. 平台管理员显示租户选择器;租户管理员隐藏租户选择器并固定当前租户。
2. 按权限显示按钮:邀请码明文查看、导出、撤销、密码重置、跨租户查看必须独立权限。
3. 表格状态、筛选下拉、表单选项必须从后端字典加载。
4. 敏感配置字段只允许写入,不默认回显明文;回显使用脱敏值和“已配置”状态。
5. 导出前必须展示范围、数量、敏感字段提示,二次确认并写审计。
6. 表单提交不接受浏览器传入 `tenant_id/db_name/db_dsn` 作为可信路由依据。
## 8. 后台页面需求
### 8.1 平台后台
| 页面 | 核心能力 |
| --- | --- |
| 租户管理 | 创建、初始化、启停、删除流程、配置 DB、查看用量 |
| 租户配置 | 配额、品牌、终端地址、登录方式、密码策略、功能开关 |
| IM 注册设置 | 注册短信发送开关、批量邀请码上限、导出限制 |
| 平台管理员 | 平台账号、角色、权限、二次认证 |
| 外部服务配置 | SMS、Push、TURN、对象存储、审核插件 |
| App 版本 | 按 platform/channel 配置版本更新策略 |
| 运维看板 | 租户健康、Outbox、任务、缓存、连接状态 |
| 平台审计 | 跨租户操作、敏感配置变更、导出记录 |
### 8.2 企业后台
| 页面 | 核心能力 |
| --- | --- |
| 邀请码管理 | 单个生成、批量生成、列表、精确查询、批次详情、撤销、导出、使用记录 |
| 企业管理员 | 添加管理员、设置角色、移除管理员、权限范围 |
| 用户管理 | 用户列表、状态、资料、重置密码、撤销会话、设备、安全事件 |
| 组织架构 | 部门树、成员、移动、导入导出、组织权限 |
| 群管理 | 群列表、详情、成员、管理员、禁言、转让群主、解散、群文件 |
| 消息与系统通知 | 模板、公告、系统通知、投递记录 |
| 文件治理 | 文件列表、用途、大小、状态、隔离、删除、下载审计 |
| 搜索治理 | 索引状态、重建、失败明细 |
| 工作台 | 模块配置、排序、图标、角标来源、权限绑定 |
| 会议 | 列表、详情、取消、提醒未响应者、统计 |
| 日报/月报 | 模板、统计、明细、提醒、重开流程 |
| 总经理信箱 | 配置、提交列表、分派、回复、关闭 |
| 实名审核 | 提交列表、详情、通过、拒绝、策略 |
| 青少年模式 | 策略、文案、用户状态、独立密码重置 |
| 反诈与审核 | 风控策略、challenge、内容审核队列、处置 |
| 举报工单 | 原因配置、举报列表、证据、处置、合并 |
| 意见反馈 | 类别配置、反馈列表、诊断附件、处理状态 |
| 租户审计 | 本租户后台操作、敏感查看、导出、业务处置 |
## 9. 数据与接口边界
### 9.1 控制库建议承载
| 表或配置 | 说明 |
| --- | --- |
| `im_tenant` | 租户元数据、状态、企业码、DB 路由 |
| `im_tenant_config` | 租户配置、配额、功能开关、品牌 |
| `hg_sys_config` | 平台全局配置,例如注册短信发送 |
| `im_registration_invite_batches` | 邀请码批次 |
| `im_registration_invite_codes` | 邀请码主表、明文码、状态、使用统计投影 |
| `im_admin_operation_audit` | IM 后台业务审计 |
| `hg_admin_member.tenant_id` | 后台管理员绑定 IM 租户 |
| 平台 Outbox/任务表 | 平台任务、投递、重试、死信 |
### 9.2 租户业务库建议承载
| 表 | 说明 |
| --- | --- |
| `im_users` | 用户主数据,目标包含 `username` 非空唯一、`phone` 可空唯一 |
| `im_auth` | 只按 `userid` 保存 Basic 密码凭据,删除 `scheme/uname` |
| `im_user_security` | `auth_version`、安全状态 |
| `im_registration_invite_uses` | 邀请码使用事实,只由 IM 注册事务写 |
| `im_business_events_outbox` | 租户内业务事件,例如密码重置、邀请码使用 |
| 用户、组织、群、文件、会议、报表、信箱、实名、举报、反馈业务表 | 不带 `tenant_id`,由选库隔离 |
### 9.3 注册认证迁移后台需求
1. 增加迁移状态看板:每个租户当前 schema version、迁移批次、成功/失败数。
2. 存量用户 username 回填报告:冲突、非法字符、保留账号、自动生成结果。
3. phone 规范化报告:可转为 `+86`、重复冲突、格式异常。
4. `im_auth` 双读/切换/清理阶段状态展示。
5. 迁移前后登录回归数据:用户名登录、手机号登录、忘记密码、管理员重置密码。
6. 失败租户支持重试和导出错误明细。
## 10. 权限、审计与日志脱敏
### 10.1 权限点
P0 必须独立拆分以下权限:
1. 注册短信开关读取、修改。
2. 邀请码列表、创建、批量创建、明文查看、精确查询、撤销、批量撤销、导出。
3. 租户创建、启停、DB 配置查看、DB 配置修改。
4. 用户查看、状态修改、重置密码、撤销会话、设备查看。
5. 审计查看、审计导出。
6. Outbox 查看、重试、标记死信。
7. 外部服务敏感配置查看状态、修改。
### 10.2 审计范围
必须审计:
1. 注册短信开关变更。
2. 邀请码生成、批量生成、明文查询/查看、导出、撤销。
3. 管理员重置密码、撤销会话、禁用用户。
4. 租户创建、启停、删除流程、DB 路由配置变更。
5. 群管理员变更、禁言、转让群主、解散群。
6. 文件下载敏感证据、隔离、删除。
7. 实名审核、举报处置、反馈处理。
8. 风控挑战确认、取消、阻断。
9. 任何跨租户查看、导出和代操作。
审计字段至少包含:`request_id`、`tenant_id`、`operator_id`、`operator_role`、`action`、`target_type`、`target_id`、`result`、`ip`、`user_agent`、`detail_json`、`created_at`。
### 10.3 日志脱敏
访问日志、错误日志、审计摘要、导出任务日志不得记录以下明文:
1. 邀请码、验证码、密码、独立密码。
2. `Authorization`、`serviceSecret`、短信/Push/对象存储密钥。
3. `db_dsn`、数据库密码。
4. 身份证件、实名原始图片、敏感证据文件临时 URL。
字段名至少覆盖:`inviteCode`、`invite_code`、`code`、`verification_code`、`password`、`secret`、`serviceSecret`、`service_secret`、`authorization`、`db_dsn`。
## 11. 验收清单
### 11.1 P0
1. 平台管理员可管理租户生命周期、配置和配额,租户管理员无法越权。
2. 每个租户业务库独立,租户业务表不依赖 `tenant_id` 过滤。
3. 注册短信开关只有平台超级管理员可改,值保存为 `1/0`,IM 服务缓存期内生效。
4. 邀请码支持单个、批量、列表、精确查询、撤销、导出和使用统计。
5. 邀请码明文查看、查询、导出都有独立权限和审计。
6. 管理员重置密码写入 `im_auth`、递增 `auth_version`、写 `security.password_reset` Outbox。
7. `bootstrap` 能返回功能开关、消息策略、限制、设置菜单、工作台基础配置。
8. `hg_sys_log` 和业务日志不会泄露邀请码、密码、验证码、Token、密钥和 DSN。
### 11.2 P1
1. 用户、组织、群治理、文件治理、系统通知、Push/SMS/TURN/对象存储配置可后台管理。
2. 群成员上限、用户配额、文件配额、消息策略在并发事务中强校验。
3. 文件清理、Outbox 重试、Push 重试、搜索索引任务可观察、可重试。
4. 前端所有状态、下拉、按钮权限从字典和权限接口动态加载。
### 11.3 P2
1. 工作台、会议、日报、月报、总经理信箱配置能动态影响客户端。
2. 实名、青少年模式、反诈、举报、反馈具备策略配置、工单处理、审计。
3. App 更新策略按 platform/channel 下发,异常时不误触发强制更新。
4. 敏感证据、实名资料、诊断包具备权限、保留期和下载审计。
## 12. 已发现冲突与待确认项
1. 注册规则存在文档冲突:`IM-注册、邀请码与认证数据模型改造需求文档.md` 定义用户名和手机号是独立字段,二者同时填写时都保存;`IM-HotGo注册短信开关与邀请码管理改造交接文档.md` 的 3.1 仍写“手机号非空时忽略用户名”。建议以新的注册模型文档为准,并同步修正交接文档。
2. 邀请码批次和主表目前按交接文档放在 HotGo 控制库,带 `tenant_id`;邀请码使用事实放在租户业务库。该设计不违反“租户业务表不带 tenant_id”,但需要在实现中明确控制库和业务库边界。
3. 邀请码过期是否需要物理状态刷新任务待定。注册校验必须实时判断 `expires_at`,定时任务只能做冗余状态和统计。
4. 注册短信开关当前是平台全局配置;未来若需要企业级差异,需迁移到 `im_tenant_config` 并定义优先级。
5. 当前交接文档允许 HotGo 对部分租户库直连操作;长期是否统一收敛到 IM 管理 API 或 Kafka,需要在运维网络条件稳定后再评审。
6. 开发/测试环境固定验证码 `123456` 不能进入生产;生产必须使用强随机验证码和真实短信服务商响应。
@@ -0,0 +1,418 @@
# IM 后台菜单覆盖测试文档
## 1. 测试范围
本文档用于覆盖 IM 后台菜单从「组织架构」开始,沿左侧菜单向下逐个页面点击验证。
当前覆盖菜单顺序:
1. 组织架构
2. 文件治理
3. 注册邀请码
4. 文件策略
5. 通知模板
6. 工作台配置
7. 外部服务配置
8. 版本更新
9. 举报原因
10. 总经理信箱配置
11. 意见反馈配置
12. 任务看板
13. Kafka 命令
14. Kafka 死信
15. Kafka 审计事件
## 2. 测试环境
| 项目 | 地址 |
| --- | --- |
| 前端 | `http://127.0.0.1:8001/` |
| 后端 | `http://127.0.0.1:8000/admin` |
| 登录账号 | 使用具备 IM 管理权限的后台账号 |
| 浏览器 | Chrome,打开 DevTools Network 和 Console |
## 3. 通用检查项
每进入一个菜单页面,都先执行以下检查:
| 编号 | 检查项 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| COMMON-001 | 点击左侧菜单 | URL、页签、面包屑、页面标题正确变化 | 待测 |
| COMMON-002 | 页面首次加载 | 无白屏,无永久 loading,无明显样式错乱 | 待测 |
| COMMON-003 | Console | 无新的 JS Error,例如组件方法不存在、字典方法不存在 | 待测 |
| COMMON-004 | Network | 页面主列表接口 HTTP 200,业务响应 `code=0` | 待测 |
| COMMON-005 | 查询按钮 | 点击后列表刷新,请求参数包含搜索表单值 | 待测 |
| COMMON-006 | 重置按钮 | 搜索条件清空,列表回到默认查询 | 待测 |
| COMMON-007 | 展开/收起 | 搜索区域展开、收起正常,不遮挡表格 | 待测 |
| COMMON-008 | 表格刷新图标 | 点击后重新请求列表接口 | 待测 |
| COMMON-009 | 表格密度/列设置 | 可打开设置,切换后表格仍正常显示 | 待测 |
| COMMON-010 | 分页 | 切换页码和每页数量,请求参数正确,页面不报错 | 待测 |
说明:涉及删除、撤销、重放、清理等副作用操作时,优先使用测试数据。没有测试数据时,至少验证弹窗、参数校验、取消流程;正式执行前确认不会影响线上有效数据。
## 4. 组织架构
菜单路径:`IM管理 / 组织架构`
主要区域:部门列表、成员列表。
### 4.1 搜索与列表
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| ORG-001 | 打开「组织架构」 | 页面标题显示「组织架构」,部门列表和成员列表正常渲染 | 待测 |
| ORG-002 | 选择租户后查询部门 | 部门列表请求成功,显示部门 ID、部门名称、状态、成员数等字段 | 待测 |
| ORG-003 | 输入部门名称、状态后点击查询 | 部门列表按条件刷新 | 待测 |
| ORG-004 | 输入成员关键词、在职状态后点击查询 | 成员列表按条件刷新 | 待测 |
| ORG-005 | 点击部门行「成员」 | 成员列表切换到当前部门范围,添加成员按钮可用 | 待测 |
### 4.2 部门按钮
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| ORG-010 | 点击「新增部门」 | 打开部门编辑弹窗 | 待测 |
| ORG-011 | 新增部门弹窗点击「取消」 | 弹窗关闭,列表不刷新或数据不变化 | 待测 |
| ORG-012 | 新增部门弹窗直接点击「保存」 | 必填项校验正常展示 | 待测 |
| ORG-013 | 填写部门名称、上级部门、排序、状态后点击「保存」 | 保存成功,部门列表刷新,新部门出现 | 待测 |
| ORG-014 | 点击部门行「编辑」 | 打开编辑弹窗,已有数据正确回填 | 待测 |
| ORG-015 | 修改部门信息后点击「保存」 | 保存成功,列表展示新值 | 待测 |
| ORG-016 | 点击部门行「删除」再点取消 | 弹窗关闭,部门不删除 | 待测 |
| ORG-017 | 点击部门行「删除」并确认 | 删除成功,列表刷新;有子部门或成员时应给出清晰错误 | 待测 |
| ORG-018 | 点击「导出部门」 | 触发文件下载,导出条件与当前查询一致 | 待测 |
### 4.3 成员按钮
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| ORG-020 | 未选择部门时观察「添加成员」 | 按钮禁用或提示先选择部门 | 待测 |
| ORG-021 | 选择部门后点击「添加成员」 | 打开成员编辑弹窗,部门信息默认带入 | 待测 |
| ORG-022 | 成员弹窗直接点击「保存」 | 必填项校验正常展示 | 待测 |
| ORG-023 | 填写用户 ID、岗位、排序、可联系等信息后保存 | 保存成功,成员列表刷新 | 待测 |
| ORG-024 | 点击成员行「编辑」 | 打开编辑弹窗,成员信息正确回填 | 待测 |
| ORG-025 | 修改成员信息后保存 | 保存成功,列表展示新值 | 待测 |
| ORG-026 | 点击成员行「移除」再取消 | 弹窗关闭,成员仍保留 | 待测 |
| ORG-027 | 点击成员行「移除」并确认 | 移除成功,成员列表刷新 | 待测 |
| ORG-028 | 点击「导出成员」 | 触发文件下载,导出条件与当前查询一致 | 待测 |
## 5. 文件治理
菜单路径:`IM管理 / 文件治理`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| FILE-001 | 打开页面 | 文件列表正常展示,包含文件 ID、状态、用途、上传用户、MIME、大小、引用数等字段 | 待测 |
| FILE-002 | 按租户、文件 ID、上传用户、状态、用途、MIME、Topic、更新时间查询 | 列表按条件刷新 | 待测 |
| FILE-003 | 点击行操作「详情」 | 打开详情弹窗,展示文件基础信息和引用列表 | 待测 |
| FILE-004 | 详情弹窗关闭 | 弹窗正常关闭,列表状态不丢失 | 待测 |
| FILE-005 | 点击行操作「隔离」再取消 | 确认框正常,取消后文件状态不变 | 待测 |
| FILE-006 | 点击行操作「隔离」并确认 | 文件状态变为隔离或列表刷新后状态正确 | 待测 |
| FILE-007 | 点击行操作「删除」再取消 | 确认框正常,取消后文件不删除 | 待测 |
| FILE-008 | 点击行操作「删除」并确认 | 删除成功,列表刷新 | 待测 |
| FILE-009 | 点击「清理孤儿文件」再取消 | 确认框正常,取消后不触发清理 | 待测 |
| FILE-010 | 点击「清理孤儿文件」并确认 | 清理请求成功,页面给出成功或结果提示 | 待测 |
## 6. 注册邀请码
菜单路径:`IM管理 / 注册邀请码`
实际菜单路由:`/#/im/registrationInvite`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| INVITE-001 | 打开页面 | 邀请码列表正常展示,包含租户、邀请码、状态、批次 ID、到期时间、使用次数等字段 | 待测 |
| INVITE-002 | 平台管理员不选择租户点击「添加」 | 提示先选择租户 | 待测 |
| INVITE-003 | 选择租户后点击「添加」 | 打开生成邀请码弹窗 | 待测 |
| INVITE-004 | 生成弹窗点击「取消」 | 弹窗关闭,列表不变化 | 待测 |
| INVITE-005 | 生成弹窗清空到期时间后点击「确认」 | 表单校验提示请选择到期时间 | 待测 |
| INVITE-006 | 填写到期时间、备注后点击「确认」 | 生成成功,列表刷新并出现新邀请码 | 待测 |
| INVITE-007 | 点击「批量生成」 | 打开批量生成弹窗,包含生成数量、到期时间、备注 | 待测 |
| INVITE-008 | 批量生成数量小于 1 或大于 1000 | 表单校验拦截 | 待测 |
| INVITE-009 | 输入合法数量后确认 | 批量生成成功,列表出现同一批次的邀请码 | 待测 |
| INVITE-010 | 按邀请码、状态、批次 ID、创建人、创建时间、到期时间查询 | 列表按条件刷新 | 待测 |
| INVITE-011 | 点击行操作「批次」 | 打开批次详情弹窗,展示总数、有效、撤销、过期、使用次数和明细 | 待测 |
| INVITE-012 | 点击有效邀请码行操作「撤销」再取消 | 确认框正常,取消后状态不变 | 待测 |
| INVITE-013 | 点击有效邀请码行操作「撤销」并确认 | 撤销成功,状态变为已撤销 | 待测 |
| INVITE-014 | 点击有效批次行操作「撤销批次」再取消 | 确认框正常,取消后批次状态不变 | 待测 |
| INVITE-015 | 点击有效批次行操作「撤销批次」并确认 | 批次内有效邀请码变为已撤销 | 待测 |
| INVITE-016 | 点击「导出」 | 下载 CSV 文件,内容与当前筛选条件一致 | 待测 |
## 7. 文件策略
菜单路径:`IM管理 / 文件策略`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| FILE-POLICY-001 | 打开页面 | 策略列表正常展示,包含用途、大小上限、保留天数、自动清理、病毒扫描、MIME 白名单等字段 | 待测 |
| FILE-POLICY-002 | 按租户、用途、自动清理、病毒扫描查询 | 列表按条件刷新 | 待测 |
| FILE-POLICY-003 | 点击行操作「编辑」 | 打开编辑弹窗,字段正确回填 | 待测 |
| FILE-POLICY-004 | 编辑弹窗点击「取消」 | 弹窗关闭,数据不变化 | 待测 |
| FILE-POLICY-005 | 修改大小上限、保留天数、开关、MIME 白名单后保存 | 保存成功,列表刷新并展示新值 | 待测 |
| FILE-POLICY-006 | 输入非法大小或保留天数后保存 | 表单校验或后端错误提示清晰 | 待测 |
## 8. 通知模板
菜单路径:`IM管理 / 通知模板`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| NOTIFY-001 | 打开页面 | 模板列表正常展示,包含场景、状态、站内、Push、短信、标题模板、内容模板等字段 | 待测 |
| NOTIFY-002 | 按租户、场景、状态查询 | 列表按条件刷新 | 待测 |
| NOTIFY-003 | 点击行操作「编辑」 | 打开编辑弹窗,模板字段正确回填 | 待测 |
| NOTIFY-004 | 编辑弹窗点击「取消」 | 弹窗关闭,数据不变化 | 待测 |
| NOTIFY-005 | 修改标题模板、内容模板、站内/Push/短信开关后保存 | 保存成功,列表刷新并展示新值 | 待测 |
| NOTIFY-006 | 清空必填字段后保存 | 表单校验或后端错误提示清晰 | 待测 |
## 9. 工作台配置
菜单路径:`IM管理 / 工作台配置`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| WORKBENCH-001 | 打开页面 | 工作台模块列表正常展示,包含编码、名称、路由、排序、图标 ID、角标 Key、状态、权限等字段 | 待测 |
| WORKBENCH-002 | 按租户、编码、名称、状态查询 | 列表按条件刷新 | 待测 |
| WORKBENCH-003 | 点击「新增模块」 | 打开模块编辑弹窗 | 待测 |
| WORKBENCH-004 | 新增弹窗点击「取消」 | 弹窗关闭,列表不变化 | 待测 |
| WORKBENCH-005 | 新增弹窗直接保存 | 必填项校验正常展示 | 待测 |
| WORKBENCH-006 | 填写编码、名称、路由、排序、状态等信息后保存 | 保存成功,列表刷新 | 待测 |
| WORKBENCH-007 | 点击行操作「编辑」 | 打开编辑弹窗,字段正确回填 | 待测 |
| WORKBENCH-008 | 修改模块信息后保存 | 保存成功,列表展示新值 | 待测 |
| WORKBENCH-009 | 点击行操作「禁用」再取消 | 确认框正常,取消后状态不变 | 待测 |
| WORKBENCH-010 | 点击行操作「禁用」并确认 | 禁用成功,列表刷新后状态正确 | 待测 |
| WORKBENCH-011 | 点击「保存排序」 | 排序保存成功;列表刷新后顺序保持一致 | 待测 |
## 10. 外部服务配置
菜单路径:`IM管理 / 外部服务配置`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| EXT-CONFIG-001 | 打开页面 | 配置列表正常展示,包含服务、服务商、端点、启用、配置状态、敏感配置、检查结果等字段 | 待测 |
| EXT-CONFIG-002 | 按租户、服务、服务商、启用状态查询 | 列表按条件刷新 | 待测 |
| EXT-CONFIG-003 | 点击行操作「编辑」 | 打开编辑弹窗,字段正确回填 | 待测 |
| EXT-CONFIG-004 | 编辑弹窗切换「启用」开关 | 开关状态可变更,保存前不应提前提交 | 待测 |
| EXT-CONFIG-005 | 修改服务商、端点、配置内容后保存 | 保存成功,列表刷新并展示新值 | 待测 |
| EXT-CONFIG-006 | 点击行操作「检查」再取消 | 确认框正常,取消后不触发检查 | 待测 |
| EXT-CONFIG-007 | 点击行操作「检查」并确认 | 检查请求成功,检查结果和检查时间刷新 | 待测 |
## 11. 版本更新
菜单路径:`IM管理 / 版本更新`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| RELEASE-001 | 打开页面 | 版本策略列表正常展示,包含平台、渠道、最新版本、最低支持、更新类型、下载地址等字段 | 待测 |
| RELEASE-002 | 按租户、平台、渠道查询 | 列表按条件刷新 | 待测 |
| RELEASE-003 | 点击「新增策略」 | 打开策略编辑弹窗 | 待测 |
| RELEASE-004 | 新增弹窗直接保存 | 必填项校验正常展示 | 待测 |
| RELEASE-005 | 填写平台、渠道、版本号、更新类型、地址、发布时间后保存 | 保存成功,列表刷新 | 待测 |
| RELEASE-006 | 点击行操作「编辑」 | 打开编辑弹窗,字段正确回填 | 待测 |
| RELEASE-007 | 修改版本策略后保存 | 保存成功,列表展示新值 | 待测 |
| RELEASE-008 | 输入非法版本号或 URL 后保存 | 表单校验或后端错误提示清晰 | 待测 |
## 12. 举报原因
菜单路径:`IM管理 / 举报原因`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| ABUSE-001 | 打开页面 | 原因列表正常展示,包含对象、编码、文案、要求描述、允许证据、排序、状态等字段 | 待测 |
| ABUSE-002 | 按租户、对象、编码、状态查询 | 列表按条件刷新 | 待测 |
| ABUSE-003 | 点击「新增原因」 | 打开原因编辑弹窗 | 待测 |
| ABUSE-004 | 新增弹窗直接保存 | 必填项校验正常展示 | 待测 |
| ABUSE-005 | 填写对象、编码、文案、排序、状态等信息后保存 | 保存成功,列表刷新 | 待测 |
| ABUSE-006 | 点击行操作「编辑」 | 打开编辑弹窗,字段正确回填 | 待测 |
| ABUSE-007 | 修改原因配置后保存 | 保存成功,列表展示新值 | 待测 |
| ABUSE-008 | 点击行操作「禁用」再取消 | 确认框正常,取消后状态不变 | 待测 |
| ABUSE-009 | 点击行操作「禁用」并确认 | 禁用成功,列表刷新后状态正确 | 待测 |
## 13. 总经理信箱配置
菜单路径:`IM管理 / 总经理信箱配置`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| MAILBOX-001 | 打开页面 | 配置表单正常展示,租户选择框可用 | 待测 |
| MAILBOX-002 | 选择租户 | 自动加载该租户信箱配置 | 待测 |
| MAILBOX-003 | 点击「刷新」 | 当前租户配置重新加载,表单无异常 | 待测 |
| MAILBOX-004 | 未选择租户时观察「保存」 | 按钮禁用或提示先选择租户 | 待测 |
| MAILBOX-005 | 修改启用状态、接收人、处理策略等配置后点击「保存」 | 保存成功,再次刷新后配置保持一致 | 待测 |
| MAILBOX-006 | 输入非法配置后保存 | 表单校验或后端错误提示清晰 | 待测 |
## 14. 意见反馈配置
菜单路径:`IM管理 / 意见反馈配置`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| FEEDBACK-001 | 打开页面 | 配置表单正常展示,租户选择框可用 | 待测 |
| FEEDBACK-002 | 选择租户 | 自动加载该租户反馈配置 | 待测 |
| FEEDBACK-003 | 点击「刷新」 | 当前租户配置重新加载,表单无异常 | 待测 |
| FEEDBACK-004 | 未选择租户时观察「保存」 | 按钮禁用或提示先选择租户 | 待测 |
| FEEDBACK-005 | 修改启用状态、分类、处理人、限制策略等配置后点击「保存」 | 保存成功,再次刷新后配置保持一致 | 待测 |
| FEEDBACK-006 | 输入非法配置后保存 | 表单校验或后端错误提示清晰 | 待测 |
## 15. 任务看板
菜单路径:`IM管理 / 任务看板`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| TASK-001 | 打开页面 | 看板列表正常展示,包含租户、企业码、状态、DB、业务待投递、业务失败、群待投递、群失败、孤儿文件、待物理清理等字段 | 待测 |
| TASK-002 | 按租户、状态查询 | 列表按条件刷新 | 待测 |
| TASK-003 | 查看建议动作字段 | 异常租户展示可理解的建议动作;正常租户展示正常或为空 | 待测 |
| TASK-004 | 刷新表格 | 统计数据重新加载,无接口报错 | 待测 |
## 16. Kafka 命令
菜单路径:`IM管理 / Kafka命令`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| KAFKA-CMD-001 | 打开页面 | 命令列表正常展示,包含租户、命令 ID、事件类型、业务类型、业务 ID、状态、错误码、消息等字段 | 待测 |
| KAFKA-CMD-002 | 按租户、命令 ID、事件 ID、事件类型、业务 ID、状态、创建时间查询 | 列表按条件刷新 | 待测 |
| KAFKA-CMD-003 | 点击「发送缓存失效测试」 | 请求成功,新增一条缓存失效命令或页面提示成功 | 待测 |
| KAFKA-CMD-004 | 点击「发送工作台测试事件」 | 请求成功,新增一条工作台测试事件命令或页面提示成功 | 待测 |
| KAFKA-CMD-005 | 点击行操作「详情」 | 打开详情弹窗,展示命令 payload、结果、错误原因等信息 | 待测 |
| KAFKA-CMD-006 | 详情弹窗点击「关闭」 | 弹窗正常关闭 | 待测 |
| KAFKA-CMD-007 | 发送测试事件后等待消费结果 | 状态从待发送/已发送变为成功或失败,失败时错误信息可读 | 待测 |
## 17. Kafka 死信
菜单路径:`IM管理 / Kafka死信`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| DEAD-001 | 打开页面 | 死信列表正常展示,包含死信 ID、事件 ID、来源 Topic、消费组、事件类型、业务类型、业务 ID、状态等字段 | 待测 |
| DEAD-002 | 按租户、状态、事件类型、业务类型、业务 ID 查询 | 列表按条件刷新 | 待测 |
| DEAD-003 | 点击行操作「详情」 | 打开详情弹窗,展示死信 payload、错误原因、处理信息 | 待测 |
| DEAD-004 | 详情弹窗点击「关闭」 | 弹窗正常关闭 | 待测 |
| DEAD-005 | 详情弹窗点击「忽略」 | 操作成功,状态变为已忽略或列表刷新后状态正确 | 待测 |
| DEAD-006 | 详情弹窗点击「标记已处理」 | 操作成功,状态变为已处理 | 待测 |
| DEAD-007 | 详情弹窗点击「重放」 | 操作成功,重放次数增加,状态或处理结果正确更新 | 待测 |
| DEAD-008 | 对已处理、已忽略死信重复操作 | 系统应拦截或给出清晰提示,不出现脏状态 | 待测 |
## 18. Kafka 审计事件
菜单路径:`IM管理 / Kafka审计事件`
| 编号 | 操作 | 预期结果 | 结果 |
| --- | --- | --- | --- |
| KAFKA-AUDIT-001 | 打开页面 | 审计事件列表正常展示,包含租户、事件 ID、事件类型、动作、资源、资源 ID、操作者、结果等字段 | 待测 |
| KAFKA-AUDIT-002 | 按租户编码、事件 ID、事件类型、动作、资源、资源 ID、结果、接收时间查询 | 列表按条件刷新 | 待测 |
| KAFKA-AUDIT-003 | 点击行操作「详情」 | 打开详情弹窗,展示事件详情、请求上下文、结果信息 | 待测 |
| KAFKA-AUDIT-004 | 详情弹窗点击「关闭」 | 弹窗正常关闭 | 待测 |
## 19. 测试数据建议
| 数据类型 | 建议准备 |
| --- | --- |
| 租户 | 至少 1 个正常租户,具备独立业务库 |
| 组织架构 | 至少 1 个根部门、1 个子部门、2 个用户成员 |
| 文件治理 | 至少 1 个正常文件、1 个可隔离文件、1 个孤儿文件 |
| 注册邀请码 | 至少 1 个有效邀请码、1 个过期邀请码、1 个批次邀请码 |
| Kafka | Kafka、消费者、IM Server 正常运行;准备 1 条可产生成功结果的命令和 1 条可产生死信的命令 |
| 配置类 | 文件策略、通知模板、工作台、外部服务、版本更新、举报原因均有初始数据 |
## 20. 缺陷记录模板
| 缺陷编号 | 菜单 | 操作步骤 | 实际结果 | 预期结果 | Console/Network 信息 | 严重级别 | 状态 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| BUG-001 | | | | | | | 待处理 |
## 21. 第一轮执行记录
执行时间:2026-09-03 15:16 - 15:22
执行环境:
| 项目 | 值 |
| --- | --- |
| 前端 | `http://127.0.0.1:8001/` |
| 后端 | Docker 容器 `im-local-admin`,端口 `8000` |
| MySQL | Docker 容器 `relaxed_cori`,库 `hotgo`、`tinode`、`tinode_test` |
| Redis | Docker 容器 `brave_blackburn` |
| Kafka | Docker 容器 `kafka` |
本轮说明:
1. 从左侧菜单「组织架构」开始,按菜单顺序逐页点击。
2. 对查询、重置、展开、刷新、新增、编辑、详情等非破坏性按钮进行了点击验证。
3. 对删除、隔离、撤销、禁用、重放等有副作用的按钮,本轮只验证入口和取消流程,不确认执行。
4. 「收起」按钮在自动化脚本里先于「展开」检测,产生过误报,本轮不作为缺陷记录。
5. 「注册邀请码」菜单点击正常,真实路由为 `/#/im/registrationInvite`;直接访问 `/#/im/registrationInvite/index` 会进入 ErrorPage,测试文档已修正。
### 21.1 页面通过项
| 菜单 | 本轮结果 |
| --- | --- |
| 组织架构 | 页面可打开,查询/重置/展开/新增部门可点击;添加成员因未先选择部门处于禁用,符合预期 |
| 文件治理 | 页面可打开,查询/重置/展开/详情可点击;列表有数据 |
| 注册邀请码 | 通过左侧菜单可打开,查询/重置/展开/添加/批量生成/导出可见;列表有 2 条历史数据 |
| 工作台配置 | 页面可打开,查询/重置/展开/新增模块/编辑可点击;禁用弹窗可打开并取消 |
| 版本更新 | 页面可打开,查询/重置/展开/新增策略/编辑可点击;列表有数据 |
| 举报原因 | 页面可打开,查询/重置/展开/新增原因/编辑可点击;禁用弹窗可打开并取消 |
| 总经理信箱配置 | 页面可打开,保存/刷新按钮可见,刷新可点击 |
| 意见反馈配置 | 页面可打开,保存/刷新按钮可见,刷新可点击 |
| 任务看板 | 页面可打开,查询/重置/展开可点击 |
### 21.2 本轮发现的问题
| 缺陷编号 | 菜单 | 操作步骤 | 实际结果 | 预期结果 | 证据 | 严重级别 | 状态 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| BUG-IM-001 | 文件策略 | 点击「IM管理 / 文件策略」,或点击查询/重置 | 页面 Console 报 `检查IM文件策略失败`,列表无法加载,行操作「编辑」不可测 | 文件策略列表应正常加载,缺省策略应自动初始化 | 后端日志:`SELECT COUNT(1) FROM im_file_policy ... Error 1146: Table 'hotgo.im_file_policy' doesn't exist`;代码位置:`server/internal/logic/sys/im_file_policy.go:128` | P0 | 待处理 |
| BUG-IM-002 | 通知模板 | 点击「IM管理 / 通知模板」,或点击查询/重置 | 页面 Console 报 `检查IM通知模板失败,请稍后重试!`,列表无法加载,行操作「编辑」不可测 | 通知模板列表应正常加载,缺省模板应自动初始化 | 后端日志:`SELECT COUNT(1) FROM im_notification_template ... Error 1146: Table 'hotgo.im_notification_template' doesn't exist`;代码位置:`server/internal/logic/sys/im_notification.go:123` | P0 | 待处理 |
| BUG-IM-003 | 外部服务配置 | 点击「IM管理 / 外部服务配置」,或点击查询/重置 | 页面 Console 报 `初始化IM外部服务配置失败`,列表无法加载,行操作「编辑」「检查」不可测 | 外部服务配置列表应正常加载,缺省服务配置应自动初始化 | 后端日志:`SELECT COUNT(1) FROM im_external_config ... Error 1146: Table 'hotgo.im_external_config' doesn't exist`;代码位置:`server/internal/logic/sys/im_external_config.go:194` | P0 | 待处理 |
| BUG-IM-004 | Kafka命令 | 点击「IM管理 / Kafka命令」后点击「发送缓存失效测试」 | 页面 toast 显示 `读取IM命令Outbox失败`,Kafka 命令列表仍为 0 条 | 应写入 Outbox 并投递 Kafka,页面能看到新事件或明确状态 | 后端日志:`读取IM命令Outbox失败: element of parameter "pointer" for function Scan should type of struct/*struct/[]struct/[]*struct`;代码位置:`server/internal/library/imkafka/command.go:103` | P0 | 待处理 |
| BUG-IM-005 | Kafka命令 | 点击「发送缓存失效测试」「发送工作台测试事件」后查看数据库 | 正确表 `hotgo.im_admin_outbox` 为 0 条;带前缀表 `hotgo.hg_im_admin_outbox` 新增 3 条 pending 记录 | Admin 新增 IM 表和代码查询应统一使用无前缀 `im_*` 表,避免 `hg_im_*` 和 `im_*` 双表分裂 | MySQL:`SHOW TABLES LIKE 'hg_im_%'` 可见 `hg_im_admin_outbox`、`hg_im_admin_commands`、`hg_im_audit_events`;`hg_im_admin_outbox` 有 pending 数据,`im_admin_outbox` 为空 | P0 | 待处理 |
| BUG-IM-006 | Kafka死信 | 点击「IM管理 / Kafka死信」 | 页面可打开,但列表无数据,行操作「详情」「忽略」「标记已处理」「重放」无法覆盖 | 联调测试库应准备至少 1 条死信数据,才能覆盖处置按钮 | MySQL:`hotgo.im_kafka_dead_letter_events` 计数为 0 | P1 | 待补测试数据 |
| BUG-IM-007 | Kafka审计事件 | 点击「IM管理 / Kafka审计事件」 | 页面可打开,但列表无数据,行操作「详情」无法覆盖 | 联调测试库应准备至少 1 条审计事件数据,才能覆盖详情按钮 | MySQL:`hotgo.im_audit_events` 计数为 0 | P1 | 待补测试数据 |
### 21.3 数据库核查结果
| 库 | 表 | 结果 |
| --- | --- | --- |
| `hotgo` | `im_file_policy` | 不存在 |
| `hotgo` | `im_notification_template` | 不存在 |
| `hotgo` | `im_external_config` | 不存在 |
| `hotgo` | `im_admin_commands` | 存在,0 条 |
| `hotgo` | `im_admin_outbox` | 存在,0 条 |
| `hotgo` | `hg_im_admin_outbox` | 存在,3 条 pending |
| `hotgo` | `im_kafka_dead_letter_events` | 存在,0 条 |
| `hotgo` | `im_audit_events` | 存在,0 条 |
### 21.4 下一步建议
1. 先导入缺失表 SQL:`server/storage/data/generate/im_file_policy_menu.sql`、`server/storage/data/generate/im_notification_menu.sql`、`server/storage/data/generate/im_external_config_menu.sql`。
2. 修复 Kafka Outbox 表名前缀分裂问题,确保所有 Kafka Admin 表统一访问 `im_*`,不要落到 `hg_im_*`。
3. 修复 `DispatchOutboxByEvent` 中 `g.DB().GetOne` 触发的 `Scan` 参数类型错误。
4. 准备 Kafka 死信和 Kafka 审计事件测试数据后,重新覆盖「详情」「忽略」「标记已处理」「重放」等按钮。
5. 上述 P0 处理后,重新执行本测试文档第 4 到第 18 章。
## 22. 第二轮修复记录
执行时间:2026-09-03 15:37 - 15:50
### 22.1 已处理项
| 缺陷编号 | 处理结果 | 复测结果 |
| --- | --- | --- |
| BUG-IM-001 | 已补齐 `hotgo.im_file_policy` 表;访问文件策略列表时可自动初始化默认策略 | `/admin/imFilePolicy/list?tenantId=1` 返回 `code=0`,列表 6 条 |
| BUG-IM-002 | 已补齐 `hotgo.im_notification_template` 表;访问通知模板列表时可自动初始化默认模板 | `/admin/imNotification/templateList` 返回 `code=0`,列表 7 条 |
| BUG-IM-003 | 已补齐 `hotgo.im_external_config` 表;访问外部服务配置列表时可自动初始化默认配置 | `/admin/imExternalConfig/list?tenantId=1` 返回 `code=0`,列表 5 条 |
| BUG-IM-004 | 已修复 Kafka Admin 命令/Outbox 读写 DB,统一改为无前缀 `imRegistry` 连接 | 点击等价接口 `/admin/imKafkaCommand/cacheInvalidate` 返回 `code=0`,不再报 `读取IM命令Outbox失败` |
| BUG-IM-005 | 已修复 `im_admin_commands`、`im_admin_outbox`、`im_audit_events`、`im_kafka_dead_letter_events` 读写前缀分裂 | 新增 Kafka 测试事件写入 `hotgo.im_admin_outbox`,状态为 `sent`;没有继续写入 `hg_im_admin_outbox` |
### 22.2 额外修复
| 问题 | 处理结果 | 复测结果 |
| --- | --- | --- |
| Docker 本地 admin 缺少运行时 MySQL/Redis 环境变量导致启动 panic | 本地容器启动时显式传入 `MYSQL_DSN`、`REDIS_ADDR`、`TOKEN_SECRET_KEY` 等变量 | `im-local-admin` 正常启动,`http://127.0.0.1:8000/admin/` 可访问 |
| admin 容器内 `im-server:6060` 解析到不可用地址,死信内部查询 EOF | `config.template`、`entrypoint.sh` 增加 IM API 环境变量;本地容器使用 `IM_INTERNAL_API_BASE_URL=http://im-local-im:6060` | `/admin/imDeadLetter/list?tenantId=1` 返回 `code=0`,列表 18 条 |
| 测试库 IM 菜单中文标题乱码 | 已在测试库用 UTF-8 连接修复 `hg_admin_menu.title`;新增 `im_menu_title_repair.sql` 可重复修复 | `imManager`、`imOrgIndex`、`imFilePolicyIndex`、`imKafkaCommandIndex` 等标题查询显示正常中文 |
| 部分新增菜单 SQL 使用旧版 `hg_admin_menu` 字段 `route/is_cache/created_by/updated_by` | 已转换相关 `*_menu.sql` 菜单插入字段为当前 HotGo 表结构 | 相关 SQL 在本地 `hotgo` 库重复执行通过,无 `Unknown column 'route'` |
### 22.3 当前剩余注意项
1. 当前浏览器页签仍保存旧 token,页面上可能继续弹「登录身份已失效」;刷新并重新登录后再继续 UI 点击测试。
2. `hg_im_admin_outbox` 里还保留第一轮测试误写入的 3 条旧数据,仅用于证明旧问题,不影响新链路;后续可按运维需要清理。
3. Kafka 审计事件列表当前仍无数据,需要 IM Server 产生或导入审计事件后才能覆盖详情弹窗。
+358
View File
@@ -0,0 +1,358 @@
# IM 未实现增强项
> 更新时间:2026-08-22
> 范围:HotGo IM 后台、IM 服务端配合项、客户端动态配置来源
本文用于记录当前后台已识别但尚未完成的增强项,作为后续开发排期和验收依据。当前多租户方案为“一个 HotGo 控制库 + 每租户一个独立 IM 业务库”,租户业务表不带 `tenant_id`,后台必须通过登录态解析租户并选择租户库。
## 已完成基线
1. 邀请码管理:单个生成、批量生成、列表、批次详情、撤销、批量撤销、导出、注册短信开关。
2. 租户管理:列表、详情、编辑、状态、用量/健康、删除前检查、进入删除流程、恢复。
3. 用户管理:列表、详情、设备、重置密码、撤销会话、账号状态停用/恢复。
4. 审计日志:列表、详情、导出。
5. Outbox 运维:列表、详情、重试、标记死信,覆盖 `im_business_events_outbox` 和 `im_group_events_outbox`。
6. 租户边界:用户、审计、群、实名、工单、Outbox 等后台接口已按登录态解析租户范围。
7. 群治理处置:治理配置更新、解散群、成员禁言、解除禁言、入群审批、管理员设置/取消、群主转让、群文件删除。
## 剩余 P0
### P0-1 Bootstrap 动态配置来源
状态:未实现。
目标:
1. 后台提供 `bootstrap` 所需配置来源,包括 `features`、`message_policy`、`limits`、`settings_menu`、`workbench.modules`。
2. IM 服务端从后台配置或控制库读取后,下发给客户端。
3. 客户端不硬编码功能开关、消息策略、设置菜单和工作台基础入口。
建议实现:
1. 扩展 `im_tenant_config` 或新增独立配置表。
2. 使用 GoFrame CLI 重新生成 DAO/entity/do,禁止手改生成文件。
3. 后台提供租户配置页面,敏感字段脱敏回显。
4. IM 服务端实现配置读取和缓存,缓存失效策略单独定义。
依赖:
1. 控制库迁移 SQL。
2. IM 服务端 `bootstrap` 接口对接。
3. 客户端按返回配置裁剪 UI。
### P0-2 完整租户配置与配额
状态:部分实现。
已实现:
1. `max_users`
2. `max_groups`
3. `max_group_members`
4. 租户状态、企业码、名称、DB 路由
未实现:
1. 品牌 Logo、品牌色、登录页展示配置。
2. HTTP API、WebSocket、文件服务等终端地址。
3. 可用登录方式。
4. 密码策略。
5. 文件存储配额。
6. 功能开关配置。
7. App 更新策略基础配置。
建议实现:
1. 将基础配额、品牌、终端地址、登录方式、密码策略拆成清晰字段或 JSON 配置。
2. 对 `db_dsn`、密钥类字段只保存不明文回显。
3. 平台管理员可编辑,租户管理员按权限只读或申请变更。
### P0-3 日志脱敏统一治理
状态:未实现。
目标:
1. 访问日志、错误日志、审计摘要、导出任务日志不得泄露敏感字段。
2. 覆盖邀请码、验证码、密码、Token、服务密钥、数据库 DSN、实名证件信息。
至少覆盖字段:
1. `inviteCode`
2. `invite_code`
3. `code`
4. `verification_code`
5. `password`
6. `secret`
7. `serviceSecret`
8. `service_secret`
9. `authorization`
10. `db_dsn`
11. `id_number`
12. `token`
建议实现:
1. 在统一响应/日志中间件或日志写入前增加脱敏工具。
2. 对业务审计 `detail_json` 做字段级脱敏。
3. 补充单元测试,覆盖嵌套 JSON、大小写字段、数组对象。
### P0-4 邀请码明文查看与精确查询审计拆分
状态:部分实现。
已实现:
1. 邀请码生成、批量生成、列表、批次详情、撤销、批量撤销、导出。
2. 基础菜单权限。
待确认/增强:
1. 明文查看是否需要独立权限点。
2. 精确查询邀请码是否需要独立权限点。
3. 导出明文邀请码是否需要二次确认和独立审计。
4. 查询/查看/导出操作是否全部写入业务审计。
建议实现:
1. 增加 `imInvitePlainView` 或等价权限。
2. 列表默认脱敏,只有具备权限时显示明文。
3. 精确查询、明文查看、导出记录审计,审计中不写邀请码明文。
## 后续 P1
### P1-0 组织架构管理
状态:部分实现。
已实现:
1. 部门列表。
2. 部门新增、编辑、移动。
3. 部门删除前校验子部门和成员。
4. 部门移动防环校验。
5. 部门成员列表。
6. 成员添加、编辑、调岗、移除。
7. 组织搜索基础接口,覆盖部门和成员。
8. 组织操作写入 IM 后台审计。
9. 部门导出和成员导出。
待实现/配合:
1. 组织数据权限:当前后台按租户选库隔离,部门级 `org_admin` 数据范围尚未建模。
2. 组织导入:需要定义 Excel 字段、冲突覆盖规则、失败明细和幂等更新策略。
3. 离职用户处理策略:当前支持 `employment_state` 和 `contactable`,客户端/IM 服务端需按该状态裁剪通讯录和可联系入口。
4. 组织版本增量同步:当前维护部门/成员版本号,客户端增量同步协议需由 IM 服务端继续承接。
### P1-1 群治理处置动作
状态:已完成基础后台闭环。
已实现:
1. 群列表、详情。
2. 成员列表。
3. 治理配置查看。
4. 入群申请、邀请、公告、禁言、管理日志列表。
5. 治理配置更新。
6. 全员禁言开关。
7. 单人禁言/解禁。
8. 解散群。
9. 入群审批通过/拒绝。
10. 设置/取消管理员。
11. 转让群主。
12. 群文件列表和删除处置。
待 IM 服务端配合确认:
1. 后台写入 `im_group_events_outbox` 后,IM 服务端消费者需同步在线会话、群资料缓存和成员 ACL。
2. 群文件删除当前为业务索引软删除,底层对象文件物理清理归入 P1-2 文件治理。
### P1-2 文件治理
状态:部分实现。
已实现:
1. 文件列表。
2. 文件用途、大小、状态查询。
3. 隔离、删除。
4. 文件详情查看审计。
5. 孤儿文件手动清理。
6. 孤儿文件定时任务 `imFileCleanupOrphan`,参数为保留天数、单租户处理上限。
7. 租户级文件用途策略配置:大小上限、保留天数、MIME 白名单、自动清理开关、病毒扫描开关。
待实现/配合:
1. 下载审计:需要 IM 服务端文件下载链路或后台下载代理在实际下载时写入审计。
2. 底层对象物理删除:当前后台将 `im_fileuploads.status` 标记为已删除,物理对象清理需由文件服务或 IM 服务端清理器消费 `location`。
3. 过期文件执行:后台已提供策略配置,IM 服务端/文件清理器需读取 `im_file_policy` 后执行过期扫描、状态更新和物理清理。
4. 文件用途识别目前基于 `im_filemsglinks`/群文件索引做基础归类,头像、举报证据、反馈附件等用途需要 IM 服务端补齐绑定关系或独立索引。
5. 病毒扫描执行:后台已提供开关,实际扫描任务、扫描结果回写和用户通知需要 IM 服务端或文件服务承接。
### P1-3 外部服务配置
状态:部分实现。
已实现:
1. SMS 服务商配置。
2. Push/APNS/FCM 配置。
3. TURN/STUN 配置。
4. 对象存储配置。
5. 审核插件配置。
6. 敏感字段 `secret_json` 只写入,不明文回显,仅返回 `hasSecret`。
7. 基础配置完整性检查,写入 `status`、`checked_at`、`check_result`。
8. 配置变更和检查写入 IM 后台审计。
待实现/配合:
1. 真实连通性检查:需要各服务商 SDK 或 IM 服务端提供探测接口。
2. IM 服务端 `bootstrap`、短信、Push、TURN、对象存储、审核链路需要读取 `im_external_config`。
3. `im_external_config` 为新增控制库表,需要执行 `server/storage/data/generate/im_external_config_menu.sql`。
### P1-4 任务看板
状态:部分实现。
已实现:
1. 只读任务看板,按租户汇总 IM 业务库健康状态。
2. Outbox 巡检:统计业务事件和群事件的待投递、失败数量。
3. 文件清理巡检:统计孤儿文件和待物理清理文件数量。
4. 展示最新业务事件、最新群事件、最新文件更新时间。
5. 根据失败/待处理/待清理数量给出基础建议动作。
待实现/配合:
1. 主动执行任务:当前看板只读,不直接触发修复或调度。
2. Push 重试:需要 IM 服务端暴露 Push 失败队列、重试入口或统一任务表。
3. 搜索索引重建:需要 IM 服务端定义索引任务入口、进度查询和失败重试模型。
4. 邀请码投影补偿:需要 IM 服务端或后台定义投影任务表、幂等键和重放策略。
5. 文件物理清理任务详情:需要文件服务或 IM 服务端回写物理删除结果。
6. 跨租户任务执行审计:执行型任务落地后需补充独立权限点和审计明细。
### P1-5 系统通知模板
状态:部分实现。
已实现:
1. 租户级通知模板列表。
2. 账号安全、好友申请、群事件、文件事件、会议提醒、日报月报提醒、工单处理等默认场景初始化。
3. 站内通知、Push、短信渠道开关。
4. 标题模板、内容模板、扩展 JSON 配置。
5. 模板启用/禁用。
6. 模板变更写入 IM 后台审计。
待实现/配合:
1. 实际投递:需要 IM 服务端 Outbox 消费器或系统 Topic 桥接读取模板并发送。
2. 投递记录:需要 IM 服务端回写站内、Push、短信投递状态和失败原因。
3. 模板变量校验:当前仅校验非空和 JSON 格式,变量白名单、缺失变量检查需要按具体场景定义。
4. 多语言模板:当前为单语言模板,后续如客户端支持多语言需扩展语言维度。
## 后续 P2
### P2-1 工作台模块配置
状态:已完成基础后台闭环。
已实现:
1. 租户工作台模块列表、搜索。
2. 模块新增、编辑、启用/禁用。
3. 模块排序接口和后台入口。
4. 默认初始化组织架构、会议通知、日报、月报、总经理信箱五个入口。
5. 路由选项对齐 IM 服务端当前白名单,避免配置后客户端接口丢弃。
6. 工作台配置变更写入 IM 后台审计。
待 IM 服务端/客户端配合确认:
1. `GET /v1/im/workbench` 当前读取 `im_workbench_apps` 已具备,需在实际环境确认租户库连接与后台修改后的缓存刷新策略。
2. 用户或角色级工作台权限表 `im_workbench_user_apps` 尚未接入后台,当前只覆盖租户级模块配置。
3. 未读角标实时事件 `workbench.badge.updated` 的聚合和增量推送仍由 IM 服务端承接。
4. 新增自定义入口若超出当前五个路由,需要先扩展 IM 服务端路由白名单和客户端页面。
### P2-2 App 版本更新策略
状态:已完成基础后台闭环。
已实现:
1. 租户级客户端版本策略列表、搜索。
2. 按 `platform + channel` 配置最新版本、最低支持版本、更新类型、商店地址、安装包地址、校验值和再次提醒时间。
3. 默认初始化 iOS/Android stable 策略。
4. 配置变更写入 IM 后台审计。
待 IM 服务端/客户端配合确认:
1. `GET /v1/im/config/app-version` 已有 IM 服务端读取链路,需确认实际环境租户库数据和客户端版本比较规则。
2. 灰度比例、分渠道灰度名单、强更弹窗样式尚未建模。
### P2-3 举报原因配置
状态:已完成基础后台闭环。
已实现:
1. 按用户、群组、消息三类对象配置举报原因。
2. 支持原因新增、编辑、禁用、排序、是否要求描述、是否允许上传证据。
3. 默认初始化诈骗、骚扰、垃圾广告、违法违规等基础原因。
4. 配置变更写入 IM 后台审计。
待实现/配合:
1. 举报工单 SLA、合并策略、批量导出仍未实现。
2. 举报工单处置结果与客户端通知联动仍由后续工单模块增强。
### P2-4 总经理信箱配置
状态:已完成基础后台闭环。
已实现:
1. 租户级总经理信箱启用/禁用。
2. 匿名提交开关。
3. 必填字段、最大字数、附件策略配置。
4. 告知标题和告知内容配置,更新时同步刷新 `notice_updated_at`。
5. 配置变更写入 IM 后台审计。
待实现/配合:
1. 信箱提交列表、处理状态、回复闭环尚未实现。
2. 受理人/部门、SLA、匿名身份展示范围尚未建模。
### P2-5 意见反馈配置
状态:已完成基础后台闭环。
已实现:
1. 租户级意见反馈分类配置。
2. 最大字数、附件策略、联系方式开关、诊断信息提示配置。
3. 配置变更写入 IM 后台审计。
待实现/配合:
1. 反馈提交列表、合并、回复、导出尚未实现。
2. 客户端分类文案如需多语言,需要扩展分类结构。
### P2 待实现
1. 会议。
2. 日报/月报。
3. 总经理信箱提交处理闭环。
4. 青少年模式。
5. 反诈与内容审核策略。
6. 举报/反馈 SLA、合并、导出。
7. 实名审核策略配置。
## 验收提示
1. 所有后台租户业务操作必须通过登录态解析租户,不能信任浏览器传入的 `tenantId`。
2. 平台管理员跨租户操作必须选择租户并写审计。
3. 租户管理员隐藏租户选择器,后端使用绑定租户。
4. 所有新增按钮必须有独立菜单权限。
5. 前端字典、状态、下拉选项必须从后端字典加载。
6. 敏感字段不得在日志、审计、导出文件中明文出现。