Files
danyang-match/实时聊天、消息通知与反骚扰机制详细设计.md

39 KiB
Raw Permalink Blame History

丹阳公益婚恋服务平台

V1.0 实时聊天、消息通知与反骚扰机制详细设计

版本:V1.0
适用范围:微信小程序用户端、公益红娘工作台、运营管理后台
核心目标:只在双方明确同意后建立沟通、保证消息稳定送达、降低骚扰与诈骗风险、保护聊天隐私、确保拉黑/封禁即时生效


第一章 设计目标

V1.0聊天模块不是社交娱乐平台。

它只服务于一个明确场景:

双方互相喜欢以后,提供安全、简单、可靠的进一步沟通渠道。

因此V1.0聊天设计必须坚持:

  • 双向喜欢后才能聊天
  • 不支持陌生人私信
  • 不支持群聊
  • 不支持红包
  • 不支持转账
  • 不支持直播
  • 不支持语音房
  • 不支持“超级消息”
  • 不允许付费解锁聊天
  • 拉黑后立即停止通信
  • 风控状态变化立即影响聊天权限
  • 工作人员默认无权查看私人聊天

第二章 V1聊天功能范围

支持:

文字消息
图片消息
Emoji
系统消息
安全提醒
消息未读
已读同步
失败重试
历史记录分页
举报
拉黑
解除匹配

V1暂不支持:

语音消息
实时语音通话
视频通话
位置共享
文件
名片
红包
转账
群聊
阅后即焚
朋友圈

第三章 聊天入口规则

用户A与用户B只有同时满足:

存在有效Match
+
match.status = active / getting_to_know
+
双方账号可用
+
双方未拉黑
+
conversation.can_send = true

才允许聊天。


第四章 会话创建时机

推荐V1:

双向喜欢成功时立即创建Conversation。

流程:

A喜欢B
↓
发现B已经喜欢A
↓
创建Match
↓
创建Conversation
↓
创建双方ConversationMember
↓
发送双向匹配通知

这样用户点击:

开始聊天

时不需要额外创建会话。


第五章 Conversation状态

V1只保留:

active
closed

active:

可以聊天。

closed:

不能发送新消息。


第六章 Conversation关闭条件

以下任一情况发生:

解除匹配
A拉黑B
B拉黑A
任一方账号封禁
任一方账号关闭
风控明确禁止聊天

Conversation立即:

status = closed

双方成员:

can_send = false

第七章 历史聊天是否删除

关闭Conversation以后:

不物理删除历史聊天。

原因:

  • 用户自己仍可能需要查看历史
  • 举报取证
  • 风控调查
  • 纠纷处理

但是否继续向用户展示历史,要根据场景决定。


第八章 解除匹配后的聊天

解除匹配后建议:

历史会话保留为只读。

页面顶部:

你们已解除匹配,无法继续发送消息。

输入框:

禁用。


第九章 拉黑后的聊天

拉黑比解除匹配更强。

建议:

拉黑方:

不再看到对方正常会话入口,可在黑名单中管理。

被拉黑方:

不提示“你被谁拉黑了”。

只显示:

当前无法继续聊天。

防止引发冲突。


第十章 Conversation数据模型

建议:

conversations
conversation_members
messages

核心字段沿用前面数据库设计。


第十一章 conversation_members

至少包含:

conversation_id
user_id
last_read_message_id
unread_count
can_send
joined_at

未来即使一直是一对一聊天,也保留member结构。


第十二章 消息类型

V1:

text
image
system
risk_notice

第十三章 Text消息结构

示例:

{
  "id": "msg_xxx",
  "conversationId": "con_xxx",
  "senderId": "usr_xxx",
  "type": "text",
  "content": "你好,很高兴认识你",
  "createdAt": "2026-08-28T10:32:00+08:00",
  "status": "sent"
}

第十四章 Image消息结构

{
  "id": "msg_xxx",
  "conversationId": "con_xxx",
  "senderId": "usr_xxx",
  "type": "image",
  "fileId": "file_xxx",
  "thumbnailUrl": "...",
  "imageUrl": "...",
  "createdAt": "..."
}

图片URL:

必须为临时签名URL。


第十五章 System消息

由系统生成。

例如:

你们互相喜欢,可以开始聊天了。
你们已解除匹配。
当前会话已停止发送消息。

System消息:

用户不能伪造。

sender_id可以为空,由message_type区分。


第十六章 RiskNotice

用于安全提示。

例如:

安全提醒:婚恋交友过程中请谨慎涉及转账、借款、投资等资金往来。

