功能需求:活动分享与嘉宾匹配系统 1. 活动分享入口 每个活动配置独立的分享链接和二维码,支持扫码或点击链接进入小程序。 2. 用户绑定流程 用户通过分享链接/二维码打开小程序,填写个人信息并绑定至对应活动。 若用户曾参与过历史活动,系统自动复用其历史信息并完成绑定,无需重复填写。 绑定成功后,在活动正式开始前,用户无法查看其他参与者的信息。 3. 信息可见性规则 活动开始前:仅允许查看自己的信息,其他用户信息不可见。 活动开始后:开放本活动内异性嘉宾资料查看与匹配,其他活动的用户信息完全隔离,不可见。 资料展示:男嘉宾、女嘉宾资料分开展示,用户仅可浏览异性嘉宾信息。 4. 嘉宾选择规则 每位用户最多可选择 3 位心仪嘉宾。 确认提交后不可再新增选择,但支持修改或撤销已选嘉宾。 管理员可设置匹配截止时间,到达截止时间后系统自动锁定,禁止任何修改。 5. 匹配判定规则 双向互选:若双方恰好互选,则判定为匹配成功,双方均可查看匹配结果。 多向匹配:用户同时与多位嘉宾匹配成功,全部同时展示。 单向选择:A选择B但B未选择A,A可在"谁选了我"页面看到B。 6. 用户页面说明 异性嘉宾列表:展示所有异性嘉宾资料,支持选择/取消选择。 我的选择:展示当前已选的3位嘉宾,支持修改/撤销(截止前)。 谁选了我:展示所有选择了自己的嘉宾(无论自己是否选择了对方)。 匹配成功:展示所有双向互选的匹配对象,支持查看对方完整资料。
17 KiB
需求补充计划
一、文档目标
本文档用于补充“活动分享与嘉宾匹配系统”的详细设计方案,并结合当前项目实际代码结构,明确以下内容:
- 在保留现有“小程序滑动选择页面”的前提下,如何完成活动内匹配能力改造
- 当前系统与目标需求之间的差距
- 建议的数据结构、接口设计、页面设计与权限规则
- 需要修改的后端、管理端、小程序文件范围
- 推荐实施顺序与风险提示
二、当前系统现状总结
当前项目由三部分组成:
- 后端:
backend - 管理后台:
admin-web - 微信小程序:
miniprogram
当前已经具备的基础能力:
- 微信登录与用户体系
- 用户全局资料维护
- 活动创建、发布、报名
- 活动报名关系记录
- 基础匹配能力
- 小程序滑动选择页
当前关键代码位置:
- 活动模型:
backend/app/models/activity.py - 用户模型:
backend/app/models/user.py - 活动报名模型:
backend/app/models/registration.py - 匹配模型:
backend/app/models/match.py - 活动服务:
backend/app/services/activity_service.py - 匹配服务:
backend/app/services/match_service.py - 小程序活动详情页:
miniprogram/pages/activity-detail - 小程序滑动匹配页:
miniprogram/pages/match - 小程序我的匹配页:
miniprogram/pages/my-matches - 管理后台活动管理:
admin-web/src/views/activities
三、本次需求的核心目标
本次不是新增一个完全独立的陌生系统,而是在现有“活动 + 用户 + 匹配”的基础上,完成“活动内隔离的嘉宾互选系统”。
必须满足的核心目标如下:
- 每个活动有独立分享入口,可通过链接或二维码进入。
- 用户通过分享入口进入后,绑定到该活动。
- 如用户已有历史资料,则自动复用,无需重复填写。
- 活动开始前,用户不能查看其他参与者信息。
- 活动开始后,只能查看本活动内异性嘉宾资料。
- 每位用户最多选择 3 位嘉宾。
- 截止时间前允许调整或撤销,截止时间后锁定。
- 支持查看“我的选择”“谁选了我”“匹配成功”。
- 匹配结果必须按活动隔离,不能与其他活动串数据。
- 保留现有滑动选择页,作为活动内异性嘉宾浏览与选择入口。
四、保留滑动选择页的设计结论
4.1 保留原则
现有页面 miniprogram/pages/match 可以保留,不建议推倒重做。
保留内容包括:
- 滑卡式浏览体验
- 左滑跳过、右滑选择的交互模型
- 页面主体样式和卡片信息展示结构
- 当前活动模式下的页面入口结构
4.2 改造原则
保留页面,不代表保留现有活动匹配的数据逻辑。
需要改造的是:
- 页面背后的数据来源
- 活动模式下的权限判断
- 选择次数限制
- 截止锁定规则
- 活动隔离逻辑
- 配套页面的数据结构
4.3 滑动页在新系统中的定位
建议将滑动选择页定义为:
- “活动内异性嘉宾浏览页”
- “我的选择”的新增入口
- 活动开始后才可进入
建议交互规则如下:
- 左滑:跳过当前嘉宾,不产生选择关系
- 右滑:将该嘉宾加入“我的选择”
- 不在滑动页执行撤销
- 撤销和修改在“我的选择”页处理
这样可以最大程度保留现有体验,同时降低交互混乱和实现复杂度。
五、当前系统与需求之间的差距
5.1 活动分享入口缺失
当前活动系统只有活动列表和活动详情,没有活动独立分享标识,也没有二维码或分享 token 的模型支持。
缺口:
- 活动无独立分享 token
- 无分享链接生成逻辑
- 无分享二维码数据字段
- 无“通过分享入口进入活动”的后端接口
5.2 报名绑定逻辑不完整
当前已经有 registrations 表作为用户报名活动关系,但现有流程更偏向用户主动进入活动后点击报名,不是“通过分享入口进入并自动绑定”的闭环。
缺口:
- 缺少分享入口触发的绑定流程
- 缺少“资料不完整时先补资料再自动绑定”的回流逻辑
5.3 活动开始前的信息隔离未满足
当前活动详情页存在已报名用户预览能力,会展示其他参与者的信息预览。
这与新需求冲突:
- 活动开始前只能看自己
- 不能看其他参与者
5.4 现有匹配不是活动隔离
当前 match_likes 表没有 activity_id,无法保证选择关系只属于某一场活动。
这会造成以下问题:
- A 活动中的选择影响 B 活动
- “谁选了我”可能出现其他活动的人
- “匹配成功”可能跨活动串联
5.5 现有匹配结果页不适合正式活动玩法
当前“我的匹配”页面里混用了服务端数据和本地缓存记录,且详情页存在演示数据兜底逻辑。
正式活动系统不能继续依赖这些临时逻辑。
六、总体设计方案
本次建议采用“保留前端滑动页,新增活动内匹配子系统”的设计。
设计原则:
- 用户资料继续使用全局
users - 活动绑定继续使用
registrations - 活动内嘉宾选择单独建模
- 活动内匹配接口独立建设
- 不强行复用现有全局匹配表承载新规则
一句话总结:
“用户还是全局的,资料还是复用的,但选择关系必须是活动内独立的。”
七、数据结构设计建议
7.1 activities 表新增字段
建议为活动表新增以下字段:
share_token- 用途:每个活动独立分享标识
- 要求:唯一
match_deadline- 用途:管理员设置匹配截止时间
selection_limit- 用途:每个活动最多可选人数
- 默认值:3
share_qr_url- 用途:保存二维码图片地址
- 可选字段
7.2 保留 registrations 表作为活动绑定关系
现有 registrations 表可以继续承担以下职责:
- 用户是否已绑定活动
- 用户是否有效参与该活动
- 活动内可见性判断基础
如需增强,可考虑新增字段:
bind_source- 值示例:
share_link、qrcode、manual
- 值示例:
bound_at- 用途:记录绑定时间
这部分属于增强项,不是第一优先级。
7.3 新增活动内嘉宾选择表
建议新增表:activity_guest_choices
字段建议如下:
idactivity_idfrom_user_idto_user_idstatus- 建议取值:
active、cancelled
- 建议取值:
created_atupdated_at
唯一约束建议:
(activity_id, from_user_id, to_user_id)
此表承担的职责:
- 记录我在某个活动中选了谁
- 支持撤销选择
- 支持重新选择
- 为“谁选了我”提供基础数据
- 为“双向互选”实时计算提供基础数据
7.4 是否保留现有 match_likes / matches
建议:
- 保留现有表,避免影响旧功能
- 新活动匹配逻辑不要继续依赖旧表
原因:
- 旧表是全局匹配逻辑
- 新需求是活动内隔离逻辑
- 两者的约束不同,直接混用风险高
八、权限与可见性规则设计
8.1 活动开始前
用户进入活动后:
- 可查看自己的资料和绑定状态
- 不可查看其他参与者列表
- 不可进入嘉宾选择页
- 不可查看“谁选了我”
- 不可查看“匹配成功”
系统返回建议:
can_view_candidates = falsecan_match = falsestage = before_start
8.2 活动开始后且截止前
用户在满足以下条件后,可进行匹配:
- 已登录
- 已绑定当前活动
- 当前活动已开始
- 当前时间未超过匹配截止时间
- 用户资料有效
此阶段允许:
- 浏览本活动内异性嘉宾
- 右滑选择
- 查看我的选择
- 撤销或修改我的选择
- 查看谁选了我
- 查看匹配成功
8.3 匹配截止后
系统自动锁定:
- 不允许新增选择
- 不允许撤销选择
- 不允许修改选择
但可以继续查看:
- 我的选择
- 谁选了我
- 匹配成功
系统返回建议:
can_choose = falsecan_modify_choice = falsestage = matching_closed
8.4 跨活动隔离
任何与活动匹配相关的数据查询都必须带 activity_id 维度。
包括:
- 候选人列表
- 我的选择
- 谁选了我
- 双向互选列表
- 匹配详情
不能出现以下情况:
- 来自其他活动的用户被展示
- 其他活动的选择记录进入当前活动
- 跨活动的匹配结果互相污染
九、用户流程设计
9.1 分享入口流程
流程建议如下:
- 用户通过分享链接或二维码进入小程序。
- 系统识别
share_token或活动参数。 - 若用户未登录,先静默登录。
- 根据分享标识查询活动。
- 若用户已存在历史资料,则直接读取全局资料。
- 若资料完整,则执行活动绑定。
- 若资料不完整,则跳转资料完善页。
- 资料保存成功后返回活动并自动绑定。
9.2 活动开始前流程
用户进入活动详情后:
- 看到活动信息
- 看到自己已绑定状态
- 看到“活动未开始,暂不可查看嘉宾信息”的提示
9.3 活动开始后流程
用户进入活动详情后:
- 点击“进入匹配”
- 跳转至保留的滑动选择页
- 系统只加载本活动内异性嘉宾
- 右滑即加入“我的选择”
9.4 我的选择流程
用户可以查看:
- 当前已选择的嘉宾
- 已用名额和剩余额度
截止前允许:
- 撤销已选嘉宾
- 从滑动页继续新增其他人
9.5 谁选了我流程
用户可以查看:
- 所有选择了自己的嘉宾
- 无论自己是否选择对方,都可在这里看到
但资料展示需按权限控制,避免提前暴露过多隐私。
9.6 匹配成功流程
当双方互为 active 选择时:
- 判定为匹配成功
- 在“匹配成功”页展示
- 支持查看对方完整资料
十、页面设计建议
10.1 活动详情页
页面:miniprogram/pages/activity-detail
需要新增或调整的内容:
- 支持从分享入口进入活动
- 显示绑定状态
- 显示活动阶段
- 显示匹配截止时间
- 活动开始前不显示他人预览
- 活动开始后显示“进入匹配”
建议移除或关闭:
- 当前
registered_preview的展示
10.2 滑动选择页
页面:miniprogram/pages/match
保留页面,调整活动模式下的数据来源和文案。
建议增强内容:
- 页面顶部显示当前活动标题
- 显示“剩余可选人数”
- 显示匹配截止时间
- 显示快速入口:
- 我的选择
- 谁选了我
- 匹配成功
页面职责:
- 只负责浏览与新增选择
- 不负责撤销选择
10.3 我的匹配页
页面:miniprogram/pages/my-matches
建议重构为活动内结果页,可使用 tab 结构:
- 我的选择
- 谁选了我
- 匹配成功
说明:
- 不建议继续保留本地缓存兜底记录
- 必须全部以服务端真实活动数据为准
10.4 匹配详情页
页面:miniprogram/pages/match-detail
建议职责调整为:
- 仅用于查看双向互选成功对象的完整资料
需要移除:
- 演示数据 fallback
- 与正式逻辑无关的本地假数据
十一、后端接口设计建议
建议新增活动内匹配接口,而不是继续挤在现有全局 /matches 下。
11.1 活动分享与绑定
GET /activities/share/{share_token}- 根据分享 token 获取活动信息
POST /activities/{activity_id}/bind- 用户绑定到活动
11.2 活动匹配状态
GET /activities/{activity_id}/match-state- 返回活动阶段、是否可查看、是否可选择、剩余额度等
建议返回字段:
activity_idstageis_boundcan_view_candidatescan_choosecan_modify_choiceselection_limitselected_countremaining_countmatch_deadline
11.3 候选人列表
GET /activities/{activity_id}/candidates- 获取当前活动内异性候选人
查询原则:
- 只查本活动已绑定用户
- 只查异性
- 不查自己
- 不查已撤销无效记录
- 已选过的人可按产品需要决定是否继续显示
11.4 选择与撤销
POST /activities/{activity_id}/choices- 新增选择
DELETE /activities/{activity_id}/choices/{target_user_id}- 撤销选择
11.5 我的选择
GET /activities/{activity_id}/my-choices
11.6 谁选了我
GET /activities/{activity_id}/liked-me
11.7 匹配成功
GET /activities/{activity_id}/mutual-matches
11.8 匹配详情
GET /activities/{activity_id}/matches/{target_user_id}/detail
说明:
- 只有在当前活动中双方互选成功时,才允许查看完整资料
十二、后端代码改造范围
12.1 需要修改的现有文件
backend/app/models/activity.pybackend/app/models/__init__.pybackend/app/services/activity_service.pybackend/app/routers/activities.pybackend/app/schemas/activity.pybackend/app/routers/__init__.py
12.2 建议新增的文件
backend/app/models/activity_guest_choice.pybackend/app/services/activity_match_service.pybackend/app/schemas/activity_match.pybackend/app/routers/activity_matches.pybackend/alembic/versions/新增活动内选择表与活动分享字段.py
12.3 需要谨慎处理的旧文件
backend/app/models/match.pybackend/app/services/match_service.pybackend/app/routers/matches.py
建议:
- 暂不强改旧全局匹配逻辑
- 新活动逻辑独立建设
- 等新活动功能稳定后,再决定是否合并或下线旧逻辑
十三、管理后台改造范围
13.1 需要修改的页面
admin-web/src/views/activities/ActivityCreateView.vueadmin-web/src/views/activities/ActivitiesView.vue
13.2 需要新增的活动配置项
- 分享 token 展示
- 分享链接展示
- 二维码展示
- 匹配截止时间
- 选择上限
13.3 后台列表建议新增展示内容
- 匹配截止时间
- 分享链接复制按钮
- 二维码预览或下载
- 活动内已选择人数统计
- 活动内匹配成功人数统计
13.4 可选增强项
可额外增加活动匹配详情页,供管理员查看:
- 本活动所有用户选择关系
- 谁选了谁
- 双向互选结果
- 男女参与情况
十四、小程序改造范围
14.1 需要修改的页面
miniprogram/pages/activity-detailminiprogram/pages/matchminiprogram/pages/my-matchesminiprogram/pages/match-detailminiprogram/pages/profile-edit
14.2 可能需要修改的公共文件
miniprogram/app.jsminiprogram/app.jsonminiprogram/utils/request.js
14.3 小程序重点调整项
活动详情页
- 支持分享入口参数
- 开始前不显示其他人
- 显示活动阶段和进入匹配入口
滑动页
- 保留 UI
- 活动模式下切换到新接口
- 增加剩余额度和快捷入口
我的匹配页
- 改造成活动内结果聚合页
- 不再依赖本地临时缓存
详情页
- 只看双向匹配成功对象的完整资料
资料页
- 支持“完善资料后自动返回活动并绑定”
十五、推荐开发顺序
建议按以下顺序实施。
第一阶段:数据层改造
- 活动表新增分享与截止字段
- 新增活动内嘉宾选择表
- 补充迁移脚本
第二阶段:后端接口改造
- 活动分享接口
- 活动绑定接口
- 活动匹配状态接口
- 候选人、选择、撤销、结果查询接口
第三阶段:管理后台改造
- 活动创建与编辑支持新字段
- 活动列表展示分享入口和截止时间
第四阶段:小程序活动详情与分享流程
- 分享进入活动
- 资料补全回流
- 活动开始前提示逻辑
第五阶段:小程序滑动页接入活动新逻辑
- 保留滑卡交互
- 改为调用活动内候选人接口
- 加入剩余额度和状态展示
第六阶段:结果页与详情页改造
- 我的选择
- 谁选了我
- 匹配成功
- 完整资料查看
十六、风险与注意事项
16.1 不建议直接复用旧全局匹配表
如果强行复用:
- 容易跨活动串数据
- 条件判断会越来越复杂
- 后期维护成本高
16.2 不建议在滑动页同时承担“新增”和“撤销”
如果在滑动页里也做撤销:
- 用户认知会混乱
- 页面状态管理复杂
- 容易和“我的选择”页职责冲突
16.3 活动开始前的隐私控制必须后端强校验
不能只在前端隐藏按钮。
所有涉及:
- 查看候选人
- 查看谁选了我
- 查看匹配成功
- 查看完整资料
都必须由后端校验:
- 活动是否已开始
- 用户是否已绑定
- 是否处于允许查看阶段
16.4 旧“我的匹配”本地缓存逻辑建议逐步清理
原因:
- 正式业务不应依赖前端伪记录
- 多活动场景下本地缓存容易污染数据判断
十七、最终方案结论
本次需求最合适的实施方案是:
- 保留现有滑动选择页作为活动内异性嘉宾浏览入口
- 用户资料继续全局复用
- 活动绑定继续复用
registrations - 活动内选择关系单独建模
- 活动内匹配接口独立实现
- 活动开始前严格隐藏他人信息
- 截止时间前允许修改,截止后统一锁定
这套方案的优点:
- 最大程度保留现有前端体验
- 改造边界清晰
- 数据隔离正确
- 后续扩展成本更低
十八、建议下一步输出物
基于本计划,下一步建议继续补充以下文档或内容:
- 数据库变更清单
- 后端 API 详细定义
- 小程序页面字段与按钮清单
- 管理后台字段改造清单
- 按文件拆分的开发任务表