Files
danyang-match/核心业务规则、状态机与异常处理设计.md
T

35 KiB
Raw Permalink Blame History

丹阳公益婚恋服务平台

V1.0 核心业务规则、状态机与异常处理设计

版本:V1.0
适用范围:微信小程序用户端、公益红娘工作台、运营管理后台
目标:保证关键业务状态一致、规则明确、异常可恢复、并发不重复、前后台行为统一


第一章 文档目标

本文件重点解决以下问题:

  • 用户什么时候可以进入匹配
  • 审核状态怎么流转
  • 喜欢和双向喜欢如何生成
  • 什么情况下可以聊天
  • 拉黑、解除匹配后发生什么
  • “正在了解”和“成功牵手”如何处理
  • 活动报名、审核、签到如何流转
  • 红娘服务如何分配和结束
  • 举报、风控、封禁如何处理
  • 并发操作时如何避免重复
  • 异常发生后如何恢复
  • 前端、后端、后台如何保持同一状态

核心原则:

所有关键业务都必须有明确状态机,不能通过页面临时逻辑决定业务结果。


第二章 状态机设计总原则

所有核心状态都遵循:

当前状态
↓
校验操作权限
↓
校验业务前置条件
↓
执行状态迁移
↓
写数据库
↓
触发副作用
↓
通知前端/用户

禁止:

页面点按钮
↓
前端直接改状态
↓
后端被动接受

第三章 状态迁移必须服务端控制

例如:

用户不能直接提交:

{
  "relationshipStatus": "matched_successfully"
}

服务端必须验证:

  • 当前是否存在有效Match
  • 是否有成功牵手请求
  • 对方是否确认
  • 双方账号是否正常

满足后才允许状态改变。


第四章 用户总状态体系

用户平台状态由四个维度共同决定:

账号状态 AccountStatus

实名状态 VerificationStatus

资料审核状态 ReviewStatus

婚恋状态 RelationshipStatus

四者彼此独立,但共同决定用户能力。


第五章 AccountStatus

状态:

normal
reviewing_risk
limited
suspended
banned
closed

第六章 AccountStatus能力矩阵

状态 登录 查看自己 推荐 喜欢 聊天 活动 红娘
normal 是 是 是 是 是 是 是
reviewing_risk 是 是 否/受限 否 受限 受限 受限
limited 是 是 受限 否 受限 视策略 视策略
suspended 是 是 否 否 否 否 否
banned 是 是 否 否 否 否 否
closed 否/仅注销提示 否 否 否 否 否 否

实际限制由RiskAction进一步决定。


第七章 VerificationStatus

not_verified
verifying
verified
failed
manual_review

只有:

verified

才能进入资料完整填写和正式匹配流程。


第八章 Profile Review状态

not_submitted
pending
processing
approved
need_edit
rejected

第九章 审核状态机

not_submitted
      ↓ 提交
pending
      ↓ 领取
processing
   ├──────────────┐
   ↓              ↓
approved       need_edit
                  ↓ 用户修改重提
                pending

processing
      ↓ 严重违规
rejected

第十章 审核允许迁移

允许:

not_submitted → pending

pending → processing

processing → approved

processing → need_edit

processing → rejected

need_edit → pending

第十一章 审核禁止迁移

禁止:

approved → pending

直接由普通前端操作触发。

如果用户修改敏感资料:

应创建:

新的ReviewTask

而不是把旧审核记录改回pending。


第十二章 敏感资料修改规则

以下修改必须重新审核:

  • 主头像
  • 生活照片
  • 自我介绍
  • 婚姻状态
  • 其他人工审核字段

新流程:

原资料 approved
↓
用户修改
↓
创建 profile_change review
↓
新内容待审核

第十三章 修改期间展示规则

建议V1采用:

已审核旧版本继续对外展示,新版本审核通过后替换。

这样避免用户修改一句自我介绍后:

整个账号退出匹配池。

但以下情况例外:

婚姻状态变更

如果从:

未婚 → 离异等重大变化

建议立即暂停推荐,待重新审核。


第十四章 审核领取并发规则

两个审核员同时点击领取。

仅第一个成功。

数据库:

UPDATE review_tasks
SET status='processing'
WHERE id=?
AND status='pending'

影响行数:

1 = 成功
0 = 已被别人领取

前端提示:

该任务已由其他工作人员领取。


第十五章 审核超时规则

如果审核员领取后长时间未处理,例如:

30分钟或运营配置时间

可以:

  • 提醒审核员
  • 管理员重新分配

不要自动直接把任务变回pending导致重复操作。


第十六章 RelationshipStatus

searching
getting_to_know
paused
matched_successfully
service_exited

第十七章 婚恋状态迁移

searching
 ├→ paused
 ├→ getting_to_know
 └→ service_exited

paused
 ├→ searching
 └→ service_exited

getting_to_know
 ├→ searching
 ├→ paused
 ├→ matched_successfully
 └→ service_exited

matched_successfully
 └→ 特殊人工恢复/关系结束流程

service_exited
 └→ 用户重新启用婚恋服务(后续规则)

第十八章 searching规则

用户在searching状态:

允许:

  • 出现在推荐池
  • 主动找对象
  • 喜欢别人
  • 被别人喜欢
  • 接受红娘推荐
  • 参加活动

前提:

账号和审核状态正常。


第十九章 paused规则

paused时:

recommendation_enabled = false
visible_in_recommendations = false

默认:

不进入推荐池。

已有聊天:

保留。

已有Match:

保留。


第二十章 getting_to_know规则

用户设置:

正在了解

时必须明确是否:

pauseOtherRecommendations = true/false

如果true:

  • 不再生成新推荐
  • 不再出现在找对象列表
  • 已有匹配关系保留

如果false:

仍允许继续使用匹配功能。


第二十一章 matched_successfully规则

双方确认成功牵手后:

relationship_status = matched_successfully
recommendation_enabled = false
visible_in_recommendations = false

双方:

  • 不再收到新推荐
  • 不再出现在找对象
  • 不再接受普通红娘推荐
  • 已有聊天保留

第二十二章 成功牵手不可单方完成

流程:

A发起成功牵手
↓
status = pending
↓
B收到确认
├→ 确认
│  ↓
│ successful
│
└→ 拒绝
   ↓
declined

只有确认后:

双方婚恋状态一起更新。


第二十三章 成功牵手并发规则

A和B可能同时发起。

系统必须识别:

同一个Match已有pending成功请求。

第二个请求:

可以直接合并成确认。

不要生成两条独立成功请求。


第二十四章 成功牵手取消问题

V1不建议用户随意一键取消“成功牵手”。

如果关系结束并重新寻找:

建议走:

重新开启婚恋服务

并记录历史。

不能删除之前成功记录。


第二十五章 用户关系基础状态

单向关系:

neutral
liked
passed
blocked

双向关系:

mutual_match

第二十六章 Like状态机

初始:

neutral

A喜欢B:

neutral → liked

如果B已经喜欢A:

liked + reverse liked
↓
mutual_match

第二十七章 Like前置条件

必须同时满足:

  • A账号正常
  • B账号正常
  • A资料审核通过
  • B资料审核通过
  • A当前允许寻找
  • B当前允许被发现
  • A没有拉黑B
  • B没有拉黑A
  • A != B

第二十八章 Like禁止场景

禁止:

  • 喜欢自己
  • 喜欢已封禁用户
  • 喜欢被自己拉黑用户
  • 喜欢已经拉黑自己的用户
  • 审核未通过用户点击喜欢
  • 已退出婚恋服务用户点击喜欢

第二十九章 重复喜欢

A已经liked B。

再次请求:

不创建新数据。

返回:

ALREADY_LIKED

或者幂等返回:

relationStatus = liked

推荐采用:

幂等成功。

前端体验更稳定。


第三十章 取消喜欢

仅适用于:

尚未形成mutual_match。

如果已经双向匹配:

不能:

取消喜欢来解除关系。

必须:

解除匹配。


第三十一章 Pass规则

A点击不合适:

neutral / liked未匹配
→ passed

如果A之前liked但尚未匹配:

可以:

覆盖为passed

并清除/失效liked。

实现上建议保留历史事件,但当前关系以passed为准。


第三十二章 Pass冷却

用户pass后:

系统在配置周期内不再推荐。

例如:

180天。

后续可以允许重新出现。

但blocked:

永久排除,直到解除拉黑。