RiskNotice不作为普通聊天内容的一方发言。


第十七章 WebSocket总体架构

推荐:

微信小程序
      │
      │ HTTPS
      ↓
REST API
      │
      │
      └────→ PostgreSQL
      │
      ↓
WebSocket Gateway
      │
      ↓
Redis

V1可以和主后端部署在同一个应用中。

不需要独立消息微服务。


第十八章 WebSocket连接地址

示例:

wss://api.example.com/ws

必须:

WSS。

生产不得使用:

ws://

第十九章 WebSocket认证

建立连接时:

必须验证有效登录凭证。

禁止:

userId=123

作为身份依据。

正确:

Token
↓
服务端解析
↓
得到真正userId
↓
绑定connection

第二十章 Connection状态

前端统一:

disconnected
connecting
connected
reconnecting

MessageStore统一管理。


第二十一章 WebSocket建立流程

小程序进入前台
↓
检查Token
↓
建立WS
↓
Token认证
↓
Server绑定userId
↓
connected
↓
拉取遗漏消息

第二十二章 WebSocket断线重连

断线以后:

自动重连。

建议退避:

1s
2s
5s
10s
20s
30s

最大:

30秒。

恢复后重置。


第二十三章 不要无限高频重连

如果:

  • Token失效
  • 账号封禁
  • 网络完全离线

不能每秒持续重连。

对应:

AUTH_EXPIRED
ACCOUNT_BANNED
OFFLINE

停止或降低重连。


第二十四章 微信小程序前后台切换

进入后台时:

WebSocket可能被系统暂停或断开。

重新回前台:

检查连接
↓
必要时重连
↓
同步消息
↓
刷新未读数

第二十五章 心跳

WebSocket建议:

客户端Ping
服务端Pong

间隔示例:

30~60秒

具体根据实际微信小程序网络特性调整。


第二十六章 实时事件

建议:

message.new
message.read
conversation.closed
match.created
notification.new
account.status_changed

第二十七章 message.new

示例:

{
  "event": "message.new",
  "eventId": "evt_xxx",
  "data": {
    "conversationId": "con_xxx",
    "message": {}
  }
}

第二十八章 eventId

每个实时事件建议拥有:

eventId

前端可用于:

去重。

避免断线恢复后重复消费。


第二十九章 消息发送方式

推荐V1:

消息发送走REST,实时接收走WebSocket。

即:

POST /conversations/{id}/messages

成功后:

服务端推送WebSocket。

优点:

  • 幂等更清晰
  • API测试简单
  • 弱网容易重试
  • 权限处理统一

第三十章 为什么不建议V1全部走WebSocket发送

全WebSocket双向消息虽然可行,但会增加:

  • ACK机制
  • 重发协议
  • 幂等实现
  • 连接异常处理
  • 测试复杂度

V1采用:

REST发送 + WS接收

更简单可靠。


第三十一章 clientMessageId

每条客户端消息必须生成:

clientMessageId

例如:

cm_018...

服务端唯一:

sender_id + client_message_id

第三十二章 消息发送流程

用户输入
↓
本地生成clientMessageId
↓
UI显示sending
↓
POST消息
↓
服务端鉴权
↓
验证Conversation
↓
风险检测
↓
数据库保存
↓
返回正式messageId
↓
UI sent
↓
服务端WS推送给接收方

第三十三章 发送状态

前端:

sending
sent
failed

第三十四章 Sending视觉

发送过程中:

不需要大Loading。

可使用:

小型旋转图标或灰色状态。


第三十五章 Failed视觉

失败:

!

点击:

重新发送。

必须使用原:

clientMessageId

保证不会重复。


第三十六章 服务端成功但客户端超时

典型弱网:

Server保存成功
↓
Response在网络中丢失
↓
客户端显示failed
↓
用户重试

由于clientMessageId相同:

服务端返回:

原消息。

不会插入第二条。


第三十七章 消息排序

服务端以:

created_at
+
message_id

稳定排序。

不要完全相信客户端时间。


第三十八章 客户端时间用途

客户端时间只用于:

本地临时展示。

最终:

服务端createdAt为准。


第三十九章 历史消息加载

进入聊天:

首先加载最近:

20~30条

向上滚动:

加载更早。

Cursor分页。


第四十章 消息Cursor

推荐使用:

createdAt + messageId

或数据库生成稳定cursor。

避免传统:

page=100

在实时消息变化下错乱。


第四十一章 本地聊天缓存

可以缓存:

最近少量消息。

