摘要:由于最近在幫學(xué)校做開發(fā)一個基于微信小程序的投票系統(tǒng)項目,開發(fā)時也遇到很多坑,有一些心得,所以想分享給大家,一起討論和進步。用戶進入微信小程序后不需登錄即可直接投票。
**
一、前言**
第一次在社區(qū)發(fā)文章,作為一個大學(xué)未畢業(yè)的前端菜鳥,自己平常也經(jīng)常逛各種技術(shù)社區(qū),今天終于要發(fā)表自己的處女文章了,還是有點小激動的。由于最近在幫學(xué)校做開發(fā)一個基于微信小程序的投票系統(tǒng)項目,開發(fā)時也遇到很多坑,有一些心得,所以想分享給大家,一起討論和進步。(個人開發(fā)技術(shù)有限,不好勿噴--)。
程序能夠發(fā)布各類主題活動進行投票。
各類主題活動下能夠支持作品的展示及參與投票活動。
用戶進入微信小程序后不需登錄即可直接投票。
每天每個用戶只能對同一個作品投一票,第二天方可繼續(xù)投票。
顯示投票時間的截止時間,通過倒計時展示。
每個作品自動生成一個二維碼,掃描該二維碼可進入該作品投票介紹界面。
其他:作品篩選、作品搜索、作品排名等。
三、開發(fā)環(huán)境及工具服務(wù)器環(huán)境:Ubuntu 16.04+Node.js+Express
數(shù)據(jù)庫環(huán)境:普惠大眾的MySQL
前端及測試:微信小程序開發(fā)工具
技術(shù):Javascript+HTML+CSS+Node
排名這些界面就不展示了,由于還在測試階段,界面還是比較學(xué)院派的,后期還會增加功能和修改界面。
五、實現(xiàn)過程及難點總結(jié)(代碼)其實整個項目難點不多,大部分是數(shù)據(jù)的展示和一些簡單的交互而已。而要做一個比較完善的投票系統(tǒng),重頭戲必然是投票這個功能是否能完美的實現(xiàn)并展現(xiàn)在用戶的眼前。本項目中涉及到的難點就是如何使用戶在不進行注冊登錄賬號,甚至不用獲取微信登錄權(quán)限的情況下進行投票,同時系統(tǒng)能準(zhǔn)確地記錄下每個用戶的投票行為,這里就要說說數(shù)據(jù)庫的設(shè)計、小程序登錄機制以及Node的應(yīng)用了。
數(shù)據(jù)庫設(shè)計由于要實現(xiàn)每個用戶每天只能為同一個作品投一票的限制,大概想到的3鐘方案:
1. 每一個用戶都有一個對應(yīng)的投票表,每投一個作品就增加該作品的id,第二天刪除該id,查詢到不存在時即可再次投票。
2. 同理也可以每個作品有一個對應(yīng)的投票表,一個用戶投一票,就增加該用戶的id。
3. 在作品表中添加一個投票用戶字段,一個用戶投一票則將該用戶的id加進去,通過查詢該id是否存在來識別是否已經(jīng)投過票。
前兩種方案無形之中就會生成很多個表,并且其實這些表其實都是同一性質(zhì)的。所以最終選擇了第三種方案,作品表中添加一個字段,在該字段中添加每個投票用戶的id(如果用戶量很大的情況下應(yīng)該會使用前面的或其他更好的方案)。但是一般字段所用的類型varchar最大長度只有255,當(dāng)數(shù)據(jù)多一些的時候不能滿足需要。而Mysql的text類型能夠滿足,最大的LONGTEXT能有4GB的存儲,對于一個校園使用人數(shù)來說也是足夠了(比如一個用戶的openid有28個英文字符,也能存儲千萬級別的用戶了。不過據(jù)說text類型的性能是不如varchar等類型的,至于影響有多大本人沒有測試過)。但是同一個字段中增加字符,需要做一下處理,用符號將添加的數(shù)據(jù)分隔開來,方便后面的查詢。
獲取小程序用戶id那么如何識別每個投票用戶的身份呢?如果不授權(quán)獲取微信用戶的信息,那么可以直接獲取微信用戶的openid,這個openid是用戶唯一的標(biāo)識。小程序官方的介紹是:小程序可以通過微信官方提供的登錄能力方便地獲取微信提供的用戶身份標(biāo)識,快速建立小程序內(nèi)的用戶體系。
小程序的API中有個wx.login方法,通過提供小程序的Appid和AppSecret以及每次登錄生成的一個不同的用戶登錄憑證,然后在服務(wù)器端通過微信官方接口獲取到用戶的openid等數(shù)據(jù)。具體官方文檔和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 }) } }) } });
服務(wù)器端獲取openid(Node)
//定義微信小程序發(fā)送到服務(wù)器的參數(shù) 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等數(shù)據(jù) 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({ //鏈接數(shù)據(jù)庫的配置信息 host: "localhost", user: "root", password: "XXX", port: 3306, database: "display", multipleStatements: true }); // 打開鏈接 connection.connect(); //將data返回字符串形式轉(zhuǎn)換成JSON格式. var id = JSON.parse(data) var newid = id.openid } })向數(shù)據(jù)庫插入用戶openid
接著就是往數(shù)據(jù)庫中對應(yīng)字段添加用戶id就行了。但是這里有兩個細節(jié),也可以說是兩個坑吧,由于自己菜,搞了半天才弄好...
1.如果該用戶沒有投過票,那么就向字段中添加該用戶的openid,如果投過票說明字段中已經(jīng)存在該用戶id,返回提示信息。text類型是沒有默認(rèn)值的,所以初始沒有投票用戶時為Null。這里我在Node中直接用JS的indexOf函數(shù)是否包含該id字符串的方式來查詢,于是就造成了一旦該字段為Null時查詢就報錯的情況。
解決辦法:在查詢之前,先將該字段為Null的都轉(zhuǎn)換為空字符串。剛開始想用JS判斷該字段是否為空再進行操作,但是后來認(rèn)為更好的解決方案是在查詢之前直接用update將該字段的null值修改為空字符串,相比用JS判斷清爽了許多。
connection.query( "update display set d_user="" where d_user is null ",[], function (queError,queData){ ... ... })
2.插入用戶id數(shù)據(jù)時,通過","將每個用戶的openid分隔開,使用到concat函數(shù)拼接字符串。但是由于拼接的是前面獲取的id變量和一個字符串",",所以寫法比較坑。concat的第二個參數(shù)是字符串,用引號" "包裹,天真以為里面直接寫變量,外面有括號,那出來不就直接是字符串了嗎?但是卻會報錯,顯示的并不是字符串。
解決辦法:如果里面直接用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 });
解決了這兩個問題之后,其他就是同時增加票數(shù)等代碼,不再贅述。
定時清除用戶id這是能實現(xiàn)用戶每天都能投票的關(guān)鍵,指定時間清除掉字段中的openid信息,就能達到第二天用戶能夠繼續(xù)投票的功能。這里有多種方法實現(xiàn),第一種是直接在數(shù)據(jù)庫層操作,通過存儲過程或者代碼的方式將該字段的內(nèi)容賦為空值即可。第二種是在Node里用定時器或者其他方法在指定時間將數(shù)據(jù)庫該字段內(nèi)容重新賦值。
我采用的是用JS定時器來解決,當(dāng)每天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)六、后期更新
后面有時間會更新活動倒計時的寫法,每個頁面生成二維碼的方法等。
七、總結(jié)由于數(shù)據(jù)庫并不是很在行,不合理的地方肯定還有很多,希望得到大佬們的指點。同時,小程序前端還是有很多細節(jié)的地方遇到過坑,后面我會多帶帶寫文來分享。如果大家覺得還算有點看頭的話,希望點個贊啥的,給菜鳥新人一點鼓勵哈哈哈哈。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/98249.html
摘要:由于最近在幫學(xué)校做開發(fā)一個基于微信小程序的投票系統(tǒng)項目,開發(fā)時也遇到很多坑,有一些心得,所以想分享給大家,一起討論和進步。用戶進入微信小程序后不需登錄即可直接投票。 ** 一、前言 **第一次在社區(qū)發(fā)文章,作為一個大學(xué)未畢業(yè)的前端菜鳥,自己平常也經(jīng)常逛各種技術(shù)社區(qū),今天終于要發(fā)表自己的處女文章了,還是有點小激動的。由于最近在幫學(xué)校做開發(fā)一個基于微信小程序的投票系統(tǒng)項目,開發(fā)時也遇到很多...
閱讀 1382·2021-09-30 09:55
閱讀 1906·2021-08-27 13:10
閱讀 2253·2019-08-29 17:22
閱讀 1307·2019-08-29 16:30
閱讀 3474·2019-08-26 18:37
閱讀 2360·2019-08-26 11:47
閱讀 1172·2019-08-23 14:44
閱讀 1747·2019-08-23 13:46