35 KiB
丹阳公益婚恋服务平台
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
唯一。
弱网重发:
返回原消息。
不能生成重复文本。
第五十二章 消息发送前置校验
发送前必须校验:
- Conversation存在
- 当前用户属于Conversation
- Conversation可发送
- Match有效
- 双方未拉黑
- 双方账号正常
- 内容合法
- 频率未超限
第五十三章 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、重复报名、重复消息。
任何后台状态变化都能及时影响用户端。
红娘、活动、系统推荐不能突破用户本人设置的硬条件和自主决定权。
账号安全与隐私规则永远高于普通业务便利性。
最终目标不是把状态机设计得复杂,而是保证:
任何一个异常情况发生时,系统都知道“现在是什么状态、下一步允许做什么、禁止做什么、怎么恢复”。