用于:

  • 快速打开
  • 弱网显示

但长期历史仍从服务端获取。


第四十二章 不在Storage长期保存全部聊天

原因:

  • 用户隐私
  • 设备共享风险
  • 数据量大

建议只保存:

必要的近期缓存。

并设置清理策略。


第四十三章 聊天输入草稿

本地:

chatDraft[conversationId]

用户退出聊天:

保留未发送文字。


第四十四章 草稿不得同步给对方

当然只存在本地。

服务端不需要保存“正在输入内容”。


第四十五章 V1不做正在输入

不需要:

对方正在输入...

减少实时协议复杂度。


第四十六章 已读机制

用户真正打开Conversation并读取消息后:

POST /conversations/{id}/read

发送:

lastReadMessageId

第四十七章 已读位置只向前

若当前:

lastRead = msg100

旧请求晚到:

msg90

服务器必须忽略。

不能回退到msg90。


第四十八章 V1是否显示“已读”

建议:

V1不向发送者显示精确“已读”。

原因:

  • 降低社交压力
  • 减少焦虑
  • 简化产品

后台仍可维护阅读位置用于未读统计。


第四十九章 未读数计算

MessageStore:

chatUnreadCount
systemUnreadCount
totalUnreadCount

统一来源。


第五十章 新消息未读

当B不在当前Conversation:

A发消息:

B.unread_count + 1

如果B当前正在该Conversation并已加载:

可以实时标记阅读。


第五十一章 Tab Badge

消息Tab:

totalUnreadCount

超过99:

99+

第五十二章 消息列表排序

按:

last_message_at DESC

最近聊天在最上。


第五十三章 消息列表项

展示:

  • 头像
  • 展示名
  • 最近消息摘要
  • 时间
  • 未读数量

第五十四章 图片消息摘要

聊天列表:

[图片]

不要尝试自动OCR图片内容作为摘要。


第五十五章 风险系统消息摘要

可显示:

安全提醒

但不要让安全消息把真正用户消息列表全部顶掉。


第五十六章 System Notification与Chat分离

消息首页两个Tab:

聊天
系统通知

业务通知不塞进普通聊天列表。


第五十七章 系统通知分类

审核通知
匹配通知
红娘通知
活动通知
安全通知
账号通知
系统通知

第五十八章 系统通知数据结构

建议:

{
  "id": "not_xxx",
  "type": "activity",
  "title": "活动报名已通过",
  "content": "你报名的丹阳青年公益相亲会已通过审核。",
  "businessType": "activity",
  "businessId": "act_xxx",
  "read": false,
  "createdAt": "..."
}

第五十九章 通知点击跳转

根据:

businessType
businessId

跳:

review → 审核页
match → 我的缘分/聊天
activity → 活动详情
matchmaker → 红娘服务
risk → 账号状态

第六十章 通知不能传完整路由URL

后端不应任意下发:

https://...

由前端根据:

businessType

映射内部页面。

避免开放重定向。


第六十一章 通知去重

例如双向匹配事务重试。

不能生成多个:

你们互相喜欢。

唯一键可以:

user_id
+
notification_type
+
business_id

第六十二章 通知状态

unread
read

V1足够。

不需要:

  • archived
  • starred
  • deleted

第六十三章 全部已读

提供:

POST /notifications/read-all

用户可以快速清除Badge。


第六十四章 微信订阅消息的定位

微信订阅消息只用于:

重要站外提醒。

例如:

  • 审核结果
  • 活动提醒
  • 红娘服务重要更新

不能用于:

每来一条聊天都发微信订阅消息。


第六十五章 新聊天是否外部提醒

V1建议:

如果用户不在小程序:

不依赖每条聊天外部推送。

可以后续提供:

有新的婚恋消息

聚合提醒。

具体须遵循微信订阅消息实际规则。


第六十六章 反骚扰体系总体模型

反骚扰不是只靠“举报”。

体系包括:

聊天准入限制
+
发送频率限制
+
内容风险提醒
+
拉黑
+
举报
+
风险评分
+
人工处置

第六十七章 第一层:陌生人不能直接发消息

这是最重要的反骚扰规则。

因为:

没有双向喜欢,就没有聊天。

直接消除大量陌生私信骚扰。


第六十八章 第二层:发送频率限制

需要防:

  • 刷屏
  • 机器人
  • 骚扰

建议配置:

单会话短时间消息上限
单用户总发送速率
连续相同消息限制

第六十九章 不建议把正常聊天限得过死

例如:

正常用户快速连续发5句:

