摘要:由于最近在幫學校做開發一個基于微信小程序的投票系統項目,開發時也遇到很多坑,有一些心得,所以想分享給大家,一起討論和進步。用戶進入微信小程序后不需登錄即可直接投票。
**
一、前言**
第一次在社區發文章,作為一個大學未畢業的前端菜鳥,自己平常也經常逛各種技術社區,今天終于要發表自己的處女文章了,還是有點小激動的。由于最近在幫學校做開發一個基于微信小程序的投票系統項目,開發時也遇到很多坑,有一些心得,所以想分享給大家,一起討論和進步。(個人開發技術有限,不好勿噴--)。
程序能夠發布各類主題活動進行投票。
各類主題活動下能夠支持作品的展示及參與投票活動。
用戶進入微信小程序后不需登錄即可直接投票。
每天每個用戶只能對同一個作品投一票,第二天方可繼續投票。
顯示投票時間的截止時間,通過倒計時展示。
每個作品自動生成一個二維碼,掃描該二維碼可進入該作品投票介紹界面。
其他:作品篩選、作品搜索、作品排名等。
三、開發環境及工具服務器環境:Ubuntu 16.04+Node.js+Express
數據庫環境:普惠大眾的MySQL
前端及測試:微信小程序開發工具
技術:Javascript+HTML+CSS+Node
排名這些界面就不展示了,由于還在測試階段,界面還是比較學院派的,后期還會增加功能和修改界面。
五、實現過程及難點總結(代碼)其實整個項目難點不多,大部分是數據的展示和一些簡單的交互而已。而要做一個比較完善的投票系統,重頭戲必然是投票這個功能是否能完美的實現并展現在用戶的眼前。本項目中涉及到的難點就是如何使用戶在不進行注冊登錄賬號,甚至不用獲取微信登錄權限的情況下進行投票,同時系統能準確地記錄下每個用戶的投票行為,這里就要說說數據庫的設計、小程序登錄機制以及Node的應用了。
數據庫設計由于要實現每個用戶每天只能為同一個作品投一票的限制,大概想到的3鐘方案:
1. 每一個用戶都有一個對應的投票表,每投一個作品就增加該作品的id,第二天刪除該id,查詢到不存在時即可再次投票。
2. 同理也可以每個作品有一個對應的投票表,一個用戶投一票,就增加該用戶的id。
3. 在作品表中添加一個投票用戶字段,一個用戶投一票則將該用戶的id加進去,通過查詢該id是否存在來識別是否已經投過票。
前兩種方案無形之中就會生成很多個表,并且其實這些表其實都是同一性質的。所以最終選擇了第三種方案,作品表中添加一個字段,在該字段中添加每個投票用戶的id(如果用戶量很大的情況下應該會使用前面的或其他更好的方案)。但是一般字段所用的類型varchar最大長度只有255,當數據多一些的時候不能滿足需要。而Mysql的text類型能夠滿足,最大的LONGTEXT能有4GB的存儲,對于一個校園使用人數來說也是足夠了(比如一個用戶的openid有28個英文字符,也能存儲千萬級別的用戶了。不過據說text類型的性能是不如varchar等類型的,至于影響有多大本人沒有測試過)。但是同一個字段中增加字符,需要做一下處理,用符號將添加的數據分隔開來,方便后面的查詢。
獲取小程序用戶id那么如何識別每個投票用戶的身份呢?如果不授權獲取微信用戶的信息,那么可以直接獲取微信用戶的openid,這個openid是用戶唯一的標識。小程序官方的介紹是:小程序可以通過微信官方提供的登錄能力方便地獲取微信提供的用戶身份標識,快速建立小程序內的用戶體系。
小程序的API中有個wx.login方法,通過提供小程序的Appid和AppSecret以及每次登錄生成的一個不同的用戶登錄憑證,然后在服務器端通過微信官方接口獲取到用戶的openid等數據。具體官方文檔和API等鏈接:https://developers.weixin.qq....
微信端請求:
wx.login({ success: res => { console.log(res.code) wx.request({ url: "http://localhost:8080/data", data: { code: res.code, Appid: "wxXXX", AppSecret: "XXX", }, header: { "content-type": "application/json" }, success: function (next) { console.log(next.data) that.setData({ showlist: next.data }) } }) } });
服務器端獲取openid(Node)
//定義微信小程序發送到服務器的參數 var code = req.query.code; var appid = req.query.Appid; var appsecret = req.query.AppSecret; var index = req.query.id; console.log(appid); //請求外部url,傳參返回用戶ID等數據 request("https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+appsecret+"&js_code="+code+"&grant_type=authorization_code", function (error, response, data) { if (!error && res.statusCode == 200) { const connection = mysql.createConnection({ //鏈接數據庫的配置信息 host: "localhost", user: "root", password: "XXX", port: 3306, database: "display", multipleStatements: true }); // 打開鏈接 connection.connect(); //將data返回字符串形式轉換成JSON格式. var id = JSON.parse(data) var newid = id.openid } })向數據庫插入用戶openid
接著就是往數據庫中對應字段添加用戶id就行了。但是這里有兩個細節,也可以說是兩個坑吧,由于自己菜,搞了半天才弄好...
1.如果該用戶沒有投過票,那么就向字段中添加該用戶的openid,如果投過票說明字段中已經存在該用戶id,返回提示信息。text類型是沒有默認值的,所以初始沒有投票用戶時為Null。這里我在Node中直接用JS的indexOf函數是否包含該id字符串的方式來查詢,于是就造成了一旦該字段為Null時查詢就報錯的情況。
解決辦法:在查詢之前,先將該字段為Null的都轉換為空字符串。剛開始想用JS判斷該字段是否為空再進行操作,但是后來認為更好的解決方案是在查詢之前直接用update將該字段的null值修改為空字符串,相比用JS判斷清爽了許多。
connection.query( "update display set d_user="" where d_user is null ",[], function (queError,queData){ ... ... })
2.插入用戶id數據時,通過","將每個用戶的openid分隔開,使用到concat函數拼接字符串。但是由于拼接的是前面獲取的id變量和一個字符串",",所以寫法比較坑。concat的第二個參數是字符串,用引號" "包裹,天真以為里面直接寫變量,外面有括號,那出來不就直接是字符串了嗎?但是卻會報錯,顯示的并不是字符串。
解決辦法:如果里面直接用ES6語法寫`${newid}`是不行的,得像下面這樣寫:
connection.query( "update display set d_user = concat(d_user, "+`"${newid},"`+") where d_id = "+index,[], function (err, data) { console.log(err) //null console.log(data) // object });
解決了這兩個問題之后,其他就是同時增加票數等代碼,不再贅述。
定時清除用戶id這是能實現用戶每天都能投票的關鍵,指定時間清除掉字段中的openid信息,就能達到第二天用戶能夠繼續投票的功能。這里有多種方法實現,第一種是直接在數據庫層操作,通過存儲過程或者代碼的方式將該字段的內容賦為空值即可。第二種是在Node里用定時器或者其他方法在指定時間將數據庫該字段內容重新賦值。
我采用的是用JS定時器來解決,當每天00:00:00時,就重新賦值。但是要注意定時器的啟動和清除,否則一直開啟肯定會有性能影響。
var timer = setInterval(function(){ var date = new Date(); var hours=new Date().getHours(); var minutes=new Date().getMinutes(); var seconds=new Date().getSeconds(); if(hours == 23 && minutes == 59 && seconds == 59){ connection.query("update display set d_user = "" ",[], function (err, data) { console.log(data) }) } },1000)六、后期更新
后面有時間會更新活動倒計時的寫法,每個頁面生成二維碼的方法等。
七、總結由于數據庫并不是很在行,不合理的地方肯定還有很多,希望得到大佬們的指點。同時,小程序前端還是有很多細節的地方遇到過坑,后面我會多帶帶寫文來分享。如果大家覺得還算有點看頭的話,希望點個贊啥的,給菜鳥新人一點鼓勵哈哈哈哈。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/53035.html
摘要:由于最近在幫學校做開發一個基于微信小程序的投票系統項目,開發時也遇到很多坑,有一些心得,所以想分享給大家,一起討論和進步。用戶進入微信小程序后不需登錄即可直接投票。 ** 一、前言 **第一次在社區發文章,作為一個大學未畢業的前端菜鳥,自己平常也經常逛各種技術社區,今天終于要發表自己的處女文章了,還是有點小激動的。由于最近在幫學校做開發一個基于微信小程序的投票系統項目,開發時也遇到很多...
閱讀 1446·2021-11-24 09:39
閱讀 3626·2021-09-29 09:47
閱讀 1570·2021-09-29 09:34
閱讀 3067·2021-09-10 10:51
閱讀 2535·2019-08-30 15:54
閱讀 3215·2019-08-30 15:54
閱讀 868·2019-08-30 11:07
閱讀 1003·2019-08-29 18:36