Commit 7399632e424ccf902533a6c2aafdf15a31bc8cff
1 parent
6dcb91e5
feat: 新增订单样式
Showing
51 changed files
with
7660 additions
and
1104 deletions
garbage-removal/src/components/z-paging-cell/z-paging-cell.vue
0 → 100644
| 1 | +<!-- z-paging --> | |
| 2 | +<!-- github地址:https://github.com/SmileZXLee/uni-z-paging --> | |
| 3 | +<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 --> | |
| 4 | +<!-- 反馈QQ群:790460711 --> | |
| 5 | + | |
| 6 | +<!-- z-paging-cell,用于在nvue中使用cell包裹,vue中使用view包裹 --> | |
| 7 | +<template> | |
| 8 | + <!-- #ifdef APP-NVUE --> | |
| 9 | + <cell :style="[cellStyle]"> | |
| 10 | + <slot /> | |
| 11 | + </cell> | |
| 12 | + <!-- #endif --> | |
| 13 | + <!-- #ifndef APP-NVUE --> | |
| 14 | + <view :style="[cellStyle]"> | |
| 15 | + <slot /> | |
| 16 | + </view> | |
| 17 | + <!-- #endif --> | |
| 18 | +</template> | |
| 19 | + | |
| 20 | +<script> | |
| 21 | + export default { | |
| 22 | + name: "z-paging-cell", | |
| 23 | + props: { | |
| 24 | + //cellStyle | |
| 25 | + cellStyle: { | |
| 26 | + type: Object, | |
| 27 | + default: function() { | |
| 28 | + return {} | |
| 29 | + } | |
| 30 | + } | |
| 31 | + } | |
| 32 | + } | |
| 33 | +</script> | |
| 34 | + | ... | ... |
garbage-removal/src/components/z-paging-empty-view/z-paging-empty-view.vue
0 → 100644
| 1 | +<!-- z-paging --> | |
| 2 | +<!-- github地址:https://github.com/SmileZXLee/uni-z-paging --> | |
| 3 | +<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 --> | |
| 4 | +<!-- 反馈QQ群:790460711 --> | |
| 5 | + | |
| 6 | +<!-- 空数据占位view,此组件支持easycom规范,可以在项目中直接引用 --> | |
| 7 | +<template> | |
| 8 | + <view :class="{'zp-container':true,'zp-container-fixed':emptyViewFixed}" :style="[finalEmptyViewStyle]" @click="emptyViewClick"> | |
| 9 | + <view class="zp-main"> | |
| 10 | + <image v-if="!emptyViewImg.length" class="zp-main-image" :style="[emptyViewImgStyle]" :src="emptyImg" /> | |
| 11 | + <image v-else class="zp-main-image" mode="aspectFit" :style="[emptyViewImgStyle]" :src="emptyViewImg" /> | |
| 12 | + <text class="zp-main-title" :style="[emptyViewTitleStyle]">{{emptyViewText}}</text> | |
| 13 | + <text v-if="showEmptyViewReload" class="zp-main-error-btn" :style="[emptyViewReloadStyle]" @click.stop="reloadClick">{{emptyViewReloadText}}</text> | |
| 14 | + </view> | |
| 15 | + </view> | |
| 16 | +</template> | |
| 17 | + | |
| 18 | +<script> | |
| 19 | + import zStatic from '../z-paging/js/z-paging-static' | |
| 20 | + export default { | |
| 21 | + name: "z-paging-empty-view", | |
| 22 | + data() { | |
| 23 | + return { | |
| 24 | + | |
| 25 | + }; | |
| 26 | + }, | |
| 27 | + props: { | |
| 28 | + //空数据描述文字 | |
| 29 | + emptyViewText: { | |
| 30 | + type: String, | |
| 31 | + default: '没有数据哦~' | |
| 32 | + }, | |
| 33 | + //空数据图片 | |
| 34 | + emptyViewImg: { | |
| 35 | + type: String, | |
| 36 | + default: '' | |
| 37 | + }, | |
| 38 | + //是否显示空数据图重新加载按钮 | |
| 39 | + showEmptyViewReload: { | |
| 40 | + type: Boolean, | |
| 41 | + default: false | |
| 42 | + }, | |
| 43 | + //空数据点击重新加载文字 | |
| 44 | + emptyViewReloadText: { | |
| 45 | + type: String, | |
| 46 | + default: '重新加载' | |
| 47 | + }, | |
| 48 | + //是否是加载失败 | |
| 49 | + isLoadFailed: { | |
| 50 | + type: Boolean, | |
| 51 | + default: false | |
| 52 | + }, | |
| 53 | + //空数据图样式 | |
| 54 | + emptyViewStyle: { | |
| 55 | + type: Object, | |
| 56 | + default: function() { | |
| 57 | + return {} | |
| 58 | + } | |
| 59 | + }, | |
| 60 | + //空数据图img样式 | |
| 61 | + emptyViewImgStyle: { | |
| 62 | + type: Object, | |
| 63 | + default: function() { | |
| 64 | + return {} | |
| 65 | + } | |
| 66 | + }, | |
| 67 | + //空数据图描述文字样式 | |
| 68 | + emptyViewTitleStyle: { | |
| 69 | + type: Object, | |
| 70 | + default: function() { | |
| 71 | + return {} | |
| 72 | + } | |
| 73 | + }, | |
| 74 | + //空数据图重新加载按钮样式 | |
| 75 | + emptyViewReloadStyle: { | |
| 76 | + type: Object, | |
| 77 | + default: function() { | |
| 78 | + return {} | |
| 79 | + } | |
| 80 | + }, | |
| 81 | + //空数据图z-index | |
| 82 | + emptyViewZIndex: { | |
| 83 | + type: Number, | |
| 84 | + default: 9 | |
| 85 | + }, | |
| 86 | + //空数据图片是否使用fixed布局并铺满z-paging | |
| 87 | + emptyViewFixed: { | |
| 88 | + type: Boolean, | |
| 89 | + default: true | |
| 90 | + } | |
| 91 | + }, | |
| 92 | + computed: { | |
| 93 | + emptyImg() { | |
| 94 | + return this.isLoadFailed ? zStatic.base64Error : zStatic.base64Empty; | |
| 95 | + }, | |
| 96 | + finalEmptyViewStyle(){ | |
| 97 | + this.emptyViewStyle['z-index'] = this.emptyViewZIndex; | |
| 98 | + return this.emptyViewStyle; | |
| 99 | + } | |
| 100 | + }, | |
| 101 | + methods: { | |
| 102 | + reloadClick() { | |
| 103 | + this.$emit('reload'); | |
| 104 | + }, | |
| 105 | + emptyViewClick() { | |
| 106 | + this.$emit('viewClick'); | |
| 107 | + } | |
| 108 | + } | |
| 109 | + } | |
| 110 | +</script> | |
| 111 | + | |
| 112 | +<style scoped> | |
| 113 | + .zp-container{ | |
| 114 | + /* #ifndef APP-NVUE */ | |
| 115 | + display: flex; | |
| 116 | + /* #endif */ | |
| 117 | + align-items: center; | |
| 118 | + justify-content: center; | |
| 119 | + } | |
| 120 | + .zp-container-fixed { | |
| 121 | + /* #ifndef APP-NVUE */ | |
| 122 | + position: absolute; | |
| 123 | + top: 0; | |
| 124 | + left: 0; | |
| 125 | + width: 100%; | |
| 126 | + height: 100%; | |
| 127 | + /* #endif */ | |
| 128 | + /* #ifdef APP-NVUE */ | |
| 129 | + flex: 1; | |
| 130 | + /* #endif */ | |
| 131 | + } | |
| 132 | + | |
| 133 | + .zp-main{ | |
| 134 | + /* #ifndef APP-NVUE */ | |
| 135 | + display: flex; | |
| 136 | + /* #endif */ | |
| 137 | + flex-direction: column; | |
| 138 | + align-items: center; | |
| 139 | + padding: 50rpx 0rpx; | |
| 140 | + } | |
| 141 | + | |
| 142 | + .zp-main-image { | |
| 143 | + width: 200rpx; | |
| 144 | + height: 200rpx; | |
| 145 | + } | |
| 146 | + | |
| 147 | + .zp-main-title { | |
| 148 | + font-size: 26rpx; | |
| 149 | + color: #aaaaaa; | |
| 150 | + text-align: center; | |
| 151 | + margin-top: 10rpx; | |
| 152 | + } | |
| 153 | + | |
| 154 | + .zp-main-error-btn { | |
| 155 | + font-size: 26rpx; | |
| 156 | + padding: 8rpx 24rpx; | |
| 157 | + border: solid 1px #dddddd; | |
| 158 | + border-radius: 6rpx; | |
| 159 | + color: #aaaaaa; | |
| 160 | + margin-top: 50rpx; | |
| 161 | + } | |
| 162 | +</style> | ... | ... |
garbage-removal/src/components/z-paging-swiper-item/z-paging-swiper-item.vue
0 → 100644
| 1 | +<!-- z-paging --> | |
| 2 | +<!-- github地址:https://github.com/SmileZXLee/uni-z-paging --> | |
| 3 | +<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 --> | |
| 4 | +<!-- 反馈QQ群:790460711 --> | |
| 5 | + | |
| 6 | +<!-- 滑动切换选项卡swiper-item,此组件支持easycom规范,可以在项目中直接引用 --> | |
| 7 | +<template> | |
| 8 | + <view class="zp-swiper-item-container"> | |
| 9 | + <z-paging ref="paging" :fixed="false" | |
| 10 | + :auto="false" :useVirtualList="useVirtualList" :useInnerList="useInnerList" :cellKeyName="cellKeyName" :innerListStyle="innerListStyle" | |
| 11 | + :preloadPage="preloadPage" :cellHeightMode="cellHeightMode" :virtualScrollFps="virtualScrollFps" :virtualListCol="virtualListCol" | |
| 12 | + @query="_queryList" @listChange="_updateList" style="height: 100%;"> | |
| 13 | + <slot /> | |
| 14 | + <template #header> | |
| 15 | + <slot name="header"/> | |
| 16 | + </template> | |
| 17 | + <template #cell="{item,index}"> | |
| 18 | + <slot name="cell" :item="item" :index="index"/> | |
| 19 | + </template> | |
| 20 | + <template #footer> | |
| 21 | + <slot name="footer"/> | |
| 22 | + </template> | |
| 23 | + </z-paging> | |
| 24 | + </view> | |
| 25 | +</template> | |
| 26 | + | |
| 27 | +<script> | |
| 28 | + import zPaging from '../z-paging/z-paging' | |
| 29 | + export default { | |
| 30 | + name: "z-paging-swiper-item", | |
| 31 | + components: { zPaging }, | |
| 32 | + data() { | |
| 33 | + return { | |
| 34 | + firstLoaded: false | |
| 35 | + } | |
| 36 | + }, | |
| 37 | + props: { | |
| 38 | + //当前组件的index,也就是当前组件是swiper中的第几个 | |
| 39 | + tabIndex: { | |
| 40 | + type: Number, | |
| 41 | + default: function() { | |
| 42 | + return 0 | |
| 43 | + } | |
| 44 | + }, | |
| 45 | + //当前swiper切换到第几个index | |
| 46 | + currentIndex: { | |
| 47 | + type: Number, | |
| 48 | + default: function() { | |
| 49 | + return 0 | |
| 50 | + } | |
| 51 | + }, | |
| 52 | + //是否使用虚拟列表,默认为否 | |
| 53 | + useVirtualList: { | |
| 54 | + type: Boolean, | |
| 55 | + default: false | |
| 56 | + }, | |
| 57 | + //是否在z-paging内部循环渲染列表(内置列表),默认为否。若use-virtual-list为true,则此项恒为true | |
| 58 | + useInnerList: { | |
| 59 | + type: Boolean, | |
| 60 | + default: false | |
| 61 | + }, | |
| 62 | + //内置列表cell的key名称,仅nvue有效,在nvue中开启use-inner-list时必须填此项 | |
| 63 | + cellKeyName: { | |
| 64 | + type: String, | |
| 65 | + default: '' | |
| 66 | + }, | |
| 67 | + //innerList样式 | |
| 68 | + innerListStyle: { | |
| 69 | + type: Object, | |
| 70 | + default: function() { | |
| 71 | + return {}; | |
| 72 | + } | |
| 73 | + }, | |
| 74 | + //预加载的列表可视范围(列表高度)页数,默认为12,即预加载当前页及上下各12页的cell。此数值越大,则虚拟列表中加载的dom越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题 | |
| 75 | + preloadPage: { | |
| 76 | + type: [Number, String], | |
| 77 | + default: 12 | |
| 78 | + }, | |
| 79 | + //虚拟列表cell高度模式,默认为fixed,也就是每个cell高度完全相同,将以第一个cell高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】。 | |
| 80 | + cellHeightMode: { | |
| 81 | + type: String, | |
| 82 | + default: 'fixed' | |
| 83 | + }, | |
| 84 | + //虚拟列表列数,默认为1。常用于每行有多列的情况,例如每行有2列数据,需要将此值设置为2 | |
| 85 | + virtualListCol: { | |
| 86 | + type: [Number, String], | |
| 87 | + default: 1 | |
| 88 | + }, | |
| 89 | + //虚拟列表scroll取样帧率,默认为60,过高可能出现卡顿等问题 | |
| 90 | + virtualScrollFps: { | |
| 91 | + type: [Number, String], | |
| 92 | + default: 60 | |
| 93 | + }, | |
| 94 | + }, | |
| 95 | + watch: { | |
| 96 | + currentIndex: { | |
| 97 | + handler(newVal, oldVal) { | |
| 98 | + if (newVal === this.tabIndex) { | |
| 99 | + //懒加载,当滑动到当前的item时,才去加载 | |
| 100 | + if (!this.firstLoaded) { | |
| 101 | + this.$nextTick(()=>{ | |
| 102 | + let delay = 5; | |
| 103 | + // #ifdef MP-TOUTIAO | |
| 104 | + delay = 100; | |
| 105 | + // #endif | |
| 106 | + setTimeout(() => { | |
| 107 | + this.$refs.paging.reload().catch(() => {}); | |
| 108 | + }, delay); | |
| 109 | + }) | |
| 110 | + } | |
| 111 | + } | |
| 112 | + }, | |
| 113 | + immediate: true | |
| 114 | + } | |
| 115 | + }, | |
| 116 | + methods: { | |
| 117 | + reload(data) { | |
| 118 | + return this.$refs.paging.reload(data); | |
| 119 | + }, | |
| 120 | + complete(data) { | |
| 121 | + this.firstLoaded = true; | |
| 122 | + return this.$refs.paging.complete(data); | |
| 123 | + }, | |
| 124 | + _queryList(pageNo, pageSize, from) { | |
| 125 | + this.$emit('query', pageNo, pageSize, from); | |
| 126 | + }, | |
| 127 | + _updateList(list) { | |
| 128 | + this.$emit('updateList', list); | |
| 129 | + } | |
| 130 | + } | |
| 131 | + } | |
| 132 | +</script> | |
| 133 | + | |
| 134 | +<style scoped> | |
| 135 | + .zp-swiper-item-container { | |
| 136 | + /* #ifndef APP-NVUE */ | |
| 137 | + height: 100%; | |
| 138 | + /* #endif */ | |
| 139 | + /* #ifdef APP-NVUE */ | |
| 140 | + flex: 1; | |
| 141 | + /* #endif */ | |
| 142 | + } | |
| 143 | +</style> | ... | ... |
garbage-removal/src/components/z-paging-swiper/z-paging-swiper.vue
0 → 100644
| 1 | +<!-- z-paging --> | |
| 2 | +<!-- github地址:https://github.com/SmileZXLee/uni-z-paging --> | |
| 3 | +<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 --> | |
| 4 | +<!-- 反馈QQ群:790460711 --> | |
| 5 | + | |
| 6 | +<!-- 滑动切换选项卡swiper容器,此组件支持easycom规范,可以在项目中直接引用 --> | |
| 7 | +<template> | |
| 8 | + <view :class="fixed?'zp-swiper-container zp-swiper-container-fixed':'zp-swiper-container'" :style="[finalSwiperStyle]"> | |
| 9 | + <!-- #ifndef APP-PLUS --> | |
| 10 | + <view v-if="cssSafeAreaInsetBottom===-1" class="zp-safe-area-inset-bottom"></view> | |
| 11 | + <!-- #endif --> | |
| 12 | + <slot v-if="zSlots.top" name="top" /> | |
| 13 | + <view class="zp-swiper-super"> | |
| 14 | + <view v-if="zSlots.left" :class="{'zp-swiper-left':true,'zp-absoulte':isOldWebView}"> | |
| 15 | + <slot name="left" /> | |
| 16 | + </view> | |
| 17 | + <view :class="{'zp-swiper':true,'zp-absoulte':isOldWebView}" :style="[swiperContentStyle]"> | |
| 18 | + <slot /> | |
| 19 | + </view> | |
| 20 | + <view v-if="zSlots.right" :class="{'zp-swiper-right':true,'zp-absoulte zp-right':isOldWebView}"> | |
| 21 | + <slot name="right" /> | |
| 22 | + </view> | |
| 23 | + </view> | |
| 24 | + <slot v-if="zSlots.bottom" name="bottom" /> | |
| 25 | + </view> | |
| 26 | +</template> | |
| 27 | + | |
| 28 | +<script> | |
| 29 | + import commonLayoutModule from '../z-paging/js/modules/common-layout' | |
| 30 | + | |
| 31 | + export default { | |
| 32 | + name: "z-paging-swiper", | |
| 33 | + mixins: [commonLayoutModule], | |
| 34 | + data() { | |
| 35 | + return { | |
| 36 | + swiperContentStyle: {} | |
| 37 | + }; | |
| 38 | + }, | |
| 39 | + props: { | |
| 40 | + //是否使用fixed布局,默认为是 | |
| 41 | + fixed: { | |
| 42 | + type: Boolean, | |
| 43 | + default: true | |
| 44 | + }, | |
| 45 | + //是否开启底部安全区域适配 | |
| 46 | + safeAreaInsetBottom: { | |
| 47 | + type: Boolean, | |
| 48 | + default: false | |
| 49 | + }, | |
| 50 | + //z-paging-swiper样式 | |
| 51 | + swiperStyle: { | |
| 52 | + type: Object, | |
| 53 | + default: function() { | |
| 54 | + return {}; | |
| 55 | + }, | |
| 56 | + } | |
| 57 | + }, | |
| 58 | + mounted() { | |
| 59 | + this.$nextTick(() => { | |
| 60 | + this.systemInfo = uni.getSystemInfoSync(); | |
| 61 | + }) | |
| 62 | + // #ifndef APP-PLUS | |
| 63 | + this._getCssSafeAreaInsetBottom(); | |
| 64 | + // #endif | |
| 65 | + this.updateLeftAndRightWidth(); | |
| 66 | + | |
| 67 | + this.swiperContentStyle = { 'flex': '1' }; | |
| 68 | + // #ifndef APP-NVUE | |
| 69 | + this.swiperContentStyle = { width: '100%',height: '100%' }; | |
| 70 | + // #endif | |
| 71 | + }, | |
| 72 | + computed: { | |
| 73 | + finalSwiperStyle() { | |
| 74 | + const swiperStyle = this.swiperStyle; | |
| 75 | + if (!this.systemInfo) return swiperStyle; | |
| 76 | + const windowTop = this.windowTop; | |
| 77 | + const windowBottom = this.systemInfo.windowBottom; | |
| 78 | + if (this.fixed) { | |
| 79 | + if (windowTop && !swiperStyle.top) { | |
| 80 | + swiperStyle.top = windowTop + 'px'; | |
| 81 | + } | |
| 82 | + if (!swiperStyle.bottom) { | |
| 83 | + let bottom = windowBottom || 0; | |
| 84 | + bottom += this.safeAreaInsetBottom ? this.safeAreaBottom : 0; | |
| 85 | + if (bottom > 0) { | |
| 86 | + swiperStyle.bottom = bottom + 'px'; | |
| 87 | + } | |
| 88 | + } | |
| 89 | + } | |
| 90 | + return swiperStyle; | |
| 91 | + } | |
| 92 | + }, | |
| 93 | + methods: { | |
| 94 | + //更新slot="left"和slot="right"宽度,当slot="left"或slot="right"宽度动态改变时调用 | |
| 95 | + updateLeftAndRightWidth() { | |
| 96 | + if (!this.isOldWebView) return; | |
| 97 | + this.$nextTick(() => this._updateLeftAndRightWidth(this.swiperContentStyle, 'zp-swiper')); | |
| 98 | + } | |
| 99 | + } | |
| 100 | + } | |
| 101 | +</script> | |
| 102 | + | |
| 103 | +<style scoped> | |
| 104 | + .zp-swiper-container { | |
| 105 | + /* #ifndef APP-NVUE */ | |
| 106 | + display: flex; | |
| 107 | + /* #endif */ | |
| 108 | + flex-direction: column; | |
| 109 | + flex: 1; | |
| 110 | + } | |
| 111 | + | |
| 112 | + .zp-swiper-container-fixed { | |
| 113 | + position: fixed; | |
| 114 | + /* #ifndef APP-NVUE */ | |
| 115 | + height: auto; | |
| 116 | + width: auto; | |
| 117 | + /* #endif */ | |
| 118 | + top: 0; | |
| 119 | + left: 0; | |
| 120 | + bottom: 0; | |
| 121 | + right: 0; | |
| 122 | + } | |
| 123 | + | |
| 124 | + .zp-safe-area-inset-bottom { | |
| 125 | + position: absolute; | |
| 126 | + /* #ifndef APP-PLUS */ | |
| 127 | + height: env(safe-area-inset-bottom); | |
| 128 | + /* #endif */ | |
| 129 | + } | |
| 130 | + | |
| 131 | + .zp-swiper-super { | |
| 132 | + flex: 1; | |
| 133 | + overflow: hidden; | |
| 134 | + position: relative; | |
| 135 | + /* #ifndef APP-NVUE */ | |
| 136 | + display: flex; | |
| 137 | + /* #endif */ | |
| 138 | + flex-direction: row; | |
| 139 | + } | |
| 140 | + | |
| 141 | + .zp-swiper-left,.zp-swiper-right{ | |
| 142 | + /* #ifndef APP-NVUE */ | |
| 143 | + height: 100%; | |
| 144 | + /* #endif */ | |
| 145 | + } | |
| 146 | + | |
| 147 | + .zp-swiper { | |
| 148 | + flex: 1; | |
| 149 | + /* #ifndef APP-NVUE */ | |
| 150 | + height: 100%; | |
| 151 | + width: 100%; | |
| 152 | + /* #endif */ | |
| 153 | + } | |
| 154 | + | |
| 155 | + .zp-absoulte { | |
| 156 | + /* #ifndef APP-NVUE */ | |
| 157 | + position: absolute; | |
| 158 | + top: 0; | |
| 159 | + width: auto; | |
| 160 | + /* #endif */ | |
| 161 | + } | |
| 162 | + | |
| 163 | + .zp-right{ | |
| 164 | + right: 0; | |
| 165 | + } | |
| 166 | + | |
| 167 | + .zp-swiper-item { | |
| 168 | + height: 100%; | |
| 169 | + } | |
| 170 | +</style> | ... | ... |
garbage-removal/src/components/z-paging/components/z-paging-load-more.vue
0 → 100644
| 1 | +<!-- [z-paging]上拉加载更多view --> | |
| 2 | +<template> | |
| 3 | + <view class="zp-l-container" :style="[c.customStyle]" @click="doClick"> | |
| 4 | + <template v-if="!c.hideContent"> | |
| 5 | + <text v-if="c.showNoMoreLine&&finalStatus===M.NoMore" class="zp-l-line" :style="[{backgroundColor:zTheme.line[ts]},c.noMoreLineCustomStyle]" /> | |
| 6 | + <!-- #ifndef APP-NVUE --> | |
| 7 | + <image v-if="finalStatus===M.Loading&&!!c.loadingIconCustomImage" | |
| 8 | + :src="c.loadingIconCustomImage" :style="[c.iconCustomStyle]" :class="{'zp-l-line-loading-custom-image':true,'zp-l-line-loading-custom-image-animated':c.loadingAnimated}" /> | |
| 9 | + <image v-if="finalStatus===M.Loading&&finalLoadingIconType==='flower'&&!c.loadingIconCustomImage.length" | |
| 10 | + class="zp-line-loading-image" :style="[c.iconCustomStyle]" :src="zTheme.flower[ts]" /> | |
| 11 | + <!-- #endif --> | |
| 12 | + <!-- #ifdef APP-NVUE --> | |
| 13 | + <view> | |
| 14 | + <loading-indicator v-if="finalStatus===M.Loading&&finalLoadingIconType!=='circle'" class="zp-line-loading-image" :style="[{color:zTheme.indicator[ts]}]" :animating="true" /> | |
| 15 | + </view> | |
| 16 | + <!-- #endif --> | |
| 17 | + <text v-if="finalStatus===M.Loading&&finalLoadingIconType==='circle'&&!c.loadingIconCustomImage.length" | |
| 18 | + class="zp-l-circle-loading-view" :style="[{borderColor:zTheme.circleBorder[ts],borderTopColor:zTheme.circleBorderTop[ts]},c.iconCustomStyle]" /> | |
| 19 | + <text class="zp-l-text" :style="[{color:zTheme.title[ts]},c.titleCustomStyle]">{{ownLoadingMoreText}}</text> | |
| 20 | + <text v-if="c.showNoMoreLine&&finalStatus===M.NoMore" class="zp-l-line" :style="[{backgroundColor:zTheme.line[ts]},c.noMoreLineCustomStyle]" /> | |
| 21 | + </template> | |
| 22 | + </view> | |
| 23 | +</template> | |
| 24 | +<script> | |
| 25 | + import zStatic from '../js/z-paging-static' | |
| 26 | + import Enum from '../js/z-paging-enum' | |
| 27 | + export default { | |
| 28 | + name: 'z-paging-load-more', | |
| 29 | + data() { | |
| 30 | + return { | |
| 31 | + M: Enum.More, | |
| 32 | + zTheme: { | |
| 33 | + title: { white: '#efefef', black: '#a4a4a4' }, | |
| 34 | + line: { white: '#efefef', black: '#eeeeee' }, | |
| 35 | + circleBorder: { white: '#aaaaaa', black: '#c8c8c8' }, | |
| 36 | + circleBorderTop: { white: '#ffffff', black: '#444444' }, | |
| 37 | + flower: { white: zStatic.base64FlowerWhite, black: zStatic.base64Flower }, | |
| 38 | + indicator: { white: '#eeeeee', black: '#777777' } | |
| 39 | + } | |
| 40 | + }; | |
| 41 | + }, | |
| 42 | + props: ['zConfig'], | |
| 43 | + computed: { | |
| 44 | + ts() { | |
| 45 | + return this.c.defaultThemeStyle; | |
| 46 | + }, | |
| 47 | + c() { | |
| 48 | + return this.zConfig || {}; | |
| 49 | + }, | |
| 50 | + ownLoadingMoreText() { | |
| 51 | + const statusTextArr = [this.c.defaultText,this.c.loadingText,this.c.noMoreText,this.c.failText]; | |
| 52 | + return statusTextArr[this.finalStatus]; | |
| 53 | + }, | |
| 54 | + finalStatus() { | |
| 55 | + if (this.c.defaultAsLoading && this.c.status === this.M.Default) return this.M.Loading; | |
| 56 | + return this.c.status; | |
| 57 | + }, | |
| 58 | + finalLoadingIconType() { | |
| 59 | + // #ifdef APP-NVUE | |
| 60 | + return 'flower'; | |
| 61 | + // #endif | |
| 62 | + return this.c.loadingIconType; | |
| 63 | + } | |
| 64 | + }, | |
| 65 | + methods: { | |
| 66 | + doClick() { | |
| 67 | + this.$emit('doClick'); | |
| 68 | + } | |
| 69 | + } | |
| 70 | + } | |
| 71 | +</script> | |
| 72 | + | |
| 73 | +<style scoped> | |
| 74 | + @import "../css/z-paging-static.css"; | |
| 75 | + | |
| 76 | + .zp-l-container { | |
| 77 | + height: 80rpx; | |
| 78 | + font-size: 27rpx; | |
| 79 | + /* #ifndef APP-NVUE */ | |
| 80 | + clear: both; | |
| 81 | + display: flex; | |
| 82 | + /* #endif */ | |
| 83 | + flex-direction: row; | |
| 84 | + align-items: center; | |
| 85 | + justify-content: center; | |
| 86 | + } | |
| 87 | + | |
| 88 | + .zp-l-line-loading-custom-image { | |
| 89 | + color: #a4a4a4; | |
| 90 | + margin-right: 8rpx; | |
| 91 | + width: 28rpx; | |
| 92 | + height: 28rpx; | |
| 93 | + } | |
| 94 | + | |
| 95 | + .zp-l-line-loading-custom-image-animated{ | |
| 96 | + /* #ifndef APP-NVUE */ | |
| 97 | + animation: loading-circle 1s linear infinite; | |
| 98 | + /* #endif */ | |
| 99 | + } | |
| 100 | + | |
| 101 | + .zp-l-circle-loading-view { | |
| 102 | + margin-right: 8rpx; | |
| 103 | + width: 23rpx; | |
| 104 | + height: 23rpx; | |
| 105 | + border: 3rpx solid #dddddd; | |
| 106 | + border-radius: 50%; | |
| 107 | + /* #ifndef APP-NVUE */ | |
| 108 | + animation: loading-circle 1s linear infinite; | |
| 109 | + /* #endif */ | |
| 110 | + /* #ifdef APP-NVUE */ | |
| 111 | + width: 30rpx; | |
| 112 | + height: 30rpx; | |
| 113 | + /* #endif */ | |
| 114 | + } | |
| 115 | + | |
| 116 | + .zp-l-text { | |
| 117 | + /* #ifdef APP-NVUE */ | |
| 118 | + font-size: 30rpx; | |
| 119 | + margin: 0rpx 10rpx; | |
| 120 | + /* #endif */ | |
| 121 | + } | |
| 122 | + | |
| 123 | + .zp-l-line { | |
| 124 | + height: 1px; | |
| 125 | + width: 100rpx; | |
| 126 | + margin: 0rpx 10rpx; | |
| 127 | + } | |
| 128 | + | |
| 129 | + /* #ifndef APP-NVUE */ | |
| 130 | + @keyframes loading-circle { | |
| 131 | + 0% { | |
| 132 | + -webkit-transform: rotate(0deg); | |
| 133 | + transform: rotate(0deg); | |
| 134 | + } | |
| 135 | + 100% { | |
| 136 | + -webkit-transform: rotate(360deg); | |
| 137 | + transform: rotate(360deg); | |
| 138 | + } | |
| 139 | + } | |
| 140 | + /* #endif */ | |
| 141 | +</style> | ... | ... |
garbage-removal/src/components/z-paging/components/z-paging-refresh.vue
0 → 100644
| 1 | +<!-- [z-paging]下拉刷新view --> | |
| 2 | +<template> | |
| 3 | + <view style="height: 100%;"> | |
| 4 | + <view :class="showUpdateTime?'zp-r-container zp-r-container-padding':'zp-r-container'"> | |
| 5 | + <view class="zp-r-left"> | |
| 6 | + <image v-if="status!==R.Loading" :class="leftImageClass" :style="[leftImageStyle,imgStyle]" :src="leftImageSrc" /> | |
| 7 | + <!-- #ifndef APP-NVUE --> | |
| 8 | + <image v-else :class="{'zp-line-loading-image':refreshingAnimated,'zp-r-left-image':true}" :style="[leftImageStyle,imgStyle]" :src="leftImageSrc" /> | |
| 9 | + <!-- #endif --> | |
| 10 | + <!-- #ifdef APP-NVUE --> | |
| 11 | + <view v-else :style="[{'margin-right':showUpdateTime?'18rpx':'12rpx'}]"> | |
| 12 | + <loading-indicator :class="isIos?'zp-loading-image-ios':'zp-loading-image-android'" | |
| 13 | + :style="[{color:zTheme.indicator[ts]},imgStyle]" :animating="true" /> | |
| 14 | + </view> | |
| 15 | + <!-- #endif --> | |
| 16 | + </view> | |
| 17 | + <view class="zp-r-right"> | |
| 18 | + <text class="zp-r-right-text" :style="[rightTextStyle,titleStyle]">{{currentTitle}}</text> | |
| 19 | + <text v-if="showUpdateTime&&refresherTimeText.length" class="zp-r-right-text zp-r-right-time-text" :style="[rightTextStyle,updateTimeStyle]"> | |
| 20 | + {{refresherTimeText}} | |
| 21 | + </text> | |
| 22 | + </view> | |
| 23 | + </view> | |
| 24 | + </view> | |
| 25 | +</template> | |
| 26 | +<script> | |
| 27 | + import zStatic from '../js/z-paging-static' | |
| 28 | + import u from '../js/z-paging-utils' | |
| 29 | + import Enum from '../js/z-paging-enum' | |
| 30 | + | |
| 31 | + export default { | |
| 32 | + name: 'z-paging-refresh', | |
| 33 | + data() { | |
| 34 | + return { | |
| 35 | + R: Enum.Refresher, | |
| 36 | + isIos: uni.getSystemInfoSync().platform === 'ios', | |
| 37 | + refresherTimeText: '', | |
| 38 | + zTheme: { | |
| 39 | + title: { white: '#efefef', black: '#555555' }, | |
| 40 | + arrow: { white: zStatic.base64ArrowWhite, black: zStatic.base64Arrow }, | |
| 41 | + flower: { white: zStatic.base64FlowerWhite, black: zStatic.base64Flower }, | |
| 42 | + success: { white: zStatic.base64SuccessWhite, black: zStatic.base64Success }, | |
| 43 | + indicator: { white: '#eeeeee', black: '#777777' } | |
| 44 | + } | |
| 45 | + }; | |
| 46 | + }, | |
| 47 | + props: ['status', 'defaultThemeStyle', 'defaultText', 'pullingText', 'refreshingText', 'completeText', 'defaultImg', 'pullingImg', | |
| 48 | + 'refreshingImg', 'completeImg', 'refreshingAnimated', 'showUpdateTime', 'updateTimeKey', 'imgStyle', 'titleStyle', 'updateTimeStyle', 'updateTimeTextMap' | |
| 49 | + ], | |
| 50 | + computed: { | |
| 51 | + ts() { | |
| 52 | + return this.defaultThemeStyle; | |
| 53 | + }, | |
| 54 | + statusTextArr() { | |
| 55 | + this.updateTime(); | |
| 56 | + return [this.defaultText,this.pullingText,this.refreshingText,this.completeText]; | |
| 57 | + }, | |
| 58 | + currentTitle() { | |
| 59 | + return this.statusTextArr[this.status] || this.defaultText; | |
| 60 | + }, | |
| 61 | + leftImageClass() { | |
| 62 | + if (this.status === this.R.Complete) return 'zp-r-left-image-pre-size'; | |
| 63 | + return `zp-r-left-image zp-r-left-image-pre-size ${this.status === this.R.Default ? 'zp-r-arrow-down' : 'zp-r-arrow-top'}`; | |
| 64 | + }, | |
| 65 | + leftImageStyle() { | |
| 66 | + const showUpdateTime = this.showUpdateTime; | |
| 67 | + const size = showUpdateTime ? '36rpx' : '30rpx'; | |
| 68 | + return {width: size,height: size,'margin-right': showUpdateTime ? '20rpx' : '9rpx'}; | |
| 69 | + }, | |
| 70 | + leftImageSrc() { | |
| 71 | + const R = this.R; | |
| 72 | + const status = this.status; | |
| 73 | + if (status === R.Default) { | |
| 74 | + if (!!this.defaultImg) return this.defaultImg; | |
| 75 | + return this.zTheme.arrow[this.ts]; | |
| 76 | + } else if (status === R.ReleaseToRefresh) { | |
| 77 | + if (!!this.pullingImg) return this.pullingImg; | |
| 78 | + if (!!this.defaultImg) return this.defaultImg; | |
| 79 | + return this.zTheme.arrow[this.ts]; | |
| 80 | + } else if (status === R.Loading) { | |
| 81 | + if (!!this.refreshingImg) return this.refreshingImg; | |
| 82 | + return this.zTheme.flower[this.ts];; | |
| 83 | + } else if (status === R.Complete) { | |
| 84 | + if (!!this.completeImg) return this.completeImg; | |
| 85 | + return this.zTheme.success[this.ts];; | |
| 86 | + } | |
| 87 | + return ''; | |
| 88 | + }, | |
| 89 | + rightTextStyle() { | |
| 90 | + let stl = {}; | |
| 91 | + // #ifdef APP-NVUE | |
| 92 | + const textHeight = this.showUpdateTime ? '40rpx' : '80rpx'; | |
| 93 | + stl = {'height': textHeight, 'line-height': textHeight} | |
| 94 | + // #endif | |
| 95 | + stl['color'] = this.zTheme.title[this.ts]; | |
| 96 | + return stl; | |
| 97 | + } | |
| 98 | + }, | |
| 99 | + methods: { | |
| 100 | + updateTime() { | |
| 101 | + if (this.showUpdateTime) { | |
| 102 | + this.refresherTimeText = u.getRefesrherFormatTimeByKey(this.updateTimeKey, this.updateTimeTextMap); | |
| 103 | + } | |
| 104 | + } | |
| 105 | + } | |
| 106 | + } | |
| 107 | +</script> | |
| 108 | + | |
| 109 | +<style scoped> | |
| 110 | + @import "../css/z-paging-static.css"; | |
| 111 | + | |
| 112 | + .zp-r-container { | |
| 113 | + /* #ifndef APP-NVUE */ | |
| 114 | + display: flex; | |
| 115 | + height: 100%; | |
| 116 | + /* #endif */ | |
| 117 | + flex-direction: row; | |
| 118 | + justify-content: center; | |
| 119 | + align-items: center; | |
| 120 | + } | |
| 121 | + | |
| 122 | + .zp-r-container-padding { | |
| 123 | + /* #ifdef APP-NVUE */ | |
| 124 | + padding: 15rpx 0rpx; | |
| 125 | + /* #endif */ | |
| 126 | + } | |
| 127 | + | |
| 128 | + .zp-r-left { | |
| 129 | + /* #ifndef APP-NVUE */ | |
| 130 | + display: flex; | |
| 131 | + /* #endif */ | |
| 132 | + flex-direction: row; | |
| 133 | + align-items: center; | |
| 134 | + overflow: hidden; | |
| 135 | + /* #ifdef MP-ALIPAY */ | |
| 136 | + margin-top: -4rpx; | |
| 137 | + /* #endif */ | |
| 138 | + } | |
| 139 | + | |
| 140 | + .zp-r-left-image { | |
| 141 | + transition-duration: .2s; | |
| 142 | + transition-property: transform; | |
| 143 | + color: #666666; | |
| 144 | + } | |
| 145 | + | |
| 146 | + .zp-r-left-image-pre-size{ | |
| 147 | + /* #ifndef APP-NVUE */ | |
| 148 | + width: 30rpx; | |
| 149 | + height: 30rpx; | |
| 150 | + overflow: hidden; | |
| 151 | + /* #endif */ | |
| 152 | + } | |
| 153 | + | |
| 154 | + .zp-r-arrow-top { | |
| 155 | + transform: rotate(0deg); | |
| 156 | + } | |
| 157 | + | |
| 158 | + .zp-r-arrow-down { | |
| 159 | + transform: rotate(180deg); | |
| 160 | + } | |
| 161 | + | |
| 162 | + .zp-r-right { | |
| 163 | + font-size: 27rpx; | |
| 164 | + /* #ifndef APP-NVUE */ | |
| 165 | + display: flex; | |
| 166 | + /* #endif */ | |
| 167 | + flex-direction: column; | |
| 168 | + align-items: center; | |
| 169 | + justify-content: center; | |
| 170 | + } | |
| 171 | + | |
| 172 | + .zp-r-right-text { | |
| 173 | + /* #ifdef APP-NVUE */ | |
| 174 | + font-size: 28rpx; | |
| 175 | + /* #endif */ | |
| 176 | + } | |
| 177 | + | |
| 178 | + .zp-r-right-time-text { | |
| 179 | + margin-top: 10rpx; | |
| 180 | + font-size: 24rpx; | |
| 181 | + } | |
| 182 | +</style> | ... | ... |
garbage-removal/src/components/z-paging/config/index.js
0 → 100644
garbage-removal/src/components/z-paging/css/z-paging-main.css
0 → 100644
| 1 | +/* [z-paging]公共css*/ | |
| 2 | + | |
| 3 | +.z-paging-content { | |
| 4 | + position: relative; | |
| 5 | + /* #ifndef APP-NVUE */ | |
| 6 | + display: flex; | |
| 7 | + width: 100%; | |
| 8 | + height: 100%; | |
| 9 | + overflow: hidden; | |
| 10 | + /* #endif */ | |
| 11 | + flex-direction: column; | |
| 12 | +} | |
| 13 | + | |
| 14 | +.z-paging-content-fixed, .zp-loading-fixed { | |
| 15 | + position: fixed; | |
| 16 | + /* #ifndef APP-NVUE */ | |
| 17 | + height: auto; | |
| 18 | + width: auto; | |
| 19 | + /* #endif */ | |
| 20 | + top: 0; | |
| 21 | + left: 0; | |
| 22 | + bottom: 0; | |
| 23 | + right: 0; | |
| 24 | +} | |
| 25 | + | |
| 26 | +.zp-page-top,.zp-page-bottom { | |
| 27 | + /* #ifndef APP-NVUE */ | |
| 28 | + width: auto; | |
| 29 | + /* #endif */ | |
| 30 | + position: fixed; | |
| 31 | + left: 0; | |
| 32 | + right: 0; | |
| 33 | + z-index: 999; | |
| 34 | +} | |
| 35 | + | |
| 36 | +.zp-page-left,.zp-page-right{ | |
| 37 | + /* #ifndef APP-NVUE */ | |
| 38 | + height: 100%; | |
| 39 | + /* #endif */ | |
| 40 | +} | |
| 41 | + | |
| 42 | +.zp-scroll-view-super { | |
| 43 | + flex: 1; | |
| 44 | + overflow: hidden; | |
| 45 | + position: relative; | |
| 46 | +} | |
| 47 | + | |
| 48 | +.zp-view-super{ | |
| 49 | + /* #ifndef APP-NVUE */ | |
| 50 | + display: flex; | |
| 51 | + /* #endif */ | |
| 52 | + flex-direction: row; | |
| 53 | +} | |
| 54 | + | |
| 55 | +.zp-scroll-view-container,.zp-scroll-view { | |
| 56 | + position: relative; | |
| 57 | + /* #ifndef APP-NVUE */ | |
| 58 | + height: 100%; | |
| 59 | + width: 100%; | |
| 60 | + /* #endif */ | |
| 61 | +} | |
| 62 | + | |
| 63 | +.zp-absoulte{ | |
| 64 | + /* #ifndef APP-NVUE */ | |
| 65 | + position: absolute; | |
| 66 | + top: 0; | |
| 67 | + width: auto; | |
| 68 | + /* #endif */ | |
| 69 | +} | |
| 70 | + | |
| 71 | +.zp-right{ | |
| 72 | + right: 0; | |
| 73 | +} | |
| 74 | + | |
| 75 | +.zp-scroll-view-absolute { | |
| 76 | + position: absolute; | |
| 77 | + top: 0; | |
| 78 | + left: 0; | |
| 79 | +} | |
| 80 | + | |
| 81 | +/* #ifndef APP-NVUE */ | |
| 82 | +.zp-scroll-view-hide-scrollbar ::-webkit-scrollbar { | |
| 83 | + display: none; | |
| 84 | + -webkit-appearance: none; | |
| 85 | + width: 0 !important; | |
| 86 | + height: 0 !important; | |
| 87 | + background: transparent; | |
| 88 | +} | |
| 89 | +/* #endif */ | |
| 90 | + | |
| 91 | +.zp-paging-touch-view { | |
| 92 | + width: 100%; | |
| 93 | + height: 100%; | |
| 94 | + position: relative; | |
| 95 | +} | |
| 96 | + | |
| 97 | +.zp-fixed-bac-view { | |
| 98 | + position: absolute; | |
| 99 | + width: 100%; | |
| 100 | + top: 0; | |
| 101 | + left: 0; | |
| 102 | + height: 200px; | |
| 103 | +} | |
| 104 | + | |
| 105 | +.zp-paging-main { | |
| 106 | + height: 100%; | |
| 107 | + /* #ifndef APP-NVUE */ | |
| 108 | + display: flex; | |
| 109 | + /* #endif */ | |
| 110 | + flex-direction: column; | |
| 111 | +} | |
| 112 | + | |
| 113 | +.zp-paging-container { | |
| 114 | + flex: 1; | |
| 115 | + position: relative; | |
| 116 | + /* #ifndef APP-NVUE */ | |
| 117 | + display: flex; | |
| 118 | + /* #endif */ | |
| 119 | + flex-direction: column; | |
| 120 | +} | |
| 121 | + | |
| 122 | +.zp-chat-record-loading-container { | |
| 123 | + /* #ifndef APP-NVUE */ | |
| 124 | + display: flex; | |
| 125 | + width: 100%; | |
| 126 | + /* #endif */ | |
| 127 | + /* #ifdef APP-NVUE */ | |
| 128 | + width: 750rpx; | |
| 129 | + /* #endif */ | |
| 130 | + align-items: center; | |
| 131 | + justify-content: center; | |
| 132 | + height: 60rpx; | |
| 133 | + font-size: 26rpx; | |
| 134 | +} | |
| 135 | + | |
| 136 | +.zp-chat-record-loading-custom-image { | |
| 137 | + width: 35rpx; | |
| 138 | + height: 35rpx; | |
| 139 | + /* #ifndef APP-NVUE */ | |
| 140 | + animation: loading-flower 1s linear infinite; | |
| 141 | + /* #endif */ | |
| 142 | +} | |
| 143 | + | |
| 144 | +.zp-custom-refresher-container { | |
| 145 | + overflow: hidden; | |
| 146 | +} | |
| 147 | + | |
| 148 | +.zp-custom-refresher-refresh { | |
| 149 | + /* #ifndef APP-NVUE */ | |
| 150 | + display: block; | |
| 151 | + /* #endif */ | |
| 152 | +} | |
| 153 | + | |
| 154 | +.zp-back-to-top { | |
| 155 | + width: 76rpx; | |
| 156 | + height: 76rpx; | |
| 157 | + z-index: 999; | |
| 158 | + position: absolute; | |
| 159 | + bottom: 0rpx; | |
| 160 | + right: 25rpx; | |
| 161 | + transition-duration: .3s; | |
| 162 | + transition-property: opacity; | |
| 163 | +} | |
| 164 | + | |
| 165 | +.zp-back-to-top-show { | |
| 166 | + opacity: 1; | |
| 167 | +} | |
| 168 | + | |
| 169 | +.zp-back-to-top-hide { | |
| 170 | + opacity: 0; | |
| 171 | +} | |
| 172 | + | |
| 173 | +.zp-back-to-top-img { | |
| 174 | + /* #ifndef APP-NVUE */ | |
| 175 | + width: 100%; | |
| 176 | + height: 100%; | |
| 177 | + /* #endif */ | |
| 178 | + /* #ifdef APP-NVUE */ | |
| 179 | + flex: 1; | |
| 180 | + /* #endif */ | |
| 181 | + z-index: 999; | |
| 182 | +} | |
| 183 | + | |
| 184 | +.zp-empty-view { | |
| 185 | + /* #ifdef APP-NVUE */ | |
| 186 | + height: 100%; | |
| 187 | + /* #endif */ | |
| 188 | + flex: 1; | |
| 189 | +} | |
| 190 | + | |
| 191 | +.zp-empty-view-center { | |
| 192 | + /* #ifndef APP-NVUE */ | |
| 193 | + display: flex; | |
| 194 | + /* #endif */ | |
| 195 | + flex-direction: column; | |
| 196 | + align-items: center; | |
| 197 | + justify-content: center; | |
| 198 | +} | |
| 199 | + | |
| 200 | +.zp-loading-fixed { | |
| 201 | + z-index: 9999; | |
| 202 | +} | |
| 203 | + | |
| 204 | +.zp-safe-area-inset-bottom { | |
| 205 | + position: absolute; | |
| 206 | + /* #ifndef APP-PLUS */ | |
| 207 | + height: env(safe-area-inset-bottom); | |
| 208 | + /* #endif */ | |
| 209 | +} | |
| 210 | + | |
| 211 | +.zp-n-refresh-container { | |
| 212 | + /* #ifndef APP-NVUE */ | |
| 213 | + display: flex; | |
| 214 | + /* #endif */ | |
| 215 | + justify-content: center; | |
| 216 | + width: 750rpx; | |
| 217 | +} | |
| 218 | + | |
| 219 | +.zp-n-list-container{ | |
| 220 | + /* #ifndef APP-NVUE */ | |
| 221 | + display: flex; | |
| 222 | + /* #endif */ | |
| 223 | + flex-direction: row; | |
| 224 | + flex: 1; | |
| 225 | +} | ... | ... |
garbage-removal/src/components/z-paging/css/z-paging-static.css
0 → 100644
| 1 | +/* [z-paging]公用的静态css资源 */ | |
| 2 | + | |
| 3 | +.zp-line-loading-image { | |
| 4 | + margin-right: 8rpx; | |
| 5 | + width: 28rpx; | |
| 6 | + height: 28rpx; | |
| 7 | + /* #ifndef APP-NVUE */ | |
| 8 | + animation: loading-flower 1s steps(12) infinite; | |
| 9 | + /* #endif */ | |
| 10 | + color: #666666; | |
| 11 | +} | |
| 12 | + | |
| 13 | +.zp-loading-image-ios{ | |
| 14 | + width: 20px; | |
| 15 | + height: 20px; | |
| 16 | +} | |
| 17 | + | |
| 18 | +.zp-loading-image-android{ | |
| 19 | + width: 32rpx; | |
| 20 | + height: 32rpx; | |
| 21 | +} | |
| 22 | + | |
| 23 | +/* #ifndef APP-NVUE */ | |
| 24 | +@keyframes loading-flower { | |
| 25 | + 0% { | |
| 26 | + -webkit-transform: rotate(0deg); | |
| 27 | + transform: rotate(0deg); | |
| 28 | + } | |
| 29 | + to { | |
| 30 | + -webkit-transform: rotate(1turn); | |
| 31 | + transform: rotate(1turn); | |
| 32 | + } | |
| 33 | +} | |
| 34 | +/* #endif */ | |
| 35 | + | ... | ... |
garbage-removal/src/components/z-paging/i18n/en.json
0 → 100644
| 1 | +{ | |
| 2 | + "zp.refresher.default": "Pull down to refresh", | |
| 3 | + "zp.refresher.pulling": "Release to refresh", | |
| 4 | + "zp.refresher.refreshing": "Refreshing...", | |
| 5 | + "zp.refresher.complete": "Refresh succeeded", | |
| 6 | + | |
| 7 | + "zp.loadingMore.default": "Click to load more", | |
| 8 | + "zp.loadingMore.loading": "Loading...", | |
| 9 | + "zp.loadingMore.noMore": "No more data", | |
| 10 | + "zp.loadingMore.fail": "Load failed,click to reload", | |
| 11 | + | |
| 12 | + "zp.emptyView.title": "No data", | |
| 13 | + "zp.emptyView.reload": "Reload", | |
| 14 | + "zp.emptyView.error": "Sorry,load failed", | |
| 15 | + | |
| 16 | + "zp.refresherUpdateTime.title": "Last update: ", | |
| 17 | + "zp.refresherUpdateTime.none": "None", | |
| 18 | + "zp.refresherUpdateTime.today": "Today", | |
| 19 | + "zp.refresherUpdateTime.yesterday": "Yesterday", | |
| 20 | + | |
| 21 | + "zp.systemLoading.title": "Loading..." | |
| 22 | +} | ... | ... |
garbage-removal/src/components/z-paging/i18n/index.js
0 → 100644
garbage-removal/src/components/z-paging/i18n/zh-Hans.json
0 → 100644
| 1 | +{ | |
| 2 | + "zp.refresher.default": "继续下拉刷新", | |
| 3 | + "zp.refresher.pulling": "松开立即刷新", | |
| 4 | + "zp.refresher.refreshing": "正在刷新...", | |
| 5 | + "zp.refresher.complete": "刷新成功", | |
| 6 | + | |
| 7 | + "zp.loadingMore.default": "点击加载更多", | |
| 8 | + "zp.loadingMore.loading": "正在加载...", | |
| 9 | + "zp.loadingMore.noMore": "没有更多了", | |
| 10 | + "zp.loadingMore.fail": "加载失败,点击重新加载", | |
| 11 | + | |
| 12 | + "zp.emptyView.title": "没有数据哦~", | |
| 13 | + "zp.emptyView.reload": "重新加载", | |
| 14 | + "zp.emptyView.error": "很抱歉,加载失败", | |
| 15 | + | |
| 16 | + "zp.refresherUpdateTime.title": "最后更新:", | |
| 17 | + "zp.refresherUpdateTime.none": "无", | |
| 18 | + "zp.refresherUpdateTime.today": "今天", | |
| 19 | + "zp.refresherUpdateTime.yesterday": "昨天", | |
| 20 | + | |
| 21 | + "zp.systemLoading.title": "加载中..." | |
| 22 | +} | ... | ... |
garbage-removal/src/components/z-paging/i18n/zh-Hant.json
0 → 100644
| 1 | +{ | |
| 2 | + "zp.refresher.default": "繼續下拉重繪", | |
| 3 | + "zp.refresher.pulling": "鬆開立即重繪", | |
| 4 | + "zp.refresher.refreshing": "正在重繪...", | |
| 5 | + "zp.refresher.complete": "重繪成功", | |
| 6 | + | |
| 7 | + "zp.loadingMore.default": "點擊加載更多", | |
| 8 | + "zp.loadingMore.loading": "正在加載...", | |
| 9 | + "zp.loadingMore.noMore": "沒有更多了", | |
| 10 | + "zp.loadingMore.fail": "加載失敗,點擊重新加載", | |
| 11 | + | |
| 12 | + "zp.emptyView.title": "沒有數據哦~", | |
| 13 | + "zp.emptyView.reload": "重新加載", | |
| 14 | + "zp.emptyView.error": "很抱歉,加載失敗", | |
| 15 | + | |
| 16 | + "zp.refresherUpdateTime.title": "最後更新:", | |
| 17 | + "zp.refresherUpdateTime.none": "無", | |
| 18 | + "zp.refresherUpdateTime.today": "今天", | |
| 19 | + "zp.refresherUpdateTime.yesterday": "昨天", | |
| 20 | + | |
| 21 | + "zp.systemLoading.title": "加載中..." | |
| 22 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/hooks/useZPaging.js
0 → 100644
| 1 | +// [z-paging]useZPaging hooks | |
| 2 | + | |
| 3 | +import { onPageScroll, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'; | |
| 4 | + | |
| 5 | +function useZPaging(paging) { | |
| 6 | + const cPaging = !!paging ? paging.value || paging : null; | |
| 7 | + | |
| 8 | + onPullDownRefresh(() => { | |
| 9 | + if (!cPaging || !cPaging.value) return; | |
| 10 | + cPaging.value.reload().catch(() => {}); | |
| 11 | + }) | |
| 12 | + | |
| 13 | + onPageScroll(e => { | |
| 14 | + if (!cPaging || !cPaging.value) return; | |
| 15 | + cPaging.value.updatePageScrollTop(e.scrollTop); | |
| 16 | + e.scrollTop < 10 && cPaging.value.doChatRecordLoadMore(); | |
| 17 | + }) | |
| 18 | + | |
| 19 | + onReachBottom(() => { | |
| 20 | + if (!cPaging || !cPaging.value) return; | |
| 21 | + cPaging.value.pageReachBottom(); | |
| 22 | + }) | |
| 23 | +} | |
| 24 | + | |
| 25 | +export default useZPaging | |
| 0 | 26 | \ No newline at end of file | ... | ... |
garbage-removal/src/components/z-paging/js/hooks/useZPagingComp.js
0 → 100644
| 1 | +// [z-paging]useZPagingComp hooks | |
| 2 | + | |
| 3 | +function useZPagingComp(paging) { | |
| 4 | + const cPaging = !!paging ? paging.value || paging : null; | |
| 5 | + | |
| 6 | + const reload = () => { | |
| 7 | + if (!cPaging || !cPaging.value) return; | |
| 8 | + cPaging.value.reload().catch(() => {}); | |
| 9 | + } | |
| 10 | + const updatePageScrollTop = scrollTop => { | |
| 11 | + if (!cPaging || !cPaging.value) return; | |
| 12 | + cPaging.value.updatePageScrollTop(scrollTop); | |
| 13 | + } | |
| 14 | + const doChatRecordLoadMore = () => { | |
| 15 | + if (!cPaging || !cPaging.value) return; | |
| 16 | + cPaging.value.doChatRecordLoadMore(); | |
| 17 | + } | |
| 18 | + const pageReachBottom = () => { | |
| 19 | + if (!cPaging || !cPaging.value) return; | |
| 20 | + cPaging.value.pageReachBottom(); | |
| 21 | + } | |
| 22 | + return { reload, updatePageScrollTop, doChatRecordLoadMore, pageReachBottom }; | |
| 23 | +} | |
| 24 | + | |
| 25 | +export default useZPagingComp | |
| 0 | 26 | \ No newline at end of file | ... | ... |
garbage-removal/src/components/z-paging/js/modules/back-to-top.js
0 → 100644
| 1 | +// [z-paging]点击返回顶部view模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | + | |
| 4 | +export default { | |
| 5 | + props: { | |
| 6 | + //自动显示点击返回顶部按钮,默认为否 | |
| 7 | + autoShowBackToTop: { | |
| 8 | + type: Boolean, | |
| 9 | + default: u.gc('autoShowBackToTop', false) | |
| 10 | + }, | |
| 11 | + //点击返回顶部按钮显示/隐藏的阈值(滚动距离),单位为px,默认为400rpx | |
| 12 | + backToTopThreshold: { | |
| 13 | + type: [Number, String], | |
| 14 | + default: u.gc('backToTopThreshold', '400rpx') | |
| 15 | + }, | |
| 16 | + //点击返回顶部按钮的自定义图片地址,默认使用z-paging内置的图片 | |
| 17 | + backToTopImg: { | |
| 18 | + type: String, | |
| 19 | + default: u.gc('backToTopImg', '') | |
| 20 | + }, | |
| 21 | + //点击返回顶部按钮返回到顶部时是否展示过渡动画,默认为是 | |
| 22 | + backToTopWithAnimate: { | |
| 23 | + type: Boolean, | |
| 24 | + default: u.gc('backToTopWithAnimate', true) | |
| 25 | + }, | |
| 26 | + //点击返回顶部按钮与底部的距离,注意添加单位px或rpx,默认为160rpx | |
| 27 | + backToTopBottom: { | |
| 28 | + type: [Number, String], | |
| 29 | + default: u.gc('backToTopBottom', '160rpx') | |
| 30 | + }, | |
| 31 | + //点击返回顶部按钮的自定义样式 | |
| 32 | + backToTopStyle: { | |
| 33 | + type: Object, | |
| 34 | + default: function() { | |
| 35 | + return u.gc('backToTopStyle', {}); | |
| 36 | + }, | |
| 37 | + }, | |
| 38 | + //iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向,默认为是 | |
| 39 | + enableBackToTop: { | |
| 40 | + type: Boolean, | |
| 41 | + default: u.gc('enableBackToTop', true) | |
| 42 | + }, | |
| 43 | + }, | |
| 44 | + data() { | |
| 45 | + return { | |
| 46 | + backToTopClass: 'zp-back-to-top zp-back-to-top-hide', | |
| 47 | + lastBackToTopShowTime: 0, | |
| 48 | + showBackToTopClass: false, | |
| 49 | + } | |
| 50 | + }, | |
| 51 | + computed: { | |
| 52 | + finalEnableBackToTop() { | |
| 53 | + return this.usePageScroll ? false : this.enableBackToTop; | |
| 54 | + }, | |
| 55 | + finalBackToTopThreshold() { | |
| 56 | + return u.convertToPx(this.backToTopThreshold); | |
| 57 | + }, | |
| 58 | + finalBackToTopStyle() { | |
| 59 | + const backToTopStyle = this.backToTopStyle; | |
| 60 | + if (!backToTopStyle.bottom) { | |
| 61 | + backToTopStyle.bottom = this.windowBottom + u.convertToPx(this.backToTopBottom) + 'px'; | |
| 62 | + } | |
| 63 | + if(!backToTopStyle.position){ | |
| 64 | + backToTopStyle.position = this.usePageScroll ? 'fixed': 'absolute'; | |
| 65 | + } | |
| 66 | + return backToTopStyle; | |
| 67 | + }, | |
| 68 | + }, | |
| 69 | + methods: { | |
| 70 | + //点击返回顶部 | |
| 71 | + _backToTopClick() { | |
| 72 | + let callbacked = false; | |
| 73 | + this.$emit('backToTopClick', toTop => { | |
| 74 | + (toTop === undefined || toTop === true) && this._handleToTop(); | |
| 75 | + callbacked = true; | |
| 76 | + }); | |
| 77 | + this.$nextTick(() => { | |
| 78 | + !callbacked && this._handleToTop(); | |
| 79 | + }) | |
| 80 | + }, | |
| 81 | + //处理滚动到顶部 | |
| 82 | + _handleToTop() { | |
| 83 | + !this.backToTopWithAnimate && this._checkShouldShowBackToTop(0); | |
| 84 | + this.scrollToTop(this.backToTopWithAnimate); | |
| 85 | + }, | |
| 86 | + //判断是否要显示返回顶部按钮 | |
| 87 | + _checkShouldShowBackToTop(scrollTop) { | |
| 88 | + if (!this.autoShowBackToTop) { | |
| 89 | + this.showBackToTopClass = false; | |
| 90 | + return; | |
| 91 | + } | |
| 92 | + if (scrollTop > this.finalBackToTopThreshold) { | |
| 93 | + if (!this.showBackToTopClass) { | |
| 94 | + this.showBackToTopClass = true; | |
| 95 | + this.lastBackToTopShowTime = new Date().getTime(); | |
| 96 | + u.delay(() => { | |
| 97 | + this.backToTopClass = 'zp-back-to-top zp-back-to-top-show'; | |
| 98 | + }, 300) | |
| 99 | + } | |
| 100 | + } else { | |
| 101 | + if (this.showBackToTopClass) { | |
| 102 | + this.backToTopClass = 'zp-back-to-top zp-back-to-top-hide'; | |
| 103 | + u.delay(() => { | |
| 104 | + this.showBackToTopClass = false; | |
| 105 | + }, new Date().getTime() - this.lastBackToTopShowTime < 500 ? 0 : 300) | |
| 106 | + } | |
| 107 | + } | |
| 108 | + }, | |
| 109 | + } | |
| 110 | +} | |
| 111 | + | ... | ... |
garbage-removal/src/components/z-paging/js/modules/common-layout.js
0 → 100644
| 1 | +// [z-paging]通用布局相关模块 | |
| 2 | + | |
| 3 | +// #ifdef APP-NVUE | |
| 4 | +const weexDom = weex.requireModule('dom'); | |
| 5 | +// #endif | |
| 6 | + | |
| 7 | +export default { | |
| 8 | + data() { | |
| 9 | + return { | |
| 10 | + systemInfo: null, | |
| 11 | + cssSafeAreaInsetBottom: -1, | |
| 12 | + } | |
| 13 | + }, | |
| 14 | + computed: { | |
| 15 | + windowTop() { | |
| 16 | + if (!this.systemInfo) return 0; | |
| 17 | + //暂时修复vue3中隐藏系统导航栏后windowTop获取不正确的问题,具体bug详见https://ask.dcloud.net.cn/question/141634 | |
| 18 | + //感谢litangyu!!https://github.com/SmileZXLee/uni-z-paging/issues/25 | |
| 19 | + // #ifdef VUE3 && H5 | |
| 20 | + const pageHeadNode = document.getElementsByTagName("uni-page-head"); | |
| 21 | + if (!pageHeadNode.length) return 0; | |
| 22 | + // #endif | |
| 23 | + return this.systemInfo.windowTop || 0; | |
| 24 | + }, | |
| 25 | + safeAreaBottom() { | |
| 26 | + if (!this.systemInfo) return 0; | |
| 27 | + let safeAreaBottom = 0; | |
| 28 | + // #ifdef APP-PLUS | |
| 29 | + safeAreaBottom = this.systemInfo.safeAreaInsets.bottom || 0 ; | |
| 30 | + // #endif | |
| 31 | + // #ifndef APP-PLUS | |
| 32 | + safeAreaBottom = Math.max(this.cssSafeAreaInsetBottom, 0); | |
| 33 | + // #endif | |
| 34 | + return safeAreaBottom; | |
| 35 | + }, | |
| 36 | + isOldWebView() { | |
| 37 | + // #ifndef APP-NVUE || MP-KUAISHOU | |
| 38 | + try { | |
| 39 | + const systemInfos = uni.getSystemInfoSync().system.split(' '); | |
| 40 | + const deviceType = systemInfos[0]; | |
| 41 | + const version = parseInt(systemInfos[1]); | |
| 42 | + if ((deviceType === 'iOS' && version <= 10) || (deviceType === 'Android' && version <= 6)) { | |
| 43 | + return true; | |
| 44 | + } | |
| 45 | + } catch(e) { | |
| 46 | + return false; | |
| 47 | + } | |
| 48 | + // #endif | |
| 49 | + return false; | |
| 50 | + }, | |
| 51 | + zSlots() { | |
| 52 | + // #ifdef VUE2 | |
| 53 | + | |
| 54 | + // #ifdef MP-ALIPAY | |
| 55 | + return this.$slots; | |
| 56 | + // #endif | |
| 57 | + | |
| 58 | + return this.$scopedSlots || this.$slots; | |
| 59 | + // #endif | |
| 60 | + | |
| 61 | + return this.$slots; | |
| 62 | + } | |
| 63 | + }, | |
| 64 | + methods: { | |
| 65 | + //获取节点尺寸 | |
| 66 | + _getNodeClientRect(select, inDom = true, scrollOffset = false) { | |
| 67 | + // #ifdef APP-NVUE | |
| 68 | + select = select.replace(/[.|#]/g, ''); | |
| 69 | + const ref = this.$refs[select]; | |
| 70 | + return new Promise((resolve, reject) => { | |
| 71 | + if (ref) { | |
| 72 | + weexDom.getComponentRect(ref, option => { | |
| 73 | + resolve(option && option.result ? [option.size] : false); | |
| 74 | + }) | |
| 75 | + } else { | |
| 76 | + resolve(false); | |
| 77 | + } | |
| 78 | + }); | |
| 79 | + return; | |
| 80 | + // #endif | |
| 81 | + //#ifdef MP-ALIPAY | |
| 82 | + inDom = false; | |
| 83 | + //#endif | |
| 84 | + let res = !!inDom ? uni.createSelectorQuery().in(inDom === true ? this : inDom) : uni.createSelectorQuery(); | |
| 85 | + scrollOffset ? res.select(select).scrollOffset() : res.select(select).boundingClientRect(); | |
| 86 | + return new Promise((resolve, reject) => { | |
| 87 | + res.exec(data => { | |
| 88 | + resolve((data && data != '' && data != undefined && data.length) ? data : false); | |
| 89 | + }); | |
| 90 | + }); | |
| 91 | + }, | |
| 92 | + //获取slot="left"和slot="right"宽度并且更新布局 | |
| 93 | + _updateLeftAndRightWidth(targetStyle, parentNodePrefix) { | |
| 94 | + this.$nextTick(() => { | |
| 95 | + let delayTime = 0; | |
| 96 | + // #ifdef MP-BAIDU | |
| 97 | + delayTime = 10; | |
| 98 | + // #endif | |
| 99 | + setTimeout(() => { | |
| 100 | + ['left','right'].map(position => { | |
| 101 | + this._getNodeClientRect(`.${parentNodePrefix}-${position}`).then(res => { | |
| 102 | + this.$set(targetStyle, position, res ? res[0].width + 'px' : '0px'); | |
| 103 | + }); | |
| 104 | + }) | |
| 105 | + }, delayTime) | |
| 106 | + }) | |
| 107 | + }, | |
| 108 | + //通过获取css设置的底部安全区域占位view高度设置bottom距离 | |
| 109 | + _getCssSafeAreaInsetBottom(success) { | |
| 110 | + this._getNodeClientRect('.zp-safe-area-inset-bottom').then(res => { | |
| 111 | + this.cssSafeAreaInsetBottom = res ? res[0].height : -1; | |
| 112 | + res && success && success(); | |
| 113 | + }); | |
| 114 | + } | |
| 115 | + } | |
| 116 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/modules/data-handle.js
0 → 100644
| 1 | +// [z-paging]数据处理模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | +import c from '.././z-paging-constant' | |
| 4 | +import Enum from '.././z-paging-enum' | |
| 5 | +import interceptor from '../z-paging-interceptor' | |
| 6 | + | |
| 7 | +export default { | |
| 8 | + props: { | |
| 9 | + //自定义初始的pageNo,默认为1 | |
| 10 | + defaultPageNo: { | |
| 11 | + type: [Number, String], | |
| 12 | + default: u.gc('defaultPageNo', 1), | |
| 13 | + observer: function(newVal) { | |
| 14 | + this.pageNo = newVal; | |
| 15 | + }, | |
| 16 | + }, | |
| 17 | + //自定义pageSize,默认为10 | |
| 18 | + defaultPageSize: { | |
| 19 | + type: [Number, String], | |
| 20 | + default: u.gc('defaultPageSize', 10), | |
| 21 | + validator: (value) => { | |
| 22 | + if (value <= 0) u.consoleErr('default-page-size必须大于0!'); | |
| 23 | + return value > 0; | |
| 24 | + } | |
| 25 | + }, | |
| 26 | + //为保证数据一致,设置当前tab切换时的标识key,并在complete中传递相同key,若二者不一致,则complete将不会生效 | |
| 27 | + dataKey: { | |
| 28 | + type: [Number, String, Object], | |
| 29 | + default: function() { | |
| 30 | + return u.gc('dataKey', null); | |
| 31 | + }, | |
| 32 | + }, | |
| 33 | + //使用缓存,若开启将自动缓存第一页的数据,默认为否。请注意,因考虑到切换tab时不同tab数据不同的情况,默认仅会缓存组件首次加载时第一次请求到的数据,后续的下拉刷新操作不会更新缓存。 | |
| 34 | + useCache: { | |
| 35 | + type: Boolean, | |
| 36 | + default: u.gc('useCache', false) | |
| 37 | + }, | |
| 38 | + //使用缓存时缓存的key,用于区分不同列表的缓存数据,useCache为true时必须设置,否则缓存无效 | |
| 39 | + cacheKey: { | |
| 40 | + type: String, | |
| 41 | + default: u.gc('cacheKey', null) | |
| 42 | + }, | |
| 43 | + //缓存模式,默认仅会缓存组件首次加载时第一次请求到的数据,可设置为always,即代表总是缓存,每次列表刷新(下拉刷新、调用reload等)都会更新缓存 | |
| 44 | + cacheMode: { | |
| 45 | + type: String, | |
| 46 | + default: u.gc('cacheMode', Enum.CacheMode.Default) | |
| 47 | + }, | |
| 48 | + //自动注入的list名,可自动修改父view(包含ref="paging")中对应name的list值 | |
| 49 | + autowireListName: { | |
| 50 | + type: String, | |
| 51 | + default: u.gc('autowireListName', '') | |
| 52 | + }, | |
| 53 | + //自动注入的query名,可自动调用父view(包含ref="paging")中的query方法 | |
| 54 | + autowireQueryName: { | |
| 55 | + type: String, | |
| 56 | + default: u.gc('autowireQueryName', '') | |
| 57 | + }, | |
| 58 | + //z-paging mounted后自动调用reload方法(mounted后自动调用接口),默认为是 | |
| 59 | + auto: { | |
| 60 | + type: Boolean, | |
| 61 | + default: u.gc('auto', true) | |
| 62 | + }, | |
| 63 | + //用户下拉刷新时是否触发reload方法,默认为是 | |
| 64 | + reloadWhenRefresh: { | |
| 65 | + type: Boolean, | |
| 66 | + default: u.gc('reloadWhenRefresh', true) | |
| 67 | + }, | |
| 68 | + //reload时自动滚动到顶部,默认为是 | |
| 69 | + autoScrollToTopWhenReload: { | |
| 70 | + type: Boolean, | |
| 71 | + default: u.gc('autoScrollToTopWhenReload', true) | |
| 72 | + }, | |
| 73 | + //reload时立即自动清空原list,默认为是,若立即自动清空,则在reload之后、请求回调之前页面是空白的 | |
| 74 | + autoCleanListWhenReload: { | |
| 75 | + type: Boolean, | |
| 76 | + default: u.gc('autoCleanListWhenReload', true) | |
| 77 | + }, | |
| 78 | + //列表刷新时自动显示下拉刷新view,默认为否 | |
| 79 | + showRefresherWhenReload: { | |
| 80 | + type: Boolean, | |
| 81 | + default: u.gc('showRefresherWhenReload', false) | |
| 82 | + }, | |
| 83 | + //列表刷新时自动显示加载更多view,且为加载中状态,默认为否 | |
| 84 | + showLoadingMoreWhenReload: { | |
| 85 | + type: Boolean, | |
| 86 | + default: u.gc('showLoadingMoreWhenReload', false) | |
| 87 | + }, | |
| 88 | + //组件created时立即触发reload(可解决一些情况下先看到页面再看到loading的问题),auto为true时有效。为否时将在mounted+nextTick后触发reload,默认为否 | |
| 89 | + createdReload: { | |
| 90 | + type: Boolean, | |
| 91 | + default: u.gc('createdReload', false) | |
| 92 | + }, | |
| 93 | + //本地分页时上拉加载更多延迟时间,单位为毫秒,默认200毫秒 | |
| 94 | + localPagingLoadingTime: { | |
| 95 | + type: [Number, String], | |
| 96 | + default: u.gc('localPagingLoadingTime', 200) | |
| 97 | + }, | |
| 98 | + //使用聊天记录模式,默认为否 | |
| 99 | + useChatRecordMode: { | |
| 100 | + type: Boolean, | |
| 101 | + default: u.gc('useChatRecordMode', false) | |
| 102 | + }, | |
| 103 | + //使用聊天记录模式时是否自动隐藏键盘:在用户触摸列表时候自动隐藏键盘,默认为是 | |
| 104 | + autoHideKeyboardWhenChat: { | |
| 105 | + type: Boolean, | |
| 106 | + default: u.gc('autoHideKeyboardWhenChat', true) | |
| 107 | + }, | |
| 108 | + //自动拼接complete中传过来的数组(使用聊天记录模式时无效) | |
| 109 | + concat: { | |
| 110 | + type: Boolean, | |
| 111 | + default: u.gc('concat', true) | |
| 112 | + }, | |
| 113 | + //请求失败是否触发reject,默认为是 | |
| 114 | + callNetworkReject: { | |
| 115 | + type: Boolean, | |
| 116 | + default: u.gc('callNetworkReject', true) | |
| 117 | + }, | |
| 118 | + //父组件v-model所绑定的list的值 | |
| 119 | + value: { | |
| 120 | + type: Array, | |
| 121 | + default: function() { | |
| 122 | + return []; | |
| 123 | + } | |
| 124 | + }, | |
| 125 | + // #ifdef VUE3 | |
| 126 | + modelValue: { | |
| 127 | + type: Array, | |
| 128 | + default: function() { | |
| 129 | + return []; | |
| 130 | + } | |
| 131 | + } | |
| 132 | + // #endif | |
| 133 | + }, | |
| 134 | + data (){ | |
| 135 | + return { | |
| 136 | + currentData: [], | |
| 137 | + totalData: [], | |
| 138 | + realTotalData: [], | |
| 139 | + totalLocalPagingList: [], | |
| 140 | + dataPromiseResultMap: { | |
| 141 | + reload: null, | |
| 142 | + complete: null, | |
| 143 | + localPaging: null | |
| 144 | + }, | |
| 145 | + isSettingCacheList: false, | |
| 146 | + pageNo: 1, | |
| 147 | + currentRefreshPageSize: 0, | |
| 148 | + isLocalPaging: false, | |
| 149 | + isAddedData: false, | |
| 150 | + isTotalChangeFromAddData: false, | |
| 151 | + privateConcat: true, | |
| 152 | + myParentQuery: -1, | |
| 153 | + firstPageLoaded: false, | |
| 154 | + pagingLoaded: false, | |
| 155 | + loaded: false, | |
| 156 | + isUserReload: true, | |
| 157 | + fromEmptyViewReload: false, | |
| 158 | + queryFrom: '', | |
| 159 | + listRendering: false, | |
| 160 | + isHandlingRefreshToPage: false | |
| 161 | + } | |
| 162 | + }, | |
| 163 | + computed: { | |
| 164 | + pageSize() { | |
| 165 | + return this.defaultPageSize; | |
| 166 | + }, | |
| 167 | + finalConcat() { | |
| 168 | + return this.concat && this.privateConcat; | |
| 169 | + }, | |
| 170 | + finalUseCache() { | |
| 171 | + if (this.useCache && !this.cacheKey) { | |
| 172 | + u.consoleErr('use-cache为true时,必须设置cache-key,否则缓存无效!'); | |
| 173 | + } | |
| 174 | + return this.useCache && !!this.cacheKey; | |
| 175 | + }, | |
| 176 | + finalCacheKey() { | |
| 177 | + return this.cacheKey ? `${c.cachePrefixKey}-${this.cacheKey}` : null; | |
| 178 | + }, | |
| 179 | + isFirstPage() { | |
| 180 | + return this.pageNo === this.defaultPageNo; | |
| 181 | + } | |
| 182 | + }, | |
| 183 | + watch: { | |
| 184 | + totalData(newVal, oldVal) { | |
| 185 | + this._totalDataChange(newVal, oldVal); | |
| 186 | + }, | |
| 187 | + currentData(newVal, oldVal) { | |
| 188 | + this._currentDataChange(newVal, oldVal); | |
| 189 | + }, | |
| 190 | + useChatRecordMode(newVal, oldVal) { | |
| 191 | + if (newVal) { | |
| 192 | + this.nLoadingMoreFixedHeight = false; | |
| 193 | + } | |
| 194 | + }, | |
| 195 | + value: { | |
| 196 | + handler(newVal) { | |
| 197 | + this.realTotalData = newVal; | |
| 198 | + }, | |
| 199 | + immediate: true | |
| 200 | + }, | |
| 201 | + // #ifdef VUE3 | |
| 202 | + modelValue: { | |
| 203 | + handler(newVal) { | |
| 204 | + this.realTotalData = newVal; | |
| 205 | + }, | |
| 206 | + immediate: true | |
| 207 | + } | |
| 208 | + // #endif | |
| 209 | + }, | |
| 210 | + methods: { | |
| 211 | + //请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否成功(默认是是) | |
| 212 | + complete(data, success = true) { | |
| 213 | + this.customNoMore = -1; | |
| 214 | + return this.addData(data, success); | |
| 215 | + }, | |
| 216 | + //【保证数据一致】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为dataKey,需与:data-key绑定的一致,第三个参数为是否成功(默认为是) | |
| 217 | + completeByKey(data, dataKey = null, success = true) { | |
| 218 | + if (dataKey !== null && this.dataKey !== null && dataKey !== this.dataKey) { | |
| 219 | + this.isFirstPage && this.endRefresh(); | |
| 220 | + return new Promise(resolve => resolve()); | |
| 221 | + } | |
| 222 | + this.customNoMore = -1; | |
| 223 | + return this.addData(data, success); | |
| 224 | + }, | |
| 225 | + //【通过total判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为total(列表总数),第三个参数为是否成功(默认为是) | |
| 226 | + completeByTotal(data, total, success = true) { | |
| 227 | + if (total == 'undefined') { | |
| 228 | + this.customNoMore = -1; | |
| 229 | + } else { | |
| 230 | + const dataTypeRes = this._checkDataType(data, success, false); | |
| 231 | + data = dataTypeRes.data; | |
| 232 | + success = dataTypeRes.success; | |
| 233 | + if (total >= 0 && success) { | |
| 234 | + return new Promise((resolve, reject) => { | |
| 235 | + this.$nextTick(() => { | |
| 236 | + let nomore = false; | |
| 237 | + const realTotalDataCount = this.pageNo == this.defaultPageNo ? 0 : this.realTotalData.length; | |
| 238 | + const dataLength = this.privateConcat ? data.length : 0; | |
| 239 | + let exceedCount = realTotalDataCount + dataLength - total; | |
| 240 | + if (exceedCount >= 0) { | |
| 241 | + nomore = true; | |
| 242 | + exceedCount = this.defaultPageSize - exceedCount; | |
| 243 | + if (this.privateConcat && exceedCount > 0 && exceedCount < data.length) { | |
| 244 | + data = data.splice(0, exceedCount); | |
| 245 | + } | |
| 246 | + } | |
| 247 | + this.completeByNoMore(data, nomore, success).then(res => resolve(res)).catch(() => reject()); | |
| 248 | + }) | |
| 249 | + }); | |
| 250 | + } | |
| 251 | + } | |
| 252 | + return this.addData(data, success); | |
| 253 | + }, | |
| 254 | + //【自行判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否有更多数据,第三个参数为是否成功(默认是是) | |
| 255 | + completeByNoMore(data, nomore, success = true) { | |
| 256 | + if (nomore != 'undefined') { | |
| 257 | + this.customNoMore = nomore == true ? 1 : 0; | |
| 258 | + } | |
| 259 | + return this.addData(data, success); | |
| 260 | + }, | |
| 261 | + //与上方complete方法功能一致,新版本中设置服务端回调数组请使用complete方法 | |
| 262 | + addData(data, success = true) { | |
| 263 | + if (!this.fromCompleteEmit) { | |
| 264 | + this.disabledCompleteEmit = true; | |
| 265 | + this.fromCompleteEmit = false; | |
| 266 | + } | |
| 267 | + const currentTimeStamp = u.getTime(); | |
| 268 | + const disTime = currentTimeStamp - this.requestTimeStamp; | |
| 269 | + let minDelay = this.minDelay; | |
| 270 | + if (this.isFirstPage && this.finalShowRefresherWhenReload) { | |
| 271 | + minDelay = Math.max(400, minDelay); | |
| 272 | + } | |
| 273 | + const addDataDalay = (this.requestTimeStamp > 0 && disTime < minDelay) ? minDelay - disTime : 0; | |
| 274 | + this.$nextTick(() => { | |
| 275 | + u.delay(() => { | |
| 276 | + this._addData(data, success, false); | |
| 277 | + }, this.delay > 0 ? this.delay : addDataDalay) | |
| 278 | + }) | |
| 279 | + | |
| 280 | + return new Promise((resolve, reject) => { | |
| 281 | + this.dataPromiseResultMap.complete = { resolve, reject }; | |
| 282 | + }); | |
| 283 | + }, | |
| 284 | + //从顶部添加数据,不会影响分页的pageNo和pageSize | |
| 285 | + addDataFromTop(data, toTop = true, toTopWithAnimate = true) { | |
| 286 | + data = Object.prototype.toString.call(data) !== '[object Array]' ? [data] : data.reverse(); | |
| 287 | + // #ifndef APP-NVUE | |
| 288 | + this.finalUseVirtualList && this._setCellIndex(data, 'top') | |
| 289 | + // #endif | |
| 290 | + this.totalData = [...data, ...this.totalData]; | |
| 291 | + if (toTop) { | |
| 292 | + u.delay(() => this._scrollToTop(toTopWithAnimate)); | |
| 293 | + } | |
| 294 | + }, | |
| 295 | + //重新设置列表数据,调用此方法不会影响pageNo和pageSize,也不会触发请求。适用场景:当需要删除列表中某一项时,将删除对应项后的数组通过此方法传递给z-paging。(当出现类似的需要修改列表数组的场景时,请使用此方法,请勿直接修改page中:list.sync绑定的数组) | |
| 296 | + resetTotalData(data) { | |
| 297 | + this.isTotalChangeFromAddData = true; | |
| 298 | + data = Object.prototype.toString.call(data) !== '[object Array]' ? [data] : data; | |
| 299 | + this.totalData = data; | |
| 300 | + }, | |
| 301 | + //添加聊天记录 | |
| 302 | + addChatRecordData(data, toBottom = true, toBottomWithAnimate = true) { | |
| 303 | + data = Object.prototype.toString.call(data) !== '[object Array]' ? [data] : data; | |
| 304 | + if (!this.useChatRecordMode) return; | |
| 305 | + this.isTotalChangeFromAddData = true; | |
| 306 | + //#ifndef APP-NVUE | |
| 307 | + this.totalData = [...this.totalData, ...data]; | |
| 308 | + //#endif | |
| 309 | + //#ifdef APP-NVUE | |
| 310 | + this.totalData = this.nIsFirstPageAndNoMore ? [...this.totalData, ...data] : [...data, ...this.totalData]; | |
| 311 | + //#endif | |
| 312 | + if (toBottom) { | |
| 313 | + u.delay(() => { | |
| 314 | + //#ifndef APP-NVUE | |
| 315 | + this._scrollToBottom(toBottomWithAnimate); | |
| 316 | + //#endif | |
| 317 | + //#ifdef APP-NVUE | |
| 318 | + this.nIsFirstPageAndNoMore ? this._scrollToBottom(toBottomWithAnimate) : this._scrollToTop(toBottomWithAnimate); | |
| 319 | + //#endif | |
| 320 | + }) | |
| 321 | + } | |
| 322 | + }, | |
| 323 | + //设置本地分页数据,请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging作分页处理(若调用了此方法,则上拉加载更多时内部会自动分页,不会触发@query所绑定的事件) | |
| 324 | + setLocalPaging(data, success = true) { | |
| 325 | + this.isLocalPaging = true; | |
| 326 | + this.$nextTick(() => { | |
| 327 | + this._addData(data, success, true); | |
| 328 | + }) | |
| 329 | + return new Promise((resolve, reject) => { | |
| 330 | + this.dataPromiseResultMap.localPaging = { resolve, reject }; | |
| 331 | + }); | |
| 332 | + }, | |
| 333 | + //重新加载分页数据,pageNo会恢复为默认值,相当于下拉刷新的效果(animate为true时会展示下拉刷新动画,默认为false) | |
| 334 | + reload(animate = this.showRefresherWhenReload) { | |
| 335 | + if (animate) { | |
| 336 | + this.privateShowRefresherWhenReload = animate; | |
| 337 | + this.isUserPullDown = true; | |
| 338 | + } | |
| 339 | + if (!this.showLoadingMoreWhenReload) { | |
| 340 | + this.listRendering = true; | |
| 341 | + } | |
| 342 | + this.$nextTick(() => { | |
| 343 | + this._preReload(animate, false); | |
| 344 | + }) | |
| 345 | + return new Promise((resolve, reject) => { | |
| 346 | + this.dataPromiseResultMap.reload = { resolve, reject }; | |
| 347 | + }); | |
| 348 | + }, | |
| 349 | + //刷新列表数据,pageNo和pageSize不会重置,列表数据会重新从服务端获取。必须保证@query绑定的方法中的pageNo和pageSize和传给服务端的一致 | |
| 350 | + refresh() { | |
| 351 | + return this._handleRefreshWithDisPageNo(this.pageNo - this.defaultPageNo + 1); | |
| 352 | + }, | |
| 353 | + //刷新列表数据至指定页,例如pageNo=5时则代表刷新列表至第5页,此时pageNo会变为5,列表会展示前5页的数据。必须保证@query绑定的方法中的pageNo和pageSize和传给服务端的一致 | |
| 354 | + refreshToPage(pageNo) { | |
| 355 | + this.isHandlingRefreshToPage = true; | |
| 356 | + return this._handleRefreshWithDisPageNo(pageNo + this.defaultPageNo - 1); | |
| 357 | + }, | |
| 358 | + //手动更新列表缓存数据,将自动截取v-model绑定的list中的前pageSize条覆盖缓存,请确保在list数据更新到预期结果后再调用此方法 | |
| 359 | + updateCache() { | |
| 360 | + if (this.finalUseCache && this.totalData.length) { | |
| 361 | + this._saveLocalCache(this.totalData.slice(0, Math.min(this.totalData.length, this.pageSize))); | |
| 362 | + } | |
| 363 | + }, | |
| 364 | + //清空分页数据 | |
| 365 | + clean() { | |
| 366 | + this._reload(true); | |
| 367 | + this._addData([], true, false); | |
| 368 | + }, | |
| 369 | + //清空分页数据 | |
| 370 | + clear() { | |
| 371 | + this.clean(); | |
| 372 | + }, | |
| 373 | + //手动触发滚动到顶部加载更多,聊天记录模式时有效 | |
| 374 | + doChatRecordLoadMore() { | |
| 375 | + this.useChatRecordMode && this._onLoadingMore('click'); | |
| 376 | + }, | |
| 377 | + //reload之前的一些处理 | |
| 378 | + _preReload(animate = this.showRefresherWhenReload, isFromMounted = true) { | |
| 379 | + const showRefresher = this.finalRefresherEnabled && this.useCustomRefresher; | |
| 380 | + // #ifndef APP-NVUE | |
| 381 | + if (this.customRefresherHeight === -1 && showRefresher) { | |
| 382 | + u.delay(() => this._preReload(animate, isFromMounted), c.delayTime / 2); | |
| 383 | + return; | |
| 384 | + } | |
| 385 | + // #endif | |
| 386 | + this.isUserReload = true; | |
| 387 | + this.loadingType = Enum.LoadingType.Refresher; | |
| 388 | + if (animate) { | |
| 389 | + this.privateShowRefresherWhenReload = animate; | |
| 390 | + // #ifndef APP-NVUE | |
| 391 | + if (this.useCustomRefresher) { | |
| 392 | + this._doRefresherRefreshAnimate(); | |
| 393 | + } else { | |
| 394 | + this.refresherTriggered = true; | |
| 395 | + } | |
| 396 | + // #endif | |
| 397 | + // #ifdef APP-NVUE | |
| 398 | + this.refresherStatus = Enum.Refresher.Loading; | |
| 399 | + this.refresherRevealStackCount ++; | |
| 400 | + u.delay(() => { | |
| 401 | + this._getNodeClientRect('zp-n-refresh-container', false).then((node) => { | |
| 402 | + if (node) { | |
| 403 | + let nodeHeight = node[0].height; | |
| 404 | + this.nShowRefresherReveal = true; | |
| 405 | + this.nShowRefresherRevealHeight = nodeHeight; | |
| 406 | + u.delay(() => { | |
| 407 | + this._nDoRefresherEndAnimation(0, -nodeHeight, false, false); | |
| 408 | + u.delay(() => { | |
| 409 | + this._nDoRefresherEndAnimation(nodeHeight, 0); | |
| 410 | + }, 10) | |
| 411 | + }, 10) | |
| 412 | + } | |
| 413 | + this._reload(false, isFromMounted); | |
| 414 | + this._doRefresherLoad(false); | |
| 415 | + }); | |
| 416 | + }, this.pagingLoaded ? 10 : 100) | |
| 417 | + return; | |
| 418 | + // #endif | |
| 419 | + } else { | |
| 420 | + this._refresherEnd(false, false, false, false); | |
| 421 | + } | |
| 422 | + this._reload(false, isFromMounted); | |
| 423 | + }, | |
| 424 | + //重新加载分页数据 | |
| 425 | + _reload(isClean = false, isFromMounted = false, isUserPullDown = false) { | |
| 426 | + this.isAddedData = false; | |
| 427 | + this.insideOfPaging = -1; | |
| 428 | + this.cacheScrollNodeHeight = -1; | |
| 429 | + this.pageNo = this.defaultPageNo; | |
| 430 | + this._cleanRefresherEndTimeout(); | |
| 431 | + !this.privateShowRefresherWhenReload && !isClean && this._startLoading(true); | |
| 432 | + this.firstPageLoaded = true; | |
| 433 | + this.isTotalChangeFromAddData = false; | |
| 434 | + if (!this.isSettingCacheList) { | |
| 435 | + this.totalData = []; | |
| 436 | + } | |
| 437 | + if (!isClean) { | |
| 438 | + this._emitQuery(this.pageNo, this.defaultPageSize, isUserPullDown ? Enum.QueryFrom.UserPullDown : Enum.QueryFrom.Reload); | |
| 439 | + let delay = 0; | |
| 440 | + // #ifdef MP-TOUTIAO | |
| 441 | + delay = 5; | |
| 442 | + // #endif | |
| 443 | + u.delay(this._callMyParentQuery, delay); | |
| 444 | + if (!isFromMounted && this.autoScrollToTopWhenReload) { | |
| 445 | + let checkedNRefresherLoading = true; | |
| 446 | + // #ifdef APP-NVUE | |
| 447 | + checkedNRefresherLoading = !this.nRefresherLoading; | |
| 448 | + // #endif | |
| 449 | + checkedNRefresherLoading && this._scrollToTop(false); | |
| 450 | + } | |
| 451 | + } | |
| 452 | + // #ifdef APP-NVUE | |
| 453 | + this.$nextTick(() => { | |
| 454 | + this.nShowBottom = this.realTotalData.length > 0; | |
| 455 | + }) | |
| 456 | + // #endif | |
| 457 | + }, | |
| 458 | + //处理服务端返回的数组 | |
| 459 | + _addData(data, success, isLocal) { | |
| 460 | + this.isAddedData = true; | |
| 461 | + this.fromEmptyViewReload = false; | |
| 462 | + this.isTotalChangeFromAddData = true; | |
| 463 | + this.refresherTriggered = false; | |
| 464 | + this._endSystemLoadingAndRefresh(); | |
| 465 | + const tempIsUserPullDown = this.isUserPullDown; | |
| 466 | + if (this.showRefresherUpdateTime && this.isFirstPage) { | |
| 467 | + u.setRefesrherTime(u.getTime(), this.refresherUpdateTimeKey); | |
| 468 | + this.$refs.refresh && this.$refs.refresh.updateTime(); | |
| 469 | + } | |
| 470 | + if (!isLocal && tempIsUserPullDown && this.isFirstPage) { | |
| 471 | + this.isUserPullDown = false; | |
| 472 | + } | |
| 473 | + if (!this.isFirstPage) { | |
| 474 | + this.listRendering = true; | |
| 475 | + this.$nextTick(() => { | |
| 476 | + u.delay(() => this.listRendering = false); | |
| 477 | + }) | |
| 478 | + } else { | |
| 479 | + this.listRendering = false; | |
| 480 | + } | |
| 481 | + let dataTypeRes = this._checkDataType(data, success, isLocal); | |
| 482 | + data = dataTypeRes.data; | |
| 483 | + success = dataTypeRes.success; | |
| 484 | + let delayTime = c.delayTime; | |
| 485 | + // #ifdef APP-NVUE | |
| 486 | + if (this.useChatRecordMode) delayTime = 0; | |
| 487 | + // #endif | |
| 488 | + this.loadingForNow = false; | |
| 489 | + u.delay(() => { | |
| 490 | + this.pagingLoaded = true; | |
| 491 | + this.$nextTick(()=>{ | |
| 492 | + !isLocal && this._refresherEnd(delayTime > 0, true, tempIsUserPullDown); | |
| 493 | + }) | |
| 494 | + }) | |
| 495 | + if (this.isFirstPage) { | |
| 496 | + this.isLoadFailed = !success; | |
| 497 | + this.$emit('isLoadFailedChange', this.isLoadFailed); | |
| 498 | + if (this.finalUseCache && success && (this.cacheMode === Enum.CacheMode.Always ? true : this.isSettingCacheList)) { | |
| 499 | + this._saveLocalCache(data); | |
| 500 | + } | |
| 501 | + } | |
| 502 | + this.isSettingCacheList = false; | |
| 503 | + if (success) { | |
| 504 | + if (!(this.privateConcat === false && this.loadingStatus === Enum.More.NoMore)) { | |
| 505 | + this.loadingStatus = Enum.More.Default; | |
| 506 | + } | |
| 507 | + if (isLocal) { | |
| 508 | + this.totalLocalPagingList = data; | |
| 509 | + const localPageNo = this.defaultPageNo; | |
| 510 | + const localPageSize = this.queryFrom !== Enum.QueryFrom.Refresh ? this.defaultPageSize : this.currentRefreshPageSize; | |
| 511 | + this._localPagingQueryList(localPageNo, localPageSize, 0, res => { | |
| 512 | + this.completeByTotal(res, this.totalLocalPagingList.length); | |
| 513 | + }) | |
| 514 | + } else { | |
| 515 | + let dataChangeDelayTime = 0; | |
| 516 | + // #ifdef APP-NVUE | |
| 517 | + if (this.privateShowRefresherWhenReload && this.finalNvueListIs === 'waterfall') { | |
| 518 | + dataChangeDelayTime = 150; | |
| 519 | + } | |
| 520 | + // #endif | |
| 521 | + u.delay(() => { | |
| 522 | + this._currentDataChange(data, this.currentData); | |
| 523 | + this._callDataPromise(true, this.totalData); | |
| 524 | + }, dataChangeDelayTime) | |
| 525 | + } | |
| 526 | + if (this.isHandlingRefreshToPage) { | |
| 527 | + this.isHandlingRefreshToPage = false; | |
| 528 | + this.pageNo = this.defaultPageNo + Math.ceil(data.length / this.pageSize) - 1; | |
| 529 | + if (data.length % this.pageSize !== 0) { | |
| 530 | + this.customNoMore = 1; | |
| 531 | + } | |
| 532 | + } | |
| 533 | + } else { | |
| 534 | + this._currentDataChange(data, this.currentData); | |
| 535 | + this._callDataPromise(false); | |
| 536 | + this.loadingStatus = Enum.More.Fail; | |
| 537 | + this.isHandlingRefreshToPage = false; | |
| 538 | + if (this.loadingType === Enum.LoadingType.LoadingMore) { | |
| 539 | + this.pageNo --; | |
| 540 | + } | |
| 541 | + } | |
| 542 | + }, | |
| 543 | + //所有数据改变时调用 | |
| 544 | + _totalDataChange(newVal, oldVal, eventThrow=true) { | |
| 545 | + if ((!this.isUserReload || !this.autoCleanListWhenReload) && this.firstPageLoaded && !newVal.length && oldVal.length) { | |
| 546 | + return; | |
| 547 | + } | |
| 548 | + this._doCheckScrollViewShouldFullHeight(newVal); | |
| 549 | + if(!this.realTotalData.length && !newVal.length){ | |
| 550 | + eventThrow = false; | |
| 551 | + } | |
| 552 | + this.realTotalData = newVal; | |
| 553 | + if (eventThrow) { | |
| 554 | + this.$emit('input', newVal); | |
| 555 | + // #ifdef VUE3 | |
| 556 | + this.$emit('update:modelValue', newVal); | |
| 557 | + // #endif | |
| 558 | + this.$emit('update:list', newVal); | |
| 559 | + this.$emit('listChange', newVal); | |
| 560 | + this._callMyParentList(newVal); | |
| 561 | + } | |
| 562 | + this.firstPageLoaded = false; | |
| 563 | + this.isTotalChangeFromAddData = false; | |
| 564 | + this.$nextTick(() => { | |
| 565 | + u.delay(()=>{ | |
| 566 | + this._getNodeClientRect('.zp-paging-container-content').then(res => { | |
| 567 | + res && this.$emit('contentHeightChanged', res[0].height); | |
| 568 | + }); | |
| 569 | + }, c.delayTime * (this.isIos ? 1 : 3)) | |
| 570 | + // #ifdef APP-NVUE | |
| 571 | + if (this.useChatRecordMode && this.nIsFirstPageAndNoMore && this.isFirstPage && !this.nFirstPageAndNoMoreChecked) { | |
| 572 | + this.nFirstPageAndNoMoreChecked = true; | |
| 573 | + this._scrollToBottom(false); | |
| 574 | + } | |
| 575 | + u.delay(() => { | |
| 576 | + this.nShowBottom = true; | |
| 577 | + }, c.delayTime * 6, 'nShowBottomDelay'); | |
| 578 | + // #endif | |
| 579 | + }) | |
| 580 | + }, | |
| 581 | + //当前数据改变时调用 | |
| 582 | + _currentDataChange(newVal, oldVal) { | |
| 583 | + newVal = [...newVal]; | |
| 584 | + // #ifndef APP-NVUE | |
| 585 | + this.finalUseVirtualList && this._setCellIndex(newVal, 'bottom'); | |
| 586 | + this.useChatRecordMode && newVal.reverse(); | |
| 587 | + // #endif | |
| 588 | + if (this.isFirstPage && this.finalConcat) { | |
| 589 | + this.totalData = []; | |
| 590 | + } | |
| 591 | + if (this.customNoMore !== -1) { | |
| 592 | + if (this.customNoMore === 1 || !newVal.length) { | |
| 593 | + this.loadingStatus = Enum.More.NoMore; | |
| 594 | + } | |
| 595 | + } else { | |
| 596 | + if (!newVal.length || (newVal.length && newVal.length < this.defaultPageSize)) { | |
| 597 | + this.loadingStatus = Enum.More.NoMore; | |
| 598 | + } | |
| 599 | + } | |
| 600 | + if (!this.totalData.length) { | |
| 601 | + if (this.finalConcat) { | |
| 602 | + // #ifdef APP-NVUE | |
| 603 | + if (this.useChatRecordMode && this.isFirstPage && this.loadingStatus === Enum.More.NoMore) { | |
| 604 | + newVal.reverse(); | |
| 605 | + } | |
| 606 | + // #endif | |
| 607 | + this.totalData = newVal; | |
| 608 | + } | |
| 609 | + if (this.useChatRecordMode) { | |
| 610 | + // #ifndef APP-NVUE | |
| 611 | + this.$nextTick(() => { | |
| 612 | + this._scrollToBottom(false); | |
| 613 | + }) | |
| 614 | + // #endif | |
| 615 | + } | |
| 616 | + } else { | |
| 617 | + if (this.useChatRecordMode) { | |
| 618 | + // #ifdef APP-NVUE | |
| 619 | + this.totalData = [...this.totalData, ...newVal]; | |
| 620 | + // #endif | |
| 621 | + //#ifndef APP-NVUE | |
| 622 | + const idIndex = newVal.length; | |
| 623 | + let idIndexStr = `z-paging-${idIndex}`; | |
| 624 | + this.totalData = [...newVal, ...this.totalData]; | |
| 625 | + if (this.pageNo !== this.defaultPageNo) { | |
| 626 | + this.privateScrollWithAnimation = 0; | |
| 627 | + this.$emit('update:chatIndex', idIndex); | |
| 628 | + this.$nextTick(() => { | |
| 629 | + this._scrollIntoView(idIndexStr, 30 + Math.max(0, this.cacheTopHeight), false, () => { | |
| 630 | + this.$emit('update:chatIndex', 0); | |
| 631 | + }); | |
| 632 | + }) | |
| 633 | + } else { | |
| 634 | + this.$nextTick(() => { | |
| 635 | + this._scrollToBottom(false); | |
| 636 | + }) | |
| 637 | + } | |
| 638 | + //#endif | |
| 639 | + | |
| 640 | + } else { | |
| 641 | + if (this.finalConcat) { | |
| 642 | + const currentScrollTop = this.oldScrollTop; | |
| 643 | + this.totalData = [...this.totalData, ...newVal]; | |
| 644 | + // #ifdef MP-WEIXIN | |
| 645 | + if (!this.isIos && !this.refresherOnly && !this.usePageScroll && newVal.length) { | |
| 646 | + this.loadingMoreTimeStamp = u.getTime(); | |
| 647 | + this.$nextTick(() => { | |
| 648 | + this.scrollToY(currentScrollTop); | |
| 649 | + }) | |
| 650 | + } | |
| 651 | + // #endif | |
| 652 | + } else { | |
| 653 | + this.totalData = newVal; | |
| 654 | + } | |
| 655 | + } | |
| 656 | + } | |
| 657 | + this.privateConcat = true; | |
| 658 | + }, | |
| 659 | + //根据pageNo处理refresh操作 | |
| 660 | + _handleRefreshWithDisPageNo(pageNo) { | |
| 661 | + if (!this.realTotalData.length) return this.reload(); | |
| 662 | + if (pageNo >= 1) { | |
| 663 | + this.loading = true; | |
| 664 | + this.privateConcat = false; | |
| 665 | + const totalPageSize = pageNo * this.pageSize; | |
| 666 | + this.currentRefreshPageSize = totalPageSize; | |
| 667 | + this._emitQuery(this.defaultPageNo, totalPageSize, Enum.QueryFrom.Refresh); | |
| 668 | + this._callMyParentQuery(this.defaultPageNo, totalPageSize); | |
| 669 | + } | |
| 670 | + return new Promise((resolve, reject) => { | |
| 671 | + this.dataPromiseResultMap.reload = { resolve, reject }; | |
| 672 | + }); | |
| 673 | + }, | |
| 674 | + //本地分页请求 | |
| 675 | + _localPagingQueryList(pageNo, pageSize, localPagingLoadingTime, callback) { | |
| 676 | + pageNo = Math.max(1, pageNo); | |
| 677 | + pageSize = Math.max(1, pageSize); | |
| 678 | + const totalPagingList = [...this.totalLocalPagingList]; | |
| 679 | + const pageNoIndex = (pageNo - 1) * pageSize; | |
| 680 | + const finalPageNoIndex = Math.min(totalPagingList.length, pageNoIndex + pageSize); | |
| 681 | + const resultPagingList = totalPagingList.splice(pageNoIndex, finalPageNoIndex - pageNoIndex); | |
| 682 | + u.delay(() => callback(resultPagingList), localPagingLoadingTime) | |
| 683 | + }, | |
| 684 | + //存储列表缓存数据 | |
| 685 | + _saveLocalCache(data) { | |
| 686 | + uni.setStorageSync(this.finalCacheKey, data); | |
| 687 | + }, | |
| 688 | + //通过缓存数据填充列表数据 | |
| 689 | + _setListByLocalCache() { | |
| 690 | + this.totalData = uni.getStorageSync(this.finalCacheKey) || []; | |
| 691 | + this.isSettingCacheList = true; | |
| 692 | + }, | |
| 693 | + //修改父view的list | |
| 694 | + _callMyParentList(newVal) { | |
| 695 | + if (this.autowireListName.length) { | |
| 696 | + const myParent = u.getParent(this.$parent); | |
| 697 | + if (myParent && myParent[this.autowireListName]) { | |
| 698 | + myParent[this.autowireListName] = newVal; | |
| 699 | + } | |
| 700 | + } | |
| 701 | + }, | |
| 702 | + //调用父view的query | |
| 703 | + _callMyParentQuery(customPageNo = 0, customPageSize = 0) { | |
| 704 | + if (this.autowireQueryName) { | |
| 705 | + if (this.myParentQuery === -1) { | |
| 706 | + const myParent = u.getParent(this.$parent); | |
| 707 | + if (myParent && myParent[this.autowireQueryName]) { | |
| 708 | + this.myParentQuery = myParent[this.autowireQueryName]; | |
| 709 | + } | |
| 710 | + } | |
| 711 | + if (this.myParentQuery !== -1) { | |
| 712 | + customPageSize > 0 ? this.myParentQuery(customPageNo, customPageSize) : this.myParentQuery(this.pageNo, this.defaultPageSize); | |
| 713 | + } | |
| 714 | + } | |
| 715 | + }, | |
| 716 | + //emit query事件 | |
| 717 | + _emitQuery(pageNo, pageSize, from){ | |
| 718 | + this.queryFrom = from; | |
| 719 | + this.requestTimeStamp = u.getTime(); | |
| 720 | + const [lastItem] = this.realTotalData.slice(-1); | |
| 721 | + this.$emit('query', ...interceptor._handleQuery(pageNo, pageSize, from, lastItem || null)); | |
| 722 | + }, | |
| 723 | + //触发数据改变promise | |
| 724 | + _callDataPromise(success, totalList) { | |
| 725 | + for (const key in this.dataPromiseResultMap) { | |
| 726 | + const obj = this.dataPromiseResultMap[key]; | |
| 727 | + if (!obj) continue; | |
| 728 | + success ? obj.resolve({ totalList, noMore: this.loadingStatus === Enum.More.NoMore }) : this.callNetworkReject && obj.reject(`z-paging-${key}-error`); | |
| 729 | + } | |
| 730 | + }, | |
| 731 | + //检查complete data的类型 | |
| 732 | + _checkDataType(data, success, isLocal) { | |
| 733 | + const dataType = Object.prototype.toString.call(data); | |
| 734 | + if (dataType === '[object Boolean]') { | |
| 735 | + success = data; | |
| 736 | + data = []; | |
| 737 | + } else if (dataType !== '[object Array]') { | |
| 738 | + data = []; | |
| 739 | + if (dataType !== '[object Undefined]' && dataType !== '[object Null]') { | |
| 740 | + u.consoleErr(`${isLocal ? 'setLocalPaging' : 'complete'}参数类型不正确,第一个参数类型必须为Array!`); | |
| 741 | + } | |
| 742 | + } | |
| 743 | + return { data, success }; | |
| 744 | + }, | |
| 745 | + } | |
| 746 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/modules/empty.js
0 → 100644
| 1 | +// [z-paging]空数据图view模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | + | |
| 4 | +export default { | |
| 5 | + props: { | |
| 6 | + //是否强制隐藏空数据图,默认为否 | |
| 7 | + hideEmptyView: { | |
| 8 | + type: Boolean, | |
| 9 | + default: u.gc('hideEmptyView', false) | |
| 10 | + }, | |
| 11 | + //空数据图描述文字,默认为“没有数据哦~” | |
| 12 | + emptyViewText: { | |
| 13 | + type: [String, Object], | |
| 14 | + default: u.gc('emptyViewText', null) | |
| 15 | + }, | |
| 16 | + //是否显示空数据图重新加载按钮(无数据时),默认为否 | |
| 17 | + showEmptyViewReload: { | |
| 18 | + type: Boolean, | |
| 19 | + default: u.gc('showEmptyViewReload', false) | |
| 20 | + }, | |
| 21 | + //加载失败时是否显示空数据图重新加载按钮,默认为是 | |
| 22 | + showEmptyViewReloadWhenError: { | |
| 23 | + type: Boolean, | |
| 24 | + default: u.gc('showEmptyViewReloadWhenError', true) | |
| 25 | + }, | |
| 26 | + //空数据图点击重新加载文字,默认为“重新加载” | |
| 27 | + emptyViewReloadText: { | |
| 28 | + type: [String, Object], | |
| 29 | + default: u.gc('emptyViewReloadText', null) | |
| 30 | + }, | |
| 31 | + //空数据图图片,默认使用z-paging内置的图片 | |
| 32 | + emptyViewImg: { | |
| 33 | + type: String, | |
| 34 | + default: u.gc('emptyViewImg', '') | |
| 35 | + }, | |
| 36 | + //空数据图“加载失败”描述文字,默认为“很抱歉,加载失败” | |
| 37 | + emptyViewErrorText: { | |
| 38 | + type: [String, Object], | |
| 39 | + default: u.gc('emptyViewErrorText', null) | |
| 40 | + }, | |
| 41 | + //空数据图“加载失败”图片,默认使用z-paging内置的图片 | |
| 42 | + emptyViewErrorImg: { | |
| 43 | + type: String, | |
| 44 | + default: u.gc('emptyViewErrorImg', '') | |
| 45 | + }, | |
| 46 | + //空数据图样式 | |
| 47 | + emptyViewStyle: { | |
| 48 | + type: Object, | |
| 49 | + default: function() { | |
| 50 | + return u.gc('emptyViewStyle', {}); | |
| 51 | + } | |
| 52 | + }, | |
| 53 | + //空数据图容器样式 | |
| 54 | + emptyViewSuperStyle: { | |
| 55 | + type: Object, | |
| 56 | + default: function() { | |
| 57 | + return u.gc('emptyViewSuperStyle', {}); | |
| 58 | + } | |
| 59 | + }, | |
| 60 | + //空数据图img样式 | |
| 61 | + emptyViewImgStyle: { | |
| 62 | + type: Object, | |
| 63 | + default: function() { | |
| 64 | + return u.gc('emptyViewImgStyle', {}); | |
| 65 | + } | |
| 66 | + }, | |
| 67 | + //空数据图描述文字样式 | |
| 68 | + emptyViewTitleStyle: { | |
| 69 | + type: Object, | |
| 70 | + default: function() { | |
| 71 | + return u.gc('emptyViewTitleStyle', {}); | |
| 72 | + } | |
| 73 | + }, | |
| 74 | + //空数据图重新加载按钮样式 | |
| 75 | + emptyViewReloadStyle: { | |
| 76 | + type: Object, | |
| 77 | + default: function() { | |
| 78 | + return u.gc('emptyViewReloadStyle', {}); | |
| 79 | + } | |
| 80 | + }, | |
| 81 | + //空数据图片是否铺满z-paging,默认为否,即填充满z-paging内列表(滚动区域)部分。若设置为否,则为填铺满整个z-paging | |
| 82 | + emptyViewFixed: { | |
| 83 | + type: Boolean, | |
| 84 | + default: u.gc('emptyViewFixed', false) | |
| 85 | + }, | |
| 86 | + //空数据图片是否垂直居中,默认为是,若设置为否即为从空数据容器顶部开始显示。emptyViewFixed为false时有效 | |
| 87 | + emptyViewCenter: { | |
| 88 | + type: Boolean, | |
| 89 | + default: u.gc('emptyViewCenter', true) | |
| 90 | + }, | |
| 91 | + //加载中时是否自动隐藏空数据图,默认为是 | |
| 92 | + autoHideEmptyViewWhenLoading: { | |
| 93 | + type: Boolean, | |
| 94 | + default: u.gc('autoHideEmptyViewWhenLoading', true) | |
| 95 | + }, | |
| 96 | + //用户下拉列表触发下拉刷新加载中时是否自动隐藏空数据图,默认为是 | |
| 97 | + autoHideEmptyViewWhenPull: { | |
| 98 | + type: Boolean, | |
| 99 | + default: u.gc('autoHideEmptyViewWhenPull', true) | |
| 100 | + }, | |
| 101 | + //空数据view的z-index,默认为9 | |
| 102 | + emptyViewZIndex: { | |
| 103 | + type: Number, | |
| 104 | + default: u.gc('emptyViewZIndex', 9) | |
| 105 | + }, | |
| 106 | + }, | |
| 107 | + computed: { | |
| 108 | + finalEmptyViewImg() { | |
| 109 | + return this.isLoadFailed ? this.emptyViewErrorImg : this.emptyViewImg; | |
| 110 | + }, | |
| 111 | + finalShowEmptyViewReload() { | |
| 112 | + return this.isLoadFailed ? this.showEmptyViewReloadWhenError : this.showEmptyViewReload; | |
| 113 | + }, | |
| 114 | + showEmpty() { | |
| 115 | + if (this.refresherOnly || this.hideEmptyView || this.realTotalData.length) return false; | |
| 116 | + if (this.autoHideEmptyViewWhenLoading) { | |
| 117 | + if (this.isAddedData && !this.firstPageLoaded && !this.loading) return true; | |
| 118 | + } else { | |
| 119 | + return true; | |
| 120 | + } | |
| 121 | + return !this.autoHideEmptyViewWhenPull && !this.isUserReload; | |
| 122 | + }, | |
| 123 | + }, | |
| 124 | + methods: { | |
| 125 | + //点击了空数据view重新加载按钮 | |
| 126 | + _emptyViewReload() { | |
| 127 | + let callbacked = false; | |
| 128 | + this.$emit('emptyViewReload', reload => { | |
| 129 | + if (reload === undefined || reload === true) { | |
| 130 | + this.fromEmptyViewReload = true; | |
| 131 | + this.reload().catch(() => {}); | |
| 132 | + } | |
| 133 | + callbacked = true; | |
| 134 | + }); | |
| 135 | + this.$nextTick(() => { | |
| 136 | + if (!callbacked) { | |
| 137 | + this.fromEmptyViewReload = true; | |
| 138 | + this.reload().catch(() => {}); | |
| 139 | + } | |
| 140 | + }) | |
| 141 | + }, | |
| 142 | + //点击了空数据view | |
| 143 | + _emptyViewClick() { | |
| 144 | + this.$emit('emptyViewClick'); | |
| 145 | + }, | |
| 146 | + } | |
| 147 | +} | |
| 0 | 148 | \ No newline at end of file | ... | ... |
garbage-removal/src/components/z-paging/js/modules/i18n.js
0 → 100644
| 1 | +// [z-paging]i18n模块 | |
| 2 | +import { initVueI18n } from '@dcloudio/uni-i18n' | |
| 3 | +import messages from '../../i18n/index.js' | |
| 4 | +const { t } = initVueI18n(messages) | |
| 5 | + | |
| 6 | +import u from '.././z-paging-utils' | |
| 7 | +import c from '.././z-paging-constant' | |
| 8 | +import interceptor from '../z-paging-interceptor' | |
| 9 | + | |
| 10 | +const language = uni.getSystemInfoSync().language; | |
| 11 | +export default { | |
| 12 | + data() { | |
| 13 | + return { | |
| 14 | + language | |
| 15 | + } | |
| 16 | + }, | |
| 17 | + computed: { | |
| 18 | + finalLanguage() { | |
| 19 | + try { | |
| 20 | + const local = uni.getLocale(); | |
| 21 | + const language = this.language; | |
| 22 | + return local === 'auto' ? interceptor._handleLanguage2Local(language, this._language2Local(language)) : local; | |
| 23 | + } catch (e) { | |
| 24 | + return 'zh-Hans'; | |
| 25 | + } | |
| 26 | + }, | |
| 27 | + finalRefresherDefaultText() { | |
| 28 | + return this._getI18nText('zp.refresher.default', this.refresherDefaultText); | |
| 29 | + }, | |
| 30 | + finalRefresherPullingText() { | |
| 31 | + return this._getI18nText('zp.refresher.pulling', this.refresherPullingText); | |
| 32 | + }, | |
| 33 | + finalRefresherRefreshingText() { | |
| 34 | + return this._getI18nText('zp.refresher.refreshing', this.refresherRefreshingText); | |
| 35 | + }, | |
| 36 | + finalRefresherCompleteText() { | |
| 37 | + return this._getI18nText('zp.refresher.complete', this.refresherCompleteText); | |
| 38 | + }, | |
| 39 | + finalRefresherUpdateTimeTextMap() { | |
| 40 | + return { | |
| 41 | + title: t('zp.refresherUpdateTime.title'), | |
| 42 | + none: t('zp.refresherUpdateTime.none'), | |
| 43 | + today: t('zp.refresherUpdateTime.today'), | |
| 44 | + yesterday: t('zp.refresherUpdateTime.yesterday') | |
| 45 | + }; | |
| 46 | + }, | |
| 47 | + finalLoadingMoreDefaultText() { | |
| 48 | + return this._getI18nText('zp.loadingMore.default', this.loadingMoreDefaultText); | |
| 49 | + }, | |
| 50 | + finalLoadingMoreLoadingText() { | |
| 51 | + return this._getI18nText('zp.loadingMore.loading', this.loadingMoreLoadingText); | |
| 52 | + }, | |
| 53 | + finalLoadingMoreNoMoreText() { | |
| 54 | + return this._getI18nText('zp.loadingMore.noMore', this.loadingMoreNoMoreText); | |
| 55 | + }, | |
| 56 | + finalLoadingMoreFailText() { | |
| 57 | + return this._getI18nText('zp.loadingMore.fail', this.loadingMoreFailText); | |
| 58 | + }, | |
| 59 | + finalEmptyViewText() { | |
| 60 | + return this.isLoadFailed ? this.finalEmptyViewErrorText : this._getI18nText('zp.emptyView.title', this.emptyViewText); | |
| 61 | + }, | |
| 62 | + finalEmptyViewReloadText() { | |
| 63 | + return this._getI18nText('zp.emptyView.reload', this.emptyViewReloadText); | |
| 64 | + }, | |
| 65 | + finalEmptyViewErrorText() { | |
| 66 | + return this._getI18nText('zp.emptyView.error', this.emptyViewErrorText); | |
| 67 | + }, | |
| 68 | + finalSystemLoadingText() { | |
| 69 | + return this._getI18nText('zp.systemLoading.title', this.systemLoadingText); | |
| 70 | + }, | |
| 71 | + }, | |
| 72 | + methods: { | |
| 73 | + //获取当前z-paging的语言 | |
| 74 | + getLanguage() { | |
| 75 | + return this.finalLanguage; | |
| 76 | + }, | |
| 77 | + //获取国际化转换后的文本 | |
| 78 | + _getI18nText(key, value) { | |
| 79 | + const dataType = Object.prototype.toString.call(value); | |
| 80 | + if (dataType === '[object Object]') { | |
| 81 | + const nextValue = value[this.finalLanguage]; | |
| 82 | + if (nextValue) return nextValue; | |
| 83 | + } else if (dataType === '[object String]') { | |
| 84 | + return value; | |
| 85 | + } | |
| 86 | + return t(key); | |
| 87 | + }, | |
| 88 | + //系统language转i18n local | |
| 89 | + _language2Local(language) { | |
| 90 | + const formatedLanguage = language.toLowerCase().replace(new RegExp('_', ''), '-'); | |
| 91 | + if (formatedLanguage.indexOf('zh') !== -1) { | |
| 92 | + if (formatedLanguage === 'zh' || formatedLanguage === 'zh-cn' || formatedLanguage.indexOf('zh-hans') !== -1) { | |
| 93 | + return 'zh-Hans'; | |
| 94 | + } | |
| 95 | + return 'zh-Hant'; | |
| 96 | + } | |
| 97 | + if (formatedLanguage.indexOf('en') !== -1) return 'en'; | |
| 98 | + return language; | |
| 99 | + } | |
| 100 | + } | |
| 101 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/modules/load-more.js
0 → 100644
| 1 | +// [z-paging]滚动到底部加载更多模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | +import Enum from '.././z-paging-enum' | |
| 4 | + | |
| 5 | +export default { | |
| 6 | + props: { | |
| 7 | + //自定义底部加载更多样式 | |
| 8 | + loadingMoreCustomStyle: { | |
| 9 | + type: Object, | |
| 10 | + default: function() { | |
| 11 | + return u.gc('loadingMoreCustomStyle', {}); | |
| 12 | + } | |
| 13 | + }, | |
| 14 | + //自定义底部加载更多文字样式 | |
| 15 | + loadingMoreTitleCustomStyle: { | |
| 16 | + type: Object, | |
| 17 | + default: function() { | |
| 18 | + return u.gc('loadingMoreTitleCustomStyle', {}); | |
| 19 | + } | |
| 20 | + }, | |
| 21 | + //自定义底部加载更多加载中动画样式 | |
| 22 | + loadingMoreLoadingIconCustomStyle: { | |
| 23 | + type: Object, | |
| 24 | + default: function() { | |
| 25 | + return u.gc('loadingMoreLoadingIconCustomStyle', {}); | |
| 26 | + } | |
| 27 | + }, | |
| 28 | + //自定义底部加载更多加载中动画图标类型,可选flower或circle,默认为flower | |
| 29 | + loadingMoreLoadingIconType: { | |
| 30 | + type: String, | |
| 31 | + default: u.gc('loadingMoreLoadingIconType', 'flower') | |
| 32 | + }, | |
| 33 | + //自定义底部加载更多加载中动画图标图片 | |
| 34 | + loadingMoreLoadingIconCustomImage: { | |
| 35 | + type: String, | |
| 36 | + default: u.gc('loadingMoreLoadingIconCustomImage', '') | |
| 37 | + }, | |
| 38 | + //底部加载更多加载中view是否展示旋转动画,默认为是 | |
| 39 | + loadingMoreLoadingAnimated: { | |
| 40 | + type: Boolean, | |
| 41 | + default: u.gc('loadingMoreLoadingAnimated', true) | |
| 42 | + }, | |
| 43 | + //是否启用加载更多数据(含滑动到底部加载更多数据和点击加载更多数据),默认为是 | |
| 44 | + loadingMoreEnabled: { | |
| 45 | + type: Boolean, | |
| 46 | + default: u.gc('loadingMoreEnabled', true) | |
| 47 | + }, | |
| 48 | + //是否启用滑动到底部加载更多数据,默认为是 | |
| 49 | + toBottomLoadingMoreEnabled: { | |
| 50 | + type: Boolean, | |
| 51 | + default: u.gc('toBottomLoadingMoreEnabled', true) | |
| 52 | + }, | |
| 53 | + //滑动到底部状态为默认状态时,以加载中的状态展示,默认为否。若设置为是,可避免滚动到底部看到默认状态然后立刻变为加载中状态的问题,但分页数量未超过一屏时,不会显示【点击加载更多】 | |
| 54 | + loadingMoreDefaultAsLoading: { | |
| 55 | + type: [Boolean], | |
| 56 | + default: u.gc('loadingMoreDefaultAsLoading', false) | |
| 57 | + }, | |
| 58 | + //滑动到底部"默认"文字,默认为【点击加载更多】 | |
| 59 | + loadingMoreDefaultText: { | |
| 60 | + type: [String, Object], | |
| 61 | + default: u.gc('loadingMoreDefaultText', null) | |
| 62 | + }, | |
| 63 | + //滑动到底部"加载中"文字,默认为【正在加载...】 | |
| 64 | + loadingMoreLoadingText: { | |
| 65 | + type: [String, Object], | |
| 66 | + default: u.gc('loadingMoreLoadingText', null) | |
| 67 | + }, | |
| 68 | + //滑动到底部"没有更多"文字,默认为【没有更多了】 | |
| 69 | + loadingMoreNoMoreText: { | |
| 70 | + type: [String, Object], | |
| 71 | + default: u.gc('loadingMoreNoMoreText', null) | |
| 72 | + }, | |
| 73 | + //滑动到底部"加载失败"文字,默认为【加载失败,点击重新加载】 | |
| 74 | + loadingMoreFailText: { | |
| 75 | + type: [String, Object], | |
| 76 | + default: u.gc('loadingMoreFailText', null) | |
| 77 | + }, | |
| 78 | + //当没有更多数据且分页内容未超出z-paging时是否隐藏没有更多数据的view,默认为否 | |
| 79 | + hideNoMoreInside: { | |
| 80 | + type: Boolean, | |
| 81 | + default: u.gc('hideNoMoreInside', false) | |
| 82 | + }, | |
| 83 | + //当没有更多数据且分页数组长度少于这个值时,隐藏没有更多数据的view,默认为0,代表不限制。 | |
| 84 | + hideNoMoreByLimit: { | |
| 85 | + type: Number, | |
| 86 | + default: u.gc('hideNoMoreByLimit', 0) | |
| 87 | + }, | |
| 88 | + //是否显示默认的加载更多text,默认为是 | |
| 89 | + showDefaultLoadingMoreText: { | |
| 90 | + type: Boolean, | |
| 91 | + default: u.gc('showDefaultLoadingMoreText', true) | |
| 92 | + }, | |
| 93 | + //是否显示没有更多数据的view | |
| 94 | + showLoadingMoreNoMoreView: { | |
| 95 | + type: Boolean, | |
| 96 | + default: u.gc('showLoadingMoreNoMoreView', true) | |
| 97 | + }, | |
| 98 | + //是否显示没有更多数据的分割线,默认为是 | |
| 99 | + showLoadingMoreNoMoreLine: { | |
| 100 | + type: Boolean, | |
| 101 | + default: u.gc('showLoadingMoreNoMoreLine', true) | |
| 102 | + }, | |
| 103 | + //自定义底部没有更多数据的分割线样式 | |
| 104 | + loadingMoreNoMoreLineCustomStyle: { | |
| 105 | + type: Object, | |
| 106 | + default: function() { | |
| 107 | + return u.gc('loadingMoreNoMoreLineCustomStyle', {}); | |
| 108 | + }, | |
| 109 | + }, | |
| 110 | + //当分页未满一屏时,是否自动加载更多,默认为否(nvue无效) | |
| 111 | + insideMore: { | |
| 112 | + type: Boolean, | |
| 113 | + default: u.gc('insideMore', false) | |
| 114 | + }, | |
| 115 | + //距底部/右边多远时(单位px),触发 scrolltolower 事件,默认为100rpx | |
| 116 | + lowerThreshold: { | |
| 117 | + type: [Number, String], | |
| 118 | + default: u.gc('lowerThreshold', '100rpx') | |
| 119 | + }, | |
| 120 | + }, | |
| 121 | + data() { | |
| 122 | + return { | |
| 123 | + M: Enum.More, | |
| 124 | + //底部加载更多状态 | |
| 125 | + loadingStatus: Enum.More.Default, | |
| 126 | + loadingStatusAfterRender: Enum.More.Default, | |
| 127 | + loadingMoreTimeStamp: 0, | |
| 128 | + loadingMoreDefaultSlot: null, | |
| 129 | + showLoadingMore: false, | |
| 130 | + customNoMore: -1, | |
| 131 | + } | |
| 132 | + }, | |
| 133 | + computed: { | |
| 134 | + zLoadMoreConfig() { | |
| 135 | + return { | |
| 136 | + status: this.loadingStatusAfterRender, | |
| 137 | + defaultAsLoading: this.loadingMoreDefaultAsLoading, | |
| 138 | + defaultThemeStyle: this.finalLoadingMoreThemeStyle, | |
| 139 | + customStyle: this.loadingMoreCustomStyle, | |
| 140 | + titleCustomStyle: this.loadingMoreTitleCustomStyle, | |
| 141 | + iconCustomStyle: this.loadingMoreLoadingIconCustomStyle, | |
| 142 | + loadingIconType: this.loadingMoreLoadingIconType, | |
| 143 | + loadingIconCustomImage: this.loadingMoreLoadingIconCustomImage, | |
| 144 | + loadingAnimated: this.loadingMoreLoadingAnimated, | |
| 145 | + showNoMoreLine: this.showLoadingMoreNoMoreLine, | |
| 146 | + noMoreLineCustomStyle: this.loadingMoreNoMoreLineCustomStyle, | |
| 147 | + defaultText: this.finalLoadingMoreDefaultText, | |
| 148 | + loadingText: this.finalLoadingMoreLoadingText, | |
| 149 | + noMoreText: this.finalLoadingMoreNoMoreText, | |
| 150 | + failText: this.finalLoadingMoreFailText, | |
| 151 | + hideContent: !this.loadingMoreDefaultAsLoading && this.listRendering, | |
| 152 | + }; | |
| 153 | + }, | |
| 154 | + finalLoadingMoreThemeStyle() { | |
| 155 | + return this.loadingMoreThemeStyle.length ? this.loadingMoreThemeStyle : this.defaultThemeStyle; | |
| 156 | + }, | |
| 157 | + showLoadingMoreDefault() { | |
| 158 | + return this._showLoadingMore('Default'); | |
| 159 | + }, | |
| 160 | + showLoadingMoreLoading() { | |
| 161 | + return this._showLoadingMore('Loading'); | |
| 162 | + }, | |
| 163 | + showLoadingMoreNoMore() { | |
| 164 | + return this._showLoadingMore('NoMore'); | |
| 165 | + }, | |
| 166 | + showLoadingMoreFail() { | |
| 167 | + return this._showLoadingMore('Fail'); | |
| 168 | + }, | |
| 169 | + showLoadingMoreCustom() { | |
| 170 | + return this._showLoadingMore('Custom'); | |
| 171 | + } | |
| 172 | + }, | |
| 173 | + methods: { | |
| 174 | + //页面滚动到底部时通知z-paging进行进一步处理 | |
| 175 | + pageReachBottom() { | |
| 176 | + !this.useChatRecordMode && this._onLoadingMore('toBottom'); | |
| 177 | + }, | |
| 178 | + //手动触发上拉加载更多(非必须,可依据具体需求使用) | |
| 179 | + doLoadMore(type) { | |
| 180 | + this._onLoadingMore(type); | |
| 181 | + }, | |
| 182 | + //通过@scroll事件检测是否滚动到了底部 | |
| 183 | + _checkScrolledToBottom(scrollDiff, checked = false) { | |
| 184 | + if (this.cacheScrollNodeHeight === -1) { | |
| 185 | + this._getNodeClientRect('.zp-scroll-view').then((res) => { | |
| 186 | + if (res) { | |
| 187 | + const pageScrollNodeHeight = res[0].height; | |
| 188 | + this.cacheScrollNodeHeight = pageScrollNodeHeight; | |
| 189 | + if (scrollDiff - pageScrollNodeHeight <= this.finalLowerThreshold) { | |
| 190 | + this._onLoadingMore('toBottom'); | |
| 191 | + } | |
| 192 | + } | |
| 193 | + }); | |
| 194 | + } else { | |
| 195 | + if (scrollDiff - this.cacheScrollNodeHeight <= this.finalLowerThreshold) { | |
| 196 | + this._onLoadingMore('toBottom'); | |
| 197 | + } else if (scrollDiff - this.cacheScrollNodeHeight <= 500 && !checked) { | |
| 198 | + u.delay(() => { | |
| 199 | + this._getNodeClientRect('.zp-scroll-view', true, true).then((res) => { | |
| 200 | + this.oldScrollTop = res[0].scrollTop; | |
| 201 | + const newScrollDiff = res[0].scrollHeight - this.oldScrollTop; | |
| 202 | + this._checkScrolledToBottom(newScrollDiff, true); | |
| 203 | + }) | |
| 204 | + }, 150, 'checkScrolledToBottomDelay') | |
| 205 | + } | |
| 206 | + } | |
| 207 | + }, | |
| 208 | + //触发加载更多时调用,from:toBottom-滑动到底部触发;1、click-点击加载更多触发 | |
| 209 | + _onLoadingMore(from = 'click') { | |
| 210 | + if (this.isIos && from === 'toBottom' && !this.scrollToBottomBounceEnabled && this.scrollEnable) { | |
| 211 | + this.scrollEnable = false; | |
| 212 | + this.$nextTick(() => { | |
| 213 | + this.scrollEnable = true; | |
| 214 | + }) | |
| 215 | + } | |
| 216 | + this.$emit('scrolltolower', from); | |
| 217 | + if (from === 'toBottom' && (!this.toBottomLoadingMoreEnabled || this.useChatRecordMode)) return; | |
| 218 | + if (this.refresherOnly || !this.loadingMoreEnabled || !(this.loadingStatus === Enum.More.Default || this.loadingStatus === Enum.More.Fail) || this.loading || this.showEmpty) return; | |
| 219 | + // #ifdef MP-WEIXIN | |
| 220 | + if (!this.isIos && !this.refresherOnly && !this.usePageScroll) { | |
| 221 | + const currentTimestamp = u.getTime(); | |
| 222 | + if (this.loadingMoreTimeStamp > 0 && currentTimestamp - this.loadingMoreTimeStamp < 100) { | |
| 223 | + this.loadingMoreTimeStamp = 0; | |
| 224 | + return; | |
| 225 | + } | |
| 226 | + } | |
| 227 | + // #endif | |
| 228 | + this._doLoadingMore(); | |
| 229 | + }, | |
| 230 | + //处理开始加载更多 | |
| 231 | + _doLoadingMore() { | |
| 232 | + if (this.pageNo >= this.defaultPageNo && this.loadingStatus !== Enum.More.NoMore) { | |
| 233 | + this.pageNo ++; | |
| 234 | + this._startLoading(false); | |
| 235 | + if (this.isLocalPaging) { | |
| 236 | + this._localPagingQueryList(this.pageNo, this.defaultPageSize, this.localPagingLoadingTime, res => { | |
| 237 | + this.completeByTotal(res, this.totalLocalPagingList.length); | |
| 238 | + }) | |
| 239 | + } else { | |
| 240 | + this._emitQuery(this.pageNo, this.defaultPageSize, Enum.QueryFrom.LoadingMore); | |
| 241 | + this._callMyParentQuery(); | |
| 242 | + } | |
| 243 | + this.loadingType = Enum.LoadingType.LoadingMore; | |
| 244 | + } | |
| 245 | + }, | |
| 246 | + //(预处理)判断当没有更多数据且分页内容未超出z-paging时是否显示没有更多数据的view | |
| 247 | + _preCheckShowNoMoreInside(newVal, scrollViewNode, pagingContainerNode) { | |
| 248 | + if (this.loadingStatus === Enum.More.NoMore && this.hideNoMoreByLimit > 0 && newVal.length) { | |
| 249 | + this.showLoadingMore = newVal.length > this.hideNoMoreByLimit; | |
| 250 | + } else if ((this.loadingStatus === Enum.More.NoMore && this.hideNoMoreInside && newVal.length) || (this.insideMore && this.insideOfPaging !== false && newVal.length)) { | |
| 251 | + this.$nextTick(() => { | |
| 252 | + this._checkShowNoMoreInside(newVal, scrollViewNode, pagingContainerNode); | |
| 253 | + }) | |
| 254 | + if (this.insideMore && this.insideOfPaging !== false && newVal.length) { | |
| 255 | + this.showLoadingMore = newVal.length; | |
| 256 | + } | |
| 257 | + } else { | |
| 258 | + this.showLoadingMore = newVal.length; | |
| 259 | + } | |
| 260 | + }, | |
| 261 | + //判断当没有更多数据且分页内容未超出z-paging时是否显示没有更多数据的view | |
| 262 | + async _checkShowNoMoreInside(totalData, oldScrollViewNode, oldPagingContainerNode) { | |
| 263 | + try { | |
| 264 | + const scrollViewNode = oldScrollViewNode || await this._getNodeClientRect('.zp-scroll-view'); | |
| 265 | + if (this.usePageScroll) { | |
| 266 | + if (scrollViewNode) { | |
| 267 | + const scrollViewTotalH = scrollViewNode[0].top + scrollViewNode[0].height; | |
| 268 | + this.insideOfPaging = scrollViewTotalH < this.windowHeight; | |
| 269 | + if (this.hideNoMoreInside) { | |
| 270 | + this.showLoadingMore = !this.insideOfPaging; | |
| 271 | + } | |
| 272 | + this._updateInsideOfPaging(); | |
| 273 | + } | |
| 274 | + } else { | |
| 275 | + const pagingContainerNode = oldPagingContainerNode || await this._getNodeClientRect('.zp-paging-container-content'); | |
| 276 | + const pagingContainerH = pagingContainerNode ? pagingContainerNode[0].height : 0; | |
| 277 | + const scrollViewH = scrollViewNode ? scrollViewNode[0].height : 0; | |
| 278 | + this.insideOfPaging = pagingContainerH < scrollViewH; | |
| 279 | + if (this.hideNoMoreInside) { | |
| 280 | + this.showLoadingMore = !this.insideOfPaging; | |
| 281 | + } | |
| 282 | + this._updateInsideOfPaging(); | |
| 283 | + } | |
| 284 | + } catch (e) { | |
| 285 | + this.insideOfPaging = !totalData.length; | |
| 286 | + if (this.hideNoMoreInside) { | |
| 287 | + this.showLoadingMore = !this.insideOfPaging; | |
| 288 | + } | |
| 289 | + this._updateInsideOfPaging(); | |
| 290 | + } | |
| 291 | + }, | |
| 292 | + //是否要展示上拉加载更多view | |
| 293 | + _showLoadingMore(type) { | |
| 294 | + if (!this.showLoadingMoreWhenReload && (!(this.loadingStatus === Enum.More.Default ? this.nShowBottom : true) || !this.realTotalData.length)) return false; | |
| 295 | + if (((!this.showLoadingMoreWhenReload || this.isUserPullDown || this.loadingStatus !== Enum.More.Loading) && !this.showLoadingMore) || | |
| 296 | + (!this.loadingMoreEnabled && (!this.showLoadingMoreWhenReload || this.isUserPullDown || this.loadingStatus !== Enum.More.Loading)) || this.refresherOnly) { | |
| 297 | + return false; | |
| 298 | + } | |
| 299 | + if (this.useChatRecordMode && type !== 'Loading') return false; | |
| 300 | + if (!this.zSlots) return false; | |
| 301 | + if (type === 'Custom') { | |
| 302 | + return this.showDefaultLoadingMoreText && !(this.loadingStatus === Enum.More.NoMore && !this.showLoadingMoreNoMoreView); | |
| 303 | + } | |
| 304 | + const res = this.loadingStatus === Enum.More[type] && this.zSlots[`loadingMore${type}`] && (type === 'NoMore' ? this.showLoadingMoreNoMoreView : true); | |
| 305 | + if (res) { | |
| 306 | + // #ifdef APP-NVUE | |
| 307 | + if (!this.isIos) { | |
| 308 | + this.nLoadingMoreFixedHeight = false; | |
| 309 | + } | |
| 310 | + // #endif | |
| 311 | + } | |
| 312 | + return res; | |
| 313 | + }, | |
| 314 | + } | |
| 315 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/modules/loading.js
0 → 100644
| 1 | +// [z-paging]loading相关模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | +import Enum from '.././z-paging-enum' | |
| 4 | + | |
| 5 | +export default { | |
| 6 | + props: { | |
| 7 | + //第一次加载后自动隐藏loading slot,默认为是 | |
| 8 | + autoHideLoadingAfterFirstLoaded: { | |
| 9 | + type: Boolean, | |
| 10 | + default: u.gc('autoHideLoadingAfterFirstLoaded', true) | |
| 11 | + }, | |
| 12 | + //loading slot是否铺满屏幕并固定,默认为否 | |
| 13 | + loadingFullFixed: { | |
| 14 | + type: Boolean, | |
| 15 | + default: u.gc('loadingFullFixed', false) | |
| 16 | + }, | |
| 17 | + //是否自动显示系统Loading:即uni.showLoading,若开启则将在刷新列表时(调用reload、refresh时)显示,下拉刷新和滚动到底部加载更多不会显示,默认为false。 | |
| 18 | + autoShowSystemLoading: { | |
| 19 | + type: Boolean, | |
| 20 | + default: u.gc('autoShowSystemLoading', false) | |
| 21 | + }, | |
| 22 | + //显示系统Loading时是否显示透明蒙层,防止触摸穿透,默认为是(H5、App、微信小程序、百度小程序有效) | |
| 23 | + systemLoadingMask: { | |
| 24 | + type: Boolean, | |
| 25 | + default: u.gc('systemLoadingMask', true) | |
| 26 | + }, | |
| 27 | + //显示系统Loading时显示的文字,默认为"加载中" | |
| 28 | + systemLoadingText: { | |
| 29 | + type: [String, Object], | |
| 30 | + default: u.gc('systemLoadingText', null) | |
| 31 | + }, | |
| 32 | + }, | |
| 33 | + data() { | |
| 34 | + return { | |
| 35 | + loading: false, | |
| 36 | + loadingForNow: false, | |
| 37 | + } | |
| 38 | + }, | |
| 39 | + watch: { | |
| 40 | + loadingStatus(newVal) { | |
| 41 | + this.$emit('loadingStatusChange', newVal); | |
| 42 | + this.$nextTick(() => { | |
| 43 | + this.loadingStatusAfterRender = newVal; | |
| 44 | + }) | |
| 45 | + // #ifdef APP-NVUE | |
| 46 | + if (this.useChatRecordMode) { | |
| 47 | + if (this.pageNo === this.defaultPageNo && newVal === Enum.More.NoMore) { | |
| 48 | + this.nIsFirstPageAndNoMore = true; | |
| 49 | + return; | |
| 50 | + } | |
| 51 | + } | |
| 52 | + this.nIsFirstPageAndNoMore = false; | |
| 53 | + // #endif | |
| 54 | + }, | |
| 55 | + loading(newVal){ | |
| 56 | + if (newVal) { | |
| 57 | + this.loadingForNow = newVal; | |
| 58 | + } | |
| 59 | + }, | |
| 60 | + }, | |
| 61 | + computed: { | |
| 62 | + showLoading() { | |
| 63 | + if (this.firstPageLoaded || !this.loading || !this.loadingForNow) return false; | |
| 64 | + if (this.finalShowSystemLoading){ | |
| 65 | + uni.showLoading({ | |
| 66 | + title: this.finalSystemLoadingText, | |
| 67 | + mask: this.systemLoadingMask | |
| 68 | + }) | |
| 69 | + } | |
| 70 | + return this.autoHideLoadingAfterFirstLoaded ? (this.fromEmptyViewReload ? true : !this.pagingLoaded) : this.loadingType === Enum.LoadingType.Refresher; | |
| 71 | + }, | |
| 72 | + finalShowSystemLoading() { | |
| 73 | + return this.autoShowSystemLoading && this.loadingType === Enum.LoadingType.Refresher; | |
| 74 | + } | |
| 75 | + }, | |
| 76 | + methods: { | |
| 77 | + //处理开始加载更多状态 | |
| 78 | + _startLoading(isReload = false) { | |
| 79 | + if ((this.showLoadingMoreWhenReload && !this.isUserPullDown) || !isReload) { | |
| 80 | + this.loadingStatus = Enum.More.Loading; | |
| 81 | + } | |
| 82 | + this.loading = true; | |
| 83 | + }, | |
| 84 | + //停止系统loading和refresh | |
| 85 | + _endSystemLoadingAndRefresh(){ | |
| 86 | + this.finalShowSystemLoading && uni.hideLoading(); | |
| 87 | + !this.useCustomRefresher && uni.stopPullDownRefresh(); | |
| 88 | + // #ifdef APP-NVUE | |
| 89 | + this.usePageScroll && uni.stopPullDownRefresh(); | |
| 90 | + // #endif | |
| 91 | + } | |
| 92 | + } | |
| 93 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/modules/nvue.js
0 → 100644
| 1 | +// [z-paging]nvue独有部分模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | +import c from '.././z-paging-constant' | |
| 4 | +import Enum from '.././z-paging-enum' | |
| 5 | + | |
| 6 | +// #ifdef APP-NVUE | |
| 7 | +const weexAnimation = weex.requireModule('animation'); | |
| 8 | +// #endif | |
| 9 | +export default { | |
| 10 | + props: { | |
| 11 | + // #ifdef APP-NVUE | |
| 12 | + //nvue中修改列表类型,可选值有list、waterfall和scroller,默认为list | |
| 13 | + nvueListIs: { | |
| 14 | + type: String, | |
| 15 | + default: u.gc('nvueListIs', 'list') | |
| 16 | + }, | |
| 17 | + //nvue waterfall配置,仅在nvue中且nvueListIs=waterfall时有效,配置参数详情参见:https://uniapp.dcloud.io/component/waterfall | |
| 18 | + nvueWaterfallConfig: { | |
| 19 | + type: Object, | |
| 20 | + default: function() { | |
| 21 | + return u.gc('nvueWaterfallConfig', {}); | |
| 22 | + } | |
| 23 | + }, | |
| 24 | + //nvue 控制是否回弹效果,iOS不支持动态修改 | |
| 25 | + nvueBounce: { | |
| 26 | + type: Boolean, | |
| 27 | + default: u.gc('nvueBounce', true) | |
| 28 | + }, | |
| 29 | + //nvue中通过代码滚动到顶部/底部时,是否加快动画效果(无滚动动画时无效),默认为否 | |
| 30 | + nvueFastScroll: { | |
| 31 | + type: Boolean, | |
| 32 | + default: u.gc('nvueFastScroll', false) | |
| 33 | + }, | |
| 34 | + //nvue中list的id | |
| 35 | + nvueListId: { | |
| 36 | + type: String, | |
| 37 | + default: u.gc('nvueListId', '') | |
| 38 | + }, | |
| 39 | + //nvue中refresh组件的样式 | |
| 40 | + nvueRefresherStyle: { | |
| 41 | + type: Object, | |
| 42 | + default: function() { | |
| 43 | + return u.gc('nvueRefresherStyle', {}); | |
| 44 | + } | |
| 45 | + }, | |
| 46 | + //nvue中是否按分页模式(类似竖向swiper)显示List,默认为false | |
| 47 | + nvuePagingEnabled: { | |
| 48 | + type: Boolean, | |
| 49 | + default: u.gc('nvuePagingEnabled', false) | |
| 50 | + }, | |
| 51 | + //是否隐藏nvue列表底部的tagView,此view用于标识滚动到底部位置,若隐藏则滚动到底部功能将失效,在nvue中实现吸顶+swiper功能时需将最外层z-paging的此属性设置为true。默认为否 | |
| 52 | + hideNvueBottomTag: { | |
| 53 | + type: Boolean, | |
| 54 | + default: u.gc('hideNvueBottomTag', false) | |
| 55 | + }, | |
| 56 | + //nvue中控制onscroll事件触发的频率:表示两次onscroll事件之间列表至少滚动了10px。注意,将该值设置为较小的数值会提高滚动事件采样的精度,但同时也会降低页面的性能 | |
| 57 | + offsetAccuracy: { | |
| 58 | + type: Number, | |
| 59 | + default: u.gc('offsetAccuracy', 10) | |
| 60 | + }, | |
| 61 | + // #endif | |
| 62 | + }, | |
| 63 | + data() { | |
| 64 | + return { | |
| 65 | + nRefresherLoading: false, | |
| 66 | + nListIsDragging: false, | |
| 67 | + nShowBottom: true, | |
| 68 | + nFixFreezing: false, | |
| 69 | + nShowRefresherReveal: false, | |
| 70 | + nIsFirstPageAndNoMore: false, | |
| 71 | + nFirstPageAndNoMoreChecked: false, | |
| 72 | + nLoadingMoreFixedHeight: false, | |
| 73 | + nShowRefresherRevealHeight: 0, | |
| 74 | + nOldShowRefresherRevealHeight: -1, | |
| 75 | + nRefresherWidth: uni.upx2px(750), | |
| 76 | + } | |
| 77 | + }, | |
| 78 | + watch: { | |
| 79 | + // #ifdef APP-NVUE | |
| 80 | + nIsFirstPageAndNoMore: { | |
| 81 | + handler(newVal) { | |
| 82 | + const cellStyle = !this.useChatRecordMode || newVal ? {} : { transform: 'rotate(180deg)' }; | |
| 83 | + this.$emit('update:cellStyle', cellStyle); | |
| 84 | + this.$emit('cellStyleChange', cellStyle); | |
| 85 | + }, | |
| 86 | + immediate: true | |
| 87 | + }, | |
| 88 | + // #endif | |
| 89 | + }, | |
| 90 | + computed: { | |
| 91 | + // #ifdef APP-NVUE | |
| 92 | + nScopedSlots() { | |
| 93 | + // #ifdef VUE2 | |
| 94 | + return this.$scopedSlots; | |
| 95 | + // #endif | |
| 96 | + // #ifdef VUE3 | |
| 97 | + return null; | |
| 98 | + // #endif | |
| 99 | + }, | |
| 100 | + nWaterfallColumnCount() { | |
| 101 | + if (this.finalNvueListIs !== 'waterfall') return 0; | |
| 102 | + return this._nGetWaterfallConfig('column-count', 2); | |
| 103 | + }, | |
| 104 | + nWaterfallColumnWidth() { | |
| 105 | + return this._nGetWaterfallConfig('column-width', 'auto'); | |
| 106 | + }, | |
| 107 | + nWaterfallColumnGap() { | |
| 108 | + return this._nGetWaterfallConfig('column-gap', 'normal'); | |
| 109 | + }, | |
| 110 | + nWaterfallLeftGap() { | |
| 111 | + return this._nGetWaterfallConfig('left-gap', 0); | |
| 112 | + }, | |
| 113 | + nWaterfallRightGap() { | |
| 114 | + return this._nGetWaterfallConfig('right-gap', 0); | |
| 115 | + }, | |
| 116 | + nViewIs() { | |
| 117 | + const is = this.finalNvueListIs; | |
| 118 | + return is === 'scroller' || is === 'view' ? 'view' : is === 'waterfall' ? 'header' : 'cell'; | |
| 119 | + }, | |
| 120 | + nSafeAreaBottomHeight() { | |
| 121 | + return this.safeAreaInsetBottom ? this.safeAreaBottom : 0; | |
| 122 | + }, | |
| 123 | + nChatRecordRotateStyle() { | |
| 124 | + return this.useChatRecordMode ? { transform: this.nIsFirstPageAndNoMore ? 'rotate(0deg)' : 'rotate(180deg)' } : {}; | |
| 125 | + }, | |
| 126 | + finalNvueListIs() { | |
| 127 | + if (this.usePageScroll) return 'view'; | |
| 128 | + const nvueListIsLowerCase = this.nvueListIs.toLowerCase(); | |
| 129 | + if (['list','waterfall','scroller'].indexOf(nvueListIsLowerCase) !== -1) return nvueListIsLowerCase; | |
| 130 | + return 'list'; | |
| 131 | + }, | |
| 132 | + finalNvueSuperListIs() { | |
| 133 | + return this.usePageScroll ? 'view' : 'scroller'; | |
| 134 | + }, | |
| 135 | + finalNvueRefresherEnabled() { | |
| 136 | + return this.finalNvueListIs !== 'view' && this.finalRefresherEnabled && !this.nShowRefresherReveal && !this.useChatRecordMode; | |
| 137 | + }, | |
| 138 | + // #endif | |
| 139 | + }, | |
| 140 | + mounted(){ | |
| 141 | + // #ifdef APP-NVUE | |
| 142 | + //旋转屏幕时更新宽度 | |
| 143 | + uni.onWindowResize((res) => { | |
| 144 | + // this._nUpdateRefresherWidth(); | |
| 145 | + }) | |
| 146 | + // #endif | |
| 147 | + }, | |
| 148 | + methods: { | |
| 149 | + // #ifdef APP-NVUE | |
| 150 | + //列表滚动时触发 | |
| 151 | + _nOnScroll(e) { | |
| 152 | + this.$emit('scroll', e); | |
| 153 | + const contentOffsetY = -e.contentOffset.y; | |
| 154 | + this.oldScrollTop = contentOffsetY; | |
| 155 | + this.nListIsDragging = e.isDragging; | |
| 156 | + this._checkShouldShowBackToTop(contentOffsetY, contentOffsetY - 1); | |
| 157 | + }, | |
| 158 | + //下拉刷新刷新中 | |
| 159 | + _nOnRrefresh() { | |
| 160 | + if (this.nShowRefresherReveal) return; | |
| 161 | + this.nRefresherLoading = true; | |
| 162 | + this.refresherStatus = Enum.Refresher.Loading; | |
| 163 | + this._doRefresherLoad(); | |
| 164 | + }, | |
| 165 | + //下拉刷新下拉中 | |
| 166 | + _nOnPullingdown(e) { | |
| 167 | + if (this.refresherStatus === Enum.Refresher.Loading || (this.isIos && !this.nListIsDragging)) return; | |
| 168 | + this._emitTouchmove(e); | |
| 169 | + const { viewHeight, pullingDistance } = e; | |
| 170 | + this.refresherStatus = pullingDistance >= viewHeight ? Enum.Refresher.ReleaseToRefresh : Enum.Refresher.Default; | |
| 171 | + }, | |
| 172 | + //下拉刷新结束 | |
| 173 | + _nRefresherEnd(doEnd = true) { | |
| 174 | + if (doEnd) { | |
| 175 | + this._nDoRefresherEndAnimation(0, -this.nShowRefresherRevealHeight); | |
| 176 | + !this.usePageScroll && this.$refs['zp-n-list'].resetLoadmore(); | |
| 177 | + this.nRefresherLoading = false; | |
| 178 | + } | |
| 179 | + }, | |
| 180 | + //执行主动触发下拉刷新动画 | |
| 181 | + _nDoRefresherEndAnimation(height, translateY, animate = true, checkStack = true) { | |
| 182 | + this._cleanRefresherCompleteTimeout(); | |
| 183 | + this._cleanRefresherEndTimeout(); | |
| 184 | + | |
| 185 | + if (!this.finalShowRefresherWhenReload) { | |
| 186 | + this.refresherEndTimeout = u.delay(() => { | |
| 187 | + this.refresherStatus = Enum.Refresher.Default; | |
| 188 | + }, this.refresherCompleteDuration); | |
| 189 | + return; | |
| 190 | + } | |
| 191 | + const stackCount = this.refresherRevealStackCount; | |
| 192 | + if (height === 0 && checkStack) { | |
| 193 | + this.refresherRevealStackCount --; | |
| 194 | + if (stackCount > 1) return; | |
| 195 | + this.refresherEndTimeout = u.delay(() => { | |
| 196 | + this.refresherStatus = Enum.Refresher.Default; | |
| 197 | + }, this.refresherCompleteDuration); | |
| 198 | + } | |
| 199 | + if (stackCount > 1) { | |
| 200 | + this.refresherStatus = Enum.Refresher.Loading; | |
| 201 | + } | |
| 202 | + | |
| 203 | + const duration = animate ? 200 : 0; | |
| 204 | + if (this.nOldShowRefresherRevealHeight !== height) { | |
| 205 | + if (height > 0) { | |
| 206 | + this.nShowRefresherReveal = true; | |
| 207 | + } | |
| 208 | + weexAnimation.transition(this.$refs['zp-n-list-refresher-reveal'], { | |
| 209 | + styles: { | |
| 210 | + height: `${height}px`, | |
| 211 | + transform: `translateY(${translateY}px)`, | |
| 212 | + }, | |
| 213 | + duration, | |
| 214 | + timingFunction: 'linear', | |
| 215 | + needLayout: true, | |
| 216 | + delay: 0 | |
| 217 | + }) | |
| 218 | + } | |
| 219 | + u.delay(() => { | |
| 220 | + if (animate) { | |
| 221 | + this.nShowRefresherReveal = height > 0; | |
| 222 | + } | |
| 223 | + }, duration > 0 ? duration - 60 : 0); | |
| 224 | + this.nOldShowRefresherRevealHeight = height; | |
| 225 | + }, | |
| 226 | + //滚动到底部加载更多 | |
| 227 | + _nOnLoadmore() { | |
| 228 | + if (this.nShowRefresherReveal || !this.totalData.length) return; | |
| 229 | + this.useChatRecordMode ? this.doChatRecordLoadMore() : this._onLoadingMore('toBottom'); | |
| 230 | + }, | |
| 231 | + //获取nvue waterfall单项配置 | |
| 232 | + _nGetWaterfallConfig(key, defaultValue) { | |
| 233 | + return this.nvueWaterfallConfig[key] || defaultValue; | |
| 234 | + }, | |
| 235 | + //更新nvue 下拉刷新view容器的宽度 | |
| 236 | + _nUpdateRefresherWidth() { | |
| 237 | + u.delay(() => { | |
| 238 | + this.$nextTick(()=>{ | |
| 239 | + this._getNodeClientRect('.zp-n-list').then(node => { | |
| 240 | + if (node) { | |
| 241 | + this.nRefresherWidth = node[0].width || this.nRefresherWidth; | |
| 242 | + } | |
| 243 | + }) | |
| 244 | + }) | |
| 245 | + }) | |
| 246 | + } | |
| 247 | + // #endif | |
| 248 | + } | |
| 249 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/modules/refresher.js
0 → 100644
| 1 | +// [z-paging]下拉刷新view模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | +import c from '.././z-paging-constant' | |
| 4 | +import Enum from '.././z-paging-enum' | |
| 5 | + | |
| 6 | +export default { | |
| 7 | + props: { | |
| 8 | + //下拉刷新的主题样式,支持black,white,默认black | |
| 9 | + refresherThemeStyle: { | |
| 10 | + type: String, | |
| 11 | + default: u.gc('refresherThemeStyle', '') | |
| 12 | + }, | |
| 13 | + //自定义下拉刷新中左侧图标的样式 | |
| 14 | + refresherImgStyle: { | |
| 15 | + type: Object, | |
| 16 | + default: function() { | |
| 17 | + return u.gc('refresherImgStyle', {}); | |
| 18 | + } | |
| 19 | + }, | |
| 20 | + //自定义下拉刷新中右侧状态描述文字的样式 | |
| 21 | + refresherTitleStyle: { | |
| 22 | + type: Object, | |
| 23 | + default: function() { | |
| 24 | + return u.gc('refresherTitleStyle', {}); | |
| 25 | + } | |
| 26 | + }, | |
| 27 | + //自定义下拉刷新中右侧最后更新时间文字的样式(show-refresher-update-time为true时有效) | |
| 28 | + refresherUpdateTimeStyle: { | |
| 29 | + type: Object, | |
| 30 | + default: function() { | |
| 31 | + return u.gc('refresherUpdateTimeStyle', {}); | |
| 32 | + } | |
| 33 | + }, | |
| 34 | + //在微信小程序和QQ小程序中,是否实时监听下拉刷新中进度,默认为否 | |
| 35 | + watchRefresherTouchmove: { | |
| 36 | + type: Boolean, | |
| 37 | + default: u.gc('watchRefresherTouchmove', false) | |
| 38 | + }, | |
| 39 | + //底部加载更多的主题样式,支持black,white,默认black | |
| 40 | + loadingMoreThemeStyle: { | |
| 41 | + type: String, | |
| 42 | + default: u.gc('loadingMoreThemeStyle', '') | |
| 43 | + }, | |
| 44 | + //是否只使用下拉刷新,设置为true后将关闭mounted自动请求数据、关闭滚动到底部加载更多,强制隐藏空数据图。默认为否 | |
| 45 | + refresherOnly: { | |
| 46 | + type: Boolean, | |
| 47 | + default: u.gc('refresherOnly', false) | |
| 48 | + }, | |
| 49 | + //自定义下拉刷新默认状态下回弹动画时间,单位为毫秒,默认为100毫秒,nvue无效 | |
| 50 | + refresherDefaultDuration: { | |
| 51 | + type: [Number, String], | |
| 52 | + default: u.gc('refresherDefaultDuration', 100) | |
| 53 | + }, | |
| 54 | + //自定义下拉刷新结束以后延迟回弹的时间,单位为毫秒,默认为0 | |
| 55 | + refresherCompleteDelay: { | |
| 56 | + type: [Number, String], | |
| 57 | + default: u.gc('refresherCompleteDelay', 0) | |
| 58 | + }, | |
| 59 | + //自定义下拉刷新结束回弹动画时间,单位为毫秒,默认为300毫秒(refresherEndBounceEnabled为false时,refresherCompleteDuration为设定值的1/3),nvue无效 | |
| 60 | + refresherCompleteDuration: { | |
| 61 | + type: [Number, String], | |
| 62 | + default: u.gc('refresherCompleteDuration', 300) | |
| 63 | + }, | |
| 64 | + //自定义下拉刷新结束状态下是否允许列表滚动,默认为否 | |
| 65 | + refresherCompleteScrollable: { | |
| 66 | + type: Boolean, | |
| 67 | + default: u.gc('refresherCompleteScrollable', false) | |
| 68 | + }, | |
| 69 | + //是否使用自定义的下拉刷新,默认为是,即使用z-paging的下拉刷新。设置为false即代表使用uni scroll-view自带的下拉刷新,h5、App、微信小程序以外的平台不支持uni scroll-view自带的下拉刷新 | |
| 70 | + useCustomRefresher: { | |
| 71 | + type: Boolean, | |
| 72 | + default: u.gc('useCustomRefresher', true) | |
| 73 | + }, | |
| 74 | + //自定义下拉刷新下拉帧率,默认为40,过高可能会出现抖动问题 | |
| 75 | + refresherFps: { | |
| 76 | + type: [Number, String], | |
| 77 | + default: u.gc('refresherFps', 40) | |
| 78 | + }, | |
| 79 | + //自定义下拉刷新允许触发的最大下拉角度,默认为40度,当下拉角度小于设定值时,自定义下拉刷新动画不会被触发 | |
| 80 | + refresherMaxAngle: { | |
| 81 | + type: [Number, String], | |
| 82 | + default: u.gc('refresherMaxAngle', 40) | |
| 83 | + }, | |
| 84 | + //自定义下拉刷新的角度由未达到最大角度变到达到最大角度时,是否继续下拉刷新手势,默认为否 | |
| 85 | + refresherAngleEnableChangeContinued: { | |
| 86 | + type: Boolean, | |
| 87 | + default: u.gc('refresherAngleEnableChangeContinued', false) | |
| 88 | + }, | |
| 89 | + //自定义下拉刷新默认状态下的文字 | |
| 90 | + refresherDefaultText: { | |
| 91 | + type: [String, Object], | |
| 92 | + default: u.gc('refresherDefaultText', null) | |
| 93 | + }, | |
| 94 | + //自定义下拉刷新松手立即刷新状态下的文字 | |
| 95 | + refresherPullingText: { | |
| 96 | + type: [String, Object], | |
| 97 | + default: u.gc('refresherPullingText', null) | |
| 98 | + }, | |
| 99 | + //自定义下拉刷新刷新中状态下的文字 | |
| 100 | + refresherRefreshingText: { | |
| 101 | + type: [String, Object], | |
| 102 | + default: u.gc('refresherRefreshingText', null) | |
| 103 | + }, | |
| 104 | + //自定义下拉刷新刷新结束状态下的文字 | |
| 105 | + refresherCompleteText: { | |
| 106 | + type: [String, Object], | |
| 107 | + default: u.gc('refresherCompleteText', null) | |
| 108 | + }, | |
| 109 | + //自定义下拉刷新默认状态下的图片 | |
| 110 | + refresherDefaultImg: { | |
| 111 | + type: String, | |
| 112 | + default: u.gc('refresherDefaultImg', null) | |
| 113 | + }, | |
| 114 | + //自定义下拉刷新松手立即刷新状态下的图片,默认与refresherDefaultImg一致 | |
| 115 | + refresherPullingImg: { | |
| 116 | + type: String, | |
| 117 | + default: u.gc('refresherPullingImg', null) | |
| 118 | + }, | |
| 119 | + //自定义下拉刷新刷新中状态下的图片 | |
| 120 | + refresherRefreshingImg: { | |
| 121 | + type: String, | |
| 122 | + default: u.gc('refresherRefreshingImg', null) | |
| 123 | + }, | |
| 124 | + //自定义下拉刷新刷新结束状态下的图片 | |
| 125 | + refresherCompleteImg: { | |
| 126 | + type: String, | |
| 127 | + default: u.gc('refresherCompleteImg', null) | |
| 128 | + }, | |
| 129 | + //自定义下拉刷新刷新中状态下是否展示旋转动画 | |
| 130 | + refresherRefreshingAnimated: { | |
| 131 | + type: Boolean, | |
| 132 | + default: u.gc('refresherRefreshingAnimated', true) | |
| 133 | + }, | |
| 134 | + //是否开启自定义下拉刷新刷新结束回弹效果,默认为是 | |
| 135 | + refresherEndBounceEnabled: { | |
| 136 | + type: Boolean, | |
| 137 | + default: u.gc('refresherEndBounceEnabled', true) | |
| 138 | + }, | |
| 139 | + //是否开启自定义下拉刷新,默认为是 | |
| 140 | + refresherEnabled: { | |
| 141 | + type: Boolean, | |
| 142 | + default: u.gc('refresherEnabled', true) | |
| 143 | + }, | |
| 144 | + //设置自定义下拉刷新阈值,默认为80rpx | |
| 145 | + refresherThreshold: { | |
| 146 | + type: [Number, String], | |
| 147 | + default: u.gc('refresherThreshold', '80rpx') | |
| 148 | + }, | |
| 149 | + //设置系统下拉刷新默认样式,支持设置 black,white,none,none 表示不使用默认样式,默认为black | |
| 150 | + refresherDefaultStyle: { | |
| 151 | + type: String, | |
| 152 | + default: u.gc('refresherDefaultStyle', 'black') | |
| 153 | + }, | |
| 154 | + //设置自定义下拉刷新区域背景 | |
| 155 | + refresherBackground: { | |
| 156 | + type: String, | |
| 157 | + default: u.gc('refresherBackground', 'transparent') | |
| 158 | + }, | |
| 159 | + //设置固定的自定义下拉刷新区域背景 | |
| 160 | + refresherFixedBackground: { | |
| 161 | + type: String, | |
| 162 | + default: u.gc('refresherFixedBackground', 'transparent') | |
| 163 | + }, | |
| 164 | + //设置固定的自定义下拉刷新区域高度,默认为0 | |
| 165 | + refresherFixedBacHeight: { | |
| 166 | + type: [Number, String], | |
| 167 | + default: u.gc('refresherFixedBacHeight', 0) | |
| 168 | + }, | |
| 169 | + //设置自定义下拉刷新下拉超出阈值后继续下拉位移衰减的比例,范围0-1,值越大代表衰减越多。默认为0.65(nvue无效) | |
| 170 | + refresherOutRate: { | |
| 171 | + type: Number, | |
| 172 | + default: u.gc('refresherOutRate', 0.65) | |
| 173 | + }, | |
| 174 | + //设置自定义下拉刷新下拉时实际下拉位移与用户下拉距离的比值,默认为0.75,即代表若用户下拉10px,则实际位移为7.5px(nvue无效) | |
| 175 | + refresherPullRate: { | |
| 176 | + type: Number, | |
| 177 | + default: u.gc('refresherPullRate', 0.75) | |
| 178 | + }, | |
| 179 | + //是否显示最后更新时间,默认为否 | |
| 180 | + showRefresherUpdateTime: { | |
| 181 | + type: Boolean, | |
| 182 | + default: u.gc('showRefresherUpdateTime', false) | |
| 183 | + }, | |
| 184 | + //如果需要区别不同页面的最后更新时间,请为不同页面的z-paging的`refresher-update-time-key`设置不同的字符串 | |
| 185 | + refresherUpdateTimeKey: { | |
| 186 | + type: String, | |
| 187 | + default: u.gc('refresherUpdateTimeKey', 'default') | |
| 188 | + }, | |
| 189 | + //下拉刷新时下拉到“松手立即刷新”状态时是否使手机短振动,默认为否(h5无效) | |
| 190 | + refresherVibrate: { | |
| 191 | + type: Boolean, | |
| 192 | + default: u.gc('refresherVibrate', false) | |
| 193 | + }, | |
| 194 | + //下拉刷新时是否禁止下拉刷新view跟随用户触摸竖直移动,默认为否。注意此属性只是禁止下拉刷新view移动,其他下拉刷新逻辑依然会正常触发 | |
| 195 | + refresherNoTransform: { | |
| 196 | + type: Boolean, | |
| 197 | + default: u.gc('refresherNoTransform', false) | |
| 198 | + }, | |
| 199 | + //是否开启下拉刷新状态栏占位,适用于隐藏导航栏时,下拉刷新需要避开状态栏高度的情况,默认为否 | |
| 200 | + useRefresherStatusBarPlaceholder: { | |
| 201 | + type: Boolean, | |
| 202 | + default: u.gc('useRefresherStatusBarPlaceholder', false) | |
| 203 | + }, | |
| 204 | + }, | |
| 205 | + data() { | |
| 206 | + return { | |
| 207 | + R: Enum.Refresher, | |
| 208 | + //下拉刷新状态 | |
| 209 | + refresherStatus: Enum.Refresher.Default, | |
| 210 | + refresherTouchstartY: 0, | |
| 211 | + lastRefresherTouchmove: null, | |
| 212 | + refresherReachMaxAngle: true, | |
| 213 | + refresherTransform: 'translateY(0px)', | |
| 214 | + refresherTransition: '', | |
| 215 | + finalRefresherDefaultStyle: 'black', | |
| 216 | + refresherRevealStackCount: 0, | |
| 217 | + refresherCompleteTimeout: null, | |
| 218 | + refresherCompleteSubTimeout: null, | |
| 219 | + refresherEndTimeout: null, | |
| 220 | + isTouchmovingTimeout: null, | |
| 221 | + refresherTriggered: false, | |
| 222 | + isTouchmoving: false, | |
| 223 | + isTouchEnded: false, | |
| 224 | + isUserPullDown: false, | |
| 225 | + privateRefresherEnabled: -1, | |
| 226 | + privateShowRefresherWhenReload: false, | |
| 227 | + customRefresherHeight: -1, | |
| 228 | + showCustomRefresher: false, | |
| 229 | + doRefreshAnimateAfter: false, | |
| 230 | + isRefresherInComplete: false, | |
| 231 | + pullDownTimeStamp: 0, | |
| 232 | + moveDis: 0, | |
| 233 | + oldMoveDis: 0, | |
| 234 | + currentDis: 0, | |
| 235 | + oldCurrentMoveDis: 0, | |
| 236 | + oldRefresherTouchmoveY: 0, | |
| 237 | + oldTouchDirection: '', | |
| 238 | + oldEmitedTouchDirection: '', | |
| 239 | + oldPullingDistance: -1, | |
| 240 | + refresherThresholdUpdateTag: 0 | |
| 241 | + } | |
| 242 | + }, | |
| 243 | + watch: { | |
| 244 | + refresherDefaultStyle: { | |
| 245 | + handler(newVal) { | |
| 246 | + if (newVal.length) { | |
| 247 | + this.finalRefresherDefaultStyle = newVal; | |
| 248 | + } | |
| 249 | + }, | |
| 250 | + immediate: true | |
| 251 | + }, | |
| 252 | + refresherStatus(newVal) { | |
| 253 | + newVal === Enum.Refresher.Loading && this._cleanRefresherEndTimeout(); | |
| 254 | + this.refresherVibrate && newVal === Enum.Refresher.ReleaseToRefresh && this._doVibrateShort(); | |
| 255 | + this.$emit('refresherStatusChange', newVal); | |
| 256 | + this.$emit('update:refresherStatus', newVal); | |
| 257 | + }, | |
| 258 | + refresherEnabled(newVal) { | |
| 259 | + !newVal && this.endRefresh(); | |
| 260 | + } | |
| 261 | + }, | |
| 262 | + computed: { | |
| 263 | + pullDownDisTimeStamp() { | |
| 264 | + return 1000 / this.refresherFps; | |
| 265 | + }, | |
| 266 | + finalRefresherEnabled() { | |
| 267 | + if (this.useChatRecordMode) return false; | |
| 268 | + if (this.privateRefresherEnabled === -1) return this.refresherEnabled; | |
| 269 | + return this.privateRefresherEnabled === 1; | |
| 270 | + }, | |
| 271 | + finalRefresherThreshold() { | |
| 272 | + let refresherThreshold = this.refresherThreshold; | |
| 273 | + let idDefault = false; | |
| 274 | + if (refresherThreshold === '80rpx') { | |
| 275 | + idDefault = true; | |
| 276 | + if (this.showRefresherUpdateTime) { | |
| 277 | + refresherThreshold = '120rpx'; | |
| 278 | + } | |
| 279 | + } | |
| 280 | + if (idDefault && this.customRefresherHeight > 0) return this.customRefresherHeight + this.finalRefresherThresholdPlaceholder; | |
| 281 | + return u.convertToPx(refresherThreshold) + this.finalRefresherThresholdPlaceholder; | |
| 282 | + }, | |
| 283 | + finalRefresherThresholdPlaceholder() { | |
| 284 | + return this.useRefresherStatusBarPlaceholder ? this.statusBarHeight : 0; | |
| 285 | + }, | |
| 286 | + finalRefresherFixedBacHeight() { | |
| 287 | + return u.convertToPx(this.refresherFixedBacHeight); | |
| 288 | + }, | |
| 289 | + finalRefresherThemeStyle() { | |
| 290 | + return this.refresherThemeStyle.length ? this.refresherThemeStyle : this.defaultThemeStyle; | |
| 291 | + }, | |
| 292 | + finalRefresherOutRate() { | |
| 293 | + let rate = this.refresherOutRate; | |
| 294 | + rate = Math.max(0,rate); | |
| 295 | + rate = Math.min(1,rate); | |
| 296 | + return rate; | |
| 297 | + }, | |
| 298 | + finalRefresherPullRate() { | |
| 299 | + let rate = this.refresherPullRate; | |
| 300 | + rate = Math.max(0,rate); | |
| 301 | + return rate; | |
| 302 | + }, | |
| 303 | + finalRefresherTransform() { | |
| 304 | + if (this.refresherNoTransform || this.refresherTransform === 'translateY(0px)') return 'none'; | |
| 305 | + return this.refresherTransform; | |
| 306 | + }, | |
| 307 | + finalShowRefresherWhenReload() { | |
| 308 | + return this.showRefresherWhenReload || this.privateShowRefresherWhenReload; | |
| 309 | + }, | |
| 310 | + finalRefresherTriggered() { | |
| 311 | + if (!(this.finalRefresherEnabled && !this.useCustomRefresher)) return false; | |
| 312 | + return this.refresherTriggered; | |
| 313 | + }, | |
| 314 | + showRefresher() { | |
| 315 | + const showRefresher = this.finalRefresherEnabled && this.useCustomRefresher; | |
| 316 | + // #ifndef APP-NVUE | |
| 317 | + this.customRefresherHeight === -1 && showRefresher && this.updateCustomRefresherHeight(); | |
| 318 | + // #endif | |
| 319 | + return showRefresher; | |
| 320 | + }, | |
| 321 | + hasTouchmove(){ | |
| 322 | + // #ifdef VUE2 | |
| 323 | + // #ifdef APP-VUE || H5 | |
| 324 | + if (this.$listeners && !this.$listeners.refresherTouchmove) return false; | |
| 325 | + // #endif | |
| 326 | + // #ifdef MP-WEIXIN || MP-QQ | |
| 327 | + return this.watchRefresherTouchmove; | |
| 328 | + // #endif | |
| 329 | + return true; | |
| 330 | + // #endif | |
| 331 | + return this.watchRefresherTouchmove; | |
| 332 | + }, | |
| 333 | + }, | |
| 334 | + methods: { | |
| 335 | + //终止下拉刷新状态 | |
| 336 | + endRefresh() { | |
| 337 | + this.totalData = this.realTotalData; | |
| 338 | + this._refresherEnd(); | |
| 339 | + this._endSystemLoadingAndRefresh(); | |
| 340 | + this._handleScrollViewDisableBounce({ bounce: true }); | |
| 341 | + this.$nextTick(() => { | |
| 342 | + this.refresherTriggered = false; | |
| 343 | + }) | |
| 344 | + }, | |
| 345 | + handleRefresherStatusChanged(func) { | |
| 346 | + this.refresherStatusChangedFunc = func; | |
| 347 | + }, | |
| 348 | + //手动更新自定义下拉刷新view高度 | |
| 349 | + updateCustomRefresherHeight() { | |
| 350 | + u.delay(() => this.$nextTick(this._updateCustomRefresherHeight)); | |
| 351 | + }, | |
| 352 | + //自定义下拉刷新被触发 | |
| 353 | + _onRefresh(fromScrollView = false,isUserPullDown = true) { | |
| 354 | + if (fromScrollView && !(this.finalRefresherEnabled && !this.useCustomRefresher)) return; | |
| 355 | + this.$emit('onRefresh'); | |
| 356 | + this.$emit('Refresh'); | |
| 357 | + // #ifdef APP-NVUE | |
| 358 | + if (this.loading) { | |
| 359 | + u.delay(this._nRefresherEnd, 500) | |
| 360 | + return; | |
| 361 | + } | |
| 362 | + // #endif | |
| 363 | + if (this.loading || this.isRefresherInComplete) return; | |
| 364 | + this.loadingType = Enum.LoadingType.Refresher; | |
| 365 | + if (this.nShowRefresherReveal) return; | |
| 366 | + this.isUserPullDown = isUserPullDown; | |
| 367 | + this.isUserReload = !isUserPullDown; | |
| 368 | + this._startLoading(true); | |
| 369 | + this.refresherTriggered = true; | |
| 370 | + if(this.reloadWhenRefresh && isUserPullDown){ | |
| 371 | + this.useChatRecordMode ? this._onLoadingMore('click') : this._reload(false, false, isUserPullDown); | |
| 372 | + } | |
| 373 | + }, | |
| 374 | + //自定义下拉刷新被复位 | |
| 375 | + _onRestore() { | |
| 376 | + this.refresherTriggered = 'restore'; | |
| 377 | + this.$emit('onRestore'); | |
| 378 | + this.$emit('Restore'); | |
| 379 | + }, | |
| 380 | + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 381 | + //拖拽开始 | |
| 382 | + _refresherTouchstart(e) { | |
| 383 | + this._handleListTouchstart(); | |
| 384 | + if (this._touchDisabled()) return; | |
| 385 | + this._handleRefresherTouchstart(u.getTouch(e)); | |
| 386 | + }, | |
| 387 | + // #endif | |
| 388 | + //进一步处理拖拽开始结果 | |
| 389 | + _handleRefresherTouchstart(touch) { | |
| 390 | + if (!this.loading && this.isTouchEnded) { | |
| 391 | + this.isTouchmoving = false; | |
| 392 | + } | |
| 393 | + this.loadingType = Enum.LoadingType.Refresher; | |
| 394 | + this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout); | |
| 395 | + this.isTouchEnded = false; | |
| 396 | + this.refresherTransition = ''; | |
| 397 | + this.refresherTouchstartY = touch.touchY; | |
| 398 | + this.$emit('refresherTouchstart', this.refresherTouchstartY); | |
| 399 | + this.lastRefresherTouchmove = touch; | |
| 400 | + this._cleanRefresherCompleteTimeout(); | |
| 401 | + this._cleanRefresherEndTimeout(); | |
| 402 | + }, | |
| 403 | + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 404 | + //拖拽中 | |
| 405 | + _refresherTouchmove(e) { | |
| 406 | + const currentTimeStamp = u.getTime(); | |
| 407 | + let touch = null; | |
| 408 | + let refresherTouchmoveY = 0; | |
| 409 | + if (this.watchTouchDirectionChange) { | |
| 410 | + touch = u.getTouch(e); | |
| 411 | + refresherTouchmoveY = touch.touchY; | |
| 412 | + const direction = refresherTouchmoveY > this.oldRefresherTouchmoveY ? 'top' : 'bottom'; | |
| 413 | + if (direction === this.oldTouchDirection && direction !== this.oldEmitedTouchDirection) { | |
| 414 | + this._handleTouchDirectionChange({ direction }); | |
| 415 | + this.oldEmitedTouchDirection = direction; | |
| 416 | + } | |
| 417 | + this.oldTouchDirection = direction; | |
| 418 | + this.oldRefresherTouchmoveY = refresherTouchmoveY; | |
| 419 | + } | |
| 420 | + if (this.pullDownTimeStamp && currentTimeStamp - this.pullDownTimeStamp <= this.pullDownDisTimeStamp) return; | |
| 421 | + if (this._touchDisabled()) return; | |
| 422 | + this.pullDownTimeStamp = Number(currentTimeStamp); | |
| 423 | + touch = u.getTouch(e); | |
| 424 | + refresherTouchmoveY = touch.touchY; | |
| 425 | + let moveDis = refresherTouchmoveY - this.refresherTouchstartY; | |
| 426 | + if (moveDis < 0) return; | |
| 427 | + if (this.refresherMaxAngle >= 0 && this.refresherMaxAngle <= 90 && this.lastRefresherTouchmove && this.lastRefresherTouchmove.touchY <= refresherTouchmoveY) { | |
| 428 | + if (!moveDis && !this.refresherAngleEnableChangeContinued && this.moveDis < 1 && !this.refresherReachMaxAngle) return; | |
| 429 | + const x = Math.abs(touch.touchX - this.lastRefresherTouchmove.touchX); | |
| 430 | + const y = Math.abs(refresherTouchmoveY - this.lastRefresherTouchmove.touchY); | |
| 431 | + const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); | |
| 432 | + if ((x || y) && x > 1) { | |
| 433 | + const angle = Math.asin(y / z) / Math.PI * 180; | |
| 434 | + if (angle < this.refresherMaxAngle) { | |
| 435 | + this.lastRefresherTouchmove = touch; | |
| 436 | + this.refresherReachMaxAngle = false; | |
| 437 | + return; | |
| 438 | + } | |
| 439 | + } | |
| 440 | + } | |
| 441 | + moveDis = this._getFinalRefresherMoveDis(moveDis); | |
| 442 | + this._handleRefresherTouchmove(moveDis, touch); | |
| 443 | + if (!this.disabledBounce) { | |
| 444 | + if(this.isIos){ | |
| 445 | + // #ifndef MP-LARK | |
| 446 | + this._handleScrollViewDisableBounce({ bounce: false }); | |
| 447 | + // #endif | |
| 448 | + } | |
| 449 | + this.disabledBounce = true; | |
| 450 | + } | |
| 451 | + this._emitTouchmove({ pullingDistance: moveDis, dy: this.moveDis - this.oldMoveDis }); | |
| 452 | + }, | |
| 453 | + // #endif | |
| 454 | + //进一步处理拖拽中结果 | |
| 455 | + _handleRefresherTouchmove(moveDis, touch) { | |
| 456 | + this.refresherReachMaxAngle = true; | |
| 457 | + this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout); | |
| 458 | + this.isTouchmoving = true; | |
| 459 | + this.isTouchEnded = false; | |
| 460 | + this.refresherStatus = moveDis >= this.finalRefresherThreshold ? Enum.Refresher.ReleaseToRefresh : this.refresherStatus = Enum.Refresher.Default; | |
| 461 | + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 462 | + // this.scrollEnable = false; | |
| 463 | + this.refresherTransform = `translateY(${moveDis}px)`; | |
| 464 | + this.lastRefresherTouchmove = touch; | |
| 465 | + // #endif | |
| 466 | + this.moveDis = moveDis; | |
| 467 | + }, | |
| 468 | + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 469 | + //拖拽结束 | |
| 470 | + _refresherTouchend(e) { | |
| 471 | + if (this._touchDisabled() || !this.isTouchmoving) return; | |
| 472 | + const touch = u.getTouch(e); | |
| 473 | + let refresherTouchendY = touch.touchY; | |
| 474 | + let moveDis = refresherTouchendY - this.refresherTouchstartY; | |
| 475 | + moveDis = this._getFinalRefresherMoveDis(moveDis); | |
| 476 | + this._handleRefresherTouchend(moveDis); | |
| 477 | + this._handleScrollViewDisableBounce({bounce: true}); | |
| 478 | + this.disabledBounce = false; | |
| 479 | + }, | |
| 480 | + // #endif | |
| 481 | + //进一步处理拖拽结束结果 | |
| 482 | + _handleRefresherTouchend(moveDis) { | |
| 483 | + // #ifndef APP-PLUS || H5 || MP-WEIXIN | |
| 484 | + if (!this.isTouchmoving) return; | |
| 485 | + // #endif | |
| 486 | + this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout); | |
| 487 | + this.refresherReachMaxAngle = true; | |
| 488 | + this.isTouchEnded = true; | |
| 489 | + const refresherThreshold = this.finalRefresherThreshold; | |
| 490 | + if (moveDis >= refresherThreshold && this.refresherStatus === Enum.Refresher.ReleaseToRefresh) { | |
| 491 | + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 492 | + this.refresherTransform = `translateY(${refresherThreshold}px)`; | |
| 493 | + this.refresherTransition = 'transform .1s linear'; | |
| 494 | + // #endif | |
| 495 | + u.delay(() => { | |
| 496 | + this._emitTouchmove({ pullingDistance: refresherThreshold, dy: this.moveDis - refresherThreshold }); | |
| 497 | + }, 0.1); | |
| 498 | + this.moveDis = refresherThreshold; | |
| 499 | + this.refresherStatus = Enum.Refresher.Loading; | |
| 500 | + this._doRefresherLoad(); | |
| 501 | + } else { | |
| 502 | + this._refresherEnd(); | |
| 503 | + this.isTouchmovingTimeout = u.delay(() => { | |
| 504 | + this.isTouchmoving = false; | |
| 505 | + }, this.refresherDefaultDuration); | |
| 506 | + } | |
| 507 | + this.scrollEnable = true; | |
| 508 | + this.$emit('refresherTouchend', moveDis); | |
| 509 | + }, | |
| 510 | + //处理列表触摸开始事件 | |
| 511 | + _handleListTouchstart() { | |
| 512 | + if (this.useChatRecordMode && this.autoHideKeyboardWhenChat) { | |
| 513 | + uni.hideKeyboard(); | |
| 514 | + this.$emit('hidedKeyboard'); | |
| 515 | + } | |
| 516 | + }, | |
| 517 | + //处理scroll-view bounce是否生效 | |
| 518 | + _handleScrollViewDisableBounce({ bounce }) { | |
| 519 | + if (!this.usePageScroll && !this.scrollToTopBounceEnabled && this.wxsScrollTop <= 5) { | |
| 520 | + // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 521 | + this.refresherTransition = ''; | |
| 522 | + // #endif | |
| 523 | + this.scrollEnable = bounce; | |
| 524 | + } | |
| 525 | + }, | |
| 526 | + //wxs正在下拉状态改变处理 | |
| 527 | + _handleWxsPullingDownStatusChange(onPullingDown) { | |
| 528 | + this.wxsOnPullingDown = onPullingDown; | |
| 529 | + if (onPullingDown && !this.useChatRecordMode) { | |
| 530 | + this.renderPropScrollTop = 0; | |
| 531 | + } | |
| 532 | + }, | |
| 533 | + //wxs正在下拉处理 | |
| 534 | + _handleWxsPullingDown({ moveDis, diffDis }){ | |
| 535 | + this._emitTouchmove({ pullingDistance: moveDis,dy: diffDis }); | |
| 536 | + }, | |
| 537 | + //wxs触摸方向改变 | |
| 538 | + _handleTouchDirectionChange({ direction }) { | |
| 539 | + this.$emit('touchDirectionChange',direction); | |
| 540 | + }, | |
| 541 | + //wxs通知更新其props | |
| 542 | + _handlePropUpdate(){ | |
| 543 | + this.wxsPropType = u.getTime().toString(); | |
| 544 | + }, | |
| 545 | + //下拉刷新结束 | |
| 546 | + _refresherEnd(shouldEndLoadingDelay = true, fromAddData = false, isUserPullDown = false, setLoading = true) { | |
| 547 | + if (this.loadingType === Enum.LoadingType.Refresher) { | |
| 548 | + const refresherCompleteDelay = (fromAddData && (isUserPullDown || this.showRefresherWhenReload)) ? this.refresherCompleteDelay : 0; | |
| 549 | + const refresherStatus = refresherCompleteDelay > 0 ? Enum.Refresher.Complete : Enum.Refresher.Default; | |
| 550 | + if (this.finalShowRefresherWhenReload) { | |
| 551 | + const stackCount = this.refresherRevealStackCount; | |
| 552 | + this.refresherRevealStackCount --; | |
| 553 | + if (stackCount > 1) return; | |
| 554 | + } | |
| 555 | + this._cleanRefresherEndTimeout(); | |
| 556 | + this.refresherEndTimeout = u.delay(() => { | |
| 557 | + this.refresherStatus = refresherStatus; | |
| 558 | + }, this.refresherStatus !== Enum.Refresher.Default && refresherStatus === Enum.Refresher.Default ? this.refresherCompleteDuration : 0); | |
| 559 | + | |
| 560 | + // #ifndef APP-NVUE | |
| 561 | + if (refresherCompleteDelay > 0) { | |
| 562 | + this.isRefresherInComplete = true; | |
| 563 | + } | |
| 564 | + // #endif | |
| 565 | + this._cleanRefresherCompleteTimeout(); | |
| 566 | + this.refresherCompleteTimeout = u.delay(() => { | |
| 567 | + let animateDuration = 1; | |
| 568 | + const animateType = this.refresherEndBounceEnabled && fromAddData ? 'cubic-bezier(0.19,1.64,0.42,0.72)' : 'linear'; | |
| 569 | + if (fromAddData) { | |
| 570 | + animateDuration = this.refresherEndBounceEnabled ? this.refresherCompleteDuration / 1000 : this.refresherCompleteDuration / 3000; | |
| 571 | + } | |
| 572 | + this.refresherTransition = `transform ${fromAddData ? animateDuration : this.refresherDefaultDuration / 1000}s ${animateType}`; | |
| 573 | + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 574 | + this.refresherTransform = 'translateY(0px)'; | |
| 575 | + this.currentDis = 0; | |
| 576 | + // #endif | |
| 577 | + // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 578 | + this.wxsPropType = this.refresherTransition + 'end' + u.getTime(); | |
| 579 | + // #endif | |
| 580 | + // #ifdef APP-NVUE | |
| 581 | + this._nRefresherEnd(); | |
| 582 | + // #endif | |
| 583 | + this.moveDis = 0; | |
| 584 | + // #ifndef APP-NVUE | |
| 585 | + if (refresherStatus === Enum.Refresher.Complete) { | |
| 586 | + if (this.refresherCompleteSubTimeout) { | |
| 587 | + clearTimeout(this.refresherCompleteSubTimeout); | |
| 588 | + this.refresherCompleteSubTimeout = null; | |
| 589 | + } | |
| 590 | + this.refresherCompleteSubTimeout = u.delay(() => { | |
| 591 | + this.$nextTick(() => { | |
| 592 | + this.refresherStatus = Enum.Refresher.Default; | |
| 593 | + this.isRefresherInComplete = false; | |
| 594 | + }) | |
| 595 | + }, animateDuration * 800); | |
| 596 | + } | |
| 597 | + // #endif | |
| 598 | + this._emitTouchmove({ pullingDistance: 0, dy: this.moveDis }); | |
| 599 | + }, refresherCompleteDelay); | |
| 600 | + } | |
| 601 | + if (setLoading) { | |
| 602 | + u.delay(() => this.loading = false, shouldEndLoadingDelay ? c.delayTime : 0); | |
| 603 | + isUserPullDown && this._onRestore(); | |
| 604 | + } | |
| 605 | + }, | |
| 606 | + //模拟用户手动触发下拉刷新 | |
| 607 | + _doRefresherRefreshAnimate() { | |
| 608 | + this._cleanRefresherCompleteTimeout(); | |
| 609 | + // #ifndef APP-NVUE | |
| 610 | + const doRefreshAnimateAfter = !this.doRefreshAnimateAfter && (this.finalShowRefresherWhenReload) && this | |
| 611 | + .customRefresherHeight === -1 && this.refresherThreshold === '80rpx'; | |
| 612 | + if (doRefreshAnimateAfter) { | |
| 613 | + this.doRefreshAnimateAfter = true; | |
| 614 | + return; | |
| 615 | + } | |
| 616 | + // #endif | |
| 617 | + this.refresherRevealStackCount ++; | |
| 618 | + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 619 | + this.refresherTransform = `translateY(${this.finalRefresherThreshold}px)`; | |
| 620 | + // #endif | |
| 621 | + // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 622 | + this.wxsPropType = 'begin' + u.getTime(); | |
| 623 | + // #endif | |
| 624 | + this.moveDis = this.finalRefresherThreshold; | |
| 625 | + this.refresherStatus = Enum.Refresher.Loading; | |
| 626 | + this.isTouchmoving = true; | |
| 627 | + this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout); | |
| 628 | + this._doRefresherLoad(false); | |
| 629 | + }, | |
| 630 | + //触发下拉刷新 | |
| 631 | + _doRefresherLoad(isUserPullDown = true) { | |
| 632 | + this._onRefresh(false,isUserPullDown); | |
| 633 | + this.loading = true; | |
| 634 | + }, | |
| 635 | + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 | |
| 636 | + //获取处理后的moveDis | |
| 637 | + _getFinalRefresherMoveDis(moveDis) { | |
| 638 | + let diffDis = moveDis - this.oldCurrentMoveDis; | |
| 639 | + this.oldCurrentMoveDis = moveDis; | |
| 640 | + if (diffDis > 0) { | |
| 641 | + diffDis = diffDis * this.finalRefresherPullRate; | |
| 642 | + if (this.currentDis > this.finalRefresherThreshold) { | |
| 643 | + diffDis = diffDis * (1 - this.finalRefresherOutRate); | |
| 644 | + } | |
| 645 | + } | |
| 646 | + diffDis = diffDis > 100 ? diffDis / 100 : diffDis; | |
| 647 | + this.currentDis += diffDis; | |
| 648 | + this.currentDis = Math.max(0, this.currentDis); | |
| 649 | + return this.currentDis; | |
| 650 | + }, | |
| 651 | + //判断touch手势是否要触发 | |
| 652 | + _touchDisabled() { | |
| 653 | + const checkOldScrollTop = this.oldScrollTop > 5; | |
| 654 | + return this.loading || this.isRefresherInComplete || this.useChatRecordMode || !this.refresherEnabled || !this.useCustomRefresher ||(this.usePageScroll && this.useCustomRefresher && this.pageScrollTop > 10) || (!(this.usePageScroll && this.useCustomRefresher) && checkOldScrollTop); | |
| 655 | + }, | |
| 656 | + // #endif | |
| 657 | + //更新自定义下拉刷新view高度 | |
| 658 | + _updateCustomRefresherHeight() { | |
| 659 | + this._getNodeClientRect('.zp-custom-refresher-slot-view').then((res) => { | |
| 660 | + this.customRefresherHeight = res ? res[0].height : 0; | |
| 661 | + this.showCustomRefresher = this.customRefresherHeight > 0; | |
| 662 | + if (this.doRefreshAnimateAfter) { | |
| 663 | + this.doRefreshAnimateAfter = false; | |
| 664 | + this._doRefresherRefreshAnimate(); | |
| 665 | + } | |
| 666 | + }); | |
| 667 | + }, | |
| 668 | + //发射pullingDown事件 | |
| 669 | + _emitTouchmove(e) { | |
| 670 | + // #ifndef APP-NVUE | |
| 671 | + e.viewHeight = this.finalRefresherThreshold; | |
| 672 | + // #endif | |
| 673 | + e.rate = e.viewHeight > 0 ? e.pullingDistance / e.viewHeight : 0; | |
| 674 | + this.hasTouchmove && this.oldPullingDistance !== e.pullingDistance && this.$emit('refresherTouchmove', e); | |
| 675 | + this.oldPullingDistance = e.pullingDistance; | |
| 676 | + }, | |
| 677 | + //清除refresherCompleteTimeout | |
| 678 | + _cleanRefresherCompleteTimeout() { | |
| 679 | + this.refresherCompleteTimeout = this._cleanTimeout(this.refresherCompleteTimeout); | |
| 680 | + // #ifdef APP-NVUE | |
| 681 | + this._nRefresherEnd(false); | |
| 682 | + // #endif | |
| 683 | + }, | |
| 684 | + //清除refresherEndTimeout | |
| 685 | + _cleanRefresherEndTimeout() { | |
| 686 | + this.refresherEndTimeout = this._cleanTimeout(this.refresherEndTimeout); | |
| 687 | + }, | |
| 688 | + } | |
| 689 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/modules/scroller.js
0 → 100644
| 1 | +// [z-paging]scroll相关模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | +import Enum from '.././z-paging-enum' | |
| 4 | + | |
| 5 | +// #ifdef APP-NVUE | |
| 6 | +const weexDom = weex.requireModule('dom'); | |
| 7 | +// #endif | |
| 8 | + | |
| 9 | +export default { | |
| 10 | + props: { | |
| 11 | + //使用页面滚动,默认为否,当设置为是时则使用页面的滚动而非此组件内部的scroll-view的滚动,使用页面滚动时z-paging无需设置确定的高度且对于长列表展示性能更高,但配置会略微繁琐 | |
| 12 | + usePageScroll: { | |
| 13 | + type: Boolean, | |
| 14 | + default: u.gc('usePageScroll', false) | |
| 15 | + }, | |
| 16 | + //是否可以滚动,使用内置scroll-view和nvue时有效,默认为是 | |
| 17 | + scrollable: { | |
| 18 | + type: Boolean, | |
| 19 | + default: u.gc('scrollable', true) | |
| 20 | + }, | |
| 21 | + //控制是否出现滚动条,默认为是 | |
| 22 | + showScrollbar: { | |
| 23 | + type: Boolean, | |
| 24 | + default: u.gc('showScrollbar', true) | |
| 25 | + }, | |
| 26 | + //是否允许横向滚动,默认为否 | |
| 27 | + scrollX: { | |
| 28 | + type: Boolean, | |
| 29 | + default: u.gc('scrollX', false) | |
| 30 | + }, | |
| 31 | + //iOS设备上滚动到顶部时是否允许回弹效果,默认为否。关闭回弹效果后可使滚动到顶部与下拉刷新更连贯,但是有吸顶view时滚动到顶部时可能出现抖动。 | |
| 32 | + scrollToTopBounceEnabled: { | |
| 33 | + type: Boolean, | |
| 34 | + default: u.gc('scrollToTopBounceEnabled', false) | |
| 35 | + }, | |
| 36 | + //iOS设备上滚动到底部时是否允许回弹效果,默认为是。 | |
| 37 | + scrollToBottomBounceEnabled: { | |
| 38 | + type: Boolean, | |
| 39 | + default: u.gc('scrollToBottomBounceEnabled', true) | |
| 40 | + }, | |
| 41 | + //在设置滚动条位置时使用动画过渡,默认为否 | |
| 42 | + scrollWithAnimation: { | |
| 43 | + type: Boolean, | |
| 44 | + default: u.gc('scrollWithAnimation', false) | |
| 45 | + }, | |
| 46 | + //值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 | |
| 47 | + scrollIntoView: { | |
| 48 | + type: String, | |
| 49 | + default: u.gc('scrollIntoView', '') | |
| 50 | + }, | |
| 51 | + }, | |
| 52 | + data() { | |
| 53 | + return { | |
| 54 | + scrollTop: 0, | |
| 55 | + oldScrollTop: 0, | |
| 56 | + scrollViewStyle: {}, | |
| 57 | + scrollViewContainerStyle: {}, | |
| 58 | + scrollViewInStyle: {}, | |
| 59 | + pageScrollTop: -1, | |
| 60 | + scrollEnable: true, | |
| 61 | + privateScrollWithAnimation: -1, | |
| 62 | + cacheScrollNodeHeight: -1 | |
| 63 | + } | |
| 64 | + }, | |
| 65 | + watch: { | |
| 66 | + oldScrollTop(newVal) { | |
| 67 | + !this.usePageScroll && this._scrollTopChange(newVal,false); | |
| 68 | + }, | |
| 69 | + pageScrollTop(newVal) { | |
| 70 | + this.usePageScroll && this._scrollTopChange(newVal,true); | |
| 71 | + }, | |
| 72 | + usePageScroll: { | |
| 73 | + handler(newVal) { | |
| 74 | + this.loaded && this.autoHeight && this._setAutoHeight(!newVal); | |
| 75 | + // #ifdef H5 | |
| 76 | + if (newVal) { | |
| 77 | + this.$nextTick(() => { | |
| 78 | + const mainScrollRef = this.$refs['zp-scroll-view'].$refs.main; | |
| 79 | + if (mainScrollRef) { | |
| 80 | + mainScrollRef.style = {}; | |
| 81 | + } | |
| 82 | + }) | |
| 83 | + } | |
| 84 | + // #endif | |
| 85 | + }, | |
| 86 | + immediate: true | |
| 87 | + }, | |
| 88 | + finalScrollTop(newVal) { | |
| 89 | + if (!this.useChatRecordMode) { | |
| 90 | + this.renderPropScrollTop = newVal < 6 ? 0 : 10; | |
| 91 | + } | |
| 92 | + }, | |
| 93 | + }, | |
| 94 | + computed: { | |
| 95 | + finalScrollWithAnimation() { | |
| 96 | + if (this.privateScrollWithAnimation !== -1) { | |
| 97 | + const scrollWithAnimation = this.privateScrollWithAnimation === 1; | |
| 98 | + this.privateScrollWithAnimation = -1; | |
| 99 | + return scrollWithAnimation; | |
| 100 | + } | |
| 101 | + return this.scrollWithAnimation; | |
| 102 | + }, | |
| 103 | + finalScrollViewStyle() { | |
| 104 | + if (this.superContentZIndex != 1) { | |
| 105 | + this.scrollViewStyle['z-index'] = this.superContentZIndex; | |
| 106 | + this.scrollViewStyle['position'] = 'relative'; | |
| 107 | + } | |
| 108 | + return this.scrollViewStyle; | |
| 109 | + }, | |
| 110 | + finalScrollTop() { | |
| 111 | + return this.usePageScroll ? this.pageScrollTop : this.oldScrollTop; | |
| 112 | + }, | |
| 113 | + finalIsOldWebView() { | |
| 114 | + return this.isOldWebView && !this.usePageScroll; | |
| 115 | + } | |
| 116 | + }, | |
| 117 | + methods: { | |
| 118 | + //滚动到顶部,animate为是否展示滚动动画,默认为是 | |
| 119 | + scrollToTop(animate, checkReverse = true) { | |
| 120 | + // #ifdef APP-NVUE | |
| 121 | + if (checkReverse && this.useChatRecordMode) { | |
| 122 | + if (!this.nIsFirstPageAndNoMore) { | |
| 123 | + this.scrollToBottom(animate, false); | |
| 124 | + return; | |
| 125 | + } | |
| 126 | + } | |
| 127 | + // #endif | |
| 128 | + this.$nextTick(() => { | |
| 129 | + this._scrollToTop(animate, false); | |
| 130 | + // #ifdef APP-NVUE | |
| 131 | + if (this.nvueFastScroll && animate) { | |
| 132 | + u.delay(() => { | |
| 133 | + this._scrollToTop(false, false); | |
| 134 | + }); | |
| 135 | + } | |
| 136 | + // #endif | |
| 137 | + }) | |
| 138 | + }, | |
| 139 | + //滚动到底部,animate为是否展示滚动动画,默认为是 | |
| 140 | + scrollToBottom(animate, checkReverse = true) { | |
| 141 | + // #ifdef APP-NVUE | |
| 142 | + if (checkReverse && this.useChatRecordMode) { | |
| 143 | + if (!this.nIsFirstPageAndNoMore) { | |
| 144 | + this.scrollToTop(animate, false); | |
| 145 | + return; | |
| 146 | + } | |
| 147 | + } | |
| 148 | + // #endif | |
| 149 | + this.$nextTick(() => { | |
| 150 | + this._scrollToBottom(animate); | |
| 151 | + // #ifdef APP-NVUE | |
| 152 | + if (this.nvueFastScroll && animate) { | |
| 153 | + u.delay(() => { | |
| 154 | + this._scrollToBottom(false); | |
| 155 | + }); | |
| 156 | + } | |
| 157 | + // #endif | |
| 158 | + }) | |
| 159 | + }, | |
| 160 | + //滚动到指定view(vue中有效)。sel为需要滚动的view的id值,不包含"#";offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 | |
| 161 | + scrollIntoViewById(sel, offset, animate) { | |
| 162 | + this._scrollIntoView(sel, offset, animate); | |
| 163 | + }, | |
| 164 | + //滚动到指定view(vue中有效)。nodeTop为需要滚动的view的top值(通过uni.createSelectorQuery()获取);offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 | |
| 165 | + scrollIntoViewByNodeTop(nodeTop, offset, animate) { | |
| 166 | + this.scrollTop = this.oldScrollTop; | |
| 167 | + this.$nextTick(() => { | |
| 168 | + this._scrollIntoViewByNodeTop(nodeTop, offset, animate); | |
| 169 | + }) | |
| 170 | + }, | |
| 171 | + //滚动到指定位置(vue中有效)。y为与顶部的距离,单位为px;offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 | |
| 172 | + scrollToY(y, offset, animate) { | |
| 173 | + this.scrollTop = this.oldScrollTop; | |
| 174 | + this.$nextTick(() => { | |
| 175 | + this._scrollToY(y, offset, animate); | |
| 176 | + }) | |
| 177 | + }, | |
| 178 | + //滚动到指定view(nvue中有效)。index为需要滚动的view的index(第几个);offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 | |
| 179 | + scrollIntoViewByIndex(index, offset, animate) { | |
| 180 | + this._scrollIntoView(index, offset, animate); | |
| 181 | + }, | |
| 182 | + //滚动到指定view(nvue中有效)。view为需要滚动的view(通过`this.$refs.xxx`获取),不包含"#";offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 | |
| 183 | + scrollIntoViewByView(view, offset, animate) { | |
| 184 | + this._scrollIntoView(view, offset, animate); | |
| 185 | + }, | |
| 186 | + //当使用页面滚动并且自定义下拉刷新时,请在页面的onPageScroll中调用此方法,告知z-paging当前的pageScrollTop,否则会导致在任意位置都可以下拉刷新 | |
| 187 | + updatePageScrollTop(value) { | |
| 188 | + this.pageScrollTop = value; | |
| 189 | + }, | |
| 190 | + //当使用页面滚动并且设置了slot="top"时,默认初次加载会自动获取其高度,并使内部容器下移,当slot="top"的view高度动态改变时,在其高度需要更新时调用此方法 | |
| 191 | + updatePageScrollTopHeight() { | |
| 192 | + this._updatePageScrollTopOrBottomHeight('top'); | |
| 193 | + }, | |
| 194 | + //当使用页面滚动并且设置了slot="bottom"时,默认初次加载会自动获取其高度,并使内部容器下移,当slot="bottom"的view高度动态改变时,在其高度需要更新时调用此方法 | |
| 195 | + updatePageScrollBottomHeight() { | |
| 196 | + this._updatePageScrollTopOrBottomHeight('bottom'); | |
| 197 | + }, | |
| 198 | + //更新slot="left"和slot="right"宽度,当slot="left"或slot="right"宽度动态改变时调用 | |
| 199 | + updateLeftAndRightWidth() { | |
| 200 | + if (!this.finalIsOldWebView) return; | |
| 201 | + this.$nextTick(() => this._updateLeftAndRightWidth(this.scrollViewContainerStyle, 'zp-page')); | |
| 202 | + }, | |
| 203 | + //更新z-paging内置scroll-view的scrollTop | |
| 204 | + updateScrollViewScrollTop(scrollTop, animate = true) { | |
| 205 | + this.privateScrollWithAnimation = animate ? 1 : 0; | |
| 206 | + this.scrollTop = this.oldScrollTop; | |
| 207 | + this.$nextTick(() => { | |
| 208 | + this.scrollTop = scrollTop; | |
| 209 | + this.oldScrollTop = this.scrollTop; | |
| 210 | + }); | |
| 211 | + }, | |
| 212 | + | |
| 213 | + //当滚动到顶部时 | |
| 214 | + _onScrollToUpper() { | |
| 215 | + this.$emit('scrolltoupper'); | |
| 216 | + this.$emit('scrollTopChange', 0); | |
| 217 | + this.$nextTick(() => { | |
| 218 | + this.oldScrollTop = 0; | |
| 219 | + }) | |
| 220 | + this.useChatRecordMode && this.loadingStatus !== Enum.More.NoMore && this._onLoadingMore('click'); | |
| 221 | + }, | |
| 222 | + //当滚动到底部时 | |
| 223 | + _onScrollToLower(e) { | |
| 224 | + (!e.detail || !e.detail.direction || e.detail.direction === 'bottom') && this._onLoadingMore('toBottom') | |
| 225 | + }, | |
| 226 | + //滚动到顶部 | |
| 227 | + _scrollToTop(animate = true, isPrivate = true) { | |
| 228 | + // #ifdef APP-NVUE | |
| 229 | + const el = this.$refs['zp-n-list-top-tag']; | |
| 230 | + if (this.usePageScroll) { | |
| 231 | + this._getNodeClientRect('zp-page-scroll-top', false).then(node => { | |
| 232 | + const nodeHeight = node ? node[0].height : 0; | |
| 233 | + weexDom.scrollToElement(el, { | |
| 234 | + offset: -nodeHeight, | |
| 235 | + animated: animate | |
| 236 | + }); | |
| 237 | + }); | |
| 238 | + } else { | |
| 239 | + if (!this.isIos && this.nvueListIs === 'scroller') { | |
| 240 | + this._getNodeClientRect('zp-n-refresh-container', false).then(node => { | |
| 241 | + const nodeHeight = node ? node[0].height : 0; | |
| 242 | + weexDom.scrollToElement(el, { | |
| 243 | + offset: -nodeHeight, | |
| 244 | + animated: animate | |
| 245 | + }); | |
| 246 | + }); | |
| 247 | + } else { | |
| 248 | + weexDom.scrollToElement(el, { | |
| 249 | + offset: 0, | |
| 250 | + animated: animate | |
| 251 | + }); | |
| 252 | + } | |
| 253 | + } | |
| 254 | + return; | |
| 255 | + // #endif | |
| 256 | + if (this.usePageScroll) { | |
| 257 | + this.$nextTick(() => { | |
| 258 | + uni.pageScrollTo({ | |
| 259 | + scrollTop: 0, | |
| 260 | + duration: animate ? 100 : 0, | |
| 261 | + }); | |
| 262 | + }); | |
| 263 | + return; | |
| 264 | + } | |
| 265 | + this.privateScrollWithAnimation = animate ? 1 : 0; | |
| 266 | + this.scrollTop = this.oldScrollTop; | |
| 267 | + this.$nextTick(() => { | |
| 268 | + this.scrollTop = 0; | |
| 269 | + this.oldScrollTop = this.scrollTop; | |
| 270 | + }); | |
| 271 | + }, | |
| 272 | + //滚动到底部 | |
| 273 | + async _scrollToBottom(animate = true) { | |
| 274 | + // #ifdef APP-NVUE | |
| 275 | + const el = this.$refs['zp-n-list-bottom-tag']; | |
| 276 | + if (el) { | |
| 277 | + weexDom.scrollToElement(el, { | |
| 278 | + offset: 0, | |
| 279 | + animated: animate | |
| 280 | + }); | |
| 281 | + } else { | |
| 282 | + u.consoleErr('滚动到底部失败,因为您设置了hideNvueBottomTag为true'); | |
| 283 | + } | |
| 284 | + return; | |
| 285 | + // #endif | |
| 286 | + if (this.usePageScroll) { | |
| 287 | + this.$nextTick(() => { | |
| 288 | + uni.pageScrollTo({ | |
| 289 | + scrollTop: Number.MAX_VALUE, | |
| 290 | + duration: animate ? 100 : 0, | |
| 291 | + }); | |
| 292 | + }); | |
| 293 | + return; | |
| 294 | + } | |
| 295 | + try { | |
| 296 | + this.privateScrollWithAnimation = animate ? 1 : 0; | |
| 297 | + const pagingContainerNode = await this._getNodeClientRect('.zp-paging-container'); | |
| 298 | + const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view'); | |
| 299 | + const pagingContainerH = pagingContainerNode ? pagingContainerNode[0].height : 0; | |
| 300 | + const scrollViewH = scrollViewNode ? scrollViewNode[0].height : 0; | |
| 301 | + if (pagingContainerH > scrollViewH) { | |
| 302 | + this.scrollTop = this.oldScrollTop; | |
| 303 | + this.$nextTick(() => { | |
| 304 | + this.scrollTop = pagingContainerH - scrollViewH + this.virtualPlaceholderTopHeight; | |
| 305 | + this.oldScrollTop = this.scrollTop; | |
| 306 | + }); | |
| 307 | + } | |
| 308 | + } catch (e) {} | |
| 309 | + }, | |
| 310 | + //滚动到指定view | |
| 311 | + _scrollIntoView(sel, offset = 0, animate = false, finishCallback) { | |
| 312 | + try { | |
| 313 | + this.scrollTop = this.oldScrollTop; | |
| 314 | + this.$nextTick(() => { | |
| 315 | + // #ifdef APP-NVUE | |
| 316 | + const refs = this.$parent.$refs; | |
| 317 | + if (!refs) return; | |
| 318 | + const dataType = Object.prototype.toString.call(sel); | |
| 319 | + let el = null; | |
| 320 | + if (dataType === '[object Number]') { | |
| 321 | + const els = refs[`z-paging-${sel}`]; | |
| 322 | + el = els ? els[0] : null; | |
| 323 | + } else if (dataType === '[object Array]') { | |
| 324 | + el = sel[0]; | |
| 325 | + } else { | |
| 326 | + el = sel; | |
| 327 | + } | |
| 328 | + if (el) { | |
| 329 | + weexDom.scrollToElement(el, { | |
| 330 | + offset: -offset, | |
| 331 | + animated: animate | |
| 332 | + }); | |
| 333 | + } else { | |
| 334 | + u.consoleErr('在nvue中滚动到指定位置,cell必须设置 :ref="`z-paging-${index}`"'); | |
| 335 | + } | |
| 336 | + return; | |
| 337 | + // #endif | |
| 338 | + this._getNodeClientRect('#' + sel.replace('#', ''), this.$parent).then((node) => { | |
| 339 | + if (node) { | |
| 340 | + let nodeTop = node[0].top; | |
| 341 | + this._scrollIntoViewByNodeTop(nodeTop, offset, animate); | |
| 342 | + finishCallback && finishCallback(); | |
| 343 | + } | |
| 344 | + }); | |
| 345 | + }); | |
| 346 | + } catch (e) {} | |
| 347 | + }, | |
| 348 | + //通过nodeTop滚动到指定view | |
| 349 | + _scrollIntoViewByNodeTop(nodeTop, offset = 0, animate = false) { | |
| 350 | + this._scrollToY(nodeTop, offset, animate, true); | |
| 351 | + }, | |
| 352 | + //滚动到指定位置 | |
| 353 | + _scrollToY(y, offset = 0, animate = false, addScrollTop = false) { | |
| 354 | + this.privateScrollWithAnimation = animate ? 1 : 0; | |
| 355 | + if (this.usePageScroll) { | |
| 356 | + uni.pageScrollTo({ | |
| 357 | + scrollTop: y - offset, | |
| 358 | + duration: animate ? 100 : 0 | |
| 359 | + }); | |
| 360 | + } else { | |
| 361 | + if(addScrollTop){ | |
| 362 | + y += this.oldScrollTop; | |
| 363 | + } | |
| 364 | + this.scrollTop = y - offset; | |
| 365 | + this.oldScrollTop = this.scrollTop; | |
| 366 | + } | |
| 367 | + }, | |
| 368 | + //scroll-view滚动中 | |
| 369 | + _scroll(e) { | |
| 370 | + this.$emit('scroll', e); | |
| 371 | + const scrollTop = e.detail.scrollTop; | |
| 372 | + // #ifndef APP-NVUE | |
| 373 | + this.finalUseVirtualList && this._updateVirtualScroll(scrollTop, this.oldScrollTop - scrollTop); | |
| 374 | + // #endif | |
| 375 | + this.oldScrollTop = scrollTop; | |
| 376 | + const scrollDiff = e.detail.scrollHeight - this.oldScrollTop; | |
| 377 | + !this.isIos && this._checkScrolledToBottom(scrollDiff); | |
| 378 | + }, | |
| 379 | + //检测scrollView是否要铺满屏幕 | |
| 380 | + _doCheckScrollViewShouldFullHeight(totalData) { | |
| 381 | + if (this.autoFullHeight && this.usePageScroll && this.isTotalChangeFromAddData) { | |
| 382 | + // #ifndef APP-NVUE | |
| 383 | + this.$nextTick(() => { | |
| 384 | + this._checkScrollViewShouldFullHeight((scrollViewNode, pagingContainerNode) => { | |
| 385 | + this._preCheckShowNoMoreInside(totalData, scrollViewNode, pagingContainerNode) | |
| 386 | + }); | |
| 387 | + }) | |
| 388 | + // #endif | |
| 389 | + // #ifdef APP-NVUE | |
| 390 | + this._preCheckShowNoMoreInside(totalData) | |
| 391 | + // #endif | |
| 392 | + } else { | |
| 393 | + this._preCheckShowNoMoreInside(totalData) | |
| 394 | + } | |
| 395 | + }, | |
| 396 | + //检测z-paging是否要全屏覆盖(当使用页面滚动并且不满全屏时,默认z-paging需要铺满全屏,避免数据过少时内部的empty-view无法正确展示) | |
| 397 | + async _checkScrollViewShouldFullHeight(callback) { | |
| 398 | + try { | |
| 399 | + const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view'); | |
| 400 | + const pagingContainerNode = await this._getNodeClientRect('.zp-paging-container-content'); | |
| 401 | + if (!scrollViewNode || !pagingContainerNode) return; | |
| 402 | + const scrollViewHeight = pagingContainerNode[0].height; | |
| 403 | + const scrollViewTop = scrollViewNode[0].top; | |
| 404 | + if (this.isAddedData && scrollViewHeight + scrollViewTop <= this.windowHeight) { | |
| 405 | + this._setAutoHeight(true, scrollViewNode); | |
| 406 | + callback(scrollViewNode, pagingContainerNode); | |
| 407 | + } else { | |
| 408 | + this._setAutoHeight(false); | |
| 409 | + callback(null, null); | |
| 410 | + } | |
| 411 | + } catch (e) { | |
| 412 | + callback(null, null); | |
| 413 | + } | |
| 414 | + }, | |
| 415 | + //scrollTop改变时触发 | |
| 416 | + _scrollTopChange(newVal, isPageScrollTop){ | |
| 417 | + this.$emit('scrollTopChange', newVal); | |
| 418 | + this.$emit('update:scrollTop', newVal); | |
| 419 | + this._checkShouldShowBackToTop(newVal); | |
| 420 | + const scrollTop = this.isIos ? (newVal > 5 ? 6 : 0) : (newVal > 105 ? 106 : (newVal > 5 ? 6 : 0)); | |
| 421 | + if (isPageScrollTop && this.wxsPageScrollTop !== scrollTop) { | |
| 422 | + this.wxsPageScrollTop = scrollTop; | |
| 423 | + } else if (!isPageScrollTop && this.wxsScrollTop !== scrollTop) { | |
| 424 | + this.wxsScrollTop = scrollTop; | |
| 425 | + if (scrollTop > 6) { | |
| 426 | + this.scrollEnable = true; | |
| 427 | + } | |
| 428 | + } | |
| 429 | + }, | |
| 430 | + //更新使用页面滚动时slot="top"或"bottom"插入view的高度 | |
| 431 | + _updatePageScrollTopOrBottomHeight(type) { | |
| 432 | + // #ifndef APP-NVUE | |
| 433 | + if (!this.usePageScroll) return; | |
| 434 | + // #endif | |
| 435 | + this._doCheckScrollViewShouldFullHeight(this.realTotalData); | |
| 436 | + const node = `.zp-page-${type}`; | |
| 437 | + const marginText = `margin${type.slice(0,1).toUpperCase() + type.slice(1)}`; | |
| 438 | + let safeAreaInsetBottomAdd = this.safeAreaInsetBottom; | |
| 439 | + this.$nextTick(() => { | |
| 440 | + let delayTime = 0; | |
| 441 | + // #ifdef MP-BAIDU || APP-NVUE | |
| 442 | + delayTime = 50; | |
| 443 | + // #endif | |
| 444 | + u.delay(() => { | |
| 445 | + this._getNodeClientRect(node).then((res) => { | |
| 446 | + if (res) { | |
| 447 | + let pageScrollNodeHeight = res[0].height; | |
| 448 | + if (type === 'bottom') { | |
| 449 | + if (safeAreaInsetBottomAdd) { | |
| 450 | + pageScrollNodeHeight += this.safeAreaBottom; | |
| 451 | + } | |
| 452 | + } else { | |
| 453 | + this.cacheTopHeight = pageScrollNodeHeight; | |
| 454 | + } | |
| 455 | + this.$set(this.scrollViewStyle, marginText, `${pageScrollNodeHeight}px`); | |
| 456 | + } else if (safeAreaInsetBottomAdd) { | |
| 457 | + this.$set(this.scrollViewStyle, marginText, `${this.safeAreaBottom}px`); | |
| 458 | + } | |
| 459 | + }); | |
| 460 | + }, delayTime) | |
| 461 | + }) | |
| 462 | + }, | |
| 463 | + } | |
| 464 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/modules/virtual-list.js
0 → 100644
| 1 | +// [z-paging]虚拟列表模块 | |
| 2 | +import u from '.././z-paging-utils' | |
| 3 | +import c from '.././z-paging-constant' | |
| 4 | +import Enum from '.././z-paging-enum' | |
| 5 | + | |
| 6 | +export default { | |
| 7 | + props: { | |
| 8 | + //是否使用虚拟列表,默认为否 | |
| 9 | + useVirtualList: { | |
| 10 | + type: Boolean, | |
| 11 | + default: u.gc('useVirtualList', false) | |
| 12 | + }, | |
| 13 | + //在使用虚拟列表时,是否使用兼容模式,默认为否 | |
| 14 | + useCompatibilityMode: { | |
| 15 | + type: Boolean, | |
| 16 | + default: u.gc('useCompatibilityMode', false) | |
| 17 | + }, | |
| 18 | + //使用兼容模式时传递的附加数据 | |
| 19 | + extraData: { | |
| 20 | + type: Object, | |
| 21 | + default: function() { | |
| 22 | + return u.gc('extraData', {}); | |
| 23 | + } | |
| 24 | + }, | |
| 25 | + //是否在z-paging内部循环渲染列表(内置列表),默认为否。若use-virtual-list为true,则此项恒为true | |
| 26 | + useInnerList: { | |
| 27 | + type: Boolean, | |
| 28 | + default: u.gc('useInnerList', false) | |
| 29 | + }, | |
| 30 | + //强制关闭inner-list,默认为false,如果为true将强制关闭innerList,适用于开启了虚拟列表后需要强制关闭inner-list的情况 | |
| 31 | + forceCloseInnerList: { | |
| 32 | + type: Boolean, | |
| 33 | + default: u.gc('forceCloseInnerList', false) | |
| 34 | + }, | |
| 35 | + //内置列表cell的key名称,仅nvue有效,在nvue中开启use-inner-list时必须填此项 | |
| 36 | + cellKeyName: { | |
| 37 | + type: String, | |
| 38 | + default: u.gc('cellKeyName', '') | |
| 39 | + }, | |
| 40 | + //innerList样式 | |
| 41 | + innerListStyle: { | |
| 42 | + type: Object, | |
| 43 | + default: function() { | |
| 44 | + return u.gc('innerListStyle', {}); | |
| 45 | + } | |
| 46 | + }, | |
| 47 | + //innerCell样式 | |
| 48 | + innerCellStyle: { | |
| 49 | + type: Object, | |
| 50 | + default: function() { | |
| 51 | + return u.gc('innerCellStyle', {}); | |
| 52 | + } | |
| 53 | + }, | |
| 54 | + //预加载的列表可视范围(列表高度)页数,默认为12,即预加载当前页及上下各12页的cell。此数值越大,则虚拟列表中加载的dom越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题 | |
| 55 | + preloadPage: { | |
| 56 | + type: [Number, String], | |
| 57 | + default: u.gc('preloadPage', 12), | |
| 58 | + validator: (value) => { | |
| 59 | + if (value <= 0) u.consoleErr('preload-page必须大于0!'); | |
| 60 | + return value > 0; | |
| 61 | + } | |
| 62 | + }, | |
| 63 | + //虚拟列表cell高度模式,默认为fixed,也就是每个cell高度完全相同,将以第一个cell高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】。 | |
| 64 | + cellHeightMode: { | |
| 65 | + type: String, | |
| 66 | + default: u.gc('cellHeightMode', Enum.CellHeightMode.Fixed) | |
| 67 | + }, | |
| 68 | + //虚拟列表列数,默认为1。常用于每行有多列的情况,例如每行有2列数据,需要将此值设置为2 | |
| 69 | + virtualListCol: { | |
| 70 | + type: [Number, String], | |
| 71 | + default: u.gc('virtualListCol', 1) | |
| 72 | + }, | |
| 73 | + //虚拟列表scroll取样帧率,默认为80,过低容易出现白屏问题,过高容易出现卡顿问题 | |
| 74 | + virtualScrollFps: { | |
| 75 | + type: [Number, String], | |
| 76 | + default: u.gc('virtualScrollFps', 80) | |
| 77 | + }, | |
| 78 | + }, | |
| 79 | + data() { | |
| 80 | + return { | |
| 81 | + virtualListKey: u.getInstanceId(), | |
| 82 | + virtualPageHeight: 0, | |
| 83 | + virtualCellHeight: 0, | |
| 84 | + virtualScrollTimeStamp: 0, | |
| 85 | + | |
| 86 | + virtualList: [], | |
| 87 | + virtualPlaceholderTopHeight: 0, | |
| 88 | + virtualPlaceholderBottomHeight: 0, | |
| 89 | + virtualTopRangeIndex: 0, | |
| 90 | + virtualBottomRangeIndex: 0, | |
| 91 | + lastVirtualTopRangeIndex: 0, | |
| 92 | + lastVirtualBottomRangeIndex: 0, | |
| 93 | + virtualItemInsertedCount: 0, | |
| 94 | + | |
| 95 | + virtualHeightCacheList: [], | |
| 96 | + | |
| 97 | + getCellHeightRetryCount: { | |
| 98 | + fixed: 0, | |
| 99 | + dynamic: 0 | |
| 100 | + }, | |
| 101 | + pagingOrgTop: -1, | |
| 102 | + updateVirtualListFromDataChange: false | |
| 103 | + } | |
| 104 | + }, | |
| 105 | + watch: { | |
| 106 | + realTotalData(newVal) { | |
| 107 | + // #ifndef APP-NVUE | |
| 108 | + if (this.finalUseVirtualList) { | |
| 109 | + this.updateVirtualListFromDataChange = true; | |
| 110 | + this.$nextTick(() => { | |
| 111 | + this.getCellHeightRetryCount.fixed = 0; | |
| 112 | + !newVal.length && this._resetDynamicListState(!this.isUserPullDown); | |
| 113 | + newVal.length && this.cellHeightMode === Enum.CellHeightMode.Fixed && this.isFirstPage && this._updateFixedCellHeight(); | |
| 114 | + this._updateVirtualScroll(this.oldScrollTop); | |
| 115 | + }) | |
| 116 | + } | |
| 117 | + // #endif | |
| 118 | + }, | |
| 119 | + virtualList(newVal){ | |
| 120 | + this.$emit('update:virtualList', newVal); | |
| 121 | + this.$emit('virtualListChange', newVal); | |
| 122 | + } | |
| 123 | + }, | |
| 124 | + computed: { | |
| 125 | + virtualCellIndexKey() { | |
| 126 | + return c.listCellIndexKey; | |
| 127 | + }, | |
| 128 | + finalUseVirtualList() { | |
| 129 | + if (this.useVirtualList && this.usePageScroll){ | |
| 130 | + u.consoleErr('使用页面滚动时,开启虚拟列表无效!'); | |
| 131 | + } | |
| 132 | + return this.useVirtualList && !this.usePageScroll; | |
| 133 | + }, | |
| 134 | + finalUseInnerList() { | |
| 135 | + return this.useInnerList || (this.finalUseVirtualList && !this.forceCloseInnerList); | |
| 136 | + }, | |
| 137 | + finalCellKeyName() { | |
| 138 | + // #ifdef APP-NVUE | |
| 139 | + if (this.finalUseVirtualList && !this.cellKeyName.length){ | |
| 140 | + u.consoleErr('在nvue中开启use-virtual-list必须设置cell-key-name,否则将可能导致列表渲染错误!'); | |
| 141 | + } | |
| 142 | + // #endif | |
| 143 | + return this.cellKeyName; | |
| 144 | + }, | |
| 145 | + finalVirtualPageHeight(){ | |
| 146 | + return this.virtualPageHeight > 0 ? this.virtualPageHeight : this.windowHeight; | |
| 147 | + }, | |
| 148 | + virtualRangePageHeight(){ | |
| 149 | + return this.finalVirtualPageHeight * this.preloadPage; | |
| 150 | + }, | |
| 151 | + virtualScrollDisTimeStamp() { | |
| 152 | + return 1000 / this.virtualScrollFps; | |
| 153 | + }, | |
| 154 | + }, | |
| 155 | + methods: { | |
| 156 | + //在使用动态高度虚拟列表时,若在列表数组中需要插入某个item,需要调用此方法;item:需要插入的item,index:插入的cell位置,若index为2,则插入的item在原list的index=1之后,index从0开始 | |
| 157 | + doInsertVirtualListItem(item, index) { | |
| 158 | + if (this.cellHeightMode !== Enum.CellHeightMode.Dynamic) return; | |
| 159 | + this.virtualItemInsertedCount ++; | |
| 160 | + if (!item || Object.prototype.toString.call(item) !== '[object Object]') { | |
| 161 | + item = { item }; | |
| 162 | + } | |
| 163 | + const cellIndexKey = this.virtualCellIndexKey; | |
| 164 | + item[cellIndexKey] = `custom-${this.virtualItemInsertedCount}`; | |
| 165 | + item[c.listCellIndexUniqueKey] = `${this.virtualListKey}-${item[cellIndexKey]}`; | |
| 166 | + this.totalData.splice(index, 0, item); | |
| 167 | + this.$nextTick(async () => { | |
| 168 | + let retryCount = 0; | |
| 169 | + while (retryCount <= 10) { | |
| 170 | + await u.wait(c.delayTime); | |
| 171 | + | |
| 172 | + const cellNode = await this._getNodeClientRect(`#zp-id-${item[cellIndexKey]}`, this.finalUseInnerList); | |
| 173 | + if (!cellNode) { | |
| 174 | + retryCount ++; | |
| 175 | + continue; | |
| 176 | + } | |
| 177 | + | |
| 178 | + const currentHeight = cellNode ? cellNode[0].height : 0; | |
| 179 | + const lastHeightCache = this.virtualHeightCacheList[index - 1]; | |
| 180 | + const lastTotalHeight = lastHeightCache ? lastHeightCache.totalHeight : 0; | |
| 181 | + this.virtualHeightCacheList.splice(index, 0, { | |
| 182 | + height: currentHeight, | |
| 183 | + lastTotalHeight, | |
| 184 | + totalHeight: lastTotalHeight + currentHeight | |
| 185 | + }); | |
| 186 | + | |
| 187 | + for (let i = index + 1; i < this.virtualHeightCacheList.length; i++) { | |
| 188 | + const thisNode = this.virtualHeightCacheList[i]; | |
| 189 | + thisNode.lastTotalHeight += currentHeight; | |
| 190 | + thisNode.totalHeight += currentHeight; | |
| 191 | + } | |
| 192 | + | |
| 193 | + this._updateVirtualScroll(this.oldScrollTop); | |
| 194 | + break; | |
| 195 | + } | |
| 196 | + }) | |
| 197 | + }, | |
| 198 | + //在使用动态高度虚拟列表时,手动更新指定cell的缓存高度(当cell高度在初始化之后再次改变时调用);index:需要更新的cell在列表中的位置,从0开始 | |
| 199 | + didUpdateVirtualListCell(index) { | |
| 200 | + if (this.cellHeightMode !== Enum.CellHeightMode.Dynamic) return; | |
| 201 | + const currentNode = this.virtualHeightCacheList[index]; | |
| 202 | + this.$nextTick(() => { | |
| 203 | + this._getNodeClientRect(`#zp-id-${index}`, this.finalUseInnerList).then(cellNode => { | |
| 204 | + const cellNodeHeight = cellNode ? cellNode[0].height : 0; | |
| 205 | + const heightDis = cellNodeHeight - currentNode.height; | |
| 206 | + currentNode.height = cellNodeHeight; | |
| 207 | + currentNode.totalHeight = currentNode.lastTotalHeight + cellNodeHeight; | |
| 208 | + | |
| 209 | + for (let i = index + 1; i < this.virtualHeightCacheList.length; i++) { | |
| 210 | + const thisNode = this.virtualHeightCacheList[i]; | |
| 211 | + thisNode.totalHeight += heightDis; | |
| 212 | + thisNode.lastTotalHeight += heightDis; | |
| 213 | + } | |
| 214 | + }); | |
| 215 | + }) | |
| 216 | + }, | |
| 217 | + //在使用动态高度虚拟列表时,若删除了列表数组中的某个item,需要调用此方法以更新高度缓存数组;index:删除的cell在列表中的位置,从0开始 | |
| 218 | + didDeleteVirtualListCell(index) { | |
| 219 | + if (this.cellHeightMode !== Enum.CellHeightMode.Dynamic) return; | |
| 220 | + const currentNode = this.virtualHeightCacheList[index]; | |
| 221 | + for (let i = index + 1; i < this.virtualHeightCacheList.length; i++) { | |
| 222 | + const thisNode = this.virtualHeightCacheList[i]; | |
| 223 | + thisNode.totalHeight -= currentNode.height; | |
| 224 | + thisNode.lastTotalHeight -= currentNode.height; | |
| 225 | + } | |
| 226 | + this.virtualHeightCacheList.splice(index, 1); | |
| 227 | + }, | |
| 228 | + //初始化虚拟列表 | |
| 229 | + _virtualListInit() { | |
| 230 | + this.$nextTick(() => { | |
| 231 | + u.delay(() => { | |
| 232 | + this._getNodeClientRect('.zp-scroll-view').then(node => { | |
| 233 | + if (node) { | |
| 234 | + this.pagingOrgTop = node[0].top; | |
| 235 | + this.virtualPageHeight = node[0].height; | |
| 236 | + } | |
| 237 | + }); | |
| 238 | + }); | |
| 239 | + }) | |
| 240 | + }, | |
| 241 | + //cellHeightMode为fixed时获取第一个cell高度 | |
| 242 | + _updateFixedCellHeight() { | |
| 243 | + this.$nextTick(() => { | |
| 244 | + u.delay(() => { | |
| 245 | + this._getNodeClientRect(`#zp-id-${0}`,this.finalUseInnerList).then(cellNode => { | |
| 246 | + if (!cellNode) { | |
| 247 | + if (this.getCellHeightRetryCount.fixed > 10) return; | |
| 248 | + this.getCellHeightRetryCount.fixed ++; | |
| 249 | + this._updateFixedCellHeight(); | |
| 250 | + } else { | |
| 251 | + this.virtualCellHeight = cellNode[0].height; | |
| 252 | + this._updateVirtualScroll(this.oldScrollTop); | |
| 253 | + } | |
| 254 | + }); | |
| 255 | + }, c.delayTime, 'updateFixedCellHeightDelay'); | |
| 256 | + }) | |
| 257 | + }, | |
| 258 | + //cellHeightMode为dynamic时获取每个cell高度 | |
| 259 | + _updateDynamicCellHeight(list, dataFrom = 'bottom') { | |
| 260 | + const dataFromTop = dataFrom === 'top'; | |
| 261 | + const heightCacheList = this.virtualHeightCacheList; | |
| 262 | + const currentCacheList = dataFromTop ? [] : heightCacheList; | |
| 263 | + let listTotalHeight = 0; | |
| 264 | + this.$nextTick(() => { | |
| 265 | + u.delay(async () => { | |
| 266 | + for (let i = 0; i < list.length; i++) { | |
| 267 | + const cellNode = await this._getNodeClientRect(`#zp-id-${list[i][this.virtualCellIndexKey]}`, this.finalUseInnerList); | |
| 268 | + const currentHeight = cellNode ? cellNode[0].height : 0; | |
| 269 | + if (!cellNode) { | |
| 270 | + if (this.getCellHeightRetryCount.dynamic <= 10) { | |
| 271 | + heightCacheList.splice(heightCacheList.length - i, i); | |
| 272 | + this.getCellHeightRetryCount.dynamic ++; | |
| 273 | + this._updateDynamicCellHeight(list, dataFrom); | |
| 274 | + } | |
| 275 | + return; | |
| 276 | + } | |
| 277 | + const lastHeightCache = currentCacheList.length ? currentCacheList.slice(-1)[0] : null; | |
| 278 | + const lastTotalHeight = lastHeightCache ? lastHeightCache.totalHeight : 0; | |
| 279 | + currentCacheList.push({ | |
| 280 | + height: currentHeight, | |
| 281 | + lastTotalHeight, | |
| 282 | + totalHeight: lastTotalHeight + currentHeight | |
| 283 | + }); | |
| 284 | + if (dataFromTop) { | |
| 285 | + listTotalHeight += currentHeight; | |
| 286 | + } | |
| 287 | + } | |
| 288 | + if (dataFromTop && list.length) { | |
| 289 | + for (let i = 0; i < heightCacheList.length; i++) { | |
| 290 | + const heightCacheItem = heightCacheList[i]; | |
| 291 | + heightCacheItem.lastTotalHeight += listTotalHeight; | |
| 292 | + heightCacheItem.totalHeight += listTotalHeight; | |
| 293 | + } | |
| 294 | + this.virtualHeightCacheList = currentCacheList.concat(heightCacheList); | |
| 295 | + } | |
| 296 | + this._updateVirtualScroll(this.oldScrollTop); | |
| 297 | + }, c.delayTime, 'updateDynamicCellHeightDelay') | |
| 298 | + }) | |
| 299 | + }, | |
| 300 | + //设置cellItem的index | |
| 301 | + _setCellIndex(list, dataFrom = 'bottom') { | |
| 302 | + let currentItemIndex = 0; | |
| 303 | + const cellIndexKey = this.virtualCellIndexKey; | |
| 304 | + if (this.totalData.length) { | |
| 305 | + if (dataFrom === 'bottom') { | |
| 306 | + currentItemIndex = this.realTotalData.length; | |
| 307 | + const lastItem = this.realTotalData.length ? this.realTotalData.slice(-1)[0] : null; | |
| 308 | + if (lastItem && lastItem[cellIndexKey] !== undefined) { | |
| 309 | + currentItemIndex = lastItem[cellIndexKey] + 1; | |
| 310 | + } | |
| 311 | + } else if (dataFrom === 'top') { | |
| 312 | + const firstItem = this.realTotalData.length ? this.realTotalData[0] : null; | |
| 313 | + if (firstItem && firstItem[cellIndexKey] !== undefined) { | |
| 314 | + currentItemIndex = firstItem[cellIndexKey] - list.length; | |
| 315 | + } | |
| 316 | + } | |
| 317 | + } else { | |
| 318 | + this._resetDynamicListState(); | |
| 319 | + } | |
| 320 | + for (let i = 0; i < list.length; i++) { | |
| 321 | + let item = list[i]; | |
| 322 | + if (!item || Object.prototype.toString.call(item) !== '[object Object]') { | |
| 323 | + item = { item }; | |
| 324 | + } | |
| 325 | + item[cellIndexKey] = currentItemIndex + i; | |
| 326 | + item[c.listCellIndexUniqueKey] = `${this.virtualListKey}-${item[cellIndexKey]}`; | |
| 327 | + list[i] = item; | |
| 328 | + } | |
| 329 | + this.getCellHeightRetryCount.dynamic = 0; | |
| 330 | + this.cellHeightMode === Enum.CellHeightMode.Dynamic && this._updateDynamicCellHeight(list, dataFrom); | |
| 331 | + }, | |
| 332 | + //更新scroll滚动 | |
| 333 | + _updateVirtualScroll(scrollTop, scrollDiff = 0) { | |
| 334 | + const currentTimeStamp = u.getTime(); | |
| 335 | + scrollTop === 0 && this._resetTopRange(); | |
| 336 | + if (scrollTop !== 0 && this.virtualScrollTimeStamp && currentTimeStamp - this.virtualScrollTimeStamp <= this.virtualScrollDisTimeStamp) { | |
| 337 | + return; | |
| 338 | + } | |
| 339 | + this.virtualScrollTimeStamp = currentTimeStamp; | |
| 340 | + | |
| 341 | + let scrollIndex = 0; | |
| 342 | + const cellHeightMode = this.cellHeightMode; | |
| 343 | + if (cellHeightMode === Enum.CellHeightMode.Fixed) { | |
| 344 | + scrollIndex = parseInt(scrollTop / this.virtualCellHeight) || 0; | |
| 345 | + this._updateFixedTopRangeIndex(scrollIndex); | |
| 346 | + this._updateFixedBottomRangeIndex(scrollIndex); | |
| 347 | + } else if(cellHeightMode === Enum.CellHeightMode.Dynamic) { | |
| 348 | + const scrollDirection = scrollDiff > 0 ? 'top' : 'bottom'; | |
| 349 | + const rangePageHeight = this.virtualRangePageHeight; | |
| 350 | + const topRangePageOffset = scrollTop - rangePageHeight; | |
| 351 | + const bottomRangePageOffset = scrollTop + this.finalVirtualPageHeight + rangePageHeight; | |
| 352 | + | |
| 353 | + let virtualBottomRangeIndex = 0; | |
| 354 | + let virtualPlaceholderBottomHeight = 0; | |
| 355 | + let reachedLimitBottom = false; | |
| 356 | + const heightCacheList = this.virtualHeightCacheList; | |
| 357 | + const lastHeightCache = !!heightCacheList ? heightCacheList.slice(-1)[0] : null; | |
| 358 | + | |
| 359 | + let startTopRangeIndex = this.virtualTopRangeIndex; | |
| 360 | + if (scrollDirection === 'bottom') { | |
| 361 | + for (let i = startTopRangeIndex; i < heightCacheList.length; i++){ | |
| 362 | + const heightCacheItem = heightCacheList[i]; | |
| 363 | + if (heightCacheItem && heightCacheItem.totalHeight > topRangePageOffset) { | |
| 364 | + this.virtualTopRangeIndex = i; | |
| 365 | + this.virtualPlaceholderTopHeight = heightCacheItem.lastTotalHeight; | |
| 366 | + break; | |
| 367 | + } | |
| 368 | + } | |
| 369 | + } else { | |
| 370 | + let topRangeMatched = false; | |
| 371 | + for (let i = startTopRangeIndex; i >= 0; i--){ | |
| 372 | + const heightCacheItem = heightCacheList[i]; | |
| 373 | + if (heightCacheItem && heightCacheItem.totalHeight < topRangePageOffset) { | |
| 374 | + this.virtualTopRangeIndex = i; | |
| 375 | + this.virtualPlaceholderTopHeight = heightCacheItem.lastTotalHeight; | |
| 376 | + topRangeMatched = true; | |
| 377 | + break; | |
| 378 | + } | |
| 379 | + } | |
| 380 | + !topRangeMatched && this._resetTopRange(); | |
| 381 | + } | |
| 382 | + for (let i = this.virtualTopRangeIndex; i < heightCacheList.length; i++){ | |
| 383 | + const heightCacheItem = heightCacheList[i]; | |
| 384 | + if (heightCacheItem && heightCacheItem.totalHeight > bottomRangePageOffset) { | |
| 385 | + virtualBottomRangeIndex = i; | |
| 386 | + virtualPlaceholderBottomHeight = lastHeightCache.totalHeight - heightCacheItem.totalHeight; | |
| 387 | + reachedLimitBottom = true; | |
| 388 | + break; | |
| 389 | + } | |
| 390 | + } | |
| 391 | + if (!reachedLimitBottom || this.virtualBottomRangeIndex === 0) { | |
| 392 | + this.virtualBottomRangeIndex = this.realTotalData.length ? this.realTotalData.length - 1 : this.pageSize; | |
| 393 | + this.virtualPlaceholderBottomHeight = 0; | |
| 394 | + } else { | |
| 395 | + this.virtualBottomRangeIndex = virtualBottomRangeIndex; | |
| 396 | + this.virtualPlaceholderBottomHeight = virtualPlaceholderBottomHeight; | |
| 397 | + } | |
| 398 | + this._updateVirtualList(); | |
| 399 | + } | |
| 400 | + }, | |
| 401 | + //更新fixedCell模式下topRangeIndex&placeholderTopHeight | |
| 402 | + _updateFixedTopRangeIndex(scrollIndex) { | |
| 403 | + let virtualTopRangeIndex = this.virtualCellHeight === 0 ? 0 : scrollIndex - (parseInt(this.finalVirtualPageHeight / this.virtualCellHeight) || 1) * this.preloadPage; | |
| 404 | + virtualTopRangeIndex *= this.virtualListCol; | |
| 405 | + virtualTopRangeIndex = Math.max(0, virtualTopRangeIndex); | |
| 406 | + this.virtualTopRangeIndex = virtualTopRangeIndex; | |
| 407 | + this.virtualPlaceholderTopHeight = (virtualTopRangeIndex / this.virtualListCol) * this.virtualCellHeight; | |
| 408 | + }, | |
| 409 | + //更新fixedCell模式下bottomRangeIndex&placeholderBottomHeight | |
| 410 | + _updateFixedBottomRangeIndex(scrollIndex) { | |
| 411 | + let virtualBottomRangeIndex = this.virtualCellHeight === 0 ? this.pageSize : scrollIndex + (parseInt(this.finalVirtualPageHeight / this.virtualCellHeight) || 1) * (this.preloadPage + 1); | |
| 412 | + virtualBottomRangeIndex *= this.virtualListCol; | |
| 413 | + virtualBottomRangeIndex = Math.min(this.realTotalData.length, virtualBottomRangeIndex); | |
| 414 | + this.virtualBottomRangeIndex = virtualBottomRangeIndex; | |
| 415 | + this.virtualPlaceholderBottomHeight = (this.realTotalData.length - virtualBottomRangeIndex) * this.virtualCellHeight / this.virtualListCol; | |
| 416 | + this._updateVirtualList(); | |
| 417 | + }, | |
| 418 | + //更新virtualList | |
| 419 | + _updateVirtualList() { | |
| 420 | + const shouldUpdateList = this.updateVirtualListFromDataChange || (this.lastVirtualTopRangeIndex !== this.virtualTopRangeIndex || this.lastVirtualBottomRangeIndex !== this.virtualBottomRangeIndex); | |
| 421 | + if (shouldUpdateList) { | |
| 422 | + this.updateVirtualListFromDataChange = false; | |
| 423 | + this.lastVirtualTopRangeIndex = this.virtualTopRangeIndex; | |
| 424 | + this.lastVirtualBottomRangeIndex = this.virtualBottomRangeIndex; | |
| 425 | + this.virtualList = this.realTotalData.slice(this.virtualTopRangeIndex, this.virtualBottomRangeIndex + 1); | |
| 426 | + } | |
| 427 | + }, | |
| 428 | + //重置动态cell模式下的高度缓存数据、虚拟列表和滚动状态 | |
| 429 | + _resetDynamicListState(resetVirtualList = false) { | |
| 430 | + this.virtualHeightCacheList = []; | |
| 431 | + if (resetVirtualList) { | |
| 432 | + this.virtualList = []; | |
| 433 | + } | |
| 434 | + this.virtualTopRangeIndex = 0; | |
| 435 | + this.virtualPlaceholderTopHeight = 0; | |
| 436 | + }, | |
| 437 | + //重置topRangeIndex和placeholderTopHeight | |
| 438 | + _resetTopRange() { | |
| 439 | + this.virtualTopRangeIndex = 0; | |
| 440 | + this.virtualPlaceholderTopHeight = 0; | |
| 441 | + this._updateVirtualList(); | |
| 442 | + }, | |
| 443 | + //检测虚拟列表当前滚动位置,如发现滚动位置不正确则重新计算虚拟列表相关参数(为解决在App中可能出现的长时间进入后台后打开App白屏的问题) | |
| 444 | + _checkVirtualListScroll() { | |
| 445 | + if (this.finalUseVirtualList) { | |
| 446 | + this.$nextTick(() => { | |
| 447 | + this._getNodeClientRect('.zp-paging-touch-view').then(node => { | |
| 448 | + const currentTop = node ? node[0].top : 0; | |
| 449 | + if (!node || (currentTop === this.pagingOrgTop && this.virtualPlaceholderTopHeight !== 0)) { | |
| 450 | + this._updateVirtualScroll(0); | |
| 451 | + } | |
| 452 | + }); | |
| 453 | + }) | |
| 454 | + } | |
| 455 | + }, | |
| 456 | + //处理使用内置列表时点击了cell事件 | |
| 457 | + _innerCellClick(item, index) { | |
| 458 | + this.$emit('innerCellClick', item, index); | |
| 459 | + } | |
| 460 | + } | |
| 461 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/z-paging-config.js
0 → 100644
| 1 | +// [z-paging]处理main.js中的配置信息工具 | |
| 2 | + | |
| 3 | +let config = null; | |
| 4 | +let getedStorage = false; | |
| 5 | +const storageKey = 'Z-PAGING-CONFIG-STORAGE-KEY' | |
| 6 | + | |
| 7 | +function setConfig(value) { | |
| 8 | + uni.setStorageSync(storageKey, value); | |
| 9 | +} | |
| 10 | + | |
| 11 | +function getConfig() { | |
| 12 | + if (getedStorage) return config; | |
| 13 | + config = uni.getStorageSync(storageKey); | |
| 14 | + getedStorage = true; | |
| 15 | + return config; | |
| 16 | +} | |
| 17 | + | |
| 18 | +export default { | |
| 19 | + setConfig, | |
| 20 | + getConfig | |
| 21 | +}; | ... | ... |
garbage-removal/src/components/z-paging/js/z-paging-constant.js
0 → 100644
| 1 | +// [z-paging]常量 | |
| 2 | + | |
| 3 | +export default { | |
| 4 | + version: '2.6.2', | |
| 5 | + delayTime: 100, | |
| 6 | + errorUpdateKey: 'z-paging-error-emit', | |
| 7 | + completeUpdateKey: 'z-paging-complete-emit', | |
| 8 | + cachePrefixKey: 'z-paging-cache', | |
| 9 | + | |
| 10 | + listCellIndexKey: 'zp_index', | |
| 11 | + listCellIndexUniqueKey: 'zp_unique_index' | |
| 12 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/z-paging-enum.js
0 → 100644
| 1 | +// [z-paging]枚举 | |
| 2 | + | |
| 3 | +export default { | |
| 4 | + //当前加载类型 0.下拉刷新 1.上拉加载更多 | |
| 5 | + LoadingType: { | |
| 6 | + Refresher: 0, | |
| 7 | + LoadingMore: 1 | |
| 8 | + }, | |
| 9 | + //下拉刷新状态 0.默认状态 1.松手立即刷新 2.刷新中 3.刷新结束 | |
| 10 | + Refresher: { | |
| 11 | + Default: 0, | |
| 12 | + ReleaseToRefresh: 1, | |
| 13 | + Loading: 2, | |
| 14 | + Complete: 3 | |
| 15 | + }, | |
| 16 | + //底部加载更多状态 0.默认状态 1.加载中 2.没有更多数据 3.加载失败 | |
| 17 | + More: { | |
| 18 | + Default: 0, | |
| 19 | + Loading: 1, | |
| 20 | + NoMore: 2, | |
| 21 | + Fail: 3 | |
| 22 | + }, | |
| 23 | + //@query触发来源 0.用户主动下拉刷新 1.通过reload触发 2.通过refresh触发 3.通过滚动到底部加载更多或点击底部加载更多触发 | |
| 24 | + QueryFrom: { | |
| 25 | + UserPullDown: 0, | |
| 26 | + Reload: 1, | |
| 27 | + Refresh: 2, | |
| 28 | + LoadingMore: 3 | |
| 29 | + }, | |
| 30 | + //虚拟列表cell高度模式 | |
| 31 | + CellHeightMode: { | |
| 32 | + //固定高度 | |
| 33 | + Fixed: 'fixed', | |
| 34 | + //动态高度 | |
| 35 | + Dynamic: 'dynamic' | |
| 36 | + }, | |
| 37 | + //列表缓存模式 | |
| 38 | + CacheMode: { | |
| 39 | + //默认模式,只会缓存一次 | |
| 40 | + Default: 'default', | |
| 41 | + //总是缓存,每次列表刷新(下拉刷新、调用reload等)都会更新缓存 | |
| 42 | + Always: 'always' | |
| 43 | + } | |
| 44 | +} | |
| 0 | 45 | \ No newline at end of file | ... | ... |
garbage-removal/src/components/z-paging/js/z-paging-interceptor.js
0 → 100644
| 1 | +// [z-paging]拦截器 | |
| 2 | + | |
| 3 | +//拦截&处理@query事件 | |
| 4 | +function handleQuery(callback) { | |
| 5 | + try { | |
| 6 | + setTimeout(function() { | |
| 7 | + _getApp().globalData.zp_handleQueryCallback = callback; | |
| 8 | + }, 1); | |
| 9 | + } catch (e) {} | |
| 10 | +} | |
| 11 | + | |
| 12 | +//拦截&处理@query事件(私有,请勿调用) | |
| 13 | +function _handleQuery(pageNo, pageSize, from, lastItem){ | |
| 14 | + const callback = _getApp().globalData.zp_handleQueryCallback; | |
| 15 | + return callback ? callback(pageNo, pageSize, from, lastItem) : [pageNo, pageSize, from]; | |
| 16 | +} | |
| 17 | + | |
| 18 | +//拦截&处理系统language转i18n local | |
| 19 | +function handleLanguage2Local(callback) { | |
| 20 | + try { | |
| 21 | + setTimeout(function() { | |
| 22 | + _getApp().globalData.zp_handleLanguage2LocalCallback = callback; | |
| 23 | + }, 1); | |
| 24 | + } catch (e) {} | |
| 25 | +} | |
| 26 | + | |
| 27 | +//拦截&处理系统language转i18n local(私有,请勿调用) | |
| 28 | +function _handleLanguage2Local(language, local){ | |
| 29 | + const callback = _getApp().globalData.zp_handleLanguage2LocalCallback; | |
| 30 | + return callback ? callback(language, local) : local; | |
| 31 | +} | |
| 32 | + | |
| 33 | +//获取当前app对象 | |
| 34 | +function _getApp(){ | |
| 35 | + // #ifndef APP-NVUE | |
| 36 | + return getApp(); | |
| 37 | + // #endif | |
| 38 | + // #ifdef APP-NVUE | |
| 39 | + return getApp({ allowDefault: true }); | |
| 40 | + // #endif | |
| 41 | +} | |
| 42 | + | |
| 43 | +export default { | |
| 44 | + handleQuery, | |
| 45 | + _handleQuery, | |
| 46 | + handleLanguage2Local, | |
| 47 | + _handleLanguage2Local | |
| 48 | +}; | ... | ... |
garbage-removal/src/components/z-paging/js/z-paging-main.js
0 → 100644
| 1 | +// [z-paging]核心js | |
| 2 | + | |
| 3 | +import zStatic from './z-paging-static' | |
| 4 | +import c from './z-paging-constant' | |
| 5 | +import u from './z-paging-utils' | |
| 6 | + | |
| 7 | +import zPagingRefresh from '../components/z-paging-refresh' | |
| 8 | +import zPagingLoadMore from '../components/z-paging-load-more' | |
| 9 | +import zPagingEmptyView from '../../z-paging-empty-view/z-paging-empty-view' | |
| 10 | + | |
| 11 | +// modules | |
| 12 | +import commonLayoutModule from './modules/common-layout' | |
| 13 | +import dataHandleModule from './modules/data-handle' | |
| 14 | +import i18nModule from './modules/i18n' | |
| 15 | +import nvueModule from './modules/nvue' | |
| 16 | +import emptyModule from './modules/empty' | |
| 17 | +import refresherModule from './modules/refresher' | |
| 18 | +import loadMoreModule from './modules/load-more' | |
| 19 | +import loadingModule from './modules/loading' | |
| 20 | +import scrollerModule from './modules/scroller' | |
| 21 | +import backToTopModule from './modules/back-to-top' | |
| 22 | +import virtualListModule from './modules/virtual-list' | |
| 23 | + | |
| 24 | +import Enum from './z-paging-enum' | |
| 25 | + | |
| 26 | +const systemInfo = uni.getSystemInfoSync(); | |
| 27 | + | |
| 28 | +export default { | |
| 29 | + name: "z-paging", | |
| 30 | + components: { | |
| 31 | + zPagingRefresh, | |
| 32 | + zPagingLoadMore, | |
| 33 | + zPagingEmptyView | |
| 34 | + }, | |
| 35 | + mixins: [ | |
| 36 | + commonLayoutModule, | |
| 37 | + dataHandleModule, | |
| 38 | + i18nModule, | |
| 39 | + nvueModule, | |
| 40 | + emptyModule, | |
| 41 | + refresherModule, | |
| 42 | + loadMoreModule, | |
| 43 | + loadingModule, | |
| 44 | + scrollerModule, | |
| 45 | + backToTopModule, | |
| 46 | + virtualListModule | |
| 47 | + ], | |
| 48 | + data() { | |
| 49 | + return { | |
| 50 | + //--------------静态资源--------------- | |
| 51 | + base64Arrow: zStatic.base64Arrow, | |
| 52 | + base64Flower: zStatic.base64Flower, | |
| 53 | + base64BackToTop: zStatic.base64BackToTop, | |
| 54 | + | |
| 55 | + //-------------全局数据相关-------------- | |
| 56 | + //当前加载类型 | |
| 57 | + loadingType: Enum.LoadingType.Refresher, | |
| 58 | + requestTimeStamp: 0, | |
| 59 | + chatRecordLoadingMoreText: '', | |
| 60 | + wxsPropType: '', | |
| 61 | + renderPropScrollTop: -1, | |
| 62 | + checkScrolledToBottomTimeOut: null, | |
| 63 | + cacheTopHeight: -1, | |
| 64 | + statusBarHeight: systemInfo.statusBarHeight, | |
| 65 | + | |
| 66 | + //--------------状态&判断--------------- | |
| 67 | + insideOfPaging: -1, | |
| 68 | + isLoadFailed: false, | |
| 69 | + isIos: systemInfo.platform === 'ios', | |
| 70 | + disabledBounce: false, | |
| 71 | + fromCompleteEmit: false, | |
| 72 | + disabledCompleteEmit: false, | |
| 73 | + pageLaunched: false, | |
| 74 | + | |
| 75 | + //---------------wxs相关--------------- | |
| 76 | + wxsIsScrollTopInTopRange: true, | |
| 77 | + wxsScrollTop: 0, | |
| 78 | + wxsPageScrollTop: 0, | |
| 79 | + wxsOnPullingDown: false, | |
| 80 | + }; | |
| 81 | + }, | |
| 82 | + props: { | |
| 83 | + //调用complete后延迟处理的时间,单位为毫秒,默认0毫秒,优先级高于minDelay | |
| 84 | + delay: { | |
| 85 | + type: [Number, String], | |
| 86 | + default: u.gc('delay', 0), | |
| 87 | + }, | |
| 88 | + //触发@query后最小延迟处理的时间,单位为毫秒,默认0毫秒,优先级低于delay(假设设置为300毫秒,若分页请求时间小于300毫秒,则在调用complete后延迟[300毫秒-请求时长];若请求时长大于300毫秒,则不延迟),当show-refresher-when-reload为true或reload(true)时,其最小值为400 | |
| 89 | + minDelay: { | |
| 90 | + type: [Number, String], | |
| 91 | + default: u.gc('minDelay', 0), | |
| 92 | + }, | |
| 93 | + //设置z-paging的style,部分平台(如微信小程序)无法直接修改组件的style,可使用此属性代替 | |
| 94 | + pagingStyle: { | |
| 95 | + type: Object, | |
| 96 | + default: function() { | |
| 97 | + return u.gc('pagingStyle', {}); | |
| 98 | + }, | |
| 99 | + }, | |
| 100 | + //z-paging的高度,优先级低于pagingStyle中设置的height;传字符串,如100px、100rpx、100% | |
| 101 | + height: { | |
| 102 | + type: String, | |
| 103 | + default: u.gc('height', '') | |
| 104 | + }, | |
| 105 | + //z-paging的宽度,优先级低于pagingStyle中设置的width;传字符串,如100px、100rpx、100% | |
| 106 | + width: { | |
| 107 | + type: String, | |
| 108 | + default: u.gc('width', '') | |
| 109 | + }, | |
| 110 | + //z-paging的背景色,优先级低于pagingStyle中设置的background。传字符串,如"#ffffff" | |
| 111 | + bgColor: { | |
| 112 | + type: String, | |
| 113 | + default: u.gc('bgColor', '') | |
| 114 | + }, | |
| 115 | + //设置z-paging的容器(插槽的父view)的style | |
| 116 | + pagingContentStyle: { | |
| 117 | + type: Object, | |
| 118 | + default: function() { | |
| 119 | + return u.gc('pagingContentStyle', {}); | |
| 120 | + }, | |
| 121 | + }, | |
| 122 | + //z-paging是否自动高度,若自动高度则会自动铺满屏幕 | |
| 123 | + autoHeight: { | |
| 124 | + type: Boolean, | |
| 125 | + default: u.gc('autoHeight', false) | |
| 126 | + }, | |
| 127 | + //z-paging是否自动高度时,附加的高度,注意添加单位px或rpx,若需要减少高度,则传负数 | |
| 128 | + autoHeightAddition: { | |
| 129 | + type: [Number, String], | |
| 130 | + default: u.gc('autoHeightAddition', '0px') | |
| 131 | + }, | |
| 132 | + //loading(下拉刷新、上拉加载更多)的主题样式,支持black,white,默认black | |
| 133 | + defaultThemeStyle: { | |
| 134 | + type: String, | |
| 135 | + default: u.gc('defaultThemeStyle', 'black') | |
| 136 | + }, | |
| 137 | + //z-paging是否使用fixed布局,若使用fixed布局,则z-paging的父view无需固定高度,z-paging高度默认为100%,默认为是(当使用内置scroll-view滚动时有效) | |
| 138 | + fixed: { | |
| 139 | + type: Boolean, | |
| 140 | + default: u.gc('fixed', true) | |
| 141 | + }, | |
| 142 | + //是否开启底部安全区域适配 | |
| 143 | + safeAreaInsetBottom: { | |
| 144 | + type: Boolean, | |
| 145 | + default: u.gc('safeAreaInsetBottom', false) | |
| 146 | + }, | |
| 147 | + //开启底部安全区域适配后,是否使用placeholder形式实现,默认为否。为否时滚动区域会自动避开底部安全区域,也就是所有滚动内容都不会挡住底部安全区域,若设置为是,则滚动时滚动内容会挡住底部安全区域,但是当滚动到底部时才会避开底部安全区域 | |
| 148 | + useSafeAreaPlaceholder: { | |
| 149 | + type: Boolean, | |
| 150 | + default: u.gc('useSafeAreaPlaceholder', false) | |
| 151 | + }, | |
| 152 | + //slot="top"的view的z-index,默认为99,仅使用页面滚动时有效 | |
| 153 | + topZIndex: { | |
| 154 | + type: Number, | |
| 155 | + default: u.gc('topZIndex', 99) | |
| 156 | + }, | |
| 157 | + //z-paging内容容器父view的z-index,默认为1 | |
| 158 | + superContentZIndex: { | |
| 159 | + type: Number, | |
| 160 | + default: u.gc('superContentZIndex', 1) | |
| 161 | + }, | |
| 162 | + //z-paging内容容器部分的z-index,默认为10 | |
| 163 | + contentZIndex: { | |
| 164 | + type: Number, | |
| 165 | + default: u.gc('contentZIndex', 10) | |
| 166 | + }, | |
| 167 | + //使用页面滚动时,是否在不满屏时自动填充满屏幕,默认为是 | |
| 168 | + autoFullHeight: { | |
| 169 | + type: Boolean, | |
| 170 | + default: u.gc('autoFullHeight', true) | |
| 171 | + }, | |
| 172 | + //是否监听列表触摸方向改变,默认为否 | |
| 173 | + watchTouchDirectionChange: { | |
| 174 | + type: Boolean, | |
| 175 | + default: u.gc('watchTouchDirectionChange', false) | |
| 176 | + }, | |
| 177 | + }, | |
| 178 | + created(){ | |
| 179 | + if (this.createdReload && !this.refresherOnly && this.auto) { | |
| 180 | + this._startLoading(); | |
| 181 | + this.$nextTick(this._preReload); | |
| 182 | + } | |
| 183 | + }, | |
| 184 | + mounted() { | |
| 185 | + this.wxsPropType = u.getTime().toString(); | |
| 186 | + this.renderJsIgnore; | |
| 187 | + if (!this.createdReload && !this.refresherOnly && this.auto) { | |
| 188 | + this.$nextTick(this._preReload); | |
| 189 | + } | |
| 190 | + this.finalUseCache && this._setListByLocalCache(); | |
| 191 | + let delay = 0; | |
| 192 | + // #ifdef H5 || MP | |
| 193 | + delay = c.delayTime; | |
| 194 | + // #endif | |
| 195 | + this.$nextTick(() => { | |
| 196 | + this.systemInfo = uni.getSystemInfoSync(); | |
| 197 | + !this.usePageScroll && this.autoHeight && this._setAutoHeight(); | |
| 198 | + this.loaded = true; | |
| 199 | + }) | |
| 200 | + this.updatePageScrollTopHeight(); | |
| 201 | + this.updatePageScrollBottomHeight(); | |
| 202 | + this.updateLeftAndRightWidth(); | |
| 203 | + if (this.finalRefresherEnabled && this.useCustomRefresher) { | |
| 204 | + this.$nextTick(() => { | |
| 205 | + this.isTouchmoving = true; | |
| 206 | + }) | |
| 207 | + } | |
| 208 | + this._onEmit(); | |
| 209 | + // #ifdef APP-NVUE | |
| 210 | + if (!this.isIos && !this.useChatRecordMode) { | |
| 211 | + this.nLoadingMoreFixedHeight = true; | |
| 212 | + } | |
| 213 | + this._nUpdateRefresherWidth(); | |
| 214 | + // #endif | |
| 215 | + // #ifndef APP-NVUE | |
| 216 | + this.finalUseVirtualList && this._virtualListInit(); | |
| 217 | + // #endif | |
| 218 | + // #ifndef APP-PLUS | |
| 219 | + this.$nextTick(() => { | |
| 220 | + setTimeout(() => { | |
| 221 | + this._getCssSafeAreaInsetBottom(() => this.safeAreaInsetBottom && this.updatePageScrollBottomHeight()); | |
| 222 | + }, delay) | |
| 223 | + }) | |
| 224 | + // #endif | |
| 225 | + }, | |
| 226 | + destroyed() { | |
| 227 | + this._offEmit(); | |
| 228 | + }, | |
| 229 | + // #ifdef VUE3 | |
| 230 | + unmounted() { | |
| 231 | + this._offEmit(); | |
| 232 | + }, | |
| 233 | + // #endif | |
| 234 | + watch: { | |
| 235 | + defaultThemeStyle: { | |
| 236 | + handler(newVal) { | |
| 237 | + if (newVal.length) { | |
| 238 | + this.finalRefresherDefaultStyle = newVal; | |
| 239 | + } | |
| 240 | + }, | |
| 241 | + immediate: true | |
| 242 | + }, | |
| 243 | + autoHeight(newVal) { | |
| 244 | + this.loaded && !this.usePageScroll && this._setAutoHeight(newVal); | |
| 245 | + }, | |
| 246 | + autoHeightAddition(newVal) { | |
| 247 | + this.loaded && !this.usePageScroll && this.autoHeight && this._setAutoHeight(newVal); | |
| 248 | + }, | |
| 249 | + }, | |
| 250 | + computed: { | |
| 251 | + finalPagingStyle() { | |
| 252 | + const pagingStyle = this.pagingStyle; | |
| 253 | + if (!this.systemInfo) return pagingStyle; | |
| 254 | + const { windowTop, windowBottom } = this; | |
| 255 | + if (!this.usePageScroll && this.fixed) { | |
| 256 | + if (windowTop && !pagingStyle.top) { | |
| 257 | + pagingStyle.top = windowTop + 'px'; | |
| 258 | + } | |
| 259 | + if (windowBottom && !pagingStyle.bottom) { | |
| 260 | + pagingStyle.bottom = windowBottom + 'px'; | |
| 261 | + } | |
| 262 | + } | |
| 263 | + if (this.bgColor.length && !pagingStyle['background']) { | |
| 264 | + pagingStyle['background'] = this.bgColor; | |
| 265 | + } | |
| 266 | + if (this.height.length && !pagingStyle['height']) { | |
| 267 | + pagingStyle['height'] = this.height; | |
| 268 | + } | |
| 269 | + if (this.width.length && !pagingStyle['width']) { | |
| 270 | + pagingStyle['width'] = this.width; | |
| 271 | + } | |
| 272 | + return pagingStyle; | |
| 273 | + }, | |
| 274 | + finalLowerThreshold() { | |
| 275 | + return u.convertToPx(this.lowerThreshold); | |
| 276 | + }, | |
| 277 | + finalPagingContentStyle() { | |
| 278 | + if (this.contentZIndex != 1) { | |
| 279 | + this.pagingContentStyle['z-index'] = this.contentZIndex; | |
| 280 | + this.pagingContentStyle['position'] = 'relative'; | |
| 281 | + } | |
| 282 | + return this.pagingContentStyle; | |
| 283 | + }, | |
| 284 | + renderJsIgnore() { | |
| 285 | + if ((this.usePageScroll && this.useChatRecordMode) || !this.refresherEnabled || !this.useCustomRefresher) { | |
| 286 | + this.$nextTick(() => { | |
| 287 | + this.renderPropScrollTop = 10; | |
| 288 | + }) | |
| 289 | + } | |
| 290 | + return 0; | |
| 291 | + }, | |
| 292 | + windowHeight() { | |
| 293 | + if (!this.systemInfo) return 0; | |
| 294 | + return this.systemInfo.windowHeight || 0; | |
| 295 | + }, | |
| 296 | + windowBottom() { | |
| 297 | + if (!this.systemInfo) return 0; | |
| 298 | + let windowBottom = this.systemInfo.windowBottom || 0; | |
| 299 | + if (this.safeAreaInsetBottom && !this.useSafeAreaPlaceholder) { | |
| 300 | + windowBottom += this.safeAreaBottom; | |
| 301 | + } | |
| 302 | + return windowBottom; | |
| 303 | + }, | |
| 304 | + isIosAndH5() { | |
| 305 | + // #ifndef H5 | |
| 306 | + return false; | |
| 307 | + // #endif | |
| 308 | + return this.isIos; | |
| 309 | + } | |
| 310 | + }, | |
| 311 | + methods: { | |
| 312 | + //当前版本号 | |
| 313 | + getVersion() { | |
| 314 | + return `z-paging v${c.version}`; | |
| 315 | + }, | |
| 316 | + //设置nvue List的specialEffects | |
| 317 | + setSpecialEffects(args) { | |
| 318 | + this.setListSpecialEffects(args); | |
| 319 | + }, | |
| 320 | + //与setSpecialEffects等效,兼容旧版本 | |
| 321 | + setListSpecialEffects(args) { | |
| 322 | + this.nFixFreezing = args && Object.keys(args).length; | |
| 323 | + if (this.isIos) { | |
| 324 | + this.privateRefresherEnabled = 0; | |
| 325 | + } | |
| 326 | + !this.usePageScroll && this.$refs['zp-n-list'].setSpecialEffects(args); | |
| 327 | + }, | |
| 328 | + // #ifdef APP-VUE | |
| 329 | + //当app长时间进入后台后进入前台,因系统内存管理导致app重新加载时,进行一些适配处理 | |
| 330 | + _handlePageLaunch() { | |
| 331 | + // 首次触发不进行处理,只有进入后台后打开app重新加载时才处理 | |
| 332 | + if (this.pageLaunched) { | |
| 333 | + // 解决在vue3+ios中,app ReLaunch时顶部下拉刷新展示位置向下偏移的问题 | |
| 334 | + // #ifdef VUE3 | |
| 335 | + this.refresherThresholdUpdateTag = 1; | |
| 336 | + this.$nextTick(() => { | |
| 337 | + this.refresherThresholdUpdateTag = 0; | |
| 338 | + }) | |
| 339 | + // #endif | |
| 340 | + // 解决使用虚拟列表时,app ReLaunch时白屏问题 | |
| 341 | + this._checkVirtualListScroll(); | |
| 342 | + } | |
| 343 | + this.pageLaunched = true; | |
| 344 | + }, | |
| 345 | + // #endif | |
| 346 | + //使手机发生较短时间的振动(15ms) | |
| 347 | + _doVibrateShort() { | |
| 348 | + // #ifndef H5 | |
| 349 | + | |
| 350 | + // #ifdef APP-PLUS | |
| 351 | + if (this.isIos) { | |
| 352 | + const UISelectionFeedbackGenerator = plus.ios.importClass('UISelectionFeedbackGenerator'); | |
| 353 | + const feedbackGenerator = new UISelectionFeedbackGenerator(); | |
| 354 | + feedbackGenerator.init(); | |
| 355 | + setTimeout(() => { | |
| 356 | + feedbackGenerator.selectionChanged(); | |
| 357 | + }, 0) | |
| 358 | + } else { | |
| 359 | + plus.device.vibrate(15); | |
| 360 | + } | |
| 361 | + // #endif | |
| 362 | + // #ifndef APP-PLUS | |
| 363 | + uni.vibrateShort(); | |
| 364 | + // #endif | |
| 365 | + | |
| 366 | + // #endif | |
| 367 | + }, | |
| 368 | + //设置z-paging高度 | |
| 369 | + async _setAutoHeight(shouldFullHeight = true, scrollViewNode = null) { | |
| 370 | + let heightKey = 'min-height'; | |
| 371 | + // #ifndef APP-NVUE | |
| 372 | + heightKey = 'min-height'; | |
| 373 | + // #endif | |
| 374 | + try { | |
| 375 | + if (shouldFullHeight) { | |
| 376 | + let finalScrollViewNode = scrollViewNode || await this._getNodeClientRect('.zp-scroll-view'); | |
| 377 | + let finalScrollBottomNode = await this._getNodeClientRect('.zp-page-bottom'); | |
| 378 | + if (finalScrollViewNode) { | |
| 379 | + const scrollViewTop = finalScrollViewNode[0].top; | |
| 380 | + let scrollViewHeight = this.windowHeight - scrollViewTop; | |
| 381 | + scrollViewHeight -= finalScrollBottomNode ? finalScrollBottomNode[0].height : 0; | |
| 382 | + const additionHeight = u.convertToPx(this.autoHeightAddition); | |
| 383 | + const finalHeight = scrollViewHeight + additionHeight - (this.insideMore ? 1 : 0) + 'px !important'; | |
| 384 | + this.$set(this.scrollViewStyle, heightKey, finalHeight); | |
| 385 | + this.$set(this.scrollViewInStyle, heightKey, finalHeight); | |
| 386 | + } | |
| 387 | + } else { | |
| 388 | + this.$delete(this.scrollViewStyle, heightKey); | |
| 389 | + this.$delete(this.scrollViewInStyle, heightKey); | |
| 390 | + } | |
| 391 | + } catch (e) {} | |
| 392 | + }, | |
| 393 | + //触发更新是否超出页面状态 | |
| 394 | + _updateInsideOfPaging() { | |
| 395 | + this.insideMore && this.insideOfPaging === true && setTimeout(this.doLoadMore, 200) | |
| 396 | + }, | |
| 397 | + //清除timeout | |
| 398 | + _cleanTimeout(timeout) { | |
| 399 | + if (timeout) { | |
| 400 | + clearTimeout(timeout); | |
| 401 | + timeout = null; | |
| 402 | + } | |
| 403 | + return timeout; | |
| 404 | + }, | |
| 405 | + //添加全局emit监听 | |
| 406 | + _onEmit() { | |
| 407 | + uni.$on(c.errorUpdateKey, () => { | |
| 408 | + this.loading && this.complete(false).catch(() => {}); | |
| 409 | + }) | |
| 410 | + uni.$on(c.completeUpdateKey, (data) => { | |
| 411 | + setTimeout(() => { | |
| 412 | + if (this.loading) { | |
| 413 | + if (!this.disabledCompleteEmit) { | |
| 414 | + const type = data.type || 'normal'; | |
| 415 | + const list = data.list || data; | |
| 416 | + const rule = data.rule; | |
| 417 | + this.fromCompleteEmit = true; | |
| 418 | + switch (type){ | |
| 419 | + case 'normal': | |
| 420 | + this.complete(list); | |
| 421 | + break; | |
| 422 | + case 'total': | |
| 423 | + this.completeByTotal(list, rule); | |
| 424 | + break; | |
| 425 | + case 'nomore': | |
| 426 | + this.completeByNoMore(list, rule); | |
| 427 | + break; | |
| 428 | + case 'key': | |
| 429 | + this.completeByKey(list, rule); | |
| 430 | + break; | |
| 431 | + default: | |
| 432 | + break; | |
| 433 | + } | |
| 434 | + } else { | |
| 435 | + this.disabledCompleteEmit = false; | |
| 436 | + } | |
| 437 | + } | |
| 438 | + }, 1); | |
| 439 | + }) | |
| 440 | + }, | |
| 441 | + //销毁全局emit和listener监听 | |
| 442 | + _offEmit(){ | |
| 443 | + uni.$off(c.errorUpdateKey); | |
| 444 | + uni.$off(c.completeUpdateKey); | |
| 445 | + } | |
| 446 | + }, | |
| 447 | +}; | ... | ... |
garbage-removal/src/components/z-paging/js/z-paging-mixin.js
0 → 100644
| 1 | +// [z-paging]使用页面滚动时引入此mixin,用于监听和处理onPullDownRefresh等页面生命周期方法 | |
| 2 | + | |
| 3 | +export default { | |
| 4 | + onPullDownRefresh() { | |
| 5 | + if (this.isPagingRefNotFound()) return; | |
| 6 | + this.$refs.paging.reload().catch(() => {}); | |
| 7 | + }, | |
| 8 | + onPageScroll(e) { | |
| 9 | + if (this.isPagingRefNotFound()) return; | |
| 10 | + this.$refs.paging.updatePageScrollTop(e.scrollTop); | |
| 11 | + e.scrollTop < 10 && this.$refs.paging.doChatRecordLoadMore(); | |
| 12 | + }, | |
| 13 | + onReachBottom() { | |
| 14 | + if (this.isPagingRefNotFound()) return; | |
| 15 | + this.$refs.paging.pageReachBottom(); | |
| 16 | + }, | |
| 17 | + methods: { | |
| 18 | + isPagingRefNotFound() { | |
| 19 | + return !this.$refs.paging; | |
| 20 | + } | |
| 21 | + } | |
| 22 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/z-paging-static.js
0 → 100644
| 1 | +// [z-paging]公用的静态图片资源 | |
| 2 | + | |
| 3 | +export default { | |
| 4 | + base64Arrow: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAD1BMVEVHcExRUVFMTExRUVFRUVE9CdWsAAAABHRSTlMAjjrY9ZnUjwAAAQFJREFUWMPt2MsNgzAMgGEEE1B1gKJmAIRYoCH7z9RCXrabh33iYktcIv35EEg5ZBh07pvxJU6MFSPOSRnjnBUjUsaciRUjMsb4xIoRCWNiYsUInzE5sWKEyxiYWDbyefqHx1zIeiYTk7mQYziTYecxHvEJjwmIT3hMQELCYSISEg4TkZj0mYTEpM8kJCU9JiMp6TEZyUmbAUhO2gxAQNJiIAKSFgMRmNQZhMCkziAEJTUGIyipMRjBSZkhCE7KDEFIUmTeGCHJxWz0zXaE0GTCG8ZFtEaS347r/1fe11YyHYVfubxayfjoHmc0YYwmmmiiiSaaaKLJ7ckyz5ve+dw3Xw2emdwm9xSbAAAAAElFTkSuQmCC', | |
| 5 | + 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==', | |
| 6 | + 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', | |
| 7 | + base64FlowerWhite: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEX///9HcEz///////////////84chYNAAAABnRSTlP/AGzCOYZj5g1nAAACfklEQVRYw+2YTVPDIBCGtza9Jw25a0bvcax30o73OOr//yvma2F3YWlpPTijXNpAHrK8LLALVPFium2vNIFSbwGKTGQA2GUiHcD29yDNy3sMIdUBQl7r2H8mOEVqAHgPkYZUS6Qc2zYhQqtjyDZEximCZwWZLIBeIgYShs2NzxKpSUehYpMJhURGb+O+w5BpMCAREKPnCDHbIY20SzhM5yxziAXpOiBXydrekT9i5XDEq4NIIHHgyU5mRGqviII4mREJJA4QJzMiILwlRJzpKxJKvCBm8OsBBbLux0tsPl4RKYm5aPu6jw1U4mGxEUR9g8M1PcqBEp/WJliNgYOXueBzS4jZSIcgY5lCtevgDSgyzE+rAfuOTQMq0yzvoGH18qju27Mayzs4fPyMziCx81NJa5RNfW7vPYK9KOfDiVkBxFHG8hAj9txuoBuSWORsFfkpBf7xKFLSeaOefEojh5jz22DJEqMP8fUyaKdQx+RnG+yXMpe8Aars8ueR1pVH/bW3FyyvPRw90upLDHwpgBDtg4aUBNkxRLXMAi03IhcZtr1m+FeI/O/JNyDmmL1djLOauSlNflBpW18RQ2bPqXI22MXXEk75KRHTnkPkYbESbdKP2ZFk0r5sIwffAjy1lx+vx7NLjB6/E7Jfv5ERKhzpN0w8IDE8IGFDv5dhz10s7GFiXRZcUeLCEG5P5nDq9k4PFDcoMpE3GY4OuxuCXhmuyNB6k0RsLIAvqp9NE5r8ZCSS8gxnUp7ODdYhZTqxuiJ9uyJJtPmpqJ7wVj+XVieS903iViHziqAhchLEJAyb7jWU647EpUofQ0ziUuXXXhDddtlllSwjgSQu7r4BRWhQqfDPMVwAAAAASUVORK5CYII=', | |
| 8 | + base64Success: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEVRUVFHcExTU1NRUVFRUVFRUVFOSlSUAAAABnRSTlP/AI6+VySB3ZENAAACcElEQVRYw+2YyYKCMAyGI8hdpdxdZu7gcpdZ7jL6/s8yYheSNi0aPdqbwOffpGmaFOYPD3gj4bisN7vddv17N/JVgxn5x12IWgIaWTuO/IE3PseQbwjGPo2cgRmHFLJwdm/X643zwiqOKPPJ1nj3sjEP2iiifZWj5bhopSyGaEO2HX5fbQJzwJ+W7x/jw5ZFjsEU0PMph9xE8i5EqprKALW95eJQURkgzw98uJ/JvwGecR7bIjWWsUgVrrIfFZ2HlLy3sKETD1mmRLRMRhGVssRa0xJkdn3SpJBymBkM8+pSSDXMDNyDaToVHd2fgpNt0sjwiUZO19+jGQ+gQEg9Oq+bufmAVGihomNmjQG7UG3020vrlm7lkFnKFGU3kZ0KGAdmKe821pipQ+qEKcrZeTL2g5FsUks4cStjEZWwXg0b0n4GxmEpkWwIs5VBynjgK7xZaz1/0D7OxkVuLpsY5BQNFyLS84VBjjbg0iL2r2EQHBOxBhikuUOkdxODVF1cxHoWtPPsiyXO455Iv34hssCO8EV4ZIYTjS8SR4qYSHRiTiYQ4ZFbHi0iIhhBTi6dTCgSWRcnw4h4yGTuyTAiOGBIWGoZTgSHJQl+LcOJ4OCnW6yX2bMnJ9pidCOXtkTkTrIGpYuOynAiOF14SamMiOCk5Ke+mq8BcOrrvym8d0zKIQnWT+M1WwOQNO4fFiWb18hhERxJPx2fblbPHHyC41VyiAtKBUFBIih7JMWVoIQTFIr3lKPN80WvoLSWFPC653ioTZA0I0FrQ7qU6asaK0H7JmkSJa2ooOGVtNUsc3j9FYHkIkJy3SG6VHnfXKXGP9t4N9Q4Ye98AAAAAElFTkSuQmCC', | |
| 9 | + base64SuccessWhite: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAGFBMVEVHcEz///////////////////////////8dS1W+AAAAB3RSTlMAiVYk6KvDHLfaegAAAo1JREFUWMPtWEtzmzAQNhCTq910ytXpiyvxTNOr60zrayepx9d02gnX4sTm7xcEiJX2gdnkGJ1A4tOnfWqXyeR1vMRYzrcPD9v5h5MBl3/Ldvx4cxIg/FWC8X0xjLjalM54uhhCfCrRuJURX0pi3EmIqZV7O59vrRZmguStHL9b7S7ftfLwOtiZDw7AHMtmquAQ12b5Wwbnordm8g9zLLO49qc/m2n6aKnhwPOGZ08hAiNHhheiHae1lOUPGZpQkPKa3q0mOUjaRzSRaGUjpy/mmWSwySSpllcEteBKAT52KEnSbblA51pJEPxBQoiH1FP4E3s5+FJv07h6/ylD6ui7B+9fq/ehrFB98ghec9EoVtyjK8pqCHLmCBOwMWSCeWFNN4MbPAk55NhsvoFHSSVR0k5TCTTEzlUGcqV/nVp7n9oIVkmtaqbAEqEgfdgHJPwsEAyZ9r4VAZXFjpEwyaw3+H2v42KYxKhs1XvY/gSSGv+IHyUSuHXCeZhLAgVI3EjgSGo1Fb3xO0tGGU9S2/KAIbtjxpJASG73qox6w5LUq0cEOa+iIONIWIilQSQ0pPa2jgaRQAgQP7c0mITRWGxpMAmEQFN2NAQJNCV0mI6GIIEO47hlQ0ORQLd0nL+hoUjg1m6I1TRr8uYEAriBHLcVFQ5UEMiBe3XkTBEG04WXlGKGxPnMS305XQPA1Ocn2JiuAZwE66fxnKwBnDTuXxZTMq85lwW6kt5ndLqZPefiU1yvmktcUSooChJF2aMprhQlnKJQ5FxRKkcVRa+itNYU8Io2oVkY14w0NMWYlqft91Bj9VHq+ca3b43BxjWJmla0sfKohlfTVpPN+93L/yLQ/IjQ/O5Q/VR5HdL4D7mlxmjwVdELAAAAAElFTkSuQmCC', | |
| 10 | + 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==', | |
| 11 | + 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', | |
| 12 | + 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==', | |
| 13 | +} | ... | ... |
garbage-removal/src/components/z-paging/js/z-paging-utils.js
0 → 100644
| 1 | +// [z-paging]工具类 | |
| 2 | + | |
| 3 | +import zConfig from './z-paging-config' | |
| 4 | +import zLocalConfig from '../config/index' | |
| 5 | +import c from './z-paging-constant' | |
| 6 | + | |
| 7 | +const storageKey = 'Z-PAGING-REFRESHER-TIME-STORAGE-KEY'; | |
| 8 | +let config = null; | |
| 9 | +const timeoutMap = {}; | |
| 10 | + | |
| 11 | +/* | |
| 12 | +当z-paging未使用uni_modules管理时,控制台会有警告:WARNING: Module not found: Error: Can't resolve '@/uni_modules/z-paging'... | |
| 13 | +此时注释下方try中的代码即可 | |
| 14 | +*/ | |
| 15 | +// #ifdef VUE2 | |
| 16 | +try { | |
| 17 | + const contextKeys = require.context('@/uni_modules/z-paging', false, /\z-paging-config$/).keys(); | |
| 18 | + if (contextKeys.length) { | |
| 19 | + const suffix = '.js'; | |
| 20 | + config = require('@/uni_modules/z-paging/z-paging-config' + suffix); | |
| 21 | + } | |
| 22 | +} catch (e) {} | |
| 23 | +// #endif | |
| 24 | + | |
| 25 | +//获取默认配置信息 | |
| 26 | +function gc(key, defaultValue) { | |
| 27 | + if (!config) { | |
| 28 | + if (zLocalConfig && Object.keys(zLocalConfig).length) { | |
| 29 | + config = zLocalConfig; | |
| 30 | + } else { | |
| 31 | + const tempConfig = zConfig.getConfig(); | |
| 32 | + if (zConfig && tempConfig) { | |
| 33 | + config = tempConfig; | |
| 34 | + } | |
| 35 | + } | |
| 36 | + } | |
| 37 | + if (!config) return defaultValue; | |
| 38 | + const value = config[_toKebab(key)]; | |
| 39 | + return value === undefined ? defaultValue : value; | |
| 40 | +} | |
| 41 | + | |
| 42 | + | |
| 43 | +//获取最终的touch位置 | |
| 44 | +function getTouch(e) { | |
| 45 | + let touch = null; | |
| 46 | + if (e.touches && e.touches.length) { | |
| 47 | + touch = e.touches[0]; | |
| 48 | + } else if (e.changedTouches && e.changedTouches.length) { | |
| 49 | + touch = e.changedTouches[0]; | |
| 50 | + } else if (e.datail && e.datail != {}) { | |
| 51 | + touch = e.datail; | |
| 52 | + } else { | |
| 53 | + return { | |
| 54 | + touchX: 0, | |
| 55 | + touchY: 0 | |
| 56 | + } | |
| 57 | + } | |
| 58 | + return { | |
| 59 | + touchX: touch.clientX, | |
| 60 | + touchY: touch.clientY | |
| 61 | + }; | |
| 62 | +} | |
| 63 | + | |
| 64 | +//判断当前手势是否在z-paging内触发 | |
| 65 | +function getTouchFromZPaging(target) { | |
| 66 | + if (target && target.tagName && target.tagName !== 'BODY' && target.tagName !== 'UNI-PAGE-BODY') { | |
| 67 | + const classList = target.classList; | |
| 68 | + if (classList && classList.contains('z-paging-content')) { | |
| 69 | + return { | |
| 70 | + isFromZp: true, | |
| 71 | + isPageScroll: classList.contains('z-paging-content-page'), | |
| 72 | + isReachedTop: classList.contains('z-paging-reached-top') | |
| 73 | + }; | |
| 74 | + } else { | |
| 75 | + return getTouchFromZPaging(target.parentNode); | |
| 76 | + } | |
| 77 | + } else { | |
| 78 | + return { isFromZp: false }; | |
| 79 | + } | |
| 80 | +} | |
| 81 | + | |
| 82 | +//获取z-paging所在的parent | |
| 83 | +function getParent(parent) { | |
| 84 | + if (!parent) return null; | |
| 85 | + if (parent.$refs.paging) return parent; | |
| 86 | + return getParent(parent.$parent); | |
| 87 | +} | |
| 88 | + | |
| 89 | +//打印错误信息 | |
| 90 | +function consoleErr(err) { | |
| 91 | + console.error(`[z-paging]${err}`); | |
| 92 | +} | |
| 93 | + | |
| 94 | +//延时操作,如果key存在,调用时根据key停止之前的延时操作 | |
| 95 | +function delay(callback, ms = c.delayTime, key) { | |
| 96 | + const timeout = setTimeout(callback, ms);; | |
| 97 | + if (!!key) { | |
| 98 | + timeoutMap[key] && clearTimeout(timeoutMap[key]); | |
| 99 | + timeoutMap[key] = timeout; | |
| 100 | + } | |
| 101 | + return timeout; | |
| 102 | +} | |
| 103 | + | |
| 104 | +//设置下拉刷新时间 | |
| 105 | +function setRefesrherTime(time, key) { | |
| 106 | + const datas = getRefesrherTime() || {}; | |
| 107 | + datas[key] = time; | |
| 108 | + uni.setStorageSync(storageKey, datas); | |
| 109 | +} | |
| 110 | + | |
| 111 | +//获取下拉刷新时间 | |
| 112 | +function getRefesrherTime() { | |
| 113 | + return uni.getStorageSync(storageKey); | |
| 114 | +} | |
| 115 | + | |
| 116 | +//通过下拉刷新标识key获取下拉刷新时间 | |
| 117 | +function getRefesrherTimeByKey(key) { | |
| 118 | + const datas = getRefesrherTime(); | |
| 119 | + return datas && datas[key] ? datas[key] : null; | |
| 120 | +} | |
| 121 | + | |
| 122 | +//通过下拉刷新标识key获取下拉刷新时间(格式化之后) | |
| 123 | +function getRefesrherFormatTimeByKey(key, textMap) { | |
| 124 | + const time = getRefesrherTimeByKey(key); | |
| 125 | + const timeText = time ? _timeFormat(time, textMap) : textMap.none; | |
| 126 | + return `${textMap.title}${timeText}`; | |
| 127 | +} | |
| 128 | + | |
| 129 | +//将文本的px或者rpx转为px的值 | |
| 130 | +function convertToPx(text) { | |
| 131 | + const dataType = Object.prototype.toString.call(text); | |
| 132 | + if (dataType === '[object Number]') return text; | |
| 133 | + let isRpx = false; | |
| 134 | + if (text.indexOf('rpx') !== -1 || text.indexOf('upx') !== -1) { | |
| 135 | + text = text.replace('rpx', '').replace('upx', ''); | |
| 136 | + isRpx = true; | |
| 137 | + } else if (text.indexOf('px') !== -1) { | |
| 138 | + text = text.replace('px', ''); | |
| 139 | + } | |
| 140 | + if (!isNaN(text)) { | |
| 141 | + if (isRpx) return Number(uni.upx2px(text)); | |
| 142 | + return Number(text); | |
| 143 | + } | |
| 144 | + return 0; | |
| 145 | +} | |
| 146 | + | |
| 147 | +//获取当前时间 | |
| 148 | +function getTime() { | |
| 149 | + return (new Date()).getTime(); | |
| 150 | +} | |
| 151 | + | |
| 152 | +//获取z-paging实例id | |
| 153 | +function getInstanceId() { | |
| 154 | + const s = []; | |
| 155 | + const hexDigits = "0123456789abcdef"; | |
| 156 | + for (let i = 0; i < 10; i++) { | |
| 157 | + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); | |
| 158 | + } | |
| 159 | + return s.join('') + getTime(); | |
| 160 | +} | |
| 161 | + | |
| 162 | +// 等待一段时间 | |
| 163 | +function wait(ms) { | |
| 164 | + return new Promise(resolve => { | |
| 165 | + setTimeout(resolve, ms); | |
| 166 | + }); | |
| 167 | +} | |
| 168 | + | |
| 169 | +//------------------ 私有方法 ------------------------ | |
| 170 | +//时间格式化 | |
| 171 | +function _timeFormat(time, textMap) { | |
| 172 | + const date = new Date(time); | |
| 173 | + const currentDate = new Date(); | |
| 174 | + const dateDay = new Date(time).setHours(0, 0, 0, 0); | |
| 175 | + const currentDateDay = new Date().setHours(0, 0, 0, 0); | |
| 176 | + const disTime = dateDay - currentDateDay; | |
| 177 | + let dayStr = ''; | |
| 178 | + const timeStr = _dateTimeFormat(date); | |
| 179 | + if (disTime === 0) { | |
| 180 | + dayStr = textMap.today; | |
| 181 | + } else if (disTime === -86400000) { | |
| 182 | + dayStr = textMap.yesterday; | |
| 183 | + } else { | |
| 184 | + dayStr = _dateDayFormat(date, date.getFullYear() !== currentDate.getFullYear()); | |
| 185 | + } | |
| 186 | + return `${dayStr} ${timeStr}`; | |
| 187 | +} | |
| 188 | + | |
| 189 | +//date格式化为年月日 | |
| 190 | +function _dateDayFormat(date, showYear = true) { | |
| 191 | + const year = date.getFullYear(); | |
| 192 | + const month = date.getMonth() + 1; | |
| 193 | + const day = date.getDate(); | |
| 194 | + return showYear ? `${year}-${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}` : `${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`; | |
| 195 | +} | |
| 196 | + | |
| 197 | +//data格式化为时分 | |
| 198 | +function _dateTimeFormat(date) { | |
| 199 | + const hour = date.getHours(); | |
| 200 | + const minute = date.getMinutes(); | |
| 201 | + return `${_fullZeroToTwo(hour)}:${_fullZeroToTwo(minute)}`; | |
| 202 | +} | |
| 203 | + | |
| 204 | +//不满2位在前面填充0 | |
| 205 | +function _fullZeroToTwo(str) { | |
| 206 | + str = str.toString(); | |
| 207 | + return str.length === 1 ? '0' + str : str; | |
| 208 | +} | |
| 209 | + | |
| 210 | +//驼峰转短横线 | |
| 211 | +function _toKebab(value) { | |
| 212 | + return value.replace(/([A-Z])/g, "-$1").toLowerCase(); | |
| 213 | +} | |
| 214 | + | |
| 215 | +export default { | |
| 216 | + gc, | |
| 217 | + setRefesrherTime, | |
| 218 | + getRefesrherFormatTimeByKey, | |
| 219 | + getTouch, | |
| 220 | + getTouchFromZPaging, | |
| 221 | + getParent, | |
| 222 | + convertToPx, | |
| 223 | + getTime, | |
| 224 | + getInstanceId, | |
| 225 | + consoleErr, | |
| 226 | + delay, | |
| 227 | + wait | |
| 228 | +}; | ... | ... |
garbage-removal/src/components/z-paging/wxs/z-paging-renderjs.js
0 → 100644
| 1 | +// [z-paging]使用renderjs在app-vue和h5中对touchmove事件冒泡进行处理 | |
| 2 | + | |
| 3 | +import u from '../js/z-paging-utils' | |
| 4 | +const data = { | |
| 5 | + startY: 0, | |
| 6 | + isTouchFromZPaging: false, | |
| 7 | + isUsePageScroll: false, | |
| 8 | + isReachedTop: true, | |
| 9 | + isIosAndH5: false, | |
| 10 | + appLaunched: false | |
| 11 | +} | |
| 12 | + | |
| 13 | +export default { | |
| 14 | + mounted() { | |
| 15 | + if (window) { | |
| 16 | + this._handleTouch(); | |
| 17 | + // #ifdef APP-VUE | |
| 18 | + this.$ownerInstance.callMethod('_handlePageLaunch'); | |
| 19 | + // #endif | |
| 20 | + } | |
| 21 | + }, | |
| 22 | + methods: { | |
| 23 | + //接收逻辑层发送的数据 | |
| 24 | + renderPropIsIosAndH5Change(newVal) { | |
| 25 | + if (newVal === -1) return; | |
| 26 | + data.isIosAndH5 = newVal; | |
| 27 | + }, | |
| 28 | + //拦截处理touch事件 | |
| 29 | + _handleTouch() { | |
| 30 | + if (!window.$zPagingRenderJsInited) { | |
| 31 | + window.$zPagingRenderJsInited = true; | |
| 32 | + window.addEventListener('touchstart', this._handleTouchstart, { passive: true }) | |
| 33 | + window.addEventListener('touchmove', this._handleTouchmove, { passive: false }) | |
| 34 | + } | |
| 35 | + }, | |
| 36 | + _handleTouchstart(e) { | |
| 37 | + const touch = u.getTouch(e); | |
| 38 | + data.startY = touch.touchY; | |
| 39 | + const touchResult = u.getTouchFromZPaging(e.target); | |
| 40 | + data.isTouchFromZPaging = touchResult.isFromZp; | |
| 41 | + data.isUsePageScroll = touchResult.isPageScroll; | |
| 42 | + data.isReachedTop = touchResult.isReachedTop; | |
| 43 | + }, | |
| 44 | + _handleTouchmove(e) { | |
| 45 | + const touch = u.getTouch(e); | |
| 46 | + const moveY = touch.touchY - data.startY; | |
| 47 | + if (data.isTouchFromZPaging && ((data.isReachedTop && moveY > 0) || (data.isIosAndH5 && !data.isUsePageScroll && moveY < 0))) { | |
| 48 | + if (e.cancelable && !e.defaultPrevented) { | |
| 49 | + e.preventDefault(); | |
| 50 | + } | |
| 51 | + } | |
| 52 | + }, | |
| 53 | + _removeAllEventListener(){ | |
| 54 | + window.removeEventListener('touchstart'); | |
| 55 | + window.removeEventListener('touchmove'); | |
| 56 | + } | |
| 57 | + } | |
| 58 | +}; | ... | ... |
garbage-removal/src/components/z-paging/wxs/z-paging-wxs.wxs
0 → 100644
| 1 | +// [z-paging]微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新,降低逻辑层与视图层的通信折损,提升性能 | |
| 2 | + | |
| 3 | +var currentDis = 0; | |
| 4 | +var isPCFlag = -1; | |
| 5 | +var startY = -1; | |
| 6 | + | |
| 7 | +function propObserver(newValue, oldValue, ownerIns, ins) { | |
| 8 | + var state = ownerIns.getState() || {}; | |
| 9 | + state.currentIns = ins; | |
| 10 | + var dataset = ins.getDataset(); | |
| 11 | + var loading = dataset.loading == true; | |
| 12 | + if (newValue && newValue.indexOf('end') != -1) { | |
| 13 | + var transition = newValue.split('end')[0]; | |
| 14 | + _setTransform('translateY(0px)', ins, false, transition); | |
| 15 | + state.moveDis = 0; | |
| 16 | + state.oldMoveDis = 0; | |
| 17 | + currentDis = 0; | |
| 18 | + } else if (newValue && newValue.indexOf('begin') != -1) { | |
| 19 | + var refresherThreshold = ins.getDataset().refresherthreshold; | |
| 20 | + _setTransformValue(refresherThreshold, ins, state, false); | |
| 21 | + } | |
| 22 | +} | |
| 23 | + | |
| 24 | +function touchstart(e, ownerIns) { | |
| 25 | + var ins = _getIns(ownerIns); | |
| 26 | + var state = {}; | |
| 27 | + var dataset = {}; | |
| 28 | + ownerIns.callMethod('_handleListTouchstart'); | |
| 29 | + if (ins) { | |
| 30 | + state = ins.getState(); | |
| 31 | + dataset = ins.getDataset(); | |
| 32 | + if (_touchDisabled(e, ins, 0)) return; | |
| 33 | + } | |
| 34 | + var isTouchEnded = state.isTouchEnded; | |
| 35 | + state.oldMoveDis = 0; | |
| 36 | + var touch = _getTouch(e); | |
| 37 | + var loading = _isTrue(dataset.loading); | |
| 38 | + state.startY = touch.touchY; | |
| 39 | + startY = state.startY; | |
| 40 | + state.lastTouch = touch; | |
| 41 | + if (!loading && isTouchEnded) { | |
| 42 | + state.isTouchmoving = false; | |
| 43 | + } | |
| 44 | + state.isTouchEnded = false; | |
| 45 | + ownerIns.callMethod('_handleRefresherTouchstart', touch); | |
| 46 | +} | |
| 47 | + | |
| 48 | +function touchmove(e, ownerIns) { | |
| 49 | + var touch = _getTouch(e); | |
| 50 | + var ins = _getIns(ownerIns); | |
| 51 | + var dataset = ins.getDataset(); | |
| 52 | + var refresherThreshold = dataset.refresherthreshold; | |
| 53 | + var isIos = _isTrue(dataset.isios); | |
| 54 | + var state = ins.getState(); | |
| 55 | + var watchTouchDirectionChange = _isTrue(dataset.watchtouchdirectionchange); | |
| 56 | + var moveDisObj = {}; | |
| 57 | + var moveDis = 0; | |
| 58 | + var prevent = false; | |
| 59 | + if (watchTouchDirectionChange) { | |
| 60 | + moveDisObj = _getMoveDis(e, ins); | |
| 61 | + moveDis = moveDisObj.currentDis; | |
| 62 | + prevent = moveDisObj.isDown; | |
| 63 | + var direction = prevent ? 'top' : 'bottom'; | |
| 64 | + if (prevent == state.oldTouchDirection && prevent != state.oldEmitedTouchDirection) { | |
| 65 | + ownerIns.callMethod('_handleTouchDirectionChange', { direction: direction }); | |
| 66 | + state.oldEmitedTouchDirection = prevent; | |
| 67 | + } | |
| 68 | + state.oldTouchDirection = prevent; | |
| 69 | + } | |
| 70 | + if (_touchDisabled(e, ins, 1)) { | |
| 71 | + _handlePullingDown(state, ownerIns, false); | |
| 72 | + return true; | |
| 73 | + } | |
| 74 | + if (!_getAngleIsInRange(e, touch, state, dataset)) { | |
| 75 | + _handlePullingDown(state, ownerIns, false); | |
| 76 | + return true; | |
| 77 | + } | |
| 78 | + moveDisObj = _getMoveDis(e, ins); | |
| 79 | + moveDis = moveDisObj.currentDis; | |
| 80 | + prevent = moveDisObj.isDown; | |
| 81 | + if (moveDis < 0) { | |
| 82 | + _setTransformValue(0, ins, state, false); | |
| 83 | + _handlePullingDown(state, ownerIns, false); | |
| 84 | + return true; | |
| 85 | + } | |
| 86 | + if (prevent && !state.disabledBounce) { | |
| 87 | + ownerIns.callMethod('_handleScrollViewDisableBounce', {bounce: false}); | |
| 88 | + state.disabledBounce = true; | |
| 89 | + _handlePullingDown(state, ownerIns, prevent); | |
| 90 | + return !prevent; | |
| 91 | + } | |
| 92 | + _setTransformValue(moveDis, ins, state, false); | |
| 93 | + var oldRefresherStatus = state.refresherStatus; | |
| 94 | + var oldIsTouchmoving = _isTrue(dataset.oldistouchmoving); | |
| 95 | + var hasTouchmove = _isTrue(dataset.hastouchmove); | |
| 96 | + var isTouchmoving = state.isTouchmoving; | |
| 97 | + state.refresherStatus = moveDis >= refresherThreshold ? 1 : 0; | |
| 98 | + if (!isTouchmoving) { | |
| 99 | + state.isTouchmoving = true; | |
| 100 | + isTouchmoving = true; | |
| 101 | + } | |
| 102 | + if (state.isTouchEnded) { | |
| 103 | + state.isTouchEnded = false; | |
| 104 | + } | |
| 105 | + if (hasTouchmove) { | |
| 106 | + ownerIns.callMethod('_handleWxsPullingDown', { moveDis:moveDis, diffDis:moveDisObj.diffDis }); | |
| 107 | + } | |
| 108 | + if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || oldIsTouchmoving != isTouchmoving) { | |
| 109 | + ownerIns.callMethod('_handleRefresherTouchmove', moveDis, touch); | |
| 110 | + } | |
| 111 | + _handlePullingDown(state, ownerIns, prevent); | |
| 112 | + return !prevent; | |
| 113 | +} | |
| 114 | + | |
| 115 | +function touchend(e, ownerIns) { | |
| 116 | + var touch = _getTouch(e); | |
| 117 | + var ins = _getIns(ownerIns); | |
| 118 | + var dataset = ins.getDataset(); | |
| 119 | + var state = ins.getState(); | |
| 120 | + if (_touchDisabled(e, ins, 2)) return; | |
| 121 | + state.reachMaxAngle = true; | |
| 122 | + state.hitReachMaxAngleCount = 0; | |
| 123 | + state.disabledBounce = false; | |
| 124 | + state.fixedIsTopHitCount = 0; | |
| 125 | + if (!state.isTouchmoving) return; | |
| 126 | + var oldRefresherStatus = state.refresherStatus; | |
| 127 | + var oldMoveDis = state.moveDis; | |
| 128 | + var refresherThreshold = ins.getDataset().refresherthreshold | |
| 129 | + var moveDis = _getMoveDis(e, ins).currentDis; | |
| 130 | + if (!(moveDis >= refresherThreshold && oldRefresherStatus === 1)) { | |
| 131 | + state.isTouchmoving = false; | |
| 132 | + } | |
| 133 | + ownerIns.callMethod('_handleRefresherTouchend', moveDis); | |
| 134 | + state.isTouchEnded = true; | |
| 135 | + if (oldMoveDis < refresherThreshold) return; | |
| 136 | + var animate = false; | |
| 137 | + if (moveDis >= refresherThreshold) { | |
| 138 | + moveDis = refresherThreshold; | |
| 139 | + animate = true; | |
| 140 | + } | |
| 141 | + _setTransformValue(moveDis, ins, state, animate); | |
| 142 | +} | |
| 143 | + | |
| 144 | +// #ifdef H5 | |
| 145 | +function isPC() { | |
| 146 | + if (!navigator) return false; | |
| 147 | + if (isPCFlag != -1) return isPCFlag; | |
| 148 | + var agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]; | |
| 149 | + isPCFlag = agents.every(function(item) { return navigator.userAgent.indexOf(item) < 0 }); | |
| 150 | + return isPCFlag; | |
| 151 | +} | |
| 152 | + | |
| 153 | +var movable = false; | |
| 154 | + | |
| 155 | +function mousedown(e, ins) { | |
| 156 | + if (!isPC()) return; | |
| 157 | + touchstart(e, ins); | |
| 158 | + movable = true; | |
| 159 | +} | |
| 160 | + | |
| 161 | +function mousemove(e, ins) { | |
| 162 | + if (!isPC() || !movable) return; | |
| 163 | + touchmove(e, ins); | |
| 164 | +} | |
| 165 | + | |
| 166 | +function mouseup(e, ins) { | |
| 167 | + if (!isPC()) return; | |
| 168 | + touchend(e, ins); | |
| 169 | + movable = false; | |
| 170 | +} | |
| 171 | + | |
| 172 | +function mouseleave(e, ins) { | |
| 173 | + if (!isPC()) return; | |
| 174 | + movable = false; | |
| 175 | +} | |
| 176 | +// #endif | |
| 177 | + | |
| 178 | + | |
| 179 | +function _setTransformValue(value, ins, state, animate) { | |
| 180 | + value = value || 0; | |
| 181 | + if (state.moveDis == value) return; | |
| 182 | + state.moveDis = value; | |
| 183 | + _setTransform('translateY(' + value + 'px)', ins, animate, ''); | |
| 184 | +} | |
| 185 | + | |
| 186 | +function _setTransform(transform, ins, animate, transition) { | |
| 187 | + var dataset = ins.getDataset(); | |
| 188 | + if (_isTrue(dataset.refreshernotransform)) return; | |
| 189 | + transform = transform == 'translateY(0px)' ? 'none' : transform; | |
| 190 | + ins.requestAnimationFrame(function() { | |
| 191 | + var stl = { 'transform': transform }; | |
| 192 | + if (animate) { | |
| 193 | + stl['transition'] = 'transform .1s linear'; | |
| 194 | + } | |
| 195 | + if (transition.length) { | |
| 196 | + stl['transition'] = transition; | |
| 197 | + } | |
| 198 | + ins.setStyle(stl); | |
| 199 | + }) | |
| 200 | +} | |
| 201 | + | |
| 202 | +function _getMoveDis(e, ins) { | |
| 203 | + var state = ins.getState(); | |
| 204 | + var refresherThreshold = parseFloat(ins.getDataset().refresherthreshold); | |
| 205 | + var refresherOutRate = parseFloat(ins.getDataset().refresheroutrate); | |
| 206 | + var refresherPullRate = parseFloat(ins.getDataset().refresherpullrate); | |
| 207 | + var touch = _getTouch(e); | |
| 208 | + var currentStartY = !state.startY || state.startY == 'NaN' ? startY : state.startY; | |
| 209 | + var moveDis = touch.touchY - currentStartY; | |
| 210 | + var oldMoveDis = state.oldMoveDis || 0; | |
| 211 | + state.oldMoveDis = moveDis; | |
| 212 | + var diffDis = moveDis - oldMoveDis; | |
| 213 | + if (diffDis > 0) { | |
| 214 | + diffDis = diffDis * refresherPullRate; | |
| 215 | + if (currentDis > refresherThreshold) { | |
| 216 | + diffDis = diffDis * (1 - refresherOutRate); | |
| 217 | + } | |
| 218 | + } | |
| 219 | + diffDis = diffDis > 100 ? diffDis / 100 : (diffDis > 20 ? diffDis / 1.2 : diffDis); | |
| 220 | + currentDis += diffDis; | |
| 221 | + currentDis = Math.max(0, currentDis); | |
| 222 | + return { | |
| 223 | + currentDis: currentDis, | |
| 224 | + diffDis: diffDis, | |
| 225 | + isDown: diffDis > 0 | |
| 226 | + }; | |
| 227 | +} | |
| 228 | + | |
| 229 | +function _getTouch(e) { | |
| 230 | + var touch = e; | |
| 231 | + if (e.touches && e.touches.length) { | |
| 232 | + touch = e.touches[0]; | |
| 233 | + } else if (e.changedTouches && e.changedTouches.length) { | |
| 234 | + touch = e.changedTouches[0]; | |
| 235 | + } else if (e.datail && e.datail != {}) { | |
| 236 | + touch = e.datail; | |
| 237 | + } | |
| 238 | + return { | |
| 239 | + touchX: touch.clientX, | |
| 240 | + touchY: touch.clientY | |
| 241 | + }; | |
| 242 | +} | |
| 243 | + | |
| 244 | +function _getIns(ownerIns) { | |
| 245 | + var ins = ownerIns.getState().currentIns; | |
| 246 | + if (!ins) { | |
| 247 | + ownerIns.callMethod('_handlePropUpdate'); | |
| 248 | + } | |
| 249 | + return ins; | |
| 250 | +} | |
| 251 | + | |
| 252 | +function _touchDisabled(e, ins, processTag) { | |
| 253 | + var dataset = ins.getDataset(); | |
| 254 | + var state = ins.getState(); | |
| 255 | + var loading = _isTrue(dataset.loading); | |
| 256 | + var useChatRecordMode = _isTrue(dataset.usechatrecordmode); | |
| 257 | + var refresherEnabled = _isTrue(dataset.refresherenabled); | |
| 258 | + var useCustomRefresher = _isTrue(dataset.usecustomrefresher); | |
| 259 | + var usePageScroll = _isTrue(dataset.usepagescroll); | |
| 260 | + var pageScrollTop = parseFloat(dataset.pagescrolltop); | |
| 261 | + var scrollTop = parseFloat(dataset.scrolltop); | |
| 262 | + var finalScrollTop = usePageScroll ? pageScrollTop : scrollTop; | |
| 263 | + var fixedIsTop = false; | |
| 264 | + var isIos = _isTrue(dataset.isios); | |
| 265 | + if (!isIos && finalScrollTop == (state.startScrollTop || 0) && finalScrollTop <= 105) { | |
| 266 | + fixedIsTop = true; | |
| 267 | + } | |
| 268 | + var fixedIsTopHitCount = state.fixedIsTopHitCount || 0; | |
| 269 | + if (fixedIsTop) { | |
| 270 | + fixedIsTopHitCount ++; | |
| 271 | + if (fixedIsTopHitCount <= 2) { | |
| 272 | + fixedIsTop = false; | |
| 273 | + } | |
| 274 | + state.fixedIsTopHitCount = fixedIsTopHitCount; | |
| 275 | + } else { | |
| 276 | + state.fixedIsTopHitCount = 0; | |
| 277 | + } | |
| 278 | + if (!isIos && processTag === 0) { | |
| 279 | + state.startScrollTop = finalScrollTop || 0; | |
| 280 | + } | |
| 281 | + if (!isIos && processTag === 2) { | |
| 282 | + fixedIsTop = true; | |
| 283 | + } | |
| 284 | + return loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || | |
| 285 | + ((usePageScroll && useCustomRefresher && pageScrollTop > 5) && !fixedIsTop) || | |
| 286 | + ((!usePageScroll && useCustomRefresher && scrollTop > 5) && !fixedIsTop); | |
| 287 | +} | |
| 288 | + | |
| 289 | +function _getAngleIsInRange(e, touch, state, dataset) { | |
| 290 | + var maxAngle = dataset.refreshermaxangle; | |
| 291 | + var refresherAecc = _isTrue(dataset.refresheraecc); | |
| 292 | + var lastTouch = state.lastTouch; | |
| 293 | + var reachMaxAngle = state.reachMaxAngle; | |
| 294 | + var moveDis = state.oldMoveDis; | |
| 295 | + if (!lastTouch) return true; | |
| 296 | + if (maxAngle >= 0 && maxAngle <= 90 && lastTouch) { | |
| 297 | + if ((!moveDis || moveDis < 1) && !refresherAecc && reachMaxAngle != null && !reachMaxAngle) return false; | |
| 298 | + var x = Math.abs(touch.touchX - lastTouch.touchX); | |
| 299 | + var y = Math.abs(touch.touchY - lastTouch.touchY); | |
| 300 | + var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); | |
| 301 | + if ((x || y) && x > 1) { | |
| 302 | + var angle = Math.asin(y / z) / Math.PI * 180; | |
| 303 | + if (angle < maxAngle) { | |
| 304 | + var hitReachMaxAngleCount = state.hitReachMaxAngleCount || 0; | |
| 305 | + state.hitReachMaxAngleCount = ++hitReachMaxAngleCount; | |
| 306 | + if (state.hitReachMaxAngleCount > 2) { | |
| 307 | + state.lastTouch = touch; | |
| 308 | + state.reachMaxAngle = false; | |
| 309 | + } | |
| 310 | + return false; | |
| 311 | + } | |
| 312 | + } | |
| 313 | + } | |
| 314 | + state.lastTouch = touch; | |
| 315 | + return true; | |
| 316 | +} | |
| 317 | + | |
| 318 | +function _handlePullingDown(state, ins, onPullingDown) { | |
| 319 | + var oldOnPullingDown = state.onPullingDown || false; | |
| 320 | + if (oldOnPullingDown != onPullingDown) { | |
| 321 | + ins.callMethod('_handleWxsPullingDownStatusChange', onPullingDown); | |
| 322 | + } | |
| 323 | + state.onPullingDown = onPullingDown; | |
| 324 | +} | |
| 325 | + | |
| 326 | +function _isTrue(value) { | |
| 327 | + value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false; | |
| 328 | + return value == true || value == 'true'; | |
| 329 | +} | |
| 330 | + | |
| 331 | +module.exports = { | |
| 332 | + touchstart: touchstart, | |
| 333 | + touchmove: touchmove, | |
| 334 | + touchend: touchend, | |
| 335 | + mousedown: mousedown, | |
| 336 | + mousemove: mousemove, | |
| 337 | + mouseup: mouseup, | |
| 338 | + mouseleave: mouseleave, | |
| 339 | + propObserver: propObserver | |
| 340 | +} | ... | ... |
garbage-removal/src/components/z-paging/z-paging.vue
0 → 100644
| 1 | + <!-- _ | |
| 2 | + ____ _ __ __ _ __ _(_)_ __ __ _ | |
| 3 | + |_ /____| '_ \ / _` |/ _` | | '_ \ / _` | | |
| 4 | + / /_____| |_) | (_| | (_| | | | | | (_| | | |
| 5 | + /___| | .__/ \__,_|\__, |_|_| |_|\__, | | |
| 6 | + |_| |___/ |___/ | |
| 7 | +v2.6.2 (2023-10-31) | |
| 8 | +by ZXLee | |
| 9 | +--> | |
| 10 | +<!-- 文档地址:https://z-paging.zxlee.cn --> | |
| 11 | +<!-- github地址:https://github.com/SmileZXLee/uni-z-paging --> | |
| 12 | +<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 --> | |
| 13 | +<!-- 反馈QQ群:790460711(已满)、371624008 --> | |
| 14 | + | |
| 15 | +<template name="z-paging"> | |
| 16 | + <!-- #ifndef APP-NVUE --> | |
| 17 | + <view :class="{'z-paging-content':true,'z-paging-content-fixed':!usePageScroll&&fixed,'z-paging-content-page':usePageScroll,'z-paging-reached-top':renderPropScrollTop<1}" :style="[finalPagingStyle]"> | |
| 18 | + <!-- #ifndef APP-PLUS --> | |
| 19 | + <view v-if="cssSafeAreaInsetBottom===-1" class="zp-safe-area-inset-bottom"></view> | |
| 20 | + <!-- #endif --> | |
| 21 | + <!-- 顶部固定的slot --> | |
| 22 | + <slot v-if="!usePageScroll&&zSlots.top" name="top" /> | |
| 23 | + <view class="zp-page-top" @touchmove.stop.prevent v-else-if="usePageScroll&&zSlots.top" :style="[{'top':`${windowTop}px`,'z-index':topZIndex}]"> | |
| 24 | + <slot name="top" /> | |
| 25 | + </view> | |
| 26 | + <view :class="{'zp-view-super':true,'zp-scroll-view-super':!usePageScroll}" :style="[finalScrollViewStyle]"> | |
| 27 | + <view v-if="zSlots.left" :class="{'zp-page-left':true,'zp-absoulte':finalIsOldWebView}"> | |
| 28 | + <slot name="left" /> | |
| 29 | + </view> | |
| 30 | + <view :class="{'zp-scroll-view-container':true,'zp-absoulte':finalIsOldWebView}" :style="[scrollViewContainerStyle]"> | |
| 31 | + <scroll-view | |
| 32 | + ref="zp-scroll-view" :class="{'zp-scroll-view':true,'zp-scroll-view-absolute':!usePageScroll,'zp-scroll-view-hide-scrollbar':!showScrollbar}" | |
| 33 | + :scroll-top="scrollTop" :scroll-x="scrollX" | |
| 34 | + :scroll-y="scrollable&&!usePageScroll&&scrollEnable&&(refresherCompleteScrollable?true:refresherStatus!==R.Complete)" :enable-back-to-top="finalEnableBackToTop" | |
| 35 | + :show-scrollbar="showScrollbar" :scroll-with-animation="finalScrollWithAnimation" | |
| 36 | + :scroll-into-view="scrollIntoView" :lower-threshold="finalLowerThreshold" :upper-threshold="5" | |
| 37 | + :refresher-enabled="finalRefresherEnabled&&!useCustomRefresher" :refresher-threshold="finalRefresherThreshold" | |
| 38 | + :refresher-default-style="finalRefresherDefaultStyle" :refresher-background="refresherBackground" | |
| 39 | + :refresher-triggered="finalRefresherTriggered" @scroll="_scroll" @scrolltolower="_onScrollToLower" | |
| 40 | + @scrolltoupper="_onScrollToUpper" @refresherrestore="_onRestore" @refresherrefresh="_onRefresh(true)" | |
| 41 | + > | |
| 42 | + <view class="zp-paging-touch-view" | |
| 43 | + <!-- #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 --> | |
| 44 | + @touchstart="_refresherTouchstart" @touchmove="_refresherTouchmove" @touchend="_refresherTouchend" @touchcancel="_refresherTouchend" | |
| 45 | + <!-- #endif --> | |
| 46 | + <!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 --> | |
| 47 | + @touchstart="pagingWxs.touchstart" @touchmove="pagingWxs.touchmove" @touchend="pagingWxs.touchend" @touchcancel="pagingWxs.touchend" | |
| 48 | + @mousedown="pagingWxs.mousedown" @mousemove="pagingWxs.mousemove" @mouseup="pagingWxs.mouseup" @mouseleave="pagingWxs.mouseleave" | |
| 49 | + <!-- #endif --> | |
| 50 | + > | |
| 51 | + <view v-if="finalRefresherFixedBacHeight>0" class="zp-fixed-bac-view" :style="[{'background': refresherFixedBackground,'height': `${finalRefresherFixedBacHeight}px`}]"></view> | |
| 52 | + <view class="zp-paging-main" :style="[scrollViewInStyle,{'transform': finalRefresherTransform,'transition': refresherTransition}]" | |
| 53 | + <!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 --> | |
| 54 | + :change:prop="pagingWxs.propObserver" :prop="wxsPropType" | |
| 55 | + :data-refresherThreshold="finalRefresherThreshold" :data-isIos="isIos" | |
| 56 | + :data-loading="loading||isRefresherInComplete" :data-useChatRecordMode="useChatRecordMode" | |
| 57 | + :data-refresherEnabled="refresherEnabled" :data-useCustomRefresher="useCustomRefresher" :data-pageScrollTop="wxsPageScrollTop" | |
| 58 | + :data-scrollTop="wxsScrollTop" :data-refresherMaxAngle="refresherMaxAngle" :data-refresherNoTransform="refresherNoTransform" | |
| 59 | + :data-refresherAecc="refresherAngleEnableChangeContinued" :data-usePageScroll="usePageScroll" :data-watchTouchDirectionChange="watchTouchDirectionChange" | |
| 60 | + :data-oldIsTouchmoving="isTouchmoving" :data-refresherOutRate="finalRefresherOutRate" :data-refresherPullRate="finalRefresherPullRate" :data-hasTouchmove="hasTouchmove" | |
| 61 | + <!-- #endif --> | |
| 62 | + <!-- #ifdef APP-VUE || H5 --> | |
| 63 | + :change:renderPropIsIosAndH5="pagingRenderjs.renderPropIsIosAndH5Change" :renderPropIsIosAndH5="isIosAndH5" | |
| 64 | + <!-- #endif --> | |
| 65 | + > | |
| 66 | + <view v-if="showRefresher" class="zp-custom-refresher-view" :style="[{'margin-top': `-${finalRefresherThreshold+refresherThresholdUpdateTag}px`,'background': refresherBackground,'opacity': isTouchmoving ? 1 : 0}]"> | |
| 67 | + <view class="zp-custom-refresher-container" :style="[{'height': `${finalRefresherThreshold}px`,'background': refresherBackground}]"> | |
| 68 | + <view v-if="useRefresherStatusBarPlaceholder" class="zp-custom-refresher-status-bar-placeholder" :style="[{'height': `${statusBarHeight}px`}]" /> | |
| 69 | + <!-- 下拉刷新view --> | |
| 70 | + <view class="zp-custom-refresher-slot-view"> | |
| 71 | + <slot v-if="!(zSlots.refresherComplete&&refresherStatus===R.Complete)" :refresherStatus="refresherStatus" name="refresher" /> | |
| 72 | + </view> | |
| 73 | + <slot v-if="zSlots.refresherComplete&&refresherStatus===R.Complete" name="refresherComplete" /> | |
| 74 | + <z-paging-refresh ref="refresh" v-else-if="!showCustomRefresher" class="zp-custom-refresher-refresh" :style="[{'height': `${finalRefresherThreshold - finalRefresherThresholdPlaceholder}px`}]" :status="refresherStatus" | |
| 75 | + :defaultThemeStyle="finalRefresherThemeStyle" :defaultText="finalRefresherDefaultText" | |
| 76 | + :pullingText="finalRefresherPullingText" :refreshingText="finalRefresherRefreshingText" :completeText="finalRefresherCompleteText" | |
| 77 | + :defaultImg="refresherDefaultImg" :pullingImg="refresherPullingImg" :refreshingImg="refresherRefreshingImg" :completeImg="refresherCompleteImg" :refreshingAnimated="refresherRefreshingAnimated" | |
| 78 | + :showUpdateTime="showRefresherUpdateTime" :updateTimeKey="refresherUpdateTimeKey" :updateTimeTextMap="finalRefresherUpdateTimeTextMap" | |
| 79 | + :imgStyle="refresherImgStyle" :titleStyle="refresherTitleStyle" :updateTimeStyle="refresherUpdateTimeStyle" /> | |
| 80 | + </view> | |
| 81 | + </view> | |
| 82 | + <view class="zp-paging-container"> | |
| 83 | + <slot v-if="useChatRecordMode&&zSlots.chatLoading&&loadingStatus!==M.NoMore&&realTotalData.length" name="chatLoading" /> | |
| 84 | + <view v-else-if="useChatRecordMode&&loadingStatus!==M.NoMore&&realTotalData.length" class="zp-chat-record-loading-container"> | |
| 85 | + <text v-if="loadingStatus!==M.Loading" @click="_onScrollToUpper" | |
| 86 | + :class="defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{chatRecordLoadingMoreText}}</text> | |
| 87 | + <image v-else :src="base64Flower" class="zp-chat-record-loading-custom-image" /> | |
| 88 | + </view> | |
| 89 | + <!-- 全屏Loading --> | |
| 90 | + <slot v-if="showLoading&&zSlots.loading&&!loadingFullFixed" name="loading" /> | |
| 91 | + <!-- 主体内容 --> | |
| 92 | + <view class="zp-paging-container-content" :style="[{transform:virtualPlaceholderTopHeight>0?`translateY(${virtualPlaceholderTopHeight}px)`:'none'},finalPagingContentStyle]"> | |
| 93 | + <slot /> | |
| 94 | + <!-- 内置列表&虚拟列表 --> | |
| 95 | + <template v-if="finalUseInnerList"> | |
| 96 | + <slot name="header"/> | |
| 97 | + <view class="zp-list-container" :style="[innerListStyle]"> | |
| 98 | + <template v-if="finalUseVirtualList"> | |
| 99 | + <view class="zp-list-cell" :style="[innerCellStyle]" :id="`zp-id-${item[virtualCellIndexKey]}`" v-for="(item,index) in virtualList" :key="item['zp_unique_index']" @click="_innerCellClick(item,virtualTopRangeIndex+index)"> | |
| 100 | + <view v-if="useCompatibilityMode">使用兼容模式请在组件源码z-paging.vue第100行中注释这一行,并打开下面一行注释</view> | |
| 101 | + <!-- <zp-public-virtual-cell v-if="useCompatibilityMode" :extraData="extraData" :item="item" :index="virtualTopRangeIndex+index" /> --> | |
| 102 | + <slot v-else name="cell" :item="item" :index="virtualTopRangeIndex+index"/> | |
| 103 | + </view> | |
| 104 | + </template> | |
| 105 | + <template v-else> | |
| 106 | + <view class="zp-list-cell" v-for="(item,index) in realTotalData" :key="index" @click="_innerCellClick(item,index)"> | |
| 107 | + <slot name="cell" :item="item" :index="index"/> | |
| 108 | + </view> | |
| 109 | + </template> | |
| 110 | + </view> | |
| 111 | + <slot name="footer"/> | |
| 112 | + </template> | |
| 113 | + <view v-if="useVirtualList" class="zp-virtual-placeholder" :style="[{height:virtualPlaceholderBottomHeight+'px'}]"/> | |
| 114 | + <!-- 上拉加载更多view --> | |
| 115 | + <!-- #ifndef MP-ALIPAY --> | |
| 116 | + <slot v-if="showLoadingMoreDefault" name="loadingMoreDefault" /> | |
| 117 | + <slot v-else-if="showLoadingMoreLoading" name="loadingMoreLoading" /> | |
| 118 | + <slot v-else-if="showLoadingMoreNoMore" name="loadingMoreNoMore" /> | |
| 119 | + <slot v-else-if="showLoadingMoreFail" name="loadingMoreFail" /> | |
| 120 | + <z-paging-load-more @doClick="_onLoadingMore('click')" v-else-if="showLoadingMoreCustom" :zConfig="zLoadMoreConfig" /> | |
| 121 | + <!-- #endif --> | |
| 122 | + <!-- #ifdef MP-ALIPAY --> | |
| 123 | + <slot v-if="loadingStatus===M.Default&&zSlots.loadingMoreDefault&&showLoadingMore&&loadingMoreEnabled&&!useChatRecordMode" name="loadingMoreDefault" /> | |
| 124 | + <slot v-else-if="loadingStatus===M.Loading&&zSlots.loadingMoreLoading&&showLoadingMore&&loadingMoreEnabled" name="loadingMoreLoading" /> | |
| 125 | + <slot v-else-if="loadingStatus===M.NoMore&&zSlots.loadingMoreNoMore&&showLoadingMore&&showLoadingMoreNoMoreView&&loadingMoreEnabled&&!useChatRecordMode" name="loadingMoreNoMore" /> | |
| 126 | + <slot v-else-if="loadingStatus===M.Fail&&zSlots.loadingMoreFail&&showLoadingMore&&loadingMoreEnabled&&!useChatRecordMode" name="loadingMoreFail" /> | |
| 127 | + <z-paging-load-more @doClick="_onLoadingMore('click')" v-else-if="showLoadingMore&&showDefaultLoadingMoreText&&!(loadingStatus===M.NoMore&&!showLoadingMoreNoMoreView)&&loadingMoreEnabled&&!useChatRecordMode" :zConfig="zLoadMoreConfig" /> | |
| 128 | + <!-- #endif --> | |
| 129 | + <view v-if="safeAreaInsetBottom&&useSafeAreaPlaceholder" class="zp-safe-area-placeholder" :style="[{height:safeAreaBottom+'px'}]" /> | |
| 130 | + </view> | |
| 131 | + <!-- 空数据图 --> | |
| 132 | + <view v-if="showEmpty" :class="{'zp-empty-view':true,'zp-empty-view-center':emptyViewCenter}" :style="[emptyViewSuperStyle]"> | |
| 133 | + <slot v-if="zSlots.empty" name="empty" :isLoadFailed="isLoadFailed"/> | |
| 134 | + <z-paging-empty-view v-else :emptyViewImg="finalEmptyViewImg" :emptyViewText="finalEmptyViewText" :showEmptyViewReload="finalShowEmptyViewReload" | |
| 135 | + :emptyViewReloadText="finalEmptyViewReloadText" :isLoadFailed="isLoadFailed" :emptyViewStyle="emptyViewStyle" :emptyViewTitleStyle="emptyViewTitleStyle" | |
| 136 | + :emptyViewImgStyle="emptyViewImgStyle" :emptyViewReloadStyle="emptyViewReloadStyle" :emptyViewZIndex="emptyViewZIndex" :emptyViewFixed="emptyViewFixed" | |
| 137 | + @reload="_emptyViewReload" @viewClick="_emptyViewClick" /> | |
| 138 | + </view> | |
| 139 | + </view> | |
| 140 | + </view> | |
| 141 | + </view> | |
| 142 | + </scroll-view> | |
| 143 | + </view> | |
| 144 | + <view v-if="zSlots.right" :class="{'zp-page-right':true,'zp-absoulte zp-right':finalIsOldWebView}"> | |
| 145 | + <slot name="right" /> | |
| 146 | + </view> | |
| 147 | + </view> | |
| 148 | + <!-- 底部固定的slot --> | |
| 149 | + <slot v-if="!usePageScroll&&zSlots.bottom" name="bottom" /> | |
| 150 | + <view class="zp-page-bottom" @touchmove.stop.prevent v-else-if="usePageScroll&&zSlots.bottom" :style="[{'bottom': `${windowBottom}px`}]"> | |
| 151 | + <slot name="bottom" /> | |
| 152 | + </view> | |
| 153 | + <!-- 点击返回顶部view --> | |
| 154 | + <view v-if="showBackToTopClass" :class="backToTopClass" :style="[finalBackToTopStyle]" @click.stop="_backToTopClick"> | |
| 155 | + <slot v-if="zSlots.backToTop" name="backToTop" /> | |
| 156 | + <image v-else class="zp-back-to-top-img" :src="backToTopImg.length?backToTopImg:base64BackToTop" /> | |
| 157 | + </view> | |
| 158 | + <!-- 全屏Loading(铺满z-paging并固定) --> | |
| 159 | + <view v-if="showLoading&&zSlots.loading&&loadingFullFixed" class="zp-loading-fixed"> | |
| 160 | + <slot name="loading" /> | |
| 161 | + </view> | |
| 162 | + </view> | |
| 163 | + <!-- #endif --> | |
| 164 | + <!-- #ifdef APP-NVUE --> | |
| 165 | + <component :is="finalNvueSuperListIs" :style="[finalPagingStyle]" :class="{'z-paging-content-fixed':fixed&&!usePageScroll}" :scrollable="false"> | |
| 166 | + <!-- 顶部固定的slot --> | |
| 167 | + <view ref="zp-page-top" v-if="zSlots.top" :class="{'zp-page-top':usePageScroll}" :style="[usePageScroll?{'top':`${windowTop}px`,'z-index':topZIndex}:{}]"> | |
| 168 | + <slot name="top" /> | |
| 169 | + </view> | |
| 170 | + <component :is="finalNvueSuperListIs" class="zp-n-list-container" :scrollable="false"> | |
| 171 | + <view v-if="zSlots.left" class="zp-page-left"> | |
| 172 | + <slot name="left" /> | |
| 173 | + </view> | |
| 174 | + <component :is="finalNvueListIs" ref="zp-n-list" :id="nvueListId" :style="[{'flex': 1,'top':isIos?'0px':'-1px'},usePageScroll?scrollViewStyle:{},nChatRecordRotateStyle]" :alwaysScrollableVertical="true" | |
| 175 | + :fixFreezing="nFixFreezing" :show-scrollbar="showScrollbar&&!useChatRecordMode" :loadmoreoffset="finalLowerThreshold" :enable-back-to-top="enableBackToTop" | |
| 176 | + :scrollable="scrollable&&scrollEnable&&(refresherCompleteScrollable?true:refresherStatus!==R.Complete)" :bounce="nvueBounce" :column-count="nWaterfallColumnCount" :column-width="nWaterfallColumnWidth" | |
| 177 | + :column-gap="nWaterfallColumnGap" :left-gap="nWaterfallLeftGap" :right-gap="nWaterfallRightGap" :pagingEnabled="nvuePagingEnabled" :offset-accuracy="offsetAccuracy" | |
| 178 | + @loadmore="_nOnLoadmore" @scroll="_nOnScroll"> | |
| 179 | + <refresh v-if="(zSlots.top?cacheTopHeight!==-1:true)&&finalNvueRefresherEnabled" class="zp-n-refresh" :style="[nvueRefresherStyle]" :display="nRefresherLoading?'show':'hide'" @refresh="_nOnRrefresh" @pullingdown="_nOnPullingdown"> | |
| 180 | + <view ref="zp-n-refresh-container" class="zp-n-refresh-container" :style="[{background:refresherBackground,width:nRefresherWidth}]" id="zp-n-refresh-container"> | |
| 181 | + <view v-if="useRefresherStatusBarPlaceholder" class="zp-custom-refresher-status-bar-placeholder" :style="[{'height': `${statusBarHeight}px`}]" /> | |
| 182 | + <!-- 下拉刷新view --> | |
| 183 | + <slot v-if="zSlots.refresherComplete&&refresherStatus===R.Complete" name="refresherComplete" /> | |
| 184 | + <slot v-else-if="(nScopedSlots?nScopedSlots:zSlots).refresher" :refresherStatus="refresherStatus" name="refresher" /> | |
| 185 | + <z-paging-refresh ref="refresh" v-else :status="refresherStatus" :defaultThemeStyle="finalRefresherThemeStyle" | |
| 186 | + :defaultText="finalRefresherDefaultText" :pullingText="finalRefresherPullingText" :refreshingText="finalRefresherRefreshingText" :completeText="finalRefresherCompleteText" | |
| 187 | + :defaultImg="refresherDefaultImg" :pullingImg="refresherPullingImg" :refreshingImg="refresherRefreshingImg" :completeImg="refresherCompleteImg" :refreshingAnimated="refresherRefreshingAnimated" | |
| 188 | + :showUpdateTime="showRefresherUpdateTime" :updateTimeKey="refresherUpdateTimeKey" :updateTimeTextMap="finalRefresherUpdateTimeTextMap" | |
| 189 | + :imgStyle="refresherImgStyle" :titleStyle="refresherTitleStyle" :updateTimeStyle="refresherUpdateTimeStyle" /> | |
| 190 | + </view> | |
| 191 | + </refresh> | |
| 192 | + <component :is="nViewIs" v-if="isIos&&!useChatRecordMode?oldScrollTop>10:true" ref="zp-n-list-top-tag" class="zp-n-list-top-tag" style="margin-top: -1rpx;" :style="[{height:finalNvueRefresherEnabled?'0px':'1px'}]"></component> | |
| 193 | + <component :is="nViewIs" v-if="nShowRefresherReveal" ref="zp-n-list-refresher-reveal" :style="[{transform:`translateY(-${nShowRefresherRevealHeight}px)`},{background:refresherBackground}]"> | |
| 194 | + <view v-if="useRefresherStatusBarPlaceholder" class="zp-custom-refresher-status-bar-placeholder" :style="[{'height': `${statusBarHeight}px`}]" /> | |
| 195 | + <!-- 下拉刷新view --> | |
| 196 | + <slot v-if="zSlots.refresherComplete&&refresherStatus===R.Complete" name="refresherComplete" /> | |
| 197 | + <slot v-else-if="(nScopedSlots?nScopedSlots:$slots).refresher" :refresherStatus="R.Loading" name="refresher" /> | |
| 198 | + <z-paging-refresh ref="refresh" v-else :status="R.Loading" :defaultThemeStyle="finalRefresherThemeStyle" | |
| 199 | + :defaultText="finalRefresherDefaultText" :pullingText="finalRefresherPullingText" :refreshingText="finalRefresherRefreshingText" :completeText="finalRefresherCompleteText" | |
| 200 | + :defaultImg="refresherDefaultImg" :pullingImg="refresherPullingImg" :refreshingImg="refresherRefreshingImg" :completeImg="refresherCompleteImg" :refreshingAnimated="refresherRefreshingAnimated" | |
| 201 | + :showUpdateTime="showRefresherUpdateTime" :updateTimeKey="refresherUpdateTimeKey" :updateTimeTextMap="finalRefresherUpdateTimeTextMap" | |
| 202 | + :imgStyle="refresherImgStyle" :titleStyle="refresherTitleStyle" :updateTimeStyle="refresherUpdateTimeStyle" /> | |
| 203 | + </component> | |
| 204 | + <template v-if="finalUseInnerList"> | |
| 205 | + <component :is="nViewIs"> | |
| 206 | + <slot name="header"/> | |
| 207 | + </component> | |
| 208 | + <component :is="nViewIs" class="zp-list-cell" v-for="(item,index) in realTotalData" :key="finalCellKeyName.length?item[finalCellKeyName]:index"> | |
| 209 | + <slot name="cell" :item="item" :index="index"/> | |
| 210 | + </component> | |
| 211 | + <component :is="nViewIs"> | |
| 212 | + <slot name="footer"/> | |
| 213 | + </component> | |
| 214 | + </template> | |
| 215 | + <template v-else> | |
| 216 | + <slot /> | |
| 217 | + </template> | |
| 218 | + <!-- 全屏Loading --> | |
| 219 | + <component :is="nViewIs" v-if="showLoading&&zSlots.loading&&!loadingFullFixed" :class="{'z-paging-content-fixed':usePageScroll}" style="flex:1" :style="[nChatRecordRotateStyle]"> | |
| 220 | + <slot name="loading" /> | |
| 221 | + </component> | |
| 222 | + <!-- 上拉加载更多view --> | |
| 223 | + <component :is="nViewIs" v-if="!refresherOnly&&loadingMoreEnabled&&!showEmpty"> | |
| 224 | + <view v-if="useChatRecordMode"> | |
| 225 | + <view v-if="loadingStatus!==M.NoMore&&realTotalData.length"> | |
| 226 | + <slot v-if="zSlots.chatLoading" name="chatLoading" /> | |
| 227 | + <view v-else class="zp-chat-record-loading-container"> | |
| 228 | + <text v-if="loadingStatus!==M.Loading" @click="_onScrollToUpper" | |
| 229 | + :class="defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{chatRecordLoadingMoreText}}</text> | |
| 230 | + <view> | |
| 231 | + <loading-indicator v-if="loadingStatus===M.Loading" class="zp-line-loading-image" animating /> | |
| 232 | + </view> | |
| 233 | + </view> | |
| 234 | + </view> | |
| 235 | + </view> | |
| 236 | + <view :style="nLoadingMoreFixedHeight?{height:loadingMoreCustomStyle&&loadingMoreCustomStyle.height?loadingMoreCustomStyle.height:'80rpx'}:{}"> | |
| 237 | + <slot v-if="showLoadingMoreDefault" name="loadingMoreDefault" /> | |
| 238 | + <slot v-else-if="showLoadingMoreLoading" name="loadingMoreLoading" /> | |
| 239 | + <slot v-else-if="showLoadingMoreNoMore" name="loadingMoreNoMore" /> | |
| 240 | + <slot v-else-if="showLoadingMoreFail" name="loadingMoreFail" /> | |
| 241 | + <z-paging-load-more @doClick="_onLoadingMore('click')" v-else-if="showLoadingMoreCustom" :zConfig="zLoadMoreConfig" /> | |
| 242 | + <view v-if="safeAreaInsetBottom&&useSafeAreaPlaceholder" class="zp-safe-area-placeholder" :style="[{height:safeAreaBottom+'px'}]" /> | |
| 243 | + </view> | |
| 244 | + </component> | |
| 245 | + <!-- 空数据图 --> | |
| 246 | + <component :is="nViewIs" v-if="showEmpty" :class="{'z-paging-content-fixed':usePageScroll}" :style="[{flex:emptyViewCenter?1:0},emptyViewSuperStyle,nChatRecordRotateStyle]"> | |
| 247 | + <view :class="{'zp-empty-view':true,'zp-empty-view-center':emptyViewCenter}"> | |
| 248 | + <slot v-if="zSlots.empty" name="empty" :isLoadFailed="isLoadFailed" /> | |
| 249 | + <z-paging-empty-view v-else :emptyViewImg="finalEmptyViewImg" :emptyViewText="finalEmptyViewText" :showEmptyViewReload="finalShowEmptyViewReload" | |
| 250 | + :emptyViewReloadText="finalEmptyViewReloadText" :isLoadFailed="isLoadFailed" :emptyViewStyle="emptyViewStyle" :emptyViewTitleStyle="emptyViewTitleStyle" | |
| 251 | + :emptyViewImgStyle="emptyViewImgStyle" :emptyViewReloadStyle="emptyViewReloadStyle" :emptyViewZIndex="emptyViewZIndex" :emptyViewFixed="emptyViewFixed" | |
| 252 | + @reload="_emptyViewReload" @viewClick="_emptyViewClick" /> | |
| 253 | + </view> | |
| 254 | + </component> | |
| 255 | + <component is="header" v-if="!hideNvueBottomTag" ref="zp-n-list-bottom-tag" class="zp-n-list-bottom-tag"></component> | |
| 256 | + </component> | |
| 257 | + <view v-if="zSlots.right" class="zp-page-right"> | |
| 258 | + <slot name="right" /> | |
| 259 | + </view> | |
| 260 | + </component> | |
| 261 | + <!-- 底部固定的slot --> | |
| 262 | + <slot name="bottom" /> | |
| 263 | + <!-- 点击返回顶部view --> | |
| 264 | + <view v-if="showBackToTopClass" :class="backToTopClass" :style="[finalBackToTopStyle]" @click.stop="_backToTopClick"> | |
| 265 | + <slot v-if="zSlots.backToTop" name="backToTop" /> | |
| 266 | + <image v-else class="zp-back-to-top-img" :src="backToTopImg.length?backToTopImg:base64BackToTop" /> | |
| 267 | + </view> | |
| 268 | + <!-- 全屏Loading(铺满z-paging并固定) --> | |
| 269 | + <view v-if="showLoading&&zSlots.loading&&loadingFullFixed" class="zp-loading-fixed"> | |
| 270 | + <slot name="loading" /> | |
| 271 | + </view> | |
| 272 | + </component> | |
| 273 | + <!-- #endif --> | |
| 274 | +</template> | |
| 275 | +<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 --> | |
| 276 | +<script src="./wxs/z-paging-wxs.wxs" module="pagingWxs" lang="wxs"></script> | |
| 277 | +<!-- #endif --> | |
| 278 | +<script module="pagingRenderjs" lang="renderjs"> | |
| 279 | + import pagingRenderjs from './wxs/z-paging-renderjs.js'; | |
| 280 | + /** | |
| 281 | + * z-paging 分页组件 | |
| 282 | + * @description 高性能,全平台兼容。支持虚拟列表,支持nvue、vue3 | |
| 283 | + * @tutorial https://z-paging.zxlee.cn | |
| 284 | + * @notice 以下仅为部分常用属性、方法和事件,完整文档请查阅z-paging官网 | |
| 285 | + * @property {Number|String} default-page-no 自定义初始的pageNo,默认为1 | |
| 286 | + * @property {Number|String} default-page-size 自定义pageSize,默认为10 | |
| 287 | + * @property {Object} paging-style 设置z-paging的style,部分平台(如微信小程序)无法直接修改组件的style,可使用此属性代替 | |
| 288 | + * @property {String} height z-paging的高度,优先级低于pagingStyle中设置的height,传字符串,如100px、100rpx、100% | |
| 289 | + * @property {String} width z-paging的宽度,优先级低于pagingStyle中设置的width,传字符串,如100px、100rpx、100% | |
| 290 | + * @property {Boolean} use-page-scroll 使用页面滚动,默认为否 | |
| 291 | + * @property {Boolean} use-virtual-list 是否使用虚拟列表,默认为否 | |
| 292 | + * @property {Boolean} fixed z-paging是否使用fixed布局,若使用fixed布局,则z-paging的父view无需固定高度,z-paging高度默认为100%,默认为是(当使用内置scroll-view滚动时有效) | |
| 293 | + * @property {Boolean} auto [z-paging]mounted后是否自动调用reload方法(mounted后自动调用接口),默认为是 | |
| 294 | + * @property {Boolean} use-chat-record-mode 使用聊天记录模式,默认为否 | |
| 295 | + * @event {Function} query 下拉刷新或滚动到底部时会自动触发此方法。z-paging加载时也会触发(若要禁止,请设置:auto="false")。pageNo和pageSize会自动计算好,直接传给服务器即可。 | |
| 296 | + * @example <z-paging ref="paging" v-model="dataList" @query="queryList"></z-paging> | |
| 297 | + */ | |
| 298 | + export default { | |
| 299 | + name:"z-paging", | |
| 300 | + // #ifdef APP-VUE || H5 | |
| 301 | + mixins: [pagingRenderjs], | |
| 302 | + // #endif | |
| 303 | + } | |
| 304 | +</script> | |
| 305 | +<script src="./js/z-paging-main.js" /> | |
| 306 | + | |
| 307 | +<style scoped> | |
| 308 | + @import "./css/z-paging-main.css"; | |
| 309 | + @import "./css/z-paging-static.css"; | |
| 310 | +</style> | ... | ... |
garbage-removal/src/pages.json
| ... | ... | @@ -51,7 +51,9 @@ |
| 51 | 51 | },{ |
| 52 | 52 | "path": "pages/order/index", |
| 53 | 53 | "style": { |
| 54 | - "navigationBarTitleText": "" | |
| 54 | + "navigationBarTitleText": "订单详情", | |
| 55 | + "navigationBarTextStyle":"white", | |
| 56 | + "navigationBarBackgroundColor":"#53c21d" | |
| 55 | 57 | } |
| 56 | 58 | },{ |
| 57 | 59 | "path": "pages/wode/index", | ... | ... |
garbage-removal/src/pages/home/address/addSite.vue
| ... | ... | @@ -28,7 +28,7 @@ |
| 28 | 28 | <view class="set">设置默认地址</view> |
| 29 | 29 | </view> |
| 30 | 30 | <view class="right"> |
| 31 | - <u-switch v-model="addressInfo.defaultFlag" size="40" activeColor="green"></u-switch> | |
| 31 | + <u-switch v-model="addressInfo.defaultFlag" size="40" activeColor="#a9e08f"></u-switch> | |
| 32 | 32 | </view> |
| 33 | 33 | </view> |
| 34 | 34 | </view> |
| ... | ... | @@ -154,7 +154,7 @@ onMounted(() => { |
| 154 | 154 | position: absolute; |
| 155 | 155 | bottom: 30rpx; |
| 156 | 156 | left: 80rpx; |
| 157 | - background-color: green; | |
| 157 | + background-color: #a9e08f; | |
| 158 | 158 | border-radius: 60rpx; |
| 159 | 159 | font-size: 30rpx; |
| 160 | 160 | ... | ... |
garbage-removal/src/pages/home/address/index.vue
| ... | ... | @@ -150,7 +150,7 @@ onLoad(() => { |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | 152 | .red { |
| 153 | - background-color: green | |
| 153 | + background-color: #a9e08f | |
| 154 | 154 | } |
| 155 | 155 | } |
| 156 | 156 | } |
| ... | ... | @@ -176,7 +176,7 @@ onLoad(() => { |
| 176 | 176 | line-height: 100rpx; |
| 177 | 177 | position: absolute; |
| 178 | 178 | bottom: 30rpx; |
| 179 | - background-color: green; | |
| 179 | + background-color: #a9e08f; | |
| 180 | 180 | border-radius: 60rpx; |
| 181 | 181 | font-size: 30rpx; |
| 182 | 182 | ... | ... |
garbage-removal/src/pages/home/clean/company-detail/index.vue
| ... | ... | @@ -33,7 +33,7 @@ |
| 33 | 33 | <view class="company-content-car-info-title">核准车辆信息</view> |
| 34 | 34 | <view class="company-content-car-info-sub-title">车牌号(车型)</view> |
| 35 | 35 | <view class="company-content-car-info-car-list"> |
| 36 | - <view v-for="item in baseDataList" class="company-content-car-info-car-list-item"> | |
| 36 | + <view v-for="(item, index) in baseDataList" :key="index" class="company-content-car-info-car-list-item"> | |
| 37 | 37 | 浙B5S785<text class="car-type">(自卸车)</text> |
| 38 | 38 | </view> |
| 39 | 39 | </view> |
| ... | ... | @@ -74,7 +74,7 @@ |
| 74 | 74 | </view> |
| 75 | 75 | </view> |
| 76 | 76 | <view class="company-bottom-button-right"> |
| 77 | - <u-button icon="car-fill" :custom-style="customStyle" @click="handleCleanGarbage(companyId)" type="success" | |
| 77 | + <u-button icon="car-fill" :custom-style="customStyle" @click="handleCleanGarbage(companyId, tel)" type="success" | |
| 78 | 78 | :hairline="true" size="normal" shape="circle" text="垃圾清运"></u-button> |
| 79 | 79 | </view> |
| 80 | 80 | </view> |
| ... | ... | @@ -99,10 +99,10 @@ const customStyle = ref({ |
| 99 | 99 | }) |
| 100 | 100 | const companyId = ref() |
| 101 | 101 | const tel = ref() |
| 102 | -const handleCleanGarbage = (companyId) => { | |
| 102 | +const handleCleanGarbage = (companyId, tel) => { | |
| 103 | 103 | console.log("垃圾清运"); |
| 104 | 104 | uni.$u.route({ |
| 105 | - url: `pages/home/clean/index?companyId=${companyId}`, | |
| 105 | + url: `pages/home/clean/index?companyId=${companyId}&tel=${tel}`, | |
| 106 | 106 | }) |
| 107 | 107 | } |
| 108 | 108 | ... | ... |
garbage-removal/src/pages/home/clean/index.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="company-clean-container"> |
| 3 | - <view class="company-clean-container-header"> | |
| 4 | - <view class="company-clean-container-header-address"> | |
| 5 | - 宁波市海曙区昱湖街道上海 | |
| 6 | - </view> | |
| 7 | - <view class="company-clean-container-header-base-info"> | |
| 8 | - 李云龙 189802245165 | |
| 9 | - </view> | |
| 10 | - <view class="company-clean-container-header-reservation"> | |
| 11 | - <view class="company-clean-container-header-reservation-left"> | |
| 12 | - <u-icon name="calendar" size="40"></u-icon> | |
| 13 | - 预约时间 | |
| 3 | + <view class="company-clean-container-box"> | |
| 4 | + <view class="company-clean-container-header"> | |
| 5 | + <view class="company-clean-container-header-address"> | |
| 6 | + 宁波市海曙区昱湖街道上海 | |
| 14 | 7 | </view> |
| 15 | - <view class="company-clean-container-header-reservation-right" @click="handleTimeChoose"> | |
| 16 | - <text style="margin-right: 10rpx;">请选择时间</text> <u-icon name="arrow-right" size="25"></u-icon> | |
| 8 | + <view class="company-clean-container-header-base-info"> | |
| 9 | + 李云龙 189802245165 | |
| 10 | + </view> | |
| 11 | + <view class="company-clean-container-header-reservation"> | |
| 12 | + <view class="company-clean-container-header-reservation-left"> | |
| 13 | + <u-icon name="calendar" size="40"></u-icon> | |
| 14 | + 预约时间 | |
| 15 | + </view> | |
| 16 | + <view class="company-clean-container-header-reservation-right" @click="handleTimeChoose"> | |
| 17 | + <text style="margin-right: 10rpx;">请选择时间</text> <u-icon name="arrow-right" size="25"></u-icon> | |
| 18 | + </view> | |
| 17 | 19 | </view> |
| 18 | - </view> | |
| 19 | 20 | |
| 20 | - </view> | |
| 21 | - <view class="company-clean-container-car-main"> | |
| 22 | - <view class="company-clean-container-car-main-title"> | |
| 23 | - 自卸车 | |
| 24 | 21 | </view> |
| 25 | - <view class="company-clean-container-car-main-content"> | |
| 26 | - <view class="company-clean-container-car-main-content-img"> | |
| 27 | - <image class="company-clean-container-car-main-content-img" /> | |
| 28 | - </view> | |
| 29 | - <view class="company-clean-container-car-main-content-remark"> | |
| 30 | - 箱体长4.2m宽1.1,高0.7,最多课容纳约110袋袋装修垃圾(75cm*45每袋) | |
| 22 | + <view class="company-clean-container-car-main"> | |
| 23 | + <view class="company-clean-container-car-main-title"> | |
| 24 | + 自卸车 | |
| 31 | 25 | </view> |
| 32 | - <view class="company-clean-container-car-main-content-type"> | |
| 33 | - <view class="company-clean-container-car-main-content-type-choose"> | |
| 34 | - <text style="margin-right: 10rpx;">6方车</text> | |
| 35 | - <u-icon name="arrow-down" size="30" color="#ffffff"></u-icon> | |
| 26 | + <view class="company-clean-container-car-main-content"> | |
| 27 | + <view class="company-clean-container-car-main-content-img"> | |
| 28 | + <image class="company-clean-container-car-main-content-img" /> | |
| 36 | 29 | </view> |
| 37 | - <view class="company-clean-container-car-main-content-type-price-area"> | |
| 38 | - $5000元/车 | |
| 30 | + <view class="company-clean-container-car-main-content-remark"> | |
| 31 | + 箱体长4.2m宽1.1,高0.7,最多课容纳约110袋袋装修垃圾(75cm*45每袋) | |
| 39 | 32 | </view> |
| 40 | - </view> | |
| 41 | - <view class="company-clean-container-car-main-content-number"> | |
| 42 | - <view class="company-clean-container-car-main-content-number-txt"> | |
| 43 | - 添加车辆数量 | |
| 33 | + <view class="company-clean-container-car-main-content-type"> | |
| 34 | + <view class="company-clean-container-car-main-content-type-choose"> | |
| 35 | + <text style="margin-right: 10rpx;">6方车</text> | |
| 36 | + <u-icon name="arrow-down" size="30" color="#ffffff"></u-icon> | |
| 37 | + </view> | |
| 38 | + <view class="company-clean-container-car-main-content-type-price-area"> | |
| 39 | + $5000元/车 | |
| 40 | + </view> | |
| 44 | 41 | </view> |
| 45 | - <view class="company-clean-container-car-main-content-number-button"> | |
| 46 | - <u-number-box :min="1" integer buttonSize="46" v-model="paramFrom.carNumber"></u-number-box> | |
| 42 | + <view class="company-clean-container-car-main-content-number"> | |
| 43 | + <view class="company-clean-container-car-main-content-number-txt"> | |
| 44 | + 添加车辆数量 | |
| 45 | + </view> | |
| 46 | + <view class="company-clean-container-car-main-content-number-button"> | |
| 47 | + <u-number-box :min="1" integer buttonSize="46" v-model="paramFrom.carNumber"></u-number-box> | |
| 48 | + </view> | |
| 49 | + </view> | |
| 50 | + <view class="company-clean-container-car-main-content-prompt"> | |
| 51 | + 温馨提示:垃圾类型不符合,有权拒绝清运。 | |
| 47 | 52 | </view> |
| 48 | - </view> | |
| 49 | - <view class="company-clean-container-car-main-content-prompt"> | |
| 50 | - 温馨提示:垃圾类型不符合,有权拒绝清运。 | |
| 51 | 53 | </view> |
| 52 | 54 | </view> |
| 53 | - </view> | |
| 54 | 55 | |
| 55 | - <view class="company-clean-container-site-image-info"> | |
| 56 | - <view class="company-clean-container-site-image-info-remark"> | |
| 57 | - <text style="color: red;">*</text>现场照片(最多上传10张) | |
| 58 | - </view> | |
| 59 | - <view class="company-clean-container-site-image-info-img"> | |
| 60 | - <u-upload :fileList="fileList" @afterRead="afterRead" @delete="deletePic" name="3" multiple :maxCount="10" | |
| 61 | - :previewFullImage="true"></u-upload> | |
| 62 | - </view> | |
| 63 | - <view class="company-clean-container-site-image-info-input-remark"> | |
| 64 | - 填写备注 | |
| 56 | + <view class="company-clean-container-site-image-info"> | |
| 57 | + <view class="company-clean-container-site-image-info-remark"> | |
| 58 | + <text style="color: red;">*</text>现场照片(最多上传10张) | |
| 59 | + </view> | |
| 60 | + <view class="company-clean-container-site-image-info-img"> | |
| 61 | + <u-upload :fileList="fileList" @afterRead="afterRead" @delete="deletePic" name="3" multiple :maxCount="10" | |
| 62 | + :previewFullImage="true"></u-upload> | |
| 63 | + </view> | |
| 64 | + <view class="company-clean-container-site-image-info-input-remark"> | |
| 65 | + 填写备注 | |
| 66 | + </view> | |
| 67 | + <view class="company-clean-container-site-image-info-input-remark-box"> | |
| 68 | + <u--textarea v-model="paramFrom.remark" placeholder="请输入内容"></u--textarea> | |
| 69 | + </view> | |
| 65 | 70 | </view> |
| 66 | - <view class="company-clean-container-site-image-info-input-remark-box"> | |
| 67 | - <u--textarea v-model="paramFrom.remark" placeholder="请输入内容"></u--textarea> | |
| 71 | + <view class="company-clean-container-site-image-info-sure-button"> | |
| 72 | + <view class="company-clean-container-site-image-info-sure-button-radio"> | |
| 73 | + <u-radio-group v-model="paramFrom.sureReadFlag"> | |
| 74 | + <u-radio activeColor="#a9e08f" size="27" labelSize="25" :labelDisabled="true" labelColor="#909399" | |
| 75 | + label="本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。"></u-radio> | |
| 76 | + </u-radio-group> | |
| 77 | + </view> | |
| 68 | 78 | </view> |
| 69 | 79 | </view> |
| 70 | - <view class="company-clean-container-site-image-info-sure-button"> | |
| 71 | - <u-radio-group v-model="paramFrom.sureReadFlag"> | |
| 72 | - <u-radio :labelDisabled="true" label="本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。"></u-radio> | |
| 73 | - </u-radio-group> | |
| 80 | + <view class="company-clean-bottom"> | |
| 81 | + <movable-area ref="movableAreaElement" class="movableArea"> | |
| 82 | + <movable-view class="movableView" :x="x" :y="y" direction="all" @change="onChange"> | |
| 83 | + <view class="company-clean-call-box-container"> | |
| 84 | + <u-icon @click="handleContactClick(tel)" name="phone-fill" color="#ffffff" size="50"></u-icon> | |
| 85 | + </view> | |
| 86 | + </movable-view> | |
| 87 | + </movable-area> | |
| 88 | + <view class="company-clean-bottom-box"> | |
| 89 | + <view class="company-clean-bottom-left"> | |
| 90 | + <u-icon @click="handleCarInfo" :stop="true" size="50" name="car-fill"></u-icon> | |
| 91 | + </view> | |
| 92 | + <view class="company-clean-bottom-right"> | |
| 93 | + <u-button @click="handleOderSure" shape="circle" color="#a9e08f" text="立即下单"></u-button> | |
| 94 | + </view> | |
| 95 | + </view> | |
| 74 | 96 | </view> |
| 75 | 97 | </view> |
| 76 | 98 | </template> |
| 77 | 99 | |
| 78 | 100 | <script setup> |
| 79 | 101 | import { onLoad } from '@dcloudio/uni-app'; |
| 80 | -import { ref } from 'vue'; | |
| 102 | +import { getCurrentInstance, onMounted, ref } from 'vue'; | |
| 103 | +const { proxy } = getCurrentInstance(); | |
| 104 | +const x = ref(5) | |
| 105 | +const y = ref() | |
| 106 | +const movableAreaElement = ref() | |
| 81 | 107 | const companyId = ref() |
| 82 | - | |
| 108 | +const tel = ref() | |
| 83 | 109 | const paramFrom = ref({ |
| 84 | 110 | carNumber: 0, |
| 85 | 111 | remark: "", |
| ... | ... | @@ -93,11 +119,26 @@ const fileList = ref([{ |
| 93 | 119 | const handleTimeChoose = () => { |
| 94 | 120 | console.log("选择时间"); |
| 95 | 121 | } |
| 122 | +/** | |
| 123 | + * 初始化信息 | |
| 124 | + */ | |
| 96 | 125 | onLoad((options) => { |
| 97 | - console.log(options.companyId); | |
| 98 | 126 | companyId.value = options.companyId; |
| 127 | + tel.value = options.tel; | |
| 128 | + console.log("tel:", tel); | |
| 129 | + | |
| 99 | 130 | }) |
| 100 | 131 | |
| 132 | +/** | |
| 133 | + * 拨打电话回调 | |
| 134 | + */ | |
| 135 | +const handleContactClick = (val) => { | |
| 136 | + console.log("拨打电话"); | |
| 137 | + uni.makePhoneCall({ phoneNumber: val }).then(res => { | |
| 138 | + console.log(res); | |
| 139 | + }).catch(err => { }); | |
| 140 | +} | |
| 141 | + | |
| 101 | 142 | // 删除图片 |
| 102 | 143 | const deletePic = (event) => { |
| 103 | 144 | fileList.value.splice(event.index, 1); |
| ... | ... | @@ -146,6 +187,33 @@ const uploadFilePromise = (url) => { |
| 146 | 187 | }); |
| 147 | 188 | }; |
| 148 | 189 | |
| 190 | +/** | |
| 191 | + * 处理车子数量 | |
| 192 | + */ | |
| 193 | +const handleCarInfo = () => { | |
| 194 | + console.log("车子数量"); | |
| 195 | +} | |
| 196 | + | |
| 197 | +/** | |
| 198 | + * 处理下单 | |
| 199 | + */ | |
| 200 | +const handleOderSure = () => { | |
| 201 | + console.log("下单了"); | |
| 202 | +} | |
| 203 | + | |
| 204 | +onMounted(() => { | |
| 205 | + let areaHeight; | |
| 206 | + // select中的参数就如css选择器一样选择元素 | |
| 207 | + let movableArea = uni.createSelectorQuery().in(proxy).select(".movableArea"); | |
| 208 | + movableArea.boundingClientRect(function (data) { | |
| 209 | + // data - 包含元素的高度等信息 | |
| 210 | + console.log("area:", data.height) // 获取元素宽度 | |
| 211 | + areaHeight = data.height; | |
| 212 | + y.value = areaHeight; | |
| 213 | + }).exec(function (res) { | |
| 214 | + // 注意:exec方法必须执行,即便什么也不做,否则不会获取到任何数据 | |
| 215 | + }) | |
| 216 | +}) | |
| 149 | 217 | |
| 150 | 218 | </script> |
| 151 | 219 | |
| ... | ... | @@ -153,179 +221,257 @@ const uploadFilePromise = (url) => { |
| 153 | 221 | $custom-marin-bottom: 20rpx; |
| 154 | 222 | $custom-page-padding: 20rpx; |
| 155 | 223 | $custom-border-radio: 20rpx; |
| 224 | +$custom-bottom-height: 200rpx; | |
| 156 | 225 | |
| 157 | 226 | .company-clean-container { |
| 158 | 227 | height: 100%; |
| 159 | 228 | width: 100%; |
| 160 | 229 | background-color: $u-info-light; |
| 161 | - padding: $custom-page-padding; | |
| 162 | 230 | box-sizing: border-box; |
| 231 | + overflow-y: scroll; | |
| 163 | 232 | |
| 164 | - .company-clean-container-header { | |
| 233 | + | |
| 234 | + .company-clean-container-box { | |
| 235 | + height: 100%; | |
| 236 | + width: 100%; | |
| 165 | 237 | padding: $custom-page-padding; |
| 166 | 238 | box-sizing: border-box; |
| 167 | - background-color: #ffffff; | |
| 168 | - border-radius: $custom-border-radio; | |
| 169 | - margin-bottom: $custom-marin-bottom; | |
| 170 | - | |
| 171 | - .company-clean-container-header-address { | |
| 172 | - font-size: 30rpx; | |
| 173 | - font-weight: bold; | |
| 174 | - color: $u-main-color; | |
| 175 | - } | |
| 176 | 239 | |
| 177 | - .company-clean-container-header-base-info { | |
| 178 | - font-size: 25rpx; | |
| 179 | - color: $u-info; | |
| 180 | - line-height: 80rpx; | |
| 181 | - } | |
| 182 | - | |
| 183 | - .company-clean-container-header-reservation { | |
| 184 | - display: flex; | |
| 185 | - justify-content: space-between; | |
| 186 | - font-size: 25rpx; | |
| 240 | + .company-clean-container-header { | |
| 241 | + padding: $custom-page-padding; | |
| 242 | + box-sizing: border-box; | |
| 243 | + background-color: #ffffff; | |
| 244 | + border-radius: $custom-border-radio; | |
| 245 | + margin-bottom: $custom-marin-bottom; | |
| 187 | 246 | |
| 247 | + .company-clean-container-header-address { | |
| 248 | + font-size: 30rpx; | |
| 249 | + font-weight: bold; | |
| 250 | + color: $u-main-color; | |
| 251 | + } | |
| 188 | 252 | |
| 189 | - .company-clean-container-header-reservation-left { | |
| 190 | - display: flex; | |
| 191 | - align-items: center; | |
| 192 | - color: $u-content-color; | |
| 253 | + .company-clean-container-header-base-info { | |
| 254 | + font-size: 25rpx; | |
| 255 | + color: $u-info; | |
| 256 | + line-height: 80rpx; | |
| 193 | 257 | } |
| 194 | 258 | |
| 195 | - .company-clean-container-header-reservation-right { | |
| 259 | + .company-clean-container-header-reservation { | |
| 196 | 260 | display: flex; |
| 197 | - align-items: center; | |
| 198 | - color: $u-content-color; | |
| 199 | - } | |
| 200 | - } | |
| 261 | + justify-content: space-between; | |
| 262 | + font-size: 25rpx; | |
| 201 | 263 | |
| 202 | 264 | |
| 203 | - } | |
| 265 | + .company-clean-container-header-reservation-left { | |
| 266 | + display: flex; | |
| 267 | + align-items: center; | |
| 268 | + color: $u-content-color; | |
| 269 | + } | |
| 270 | + | |
| 271 | + .company-clean-container-header-reservation-right { | |
| 272 | + display: flex; | |
| 273 | + align-items: center; | |
| 274 | + color: $u-content-color; | |
| 275 | + } | |
| 276 | + } | |
| 204 | 277 | |
| 205 | - .company-clean-container-car-main { | |
| 206 | - padding: $custom-page-padding; | |
| 207 | - border-radius: $custom-border-radio; | |
| 208 | - box-sizing: border-box; | |
| 209 | - background-color: #ffffff; | |
| 210 | - margin-bottom: $custom-marin-bottom; | |
| 211 | 278 | |
| 212 | - .company-clean-container-car-main-title { | |
| 213 | - font-size: 30rpx; | |
| 214 | - font-weight: bold; | |
| 215 | - color: green; | |
| 216 | - display: flex; | |
| 217 | - justify-content: center; | |
| 218 | 279 | } |
| 219 | 280 | |
| 220 | - .company-clean-container-car-main-content { | |
| 221 | - width: 100%; | |
| 222 | - display: flex; | |
| 223 | - flex-direction: column; | |
| 224 | - justify-content: center; | |
| 281 | + .company-clean-container-car-main { | |
| 282 | + padding: $custom-page-padding; | |
| 283 | + border-radius: $custom-border-radio; | |
| 284 | + box-sizing: border-box; | |
| 285 | + background-color: #ffffff; | |
| 286 | + margin-bottom: $custom-marin-bottom; | |
| 287 | + | |
| 288 | + .company-clean-container-car-main-title { | |
| 289 | + font-size: 30rpx; | |
| 290 | + font-weight: bold; | |
| 291 | + color: #a9e08f; | |
| 292 | + display: flex; | |
| 293 | + justify-content: center; | |
| 294 | + } | |
| 225 | 295 | |
| 226 | - .company-clean-container-car-main-content-img { | |
| 227 | - width: 600rpx; | |
| 228 | - height: 400rpx; | |
| 296 | + .company-clean-container-car-main-content { | |
| 297 | + width: 100%; | |
| 298 | + display: flex; | |
| 299 | + flex-direction: column; | |
| 300 | + justify-content: center; | |
| 229 | 301 | |
| 230 | 302 | .company-clean-container-car-main-content-img { |
| 231 | 303 | width: 600rpx; |
| 232 | 304 | height: 400rpx; |
| 233 | - } | |
| 234 | - } | |
| 235 | 305 | |
| 236 | - .company-clean-container-car-main-content-remark { | |
| 237 | - color: $u-tips-color; | |
| 238 | - font-size: 23rpx; | |
| 239 | - line-height: 30rpx; | |
| 240 | - padding: $custom-page-padding; | |
| 241 | - background-color: $u-info-light; | |
| 242 | - word-break: break-all; | |
| 243 | - } | |
| 306 | + .company-clean-container-car-main-content-img { | |
| 307 | + width: 600rpx; | |
| 308 | + height: 400rpx; | |
| 309 | + } | |
| 310 | + } | |
| 244 | 311 | |
| 245 | - .company-clean-container-car-main-content-type { | |
| 246 | - margin-top: $custom-marin-bottom; | |
| 247 | - margin-bottom: $custom-marin-bottom; | |
| 248 | - display: flex; | |
| 249 | - justify-content: space-between; | |
| 250 | - border-radius: $custom-border-radio; | |
| 251 | - background-color: $u-info-light; | |
| 252 | - box-sizing: border-box; | |
| 253 | - font-size: 30rpx; | |
| 312 | + .company-clean-container-car-main-content-remark { | |
| 313 | + color: $u-tips-color; | |
| 314 | + font-size: 23rpx; | |
| 315 | + line-height: 30rpx; | |
| 316 | + padding: $custom-page-padding; | |
| 317 | + background-color: $u-info-light; | |
| 318 | + word-break: break-all; | |
| 319 | + } | |
| 254 | 320 | |
| 255 | - .company-clean-container-car-main-content-type-choose { | |
| 256 | - width: 230rpx; | |
| 257 | - color: #ffffff; | |
| 321 | + .company-clean-container-car-main-content-type { | |
| 322 | + margin-top: $custom-marin-bottom; | |
| 323 | + margin-bottom: $custom-marin-bottom; | |
| 258 | 324 | display: flex; |
| 259 | - justify-content: center; | |
| 260 | - align-items: center; | |
| 261 | - background-color: green; | |
| 262 | - padding: 30rpx $custom-page-padding 30rpx $custom-page-padding; | |
| 325 | + justify-content: space-between; | |
| 326 | + border-radius: $custom-border-radio; | |
| 327 | + background-color: $u-info-light; | |
| 263 | 328 | box-sizing: border-box; |
| 264 | - border-radius: $custom-border-radio 0 0 $custom-border-radio; | |
| 329 | + font-size: 30rpx; | |
| 330 | + | |
| 331 | + .company-clean-container-car-main-content-type-choose { | |
| 332 | + width: 230rpx; | |
| 333 | + color: #ffffff; | |
| 334 | + display: flex; | |
| 335 | + justify-content: center; | |
| 336 | + align-items: center; | |
| 337 | + background-color: #a9e08f; | |
| 338 | + padding: 30rpx $custom-page-padding 30rpx $custom-page-padding; | |
| 339 | + box-sizing: border-box; | |
| 340 | + border-radius: $custom-border-radio 0 0 $custom-border-radio; | |
| 341 | + } | |
| 342 | + | |
| 343 | + .company-clean-container-car-main-content-type-price-area { | |
| 344 | + width: 100%; | |
| 345 | + display: flex; | |
| 346 | + justify-content: flex-end; | |
| 347 | + align-items: center; | |
| 348 | + box-sizing: border-box; | |
| 349 | + color: $u-tips-color; | |
| 350 | + padding-right: $custom-page-padding; | |
| 351 | + } | |
| 265 | 352 | } |
| 266 | 353 | |
| 267 | - .company-clean-container-car-main-content-type-price-area { | |
| 268 | - width: 100%; | |
| 354 | + .company-clean-container-car-main-content-number { | |
| 269 | 355 | display: flex; |
| 270 | - justify-content: flex-end; | |
| 271 | - align-items: center; | |
| 272 | - box-sizing: border-box; | |
| 356 | + justify-content: space-between; | |
| 357 | + font-size: 28rpx; | |
| 273 | 358 | color: $u-tips-color; |
| 274 | - padding-right: $custom-page-padding; | |
| 359 | + font-weight: small; | |
| 360 | + align-items: center; | |
| 361 | + | |
| 362 | + .company-clean-container-car-main-content-number-txt { | |
| 363 | + line-height: 80rpx; | |
| 364 | + } | |
| 365 | + | |
| 366 | + .company-clean-container-car-main-content-number-button {} | |
| 275 | 367 | } |
| 276 | 368 | } |
| 277 | 369 | |
| 278 | - .company-clean-container-car-main-content-number { | |
| 279 | - display: flex; | |
| 280 | - justify-content: space-between; | |
| 281 | - font-size: 28rpx; | |
| 282 | - color: $u-tips-color; | |
| 283 | - font-weight: small; | |
| 284 | - align-items: center; | |
| 285 | 370 | |
| 286 | - .company-clean-container-car-main-content-number-txt { | |
| 287 | - line-height: 80rpx; | |
| 288 | - } | |
| 371 | + } | |
| 372 | + | |
| 373 | + .company-clean-container-car-main-content-prompt { | |
| 374 | + color: $u-tips-color; | |
| 375 | + font-size: 23rpx; | |
| 376 | + line-height: 30rpx; | |
| 377 | + padding: $custom-page-padding; | |
| 378 | + word-break: break-all; | |
| 379 | + text-align: center; | |
| 380 | + } | |
| 381 | + | |
| 382 | + .company-clean-container-site-image-info { | |
| 383 | + padding: $custom-page-padding; | |
| 384 | + background-color: #ffffff; | |
| 385 | + border-radius: $custom-border-radio; | |
| 386 | + color: $u-info; | |
| 387 | + font-size: 28rpx; | |
| 388 | + margin-bottom: $custom-marin-bottom; | |
| 289 | 389 | |
| 290 | - .company-clean-container-car-main-content-number-button {} | |
| 390 | + .company-clean-container-site-image-info-remark { | |
| 391 | + line-height: 80rpx; | |
| 392 | + | |
| 393 | + } | |
| 394 | + | |
| 395 | + .company-clean-container-site-image-info-img {} | |
| 396 | + | |
| 397 | + .company-clean-container-site-image-info-input-remark { | |
| 398 | + line-height: 80rpx; | |
| 291 | 399 | } |
| 400 | + | |
| 401 | + .company-clean-container-site-image-info-input-remark-box {} | |
| 292 | 402 | } |
| 293 | 403 | |
| 404 | + .company-clean-container-site-image-info-sure-button { | |
| 405 | + padding-bottom: $custom-bottom-height; | |
| 406 | + font-size: 28rpx; | |
| 407 | + | |
| 408 | + .company-clean-container-site-image-info-sure-button-radio { | |
| 409 | + padding: $custom-page-padding; | |
| 410 | + box-sizing: border-box; | |
| 411 | + display: flex; | |
| 412 | + flex-flow: row wrap; | |
| 413 | + } | |
| 414 | + } | |
| 294 | 415 | |
| 295 | - } | |
| 296 | 416 | |
| 297 | - .company-clean-container-car-main-content-prompt { | |
| 298 | - color: $u-tips-color; | |
| 299 | - font-size: 23rpx; | |
| 300 | - line-height: 30rpx; | |
| 301 | - padding: $custom-page-padding; | |
| 302 | - word-break: break-all; | |
| 303 | - text-align: center; | |
| 304 | 417 | } |
| 305 | 418 | |
| 306 | - .company-clean-container-site-image-info { | |
| 307 | - padding: $custom-page-padding; | |
| 308 | - background-color: #ffffff; | |
| 309 | - border-radius: $custom-border-radio; | |
| 310 | - color: $u-info; | |
| 311 | - font-size: 28rpx; | |
| 312 | 419 | |
| 313 | - .company-clean-container-site-image-info-remark { | |
| 314 | - line-height: 80rpx; | |
| 315 | 420 | |
| 421 | + | |
| 422 | + .company-clean-bottom { | |
| 423 | + position: absolute; | |
| 424 | + width: 100%; | |
| 425 | + // height: 100%; | |
| 426 | + bottom: 0; | |
| 427 | + left: 0; | |
| 428 | + | |
| 429 | + .movableArea { | |
| 430 | + pointer-events: none; | |
| 431 | + position: fixed; | |
| 432 | + left: 0; | |
| 433 | + top: 0; | |
| 434 | + width: 100%; | |
| 435 | + height: calc(100% - $custom-bottom-height); | |
| 436 | + z-index: 999; | |
| 437 | + | |
| 438 | + .movableView { | |
| 439 | + pointer-events: auto; | |
| 440 | + min-height: 60rpx; | |
| 441 | + min-width: 60rpx; | |
| 442 | + | |
| 443 | + .company-clean-call-box-container { | |
| 444 | + min-height: 60rpx; | |
| 445 | + min-width: 60rpx; | |
| 446 | + display: flex; | |
| 447 | + align-items: center; | |
| 448 | + justify-content: center; | |
| 449 | + background-color: #a9e08f; | |
| 450 | + border-radius: 100%; | |
| 451 | + } | |
| 452 | + } | |
| 316 | 453 | } |
| 317 | 454 | |
| 318 | - .company-clean-container-site-image-info-img {} | |
| 455 | + .company-clean-bottom-box { | |
| 456 | + height: $custom-bottom-height; | |
| 457 | + background-color: #ffffff; | |
| 458 | + padding: 50rpx; | |
| 459 | + box-sizing: border-box; | |
| 460 | + display: flex; | |
| 461 | + justify-content: space-between; | |
| 462 | + align-items: center; | |
| 319 | 463 | |
| 320 | - .company-clean-container-site-image-info-input-remark { | |
| 321 | - line-height: 80rpx; | |
| 464 | + .company-clean-bottom-left { | |
| 465 | + transform: rotateY(180deg); | |
| 466 | + } | |
| 467 | + | |
| 468 | + .company-clean-bottom-right { | |
| 469 | + min-width: 200rpx; | |
| 470 | + } | |
| 322 | 471 | } |
| 323 | 472 | |
| 324 | - .company-clean-container-site-image-info-input-remark-box {} | |
| 325 | 473 | } |
| 326 | 474 | |
| 327 | 475 | |
| 328 | - | |
| 329 | - .company-clean-container-site-image-info-sure-button {} | |
| 330 | 476 | } |
| 331 | 477 | </style> | ... | ... |
garbage-removal/src/pages/home/index.vue
| ... | ... | @@ -52,8 +52,8 @@ |
| 52 | 52 | <view class="company-list-item-main-right-score"> |
| 53 | 53 | <text class="company-list-item-main-right-text">评分:</text> |
| 54 | 54 | <view class="company-list-item-main-right-score-start"> |
| 55 | - <u-icon v-for="todo in maxStar" :name="item.score > todo ? 'star-fill' : 'star'" color="#f9ae3d" | |
| 56 | - size="28"></u-icon> | |
| 55 | + <u-icon v-for="todo in maxStar" :name="item.score > todo ? 'star-fill' : 'star'" :key="todo" | |
| 56 | + color="#f9ae3d" size="28"></u-icon> | |
| 57 | 57 | </view> |
| 58 | 58 | <text class="company-list-item-main-right-text" style="color: #fd5d00;">5分</text> |
| 59 | 59 | </view> |
| ... | ... | @@ -74,8 +74,8 @@ |
| 74 | 74 | :hairline="true" shape="circle" text="联系公司"></u-button> |
| 75 | 75 | </view> |
| 76 | 76 | <view class="company-list-item-bottom-button-clean"> |
| 77 | - <u-button @click="handleCleanGarbage(item.companyId)" type="success" :hairline="true" size="normal" | |
| 78 | - shape="circle" text="垃圾清运"></u-button> | |
| 77 | + <u-button @click="handleCleanGarbage(item.companyId, item.tel)" type="success" :hairline="true" | |
| 78 | + size="normal" shape="circle" text="垃圾清运"></u-button> | |
| 79 | 79 | </view> |
| 80 | 80 | </view> |
| 81 | 81 | </view> |
| ... | ... | @@ -197,10 +197,10 @@ function handleDetailClick(companyId, tel) { |
| 197 | 197 | /** |
| 198 | 198 | * 清运跳转 |
| 199 | 199 | */ |
| 200 | -const handleCleanGarbage = (companyId) => { | |
| 200 | +const handleCleanGarbage = (companyId, tel) => { | |
| 201 | 201 | console.log("垃圾清运"); |
| 202 | 202 | uni.$u.route({ |
| 203 | - url: `pages/home/clean/index?companyId=${companyId}`, | |
| 203 | + url: `pages/home/clean/index?companyId=${companyId}&tel=${tel}`, | |
| 204 | 204 | }) |
| 205 | 205 | } |
| 206 | 206 | ... | ... |
garbage-removal/src/pages/order/index.vue
| 1 | 1 | <template> |
| 2 | - <view> | |
| 3 | - order | |
| 4 | - </view> | |
| 2 | + <z-paging-swiper> | |
| 3 | + <template v-slot:top> | |
| 4 | + <u-tabs lineWidth="40" lineColor="#ffffff" lineHeight="6" | |
| 5 | + :activeStyle="{ 'color': '#ffffff', 'font-weight': 'bolder' }" :inactiveStyle="{ color: '#ffffff' }" | |
| 6 | + ref="uTabsElement" :list="list" :current="current" @change="tabsChange" :scrollable="false"></u-tabs> | |
| 7 | + </template> | |
| 8 | + <swiper class="swiper" :current="swiperCurrent" @translation="translation" @animationfinish="animationfinish"> | |
| 9 | + <swiper-item class="swiper-item" v-for="(item, index) in list" :key="index"> | |
| 10 | + <swiper-list-item :tabIndex="index" :currentIndex="swiperCurrent"></swiper-list-item> | |
| 11 | + </swiper-item> | |
| 12 | + </swiper> | |
| 13 | + </z-paging-swiper> | |
| 5 | 14 | </template> |
| 6 | - | |
| 7 | 15 | <script setup> |
| 8 | - | |
| 16 | +import { ref } from 'vue'; | |
| 17 | +import swiperListItem from './swiper-list-item/index.vue'; | |
| 18 | +const list = ref([{ name: '待清运' }, { name: '清运中' }, { name: '全部' }, { name: '待支付' }, { name: '已完成' }]) | |
| 19 | +const current = ref(0); | |
| 20 | +const swiperCurrent = ref(0) | |
| 21 | +const uTabsElement = ref() | |
| 22 | +const tabsChange = (el) => { | |
| 23 | + swiperCurrent.value = Number(el.index) | |
| 24 | +} | |
| 25 | +const animationfinish = (e) => { | |
| 26 | + current.value = e.detail.current | |
| 27 | + swiperCurrent.value = e.detail.current | |
| 28 | +} | |
| 29 | +const translation = (e) => { | |
| 30 | + uTabsElement.value.setDx(e.detail.dx) | |
| 31 | +} | |
| 9 | 32 | </script> |
| 10 | - | |
| 11 | 33 | <style lang="scss" scoped> |
| 34 | +::v-deep .u-tabs__wrapper__scroll-view { | |
| 35 | + background-color: #53c21d; | |
| 36 | +} | |
| 37 | + | |
| 38 | +.swiper { | |
| 39 | + height: 100%; | |
| 40 | + background: linear-gradient(to bottom, $u-success-dark, #ffffff, #ffffff, #ffffff, #ffffff, #ffffff, #ffffff); | |
| 41 | +} | |
| 12 | 42 | </style> | ... | ... |
garbage-removal/src/pages/order/swiper-list-item/index.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="content-container"> | |
| 3 | + <z-paging ref="paging" v-model="dataList" @query="queryList"> | |
| 4 | + <empty-view slot:empty></empty-view> | |
| 5 | + <view class="item" v-for="(item, index) in dataList"> | |
| 6 | + <view class="item-title">{{ item }}</view> | |
| 7 | + </view> | |
| 8 | + </z-paging> | |
| 9 | + </view> | |
| 10 | +</template> | |
| 11 | + | |
| 12 | +<script setup> | |
| 13 | +import { onMounted, ref } from 'vue'; | |
| 14 | + | |
| 15 | +const props = defineProps({ | |
| 16 | + tabIndex: { | |
| 17 | + type: Number | |
| 18 | + }, | |
| 19 | + currentIndex: { | |
| 20 | + type: Number | |
| 21 | + } | |
| 22 | +}) | |
| 23 | +const paging = ref(null) | |
| 24 | +const dataList = ref([]) | |
| 25 | +const count = ref(0) | |
| 26 | +const queryList = (pageNo, pageSize) => { | |
| 27 | + //这里的pageNo和pageSize会自动计算好,直接传给服务器即可 | |
| 28 | + //这里的请求只是演示,请替换成自己的项目的网络请求,并在网络请求回调中通过paging.value.complete(请求回来的数组)将请求结果传给z-paging | |
| 29 | + // request.queryList({ pageNo, pageSize }).then(res => { | |
| 30 | + // //请勿在网络请求回调中给dataList赋值!!只需要调用complete就可以了 | |
| 31 | + if (props.tabIndex == 3) { | |
| 32 | + paging.value.complete([]) | |
| 33 | + return | |
| 34 | + } | |
| 35 | + if (++count.value < 3) { | |
| 36 | + | |
| 37 | + } | |
| 38 | + setInterval(() => { | |
| 39 | + paging.value.complete([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); | |
| 40 | + }, 500); | |
| 41 | + paging.value.complete([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); | |
| 42 | + // }).catch(res => { | |
| 43 | + // //如果请求失败写paging.value.complete(false),会自动展示错误页面 | |
| 44 | + // //注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理 | |
| 45 | + // //在底层的网络请求抛出异常时,写uni.$emit('z-paging-error-emit');即可 | |
| 46 | + // paging.value.complete(false); | |
| 47 | + // }) | |
| 48 | +} | |
| 49 | + | |
| 50 | +onMounted(() => { | |
| 51 | + console.log("tabIndex:", props.tabIndex); | |
| 52 | + console.log("currentIndex:", props.currentIndex); | |
| 53 | +}) | |
| 54 | +</script> | |
| 55 | + | |
| 56 | +<style lang="scss" scoped> | |
| 57 | +.content-container { | |
| 58 | + height: 100%; | |
| 59 | +} | |
| 60 | +</style> | ... | ... |
garbage-removal/src/uview-plus/components/u-radio-group/u-radio-group.vue
| 1 | 1 | <template> |
| 2 | - <view | |
| 3 | - class="u-radio-group" | |
| 4 | - :class="bemClass" | |
| 5 | - > | |
| 2 | + <view class="u-radio-group" :class="bemClass"> | |
| 6 | 3 | <slot></slot> |
| 7 | 4 | </view> |
| 8 | 5 | </template> |
| 9 | 6 | |
| 10 | 7 | <script> |
| 11 | - import props from './props.js'; | |
| 12 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 13 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 8 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 9 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 10 | +import props from './props.js'; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * radioRroup 单选框父组件 | |
| 14 | + * @description 单选框用于有一个选择,用户只能选择其中一个的场景。搭配u-radio使用 | |
| 15 | + * @tutorial https://ijry.github.io/uview-plus/components/radio.html | |
| 16 | + * @property {String | Number | Boolean} value 绑定的值 | |
| 17 | + * @property {Boolean} disabled 是否禁用所有radio(默认 false ) | |
| 18 | + * @property {String} shape 外观形状,shape-方形,circle-圆形(默认 circle ) | |
| 19 | + * @property {String} activeColor 选中时的颜色,应用到所有子Radio组件(默认 '#2979ff' ) | |
| 20 | + * @property {String} inactiveColor 未选中的颜色 (默认 '#c8c9cc' ) | |
| 21 | + * @property {String} name 标识符 | |
| 22 | + * @property {String | Number} size 组件整体的大小,单位px(默认 18 ) | |
| 23 | + * @property {String} placement 布局方式,row-横向,column-纵向 (默认 'row' ) | |
| 24 | + * @property {String} label 文本 | |
| 25 | + * @property {String} labelColor label的颜色 (默认 '#303133' ) | |
| 26 | + * @property {String | Number} labelSize label的字体大小,px单位 (默认 14 ) | |
| 27 | + * @property {Boolean} labelDisabled 是否禁止点击文本操作checkbox(默认 false ) | |
| 28 | + * @property {String} iconColor 图标颜色 (默认 '#ffffff' ) | |
| 29 | + * @property {String | Number} iconSize 图标的大小,单位px (默认 12 ) | |
| 30 | + * @property {Boolean} borderBottom placement为row时,是否显示下边框 (默认 false ) | |
| 31 | + * @property {String} iconPlacement 图标与文字的对齐方式 (默认 'left' ) | |
| 32 | + * @property {Object} customStyle 组件的样式,对象形式 | |
| 33 | + * @event {Function} change 任一个radio状态发生变化时触发 | |
| 34 | + * @example <u-radio-group v-model="value"></u-radio-group> | |
| 35 | + */ | |
| 36 | +export default { | |
| 37 | + name: 'u-radio-group', | |
| 38 | + mixins: [mpMixin, mixin, props], | |
| 39 | + computed: { | |
| 40 | + // 这里computed的变量,都是子组件u-radio需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化 | |
| 41 | + // 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-radio-group) | |
| 42 | + // 拉取父组件新的变化后的参数 | |
| 43 | + parentData() { | |
| 44 | + // #ifdef VUE3 | |
| 45 | + return [this.modelValue, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape, | |
| 46 | + this.iconSize, this.borderBottom, this.placement | |
| 47 | + ] | |
| 48 | + // #endif | |
| 14 | 49 | |
| 15 | - /** | |
| 16 | - * radioRroup 单选框父组件 | |
| 17 | - * @description 单选框用于有一个选择,用户只能选择其中一个的场景。搭配u-radio使用 | |
| 18 | - * @tutorial https://ijry.github.io/uview-plus/components/radio.html | |
| 19 | - * @property {String | Number | Boolean} value 绑定的值 | |
| 20 | - * @property {Boolean} disabled 是否禁用所有radio(默认 false ) | |
| 21 | - * @property {String} shape 外观形状,shape-方形,circle-圆形(默认 circle ) | |
| 22 | - * @property {String} activeColor 选中时的颜色,应用到所有子Radio组件(默认 '#2979ff' ) | |
| 23 | - * @property {String} inactiveColor 未选中的颜色 (默认 '#c8c9cc' ) | |
| 24 | - * @property {String} name 标识符 | |
| 25 | - * @property {String | Number} size 组件整体的大小,单位px(默认 18 ) | |
| 26 | - * @property {String} placement 布局方式,row-横向,column-纵向 (默认 'row' ) | |
| 27 | - * @property {String} label 文本 | |
| 28 | - * @property {String} labelColor label的颜色 (默认 '#303133' ) | |
| 29 | - * @property {String | Number} labelSize label的字体大小,px单位 (默认 14 ) | |
| 30 | - * @property {Boolean} labelDisabled 是否禁止点击文本操作checkbox(默认 false ) | |
| 31 | - * @property {String} iconColor 图标颜色 (默认 '#ffffff' ) | |
| 32 | - * @property {String | Number} iconSize 图标的大小,单位px (默认 12 ) | |
| 33 | - * @property {Boolean} borderBottom placement为row时,是否显示下边框 (默认 false ) | |
| 34 | - * @property {String} iconPlacement 图标与文字的对齐方式 (默认 'left' ) | |
| 35 | - * @property {Object} customStyle 组件的样式,对象形式 | |
| 36 | - * @event {Function} change 任一个radio状态发生变化时触发 | |
| 37 | - * @example <u-radio-group v-model="value"></u-radio-group> | |
| 38 | - */ | |
| 39 | - export default { | |
| 40 | - name: 'u-radio-group', | |
| 41 | - mixins: [mpMixin, mixin, props], | |
| 42 | - computed: { | |
| 43 | - // 这里computed的变量,都是子组件u-radio需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化 | |
| 44 | - // 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-radio-group) | |
| 45 | - // 拉取父组件新的变化后的参数 | |
| 46 | - parentData() { | |
| 47 | - // #ifdef VUE3 | |
| 48 | - return [this.modelValue, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape, | |
| 49 | - this.iconSize, this.borderBottom, this.placement | |
| 50 | - ] | |
| 51 | - // #endif | |
| 52 | - // #ifdef VUE2 | |
| 53 | - return [this.value, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape, | |
| 54 | - this.iconSize, this.borderBottom, this.placement | |
| 55 | - ] | |
| 56 | - // #endif | |
| 57 | - | |
| 58 | - }, | |
| 59 | - bemClass() { | |
| 60 | - // this.bem为一个computed变量,在mixin中 | |
| 61 | - return this.bem('radio-group', ['placement']) | |
| 62 | - }, | |
| 63 | - }, | |
| 64 | - watch: { | |
| 65 | - // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件 | |
| 66 | - parentData() { | |
| 67 | - if (this.children.length) { | |
| 68 | - this.children.map(child => { | |
| 69 | - // 判断子组件(u-radio)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值) | |
| 70 | - typeof(child.init) === 'function' && child.init() | |
| 71 | - }) | |
| 72 | - } | |
| 73 | - }, | |
| 74 | - }, | |
| 75 | - data() { | |
| 76 | - return { | |
| 77 | - } | |
| 78 | 50 | }, |
| 79 | - created() { | |
| 80 | - this.children = [] | |
| 51 | + bemClass() { | |
| 52 | + // this.bem为一个computed变量,在mixin中 | |
| 53 | + return this.bem('radio-group', ['placement']) | |
| 81 | 54 | }, |
| 82 | - // #ifdef VUE3 | |
| 83 | - emits: ['update:modelValue', 'change'], | |
| 84 | - // #endif | |
| 85 | - methods: { | |
| 86 | - // 将其他的radio设置为未选中的状态 | |
| 87 | - unCheckedOther(childInstance) { | |
| 55 | + }, | |
| 56 | + watch: { | |
| 57 | + // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件 | |
| 58 | + parentData() { | |
| 59 | + if (this.children.length) { | |
| 88 | 60 | this.children.map(child => { |
| 89 | - // 所有子radio中,被操作组件实例的checked的值无需修改 | |
| 90 | - if (childInstance !== child) { | |
| 91 | - child.checked = false | |
| 92 | - } | |
| 61 | + // 判断子组件(u-radio)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值) | |
| 62 | + typeof (child.init) === 'function' && child.init() | |
| 93 | 63 | }) |
| 94 | - const { | |
| 95 | - name | |
| 96 | - } = childInstance | |
| 97 | - // 通过emit事件,设置父组件通过v-model双向绑定的值 | |
| 98 | - // #ifdef VUE3 | |
| 99 | - this.$emit("update:modelValue", name); | |
| 100 | - // #endif | |
| 101 | - // #ifdef VUE2 | |
| 102 | - this.$emit("input", name); | |
| 103 | - // #endif | |
| 104 | - // 发出事件 | |
| 105 | - this.$emit('change', name) | |
| 106 | - }, | |
| 64 | + } | |
| 65 | + }, | |
| 66 | + }, | |
| 67 | + data() { | |
| 68 | + return { | |
| 107 | 69 | } |
| 70 | + }, | |
| 71 | + created() { | |
| 72 | + this.children = [] | |
| 73 | + }, | |
| 74 | + // #ifdef VUE3 | |
| 75 | + emits: ['update:modelValue', 'change'], | |
| 76 | + // #endif | |
| 77 | + methods: { | |
| 78 | + // 将其他的radio设置为未选中的状态 | |
| 79 | + unCheckedOther(childInstance) { | |
| 80 | + this.children.map(child => { | |
| 81 | + // 所有子radio中,被操作组件实例的checked的值无需修改 | |
| 82 | + if (childInstance !== child) { | |
| 83 | + child.checked = false | |
| 84 | + } | |
| 85 | + }) | |
| 86 | + const { | |
| 87 | + name | |
| 88 | + } = childInstance | |
| 89 | + // 通过emit事件,设置父组件通过v-model双向绑定的值 | |
| 90 | + // #ifdef VUE3 | |
| 91 | + this.$emit("update:modelValue", name); | |
| 92 | + // #endif | |
| 93 | + // #ifdef VUE2 | |
| 94 | + this.$emit("input", name); | |
| 95 | + // #endif | |
| 96 | + // 发出事件 | |
| 97 | + this.$emit('change', name) | |
| 98 | + }, | |
| 108 | 99 | } |
| 100 | +} | |
| 109 | 101 | </script> |
| 110 | 102 | |
| 111 | 103 | <style lang="scss" scoped> |
| 112 | - @import "../../libs/css/components.scss"; | |
| 104 | +@import "../../libs/css/components.scss"; | |
| 113 | 105 | |
| 114 | - .u-radio-group { | |
| 115 | - flex: 1; | |
| 106 | +.u-radio-group { | |
| 107 | + flex: 1; | |
| 116 | 108 | |
| 117 | - &--row { | |
| 118 | - /* #ifndef APP-NVUE */ | |
| 119 | - display: flex; | |
| 120 | - /* #endif */ | |
| 121 | - flex-flow: row wrap; | |
| 122 | - } | |
| 109 | + &--row { | |
| 110 | + /* #ifndef APP-NVUE */ | |
| 111 | + display: flex; | |
| 112 | + /* #endif */ | |
| 113 | + // flex-flow: row wrap; | |
| 114 | + } | |
| 123 | 115 | |
| 124 | - &--column { | |
| 125 | - @include flex(column); | |
| 126 | - } | |
| 116 | + &--column { | |
| 117 | + @include flex(column); | |
| 127 | 118 | } |
| 119 | +} | |
| 128 | 120 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-radio/u-radio.vue
| 1 | 1 | <template> |
| 2 | - <view | |
| 3 | - class="u-radio" | |
| 4 | - @tap.stop="wrapperClickHandler" | |
| 5 | - :style="[radioStyle]" | |
| 6 | - :class="[`u-radio-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']" | |
| 7 | - > | |
| 8 | - <view | |
| 9 | - class="u-radio__icon-wrap" | |
| 10 | - @tap.stop="iconClickHandler" | |
| 11 | - :class="iconClasses" | |
| 12 | - :style="[iconWrapStyle]" | |
| 13 | - > | |
| 2 | + <view class="u-radio" @tap.stop="wrapperClickHandler" :style="[radioStyle]" | |
| 3 | + :class="[`u-radio-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']"> | |
| 4 | + <view class="u-radio__icon-wrap" @tap.stop="iconClickHandler" :class="iconClasses" :style="[iconWrapStyle]"> | |
| 14 | 5 | <slot name="icon"> |
| 15 | - <u-icon | |
| 16 | - class="u-radio__icon-wrap__icon" | |
| 17 | - name="checkbox-mark" | |
| 18 | - :size="elIconSize" | |
| 19 | - :color="elIconColor" | |
| 20 | - /> | |
| 6 | + <u-icon class="u-radio__icon-wrap__icon" name="checkbox-mark" :size="elIconSize" :color="elIconColor" /> | |
| 21 | 7 | </slot> |
| 22 | 8 | </view> |
| 23 | - <text | |
| 24 | - class="u-radio__text" | |
| 25 | - @tap.stop="labelClickHandler" | |
| 26 | - :style="{ | |
| 27 | - color: elDisabled ? elInactiveColor : elLabelColor, | |
| 28 | - fontSize: elLabelSize, | |
| 29 | - lineHeight: elLabelSize | |
| 30 | - }" | |
| 31 | - >{{label}}</text> | |
| 9 | + <text class="u-radio__text" @tap.stop="labelClickHandler" :style="{ | |
| 10 | + color: elDisabled ? elInactiveColor : elLabelColor, | |
| 11 | + fontSize: elLabelSize, | |
| 12 | + lineHeight: elLabelSize | |
| 13 | + }">{{ label }}</text> | |
| 32 | 14 | </view> |
| 33 | 15 | </template> |
| 34 | 16 | |
| 35 | 17 | <script> |
| 36 | - import props from './props.js'; | |
| 37 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 38 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 39 | - /** | |
| 40 | - * radio 单选框 | |
| 41 | - * @description 单选框用于有一个选择,用户只能选择其中一个的场景。搭配u-radio-group使用 | |
| 42 | - * @tutorial https://ijry.github.io/uview-plus/components/radio.html | |
| 43 | - * @property {String | Number} name radio的名称 | |
| 44 | - * @property {String} shape 形状,square为方形,circle为圆型 | |
| 45 | - * @property {Boolean} disabled 是否禁用 | |
| 46 | - * @property {String | Boolean} labelDisabled 是否禁止点击提示语选中单选框 | |
| 47 | - * @property {String} activeColor 选中时的颜色,如设置parent的active-color将失效 | |
| 48 | - * @property {String} inactiveColor 未选中的颜色 | |
| 49 | - * @property {String | Number} iconSize 图标大小,单位px | |
| 50 | - * @property {String | Number} labelSize label字体大小,单位px | |
| 51 | - * @property {String | Number} label label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式 | |
| 52 | - * @property {String | Number} size 整体的大小 | |
| 53 | - * @property {String} iconColor 图标颜色 | |
| 54 | - * @property {String} labelColor label的颜色 | |
| 55 | - * @property {Object} customStyle 组件的样式,对象形式 | |
| 56 | - * | |
| 57 | - * @event {Function} change 某个radio状态发生变化时触发(选中状态) | |
| 58 | - * @example <u-radio :labelDisabled="false">门掩黄昏,无计留春住</u-radio> | |
| 59 | - */ | |
| 60 | - export default { | |
| 61 | - name: "u-radio", | |
| 62 | - | |
| 63 | - mixins: [mpMixin, mixin,props], | |
| 64 | - data() { | |
| 65 | - return { | |
| 66 | - checked: false, | |
| 67 | - // 当你看到这段代码的时候, | |
| 68 | - // 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式 | |
| 69 | - // 故只能使用如此方法 | |
| 70 | - parentData: { | |
| 71 | - iconSize: 12, | |
| 72 | - labelDisabled: null, | |
| 73 | - disabled: null, | |
| 74 | - shape: null, | |
| 75 | - activeColor: null, | |
| 76 | - inactiveColor: null, | |
| 77 | - size: 18, | |
| 78 | - value: null, | |
| 79 | - modelValue: null, | |
| 80 | - iconColor: null, | |
| 81 | - placement: 'row', | |
| 82 | - borderBottom: false, | |
| 83 | - iconPlacement: 'left' | |
| 84 | - } | |
| 18 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 19 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 20 | +import props from './props.js'; | |
| 21 | +/** | |
| 22 | + * radio 单选框 | |
| 23 | + * @description 单选框用于有一个选择,用户只能选择其中一个的场景。搭配u-radio-group使用 | |
| 24 | + * @tutorial https://ijry.github.io/uview-plus/components/radio.html | |
| 25 | + * @property {String | Number} name radio的名称 | |
| 26 | + * @property {String} shape 形状,square为方形,circle为圆型 | |
| 27 | + * @property {Boolean} disabled 是否禁用 | |
| 28 | + * @property {String | Boolean} labelDisabled 是否禁止点击提示语选中单选框 | |
| 29 | + * @property {String} activeColor 选中时的颜色,如设置parent的active-color将失效 | |
| 30 | + * @property {String} inactiveColor 未选中的颜色 | |
| 31 | + * @property {String | Number} iconSize 图标大小,单位px | |
| 32 | + * @property {String | Number} labelSize label字体大小,单位px | |
| 33 | + * @property {String | Number} label label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式 | |
| 34 | + * @property {String | Number} size 整体的大小 | |
| 35 | + * @property {String} iconColor 图标颜色 | |
| 36 | + * @property {String} labelColor label的颜色 | |
| 37 | + * @property {Object} customStyle 组件的样式,对象形式 | |
| 38 | + * | |
| 39 | + * @event {Function} change 某个radio状态发生变化时触发(选中状态) | |
| 40 | + * @example <u-radio :labelDisabled="false">门掩黄昏,无计留春住</u-radio> | |
| 41 | + */ | |
| 42 | +export default { | |
| 43 | + name: "u-radio", | |
| 44 | + | |
| 45 | + mixins: [mpMixin, mixin, props], | |
| 46 | + data() { | |
| 47 | + return { | |
| 48 | + checked: false, | |
| 49 | + // 当你看到这段代码的时候, | |
| 50 | + // 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式 | |
| 51 | + // 故只能使用如此方法 | |
| 52 | + parentData: { | |
| 53 | + iconSize: 12, | |
| 54 | + labelDisabled: null, | |
| 55 | + disabled: null, | |
| 56 | + shape: null, | |
| 57 | + activeColor: null, | |
| 58 | + inactiveColor: null, | |
| 59 | + size: 18, | |
| 60 | + value: null, | |
| 61 | + modelValue: null, | |
| 62 | + iconColor: null, | |
| 63 | + placement: 'row', | |
| 64 | + borderBottom: false, | |
| 65 | + iconPlacement: 'left' | |
| 85 | 66 | } |
| 67 | + } | |
| 68 | + }, | |
| 69 | + computed: { | |
| 70 | + // 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置 | |
| 71 | + elDisabled() { | |
| 72 | + return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false; | |
| 73 | + }, | |
| 74 | + // 是否禁用label点击 | |
| 75 | + elLabelDisabled() { | |
| 76 | + return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled : | |
| 77 | + false; | |
| 78 | + }, | |
| 79 | + // 组件尺寸,对应size的值,默认值为21px | |
| 80 | + elSize() { | |
| 81 | + return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21); | |
| 82 | + }, | |
| 83 | + // 组件的勾选图标的尺寸,默认12px | |
| 84 | + elIconSize() { | |
| 85 | + return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12); | |
| 86 | + }, | |
| 87 | + // 组件选中激活时的颜色 | |
| 88 | + elActiveColor() { | |
| 89 | + return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff'); | |
| 90 | + }, | |
| 91 | + // 组件选未中激活时的颜色 | |
| 92 | + elInactiveColor() { | |
| 93 | + return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor : | |
| 94 | + '#c8c9cc'); | |
| 86 | 95 | }, |
| 87 | - computed: { | |
| 88 | - // 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置 | |
| 89 | - elDisabled() { | |
| 90 | - return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false; | |
| 91 | - }, | |
| 92 | - // 是否禁用label点击 | |
| 93 | - elLabelDisabled() { | |
| 94 | - return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled : | |
| 95 | - false; | |
| 96 | - }, | |
| 97 | - // 组件尺寸,对应size的值,默认值为21px | |
| 98 | - elSize() { | |
| 99 | - return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21); | |
| 100 | - }, | |
| 101 | - // 组件的勾选图标的尺寸,默认12px | |
| 102 | - elIconSize() { | |
| 103 | - return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12); | |
| 104 | - }, | |
| 105 | - // 组件选中激活时的颜色 | |
| 106 | - elActiveColor() { | |
| 107 | - return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff'); | |
| 108 | - }, | |
| 109 | - // 组件选未中激活时的颜色 | |
| 110 | - elInactiveColor() { | |
| 111 | - return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor : | |
| 112 | - '#c8c9cc'); | |
| 113 | - }, | |
| 114 | - // label的颜色 | |
| 115 | - elLabelColor() { | |
| 116 | - return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266') | |
| 117 | - }, | |
| 96 | + // label的颜色 | |
| 97 | + elLabelColor() { | |
| 98 | + return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266') | |
| 99 | + }, | |
| 100 | + // 组件的形状 | |
| 101 | + elShape() { | |
| 102 | + return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle'); | |
| 103 | + }, | |
| 104 | + // label大小 | |
| 105 | + elLabelSize() { | |
| 106 | + return uni.$u.addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize : | |
| 107 | + '15')) | |
| 108 | + }, | |
| 109 | + elIconColor() { | |
| 110 | + const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor : | |
| 111 | + '#ffffff'); | |
| 112 | + // 图标的颜色 | |
| 113 | + if (this.elDisabled) { | |
| 114 | + // disabled状态下,已勾选的radio图标改为elInactiveColor | |
| 115 | + return this.checked ? this.elInactiveColor : 'transparent' | |
| 116 | + } else { | |
| 117 | + return this.checked ? iconColor : 'transparent' | |
| 118 | + } | |
| 119 | + }, | |
| 120 | + iconClasses() { | |
| 121 | + let classes = [] | |
| 118 | 122 | // 组件的形状 |
| 119 | - elShape() { | |
| 120 | - return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle'); | |
| 121 | - }, | |
| 122 | - // label大小 | |
| 123 | - elLabelSize() { | |
| 124 | - return uni.$u.addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize : | |
| 125 | - '15')) | |
| 126 | - }, | |
| 127 | - elIconColor() { | |
| 128 | - const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor : | |
| 129 | - '#ffffff'); | |
| 130 | - // 图标的颜色 | |
| 131 | - if (this.elDisabled) { | |
| 132 | - // disabled状态下,已勾选的radio图标改为elInactiveColor | |
| 133 | - return this.checked ? this.elInactiveColor : 'transparent' | |
| 134 | - } else { | |
| 135 | - return this.checked ? iconColor : 'transparent' | |
| 136 | - } | |
| 137 | - }, | |
| 138 | - iconClasses() { | |
| 139 | - let classes = [] | |
| 140 | - // 组件的形状 | |
| 141 | - classes.push('u-radio__icon-wrap--' + this.elShape) | |
| 142 | - if (this.elDisabled) { | |
| 143 | - classes.push('u-radio__icon-wrap--disabled') | |
| 144 | - } | |
| 145 | - if (this.checked && this.elDisabled) { | |
| 146 | - classes.push('u-radio__icon-wrap--disabled--checked') | |
| 147 | - } | |
| 148 | - // 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效 | |
| 149 | - // #ifdef MP-ALIPAY || MP-TOUTIAO | |
| 150 | - classes = classes.join(' ') | |
| 151 | - // #endif | |
| 152 | - return classes | |
| 153 | - }, | |
| 154 | - iconWrapStyle() { | |
| 155 | - // radio的整体样式 | |
| 156 | - const style = {} | |
| 157 | - style.backgroundColor = this.checked && !this.elDisabled ? this.elActiveColor : '#ffffff' | |
| 158 | - style.borderColor = this.checked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor | |
| 159 | - style.width = uni.$u.addUnit(this.elSize) | |
| 160 | - style.height = uni.$u.addUnit(this.elSize) | |
| 161 | - // 如果是图标在右边的话,移除它的右边距 | |
| 162 | - if (this.parentData.iconPlacement === 'right') { | |
| 163 | - style.marginRight = 0 | |
| 164 | - } | |
| 165 | - return style | |
| 166 | - }, | |
| 167 | - radioStyle() { | |
| 168 | - const style = {} | |
| 169 | - if(this.parentData.borderBottom && this.parentData.placement === 'row') { | |
| 170 | - uni.$u.error('检测到您将borderBottom设置为true,需要同时将u-radio-group的placement设置为column才有效') | |
| 171 | - } | |
| 172 | - // 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔 | |
| 173 | - if(this.parentData.borderBottom && this.parentData.placement === 'column') { | |
| 174 | - // ios像素密度高,需要多一点的距离 | |
| 175 | - style.paddingBottom = uni.$u.os() === 'ios' ? '12px' : '8px' | |
| 176 | - } | |
| 177 | - return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) | |
| 123 | + classes.push('u-radio__icon-wrap--' + this.elShape) | |
| 124 | + if (this.elDisabled) { | |
| 125 | + classes.push('u-radio__icon-wrap--disabled') | |
| 126 | + } | |
| 127 | + if (this.checked && this.elDisabled) { | |
| 128 | + classes.push('u-radio__icon-wrap--disabled--checked') | |
| 178 | 129 | } |
| 130 | + // 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效 | |
| 131 | + // #ifdef MP-ALIPAY || MP-TOUTIAO | |
| 132 | + classes = classes.join(' ') | |
| 133 | + // #endif | |
| 134 | + return classes | |
| 179 | 135 | }, |
| 180 | - mounted() { | |
| 181 | - this.init() | |
| 136 | + iconWrapStyle() { | |
| 137 | + // radio的整体样式 | |
| 138 | + const style = {} | |
| 139 | + style.backgroundColor = this.checked && !this.elDisabled ? this.elActiveColor : '#ffffff' | |
| 140 | + style.borderColor = this.checked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor | |
| 141 | + style.width = uni.$u.addUnit(this.elSize) | |
| 142 | + style.height = uni.$u.addUnit(this.elSize) | |
| 143 | + // 如果是图标在右边的话,移除它的右边距 | |
| 144 | + if (this.parentData.iconPlacement === 'right') { | |
| 145 | + style.marginRight = 0 | |
| 146 | + } | |
| 147 | + return style | |
| 182 | 148 | }, |
| 149 | + radioStyle() { | |
| 150 | + const style = {} | |
| 151 | + if (this.parentData.borderBottom && this.parentData.placement === 'row') { | |
| 152 | + uni.$u.error('检测到您将borderBottom设置为true,需要同时将u-radio-group的placement设置为column才有效') | |
| 153 | + } | |
| 154 | + // 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔 | |
| 155 | + if (this.parentData.borderBottom && this.parentData.placement === 'column') { | |
| 156 | + // ios像素密度高,需要多一点的距离 | |
| 157 | + style.paddingBottom = uni.$u.os() === 'ios' ? '12px' : '8px' | |
| 158 | + } | |
| 159 | + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) | |
| 160 | + } | |
| 161 | + }, | |
| 162 | + mounted() { | |
| 163 | + this.init() | |
| 164 | + }, | |
| 183 | 165 | |
| 184 | - methods: { | |
| 185 | - init() { | |
| 186 | - // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用 | |
| 187 | - this.updateParentData() | |
| 188 | - if (!this.parent) { | |
| 189 | - uni.$u.error('u-radio必须搭配u-radio-group组件使用') | |
| 190 | - } | |
| 191 | - // 设置初始化时,是否默认选中的状态 | |
| 192 | - // #ifdef VUE3 | |
| 193 | - this.checked = this.name === this.parentData.modelValue | |
| 194 | - // #endif | |
| 195 | - // #ifdef VUE2 | |
| 196 | - this.checked = this.name === this.parentData.value | |
| 197 | - // #endif | |
| 198 | - }, | |
| 199 | - updateParentData() { | |
| 200 | - this.getParentData('u-radio-group') | |
| 201 | - }, | |
| 202 | - // 点击图标 | |
| 203 | - iconClickHandler(e) { | |
| 204 | - this.preventEvent(e) | |
| 205 | - // 如果整体被禁用,不允许被点击 | |
| 206 | - if (!this.elDisabled) { | |
| 207 | - this.setRadioCheckedStatus() | |
| 208 | - } | |
| 209 | - }, | |
| 210 | - // 横向两端排列时,点击组件即可触发选中事件 | |
| 211 | - wrapperClickHandler(e) { | |
| 212 | - this.parentData.iconPlacement === 'right' && this.iconClickHandler(e) | |
| 213 | - }, | |
| 214 | - // 点击label | |
| 215 | - labelClickHandler(e) { | |
| 216 | - this.preventEvent(e) | |
| 217 | - // 如果按钮整体被禁用或者label被禁用,则不允许点击文字修改状态 | |
| 218 | - if (!this.elLabelDisabled && !this.elDisabled) { | |
| 219 | - this.setRadioCheckedStatus() | |
| 220 | - } | |
| 221 | - }, | |
| 222 | - emitEvent() { | |
| 223 | - // u-radio的checked不为true时(意味着未选中),才发出事件,避免多次点击触发事件 | |
| 224 | - if (!this.checked) { | |
| 225 | - this.$emit('change', this.name) | |
| 226 | - // 尝试调用u-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时 | |
| 227 | - this.$nextTick(() => { | |
| 228 | - uni.$u.formValidate(this, 'change') | |
| 229 | - }) | |
| 230 | - } | |
| 231 | - }, | |
| 232 | - // 改变组件选中状态 | |
| 233 | - // 这里的改变的依据是,更改本组件的checked值为true,同时通过父组件遍历所有u-radio实例 | |
| 234 | - // 将本组件外的其他u-radio的checked都设置为false(都被取消选中状态),因而只剩下一个为选中状态 | |
| 235 | - setRadioCheckedStatus() { | |
| 236 | - this.emitEvent() | |
| 237 | - // 将本组件标记为选中状态 | |
| 238 | - this.checked = true | |
| 239 | - typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this) | |
| 166 | + methods: { | |
| 167 | + init() { | |
| 168 | + // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用 | |
| 169 | + this.updateParentData() | |
| 170 | + if (!this.parent) { | |
| 171 | + uni.$u.error('u-radio必须搭配u-radio-group组件使用') | |
| 172 | + } | |
| 173 | + // 设置初始化时,是否默认选中的状态 | |
| 174 | + // #ifdef VUE3 | |
| 175 | + this.checked = this.name === this.parentData.modelValue | |
| 176 | + // #endif | |
| 177 | + // #ifdef VUE2 | |
| 178 | + this.checked = this.name === this.parentData.value | |
| 179 | + // #endif | |
| 180 | + }, | |
| 181 | + updateParentData() { | |
| 182 | + this.getParentData('u-radio-group') | |
| 183 | + }, | |
| 184 | + // 点击图标 | |
| 185 | + iconClickHandler(e) { | |
| 186 | + this.preventEvent(e) | |
| 187 | + // 如果整体被禁用,不允许被点击 | |
| 188 | + if (!this.elDisabled) { | |
| 189 | + this.setRadioCheckedStatus() | |
| 190 | + } | |
| 191 | + }, | |
| 192 | + // 横向两端排列时,点击组件即可触发选中事件 | |
| 193 | + wrapperClickHandler(e) { | |
| 194 | + this.parentData.iconPlacement === 'right' && this.iconClickHandler(e) | |
| 195 | + }, | |
| 196 | + // 点击label | |
| 197 | + labelClickHandler(e) { | |
| 198 | + this.preventEvent(e) | |
| 199 | + // 如果按钮整体被禁用或者label被禁用,则不允许点击文字修改状态 | |
| 200 | + if (!this.elLabelDisabled && !this.elDisabled) { | |
| 201 | + this.setRadioCheckedStatus() | |
| 202 | + } | |
| 203 | + }, | |
| 204 | + emitEvent() { | |
| 205 | + // u-radio的checked不为true时(意味着未选中),才发出事件,避免多次点击触发事件 | |
| 206 | + if (!this.checked) { | |
| 207 | + this.$emit('change', this.name) | |
| 208 | + // 尝试调用u-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时 | |
| 209 | + this.$nextTick(() => { | |
| 210 | + uni.$u.formValidate(this, 'change') | |
| 211 | + }) | |
| 240 | 212 | } |
| 213 | + }, | |
| 214 | + // 改变组件选中状态 | |
| 215 | + // 这里的改变的依据是,更改本组件的checked值为true,同时通过父组件遍历所有u-radio实例 | |
| 216 | + // 将本组件外的其他u-radio的checked都设置为false(都被取消选中状态),因而只剩下一个为选中状态 | |
| 217 | + setRadioCheckedStatus() { | |
| 218 | + this.emitEvent() | |
| 219 | + // 将本组件标记为选中状态 | |
| 220 | + this.checked = true | |
| 221 | + typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this) | |
| 241 | 222 | } |
| 242 | 223 | } |
| 224 | +} | |
| 243 | 225 | </script> |
| 244 | 226 | |
| 245 | 227 | <style lang="scss" scoped> |
| 246 | - @import "../../libs/css/components.scss"; | |
| 247 | - $u-radio-wrap-margin-right:6px !default; | |
| 248 | - $u-radio-wrap-font-size:20px !default; | |
| 249 | - $u-radio-wrap-border-width:1px !default; | |
| 250 | - $u-radio-wrap-border-color: #c8c9cc !default; | |
| 251 | - $u-radio-line-height:0 !default; | |
| 252 | - $u-radio-circle-border-radius:100% !default; | |
| 253 | - $u-radio-square-border-radius:3px !default; | |
| 254 | - $u-radio-checked-color:#fff !default; | |
| 255 | - $u-radio-checked-background-color:red !default; | |
| 256 | - $u-radio-checked-border-color: #2979ff !default; | |
| 257 | - $u-radio-disabled-background-color:#ebedf0 !default; | |
| 258 | - $u-radio-disabled--checked-color:#c8c9cc !default; | |
| 259 | - $u-radio-label-margin-left: 5px !default; | |
| 260 | - $u-radio-label-margin-right:12px !default; | |
| 261 | - $u-radio-label-color:$u-content-color !default; | |
| 262 | - $u-radio-label-font-size:15px !default; | |
| 263 | - $u-radio-label-disabled-color:#c8c9cc !default; | |
| 264 | - | |
| 265 | - .u-radio { | |
| 228 | +@import "../../libs/css/components.scss"; | |
| 229 | +$u-radio-wrap-margin-right: 6px !default; | |
| 230 | +$u-radio-wrap-font-size: 20px !default; | |
| 231 | +$u-radio-wrap-border-width: 1px !default; | |
| 232 | +$u-radio-wrap-border-color: #c8c9cc !default; | |
| 233 | +$u-radio-line-height: 0 !default; | |
| 234 | +$u-radio-circle-border-radius: 100% !default; | |
| 235 | +$u-radio-square-border-radius: 3px !default; | |
| 236 | +$u-radio-checked-color: #fff !default; | |
| 237 | +$u-radio-checked-background-color: red !default; | |
| 238 | +$u-radio-checked-border-color: #2979ff !default; | |
| 239 | +$u-radio-disabled-background-color: #ebedf0 !default; | |
| 240 | +$u-radio-disabled--checked-color: #c8c9cc !default; | |
| 241 | +$u-radio-label-margin-left: 5px !default; | |
| 242 | +$u-radio-label-margin-right: 12px !default; | |
| 243 | +$u-radio-label-color: $u-content-color !default; | |
| 244 | +$u-radio-label-font-size: 15px !default; | |
| 245 | +$u-radio-label-disabled-color: #c8c9cc !default; | |
| 246 | + | |
| 247 | +.u-radio { | |
| 248 | + /* #ifndef APP-NVUE */ | |
| 249 | + // @include flex(row); | |
| 250 | + /* #endif */ | |
| 251 | + // overflow: hidden; | |
| 252 | + flex-direction: row; | |
| 253 | + // align-items: center; | |
| 254 | + // margin-bottom: 5px; | |
| 255 | + // margin-top: 5px; | |
| 256 | + | |
| 257 | + &-label--left { | |
| 258 | + flex-direction: row | |
| 259 | + } | |
| 260 | + | |
| 261 | + &-label--right { | |
| 262 | + flex-direction: row-reverse; | |
| 263 | + justify-content: space-between | |
| 264 | + } | |
| 265 | + | |
| 266 | + &__icon-wrap { | |
| 266 | 267 | /* #ifndef APP-NVUE */ |
| 267 | - @include flex(row); | |
| 268 | + box-sizing: border-box; | |
| 269 | + // nvue下,border-color过渡有问题 | |
| 270 | + transition-property: border-color, background-color, color; | |
| 271 | + transition-duration: 0.2s; | |
| 268 | 272 | /* #endif */ |
| 269 | - overflow: hidden; | |
| 270 | - flex-direction: row; | |
| 273 | + color: $u-content-color; | |
| 274 | + @include flex; | |
| 271 | 275 | align-items: center; |
| 272 | - margin-bottom: 5px; | |
| 273 | - margin-top: 5px; | |
| 274 | - | |
| 275 | - &-label--left { | |
| 276 | - flex-direction: row | |
| 277 | - } | |
| 276 | + justify-content: center; | |
| 277 | + color: transparent; | |
| 278 | + text-align: center; | |
| 279 | + margin-right: $u-radio-wrap-margin-right; | |
| 280 | + font-size: $u-radio-wrap-font-size; | |
| 281 | + border-width: $u-radio-wrap-border-width; | |
| 282 | + border-color: $u-radio-wrap-border-color; | |
| 283 | + border-style: solid; | |
| 278 | 284 | |
| 279 | - &-label--right { | |
| 280 | - flex-direction: row-reverse; | |
| 281 | - justify-content: space-between | |
| 285 | + /* #ifdef MP-TOUTIAO */ | |
| 286 | + // 头条小程序兼容性问题,需要设置行高为0,否则图标偏下 | |
| 287 | + &__icon { | |
| 288 | + line-height: $u-radio-line-height; | |
| 282 | 289 | } |
| 283 | 290 | |
| 284 | - &__icon-wrap { | |
| 285 | - /* #ifndef APP-NVUE */ | |
| 286 | - box-sizing: border-box; | |
| 287 | - // nvue下,border-color过渡有问题 | |
| 288 | - transition-property: border-color, background-color, color; | |
| 289 | - transition-duration: 0.2s; | |
| 290 | - /* #endif */ | |
| 291 | - color: $u-content-color; | |
| 292 | - @include flex; | |
| 293 | - align-items: center; | |
| 294 | - justify-content: center; | |
| 295 | - color: transparent; | |
| 296 | - text-align: center; | |
| 297 | - margin-right: $u-radio-wrap-margin-right; | |
| 298 | - font-size: $u-radio-wrap-font-size; | |
| 299 | - border-width: $u-radio-wrap-border-width; | |
| 300 | - border-color: $u-radio-wrap-border-color; | |
| 301 | - border-style: solid; | |
| 302 | - | |
| 303 | - /* #ifdef MP-TOUTIAO */ | |
| 304 | - // 头条小程序兼容性问题,需要设置行高为0,否则图标偏下 | |
| 305 | - &__icon { | |
| 306 | - line-height: $u-radio-line-height; | |
| 307 | - } | |
| 308 | - | |
| 309 | - /* #endif */ | |
| 291 | + /* #endif */ | |
| 310 | 292 | |
| 311 | - &--circle { | |
| 312 | - border-radius: $u-radio-circle-border-radius; | |
| 313 | - } | |
| 293 | + &--circle { | |
| 294 | + border-radius: $u-radio-circle-border-radius; | |
| 295 | + } | |
| 314 | 296 | |
| 315 | - &--square { | |
| 316 | - border-radius: $u-radio-square-border-radius; | |
| 317 | - } | |
| 297 | + &--square { | |
| 298 | + border-radius: $u-radio-square-border-radius; | |
| 299 | + } | |
| 318 | 300 | |
| 319 | - &--checked { | |
| 320 | - color: $u-radio-checked-color; | |
| 321 | - background-color: $u-radio-checked-background-color; | |
| 322 | - border-color: $u-radio-checked-border-color; | |
| 323 | - } | |
| 301 | + &--checked { | |
| 302 | + color: $u-radio-checked-color; | |
| 303 | + background-color: $u-radio-checked-background-color; | |
| 304 | + border-color: $u-radio-checked-border-color; | |
| 305 | + } | |
| 324 | 306 | |
| 325 | - &--disabled { | |
| 326 | - background-color: $u-radio-disabled-background-color !important; | |
| 327 | - } | |
| 307 | + &--disabled { | |
| 308 | + background-color: $u-radio-disabled-background-color !important; | |
| 309 | + } | |
| 328 | 310 | |
| 329 | - &--disabled--checked { | |
| 330 | - color: $u-radio-disabled--checked-color !important; | |
| 331 | - } | |
| 311 | + &--disabled--checked { | |
| 312 | + color: $u-radio-disabled--checked-color !important; | |
| 332 | 313 | } |
| 314 | + } | |
| 333 | 315 | |
| 334 | - &__label { | |
| 335 | - /* #ifndef APP-NVUE */ | |
| 336 | - word-wrap: break-word; | |
| 337 | - /* #endif */ | |
| 338 | - margin-left: $u-radio-label-margin-left; | |
| 339 | - margin-right: $u-radio-label-margin-right; | |
| 340 | - color: $u-radio-label-color; | |
| 341 | - font-size: $u-radio-label-font-size; | |
| 316 | + &__label { | |
| 317 | + /* #ifndef APP-NVUE */ | |
| 318 | + word-wrap: break-word; | |
| 319 | + /* #endif */ | |
| 320 | + margin-left: $u-radio-label-margin-left; | |
| 321 | + margin-right: $u-radio-label-margin-right; | |
| 322 | + color: $u-radio-label-color; | |
| 323 | + font-size: $u-radio-label-font-size; | |
| 342 | 324 | |
| 343 | - &--disabled { | |
| 344 | - color: $u-radio-label-disabled-color; | |
| 345 | - } | |
| 325 | + &--disabled { | |
| 326 | + color: $u-radio-label-disabled-color; | |
| 346 | 327 | } |
| 347 | 328 | } |
| 329 | +} | |
| 348 | 330 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-upload/u-upload.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="u-upload" :style="[$u.addStyle(customStyle)]"> |
| 3 | - <view class="u-upload__wrap" > | |
| 3 | + <view class="u-upload__wrap"> | |
| 4 | 4 | <template v-if="previewImage"> |
| 5 | - <view | |
| 6 | - class="u-upload__wrap__preview" | |
| 7 | - v-for="(item, index) in lists" | |
| 8 | - :key="index" | |
| 9 | - > | |
| 10 | - <image | |
| 11 | - v-if="item.isImage || (item.type && item.type === 'image')" | |
| 12 | - :src="item.thumb || item.url" | |
| 13 | - :mode="imageMode" | |
| 14 | - class="u-upload__wrap__preview__image" | |
| 15 | - @tap="onPreviewImage(item)" | |
| 16 | - :style="[{ | |
| 5 | + <view class="u-upload__wrap__preview" v-for="(item, index) in lists" :key="index"> | |
| 6 | + <image v-if="item.isImage || (item.type && item.type === 'image')" :src="item.thumb || item.url" | |
| 7 | + :mode="imageMode" class="u-upload__wrap__preview__image" @tap="onPreviewImage(item)" :style="[{ | |
| 17 | 8 | width: $u.addUnit(width), |
| 18 | 9 | height: $u.addUnit(height) |
| 19 | - }]" | |
| 20 | - /> | |
| 21 | - <view | |
| 22 | - v-else | |
| 23 | - class="u-upload__wrap__preview__other" | |
| 24 | - > | |
| 25 | - <u-icon | |
| 26 | - color="#80CBF9" | |
| 27 | - size="26" | |
| 28 | - :name="item.isVideo || (item.type && item.type === 'video') ? 'movie' : 'folder'" | |
| 29 | - ></u-icon> | |
| 30 | - <text class="u-upload__wrap__preview__other__text">{{item.isVideo || (item.type && item.type === 'video') ? '视频' : '文件'}}</text> | |
| 10 | + }]" /> | |
| 11 | + <view v-else class="u-upload__wrap__preview__other"> | |
| 12 | + <u-icon color="#80CBF9" size="26" | |
| 13 | + :name="item.isVideo || (item.type && item.type === 'video') ? 'movie' : 'folder'"></u-icon> | |
| 14 | + <text class="u-upload__wrap__preview__other__text">{{ item.isVideo || (item.type && item.type === 'video') ? | |
| 15 | + '视频' : '文件' }}</text> | |
| 31 | 16 | </view> |
| 32 | - <view | |
| 33 | - class="u-upload__status" | |
| 34 | - v-if="item.status === 'uploading' || item.status === 'failed'" | |
| 35 | - > | |
| 17 | + <view class="u-upload__status" v-if="item.status === 'uploading' || item.status === 'failed'"> | |
| 36 | 18 | <view class="u-upload__status__icon"> |
| 37 | - <u-icon | |
| 38 | - v-if="item.status === 'failed'" | |
| 39 | - name="close-circle" | |
| 40 | - color="#ffffff" | |
| 41 | - size="25" | |
| 42 | - /> | |
| 43 | - <u-loading-icon | |
| 44 | - size="22" | |
| 45 | - mode="circle" | |
| 46 | - color="#ffffff" | |
| 47 | - v-else | |
| 48 | - /> | |
| 19 | + <u-icon v-if="item.status === 'failed'" name="close-circle" color="#ffffff" size="25" /> | |
| 20 | + <u-loading-icon size="22" mode="circle" color="#ffffff" v-else /> | |
| 49 | 21 | </view> |
| 50 | - <text | |
| 51 | - v-if="item.message" | |
| 52 | - class="u-upload__status__message" | |
| 53 | - >{{ item.message }}</text> | |
| 22 | + <text v-if="item.message" class="u-upload__status__message">{{ item.message }}</text> | |
| 54 | 23 | </view> |
| 55 | - <view | |
| 56 | - class="u-upload__deletable" | |
| 57 | - v-if="item.status !== 'uploading' && (deletable || item.deletable)" | |
| 58 | - @tap.stop="deleteItem(index)" | |
| 59 | - > | |
| 24 | + <view class="u-upload__deletable" v-if="item.status !== 'uploading' && (deletable || item.deletable)" | |
| 25 | + @tap.stop="deleteItem(index)"> | |
| 60 | 26 | <view class="u-upload__deletable__icon"> |
| 61 | - <u-icon | |
| 62 | - name="close" | |
| 63 | - color="#ffffff" | |
| 64 | - size="10" | |
| 65 | - ></u-icon> | |
| 27 | + <u-icon name="close" color="#ffffff" size="25"></u-icon> | |
| 66 | 28 | </view> |
| 67 | 29 | </view> |
| 68 | - <view | |
| 69 | - class="u-upload__success" | |
| 70 | - v-if="item.status === 'success'" | |
| 71 | - > | |
| 30 | + <view class="u-upload__success" v-if="item.status === 'success'"> | |
| 72 | 31 | <!-- #ifdef APP-NVUE --> |
| 73 | - <image | |
| 74 | - :src="successIcon" | |
| 75 | - class="u-upload__success__icon" | |
| 76 | - ></image> | |
| 32 | + <image :src="successIcon" class="u-upload__success__icon"></image> | |
| 77 | 33 | <!-- #endif --> |
| 78 | 34 | <!-- #ifndef APP-NVUE --> |
| 79 | 35 | <view class="u-upload__success__icon"> |
| 80 | - <u-icon | |
| 81 | - name="checkmark" | |
| 82 | - color="#ffffff" | |
| 83 | - size="12" | |
| 84 | - ></u-icon> | |
| 36 | + <u-icon name="checkmark" color="#ffffff" size="12"></u-icon> | |
| 85 | 37 | </view> |
| 86 | 38 | <!-- #endif --> |
| 87 | 39 | </view> |
| 88 | 40 | </view> |
| 89 | - | |
| 41 | + | |
| 90 | 42 | </template> |
| 91 | - | |
| 43 | + | |
| 92 | 44 | <template v-if="isInCount"> |
| 93 | - <view | |
| 94 | - v-if="$slots.default || $slots.$default" | |
| 95 | - @tap="chooseFile" | |
| 96 | - > | |
| 45 | + <view v-if="$slots.default || $slots.$default" @tap="chooseFile"> | |
| 97 | 46 | <slot /> |
| 98 | 47 | </view> |
| 99 | - <view | |
| 100 | - v-else | |
| 101 | - class="u-upload__button" | |
| 102 | - :hover-class="!disabled ? 'u-upload__button--hover' : ''" | |
| 103 | - hover-stay-time="150" | |
| 104 | - @tap="chooseFile" | |
| 105 | - :class="[disabled && 'u-upload__button--disabled']" | |
| 106 | - :style="[{ | |
| 48 | + <view v-else class="u-upload__button" :hover-class="!disabled ? 'u-upload__button--hover' : ''" | |
| 49 | + hover-stay-time="150" @tap="chooseFile" :class="[disabled && 'u-upload__button--disabled']" :style="[{ | |
| 107 | 50 | width: $u.addUnit(width), |
| 108 | 51 | height: $u.addUnit(height) |
| 109 | - }]" | |
| 110 | - > | |
| 111 | - <u-icon | |
| 112 | - :name="uploadIcon" | |
| 113 | - size="26" | |
| 114 | - :color="uploadIconColor" | |
| 115 | - ></u-icon> | |
| 116 | - <text | |
| 117 | - v-if="uploadText" | |
| 118 | - class="u-upload__button__text" | |
| 119 | - >{{ uploadText }}</text> | |
| 52 | + }]"> | |
| 53 | + <u-icon :name="uploadIcon" size="26" :color="uploadIconColor"></u-icon> | |
| 54 | + <text v-if="uploadText" class="u-upload__button__text">{{ uploadText }}</text> | |
| 120 | 55 | </view> |
| 121 | 56 | </template> |
| 122 | 57 | </view> |
| ... | ... | @@ -125,440 +60,440 @@ |
| 125 | 60 | </template> |
| 126 | 61 | |
| 127 | 62 | <script> |
| 128 | - import { | |
| 129 | - chooseFile | |
| 130 | - } from './utils'; | |
| 131 | - import mixinUp from './mixin.js'; | |
| 132 | - import props from './props.js'; | |
| 133 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 134 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 63 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 64 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 65 | +import mixinUp from './mixin.js'; | |
| 66 | +import props from './props.js'; | |
| 67 | +import { | |
| 68 | + chooseFile | |
| 69 | +} from './utils'; | |
| 135 | 70 | |
| 136 | - /** | |
| 137 | - * upload 上传 | |
| 138 | - * @description 该组件用于上传图片场景 | |
| 139 | - * @tutorial https://uviewui.com/components/upload.html | |
| 140 | - * @property {String} accept 接受的文件类型, 可选值为all media image file video (默认 'image' ) | |
| 141 | - * @property {String | Array} capture 图片或视频拾取模式,当accept为image类型时设置capture可选额外camera可以直接调起摄像头(默认 ['album', 'camera'] ) | |
| 142 | - * @property {Boolean} compressed 当accept为video时生效,是否压缩视频,默认为true(默认 true ) | |
| 143 | - * @property {String} camera 当accept为video时生效,可选值为back或front(默认 'back' ) | |
| 144 | - * @property {Number} maxDuration 当accept为video时生效,拍摄视频最长拍摄时间,单位秒(默认 60 ) | |
| 145 | - * @property {String} uploadIcon 上传区域的图标,只能内置图标(默认 'camera-fill' ) | |
| 146 | - * @property {String} uploadIconColor 上传区域的图标的字体颜色,只能内置图标(默认 #D3D4D6 ) | |
| 147 | - * @property {Boolean} useBeforeRead 是否开启文件读取前事件(默认 false ) | |
| 148 | - * @property {Boolean} previewFullImage 是否显示组件自带的图片预览功能(默认 true ) | |
| 149 | - * @property {String | Number} maxCount 最大上传数量(默认 52 ) | |
| 150 | - * @property {Boolean} disabled 是否启用(默认 false ) | |
| 151 | - * @property {String} imageMode 预览上传的图片时的裁剪模式,和image组件mode属性一致(默认 'aspectFill' ) | |
| 152 | - * @property {String} name 标识符,可以在回调函数的第二项参数中获取 | |
| 153 | - * @property {Array} sizeType 所选的图片的尺寸, 可选值为original compressed(默认 ['original', 'compressed'] ) | |
| 154 | - * @property {Boolean} multiple 是否开启图片多选,部分安卓机型不支持 (默认 false ) | |
| 155 | - * @property {Boolean} deletable 是否展示删除按钮(默认 true ) | |
| 156 | - * @property {String | Number} maxSize 文件大小限制,单位为byte (默认 Number.MAX_VALUE ) | |
| 157 | - * @property {Array} fileList 显示已上传的文件列表 | |
| 158 | - * @property {String} uploadText 上传区域的提示文字 | |
| 159 | - * @property {String | Number} width 内部预览图片区域和选择图片按钮的区域宽度(默认 80 ) | |
| 160 | - * @property {String | Number} height 内部预览图片区域和选择图片按钮的区域高度(默认 80 ) | |
| 161 | - * @property {Object} customStyle 组件的样式,对象形式 | |
| 162 | - * @event {Function} afterRead 读取后的处理函数 | |
| 163 | - * @event {Function} beforeRead 读取前的处理函数 | |
| 164 | - * @event {Function} oversize 文件超出大小限制 | |
| 165 | - * @event {Function} clickPreview 点击预览图片 | |
| 166 | - * @event {Function} delete 删除图片 | |
| 167 | - * @example <u-upload :action="action" :fileList="fileList" ></u-upload> | |
| 168 | - */ | |
| 169 | - export default { | |
| 170 | - name: "u-upload", | |
| 171 | - mixins: [mpMixin, mixin, mixinUp, props], | |
| 172 | - data() { | |
| 173 | - return { | |
| 174 | - // #ifdef APP-NVUE | |
| 175 | - successIcon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAKKADAAQAAAABAAAAKAAAAAB65masAAACP0lEQVRYCc3YXygsURwH8K/dpcWyG3LF5u/6/+dKVylSypuUl6uUPMifKMWL8oKEB1EUT1KeUPdR3uTNUsSLxb2udG/cbvInNuvf2rVnazZ/ZndmZ87snjM1Z+Z3zpzfp9+Z5mEAhlvjRtZgCKs+gnPAOcAkkMOR4jEHfItjDvgRxxSQD8cM0BuOCaAvXNCBQrigAsXgggYUiwsK0B9cwIH+4gIKlIILGFAqLiBAOTjFgXJxigJp4BQD0sIpAqSJow6kjSNAFTnRaHJwLenD6Mud52VQAcrBfTd2oyq+HtGaGGWAcnAVcXWoM3bCZrdi+ncPfaAcXE5UKVpdW/vitGPqqAtn98d0gXJwX7Qp6MmegUYVhvmTIezdmHlxJCjpHRTCFerLkRRu4k0aqdajN3sWOo0BK//msHa+xDuPC/oNFMKRhTtM4xjIX0SCNpXL4+7VIaHuyiWEp2L7ahWLf8fejfPdqPmC3mJicORZUp1CQzm+GiphvljGk+PBvWRbxii+xVTj5M6CiZ/tsDufvaXyxEUDxeLIyvu3m0iOyEFWVAkydcVYdyFrE9tQk9iMq6f/GNlvwt3LjQfh60LUrw9/cFyyMJUW/XkLSNMV4Mi6C5ML+ui4x5ClAX9sB9w0wV6wglJwJCv5fOxcr6EstgbGiEw4XcfUry4cWrcEUW8n+ARKxXEJHhw2WG43UKSvwI/TSZgvl7kh0b3XLZaLEy0QmMgLZAVH7J+ALOE+AVnDvQOyiPMAWcW5gSzjCPAV+78S5WE0GrQAAAAASUVORK5CYII=', | |
| 176 | - // #endif | |
| 177 | - lists: [], | |
| 178 | - isInCount: true, | |
| 179 | - } | |
| 180 | - }, | |
| 181 | - watch: { | |
| 182 | - // 监听文件列表的变化,重新整理内部数据 | |
| 183 | - fileList: { | |
| 184 | - handler() { | |
| 185 | - this.formatFileList() | |
| 186 | - }, | |
| 187 | - immediate: true, | |
| 188 | - deep: true, | |
| 71 | +/** | |
| 72 | + * upload 上传 | |
| 73 | + * @description 该组件用于上传图片场景 | |
| 74 | + * @tutorial https://uviewui.com/components/upload.html | |
| 75 | + * @property {String} accept 接受的文件类型, 可选值为all media image file video (默认 'image' ) | |
| 76 | + * @property {String | Array} capture 图片或视频拾取模式,当accept为image类型时设置capture可选额外camera可以直接调起摄像头(默认 ['album', 'camera'] ) | |
| 77 | + * @property {Boolean} compressed 当accept为video时生效,是否压缩视频,默认为true(默认 true ) | |
| 78 | + * @property {String} camera 当accept为video时生效,可选值为back或front(默认 'back' ) | |
| 79 | + * @property {Number} maxDuration 当accept为video时生效,拍摄视频最长拍摄时间,单位秒(默认 60 ) | |
| 80 | + * @property {String} uploadIcon 上传区域的图标,只能内置图标(默认 'camera-fill' ) | |
| 81 | + * @property {String} uploadIconColor 上传区域的图标的字体颜色,只能内置图标(默认 #D3D4D6 ) | |
| 82 | + * @property {Boolean} useBeforeRead 是否开启文件读取前事件(默认 false ) | |
| 83 | + * @property {Boolean} previewFullImage 是否显示组件自带的图片预览功能(默认 true ) | |
| 84 | + * @property {String | Number} maxCount 最大上传数量(默认 52 ) | |
| 85 | + * @property {Boolean} disabled 是否启用(默认 false ) | |
| 86 | + * @property {String} imageMode 预览上传的图片时的裁剪模式,和image组件mode属性一致(默认 'aspectFill' ) | |
| 87 | + * @property {String} name 标识符,可以在回调函数的第二项参数中获取 | |
| 88 | + * @property {Array} sizeType 所选的图片的尺寸, 可选值为original compressed(默认 ['original', 'compressed'] ) | |
| 89 | + * @property {Boolean} multiple 是否开启图片多选,部分安卓机型不支持 (默认 false ) | |
| 90 | + * @property {Boolean} deletable 是否展示删除按钮(默认 true ) | |
| 91 | + * @property {String | Number} maxSize 文件大小限制,单位为byte (默认 Number.MAX_VALUE ) | |
| 92 | + * @property {Array} fileList 显示已上传的文件列表 | |
| 93 | + * @property {String} uploadText 上传区域的提示文字 | |
| 94 | + * @property {String | Number} width 内部预览图片区域和选择图片按钮的区域宽度(默认 80 ) | |
| 95 | + * @property {String | Number} height 内部预览图片区域和选择图片按钮的区域高度(默认 80 ) | |
| 96 | + * @property {Object} customStyle 组件的样式,对象形式 | |
| 97 | + * @event {Function} afterRead 读取后的处理函数 | |
| 98 | + * @event {Function} beforeRead 读取前的处理函数 | |
| 99 | + * @event {Function} oversize 文件超出大小限制 | |
| 100 | + * @event {Function} clickPreview 点击预览图片 | |
| 101 | + * @event {Function} delete 删除图片 | |
| 102 | + * @example <u-upload :action="action" :fileList="fileList" ></u-upload> | |
| 103 | + */ | |
| 104 | +export default { | |
| 105 | + name: "u-upload", | |
| 106 | + mixins: [mpMixin, mixin, mixinUp, props], | |
| 107 | + data() { | |
| 108 | + return { | |
| 109 | + // #ifdef APP-NVUE | |
| 110 | + successIcon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAKKADAAQAAAABAAAAKAAAAAB65masAAACP0lEQVRYCc3YXygsURwH8K/dpcWyG3LF5u/6/+dKVylSypuUl6uUPMifKMWL8oKEB1EUT1KeUPdR3uTNUsSLxb2udG/cbvInNuvf2rVnazZ/ZndmZ87snjM1Z+Z3zpzfp9+Z5mEAhlvjRtZgCKs+gnPAOcAkkMOR4jEHfItjDvgRxxSQD8cM0BuOCaAvXNCBQrigAsXgggYUiwsK0B9cwIH+4gIKlIILGFAqLiBAOTjFgXJxigJp4BQD0sIpAqSJow6kjSNAFTnRaHJwLenD6Mud52VQAcrBfTd2oyq+HtGaGGWAcnAVcXWoM3bCZrdi+ncPfaAcXE5UKVpdW/vitGPqqAtn98d0gXJwX7Qp6MmegUYVhvmTIezdmHlxJCjpHRTCFerLkRRu4k0aqdajN3sWOo0BK//msHa+xDuPC/oNFMKRhTtM4xjIX0SCNpXL4+7VIaHuyiWEp2L7ahWLf8fejfPdqPmC3mJicORZUp1CQzm+GiphvljGk+PBvWRbxii+xVTj5M6CiZ/tsDufvaXyxEUDxeLIyvu3m0iOyEFWVAkydcVYdyFrE9tQk9iMq6f/GNlvwt3LjQfh60LUrw9/cFyyMJUW/XkLSNMV4Mi6C5ML+ui4x5ClAX9sB9w0wV6wglJwJCv5fOxcr6EstgbGiEw4XcfUry4cWrcEUW8n+ARKxXEJHhw2WG43UKSvwI/TSZgvl7kh0b3XLZaLEy0QmMgLZAVH7J+ALOE+AVnDvQOyiPMAWcW5gSzjCPAV+78S5WE0GrQAAAAASUVORK5CYII=', | |
| 111 | + // #endif | |
| 112 | + lists: [], | |
| 113 | + isInCount: true, | |
| 114 | + } | |
| 115 | + }, | |
| 116 | + watch: { | |
| 117 | + // 监听文件列表的变化,重新整理内部数据 | |
| 118 | + fileList: { | |
| 119 | + handler() { | |
| 120 | + this.formatFileList() | |
| 189 | 121 | }, |
| 122 | + immediate: true, | |
| 123 | + deep: true, | |
| 190 | 124 | }, |
| 191 | - // #ifdef VUE3 | |
| 192 | - emits: ['error', 'beforeRead', 'oversize', 'afterRead', 'delete', 'clickPreview'], | |
| 193 | - // #endif | |
| 194 | - methods: { | |
| 195 | - formatFileList() { | |
| 196 | - const { | |
| 197 | - fileList = [], maxCount | |
| 198 | - } = this; | |
| 199 | - const lists = fileList.map((item) => | |
| 200 | - Object.assign(Object.assign({}, item), { | |
| 201 | - // 如果item.url为本地选择的blob文件的话,无法判断其为video还是image,此处优先通过accept做判断处理 | |
| 202 | - isImage: this.accept === 'image' || uni.$u.test.image(item.url || item.thumb), | |
| 203 | - isVideo: this.accept === 'video' || uni.$u.test.video(item.url || item.thumb), | |
| 204 | - deletable: typeof(item.deletable) === 'boolean' ? item.deletable : this.deletable, | |
| 205 | - }) | |
| 206 | - ); | |
| 207 | - this.lists = lists | |
| 208 | - this.isInCount = lists.length < maxCount | |
| 209 | - }, | |
| 210 | - chooseFile() { | |
| 211 | - const { | |
| 212 | - maxCount, | |
| 213 | - multiple, | |
| 214 | - lists, | |
| 215 | - disabled | |
| 216 | - } = this; | |
| 217 | - if (disabled) return; | |
| 218 | - // 如果用户传入的是字符串,需要格式化成数组 | |
| 219 | - let capture; | |
| 220 | - try { | |
| 221 | - capture = uni.$u.test.array(this.capture) ? this.capture : this.capture.split(','); | |
| 222 | - }catch(e) { | |
| 223 | - capture = []; | |
| 224 | - } | |
| 225 | - chooseFile( | |
| 226 | - Object.assign({ | |
| 227 | - accept: this.accept, | |
| 228 | - multiple: this.multiple, | |
| 229 | - capture: capture, | |
| 230 | - compressed: this.compressed, | |
| 231 | - maxDuration: this.maxDuration, | |
| 232 | - sizeType: this.sizeType, | |
| 233 | - camera: this.camera, | |
| 234 | - }, { | |
| 235 | - maxCount: maxCount - lists.length, | |
| 125 | + }, | |
| 126 | + // #ifdef VUE3 | |
| 127 | + emits: ['error', 'beforeRead', 'oversize', 'afterRead', 'delete', 'clickPreview'], | |
| 128 | + // #endif | |
| 129 | + methods: { | |
| 130 | + formatFileList() { | |
| 131 | + const { | |
| 132 | + fileList = [], maxCount | |
| 133 | + } = this; | |
| 134 | + const lists = fileList.map((item) => | |
| 135 | + Object.assign(Object.assign({}, item), { | |
| 136 | + // 如果item.url为本地选择的blob文件的话,无法判断其为video还是image,此处优先通过accept做判断处理 | |
| 137 | + isImage: this.accept === 'image' || uni.$u.test.image(item.url || item.thumb), | |
| 138 | + isVideo: this.accept === 'video' || uni.$u.test.video(item.url || item.thumb), | |
| 139 | + deletable: typeof (item.deletable) === 'boolean' ? item.deletable : this.deletable, | |
| 140 | + }) | |
| 141 | + ); | |
| 142 | + this.lists = lists | |
| 143 | + this.isInCount = lists.length < maxCount | |
| 144 | + }, | |
| 145 | + chooseFile() { | |
| 146 | + const { | |
| 147 | + maxCount, | |
| 148 | + multiple, | |
| 149 | + lists, | |
| 150 | + disabled | |
| 151 | + } = this; | |
| 152 | + if (disabled) return; | |
| 153 | + // 如果用户传入的是字符串,需要格式化成数组 | |
| 154 | + let capture; | |
| 155 | + try { | |
| 156 | + capture = uni.$u.test.array(this.capture) ? this.capture : this.capture.split(','); | |
| 157 | + } catch (e) { | |
| 158 | + capture = []; | |
| 159 | + } | |
| 160 | + chooseFile( | |
| 161 | + Object.assign({ | |
| 162 | + accept: this.accept, | |
| 163 | + multiple: this.multiple, | |
| 164 | + capture: capture, | |
| 165 | + compressed: this.compressed, | |
| 166 | + maxDuration: this.maxDuration, | |
| 167 | + sizeType: this.sizeType, | |
| 168 | + camera: this.camera, | |
| 169 | + }, { | |
| 170 | + maxCount: maxCount - lists.length, | |
| 171 | + }) | |
| 172 | + ) | |
| 173 | + .then((res) => { | |
| 174 | + this.onBeforeRead(multiple ? res : res[0]); | |
| 175 | + }) | |
| 176 | + .catch((error) => { | |
| 177 | + this.$emit('error', error); | |
| 178 | + }); | |
| 179 | + }, | |
| 180 | + // 文件读取之前 | |
| 181 | + onBeforeRead(file) { | |
| 182 | + const { | |
| 183 | + beforeRead, | |
| 184 | + useBeforeRead, | |
| 185 | + } = this; | |
| 186 | + let res = true | |
| 187 | + // beforeRead是否为一个方法 | |
| 188 | + if (uni.$u.test.func(beforeRead)) { | |
| 189 | + // 如果用户定义了此方法,则去执行此方法,并传入读取的文件回调 | |
| 190 | + res = beforeRead(file, this.getDetail()); | |
| 191 | + } | |
| 192 | + if (useBeforeRead) { | |
| 193 | + res = new Promise((resolve, reject) => { | |
| 194 | + this.$emit( | |
| 195 | + 'beforeRead', | |
| 196 | + Object.assign(Object.assign({ | |
| 197 | + file | |
| 198 | + }, this.getDetail()), { | |
| 199 | + callback: (ok) => { | |
| 200 | + ok ? resolve() : reject(); | |
| 201 | + }, | |
| 236 | 202 | }) |
| 237 | - ) | |
| 238 | - .then((res) => { | |
| 239 | - this.onBeforeRead(multiple ? res : res[0]); | |
| 240 | - }) | |
| 241 | - .catch((error) => { | |
| 242 | - this.$emit('error', error); | |
| 243 | - }); | |
| 244 | - }, | |
| 245 | - // 文件读取之前 | |
| 246 | - onBeforeRead(file) { | |
| 247 | - const { | |
| 248 | - beforeRead, | |
| 249 | - useBeforeRead, | |
| 250 | - } = this; | |
| 251 | - let res = true | |
| 252 | - // beforeRead是否为一个方法 | |
| 253 | - if (uni.$u.test.func(beforeRead)) { | |
| 254 | - // 如果用户定义了此方法,则去执行此方法,并传入读取的文件回调 | |
| 255 | - res = beforeRead(file, this.getDetail()); | |
| 256 | - } | |
| 257 | - if (useBeforeRead) { | |
| 258 | - res = new Promise((resolve, reject) => { | |
| 259 | - this.$emit( | |
| 260 | - 'beforeRead', | |
| 261 | - Object.assign(Object.assign({ | |
| 262 | - file | |
| 263 | - }, this.getDetail()), { | |
| 264 | - callback: (ok) => { | |
| 265 | - ok ? resolve() : reject(); | |
| 266 | - }, | |
| 267 | - }) | |
| 268 | - ); | |
| 269 | - }); | |
| 270 | - } | |
| 271 | - if (!res) { | |
| 272 | - return; | |
| 273 | - } | |
| 274 | - if (uni.$u.test.promise(res)) { | |
| 275 | - res.then((data) => this.onAfterRead(data || file)); | |
| 276 | - } else { | |
| 277 | - this.onAfterRead(file); | |
| 278 | - } | |
| 279 | - }, | |
| 280 | - getDetail(index) { | |
| 281 | - return { | |
| 282 | - name: this.name, | |
| 283 | - index: index == null ? this.fileList.length : index, | |
| 284 | - }; | |
| 285 | - }, | |
| 286 | - onAfterRead(file) { | |
| 287 | - const { | |
| 288 | - maxSize, | |
| 289 | - afterRead | |
| 290 | - } = this; | |
| 291 | - const oversize = Array.isArray(file) ? | |
| 292 | - file.some((item) => item.size > maxSize) : | |
| 293 | - file.size > maxSize; | |
| 294 | - if (oversize) { | |
| 295 | - this.$emit('oversize', Object.assign({ | |
| 296 | - file | |
| 297 | - }, this.getDetail())); | |
| 298 | - return; | |
| 299 | - } | |
| 300 | - if (typeof afterRead === 'function') { | |
| 301 | - afterRead(file, this.getDetail()); | |
| 302 | - } | |
| 303 | - this.$emit('afterRead', Object.assign({ | |
| 203 | + ); | |
| 204 | + }); | |
| 205 | + } | |
| 206 | + if (!res) { | |
| 207 | + return; | |
| 208 | + } | |
| 209 | + if (uni.$u.test.promise(res)) { | |
| 210 | + res.then((data) => this.onAfterRead(data || file)); | |
| 211 | + } else { | |
| 212 | + this.onAfterRead(file); | |
| 213 | + } | |
| 214 | + }, | |
| 215 | + getDetail(index) { | |
| 216 | + return { | |
| 217 | + name: this.name, | |
| 218 | + index: index == null ? this.fileList.length : index, | |
| 219 | + }; | |
| 220 | + }, | |
| 221 | + onAfterRead(file) { | |
| 222 | + const { | |
| 223 | + maxSize, | |
| 224 | + afterRead | |
| 225 | + } = this; | |
| 226 | + const oversize = Array.isArray(file) ? | |
| 227 | + file.some((item) => item.size > maxSize) : | |
| 228 | + file.size > maxSize; | |
| 229 | + if (oversize) { | |
| 230 | + this.$emit('oversize', Object.assign({ | |
| 304 | 231 | file |
| 305 | 232 | }, this.getDetail())); |
| 306 | - }, | |
| 307 | - deleteItem(index) { | |
| 308 | - this.$emit( | |
| 309 | - 'delete', | |
| 310 | - Object.assign(Object.assign({}, this.getDetail(index)), { | |
| 311 | - file: this.fileList[index], | |
| 312 | - }) | |
| 313 | - ); | |
| 314 | - }, | |
| 315 | - // 预览图片 | |
| 316 | - onPreviewImage(item) { | |
| 317 | - if (!item.isImage || !this.previewFullImage) return | |
| 318 | - uni.previewImage({ | |
| 319 | - // 先filter找出为图片的item,再返回filter结果中的图片url | |
| 320 | - urls: this.lists.filter((item) => this.accept === 'image' || uni.$u.test.image(item.url || item.thumb)).map((item) => item.url || item.thumb), | |
| 321 | - current: item.url || item.thumb, | |
| 322 | - fail() { | |
| 323 | - uni.$u.toast('预览图片失败') | |
| 324 | - }, | |
| 325 | - }); | |
| 326 | - }, | |
| 327 | - onPreviewVideo(event) { | |
| 328 | - if (!this.data.previewFullImage) return; | |
| 329 | - const { | |
| 330 | - index | |
| 331 | - } = event.currentTarget.dataset; | |
| 332 | - const { | |
| 333 | - lists | |
| 334 | - } = this.data; | |
| 335 | - wx.previewMedia({ | |
| 336 | - sources: lists | |
| 337 | - .filter((item) => isVideoFile(item)) | |
| 338 | - .map((item) => | |
| 339 | - Object.assign(Object.assign({}, item), { | |
| 340 | - type: 'video' | |
| 341 | - }) | |
| 342 | - ), | |
| 343 | - current: index, | |
| 344 | - fail() { | |
| 345 | - uni.$u.toast('预览视频失败') | |
| 346 | - }, | |
| 347 | - }); | |
| 348 | - }, | |
| 349 | - onClickPreview(event) { | |
| 350 | - const { | |
| 351 | - index | |
| 352 | - } = event.currentTarget.dataset; | |
| 353 | - const item = this.data.lists[index]; | |
| 354 | - this.$emit( | |
| 355 | - 'clickPreview', | |
| 356 | - Object.assign(Object.assign({}, item), this.getDetail(index)) | |
| 357 | - ); | |
| 233 | + return; | |
| 234 | + } | |
| 235 | + if (typeof afterRead === 'function') { | |
| 236 | + afterRead(file, this.getDetail()); | |
| 358 | 237 | } |
| 238 | + this.$emit('afterRead', Object.assign({ | |
| 239 | + file | |
| 240 | + }, this.getDetail())); | |
| 241 | + }, | |
| 242 | + deleteItem(index) { | |
| 243 | + this.$emit( | |
| 244 | + 'delete', | |
| 245 | + Object.assign(Object.assign({}, this.getDetail(index)), { | |
| 246 | + file: this.fileList[index], | |
| 247 | + }) | |
| 248 | + ); | |
| 249 | + }, | |
| 250 | + // 预览图片 | |
| 251 | + onPreviewImage(item) { | |
| 252 | + if (!item.isImage || !this.previewFullImage) return | |
| 253 | + uni.previewImage({ | |
| 254 | + // 先filter找出为图片的item,再返回filter结果中的图片url | |
| 255 | + urls: this.lists.filter((item) => this.accept === 'image' || uni.$u.test.image(item.url || item.thumb)).map((item) => item.url || item.thumb), | |
| 256 | + current: item.url || item.thumb, | |
| 257 | + fail() { | |
| 258 | + uni.$u.toast('预览图片失败') | |
| 259 | + }, | |
| 260 | + }); | |
| 261 | + }, | |
| 262 | + onPreviewVideo(event) { | |
| 263 | + if (!this.data.previewFullImage) return; | |
| 264 | + const { | |
| 265 | + index | |
| 266 | + } = event.currentTarget.dataset; | |
| 267 | + const { | |
| 268 | + lists | |
| 269 | + } = this.data; | |
| 270 | + wx.previewMedia({ | |
| 271 | + sources: lists | |
| 272 | + .filter((item) => isVideoFile(item)) | |
| 273 | + .map((item) => | |
| 274 | + Object.assign(Object.assign({}, item), { | |
| 275 | + type: 'video' | |
| 276 | + }) | |
| 277 | + ), | |
| 278 | + current: index, | |
| 279 | + fail() { | |
| 280 | + uni.$u.toast('预览视频失败') | |
| 281 | + }, | |
| 282 | + }); | |
| 283 | + }, | |
| 284 | + onClickPreview(event) { | |
| 285 | + const { | |
| 286 | + index | |
| 287 | + } = event.currentTarget.dataset; | |
| 288 | + const item = this.data.lists[index]; | |
| 289 | + this.$emit( | |
| 290 | + 'clickPreview', | |
| 291 | + Object.assign(Object.assign({}, item), this.getDetail(index)) | |
| 292 | + ); | |
| 359 | 293 | } |
| 360 | 294 | } |
| 295 | +} | |
| 361 | 296 | </script> |
| 362 | 297 | |
| 363 | 298 | <style lang="scss" scoped> |
| 364 | - @import '../../libs/css/components.scss'; | |
| 365 | - $u-upload-preview-border-radius: 2px !default; | |
| 366 | - $u-upload-preview-margin: 0 8px 8px 0 !default; | |
| 367 | - $u-upload-image-width:80px !default; | |
| 368 | - $u-upload-image-height:$u-upload-image-width; | |
| 369 | - $u-upload-other-bgColor: rgb(242, 242, 242) !default; | |
| 370 | - $u-upload-other-flex:1 !default; | |
| 371 | - $u-upload-text-font-size:11px !default; | |
| 372 | - $u-upload-text-color:$u-tips-color !default; | |
| 373 | - $u-upload-text-margin-top:2px !default; | |
| 374 | - $u-upload-deletable-right:0 !default; | |
| 375 | - $u-upload-deletable-top:0 !default; | |
| 376 | - $u-upload-deletable-bgColor:rgb(55, 55, 55) !default; | |
| 377 | - $u-upload-deletable-height:14px !default; | |
| 378 | - $u-upload-deletable-width:$u-upload-deletable-height; | |
| 379 | - $u-upload-deletable-boder-bottom-left-radius:100px !default; | |
| 380 | - $u-upload-deletable-zIndex:3 !default; | |
| 381 | - $u-upload-success-bottom:0 !default; | |
| 382 | - $u-upload-success-right:0 !default; | |
| 383 | - $u-upload-success-border-style:solid !default; | |
| 384 | - $u-upload-success-border-top-color:transparent !default; | |
| 385 | - $u-upload-success-border-left-color:transparent !default; | |
| 386 | - $u-upload-success-border-bottom-color: $u-success !default; | |
| 387 | - $u-upload-success-border-right-color:$u-upload-success-border-bottom-color; | |
| 388 | - $u-upload-success-border-width:9px !default; | |
| 389 | - $u-upload-icon-top:0px !default; | |
| 390 | - $u-upload-icon-right:0px !default; | |
| 391 | - $u-upload-icon-h5-top:1px !default; | |
| 392 | - $u-upload-icon-h5-right:0 !default; | |
| 393 | - $u-upload-icon-width:16px !default; | |
| 394 | - $u-upload-icon-height:$u-upload-icon-width; | |
| 395 | - $u-upload-success-icon-bottom:-10px !default; | |
| 396 | - $u-upload-success-icon-right:-10px !default; | |
| 397 | - $u-upload-status-right:0 !default; | |
| 398 | - $u-upload-status-left:0 !default; | |
| 399 | - $u-upload-status-bottom:0 !default; | |
| 400 | - $u-upload-status-top:0 !default; | |
| 401 | - $u-upload-status-bgColor:rgba(0, 0, 0, 0.5) !default; | |
| 402 | - $u-upload-status-icon-Zindex:1 !default; | |
| 403 | - $u-upload-message-font-size:12px !default; | |
| 404 | - $u-upload-message-color:#FFFFFF !default; | |
| 405 | - $u-upload-message-margin-top:5px !default; | |
| 406 | - $u-upload-button-width:80px !default; | |
| 407 | - $u-upload-button-height:$u-upload-button-width; | |
| 408 | - $u-upload-button-bgColor:rgb(244, 245, 247) !default; | |
| 409 | - $u-upload-button-border-radius:2px !default; | |
| 410 | - $u-upload-botton-margin: 0 8px 8px 0 !default; | |
| 411 | - $u-upload-text-font-size:11px !default; | |
| 412 | - $u-upload-text-color:$u-tips-color !default; | |
| 413 | - $u-upload-text-margin-top: 2px !default; | |
| 414 | - $u-upload-hover-bgColor:rgb(230, 231, 233) !default; | |
| 415 | - $u-upload-disabled-opacity:.5 !default; | |
| 299 | +@import '../../libs/css/components.scss'; | |
| 300 | +$u-upload-preview-border-radius: 2px !default; | |
| 301 | +$u-upload-preview-margin: 0 8px 8px 0 !default; | |
| 302 | +$u-upload-image-width: 80px !default; | |
| 303 | +$u-upload-image-height: $u-upload-image-width; | |
| 304 | +$u-upload-other-bgColor: rgb(242, 242, 242) !default; | |
| 305 | +$u-upload-other-flex: 1 !default; | |
| 306 | +$u-upload-text-font-size: 11px !default; | |
| 307 | +$u-upload-text-color: $u-tips-color !default; | |
| 308 | +$u-upload-text-margin-top: 2px !default; | |
| 309 | +$u-upload-deletable-right: 0 !default; | |
| 310 | +$u-upload-deletable-top: 0 !default; | |
| 311 | +$u-upload-deletable-bgColor: rgb(55, 55, 55) !default; | |
| 312 | +$u-upload-deletable-height: 14px !default; | |
| 313 | +$u-upload-deletable-width: $u-upload-deletable-height; | |
| 314 | +$u-upload-deletable-boder-bottom-left-radius: 100px !default; | |
| 315 | +$u-upload-deletable-zIndex: 3 !default; | |
| 316 | +$u-upload-success-bottom: 0 !default; | |
| 317 | +$u-upload-success-right: 0 !default; | |
| 318 | +$u-upload-success-border-style: solid !default; | |
| 319 | +$u-upload-success-border-top-color: transparent !default; | |
| 320 | +$u-upload-success-border-left-color: transparent !default; | |
| 321 | +$u-upload-success-border-bottom-color: $u-success !default; | |
| 322 | +$u-upload-success-border-right-color: $u-upload-success-border-bottom-color; | |
| 323 | +$u-upload-success-border-width: 9px !default; | |
| 324 | +$u-upload-icon-top: 0px !default; | |
| 325 | +$u-upload-icon-right: 0px !default; | |
| 326 | +$u-upload-icon-h5-top: 1px !default; | |
| 327 | +$u-upload-icon-h5-right: 0 !default; | |
| 328 | +$u-upload-icon-width: 16px !default; | |
| 329 | +$u-upload-icon-height: $u-upload-icon-width; | |
| 330 | +$u-upload-success-icon-bottom: -10px !default; | |
| 331 | +$u-upload-success-icon-right: -10px !default; | |
| 332 | +$u-upload-status-right: 0 !default; | |
| 333 | +$u-upload-status-left: 0 !default; | |
| 334 | +$u-upload-status-bottom: 0 !default; | |
| 335 | +$u-upload-status-top: 0 !default; | |
| 336 | +$u-upload-status-bgColor: rgba(0, 0, 0, 0.5) !default; | |
| 337 | +$u-upload-status-icon-Zindex: 1 !default; | |
| 338 | +$u-upload-message-font-size: 12px !default; | |
| 339 | +$u-upload-message-color: #FFFFFF !default; | |
| 340 | +$u-upload-message-margin-top: 5px !default; | |
| 341 | +$u-upload-button-width: 80px !default; | |
| 342 | +$u-upload-button-height: $u-upload-button-width; | |
| 343 | +$u-upload-button-bgColor: rgb(244, 245, 247) !default; | |
| 344 | +$u-upload-button-border-radius: 2px !default; | |
| 345 | +$u-upload-botton-margin: 0 8px 8px 0 !default; | |
| 346 | +$u-upload-text-font-size: 11px !default; | |
| 347 | +$u-upload-text-color: $u-tips-color !default; | |
| 348 | +$u-upload-text-margin-top: 2px !default; | |
| 349 | +$u-upload-hover-bgColor: rgb(230, 231, 233) !default; | |
| 350 | +$u-upload-disabled-opacity: .5 !default; | |
| 416 | 351 | |
| 417 | - .u-upload { | |
| 418 | - @include flex(column); | |
| 352 | +.u-upload { | |
| 353 | + @include flex(column); | |
| 354 | + flex: 1; | |
| 355 | + | |
| 356 | + &__wrap { | |
| 357 | + @include flex; | |
| 358 | + flex-wrap: wrap; | |
| 419 | 359 | flex: 1; |
| 420 | 360 | |
| 421 | - &__wrap { | |
| 361 | + &__preview { | |
| 362 | + border-radius: $u-upload-preview-border-radius; | |
| 363 | + margin: $u-upload-preview-margin; | |
| 364 | + position: relative; | |
| 365 | + overflow: hidden; | |
| 422 | 366 | @include flex; |
| 423 | - flex-wrap: wrap; | |
| 424 | - flex: 1; | |
| 425 | - | |
| 426 | - &__preview { | |
| 427 | - border-radius: $u-upload-preview-border-radius; | |
| 428 | - margin: $u-upload-preview-margin; | |
| 429 | - position: relative; | |
| 430 | - overflow: hidden; | |
| 431 | - @include flex; | |
| 432 | 367 | |
| 433 | - &__image { | |
| 434 | - width: $u-upload-image-width; | |
| 435 | - height: $u-upload-image-height; | |
| 436 | - } | |
| 368 | + &__image { | |
| 369 | + width: $u-upload-image-width; | |
| 370 | + height: $u-upload-image-height; | |
| 371 | + } | |
| 437 | 372 | |
| 438 | - &__other { | |
| 439 | - width: $u-upload-image-width; | |
| 440 | - height: $u-upload-image-height; | |
| 441 | - background-color: $u-upload-other-bgColor; | |
| 442 | - flex: $u-upload-other-flex; | |
| 443 | - @include flex(column); | |
| 444 | - justify-content: center; | |
| 445 | - align-items: center; | |
| 373 | + &__other { | |
| 374 | + width: $u-upload-image-width; | |
| 375 | + height: $u-upload-image-height; | |
| 376 | + background-color: $u-upload-other-bgColor; | |
| 377 | + flex: $u-upload-other-flex; | |
| 378 | + @include flex(column); | |
| 379 | + justify-content: center; | |
| 380 | + align-items: center; | |
| 446 | 381 | |
| 447 | - &__text { | |
| 448 | - font-size: $u-upload-text-font-size; | |
| 449 | - color: $u-upload-text-color; | |
| 450 | - margin-top: $u-upload-text-margin-top; | |
| 451 | - } | |
| 382 | + &__text { | |
| 383 | + font-size: $u-upload-text-font-size; | |
| 384 | + color: $u-upload-text-color; | |
| 385 | + margin-top: $u-upload-text-margin-top; | |
| 452 | 386 | } |
| 453 | 387 | } |
| 454 | 388 | } |
| 389 | + } | |
| 455 | 390 | |
| 456 | - &__deletable { | |
| 457 | - position: absolute; | |
| 458 | - top: $u-upload-deletable-top; | |
| 459 | - right: $u-upload-deletable-right; | |
| 460 | - background-color: $u-upload-deletable-bgColor; | |
| 461 | - height: $u-upload-deletable-height; | |
| 462 | - width: $u-upload-deletable-width; | |
| 463 | - @include flex; | |
| 464 | - border-bottom-left-radius: $u-upload-deletable-boder-bottom-left-radius; | |
| 465 | - align-items: center; | |
| 466 | - justify-content: center; | |
| 467 | - z-index: $u-upload-deletable-zIndex; | |
| 391 | + &__deletable { | |
| 392 | + position: absolute; | |
| 393 | + top: $u-upload-deletable-top; | |
| 394 | + right: $u-upload-deletable-right; | |
| 395 | + background-color: $u-upload-deletable-bgColor; | |
| 396 | + height: $u-upload-deletable-height; | |
| 397 | + width: $u-upload-deletable-width; | |
| 398 | + @include flex; | |
| 399 | + border-bottom-left-radius: $u-upload-deletable-boder-bottom-left-radius; | |
| 400 | + align-items: center; | |
| 401 | + justify-content: center; | |
| 402 | + z-index: $u-upload-deletable-zIndex; | |
| 468 | 403 | |
| 469 | - &__icon { | |
| 470 | - position: absolute; | |
| 471 | - transform: scale(0.7); | |
| 472 | - top: $u-upload-icon-top; | |
| 473 | - right: $u-upload-icon-right; | |
| 474 | - /* #ifdef H5 */ | |
| 475 | - top: $u-upload-icon-h5-top; | |
| 476 | - right: $u-upload-icon-h5-right; | |
| 477 | - /* #endif */ | |
| 478 | - } | |
| 404 | + &__icon { | |
| 405 | + position: absolute; | |
| 406 | + transform: scale(0.7); | |
| 407 | + top: $u-upload-icon-top; | |
| 408 | + right: $u-upload-icon-right; | |
| 409 | + /* #ifdef H5 */ | |
| 410 | + top: $u-upload-icon-h5-top; | |
| 411 | + right: $u-upload-icon-h5-right; | |
| 412 | + /* #endif */ | |
| 479 | 413 | } |
| 414 | + } | |
| 480 | 415 | |
| 481 | - &__success { | |
| 482 | - position: absolute; | |
| 483 | - bottom: $u-upload-success-bottom; | |
| 484 | - right: $u-upload-success-right; | |
| 485 | - @include flex; | |
| 486 | - // 由于weex(nvue)为阿里巴巴的KPI(部门业绩考核)的laji产物,不支持css绘制三角形 | |
| 487 | - // 所以在nvue下使用图片,非nvue下使用css实现 | |
| 416 | + &__success { | |
| 417 | + position: absolute; | |
| 418 | + bottom: $u-upload-success-bottom; | |
| 419 | + right: $u-upload-success-right; | |
| 420 | + @include flex; | |
| 421 | + // 由于weex(nvue)为阿里巴巴的KPI(部门业绩考核)的laji产物,不支持css绘制三角形 | |
| 422 | + // 所以在nvue下使用图片,非nvue下使用css实现 | |
| 423 | + /* #ifndef APP-NVUE */ | |
| 424 | + border-style: $u-upload-success-border-style; | |
| 425 | + border-top-color: $u-upload-success-border-top-color; | |
| 426 | + border-left-color: $u-upload-success-border-left-color; | |
| 427 | + border-bottom-color: $u-upload-success-border-bottom-color; | |
| 428 | + border-right-color: $u-upload-success-border-right-color; | |
| 429 | + border-width: $u-upload-success-border-width; | |
| 430 | + align-items: center; | |
| 431 | + justify-content: center; | |
| 432 | + /* #endif */ | |
| 433 | + | |
| 434 | + &__icon { | |
| 488 | 435 | /* #ifndef APP-NVUE */ |
| 489 | - border-style: $u-upload-success-border-style; | |
| 490 | - border-top-color: $u-upload-success-border-top-color; | |
| 491 | - border-left-color: $u-upload-success-border-left-color; | |
| 492 | - border-bottom-color: $u-upload-success-border-bottom-color; | |
| 493 | - border-right-color: $u-upload-success-border-right-color; | |
| 494 | - border-width: $u-upload-success-border-width; | |
| 495 | - align-items: center; | |
| 496 | - justify-content: center; | |
| 436 | + position: absolute; | |
| 437 | + transform: scale(0.7); | |
| 438 | + bottom: $u-upload-success-icon-bottom; | |
| 439 | + right: $u-upload-success-icon-right; | |
| 440 | + /* #endif */ | |
| 441 | + /* #ifdef APP-NVUE */ | |
| 442 | + width: $u-upload-icon-width; | |
| 443 | + height: $u-upload-icon-height; | |
| 497 | 444 | /* #endif */ |
| 498 | - | |
| 499 | - &__icon { | |
| 500 | - /* #ifndef APP-NVUE */ | |
| 501 | - position: absolute; | |
| 502 | - transform: scale(0.7); | |
| 503 | - bottom: $u-upload-success-icon-bottom; | |
| 504 | - right: $u-upload-success-icon-right; | |
| 505 | - /* #endif */ | |
| 506 | - /* #ifdef APP-NVUE */ | |
| 507 | - width: $u-upload-icon-width; | |
| 508 | - height: $u-upload-icon-height; | |
| 509 | - /* #endif */ | |
| 510 | - } | |
| 511 | 445 | } |
| 446 | + } | |
| 512 | 447 | |
| 513 | - &__status { | |
| 514 | - position: absolute; | |
| 515 | - top: $u-upload-status-top; | |
| 516 | - bottom: $u-upload-status-bottom; | |
| 517 | - left: $u-upload-status-left; | |
| 518 | - right: $u-upload-status-right; | |
| 519 | - background-color: $u-upload-status-bgColor; | |
| 520 | - @include flex(column); | |
| 521 | - align-items: center; | |
| 522 | - justify-content: center; | |
| 448 | + &__status { | |
| 449 | + position: absolute; | |
| 450 | + top: $u-upload-status-top; | |
| 451 | + bottom: $u-upload-status-bottom; | |
| 452 | + left: $u-upload-status-left; | |
| 453 | + right: $u-upload-status-right; | |
| 454 | + background-color: $u-upload-status-bgColor; | |
| 455 | + @include flex(column); | |
| 456 | + align-items: center; | |
| 457 | + justify-content: center; | |
| 523 | 458 | |
| 524 | - &__icon { | |
| 525 | - position: relative; | |
| 526 | - z-index: $u-upload-status-icon-Zindex; | |
| 527 | - } | |
| 459 | + &__icon { | |
| 460 | + position: relative; | |
| 461 | + z-index: $u-upload-status-icon-Zindex; | |
| 462 | + } | |
| 528 | 463 | |
| 529 | - &__message { | |
| 530 | - font-size: $u-upload-message-font-size; | |
| 531 | - color: $u-upload-message-color; | |
| 532 | - margin-top: $u-upload-message-margin-top; | |
| 533 | - } | |
| 464 | + &__message { | |
| 465 | + font-size: $u-upload-message-font-size; | |
| 466 | + color: $u-upload-message-color; | |
| 467 | + margin-top: $u-upload-message-margin-top; | |
| 534 | 468 | } |
| 469 | + } | |
| 535 | 470 | |
| 536 | - &__button { | |
| 537 | - @include flex(column); | |
| 538 | - align-items: center; | |
| 539 | - justify-content: center; | |
| 540 | - width: $u-upload-button-width; | |
| 541 | - height: $u-upload-button-height; | |
| 542 | - background-color: $u-upload-button-bgColor; | |
| 543 | - border-radius: $u-upload-button-border-radius; | |
| 544 | - margin: $u-upload-botton-margin; | |
| 545 | - /* #ifndef APP-NVUE */ | |
| 546 | - box-sizing: border-box; | |
| 547 | - /* #endif */ | |
| 471 | + &__button { | |
| 472 | + @include flex(column); | |
| 473 | + align-items: center; | |
| 474 | + justify-content: center; | |
| 475 | + width: $u-upload-button-width; | |
| 476 | + height: $u-upload-button-height; | |
| 477 | + background-color: $u-upload-button-bgColor; | |
| 478 | + border-radius: $u-upload-button-border-radius; | |
| 479 | + margin: $u-upload-botton-margin; | |
| 480 | + /* #ifndef APP-NVUE */ | |
| 481 | + box-sizing: border-box; | |
| 482 | + /* #endif */ | |
| 548 | 483 | |
| 549 | - &__text { | |
| 550 | - font-size: $u-upload-text-font-size; | |
| 551 | - color: $u-upload-text-color; | |
| 552 | - margin-top: $u-upload-text-margin-top; | |
| 553 | - } | |
| 484 | + &__text { | |
| 485 | + font-size: $u-upload-text-font-size; | |
| 486 | + color: $u-upload-text-color; | |
| 487 | + margin-top: $u-upload-text-margin-top; | |
| 488 | + } | |
| 554 | 489 | |
| 555 | - &--hover { | |
| 556 | - background-color: $u-upload-hover-bgColor; | |
| 557 | - } | |
| 490 | + &--hover { | |
| 491 | + background-color: $u-upload-hover-bgColor; | |
| 492 | + } | |
| 558 | 493 | |
| 559 | - &--disabled { | |
| 560 | - opacity: $u-upload-disabled-opacity; | |
| 561 | - } | |
| 494 | + &--disabled { | |
| 495 | + opacity: $u-upload-disabled-opacity; | |
| 562 | 496 | } |
| 563 | 497 | } |
| 498 | +} | |
| 564 | 499 | </style> | ... | ... |
garbage-removal/src/z-paging/changelog.md
0 → 100644
| 1 | +## 2.6.2(2023-10-31) | |
| 2 | +1.`修复` 在源码中有异常字符导致的在vue3中编译报错的问题。 | |
| 3 | +2.`修复` 在微信小程序中`z-paging-refresh`的height无效的问题(by xiaohe0601)。 | |
| 4 | +近期更新: | |
| 5 | +============================= | |
| 6 | +1.`新增` 手动更新自定义下拉刷新view高度方法。 | |
| 7 | +2.`新增` 点击返回顶部按钮添加事件监听&支持拦截。 | |
| 8 | +3.`新增` 是否开启下拉刷新状态栏占位,适用于隐藏导航栏时,下拉刷新需要避开状态栏高度的情况。 | |
| 9 | +4.`新增` 支持配置网络请求失败触发`reject`。 | |
| 10 | +5.`修复` 显示空数据图时,滚动到底部依然可以加载更多的问题。 | |
| 11 | +6.`修复` 在vue2中底部加载更多相关`slot`使用`template`插入无效的问题。 | |
| 12 | +7.`修复` `complete`的`Promise`可能无效的问题。 | |
| 13 | +8.`优化` `hooks`判断`z-paging`为空则不调用。 | |
| 14 | + | |
| 15 | + | |
| 16 | + | ... | ... |
garbage-removal/src/z-paging/package.json
0 → 100644
| 1 | +{ | |
| 2 | + "id": "z-paging", | |
| 3 | + "name": "z-paging", | |
| 4 | + "displayName": "【z-paging下拉刷新、上拉加载】高性能,全平台兼容。支持虚拟列表,支持nvue、vue3", | |
| 5 | + "version": "2.6.2", | |
| 6 | + "description": "超简单、低耦合!使用wxs+renderjs实现。支持长列表优化,支持自定义下拉刷新、上拉加载更多,支持自动管理空数据图、点击返回顶部,支持聊天分页、本地分页,支持国际化等100+项配置", | |
| 7 | + "keywords": [ | |
| 8 | + "下拉刷新", | |
| 9 | + "上拉加载", | |
| 10 | + "分页器", | |
| 11 | + "nvue", | |
| 12 | + "虚拟列表" | |
| 13 | +], | |
| 14 | + "repository": "https://github.com/SmileZXLee/uni-z-paging", | |
| 15 | + "engines": { | |
| 16 | + "HBuilderX": "^3.0.7" | |
| 17 | + }, | |
| 18 | +"dcloudext": { | |
| 19 | + "sale": { | |
| 20 | + "regular": { | |
| 21 | + "price": "0.00" | |
| 22 | + }, | |
| 23 | + "sourcecode": { | |
| 24 | + "price": "0.00" | |
| 25 | + } | |
| 26 | + }, | |
| 27 | + "contact": { | |
| 28 | + "qq": "393727164" | |
| 29 | + }, | |
| 30 | + "declaration": { | |
| 31 | + "ads": "无", | |
| 32 | + "data": "无", | |
| 33 | + "permissions": "无" | |
| 34 | + }, | |
| 35 | + "npmurl": "https://www.npmjs.com/package/z-paging", | |
| 36 | + "type": "component-vue" | |
| 37 | + }, | |
| 38 | + "uni_modules": { | |
| 39 | + "dependencies": [], | |
| 40 | + "encrypt": [], | |
| 41 | + "platforms": { | |
| 42 | + "cloud": { | |
| 43 | + "tcb": "y", | |
| 44 | + "aliyun": "y" | |
| 45 | + }, | |
| 46 | + "client": { | |
| 47 | + "App": { | |
| 48 | + "app-vue": "y", | |
| 49 | + "app-nvue": "y" | |
| 50 | + }, | |
| 51 | + "H5-mobile": { | |
| 52 | + "Safari": "y", | |
| 53 | + "Android Browser": "y", | |
| 54 | + "微信浏览器(Android)": "y", | |
| 55 | + "QQ浏览器(Android)": "y" | |
| 56 | + }, | |
| 57 | + "H5-pc": { | |
| 58 | + "Chrome": "y", | |
| 59 | + "IE": "y", | |
| 60 | + "Edge": "y", | |
| 61 | + "Firefox": "y", | |
| 62 | + "Safari": "y" | |
| 63 | + }, | |
| 64 | + "小程序": { | |
| 65 | + "微信": "y", | |
| 66 | + "阿里": "y", | |
| 67 | + "百度": "y", | |
| 68 | + "字节跳动": "y", | |
| 69 | + "QQ": "y", | |
| 70 | + "钉钉": "y", | |
| 71 | + "快手": "y", | |
| 72 | + "飞书": "y", | |
| 73 | + "京东": "y" | |
| 74 | + }, | |
| 75 | + "快应用": { | |
| 76 | + "华为": "y", | |
| 77 | + "联盟": "y" | |
| 78 | + }, | |
| 79 | + "Vue": { | |
| 80 | + "vue2": "y", | |
| 81 | + "vue3": "y" | |
| 82 | + } | |
| 83 | + } | |
| 84 | + } | |
| 85 | + } | |
| 86 | +} | |
| 0 | 87 | \ No newline at end of file | ... | ... |
garbage-removal/src/z-paging/readme.md
0 → 100644
| 1 | +# z-paging | |
| 2 | + | |
| 3 | +<p align="center"> | |
| 4 | + <img alt="logo" src="https://z-paging.zxlee.cn/img/title-logo.png" height="100" style="margin-bottom: 50px;"> | |
| 5 | +</p> | |
| 6 | + | |
| 7 | +[](https://github.com/SmileZXLee/uni-z-paging) | |
| 8 | +[](https://en.wikipedia.org/wiki/MIT_License) | |
| 9 | + | |
| 10 | +### 文档地址:[https://z-paging.zxlee.cn](https://z-paging.zxlee.cn) | |
| 11 | + | |
| 12 | +### 更新组件前,请注意[版本差异](https://z-paging.zxlee.cn/start/upgrade-guide.html) | |
| 13 | + | |
| 14 | +*** | |
| 15 | +### 功能&特点 | |
| 16 | +* 【配置简单】仅需两步(绑定网络请求方法、绑定分页结果数组)轻松完成完整下拉刷新,上拉加载更多功能。 | |
| 17 | +* 【低耦合,低侵入】分页自动管理。在page中无需处理任何分页相关逻辑,无需在data中定义任何分页相关变量,全由z-paging内部处理。 | |
| 18 | +* 【超灵活,支持各种类型自定义】支持自定义下拉刷新,自定义上拉加载更多等各种自定义效果;支持使用内置自动分页,同时也支持通过监听下拉刷新和滚动到底部事件自行处理;支持使用自带全屏布局规范,同时也支持将z-paging自由放在任意容器中。 | |
| 19 | +* 【功能丰富】支持国际化,支持自定义且自动管理空数据图,支持主题模式切换,支持本地分页,支持聊天分页模式,支持展示最后更新时间,支持吸顶效果,支持内部scroll-view滚动与页面滚动,支持一键滚动到顶部等诸多功能。 | |
| 20 | +* 【全平台兼容】支持vue、nvue,vue2、vue3,支持h5、app及各家小程序。 | |
| 21 | +* 【高性能】在app-vue、h5、微信小程序、QQ小程序上使用wxs+renderjs从视图层实现下拉刷新;支持虚拟列表,轻松渲染万级数据! | |
| 22 | + | |
| 23 | +*** | |
| 24 | +### 反馈qq群 | |
| 25 | +* 官方1群`已满`:[790460711](https://jq.qq.com/?_wv=1027&k=vU2fKZZH) | |
| 26 | + | |
| 27 | +* 官方2群:[371624008](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=avPmibADf2TNi4LxkIwjCE5vbfXpa-r1&authKey=dQ%2FVDAR87ONxI4b32Py%2BvmXbhnopjHN7%2FJPtdsqJdsCPFZB6zDQ17L06Uh0kITUZ&noverify=0&group_code=371624008) | |
| 28 | + | |
| 29 | +*** | |
| 30 | + | |
| 31 | +### 预览 | |
| 32 | + | |
| 33 | +*** | |
| 34 | + | |
| 35 | +| 自定义下拉刷新效果演示 | 滑动切换选项卡+吸顶演示 | | |
| 36 | +| :----------------------------------------------------------: | :----------------------------------------------------------: | | |
| 37 | +|  |  | | |
| 38 | + | |
| 39 | +| 聊天记录模式演示 | 虚拟列表(流畅渲染1万+条)演示 | | |
| 40 | +| :----------------------------------------------------------: | :----------------------------------------------------------: | | |
| 41 | +|  |  | | |
| 42 | + | |
| 43 | +### 在线demo体验地址: | |
| 44 | + | |
| 45 | +* [https://demo.z-paging.zxlee.cn](https://demo.z-paging.zxlee.cn) | |
| 46 | + | |
| 47 | +| 扫码体验 | | |
| 48 | +| ------------------------------------------------------------ | | |
| 49 | +|  | | |
| 50 | + | |
| 51 | +### demo下载 | |
| 52 | +* 支持vue2&vue3的`选项式api`写法demo下载,请点击页面右上角的【使用HBuilderX导入示例项目】或【下载示例项目ZIP】。 | |
| 53 | +* 支持vue3的`组合式api`写法demo下载,请访问[github](https://github.com/SmileZXLee/uni-z-paging)。 | |
| 0 | 54 | \ No newline at end of file | ... | ... |