Browse Source

增加z-paging组件 解决包月无法下拉刷新问题

CarlYang 3 years ago
parent
commit
a249a98811
26 changed files with 5322 additions and 280 deletions
  1. 13 4
      pages.json
  2. 4 1
      pages/center/monthly/monthly.scss
  3. 80 132
      pages/center/monthly/monthly.vue
  4. 116 85
      pages/center/monthly/monthly1.vue
  5. 10 5
      pages/favourableActivity/favourableActivity.vue
  6. 1 1
      pages/index/index.vue
  7. 83 52
      pages/myCars/myCars.vue
  8. 38 0
      uni_modules/z-paging/changelog.md
  9. 170 0
      uni_modules/z-paging/components/z-paging-empty-view/z-paging-empty-view.vue
  10. 86 0
      uni_modules/z-paging/components/z-paging-swiper-item/z-paging-swiper-item.vue
  11. 123 0
      uni_modules/z-paging/components/z-paging-swiper/z-paging-swiper.vue
  12. 158 0
      uni_modules/z-paging/components/z-paging/components/z-paging-load-more.vue
  13. 259 0
      uni_modules/z-paging/components/z-paging/components/z-paging-refresh.vue
  14. 157 0
      uni_modules/z-paging/components/z-paging/css/z-paging-main.css
  15. 38 0
      uni_modules/z-paging/components/z-paging/css/z-paging-static.css
  16. 32 0
      uni_modules/z-paging/components/z-paging/js/z-paging-config.js
  17. 150 0
      uni_modules/z-paging/components/z-paging/js/z-paging-i18n.js
  18. 2617 0
      uni_modules/z-paging/components/z-paging/js/z-paging-main.js
  19. 36 0
      uni_modules/z-paging/components/z-paging/js/z-paging-mixin.js
  20. 25 0
      uni_modules/z-paging/components/z-paging/js/z-paging-static.js
  21. 179 0
      uni_modules/z-paging/components/z-paging/js/z-paging-utils.js
  22. 60 0
      uni_modules/z-paging/components/z-paging/wxs/z-paging-renderjs.js
  23. 335 0
      uni_modules/z-paging/components/z-paging/wxs/z-paging-wxs.wxs
  24. 239 0
      uni_modules/z-paging/components/z-paging/z-paging.vue
  25. 80 0
      uni_modules/z-paging/package.json
  26. 233 0
      uni_modules/z-paging/readme.md

+ 13 - 4
pages.json

@@ -134,16 +134,25 @@
             
         }
         ,{
-            "path" : "pages/center/monthly/monthly",
+            "path" : "pages/center/monthly/monthly1",
             "style" :                                                                                    
             {
-				// "navigationStyle":"custom",
                 "navigationBarTitleText": "我的包月",
                 "navigationBarBackgroundColor": "#008CFF",
-                "navigationBarTextStyle": "white"
+                "navigationBarTextStyle": "white",
+				"enablePullDownRefresh": false
             }
-            
         },