第三十三章 Mutual Match状态机

当双方liked:

no_match
↓
active

之后:

active
├→ getting_to_know
├→ unmatched
└→ successful

第三十四章 Mutual Match唯一规则

一对用户只能存在:

一个当前Match实体。

标准化:

userA = min(user1,user2)
userB = max(user1,user2)

数据库唯一约束。


第三十五章 同时点赞并发

A和B同一毫秒点击喜欢。

两边事务都可能检测。

最终依赖:

  • user_relation唯一约束
  • match pair唯一约束
  • duplicate key捕获

保证:

只创建一个Match。


第三十六章 Match创建后副作用

Match成功后:

主事务必须完成:

  • Match记录
  • Conversation记录
  • ConversationMembers

事务提交后:

  • 创建系统通知
  • WebSocket通知
  • 统计+1

通知失败:

不能回滚Match。


第三十七章 Chat开启规则

只有:

match.status = active
OR getting_to_know

且:

  • 双方账号可用
  • 双方未拉黑
  • conversation.can_send = true

才能聊天。


第三十八章 没有双向喜欢不能聊天

无论用户是否:

  • 搜索到对方
  • 被红娘推荐
  • 活动认识
  • 单向喜欢

都不能直接聊天。

必须形成:

双方明确同意。


第三十九章 红娘推荐与聊天关系

红娘推荐:

红娘 → 用户A推荐B

不创建:

  • like
  • match
  • conversation

A点击喜欢后:

仍然等B喜欢A。


第四十章 活动互选与聊天

活动结束:

A选择B感兴趣。

B也选择A。

系统可以直接视为:

双方明确意向

因此可以生成Match。

但前端应明确告知:

你们在本次活动中互相选择,可以开始交流。


第四十一章 Conversation状态

建议:

active
closed

不需要V1搞复杂。


第四十二章 Conversation关闭场景

以下事件关闭发送能力:

  • 解除匹配
  • 任一方拉黑
  • 任一方账号封禁
  • 账号关闭

历史聊天可以保留。


第四十三章 Unmatch规则

任何一方可以解除匹配。

请求:

match.status = active/getting_to_know

执行:

match.status → unmatched
conversation.can_send → false

第四十四章 解除匹配后的推荐

默认:

双方进入较长排除期。

建议:

不再主动推荐。

是否未来重新出现,可配置。

V1建议:

默认长期排除。


第四十五章 解除匹配不等于拉黑

解除匹配:

不继续了解。

拉黑:

不希望对方再看到/联系自己。

两者必须分开。


第四十六章 Block状态机

neutral / liked / mutual_match / unmatched
↓
blocked

拉黑优先级最高。


第四十七章 拉黑后的即时副作用

必须立即:

  • 停止双方聊天
  • 移除推荐
  • 移除搜索可见关系
  • 移除喜欢列表展示
  • 红娘候选排除
  • 活动推荐关系排除

第四十八章 解除拉黑

解除后:

blocked → neutral

但:

  • 不恢复旧Like
  • 不恢复旧Match
  • 不恢复旧Conversation发送能力

如果以后重新匹配:

重新走喜欢流程。


第四十九章 举报与拉黑关系

举报不自动拉黑。

用户可以:

举报后选择是否同时拉黑。

严重风险场景前端可以提示:

是否同时拉黑该用户?


第五十章 Message状态机

客户端消息:

local
↓
sending
├→ sent
└→ failed

服务端消息:

accepted
↓
persisted
↓
delivered(可选)
↓
read

V1数据库可只保留:

sent/read相关必要状态。


第五十一章 消息幂等规则

每条发送请求:

sender_id + client_message_id

唯一。

弱网重发:

返回原消息。

不能生成重复文本。


第五十二章 消息发送前置校验

发送前必须校验:

  1. Conversation存在
  2. 当前用户属于Conversation
  3. Conversation可发送
  4. Match有效
  5. 双方未拉黑
  6. 双方账号正常
  7. 内容合法
  8. 频率未超限

第五十三章 Message发送异常恢复

情况:

数据库已经保存,但WebSocket返回失败。

客户端重试同一clientMessageId:

服务端查询原消息并返回。

这样避免:

用户看到重复消息。


第五十四章 未读数规则

接收方新消息:

unread_count + 1

进入会话并读到:

last_read_message_id

服务端计算/更新:

unread_count。


第五十五章 已读并发

客户端可能重复调用read。

接口必须幂等。

只允许:

lastReadMessage位置向前推进。

不能因为旧请求晚到:

把已读位置回退。


第五十六章 聊天风险提示规则

检测到普通风险关键词:

提醒,不拦截。

例如:

  • 转账
  • 借钱
  • 投资

系统插入:

risk_notice。


第五十七章 严重消息风险

如果命中明显诈骗模板、高频群发等:

可以:

  • 创建RiskEvent
  • 提高风险分
  • 临时限速
  • 进入人工关注

但V1不建议:

单凭一个关键词直接永久封禁。


第五十八章 Activity状态机

draft
↓ 发布
registration_open
↓ 截止
registration_closed
↓ 开始
ongoing
↓ 结束
ended

另有:

draft / registration_open
↓
cancelled

第五十九章 活动状态迁移规则

允许:

draft → registration_open
registration_open → registration_closed
registration_closed → ongoing
ongoing → ended

管理员取消:

draft → cancelled
registration_open → cancelled
registration_closed → cancelled

第六十章 活动禁止迁移

禁止普通操作:

ended → registration_open
cancelled → ongoing

如果运营误操作:

应复制创建新活动,而不是倒退旧活动。


第六十一章 ActivityRegistration状态机

not_applied
↓
pending
├→ approved
├→ rejected
└→ cancelled

若活动无需审核:

not_applied → approved

第六十二章 报名前置条件

必须:

  • 用户实名
  • 用户审核通过
  • 账号正常
  • 活动报名中
  • 年龄符合
  • 未重复报名
  • 名额可用

第六十三章 活动年龄规则

年龄必须:

服务端根据birth_date计算。

不能相信前端传age。


第六十四章 活动报名并发

如果最后一个名额:

多人同时报名。

必须在事务中:

  • 锁定活动或计数资源
  • 检查剩余名额
  • 写报名

最终:

不能超额。


第六十五章 待审核是否占名额

V1必须明确规则。

建议:

pending暂不占正式名额,approved才占名额。

原因:

工作人员需要审核。

但这样可能:

待审核人数大于剩余名额。

后台应提示:

通过时按剩余名额校验。


第六十六章 无需审核活动

如果:

need_review = false

报名事务中直接:

approved并占名额。


第六十七章 报名拒绝

拒绝后:

pending → rejected

必须记录原因。

用户收到通知。


第六十八章 活动取消

活动取消后:

  • 所有用户收到通知
  • 报名记录保留
  • 签到关闭
  • 不物理删除报名

状态:

activity = cancelled

第六十九章 签到前置条件

只有:

  • activity有效
  • registration = approved
  • 未签到
  • token有效

才可签到。


第七十章 重复签到

重复扫码:

返回:

已签到 + 原签到时间。

不要报系统错误。


第七十一章 签到Token规则

签到二维码Token:

  • 短时有效
  • 签名
  • 不直接暴露userId
  • 与activity绑定

过期:

客户端重新获取。


第七十二章 活动反馈规则

只有:

  • 已报名
  • 活动已结束

才允许提交反馈。

是否必须签到:

建议:

只有已签到用户可提交完整活动反馈。

未签到用户可提交:

未参与原因(以后可加)。


第七十三章 活动互选规则

用户只能选择:

  • 同一活动
  • 实际允许被选择的参与者
  • 未被拉黑
  • 账号正常

不能通过修改userId选择任意平台用户。


第七十四章 MatchmakerService状态机

submitted
↓ 分配
assigned
↓ 开始服务
in_service
├→ waiting_user
│    ↓
│ in_service
└→ completed

submitted/assigned
→ cancelled

第七十五章 红娘服务申请规则

用户可以申请:

  • 推荐对象
  • 调整择偶条件
  • 联系意向对象
  • 活动帮助
  • 匹配困难
  • 沟通帮助

同类型服务若已有:

in_service

建议限制重复提交。

返回:

SERVICE_ALREADY_ACTIVE


第七十六章 红娘接单并发

两位红娘同时接单。

采用数据库原子更新。

只允许一个成功。

失败:

该服务已由其他红娘接单。