不应该被处罚。

限频主要拦:

极端异常速率。


第七十章 高频行为分级

例如:

Level 1:
稍微高频
→ 不处理

Level 2:
明显高频
→ 轻限速

Level 3:
机器式高频
→ 临时停止发送 + RiskEvent

阈值配置化。


第七十一章 重复文本检测

如果用户向多个对象发送:

完全相同的营销话术。

可以记录:

DUPLICATE_MESSAGE_SPAM

风险事件。


第七十二章 跨会话群发

例如同一用户:

1分钟内
向10个不同Match
发送完全相同内容

非常值得关注。

系统:

  • 风险加分
  • 限速
  • 人工关注

第七十三章 联系方式识别

聊天中可以允许用户:

自主交换联系方式。

所以不能像Profile一样完全禁止手机号和微信号。

但大量、高频向不同用户发送联系方式:

可能是引流/营销。

需要结合频率判断。


第七十四章 Profile与Chat的区别

Profile:

不允许放联系方式。

Chat:

双向Match后允许用户自主交流。

这是重要规则差异。


第七十五章 资金风险词

重点词组:

转账
借钱
投资
理财
虚拟币
博彩
贷款
刷单
银行卡
高收益
项目投资
资金周转

命中:

风险提醒。


第七十六章 普通关键词提示

第一次风险命中:

系统插入:

安全提醒:
婚恋交友过程中请谨慎涉及资金往来,
不要轻信投资、借款或高收益项目。

第七十七章 同一会话不要反复提示

例如用户正常聊银行工作。

不能每次出现“投资”都插一条黄色提醒。

建议:

同类风险提示
24小时/一段会话内
最多提示1次

具体可配置。


第七十八章 风险提示冷却

例如:

money_warning cooldown = 24h

这样避免干扰。


第七十九章 严重风险组合

单关键词不处罚。

但是组合行为:

多用户举报诈骗
+
高频发送投资话术
+
多人拉黑

风险显著提高。


第八十章 风险评分不在聊天UI显示

不能告诉用户:

对方风险分82

除非账号已经进入明确处置状态。


第八十一章 被多人拉黑

被多人拉黑:

是风险信号。

但也可能是正常婚恋拒绝。

所以权重不能过高。

结合:

  • 举报
  • 高频消息
  • 重复话术

综合判断。


第八十二章 单会话举报入口

聊天右上角:

···

包含:

查看资料
解除匹配
举报
拉黑

第八十三章 举报聊天时的证据方式

用户可以:

直接选择举报当前用户。

系统自动关联:

conversationId

并允许用户选择:

相关聊天时间范围/截图。


第八十四章 不建议让用户手工截所有聊天

如果用户举报:

平台内部已有Conversation。

可以让系统后台在授权调查时:

查询相关上下文。

用户可额外上传截图作为补充。


第八十五章 举报关联信息

Report可以记录:

conversation_id
related_message_ids

这样风控查看更准确。


第八十六章 风控人员聊天访问

默认:

无权限。

处理举报时:

只有拥有:

message.content.review

才能访问。

同时写:

Sensitive Access Log。


第八十七章 红娘不能查看用户聊天

即使红娘负责双方用户:

也不能查看两人的私人聊天。

红娘只能根据用户主动反馈:

“不知道怎么聊”

给一般建议。


第八十八章 红娘聊天辅助

用户申请:

不知道怎么开始聊天。

红娘可以:

  • 给聊天建议
  • 给破冰话题
  • 根据公开资料建议话题

不能:

登录用户账号替他聊天。


第八十九章 V1不做AI代聊

不提供:

AI自动替用户回复。

避免:

  • 身份真实性问题
  • 情感欺骗
  • 误发内容
  • 责任不清

第九十章 可以后续提供的辅助

未来最多考虑:

用户主动点击“帮我润色一句”。

且必须:

  • 用户确认
  • AI不自动发送

V1不做。


第九十一章 图片消息安全

用户聊天图片上传:

必须:

  • 图片格式校验
  • 大小校验
  • EXIF清理
  • 风险扫描
  • 私有存储

第九十二章 图片消息审核策略

V1可以:

机器基础安全检测 + 举报后人工处理。

是否每张聊天图片人工预审:

不建议。

会严重影响隐私与成本。


第九十三章 明显非法图片

如果自动内容安全服务识别到:

高置信度违法/色情内容。

可以:

  • 阻止发送
  • 记录风险事件
  • 必要时人工复核

第九十四章 图片失败

图片上传成功但消息发送失败:

