服務端:https://github.com/jrainlau/t...
經過為期兩個晚上下班時間的努力,終于把我第一個小程序開發完成并發布上線了。整個過程還算順利,由于使用了mpvue方案進行開發,故可以享受和vue一致的流暢開發體驗;后臺系統使用了python3+flask框架進行,使用最少的代碼完成了小程序的后臺邏輯。除了開發之外,還實實在在地體驗了一把微信小程序的開發流程,包括開發者工具的使用、體驗版的發布、上線的申請等等。這些開發體驗都非常值得被記錄下來,于是便趁熱打鐵,寫下這篇文章。
由于公司里有相當多的同事都住在同一個小區,所以上下班的時候經常會在公司群里組織拼車。但是由于完全依賴聊天記錄,且上下班拼車的同事也很多,依賴群聊很容易把消息刷走,而且容易造成信息錯亂。既然如此,那么完全可以開發一個小工具把這些問題解決。
發起拼車的人把出發地點、目的地點、打車信息以卡片的形式分享出來,參與拼車的人點擊卡片就能選擇參加拼車,并且能看到同車拼友是誰,拼單的信息等等內容。
交互流程如下:
可以看到,邏輯是非常簡單的,我們只需要保證生成拼單、分享拼單、進入拼單和退出拼單這四個功能就好。
需求和功能已經確定好,首先按照小程序官網的介紹,注冊好小程序并拿到appId,接下來可以開始進行后臺邏輯的開發。
由于時間倉促,功能又簡單,所以并沒有考慮任何高并發等復雜場景,僅僅考慮功能的實現。從需求的邏輯可以知道,其實后臺只需要維護兩個列表,分別存儲當前所有拼車單以及當前所有參與了拼車的用戶即可,其數據結構如下:
當用戶確定并分享了一個拼單之后,會直接新建一個拼單,同時把該用戶添加到當前所有參與了拼車的用戶列表列表里面,并且添加到該拼單的成員列表當中:
只要維護好這兩個列表,接下來就是具體的業務邏輯了。
為了快速開發,這里我使用了python3+flask框架的方案。不懂python的讀者看到這里也不用緊張,代碼非常簡單且直白,看看也無妨。
首先新建一個BillController類:
class BillController: billsList = [] inBillUsers = []
接下來會在這個類的內部添加創建拼單、獲取拼單、參與拼單、退出拼單、判斷用戶是否在某一拼單中、圖片上傳的功能。
該方法接收客戶端傳來的拼單ID,然后拿這個ID去檢索是否存在對應的拼單。若存在則返回對應的拼單,否則報錯給客戶端。
def getBill(self, ctx): ctxBody = ctx.form billId = ctxBody['billId'] try: return response([item for item in self.billsList if item['billId'] == billId][0]) except IndexError: return response({ 'errMsg': '拼單不存在!', 'billsList': self.billsList, }, 1)
該方法會接收來自客戶端的用戶信息和拼單信息,分別添加到billsList和inBillUsers當中。
def createBill(self, ctx): ctxBody = ctx.form user = { 'userId': ctxBody['userId'], 'billId': ctxBody['billId'], 'name': ctxBody['name'], 'avatar': ctxBody['avatar'] } bill = { 'billId': ctxBody['billId'], 'from': ctxBody['from'], 'to': ctxBody['to'], 'time': ctxBody['time'], 'members': [user] } if ctxBody['userId'] in [item['userId'] for item in self.inBillUsers]: return response({ 'errMsg': '用戶已經在拼單中!' }, 1) self.billsList.append(bill) self.inBillUsers.append(user) return response({ 'billsList': self.billsList, 'inBillUsers': self.inBillUsers })
創建完成后,會返回當前的billsList和inBillUsers到客戶端。
接收客戶端傳來的用戶信息和拼單ID,把用戶添加到拼單和inBillUsers列表中。
def joinBill(self, ctx): ctxBody = ctx.form billId = ctxBody['billId'] user = { 'userId': ctxBody['userId'], 'name': ctxBody['name'], 'avatar': ctxBody['avatar'], 'billId': ctxBody['billId'] } if ctxBody['userId'] in [item['userId'] for item in self.inBillUsers]: return response({ 'errMsg': '用戶已經在拼單中!' }, 1) theBill = [item for item in self.billsList if item['billId'] == billId] if not theBill: return response({ 'errMsg': '拼單不存在' }, 1) theBill[0]['members'].append(user) self.inBillUsers.append(user) return response({ 'billsList': self.billsList, 'inBillUsers': self.inBillUsers })
接收客戶端傳來的用戶ID和拼單ID,然后刪除掉兩個列表里面的該用戶。
這個函數還有一個功能,如果判斷到這個拼單ID所對應的拼單成員為空,會認為該拼單已經作廢,會直接刪除掉這個拼單以及所對應的車輛信息圖片。
def leaveBill(self, ctx): ctxBody = ctx.form billId = ctxBody['billId'] userId = ctxBody['userId'] indexOfUser = [i for i, member in enumerate(self.inBillUsers) if member['userId'] == userId][0] indexOfTheBill = [i for i, bill in enumerate(self.billsList) if bill['billId'] == billId][0] indexOfUserInBill = [i for i, member in enumerate(self.billsList[indexOfTheBill]['members']) if member['userId'] == userId][0] # 刪除拼單里面的該用戶 self.billsList[indexOfTheBill]['members'].pop(indexOfUserInBill) # 刪除用戶列表里面的該用戶 self.inBillUsers.pop(indexOfUser) # 如果拼單里面用戶為空,則直接刪除這筆拼單 if len(self.billsList[indexOfTheBill]['members']) == 0: imgPath = './imgs/' + self.billsList[indexOfTheBill]['img'].split('/getImg')[1] if os.path.exists(imgPath): os.remove(imgPath) self.billsList.pop(indexOfTheBill) return response({ 'billsList': self.billsList, 'inBillUsers': self.inBillUsers })
接收客戶端傳來的用戶ID,接下來會根據這個用戶ID去inBillUsers里面去檢索該用戶所對應的拼單,如果能檢索到,會返回其所在的拼單。
def inBill(self, ctx): ctxBody = ctx.form userId = ctxBody['userId'] if ctxBody['userId'] in [item['userId'] for item in self.inBillUsers]: return response({ 'inBill': [item for item in self.inBillUsers if ctxBody['userId'] == item['userId']][0], 'billsList': self.billsList, 'inBillUsers': self.inBillUsers }) return response({ 'inBill': False, 'billsList': self.billsList, 'inBillUsers': self.inBillUsers })
接收客戶端傳來的拼單ID和圖片資源,先存儲圖片,然后把該圖片的路徑寫入對應拼單ID的拼單當中。
def uploadImg(self, ctx): billId = ctx.form['billId'] file = ctx.files['file'] filename = file.filename file.save(os.path.join('./imgs', filename)) # 把圖片信息掛載到對應的拼單 indexOfTheBill = [i for i, bill in enumerate(self.billsList) if bill['billId'] == billId][0] self.billsList[indexOfTheBill]['img'