+		{
+		    "path" : "pages/center/monthly/monthly",
+		    "style" :                                                                                    
+		    {
+		        "navigationBarTitleText": "我的包月",
+		        "navigationBarBackgroundColor": "#008CFF",
+		        "navigationBarTextStyle": "white",
+				"enablePullDownRefresh": false
+		    }
+		},
 		{
 		    "path" : "pages/payLists/pay",
 		    "style" :                                                                                    

+ 4 - 1
pages/center/monthly/monthly.scss

@@ -1,10 +1,13 @@
-page{
+page {
 	background-color: #F6F6FF
 }
 .monthly {
 	padding: 37rpx 40rpx;
 	height: calc(100vh - 88rpx);
 	overflow-y: scroll;
+	.paging {
+		padding: 37rpx 40rpx;
+	}
 	.monthly-list {
 		.monthly-list-item {
 			overflow: hidden;

+ 80 - 132
pages/center/monthly/monthly.vue

@@ -1,31 +1,27 @@
 <template>
 	<!-- 包月 -->
 	<view class="monthly">
-		<!-- <u-navbar
-		 title-color="#fff" 
-		 :custom-back="customBack" 
-		 :border-bottom="false" 
-		 back-icon-color="#CCE8FF" 
-		 :background="{background: '#008CFF' }" title="我的包月"></u-navbar> -->
-		<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
+		<z-paging class="paging" ref="paging" v-model="dataList" @query="queryList">
 			<view class="monthly-list">
-				<view class="monthly-list-item" :index="index" v-for="(monthlyItem, index) in  monthlyList" :key="index">
+				<view class="monthly-list-item" v-for="(monthlyItem, index) in  dataList" :key="monthlyItem.id">
 					<view class="monthly-list-item-top">
 						<view class="mlit-left">
 							<view>{{monthlyItem.vehicleNo}}</view>
 							<view>{{monthlyItem.roadName}}</view>
 						</view>
 						<view class="mlit-right u-flex">
-						<view class="mlit-right-item fee-status" v-if="monthlyItem.feeStatus === 0">未缴费</view>
-						<view class="mlit-right-item fee-status" v-if="monthlyItem.feeStatus === 1">已缴费</view>
-						<view class="mlit-right-item" v-if="monthlyItem.energyType === 1">汽油车</view>
-						<view class="mlit-right-item" v-if="monthlyItem.energyType === 2">新能源</view>
+							<view class="mlit-right-item fee-status" v-if="monthlyItem.feeStatus === 0">未缴费</view>
+							<view class="mlit-right-item fee-status" v-if="monthlyItem.feeStatus === 1">已缴费</view>
+							<view class="mlit-right-item" v-if="monthlyItem.energyType === 1">汽油车</view>
+							<view class="mlit-right-item" v-if="monthlyItem.energyType === 2">新能源</view>
 						</view>
 					</view>
-					<view class="monthly-list-item-bottom" >
+					<view class="monthly-list-item-bottom">
 						<view class="mlib-item">
 							<view>有效期限</view>:
-							<view>{{(monthlyItem.beginTime.split('-')).join('.')}}-{{(monthlyItem.endTime.split('-')).join('.')}}</view>
+							<view>
+								{{(monthlyItem.beginTime.split('-')).join('.')}}-{{(monthlyItem.endTime.split('-')).join('.')}}
+							</view>
 						</view>
 						<view class="mlib-item">
 							<view>剩余天数</view>:
@@ -33,147 +29,99 @@
 						</view>
 					</view>
 					<view v-if="monthlyItem.feeStatus=='0'" class="button-wrap u-flex u-row-right">
-						<view class="tool-btn" 
-						:class="{'tool-btn-cancel':monthlyItem.feeStatus=='0'}" 
-						v-if="monthlyItem.feeStatus=='0'" 
-						@click="cancelMonth(monthlyItem.monthId)">取消订单</view>
+						<view class="tool-btn" :class="{'tool-btn-cancel': monthlyItem.feeStatus=='0'}"
+							v-if="monthlyItem.feeStatus=='0'" @click="cancelMonth(monthlyItem.monthId)">取消订单</view>
 					</view>
-					<view v-else-if="monthlyItem.feeStatus == 1 && monthlyItem.surplusDays > 2" class="button-wrap u-flex u-row-right">
+					<view v-else-if="monthlyItem.feeStatus == 1 && monthlyItem.surplusDays > 2"
+						class="button-wrap u-flex u-row-right">
 						<view class="tool-btn">已缴费</view>
 					</view>
-					<view v-else-if="monthlyItem.feeStatus == 1 && monthlyItem.surplusDays < 3" class="button-wrap u-flex u-row-right">
+					<view v-else-if="monthlyItem.feeStatus == 1 && monthlyItem.surplusDays < 3"
+						class="button-wrap u-flex u-row-right">
 						<view class="tool-btn" @click="goRenewal(monthlyItem)">去续费</view>
 					</view>
 				</view>
 			</view>
-		</mescroll-body>
-		<u-modal v-model="canclShow" content="确认取消该订单?" @confirm="confirm" :show-cancel-button="true"></u-modal>
+		</z-paging>
+		<u-modal v-model="cancelShow" content="确认取消该订单?" @confirm="confirm" :show-cancel-button="true"></u-modal>
 		<u-toast ref="uToast" />
 	</view>
 </template>
 
 <script>
-	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
 	export default {
-		mixins: [MescrollMixin], // 使用mixin
 		data() {
 			return {
-				id:'',
-				canclShow: false,
-				monthlyList: [],
-				monthList:'',
-				beginTime:'',
-				endTime:'',
-				time:[],
-			}
-		},
-		onShow() {
-			// onShow 刷新数据
-			if(this.mescroll){
-				this.mescroll.triggerDownScroll();
+				id: '', // 当前选中的条目id
+				cancelShow: false,
+				dataList: [],
+				pageSize: 10,
+				pageNo: 1
 			}
 		},
 		methods: {
-			customBack(){
+			customBack() {
 				this.$u.route({
-					type:'switchTab',
+					type: 'switchTab',
 					url: 'pages/center/index'
 				});
 			},
-			/*下拉刷新的回调*/
-			downCallback(){
-				// 第2种: 下拉刷新和上拉加载调同样的接口, 则不用第1种, 直接mescroll.resetUpScroll()即可
-				this.mescroll.resetUpScroll(); // 重置列表为第一页 (自动执行 page.num=1, 再触发upCallback方法 )
-			},
-			/*上拉加载的回调*/
-			upCallback(page) {
-				let pageNum = page.num; // 页码, 默认从1开始
-				let pageSize = page.size; // 页长, 默认每页10条
-				// this.getMessageList()
-				this.$u.api.getMonthList({pageSize:pageSize ,pageNum: pageNum})
-				.then(res=>{
-					if(res.code == 200){
-					console.log('res',res)
-					// 接口返回的当前页数据列表 (数组)
-					let curPageData = res.data.rows;
-					// 接口返回的当前页数据长度 (如列表有26个数据,当前页返回8个,则curPageLen=8)
-					let curPageLen = curPageData.length; 
-					// 接口返回的总页数 (如列表有26个数据,每页10条,共3页; 则totalPage=3)
-					let totalPage = res.data.pages; 
-					// 接口返回的总数据量(如列表有26个数据,每页10条,共3页; 则totalSize=26)
-					let totalSize = res.data.total; 
-					// 接口返回的是否有下一页 (true/false)
-					// let hasNext = Number(res.data.page) < Number(res.data.pages); 
-					
-					//设置列表数据
-					if(page.num == 1) this.monthlyList = []; //如果是第一页需手动置空列表
-					this.monthlyList = this.monthlyList.concat(curPageData); //追加新数据
-					
-					// 请求成功,隐藏加载状态
-					//方法一(推荐): 后台接口有返回列表的总页数 totalPage
-					this.mescroll.endByPage(curPageLen, totalPage); 
-					setTimeout(()=>{
-						this.mescroll.endSuccess(curPageLen)
-					},20)
-					this.monthList=[],
-					res.data.rows.forEach(item => {
-						const obj = {
-							beginTime: item.beginTime,
-							endTime: item.endTime,
+			// 下拉刷新操作
+			queryList(pageNo, pageSize) {
+				console.log(pageNo)
+				console.log(pageSize)
+				this.$u.api.getMonthList({
+						pageSize: pageSize,
+						pageNum: pageNo,
+					})
+					.then(res => {
+						if (res.code === 200) {
+							this.pageNo = pageNo
+							this.pageSize = pageSize
+							this.$refs.paging.complete(res.data.rows);
+						} else {
+							this.$refs.uToast.show({
+								title: res.msg,
+								type: 'error',
+							});
 						}
-						this.monthList.push(obj)
-						// console.log(obj)
-					});
-					this.time = this.monthList[0]
-					let Date1 = this.time.beginTime;
-					let Date2 = this.time.endTime;
-					// Date1 = Date1.valueOf() + 24 * 60 * 60 * 1000
-					Date1 = new Date(Date1)
-					const year = Date1.getFullYear()
-					const month = Date1.getMonth()+1
-					const day = Date1.getDate()
-					Date2 = new Date(Date2)
-					const year2 = Date2.getFullYear()
-					const month2 = Date2.getMonth()+1
-					const day2 = Date2.getDate()
-					this.beginTime = year + '.' + month + '.' + day
-					console.log(this.beginTime)
-					this.endTime = year2 + '.' + month2 + '.' + day2
-					}else{
-						this.mescroll.endErr()
-					}
-				}).catch(err=>{
-					// console.log('err',err);
-					// this.$refs.uToast.show({
-					// 	title: err.msg,
-					// 	type: 'error',
-					// });
-				});
-				
+					})
+					.catch(err => {
+						this.$refs.uToast.show({
+							title: '操作失败',
+							type: 'error',
+						});
+					})
 			},
-			cancelMonth(monthId){
-				this.id=monthId;
-				this.canclShow = true;
-				console.log('monthId',monthId)
+			// 取消订单
+			cancelMonth(monthId) {
+				this.id = monthId;
+				this.cancelShow = true;
 			},
-			confirm(){
-				this.$u.api.cancelMonth({monthId: this.id})
-				.then(res=>{
-					if(res.code === 200){
-					this.$refs.uToast.show({ 
-						title: res.msg,
-						type: 'success',
-					});
-					this.downCallback()
-					}else{
-						
-					}
-				}).catch(err=>{
-					this.$refs.uToast.show({
-						title: err.msg,
-						type: 'error',
-					});
-				})
+			// 确认取消订单
+			confirm() {
+				this.$u.api.cancelMonth({
+						monthId: this.id,
+					})
+					.then(res => {
+						if (res.code === 200) {
+							this.$refs.uToast.show({
+								title: res.msg,
+								type: 'success',
+							});
+							this.queryList(this.pageNo, this.pageSize)
+						} else {
+							this.$refs.uToast.show({
+								title: res.msg,
+								type: 'error',
+							});
+						}
+					}).catch(err => {
+						this.$refs.uToast.show({
+							title: '操作失败',
+							type: 'error',
+						});
+					})
 			},
 			/**
 			 * 去续费
@@ -186,11 +134,11 @@
 						vehicleNo: item.vehicleNo
 					}
 				})
-			 }
+			}
 		}
 	}
 </script>
 
 <style lang="scss" scoped>
-@import './monthly.scss';
+	@import './monthly.scss';
 </style>

+ 116 - 85
pages/center/monthly/monthly1.vue

@@ -7,47 +7,47 @@
 		 :border-bottom="false" 
 		 back-icon-color="#CCE8FF" 
 		 :background="{background: '#008CFF' }" title="我的包月"></u-navbar> -->
-		 <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
-			 <view class="monthly-list">
-			 	<view class="monthly-list-item"  v-for="(monthlyItem, index) in  dataList" :key="monthlyItem.id">
-			 		<view class="monthly-list-item-top">
-			 			<view class="mlit-left">
-			 				<view>{{monthlyItem.vehicleNo}}</view>
-			 				<view>{{monthlyItem.roadName}}</view>
-			 			</view>
-			 			<view class="mlit-right u-flex">
-			 			<view class="mlit-right-item fee-status" v-if="monthlyItem.feeStatus === 0">未缴费</view>
-			 			<view class="mlit-right-item fee-status" v-if="monthlyItem.feeStatus === 1">已缴费</view>
-			 			<view class="mlit-right-item" v-if="monthlyItem.energyType === 1">汽油车</view>
-			 			<view class="mlit-right-item" v-if="monthlyItem.energyType === 2">新能源</view>
-			 			</view>
-			 		</view>
-			 		<view class="monthly-list-item-bottom" >
-			 			<view class="mlib-item">
-			 				<view>有效期限</view>:
-			 				<view>{{(monthlyItem.beginTime.split('-')).join('.')}}-{{(monthlyItem.endTime.split('-')).join('.')}}</view>
-			 			</view>
-			 			<view class="mlib-item">
-			 				<view>剩余天数</view>:
-			 				<view>{{monthlyItem.surplusDays}}天</view>
-			 			</view>
-			 		</view>
-			 		<view v-if="monthlyItem.feeStatus=='0'" class="button-wrap u-flex u-row-right">
-			 			<view class="tool-btn" 
-			 			:class="{'tool-btn-cancel':monthlyItem.feeStatus=='0'}" 
-			 			v-if="monthlyItem.feeStatus=='0'" 
-			 			@click="cancelMonth(monthlyItem.monthId)">取消订单</view>
-			 		</view>
-			 		<view v-else-if="monthlyItem.feeStatus == 1 && monthlyItem.surplusDays > 2" class="button-wrap u-flex u-row-right">
-			 			<view class="tool-btn">已缴费</view>
-			 		</view>
-			 		<view v-else-if="monthlyItem.feeStatus == 1 && monthlyItem.surplusDays < 3" class="button-wrap u-flex u-row-right">
-			 			<view class="tool-btn" @click="goRenewal(monthlyItem)">去续费</view>
-			 		</view>
-			 	</view>
-			 </view>
-		 </mescroll-body>
-		<u-modal v-model="cancelShow" content="确认取消该订单?" @confirm="confirm" :show-cancel-button="true"></u-modal>
+		<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
+			<view class="monthly-list">
+				<view class="monthly-list-item" :index="index" v-for="(monthlyItem, index) in  monthlyList" :key="index">
+					<view class="monthly-list-item-top">
+						<view class="mlit-left">
+							<view>{{monthlyItem.vehicleNo}}</view>
+							<view>{{monthlyItem.roadName}}</view>
+						</view>
+						<view class="mlit-right u-flex">
+						<view class="mlit-right-item fee-status" v-if="monthlyItem.feeStatus === 0">未缴费</view>
+						<view class="mlit-right-item fee-status" v-if="monthlyItem.feeStatus === 1">已缴费</view>
+						<view class="mlit-right-item" v-if="monthlyItem.energyType === 1">汽油车</view>
+						<view class="mlit-right-item" v-if="monthlyItem.energyType === 2">新能源</view>
+						</view>
+					</view>
+					<view class="monthly-list-item-bottom" >
+						<view class="mlib-item">
+							<view>有效期限</view>:
+							<view>{{(monthlyItem.beginTime.split('-')).join('.')}}-{{(monthlyItem.endTime.split('-')).join('.')}}</view>
+						</view>
+						<view class="mlib-item">
+							<view>剩余天数</view>:
+							<view>{{monthlyItem.surplusDays}}天</view>
+						</view>
+					</view>
+					<view v-if="monthlyItem.feeStatus=='0'" class="button-wrap u-flex u-row-right">
+						<view class="tool-btn" 
+						:class="{'tool-btn-cancel':monthlyItem.feeStatus=='0'}" 
+						v-if="monthlyItem.feeStatus=='0'" 
+						@click="cancelMonth(monthlyItem.monthId)">取消订单</view>
+					</view>
+					<view v-else-if="monthlyItem.feeStatus == 1 && monthlyItem.surplusDays > 2" class="button-wrap u-flex u-row-right">
+						<view class="tool-btn">已缴费</view>
+					</view>
+					<view v-else-if="monthlyItem.feeStatus == 1 && monthlyItem.surplusDays < 3" class="button-wrap u-flex u-row-right">
+						<view class="tool-btn" @click="goRenewal(monthlyItem)">去续费</view>
+					</view>
+				</view>
+			</view>
+		</mescroll-body>
+		<u-modal v-model="canclShow" content="确认取消该订单?" @confirm="confirm" :show-cancel-button="true"></u-modal>
 		<u-toast ref="uToast" />
 	</view>
 </template>
@@ -58,9 +58,13 @@
 		mixins: [MescrollMixin], // 使用mixin
 		data() {
 			return {
-				cancelShow: false,
-				mescroll: null,
-				dataList: []
+				id:'',
+				canclShow: false,
+				monthlyList: [],
+				monthList:'',
+				beginTime:'',
+				endTime:'',
+				time:[],
 			}
 		},
 		onShow() {
@@ -76,54 +80,81 @@
 					url: 'pages/center/index'
 				});
 			},
-			// mescroll组件初始化的回调,可获取到mescroll对象
-			mescrollInit(mescroll) {
-				this.mescroll = mescroll;
-			},
-			// 下拉刷新的回调
+			/*下拉刷新的回调*/
 			downCallback(){
-				// 下拉刷新和上拉加载调同样的接口
+				// 第2种: 下拉刷新和上拉加载调同样的接口, 则不用第1种, 直接mescroll.resetUpScroll()即可
 				this.mescroll.resetUpScroll(); // 重置列表为第一页 (自动执行 page.num=1, 再触发upCallback方法 )
 			},
-			// 上拉加载的回调
+			/*上拉加载的回调*/
 			upCallback(page) {
 				let pageNum = page.num; // 页码, 默认从1开始
 				let pageSize = page.size; // 页长, 默认每页10条
-				this.$u.api.getMonthList({
-					pageSize: pageSize,
-					pageNum: pageNum,
-				})
-				.then(res =>{
-					console.log(res)
-					if (res.code === 200) {
-						// 接口返回的当前页数据列表 (数组)
-						let curPageData = res.data.rows; 
-						// 接口返回的当前页数据长度 
-						let curPageLen = curPageData.length; 
-						// 接口返回的总页数 (如列表有26个数据,每页10条,共3页; 则totalPage=3)
-						let totalPage = res.data.pages; 
-						// 接口返回的总数据量(如列表有26个数据,每页10条,共3页; 则totalSize=26)
-						let totalSize = res.data.total; 
-						// 接口返回的是否有下一页 (true/false)
-						let hasNext = res.data.page < res.data.pages; 
-						
-						//设置列表数据
-						if(page.num == 1) this.dataList = []; //如果是第一页需手动置空列表
-						this.dataList = this.dataList.concat(curPageData); //追加新数据
-						
-						// 请求成功,隐藏加载状态
-						this.mescroll.endByPage(curPageLen, totalPage);
-						setTimeout(()=>{
-							this.mescroll.endSuccess(curPageLen)
-						}, 20)
+				// this.getMessageList()
+				this.$u.api.getMonthList({pageSize:pageSize ,pageNum: pageNum})
+				.then(res=>{
+					if(res.code == 200){
+					console.log('res',res)
+					// 接口返回的当前页数据列表 (数组)
+					let curPageData = res.data.rows;
+					// 接口返回的当前页数据长度 (如列表有26个数据,当前页返回8个,则curPageLen=8)
+					let curPageLen = curPageData.length; 
+					// 接口返回的总页数 (如列表有26个数据,每页10条,共3页; 则totalPage=3)
+					let totalPage = res.data.pages; 
+					// 接口返回的总数据量(如列表有26个数据,每页10条,共3页; 则totalSize=26)
+					let totalSize = res.data.total; 
+					// 接口返回的是否有下一页 (true/false)
+					// let hasNext = Number(res.data.page) < Number(res.data.pages); 
+					
+					//设置列表数据
+					if(page.num == 1) this.monthlyList = []; //如果是第一页需手动置空列表
+					this.monthlyList = this.monthlyList.concat(curPageData); //追加新数据
+					
+					// 请求成功,隐藏加载状态
+					//方法一(推荐): 后台接口有返回列表的总页数 totalPage
+					this.mescroll.endByPage(curPageLen, totalPage); 
+					setTimeout(()=>{
+						this.mescroll.endSuccess(curPageLen)
+					},20)
+					this.monthList=[],
+					res.data.rows.forEach(item => {
+						const obj = {
+							beginTime: item.beginTime,
+							endTime: item.endTime,
+						}
+						this.monthList.push(obj)
+						// console.log(obj)
+					});
+					this.time = this.monthList[0]
+					let Date1 = this.time.beginTime;
+					let Date2 = this.time.endTime;
+					// Date1 = Date1.valueOf() + 24 * 60 * 60 * 1000
+					Date1 = new Date(Date1)
+					const year = Date1.getFullYear()
+					const month = Date1.getMonth()+1
+					const day = Date1.getDate()
+					Date2 = new Date(Date2)
+					const year2 = Date2.getFullYear()
+					const month2 = Date2.getMonth()+1
+					const day2 = Date2.getDate()
+					this.beginTime = year + '.' + month + '.' + day
+					console.log(this.beginTime)
+					this.endTime = year2 + '.' + month2 + '.' + day2
+					}else{
+						this.mescroll.endErr()
 					}
-				})
-				.catch(err => {
-					this.$refs.uToast.show({
-						title: '操作失败!',
-						type: 'error'
-					})
-				})
+				}).catch(err=>{
+					// console.log('err',err);
+					// this.$refs.uToast.show({
+					// 	title: err.msg,
+					// 	type: 'error',
+					// });
+				});
+				
+			},
+			cancelMonth(monthId){
+				this.id=monthId;
+				this.canclShow = true;
+				console.log('monthId',monthId)
 			},
 			confirm(){
 				this.$u.api.cancelMonth({monthId: this.id})

+ 10 - 5
pages/favourableActivity/favourableActivity.vue

@@ -9,7 +9,7 @@
 				</view>
 				<view>如果停车场、路边停车位有15分钟内等免费政策的,我行客户自然享受后再按“一分钱停车”、“八折停车”执行。</view>
 				<view>
-					<button type="default" class="btn1">银行卡开户</button>
+					<button type="default" class="btn1" @click="openAcount">银行卡开户</button>
 				</view>
 			</view>
 		</view>
@@ -21,10 +21,11 @@
 				</view>
 				<view>如果停车场、路边停车位有15分钟内等免费政策的,我行客户自然享受后再按“一分钱停车”、“八折停车”执行。</view>
 				<view>
-					<button type="default" class="btn2">银行卡开户</button>
+					<button type="default" class="btn2" @click="openAcount">银行卡开户</button>
 				</view>
 			</view>
 		</view>
+		<u-toast ref="uToast"/>
 	</view>
 </template>
 
@@ -48,10 +49,14 @@
 				this.id = 1
 			}
 		},
-		onShow() {
-			console.log(this.id == 1)
-		},
+		onShow() {},
 		methods: {
+			openAcount() {
+				this.$refs.uToast.show({
+					title: '该功能尚未开发',
+					type: 'warning'
+				})
+			}
 		}
 	}
 </script>

+ 1 - 1
pages/index/index.vue

@@ -214,7 +214,7 @@
 			this.handleGetIndexData();
 			this.getLocation();
 			let locationLocaturl = window.location.search;
-			this.code = getUrlParams(locationLocaturl,"code");
+			this.code = getUrlParams(locationLocaturl, "code");
 			if(this.code&&!this.$store.state.vuex_wxinfo.openId){this.handleGetWXInfo(this.code)};
 		},
 		methods: {

+ 83 - 52
pages/myCars/myCars.vue

@@ -31,7 +31,7 @@
 					<view class="mycars-item-tool">
 						<span class="default" v-if="item.isDefault == 1" :class="{'isDefault':item.isDefault == 1}" @click="handlesetDefault(item.id)">默认</span>
 						<span class="default" v-else @click="handlesetDefault(item.id)">设为默认</span>
-						<span @click="handleDelCar(item.id,item.vehicleNo)">删除</span>
+						<span @click="handleDelCar(item.id, item.vehicleNo)">删除</span>
 					</view>
 				</view>
 			</view>
@@ -69,9 +69,9 @@
 		onLoad(){
 			this.handlegetMycars();
 		},
-		onShow() {
-			this.handlegetMycars();
-		},
+		// onShow() {
+		// 	this.handlegetMycars();
+		// },
 		methods:{
 			customBack(){
 				this.$u.route({
@@ -79,16 +79,28 @@
 					url: 'pages/index/index'
 				});
 			},
+			// 获取车辆列表
 			handlegetMycars(){
 				this.$u.api.getMycars()
-				.then(res=>{
-					this.mycars = res.data.rows;
-					this.mycarsTotal = res.data.total;
-					console.log('this.mycars',this.mycars)
-				}).catch(err=>{
-					console.log('getMycars ',err)
-				});
+					.then(res=>{
+						if (res.code === 200) {
+							this.mycars = res.data.rows;
+							this.mycarsTotal = res.data.total;
+						} else {
+							this.$refs.uToast.show({
+								title: res.msg,
+								type: 'error'
+							})
+						}
+					})
+					.catch(err=>{
+						this.$refs.uToast.show({
+							title: '操作失败!',
+							type: 'error'
+						})
+					});
 			},
+			// 添加车辆
 			handleAddCar(){
 				if(!this.$u.test.carNo(this.newPlateNumber)){
 					this.$refs.uToast.show({
@@ -97,50 +109,64 @@
 					});
 					return
 				}
-				let param ={
+				let param = {
 					vehicleNo: this.newPlateNumber,
 					vehicleColor: this.vehicleColor
 				};
 				this.$u.api.addCar(param)
-				.then(res=>{
-					this.$refs.uToast.show({
-						title: res.msg,
-						type: 'success',
-					});
-					this.handlegetMycars();
-					console.log('getMycars',res)
-				}).catch(err=>{
-					this.$refs.uToast.show({
-						title: err.msg,
-						type: 'error',
+					.then(res=>{
+						if (res.code === 200) {
+							this.$refs.uToast.show({
+								title: res.msg,
+								type: 'success',
+							});
+							this.handlegetMycars();
+						} else {
+							this.$refs.uToast.show({
+								title: res.msg,
+								type: 'error',
+							});
+						}
+					})
+					.catch(err=>{
+						this.$refs.uToast.show({
+							title: '操作失败!',
+							type: 'error',
+						});
 					});
-					console.log('getMycars ',err)
-				});
 			},
-			handleDelCar(id,content){
+			// 删除车辆
+			handleDelCar(id, content){
 				this.delCarContent = `是否删除${content}`;
 				this.delCarId = id;
 				this.delCarshow = true;
 				
 			},
+			// 确认删除
 			confirmDelCar(){
-				console.log(this.delCarId);
 				this.$u.api.delCar(this.delCarId)
-				.then(res=>{
-					this.$refs.uToast.show({
-						title: res.msg,
-						type: 'success',
-					});
-					this.handlegetMycars();
-					console.log('getMycars',res)
-				}).catch(err=>{
-					this.$refs.uToast.show({
-						title: err.msg,
-						type: 'error',
-					});
-					console.log('getMycars ',err)
-				});				
+					.then(res=>{
+						if (res.code === 200) {
+							this.$refs.uToast.show({
+								title: res.msg,
+								type: 'success',
+							});
+							this.handlegetMycars();
+						} else {
+							this.$refs.uToast.show({
+								title: res.msg,
+								type: 'error',
+							});
+						}
+					})
+					.catch(err=>{
+						this.$refs.uToast.show({
+							title: '操作失败!',
+							type: 'error',
+						});
+					});				
 			},
+			// 点击输入框
 			messageInputClick(){
 				this.keyboardshow = true;
 			},
@@ -148,36 +174,41 @@
 			keyboardChange(val) {
 				// 将每次按键的值拼接到value变量中,注意+=写法
 				this.newPlateNumber += val;
-				console.log(this.newPlateNumber);
 			},
 			// 退格键被点击
 			backspace() {
 				// 删除value的最后一个字符
 				if(this.newPlateNumber.length) this.newPlateNumber = this.newPlateNumber.substr(0, this.newPlateNumber.length - 1);
-				console.log(this.newPlateNumber);
 			},
+			// 键盘输入完成后确认
 			keyboardConfirm(){
 				this.colorShow = true;
 			},
+			// 确认颜色
 			confirmColor(e){
 				this.vehicleColor = this.colorList[e].colorCode;
 			},
-			// 设置默认车辆
+			// 设置默认车辆操作
 			handlesetDefault(id){
 				this.$u.api.setDefaultCar({id:id})
 				.then(res=>{
-					this.$refs.uToast.show({
-						title: res.msg,
-						type: 'success',
-					});
-					this.handlegetMycars();
-					console.log('handlesetDefault',res)
+					if (res.code === 200) {
+						this.$refs.uToast.show({
+							title: res.msg,
+							type: 'success',
+						});
+						this.handlegetMycars();
+					} else {
+						this.$refs.uToast.show({
+							title: res.msg,
+							type: 'error',
+						});
+					}
 				}).catch(err=>{
 					this.$refs.uToast.show({
-						title: err.msg,
+						title: '操作失败!',
 						type: 'error',
 					});
-					console.log('handlesetDefault err',err)
 				});	
 			}
 			

+ 38 - 0
uni_modules/z-paging/changelog.md

@@ -0,0 +1,38 @@
+## 1.9.3(2021-07-12)
+1.延后首次加载自动请求的时机,使其在onLoad之后触发。  
+2.修复使用`safe-area-inset-bottom`时,距离顶部有段空白的BUG。  
+3.优化横向切换与下拉刷新手势的兼容,横向切换时禁止下拉刷新的细节调整。  
+## 1.9.2(2021-07-09)
+## 【注意】由V1.9.0起,fixed属性默认值为true,z-paging默认会铺满屏幕。老项目更新请注意,使用侧滑滚动切换选项卡或需要局部使用z-paging请设置:fixed="false"。如果您希望fixed属性默认为false,请参考文档:z-paging.com,将fixed默认值设置为false。 
+1.新增`completeByNoMore(data,nomore)`方法,支持在请求结束时自行控制是否有更多数据。  
+2.修复在微信小程序中,:fixed="false"时列表未展示的BUG。  
+3.进一步兼容和整合vue和nvue的写法。  
+4.其他细节调整与优化。
+## 1.9.1(2021-07-07)
+# 【注意】由V1.9.0起,fixed属性默认值为true,z-paging默认会铺满屏幕。老项目更新请注意,使用侧滑滚动切换选项卡或需要局部使用z-paging请设置:fixed="false"。如果您希望fixed属性默认为false,请参考文档:z-paging.com,将fixed默认值设置为false。
+1.修复在一些情况下空数据图无法展示或展示位置不正确的问题。  
+2.其他细节优化。
+## 1.9.0(2021-07-04)
+## 【注意1】由V1.9.0起,fixed属性默认值为true,z-paging默认会铺满屏幕。老项目更新请注意,使用侧滑滚动切换选项卡或需要局部使用z-paging请设置:fixed="false"。如果您希望fixed属性默认为false,请参考下方的【全局配置】,将fixed默认值设置为false。  
+1.修复使用slot="top"时可能出现的置顶view点击无效的问题。  
+2.修复设置`show-loading-more-when-reload`后,下拉刷新时底部加载更多view也处于loading状态的问题。  
+3.其他细节调整。
+
+## 1.8.9(2021-07-01)
+1.默认状态由`translateY(0px)`修改为`none`,修复因使用transform引发的子view fixed被降级为absoult的BUG。  
+2.修复在nvue安卓中,通过`loading-more-custom-style`修改加载更多view的高度时,加载更多view被裁剪的BUG。  
+3.去掉reload自动滚动到顶部的动画。  
+4.当`loading-more-enabled`设置为false,且`show-loading-more-when-reload`为true时,`show-loading-more-when-reload`优先。  
+5.修复在nvue 安卓中使用聊天记录模式,只有一页时底部有一段空白的BUG。  
+6.`concat`为false时,不再自动清空list。  
+## 1.8.8(2021-06-30)
+1.修复设置了`show-loading-more-when-reload`后,下拉刷新时展示加载更多loading且无数据时展示加载更多view的BUG。  
+2.修复在nvue中,在安卓设备上下拉刷新view底部有一根白色横线的BUG。  
+3.修复在nvue中,设置了`show-refresher-when-reload`后,部分平台reload时页面卡住闪退的BUG。  
+4.在nvue中支持`slot="top"`和`slot="bottom"`,使其写法与vue相同。  
+5.修改部分内部通用变量名,以避免在一些项目中引入mixins与其冲突的问题。  
+6.修复在nvue中,滚动到顶部会停顿一下,继续上拉才可以加载更多的BUG。  
+7.新增`concat`属性,支持控制是否自动拼接complete传过来的数组。
+## 1.8.7(2021-06-22)
+1.新增滑动切换选项卡简化写法及演示。  
+2.修复reload自动滚动到顶部无效的BUG。

+ 170 - 0
uni_modules/z-paging/components/z-paging-empty-view/z-paging-empty-view.vue

@@ -0,0 +1,170 @@
+<!-- z-paging -->
+<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
+<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
+<!-- 反馈QQ群:790460711 -->
+
+<!-- 空数据占位view,此组件支持easycom规范,可以在项目中直接引用 -->
+<template>
+	<view class="zp-container" :style="[finalEmptyViewStyle]">
+		<view class="zp-main">
+			<image v-if="!emptyViewImg.length" class="zp-main-image" :style="[emptyViewImgStyle]" :src="emptyImg"></image>
+			<image v-else class="zp-main-image" mode="aspectFit" :style="[emptyViewImgStyle]" :src="emptyViewImg"></image>
+			<text class="zp-main-title" :style="[emptyViewTitleStyle]">{{emptyViewText}}</text>
+			<text v-if="showEmptyViewReload" class="zp-main-error-btn" :style="[emptyViewReloadStyle]"
+				@click="reloadClick">{{emptyViewReloadText}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import zStatic from '../z-paging/js/z-paging-static'
+	export default {
+		data() {
+			return {
+				base64Empty: zStatic.base64Empty,
+				base64Error: zStatic.base64Error
+			};
+		},
+		props: {
+			//空数据描述文字
+			emptyViewText: {
+				type: String,
+				default: function() {
+					return '没有数据哦~'
+				}
+			},
+			//空数据图片
+			emptyViewImg: {
+				type: String,
+				default: function() {
+					return ''
+				}
+			},
+			//是否显示空数据图重新加载按钮
+			showEmptyViewReload: {
+				type: Boolean,
+				default: function() {
+					return false
+				}
+			},
+			//空数据点击重新加载文字
+			emptyViewReloadText: {
+				type: String,
+				default: function() {
+					return '重新加载'
+				}
+			},
+			//是否是加载失败
+			isLoadFailed: {
+				type: Boolean,
+				default: function() {
+					return false
+				}
+			},
+			//空数据图样式
+			emptyViewStyle: {
+				type: Object,
+				default: function() {
+					return {}
+				}
+			},
+			//空数据图img样式
+			emptyViewImgStyle: {
+				type: Object,
+				default: function() {
+					return {}
+				}
+			},
+			//空数据图描述文字样式
+			emptyViewTitleStyle: {
+				type: Object,
+				default: function() {
+					return {}
+				}
+			},
+			//空数据图重新加载按钮样式
+			emptyViewReloadStyle: {
+				type: Object,
+				default: function() {
+					return {}
+				}
+			},
+			//空数据图z-index
+			emptyViewZIndex: {
+				type: Number,
+				default: function() {
+					return 9
+				}
+			}
+		},
+		computed: {
+			emptyImg() {
+				if (this.isLoadFailed) {
+					return this.base64Error;
+				} else {
+					return this.base64Empty;
+				}
+			},
+			finalEmptyViewStyle(){
+				this.emptyViewStyle['z-index'] = this.emptyViewZIndex;
+				return this.emptyViewStyle;
+			}
+		},
+		methods: {
+			reloadClick() {
+				this.$emit('reload');
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.zp-container {
+		/* #ifndef APP-NVUE */
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		display: flex;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+	}
+
+	.zp-main {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		margin-top: -150rpx;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		margin-top: -100rpx;
+		/* #endif */
+		flex-direction: column;
+		align-items: center;
+	}
+
+	.zp-main-image {
+		width: 200rpx;
+		height: 200rpx;
+	}
+
+	.zp-main-title {
+		font-size: 26rpx;
+		color: #aaaaaa;
+		text-align: center;
+		margin-top: 10rpx;
+	}
+
+	.zp-main-error-btn {
+		font-size: 26rpx;
+		padding: 8rpx 24rpx;
+		border: solid 1px #dddddd;
+		border-radius: 6rpx;
+		color: #aaaaaa;
+		margin-top: 50rpx;
+	}
+</style>

+ 86 - 0
uni_modules/z-paging/components/z-paging-swiper-item/z-paging-swiper-item.vue

@@ -0,0 +1,86 @@
+<!-- z-paging -->
+<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
+<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
+<!-- 反馈QQ群:790460711 -->
+
+<!-- 滑动切换选项卡swiper-item,此组件支持easycom规范,可以在项目中直接引用 -->
+<template>
+	<view class="zp-swiper-item-container">
+		<z-paging ref="paging" :fixed="false" @query="_queryList" @listChange="_updateList" :mounted-auto-call-reload="false"
+			style="height: 100%;">
+			<slot></slot>
+		</z-paging>
+	</view>
+</template>
+
+<script>
+	import zPaging from '../z-paging/z-paging'
+	export default {
+		name: "z-paging-swiper-item",
+		components: {
+			zPaging
+		},
+		data() {
+			return {
+				firstLoaded: false
+			}
+		},
+		props: {
+			//当前组件的index,也就是当前组件是swiper中的第几个
+			tabIndex: {
+				type: Number,
+				default: function() {
+					return 0
+				}
+			},
+			//当前swiper切换到第几个index
+			currentIndex: {
+				type: Number,
+				default: function() {
+					return 0
+				}
+			},
+		},
+		watch: {
+			currentIndex: {
+				handler(newVal, oldVal) {
+					if (newVal === this.tabIndex) {
+						//懒加载,当滑动到当前的item时,才去加载
+						if (!this.firstLoaded) {
+							setTimeout(() => {
+								this.$refs.paging.reload();
+							}, 5);
+						}
+					}
+				},
+				immediate: true
+			}
+		},
+		methods: {
+			reload(data) {
+				this.$refs.paging.reload(data);
+			},
+			complete(data) {
+				this.firstLoaded = true;
+				this.$refs.paging.complete(data);
+			},
+			_queryList(pageNo, pageSize) {
+				this.$emit('query', pageNo, pageSize);
+			},
+			_updateList(list) {
+				this.$emit('updateList', list);
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.zp-swiper-item-container {
+		/* #ifndef APP-NVUE */
+		height: 100%;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+	}
+</style>

+ 123 - 0
uni_modules/z-paging/components/z-paging-swiper/z-paging-swiper.vue

@@ -0,0 +1,123 @@
+<!-- z-paging -->
+<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
+<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
+<!-- 反馈QQ群:790460711 -->
+
+<!-- 滑动切换选项卡swiper,此组件支持easycom规范,可以在项目中直接引用 -->
+<template>
+	<view :class="fixed?'zp-swiper-container zp-swiper-container-fixed':'zp-swiper-container'" :style="[swiperStyle]">
+		<slot v-if="$slots.top" name="top"></slot>
+		<view class="zp-swiper-super">
+			<view class="zp-swiper">
+				<slot/></slot>
+			</view>
+		</view>
+		<slot v-if="$slots.bottom" name="bottom"></slot>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "z-paging-swiper",
+		data() {
+			return {
+				systemInfo: null
+			};
+		},
+		props: {
+			//是否使用fixed布局,默认为是
+			fixed: {
+				type: Boolean,
+				default: true
+			},
+			//是否开启底部安全区域适配
+			safeAreaInsetBottom: {
+				type: Boolean,
+				default: false
+			}
+		},
+		mounted() {
+			this.$nextTick(() => {
+				this.systemInfo = uni.getSystemInfoSync();
+			})
+		},
+		computed: {
+			swiperStyle() {
+				if (!this.systemInfo) {
+					return {};
+				}
+				let swiperStyle = {};
+				const windowTop = this.systemInfo.windowTop;
+				const windowBottom = this.systemInfo.windowBottom;
+				if (this.fixed) {
+					if (windowTop && windowTop !== undefined) {
+						swiperStyle.top = windowTop + 'px';
+					}
+					let bottom = 0;
+					if (windowBottom && windowBottom !== undefined) {
+						bottom = windowBottom;
+					}
+					if (this.safeAreaInsetBottom) {
+						bottom += this.safeAreaBottom;
+					}
+					swiperStyle.bottom = bottom + 'px';
+				}
+				return swiperStyle;
+			},
+			safeAreaBottom() {
+				if (!this.systemInfo) {
+					return 0;
+				}
+				let safeAreaBottom = 0;
+				// #ifdef APP-PLUS || H5 || MP-WEIXIN
+				safeAreaBottom = this.systemInfo.safeAreaInsets.bottom || 0;
+				// #endif
+				return safeAreaBottom;
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.zp-swiper-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		flex: 1;
+	}
+
+	.zp-swiper-container-fixed {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		height: auto;
+		width: auto;
+		/* #endif */
+		top: 0;
+		left: 0;
+		bottom: 0;
+		right: 0;
+	}
+
+	.zp-swiper-super {
+		flex: 1;
+		position: relative;
+	}
+
+	.zp-swiper {
+		/* #ifndef APP-NVUE */
+		height: 100%;
+		width: 100%;
+		position: absolute;
+		top: 0;
+		left: 0;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+	}
+	
+	.zp-swiper-item {
+		height: 100%;
+	}
+</style>

+ 158 - 0
uni_modules/z-paging/components/z-paging/components/z-paging-load-more.vue

@@ -0,0 +1,158 @@
+<!-- z-paging -->
+<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
+<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
+<!-- 反馈QQ群:790460711 -->
+
+<!-- 上拉加载更多view -->
+<template>
+	<view class="zp-load-more-container" :style="[zConfig.loadingMoreCustomStyle]">
+		<text
+			:class="zConfig.defaultThemeStyle==='white'?'zp-loading-more-line zp-loading-more-line-white':'zp-loading-more-line zp-loading-more-line-black'"
+			:style="[zConfig.loadingMoreNoMoreLineCustomStyle]"
+			v-if="zConfig.showLoadingMoreNoMoreLine&&zConfig.loadingStatus===2"></text>
+		<!-- #ifndef APP-NVUE -->
+		<image v-if="zConfig.loadingStatus===1&&zConfig.loadingMoreLoadingIconCustomImage.length"
+			:src="zConfig.loadingMoreLoadingIconCustomImage" class="zp-loading-more-line-loading-custom-image">
+		</image>
+		<image
+			v-if="zConfig.loadingStatus===1&&zConfig.loadingMoreLoadingIconType==='flower'&&!zConfig.loadingMoreLoadingIconCustomImage.length"
+			class="zp-loading-more-line-loading-image" :style="[zConfig.loadingMoreLoadingIconCustomStyle]"
+			:src="zConfig.defaultThemeStyle==='white'?base64FlowerWhite:base64Flower">
+		</image>
+		<!-- #endif -->
+		<!-- #ifdef APP-NVUE -->
+		<view>
+			<loading-indicator v-if="zConfig.loadingStatus===1"
+				:style="[{color:zConfig.defaultThemeStyle==='white'?'white':'#777777'}]" :animating="true"
+				class="zp-loading-more-line-loading-image">
+			</loading-indicator>
+		</view>
+		<!-- #endif -->
+		<text
+			v-if="zConfig.loadingStatus===1&&zConfig.loadingMoreLoadingIconType==='circle'&&!zConfig.loadingMoreLoadingIconCustomImage.length"
+			:class="zConfig.defaultThemeStyle==='white'?'zp-loading-more-line-loading-view zp-loading-more-line-loading-view-white':'zp-loading-more-line-loading-view zp-loading-more-line-loading-view-black'"
+			:style="[zConfig.loadingMoreLoadingIconCustomStyle]"></text>
+		<text
+			:class="zConfig.defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{ownLoadingMoreText}}</text>
+		<text
+			:class="zConfig.defaultThemeStyle==='white'?'zp-loading-more-line zp-loading-more-line-white':'zp-loading-more-line zp-loading-more-line-black'"
+			:style="[zConfig.loadingMoreNoMoreLineCustomStyle]"
+			v-if="zConfig.showLoadingMoreNoMoreLine&&zConfig.loadingStatus===2"></text>
+	</view>
+</template>
+<script>
+	import zStatic from '../js/z-paging-static'
+	export default {
+		name: 'z-paging-load-more',
+		data() {
+			return {
+				base64Arrow: zStatic.base64Arrow,
+				base64Flower: zStatic.base64Flower,
+				base64FlowerWhite: zStatic.base64FlowerWhite,
+			};
+		},
+		props: ['zConfig'],
+		computed: {
+			ownLoadingMoreText() {
+				const loadingMoreText = this.loadingStatusTextMap[this.zConfig.loadingStatus];
+				return loadingMoreText;
+			},
+			loadingStatusTextMap() {
+				return {
+					0: this.zConfig.loadingMoreDefaultText,
+					1: this.zConfig.loadingMoreLoadingText,
+					2: this.zConfig.loadingMoreNoMoreText,
+					3: this.zConfig.loadingMoreFailText,
+				}
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	@import "../css/z-paging-static.css";
+
+	.zp-load-more-container {
+		height: 80rpx;
+		font-size: 27rpx;
+		/* #ifndef APP-NVUE */
+		clear: both;
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.zp-loading-more-line-loading-custom-image {
+		color: #a4a4a4;
+		margin-right: 8rpx;
+		width: 28rpx;
+		height: 28rpx;
+		/* #ifndef APP-NVUE */
+		animation: loading-circle 1s linear infinite;
+		/* #endif */
+	}
+
+	.zp-loading-more-line-loading-view {
+		margin-right: 8rpx;
+		width: 22rpx;
+		height: 23rpx;
+		border: 3rpx solid #dddddd;
+		border-radius: 50%;
+		/* #ifndef APP-NVUE */
+		animation: loading-circle 1s linear infinite;
+		/* #endif */
+	}
+
+	.zp-loading-more-line-loading-view-black {
+		border-color: #c8c8c8;
+		border-top-color: #444444;
+	}
+
+	.zp-loading-more-line-loading-view-white {
+		border-color: #aaaaaa;
+		border-top-color: #ffffff;
+	}
+
+	.zp-loading-more-text {
+		/* #ifdef APP-NVUE */
+		font-size: 30rpx;
+		margin: 0rpx 10rpx;
+		/* #endif */
+	}
+
+	.zp-loading-more-text-black {
+		color: #a4a4a4;
+	}
+
+	.zp-loading-more-text-white {
+		color: #efefef;
+	}
+
+	.zp-loading-more-line {
+		height: 1px;
+		width: 100rpx;
+		margin: 0rpx 10rpx;
+	}
+
+	.zp-loading-more-line-black {
+		background-color: #eeeeee;
+	}
+
+	.zp-loading-more-line-white {
+		background-color: #efefef;
+	}
+
+	@keyframes loading-circle {
+		0% {
+			-webkit-transform: rotate(0deg);
+			transform: rotate(0deg);
+		}
+
+		100% {
+			-webkit-transform: rotate(360deg);
+			transform: rotate(360deg);
+		}
+	}
+</style>

+ 259 - 0
uni_modules/z-paging/components/z-paging/components/z-paging-refresh.vue

@@ -0,0 +1,259 @@
+<!-- z-paging -->
+<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
+<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
+<!-- 反馈QQ群:790460711 -->
+
+<!-- 下拉刷新view -->
+<template>
+	<view style="height: 100%;">
+		<view
+			:class="['zp-custom-refresher-container',{'zp-custom-refresher-container-padding':showRefresherUpdateTime}]"
+			style="height: 100%;">
+			<view class="zp-custom-refresher-left">
+				<image v-if="refresherStatus!==2" :class="refresherLeftImageClass"
+					:style="[{width: showRefresherUpdateTime?'36rpx':'30rpx',height: showRefresherUpdateTime?'36rpx':'30rpx','margin-right': showRefresherUpdateTime?'20rpx':'8rpx'}]"
+					:src="defaultThemeStyle==='white'?base64ArrowWhite:base64Arrow">
+				</image>
+				<!-- #ifndef APP-NVUE -->
+				<image v-else class="zp-loading-more-line-loading-image zp-custom-refresher-left-image"
+					:style="[{width: showRefresherUpdateTime?'36rpx':'30rpx',height: showRefresherUpdateTime?'36rpx':'30rpx','margin-right': showRefresherUpdateTime?'20rpx':'8rpx'}]"
+					:src="defaultThemeStyle==='white'?base64FlowerWhite:base64Flower">
+				</image>
+				<!-- #endif -->
+				<!-- #ifdef APP-NVUE -->
+				<view v-else :style="[{'margin-right':showRefresherUpdateTime?'18rpx':'12rpx'}]">
+					<loading-indicator
+						:class="systemInfo.platform==='ios'?'zp-loading-image-ios':'zp-loading-image-android'"
+						:style="[{color:defaultThemeStyle==='white'?'white':'#777777'}]" :animating="true">
+					</loading-indicator>
+				</view>
+				<!-- #endif -->
+			</view>
+			<view class="zp-custom-refresher-right">
+				<text class="zp-custom-refresher-right-text"
+					:style="[refresherRightTextStyle]">{{refresherStatusTextMap[refresherStatus]||refresherDefaultText}}
+				</text>
+				<text class="zp-custom-refresher-right-text zp-custom-refresher-right-time-text"
+					:style="[refresherRightTextStyle]"
+					v-if="showRefresherUpdateTime&&refresherTimeText.length">{{refresherTimeText}}
+				</text>
+			</view>
+		</view>
+	</view>
+</template>
+<script>
+	const systemInfo = uni.getSystemInfoSync();
+	import zStatic from '../js/z-paging-static'
+	import {
+		getRefesrherFormatTimeByKey
+	} from '../js/z-paging-utils'
+	export default {
+		name: 'z-paging-refresh',
+		data() {
+			return {
+				systemInfo: systemInfo,
+				base64Arrow: zStatic.base64Arrow,
+				base64ArrowWhite: zStatic.base64ArrowWhite,
+				base64Flower: zStatic.base64Flower,
+				base64FlowerWhite: zStatic.base64FlowerWhite,
+				refresherTimeText: '',
+				isRefresherLeftImageClassLoaded: false
+			};
+		},
+		props: {
+			'refresherStatus': {
+				default: 0
+			},
+			'defaultThemeStyle': {},
+			'refresherDefaultText': {},
+			'refresherPullingText': {},
+			'refresherPullingText': {},
+			'refresherRefreshingText': {},
+			'showRefresherUpdateTime': {
+				default: false
+			},
+			'refresherUpdateTimeKey': {}
+		},
+		computed: {
+			refresherStatusTextMap() {
+				this.updateTime(this.refresherUpdateTimeKey);
+				return {
+					0: this.refresherDefaultText,
+					1: this.refresherPullingText,
+					2: this.refresherRefreshingText
+				};
+			},
+			refresherLeftImageClass() {
+				let refresherLeftImageClass = '';
+				if (this.refresherStatus === 0) {
+					if (this.isRefresherLeftImageClassLoaded) {
+						refresherLeftImageClass = 'zp-custom-refresher-left-image zp-custom-refresher-arrow-down';
+					} else {
+						this.isRefresherLeftImageClassLoaded = true;
+						refresherLeftImageClass =
+							'zp-custom-refresher-left-image zp-custom-refresher-arrow-down-no-duration';
+					}
+				} else {
+					refresherLeftImageClass = 'zp-custom-refresher-left-image zp-custom-refresher-arrow-top';
+				}
+				return refresherLeftImageClass;
+			},
+			refresherRightTextStyle() {
+				let refresherRightTextStyle = {};
+				let color = '#555555';
+				if (this.defaultThemeStyle === 'white') {
+					color = '#efefef';
+				}
+				// #ifdef APP-NVUE
+				if (this.showRefresherUpdateTime) {
+					refresherRightTextStyle = {
+						'height': '40rpx',
+						'line-height': '40rpx'
+					};
+				} else {
+					refresherRightTextStyle = {
+						'height': '80rpx',
+						'line-height': '80rpx'
+					};
+				}
+				// #endif
+				refresherRightTextStyle['color'] = color;
+				return refresherRightTextStyle;
+			}
+		},
+		methods: {
+			updateTime(refresherUpdateTimeKey) {
+				if (!refresherUpdateTimeKey) {
+					refresherUpdateTimeKey = this.refresherUpdateTimeKey;
+				}
+				if (this.showRefresherUpdateTime) {
+					this.refresherTimeText = getRefesrherFormatTimeByKey(refresherUpdateTimeKey);
+				}
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	@import "../css/z-paging-static.css";
+
+	.zp-custom-refresher-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.zp-custom-refresher-container-padding {
+		/* #ifdef APP-NVUE */
+		padding: 15rpx 0rpx;
+		/* #endif */
+	}
+
+	.zp-custom-refresher-left {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		overflow: hidden;
+	}
+
+	.zp-custom-refresher-left-image {
+		/* #ifndef APP-NVUE */
+		transform: rotate(180deg);
+		margin-top: 2rpx;
+		/* #endif */
+		/* #ifdef MP-ALIPAY */
+		margin-top: 0rpx;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		transition-duration: .2s;
+		transition-property: transform;
+		color: #666666;
+		/* #endif */
+	}
+
+	.zp-custom-refresher-arrow-top {
+		/* #ifndef APP-NVUE */
+		animation: refresher-arrow-top .2s linear;
+		-webkit-animation: refresher-arrow-top .2s linear;
+		animation-fill-mode: forwards;
+		-webkit-animation-fill-mode: forwards;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		transform: rotate(0deg);
+		/* #endif */
+	}
+
+	.zp-custom-refresher-arrow-down {
+		/* #ifndef APP-NVUE */
+		animation: refresher-arrow-down .2s linear;
+		-webkit-animation: refresher-arrow-down .2s linear;
+		animation-fill-mode: forwards;
+		-webkit-animation-fill-mode: forwards;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		transform: rotate(180deg);
+		/* #endif */
+	}
+
+	.zp-custom-refresher-arrow-down-no-duration {
+		/* #ifndef APP-NVUE */
+		animation: refresher-arrow-down 0s linear;
+		-webkit-animation: refresher-arrow-down 0s linear;
+		animation-fill-mode: forwards;
+		-webkit-animation-fill-mode: forwards;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		transform: rotate(180deg);
+		/* #endif */
+	}
+
+	.zp-custom-refresher-right {
+		font-size: 27rpx;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.zp-custom-refresher-right-text {
+		/* #ifdef APP-NVUE */
+		font-size: 28rpx;
+		/* #endif */
+	}
+
+	.zp-custom-refresher-right-time-text {
+		margin-top: 10rpx;
+		font-size: 24rpx;
+	}
+
+	@keyframes refresher-arrow-top {
+		0% {
+			-webkit-transform: rotate(180deg);
+			transform: rotate(180deg);
+		}
+
+		100% {
+			-webkit-transform: rotate(0deg);
+			transform: rotate(0deg);
+		}
+	}
+
+	@keyframes refresher-arrow-down {
+		0% {
+			-webkit-transform: rotate(0deg);
+			transform: rotate(0deg);
+		}
+
+		100% {
+			-webkit-transform: rotate(180deg);
+			transform: rotate(180deg);
+		}
+	}
+</style>

+ 157 - 0
uni_modules/z-paging/components/z-paging/css/z-paging-main.css

@@ -0,0 +1,157 @@
+/* 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-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;
+}

+ 38 - 0
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);
+	}
+}

+ 32 - 0
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
+};

+ 150 - 0
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
+}

File diff suppressed because it is too large
+ 2617 - 0
uni_modules/z-paging/components/z-paging/js/z-paging-main.js


+ 36 - 0
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;

File diff suppressed because it is too large
+ 25 - 0
uni_modules/z-paging/components/z-paging/js/z-paging-static.js


+ 179 - 0
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
+};

+ 60 - 0
uni_modules/z-paging/components/z-paging/wxs/z-paging-renderjs.js

@@ -0,0 +1,60 @@
+// 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'
+export default {
+	data() {
+		return {
+			renderScrollTop: 0,
+			renderUsePageScroll: false,
+			renderIsIos: uni.getSystemInfoSync().platform === 'ios',
+			startY: 0,
+			isTouchFromZPaging: false
+		}
+	},
+	mounted() {
+		this._handleTouch();
+	},
+	methods: {
+		//接收逻辑层发送的数据
+		renderPropScrollTopChange(newVal, oldVal, ownerVm, vm) {
+			this.renderScrollTop = newVal;
+		},
+		renderUsePageScrollChange(newVal, oldVal, ownerVm, vm) {
+			this.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);
+			this.startY = touch.touchY;
+			this.isTouchFromZPaging = zUtils.getTouchFromZPaging(e.target);
+		},
+		_handleTouchmove(e) {
+			const touch = zUtils.getCommonTouch(e);
+			var moveY = touch.touchY - this.startY;
+			if ((this.isTouchFromZPaging && this.renderScrollTop < 1 && moveY > 0) || (this.isTouchFromZPaging && this
+					.renderIsIos && !this
+					.renderUsePageScroll && moveY <
+					0)) {
+				if (e.cancelable && !e.defaultPrevented) {
+					e.preventDefault();
+				}
+			}
+		},
+
+	}
+};

+ 335 - 0
uni_modules/z-paging/components/z-paging/wxs/z-paging-wxs.wxs

@@ -0,0 +1,335 @@
+// 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;
+	}
+	if (moveDistance >= refresherThreshold) {
+		moveDistance = refresherThreshold;
+	}
+	_setTransformValue(moveDistance, instance, state)
+}
+
+// #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) {
+	value = value || 0;
+	if (state.moveDistance == value) {
+		return;
+	}
+	state.moveDistance = value;
+	_setTransform('translateY(' + value + 'px)', instance);
+}
+
+function _setTransform(transform, instance) {
+	if (transform == 'translateY(0px)') {
+		transform = 'none';
+	}
+	instance.requestAnimationFrame(function() {
+		instance.setStyle({
+			transform: transform,
+			'-webkit-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
+}

+ 239 - 0
uni_modules/z-paging/components/z-paging/z-paging.vue

@@ -0,0 +1,239 @@
+ <!--                        _             
+  ____     _ __   __ _  __ _(_)_ __   __ _ 
+ |_  /____| '_ \ / _` |/ _` | | '_ \ / _` |
+  / /_____| |_) | (_| | (_| | | | | | (_| |
+ /___|    | .__/ \__,_|\__, |_|_| |_|\__, |
+          |_|          |___/         |___/ 
+V1.9.3
+by ZXLee 2021-07-12
+-- >
+<!-- API文档地址:http://z-paging.com -->
+<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
+<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
+<!-- 反馈QQ群:790460711 -->
+
+<template name="z-paging">
+	<!-- #ifndef APP-NVUE -->
+	<view :class="!usePageScroll&&fixed?'z-paging-content z-paging-content-fixed':'z-paging-content'"
+		:style="[finalPagingStyle]">
+		<!-- 顶部固定的slot -->
+		<slot v-if="!usePageScroll&&$slots.top" name="top"></slot>
+		<view class="zp-page-scroll-top" v-else-if="usePageScroll&&$slots.top" :style="[{'top':`${windowTop}px`,'z-index':topZIndex}]">
+			<slot name="top"></slot>
+		</view>
+		<view :class="{'zp-scroll-view-super':!usePageScroll}" :style="[finalScrollViewStyle]">
+			<scroll-view
+				:class="{'zp-scroll-view':true,'zp-scroll-view-absolute':!usePageScroll}"
+				:scroll-top="scrollTop"
+				:scroll-y="scrollable&&!usePageScroll&&scrollEnable" :enable-back-to-top="finalEnableBackToTop"
+				:show-scrollbar="showScrollbar" :scroll-with-animation="finalScrollWithAnimation"
+				:scroll-into-view="scrollIntoView" :lower-threshold="finalLowerThreshold" :upper-threshold="5"
+				:refresher-enabled="finalRefresherEnabled&&!useCustomRefresher" :refresher-threshold="finalRefresherThreshold"
+				:refresher-default-style="finalRefresherDefaultStyle" :refresher-background="refresherBackground"
+				:refresher-triggered="refresherTriggered" @scroll="_scroll" @scrolltolower="_onLoadingMore('toBottom')"
+				@scrolltoupper="_scrollToUpper" @refresherrestore="_onRestore" @refresherrefresh="_onRefresh"  
+				>	
+				<view class="zp-paging-touch-view"
+				<!-- #ifndef APP-VUE || MP-WEIXIN || MP-QQ  || H5 -->
+				@touchstart="_refresherTouchstart" @touchmove="_refresherTouchmove" @touchend="_refresherTouchend" @touchcancel="_refresherTouchend"
+				<!-- #endif -->
+				<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
+				@touchstart="pagingWxs.touchstart" @touchmove="pagingWxs.touchmove" @touchend="pagingWxs.touchend" @touchcancel="pagingWxs.touchend"
+				@mousedown="pagingWxs.mousedown" @mousemove="pagingWxs.mousemove" @mouseup="pagingWxs.mouseup" @mouseleave="pagingWxs.mouseleave"
+				<!-- #endif -->
+				>	
+					<view v-if="finalRefresherFixedBacHeight>0" class="zp-fixed-bac-view" :style="[{'background-color': refresherFixedBackground,'height': `${finalRefresherFixedBacHeight}px`}]"></view>
+					<view class="zp-paging-main" :style="[{'transform': finalRefresherTransform,'transition': refresherTransition}]"
+					<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
+					:change:prop="pagingWxs.propObserver" :prop="wxsPropType"
+					:data-refresherThreshold="finalRefresherThreshold" :data-isIos="isIos"
+					: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"
+					<!-- #endif -->
+					<!-- #ifdef APP-VUE || H5 -->
+					:change:renderPropScrollTop="pagingRenderjs.renderPropScrollTopChange" :renderPropScrollTop="renderPropScrollTop"
+					:change:renderUsePageScroll="pagingRenderjs.renderUsePageScrollChange" :renderUsePageScroll="renderUsePageScroll"
+					<!-- #endif -->
+					>	
+						<view v-if="finalRefresherEnabled&&useCustomRefresher&&isTouchmoving" class="zp-custom-refresher-view"
+							:style="[{'margin-top': `-${finalRefresherThreshold}px`,'background-color': refresherBackground}]">
+							<view :style="[{'height': `${finalRefresherThreshold}px`,'background-color': refresherBackground}]">
+								<!-- 下拉刷新view -->
+								<slot 
+								<!-- #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO || MP-BAIDU  -->
+								v-if="zScopedSlots.refresher"
+								<!-- #endif -->
+								<!-- #ifndef MP-WEIXIN || MP-QQ || MP-TOUTIAO || MP-BAIDU -->
+								v-if="$scopedSlots.refresher||$slots.refresher"
+								<!-- #endif -->
+								<!-- #ifndef MP-QQ -->
+								:refresherStatus="refresherStatus"
+								<!-- #endif -->
+								name="refresher" />
+								<z-paging-refresh ref="refresh" v-else :style="[{'height': `${finalRefresherThreshold}px`}]" :refresherStatus="refresherStatus"
+									:defaultThemeStyle="finalRefresherThemeStyle" :refresherDefaultText="finalRefresherDefaultText"
+									:refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText" 
+									:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
+							</view>
+						</view>
+						<view class="zp-paging-container">
+							<slot v-if="useChatRecordMode&&$slots.chatLoading&&loadingStatus!==2&&realTotalData.length"
+								name="chatLoading" />
+							<view v-else-if="useChatRecordMode&&loadingStatus!==2&&realTotalData.length"
+								class="zp-chat-record-loading-container">
+								<text v-if="loadingStatus!==1" @click="_scrollToUpper()"
+									:class="defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{chatRecordLoadingMoreText}}</text>
+								<image v-else :src="base64Flower" class="zp-chat-record-loading-custom-image">
+								</image>
+							</view>
+							<slot v-if="$slots.loading&&!firstPageLoaded&&(autoHideLoadingAfterFirstLoaded?!pagingLoaded:true)&&loading" name="loading" />
+							<!-- 空数据图 -->
+							<view class="zp-empty-view"
+								v-if="showEmpty">
+								<slot v-if="$slots.empty" name="empty" />
+								<z-paging-empty-view v-else :emptyViewImg="finalEmptyViewImg" :emptyViewText="finalEmptyViewText" :showEmptyViewReload="finalShowEmptyViewReload" :emptyViewReloadText="finalEmptyViewReloadText" :isLoadFailed="isLoadFailed" :emptyViewStyle="emptyViewStyle" :emptyViewTitleStyle="emptyViewTitleStyle" :emptyViewImgStyle="emptyViewImgStyle" :emptyViewReloadStyle="emptyViewReloadStyle" :emptyViewZIndex="emptyViewZIndex" @reload="_emptyViewReload">
+								</z-paging-empty-view>
+							</view>
+							<!-- 主体内容 -->
+							<view class="zp-paging-container-content" :style="[finalPagingContentStyle]">
+								<slot />
+							</view>
+							<!-- 上拉加载更多view -->
+							<!-- #ifndef MP-ALIPAY -->
+							<slot v-if="_shouldShowLoading('loadingMoreDefault')" name="loadingMoreDefault" />
+							<slot v-else-if="_shouldShowLoading('loadingMoreLoading')" name="loadingMoreLoading" />
+							<slot v-else-if="_shouldShowLoading('loadingMoreNoMore')" name="loadingMoreNoMore" />
+							<slot v-else-if="_shouldShowLoading('loadingMoreFail')" name="loadingMoreFail" />
+							<z-paging-load-more @click.native="_onLoadingMore('click')"
+								v-else-if="_shouldShowLoading('loadingMoreCustom')" :zConfig="zPagingLoadMoreConfig">
+							</z-paging-load-more>
+							<!-- #endif -->
+							<!-- #ifdef MP-ALIPAY -->
+							<slot v-if="loadingStatus===0&&$slots.loadingMoreDefault&&showLoadingMore&&loadingMoreEnabled&&!useChatRecordMode"
+								name="loadingMoreDefault" />
+							<slot v-else-if="loadingStatus===1&&$slots.loadingMoreLoading&&showLoadingMore&&loadingMoreEnabled"
+								name="loadingMoreLoading" />
+							<slot v-else-if="loadingStatus===2&&$slots.loadingMoreNoMore&&showLoadingMore&&showLoadingMoreNoMoreView&&loadingMoreEnabled&&!useChatRecordMode"
+								name="loadingMoreNoMore" />
+							<slot v-else-if="loadingStatus===3&&$slots.loadingMoreFail&&showLoadingMore&&loadingMoreEnabled&&!useChatRecordMode"
+								name="loadingMoreFail" />
+							<z-paging-load-more @click.native="_onLoadingMore('click')" v-else-if="showLoadingMore&&showDefaultLoadingMoreText&&!(loadingStatus===2&&!showLoadingMoreNoMoreView)&&loadingMoreEnabled&&!useChatRecordMode" :zConfig="zPagingLoadMoreConfig">
+							</z-paging-load-more>
+							<!-- #endif -->
+						</view>
+					</view>
+				</view>
+			</scroll-view>
+		</view>
+		<slot v-if="!usePageScroll&&$slots.bottom" name="bottom"></slot>
+		<view class="zp-page-scroll-bottom" v-else-if="usePageScroll&&$slots.bottom" :style="[{'bottom': `${windowBottom}px`}]">
+			<slot name="bottom"></slot>
+		</view>
+		<view v-if="showBackToTopClass" :class="backToTopClass" :style="[finalBackToTopStyle]" @click.stop="_backToTopClick">
+			<image class="zp-back-to-top-img" :src="backToTopImg.length?backToTopImg:base64BackToTop"></image>
+		</view>  
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<view :is="finalNvueSuperListIs">
+		<view ref="zp-page-scroll-top" :is="nViewIs" class="zp-page-scroll-top" v-if="$slots.top" :style="[{'top':`${windowTop}px`,'z-index':topZIndex}]">
+			<slot name="top"></slot>
+		</view>
+		<view ref="n-list" id="z-paging-nlist" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" :is="finalNvueListIs" alwaysScrollableVertical="true"
+			:fixFreezing="nFixFreezing" :show-scrollbar="showScrollbar" :loadmoreoffset="finalLowerThreshold"
+			:scrollable="scrollable&&scrollEnable" :bounce="nvueBounce" :column-count="nWaterfallColumnCount" :column-width="nWaterfallColumnWidth"
+			:column-gap="nWaterfallColumnGap" :left-gap="nWaterfallLeftGap" :right-gap="nWaterfallRightGap"
+			@loadmore="_nOnLoadmore" @scroll="_nOnScroll">
+			<refresh class="zp-n-refresh" v-if="finalNvueListIs!=='view'&&refresherEnabled&&!nShowRefresherReveal&&!useChatRecordMode" :display="nRefresherLoading?'show':'hide'" @refresh="_nOnRrefresh"
+				@pullingdown="_nOnPullingdown">
+				<view ref="zp-n-refresh-container" class="zp-n-refresh-container">
+					<!-- 下拉刷新view -->
+					<slot v-if="zScopedSlots.refresher" :refresherStatus="refresherStatus" name="refresher" />
+					<z-paging-refresh ref="refresh" v-else :refresherStatus="refresherStatus" :defaultThemeStyle="finalRefresherThemeStyle"
+						:refresherDefaultText="finalRefresherDefaultText" :refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText" 
+						:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
+				</view>
+			</refresh>
+			<view ref="zp-n-list-top-tag" class="zp-n-list-top-tag" :is="nViewIs"></view>
+			<view v-if="nShowRefresherReveal" ref="zp-n-list-refresher-reveal" :style="[{transform:`translateY(-${nShowRefresherRevealHeight}px)`,height:'0px'}]" :is="nViewIs">
+				<slot v-if="zScopedSlots.refresher" :refresherStatus="refresherStatus" name="refresher" />
+				<z-paging-refresh ref="refresh" v-else :refresherStatus="refresherStatus" :defaultThemeStyle="finalRefresherThemeStyle"
+					:refresherDefaultText="finalRefresherDefaultText" :refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText" 
+					:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
+			</view>
+			<slot />
+			<!-- 空数据图 -->
+			<view style="flex: 1;" key="z-paging-empty-view" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" v-if="showEmpty" :is="finalNvueListIs==='scroller'?'view':finalNvueListIs==='waterfall'?'header':'cell'">
+				<view class="zp-empty-view">
+					<slot v-if="$slots.empty" name="empty" />
+					<z-paging-empty-view v-else :emptyViewImg="finalEmptyViewImg" :emptyViewText="finalEmptyViewText" :showEmptyViewReload="finalShowEmptyViewReload" :emptyViewReloadText="finalEmptyViewReloadText" :isLoadFailed="isLoadFailed" :emptyViewStyle="emptyViewStyle" :emptyViewTitleStyle="emptyViewTitleStyle" :emptyViewImgStyle="emptyViewImgStyle" :emptyViewReloadStyle="emptyViewReloadStyle" :emptyViewZIndex="emptyViewZIndex" @reload="_emptyViewReload">
+					</z-paging-empty-view>
+				</view>
+			</view>
+			<view ref="zp-n-list-bottom-tag" class="zp-n-list-bottom-tag" is="header"></view>
+			<!-- 全屏 -->
+			<view style="flex: 1;" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" v-if="$slots.loading&&!firstPageLoaded&&(autoHideLoadingAfterFirstLoaded?!pagingLoaded:true)&&loading" :is="finalNvueListIs==='scroller'?'view':finalNvueListIs==='waterfall'?'header':'cell'">
+				<slot name="loading" />
+			</view>
+			<!-- 上拉加载更多view -->
+			<view :is="nViewIs">
+				<view v-if="useChatRecordMode">
+					<view v-if="loadingStatus!==2&&realTotalData.length">
+						<slot v-if="$slots.chatLoading"
+							name="chatLoading" />
+						<view v-else class="zp-chat-record-loading-container">
+							<text v-if="loadingStatus!==1" @click="_scrollToUpper()"
+								:class="defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{chatRecordLoadingMoreText}}</text>
+							<view>
+								<loading-indicator v-if="loadingStatus===1" :animating="true"
+									class="zp-loading-more-line-loading-image">
+								</loading-indicator>
+							</view>
+						</view>
+					</view>
+				</view>
+				<view :style="nLoadingMoreFixedHeight?{height:loadingMoreCustomStyle&&loadingMoreCustomStyle.height?loadingMoreCustomStyle.height:'80rpx'}:{}">
+					<slot v-if="_shouldShowLoading('loadingMoreDefault')" name="loadingMoreDefault" />
+					<slot v-else-if="_shouldShowLoading('loadingMoreLoading')" name="loadingMoreLoading" />
+					<slot v-else-if="_shouldShowLoading('loadingMoreNoMore')" name="loadingMoreNoMore" />
+					<slot v-else-if="_shouldShowLoading('loadingMoreFail')" name="loadingMoreFail" />
+					<z-paging-load-more @click.native="_onLoadingMore('click')"
+						v-else-if="_shouldShowLoading('loadingMoreCustom')" :zConfig="zPagingLoadMoreConfig">
+					</z-paging-load-more>
+				</view>
+			</view>
+		</view>
+		<slot name="bottom"></slot>
+		<view v-if="showBackToTopClass" :class="backToTopClass" :style="[finalBackToTopStyle]" @click.stop="_backToTopClick">
+			<image class="zp-back-to-top-img" :src="backToTopImg.length?backToTopImg:base64BackToTop"></image>
+		</view>
+	</view>
+	<!-- #endif -->
+</template>
+
+<script
+    src="./js/z-paging-main.js"></script>
+<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
+<script
+    src="./wxs/z-paging-wxs.wxs"
+    module="pagingWxs"
+    lang="wxs"
+></script>
+<!-- #endif -->
+
+<!-- #ifdef APP-VUE || H5 -->
+<script module="pagingRenderjs" lang="renderjs">
+	import pagingRenderjs from './wxs/z-paging-renderjs.js';
+	export default {
+		mixins: [pagingRenderjs]
+	}
+</script>
+<!-- #endif -->
+
+<style scoped>
+	@import "./css/z-paging-main.css";
+	@import "./css/z-paging-static.css";
+</style>

+ 80 - 0
uni_modules/z-paging/package.json

@@ -0,0 +1,80 @@
+{
+  "id": "z-paging",
+  "displayName": "超简单、低耦合!仅需两步轻松完成完整分页逻辑(下拉刷新、上拉加载更多)",
+  "version": "1.9.3",
+  "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"
+        }
+      }
+    }
+  }
+}

File diff suppressed because it is too large
+ 233 - 0
uni_modules/z-paging/readme.md