文件成为:

未绑定临时对象。

定时任务清理。


第九十五章 上传图片大小

建议:

原图 ≤ 10MB

后端:

压缩。

聊天展示不需要保存巨大原图。


第九十六章 图片预览

点击图片:

全屏预览。

禁止自动保存到相册。

如用户主动保存:

使用系统正常授权流程。


第九十七章 消息撤回

V1建议:

暂不做消息撤回。

原因:

  • 增加状态复杂度
  • 举报取证更复杂
  • 不是核心需求

第九十八章 删除聊天

V1可以不提供:

删除整个Conversation。

如果未来提供:

只做:

用户侧隐藏

而不是物理删除系统记录。


第九十九章 敏感词与内容过滤

区分:

非法内容
风险内容
普通敏感场景

非法内容:

阻止。

风险内容:

提醒或进入风控。

普通敏感场景:

正常允许。


第一百章 不要建立超大关键词黑名单

维护成本高,误伤严重。

V1重点:

小而明确的反诈骗/违法规则集。


第一百零一章 安全规则配置

后台可维护:

消息发送频率阈值
重复文本阈值
风险关键词
风险提示冷却
高风险分数阈值

但修改必须:

Audit。


第一百零二章 规则配置不要让普通运营改

权限:

risk.rule.manage

仅安全管理员。


第一百零三章 用户主动拉黑流程

点击拉黑
↓
二次确认
↓
POST block
↓
建立blocked关系
↓
Match失效/聊天关闭
↓
更新缓存
↓
WS通知相关客户端状态变化

第一百零四章 拉黑确认文案

建议:

拉黑后,对方将无法继续与你聊天,
你们也不会再互相出现在推荐中。

确认拉黑?

按钮:

确认拉黑
取消

第一百零五章 被拉黑方通知

不要发送:

“王女士拉黑了你。”

这样可能引发线下冲突。

只在其尝试访问Conversation时:

当前无法继续聊天。


第一百零六章 解除匹配流程

用户选择解除匹配
↓
选择原因
↓
确认
↓
Match = unmatched
↓
Conversation关闭
↓
双方不再继续聊天

第一百零七章 解除匹配是否通知对方

建议:

系统通知对方“该匹配关系已结束”。

不要显示:

对方选择你的原因。

例如:

当前匹配关系已结束,双方将无法继续发送消息。

第一百零八章 为什么不展示Unmatch原因

原因可能造成:

  • 伤害
  • 争执
  • 报复

原因只用于:

内部产品分析。


第一百零九章 Match成功后的第一条系统消息

建议:

你们互相喜欢,可以开始进一步了解了。

下面安全说明:

请注意保护个人隐私,谨慎涉及转账、
借款、投资等资金往来。

第一百一十章 第一次聊天安全提醒

顶部NoticeBar显示一次。

用户关闭后:

当前Conversation不再重复顶部显示。

但风险命中仍可出现RiskNotice。


第一百一十一章 安全提醒本地状态

可存:

conversationSafetyNoticeClosed[conversationId]

只是UI偏好。

不是安全业务真相。


第一百一十二章 账号封禁实时流程

后台封禁A:

RiskService更新AccountStatus
↓
关闭A所有发送能力
↓
缓存失效
↓
WebSocket发送 account.status_changed
↓
客户端UserStore刷新
↓
聊天输入框全部禁用

第一百一十三章 封禁后已有消息

历史消息不删除。

对方看到:

当前用户暂时无法联系。

具体文案不要暴露内部风控细节。


第一百一十四章 临时限制与永久封禁区别

feature_limit:

可能只限制Like或消息。

temporary_suspend:

核心婚恋功能暂停。

ban:

严重限制账号。

MessageService每次发送都读取:

当前有效权限。


第一百一十五章 不只在登录时检查风控

用户登录后可能过几个小时才被限制。

因此:

每次发送消息必须重新检查账号聊天能力。


第一百一十六章 Redis可缓存聊天能力

可以缓存:

chat_permission:{userId}

但User状态变化:

必须立即失效。

安全关键接口不能长期使用过期缓存。


第一百一十七章 消息接口限流

至少:

按user
按conversation
按IP/Session

结合。


第一百一十八章 上传接口限流

防止:

用户疯狂上传图片占存储。

限制:

  • 单用户单位时间上传数
  • 单日总量
  • 单文件大小

第一百一十九章 消息长度

文字建议:

1~1000字符

具体可配置。

超过:

提示分段发送。

不需要支持一条几万字。


第一百二十章 空消息

