快接龙 | 要如何对用户的接龙频次进行系统硬控
快接龙小程序(前后端)开源地址:https://github.com/0604hx/quick-jielong
需求概述
某天傍晚,"甲方"
问,接龙小程序
可以设置同一个用户一个时间段内只能接龙一次吗?
因为想要工会的福利惠及更多有需要的人。
我简单思考了下,这需求挺合理,实施起来不难,马上安排!
实施方案
设计思路
符合需求的同时,改动的尽可能符合以下要求:
- 小程序端无需变动(避免
审核
的步骤😄) - 频次的限定可以只针对
指定人
发布的接龙信息 - 可以设置时间段的长度(单位为
天
,默认21
) - 限定只作用于同系列的接龙(比如同一个人发布
理发
、洗头
两个序列的接龙互不影响)
如何确定接龙为同系列?
比如有以下接龙:
序号 | 标题 |
---|---|
1 | 8月5号理发💇接龙 |
2 | 8月5号洗头🚿接龙 |
3 | 7月29号理发💇接龙 |
4 | 7月29号洗头🚿接龙 |
用户A已经参与序号3
的接龙,此时参与序号1
(因为1跟3 是同系列的接龙)则应该报错并回显:您已于xxxx参与接龙,21天内只能参与一次噢!
。
那在程序中,如何确定接龙是同一个系列呢?
- 方式一:根据标题匹配,比如具有很明显的同个关键词(如
理发
)。不过这个方法出错率很高,一是不好确认关键词,二是同一个词也可能有多种表达方式(博大精深的中文👍); - 方式二:新增一个
源头ID
字段,具有相同值的接龙视为同系列,这要求每次新增接龙都应该从同系列的接龙中复制
(本就有的功能,方便快速创建新接龙😄)。
所以,我最终选择方式二
,尽管需要新增一个字段。
如何配置特定的人
?
通过配置文件,录入特定人及时长
。
整改后的流程
- 配置文件加入属性
periodLimits
(Object),Key
为用户ID,Value
为时长; - 接龙表新增字段
origin
,用于标识同源信息 数据员
以复制
方式创建接龙时,origin
字段赋值为父接龙的origin
属性或者 ID- 用户参与接龙时:
- 判断接龙发起人是否在
periodLimits
内 - 判断指定时长内用户已经参与的
接龙
是否与当前接龙
为同系列 - 上一步为
true
则报错
- 判断接龙发起人是否在
代码实现
/* packages\server\src\service\JielongService.js *///仅当接龙配置有 origin 字段才判断是否重复参与同系列接龙
let { origin } = bean
if(origin && bean.uid in config.periodLimits){let limitDays = parseInt(config.periodLimits[bean.uid] || 21)logger.info(`${bean.uid}发布的接龙设置${limitDays}天不能重复参与...`)//获取指定时间内用户参与的接龙let joineds = await Entry.query().where({ uid }).andWhere(DAY, ">=", Date.now()-limitDays*24*60*60*1000)logger.debug("过去21天内参与的接龙有", joineds)if(joineds.length){const errMsg = `发布者已设置${limitDays}天内不能重复参与同类型接龙`//判断是否存在同系列接龙const joinedIds = joineds.map(v=>v.pid)if(joinedIds.includes(origin))throw errMsglet size = (await Jielong.query().where({ origin }).whereIn(ID, joinedIds).count("* as total"))[0].totalif(size > 0)throw errMsg}
}
总结
个人觉得,这次的功能变更,还是很贴合最少的代码变动实现需求的初心😄。
大家如果有更好的方案,欢迎来提🤝。