第七十七章 红娘服务权限

红娘只能操作:

  • 自己被分配的服务
  • 或所在机构授权服务

不能通过修改serviceId查看其他机构数据。


第七十八章 红娘推荐前置条件

推荐B给A前必须:

  • A服务有效
  • B审核通过
  • B账号正常
  • B可被推荐
  • 双方无拉黑
  • 双方required条件不冲突

第七十九章 红娘不能突破硬条件

即便红娘认为“很合适”。

如果用户设置:

必须符合

而候选人不符合:

系统不允许推荐。

除非:

用户本人先修改条件。


第八十章 红娘服务完成

完成前建议至少:

  • 有跟进记录
  • 或有明确处理结果

例如:

已推荐3位
用户暂时暂停服务
用户已成功牵手
未找到合适对象

第八十一章 红娘超时提醒

如果服务:

3天/配置时间未跟进

后台显示:

超时待跟进。

不自动结束服务。


第八十二章 Report状态机

pending
↓ 受理
processing
├→ confirmed
├→ rejected
└→ insufficient_evidence

第八十三章 举报结果与处置分离

Report结果:

举报是否成立。

RiskAction:

对用户采取什么措施。

不要把二者混成一个status。

例如:

report = confirmed
riskAction = warning

或:

report = confirmed
riskAction = ban

第八十四章 RiskLevel状态

normal
watch
high
critical

风险等级用于:

排序和关注。

不是直接等于账号状态。


第八十五章 风险处置状态

RiskAction:

warning
feature_limit
temporary_suspend
ban
manual_investigation

第八十六章 风控副作用

例如 temporary_suspend:

必须同步:

  • AccountStatus
  • Match推荐排除
  • Like禁止
  • Chat发送禁止
  • 活动报名禁止
  • 红娘服务限制

第八十七章 风控处置事务

建议主事务:

创建RiskAction
↓
更新User AccountStatus
↓
写AuditLog

事务后:

  • WebSocket通知客户端
  • Notification通知用户
  • 缓存失效

第八十八章 风控状态实时生效

不能等用户下次登录。

如果用户正在聊天时被封禁:

下一次:

  • WebSocket状态事件
  • 或任何API响应

必须让客户端更新状态并停止发送。


第八十九章 Appeal申诉状态机

pending
↓
processing
├→ approved
└→ rejected

approved:

可能:

  • 撤销RiskAction
  • 恢复AccountStatus

但必须保留原始风险记录。


第九十章 风控误判恢复

撤销封禁:

risk_action.revoked_at = now

更新用户:

根据仍然生效的其他RiskAction重新计算最终AccountStatus。

不能简单:

account_status = normal

因为可能还有其他限制。


第九十一章 Notification规则

业务状态变化后产生通知。

典型事件:

  • 审核通过
  • 审核退回
  • 双向喜欢
  • 红娘推荐
  • 活动审核通过
  • 活动取消
  • 风险处置
  • 成功牵手确认

第九十二章 通知失败不影响主业务

例如:

活动报名已审核通过

Notification服务失败。

不能:

把报名状态回滚。

应:

  • 业务成功
  • 通知进入补偿队列/任务

第九十三章 通知去重

相同业务事件:

例如同一match:

不得重复发送10次“互相喜欢”。

建议:

event_type + business_id + user_id

做去重Key。


第九十四章 用户删除/注销状态机

V1建议:

normal account
↓ 用户申请注销
closing(可选)
↓ 完成
closed

如果不做等待期:

可以直接:

closed

但仍需服务端完成数据退出流程。


第九十五章 注销后的副作用

必须:

  • 停止推荐
  • 隐藏资料
  • 禁止Like
  • 禁止新消息
  • 停止红娘服务
  • 取消未开始活动报名视业务处理
  • 关闭登录会话

第九十六章 注销不删除历史关系

保留:

  • Match历史
  • 举报
  • 审核
  • 审计
  • 活动记录

展示时:

已注销用户

而不是查询失败导致数据链断裂。


第九十七章 Session状态异常

Token过期:

AUTH_EXPIRED

前端:

  • 保存安全草稿
  • 尝试refresh
  • refresh失败才回登录

第九十八章 服务端状态比前端新

例如前端显示:

审核通过

但后台刚封禁。