纯空格:

拒绝。

Emoji:

正常允许。


第一百二十一章 URL链接

聊天中用户可能发送链接。

V1建议:

以纯文本展示。

不要自动:

生成富卡片预览。

原因:

  • 安全
  • 防钓鱼
  • 开发简单

第一百二十二章 可疑链接提示

如果检测到:

外部网址

可以轻提示:

打开陌生链接请注意安全。

但不要每条网址都阻断。


第一百二十三章 V1不支持二维码扫描跳转

聊天图片里即使有二维码:

平台不主动识别并跳转。

减少诈骗跳转风险。


第一百二十四章 通知系统服务边界

所有业务模块:

不要自己写:

INSERT notifications...

统一:

NotificationService

第一百二十五章 Notification事件来源

例如:

ProfileApproved
MutualMatchCreated
ActivityRegistrationApproved
MatchmakerRecommendationCreated
RiskActionCreated

由Notification模块消费。


第一百二十六章 通知失败补偿

建议建立:

notification_delivery_tasks

或简单任务表/重试机制。

不强制MQ。


第一百二十七章 站内通知和微信通知分离

状态:

in_app_created
wechat_pending
wechat_sent
wechat_failed

站内通知成功:

即认为核心通知存在。

微信订阅消息失败:

不影响业务。


第一百二十八章 通知发送优先级

高:

  • 账号安全
  • 活动取消
  • 审核结果
  • Match成功

中:

  • 红娘推荐
  • 活动报名结果

低:

  • 普通运营提醒

第一百二十九章 不做营销推送

V1不推:

  • “快来看看新用户”
  • “今天桃花运爆棚”
  • “已有3人偷偷喜欢你”

避免商业婚恋套路。


第一百三十章 喜欢我的通知

用户被Like:

V1可以:

系统通知有新的喜欢。

但不要过度刺激。

建议:

有人表达了想进一步了解你的意愿。

也可以只在:

我的缘分 → 喜欢我的

展示。

具体通知频率可配置。


第一百三十一章 批量聚合通知

如果短时间收到多个Like:

不要发5条通知。

可以:

你收到了新的喜欢。

聚合处理。


第一百三十二章 聊天数据访问权限矩阵

角色 会话列表 聊天正文
用户本人 自己的 自己的
公益红娘 否 否
活动管理员 否 否
审核员 否 否
普通管理员 否 否
风控员 关联案件必要范围 特殊权限
超级管理员 默认否 特殊授权

第一百三十三章 聊天数据库查询接口

普通后台不要提供:

GET /admin/users/{id}/messages

这种入口。

风控使用专门接口:

GET /admin/risk/reports/{reportId}/conversation-context

只能围绕案件访问。


第一百三十四章 风控聊天查询范围

参数可以:

beforeMessageId
afterMessageId
limit

限制上下文数量。

避免一次加载全部历史。


第一百三十五章 所有风控查询必须Audit

记录:

operatorId
reportId
conversationId
range
reason
time

第一百三十六章 消息保留策略

V1不在本章拍死具体年限。

必须由:

数据生命周期政策 + 法律合规审查

确定。

系统需要支持:

  • 按用户/时间删除或匿名化
  • 注销处理
  • 纠纷保留
  • 安全调查保留

第一百三十七章 用户注销对聊天影响

注销后:

can_send = false

历史Conversation中:

展示名可变为:

用户已注销

头像:

中性占位图。


第一百三十八章 注销用户消息内容

历史消息是否保留:

按平台数据保留政策处理。

不能简单因为注销:

让另一方历史聊天全部报错。


第一百三十九章 消息搜索

V1不做:

全局聊天内容搜索。

用户端也暂不需要聊天记录搜索。

降低开发与隐私复杂度。


第一百四十章 后台不做聊天大数据分析

V1不建设:

  • 聊天情感分析
  • AI全量监听
  • 聊天画像
  • 关系亲密度预测

风险检测只做:

最小必要的安全规则。


第一百四十一章 监控指标

技术监控:

WebSocket在线连接数
连接成功率
重连率
消息发送成功率
消息发送P95
消息失败率
上传失败率

第一百四十二章 业务安全指标

每千次会话举报数
被拉黑率
高频发送账号数
重复文本风险账号
资金类风险提醒数量
诈骗举报数

第一百四十三章 不把“聊天多”作为成功核心指标

聊天消息数量大:

不代表婚恋效果好。

真正关注:

Match后聊天启动率
持续沟通率
正在了解率
成功牵手率

第一百四十四章 Conversation长期沉默

