程序地带

元旦三天假期,实现一个电商退单管理系统【四】-手机客户端实现


需求变更

 拆包出现异常,需要留下照片凭证,以防后期抵赖。这当然属于手机端功能,于是强烈向电商老板推荐手机客户端。


另外近期出现了一个奇怪的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

 


其他代码不放了,都是一些轮子。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zhouyu629/p/14267655.html

随机推荐

python_unittest框架

python_unittest框架

一、Unittest:unittest是Python自带的单元测试框架,我们可以用其来作为我们自动化测试框架的用例组织执行框架二、Unittest核心工作原理:...

CC ♛ 阅读(587)

java学习基础篇—2

类型转换低----------------------------------------->高byte,short,char->int->long-&g...

薛博 阅读(370)

CSS行内样式

一、CSS在页面中可以帮助用户完成如下任务:显隐特效:借助CSS的display和visibility实现。再结合渐隐、渐显和各种动画序列,可以设计出复杂的视...

QXXXD 阅读(113)

Mybatis面试题最新总结

1、什么是Mybatis?  MyBatis是一个基于ORM的数据访问层/持久层的框架。2.什么是ORM?  ORM—对象关系映射  我们在访问数据库的时候所编写的都是Java程序&#x...

夏至青柠 阅读(264)

router页面缓存

一、设置标签//App.vue标签<keep-alive><router-viewv-if="this.$route.meta.keepAlive"/>...

Mr.Tang's Blog 阅读(325)