1、uniapp官网
网址:https://uniapp.dcloud.net.cn/
2、引入组件库
网址:https://www.uviewui.com/
3、问题如下
(1)使用SwipeAction 滑动单元格后,在滑动单元格上无法上下滑动
解决方法:自己写,代码如下
<template>
<view class="main">
<view
v-for="(item, index) in infoList"
:key="index"
:data-index="index"
class="order-item"
@touchstart="drawStart"
@touchmove="drawMove"
@touchend="drawEnd"
:style="'right:'+item.right+'px'">
<view class="content">
我打碎了夕阳,也揉碎了月光,拉着李白大醉一场,撒下九州的霜{{item.label}}
</view>
<view class="edit">编辑</view>
<view class="remove">删除</view>
</view>
<u-popup :show="showKong">
<view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
components: {
},
props: {
},
data() {
return {
//左滑默认宽度
delBtnWidth: 200,
startX: 0,
showKong: false,
infoList: [
{
label: '我打碎了夕阳,也揉碎了月光,拉着李白大醉一场,撒下九州的霜',
right: 0
},
{
label: '我打碎了夕阳,洒在你的身上,你有了圣光,我黯然退场',
right: 0
},
{
label: '我打碎了夕阳,把青春留给边疆;看万家灯火,可有一盏为我亮',
right: 0
},
{
label: '我打碎了夕阳,借了一碗清汤,想等一束月光,可倒影全是你的模样',
right: 0
},
{
label: '我打碎了夕阳,不顾他人的目光,抛弃一切,只为不负这人间一趟',
right: 0
},
{
label: '我打碎了夕阳,落在了我的心上。看着残破的夕阳,想着远方你的模样,已然为你痴狂',
right: 0
},
]
}
},
methods: {
// 开始触发
drawStart(e) {
var touch = e.touches[0];
this.startX = touch.clientX;
},
//触摸滑动
drawMove(e) {
for (var index in this.infoList) {
this.$set(this.infoList[index],'right',0);
}
var touch = e.touches[0];
var item = this.infoList[e.currentTarget.dataset.index];
var disX = this.startX - touch.clientX;
if (disX >= 20) {
if (disX > this.delBtnWidth) {
disX = this.delBtnWidth;
}
this.$set(this.infoList[e.currentTarget.dataset.index],'right',disX);
} else {
this.$set(this.infoList[e.currentTarget.dataset.index],'right',0);
}
},
//触摸滑动结束
drawEnd(e) {
var item = this.infoList[e.currentTarget.dataset.index];
if (item.right >= this.delBtnWidth / 2) {
this.$set(this.infoList[e.currentTarget.dataset.index],'right',this.delBtnWidth);
} else {
this.$set(this.infoList[e.currentTarget.dataset.index],'right',0);
}
this.showKong = true;
this.showKong = false;
}
}
}
</script>
<style lang="scss">
.main{
width: 100%;
height: auto;
margin: 10px auto;
overflow: hidden;
.order-item {
width: 100%;
display: flex;
position: relative;
margin: 10px auto;
align-items:right ;
flex-direction: row;
}
.content{
width: 100%;
padding: 48rpx;
border-bottom: 1px solid #ddd;
}
.remove {
margin-left:-5%;
width: 200rpx;
height: 100%;
background-color: #FF6868;
color: #FFFFFF;
position: absolute;
top: 0;
right: -400rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
}
.edit{
width: 200rpx;
height: 100%;
background-color: #F5F6F9;
color: #1A1A1A;
position: absolute;
top: 0;
right: -200rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
}
}
</style>
(2)列表数据改变后列表数据不变
解决方法:网上的方法试了,也不好用,就加一个空的弹出层,数据改变后显示隐藏
<u-popup :show="showKong">
<view>
</view>
</u-popup>
this.showKong = true;
this.showKong = false;
(3)需求:筛选1个月以下,3个月以下,1年以内,1-3年,3-5年,需要传给后端时间段,我需要获取当前时间,1个月前的时间,3个月前的时间,1年前的时间,3年前的时间,5年前的时间
没有使用moment.js,不知道在这里可不可用,写的第一个方法web端好用,app报错,最终使用的方法如下:
const getFormatDate = (dateInfo) => { // 获取时间,格式YYYY-MM-DD
if (!dateInfo) {
return
}
let date = dateInfo;
let seperator1 = "-";
let year = date.getFullYear();
let month = date.getMonth() + 1;
let strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
let currentdate = year + seperator1 + month + seperator1 + strDate;
return currentdate;
}
/* 获取之前的日期 1个月前传2一年前传13*/
const getFDate = (num,type) => {
const date = getFormatDate(new Date()).split('-')
let yy0=parseInt(date[0]);
let mm0=parseInt(date[1]);
let dd0=parseInt(date[2]);
let pdStr = getFormatDate(new Date(yy0,mm0-num,dd0-type));
return pdStr; // 可针对需要的格式进行优化。
}
/* 时间段定义 */
ageSearchOption: [{
name: '全部',
value: '',
maxBirthday: '',
minBirthday: ''
}, {
name: '1个月以下',
value: '1',
maxBirthday: common.getFDate(1,0),
minBirthday: common.getFDate(2,1)
}, {
name: '3个月以下',
value: '2',
maxBirthday: common.getFDate(1,0),
minBirthday: common.getFDate(4,1)
}, {
name: '1岁以下',
value: '3',
maxBirthday: common.getFDate(1,0),
minBirthday: common.getFDate(13,1)
},{
name: '1-3岁',
value: '4',
maxBirthday: common.getFDate(13,0),
minBirthday: common.getFDate(37,1)
}, {
name: '3-5岁',
value: '5',
maxBirthday: common.getFDate(37,0),
minBirthday: common.getFDate(61,1)
}]
(4)获取当前日期后面几天的日期
const getNextDay = (cdate,daynum) => { // cdate:日期,daynum:几天
var date = new Date(cdate);
var base = Date.parse(date); // 转换为时间戳
var year = date.getFullYear(); //获取当前年份
var mon = date.getMonth() + 1; //获取当前月份
var day = date.getDate(); //获取当前日
var oneDay = 24 * 3600 *1000
var daytimeArr = []
var now = new Date(base += oneDay*daynum);
var myear = now.getFullYear();
var month = now.getMonth() + 1;
var mday = now.getDate()
daytimeArr.push([myear, month >=10 ?month :'0'+ month, mday>=10?mday:'0'+mday].join('-'))
return daytimeArr[0]
}
(5)根据出生日期判断年龄
const getAge = (strBirthday) => { // 根据出生日期计算年龄
//strBirthday传入格式 2020-04-15
if (!strBirthday) {
return
}
var returnAge;
var strBirthdayArr = strBirthday.split('-');
var birthYear = strBirthdayArr[0];
var birthMonth = strBirthdayArr[1];
var birthDay = strBirthdayArr[2].substr(0,2);
//获取当前日期
var d = new Date();
var nowYear = d.getFullYear();
var nowMonth = d.getMonth() + 1;
var nowDay = d.getDate();
if (nowYear == birthYear) {
// returnAge = 0; //同年 则为0岁
if (nowMonth==birthMonth) {
returnAge = nowDay-birthDay + '天'
} else {
returnAge = nowMonth-birthMonth + '个月'
}
} else {
var ageDiff = nowYear - birthYear; //年之差
if (ageDiff > 0) {
if (nowMonth == birthMonth) {
var dayDiff = nowDay - birthDay; //日之差
if (dayDiff < 0) {
returnAge = ageDiff - 1 + '岁';
} else {
returnAge = ageDiff + '岁';
}
} else if (nowMonth > birthMonth) {
returnAge = ageDiff + '岁' + (nowMonth-birthMonth) + '个月'
} else if (nowMonth < birthMonth){
returnAge = ageDiff-1 + '岁' +(12 - birthMonth + nowMonth) + '个月'
if(ageDiff-1==0){
returnAge = (12 - birthMonth + nowMonth) + '个月'
}
}
} else {
returnAge = -1; //返回-1 表示出生日期输入错误 晚于今天
}
}
return returnAge; //返回周岁年龄
}
(6)保存sku图片功能
链接:https://www.cnblogs.com/boreguo/p/16327447.html
(7)app扫码功能
uni.scanCode方法
(8)使用icon图标操作过于频繁偶现undefined
解决方法:这个我这边正常操作没有复现这个问题,是测试那边偶发的,最后把icon图标改成image图了
(9)token刷新与网络中断提示,这个把请求封装了一下request.js
//const baseUrl = 'https://cpkx.bjzkkp.com:7110/'; // 正式
const baseUrl = 'http://cpkx.bjzkkp.com:7010/'; // 测试
// 不带token请求
const httpRequest = (opts, data) => {
uni.getNetworkType({
success: function(res) {
if (res.networkType=='none') {
uni.showToast({
title: '网络连接不可用!',
icon: 'none',
duration: 3000
});
return;
}
}
})
let httpDefaultOpts = {
url: baseUrl + opts.url,
data: data,
method: opts.method,
header: opts.method == 'get' ? {
'X-Requested-With': 'XMLHttpRequest',
"Accept": "application/json",
"Content-Type": "application/json; charset=UTF-8"
} : {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json; charset=UTF-8'
},
dataType: 'json',
}
let promise = new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(res) => {
resolve(res[1])
}
).catch(
(response) => {
if (response) {
upDateToken().then(r => {
return _httpRequest(httpDefaultOpts).then(re => {
if (re.statusCode==200) {
return resolve(re);
}
})
})
}
}
)
})
return promise
};
const _httpRequest = (httpDefaultOpts) => {
return new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(res) => {
if (res[1].statusCode == 200) {
resolve(res[1])
} else if (res[1].statusCode == 403) {
reject(res[1])
}
}
).catch(
(response) => {
reject(response)
}
)
})
};
const httpRequest2 = (opts, data) => {
uni.getNetworkType({
success: function(res) {
if (res.networkType=='none') {
uni.showToast({
title: '网络连接不可用!',
icon: 'none',
duration: 3000
});
return;
}
}
})
let httpDefaultOpts = {
url: baseUrl + opts.url,
data: data,
method: opts.method,
header: opts.method == 'get' ? {
'X-Requested-With': 'XMLHttpRequest',
"Accept": "application/json",
"Content-Type": "application/json; charset=UTF-8"
} : {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded'
},
dataType: 'json',
}
let promise = new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(res) => {
resolve(res[1])
}
).catch(
(response) => {
if (response) {
upDateToken().then(r => {
return _httpRequest(httpDefaultOpts).then(re => {
if (re.statusCode==200) {
return resolve(re);
}
})
})
}
}
)
})
return promise
};
//带Token请求
const httpTokenRequest = (opts, data) => {
const that = this;
uni.getNetworkType({
success: function(res) {
if (res.networkType=='none') {
uni.showToast({
title: '网络连接不可用!',
icon: 'none',
duration: 3000
});
return;
}
}
})
let token = uni.getStorageSync('token');
if (token == '' || token == undefined || token == null) {
uni.showToast({
title: '账号已过期,请重新登录',
icon: 'none',
complete: function() {
uni.reLaunch({
url: '/pages/login/index'
});
}
});
} else {
let httpDefaultOpts = {
url: baseUrl + opts.url,
data: data,
method: opts.method,
header: opts.method == 'get' ? {
'Authorization': token,
'X-Requested-With': 'XMLHttpRequest',
"Accept": "application/json",
"Content-Type": "application/json; charset=UTF-8"
} : {
'Authorization': token,
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json; charset=UTF-8'
},
dataType: 'json',
}
let promise = new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(res) => {
if (res[1].statusCode == 200) {
resolve(res[1])
} else {
if (res[1].statusCode == 403) {
upDateToken().then(r => {
return _httpTokenRequest(opts, data).then(re => {
if (re.statusCode==200) {
return resolve(re);
}
})
})
} else {
resolve(res[1])
}
}
}
).catch(
(response) => {
upDateToken().then(r => {
return _httpRequest(httpDefaultOpts).then(re => {
if (re.statusCode==200) {
return resolve(re);
}
})
})
}
)
})
return promise
}
// let token = uni.getStorageSync('token')
//此token是登录成功后后台返回保存在storage中的
};
const _httpTokenRequest = (opts, data) => {
const that = this;
uni.getNetworkType({
success: function(res) {
if (res.networkType=='none') {
uni.showToast({
title: '网络连接不可用!',
icon: 'none',
duration: 3000
});
return;
}
}
})
let token = uni.getStorageSync('token');
if (token == '' || token == undefined || token == null) {
uni.showToast({
title: '账号已过期,请重新登录',
icon: 'none',
complete: function() {
uni.reLaunch({
url: '/pages/login/index'
});
}
});
} else {
let httpDefaultOpts = {
url: baseUrl + opts.url,
data: data,
method: opts.method,
header: opts.method == 'get' ? {
'Authorization': token,
'X-Requested-With': 'XMLHttpRequest',
"Accept": "application/json",
"Content-Type": "application/json; charset=UTF-8"
} : {
'Authorization': token,
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json; charset=UTF-8'
},
dataType: 'json',
}
let promise = new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(res) => {
if (res[1].statusCode == 200) {
resolve(res[1])
} else {
if (res[1].statusCode == 403) {
reject(res[1])
} else {
resolve(res[1])
}
}
}
).catch(
(response) => {
upDateToken().then(r => {
return _httpTokenRequest(opts, data).then(re => {
if (re.statusCode==200) {
return resolve(re);
}
})
})
}
)
})
return promise
}
// let token = uni.getStorageSync('token')
//此token是登录成功后后台返回保存在storage中的
};
const httpTokenRequest2 = (opts, data) => {
uni.getNetworkType({
success: function(res) {
if (res.networkType=='none') {
uni.showToast({
title: '网络连接不可用!',
icon: 'none',
duration: 3000
});
return;
}
}
})
let token = uni.getStorageSync('token');
if (token == '' || token == undefined || token == null) {
uni.showToast({
title: '账号已过期,请重新登录',
icon: 'none',
complete: function() {
uni.reLaunch({
url: '/pages/login/index'
});
}
});
} else {
let httpDefaultOpts = {
url: baseUrl + opts.url,
data: data,
method: opts.method,
header: opts.method == 'get' ? {
'Authorization': token,
'X-Requested-With': 'XMLHttpRequest',
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
} : {
'Authorization': token,
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded'
},
dataType: 'json',
}
let promise = new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(res) => {
if (res[1].statusCode == 200) {
resolve(res[1])
} else {
if (res[1].statusCode == 403) {
upDateToken().then(r => {
return _httpTokenRequest2(opts, data).then(re => {
if (re.statusCode==200) {
return resolve(re);
}
})
})
} else {
resolve(res[1])
}
}
}
).catch(
(response) => {
upDateToken().then(r => {
return _httpRequest(httpDefaultOpts).then(re => {
if (re.statusCode==200) {
return resolve(re);
}
})
})
}
)
})
return promise
}
// let token = uni.getStorageSync('token')
//此token是登录成功后后台返回保存在storage中的
};
//带Token请求
const _httpTokenRequest2 = (opts, data) => {
uni.getNetworkType({
success: function(res) {
if (res.networkType=='none') {
uni.showToast({
title: '网络连接不可用!',
icon: 'none',
duration: 3000
});
return;
}
}
})
let token = uni.getStorageSync('token');
if (token == '' || token == undefined || token == null) {
uni.showToast({
title: '账号已过期,请重新登录',
icon: 'none',
complete: function() {
uni.reLaunch({
url: '/pages/login/index'
});
}
});
} else {
let httpDefaultOpts = {
url: baseUrl + opts.url,
data: data,
method: opts.method,
header: opts.method == 'get' ? {
'Authorization': token,
'X-Requested-With': 'XMLHttpRequest',
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
} : {
'Authorization': token,
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded'
},
dataType: 'json',
}
let promise = new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(res) => {
if (res[1].statusCode == 200) {
resolve(res[1])
} else {
if (res[1].statusCode == 403) {
reject(res[1])
} else {
resolve(res[1])
}
}
}
).catch(
(response) => {
upDateToken().then(r => {
return _httpRequest(httpDefaultOpts).then(re => {
if (re.statusCode==200) {
return resolve(re);
}
})
})
}
)
})
return promise
}
// let token = uni.getStorageSync('token')
//此token是登录成功后后台返回保存在storage中的
};
// 更新update
const upDateToken = () => {
let token = uni.getStorageSync('token');
let refreshToken = uni.getStorageSync('refreshToken');
return new Promise((resolve, reject) => {
uni.request({
url: baseUrl + `auth/tokens`,
method: "POST",
header: {
'content-type': 'application/json',
'Authorization': token
},
data: {
"refreshToken": refreshToken
},
success: (rres) => {
const code = rres.statusCode.toString()
if (code.startsWith('2')) {
uni.setStorageSync('token',rres.data.token)
resolve(rres)
} else {
reject(rres)
}
},
fail: (error) => {
/* uni.showToast({
title: '账号已过期,请重新登录',
icon: 'none',
complete: function() {
uni.reLaunch({
url: '/pages/login/index'
});
}
});
uni.removeStorageSync('token')
uni.removeStorageSync('refreshToken') */
//reject(error)
}
})
})
}
export default {
baseUrl,
httpRequest,
httpRequest2,
httpTokenRequest,
httpTokenRequest2,
upDateToken
}
(10)微信支付功能实现: 请求后端接口,拿到支付订单信息,将订单信息放到请求中去调起微信支付
rechargeNow() {
let optsList = {
url:`api/currencies/recharges`,
method: 'post'
};
let info = {
payType: this.rechargeType
}
if (this.currentRechargeIndex==-1) {
info = {
payType: this.rechargeType,
currencyNum: this.currencyNum
}
} else {
info = {
payType: this.rechargeType,
rechargeSetCode: this.rechargeList[this.currentRechargeIndex].code
}
}
const that = this;
request.httpTokenRequest(optsList, info).then(res => {
if (res.statusCode === 200) {
if (that.rechargeType==1) {
uni.requestPayment({
provider: "wxpay",
orderInfo: res.data,
success: (e) => {
that.$emit("changes", true)
},
fail: (e) => {
uni.showModal({
content: "取消支付",
showCancel: false
})
}
})
} else {
uni.showToast({
icon: 'none',
title: '支付宝支付,暂时没有哈'
})
}
} else {
uni.showToast({
icon: 'none',
title: res.data.message || '调用失败'
})
}
})
}
(11)全局样式配置
在pages.json中配置globalStyle
a.横屏配置
"pageOrientation": "landscape", //横屏配置,全局屏幕旋转设置(仅 APP/微信/QQ小程序),支持 auto / portrait / landscape
b.屏幕适配
"rpxCalcMaxDeviceWidth": 960, // rpx 计算所支持的最大设备宽度,单位 px,默认值为 960
"rpxCalcBaseDeviceWidth": 375, // rpx 计算使用的基准设备宽度,设备实际宽度超出 rpx 计算所支持的最大设备宽度时将按基准宽度计算,单位 px,默认值为 375
"rpxCalcIncludeWidth": 750 // rpx 计算特殊处理的值,始终按实际的设备宽度计算,单位 rpx,默认值为 750
(12)刷新页面
主要涉及父子组件之间传参,保存成功后像父组件发送刷新请求。
(13)app版本检查更新功能,获取服务器版本,获取本地版本,判断版本号是否相同,相同无更新,不同就根据后端返回的apk地址去更新
/* 检查更新 */
checkNew() {
this.checkVersionToLoadUpdate(this.currentVersion,{edition:this.apkVersion,uplodurl:this.apkUrl})
},
/**
* 进行版本型号的比对 以及下载更新请求
* @param {Object} server_version 服务器最新 应用版本号
* @param {Object} curr_version 当前应用版本号
*/
checkVersionToLoadUpdate:function(curr_version,data){
if(curr_version != data.edition){
//TODO 此处判断是否为 WIFI连接状态
if(plus.networkinfo.getCurrentType()!=3){
uni.showToast({
title: '有新的版本发布,检测到您目前非Wifi连接,为节约您的流量,程序已停止自动更新,将在您连接WIFI之后重新检测更新',
mask: true,
duration: 5000,
icon:"none"
});
return;
}else{
uni.showModal({
title: "版本更新",
content: '有新的版本发布,检测到您当前为Wifi连接,是否立即进行新版本下载?',
confirmText:'立即更新',
cancelText:'稍后进行',
success: function (res) {
if (res.confirm) {
uni.showToast({
icon:"none",
mask: true,
title: '正在下载,新版本下载完成后将自动弹出安装程序',
duration: 5000,
});
//设置 最新版本apk的下载链接
var downloadApkUrl = data.uplodurl;
var dtask = plus.downloader.createDownload( downloadApkUrl, {}, function ( d, status ) {
// 下载完成
if ( status == 200 ) {
plus.runtime.install(plus.io.convertLocalFileSystemURL(d.filename),{},{},function(error){
uni.showToast({
title: '安装失败',
duration: 1500
});
})
} else {
uni.showToast({
title: '更新失败',
duration: 1500
});
}
});
dtask.start();
} else if (res.cancel) {
console.log('稍后更新');
}
}
});
}
} else {
uni.showToast({
title: '当前版本为最新版本',
duration: 1500,
icon:"none"
});
}
}
参考链接: