元旦三天假期,實現一個電商退單管理系統【四】-手機客戶端實現
需求變更
拆包出現異常,需要留下照片憑證,以防後期抵賴。這當然屬於手機端功能,於是強烈向電商老闆推薦手機客戶端。
另外近期出現了一個奇怪的bug,經常掃碼時重複出現同一個編碼,明明已經掃了別的碼了,系統裡接收一的還是前一個。非常難復現,初步懷疑是掃碼槍的快取功能造成的,但沒有辦法根治,造成倉庫抱怨。於是將掃碼入庫功能也加到手機客戶端上,並控制該功能只允許在倉庫使用(GPS定位,劃定區域內使用,有點電子圍欄的意思)。
開發過程中,封裝了幾個元件,版本升級已放到uni的外掛市場上,我寫了一個非常詳細的使用方法,歡迎大家免費下載,順手打個星。
https://ext.dcloud.net.cn/plugin?id=3931
主要功能預覽
1. 登入
線上升級支援多種面板定製,支援強制升級和非強制升級,支援下載進度並中途中斷升級,支援ios下載升級(企業證書)和appstore升級。圖片截的有點高高低低的,湊合看吧。
2. 拆包檢驗
默認出現列表供拆包,也可以快速掃條形碼進入檢驗。列表上拉翻頁下拉重新整理用的是MescrollBody,比uni自帶的那個好用且體驗好很多。
多照片佈局直接用的colorui。最多支援9張照片上傳。
3. 掃碼入庫
介面應該是首頁,後面應該會做成首頁。
業務邏輯跟電腦客戶端一致,先選擇快遞公司,然後掃碼入庫,不同的是,手機端不會暫存,直接調單個入庫介面上傳伺服器。
4. 照片補錄
為保證補錄的是當前快遞的照片,不允許列表選擇和手動輸入單號,只能掃碼拍照,最多支援9張照片。
5. 關於
現在介面上還叫“我的”,應該叫“關於”更合適點。功能比較少。我從colorui裡把wave.gif扒出來了,頂部圖片顯示波紋效果,看著就很舒服了,我特意截了一個 gif
部分程式碼
1. 封裝一個httpclient用於請求網路。
由於每次請求都有簽名驗證、時間戳等引數一同上傳,就封了一個js檔案。多圖片上傳,本來也準備封到這個js裡,結果服務端只能收到一張,h5端正常,已向dcloud報了bug,有了解的同學也請幫忙回覆下:https://ask.dcloud.net.cn/question/115109
function request(url, data = {}, type = 'GET', header = { }){ let ts = util.gettimestamp(); let transid = util.gettransid(ts); let sign = util.getsign(transid); const baseUrl = getApp().globalData.serverInterfaceUrl data.ts = ts data.transid = transid data.sign = sign return new Promise((resolve, reject) => { uni.request({ method: type, url: baseUrl + url, data: data, header: header, dataType: 'json', }).then((response) => { console.log(response) setTimeout(function() { uni.hideLoading(); }, 200); let [error, res] = response; resolve(res.data); }).catch(error => { let [err, res] = error; console.log(err) reject(err) }) }); }
呼叫:
httpclient.request('user',{method:"login","uname":that.user_name,"ucode":that.password} ).then(res=>{ if(res.code == 100){ //登入成功 if(that.remember_username){ uni.setStorageSync("remember_username",true) } if(that.remember_password){ uni.setStorageSync("remember_password",true) } //寫入其他快取.......
//跳轉首頁
uni.switchTab({ url:'../index/index' }) }else{ uni.showToast({ title: '登入失敗:'+res.msg, icon:'none' }); } });
2. 升級業務程式碼也放下吧,不解釋了。差分升級還在實現中,暫未放在程式碼裡。
<template> <view class="zy-modal" :class="dshow?'show':''"> <view class="zy-dialog" style="background-color: transparent;"> <view class="padding-top text-white" :class="'zy-upgrade-topbg-'+theme"> <view> <text class="zy-upgrade-title"> 發現新版本 </text> </view> <text class="flex-wrap">{{version}}</text> </view> <view class="padding-xl bg-white text-left"> <scroll-view style="max-height: 200rpx;" scroll-y="auto" v-if="!update_flag"> <text>{{update_tips}}</text> </scroll-view> <view class="zy-progress radius striped active" v-if="update_flag"> <view :class="'bg-'+theme" :style="'width: '+update_process+'%;'"> {{update_process}} </view> </view> </view> <view class="zy-bar bg-white justify-end"> <view class="action" v-if="!update_flag"> <button class="zy-btn" :class="'bg-'+theme" @click="upgrade_checked">確認升級</button> <button class="zy-btn margin-left" :class="'line-'+theme" v-if="!forceupgrade" @click="upgrade_cancel">取消升級</button> </view> <view class="action text-center" v-if="update_flag&&!forceupgrade"> <button class="zy-btn" :class="'bg-'+theme" @click="upgrade_break">中斷升級</button> </view> </view> </view> </view> </template> <script> export default { name: 'ZyUpgrade', props: { theme: { //主題,目前支援green,pink,blue,yellow,red type: String, default: 'green' }, updateurl: { //升級檢測url,全路徑 type:String, default: '' }, h5preview:{ //H5介面下是否預覽升級 type: Boolean, default: false }, oldversion: { //如果是H5,為了方便測試,可以傳入一箇舊版本號進來。 type: String, default: '' }, oldcode: { //如果是H5,為了方便測試,可以傳一箇舊版本的code進來。 type: Number, default: 0 }, appstoreflag: { //是否啟用appstore升級,如果啟用,由服務端返回appstore的地址 type: Boolean, default: false }, noticeflag:{ //是否通知主介面無需更新 type:Boolean, default: false }, autocheckupdate:{ //是否頁面截入時就判斷升級 type:Boolean, default: false } }, data() { return { update_flag: false, //點選升級按鈕後,顯示進度條 dshow: false, update_process: 0, downloadTask: [], updated2version: '', version_url: '', update_tips: '', forceupgrade: false, currentversion: this.oldversion, versionname: '', vesioncode: this.oldcode } }, mounted() { let app_flag = false // #ifdef APP-PLUS app_flag = true // #endif if((this.h5preview || app_flag) && this.autocheckupdate){ console.log("檢測升級") this.check_update() } }, computed:{ version(){ let retversion = '' retversion = this.currentversion + (this.currentversion!=''&&this.updated2version!=''?'->':'')+this.updated2version return retversion } }, methods:{ //檢測升級 check_update(){ let that = this // #ifdef APP-PLUS plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) { that.currentversion = widgetInfo.version that.versionname = widgetInfo.name that.versioncode = widgetInfo.versionCode that.updatebusiness(that) }); // #endif // #ifdef H5 if(this.h5preview){ this.updatebusiness(that) } // #endif }, updatebusiness: function(that){ //具體升級的業務邏輯 uni.showLoading({ title: '', mask: false }); let platform = uni.getSystemInfoSync().platform let formdata = { method: "upgrade", version: that.currentversion, name: that.versionname, code: that.versioncode, ts:'123', transid:'123', sign:'123', platform: platform } uni.request({ url: that.updateurl, data: formdata, success: (result) => { uni.hideLoading() let data = result.data if(data.code == 100){ console.log(data) //提示升級 if(data.data.update_flag == 1){ that.dshow = true that.update_tips = data.data.update_tips that.forceupgrade = data.data.forceupdate==1 that.version_url = data.data.update_url //that.currentversion = widgetInfo.version that.updated2version = data.data.version }else{ if(that.noticeflag){ //通知父元件,當前版為最新版本 that.$emit("showupdateTips",0) } } }else{ uni.showToast({ title: '請求升級出錯:'+data.msg, icon:'none' }); } } }); }, //點選開始升級按鈕,開始升級 upgrade_checked:function(){ this.update_flag = true this.updateversion() }, //點選取消升級按鈕,取消升級 upgrade_cancel:function(){ this.dshow = false }, //升級過程中,點選中斷升級按鈕,中斷升級 upgrade_break: function(){ this.downloadTask.abort() this.update_flag = false }, //升級下載apk安裝包的具體處理業務邏輯 updateversion: function(){ let platform = uni.getSystemInfoSync().platform console.log("作業系統:",platform) if(platform == 'ios' && this.appstoreflag){ //如果啟用ios appstore升級,則開啟appstore that.dshow = false console.log("跳轉至appstore") plus.runtime.launchApplication({ action: that.version_url }, function(e) { uni.showToast({ title: '開啟appstore失敗', icon:'none' }); }); }else{ let that = this this.update_confirm = true this.downloadTask = uni.downloadFile({ url: that.version_url, success:function(res){ if(res.statusCode == 200){ //開始安裝 plus.runtime.install(res.tempFilePath, { force: false }, function() { console.log('install success...'); plus.runtime.restart(); }, function(e) { console.error('install fail...'); }); }else{ uni.showToast({ title: '下載失敗,網路錯誤', icon:'none' }); } }, fail:function(e) { console.log("下載失敗",e) uni.showToast({ title: '下載失敗:'+e.errMsg, icon:'none' }); this.update_flag = false }, complete:function(){ } }) this.downloadTask.onProgressUpdate(function(res){ that.update_process = res.progress }) } }, } } </script> <style scoped> @import url("static/css/main.css"); .zy-upgrade-topbg-green { background-image: url('static/images/green.png'); background-size: 100% 100%; background-repeat: no-repeat; height: 290rpx; } .zy-upgrade-topbg-red { background-image: url('static/images/red.png'); background-size: 100% 100%; background-repeat: no-repeat; height: 290rpx; } .zy-upgrade-topbg-pink { background-image: url('static/images/pink.png'); background-size: 100% 100%; background-repeat: no-repeat; height: 290rpx; } .zy-upgrade-topbg-yellow { background-image: url('static/images/yellow.png'); background-size: 100% 100%; background-repeat: no-repeat; height: 290rpx; } .zy-upgrade-topbg-blue { background-image: url('static/images/blue.png'); background-size: 100% 100%; background-repeat: no-repeat; height: 290rpx; } .zy-upgrade-title { font-size: 50rpx; color: white; } </style>View Code
其他程式碼不放了,都是一些輪