228 lines
10 KiB
Markdown
228 lines
10 KiB
Markdown
# IM 剩余问题修复方案
|
||
|
||
整理时间:2026-09-18
|
||
|
||
本文记录当前暂未完成的三个后端问题:青少年模式业务限制、Web 平台版本检查、消息搜索召回稳定性。
|
||
|
||
更新记录:
|
||
|
||
- 2026-09-18:P1 第一阶段已处理 Web 平台版本检查与消息搜索召回兜底;青少年模式已完成第一阶段策略层、夜间通话限制和消息内容过滤接入,剩余支付守护、好友/群邀请、Push 等全链路限制继续按 P2 增强。
|
||
|
||
## 1. 青少年模式业务限制未强制执行
|
||
|
||
### 现状
|
||
|
||
当前后端已经具备青少年模式的基础状态能力:
|
||
|
||
- `GET /v1/im/settings/youth-mode` 可返回 `enabled`、`policy_version`、`restrictions`、`restriction_items`。
|
||
- `POST /v1/im/settings/youth-mode/enable` 和 `disable` 已完成开启、关闭和独立密码校验链路。
|
||
- `im_youth_mode_settings` 已保存用户维度的启用状态、策略版本、限制项和密码状态。
|
||
|
||
第一阶段已将 `night_quiet` 接入音视频呼叫发起限制,将 `content_filter` 接入消息发送前内容安全审核,并把这两项 `restriction_items[].enforced` 改为 `true`。`payment_guard` 以及好友申请、群邀请、系统通知/Push 等更大范围入口仍未完整接入。
|
||
|
||
### 问题影响
|
||
|
||
如果只保存开关、不做服务端限制,客户端隐藏入口不能形成安全边界。用户可以通过旧客户端、重新安装、直接调用接口或构造 WebSocket 消息绕过限制。
|
||
|
||
### 建议修复方案
|
||
|
||
建议将青少年模式拆成一个统一策略检查层,例如 `imYouthPolicy` 或 `impolicy/youth`,所有关键入口调用同一套判断逻辑。
|
||
|
||
第一阶段建议先落这几个限制:
|
||
|
||
| 限制项 | 建议拦截点 | 修复方式 |
|
||
| --- | --- | --- |
|
||
| `night_quiet` 深夜免打扰 | 发消息、音视频呼叫、系统通知/Push | 服务端读取用户青少年状态和当前时间段,限制指定时段内发起呼叫或降低通知等级。 |
|
||
| `content_filter` 内容过滤 | 发文本、发链接、上传后发布文件、资料/群资料修改 | 复用现有内容安全/风险审核能力;命中高风险时拒绝或进入审核状态。 |
|
||
| `payment_guard` 支付守护 | 充值、购买、付费功能入口 | 当前 IM 暂无支付主链路,先预留统一错误码和策略接口,后续支付接口接入时强制调用。 |
|
||
|
||
建议新增统一返回:
|
||
|
||
```json
|
||
{
|
||
"code": 30005,
|
||
"reason": "YOUTH_MODE_RESTRICTED",
|
||
"message": "restricted by youth mode",
|
||
"details": {
|
||
"restriction": "night_quiet",
|
||
"policy_version": 1
|
||
}
|
||
}
|
||
```
|
||
|
||
### 建议改造点
|
||
|
||
- `server/im_http.go`
|
||
- HTTP 发消息、转发、收藏转发、好友申请、群邀请、音视频相关接口前置检查。
|
||
- `youthModeRestrictionItems` 中已真正接入的规则将 `enforced` 改为 `true`。
|
||
- `server/topic.go`
|
||
- 原生 WebSocket `{pub}` 保存消息前执行相同策略,避免绕过 HTTP。
|
||
- `server/store/store.go`
|
||
- 增加按用户读取青少年模式的轻量缓存,短 TTL 即可。
|
||
- `docs/IM-青少年模式前后端对接文档.md`
|
||
- 补充哪些接口会返回 `YOUTH_MODE_RESTRICTED`。
|
||
|
||
### 验收建议
|
||
|
||
- 开启青少年模式后,旧客户端直接发消息不能绕过限制。
|
||
- HTTP 和 WebSocket 两条链路限制结果一致。
|
||
- 关闭青少年模式后限制即时解除。
|
||
- `restriction_items[].enforced` 只对已经服务端强制执行的规则返回 `true`。
|
||
|
||
### 当前处理状态
|
||
|
||
已新增统一策略判断 `imYouthModePolicyDecision`。当前行为:
|
||
|
||
- `night_quiet`:青少年模式开启且带该限制时,22:00-06:00 发起音视频呼叫返回 `YOUTH_MODE_RESTRICTED`。
|
||
- `content_filter`:普通 WS 消息发送前进入内容安全审核,文本、文件名、链接 URL 等可展示内容会参与提取。
|
||
- `payment_guard`:仍为预留项,返回 `enforced=false`,后续支付或付费功能接入时再强制调用。
|
||
|
||
## 2. Web 平台版本检查接口缺失
|
||
|
||
### 现状
|
||
|
||
当前版本检查接口为:
|
||
|
||
```http
|
||
GET /v1/im/app/releases/latest?platform=ios|android¤t_version=1.0.0&channel=stable
|
||
```
|
||
|
||
当前实现和文档主要覆盖 `ios`、`android`。Web 客户端如果调用 `platform=web`,会因为平台枚举未支持而无法得到可用版本配置。
|
||
|
||
### 问题影响
|
||
|
||
Web 端无法统一读取版本策略、升级提示、最低支持版本和发布说明。后续如果 Web 端需要灰度、强刷、维护提示或版本兼容控制,只能靠前端硬编码。
|
||
|
||
### 建议修复方案
|
||
|
||
将 `web` 加入 App Release 平台枚举。平台建议统一为:
|
||
|
||
```text
|
||
ios, android, web
|
||
```
|
||
|
||
Web 响应建议保持与移动端同结构:
|
||
|
||
```json
|
||
{
|
||
"current_version": "1.0.0",
|
||
"has_update": false,
|
||
"force_update": false,
|
||
"platform": "web",
|
||
"channel": "stable",
|
||
"latest_version": "1.0.0",
|
||
"min_supported_version": "1.0.0",
|
||
"update_type": "none",
|
||
"package_url": "",
|
||
"store_url": "",
|
||
"release_notes": "当前已是最新版本。",
|
||
"remind_after_seconds": 0
|
||
}
|
||
```
|
||
|
||
Web 没有安装包时,`package_url` 和 `store_url` 可以为空;如果需要强刷或维护提示,可通过 `update_type=required` 和 `release_notes` 传达。
|
||
|
||
### 建议改造点
|
||
|
||
- `server/im_http.go`
|
||
- 放开 `platform=web` 参数校验。
|
||
- 保持 `current_version` 必传。
|
||
- `server/db/mysql/adapter.go` 或 App Release 相关存储实现
|
||
- 确认 `im_app_releases.platform` 没有限制 `web`。
|
||
- 如数据库通过字典/配置初始化版本记录,需要补默认 Web 记录。
|
||
- `docs/IM-App版本更新前后端对接文档.md`
|
||
- 补充 Web 平台示例。
|
||
- `docs/IM-前后端对接文档.md`
|
||
- 将 `platform=ios|android` 更新为 `ios|android|web`。
|
||
|
||
### 验收建议
|
||
|
||
- `platform=web¤t_version=1.0.0&channel=stable` 返回 200。
|
||
- `platform=invalid` 仍返回参数错误。
|
||
- Web 无更新、推荐更新、强制更新三类数据都能按同一结构返回。
|
||
|
||
### 当前处理状态
|
||
|
||
已在 `serveIMAppReleaseLatest` 放开 `platform=web`,并补充 Web 平台单元测试。对接文档已同步更新为 `ios|android|web`。
|
||
|
||
## 3. 消息搜索召回稳定性待复核
|
||
|
||
### 现状
|
||
|
||
当前接口为:
|
||
|
||
```http
|
||
GET /v1/im/topics/{topic}/messages/search?q=&type=text&cursor=
|
||
GET /v1/im/topics/{topic}/messages/search?type=file&q=&cursor=
|
||
```
|
||
|
||
现有后端已经能返回 `seq`、`from`、`ts`、`snippet`、`matches`、`snapshot`、`availability` 等字段。但问题清单中仍记录了“部分明显应该命中的关键词搜索返回空结果”的现象。该问题目前属于待复核项,可能来源包括:
|
||
|
||
- 搜索范围只覆盖部分消息内容字段,没有覆盖所有文本来源。
|
||
- 结构化消息中正文可能存在于 `content.text`、`content.txt`、`content.title`、`content.summary`、Drafty 或文件快照字段中,索引/过滤口径不一致。
|
||
- 中文分词、大小写、空格、标点归一化不一致。
|
||
- 分页游标与过滤顺序不一致,导致命中项被跳过。
|
||
- 热消息、分表消息和历史消息的查询路径不一致。
|
||
|
||
### 问题影响
|
||
|
||
搜索结果不稳定会直接影响聊天记录检索、文件检索、收藏定位和问题复盘。用户明知道某条消息存在,但搜索不到,会被认为是数据丢失。
|
||
|
||
### 建议修复方案
|
||
|
||
第一阶段先做“确定性兜底”,不急于引入复杂搜索引擎:
|
||
|
||
1. 明确搜索字段规范。
|
||
- 文本消息:统一提取 `content.text`、`content.txt`、`content.content`、`content.title`、`content.summary`、字符串 content。
|
||
- 文件消息:统一提取文件名、mime、文件说明、消息文本。
|
||
- 链接/名片/合并转发:提取标题、摘要、展示文本。
|
||
2. 增加 `message_search_text` 生成函数。
|
||
- 写入消息时生成可搜索文本。
|
||
- 老数据可查询时动态 fallback。
|
||
3. 查询顺序固定。
|
||
- 先按用户权限和 topic 过滤可见消息。
|
||
- 再按搜索文本匹配。
|
||
- 最后按 `seq desc` 或 `created_at desc` 分页。
|
||
4. 中文和符号归一化。
|
||
- 至少做大小写归一、前后空格、连续空白压缩、全角半角基础处理。
|
||
5. 增加回归测试。
|
||
- 普通文本、中文关键词、文件名、链接标题、转发快照、撤回/删除消息、分页边界都要覆盖。
|
||
|
||
第二阶段如果数据量和体验要求更高,再考虑引入专用搜索索引:
|
||
|
||
- MySQL FULLTEXT/ngram。
|
||
- OpenSearch/Elasticsearch。
|
||
- 独立 `im_message_search_index` 表,按 topic、seq、search_text 存储轻量索引。
|
||
|
||
### 建议改造点
|
||
|
||
- `server/im_http.go`
|
||
- `messageText` 和 `messageSearchPayload` 的提取逻辑继续收口,保证响应与查询使用同一文本口径。
|
||
- `server/db/mysql/adapter.go` 或消息查询实现
|
||
- 检查 `TenantMessageSearch` 的 SQL 过滤条件和分页顺序。
|
||
- 确认群消息分表 `im_group_messages_YYYYMM` 与私聊消息表搜索路径一致。
|
||
- `server/store/types`
|
||
- 如新增搜索索引表,补结构体和迁移 SQL。
|
||
- `docs/IM-前后端对接文档.md`
|
||
- 明确搜索匹配字段、排序规则和 `availability` 行为。
|
||
|
||
### 验收建议
|
||
|
||
- 同一 topic 下创建 20 条混合消息,逐条用关键词可搜到。
|
||
- 搜索中文短词、英文大小写、文件名、链接标题均有稳定结果。
|
||
- 翻页时不丢边界记录、不重复。
|
||
- 被删除/撤回消息按 `availability` 返回或按产品规则隐藏,行为一致。
|
||
- 私聊和群聊搜索结果字段一致。
|
||
|
||
### 当前处理状态
|
||
|
||
已完成第一阶段确定性兜底:私聊和群聊搜索不再只依赖 SQL `LIKE` 命中消息 JSON 原文,改为先按权限、Topic、类型和游标读取固定窗口,再对结构化文本做统一提取和归一化匹配。当前覆盖文本、文件名、标题、摘要、链接、卡片和转发快照等字段,并补充结构化内容召回测试。
|
||
|
||
## 建议排期
|
||
|
||
| 优先级 | 项目 | 原因 |
|
||
| --- | --- | --- |
|
||
| P1 | Web 平台版本检查 | 改动小,边界清楚,适合快速补齐。 |
|
||
| P1 | 消息搜索召回复核 | 影响用户感知,需要先补测试锁定问题。 |
|
||
| P2 | 青少年模式业务限制 | 涉及多个入口和策略口径,需要独立设计和联调,不能只改一个接口。 |
|