zoukankan      html  css  js  c++  java
  • 年会抽奖程序,开箱即用

    年底降至,各类年会都需用到抽奖,最近刚好写了一个抽奖程序,总结一下,也为了方便日后温故,也可给诸位一个开箱即用的抽奖demo参考

    demo演示链接

    先睹为快,传送门

    完整代码地址

    传送门

    流程图

    image

    说明

    1. 公平抽奖,没有暗箱操作,代码通过功能测试、压测,经过多人review,可放心开箱即用。
    2. 这个抽奖程序是上周公司抽奖实际使用的,但是代码我隐去了跟公司相关的信息,所以UI上效果基本没有,但只要稍作修改,如设计一张背景图即可。
    3. 分辨率1920*1080效果最佳,但需考虑实际使用地方的屏幕设备
    4. 有抽奖中、中奖两个音乐,需要连接音频效果更佳
    5. 奖品信息可以配置,一次抽奖可以分若干小次进行,这里抽奖暂时只按1桌/1次来,原因:删除/放回这里需要优化一下
    6. 中奖后会将中奖人名单以及奖品信息写入中奖记录表,有页面可查看,方便后面兑奖
    7. 暂时只放出抽桌号的代码,其实将桌号的图片换成员工头像效果会更好,原还有一个签到页面,可签到的人提前录入了user表,只有签到的人才在奖池中,这里还有一个nestjs写的后台,代码暂时没有放出来,可以私聊沟通。流程可以参考
      image

    核心代码

    关键节点有相应注释,请仔细阅读,欢迎指正不足

    //生成从minNum到maxNum的随机数
    randomNum(minNum, maxNum){
        return parseInt(Math.random()* (maxNum - minNum + 1) + minNum); 
    },
    
    //奖头像动起来
    doMove(start, end) {
        console.log('start, end', start, end );
    
        this.setIntervalFun = setInterval(() => {
            for(let i = start; i < end; i ++ ) {
                this.$set(this.currentPrizeUsers, i, this.keepNoRepeat(this.currentPrizeUsers, this.moveUsers));
            }
        }, 80) 
    },
    
    //保证数字不重复
    keepNoRepeat(currentPrizeUsers, userNoPrize) {
      let user = userNoPrize[this.randomNum(0, userNoPrize.length)];
    
      //由于分多小次抽奖,抽奖完成后奖池人数才变化,所以可能存在取值越界
      if(!user) {
        return this.keepNoRepeat(currentPrizeUsers, userNoPrize);
      }
      if(currentPrizeUsers.filter(item => item.userid == user.userid).length > 0) {
        return this.keepNoRepeat(currentPrizeUsers, userNoPrize);
      }else {
        return user;
      }
    },
    
    //停/继续/完成点击
    handlePrizeClick: throttle(function() {
        //单次抽奖的最后一小次暂停
        if(this.movePrizeNum == this.currentPrizeInfo.count) {
            this.choujiangId.pause();
            this.zhongjiangId.play();
            clearInterval(this.setIntervalFun);
            this.movePrizeStatus = 2;
            this.movePrizeNum += 1;
            this.doPrize(this.currentPrizeUsers.filter(item => item.userid).map(item => item.userid).join(','));
            return;
        }
    
        if(this.movePrizeStatus == 2) {//显示状态-完成抽奖
            this.choujiangId.pause();
            this.zhongjiangId.pause();
            this.dialogTableVisible = false;
            this.movePrizeStatus = 0;
        }else if(this.movePrizeStatus == 3) {//再次启动
            this.choujiangId.play();
            this.zhongjiangId.pause();
            this.movePrizeStatus = 1;
            this.doMove(this.movePrizeNum * this.currentPrizeInfo.everytime, this.currentPrizeInfo.everytime * (this.movePrizeNum + 1) );
            this.movePrizeNum += 1;
        }else if(this.movePrizeStatus == 1) {//暂停
            this.choujiangId.pause();
            this.zhongjiangId.play();
            clearInterval(this.setIntervalFun);
            this.movePrizeStatus = 3;
            this.doPrize(this.currentPrizeUsers.filter(item => item.userid).map(item => item.userid).join(','));
        }
    }, 1000),
    
    //洗牌
    randomUser() {
        let randomUser = setInterval(() => {
            this.moveUsers = this.moveUsers.sort((a, b) => Math.random() > .5 ? -1 : 1);
        }, 100)
        setTimeout(() => {
            clearInterval(randomUser);
        }, 2000);
    }
    

    迭代思路(不足之处)

    1. 配置奖品信息应更丰富,单独做一个后台配置页面,支持配置奖品图片、抽奖个数、次数、音乐等等
    2. 将奖品配置信息用数据表管理,而不是json
    3. 抽奖历史记录应可以回看,可以删除(作废),同时删除中奖记录表
    4. 如果奖池人数足够多(1w人以上),可能有性能问题,前端循环可以持续优化
    5. 添加登录/接口权限控制

    后续考虑

    1. 空格键按暂停可能会更好操作,但是声控呢?
    2. 洗牌效果做得更炫酷一些
  • 相关阅读:
    Python + unittest + HTMLTestRunnerCN 生成接口自动化测试报告
    python 读写操作CSV文件
    with关键字
    Django常规命令大全
    科技阅读与写作资料
    Topics in Service Computing
    学习总结100515
    【论文收集】PQDT硕博库中的搜索结果service composition
    毕业开题结束感想
    excle操作备忘
  • 原文地址:https://www.cnblogs.com/liliangel/p/12079759.html
Copyright © 2011-2022 走看看