diff --git a/manifest.json b/manifest.json
index 3b9be0f..2b342a8 100644
--- a/manifest.json
+++ b/manifest.json
@@ -2,8 +2,8 @@
"name" : "心灵空间",
"appid" : "__UNI__BBBDFD2",
"description" : "心灵空间",
- "versionName" : "1.0.11",
- "versionCode" : 1011,
+ "versionName" : "1.0.22",
+ "versionCode" : 1022,
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
@@ -30,7 +30,7 @@
"prompt" : "template",
"template" : {
"title" : "用户协议和隐私政策",
- "message" : "请你务必审慎阅读、充分理解“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。
你可阅读《用户协议》和《隐私协议》了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
+ "message" : "请你务必审慎阅读、充分理解“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。
你可阅读《用户协议》和《隐私协议》了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
"buttonAccept" : "同意",
"buttonRefuse" : "暂不同意"
}
@@ -56,7 +56,8 @@
],
"minSdkVersion" : 23,
"targetSdkVersion" : 35,
- "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
+ "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
+ "schemes" : "soulspace"
},
/* ios打包配置 */
"ios" : {
@@ -70,13 +71,14 @@
]
}
},
- "idfa" : false,
- "plistcmds" : [ "Delete :NSUserTrackingUsageDescription" ],
+ "idfa" : true,
"privacyDescription" : {
"NSPhotoLibraryUsageDescription" : "保障您在此app中的修改头像、申诉反馈上传图片功能的正常使用",
"NSPhotoLibraryAddUsageDescription" : "保障您在此app中的修改头像、申诉反馈上传图片功能的正常使用",
- "NSCameraUsageDescription" : "保障您在此app中的修改头像、申诉反馈上传图片功能的正常使用"
- }
+ "NSCameraUsageDescription" : "保障您在此app中的修改头像、申诉反馈上传图片功能的正常使用",
+ "NSUserTrackingUsageDescription" : "请放心,开启权限不会获取您在其他站点的隐私信息,该权限仅用于标识设备并保障服务安全与提示浏览体验"
+ },
+ "urltypes" : "soulspace"
},
/* SDK配置 */
"sdkConfigs" : {
diff --git a/pages.json b/pages.json
index 9b3fe83..bd42fd2 100644
--- a/pages.json
+++ b/pages.json
@@ -412,6 +412,21 @@
"popGesture": "none"
}
}
+ },
+ {
+ "path": "uni_modules/uni-upgrade-center-app/pages/upgrade-popup",
+ "style": {
+ "app-plus": {
+ "animationDuration": 200,
+ "animationType": "fade-in",
+ "background": "transparent",
+ "backgroundColorTop": "transparent",
+ "popGesture": "none",
+ "scrollIndicator": false,
+ "titleNView": false
+ },
+ "disableScroll": true
+ }
}
],
"tabBar": {
diff --git a/pages/component/commonComponents/selectGoods.vue b/pages/component/commonComponents/selectGoods.vue
index d834414..98c5ea5 100644
--- a/pages/component/commonComponents/selectGoods.vue
+++ b/pages/component/commonComponents/selectGoods.vue
@@ -14,15 +14,15 @@
-
-
+
+
¥{{selectGoodsData.price}}
{{ slotProps.row.productName }}
-
-
- ¥{{slotProps.row.price}}
-
-
+
@@ -129,6 +120,38 @@ export default {
...mapState(["userInfo"]),
},
methods: {
+ getPrice(slotProps) {
+ if (
+ Number(slotProps.row.isVipPrice) === 1 &&
+ Number(slotProps.row.vipPrice) > 0
+ ) {
+ return `
+
+ ¥${Number(slotProps.row.vipPrice).toFixed(2)}
+
+
+ ¥${Number(slotProps.row.price).toFixed(2)}
+
+ `;
+ } else if (Number(slotProps.row.activityPrice) > 0) {
+ return `
+
+ ¥${Number(slotProps.row.activityPrice).toFixed(2)}
+
+
+ ¥${Number(slotProps.row.price).toFixed(2)}
+
+ `;
+ } else {
+ return `
+ ¥${Number(slotProps.row.price).toFixed(2)}
+ `;
+ }
+ },
// 放大图片
previewImage(url) {
console.log(url);
diff --git a/pages/curriculum/list/index.vue b/pages/curriculum/list/index.vue
index f80af38..52c64d8 100644
--- a/pages/curriculum/list/index.vue
+++ b/pages/curriculum/list/index.vue
@@ -9,8 +9,7 @@
-
-
+
暂无数据
-
+
{{item.title}}
diff --git a/pages/detail/orderLCont.vue b/pages/detail/orderLCont.vue
index b82632d..17c53fb 100644
--- a/pages/detail/orderLCont.vue
+++ b/pages/detail/orderLCont.vue
@@ -153,7 +153,7 @@
¥{{ orderContet.shippingMoney }}
-
-
- 积分 :
-
- - ¥{{ orderContet.jfDeduction }}
-
+
+
+ 积分抵扣:
+
+ -
+ {{ orderContet.jfDeduction }}
+
+
+ 天医币抵扣:
+
+ -
+ ¥{{ orderContet.realMoney }}
+
- 实付款 :
+ 实付款:
- ¥{{ orderContet.realMoney }}
+ ¥ {{ orderContet.bookBuyConfigEntity.realMoney }}
+
+
+ ¥{{ orderContet.realMoney }}
+
+
+ 微信支付
+ 支付宝支付
+ 苹果支付
+
+ 天医币支付
+
+
+
+ ¥0
+
+ +
+
+
+ {{ orderContet.jfDeduction }} 积分
+
diff --git a/pages/goods/index.vue b/pages/goods/index.vue
index 73d36d0..872f631 100644
--- a/pages/goods/index.vue
+++ b/pages/goods/index.vue
@@ -13,7 +13,7 @@
-
-
+
+
¥{{ curriculumData.price }}
diff --git a/pages/goods/order.vue b/pages/goods/order.vue
index c51de70..b8614eb 100644
--- a/pages/goods/order.vue
+++ b/pages/goods/order.vue
@@ -27,14 +27,14 @@
-
+ VIP优惠
{{ v.productName }}
-
- ¥{{ v.price }}
+
+ ¥{{ v.price }}
x 1
@@ -92,13 +92,13 @@
(全部积分:{{ initData.user.jf }})
-
+
{{ v.text }}
@@ -110,12 +110,12 @@
-¥{{ jfNumberShow }}
-
+
@@ -149,7 +149,7 @@
{{ v.text }}
-
@@ -213,10 +213,19 @@
- 共{{ number }}件
- 合计:
-
- ¥{{ actualPayment }}
+
+ 合计:
+
+
+
+ ¥{{ Number(actualPayment).toFixed(2) }}
+
+
+ +
+
+
+ {{ jfNumber }} 积分
+
@@ -269,21 +278,32 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
isDefaultCurrency: {
immediate: true,
handler(newRoute) {
- if (this.isDefaultCurrency) {
- if (platform == "ios") {
- this.selectPayIndex = 0;
- } else {
- this.selectPayIndex = 0;
- }
- } else {
- if (platform == "ios") {
- this.selectPayIndex = 0;
- } else {
- this.selectPayIndex = 0;
- }
- }
- this.payType = this.payList[this.selectPayIndex].type;
- this.$forceUpdate();
+ if (this.isDefaultCurrency) {
+ if (platform == "ios") {
+ this.selectPayIndex = 0;
+ } else {
+ this.selectPayIndex = 0;
+ }
+ } else {
+ if (platform == "ios") {
+ this.selectPayIndex = 0;
+ } else {
+ this.selectPayIndex = 0;
+ }
+ }
+
+ this.payType = this.payList[this.selectPayIndex].type;
+ if (this.actualPayment == 0) {
+ var that = this;
+ this.payList.forEach((e, i) => {
+ if (e.type == 4) {
+ that.selectPayIndex = i;
+ that.payType = 4;
+ }
+ });
+ this.$forceUpdate();
+ }
+ this.$forceUpdate();
},
},
},
@@ -370,7 +390,7 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
freightNum: "book/buyOrder/calculateTransportPrice", //运费
},
customButton: [{
- width: "340rpx",
+ width: "300rpx",
text: "立即支付",
backgroundColor: "linear-gradient(90deg, #294a97 0%, #7dc1f0 80%)",
color: "#fff",
@@ -558,12 +578,21 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
this.jfNumberShow = this.jfNumber.toFixed(2);
}
- this.actualPayment = this.totalPrice - this.jfNumber + this.freightNum;
+ this.actualPayment = this.totalPrice - this.jfNumber - this.vipPrice - this.districtAmount + this.freightNum;
+ // 如果实际支付金额为0,设置支付方式为默认货币
if (this.actualPayment == 0) {
- this.isDefaultCurrency = true;
+ console.log("this.actualPayment at line 1097:", this.actualPayment);
+ this.isDefaultCurrency = true;
+ this.payList.forEach((e, i) => {
+ if (e.type == 4) {
+ this.selectPayIndex = i;
+ this.payType = 4;
+ }
+ });
+ this.$forceUpdate();
} else {
- this.isDefaultCurrency = false;
+ this.isDefaultCurrency = false;
}
this.$forceUpdate();
});
@@ -597,17 +626,17 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
},
];
//如果是活动
- // if(this.goodsDataList[0].activityPrice&&this.goodsDataList[0].activityPrice>0&&!this.goodsDataList[0].vipPrice>0){
- // this.priceBreakdownList.push({
- // type: 5,
- // })
- // }
- // //如果是vip
- // if(this.goodsDataList[0].isVipPrice==1&&this.goodsDataList[0].vipPrice!=null&&this.goodsDataList[0].vipPrice!=0){
- // this.priceBreakdownList.push({
- // type: 6,
- // })
- // }
+ if(this.goodsDataList[0].activityPrice&&this.goodsDataList[0].activityPrice>0&&!this.goodsDataList[0].vipPrice>0){
+ this.priceBreakdownList.push({
+ type: 5,
+ })
+ }
+ //如果是vip
+ if(this.goodsDataList[0].isVipPrice==1&&this.goodsDataList[0].vipPrice!=null&&this.goodsDataList[0].vipPrice!=0){
+ this.priceBreakdownList.push({
+ type: 6,
+ })
+ }
var data = {
uid: this.userInfo.id,
@@ -753,8 +782,8 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
if (!this.isShowAddress) {
if (this.initData.user.jf >= that.totalPrice) {
- this.jfNumber = that.totalPrice;
- this.jfNumberMax = that.totalPrice;
+ this.jfNumber = that.totalPrice - that.vipPrice - that.districtAmount;
+ this.jfNumberMax = that.totalPrice - that.vipPrice - that.districtAmount;
} else {
this.jfNumber = this.initData.user.jf;
this.jfNumberMax = this.initData.user.jf;
@@ -766,23 +795,13 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
that.jfNumberShow = that.jfNumber.toFixed(2);
that.actualPayment = that.totalPrice - that.jfNumber;
}
- that.actualPayment = that.actualPayment + that.freightNum;
+ that.actualPayment = that.actualPayment + that.freightNum - that.vipPrice- that.districtAmount;
} else {
- that.actualPayment = that.totalPrice + that.freightNum;
+ that.actualPayment = that.totalPrice + that.freightNum - that.vipPrice - that.districtAmount;
}
if (this.actualPayment == 0 && !this.isShowAddress) {
- this.isDefaultCurrency = true;
- this.payList = [
- {
- text: "天医币",
- imgUrl: require("@/static/icon/pay_3.png"),
- type: 4,
- value: "2",
- },
- ];
- this.selectPayIndex = 0;
- this.payType = 4;
+ this.isDefaultCurrency = true;
} else {
this.isDefaultCurrency = false;
}
@@ -1212,9 +1231,8 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
.price {
width: auto;
- font-size: 30rpx;
+ font-size: 28rpx;
font-weight: 600;
- float: right;
margin-right: 10rpx;
color: #333;
}
@@ -1378,7 +1396,6 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
.number {
font-size: 26rpx;
margin-right: 15rpx;
- margin-top: 5rpx;
}
.price {
@@ -1395,7 +1412,6 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
width: calc(100% - 220rpx);
height: auto;
position: relative;
- // overflow: hidden;
}
}
@@ -1409,6 +1425,7 @@ import parse from "../../uni_modules/uview-ui/libs/config/props/parse";
.order_bottom_box {
display: flex;
align-items: center;
+ justify-content: center;
}
.pay_box {
diff --git a/pages/home/index.vue b/pages/home/index.vue
index 18a7414..89c2579 100644
--- a/pages/home/index.vue
+++ b/pages/home/index.vue
@@ -37,13 +37,22 @@
-
+
+
+
+
+
+ 心身健康科学
+ {{ item.title }}
+
+
+
+
- 心身健康科学
- {{ item.title }}
+ {{ item.title }}
@@ -66,7 +75,7 @@
-
+ VIP优惠
{{ v.productName }}
diff --git a/pages/my/index.vue b/pages/my/index.vue
index 8b6983d..1dd734a 100644
--- a/pages/my/index.vue
+++ b/pages/my/index.vue
@@ -23,7 +23,7 @@
{{ userMes.nickname ? userMes.nickname : "未设置" }}
-
+ 手机号:({{ userMes.tel }})
{{item}}
diff --git a/pages/order/index.vue b/pages/order/index.vue
index 8ffb069..3befc09 100644
--- a/pages/order/index.vue
+++ b/pages/order/index.vue
@@ -115,7 +115,8 @@
font-weight: 700;
">
¥
- {{item2.product.price ? item2.product.price : ""}}
+ {{item2.product.price}}
+
@@ -138,67 +139,64 @@
-
-
- 实付款
-
- ¥
- {{ slotProps.row.realMoney || slotProps.row.realMoney == 0 ? slotProps.row.realMoney: "" }}
-
-
-
-
- (
- 积分抵扣
-
- ¥
- {{ slotProps.row.jfDeduction }}
-
- )
-
+
+
+ 实付款
+
+
+ {{ slotProps.row.bookBuyConfigEntity.realMoney }}
+
+
+
+ ¥{{ slotProps.row.realMoney }}
+
+
+ ¥0
+
+
+
+ +
+
+
+
+ {{ slotProps.row.jfDeduction }} 积分
+
+
+
diff --git a/pages/visitor/detail.vue b/pages/visitor/detail.vue
index 52c5caf..9567e94 100644
--- a/pages/visitor/detail.vue
+++ b/pages/visitor/detail.vue
@@ -42,7 +42,7 @@
-
@@ -56,8 +56,7 @@
-
+
-
+
@@ -258,7 +258,7 @@ export default {
align-items: center;
.cate_item_box {
- width: 20%;
+ width: 25%;
padding: 40rpx 0 30rpx;
text-align: center;
diff --git a/pages/visitor/list.vue b/pages/visitor/list.vue
index f9fa0d0..b84b2c8 100644
--- a/pages/visitor/list.vue
+++ b/pages/visitor/list.vue
@@ -12,7 +12,7 @@
{{item.title}}
- 了解课程
+ 了解课程
@@ -20,7 +20,7 @@
-
+
自恋型人格障碍诊断标准
@@ -44,13 +44,13 @@ export default {
},
onLoad(options) {
- this.title = options.title;
this.id = options.id;
- //如果是心理评测
- if(this.id==75){
- this.statusXLCP = true;
+ this.getData();
+ //针对身心医学的判断
+ if(options.title=='心身医学'){
+ this.title = '心身健康科学'
}else{
- this.getData();
+ this.title = options.title;
}
},
methods: {
@@ -74,20 +74,6 @@ export default {
this.statusNull = true;
}
});
- },
- toLogin(){
- uni.showModal({
- title: '提示',
- content: '为了方便您后期用不同的设备查阅订购的记录,请先完成登录或注册。',
- confirmText: '确认',
- success(res){
- if (res.confirm) {
- uni.navigateTo({
- url: '/pages/user/login'
- })
- }
- }
- })
}
}
};
diff --git a/pages/visitor/mine.vue b/pages/visitor/mine.vue
index 9ba2338..cdc4785 100644
--- a/pages/visitor/mine.vue
+++ b/pages/visitor/mine.vue
@@ -1,10 +1,6 @@
-
-
-
-
+
diff --git a/pages/wallet/recharge.vue b/pages/wallet/recharge.vue
index a9c15de..fc5ea14 100644
--- a/pages/wallet/recharge.vue
+++ b/pages/wallet/recharge.vue
@@ -313,7 +313,7 @@ export default {
quantity: 1,
manualFinishTransaction: true, // 3.5.1+ 支持,设置此参数后需要开发者主动关闭订单,参见下面的关闭订单方法 finishTransaction()
}
- this.transaction = await this.requestPayment(orderInfo)
+ that.transaction = await that.requestPayment(orderInfo)
},
iapCheck(result) {
let that = this;
@@ -323,8 +323,8 @@ export default {
productId: result.payment.productid.slice(1), // 产品id
orderId: result.payment.username, // 系统订单号
receiptData: result.transactionReceipt, // 苹果返回收据
- //sandBox: true, //测试数据
- //body: that.stepsCj.priceTypeId // 充值类型id
+ // sandBox: true, //测试数据
+ // body: that.stepsCj.priceTypeId // 充值类型id
};
$http
.request({
@@ -337,7 +337,7 @@ export default {
})
.then((res) => {
if (res.code == 0) {
- this.transaction = null
+ that.transaction = null
uni.hideLoading()
uni.showToast({
title: '充值成功!',
diff --git a/uni_modules/cx-audio-play111.rar b/uni_modules/cx-audio-play111.rar
new file mode 100644
index 0000000..2a8d911
Binary files /dev/null and b/uni_modules/cx-audio-play111.rar differ
diff --git a/uni_modules/multiple-choice/changelog.md b/uni_modules/multiple-choice/changelog.md
new file mode 100644
index 0000000..96b273b
--- /dev/null
+++ b/uni_modules/multiple-choice/changelog.md
@@ -0,0 +1,2 @@
+## 1.0.0(2021-05-12)
+1. 支持uni_modules
diff --git a/uni_modules/multiple-choice/components/multiple-choice/multiple-choice.vue b/uni_modules/multiple-choice/components/multiple-choice/multiple-choice.vue
new file mode 100644
index 0000000..83c16dc
--- /dev/null
+++ b/uni_modules/multiple-choice/components/multiple-choice/multiple-choice.vue
@@ -0,0 +1,185 @@
+
+
+
+
+
+ 取消
+ {{title}}
+ 确定
+
+
+
+
+
+
+ {{item[rangeKey]}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/multiple-choice/package.json b/uni_modules/multiple-choice/package.json
new file mode 100644
index 0000000..148ee2c
--- /dev/null
+++ b/uni_modules/multiple-choice/package.json
@@ -0,0 +1,77 @@
+{
+ "id": "multiple-choice",
+ "displayName": "多选组件",
+ "version": "1.0.0",
+ "description": "多选组件",
+ "keywords": [
+ "多选",
+ "多选组件"
+],
+ "repository": "https://github.com/zhouwei1994/uni-app-demo",
+ "engines": {
+ "HBuilderX": "^3.0.0"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": "465081029"
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/multiple-choice/readme.md b/uni_modules/multiple-choice/readme.md
new file mode 100644
index 0000000..1df18a2
--- /dev/null
+++ b/uni_modules/multiple-choice/readme.md
@@ -0,0 +1,29 @@
+# 多选组件
+
+多选组件
+
+| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群")` |
+| ----------------------------|--------------------------- |
+|||
+| QQ群号:607391225 |微信号:zhou0612wei|
+
+### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
+
+### 案例一
+```
+
+```
+### 案例二
+```
+
+
+
+```
+
+### 属性
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
+| value | Boolean | false | 控制弹窗是否打开 |
+| title | String | | 弹窗标题|
+| range | Array | [] | 可选内容 |
+| rangeKey | String | name | 显示内容的key|
\ No newline at end of file
diff --git a/uni_modules/qf-image-cropper/changelog.md b/uni_modules/qf-image-cropper/changelog.md
new file mode 100644
index 0000000..0fa6898
--- /dev/null
+++ b/uni_modules/qf-image-cropper/changelog.md
@@ -0,0 +1,72 @@
+## 2.2.5(2024-07-30)
+* 修复 当 checkRange=true 时,拖动四个伸缩角放大图片时还可能会超出或未到边界的问题
+* 修复 当 checkRange=false 时,图片旋转时会放大图片适应裁剪尺寸的问题
+* 修复 当 checkRange=true 时,图片旋转 90° 或 270° 进行缩放可能会无法拖动图片的问题
+## 2.2.4(2024-06-21)
+* 新增 reverseRotatable 属性,是否支持逆向翻转
+* 修复 `2.1.7` 版本导致旋转后图片没有自动适配裁剪框的问题
+
+## 2.2.3(2024-06-21)
+* 新增 gpu 属性,是否开启硬件加速,图片缩放过程中如果出现元素的“留影”或“重影”效果,可通过该方式解决或减轻这一问题
+* 修复 组件使用 `v-if` 并设置 `src` 属性时可能会出现图片渲染位置存在偏差的问题
+
+## 2.2.2(2024-06-21)
+* 优化 组件实例 chooseImage 方法支持传参
+* 修复 组件使用 `v-if` 时组件无非正常渲染的问题
+
+## 2.2.1(2024-06-15)
+* 修复 H5平台不支持手势拖动图片的问题
+
+## 2.2.0(2024-05-31)
+* 修复 APP平台 `vue2` 项目因 `2.1.9` 版本修复 `vue3` 项目bug而引发的问题
+
+## 2.1.9(2024-05-29)
+* 修复 APP平台 `vue3` 项目因 uniapp `renderjs` 中未支持条件编译,导致运行了H5平台代码报错的问题
+
+## 2.1.8(2024-05-29)
+* 新增 zIndex 属性,调整组件层级
+* 新增 组件内容插槽
+* 优化 微信小程序平台动态修改元素style时的多余内容
+
+## 2.1.7(2024-05-28)
+* 新增 checkRange 属性,当 checkRange=false 时允许图片位置超出裁剪边界
+* 新增 minScale 属性,图片最小缩放倍数,当 minScale<0 时可使图片宽高不再受裁剪区域宽高限制
+* 新增 backgroundColor 属性,生成图片背景色,如果裁剪区域没有完全包含在图片中时,不设置该属性生成图片存在一定的透明块
+* 优化 动态修改图片宽高但没有传入src时,尺寸适应问题
+* 修复 APP平台通过 `this.$ownerInstance` 获取组件实例时机过早,其值为 `undefined` 导致报错界面没有正常渲染的问题
+
+## 2.1.6(2023-04-16)
+* 修复 组件使用 v-show 指令会导致选择图片后初始位置严重偏位的问题
+
+## 2.1.5(2023-04-15)
+* 新增 兼容APP平台
+
+## 2.1.4(2023-03-13)
+* 新增 fileType 属性,用于指定生成文件的类型,只支持 'jpg' 或 'png',默认为 'png'
+* 新增 delay 属性,微信小程序平台使用 `Canvas 2D` 绘制时控制图片从绘制到生成所需时间
+* 优化 当生成图片的尺寸宽/高超过 Canvas 2D 最大限制(1365*1365)则将画布尺寸缩放在限制范围内绘制完成后输出目标尺寸
+* 优化 旋转图标指示方向与实际旋转方向不符
+
+## 2.1.3(2023-02-06)
+* 优化 vue3支持
+
+## 2.1.2(2023-02-03)
+* 新增 navigation 属性,H5平台当 showAngle 为 true 时,使用插件的页面在 `page.json` 中配置了 "navigationStyle": "custom" 时,必须将此值设为 false ,否则四个可拉伸角的触发位置会有偏差
+* 修复 H5平台部分设备(已知iPhone11以下机型)拍照的图片缩放时会闪动的问题
+
+## 2.1.1(2022-12-06)
+* 修复 横屏适配问题
+
+## 2.1.0(2022-12-06)
+* 新增 兼容H5平台,使用 renderjs 响应手势事件
+
+## 2.0.0(2022-12-05)
+* 重构 插件,使用 WXS 响应手势事件
+* 新增 图片翻转
+* 新增 拉伸裁剪框放大图片
+* 新增 监听PC鼠标滚轮触发缩放
+* 新增 圆形、圆角矩形的图片裁剪
+* 优化 图片缩放,移动端以双指触摸中心点为缩放中心点,PC端以鼠标所在点为缩放中心点
+* 优化 裁剪框样式
+* 优化 图片位置拖动 支持边界回弹效果(滑动时可滑出边界,释放时回弹到边界)
+* 优化 生成图片使用新版 Canvas 2D 接口
diff --git a/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.render.js b/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.render.js
new file mode 100644
index 0000000..becac19
--- /dev/null
+++ b/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.render.js
@@ -0,0 +1,855 @@
+/**
+ * 图片编辑器-手势监听
+ * 1. 支持编译到app-vue(uni-app 2.5.5及以上版本)、H5上
+ */
+/** 图片偏移量 */
+var offset = { x: 0, y: 0 };
+/** 图片缩放比例 */
+var scale = 1;
+/** 图片最小缩放比例 */
+var minScale = 1;
+/** 图片旋转角度 */
+var rotate = 0;
+/** 触摸点 */
+var touches = [];
+/** 图片布局信息 */
+var img = {};
+/** 系统信息 */
+var sys = {};
+/** 裁剪区域布局信息 */
+var area = {};
+/** 触摸行为类型 */
+var touchType = '';
+/** 操作角的位置 */
+var activeAngle = 0;
+/** 裁剪区域布局信息偏移量 */
+var areaOffset = { left: 0, right: 0, top: 0, bottom: 0 };
+/** 元素ID */
+var elIds = {
+ 'imageStyles': 'crop-image',
+ 'maskStylesList': 'crop-mask-block',
+ 'borderStyles': 'crop-border',
+ 'circleBoxStyles': 'crop-circle-box',
+ 'circleStyles': 'crop-circle',
+ 'gridStylesList': 'crop-grid',
+ 'angleStylesList': 'crop-angle',
+}
+/** 记录上次初始化时间戳,排除APP重复更新 */
+var timestamp = 0;
+/** vue3 renderjs 条件编译无效,以此方式区别 APP 和 H5 */
+// #ifdef H5
+var platform = 'H5';
+// #endif
+// #ifdef APP
+var platform = 'APP';
+// #endif
+/** 容错值 */
+var fault = 0.000001;
+/**
+ * 获取a、b两数中的最小正数
+ * @param a
+ * @param b
+ */
+function minimum(a, b) {
+ if (a > 0 && b < 0) return a;
+ if (a < 0 && b > 0) return b;
+ if (a > 0 && b > 0) return Math.min(a, b);
+ return 0;
+}
+/**
+ * 在容错访问内获取n近似值
+ * @param n
+ */
+function num(n) {
+ var m = parseFloat((n).toFixed(6));
+ return m === fault || m === -fault ? 0 : m;
+}
+/**
+ * 比较a值在容错值范围内是否等于b值
+ * @param a
+ * @param b
+ */
+function equalsByFault(a, b) {
+ return Math.abs(a - b) <= fault;
+}
+/**
+ * 比较a值在容错值范围内是否小于b值
+ * @param a
+ * @param b
+ */
+function lessThanByFault(a, b) {
+ var c = a - b;
+ return c < 0 ? c < -fault : c < fault;
+}
+/**
+ * 验证并获取有效最大值
+ * @param v
+ * @param max
+ * @param isInclude
+ * @param x
+ * @param y
+ * @param rate
+ * @returns
+ */
+function validMax(v, max, isInclude, x, y, rate) {
+ if(typeof max === 'number') {
+ if(isInclude && equalsByFault(max, y)) { // 宽高不等时,x轴用y轴值要做等比例转换
+ var n = num(max * rate);
+ if (n <= x) return n; // 转化后值在x轴最大值范围内
+ return x; // 转化后值超出x轴最大值范围则用最大值
+ }
+ return max;
+ }
+ return v;
+}
+/**
+ * 样式对象转字符串
+ * @param {Object} style 样式对象
+ */
+function styleToString(style) {
+ if(typeof style === 'string') return style;
+ var str = '';
+ for (let k in style) {
+ str += k + ':' + style[k] + ';';
+ }
+ return str;
+}
+/**
+ *
+ * @param {Object} instance 页面实例对象
+ * @param {Object} key 要修改样式的key
+ * @param {Object|Array} style 样式
+ */
+function setStyle(instance, key, style) {
+ // console.log('setStyle', instance, key, JSON.stringify(style))
+ // #ifdef APP-PLUS
+ if(platform === 'APP') {
+ if(Object.prototype.toString.call(style) === '[object Array]') {
+ for (var i = 0, len = style.length; i < len; i++) {
+ var el = window.document.getElementById(elIds[key] + '-' + (i + 1));
+ el && (el.style = styleToString(style[i]));
+ }
+ } else {
+ var el = window.document.getElementById(elIds[key]);
+ el && (el.style = styleToString(style));
+ }
+ }
+ // #endif
+ // #ifdef H5
+ if(platform === 'H5') instance[key] = style;
+ // #endif
+}
+/**
+ * 触发页面实例指定方法
+ * @param {Object} instance 页面实例对象
+ * @param {Object} name 方法名称
+ * @param {Object} obj 传递参数
+ */
+function callMethod(instance, name, obj) {
+ // #ifdef APP-PLUS
+ if(platform === 'APP') instance.callMethod(name, obj);
+ // #endif
+ // #ifdef H5
+ if(platform === 'H5') instance[name](obj);
+ // #endif
+}
+/**
+ * 计算两点间距
+ * @param {Object} touches 触摸点信息
+ */
+function getDistanceByTouches(touches) {
+ // 根据勾股定理求两点间距离
+ var a = touches[1].pageX - touches[0].pageX;
+ var b = touches[1].pageY - touches[0].pageY;
+ var c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
+ // 求两点间的中点坐标
+ // 1. a、b可能为负值
+ // 2. 在求a、b时,如用touches[1]减touches[0],则求中点坐标也得用touches[1]减a/2、b/2
+ // 3. 同理,在求a、b时,也可用touches[0]减touches[1],则求中点坐标也得用touches[0]减a/2、b/2
+ var x = touches[1].pageX - a / 2;
+ var y = touches[1].pageY - b / 2;
+ return { c, x, y };
+};
+
+/**
+ * 修正取值
+ * @param {Object} a
+ * @param {Object} b
+ * @param {Object} c
+ * @param {Object} reverse 是否反向
+ */
+function correctValue(a, b, c, reverse) {
+ return num(reverse ? Math.max(Math.min(a, b), c) : Math.min(Math.max(a, b), c));
+}
+
+/**
+ * 旋转90°或270°时检查边界:限制 x、y 拖动范围,禁止滑出边界
+ * @param {Object} e 点坐标
+ * @param {Object} xReverse x是否反向
+ * @param {Object} yReverse y是否反向
+ */
+function checkRotateRange(e, xReverse, yReverse) {
+ var o = num((img.height - img.width) / 2); // 宽高差值一半
+ return {
+ x: correctValue(e.x, -img.height + o + area.width + area.left, area.left + o, xReverse),
+ y: correctValue(e.y, -img.width - o + area.height + area.top, area.top - o, yReverse)
+ };
+}
+
+/**
+ * 检查边界:限制 x、y 拖动范围,禁止滑出边界
+ * @param {Object} e 点坐标
+ */
+function checkRange(e) {
+ var r = rotate / 90 % 2;
+ if(r === 1) { // 因图片宽高可能不等,翻转 90° 或 270° 后图片宽高需反着计算,且左右和上下边界要根据差值做偏移
+ if (area.width === area.height) {
+ return checkRotateRange(e, img.height < area.height, img.width < area.width);
+ }
+ var isInclude = img.height < area.width && img.width < area.height; // 图片是否包含在裁剪区域内
+ if (img.width < area.height || img.height < area.width) {
+ if (area.width < area.height && img.width < img.height) {
+ return isInclude
+ ? checkRotateRange(e, area.width < area.height, area.width < area.height)
+ : checkRotateRange(e, false, true);
+ }
+ if (area.height < area.width && img.height < img.width) {
+ return isInclude
+ ? checkRotateRange(e, area.height < area.width, area.height < area.width)
+ : checkRotateRange(e, true, false);
+ }
+ }
+ if (img.height >= area.width && img.width >= area.height) {
+ return checkRotateRange(e, false, false);
+ }
+ if (isInclude) {
+ return area.height < area.width
+ ? checkRotateRange(e, true, true)
+ : checkRotateRange(e, area.width < area.height, area.width < area.height);
+ }
+ if (img.height < area.width && !img.width < area.height) {
+ return checkRotateRange(e, true, false);
+ }
+ if (!img.height < area.width && img.width < area.height) {
+ return checkRotateRange(e, false, true);
+ }
+ return checkRotateRange(e, img.height < area.height, img.width < area.width);
+ }
+ return {
+ x: correctValue(e.x, -img.width + area.width + area.left, area.left, img.width < area.width),
+ y: correctValue(e.y, -img.height + area.height + area.top, area.top, img.height < area.height)
+ }
+};
+/**
+ * 变更图片布局信息
+ * @param {Object} e 布局信息
+ */
+function changeImageRect(e) {
+ // console.log('changeImageRect', e)
+ offset.x += e.x || 0;
+ offset.y += e.y || 0;
+ if(e.check && area.checkRange) { // 检查边界
+ var point = checkRange(offset);
+ if(offset.x !== point.x || offset.y !== point.y) {
+ offset = point;
+ }
+ }
+
+ // 因频繁修改 width/height 会造成大量的内存消耗,改为scale
+ // e.instance.imageStyles = {
+ // width: img.width + 'px',
+ // height: img.height + 'px',
+ // transform: 'translate(' + (offset.x + ox) + 'px, ' + (offset.y + ox) + 'px) rotate(' + rotate +'deg)'
+ // };
+ var ox = (img.width - img.oldWidth) / 2;
+ var oy = (img.height - img.oldHeight) / 2;
+ // e.instance.imageStyles = {
+ // width: img.oldWidth + 'px',
+ // height: img.oldHeight + 'px',
+ // transform: 'translate(' + (offset.x + ox) + 'px, ' + (offset.y + oy) + 'px) rotate(' + rotate +'deg) scale(' + scale + ')'
+ // };
+ setStyle(e.instance, 'imageStyles', {
+ width: img.oldWidth + 'px',
+ height: img.oldHeight + 'px',
+ transform: (img.gpu ? 'translateZ(0) ' : '') + 'translate(' + (offset.x + ox) + 'px, ' + (offset.y + oy) + 'px' + ') rotate(' + rotate +'deg) scale(' + scale + ')'
+ });
+ callMethod(e.instance, 'dataChange', {
+ width: img.width,
+ height: img.height,
+ x: offset.x,
+ y: offset.y,
+ rotate: rotate
+ });
+};
+/**
+ * 变更裁剪区域布局信息
+ * @param {Object} e 布局信息
+ */
+function changeAreaRect(e) {
+ // console.log('changeAreaRect', e)
+ // 变更蒙版样式
+ setStyle(e.instance, 'maskStylesList', [
+ {
+ left: 0,
+ width: (area.left + areaOffset.left) + 'px',
+ top: 0,
+ bottom: 0,
+ 'z-index': area.zIndex + 2
+ },
+ {
+ left: (area.right + areaOffset.right) + 'px',
+ right: 0,
+ top: 0,
+ bottom: 0,
+ 'z-index': area.zIndex + 2
+ },
+ {
+ left: (area.left + areaOffset.left) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ top: 0,
+ height: (area.top + areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 2
+ },
+ {
+ left: (area.left + areaOffset.left) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ top: (area.bottom + areaOffset.bottom) + 'px',
+ // height: (area.top - areaOffset.bottom + sys.offsetBottom) + 'px',
+ bottom: 0,
+ 'z-index': area.zIndex + 2
+ }
+ ]);
+ // 变更边框样式
+ if(area.showBorder) {
+ setStyle(e.instance, 'borderStyles', {
+ left: (area.left + areaOffset.left) + 'px',
+ top: (area.top + areaOffset.top) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 3
+ });
+ }
+
+ // 变更参考线样式
+ if(area.showGrid) {
+ setStyle(e.instance, 'gridStylesList', [
+ {
+ 'border-width': '1px 0 0 0',
+ left: (area.left + areaOffset.left) + 'px',
+ right: (area.right + areaOffset.right) + 'px',
+ top: (area.top + areaOffset.top + (area.height + areaOffset.bottom - areaOffset.top) / 3 - 0.5) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '1px 0 0 0',
+ left: (area.left + areaOffset.left) + 'px',
+ right: (area.right + areaOffset.right) + 'px',
+ top: (area.top + areaOffset.top + (area.height + areaOffset.bottom - areaOffset.top) * 2 / 3 - 0.5) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '0 1px 0 0',
+ top: (area.top + areaOffset.top) + 'px',
+ bottom: (area.bottom + areaOffset.bottom) + 'px',
+ left: (area.left + areaOffset.left + (area.width + areaOffset.right - areaOffset.left) / 3 - 0.5) + 'px',
+ height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '0 1px 0 0',
+ top: (area.top + areaOffset.top) + 'px',
+ bottom: (area.bottom + areaOffset.bottom) + 'px',
+ left: (area.left + areaOffset.left + (area.width + areaOffset.right - areaOffset.left) * 2 / 3 - 0.5) + 'px',
+ height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 3
+ }
+ ]);
+ }
+
+ // 变更四个伸缩角样式
+ if(area.showAngle) {
+ setStyle(e.instance, 'angleStylesList', [
+ {
+ 'border-width': area.angleBorderWidth + 'px 0 0 ' + area.angleBorderWidth + 'px',
+ left: (area.left + areaOffset.left - area.angleBorderWidth) + 'px',
+ top: (area.top + areaOffset.top - area.angleBorderWidth) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px 0 0',
+ left: (area.right + areaOffset.right - area.angleSize) + 'px',
+ top: (area.top + areaOffset.top - area.angleBorderWidth) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '0 0 ' + area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px',
+ left: (area.left + areaOffset.left - area.angleBorderWidth) + 'px',
+ top: (area.bottom + areaOffset.bottom - area.angleSize) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '0 ' + area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px 0',
+ left: (area.right + areaOffset.right - area.angleSize) + 'px',
+ top: (area.bottom + areaOffset.bottom - area.angleSize) + 'px',
+ 'z-index': area.zIndex + 3
+ }
+ ]);
+ }
+
+ // 变更圆角样式
+ if(area.radius > 0) {
+ var radius = area.radius;
+ if(area.width === area.height && area.radius >= area.width / 2) { // 圆形
+ radius = (area.width / 2);
+ } else { // 圆角矩形
+ if(area.width !== area.height) { // 限制圆角半径不能超过短边的一半
+ radius = Math.min(area.width / 2, area.height / 2, radius);
+ }
+ }
+ setStyle(e.instance, 'circleBoxStyles', {
+ left: (area.left + areaOffset.left) + 'px',
+ top: (area.top + areaOffset.top) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 2
+ });
+ setStyle(e.instance, 'circleStyles', {
+ 'box-shadow': '0 0 0 ' + Math.max(area.width, area.height) + 'px rgba(51, 51, 51, 0.8)',
+ 'border-radius': radius + 'px'
+ });
+ }
+};
+/**
+ * 缩放图片
+ * @param {Object} e 布局信息
+ */
+function scaleImage(e) {
+ // console.log('scaleImage', e)
+ var last = scale;
+ scale = Math.min(Math.max(e.scale + scale, minScale), img.maxScale);
+ if(last !== scale) {
+ img.width = num(img.oldWidth * scale);
+ img.height = num(img.oldHeight * scale);
+ // 参考问题:有一个长4000px、宽4000px的四方形ABCD,A点的坐标固定在(-2000,-2000),
+ // 该四边形上有一个点E,坐标为(-100,-300),将该四方形复制一份并缩小到90%后,
+ // 新四边形的A点坐标为多少时可使新四边形的E点与原四边形的E点重合?
+ // 预期效果:从图中选取某点(参照物)为中心点进行缩放,缩放时无论图像怎么变化,该点位置始终固定不变
+ // 计算方法:以相同起点先计算缩放前后两点间的距离,再加上原图像偏移量即可
+ e.x = num((e.x - offset.x) * (1 - scale / last));
+ e.y = num((e.y - offset.y) * (1 - scale / last));
+ changeImageRect(e);
+ return true;
+ }
+ return false;
+};
+/**
+ * 获取触摸点在哪个角
+ * @param {number} x 触摸点x轴坐标
+ * @param {number} y 触摸点y轴坐标
+ * @return {number} 角的位置:0=无;1=左上;2=右上;3=左下;4=右下;
+ */
+function getToucheAngle(x, y) {
+ // console.log('getToucheAngle', x, y, JSON.stringify(area))
+ var o = area.angleBorderWidth; // 需扩大触发范围则把 o 值加大即可
+ var oy = sys.navigation ? 0 : sys.windowTop;
+ if(y >= area.top - o + oy && y <= area.top + area.angleSize + o + oy) {
+ if(x >= area.left - o && x <= area.left + area.angleSize + o) {
+ return 1; // 左上角
+ } else if(x >= area.right - area.angleSize - o && x <= area.right + o) {
+ return 2; // 右上角
+ }
+ } else if(y >= area.bottom - area.angleSize - o + oy && y <= area.bottom + o + oy) {
+ if(x >= area.left - o && x <= area.left + area.angleSize + o) {
+ return 3; // 左下角
+ } else if(x >= area.right - area.angleSize - o && x <= area.right + o) {
+ return 4; // 右下角
+ }
+ }
+ return 0; // 无触摸到角
+};
+/**
+ * 重置数据
+ */
+function resetData() {
+ offset = { x: 0, y: 0 };
+ scale = 1;
+ minScale = img.minScale;
+ rotate = 0;
+};
+function getTouchs(touches) {
+ var result = [];
+ var len = touches ? touches.length : 0
+ for (var i = 0; i < len; i++) {
+ result[i] = {
+ pageX: touches[i].pageX,
+ // h5无标题栏时,窗口顶部距离仍为标题栏高度,且触摸点y轴坐标还是有标题栏的值,即减去标题栏高度的值
+ pageY: touches[i].pageY + sys.windowTop
+ };
+ }
+ return result;
+};
+var mouseEvent = false;
+export default {
+ data() {
+ return {
+ imageStyles: {},
+ maskStylesList: [{}, {}, {}, {}],
+ borderStyles: {},
+ gridStylesList: [{}, {}, {}, {}],
+ angleStylesList: [{}, {}, {}, {}],
+ circleBoxStyles: {},
+ circleStyles: {}
+ }
+ },
+ created() {
+ // 监听 PC 端鼠标滚轮
+ // #ifdef H5
+ platform === 'H5' && window.addEventListener('mousewheel', async (e) => {
+ var touchs = getTouchs([e])
+ img.src && scaleImage({
+ instance: await this.getInstance(),
+ check: true,
+ // 鼠标向上滚动时,deltaY 固定 -100,鼠标向下滚动时,deltaY 固定 100
+ scale: e.deltaY > 0 ? -0.05 : 0.05,
+ x: touchs[0].pageX,
+ y: touchs[0].pageY
+ });
+ });
+ // #endif
+ },
+ // #ifdef H5
+ mounted() {
+ platform === 'H5' && this.initH5Events();
+ },
+ // #endif
+ setPlatform(p) {
+ platform = p;
+ },
+ methods: {
+ // #ifdef H5
+ getTouchEvent(e) {
+ e.touches = [
+ { pageX: e.pageX, pageY: e.pageY }
+ ];
+ return e;
+ },
+ initH5Events() {
+ const preview = document.getElementById('pic-preview');
+ preview?.addEventListener('mousedown', (e, ev) => {
+ mouseEvent = true;
+ this.touchstart(this.getTouchEvent(e));
+ });
+ preview?.addEventListener('mousemove', (e) => {
+ if (!mouseEvent) return;
+ this.touchmove(this.getTouchEvent(e));
+ });
+ preview?.addEventListener('mouseup', (e) => {
+ mouseEvent = false;
+ this.touchend(this.getTouchEvent(e))
+ });
+ preview?.addEventListener('mouseleave', (e) => {
+ mouseEvent = false;
+ this.touchend(this.getTouchEvent(e))
+ });
+ },
+ // #endif
+ async getInstance() {
+ // #ifdef APP-PLUS
+ if(platform === 'APP')
+ return this.$ownerInstance
+ ? Promise.resolve(this.$ownerInstance)
+ : new Promise((resolve) => {
+ setTimeout(async () => {
+ resolve(await this.getInstance());
+ });
+ });
+ // #endif
+ // #ifdef H5
+ if(platform === 'H5')
+ return Promise.resolve(this);
+ // #endif
+ },
+ /**
+ * 初始化:观察数据变更
+ * @param {Object} newVal 新数据
+ * @param {Object} oldVal 旧数据
+ * @param {Object} o 组件实例对象
+ */
+ initObserver: async function(newVal, oldVal, o, i) {
+ // console.log('initObserver', newVal, oldVal, o, i)
+ if(newVal && (!img.src || timestamp !== newVal.timestamp)) {
+ timestamp = newVal.timestamp;
+ img = newVal.img;
+ sys = newVal.sys;
+ area = newVal.area;
+ minScale = img.minScale;
+ resetData();
+ const instance = await this.getInstance()
+ img.src && changeImageRect({
+ instance,
+ x: (sys.windowWidth - img.width) / 2,
+ y: (sys.windowHeight + sys.windowTop - sys.offsetBottom - img.height) / 2
+ });
+ changeAreaRect({
+ instance
+ });
+ }
+ },
+ /**
+ * 鼠标滚轮滚动
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ mousewheel: function(e, o) {
+ // h5平台 wheel 事件无法判断滚轮滑动方向,需使用 mousewheel
+ },
+ /**
+ * 触摸开始
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ touchstart: function(e, o) {
+ if(!img.src) return;
+ touches = getTouchs(e.touches);
+ activeAngle = area.showAngle ? getToucheAngle(touches[0].pageX, touches[0].pageY) : 0;
+ if(touches.length === 1 && activeAngle !== 0) {
+ touchType = 'stretch'; // 伸缩裁剪区域
+ } else {
+ touchType = '';
+ }
+ // console.log('touchstart', e, activeAngle)
+ },
+ /**
+ * 触摸移动
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ touchmove: async function(e, o) {
+ if(!img.src) return;
+ // console.log('touchmove', e, o)
+ e.touches = getTouchs(e.touches);
+ if(touchType === 'stretch') { // 触摸四个角进行拉伸
+ var point = e.touches[0];
+ var start = touches[0];
+ var x = point.pageX - start.pageX;
+ var y = point.pageY - start.pageY;
+ if(x !== 0 || y !== 0) {
+ var maxX = num(area.width * (1 - area.minScale));
+ var maxY = num(area.height * (1 - area.minScale));
+ // console.log(x, y, maxX, maxY, offset, area)
+ touches[0] = point;
+ var r = rotate / 90 % 2;
+ var m = r === 1 ? num((img.height - img.width) / 2) : 0; // 宽高差值一半
+ var xCompare = r === 1 ? lessThanByFault(img.height, area.width) : lessThanByFault(img.width, area.width);
+ var yCompare = r === 1 ? lessThanByFault(img.width, area.height) : lessThanByFault(img.height, area.height)
+ var isInclude = xCompare && yCompare;
+ var isIntersect = area.checkRange && (xCompare || yCompare); // 图片是否包含在裁剪区域内
+ var isReverse = !isInclude || num((offset.x - area.left) / area.width) <= num((offset.y - area.top) / area.height) || (area.width > area.height && img.width < img.height && r === 1);
+ switch(activeAngle) {
+ case 1: // 左上角
+ x = num(x + areaOffset.left);
+ y = num(y + areaOffset.top);
+ if(x >= 0 && y >= 0) { // 有效滑动
+ var t = num(offset.y + m - area.top);
+ var l = num(offset.x - m - area.left);
+ // && (offset.x + img.width < area.right || offset.y + img.height < area.bottom)
+ var max = isIntersect && ((l >= 0) || (t >= 0))
+ ? minimum(t, l)
+ : false;
+ if(x > y && isReverse) { // 以x轴滑动距离为缩放基准
+ maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
+ if(x > maxX) x = maxX;
+ y = num(x * area.height / area.width);
+ } else { // 以y轴滑动距离为缩放基准
+ maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
+ if(y > maxY) y = maxY;
+ x = num(y * area.width / area.height);
+ }
+ areaOffset.left = x;
+ areaOffset.top = y;
+ }
+ break;
+ case 2: // 右上角
+ x = num(x + areaOffset.right);
+ y = num(y + areaOffset.top);
+ if(x <= 0 && y >= 0) { // 有效滑动
+ var w = (r === 1 ? img.height : img.width);
+ var t = num(offset.y + m - area.top);
+ var l = num(area.right + m - offset.x - w);
+ var max = isIntersect && ((t >= 0) || (l >= 0))
+ ? minimum(t, l)
+ : false;
+ if(-x > y && isReverse) { // 以x轴滑动距离为缩放基准
+ maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
+ if(-x > maxX) x = -maxX;
+ y = num(-x * area.height / area.width);
+ } else { // 以y轴滑动距离为缩放基准
+ maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
+ if(y > maxY) y = maxY;
+ x = num(-y * area.width / area.height);
+ }
+ areaOffset.right = x;
+ areaOffset.top = y;
+ }
+ break;
+ case 3: // 左下角
+ x += num(x + areaOffset.left);
+ y += num(y + areaOffset.bottom);
+ if(x >= 0 && y <= 0) { // 有效滑动
+ var w = (r === 1 ? img.width : img.height);
+ var t = num(area.bottom - m - offset.y - w);
+ var l = num(offset.x - m - area.left);
+ var max = isIntersect && ((l >= 0) || (t >= 0))
+ ? minimum(t, l)
+ : false;
+ if(x > -y && isReverse) { // 以x轴滑动距离为缩放基准
+ maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
+ if(x > maxX) x = maxX;
+ y = num(-x * area.height / area.width);
+ } else { // 以y轴滑动距离为缩放基准
+ maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
+ if(-y > maxY) y = -maxY;
+ x = num(-y * area.width / area.height);
+ }
+ areaOffset.left = x;
+ areaOffset.bottom = y;
+ }
+ break;
+ case 4: // 右下角
+ x = num(x + areaOffset.right);
+ y = num(y + areaOffset.bottom);
+ if(x <= 0 && y <= 0) { // 有效滑动
+ var w = (r === 1 ? img.height : img.width);
+ var h = (r === 1 ? img.width : img.height);
+ var t = num(area.bottom - offset.y - h - m);
+ var l = num(area.right + m - offset.x - w);
+ var max = isIntersect && ((l >= 0) || (t >= 0))
+ ? minimum(t, l)
+ : false;
+ if(-x > -y && isReverse) { // 以x轴滑动距离为缩放基准
+ maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
+ if(-x > maxX) x = -maxX;
+ y = num(x * area.height / area.width);
+ } else { // 以y轴滑动距离为缩放基准
+ maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
+ if(-y > maxY) y = -maxY;
+ x = num(y * area.width / area.height);
+ }
+ areaOffset.right = x;
+ areaOffset.bottom = y;
+ }
+ break;
+ }
+ // console.log(x, y, JSON.stringify(areaOffset))
+ changeAreaRect({
+ instance: await this.getInstance(),
+ });
+ // this.draw();
+ }
+ } else if (e.touches.length == 2) { // 双点触摸缩放
+ var start = getDistanceByTouches(touches);
+ var end = getDistanceByTouches(e.touches);
+ scaleImage({
+ instance: await this.getInstance(),
+ check: !area.bounce,
+ scale: (end.c - start.c) / 100,
+ x: end.x,
+ y: end.y
+ });
+ touchType = 'scale';
+ } else if(touchType === 'scale') {// 从双点触摸变成单点触摸 / 从缩放变成拖动
+ touchType = 'move';
+ } else {
+ changeImageRect({
+ instance: await this.getInstance(),
+ check: !area.bounce,
+ x: e.touches[0].pageX - touches[0].pageX,
+ y: e.touches[0].pageY - touches[0].pageY
+ });
+ touchType = 'move';
+ }
+ touches = e.touches;
+ },
+ /**
+ * 触摸结束
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ touchend: async function(e, o) {
+ if(!img.src) return;
+ if(touchType === 'stretch') { // 拉伸裁剪区域的四个角缩放
+ // 裁剪区域宽度被缩放到多少
+ var left = areaOffset.left;
+ var right = areaOffset.right;
+ var top = areaOffset.top;
+ var bottom = areaOffset.bottom;
+ var w = area.width + right - left;
+ var h = area.height + bottom - top;
+ // 图像放大倍数
+ var p = scale * (area.width / w) - scale;
+ // 复原裁剪区域
+ areaOffset = { left: 0, right: 0, top: 0, bottom: 0 };
+ changeAreaRect({
+ instance: await this.getInstance(),
+ });
+ scaleImage({
+ instance: await this.getInstance(),
+ scale: p,
+ x: area.left + left + (1 === activeAngle || 3 === activeAngle ? w : 0),
+ y: area.top + top + (1 === activeAngle || 2 === activeAngle ? h : 0)
+ });
+ } else if (area.bounce) { // 检查边界并矫正,实现拖动到边界时有回弹效果
+ changeImageRect({
+ instance: await this.getInstance(),
+ check: true
+ });
+ }
+ },
+ /**
+ * 顺时针翻转图片90°
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ rotateImage: async function(r) {
+ rotate = (rotate + (r || 90)) % 360;
+
+ if(img.minScale >= 1 && area.checkRange) {
+ // 因图片宽高可能不等,翻转后图片宽高需足够填满裁剪区域
+ minScale = 1;
+ if(img.width < area.height) {
+ minScale = area.height / img.oldWidth;
+ } else if(img.height < area.width) {
+ minScale = area.width / img.oldHeight;
+ }
+ if(minScale !== 1) {
+ scaleImage({
+ instance: await this.getInstance(),
+ scale: minScale - scale,
+ x: sys.windowWidth / 2,
+ y: (sys.windowHeight - sys.offsetBottom) / 2
+ });
+ }
+ }
+
+ // 由于拖动画布后会导致图片位置偏移,翻转时的旋转中心点需是图片区域+偏移区域的中心点
+ // 翻转x轴中心点 = (超出裁剪区域右侧的图片宽度 - 超出裁剪区域左侧的图片宽度) / 2
+ // 翻转y轴中心点 = (超出裁剪区域下方的图片宽度 - 超出裁剪区域上方的图片宽度) / 2
+ var ox = ((offset.x + img.width - area.right) - (area.left - offset.x)) / 2;
+ var oy = ((offset.y + img.height - area.bottom) - (area.top - offset.y)) / 2;
+ changeImageRect({
+ instance: await this.getInstance(),
+ check: true,
+ x: -ox - oy,
+ y: -oy + ox
+ });
+ },
+ rotateImage90: function() {
+ this.rotateImage(90)
+ },
+ rotateImage270: function() {
+ this.rotateImage(270)
+ },
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.vue b/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.vue
new file mode 100644
index 0000000..fc85bda
--- /dev/null
+++ b/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.vue
@@ -0,0 +1,746 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 确定
+
+ 重选
+
+
+ 选择图片
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.wxs b/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.wxs
new file mode 100644
index 0000000..98a5116
--- /dev/null
+++ b/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.wxs
@@ -0,0 +1,727 @@
+/**
+ * 图片编辑器-手势监听
+ * 1. wxs 暂不支持 es6 语法
+ * 2. 支持编译到微信小程序、QQ小程序、app-vue、H5上(uni-app 2.2.5及以上版本)
+ */
+/** 图片偏移量 */
+var offset = { x: 0, y: 0 };
+/** 图片缩放比例 */
+var scale = 1;
+/** 图片最小缩放比例 */
+var minScale = 1;
+/** 图片旋转角度 */
+var rotate = 0;
+/** 触摸点 */
+var touches = [];
+/** 图片布局信息 */
+var img = {};
+/** 系统信息 */
+var sys = {};
+/** 裁剪区域布局信息 */
+var area = {};
+/** 触摸行为类型 */
+var touchType = '';
+/** 操作角的位置 */
+var activeAngle = 0;
+/** 裁剪区域布局信息偏移量 */
+var areaOffset = { left: 0, right: 0, top: 0, bottom: 0 };
+/** 容错值 */
+var fault = 0.000001;
+/**
+ * 获取a、b两数中的最小正数
+ * @param a
+ * @param b
+ */
+function minimum(a, b) {
+ if (a > 0 && b < 0) return a;
+ if (a < 0 && b > 0) return b;
+ if (a > 0 && b > 0) return Math.min(a, b);
+ return 0;
+}
+/**
+ * 在容错访问内获取n近似值
+ * @param n
+ */
+function num(n) {
+ var m = parseFloat((n).toFixed(6));
+ return m === fault || m === -fault ? 0 : m;
+}
+/**
+ * 比较a值在容错值范围内是否等于b值
+ * @param a
+ * @param b
+ */
+function equalsByFault(a, b) {
+ return Math.abs(a - b) <= fault;
+}
+/**
+ * 比较a值在容错值范围内是否小于b值
+ * @param a
+ * @param b
+ */
+function lessThanByFault(a, b) {
+ var c = a - b;
+ return c < 0 ? c < -fault : c < fault;
+}
+/**
+ * 验证并获取有效最大值
+ * @param v
+ * @param max
+ * @param isInclude
+ * @param x
+ * @param y
+ * @param rate
+ * @returns
+ */
+function validMax(v, max, isInclude, x, y, rate) {
+ if(typeof max === 'number') {
+ if(isInclude && equalsByFault(max, y)) { // 宽高不等时,x轴用y轴值要做等比例转换
+ var n = num(max * rate);
+ if (n <= x) return n; // 转化后值在x轴最大值范围内
+ return x; // 转化后值超出x轴最大值范围则用最大值
+ }
+ return max;
+ }
+ return v;
+}
+/**
+ * 计算两点间距
+ * @param {Object} touches 触摸点信息
+ */
+function getDistanceByTouches(touches) {
+ // 根据勾股定理求两点间距离
+ var a = touches[1].pageX - touches[0].pageX;
+ var b = touches[1].pageY - touches[0].pageY;
+ var c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
+ // 求两点间的中点坐标
+ // 1. a、b可能为负值
+ // 2. 在求a、b时,如用touches[1]减touches[0],则求中点坐标也得用touches[1]减a/2、b/2
+ // 3. 同理,在求a、b时,也可用touches[0]减touches[1],则求中点坐标也得用touches[0]减a/2、b/2
+ var x = touches[1].pageX - a / 2;
+ var y = touches[1].pageY - b / 2;
+ return { c, x, y };
+};
+/**
+ * 修正取值
+ * @param {Object} a
+ * @param {Object} b
+ * @param {Object} c
+ * @param {Object} reverse 是否反向
+ */
+function correctValue(a, b, c, reverse) {
+ return num(reverse ? Math.max(Math.min(a, b), c) : Math.min(Math.max(a, b), c));
+}
+
+/**
+ * 旋转90°或270°时检查边界:限制 x、y 拖动范围,禁止滑出边界
+ * @param {Object} e 点坐标
+ * @param {Object} xReverse x是否反向
+ * @param {Object} yReverse y是否反向
+ */
+function checkRotateRange(e, xReverse, yReverse) {
+ var o = num((img.height - img.width) / 2); // 宽高差值一半
+ return {
+ x: correctValue(e.x, -img.height + o + area.width + area.left, area.left + o, xReverse),
+ y: correctValue(e.y, -img.width - o + area.height + area.top, area.top - o, yReverse)
+ };
+}
+
+/**
+ * 检查边界:限制 x、y 拖动范围,禁止滑出边界
+ * @param {Object} e 点坐标
+ */
+function checkRange(e) {
+ var r = rotate / 90 % 2;
+ if(r === 1) { // 因图片宽高可能不等,翻转 90° 或 270° 后图片宽高需反着计算,且左右和上下边界要根据差值做偏移
+ if (area.width === area.height) {
+ return checkRotateRange(e, img.height < area.height, img.width < area.width);
+ }
+ var isInclude = img.height < area.width && img.width < area.height; // 图片是否包含在裁剪区域内
+ if (img.width < area.height || img.height < area.width) {
+ if (area.width < area.height && img.width < img.height) {
+ return isInclude
+ ? checkRotateRange(e, area.width < area.height, area.width < area.height)
+ : checkRotateRange(e, false, true);
+ }
+ if (area.height < area.width && img.height < img.width) {
+ return isInclude
+ ? checkRotateRange(e, area.height < area.width, area.height < area.width)
+ : checkRotateRange(e, true, false);
+ }
+ }
+ if (img.height >= area.width && img.width >= area.height) {
+ return checkRotateRange(e, false, false);
+ }
+ if (isInclude) {
+ return area.height < area.width
+ ? checkRotateRange(e, true, true)
+ : checkRotateRange(e, area.width < area.height, area.width < area.height);
+ }
+ if (img.height < area.width && !img.width < area.height) {
+ return checkRotateRange(e, true, false);
+ }
+ if (!img.height < area.width && img.width < area.height) {
+ return checkRotateRange(e, false, true);
+ }
+ return checkRotateRange(e, img.height < area.height, img.width < area.width);
+ }
+ return {
+ x: correctValue(e.x, -img.width + area.width + area.left, area.left, img.width < area.width),
+ y: correctValue(e.y, -img.height + area.height + area.top, area.top, img.height < area.height)
+ };
+};
+/**
+ * 变更图片布局信息
+ * @param {Object} e 布局信息
+ */
+function changeImageRect(e) {
+ offset.x += e.x || 0;
+ offset.y += e.y || 0;
+ var image = e.instance.selectComponent('.crop-image');
+ if(e.check && area.checkRange) { // 检查边界
+ var point = checkRange(offset);
+ if(offset.x !== point.x || offset.y !== point.y) {
+ offset = point;
+ }
+ }
+ // image.setStyle({
+ // width: img.width + 'px',
+ // height: img.height + 'px',
+ // transform: 'translate(' + offset.x + 'px, ' + offset.y + 'px) rotate(' + rotate +'deg)'
+ // });
+ var ox = (img.width - img.oldWidth) / 2;
+ var oy = (img.height - img.oldHeight) / 2;
+ image.setStyle({
+ width: img.oldWidth + 'px',
+ height: img.oldHeight + 'px',
+ transform: (img.gpu ? 'translateZ(0) ' : '') + 'translate(' + (offset.x + ox) + 'px, ' + (offset.y + oy) + 'px) rotate(' + rotate +'deg) scale(' + scale + ')'
+ });
+
+ e.instance.callMethod('dataChange', {
+ width: img.width,
+ height: img.height,
+ x: offset.x,
+ y: offset.y,
+ rotate: rotate
+ });
+};
+/**
+ * 变更裁剪区域布局信息
+ * @param {Object} e 布局信息
+ */
+function changeAreaRect(e) {
+ // 变更蒙版样式
+ var masks = e.instance.selectAllComponents('.crop-mask-block');
+ var maskStyles = [
+ {
+ left: 0,
+ width: (area.left + areaOffset.left) + 'px',
+ top: 0,
+ bottom: 0,
+ 'z-index': area.zIndex + 2
+ },
+ {
+ left: (area.right + areaOffset.right) + 'px',
+ right: 0,
+ top: 0,
+ bottom: 0,
+ 'z-index': area.zIndex + 2
+ },
+ {
+ left: (area.left + areaOffset.left) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ top: 0,
+ height: (area.top + areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 2
+ },
+ {
+ left: (area.left + areaOffset.left) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ top: (area.bottom + areaOffset.bottom) + 'px',
+ // height: (area.top - areaOffset.bottom + sys.offsetBottom) + 'px',
+ bottom: 0,
+ 'z-index': area.zIndex + 2
+ }
+ ];
+ var len = masks.length;
+ for (var i = 0; i < len; i++) {
+ masks[i].setStyle(maskStyles[i]);
+ }
+
+ // 变更边框样式
+ if(area.showBorder) {
+ var border = e.instance.selectComponent('.crop-border');
+ border.setStyle({
+ left: (area.left + areaOffset.left) + 'px',
+ top: (area.top + areaOffset.top) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 3
+ });
+ }
+
+ // 变更参考线样式
+ if(area.showGrid) {
+ var grids = e.instance.selectAllComponents('.crop-grid');
+ var gridStyles = [
+ {
+ 'border-width': '1px 0 0 0',
+ left: (area.left + areaOffset.left) + 'px',
+ right: (area.right + areaOffset.right) + 'px',
+ top: (area.top + areaOffset.top + (area.height + areaOffset.bottom - areaOffset.top) / 3 - 0.5) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '1px 0 0 0',
+ left: (area.left + areaOffset.left) + 'px',
+ right: (area.right + areaOffset.right) + 'px',
+ top: (area.top + areaOffset.top + (area.height + areaOffset.bottom - areaOffset.top) * 2 / 3 - 0.5) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '0 1px 0 0',
+ top: (area.top + areaOffset.top) + 'px',
+ bottom: (area.bottom + areaOffset.bottom) + 'px',
+ left: (area.left + areaOffset.left + (area.width + areaOffset.right - areaOffset.left) / 3 - 0.5) + 'px',
+ height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '0 1px 0 0',
+ top: (area.top + areaOffset.top) + 'px',
+ bottom: (area.bottom + areaOffset.bottom) + 'px',
+ left: (area.left + areaOffset.left + (area.width + areaOffset.right - areaOffset.left) * 2 / 3 - 0.5) + 'px',
+ height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 3
+ }
+ ];
+ var len = grids.length;
+ for (var i = 0; i < len; i++) {
+ grids[i].setStyle(gridStyles[i]);
+ }
+ }
+
+ // 变更四个伸缩角样式
+ if(area.showAngle) {
+ var angles = e.instance.selectAllComponents('.crop-angle');
+ var angleStyles = [
+ {
+ 'border-width': area.angleBorderWidth + 'px 0 0 ' + area.angleBorderWidth + 'px',
+ left: (area.left + areaOffset.left - area.angleBorderWidth) + 'px',
+ top: (area.top + areaOffset.top - area.angleBorderWidth) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px 0 0',
+ left: (area.right + areaOffset.right - area.angleSize) + 'px',
+ top: (area.top + areaOffset.top - area.angleBorderWidth) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '0 0 ' + area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px',
+ left: (area.left + areaOffset.left - area.angleBorderWidth) + 'px',
+ top: (area.bottom + areaOffset.bottom - area.angleSize) + 'px',
+ 'z-index': area.zIndex + 3
+ },
+ {
+ 'border-width': '0 ' + area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px 0',
+ left: (area.right + areaOffset.right - area.angleSize) + 'px',
+ top: (area.bottom + areaOffset.bottom - area.angleSize) + 'px',
+ 'z-index': area.zIndex + 3
+ }
+ ];
+ var len = angles.length;
+ for (var i = 0; i < len; i++) {
+ angles[i].setStyle(angleStyles[i]);
+ }
+ }
+
+ // 变更圆角样式
+ if(area.radius > 0) {
+ var circleBox = e.instance.selectComponent('.crop-circle-box');
+ var circle = e.instance.selectComponent('.crop-circle');
+ var radius = area.radius;
+ if(area.width === area.height && area.radius >= area.width / 2) { // 圆形
+ radius = (area.width / 2);
+ } else { // 圆角矩形
+ if(area.width !== area.height) { // 限制圆角半径不能超过短边的一半
+ radius = Math.min(area.width / 2, area.height / 2, radius);
+ }
+ }
+ circleBox.setStyle({
+ left: (area.left + areaOffset.left) + 'px',
+ top: (area.top + areaOffset.top) + 'px',
+ width: (area.width + areaOffset.right - areaOffset.left) + 'px',
+ height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
+ 'z-index': area.zIndex + 2
+ });
+ circle.setStyle({
+ 'box-shadow': '0 0 0 ' + Math.max(area.width, area.height) + 'px rgba(51, 51, 51, 0.8)',
+ 'border-radius': radius + 'px'
+ });
+ }
+};
+/**
+ * 缩放图片
+ * @param {Object} e 布局信息
+ */
+function scaleImage(e) {
+ var last = scale;
+ scale = Math.min(Math.max(e.scale + scale, minScale), img.maxScale);
+ if(last !== scale) {
+ img.width = num(img.oldWidth * scale);
+ img.height = num(img.oldHeight * scale);
+ // 参考问题:有一个长4000px、宽4000px的四方形ABCD,A点的坐标固定在(-2000,-2000),
+ // 该四边形上有一个点E,坐标为(-100,-300),将该四方形复制一份并缩小到90%后,
+ // 新四边形的A点坐标为多少时可使新四边形的E点与原四边形的E点重合?
+ // 预期效果:从图中选取某点(参照物)为中心点进行缩放,缩放时无论图像怎么变化,该点位置始终固定不变
+ // 计算方法:以相同起点先计算缩放前后两点间的距离,再加上原图像偏移量即可
+ e.x = num((e.x - offset.x) * (1 - scale / last));
+ e.y = num((e.y - offset.y) * (1 - scale / last));
+ changeImageRect(e);
+ return true;
+ }
+ return false;
+};
+/**
+ * 获取触摸点在哪个角
+ * @param {number} x 触摸点x轴坐标
+ * @param {number} y 触摸点y轴坐标
+ * @return {number} 角的位置:0=无;1=左上;2=右上;3=左下;4=右下;
+ */
+function getToucheAngle(x, y) {
+ // console.log('getToucheAngle', x, y, JSON.stringify(area))
+ var o = area.angleBorderWidth; // 需扩大触发范围则把 o 值加大即可
+ if(y >= area.top - o && y <= area.top + area.angleSize + o) {
+ if(x >= area.left - o && x <= area.left + area.angleSize + o) {
+ return 1; // 左上角
+ } else if(x >= area.right - area.angleSize - o && x <= area.right + o) {
+ return 2; // 右上角
+ }
+ } else if(y >= area.bottom - area.angleSize - o && y <= area.bottom + o) {
+ if(x >= area.left - o && x <= area.left + area.angleSize + o) {
+ return 3; // 左下角
+ } else if(x >= area.right - area.angleSize - o && x <= area.right + o) {
+ return 4; // 右下角
+ }
+ }
+ return 0; // 无触摸到角
+};
+/**
+ * 重置数据
+ */
+function resetData() {
+ offset = { x: 0, y: 0 };
+ scale = 1;
+ minScale = img.minScale;
+ rotate = 0;
+};
+/**
+* 顺时针翻转图片90°
+* @param {Object} e 事件对象
+* @param {Object} o 组件实例对象
+*/
+function rotateImage(e, o, r) {
+ rotate = (rotate + r) % 360;
+ if(img.minScale >= 1 && area.checkRange) {
+ // 因图片宽高可能不等,翻转后图片宽高需足够填满裁剪区域
+ minScale = 1;
+ if(img.width < area.height) {
+ minScale = area.height / img.oldWidth;
+ } else if(img.height < area.width) {
+ minScale = area.width / img.oldHeight;
+ }
+ if(minScale !== 1) {
+ scaleImage({
+ instance: o,
+ scale: minScale - scale,
+ x: sys.windowWidth / 2,
+ y: (sys.windowHeight - sys.offsetBottom) / 2
+ });
+ }
+ }
+
+ // 由于拖动画布后会导致图片位置偏移,翻转时的旋转中心点需是图片区域+偏移区域的中心点
+ // 翻转x轴中心点 = (超出裁剪区域右侧的图片宽度 - 超出裁剪区域左侧的图片宽度) / 2
+ // 翻转y轴中心点 = (超出裁剪区域下方的图片宽度 - 超出裁剪区域上方的图片宽度) / 2
+ var ox = ((offset.x + img.width - area.right) - (area.left - offset.x)) / 2;
+ var oy = ((offset.y + img.height - area.bottom) - (area.top - offset.y)) / 2;
+ changeImageRect({
+ instance: o,
+ check: true,
+ x: -ox - oy,
+ y: -oy + ox
+ });
+};
+module.exports = {
+ /**
+ * 初始化:观察数据变更
+ * @param {Object} newVal 新数据
+ * @param {Object} oldVal 旧数据
+ * @param {Object} o 组件实例对象
+ */
+ initObserver: function(newVal, oldVal, o, i) {
+ if(newVal) {
+ img = newVal.img;
+ sys = newVal.sys;
+ area = newVal.area;
+ minScale = img.minScale;
+ resetData();
+ img.src && changeImageRect({
+ instance: o,
+ x: (sys.windowWidth - img.width) / 2,
+ y: (sys.windowHeight - sys.offsetBottom - img.height) / 2
+ });
+ changeAreaRect({
+ instance: o
+ });
+ // console.log('initRect', JSON.stringify(newVal))
+ }
+ },
+ /**
+ * 鼠标滚轮滚动
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ mousewheel: function(e, o) {
+ if(!img.src) return;
+ scaleImage({
+ instance: o,
+ check: true,
+ // 鼠标向上滚动时,deltaY 固定 -100,鼠标向下滚动时,deltaY 固定 100
+ scale: e.detail.deltaY > 0 ? -0.05 : 0.05,
+ x: e.touches[0].pageX,
+ y: e.touches[0].pageY
+ });
+ },
+ /**
+ * 触摸开始
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ touchstart: function(e, o) {
+ if(!img.src) return;
+ touches = e.touches;
+ activeAngle = area.showAngle ? getToucheAngle(touches[0].pageX, touches[0].pageY) : 0;
+ if(touches.length === 1 && activeAngle !== 0) {
+ touchType = 'stretch'; // 伸缩裁剪区域
+ } else {
+ touchType = '';
+ }
+ // console.log('touchstart', JSON.stringify(e), activeAngle)
+ },
+ /**
+ * 触摸移动
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ touchmove: function(e, o) {
+ if(!img.src) return;
+ // console.log('touchmove', JSON.stringify(e), JSON.stringify(o))
+ if(touchType === 'stretch') { // 触摸四个角进行拉伸
+ var point = e.touches[0];
+ var start = touches[0];
+ var x = point.pageX - start.pageX;
+ var y = point.pageY - start.pageY;
+ if(x !== 0 || y !== 0) {
+ var maxX = num(area.width * (1 - area.minScale));
+ var maxY = num(area.height * (1 - area.minScale));
+ // console.log(x, y, maxX, maxY, offset, area)
+ touches[0] = point;
+ var r = rotate / 90 % 2;
+ var m = r === 1 ? num((img.height - img.width) / 2) : 0; // 宽高差值一半
+ var xCompare = r === 1 ? lessThanByFault(img.height, area.width) : lessThanByFault(img.width, area.width);
+ var yCompare = r === 1 ? lessThanByFault(img.width, area.height) : lessThanByFault(img.height, area.height)
+ var isInclude = xCompare && yCompare;
+ var isIntersect = area.checkRange && (xCompare || yCompare); // 图片是否包含在裁剪区域内
+ var isReverse = !isInclude || num((offset.x - area.left) / area.width) <= num((offset.y - area.top) / area.height) || (area.width > area.height && img.width < img.height && r === 1);
+ switch(activeAngle) {
+ case 1: // 左上角
+ x = num(x + areaOffset.left);
+ y = num(y + areaOffset.top);
+ if(x >= 0 && y >= 0) { // 有效滑动
+ var t = num(offset.y + m - area.top);
+ var l = num(offset.x - m - area.left);
+ // && (offset.x + img.width < area.right || offset.y + img.height < area.bottom)
+ var max = isIntersect && ((l >= 0) || (t >= 0))
+ ? minimum(t, l)
+ : false;
+ if(x > y && isReverse) { // 以x轴滑动距离为缩放基准
+ maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
+ if(x > maxX) x = maxX;
+ y = num(x * area.height / area.width);
+ } else { // 以y轴滑动距离为缩放基准
+ maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
+ if(y > maxY) y = maxY;
+ x = num(y * area.width / area.height);
+ }
+ areaOffset.left = x;
+ areaOffset.top = y;
+ }
+ break;
+ case 2: // 右上角
+ x = num(x + areaOffset.right);
+ y = num(y + areaOffset.top);
+ if(x <= 0 && y >= 0) { // 有效滑动
+ var w = (r === 1 ? img.height : img.width);
+ var t = num(offset.y + m - area.top);
+ var l = num(area.right + m - offset.x - w);
+ var max = isIntersect && ((t >= 0) || (l >= 0))
+ ? minimum(t, l)
+ : false;
+ // var max = isInclude && ((offset.x > 0 && offset.x + img.width <= area.right) || (offset.y > 0 && offset.y >= area.top))
+ // ? minimum(offset.y - area.top, area.right - offset.x - img.width)
+ // : false;
+ // console.log(offset.x, offset.y, img.width, img.height, area.top, area.right, m, max)
+ // console.log(offset.y + m - area.top, area.right + m - offset.x - w)
+ if(-x > y && isReverse) { // 以x轴滑动距离为缩放基准
+ maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
+ if(-x > maxX) x = -maxX;
+ y = num(-x * area.height / area.width);
+ } else { // 以y轴滑动距离为缩放基准
+ maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
+ if(y > maxY) y = maxY;
+ x = num(-y * area.width / area.height);
+ }
+ areaOffset.right = x;
+ areaOffset.top = y;
+ }
+ break;
+ case 3: // 左下角
+ x += num(x + areaOffset.left);
+ y += num(y + areaOffset.bottom);
+ if(x >= 0 && y <= 0) { // 有效滑动
+ var w = (r === 1 ? img.width : img.height);
+ var t = num(area.bottom - m - offset.y - w);
+ var l = num(offset.x - m - area.left);
+ var max = isIntersect && ((l >= 0) || (t >= 0))
+ ? minimum(t, l)
+ : false;
+ if(x > -y && isReverse) { // 以x轴滑动距离为缩放基准
+ maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
+ if(x > maxX) x = maxX;
+ y = num(-x * area.height / area.width);
+ } else { // 以y轴滑动距离为缩放基准
+ maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
+ if(-y > maxY) y = -maxY;
+ x = num(-y * area.width / area.height);
+ }
+ areaOffset.left = x;
+ areaOffset.bottom = y;
+ }
+ break;
+ case 4: // 右下角
+ x = num(x + areaOffset.right);
+ y = num(y + areaOffset.bottom);
+ if(x <= 0 && y <= 0) { // 有效滑动
+ var w = (r === 1 ? img.height : img.width);
+ var h = (r === 1 ? img.width : img.height);
+ var t = num(area.bottom - offset.y - h - m);
+ var l = num(area.right + m - offset.x - w);
+ var max = isIntersect && ((l >= 0) || (t >= 0))
+ ? minimum(t, l)
+ : false;
+ if(-x > -y && isReverse) { // 以x轴滑动距离为缩放基准
+ maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
+ if(-x > maxX) x = -maxX;
+ y = num(x * area.height / area.width);
+ } else { // 以y轴滑动距离为缩放基准
+ maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
+ if(-y > maxY) y = -maxY;
+ x = num(y * area.width / area.height);
+ }
+ areaOffset.right = x;
+ areaOffset.bottom = y;
+ }
+ break;
+ }
+ // console.log(x, y, JSON.stringify(areaOffset))
+ changeAreaRect({
+ instance: o,
+ });
+ // this.draw();
+ }
+ } else if (e.touches.length == 2) { // 双点触摸缩放
+ var start = getDistanceByTouches(touches);
+ var end = getDistanceByTouches(e.touches);
+ scaleImage({
+ instance: o,
+ check: !area.bounce,
+ scale: (end.c - start.c) / 100,
+ x: end.x,
+ y: end.y
+ });
+ touchType = 'scale';
+ } else if(touchType === 'scale') {// 从双点触摸变成单点触摸 / 从缩放变成拖动
+ touchType = 'move';
+ } else {
+ changeImageRect({
+ instance: o,
+ check: !area.bounce,
+ x: e.touches[0].pageX - touches[0].pageX,
+ y: e.touches[0].pageY - touches[0].pageY
+ });
+ touchType = 'move';
+ }
+ touches = e.touches;
+ },
+ /**
+ * 触摸结束
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ touchend: function(e, o) {
+ if(!img.src) return;
+ if(touchType === 'stretch') { // 拉伸裁剪区域的四个角缩放
+ // 裁剪区域宽度被缩放到多少
+ var left = areaOffset.left;
+ var right = areaOffset.right;
+ var top = areaOffset.top;
+ var bottom = areaOffset.bottom;
+ var w = area.width + right - left;
+ var h = area.height + bottom - top;
+ // 图像放大倍数
+ var p = scale * (area.width / w) - scale;
+ // 复原裁剪区域
+ areaOffset = { left: 0, right: 0, top: 0, bottom: 0 };
+ changeAreaRect({
+ instance: o,
+ });
+ scaleImage({
+ instance: o,
+ scale: p,
+ x: area.left + left + (1 === activeAngle || 3 === activeAngle ? w : 0),
+ y: area.top + top + (1 === activeAngle || 2 === activeAngle ? h : 0)
+ });
+ } else if (area.bounce) { // 检查边界并矫正,实现拖动到边界时有回弹效果
+ changeImageRect({
+ instance: o,
+ check: true
+ });
+ }
+ },
+ /**
+ * 顺时针翻转图片90°
+ * @param {Object} e 事件对象
+ * @param {Object} o 组件实例对象
+ */
+ rotateImage: function(e, o) {
+ rotateImage(e, o, 90);
+ },
+ rotateImage90: function(e, o) {
+ rotateImage(e, o, 90)
+ },
+ rotateImage270: function(e, o) {
+ rotateImage(e, o, 270)
+ },
+ // 此处只用于对齐其他平台端的样式参数,防止异常,无作用
+ imageStyles: '',
+ maskStylesList: ['', '', '', ''],
+ borderStyles: '',
+ gridStylesList: ['', '', '', ''],
+ angleStylesList: ['', '', '', ''],
+ circleBoxStyles: '',
+ circleStyles: '',
+}
\ No newline at end of file
diff --git a/uni_modules/qf-image-cropper/package.json b/uni_modules/qf-image-cropper/package.json
new file mode 100644
index 0000000..f101c5b
--- /dev/null
+++ b/uni_modules/qf-image-cropper/package.json
@@ -0,0 +1,81 @@
+{
+ "id": "qf-image-cropper",
+ "displayName": "图片裁剪插件",
+ "version": "2.2.5",
+ "description": "图片裁剪插件,支持自定义尺寸、定点等比例缩放、拖动、图片翻转、剪切圆形/圆角图片、定制样式,功能多性能高体验好注释全。",
+ "keywords": [
+ "qf-image-cropper",
+ "图片裁剪",
+ "图片编辑",
+ "头像裁剪",
+ "小程序"
+],
+ "repository": "",
+ "engines": {
+ "HBuilderX": "^3.1.0"
+ },
+"dcloudext": {
+ "type": "component-vue",
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "插件不采集任何数据",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "client": {
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ },
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "n",
+ "百度": "n",
+ "字节跳动": "n",
+ "QQ": "u",
+ "钉钉": "n",
+ "快手": "n",
+ "飞书": "n",
+ "京东": "n"
+ },
+ "快应用": {
+ "华为": "n",
+ "联盟": "n"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/qf-image-cropper/readme.md b/uni_modules/qf-image-cropper/readme.md
new file mode 100644
index 0000000..f39f645
--- /dev/null
+++ b/uni_modules/qf-image-cropper/readme.md
@@ -0,0 +1,97 @@
+# qf-image-cropper
+## 图片裁剪插件
+uniapp微信小程序图片裁剪插件,支持自定义尺寸、定点等比例缩放、拖动、图片翻转、剪切圆形/圆角图片、定制样式,功能多性能高体验好注释全。
+
+### 平台支持:
+1. 支持微信小程序:移动端、PC端、开发者工具
+2. 支持H5平台(2.1.0版本起)
+3. 支持APP平台(2.1.5版本起):Android、IOS
+4. 其他平台暂未测试兼容性未知
+
+### 支持功能:
+1. 自定义裁剪尺寸
+2. 定点等比例缩放:移动端以双指触摸中心点为缩放中心点,PC端以鼠标所在点为缩放中心点
+3. 自由拖动:支持限制滑出边界,也支持回弹效果(滑动时可滑出边界,释放时回弹到边界)
+4. 图片翻转:在裁剪尺寸非 1:1 的情况下,翻转时宽高无法铺满裁剪区域时,图片会自动放大到合适尺寸
+5. 裁剪生成新图片
+6. 本地选择图片
+7. 可定制样式:可自由选择是否渲染裁剪边框、可伸缩裁剪顶角、参考线
+8. 裁剪圆角图片:圆形、圆角矩形
+
+### 属性说明
+| 属性名 | 类型 | 默认值 | 说明 |
+|:---|:---|:---|:---|
+| src | String | | 图片资源地址 |
+| width | Number | 300 | 裁剪宽度 |
+| height | Number | 300 | 裁剪高度 |
+| showBorder | Boolean | true | 是否绘制裁剪区域边框 |
+| showGrid | Boolean | true | 是否绘制裁剪区域网格参考线 |
+| showAngle | Boolean | true | 是否展示四个支持伸缩的角 |
+| areaScale | Number | 0.3 | 裁剪区域最小缩放倍数 |
+| minScale | Number | 1 | 图片最小缩放倍数 |
+| maxScale | Number | 5 | 图片最大缩放倍数 |
+| checkRange | Boolean | true | 检查图片位置是否超出裁剪边界,如果超出则会矫正位置 |
+| backgroundColor | String | | 生成图片背景色:如果裁剪区域没有完全包含在图片中时,不设置该属性则生成图片存在一定的透明块 |
+| bounce | Boolean | true | 是否有回弹效果:当 checkRange 为 true 时有效,拖动时可以拖出边界,释放时会弹回边界 |
+| rotatable | Boolean | true | 是否支持翻转 |
+| reverseRotatable | Boolean | false | 是否支持逆向翻转 |
+| choosable | Boolean | true | 是否支持从本地选择素材 |
+| gpu | Boolean | false | 是否开启硬件加速,图片缩放过程中如果出现元素的“留影”或“重影”效果,可通过该方式解决或减轻这一问题 |
+| angleSize | Number | 20 | 四个角尺寸,单位px |
+| angleBorderWidth | Number | 2 | 四个角边框宽度,单位px |
+| zIndex | Number/String | | 调整组件层级 |
+| radius | Number | | 裁剪图片圆角半径,单位px |
+| fileType | String | png | 生成文件的类型,只支持 'jpg' 或 'png'。默认为 'png' |
+| delay | Number | 1000 | 图片从绘制到生成所需时间,单位ms
微信小程序平台使用 `Canvas 2D` 绘制时有效
如绘制大图或出现裁剪图片空白等情况应适当调大该值,因 `Canvas 2d` 采用同步绘制,需自己把控绘制完成时间 |
+| navigation | Boolean | true | 页面是否是原生标题栏:
H5平台当 showAngle 为 true 时,使用插件的页面在 `page.json` 中配置了 `"navigationStyle": "custom"` 时,必须将此值设为 false ,否则四个可拉伸角的触发位置会有偏差。
注:因H5平台的窗口高度是包含标题栏的,而屏幕触摸点的坐标是不包含的 |
+| @crop | EventHandle | | 剪裁完成后触发,event = { tempFilePath }。在H5平台下,tempFilePath 为 base64 |
+
+### 基本用法
+```
+
+
+
+
+
+
+
+```
+通过ref组件实例可在进入页面后直接打开相册选择图片
+```
+mounted() {
+ this.$refs.qfImageCropper.chooseImage({ sourceType: ['album'] });
+}
+```
+### 使用说明
+1.建议在`pages.json`中将引用插件的页面添加一下配置禁止下拉刷新和禁止页面滑动,防止出现性能或页面抖动等问题。
+```
+{
+ "enablePullDownRefresh": false,
+ "disableScroll": true
+}
+```
+2.建议使用本插件不要设置过大宽高的目标图片尺寸,建议1365x1365以内,否则可能会导致如下问题:
+```
+1.界面卡顿,内存占用过高
+2.生成图片失真(模糊)
+3.确定裁剪后一直显示 `裁剪中...`,该问题是由 `uni.canvasToTempFilePath` 无法回调导致,不同平台不同设备限制可能有所不同。
+```
+3.如裁剪后的图片存在偏移的问题,请检查是否受自己项目中父组件或全局样式影响。
+4.src属性设置网络图片时,图片资源必须是能触发 `getImageInfo` API 的 success 回调才可用于插件裁剪。因此小程序平台获取网络图片信息需先配置download域名白名单才能生效。
+5.如果组件无法正常渲染且使用了 `v-if` 时,可尝试将 `v-if` 替换为 `v-show`
+6.如果App端导入组件后无法正常渲染,请尝试重新运行
\ No newline at end of file
diff --git a/uni_modules/uni-calendar/changelog.md b/uni_modules/uni-calendar/changelog.md
index 0160b69..f291eec 100644
--- a/uni_modules/uni-calendar/changelog.md
+++ b/uni_modules/uni-calendar/changelog.md
@@ -1,20 +1,26 @@
+## 1.4.10(2023-04-10)
+- 修复 某些情况 monthSwitch 未触发的Bug
+## 1.4.9(2023-02-02)
+- 修复 某些情况切换月份错误的Bug
+## 1.4.8(2023-01-30)
+- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964)
## 1.4.7(2022-09-16)
-- 可以使用 uni-scss 控制主题色
+- 优化 支持使用 uni-scss 控制主题色
## 1.4.6(2022-09-08)
-- fix: 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件
+- 修复 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件的Bug
## 1.4.5(2022-02-25)
-- 修复 条件编译 nvue 不支持的 css 样式
+- 修复 条件编译 nvue 不支持的 css 样式的Bug
## 1.4.4(2022-02-25)
-- 修复 条件编译 nvue 不支持的 css 样式
+- 修复 条件编译 nvue 不支持的 css 样式的Bug
## 1.4.3(2021-09-22)
-- 修复 startDate、 endDate 属性失效的 bug
+- 修复 startDate、 endDate 属性失效的Bug
## 1.4.2(2021-08-24)
- 新增 支持国际化
## 1.4.1(2021-08-05)
-- 修复 弹出层被 tabbar 遮盖 bug
+- 修复 弹出层被 tabbar 遮盖的Bug
## 1.4.0(2021-07-30)
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.3.16(2021-05-12)
- 新增 组件示例地址
## 1.3.15(2021-02-04)
-- 调整为uni_modules目录规范
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
index 369710e..a54135e 100644
--- a/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
+++ b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
@@ -51,11 +51,10 @@
-
+ /* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */
+ /* #ifndef APP-NVUE */
+ .uni-popper__arrow,
+ .uni-popper__arrow::after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 6px;
+ }
+
+ .uni-popper__arrow {
+ filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+ top: -6px;
+ left: 10%;
+ margin-right: 3px;
+ border-top-width: 0;
+ border-bottom-color: #EBEEF5;
+ }
+
+ .uni-popper__arrow::after {
+ content: " ";
+ top: 1px;
+ margin-left: -6px;
+ border-top-width: 0;
+ border-bottom-color: #fff;
+ }
+
+ /* #endif */
+
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
index c12fd54..cfae22a 100644
--- a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
@@ -42,7 +42,7 @@ export default {
},
pageSize: {
type: Number,
- default: 20
+ default: 500
},
getcount: {
type: [Boolean, String],
@@ -94,7 +94,7 @@ export default {
},
map: {
type: Object,
- default() {
+ default () {
return {
text: "text",
value: "value"
@@ -122,19 +122,22 @@ export default {
}
},
computed: {
- isLocaldata() {
- return !this.collection.length
+ isLocalData() {
+ return !this.collection.length;
},
- postField() {
- let fields = [this.field];
- if (this.parentField) {
- fields.push(`${this.parentField} as parent_value`);
- }
- return fields.join(',');
+ isCloudData() {
+ return this.collection.length > 0;
+ },
+ isCloudDataList() {
+ return (this.isCloudData && (!this.parentField && !this.selfField));
+ },
+ isCloudDataTree() {
+ return (this.isCloudData && this.parentField && this.selfField);
},
dataValue() {
- let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null || this.modelValue !== undefined)
- return isModelValue ? this.modelValue : this.value
+ let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null ||
+ this.modelValue !== undefined);
+ return isModelValue ? this.modelValue : this.value;
},
hasValue() {
if (typeof this.dataValue === 'number') {
@@ -183,8 +186,169 @@ export default {
},
methods: {
onPropsChange() {
- this._treeData = []
+ this._treeData = [];
},
+
+ // 填充 pickview 数据
+ async loadData() {
+ if (this.isLocalData) {
+ this.loadLocalData();
+ } else if (this.isCloudDataList) {
+ this.loadCloudDataList();
+ } else if (this.isCloudDataTree) {
+ this.loadCloudDataTree();
+ }
+ },
+
+ // 加载本地数据
+ async loadLocalData() {
+ this._treeData = [];
+ this._extractTree(this.localdata, this._treeData);
+
+ let inputValue = this.dataValue;
+ if (inputValue === undefined) {
+ return;
+ }
+
+ if (Array.isArray(inputValue)) {
+ inputValue = inputValue[inputValue.length - 1];
+ if (typeof inputValue === 'object' && inputValue[this.map.value]) {
+ inputValue = inputValue[this.map.value];
+ }
+ }
+
+ this.selected = this._findNodePath(inputValue, this.localdata);
+ },
+
+ // 加载 Cloud 数据 (单列)
+ async loadCloudDataList() {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let response = await this.getCommand();
+ let responseData = response.result.data;
+
+ this._treeData = responseData;
+
+ this._updateBindData();
+ this._updateSelected();
+
+ this.onDataChange();
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 加载 Cloud 数据 (树形)
+ async loadCloudDataTree() {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let commandOptions = {
+ field: this._cloudDataPostField(),
+ where: this._cloudDataTreeWhere()
+ };
+ if (this.gettree) {
+ commandOptions.startwith = `${this.selfField}=='${this.dataValue}'`;
+ }
+
+ let response = await this.getCommand(commandOptions);
+ let responseData = response.result.data;
+
+ this._treeData = responseData;
+ this._updateBindData();
+ this._updateSelected();
+
+ this.onDataChange();
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 加载 Cloud 数据 (节点)
+ async loadCloudDataNode(callback) {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let commandOptions = {
+ field: this._cloudDataPostField(),
+ where: this._cloudDataNodeWhere()
+ };
+
+ let response = await this.getCommand(commandOptions);
+ let responseData = response.result.data;
+
+ callback(responseData);
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 回显 Cloud 数据
+ getCloudDataValue() {
+ if (this.isCloudDataList) {
+ return this.getCloudDataListValue();
+ }
+
+ if (this.isCloudDataTree) {
+ return this.getCloudDataTreeValue();
+ }
+ },
+
+ // 回显 Cloud 数据 (单列)
+ getCloudDataListValue() {
+ // 根据 field's as value标识匹配 where 条件
+ let where = [];
+ let whereField = this._getForeignKeyByField();
+ if (whereField) {
+ where.push(`${whereField} == '${this.dataValue}'`)
+ }
+
+ where = where.join(' || ');
+
+ if (this.where) {
+ where = `(${this.where}) && (${where})`
+ }
+
+ return this.getCommand({
+ field: this._cloudDataPostField(),
+ where
+ }).then((res) => {
+ this.selected = res.result.data;
+ return res.result.data;
+ });
+ },
+
+ // 回显 Cloud 数据 (树形)
+ getCloudDataTreeValue() {
+ return this.getCommand({
+ field: this._cloudDataPostField(),
+ getTreePath: {
+ startWith: `${this.selfField}=='${this.dataValue}'`
+ }
+ }).then((res) => {
+ let treePath = [];
+ this._extractTreePath(res.result.data, treePath);
+ this.selected = treePath;
+ return treePath;
+ });
+ },
+
getCommand(options = {}) {
/* eslint-disable no-undef */
let db = uniCloud.database(this.spaceInfo)
@@ -229,125 +393,16 @@ export default {
return db
},
- getNodeData(callback) {
- if (this.loading) {
- return
- }
- this.loading = true
- this.getCommand({
- field: this.postField,
- where: this._pathWhere()
- }).then((res) => {
- this.loading = false
- this.selected = res.result.data
- callback && callback()
- }).catch((err) => {
- this.loading = false
- this.errorMessage = err
- })
- },
- getTreePath(callback) {
- if (this.loading) {
- return
- }
- this.loading = true
- this.getCommand({
- field: this.postField,
- getTreePath: {
- startWith: `${this.selfField}=='${this.dataValue}'`
- }
- }).then((res) => {
- this.loading = false
- let treePath = []
- this._extractTreePath(res.result.data, treePath)
- this.selected = treePath
- callback && callback()
- }).catch((err) => {
- this.loading = false
- this.errorMessage = err
- })
+ _cloudDataPostField() {
+ let fields = [this.field];
+ if (this.parentField) {
+ fields.push(`${this.parentField} as parent_value`);
+ }
+ return fields.join(',');
},
- loadData() {
- if (this.isLocaldata) {
- this._processLocalData()
- return
- }
- if (this.dataValue != null) {
- this._loadNodeData((data) => {
- this._treeData = data
- this._updateBindData()
- this._updateSelected()
- })
- return
- }
-
- if (this.stepSearh) {
- this._loadNodeData((data) => {
- this._treeData = data
- this._updateBindData()
- })
- } else {
- this._loadAllData((data) => {
- this._treeData = []
- this._extractTree(data, this._treeData, null)
- this._updateBindData()
- })
- }
- },
- _loadAllData(callback) {
- if (this.loading) {
- return
- }
- this.loading = true
-
- this.getCommand({
- field: this.postField,
- gettree: true,
- startwith: `${this.selfField}=='${this.dataValue}'`
- }).then((res) => {
- this.loading = false
- callback(res.result.data)
- this.onDataChange()
- }).catch((err) => {
- this.loading = false
- this.errorMessage = err
- })
- },
- _loadNodeData(callback, pw) {
- if (this.loading) {
- return
- }
- this.loading = true
-
- this.getCommand({
- field: this.postField,
- where: pw || this._postWhere(),
- pageSize: 500
- }).then((res) => {
- this.loading = false
- callback(res.result.data)
- this.onDataChange()
- }).catch((err) => {
- this.loading = false
- this.errorMessage = err
- })
- },
- _pathWhere() {
- let result = []
- let where_field = this._getParentNameByField();
- if (where_field) {
- result.push(`${where_field} == '${this.dataValue}'`)
- }
-
- if (this.where) {
- return `(${this.where}) && (${result.join(' || ')})`
- }
-
- return result.join(' || ')
- },
- _postWhere() {
+ _cloudDataTreeWhere() {
let result = []
let selected = this.selected
let parentField = this.parentField
@@ -364,17 +419,35 @@ export default {
if (this.where) {
where.push(`(${this.where})`)
}
+
if (result.length) {
where.push(`(${result.join(' || ')})`)
}
return where.join(' && ')
},
- _nodeWhere() {
- let result = []
- let selected = this.selected
+
+ _cloudDataNodeWhere() {
+ let where = []
+ let selected = this.selected;
if (selected.length) {
- result.push(`${this.parentField} == '${selected[selected.length - 1].value}'`)
+ where.push(`${this.parentField} == '${selected[selected.length - 1].value}'`);
+ }
+
+ where = where.join(' || ');
+
+ if (this.where) {
+ return `(${this.where}) && (${where})`
+ }
+
+ return where
+ },
+
+ _getWhereByForeignKey() {
+ let result = []
+ let whereField = this._getForeignKeyByField();
+ if (whereField) {
+ result.push(`${whereField} == '${this.dataValue}'`)
}
if (this.where) {
@@ -383,41 +456,23 @@ export default {
return result.join(' || ')
},
- _getParentNameByField() {
- const fields = this.field.split(',');
- let where_field = null;
+
+ _getForeignKeyByField() {
+ let fields = this.field.split(',');
+ let whereField = null;
for (let i = 0; i < fields.length; i++) {
const items = fields[i].split('as');
if (items.length < 2) {
continue;
}
if (items[1].trim() === 'value') {
- where_field = items[0].trim();
+ whereField = items[0].trim();
break;
}
}
- return where_field
- },
- _isTreeView() {
- return (this.parentField && this.selfField)
- },
- _updateSelected() {
- var dl = this.dataList
- var sl = this.selected
- let textField = this.map.text
- let valueField = this.map.value
- for (var i = 0; i < sl.length; i++) {
- var value = sl[i].value
- var dl2 = dl[i]
- for (var j = 0; j < dl2.length; j++) {
- var item2 = dl2[j]
- if (item2[valueField] === value) {
- sl[i].text = item2[textField]
- break
- }
- }
- }
+ return whereField;
},
+
_updateBindData(node) {
const {
dataList,
@@ -445,6 +500,25 @@ export default {
hasNodes
}
},
+
+ _updateSelected() {
+ let dl = this.dataList
+ let sl = this.selected
+ let textField = this.map.text
+ let valueField = this.map.value
+ for (let i = 0; i < sl.length; i++) {
+ let value = sl[i].value
+ let dl2 = dl[i]
+ for (let j = 0; j < dl2.length; j++) {
+ let item2 = dl2[j]
+ if (item2[valueField] === value) {
+ sl[i].text = item2[textField]
+ break
+ }
+ }
+ }
+ },
+
_filterData(data, paths) {
let dataList = []
let hasNodes = true
@@ -453,8 +527,8 @@ export default {
return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '')
}))
for (let i = 0; i < paths.length; i++) {
- var value = paths[i].value
- var nodes = data.filter((item) => {
+ let value = paths[i].value
+ let nodes = data.filter((item) => {
return item.parent_value === value
})
@@ -470,6 +544,7 @@ export default {
hasNodes
}
},
+
_extractTree(nodes, result, parent_value) {
let list = result || []
let valueField = this.map.value
@@ -493,6 +568,7 @@ export default {
}
}
},
+
_extractTreePath(nodes, result) {
let list = result || []
for (let i = 0; i < nodes.length; i++) {
@@ -512,6 +588,7 @@ export default {
}
}
},
+
_findNodePath(key, nodes, path = []) {
let textField = this.map.text
let valueField = this.map.value
@@ -540,24 +617,6 @@ export default {
path.pop()
}
return []
- },
- _processLocalData() {
- this._treeData = []
- this._extractTree(this.localdata, this._treeData)
-
- var inputValue = this.dataValue
- if (inputValue === undefined) {
- return
- }
-
- if (Array.isArray(inputValue)) {
- inputValue = inputValue[inputValue.length - 1]
- if (typeof inputValue === 'object' && inputValue[this.map.value]) {
- inputValue = inputValue[this.map.value]
- }
- }
-
- this.selected = this._findNodePath(inputValue, this.localdata)
}
}
}
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
index f332950..6ebced9 100644
--- a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
@@ -1,182 +1,171 @@
-
-
-
-
-
- {{item.text}}
-
-
-
-
-
-
-
-
- {{item[map.text]}}
-
-
-
-
+
+
+
+
+ {{item.text || ''}}
+
+
+
+
+
+
+ {{item[map.text]}}
+
+
+
-
-
-
-
- {{errorMessage}}
-
-
-
+
+
+
+
+ {{errorMessage}}
+
+
+
+
diff --git a/uni_modules/uni-data-select/package.json b/uni_modules/uni-data-select/package.json
index c61afee..0187429 100644
--- a/uni_modules/uni-data-select/package.json
+++ b/uni_modules/uni-data-select/package.json
@@ -1,7 +1,7 @@
{
"id": "uni-data-select",
"displayName": "uni-data-select 下拉框选择器",
- "version": "1.0.3",
+ "version": "1.0.6",
"description": "通过数据驱动的下拉框选择器",
"keywords": [
"uni-ui",
diff --git a/uni_modules/uni-datetime-picker/changelog.md b/uni_modules/uni-datetime-picker/changelog.md
index 953afea..47e3ccf 100644
--- a/uni_modules/uni-datetime-picker/changelog.md
+++ b/uni_modules/uni-datetime-picker/changelog.md
@@ -1,3 +1,17 @@
+## 2.2.23(2023-05-02)
+- 修复 部分情况修改时间,开始时间未更新 [详情](https://github.com/dcloudio/uni-ui/issues/737)
+- 修复 部分平台及设备第一次点击无法显示弹框
+- 修复 ios 日期格式未补零显示及使用异常 [详情](https://ask.dcloud.net.cn/question/162979)
+## 2.2.22(2023-03-30)
+- 修复 日历 picker 修改年月后,自动选中当月1日 [详情](https://ask.dcloud.net.cn/question/165937)
+- 修复 小程序端 低版本 ios NaN [详情](https://ask.dcloud.net.cn/question/162979)
+## 2.2.21(2023-02-20)
+- 修复 firefox 浏览器显示区域点击无法拉起日历弹框的Bug [详情](https://ask.dcloud.net.cn/question/163362)
+## 2.2.20(2023-02-17)
+- 优化 值为空依然选中当天问题
+- 优化 提供 default-value 属性支持配置选择器打开时默认显示的时间
+- 优化 非范围选择未选择日期时间,点击确认按钮选中当前日期时间
+- 优化 字节小程序日期时间范围选择,底部日期换行问题
## 2.2.19(2023-02-09)
- 修复 2.2.18 引起范围选择配置 end 选择无效的Bug [详情](https://github.com/dcloudio/uni-ui/issues/686)
## 2.2.18(2023-02-08)
diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
index 1b1a2eb..dba9887 100644
--- a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
+++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
@@ -13,10 +13,10 @@
'uni-calendar-item--after-checked':weeks.afterMultiple,
'uni-calendar-item--disable':weeks.disable,
}">
-
+
{{weeks.date}}
-
+
@@ -41,10 +41,6 @@
return []
}
},
- lunar: {
- type: Boolean,
- default: false
- },
checkHover: {
type: Boolean,
default: false
@@ -83,11 +79,6 @@
color: darken($color: $uni-primary, $amount: 40%);
}
- .uni-calendar-item__weeks-lunar-text {
- font-size: 12px;
- color: #333;
- }
-
.uni-calendar-item__weeks-box-item {
position: relative;
/* #ifndef APP-NVUE */
@@ -123,7 +114,7 @@
color: #D1D1D1;
}
- .uni-calendar-item--isDay {
+ .uni-calendar-item--today {
position: absolute;
top: 10px;
right: 17%;
diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
index d226154..2932a91 100644
--- a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
+++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
@@ -1,29 +1,37 @@
-
+
+
+
@@ -890,7 +833,11 @@
padding-left: 3px;
}
.range-separator{
+ height: 35px;
+ /* #ifndef MP */
padding: 0 2px;
+ /* #endif */
+ line-height: 35px;
}
}
@@ -917,15 +864,18 @@
.uni-date__x-input {
width: auto;
- position: relative;
- overflow: hidden;
- flex: 1;
- line-height: 1;
- font-size: 14px;
height: 35px;
+ /* #ifndef MP */
+ padding-left: 5px;
+ /* #endif */
+ position: relative;
+ flex: 1;
+ line-height: 35px;
+ font-size: 14px;
+ overflow: hidden;
}
- .t-c {
+ .text-center {
text-align: center;
}
@@ -962,7 +912,7 @@
top: 0;
z-index: 999;
border: 1px solid #EBEEF5;
- box-shadow: 0px 0px 3px 0px rgba(0, 82, 79, 0.65);
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
}
@@ -972,7 +922,7 @@
top: 0;
z-index: 999;
border: 1px solid #EBEEF5;
- box-shadow: 0px 0px 3px 0px rgba(0, 82, 79, 0.65);
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
}
@@ -1023,7 +973,7 @@
opacity: 0.8;
}
- .popup-x-footer .confirm {
+ .popup-x-footer .confirm-text {
margin-left: 20px;
color: $uni-primary;
}
diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
index 1afdaa9..ab40b23 100644
--- a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
+++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
@@ -1,27 +1,24 @@
class Calendar {
constructor({
- date,
selected,
startDate,
endDate,
range,
- // multipleStatus
} = {}) {
// 当前日期
- this.date = this.getDate(new Date()) // 当前初入日期
+ this.date = this.getDateObj(new Date()) // 当前初入日期
// 打点信息
this.selected = selected || [];
- // 范围开始
+ // 起始时间
this.startDate = startDate
- // 范围结束
+ // 终止时间
this.endDate = endDate
+ // 是否范围选择
this.range = range
// 多选状态
this.cleanMultipleStatus()
// 每周日期
this.weeks = {}
- // this._getWeek(this.date.fullDate)
- // this.multipleStatus = multipleStatus
this.lastHover = false
}
/**
@@ -29,8 +26,8 @@ class Calendar {
* @param {Object} date
*/
setDate(date) {
- this.selectDate = this.getDate(date)
- this._getWeek(this.selectDate.fullDate)
+ const selectDate = this.getDateObj(date)
+ this.getWeeks(selectDate.fullDate)
}
/**
@@ -44,103 +41,82 @@ class Calendar {
}
}
- /**
- * 重置开始日期
- */
- resetSatrtDate(startDate) {
- // 范围开始
+ setStartDate(startDate) {
this.startDate = startDate
-
}
- /**
- * 重置结束日期
- */
- resetEndDate(endDate) {
- // 范围结束
+ setEndDate(endDate) {
this.endDate = endDate
}
+ getPreMonthObj(date){
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+
+ const oldMonth = date.getMonth()
+ date.setMonth(oldMonth - 1)
+ const newMonth = date.getMonth()
+ if(oldMonth !== 0 && newMonth - oldMonth === 0){
+ date.setMonth(newMonth - 1)
+ }
+ return this.getDateObj(date)
+ }
+ getNextMonthObj(date){
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+
+ const oldMonth = date.getMonth()
+ date.setMonth(oldMonth + 1)
+ const newMonth = date.getMonth()
+ if(newMonth - oldMonth > 1){
+ date.setMonth(newMonth - 1)
+ }
+ return this.getDateObj(date)
+ }
+
/**
- * 获取任意时间
+ * 获取指定格式Date对象
*/
- getDate(date, AddDayCount = 0, str = 'day') {
- if (!date) {
- date = new Date()
- }
- if (typeof date !== 'object') {
- date = date.replace(/-/g, '/')
- }
- const dd = new Date(date)
- switch (str) {
- case 'day':
- dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
- break
- case 'month':
- if (dd.getDate() === 31 && AddDayCount>0) {
- dd.setDate(dd.getDate() + AddDayCount)
- } else {
- const preMonth = dd.getMonth()
- dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期
- const nextMonth = dd.getMonth()
- // 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
- if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){
- dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount))
- }
- // 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
- if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){
- dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount))
- }
- }
- break
- case 'year':
- dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
- break
- }
- const y = dd.getFullYear()
- const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
- const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
+ getDateObj(date) {
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+
return {
- fullDate: y + '-' + m + '-' + d,
- year: y,
- month: m,
- date: d,
- day: dd.getDay()
+ fullDate: getDate(date),
+ year: date.getFullYear(),
+ month: addZero(date.getMonth() + 1),
+ date: addZero(date.getDate()),
+ day: date.getDay()
}
}
-
/**
- * 获取上月剩余天数
+ * 获取上一个月日期集合
*/
- _getLastMonthDays(firstDay, full) {
- let dateArr = []
- for (let i = firstDay; i > 0; i--) {
- const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
- dateArr.push({
- date: beforeDate,
- month: full.month - 1,
+ getPreMonthDays(amount, dateObj) {
+ const result = []
+ for (let i = amount - 1; i >= 0; i--) {
+ const month = dateObj.month - 1
+ result.push({
+ date: new Date(dateObj.year, month, -i).getDate(),
+ month,
disable: true
})
}
- return dateArr
+ return result
}
/**
- * 获取本月天数
+ * 获取本月日期集合
*/
- _currentMonthDys(dateData, full) {
- let dateArr = []
- let fullDate = this.date.fullDate
- for (let i = 1; i <= dateData; i++) {
- let isinfo = false
- let nowDate = full.year + '-' + (full.month < 10 ?
- full.month : full.month) + '-' + (i < 10 ?
- '0' + i : i)
- // 是否今天
- let isDay = fullDate === nowDate
+ getCurrentMonthDays(amount, dateObj) {
+ const result = []
+ const fullDate = this.date.fullDate
+ for (let i = 1; i <= amount; i++) {
+ const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}`
+ const isToday = fullDate === currentDate
// 获取打点信息
- let info = this.selected && this.selected.find((item) => {
- if (this.dateEqual(nowDate, item.date)) {
+ const info = this.selected && this.selected.find((item) => {
+ if (this.dateEqual(currentDate, item.date)) {
return item
}
})
@@ -149,62 +125,52 @@ class Calendar {
let disableBefore = true
let disableAfter = true
if (this.startDate) {
- // let dateCompBefore = this.dateCompare(this.startDate, fullDate)
- // disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
- disableBefore = this.dateCompare(this.startDate, nowDate)
+ disableBefore = dateCompare(this.startDate, currentDate)
}
if (this.endDate) {
- // let dateCompAfter = this.dateCompare(fullDate, this.endDate)
- // disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
- disableAfter = this.dateCompare(nowDate, this.endDate)
- }
- let multiples = this.multipleStatus.data
- let checked = false
- let multiplesStatus = -1
- if (this.range) {
- if (multiples) {
- multiplesStatus = multiples.findIndex((item) => {
- return this.dateEqual(item, nowDate)
- })
- }
- if (multiplesStatus !== -1) {
- checked = true
- }
- }
- let data = {
- fullDate: nowDate,
- year: full.year,
- date: i,
- multiple: this.range ? checked : false,
- beforeMultiple: this.isLogicBefore(nowDate, this.multipleStatus.before, this.multipleStatus.after),
- afterMultiple: this.isLogicAfter(nowDate, this.multipleStatus.before, this.multipleStatus.after),
- month: full.month,
- disable: !(disableBefore && disableAfter),
- isDay,
- userChecked: false
- }
- if (info) {
- data.extraInfo = info
+ disableAfter = dateCompare(currentDate, this.endDate)
}
- dateArr.push(data)
+ let multiples = this.multipleStatus.data
+ let multiplesStatus = -1
+ if (this.range && multiples) {
+ multiplesStatus = multiples.findIndex((item) => {
+ return this.dateEqual(item, currentDate)
+ })
+ }
+ const checked = multiplesStatus !== -1
+
+ result.push({
+ fullDate: currentDate,
+ year: dateObj.year,
+ date: i,
+ multiple: this.range ? checked : false,
+ beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after),
+ afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after),
+ month: dateObj.month,
+ disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(currentDate,this.endDate)),
+ isToday,
+ userChecked: false,
+ extraInfo: info
+ })
}
- return dateArr
+ return result
}
/**
- * 获取下月天数
+ * 获取下一个月日期集合
*/
- _getNextMonthDays(surplus, full) {
- let dateArr = []
- for (let i = 1; i < surplus + 1; i++) {
- dateArr.push({
+ _getNextMonthDays(amount, dateObj) {
+ const result = []
+ const month = dateObj.month + 1
+ for (let i = 1; i <= amount; i++) {
+ result.push({
date: i,
- month: Number(full.month) + 1,
+ month,
disable: true
})
}
- return dateArr
+ return result
}
/**
@@ -215,58 +181,37 @@ class Calendar {
if (!date) {
date = new Date()
}
- const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
- return dateInfo
- }
- /**
- * 比较时间大小
- */
- dateCompare(startDate, endDate) {
- // 计算截止时间
- startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
- // 计算详细项的截止时间
- endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
- if (startDate <= endDate) {
- return true
- } else {
- return false
- }
+ return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate)
}
/**
* 比较时间是否相等
*/
dateEqual(before, after) {
- // 计算截止时间
- before = new Date(before.replace('-', '/').replace('-', '/'))
- // 计算详细项的截止时间
- after = new Date(after.replace('-', '/').replace('-', '/'))
- if (before.getTime() - after.getTime() === 0) {
- return true
- } else {
- return false
- }
+ before = new Date(fixIosDateFormat(before))
+ after = new Date(fixIosDateFormat(after))
+ return before.valueOf() === after.valueOf()
}
/**
* 比较真实起始日期
*/
- isLogicBefore(currentDay, before, after) {
+ isLogicBefore(currentDate, before, after) {
let logicBefore = before
if (before && after) {
- logicBefore = this.dateCompare(before, after) ? before : after
+ logicBefore = dateCompare(before, after) ? before : after
}
- return this.dateEqual(logicBefore, currentDay)
+ return this.dateEqual(logicBefore, currentDate)
}
- isLogicAfter(currentDay, before, after) {
+ isLogicAfter(currentDate, before, after) {
let logicAfter = after
if (before && after) {
- logicAfter = this.dateCompare(before, after) ? after : before
+ logicAfter = dateCompare(before, after) ? after : before
}
- return this.dateEqual(logicAfter, currentDay)
+ return this.dateEqual(logicAfter, currentDate)
}
/**
@@ -286,7 +231,7 @@ class Calendar {
var unixDe = de.getTime() - 24 * 60 * 60 * 1000
for (var k = unixDb; k <= unixDe;) {
k = k + 24 * 60 * 60 * 1000
- arr.push(this.getDate(new Date(parseInt(k))).fullDate)
+ arr.push(this.getDateObj(new Date(parseInt(k))).fullDate)
}
return arr
}
@@ -295,11 +240,12 @@ class Calendar {
* 获取多选状态
*/
setMultiple(fullDate) {
+ if (!this.range) return
+
let {
before,
after
} = this.multipleStatus
- if (!this.range) return
if (before && after) {
if (!this.lastHover) {
this.lastHover = true
@@ -316,7 +262,7 @@ class Calendar {
this.lastHover = false
} else {
this.multipleStatus.after = fullDate
- if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+ if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
.after);
} else {
@@ -326,32 +272,28 @@ class Calendar {
this.lastHover = true
}
}
- this._getWeek(fullDate)
+ this.getWeeks(fullDate)
}
/**
* 鼠标 hover 更新多选状态
*/
setHoverMultiple(fullDate) {
- let {
- before,
- after
- } = this.multipleStatus
+ if (!this.range || this.lastHover) return
- if (!this.range) return
- if (this.lastHover) return
+ const { before } = this.multipleStatus
if (!before) {
this.multipleStatus.before = fullDate
} else {
this.multipleStatus.after = fullDate
- if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+ if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
}
}
- this._getWeek(fullDate)
+ this.getWeeks(fullDate)
}
/**
@@ -361,12 +303,12 @@ class Calendar {
this.multipleStatus.before = before
this.multipleStatus.after = after
if (before && after) {
- if (this.dateCompare(before, after)) {
+ if (dateCompare(before, after)) {
this.multipleStatus.data = this.geDateAll(before, after);
- this._getWeek(after)
+ this.getWeeks(after)
} else {
this.multipleStatus.data = this.geDateAll(after, before);
- this._getWeek(before)
+ this.getWeeks(before)
}
}
}
@@ -375,46 +317,87 @@ class Calendar {
* 获取每周数据
* @param {Object} dateData
*/
- _getWeek(dateData) {
+ getWeeks(dateData) {
const {
- fullDate,
year,
month,
- date,
- day
- } = this.getDate(dateData)
- let firstDay = new Date(year, month - 1, 1).getDay()
- let currentDay = new Date(year, month, 0).getDate()
- let dates = {
- lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
- currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
- nextMonthDays: [], // 下个月开始几天
- weeks: []
+ } = this.getDateObj(dateData)
+
+ const preMonthDayAmount = new Date(year, month - 1, 1).getDay()
+ const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData))
+
+ const currentMonthDayAmount = new Date(year, month, 0).getDate()
+ const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData))
+
+ const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount
+ const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData))
+
+ const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays]
+
+ const weeks = new Array(6)
+ for (let i = 0; i < calendarDays.length; i++) {
+ const index = Math.floor(i / 7)
+ if(!weeks[index]){
+ weeks[index] = new Array(7)
+ }
+ weeks[index][i % 7] = calendarDays[i]
}
- let canlender = []
- const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
- dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
- canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
- let weeks = {}
- // 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
- for (let i = 0; i < canlender.length; i++) {
- if (i % 7 === 0) {
- weeks[parseInt(i / 7)] = new Array(7)
- }
- weeks[parseInt(i / 7)][i % 7] = canlender[i]
- }
- this.canlender = canlender
+
+ this.calendar = calendarDays
this.weeks = weeks
}
-
- //静态方法
- // static init(date) {
- // if (!this.instance) {
- // this.instance = new Calendar(date);
- // }
- // return this.instance;
- // }
}
+function getDateTime(date, hideSecond){
+ return `${getDate(date)} ${getTime(date, hideSecond)}`
+}
-export default Calendar
+function getDate(date) {
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+ const year = date.getFullYear()
+ const month = date.getMonth()+1
+ const day = date.getDate()
+ return `${year}-${addZero(month)}-${addZero(day)}`
+}
+
+function getTime(date, hideSecond){
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+ const hour = date.getHours()
+ const minute = date.getMinutes()
+ const second = date.getSeconds()
+ return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}`
+}
+
+function addZero(num) {
+ if(num < 10){
+ num = `0${num}`
+ }
+ return num
+}
+
+function getDefaultSecond(hideSecond) {
+ return hideSecond ? '00:00' : '00:00:00'
+}
+
+function dateCompare(startDate, endDate) {
+ startDate = new Date(fixIosDateFormat(startDate))
+ endDate = new Date(fixIosDateFormat(endDate))
+ return startDate <= endDate
+}
+
+function checkDate(date){
+ const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g
+ return date.match(dateReg)
+}
+
+const dateTimeReg = /^\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])( [0-5]?[0-9]:[0-5]?[0-9]:[0-5]?[0-9])?$/
+function fixIosDateFormat(value) {
+ if (typeof value === 'string' && dateTimeReg.test(value)) {
+ value = value.replace(/-/g, '/')
+ }
+ return value
+}
+
+export {Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat}
\ No newline at end of file
diff --git a/uni_modules/uni-datetime-picker/package.json b/uni_modules/uni-datetime-picker/package.json
index 2ec840e..bc2378f 100644
--- a/uni_modules/uni-datetime-picker/package.json
+++ b/uni_modules/uni-datetime-picker/package.json
@@ -1,7 +1,7 @@
{
"id": "uni-datetime-picker",
"displayName": "uni-datetime-picker 日期选择器",
- "version": "2.2.19",
+ "version": "2.2.23",
"description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
"keywords": [
"uni-datetime-picker",
diff --git a/uni_modules/uni-easyinput/changelog.md b/uni_modules/uni-easyinput/changelog.md
index 33130c6..765401a 100644
--- a/uni_modules/uni-easyinput/changelog.md
+++ b/uni_modules/uni-easyinput/changelog.md
@@ -1,53 +1,97 @@
-## 1.1.3(2022-09-22)
-- 修复,引入 uni.scss 引入默认主题色报错的问题
-## 1.1.2(2022-09-22)
-- 增加主题色 primaryColor 配置选项
-## 1.1.1(2022-09-19)
-- 修复,输入后回车,change 事件触发两次,[详情](https://ask.dcloud.net.cn/question/152149)
+## 1.1.9(2023-04-11)
+- 修复 vue3 下 keyboardheightchange 事件报错的bug
+## 1.1.8(2023-03-29)
+- 优化 trim 属性默认值
+## 1.1.7(2023-03-29)
+- 新增 cursor-spacing 属性
+## 1.1.6(2023-01-28)
+- 新增 keyboardheightchange 事件,可监听键盘高度变化
+## 1.1.5(2022-11-29)
+- 优化 主题样式
+## 1.1.4(2022-10-27)
+- 修复 props 中背景颜色无默认值的bug
## 1.1.0(2022-06-30)
+
- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
- 新增 clear 事件,点击右侧叉号图标触发
- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
--
+
## 1.0.5(2022-06-07)
+
- 优化 clearable 显示策略
+
## 1.0.4(2022-06-07)
+
- 优化 clearable 显示策略
+
## 1.0.3(2022-05-20)
-- 修复 关闭图标某些情况下无法取消的bug
+
+- 修复 关闭图标某些情况下无法取消的 bug
+
## 1.0.2(2022-04-12)
-- 修复 默认值不生效的bug
+
+- 修复 默认值不生效的 bug
+
## 1.0.1(2022-04-02)
-- 修复 value不能为0的bug
+
+- 修复 value 不能为 0 的 bug
+
## 1.0.0(2021-11-19)
-- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+
+- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
+
## 0.1.4(2021-08-20)
+
- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug
+
## 0.1.3(2021-08-11)
+
- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题
+
## 0.1.2(2021-07-30)
-- 优化 vue3下事件警告的问题
+
+- 优化 vue3 下事件警告的问题
+
## 0.1.1
+
- 优化 errorMessage 属性支持 Boolean 类型
+
## 0.1.0(2021-07-13)
-- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+
+- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+
## 0.0.16(2021-06-29)
+
- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug
+
## 0.0.15(2021-06-21)
+
- 修复 passwordIcon 属性拼写错误的 bug
+
## 0.0.14(2021-06-18)
-- 新增 passwordIcon 属性,当type=password时是否显示小眼睛图标
+
+- 新增 passwordIcon 属性,当 type=password 时是否显示小眼睛图标
- 修复 confirmType 属性不生效的问题
+
## 0.0.13(2021-06-04)
+
- 修复 disabled 状态可清出内容的 bug
+
## 0.0.12(2021-05-12)
+
- 新增 组件示例地址
+
## 0.0.11(2021-05-07)
+
- 修复 input-border 属性不生效的问题
+
## 0.0.10(2021-04-30)
+
- 修复 ios 遮挡文字、显示一半的问题
+
## 0.0.9(2021-02-05)
-- 调整为uni_modules目录规范
+
+- 调整为 uni_modules 目录规范
- 优化 兼容 nvue 页面
diff --git a/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
index 75374a5..2c7993a 100644
--- a/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
+++ b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
@@ -1,34 +1,74 @@
-
+
-
-
-
+
+
+
-
-
+
-
+
-
+
@@ -36,570 +76,582 @@
diff --git a/uni_modules/uni-easyinput/package.json b/uni_modules/uni-easyinput/package.json
index 4ca4200..bd128e1 100644
--- a/uni_modules/uni-easyinput/package.json
+++ b/uni_modules/uni-easyinput/package.json
@@ -1,7 +1,7 @@
{
"id": "uni-easyinput",
"displayName": "uni-easyinput 增强输入框",
- "version": "1.1.3",
+ "version": "1.1.9",
"description": "Easyinput 组件是对原生input组件的增强",
"keywords": [
"uni-ui",
diff --git a/uni_modules/uni-fab/changelog.md b/uni_modules/uni-fab/changelog.md
index 0048ff9..9bd4729 100644
--- a/uni_modules/uni-fab/changelog.md
+++ b/uni_modules/uni-fab/changelog.md
@@ -1,3 +1,5 @@
+## 1.2.5(2023-03-29)
+- 新增 pattern.icon 属性,可自定义图标
## 1.2.4(2022-09-07)
小程序端由于 style 使用了对象导致报错,[详情](https://ask.dcloud.net.cn/question/152790?item_id=211778&rf=false)
## 1.2.3(2022-09-05)
diff --git a/uni_modules/uni-fab/components/uni-fab/uni-fab.vue b/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
index 96c4739..dfa65c1 100644
--- a/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
+++ b/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
@@ -35,7 +35,7 @@
'uni-fab__circle--rightTop': rightTop,
'uni-fab__content--other-platform': !isAndroidNvue
}" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor, 'bottom': nvueBottom }" @click="_onClick">
-
@@ -115,7 +115,8 @@
selectedColor: '#007AFF',
backgroundColor: '#fff',
buttonColor: '#007AFF',
- iconColor: '#fff'
+ iconColor: '#fff',
+ icon: 'plusempty'
}
}
},
@@ -206,6 +207,9 @@
* 按钮点击事件
*/
_onItemClick(index, item) {
+ if (!this.isShow) {
+ return
+ }
this.$emit('trigger', {
index,
item
diff --git a/uni_modules/uni-fab/package.json b/uni_modules/uni-fab/package.json
index 6636170..18c0810 100644
--- a/uni_modules/uni-fab/package.json
+++ b/uni_modules/uni-fab/package.json
@@ -1,7 +1,7 @@
{
"id": "uni-fab",
"displayName": "uni-fab 悬浮按钮",
- "version": "1.2.4",
+ "version": "1.2.5",
"description": "悬浮按钮 fab button ,点击可展开一个图标按钮菜单。",
"keywords": [
"uni-ui",
diff --git a/uni_modules/uni-file-picker/changelog.md b/uni_modules/uni-file-picker/changelog.md
index e1621c3..b8230e9 100644
--- a/uni_modules/uni-file-picker/changelog.md
+++ b/uni_modules/uni-file-picker/changelog.md
@@ -1,4 +1,6 @@
-## 1.0.3(2022-12-21)
+## 1.0.4(2023-03-29)
+- 修复 手动上传删除一个文件后不能再上传的bug
+## 1.0.3(2022-12-19)
- 新增 sourceType 属性, 可以自定义图片和视频选择的来源
## 1.0.2(2022-07-04)
- 修复 在uni-forms下样式不生效的bug
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue b/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
index 9bb9829..370441d 100644
--- a/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
@@ -583,7 +583,11 @@
path: v.path,
size: v.size,
fileID:v.fileID,
- url: v.url
+ url: v.url,
+ // 修改删除一个文件后不能再上传的bug, #694
+ uuid: v.uuid,
+ status: v.status,
+ cloudPath: v.cloudPath
})
})
return newFilesData
diff --git a/uni_modules/uni-file-picker/package.json b/uni_modules/uni-file-picker/package.json
index c93b634..35c926c 100644
--- a/uni_modules/uni-file-picker/package.json
+++ b/uni_modules/uni-file-picker/package.json
@@ -1,7 +1,7 @@
{
"id": "uni-file-picker",
"displayName": "uni-file-picker 文件选择上传",
- "version": "1.0.3",
+ "version": "1.0.4",
"description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间",
"keywords": [
"uni-ui",
@@ -16,11 +16,7 @@
"directories": {
"example": "../../temps/example_temps"
},
- "dcloudext": {
- "category": [
- "前端组件",
- "通用组件"
- ],
+"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
@@ -37,7 +33,8 @@
"data": "无",
"permissions": "无"
},
- "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
},
"uni_modules": {
"dependencies": ["uni-scss"],
diff --git a/uni_modules/uni-forms/changelog.md b/uni_modules/uni-forms/changelog.md
index c358a21..8218df5 100644
--- a/uni_modules/uni-forms/changelog.md
+++ b/uni_modules/uni-forms/changelog.md
@@ -1,3 +1,5 @@
+## 1.4.9(2023-02-10)
+- 修复 required 参数无法动态绑定
## 1.4.8(2022-08-23)
- 优化 根据 rules 自动添加 required 的问题
## 1.4.7(2022-08-22)
diff --git a/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
index ce7c460..91fe351 100644
--- a/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
+++ b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
@@ -2,9 +2,9 @@
-
- *
+ *
{{label}}
@@ -126,7 +126,6 @@
data() {
return {
errMsg: '',
- isRequired: false,
userRules: null,
localLabelAlign: 'left',
localLabelWidth: '65px',
@@ -315,7 +314,6 @@
this.localLabelWidth = this._labelWidthUnit(labelWidth)
// 标签位置
this.localLabelPos = this._labelPosition()
- this.isRequired = this.required
// 将需要校验的子组件加入form 队列
this.form && type && childrens.push(this)
@@ -351,8 +349,6 @@
this.validator = validator
// 默认值赋予
this.itemSetValue(_getDataValue(this.name, localData))
- this.isRequired = this._isRequired()
-
},
unInit() {
if (this.form) {
diff --git a/uni_modules/uni-forms/package.json b/uni_modules/uni-forms/package.json
index e3736c4..1925611 100644
--- a/uni_modules/uni-forms/package.json
+++ b/uni_modules/uni-forms/package.json
@@ -1,7 +1,7 @@
{
"id": "uni-forms",
"displayName": "uni-forms 表单",
- "version": "1.4.8",
+ "version": "1.4.9",
"description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据",
"keywords": [
"uni-ui",
diff --git a/uni_modules/uni-icons/changelog.md b/uni_modules/uni-icons/changelog.md
index 6449885..0261131 100644
--- a/uni_modules/uni-icons/changelog.md
+++ b/uni_modules/uni-icons/changelog.md
@@ -1,3 +1,23 @@
+## 2.0.10(2024-06-07)
+- 优化 uni-app x 中,size 属性的类型
+## 2.0.9(2024-01-12)
+fix: 修复图标大小默认值错误的问题
+## 2.0.8(2023-12-14)
+- 修复 项目未使用 ts 情况下,打包报错的bug
+## 2.0.7(2023-12-14)
+- 修复 size 属性为 string 时,不加单位导致尺寸异常的bug
+## 2.0.6(2023-12-11)
+- 优化 兼容老版本icon类型,如 top ,bottom 等
+## 2.0.5(2023-12-11)
+- 优化 兼容老版本icon类型,如 top ,bottom 等
+## 2.0.4(2023-12-06)
+- 优化 uni-app x 下示例项目图标排序
+## 2.0.3(2023-12-06)
+- 修复 nvue下引入组件报错的bug
+## 2.0.2(2023-12-05)
+-优化 size 属性支持单位
+## 2.0.1(2023-12-05)
+- 新增 uni-app x 支持定义图标
## 1.3.5(2022-01-24)
- 优化 size 属性可以传入不带单位的字符串数值
## 1.3.4(2022-01-24)
diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue b/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
new file mode 100644
index 0000000..8740559
--- /dev/null
+++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
@@ -0,0 +1,91 @@
+
+
+ {{unicode}}
+
+
+
+
+
+
diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
index 86e7444..7da5356 100644
--- a/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
+++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
@@ -1,24 +1,28 @@
- {{unicode}}
+ {{unicode}}
-
+
+
+
diff --git a/uni_modules/uni-table/components/uni-th/uni-th.vue b/uni_modules/uni-table/components/uni-th/uni-th.vue
index 883e3f2..14889dd 100644
--- a/uni_modules/uni-table/components/uni-th/uni-th.vue
+++ b/uni_modules/uni-table/components/uni-th/uni-th.vue
@@ -9,7 +9,7 @@
-
+
@@ -79,6 +79,12 @@ export default {
default () {
return []
}
+ },
+ filterDefaultValue: {
+ type: [Array,String],
+ default () {
+ return ""
+ }
}
},
data() {
@@ -200,6 +206,7 @@ export default {
+
\ No newline at end of file
diff --git a/uni_modules/uni-upgrade-center-app/readme.md b/uni_modules/uni-upgrade-center-app/readme.md
index 048fe3a..3e830b5 100644
--- a/uni_modules/uni-upgrade-center-app/readme.md
+++ b/uni_modules/uni-upgrade-center-app/readme.md
@@ -22,9 +22,9 @@
3. 在插件市场打开本插件页面,在右侧点击`使用 HBuilderX 导入插件`,选择要导入的项目点击确定
-4. 绑定一个服务空间
+4. 绑定一个服务空间。自 `0.6.0` 起,依赖 `uni-admin 1.9.3+` 的 `uni-upgrade-center 云函数`,请和 uni-admin 项目关联同一个服务空间
-5. 找到`/uni_modules/uni-upgrade-center-app/uniCloud/cloudfunctions/check-version`,右键上传部署
+5. 找到`/uni_modules/uni-upgrade-center-app/uniCloud/cloudfunctions/check-version`,右键上传部署。自 `0.6.0` 起,依赖 `uni-admin 1.9.3+` 的 `uni-upgrade-center 云函数`,插件不再单独提供云函数,这样可以省下一个云函数名额。
6. 在`pages.json`中添加页面路径。**注:请不要设置为pages.json中第一项**
```json
diff --git a/uni_modules/uni-upgrade-center-app/uniCloud/database/db_init.json b/uni_modules/uni-upgrade-center-app/uniCloud/database/db_init.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/uni_modules/uni-upgrade-center-app/uniCloud/database/db_init.json
@@ -0,0 +1 @@
+{}
diff --git a/uni_modules/uni-upgrade-center-app/utils/call-check-version.js b/uni_modules/uni-upgrade-center-app/utils/call-check-version.js
index 31938cb..3dc7d07 100644
--- a/uni_modules/uni-upgrade-center-app/utils/call-check-version.js
+++ b/uni_modules/uni-upgrade-center-app/utils/call-check-version.js
@@ -2,13 +2,13 @@ export default function() {
// #ifdef APP-PLUS
return new Promise((resolve, reject) => {
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
- const data = {
+ console.log('哈哈哈哈', widgetInfo)
+ let data = {
action: 'checkVersion',
appid: plus.runtime.appid,
appVersion: plus.runtime.version,
wgtVersion: widgetInfo.version
}
- console.log("获取当前版本信息data: ",data);
uniCloud.callFunction({
name: 'uni-upgrade-center',
data,
@@ -30,4 +30,4 @@ export default function() {
})
})
// #endif
-}
+}
\ No newline at end of file
diff --git a/uni_modules/uni-upgrade-center-app/utils/check-update.js b/uni_modules/uni-upgrade-center-app/utils/check-update.js
index 38fe7b0..2ff9b1d 100644
--- a/uni_modules/uni-upgrade-center-app/utils/check-update.js
+++ b/uni_modules/uni-upgrade-center-app/utils/check-update.js
@@ -7,6 +7,7 @@ export default function() {
// #ifdef APP-PLUS
return new Promise((resolve, reject) => {
callCheckVersion().then(async (e) => {
+ console.log('hhhhhhhhhhhh', e)
if (!e.result) return;
const {
code,
@@ -64,7 +65,7 @@ export default function() {
uni.removeStorageSync(PACKAGE_INFO_KEY)
}
})
-
+
return
} else if (code < 0) {
// TODO 云函数报错处理
@@ -155,4 +156,4 @@ function updateUseModal(packageInfo) {
});
}
});
-}
+}
\ No newline at end of file
diff --git a/uni_modules/uni-upgrade-center/changelog.md b/uni_modules/uni-upgrade-center/changelog.md
new file mode 100644
index 0000000..3d9885a
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/changelog.md
@@ -0,0 +1,51 @@
+## 0.6.0(2023-02-24)
+- 修复 升级中心安卓应用市场不显示的Bug
+## 0.5.1(2022-07-06)
+- 修复 上版带出云函数不存在的Bug
+- 升级 uni-admin 大于等于 1.9.0 务必更新至此版本。uni-admin 版本小于 1.9.0 请不要更新,历史版本在 Gitee 有发行版。后续 uni-admin 会集成升级中心
+## 0.5.0(2022-07-05)
+- 修复 版本列表默认显示全部版本的Bug
+- 升级 uni-admin 1.9.0 务必更新至此版本。uni-admin 版本小于 1.9.0 请不要更新,后续 uni-admin 会集成升级中心
+
+## 0.4.2(2021-12-07)
+- 更新 优化 list 页面显示,修复 list 页面报错
+## 0.4.1(2021-12-01)
+- 修复 0.4.0版本带出来,发布新版时 appid、name 不会自动填充的Bug
+## 0.4.0(2021-11-26)
+- 更新 升级中心移除应用管理,现在由uni-admin接管。旧版本若没有应用管理请做升级处理
+## 0.3.0(2021-11-18)
+- 兼容 uni-admin 新版内置 $request 函数改动
+## 0.2.2(2021-09-06)
+- 解决 opendb-app-list表对应的schema名称冲突的问题
+## 0.2.1(2021-09-03)
+- 修复 一个在添加菜单时报错,createdate不与默认值匹配 的Bug
+## 0.2.0(2021-08-25)
+- 兼容vue3.0
+## 0.1.9(2021-08-13)
+- 更新 uni-forms使用validate校验字段
+- 修复 报错dirty_data、create_date在数据库中并不存在
+## 0.1.8(2021-08-09)
+- 修复 默认配置项配置错误
+## 0.1.7(2021-08-09)
+- 移除测试时配置项
+## 0.1.6(2021-08-09)
+- 修复 修改版本信息时,上传时间丢失问题
+## 0.1.5(2021-07-21)
+- 更新 :value.sync 改为 :value 和 @update:value
+## 0.1.4(2021-07-13)
+- 修复 uni-easyinput去除输入字符长度限制
+- 更新文档 关于 uni-id缺少配置信息 错误。请查看安装指引第13条
+## 0.1.3(2021-06-15)
+- 修复 wgt更新某些情况下获取数据错误
+## 0.1.2(2021-06-04)
+- 修复 上传包时根据平台筛选文件
+- 更新 文档
+## 0.1.1(2021-05-18)
+- 更新uni-table中uni-tr组件的selectable属性为disabled
+## 0.1.0(2021-04-07)
+- 更新版本对比函数 compare
+## 0.0.6(2021-04-01)
+- 调整db_init.json
+## 0.0.5(2021-03-25)
+- 调整为uni_modules目录
+- 升级中心后台管理系统拆分为 Admin 后台管理 和 前台检查更新(uni-upgrade-center-app)
diff --git a/uni_modules/uni-upgrade-center/package.json b/uni_modules/uni-upgrade-center/package.json
new file mode 100644
index 0000000..73e401e
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/package.json
@@ -0,0 +1,91 @@
+{
+ "id": "uni-upgrade-center",
+ "displayName": "升级中心 uni-upgrade-center - Admin",
+ "version": "0.6.0",
+ "description": "uni升级中心 - 后台管理系统",
+ "keywords": [
+ "uniCloud",
+ "admin",
+ "update",
+ "升级",
+ "wgt"
+],
+ "repository": "https://gitee.com/dcloud/uni-upgrade-center/tree/master/uni_modules/uni-upgrade-center",
+ "engines": {
+ "HBuilderX": "^3.3.10"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "插件不采集任何数据",
+ "permissions": "无"
+ },
+ "npmurl": "",
+ "type": "unicloud-admin"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-data-checkbox",
+ "uni-data-picker",
+ "uni-dateformat",
+ "uni-easyinput",
+ "uni-file-picker",
+ "uni-forms",
+ "uni-icons",
+ "uni-pagination",
+ "uni-table"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "y",
+ "联盟": "y"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/uni_modules/uni-upgrade-center/pages/components/show-info.vue b/uni_modules/uni-upgrade-center/pages/components/show-info.vue
new file mode 100644
index 0000000..459eda6
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/pages/components/show-info.vue
@@ -0,0 +1,52 @@
+
+
+
+
+ {{content}}
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-upgrade-center/pages/mixin/version_add_detail_mixin.js b/uni_modules/uni-upgrade-center/pages/mixin/version_add_detail_mixin.js
new file mode 100644
index 0000000..cff2ffb
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/pages/mixin/version_add_detail_mixin.js
@@ -0,0 +1,187 @@
+import {
+ validator,
+ enumConverter
+} from '@/js_sdk/validator/opendb-app-versions.js';
+
+const platform_iOS = 'iOS';
+const platform_Android = 'Android';
+const db = uniCloud.database();
+
+function getValidator(fields) {
+ let reuslt = {}
+ for (let key in validator) {
+ if (fields.includes(key)) {
+ reuslt[key] = validator[key]
+ }
+ }
+ return reuslt
+}
+
+export const fields =
+ 'appid,name,title,contents,platform,type,version,min_uni_version,url,stable_publish,is_silently,is_mandatory,create_date,store_list'
+
+export default {
+ data() {
+ return {
+ labelWidth: '80px',
+ enableiOSWgt: true, // 是否开启iOS的wgt更新
+ silentlyContent: '静默更新:App升级时会在后台下载wgt包并自行安装。新功能在下次启动App时生效',
+ mandatoryContent: '强制更新:App升级弹出框不可取消',
+ stablePublishContent: '同时只可有一个线上发行版,线上发行不可更设为下线。\n未上线可以设为上线发行并自动替换当前线上发行版',
+ stablePublishContent2: '使用本包替换当前线上发行版',
+ uploadFileContent: '可下载安装包地址。上传文件到云存储自动填写,也可以手动填写',
+ minUniVersionContent: '上次使用新Api或打包新模块的App版本',
+ priorityContent: '检查更新时,按照优先级从大到小依次尝试跳转商店。如果都跳转失败,则会打开浏览器使用下载链接下载apk安装包',
+ latestStableData: [], // 库中最新已上线版
+ appFileList: null, // 上传包
+ type_valuetotext: enumConverter.type_valuetotext,
+ preUrl: '',
+ formData: {
+ "appid": "",
+ "name": "",
+ "title": "",
+ "contents": "",
+ "platform": [],
+ "store_list": [],
+ "type": "",
+ "version": "",
+ "min_uni_version": "",
+ "url": "",
+ "stable_publish": false,
+ "create_date": null
+ },
+ formOptions: {
+ "platform_localdata": [{
+ "value": "Android",
+ "text": "安卓"
+ },
+ {
+ "value": "iOS",
+ "text": "苹果"
+ }
+ ],
+ "type_localdata": [{
+ "value": "native_app",
+ "text": "原生App安装包"
+ },
+ {
+ "value": "wgt",
+ "text": "App资源包"
+ }
+ ]
+ },
+ rules: {
+ ...getValidator([
+ "appid", "contents", "platform", "type",
+ "version", "min_uni_version", "url", "stable_publish",
+ "title", "name", "is_silently", "is_mandatory", "store_list"
+ ])
+ }
+ }
+ },
+ onReady() {
+ this.$refs.form.setRules(this.rules)
+ },
+ computed: {
+ isWGT() {
+ return this.formData.type === 'wgt'
+ },
+ isiOS() {
+ return !this.isWGT ? this.formData.platform.includes(platform_iOS) : false;
+ },
+ hasPackage() {
+ return this.appFileList && !!Object.keys(this.appFileList).length
+ },
+ fileExtname() {
+ return this.isWGT ? ['wgt'] : ['apk']
+ },
+ platformLocaldata() {
+ return !this.isWGT ? this.formOptions.platform_localdata : this.enableiOSWgt ? this.formOptions
+ .platform_localdata : [this.formOptions.platform_localdata[0]]
+ },
+ uni_platform() {
+ return (this.isiOS ? platform_iOS : platform_Android).toLocaleLowerCase()
+ }
+ },
+ methods: {
+ getStoreList(appid) {
+ return db.collection('opendb-app-list')
+ .where({
+ appid
+ })
+ .get()
+ .then(res => {
+ const data = res.result.data[0]
+ return data.store_list || []
+ })
+ },
+ packageUploadSuccess(res) {
+ uni.showToast({
+ icon: 'success',
+ title: '上传成功',
+ duration: 800
+ })
+ this.preUrl = this.formData.url
+ this.formData.url = res.tempFilePaths[0]
+ },
+ deleteFile(fileList) {
+ return this.$request('deleteFile', {
+ fileList
+ }, {
+ functionName: 'uni-upgrade-center'
+ })
+ },
+ async packageDelete(res) {
+ if (!this.hasPackage) return;
+ let [deleteRes] = await this.deleteFile([res.tempFilePath])
+ if (deleteRes.success) {
+ uni.showToast({
+ icon: 'success',
+ title: '删除成功',
+ duration: 800
+ })
+ this.formData.url = this.preUrl
+ this.$refs.form.clearValidate('url')
+ }
+ },
+ selectFile() {
+ if (this.hasPackage) {
+ uni.showToast({
+ icon: 'none',
+ title: '只可上传一个文件,请删除已上传后重试',
+ duration: 1000
+ });
+ }
+ },
+ createCenterRecord(value) {
+ return {
+ ...value,
+ uni_platform: this.uni_platform,
+ create_env: 'upgrade-center'
+ }
+ },
+ createCenterQuery({
+ appid
+ }) {
+ return {
+ appid,
+ create_env: 'upgrade-center'
+ }
+ },
+ createStatQuery({
+ appid,
+ type,
+ version,
+ uni_platform
+ }) {
+ return {
+ appid,
+ type,
+ version,
+ uni_platform: uni_platform ? uni_platform : this.uni_platform,
+ create_env: 'uni-stat',
+ stable_publish: false
+ }
+ }
+ }
+}
diff --git a/uni_modules/uni-upgrade-center/pages/utils.js b/uni_modules/uni-upgrade-center/pages/utils.js
new file mode 100644
index 0000000..df0aeb3
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/pages/utils.js
@@ -0,0 +1,26 @@
+// 判断arr是否为一个数组,返回一个bool值
+function isArray(arr) {
+ return Object.prototype.toString.call(arr) === '[object Array]';
+}
+
+// 深度克隆
+export function deepClone(obj) {
+ // 对常见的“非”值,直接返回原来值
+ if ([null, undefined, NaN, false].includes(obj)) return obj;
+ if (typeof obj !== "object" && typeof obj !== 'function') {
+ //原始类型直接返回
+ return obj;
+ }
+ var o = isArray(obj) ? [] : {};
+ for (let i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
+ }
+ }
+ return o;
+}
+
+export const appListDbName = 'opendb-app-list'
+export const appVersionListDbName = 'opendb-app-versions'
+// 版本列表默认显示应用Appid
+export const defaultDisplayApp = ''
diff --git a/uni_modules/uni-upgrade-center/pages/version/add.vue b/uni_modules/uni-upgrade-center/pages/version/add.vue
new file mode 100644
index 0000000..050a75c
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/pages/version/add.vue
@@ -0,0 +1,412 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 上传apk到当前服务空间的云存储中,上传成功后,会自动使用云存储地址填充下载链接
+
+
+ {{Number(appFileList.size / 1024 / 1024).toFixed(2)}}M
+
+
+
+
+
+
+
+
+
+
+
+ {item.enable = !!value.length}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-upgrade-center/pages/version/detail.vue b/uni_modules/uni-upgrade-center/pages/version/detail.vue
new file mode 100644
index 0000000..89f3730
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/pages/version/detail.vue
@@ -0,0 +1,337 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{Number(appFileList.size / 1024 / 1024).toFixed(2)}}M
+
+
+
+
+
+
+
+
+
+
+
+ {item.enable = !!value.length}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-upgrade-center/pages/version/list.vue b/uni_modules/uni-upgrade-center/pages/version/list.vue
new file mode 100644
index 0000000..9cdc9f3
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/pages/version/list.vue
@@ -0,0 +1,368 @@
+
+
+
+
+
+
+
+
+ AppID
+ 更新标题
+ 安装包类型
+ 平台
+ 已上架应用市场
+ 版本号
+ 安装包状态
+ 上传时间
+ 操作
+
+
+ {{item.appid}}
+ {{item.title || '-'}}
+
+ {{options.type_valuetotext[item.type]}}
+
+
+
+
+
+ {{store_list_key(item.store_list)}}
+
+ {{item.version}}
+ {{item.stable_publish == true ? '已上线' : '已下线'}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-upgrade-center/readme.md b/uni_modules/uni-upgrade-center/readme.md
new file mode 100644
index 0000000..46ec891
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/readme.md
@@ -0,0 +1,233 @@
+## uni-admin 1.9.3+ 已内置,此插件不再维护 [点击查看文档](https://uniapp.dcloud.net.cn/uniCloud/upgrade-center.html)
+
+- `uni-admin < 1.9.0`:请前往 [Gitee](https://gitee.com/dcloud/uni-upgrade-center/releases) 下载 `tag v0.4.2` 版本使用
+-`1.9.0 <= uni-admin < 1.9.2` :请前往 [Gitee](https://gitee.com/dcloud/uni-upgrade-center/releases) 下载 `tag v0.5.1` 版本使用
+- `uni-admin >= 1.9.3` :uni-admin 已内置 升级中心,直接使用即可 [详情](https://uniapp.dcloud.io/uniCloud/admin.html#app-manager)。并且云函数 `upgrade-center` 废弃,使用 `uni-upgrade-center` 云函数。
+
+# uni-upgrade-center - Admin
+
+### 概述
+
+> 统一管理App及App在`Android`、`iOS`平台上`App安装包`和`wgt资源包`的发布升级
+
+> 本插件为uni升级中心后台管理系统,客户端检查更新插件请点击查看 [uni-upgrade-center-app](https://ext.dcloud.net.cn/plugin?id=4542)
+
+### 基于uniCloud的App升级中心,本插件具有如下特征:
+ - 云端基于uniCloud云函数实现
+ - 数据库遵循opendb规范
+ - 遵循uni-Admin框架规范,可直接导入uni-admin项目中
+ - 支持App整包升级及wgt资源包升级
+
+## 升级中心解决了什么问题?
+
+升级中心是一款uni-admin插件,负责App版本更新业务。包含后台管理界面、更新检查逻辑,App内只要调用弹出提示即可。
+
+升级中心有以下功能点:
+
+- 应用管理,对App的信息记录和应用版本管理
+- 版本管理,可以发布新版,也可方便直观的对当前App历史版本以及线上发行版本进行查看、编辑和删除操作
+- 版本发布信息管理,包括 更新标题,更新内容,版本号,静默更新,强制更新,灵活上线发行 的设置和修改
+- 原生App安装包,发布Apk更新,用于App的整包更新,可设置是否强制更新
+- wgt资源包,发布wgt更新,用于App的热更新,可设置是否强制更新,静默更新
+- App管理列表及App版本记录列表搜索
+
+只需导入插件,初始化数据库即可拥有上述功能。
+
+您也可以自己修改逻辑自定义数据库字段,和随意定制 UI 样式。
+
+## 安装指引
+
+1. 使用`HBuilderX 3.1.0+`,因为要使用到`uni_modules`
+
+2. 使用已有`uniCloud-admin`项目或新建项目:`打开HBuilderX` -> `文件` -> `新建` -> `项目` -> `uni-app` 选择 `uniCloud admin`模板,键入一个名字,确定
+
+3. 鼠标右键选择`关联云服务空间`和`运行云服务空间初始化向导`
+
+3. 在插件市场打开本插件页面,在右侧点击`使用 HBuilderX 导入插件`,选择 `uniCloud admin` 项目点击确定
+
+4. 等待下载安装完毕。由于本插件依赖一些uni-ui插件,下载完成后会显示合并插件页面,自行选择即可
+
+5. 找到`/uni_modules/uni-upgrade-center/uniCloud/cloudfunctions/upgrade-center`,右键上传部署
+
+7. 在`pages.json`中添加页面路径
+```json
+//此结构与uniCloud admin中的pages.json结构一致
+{
+ "pages": [
+ // ……其他页面配置
+ {
+ "path": "uni_modules/uni-upgrade-center/pages/version/list",
+ "style": {
+ "navigationBarTitleText": "版本列表"
+ }
+ }, {
+ "path": "uni_modules/uni-upgrade-center/pages/version/add",
+ "style": {
+ "navigationBarTitleText": "新版发布"
+ }
+ }, {
+ "path": "uni_modules/uni-upgrade-center/pages/version/detail",
+ "style": {
+ "navigationBarTitleText": "版本信息查看"
+ }
+ }
+ ]
+}
+```
+
+8. 在`manifest.json -> 源码视图`中添加以下配置:
+ ```js
+ "networkTimeout":{
+ "uploadFile":1200000 //ms, 如果不配置,上传大文件可能会超时
+ }
+ ```
+
+9. 运行项目到`Chrome`
+
+10. 添加菜单
+ - `vue2`
+
+ 运行起来uniCloud admin,菜单管理模块会自动读取`/uni_modules/uni-upgrade-center/menu.json`文件中的菜单配置,生成【待添加菜单】,选中升级中心,点击`添加选中的菜单`即可
+
+

+
+ - `vue3`
+
+ 可将 `/uni_modules/uni-upgrade-center/menu.json` 拷贝至 `uniCloud/database/db_init.json` 中的 `opendb-admin-menus` 节点下,并右键初始化数据库即可。
+11. 添加成功后,就可以在左侧的菜单栏中找到`升级中心`菜单
+
+
+

+
+
+12. 在进入`升级中心`之前:
+ 1. 需要到`uni-admin`的`应用管理`中添加一个应用,才可以在`升级中心`中发布对应应用的版本。
+ 2. 当你有多个应用时,可以在`/uni_modules/uni-upgrade-center/pages/utils.js`中修改`defaultDisplayApp`字段来设置默认显示应用的`appid`。
+ 3. 如果不设置或设置应用不存在则默认从数据库中查出来的第一个应用。
+
+13. 由于插件依赖的uni-ui的一些组件,建议右键`/uni_modules/uni-upgrade-center`安装一下第三方依赖,否则可能会出现一些问题
+
+14. 运行在`uniCloud`,由于本插件使用了`clientDB`,因此可能需要配置一下`uni-config-center插件`关于`uni-id`的配置信息。如提示`公用模块uni-id缺少配置信息`请这样做:
+ 1. 点击[uni-config-center](https://ext.dcloud.net.cn/plugin?id=4425)导入插件
+ 2. 在`/uniCloud/cloudfunctions/common/uni-config-center/`下创建`uni-id`文件夹,文件夹内创建`config.json`文件。
+ 3. 点击[config.json默认配置](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=start)。将内容拷贝至`config.json`中。**注:一定要把注释去除!**
+
+## 使用指南
+
+### 升级中心
+
+#### 应用列表
+
+1. 点击菜单 `应用管理`,这里展示你所添加的 App,点击右上角 `新增` 可以新增一个 App
+
+
+

+
+
+2. 将App的信息都填写完善后,你可以在列表的操作列进行`修改`应用信息或者`删除`该应用。
+
+**Tips**
+- 删除应用会把该应用的所有版本记录同时删除
+
+#### 版本管理
+1. 在版本管理list的右上角点击`发布新版`,可以发布`原生App安装包`和`wgt资源包`。在左上角点击`下拉列表`,可以切换展示应用。
+
+
+

+
+
+- #### 发布原生App安装包
+ 1. 在上传安装包界面填写此次发版信息
+
+
+

+
+
+ 2. `包地址`
+ - 可以选择手动上传一个文件到 `云存储`,会自动将地址填入该项
+
+ - 也可以手动填写一个地址,就可以不用再上传文件
+
+ - 如果是发布`苹果`版本,包地址则为 应用在`AppStore的链接`
+
+ 3. `强制更新`
+ - 如果使用强制更新,App端接收到该字段后,App升级弹出框不可取消
+
+ 4. `上线发行`
+ - 可设置当前包是否上线发行,只有已上线才会进行更新检测
+
+ - 同时只可有一个线上发行版,线上发行不可更设为下线。未上线可以设为上线发行并自动替换当前线上发行版
+
+ - 修改当前包为上线发行,自动替换当前线上发行版
+
+ **注:版本号请填写以`.`分隔字符串,例如:`0.0.1`**
+- #### 发布wgt资源包
+ 1. 大部分配置与发布 `原生App安装包` 一致
+
+
+

+
+
+ 2. `原生App最低版本`
+ - 上次使用新Api或打包新模块的App版本
+
+ - 如果此次打包wgt使用了`新的api`或者打包了`新的模块`,则在发布 `wgt资源包` 的时候,将此版本更新为本次版本
+
+ - 如果已有正式版`wgt资源包`,则本次新增会自动带出
+
+ 2. `静默更新`
+ - App升级时会在后台下载wgt包并自行安装。新功能在下次启动App时生效
+ - **静默更新后不重启应用,可能会导致正在访问的应用的页面数据错乱,请谨慎使用!**
+
+ **注:版本号请填写以`.`分隔字符串,例如:`0.0.1`**
+
+- #### 发布完成页面
+
+
+

+
+
+**Tips**
+
+1. `pages/system/upgradecenter/version/add.vue`中有版本对比函数(compare)。
+ - 使用多段式版本格式(如:"3.0.0.0.0.1.0.1", "3.0.0.0.0.1")。如果不满足对比规则,请自行修改。
+
+## 项目代码说明
+
+### uniCloud 数据表
+
+数据表基于 [openDB](https://gitee.com/dcloud/opendb/tree/master) 规范,它约定了一个标准用户表的表名和字段定义,并且基于 nosql 的特性,可以由开发者自行扩展字段。
+
+本项目用到了 2 个表:
+
+- opendb-app-list:app管理列表。记录应用的 appid、name、description 用于展示。[详见](https://gitee.com/dcloud/opendb/tree/master/collection/opendb-app-list)
+- opendb-app-versions:应用版本管理表。记录管理应用的版本信息。[详见](https://gitee.com/dcloud/opendb/tree/master/collection/opendb-app-versions)
+
+### 前端页面
+
+点击`升级中心`,会进入应用管理列表,在这里你可以新增应用,或者在`应用详情`中查看、修改或删除一个已经录入的应用。
+
+在应用管理列表中点击某个应用的`版本管理`,进入该应用的所有版本记录。列表排序为:先排序已上线版本,剩下已下线版本根据创建时间排列。
+
+在应用版本列表中点击`详情`,即可进入该版本的信息详情中查看、修改或删除该记录。
+
+**Tips**
+- 升级中心设计之初就支持iOS的wgt更新
+- iOS的wgt更新肯定是违反apple政策的,注意事项:
+ - 审核期间请不要弹窗升级
+ - 升级完后尽量不要自行重启
+ - 尽量使用静默更新
+- 可以通过以下修改支持iOS的wgt更新:
+ > \uni_modules\uni-upgrade-center\pages\mixin\version_add_detail_mixin.js
+ >
+ > 将 `data` 中的 `enableiOSWgt: false` 中 改为 `enableiOSWgt: true`
+
+**常见问题**
+- 以下问题可以通过升级插件版本解决:
+ - createdate不与默认值匹配
+ - ["create_date"]在数据库中并不存在
+ - 提交的字段["dirty_data"]在数据库中并不存在
+ - 集合[opendb-app-list]对应的schema内存在错误,详细信息:opendb-app-list表对应的schema名称冲突,这是什么意思呢
+
+- 没有/找不到 [opendb-app-list] 集合/表。**解决方案:**升级 admin 至 1.6.0+ 即可
+- 测试时发布了高版本的包,测试完了发布包提示需要大于版本号 (x.x.x)。**解决方案:**直接在控制台修改数据库
\ No newline at end of file
diff --git a/uni_modules/uni-upgrade-center/uniCloud/database/db_init.json b/uni_modules/uni-upgrade-center/uniCloud/database/db_init.json
new file mode 100644
index 0000000..cb5b6ae
--- /dev/null
+++ b/uni_modules/uni-upgrade-center/uniCloud/database/db_init.json
@@ -0,0 +1,10 @@
+// 在本文件中可配置云数据库初始化,数据格式见:https://uniapp.dcloud.io/uniCloud/hellodb?id=db-init
+
+// 编写完毕后对本文件点右键,可按配置规则创建表和添加数据
+
+{
+
+
+
+}
+
diff --git a/uni_modules/uview-ui/components/u-alert/u-alert.vue b/uni_modules/uview-ui/components/u-alert/u-alert.vue
index f5d8f3f..af6c584 100644
--- a/uni_modules/uview-ui/components/u-alert/u-alert.vue
+++ b/uni_modules/uview-ui/components/u-alert/u-alert.vue
@@ -45,7 +45,6 @@
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
>{{ description }}
-
@@ -38,7 +37,6 @@
* @property {String | Number} size 列表锚点文字大小,单位默认px ( 默认 14 )
* @property {String} bgColor 列表锚点背景颜色 ( 默认 '#dedede' )
* @property {String | Number} height 列表锚点高度,单位默认px ( 默认 32 )
-
* @example
*/
export default {
diff --git a/uni_modules/uview-ui/components/u-index-list/props.js b/uni_modules/uview-ui/components/u-index-list/props.js
index fa00f8b..354d459 100644
--- a/uni_modules/uview-ui/components/u-index-list/props.js
+++ b/uni_modules/uview-ui/components/u-index-list/props.js
@@ -13,7 +13,7 @@ export default {
// 索引字符列表,数组形式
indexList: {
type: Array,
- default: []
+ default: uni.$u.props.indexList.indexList
},
// 是否开启锚点自动吸顶
sticky: {
@@ -24,11 +24,6 @@ export default {
customNavHeight: {
type: [String, Number],
default: uni.$u.props.indexList.customNavHeight
- },
- // 自定义导航栏的高度
- uIndexStyle: {
- type:Object,
- default: {}
}
}
}
diff --git a/uni_modules/uview-ui/components/u-index-list/u-index-list.vue b/uni_modules/uview-ui/components/u-index-list/u-index-list.vue
index 7c8accd..d712618 100644
--- a/uni_modules/uview-ui/components/u-index-list/u-index-list.vue
+++ b/uni_modules/uview-ui/components/u-index-list/u-index-list.vue
@@ -54,10 +54,10 @@
@touchcancel.stop.prevent="touchEnd"
>
@@ -77,17 +77,16 @@
zIndex: 2
}"
>
-
+ {{ uIndexList[activeIndex] }}
+
@@ -95,10 +94,10 @@
+
+
diff --git a/uni_modules/z-address-popup/package.json b/uni_modules/z-address-popup/package.json
new file mode 100644
index 0000000..5d756cd
--- /dev/null
+++ b/uni_modules/z-address-popup/package.json
@@ -0,0 +1,78 @@
+{
+ "id": "z-address",
+ "displayName": "三级联动弹窗,地址选择弹窗,可选长度",
+ "version": "1.0.0",
+ "description": "三级联动,地址选择,可选长度",
+ "keywords": [
+ "三级联动弹窗",
+ "地址选择弹窗",
+ "地区选择弹窗"
+],
+ "repository": "https://github.com/zhouwei1994/uni-app-demo",
+ "engines": {
+ "HBuilderX": "^3.0.0"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": "465081029"
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/z-address-popup/readme.md b/uni_modules/z-address-popup/readme.md
new file mode 100644
index 0000000..fdd7c20
--- /dev/null
+++ b/uni_modules/z-address-popup/readme.md
@@ -0,0 +1,28 @@
+# 三级联动弹窗,地址选择弹窗,可选长度
+
+三级联动弹窗,地址选择弹窗,可选长度
+
+| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群")` |
+| ----------------------------|--------------------------- |
+|||
+| QQ群号:607391225 |微信号:zhou0612wei|
+
+### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
+
+### 案例一
+```
+
+```
+
+### 属性
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
+| dataList | Array | [] | 默认值|
+| length | Number | 3 | 地区选择长度(1-3) |
+| force | Boolean | true | 强制选择,选择长度必须达到指定长度|
+| value | Boolean | false | 控制弹窗是否打开 |
+
+### 事件
+| 名称 | 类型 | 描述 |
+| -----------------|------------------ | --------------------------|
+| @change | function | 选择时数据返回 |
diff --git a/uni_modules/z-address/changelog.md b/uni_modules/z-address/changelog.md
new file mode 100644
index 0000000..96b273b
--- /dev/null
+++ b/uni_modules/z-address/changelog.md
@@ -0,0 +1,2 @@
+## 1.0.0(2021-05-12)
+1. 支持uni_modules
diff --git a/uni_modules/z-address/components/z-address/z-address.vue b/uni_modules/z-address/components/z-address/z-address.vue
new file mode 100644
index 0000000..0ffac09
--- /dev/null
+++ b/uni_modules/z-address/components/z-address/z-address.vue
@@ -0,0 +1,175 @@
+
+
+
+
+ {{ item.name }}
+
+ 请选择
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-address/package.json b/uni_modules/z-address/package.json
new file mode 100644
index 0000000..e3c96af
--- /dev/null
+++ b/uni_modules/z-address/package.json
@@ -0,0 +1,78 @@
+{
+ "id": "z-address",
+ "displayName": "三级联动,地址选择,可选长度",
+ "version": "1.0.0",
+ "description": "三级联动,地址选择,可选长度",
+ "keywords": [
+ "三级联动",
+ "地址选择",
+ "地区选择"
+],
+ "repository": "https://github.com/zhouwei1994/uni-app-demo",
+ "engines": {
+ "HBuilderX": "^3.0.0"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": "465081029"
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/z-address/readme.md b/uni_modules/z-address/readme.md
new file mode 100644
index 0000000..9c3d676
--- /dev/null
+++ b/uni_modules/z-address/readme.md
@@ -0,0 +1,27 @@
+# 三级联动,地址选择,可选长度
+
+三级联动,地址选择,可选长度
+
+| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群")` |
+| ----------------------------|--------------------------- |
+|||
+| QQ群号:607391225 |微信号:zhou0612wei|
+
+### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
+
+### 案例一
+```
+
+```
+
+### 属性
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
+| dataList | Array | [] | 默认值|
+| length | Number | 3 | 地区选择长度(1-3) |
+| force | Boolean | true | 强制选择,选择长度必须达到指定长度|
+
+### 事件
+| 名称 | 类型 | 描述 |
+| -----------------|------------------ | --------------------------|
+| @change | function | 选择时数据返回 |
diff --git a/uni_modules/z-loading/components/z-loading/z-loading.vue b/uni_modules/z-loading/components/z-loading/z-loading.vue
index d3e11fa..ea2866a 100644
--- a/uni_modules/z-loading/components/z-loading/z-loading.vue
+++ b/uni_modules/z-loading/components/z-loading/z-loading.vue
@@ -56,7 +56,7 @@ export default {
height: 120rpx;
border-radius: 50%;
border: 3rpx solid transparent;
- border-top-color: #3AB3AE;
+ border-top-color: #54a966;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
diff --git a/uni_modules/z-nav-bar/components/z-nav-bar/z-nav-bar.vue b/uni_modules/z-nav-bar/components/z-nav-bar/z-nav-bar.vue
index 373b3aa..05bfa9d 100644
--- a/uni_modules/z-nav-bar/components/z-nav-bar/z-nav-bar.vue
+++ b/uni_modules/z-nav-bar/components/z-nav-bar/z-nav-bar.vue
@@ -357,6 +357,7 @@ export default {
},
//导航字体是否是白色颜色
isWhite() {
+ // console.log(whiteList,'this.navFontColor')
return whiteList.includes(this.navFontColor);
},
//右上角是否有两个按钮
@@ -404,9 +405,9 @@ export default {
let currentPages = getCurrentPages();
let pageLen = currentPages.length;
//判断是否是第一个页面,如果是有设置back为true的页面,将不显示返回箭头,而显示返回首页按钮
- if (pageLen == 1 && !mainPagePath.includes(currentPages[0].route)) {
- this.firstPage = true;
- }
+ // if (pageLen == 1 && !mainPagePath.includes(currentPages[0].route)) {
+ // this.firstPage = true;
+ // }
},
//方法
methods: {
@@ -425,7 +426,7 @@ export default {
this.$emit("homeClick");
} else {
uni.switchTab({
- url: '/pages/home/index',
+ url: '/pages/homePage/index/index',
});
}
},
@@ -602,7 +603,6 @@ export default {
/* #endif */
/* #ifdef APP-PLUS-NVUE */
lines: 1;
- max-width: calc(100vw - 100px) !important;
/* #endif */
flex-direction: row;
align-items: center;
diff --git a/uni_modules/z-paging/changelog.md b/uni_modules/z-paging/changelog.md
new file mode 100644
index 0000000..e07e38d
--- /dev/null
+++ b/uni_modules/z-paging/changelog.md
@@ -0,0 +1,14 @@
+## 2.0.1(2021-08-16)
+1.自定义下拉刷新view无需设置`refresher-threshold`,将根据view自动计算高度。
+2.修复在iOS 13中下拉刷新抖动的问题。
+3.新增`inside-more`,支持在分页未满一屏时自动加载下一页。
+4.修复z-paging prop代码自动补全无效的问题,完善代码自动补全文档注释。
+5.修复在微信小程序中提示:uni is not defined的bug。
+6.修复在某些情况下,下拉刷新页面会跟着下拉的bug。
+7.其他细节优化。
+## 2.0.0(2021-08-16)
+1.自定义下拉刷新view无需设置`refresher-threshold`,将根据view自动计算高度。
+2.修复在iOS 13中下拉刷新抖动的问题。
+3.新增`inside-more`,支持在分页未满一屏时自动加载下一页。
+4.修复z-paging prop代码自动补全无效的问题,完善代码自动补全文档注释。
+5.其他细节优化。
diff --git a/uni_modules/z-paging/components/z-paging-empty-view/z-paging-empty-view.vue b/uni_modules/z-paging/components/z-paging-empty-view/z-paging-empty-view.vue
new file mode 100644
index 0000000..a8e6513
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging-empty-view/z-paging-empty-view.vue
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{emptyViewText}}
+ {{emptyViewReloadText}}
+
+
+
+
+
+
+
diff --git a/uni_modules/z-paging/components/z-paging-swiper-item/z-paging-swiper-item.vue b/uni_modules/z-paging/components/z-paging-swiper-item/z-paging-swiper-item.vue
new file mode 100644
index 0000000..9871555
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging-swiper-item/z-paging-swiper-item.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-paging/components/z-paging-swiper/z-paging-swiper.vue b/uni_modules/z-paging/components/z-paging-swiper/z-paging-swiper.vue
new file mode 100644
index 0000000..ee21c0c
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging-swiper/z-paging-swiper.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-paging/components/z-paging/components/z-paging-load-more.vue b/uni_modules/z-paging/components/z-paging/components/z-paging-load-more.vue
new file mode 100644
index 0000000..8b31f8c
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/components/z-paging-load-more.vue
@@ -0,0 +1,161 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ownLoadingMoreText}}
+
+
+
+
+
+
diff --git a/uni_modules/z-paging/components/z-paging/components/z-paging-refresh.vue b/uni_modules/z-paging/components/z-paging/components/z-paging-refresh.vue
new file mode 100644
index 0000000..b2e48db
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/components/z-paging-refresh.vue
@@ -0,0 +1,259 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{refresherStatusTextMap[refresherStatus]||refresherDefaultText}}
+
+ {{refresherTimeText}}
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-paging/components/z-paging/css/z-paging-main.css b/uni_modules/z-paging/components/z-paging/css/z-paging-main.css
new file mode 100644
index 0000000..6b25469
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/css/z-paging-main.css
@@ -0,0 +1,161 @@
+/* z-paging
+github地址:https://github.com/SmileZXLee/uni-z-paging
+dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+反馈QQ群:790460711
+*/
+
+.z-paging-content {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ width: 100%;
+ height: 100%;
+ /* #endif */
+ flex-direction: column;
+}
+
+.z-paging-content-fixed {
+ position: fixed;
+ /* #ifndef APP-NVUE */
+ height: auto;
+ width: auto;
+ /* #endif */
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+}
+
+.zp-page-scroll-top,
+.zp-page-scroll-bottom {
+ /* #ifndef APP-NVUE */
+ width: auto;
+ /* #endif */
+ position: fixed;
+ left: 0;
+ right: 0;
+ z-index: 999;
+}
+
+.zp-scroll-view-super {
+ flex: 1;
+ position: relative;
+}
+
+.zp-custom-refresher-container {
+ overflow: hidden;
+}
+
+.zp-scroll-view {
+ height: 100%;
+ width: 100%;
+}
+
+.zp-scroll-view-absolute {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+.zp-paging-touch-view {
+ width: 100%;
+ height: 100%;
+ position: relative;
+}
+
+.zp-fixed-bac-view {
+ position: absolute;
+ width: 100%;
+ top: 0;
+ left: 0;
+ height: 200px;
+}
+
+.zp-paging-main {
+ height: 100%;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+}
+
+.zp-paging-container {
+ flex: 1;
+ position: relative;
+}
+
+.zp-chat-record-loading-container {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ width: 100%;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ width: 750rpx;
+ /* #endif */
+ align-items: center;
+ justify-content: center;
+ height: 60rpx;
+ font-size: 26rpx;
+}
+
+.zp-chat-record-loading-custom-image {
+ width: 35rpx;
+ height: 35rpx;
+ /* #ifndef APP-NVUE */
+ animation: loading-flower 1s linear infinite;
+ /* #endif */
+}
+
+.zp-custom-refresher-container {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+}
+
+.zp-back-to-top {
+ width: 76rpx;
+ height: 76rpx;
+ z-index: 999;
+ position: absolute;
+ bottom: 0rpx;
+ right: 25rpx;
+ transition-duration: .3s;
+ transition-property: opacity;
+}
+
+.zp-back-to-top-show {
+ opacity: 1;
+}
+
+.zp-back-to-top-hide {
+ opacity: 0;
+}
+
+.zp-back-to-top-img {
+ /* #ifndef APP-NVUE */
+ width: 100%;
+ height: 100%;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ flex: 1;
+ /* #endif */
+ z-index: 999;
+}
+
+.zp-empty-view {
+ /* #ifdef APP-NVUE */
+ height: 100%;
+ /* #endif */
+ flex: 1;
+}
+
+.zp-n-refresh-container {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ width: 750rpx;
+}
diff --git a/uni_modules/z-paging/components/z-paging/css/z-paging-static.css b/uni_modules/z-paging/components/z-paging/css/z-paging-static.css
new file mode 100644
index 0000000..714edeb
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/css/z-paging-static.css
@@ -0,0 +1,38 @@
+/* z-paging
+github地址:https://github.com/SmileZXLee/uni-z-paging
+dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+反馈QQ群:790460711
+
+公用的静态css资源 */
+
+.zp-loading-more-line-loading-image {
+ margin-right: 8rpx;
+ width: 28rpx;
+ height: 28rpx;
+ /* #ifndef APP-NVUE */
+ animation: loading-flower 1s steps(12) infinite;
+ /* #endif */
+ color: #666666;
+}
+
+.zp-loading-image-ios{
+ width: 20px;
+ height: 20px;
+}
+
+.zp-loading-image-android{
+ width: 32rpx;
+ height: 32rpx;
+}
+
+@keyframes loading-flower {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ to {
+ -webkit-transform: rotate(1turn);
+ transform: rotate(1turn);
+ }
+}
diff --git a/uni_modules/z-paging/components/z-paging/js/z-paging-config.js b/uni_modules/z-paging/components/z-paging/js/z-paging-config.js
new file mode 100644
index 0000000..58c00eb
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/js/z-paging-config.js
@@ -0,0 +1,32 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+// z-paging配置文件
+
+let config = null;
+let getedStorage = false;
+const storageKey = 'Z-PAGING-CONFIG-STORAGE-KEY'
+
+function setConfig(value) {
+ try {
+ uni.setStorageSync(storageKey, value);
+ } catch {}
+}
+
+function getConfig() {
+ try {
+ if (getedStorage) {
+ return config;
+ }
+ config = uni.getStorageSync(storageKey);
+ getedStorage = true;
+ } catch {
+ return null;
+ }
+}
+
+module.exports = {
+ setConfig,
+ getConfig
+};
diff --git a/uni_modules/z-paging/components/z-paging/js/z-paging-i18n.js b/uni_modules/z-paging/components/z-paging/js/z-paging-i18n.js
new file mode 100644
index 0000000..949f799
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/js/z-paging-i18n.js
@@ -0,0 +1,150 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+// z-paging国际化(支持中文、中文繁体和英文)
+
+const i18nUpdateKey = 'z-paging-i18n-update';
+
+const refresherDefaultText = {
+ 'en': 'Pull down to refresh',
+ 'zh-cn': '继续下拉刷新',
+ 'zh-hant-cn': '繼續下拉重繪',
+}
+const refresherPullingText = {
+ 'en': 'Release to refresh',
+ 'zh-cn': '松开立即刷新',
+ 'zh-hant-cn': '鬆開立即重繪',
+}
+const refresherRefreshingText = {
+ 'en': 'Refreshing...',
+ 'zh-cn': '正在刷新...',
+ 'zh-hant-cn': '正在重繪...',
+}
+
+const loadingMoreDefaultText = {
+ 'en': 'Click to load more',
+ 'zh-cn': '点击加载更多',
+ 'zh-hant-cn': '點擊加載更多',
+}
+const loadingMoreLoadingText = {
+ 'en': 'Loading...',
+ 'zh-cn': '正在加载...',
+ 'zh-hant-cn': '正在加載...',
+}
+const loadingMoreNoMoreText = {
+ 'en': 'No more data',
+ 'zh-cn': '没有更多了',
+ 'zh-hant-cn': '沒有更多了',
+}
+const loadingMoreFailText = {
+ 'en': 'Load failed,click to reload',
+ 'zh-cn': '加载失败,点击重新加载',
+ 'zh-hant-cn': '加載失敗,點擊重新加載',
+}
+
+const emptyViewText = {
+ 'en': 'No data',
+ 'zh-cn': '没有数据哦~',
+ 'zh-hant-cn': '沒有數據哦~',
+}
+
+const emptyViewReloadText = {
+ 'en': 'Reload',
+ 'zh-cn': '重新加载',
+ 'zh-hant-cn': '重新加載',
+}
+
+const emptyViewErrorText = {
+ 'en': 'Sorry,load failed',
+ 'zh-cn': '很抱歉,加载失败',
+ 'zh-hant-cn': '很抱歉,加載失敗',
+}
+
+const refresherUpdateTimeText = {
+ 'en': 'Last update: ',
+ 'zh-cn': '最后更新:',
+ 'zh-hant-cn': '最後更新:',
+}
+
+const refresherUpdateTimeNoneText = {
+ 'en': 'None',
+ 'zh-cn': '无',
+ 'zh-hant-cn': '無',
+}
+
+const refresherUpdateTimeTodayText = {
+ 'en': 'Today',
+ 'zh-cn': '今天',
+ 'zh-hant-cn': '今天',
+}
+
+const refresherUpdateTimeYesterdayText = {
+ 'en': 'Yesterday',
+ 'zh-cn': '昨天',
+ 'zh-hant-cn': '昨天',
+}
+
+// 插件内部使用,请勿直接调用
+function getPrivateLanguage(myLanguage, followSystemLanguage = true) {
+ let systemLanguage = '';
+ if (followSystemLanguage) {
+ systemLanguage = uni.getSystemInfoSync().language;
+ }
+ let language = myLanguage || uni.getStorageSync(i18nUpdateKey) || systemLanguage;
+ language = language.toLowerCase();
+ var reg = new RegExp('_', '');
+ language = language.replace(reg, '-');
+ if (language.indexOf('zh') !== -1) {
+ if (language === 'zh' || language === 'zh-cn' || language.indexOf('zh-hans') !== -1) {
+ return 'zh-cn';
+ }
+ return 'zh-hant-cn';
+ }
+ if (language.indexOf('en') !== -1) {
+ return 'en';
+ }
+ return 'zh-cn';
+}
+
+// 获取当前语言,格式为:zh-cn、zh-hant-cn、en。followSystemLanguage:获取的结果是否是在不跟随系统语言下获取到的
+function getLanguage(followSystemLanguage = true) {
+ return getPrivateLanguage(false, followSystemLanguage);
+}
+
+// 获取当前语言,格式为:简体中文、繁體中文、English。followSystemLanguage:获取的结果是否是在不跟随系统语言下获取到的
+function getLanguageName(followSystemLanguage = true) {
+ const language = getLanguage(followSystemLanguage);
+ const languageNameMap = {
+ 'zh-cn': '简体中文',
+ 'zh-hant-cn': '繁體中文',
+ 'en': 'English'
+ };
+ return languageNameMap[language];
+}
+
+function setLanguage(myLanguage) {
+ uni.setStorageSync(i18nUpdateKey, myLanguage);
+ uni.$emit(i18nUpdateKey, myLanguage);
+}
+
+module.exports = {
+ refresherDefaultText,
+ refresherPullingText,
+ refresherRefreshingText,
+ loadingMoreDefaultText,
+ loadingMoreLoadingText,
+ loadingMoreNoMoreText,
+ loadingMoreFailText,
+ emptyViewText,
+ emptyViewReloadText,
+ emptyViewErrorText,
+ getPrivateLanguage,
+ getLanguage,
+ getLanguageName,
+ setLanguage,
+ refresherUpdateTimeText,
+ refresherUpdateTimeNoneText,
+ refresherUpdateTimeTodayText,
+ refresherUpdateTimeYesterdayText
+}
diff --git a/uni_modules/z-paging/components/z-paging/js/z-paging-main.js b/uni_modules/z-paging/components/z-paging/js/z-paging-main.js
new file mode 100644
index 0000000..93d3d2d
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/js/z-paging-main.js
@@ -0,0 +1,2745 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+
+import zStatic from './z-paging-static'
+import zConfig from './z-paging-config'
+import zUtils from './z-paging-utils'
+import zI18n from './z-paging-i18n'
+import zPagingRefresh from '../components/z-paging-refresh'
+import zPagingLoadMore from '../components/z-paging-load-more'
+import zPagingEmptyView from '../../z-paging-empty-view/z-paging-empty-view'
+
+const currentVersion = 'V1.9.8';
+const systemInfo = uni.getSystemInfoSync();
+const commonDelayTime = 100;
+const i18nUpdateKey = 'z-paging-i18n-update';
+const errorUpdateKey = 'z-paging-error-emit';
+let config = null;
+// #ifdef APP-NVUE
+const weexDom = weex.requireModule('dom');
+const weexAnimation = weex.requireModule('animation');
+// #endif
+
+/*
+当z-paging未使用uni_modules管理时,控制台会有警告:WARNING: Module not found: Error: Can't resolve '@/uni_modules/z-paging'...
+此时注释下方try中的代码即可
+*/
+try {
+ const contextKeys = require.context('@/uni_modules/z-paging', false, /\z-paging-config$/).keys();
+ if (contextKeys.length) {
+ const suffix = '.js';
+ config = require('@/uni_modules/z-paging/z-paging-config' + suffix);
+ }
+} catch {}
+
+//获取默认配置信息
+function _getConfig(key, defaultValue) {
+ if (!config) {
+ const temConfig = zConfig.getConfig();
+ if (zConfig && temConfig) {
+ config = temConfig;
+ }
+ }
+ if (!config) {
+ return defaultValue;
+ }
+ let value = config[toKebab(key)];
+ if (value === undefined) {
+ value = config[key];
+ }
+ if (value !== undefined) {
+ return value;
+ }
+ return defaultValue;
+}
+//驼峰转短横线
+function toKebab(value) {
+ return value.replace(/([A-Z])/g, "-$1").toLowerCase();
+}
+
+export default {
+ name: "z-paging",
+ components: {
+ zPagingRefresh,
+ zPagingLoadMore,
+ zPagingEmptyView
+ },
+ data() {
+ return {
+ base64Arrow: zStatic.base64Arrow,
+ base64Flower: zStatic.base64Flower,
+ base64BackToTop: zStatic.base64BackToTop,
+ systemInfo: null,
+ currentData: [],
+ totalData: [],
+ pageNo: 1,
+ showLoadingMore: false,
+ insideOfPaging: -1,
+ refresherTriggered: false,
+ loading: false,
+ firstPageLoaded: false,
+ pagingLoaded: false,
+ loaded: false,
+ isUserReload: true,
+ scrollEnable: true,
+ scrollTop: 0,
+ oldScrollTop: 0,
+ refresherTouchstartY: 0,
+ lastRefresherTouchmove: null,
+ refresherReachMaxAngle: true,
+ refresherTransform: 'translateY(0px)',
+ refresherTransition: '',
+ finalRefresherDefaultStyle: 'black',
+ //当前加载类型 0-下拉刷新 1-上拉加载更多
+ loadingType: 0,
+ //底部加载更多状态 0-默认状态 1.加载中 2.没有更多数据 3.加载失败
+ loadingStatus: 0,
+ //下拉刷新状态 0-默认状态 1.松手立即刷新 2.刷新中
+ refresherStatus: 0,
+ scrollViewStyle: {},
+ pullDownTimeStamp: 0,
+ pageScrollTop: -1,
+ isTouchmoving: false,
+ isLocalPaging: false,
+ totalLocalPagingList: [],
+ realTotalData: [],
+ isAddedData: false,
+ isTotalChangeFromAddData: false,
+ isTouchEnded: false,
+ isUserPullDown: false,
+ privateRefresherEnabled: -1,
+ privateScrollWithAnimation: -1,
+ myParentQuery: -1,
+ chatRecordLoadingMoreText: '',
+ moveDistance: 0,
+ loadingMoreDefaultSlot: null,
+ backToTopClass: 'zp-back-to-top zp-back-to-top-hide',
+ showBackToTopClass: false,
+ tempLanguageUpdateKey: 0,
+ isLoadFailed: false,
+ isIos: systemInfo.platform === 'ios',
+ privateShowRefresherWhenReload: false,
+ nRefresherLoading: true,
+ nListIsDragging: false,
+ nShowBottom: true,
+ nFixFreezing: false,
+ nShowRefresherReveal: false,
+ nShowRefresherRevealHeight: 0,
+ nIsFirstPageAndNoMore: false,
+ nFirstPageAndNoMoreChecked: false,
+ nLoadingMoreFixedHeight: false,
+ wxsPropType: '',
+ refresherRevealStackCount: 0,
+ renderPropScrollTop: -1,
+ renderPropUsePageScroll: -1,
+ wxsIsScrollTopInTopRange: true,
+ wxsScrollTop: 0,
+ wxsPageScrollTop: 0,
+ wxsOnPullingDown: false,
+ disabledBounce: false,
+ cacheScrollNodeHeight: -1,
+ customNoMore: -1,
+ customRefresherHeight: -1,
+ showCustomRefresher: false,
+ checkScrolledToBottomTimeOut: null,
+ isIos13: systemInfo.system && systemInfo.system.length && systemInfo.system.indexOf('iOS 13') != -1
+ };
+ },
+ props: {
+ //自定义pageNo,默认为1
+ defaultPageNo: {
+ type: [Number, String],
+ default: _getConfig('defaultPageNo', 1),
+ observer: function(newVal, oldVal) {
+ this.pageNo = newVal;
+ },
+ },
+ //自定义pageSize,默认为10
+ defaultPageSize: {
+ type: [Number, String],
+ default: _getConfig('defaultPageSize', 10),
+ },
+ //为保证数据一致,设置当前tab切换时的标识key,并在complete中传递相同key,若二者不一致,则complete将不会生效
+ dataKey: {
+ type: [Number, Object],
+ default: function() {
+ return _getConfig('dataKey', null);
+ },
+ },
+ //自动注入的list名,可自动修改父view(包含ref="paging")中对应name的list值
+ autowireListName: {
+ type: String,
+ default: function() {
+ return _getConfig('autowireListName', '');
+ },
+ },
+ //自动注入的query名,可自动调用父view(包含ref="paging")中的query方法
+ autowireQueryName: {
+ type: String,
+ default: function() {
+ return _getConfig('autowireQueryName', '');
+ },
+ },
+ //调用complete后延迟处理的时间,单位为毫秒,默认0毫秒
+ delay: {
+ type: [Number, String],
+ default: _getConfig('delay', 0),
+ },
+ //i18n国际化设置语言,支持简体中文(zh-cn)、繁体中文(zh-hant-cn)和英文(en)
+ language: {
+ type: String,
+ default: _getConfig('language', '')
+ },
+ //i18n国际化默认是否跟随系统语言,默认为是
+ followSystemLanguage: {
+ type: Boolean,
+ default: _getConfig('followSystemLanguage', true)
+ },
+ //设置z-paging的style,部分平台可能无法直接修改组件的style,可使用此属性代替
+ pagingStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('pagingStyle', {});
+ },
+ },
+ //设置z-paging的容器(插槽的父view)的style
+ pagingContentStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('pagingContentStyle', {});
+ },
+ },
+ //z-paging是否自动高度,若自动高度则会自动铺满屏幕
+ autoHeight: {
+ type: Boolean,
+ default: _getConfig('autoHeight', false)
+ },
+ //z-paging是否自动高度时,附加的高度,注意添加单位px或rpx,若需要减少高度,则传负数
+ autoHeightAddition: {
+ type: [Number, String],
+ default: _getConfig('autoHeightAddition', '0px')
+ },
+ //loading(下拉刷新、上拉加载更多)的主题样式,支持black,white,默认black
+ defaultThemeStyle: {
+ type: String,
+ default: function() {
+ return _getConfig('defaultThemeStyle', 'black');
+ }
+ },
+ //下拉刷新的主题样式,支持black,white,默认black
+ refresherThemeStyle: {
+ type: String,
+ default: function() {
+ return _getConfig('refresherThemeStyle', '');
+ }
+ },
+ //底部加载更多的主题样式,支持black,white,默认black
+ loadingMoreThemeStyle: {
+ type: String,
+ default: function() {
+ return _getConfig('loadingMoreThemeStyle', '');
+ }
+ },
+ //是否只使用下拉刷新,设置为true后将关闭mounted自动请求数据、关闭滚动到底部加载更多,强制隐藏空数据图。默认为否
+ refresherOnly: {
+ type: Boolean,
+ default: _getConfig('refresherOnly', false)
+ },
+ //使用页面滚动,默认为否,当设置为是时则使用页面的滚动而非此组件内部的scroll-view的滚动,使用页面滚动时z-paging无需设置确定的高度且对于长列表展示性能更高,但配置会略微繁琐
+ usePageScroll: {
+ type: Boolean,
+ default: _getConfig('usePageScroll', false)
+ },
+ //z-paging是否使用fixed布局,若使用fixed布局,则z-paging的父view无需固定高度,z-paging高度默认为100%,默认为否(当使用内置scroll-view滚动时有效)
+ fixed: {
+ type: Boolean,
+ default: _getConfig('fixed', false)
+ },
+ //是否开启底部安全区域适配
+ safeAreaInsetBottom: {
+ type: Boolean,
+ default: _getConfig('safeAreaInsetBottom', false)
+ },
+ //是否可以滚动,使用内置scroll-view和nvue时有效,默认为是
+ scrollable: {
+ type: Boolean,
+ default: _getConfig('scrollable', true)
+ },
+ //z-paging mounted后自动调用reload方法(mounted后自动调用接口),默认为是。请使用简便写法:auto
+ mountedAutoCallReload: {
+ type: Boolean,
+ default: _getConfig('mountedAutoCallReload', true)
+ },
+ //z-paging mounted后自动调用reload方法(mounted后自动调用接口),默认为是
+ auto: {
+ type: Boolean,
+ default: _getConfig('auto', true)
+ },
+ //reload时自动滚动到顶部,默认为否
+ autoScrollToTopWhenReload: {
+ type: Boolean,
+ default: _getConfig('autoScrollToTopWhenReload', false)
+ },
+ //reload时立即自动清空原list,默认为是,若立即自动清空,则在reload之后、请求回调之前页面是空白的
+ autoCleanListWhenReload: {
+ type: Boolean,
+ default: _getConfig('autoCleanListWhenReload', false)
+ },
+ //调用reload方法时自动显示下拉刷新view,默认为否
+ showRefresherWhenReload: {
+ type: Boolean,
+ default: _getConfig('showRefresherWhenReload', false)
+ },
+ //调用reload方法时自动显示加载更多view,且为加载中状态,默认为否
+ showLoadingMoreWhenReload: {
+ type: Boolean,
+ default: _getConfig('showLoadingMoreWhenReload', false)
+ },
+ //是否使用自定义的下拉刷新,默认为是,即使用z-paging的下拉刷新。设置为false即代表使用uni scroll-view自带的下拉刷新,h5、App、微信小程序以外的平台不支持uni scroll-view自带的下拉刷新
+ useCustomRefresher: {
+ type: Boolean,
+ default: _getConfig('useCustomRefresher', true)
+ },
+ //自定义下拉刷新下拉帧率,默认为40,过高可能会出现抖动问题(use-custom-refresher为true时生效)
+ refresherFps: {
+ type: [Number, String],
+ default: _getConfig('refresherFps', 40)
+ },
+ //自定义下拉刷新允许触发的最大下拉角度,默认为40度,当下拉角度小于设定值时,自定义下拉刷新动画不会被触发
+ refresherMaxAngle: {
+ type: [Number, String],
+ default: _getConfig('refresherMaxAngle', 40)
+ },
+ //自定义下拉刷新的角度由未达到最大角度变到达到最大角度时,是否继续下拉刷新手势,默认为否
+ refresherAngleEnableChangeContinued: {
+ type: Boolean,
+ default: _getConfig('refresherAngleEnableChangeContinued', false)
+ },
+ //自定义下拉刷新默认状态下的文字(use-custom-refresher为true时生效)
+ refresherDefaultText: {
+ type: [String, Object],
+ default: _getConfig('refresherDefaultText', null)
+ },
+ //自定义下拉刷新松手立即刷新状态下的文字(use-custom-refresher为true时生效)
+ refresherPullingText: {
+ type: [String, Object],
+ default: _getConfig('refresherPullingText', null)
+ },
+ //自定义下拉刷新刷新中状态下的文字(use-custom-refresher为true时生效)
+ refresherRefreshingText: {
+ type: [String, Object],
+ default: _getConfig('refresherRefreshingText', null)
+ },
+ //是否开启自定义下拉刷新刷新结束回弹效果,默认为是(use-custom-refresher为true时生效)
+ refresherEndBounceEnabled: {
+ type: Boolean,
+ default: _getConfig('refresherEndBounceEnabled', true)
+ },
+ //自定义底部加载更多样式
+ loadingMoreCustomStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('loadingMoreCustomStyle', {});
+ }
+ },
+ //自定义底部加载更多加载中动画样式
+ loadingMoreLoadingIconCustomStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('loadingMoreLoadingIconCustomStyle', {});
+ }
+ },
+ //自定义底部加载更多加载中动画图标类型,可选flower或circle,默认为flower
+ loadingMoreLoadingIconType: {
+ type: String,
+ default: _getConfig('loadingMoreLoadingIconType', 'flower')
+ },
+ //自定义底部加载更多加载中动画图标图片
+ loadingMoreLoadingIconCustomImage: {
+ type: String,
+ default: _getConfig('loadingMoreLoadingIconCustomImage', '')
+ },
+ //底部加载更多加载中view是否展示旋转动画,默认为是
+ loadingMoreLoadingAnimated: {
+ type: Boolean,
+ default: _getConfig('loadingMoreLoadingAnimated', true)
+ },
+ //是否启用加载更多数据(含滑动到底部加载更多数据和点击加载更多数据),默认为是
+ loadingMoreEnabled: {
+ type: Boolean,
+ default: _getConfig('loadingMoreEnabled', true)
+ },
+ //是否启用滑动到底部加载更多数据,默认为是
+ toBottomLoadingMoreEnabled: {
+ type: Boolean,
+ default: _getConfig('toBottomLoadingMoreEnabled', true)
+ },
+ //滑动到底部"默认"文字,默认为【点击加载更多】
+ loadingMoreDefaultText: {
+ type: [String, Object],
+ default: _getConfig('loadingMoreDefaultText', null)
+ },
+ //滑动到底部"加载中"文字,默认为【正在加载...】
+ loadingMoreLoadingText: {
+ type: [String, Object],
+ default: _getConfig('loadingMoreLoadingText', null)
+ },
+ //滑动到底部"没有更多"文字,默认为【没有更多了】
+ loadingMoreNoMoreText: {
+ type: [String, Object],
+ default: _getConfig('loadingMoreNoMoreText', null)
+ },
+ //滑动到底部"加载失败"文字,默认为【加载失败,点击重新加载】
+ loadingMoreFailText: {
+ type: [String, Object],
+ default: _getConfig('loadingMoreFailText', null)
+ },
+ //当没有更多数据且分页内容未超出z-paging时是否隐藏没有更多数据的view,默认为否
+ hideLoadingMoreWhenNoMoreAndInsideOfPaging: {
+ type: Boolean,
+ default: _getConfig('hideLoadingMoreWhenNoMoreAndInsideOfPaging', false)
+ },
+ //当没有更多数据且分页数组长度少于这个值时,隐藏没有更多数据的view,默认为0,代表不限制。
+ hideLoadingMoreWhenNoMoreByLimit: {
+ type: Number,
+ default: _getConfig('hideLoadingMoreWhenNoMoreByLimit', 0)
+ },
+ //当分页未满一屏时,是否自动加载更多,默认为否(nvue无效)
+ insideMore: {
+ type: Boolean,
+ default: _getConfig('insideMore', false)
+ },
+ //是否显示默认的加载更多text,默认为是
+ showDefaultLoadingMoreText: {
+ type: Boolean,
+ default: _getConfig('showDefaultLoadingMoreText', true)
+ },
+ //是否显示没有更多数据的view
+ showLoadingMoreNoMoreView: {
+ type: Boolean,
+ default: _getConfig('showLoadingMoreNoMoreView', true)
+ },
+ //是否显示没有更多数据的分割线,默认为是
+ showLoadingMoreNoMoreLine: {
+ type: Boolean,
+ default: _getConfig('showLoadingMoreNoMoreLine', true)
+ },
+ //自定义底部没有更多数据的分割线样式
+ loadingMoreNoMoreLineCustomStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('loadingMoreNoMoreLineCustomStyle', {});
+ },
+ },
+ //是否强制隐藏空数据图,默认为否
+ hideEmptyView: {
+ type: Boolean,
+ default: _getConfig('hideEmptyView', false)
+ },
+ //空数据图描述文字,默认为“没有数据哦~”
+ emptyViewText: {
+ type: [String, Object],
+ default: _getConfig('emptyViewText', null)
+ },
+ //是否显示空数据图重新加载按钮(无数据时),默认为否
+ showEmptyViewReload: {
+ type: Boolean,
+ default: _getConfig('showEmptyViewReload', false)
+ },
+ //加载失败时是否显示空数据图重新加载按钮,默认为是
+ showEmptyViewReloadWhenError: {
+ type: Boolean,
+ default: _getConfig('showEmptyViewReloadWhenError', true)
+ },
+ //空数据图点击重新加载文字,默认为“重新加载”
+ emptyViewReloadText: {
+ type: [String, Object],
+ default: _getConfig('emptyViewReloadText', null)
+ },
+ //空数据图图片,默认使用z-paging内置的图片
+ emptyViewImg: {
+ type: String,
+ default: _getConfig('emptyViewImg', '')
+ },
+ //空数据图“加载失败”描述文字,默认为“很抱歉,加载失败”
+ emptyViewErrorText: {
+ type: [String, Object],
+ default: _getConfig('emptyViewErrorText', null)
+ },
+ //空数据图“加载失败”图片,默认使用z-paging内置的图片
+ emptyViewErrorImg: {
+ type: String,
+ default: _getConfig('emptyViewErrorImg', '')
+ },
+ //空数据图样式
+ emptyViewStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('emptyViewStyle', {});
+ }
+ },
+ //空数据图img样式
+ emptyViewImgStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('emptyViewImgStyle', {});
+ }
+ },
+ //空数据图描述文字样式
+ emptyViewTitleStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('emptyViewTitleStyle', {});
+ }
+ },
+ //空数据图重新加载按钮样式
+ emptyViewReloadStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('emptyViewReloadStyle', {});
+ }
+ },
+ //加载中时是否自动隐藏空数据图,默认为是
+ autoHideEmptyViewWhenLoading: {
+ type: Boolean,
+ default: _getConfig('autoHideEmptyViewWhenLoading', true)
+ },
+ //第一次加载后自动隐藏loading slot,默认为是
+ autoHideLoadingAfterFirstLoaded: {
+ type: Boolean,
+ default: _getConfig('autoHideLoadingAfterFirstLoaded', true)
+ },
+ //自动显示点击返回顶部按钮,默认为否
+ autoShowBackToTop: {
+ type: Boolean,
+ default: _getConfig('autoShowBackToTop', true)
+ },
+ //点击返回顶部按钮显示/隐藏的阈值(滚动距离),单位为px,默认为400rpx
+ backToTopThreshold: {
+ type: [Number, String],
+ default: _getConfig('backToTopThreshold', '400rpx')
+ },
+ //点击返回顶部按钮的自定义图片地址,默认使用z-paging内置的图片
+ backToTopImg: {
+ type: String,
+ default: _getConfig('backToTopImg', '')
+ },
+ //点击返回顶部按钮返回到顶部时是否展示过渡动画,默认为是
+ backToTopWithAnimate: {
+ type: Boolean,
+ default: _getConfig('backToTopWithAnimate', true)
+ },
+ //点击返回顶部按钮与底部的距离,注意添加单位px或rpx,默认为160rpx
+ backToTopBottom: {
+ type: [Number, String],
+ default: _getConfig('backToTopBottom', '160rpx')
+ },
+ //点击返回顶部按钮的自定义样式
+ backToTopStyle: {
+ type: Object,
+ default: function() {
+ return _getConfig('backToTopStyle', {});
+ },
+ },
+ //控制是否出现滚动条,默认为否
+ showScrollbar: {
+ type: Boolean,
+ default: _getConfig('showScrollbar', false)
+ },
+ //iOS设备上滚动到顶部时是否允许回弹效果,默认为否。关闭回弹效果后可使滚动到顶部与下拉刷新更连贯,但是有吸顶view时滚动到顶部时可能出现抖动。
+ scrollToTopBounceEnabled: {
+ type: Boolean,
+ default: _getConfig('scrollToTopBounceEnabled', false)
+ },
+ //iOS设备上滚动到底部时是否允许回弹效果,默认为是。
+ scrollToBottomBounceEnabled: {
+ type: Boolean,
+ default: _getConfig('scrollToBottomBounceEnabled', true)
+ },
+ //在设置滚动条位置时使用动画过渡,默认为否
+ scrollWithAnimation: {
+ type: Boolean,
+ default: _getConfig('scrollWithAnimation', false)
+ },
+ //值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素
+ scrollIntoView: {
+ type: String,
+ default: _getConfig('scrollIntoView', '')
+ },
+ //距底部/右边多远时(单位px),触发 scrolltolower 事件,默认为100rpx
+ lowerThreshold: {
+ type: [Number, String],
+ default: _getConfig('lowerThreshold', '100rpx')
+ },
+ //iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向,默认为是
+ enableBackToTop: {
+ type: Boolean,
+ default: _getConfig('enableBackToTop', true)
+ },
+ //是否开启自定义下拉刷新,默认为是
+ refresherEnabled: {
+ type: Boolean,
+ default: _getConfig('refresherEnabled', true)
+ },
+ //设置自定义下拉刷新阈值,默认为80rpx
+ refresherThreshold: {
+ type: [Number, String],
+ default: _getConfig('refresherThreshold', '80rpx')
+ },
+ //设置系统下拉刷新默认样式,支持设置 black,white,none,none 表示不使用默认样式,默认为black
+ refresherDefaultStyle: {
+ type: String,
+ default: _getConfig('refresherDefaultStyle', 'black')
+ },
+ //设置自定义下拉刷新区域背景颜色
+ refresherBackground: {
+ type: String,
+ default: _getConfig('refresherBackground', '#ffffff00')
+ },
+ //设置固定的自定义下拉刷新区域背景颜色
+ refresherFixedBackground: {
+ type: String,
+ default: _getConfig('refresherFixedBackground', '#ffffff00')
+ },
+ //设置固定的自定义下拉刷新区域高度,默认为0
+ refresherFixedBacHeight: {
+ type: [Number, String],
+ default: _getConfig('refresherFixedBacHeight', 0)
+ },
+ //设置自定义下拉刷新下拉超出阈值后继续下拉位移衰减的比例,范围0-1,值越大代表衰减越多。默认为0.7(nvue无效)
+ refresherOutRate: {
+ type: Number,
+ default: _getConfig('refresherOutRate', 0.7)
+ },
+ //是否显示最后更新时间,默认为否
+ showRefresherUpdateTime: {
+ type: Boolean,
+ default: _getConfig('showRefresherUpdateTime', false)
+ },
+ //如果需要区别不同页面的最后更新时间,请为不同页面的z-paging的`refresher-update-time-key`设置不同的字符串
+ refresherUpdateTimeKey: {
+ type: String,
+ default: _getConfig('refresherUpdateTimeKey', 'default')
+ },
+ //本地分页时上拉加载更多延迟时间,单位为毫秒,默认200毫秒
+ localPagingLoadingTime: {
+ type: [Number, String],
+ default: _getConfig('localPagingLoadingTime', 200)
+ },
+ //使用聊天记录模式,默认为否
+ useChatRecordMode: {
+ type: Boolean,
+ default: _getConfig('useChatRecordMode', false)
+ },
+ //slot="top"的view的z-index,默认为99,仅使用页面滚动时有效
+ topZIndex: {
+ type: Number,
+ default: _getConfig('topZIndex', 99)
+ },
+ //z-paging内容容器父view的z-index,默认为1
+ superContentZIndex: {
+ type: Number,
+ default: _getConfig('superContentZIndex', 1)
+ },
+ //z-paging内容容器部分的z-index,默认为10
+ contentZIndex: {
+ type: Number,
+ default: _getConfig('contentZIndex', 10)
+ },
+ //空数据view的z-index,默认为9
+ emptyViewZIndex: {
+ type: Number,
+ default: _getConfig('emptyViewZIndex', 9)
+ },
+ //使用页面滚动时,是否在不满屏时自动填充满屏幕,默认为是
+ autoFullHeight: {
+ type: Boolean,
+ default: _getConfig('autoFullHeight', true)
+ },
+ //自动拼接complete中传过来的数组(使用聊天记录模式时无效)
+ concat: {
+ type: Boolean,
+ default: _getConfig('concat', true)
+ },
+ //nvue中修改列表类型,可选值有list、waterfall和scroller,默认为list
+ nvueListIs: {
+ type: String,
+ default: _getConfig('nvueListIs', 'list')
+ },
+ //nvue waterfall配置,仅在nvue中且nvueListIs=waterfall时有效,配置参数详情参见:https://uniapp.dcloud.io/component/waterfall
+ nvueWaterfallConfig: {
+ type: Object,
+ default: function() {
+ return _getConfig('nvueWaterfallConfig', {});
+ }
+ },
+ //nvue 控制是否回弹效果,iOS不支持动态修改
+ nvueBounce: {
+ type: Boolean,
+ default: function() {
+ return _getConfig('nvueBounce', true);
+ }
+ },
+ //nvue中通过代码滚动到顶部/底部时,是否加快动画效果(无滚动动画时无效),默认为否
+ nvueFastScroll: {
+ type: Boolean,
+ default: function() {
+ return _getConfig('nvueFastScroll', false);
+ }
+ },
+ //是否将错误信息打印至控制台,默认为是
+ showConsoleError: {
+ type: Boolean,
+ default: function() {
+ return _getConfig('showConsoleError', true);
+ }
+ },
+ //父组件v-model所绑定的list的值
+ value: {
+ type: Array,
+ default: function() {
+ return [];
+ }
+ }
+ },
+ mounted() {
+ this.wxsPropType = (new Date()).getTime().toString();
+ this.renderJsIgnore;
+ if (!this.refresherOnly && (this.mountedAutoCallReload && this.auto)) {
+ this.$nextTick(() => {
+ this._preReload();
+ })
+ }
+ this.$nextTick(() => {
+ this.systemInfo = uni.getSystemInfoSync();
+ if (!this.usePageScroll && this.autoHeight) {
+ this._setAutoHeight();
+ }
+ this.loaded = true;
+ })
+ this.updatePageScrollTopHeight();
+ this.updatePageScrollBottomHeight();
+ if (this.finalRefresherEnabled && this.useCustomRefresher) {
+ this.$nextTick(() => {
+ this.isTouchmoving = true;
+ })
+ }
+ uni.$on(i18nUpdateKey, () => {
+ this.tempLanguageUpdateKey = (new Date()).getTime();
+ })
+ uni.$on(errorUpdateKey, () => {
+ if (this.loading) {
+ this.complete(false);
+ }
+ })
+ // #ifdef APP-NVUE
+ if (!this.isIos && !this.useChatRecordMode) {
+ this.nLoadingMoreFixedHeight = true;
+ }
+ // #endif
+ },
+ destroyed() {
+ uni.$off(i18nUpdateKey);
+ uni.$off(errorUpdateKey);
+ },
+ watch: {
+ value(newVal, oldVal) {
+ let dataType = Object.prototype.toString.call(newVal);
+ if (dataType === '[object Undefined]') {
+ zUtils.consoleErr('v-model所绑定的值不存在!');
+ return;
+ }
+ if (dataType !== '[object Array]') {
+ zUtils.consoleErr('v-model所绑定的值必须为Array类型!');
+ return;
+ }
+ if (!zUtils.arrayIsEqual(newVal, this.totalData)) {
+ this.totalData = newVal;
+ }
+ },
+ totalData(newVal, oldVal) {
+ if ((!this.isUserReload || !this.autoCleanListWhenReload) && this.firstPageLoaded && !newVal.length &&
+ oldVal.length) {
+ return;
+ }
+ newVal = [...newVal];
+ if (this.autoFullHeight && this.usePageScroll && this.isTotalChangeFromAddData) {
+ this.$nextTick(() => {
+ // this._checkScrollViewShouldFullHeight((scrollViewNode, pagingContainerNode) => {
+ // this._preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(newVal, scrollViewNode,
+ // pagingContainerNode)
+ // });
+ })
+ } else {
+ this._preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(newVal)
+ }
+ if (!this.usePageScroll && (this.pageNo === this.defaultPageNo || this.defaultPageNo + 1)) {
+ setTimeout(() => {
+ this._checkScrollViewOutOfPage();
+ }, commonDelayTime)
+ }
+ this.realTotalData = newVal;
+ this.$emit('input', newVal);
+ this.$emit('update:list', newVal);
+ this.$emit('listChange', newVal);
+ this._callMyParentList(newVal);
+ this.firstPageLoaded = false;
+ this.isTotalChangeFromAddData = false;
+ this.$nextTick(() => {
+ this._getNodeClientRect('.zp-paging-container-content').then((res) => {
+ if (res) {
+ this.$emit('pagingContentHeightChanged', res[0].height);
+ }
+ });
+ // #ifdef APP-NVUE
+ if (this.useChatRecordMode && this.nIsFirstPageAndNoMore && this.pageNo === this
+ .defaultPageNo && !this.nFirstPageAndNoMoreChecked) {
+ this.nFirstPageAndNoMoreChecked = true;
+ this._scrollToBottom(false);
+ }
+ // #endif
+ })
+ },
+ currentData(newVal, oldVal) {
+ this._currentDataChange(newVal, oldVal);
+ },
+ loadingStatus(newVal, oldVal) {
+ this.$emit('loadingStatusChange', newVal);
+ // #ifdef APP-NVUE
+ if (this.useChatRecordMode) {
+ if (this.pageNo === this.defaultPageNo && newVal === 2) {
+ this.nIsFirstPageAndNoMore = true;
+ return;
+ }
+ }
+ this.nIsFirstPageAndNoMore = false;
+ // #endif
+ },
+ oldScrollTop(newVal, oldVal) {
+ if (!this.usePageScroll) {
+ this.$emit('scrollTopChange', newVal);
+ this.$emit('update:scrollTop', newVal);
+ this._checkShouldShowBackToTop(newVal, oldVal);
+ if (this.isIos) {
+ if (newVal > 5) {
+ this.wxsScrollTop = 6;
+ } else {
+ this.wxsScrollTop = 0;
+ }
+ } else {
+ this.wxsScrollTop = newVal;
+ }
+ }
+ },
+ pageScrollTop(newVal, oldVal) {
+ if (this.usePageScroll) {
+ this.$emit('scrollTopChange', newVal);
+ this.$emit('update:scrollTop', newVal);
+ this._checkShouldShowBackToTop(newVal, oldVal);
+ if (this.isIos) {
+ if (newVal > 5) {
+ this.wxsPageScrollTop = 6;
+ } else {
+ this.wxsPageScrollTop = 0;
+ }
+ } else {
+ this.wxsPageScrollTop = newVal;
+ }
+ }
+ },
+ defaultThemeStyle: {
+ handler(newVal) {
+ if (newVal.length) {
+ this.finalRefresherDefaultStyle = newVal;
+ }
+ },
+ immediate: true
+ },
+ usePageScroll: {
+ handler(newVal) {
+ this.$nextTick(() => {
+ this.renderPropUsePageScroll = newVal;
+ })
+ if (this.loaded && this.autoHeight) {
+ this._setAutoHeight(!newVal);
+ }
+ },
+ immediate: true
+ },
+ autoHeight(newVal, oldVal) {
+ if (this.loaded && !this.usePageScroll) {
+ this._setAutoHeight(newVal);
+ }
+ },
+ autoHeightAddition(newVal, oldVal) {
+ if (this.loaded && !this.usePageScroll && this.autoHeight) {
+ this._setAutoHeight(newVal);
+ }
+ },
+ refresherDefaultStyle: {
+ handler(newVal) {
+ if (newVal.length) {
+ this.finalRefresherDefaultStyle = newVal;
+ }
+ },
+ immediate: true
+ },
+ refresherStatus(newVal, oldVal) {
+ if (newVal !== oldVal) {
+ this.$emit('refresherStatusChange', newVal);
+ this.$emit('update:refresherStatus', newVal);
+ }
+ },
+ useChatRecordMode(newVal, oldVal) {
+ if (newVal) {
+ this.nLoadingMoreFixedHeight = false;
+ }
+ },
+ finalScrollTop(newVal, oldVal) {
+ if (!this.useChatRecordMode) {
+ if (newVal < 6) {
+ this.renderPropScrollTop = 0;
+ } else {
+ this.renderPropScrollTop = 10;
+ }
+ }
+ },
+ nIsFirstPageAndNoMore: {
+ handler(newVal) {
+ const cellStyle = !this.useChatRecordMode || newVal ? {} : {
+ transform: 'rotate(180deg)'
+ };
+ this.$emit('update:cellStyle', cellStyle);
+ },
+ immediate: true
+ }
+ },
+ computed: {
+ pageSize() {
+ return this.defaultPageSize;
+ },
+ pullDownDisTimeStamp() {
+ return 1000 / this.refresherFps;
+ },
+ finalRefresherEnabled() {
+ if (this.useChatRecordMode) {
+ return false;
+ }
+ if (this.privateRefresherEnabled === -1) {
+ return this.refresherEnabled;
+ }
+ return this.privateRefresherEnabled === 1;
+ },
+ finalScrollWithAnimation() {
+ if (this.privateScrollWithAnimation !== -1) {
+ const scrollWithAnimation = this.privateScrollWithAnimation === 1;
+ this.privateScrollWithAnimation = -1;
+ return scrollWithAnimation;
+ }
+ return this.scrollWithAnimation;
+ },
+ zPagingLoadMoreConfig() {
+ return {
+ loadingStatus: this.loadingStatus,
+ defaultThemeStyle: this.finalLoadingMoreThemeStyle,
+ loadingMoreCustomStyle: this.loadingMoreCustomStyle,
+ loadingMoreLoadingIconCustomStyle: this.loadingMoreLoadingIconCustomStyle,
+ loadingMoreLoadingIconType: this.loadingMoreLoadingIconType,
+ loadingMoreLoadingIconCustomImage: this.loadingMoreLoadingIconCustomImage,
+ loadingMoreLoadingAnimated: this.loadingMoreLoadingAnimated,
+ showLoadingMoreNoMoreLine: this.showLoadingMoreNoMoreLine,
+ loadingMoreNoMoreLineCustomStyle: this.loadingMoreNoMoreLineCustomStyle,
+ loadingMoreDefaultText: this.finalLoadingMoreDefaultText,
+ loadingMoreLoadingText: this.finalLoadingMoreLoadingText,
+ loadingMoreNoMoreText: this.finalLoadingMoreNoMoreText,
+ loadingMoreFailText: this.finalLoadingMoreFailText
+ };
+ },
+ zScopedSlots() {
+ return this.$scopedSlots;
+ },
+ finalNvueListIs() {
+ if (this.usePageScroll) {
+ return 'view';
+ }
+ const nvueListIsLowerCase = this.nvueListIs.toLowerCase();
+ if (nvueListIsLowerCase === 'list' || nvueListIsLowerCase === 'waterfall' || nvueListIsLowerCase ===
+ 'scroller') {
+ return nvueListIsLowerCase;
+ }
+ return 'list';
+ },
+ finalNvueSuperListIs() {
+ if (this.usePageScroll) {
+ return 'view';
+ }
+ return 'scroller';
+ },
+ finalPagingStyle() {
+ let pagingStyle = this.pagingStyle;
+ if (!this.systemInfo) {
+ return pagingStyle;
+ }
+ const windowTop = this.systemInfo.windowTop;
+ const windowBottom = this.systemInfo.windowBottom;
+ if (!this.usePageScroll && this.fixed) {
+ if (windowTop && windowTop !== undefined) {
+ pagingStyle.top = windowTop + 'px';
+ }
+ let bottom = 0;
+ if (windowBottom && windowBottom !== undefined) {
+ bottom = windowBottom;
+ }
+ if (this.safeAreaInsetBottom) {
+ bottom += this.safeAreaBottom;
+ }
+ pagingStyle.bottom = bottom + 'px';
+ }
+ return pagingStyle;
+ },
+ finalEnableBackToTop() {
+ if (this.usePageScroll) {
+ return false;
+ }
+ return this.enableBackToTop;
+ },
+ finalBackToTopThreshold() {
+ return this._convertTextToPx(this.backToTopThreshold);
+ },
+ finalLowerThreshold() {
+ return this._convertTextToPx(this.lowerThreshold);
+ },
+ finalRefresherThreshold() {
+ let refresherThreshold = this.refresherThreshold;
+ let idDefault = false;
+ if (refresherThreshold === '80rpx') {
+ idDefault = true;
+ if (this.showRefresherUpdateTime) {
+ refresherThreshold = '120rpx';
+ }
+ }
+ if (idDefault && this.customRefresherHeight > 0) {
+ return this.customRefresherHeight;
+ }
+ return this._convertTextToPx(refresherThreshold);
+ },
+ finalRefresherFixedBacHeight() {
+ return this._convertTextToPx(this.refresherFixedBacHeight);
+ },
+ finalScrollTop() {
+ if (this.usePageScroll) {
+ return this.pageScrollTop;
+ }
+ return this.oldScrollTop;
+ },
+ finalBackToTopStyle() {
+ let tempBackToTopStyle = this.backToTopStyle;
+ if (!tempBackToTopStyle.bottom) {
+ tempBackToTopStyle.bottom = this.windowBottom + this._convertTextToPx(this.backToTopBottom) + 'px';
+ }
+ return tempBackToTopStyle;
+ },
+ finalTempLanguage() {
+ if (this.language.length) {
+ return this.language;
+ }
+ return this.tempLanguage;
+ },
+ finalLanguage() {
+ let language = this.finalTempLanguage.toLowerCase();
+ return zI18n.getPrivateLanguage(language, this.followSystemLanguage);
+ },
+ finalRefresherDefaultText() {
+ return this._getI18nText('refresherDefaultText', this.refresherDefaultText);
+ },
+ finalRefresherPullingText() {
+ return this._getI18nText('refresherPullingText', this.refresherPullingText);
+ },
+ finalRefresherRefreshingText() {
+ return this._getI18nText('refresherRefreshingText', this.refresherRefreshingText);
+ },
+ finalLoadingMoreDefaultText() {
+ return this._getI18nText('loadingMoreDefaultText', this.loadingMoreDefaultText);
+ },
+ finalLoadingMoreLoadingText() {
+ return this._getI18nText('loadingMoreLoadingText', this.loadingMoreLoadingText);
+ },
+ finalLoadingMoreNoMoreText() {
+ return this._getI18nText('loadingMoreNoMoreText', this.loadingMoreNoMoreText);
+ },
+ finalLoadingMoreFailText() {
+ return this._getI18nText('loadingMoreFailText', this.loadingMoreFailText);
+ },
+ finalEmptyViewText() {
+ if (this.isLoadFailed) {
+ return this.finalEmptyViewErrorText;
+ } else {
+ return this._getI18nText('emptyViewText', this.emptyViewText);
+ }
+ },
+ finalEmptyViewReloadText() {
+ return this._getI18nText('emptyViewReloadText', this.emptyViewReloadText);
+ },
+ finalEmptyViewErrorText() {
+ return this._getI18nText('emptyViewErrorText', this.emptyViewErrorText);
+ },
+ finalEmptyViewImg() {
+ if (this.isLoadFailed) {
+ return this.emptyViewErrorImg;
+ } else {
+ return this.emptyViewImg;
+ }
+ },
+ finalShowEmptyViewReload() {
+ if (this.isLoadFailed) {
+ return this.showEmptyViewReloadWhenError;
+ } else {
+ return this.showEmptyViewReload;
+ }
+ },
+ finalRefresherThemeStyle() {
+ if (this.refresherThemeStyle.length) {
+ return this.refresherThemeStyle;
+ }
+ return this.defaultThemeStyle;
+ },
+ finalLoadingMoreThemeStyle() {
+ if (this.loadingMoreThemeStyle.length) {
+ return this.loadingMoreThemeStyle;
+ }
+ return this.defaultThemeStyle;
+ },
+ finalPagingContentStyle() {
+ if (this.contentZIndex != 1) {
+ this.pagingContentStyle['z-index'] = this.contentZIndex;
+ this.pagingContentStyle['position'] = 'relative';
+ }
+ return this.pagingContentStyle;
+ },
+ finalScrollViewStyle() {
+ if (this.superContentZIndex != 1) {
+ this.scrollViewStyle['z-index'] = this.superContentZIndex;
+ this.scrollViewStyle['position'] = 'relative';
+ }
+ return this.scrollViewStyle;
+ },
+ finalRefresherOutRate() {
+ if (this.refresherOutRate < 0) {
+ return 0;
+ }
+ if (this.refresherOutRate > 1) {
+ return 1;
+ }
+ return this.refresherOutRate;
+ },
+ finalRefresherTransform() {
+ if (this.refresherTransform === 'translateY(0px)') {
+ return 'none';
+ }
+ return this.refresherTransform;
+ },
+ showEmpty() {
+ const showEmpty = !this.refresherOnly && !this.totalData.length && (this.autoHideEmptyViewWhenLoading ? this
+ .isAddedData : true) && !this.hideEmptyView && (this.autoHideEmptyViewWhenLoading ? (!this
+ .firstPageLoaded && !this.loading) : true);
+ return showEmpty;
+ },
+ tempLanguage() {
+ let systemLanguage = false;
+ const temp = this.tempLanguageUpdateKey;
+ if (this.followSystemLanguage) {
+ systemLanguage = systemInfo.language;
+ }
+ return uni.getStorageSync(i18nUpdateKey) || systemLanguage || 'zh-cn';
+ },
+ safeAreaBottom() {
+ if (!this.systemInfo) {
+ return 0;
+ }
+ let safeAreaBottom = 0;
+ // #ifdef MP-WEIXIN
+ safeAreaBottom = this.systemInfo.screenHeight - this.systemInfo.safeArea.bottom;
+ // #endif
+ // #ifdef APP-PLUS || H5
+ safeAreaBottom = this.systemInfo.safeAreaInsets.bottom || 0;
+ // #endif
+ return Math.abs(safeAreaBottom);
+ },
+ renderJsIgnore() {
+ if ((this.usePageScroll && this.useChatRecordMode) || !this.refresherEnabled || !this.useCustomRefresher) {
+ this.$nextTick(() => {
+ this.renderPropScrollTop = 10;
+ })
+ }
+ return 0;
+ },
+ windowTop() {
+ if (!this.systemInfo) {
+ return 0;
+ }
+ const windowTop = this.systemInfo.windowTop;
+ return windowTop || 0;
+ },
+ windowBottom() {
+ if (!this.systemInfo) {
+ return 0;
+ }
+ let windowBottom = this.systemInfo.windowBottom || 0;
+ if (this.safeAreaInsetBottom) {
+ windowBottom += this.safeAreaBottom;
+ }
+ return windowBottom;
+ },
+ showRefresher() {
+ const showRefresher = this.finalRefresherEnabled && this.useCustomRefresher && this.isTouchmoving;
+ // #ifndef APP-NVUE
+ if (this.customRefresherHeight === -1 && showRefresher) {
+ setTimeout(() => {
+ this._updateCustomRefresherHeight();
+ }, 100)
+ }
+ // #endif
+ return showRefresher;
+ },
+ nWaterfallColumnCount() {
+ if (this.finalNvueListIs !== 'waterfall') {
+ return 0;
+ }
+ return this._getNvueWaterfallSingleConfig('column-count', 2);
+ },
+ nWaterfallColumnWidth() {
+ return this._getNvueWaterfallSingleConfig('column-width', 'auto');
+ },
+ nWaterfallColumnGap() {
+ return this._getNvueWaterfallSingleConfig('column-gap', 'normal');
+ },
+ nWaterfallLeftGap() {
+ return this._getNvueWaterfallSingleConfig('left-gap', 0);
+ },
+ nWaterfallRightGap() {
+ return this._getNvueWaterfallSingleConfig('right-gap', 0);
+ },
+ nViewIs() {
+ const finalNvueListIs = this.finalNvueListIs;
+ return finalNvueListIs === 'scroller' || finalNvueListIs === 'view' ? 'view' : finalNvueListIs ===
+ 'waterfall' ? 'header' : 'cell';
+ },
+ nSafeAreaBottomHeight() {
+ return this.safeAreaInsetBottom ? this.safeAreaBottom : 0;
+ }
+ },
+ methods: {
+ //请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否成功(默认是是)
+ complete(data, success = true) {
+ this.customNoMore = -1;
+ this.addData(data, success);
+ },
+ //【保证数据一致】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为dataKey,需与:data-key绑定的一致,第三个参数为是否成功(默认为是)
+ completeByKey(data, dataKey = null, success = true) {
+ if (dataKey !== null && this.dataKey !== null && dataKey !== this.dataKey) {
+ return;
+ }
+ this.customNoMore = -1;
+ this.addData(data, success);
+ },
+ //【通过totalCount判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为totalCount(列表总数),第三个参数为是否成功(默认为是)
+ completeByTotalCount(data, totalCount, success = true) {
+ if (totalCount == 'undefined') {
+ this.customNoMore = -1;
+ } else {
+ let dataTypeRes = this._checkDataType(data, success, false);
+ data = dataTypeRes.data;
+ success = dataTypeRes.success;
+ if (totalCount >= 0 && success) {
+ this.$nextTick(() => {
+ let nomore = true;
+ let realTotalDataCount = this.realTotalData.length;
+ if (this.pageNo == this.defaultPageNo) {
+ realTotalDataCount = 0;
+ }
+ let exceedCount = realTotalDataCount + data.length - totalCount;
+ if (exceedCount >= 0) {
+ nomore = false;
+ exceedCount = this.defaultPageSize - exceedCount;
+ if (exceedCount > 0 && exceedCount < data.length) {
+ data = data.splice(0, exceedCount);
+ }
+ }
+ this.completeByNoMore(data, nomore, success);
+ })
+ return;
+ }
+ }
+ this.addData(data, success);
+ },
+ //【自行判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否有更多数据,第三个参数为是否成功(默认是是)
+ completeByNoMore(data, nomore, success = true) {
+ if (nomore != 'undefined') {
+ this.customNoMore = nomore == true ? 1 : 0;
+ }
+ this.addData(data, success);
+ },
+ //与上方complete方法功能一致,新版本中设置服务端回调数组请使用complete方法
+ addData(data, success = true) {
+ this.$nextTick(() => {
+ if (this.delay > 0) {
+ setTimeout(() => {
+ this._addData(data, success, false);
+ }, this.delay)
+ } else {
+ this._addData(data, success, false);
+ }
+ })
+ },
+ //设置i18n国际化语言
+ setI18n(language) {
+ zI18n.setLanguage(language);
+ },
+ //获取当前z-paging的语言
+ getLanguage() {
+ return this.finalLanguage;
+ },
+ //当前版本号
+ getVersion() {
+ return `z-paging ${currentVersion}`;
+ },
+ //添加聊天记录
+ addChatRecordData(data, toBottom = true, toBottomWithAnimate = true) {
+ let dataType = Object.prototype.toString.call(data);
+ if (dataType !== '[object Array]') {
+ data = [data];
+ }
+ if (!this.useChatRecordMode) {
+ return;
+ }
+ this.isTotalChangeFromAddData = true;
+ //#ifndef APP-NVUE
+ this.totalData = [...this.totalData, ...data];
+ //#endif
+ //#ifdef APP-NVUE
+ if (this.nIsFirstPageAndNoMore) {
+ this.totalData = [...this.totalData, ...data];
+ } else {
+ this.totalData = [...data, ...this.totalData];
+ }
+ //#endif
+ if (toBottom) {
+ setTimeout(() => {
+ //#ifndef APP-NVUE
+ this._scrollToBottom(toBottomWithAnimate);
+ //#endif
+ //#ifdef APP-NVUE
+ if (this.nIsFirstPageAndNoMore) {
+ this._scrollToBottom(toBottomWithAnimate);
+ } else {
+ this._scrollToTop(toBottomWithAnimate);
+ }
+ //#endif
+ }, commonDelayTime)
+ }
+ },
+ //从顶部添加数据,不会影响分页的pageNo和pageSize
+ addDataFromTop(data, toTop = true, toTopWithAnimate = true) {
+ let dataType = Object.prototype.toString.call(data);
+ if (dataType !== '[object Array]') {
+ data = [data];
+ }
+ this.totalData = [...data, ...this.totalData];
+ if (toTop) {
+ setTimeout(() => {
+ this._scrollToTop(toTopWithAnimate);
+ }, commonDelayTime)
+ }
+ },
+ //重新设置列表数据,调用此方法不会影响pageNo和pageSize,也不会触发请求。适用场景:当需要删除列表中某一项时,将删除对应项后的数组通过此方法传递给z-paging。(当出现类似的需要修改列表数组的场景时,请使用此方法,请勿直接修改page中:list.sync绑定的数组)
+ resetTotalData(data) {
+ if (data == undefined) {
+ if (this.showConsoleError) {
+ zUtils.consoleErr('方法resetTotalData参数缺失!');
+ }
+ return;
+ }
+ this.isTotalChangeFromAddData = true;
+ let dataType = Object.prototype.toString.call(data);
+ if (dataType !== '[object Array]') {
+ data = [data];
+ }
+ this.totalData = data;
+ },
+ //设置本地分页数据,请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging作分页处理(若调用了此方法,则上拉加载更多时内部会自动分页,不会触发@query所绑定的事件)
+ setLocalPaging(data, success = true) {
+ this.isLocalPaging = true;
+ this.$nextTick(() => {
+ this._addData(data, success, true);
+ })
+ },
+ //重新加载分页数据,pageNo会恢复为默认值,相当于下拉刷新的效果(animate为true时会展示下拉刷新动画,默认为false)
+ reload(animate = this.showRefresherWhenReload) {
+ if (animate) {
+ this.privateShowRefresherWhenReload = animate;
+ this.isUserPullDown = true;
+ }
+ this._preReload(animate, false);
+ },
+ //清空分页数据
+ clean() {
+ this._reload(true);
+ this._addData([], true, false);
+ },
+ //手动触发滚动到顶部加载更多,聊天记录模式时有效
+ doChatRecordLoadMore() {
+ if (this.useChatRecordMode) {
+ this._onLoadingMore('click');
+ }
+ },
+ //手动触发上拉加载更多(非必须,可依据具体需求使用)
+ doLoadMore() {
+ this._onLoadingMore('toBottom');
+ },
+ //手动停止下拉刷新加载
+ endRefresh() {
+ this.refresherTriggered = false;
+ },
+ //滚动到顶部,animate为是否展示滚动动画,默认为是
+ scrollToTop(animate) {
+ this.$nextTick(() => {
+ this._scrollToTop(animate, false);
+ // #ifdef APP-NVUE
+ if (this.nvueFastScroll && animate) {
+ setTimeout(() => {
+ this._scrollToTop(false, false);
+ }, 150);
+ }
+ // #endif
+ })
+ },
+ //滚动到底部,animate为是否展示滚动动画,默认为是
+ scrollToBottom(animate) {
+ this.$nextTick(() => {
+ this._scrollToBottom(animate);
+ // #ifdef APP-NVUE
+ if (this.nvueFastScroll && animate) {
+ setTimeout(() => {
+ this._scrollToBottom(false);
+ }, 150);
+ }
+ // #endif
+ })
+ },
+ //滚动到指定view(vue中有效)。sel为需要滚动的view的id值,不包含"#";offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
+ scrollIntoViewById(sel, offset, animate) {
+ this._scrollIntoView(sel, offset, animate);
+ },
+ //滚动到指定view(vue中有效)。nodeTop为需要滚动的view的top值(通过uni.createSelectorQuery()获取);offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
+ scrollIntoViewByNodeTop(nodeTop, offset, animate) {
+ this.scrollTop = this.oldScrollTop;
+ this.$nextTick(() => {
+ this._scrollIntoViewByNodeTop(nodeTop, offset, animate);
+ })
+ },
+ //滚动到指定view(nvue中有效)。index为需要滚动的view的index(第几个);offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
+ scrollIntoViewByIndex(index, offset, animate) {
+ this._scrollIntoView(index, offset, animate);
+ },
+ //滚动到指定view(nvue中有效)。view为需要滚动的view(通过`this.$refs.xxx`获取),不包含"#";offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
+ scrollIntoViewByView(view, offset, animate) {
+ this._scrollIntoView(view, offset, animate);
+ },
+ //当使用页面滚动并且自定义下拉刷新时,请在页面的onPageScroll中调用此方法,告知z-paging当前的pageScrollTop,否则会导致在任意位置都可以下拉刷新
+ updatePageScrollTop(value) {
+ if (value == undefined) {
+ //zUtils.consoleErr('updatePageScrollTop方法缺少参数,请将页面onPageScroll事件中的scrollTop传递给此方法');
+ return;
+ }
+ this.pageScrollTop = value;
+ },
+ //当使用页面滚动并且设置了slot="top"时,默认初次加载会自动获取其高度,并使内部容器下移,当slot="top"的view高度动态改变时,在其高度需要更新时调用此方法
+ updatePageScrollTopHeight() {
+ this._updatePageScrollTopOrBottomHeight('top');
+ },
+ //当使用页面滚动并且设置了slot="bottom"时,默认初次加载会自动获取其高度,并使内部容器下移,当slot="bottom"的view高度动态改变时,在其高度需要更新时调用此方法
+ updatePageScrollBottomHeight() {
+ this._updatePageScrollTopOrBottomHeight('bottom');
+ },
+ //更新z-paging内置scroll-view的scrollTop
+ updateScrollViewScrollTop(scrollTop, animate = true) {
+ this.privateScrollWithAnimation = animate ? 1 : 0;
+ this.scrollTop = this.oldScrollTop;
+ this.$nextTick(() => {
+ this.scrollTop = scrollTop;
+ this.oldScrollTop = this.scrollTop;
+ });
+ },
+ //设置nvue List的specialEffects
+ setListSpecialEffects(args) {
+ this.nFixFreezing = args !== {};
+ if (!this.usePageScroll) {
+ this.$refs['n-list'].setSpecialEffects(args);
+ }
+ },
+ handleRefresherStatusChanged(func) {
+ this.refresherStatusChangedFunc = func;
+ },
+ //------------------ 私有方法 ------------------------
+ //reload之前的一些处理
+ _preReload(animate = this.showRefresherWhenReload, isFromMounted = true) {
+ this.isUserReload = true;
+ if (animate) {
+ this.privateShowRefresherWhenReload = animate;
+ // #ifndef APP-NVUE
+ if (this.useCustomRefresher) {
+ this._doRefresherRefreshAnimate();
+ } else {
+ this.refresherTriggered = true;
+ }
+ // #endif
+ // #ifdef APP-NVUE
+ this.refresherStatus = 2;
+ this.refresherRevealStackCount++;
+ setTimeout(() => {
+ this._getNodeClientRect('zp-n-refresh-container', false).then((node) => {
+ if (node) {
+ let nodeHeight = node[0].height;
+ this.nShowRefresherReveal = true;
+ this.nShowRefresherRevealHeight = nodeHeight;
+ setTimeout(() => {
+ this._nDoRefresherEndAnimation(0, -nodeHeight, false, false);
+ setTimeout(() => {
+ this._nDoRefresherEndAnimation(nodeHeight, 0);
+ }, 10)
+ }, 10)
+ this._reload(false, isFromMounted);
+ } else {
+ this._reload(false, isFromMounted);
+ }
+ });
+ }, 10)
+ return;
+ // #endif
+ } else {
+ this._refresherEnd(false, false);
+ }
+ this._reload(false, isFromMounted);
+ },
+ //重新加载分页数据
+ _reload(isClean = false, isFromMounted = false) {
+ this.isAddedData = false;
+ this.cacheScrollNodeHeight = -1;
+ this.insideOfPaging = -1;
+ this.pageNo = this.defaultPageNo;
+ if (!isClean) {
+ this._startLoading(true);
+ }
+ this.firstPageLoaded = true;
+ this.isTotalChangeFromAddData = false;
+ this.totalData = [];
+ if (!isClean) {
+ this.$emit('query', this.pageNo, this.defaultPageSize);
+ let delay = 0;
+ // #ifdef MP-TOUTIAO
+ delay = 5;
+ // #endif
+ setTimeout(() => {
+ this._callMyParentQuery();
+ }, delay)
+ if (!isFromMounted && this.autoScrollToTopWhenReload) {
+ let checkedNRefresherLoading = true;
+ // #ifdef APP-NVUE
+ checkedNRefresherLoading = !this.nRefresherLoading;
+ // #endif
+ if (checkedNRefresherLoading) {
+ this._scrollToTop(false);
+ }
+ }
+ // #ifndef APP-NVUE
+ if (!this.usePageScroll && this.useChatRecordMode) {
+ if (this.showConsoleError) {
+ zUtils.consoleWarn('使用聊天记录模式时,建议使用页面滚动,可���usePageScroll设置为true以启用页面滚动!!');
+ }
+ }
+ // #endif
+ }
+ this.$nextTick(() => {
+ if (!this.realTotalData.length) {
+ // #ifdef APP-NVUE
+ this.nShowBottom = false;
+ // #endif
+ }
+ })
+ },
+ //处理服务端返回的数组
+ _addData(data, success, isLocal) {
+ this.isAddedData = true;
+ this.isTotalChangeFromAddData = true;
+ if (!this.useCustomRefresher) {
+ uni.stopPullDownRefresh();
+ }
+ // #ifdef APP-NVUE
+ if (this.usePageScroll) {
+ uni.stopPullDownRefresh();
+ }
+ // #endif
+ if (this.isUserPullDown && this.showRefresherUpdateTime && this.pageNo === this.defaultPageNo) {
+ zUtils.setRefesrherTime((new Date()).getTime(), this.refresherUpdateTimeKey);
+ this.tempLanguageUpdateKey = (new Date()).getTime();
+ if (this.$refs.refresh) {
+ this.$refs.refresh.updateTime();
+ }
+ }
+ if (this.isUserPullDown && this.pageNo === this.defaultPageNo) {
+ this.isUserPullDown = false;
+ }
+ let dataTypeRes = this._checkDataType(data, success, true);
+ data = dataTypeRes.data;
+ success = dataTypeRes.success;
+ if (this.refresherTriggered) {
+ this.refresherTriggered = false;
+ }
+ let delayTime = commonDelayTime;
+ // #ifdef APP-NVUE
+ if (this.useChatRecordMode) {
+ delayTime = 0
+ }
+ // #endif
+ setTimeout(() => {
+ this._refresherEnd(true, true);
+ this.pagingLoaded = true;
+ }, delayTime)
+ if (this.pageNo === this.defaultPageNo) {
+ this.isLoadFailed = !success;
+ }
+ if (success) {
+ this.loadingStatus = 0;
+ if (isLocal) {
+ this.totalLocalPagingList = data;
+ this._localPagingQueryList(this.defaultPageNo, this.defaultPageSize, 0, (res) => {
+ this.complete(res);
+ })
+ } else {
+ this._currentDataChange(data, this.currentData);
+ }
+ } else {
+ this._currentDataChange(data, this.currentData);
+ this.loadingStatus = 3;
+ if (this.loadingType === 1) {
+ this.pageNo--;
+ }
+ }
+ },
+ //当前数据改变时调用
+ _currentDataChange(newVal, oldVal) {
+ newVal = [...newVal];
+ // #ifndef APP-NVUE
+ if (this.useChatRecordMode) {
+ newVal.reverse();
+ }
+ // #endif
+ if (this.pageNo === this.defaultPageNo && this.concat) {
+ this.totalData = [];
+ }
+ if (this.customNoMore !== -1) {
+ if (this.customNoMore === 0 || !newVal.length) {
+ this.loadingStatus = 2;
+ }
+ } else {
+ if (!newVal.length ||
+ (newVal.length && newVal.length < this.defaultPageSize)) {
+ this.loadingStatus = 2;
+ }
+ }
+ if (!this.totalData.length) {
+ if (this.concat) {
+ this.totalData = newVal;
+ }
+ if (this.useChatRecordMode) {
+ // #ifndef APP-NVUE
+ this.$nextTick(() => {
+ this._scrollToBottom(false);
+ })
+ // #endif
+ }
+ } else {
+ if (this.useChatRecordMode) {
+ // #ifdef APP-NVUE
+ this.totalData = [...this.totalData, ...newVal];
+ // #endif
+ //#ifndef APP-NVUE
+ const idIndex = newVal.length;
+ let idIndexStr = `z-paging-${idIndex}`;
+ this.totalData = [...newVal, ...this.totalData];
+ if (this.pageNo !== this.defaultPageNo) {
+ this.privateScrollWithAnimation = 0;
+ let delayTime = 200;
+ //#ifdef H5
+ delayTime = 0;
+ //#endif
+ this.$emit('update:chatIndex', idIndex);
+ if (this.usePageScroll) {
+ this._scrollIntoView(idIndexStr, 30, false, () => {
+ this.$emit('update:chatIndex', 0);
+ });
+ } else {
+ setTimeout(() => {
+ this._scrollIntoView(idIndexStr, 30, false, () => {
+ this.$emit('update:chatIndex', 0);
+ });
+ }, delayTime)
+ }
+ } else {
+ this.$nextTick(() => {
+ this._scrollToBottom(false);
+ })
+ }
+ //#endif
+
+ } else {
+ if (this.concat) {
+ this.totalData = [...this.totalData, ...newVal];
+ }
+ }
+ }
+ },
+ //通过@scroll事件检测是否滚动到了底部
+ _checkScrolledToBottom(scrollDiff, checked = false) {
+ if (this.checkScrolledToBottomTimeOut) {
+ clearTimeout(this.checkScrolledToBottomTimeOut);
+ this.checkScrolledToBottomTimeOut = null;
+ }
+ if (this.cacheScrollNodeHeight === -1) {
+ this._getNodeClientRect('.zp-scroll-view').then((res) => {
+ if (res) {
+ let pageScrollNodeHeight = res[0].height;
+ this.cacheScrollNodeHeight = pageScrollNodeHeight;
+ if (scrollDiff - pageScrollNodeHeight <= this.finalLowerThreshold) {
+ this._onLoadingMore('toBottom');
+ }
+ }
+ });
+ } else {
+ if (scrollDiff - this.cacheScrollNodeHeight <= this.finalLowerThreshold) {
+ this._onLoadingMore('toBottom');
+ } else if (scrollDiff - this.cacheScrollNodeHeight <= 500 && !checked) {
+ this.checkScrolledToBottomTimeOut = setTimeout(() => {
+ this._getNodeClientRect('.zp-scroll-view', true, true).then((res) => {
+ this.oldScrollTop = res[0].scrollTop;
+ const newScrollDiff = res[0].scrollHeight - this.oldScrollTop;
+ this._checkScrolledToBottom(newScrollDiff, true);
+ })
+ }, 150)
+ }
+ }
+ },
+ //触发加载更多时调用,from:0-滑动到底部触发;1-点击加载更多触发
+ _onLoadingMore(from = 'click') {
+ if (from === 'toBottom') {
+ if (!this.scrollToBottomBounceEnabled) {
+ if (this.scrollEnable) {
+ this.scrollEnable = false;
+ this.$nextTick(() => {
+ this.scrollEnable = true;
+ })
+ }
+ }
+ //#ifdef APP-VUE || H5
+ if (this.isIos) {
+ this.renderPropUsePageScroll = -1;
+ this.$nextTick(() => {
+ this.renderPropUsePageScroll = this.usePageScroll;
+ })
+ }
+ //#endif
+ }
+ this.$emit('scrolltolower', from);
+ if (from === 'toBottom' && (!this.toBottomLoadingMoreEnabled || this.useChatRecordMode)) {
+ return;
+ }
+ if (this.refresherOnly || !this.loadingMoreEnabled || !(this.loadingStatus === 0 || 3) || this.loading)
+ return;
+ this._doLoadingMore();
+ },
+ //当滚动到顶部时
+ _scrollToUpper() {
+ this.$emit('scrolltoupper');
+ this.$emit('scrollTopChange', 0);
+ this.$nextTick(() => {
+ this.oldScrollTop = 0;
+ })
+ if (!this.useChatRecordMode) {
+ return;
+ }
+ if (this.loadingStatus === 2) {
+ return;
+ }
+
+ this._onLoadingMore('click');
+ },
+ //点击返回顶部
+ _backToTopClick() {
+ if (!this.backToTopWithAnimate) {
+ this._checkShouldShowBackToTop(1, 0);
+ }
+ this.scrollToTop(this.backToTopWithAnimate);
+ },
+ //滚动到顶部
+ _scrollToTop(animate, isPrivate = true) {
+ // #ifdef APP-NVUE
+ const el = this.$refs['zp-n-list-top-tag'];
+ if (this.usePageScroll) {
+ this._getNodeClientRect('zp-page-scroll-top', false).then((node) => {
+ if (node) {
+ let nodeHeight = node[0].height;
+ weexDom.scrollToElement(el, {
+ offset: -nodeHeight,
+ animated: animate
+ });
+ }
+ });
+ } else {
+ weexDom.scrollToElement(el, {
+ offset: 0,
+ animated: animate
+ });
+ }
+ return;
+ // #endif
+ if (this.usePageScroll) {
+ this.$nextTick(() => {
+ uni.pageScrollTo({
+ scrollTop: 0,
+ duration: animate ? 100 : 0,
+ });
+ });
+ return;
+ }
+ this.privateScrollWithAnimation = animate ? 1 : 0;
+ this.scrollTop = this.oldScrollTop;
+ this.$nextTick(() => {
+ this.scrollTop = 0;
+ this.oldScrollTop = this.scrollTop;
+ });
+ },
+ //滚动到底部
+ async _scrollToBottom(animate = true) {
+ // #ifdef APP-NVUE
+ const el = this.$refs['zp-n-list-bottom-tag'];
+ weexDom.scrollToElement(el, {
+ offset: 0,
+ animated: animate
+ });
+ return;
+ // #endif
+ if (this.usePageScroll) {
+ this.$nextTick(() => {
+ uni.pageScrollTo({
+ scrollTop: Number.MAX_VALUE,
+ duration: animate ? 100 : 0,
+ });
+ });
+ return;
+ }
+ try {
+ this.privateScrollWithAnimation = animate ? 1 : 0;
+ let pagingContainerH = 0;
+ let scrollViewH = 0;
+ const pagingContainerNode = await this._getNodeClientRect('.zp-paging-container');
+ const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view');
+ if (pagingContainerNode) {
+ pagingContainerH = pagingContainerNode[0].height;
+ }
+ if (scrollViewNode) {
+ scrollViewH = scrollViewNode[0].height;
+ }
+ if (pagingContainerH > scrollViewH) {
+ this.scrollTop = this.oldScrollTop;
+ this.$nextTick(() => {
+ this.scrollTop = pagingContainerH - scrollViewH;
+ this.oldScrollTop = this.scrollTop;
+ });
+ }
+ } catch (e) {
+
+ }
+ },
+ //滚动到指定view
+ _scrollIntoView(sel, offset = 0, animate = false, finishCallback) {
+ try {
+ this.scrollTop = this.oldScrollTop;
+ this.$nextTick(() => {
+ // #ifdef APP-NVUE
+ const refs = this.$parent.$refs;
+ if (!refs) {
+ return;
+ }
+ const dataType = Object.prototype.toString.call(sel);
+ let el = null;
+ if (dataType === '[object Number]') {
+ const els = refs[`z-paging-${sel}`];
+ el = els ? els[0] : null;
+ } else if (dataType === '[object Array]') {
+ el = sel[0];
+ } else {
+ el = sel;
+ }
+ if (el) {
+ weexDom.scrollToElement(el, {
+ offset: -offset,
+ animated: animate
+ });
+ } else {
+ zUtils.consoleErr('在nvue中滚动到指定位置,cell必须设置 :ref="`z-paging-${index}`"');
+ }
+ return;
+ // #endif
+ if (sel.indexOf('#') != -1) {
+ sel = sel.replace('#', '');
+ }
+ this._getNodeClientRect('#' + sel, false).then((node) => {
+ if (node) {
+ let nodeTop = node[0].top;
+ this._scrollIntoViewByNodeTop(nodeTop, offset, animate);
+ if (finishCallback) {
+ finishCallback();
+ }
+ }
+ });
+ });
+ } catch (e) {
+
+ }
+ },
+ //通过nodeTop滚动到指定view
+ _scrollIntoViewByNodeTop(nodeTop, offset = 0, animate = false) {
+ this.privateScrollWithAnimation = animate ? 1 : 0;
+ if (this.usePageScroll) {
+ uni.pageScrollTo({
+ scrollTop: nodeTop - offset,
+ duration: animate ? 100 : 0
+ });
+ } else {
+ nodeTop = nodeTop + this.oldScrollTop;
+ this.scrollTop = nodeTop - offset;
+ this.oldScrollTop = this.scrollTop;
+ }
+ },
+ //是否要展示上拉加载更多view
+ _shouldShowLoading(type) {
+ if (!(this.loadingStatus === 0 ? this.nShowBottom : true)) {
+ return false;
+ }
+ if (((!this.showLoadingMoreWhenReload || this.isUserPullDown || this.loadingStatus !== 1) && !this
+ .showLoadingMore) || (!this.loadingMoreEnabled && (!this.showLoadingMoreWhenReload || this
+ .isUserPullDown || this.loadingStatus !== 1)) || this
+ .refresherOnly) {
+ return false;
+ }
+ if (this.useChatRecordMode && type !== 'loadingMoreLoading') {
+ return false;
+ }
+ if (!this.$slots) {
+ return false;
+ }
+ if (type === 'loadingMoreDefault') {
+ const res = this.loadingStatus === 0 && this.$slots.loadingMoreDefault;
+ if (res) {
+ // #ifdef APP-NVUE
+ if (!this.isIos) {
+ this.nLoadingMoreFixedHeight = false;
+ }
+ // #endif
+ }
+ return res;
+ } else if (type === 'loadingMoreLoading') {
+ const res = this.loadingStatus === 1 && this.$slots.loadingMoreLoading;
+ if (res) {
+ // #ifdef APP-NVUE
+ if (!this.isIos) {
+ this.nLoadingMoreFixedHeight = false;
+ }
+ // #endif
+ }
+ return res;
+ } else if (type === 'loadingMoreNoMore') {
+ const res = this.loadingStatus === 2 && this.$slots.loadingMoreNoMore && this.showLoadingMoreNoMoreView;
+ if (res) {
+ // #ifdef APP-NVUE
+ if (!this.isIos) {
+ this.nLoadingMoreFixedHeight = false;
+ }
+ // #endif
+ }
+ return res;
+ } else if (type === 'loadingMoreFail') {
+ const res = this.loadingStatus === 3 && this.$slots.loadingMoreFail;
+ if (res) {
+ // #ifdef APP-NVUE
+ if (!this.isIos) {
+ this.nLoadingMoreFixedHeight = false;
+ }
+ // #endif
+ }
+ return res;
+ } else if (type === 'loadingMoreCustom') {
+ const res = this.showDefaultLoadingMoreText && !(this.loadingStatus === 2 && !this
+ .showLoadingMoreNoMoreView);
+ return res;
+ }
+ return false;
+ },
+ //处理开始加载更多状态
+ _startLoading(isReload = false) {
+ if ((this.showLoadingMoreWhenReload && !this.isUserPullDown) || !isReload) {
+ this.loadingStatus = 1;
+ }
+ this.loading = true;
+ },
+ //处理开始加载更多
+ _doLoadingMore() {
+ if (this.pageNo >= this.defaultPageNo && this.loadingStatus !== 2) {
+ this.pageNo++;
+ this._startLoading(false);
+ if (this.isLocalPaging) {
+ this._localPagingQueryList(this.pageNo, this.defaultPageSize, this.localPagingLoadingTime, (
+ res) => {
+ this.addData(res);
+ })
+ } else {
+ this.$emit('query', this.pageNo, this.defaultPageSize);
+ this._callMyParentQuery();
+ }
+ this.loadingType = 1;
+ }
+ },
+ _scroll(e) {
+ this.$emit('scroll', e);
+ this.oldScrollTop = e.detail.scrollTop;
+ const scrollDiff = e.detail.scrollHeight - this.oldScrollTop;
+ if (!this.isIos) {
+ this._checkScrolledToBottom(scrollDiff);
+ }
+ },
+ //自定义下拉刷新被触发
+ _onRefresh() {
+ if (this.loading || this.nShowRefresherReveal) {
+ return;
+ }
+ this.isUserPullDown = true;
+ this.isUserReload = false;
+ this._startLoading(true);
+ this.refresherTriggered = true;
+ if (this.useChatRecordMode) {
+ this._onLoadingMore('click')
+ } else {
+ this._reload();
+ }
+ this.$emit('onRefresh');
+ this.$emit('Refresh');
+ this.loadingType = 0;
+ },
+ //自定义下拉刷新被复位
+ _onRestore() {
+ this.refresherTriggered = 'restore';
+ this.$emit('onRestore');
+ this.$emit('Restore');
+ },
+ //拖拽开始
+ _refresherTouchstart(e) {
+ if (this._getRefresherTouchDisabled()) {
+ return;
+ }
+ const touch = zUtils.getCommonTouch(e);
+ this._handleRefresherTouchstart(touch);
+ },
+ //进一步处理拖拽开始结果
+ _handleRefresherTouchstart(touch) {
+ if (!this.loading && this.isTouchEnded) {
+ this.isTouchmoving = false;
+ }
+ this.isTouchEnded = false;
+ if (this.isIos13) {
+ this.refresherTransition = '';
+ } else {
+ this.refresherTransition = 'transform .1s linear';
+ }
+ this.refresherTouchstartY = touch.touchY;
+ this.$emit('refresherTouchstart', this.refresherTouchstartY);
+ this.lastRefresherTouchmove = touch;
+ },
+ //拖拽中
+ _refresherTouchmove(e) {
+ const currentTimeStamp = (new Date()).getTime();
+ if (this.pullDownTimeStamp && currentTimeStamp - this.pullDownTimeStamp <= this.pullDownDisTimeStamp) {
+ return;
+ }
+ if (this._getRefresherTouchDisabled()) {
+ return;
+ }
+ this.pullDownTimeStamp = Number(currentTimeStamp);
+ const touch = zUtils.getCommonTouch(e);
+ let refresherTouchmoveY = touch.touchY;
+ let moveDistance = refresherTouchmoveY - this.refresherTouchstartY;
+ if (moveDistance < 0) {
+ return;
+ }
+ if (this.refresherMaxAngle >= 0 && this.refresherMaxAngle <= 90 && this.lastRefresherTouchmove && this
+ .lastRefresherTouchmove.touchY <= refresherTouchmoveY) {
+ if (!moveDistance && !this.refresherAngleEnableChangeContinued && this.moveDistance < 1 && !this
+ .refresherReachMaxAngle) {
+ return;
+ }
+ const x = Math.abs(touch.touchX - this.lastRefresherTouchmove.touchX);
+ const y = Math.abs(refresherTouchmoveY - this.lastRefresherTouchmove.touchY);
+ const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
+ if ((x || y) && x > 1) {
+ const angle = Math.asin(y / z) / Math.PI * 180;
+ if (angle < this.refresherMaxAngle) {
+ this.lastRefresherTouchmove = touch;
+ this.refresherReachMaxAngle = false;
+ return;
+ }
+ }
+ }
+ moveDistance = this._getFinalRefresherMoveDistance(moveDistance);
+ this._handleRefresherTouchmove(moveDistance, touch);
+ if (!this.disabledBounce) {
+ this._handleScrollViewDisableBounce({
+ bounce: false
+ });
+ this.disabledBounce = true;
+ }
+ },
+ //进一步处理拖拽中结果
+ _handleRefresherTouchmove(moveDistance, touch) {
+ this.refresherReachMaxAngle = true;
+ if (!this.isTouchmoving) {
+ this.isTouchmoving = true;
+ }
+ //this.refresherTransition = '';
+ this.isTouchEnded = false;
+ if (moveDistance >= this.finalRefresherThreshold) {
+ this.refresherStatus = 1;
+ } else {
+ this.refresherStatus = 0;
+ }
+ // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
+ // this.scrollEnable = false;
+ this.refresherTransform = `translateY(${moveDistance}px)`;
+ this.lastRefresherTouchmove = touch;
+ // #endif
+ this.moveDistance = moveDistance;
+ this.$emit('refresherTouchmove', moveDistance);
+ },
+ //拖拽结束
+ _refresherTouchend(e) {
+ if (this._getRefresherTouchDisabled() || !this.isTouchmoving) {
+ return;
+ }
+ const touch = zUtils.getCommonTouch(e);
+ let refresherTouchendY = touch.touchY;
+ let moveDistance = refresherTouchendY - this.refresherTouchstartY;
+ moveDistance = this._getFinalRefresherMoveDistance(moveDistance);
+ this._handleRefresherTouchend(moveDistance);
+ this._handleScrollViewDisableBounce({
+ bounce: true
+ });
+ this.disabledBounce = false;
+ },
+ //进一步处理拖拽结束结果
+ _handleRefresherTouchend(moveDistance) {
+ // #ifndef APP-PLUS || H5 || MP-WEIXIN
+ if (!this.isTouchmoving) {
+ return;
+ }
+ // #endif
+ this.refresherReachMaxAngle = true;
+ if (moveDistance < 0 && this.usePageScroll && this.loadingMoreEnabled && this.useCustomRefresher && this
+ .pageScrollTop === -1) {
+ if (this.showConsoleError) {
+ zUtils.consoleErr(
+ 'usePageScroll为true并且自定义下拉刷新时必须引入mixin或在page滚动时通过调用z-paging组件的updatePageScrollTop方法设置当前的scrollTop'
+ )
+ }
+ }
+ this.isTouchEnded = true;
+ if (moveDistance >= this.finalRefresherThreshold && this.refresherStatus === 1) {
+ // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
+ this.refresherTransform = `translateY(${this.finalRefresherThreshold}px)`;
+ // #endif
+ this.moveDistance = this.finalRefresherThreshold;
+ this.refresherStatus = 2;
+ this._doRefresherLoad();
+ } else {
+ this._refresherEnd(true, false);
+ setTimeout(() => {
+ this.isTouchmoving = false;
+ }, commonDelayTime);
+ }
+ this.scrollEnable = true;
+ this.refresherTransition = 'transform .1s linear';
+ this.$emit('refresherTouchend', moveDistance);
+ },
+ //处理scroll-view bounce是否生效
+ _handleScrollViewDisableBounce(e) {
+ if (!this.usePageScroll && !this.scrollToTopBounceEnabled) {
+ if (this.isIos13) {
+ this.refresherTransition = '';
+ }
+ if (!e.bounce) {
+ if (this.scrollEnable) {
+ this.scrollEnable = false;
+ }
+ } else {
+ this.scrollEnable = true;
+ }
+ }
+ },
+ //wxs正在下拉处理
+ _handleWxsOnPullingDown(onPullingDown) {
+ this.wxsOnPullingDown = onPullingDown;
+ if (onPullingDown) {
+ if (!this.useChatRecordMode) {
+ this.renderPropScrollTop = 0;
+ }
+ }
+ },
+ //下拉刷新结束
+ _refresherEnd(shouldEndLoadingDelay = true, fromAddData = false) {
+ // #ifndef APP-NVUE
+ if (this.showRefresherWhenReload || this.privateShowRefresherWhenReload) {
+ const stackCount = this.refresherRevealStackCount;
+ this.refresherRevealStackCount--;
+ if (stackCount > 1) {
+ return;
+ }
+ this.refresherStatus = 0;
+ } else {
+ setTimeout(() => {
+ this.refresherStatus = 0;
+ }, commonDelayTime);
+ }
+ // #endif
+ if (this.refresherEndBounceEnabled && fromAddData) {
+ this.refresherTransition = 'transform 0.3s cubic-bezier(0.19,1.64,0.42,0.72)';
+ }
+ // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
+ this.refresherTransform = 'translateY(0px)';
+ // #endif
+ // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5
+ this.wxsPropType = 'end' + (new Date()).getTime();
+ // #endif
+ this.moveDistance = 0;
+ if (shouldEndLoadingDelay) {
+ setTimeout(() => {
+ this.loading = false;
+ }, commonDelayTime);
+ } else {
+ this.loading = false;
+ }
+ this.$emit('onRestore');
+ this.$emit('Restore');
+ // #ifdef APP-NVUE
+ this._nRefresherEnd();
+ // #endif
+ },
+ //模拟用户手动触发下拉刷新
+ _doRefresherRefreshAnimate() {
+ this.refresherRevealStackCount++;
+ this.refresherTransform = `translateY(${this.finalRefresherThreshold}px)`;
+ // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5
+ this.wxsPropType = 'begin' + (new Date()).getTime();
+ // #endif
+ this.moveDistance = this.finalRefresherThreshold;
+ this.refresherStatus = 2;
+ this.isTouchmoving = true;
+ },
+ //触发下拉刷新
+ _doRefresherLoad() {
+ this._onRefresh();
+ this.loading = true;
+ },
+ //获取处理后的moveDistance
+ _getFinalRefresherMoveDistance(moveDistance) {
+ moveDistance = moveDistance * 0.85;
+ if (moveDistance >= this.finalRefresherThreshold) {
+ moveDistance = this.finalRefresherThreshold + (moveDistance - this.finalRefresherThreshold) * (1 - this
+ .finalRefresherOutRate);
+ }
+ return moveDistance;
+ },
+ //(预处理)判断当没有更多数据且分页内容未超出z-paging时是否显示没有更多数据的view
+ _preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(newVal, scrollViewNode, pagingContainerNode) {
+ if (this.loadingStatus === 2 && this.hideLoadingMoreWhenNoMoreByLimit > 0 &&
+ newVal.length) {
+ this.showLoadingMore = newVal.length > this.hideLoadingMoreWhenNoMoreByLimit;
+ } else if ((this.loadingStatus === 2 && this.hideLoadingMoreWhenNoMoreAndInsideOfPaging &&
+ newVal.length) || (this.insideMore && this.insideOfPaging !== false &&
+ newVal.length)) {
+ this.$nextTick(() => {
+ this._checkShowLoadingMoreWhenNoMoreAndInsideOfPaging(newVal, scrollViewNode,
+ pagingContainerNode);
+ })
+ if (this.insideMore && this.insideOfPaging !== false &&
+ newVal.length) {
+ this.showLoadingMore = newVal.length;
+ }
+ } else {
+ this.showLoadingMore = newVal.length;
+ }
+ },
+ //判断当没有更多数据且分页内容未超出z-paging时是否显示没有更多数据的view
+ async _checkShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData, oldScrollViewNode, oldPagingContainerNode) {
+ try {
+ const scrollViewNode = oldScrollViewNode || await this._getNodeClientRect('.zp-scroll-view');
+ if (this.usePageScroll) {
+ if (scrollViewNode) {
+ const scrollViewTotalH = scrollViewNode[0].top + scrollViewNode[0].height;
+ this.insideOfPaging = scrollViewTotalH < this.systemInfo.windowHeight;
+ if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) {
+ this.showLoadingMore = !this.insideOfPaging;
+ }
+ this._updateInsideOfPaging();
+ }
+ } else {
+ let pagingContainerH = 0;
+ let scrollViewH = 0;
+ const pagingContainerNode = oldPagingContainerNode || await this._getNodeClientRect(
+ '.zp-paging-container-content');
+ if (pagingContainerNode) {
+ pagingContainerH = pagingContainerNode[0].height;
+ }
+ if (scrollViewNode) {
+ scrollViewH = scrollViewNode[0].height;
+ }
+ this.insideOfPaging = pagingContainerH < scrollViewH;
+ if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) {
+ this.showLoadingMore = !this.insideOfPaging;
+ }
+ this._updateInsideOfPaging();
+ }
+ } catch (e) {
+ this.insideOfPaging = !totalData.length;
+ if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) {
+ this.showLoadingMore = !this.insideOfPaging;
+ }
+ this._updateInsideOfPaging();
+ }
+ },
+ //检测z-paging是否超出了页面高度
+ async _checkScrollViewOutOfPage() {
+ try {
+ const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view');
+ if (scrollViewNode) {
+ const scrollViewTotalH = scrollViewNode[0].top + scrollViewNode[0].height;
+ if (scrollViewTotalH > this.systemInfo.windowHeight + 100) {
+ if (this.showConsoleError) {
+ zUtils.consoleWarn(
+ '检测到z-paging的高度超出页面高度,这将导致滚动或展示出现异常,请设置【:fixed="true"】或【确保z-paging有确定的高度(如果通过百分比设置z-paging的高度,请保证z-paging的所有父view已设置高度,同时确保page也设置了height:100%,如:page{height:100%}】,此时z-paging的百分比高度才能生效。详情参考demo或访问:https://ext.dcloud.net.cn/plugin?id=3935)'
+ );
+ }
+ }
+ }
+ } catch (e) {
+
+ }
+ },
+ //检测z-paging是否要全屏覆盖(当使用页面滚动并且不满全屏时,默认z-paging需要铺满全屏,避免数据过少时内部的empty-view无法正确展示)
+ async _checkScrollViewShouldFullHeight(callback) {
+ try {
+ const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view');
+ const pagingContainerNode = await this._getNodeClientRect('.zp-paging-container-content');
+ if (!scrollViewNode || !pagingContainerNode) {
+ return;
+ }
+ const scrollViewHeight = pagingContainerNode[0].height;
+ const scrollViewTop = scrollViewNode[0].top;
+ if (this.isAddedData && scrollViewHeight + scrollViewTop <= this.systemInfo.windowHeight) {
+ this._setAutoHeight(true, scrollViewNode);
+ callback(scrollViewNode, pagingContainerNode);
+ } else {
+ this._setAutoHeight(false);
+ callback(null, null);
+ }
+ } catch (e) {
+ callback(null, null);
+ }
+ },
+ //设置z-paging高度
+ async _setAutoHeight(shouldFullHeight = true, scrollViewNode = null) {
+ try {
+ if (shouldFullHeight) {
+ let finalScrollViewNode = scrollViewNode ? scrollViewNode : await this._getNodeClientRect(
+ '.scroll-view');
+ if (finalScrollViewNode) {
+ const scrollViewTop = finalScrollViewNode[0].top;
+ const scrollViewHeight = this.systemInfo.windowHeight - scrollViewTop;
+ let additionHeight = this._convertTextToPx(this.autoHeightAddition);
+ this.$set(this.scrollViewStyle, 'height', scrollViewHeight + additionHeight - (this
+ .insideMore ? 1 : 0) + 'px');
+ }
+ } else {
+ this.$delete(this.scrollViewStyle, 'height');
+ }
+ } catch (e) {
+
+ }
+ },
+ //触发更新是否超出页面状态
+ _updateInsideOfPaging() {
+ if (this.insideMore && this.insideOfPaging === true) {
+ setTimeout(() => {
+ this.doLoadMore();
+ }, 200)
+ }
+ },
+ //获取节点尺寸
+ _getNodeClientRect(select, inThis = true, scrollOffset = false) {
+ // #ifdef APP-NVUE
+ select = select.replace('.', '').replace('#', '');
+ const ref = this.$refs[select];
+ if (ref) {
+ return new Promise((resolve, reject) => {
+ weexDom.getComponentRect(ref, option => {
+ if (option && option.result && option.result) {
+ resolve([option.size]);
+ } else {
+ resolve(false);
+ }
+ })
+ });
+ } else {
+ return new Promise((resolve, reject) => {
+ resolve(false);
+ });
+ }
+ return;
+ // #endif
+ let res = null;
+ if (inThis) {
+ res = uni.createSelectorQuery().in(this);
+ } else {
+ res = uni.createSelectorQuery();
+ }
+ //#ifdef MP-ALIPAY
+ res = uni.createSelectorQuery();
+ //#endif
+ if (scrollOffset) {
+ res.select(select).scrollOffset();
+ } else {
+ res.select(select).boundingClientRect();
+ }
+ return new Promise((resolve, reject) => {
+ res.exec(data => {
+ if (data && data != '' && data != undefined && data.length) {
+ resolve(data);
+ } else {
+ resolve(false);
+ }
+ });
+ });
+ },
+ //判断touch手势是否要触发
+ _getRefresherTouchDisabled() {
+ let checkOldScrollTop = this.oldScrollTop > 5;
+ const res = this.loading || this.useChatRecordMode || !this.refresherEnabled || !this.useCustomRefresher ||
+ (
+ this.usePageScroll && this
+ .useCustomRefresher && this
+ .pageScrollTop > 10) || (!(this.usePageScroll && this.useCustomRefresher) && checkOldScrollTop);
+ return res;
+ },
+ //本地分页请求
+ _localPagingQueryList(pageNo, pageSize, localPagingLoadingTime, callback) {
+ pageNo = parseInt(pageNo);
+ pageSize = parseInt(pageSize);
+ if (pageNo < 0 || pageSize <= 0) {
+ callQueryResult(callback, []);
+ return;
+ }
+ if (pageNo == 0) {
+ pageNo = 1;
+ }
+ let totalPagingList = [...this.totalLocalPagingList];
+ let pageNoIndex = (pageNo - 1) * pageSize;
+ if (pageNoIndex + pageSize <= totalPagingList.length) {
+ this._localPagingQueryResult(callback, totalPagingList.splice(pageNoIndex, pageSize),
+ localPagingLoadingTime);
+ } else if (pageNoIndex < totalPagingList.length) {
+ this._localPagingQueryResult(callback, totalPagingList.splice(pageNoIndex, totalPagingList.length -
+ pageNoIndex),
+ localPagingLoadingTime);
+ } else {
+ this._localPagingQueryResult(callback, [], localPagingLoadingTime);
+ }
+ },
+ //本地分页请求回调
+ _localPagingQueryResult(callback, arg, localPagingLoadingTime) {
+ setTimeout(() => {
+ callback(arg);
+ }, localPagingLoadingTime)
+ },
+ //将文本的px或者rpx转为px的值
+ _convertTextToPx(text) {
+ const dataType = Object.prototype.toString.call(text);
+ if (dataType === '[object Number]') {
+ return text;
+ }
+ let isRpx = false;
+ if (text.indexOf('rpx') !== -1 || text.indexOf('upx') !== -1) {
+ text = text.replace('rpx', '').replace('upx', '');
+ isRpx = true;
+ } else if (text.indexOf('px') !== -1) {
+ text = text.replace('px', '');
+ }
+ if (!isNaN(text)) {
+ if (isRpx) {
+ return Number(uni.upx2px(text));
+ }
+ return Number(text);
+ }
+ return 0;
+ },
+
+ //判断是否要显示返回顶部按钮
+ _checkShouldShowBackToTop(newVal, oldVal) {
+ if (!this.autoShowBackToTop) {
+ if (this.showBackToTopClass) {
+ this.showBackToTopClass = false;
+ }
+ return;
+ }
+ if (newVal !== oldVal) {
+ if (newVal > this.finalBackToTopThreshold) {
+ if (!this.showBackToTopClass) {
+ this.showBackToTopClass = true;
+ setTimeout(() => {
+ this.backToTopClass = 'zp-back-to-top zp-back-to-top-show';
+ }, 300)
+ }
+ } else {
+ if (this.showBackToTopClass) {
+ this.backToTopClass = 'zp-back-to-top zp-back-to-top-hide';
+ setTimeout(() => {
+ this.showBackToTopClass = false;
+ }, 300)
+ }
+ }
+ }
+ },
+ _updatePageScrollTopOrBottomHeight(type) {
+ // #ifndef APP-NVUE
+ if (!this.usePageScroll) {
+ return;
+ }
+ // #endif
+ const node = `.zp-page-scroll-${type}`;
+ const marginText = `margin${type.slice(0,1).toUpperCase() + type.slice(1)}`;
+ this.$nextTick(() => {
+ let delayTime = 0;
+ // #ifdef MP-BAIDU
+ delayTime = 10;
+ // #endif
+ setTimeout(() => {
+ this._getNodeClientRect(node).then((res) => {
+ if (res) {
+ let pageScrollNodeHeight = res[0].height;
+ if (type === 'bottom') {
+ if (this.safeAreaInsetBottom) {
+ pageScrollNodeHeight += this.safeAreaBottom;
+ }
+ }
+ this.$set(this.scrollViewStyle, marginText,
+ `${pageScrollNodeHeight}px`);
+ } else if (this.safeAreaInsetBottom) {
+ this.$set(this.scrollViewStyle, marginText,
+ `${this.safeAreaBottom}px`);
+ }
+ });
+ }, delayTime)
+ })
+ },
+ _updateCustomRefresherHeight() {
+ this._getNodeClientRect('.zp-custom-refresher-slot-view').then((res) => {
+ if (res) {
+ this.customRefresherHeight = res[0].height;
+ if (this.customRefresherHeight > 0) {
+ this.showCustomRefresher = true;
+ }
+ } else {
+ this.customRefresherHeight = 0;
+ }
+ });
+ },
+ //点击了空数据view重新加载按钮
+ _emptyViewReload() {
+ let callbacked = false;
+ this.$emit('emptyViewReload', (reload) => {
+ if (reload === undefined || reload === true) {
+ this.reload();
+ }
+ callbacked = true;
+ });
+ this.$nextTick(() => {
+ if (!callbacked) {
+ this.reload();
+ }
+ })
+ },
+ //获取国际化转换后的文本
+ _getI18nText(key, value) {
+ const dataType = Object.prototype.toString.call(value);
+ if (dataType === '[object Object]') {
+ const nextValue = value[this.finalLanguage];
+ if (nextValue) {
+ return nextValue;
+ }
+ } else if (dataType === '[object String]') {
+ return value;
+ }
+ return zI18n[key][this.finalLanguage];
+ },
+ //修改父view的list
+ _callMyParentList(newVal) {
+ if (this.autowireListName.length) {
+ const myParent = zUtils.getParent(this.$parent);
+ if (myParent && myParent[this.autowireListName]) {
+ myParent[this.autowireListName] = newVal;
+ }
+ }
+ },
+ //调用父view的query
+ _callMyParentQuery() {
+ if (this.autowireQueryName) {
+ if (this.myParentQuery === -1) {
+ const myParent = zUtils.getParent(this.$parent);
+ if (myParent && myParent[this.autowireQueryName]) {
+ this.myParentQuery = myParent[this.autowireQueryName];
+ }
+ }
+ if (this.myParentQuery !== -1) {
+ this.myParentQuery(this.pageNo, this.defaultPageSize);
+ }
+ }
+ },
+ //检查complete data的类型
+ _checkDataType(data, success, isLocal) {
+ const dataType = Object.prototype.toString.call(data);
+ if (dataType === '[object Boolean]') {
+ success = data;
+ data = [];
+ } else if (dataType !== '[object Array]') {
+ data = [];
+ let methodStr = isLocal ? 'setLocalPaging' : 'complete';
+ if (dataType !== '[object Undefined]') {
+ if (this.showConsoleError) {
+ zUtils.consoleErr(`${methodStr}参数类型不正确,第一个参数类型必须为Array!`);
+ }
+ }
+ }
+ return {
+ data,
+ success
+ };
+ },
+ // ------------nvue独有的方法----------------
+ //列表滚动时触发
+ _nOnScroll(e) {
+ const contentOffsetY = e.contentOffset.y;
+ this.$emit('scroll', e);
+ this.nListIsDragging = e.isDragging;
+ this._checkShouldShowBackToTop(-e.contentOffset.y, -e.contentOffset.y - 1);
+ },
+ //下拉刷新刷新中
+ _nOnRrefresh() {
+ if (this.nShowRefresherReveal) {
+ return;
+ }
+ this.nRefresherLoading = true;
+ this.refresherStatus = 2;
+ this._doRefresherLoad();
+ },
+ //下拉刷新下拉中
+ _nOnPullingdown(e) {
+ if (this.refresherStatus === 2 || (this.isIos && !this.nListIsDragging)) {
+ return;
+ }
+ const viewHeight = e.viewHeight;
+ const pullingDistance = e.pullingDistance;
+ if (pullingDistance >= viewHeight) {
+ this.refresherStatus = 1;
+ } else {
+ this.refresherStatus = 0;
+ }
+ },
+ //下拉刷新结束
+ _nRefresherEnd() {
+ this._nDoRefresherEndAnimation(0, -this.nShowRefresherRevealHeight);
+ if (!this.nShowBottom) {
+ setTimeout(() => {
+ this.$nextTick(() => {
+ this.nShowBottom = true;
+ })
+ }, 1000);
+ }
+ if (!this.usePageScroll) {
+ this.$refs["n-list"].resetLoadmore();
+ }
+ this.nRefresherLoading = false;
+ },
+ //执行主动触发下拉刷新动画
+ _nDoRefresherEndAnimation(height, translateY, animate = true, checkStack = true) {
+ if (!this.showRefresherWhenReload && !this.privateShowRefresherWhenReload) {
+ setTimeout(() => {
+ this.refresherStatus = 0;
+ }, commonDelayTime);
+ return;
+ }
+ const stackCount = this.refresherRevealStackCount;
+ if (height === 0 && checkStack) {
+ this.refresherRevealStackCount--;
+ if (stackCount > 1) {
+ return;
+ }
+ this.refresherStatus = 0;
+ }
+ if (stackCount > 1) {
+ this.refresherStatus = 2;
+ }
+ const duration = animate ? 120 : 0;
+ weexAnimation.transition(this.$refs['zp-n-list-refresher-reveal'], {
+ styles: {
+ height: `${height}px`,
+ transform: `translateY(${translateY}px)`,
+ },
+ duration: duration,
+ timingFunction: 'linear',
+ needLayout: true,
+ delay: 0
+ })
+ setTimeout(() => {
+ if (animate) {
+ this.nShowRefresherReveal = height > 0;
+ }
+ }, duration > 0 ? duration - 100 : 0);
+ },
+ //滚动到底部加载更多
+ _nOnLoadmore() {
+ if (this.nShowRefresherReveal || !this.totalData.length) {
+ return;
+ }
+ if (this.useChatRecordMode) {
+ this.doChatRecordLoadMore();
+ } else {
+ this._onLoadingMore('toBottom');
+ }
+ },
+ //获取nvue waterfall单项配置
+ _getNvueWaterfallSingleConfig(key, defaultValue) {
+ const value = this.nvueWaterfallConfig[key];
+ if (value) {
+ return value;
+ }
+ return defaultValue;
+ }
+ },
+};
diff --git a/uni_modules/z-paging/components/z-paging/js/z-paging-mixin.js b/uni_modules/z-paging/components/z-paging/js/z-paging-mixin.js
new file mode 100644
index 0000000..866b1c2
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/js/z-paging-mixin.js
@@ -0,0 +1,36 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+// 使用页面滚动时引入此mixin,用于监听和处理onPullDownRefresh等页面生命周期方法
+
+const ZPagingMixin = {
+ onPullDownRefresh() {
+ if (this.isPagingRefNotFound()) {
+ return;
+ }
+ this.$refs.paging.reload();
+ },
+ onPageScroll(e) {
+ if (this.isPagingRefNotFound()) {
+ return;
+ }
+ this.$refs.paging.updatePageScrollTop(e.scrollTop);
+ if (e.scrollTop < 10) {
+ this.$refs.paging.doChatRecordLoadMore();
+ }
+ },
+ onReachBottom() {
+ if (this.isPagingRefNotFound()) {
+ return;
+ }
+ this.$refs.paging.doLoadMore();
+ },
+ methods: {
+ isPagingRefNotFound() {
+ return !this.$refs.paging || this.$refs.paging === undefined;
+ }
+ }
+}
+
+export default ZPagingMixin;
diff --git a/uni_modules/z-paging/components/z-paging/js/z-paging-static.js b/uni_modules/z-paging/components/z-paging/js/z-paging-static.js
new file mode 100644
index 0000000..867e845
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/js/z-paging-static.js
@@ -0,0 +1,25 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+// 公用的静态图片资源
+
+const base64Arrow =
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAD1BMVEVHcExRUVFMTExRUVFRUVE9CdWsAAAABHRSTlMAjjrY9ZnUjwAAAQFJREFUWMPt2MsNgzAMgGEEE1B1gKJmAIRYoCH7z9RCXrabh33iYktcIv35EEg5ZBh07pvxJU6MFSPOSRnjnBUjUsaciRUjMsb4xIoRCWNiYsUInzE5sWKEyxiYWDbyefqHx1zIeiYTk7mQYziTYecxHvEJjwmIT3hMQELCYSISEg4TkZj0mYTEpM8kJCU9JiMp6TEZyUmbAUhO2gxAQNJiIAKSFgMRmNQZhMCkziAEJTUGIyipMRjBSZkhCE7KDEFIUmTeGCHJxWz0zXaE0GTCG8ZFtEaS347r/1fe11YyHYVfubxayfjoHmc0YYwmmmiiiSaaaKLJ7ckyz5ve+dw3Xw2emdwm9xSbAAAAAElFTkSuQmCC';
+const base64ArrowWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEVHcEz///////////////////+IGTx/AAAABnRSTlMA/dAkXZOhASU/AAABYElEQVRYw+2YwXLCIBCGsdAHWGbyAKZ4zxi9O017rxLf/1UaWFAgA1m8dcpedNSPf/l/Vh0Ya/Wn6hN0JcGvoCqRM4C8VBFiDwBqqNuJKV0rAnCgy3AUqZE57x0iqTL8Br4U3WBf/YWaIlTKfAcELU/h9w72CSVPa3C3OCDvhpHbRp/s2vq4fHhCeiCl2A3m4Qd71DQR257mFBlMcTlbFnFWzNtHxewYEfSiaLS4el8d8nyhmKJd1CF4eOS0keLMAuSxubLBIeIGQW8YHCFFo7EH9+YDcQt9FMZEswTheaNxTHwHT8SZorJjMrEVwo4Zo0U8HSEyZvJMOg4RjnmmRr8nDYeIz3OMkbfE/QhBo+U9RnZJxjGCRh/WKmHEMWLNkfPKsGh/CWJk1JjG0kcuJggTt34VDP8aWAFhp4nybVb5+9qQhjSkIQ1pSEMa8k+Q5U9rV3dF8MpFBK+/7miVq1/HZ2qmo9D+pAAAAABJRU5ErkJggg=='
+const base64Flower =
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAKlBMVEVHcEzDw8Ovr6+pqamUlJTCwsKenp61tbWxsbGysrLNzc2bm5u5ubmjo6MpovhuAAAACnRSTlMA/P79/sHDhiZS0DxZowAABBBJREFUWMPtl89rE0EUx7ctTXatB3MI1SWnDbUKPUgXqh4ED8Uf7KUVSm3ooVSpSii0Fn/gD4j4o+APiEoVmos9FO2celiqZVgwgaKHPQiCCkv+F99kM7Ozm5kxq1dfD91k9pPve9/3ZjbRNHHok/mKli4eIPNgSuRObuN9SqSEzM20iGnm0yIbqCuV7NSSSIV7uyPM6JMBYdeTOanh/QihJYZsUCSby+VkMj2AvOt0rAeQAwqE3lfKMZVlQCZk1QOCKkkVPadITCfIRNKxfoJI5+0OIFtJx14CMSg1mRSDko7VAfksRQzEbGYqxOJcVTWMCH2I1/IACNW0PWU2M8cmAVHtnH5mM1VRWtwKZjOd5JbF6s1IbaYqaotjNlPHgDAnlAizubTR6ovMYn052g/U5qcmOpi0WL8xTS/3IfSet5m8MEr5ajjF5le6dq/OJpobrdY0t3i9QgefWrxW9/1BLhk0E9m8FeUMhhXal499iD0eQRfDF+ts/tttORRerfp+oV7f4xJj82iUYm1Yzod+ZQEAlS/8mMBwKebVmCVp1f0JLS6zKd17+iwRKTARVg2SHtz3iEbBH+Q+U28zW2Jiza8Tjb1YFoYZMsJyjDqp3M9XBQdSdPLFdxEpvOB37JrHcmR/y9+LgoTlCFGZEa2sc6d4PGlweEa2JSVPoVm+IfGG3ZL037iV9oH+P+Jxc4HGVflNq1M0pivao/EopO4b/ojVCP9GjmiXOeS0DOn1o/iiccT4ORnyvBGF3yUywkQajW4Ti0SGuiy/wVSg/L8w+X/8Q+hvUx8Xd90z4oV5a1i88MbFWHz0WZZ1UrTwBGPX3Rat9AFiXRMRjoMdIdJLEOt2h7jrYOzgOamKZSWSNspOS0X8SAqRYmxRL7sg4eLzYmNehcxh3uoyud/BH2Udux4ywxFTc1xC7Mgf4vMhc5S+kSH3Y7yj+qpwIWSoPTVCOOPVthGx9FbGqrwFw6wSFxJr+17zeKcztt3u+2roAEVgUjDd+AHGuxHy2rZHaa8JMkTHEeyi85ANPO9j9BVuBRD2FY5LDMo/Sz/2hReqGIs/KiFin+CsPsYO/yvM3jL2vE8EbX7/Bf8ejtr2GLN65bioAdgLd8Bis/mD5GmP2qeqyo2ZwQEOtAjRIDH7mBKpUcMoApbZJ5UIxkEwxyMZyMxW/uKFvHCFR3SSmerHyDNQ2dF4JG6zIMpBgLfjSF9x1D6smFcYnGApjmSLICO3ecCDWrQ48geba9DI3STy2i7ax6WIB62fSyIZIiO3GFQqSURp8wCo7GhJBGwuSovJBNjb7kT6FPVnIa9qJ2Ko+l9mefGIdinaMp0yC1URYiwsdfNE45EuA5Cx9EhalfvN5s+UyItm81vaB3p4joniN+SCP7Qc1hblAAAAAElFTkSuQmCC';
+const base64FlowerWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEX///9HcEz///////////////84chYNAAAABnRSTlP/AGzCOYZj5g1nAAACfklEQVRYw+2YTVPDIBCGtza9Jw25a0bvcax30o73OOr//yvma2F3YWlpPTijXNpAHrK8LLALVPFium2vNIFSbwGKTGQA2GUiHcD29yDNy3sMIdUBQl7r2H8mOEVqAHgPkYZUS6Qc2zYhQqtjyDZEximCZwWZLIBeIgYShs2NzxKpSUehYpMJhURGb+O+w5BpMCAREKPnCDHbIY20SzhM5yxziAXpOiBXydrekT9i5XDEq4NIIHHgyU5mRGqviII4mREJJA4QJzMiILwlRJzpKxJKvCBm8OsBBbLux0tsPl4RKYm5aPu6jw1U4mGxEUR9g8M1PcqBEp/WJliNgYOXueBzS4jZSIcgY5lCtevgDSgyzE+rAfuOTQMq0yzvoGH18qju27Mayzs4fPyMziCx81NJa5RNfW7vPYK9KOfDiVkBxFHG8hAj9txuoBuSWORsFfkpBf7xKFLSeaOefEojh5jz22DJEqMP8fUyaKdQx+RnG+yXMpe8Aars8ueR1pVH/bW3FyyvPRw90upLDHwpgBDtg4aUBNkxRLXMAi03IhcZtr1m+FeI/O/JNyDmmL1djLOauSlNflBpW18RQ2bPqXI22MXXEk75KRHTnkPkYbESbdKP2ZFk0r5sIwffAjy1lx+vx7NLjB6/E7Jfv5ERKhzpN0w8IDE8IGFDv5dhz10s7GFiXRZcUeLCEG5P5nDq9k4PFDcoMpE3GY4OuxuCXhmuyNB6k0RsLIAvqp9NE5r8ZCSS8gxnUp7ODdYhZTqxuiJ9uyJJtPmpqJ7wVj+XVieS903iViHziqAhchLEJAyb7jWU647EpUofQ0ziUuXXXhDddtlllSwjgSQu7r4BRWhQqfDPMVwAAAAASUVORK5CYII='
+const base64Empty = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAbUExURdvc3EdwTMLBwcjIyLSzs/Hx8ff39////19dXXz7IJEAAAAFdFJOU/4A6J9QDyyutAAAB5VJREFUeNrtnM1z4jYYxhUHkR4hdu9eU7Z75Ct7jgPbs9ZZmSuTrUWPmXTA186e+LMrf0uWLMtf2WkHXQgzln88et5XeiVMwPQdGrhCrpAr5Aq5Qv4TkJ07OGQFMLp1B4VYCz+kDblDQhJGeH4eEDLBYdLOHwaDWNBPIeHLYJAJ3meQ83IoCMTHDBKOBoKYGOeM8G0gyD0LObnDQB5ZSCtTNCBfsM9AboaBPLCQcDAIM1zht/dQEkMsd1DjI4hpw2YzMtBJeBbydWpCTJs3YDKGX62YgfGoVwi9KwtZJAzcYHHRm7sYCKD390nQSIoO5JGZIEOYxNoZ4+deISYLyeL5hLHbJ2QK98W0kudMgJe9Qh73odhO+KZHyNYGvgQS9gmJKhUigwSj3iBPUhXxePWmxBqHw0Mej9WQ3qILVjLC177yxNxXQ/7uK+Mn1aNVLsGsBTaWrSAPobYl0aUHt2fIs2Rgz7c9QYL0pSTkSzILLFtAJMH1cidN998T9E0/Sg73/pEEwrgkYRh86wlC949gJsR6EobBcz8hHOVgKYi2m6kZtodIkjEQvF3QjbGpmplB4/lRgJhxgRS2N15iijAvPmByDtCxfQhPJ8J4CR82rgCCBILarScw6X0OcMUyYrFVmbxErl0ZacFIoloOLdJAO42qY+NMDss2kKS8xmiZxcCpFKXWvpRGbQqJp5ixyRfJMmR6x0Fk+z29kmgWDYI5ziFbdug/84HxvduhWhLOJ2StPDQrMJPSjNANklh8QhB7dBO0yTGRwn1fkOk8rbQjiB8Ymww+JuiuN0icmSccK4naLMWYa/euL0+m23GyM8kgAc6sYeL4z04Qa4WjGepcKIliO8EUGSk7d9OGWOsoK31OSdy8TQZ59Y/hWbaV1IVs5/Ed6UzGK4nANAJiyGhRsZPUg2yzLe9hLyiJIyCaDU7udC2uy9pnkKvidlBUEltzFAqxRhBrBZm7HfZnjEQI3boqTsJq15PUDEaKZLgiJYc8OZtCtnM/4G93OFYooXpvdy0guwWWNQkEHl/j7Jw1XRmtlS9HYJkSPjk1IUnyyRqUKQn45NSDlP1mcg9i6En1ZU2IADnEtHF1Q+JwIcS/d5YakPuDUamEShGUHHikAz9oQCaE0CsrpYjDBVkEHQYdyK+EkKPhVErxqh1xbJ/oQf4gEeVsOIEc41WJNAwcd9GBfCZJezXsJhAvH+ImEEIOzlwXgpw5wQ0gH3MIOcsiQAahZuSD69/UQyxcQEggiQARQseVFO/ASAMCgM9gjkHZmhLENzi1AOhA7ullkMWUrfHKfpMiDBHtDIx6yCS6jseEnDUe7zcT6DGCtnrIY3olZw1hrPHkfucIAJa1EDu/lsVEyVmGGA67coKijeogFnMxlEaAV5ghRdDm1kDuuatZTJBGgJdOthIzsvZbDWRRuh6ScgR4EQLgagQvRQIxxQ4sxqcR4GE+c4CkjZQQW9YF89Y4OFAjOCki5KmiDxsBL3PlSJWlAFVogaoIePlYi2ClCJAHRa/cmre5eqTii4uvisqQJxqnip6pNd68DhEvyEs5xIyHBNdh4thCKhU++10kD7Gy1Up1A/o56FKuRJQWSFCuf8dpbisxhqHSKlSSgvG7VTaFKO5TzYD5VMPUxEB2YJNiqq3xYJ0KrroH8mq7xpoXqEZgfgNRUQsDtTVvUOk3sLUKbqrBr7YGvkCkQNC/9SA+vTYtvERrxiKEmcogk4ZqCLUd59MIEiFYHlIoxelCaJWDMmtOPIa80XVLbkb6hzaEwwTcPEmV4AIRlBGNIEmuJBFwLAZoHClJ36J8h+wxihpCqJosAnJrSKwEcQOFAFeWN4RQMYc0Ao4Jhg5gpASzyWcDvjpuDIlTkrGGJEro1rHIjHKR3wJCAj+z5oyi11gJBkXy9QFJIiAu78d+pgSjuWhGN0gUAZAcEncSJf4LRrZ8I94WEmcNCJJqBWYjVbE9bg2JxiyrViBWty6QvO56D8jPVWLA4ZX8dfkxvJJPl8t8aCX+pU/Iz1SCf7lc4OBK0OWfQaKLP0TKjj96VvIp+/BDZjwNKF2ItV2vN7sWStAl87oWkm3dZ+k3lEMoYXe8cT1eq2TOePJDD8KfQdxu6iEPxanUZa4HmZRq3dunGsj3BzFq6yD3wnZNX4n2emI2hXyXQpi6RRZdfSgxHNuxVZBFdyVeBPDmCsiksxKUiDAUEKuzkvRUEs0V08pjVyU2/yqFmF2VZGYop3peitdUiQd1pnrL7qTE01tPzE6eaEKm23dQwh2jNlbiay+/245zl94abw45CzNPyqYQ2++kxHGV1crWzg4A2yvR+BY7wziwnRLN7+O36aA54+ZKGjxZYK3txJpxQyUNn5GwtquII4+ACiWtnvawduu1A3SVtH5uhTvAVSpBG7fDYz6RQ+M6JWjmKm6g+RvTla9UMtspu+s+37VbVCupNqPx43CsNawSb1PbtcmDfQWmUILW7rRXSPHtSq5k5ur0a/hb7DQCUiW3G71ejX/wvV1kSoyNbp8Wvyqn1lCIKvl6gNDkNBYzt0GHdr+Pt9xGl1//ncAVcoVcIVfIFXKFXCFXyP8I8i8SyTW4yTz2lwAAAABJRU5ErkJggg=='
+const base64Error = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAJFBMVEVHcEzo6Oibm5ukpKSbm5uampqbm5ubm5u5ubnn5+fm5ub6+vpGpDPdAAAAC3RSTlMA/v4hb+u20dq8aQhnHL4AAATwSURBVHja7ZvNb+JGGMbdjjdVe3NPodzeMhj1ZMUGujkh28B9wKR7iwwBqafWSbPqsbm0uTWtVlrTS9v0Et9yqLQS/1zHNiTZMMB4bO92d+dRUITt8c/PvPPx2h4URUpKSkpKSkpK6m3K6lFN73Q+S/+es3W3fzabTh2Dl0FAXEM+BgrgeXxRsdILTDU9n7J0vz/+EsCYC9KEiSFc06pf5zouqAkjkGWo0OG5Fq6j2IwZ6I4/4DhyTxc20oUjAj5PRTTrwvGAZ9p+ADzlD4RDctCoLhb7JUP87xeLxS3BZUIQ+YNCFi8wRwc4GIqGRK/GkM+5ILV8kFflOmkkkH/LddJ4c05eSSfSyTvrZPEmnCw+UCeuk84QvTSnUF0uCL68fBle/swF+RL1QZ/EpU6gHtOsAM64pnjPwxgTLsjoBM58ODNaAXYBT5QeGdr0KwcEA8He0TkPBLCjUDNHpG4qlg8eTCzXht1FVd1MxTPHj5LTtUiSrKK+7iDf8wBGxk4If3arLv/HF4Tox0A2nlFIGp+CIA+LzSamgbp4TNvZjECtDAjyMcB5HybLO6NxsRA1vmFCNjguNXDGWygbRPXh/B+zn9zPWK5RCkT18QxA57YgAqE+HGS6/tAoD4JO0ts+M2tbyQJpc95a5oI0xXNhCZGQ/x8E0VSCkUZY6Z6CIE/qdO5eL+yPlW6tMMgefPs3o7Bdt8iguJj4DThlZSY/rJ0yB+RraLDK2jAQCHyr4zIhT9mQ7vowygMZjpgQG+CYUV2E1EWqixyzICr8eFFnBB5ba1Y4IIfeKQvysW7ssZrwQLEFmvCBM2U6oRkdI5Wgm1QnO8RUTDlASoiESIiESMh7BDHKhlhu/LbSNUuEqL3lu1p945vO3BArADiaum7vBGDUKQfSIjBykooyrRPQnTIglHFfSagHeqd4iErwa9duEebpckGQjx/VT4v5fC0XhJHAd1mPRvJAVMZiAeQzTpgHYrPKqkGnUEiX+dCoNS4UgniHMTnUS4iESIiE7IS0x+mnVAidglDwVcmQJpy2WQ8VC4UgogfbA1RE4Nuw3UghEBV2rKl7V5ygAJPSY9KGQbP01mVjA5Fa2f1kQN2U3k+M9POWB8gnJUNMZJioWTMzKwOklyxgDrCXVcMMEF90tXM9C2TiCqmfCdIRi/jeewNpyerKok9WkGuzfCdYC+fXRsmBxxpVGG2zY0ZBbieJKvPrDQce3lxppBhIjGFWGkVoxUEoZt0Mukn2XBQH0bTHZpaMIp2sU/6qasU70W6/eHjM09VmYSc6C6Jpvz+orKvVxot8kL3HkMr9IZ9qeZ2o6RrO9mOI9ufdIR9peZ2gNIW31yC/MpyI9ngUDNIsezPks3vIsWDGdYA7cZa9pbqUVeCr/neiaR3U3R4BfXPg75vwb8I/b7HjxChobDZCO+Ny4wuxxaVxPPowcoNnrzPmzGFlX3RJHz2FafbhJ41n8PLx2DCM7KkwQgpqka1DVzKdJNHfJwBe9l/n0eSZFsIPjVSY8xZKZpSXnogwled98wAx3xRcdBNq1f1fhFVdIcL5tvaDolC7XaqaWStEtLOJHkbhlSauMLrma4yHEa03AVUoIUs/M2NQFkchBZiGUPeKonAnqhLOo4hrKf0WTyZ1FcU0Ki0hVrSr+Mucnvya7jYUKSkpKSkpKSmpD0f/AXq+Umj5XnXDAAAAAElFTkSuQmCC';
+const base64BackToTop = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAElBMVEVRUVH+/v5HcEyZmZlRUVFRUVGm1ByOAAAABnRSTlPMzADMTZAJBBGsAAAEnElEQVR42t2cS27jMAyGf7/2U+QCQeDsbeQCgZDujaC5/1UmkzaJn+JDFGcw3LdfflKibJkkDnxrL7dbg7sNt6+L4O8OYBM+B0ys+QrGkHZG+OEEQ8g6go8Bx1GIGMdpNOQyIG6XdMgnSPtKhLQDGEZFBgYMkhKFtGBb0EIEjDgFRowoBVaMGAWpMedEfxMiZtwpUsgZCqtlkCNUdpVAWigtCCCDFtLwIWeoreZCWiRYYEKGFEjDg+yRZCUH0iLRAgNyToXUNCRZyMqWhGnUN2IPm3wSlwJ7IUspyCBkIQUZhCykIIeQuRTkEDKXAuM9srrtYbrZN7Y98giZSoFd+t1OxmMITG0dcrSFXFchZ1tIvQZpYWxhBbK3hpQrkMEa0iwh5t4a+QvZvDXyF7J5a+Qv5PPW21/I5623v5DPW29/IaO3Xv5Clrw1y1/Ikrdm+Qs5svw83yNnSJ5BQb4F/F7EIEJSnThGBAXxkFQfLOviQUE8JAUPsosHBfGQfDAtHhREQ1JxIV00KIgmrnRI84S0yAd5BAXxxJUck0f6Qnwr9qmr6xF5xLMjcwn/iudIEAdWnyjkEXlQKZiRVzoqRyLbgeUKKR8Q4alY7cSnoxzSf2ggsqehKr6YVpcXpOd7H93f60cKhOd7Re2LteUF4eLqiVS1mr0ge4io6C2+soaFkJ7MuuuQs1yITEp9hwwKISIpzR2iESKSIoT0rLNwuVHQqoSIpAQJpGce60vIUSdEIuUqgPTsJ5QFZK8UIpBS8iG94GFrDjlrhfCl8CG96Llxmle4kEr6vKWBPIVo9kqDQSRk9/3cWoikcCFPAd33v4dIChPyEvLzBA6RlEYWke4JEUnhKXkLeUEKxRHJFfKCQHGucIW8IdZSRkLeEGMpYyEjiK2UsZARxFTKRMgYYillImQMMZQyFTKB2EmZCplAuFLIHT8TMoWwpQwiIVMIUwqpZP5bp5CCvCTiQKr5f5lCQN+tPCBn2ZvVDFJwIDUP0m1BYAfZYRNSsCB7BqTbhoARePIxtZ9tgwWkoJcwCalmv3MBAemtO4R6dah2HaKQqj8Zvp9sQDjvJ21+SPCBHPJDDk6QITekEV7gqCC19CpKAym9IMfckKv4olMBCeIrWwVEfvkshzQekO9r9P1/ALk+IG1eSPCDiCJfyG+FyU+A6ZCa/piZDinpz7LpkCv5gdkAEshP5emQhv7onw6pGeULyZCSUYiRDAmMkpJkCKs4JhFSq8p8hJBSVbAkhARV6ZUQoisik0FqXTmcDHLVFfbJIEFXoiiCNMpiSxGkVJaNiiBBWQArgTTaUl4JpNQWJUsgQVteXQg+AKkLxQWFGKW+5J2+eVp4S168X3CF1CltCKdTJ8lb84YK2bUBO+wZW0Pqv9nk4tKu49N45NJC5dMM5tLW5tOg59Jq6NM06dL+abFXwr/RkuvTXJwae1abtE/Dt0/ruksTvs84AZ/BCC4jHnyGVfiM3VBQFANEXEah+Ax18RlP4zNox2dkkM/wI58xTn8yDCXGYCDV3W5RGSajtXyGhG1jbpbjzpwGt/0MJft8jqC7iUbQ/QZaxdnKqcIftwAAAABJRU5ErkJggg==';
+
+module.exports = {
+ base64Arrow,
+ base64ArrowWhite,
+ base64Flower,
+ base64FlowerWhite,
+ base64Empty,
+ base64Error,
+ base64BackToTop
+}
diff --git a/uni_modules/z-paging/components/z-paging/js/z-paging-utils.js b/uni_modules/z-paging/components/z-paging/js/z-paging-utils.js
new file mode 100644
index 0000000..f5b603e
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/js/z-paging-utils.js
@@ -0,0 +1,179 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+// z-paging工具类
+
+import zI18n from './z-paging-i18n'
+
+const storageKey = 'Z-PAGING-REFRESHER-TIME-STORAGE-KEY'
+
+//判断两个数组是否相等
+function arrayIsEqual(arr1, arr2) {
+ if (arr1 === arr2) {
+ return true;
+ }
+ if (arr1.length !== arr2.length) {
+ return false;
+ }
+ for (let i = 0; i < arr1.length; i++) {
+ if (arr1[i] !== arr2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+//获取最终的touch位置
+function getCommonTouch(e) {
+ let touch = null;
+ if (e.touches && e.touches.length) {
+ touch = e.touches[0];
+ } else if (e.changedTouches && e.changedTouches.length) {
+ touch = e.changedTouches[0];
+ } else if (e.datail && e.datail !== {}) {
+ touch = e.datail;
+ } else {
+ return {
+ touchX: 0,
+ touchY: 0
+ }
+ }
+ return {
+ touchX: touch.clientX,
+ touchY: touch.clientY
+ };
+}
+
+//判断当前手势是否在z-paging内触发
+function getTouchFromZPaging(target) {
+ if (target && target.tagName && target.tagName !== 'BODY' && target.tagName !== 'UNI-PAGE-BODY') {
+ var classList = target.classList;
+ if (classList && classList.contains('zp-paging-touch-view')) {
+ return true;
+ } else {
+ return getTouchFromZPaging(target.parentNode);
+ }
+ } else {
+ return false;
+ }
+}
+
+//获取z-paging所在的parent
+function getParent(parent) {
+ if (!parent) {
+ return null;
+ }
+ if (parent.$refs.paging) {
+ return parent;
+ }
+ return getParent(parent.$parent);
+}
+
+//打印错误信息
+function consoleErr(err) {
+ console.error(`[z-paging]${err}`);
+}
+
+//打印警告信息
+function consoleWarn(warn) {
+ console.warn(`[z-paging]${warn}`);
+}
+
+//设置下拉刷新时间
+function setRefesrherTime(time, key) {
+ try {
+ let datas = getRefesrherTime();
+ if (!datas) {
+ datas = {};
+ }
+ datas[key] = time;
+ uni.setStorageSync(storageKey, datas);
+ } catch {}
+}
+
+//获取下拉刷新时间
+function getRefesrherTime() {
+ try {
+ const datas = uni.getStorageSync(storageKey);
+ return datas;
+ } catch {
+ return null;
+ }
+}
+
+//通过下拉刷新标识key获取下拉刷新时间
+function getRefesrherTimeByKey(key) {
+ const datas = getRefesrherTime();
+ if (datas) {
+ const data = datas[key];
+ if (data) {
+ return data;
+ }
+ }
+ return null;
+}
+
+//通过下拉刷新标识key获取下拉刷新时间(格式化之后)
+function getRefesrherFormatTimeByKey(key) {
+ const time = getRefesrherTimeByKey(key);
+ let timeText = zI18n['refresherUpdateTimeNoneText'][zI18n.getLanguage()];
+ if (time) {
+ timeText = _timeFormat(time);
+ }
+ return `${zI18n['refresherUpdateTimeText'][zI18n.getLanguage()]}${timeText}`;
+}
+
+function _timeFormat(time) {
+ const date = new Date(time);
+ const currentDate = new Date();
+ const dateDay = new Date(time).setHours(0, 0, 0, 0);
+ const currentDateDay = new Date().setHours(0, 0, 0, 0);
+ const disTime = dateDay - currentDateDay;
+ let dayStr = '';
+ const timeStr = _dateTimeFormat(date);
+ if (disTime === 0) {
+ dayStr = zI18n['refresherUpdateTimeTodayText'][zI18n.getLanguage()];
+ } else if (disTime === -86400000) {
+ dayStr = zI18n['refresherUpdateTimeYesterdayText'][zI18n.getLanguage()];
+ } else {
+ dayStr = _dateDayFormat(date, date.getFullYear() !== currentDate.getFullYear());
+ }
+ return `${dayStr} ${timeStr}`;
+}
+
+function _dateDayFormat(date, showYear = true) {
+ const year = date.getFullYear();
+ const month = date.getMonth() + 1;
+ const day = date.getDate();
+ if (showYear) {
+ return `${year}-${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`;
+ } else {
+ return `${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`;
+ }
+}
+
+function _dateTimeFormat(date) {
+ const hour = date.getHours();
+ const minute = date.getMinutes();
+ return `${_fullZeroToTwo(hour)}:${_fullZeroToTwo(minute)}`;
+}
+
+function _fullZeroToTwo(str) {
+ str = str.toString();
+ if (str.length === 1) {
+ return '0' + str;
+ }
+ return str;
+}
+
+module.exports = {
+ setRefesrherTime,
+ getRefesrherFormatTimeByKey,
+ arrayIsEqual,
+ getCommonTouch,
+ getTouchFromZPaging,
+ getParent,
+ consoleErr,
+ consoleWarn
+};
diff --git a/uni_modules/z-paging/components/z-paging/wxs/z-paging-refresh.wxs b/uni_modules/z-paging/components/z-paging/wxs/z-paging-refresh.wxs
new file mode 100644
index 0000000..97602af
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/wxs/z-paging-refresh.wxs
@@ -0,0 +1,205 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+
+//微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新,降低逻辑层与视图层的通信折损,提升性能
+
+function propObserver(newValue, oldValue, ownerInstance, instance) {
+ var state = ownerInstance.getState();
+ state.currentInstance = instance;
+ var dataset = instance.getDataset();
+ var loading = dataset.loading == true;
+ if (newValue.indexOf('end') != -1) {
+ _setTransform('translateY(0px)', instance)
+ state.moveDistance = 0;
+ } else if (newValue.indexOf('begin') != -1) {
+ var refresherThreshold = instance.getDataset().refresherthreshold
+ _setTransformValue(refresherThreshold, instance, state);
+ }
+}
+
+function touchstart(e, ownerInstance) {
+ var instance = ownerInstance.getState().currentInstance;
+ var state = instance.getState();
+ if (_getRefresherTouchDisabled(e, instance)) {
+ return;
+ }
+ var touch = _getCommonTouch(e);
+ state.startY = touch.touchY;
+ state.lastRefresherTouchmove = touch;
+ ownerInstance.callMethod('_handleRefresherTouchstart', touch);
+}
+
+function touchmove(e, ownerInstance) {
+ var touch = _getCommonTouch(e);
+ var instance = ownerInstance.getState().currentInstance;
+ var dataset = instance.getDataset();
+ var refresherThreshold = dataset.refresherthreshold;
+ var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
+ var state = instance.getState();
+ if (_getRefresherTouchDisabled(e, instance)) {
+ return;
+ }
+ if (!_getAngleIsInRange(e, touch, state, dataset)) {
+ return;
+ }
+ var moveDistance = _getMoveDistance(e, instance);
+ if (moveDistance < 0) {
+ return;
+ }
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ _setTransformValue(moveDistance, instance, state);
+ var oldRefresherStatus = state.refresherStatus;
+ if (moveDistance >= refresherThreshold) {
+ state.refresherStatus = 1;
+ } else {
+ state.refresherStatus = 0;
+ }
+ if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || !isTouchmoving) {
+ ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
+ }
+ return false;
+}
+
+function touchend(e, ownerInstance) {
+ var touch = _getCommonTouch(e);
+ var instance = ownerInstance.getState().currentInstance;
+ var dataset = instance.getDataset();
+ var state = instance.getState();
+ if (_getRefresherTouchDisabled(e, instance)) {
+ return;
+ }
+ state.refresherReachMaxAngle = true;
+
+ var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
+ if (!isTouchmoving) {
+ return;
+ }
+ var oldMoveDistance = state.moveDistance;
+ var refresherThreshold = instance.getDataset().refresherthreshold
+ var moveDistance = _getMoveDistance(e, instance);
+ ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
+ if (oldMoveDistance < refresherThreshold) {
+ return;
+ }
+ if (moveDistance >= refresherThreshold) {
+ moveDistance = refresherThreshold;
+ }
+ _setTransformValue(moveDistance, instance, state)
+}
+
+
+function _setTransformValue(value, instance, state) {
+ value = value || 0;
+ state.moveDistance = value;
+ _setTransform('translateY(' + value + 'px)', instance);
+}
+
+function _setTransform(transform, instance) {
+ instance.requestAnimationFrame(function() {
+ instance.setStyle({
+ transform: transform,
+ '-webkit-transform': transform
+ })
+ })
+
+}
+
+function _getMoveDistance(e, instance) {
+ var state = instance.getState()
+ var refresherThreshold = instance.getDataset().refresherthreshold
+ var touch = _getCommonTouch(e);
+ var moveDistance = touch.touchY - state.startY;
+ moveDistance = _getFinalRefresherMoveDistance(moveDistance, refresherThreshold);
+ return moveDistance;
+}
+
+function _getCommonTouch(e) {
+ var touch = null;
+ if (e.touches && e.touches.length) {
+ touch = e.touches[0];
+ } else if (e.changedTouches && e.changedTouches.length) {
+ touch = e.changedTouches[0];
+ } else if (e.datail && e.datail !== {}) {
+ touch = e.datail;
+ } else {
+ return {
+ touchX: 0,
+ touchY: 0
+ }
+ }
+ return {
+ touchX: touch.clientX,
+ touchY: touch.clientY
+ };
+}
+
+function _getFinalRefresherMoveDistance(moveDistance, refresherThreshold) {
+ refresherThreshold = parseFloat(refresherThreshold);
+ moveDistance = moveDistance * 0.7;
+ if (moveDistance >= refresherThreshold) {
+ moveDistance = refresherThreshold + (moveDistance - refresherThreshold) * 0.3;
+ }
+ return moveDistance;
+}
+
+
+function _getRefresherTouchDisabled(e, instance) {
+ var dataset = instance.getDataset();
+ var loading = _getIsTrue(dataset.loading);
+ var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
+ var refresherEnabled = _getIsTrue(dataset.refresherenabled);
+ var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
+ var usePageScroll = _getIsTrue(dataset.usepagescroll);
+ var pageScrollTop = parseFloat(dataset.pagescrolltop);
+ var wxsIsScrollTopInTopRange = _getIsTrue(dataset.wxsisscrolltopintoprange);
+ var scrollTop = parseFloat(dataset.scrolltop);
+ var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || (
+ usePageScroll && useCustomRefresher && pageScrollTop > 10) || (!(
+ usePageScroll && useCustomRefresher) && !wxsIsScrollTopInTopRange);
+ return res;
+}
+
+function _getAngleIsInRange(e, touch, state, dataset) {
+ var refresherMaxAngle = dataset.refreshermaxangle;
+ var refresherAecc = _getIsTrue(dataset.refresheraecc);
+ var lastRefresherTouchmove = state.lastRefresherTouchmove;
+ var moveDistance = state.moveDistance;
+ var refresherReachMaxAngle = state.refresherReachMaxAngle;
+ if (!lastRefresherTouchmove) {
+ return true;
+ }
+ if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
+ if (!refresherAecc && refresherReachMaxAngle != null && !refresherReachMaxAngle) {
+ return false;
+ }
+ var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
+ var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
+ var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
+ if (x && y) {
+ var angle = Math.asin(y / z) / Math.PI * 180;
+ if (angle < refresherMaxAngle) {
+ state.lastRefresherTouchmove = touch;
+ state.refresherReachMaxAngle = false;
+ return false;
+ }
+ }
+ }
+ state.lastRefresherTouchmove = touch;
+ return true;
+}
+
+function _getIsTrue(value) {
+ value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
+ return value == true || value == 'true';
+}
+
+module.exports = {
+ touchstart: touchstart,
+ touchmove: touchmove,
+ touchend: touchend,
+ propObserver: propObserver
+}
diff --git a/uni_modules/z-paging/components/z-paging/wxs/z-paging-renderjs.js b/uni_modules/z-paging/components/z-paging/wxs/z-paging-renderjs.js
new file mode 100644
index 0000000..9a65752
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/wxs/z-paging-renderjs.js
@@ -0,0 +1,58 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+// 使用renderjs在app-vue和h5中对touchmove事件冒泡进行处理
+
+import zUtils from '../js/z-paging-utils'
+var data = {
+ renderScrollTop: 0,
+ renderUsePageScroll: false,
+ renderIsIos: uni.getSystemInfoSync().platform === 'ios',
+ startY: 0,
+ isTouchFromZPaging: false
+}
+
+export default {
+ mounted() {
+ this._handleTouch();
+ },
+ methods: {
+ //接收逻辑层发送的数据
+ renderPropScrollTopChange(newVal, oldVal, ownerVm, vm) {
+ data.renderScrollTop = newVal;
+ },
+ renderPropUsePageScrollChange(newVal, oldVal, ownerVm, vm) {
+ if(newVal !== -1){
+ data.renderUsePageScroll = newVal;
+ }
+ },
+ //拦截处理touch事件
+ _handleTouch() {
+ if (window && !window.$zPagingRenderJsInited) {
+ window.$zPagingRenderJsInited = true;
+ window.addEventListener('touchstart', this._handleTouchstart, {
+ passive: true
+ })
+ window.addEventListener('touchmove', this._handleTouchmove, {
+ passive: false
+ })
+ }
+ },
+ _handleTouchstart(e) {
+ const touch = zUtils.getCommonTouch(e);
+ data.startY = touch.touchY;
+ data.isTouchFromZPaging = zUtils.getTouchFromZPaging(e.target);
+ },
+ _handleTouchmove(e) {
+ const touch = zUtils.getCommonTouch(e);
+ var moveY = touch.touchY - data.startY;
+ if ((data.isTouchFromZPaging && data.renderScrollTop < 1 && moveY > 0) || (data.isTouchFromZPaging && data.renderIsIos && !data.renderUsePageScroll && moveY < 0)) {
+ if (e.cancelable && !e.defaultPrevented) {
+ e.preventDefault();
+ }
+ }
+ },
+
+ }
+};
diff --git a/uni_modules/z-paging/components/z-paging/wxs/z-paging-wxs.wxs b/uni_modules/z-paging/components/z-paging/wxs/z-paging-wxs.wxs
new file mode 100644
index 0000000..362946a
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/wxs/z-paging-wxs.wxs
@@ -0,0 +1,346 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+// 微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新,降低逻辑层与视图层的通信折损,提升性能
+
+var currentMoveDistance = 0;
+
+function propObserver(newValue, oldValue, ownerInstance, instance) {
+ var state = ownerInstance.getState();
+ state.currentInstance = instance;
+ var dataset = instance.getDataset();
+ var loading = dataset.loading == true;
+ if (newValue.indexOf('end') != -1) {
+ _setTransform('translateY(0px)', instance)
+ state.moveDistance = 0;
+ state.oldMoveDistance = 0;
+ currentMoveDistance = 0;
+ } else if (newValue.indexOf('begin') != -1) {
+ var refresherThreshold = instance.getDataset().refresherthreshold
+ _setTransformValue(refresherThreshold, instance, state);
+ }
+}
+
+function touchstart(e, ownerInstance) {
+ var instance = ownerInstance.getState().currentInstance;
+ var state = instance.getState();
+ var dataset = instance.getDataset();
+ var isTouchEnded = state.isTouchEnded;
+ if (_getRefresherTouchDisabled(e, instance, 0)) {
+ return;
+ }
+ state.oldMoveDistance = 0;
+ var touch = _getCommonTouch(e);
+ var loading = _getIsTrue(dataset.loading);
+ state.startY = touch.touchY;
+ state.lastRefresherTouchmove = touch;
+ if (!loading && isTouchEnded) {
+ state.isTouchmoving = false;
+ }
+ state.isTouchEnded = false;
+ ownerInstance.callMethod('_handleRefresherTouchstart', touch);
+}
+
+function touchmove(e, ownerInstance) {
+ var touch = _getCommonTouch(e);
+ var instance = ownerInstance.getState().currentInstance;
+ var dataset = instance.getDataset();
+ var refresherThreshold = dataset.refresherthreshold;
+ var state = instance.getState();
+ if (_getRefresherTouchDisabled(e, instance, 1)) {
+ _handleTouchMovePullingDown(state, ownerInstance, false);
+ return true;
+ }
+ if (!_getAngleIsInRange(e, touch, state, dataset)) {
+ _handleTouchMovePullingDown(state, ownerInstance, false);
+ return true;
+ }
+ var moveDistanceObj = _getMoveDistance(e, instance);
+ var moveDistance = moveDistanceObj.currentMoveDistance;
+ var prevent = moveDistanceObj.isDown;
+ if (moveDistance < 0) {
+ _setTransformValue(0, instance, state);
+ _handleTouchMovePullingDown(state, ownerInstance, false);
+ return true;
+ }
+ if (prevent && !state.disabledBounce) {
+ ownerInstance.callMethod('_handleScrollViewDisableBounce', {
+ bounce: false
+ });
+ state.disabledBounce = true;
+ _handleTouchMovePullingDown(state, ownerInstance, prevent);
+ return !prevent;
+ }
+ _setTransformValue(moveDistance, instance, state);
+ var oldRefresherStatus = state.refresherStatus;
+ var dataset = instance.getDataset();
+ var oldIsTouchmoving = _getIsTrue(dataset.oldistouchmoving);
+ var isTouchmoving = state.isTouchmoving;
+ if (moveDistance >= refresherThreshold) {
+ state.refresherStatus = 1;
+ } else {
+ state.refresherStatus = 0;
+ }
+ if (!isTouchmoving) {
+ state.isTouchmoving = true;
+ isTouchmoving = true;
+ }
+ if (state.isTouchEnded) {
+ state.isTouchEnded = false;
+ }
+ if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || oldIsTouchmoving !=
+ isTouchmoving) {
+ ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
+ }
+ _handleTouchMovePullingDown(state, ownerInstance, prevent);
+ return !prevent;
+}
+
+function touchend(e, ownerInstance) {
+ var touch = _getCommonTouch(e);
+ var instance = ownerInstance.getState().currentInstance;
+ var dataset = instance.getDataset();
+ var state = instance.getState();
+ if (_getRefresherTouchDisabled(e, instance, 2)) {
+ return;
+ }
+ state.refresherReachMaxAngle = true;
+ state.hitReachMaxAngleCount = 0;
+ state.disabledBounce = false;
+ state.fixedIsTopHitCount = 0;
+ //ownerInstance.callMethod('_handleScrollViewDisableBounce', {bounce:true});
+ var isTouchmoving = state.isTouchmoving;
+ if (!isTouchmoving) {
+ return;
+ }
+ var oldRefresherStatus = state.refresherStatus;
+ var oldMoveDistance = state.moveDistance;
+ var refresherThreshold = instance.getDataset().refresherthreshold
+ var moveDistance = _getMoveDistance(e, instance).currentMoveDistance;
+ if (!(moveDistance >= refresherThreshold && oldRefresherStatus === 1)) {
+ state.isTouchmoving = false;
+ }
+ ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
+ state.isTouchEnded = true;
+ if (oldMoveDistance < refresherThreshold) {
+ return;
+ }
+ var animate = false;
+ if (moveDistance >= refresherThreshold) {
+ moveDistance = refresherThreshold;
+ var isIos13 = _getIsTrue(dataset.isios13);
+ if (isIos13) {
+ animate = true;
+ }
+ }
+ _setTransformValue(moveDistance, instance, state, animate);
+}
+
+// #ifdef H5
+function isPC() {
+ var userAgentInfo = navigator.userAgent;
+ var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+ var flag = true;
+ for (var v = 0; v < Agents.length - 1; v++) {
+ if (userAgentInfo.indexOf(Agents[v]) > 0) {
+ flag = false;
+ break;
+ }
+ }
+ return flag;
+}
+
+var movable = false;
+
+function mousedown(e, ins) {
+ if (!isPC()) return;
+ touchstart(e, ins);
+ movable = true;
+}
+
+function mousemove(e, ins) {
+ if (!isPC()) return;
+ if (!movable) return;
+ touchmove(e, ins);
+}
+
+function mouseup(e, ins) {
+ if (!isPC()) return;
+ touchend(e, ins);
+ movable = false;
+}
+
+function mouseleave(e, ins) {
+ if (!isPC()) return;
+ movable = false;
+}
+// #endif
+
+
+function _setTransformValue(value, instance, state, animate = false) {
+ value = value || 0;
+ if (state.moveDistance == value) {
+ return;
+ }
+ state.moveDistance = value;
+ _setTransform('translateY(' + value + 'px)', instance, animate);
+}
+
+function _setTransform(transform, instance, animate = false) {
+ if (transform == 'translateY(0px)') {
+ transform = 'none';
+ }
+ instance.requestAnimationFrame(function() {
+ if (animate) {
+ instance.setStyle({
+ 'transform': transform,
+ 'transition': 'transform .1s linear',
+ })
+ } else {
+ instance.setStyle({
+ 'transform': transform
+ })
+ }
+ })
+}
+
+function _getMoveDistance(e, instance) {
+ var state = instance.getState();
+ var refresherThreshold = instance.getDataset().refresherthreshold;
+ var refresherOutRate = instance.getDataset().refresheroutrate;
+ refresherThreshold = parseFloat(refresherThreshold);
+ refresherOutRate = parseFloat(refresherOutRate);
+ var touch = _getCommonTouch(e);
+ var moveDistance = touch.touchY - state.startY;
+ var oldMoveDistance = state.oldMoveDistance || 0;
+ state.oldMoveDistance = moveDistance;
+ var diffDis = moveDistance - oldMoveDistance;
+ if (diffDis > 0) {
+ diffDis = diffDis * 0.85;
+ if (currentMoveDistance > refresherThreshold) {
+ diffDis = diffDis * (1 - refresherOutRate);
+ }
+ }
+ currentMoveDistance += diffDis;
+ if (currentMoveDistance < 0) {
+ currentMoveDistance = 0;
+ }
+ return {
+ currentMoveDistance: currentMoveDistance,
+ isDown: diffDis > 0
+ };
+}
+
+function _getCommonTouch(e) {
+ var touch = null;
+ if (e.touches && e.touches.length) {
+ touch = e.touches[0];
+ } else if (e.changedTouches && e.changedTouches.length) {
+ touch = e.changedTouches[0];
+ } else if (e.datail && e.datail !== {}) {
+ touch = e.datail;
+ } else {
+ touch = e;
+ }
+ return {
+ touchX: touch.clientX,
+ touchY: touch.clientY
+ };
+}
+
+function _getRefresherTouchDisabled(e, instance, processTag) {
+ var dataset = instance.getDataset();
+ var state = instance.getState();
+ var loading = _getIsTrue(dataset.loading);
+ var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
+ var refresherEnabled = _getIsTrue(dataset.refresherenabled);
+ var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
+ var usePageScroll = _getIsTrue(dataset.usepagescroll);
+ var pageScrollTop = parseFloat(dataset.pagescrolltop);
+ var scrollTop = parseFloat(dataset.scrolltop);
+ var finalScrollTop = usePageScroll ? pageScrollTop : scrollTop;
+ var fixedIsTop = false;
+ var isIos = _getIsTrue(dataset.isios);
+ if (!isIos && finalScrollTop == (state.startScrollTop || 0) && finalScrollTop <= 105) {
+ fixedIsTop = true;
+ }
+ var fixedIsTopHitCount = state.fixedIsTopHitCount || 0;
+ if (fixedIsTop) {
+ fixedIsTopHitCount++;
+ if (fixedIsTopHitCount <= 3) {
+ fixedIsTop = false;
+ }
+ state.fixedIsTopHitCount = fixedIsTopHitCount;
+ } else {
+ state.fixedIsTopHitCount = 0;
+ }
+ if (!isIos && processTag === 0) {
+ state.startScrollTop = finalScrollTop || 0;
+ }
+ if (!isIos && processTag === 2) {
+ fixedIsTop = true;
+ }
+ var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || ((
+ usePageScroll && useCustomRefresher && pageScrollTop > 5) && !fixedIsTop) || ((
+ !usePageScroll && useCustomRefresher && scrollTop > 5) && !fixedIsTop);
+ return res;
+}
+
+function _getAngleIsInRange(e, touch, state, dataset) {
+ var refresherMaxAngle = dataset.refreshermaxangle;
+ var refresherAecc = _getIsTrue(dataset.refresheraecc);
+ var lastRefresherTouchmove = state.lastRefresherTouchmove;
+ var refresherReachMaxAngle = state.refresherReachMaxAngle;
+ var moveDistance = state.oldMoveDistance;
+ if (!lastRefresherTouchmove) {
+ return true;
+ }
+ if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
+ if ((!moveDistance || moveDistance < 1) && !refresherAecc && refresherReachMaxAngle != null && !
+ refresherReachMaxAngle) {
+ return false;
+ }
+ var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
+ var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
+ var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
+ if ((x || y) && x > 1) {
+ var angle = Math.asin(y / z) / Math.PI * 180;
+ if (angle < refresherMaxAngle) {
+ var hitReachMaxAngleCount = state.hitReachMaxAngleCount || 0;
+ state.hitReachMaxAngleCount = ++hitReachMaxAngleCount;
+ if (state.hitReachMaxAngleCount > 2) {
+ state.lastRefresherTouchmove = touch;
+ state.refresherReachMaxAngle = false;
+ }
+ return false;
+ }
+ }
+ }
+ state.lastRefresherTouchmove = touch;
+ return true;
+}
+
+function _handleTouchMovePullingDown(state, instance, onPullingDown) {
+ var oldOnPullingDown = state.onPullingDown || false;
+ if (oldOnPullingDown != onPullingDown) {
+ instance.callMethod('_handleWxsOnPullingDown', onPullingDown);
+ }
+ state.onPullingDown = onPullingDown;
+}
+
+function _getIsTrue(value) {
+ value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
+ return value == true || value == 'true';
+}
+
+module.exports = {
+ touchstart: touchstart,
+ touchmove: touchmove,
+ touchend: touchend,
+ mousedown: mousedown,
+ mousemove: mousemove,
+ mouseup: mouseup,
+ mouseleave: mouseleave,
+ propObserver: propObserver
+}
diff --git a/uni_modules/z-paging/components/z-paging/z-paging-load-more.vue b/uni_modules/z-paging/components/z-paging/z-paging-load-more.vue
new file mode 100644
index 0000000..d7fbc82
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/z-paging-load-more.vue
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ownLoadingMoreText}}
+
+
+
+
+
+
diff --git a/uni_modules/z-paging/components/z-paging/z-paging-mixin.js b/uni_modules/z-paging/components/z-paging/z-paging-mixin.js
new file mode 100644
index 0000000..6511283
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/z-paging-mixin.js
@@ -0,0 +1,35 @@
+
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+
+// 使用页面滚动时引入此mixin,用于监听和处理onPullDownRefresh等页面生命周期方法
+
+const ZPagingMixin = {
+ onPullDownRefresh(){
+ if(this.isPagingRefNotFound()){
+ return;
+ }
+ this.$refs.paging.reload();
+ },
+ onPageScroll(e) {
+ if(this.isPagingRefNotFound()){
+ return;
+ }
+ this.$refs.paging.updatePageScrollTop(e.scrollTop);
+ },
+ onReachBottom() {
+ if(this.isPagingRefNotFound()){
+ return;
+ }
+ this.$refs.paging.doLoadMore();
+ },
+ methods: {
+ isPagingRefNotFound(){
+ return !this.$refs.paging || this.$refs.paging === undefined;
+ }
+ }
+}
+
+export default ZPagingMixin;
diff --git a/uni_modules/z-paging/components/z-paging/z-paging-refresh.vue b/uni_modules/z-paging/components/z-paging/z-paging-refresh.vue
new file mode 100644
index 0000000..1a11716
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/z-paging-refresh.vue
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{refresherStatusTextMap[refresherStatus]}}
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-paging/components/z-paging/z-paging-refresh.wxs b/uni_modules/z-paging/components/z-paging/z-paging-refresh.wxs
new file mode 100644
index 0000000..97602af
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/z-paging-refresh.wxs
@@ -0,0 +1,205 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+
+//微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新,降低逻辑层与视图层的通信折损,提升性能
+
+function propObserver(newValue, oldValue, ownerInstance, instance) {
+ var state = ownerInstance.getState();
+ state.currentInstance = instance;
+ var dataset = instance.getDataset();
+ var loading = dataset.loading == true;
+ if (newValue.indexOf('end') != -1) {
+ _setTransform('translateY(0px)', instance)
+ state.moveDistance = 0;
+ } else if (newValue.indexOf('begin') != -1) {
+ var refresherThreshold = instance.getDataset().refresherthreshold
+ _setTransformValue(refresherThreshold, instance, state);
+ }
+}
+
+function touchstart(e, ownerInstance) {
+ var instance = ownerInstance.getState().currentInstance;
+ var state = instance.getState();
+ if (_getRefresherTouchDisabled(e, instance)) {
+ return;
+ }
+ var touch = _getCommonTouch(e);
+ state.startY = touch.touchY;
+ state.lastRefresherTouchmove = touch;
+ ownerInstance.callMethod('_handleRefresherTouchstart', touch);
+}
+
+function touchmove(e, ownerInstance) {
+ var touch = _getCommonTouch(e);
+ var instance = ownerInstance.getState().currentInstance;
+ var dataset = instance.getDataset();
+ var refresherThreshold = dataset.refresherthreshold;
+ var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
+ var state = instance.getState();
+ if (_getRefresherTouchDisabled(e, instance)) {
+ return;
+ }
+ if (!_getAngleIsInRange(e, touch, state, dataset)) {
+ return;
+ }
+ var moveDistance = _getMoveDistance(e, instance);
+ if (moveDistance < 0) {
+ return;
+ }
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ _setTransformValue(moveDistance, instance, state);
+ var oldRefresherStatus = state.refresherStatus;
+ if (moveDistance >= refresherThreshold) {
+ state.refresherStatus = 1;
+ } else {
+ state.refresherStatus = 0;
+ }
+ if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || !isTouchmoving) {
+ ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
+ }
+ return false;
+}
+
+function touchend(e, ownerInstance) {
+ var touch = _getCommonTouch(e);
+ var instance = ownerInstance.getState().currentInstance;
+ var dataset = instance.getDataset();
+ var state = instance.getState();
+ if (_getRefresherTouchDisabled(e, instance)) {
+ return;
+ }
+ state.refresherReachMaxAngle = true;
+
+ var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
+ if (!isTouchmoving) {
+ return;
+ }
+ var oldMoveDistance = state.moveDistance;
+ var refresherThreshold = instance.getDataset().refresherthreshold
+ var moveDistance = _getMoveDistance(e, instance);
+ ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
+ if (oldMoveDistance < refresherThreshold) {
+ return;
+ }
+ if (moveDistance >= refresherThreshold) {
+ moveDistance = refresherThreshold;
+ }
+ _setTransformValue(moveDistance, instance, state)
+}
+
+
+function _setTransformValue(value, instance, state) {
+ value = value || 0;
+ state.moveDistance = value;
+ _setTransform('translateY(' + value + 'px)', instance);
+}
+
+function _setTransform(transform, instance) {
+ instance.requestAnimationFrame(function() {
+ instance.setStyle({
+ transform: transform,
+ '-webkit-transform': transform
+ })
+ })
+
+}
+
+function _getMoveDistance(e, instance) {
+ var state = instance.getState()
+ var refresherThreshold = instance.getDataset().refresherthreshold
+ var touch = _getCommonTouch(e);
+ var moveDistance = touch.touchY - state.startY;
+ moveDistance = _getFinalRefresherMoveDistance(moveDistance, refresherThreshold);
+ return moveDistance;
+}
+
+function _getCommonTouch(e) {
+ var touch = null;
+ if (e.touches && e.touches.length) {
+ touch = e.touches[0];
+ } else if (e.changedTouches && e.changedTouches.length) {
+ touch = e.changedTouches[0];
+ } else if (e.datail && e.datail !== {}) {
+ touch = e.datail;
+ } else {
+ return {
+ touchX: 0,
+ touchY: 0
+ }
+ }
+ return {
+ touchX: touch.clientX,
+ touchY: touch.clientY
+ };
+}
+
+function _getFinalRefresherMoveDistance(moveDistance, refresherThreshold) {
+ refresherThreshold = parseFloat(refresherThreshold);
+ moveDistance = moveDistance * 0.7;
+ if (moveDistance >= refresherThreshold) {
+ moveDistance = refresherThreshold + (moveDistance - refresherThreshold) * 0.3;
+ }
+ return moveDistance;
+}
+
+
+function _getRefresherTouchDisabled(e, instance) {
+ var dataset = instance.getDataset();
+ var loading = _getIsTrue(dataset.loading);
+ var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
+ var refresherEnabled = _getIsTrue(dataset.refresherenabled);
+ var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
+ var usePageScroll = _getIsTrue(dataset.usepagescroll);
+ var pageScrollTop = parseFloat(dataset.pagescrolltop);
+ var wxsIsScrollTopInTopRange = _getIsTrue(dataset.wxsisscrolltopintoprange);
+ var scrollTop = parseFloat(dataset.scrolltop);
+ var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || (
+ usePageScroll && useCustomRefresher && pageScrollTop > 10) || (!(
+ usePageScroll && useCustomRefresher) && !wxsIsScrollTopInTopRange);
+ return res;
+}
+
+function _getAngleIsInRange(e, touch, state, dataset) {
+ var refresherMaxAngle = dataset.refreshermaxangle;
+ var refresherAecc = _getIsTrue(dataset.refresheraecc);
+ var lastRefresherTouchmove = state.lastRefresherTouchmove;
+ var moveDistance = state.moveDistance;
+ var refresherReachMaxAngle = state.refresherReachMaxAngle;
+ if (!lastRefresherTouchmove) {
+ return true;
+ }
+ if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
+ if (!refresherAecc && refresherReachMaxAngle != null && !refresherReachMaxAngle) {
+ return false;
+ }
+ var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
+ var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
+ var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
+ if (x && y) {
+ var angle = Math.asin(y / z) / Math.PI * 180;
+ if (angle < refresherMaxAngle) {
+ state.lastRefresherTouchmove = touch;
+ state.refresherReachMaxAngle = false;
+ return false;
+ }
+ }
+ }
+ state.lastRefresherTouchmove = touch;
+ return true;
+}
+
+function _getIsTrue(value) {
+ value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
+ return value == true || value == 'true';
+}
+
+module.exports = {
+ touchstart: touchstart,
+ touchmove: touchmove,
+ touchend: touchend,
+ propObserver: propObserver
+}
diff --git a/uni_modules/z-paging/components/z-paging/z-paging-static.css b/uni_modules/z-paging/components/z-paging/z-paging-static.css
new file mode 100644
index 0000000..e62e6ee
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/z-paging-static.css
@@ -0,0 +1,28 @@
+/* z-paging
+github地址:https://github.com/SmileZXLee/uni-z-paging
+dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+反馈QQ群:790460711
+
+公用的静态css资源 */
+
+.zp-loading-more-line-loading-image {
+ margin-right: 8rpx;
+ width: 28rpx;
+ height: 28rpx;
+ /* #ifndef APP-NVUE */
+ animation: loading-flower 1s steps(12) infinite;
+ /* #endif */
+ color: #666666;
+}
+
+@keyframes loading-flower {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ to {
+ -webkit-transform: rotate(1turn);
+ transform: rotate(1turn);
+ }
+}
diff --git a/uni_modules/z-paging/components/z-paging/z-paging-static.js b/uni_modules/z-paging/components/z-paging/z-paging-static.js
new file mode 100644
index 0000000..c8365cf
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/z-paging-static.js
@@ -0,0 +1,18 @@
+// z-paging
+// github地址:https://github.com/SmileZXLee/uni-z-paging
+// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
+// 反馈QQ群:790460711
+
+// 公用的静态图片资源
+const base64Arrow =
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAD1BMVEVHcExRUVFMTExRUVFRUVE9CdWsAAAABHRSTlMAjjrY9ZnUjwAAAQFJREFUWMPt2MsNgzAMgGEEE1B1gKJmAIRYoCH7z9RCXrabh33iYktcIv35EEg5ZBh07pvxJU6MFSPOSRnjnBUjUsaciRUjMsb4xIoRCWNiYsUInzE5sWKEyxiYWDbyefqHx1zIeiYTk7mQYziTYecxHvEJjwmIT3hMQELCYSISEg4TkZj0mYTEpM8kJCU9JiMp6TEZyUmbAUhO2gxAQNJiIAKSFgMRmNQZhMCkziAEJTUGIyipMRjBSZkhCE7KDEFIUmTeGCHJxWz0zXaE0GTCG8ZFtEaS347r/1fe11YyHYVfubxayfjoHmc0YYwmmmiiiSaaaKLJ7ckyz5ve+dw3Xw2emdwm9xSbAAAAAElFTkSuQmCC';
+const base64Flower =
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAKlBMVEVHcEzDw8Ovr6+pqamUlJTCwsKenp61tbWxsbGysrLNzc2bm5u5ubmjo6MpovhuAAAACnRSTlMA/P79/sHDhiZS0DxZowAABBBJREFUWMPtl89rE0EUx7ctTXatB3MI1SWnDbUKPUgXqh4ED8Uf7KUVSm3ooVSpSii0Fn/gD4j4o+APiEoVmos9FO2celiqZVgwgaKHPQiCCkv+F99kM7Ozm5kxq1dfD91k9pPve9/3ZjbRNHHok/mKli4eIPNgSuRObuN9SqSEzM20iGnm0yIbqCuV7NSSSIV7uyPM6JMBYdeTOanh/QihJYZsUCSby+VkMj2AvOt0rAeQAwqE3lfKMZVlQCZk1QOCKkkVPadITCfIRNKxfoJI5+0OIFtJx14CMSg1mRSDko7VAfksRQzEbGYqxOJcVTWMCH2I1/IACNW0PWU2M8cmAVHtnH5mM1VRWtwKZjOd5JbF6s1IbaYqaotjNlPHgDAnlAizubTR6ovMYn052g/U5qcmOpi0WL8xTS/3IfSet5m8MEr5ajjF5le6dq/OJpobrdY0t3i9QgefWrxW9/1BLhk0E9m8FeUMhhXal499iD0eQRfDF+ts/tttORRerfp+oV7f4xJj82iUYm1Yzod+ZQEAlS/8mMBwKebVmCVp1f0JLS6zKd17+iwRKTARVg2SHtz3iEbBH+Q+U28zW2Jiza8Tjb1YFoYZMsJyjDqp3M9XBQdSdPLFdxEpvOB37JrHcmR/y9+LgoTlCFGZEa2sc6d4PGlweEa2JSVPoVm+IfGG3ZL037iV9oH+P+Jxc4HGVflNq1M0pivao/EopO4b/ojVCP9GjmiXOeS0DOn1o/iiccT4ORnyvBGF3yUywkQajW4Ti0SGuiy/wVSg/L8w+X/8Q+hvUx8Xd90z4oV5a1i88MbFWHz0WZZ1UrTwBGPX3Rat9AFiXRMRjoMdIdJLEOt2h7jrYOzgOamKZSWSNspOS0X8SAqRYmxRL7sg4eLzYmNehcxh3uoyud/BH2Udux4ywxFTc1xC7Mgf4vMhc5S+kSH3Y7yj+qpwIWSoPTVCOOPVthGx9FbGqrwFw6wSFxJr+17zeKcztt3u+2roAEVgUjDd+AHGuxHy2rZHaa8JMkTHEeyi85ANPO9j9BVuBRD2FY5LDMo/Sz/2hReqGIs/KiFin+CsPsYO/yvM3jL2vE8EbX7/Bf8ejtr2GLN65bioAdgLd8Bis/mD5GmP2qeqyo2ZwQEOtAjRIDH7mBKpUcMoApbZJ5UIxkEwxyMZyMxW/uKFvHCFR3SSmerHyDNQ2dF4JG6zIMpBgLfjSF9x1D6smFcYnGApjmSLICO3ecCDWrQ48geba9DI3STy2i7ax6WIB62fSyIZIiO3GFQqSURp8wCo7GhJBGwuSovJBNjb7kT6FPVnIa9qJ2Ko+l9mefGIdinaMp0yC1URYiwsdfNE45EuA5Cx9EhalfvN5s+UyItm81vaB3p4joniN+SCP7Qc1hblAAAAAElFTkSuQmCC';
+const base64Empty = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAbUExURdvc3EdwTMLBwcjIyLSzs/Hx8ff39////19dXXz7IJEAAAAFdFJOU/4A6J9QDyyutAAAB5VJREFUeNrtnM1z4jYYxhUHkR4hdu9eU7Z75Ct7jgPbs9ZZmSuTrUWPmXTA186e+LMrf0uWLMtf2WkHXQgzln88et5XeiVMwPQdGrhCrpAr5Aq5Qv4TkJ07OGQFMLp1B4VYCz+kDblDQhJGeH4eEDLBYdLOHwaDWNBPIeHLYJAJ3meQ83IoCMTHDBKOBoKYGOeM8G0gyD0LObnDQB5ZSCtTNCBfsM9AboaBPLCQcDAIM1zht/dQEkMsd1DjI4hpw2YzMtBJeBbydWpCTJs3YDKGX62YgfGoVwi9KwtZJAzcYHHRm7sYCKD390nQSIoO5JGZIEOYxNoZ4+deISYLyeL5hLHbJ2QK98W0kudMgJe9Qh73odhO+KZHyNYGvgQS9gmJKhUigwSj3iBPUhXxePWmxBqHw0Mej9WQ3qILVjLC177yxNxXQ/7uK+Mn1aNVLsGsBTaWrSAPobYl0aUHt2fIs2Rgz7c9QYL0pSTkSzILLFtAJMH1cidN998T9E0/Sg73/pEEwrgkYRh86wlC949gJsR6EobBcz8hHOVgKYi2m6kZtodIkjEQvF3QjbGpmplB4/lRgJhxgRS2N15iijAvPmByDtCxfQhPJ8J4CR82rgCCBILarScw6X0OcMUyYrFVmbxErl0ZacFIoloOLdJAO42qY+NMDss2kKS8xmiZxcCpFKXWvpRGbQqJp5ixyRfJMmR6x0Fk+z29kmgWDYI5ziFbdug/84HxvduhWhLOJ2StPDQrMJPSjNANklh8QhB7dBO0yTGRwn1fkOk8rbQjiB8Ymww+JuiuN0icmSccK4naLMWYa/euL0+m23GyM8kgAc6sYeL4z04Qa4WjGepcKIliO8EUGSk7d9OGWOsoK31OSdy8TQZ59Y/hWbaV1IVs5/Ed6UzGK4nANAJiyGhRsZPUg2yzLe9hLyiJIyCaDU7udC2uy9pnkKvidlBUEltzFAqxRhBrBZm7HfZnjEQI3boqTsJq15PUDEaKZLgiJYc8OZtCtnM/4G93OFYooXpvdy0guwWWNQkEHl/j7Jw1XRmtlS9HYJkSPjk1IUnyyRqUKQn45NSDlP1mcg9i6En1ZU2IADnEtHF1Q+JwIcS/d5YakPuDUamEShGUHHikAz9oQCaE0CsrpYjDBVkEHQYdyK+EkKPhVErxqh1xbJ/oQf4gEeVsOIEc41WJNAwcd9GBfCZJezXsJhAvH+ImEEIOzlwXgpw5wQ0gH3MIOcsiQAahZuSD69/UQyxcQEggiQARQseVFO/ASAMCgM9gjkHZmhLENzi1AOhA7ullkMWUrfHKfpMiDBHtDIx6yCS6jseEnDUe7zcT6DGCtnrIY3olZw1hrPHkfucIAJa1EDu/lsVEyVmGGA67coKijeogFnMxlEaAV5ghRdDm1kDuuatZTJBGgJdOthIzsvZbDWRRuh6ScgR4EQLgagQvRQIxxQ4sxqcR4GE+c4CkjZQQW9YF89Y4OFAjOCki5KmiDxsBL3PlSJWlAFVogaoIePlYi2ClCJAHRa/cmre5eqTii4uvisqQJxqnip6pNd68DhEvyEs5xIyHBNdh4thCKhU++10kD7Gy1Up1A/o56FKuRJQWSFCuf8dpbisxhqHSKlSSgvG7VTaFKO5TzYD5VMPUxEB2YJNiqq3xYJ0KrroH8mq7xpoXqEZgfgNRUQsDtTVvUOk3sLUKbqrBr7YGvkCkQNC/9SA+vTYtvERrxiKEmcogk4ZqCLUd59MIEiFYHlIoxelCaJWDMmtOPIa80XVLbkb6hzaEwwTcPEmV4AIRlBGNIEmuJBFwLAZoHClJ36J8h+wxihpCqJosAnJrSKwEcQOFAFeWN4RQMYc0Ao4Jhg5gpASzyWcDvjpuDIlTkrGGJEro1rHIjHKR3wJCAj+z5oyi11gJBkXy9QFJIiAu78d+pgSjuWhGN0gUAZAcEncSJf4LRrZ8I94WEmcNCJJqBWYjVbE9bg2JxiyrViBWty6QvO56D8jPVWLA4ZX8dfkxvJJPl8t8aCX+pU/Iz1SCf7lc4OBK0OWfQaKLP0TKjj96VvIp+/BDZjwNKF2ItV2vN7sWStAl87oWkm3dZ+k3lEMoYXe8cT1eq2TOePJDD8KfQdxu6iEPxanUZa4HmZRq3dunGsj3BzFq6yD3wnZNX4n2emI2hXyXQpi6RRZdfSgxHNuxVZBFdyVeBPDmCsiksxKUiDAUEKuzkvRUEs0V08pjVyU2/yqFmF2VZGYop3peitdUiQd1pnrL7qTE01tPzE6eaEKm23dQwh2jNlbiay+/245zl94abw45CzNPyqYQ2++kxHGV1crWzg4A2yvR+BY7wziwnRLN7+O36aA54+ZKGjxZYK3txJpxQyUNn5GwtquII4+ACiWtnvawduu1A3SVtH5uhTvAVSpBG7fDYz6RQ+M6JWjmKm6g+RvTla9UMtspu+s+37VbVCupNqPx43CsNawSb1PbtcmDfQWmUILW7rRXSPHtSq5k5ur0a/hb7DQCUiW3G71ejX/wvV1kSoyNbp8Wvyqn1lCIKvl6gNDkNBYzt0GHdr+Pt9xGl1//ncAVcoVcIVfIFXKFXCFXyP8I8i8SyTW4yTz2lwAAAABJRU5ErkJggg=='
+const base64BackToTop = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAElBMVEVRUVH+/v5HcEyZmZlRUVFRUVGm1ByOAAAABnRSTlPMzADMTZAJBBGsAAAEnElEQVR42t2cS27jMAyGf7/2U+QCQeDsbeQCgZDujaC5/1UmkzaJn+JDFGcw3LdfflKibJkkDnxrL7dbg7sNt6+L4O8OYBM+B0ys+QrGkHZG+OEEQ8g6go8Bx1GIGMdpNOQyIG6XdMgnSPtKhLQDGEZFBgYMkhKFtGBb0EIEjDgFRowoBVaMGAWpMedEfxMiZtwpUsgZCqtlkCNUdpVAWigtCCCDFtLwIWeoreZCWiRYYEKGFEjDg+yRZCUH0iLRAgNyToXUNCRZyMqWhGnUN2IPm3wSlwJ7IUspyCBkIQUZhCykIIeQuRTkEDKXAuM9srrtYbrZN7Y98giZSoFd+t1OxmMITG0dcrSFXFchZ1tIvQZpYWxhBbK3hpQrkMEa0iwh5t4a+QvZvDXyF7J5a+Qv5PPW21/I5623v5DPW29/IaO3Xv5Clrw1y1/Ikrdm+Qs5svw83yNnSJ5BQb4F/F7EIEJSnThGBAXxkFQfLOviQUE8JAUPsosHBfGQfDAtHhREQ1JxIV00KIgmrnRI84S0yAd5BAXxxJUck0f6Qnwr9qmr6xF5xLMjcwn/iudIEAdWnyjkEXlQKZiRVzoqRyLbgeUKKR8Q4alY7cSnoxzSf2ggsqehKr6YVpcXpOd7H93f60cKhOd7Re2LteUF4eLqiVS1mr0ge4io6C2+soaFkJ7MuuuQs1yITEp9hwwKISIpzR2iESKSIoT0rLNwuVHQqoSIpAQJpGce60vIUSdEIuUqgPTsJ5QFZK8UIpBS8iG94GFrDjlrhfCl8CG96Llxmle4kEr6vKWBPIVo9kqDQSRk9/3cWoikcCFPAd33v4dIChPyEvLzBA6RlEYWke4JEUnhKXkLeUEKxRHJFfKCQHGucIW8IdZSRkLeEGMpYyEjiK2UsZARxFTKRMgYYillImQMMZQyFTKB2EmZCplAuFLIHT8TMoWwpQwiIVMIUwqpZP5bp5CCvCTiQKr5f5lCQN+tPCBn2ZvVDFJwIDUP0m1BYAfZYRNSsCB7BqTbhoARePIxtZ9tgwWkoJcwCalmv3MBAemtO4R6dah2HaKQqj8Zvp9sQDjvJ21+SPCBHPJDDk6QITekEV7gqCC19CpKAym9IMfckKv4olMBCeIrWwVEfvkshzQekO9r9P1/ALk+IG1eSPCDiCJfyG+FyU+A6ZCa/piZDinpz7LpkCv5gdkAEshP5emQhv7onw6pGeULyZCSUYiRDAmMkpJkCKs4JhFSq8p8hJBSVbAkhARV6ZUQoisik0FqXTmcDHLVFfbJIEFXoiiCNMpiSxGkVJaNiiBBWQArgTTaUl4JpNQWJUsgQVteXQg+AKkLxQWFGKW+5J2+eVp4S168X3CF1CltCKdTJ8lb84YK2bUBO+wZW0Pqv9nk4tKu49N45NJC5dMM5tLW5tOg59Jq6NM06dL+abFXwr/RkuvTXJwae1abtE/Dt0/ruksTvs84AZ/BCC4jHnyGVfiM3VBQFANEXEah+Ax18RlP4zNox2dkkM/wI58xTn8yDCXGYCDV3W5RGSajtXyGhG1jbpbjzpwGt/0MJft8jqC7iUbQ/QZaxdnKqcIftwAAAABJRU5ErkJggg==';
+module.exports = {
+ base64Arrow: base64Arrow,
+ base64Flower: base64Flower,
+ base64Empty: base64Empty,
+ base64BackToTop: base64BackToTop
+}
diff --git a/uni_modules/z-paging/components/z-paging/z-paging.vue b/uni_modules/z-paging/components/z-paging/z-paging.vue
new file mode 100644
index 0000000..a6da545
--- /dev/null
+++ b/uni_modules/z-paging/components/z-paging/z-paging.vue
@@ -0,0 +1,462 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @touchstart="_refresherTouchstart" @touchmove="_refresherTouchmove" @touchend="_refresherTouchend" @touchcancel="_refresherTouchend"
+
+
+ @touchstart="pagingWxs.touchstart" @touchmove="pagingWxs.touchmove" @touchend="pagingWxs.touchend" @touchcancel="pagingWxs.touchend"
+ @mousedown="pagingWxs.mousedown" @mousemove="pagingWxs.mousemove" @mouseup="pagingWxs.mouseup" @mouseleave="pagingWxs.mouseleave"
+
+ >
+
+
+ :change:prop="pagingWxs.propObserver" :prop="wxsPropType"
+ :data-refresherThreshold="finalRefresherThreshold" :data-isIos="isIos" :data-isIos13="isIos13"
+ :data-loading="loading" :data-useChatRecordMode="useChatRecordMode"
+ :data-refresherEnabled="refresherEnabled" :data-useCustomRefresher="useCustomRefresher" :data-pageScrollTop="wxsPageScrollTop"
+ :data-scrollTop="wxsScrollTop" :data-refresherMaxAngle="refresherMaxAngle"
+ :data-refresherAecc="refresherAngleEnableChangeContinued" :data-usePageScroll="usePageScroll"
+ :data-oldIsTouchmoving="isTouchmoving" :data-refresherOutRate="finalRefresherOutRate"
+
+
+ :change:renderPropScrollTop="pagingRenderjs.renderPropScrollTopChange" :renderPropScrollTop="renderPropScrollTop"
+ :change:renderPropUsePageScroll="pagingRenderjs.renderPropUsePageScrollChange" :renderPropUsePageScroll="renderPropUsePageScroll"
+
+ >
+
+
+
+
+
+ :refresherStatus="refresherStatus"
+
+ name="refresher" />
+
+
+
+
+
+
+
+ {{chatRecordLoadingMoreText}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{chatRecordLoadingMoreText}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-paging/package.json b/uni_modules/z-paging/package.json
new file mode 100644
index 0000000..daa9267
--- /dev/null
+++ b/uni_modules/z-paging/package.json
@@ -0,0 +1,80 @@
+{
+ "id": "z-paging",
+ "displayName": "【z-paging下拉刷新、上拉加载更多】超简单、低耦合!仅需两步轻松完成完整分页逻辑",
+ "version": "2.0.1",
+ "description": "【支持nvue,使用wxs+renderjs实现】全平台兼容,支持自定义下拉刷新、上拉加载更多,支持自动管理空数据图、点击返回顶部,支持聊天分页、本地分页,支持展示最后更新时间,支持国际化等等",
+ "keywords": [
+ "下拉刷新",
+ "上拉加载",
+ "分页器",
+ "nvue",
+ "wxs"
+],
+ "repository": "https://github.com/SmileZXLee/uni-z-paging",
+ "engines": {
+ "HBuilderX": "^3.0.7"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": "393727164"
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/z-paging/readme.md b/uni_modules/z-paging/readme.md
new file mode 100644
index 0000000..eb3305f
--- /dev/null
+++ b/uni_modules/z-paging/readme.md
@@ -0,0 +1,237 @@
+# z-paging
+
+
+***
+
+## 【注意】由V1.9.0起,fixed属性默认值为true,z-paging默认会铺满屏幕。老项目更新请注意,使用侧滑滚动切换选项卡或需要局部使用z-paging请设置:fixed="false"。如果您希望fixed属性默认为false,请参考文档:z-paging.com,将fixed默认值设置为false。
+***
+
+> 【uni-app自动分页器】超简单,低耦合!仅需两步轻松完成完整分页逻辑(下拉刷新、上拉加载更多),分页全自动处理。支持自定义加载更多的文字或整个view,自定义下拉刷新样式,自动管理空数据view,支持吸顶效果,支持国际化等。
+
+### API文档地址:[http://z-paging.com](http://z-paging.com)
+### 备用API文档地址:[https://www.kancloud.cn/zxlee/z-paging/content](https://www.kancloud.cn/zxlee/z-paging/content)
+
+### 功能&特点
+
+* 【配置简单】仅需两步(绑定网络请求方法、绑定分页结果数组)轻松完成完整下拉刷新,上拉加载更多功能。
+* 【低耦合,低侵入】分页自动管理。在page中无需处理任何分页相关逻辑,无需在data中定义任何分页相关变量,全由z-paging内部处理。
+* 【超灵活,支持各种类型自定义】支持自定义下拉刷新,自定义上拉加载更多,自带自定义下拉刷新效果,及其他数十种自定义属性。
+* 【功能丰富】支持国际化,支持自定义且自动管理空数据图,支持主题模式切换,支持本地分页,支持聊天分页模式,支持展示最后更新时间,支持吸顶效果,支持内部scroll-view滚动与页面滚动,支持一键滚动到顶部等诸多功能。
+* 【多平台兼容,细致,流畅】支持nvue,支持h5、app及各家小程序;在app-vue、h5、微信小程序、QQ小程序上使用wxs实现下拉刷新,大幅提升性能。多处细节优化,给您精致流畅的体验。
+
+### 反馈qq群(点击加群):[790460711](https://jq.qq.com/?_wv=1027&k=vU2fKZZH)
+
+
+#### 关于自动引入组件
+
+> `z-paging` 支持[easycom组件规范](https://uniapp.dcloud.io/component/README?id=easycom组件规范),无需引用和注册组件即可直接使用,在正在运行的项目中导入`z-paging`可能会提示:`Unknown custom element: - did you register the component corrently?... `,此时需要重新运行项目即可。
+
+### 预览
+
+***
+
+| 自定义下拉刷新效果+分页演示 | 吸顶效果+分页演示 |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+|  |  |
+
+| 滑动切换选项卡+分页演示 | 聊天记录模式+分页演示 |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+|  |  |
+
+### 在线demo体验地址:
+
+* [http://www.zxlee.cn/github/uni-z-paging/demo/index.html](http://www.zxlee.cn/github/uni-z-paging/demo/index.html)
+
+| 扫码体验 |
+| ------------------------------------------------------------ |
+|  |
+
+### 此组件已支持`uni_modules`,下载完整示例时组件在`uni_modules`目录下。
+
+## 基本使用
+
+* ①在`` 中使用@query绑定js中分页请求的方法(`z-paging`会将计算好的pageNo和pageSize两个参数传递到此方法中),然后通过` v-model`绑定列表for循环的list。
+* ②在请求结果回调中,通过调用`z-paging`的`complete()`方法,将请求返回的数组传递给`z-paging`处理,如:`this.$refs.paging.complete(服务器返回的数组);`;若请求失败,调用:`this.$refs.paging.complete(false);`即可。
+* 当tab切换或搜索时,可以通过`this.$refs.paging.reload()`刷新整个列表。
+* 在nvue中,z-paging中插入的列表item(z-paging的直接子view)必须是cell,必须使用cell包住,因为在nvue中,z-paging使用的是nvue的list组件,具体请查阅demo中的`common-demo-n.vue`示例。
+
+```html
+
+
+
+
+
+
+ {{item.title}}
+
+
+
+
+
+
+
+
+
+```
+
+## 设置自定义emptyView组件示例
+
+* 设置自定义emptyView组件,非必须。空数据时会自动展示空数据组件,不需要自己处理
+
+```html
+
+
+
+
+
+ {{item.title}}
+
+
+
+```
+
+## 自定义加载更多各个状态的描述文字示例
+
+* 以修改【没有更多了】状态描述文字为例(将默认的"没有更多了"修改为"我也是有底线的!")
+
+```html
+
+
+
+
+ {{item.title}}
+
+
+
+```
+
+## 自定义下拉刷新view示例
+
+* `use-custom-refresher`需要设置为true(默认为true),此时将不会使用uni自带的下拉刷新,转为使用z-paging自定义的下拉刷新,通过slot可以插入开发者自定义的下拉刷新view。
+
+```html
+
+
+
+
+
+
+
+
+ {{item.title}}
+ {{item.detail}}
+
+
+
+
+```
+
+## 自定义加载更多各个状态的描述view示例
+
+* 以修改【没有更多了】状态描述view为例
+
+```html
+
+
+
+ {{item.title}}
+
+
+ 这是完全自定义的没有更多数据view
+
+```
+
+## 使用页面滚动示例
+
+```html
+
+
+
+
+
+
+
+
+
+
+ {{item.title}}
+ {{item.detail}}
+
+
+
+
+
+
+
+
+```
+
+## i18n示例
+
+* 请参照demo:`i18n-demo.vue`
+
+## 性能与建议
+
+| | 使用内置scroll-view滚动 | 使用页面滚动 | 使用nvue |
+| :--------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
+| **说明** | 默认模式,`z-paging`需要有确定的高度,下拉刷新与上拉加载更多由`z-paging`内部处理,配置简单。 | `use-page-scroll`设置为true时生效,使用页面滚动而非内置scroll-view滚动,无需固定`z-paging`的高度,但需要在页面滚动到底部时调用`z-paging`的`doLoadMore()`方法。
当使用页面的下拉刷新时,需要引入mixin(可全局引入),具体可参见demo。 | 创建nvue页面并引入`z-paging`且运行在APP上生效,`z-paging`将使用nvue独有的``和``代替原有的scroll-view和自定义的下拉刷新,可大幅提升性能。 |
+| **性能** | 不佳 | 一般 | 优 |
+| **优缺点** | 【优点】配置简单、耦合度低。普通的简单列表不会有明显卡顿。
【缺点】需要固定`z-paging`高度,超出页面部分渲染的资源无法自动回收,当列表item比较复杂或数据量过多时,可能会造成明显卡顿。 | 【优点】性能优于使用内置的scroll-view滚动,超出页面部分渲染的资源会自动回收,能适应绝大多数列表滚动的情况,即使列表item比较复杂,一般也不会感知到卡顿。
【缺点】配置略麻烦,耦合度较高。 | 【优点】原生渲染,极致性能,``组件在不可见部分的渲染资源回收有特殊的优化处理,``组件是app端独有的下拉刷新组件,性能远超普通vue页面中的自定义下拉刷新。
【缺点】仅App端支持,nvue页面写法不如vue页面方便,在`z-paging`中一些配置和方法在nvue中不支持,且nvue页面中支持的第三方组件也比vue页面少。 |
+
+#### 【总结】
+
+* 如果项目列表item比较简单,分页数据量不是特别多,建议使用默认的「内置scroll-view滚动」。
+* 如果项目列表item比较复杂,数据量多,且使用「内置scroll-view滚动」时卡顿明显,建议使用页面滚动。
+* 如果是App项目,且对性能和细节有较高要求,建议在nvue中使用`z-paging`。
+
+## 注意事项及常见问题
+
+* 【若无法下拉刷新】请确认要在@query所绑定的方法中调用`this.$refs.paging.complete()`,无论是否需要网络请求都要调用,只有告知z-paging刷新状态结束了,才可以开始下次的下拉刷新。
+
+* 【使用内置scroll-view滚动时】z-paging必须有确定的高度!否则上拉加载更多将无法触发,建议设置`:fixed=true`即可不设置高度!!(不希望跟着滚动的view可以设置`slot="top"`)。
+
+* 【使用页面滚动时】使用z-paging内置的scroll-view滚动性能不及使用页面的滚动。若您要使用页面的滚动,请勿固定z-paging的高度,并且必须设置`use-page-scroll`为true,否则将导致页面无法滚动(不希望跟着滚动的view可以设置`slot="top"`)。
+
+* 【使用页面滚动时】必须引入mixin(可全局引入)(具体可参照demo中的`page-default-demo.vue`文件)或在页面的`onReachBottom`事件中调用`this.$refs.paging.doLoadMore()`且在`onPageScroll(e)`事件中调用`this.$refs.paging.updatePageScrollTop(e.scrollTop)`。(具体可参照demo中的`page-default-demo.vue`文件)
+
+* 【出现实际上有更多数据,而显示没有更多数据时】默认的pageSize(每页显示数量)为10,如果您服务端不需要传pageSize(例如有默认的pageSize:8),则您需要将默认的pageSize改成您与后端约定好的(8),若没有修改,则z-paging会认为传给服务端的pageSize是10,而服务端只返回了8条,因此会直接判定为没有更多数据。
+
+* 【若页面无法滚动】请检查z-paging是否有固定的高度;若您想使用页面滚动而非z-paging内置的scroll-view的滚动,请设置`use-page-scroll`为true。
+
+* 【关于自定义导航栏】若设置了`:fixed=true`,则必须将自定义导航栏放在z-paging标签中且添加slot="top",如:``,如果有多个需要固定顶部的元素,则书写`需要固定顶部的元素`。
+
+### API文档地址:[http://z-paging.com](http://z-paging.com)
+### 备用API文档地址:[https://www.kancloud.cn/zxlee/z-paging/content](https://www.kancloud.cn/zxlee/z-paging/content)
\ No newline at end of file
diff --git a/uni_modules/z-popup/changelog.md b/uni_modules/z-popup/changelog.md
new file mode 100644
index 0000000..5c2c053
--- /dev/null
+++ b/uni_modules/z-popup/changelog.md
@@ -0,0 +1,4 @@
+## 1.0.1(2021-06-24)
+修复微信小程序不显示问题
+## 1.0.0(2021-05-12)
+1. 支持uni_modules
diff --git a/uni_modules/z-popup/components/z-popup/z-popup.vue b/uni_modules/z-popup/components/z-popup/z-popup.vue
new file mode 100644
index 0000000..17058f8
--- /dev/null
+++ b/uni_modules/z-popup/components/z-popup/z-popup.vue
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
diff --git a/uni_modules/z-popup/package.json b/uni_modules/z-popup/package.json
new file mode 100644
index 0000000..488941c
--- /dev/null
+++ b/uni_modules/z-popup/package.json
@@ -0,0 +1,79 @@
+{
+ "id": "z-popup",
+ "displayName": "弹窗,上弹窗,下弹窗,中间弹窗",
+ "version": "1.0.1",
+ "description": "弹窗,上弹窗,下弹窗,中间弹窗",
+ "keywords": [
+ "弹窗",
+ "下弹窗",
+ "中间弹窗",
+ "上弹窗"
+],
+ "repository": "https://github.com/zhouwei1994/uni-app-demo",
+ "engines": {
+ "HBuilderX": "^3.0.7"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": "465081029"
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/z-popup/readme.md b/uni_modules/z-popup/readme.md
new file mode 100644
index 0000000..4427b40
--- /dev/null
+++ b/uni_modules/z-popup/readme.md
@@ -0,0 +1,51 @@
+# 弹窗,上弹窗,下弹窗,中间弹窗
+
+弹窗,上弹窗,下弹窗,中间弹窗
+
+| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群")` |
+| ----------------------------|--------------------------- |
+|||
+| QQ群号:607391225 |微信号:zhou0612wei|
+
+### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
+
+### 案例一
+```
+
+
+
+
+
+// js
+methods: {
+ onChange(e){
+ if(e){
+ uni.showToast({
+ title:"打开了弹窗",
+ icon:"none"
+ });
+ }else {
+ uni.showToast({
+ title:"关闭了弹窗",
+ icon:"none"
+ });
+ }
+ }
+},
+```
+
+### 属性
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
+| value | Boolean | false | 控制弹窗是否打开 |
+| hideOnBlur | Boolean | true | 点击遮罩层关闭弹窗|
+| scroll | Boolean | true | 禁止页面滚动(H5生效) |
+| type | String | bottom | 弹窗方位bottom 靠下, center 居中, top 靠上 |
+| offset | Number | 0 | type=bottom和type=top的时候设置这个数据弹窗会朝相反的方向偏移 |
+| zIndex | Number | 500 | 设置弹窗的层级, 普通vue页面有效 |
\ No newline at end of file
diff --git a/uni_modules/z-prompt/changelog.md b/uni_modules/z-prompt/changelog.md
new file mode 100644
index 0000000..96b273b
--- /dev/null
+++ b/uni_modules/z-prompt/changelog.md
@@ -0,0 +1,2 @@
+## 1.0.0(2021-05-12)
+1. 支持uni_modules
diff --git a/uni_modules/z-prompt/components/z-prompt/z-prompt.vue b/uni_modules/z-prompt/components/z-prompt/z-prompt.vue
new file mode 100644
index 0000000..ae2e7a6
--- /dev/null
+++ b/uni_modules/z-prompt/components/z-prompt/z-prompt.vue
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-prompt/package.json b/uni_modules/z-prompt/package.json
new file mode 100644
index 0000000..fa0681c
--- /dev/null
+++ b/uni_modules/z-prompt/package.json
@@ -0,0 +1,77 @@
+{
+ "id": "z-prompt",
+ "displayName": "弹出输入框",
+ "version": "1.0.0",
+ "description": "弹出输入框",
+ "keywords": [
+ "弹出输入框",
+ "输入框"
+],
+ "repository": "https://github.com/zhouwei1994/uni-app-demo",
+ "engines": {
+ "HBuilderX": "^3.0.0"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": "465081029"
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/z-prompt/readme.md b/uni_modules/z-prompt/readme.md
new file mode 100644
index 0000000..6705de3
--- /dev/null
+++ b/uni_modules/z-prompt/readme.md
@@ -0,0 +1,65 @@
+# 弹出输入框
+
+弹出输入框
+
+| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群")` |
+| ----------------------------|--------------------------- |
+|||
+| QQ群号:607391225 |微信号:zhou0612wei|
+
+### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
+
+### 案例一
+```
+
+// js
+methods: {
+ onChange(e){
+ if(/^1\d{10}$/.test(e.value)){
+ uni.showToast({
+ title: '请输入正确的手机',
+ icon: 'none'
+ });
+ return;
+ }
+ e.close();
+ }
+},
+```
+### 案例二
+```
+
+
+
+// js
+methods: {
+ onChange(e){
+ if(/^1\d{10}$/.test(e.value)){
+ uni.showToast({
+ title: '请输入正确的手机',
+ icon: 'none'
+ });
+ return;
+ }
+ e.close();
+ }
+},
+```
+
+### 属性
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
+| value | Boolean | false | 控制弹窗是否打开 |
+| options | Object | 有 | 弹窗配置参数 请看下面options属性 |
+
+### options属性
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
+| title | String | 操作 | 弹窗标题 |
+| tips | String | 请输入 | 输入框上面的提示 |
+| confirmText | String | 请输入 | 确认按钮的弹窗 |
+| placeholder | String | | 输入框的提示 |
+| password | Boolean | false | 是否密码输入框 |
+| inputType | String | text | 输入框类型 |
+| maxlength | Number | 140 | 输入框最大可输入长度 |
+| confirmType | String | done | 键盘提交按钮配置(值请参考官方) |
\ No newline at end of file
diff --git a/uni_modules/z-swipe-action/README.md b/uni_modules/z-swipe-action/README.md
new file mode 100644
index 0000000..c6bc59f
--- /dev/null
+++ b/uni_modules/z-swipe-action/README.md
@@ -0,0 +1,95 @@
+# swipe-action 滑动操作
+### `觉得不错,给个5星好评吧`
+
+| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群")` |
+| ----------------------------|--------------------------- |
+|||
+| QQ群号:607391225 |微信号:zhou0612wei|
+
+### [点击跳转-本插件示例](https://ext.dcloud.net.cn/plugin?id=2009)
+### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
+
+### 使用时不懂的请看上面链接的插件示例
+
+### 示例代码
+```
+
+
+ 滑动
+ 禁止滑动
+
+
+ 滑动列表{{ index + 1 }}
+
+
+
+
+
+```
+
+
+### 使用说明
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------|--------------- | ------------- | -------------------|
+| options | Array | [] | 查看options参数说明 |
+| disabled | Boolean | false | 是否禁止滑动 |
+| show | Boolean | false | 是否打开 |
+| autoClose | Boolean | true | 点击后是否自动关闭 |
+| index | Number | 0 | 循环的时候的索引值,通过@button传递出去 |
+
+### options参数说明
+| 名称 | 类型 | 描述 |
+| ------------------------|--------------- | -------------------|
+| text | String | 按钮名称 |
+| style | Object | 按钮样式 |
+| style.backgroundColor | String | 按钮背景颜色 |
+| style.fontSize | String | 按钮字体大小 |
+| style.color | String | 按钮字体颜色 |
+
+### 事件
+| 名称 | 描述 |
+| -----------------| --------------------------|
+| button | 左滑按钮点击事件 |
+
+```
+按钮左滑按钮点击事件返回值
+{
+ content: "点击按钮的options参数",
+ index: "循环的时候的索引值",
+ buttonIndex: "点击按钮的索引值"
+}
+```
\ No newline at end of file
diff --git a/uni_modules/z-swipe-action/changelog.md b/uni_modules/z-swipe-action/changelog.md
new file mode 100644
index 0000000..4fbb285
--- /dev/null
+++ b/uni_modules/z-swipe-action/changelog.md
@@ -0,0 +1,2 @@
+## 2.0.5(2021-05-12)
+1. 支持uni_modules
diff --git a/uni_modules/z-swipe-action/components/z-swipe-action/z-swipe-action.vue b/uni_modules/z-swipe-action/components/z-swipe-action/z-swipe-action.vue
new file mode 100644
index 0000000..f2d05c2
--- /dev/null
+++ b/uni_modules/z-swipe-action/components/z-swipe-action/z-swipe-action.vue
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-swipe-action/index.vue b/uni_modules/z-swipe-action/index.vue
new file mode 100644
index 0000000..f2d05c2
--- /dev/null
+++ b/uni_modules/z-swipe-action/index.vue
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
diff --git a/uni_modules/z-swipe-action/package.json b/uni_modules/z-swipe-action/package.json
new file mode 100644
index 0000000..f6bb779
--- /dev/null
+++ b/uni_modules/z-swipe-action/package.json
@@ -0,0 +1,80 @@
+{
+ "id": "z-swipe-action",
+ "displayName": "swipe-action 滑动操作",
+ "version": "2.0.5",
+ "description": "swipe-action 滑动操作",
+ "keywords": [
+ "滑动",
+ "滑动操作",
+ "action",
+ "左滑",
+ "swipe"
+],
+ "repository": "https://github.com/zhouwei1994/uni-app-demo",
+ "engines": {
+ "HBuilderX": "^3.0.0"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": "465081029"
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/zhouWei-APPUpdate/js_sdk/appUpdate.js b/uni_modules/zhouWei-APPUpdate/js_sdk/appUpdate.js
index c611e9d..e2573d2 100644
--- a/uni_modules/zhouWei-APPUpdate/js_sdk/appUpdate.js
+++ b/uni_modules/zhouWei-APPUpdate/js_sdk/appUpdate.js
@@ -441,8 +441,8 @@ function updatePopup(data, callback) {
});
}
// 显示弹窗
- maskLayer.show();
- popupView.show();
+ // maskLayer.show();
+ // popupView.show();
}
// 文件下载的弹窗绘图
function downloadPopupDrawing(data){
diff --git a/uni_modules/zhouWei-APPUpdate/readme.md b/uni_modules/zhouWei-APPUpdate/readme.md
index 953f1b0..c6b8d86 100644
--- a/uni_modules/zhouWei-APPUpdate/readme.md
+++ b/uni_modules/zhouWei-APPUpdate/readme.md
@@ -41,8 +41,12 @@
### 第一步`关键`配置APP更新接口(可以参考上面的示例)
在项目目录下`config/componentConfig.js`里面如下配置
```
-// 此方法是接口请求方法
-import $http from '@/config/requestConfig'
+/**** 此文件说明请看注释 *****/
+// 可以用自己项目的请求方法
+// 请求配置说明:https://ext.dcloud.net.cn/plugin?id=822
+import $http from '@/config/requestConfig';
+/**** 结束 *****/
+const platform = uni.getSystemInfoSync().platform;
export default {
// 发起ajax请求获取服务端版本号
getServerNo: (version, isPrompt = false, callback) => {
@@ -127,9 +131,6 @@ onLaunch: function(e) {
```
-### 修改弹窗的主题色或弹窗图标
-在`APPUpdate/index.js`里面上面`$mainColor`常量中定义主题颜色,`$iconUrl`常量中定义图标地址
-
### 检查APP是否有新版本(一般在设置页面使用)
```
// #ifdef APP-PLUS
diff --git a/uni_modules/zhouWei-APPshare/static/fengziIcon.jpg b/uni_modules/zhouWei-APPshare/static/fengziIcon.jpg
new file mode 100644
index 0000000..cc75abf
Binary files /dev/null and b/uni_modules/zhouWei-APPshare/static/fengziIcon.jpg differ
diff --git a/uni_modules/zhouWei-request/js_sdk/request/core/utils.js b/uni_modules/zhouWei-request/js_sdk/request/core/utils.js
index 65e4a70..aa2a044 100644
--- a/uni_modules/zhouWei-request/js_sdk/request/core/utils.js
+++ b/uni_modules/zhouWei-request/js_sdk/request/core/utils.js
@@ -36,6 +36,19 @@ export const dispatchRequest = function(requestInfo) {
errMsg: "请求超时,请重新尝试",
statusCode: 0,
});
+ console.log('requestInfo.url',requestInfo.url);
+ if(!requestInfo.url.includes('sociology/course/saveCoursePosition')){
+ uni.showToast({
+ title:'请求超时,请重新尝试',
+ icon:'none',
+ duration: 5000
+ })
+ }
+
+ // console.log('');
+ // uni.navigateTo({
+ // url: "/pages/user/login"
+ // });
} else {
reject(err);
}
diff --git a/uni_modules/zhouWei-request/js_sdk/request/upload/utils.js b/uni_modules/zhouWei-request/js_sdk/request/upload/utils.js
index 10eaeda..0681b5d 100644
--- a/uni_modules/zhouWei-request/js_sdk/request/upload/utils.js
+++ b/uni_modules/zhouWei-request/js_sdk/request/upload/utils.js
@@ -194,16 +194,6 @@ export const aliUpload = function(requestInfo, getAliToken) {
let nameArr = item.path.split(".");
updateUrl += "." + nameArr[nameArr.length - 1];
}
- console.log("----------111", {
- url: aliRes.visitPrefix, // 开发者服务器的URL。
- filePath: item.path,
- name: 'file', // 必须填file。
- formData: {
- key: updateUrl,
- policy: aliyunOssKey.policy,
- OSSAccessKeyId: aliyunOssKey.accessKeyId,
- signature: aliyunOssKey.signature,
- }});
uni.uploadFile({
url: aliRes.visitPrefix, // 开发者服务器的URL。
filePath: item.path,
@@ -228,12 +218,10 @@ export const aliUpload = function(requestInfo, getAliToken) {
resolve(fileList);
}
} else {
- console.log("----失败", res);
reject(res);
}
},
fail: err => {
- console.log("----失败", err);
reject(err);
}
});