This commit is contained in:
@fawn-nine
2023-03-03 12:11:23 +08:00
commit f8e1a3015b
502 changed files with 57308 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
## 1.0.02021-05-12
1. 支持uni_modules

View File

@@ -0,0 +1,185 @@
<template>
<view>
<view class="popupClick" @click="onPopupShow()"><slot></slot></view>
<z-popup v-model="currentValue">
<view class="multiple_choice_title">
<text @click="currentValue = false">取消</text>
<view>{{title}}</view>
<text @click="onConfirm">确定</text>
</view>
<scroll-view scroll-y="true" class="multiple_choice_scroll">
<view class="multiple_choice_box">
<view class="multiple_choice_content">
<view class="multiple_choice_item" v-for="(item,index) of rangeList" :key="index" @click="onSelect(index)">
<view class="select" :class="{active: item.select }"></view>
<view class="value">{{item[rangeKey]}}</view>
</view>
</view>
</view>
</scroll-view>
</z-popup>
</view>
</template>
<script>
export default {
props: {
value: {
type: Boolean,
default: false
},
title: {
type: String,
default: ""
},
range: {
type: Array,
default: function(){
return []
}
},
rangeKey: {
type: String,
default: "name"
},
},
created() {
if (typeof this.value !== 'undefined') {
this.currentValue = this.value;
}
this.rangeList = this.range.map(item => {
item.select = false;
return item;
});
},
watch: {
value(val) {
this.currentValue = val;
},
currentValue(val) {
this.$emit(val ? 'on-show' : 'on-hide');
this.$emit('input', val);
},
range(val){
this.rangeList = val.map(item => {
item.select = false;
return item;
});
}
},
data() {
return {
currentValue: false,
rangeList: []
};
},
methods: {
onPopupShow(){
this.currentValue = true;
},
onSelect(index){
let item = this.rangeList[index];
item.select = !item.select;
this.$set(this.rangeList, index, item);
},
onConfirm(){
let resultList = this.rangeList.filter(item => {
if(item.select){
return true;
} else {
return false;
}
});
if(resultList.length > 0){
this.currentValue = false;
this.$emit("change", resultList);
} else {
uni.showToast({
title: "请选择",
icon: "none"
});
}
}
},
mounted() {}
};
</script>
<style lang="scss" scoped>
@import '@/style/mixin.scss';
.multiple_choice_title {
display: flex;
justify-content: space-between;
height: 88upx;
line-height: 88upx;
border-bottom: 2upx solid #ebebeb;
padding: 0 20upx;
background-color: #FFF;
}
.multiple_choice_title view {
font-size: 32upx;
}
.multiple_choice_title text {
width: 80upx;
flex-shrink: 0;
text-align: center;
}
.multiple_choice_title text {
font-size: 28upx;
color: #999;
}
.multiple_choice_title text:last-child {
color: $themeColor;
}
.multiple_choice_scroll {
background-color: #FFF;
max-height: 60vh;
min-height: 30vh;
}
.multiple_choice_box {
display: flex;
justify-content: center;
align-items: center;
min-height: 30vh;
}
.multiple_choice_content {
.multiple_choice_item {
height: 100rpx;
padding: 0 30rpx;
font-size: 30rpx;
display: flex;
align-items: center;
// &:nth-child(2n) {
// background-color: #f7f7f7;
// }
.select {
width: 40rpx;
height: 40rpx;
margin-right: 15rpx;
// background-image: url(../../static/icon/ic_notselected.png);
// background-size: 100% 100%;
flex-shrink: 0;
border-radius: 50%;
border: 2rpx solid #ccc;
&.active {
border: 2rpx solid $themeColor;
background-color: $themeColor;
text-align: center;
line-height: 38rpx;
transform:rotate(15deg);
}
&.active::before {
content: "√";
color: #FFF;
}
}
.value {
width: calc(100% - 55rpx);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap
}
}
}
</style>

View File

