1. 程式人生 > >年會抽獎程式,開箱即用

年會抽獎程式,開箱即用

年底降至,各類年會都需用到抽獎,最近剛好寫了一個抽獎程式,總結一下,也為了方便日後溫故,也可給諸位一個開箱即用的抽獎demo參考

demo演示連結

先睹為快,傳送門

完整程式碼地址

傳送門

流程圖

說明

  1. 公平抽獎,沒有暗箱操作,程式碼通過功能測試、壓測,經過多人review,可放心開箱即用。
  2. 這個抽獎程式是上週公司抽獎實際使用的,但是程式碼我隱去了跟公司相關的資訊,所以UI上效果基本沒有,但只要稍作修改,如設計一張背景圖即可。
  3. 解析度1920*1080效果最佳,但需考慮實際使用地方的螢幕裝置
  4. 有抽獎中、中獎兩個音樂,需要連線音訊效果更佳
  5. 獎品資訊可以配置,一次抽獎可以分若干小次進行,這裡抽獎暫時只按1桌/1次來,原因:刪除/放回這裡需要優化一下
  6. 中獎後會將中獎人名單以及獎品資訊寫入中獎記錄表,有頁面可檢視,方便後面兌獎
  7. 暫時只放出抽桌號的程式碼,其實將桌號的圖片換成員工頭像效果會更好,原還有一個簽到頁面,可簽到的人提前錄入了user表,只有簽到的人才在獎池中,這裡還有一個nestjs寫的後臺,程式碼暫時沒有放出來,可以私聊溝通。流程可以參考

核心程式碼

關鍵節點有相應註釋,請仔細閱讀,歡迎指正不足

//生成從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. 洗牌效果做得更炫酷一些