任何关键API:

必须重新校验数据库/缓存中的最新账号状态。

不能因为前端旧状态继续执行。


第九十九章 缓存一致性规则

关键状态变化:

必须主动失效相关缓存。

例如拉黑:

推荐缓存
用户详情缓存
关系缓存
红娘候选缓存

都需要失效。


第一百章 推荐缓存不能绕过状态校验

即使推荐列表已经缓存:

返回给客户端之前仍需快速检查:

  • target账号
  • target审核状态
  • 是否拉黑
  • 是否暂停曝光

第一百零一章 用户详情失效

用户打开详情时:

如果对方刚被封禁。

返回:

TARGET_UNAVAILABLE

前端:

该用户当前不可查看。


第一百零二章 关键业务错误分类

分为:

可重试错误
不可重试业务错误
权限错误
状态冲突
系统错误

第一百零三章 可重试错误

例如:

  • 网络超时
  • 短暂数据库连接失败
  • 对象存储临时失败

前端:

可以重试。


第一百零四章 不可重试业务错误

例如:

PROFILE_NOT_APPROVED
ACTIVITY_FULL
BLOCKED_RELATION
TARGET_UNAVAILABLE

前端不能无限重试。

应改变页面状态。


第一百零五章 状态冲突

例如:

审核员操作:

任务已被别人处理。

返回:

STATE_CONFLICT

前端:

刷新当前数据。


第一百零六章 系统错误

后端500:

前端统一:

操作暂时未完成,请稍后重试。

不能展示:

  • SQL异常
  • Java堆栈
  • Node错误对象

第一百零七章 幂等业务总览

必须幂等:

Like
Pass
Block
提交审核
活动报名
活动签到
红娘申请
消息发送
举报
成功牵手请求

第一百零八章 幂等成功优先

如果同一请求重复到达,但第一次已经成功:

推荐返回:

原成功结果

而不是:

“重复错误”。

这样弱网体验更好。


第一百零九章 数据库唯一约束兜底

关键唯一约束:

  • user relation
  • match pair
  • activity registration
  • message client ID
  • conversation match ID

应用逻辑不能代替数据库约束。


第一百一十章 事务与副作用边界

原则:

核心业务数据在事务内。

通知、统计、推送等副作用在事务后。


第一百一十一章 双向喜欢事务

事务内:

写liked
检查reverse liked
创建match
创建conversation
创建members

事务后:

通知
WebSocket
统计

第一百一十二章 活动报名事务

事务内:

检查活动
检查名额
创建/更新registration

事务后:

发送报名通知
统计

第一百一十三章 举报处理事务

事务内:

更新report
创建risk event
创建risk action
更新account status
audit

事务后:

通知
WebSocket
缓存失效

第一百一十四章 超时补偿任务

建议至少有:

  • 通知补发
  • 活动状态补正
  • 审核超时提醒
  • 红娘跟进超时提醒
  • 风险状态重算
  • 缓存重建

第一百一十五章 失败补偿原则

如果副作用失败:

可重试。

如果核心事务失败:

整体回滚。

不要出现:

Match没创建,但发了“互相喜欢”通知。


第一百一十六章 软删除业务规则

用户照片删除:

soft delete。

活动删除:

如果草稿可soft delete。

已发布活动:

优先cancelled。

不能物理删除造成历史断裂。


第一百一十七章 状态操作审计范围

后台以下动作必须Audit:

  • 审核通过/退回
  • 用户封禁/解封
  • 风控处置
  • 红娘分配
  • 活动取消
  • 权限调整
  • 查看敏感数据
  • 匹配规则修改

第一百一十八章 普通用户操作日志

不需要所有点击都做Audit。

但关键业务事件应留业务记录:

  • Like
  • Match
  • Unmatch
  • Block
  • 举报
  • 成功牵手

第一百一十九章 异常场景一:喜欢时对方被封禁

流程:

A打开旧详情
↓
B刚被封禁
↓
A点击喜欢
↓
服务端重新校验
↓
TARGET_UNAVAILABLE

前端:

该用户当前不可继续了解。

并移除卡片。


第一百二十章 异常场景二:双方同时解除/拉黑

A解除匹配,B同时拉黑A。

最终:

  • Match = unmatched
  • Block关系存在
  • Conversation关闭