@@ -0,0 +1,77 @@
{
"id": "multiple-choice",
"displayName": "多选组件",
"version": "1.0.0",
"description": "多选组件",
"keywords": [
"多选",
"多选组件"
],
"repository": "https://github.com/zhouwei1994/uni-app-demo",
"engines": {
"HBuilderX": "^3.0.0"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "465081029"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
# 多选组件
多选组件
| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群"` |
| ----------------------------|--------------------------- |
|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
| QQ群号607391225 |微信号zhou0612wei|
### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
### 案例一
```
<multiple-choice v-model="true" title="选择性别" :range="[{name: '男'}, {name: '女'}]" rangeKey="name"></multiple-choice>
```
### 案例二
```
<multiple-choice title="选择性别" :range="[{name: '男'}, {name: '女'}]" rangeKey="name">
<button>打开</button>
</multiple-choice>
```
### 属性
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
| value | Boolean | false | 控制弹窗是否打开 |
| title | String | | 弹窗标题|
| range | Array | [] | 可选内容 |
| rangeKey | String | name | 显示内容的key|

View File

@@ -0,0 +1,4 @@
## 0.0.22021-04-16
- 修改插件package信息
## 0.0.12021-03-15
- 初始化项目

View File

@@ -0,0 +1,80 @@
{
"id": "uni-config-center",
"displayName": "uni-config-center",
"version": "0.0.2",
"description": "uniCloud 配置中心",
"keywords": [
"配置",
"配置中心"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"uniCloud",
"云函数模板"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"directories": {
"example": "../../../scripts/dist"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,93 @@
# 为什么使用uni-config-center
实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ ├─index.js
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b // plugin-b对应的目录
├─index.js
└─config.json // plugin-b对应的配置文件
```
假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。
uni-config-center就是用了统一管理这些配置文件的使用uni-config-center后的目录结构如下
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ └─index.js
├─plugin-b // plugin-b对应的目录
│ └─index.js
└─uni-config-center
├─index.js // config-center入口文件
├─plugin-a
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b
└─config.json // plugin-b对应的配置文件
```
使用uni-config-center后的优势
- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便
- 支持对config.json设置schema插件使用者在HBuilderX内编写config.json文件时会有更好的提示后续HBuilderX会提供支持
# 用法
在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖请参考[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common)
```js
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
pluginId: 'uni-id', // 插件id
defaultConfig: { // 默认配置
tokenExpiresIn: 7200,
tokenExpiresThreshold: 600,
},
customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并
// defaudltConfig 默认配置
// userConfig 用户配置
return Object.assign(defaultConfig, userConfig)
}
})
// 以如下配置为例
// {
// "tokenExpiresIn": 7200,
// "passwordErrorLimit": 6,
// "bindTokenToDevice": false,
// "passwordErrorRetryTime": 3600,
// "app-plus": {
// "tokenExpiresIn": 2592000
// },
// "service": {
// "sms": {
// "codeExpiresIn": 300
// }
// }
// }
// 获取配置
uniIdConfig.config() // 获取全部配置注意uni-config-center内不存在对应插件目录时会返回空对象
uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置返回7200
uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置返回300
uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置如果不存在则取传入的默认值返回600
// 获取文件绝对路径
uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径
// 引用文件require
uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined文件内有其他错误导致require失败时会抛出错误。
// 判断是否包含某文件
uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件true: 文件存在false: 文件不存在
```

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
{
"name": "uni-config-center",
"version": "0.0.2",
"description": "配置中心",
"main": "index.js",
"keywords": [],
"author": "DCloud",
"license": "Apache-2.0"
}

View File

@@ -0,0 +1,18 @@
## 1.2.12022-05-30
- 新增 stat属性是否开启uni统计功能
## 1.2.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-goods-nav](https://uniapp.dcloud.io/component/uniui/uni-goods-nav)
## 1.1.12021-08-24
- 新增 支持国际化
## 1.1.02021-07-13
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.0.72021-05-12
- 新增 组件示例地址
## 1.0.62021-04-21
- 优化 添加依赖 uni-icons, 导入后自动下载依赖
## 1.0.52021-02-05
- 优化 组件引用关系通过uni_modules引用组件
## 1.0.42021-02-05
- 调整为uni_modules目录规范

View File

@@ -0,0 +1,6 @@
{
"uni-goods-nav.options.shop": "shop",
"uni-goods-nav.options.cart": "cart",
"uni-goods-nav.buttonGroup.addToCart": "add to cart",
"uni-goods-nav.buttonGroup.buyNow": "buy now"
}

View File

@@ -0,0 +1,8 @@
import en from './en.json'
import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json'
export default {
en,
'zh-Hans': zhHans,
'zh-Hant': zhHant
}

View File

@@ -0,0 +1,6 @@
{
"uni-goods-nav.options.shop": "店铺",
"uni-goods-nav.options.cart": "购物车",
"uni-goods-nav.buttonGroup.addToCart": "加入购物车",
"uni-goods-nav.buttonGroup.buyNow": "立即购买"
}

View File

@@ -0,0 +1,6 @@
{
"uni-goods-nav.options.shop": "店鋪",
"uni-goods-nav.options.cart": "購物車",
"uni-goods-nav.buttonGroup.addToCart": "加入購物車",
"uni-goods-nav.buttonGroup.buyNow": "立即購買"
}

View File

@@ -0,0 +1,229 @@
<template>
<view class="uni-goods-nav">
<!-- 底部占位 -->
<view class="uni-tab__seat" />
<view class="uni-tab__cart-box flex">
<view class="flex uni-tab__cart-sub-left">
<view v-for="(item,index) in options" :key="index" class="flex uni-tab__cart-button-left uni-tab__shop-cart" @click="onClick(index,item)">
<view class="uni-tab__icon">
<uni-icons :type="item.icon" size="20" color="#646566"></uni-icons>
<!-- <image class="image" :src="item.icon" mode="widthFix" /> -->
</view>
<text class="uni-tab__text">{{ item.text }}</text>
<view class="flex uni-tab__dot-box">
<text v-if="item.info" :class="{ 'uni-tab__dots': item.info > 9 }" class="uni-tab__dot " :style="{'backgroundColor':item.infoBackgroundColor?item.infoBackgroundColor:'#ff0000',
color:item.infoColor?item.infoColor:'#fff'
}">{{ item.info }}</text>
</view>
</view>
</view>
<view :class="{'uni-tab__right':fill}" class="flex uni-tab__cart-sub-right ">
<view v-for="(item,index) in buttonGroup" :key="index" :style="{background:item.backgroundColor,color:item.color}"
class="flex uni-tab__cart-button-right" @click="buttonClick(index,item)"><text :style="{color:item.color}" class="uni-tab__cart-button-right-text">{{ item.text }}</text></view>
</view>
</view>
</view>
</template>
<script>
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from './i18n/index.js'
const { t } = initVueI18n(messages)
/**
* GoodsNav 商品导航
* @description 商品加入购物车、立即购买等
* @tutorial https://ext.dcloud.net.cn/plugin?id=865
* @property {Array} options 组件参数
* @property {Array} buttonGroup 组件按钮组参数
* @property {Boolean} fill = [true | false] 组件按钮组参数
* @property {Boolean} stat 是否开启统计功能
* @event {Function} click 左侧点击事件
* @event {Function} buttonClick 右侧按钮组点击事件
* @example <uni-goods-nav :fill="true" options="" buttonGroup="buttonGroup" @click="" @buttonClick="" />
*/
export default {
name: 'UniGoodsNav',
emits:['click','buttonClick'],
props: {
options: {
type: Array,
default () {
return [{
icon: 'shop',
text: t("uni-goods-nav.options.shop"),
}, {
icon: 'cart',
text: t("uni-goods-nav.options.cart")
}]
}
},
buttonGroup: {
type: Array,
default () {
return [{
text: t("uni-goods-nav.buttonGroup.addToCart"),
backgroundColor: 'linear-gradient(90deg, #FFCD1E, #FF8A18)',
color: '#fff'
},
{
text: t("uni-goods-nav.buttonGroup.buyNow"),
backgroundColor: 'linear-gradient(90deg, #FE6035, #EF1224)',
color: '#fff'
}
]
}
},
fill: {
type: Boolean,
default: false
},
stat:{
type: Boolean,
default: false
}
},
methods: {
onClick(index, item) {
this.$emit('click', {
index,
content: item,
})
},
buttonClick(index, item) {
if (uni.report && this.stat) {
uni.report(item.text, item.text)
}
this.$emit('buttonClick', {
index,
content: item
})
}
}
}
</script>
<style lang="scss" >
.flex {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-goods-nav {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
}
.uni-tab__cart-box {
flex: 1;
height: 50px;
background-color: #fff;
z-index: 900;
}
.uni-tab__cart-sub-left {
padding: 0 5px;
}
.uni-tab__cart-sub-right {
flex: 1;
}
.uni-tab__right {
margin: 5px 0;
margin-right: 10px;
border-radius: 100px;
overflow: hidden;
}
.uni-tab__cart-button-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
// flex: 1;
position: relative;
justify-content: center;
align-items: center;
flex-direction: column;
margin: 0 10px;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-tab__icon {
width: 18px;
height: 18px;
}
.image {
width: 18px;
height: 18px;
}
.uni-tab__text {
margin-top: 3px;
font-size: 12px;
color: #646566;
}
.uni-tab__cart-button-right {
/* #ifndef APP-NVUE */
display: flex;
flex-direction: column;
/* #endif */
flex: 1;
justify-content: center;
align-items: center;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-tab__cart-button-right-text {
font-size: 14px;
color: #fff;
}
.uni-tab__cart-button-right:active {
opacity: 0.7;
}
.uni-tab__dot-box {
/* #ifndef APP-NVUE */
display: flex;
flex-direction: column;
/* #endif */
position: absolute;
right: -2px;
top: 2px;
justify-content: center;
align-items: center;
// width: 0;
// height: 0;
}
.uni-tab__dot {
// width: 30rpx;
// height: 30rpx;
padding: 0 4px;
line-height: 15px;
color: #ffffff;
text-align: center;
font-size: 12px;
background-color: #ff0000;
border-radius: 15px;
}
.uni-tab__dots {
padding: 0 4px;
// width: auto;
border-radius: 15px;
}
</style>

View File

@@ -0,0 +1,88 @@
{
"id": "uni-goods-nav",
"displayName": "uni-goods-nav 商品导航",
"version": "1.2.1",
"description": "商品导航组件主要用于电商类应用底部导航,可自定义加入购物车,购买等操作",
"keywords": [
"uni-ui",
"uniui",
"商品导航"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-icons"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,10 @@
## GoodsNav 商品导航
> **组件名uni-goods-nav**
> 代码块: `uGoodsNav`
商品加入购物车,立即购买等。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-goods-nav)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,22 @@
## 1.3.52022-01-24
- 优化 size 属性可以传入不带单位的字符串数值
## 1.3.42022-01-24
- 优化 size 支持其他单位
## 1.3.32022-01-17
- 修复 nvue 有些图标不显示的bug兼容老版本图标
## 1.3.22021-12-01
- 优化 示例可复制图标名称
## 1.3.12021-11-23
- 优化 兼容旧组件 type 值
## 1.3.02021-11-19
- 新增 更多图标
- 优化 自定义图标使用方式
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons)
## 1.1.72021-11-08
## 1.2.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.52021-05-12
- 新增 组件示例地址
## 1.1.42021-02-05
- 调整为uni_modules目录规范

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,96 @@
<template>
<!-- #ifdef APP-NVUE -->
<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" @click="_onClick">{{unicode}}</text>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick"></text>
<!-- #endif -->
</template>
<script>
import icons from './icons.js';
const getVal = (val) => {
const reg = /^[0-9]*$/g
return (typeof val === 'number' || reg.test(val) )? val + 'px' : val;
}
// #ifdef APP-NVUE
var domModule = weex.requireModule('dom');
import iconUrl from './uniicons.ttf'
domModule.addRule('fontFace', {
'fontFamily': "uniicons",
'src': "url('"+iconUrl+"')"
});
// #endif
/**
* Icons 图标
* @description 用于展示 icons 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: 'UniIcons',
emits:['click'],
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
customPrefix:{
type: String,
default: ''
}
},
data() {
return {
icons: icons.glyphs
}
},
computed:{
unicode(){
let code = this.icons.find(v=>v.font_class === this.type)
if(code){
return unescape(`%u${code.unicode}`)
}
return ''
},
iconSize(){
return getVal(this.size)
}
},
methods: {
_onClick() {
this.$emit('click')
}
}
}
</script>
<style lang="scss">
/* #ifndef APP-NVUE */
@import './uniicons.css';
@font-face {
font-family: uniicons;
src: url('./uniicons.ttf') format('truetype');
}
/* #endif */
.uni-icons {
font-family: uniicons;
text-decoration: none;
text-align: center;
}
</style>

View File

@@ -0,0 +1,663 @@
.uniui-color:before {
content: "\e6cf";
}
.uniui-wallet:before {
content: "\e6b1";
}
.uniui-settings-filled:before {
content: "\e6ce";
}
.uniui-auth-filled:before {
content: "\e6cc";
}
.uniui-shop-filled:before {
content: "\e6cd";
}
.uniui-staff-filled:before {
content: "\e6cb";
}
.uniui-vip-filled:before {
content: "\e6c6";
}
.uniui-plus-filled:before {
content: "\e6c7";
}
.uniui-folder-add-filled:before {
content: "\e6c8";
}
.uniui-color-filled:before {
content: "\e6c9";
}
.uniui-tune-filled:before {
content: "\e6ca";
}
.uniui-calendar-filled:before {
content: "\e6c0";
}
.uniui-notification-filled:before {
content: "\e6c1";
}
.uniui-wallet-filled:before {
content: "\e6c2";
}
.uniui-medal-filled:before {
content: "\e6c3";
}
.uniui-gift-filled:before {
content: "\e6c4";
}
.uniui-fire-filled:before {
content: "\e6c5";
}
.uniui-refreshempty:before {
content: "\e6bf";
}
.uniui-location-filled:before {
content: "\e6af";
}
.uniui-person-filled:before {
content: "\e69d";
}
.uniui-personadd-filled:before {
content: "\e698";
}
.uniui-back:before {
content: "\e6b9";
}
.uniui-forward:before {
content: "\e6ba";
}
.uniui-arrow-right:before {
content: "\e6bb";
}
.uniui-arrowthinright:before {
content: "\e6bb";
}
.uniui-arrow-left:before {
content: "\e6bc";
}
.uniui-arrowthinleft:before {
content: "\e6bc";
}
.uniui-arrow-up:before {
content: "\e6bd";
}
.uniui-arrowthinup:before {
content: "\e6bd";
}
.uniui-arrow-down:before {
content: "\e6be";
}
.uniui-arrowthindown:before {
content: "\e6be";
}
.uniui-bottom:before {
content: "\e6b8";
}
.uniui-arrowdown:before {
content: "\e6b8";
}
.uniui-right:before {
content: "\e6b5";
}
.uniui-arrowright:before {
content: "\e6b5";
}
.uniui-top:before {
content: "\e6b6";
}
.uniui-arrowup:before {
content: "\e6b6";
}
.uniui-left:before {
content: "\e6b7";
}
.uniui-arrowleft:before {
content: "\e6b7";
}
.uniui-eye:before {
content: "\e651";
}
.uniui-eye-filled:before {
content: "\e66a";
}
.uniui-eye-slash:before {
content: "\e6b3";
}
.uniui-eye-slash-filled:before {
content: "\e6b4";
}
.uniui-info-filled:before {
content: "\e649";
}
.uniui-reload:before {
content: "\e6b2";
}
.uniui-micoff-filled:before {
content: "\e6b0";
}
.uniui-map-pin-ellipse:before {
content: "\e6ac";
}
.uniui-map-pin:before {
content: "\e6ad";
}
.uniui-location:before {
content: "\e6ae";
}
.uniui-starhalf:before {
content: "\e683";
}
.uniui-star:before {
content: "\e688";
}
.uniui-star-filled:before {
content: "\e68f";
}
.uniui-calendar:before {
content: "\e6a0";
}
.uniui-fire:before {
content: "\e6a1";
}
.uniui-medal:before {
content: "\e6a2";
}
.uniui-font:before {
content: "\e6a3";
}
.uniui-gift:before {
content: "\e6a4";
}
.uniui-link:before {
content: "\e6a5";
}
.uniui-notification:before {
content: "\e6a6";
}
.uniui-staff:before {
content: "\e6a7";
}
.uniui-vip:before {
content: "\e6a8";
}
.uniui-folder-add:before {
content: "\e6a9";
}
.uniui-tune:before {
content: "\e6aa";
}
.uniui-auth:before {
content: "\e6ab";
}
.uniui-person:before {
content: "\e699";
}
.uniui-email-filled:before {
content: "\e69a";
}
.uniui-phone-filled:before {
content: "\e69b";
}
.uniui-phone:before {
content: "\e69c";
}
.uniui-email:before {
content: "\e69e";
}
.uniui-personadd:before {
content: "\e69f";
}
.uniui-chatboxes-filled:before {
content: "\e692";
}
.uniui-contact:before {
content: "\e693";
}
.uniui-chatbubble-filled:before {
content: "\e694";
}
.uniui-contact-filled:before {
content: "\e695";
}
.uniui-chatboxes:before {
content: "\e696";
}
.uniui-chatbubble:before {
content: "\e697";
}
.uniui-upload-filled:before {
content: "\e68e";
}
.uniui-upload:before {
content: "\e690";
}
.uniui-weixin:before {
content: "\e691";
}
.uniui-compose:before {
content: "\e67f";
}
.uniui-qq:before {
content: "\e680";
}
.uniui-download-filled:before {
content: "\e681";
}
.uniui-pyq:before {
content: "\e682";
}
.uniui-sound:before {
content: "\e684";
}
.uniui-trash-filled:before {
content: "\e685";
}
.uniui-sound-filled:before {
content: "\e686";
}
.uniui-trash:before {
content: "\e687";
}
.uniui-videocam-filled:before {
content: "\e689";
}
.uniui-spinner-cycle:before {
content: "\e68a";
}
.uniui-weibo:before {
content: "\e68b";
}
.uniui-videocam:before {
content: "\e68c";
}
.uniui-download:before {
content: "\e68d";
}
.uniui-help:before {
content: "\e679";
}
.uniui-navigate-filled:before {
content: "\e67a";
}
.uniui-plusempty:before {
content: "\e67b";
}
.uniui-smallcircle:before {
content: "\e67c";
}
.uniui-minus-filled:before {
content: "\e67d";
}
.uniui-micoff:before {
content: "\e67e";
}
.uniui-closeempty:before {
content: "\e66c";
}
.uniui-clear:before {
content: "\e66d";
}
.uniui-navigate:before {
content: "\e66e";
}
.uniui-minus:before {
content: "\e66f";
}
.uniui-image:before {
content: "\e670";
}
.uniui-mic:before {
content: "\e671";
}
.uniui-paperplane:before {
content: "\e672";
}
.uniui-close:before {
content: "\e673";
}
.uniui-help-filled:before {
content: "\e674";
}
.uniui-paperplane-filled:before {
content: "\e675";
}
.uniui-plus:before {
content: "\e676";
}
.uniui-mic-filled:before {
content: "\e677";
}
.uniui-image-filled:before {
content: "\e678";
}
.uniui-locked-filled:before {
content: "\e668";
}
.uniui-info:before {
content: "\e669";
}
.uniui-locked:before {
content: "\e66b";
}
.uniui-camera-filled:before {
content: "\e658";
}
.uniui-chat-filled:before {
content: "\e659";
}
.uniui-camera:before {
content: "\e65a";
}
.uniui-circle:before {
content: "\e65b";
}
.uniui-checkmarkempty:before {
content: "\e65c";
}
.uniui-chat:before {
content: "\e65d";
}
.uniui-circle-filled:before {
content: "\e65e";
}
.uniui-flag:before {
content: "\e65f";
}
.uniui-flag-filled:before {
content: "\e660";
}
.uniui-gear-filled:before {
content: "\e661";
}
.uniui-home:before {
content: "\e662";
}
.uniui-home-filled:before {
content: "\e663";
}
.uniui-gear:before {
content: "\e664";
}
.uniui-smallcircle-filled:before {
content: "\e665";
}
.uniui-map-filled:before {
content: "\e666";
}
.uniui-map:before {
content: "\e667";
}
.uniui-refresh-filled:before {
content: "\e656";
}
.uniui-refresh:before {
content: "\e657";
}
.uniui-cloud-upload:before {
content: "\e645";
}
.uniui-cloud-download-filled:before {
content: "\e646";
}
.uniui-cloud-download:before {
content: "\e647";
}
.uniui-cloud-upload-filled:before {
content: "\e648";
}
.uniui-redo:before {
content: "\e64a";
}
.uniui-images-filled:before {
content: "\e64b";
}
.uniui-undo-filled:before {
content: "\e64c";
}
.uniui-more:before {
content: "\e64d";
}
.uniui-more-filled:before {
content: "\e64e";
}
.uniui-undo:before {
content: "\e64f";
}
.uniui-images:before {
content: "\e650";
}
.uniui-paperclip:before {
content: "\e652";
}
.uniui-settings:before {
content: "\e653";
}
.uniui-search:before {
content: "\e654";
}
.uniui-redo-filled:before {
content: "\e655";
}
.uniui-list:before {
content: "\e644";
}
.uniui-mail-open-filled:before {
content: "\e63a";
}
.uniui-hand-down-filled:before {
content: "\e63c";
}
.uniui-hand-down:before {
content: "\e63d";
}
.uniui-hand-up-filled:before {
content: "\e63e";
}
.uniui-hand-up:before {
content: "\e63f";
}
.uniui-heart-filled:before {
content: "\e641";
}
.uniui-mail-open:before {
content: "\e643";
}
.uniui-heart:before {
content: "\e639";
}
.uniui-loop:before {
content: "\e633";
}
.uniui-pulldown:before {
content: "\e632";
}
.uniui-scan:before {
content: "\e62a";
}
.uniui-bars:before {
content: "\e627";
}
.uniui-cart-filled:before {
content: "\e629";
}
.uniui-checkbox:before {
content: "\e62b";
}
.uniui-checkbox-filled:before {
content: "\e62c";
}
.uniui-shop:before {
content: "\e62f";
}
.uniui-headphones:before {
content: "\e630";
}
.uniui-cart:before {
content: "\e631";
}

View File

@@ -0,0 +1,86 @@
{
"id": "uni-icons",
"displayName": "uni-icons 图标",
"version": "1.3.5",
"description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
"keywords": [
"uni-ui",
"uniui",
"icon",
"图标"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.2.14"
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": ["uni-scss"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
## Icons 图标
> **组件名uni-icons**
> 代码块: `uIcons`
用于展示 icons 图标 。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,24 @@
## 3.1.02021-04-19
- 增加对用户名、邮箱、密码字段的两端去空格
- 默认忽略用户名、邮箱的大小写 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=case-sensitive)
- 修复 customToken导出async方法报错的Bug
## 3.0.122021-04-13
- 调整bindTokenToDevice默认值为false
## 3.0.112021-04-12
- 修复3.0.7版本引出的多个用户访问时可能出现30201报错的Bug
## 3.0.102021-04-08
- 优化错误提示
## 3.0.92021-04-08
- bindMobile接口支持通过一键登录的方式绑定
- 优化错误提示
## 3.0.82021-03-19
- 修复 3.0.7版本某些情况下生成token报错的Bug
## 3.0.72021-03-19
- 新增 支持uni-config-center更新uni-id无须再担心配置被覆盖 [详情](https://uniapp.dcloud.io/uniCloud/uni-id?id=uni-config-center)
- 新增 自定义token内容可以缓存角色权限之外的更多信息到客户端 [详情](https://uniapp.dcloud.io/uniCloud/uni-id?id=custom-token)
- 新增 支持传入context获取uni-id实例防止单实例多并发时全局context混乱 [详情](https://uniapp.dcloud.io/uniCloud/uni-id?id=create-instance)
## 3.0.62021-03-05
- 新增[uniID.wxBizDataCrypt](https://uniapp.dcloud.io/uniCloud/uni-id?id=%e5%be%ae%e4%bf%a1%e6%95%b0%e6%8d%ae%e8%a7%a3%e5%af%86)方法
- 优化loginByApple方法提高接口响应速度
## 3.0.52021-02-03
- 调整为uni_modules目录规范

View File

@@ -0,0 +1,80 @@
{
"id": "uni-id",
"displayName": "uni-id",
"version": "3.1.0",
"description": "简单、统一、可扩展的用户中心",
"keywords": [
"uniid",
"uni-id",
"用户管理",
"用户中心",
"短信验证码"
],
"repository": "https://gitee.com/dcloud/uni-id.git",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"uniCloud",
"云函数模板"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": ["uni-config-center"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
**文档已移至[uni-id文档](https://uniapp.dcloud.net.cn/uniCloud/uni-id)**
> 一般uni-id升级大版本时为不兼容更新从低版本迁移到高版本请参考[uni-id迁移指南](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=migration)
## 重要升级说明
**uni-id 3.x版本搭配的uniCloud admin版本需大于1.2.10。**
### 缓存角色权限
`uni-id 3.0.0`支持在token内缓存用户的角色权限默认开启此功能各登录接口的needPermission参数不再生效。如需关闭请在config内配置`"removePermissionAndRoleFromToken": true`
为什么要缓存角色权限?要知道云数据库是按照读写次数来收取费用的,并且读写数据库会拖慢接口响应速度。未配置`"removePermissionAndRoleFromToken": true`的情况下可以在调用checkToken接口时不查询数据库获取用户角色权限。
详细checkToken流程如下
![](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/ed45d350-5a4d-11eb-b997-9918a5dda011.jpg)
可以看出旧版tokenremovePermissionAndRoleFromToken为true时生成的在checkToken时如需返回权限需要进行两次数据库查询。新版token不需要查库即可返回权限信息。
**注意**
- 由于角色权限缓存在token内可能会存在权限已经更新但是用户token未过期之前依然是旧版角色权限的情况。可以调短一些token过期时间来减少这种情况的影响。
- admin角色token内不包含permission如需自行判断用户是否有某个权限要注意admin角色需要额外判断一下写法如下
```js
const {
role,
permission
} = await uniID.checkToken(event.uniIdToken)
if(role.includes('admin') || permission.includes('your permission id')) {
// 当前角色拥有'your permission id'对应的权限
}
```

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
{
"name": "uni-id",
"version": "3.1.0",
"description": "uni-id for uniCloud",
"main": "index.js",
"homepage": "https://uniapp.dcloud.io/uniCloud/uni-id",
"repository": {
"type": "git",
"url": "git+https://gitee.com/dcloud/uni-id.git"
},
"author": "",
"license": "Apache-2.0",
"dependencies": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}

View File

@@ -0,0 +1,8 @@
## 1.0.32022-01-21
- 优化 组件示例
## 1.0.22021-11-22
- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
## 1.0.12021-11-22
- 修复 vue3中scss语法兼容问题
## 1.0.02021-11-18
- init

View File

@@ -0,0 +1 @@
@import './styles/index.scss';

View File

@@ -0,0 +1,82 @@
{
"id": "uni-scss",
"displayName": "uni-scss 辅助样式",
"version": "1.0.3",
"description": "uni-sass是uni-ui提供的一套全局样式 通过一些简单的类名和sass变量实现简单的页面布局操作比如颜色、边距、圆角等。",
"keywords": [
"uni-scss",
"uni-ui",
"辅助样式"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,4 @@
`uni-sass``uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,7 @@
@import './setting/_variables.scss';
@import './setting/_border.scss';
@import './setting/_color.scss';
@import './setting/_space.scss';
@import './setting/_radius.scss';
@import './setting/_text.scss';
@import './setting/_styles.scss';

View File

@@ -0,0 +1,3 @@
.uni-border {
border: 1px $uni-border-1 solid;
}

View File

@@ -0,0 +1,66 @@
// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐
// @mixin get-styles($k,$c) {
// @if $k == size or $k == weight{
// font-#{$k}:#{$c}
// }@else{
// #{$k}:#{$c}
// }
// }
$uni-ui-color:(
// 主色
primary: $uni-primary,
primary-disable: $uni-primary-disable,
primary-light: $uni-primary-light,
// 辅助色
success: $uni-success,
success-disable: $uni-success-disable,
success-light: $uni-success-light,
warning: $uni-warning,
warning-disable: $uni-warning-disable,
warning-light: $uni-warning-light,
error: $uni-error,
error-disable: $uni-error-disable,
error-light: $uni-error-light,
info: $uni-info,
info-disable: $uni-info-disable,
info-light: $uni-info-light,
// 中性色
main-color: $uni-main-color,
base-color: $uni-base-color,
secondary-color: $uni-secondary-color,
extra-color: $uni-extra-color,
// 背景色
bg-color: $uni-bg-color,
// 边框颜色
border-1: $uni-border-1,
border-2: $uni-border-2,
border-3: $uni-border-3,
border-4: $uni-border-4,
// 黑色
black:$uni-black,
// 白色
white:$uni-white,
// 透明
transparent:$uni-transparent
) !default;
@each $key, $child in $uni-ui-color {
.uni-#{"" + $key} {
color: $child;
}
.uni-#{"" + $key}-bg {
background-color: $child;
}
}
.uni-shadow-sm {
box-shadow: $uni-shadow-sm;
}
.uni-shadow-base {
box-shadow: $uni-shadow-base;
}
.uni-shadow-lg {
box-shadow: $uni-shadow-lg;
}
.uni-mask {
background-color:$uni-mask;
}

View File

@@ -0,0 +1,55 @@
@mixin radius($r,$d:null ,$important: false){
$radius-value:map-get($uni-radius, $r) if($important, !important, null);
// Key exists within the $uni-radius variable
@if (map-has-key($uni-radius, $r) and $d){
@if $d == t {
border-top-left-radius:$radius-value;
border-top-right-radius:$radius-value;
}@else if $d == r {
border-top-right-radius:$radius-value;
border-bottom-right-radius:$radius-value;
}@else if $d == b {
border-bottom-left-radius:$radius-value;
border-bottom-right-radius:$radius-value;
}@else if $d == l {
border-top-left-radius:$radius-value;
border-bottom-left-radius:$radius-value;
}@else if $d == tl {
border-top-left-radius:$radius-value;
}@else if $d == tr {
border-top-right-radius:$radius-value;
}@else if $d == br {
border-bottom-right-radius:$radius-value;
}@else if $d == bl {
border-bottom-left-radius:$radius-value;
}
}@else{
border-radius:$radius-value;
}
}
@each $key, $child in $uni-radius {
@if($key){
.uni-radius-#{"" + $key} {
@include radius($key)
}
}@else{
.uni-radius {
@include radius($key)
}
}
}
@each $direction in t, r, b, l,tl, tr, br, bl {
@each $key, $child in $uni-radius {
@if($key){
.uni-radius-#{"" + $direction}-#{"" + $key} {
@include radius($key,$direction,false)
}
}@else{
.uni-radius-#{$direction} {
@include radius($key,$direction,false)
}
}
}
}

View File

@@ -0,0 +1,56 @@
@mixin fn($space,$direction,$size,$n) {
@if $n {
#{$space}-#{$direction}: #{$size*$uni-space-root}px
} @else {
#{$space}-#{$direction}: #{-$size*$uni-space-root}px
}
}
@mixin get-styles($direction,$i,$space,$n){
@if $direction == t {
@include fn($space, top,$i,$n);
}
@if $direction == r {
@include fn($space, right,$i,$n);
}
@if $direction == b {
@include fn($space, bottom,$i,$n);
}
@if $direction == l {
@include fn($space, left,$i,$n);
}
@if $direction == x {
@include fn($space, left,$i,$n);
@include fn($space, right,$i,$n);
}
@if $direction == y {
@include fn($space, top,$i,$n);
@include fn($space, bottom,$i,$n);
}
@if $direction == a {
@if $n {
#{$space}:#{$i*$uni-space-root}px;
} @else {
#{$space}:#{-$i*$uni-space-root}px;
}
}
}
@each $orientation in m,p {
$space: margin;
@if $orientation == m {
$space: margin;
} @else {
$space: padding;
}
@for $i from 0 through 16 {
@each $direction in t, r, b, l, x, y, a {
.uni-#{$orientation}#{$direction}-#{$i} {
@include get-styles($direction,$i,$space,true);
}
.uni-#{$orientation}#{$direction}-n#{$i} {
@include get-styles($direction,$i,$space,false);
}
}
}
}

View File

@@ -0,0 +1,167 @@
/* #ifndef APP-NVUE */
$-color-white:#fff;
$-color-black:#000;
@mixin base-style($color) {
color: #fff;
background-color: $color;
border-color: mix($-color-black, $color, 8%);
&:not([hover-class]):active {
background: mix($-color-black, $color, 10%);
border-color: mix($-color-black, $color, 20%);
color: $-color-white;
outline: none;
}
}
@mixin is-color($color) {
@include base-style($color);
&[loading] {
@include base-style($color);
&::before {
margin-right:5px;
}
}
&[disabled] {
&,
&[loading],
&:not([hover-class]):active {
color: $-color-white;
border-color: mix(darken($color,10%), $-color-white);
background-color: mix($color, $-color-white);
}
}
}
@mixin base-plain-style($color) {
color:$color;
background-color: mix($-color-white, $color, 90%);
border-color: mix($-color-white, $color, 70%);
&:not([hover-class]):active {
background: mix($-color-white, $color, 80%);
color: $color;
outline: none;
border-color: mix($-color-white, $color, 50%);
}
}
@mixin is-plain($color){
&[plain] {
@include base-plain-style($color);
&[loading] {
@include base-plain-style($color);
&::before {
margin-right:5px;
}
}
&[disabled] {
&,
&:active {
color: mix($-color-white, $color, 40%);
background-color: mix($-color-white, $color, 90%);
border-color: mix($-color-white, $color, 80%);
}
}
}
}
.uni-btn {
margin: 5px;
color: #393939;
border:1px solid #ccc;
font-size: 16px;
font-weight: 200;
background-color: #F9F9F9;
// TODO 暂时处理边框隐藏一边的问题
overflow: visible;
&::after{
border: none;
}
&:not([type]),&[type=default] {
color: #999;
&[loading] {
background: none;
&::before {
margin-right:5px;
}
}
&[disabled]{
color: mix($-color-white, #999, 60%);
&,
&[loading],
&:active {
color: mix($-color-white, #999, 60%);
background-color: mix($-color-white,$-color-black , 98%);
border-color: mix($-color-white, #999, 85%);
}
}
&[plain] {
color: #999;
background: none;
border-color: $uni-border-1;
&:not([hover-class]):active {
background: none;
color: mix($-color-white, $-color-black, 80%);
border-color: mix($-color-white, $-color-black, 90%);
outline: none;
}
&[disabled]{
&,
&[loading],
&:active {
background: none;
color: mix($-color-white, #999, 60%);
border-color: mix($-color-white, #999, 85%);
}
}
}
}
&:not([hover-class]):active {
color: mix($-color-white, $-color-black, 50%);
}
&[size=mini] {
font-size: 16px;
font-weight: 200;
border-radius: 8px;
}
&.uni-btn-small {
font-size: 14px;
}
&.uni-btn-mini {
font-size: 12px;
}
&.uni-btn-radius {
border-radius: 999px;
}
&[type=primary] {
@include is-color($uni-primary);
@include is-plain($uni-primary)
}
&[type=success] {
@include is-color($uni-success);
@include is-plain($uni-success)
}
&[type=error] {
@include is-color($uni-error);
@include is-plain($uni-error)
}
&[type=warning] {
@include is-color($uni-warning);
@include is-plain($uni-warning)
}
&[type=info] {
@include is-color($uni-info);
@include is-plain($uni-info)
}
}
/* #endif */

View File

@@ -0,0 +1,24 @@
@mixin get-styles($k,$c) {
@if $k == size or $k == weight{
font-#{$k}:#{$c}
}@else{
#{$k}:#{$c}
}
}
@each $key, $child in $uni-headings {
/* #ifndef APP-NVUE */
.uni-#{$key} {
@each $k, $c in $child {
@include get-styles($k,$c)
}
}
/* #endif */
/* #ifdef APP-NVUE */
.container .uni-#{$key} {
@each $k, $c in $child {
@include get-styles($k,$c)
}
}
/* #endif */
}

View File

@@ -0,0 +1,146 @@
// @use "sass:math";
@import '../tools/functions.scss';
// 间距基础倍数
$uni-space-root: 2 !default;
// 边框半径默认值
$uni-radius-root:5px !default;
$uni-radius: () !default;
// 边框半径断点
$uni-radius: map-deep-merge(
(
0: 0,
// TODO 当前版本暂时不支持 sm 属性
// 'sm': math.div($uni-radius-root, 2),
null: $uni-radius-root,
'lg': $uni-radius-root * 2,
'xl': $uni-radius-root * 6,
'pill': 9999px,
'circle': 50%
),
$uni-radius
);
// 字体家族
$body-font-family: 'Roboto', sans-serif !default;
// 文本
$heading-font-family: $body-font-family !default;
$uni-headings: () !default;
$letterSpacing: -0.01562em;
$uni-headings: map-deep-merge(
(
'h1': (
size: 32px,
weight: 300,
line-height: 50px,
// letter-spacing:-0.01562em
),
'h2': (
size: 28px,
weight: 300,
line-height: 40px,
// letter-spacing: -0.00833em
),
'h3': (
size: 24px,
weight: 400,
line-height: 32px,
// letter-spacing: normal
),
'h4': (
size: 20px,
weight: 400,
line-height: 30px,
// letter-spacing: 0.00735em
),
'h5': (
size: 16px,
weight: 400,
line-height: 24px,
// letter-spacing: normal
),
'h6': (
size: 14px,
weight: 500,
line-height: 18px,
// letter-spacing: 0.0125em
),
'subtitle': (
size: 12px,
weight: 400,
line-height: 20px,
// letter-spacing: 0.00937em
),
'body': (
font-size: 14px,
font-weight: 400,
line-height: 22px,
// letter-spacing: 0.03125em
),
'caption': (
'size': 12px,
'weight': 400,
'line-height': 20px,
// 'letter-spacing': 0.03333em,
// 'text-transform': false
)
),
$uni-headings
);
// 主色
$uni-primary: #2979ff !default;
$uni-primary-disable:lighten($uni-primary,20%) !default;
$uni-primary-light: lighten($uni-primary,25%) !default;
// 辅助色
// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
$uni-success: #18bc37 !default;
$uni-success-disable:lighten($uni-success,20%) !default;
$uni-success-light: lighten($uni-success,25%) !default;
$uni-warning: #f3a73f !default;
$uni-warning-disable:lighten($uni-warning,20%) !default;
$uni-warning-light: lighten($uni-warning,25%) !default;
$uni-error: #e43d33 !default;
$uni-error-disable:lighten($uni-error,20%) !default;
$uni-error-light: lighten($uni-error,25%) !default;
$uni-info: #8f939c !default;
$uni-info-disable:lighten($uni-info,20%) !default;
$uni-info-light: lighten($uni-info,25%) !default;
// 中性色
// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
$uni-main-color: #3a3a3a !default; // 主要文字
$uni-base-color: #6a6a6a !default; // 常规文字
$uni-secondary-color: #909399 !default; // 次要文字
$uni-extra-color: #c7c7c7 !default; // 辅助说明
// 边框颜色
$uni-border-1: #F0F0F0 !default;
$uni-border-2: #EDEDED !default;
$uni-border-3: #DCDCDC !default;
$uni-border-4: #B9B9B9 !default;
// 常规色
$uni-black: #000000 !default;
$uni-white: #ffffff !default;
$uni-transparent: rgba($color: #000000, $alpha: 0) !default;
// 背景色
$uni-bg-color: #f7f7f7 !default;
/* 水平间距 */
$uni-spacing-sm: 8px !default;
$uni-spacing-base: 15px !default;
$uni-spacing-lg: 30px !default;
// 阴影
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default;
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default;
// 蒙版
$uni-mask: rgba($color: #000000, $alpha: 0.4) !default;

View File

@@ -0,0 +1,19 @@
// 合并 map
@function map-deep-merge($parent-map, $child-map){
$result: $parent-map;
@each $key, $child in $child-map {
$parent-has-key: map-has-key($result, $key);
$parent-value: map-get($result, $key);
$parent-type: type-of($parent-value);
$child-type: type-of($child);
$parent-is-map: $parent-type == map;
$child-is-map: $child-type == map;
@if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){
$result: map-merge($result, ( $key: $child ));
}@else {
$result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) ));
}
}
@return $result;
};

View File

@@ -0,0 +1,31 @@
// 间距基础倍数
$uni-space-root: 2;
// 边框半径默认值
$uni-radius-root:5px;
// 主色
$uni-primary: #2979ff;
// 辅助色
$uni-success: #4cd964;
// 警告色
$uni-warning: #f0ad4e;
// 错误色
$uni-error: #dd524d;
// 描述色
$uni-info: #909399;
// 中性色
$uni-main-color: #303133;
$uni-base-color: #606266;
$uni-secondary-color: #909399;
$uni-extra-color: #C0C4CC;
// 背景色
$uni-bg-color: #f5f5f5;
// 边框颜色
$uni-border-1: #DCDFE6;
$uni-border-2: #E4E7ED;
$uni-border-3: #EBEEF5;
$uni-border-4: #F2F6FC;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);

View File

@@ -0,0 +1,62 @@
@import './styles/setting/_variables.scss';
// 间距基础倍数
$uni-space-root: 2;
// 边框半径默认值
$uni-radius-root:5px;
// 主色
$uni-primary: #2979ff;
$uni-primary-disable:mix(#fff,$uni-primary,50%);
$uni-primary-light: mix(#fff,$uni-primary,80%);
// 辅助色
// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
$uni-success: #18bc37;
$uni-success-disable:mix(#fff,$uni-success,50%);
$uni-success-light: mix(#fff,$uni-success,80%);
$uni-warning: #f3a73f;
$uni-warning-disable:mix(#fff,$uni-warning,50%);
$uni-warning-light: mix(#fff,$uni-warning,80%);
$uni-error: #e43d33;
$uni-error-disable:mix(#fff,$uni-error,50%);
$uni-error-light: mix(#fff,$uni-error,80%);
$uni-info: #8f939c;
$uni-info-disable:mix(#fff,$uni-info,50%);
$uni-info-light: mix(#fff,$uni-info,80%);
// 中性色
// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
$uni-main-color: #3a3a3a; // 主要文字
$uni-base-color: #6a6a6a; // 常规文字
$uni-secondary-color: #909399; // 次要文字
$uni-extra-color: #c7c7c7; // 辅助说明
// 边框颜色
$uni-border-1: #F0F0F0;
$uni-border-2: #EDEDED;
$uni-border-3: #DCDCDC;
$uni-border-4: #B9B9B9;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);
// 背景色
$uni-bg-color: #f7f7f7;
/* 水平间距 */
$uni-spacing-sm: 8px;
$uni-spacing-base: 15px;
$uni-spacing-lg: 30px;
// 阴影
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
// 蒙版
$uni-mask: rgba($color: #000000, $alpha: 0.4);

View File

@@ -0,0 +1,2 @@
## 1.0.02021-05-12
1. 支持uni_modules

View File

@@ -0,0 +1,108 @@
<template>
<z-popup v-model="currentValue">
<view class="addresTitle">
<text @click="currentValue = false">取消</text>
<view>所在地区</view>
<text @click="onConfirm">确定</text>
</view>
<z-address :dataList="addressVal" @change="addressChange" :length="length" :force="force"></z-address>
</z-popup>
</template>
<script>
export default {
props: {
dataList: {
type: Array,
default() {
return [];
}
},
value: {
type: Boolean,
default: false
},
length: {
type: Number,
default: 3
},
force:{
type: Boolean,
default: true
}
},
created() {
if (typeof this.value !== 'undefined') {
this.currentValue = this.value;
}
if (this.dataList instanceof Array) {
this.addressVal = this.dataList;
}
},
watch: {
value(val) {
this.currentValue = val;
},
currentValue(val) {
this.$emit(val ? 'on-show' : 'on-hide');
this.$emit('input', val);
},
dataList(val) {
this.addressVal = val;
}
},
data() {
return {
currentValue: false,
//选出的值
addressVal: []
};
},
methods: {
addressChange(val) {
console.log(val);
this.addressVal = val;
},
onConfirm() {
if (parseInt(this.length) <= this.addressVal.length || !this.force && this.addressVal.length > 0) {
this.currentValue = false;
this.$emit('change', this.addressVal);
} else {
uni.showToast({
title: '请选择',
icon: 'none'
});
}
}
},
mounted() {}
};
</script>
<style lang="scss" scoped>
@import '@/style/mixin.scss';
.addresTitle {
display: flex;
justify-content: space-between;
height: 88upx;
line-height: 88upx;
border-bottom: 2upx solid #ebebeb;
padding: 0 20upx;
background-color: #FFF;
}
.addresTitle view {
font-size: 32upx;
}
.addresTitle text {
width: 80upx;
flex-shrink: 0;
text-align: center;
}
.addresTitle text {
font-size: 28upx;
color: #999;
}
.addresTitle text:last-child {
color: $themeColor;
}
</style>

View File

@@ -0,0 +1,78 @@
{
"id": "z-address",
"displayName": "三级联动弹窗,地址选择弹窗,可选长度",
"version": "1.0.0",
"description": "三级联动,地址选择,可选长度",
"keywords": [
"三级联动弹窗",
"地址选择弹窗",
"地区选择弹窗"
],
"repository": "https://github.com/zhouwei1994/uni-app-demo",
"engines": {
"HBuilderX": "^3.0.0"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "465081029"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,28 @@
# 三级联动弹窗,地址选择弹窗,可选长度
三级联动弹窗,地址选择弹窗,可选长度
| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群"` |
| ----------------------------|--------------------------- |
|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
| QQ群号607391225 |微信号zhou0612wei|
### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
### 案例一
```
<z-address-popup v-model="true" :dataList="[]" @change="addressChange" :length="3" :force="force"></z-address-popup>
```
### 属性
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
| dataList | Array | [] | 默认值|
| length | Number | 3 | 地区选择长度1-3 |
| force | Boolean | true | 强制选择,选择长度必须达到指定长度|
| value | Boolean | false | 控制弹窗是否打开 |
### 事件
| 名称 | 类型 | 描述 |
| -----------------|------------------ | --------------------------|
| @change | function | 选择时数据返回 |

View File

@@ -0,0 +1,2 @@
## 1.0.02021-05-12
1. 支持uni_modules

View File

@@ -0,0 +1,175 @@
<template>
<view>
<view class="addres_select_val">
<view>
<view v-for="(item, index) of addressVal" :key="index" :class="{ select: addressIndex == index }" @click="selectType(index)" k>{{ item.name }}</view>
<view
:class="{ select: selectState == addressIndex }"
v-show="selectState < length || (selectState >= length && selectState < 3 && !force)"
@click="selectType(selectState)"
>
请选择
</view>
</view>
</view>
<scroll-view class="addres_box" scroll-y :scroll-top="scrollTop">
<view>
<view
v-for="(item, index) of addressList"
:key="index"
:class="{ select: addressVal.length > addressIndex && item.objId == addressVal[addressIndex].objId }"
@click="selectClick(item)"
>
{{ item.name }}
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
props: {
//选中数据
dataList: {
type: Array,
default() {
return [];
}
},
//联动长度[省,市,区]
length: {
type: Number,
default() {
return 3;
}
},
//是否强制选择,如果length=2,force = false 选择到市的时候就可以确定了,但是还可以选择到区
force: {
type: Boolean,
default() {
return true;
}
}
},
created() {
if (this.dataList instanceof Array) {
this.addressVal = this.dataList;
this.selectState = this.dataList.length;
}
},
watch: {
dataList(val) {
this.addressVal = val;
this.selectState = val.length;
}
},
data() {
return {
//选出的值
addressVal: [],
//当前选择
addressIndex: 0,
//选择的值
addressList: [],
//请选择的显示
selectState: 0,
scrollTop:0
};
},
methods: {
getRegion(pid) {
//请求数据
this.$http.get('api/common/v1/region', { pid: pid }, { load: false }).then(data => {
if (data.length > 0) {
this.addressList = data;
this.scrollTop = 0;
} else {
this.$emit('change', this.addressVal);
}
});
},
//切换对应的类型
selectType(index) {
this.addressIndex = index;
var len = this.addressVal.length;
if (index == 0) {
this.getRegion(0);
} else {
this.getRegion(this.addressVal[index - 1].objId);
}
if (len == this.length) {
this.selectState = this.length;
} else if (len == this.length && index == this.length && this.force) {
this.selectState = index;
} else {
this.selectState = index + 1;
}
},
//选择
selectClick(item) {
if (this.addressIndex == 0) {
this.addressVal = [];
} else {
this.addressVal.splice(this.addressIndex, this.addressVal.length - 1);
}
this.addressVal.push(item);
if (this.addressVal.length < this.length || (this.addressVal.length < 3 && !this.force)) {
this.getRegion(item.objId);
this.addressIndex++;
}
if (this.addressVal.length >= this.length || !this.force) {
this.$emit('change', this.addressVal);
}
this.selectState = this.addressVal.length;
}
},
mounted() {
this.getRegion(0);
}
};
</script>
<style lang="scss" scoped>
@import "@/style/mixin.scss";
.addres_select_val {
padding: 0upx 10upx;
border-bottom: 1upx solid #ebebeb;
box-sizing: border-box;
background-color: #fff;
}
.addres_select_val > view {
display: flex;
flex-wrap: wrap;
}
.addres_select_val > view > view {
margin-left: 20upx;
padding: 0upx 10upx;
height: 72upx;
line-height: 72upx;
border-bottom: 2upx solid #fff;
box-sizing: border-box;
font-size: 28upx;
}
.addres_select_val > view > view:first-child {
margin-left: 0upx;
}
.addres_select_val > view > view.select {
border-bottom: 2upx solid $themeColor;
color: $themeColor;
}
.addres_box {
padding: 0upx 20upx;
height: 420upx;
overflow-y: auto;
background-color: #fff;
}
.addres_box view > view {
height: 72upx;
line-height: 72upx;
font-size: 28upx;
}
.addres_box view > view.select {
color: $themeColor;
}
</style>

View File

@@ -0,0 +1,78 @@
{
"id": "z-address",
"displayName": "三级联动,地址选择,可选长度",
"version": "1.0.0",
"description": "三级联动,地址选择,可选长度",
"keywords": [
"三级联动",
"地址选择",
"地区选择"
],
"repository": "https://github.com/zhouwei1994/uni-app-demo",
"engines": {
"HBuilderX": "^3.0.0"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "465081029"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,27 @@
# 三级联动,地址选择,可选长度
三级联动,地址选择,可选长度
| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群"` |
| ----------------------------|--------------------------- |
|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
| QQ群号607391225 |微信号zhou0612wei|
### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
### 案例一
```
<z-address :dataList="[]" @change="addressChange" :length="3" :force="force"></z-address>
```
### 属性
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
| dataList | Array | [] | 默认值|
| length | Number | 3 | 地区选择长度1-3 |
| force | Boolean | true | 强制选择,选择长度必须达到指定长度|
### 事件
| 名称 | 类型 | 描述 |
| -----------------|------------------ | --------------------------|
| @change | function | 选择时数据返回 |

View File

@@ -0,0 +1,2 @@
## 1.0.02021-05-12
1. 支持uni_modules

View File

@@ -0,0 +1,113 @@
<template>
<view class="mask mask-show" v-if="loadingShow" @touchmove.stop.prevent="preventTouchMove">
<!-- 加载动画开始 -->
<view class="preloader">
<view class="loader"></view>
</view>
<!-- 加载动画结束 -->
<view class="title">加载中...</view>
</view>
</template>
<script scoped="true">
import { mapState, mapMutations } from 'vuex';
export default {
computed: {
...mapState(['loadingShow'])
},
methods:{
preventTouchMove(){
console.log('stop user scroll it!');
return;
}
}
};
</script>
<style>
.mask {
/* pointer-events: none; */
position: fixed;
z-index: 99999;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.mask.mask-show {
background: rgba(255,255,255, 0.3);
}
.title {
color: #333;
font-size: 28rpx;
margin-top: 20rpx;
}
.loader {
display: block;
width: 120rpx;
height: 120rpx;
border-radius: 50%;
border: 3rpx solid transparent;
border-top-color: #54a966;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
.loader::before {
content: "";
position: absolute;
top: 5rpx;
left: 5rpx;
right: 5rpx;
bottom: 5rpx;
border-radius: 50%;
border: 3rpx solid transparent;
border-top-color: #5aa9ac;
-webkit-animation: spin 3s linear infinite;
animation: spin 3s linear infinite;
}
.loader::after {
content: "";
position: absolute;
top: 15rpx;
left: 15rpx;
right: 15rpx;
bottom: 15rpx;
border-radius: 50%;
border: 3rpx solid transparent;
border-top-color: #c4e3ae;
-webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>

View File

@@ -0,0 +1,78 @@
{
"id": "z-loading",
"displayName": "加载中组件",
"version": "1.0.0",
"description": "加载中组件",
"keywords": [
"加载",
"加载中",
"加载组件"
],
"repository": "https://github.com/zhouwei1994/uni-app-demo",
"engines": {
"HBuilderX": "^3.0.0"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "465081029"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,27 @@
# 加载中组件
加载中组件
| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群"` |
| ----------------------------|--------------------------- |
|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
| QQ群号607391225 |微信号zhou0612wei|
### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
### 案例一
```
<z-loading></z-loading>
```
### 用法第一步
```
// vuex里面注册loadingShow变量和setLoadingShow赋值方法
```
### 用法第二步
```
import store from '@/store';
//调用vuex方法打开加载动画
store.commit("setLoadingShow", true);
```

View File

@@ -0,0 +1,2 @@
## 2.0.52021-05-12
1. 支持uni_modules

View File

@@ -0,0 +1,534 @@
<template>
<view>
<view
:class="[navFixed ? 'header_fixed' : '', type == 'transparent' ? 'header_absolute': '', navShadow ? 'header_shadow': '', themeBgColorName]"
:style="[navBgColor ? { backgroundImage: navBgColor } : {}, { paddingTop: statusBarHeight + 'px', color: navFontColor, opacity: transparentValue}]"
>
<view class="header_content">
<view class="header_left_box">
<slot name="left">
<view class="header_left_info" :class="[isTwoBtn ? 'header_btnMongol' : '' , isWhite && isTwoBtn ? 'header_colorWhite_btnMongol' : '']" v-if="back || $slots.left || home">
<view class="header_left_back" :class="[ isTwoBtn ? 'header_btnMongol_left_back' : '' ]" v-if="back && !firstPage" @click="onBackPage">
<image class="header_icon" v-if="isWhite" src="../../static/icon_back_white.png" mode="aspectFit"></image>
<image class="header_icon" v-else src="../../static/icon_back_black.png" mode="aspectFit"></image>
</view>
<text class="header_left_line" :class="[isWhite ? 'header_colorWhite_left_line' : '']" v-if="isTwoBtn"></text>
<view class="header_left_home" :class="[isTwoBtn ? 'header_btnMongol_left_home' : '']" v-if="(firstPage && back) || home" @click="onBackHome">
<image class="header_icon" v-if="isWhite" src="../../static/icon_home_white.png" mode="aspectFit"></image>
<image class="header_icon" v-else src="../../static/icon_home_black.png" mode="aspectFit"></image>
</view>
</view>
</slot>
<view class="header_title" v-if="!titleCenter && ($slots.default || navTitle)" :style="{ color: navFontColor }">
<slot>
<text :style="{ color: navFontColor }">{{ navTitle }}</text>
</slot>
</view>
</view>
<view class="header_title header_title_center" v-if="titleCenter && ($slots.default || navTitle)" :style="{ color: navFontColor }">
<slot>
<text :style="{ color: navFontColor }">{{ navTitle }}</text>
</slot>
</view>
<view class="header_right_info"><slot name="right"></slot></view>
</view>
</view>
<view
class="header_transparentFixed header_fixed"
v-if="type == 'transparentFixed'"
:style="{ paddingTop: statusBarHeight + 'px', color: navTransparentFixedFontColor, opacity: 1 - transparentValue, zIndex: transparentValue < 0.3 ? 100 : 90}"
>
<view class="header_content">
<view class="header_left_box">
<slot name="transparentFixedLeft">
<view
class="header_left_info header_transparentFixed_left_info"
:class="[ isWhite ? 'header_transparentFixed_colorWhite_left_info' : '' ]"
v-if="back || $slots.left || home"
>
<view class="header_left_back" :class="[ isTwoBtn ? 'header_btnMongol_left_back' : '' ]" v-if="back && !firstPage" @click="onBackPage">
<image class="header_icon" v-if="isWhite" src="../../static/icon_back_white.png" mode="aspectFit"></image>
<image class="header_icon" v-else src="../../static/icon_back_black.png" mode="aspectFit"></image>
</view>
<text class="header_left_line" v-if="isTwoBtn"></text>
<view class="header_left_home" :class="[isTwoBtn ? 'header_btnMongol_left_home' : '']" v-if="(firstPage && back) || home" @click="onBackHome">
<image class="header_icon" v-if="isWhite" src="../../static/icon_home_white.png" mode="aspectFit"></image>
<image class="header_icon" v-else src="../../static/icon_home_black.png" mode="aspectFit"></image>
</view>
</view>
</slot>
<view class="header_title" v-if="!titleCenter && (navTitle || $slots.transparentFixed)" :style="{ color: navTransparentFixedFontColor }">
<slot name="transparentFixed">
<text :style="{ color: navTransparentFixedFontColor }">{{ navTitle }}</text>
</slot>
</view>
</view>
<view class="header_title header_title_center" v-if="titleCenter && (navTitle || $slots.transparentFixed)" :style="{ color: navTransparentFixedFontColor }">
<slot name="transparentFixed">
<text :style="{ color: navTransparentFixedFontColor }">{{ navTitle }}</text>
</slot>
</view>
<view class="header_right_info"><slot name="transparentFixedRight"></slot></view>
</view>
</view>
<view v-if="type == 'fixed'" :style="{ paddingTop: statusBarHeight + 'px' }"><view class="header_station"></view></view>
</view>
</template>
<script>
import componentConfig from "@/config/componentConfig"
//白色表达值
const whiteList = ['#FFF', '#fff', '#FFFFFF', '#ffffff', 'white', 'rgb(255,255,255)', 'rgba(255,255,255,1)'];
export default {
props: {
//是否显示返回按钮
// 1000 显示返回按钮
// 2000 不显示返回按钮
// 3000 自定义返回按钮方法点击返回箭头后会发送一个backClick事件
backState: {
type: [String, Number],
default: function() {
return 1000;
}
},
//是否显示返回首页按钮
// 1000 显示首页按钮
// 2000 不显示首页按钮
// 3000 自定义首页按钮方法点击首页箭头后会发送一个homeClick事件
homeState: {
type: [String, Number],
default: function() {
return 2000;
}
},
//导航背景色,支持渐变
bgColor: {
type: [String, Array],
default: function() {
return '#FFFFFF';
}
},
// 导航背景色渐变角度
bgColorAngle: {
type: [String, Number],
default: function() {
return 90;
}
},
//导航字体颜色,字体颜色为白色的时候会把手机状态栏设置为白色,否则为黑色
fontColor: {
type: String,
default: function() {
return '#000000';
}
},
//标题是否居中
titleCenter: {
type: Boolean,
default: function() {
return true;
}
},
//标题
title: {
type: String,
default: function() {
return '';
}
},
//类型 fixed为固定 默认
// ordinary 普通的 不固定
// transparent 透明不固定的
//transparentFixed 透明固定的
type: {
type: String,
default: function() {
return 'fixed';
}
},
//透明固定的时候字体颜色
transparentFixedFontColor: {
type: String,
default: function() {
return '#000000';
}
},
// 屏幕滑动距离顶部距离(透明固定导航比传)
scrollTop: {
type: Number,
default: function() {
return 0;
}
},
// 是否显示阴影
shadow: {
type: Boolean,
default: function() {
return false;
}
}
},
data() {
return {
//当前页面是否是第一个页面
firstPage: false,
//透明度值
transparentValue: 1,
//标题
navTitle: '',
//字体色
navFontColor: '#000000',
//背景色
navBgColor: '',
//透明底字体色
navTransparentFixedFontColor: '#000000',
// 导航栏高度
statusBarHeight: 0,
// 上次显示的导航栏颜色
lastFrontColor: '',
themeBgColorName: '',
};
},
computed: {
back() {
return this.backState == 1000 || this.backState == 3000;
},
home() {
return this.homeState == 1000;
},
//导航固定
navFixed() {
if (this.type == 'transparentFixed' || this.type == 'fixed') {
return true;
} else {
return false;
}
},
//导航底部线是否显示
navShadow() {
if (this.bgColor && typeof this.bgColor == 'string') {
return this.shadow && this.type !== 'transparent' && whiteList.includes(this.bgColor);
} else {
return false;
}
},
//导航字体是否是白色颜色
isWhite() {
return whiteList.includes(this.navFontColor);
},
//右上角是否有两个按钮
isTwoBtn() {
return (this.backState == 1000 || this.backState == 3000) && this.homeState == 1000 && !this.firstPage;
}
},
watch: {
title(val) {
this.navTitle = val;
},
fontColor(val) {
this.navFontColor = val;
this.settingColor();
},
bgColor(val) {
this.getNavBgColor(val);
},
transparentFixedFontColor(val) {
this.navTransparentFixedFontColor = val;
},
scrollTop(val) {
this.pageScroll({
scrollTop: val
});
}
},
//第一次加载
created() {
this.navTitle = this.title;
this.navFontColor = this.fontColor;
this.getNavBgColor(this.bgColor);
this.navTransparentFixedFontColor = this.transparentFixedFontColor;
//获取手机状态栏高度
this.statusBarHeight = uni.getSystemInfoSync()['statusBarHeight'];
const _this = this;
this.pageScroll({
scrollTop: this.scrollTop
});
//获取所有页面
let currentPages = getCurrentPages();
let pageLen = currentPages.length;
//判断是否是第一个页面如果是有设置back为true的页面将不显示返回箭头而显示返回首页按钮
if (pageLen == 1 && !componentConfig.mainPagePath.includes(currentPages[0].route)) {
this.firstPage = true;
}
},
//方法
methods: {
//返回上一页面
onBackPage() {
if (this.backState == 3000) {
this.$emit('backClick');
} else {
uni.navigateBack();
}
},
//返回首页
onBackHome() {
if(this.homeState == 3000){
this.$emit('homeClick');
} else {
uni.reLaunch({
url: componentConfig.homePath
});
}
},
pageScroll(e) {
if (this.type == 'transparentFixed') {
if (e.scrollTop && e.scrollTop > 0) {
if (e.scrollTop > 180) {
this.transparentValue = 1;
} else {
this.transparentValue = e.scrollTop / 180;
}
} else {
this.transparentValue = 0;
}
this.settingColor();
}
},
// 获取导航背景颜色
getNavBgColor(val) {
if (typeof val == 'string') {
if (this.type == 'transparent') {
this.navBgColor = '';
} else if (/^#|rgb\(|rgba\(/.test(val)) {
this.navBgColor = 'linear-gradient(90deg,' + val + ',' + val + ')';
} else {
this.themeBgColorName = val;
this.navBgColor = '';
}
} else if (Array.isArray(val) && val.length >= 2) {
let navBgColor = 'linear-gradient(' + this.bgColorAngle + 'deg';
val.forEach(item => {
if (typeof item == 'string') {
navBgColor += ',' + item;
} else if (typeof item == 'object') {
navBgColor += ',' + item.color + ' ' + item.scale;
}
});
navBgColor += ')';
this.navBgColor = navBgColor;
}
},
//设置手机状态栏颜色
settingColor() {
let navColor = this.navFontColor;
if (this.type == 'transparentFixed' && this.transparentValue <= 0.5) {
navColor = this.navTransparentFixedFontColor;
}
let frontColor = '#000000';
if (whiteList.includes(navColor)) {
frontColor = '#ffffff';
}
if (this.lastFrontColor == frontColor) {
return;
}
setTimeout(() => {
this.lastFrontColor = frontColor;
// 改变手机状态栏颜色
uni.setNavigationBarColor({
frontColor: frontColor,
backgroundColor: '#FFFFFF'
});
}, 150);
}
}
};
</script>
<style lang="scss">
.header_content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
/* #ifdef MP */
padding-right: 190rpx;
box-sizing: border-box;
/* #endif */
width: 750rpx;
align-items: flex-end;
justify-content: space-between;
flex-direction: row;
height: 88rpx;
position: relative;
}
.header_station {
height: 88rpx;
}
.header_shadow {
// border-style: solid;
// border-width: 2rpx;
// border-color: #f5f5f5;
box-shadow: 0 0 6rpx 0 #ddd;
}
.header_fixed {
position: fixed;
top: 0;
left: 0;
width: 750rpx;
z-index: 99;
}
.header_absolute {
position: absolute;
top: 0;
left: 0;
z-index: 99;
width: 750rpx;
background-color: transparent !important;
}
.header_left_box {
/* #ifndef APP-PLUS-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
height: 88rpx;
flex: 1;
}
.header_left_line {
height: 30rpx;
width: 2rpx;
background-color: rgba(255, 255, 255, 0.4);
}
.header_left_back {
width: 56rpx;
height: 100%;
/* #ifndef APP-PLUS-NVUE */
display: flex;
/* #endif */
align-items: center;
justify-content: center;
}
.header_icon {
width: 30rpx;
height: 30rpx;
}
.header_left_home {
width: 56rpx;
height: 100%;
/* #ifndef APP-PLUS-NVUE */
display: flex;
/* #endif */
align-items: center;
justify-content: center;
}
.header_left_info {
/* #ifndef APP-PLUS-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
height: 56rpx;
margin-left: 16rpx;
}
.header_title {
width: 80%;
height: 88rpx;
font-size: 32rpx;
padding-left: 30rpx;
padding-right: 30rpx;
font-weight: 700;
text-overflow: ellipsis;
/* #ifndef APP-PLUS-NVUE */
white-space: nowrap;
display: flex;
overflow: hidden;
/* #endif */
/* #ifdef APP-PLUS-NVUE */
lines: 1;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
/* #ifdef MP */
max-width: calc(100vw - 160rpx);
/* #endif */
}
.header_title_center {
position: absolute;
bottom: 0rpx;
left: 375rpx;
transform: translateX(-50%);
}
.header_right_info {
height: 88rpx;
/* #ifndef APP-PLUS-NVUE */
display: flex;
flex-shrink: 0;
/* #endif */
flex-direction: row;
align-items: center;
}
.header_btnMongol {
border-radius: 33rpx;
border-style: solid;
border-width: 2rpx;
border-color: rgba(0, 0, 0, 0.1);
background-color: rgba(255, 255, 255, 0.7);
/* #ifndef APP-PLUS-NVUE */
box-sizing: border-box;
/* #endif */
}
.header_btnMongol_left_back,
.header_btnMongol_left_home {
width: 70rpx;
}
.header_transparentFixed {
border-bottom-width: 0;
background-color: transparent;
background-image: transparent;
}
.header_transparentFixed_left_info {
border-style: solid;
border-width: 2rpx;
border-color: rgba(0, 0, 0, 0.1);
background-color: rgba(255, 255, 255, 0.7);
border-radius: 33rpx;
/* #ifndef APP-PLUS-NVUE */
box-sizing: border-box;
/* #endif */
}
.header_transparentFixed_colorWhite_left_info {
border-style: solid;
border-width: 2rpx;
border-color: rgba(255, 255, 255, 0.3);
background-color: rgba(0, 0, 0, 0.2);
}
//颜色白色
.header_colorWhite_btnMongol {
border-style: solid;
border-width: 2rpx;
border-color: rgba(255, 255, 255, 0.3);
background-color: rgba(0, 0, 0, 0.2);
}
.header_colorWhite_left_line {
background-color: rgba(255, 255, 255, 0.3);
}
</style>

View File

@@ -0,0 +1,79 @@
{
"id": "z-nav-bar",
"displayName": "zhouWei-navBar 适用于 uni-app 项目的头部导航组件支持V3编译、nvue编译",
"version": "2.0.5",
"description": "导航栏组件主要用于头部导航主流平台都支持。自动改变导航栏颜色和头部返回首页支持nvue、V3",
"keywords": [
"导航栏",
"nvue",
"navBar",
"顶部导航"
],
"repository": "https://github.com/zhouwei1994/uni-app-demo",
"engines": {
"HBuilderX": "^3.0.0"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "465081029"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,141 @@
# zhouWei-navBar 适用于 uni-app 项目的头部导航组件支持V3编译、nvue编译
导航栏组件主要用于头部导航组件名zhouWei-navBar
本组件目前兼容微信小程序、H5、5+APP。其他平台没试过
本组件支持模式:
1. 普通固定顶部导航
2. 透明导航
3. 透明固定顶部导航
4. 不固定普通导航
5. 颜色渐变导航
本组件内置特殊功能:
1. fontColor字体颜色为白色的时候手机状态栏会自动显示白色否则显示灰色
2. 页面为第一个页面时左上角自动显示返回主页的图标(具体看组件zhouWei-navBar/index.vue =>页面script)
3. nvue页面必须在当前页面引入本组件才可以使用
| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群"` |
| ----------------------------|--------------------------- |
|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
| QQ群号607391225 |微信号zhou0612wei|
### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
# `关键配置`config/componentConfig.js
```
export default {
// 主页页面的页面路径
// 关联功能:打开的页面只有一个的时候右上角自动显示返回首页按钮,下面这个数组是排除显示返回首页的页面。
// 主页使用场景:小程序分享出去的页面,用户点击开是分享页面,很多情况下是没有返回首页按钮的
mainPagePath: ['pages/home/home', 'pages/my/my', 'pages/demo/common', 'pages/template/common', 'pages/apiDemo/common', "pages/template/addTemplate"],
//返回首页的地址
homePath: '/pages/template/addTemplate'
}
```
### 案例一
默认特性左上角有返回箭头nav-bar导航固定在顶部、标题居中
```
<z-nav-bar>我的</z-nav-bar>
```
### 案例二
特性无返回箭头、字体色为白色、标题左对齐、nav-bar导航透明并不固定在顶部、右边插槽有按钮
```
<z-nav-bar backState="2000" fontColor="#FFF" :titleCenter="false" type="transparent" title="我的">
<view class="icon_setUp" slot="right">设置</view>
</z-nav-bar>
```
### 案例三:颜色渐变导航
特性:颜色渐变导航
```
<z-nav-bar home :bgColor="['#f37402','#0f0']" bgColorAngle="90" fontColor="#FFF" title="颜色渐变导航"></z-nav-bar>
```
### 案例四:颜色渐变导航
特性:颜色渐变导航
```
<z-nav-bar :bgColor="bgColorList" bgColorAngle="45" fontColor="#FFF" title="颜色渐变导航"></z-nav-bar>
<!-- bgColor值 -->
bgColorList:[
{color:"#f37402",scale:"0%"},
{color:"#0f0",scale:"20%"},
{color:"#f00",scale:"80%"},
{color:"#00f",scale:"100%"}
]
```
### 案例五:滑动透明导航
特性有返回箭头、nav-bar导航透明并固定在顶部、透明状态字体为白色、页面想下滑动nav-bar导航条逐渐变白色、右边插槽有按钮
```
<z-nav-bar ref="navBar" :scrollTop="scrollTop" transparentFixedFontColor="#FFF" type="transparentFixed" title="我的简历">
<view class="transparent_fixed_preview" slot="transparentFixedRight" @click="onPreview">预览</view> //透明状态下的按钮
<view class="preview" slot="right" @click="onPreview">预览</view> //不状态下的按钮
</z-nav-bar>
```
```
//设置滚动值方法一:
data() {
return {
scrollTop:0
}
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
}
//设置滚动值方法二:
onPageScroll (e) {
this.$refs.navBar.pageScroll(e);
}
```
### 案例六:搜索框|地区选择
特性无返回箭头、nav-bar导航固定在顶部、地区选择、搜索框
```
<z-nav-bar backState="2000">
<view slot="left" class="address_select">深圳市</view>
<view slot="right" class="search_box" @click="onPageJump('/pages/home/search')">
<text class="icon_search"></text>
<text class="tips">搜索目的地/职位等</text>
</view>
</z-nav-bar>
```
### 属性
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
| backState | String | 1000 | 返回上一页面按钮,`1000` 显示返回按钮,`2000` 不显示返回按钮,`3000`自定义返回按钮方法,点击返回箭头后会发送一个`backClick`事件|
| home | Boolean | true | 返回首页按钮(首页地址在源文件里配置) |
| bgColor | StringArray | #FFF | 导航背景颜色,值为数组的时候显示渐变颜色,`bgColor="themeBgColor"`的时候会调用全局`class="themeBgColor"`的样式|
| bgColorAngle | StringNumber | 90 | 导航背景颜色渐变角度(`bgColor`为数组生效) |
| fontColor | String | #000 | 导航字体颜色,(当颜色为白色的时候导航状态栏和图片为白色的)|
| titleCenter | Boolean | true | 标题`title`居中 |
| title | String | -- | 标题`title`值 |
| transparentFixedFontColor | String | #000 | 导航`type`类型为`transparentFixed`时透明状态下的字体颜色 |
| type | String | fixed | 导航类型可选1.`fixed`固定导航 2.`ordinary`不固定导航 3.`transparent`透明不固定导航 4.`transparentFixed`透明固定导航|
| scrollTop | Number | 0 | 导航`type`类型为`transparentFixed`时页面滚动值(`具体看上面的案例五`|
| shadow | Boolean | true | 是否显示底边阴影 |
### bgColor数组值为JSON的参数
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
| color | String | -- | 渐变颜色值 |
| scale | String | -- | 渐变比例(百分比% |
### 插槽
| 名称 | 描述 |
| ----------------------|-------------------------------------------------------------------|
| left | 左插槽 |
| default | 中间标题插槽(`type`类型为`transparentFixed`时插槽只会穿透到实色背景下) |
| right | 右插槽 |
| transparentFixed | 导航`type`类型为`transparentFixed`时透明状态下中间插槽 |
| transparentFixedRight | 导航`type`类型为`transparentFixed`时透明状态下右插槽 |
| transparentFixedRight | 导航`type`类型为`transparentFixed`时透明状态下右插槽 |
### 事件type类型为transparentFixed时可用
| 名称 | 参数 | 描述 |
| -----------------|------------------ | --------------------------|
| backClick | 返回上一页按钮方法 | `backState=3000`时生效 |

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

View File

@@ -0,0 +1,14 @@
## 2.0.12021-08-16
1.自定义下拉刷新view无需设置`refresher-threshold`将根据view自动计算高度。
2.修复在iOS 13中下拉刷新抖动的问题。
3.新增`inside-more`,支持在分页未满一屏时自动加载下一页。
4.修复z-paging prop代码自动补全无效的问题完善代码自动补全文档注释。
5.修复在微信小程序中提示uni is not defined的bug。
6.修复在某些情况下下拉刷新页面会跟着下拉的bug。
7.其他细节优化。
## 2.0.02021-08-16
1.自定义下拉刷新view无需设置`refresher-threshold`将根据view自动计算高度。
2.修复在iOS 13中下拉刷新抖动的问题。
3.新增`inside-more`,支持在分页未满一屏时自动加载下一页。
4.修复z-paging prop代码自动补全无效的问题完善代码自动补全文档注释。
5.其他细节优化。

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,161 @@
/* z-paging
github地址:https://github.com/SmileZXLee/uni-z-paging
dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
反馈QQ群790460711
*/
.z-paging-content {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
width: 100%;
height: 100%;
/* #endif */
flex-direction: column;
}
.z-paging-content-fixed {
position: fixed;
/* #ifndef APP-NVUE */
height: auto;
width: auto;
/* #endif */
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.zp-page-scroll-top,
.zp-page-scroll-bottom {
/* #ifndef APP-NVUE */
width: auto;
/* #endif */
position: fixed;
left: 0;
right: 0;
z-index: 999;
}
.zp-scroll-view-super {
flex: 1;
position: relative;
}
.zp-custom-refresher-container {
overflow: hidden;
}
.zp-scroll-view {
height: 100%;
width: 100%;
}
.zp-scroll-view-absolute {
position: absolute;
top: 0;
left: 0;
}
.zp-paging-touch-view {
width: 100%;
height: 100%;
position: relative;
}
.zp-fixed-bac-view {
position: absolute;
width: 100%;
top: 0;
left: 0;
height: 200px;
}
.zp-paging-main {
height: 100%;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.zp-paging-container {
flex: 1;
position: relative;
}
.zp-chat-record-loading-container {
/* #ifndef APP-NVUE */
display: flex;
width: 100%;
/* #endif */
/* #ifdef APP-NVUE */
width: 750rpx;
/* #endif */
align-items: center;
justify-content: center;
height: 60rpx;
font-size: 26rpx;
}
.zp-chat-record-loading-custom-image {
width: 35rpx;
height: 35rpx;
/* #ifndef APP-NVUE */
animation: loading-flower 1s linear infinite;
/* #endif */
}
.zp-custom-refresher-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
}
.zp-back-to-top {
width: 76rpx;
height: 76rpx;
z-index: 999;
position: absolute;
bottom: 0rpx;
right: 25rpx;
transition-duration: .3s;
transition-property: opacity;
}
.zp-back-to-top-show {
opacity: 1;
}
.zp-back-to-top-hide {
opacity: 0;
}
.zp-back-to-top-img {
/* #ifndef APP-NVUE */
width: 100%;
height: 100%;
/* #endif */
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
z-index: 999;
}
.zp-empty-view {
/* #ifdef APP-NVUE */
height: 100%;
/* #endif */
flex: 1;
}
.zp-n-refresh-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
width: 750rpx;
}

View File

@@ -0,0 +1,38 @@
/* z-paging
github地址:https://github.com/SmileZXLee/uni-z-paging
dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
反馈QQ群790460711
公用的静态css资源 */
.zp-loading-more-line-loading-image {
margin-right: 8rpx;
width: 28rpx;
height: 28rpx;
/* #ifndef APP-NVUE */
animation: loading-flower 1s steps(12) infinite;
/* #endif */
color: #666666;
}
.zp-loading-image-ios{
width: 20px;
height: 20px;
}
.zp-loading-image-android{
width: 32rpx;
height: 32rpx;
}
@keyframes loading-flower {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}

View File

@@ -0,0 +1,32 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// z-paging配置文件
let config = null;
let getedStorage = false;
const storageKey = 'Z-PAGING-CONFIG-STORAGE-KEY'
function setConfig(value) {
try {
uni.setStorageSync(storageKey, value);
} catch {}
}
function getConfig() {
try {
if (getedStorage) {
return config;
}
config = uni.getStorageSync(storageKey);
getedStorage = true;
} catch {
return null;
}
}
module.exports = {
setConfig,
getConfig
};

View File

@@ -0,0 +1,150 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// z-paging国际化(支持中文、中文繁体和英文)
const i18nUpdateKey = 'z-paging-i18n-update';
const refresherDefaultText = {
'en': 'Pull down to refresh',
'zh-cn': '继续下拉刷新',
'zh-hant-cn': '繼續下拉重繪',
}
const refresherPullingText = {
'en': 'Release to refresh',
'zh-cn': '松开立即刷新',
'zh-hant-cn': '鬆開立即重繪',
}
const refresherRefreshingText = {
'en': 'Refreshing...',
'zh-cn': '正在刷新...',
'zh-hant-cn': '正在重繪...',
}
const loadingMoreDefaultText = {
'en': 'Click to load more',
'zh-cn': '点击加载更多',
'zh-hant-cn': '點擊加載更多',
}
const loadingMoreLoadingText = {
'en': 'Loading...',
'zh-cn': '正在加载...',
'zh-hant-cn': '正在加載...',
}
const loadingMoreNoMoreText = {
'en': 'No more data',
'zh-cn': '没有更多了',
'zh-hant-cn': '沒有更多了',
}
const loadingMoreFailText = {
'en': 'Load failed,click to reload',
'zh-cn': '加载失败,点击重新加载',
'zh-hant-cn': '加載失敗,點擊重新加載',
}
const emptyViewText = {
'en': 'No data',
'zh-cn': '没有数据哦~',
'zh-hant-cn': '沒有數據哦~',
}
const emptyViewReloadText = {
'en': 'Reload',
'zh-cn': '重新加载',
'zh-hant-cn': '重新加載',
}
const emptyViewErrorText = {
'en': 'Sorry,load failed',
'zh-cn': '很抱歉,加载失败',
'zh-hant-cn': '很抱歉,加載失敗',
}
const refresherUpdateTimeText = {
'en': 'Last update: ',
'zh-cn': '最后更新:',
'zh-hant-cn': '最後更新:',
}
const refresherUpdateTimeNoneText = {
'en': 'None',
'zh-cn': '无',
'zh-hant-cn': '無',
}
const refresherUpdateTimeTodayText = {
'en': 'Today',
'zh-cn': '今天',
'zh-hant-cn': '今天',
}
const refresherUpdateTimeYesterdayText = {
'en': 'Yesterday',
'zh-cn': '昨天',
'zh-hant-cn': '昨天',
}
// 插件内部使用,请勿直接调用
function getPrivateLanguage(myLanguage, followSystemLanguage = true) {
let systemLanguage = '';
if (followSystemLanguage) {
systemLanguage = uni.getSystemInfoSync().language;
}
let language = myLanguage || uni.getStorageSync(i18nUpdateKey) || systemLanguage;
language = language.toLowerCase();
var reg = new RegExp('_', '');
language = language.replace(reg, '-');
if (language.indexOf('zh') !== -1) {
if (language === 'zh' || language === 'zh-cn' || language.indexOf('zh-hans') !== -1) {
return 'zh-cn';
}
return 'zh-hant-cn';
}
if (language.indexOf('en') !== -1) {
return 'en';
}
return 'zh-cn';
}
// 获取当前语言,格式为:zh-cn、zh-hant-cn、en。followSystemLanguage:获取的结果是否是在不跟随系统语言下获取到的
function getLanguage(followSystemLanguage = true) {
return getPrivateLanguage(false, followSystemLanguage);
}
// 获取当前语言,格式为:简体中文、繁體中文、English。followSystemLanguage:获取的结果是否是在不跟随系统语言下获取到的
function getLanguageName(followSystemLanguage = true) {
const language = getLanguage(followSystemLanguage);
const languageNameMap = {
'zh-cn': '简体中文',
'zh-hant-cn': '繁體中文',
'en': 'English'
};
return languageNameMap[language];
}
function setLanguage(myLanguage) {
uni.setStorageSync(i18nUpdateKey, myLanguage);
uni.$emit(i18nUpdateKey, myLanguage);
}
module.exports = {
refresherDefaultText,
refresherPullingText,
refresherRefreshingText,
loadingMoreDefaultText,
loadingMoreLoadingText,
loadingMoreNoMoreText,
loadingMoreFailText,
emptyViewText,
emptyViewReloadText,
emptyViewErrorText,
getPrivateLanguage,
getLanguage,
getLanguageName,
setLanguage,
refresherUpdateTimeText,
refresherUpdateTimeNoneText,
refresherUpdateTimeTodayText,
refresherUpdateTimeYesterdayText
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 使用页面滚动时引入此mixin用于监听和处理onPullDownRefresh等页面生命周期方法
const ZPagingMixin = {
onPullDownRefresh() {
if (this.isPagingRefNotFound()) {
return;
}
this.$refs.paging.reload();
},
onPageScroll(e) {
if (this.isPagingRefNotFound()) {
return;
}
this.$refs.paging.updatePageScrollTop(e.scrollTop);
if (e.scrollTop < 10) {
this.$refs.paging.doChatRecordLoadMore();
}
},
onReachBottom() {
if (this.isPagingRefNotFound()) {
return;
}
this.$refs.paging.doLoadMore();
},
methods: {
isPagingRefNotFound() {
return !this.$refs.paging || this.$refs.paging === undefined;
}
}
}
export default ZPagingMixin;

View File

@@ -0,0 +1,25 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 公用的静态图片资源
const base64Arrow =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAD1BMVEVHcExRUVFMTExRUVFRUVE9CdWsAAAABHRSTlMAjjrY9ZnUjwAAAQFJREFUWMPt2MsNgzAMgGEEE1B1gKJmAIRYoCH7z9RCXrabh33iYktcIv35EEg5ZBh07pvxJU6MFSPOSRnjnBUjUsaciRUjMsb4xIoRCWNiYsUInzE5sWKEyxiYWDbyefqHx1zIeiYTk7mQYziTYecxHvEJjwmIT3hMQELCYSISEg4TkZj0mYTEpM8kJCU9JiMp6TEZyUmbAUhO2gxAQNJiIAKSFgMRmNQZhMCkziAEJTUGIyipMRjBSZkhCE7KDEFIUmTeGCHJxWz0zXaE0GTCG8ZFtEaS347r/1fe11YyHYVfubxayfjoHmc0YYwmmmiiiSaaaKLJ7ckyz5ve+dw3Xw2emdwm9xSbAAAAAElFTkSuQmCC';
const base64ArrowWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEVHcEz///////////////////+IGTx/AAAABnRSTlMA/dAkXZOhASU/AAABYElEQVRYw+2YwXLCIBCGsdAHWGbyAKZ4zxi9O017rxLf/1UaWFAgA1m8dcpedNSPf/l/Vh0Ya/Wn6hN0JcGvoCqRM4C8VBFiDwBqqNuJKV0rAnCgy3AUqZE57x0iqTL8Br4U3WBf/YWaIlTKfAcELU/h9w72CSVPa3C3OCDvhpHbRp/s2vq4fHhCeiCl2A3m4Qd71DQR257mFBlMcTlbFnFWzNtHxewYEfSiaLS4el8d8nyhmKJd1CF4eOS0keLMAuSxubLBIeIGQW8YHCFFo7EH9+YDcQt9FMZEswTheaNxTHwHT8SZorJjMrEVwo4Zo0U8HSEyZvJMOg4RjnmmRr8nDYeIz3OMkbfE/QhBo+U9RnZJxjGCRh/WKmHEMWLNkfPKsGh/CWJk1JjG0kcuJggTt34VDP8aWAFhp4nybVb5+9qQhjSkIQ1pSEMa8k+Q5U9rV3dF8MpFBK+/7miVq1/HZ2qmo9D+pAAAAABJRU5ErkJggg=='
const base64Flower =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAKlBMVEVHcEzDw8Ovr6+pqamUlJTCwsKenp61tbWxsbGysrLNzc2bm5u5ubmjo6MpovhuAAAACnRSTlMA/P79/sHDhiZS0DxZowAABBBJREFUWMPtl89rE0EUx7ctTXatB3MI1SWnDbUKPUgXqh4ED8Uf7KUVSm3ooVSpSii0Fn/gD4j4o+APiEoVmos9FO2celiqZVgwgaKHPQiCCkv+F99kM7Ozm5kxq1dfD91k9pPve9/3ZjbRNHHok/mKli4eIPNgSuRObuN9SqSEzM20iGnm0yIbqCuV7NSSSIV7uyPM6JMBYdeTOanh/QihJYZsUCSby+VkMj2AvOt0rAeQAwqE3lfKMZVlQCZk1QOCKkkVPadITCfIRNKxfoJI5+0OIFtJx14CMSg1mRSDko7VAfksRQzEbGYqxOJcVTWMCH2I1/IACNW0PWU2M8cmAVHtnH5mM1VRWtwKZjOd5JbF6s1IbaYqaotjNlPHgDAnlAizubTR6ovMYn052g/U5qcmOpi0WL8xTS/3IfSet5m8MEr5ajjF5le6dq/OJpobrdY0t3i9QgefWrxW9/1BLhk0E9m8FeUMhhXal499iD0eQRfDF+ts/tttORRerfp+oV7f4xJj82iUYm1Yzod+ZQEAlS/8mMBwKebVmCVp1f0JLS6zKd17+iwRKTARVg2SHtz3iEbBH+Q+U28zW2Jiza8Tjb1YFoYZMsJyjDqp3M9XBQdSdPLFdxEpvOB37JrHcmR/y9+LgoTlCFGZEa2sc6d4PGlweEa2JSVPoVm+IfGG3ZL037iV9oH+P+Jxc4HGVflNq1M0pivao/EopO4b/ojVCP9GjmiXOeS0DOn1o/iiccT4ORnyvBGF3yUywkQajW4Ti0SGuiy/wVSg/L8w+X/8Q+hvUx8Xd90z4oV5a1i88MbFWHz0WZZ1UrTwBGPX3Rat9AFiXRMRjoMdIdJLEOt2h7jrYOzgOamKZSWSNspOS0X8SAqRYmxRL7sg4eLzYmNehcxh3uoyud/BH2Udux4ywxFTc1xC7Mgf4vMhc5S+kSH3Y7yj+qpwIWSoPTVCOOPVthGx9FbGqrwFw6wSFxJr+17zeKcztt3u+2roAEVgUjDd+AHGuxHy2rZHaa8JMkTHEeyi85ANPO9j9BVuBRD2FY5LDMo/Sz/2hReqGIs/KiFin+CsPsYO/yvM3jL2vE8EbX7/Bf8ejtr2GLN65bioAdgLd8Bis/mD5GmP2qeqyo2ZwQEOtAjRIDH7mBKpUcMoApbZJ5UIxkEwxyMZyMxW/uKFvHCFR3SSmerHyDNQ2dF4JG6zIMpBgLfjSF9x1D6smFcYnGApjmSLICO3ecCDWrQ48geba9DI3STy2i7ax6WIB62fSyIZIiO3GFQqSURp8wCo7GhJBGwuSovJBNjb7kT6FPVnIa9qJ2Ko+l9mefGIdinaMp0yC1URYiwsdfNE45EuA5Cx9EhalfvN5s+UyItm81vaB3p4joniN+SCP7Qc1hblAAAAAElFTkSuQmCC';
const base64FlowerWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEX///9HcEz///////////////84chYNAAAABnRSTlP/AGzCOYZj5g1nAAACfklEQVRYw+2YTVPDIBCGtza9Jw25a0bvcax30o73OOr//yvma2F3YWlpPTijXNpAHrK8LLALVPFium2vNIFSbwGKTGQA2GUiHcD29yDNy3sMIdUBQl7r2H8mOEVqAHgPkYZUS6Qc2zYhQqtjyDZEximCZwWZLIBeIgYShs2NzxKpSUehYpMJhURGb+O+w5BpMCAREKPnCDHbIY20SzhM5yxziAXpOiBXydrekT9i5XDEq4NIIHHgyU5mRGqviII4mREJJA4QJzMiILwlRJzpKxJKvCBm8OsBBbLux0tsPl4RKYm5aPu6jw1U4mGxEUR9g8M1PcqBEp/WJliNgYOXueBzS4jZSIcgY5lCtevgDSgyzE+rAfuOTQMq0yzvoGH18qju27Mayzs4fPyMziCx81NJa5RNfW7vPYK9KOfDiVkBxFHG8hAj9txuoBuSWORsFfkpBf7xKFLSeaOefEojh5jz22DJEqMP8fUyaKdQx+RnG+yXMpe8Aars8ueR1pVH/bW3FyyvPRw90upLDHwpgBDtg4aUBNkxRLXMAi03IhcZtr1m+FeI/O/JNyDmmL1djLOauSlNflBpW18RQ2bPqXI22MXXEk75KRHTnkPkYbESbdKP2ZFk0r5sIwffAjy1lx+vx7NLjB6/E7Jfv5ERKhzpN0w8IDE8IGFDv5dhz10s7GFiXRZcUeLCEG5P5nDq9k4PFDcoMpE3GY4OuxuCXhmuyNB6k0RsLIAvqp9NE5r8ZCSS8gxnUp7ODdYhZTqxuiJ9uyJJtPmpqJ7wVj+XVieS903iViHziqAhchLEJAyb7jWU647EpUofQ0ziUuXXXhDddtlllSwjgSQu7r4BRWhQqfDPMVwAAAAASUVORK5CYII='
const base64Empty = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAbUExURdvc3EdwTMLBwcjIyLSzs/Hx8ff39////19dXXz7IJEAAAAFdFJOU/4A6J9QDyyutAAAB5VJREFUeNrtnM1z4jYYxhUHkR4hdu9eU7Z75Ct7jgPbs9ZZmSuTrUWPmXTA186e+LMrf0uWLMtf2WkHXQgzln88et5XeiVMwPQdGrhCrpAr5Aq5Qv4TkJ07OGQFMLp1B4VYCz+kDblDQhJGeH4eEDLBYdLOHwaDWNBPIeHLYJAJ3meQ83IoCMTHDBKOBoKYGOeM8G0gyD0LObnDQB5ZSCtTNCBfsM9AboaBPLCQcDAIM1zht/dQEkMsd1DjI4hpw2YzMtBJeBbydWpCTJs3YDKGX62YgfGoVwi9KwtZJAzcYHHRm7sYCKD390nQSIoO5JGZIEOYxNoZ4+deISYLyeL5hLHbJ2QK98W0kudMgJe9Qh73odhO+KZHyNYGvgQS9gmJKhUigwSj3iBPUhXxePWmxBqHw0Mej9WQ3qILVjLC177yxNxXQ/7uK+Mn1aNVLsGsBTaWrSAPobYl0aUHt2fIs2Rgz7c9QYL0pSTkSzILLFtAJMH1cidN998T9E0/Sg73/pEEwrgkYRh86wlC949gJsR6EobBcz8hHOVgKYi2m6kZtodIkjEQvF3QjbGpmplB4/lRgJhxgRS2N15iijAvPmByDtCxfQhPJ8J4CR82rgCCBILarScw6X0OcMUyYrFVmbxErl0ZacFIoloOLdJAO42qY+NMDss2kKS8xmiZxcCpFKXWvpRGbQqJp5ixyRfJMmR6x0Fk+z29kmgWDYI5ziFbdug/84HxvduhWhLOJ2StPDQrMJPSjNANklh8QhB7dBO0yTGRwn1fkOk8rbQjiB8Ymww+JuiuN0icmSccK4naLMWYa/euL0+m23GyM8kgAc6sYeL4z04Qa4WjGepcKIliO8EUGSk7d9OGWOsoK31OSdy8TQZ59Y/hWbaV1IVs5/Ed6UzGK4nANAJiyGhRsZPUg2yzLe9hLyiJIyCaDU7udC2uy9pnkKvidlBUEltzFAqxRhBrBZm7HfZnjEQI3boqTsJq15PUDEaKZLgiJYc8OZtCtnM/4G93OFYooXpvdy0guwWWNQkEHl/j7Jw1XRmtlS9HYJkSPjk1IUnyyRqUKQn45NSDlP1mcg9i6En1ZU2IADnEtHF1Q+JwIcS/d5YakPuDUamEShGUHHikAz9oQCaE0CsrpYjDBVkEHQYdyK+EkKPhVErxqh1xbJ/oQf4gEeVsOIEc41WJNAwcd9GBfCZJezXsJhAvH+ImEEIOzlwXgpw5wQ0gH3MIOcsiQAahZuSD69/UQyxcQEggiQARQseVFO/ASAMCgM9gjkHZmhLENzi1AOhA7ullkMWUrfHKfpMiDBHtDIx6yCS6jseEnDUe7zcT6DGCtnrIY3olZw1hrPHkfucIAJa1EDu/lsVEyVmGGA67coKijeogFnMxlEaAV5ghRdDm1kDuuatZTJBGgJdOthIzsvZbDWRRuh6ScgR4EQLgagQvRQIxxQ4sxqcR4GE+c4CkjZQQW9YF89Y4OFAjOCki5KmiDxsBL3PlSJWlAFVogaoIePlYi2ClCJAHRa/cmre5eqTii4uvisqQJxqnip6pNd68DhEvyEs5xIyHBNdh4thCKhU++10kD7Gy1Up1A/o56FKuRJQWSFCuf8dpbisxhqHSKlSSgvG7VTaFKO5TzYD5VMPUxEB2YJNiqq3xYJ0KrroH8mq7xpoXqEZgfgNRUQsDtTVvUOk3sLUKbqrBr7YGvkCkQNC/9SA+vTYtvERrxiKEmcogk4ZqCLUd59MIEiFYHlIoxelCaJWDMmtOPIa80XVLbkb6hzaEwwTcPEmV4AIRlBGNIEmuJBFwLAZoHClJ36J8h+wxihpCqJosAnJrSKwEcQOFAFeWN4RQMYc0Ao4Jhg5gpASzyWcDvjpuDIlTkrGGJEro1rHIjHKR3wJCAj+z5oyi11gJBkXy9QFJIiAu78d+pgSjuWhGN0gUAZAcEncSJf4LRrZ8I94WEmcNCJJqBWYjVbE9bg2JxiyrViBWty6QvO56D8jPVWLA4ZX8dfkxvJJPl8t8aCX+pU/Iz1SCf7lc4OBK0OWfQaKLP0TKjj96VvIp+/BDZjwNKF2ItV2vN7sWStAl87oWkm3dZ+k3lEMoYXe8cT1eq2TOePJDD8KfQdxu6iEPxanUZa4HmZRq3dunGsj3BzFq6yD3wnZNX4n2emI2hXyXQpi6RRZdfSgxHNuxVZBFdyVeBPDmCsiksxKUiDAUEKuzkvRUEs0V08pjVyU2/yqFmF2VZGYop3peitdUiQd1pnrL7qTE01tPzE6eaEKm23dQwh2jNlbiay+/245zl94abw45CzNPyqYQ2++kxHGV1crWzg4A2yvR+BY7wziwnRLN7+O36aA54+ZKGjxZYK3txJpxQyUNn5GwtquII4+ACiWtnvawduu1A3SVtH5uhTvAVSpBG7fDYz6RQ+M6JWjmKm6g+RvTla9UMtspu+s+37VbVCupNqPx43CsNawSb1PbtcmDfQWmUILW7rRXSPHtSq5k5ur0a/hb7DQCUiW3G71ejX/wvV1kSoyNbp8Wvyqn1lCIKvl6gNDkNBYzt0GHdr+Pt9xGl1//ncAVcoVcIVfIFXKFXCFXyP8I8i8SyTW4yTz2lwAAAABJRU5ErkJggg=='
const base64Error = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAJFBMVEVHcEzo6Oibm5ukpKSbm5uampqbm5ubm5u5ubnn5+fm5ub6+vpGpDPdAAAAC3RSTlMA/v4hb+u20dq8aQhnHL4AAATwSURBVHja7ZvNb+JGGMbdjjdVe3NPodzeMhj1ZMUGujkh28B9wKR7iwwBqafWSbPqsbm0uTWtVlrTS9v0Et9yqLQS/1zHNiTZMMB4bO92d+dRUITt8c/PvPPx2h4URUpKSkpKSkpK6m3K6lFN73Q+S/+es3W3fzabTh2Dl0FAXEM+BgrgeXxRsdILTDU9n7J0vz/+EsCYC9KEiSFc06pf5zouqAkjkGWo0OG5Fq6j2IwZ6I4/4DhyTxc20oUjAj5PRTTrwvGAZ9p+ADzlD4RDctCoLhb7JUP87xeLxS3BZUIQ+YNCFi8wRwc4GIqGRK/GkM+5ILV8kFflOmkkkH/LddJ4c05eSSfSyTvrZPEmnCw+UCeuk84QvTSnUF0uCL68fBle/swF+RL1QZ/EpU6gHtOsAM64pnjPwxgTLsjoBM58ODNaAXYBT5QeGdr0KwcEA8He0TkPBLCjUDNHpG4qlg8eTCzXht1FVd1MxTPHj5LTtUiSrKK+7iDf8wBGxk4If3arLv/HF4Tox0A2nlFIGp+CIA+LzSamgbp4TNvZjECtDAjyMcB5HybLO6NxsRA1vmFCNjguNXDGWygbRPXh/B+zn9zPWK5RCkT18QxA57YgAqE+HGS6/tAoD4JO0ts+M2tbyQJpc95a5oI0xXNhCZGQ/x8E0VSCkUZY6Z6CIE/qdO5eL+yPlW6tMMgefPs3o7Bdt8iguJj4DThlZSY/rJ0yB+RraLDK2jAQCHyr4zIhT9mQ7vowygMZjpgQG+CYUV2E1EWqixyzICr8eFFnBB5ba1Y4IIfeKQvysW7ssZrwQLEFmvCBM2U6oRkdI5Wgm1QnO8RUTDlASoiESIiESMh7BDHKhlhu/LbSNUuEqL3lu1p945vO3BArADiaum7vBGDUKQfSIjBykooyrRPQnTIglHFfSagHeqd4iErwa9duEebpckGQjx/VT4v5fC0XhJHAd1mPRvJAVMZiAeQzTpgHYrPKqkGnUEiX+dCoNS4UgniHMTnUS4iESIiE7IS0x+mnVAidglDwVcmQJpy2WQ8VC4UgogfbA1RE4Nuw3UghEBV2rKl7V5ygAJPSY9KGQbP01mVjA5Fa2f1kQN2U3k+M9POWB8gnJUNMZJioWTMzKwOklyxgDrCXVcMMEF90tXM9C2TiCqmfCdIRi/jeewNpyerKok9WkGuzfCdYC+fXRsmBxxpVGG2zY0ZBbieJKvPrDQce3lxppBhIjGFWGkVoxUEoZt0Mukn2XBQH0bTHZpaMIp2sU/6qasU70W6/eHjM09VmYSc6C6Jpvz+orKvVxot8kL3HkMr9IZ9qeZ2o6RrO9mOI9ufdIR9peZ2gNIW31yC/MpyI9ngUDNIsezPks3vIsWDGdYA7cZa9pbqUVeCr/neiaR3U3R4BfXPg75vwb8I/b7HjxChobDZCO+Ny4wuxxaVxPPowcoNnrzPmzGFlX3RJHz2FafbhJ41n8PLx2DCM7KkwQgpqka1DVzKdJNHfJwBe9l/n0eSZFsIPjVSY8xZKZpSXnogwled98wAx3xRcdBNq1f1fhFVdIcL5tvaDolC7XaqaWStEtLOJHkbhlSauMLrma4yHEa03AVUoIUs/M2NQFkchBZiGUPeKonAnqhLOo4hrKf0WTyZ1FcU0Ki0hVrSr+Mucnvya7jYUKSkpKSkpKSmpD0f/AXq+Umj5XnXDAAAAAElFTkSuQmCC';
const base64BackToTop = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAElBMVEVRUVH+/v5HcEyZmZlRUVFRUVGm1ByOAAAABnRSTlPMzADMTZAJBBGsAAAEnElEQVR42t2cS27jMAyGf7/2U+QCQeDsbeQCgZDujaC5/1UmkzaJn+JDFGcw3LdfflKibJkkDnxrL7dbg7sNt6+L4O8OYBM+B0ys+QrGkHZG+OEEQ8g6go8Bx1GIGMdpNOQyIG6XdMgnSPtKhLQDGEZFBgYMkhKFtGBb0EIEjDgFRowoBVaMGAWpMedEfxMiZtwpUsgZCqtlkCNUdpVAWigtCCCDFtLwIWeoreZCWiRYYEKGFEjDg+yRZCUH0iLRAgNyToXUNCRZyMqWhGnUN2IPm3wSlwJ7IUspyCBkIQUZhCykIIeQuRTkEDKXAuM9srrtYbrZN7Y98giZSoFd+t1OxmMITG0dcrSFXFchZ1tIvQZpYWxhBbK3hpQrkMEa0iwh5t4a+QvZvDXyF7J5a+Qv5PPW21/I5623v5DPW29/IaO3Xv5Clrw1y1/Ikrdm+Qs5svw83yNnSJ5BQb4F/F7EIEJSnThGBAXxkFQfLOviQUE8JAUPsosHBfGQfDAtHhREQ1JxIV00KIgmrnRI84S0yAd5BAXxxJUck0f6Qnwr9qmr6xF5xLMjcwn/iudIEAdWnyjkEXlQKZiRVzoqRyLbgeUKKR8Q4alY7cSnoxzSf2ggsqehKr6YVpcXpOd7H93f60cKhOd7Re2LteUF4eLqiVS1mr0ge4io6C2+soaFkJ7MuuuQs1yITEp9hwwKISIpzR2iESKSIoT0rLNwuVHQqoSIpAQJpGce60vIUSdEIuUqgPTsJ5QFZK8UIpBS8iG94GFrDjlrhfCl8CG96Llxmle4kEr6vKWBPIVo9kqDQSRk9/3cWoikcCFPAd33v4dIChPyEvLzBA6RlEYWke4JEUnhKXkLeUEKxRHJFfKCQHGucIW8IdZSRkLeEGMpYyEjiK2UsZARxFTKRMgYYillImQMMZQyFTKB2EmZCplAuFLIHT8TMoWwpQwiIVMIUwqpZP5bp5CCvCTiQKr5f5lCQN+tPCBn2ZvVDFJwIDUP0m1BYAfZYRNSsCB7BqTbhoARePIxtZ9tgwWkoJcwCalmv3MBAemtO4R6dah2HaKQqj8Zvp9sQDjvJ21+SPCBHPJDDk6QITekEV7gqCC19CpKAym9IMfckKv4olMBCeIrWwVEfvkshzQekO9r9P1/ALk+IG1eSPCDiCJfyG+FyU+A6ZCa/piZDinpz7LpkCv5gdkAEshP5emQhv7onw6pGeULyZCSUYiRDAmMkpJkCKs4JhFSq8p8hJBSVbAkhARV6ZUQoisik0FqXTmcDHLVFfbJIEFXoiiCNMpiSxGkVJaNiiBBWQArgTTaUl4JpNQWJUsgQVteXQg+AKkLxQWFGKW+5J2+eVp4S168X3CF1CltCKdTJ8lb84YK2bUBO+wZW0Pqv9nk4tKu49N45NJC5dMM5tLW5tOg59Jq6NM06dL+abFXwr/RkuvTXJwae1abtE/Dt0/ruksTvs84AZ/BCC4jHnyGVfiM3VBQFANEXEah+Ax18RlP4zNox2dkkM/wI58xTn8yDCXGYCDV3W5RGSajtXyGhG1jbpbjzpwGt/0MJft8jqC7iUbQ/QZaxdnKqcIftwAAAABJRU5ErkJggg==';
module.exports = {
base64Arrow,
base64ArrowWhite,
base64Flower,
base64FlowerWhite,
base64Empty,
base64Error,
base64BackToTop
}

View File

@@ -0,0 +1,179 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// z-paging工具类
import zI18n from './z-paging-i18n'
const storageKey = 'Z-PAGING-REFRESHER-TIME-STORAGE-KEY'
//判断两个数组是否相等
function arrayIsEqual(arr1, arr2) {
if (arr1 === arr2) {
return true;
}
if (arr1.length !== arr2.length) {
return false;
}
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) {
return false;
}
}
return true;
}
//获取最终的touch位置
function getCommonTouch(e) {
let touch = null;
if (e.touches && e.touches.length) {
touch = e.touches[0];
} else if (e.changedTouches && e.changedTouches.length) {
touch = e.changedTouches[0];
} else if (e.datail && e.datail !== {}) {
touch = e.datail;
} else {
return {
touchX: 0,
touchY: 0
}
}
return {
touchX: touch.clientX,
touchY: touch.clientY
};
}
//判断当前手势是否在z-paging内触发
function getTouchFromZPaging(target) {
if (target && target.tagName && target.tagName !== 'BODY' && target.tagName !== 'UNI-PAGE-BODY') {
var classList = target.classList;
if (classList && classList.contains('zp-paging-touch-view')) {
return true;
} else {
return getTouchFromZPaging(target.parentNode);
}
} else {
return false;
}
}
//获取z-paging所在的parent
function getParent(parent) {
if (!parent) {
return null;
}
if (parent.$refs.paging) {
return parent;
}
return getParent(parent.$parent);
}
//打印错误信息
function consoleErr(err) {
console.error(`[z-paging]${err}`);
}
//打印警告信息
function consoleWarn(warn) {
console.warn(`[z-paging]${warn}`);
}
//设置下拉刷新时间
function setRefesrherTime(time, key) {
try {
let datas = getRefesrherTime();
if (!datas) {
datas = {};
}
datas[key] = time;
uni.setStorageSync(storageKey, datas);
} catch {}
}
//获取下拉刷新时间
function getRefesrherTime() {
try {
const datas = uni.getStorageSync(storageKey);
return datas;
} catch {
return null;
}
}
//通过下拉刷新标识key获取下拉刷新时间
function getRefesrherTimeByKey(key) {
const datas = getRefesrherTime();
if (datas) {
const data = datas[key];
if (data) {
return data;
}
}
return null;
}
//通过下拉刷新标识key获取下拉刷新时间(格式化之后)
function getRefesrherFormatTimeByKey(key) {
const time = getRefesrherTimeByKey(key);
let timeText = zI18n['refresherUpdateTimeNoneText'][zI18n.getLanguage()];
if (time) {
timeText = _timeFormat(time);
}
return `${zI18n['refresherUpdateTimeText'][zI18n.getLanguage()]}${timeText}`;
}
function _timeFormat(time) {
const date = new Date(time);
const currentDate = new Date();
const dateDay = new Date(time).setHours(0, 0, 0, 0);
const currentDateDay = new Date().setHours(0, 0, 0, 0);
const disTime = dateDay - currentDateDay;
let dayStr = '';
const timeStr = _dateTimeFormat(date);
if (disTime === 0) {
dayStr = zI18n['refresherUpdateTimeTodayText'][zI18n.getLanguage()];
} else if (disTime === -86400000) {
dayStr = zI18n['refresherUpdateTimeYesterdayText'][zI18n.getLanguage()];
} else {
dayStr = _dateDayFormat(date, date.getFullYear() !== currentDate.getFullYear());
}
return `${dayStr} ${timeStr}`;
}
function _dateDayFormat(date, showYear = true) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
if (showYear) {
return `${year}-${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`;
} else {
return `${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`;
}
}
function _dateTimeFormat(date) {
const hour = date.getHours();
const minute = date.getMinutes();
return `${_fullZeroToTwo(hour)}:${_fullZeroToTwo(minute)}`;
}
function _fullZeroToTwo(str) {
str = str.toString();
if (str.length === 1) {
return '0' + str;
}
return str;
}
module.exports = {
setRefesrherTime,
getRefesrherFormatTimeByKey,
arrayIsEqual,
getCommonTouch,
getTouchFromZPaging,
getParent,
consoleErr,
consoleWarn
};

View File

@@ -0,0 +1,205 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
//微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新降低逻辑层与视图层的通信折损提升性能
function propObserver(newValue, oldValue, ownerInstance, instance) {
var state = ownerInstance.getState();
state.currentInstance = instance;
var dataset = instance.getDataset();
var loading = dataset.loading == true;
if (newValue.indexOf('end') != -1) {
_setTransform('translateY(0px)', instance)
state.moveDistance = 0;
} else if (newValue.indexOf('begin') != -1) {
var refresherThreshold = instance.getDataset().refresherthreshold
_setTransformValue(refresherThreshold, instance, state);
}
}
function touchstart(e, ownerInstance) {
var instance = ownerInstance.getState().currentInstance;
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
var touch = _getCommonTouch(e);
state.startY = touch.touchY;
state.lastRefresherTouchmove = touch;
ownerInstance.callMethod('_handleRefresherTouchstart', touch);
}
function touchmove(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var refresherThreshold = dataset.refresherthreshold;
var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
if (!_getAngleIsInRange(e, touch, state, dataset)) {
return;
}
var moveDistance = _getMoveDistance(e, instance);
if (moveDistance < 0) {
return;
}
if (e.preventDefault) {
e.preventDefault();
}
_setTransformValue(moveDistance, instance, state);
var oldRefresherStatus = state.refresherStatus;
if (moveDistance >= refresherThreshold) {
state.refresherStatus = 1;
} else {
state.refresherStatus = 0;
}
if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || !isTouchmoving) {
ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
}
return false;
}
function touchend(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
state.refresherReachMaxAngle = true;
var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
if (!isTouchmoving) {
return;
}
var oldMoveDistance = state.moveDistance;
var refresherThreshold = instance.getDataset().refresherthreshold
var moveDistance = _getMoveDistance(e, instance);
ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
if (oldMoveDistance < refresherThreshold) {
return;
}
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold;
}
_setTransformValue(moveDistance, instance, state)
}
function _setTransformValue(value, instance, state) {
value = value || 0;
state.moveDistance = value;
_setTransform('translateY(' + value + 'px)', instance);
}
function _setTransform(transform, instance) {
instance.requestAnimationFrame(function() {
instance.setStyle({
transform: transform,
'-webkit-transform': transform
})
})
}
function _getMoveDistance(e, instance) {
var state = instance.getState()
var refresherThreshold = instance.getDataset().refresherthreshold
var touch = _getCommonTouch(e);
var moveDistance = touch.touchY - state.startY;
moveDistance = _getFinalRefresherMoveDistance(moveDistance, refresherThreshold);
return moveDistance;
}
function _getCommonTouch(e) {
var touch = null;
if (e.touches && e.touches.length) {
touch = e.touches[0];
} else if (e.changedTouches && e.changedTouches.length) {
touch = e.changedTouches[0];
} else if (e.datail && e.datail !== {}) {
touch = e.datail;
} else {
return {
touchX: 0,
touchY: 0
}
}
return {
touchX: touch.clientX,
touchY: touch.clientY
};
}
function _getFinalRefresherMoveDistance(moveDistance, refresherThreshold) {
refresherThreshold = parseFloat(refresherThreshold);
moveDistance = moveDistance * 0.7;
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold + (moveDistance - refresherThreshold) * 0.3;
}
return moveDistance;
}
function _getRefresherTouchDisabled(e, instance) {
var dataset = instance.getDataset();
var loading = _getIsTrue(dataset.loading);
var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
var refresherEnabled = _getIsTrue(dataset.refresherenabled);
var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
var usePageScroll = _getIsTrue(dataset.usepagescroll);
var pageScrollTop = parseFloat(dataset.pagescrolltop);
var wxsIsScrollTopInTopRange = _getIsTrue(dataset.wxsisscrolltopintoprange);
var scrollTop = parseFloat(dataset.scrolltop);
var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || (
usePageScroll && useCustomRefresher && pageScrollTop > 10) || (!(
usePageScroll && useCustomRefresher) && !wxsIsScrollTopInTopRange);
return res;
}
function _getAngleIsInRange(e, touch, state, dataset) {
var refresherMaxAngle = dataset.refreshermaxangle;
var refresherAecc = _getIsTrue(dataset.refresheraecc);
var lastRefresherTouchmove = state.lastRefresherTouchmove;
var moveDistance = state.moveDistance;
var refresherReachMaxAngle = state.refresherReachMaxAngle;
if (!lastRefresherTouchmove) {
return true;
}
if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
if (!refresherAecc && refresherReachMaxAngle != null && !refresherReachMaxAngle) {
return false;
}
var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
if (x && y) {
var angle = Math.asin(y / z) / Math.PI * 180;
if (angle < refresherMaxAngle) {
state.lastRefresherTouchmove = touch;
state.refresherReachMaxAngle = false;
return false;
}
}
}
state.lastRefresherTouchmove = touch;
return true;
}
function _getIsTrue(value) {
value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
return value == true || value == 'true';
}
module.exports = {
touchstart: touchstart,
touchmove: touchmove,
touchend: touchend,
propObserver: propObserver
}

View File

@@ -0,0 +1,58 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 使用renderjs在app-vue和h5中对touchmove事件冒泡进行处理
import zUtils from '../js/z-paging-utils'
var data = {
renderScrollTop: 0,
renderUsePageScroll: false,
renderIsIos: uni.getSystemInfoSync().platform === 'ios',
startY: 0,
isTouchFromZPaging: false
}
export default {
mounted() {
this._handleTouch();
},
methods: {
//接收逻辑层发送的数据
renderPropScrollTopChange(newVal, oldVal, ownerVm, vm) {
data.renderScrollTop = newVal;
},
renderPropUsePageScrollChange(newVal, oldVal, ownerVm, vm) {
if(newVal !== -1){
data.renderUsePageScroll = newVal;
}
},
//拦截处理touch事件
_handleTouch() {
if (window && !window.$zPagingRenderJsInited) {
window.$zPagingRenderJsInited = true;
window.addEventListener('touchstart', this._handleTouchstart, {
passive: true
})
window.addEventListener('touchmove', this._handleTouchmove, {
passive: false
})
}
},
_handleTouchstart(e) {
const touch = zUtils.getCommonTouch(e);
data.startY = touch.touchY;
data.isTouchFromZPaging = zUtils.getTouchFromZPaging(e.target);
},
_handleTouchmove(e) {
const touch = zUtils.getCommonTouch(e);
var moveY = touch.touchY - data.startY;
if ((data.isTouchFromZPaging && data.renderScrollTop < 1 && moveY > 0) || (data.isTouchFromZPaging && data.renderIsIos && !data.renderUsePageScroll && moveY < 0)) {
if (e.cancelable && !e.defaultPrevented) {
e.preventDefault();
}
}
},
}
};

View File

@@ -0,0 +1,346 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新降低逻辑层与视图层的通信折损提升性能
var currentMoveDistance = 0;
function propObserver(newValue, oldValue, ownerInstance, instance) {
var state = ownerInstance.getState();
state.currentInstance = instance;
var dataset = instance.getDataset();
var loading = dataset.loading == true;
if (newValue.indexOf('end') != -1) {
_setTransform('translateY(0px)', instance)
state.moveDistance = 0;
state.oldMoveDistance = 0;
currentMoveDistance = 0;
} else if (newValue.indexOf('begin') != -1) {
var refresherThreshold = instance.getDataset().refresherthreshold
_setTransformValue(refresherThreshold, instance, state);
}
}
function touchstart(e, ownerInstance) {
var instance = ownerInstance.getState().currentInstance;
var state = instance.getState();
var dataset = instance.getDataset();
var isTouchEnded = state.isTouchEnded;
if (_getRefresherTouchDisabled(e, instance, 0)) {
return;
}
state.oldMoveDistance = 0;
var touch = _getCommonTouch(e);
var loading = _getIsTrue(dataset.loading);
state.startY = touch.touchY;
state.lastRefresherTouchmove = touch;
if (!loading && isTouchEnded) {
state.isTouchmoving = false;
}
state.isTouchEnded = false;
ownerInstance.callMethod('_handleRefresherTouchstart', touch);
}
function touchmove(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var refresherThreshold = dataset.refresherthreshold;
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance, 1)) {
_handleTouchMovePullingDown(state, ownerInstance, false);
return true;
}
if (!_getAngleIsInRange(e, touch, state, dataset)) {
_handleTouchMovePullingDown(state, ownerInstance, false);
return true;
}
var moveDistanceObj = _getMoveDistance(e, instance);
var moveDistance = moveDistanceObj.currentMoveDistance;
var prevent = moveDistanceObj.isDown;
if (moveDistance < 0) {
_setTransformValue(0, instance, state);
_handleTouchMovePullingDown(state, ownerInstance, false);
return true;
}
if (prevent && !state.disabledBounce) {
ownerInstance.callMethod('_handleScrollViewDisableBounce', {
bounce: false
});
state.disabledBounce = true;
_handleTouchMovePullingDown(state, ownerInstance, prevent);
return !prevent;
}
_setTransformValue(moveDistance, instance, state);
var oldRefresherStatus = state.refresherStatus;
var dataset = instance.getDataset();
var oldIsTouchmoving = _getIsTrue(dataset.oldistouchmoving);
var isTouchmoving = state.isTouchmoving;
if (moveDistance >= refresherThreshold) {
state.refresherStatus = 1;
} else {
state.refresherStatus = 0;
}
if (!isTouchmoving) {
state.isTouchmoving = true;
isTouchmoving = true;
}
if (state.isTouchEnded) {
state.isTouchEnded = false;
}
if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || oldIsTouchmoving !=
isTouchmoving) {
ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
}
_handleTouchMovePullingDown(state, ownerInstance, prevent);
return !prevent;
}
function touchend(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance, 2)) {
return;
}
state.refresherReachMaxAngle = true;
state.hitReachMaxAngleCount = 0;
state.disabledBounce = false;
state.fixedIsTopHitCount = 0;
//ownerInstance.callMethod('_handleScrollViewDisableBounce', {bounce:true});
var isTouchmoving = state.isTouchmoving;
if (!isTouchmoving) {
return;
}
var oldRefresherStatus = state.refresherStatus;
var oldMoveDistance = state.moveDistance;
var refresherThreshold = instance.getDataset().refresherthreshold
var moveDistance = _getMoveDistance(e, instance).currentMoveDistance;
if (!(moveDistance >= refresherThreshold && oldRefresherStatus === 1)) {
state.isTouchmoving = false;
}
ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
state.isTouchEnded = true;
if (oldMoveDistance < refresherThreshold) {
return;
}
var animate = false;
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold;
var isIos13 = _getIsTrue(dataset.isios13);
if (isIos13) {
animate = true;
}
}
_setTransformValue(moveDistance, instance, state, animate);
}
// #ifdef H5
function isPC() {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
var flag = true;
for (var v = 0; v < Agents.length - 1; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
var movable = false;
function mousedown(e, ins) {
if (!isPC()) return;
touchstart(e, ins);
movable = true;
}
function mousemove(e, ins) {
if (!isPC()) return;
if (!movable) return;
touchmove(e, ins);
}
function mouseup(e, ins) {
if (!isPC()) return;
touchend(e, ins);
movable = false;
}
function mouseleave(e, ins) {
if (!isPC()) return;
movable = false;
}
// #endif
function _setTransformValue(value, instance, state, animate = false) {
value = value || 0;
if (state.moveDistance == value) {
return;
}
state.moveDistance = value;
_setTransform('translateY(' + value + 'px)', instance, animate);
}
function _setTransform(transform, instance, animate = false) {
if (transform == 'translateY(0px)') {
transform = 'none';
}
instance.requestAnimationFrame(function() {
if (animate) {
instance.setStyle({
'transform': transform,
'transition': 'transform .1s linear',
})
} else {
instance.setStyle({
'transform': transform
})
}
})
}
function _getMoveDistance(e, instance) {
var state = instance.getState();
var refresherThreshold = instance.getDataset().refresherthreshold;
var refresherOutRate = instance.getDataset().refresheroutrate;
refresherThreshold = parseFloat(refresherThreshold);
refresherOutRate = parseFloat(refresherOutRate);
var touch = _getCommonTouch(e);
var moveDistance = touch.touchY - state.startY;
var oldMoveDistance = state.oldMoveDistance || 0;
state.oldMoveDistance = moveDistance;
var diffDis = moveDistance - oldMoveDistance;
if (diffDis > 0) {
diffDis = diffDis * 0.85;
if (currentMoveDistance > refresherThreshold) {
diffDis = diffDis * (1 - refresherOutRate);
}
}
currentMoveDistance += diffDis;
if (currentMoveDistance < 0) {
currentMoveDistance = 0;
}
return {
currentMoveDistance: currentMoveDistance,
isDown: diffDis > 0
};
}
function _getCommonTouch(e) {
var touch = null;
if (e.touches && e.touches.length) {
touch = e.touches[0];
} else if (e.changedTouches && e.changedTouches.length) {
touch = e.changedTouches[0];
} else if (e.datail && e.datail !== {}) {
touch = e.datail;
} else {
touch = e;
}
return {
touchX: touch.clientX,
touchY: touch.clientY
};
}
function _getRefresherTouchDisabled(e, instance, processTag) {
var dataset = instance.getDataset();
var state = instance.getState();
var loading = _getIsTrue(dataset.loading);
var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
var refresherEnabled = _getIsTrue(dataset.refresherenabled);
var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
var usePageScroll = _getIsTrue(dataset.usepagescroll);
var pageScrollTop = parseFloat(dataset.pagescrolltop);
var scrollTop = parseFloat(dataset.scrolltop);
var finalScrollTop = usePageScroll ? pageScrollTop : scrollTop;
var fixedIsTop = false;
var isIos = _getIsTrue(dataset.isios);
if (!isIos && finalScrollTop == (state.startScrollTop || 0) && finalScrollTop <= 105) {
fixedIsTop = true;
}
var fixedIsTopHitCount = state.fixedIsTopHitCount || 0;
if (fixedIsTop) {
fixedIsTopHitCount++;
if (fixedIsTopHitCount <= 3) {
fixedIsTop = false;
}
state.fixedIsTopHitCount = fixedIsTopHitCount;
} else {
state.fixedIsTopHitCount = 0;
}
if (!isIos && processTag === 0) {
state.startScrollTop = finalScrollTop || 0;
}
if (!isIos && processTag === 2) {
fixedIsTop = true;
}
var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || ((
usePageScroll && useCustomRefresher && pageScrollTop > 5) && !fixedIsTop) || ((
!usePageScroll && useCustomRefresher && scrollTop > 5) && !fixedIsTop);
return res;
}
function _getAngleIsInRange(e, touch, state, dataset) {
var refresherMaxAngle = dataset.refreshermaxangle;
var refresherAecc = _getIsTrue(dataset.refresheraecc);
var lastRefresherTouchmove = state.lastRefresherTouchmove;
var refresherReachMaxAngle = state.refresherReachMaxAngle;
var moveDistance = state.oldMoveDistance;
if (!lastRefresherTouchmove) {
return true;
}
if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
if ((!moveDistance || moveDistance < 1) && !refresherAecc && refresherReachMaxAngle != null && !
refresherReachMaxAngle) {
return false;
}
var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
if ((x || y) && x > 1) {
var angle = Math.asin(y / z) / Math.PI * 180;
if (angle < refresherMaxAngle) {
var hitReachMaxAngleCount = state.hitReachMaxAngleCount || 0;
state.hitReachMaxAngleCount = ++hitReachMaxAngleCount;
if (state.hitReachMaxAngleCount > 2) {
state.lastRefresherTouchmove = touch;
state.refresherReachMaxAngle = false;
}
return false;
}
}
}
state.lastRefresherTouchmove = touch;
return true;
}
function _handleTouchMovePullingDown(state, instance, onPullingDown) {
var oldOnPullingDown = state.onPullingDown || false;
if (oldOnPullingDown != onPullingDown) {
instance.callMethod('_handleWxsOnPullingDown', onPullingDown);
}
state.onPullingDown = onPullingDown;
}
function _getIsTrue(value) {
value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
return value == true || value == 'true';
}
module.exports = {
touchstart: touchstart,
touchmove: touchmove,
touchend: touchend,
mousedown: mousedown,
mousemove: mousemove,
mouseup: mouseup,
mouseleave: mouseleave,
propObserver: propObserver
}

View File

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

View File

@@ -0,0 +1,35 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 使用页面滚动时引入此mixin用于监听和处理onPullDownRefresh等页面生命周期方法
const ZPagingMixin = {
onPullDownRefresh(){
if(this.isPagingRefNotFound()){
return;
}
this.$refs.paging.reload();
},
onPageScroll(e) {
if(this.isPagingRefNotFound()){
return;
}
this.$refs.paging.updatePageScrollTop(e.scrollTop);
},
onReachBottom() {
if(this.isPagingRefNotFound()){
return;
}
this.$refs.paging.doLoadMore();
},
methods: {
isPagingRefNotFound(){
return !this.$refs.paging || this.$refs.paging === undefined;
}
}
}
export default ZPagingMixin;

View File

@@ -0,0 +1,173 @@
<!-- z-paging -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<!-- 下拉刷新view -->
<template>
<view style="height: 100%;">
<view class="zp-custom-refresher-container" style="height: 100%;">
<view class="zp-custom-refresher-left">
<image v-if="refresherStatus!==2" :class="refresherLeftImageClass"
:style="[{'filter' :defaultThemeStyle==='white'?'brightness(10)':''}]" :src="base64Arrow">
</image>
<!-- #ifndef APP-NVUE -->
<image v-else class="zp-loading-more-line-loading-image zp-custom-refresher-left-image" :src="base64Flower">
</image>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view v-else>
<loading-indicator class="zp-custom-refresher-left-image" :animating="true"></loading-indicator>
</view>
<!-- #endif -->
</view>
<view
:class="defaultThemeStyle==='white'?'zp-custom-refresher-right zp-custom-refresher-right-white':'zp-custom-refresher-right zp-custom-refresher-right-black'">
<text class="zp-custom-refresher-right-text">{{refresherStatusTextMap[refresherStatus]}}
</text>
</view>
</view>
</view>
</template>
<script>
import zStatic from './z-paging-static'
export default {
name: 'z-paging-refresh',
data() {
return {
base64Arrow: zStatic.base64Arrow,
base64Flower: zStatic.base64Flower,
refresherStatusTextMap: {
0: this.refresherDefaultText,
1: this.refresherPullingText,
2: this.refresherRefreshingText
},
refresherLeftImageClass: 'zp-custom-refresher-left-image',
};
},
props: ['refresherStatus', 'defaultThemeStyle', 'refresherDefaultText', 'refresherPullingText',
'refresherPullingText', 'refresherRefreshingText'
],
watch: {
refresherStatus(newVal, oldVal) {
if (newVal === 0 && oldVal !== 0) {
this.refresherLeftImageClass = 'zp-custom-refresher-left-image zp-custom-refresher-arrow-down';
}
if (newVal !== 0 && oldVal === 0) {
this.refresherLeftImageClass = 'zp-custom-refresher-left-image zp-custom-refresher-arrow-top';
}
}
}
}
</script>
<style scoped>
@import "./z-paging-static.css";
.zp-custom-refresher-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
}
.zp-custom-refresher-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
}
.zp-custom-refresher-left-image {
width: 30rpx;
height: 30rpx;
transform: rotate(180deg);
margin-right: 8rpx;
/* #ifdef APP-NVUE */
width: 35rpx;
height: 35rpx;
transition-duration: .2s;
transition-property: transform;
color: #666666;
/* #endif */
}
.zp-custom-refresher-arrow-top {
/* #ifndef APP-NVUE */
animation: refresher-arrow-top 0.25s linear;
-webkitanimation: refresher-arrow-top 0.25s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
/* #endif */
/* #ifdef APP-NVUE */
transform: rotate(0deg);
/* #endif */
}
.zp-custom-refresher-arrow-down {
/* #ifndef APP-NVUE */
animation: refresher-arrow-down 0.25s linear;
-webkit-animation: refresher-arrow-down 0.25s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
/* #endif */
/* #ifdef APP-NVUE */
transform: rotate(180deg);
/* #endif */
}
.zp-custom-refresher-right {
font-size: 26rpx;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
}
.zp-custom-refresher-right-text {
/* #ifdef APP-NVUE */
font-size: 28rpx;
height: 40px;
line-height: 40px;
/* #endif */
color: #555555
}
.zp-custom-refresher-right-black {
color: #666666;
}
.zp-custom-refresher-right-white {
color: #efefef;
}
@keyframes refresher-arrow-top {
0% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
@keyframes refresher-arrow-down {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
</style>

View File

@@ -0,0 +1,205 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
//微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新降低逻辑层与视图层的通信折损提升性能
function propObserver(newValue, oldValue, ownerInstance, instance) {
var state = ownerInstance.getState();
state.currentInstance = instance;
var dataset = instance.getDataset();
var loading = dataset.loading == true;
if (newValue.indexOf('end') != -1) {
_setTransform('translateY(0px)', instance)
state.moveDistance = 0;
} else if (newValue.indexOf('begin') != -1) {
var refresherThreshold = instance.getDataset().refresherthreshold
_setTransformValue(refresherThreshold, instance, state);
}
}
function touchstart(e, ownerInstance) {
var instance = ownerInstance.getState().currentInstance;
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
var touch = _getCommonTouch(e);
state.startY = touch.touchY;
state.lastRefresherTouchmove = touch;
ownerInstance.callMethod('_handleRefresherTouchstart', touch);
}
function touchmove(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var refresherThreshold = dataset.refresherthreshold;
var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
if (!_getAngleIsInRange(e, touch, state, dataset)) {
return;
}
var moveDistance = _getMoveDistance(e, instance);
if (moveDistance < 0) {
return;
}
if (e.preventDefault) {
e.preventDefault();
}
_setTransformValue(moveDistance, instance, state);
var oldRefresherStatus = state.refresherStatus;
if (moveDistance >= refresherThreshold) {
state.refresherStatus = 1;
} else {
state.refresherStatus = 0;
}
if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || !isTouchmoving) {
ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
}
return false;
}
function touchend(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
state.refresherReachMaxAngle = true;
var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
if (!isTouchmoving) {
return;
}
var oldMoveDistance = state.moveDistance;
var refresherThreshold = instance.getDataset().refresherthreshold
var moveDistance = _getMoveDistance(e, instance);
ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
if (oldMoveDistance < refresherThreshold) {
return;
}
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold;
}
_setTransformValue(moveDistance, instance, state)
}
function _setTransformValue(value, instance, state) {
value = value || 0;
state.moveDistance = value;
_setTransform('translateY(' + value + 'px)', instance);
}
function _setTransform(transform, instance) {
instance.requestAnimationFrame(function() {
instance.setStyle({
transform: transform,
'-webkit-transform': transform
})
})
}
function _getMoveDistance(e, instance) {
var state = instance.getState()
var refresherThreshold = instance.getDataset().refresherthreshold
var touch = _getCommonTouch(e);
var moveDistance = touch.touchY - state.startY;
moveDistance = _getFinalRefresherMoveDistance(moveDistance, refresherThreshold);
return moveDistance;
}
function _getCommonTouch(e) {
var touch = null;
if (e.touches && e.touches.length) {
touch = e.touches[0];
} else if (e.changedTouches && e.changedTouches.length) {
touch = e.changedTouches[0];
} else if (e.datail && e.datail !== {}) {
touch = e.datail;
} else {
return {
touchX: 0,
touchY: 0
}
}
return {
touchX: touch.clientX,
touchY: touch.clientY
};
}
function _getFinalRefresherMoveDistance(moveDistance, refresherThreshold) {
refresherThreshold = parseFloat(refresherThreshold);
moveDistance = moveDistance * 0.7;
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold + (moveDistance - refresherThreshold) * 0.3;
}
return moveDistance;
}
function _getRefresherTouchDisabled(e, instance) {
var dataset = instance.getDataset();
var loading = _getIsTrue(dataset.loading);
var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
var refresherEnabled = _getIsTrue(dataset.refresherenabled);
var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
var usePageScroll = _getIsTrue(dataset.usepagescroll);
var pageScrollTop = parseFloat(dataset.pagescrolltop);
var wxsIsScrollTopInTopRange = _getIsTrue(dataset.wxsisscrolltopintoprange);
var scrollTop = parseFloat(dataset.scrolltop);
var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || (
usePageScroll && useCustomRefresher && pageScrollTop > 10) || (!(
usePageScroll && useCustomRefresher) && !wxsIsScrollTopInTopRange);
return res;
}
function _getAngleIsInRange(e, touch, state, dataset) {
var refresherMaxAngle = dataset.refreshermaxangle;
var refresherAecc = _getIsTrue(dataset.refresheraecc);
var lastRefresherTouchmove = state.lastRefresherTouchmove;
var moveDistance = state.moveDistance;
var refresherReachMaxAngle = state.refresherReachMaxAngle;
if (!lastRefresherTouchmove) {
return true;
}
if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
if (!refresherAecc && refresherReachMaxAngle != null && !refresherReachMaxAngle) {
return false;
}
var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
if (x && y) {
var angle = Math.asin(y / z) / Math.PI * 180;
if (angle < refresherMaxAngle) {
state.lastRefresherTouchmove = touch;
state.refresherReachMaxAngle = false;
return false;
}
}
}
state.lastRefresherTouchmove = touch;
return true;
}
function _getIsTrue(value) {
value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
return value == true || value == 'true';
}
module.exports = {
touchstart: touchstart,
touchmove: touchmove,
touchend: touchend,
propObserver: propObserver
}

View File

@@ -0,0 +1,28 @@
/* z-paging
github地址:https://github.com/SmileZXLee/uni-z-paging
dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
反馈QQ群790460711
公用的静态css资源 */
.zp-loading-more-line-loading-image {
margin-right: 8rpx;
width: 28rpx;
height: 28rpx;
/* #ifndef APP-NVUE */
animation: loading-flower 1s steps(12) infinite;
/* #endif */
color: #666666;
}
@keyframes loading-flower {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}

View File

@@ -0,0 +1,18 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 公用的静态图片资源
const base64Arrow =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAD1BMVEVHcExRUVFMTExRUVFRUVE9CdWsAAAABHRSTlMAjjrY9ZnUjwAAAQFJREFUWMPt2MsNgzAMgGEEE1B1gKJmAIRYoCH7z9RCXrabh33iYktcIv35EEg5ZBh07pvxJU6MFSPOSRnjnBUjUsaciRUjMsb4xIoRCWNiYsUInzE5sWKEyxiYWDbyefqHx1zIeiYTk7mQYziTYecxHvEJjwmIT3hMQELCYSISEg4TkZj0mYTEpM8kJCU9JiMp6TEZyUmbAUhO2gxAQNJiIAKSFgMRmNQZhMCkziAEJTUGIyipMRjBSZkhCE7KDEFIUmTeGCHJxWz0zXaE0GTCG8ZFtEaS347r/1fe11YyHYVfubxayfjoHmc0YYwmmmiiiSaaaKLJ7ckyz5ve+dw3Xw2emdwm9xSbAAAAAElFTkSuQmCC';
const base64Flower =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAKlBMVEVHcEzDw8Ovr6+pqamUlJTCwsKenp61tbWxsbGysrLNzc2bm5u5ubmjo6MpovhuAAAACnRSTlMA/P79/sHDhiZS0DxZowAABBBJREFUWMPtl89rE0EUx7ctTXatB3MI1SWnDbUKPUgXqh4ED8Uf7KUVSm3ooVSpSii0Fn/gD4j4o+APiEoVmos9FO2celiqZVgwgaKHPQiCCkv+F99kM7Ozm5kxq1dfD91k9pPve9/3ZjbRNHHok/mKli4eIPNgSuRObuN9SqSEzM20iGnm0yIbqCuV7NSSSIV7uyPM6JMBYdeTOanh/QihJYZsUCSby+VkMj2AvOt0rAeQAwqE3lfKMZVlQCZk1QOCKkkVPadITCfIRNKxfoJI5+0OIFtJx14CMSg1mRSDko7VAfksRQzEbGYqxOJcVTWMCH2I1/IACNW0PWU2M8cmAVHtnH5mM1VRWtwKZjOd5JbF6s1IbaYqaotjNlPHgDAnlAizubTR6ovMYn052g/U5qcmOpi0WL8xTS/3IfSet5m8MEr5ajjF5le6dq/OJpobrdY0t3i9QgefWrxW9/1BLhk0E9m8FeUMhhXal499iD0eQRfDF+ts/tttORRerfp+oV7f4xJj82iUYm1Yzod+ZQEAlS/8mMBwKebVmCVp1f0JLS6zKd17+iwRKTARVg2SHtz3iEbBH+Q+U28zW2Jiza8Tjb1YFoYZMsJyjDqp3M9XBQdSdPLFdxEpvOB37JrHcmR/y9+LgoTlCFGZEa2sc6d4PGlweEa2JSVPoVm+IfGG3ZL037iV9oH+P+Jxc4HGVflNq1M0pivao/EopO4b/ojVCP9GjmiXOeS0DOn1o/iiccT4ORnyvBGF3yUywkQajW4Ti0SGuiy/wVSg/L8w+X/8Q+hvUx8Xd90z4oV5a1i88MbFWHz0WZZ1UrTwBGPX3Rat9AFiXRMRjoMdIdJLEOt2h7jrYOzgOamKZSWSNspOS0X8SAqRYmxRL7sg4eLzYmNehcxh3uoyud/BH2Udux4ywxFTc1xC7Mgf4vMhc5S+kSH3Y7yj+qpwIWSoPTVCOOPVthGx9FbGqrwFw6wSFxJr+17zeKcztt3u+2roAEVgUjDd+AHGuxHy2rZHaa8JMkTHEeyi85ANPO9j9BVuBRD2FY5LDMo/Sz/2hReqGIs/KiFin+CsPsYO/yvM3jL2vE8EbX7/Bf8ejtr2GLN65bioAdgLd8Bis/mD5GmP2qeqyo2ZwQEOtAjRIDH7mBKpUcMoApbZJ5UIxkEwxyMZyMxW/uKFvHCFR3SSmerHyDNQ2dF4JG6zIMpBgLfjSF9x1D6smFcYnGApjmSLICO3ecCDWrQ48geba9DI3STy2i7ax6WIB62fSyIZIiO3GFQqSURp8wCo7GhJBGwuSovJBNjb7kT6FPVnIa9qJ2Ko+l9mefGIdinaMp0yC1URYiwsdfNE45EuA5Cx9EhalfvN5s+UyItm81vaB3p4joniN+SCP7Qc1hblAAAAAElFTkSuQmCC';
const base64Empty = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAbUExURdvc3EdwTMLBwcjIyLSzs/Hx8ff39////19dXXz7IJEAAAAFdFJOU/4A6J9QDyyutAAAB5VJREFUeNrtnM1z4jYYxhUHkR4hdu9eU7Z75Ct7jgPbs9ZZmSuTrUWPmXTA186e+LMrf0uWLMtf2WkHXQgzln88et5XeiVMwPQdGrhCrpAr5Aq5Qv4TkJ07OGQFMLp1B4VYCz+kDblDQhJGeH4eEDLBYdLOHwaDWNBPIeHLYJAJ3meQ83IoCMTHDBKOBoKYGOeM8G0gyD0LObnDQB5ZSCtTNCBfsM9AboaBPLCQcDAIM1zht/dQEkMsd1DjI4hpw2YzMtBJeBbydWpCTJs3YDKGX62YgfGoVwi9KwtZJAzcYHHRm7sYCKD390nQSIoO5JGZIEOYxNoZ4+deISYLyeL5hLHbJ2QK98W0kudMgJe9Qh73odhO+KZHyNYGvgQS9gmJKhUigwSj3iBPUhXxePWmxBqHw0Mej9WQ3qILVjLC177yxNxXQ/7uK+Mn1aNVLsGsBTaWrSAPobYl0aUHt2fIs2Rgz7c9QYL0pSTkSzILLFtAJMH1cidN998T9E0/Sg73/pEEwrgkYRh86wlC949gJsR6EobBcz8hHOVgKYi2m6kZtodIkjEQvF3QjbGpmplB4/lRgJhxgRS2N15iijAvPmByDtCxfQhPJ8J4CR82rgCCBILarScw6X0OcMUyYrFVmbxErl0ZacFIoloOLdJAO42qY+NMDss2kKS8xmiZxcCpFKXWvpRGbQqJp5ixyRfJMmR6x0Fk+z29kmgWDYI5ziFbdug/84HxvduhWhLOJ2StPDQrMJPSjNANklh8QhB7dBO0yTGRwn1fkOk8rbQjiB8Ymww+JuiuN0icmSccK4naLMWYa/euL0+m23GyM8kgAc6sYeL4z04Qa4WjGepcKIliO8EUGSk7d9OGWOsoK31OSdy8TQZ59Y/hWbaV1IVs5/Ed6UzGK4nANAJiyGhRsZPUg2yzLe9hLyiJIyCaDU7udC2uy9pnkKvidlBUEltzFAqxRhBrBZm7HfZnjEQI3boqTsJq15PUDEaKZLgiJYc8OZtCtnM/4G93OFYooXpvdy0guwWWNQkEHl/j7Jw1XRmtlS9HYJkSPjk1IUnyyRqUKQn45NSDlP1mcg9i6En1ZU2IADnEtHF1Q+JwIcS/d5YakPuDUamEShGUHHikAz9oQCaE0CsrpYjDBVkEHQYdyK+EkKPhVErxqh1xbJ/oQf4gEeVsOIEc41WJNAwcd9GBfCZJezXsJhAvH+ImEEIOzlwXgpw5wQ0gH3MIOcsiQAahZuSD69/UQyxcQEggiQARQseVFO/ASAMCgM9gjkHZmhLENzi1AOhA7ullkMWUrfHKfpMiDBHtDIx6yCS6jseEnDUe7zcT6DGCtnrIY3olZw1hrPHkfucIAJa1EDu/lsVEyVmGGA67coKijeogFnMxlEaAV5ghRdDm1kDuuatZTJBGgJdOthIzsvZbDWRRuh6ScgR4EQLgagQvRQIxxQ4sxqcR4GE+c4CkjZQQW9YF89Y4OFAjOCki5KmiDxsBL3PlSJWlAFVogaoIePlYi2ClCJAHRa/cmre5eqTii4uvisqQJxqnip6pNd68DhEvyEs5xIyHBNdh4thCKhU++10kD7Gy1Up1A/o56FKuRJQWSFCuf8dpbisxhqHSKlSSgvG7VTaFKO5TzYD5VMPUxEB2YJNiqq3xYJ0KrroH8mq7xpoXqEZgfgNRUQsDtTVvUOk3sLUKbqrBr7YGvkCkQNC/9SA+vTYtvERrxiKEmcogk4ZqCLUd59MIEiFYHlIoxelCaJWDMmtOPIa80XVLbkb6hzaEwwTcPEmV4AIRlBGNIEmuJBFwLAZoHClJ36J8h+wxihpCqJosAnJrSKwEcQOFAFeWN4RQMYc0Ao4Jhg5gpASzyWcDvjpuDIlTkrGGJEro1rHIjHKR3wJCAj+z5oyi11gJBkXy9QFJIiAu78d+pgSjuWhGN0gUAZAcEncSJf4LRrZ8I94WEmcNCJJqBWYjVbE9bg2JxiyrViBWty6QvO56D8jPVWLA4ZX8dfkxvJJPl8t8aCX+pU/Iz1SCf7lc4OBK0OWfQaKLP0TKjj96VvIp+/BDZjwNKF2ItV2vN7sWStAl87oWkm3dZ+k3lEMoYXe8cT1eq2TOePJDD8KfQdxu6iEPxanUZa4HmZRq3dunGsj3BzFq6yD3wnZNX4n2emI2hXyXQpi6RRZdfSgxHNuxVZBFdyVeBPDmCsiksxKUiDAUEKuzkvRUEs0V08pjVyU2/yqFmF2VZGYop3peitdUiQd1pnrL7qTE01tPzE6eaEKm23dQwh2jNlbiay+/245zl94abw45CzNPyqYQ2++kxHGV1crWzg4A2yvR+BY7wziwnRLN7+O36aA54+ZKGjxZYK3txJpxQyUNn5GwtquII4+ACiWtnvawduu1A3SVtH5uhTvAVSpBG7fDYz6RQ+M6JWjmKm6g+RvTla9UMtspu+s+37VbVCupNqPx43CsNawSb1PbtcmDfQWmUILW7rRXSPHtSq5k5ur0a/hb7DQCUiW3G71ejX/wvV1kSoyNbp8Wvyqn1lCIKvl6gNDkNBYzt0GHdr+Pt9xGl1//ncAVcoVcIVfIFXKFXCFXyP8I8i8SyTW4yTz2lwAAAABJRU5ErkJggg=='
const base64BackToTop = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAElBMVEVRUVH+/v5HcEyZmZlRUVFRUVGm1ByOAAAABnRSTlPMzADMTZAJBBGsAAAEnElEQVR42t2cS27jMAyGf7/2U+QCQeDsbeQCgZDujaC5/1UmkzaJn+JDFGcw3LdfflKibJkkDnxrL7dbg7sNt6+L4O8OYBM+B0ys+QrGkHZG+OEEQ8g6go8Bx1GIGMdpNOQyIG6XdMgnSPtKhLQDGEZFBgYMkhKFtGBb0EIEjDgFRowoBVaMGAWpMedEfxMiZtwpUsgZCqtlkCNUdpVAWigtCCCDFtLwIWeoreZCWiRYYEKGFEjDg+yRZCUH0iLRAgNyToXUNCRZyMqWhGnUN2IPm3wSlwJ7IUspyCBkIQUZhCykIIeQuRTkEDKXAuM9srrtYbrZN7Y98giZSoFd+t1OxmMITG0dcrSFXFchZ1tIvQZpYWxhBbK3hpQrkMEa0iwh5t4a+QvZvDXyF7J5a+Qv5PPW21/I5623v5DPW29/IaO3Xv5Clrw1y1/Ikrdm+Qs5svw83yNnSJ5BQb4F/F7EIEJSnThGBAXxkFQfLOviQUE8JAUPsosHBfGQfDAtHhREQ1JxIV00KIgmrnRI84S0yAd5BAXxxJUck0f6Qnwr9qmr6xF5xLMjcwn/iudIEAdWnyjkEXlQKZiRVzoqRyLbgeUKKR8Q4alY7cSnoxzSf2ggsqehKr6YVpcXpOd7H93f60cKhOd7Re2LteUF4eLqiVS1mr0ge4io6C2+soaFkJ7MuuuQs1yITEp9hwwKISIpzR2iESKSIoT0rLNwuVHQqoSIpAQJpGce60vIUSdEIuUqgPTsJ5QFZK8UIpBS8iG94GFrDjlrhfCl8CG96Llxmle4kEr6vKWBPIVo9kqDQSRk9/3cWoikcCFPAd33v4dIChPyEvLzBA6RlEYWke4JEUnhKXkLeUEKxRHJFfKCQHGucIW8IdZSRkLeEGMpYyEjiK2UsZARxFTKRMgYYillImQMMZQyFTKB2EmZCplAuFLIHT8TMoWwpQwiIVMIUwqpZP5bp5CCvCTiQKr5f5lCQN+tPCBn2ZvVDFJwIDUP0m1BYAfZYRNSsCB7BqTbhoARePIxtZ9tgwWkoJcwCalmv3MBAemtO4R6dah2HaKQqj8Zvp9sQDjvJ21+SPCBHPJDDk6QITekEV7gqCC19CpKAym9IMfckKv4olMBCeIrWwVEfvkshzQekO9r9P1/ALk+IG1eSPCDiCJfyG+FyU+A6ZCa/piZDinpz7LpkCv5gdkAEshP5emQhv7onw6pGeULyZCSUYiRDAmMkpJkCKs4JhFSq8p8hJBSVbAkhARV6ZUQoisik0FqXTmcDHLVFfbJIEFXoiiCNMpiSxGkVJaNiiBBWQArgTTaUl4JpNQWJUsgQVteXQg+AKkLxQWFGKW+5J2+eVp4S168X3CF1CltCKdTJ8lb84YK2bUBO+wZW0Pqv9nk4tKu49N45NJC5dMM5tLW5tOg59Jq6NM06dL+abFXwr/RkuvTXJwae1abtE/Dt0/ruksTvs84AZ/BCC4jHnyGVfiM3VBQFANEXEah+Ax18RlP4zNox2dkkM/wI58xTn8yDCXGYCDV3W5RGSajtXyGhG1jbpbjzpwGt/0MJft8jqC7iUbQ/QZaxdnKqcIftwAAAABJRU5ErkJggg==';
module.exports = {
base64Arrow: base64Arrow,
base64Flower: base64Flower,
base64Empty: base64Empty,
base64BackToTop: base64BackToTop
}

View File

@@ -0,0 +1,462 @@
<!-- _
____ _ __ __ _ __ _(_)_ __ __ _
|_ /____| '_ \ / _` |/ _` | | '_ \ / _` |
/ /_____| |_) | (_| | (_| | | | | | (_| |
/___| | .__/ \__,_|\__, |_|_| |_|\__, |
|_| |___/ |___/
V2.0.1
by ZXLee 2021-08-17
-- >
<!-- API文档地址http://z-paging.com -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<template name="z-paging">
<!-- #ifndef APP-NVUE -->
<view :class="!usePageScroll&&fixed?'z-paging-content z-paging-content-fixed':'z-paging-content'"
:style="[finalPagingStyle]">
<!-- 顶部固定的slot -->
<slot v-if="!usePageScroll&&$slots.top" name="top"></slot>
<view class="zp-page-scroll-top" v-else-if="usePageScroll&&$slots.top" :style="[{'top':`${windowTop}px`,'z-index':topZIndex}]">
<slot name="top"></slot>
</view>
<view :class="{'zp-scroll-view-super':!usePageScroll}" :style="[finalScrollViewStyle]">
<scroll-view
:class="{'zp-scroll-view':true,'zp-scroll-view-absolute':!usePageScroll}"
:scroll-top="scrollTop"
:scroll-y="scrollable&&!usePageScroll&&scrollEnable" :enable-back-to-top="finalEnableBackToTop"
:show-scrollbar="showScrollbar" :scroll-with-animation="finalScrollWithAnimation"
:scroll-into-view="scrollIntoView" :lower-threshold="finalLowerThreshold" :upper-threshold="5"
:refresher-enabled="finalRefresherEnabled&&!useCustomRefresher" :refresher-threshold="finalRefresherThreshold"
:refresher-default-style="finalRefresherDefaultStyle" :refresher-background="refresherBackground"
:refresher-triggered="refresherTriggered" @scroll="_scroll" @scrolltolower="_onLoadingMore('toBottom')"
@scrolltoupper="_scrollToUpper" @refresherrestore="_onRestore" @refresherrefresh="_onRefresh"
>
<view class="zp-paging-touch-view"
<!-- #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
@touchstart="_refresherTouchstart" @touchmove="_refresherTouchmove" @touchend="_refresherTouchend" @touchcancel="_refresherTouchend"
<!-- #endif -->
<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
@touchstart="pagingWxs.touchstart" @touchmove="pagingWxs.touchmove" @touchend="pagingWxs.touchend" @touchcancel="pagingWxs.touchend"
@mousedown="pagingWxs.mousedown" @mousemove="pagingWxs.mousemove" @mouseup="pagingWxs.mouseup" @mouseleave="pagingWxs.mouseleave"
<!-- #endif -->
>
<view v-if="finalRefresherFixedBacHeight>0" class="zp-fixed-bac-view" :style="[{'background-color': refresherFixedBackground,'height': `${finalRefresherFixedBacHeight}px`}]"></view>
<view class="zp-paging-main" :style="[{'transform': finalRefresherTransform,'transition': refresherTransition}]"
<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
:change:prop="pagingWxs.propObserver" :prop="wxsPropType"
:data-refresherThreshold="finalRefresherThreshold" :data-isIos="isIos" :data-isIos13="isIos13"
:data-loading="loading" :data-useChatRecordMode="useChatRecordMode"
:data-refresherEnabled="refresherEnabled" :data-useCustomRefresher="useCustomRefresher" :data-pageScrollTop="wxsPageScrollTop"
:data-scrollTop="wxsScrollTop" :data-refresherMaxAngle="refresherMaxAngle"
:data-refresherAecc="refresherAngleEnableChangeContinued" :data-usePageScroll="usePageScroll"
:data-oldIsTouchmoving="isTouchmoving" :data-refresherOutRate="finalRefresherOutRate"
<!-- #endif -->
<!-- #ifdef APP-VUE || H5 -->
:change:renderPropScrollTop="pagingRenderjs.renderPropScrollTopChange" :renderPropScrollTop="renderPropScrollTop"
:change:renderPropUsePageScroll="pagingRenderjs.renderPropUsePageScrollChange" :renderPropUsePageScroll="renderPropUsePageScroll"
<!-- #endif -->
>
<view v-if="showRefresher" class="zp-custom-refresher-view"
:style="[{'margin-top': `-${finalRefresherThreshold}px`,'background-color': refresherBackground}]">
<view class="zp-custom-refresher-container" :style="[{'height': `${finalRefresherThreshold}px`,'background-color': refresherBackground}]">
<!-- 下拉刷新view -->
<view
class="zp-custom-refresher-slot-view">
<slot
<!-- #ifndef MP-QQ -->
:refresherStatus="refresherStatus"
<!-- #endif -->
name="refresher" />
</view>
<z-paging-refresh ref="refresh" v-if="!showCustomRefresher" :style="[{'height': `${finalRefresherThreshold}px`}]" :refresherStatus="refresherStatus"
:defaultThemeStyle="finalRefresherThemeStyle" :refresherDefaultText="finalRefresherDefaultText"
:refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText"
:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
</view>
</view>
<view class="zp-paging-container">
<slot v-if="useChatRecordMode&&$slots.chatLoading&&loadingStatus!==2&&realTotalData.length"
name="chatLoading" />
<view v-else-if="useChatRecordMode&&loadingStatus!==2&&realTotalData.length"
class="zp-chat-record-loading-container">
<text v-if="loadingStatus!==1" @click="_scrollToUpper()"
:class="defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{chatRecordLoadingMoreText}}</text>
<image v-else :src="base64Flower" class="zp-chat-record-loading-custom-image">
</image>
</view>
<slot v-if="$slots.loading&&!firstPageLoaded&&(autoHideLoadingAfterFirstLoaded?!pagingLoaded:true)&&loading" name="loading" />
<!-- 主体内容 -->
<view class="zp-paging-container-content" :style="[finalPagingContentStyle]">
<slot />
</view>
<!-- 上拉加载更多view -->
<!-- #ifndef MP-ALIPAY -->
<slot v-if="_shouldShowLoading('loadingMoreDefault')" name="loadingMoreDefault" />
<slot v-else-if="_shouldShowLoading('loadingMoreLoading')" name="loadingMoreLoading" />
<slot v-else-if="_shouldShowLoading('loadingMoreNoMore')" name="loadingMoreNoMore" />
<slot v-else-if="_shouldShowLoading('loadingMoreFail')" name="loadingMoreFail" />
<z-paging-load-more @click.native="_onLoadingMore('click')"
v-else-if="_shouldShowLoading('loadingMoreCustom')" :zConfig="zPagingLoadMoreConfig">
</z-paging-load-more>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY -->
<slot v-if="loadingStatus===0&&$slots.loadingMoreDefault&&showLoadingMore&&loadingMoreEnabled&&!useChatRecordMode"
name="loadingMoreDefault" />
<slot v-else-if="loadingStatus===1&&$slots.loadingMoreLoading&&showLoadingMore&&loadingMoreEnabled"
name="loadingMoreLoading" />
<slot v-else-if="loadingStatus===2&&$slots.loadingMoreNoMore&&showLoadingMore&&showLoadingMoreNoMoreView&&loadingMoreEnabled&&!useChatRecordMode"
name="loadingMoreNoMore" />
<slot v-else-if="loadingStatus===3&&$slots.loadingMoreFail&&showLoadingMore&&loadingMoreEnabled&&!useChatRecordMode"
name="loadingMoreFail" />
<z-paging-load-more @click.native="_onLoadingMore('click')" v-else-if="showLoadingMore&&showDefaultLoadingMoreText&&!(loadingStatus===2&&!showLoadingMoreNoMoreView)&&loadingMoreEnabled&&!useChatRecordMode" :zConfig="zPagingLoadMoreConfig">
</z-paging-load-more>
<!-- #endif -->
<!-- 空数据图 -->
<view class="zp-empty-view"
v-if="showEmpty">
<slot v-if="$slots.empty" name="empty" />
<z-paging-empty-view v-else :emptyViewImg="finalEmptyViewImg" :emptyViewText="finalEmptyViewText" :showEmptyViewReload="finalShowEmptyViewReload" :emptyViewReloadText="finalEmptyViewReloadText" :isLoadFailed="isLoadFailed" :emptyViewStyle="emptyViewStyle" :emptyViewTitleStyle="emptyViewTitleStyle" :emptyViewImgStyle="emptyViewImgStyle" :emptyViewReloadStyle="emptyViewReloadStyle" :emptyViewZIndex="emptyViewZIndex" @reload="_emptyViewReload">
</z-paging-empty-view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<slot v-if="!usePageScroll&&$slots.bottom" name="bottom"></slot>
<view class="zp-page-scroll-bottom" v-else-if="usePageScroll&&$slots.bottom" :style="[{'bottom': `${windowBottom}px`}]">
<slot name="bottom"></slot>
</view>
<view v-if="showBackToTopClass" :class="backToTopClass" :style="[finalBackToTopStyle]" @click.stop="_backToTopClick">
<slot v-if="$slots.backToTop" name="backToTop" />
<image v-else class="zp-back-to-top-img" :src="backToTopImg.length?backToTopImg:base64BackToTop"></image>
</view>
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view :is="finalNvueSuperListIs">
<view ref="zp-page-scroll-top" :is="nViewIs" class="zp-page-scroll-top" v-if="$slots.top" :style="[{'top':`${windowTop}px`,'z-index':topZIndex}]">
<slot name="top"></slot>
</view>
<view ref="n-list" id="z-paging-nlist" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" :is="finalNvueListIs" alwaysScrollableVertical="true"
:fixFreezing="nFixFreezing" :show-scrollbar="showScrollbar" :loadmoreoffset="finalLowerThreshold"
:scrollable="scrollable&&scrollEnable" :bounce="nvueBounce" :column-count="nWaterfallColumnCount" :column-width="nWaterfallColumnWidth"
:column-gap="nWaterfallColumnGap" :left-gap="nWaterfallLeftGap" :right-gap="nWaterfallRightGap"
@loadmore="_nOnLoadmore" @scroll="_nOnScroll">
<refresh class="zp-n-refresh" v-if="finalNvueListIs!=='view'&&refresherEnabled&&!nShowRefresherReveal&&!useChatRecordMode" :display="nRefresherLoading?'show':'hide'" @refresh="_nOnRrefresh"
@pullingdown="_nOnPullingdown">
<view ref="zp-n-refresh-container" class="zp-n-refresh-container">
<!-- 下拉刷新view -->
<slot v-if="zScopedSlots.refresher" :refresherStatus="refresherStatus" name="refresher" />
<z-paging-refresh ref="refresh" v-else :refresherStatus="refresherStatus" :defaultThemeStyle="finalRefresherThemeStyle"
:refresherDefaultText="finalRefresherDefaultText" :refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText"
:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
</view>
</refresh>
<view ref="zp-n-list-top-tag" class="zp-n-list-top-tag" :is="nViewIs"></view>
<view v-if="nShowRefresherReveal" ref="zp-n-list-refresher-reveal" :style="[{transform:`translateY(-${nShowRefresherRevealHeight}px)`,height:'0px'}]" :is="nViewIs">
<slot v-if="zScopedSlots.refresher" :refresherStatus="refresherStatus" name="refresher" />
<z-paging-refresh ref="refresh" v-else :refresherStatus="refresherStatus" :defaultThemeStyle="finalRefresherThemeStyle"
:refresherDefaultText="finalRefresherDefaultText" :refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText"
:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
</view>
<slot />
<view ref="zp-n-list-bottom-tag" class="zp-n-list-bottom-tag" is="header"></view>
<!-- 全屏 -->
<view style="flex: 1;" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" v-if="$slots.loading&&!firstPageLoaded&&(autoHideLoadingAfterFirstLoaded?!pagingLoaded:true)&&loading" :is="finalNvueListIs==='scroller'?'view':finalNvueListIs==='waterfall'?'header':'cell'">
<slot name="loading" />
</view>
<!-- 上拉加载更多view -->
<view :is="nViewIs">
<view v-if="useChatRecordMode">
<view v-if="loadingStatus!==2&&realTotalData.length">
<slot v-if="$slots.chatLoading"
name="chatLoading" />
<view v-else class="zp-chat-record-loading-container">
<text v-if="loadingStatus!==1" @click="_scrollToUpper()"
:class="defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{chatRecordLoadingMoreText}}</text>
<view>
<loading-indicator v-if="loadingStatus===1" :animating="true"
class="zp-loading-more-line-loading-image">
</loading-indicator>
</view>
</view>
</view>
</view>
<view :style="nLoadingMoreFixedHeight?{height:loadingMoreCustomStyle&&loadingMoreCustomStyle.height?loadingMoreCustomStyle.height:'80rpx'}:{}">
<slot v-if="_shouldShowLoading('loadingMoreDefault')" name="loadingMoreDefault" />
<slot v-else-if="_shouldShowLoading('loadingMoreLoading')" name="loadingMoreLoading" />
<slot v-else-if="_shouldShowLoading('loadingMoreNoMore')" name="loadingMoreNoMore" />
<slot v-else-if="_shouldShowLoading('loadingMoreFail')" name="loadingMoreFail" />
<z-paging-load-more @click.native="_onLoadingMore('click')"
v-else-if="_shouldShowLoading('loadingMoreCustom')" :zConfig="zPagingLoadMoreConfig">
</z-paging-load-more>
</view>
</view>
<!-- 空数据图 -->
<view style="flex: 1;" key="z-paging-empty-view" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" v-if="showEmpty" :is="finalNvueListIs==='scroller'?'view':finalNvueListIs==='waterfall'?'header':'cell'">
<view class="zp-empty-view">
<slot v-if="$slots.empty" name="empty" />
<z-paging-empty-view v-else :emptyViewImg="finalEmptyViewImg" :emptyViewText="finalEmptyViewText" :showEmptyViewReload="finalShowEmptyViewReload" :emptyViewReloadText="finalEmptyViewReloadText" :isLoadFailed="isLoadFailed" :emptyViewStyle="emptyViewStyle" :emptyViewTitleStyle="emptyViewTitleStyle" :emptyViewImgStyle="emptyViewImgStyle" :emptyViewReloadStyle="emptyViewReloadStyle" :emptyViewZIndex="emptyViewZIndex" @reload="_emptyViewReload">
</z-paging-empty-view>
</view>
</view>
</view>
<slot name="bottom"></slot>
<view v-if="showBackToTopClass" :class="backToTopClass" :style="[finalBackToTopStyle]" @click.stop="_backToTopClick">
<slot v-if="$slots.backToTop" name="backToTop" />
<image v-else class="zp-back-to-top-img" :src="backToTopImg.length?backToTopImg:base64BackToTop"></image>
</view>
</view>
<!-- #endif -->
</template>
<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
<script
src="./wxs/z-paging-wxs.wxs"
module="pagingWxs"
lang="wxs"
></script>
<!-- #endif -->
<script module="pagingRenderjs" lang="renderjs">
import pagingRenderjs from './wxs/z-paging-renderjs.js';
/**
* z-paging 分页组件
* @description 【uni-app自动分页器】超简单低耦合仅需两步轻松完成完整分页逻辑(下拉刷新、上拉加载更多)分页全自动处理。支持自定义加载更多的文字或整个view自定义下拉刷新样式自动管理空数据view等。
* @tutorial http://z-paging.com
* @property {Number|String} default-page-no 自定义pageNo默认为1
* @property {Number|String} default-page-size 自定义pageSize默认为10
* @property {Number|Object} data-key 为保证数据一致设置当前tab切换时的标识key并在complete中传递相同key若二者不一致则complete将不会生效
* @property {String} autowire-list-name 【极简写法】自动注入的list名可自动修改父view(包含ref="paging")中对应name的list值(z-paging标签必须设置`ref="paging"`)
* @property {String} autowire-query-name 【极简写法】自动注入的query名可自动调用父view(包含ref="paging")中的query方法(z-paging标签必须设置`ref="paging"`)
* @property {Number|Object} delay 调用complete后延迟处理的时间单位为毫秒
* @property {String} language i18n国际化设置语言支持简体中文(zh-cn)、繁体中文(zh-hant-cn)和英文(en)
* @property {Boolean} follow-system-language i18n国际化默认是否跟随系统语言默认为是
* @property {Object} paging-style 设置z-paging的style部分平台可能无法直接修改组件的style可使用此属性代替
* @property {Object} paging-content-style 设置z-paging的容器(插槽的父view)的style
* @property {Boolean} auto-height z-paging是否自动高度若自动高度则会自动铺满屏幕默认为否
* @property {Number|String} auto-height-addition z-paging是否自动高度时附加的高度注意添加单位px或rpx默认为px若需要减少高度请传负数
* @property {String} default-theme-style loading(下拉刷新、上拉加载更多)的主题样式支持blackwhite默认black
* @property {String} refresher-theme-style 下拉刷新的主题样式支持blackwhite默认black
* @property {String} loading-more-theme-style 底部加载更多的主题样式支持blackwhite默认black
* @property {Boolean} refresher-only 是否只使用下拉刷新设置为true后将关闭mounted自动请求数据、关闭滚动到底部加载更多强制隐藏空数据图。默认为否
* @property {Boolean} use-page-scroll 使用页面滚动默认为否当设置为是时则使用页面的滚动而非此组件内部的scroll-view的滚动使用页面滚动时z-paging无需设置确定的高度且对于长列表展示性能更高但配置会略微繁琐
* @property {Boolean} fixed z-paging是否使用fixed布局若使用fixed布局则z-paging的父view无需固定高度z-paging高度默认为100%,默认为否(当使用内置scroll-view滚动时有效)
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区域适配,默认为否
* @property {Boolean} scrollable 是否可以滚动使用内置scroll-view和nvue时有效默认为是
* @property {Boolean} auto [z-paging]mounted后自动调用reload方法(mounted后自动调用接口),默认为是
* @property {Boolean} auto-scroll-to-top-when-reload reload时自动滚动到顶部默认为是
* @property {Boolean} auto-clean-list-when-reload reload时立即自动清空原list默认为是若立即自动清空则在reload之后、请求回调之前页面是空白的
* @property {Boolean} show-refresher-when-reload 调用reload方法时是否自动显示下拉刷新view默认为否
* @property {Boolean} show-loading-more-when-reload 调用reload方法时自动显示加载更多view且为加载中状态(仅初始设置有效,不可动态修改)
* @property {Boolean} refresher-update-time-key 如果需要区别不同页面的最后更新时间请为不同页面的z-paging的`refresher-update-time-key`设置不同的字符串
* @property {Boolean} use-custom-refresher 是否使用自定义的下拉刷新默认为是即使用z-paging的下拉刷新。设置为false即代表使用uni scroll-view自带的下拉刷新h5、App、微信小程序以外的平台不支持uni scroll-view自带的下拉刷新
* @property {Number|String} refresher-fps 自定义下拉刷新下拉帧率默认为40过高可能会出现抖动问题(use-custom-refresher为true时生效)
* @property {Number|String} refresher-max-angle 自定义下拉刷新允许触发的最大下拉角度默认为40度当下拉角度小于设定值时自定义下拉刷新动画不会被触发
* @property {Boolean} refresher-angle-enable-change-continued 自定义下拉刷新的角度由未达到最大角度变到达到最大角度时,是否继续下拉刷新手势,默认为否
* @property {String|Object} refresher-default-text 自定义下拉刷新默认状态下的文字(use-custom-refresher为true时生效)
* @property {String|Object} refresher-pulling-text 自定义下拉刷新松手立即刷新状态下的文字(use-custom-refresher为true时生效)
* @property {String|Object} refresher-refreshing-text 自定义下拉刷新刷新中状态下的文字(use-custom-refresher为true时生效)
* @property {Boolean} refresher-end-bounce-enabled 是否开启自定义下拉刷新刷新结束回弹效果,默认为是(use-custom-refresher为true时生效)
* @property {Object} loading-more-custom-style 自定义底部加载更多样式
* @property {Object} loading-more-loading-icon-custom-style 自定义底部加载更多加载中动画样式
* @property {String} loading-more-loading-icon-type 自定义底部加载更多加载中动画图标类型可选circle或flower默认为circle
* @property {String} loading-more-loading-icon-custom-image 自定义底部加载更多加载中动画图标图片
* @property {Boolean} loading-more-loading-animated 底部加载更多加载中view是否展示旋转动画(loading-more-loading-icon-custom-image有值时有效nvue无效)
* @property {Boolean} loading-more-enabled 是否启用加载更多数据(含滑动到底部加载更多数据和点击加载更多数据),默认为是
* @property {Boolean} to-bottom-loading-more-enabled 是否启用滑动到底部加载更多数据
* @property {String|Object} loading-more-default-text 滑动到底部"默认"文字,默认为【点击加载更多】
* @property {String|Object} loading-more-loading-text 滑动到底部"加载中"文字,默认为【正在加载...】
* @property {String|Object} loading-more-no-more-text 滑动到底部"没有更多"文字,默认为【没有更多了】
* @property {String|Object} loading-more-fail-text 滑动到底部"加载失败"文字,默认为【加载失败,点击重新加载】
* @property {Boolean} hide-loading-more-when-no-more-and-inside-of-paging 当没有更多数据且分页内容未超出z-paging时是否隐藏没有更多数据的view默认为是
* @property {Boolean} hide-loading-more-when-no-more-and-inside-of-paging 当没有更多数据且分页内容未超出z-paging时是否隐藏没有更多数据的view默认为是
* @property {Boolean} inside-more 当分页未满一屏时,是否自动加载更多(nvue无效),默认为否
* @property {Boolean} show-default-loading-more-text 是否显示默认的加载更多text默认为是
* @property {Boolean} show-loading-more-no-more-line 是否显示没有更多数据的分割线,默认为是
* @property {Object} loading-more-no-more-line-custom-style 自定义底部没有更多数据的分割线样式
* @property {Boolean} hide-empty-view 是否强制隐藏空数据图,默认为否
* @property {String|Object} empty-view-text 空数据图描述文字,默认为“没有数据哦~”
* @property {Boolean} show-empty-view-reload 是否显示空数据图重新加载按钮(无数据时),默认为否
* @property {Boolean} show-empty-view-reload-when-error 加载失败时是否显示空数据图重新加载按钮,默认为是
* @property {String} empty-view-img 空数据图图片默认使用z-paging内置的图片
* @property {String|Object} empty-view-reload-text 空数据图点击重新加载文字
* @property {String|Object} empty-view-error-text 空数据图“加载失败”描述文字
* @property {String} empty-view-error-img 空数据图“加载失败”图片默认使用z-paging内置的图片(建议使用绝对路径)
* @property {Object} empty-view-style 空数据图样式
* @property {Object} empty-view-img-style 空数据图img样式
* @property {Object} empty-view-title-style 空数据图描述文字样式
* @property {Object} empty-view-reload-style 空数据图重新加载按钮样式
* @property {Boolean} auto-hide-empty-view-when-loading 加载中时是否自动隐藏空数据图,默认为是
* @property {Boolean} auto-hide-loading-after-first-loaded 第一次加载后自动隐藏loading slot默认为是
* @property {Boolean} auto-show-back-to-top 自动显示点击返回顶部按钮,默认为否
* @property {Number|String} back-to-top-threshold 点击返回顶部按钮显示/隐藏的阈值(滚动距离)单位为px默认为400rpx
* @property {String} back-to-top-img 点击返回顶部按钮的自定义图片地址默认使用z-paging内置的图片
* @property {Boolean} back-to-top-with-animate 点击返回顶部按钮返回到顶部时是否展示过渡动画,默认为是
* @property {Number|String} back-to-top-bottom 点击返回顶部按钮与底部的距离注意添加单位px或rpx默认为160rpx
* @property {Object} back-to-top-style 点击返回顶部按钮的自定义样式
* @property {Boolean} show-scrollbar 在设置滚动条位置时使用动画过渡,默认为否
* @property {Boolean} scroll-to-top-bounce-enabled iOS设备上滚动到顶部时是否允许回弹效果默认为否。关闭回弹效果后可使滚动到顶部与下拉刷新更连贯但是有吸顶view时滚动到顶部时可能出现抖动。
* @property {Boolean} scroll-with-animation 控制是否出现滚动条,默认为否
* @property {String} scroll-into-view 值应为某子元素idid不能以数字开头。设置哪个方向可滚动则在哪个方向滚动到该元素
* @property {Number|String} lower-threshold 距底部/右边多远时单位px触发 scrolltolower 事件默认为100rpx
* @property {Boolean} enable-back-to-top iOS点击顶部状态栏、安卓双击标题栏时滚动条返回顶部只支持竖向默认为是
* @property {Boolean} refresher-enabled 是否开启自定义下拉刷新,默认为是
* @property {Number|String} refresher-threshold 设置自定义下拉刷新阈值默认为80rpx
* @property {String} refresher-default-style 设置自定义下拉刷新默认样式,支持设置 blackwhitenonenone 表示不使用默认样式默认为black
* @property {String} refresher-background 设置自定义下拉刷新区域背景颜色
* @property {Boolean} show-refresher-update-time 是否显示上次下拉刷新更新时间,默认为否
* @property {String} refresher-update-time-key 上次下拉刷新更新时间的key用于区别不同的上次更新时间
* @property {Number|String} local-paging-loading-time 本地分页时上拉加载更多延迟时间单位为毫秒默认200毫秒
* @property {Boolean} use-chat-record-mode 使用聊天记录模式,默认为否
* @property {Number} top-z-index slot="top"的view的z-index仅使用页面滚动时有效默认为99
* @property {Number} super-content-z-index z-paging内容容器父view的z-index默认为1
* @property {Number} content-z-index z-paging内容容器部分的z-index默认为10
* @property {Number} empty-view-z-index 空数据view的z-index默认为9
* @property {Boolean} auto-full-height 使用页面滚动时,是否在不满屏时自动填充满屏幕,默认为是
* @property {Boolean} concat 自动拼接complete中传过来的数组(使用聊天记录模式时无效),默认为是
* @property {String} nvue-list-is nvue中修改列表类型可选值有list、waterfall和scroller默认为list
* @property {Object} nvue-waterfall-config nvue waterfall配置仅在nvue中且nvueListIs=waterfall时有效配置参数详情参见https://uniapp.dcloud.io/component/waterfall
* @property {Boolean} nvue-bounce nvue 控制是否回弹效果iOS不支持动态修改(若禁用回弹效果,下拉刷新将失效),默认为是
* @property {Boolean} nvue-fast-scroll nvue中通过代码滚动到顶部/底部时,是否加快动画效果(无滚动动画时无效),默认为否
* @property {Boolean} show-console-error 是否将错误信息打印至控制台,默认为是
* @event {Function} query 组件加载时会自动触发此方法因此默认页面加载时会自动触发无需手动调用。pageNo和pageSize会自动计算好直接传给服务器即可。
* @event {Function} refresherStatusChange 自定义下拉刷新状态改变(use-custom-refresher为true时生效)【注:通过`:refresher-status.sync`绑定当前data中的指定变量亦可】
* @event {Function} loadingStatusChange 上拉加载更多状态改变
* @event {Function} refresherTouchstart 自定义下拉刷新下拉开始(use-custom-refresher为true时生效)【注:当需要更细致定制自定义下拉刷新时使用,如果只需监听下拉刷新各个状态改变,使用`refresherStatusChange`即可】
* @event {Function} refresherTouchmove 自定义下拉刷新下拉中开始(use-custom-refresher为true时生效)【注:当需要更细致定制自定义下拉刷新时使用,如果只需监听下拉刷新各个状态改变,使用`refresherStatusChange`即可】
* @event {Function} refresherTouchend 自定义下拉刷新下拉结束(use-custom-refresher为true时生效)【注:当需要更细致定制自定义下拉刷新时使用,如果只需监听下拉刷新各个状态改变,使用`refresherStatusChange`即可】
* @event {Function} onRefresh 自定义下拉刷新被触发
* @event {Function} onRestore 自定义下拉刷新被复位
* @event {Function} scroll `z-paging`内置的scroll-view滚动时触发
* @event {Function} scrollTopChange scrollTop改变时触发使用点击返回顶部时需要获取scrollTop时可使用此事件【注通过`:scroll-top.sync`绑定当前data中的指定变量亦可】(@scrolltoupper触发时也会自动触发此方法且scrollTop=0)
* @event {Function} scrolltolower `z-paging`内置的scroll-view滚动底部时触发
* @event {Function} scrolltoupper `z-paging`内置的scroll-view滚动顶部时触发
* @event {Function} listChange 分页渲染的数组改变时触发
* @event {Function} emptyViewReload 点击了空数据图中的重新加载按钮
* @example <z-paging ref="paging" v-model="dataList" @query="queryList"></z-paging>
*/
export default {
name:"z-paging",
// #ifdef APP-VUE || H5
mixins: [pagingRenderjs],
// #endif
// 以下代码是为了欺骗编译器使props的代码提示功能生效不会被编译到项目中
// #ifdef QUICKAPP-WEBVIEW-UNION
props: {
defaultPageNo: {type: [Number, String]},
defaultPageSize: {type: [Number, String]},
dataKey: {type: [Number, Object]},
autowireListName: {type: String},
autowireQueryName: {type: String},
delay: {type: [Number, String]},
language: {type: String},
followSystemLanguage: {type: Boolean},
pagingStyle: {type: Object},
pagingContentStyle: {type: Object},
autoHeight: {type: Boolean},
autoHeightAddition: {type: [Number, String]},
defaultThemeStyle: {type: String},
refresherThemeStyle: {type: String},
loadingMoreThemeStyle: {type: String},
refresherOnly: {type: Boolean},
usePageScroll: {type: Boolean},
fixed: {type: Boolean},
safeAreaInsetBottom: {type: Boolean},
scrollable: {type: Boolean},
mountedAutoCallReload: {type: Boolean},
auto: {type: Boolean},
autoScrollToTopWhenReload: {type: Boolean},
autoCleanListWhenReload: {type: Boolean},
showRefresherWhenReload: {type: Boolean},
showLoadingMoreWhenReload: {type: Boolean},
useCustomRefresher: {type: Boolean},
refresherFps: {type: [Number, String]},
refresherMaxAngle: {type: [Number, String]},
refresherAngleEnableChangeContinued: {type: Boolean},
refresherDefaultText: {type: [String, Object]},
refresherPullingText: {type: [String, Object]},
refresherRefreshingText: {type: [String, Object]},
refresherEndBounceEnabled: {type: Boolean},
loadingMoreCustomStyle: {type: Object},
loadingMoreLoadingIconCustomStyle: {type: Object},
loadingMoreLoadingIconType: {type: String},
loadingMoreLoadingIconCustomImage: {type: String},
loadingMoreLoadingAnimated: {type: Boolean},
loadingMoreEnabled: {type: Boolean},
toBottomLoadingMoreEnabled: {type: Boolean},
loadingMoreDefaultText: {type: [String, Object]},
loadingMoreLoadingText: {type: [String, Object]},
loadingMoreNoMoreText: {type: [String, Object]},
loadingMoreFailText: {type: [String, Object]},
hideLoadingMoreWhenNoMoreAndInsideOfPaging: {type: Boolean},
hideLoadingMoreWhenNoMoreByLimit: {type: Number},
insideMore: {type: Boolean},
showDefaultLoadingMoreText: {type: Boolean},
showLoadingMoreNoMoreView: {type: Boolean},
showLoadingMoreNoMoreLine: {type: Boolean},
loadingMoreNoMoreLineCustomStyle: {type: Object},
hideEmptyView: {type: Boolean},
emptyViewText: {type: [String, Object]},
showEmptyViewReload: {type: Boolean},
showEmptyViewReloadWhenError: {type: Boolean},
emptyViewReloadText: {type: [String, Object]},
emptyViewImg: {type: String},
emptyViewErrorText: {type: [String, Object]},
emptyViewErrorImg: {type: String},
emptyViewStyle: {type: Object},
emptyViewImgStyle: {type: Object},
emptyViewTitleStyle: {type: Object},
emptyViewReloadStyle: {type: Object},
autoHideEmptyViewWhenLoading: {type: Boolean},
autoHideLoadingAfterFirstLoaded: {type: Boolean},
autoShowBackToTop: {type: Boolean},
backToTopThreshold: {type: [Number, String]},
backToTopImg: {type: String},
backToTopWithAnimate: {type: Boolean},
backToTopBottom: {type: [Number, String]},
backToTopStyle: {type: Object},
showScrollbar: {type: Boolean},
scrollToTopBounceEnabled: {type: Boolean},
scrollToBottomBounceEnabled: {type: Boolean},
scrollWithAnimation: {type: Boolean},
scrollIntoView: {type: String},
lowerThreshold: {type: [Number, String]},
enableBackToTop: {type: Boolean},
refresherEnabled: {type: Boolean},
refresherThreshold: {type: [Number, String]},
refresherDefaultStyle: {type: String},
refresherBackground: {type: String},
refresherFixedBackground: {type: String},
refresherFixedBacHeight: {type: [Number, String]},
refresherOutRate: {type: Number},
showRefresherUpdateTime: {type: Boolean},
refresherUpdateTimeKey: {type: String},
localPagingLoadingTime: {type: [Number, String]},
useChatRecordMode: {type: Boolean},
topZIndex: {type: Number},
superContentZIndex: {type: Number},
contentZIndex: {type: Number},
emptyViewZIndex: {type: Number},
autoFullHeight: {type: Boolean},
concat: {type: Boolean},
nvueListIs: {type: String},
nvueWaterfallConfig: {type: Object},
nvueBounce: {type: Boolean},
nvueFastScroll: {type: Boolean},
showConsoleError: {type: Boolean},
value: {type: Array}
}
// #endif
}
</script>
<script
src="./js/z-paging-main.js"></script>
<style scoped>
@import "./css/z-paging-main.css";
@import "./css/z-paging-static.css";
</style>

View File

@@ -0,0 +1,80 @@
{
"id": "z-paging",
"displayName": "【z-paging下拉刷新、上拉加载更多】超简单、低耦合仅需两步轻松完成完整分页逻辑",
"version": "2.0.1",
"description": "【支持nvue使用wxs+renderjs实现】全平台兼容支持自定义下拉刷新、上拉加载更多支持自动管理空数据图、点击返回顶部支持聊天分页、本地分页支持展示最后更新时间支持国际化等等",
"keywords": [
"下拉刷新",
"上拉加载",
"分页器",
"nvue",
"wxs"
],
"repository": "https://github.com/SmileZXLee/uni-z-paging",
"engines": {
"HBuilderX": "^3.0.7"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "393727164"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,237 @@
# z-paging
***
## 【注意】由V1.9.0起fixed属性默认值为truez-paging默认会铺满屏幕。老项目更新请注意使用侧滑滚动切换选项卡或需要局部使用z-paging请设置:fixed="false"。如果您希望fixed属性默认为false请参考文档z-paging.com将fixed默认值设置为false。
***
> 【uni-app自动分页器】超简单低耦合仅需两步轻松完成完整分页逻辑(下拉刷新、上拉加载更多)分页全自动处理。支持自定义加载更多的文字或整个view自定义下拉刷新样式自动管理空数据view支持吸顶效果支持国际化等。
### API文档地址[http://z-paging.com](http://z-paging.com)
### 备用API文档地址[https://www.kancloud.cn/zxlee/z-paging/content](https://www.kancloud.cn/zxlee/z-paging/content)
### 功能&特点
* 【配置简单】仅需两步(绑定网络请求方法、绑定分页结果数组)轻松完成完整下拉刷新,上拉加载更多功能。
* 【低耦合低侵入】分页自动管理。在page中无需处理任何分页相关逻辑无需在data中定义任何分页相关变量全由z-paging内部处理。
* 【超灵活,支持各种类型自定义】支持自定义下拉刷新,自定义上拉加载更多,自带自定义下拉刷新效果,及其他数十种自定义属性。
* 【功能丰富】支持国际化支持自定义且自动管理空数据图支持主题模式切换支持本地分页支持聊天分页模式支持展示最后更新时间支持吸顶效果支持内部scroll-view滚动与页面滚动支持一键滚动到顶部等诸多功能。
* 【多平台兼容细致流畅】支持nvue支持h5、app及各家小程序在app-vue、h5、微信小程序、QQ小程序上使用wxs实现下拉刷新大幅提升性能。多处细节优化给您精致流畅的体验。
### 反馈qq群(点击加群)[790460711](https://jq.qq.com/?_wv=1027&k=vU2fKZZH)
#### 关于自动引入组件
> `z-paging` 支持[easycom组件规范](https://uniapp.dcloud.io/component/README?id=easycom组件规范),无需引用和注册组件即可直接使用,在正在运行的项目中导入`z-paging`可能会提示:`Unknown custom element<z-paging> - did you register the component corrently?... `,此时需要重新运行项目即可。
### 预览
***
| 自定义下拉刷新效果+分页演示 | 吸顶效果+分页演示 |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| ![](http://www.zxlee.cn/github/uni-z-paging/uni-z-paging.gif) | ![](http://www.zxlee.cn/github/uni-z-paging/uni-z-paging2.gif) |
| 滑动切换选项卡+分页演示 | 聊天记录模式+分页演示 |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| ![](http://www.zxlee.cn/github/uni-z-paging/z-paging-demo3.gif) | ![](http://www.zxlee.cn/github/uni-z-paging/z-paging-demo4.gif) |
### 在线demo体验地址
* [http://www.zxlee.cn/github/uni-z-paging/demo/index.html](http://www.zxlee.cn/github/uni-z-paging/demo/index.html)
| 扫码体验 |
| ------------------------------------------------------------ |
| ![](http://www.zxlee.cn/github/uni-z-paging/z-paging-demo.png) |
### 此组件已支持`uni_modules`,下载完整示例时组件在`uni_modules`目录下。
## 基本使用
* ①在`<template>` 中使用@query绑定js中分页请求的方法(`z-paging`会将计算好的pageNo和pageSize两个参数传递到此方法中),然后通过` v-model`绑定列表for循环的list。
* ②在请求结果回调中,通过调用`z-paging``complete()`方法,将请求返回的数组传递给`z-paging`处理,如:`this.$refs.paging.complete(服务器返回的数组);`;若请求失败,调用:`this.$refs.paging.complete(false);`即可。
* 当tab切换或搜索时可以通过`this.$refs.paging.reload()`刷新整个列表。
* 在nvue中z-paging中插入的列表item(z-paging的直接子view)必须是cell必须使用cell包住因为在nvue中z-paging使用的是nvue的list组件具体请查阅demo中的`common-demo-n.vue`示例。
```html
<template>
<view class="content">
<z-paging ref="paging" v-model="dataList" @query="queryList">
<!-- list数据建议像下方这样在item外层套一个view而非直接for循环item因为slot插入有数量限制 -->
<view>
<view class="item" v-for="(item,index) in dataList">
<view class="item-title">{{item.title}}</view>
</view>
</view>
</z-paging>
</view>
</template>
<script>
export default {
data() {
return {
dataList: [],
};
},
methods: {
queryList(pageNo, pageSize) {
//这里的pageNo和pageSize会自动计算好直接传给服务器即可
//这里的请求只是演示,请替换成自己的项目的网络请求,请在网络请求回调中
//通过this.$refs.paging.complete(请求回来的数组);将请求结果传给z-paging
this.$request.queryList(pageNo, pageSize, (data) => {
this.$refs.paging.complete(data);
});
},
},
};
</script>
<style scoped>
</style>
```
## 设置自定义emptyView组件示例
* 设置自定义emptyView组件非必须。空数据时会自动展示空数据组件不需要自己处理
```html
<z-paging ref="paging" v-model="dataList" @query="queryList">
<!-- 设置自己的emptyView组件非必须。空数据时会自动展示空数据组件不需要自己处理 -->
<empty-view slot="empty"></empty-view>
<view>
<view class="item" v-for="(item,index) in dataList">
<view class="item-title">{{item.title}}</view>
</view>
</view>
</z-paging>
```
## 自定义加载更多各个状态的描述文字示例
* 以修改【没有更多了】状态描述文字为例(将默认的"没有更多了"修改为"我也是有底线的!")
```html
<z-paging ref="paging" v-model="dataList" loading-more-no-more-text="我也是有底线的!" @query="queryList">
<!-- 设置自己的emptyView组件非必须。空数据时会自动展示空数据组件不需要自己处理 -->
<view>
<view class="item" v-for="(item,index) in dataList">
<view class="item-title">{{item.title}}</view>
</view>
</view>
</z-paging>
```
## 自定义下拉刷新view示例
* `use-custom-refresher`需要设置为true(默认为true)此时将不会使用uni自带的下拉刷新转为使用z-paging自定义的下拉刷新通过slot可以插入开发者自定义的下拉刷新view。
```html
<z-paging ref="paging" v-model="dataList" :refresher-threshold="80" @query="queryList">
<!-- 自定义下拉刷新view -->
<!-- 注意注意注意QQ小程序或字节跳动小程序中自定义下拉刷新不支持slot-scope将导致custom-refresher无法显示 -->
<!-- 如果是QQ小程序或字节跳动小程序请参照demo中的sticky-demo.vue中的写法此处使用slot-scope是为了减少data中无关变量声明降低依赖 -->
<custom-refresher slot="refresher" slot-scope="{refresherStatus}" :status="refresherStatus"></custom-refresher>
<!-- list数据建议像下方这样在item外层套一个view而非直接for循环item因为slot插入有数量限制 -->
<view>
<view class="item" v-for="(item,index) in dataList" @click="itemClick(item)">
<view class="item-title">{{item.title}}</view>
<view class="item-detail">{{item.detail}}</view>
<view class="item-line"></view>
</view>
</view>
</z-paging>
```
## 自定义加载更多各个状态的描述view示例
* 以修改【没有更多了】状态描述view为例
```html
<z-paging ref="paging" v-model="dataList" @query="queryList">
<view>
<view class="item" v-for="(item,index) in dataList">
<view class="item-title">{{item.title}}</view>
</view>
</view>
<view style="background-color: red" slot="loadingMoreNoMore">这是完全自定义的没有更多数据view</view>
</z-paging>
```
## 使用页面滚动示例
```html
<!-- 使用页面滚动示例(无需设置z-paging的高度) -->
<template>
<view class="content">
<!-- 此时使用了页面的滚动z-paging不需要有确定的高度use-page-scroll需要设置为true -->
<!-- 注意注意这里的ref必须设置且必须等于"paging"否则mixin方法无效 -->
<z-paging ref="paging" v-model="dataList" use-page-scroll @query="queryList">
<!-- 如果希望其他view跟着页面滚动可以放在z-paging标签内 -->
<!-- list数据建议像下方这样在item外层套一个view而非直接for循环item因为slot插入有数量限制 -->
<view>
<view class="item" v-for="(item,index) in dataList" :key="index" @click="itemClick(item)">
<view class="item-title">{{item.title}}</view>
<view class="item-detail">{{item.detail}}</view>
<view class="item-line"></view>
</view>
</view>
</z-paging>
</view>
</template>
<script>
//使用页面滚动时引入此mixin用于监听和处理onPullDownRefresh等页面生命周期方法(如果全局引入了就不要这一步全局引入示例见main.js)
import ZPagingMixin from '@/uni_modules/z-paging/components/z-paging/js/z-paging-mixin'
export default {
//注意这一步不要漏掉必须注册mixins(如果全局引入了就不要这一步全局引入示例见main.js)
mixins: [ZPagingMixin],
data() {
//参见demo
},
methods: {
//参见demo
}
}
</script>
```
## i18n示例
* 请参照demo`i18n-demo.vue`
## 性能与建议
| | 使用内置scroll-view滚动 | 使用页面滚动 | 使用nvue |
| :--------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
| **说明** | 默认模式,`z-paging`需要有确定的高度,下拉刷新与上拉加载更多由`z-paging`内部处理,配置简单。 | `use-page-scroll`设置为true时生效使用页面滚动而非内置scroll-view滚动无需固定`z-paging`的高度,但需要在页面滚动到底部时调用`z-paging``doLoadMore()`方法。<br>当使用页面的下拉刷新时需要引入mixin(可全局引入)具体可参见demo。 | 创建nvue页面并引入`z-paging`且运行在APP上生效`z-paging`将使用nvue独有的`<list>``<refresh>`代替原有的scroll-view和自定义的下拉刷新可大幅提升性能。 |
| **性能** | 不佳 | 一般 | 优 |
| **优缺点** | 【优点】配置简单、耦合度低。普通的简单列表不会有明显卡顿。<br/>【缺点】需要固定`z-paging`高度超出页面部分渲染的资源无法自动回收当列表item比较复杂或数据量过多时可能会造成明显卡顿。 | 【优点】性能优于使用内置的scroll-view滚动超出页面部分渲染的资源会自动回收能适应绝大多数列表滚动的情况即使列表item比较复杂一般也不会感知到卡顿。<br>【缺点】配置略麻烦,耦合度较高。 | 【优点】原生渲染,极致性能,`<list>`组件在不可见部分的渲染资源回收有特殊的优化处理,`<refresh>`组件是app端独有的下拉刷新组件性能远超普通vue页面中的自定义下拉刷新。<br>【缺点】仅App端支持nvue页面写法不如vue页面方便`z-paging`中一些配置和方法在nvue中不支持且nvue页面中支持的第三方组件也比vue页面少。 |
#### 【总结】
* 如果项目列表item比较简单分页数据量不是特别多建议使用默认的「内置scroll-view滚动」。
* 如果项目列表item比较复杂数据量多且使用「内置scroll-view滚动」时卡顿明显建议使用页面滚动。
* 如果是App项目且对性能和细节有较高要求建议在nvue中使用`z-paging`
## 注意事项及常见问题
* 【若无法下拉刷新】请确认要在@query所绑定的方法中调用`this.$refs.paging.complete()`无论是否需要网络请求都要调用只有告知z-paging刷新状态结束了才可以开始下次的下拉刷新。
* 【使用内置scroll-view滚动时】z-paging必须有确定的高度否则上拉加载更多将无法触发建议设置`:fixed=true`即可不设置高度!!(不希望跟着滚动的view可以设置`slot="top"`)。
* 【使用页面滚动时】使用z-paging内置的scroll-view滚动性能不及使用页面的滚动。若您要使用页面的滚动请勿固定z-paging的高度并且必须设置`use-page-scroll`为true否则将导致页面无法滚动(不希望跟着滚动的view可以设置`slot="top"`)。
* 【使用页面滚动时】必须引入mixin(可全局引入)(具体可参照demo中的`page-default-demo.vue`文件)或在页面的`onReachBottom`事件中调用`this.$refs.paging.doLoadMore()`且在`onPageScroll(e)`事件中调用`this.$refs.paging.updatePageScrollTop(e.scrollTop)`。(具体可参照demo中的`page-default-demo.vue`文件)
* 【出现实际上有更多数据而显示没有更多数据时】默认的pageSize(每页显示数量)为10如果您服务端不需要传pageSize(例如有默认的pageSize8)则您需要将默认的pageSize改成您与后端约定好的8若没有修改则z-paging会认为传给服务端的pageSize是10而服务端只返回了8条因此会直接判定为没有更多数据。
* 【若页面无法滚动】请检查z-paging是否有固定的高度若您想使用页面滚动而非z-paging内置的scroll-view的滚动请设置`use-page-scroll`为true。
* 【关于自定义导航栏】若设置了`:fixed=true`则必须将自定义导航栏放在z-paging标签中且添加slot="top",如:`<custom-nav slot="top"></custom-nav>`,如果有多个需要固定顶部的元素,则书写`<view slot="top">需要固定顶部的元素</view>`
### API文档地址[http://z-paging.com](http://z-paging.com)
### 备用API文档地址[https://www.kancloud.cn/zxlee/z-paging/content](https://www.kancloud.cn/zxlee/z-paging/content)

View File

@@ -0,0 +1,4 @@
## 1.0.12021-06-24
修复微信小程序不显示问题
## 1.0.02021-05-12
1. 支持uni_modules

View File

@@ -0,0 +1,295 @@
<template>
<view class="popup_view" :style="{top:popupTop, bottom: popupBottom, zIndex: zIndex}"
:class="{'popup_view_bottom': type == 'bottom' ,'popup_view_center':type == 'center', 'popup_view_top': type == 'top'}"
@touchmove="onTouchMove" v-if="currentValue">
<!-- 遮罩层动画 -->
<view class="popup_mask" @click="hideOnBlur && setAnimationHide()"></view>
<!-- 显示信息层 -->
<view class="popup_container" ref="popupContainer" :class="{'popup_container_bottom': type == 'bottom' ,'popup_container_center':type == 'center', 'popup_container_top': type == 'top'}" :style="{opacity: opacity, transform: transform}">
<slot></slot>
</view>
</view>
</template>
<script>
// #ifdef APP-NVUE
const animation = weex.requireModule('animation');
const dom = weex.requireModule('dom');
// #endif
export default {
props: {
//是否显示
value: {
type: Boolean,
default: function() {
return false;
}
},
//点击遮罩层关闭弹窗
hideOnBlur: {
type: Boolean,
default: function() {
return true;
}
},
//禁止页面滚动H5生效
scroll: {
type: Boolean,
default: true
},
// 类型
// bottom 靠下
// center 居中
// top 靠上
type: {
type: String,
default: function() {
return "bottom";
}
},
// 偏移
offset: {
type: Number,
default: function() {
return 0;
}
},
// index
zIndex: {
type: Number,
default: function() {
return 500;
}
},
},
created() {
this.systemInfo = uni.getSystemInfoSync();
if (typeof this.value !== "undefined") {
if(this.value){
this.setAnimationShow();
}
}
},
watch: {
value(val) {
if(val){
this.setAnimationShow();
} else {
this.setAnimationHide();
}
}
},
data() {
return {
// 传进来的值
currentValue: false,
opacity: 0,
popupTop: "inherit",
popupBottom: "inherit",
transform: "",
systemInfo: {},
timer: null
};
},
methods: {
onTouchMove: function(event) {
!this.scroll && event.preventDefault();
},
getPxRpx(px){
let ratio = 750 / this.systemInfo.screenWidth;
return ratio * px;
},
setAnimationShow() {
this.currentValue = true;
this.$nextTick(() => {
this.timer && clearTimeout(this.timer);
this.$emit("input", true);
this.$emit("change", true);
if (this.type == "bottom") {
this.popupTop = "0rpx";
if(this.offset > 0){
this.popupBottom = this.offset + "rpx";
} else {
this.popupBottom = this.getPxRpx(this.systemInfo.windowBottom) + "rpx";
}
this.animationParsing({
translateY: 0,
defaulTranslateY: 1,
opacity: 1
});
} else if (this.type == "center") {
this.popupTop = "0rpx";
this.popupBottom = "0rpx";
this.animationParsing({
scale: 1,
defaulScale: 0,
opacity: 1
});
} else if (this.type == "top") {
this.popupBottom = "0rpx";
if(this.offset > 0){
this.popupTop = (this.offset + this.getPxRpx(this.systemInfo.statusBarHeight)) + "rpx";
this.maskTop = this.popupTop;
} else {
this.popupTop = "0rpx";
this.maskTop = "0rpx";
}
this.animationParsing({
defaulTranslateY: -1,
translateY: 0,
opacity: 1
});
}
});
},
setAnimationHide() {
this.timer && clearTimeout(this.timer);
if (this.type == "bottom") {
this.animationParsing({
defaulTranslateY: 0,
translateY: 1,
opacity: 0
});
// this.popupTop = "inherit";
// this.popupBottom = "0rpx";
} else if (this.type == "center") {
// this.popupTop = "0rpx";
// this.popupBottom = "0rpx";
this.animationParsing({
scale: 0,
defaulScale: 1,
opacity: 0
});
} else if (this.type == "top") {
this.animationParsing({
defaulTranslateY: 0,
translateY: -1,
opacity: 0
});
// this.popupTop = "0rpx";
// this.popupBottom = "inherit";
}
this.timer = setTimeout(() => {
this.currentValue = false;
this.$emit("input", false);
this.$emit("change", false);
}, 300);
},
animationParsing(data){
// #ifndef APP-NVUE
setTimeout(() => {
let transform = "";
if(data.hasOwnProperty("translateX")){
transform += " translateX("+ (data.translateX * 100) +"%)"
}
if(data.hasOwnProperty("translateY")){
transform += " translateY("+ (data.translateY * 100) +"%)"
}
if(data.hasOwnProperty("scale")){
transform += " scale("+ data.scale +")"
}
this.opacity = data.opacity;
this.transform = transform;
},10);
// #endif
// #ifdef APP-NVUE
let popupContainer = this.$refs.popupContainer;
if(popupContainer){
// if(data.hasOwnProperty("defaulTranslateY") || data.hasOwnProperty("defaulScale")){
// let defaulTransform = "";
// if(data.hasOwnProperty("defaulTranslateY")){
// defaulTransform = "translateY(" + (data.defaulTranslateY * 100) + "%)";
// }
// if(data.hasOwnProperty("defaulScale")){
// defaulTransform = "scale(" + data.defaulScale + ")";
// }
// this.transform = defaulTransform;
// }
if(Array.isArray(popupContainer)){
popupContainer = popupContainer[0];
}
let transform = "";
if(data.hasOwnProperty("translateX") || data.hasOwnProperty("translateY")){
transform += " translate("+ (data.translateX ? data.translateX * 100 : 0) +"%, " + (data.translateY ? data.translateY * 100 : 0) + "%)";
}
if(data.hasOwnProperty("scale")){
transform += " scale("+ data.scale +")"
}
animation.transition(popupContainer, {
styles: {
transform: transform,
transformOrigin: 'center center',
opacity: data.opacity,
},
duration: 300, //ms
timingFunction: 'ease',
delay: 0 //ms
}, function () { });
}
// #endif
},
}
};
</script>
<style lang="scss" scoped>
.popup_view {
position: fixed;
z-index: 500;
top: 0;
right: 0;
left: 0;
bottom: 0;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.popup_view_bottom {
align-items: flex-end;
justify-content: center;
}
.popup_view_top {
align-items: flex-start;
justify-content: center;
}
.popup_view_center {
align-items: center;
justify-content: center;
}
/*遮罩层*/
.popup_mask {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.popup_container {
/* #ifndef APP-NVUE */
max-width: 100vw;
max-height: 100vh;
min-height: 50rpx;
transition: all 0.4s;
z-index: 2;
/* #endif */
z-index: 501;
opacity: 0;
font-size: 28rpx;
position: relative;
border-radius: 30rpx;
background-color: #fff;
}
.popup_container_bottom {
transform: translateY(100%);
width: 750rpx;
}
.popup_container_center {
}
.popup_container_top {
transform: translateY(-100%);
width: 750rpx;
}
</style>

View File

@@ -0,0 +1,79 @@
{
"id": "z-popup",
"displayName": "弹窗,上弹窗,下弹窗,中间弹窗",
"version": "1.0.1",
"description": "弹窗,上弹窗,下弹窗,中间弹窗",
"keywords": [
"弹窗",
"下弹窗",
"中间弹窗",
"上弹窗"
],
"repository": "https://github.com/zhouwei1994/uni-app-demo",
"engines": {
"HBuilderX": "^3.0.7"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "465081029"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,51 @@
# 弹窗,上弹窗,下弹窗,中间弹窗
弹窗,上弹窗,下弹窗,中间弹窗
| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群"` |
| ----------------------------|--------------------------- |
|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
| QQ群号607391225 |微信号zhou0612wei|
### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
### 案例一
```
<z-popup v-model="true" @change="onChange">
<view class="popup_title">
<text @click="popupShow = false">取消</text>
<view>弹窗标题</view>
<text @click="popupShow = false">确定</text>
</view>
<view class="popup_content">
弹窗内容
</view>
</z-popup>
// js
methods: {
onChange(e){
if(e){
uni.showToast({
title:"打开了弹窗",
icon:"none"
});
}else {
uni.showToast({
title:"关闭了弹窗",
icon:"none"
});
}
}
},
```
### 属性
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
| value | Boolean | false | 控制弹窗是否打开 |
| hideOnBlur | Boolean | true | 点击遮罩层关闭弹窗|
| scroll | Boolean | true | 禁止页面滚动H5生效 |
| type | String | bottom | 弹窗方位bottom 靠下, center 居中, top 靠上 |
| offset | Number | 0 | type=bottom和type=top的时候设置这个数据弹窗会朝相反的方向偏移 |
| zIndex | Number | 500 | 设置弹窗的层级, 普通vue页面有效 |

View File

@@ -0,0 +1,2 @@
## 1.0.02021-05-12
1. 支持uni_modules

View File

@@ -0,0 +1,193 @@
<template>
<view>
<view class="popupClick" @click="onPopupShow()"><slot></slot></view>
<view class="popupMask" v-if="popupShow" @click="onPopupHide"></view>
<view class="popupContentBox" v-if="popupShow">
<view class="close" @click="onPopupHide">×</view>
<view class="title">{{ popupConfig.title }}</view>
<view class="popupContent">
<view class="introduce">{{ popupConfig.tips }}</view>
<input
class="input"
:type="popupConfig.inputType"
adjust-position="true"
:password="popupConfig.password"
v-model="popupInput"
:placeholder="popupConfig.placeholder"
:maxlength="popupConfig.maxlength"
focus="true"
placeholder-style="color:#999"
:confirm-type="popupConfig.confirmType"
/>
</view>
<view class="popupBut">
<button @click="onConfirm">{{ popupConfig.confirmText }}</button>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
value: {
type: String,
default: function() {
return '';
}
},
options: {
type: Object,
default: function() {
return {};
}
}
},
data() {
return {
popupConfig: {
title: '操作',
tips: "请输入",
confirmText: '确认',
placeholder: '',
password: false,
inputType: 'text',
maxlength: 140,
confirmType: "done"
},
popupInput: '',
popupShow: false
};
},
//第一次加载
created() {
if(this.value){
this.popupInput = this.value;
}
if(this.options && typeof(this.options) == "object"){
this.popupConfig = Object.assign(this.popupConfig, this.options);
}
},
watch:{
value(val){
this.popupInput = val;
},
options(val){
if(val && typeof(val) == "object"){
this.popupConfig = Object.assign(this.popupConfig, val);
}
}
},
//方法
methods: {
//打开弹窗
onPopupShow(value,options) {
if(value){
this.popupInput = value;
}
if(options && typeof(options) == "object"){
this.popupConfig = Object.assign(this.popupConfig, options);
}
this.popupShow = true;
},
//关闭弹窗
onPopupHide() {
this.popupShow = false;
},
onConfirm() {
if (this.popupInput == '') {
uni.showToast({
title: '请输入',
icon: 'none'
});
return;
}
this.$emit('confirm', {
close:() => {
this.popupShow = false;
},
value: this.popupInput
});
}
}
};
</script>
<style lang="scss" scoped>
@import '@/style/mixin.scss';
.popupMask {
position: fixed;
top: 0upx;
left: 0upx;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 510;
animation: popupMask 0.4s;
}
.popupContentBox {
position: fixed;
top: 30%;
left: 10%;
width: 80%;
transform: translateY(-50%);
background-color: #fff;
z-index: 511;
animation: popupContentBox 0.4s;
}
.popupContentBox .close {
position: absolute;
top: 10upx;
right: 15upx;
color: #999;
font-size: 42upx;
line-height: 40upx;
}
.popupContentBox .title {
text-align: center;
height: 80upx;
line-height: 80upx;
font-size: 34upx;
color: #666;
}
.popupContentBox .popupContent {
padding: 30upx 40upx;
}
.popupContentBox .popupContent .input {
width: 100%;
border-radius: 10upx;
border: 1px solid #eee;
height: 80upx;
font-size: 30upx;
padding: 0 20upx;
box-sizing: border-box;
}
.popupContentBox .popupContent .introduce {
font-size: 28upx;
color: #999;
padding-bottom: 10upx;
}
.popupContentBox .popupBut {
padding: 20upx 20upx 20upx 20upx;
}
.popupContentBox .popupBut button {
background-color:$themeColor;
color: #fff;
}
@keyframes popupMask {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes popupContentBox {
0% {
opacity: 0;
transform: translateY(-60%);
}
100% {
opacity: 1;
transform: translateY(-50%);
}
}
</style>

View File

@@ -0,0 +1,77 @@
{
"id": "z-prompt",
"displayName": "弹出输入框",
"version": "1.0.0",
"description": "弹出输入框",
"keywords": [
"弹出输入框",
"输入框"
],
"repository": "https://github.com/zhouwei1994/uni-app-demo",
"engines": {
"HBuilderX": "^3.0.0"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "465081029"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,65 @@
# 弹出输入框
弹出输入框
| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群"` |
| ----------------------------|--------------------------- |
|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
| QQ群号607391225 |微信号zhou0612wei|
### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
### 案例一
```
<z-prompt v-model="true" @change="onChange"></z-prompt>
// js
methods: {
onChange(e){
if(/^1\d{10}$/.test(e.value)){
uni.showToast({
title: '请输入正确的手机',
icon: 'none'
});
return;
}
e.close();
}
},
```
### 案例二
```
<z-prompt @change="onChange">
<button>打开</button>
</z-prompt>
// js
methods: {
onChange(e){
if(/^1\d{10}$/.test(e.value)){
uni.showToast({
title: '请输入正确的手机',
icon: 'none'
});
return;
}
e.close();
}
},
```
### 属性
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
| value | Boolean | false | 控制弹窗是否打开 |
| options | Object | 有 | 弹窗配置参数 请看下面options属性 |
### options属性
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
| title | String | 操作 | 弹窗标题 |
| tips | String | 请输入 | 输入框上面的提示 |
| confirmText | String | 请输入 | 确认按钮的弹窗 |
| placeholder | String | | 输入框的提示 |
| password | Boolean | false | 是否密码输入框 |
| inputType | String | text | 输入框类型 |
| maxlength | Number | 140 | 输入框最大可输入长度 |
| confirmType | String | done | 键盘提交按钮配置(值请参考官方) |

View File

@@ -0,0 +1,95 @@
# swipe-action 滑动操作
### `觉得不错给个5星好评吧`
| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群"` |
| ----------------------------|--------------------------- |
|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
| QQ群号607391225 |微信号zhou0612wei|
### [点击跳转-本插件示例](https://ext.dcloud.net.cn/plugin?id=2009)
### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
### 使用时不懂的请看上面链接的插件示例
### 示例代码
```
<template>
<view>
<swipe-action :options="options" :show="show"><view class="swipe_action">滑动</view></swipe-action>
<swipe-action :options="options" disabled><view class="swipe_action">禁止滑动</view></swipe-action>
<view v-for="(item, index) of 3" :key="index" class="swipe_action_list">
<swipe-action :options="options3" :index="index" @button="onButton">
<view class="swipe_action">滑动列表{{ index + 1 }}</view>
</swipe-action>
</view>
</view>
</template>
<script>
import swipeAction from '@/components/zhouWei-swipeAction';
export default {
components: {
swipeAction
},
data() {
return {
options: [
{
text: '删除',
style: {
backgroundColor: '#dd524d'
}
},
{
text: '取消',
style: {
backgroundColor: '#007aff'
}
}
],
show: true
};
},
methods: {
onButton(e) {
uni.showToast({
title: '您点击了滑动列表' + (e.index + 1) + '的第' + (e.buttonIndex + 1) + '个按钮,按钮为‘' + e.content.text + '',
icon: 'none'
});
}
},
}
</script>
```
### 使用说明
| 名称 | 类型 | 默认值 | 描述 |
| ----------|--------------- | ------------- | -------------------|
| options | Array | [] | 查看options参数说明 |
| disabled | Boolean | false | 是否禁止滑动 |
| show | Boolean | false | 是否打开 |
| autoClose | Boolean | true | 点击后是否自动关闭 |
| index | Number | 0 | 循环的时候的索引值,通过@button传递出去 |
### options参数说明
| 名称 | 类型 | 描述 |
| ------------------------|--------------- | -------------------|
| text | String | 按钮名称 |
| style | Object | 按钮样式 |
| style.backgroundColor | String | 按钮背景颜色 |
| style.fontSize | String | 按钮字体大小 |
| style.color | String | 按钮字体颜色 |
### 事件
| 名称 | 描述 |
| -----------------| --------------------------|
| button | 左滑按钮点击事件 |
```
按钮左滑按钮点击事件返回值
{
content: "点击按钮的options参数",
index: "循环的时候的索引值",
buttonIndex: "点击按钮的索引值"
}
```

Some files were not shown because too many files have changed in this diff Show More