1. 程式人生 > 其它 >如何用vue+免費的webdb 實現一個世界盃足球競猜系統

如何用vue+免費的webdb 實現一個世界盃足球競猜系統

一、前言
最近世界盃在如火如荼的進行。我們都知道,中國也派出了我們的一支強大的隊伍:中國建築隊,全程參與了世界盃的所有比賽。

哈哈開個玩笑,不過說到世界盃,還真有不少朋友,不僅僅是看球,還切身參與了。比如足彩,世界盃競猜等等活動。

那麼今天我們就通過kintone來自己實現一個世界盃競猜系統吧!

二、視訊學習
開始學習前,可以先來看看本文的視訊“如何用vue+免費的web db,來實現一個世界盃足球競猜系統”,可以幫助你更好的理解本文的思路,更能提高學習的效率。配合著視訊我們快來學習吧!

三、功能梳理
想要實現的功能如下:

使用者競猜前臺:

1 每個人擁有自己獨立的積分

2 有比賽列表,賠付率資訊。能實現各自投票。

3 有個人資訊介面,列出我的積分,往期競猜資訊及結果。

競猜系統後臺:

1 可以錄入比賽資訊,賠付率資訊。可以到期進行開獎。

2 可以查詢使用者的競猜資訊。

3 使用者的積分變化有跡可查。

四、效果圖

五、如何實現?
效果看完了,那這個世界盃競猜系統是如何通過kintone實現的呢?

1、應用準備
這個世界盃競猜系統可以簡單通過以下應用進行搭建

1 球隊資訊應用:

記錄球隊名,球隊國旗等。

2 比賽資訊應用:

記錄比賽的兩支球隊,場次,該場比分,賠付率等。

3 使用者競猜資訊應用:

記錄使用者id,他的競猜的比賽場次,勝負,競猜使用的積分等。

4 積分變更履歷應用:

記錄使用者積分變化的履歷,每個場次押注所獲得或者付出的積分。

5 輪播圖應用

記錄一些比賽精彩圖片,美化頁面。

2、系統開發
接下來分享下這個系統是如何開發的。

整個投注系統使用Vue3框架來實現。

引入根節點

首先通過kintone的 JS API來獲取門戶上方的空白部分的元素 kintone.portal.getContentSpaceElement(),將其作為根節點。這樣就能把Vue產生的頁面掛載到這個根結點上。同時可以引入Pinia作為集中式狀態管理,Element UI 作為我們的UI框架。

1 2 3 4 5 6 7 8 9 10 11 12 13 import { createApp } from "vue"; import App from 
"./App.vue"; import installElementPlus from "@/libs/element"; import { createPinia } from "pinia"; /* eslint-disable */ kintone.events.on("portal.show", (event) => {     const myContainer = kintone.portal.getContentSpaceElement();     const app = createApp(App);     installElementPlus(app);     app.use(createPinia());     app.mount(myContainer);     return event; });

準備資料來源,獲取資料

然後通過kintone的REST API就能將kintone各個應用中的資料取出來,並在頁面上進行展示。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import { KintoneRestAPIClient } from "@kintone/rest-api-client"; const client = new KintoneRestAPIClient();   //獲取比賽列表 export const GetMatchList = async () => {     const app = appList.matchInfo;     import {appList,matchInfoField,usersField,userChipInField,picField} from "@/config";     try {         const params = {             app,         };         const resp = await client.record.getRecords(params);         if (resp.records.length > 0) {         return resp.records.map((record) => {             return dataConvert(record);         });         else {             return null;         }     catch (err) {         console.log(err);     } };

多語言開發

同時通過kintone.getLoginUser()我們可以獲取到當前登陸使用者的資訊。其中包含了他的語言資訊。根據語言資訊,我們可以配置I18N做多語言的開發。

1 2 const { language } = kintone.getLoginUser(); //   'language': 'zh'

集中式狀態管理

