快接龙 | 要如何对用户的接龙频次进行系统硬控

快接龙小程序(前后端)开源地址:https://github.com/0604hx/quick-jielong


需求概述

某天傍晚,"甲方"问,接龙小程序可以设置同一个用户一个时间段内只能接龙一次吗?

因为想要工会的福利惠及更多有需要的人。

我简单思考了下,这需求挺合理,实施起来不难,马上安排!

实施方案

设计思路

符合需求的同时,改动的尽可能符合以下要求:

  1. 小程序端无需变动(避免审核的步骤😄)
  2. 频次的限定可以只针对指定人发布的接龙信息
  3. 可以设置时间段的长度(单位为,默认21
  4. 限定只作用于同系列的接龙(比如同一个人发布理发洗头两个序列的接龙互不影响)

如何确定接龙为同系列?

比如有以下接龙:

序号 标题
1 8月5号理发💇‍接龙
2 8月5号洗头🚿接龙
3 7月29号理发💇‍接龙
4 7月29号洗头🚿接龙

用户A已经参与序号3的接龙,此时参与序号1(因为1跟3 是同系列的接龙)则应该报错并回显:您已于xxxx参与接龙,21天内只能参与一次噢!

那在程序中,如何确定接龙是同一个系列呢?

  • 方式一 :根据标题匹配,比如具有很明显的同个关键词(如理发)。不过这个方法出错率很高,一是不好确认关键词,二是同一个词也可能有多种表达方式(博大精深的中文👍);
  • 方式二 :新增一个源头ID字段,具有相同值的接龙视为同系列,这要求每次新增接龙都应该从同系列的接龙中复制(本就有的功能,方便快速创建新接龙😄)。

所以,我最终选择方式二,尽管需要新增一个字段。

如何配置特定的人

通过配置文件,录入特定人及时长

整改后的流程

  1. 配置文件加入属性periodLimits(Object),Key 为用户ID,Value 为时长;
  2. 接龙表新增字段origin,用于标识同源信息
  3. 数据员复制方式创建接龙时,origin字段赋值为父接龙的origin属性或者 ID
  4. 用户参与接龙时:
    • 判断接龙发起人是否在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
    }
}

总结

个人觉得,这次的功能变更,还是很贴合最少的代码变动实现需求的初心😄。

大家如果有更好的方案,欢迎来提🤝。