Block优先级高。


第一百二十一章 异常场景三:活动最后一个名额

A和B同时审核通过。

数据库事务保证:

只有一个通过。

另一个:

ACTIVITY_FULL

工作人员界面刷新。


第一百二十二章 异常场景四:报名时活动被取消

客户端打开旧页面。

提交报名。

服务端:

检查activity.status

返回:

ACTIVITY_NOT_OPEN

前端刷新活动详情。


第一百二十三章 异常场景五:聊天中对方拉黑

A正在输入。

B拉黑A。

A发送:

BLOCKED_RELATION

前端:

  • 停止发送
  • 关闭输入框
  • 显示“当前无法继续聊天”

第一百二十四章 异常场景六:审核中用户修改资料

V1建议:

审核pending/processing期间:

禁止修改正在审核的关键字段。

提示:

资料正在审核中,审核完成后可继续修改。

避免审核版本混乱。


第一百二十五章 异常场景七:红娘候选失效

红娘打开候选B。

B随后暂停寻找。

红娘点击推荐:

服务端重新校验。

返回:

TARGET_UNAVAILABLE

候选从列表移除。


第一百二十六章 异常场景八:成功牵手确认时Match已解除

A发起成功。

期间双方解除匹配。

B再点击确认。

服务端:

MATCH_NOT_ACTIVE

成功请求标记:

cancelled/invalid。


第一百二十七章 异常场景九:用户注销时有未开始活动

V1建议:

注销前提示:

你有已报名活动,注销后报名将自动取消。

用户确认注销后:

  • 未开始活动报名 → cancelled
  • 已结束活动记录保留

第一百二十八章 异常场景十:管理员误重复处理举报

第二次resolve:

如果Report已经final状态:

返回:

REPORT_ALREADY_RESOLVED

不能创建第二个重复RiskAction。


第一百二十九章 业务优先级冲突规则

当多个状态冲突时:

优先级建议:

账号安全状态
>
拉黑关系
>
审核状态
>
婚恋状态
>
普通Match关系
>
UI偏好

第一百三十章 示例:用户审核通过但被封禁

即使:

review = approved

但:

account = banned

最终:

禁止匹配和聊天。

AccountStatus优先。


第一百三十一章 示例:双方Match但一方拉黑

即使:

match = active

但:

block = true

最终:

不能聊天。

Block优先。


第一百三十二章 示例:正在了解但用户主动暂停

如果:

relationship = getting_to_know

并且:

recommendation_enabled = false

最终:

不推荐新人,但保留已有聊天。


第一百三十三章 状态最终来源

最终业务真相来自:

PostgreSQL。

Redis:

缓存。

前端Store:

展示。

任何冲突:

以服务端数据库状态为准。


第一百三十四章 状态更新时间

所有状态变化必须包含:

updated_at

关键状态应额外记录:

approved_at
matched_at
unmatched_at
successful_at
processed_at

方便审计和统计。


第一百三十五章 状态变更原因

以下状态必须记录原因:

  • 审核need_edit/rejected
  • 解除匹配
  • 举报处理
  • 风控处置
  • 活动拒绝
  • 账号封禁
  • 申诉处理

不能只有状态没有原因。


第一百三十六章 用户可见原因与后台原因分离

例如封禁:

后台内部:

多次举报+疑似诈骗话术。

用户前台:

账号因安全风险暂时受限。

必要时再显示合规的具体说明。

避免泄露举报人信息。


第一百三十七章 状态机测试策略

每一个状态机至少测试:

  • 正常前向迁移
  • 非法逆向迁移
  • 重复请求
  • 并发请求
  • 权限不足
  • 对象失效
  • 网络重试

第一百三十八章 审核状态测试

必须覆盖:

not_submitted → pending
pending → processing
processing → approved
processing → need_edit
need_edit → pending

同时测试:

approved → pending

被拒绝。


第一百三十九章 Match测试

必须覆盖:

  • 单向Like
  • 双向Like
  • 同时Like
  • 重复Like
  • 拉黑后Like
  • Unmatch后聊天
  • 成功牵手确认

第一百四十章 活动测试

必须覆盖:

  • 正常报名
  • 重复报名
  • 最后名额并发
  • 审核通过
  • 活动取消
  • 重复签到
  • Token过期