可以將使用者的剩餘積分,比賽下注資訊等寫入集中式狀態管理,因為他可能會在多頁面進行響應式變化。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import {   GetLeftScore,   GetChipInList,   GetMatchList, } from "@/services/kintoneApi"; import { defineStore } from "pinia";   export const useStore = defineStore("store", {   state: () => {     return {       myScore: 0,       chipInList: [],     };   },     getters: {     chipListShow(state) {       return state.chipInList.map((record) => {         if (record.Score_result == 0) {           record.scoreWin = "--";           record.teamInfo.Score = "--";           record.type = "chip in";         else if (record.Score_result < 0) {           record.scoreWin = `--`;           record.type = "loss";         else {           record.scoreWin = `+ ${record.Score_result}`;           record.type = "win";         }         return record;       });     },   },     actions: {     async init() {       const initLeftScorePromise = this.getLeftScore();       const initChipInListPromise = this.getChipInList();       return Promise.all([initLeftScorePromise, initChipInListPromise]);     },       async getLeftScore() {       this.myScore = await GetLeftScore();     },       async getChipInList() {       const chipInList = await GetChipInList();       const matches = await GetMatchList();       const matchMapping = {};       for (const item of matches) {         matchMapping[item.Match_id] = {           FlagA: item.FlagA,           FlagB: item.FlagB,           TeamA_name: item.TeamA_name,           TeamB_name: item.TeamB_name,           Score: `${item.ScoreA}:${item.ScoreB}`,         };       }       chipInList.map((chip) => {         chip.teamInfo = matchMapping[chip.Match_id];         return chip;       });       this.chipInList = chipInList;     },   }, });

競猜系統整體說明

首先是可以通過管理員給每個使用者錄入一些初始積分,使用者有了積分可以進行比賽的勝負平的競猜。比賽場次,勝負平賠付率可以通過取出後臺資料後進行展示。

當用戶進行競猜後,會將記錄寫入使用者競猜資訊應用。同時還可以計算出使用者的剩餘積分,使用者的競猜列表等。

開獎系統整體說明

開獎系統可以直接對比賽資訊應用進行自定義開發。

當比賽結束出來結果後,管理員可以錄入比分,自動計算出比賽結果。然後可以一鍵開獎,系統自動計算出哪些使用者猜對了比賽,並且通過賠付率計算出他所獲得的積分。並且寫入到使用者的積分履歷中去。

開發上的注意點

因為這裡沒有後端系統,所以可能存在使用者自行通過偽造請求等方式生成投票資料。這樣就有可能出現:

1 幫別人投票,讓別人無分可投

2 讓自己的投票超出自己的積分

3 比賽結束後進行投票

等等一系列的問題。那這邊如何一一化解呢?

1 偽造別人投票:可以通過應用的建立者欄位來實現。因為這個欄位是系統後端自動生成,所以不再有這個困擾。

2 讓自己的投票超出自己的積分:為防止這種篡改積分的情況,這裡將使用者的競猜列表和積分列表分開。競猜列表使用者有讀寫許可權,但是積分列表使用者只有讀取許可權。

通過kintone的許可權設定,普通登入使用者都是隻讀許可權,沒有修改許可權。然後通過管理員使用者的開獎系統對使用者的競猜進行稽核。過濾後,由管理員進行修改(當然這些都是程式碼自動實現的。)

比如判斷使用者的投票時,會先計算出他當前沒有開獎的投票總數是否大於他剩餘的積分。這樣就能防止他是否會進行偽造投票。

3 超過時間的投票:通過kintone自帶的更新時間欄位(這是使用者無法自行修改的特點),判斷使用者該條投票記錄的更新時間是否超過該場比賽的投票截止時間,就能過濾掉使用者的超時偽造投票。

經過以上種種的判斷,就能很好的避免了使用者偽造的資料,讓這次投票無需伺服器,也能變得安全可靠了。

程式碼分享

參考:https://cybozudev.kf5.com/hc/kb/article/1588162/

視訊參考:https://www.bilibili.com/video/BV1Q841157A3/