年會抽獎程式,開箱即用
阿新 • • 發佈:2019-12-22
年底降至,各類年會都需用到抽獎,最近剛好寫了一個抽獎程式,總結一下,也為了方便日後溫故,也可給諸位一個開箱即用的抽獎demo參考
demo演示連結
先睹為快,傳送門
完整程式碼地址
傳送門
流程圖
說明
- 公平抽獎,沒有暗箱操作,程式碼通過功能測試、壓測,經過多人review,可放心開箱即用。
- 這個抽獎程式是上週公司抽獎實際使用的,但是程式碼我隱去了跟公司相關的資訊,所以UI上效果基本沒有,但只要稍作修改,如設計一張背景圖即可。
- 解析度1920*1080效果最佳,但需考慮實際使用地方的螢幕裝置
- 有抽獎中、中獎兩個音樂,需要連線音訊效果更佳
- 獎品資訊可以配置,一次抽獎可以分若干小次進行,這裡抽獎暫時只按1桌/1次來,原因:刪除/放回這裡需要優化一下
- 中獎後會將中獎人名單以及獎品資訊寫入中獎記錄表,有頁面可檢視,方便後面兌獎
- 暫時只放出抽桌號的程式碼,其實將桌號的圖片換成員工頭像效果會更好,原還有一個簽到頁面,可簽到的人提前錄入了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); }
迭代思路(不足之處)
- 配置獎品資訊應更豐富,單獨做一個後臺配置頁面,支援配置獎品圖片、抽獎個數、次數、音樂等等
- 將獎品配置資訊用資料表管理,而不是json
- 抽獎歷史記錄應可以回看,可以刪除(作廢),同時刪除中獎記錄表
- 如果獎池人數足夠多(1w人以上),可能有效能問題,前端迴圈可以持續優化
- 新增登入/介面許可權控制
後續考慮
- 空格鍵按暫停可能會更好操作,但是聲控呢?
- 洗牌效果做得更炫酷一些