第一百四十一章 红娘测试

必须覆盖:

  • 重复申请
  • 两人同时接单
  • 推荐失效用户
  • 红娘越权查看
  • 已完成服务再次操作

第一百四十二章 风控测试

必须覆盖:

  • 举报成立
  • 举报不成立
  • 多次举报
  • 封禁实时生效
  • 解封
  • 申诉通过
  • 多个RiskAction同时存在

第一百四十三章 前后端状态码统一

前端不要自己推断:

“按钮灰了所以应该是审核中”。

后端明确返回:

reviewStatus
accountStatus
relationshipStatus
relationStatus
activityStatus
serviceStatus

第一百四十四章 状态字典统一

所有枚举建议放共享文档/代码包。

例如:

AccountStatus
ReviewStatus
RelationshipStatus
MatchStatus
RegistrationStatus
MatchmakerServiceStatus
ReportStatus
RiskLevel

避免前后端分别定义不同字符串。


第一百四十五章 V1.0不需要复杂状态机框架

无需引入:

  • Temporal
  • Camunda
  • 工作流引擎
  • BPMN平台

当前业务使用:

枚举 + Service规则 + 数据库约束

足够。


第一百四十六章 什么时候未来考虑工作流引擎

只有当未来出现:

  • 多级审批
  • 跨机构复杂审批
  • 大量动态流程
  • 可配置工作流

才考虑。

V1不需要。


第一百四十七章 核心业务规则汇总

用户进入推荐的必要条件

已登录
+
已绑定手机号
+
已实名
+
资料审核通过
+
账号正常
+
婚恋状态允许
+
隐私允许

第一百四十八章 用户聊天必要条件

双方互相喜欢
+
Match有效
+
Conversation有效
+
双方账号正常
+
双方未拉黑

第一百四十九章 红娘推荐必要条件

服务有效
+
候选人审核通过
+
双方账号正常
+
双方未拉黑
+
双方Required条件不冲突

第一百五十章 活动报名必要条件

活动开放
+
用户实名
+
资料审核通过
+
账号正常
+
年龄符合
+
未重复报名
+
名额可用

第一百五十一章 成功牵手必要条件

有效Match
+
一方发起
+
另一方确认
+
双方账号有效

第一百五十二章 风控最高优先级原则

任何业务规则都必须让位于:

用户安全。

即使用户:

  • 已匹配
  • 已报名活动
  • 已有红娘服务

一旦确认严重风险:

平台有权:

  • 暂停功能
  • 停止聊天
  • 停止活动参与
  • 进入人工处理

同时保留申诉机制。


第一百五十三章 用户自主决定原则

任何系统和工作人员都不能替用户:

  • 喜欢某人
  • 开启聊天
  • 确认成功牵手

红娘和算法:

只能推荐与辅助。

最终决定:

永远属于用户本人。


第一百五十四章 隐私优先原则

如果隐私设置与推荐规则冲突:

隐私设置优先。

例如:

用户关闭:

visible_in_search = false

即使匹配分100:

也不能出现在主动搜索结果。


第一百五十五章 V1.0最终状态机总图

用户注册
↓
实名
↓
完善资料
↓
人工审核
↓
审核通过
↓
正在寻找
↓
系统推荐/主动搜索/红娘/活动
↓
喜欢
↓
双向喜欢
↓
聊天
↓
正在了解
↓
成功牵手

任何阶段都有安全旁路:

举报
↓
风险审核
↓
限制 / 暂停 / 封禁

任何阶段用户都可以:

暂停寻找
或
退出婚恋服务

第一百五十六章 最终设计原则

整个V1.0必须做到:

每一个状态都有明确来源。

每一次状态迁移都有前置条件。

每一个关键动作都能防重复。

每一种异常都有明确恢复方式。

任何并发都不能制造重复Match、重复报名、重复消息。

任何后台状态变化都能及时影响用户端。

红娘、活动、系统推荐不能突破用户本人设置的硬条件和自主决定权。

账号安全与隐私规则永远高于普通业务便利性。

最终目标不是把状态机设计得复杂,而是保证:

任何一个异常情况发生时,系统都知道“现在是什么状态、下一步允许做什么、禁止做什么、怎么恢复”。