例如Match后:

30天双方都未发消息。

可以标记:

inactive。

但V1不需要自动关闭。


第一百四十五章 是否做破冰提示

可以轻量提供:

不知道怎么开始?
可以从兴趣、工作和周末生活聊起。

不需要AI。


第一百四十六章 破冰提示不要自动发送

只作为:

用户自己看的提示。

绝不能自动替用户发:

“你好,你也喜欢旅行吗?”


第一百四十七章 聊天首屏示例

← 王女士                           ···

安全提醒
请保护个人隐私,谨慎涉及转账、
借款、投资等资金往来。         ×

          你们互相喜欢
      可以开始进一步了解了

[头像] 你好,很高兴认识你

             你好,我也是

────────────────────────

😊  输入消息...                  +

第一百四十八章 Conversation关闭示例

← 王女士

历史聊天内容……

────────────────────────

当前匹配关系已结束,
无法继续发送消息。

不显示Input。


第一百四十九章 被风控限制示例

当前账号部分功能暂时受限,
暂时无法发送消息。

[查看账号状态]

第一百五十章 消息服务内部模块建议

ConversationService
MessageService
MessagePermissionService
MessageRiskService
UnreadService
RealtimePushService
NotificationService

仍属于模块化单体。


第一百五十一章 MessagePermissionService

负责:

用户是否属于Conversation
Match是否有效
Block关系
AccountStatus
Conversation状态
can_send

所有发送请求统一调用。


第一百五十二章 MessageRiskService

负责:

  • 消息频率
  • 重复文本
  • 风险关键词
  • 可疑外链
  • 风险事件

不负责:

永久封禁决定。

严重事件交Risk模块。


第一百五十三章 UnreadService

统一维护:

conversation unread
chat total
notification unread
total unread

防止多个模块各算一套。


第一百五十四章 RealtimePushService

只负责:

把已经发生的业务事件推给在线客户端。

不能把WebSocket当业务数据库。


第一百五十五章 Redis在实时消息中的用途

可以:

  • userId → connection/node映射
  • 在线状态
  • 未读缓存
  • Pub/Sub跨实例推送

如果V1只有单实例:

Redis Pub/Sub甚至可以暂时不使用。

但接口设计应方便未来扩展。


第一百五十六章 多实例未来扩展

未来后端2台:

Backend A
Backend B

用户A连接A。

用户B连接B。

消息保存后:

Redis Pub/Sub通知B实例。

V1先预留。


第一百五十七章 不建议V1引入Kafka

实时聊天量在丹阳本地初期无需Kafka。

优先:

PostgreSQL + Redis + WebSocket。


第一百五十八章 消息数据库写入优先

原则:

先落库
↓
再推送

不要:

先推给对方
↓
数据库写入失败

否则双方消息状态会错乱。


第一百五十九章 推送失败

消息已经落库:

仍是成功。

接收方下一次:

  • 打开消息页
  • WS重连
  • 拉取增量

都能看到。


第一百六十章 消息同步Cursor

客户端保存:

lastMessageSyncCursor

重连:

GET /messages/sync?cursor=...

可作为未来接口。


第一百六十一章 V1是否必须做全局sync接口

不是绝对必须。

可以先:

重连后刷新Conversation列表 + 当前Conversation。

但建议预留:

/messages/sync

以后更稳。


第一百六十二章 服务端事件顺序

事件至少包含:

eventId
occurredAt

客户端遇到顺序异常:

最终以REST拉取的服务端状态为准。


第一百六十三章 网络恢复策略

断网时:

用户输入:

草稿保留。

发送失败:

failed。

恢复网络:

不自动把所有失败消息无限发送。

建议:

用户点击重试

或仅对明确未提交成功的消息做有限重试。


第一百六十四章 图片消息弱网

图片上传过程中断:

显示失败。

重新上传。

不要产生:

空白Image消息。


第一百六十五章 安全降级

Risk关键词服务异常:

普通消息:

可以在满足基础安全条件下继续发送。

但:

  • AccountStatus
  • Block
  • Conversation权限

这些核心安全检查不可绕过。


第一百六十六章 权限服务异常

如果无法判断:

当前用户是否属于Conversation。

必须:

Fail Closed。

拒绝发送。


第一百六十七章 用户隐私设置和聊天

用户关闭:

visibleInSearch

不会自动关闭已有Match聊天。

隐私曝光和已有关系:

分开。


第一百六十八章 paused状态和聊天

用户暂停寻找:

仍可继续已有聊天。

