
快接龙小程序(前后端)开源地址: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
则报错
- 判断接龙发起人是否在
代码实现
js
/* 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 errMsg
let size = (await Jielong.query().where({ origin }).whereIn(ID, joinedIds).count("* as total"))[0].total
if(size > 0)
throw errMsg
}
}
总结
个人觉得,这次的功能变更,还是很贴合最少的代码变动实现需求的初心😄。
大家如果有更好的方案,欢迎来提🤝。