暂停的含义是:

不寻找新人。

不是:

强制断掉已有沟通。


第一百六十九章 getting_to_know和聊天

正常保留。

甚至这是聊天最主要阶段。


第一百七十章 successful状态和聊天

成功牵手后:

已有双方Conversation继续保留。

平台不强制关闭。


第一百七十一章 多Match聊天

用户可能同时有多个Mutual Match。

每个Conversation独立。

V1不人为限制:

只能聊一个人。


第一百七十二章 红娘是否知道用户有多少会话

红娘可以看到:

用户匹配/服务摘要

但不需要看到:

  • 聊天对象详情列表
  • 聊天内容

只提供服务必要的有限状态。


第一百七十三章 防骚扰优先级

Block
>
Account Restriction
>
Conversation Status
>
Message Rate Limit
>
Risk Warning

第一百七十四章 用户主动权

任何时候用户都能:

  • 不回复
  • 解除匹配
  • 拉黑
  • 举报

不需要经过红娘批准。


第一百七十五章 Chat API验收

必须测试:

无Match发消息
单向Like发消息
有效Match发消息
已Unmatch发消息
被Block发消息
账号被封禁发消息
重复clientMessageId
消息超长
空消息
图片失败

第一百七十六章 实时通信验收

必须测试:

  • 双方在线
  • 一方离线
  • WS断线重连
  • 微信切后台再回来
  • Token过期
  • 账号实时封禁
  • 消息重复推送
  • 消息乱序
  • 推送失败后REST恢复

第一百七十七章 未读验收

确保:

聊天列表未读
消息Tab Badge
Conversation已读
系统通知未读

数据一致。


第一百七十八章 反骚扰验收

模拟:

  • 1秒发100条
  • 多会话复制广告
  • 连续发送联系方式
  • 多人举报
  • 资金关键词
  • 多次拉黑
  • 正常用户快速聊天

必须:

拦异常,但不能严重误伤正常沟通。


第一百七十九章 隐私验收

必须测试:

  • 红娘查看聊天 → 拒绝
  • 活动管理员查看聊天 → 拒绝
  • 普通管理员获取聊天 → 拒绝
  • 风控员无案件访问 → 拒绝
  • 有权限风控员关联举报访问 → 允许并审计

第一百八十章 V1明确不开发

语音通话
视频通话
语音房
群聊
直播
红包
支付
礼物
阅后即焚
消息撤回
聊天记录全局搜索
AI自动回复
AI代聊
自动情感分析
恋爱亲密度评分
“正在输入”状态
已读回执展示

第一百八十一章 开发优先级

P0

Conversation
Text Message
Message Permission
REST发送
WebSocket接收
未读
历史分页
失败重试
Unmatch关闭
Block关闭
AccountStatus实时限制

P1

Image Message
RiskNotice
发送限频
重复文本检测
系统通知
微信订阅消息封装

P2

更完善的增量Sync
聚合通知
反Spam规则优化
消息性能统计

第一百八十二章 最终架构

                ┌─────────────────┐
                │ 微信小程序客户端 │
                └───────┬─────────┘
                        │
             HTTPS      │      WSS
              ↓         │       ↓
        ┌──────────┐    │  ┌──────────────┐
        │ REST API │    │  │ WebSocket    │
        └────┬─────┘    │  │ Gateway      │
             │          │  └──────┬───────┘
             ↓          │         │
        MessageService  │         │
             │          │         │
       ┌─────┼─────┐    │         │
       ↓     ↓     ↓    │         │
 Permission Risk  Unread│         │
       │     │     │    │         │
       └─────┼─────┘    │         │
             ↓          │         │
         PostgreSQL     │       Redis
             │          │
             ↓          │
      RealtimePush ─────┘

第一百八十三章 最终设计原则

V1.0实时聊天与消息体系必须坚持:

没有双向喜欢,就没有聊天。

消息先落库,再实时推送。

每条消息都有客户端幂等ID。

WebSocket断线不能造成消息丢失。

拉黑、解除匹配和封禁必须立即停止发送。

暂停寻找不影响已有正常聊天。

工作人员默认没有查看私人聊天的权限。

风险关键词用于提醒和发现风险,不用于简单粗暴定罪。

用户可以自主拉黑、举报、结束匹配。

V1只做可靠沟通,不把聊天模块做成复杂社交平台。

最终要达到的体验不是:

“功能很多。”

而是:

双方愿意聊的时候,消息稳定、简单、安全;不愿意继续的时候,可以立即、明确、没有负担地结束沟通。