260720
This commit is contained in:
31
uni_modules/uv-icon/changelog.md
Normal file
31
uni_modules/uv-icon/changelog.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## 1.0.13(2023-12-06)
|
||||
1. 优化
|
||||
## 1.0.12(2023-12-06)
|
||||
1. 阻止事件冒泡处理
|
||||
## 1.0.11(2023-10-29)
|
||||
1. imgMode默认值改成aspectFit
|
||||
## 1.0.10(2023-08-13)
|
||||
1. 优化nvue,方便自定义图标
|
||||
## 1.0.9(2023-07-28)
|
||||
1. 修改几个对应错误图标的BUG
|
||||
## 1.0.8(2023-07-24)
|
||||
1. 优化 支持base64图片
|
||||
## 1.0.7(2023-07-17)
|
||||
1. 修复 uv-icon 恢复uv-empty相关的图标
|
||||
## 1.0.6(2023-07-13)
|
||||
1. 修复icon设置name属性对应图标错误的BUG
|
||||
## 1.0.5(2023-07-04)
|
||||
1. 更新图标,删除一些不常用的图标
|
||||
2. 删除base64,修改成ttf文件引入读取图标
|
||||
3. 自定义图标文档说明:https://www.uvui.cn/guide/customIcon.html
|
||||
## 1.0.4(2023-07-03)
|
||||
1. 修复主题颜色在APP不生效的BUG
|
||||
## 1.0.3(2023-05-24)
|
||||
1. 将线上ttf字体包替换成base64,避免加载时或者网络差时候显示白色方块
|
||||
## 1.0.2(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.1(2023-05-10)
|
||||
1. 修复小程序中异常显示
|
||||
## 1.0.0(2023-05-04)
|
||||
新发版
|
||||
160
uni_modules/uv-icon/components/uv-icon/icons.js
Normal file
160
uni_modules/uv-icon/components/uv-icon/icons.js
Normal file
@@ -0,0 +1,160 @@
|
||||
export default {
|
||||
'uvicon-level': 'e68f',
|
||||
'uvicon-checkbox-mark': 'e659',
|
||||
'uvicon-folder': 'e694',
|
||||
'uvicon-movie': 'e67c',
|
||||
'uvicon-star-fill': 'e61e',
|
||||
'uvicon-star': 'e618',
|
||||
'uvicon-phone-fill': 'e6ac',
|
||||
'uvicon-phone': 'e6ba',
|
||||
'uvicon-apple-fill': 'e635',
|
||||
'uvicon-backspace': 'e64d',
|
||||
'uvicon-attach': 'e640',
|
||||
'uvicon-empty-data': 'e671',
|
||||
'uvicon-empty-address': 'e68a',
|
||||
'uvicon-empty-favor': 'e662',
|
||||
'uvicon-empty-car': 'e657',
|
||||
'uvicon-empty-order': 'e66b',
|
||||
'uvicon-empty-list': 'e672',
|
||||
'uvicon-empty-search': 'e677',
|
||||
'uvicon-empty-permission': 'e67d',
|
||||
'uvicon-empty-news': 'e67e',
|
||||
'uvicon-empty-history': 'e685',
|
||||
'uvicon-empty-coupon': 'e69b',
|
||||
'uvicon-empty-page': 'e60e',
|
||||
'uvicon-empty-wifi-off': 'e6cc',
|
||||
'uvicon-reload': 'e627',
|
||||
'uvicon-order': 'e695',
|
||||
'uvicon-server-man': 'e601',
|
||||
'uvicon-search': 'e632',
|
||||
'uvicon-more-dot-fill': 'e66f',
|
||||
'uvicon-scan': 'e631',
|
||||
'uvicon-map': 'e665',
|
||||
'uvicon-map-fill': 'e6a8',
|
||||
'uvicon-tags': 'e621',
|
||||
'uvicon-tags-fill': 'e613',
|
||||
'uvicon-eye': 'e664',
|
||||
'uvicon-eye-fill': 'e697',
|
||||
'uvicon-eye-off': 'e69c',
|
||||
'uvicon-eye-off-outline': 'e688',
|
||||
'uvicon-mic': 'e66d',
|
||||
'uvicon-mic-off': 'e691',
|
||||
'uvicon-calendar': 'e65c',
|
||||
'uvicon-trash': 'e623',
|
||||
'uvicon-trash-fill': 'e6ce',
|
||||
'uvicon-play-left': 'e6bf',
|
||||
'uvicon-play-right': 'e6b3',
|
||||
'uvicon-minus': 'e614',
|
||||
'uvicon-plus': 'e625',
|
||||
'uvicon-info-circle': 'e69f',
|
||||
'uvicon-info-circle-fill': 'e6a7',
|
||||
'uvicon-question-circle': 'e622',
|
||||
'uvicon-question-circle-fill': 'e6bc',
|
||||
'uvicon-close': 'e65a',
|
||||
'uvicon-checkmark': 'e64a',
|
||||
'uvicon-checkmark-circle': 'e643',
|
||||
'uvicon-checkmark-circle-fill': 'e668',
|
||||
'uvicon-setting': 'e602',
|
||||
'uvicon-setting-fill': 'e6d0',
|
||||
'uvicon-heart': 'e6a2',
|
||||
'uvicon-heart-fill': 'e68b',
|
||||
'uvicon-camera': 'e642',
|
||||
'uvicon-camera-fill': 'e650',
|
||||
'uvicon-more-circle': 'e69e',
|
||||
'uvicon-more-circle-fill': 'e684',
|
||||
'uvicon-chat': 'e656',
|
||||
'uvicon-chat-fill': 'e63f',
|
||||
'uvicon-bag': 'e647',
|
||||
'uvicon-error-circle': 'e66e',
|
||||
'uvicon-error-circle-fill': 'e655',
|
||||
'uvicon-close-circle': 'e64e',
|
||||
'uvicon-close-circle-fill': 'e666',
|
||||
'uvicon-share': 'e629',
|
||||
'uvicon-share-fill': 'e6bb',
|
||||
'uvicon-share-square': 'e6c4',
|
||||
'uvicon-shopping-cart': 'e6cb',
|
||||
'uvicon-shopping-cart-fill': 'e630',
|
||||
'uvicon-bell': 'e651',
|
||||
'uvicon-bell-fill': 'e604',
|
||||
'uvicon-list': 'e690',
|
||||
'uvicon-list-dot': 'e6a9',
|
||||
'uvicon-zhifubao-circle-fill': 'e617',
|
||||
'uvicon-weixin-circle-fill': 'e6cd',
|
||||
'uvicon-weixin-fill': 'e620',
|
||||
'uvicon-qq-fill': 'e608',
|
||||
'uvicon-qq-circle-fill': 'e6b9',
|
||||
'uvicon-moments-circel-fill': 'e6c2',
|
||||
'uvicon-moments': 'e6a0',
|
||||
'uvicon-car': 'e64f',
|
||||
'uvicon-car-fill': 'e648',
|
||||
'uvicon-warning-fill': 'e6c7',
|
||||
'uvicon-warning': 'e6c1',
|
||||
'uvicon-clock-fill': 'e64b',
|
||||
'uvicon-clock': 'e66c',
|
||||
'uvicon-edit-pen': 'e65d',
|
||||
'uvicon-edit-pen-fill': 'e679',
|
||||
'uvicon-email': 'e673',
|
||||
'uvicon-email-fill': 'e683',
|
||||
'uvicon-minus-circle': 'e6a5',
|
||||
'uvicon-plus-circle': 'e603',
|
||||
'uvicon-plus-circle-fill': 'e611',
|
||||
'uvicon-file-text': 'e687',
|
||||
'uvicon-file-text-fill': 'e67f',
|
||||
'uvicon-pushpin': 'e6d1',
|
||||
'uvicon-pushpin-fill': 'e6b6',
|
||||
'uvicon-grid': 'e68c',
|
||||
'uvicon-grid-fill': 'e698',
|
||||
'uvicon-play-circle': 'e6af',
|
||||
'uvicon-play-circle-fill': 'e62a',
|
||||
'uvicon-pause-circle-fill': 'e60c',
|
||||
'uvicon-pause': 'e61c',
|
||||
'uvicon-pause-circle': 'e696',
|
||||
'uvicon-gift-fill': 'e6b0',
|
||||
'uvicon-gift': 'e680',
|
||||
'uvicon-kefu-ermai': 'e660',
|
||||
'uvicon-server-fill': 'e610',
|
||||
'uvicon-coupon-fill': 'e64c',
|
||||
'uvicon-coupon': 'e65f',
|
||||
'uvicon-integral': 'e693',
|
||||
'uvicon-integral-fill': 'e6b1',
|
||||
'uvicon-home-fill': 'e68e',
|
||||
'uvicon-home': 'e67b',
|
||||
'uvicon-account': 'e63a',
|
||||
'uvicon-account-fill': 'e653',
|
||||
'uvicon-thumb-down-fill': 'e628',
|
||||
'uvicon-thumb-down': 'e60a',
|
||||
'uvicon-thumb-up': 'e612',
|
||||
'uvicon-thumb-up-fill': 'e62c',
|
||||
'uvicon-lock-fill': 'e6a6',
|
||||
'uvicon-lock-open': 'e68d',
|
||||
'uvicon-lock-opened-fill': 'e6a1',
|
||||
'uvicon-lock': 'e69d',
|
||||
'uvicon-red-packet': 'e6c3',
|
||||
'uvicon-photo-fill': 'e6b4',
|
||||
'uvicon-photo': 'e60d',
|
||||
'uvicon-volume-off-fill': 'e6c8',
|
||||
'uvicon-volume-off': 'e6bd',
|
||||
'uvicon-volume-fill': 'e624',
|
||||
'uvicon-volume': 'e605',
|
||||
'uvicon-download': 'e670',
|
||||
'uvicon-arrow-up-fill': 'e636',
|
||||
'uvicon-arrow-down-fill': 'e638',
|
||||
'uvicon-play-left-fill': 'e6ae',
|
||||
'uvicon-play-right-fill': 'e6ad',
|
||||
'uvicon-arrow-downward': 'e634',
|
||||
'uvicon-arrow-leftward': 'e63b',
|
||||
'uvicon-arrow-rightward': 'e644',
|
||||
'uvicon-arrow-upward': 'e641',
|
||||
'uvicon-arrow-down': 'e63e',
|
||||
'uvicon-arrow-right': 'e63c',
|
||||
'uvicon-arrow-left': 'e646',
|
||||
'uvicon-arrow-up': 'e633',
|
||||
'uvicon-skip-back-left': 'e6c5',
|
||||
'uvicon-skip-forward-right': 'e61f',
|
||||
'uvicon-arrow-left-double': 'e637',
|
||||
'uvicon-man': 'e675',
|
||||
'uvicon-woman': 'e626',
|
||||
'uvicon-en': 'e6b8',
|
||||
'uvicon-twitte': 'e607',
|
||||
'uvicon-twitter-circle-fill': 'e6cf'
|
||||
}
|
||||
90
uni_modules/uv-icon/components/uv-icon/props.js
Normal file
90
uni_modules/uv-icon/components/uv-icon/props.js
Normal file
@@ -0,0 +1,90 @@
|
||||
export default {
|
||||
props: {
|
||||
// 图标类名
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 图标颜色,可接受主题色
|
||||
color: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
// 字体大小,单位px
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: '16px'
|
||||
},
|
||||
// 是否显示粗体
|
||||
bold: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
|
||||
index: {
|
||||
type: [String, Number],
|
||||
default: null
|
||||
},
|
||||
// 触摸图标时的类名
|
||||
hoverClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 自定义扩展前缀,方便用户扩展自己的图标库
|
||||
customPrefix: {
|
||||
type: String,
|
||||
default: 'uvicon'
|
||||
},
|
||||
// 图标右边或者下面的文字
|
||||
label: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// label的位置,只能右边或者下边
|
||||
labelPos: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
},
|
||||
// label的大小
|
||||
labelSize: {
|
||||
type: [String, Number],
|
||||
default: '15px'
|
||||
},
|
||||
// label的颜色
|
||||
labelColor: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
// label与图标的距离
|
||||
space: {
|
||||
type: [String, Number],
|
||||
default: '3px'
|
||||
},
|
||||
// 图片的mode
|
||||
imgMode: {
|
||||
type: String,
|
||||
default: 'aspectFit'
|
||||
},
|
||||
// 用于显示图片小图标时,图片的宽度
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 用于显示图片小图标时,图片的高度
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 用于解决某些情况下,让图标垂直居中的用途
|
||||
top: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 是否阻止事件传播
|
||||
stop: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
...uni.$uv?.props?.icon
|
||||
}
|
||||
}
|
||||
226
uni_modules/uv-icon/components/uv-icon/uv-icon.vue
Normal file
226
uni_modules/uv-icon/components/uv-icon/uv-icon.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-icon"
|
||||
@tap="clickHandler"
|
||||
:class="['uv-icon--' + labelPos]"
|
||||
>
|
||||
<image
|
||||
class="uv-icon__img"
|
||||
v-if="isImg"
|
||||
:src="name"
|
||||
:mode="imgMode"
|
||||
:style="[imgStyle, $uv.addStyle(customStyle)]"
|
||||
></image>
|
||||
<text
|
||||
v-else
|
||||
class="uv-icon__icon"
|
||||
:class="uClasses"
|
||||
:style="[iconStyle, $uv.addStyle(customStyle)]"
|
||||
:hover-class="hoverClass"
|
||||
>{{icon}}</text>
|
||||
<!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
|
||||
<text
|
||||
v-if="label !== ''"
|
||||
class="uv-icon__label"
|
||||
:style="{
|
||||
color: labelColor,
|
||||
fontSize: $uv.addUnit(labelSize),
|
||||
marginLeft: labelPos == 'right' ? $uv.addUnit(space) : 0,
|
||||
marginTop: labelPos == 'bottom' ? $uv.addUnit(space) : 0,
|
||||
marginRight: labelPos == 'left' ? $uv.addUnit(space) : 0,
|
||||
marginBottom: labelPos == 'top' ? $uv.addUnit(space) : 0
|
||||
}"
|
||||
>{{ label }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
// #ifdef APP-NVUE
|
||||
// nvue通过weex的dom模块引入字体,相关文档地址如下:
|
||||
// https://weex.apache.org/zh/docs/modules/dom.html#addrule
|
||||
import iconUrl from './uvicons.ttf';
|
||||
const domModule = weex.requireModule('dom')
|
||||
domModule.addRule('fontFace', {
|
||||
'fontFamily': "uvicon-iconfont",
|
||||
'src': "url('" + iconUrl + "')"
|
||||
})
|
||||
// #endif
|
||||
// 引入图标名称,已经对应的unicode
|
||||
import icons from './icons';
|
||||
import props from './props.js';
|
||||
/**
|
||||
* icon 图标
|
||||
* @description 基于字体的图标集,包含了大多数常见场景的图标。
|
||||
* @tutorial https://www.uvui.cn/components/icon.html
|
||||
* @property {String} name 图标名称,见示例图标集
|
||||
* @property {String} color 图标颜色,可接受主题色 (默认 color['uv-content-color'] )
|
||||
* @property {String | Number} size 图标字体大小,单位px (默认 '16px' )
|
||||
* @property {Boolean} bold 是否显示粗体 (默认 false )
|
||||
* @property {String | Number} index 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
|
||||
* @property {String} hoverClass 图标按下去的样式类,用法同uni的view组件的hoverClass参数,详情见官网
|
||||
* @property {String} customPrefix 自定义扩展前缀,方便用户扩展自己的图标库 (默认 'uicon' )
|
||||
* @property {String | Number} label 图标右侧的label文字
|
||||
* @property {String} labelPos label相对于图标的位置,只能right或bottom (默认 'right' )
|
||||
* @property {String | Number} labelSize label字体大小,单位px (默认 '15px' )
|
||||
* @property {String} labelColor 图标右侧的label文字颜色 ( 默认 color['uv-content-color'] )
|
||||
* @property {String | Number} space label与图标的距离,单位px (默认 '3px' )
|
||||
* @property {String} imgMode 图片的mode
|
||||
* @property {String | Number} width 显示图片小图标时的宽度
|
||||
* @property {String | Number} height 显示图片小图标时的高度
|
||||
* @property {String | Number} top 图标在垂直方向上的定位 用于解决某些情况下,让图标垂直居中的用途 (默认 0 )
|
||||
* @property {Boolean} stop 是否阻止事件传播 (默认 false )
|
||||
* @property {Object} customStyle icon的样式,对象形式
|
||||
* @event {Function} click 点击图标时触发
|
||||
* @event {Function} touchstart 事件触摸时触发
|
||||
* @example <uv-icon name="photo" color="#2979ff" size="28"></uv-icon>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-icon',
|
||||
emits: ['click'],
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
colorType: [
|
||||
'primary',
|
||||
'success',
|
||||
'info',
|
||||
'error',
|
||||
'warning'
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
uClasses() {
|
||||
let classes = []
|
||||
classes.push(this.customPrefix)
|
||||
classes.push(this.customPrefix + '-' + this.name)
|
||||
// 主题色,通过类配置
|
||||
if (this.color && this.colorType.includes(this.color)) classes.push('uv-icon__icon--' + this.color)
|
||||
// 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
|
||||
// 故需将其拆成一个字符串的形式,通过空格隔开各个类名
|
||||
//#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
|
||||
classes = classes.join(' ')
|
||||
//#endif
|
||||
return classes
|
||||
},
|
||||
iconStyle() {
|
||||
let style = {}
|
||||
style = {
|
||||
fontSize: this.$uv.addUnit(this.size),
|
||||
lineHeight: this.$uv.addUnit(this.size),
|
||||
fontWeight: this.bold ? 'bold' : 'normal',
|
||||
// 某些特殊情况需要设置一个到顶部的距离,才能更好的垂直居中
|
||||
top: this.$uv.addUnit(this.top)
|
||||
}
|
||||
// 非主题色值时,才当作颜色值
|
||||
if (this.color && !this.colorType.includes(this.color)) style.color = this.color
|
||||
return style
|
||||
},
|
||||
// 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
|
||||
isImg() {
|
||||
const isBase64 = this.name.indexOf('data:') > -1 && this.name.indexOf('base64') > -1;
|
||||
return this.name.indexOf('/') !== -1 || isBase64;
|
||||
},
|
||||
imgStyle() {
|
||||
let style = {}
|
||||
// 如果设置width和height属性,则优先使用,否则使用size属性
|
||||
style.width = this.width ? this.$uv.addUnit(this.width) : this.$uv.addUnit(this.size)
|
||||
style.height = this.height ? this.$uv.addUnit(this.height) : this.$uv.addUnit(this.size)
|
||||
return style
|
||||
},
|
||||
// 通过图标名,查找对应的图标
|
||||
icon() {
|
||||
// 如果内置的图标中找不到对应的图标,就直接返回name值,因为用户可能传入的是unicode代码
|
||||
const code = icons['uvicon-' + this.name];
|
||||
// #ifdef APP-NVUE
|
||||
if(!code) {
|
||||
return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? unescape(`%u${this.name}`) : '';
|
||||
}
|
||||
// #endif
|
||||
return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? this.name : '';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickHandler(e) {
|
||||
this.$emit('click', this.index)
|
||||
// 是否阻止事件冒泡
|
||||
this.stop && this.preventEvent(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
// 变量定义
|
||||
$uv-icon-primary: $uv-primary !default;
|
||||
$uv-icon-success: $uv-success !default;
|
||||
$uv-icon-info: $uv-info !default;
|
||||
$uv-icon-warning: $uv-warning !default;
|
||||
$uv-icon-error: $uv-error !default;
|
||||
$uv-icon-label-line-height: 1 !default;
|
||||
/* #ifndef APP-NVUE */
|
||||
// 非nvue下加载字体
|
||||
@font-face {
|
||||
font-family: 'uvicon-iconfont';
|
||||
src: url('./uvicons.ttf') format('truetype');
|
||||
}
|
||||
/* #endif */
|
||||
.uv-icon {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
&--left {
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
}
|
||||
&--right {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
&--top {
|
||||
flex-direction: column-reverse;
|
||||
justify-content: center;
|
||||
}
|
||||
&--bottom {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
&__icon {
|
||||
font-family: uvicon-iconfont;
|
||||
position: relative;
|
||||
@include flex;
|
||||
align-items: center;
|
||||
&--primary {
|
||||
color: $uv-icon-primary;
|
||||
}
|
||||
&--success {
|
||||
color: $uv-icon-success;
|
||||
}
|
||||
&--error {
|
||||
color: $uv-icon-error;
|
||||
}
|
||||
&--warning {
|
||||
color: $uv-icon-warning;
|
||||
}
|
||||
&--info {
|
||||
color: $uv-icon-info;
|
||||
}
|
||||
}
|
||||
&__img {
|
||||
/* #ifndef APP-NVUE */
|
||||
height: auto;
|
||||
will-change: transform;
|
||||
/* #endif */
|
||||
}
|
||||
&__label {
|
||||
/* #ifndef APP-NVUE */
|
||||
line-height: $uv-icon-label-line-height;
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
</style>
|
||||
BIN
uni_modules/uv-icon/components/uv-icon/uvicons.ttf
Normal file
BIN
uni_modules/uv-icon/components/uv-icon/uvicons.ttf
Normal file
Binary file not shown.
83
uni_modules/uv-icon/package.json
Normal file
83
uni_modules/uv-icon/package.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"id": "uv-icon",
|
||||
"displayName": "uv-icon 图标 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.13",
|
||||
"description": "基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。可自定义颜色、大小。",
|
||||
"keywords": [
|
||||
"uv-ui,uvui,uv-icon,icon,图标,字体图标"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
uni_modules/uv-icon/readme.md
Normal file
15
uni_modules/uv-icon/readme.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## uv-icon 图标库
|
||||
|
||||
> **组件名:uv-icon**
|
||||
|
||||
基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/icon.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||

|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
29
uni_modules/uv-input/changelog.md
Normal file
29
uni_modules/uv-input/changelog.md
Normal file
@@ -0,0 +1,29 @@
|
||||
## 1.0.13(2023-12-06)
|
||||
1. 优化
|
||||
## 1.0.12(2023-12-06)
|
||||
1. 阻止事件冒泡问题
|
||||
## 1.0.11(2023-11-10)
|
||||
1. 调整清除按钮样式的marginLeft,避免微信上多数情况触发不了的BUG
|
||||
## 1.0.10(2023-10-07)
|
||||
1. 修复搜狗输入法下存在不可清空的情况
|
||||
## 1.0.9(2023-09-14)
|
||||
1. 修复H5等情况设置禁用或可读情况下,点击事件无效的问题
|
||||
## 1.0.8(2023-08-22)
|
||||
1. 修复无法@keyboardheightchange无法获取键盘高度的BUG
|
||||
## 1.0.7(2023-08-18)
|
||||
1. 修复ios端不能输入的BUG
|
||||
## 1.0.6(2023-08-05)
|
||||
1. 修复在vue2模式下,v-model设置为0时不生效的BUG
|
||||
## 1.0.5(2023-07-18)
|
||||
1. 修复在微信小程序端清除内容存在不能清除的BUG
|
||||
## 1.0.4(2023-07-13)
|
||||
1. 修复value/v-model更改不生效的BUG
|
||||
## 1.0.3(2023-07-03)
|
||||
去除插槽判断,避免某些平台不显示的BUG
|
||||
## 1.0.2(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.1(2023-05-12)
|
||||
1. 修复vue3双向绑定的BUG
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-input 输入框
|
||||
175
uni_modules/uv-input/components/uv-input/props.js
Normal file
175
uni_modules/uv-input/components/uv-input/props.js
Normal file
@@ -0,0 +1,175 @@
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 输入框类型
|
||||
// number-数字输入键盘,app-vue下可以输入浮点数,app-nvue和小程序平台下只能输入整数
|
||||
// idcard-身份证输入键盘,微信、支付宝、百度、QQ小程序
|
||||
// digit-带小数点的数字键盘,App的nvue页面、微信、支付宝、百度、头条、QQ小程序
|
||||
// text-文本输入键盘
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
// 是否禁用输入框
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 禁用状态时的背景色
|
||||
disabledColor: {
|
||||
type: String,
|
||||
default: '#f5f7fa'
|
||||
},
|
||||
// 是否显示清除控件
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否密码类型
|
||||
password: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 最大输入长度,设置为 -1 的时候不限制最大长度
|
||||
maxlength: {
|
||||
type: [String, Number],
|
||||
default: -1
|
||||
},
|
||||
// 输入框为空时的占位符
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
// 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写/deep/
|
||||
placeholderClass: {
|
||||
type: String,
|
||||
default: 'input-placeholder'
|
||||
},
|
||||
// 指定placeholder的样式
|
||||
placeholderStyle: {
|
||||
type: [String, Object],
|
||||
default: 'color: #c0c4cc'
|
||||
},
|
||||
// 设置右下角按钮的文字,有效值:send|search|next|go|done,兼容性详见uni-app文档
|
||||
// https://uniapp.dcloud.io/component/input
|
||||
// https://uniapp.dcloud.io/component/textarea
|
||||
confirmType: {
|
||||
type: String,
|
||||
default: 'done'
|
||||
},
|
||||
// 点击键盘右下角按钮时是否保持键盘不收起,H5无效
|
||||
confirmHold: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// focus时,点击页面的时候不收起键盘,微信小程序有效
|
||||
holdKeyboard: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 自动获取焦点
|
||||
// 在 H5 平台能否聚焦以及软键盘是否跟随弹出,取决于当前浏览器本身的实现。nvue 页面不支持,需使用组件的 focus()、blur() 方法控制焦点
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 键盘收起时,是否自动失去焦点,目前仅App3.0.0+有效
|
||||
autoBlur: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 指定focus时光标的位置
|
||||
cursor: {
|
||||
type: [String, Number],
|
||||
default: -1
|
||||
},
|
||||
// 输入框聚焦时底部与键盘的距离
|
||||
cursorSpacing: {
|
||||
type: [String, Number],
|
||||
default: 30
|
||||
},
|
||||
// 光标起始位置,自动聚集时有效,需与selection-end搭配使用
|
||||
selectionStart: {
|
||||
type: [String, Number],
|
||||
default: -1
|
||||
},
|
||||
// 光标结束位置,自动聚集时有效,需与selection-start搭配使用
|
||||
selectionEnd: {
|
||||
type: [String, Number],
|
||||
default: -1
|
||||
},
|
||||
// 键盘弹起时,是否自动上推页面
|
||||
adjustPosition: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 输入框内容对齐方式,可选值为:left|center|right
|
||||
inputAlign: {
|
||||
type: String,
|
||||
default: 'left'
|
||||
},
|
||||
// 输入框字体的大小
|
||||
fontSize: {
|
||||
type: [String, Number],
|
||||
default: '14px'
|
||||
},
|
||||
// 输入框字体颜色
|
||||
color: {
|
||||
type: String,
|
||||
default: '#303133'
|
||||
},
|
||||
// 输入框前置图标
|
||||
prefixIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 前置图标样式,对象或字符串
|
||||
prefixIconStyle: {
|
||||
type: [String, Object],
|
||||
default: ''
|
||||
},
|
||||
// 输入框后置图标
|
||||
suffixIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 后置图标样式,对象或字符串
|
||||
suffixIconStyle: {
|
||||
type: [String, Object],
|
||||
default: ''
|
||||
},
|
||||
// 边框类型,surround-四周边框,bottom-底部边框,none-无边框
|
||||
border: {
|
||||
type: String,
|
||||
default: 'surround'
|
||||
},
|
||||
// 是否只读,与disabled不同之处在于disabled会置灰组件,而readonly则不会
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 输入框形状,circle-圆形,square-方形
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'square'
|
||||
},
|
||||
// 用于处理或者过滤输入框内容的方法
|
||||
formatter: {
|
||||
type: [Function, null],
|
||||
default: null
|
||||
},
|
||||
// 是否忽略组件内对文本合成系统事件的处理
|
||||
ignoreCompositionEvent: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
...uni.$uv?.props?.input
|
||||
}
|
||||
}
|
||||
348
uni_modules/uv-input/components/uv-input/uv-input.vue
Normal file
348
uni_modules/uv-input/components/uv-input/uv-input.vue
Normal file
@@ -0,0 +1,348 @@
|
||||
<template>
|
||||
<view class="uv-input" :class="inputClass" :style="[wrapperStyle]">
|
||||
<view class="uv-input__content">
|
||||
<view class="uv-input__content__prefix-icon">
|
||||
<slot name="prefix">
|
||||
<uv-icon
|
||||
v-if="prefixIcon"
|
||||
:name="prefixIcon"
|
||||
size="18"
|
||||
:customStyle="prefixIconStyle"
|
||||
></uv-icon>
|
||||
</slot>
|
||||
</view>
|
||||
<view class="uv-input__content__field-wrapper" @click="clickHandler">
|
||||
<!-- 根据uni-app的input组件文档,H5和APP中只要声明了password参数(无论true还是false),type均失效,此时
|
||||
为了防止type=number时,又存在password属性,type无效,此时需要设置password为undefined
|
||||
-->
|
||||
<input
|
||||
class="uv-input__content__field-wrapper__field"
|
||||
:style="[inputStyle]"
|
||||
:type="type"
|
||||
:focus="focus"
|
||||
:cursor="cursor"
|
||||
:value="innerValue"
|
||||
:auto-blur="autoBlur"
|
||||
:disabled="disabled || readonly"
|
||||
:maxlength="maxlength"
|
||||
:placeholder="placeholder"
|
||||
:placeholder-style="placeholderStyle"
|
||||
:placeholder-class="placeholderClass"
|
||||
:confirm-type="confirmType"
|
||||
:confirm-hold="confirmHold"
|
||||
:hold-keyboard="holdKeyboard"
|
||||
:cursor-spacing="cursorSpacing"
|
||||
:adjust-position="adjustPosition"
|
||||
:selection-end="selectionEnd"
|
||||
:selection-start="selectionStart"
|
||||
:password="password || type === 'password' || undefined"
|
||||
:ignoreCompositionEvent="ignoreCompositionEvent"
|
||||
@input="onInput"
|
||||
@blur="onBlur"
|
||||
@focus="onFocus"
|
||||
@confirm="onConfirm"
|
||||
@keyboardheightchange="onkeyboardheightchange"
|
||||
/>
|
||||
</view>
|
||||
<view
|
||||
class="uv-input__content__clear"
|
||||
v-if="isShowClear"
|
||||
@tap="onClear"
|
||||
>
|
||||
<uv-icon
|
||||
name="close"
|
||||
size="11"
|
||||
color="#ffffff"
|
||||
customStyle="line-height: 12px"
|
||||
></uv-icon>
|
||||
</view>
|
||||
<view class="uv-input__content__subfix-icon">
|
||||
<slot name="suffix">
|
||||
<uv-icon
|
||||
v-if="suffixIcon"
|
||||
:name="suffixIcon"
|
||||
size="18"
|
||||
:customStyle="suffixIconStyle"
|
||||
></uv-icon>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from "./props.js";
|
||||
/**
|
||||
* Input 输入框
|
||||
* @description 此组件为一个输入框,默认没有边框和样式,是专门为配合表单组件uv-form而设计的,利用它可以快速实现表单验证,输入内容,下拉选择等功能。
|
||||
* @tutorial https://www.uvui.cn/components/input.html
|
||||
* @property {String | Number} value 输入的值
|
||||
* @property {String} type 输入框类型,见上方说明 ( 默认 'text' )
|
||||
* @property {Boolean} fixed 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true,兼容性:微信小程序、百度小程序、字节跳动小程序、QQ小程序 ( 默认 false )
|
||||
* @property {Boolean} disabled 是否禁用输入框 ( 默认 false )
|
||||
* @property {String} disabledColor 禁用状态时的背景色( 默认 '#f5f7fa' )
|
||||
* @property {Boolean} clearable 是否显示清除控件 ( 默认 false )
|
||||
* @property {Boolean} password 是否密码类型 ( 默认 false )
|
||||
* @property {String | Number} maxlength 最大输入长度,设置为 -1 的时候不限制最大长度 ( 默认 -1 )
|
||||
* @property {String} placeholder 输入框为空时的占位符
|
||||
* @property {String} placeholderClass 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写/deep/ ( 默认 'input-placeholder' )
|
||||
* @property {String | Object} placeholderStyle 指定placeholder的样式,字符串/对象形式,如"color: red;"
|
||||
* @property {Boolean} showWordLimit 是否显示输入字数统计,只在 type ="text"或type ="textarea"时有效 ( 默认 false )
|
||||
* @property {String} confirmType 设置右下角按钮的文字,兼容性详见uni-app文档 ( 默认 'done' )
|
||||
* @property {Boolean} confirmHold 点击键盘右下角按钮时是否保持键盘不收起,H5无效 ( 默认 false )
|
||||
* @property {Boolean} holdKeyboard focus时,点击页面的时候不收起键盘,微信小程序有效 ( 默认 false )
|
||||
* @property {Boolean} focus 自动获取焦点,在 H5 平台能否聚焦以及软键盘是否跟随弹出,取决于当前浏览器本身的实现。nvue 页面不支持,需使用组件的 focus()、blur() 方法控制焦点 ( 默认 false )
|
||||
* @property {Boolean} autoBlur 键盘收起时,是否自动失去焦点,目前仅App3.0.0+有效 ( 默认 false )
|
||||
* @property {Boolean} disableDefaultPadding 是否去掉 iOS 下的默认内边距,仅微信小程序,且type=textarea时有效 ( 默认 false )
|
||||
* @property {String | Number} cursor 指定focus时光标的位置( 默认 -1 )
|
||||
* @property {String | Number} cursorSpacing 输入框聚焦时底部与键盘的距离 ( 默认 30 )
|
||||
* @property {String | Number} selectionStart 光标起始位置,自动聚集时有效,需与selection-end搭配使用 ( 默认 -1 )
|
||||
* @property {String | Number} selectionEnd 光标结束位置,自动聚集时有效,需与selection-start搭配使用 ( 默认 -1 )
|
||||
* @property {Boolean} adjustPosition 键盘弹起时,是否自动上推页面 ( 默认 true )
|
||||
* @property {String} inputAlign 输入框内容对齐方式( 默认 'left' )
|
||||
* @property {String | Number} fontSize 输入框字体的大小 ( 默认 '15px' )
|
||||
* @property {String} color 输入框字体颜色 ( 默认 '#303133' )
|
||||
* @property {Function} formatter 内容式化函数
|
||||
* @property {String} prefixIcon 输入框前置图标
|
||||
* @property {String | Object} prefixIconStyle 前置图标样式,对象或字符串
|
||||
* @property {String} suffixIcon 输入框后置图标
|
||||
* @property {String | Object} suffixIconStyle 后置图标样式,对象或字符串
|
||||
* @property {String} border 边框类型,surround-四周边框,bottom-底部边框,none-无边框 ( 默认 'surround' )
|
||||
* @property {Boolean} readonly 是否只读,与disabled不同之处在于disabled会置灰组件,而readonly则不会 ( 默认 false )
|
||||
* @property {String} shape 输入框形状,circle-圆形,square-方形 ( 默认 'square' )
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
* @property {Boolean} ignoreCompositionEvent 是否忽略组件内对文本合成系统事件的处理。
|
||||
* @example <uv-input v-model="value" :password="true" suffix-icon="lock-fill" />
|
||||
*/
|
||||
export default {
|
||||
name: "uv-input",
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
// 输入框的值
|
||||
innerValue: "",
|
||||
// 是否处于获得焦点状态
|
||||
focused: false,
|
||||
// 过滤处理方法
|
||||
innerFormatter: value => value
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// #ifdef VUE2
|
||||
this.innerValue = this.value;
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
this.innerValue = this.modelValue;
|
||||
// #endif
|
||||
},
|
||||
watch: {
|
||||
value(newVal){
|
||||
this.innerValue = newVal;
|
||||
},
|
||||
modelValue(newVal){
|
||||
this.innerValue = newVal;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否显示清除控件
|
||||
isShowClear() {
|
||||
const { clearable, readonly, focused, innerValue } = this;
|
||||
return !!clearable && !readonly && !!focused && innerValue !== "";
|
||||
},
|
||||
// 组件的类名
|
||||
inputClass() {
|
||||
let classes = [],
|
||||
{ border, disabled, shape } = this;
|
||||
border === "surround" &&
|
||||
(classes = classes.concat(["uv-border", "uv-input--radius"]));
|
||||
classes.push(`uv-input--${shape}`);
|
||||
border === "bottom" &&
|
||||
(classes = classes.concat([
|
||||
"uv-border-bottom",
|
||||
"uv-input--no-radius",
|
||||
]));
|
||||
return classes.join(" ");
|
||||
},
|
||||
// 组件的样式
|
||||
wrapperStyle() {
|
||||
const style = {};
|
||||
// 禁用状态下,被背景色加上对应的样式
|
||||
if (this.disabled) {
|
||||
style.backgroundColor = this.disabledColor;
|
||||
}
|
||||
// 无边框时,去除内边距
|
||||
if (this.border === "none") {
|
||||
style.padding = "0";
|
||||
} else {
|
||||
// 由于uni-app的iOS开发者能力有限,导致需要分开写才有效
|
||||
style.paddingTop = "6px";
|
||||
style.paddingBottom = "6px";
|
||||
style.paddingLeft = "9px";
|
||||
style.paddingRight = "9px";
|
||||
}
|
||||
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle));
|
||||
},
|
||||
// 输入框的样式
|
||||
inputStyle() {
|
||||
const style = {
|
||||
color: this.color,
|
||||
fontSize: this.$uv.addUnit(this.fontSize),
|
||||
textAlign: this.inputAlign
|
||||
};
|
||||
// #ifndef APP-NVUE
|
||||
if(this.disabled || this.readonly) {
|
||||
style['pointer-events'] = 'none';
|
||||
}
|
||||
// #endif
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用
|
||||
setFormatter(e) {
|
||||
this.innerFormatter = e
|
||||
},
|
||||
// 当键盘输入时,触发input事件
|
||||
onInput(e) {
|
||||
let { value = "" } = e.detail || {};
|
||||
// 格式化过滤方法
|
||||
const formatter = this.formatter || this.innerFormatter
|
||||
const formatValue = formatter(value)
|
||||
// 为了避免props的单向数据流特性,需要先将innerValue值设置为当前值,再在$nextTick中重新赋予设置后的值才有效
|
||||
this.innerValue = value
|
||||
this.$nextTick(() => {
|
||||
this.innerValue = formatValue;
|
||||
this.valueChange();
|
||||
})
|
||||
},
|
||||
// 输入框失去焦点时触发
|
||||
onBlur(event) {
|
||||
this.$emit("blur", event.detail.value);
|
||||
// H5端的blur会先于点击清除控件的点击click事件触发,导致focused
|
||||
// 瞬间为false,从而隐藏了清除控件而无法被点击到
|
||||
this.$uv.sleep(100).then(() => {
|
||||
this.focused = false;
|
||||
});
|
||||
// 尝试调用uv-form的验证方法
|
||||
this.$uv.formValidate(this, "blur");
|
||||
},
|
||||
// 输入框聚焦时触发
|
||||
onFocus(event) {
|
||||
this.focused = true;
|
||||
this.$emit("focus");
|
||||
},
|
||||
// 点击完成按钮时触发
|
||||
onConfirm(event) {
|
||||
this.$emit("confirm", this.innerValue);
|
||||
},
|
||||
// 键盘高度发生变化的时候触发此事件
|
||||
// 兼容性:微信小程序2.7.0+、App 3.1.0+
|
||||
onkeyboardheightchange(e) {
|
||||
this.$emit("keyboardheightchange",e);
|
||||
},
|
||||
// 内容发生变化,进行处理
|
||||
valueChange() {
|
||||
if(this.isClear) this.innerValue = '';
|
||||
const value = this.innerValue;
|
||||
this.$nextTick(() => {
|
||||
this.$emit("input", value);
|
||||
this.$emit("update:modelValue", value);
|
||||
this.$emit("change", value);
|
||||
// 尝试调用uv-form的验证方法
|
||||
this.$uv.formValidate(this, "change");
|
||||
});
|
||||
},
|
||||
// 点击清除控件
|
||||
onClear() {
|
||||
this.innerValue = "";
|
||||
this.isClear = true;
|
||||
this.$uv.sleep(200).then(res=>{
|
||||
this.isClear = false;
|
||||
})
|
||||
this.$nextTick(() => {
|
||||
this.$emit("clear");
|
||||
this.valueChange();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 在安卓nvue上,事件无法冒泡
|
||||
* 在某些时间,我们希望监听uv-from-item的点击事件,此时会导致点击uv-form-item内的uv-input后
|
||||
* 无法触发uv-form-item的点击事件,这里通过手动调用uv-form-item的方法进行触发
|
||||
*/
|
||||
clickHandler() {
|
||||
// #ifdef APP-NVUE
|
||||
if (this.$uv.os() === "android") {
|
||||
const formItem = this.$uv.$parent.call(this, "uv-form-item");
|
||||
if (formItem) {
|
||||
formItem.clickHandler();
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-border: 1;
|
||||
$show-border-surround: 1;
|
||||
$show-border-bottom: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
.uv-input {
|
||||
@include flex(row);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
&--radius,
|
||||
&--square {
|
||||
border-radius: 4px;
|
||||
}
|
||||
&--no-radius {
|
||||
border-radius: 0;
|
||||
}
|
||||
&--circle {
|
||||
border-radius: 100px;
|
||||
}
|
||||
&__content {
|
||||
flex: 1;
|
||||
@include flex(row);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
&__field-wrapper {
|
||||
position: relative;
|
||||
@include flex(row);
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
&__field {
|
||||
line-height: 26px;
|
||||
text-align: left;
|
||||
color: $uv-main-color;
|
||||
height: 24px;
|
||||
font-size: 15px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
&__clear {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 100px;
|
||||
background-color: #c6c7cb;
|
||||
@include flex(row);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transform: scale(0.82);
|
||||
margin-left: 15px;
|
||||
}
|
||||
&__subfix-icon {
|
||||
margin-left: 4px;
|
||||
}
|
||||
&__prefix-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
88
uni_modules/uv-input/package.json
Normal file
88
uni_modules/uv-input/package.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"id": "uv-input",
|
||||
"displayName": "uv-input 输入框 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.13",
|
||||
"description": "uv-input 该组件为一个输入框,默认没有边框和样式,是专门为配合表单组件uv-form而设计的,利用它可以快速实现表单验证,输入内容,下拉选择等功能。",
|
||||
"keywords": [
|
||||
"uv-input",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"input",
|
||||
"输入框"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-icon"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
uni_modules/uv-input/readme.md
Normal file
19
uni_modules/uv-input/readme.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## Input 输入框
|
||||
|
||||
> **组件名:uv-input**
|
||||
|
||||
此组件为一个输入框,默认没有边框和样式,是专门为配合表单组件uv-form而设计的,利用它可以快速实现表单验证,输入内容,下拉选择等功能。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/input.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
9
uni_modules/uv-loading-icon/changelog.md
Normal file
9
uni_modules/uv-loading-icon/changelog.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 1.0.3(2023-08-14)
|
||||
1. 新增参数textStyle,自定义文本样式
|
||||
## 1.0.2(2023-06-27)
|
||||
优化
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
1. 新增uv-loading-icon组件
|
||||
@@ -0,0 +1,67 @@
|
||||
export default {
|
||||
props: {
|
||||
// 是否显示组件
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 颜色
|
||||
color: {
|
||||
type: String,
|
||||
default: '#909193'
|
||||
},
|
||||
// 提示文字颜色
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#909193'
|
||||
},
|
||||
// 文字和图标是否垂直排列
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 模式选择,circle-圆形,spinner-花朵形,semicircle-半圆形
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'spinner'
|
||||
},
|
||||
// 图标大小,单位默认px
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: 24
|
||||
},
|
||||
// 文字大小
|
||||
textSize: {
|
||||
type: [String, Number],
|
||||
default: 15
|
||||
},
|
||||
// 文字样式
|
||||
textStyle: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
// 文字内容
|
||||
text: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 动画模式 https://www.runoob.com/cssref/css3-pr-animation-timing-function.html
|
||||
timingFunction: {
|
||||
type: String,
|
||||
default: 'linear'
|
||||
},
|
||||
// 动画执行周期时间
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 1200
|
||||
},
|
||||
// mode=circle时的暗边颜色
|
||||
inactiveColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
...uni.$uv?.props?.loadingIcon
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-loading-icon"
|
||||
:style="[$uv.addStyle(customStyle)]"
|
||||
:class="[vertical && 'uv-loading-icon--vertical']"
|
||||
v-if="show"
|
||||
>
|
||||
<view
|
||||
v-if="!webviewHide"
|
||||
class="uv-loading-icon__spinner"
|
||||
:class="[`uv-loading-icon__spinner--${mode}`]"
|
||||
ref="ani"
|
||||
:style="{
|
||||
color: color,
|
||||
width: $uv.addUnit(size),
|
||||
height: $uv.addUnit(size),
|
||||
borderTopColor: color,
|
||||
borderBottomColor: otherBorderColor,
|
||||
borderLeftColor: otherBorderColor,
|
||||
borderRightColor: otherBorderColor,
|
||||
'animation-duration': `${duration}ms`,
|
||||
'animation-timing-function': mode === 'semicircle' || mode === 'circle' ? timingFunction : ''
|
||||
}"
|
||||
>
|
||||
<block v-if="mode === 'spinner'">
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view
|
||||
v-for="(item, index) in array12"
|
||||
:key="index"
|
||||
class="uv-loading-icon__dot"
|
||||
>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<!-- 此组件内部图标部分无法设置宽高,即使通过width和height配置了也无效 -->
|
||||
<loading-indicator
|
||||
v-if="!webviewHide"
|
||||
class="uv-loading-indicator"
|
||||
:animating="true"
|
||||
:style="{
|
||||
color: color,
|
||||
width: $uv.addUnit(size),
|
||||
height: $uv.addUnit(size)
|
||||
}"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</block>
|
||||
</view>
|
||||
<text
|
||||
v-if="text"
|
||||
class="uv-loading-icon__text"
|
||||
:style="[{
|
||||
fontSize: $uv.addUnit(textSize),
|
||||
color: textColor,
|
||||
},$uv.addStyle(textStyle)]"
|
||||
>{{text}}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { colorGradient } from '@/uni_modules/uv-ui-tools/libs/function/colorGradient.js'
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
// #ifdef APP-NVUE
|
||||
const animation = weex.requireModule('animation');
|
||||
// #endif
|
||||
/**
|
||||
* loading 加载动画
|
||||
* @description 警此组件为一个小动画,目前用在uvui的loadmore加载更多和switch开关等组件的正在加载状态场景。
|
||||
* @tutorial https://www.uvui.cn/components/loading.html
|
||||
* @property {Boolean} show 是否显示组件 (默认 true)
|
||||
* @property {String} color 动画活动区域的颜色,只对 mode = flower 模式有效(默认#909193)
|
||||
* @property {String} textColor 提示文本的颜色(默认#909193)
|
||||
* @property {Boolean} vertical 文字和图标是否垂直排列 (默认 false )
|
||||
* @property {String} mode 模式选择,见官网说明(默认 'circle' )
|
||||
* @property {String | Number} size 加载图标的大小,单位px (默认 24 )
|
||||
* @property {String | Number} textSize 文字大小(默认 15 )
|
||||
* @property {String | Number} text 文字内容
|
||||
* @property {Object} textStyle 文字样式
|
||||
* @property {String} timingFunction 动画模式 (默认 'ease-in-out' )
|
||||
* @property {String | Number} duration 动画执行周期时间(默认 1200)
|
||||
* @property {String} inactiveColor mode=circle时的暗边颜色
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
* @example <uv-loading mode="circle"></uv-loading>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-loading-icon',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
// Array.form可以通过一个伪数组对象创建指定长度的数组
|
||||
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/from
|
||||
array12: Array.from({
|
||||
length: 12
|
||||
}),
|
||||
// 这里需要设置默认值为360,否则在安卓nvue上,会延迟一个duration周期后才执行
|
||||
// 在iOS nvue上,则会一开始默认执行两个周期的动画
|
||||
aniAngel: 360, // 动画旋转角度
|
||||
webviewHide: false, // 监听webview的状态,如果隐藏了页面,则停止动画,以免性能消耗
|
||||
loading: false, // 是否运行中,针对nvue使用
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 当为circle类型时,给其另外三边设置一个更轻一些的颜色
|
||||
// 之所以需要这么做的原因是,比如父组件传了color为红色,那么需要另外的三个边为浅红色
|
||||
// 而不能是固定的某一个其他颜色(因为这个固定的颜色可能浅蓝,导致效果没有那么细腻良好)
|
||||
otherBorderColor() {
|
||||
const lightColor = colorGradient(this.color, '#ffffff', 100)[80]
|
||||
if (this.mode === 'circle') {
|
||||
return this.inactiveColor ? this.inactiveColor : lightColor
|
||||
} else {
|
||||
return 'transparent'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(n) {
|
||||
// nvue中,show为true,且为非loading状态,就重新执行动画模块
|
||||
// #ifdef APP-NVUE
|
||||
if (n && !this.loading) {
|
||||
setTimeout(() => {
|
||||
this.startAnimate()
|
||||
}, 30)
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
setTimeout(() => {
|
||||
// #ifdef APP-NVUE
|
||||
this.show && this.nvueAnimate()
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
this.show && this.addEventListenerToWebview()
|
||||
// #endif
|
||||
}, 20)
|
||||
},
|
||||
// 监听webview的显示与隐藏
|
||||
addEventListenerToWebview() {
|
||||
// webview的堆栈
|
||||
const pages = getCurrentPages()
|
||||
// 当前页面
|
||||
const page = pages[pages.length - 1]
|
||||
// 当前页面的webview实例
|
||||
const currentWebview = page.$getAppWebview()
|
||||
// 监听webview的显示与隐藏,从而停止或者开始动画(为了性能)
|
||||
currentWebview.addEventListener('hide', () => {
|
||||
this.webviewHide = true
|
||||
})
|
||||
currentWebview.addEventListener('show', () => {
|
||||
this.webviewHide = false
|
||||
})
|
||||
},
|
||||
// #ifdef APP-NVUE
|
||||
nvueAnimate() {
|
||||
// nvue下,非spinner类型时才需要旋转,因为nvue的spinner类型,使用了weex的
|
||||
// loading-indicator组件,自带旋转功能
|
||||
this.mode !== 'spinner' && this.startAnimate()
|
||||
},
|
||||
// 执行nvue的animate模块动画
|
||||
startAnimate() {
|
||||
this.loading = true
|
||||
const ani = this.$refs.ani
|
||||
if (!ani) return
|
||||
animation.transition(ani, {
|
||||
// 进行角度旋转
|
||||
styles: {
|
||||
transform: `rotate(${this.aniAngel}deg)`,
|
||||
transformOrigin: 'center center'
|
||||
},
|
||||
duration: this.duration,
|
||||
timingFunction: this.timingFunction,
|
||||
// delay: 10
|
||||
}, () => {
|
||||
// 每次增加360deg,为了让其重新旋转一周
|
||||
this.aniAngel += 360
|
||||
// 动画结束后,继续循环执行动画,需要同时判断webviewHide变量
|
||||
// nvue安卓,页面隐藏后依然会继续执行startAnimate方法
|
||||
this.show && !this.webviewHide ? this.startAnimate() : this.loading = false
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
$uv-loading-icon-color: #c8c9cc !default;
|
||||
$uv-loading-icon-text-margin-left:4px !default;
|
||||
$uv-loading-icon-text-color:$uv-content-color !default;
|
||||
$uv-loading-icon-text-font-size:14px !default;
|
||||
$uv-loading-icon-text-line-height:20px !default;
|
||||
$uv-loading-width:30px !default;
|
||||
$uv-loading-height:30px !default;
|
||||
$uv-loading-max-width:100% !default;
|
||||
$uv-loading-max-height:100% !default;
|
||||
$uv-loading-semicircle-border-width: 2px !default;
|
||||
$uv-loading-semicircle-border-color:transparent !default;
|
||||
$uv-loading-semicircle-border-top-right-radius: 100px !default;
|
||||
$uv-loading-semicircle-border-top-left-radius: 100px !default;
|
||||
$uv-loading-semicircle-border-bottom-left-radius: 100px !default;
|
||||
$uv-loading-semicircle-border-bottom-right-radiu: 100px !default;
|
||||
$uv-loading-semicircle-border-style: solid !default;
|
||||
$uv-loading-circle-border-top-right-radius: 100px !default;
|
||||
$uv-loading-circle-border-top-left-radius: 100px !default;
|
||||
$uv-loading-circle-border-bottom-left-radius: 100px !default;
|
||||
$uv-loading-circle-border-bottom-right-radiu: 100px !default;
|
||||
$uv-loading-circle-border-width:2px !default;
|
||||
$uv-loading-circle-border-top-color:#e5e5e5 !default;
|
||||
$uv-loading-circle-border-right-color:$uv-loading-circle-border-top-color !default;
|
||||
$uv-loading-circle-border-bottom-color:$uv-loading-circle-border-top-color !default;
|
||||
$uv-loading-circle-border-left-color:$uv-loading-circle-border-top-color !default;
|
||||
$uv-loading-circle-border-style:solid !default;
|
||||
$uv-loading-icon-host-font-size:0px !default;
|
||||
$uv-loading-icon-host-line-height:1 !default;
|
||||
$uv-loading-icon-vertical-margin:6px 0 0 !default;
|
||||
$uv-loading-icon-dot-top:0 !default;
|
||||
$uv-loading-icon-dot-left:0 !default;
|
||||
$uv-loading-icon-dot-width:100% !default;
|
||||
$uv-loading-icon-dot-height:100% !default;
|
||||
$uv-loading-icon-dot-before-width:2px !default;
|
||||
$uv-loading-icon-dot-before-height:25% !default;
|
||||
$uv-loading-icon-dot-before-margin:0 auto !default;
|
||||
$uv-loading-icon-dot-before-background-color:currentColor !default;
|
||||
$uv-loading-icon-dot-before-border-radius:40% !default;
|
||||
|
||||
.uv-loading-icon {
|
||||
/* #ifndef APP-NVUE */
|
||||
// display: inline-flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: $uv-loading-icon-color;
|
||||
|
||||
&__text {
|
||||
margin-left: $uv-loading-icon-text-margin-left;
|
||||
color: $uv-loading-icon-text-color;
|
||||
font-size: $uv-loading-icon-text-font-size;
|
||||
line-height: $uv-loading-icon-text-line-height;
|
||||
}
|
||||
|
||||
&__spinner {
|
||||
width: $uv-loading-width;
|
||||
height: $uv-loading-height;
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
max-width: $uv-loading-max-width;
|
||||
max-height: $uv-loading-max-height;
|
||||
animation: uv-rotate 1s linear infinite;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
&__spinner--semicircle {
|
||||
border-width: $uv-loading-semicircle-border-width;
|
||||
border-color: $uv-loading-semicircle-border-color;
|
||||
border-top-right-radius: $uv-loading-semicircle-border-top-right-radius;
|
||||
border-top-left-radius: $uv-loading-semicircle-border-top-left-radius;
|
||||
border-bottom-left-radius: $uv-loading-semicircle-border-bottom-left-radius;
|
||||
border-bottom-right-radius: $uv-loading-semicircle-border-bottom-right-radiu;
|
||||
border-style: $uv-loading-semicircle-border-style;
|
||||
}
|
||||
|
||||
&__spinner--circle {
|
||||
border-top-right-radius: $uv-loading-circle-border-top-right-radius;
|
||||
border-top-left-radius: $uv-loading-circle-border-top-left-radius;
|
||||
border-bottom-left-radius: $uv-loading-circle-border-bottom-left-radius;
|
||||
border-bottom-right-radius: $uv-loading-circle-border-bottom-right-radiu;
|
||||
border-width: $uv-loading-circle-border-width;
|
||||
border-top-color: $uv-loading-circle-border-top-color;
|
||||
border-right-color: $uv-loading-circle-border-right-color;
|
||||
border-bottom-color: $uv-loading-circle-border-bottom-color;
|
||||
border-left-color: $uv-loading-circle-border-left-color;
|
||||
border-style: $uv-loading-circle-border-style;
|
||||
}
|
||||
|
||||
&--vertical {
|
||||
flex-direction: column
|
||||
}
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
:host {
|
||||
font-size: $uv-loading-icon-host-font-size;
|
||||
line-height: $uv-loading-icon-host-line-height;
|
||||
}
|
||||
|
||||
.uv-loading-icon {
|
||||
&__spinner--spinner {
|
||||
animation-timing-function: steps(12)
|
||||
}
|
||||
|
||||
&__text:empty {
|
||||
display: none
|
||||
}
|
||||
|
||||
&--vertical &__text {
|
||||
margin: $uv-loading-icon-vertical-margin;
|
||||
color: $uv-content-color;
|
||||
}
|
||||
|
||||
&__dot {
|
||||
position: absolute;
|
||||
top: $uv-loading-icon-dot-top;
|
||||
left: $uv-loading-icon-dot-left;
|
||||
width: $uv-loading-icon-dot-width;
|
||||
height: $uv-loading-icon-dot-height;
|
||||
|
||||
&:before {
|
||||
display: block;
|
||||
width: $uv-loading-icon-dot-before-width;
|
||||
height: $uv-loading-icon-dot-before-height;
|
||||
margin: $uv-loading-icon-dot-before-margin;
|
||||
background-color: $uv-loading-icon-dot-before-background-color;
|
||||
border-radius: $uv-loading-icon-dot-before-border-radius;
|
||||
content: " "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
.uv-loading-icon__dot:nth-of-type(#{$i}) {
|
||||
transform: rotate($i * 30deg);
|
||||
opacity: 1 - 0.0625 * ($i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes uv-rotate {
|
||||
0% {
|
||||
transform: rotate(0deg)
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(1turn)
|
||||
}
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
||||
87
uni_modules/uv-loading-icon/package.json
Normal file
87
uni_modules/uv-loading-icon/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"id": "uv-loading-icon",
|
||||
"displayName": "uv-loading-icon 加载动画 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.3",
|
||||
"description": "此组件为一个小动画,目前用在uv-ui的uv-load-more加载更多等组件,还可以运用在项目中正在加载状态场景。",
|
||||
"keywords": [
|
||||
"uv-loading-icon",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"loading",
|
||||
"加载动画"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
uni_modules/uv-loading-icon/readme.md
Normal file
19
uni_modules/uv-loading-icon/readme.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## LoadingIcon 加载动画
|
||||
|
||||
> **组件名:uv-loading-icon**
|
||||
|
||||
此组件为一个小动画,目前用在 `uv-ui` 的 `uv-load-more` 加载更多等组件,还可以运用在项目中正在加载状态场景。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/loadingIcon.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
9
uni_modules/uv-overlay/changelog.md
Normal file
9
uni_modules/uv-overlay/changelog.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 1.0.3(2023-07-02)
|
||||
uv-overlay 由于弹出层uv-transition的修改,组件内部做了相应的修改,参数不变。
|
||||
## 1.0.2(2023-06-29)
|
||||
1. 优化,H5端禁止穿透滚动
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
1. 新增uv-overlay组件
|
||||
25
uni_modules/uv-overlay/components/uv-overlay/props.js
Normal file
25
uni_modules/uv-overlay/components/uv-overlay/props.js
Normal file
@@ -0,0 +1,25 @@
|
||||
export default {
|
||||
props: {
|
||||
// 是否显示遮罩
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 层级z-index
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 10070
|
||||
},
|
||||
// 遮罩的过渡时间,单位为ms
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 300
|
||||
},
|
||||
// 不透明度值,当做rgba的第四个参数
|
||||
opacity: {
|
||||
type: [String, Number],
|
||||
default: 0.5
|
||||
},
|
||||
...uni.$uv?.props?.overlay
|
||||
}
|
||||
}
|
||||
85
uni_modules/uv-overlay/components/uv-overlay/uv-overlay.vue
Normal file
85
uni_modules/uv-overlay/components/uv-overlay/uv-overlay.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<uv-transition
|
||||
:show="show"
|
||||
mode="fade"
|
||||
custom-class="uv-overlay"
|
||||
:duration="duration"
|
||||
:custom-style="overlayStyle"
|
||||
@click="clickHandler"
|
||||
@touchmove.stop.prevent="clear"
|
||||
>
|
||||
<slot />
|
||||
</uv-transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
|
||||
/**
|
||||
* overlay 遮罩
|
||||
* @description 创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景
|
||||
* @tutorial https://www.uvui.cn/components/overlay.html
|
||||
* @property {Boolean} show 是否显示遮罩(默认 false )
|
||||
* @property {String | Number} zIndex zIndex 层级(默认 10070 )
|
||||
* @property {String | Number} duration 动画时长,单位毫秒(默认 300 )
|
||||
* @property {String | Number} opacity 不透明度值,当做rgba的第四个参数 (默认 0.5 )
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
* @event {Function} click 点击遮罩发送事件
|
||||
* @example <uv-overlay :show="show" @click="show = false"></uv-overlay>
|
||||
*/
|
||||
export default {
|
||||
name: "uv-overlay",
|
||||
emits: ['click'],
|
||||
mixins: [mpMixin, mixin, props],
|
||||
watch: {
|
||||
show(newVal){
|
||||
// #ifdef H5
|
||||
if(newVal){
|
||||
document.querySelector('body').style.overflow = 'hidden';
|
||||
}else{
|
||||
document.querySelector('body').style.overflow = '';
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
overlayStyle() {
|
||||
const style = {
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
zIndex: this.zIndex,
|
||||
bottom: 0,
|
||||
'background-color': `rgba(0, 0, 0, ${this.opacity})`
|
||||
}
|
||||
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickHandler() {
|
||||
this.$emit('click')
|
||||
},
|
||||
clear() {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
$uv-overlay-top:0 !default;
|
||||
$uv-overlay-left:0 !default;
|
||||
$uv-overlay-width:100% !default;
|
||||
$uv-overlay-height:100% !default;
|
||||
$uv-overlay-background-color:rgba(0, 0, 0, .7) !default;
|
||||
.uv-overlay {
|
||||
position: fixed;
|
||||
top:$uv-overlay-top;
|
||||
left:$uv-overlay-left;
|
||||
width: $uv-overlay-width;
|
||||
height:$uv-overlay-height;
|
||||
background-color:$uv-overlay-background-color;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
88
uni_modules/uv-overlay/package.json
Normal file
88
uni_modules/uv-overlay/package.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"id": "uv-overlay",
|
||||
"displayName": "uv-overlay 遮罩层 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.3",
|
||||
"description": "uv-overlay 创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景,uv-popup、uv-toast、uv-tooltip等组件就是用了该组件。",
|
||||
"keywords": [
|
||||
"uv-overlay",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"overlay",
|
||||
"遮罩层"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-transition"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
uni_modules/uv-overlay/readme.md
Normal file
11
uni_modules/uv-overlay/readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## Overlay 遮罩层
|
||||
|
||||
> **组件名:uv-overlay**
|
||||
|
||||
创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景,uv-popup、uv-toast、uv-tooltip等组件就是用了该组件。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/overlay.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
33
uni_modules/uv-picker/changelog.md
Normal file
33
uni_modules/uv-picker/changelog.md
Normal file
@@ -0,0 +1,33 @@
|
||||
## 1.0.14(2023-12-29)
|
||||
1. 修复上个版本引出的BUG
|
||||
## 1.0.13(2023-12-26)
|
||||
1. 修复抖音小程序滚到底不触发change的BUG
|
||||
## 1.0.12(2023-11-20)
|
||||
1. 修复issues反馈的问题uv-picker在组合式API的自定义组件中,columns动态赋值无法显示选项:https://gitee.com/climblee/uv-ui/issues/I8H0GQ
|
||||
## 1.0.11(2023-10-11)
|
||||
1. 将immediate-change默认值改为true,该值在于change回调的及时性,微信小程序生效
|
||||
## 1.0.10(2023-08-25)
|
||||
1. 增加round属性设置弹窗圆角,默认为0
|
||||
## 1.0.9(2023-08-24)
|
||||
1. 修复cli项目不返回值的问题
|
||||
## 1.0.8(2023-08-04)
|
||||
1. 优化
|
||||
## 1.0.7(2023-08-02)
|
||||
1. 改组件中删除uv-toolbar组件,请单独下载uv-toolbar组件
|
||||
## 1.0.6(2023-07-02)
|
||||
uv-picker 由于弹出层uv-popup的修改,打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/picker.html
|
||||
## 1.0.5(2023-06-26)
|
||||
1. 增加color参数
|
||||
2. 增加activeColor参数
|
||||
## 1.0.4(2023-06-15)
|
||||
1. 修改支付宝报错的BUG
|
||||
## 1.0.3(2023-06-12)
|
||||
1. setColumnValues的使用统一化,避免某些平台报错
|
||||
2. 取消change回调回传的组件实例,直接统一通过ref的方式调取setColumnValues方法
|
||||
## 1.0.2(2023-05-23)
|
||||
1. uv-toolbar组件新增下边框属性
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-picker 选择器
|
||||
95
uni_modules/uv-picker/components/uv-picker/props.js
Normal file
95
uni_modules/uv-picker/components/uv-picker/props.js
Normal file
@@ -0,0 +1,95 @@
|
||||
export default {
|
||||
props: {
|
||||
// 是否展示顶部的操作栏
|
||||
showToolbar: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 顶部标题
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 弹窗圆角
|
||||
round: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 对象数组,设置每一列的数据
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 是否显示加载中状态
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 各列中,单个选项的高度
|
||||
itemHeight: {
|
||||
type: [String, Number],
|
||||
default: 44
|
||||
},
|
||||
// 取消按钮的文字
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
// 确认按钮的文字
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确定'
|
||||
},
|
||||
// 取消按钮的颜色
|
||||
cancelColor: {
|
||||
type: String,
|
||||
default: '#909193'
|
||||
},
|
||||
// 确认按钮的颜色
|
||||
confirmColor: {
|
||||
type: String,
|
||||
default: '#3c9cff'
|
||||
},
|
||||
// 文字颜色
|
||||
color: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 选中文字的颜色
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 每列中可见选项的数量
|
||||
visibleItemCount: {
|
||||
type: [String, Number],
|
||||
default: 5
|
||||
},
|
||||
// 选项对象中,需要展示的属性键名
|
||||
keyName: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
// 是否允许点击遮罩关闭选择器
|
||||
closeOnClickOverlay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否允许点击确认关闭选择器
|
||||
closeOnClickConfirm: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 各列的默认索引
|
||||
defaultIndex: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
// 是否在手指松开时立即触发 change 事件。若不开启则会在滚动动画结束后触发 change 事件,只在微信2.21.1及以上有效
|
||||
immediateChange: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
...uni.$uv?.props?.picker
|
||||
}
|
||||
}
|
||||
330
uni_modules/uv-picker/components/uv-picker/uv-picker.vue
Normal file
330
uni_modules/uv-picker/components/uv-picker/uv-picker.vue
Normal file
@@ -0,0 +1,330 @@
|
||||
<template>
|
||||
<uv-popup
|
||||
ref="pickerPopup"
|
||||
mode="bottom"
|
||||
:round="round"
|
||||
:close-on-click-overlay="closeOnClickOverlay"
|
||||
@change="popupChange"
|
||||
>
|
||||
<view class="uv-picker">
|
||||
<uv-toolbar
|
||||
v-if="showToolbar"
|
||||
:cancelColor="cancelColor"
|
||||
:confirmColor="confirmColor"
|
||||
:cancelText="cancelText"
|
||||
:confirmText="confirmText"
|
||||
:title="title"
|
||||
@cancel="cancel"
|
||||
@confirm="confirm"
|
||||
></uv-toolbar>
|
||||
<!-- #ifdef MP-TOUTIAO -->
|
||||
<picker-view
|
||||
class="uv-picker__view"
|
||||
:indicatorStyle="`height: ${$uv.addUnit(itemHeight)}`"
|
||||
:value="innerIndex"
|
||||
:immediateChange="immediateChange"
|
||||
:style="{
|
||||
height: `${$uv.addUnit(visibleItemCount * itemHeight)}`
|
||||
}"
|
||||
@pickend="changeHandler"
|
||||
>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<picker-view
|
||||
class="uv-picker__view"
|
||||
:indicatorStyle="`height: ${$uv.addUnit(itemHeight)}`"
|
||||
:value="innerIndex"
|
||||
:immediateChange="immediateChange"
|
||||
:style="{
|
||||
height: `${$uv.addUnit(visibleItemCount * itemHeight)}`
|
||||
}"
|
||||
@change="changeHandler"
|
||||
>
|
||||
<!-- #endif -->
|
||||
<!-- @pickend在这里为了解决抖音等滚到底不触发change兼容性问题 -->
|
||||
<picker-view-column
|
||||
v-for="(item, index) in innerColumns"
|
||||
:key="index"
|
||||
class="uv-picker__view__column"
|
||||
>
|
||||
<text
|
||||
v-if="$uv.test.array(item)"
|
||||
class="uv-picker__view__column__item uv-line-1"
|
||||
v-for="(item1, index1) in item"
|
||||
:key="index1"
|
||||
:style="[{
|
||||
height: $uv.addUnit(itemHeight),
|
||||
lineHeight: $uv.addUnit(itemHeight),
|
||||
fontWeight: index1 === innerIndex[index] ? 'bold' : 'normal'
|
||||
},textStyle(index,index1)]"
|
||||
>{{ getItemText(item1) }}</text>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
<view
|
||||
v-if="loading"
|
||||
class="uv-picker--loading"
|
||||
>
|
||||
<uv-loading-icon mode="circle"></uv-loading-icon>
|
||||
</view>
|
||||
</view>
|
||||
</uv-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* uv-picker
|
||||
* @description 选择器
|
||||
* @property {Boolean} showToolbar 是否显示顶部的操作栏(默认 true )
|
||||
* @property {String} title 顶部标题
|
||||
* @property {Array} columns 对象数组,设置每一列的数据
|
||||
* @property {Boolean} loading 是否显示加载中状态(默认 false )
|
||||
* @property {String | Number} itemHeight 各列中,单个选项的高度(默认 44 )
|
||||
* @property {String} cancelText 取消按钮的文字(默认 '取消' )
|
||||
* @property {String} confirmText 确认按钮的文字(默认 '确定' )
|
||||
* @property {String} cancelColor 取消按钮的颜色(默认 '#909193' )
|
||||
* @property {String} confirmColor 确认按钮的颜色(默认 '#3c9cff' )
|
||||
* @property {String} color 文字颜色(默认 '' )
|
||||
* @property {String} activeColor 选中文字的颜色(默认 '' )
|
||||
* @property {String | Number} visibleItemCount 每列中可见选项的数量(默认 5 )
|
||||
* @property {String} keyName 选项对象中,需要展示的属性键名(默认 'text' )
|
||||
* @property {Boolean} closeOnClickOverlay 是否允许点击遮罩关闭选择器(默认 false )
|
||||
* @property {Array} defaultIndex 各列的默认索引
|
||||
* @property {Boolean} immediateChange 是否在手指松开时立即触发change事件(默认 false )
|
||||
* @event {Function} close 关闭选择器时触发
|
||||
* @event {Function} cancel 点击取消按钮触发
|
||||
* @event {Function} change 当选择值变化时触发
|
||||
* @event {Function} confirm 点击确定按钮,返回当前选择的值
|
||||
*/
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
export default {
|
||||
name: 'uv-picker',
|
||||
emits: ['confirm','cancel','close','change'],
|
||||
mixins: [mpMixin, mixin, props],
|
||||
computed: {
|
||||
// 为了解决支付宝不生效
|
||||
textStyle(){
|
||||
return (index,index1) => {
|
||||
const style = {};
|
||||
// #ifndef APP-NVUE
|
||||
style.display = 'block';
|
||||
// #endif
|
||||
if(this.color) {
|
||||
style.color = this.color;
|
||||
}
|
||||
if(this.activeColor && index1 === this.innerIndex[index]) {
|
||||
style.color = this.activeColor;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 上一次选择的列索引
|
||||
lastIndex: [],
|
||||
// 索引值 ,对应picker-view的value
|
||||
innerIndex: [],
|
||||
// 各列的值
|
||||
innerColumns: [],
|
||||
// 上一次的变化列索引
|
||||
columnIndex: 0,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听默认索引的变化,重新设置对应的值
|
||||
defaultIndex: {
|
||||
immediate: true,
|
||||
handler(n) {
|
||||
this.setIndexs(n, true)
|
||||
}
|
||||
},
|
||||
// 监听columns参数的变化
|
||||
columns: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(n) {
|
||||
this.setColumns(n)
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.pickerPopup.open();
|
||||
},
|
||||
close() {
|
||||
this.$refs.pickerPopup.close();
|
||||
},
|
||||
popupChange(e) {
|
||||
if(!e.show) this.$emit('close');
|
||||
},
|
||||
// 获取item需要显示的文字,判别为对象还是文本
|
||||
getItemText(item) {
|
||||
if (this.$uv.test.object(item)) {
|
||||
return item[this.keyName]
|
||||
} else {
|
||||
return item
|
||||
}
|
||||
},
|
||||
// 点击工具栏的取消按钮
|
||||
cancel() {
|
||||
this.$emit('cancel');
|
||||
this.close();
|
||||
},
|
||||
// 点击工具栏的确定按钮
|
||||
confirm() {
|
||||
// 在这里使用deepClone拷贝后,vue3会自动转换成原始对象,这样处理是因为cli项目可能出现不返回值的情况
|
||||
this.$emit('confirm', this.$uv.deepClone({
|
||||
indexs: this.innerIndex,
|
||||
value: this.innerColumns.map((item, index) => item[this.innerIndex[index]]),
|
||||
values: this.innerColumns
|
||||
}));
|
||||
if(this.closeOnClickConfirm) {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
// 选择器某一列的数据发生变化时触发
|
||||
changeHandler(e) {
|
||||
const {
|
||||
value
|
||||
} = e.detail
|
||||
let index = 0,
|
||||
columnIndex = 0
|
||||
// 通过对比前后两次的列索引,得出当前变化的是哪一列
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
let item = value[i]
|
||||
if (item !== (this.lastIndex[i] || 0)) { // 把undefined转为合法假值0
|
||||
// 设置columnIndex为当前变化列的索引
|
||||
columnIndex = i
|
||||
// index则为变化列中的变化项的索引
|
||||
index = item
|
||||
break // 终止循环,即使少一次循环,也是性能的提升
|
||||
}
|
||||
}
|
||||
this.columnIndex = columnIndex
|
||||
const values = this.innerColumns
|
||||
// 将当前的各项变化索引,设置为"上一次"的索引变化值
|
||||
this.setLastIndex(value)
|
||||
this.setIndexs(value)
|
||||
|
||||
this.$emit('change', {
|
||||
value: this.innerColumns.map((item, index) => item[value[index]]),
|
||||
index,
|
||||
indexs: value,
|
||||
// values为当前变化列的数组内容
|
||||
values,
|
||||
columnIndex
|
||||
})
|
||||
},
|
||||
// 设置index索引,此方法可被外部调用设置
|
||||
setIndexs(index, setLastIndex) {
|
||||
this.innerIndex = this.$uv.deepClone(index)
|
||||
if (setLastIndex) {
|
||||
this.setLastIndex(index)
|
||||
}
|
||||
},
|
||||
// 记录上一次的各列索引位置
|
||||
setLastIndex(index) {
|
||||
// 当能进入此方法,意味着当前设置的各列默认索引,即为“上一次”的选中值,需要记录,是因为changeHandler中
|
||||
// 需要拿前后的变化值进行对比,得出当前发生改变的是哪一列
|
||||
this.lastIndex = this.$uv.deepClone(index)
|
||||
},
|
||||
// 设置对应列选项的所有值
|
||||
setColumnValues(columnIndex, values) {
|
||||
// 替换innerColumns数组中columnIndex索引的值为values,使用的是数组的splice方法
|
||||
this.innerColumns.splice(columnIndex, 1, values)
|
||||
// 拷贝一份原有的innerIndex做临时变量,将大于当前变化列的所有的列的默认索引设置为0
|
||||
let tmpIndex = this.$uv.deepClone(this.innerIndex)
|
||||
for (let i = 0; i < this.innerColumns.length; i++) {
|
||||
if (i > this.columnIndex) {
|
||||
tmpIndex[i] = 0
|
||||
}
|
||||
}
|
||||
// 一次性赋值,不能单个修改,否则无效
|
||||
this.setIndexs(tmpIndex)
|
||||
},
|
||||
// 获取对应列的所有选项
|
||||
getColumnValues(columnIndex) {
|
||||
// 进行同步阻塞,因为外部得到change事件之后,可能需要执行setColumnValues更新列的值
|
||||
// 索引如果在外部change的回调中调用getColumnValues的话,可能无法得到变更后的列值,这里进行一定延时,保证值的准确性
|
||||
(async () => {
|
||||
await this.$uv.sleep()
|
||||
})()
|
||||
return this.innerColumns[columnIndex]
|
||||
},
|
||||
// 设置整体各列的columns的值
|
||||
setColumns(columns) {
|
||||
this.innerColumns = this.$uv.deepClone(columns)
|
||||
// 如果在设置各列数据时,没有被设置默认的各列索引defaultIndex,那么用0去填充它,数组长度为列的数量
|
||||
if (this.innerIndex.length === 0) {
|
||||
this.innerIndex = new Array(columns.length).fill(0)
|
||||
}
|
||||
},
|
||||
// 获取各列选中值对应的索引
|
||||
getIndexs() {
|
||||
return this.innerIndex
|
||||
},
|
||||
// 获取各列选中的值
|
||||
getValues() {
|
||||
// 进行同步阻塞,因为外部得到change事件之后,可能需要执行setColumnValues更新列的值
|
||||
// 索引如果在外部change的回调中调用getValues的话,可能无法得到变更后的列值,这里进行一定延时,保证值的准确性
|
||||
(async () => {
|
||||
await this.$uv.sleep()
|
||||
})()
|
||||
return this.innerColumns.map((item, index) => item[this.innerIndex[index]])
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-lines: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
.uv-picker {
|
||||
position: relative;
|
||||
|
||||
&__view {
|
||||
|
||||
&__column {
|
||||
@include flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
|
||||
&__item {
|
||||
@include flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
color: $uv-main-color;
|
||||
|
||||
&--disabled {
|
||||
/* #ifndef APP-NVUE */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
opacity: 0.35;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
@include flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: rgba(255, 255, 255, 0.87);
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
90
uni_modules/uv-picker/package.json
Normal file
90
uni_modules/uv-picker/package.json
Normal file
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"id": "uv-picker",
|
||||
"displayName": "uv-picker 选择器 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.14",
|
||||
"description": "uv-picker 此选择器用于单列,多列,多列联动的选择场景...",
|
||||
"keywords": [
|
||||
"uv-picker",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"picker",
|
||||
"联动选择"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-popup",
|
||||
"uv-loading-icon",
|
||||
"uv-toolbar"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
uni_modules/uv-picker/readme.md
Normal file
21
uni_modules/uv-picker/readme.md
Normal file
@@ -0,0 +1,21 @@
|
||||
## Picker 选择器
|
||||
|
||||
> **组件名:uv-picker**
|
||||
|
||||
此选择器用于单列,多列,多列联动的选择场景。
|
||||
|
||||
`uv-datetime-picker`等组件也用到了该组件,功能完善,需要特别注意的是`columns`参数的形式是数组嵌套。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/picker.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
18
uni_modules/uv-popup/changelog.md
Normal file
18
uni_modules/uv-popup/changelog.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## 1.0.7(2023-11-20)
|
||||
修复issues问题:https://gitee.com/climblee/uv-ui/issues/I8HDLO
|
||||
## 1.0.6(2023-10-13)
|
||||
1. 优化vue,内容有背景色,设置圆角被遮挡的情况
|
||||
## 1.0.5(2023-09-10)
|
||||
1. 修复H5默认层级过高的问题
|
||||
2. 修复全局设置prop无效的问题
|
||||
## 1.0.4(2023-08-08)
|
||||
1. 修复修改zIndex不生效的BUG
|
||||
## 1.0.3(2023-07-02)
|
||||
uv-popup 弹出层,代码重构优化,性能翻倍,小程序体验性能更加,避免卡顿。打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/popup.html
|
||||
## 1.0.2(2023-06-11)
|
||||
1. 修复zIndex层级问题
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
1. 新增uv-popup组件
|
||||
45
uni_modules/uv-popup/components/uv-popup/keypress.js
Normal file
45
uni_modules/uv-popup/components/uv-popup/keypress.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// #ifdef H5
|
||||
export default {
|
||||
name: 'Keypress',
|
||||
props: {
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const keyNames = {
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
space: [' ', 'Spacebar'],
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
const listener = ($event) => {
|
||||
if (this.disable) {
|
||||
return
|
||||
}
|
||||
const keyName = Object.keys(keyNames).find(key => {
|
||||
const keyName = $event.key
|
||||
const value = keyNames[key]
|
||||
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||
})
|
||||
if (keyName) {
|
||||
// 避免和其他按键事件冲突
|
||||
setTimeout(() => {
|
||||
this.$emit(keyName, {})
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', listener)
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// document.removeEventListener('keyup', listener)
|
||||
// })
|
||||
},
|
||||
render: () => {}
|
||||
}
|
||||
// #endif
|
||||
539
uni_modules/uv-popup/components/uv-popup/uv-popup.vue
Normal file
539
uni_modules/uv-popup/components/uv-popup/uv-popup.vue
Normal file
@@ -0,0 +1,539 @@
|
||||
<template>
|
||||
<view
|
||||
v-if="showPopup"
|
||||
class="uv-popup"
|
||||
:class="[popupClass, isDesktop ? 'fixforpc-z-index' : '']"
|
||||
:style="[{zIndex: zIndex}]"
|
||||
>
|
||||
<view @touchstart="touchstart">
|
||||
<!-- 遮罩层 -->
|
||||
<uv-overlay
|
||||
key="1"
|
||||
v-if="maskShow && overlay"
|
||||
:show="showTrans"
|
||||
:duration="duration"
|
||||
:custom-style="overlayStyle"
|
||||
:opacity="overlayOpacity"
|
||||
:zIndex="zIndex"
|
||||
@click="onTap"
|
||||
></uv-overlay>
|
||||
<uv-transition
|
||||
key="2"
|
||||
:mode="ani"
|
||||
name="content"
|
||||
:custom-style="transitionStyle"
|
||||
:duration="duration"
|
||||
:show="showTrans"
|
||||
@click="onTap"
|
||||
>
|
||||
<view
|
||||
class="uv-popup__content"
|
||||
:style="[contentStyle]"
|
||||
:class="[popupClass]"
|
||||
@click="clear"
|
||||
>
|
||||
<uv-status-bar v-if="safeAreaInsetTop"></uv-status-bar>
|
||||
<slot />
|
||||
<uv-safe-bottom v-if="safeAreaInsetBottom"></uv-safe-bottom>
|
||||
<view
|
||||
v-if="closeable"
|
||||
@tap.stop="close"
|
||||
class="uv-popup__content__close"
|
||||
:class="['uv-popup__content__close--' + closeIconPos]"
|
||||
hover-class="uv-popup__content__close--hover"
|
||||
hover-stay-time="150"
|
||||
>
|
||||
<uv-icon
|
||||
name="close"
|
||||
color="#909399"
|
||||
size="18"
|
||||
bold
|
||||
></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
</uv-transition>
|
||||
</view>
|
||||
<!-- #ifdef H5 -->
|
||||
<keypress v-if="maskShow" @esc="onTap" />
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef H5
|
||||
import keypress from './keypress.js'
|
||||
// #endif
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
/**
|
||||
* PopUp 弹出层
|
||||
* @description 弹出层组件,为了解决遮罩弹层的问题
|
||||
* @tutorial https://www.uvui.cn/components/popup.html
|
||||
* @property {String} mode = [top|center|bottom|left|right] 弹出方式
|
||||
* @value top 顶部弹出
|
||||
* @value center 中间弹出
|
||||
* @value bottom 底部弹出
|
||||
* @value left 左侧弹出
|
||||
* @value right 右侧弹出
|
||||
* @property {Number} duration 动画时长,默认300
|
||||
* @property {Boolean} overlay 是否显示遮罩,默认true
|
||||
* @property {Boolean} overlayOpacity 遮罩透明度,默认0.5
|
||||
* @property {Object} overlayStyle 遮罩自定义样式
|
||||
* @property {Boolean} closeOnClickOverlay = [true|false] 蒙版点击是否关闭弹窗,默认true
|
||||
* @property {Number | String} zIndex 弹出层的层级
|
||||
* @property {Boolean} safeAreaInsetTop 是否留出顶部安全区(状态栏高度),默认false
|
||||
* @property {Boolean} safeAreaInsetBottom 是否为留出底部安全区适配,默认true
|
||||
* @property {Boolean} closeable 是否显示关闭图标,默认false
|
||||
* @property {Boolean} closeIconPos 自定义关闭图标位置,`top-left`-左上角,`top-right`-右上角,`bottom-left`-左下角,`bottom-right`-右下角,默认top-right
|
||||
* @property {String} bgColor 主窗口背景色
|
||||
* @property {String} maskBackgroundColor 蒙版颜色
|
||||
* @property {Boolean} customStyle 自定义样式
|
||||
* @event {Function} change 打开关闭弹窗触发,e={show: false}
|
||||
* @event {Function} maskClick 点击遮罩触发
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-popup',
|
||||
components: {
|
||||
// #ifdef H5
|
||||
keypress
|
||||
// #endif
|
||||
},
|
||||
mixins: [mpMixin, mixin],
|
||||
emits: ['change', 'maskClick'],
|
||||
props: {
|
||||
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
|
||||
// message: 消息提示 ; dialog : 对话框
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'center'
|
||||
},
|
||||
// 动画时长,单位ms
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 300
|
||||
},
|
||||
// 层级
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
// #ifdef H5
|
||||
default: 997
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
default: 10075
|
||||
// #endif
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
},
|
||||
safeArea: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否显示遮罩
|
||||
overlay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 点击遮罩是否关闭弹窗
|
||||
closeOnClickOverlay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 遮罩的透明度,0-1之间
|
||||
overlayOpacity: {
|
||||
type: [Number, String],
|
||||
default: 0.4
|
||||
},
|
||||
// 自定义遮罩的样式
|
||||
overlayStyle: {
|
||||
type: [Object, String],
|
||||
default: ''
|
||||
},
|
||||
// 是否为iPhoneX留出底部安全距离
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否留出顶部安全距离(状态栏高度)
|
||||
safeAreaInsetTop: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示关闭图标
|
||||
closeable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 自定义关闭图标位置,top-left为左上角,top-right为右上角,bottom-left为左下角,bottom-right为右下角
|
||||
closeIconPos: {
|
||||
type: String,
|
||||
default: 'top-right'
|
||||
},
|
||||
// mode=center,也即中部弹出时,是否使用缩放模式
|
||||
zoom: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
round: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
...uni.$uv?.props?.popup
|
||||
},
|
||||
watch: {
|
||||
/**
|
||||
* 监听type类型
|
||||
*/
|
||||
type: {
|
||||
handler: function(type) {
|
||||
if (!this.config[type]) return
|
||||
this[this.config[type]](true)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
isDesktop: {
|
||||
handler: function(newVal) {
|
||||
if (!this.config[newVal]) return
|
||||
this[this.config[this.mode]](true)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
// H5 下禁止底部滚动
|
||||
showPopup(show) {
|
||||
// #ifdef H5
|
||||
// fix by mehaotian 处理 h5 滚动穿透的问题
|
||||
document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible'
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ani: [],
|
||||
showPopup: false,
|
||||
showTrans: false,
|
||||
popupWidth: 0,
|
||||
popupHeight: 0,
|
||||
config: {
|
||||
top: 'top',
|
||||
bottom: 'bottom',
|
||||
center: 'center',
|
||||
left: 'left',
|
||||
right: 'right',
|
||||
message: 'top',
|
||||
dialog: 'center',
|
||||
share: 'bottom'
|
||||
},
|
||||
transitionStyle: {
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
maskShow: true,
|
||||
mkclick: true,
|
||||
popupClass: this.isDesktop ? 'fixforpc-top' : 'top',
|
||||
direction: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isDesktop() {
|
||||
return this.popupWidth >= 500 && this.popupHeight >= 500
|
||||
},
|
||||
bg() {
|
||||
if (this.bgColor === '' || this.bgColor === 'none' || this.$uv.getPx(this.round)>0) {
|
||||
return 'transparent'
|
||||
}
|
||||
return this.bgColor
|
||||
},
|
||||
contentStyle() {
|
||||
const style = {};
|
||||
if (this.bgColor) {
|
||||
style.backgroundColor = this.bg
|
||||
}
|
||||
if(this.round) {
|
||||
const value = this.$uv.addUnit(this.round)
|
||||
const mode = this.direction?this.direction:this.mode
|
||||
style.backgroundColor = this.bgColor
|
||||
if(mode === 'top') {
|
||||
style.borderBottomLeftRadius = value
|
||||
style.borderBottomRightRadius = value
|
||||
} else if(mode === 'bottom') {
|
||||
style.borderTopLeftRadius = value
|
||||
style.borderTopRightRadius = value
|
||||
} else if(mode === 'center') {
|
||||
style.borderRadius = value
|
||||
}
|
||||
}
|
||||
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
|
||||
}
|
||||
},
|
||||
// #ifndef VUE3
|
||||
// TODO vue2
|
||||
destroyed() {
|
||||
this.setH5Visible()
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
// TODO vue3
|
||||
unmounted() {
|
||||
this.setH5Visible()
|
||||
},
|
||||
// #endif
|
||||
created() {
|
||||
// TODO 处理 message 组件生命周期异常的问题
|
||||
this.messageChild = null
|
||||
// TODO 解决头条冒泡的问题
|
||||
this.clearPropagation = false
|
||||
},
|
||||
methods: {
|
||||
setH5Visible() {
|
||||
// #ifdef H5
|
||||
// fix by mehaotian 处理 h5 滚动穿透的问题
|
||||
document.getElementsByTagName('body')[0].style.overflow = 'visible'
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 公用方法,不显示遮罩层
|
||||
*/
|
||||
closeMask() {
|
||||
this.maskShow = false
|
||||
},
|
||||
// TODO nvue 取消冒泡
|
||||
clear(e) {
|
||||
// #ifndef APP-NVUE
|
||||
e.stopPropagation()
|
||||
// #endif
|
||||
this.clearPropagation = true
|
||||
},
|
||||
|
||||
open(direction) {
|
||||
// fix by mehaotian 处理快速打开关闭的情况
|
||||
if (this.showPopup) {
|
||||
return
|
||||
}
|
||||
let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
|
||||
if (!(direction && innerType.indexOf(direction) !== -1)) {
|
||||
direction = this.mode
|
||||
}else {
|
||||
this.direction = direction;
|
||||
}
|
||||
if (!this.config[direction]) {
|
||||
return this.$uv.error(`缺少类型:${direction}`);
|
||||
}
|
||||
this[this.config[direction]]()
|
||||
this.$emit('change', {
|
||||
show: true,
|
||||
type: direction
|
||||
})
|
||||
},
|
||||
close(type) {
|
||||
this.showTrans = false
|
||||
this.$emit('change', {
|
||||
show: false,
|
||||
type: this.mode
|
||||
})
|
||||
clearTimeout(this.timer)
|
||||
// // 自定义关闭事件
|
||||
this.timer = setTimeout(() => {
|
||||
this.showPopup = false
|
||||
}, 300)
|
||||
},
|
||||
// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
|
||||
touchstart() {
|
||||
this.clearPropagation = false
|
||||
},
|
||||
onTap() {
|
||||
if (this.clearPropagation) {
|
||||
// fix by mehaotian 兼容 nvue
|
||||
this.clearPropagation = false
|
||||
return
|
||||
}
|
||||
this.$emit('maskClick')
|
||||
if (!this.closeOnClickOverlay) return
|
||||
this.close()
|
||||
},
|
||||
/**
|
||||
* 顶部弹出样式处理
|
||||
*/
|
||||
top(type) {
|
||||
this.popupClass = this.isDesktop ? 'fixforpc-top' : 'top'
|
||||
this.ani = ['slide-top']
|
||||
this.transitionStyle = {
|
||||
position: 'fixed',
|
||||
zIndex: this.zIndex,
|
||||
left: 0,
|
||||
right: 0,
|
||||
backgroundColor: this.bg
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
this.$nextTick(() => {
|
||||
if (this.messageChild && this.mode === 'message') {
|
||||
this.messageChild.timerClose()
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 底部弹出样式处理
|
||||
*/
|
||||
bottom(type) {
|
||||
this.popupClass = 'bottom'
|
||||
this.ani = ['slide-bottom']
|
||||
this.transitionStyle = {
|
||||
position: 'fixed',
|
||||
zIndex: this.zIndex,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: this.bg
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
},
|
||||
/**
|
||||
* 中间弹出样式处理
|
||||
*/
|
||||
center(type) {
|
||||
this.popupClass = 'center'
|
||||
this.ani = this.zoom?['zoom-in', 'fade']:['fade'];
|
||||
this.transitionStyle = {
|
||||
position: 'fixed',
|
||||
zIndex: this.zIndex,
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
/* #endif */
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
},
|
||||
left(type) {
|
||||
this.popupClass = 'left'
|
||||
this.ani = ['slide-left']
|
||||
this.transitionStyle = {
|
||||
position: 'fixed',
|
||||
zIndex: this.zIndex,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
backgroundColor: this.bg,
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
/* #endif */
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
},
|
||||
right(type) {
|
||||
this.popupClass = 'right'
|
||||
this.ani = ['slide-right']
|
||||
this.transitionStyle = {
|
||||
position: 'fixed',
|
||||
zIndex: this.zIndex,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
backgroundColor: this.bg,
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
/* #endif */
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uv-popup {
|
||||
position: fixed;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 99;
|
||||
|
||||
/* #endif */
|
||||
&.top,
|
||||
&.left,
|
||||
&.right {
|
||||
/* #ifdef H5 */
|
||||
top: var(--window-top);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
top: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uv-popup__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
|
||||
&.left,
|
||||
&.right {
|
||||
/* #ifdef H5 */
|
||||
padding-top: var(--window-top);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
padding-top: 0;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
}
|
||||
&__close {
|
||||
position: absolute;
|
||||
|
||||
&--hover {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
&__close--top-left {
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
&__close--top-right {
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
&__close--bottom-left {
|
||||
bottom: 15px;
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
&__close--bottom-right {
|
||||
right: 15px;
|
||||
bottom: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fixforpc-z-index {
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 999;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fixforpc-top {
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
||||
92
uni_modules/uv-popup/package.json
Normal file
92
uni_modules/uv-popup/package.json
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"id": "uv-popup",
|
||||
"displayName": "uv-popup 弹出层 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.7",
|
||||
"description": "uv-popup 弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义。",
|
||||
"keywords": [
|
||||
"uv-popup",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"popup",
|
||||
"弹出层"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-overlay",
|
||||
"uv-transition",
|
||||
"uv-icon",
|
||||
"uv-status-bar",
|
||||
"uv-safe-bottom"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
uni_modules/uv-popup/readme.md
Normal file
21
uni_modules/uv-popup/readme.md
Normal file
@@ -0,0 +1,21 @@
|
||||
## Popup 弹出层
|
||||
|
||||
> **组件名:uv-popup**
|
||||
|
||||
弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义。
|
||||
|
||||
该组件已经放弃原来`uview2.x`的写法,参照了官方`uni-popup`的写法进行重构。在小程序端的性能大大提升,打开和关闭避免延迟,调用方法与之前相比也有所差异,具体请查看文档。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/popup.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
11
uni_modules/uv-safe-bottom/changelog.md
Normal file
11
uni_modules/uv-safe-bottom/changelog.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## 1.0.4(2023-09-14)
|
||||
1. 飞书小程序支持
|
||||
## 1.0.3(2023-08-14)
|
||||
1. 修复百度报错的BUG
|
||||
## 1.0.2(2023-07-02)
|
||||
uv-safe-bottom 修复,在百度程序,抖音小程序不生效的BUG
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-safe-bottom 底部安全区组件
|
||||
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-safe-bottom"
|
||||
:style="[style]"
|
||||
:class="[!isNvue && 'uv-safe-area-inset-bottom']"
|
||||
>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
/**
|
||||
* SafeBottom 底部安全区
|
||||
* @description 这个适配,主要是针对IPhone X等一些底部带指示条的机型,指示条的操作区域与页面底部存在重合,容易导致用户误操作,因此我们需要针对这些机型进行底部安全区适配。
|
||||
* @tutorial https://www.uvui.cn/components/safeAreaInset.html
|
||||
* @property {type} prop_name
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
*
|
||||
* @event {Function()}
|
||||
* @example <uv-status-bar></uv-status-bar>
|
||||
*/
|
||||
export default {
|
||||
name: "uv-safe-bottom",
|
||||
mixins: [mpMixin, mixin],
|
||||
data() {
|
||||
return {
|
||||
safeAreaBottomHeight: 0,
|
||||
isNvue: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
style() {
|
||||
const style = {};
|
||||
// #ifdef APP-NVUE || MP-TOUTIAO || MP-LARK
|
||||
// nvue下,高度使用js计算填充
|
||||
style.height = this.$uv.addUnit(this.$uv.sys()?.safeAreaInsets?.bottom, 'px');
|
||||
// #endif
|
||||
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle));
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef APP-NVUE
|
||||
// 标识为是否nvue
|
||||
this.isNvue = true;
|
||||
// #endif
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uv-safe-bottom {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
}
|
||||
/* #ifndef APP-NVUE */
|
||||
// 历遍生成4个方向的底部安全区
|
||||
@each $d in top, right, bottom, left {
|
||||
.uv-safe-area-inset-#{$d} {
|
||||
padding-#{$d}: 0;
|
||||
padding-#{$d}: constant(safe-area-inset-#{$d});
|
||||
padding-#{$d}: env(safe-area-inset-#{$d});
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
87
uni_modules/uv-safe-bottom/package.json
Normal file
87
uni_modules/uv-safe-bottom/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"id": "uv-safe-bottom",
|
||||
"displayName": "uv-safe-bottom 底部安全区 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.4",
|
||||
"description": "这个适配,主要是针对IPhone X等一些底部带指示条的机型,指示条的操作区域与页面底部存在重合,容易导致用户误操作,因此我们需要针对这些机型进行底部安全区适配。",
|
||||
"keywords": [
|
||||
"uv-safe-bottom",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"bottom",
|
||||
"底部安全区"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
uni_modules/uv-safe-bottom/readme.md
Normal file
11
uni_modules/uv-safe-bottom/readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## SafeBottom 底部安全区
|
||||
|
||||
> **组件名:uv-safe-bottom**
|
||||
|
||||
这个适配,主要是针对IPhone X等一些底部带指示条的机型,指示条的操作区域与页面底部存在重合,容易导致用户误操作,因此我们需要针对这些机型进行底部安全区适配。
|
||||
|
||||
### <a href="https://www.uvui.cn/guide/safeAreaInset.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
7
uni_modules/uv-status-bar/changelog.md
Normal file
7
uni_modules/uv-status-bar/changelog.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## 1.0.2(2023-06-05)
|
||||
1. 兼容渐变背景色
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
1. 新增uv-status-bar组件
|
||||
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
props: {
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: 'transparent'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<view
|
||||
:style="[style]"
|
||||
class="uv-status-bar"
|
||||
>
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* StatbusBar 状态栏占位
|
||||
* @description 本组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。
|
||||
* @tutorial https://www.uvui.cn/components/statusBar.html
|
||||
* @property {String} bgColor 背景色 (默认 'transparent' )
|
||||
* @property {String | Object} customStyle 自定义样式
|
||||
* @example <uv-status-bar></uv-status-bar>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-status-bar',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
style() {
|
||||
const style = {}
|
||||
// 状态栏高度,由于某些安卓和微信开发工具无法识别css的顶部状态栏变量,所以使用js获取的方式
|
||||
style.height = this.$uv.addUnit(this.$uv.sys().statusBarHeight, 'px')
|
||||
if(this.bgColor){
|
||||
if (this.bgColor.indexOf("gradient") > -1) {// 渐变色
|
||||
style.backgroundImage = this.bgColor;
|
||||
}else{
|
||||
style.background = this.bgColor;
|
||||
}
|
||||
}
|
||||
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uv-status-bar {
|
||||
// nvue会默认100%,如果nvue下,显式写100%的话,会导致宽度不为100%而异常
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
87
uni_modules/uv-status-bar/package.json
Normal file
87
uni_modules/uv-status-bar/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"id": "uv-status-bar",
|
||||
"displayName": "uv-status-bar 状态栏占位",
|
||||
"version": "1.0.2",
|
||||
"description": "状态栏占位组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。",
|
||||
"keywords": [
|
||||
"uv-status-bar",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"status-bar",
|
||||
"状态栏"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
uni_modules/uv-status-bar/readme.md
Normal file
10
uni_modules/uv-status-bar/readme.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## StatbusBar 状态栏占位
|
||||
|
||||
> **组件名:uv-status-bar**
|
||||
|
||||
本组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
|
||||
2
uni_modules/uv-toolbar/changelog.md
Normal file
2
uni_modules/uv-toolbar/changelog.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## 1.0.0(2023-08-02)
|
||||
1. 新增工具条组件
|
||||
40
uni_modules/uv-toolbar/components/uv-toolbar/props.js
Normal file
40
uni_modules/uv-toolbar/components/uv-toolbar/props.js
Normal file
@@ -0,0 +1,40 @@
|
||||
export default {
|
||||
props: {
|
||||
// 是否展示工具条
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否显示下边框
|
||||
showBorder: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 取消按钮的文字
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
// 确认按钮的文字
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
},
|
||||
// 取消按钮的颜色
|
||||
cancelColor: {
|
||||
type: String,
|
||||
default: '#909193'
|
||||
},
|
||||
// 确认按钮的颜色
|
||||
confirmColor: {
|
||||
type: String,
|
||||
default: '#3c9cff'
|
||||
},
|
||||
// 标题文字
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
...uni.$uv?.props?.toolbar
|
||||
}
|
||||
}
|
||||
109
uni_modules/uv-toolbar/components/uv-toolbar/uv-toolbar.vue
Normal file
109
uni_modules/uv-toolbar/components/uv-toolbar/uv-toolbar.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<view
|
||||
:class="['uv-toolbar',{'uv-border-bottom':showBorder}]"
|
||||
@touchmove.stop.prevent="noop"
|
||||
v-if="show"
|
||||
>
|
||||
<view
|
||||
class="uv-toolbar__cancel__wrapper"
|
||||
hover-class="uv-hover-class"
|
||||
>
|
||||
<text
|
||||
class="uv-toolbar__wrapper__cancel"
|
||||
@tap="cancel"
|
||||
:style="{
|
||||
color: cancelColor
|
||||
}"
|
||||
>{{ cancelText }}</text>
|
||||
</view>
|
||||
<text
|
||||
class="uv-toolbar__title uv-line-1"
|
||||
v-if="title"
|
||||
>{{ title }}</text>
|
||||
<view
|
||||
class="uv-toolbar__confirm__wrapper"
|
||||
hover-class="uv-hover-class"
|
||||
>
|
||||
<text
|
||||
class="uv-toolbar__wrapper__confirm"
|
||||
@tap="confirm"
|
||||
:style="{
|
||||
color: confirmColor
|
||||
}"
|
||||
>{{ confirmText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* Toolbar 工具条
|
||||
* @description
|
||||
* @tutorial https://www.uvui.cn/components/toolbar.html
|
||||
* @property {Boolean} show 是否展示工具条(默认 true )
|
||||
* @property {Boolean} showBorder 是否展示工具条下方边框(默认 false )
|
||||
* @property {String} cancelText 取消按钮的文字(默认 '取消' )
|
||||
* @property {String} confirmText 确认按钮的文字(默认 '确认' )
|
||||
* @property {String} cancelColor 取消按钮的颜色(默认 '#909193' )
|
||||
* @property {String} confirmColor 确认按钮的颜色(默认 '#3c9cff' )
|
||||
* @property {String} title 标题文字
|
||||
* @event {Function}
|
||||
* @example
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-toolbar',
|
||||
emits: ['confirm', 'cancel'],
|
||||
mixins: [mpMixin, mixin, props],
|
||||
methods: {
|
||||
// 点击取消按钮
|
||||
cancel() {
|
||||
this.$emit('cancel')
|
||||
},
|
||||
// 点击确定按钮
|
||||
confirm() {
|
||||
this.$emit('confirm')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-lines: 1;
|
||||
$show-hover: 1;
|
||||
$show-border: 1;
|
||||
$show-border-bottom: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
$uv-tips-color: #909193 !default;
|
||||
$uv-main-color: #303133 !default;
|
||||
$uv-primary: #3c9cff !default;
|
||||
.uv-toolbar {
|
||||
height: 42px;
|
||||
@include flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
&__wrapper {
|
||||
&__cancel {
|
||||
color: $uv-tips-color;
|
||||
font-size: 15px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
&__title {
|
||||
color: $uv-main-color;
|
||||
padding: 0 60rpx;
|
||||
font-size: 16px;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
&__wrapper {
|
||||
&__confirm {
|
||||
color: $uv-primary;
|
||||
font-size: 15px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
87
uni_modules/uv-toolbar/package.json
Normal file
87
uni_modules/uv-toolbar/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"id": "uv-toolbar",
|
||||
"displayName": "uv-toolbar 工具条",
|
||||
"version": "1.0.0",
|
||||
"description": "该组价是仅用于uv-ui中一个公共小工具,提供一个取消和确定的样式,可以设置标题,主要用于弹窗顶部的选择确定工具条",
|
||||
"keywords": [
|
||||
"uv-toolbar",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"工具条",
|
||||
"工具"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
uni_modules/uv-toolbar/readme.md
Normal file
31
uni_modules/uv-toolbar/readme.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Toolbar 工具条
|
||||
|
||||
> **组件名:uv-toolbar**
|
||||
|
||||
该组价是仅用于uv-ui中一个公共小工具,提供一个取消和确定的样式,可以设置标题,主要用于弹窗顶部的选择确定工具条。
|
||||
|
||||
### 基本使用
|
||||
|
||||
```vue
|
||||
<uv-toolbar title="标题文字"></uv-toolbar>
|
||||
```
|
||||
|
||||
### Toolbar Props
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
|:-|:-|:-|:-|
|
||||
| show | Boolean | true | 是否展示工具条 |
|
||||
| showBorder | Boolean | false | 是否显示下边框 |
|
||||
| cancelText | String | '取消' | 取消按钮的文字 |
|
||||
| confirmText | String | '确定' | 确定按钮的文字 |
|
||||
| cancelColor | String | '#909193' | 取消按钮的颜色 |
|
||||
| confirmColor | String | '#3c9cff' | 确认按钮的颜色 |
|
||||
| title | String | - | 标题文字 |
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||

|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
19
uni_modules/uv-transition/changelog.md
Normal file
19
uni_modules/uv-transition/changelog.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## 1.0.8(2023-10-18)
|
||||
1. 修复在APP上不能正常显示的BUG
|
||||
## 1.0.7(2023-10-12)
|
||||
1. 修复部分情况,修改某属性自动关闭的BUG
|
||||
## 1.0.6(2023-07-24)
|
||||
1. 优化 nvue模式下增加cellChild参数,是否在list中cell节点下,nvue中cell下建议设置成true
|
||||
## 1.0.5(2023-07-02)
|
||||
修改VUE3模式下可能存在的BUG
|
||||
## 1.0.4(2023-07-02)
|
||||
uv-transition 动画组件,代码重构优化,性能更加友好,增加自定义动画功能。详情参考文档:https://www.uvui.cn/components/transition.html
|
||||
## 1.0.3(2023-06-12)
|
||||
1. 恢复this.$nextTick的使用,经过测试百度等平台无问题
|
||||
## 1.0.2(2023-05-23)
|
||||
1. 百度小程序等平台不支持this.$nextick,修改成延时
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
1. 新增动画组件
|
||||
@@ -0,0 +1,131 @@
|
||||
// const defaultOption = {
|
||||
// duration: 300,
|
||||
// timingFunction: 'linear',
|
||||
// delay: 0,
|
||||
// transformOrigin: '50% 50% 0'
|
||||
// }
|
||||
// #ifdef APP-NVUE
|
||||
const nvueAnimation = uni.requireNativePlugin('animation')
|
||||
// #endif
|
||||
class MPAnimation {
|
||||
constructor(options, _this) {
|
||||
this.options = options
|
||||
// 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误
|
||||
this.animation = uni.createAnimation({
|
||||
...options
|
||||
})
|
||||
this.currentStepAnimates = {}
|
||||
this.next = 0
|
||||
this.$ = _this
|
||||
|
||||
}
|
||||
|
||||
_nvuePushAnimates(type, args) {
|
||||
let aniObj = this.currentStepAnimates[this.next]
|
||||
let styles = {}
|
||||
if (!aniObj) {
|
||||
styles = {
|
||||
styles: {},
|
||||
config: {}
|
||||
}
|
||||
} else {
|
||||
styles = aniObj
|
||||
}
|
||||
if (animateTypes1.includes(type)) {
|
||||
if (!styles.styles.transform) {
|
||||
styles.styles.transform = ''
|
||||
}
|
||||
let unit = ''
|
||||
if(type === 'rotate'){
|
||||
unit = 'deg'
|
||||
}
|
||||
styles.styles.transform += `${type}(${args+unit}) `
|
||||
} else {
|
||||
styles.styles[type] = `${args}`
|
||||
}
|
||||
this.currentStepAnimates[this.next] = styles
|
||||
}
|
||||
_animateRun(styles = {}, config = {}) {
|
||||
let ref = this.$.$refs['ani'].ref
|
||||
if (!ref) return
|
||||
return new Promise((resolve, reject) => {
|
||||
nvueAnimation.transition(ref, {
|
||||
styles,
|
||||
...config
|
||||
}, res => {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
_nvueNextAnimate(animates, step = 0, fn) {
|
||||
let obj = animates[step]
|
||||
if (obj) {
|
||||
let {
|
||||
styles,
|
||||
config
|
||||
} = obj
|
||||
this._animateRun(styles, config).then(() => {
|
||||
step += 1
|
||||
this._nvueNextAnimate(animates, step, fn)
|
||||
})
|
||||
} else {
|
||||
this.currentStepAnimates = {}
|
||||
typeof fn === 'function' && fn()
|
||||
this.isEnd = true
|
||||
}
|
||||
}
|
||||
|
||||
step(config = {}) {
|
||||
// #ifndef APP-NVUE
|
||||
this.animation.step(config)
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
|
||||
this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
|
||||
this.next++
|
||||
// #endif
|
||||
return this
|
||||
}
|
||||
|
||||
run(fn) {
|
||||
// #ifndef APP-NVUE
|
||||
this.$.animationData = this.animation.export()
|
||||
this.$.timer = setTimeout(() => {
|
||||
typeof fn === 'function' && fn()
|
||||
}, this.$.durationTime)
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this.isEnd = false
|
||||
let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
|
||||
if(!ref) return
|
||||
this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
|
||||
this.next = 0
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
|
||||
'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
|
||||
'translateZ'
|
||||
]
|
||||
const animateTypes2 = ['opacity', 'backgroundColor']
|
||||
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
|
||||
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
|
||||
MPAnimation.prototype[type] = function(...args) {
|
||||
// #ifndef APP-NVUE
|
||||
this.animation[type](...args)
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this._nvuePushAnimates(type, args)
|
||||
// #endif
|
||||
return this
|
||||
}
|
||||
})
|
||||
|
||||
export function createAnimation(option, _this) {
|
||||
if(!_this) return
|
||||
clearTimeout(_this.timer)
|
||||
return new MPAnimation(option, _this)
|
||||
}
|
||||
31
uni_modules/uv-transition/components/uv-transition/props.js
Normal file
31
uni_modules/uv-transition/components/uv-transition/props.js
Normal file
@@ -0,0 +1,31 @@
|
||||
export default {
|
||||
props: {
|
||||
// 是否展示组件
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 使用的动画模式
|
||||
mode: {
|
||||
type: [Array, String, null],
|
||||
default() {
|
||||
return 'fade'
|
||||
}
|
||||
},
|
||||
// 动画的执行时间,单位ms
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 300
|
||||
},
|
||||
// 使用的动画过渡函数
|
||||
timingFunction: {
|
||||
type: String,
|
||||
default: 'ease-out'
|
||||
},
|
||||
customClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
...uni.$uv?.props?.transition
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
<template>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view
|
||||
v-if="isShow"
|
||||
ref="ani"
|
||||
:animation="animationData"
|
||||
:class="customClass"
|
||||
:style="transformStyles"
|
||||
@click="onClick">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view
|
||||
v-if="isShow"
|
||||
ref="ani"
|
||||
:animation="animationData"
|
||||
:class="customClass"
|
||||
:style="transformStyles"
|
||||
@click="onClick">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import { createAnimation } from './createAnimation'
|
||||
/**
|
||||
* transition 动画组件
|
||||
* @description
|
||||
* @tutorial
|
||||
* @property {Boolean} show 控制组件显示或关闭 (默认 false )
|
||||
* @property {Array | String } mode 内置过渡动画类型 (默认 'fade' )
|
||||
* @value fade 渐隐渐出过渡
|
||||
* @value slide-top 由上至下过渡
|
||||
* @value slide-bottom 由下至上过渡
|
||||
* @value slide-left 由左至右过渡
|
||||
* @value slide-right 由右至左过渡
|
||||
* @value zoom-in 由小到大过渡
|
||||
* @value zoom-out 由大到小过渡
|
||||
* @property {String | Number} duration 动画的执行时间,单位ms (默认 300 )
|
||||
* @property {String} timingFunction 使用的动画过渡函数 (默认 'ease-out' )
|
||||
* @property {Object} customStyle 自定义样式
|
||||
* @property {String} customClass 自定义类名
|
||||
* @event {Function} click 点击组件触发
|
||||
* @event {Function} change 过渡动画结束时触发
|
||||
* @example
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-transition',
|
||||
mixins: [mpMixin,mixin],
|
||||
emits:['click','change'],
|
||||
props: {
|
||||
// 是否展示组件
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 使用的动画模式
|
||||
mode: {
|
||||
type: [Array, String, null],
|
||||
default() {
|
||||
return 'fade'
|
||||
}
|
||||
},
|
||||
// 动画的执行时间,单位ms
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 300
|
||||
},
|
||||
// 使用的动画过渡函数
|
||||
timingFunction: {
|
||||
type: String,
|
||||
default: 'ease-out'
|
||||
},
|
||||
customClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// nvue模式下 是否直接显示,在uv-list等cell下面使用就需要设置
|
||||
cellChild: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
isShow: false,
|
||||
transform: '',
|
||||
opacity: 1,
|
||||
animationData: {},
|
||||
durationTime: 300,
|
||||
config: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show: {
|
||||
handler(newVal) {
|
||||
if (newVal) {
|
||||
this.open();
|
||||
} else {
|
||||
// 避免上来就执行 close,导致动画错乱
|
||||
if (this.isShow) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 初始化动画条件
|
||||
transformStyles() {
|
||||
const style = {
|
||||
transform: this.transform,
|
||||
opacity: this.opacity,
|
||||
...this.$uv.addStyle(this.customStyle),
|
||||
'transition-duration': `${this.duration / 1000}s`
|
||||
};
|
||||
return this.$uv.addStyle(style,'string');
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 动画默认配置
|
||||
this.config = {
|
||||
duration: this.duration,
|
||||
timingFunction: this.timingFunction,
|
||||
transformOrigin: '50% 50%',
|
||||
delay: 0
|
||||
};
|
||||
this.durationTime = this.duration;
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* ref 触发 初始化动画
|
||||
*/
|
||||
init(obj = {}) {
|
||||
if (obj.duration) {
|
||||
this.durationTime = obj.duration;
|
||||
}
|
||||
this.animation = createAnimation(Object.assign(this.config, obj),this);
|
||||
},
|
||||
/**
|
||||
* 点击组件触发回调
|
||||
*/
|
||||
onClick() {
|
||||
this.$emit('click', {
|
||||
detail: this.isShow
|
||||
})
|
||||
},
|
||||
/**
|
||||
* ref 触发 动画分组
|
||||
* @param {Object} obj
|
||||
*/
|
||||
step(obj, config = {}) {
|
||||
if (!this.animation) return;
|
||||
for (let i in obj) {
|
||||
try {
|
||||
if(typeof obj[i] === 'object'){
|
||||
this.animation[i](...obj[i]);
|
||||
}else{
|
||||
this.animation[i](obj[i]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`方法 ${i} 不存在`);
|
||||
}
|
||||
}
|
||||
this.animation.step(config);
|
||||
return this;
|
||||
},
|
||||
/**
|
||||
* ref 触发 执行动画
|
||||
*/
|
||||
run(fn) {
|
||||
if (!this.animation) return;
|
||||
this.animation.run(fn);
|
||||
},
|
||||
// 开始过度动画
|
||||
open() {
|
||||
clearTimeout(this.timer);
|
||||
this.transform = '';
|
||||
this.isShow = true;
|
||||
let { opacity, transform } = this.styleInit(false);
|
||||
if (typeof opacity !== 'undefined') {
|
||||
this.opacity = opacity;
|
||||
}
|
||||
this.transform = transform;
|
||||
// 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常
|
||||
this.$nextTick(() => {
|
||||
// TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器
|
||||
this.timer = setTimeout(() => {
|
||||
this.animation = createAnimation(this.config, this);
|
||||
this.tranfromInit(false).step();
|
||||
// #ifdef APP-NVUE
|
||||
if(this.cellChild) {
|
||||
this.opacity = 1;
|
||||
} else{
|
||||
this.animation.run();
|
||||
}
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.animation.run();
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
// #ifdef H5
|
||||
this.opacity = 1;
|
||||
// #endif
|
||||
// #endif
|
||||
this.$emit('change', {
|
||||
detail: this.isShow
|
||||
})
|
||||
// #ifdef H5
|
||||
// #ifdef VUE3
|
||||
this.transform = '';
|
||||
// #endif
|
||||
// #endif
|
||||
}, 20);
|
||||
})
|
||||
},
|
||||
// 关闭过渡动画
|
||||
close(type) {
|
||||
if (!this.animation) return;
|
||||
this.tranfromInit(true)
|
||||
.step()
|
||||
.run(() => {
|
||||
this.isShow = false;
|
||||
this.animationData = null;
|
||||
this.animation = null;
|
||||
let { opacity, transform } = this.styleInit(false);
|
||||
this.opacity = opacity || 1;
|
||||
this.transform = transform;
|
||||
this.$emit('change', {
|
||||
detail: this.isShow
|
||||
});
|
||||
})
|
||||
},
|
||||
// 处理动画开始前的默认样式
|
||||
styleInit(type) {
|
||||
let styles = {
|
||||
transform: ''
|
||||
};
|
||||
let buildStyle = (type, mode) => {
|
||||
if (mode === 'fade') {
|
||||
styles.opacity = this.animationType(type)[mode];
|
||||
} else {
|
||||
styles.transform += this.animationType(type)[mode] + ' ';
|
||||
}
|
||||
}
|
||||
if (typeof this.mode === 'string') {
|
||||
buildStyle(type, this.mode);
|
||||
} else {
|
||||
this.mode.forEach(mode => {
|
||||
buildStyle(type, mode)
|
||||
})
|
||||
}
|
||||
return styles
|
||||
},
|
||||
// 处理内置组合动画
|
||||
tranfromInit(type) {
|
||||
let buildTranfrom = (type, mode) => {
|
||||
let aniNum = null;
|
||||
if (mode === 'fade') {
|
||||
aniNum = type ? 0 : 1;
|
||||
} else {
|
||||
aniNum = type ? '-100%' : '0';
|
||||
if (mode === 'zoom-in') {
|
||||
aniNum = type ? 0.8 : 1
|
||||
}
|
||||
if (mode === 'zoom-out') {
|
||||
aniNum = type ? 1.2 : 1
|
||||
}
|
||||
if (mode === 'slide-right') {
|
||||
aniNum = type ? '100%' : '0'
|
||||
}
|
||||
if (mode === 'slide-bottom') {
|
||||
aniNum = type ? '100%' : '0'
|
||||
}
|
||||
}
|
||||
this.animation[this.animationMode()[mode]](aniNum)
|
||||
}
|
||||
if (typeof this.mode === 'string') {
|
||||
buildTranfrom(type, this.mode)
|
||||
} else {
|
||||
this.mode.forEach(mode => {
|
||||
buildTranfrom(type, mode)
|
||||
})
|
||||
}
|
||||
return this.animation;
|
||||
},
|
||||
animationType(type) {
|
||||
return {
|
||||
fade: type ? 1 : 0,
|
||||
'slide-top': `translateY(${type ? '0' : '-100%'})`,
|
||||
'slide-right': `translateX(${type ? '0' : '100%'})`,
|
||||
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
|
||||
'slide-left': `translateX(${type ? '0' : '-100%'})`,
|
||||
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
|
||||
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
|
||||
}
|
||||
},
|
||||
// 内置动画类型与实际动画对应字典
|
||||
animationMode() {
|
||||
return {
|
||||
fade: 'opacity',
|
||||
'slide-top': 'translateY',
|
||||
'slide-right': 'translateX',
|
||||
'slide-bottom': 'translateY',
|
||||
'slide-left': 'translateX',
|
||||
'zoom-in': 'scale',
|
||||
'zoom-out': 'scale'
|
||||
}
|
||||
},
|
||||
// 驼峰转中横线
|
||||
toLine(name) {
|
||||
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
87
uni_modules/uv-transition/package.json
Normal file
87
uni_modules/uv-transition/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"id": "uv-transition",
|
||||
"displayName": "uv-transition 动画 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.8",
|
||||
"description": "transition 该组件用于组件的动画过渡效果。",
|
||||
"keywords": [
|
||||
"uv-transition",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"transition",
|
||||
"动画"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
uni_modules/uv-transition/readme.md
Normal file
15
uni_modules/uv-transition/readme.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## Transition 动画
|
||||
|
||||
> **组件名:uv-transition**
|
||||
|
||||
该组件用于组件的动画过渡效果,支持自定义动画,开箱即用。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/transition.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||

|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
76
uni_modules/uv-ui-tools/changelog.md
Normal file
76
uni_modules/uv-ui-tools/changelog.md
Normal file
@@ -0,0 +1,76 @@
|
||||
## 1.1.25(2024-01-20)
|
||||
1.1.20版本更新
|
||||
## 1.1.24(2023-12-21)
|
||||
1. luch-request更新
|
||||
## 1.1.23(2023-12-12)
|
||||
1. 1.1.19版本
|
||||
## 1.1.22(2023-11-28)
|
||||
1. 优化
|
||||
## 1.1.21(2023-11-10)
|
||||
1. 1.1.17版本
|
||||
## 1.1.20(2023-10-30)
|
||||
1. 1.1.16版本
|
||||
## 1.1.19(2023-10-13)
|
||||
1. 兼容vue3
|
||||
## 1.1.18(2023-10-12)
|
||||
1. 1.1.15版本
|
||||
## 1.1.17(2023-09-27)
|
||||
1. 1.1.14版本发布
|
||||
## 1.1.16(2023-09-15)
|
||||
1. 1.1.13版本发布
|
||||
## 1.1.15(2023-09-15)
|
||||
1. 更新button.js相关按钮支持open-type="agreePrivacyAuthorization"
|
||||
## 1.1.14(2023-09-14)
|
||||
1. 优化dayjs
|
||||
## 1.1.13(2023-09-13)
|
||||
1. 优化,$uv中增加unit参数,方便组件中使用
|
||||
## 1.1.12(2023-09-10)
|
||||
1. 升级版本
|
||||
## 1.1.11(2023-09-04)
|
||||
1. 1.1.11版本
|
||||
## 1.1.10(2023-08-31)
|
||||
1. 修复customStyle和customClass存在冲突的问题
|
||||
## 1.1.9(2023-08-27)
|
||||
1. 版本升级
|
||||
2. 优化
|
||||
## 1.1.8(2023-08-24)
|
||||
1. 版本升级
|
||||
## 1.1.7(2023-08-22)
|
||||
1. 版本升级
|
||||
## 1.1.6(2023-08-18)
|
||||
uvui版本:1.1.6
|
||||
## 1.0.15(2023-08-14)
|
||||
1. 更新uvui版本号
|
||||
## 1.0.13(2023-08-06)
|
||||
1. 优化
|
||||
## 1.0.12(2023-08-06)
|
||||
1. 修改版本号
|
||||
## 1.0.11(2023-08-06)
|
||||
1. 路由增加events参数
|
||||
2. 路由拦截修复
|
||||
## 1.0.10(2023-08-01)
|
||||
1. 优化
|
||||
## 1.0.9(2023-06-28)
|
||||
优化openType.js
|
||||
## 1.0.8(2023-06-15)
|
||||
1. 修改支付宝报错的BUG
|
||||
## 1.0.7(2023-06-07)
|
||||
1. 解决微信小程序使用uvui提示 Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors
|
||||
2. 解决上述提示,需要在uni.scss配置$uvui-nvue-style: false; 然后在APP.vue下面引入uvui内置的基础样式:@import '@/uni_modules/uv-ui-tools/index.scss';
|
||||
## 1.0.6(2023-06-04)
|
||||
1. uv-ui-tools 优化工具组件,兼容更多功能
|
||||
2. 小程序分享功能优化等
|
||||
## 1.0.5(2023-06-02)
|
||||
1. 修改扩展使用mixin中方法的问题
|
||||
## 1.0.4(2023-05-23)
|
||||
1. 兼容百度小程序修改bem函数
|
||||
## 1.0.3(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.2(2023-05-10)
|
||||
1. 增加Http请求封装
|
||||
2. 优化
|
||||
## 1.0.1(2023-05-04)
|
||||
1. 修改名称及备注
|
||||
## 1.0.0(2023-05-04)
|
||||
1. uv-ui工具集首次发布
|
||||
@@ -0,0 +1,6 @@
|
||||
<template>
|
||||
</template>
|
||||
<script>
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
79
uni_modules/uv-ui-tools/index.js
Normal file
79
uni_modules/uv-ui-tools/index.js
Normal file
@@ -0,0 +1,79 @@
|
||||
// 全局挂载引入http相关请求拦截插件
|
||||
import Request from './libs/luch-request'
|
||||
|
||||
// 引入全局mixin
|
||||
import mixin from './libs/mixin/mixin.js'
|
||||
// 小程序特有的mixin
|
||||
import mpMixin from './libs/mixin/mpMixin.js'
|
||||
// #ifdef MP
|
||||
import mpShare from './libs/mixin/mpShare.js'
|
||||
// #endif
|
||||
|
||||
// 路由封装
|
||||
import route from './libs/util/route.js'
|
||||
// 公共工具函数
|
||||
import * as index from './libs/function/index.js'
|
||||
// 防抖方法
|
||||
import debounce from './libs/function/debounce.js'
|
||||
// 节流方法
|
||||
import throttle from './libs/function/throttle.js'
|
||||
// 规则检验
|
||||
import * as test from './libs/function/test.js'
|
||||
|
||||
// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制
|
||||
import * as colorGradient from './libs/function/colorGradient.js'
|
||||
|
||||
// 配置信息
|
||||
import config from './libs/config/config.js'
|
||||
// 平台
|
||||
import platform from './libs/function/platform'
|
||||
|
||||
const $uv = {
|
||||
route,
|
||||
config,
|
||||
test,
|
||||
date: index.timeFormat, // 另名date
|
||||
...index,
|
||||
colorGradient: colorGradient.colorGradient,
|
||||
hexToRgb: colorGradient.hexToRgb,
|
||||
rgbToHex: colorGradient.rgbToHex,
|
||||
colorToRgba: colorGradient.colorToRgba,
|
||||
http: new Request(),
|
||||
debounce,
|
||||
throttle,
|
||||
platform,
|
||||
mixin,
|
||||
mpMixin
|
||||
}
|
||||
uni.$uv = $uv;
|
||||
const install = (Vue,options={}) => {
|
||||
// #ifndef APP-NVUE
|
||||
const cloneMixin = index.deepClone(mixin);
|
||||
delete cloneMixin?.props?.customClass;
|
||||
delete cloneMixin?.props?.customStyle;
|
||||
Vue.mixin(cloneMixin);
|
||||
// #ifdef MP
|
||||
if(options.mpShare){
|
||||
Vue.mixin(mpShare);
|
||||
}
|
||||
// #endif
|
||||
// #endif
|
||||
// #ifdef VUE2
|
||||
// 时间格式化,同时两个名称,date和timeFormat
|
||||
Vue.filter('timeFormat', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
|
||||
Vue.filter('date', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
|
||||
// 将多久以前的方法,注入到全局过滤器
|
||||
Vue.filter('timeFrom', (timestamp, format) => uni.$uv.timeFrom(timestamp, format));
|
||||
// 同时挂载到uni和Vue.prototype中
|
||||
// #ifndef APP-NVUE
|
||||
// 只有vue,挂载到Vue.prototype才有意义,因为nvue中全局Vue.prototype和Vue.mixin是无效的
|
||||
Vue.prototype.$uv = $uv;
|
||||
// #endif
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
Vue.config.globalProperties.$uv = $uv;
|
||||
// #endif
|
||||
}
|
||||
export default {
|
||||
install
|
||||
}
|
||||
7
uni_modules/uv-ui-tools/index.scss
Normal file
7
uni_modules/uv-ui-tools/index.scss
Normal file
@@ -0,0 +1,7 @@
|
||||
// 引入公共基础类
|
||||
@import "./libs/css/common.scss";
|
||||
|
||||
// 非nvue的样式
|
||||
/* #ifndef APP-NVUE */
|
||||
@import "./libs/css/vue.scss";
|
||||
/* #endif */
|
||||
34
uni_modules/uv-ui-tools/libs/config/config.js
Normal file
34
uni_modules/uv-ui-tools/libs/config/config.js
Normal file
@@ -0,0 +1,34 @@
|
||||
// 此版本发布于2024-01-20
|
||||
const version = '1.1.20'
|
||||
|
||||
// 开发环境才提示,生产环境不会提示
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.log(`\n %c uvui V${version} https://www.uvui.cn/ \n\n`, 'color: #ffffff; background: #3c9cff; padding:5px 0; border-radius: 5px;');
|
||||
}
|
||||
|
||||
export default {
|
||||
v: version,
|
||||
version,
|
||||
// 主题名称
|
||||
type: [
|
||||
'primary',
|
||||
'success',
|
||||
'info',
|
||||
'error',
|
||||
'warning'
|
||||
],
|
||||
// 颜色部分,本来可以通过scss的:export导出供js使用,但是奈何nvue不支持
|
||||
color: {
|
||||
'uv-primary': '#2979ff',
|
||||
'uv-warning': '#ff9900',
|
||||
'uv-success': '#19be6b',
|
||||
'uv-error': '#fa3534',
|
||||
'uv-info': '#909399',
|
||||
'uv-main-color': '#303133',
|
||||
'uv-content-color': '#606266',
|
||||
'uv-tips-color': '#909399',
|
||||
'uv-light-color': '#c0c4cc'
|
||||
},
|
||||
// 默认单位,可以通过配置为rpx,那么在用于传入组件大小参数为数值时,就默认为rpx
|
||||
unit: 'px'
|
||||
}
|
||||
32
uni_modules/uv-ui-tools/libs/css/color.scss
Normal file
32
uni_modules/uv-ui-tools/libs/css/color.scss
Normal file
@@ -0,0 +1,32 @@
|
||||
$uv-main-color: #303133 !default;
|
||||
$uv-content-color: #606266 !default;
|
||||
$uv-tips-color: #909193 !default;
|
||||
$uv-light-color: #c0c4cc !default;
|
||||
$uv-border-color: #dadbde !default;
|
||||
$uv-bg-color: #f3f4f6 !default;
|
||||
$uv-disabled-color: #c8c9cc !default;
|
||||
|
||||
$uv-primary: #3c9cff !default;
|
||||
$uv-primary-dark: #398ade !default;
|
||||
$uv-primary-disabled: #9acafc !default;
|
||||
$uv-primary-light: #ecf5ff !default;
|
||||
|
||||
$uv-warning: #f9ae3d !default;
|
||||
$uv-warning-dark: #f1a532 !default;
|
||||
$uv-warning-disabled: #f9d39b !default;
|
||||
$uv-warning-light: #fdf6ec !default;
|
||||
|
||||
$uv-success: #5ac725 !default;
|
||||
$uv-success-dark: #53c21d !default;
|
||||
$uv-success-disabled: #a9e08f !default;
|
||||
$uv-success-light: #f5fff0;
|
||||
|
||||
$uv-error: #f56c6c !default;
|
||||
$uv-error-dark: #e45656 !default;
|
||||
$uv-error-disabled: #f7b2b2 !default;
|
||||
$uv-error-light: #fef0f0 !default;
|
||||
|
||||
$uv-info: #909399 !default;
|
||||
$uv-info-dark: #767a82 !default;
|
||||
$uv-info-disabled: #c4c6c9 !default;
|
||||
$uv-info-light: #f4f4f5 !default;
|
||||
100
uni_modules/uv-ui-tools/libs/css/common.scss
Normal file
100
uni_modules/uv-ui-tools/libs/css/common.scss
Normal file
@@ -0,0 +1,100 @@
|
||||
// 超出行数,自动显示行尾省略号,最多5行
|
||||
// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
|
||||
@for $i from 1 through 5 {
|
||||
.uv-line-#{$i} {
|
||||
/* #ifdef APP-NVUE */
|
||||
// nvue下,可以直接使用lines属性,这是weex特有样式
|
||||
lines: $i;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
// vue下,单行和多行显示省略号需要单独处理
|
||||
@if $i == '1' {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
} @else {
|
||||
display: -webkit-box!important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: $i;
|
||||
-webkit-box-orient: vertical!important;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
$uv-bordercolor: #dadbde;
|
||||
@if variable-exists(uv-border-color) {
|
||||
$uv-bordercolor: $uv-border-color;
|
||||
}
|
||||
|
||||
// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
|
||||
// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
|
||||
// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
|
||||
// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
|
||||
.uv-border {
|
||||
border-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-top {
|
||||
border-top-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-top-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-left {
|
||||
border-left-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-right {
|
||||
border-right-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-right-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-bottom {
|
||||
border-bottom-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-top-bottom {
|
||||
border-top-width: 0.5px!important;
|
||||
border-bottom-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-top-style: solid;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
|
||||
.uv-reset-button {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
/* #ifndef APP-PLUS */
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
border-width: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uv-reset-button::after {
|
||||
border: none;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.uv-hover-class {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
23
uni_modules/uv-ui-tools/libs/css/components.scss
Normal file
23
uni_modules/uv-ui-tools/libs/css/components.scss
Normal file
@@ -0,0 +1,23 @@
|
||||
@mixin flex($direction: row) {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: $direction;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
// 由于uvui是基于nvue环境进行开发的,此环境中普通元素默认为flex-direction: column;
|
||||
// 所以在非nvue中,需要对元素进行重置为flex-direction: column; 否则可能会表现异常
|
||||
$uvui-nvue-style: true !default;
|
||||
@if $uvui-nvue-style == true {
|
||||
view, scroll-view, swiper-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: auto;
|
||||
align-items: stretch;
|
||||
align-content: flex-start;
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
111
uni_modules/uv-ui-tools/libs/css/variable.scss
Normal file
111
uni_modules/uv-ui-tools/libs/css/variable.scss
Normal file
@@ -0,0 +1,111 @@
|
||||
// 超出行数,自动显示行尾省略号,最多5行
|
||||
// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
|
||||
@if variable-exists(show-lines) {
|
||||
@for $i from 1 through 5 {
|
||||
.uv-line-#{$i} {
|
||||
/* #ifdef APP-NVUE */
|
||||
// nvue下,可以直接使用lines属性,这是weex特有样式
|
||||
lines: $i;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
// vue下,单行和多行显示省略号需要单独处理
|
||||
@if $i == '1' {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
} @else {
|
||||
display: -webkit-box!important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: $i;
|
||||
-webkit-box-orient: vertical!important;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border) {
|
||||
$uv-bordercolor: #dadbde;
|
||||
@if variable-exists(uv-border-color) {
|
||||
$uv-bordercolor: $uv-border-color;
|
||||
}
|
||||
// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
|
||||
// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
|
||||
// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
|
||||
// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
|
||||
@if variable-exists(show-border-surround) {
|
||||
.uv-border {
|
||||
border-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-top) {
|
||||
.uv-border-top {
|
||||
border-top-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-top-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-left) {
|
||||
.uv-border-left {
|
||||
border-left-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-left-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-right) {
|
||||
.uv-border-right {
|
||||
border-right-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-right-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-bottom) {
|
||||
.uv-border-bottom {
|
||||
border-bottom-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-top-bottom) {
|
||||
.uv-border-top-bottom {
|
||||
border-top-width: 0.5px!important;
|
||||
border-bottom-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-top-style: solid;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-reset-button) {
|
||||
// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
|
||||
.uv-reset-button {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
/* #ifndef APP-PLUS */
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
border-width: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uv-reset-button::after {
|
||||
border: none;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
@if variable-exists(show-hover) {
|
||||
.uv-hover-class {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
40
uni_modules/uv-ui-tools/libs/css/vue.scss
Normal file
40
uni_modules/uv-ui-tools/libs/css/vue.scss
Normal file
@@ -0,0 +1,40 @@
|
||||
// 历遍生成4个方向的底部安全区
|
||||
@each $d in top, right, bottom, left {
|
||||
.uv-safe-area-inset-#{$d} {
|
||||
padding-#{$d}: 0;
|
||||
padding-#{$d}: constant(safe-area-inset-#{$d});
|
||||
padding-#{$d}: env(safe-area-inset-#{$d});
|
||||
}
|
||||
}
|
||||
|
||||
//提升H5端uni.toast()的层级,避免被uvui的modal等遮盖
|
||||
/* #ifdef H5 */
|
||||
uni-toast {
|
||||
z-index: 10090;
|
||||
}
|
||||
uni-toast .uni-toast {
|
||||
z-index: 10090;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
// 隐藏scroll-view的滚动条
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
$uvui-nvue-style: true !default;
|
||||
@if $uvui-nvue-style == false {
|
||||
view, scroll-view, swiper-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: auto;
|
||||
align-items: stretch;
|
||||
align-content: flex-start;
|
||||
}
|
||||
}
|
||||
134
uni_modules/uv-ui-tools/libs/function/colorGradient.js
Normal file
134
uni_modules/uv-ui-tools/libs/function/colorGradient.js
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* 求两个颜色之间的渐变值
|
||||
* @param {string} startColor 开始的颜色
|
||||
* @param {string} endColor 结束的颜色
|
||||
* @param {number} step 颜色等分的份额
|
||||
* */
|
||||
function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) {
|
||||
const startRGB = hexToRgb(startColor, false) // 转换为rgb数组模式
|
||||
const startR = startRGB[0]
|
||||
const startG = startRGB[1]
|
||||
const startB = startRGB[2]
|
||||
|
||||
const endRGB = hexToRgb(endColor, false)
|
||||
const endR = endRGB[0]
|
||||
const endG = endRGB[1]
|
||||
const endB = endRGB[2]
|
||||
|
||||
const sR = (endR - startR) / step // 总差值
|
||||
const sG = (endG - startG) / step
|
||||
const sB = (endB - startB) / step
|
||||
const colorArr = []
|
||||
for (let i = 0; i < step; i++) {
|
||||
// 计算每一步的hex值
|
||||
let hex = rgbToHex(`rgb(${Math.round((sR * i + startR))},${Math.round((sG * i + startG))},${Math.round((sB
|
||||
* i + startB))})`)
|
||||
// 确保第一个颜色值为startColor的值
|
||||
if (i === 0) hex = rgbToHex(startColor)
|
||||
// 确保最后一个颜色值为endColor的值
|
||||
if (i === step - 1) hex = rgbToHex(endColor)
|
||||
colorArr.push(hex)
|
||||
}
|
||||
return colorArr
|
||||
}
|
||||
|
||||
// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
|
||||
function hexToRgb(sColor, str = true) {
|
||||
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
|
||||
sColor = String(sColor).toLowerCase()
|
||||
if (sColor && reg.test(sColor)) {
|
||||
if (sColor.length === 4) {
|
||||
let sColorNew = '#'
|
||||
for (let i = 1; i < 4; i += 1) {
|
||||
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
|
||||
}
|
||||
sColor = sColorNew
|
||||
}
|
||||
// 处理六位的颜色值
|
||||
const sColorChange = []
|
||||
for (let i = 1; i < 7; i += 2) {
|
||||
sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
|
||||
}
|
||||
if (!str) {
|
||||
return sColorChange
|
||||
}
|
||||
return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`
|
||||
} if (/^(rgb|RGB)/.test(sColor)) {
|
||||
const arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
|
||||
return arr.map((val) => Number(val))
|
||||
}
|
||||
return sColor
|
||||
}
|
||||
|
||||
// 将rgb表示方式转换为hex表示方式
|
||||
function rgbToHex(rgb) {
|
||||
const _this = rgb
|
||||
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
|
||||
if (/^(rgb|RGB)/.test(_this)) {
|
||||
const aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
|
||||
let strHex = '#'
|
||||
for (let i = 0; i < aColor.length; i++) {
|
||||
let hex = Number(aColor[i]).toString(16)
|
||||
hex = String(hex).length == 1 ? `${0}${hex}` : hex // 保证每个rgb的值为2位
|
||||
if (hex === '0') {
|
||||
hex += hex
|
||||
}
|
||||
strHex += hex
|
||||
}
|
||||
if (strHex.length !== 7) {
|
||||
strHex = _this
|
||||
}
|
||||
return strHex
|
||||
} if (reg.test(_this)) {
|
||||
const aNum = _this.replace(/#/, '').split('')
|
||||
if (aNum.length === 6) {
|
||||
return _this
|
||||
} if (aNum.length === 3) {
|
||||
let numHex = '#'
|
||||
for (let i = 0; i < aNum.length; i += 1) {
|
||||
numHex += (aNum[i] + aNum[i])
|
||||
}
|
||||
return numHex
|
||||
}
|
||||
} else {
|
||||
return _this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串
|
||||
* sHex为传入的十六进制的色值
|
||||
* alpha为rgba的透明度
|
||||
*/
|
||||
function colorToRgba(color, alpha) {
|
||||
color = rgbToHex(color)
|
||||
// 十六进制颜色值的正则表达式
|
||||
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
|
||||
/* 16进制颜色转为RGB格式 */
|
||||
let sColor = String(color).toLowerCase()
|
||||
if (sColor && reg.test(sColor)) {
|
||||
if (sColor.length === 4) {
|
||||
let sColorNew = '#'
|
||||
for (let i = 1; i < 4; i += 1) {
|
||||
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
|
||||
}
|
||||
sColor = sColorNew
|
||||
}
|
||||
// 处理六位的颜色值
|
||||
const sColorChange = []
|
||||
for (let i = 1; i < 7; i += 2) {
|
||||
sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
|
||||
}
|
||||
// return sColorChange.join(',')
|
||||
return `rgba(${sColorChange.join(',')},${alpha})`
|
||||
}
|
||||
|
||||
return sColor
|
||||
}
|
||||
|
||||
export {
|
||||
colorGradient,
|
||||
hexToRgb,
|
||||
rgbToHex,
|
||||
colorToRgba
|
||||
}
|
||||
29
uni_modules/uv-ui-tools/libs/function/debounce.js
Normal file
29
uni_modules/uv-ui-tools/libs/function/debounce.js
Normal file
@@ -0,0 +1,29 @@
|
||||
let timeout = null
|
||||
|
||||
/**
|
||||
* 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
|
||||
*
|
||||
* @param {Function} func 要执行的回调函数
|
||||
* @param {Number} wait 延时的时间
|
||||
* @param {Boolean} immediate 是否立即执行
|
||||
* @return null
|
||||
*/
|
||||
function debounce(func, wait = 500, immediate = false) {
|
||||
// 清除定时器
|
||||
if (timeout !== null) clearTimeout(timeout)
|
||||
// 立即执行,此类情况一般用不到
|
||||
if (immediate) {
|
||||
const callNow = !timeout
|
||||
timeout = setTimeout(() => {
|
||||
timeout = null
|
||||
}, wait)
|
||||
if (callNow) typeof func === 'function' && func()
|
||||
} else {
|
||||
// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
|
||||
timeout = setTimeout(() => {
|
||||
typeof func === 'function' && func()
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
|
||||
export default debounce
|
||||
167
uni_modules/uv-ui-tools/libs/function/digit.js
Normal file
167
uni_modules/uv-ui-tools/libs/function/digit.js
Normal file
@@ -0,0 +1,167 @@
|
||||
let _boundaryCheckingState = true; // 是否进行越界检查的全局开关
|
||||
|
||||
/**
|
||||
* 把错误的数据转正
|
||||
* @private
|
||||
* @example strip(0.09999999999999998)=0.1
|
||||
*/
|
||||
function strip(num, precision = 15) {
|
||||
return +parseFloat(Number(num).toPrecision(precision));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return digits length of a number
|
||||
* @private
|
||||
* @param {*number} num Input number
|
||||
*/
|
||||
function digitLength(num) {
|
||||
// Get digit length of e
|
||||
const eSplit = num.toString().split(/[eE]/);
|
||||
const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
|
||||
return len > 0 ? len : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把小数转成整数,如果是小数则放大成整数
|
||||
* @private
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function float2Fixed(num) {
|
||||
if (num.toString().indexOf('e') === -1) {
|
||||
return Number(num.toString().replace('.', ''));
|
||||
}
|
||||
const dLen = digitLength(num);
|
||||
return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测数字是否越界,如果越界给出提示
|
||||
* @private
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function checkBoundary(num) {
|
||||
if (_boundaryCheckingState) {
|
||||
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
|
||||
console.warn(`${num} 超出了精度限制,结果可能不正确`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把递归操作扁平迭代化
|
||||
* @param {number[]} arr 要操作的数字数组
|
||||
* @param {function} operation 迭代操作
|
||||
* @private
|
||||
*/
|
||||
function iteratorOperation(arr, operation) {
|
||||
const [num1, num2, ...others] = arr;
|
||||
let res = operation(num1, num2);
|
||||
|
||||
others.forEach((num) => {
|
||||
res = operation(res, num);
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度乘法
|
||||
* @export
|
||||
*/
|
||||
export function times(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, times);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const num1Changed = float2Fixed(num1);
|
||||
const num2Changed = float2Fixed(num2);
|
||||
const baseNum = digitLength(num1) + digitLength(num2);
|
||||
const leftValue = num1Changed * num2Changed;
|
||||
|
||||
checkBoundary(leftValue);
|
||||
|
||||
return leftValue / Math.pow(10, baseNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度加法
|
||||
* @export
|
||||
*/
|
||||
export function plus(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, plus);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
// 取最大的小数位
|
||||
const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
|
||||
// 把小数都转为整数然后再计算
|
||||
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度减法
|
||||
* @export
|
||||
*/
|
||||
export function minus(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, minus);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
|
||||
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度除法
|
||||
* @export
|
||||
*/
|
||||
export function divide(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, divide);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const num1Changed = float2Fixed(num1);
|
||||
const num2Changed = float2Fixed(num2);
|
||||
checkBoundary(num1Changed);
|
||||
checkBoundary(num2Changed);
|
||||
// 重要,这里必须用strip进行修正
|
||||
return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
|
||||
}
|
||||
|
||||
/**
|
||||
* 四舍五入
|
||||
* @export
|
||||
*/
|
||||
export function round(num, ratio) {
|
||||
const base = Math.pow(10, ratio);
|
||||
let result = divide(Math.round(Math.abs(times(num, base))), base);
|
||||
if (num < 0 && result !== 0) {
|
||||
result = times(result, -1);
|
||||
}
|
||||
// 位数不足则补0
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否进行边界检查,默认开启
|
||||
* @param flag 标记开关,true 为开启,false 为关闭,默认为 true
|
||||
* @export
|
||||
*/
|
||||
export function enableBoundaryChecking(flag = true) {
|
||||
_boundaryCheckingState = flag;
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
times,
|
||||
plus,
|
||||
minus,
|
||||
divide,
|
||||
round,
|
||||
enableBoundaryChecking,
|
||||
};
|
||||
|
||||
734
uni_modules/uv-ui-tools/libs/function/index.js
Normal file
734
uni_modules/uv-ui-tools/libs/function/index.js
Normal file
@@ -0,0 +1,734 @@
|
||||
import { number, empty } from './test.js'
|
||||
import { round } from './digit.js'
|
||||
/**
|
||||
* @description 如果value小于min,取min;如果value大于max,取max
|
||||
* @param {number} min
|
||||
* @param {number} max
|
||||
* @param {number} value
|
||||
*/
|
||||
function range(min = 0, max = 0, value = 0) {
|
||||
return Math.max(min, Math.min(max, Number(value)))
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 用于获取用户传递值的px值 如果用户传递了"xxpx"或者"xxrpx",取出其数值部分,如果是"xxxrpx"还需要用过uni.upx2px进行转换
|
||||
* @param {number|string} value 用户传递值的px值
|
||||
* @param {boolean} unit
|
||||
* @returns {number|string}
|
||||
*/
|
||||
function getPx(value, unit = false) {
|
||||
if (number(value)) {
|
||||
return unit ? `${value}px` : Number(value)
|
||||
}
|
||||
// 如果带有rpx,先取出其数值部分,再转为px值
|
||||
if (/(rpx|upx)$/.test(value)) {
|
||||
return unit ? `${uni.upx2px(parseInt(value))}px` : Number(uni.upx2px(parseInt(value)))
|
||||
}
|
||||
return unit ? `${parseInt(value)}px` : parseInt(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 进行延时,以达到可以简写代码的目的 比如: await uni.$uv.sleep(20)将会阻塞20ms
|
||||
* @param {number} value 堵塞时间 单位ms 毫秒
|
||||
* @returns {Promise} 返回promise
|
||||
*/
|
||||
function sleep(value = 30) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve()
|
||||
}, value)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description 运行期判断平台
|
||||
* @returns {string} 返回所在平台(小写)
|
||||
* @link 运行期判断平台 https://uniapp.dcloud.io/frame?id=判断平台
|
||||
*/
|
||||
function os() {
|
||||
return uni.getSystemInfoSync().platform.toLowerCase()
|
||||
}
|
||||
/**
|
||||
* @description 获取系统信息同步接口
|
||||
* @link 获取系统信息同步接口 https://uniapp.dcloud.io/api/system/info?id=getsysteminfosync
|
||||
*/
|
||||
function sys() {
|
||||
return uni.getSystemInfoSync()
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 取一个区间数
|
||||
* @param {Number} min 最小值
|
||||
* @param {Number} max 最大值
|
||||
*/
|
||||
function random(min, max) {
|
||||
if (min >= 0 && max > 0 && max >= min) {
|
||||
const gab = max - min + 1
|
||||
return Math.floor(Math.random() * gab + min)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} len uuid的长度
|
||||
* @param {Boolean} firstU 将返回的首字母置为"u"
|
||||
* @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
|
||||
*/
|
||||
function guid(len = 32, firstU = true, radix = null) {
|
||||
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
|
||||
const uuid = []
|
||||
radix = radix || chars.length
|
||||
|
||||
if (len) {
|
||||
// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
|
||||
for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
|
||||
} else {
|
||||
let r
|
||||
// rfc4122标准要求返回的uuid中,某些位为固定的字符
|
||||
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
|
||||
uuid[14] = '4'
|
||||
|
||||
for (let i = 0; i < 36; i++) {
|
||||
if (!uuid[i]) {
|
||||
r = 0 | Math.random() * 16
|
||||
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
|
||||
}
|
||||
}
|
||||
}
|
||||
// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
|
||||
if (firstU) {
|
||||
uuid.shift()
|
||||
return `u${uuid.join('')}`
|
||||
}
|
||||
return uuid.join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
|
||||
this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
|
||||
这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name
|
||||
值(默认为undefined),就是查找最顶层的$parent
|
||||
* @param {string|undefined} name 父组件的参数名
|
||||
*/
|
||||
function $parent(name = undefined) {
|
||||
let parent = this.$parent
|
||||
// 通过while历遍,这里主要是为了H5需要多层解析的问题
|
||||
while (parent) {
|
||||
// 父组件
|
||||
if (parent.$options && parent.$options.name !== name) {
|
||||
// 如果组件的name不相等,继续上一级寻找
|
||||
parent = parent.$parent
|
||||
} else {
|
||||
return parent
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 样式转换
|
||||
* 对象转字符串,或者字符串转对象
|
||||
* @param {object | string} customStyle 需要转换的目标
|
||||
* @param {String} target 转换的目的,object-转为对象,string-转为字符串
|
||||
* @returns {object|string}
|
||||
*/
|
||||
function addStyle(customStyle, target = 'object') {
|
||||
// 字符串转字符串,对象转对象情形,直接返回
|
||||
if (empty(customStyle) || typeof(customStyle) === 'object' && target === 'object' || target === 'string' &&
|
||||
typeof(customStyle) === 'string') {
|
||||
return customStyle
|
||||
}
|
||||
// 字符串转对象
|
||||
if (target === 'object') {
|
||||
// 去除字符串样式中的两端空格(中间的空格不能去掉,比如padding: 20px 0如果去掉了就错了),空格是无用的
|
||||
customStyle = trim(customStyle)
|
||||
// 根据";"将字符串转为数组形式
|
||||
const styleArray = customStyle.split(';')
|
||||
const style = {}
|
||||
// 历遍数组,拼接成对象
|
||||
for (let i = 0; i < styleArray.length; i++) {
|
||||
// 'font-size:20px;color:red;',如此最后字符串有";"的话,会导致styleArray最后一个元素为空字符串,这里需要过滤
|
||||
if (styleArray[i]) {
|
||||
const item = styleArray[i].split(':')
|
||||
style[trim(item[0])] = trim(item[1])
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
// 这里为对象转字符串形式
|
||||
let string = ''
|
||||
for (const i in customStyle) {
|
||||
// 驼峰转为中划线的形式,否则css内联样式,无法识别驼峰样式属性名
|
||||
const key = i.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||
string += `${key}:${customStyle[i]};`
|
||||
}
|
||||
// 去除两端空格
|
||||
return trim(string)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 添加单位,如果有rpx,upx,%,px等单位结尾或者值为auto,直接返回,否则加上px单位结尾
|
||||
* @param {string|number} value 需要添加单位的值
|
||||
* @param {string} unit 添加的单位名 比如px
|
||||
*/
|
||||
function addUnit(value = 'auto', unit = uni?.$uv?.config?.unit ? uni?.$uv?.config?.unit : 'px') {
|
||||
value = String(value)
|
||||
// 用uvui内置验证规则中的number判断是否为数值
|
||||
return number(value) ? `${value}${unit}` : value
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 深度克隆
|
||||
* @param {object} obj 需要深度克隆的对象
|
||||
* @param cache 缓存
|
||||
* @returns {*} 克隆后的对象或者原值(不是对象)
|
||||
*/
|
||||
function deepClone(obj, cache = new WeakMap()) {
|
||||
if (obj === null || typeof obj !== 'object') return obj;
|
||||
if (cache.has(obj)) return cache.get(obj);
|
||||
let clone;
|
||||
if (obj instanceof Date) {
|
||||
clone = new Date(obj.getTime());
|
||||
} else if (obj instanceof RegExp) {
|
||||
clone = new RegExp(obj);
|
||||
} else if (obj instanceof Map) {
|
||||
clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
|
||||
} else if (obj instanceof Set) {
|
||||
clone = new Set(Array.from(obj, value => deepClone(value, cache)));
|
||||
} else if (Array.isArray(obj)) {
|
||||
clone = obj.map(value => deepClone(value, cache));
|
||||
} else if (Object.prototype.toString.call(obj) === '[object Object]') {
|
||||
clone = Object.create(Object.getPrototypeOf(obj));
|
||||
cache.set(obj, clone);
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
clone[key] = deepClone(value, cache);
|
||||
}
|
||||
} else {
|
||||
clone = Object.assign({}, obj);
|
||||
}
|
||||
cache.set(obj, clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description JS对象深度合并
|
||||
* @param {object} target 需要拷贝的对象
|
||||
* @param {object} source 拷贝的来源对象
|
||||
* @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
|
||||
*/
|
||||
function deepMerge(target = {}, source = {}) {
|
||||
target = deepClone(target)
|
||||
if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
|
||||
const merged = Array.isArray(target) ? target.slice() : Object.assign({}, target);
|
||||
for (const prop in source) {
|
||||
if (!source.hasOwnProperty(prop)) continue;
|
||||
const sourceValue = source[prop];
|
||||
const targetValue = merged[prop];
|
||||
if (sourceValue instanceof Date) {
|
||||
merged[prop] = new Date(sourceValue);
|
||||
} else if (sourceValue instanceof RegExp) {
|
||||
merged[prop] = new RegExp(sourceValue);
|
||||
} else if (sourceValue instanceof Map) {
|
||||
merged[prop] = new Map(sourceValue);
|
||||
} else if (sourceValue instanceof Set) {
|
||||
merged[prop] = new Set(sourceValue);
|
||||
} else if (typeof sourceValue === 'object' && sourceValue !== null) {
|
||||
merged[prop] = deepMerge(targetValue, sourceValue);
|
||||
} else {
|
||||
merged[prop] = sourceValue;
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description error提示
|
||||
* @param {*} err 错误内容
|
||||
*/
|
||||
function error(err) {
|
||||
// 开发环境才提示,生产环境不会提示
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.error(`uvui提示:${err}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 打乱数组
|
||||
* @param {array} array 需要打乱的数组
|
||||
* @returns {array} 打乱后的数组
|
||||
*/
|
||||
function randomArray(array = []) {
|
||||
// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
|
||||
return array.sort(() => Math.random() - 0.5)
|
||||
}
|
||||
|
||||
// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
|
||||
// 所以这里做一个兼容polyfill的兼容处理
|
||||
if (!String.prototype.padStart) {
|
||||
// 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
|
||||
String.prototype.padStart = function(maxLength, fillString = ' ') {
|
||||
if (Object.prototype.toString.call(fillString) !== '[object String]') {
|
||||
throw new TypeError(
|
||||
'fillString must be String'
|
||||
)
|
||||
}
|
||||
const str = this
|
||||
// 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
|
||||
if (str.length >= maxLength) return String(str)
|
||||
|
||||
const fillLength = maxLength - str.length
|
||||
let times = Math.ceil(fillLength / fillString.length)
|
||||
while (times >>= 1) {
|
||||
fillString += fillString
|
||||
if (times === 1) {
|
||||
fillString += fillString
|
||||
}
|
||||
}
|
||||
return fillString.slice(0, fillLength) + str
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 格式化时间
|
||||
* @param {String|Number} dateTime 需要格式化的时间戳
|
||||
* @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
|
||||
* @returns {string} 返回格式化后的字符串
|
||||
*/
|
||||
function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
|
||||
let date
|
||||
// 若传入时间为假值,则取当前时间
|
||||
if (!dateTime) {
|
||||
date = new Date()
|
||||
}
|
||||
// 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
|
||||
else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
|
||||
date = new Date(dateTime * 1000)
|
||||
}
|
||||
// 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
|
||||
else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
|
||||
date = new Date(Number(dateTime))
|
||||
}
|
||||
// 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
|
||||
// 处理 '2022-07-10 01:02:03',跳过 '2022-07-10T01:02:03'
|
||||
else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) {
|
||||
date = new Date(dateTime.replace(/-/g, '/'))
|
||||
}
|
||||
// 其他都认为符合 RFC 2822 规范
|
||||
else {
|
||||
date = new Date(dateTime)
|
||||
}
|
||||
|
||||
const timeSource = {
|
||||
'y': date.getFullYear().toString(), // 年
|
||||
'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
|
||||
'd': date.getDate().toString().padStart(2, '0'), // 日
|
||||
'h': date.getHours().toString().padStart(2, '0'), // 时
|
||||
'M': date.getMinutes().toString().padStart(2, '0'), // 分
|
||||
's': date.getSeconds().toString().padStart(2, '0') // 秒
|
||||
// 有其他格式化字符需求可以继续添加,必须转化成字符串
|
||||
}
|
||||
|
||||
for (const key in timeSource) {
|
||||
const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
|
||||
if (ret) {
|
||||
// 年可能只需展示两位
|
||||
const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
|
||||
formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
|
||||
}
|
||||
}
|
||||
|
||||
return formatStr
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 时间戳转为多久之前
|
||||
* @param {String|Number} timestamp 时间戳
|
||||
* @param {String|Boolean} format
|
||||
* 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
|
||||
* 如果为布尔值false,无论什么时间,都返回多久以前的格式
|
||||
* @returns {string} 转化后的内容
|
||||
*/
|
||||
function timeFrom(timestamp = null, format = 'yyyy-mm-dd') {
|
||||
if (timestamp == null) timestamp = Number(new Date())
|
||||
timestamp = parseInt(timestamp)
|
||||
// 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
|
||||
if (timestamp.toString().length == 10) timestamp *= 1000
|
||||
let timer = (new Date()).getTime() - timestamp
|
||||
timer = parseInt(timer / 1000)
|
||||
// 如果小于5分钟,则返回"刚刚",其他以此类推
|
||||
let tips = ''
|
||||
switch (true) {
|
||||
case timer < 300:
|
||||
tips = '刚刚'
|
||||
break
|
||||
case timer >= 300 && timer < 3600:
|
||||
tips = `${parseInt(timer / 60)}分钟前`
|
||||
break
|
||||
case timer >= 3600 && timer < 86400:
|
||||
tips = `${parseInt(timer / 3600)}小时前`
|
||||
break
|
||||
case timer >= 86400 && timer < 2592000:
|
||||
tips = `${parseInt(timer / 86400)}天前`
|
||||
break
|
||||
default:
|
||||
// 如果format为false,则无论什么时间戳,都显示xx之前
|
||||
if (format === false) {
|
||||
if (timer >= 2592000 && timer < 365 * 86400) {
|
||||
tips = `${parseInt(timer / (86400 * 30))}个月前`
|
||||
} else {
|
||||
tips = `${parseInt(timer / (86400 * 365))}年前`
|
||||
}
|
||||
} else {
|
||||
tips = timeFormat(timestamp, format)
|
||||
}
|
||||
}
|
||||
return tips
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 去除空格
|
||||
* @param String str 需要去除空格的字符串
|
||||
* @param String pos both(左右)|left|right|all 默认both
|
||||
*/
|
||||
function trim(str, pos = 'both') {
|
||||
str = String(str)
|
||||
if (pos == 'both') {
|
||||
return str.replace(/^\s+|\s+$/g, '')
|
||||
}
|
||||
if (pos == 'left') {
|
||||
return str.replace(/^\s*/, '')
|
||||
}
|
||||
if (pos == 'right') {
|
||||
return str.replace(/(\s*$)/g, '')
|
||||
}
|
||||
if (pos == 'all') {
|
||||
return str.replace(/\s+/g, '')
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 对象转url参数
|
||||
* @param {object} data,对象
|
||||
* @param {Boolean} isPrefix,是否自动加上"?"
|
||||
* @param {string} arrayFormat 规则 indices|brackets|repeat|comma
|
||||
*/
|
||||
function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
|
||||
const prefix = isPrefix ? '?' : ''
|
||||
const _result = []
|
||||
if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'
|
||||
for (const key in data) {
|
||||
const value = data[key]
|
||||
// 去掉为空的参数
|
||||
if (['', undefined, null].indexOf(value) >= 0) {
|
||||
continue
|
||||
}
|
||||
// 如果值为数组,另行处理
|
||||
if (value.constructor === Array) {
|
||||
// e.g. {ids: [1, 2, 3]}
|
||||
switch (arrayFormat) {
|
||||
case 'indices':
|
||||
// 结果: ids[0]=1&ids[1]=2&ids[2]=3
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
_result.push(`${key}[${i}]=${value[i]}`)
|
||||
}
|
||||
break
|
||||
case 'brackets':
|
||||
// 结果: ids[]=1&ids[]=2&ids[]=3
|
||||
value.forEach((_value) => {
|
||||
_result.push(`${key}[]=${_value}`)
|
||||
})
|
||||
break
|
||||
case 'repeat':
|
||||
// 结果: ids=1&ids=2&ids=3
|
||||
value.forEach((_value) => {
|
||||
_result.push(`${key}=${_value}`)
|
||||
})
|
||||
break
|
||||
case 'comma':
|
||||
// 结果: ids=1,2,3
|
||||
let commaStr = ''
|
||||
value.forEach((_value) => {
|
||||
commaStr += (commaStr ? ',' : '') + _value
|
||||
})
|
||||
_result.push(`${key}=${commaStr}`)
|
||||
break
|
||||
default:
|
||||
value.forEach((_value) => {
|
||||
_result.push(`${key}[]=${_value}`)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
_result.push(`${key}=${value}`)
|
||||
}
|
||||
}
|
||||
return _result.length ? prefix + _result.join('&') : ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示消息提示框
|
||||
* @param {String} title 提示的内容,长度与 icon 取值有关。
|
||||
* @param {Number} duration 提示的延迟时间,单位毫秒,默认:2000
|
||||
*/
|
||||
function toast(title, duration = 2000) {
|
||||
uni.showToast({
|
||||
title: String(title),
|
||||
icon: 'none',
|
||||
duration
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 根据主题type值,获取对应的图标
|
||||
* @param {String} type 主题名称,primary|info|error|warning|success
|
||||
* @param {boolean} fill 是否使用fill填充实体的图标
|
||||
*/
|
||||
function type2icon(type = 'success', fill = false) {
|
||||
// 如果非预置值,默认为success
|
||||
if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success'
|
||||
let iconName = ''
|
||||
// 目前(2019-12-12),info和primary使用同一个图标
|
||||
switch (type) {
|
||||
case 'primary':
|
||||
iconName = 'info-circle'
|
||||
break
|
||||
case 'info':
|
||||
iconName = 'info-circle'
|
||||
break
|
||||
case 'error':
|
||||
iconName = 'close-circle'
|
||||
break
|
||||
case 'warning':
|
||||
iconName = 'error-circle'
|
||||
break
|
||||
case 'success':
|
||||
iconName = 'checkmark-circle'
|
||||
break
|
||||
default:
|
||||
iconName = 'checkmark-circle'
|
||||
}
|
||||
// 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
|
||||
if (fill) iconName += '-fill'
|
||||
return iconName
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 数字格式化
|
||||
* @param {number|string} number 要格式化的数字
|
||||
* @param {number} decimals 保留几位小数
|
||||
* @param {string} decimalPoint 小数点符号
|
||||
* @param {string} thousandsSeparator 千分位符号
|
||||
* @returns {string} 格式化后的数字
|
||||
*/
|
||||
function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') {
|
||||
number = (`${number}`).replace(/[^0-9+-Ee.]/g, '')
|
||||
const n = !isFinite(+number) ? 0 : +number
|
||||
const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
|
||||
const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator
|
||||
const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint
|
||||
let s = ''
|
||||
|
||||
s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.')
|
||||
const re = /(-?\d+)(\d{3})/
|
||||
while (re.test(s[0])) {
|
||||
s[0] = s[0].replace(re, `$1${sep}$2`)
|
||||
}
|
||||
|
||||
if ((s[1] || '').length < prec) {
|
||||
s[1] = s[1] || ''
|
||||
s[1] += new Array(prec - s[1].length + 1).join('0')
|
||||
}
|
||||
return s.join(dec)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取duration值
|
||||
* 如果带有ms或者s直接返回,如果大于一定值,认为是ms单位,小于一定值,认为是s单位
|
||||
* 比如以30位阈值,那么300大于30,可以理解为用户想要的是300ms,而不是想花300s去执行一个动画
|
||||
* @param {String|number} value 比如: "1s"|"100ms"|1|100
|
||||
* @param {boolean} unit 提示: 如果是false 默认返回number
|
||||
* @return {string|number}
|
||||
*/
|
||||
function getDuration(value, unit = true) {
|
||||
const valueNum = parseInt(value)
|
||||
if (unit) {
|
||||
if (/s$/.test(value)) return value
|
||||
return value > 30 ? `${value}ms` : `${value}s`
|
||||
}
|
||||
if (/ms$/.test(value)) return valueNum
|
||||
if (/s$/.test(value)) return valueNum > 30 ? valueNum : valueNum * 1000
|
||||
return valueNum
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 日期的月或日补零操作
|
||||
* @param {String} value 需要补零的值
|
||||
*/
|
||||
function padZero(value) {
|
||||
return `00${value}`.slice(-2)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 在uv-form的子组件内容发生变化,或者失去焦点时,尝试通知uv-form执行校验方法
|
||||
* @param {*} instance
|
||||
* @param {*} event
|
||||
*/
|
||||
function formValidate(instance, event) {
|
||||
const formItem = $parent.call(instance, 'uv-form-item')
|
||||
const form = $parent.call(instance, 'uv-form')
|
||||
// 如果发生变化的input或者textarea等,其父组件中有uv-form-item或者uv-form等,就执行form的validate方法
|
||||
// 同时将form-item的pros传递给form,让其进行精确对象验证
|
||||
if (formItem && form) {
|
||||
form.validateField(formItem.prop, () => {}, event)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取某个对象下的属性,用于通过类似'a.b.c'的形式去获取一个对象的的属性的形式
|
||||
* @param {object} obj 对象
|
||||
* @param {string} key 需要获取的属性字段
|
||||
* @returns {*}
|
||||
*/
|
||||
function getProperty(obj, key) {
|
||||
if (!obj) {
|
||||
return
|
||||
}
|
||||
if (typeof key !== 'string' || key === '') {
|
||||
return ''
|
||||
}
|
||||
if (key.indexOf('.') !== -1) {
|
||||
const keys = key.split('.')
|
||||
let firstObj = obj[keys[0]] || {}
|
||||
|
||||
for (let i = 1; i < keys.length; i++) {
|
||||
if (firstObj) {
|
||||
firstObj = firstObj[keys[i]]
|
||||
}
|
||||
}
|
||||
return firstObj
|
||||
}
|
||||
return obj[key]
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 设置对象的属性值,如果'a.b.c'的形式进行设置
|
||||
* @param {object} obj 对象
|
||||
* @param {string} key 需要设置的属性
|
||||
* @param {string} value 设置的值
|
||||
*/
|
||||
function setProperty(obj, key, value) {
|
||||
if (!obj) {
|
||||
return
|
||||
}
|
||||
// 递归赋值
|
||||
const inFn = function(_obj, keys, v) {
|
||||
// 最后一个属性key
|
||||
if (keys.length === 1) {
|
||||
_obj[keys[0]] = v
|
||||
return
|
||||
}
|
||||
// 0~length-1个key
|
||||
while (keys.length > 1) {
|
||||
const k = keys[0]
|
||||
if (!_obj[k] || (typeof _obj[k] !== 'object')) {
|
||||
_obj[k] = {}
|
||||
}
|
||||
const key = keys.shift()
|
||||
// 自调用判断是否存在属性,不存在则自动创建对象
|
||||
inFn(_obj[k], keys, v)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof key !== 'string' || key === '') {
|
||||
|
||||
} else if (key.indexOf('.') !== -1) { // 支持多层级赋值操作
|
||||
const keys = key.split('.')
|
||||
inFn(obj, keys, value)
|
||||
} else {
|
||||
obj[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取当前页面路径
|
||||
*/
|
||||
function page() {
|
||||
const pages = getCurrentPages();
|
||||
const route = pages[pages.length - 1]?.route;
|
||||
// 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
|
||||
return `/${route ? route : ''}`
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取当前路由栈实例数组
|
||||
*/
|
||||
function pages() {
|
||||
const pages = getCurrentPages()
|
||||
return pages
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取页面历史栈指定层实例
|
||||
* @param back {number} [0] - 0或者负数,表示获取历史栈的哪一层,0表示获取当前页面实例,-1 表示获取上一个页面实例。默认0。
|
||||
*/
|
||||
function getHistoryPage(back = 0) {
|
||||
const pages = getCurrentPages()
|
||||
const len = pages.length
|
||||
return pages[len - 1 + back]
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @description 修改uvui内置属性值
|
||||
* @param {object} props 修改内置props属性
|
||||
* @param {object} config 修改内置config属性
|
||||
* @param {object} color 修改内置color属性
|
||||
* @param {object} zIndex 修改内置zIndex属性
|
||||
*/
|
||||
function setConfig({
|
||||
props = {},
|
||||
config = {},
|
||||
color = {},
|
||||
zIndex = {}
|
||||
}) {
|
||||
const {
|
||||
deepMerge,
|
||||
} = uni.$uv
|
||||
uni.$uv.config = deepMerge(uni.$uv.config, config)
|
||||
uni.$uv.props = deepMerge(uni.$uv.props, props)
|
||||
uni.$uv.color = deepMerge(uni.$uv.color, color)
|
||||
uni.$uv.zIndex = deepMerge(uni.$uv.zIndex, zIndex)
|
||||
}
|
||||
|
||||
export {
|
||||
range,
|
||||
getPx,
|
||||
sleep,
|
||||
os,
|
||||
sys,
|
||||
random,
|
||||
guid,
|
||||
$parent,
|
||||
addStyle,
|
||||
addUnit,
|
||||
deepClone,
|
||||
deepMerge,
|
||||
error,
|
||||
randomArray,
|
||||
timeFormat,
|
||||
timeFrom,
|
||||
trim,
|
||||
queryParams,
|
||||
toast,
|
||||
type2icon,
|
||||
priceFormat,
|
||||
getDuration,
|
||||
padZero,
|
||||
formValidate,
|
||||
getProperty,
|
||||
setProperty,
|
||||
page,
|
||||
pages,
|
||||
getHistoryPage,
|
||||
setConfig
|
||||
}
|
||||
75
uni_modules/uv-ui-tools/libs/function/platform.js
Normal file
75
uni_modules/uv-ui-tools/libs/function/platform.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 注意:
|
||||
* 此部分内容,在vue-cli模式下,需要在vue.config.js加入如下内容才有效:
|
||||
* module.exports = {
|
||||
* transpileDependencies: ['uview-v2']
|
||||
* }
|
||||
*/
|
||||
|
||||
let platform = 'none'
|
||||
|
||||
// #ifdef VUE3
|
||||
platform = 'vue3'
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE2
|
||||
platform = 'vue2'
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
platform = 'plus'
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
platform = 'nvue'
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
platform = 'h5'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
platform = 'weixin'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-ALIPAY
|
||||
platform = 'alipay'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-BAIDU
|
||||
platform = 'baidu'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-TOUTIAO
|
||||
platform = 'toutiao'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-QQ
|
||||
platform = 'qq'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-KUAISHOU
|
||||
platform = 'kuaishou'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-360
|
||||
platform = '360'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
platform = 'mp'
|
||||
// #endif
|
||||
|
||||
// #ifdef QUICKAPP-WEBVIEW
|
||||
platform = 'quickapp-webview'
|
||||
// #endif
|
||||
|
||||
// #ifdef QUICKAPP-WEBVIEW-HUAWEI
|
||||
platform = 'quickapp-webview-huawei'
|
||||
// #endif
|
||||
|
||||
// #ifdef QUICKAPP-WEBVIEW-UNION
|
||||
platform = 'quckapp-webview-union'
|
||||
// #endif
|
||||
|
||||
export default platform
|
||||
287
uni_modules/uv-ui-tools/libs/function/test.js
Normal file
287
uni_modules/uv-ui-tools/libs/function/test.js
Normal file
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* 验证电子邮箱格式
|
||||
*/
|
||||
function email(value) {
|
||||
return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证手机格式
|
||||
*/
|
||||
function mobile(value) {
|
||||
return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证URL格式
|
||||
*/
|
||||
function url(value) {
|
||||
return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
|
||||
.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证日期格式
|
||||
*/
|
||||
function date(value) {
|
||||
if (!value) return false
|
||||
// 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
|
||||
if (number(value)) value = +value
|
||||
return !/Invalid|NaN/.test(new Date(value).toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证ISO类型的日期格式
|
||||
*/
|
||||
function dateISO(value) {
|
||||
return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证十进制数字
|
||||
*/
|
||||
function number(value) {
|
||||
return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证字符串
|
||||
*/
|
||||
function string(value) {
|
||||
return typeof value === 'string'
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证整数
|
||||
*/
|
||||
function digits(value) {
|
||||
return /^\d+$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证身份证号码
|
||||
*/
|
||||
function idCard(value) {
|
||||
return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
|
||||
value
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否车牌号
|
||||
*/
|
||||
function carNo(value) {
|
||||
// 新能源车牌
|
||||
const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
|
||||
// 旧车牌
|
||||
const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/
|
||||
if (value.length === 7) {
|
||||
return creg.test(value)
|
||||
} if (value.length === 8) {
|
||||
return xreg.test(value)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额,只允许2位小数
|
||||
*/
|
||||
function amount(value) {
|
||||
// 金额,只允许保留两位小数
|
||||
return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 中文
|
||||
*/
|
||||
function chinese(value) {
|
||||
const reg = /^[\u4e00-\u9fa5]+$/gi
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能输入字母
|
||||
*/
|
||||
function letter(value) {
|
||||
return /^[a-zA-Z]*$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能是字母或者数字
|
||||
*/
|
||||
function enOrNum(value) {
|
||||
// 英文或者数字
|
||||
const reg = /^[0-9a-zA-Z]*$/g
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否包含某个值
|
||||
*/
|
||||
function contains(value, param) {
|
||||
return value.indexOf(param) >= 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证一个值范围[min, max]
|
||||
*/
|
||||
function range(value, param) {
|
||||
return value >= param[0] && value <= param[1]
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证一个长度范围[min, max]
|
||||
*/
|
||||
function rangeLength(value, param) {
|
||||
return value.length >= param[0] && value.length <= param[1]
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否固定电话
|
||||
*/
|
||||
function landline(value) {
|
||||
const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为空
|
||||
*/
|
||||
function empty(value) {
|
||||
switch (typeof value) {
|
||||
case 'undefined':
|
||||
return true
|
||||
case 'string':
|
||||
if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
|
||||
break
|
||||
case 'boolean':
|
||||
if (!value) return true
|
||||
break
|
||||
case 'number':
|
||||
if (value === 0 || isNaN(value)) return true
|
||||
break
|
||||
case 'object':
|
||||
if (value === null || value.length === 0) return true
|
||||
for (const i in value) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否json字符串
|
||||
*/
|
||||
function jsonString(value) {
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
const obj = JSON.parse(value)
|
||||
if (typeof obj === 'object' && obj) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否数组
|
||||
*/
|
||||
function array(value) {
|
||||
if (typeof Array.isArray === 'function') {
|
||||
return Array.isArray(value)
|
||||
}
|
||||
return Object.prototype.toString.call(value) === '[object Array]'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否对象
|
||||
*/
|
||||
function object(value) {
|
||||
return Object.prototype.toString.call(value) === '[object Object]'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否短信验证码
|
||||
*/
|
||||
function code(value, len = 6) {
|
||||
return new RegExp(`^\\d{${len}}$`).test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否函数方法
|
||||
* @param {Object} value
|
||||
*/
|
||||
function func(value) {
|
||||
return typeof value === 'function'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否promise对象
|
||||
* @param {Object} value
|
||||
*/
|
||||
function promise(value) {
|
||||
return object(value) && func(value.then) && func(value.catch)
|
||||
}
|
||||
|
||||
/** 是否图片格式
|
||||
* @param {Object} value
|
||||
*/
|
||||
function image(value) {
|
||||
const newValue = value.split('?')[0]
|
||||
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
|
||||
return IMAGE_REGEXP.test(newValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否视频格式
|
||||
* @param {Object} value
|
||||
*/
|
||||
function video(value) {
|
||||
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
|
||||
return VIDEO_REGEXP.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为正则对象
|
||||
* @param {Object}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function regExp(o) {
|
||||
return o && Object.prototype.toString.call(o) === '[object RegExp]'
|
||||
}
|
||||
|
||||
export {
|
||||
email,
|
||||
mobile,
|
||||
url,
|
||||
date,
|
||||
dateISO,
|
||||
number,
|
||||
digits,
|
||||
idCard,
|
||||
carNo,
|
||||
amount,
|
||||
chinese,
|
||||
letter,
|
||||
enOrNum,
|
||||
contains,
|
||||
range,
|
||||
rangeLength,
|
||||
empty,
|
||||
jsonString,
|
||||
landline,
|
||||
object,
|
||||
array,
|
||||
code,
|
||||
func,
|
||||
promise,
|
||||
video,
|
||||
image,
|
||||
regExp,
|
||||
string
|
||||
}
|
||||
30
uni_modules/uv-ui-tools/libs/function/throttle.js
Normal file
30
uni_modules/uv-ui-tools/libs/function/throttle.js
Normal file
@@ -0,0 +1,30 @@
|
||||
let timer; let
|
||||
flag
|
||||
/**
|
||||
* 节流原理:在一定时间内,只能触发一次
|
||||
*
|
||||
* @param {Function} func 要执行的回调函数
|
||||
* @param {Number} wait 延时的时间
|
||||
* @param {Boolean} immediate 是否立即执行
|
||||
* @return null
|
||||
*/
|
||||
function throttle(func, wait = 500, immediate = true) {
|
||||
if (immediate) {
|
||||
if (!flag) {
|
||||
flag = true
|
||||
// 如果是立即执行,则在wait毫秒内开始时执行
|
||||
typeof func === 'function' && func()
|
||||
timer = setTimeout(() => {
|
||||
flag = false
|
||||
}, wait)
|
||||
}
|
||||
} else if (!flag) {
|
||||
flag = true
|
||||
// 如果是非立即执行,则在wait毫秒内的结束处执行
|
||||
timer = setTimeout(() => {
|
||||
flag = false
|
||||
typeof func === 'function' && func()
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
export default throttle
|
||||
132
uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js
Normal file
132
uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js
Normal file
@@ -0,0 +1,132 @@
|
||||
import buildURL from '../helpers/buildURL'
|
||||
import buildFullPath from '../core/buildFullPath'
|
||||
import settle from '../core/settle'
|
||||
import {isUndefined} from "../utils"
|
||||
|
||||
/**
|
||||
* 返回可选值存在的配置
|
||||
* @param {Array} keys - 可选值数组
|
||||
* @param {Object} config2 - 配置
|
||||
* @return {{}} - 存在的配置项
|
||||
*/
|
||||
const mergeKeys = (keys, config2) => {
|
||||
let config = {}
|
||||
keys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
}
|
||||
})
|
||||
return config
|
||||
}
|
||||
export default (config) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
|
||||
const _config = {
|
||||
url: fullPath,
|
||||
header: config.header,
|
||||
complete: (response) => {
|
||||
config.fullPath = fullPath
|
||||
response.config = config
|
||||
response.rawData = response.data
|
||||
try {
|
||||
let jsonParseHandle = false
|
||||
const forcedJSONParsingType = typeof config.forcedJSONParsing
|
||||
if (forcedJSONParsingType === 'boolean') {
|
||||
jsonParseHandle = config.forcedJSONParsing
|
||||
} else if (forcedJSONParsingType === 'object') {
|
||||
const includesMethod = config.forcedJSONParsing.include || []
|
||||
jsonParseHandle = includesMethod.includes(config.method)
|
||||
}
|
||||
|
||||
// 对可能字符串不是json 的情况容错
|
||||
if (jsonParseHandle && typeof response.data === 'string') {
|
||||
response.data = JSON.parse(response.data)
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {
|
||||
}
|
||||
settle(resolve, reject, response)
|
||||
}
|
||||
}
|
||||
let requestTask
|
||||
if (config.method === 'UPLOAD') {
|
||||
delete _config.header['content-type']
|
||||
delete _config.header['Content-Type']
|
||||
let otherConfig = {
|
||||
// #ifdef MP-ALIPAY
|
||||
fileType: config.fileType,
|
||||
// #endif
|
||||
filePath: config.filePath,
|
||||
name: config.name
|
||||
}
|
||||
const optionalKeys = [
|
||||
// #ifdef APP-PLUS || H5
|
||||
'files',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'file',
|
||||
// #endif
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
'timeout',
|
||||
// #endif
|
||||
'formData'
|
||||
]
|
||||
requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
|
||||
} else if (config.method === 'DOWNLOAD') {
|
||||
const optionalKeys = [
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
'timeout',
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
'filePath',
|
||||
// #endif
|
||||
]
|
||||
requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
|
||||
} else {
|
||||
const optionalKeys = [
|
||||
'data',
|
||||
'method',
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
'timeout',
|
||||
// #endif
|
||||
'dataType',
|
||||
// #ifndef MP-ALIPAY
|
||||
'responseType',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'sslVerify',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'withCredentials',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'firstIpv4',
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
'enableHttp2',
|
||||
'enableQuic',
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO || MP-WEIXIN
|
||||
'enableCache',
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
'enableHttpDNS',
|
||||
'httpDNSServiceId',
|
||||
'enableChunked',
|
||||
'forceCellularNetwork',
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
'enableCookie',
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU
|
||||
'cloudCache',
|
||||
'defer'
|
||||
// #endif
|
||||
]
|
||||
requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
|
||||
}
|
||||
if (config.getTask) {
|
||||
config.getTask(requestTask, config)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
'use strict'
|
||||
|
||||
|
||||
function InterceptorManager() {
|
||||
this.handlers = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new interceptor to the stack
|
||||
*
|
||||
* @param {Function} fulfilled The function to handle `then` for a `Promise`
|
||||
* @param {Function} rejected The function to handle `reject` for a `Promise`
|
||||
*
|
||||
* @return {Number} An ID used to remove interceptor later
|
||||
*/
|
||||
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
|
||||
this.handlers.push({
|
||||
fulfilled: fulfilled,
|
||||
rejected: rejected
|
||||
})
|
||||
return this.handlers.length - 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an interceptor from the stack
|
||||
*
|
||||
* @param {Number} id The ID that was returned by `use`
|
||||
*/
|
||||
InterceptorManager.prototype.eject = function eject(id) {
|
||||
if (this.handlers[id]) {
|
||||
this.handlers[id] = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all the registered interceptors
|
||||
*
|
||||
* This method is particularly useful for skipping over any
|
||||
* interceptors that may have become `null` calling `eject`.
|
||||
*
|
||||
* @param {Function} fn The function to call for each interceptor
|
||||
*/
|
||||
InterceptorManager.prototype.forEach = function forEach(fn) {
|
||||
this.handlers.forEach(h => {
|
||||
if (h !== null) {
|
||||
fn(h)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default InterceptorManager
|
||||
201
uni_modules/uv-ui-tools/libs/luch-request/core/Request.js
Normal file
201
uni_modules/uv-ui-tools/libs/luch-request/core/Request.js
Normal file
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* @Class Request
|
||||
* @description luch-request http请求插件
|
||||
* @Author lu-ch
|
||||
* @Email webwork.s@qq.com
|
||||
* 文档: https://www.quanzhan.co/luch-request/
|
||||
* github: https://github.com/lei-mu/luch-request
|
||||
* DCloud: http://ext.dcloud.net.cn/plugin?id=392
|
||||
*/
|
||||
|
||||
|
||||
import dispatchRequest from './dispatchRequest'
|
||||
import InterceptorManager from './InterceptorManager'
|
||||
import mergeConfig from './mergeConfig'
|
||||
import defaults from './defaults'
|
||||
import { isPlainObject } from '../utils'
|
||||
import clone from '../utils/clone'
|
||||
|
||||
export default class Request {
|
||||
/**
|
||||
* @param {Object} arg - 全局配置
|
||||
* @param {String} arg.baseURL - 全局根路径
|
||||
* @param {Object} arg.header - 全局header
|
||||
* @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
|
||||
* @param {String} arg.dataType = [json] - 全局默认的dataType
|
||||
* @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
|
||||
* @param {Object} arg.custom - 全局默认的自定义参数
|
||||
* @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
|
||||
* @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
|
||||
* @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
|
||||
* @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
|
||||
* @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
|
||||
*/
|
||||
constructor(arg = {}) {
|
||||
if (!isPlainObject(arg)) {
|
||||
arg = {}
|
||||
console.warn('设置全局参数必须接收一个Object')
|
||||
}
|
||||
this.config = clone({...defaults, ...arg})
|
||||
this.interceptors = {
|
||||
request: new InterceptorManager(),
|
||||
response: new InterceptorManager()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Function
|
||||
* @param {Request~setConfigCallback} f - 设置全局默认配置
|
||||
*/
|
||||
setConfig(f) {
|
||||
this.config = f(this.config)
|
||||
}
|
||||
|
||||
middleware(config) {
|
||||
config = mergeConfig(this.config, config)
|
||||
let chain = [dispatchRequest, undefined]
|
||||
let promise = Promise.resolve(config)
|
||||
|
||||
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
|
||||
chain.unshift(interceptor.fulfilled, interceptor.rejected)
|
||||
})
|
||||
|
||||
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
|
||||
chain.push(interceptor.fulfilled, interceptor.rejected)
|
||||
})
|
||||
|
||||
while (chain.length) {
|
||||
promise = promise.then(chain.shift(), chain.shift())
|
||||
}
|
||||
|
||||
return promise
|
||||
}
|
||||
|
||||
/**
|
||||
* @Function
|
||||
* @param {Object} config - 请求配置项
|
||||
* @prop {String} options.url - 请求路径
|
||||
* @prop {Object} options.data - 请求参数
|
||||
* @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
|
||||
* @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
|
||||
* @prop {Object} [options.header = config.header] - 请求header
|
||||
* @prop {Object} [options.method = config.method] - 请求方法
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
request(config = {}) {
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
get(url, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
method: 'GET',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
post(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'POST',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
|
||||
put(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'PUT',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
|
||||
delete(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'DELETE',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN
|
||||
connect(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'CONNECT',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN || MP-BAIDU
|
||||
head(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'HEAD',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
|
||||
options(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'OPTIONS',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN
|
||||
trace(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'TRACE',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
upload(url, config = {}) {
|
||||
config.url = url
|
||||
config.method = 'UPLOAD'
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
download(url, config = {}) {
|
||||
config.url = url
|
||||
config.method = 'DOWNLOAD'
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
get version () {
|
||||
return '3.1.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* setConfig回调
|
||||
* @return {Object} - 返回操作后的config
|
||||
* @callback Request~setConfigCallback
|
||||
* @param {Object} config - 全局默认config
|
||||
*/
|
||||
@@ -0,0 +1,20 @@
|
||||
'use strict'
|
||||
|
||||
import isAbsoluteURL from '../helpers/isAbsoluteURL'
|
||||
import combineURLs from '../helpers/combineURLs'
|
||||
|
||||
/**
|
||||
* Creates a new URL by combining the baseURL with the requestedURL,
|
||||
* only when the requestedURL is not already an absolute URL.
|
||||
* If the requestURL is absolute, this function returns the requestedURL untouched.
|
||||
*
|
||||
* @param {string} baseURL The base URL
|
||||
* @param {string} requestedURL Absolute or relative URL to combine
|
||||
* @returns {string} The combined full path
|
||||
*/
|
||||
export default function buildFullPath(baseURL, requestedURL) {
|
||||
if (baseURL && !isAbsoluteURL(requestedURL)) {
|
||||
return combineURLs(baseURL, requestedURL)
|
||||
}
|
||||
return requestedURL
|
||||
}
|
||||
33
uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js
Normal file
33
uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 默认的全局配置
|
||||
*/
|
||||
|
||||
|
||||
export default {
|
||||
baseURL: '',
|
||||
header: {},
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
paramsSerializer: null,
|
||||
// #ifndef MP-ALIPAY
|
||||
responseType: 'text',
|
||||
// #endif
|
||||
custom: {},
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
timeout: 60000,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
sslVerify: true,
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
withCredentials: false,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
firstIpv4: false,
|
||||
// #endif
|
||||
validateStatus: function validateStatus(status) {
|
||||
return status >= 200 && status < 300
|
||||
},
|
||||
// 是否尝试将响应数据json化
|
||||
forcedJSONParsing: true
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import adapter from '../adapters/index'
|
||||
|
||||
|
||||
export default (config) => {
|
||||
return adapter(config)
|
||||
}
|
||||
126
uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js
Normal file
126
uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js
Normal file
@@ -0,0 +1,126 @@
|
||||
import {deepMerge, isUndefined} from '../utils'
|
||||
|
||||
/**
|
||||
* 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
|
||||
* @param {Array} keys - 配置项
|
||||
* @param {Object} globalsConfig - 当前的全局配置
|
||||
* @param {Object} config2 - 局部配置
|
||||
* @return {{}}
|
||||
*/
|
||||
const mergeKeys = (keys, globalsConfig, config2) => {
|
||||
let config = {}
|
||||
keys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
} else if (!isUndefined(globalsConfig[prop])) {
|
||||
config[prop] = globalsConfig[prop]
|
||||
}
|
||||
})
|
||||
return config
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param globalsConfig - 当前实例的全局配置
|
||||
* @param config2 - 当前的局部配置
|
||||
* @return - 合并后的配置
|
||||
*/
|
||||
export default (globalsConfig, config2 = {}) => {
|
||||
const method = config2.method || globalsConfig.method || 'GET'
|
||||
let config = {
|
||||
baseURL: config2.baseURL || globalsConfig.baseURL || '',
|
||||
method: method,
|
||||
url: config2.url || '',
|
||||
params: config2.params || {},
|
||||
custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
|
||||
header: deepMerge(globalsConfig.header || {}, config2.header || {})
|
||||
}
|
||||
const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
|
||||
config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
|
||||
|
||||
// eslint-disable-next-line no-empty
|
||||
if (method === 'DOWNLOAD') {
|
||||
const downloadKeys = [
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
'timeout',
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
'filePath',
|
||||
// #endif
|
||||
]
|
||||
config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
|
||||
} else if (method === 'UPLOAD') {
|
||||
delete config.header['content-type']
|
||||
delete config.header['Content-Type']
|
||||
const uploadKeys = [
|
||||
// #ifdef APP-PLUS || H5
|
||||
'files',
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
'fileType',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'file',
|
||||
// #endif
|
||||
'filePath',
|
||||
'name',
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
'timeout',
|
||||
// #endif
|
||||
'formData',
|
||||
]
|
||||
uploadKeys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
}
|
||||
})
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
|
||||
config['timeout'] = globalsConfig['timeout']
|
||||
}
|
||||
// #endif
|
||||
} else {
|
||||
const defaultsKeys = [
|
||||
'data',
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
'timeout',
|
||||
// #endif
|
||||
'dataType',
|
||||
// #ifndef MP-ALIPAY
|
||||
'responseType',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'sslVerify',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'withCredentials',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'firstIpv4',
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
'enableHttp2',
|
||||
'enableQuic',
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO || MP-WEIXIN
|
||||
'enableCache',
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
'enableHttpDNS',
|
||||
'httpDNSServiceId',
|
||||
'enableChunked',
|
||||
'forceCellularNetwork',
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
'enableCookie',
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU
|
||||
'cloudCache',
|
||||
'defer'
|
||||
// #endif
|
||||
|
||||
]
|
||||
config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
16
uni_modules/uv-ui-tools/libs/luch-request/core/settle.js
Normal file
16
uni_modules/uv-ui-tools/libs/luch-request/core/settle.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Resolve or reject a Promise based on response status.
|
||||
*
|
||||
* @param {Function} resolve A function that resolves the promise.
|
||||
* @param {Function} reject A function that rejects the promise.
|
||||
* @param {object} response The response.
|
||||
*/
|
||||
export default function settle(resolve, reject, response) {
|
||||
const validateStatus = response.config.validateStatus
|
||||
const status = response.statusCode
|
||||
if (status && (!validateStatus || validateStatus(status))) {
|
||||
resolve(response)
|
||||
} else {
|
||||
reject(response)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
'use strict'
|
||||
|
||||
import * as utils from './../utils'
|
||||
|
||||
function encode(val) {
|
||||
return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a URL by appending params to the end
|
||||
*
|
||||
* @param {string} url The base of the url (e.g., http://www.google.com)
|
||||
* @param {object} [params] The params to be appended
|
||||
* @returns {string} The formatted url
|
||||
*/
|
||||
export default function buildURL(url, params, paramsSerializer) {
|
||||
/*eslint no-param-reassign:0*/
|
||||
if (!params) {
|
||||
return url
|
||||
}
|
||||
|
||||
var serializedParams
|
||||
if (paramsSerializer) {
|
||||
serializedParams = paramsSerializer(params)
|
||||
} else if (utils.isURLSearchParams(params)) {
|
||||
serializedParams = params.toString()
|
||||
} else {
|
||||
var parts = []
|
||||
|
||||
utils.forEach(params, function serialize(val, key) {
|
||||
if (val === null || typeof val === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
if (utils.isArray(val)) {
|
||||
key = key + '[]'
|
||||
} else {
|
||||
val = [val]
|
||||
}
|
||||
|
||||
utils.forEach(val, function parseValue(v) {
|
||||
if (utils.isDate(v)) {
|
||||
v = v.toISOString()
|
||||
} else if (utils.isObject(v)) {
|
||||
v = JSON.stringify(v)
|
||||
}
|
||||
parts.push(encode(key) + '=' + encode(v))
|
||||
})
|
||||
})
|
||||
|
||||
serializedParams = parts.join('&')
|
||||
}
|
||||
|
||||
if (serializedParams) {
|
||||
var hashmarkIndex = url.indexOf('#')
|
||||
if (hashmarkIndex !== -1) {
|
||||
url = url.slice(0, hashmarkIndex)
|
||||
}
|
||||
|
||||
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Creates a new URL by combining the specified URLs
|
||||
*
|
||||
* @param {string} baseURL The base URL
|
||||
* @param {string} relativeURL The relative URL
|
||||
* @returns {string} The combined URL
|
||||
*/
|
||||
export default function combineURLs(baseURL, relativeURL) {
|
||||
return relativeURL
|
||||
? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
|
||||
: baseURL
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Determines whether the specified URL is absolute
|
||||
*
|
||||
* @param {string} url The URL to test
|
||||
* @returns {boolean} True if the specified URL is absolute, otherwise false
|
||||
*/
|
||||
export default function isAbsoluteURL(url) {
|
||||
// A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
|
||||
// RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
|
||||
// by any combination of letters, digits, plus, period, or hyphen.
|
||||
return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
|
||||
}
|
||||
197
uni_modules/uv-ui-tools/libs/luch-request/index.d.ts
vendored
Normal file
197
uni_modules/uv-ui-tools/libs/luch-request/index.d.ts
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
|
||||
|
||||
export type HttpRequestTask = UniApp.RequestTask;
|
||||
|
||||
export type HttpUploadTask = UniApp.UploadTask;
|
||||
|
||||
export type HttpDownloadTask = UniApp.DownloadTask;
|
||||
|
||||
export type HttpMethod =
|
||||
"GET"
|
||||
| "POST"
|
||||
| "PUT"
|
||||
| "DELETE"
|
||||
| "CONNECT"
|
||||
| "HEAD"
|
||||
| "OPTIONS"
|
||||
| "TRACE"
|
||||
| "UPLOAD"
|
||||
| "DOWNLOAD";
|
||||
|
||||
export type HttpRequestHeader = Record<string, string>;
|
||||
|
||||
export type HttpParams = Record<string, any>;
|
||||
|
||||
export type HttpData = Record<string, any>;
|
||||
|
||||
export type HttpResponseType = 'arraybuffer' | 'text';
|
||||
|
||||
export type HttpCustom = Record<string, any>;
|
||||
|
||||
export type HttpFileType = 'image' | 'video' | 'audio';
|
||||
|
||||
export type HttpFormData = Record<string, any>;
|
||||
|
||||
export type HttpResponseHeader = Record<string, string> & {
|
||||
"set-cookie"?: string[]
|
||||
};
|
||||
|
||||
export interface HttpRequestConfig<T = HttpTask> {
|
||||
/** @desc 请求服务器接口地址 */
|
||||
url?: string;
|
||||
/** @desc 请求方式,默认为 GET */
|
||||
method?: HttpMethod;
|
||||
/** @desc 请求基地址 */
|
||||
baseURL?: string;
|
||||
/** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
|
||||
header?: HttpRequestHeader;
|
||||
/** @desc 请求查询参数,自动拼接为查询字符串 */
|
||||
params?: HttpParams;
|
||||
/** @desc 请求体参数 */
|
||||
data?: HttpData;
|
||||
/** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
|
||||
timeout?: number;
|
||||
/** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
|
||||
withCredentials?: boolean;
|
||||
/** @desc 设置响应的数据类型,支付宝小程序不支持 */
|
||||
responseType?: HttpResponseType;
|
||||
/** @desc 全局自定义验证器 */
|
||||
validateStatus?: ((statusCode: number) => boolean) | null;
|
||||
|
||||
|
||||
/** params 参数自定义处理 */
|
||||
paramsSerializer?: (params: AnyObject) => string | void;
|
||||
|
||||
/** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
|
||||
dataType?: string;
|
||||
/** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
|
||||
firstIpv4?: boolean;
|
||||
/** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
|
||||
sslVerify?: boolean;
|
||||
|
||||
/** @desc 开启 http2;微信小程序 */
|
||||
enableHttp2?: boolean;
|
||||
|
||||
/** @desc 开启 quic;微信小程序 */
|
||||
enableQuic?: boolean;
|
||||
/** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
|
||||
enableCache?: boolean;
|
||||
/** @desc 开启 httpDNS;微信小程序 */
|
||||
enableHttpDNS?: boolean;
|
||||
/** @desc httpDNS 服务商;微信小程序 */
|
||||
httpDNSServiceId?: string;
|
||||
/** @desc 开启 transfer-encoding chunked;微信小程序 */
|
||||
enableChunked?: boolean;
|
||||
/** @desc wifi下使用移动网络发送请求;微信小程序 */
|
||||
forceCellularNetwork?: boolean;
|
||||
/** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
|
||||
enableCookie?: boolean;
|
||||
/** @desc 是否开启云加速;百度小程序 3.310.11+ */
|
||||
cloudCache?: boolean | object;
|
||||
/** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
|
||||
defer?: boolean;
|
||||
|
||||
/** @desc 自定义参数 */
|
||||
custom?: HttpCustom;
|
||||
|
||||
/** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
|
||||
getTask?: (task: T, options: HttpRequestConfig<T>) => void;
|
||||
|
||||
/** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
|
||||
files?: { name?: string; file?: File; uri: string; }[];
|
||||
/** @desc 文件类型,仅支付宝小程序支持且为必填项 */
|
||||
fileType?: HttpFileType;
|
||||
/** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
|
||||
file?: File;
|
||||
/** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
|
||||
filePath?: string;
|
||||
/** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
|
||||
name?: string;
|
||||
/** @desc 请求中其他额外的 form data */
|
||||
formData?: HttpFormData;
|
||||
}
|
||||
|
||||
export interface HttpResponse<T = any, D = HttpTask> {
|
||||
data: T;
|
||||
statusCode: number;
|
||||
header: HttpResponseHeader;
|
||||
config: HttpRequestConfig<D>;
|
||||
cookies: string[];
|
||||
errMsg: string;
|
||||
rawData: any;
|
||||
}
|
||||
|
||||
export interface HttpUploadResponse<T = any, D = HttpTask> {
|
||||
data: T;
|
||||
statusCode: number;
|
||||
config: HttpRequestConfig<D>;
|
||||
errMsg: string;
|
||||
rawData: any;
|
||||
}
|
||||
|
||||
export interface HttpDownloadResponse extends HttpResponse {
|
||||
tempFilePath: string;
|
||||
apFilePath?: string;
|
||||
filePath?: string;
|
||||
fileContent?: string;
|
||||
}
|
||||
|
||||
export interface HttpError<T = any, D = HttpTask> {
|
||||
data?: T;
|
||||
statusCode?: number;
|
||||
header?: HttpResponseHeader;
|
||||
config: HttpRequestConfig<D>;
|
||||
cookies?: string[];
|
||||
errMsg: string;
|
||||
}
|
||||
|
||||
export interface HttpPromise<T = any> extends Promise<HttpResponse<T>> {
|
||||
}
|
||||
|
||||
export interface HttpInterceptorManager<V, E = V> {
|
||||
use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: E) => T | Promise<E>): void;
|
||||
|
||||
eject(id: number): void;
|
||||
}
|
||||
|
||||
export abstract class HttpRequestAbstract {
|
||||
constructor(config?: HttpRequestConfig);
|
||||
|
||||
interceptors: {
|
||||
request: HttpInterceptorManager<HttpRequestConfig>;
|
||||
response: HttpInterceptorManager<HttpResponse, HttpError>;
|
||||
}
|
||||
|
||||
request<T = any, R = HttpResponse<T>, D = HttpRequestTask>(config: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
get<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
delete<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
head<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
options<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
post<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
put<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
config: HttpRequestConfig;
|
||||
|
||||
setConfig<D = HttpTask>(onSend: (config: HttpRequestConfig<D>) => HttpRequestConfig<D>): void;
|
||||
|
||||
connect<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
trace<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
upload<T = any, R = HttpUploadResponse<T>, D = HttpUploadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
download<T = any, R = HttpDownloadResponse<T>, D = HttpDownloadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
middleware<T = any, R = HttpResponse<T>, D = HttpTask>(config: HttpRequestConfig<D>): Promise<R>;
|
||||
}
|
||||
|
||||
declare class HttpRequest extends HttpRequestAbstract {
|
||||
}
|
||||
|
||||
export default HttpRequest;
|
||||
2
uni_modules/uv-ui-tools/libs/luch-request/index.js
Normal file
2
uni_modules/uv-ui-tools/libs/luch-request/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import Request from './core/Request'
|
||||
export default Request
|
||||
135
uni_modules/uv-ui-tools/libs/luch-request/utils.js
Normal file
135
uni_modules/uv-ui-tools/libs/luch-request/utils.js
Normal file
@@ -0,0 +1,135 @@
|
||||
'use strict'
|
||||
|
||||
// utils is a library of generic helper functions non-specific to axios
|
||||
|
||||
var toString = Object.prototype.toString
|
||||
|
||||
/**
|
||||
* Determine if a value is an Array
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is an Array, otherwise false
|
||||
*/
|
||||
export function isArray (val) {
|
||||
return toString.call(val) === '[object Array]'
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if a value is an Object
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is an Object, otherwise false
|
||||
*/
|
||||
export function isObject (val) {
|
||||
return val !== null && typeof val === 'object'
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value is a Date
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is a Date, otherwise false
|
||||
*/
|
||||
export function isDate (val) {
|
||||
return toString.call(val) === '[object Date]'
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value is a URLSearchParams object
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is a URLSearchParams object, otherwise false
|
||||
*/
|
||||
export function isURLSearchParams (val) {
|
||||
return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over an Array or an Object invoking a function for each item.
|
||||
*
|
||||
* If `obj` is an Array callback will be called passing
|
||||
* the value, index, and complete array for each item.
|
||||
*
|
||||
* If 'obj' is an Object callback will be called passing
|
||||
* the value, key, and complete object for each property.
|
||||
*
|
||||
* @param {Object|Array} obj The object to iterate
|
||||
* @param {Function} fn The callback to invoke for each item
|
||||
*/
|
||||
export function forEach (obj, fn) {
|
||||
// Don't bother if no value provided
|
||||
if (obj === null || typeof obj === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
// Force an array if not already something iterable
|
||||
if (typeof obj !== 'object') {
|
||||
/*eslint no-param-reassign:0*/
|
||||
obj = [obj]
|
||||
}
|
||||
|
||||
if (isArray(obj)) {
|
||||
// Iterate over array values
|
||||
for (var i = 0, l = obj.length; i < l; i++) {
|
||||
fn.call(null, obj[i], i, obj)
|
||||
}
|
||||
} else {
|
||||
// Iterate over object keys
|
||||
for (var key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
fn.call(null, obj[key], key, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为boolean 值
|
||||
* @param val
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isBoolean(val) {
|
||||
return typeof val === 'boolean'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为真正的对象{} new Object
|
||||
* @param {any} obj - 检测的对象
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPlainObject(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Object]'
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function equal to merge with the difference being that no reference
|
||||
* to original objects is kept.
|
||||
*
|
||||
* @see merge
|
||||
* @param {Object} obj1 Object to merge
|
||||
* @returns {Object} Result of all merge properties
|
||||
*/
|
||||
export function deepMerge(/* obj1, obj2, obj3, ... */) {
|
||||
let result = {}
|
||||
function assignValue(val, key) {
|
||||
if (typeof result[key] === 'object' && typeof val === 'object') {
|
||||
result[key] = deepMerge(result[key], val)
|
||||
} else if (typeof val === 'object') {
|
||||
result[key] = deepMerge({}, val)
|
||||
} else {
|
||||
result[key] = val
|
||||
}
|
||||
}
|
||||
for (let i = 0, l = arguments.length; i < l; i++) {
|
||||
forEach(arguments[i], assignValue)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function isUndefined (val) {
|
||||
return typeof val === 'undefined'
|
||||
}
|
||||
264
uni_modules/uv-ui-tools/libs/luch-request/utils/clone.js
Normal file
264
uni_modules/uv-ui-tools/libs/luch-request/utils/clone.js
Normal file
@@ -0,0 +1,264 @@
|
||||
/* eslint-disable */
|
||||
var clone = (function() {
|
||||
'use strict';
|
||||
|
||||
function _instanceof(obj, type) {
|
||||
return type != null && obj instanceof type;
|
||||
}
|
||||
|
||||
var nativeMap;
|
||||
try {
|
||||
nativeMap = Map;
|
||||
} catch(_) {
|
||||
// maybe a reference error because no `Map`. Give it a dummy value that no
|
||||
// value will ever be an instanceof.
|
||||
nativeMap = function() {};
|
||||
}
|
||||
|
||||
var nativeSet;
|
||||
try {
|
||||
nativeSet = Set;
|
||||
} catch(_) {
|
||||
nativeSet = function() {};
|
||||
}
|
||||
|
||||
var nativePromise;
|
||||
try {
|
||||
nativePromise = Promise;
|
||||
} catch(_) {
|
||||
nativePromise = function() {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones (copies) an Object using deep copying.
|
||||
*
|
||||
* This function supports circular references by default, but if you are certain
|
||||
* there are no circular references in your object, you can save some CPU time
|
||||
* by calling clone(obj, false).
|
||||
*
|
||||
* Caution: if `circular` is false and `parent` contains circular references,
|
||||
* your program may enter an infinite loop and crash.
|
||||
*
|
||||
* @param `parent` - the object to be cloned
|
||||
* @param `circular` - set to true if the object to be cloned may contain
|
||||
* circular references. (optional - true by default)
|
||||
* @param `depth` - set to a number if the object is only to be cloned to
|
||||
* a particular depth. (optional - defaults to Infinity)
|
||||
* @param `prototype` - sets the prototype to be used when cloning an object.
|
||||
* (optional - defaults to parent prototype).
|
||||
* @param `includeNonEnumerable` - set to true if the non-enumerable properties
|
||||
* should be cloned as well. Non-enumerable properties on the prototype
|
||||
* chain will be ignored. (optional - false by default)
|
||||
*/
|
||||
function clone(parent, circular, depth, prototype, includeNonEnumerable) {
|
||||
if (typeof circular === 'object') {
|
||||
depth = circular.depth;
|
||||
prototype = circular.prototype;
|
||||
includeNonEnumerable = circular.includeNonEnumerable;
|
||||
circular = circular.circular;
|
||||
}
|
||||
// maintain two arrays for circular references, where corresponding parents
|
||||
// and children have the same index
|
||||
var allParents = [];
|
||||
var allChildren = [];
|
||||
|
||||
var useBuffer = typeof Buffer != 'undefined';
|
||||
|
||||
if (typeof circular == 'undefined')
|
||||
circular = true;
|
||||
|
||||
if (typeof depth == 'undefined')
|
||||
depth = Infinity;
|
||||
|
||||
// recurse this function so we don't reset allParents and allChildren
|
||||
function _clone(parent, depth) {
|
||||
// cloning null always returns null
|
||||
if (parent === null)
|
||||
return null;
|
||||
|
||||
if (depth === 0)
|
||||
return parent;
|
||||
|
||||
var child;
|
||||
var proto;
|
||||
if (typeof parent != 'object') {
|
||||
return parent;
|
||||
}
|
||||
|
||||
if (_instanceof(parent, nativeMap)) {
|
||||
child = new nativeMap();
|
||||
} else if (_instanceof(parent, nativeSet)) {
|
||||
child = new nativeSet();
|
||||
} else if (_instanceof(parent, nativePromise)) {
|
||||
child = new nativePromise(function (resolve, reject) {
|
||||
parent.then(function(value) {
|
||||
resolve(_clone(value, depth - 1));
|
||||
}, function(err) {
|
||||
reject(_clone(err, depth - 1));
|
||||
});
|
||||
});
|
||||
} else if (clone.__isArray(parent)) {
|
||||
child = [];
|
||||
} else if (clone.__isRegExp(parent)) {
|
||||
child = new RegExp(parent.source, __getRegExpFlags(parent));
|
||||
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
|
||||
} else if (clone.__isDate(parent)) {
|
||||
child = new Date(parent.getTime());
|
||||
} else if (useBuffer && Buffer.isBuffer(parent)) {
|
||||
if (Buffer.from) {
|
||||
// Node.js >= 5.10.0
|
||||
child = Buffer.from(parent);
|
||||
} else {
|
||||
// Older Node.js versions
|
||||
child = new Buffer(parent.length);
|
||||
parent.copy(child);
|
||||
}
|
||||
return child;
|
||||
} else if (_instanceof(parent, Error)) {
|
||||
child = Object.create(parent);
|
||||
} else {
|
||||
if (typeof prototype == 'undefined') {
|
||||
proto = Object.getPrototypeOf(parent);
|
||||
child = Object.create(proto);
|
||||
}
|
||||
else {
|
||||
child = Object.create(prototype);
|
||||
proto = prototype;
|
||||
}
|
||||
}
|
||||
|
||||
if (circular) {
|
||||
var index = allParents.indexOf(parent);
|
||||
|
||||
if (index != -1) {
|
||||
return allChildren[index];
|
||||
}
|
||||
allParents.push(parent);
|
||||
allChildren.push(child);
|
||||
}
|
||||
|
||||
if (_instanceof(parent, nativeMap)) {
|
||||
parent.forEach(function(value, key) {
|
||||
var keyChild = _clone(key, depth - 1);
|
||||
var valueChild = _clone(value, depth - 1);
|
||||
child.set(keyChild, valueChild);
|
||||
});
|
||||
}
|
||||
if (_instanceof(parent, nativeSet)) {
|
||||
parent.forEach(function(value) {
|
||||
var entryChild = _clone(value, depth - 1);
|
||||
child.add(entryChild);
|
||||
});
|
||||
}
|
||||
|
||||
for (var i in parent) {
|
||||
var attrs = Object.getOwnPropertyDescriptor(parent, i);
|
||||
if (attrs) {
|
||||
child[i] = _clone(parent[i], depth - 1);
|
||||
}
|
||||
|
||||
try {
|
||||
var objProperty = Object.getOwnPropertyDescriptor(parent, i);
|
||||
if (objProperty.set === 'undefined') {
|
||||
// no setter defined. Skip cloning this property
|
||||
continue;
|
||||
}
|
||||
child[i] = _clone(parent[i], depth - 1);
|
||||
} catch(e){
|
||||
if (e instanceof TypeError) {
|
||||
// when in strict mode, TypeError will be thrown if child[i] property only has a getter
|
||||
// we can't do anything about this, other than inform the user that this property cannot be set.
|
||||
continue
|
||||
} else if (e instanceof ReferenceError) {
|
||||
//this may happen in non strict mode
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Object.getOwnPropertySymbols) {
|
||||
var symbols = Object.getOwnPropertySymbols(parent);
|
||||
for (var i = 0; i < symbols.length; i++) {
|
||||
// Don't need to worry about cloning a symbol because it is a primitive,
|
||||
// like a number or string.
|
||||
var symbol = symbols[i];
|
||||
var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
|
||||
if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
|
||||
continue;
|
||||
}
|
||||
child[symbol] = _clone(parent[symbol], depth - 1);
|
||||
Object.defineProperty(child, symbol, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeNonEnumerable) {
|
||||
var allPropertyNames = Object.getOwnPropertyNames(parent);
|
||||
for (var i = 0; i < allPropertyNames.length; i++) {
|
||||
var propertyName = allPropertyNames[i];
|
||||
var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
|
||||
if (descriptor && descriptor.enumerable) {
|
||||
continue;
|
||||
}
|
||||
child[propertyName] = _clone(parent[propertyName], depth - 1);
|
||||
Object.defineProperty(child, propertyName, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
return _clone(parent, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple flat clone using prototype, accepts only objects, usefull for property
|
||||
* override on FLAT configuration object (no nested props).
|
||||
*
|
||||
* USE WITH CAUTION! This may not behave as you wish if you do not know how this
|
||||
* works.
|
||||
*/
|
||||
clone.clonePrototype = function clonePrototype(parent) {
|
||||
if (parent === null)
|
||||
return null;
|
||||
|
||||
var c = function () {};
|
||||
c.prototype = parent;
|
||||
return new c();
|
||||
};
|
||||
|
||||
// private utility functions
|
||||
|
||||
function __objToStr(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
}
|
||||
clone.__objToStr = __objToStr;
|
||||
|
||||
function __isDate(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object Date]';
|
||||
}
|
||||
clone.__isDate = __isDate;
|
||||
|
||||
function __isArray(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object Array]';
|
||||
}
|
||||
clone.__isArray = __isArray;
|
||||
|
||||
function __isRegExp(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
|
||||
}
|
||||
clone.__isRegExp = __isRegExp;
|
||||
|
||||
function __getRegExpFlags(re) {
|
||||
var flags = '';
|
||||
if (re.global) flags += 'g';
|
||||
if (re.ignoreCase) flags += 'i';
|
||||
if (re.multiline) flags += 'm';
|
||||
return flags;
|
||||
}
|
||||
clone.__getRegExpFlags = __getRegExpFlags;
|
||||
|
||||
return clone;
|
||||
})();
|
||||
|
||||
export default clone
|
||||
13
uni_modules/uv-ui-tools/libs/mixin/button.js
Normal file
13
uni_modules/uv-ui-tools/libs/mixin/button.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export default {
|
||||
props: {
|
||||
lang: String,
|
||||
sessionFrom: String,
|
||||
sendMessageTitle: String,
|
||||
sendMessagePath: String,
|
||||
sendMessageImg: String,
|
||||
showMessageCard: Boolean,
|
||||
appParameter: String,
|
||||
formType: String,
|
||||
openType: String
|
||||
}
|
||||
}
|
||||
172
uni_modules/uv-ui-tools/libs/mixin/mixin.js
Normal file
172
uni_modules/uv-ui-tools/libs/mixin/mixin.js
Normal file
@@ -0,0 +1,172 @@
|
||||
import * as index from '../function/index.js';
|
||||
import * as test from '../function/test.js';
|
||||
import route from '../util/route.js';
|
||||
import debounce from '../function/debounce.js';
|
||||
import throttle from '../function/throttle.js';
|
||||
export default {
|
||||
// 定义每个组件都可能需要用到的外部样式以及类名
|
||||
props: {
|
||||
// 每个组件都有的父组件传递的样式,可以为字符串或者对象形式
|
||||
customStyle: {
|
||||
type: [Object, String],
|
||||
default: () => ({})
|
||||
},
|
||||
customClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 跳转的页面路径
|
||||
url: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 页面跳转的类型
|
||||
linkType: {
|
||||
type: String,
|
||||
default: 'navigateTo'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
onLoad() {
|
||||
// getRect挂载到$uv上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出
|
||||
this.$uv.getRect = this.$uvGetRect
|
||||
},
|
||||
created() {
|
||||
// 组件当中,只有created声明周期,为了能在组件使用,故也在created中将方法挂载到$uv
|
||||
this.$uv.getRect = this.$uvGetRect
|
||||
},
|
||||
computed: {
|
||||
$uv() {
|
||||
return {
|
||||
...index,
|
||||
test,
|
||||
route,
|
||||
debounce,
|
||||
throttle,
|
||||
unit: uni?.$uv?.config?.unit
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 生成bem规则类名
|
||||
* 由于微信小程序,H5,nvue之间绑定class的差异,无法通过:class="[bem()]"的形式进行同用
|
||||
* 故采用如下折中做法,最后返回的是数组(一般平台)或字符串(支付宝和字节跳动平台),类似['a', 'b', 'c']或'a b c'的形式
|
||||
* @param {String} name 组件名称
|
||||
* @param {Array} fixed 一直会存在的类名
|
||||
* @param {Array} change 会根据变量值为true或者false而出现或者隐藏的类名
|
||||
* @returns {Array|string}
|
||||
*/
|
||||
bem() {
|
||||
return function(name, fixed, change) {
|
||||
// 类名前缀
|
||||
const prefix = `uv-${name}--`
|
||||
const classes = {}
|
||||
if (fixed) {
|
||||
fixed.map((item) => {
|
||||
// 这里的类名,会一直存在
|
||||
classes[prefix + this[item]] = true
|
||||
})
|
||||
}
|
||||
if (change) {
|
||||
change.map((item) => {
|
||||
// 这里的类名,会根据this[item]的值为true或者false,而进行添加或者移除某一个类
|
||||
this[item] ? (classes[prefix + item] = this[item]) : (delete classes[prefix + item])
|
||||
})
|
||||
}
|
||||
return Object.keys(classes)
|
||||
// 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
|
||||
// #ifdef MP-ALIPAY || MP-TOUTIAO || MP-LARK || MP-BAIDU
|
||||
.join(' ')
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 跳转某一个页面
|
||||
openPage(urlKey = 'url') {
|
||||
const url = this[urlKey]
|
||||
if (url) {
|
||||
// 执行类似uni.navigateTo的方法
|
||||
uni[this.linkType]({
|
||||
url
|
||||
})
|
||||
}
|
||||
},
|
||||
// 查询节点信息
|
||||
// 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21)
|
||||
// 解决办法为在组件根部再套一个没有任何作用的view元素
|
||||
$uvGetRect(selector, all) {
|
||||
return new Promise((resolve) => {
|
||||
uni.createSelectorQuery()
|
||||
.in(this)[all ? 'selectAll' : 'select'](selector)
|
||||
.boundingClientRect((rect) => {
|
||||
if (all && Array.isArray(rect) && rect.length) {
|
||||
resolve(rect)
|
||||
}
|
||||
if (!all && rect) {
|
||||
resolve(rect)
|
||||
}
|
||||
})
|
||||
.exec()
|
||||
})
|
||||
},
|
||||
getParentData(parentName = '') {
|
||||
// 避免在created中去定义parent变量
|
||||
if (!this.parent) this.parent = {}
|
||||
// 这里的本质原理是,通过获取父组件实例(也即类似uv-radio的父组件uv-radio-group的this)
|
||||
// 将父组件this中对应的参数,赋值给本组件(uv-radio的this)的parentData对象中对应的属性
|
||||
// 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
|
||||
// 此处并不会自动更新子组件的数据,而是依赖父组件uv-radio-group去监听data的变化,手动调用更新子组件的方法去重新获取
|
||||
this.parent = this.$uv.$parent.call(this, parentName)
|
||||
if (this.parent.children) {
|
||||
// 如果父组件的children不存在本组件的实例,才将本实例添加到父组件的children中
|
||||
this.parent.children.indexOf(this) === -1 && this.parent.children.push(this)
|
||||
}
|
||||
if (this.parent && this.parentData) {
|
||||
// 历遍parentData中的属性,将parent中的同名属性赋值给parentData
|
||||
Object.keys(this.parentData).map((key) => {
|
||||
this.parentData[key] = this.parent[key]
|
||||
})
|
||||
}
|
||||
},
|
||||
// 阻止事件冒泡
|
||||
preventEvent(e) {
|
||||
e && typeof(e.stopPropagation) === 'function' && e.stopPropagation()
|
||||
},
|
||||
// 空操作
|
||||
noop(e) {
|
||||
this.preventEvent(e)
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
uni.$emit('uvOnReachBottom')
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 判断当前页面是否存在parent和chldren,一般在checkbox和checkbox-group父子联动的场景会有此情况
|
||||
// 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱
|
||||
if (this.parent && test.array(this.parent.children)) {
|
||||
// 组件销毁时,移除父组件中的children数组中对应的实例
|
||||
const childrenList = this.parent.children
|
||||
childrenList.map((child, index) => {
|
||||
// 如果相等,则移除
|
||||
if (child === this) {
|
||||
childrenList.splice(index, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
// 兼容vue3
|
||||
unmounted() {
|
||||
if (this.parent && test.array(this.parent.children)) {
|
||||
// 组件销毁时,移除父组件中的children数组中对应的实例
|
||||
const childrenList = this.parent.children
|
||||
childrenList.map((child, index) => {
|
||||
// 如果相等,则移除
|
||||
if (child === this) {
|
||||
childrenList.splice(index, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
8
uni_modules/uv-ui-tools/libs/mixin/mpMixin.js
Normal file
8
uni_modules/uv-ui-tools/libs/mixin/mpMixin.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
// #ifdef MP-WEIXIN
|
||||
// 将自定义节点设置成虚拟的(去掉自定义组件包裹层),更加接近Vue组件的表现,能更好的使用flex属性
|
||||
options: {
|
||||
virtualHost: true
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
13
uni_modules/uv-ui-tools/libs/mixin/mpShare.js
Normal file
13
uni_modules/uv-ui-tools/libs/mixin/mpShare.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export default {
|
||||
onLoad() {
|
||||
// 设置默认的转发参数
|
||||
uni.$uv.mpShare = {
|
||||
title: '', // 默认为小程序名称
|
||||
path: '', // 默认为当前页面路径
|
||||
imageUrl: '' // 默认为当前页面的截图
|
||||
}
|
||||
},
|
||||
onShareAppMessage() {
|
||||
return uni.$uv.mpShare
|
||||
}
|
||||
}
|
||||
47
uni_modules/uv-ui-tools/libs/mixin/openType.js
Normal file
47
uni_modules/uv-ui-tools/libs/mixin/openType.js
Normal file
@@ -0,0 +1,47 @@
|
||||
export default {
|
||||
props: {
|
||||
openType: String
|
||||
},
|
||||
emits: ['getphonenumber','getuserinfo','error','opensetting','launchapp','contact','chooseavatar','addgroupapp','chooseaddress','subscribe','login','im'],
|
||||
methods: {
|
||||
onGetPhoneNumber(event) {
|
||||
this.$emit('getphonenumber', event.detail)
|
||||
},
|
||||
onGetUserInfo(event) {
|
||||
this.$emit('getuserinfo', event.detail)
|
||||
},
|
||||
onError(event) {
|
||||
this.$emit('error', event.detail)
|
||||
},
|
||||
onOpenSetting(event) {
|
||||
this.$emit('opensetting', event.detail)
|
||||
},
|
||||
onLaunchApp(event) {
|
||||
this.$emit('launchapp', event.detail)
|
||||
},
|
||||
onContact(event) {
|
||||
this.$emit('contact', event.detail)
|
||||
},
|
||||
onChooseavatar(event) {
|
||||
this.$emit('chooseavatar', event.detail)
|
||||
},
|
||||
onAgreeprivacyauthorization(event) {
|
||||
this.$emit('agreeprivacyauthorization', event.detail)
|
||||
},
|
||||
onAddgroupapp(event) {
|
||||
this.$emit('addgroupapp', event.detail)
|
||||
},
|
||||
onChooseaddress(event) {
|
||||
this.$emit('chooseaddress', event.detail)
|
||||
},
|
||||
onSubscribe(event) {
|
||||
this.$emit('subscribe', event.detail)
|
||||
},
|
||||
onLogin(event) {
|
||||
this.$emit('login', event.detail)
|
||||
},
|
||||
onIm(event) {
|
||||
this.$emit('im', event.detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
59
uni_modules/uv-ui-tools/libs/mixin/touch.js
Normal file
59
uni_modules/uv-ui-tools/libs/mixin/touch.js
Normal file
@@ -0,0 +1,59 @@
|
||||
const MIN_DISTANCE = 10
|
||||
|
||||
function getDirection(x, y) {
|
||||
if (x > y && x > MIN_DISTANCE) {
|
||||
return 'horizontal'
|
||||
}
|
||||
if (y > x && y > MIN_DISTANCE) {
|
||||
return 'vertical'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
getTouchPoint(e) {
|
||||
if (!e) {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
} if (e.touches && e.touches[0]) {
|
||||
return {
|
||||
x: e.touches[0].pageX,
|
||||
y: e.touches[0].pageY
|
||||
}
|
||||
} if (e.changedTouches && e.changedTouches[0]) {
|
||||
return {
|
||||
x: e.changedTouches[0].pageX,
|
||||
y: e.changedTouches[0].pageY
|
||||
}
|
||||
}
|
||||
return {
|
||||
x: e.clientX || 0,
|
||||
y: e.clientY || 0
|
||||
}
|
||||
},
|
||||
resetTouchStatus() {
|
||||
this.direction = ''
|
||||
this.deltaX = 0
|
||||
this.deltaY = 0
|
||||
this.offsetX = 0
|
||||
this.offsetY = 0
|
||||
},
|
||||
touchStart(event) {
|
||||
this.resetTouchStatus()
|
||||
const touch = this.getTouchPoint(event)
|
||||
this.startX = touch.x
|
||||
this.startY = touch.y
|
||||
},
|
||||
touchMove(event) {
|
||||
const touch = this.getTouchPoint(event)
|
||||
this.deltaX = touch.x - this.startX
|
||||
this.deltaY = touch.y - this.startY
|
||||
this.offsetX = Math.abs(this.deltaX)
|
||||
this.offsetY = Math.abs(this.deltaY)
|
||||
this.direction = this.direction || getDirection(this.offsetX, this.offsetY)
|
||||
}
|
||||
}
|
||||
}
|
||||
216
uni_modules/uv-ui-tools/libs/util/dayjs.js
Normal file
216
uni_modules/uv-ui-tools/libs/util/dayjs.js
Normal file
@@ -0,0 +1,216 @@
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
|
||||
var require_dayjs_min = __commonJS({
|
||||
"uvuidayjs"(exports, module) {
|
||||
!function(t, e) {
|
||||
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs = e();
|
||||
}(exports, function() {
|
||||
"use strict";
|
||||
var t = 1e3, e = 6e4, n = 36e5, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", f = "month", h = "quarter", c = "year", d = "date", l = "Invalid Date", $ = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = { name: "en", weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), ordinal: function(t2) {
|
||||
var e2 = ["th", "st", "nd", "rd"], n2 = t2 % 100;
|
||||
return "[" + t2 + (e2[(n2 - 20) % 10] || e2[n2] || e2[0]) + "]";
|
||||
} }, m = function(t2, e2, n2) {
|
||||
var r2 = String(t2);
|
||||
return !r2 || r2.length >= e2 ? t2 : "" + Array(e2 + 1 - r2.length).join(n2) + t2;
|
||||
}, v = { s: m, z: function(t2) {
|
||||
var e2 = -t2.utcOffset(), n2 = Math.abs(e2), r2 = Math.floor(n2 / 60), i2 = n2 % 60;
|
||||
return (e2 <= 0 ? "+" : "-") + m(r2, 2, "0") + ":" + m(i2, 2, "0");
|
||||
}, m: function t2(e2, n2) {
|
||||
if (e2.date() < n2.date())
|
||||
return -t2(n2, e2);
|
||||
var r2 = 12 * (n2.year() - e2.year()) + (n2.month() - e2.month()), i2 = e2.clone().add(r2, f), s2 = n2 - i2 < 0, u2 = e2.clone().add(r2 + (s2 ? -1 : 1), f);
|
||||
return +(-(r2 + (n2 - i2) / (s2 ? i2 - u2 : u2 - i2)) || 0);
|
||||
}, a: function(t2) {
|
||||
return t2 < 0 ? Math.ceil(t2) || 0 : Math.floor(t2);
|
||||
}, p: function(t2) {
|
||||
return { M: f, y: c, w: o, d: a, D: d, h: u, m: s, s: i, ms: r, Q: h }[t2] || String(t2 || "").toLowerCase().replace(/s$/, "");
|
||||
}, u: function(t2) {
|
||||
return void 0 === t2;
|
||||
} }, g = "en", D = {};
|
||||
D[g] = M;
|
||||
var p = function(t2) {
|
||||
return t2 instanceof _;
|
||||
}, S = function t2(e2, n2, r2) {
|
||||
var i2;
|
||||
if (!e2)
|
||||
return g;
|
||||
if ("string" == typeof e2) {
|
||||
var s2 = e2.toLowerCase();
|
||||
D[s2] && (i2 = s2), n2 && (D[s2] = n2, i2 = s2);
|
||||
var u2 = e2.split("-");
|
||||
if (!i2 && u2.length > 1)
|
||||
return t2(u2[0]);
|
||||
} else {
|
||||
var a2 = e2.name;
|
||||
D[a2] = e2, i2 = a2;
|
||||
}
|
||||
return !r2 && i2 && (g = i2), i2 || !r2 && g;
|
||||
}, w = function(t2, e2) {
|
||||
if (p(t2))
|
||||
return t2.clone();
|
||||
var n2 = "object" == typeof e2 ? e2 : {};
|
||||
return n2.date = t2, n2.args = arguments, new _(n2);
|
||||
}, O = v;
|
||||
O.l = S, O.i = p, O.w = function(t2, e2) {
|
||||
return w(t2, { locale: e2.$L, utc: e2.$u, x: e2.$x, $offset: e2.$offset });
|
||||
};
|
||||
var _ = function() {
|
||||
function M2(t2) {
|
||||
this.$L = S(t2.locale, null, true), this.parse(t2);
|
||||
}
|
||||
var m2 = M2.prototype;
|
||||
return m2.parse = function(t2) {
|
||||
this.$d = function(t3) {
|
||||
var e2 = t3.date, n2 = t3.utc;
|
||||
if (null === e2)
|
||||
return new Date(NaN);
|
||||
if (O.u(e2))
|
||||
return new Date();
|
||||
if (e2 instanceof Date)
|
||||
return new Date(e2);
|
||||
if ("string" == typeof e2 && !/Z$/i.test(e2)) {
|
||||
var r2 = e2.match($);
|
||||
if (r2) {
|
||||
var i2 = r2[2] - 1 || 0, s2 = (r2[7] || "0").substring(0, 3);
|
||||
return n2 ? new Date(Date.UTC(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2)) : new Date(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2);
|
||||
}
|
||||
}
|
||||
return new Date(e2);
|
||||
}(t2), this.$x = t2.x || {}, this.init();
|
||||
}, m2.init = function() {
|
||||
var t2 = this.$d;
|
||||
this.$y = t2.getFullYear(), this.$M = t2.getMonth(), this.$D = t2.getDate(), this.$W = t2.getDay(), this.$H = t2.getHours(), this.$m = t2.getMinutes(), this.$s = t2.getSeconds(), this.$ms = t2.getMilliseconds();
|
||||
}, m2.$utils = function() {
|
||||
return O;
|
||||
}, m2.isValid = function() {
|
||||
return !(this.$d.toString() === l);
|
||||
}, m2.isSame = function(t2, e2) {
|
||||
var n2 = w(t2);
|
||||
return this.startOf(e2) <= n2 && n2 <= this.endOf(e2);
|
||||
}, m2.isAfter = function(t2, e2) {
|
||||
return w(t2) < this.startOf(e2);
|
||||
}, m2.isBefore = function(t2, e2) {
|
||||
return this.endOf(e2) < w(t2);
|
||||
}, m2.$g = function(t2, e2, n2) {
|
||||
return O.u(t2) ? this[e2] : this.set(n2, t2);
|
||||
}, m2.unix = function() {
|
||||
return Math.floor(this.valueOf() / 1e3);
|
||||
}, m2.valueOf = function() {
|
||||
return this.$d.getTime();
|
||||
}, m2.startOf = function(t2, e2) {
|
||||
var n2 = this, r2 = !!O.u(e2) || e2, h2 = O.p(t2), l2 = function(t3, e3) {
|
||||
var i2 = O.w(n2.$u ? Date.UTC(n2.$y, e3, t3) : new Date(n2.$y, e3, t3), n2);
|
||||
return r2 ? i2 : i2.endOf(a);
|
||||
}, $2 = function(t3, e3) {
|
||||
return O.w(n2.toDate()[t3].apply(n2.toDate("s"), (r2 ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e3)), n2);
|
||||
}, y2 = this.$W, M3 = this.$M, m3 = this.$D, v2 = "set" + (this.$u ? "UTC" : "");
|
||||
switch (h2) {
|
||||
case c:
|
||||
return r2 ? l2(1, 0) : l2(31, 11);
|
||||
case f:
|
||||
return r2 ? l2(1, M3) : l2(0, M3 + 1);
|
||||
case o:
|
||||
var g2 = this.$locale().weekStart || 0, D2 = (y2 < g2 ? y2 + 7 : y2) - g2;
|
||||
return l2(r2 ? m3 - D2 : m3 + (6 - D2), M3);
|
||||
case a:
|
||||
case d:
|
||||
return $2(v2 + "Hours", 0);
|
||||
case u:
|
||||
return $2(v2 + "Minutes", 1);
|
||||
case s:
|
||||
return $2(v2 + "Seconds", 2);
|
||||
case i:
|
||||
return $2(v2 + "Milliseconds", 3);
|
||||
default:
|
||||
return this.clone();
|
||||
}
|
||||
}, m2.endOf = function(t2) {
|
||||
return this.startOf(t2, false);
|
||||
}, m2.$set = function(t2, e2) {
|
||||
var n2, o2 = O.p(t2), h2 = "set" + (this.$u ? "UTC" : ""), l2 = (n2 = {}, n2[a] = h2 + "Date", n2[d] = h2 + "Date", n2[f] = h2 + "Month", n2[c] = h2 + "FullYear", n2[u] = h2 + "Hours", n2[s] = h2 + "Minutes", n2[i] = h2 + "Seconds", n2[r] = h2 + "Milliseconds", n2)[o2], $2 = o2 === a ? this.$D + (e2 - this.$W) : e2;
|
||||
if (o2 === f || o2 === c) {
|
||||
var y2 = this.clone().set(d, 1);
|
||||
y2.$d[l2]($2), y2.init(), this.$d = y2.set(d, Math.min(this.$D, y2.daysInMonth())).$d;
|
||||
} else
|
||||
l2 && this.$d[l2]($2);
|
||||
return this.init(), this;
|
||||
}, m2.set = function(t2, e2) {
|
||||
return this.clone().$set(t2, e2);
|
||||
}, m2.get = function(t2) {
|
||||
return this[O.p(t2)]();
|
||||
}, m2.add = function(r2, h2) {
|
||||
var d2, l2 = this;
|
||||
r2 = Number(r2);
|
||||
var $2 = O.p(h2), y2 = function(t2) {
|
||||
var e2 = w(l2);
|
||||
return O.w(e2.date(e2.date() + Math.round(t2 * r2)), l2);
|
||||
};
|
||||
if ($2 === f)
|
||||
return this.set(f, this.$M + r2);
|
||||
if ($2 === c)
|
||||
return this.set(c, this.$y + r2);
|
||||
if ($2 === a)
|
||||
return y2(1);
|
||||
if ($2 === o)
|
||||
return y2(7);
|
||||
var M3 = (d2 = {}, d2[s] = e, d2[u] = n, d2[i] = t, d2)[$2] || 1, m3 = this.$d.getTime() + r2 * M3;
|
||||
return O.w(m3, this);
|
||||
}, m2.subtract = function(t2, e2) {
|
||||
return this.add(-1 * t2, e2);
|
||||
}, m2.format = function(t2) {
|
||||
var e2 = this, n2 = this.$locale();
|
||||
if (!this.isValid())
|
||||
return n2.invalidDate || l;
|
||||
var r2 = t2 || "YYYY-MM-DDTHH:mm:ssZ", i2 = O.z(this), s2 = this.$H, u2 = this.$m, a2 = this.$M, o2 = n2.weekdays, f2 = n2.months, h2 = function(t3, n3, i3, s3) {
|
||||
return t3 && (t3[n3] || t3(e2, r2)) || i3[n3].slice(0, s3);
|
||||
}, c2 = function(t3) {
|
||||
return O.s(s2 % 12 || 12, t3, "0");
|
||||
}, d2 = n2.meridiem || function(t3, e3, n3) {
|
||||
var r3 = t3 < 12 ? "AM" : "PM";
|
||||
return n3 ? r3.toLowerCase() : r3;
|
||||
}, $2 = { YY: String(this.$y).slice(-2), YYYY: this.$y, M: a2 + 1, MM: O.s(a2 + 1, 2, "0"), MMM: h2(n2.monthsShort, a2, f2, 3), MMMM: h2(f2, a2), D: this.$D, DD: O.s(this.$D, 2, "0"), d: String(this.$W), dd: h2(n2.weekdaysMin, this.$W, o2, 2), ddd: h2(n2.weekdaysShort, this.$W, o2, 3), dddd: o2[this.$W], H: String(s2), HH: O.s(s2, 2, "0"), h: c2(1), hh: c2(2), a: d2(s2, u2, true), A: d2(s2, u2, false), m: String(u2), mm: O.s(u2, 2, "0"), s: String(this.$s), ss: O.s(this.$s, 2, "0"), SSS: O.s(this.$ms, 3, "0"), Z: i2 };
|
||||
return r2.replace(y, function(t3, e3) {
|
||||
return e3 || $2[t3] || i2.replace(":", "");
|
||||
});
|
||||
}, m2.utcOffset = function() {
|
||||
return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
|
||||
}, m2.diff = function(r2, d2, l2) {
|
||||
var $2, y2 = O.p(d2), M3 = w(r2), m3 = (M3.utcOffset() - this.utcOffset()) * e, v2 = this - M3, g2 = O.m(this, M3);
|
||||
return g2 = ($2 = {}, $2[c] = g2 / 12, $2[f] = g2, $2[h] = g2 / 3, $2[o] = (v2 - m3) / 6048e5, $2[a] = (v2 - m3) / 864e5, $2[u] = v2 / n, $2[s] = v2 / e, $2[i] = v2 / t, $2)[y2] || v2, l2 ? g2 : O.a(g2);
|
||||
}, m2.daysInMonth = function() {
|
||||
return this.endOf(f).$D;
|
||||
}, m2.$locale = function() {
|
||||
return D[this.$L];
|
||||
}, m2.locale = function(t2, e2) {
|
||||
if (!t2)
|
||||
return this.$L;
|
||||
var n2 = this.clone(), r2 = S(t2, e2, true);
|
||||
return r2 && (n2.$L = r2), n2;
|
||||
}, m2.clone = function() {
|
||||
return O.w(this.$d, this);
|
||||
}, m2.toDate = function() {
|
||||
return new Date(this.valueOf());
|
||||
}, m2.toJSON = function() {
|
||||
return this.isValid() ? this.toISOString() : null;
|
||||
}, m2.toISOString = function() {
|
||||
return this.$d.toISOString();
|
||||
}, m2.toString = function() {
|
||||
return this.$d.toUTCString();
|
||||
}, M2;
|
||||
}(), T = _.prototype;
|
||||
return w.prototype = T, [["$ms", r], ["$s", i], ["$m", s], ["$H", u], ["$W", a], ["$M", f], ["$y", c], ["$D", d]].forEach(function(t2) {
|
||||
T[t2[1]] = function(e2) {
|
||||
return this.$g(e2, t2[0], t2[1]);
|
||||
};
|
||||
}), w.extend = function(t2, e2) {
|
||||
return t2.$i || (t2(e2, _, w), t2.$i = true), w;
|
||||
}, w.locale = S, w.isDayjs = p, w.unix = function(t2) {
|
||||
return w(1e3 * t2);
|
||||
}, w.en = D[g], w.Ls = D, w.p = {}, w;
|
||||
});
|
||||
}
|
||||
});
|
||||
export default require_dayjs_min();
|
||||
126
uni_modules/uv-ui-tools/libs/util/route.js
Normal file
126
uni_modules/uv-ui-tools/libs/util/route.js
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷
|
||||
* 并且带有路由拦截功能
|
||||
*/
|
||||
import { queryParams, deepMerge, page } from '@/uni_modules/uv-ui-tools/libs/function/index.js'
|
||||
class Router {
|
||||
constructor() {
|
||||
// 原始属性定义
|
||||
this.config = {
|
||||
type: 'navigateTo',
|
||||
url: '',
|
||||
delta: 1, // navigateBack页面后退时,回退的层数
|
||||
params: {}, // 传递的参数
|
||||
animationType: 'pop-in', // 窗口动画,只在APP有效
|
||||
animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效
|
||||
intercept: false ,// 是否需要拦截
|
||||
events: {} // 页面间通信接口,用于监听被打开页面发送到当前页面的数据。hbuilderx 2.8.9+ 开始支持。
|
||||
}
|
||||
// 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文
|
||||
// 这里在构造函数中进行this绑定
|
||||
this.route = this.route.bind(this)
|
||||
}
|
||||
|
||||
// 判断url前面是否有"/",如果没有则加上,否则无法跳转
|
||||
addRootPath(url) {
|
||||
return url[0] === '/' ? url : `/${url}`
|
||||
}
|
||||
|
||||
// 整合路由参数
|
||||
mixinParam(url, params) {
|
||||
url = url && this.addRootPath(url)
|
||||
|
||||
// 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary"
|
||||
// 如果有url中有get参数,转换后无需带上"?"
|
||||
let query = ''
|
||||
if (/.*\/.*\?.*=.*/.test(url)) {
|
||||
// object对象转为get类型的参数
|
||||
query = queryParams(params, false)
|
||||
// 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
|
||||
return url += `&${query}`
|
||||
}
|
||||
// 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号
|
||||
query = queryParams(params)
|
||||
return url += query
|
||||
}
|
||||
|
||||
// 对外的方法名称
|
||||
async route(options = {}, params = {}) {
|
||||
// 合并用户的配置和内部的默认配置
|
||||
let mergeConfig = {}
|
||||
|
||||
if (typeof options === 'string') {
|
||||
// 如果options为字符串,则为route(url, params)的形式
|
||||
mergeConfig.url = this.mixinParam(options, params)
|
||||
mergeConfig.type = 'navigateTo'
|
||||
} else {
|
||||
mergeConfig = deepMerge(this.config, options)
|
||||
// 否则正常使用mergeConfig中的url和params进行拼接
|
||||
mergeConfig.url = this.mixinParam(options.url, options.params)
|
||||
}
|
||||
// 如果本次跳转的路径和本页面路径一致,不执行跳转,防止用户快速点击跳转按钮,造成多次跳转同一个页面的问题
|
||||
if (mergeConfig.url === page()) return
|
||||
|
||||
if (params.intercept) {
|
||||
mergeConfig.intercept = params.intercept
|
||||
}
|
||||
// params参数也带给拦截器
|
||||
mergeConfig.params = params
|
||||
// 合并内外部参数
|
||||
mergeConfig = deepMerge(this.config, mergeConfig)
|
||||
// 判断用户是否定义了拦截器
|
||||
if (typeof mergeConfig.intercept === 'function') {
|
||||
// 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转
|
||||
const isNext = await new Promise((resolve, reject) => {
|
||||
mergeConfig.intercept(mergeConfig, resolve)
|
||||
})
|
||||
// 如果isNext为true,则执行路由跳转
|
||||
isNext && this.openPage(mergeConfig)
|
||||
} else {
|
||||
this.openPage(mergeConfig)
|
||||
}
|
||||
}
|
||||
|
||||
// 执行路由跳转
|
||||
openPage(config) {
|
||||
// 解构参数
|
||||
const {
|
||||
url,
|
||||
type,
|
||||
delta,
|
||||
animationType,
|
||||
animationDuration,
|
||||
events
|
||||
} = config
|
||||
if (config.type == 'navigateTo' || config.type == 'to') {
|
||||
uni.navigateTo({
|
||||
url,
|
||||
animationType,
|
||||
animationDuration,
|
||||
events
|
||||
})
|
||||
}
|
||||
if (config.type == 'redirectTo' || config.type == 'redirect') {
|
||||
uni.redirectTo({
|
||||
url
|
||||
})
|
||||
}
|
||||
if (config.type == 'switchTab' || config.type == 'tab') {
|
||||
uni.switchTab({
|
||||
url
|
||||
})
|
||||
}
|
||||
if (config.type == 'reLaunch' || config.type == 'launch') {
|
||||
uni.reLaunch({
|
||||
url
|
||||
})
|
||||
}
|
||||
if (config.type == 'navigateBack' || config.type == 'back') {
|
||||
uni.navigateBack({
|
||||
delta
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default (new Router()).route
|
||||
81
uni_modules/uv-ui-tools/package.json
Normal file
81
uni_modules/uv-ui-tools/package.json
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"id": "uv-ui-tools",
|
||||
"displayName": "uv-ui-tools 工具集 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.1.25",
|
||||
"description": "uv-ui-tools,集成工具库,强大的Http请求封装,清晰的文档说明,开箱即用。方便使用,可以全局使用",
|
||||
"keywords": [
|
||||
"uv-ui-tools,uv-ui组件库,工具集,uvui,uView2.x"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "y",
|
||||
"快手": "y",
|
||||
"飞书": "y",
|
||||
"京东": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "y",
|
||||
"联盟": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
uni_modules/uv-ui-tools/readme.md
Normal file
23
uni_modules/uv-ui-tools/readme.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## uv-ui-tools 工具集
|
||||
|
||||
> **组件名:uv-ui-tools**
|
||||
|
||||
uv-ui工具集成,包括网络Http请求、便捷工具、节流防抖、对象操作、时间格式化、路由跳转、全局唯一标识符、规则校验等等。
|
||||
|
||||
该组件推荐配合[uv-ui组件库](https://www.uvui.cn/components/intro.html)使用,单独下载也可以在自己项目中使用,需要做相应的配置,可查看文档。强烈推荐使用[uv-ui组件库](https://www.uvui.cn/components/intro.html),导入组件都会自动导入`uv-ui-tools`。需要在自己的项目中使用请参考[扩展配置](https://www.uvui.cn/components/setting.html)。
|
||||
|
||||
uv-ui破釜沉舟之兼容vue3+2、app、h5、多端小程序的uni-app生态框架,大部分组件基于uView2.x,在经过改进后全面支持vue3,部分组件做了进一步的优化,修复大量BUG,支持单独导入,方便开发者选择导入需要的组件。开箱即用,灵活配置。
|
||||
|
||||
# <a href="https://www.uvui.cn/js/intro.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
||||
43
uni_modules/uv-ui-tools/theme.scss
Normal file
43
uni_modules/uv-ui-tools/theme.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
// 此文件为uvUI的主题变量,这些变量目前只能通过uni.scss引入才有效,另外由于
|
||||
// uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大,
|
||||
// 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入
|
||||
|
||||
$uv-main-color: #303133;
|
||||
$uv-content-color: #606266;
|
||||
$uv-tips-color: #909193;
|
||||
$uv-light-color: #c0c4cc;
|
||||
$uv-border-color: #dadbde;
|
||||
$uv-bg-color: #f3f4f6;
|
||||
$uv-disabled-color: #c8c9cc;
|
||||
|
||||
$uv-primary: #3c9cff;
|
||||
$uv-primary-dark: #398ade;
|
||||
$uv-primary-disabled: #9acafc;
|
||||
$uv-primary-light: #ecf5ff;
|
||||
|
||||
$uv-warning: #f9ae3d;
|
||||
$uv-warning-dark: #f1a532;
|
||||
$uv-warning-disabled: #f9d39b;
|
||||
$uv-warning-light: #fdf6ec;
|
||||
|
||||
$uv-success: #5ac725;
|
||||
$uv-success-dark: #53c21d;
|
||||
$uv-success-disabled: #a9e08f;
|
||||
$uv-success-light: #f5fff0;
|
||||
|
||||
$uv-error: #f56c6c;
|
||||
$uv-error-dark: #e45656;
|
||||
$uv-error-disabled: #f7b2b2;
|
||||
$uv-error-light: #fef0f0;
|
||||
|
||||
$uv-info: #909399;
|
||||
$uv-info-dark: #767a82;
|
||||
$uv-info-disabled: #c4c6c9;
|
||||
$uv-info-light: #f4f4f5;
|
||||
|
||||
@mixin flex($direction: row) {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: $direction;
|
||||
}
|
||||
353
uni_modules/uv-ui/changelog.md
Normal file
353
uni_modules/uv-ui/changelog.md
Normal file
@@ -0,0 +1,353 @@
|
||||
## 1.1.20(2024-01-20)
|
||||
1. 优化 uv-loading-page重构,避免初始加载的时候先显示页面的问题,小程序平台由于性能问题,可能还是会短暂出现,请注意优化处理
|
||||
2. 优化 uv-textarea confirmType默认值改成return,支持换行
|
||||
3. 优化 uv-ui-tools luch-request更新
|
||||
4. 修复 uv-drop-down parentData不变的BUG
|
||||
5. 修复 uv-picker 上个版本引出的BUG
|
||||
6. 修复 uv-image 设置show-menu-by-longpress不生效的BUG
|
||||
7. 修复 uv-upload 动态设置deletable为false不生效的BUG
|
||||
## 1.1.19(2023-12-12)
|
||||
1. 优化 uv-toast部分重构,支持取消遮罩不影响点击其他元素 a. 增加z-index参数;b. 增加overlay参数
|
||||
2. 优化 关于组件如何阻止事件冒泡,增加相关说明:[组件怎么阻止事件冒泡](https://www.uvui.cn/components/feature.html#组件怎么阻止事件冒泡)
|
||||
3. 优化 持续优化文档
|
||||
4. 修复 uv-tabs current为字符串activeStyle不生效的BUG
|
||||
5. 修复 uv-vtabs 在change回调中设置current,快速点击菜单,导致死循环的BUG
|
||||
6. 修复 uv-cell right-icon插槽编译到APP端不显示的BUG,问题来源:[https://gitee.com/climblee/uv-ui/issues/I8LXZI](https://gitee.com/climblee/uv-ui/issues/I8LXZI)
|
||||
## 1.1.18(2023-11-28)
|
||||
0. 优化 uv-datetime-picker 增加round属性,设置弹窗圆角
|
||||
1. 优化 uv-subsection 增加customItemStyle属性,方便修改bar样式,比如设置圆角
|
||||
2. 修复 uv-picker issues反馈的问题uv-picker在组合式API的自定义组件中,columns动态赋值无法显示选项:[https://gitee.com/climblee/uv-ui/issues/I8H0GQ](https://gitee.com/climblee/uv-ui/issues/I8H0GQ)
|
||||
3. 修复 uv-popup issues问题:[https://gitee.com/climblee/uv-ui/issues/I8HDLO](https://gitee.com/climblee/uv-ui/issues/I8HDLO)
|
||||
4. 修复 uv-skeletons 支付宝小程序报错的BUG
|
||||
5. 修复 uv-image webp之前未使用的BUG & 微信报错的BUG
|
||||
6. 修复 uv-modal 上版本引出的确认和取消按钮均不显示,还有高度的BUG
|
||||
## 1.1.17(2023-11-10)
|
||||
0. 交流反馈 欢迎加入uv-ui官方群1交流反馈: 549833913(1000+)
|
||||
1. 交流反馈 欢迎加入uv-ui官方群2交流反馈: 206060892
|
||||
2. 新增 新增其他小组件下载入口:其他小组件
|
||||
3. 优化 uv-calendars 增加readonly属性,是否为只读状态,只读状态下禁止选择日期
|
||||
4. 修复 uv-search 禁用时,不能触发click的BUG
|
||||
5. 修复 uv-checkbox and uv-radio label文字过长,不换行的相关说明及处理
|
||||
6. 修复 uv-input and uv-search 点击clear按钮在微信小程序不好触发的BUG
|
||||
7. 修复 uv-list 修复设置ellipsis不生效的BUG
|
||||
8. 修复 uv-index-list 修复sticky属性不生效的BUG
|
||||
## 1.1.16(2023-10-30)
|
||||
1. 交流反馈 欢迎加入uv-ui官方群1交流反馈: 549833913(940+/1000)
|
||||
2. 交流反馈 欢迎加入uv-ui官方群2交流反馈: 206060892
|
||||
3. 新增 uv-skeletons 骨架屏,全新升级骨架屏,更加灵活,体验更加,强烈推荐使用新版骨架屏。一般用于页面在请求远程数据尚未完成时,在内容加载出来前展示与内容布局结构一致的灰白块,提升用户视觉体验。
|
||||
4. 优化 uv-button 增加后置插槽suffix,方便在按钮文字后面增加图标等
|
||||
5. 优化 uv-popup vue模式内容有背景色,设置圆角被遮挡的情况
|
||||
6. 优化 uv-tabs 点击一个选项,change事件重复派发的问题
|
||||
7. 优化 持续优化文档及其他
|
||||
8. 修复 uv-album 设置singleSize、multipleSize、space等值带单位,存在不显示的BUG
|
||||
9. 修复 uv-picker 省市级示例设置defaultValue,再次选择第二列错乱的BUG
|
||||
10. 修复 uv-icon imgMode默认值改成aspectFit,否则会导致支付宝平台name设置为本地图片显示不全的BUG
|
||||
11. 修复 uv-transition 在APP-IOS上不能正常显示的BUG
|
||||
12. 修复 uv-toast、uv-swipe-action、uv-sticky、uv-notify、uv-notice-bar、uv-grid、uv-count-down、uv-code等组件,unmounted兼容vue3
|
||||
## 1.1.15(2023-10-12)
|
||||
1. 优化 uv-keyboard a. 增加disKeys参数,mode = "car"下,被禁用的键,如:['I','O']; b. 增加customabc参数,mode = "car"下,是否启用自定义中英文切换内容模式,为了兼容支付宝等小程序不兼容嵌套插槽,导致同时显示自定义内容和原始内容; c. 增加ref方法changeCarMode,mode = "car"下, 调用此方法可以切换中英文模式; d. 增加@changeCarInputMode,mode = "car"下,调用此方法可以进行切换中英文; e. 增加插槽abc,mode = "car"下,自定义中英文切换内容
|
||||
2. 优化 uv-checkbox uv-radio 优化:https://gitee.com/climblee/uv-ui/issues/I872VD
|
||||
3. 优化 uv-picker 将immediate-change默认值改为true,该值在于change回调的及时性,微信小程序生效
|
||||
4. 优化 uv-tags 兼容customStyle参数等优化
|
||||
5. 修复 uv-transition 部分情况,修改某属性自动关闭的BUG
|
||||
6. 修复 uv-calendars 懒加载报错:https://gitee.com/climblee/uv-ui/issues/I869JS
|
||||
7. 修复 uv-datetime-picker 设置minDate出现选择错乱的BUG
|
||||
8. 修复 uv-input 搜狗输入法下存在不可清空的情况
|
||||
9. 修复 uv-calendars selected没有设置了info或者info设置为空字符串后,文本则无法恢复BUG
|
||||
## 1.1.14(2023-09-27)
|
||||
1. 优化 uv-list-item 可使用customStyle变量进行样式控制
|
||||
2. 优化 uv-cell 增加cellStyle参数,方便自定义单元格的样式
|
||||
3. 优化 uv-switch 优化细节
|
||||
4. 优化 不断优化[文档](https://www.uvui.cn/)
|
||||
5. 修复 uv-button 通过customStyle修改按钮宽度,组件中最外层节点不改变的问题
|
||||
6. 修复 uv-calendars a. 修复range模式下,selected设置了info后选中后,导致文本不恢复的问题;b. 修复multiple模式下,selected自定义信息的颜色没变,依然是白色
|
||||
7. 修复 uv-checkbox uv-checkbox-group之change回调中v-model值不更新的BUG
|
||||
## 1.1.13(2023-09-15)
|
||||
1. 优化 uv-button a. 增加参数iconSize,用于控制图标的大小;b. 增加open-type="agreePrivacyAuthorization"类型,用户同意隐私协议事件回调
|
||||
2. 优化 uv-picker 三级联动的案例:[https://www.uvui.cn/components/picker.html#省市区三级联动](https://www.uvui.cn/components/picker.html#省市区三级联动)
|
||||
3. 修复 uv-read-more 全局设置rpx时,导致展开高度不对的BUG
|
||||
4. 修复 uv-tabs a. 设置lineWidth未带单位产生的误差BUG;b. 首次加载时,处理下划线会有左到右的过渡效果
|
||||
5. 修复 uv-textaera 设置autoHeight后出现高度异常的BUG
|
||||
6. 修复 uv-input H5等情况设置禁用或可读情况下,点击事件无效的问题,nvue需要特殊处理
|
||||
7. 修复 uv-calendars a. 在vue2+小程序渲染时闪烁的问题;b. 增加allowSameDay参数,是否允许日期范围的起止时间为同一天,mode=range时有效
|
||||
8. 修复 uv-safe-bottom 兼容飞书小程序
|
||||
9. 修复 uv-album 添加依赖,避免导入运行有误
|
||||
10. 修复 uv-ui-tools 优化组件用到的相关
|
||||
## 1.1.12(2023-09-10)
|
||||
1. 修复 uv-popup a. h5初始zIndex错误的问题;b. 修复全局设置prop无效的问题
|
||||
2. 修复 uv-button 修复多个按钮由view包裹,显示在一行宽度不正常的BUG
|
||||
3. 修复 uv-modal a. 修复两个按钮之间竖线不显示的问题;b. uv-ui项目自定义按钮示例修复
|
||||
4. 修复 uv-calendars 修复国际化失效的BUG
|
||||
5. 修复 uv-keyboard 修复键盘change回调事件产生冲突的BUG
|
||||
## 1.1.11(2023-09-02)
|
||||
1. 优化 uv-calendars a. 去除range参数,由mode="range"替换;b. 新增mode参数,不传 / multiple / range,分别为单日期, 多个日期,选择日期范围;c. 与uv-calendar选择日期的功能保持一致
|
||||
2. 优化 uv-modal a. 增加align参数,设置文本对齐方式;b. 增加textStyle参数,扩展文本样式
|
||||
3. 优化 uv-datetime-picker a. 增加mode="year"模式,方便只选择年;b. 增加clearDate参数,是否清除上次选择
|
||||
4. 修复 uv-ui-tools 设置customstyle同名计算属性报错:The computed property "customStyle" is already defined as a prop
|
||||
5. 修复 uv-image a. 设置widthFix时出现显示不全的BUG;b. 修复抖音等平台在width和height属性改变时出现不显示的BUG
|
||||
6. 修复 uv-checkbox 点击空隙处或label插槽内容不会选中的问题
|
||||
7. 修复 uv-radio 点击空隙处或label插槽内容不会选中的问题
|
||||
8. 修复 uv-calendars 在pages.json中设置easycom会报错的BUG
|
||||
9. 修复 uv-index-list 设置customNavHeight导致定位不准确的BUG
|
||||
## 1.1.10(2023-08-30)
|
||||
1. 交流反馈 欢迎加入uv-ui官方群1交流反馈: 549833913
|
||||
2. 交流反馈 欢迎加入uv-ui官方群2交流反馈: 206060892
|
||||
3. 优化 uv-calendars 1. 去除range参数,由mode="range"替换;2. 新增mode参数,不传 / multiple / range,分别为单日期, 多个日期,选择日期范围;3. 与uv-calendar选择日期的功能保持一致
|
||||
4. 新增 uv-album 新增相册组件及相关文档
|
||||
5. 优化 其他优化
|
||||
6. 修复 uv-text app-nvue设置align不生效的BUG
|
||||
7. 修复 uv-drop-down 自定义内容,点击自定义内容时会自动关闭弹窗的问题
|
||||
8. 修复 uv-image 异步修改宽高不生效的问题,问题来源:https://gitee.com/climblee/uv-ui/issues/I7WUQ3
|
||||
9. 修复 uv-calendars 通过setConfig修改属性不生效的问题,出自评论区:https://ext.dcloud.net.cn/plugin?id=12287
|
||||
10. 修复 uv-list 设置边框不生效的BUG
|
||||
## 1.1.9(2023-08-27)
|
||||
1. 优化 uv-calendars 1. 去除range参数,由mode="range"替换;2. 新增mode参数,不传 / multiple / range,分别为单日期, 多个日期,选择日期范围;3. 与uv-calendar选择日期的功能保持一致
|
||||
2. 优化 uv-picker 增加round属性,设置圆角
|
||||
3. 修复 uv-calendars 点击返回今天按钮时,monthSwitch方法回调参数返回月份不是当天对应月份
|
||||
4. 修复 uv-radio 1. 设置 labelSize 属性设置无效的问题:https://gitee.com/climblee/uv-ui/issues/I7W6UN;2. v-model 绑定布尔值控制台报警:https://gitee.com/climblee/uv-ui/issues/I7W714
|
||||
5. 修复 uv-checkbox 1. 设置 label 属性为布尔值不生效的BUG
|
||||
## 1.1.8(2023-08-24)
|
||||
1. 优化 uv-popup 弹出不丝滑优化思路:https://www.uvui.cn/components/popup.html#yh
|
||||
2. 修复 uv-switch 取消value传值,只能使用v-model传值,避免异步操作不生效的BUG
|
||||
3. 修复 uv-index-list ios端滚动过程中+快速点击右侧导航页面出现空白的BUG
|
||||
4. 修复 uv-rate 1. 支付宝报错的BUG; 2. 不能选半星的BUG
|
||||
5. 修复 uv-model 异步loading时,确认回调还会一直触发的BUG
|
||||
6. 修复 uv-swiper 标题文字过多未隐藏掉的BUG
|
||||
7. 修复 uv-text app-nvue编译不能自动换行的BUG
|
||||
## 1.1.7(2023-08-22)
|
||||
1. 优化 uv-drop-down a. 增加@change回调,返回弹窗关闭状态; b. 增加init方法,方便位置改变进行调整
|
||||
2. 优化 部分文档优化
|
||||
3. 修复 uv-input a. app-nvue-ios端不能输入的BUG;b. 键盘高度等值不返回BUG
|
||||
4. 修复 uv-scroll-list 报错导致不能移动指示器的BUG
|
||||
5. 修复 uv-search 边距值在上次更新中误改导致不对的BUG
|
||||
6. 修复 uv-image 设置width和height为100%不生效的BUG
|
||||
## 1.1.6(2023-08-18)
|
||||
1. 优化 优化文档
|
||||
2. 修复 uv-list 使用列表右侧显示 switch,switchChange回调中返回数据为undefined的BUG
|
||||
3. 修复 uv-checkbox 数据多不换行的BUG
|
||||
4. 修复 uv-upload 1. 图片预览位置错误的BUG;2. 视频预览不生效的BUG;3. 改变上传视频宽高不生效的BUG
|
||||
5. 修复 uv-navbar 在部分ios高版本机型,返回按钮不好操作的问题
|
||||
6. 修复 uv-waterfall 只有一条数据的时候,切换的时候数据会左右显示错误的BUG
|
||||
## 1.1.5(2023-08-14)
|
||||
1. 优化 uv-pick-color 删除scrollTop参数,内部修改后就不需要了
|
||||
2. 优化 uv-loading-icon 增加textStyle参数,可自定义文本样式,比如给上边距
|
||||
3. 修复 uv-safe-bottom 百度小程序报错的BUG
|
||||
4. 修复 uv-form 设置labelWidth属性时,节点渲染有闪动的BUG
|
||||
5. 修复 uv-grid 设置col属性时,节点渲染有闪动的BUG
|
||||
6. 修复 uv-parse 阻止a标签跳转文档说明
|
||||
## 1.1.4(2023-08-13)
|
||||
1. 优化 nvue自定义图标 [详细文档-nvue中自定义图标库](https://www.uvui.cn/guide/customIcon.html#nvue%E4%B8%AD%E8%87%AA%E5%AE%9A%E4%B9%89%E5%9B%BE%E6%A0%87%E5%BA%93)
|
||||
2. 优化 uv.$uv.http 在APP.vue页面使用报错的BUG: [Api集中管理](https://www.uvui.cn/js/http.html#_3-api%E9%9B%86%E4%B8%AD%E7%AE%A1%E7%90%86)
|
||||
3. 修复 uv-navbar app-nvue运行ios存在背景图片错乱的问题
|
||||
4. 修复 uv-list app-nvue运行ios存在,分包页面不滚动
|
||||
5. 修复 uv-textarea 值为null或undefined时显示错误的bug
|
||||
6. 修复 uv-search 值为null或undefined时显示错误的bug
|
||||
7. 修复 uv-scroll-list vue2编译报错的BUG
|
||||
8. 修复 uv-calendars 选择月份弹窗层级的问题
|
||||
9. 修复 uv-form 动画在vue3 setup语法糖中错乱,以及表单其他相关问题解决: [Issues](https://gitee.com/my_dear_li_pan/uv-ui/issues/I7SNTT)
|
||||
10. 修复 uv-picker-color 滚动页面无法点击的BUG:增加scrollTop参数,设置滚动条的位置。不设置如果页面出现滚动就需要传该值,会出现颜色面板无法进行选颜色的情况。
|
||||
11. 交流反馈 欢迎加入uv-ui官方群1交流反馈: [549833913](https://www.uvui.cn/components/addQQGroup.html)
|
||||
12. 交流反馈 欢迎加入uv-ui官方群2交流反馈: [206060892](https://www.uvui.cn/components/addQQGroup.html)
|
||||
## 1.1.3(2023-08-06)
|
||||
1. 优化 uv-calendars 1. 增加startText参数; 2. 增加endText参数; 3. 增加selected中的参数; 4. 优化日历范围选择
|
||||
2. 优化 uv-empty icon属性支持base64图片
|
||||
3. 优化 uv-navbar 增加背景图片的裁剪模式参数imgMode
|
||||
4. 优化 uv-picker-color 颜色值不对的BUG
|
||||
5. 优化 [API文档优化](https://www.uvui.cn/components/changelog.html)
|
||||
6. 优化 常见问题增加:[怎么隐藏uv-tabs等组件的滚动条](https://www.uvui.cn/components/problem.html#%E4%B9%9D%E3%80%81%E6%80%8E%E4%B9%88%E9%9A%90%E8%97%8Fuv-tabs%E7%AD%89%E7%BB%84%E4%BB%B6%E7%9A%84%E6%BB%9A%E5%8A%A8%E6%9D%A1)
|
||||
7. 修复 uv-radio name为数字0时不能选中的BUG
|
||||
8. 修复 uv-textarea 1. v-model设置为数据时的BUG;2. 复制过多内容,计数显示错误的BUG;3. maxlength为-1改成不显示计数
|
||||
9. 修复 uv-code-input 在vue2模式下,v-model设置为0时不生效的BUG
|
||||
10. 修复 uv-input 在vue2模式下,v-model设置为0时不生效的BUG
|
||||
11. 修复 uv-search 在vue2模式下,v-model设置为0时不生效的BUG
|
||||
12. 修复 uv-ui-tools 1. 路由拦截修复;2. 增加events参数
|
||||
## 1.1.2(2023-08-03)
|
||||
1. 新增 uv-calendars 新版日历发布
|
||||
2. 新增 uv-toolbar 组件独立发布,老用户更新uv-picker,需要手动删除uv-picker目录下的uv-toolbar目录,否则会有冲突提示
|
||||
3. 优化 uv-tags 增加cellChild参数
|
||||
4. 优化 uv-navbar 兼容背景图片
|
||||
5. 优化 uv-notice-bar 竖向滚动时候增加change回调
|
||||
## 1.1.1(2023-07-30)
|
||||
1. 新增 uv-drop-down 下拉筛选组件,兼容app-nvue及多端
|
||||
2. 优化 uv-textarea 增加confirm-hold参数,方便设置进行换行处理
|
||||
3. 优化 其他关于文档的优化等
|
||||
## 1.1.0(2023-07-26)
|
||||
1. 重构 uv-list 全面重构,提高性能,放弃使用scroll-view,具体文档参考:uv-list列表
|
||||
2. 优化 uv-search 1. 增加prefix和suffix 前置和后置插槽;2. 增加boxStyle参数,方便控制输入框部分的样式
|
||||
3. 优化 文档优化:获取节点布局信息,文档新增nvue获取方式的说明
|
||||
## 1.0.22(2023-07-26)
|
||||
1. 优化 uv-textarea 组件 增加textStyle和countStyle属性,方便控制文本样式
|
||||
2. 优化 uv-swiper 增加竖向播放属性:vertical
|
||||
3. 优化 uv-icon 支持base64图片格式
|
||||
4. 优化 uv-transition 和 uv-image 增加参数cellChild属性,避免nvue中出现回收后不显示的BUG
|
||||
5. 优化 uv-button 增加customTextStyle属性,方便自定义按钮文字样式
|
||||
6. 优化 优化部分文档说明
|
||||
7. 修复 uv-slider 修改背景颜色属性为backgroundColor,避免设置不生效
|
||||
8. 修复 uv-index-list 1. 修复全局设置成rpx存在的高度BUG;2. 修复其他BUG
|
||||
## 1.0.21(2023-07-22)
|
||||
1. 新增 uv-scroll-list 横向滚动列表组件
|
||||
2. 优化 增加测试占位图,方便开发者使用线上图片进行测试:[https://www.uvui.cn/components/testPic.html](https://www.uvui.cn/components/testPic.html)
|
||||
3. 优化 uv-calendar 组件文档示例等优化,增加setFormatter说明
|
||||
4. 优化 uv-notice-bar 优化文档,说明不显示左边图标的使用方法
|
||||
5. 修复 uv-input 在微信小程序端清除内容存在不能清除的BUG
|
||||
6. 修复 uv-button 1. 解决微信小程序动态设置hover-class点击态不消失的BUG; 2. 文档优化
|
||||
7. 修复 uv-waterfall 在tab切换等场景快速切换时,会出现报错的BUG
|
||||
8. 优化 优化其他
|
||||
## 1.0.20(2023-07-18)
|
||||
1. 修复 uv-textarea 设置-1不生效
|
||||
2. 修复 uv-icon 恢复uv-empty相关的图标
|
||||
3. 修复 uv-empty 恢复设置mode属性的内置图标
|
||||
4. 优化 [优化文档](https://www.uvui.cn)
|
||||
## 1.0.19(2023-07-14)
|
||||
1. 优化 uv-waterfall 当changeList未处理数据时,正确返回对应列的数据,避免误导
|
||||
2. 修复 uv-rate VUE3模式下设置value属性不生效的BUG
|
||||
3. 修复 uv-input VUE3模式下设置value属性不生效的BUG
|
||||
4. 修复 uv-search VUE3模式下设置value属性不生效的BUG
|
||||
5. 修复 uv-code-input VUE3模式下设置value属性不生效的BUG
|
||||
6. 修复 uv-number-box VUE3模式下设置value属性不生效的BUG
|
||||
7. 修复 uv-radio VUE3模式下设置value属性不生效的BUG
|
||||
8. 修复 uv-checkbox VUE3模式下设置value属性不生效的BUG
|
||||
9. 修复 uv-textarea VUE3模式下设置value属性不生效的BUG
|
||||
10. 修复 uv-switch VUE3模式下设置value属性不生效的BUG
|
||||
11. 修复 uv-slider VUE3模式下设置value属性不生效的BUG
|
||||
12. 修复 uv-datetime-picker VUE3模式下设置value属性不生效的BUG
|
||||
13. 修复 uv-icon 部分图标错误的BUG
|
||||
## 1.0.18(2023-07-06)
|
||||
1. 优化 uv-icon 1. 更新图标,删除一些不常用的图标;2. 删除base64,修改成ttf文件引入读取图标。uv-icon 图标
|
||||
2. 优化 uv-icon nvue自定义图标用法,文档说明:[点击跳转](https://www.uvui.cn/guide/customIcon.html)
|
||||
3. 优化 uv-upload 文档示例代码,增加fileList参数说明:[点击跳转](https://www.uvui.cn/components/upload.html#filelist-options)
|
||||
4. 修复 uv-checkbox vue3模式下,动态修改v-model绑定的值无效的BUG
|
||||
5. 修复 uv-radio vue3模式下,动态修改v-model绑定的值无效的BUG
|
||||
6. 修复 uv-datetime-picker vue3模式下,动态修改v-model绑定的值无效的BUG
|
||||
## 1.0.17(2023-07-04)
|
||||
1. 优化 uv-icon 修复,NVUE平台主题颜色在APP不生效的BUG
|
||||
2. 优化 uv-notice-bar 优化,增加disableScroll属性
|
||||
3. 优化 uv-input uv-back-top uv-cell uv-form uv-search uv-modal uv-navbar uv-index-list uv-empty uv-upload 去除插槽判断,避免某些平台不显示的BUG
|
||||
4. 优化 uv-form 优化文档
|
||||
5. 优化 优化其他相关文档
|
||||
## 1.0.16(2023-07-03)
|
||||
1. 优化 uv-transition 动画组件,代码重构优化,性能更加友好,增加自定义动画功能。详情[参考文档](https://www.uvui.cn/components/transition.html)
|
||||
2. 优化 uv-popup 弹出层,代码重构优化,性能翻倍,小程序体验性能更加,避免卡顿。打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/popup.html)
|
||||
3. 优化 uv-calendar 由于弹出层uv-popup的修改,打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/actionSheet.html)
|
||||
4. 优化 uv-action-sheet 由于弹出层uv-popup的修改,打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/calendar.html)
|
||||
5. 优化 uv-datetime-picker 由于弹出层uv-popup的修改,打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/datetimePicker.html)
|
||||
6. 优化 uv-form 由于弹出层uv-transition的修改,组件内部做了相应的修改,参数不变。
|
||||
7. 优化 uv-keyboard 由于弹出层uv-popup的修改,打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/keyboard.html)
|
||||
8. 优化 uv-modal 由于弹出层uv-popup的修改,打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/modal.html)
|
||||
9. 优化 uv-notify 由于弹出层uv-popup的修改,打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/notify.html)
|
||||
10. 优化 uv-overlay 由于弹出层uv-transition的修改,组件内部做了相应的修改,参数不变。
|
||||
11. 优化 uv-pick-color 由于弹出层uv-popup的修改,打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/pickColor.html)
|
||||
12. 优化 uv-picker 由于弹出层uv-popup的修改,打开和关闭方法更改,详情[参考文档](https://www.uvui.cn/components/picker.html)
|
||||
13. 优化 uv-tooltip 由于弹出层uv-transition的修改,组件内部做了相应的修改,参数不变。
|
||||
14. 优化 uv-loading-page 由于弹出层uv-transition的修改,组件内部做了相应的修改,参数不变。
|
||||
15. 优化 相关文档的优化更改。
|
||||
16. 修复 uv-safe-bottom 修复,在百度程序,抖音小程序不生效的BUG
|
||||
## 1.0.15(2023-06-29)
|
||||
1. 欢迎加QQ群交流:[549833913](https://www.uvui.cn/components/addQQGroup.html)
|
||||
2. 优化 uv-swiper 优化:1. 增加titleStyle属性,方便修改标题样式;2. 标题上去掉是否是图片的判断,避免无后缀的图片不显示
|
||||
3. 优化 uv-steps 优化:1. 增加插槽title; 3. 文档关于插槽相关的参数说明完善;增加customStyle属性
|
||||
4. 优化 uv-checkbox 优化:增加label文字插槽,与radio保持一致,优化文档相关说明
|
||||
5. 优化 uv-modal 优化:增加closeLoading方法,方便异步加载手动取消加载状态,更新文档
|
||||
6. 优化 uv-image 增加文档说明:uv-list、 uv-waterfall等组件在 Android平台使用了list封装,所以在该组件中仍然不能使用uv-image等组件
|
||||
7. 优化 优化更多文档
|
||||
8. 修复 uv-vtabs 修复非联动情况下,内容过多的情况,滚动一段距离,再切换未滚动到顶部的BUG
|
||||
9. 修复 uv-image 修复:duration属性不生效的BUG
|
||||
10. 修复 uv-code-input 修复:使用:disabledKeyboard="true"属性,事件全部失效的BUG
|
||||
11. 修复 uv-button 修复:设置open-type="chooseAvatar"等值不生效的BUG
|
||||
## 1.0.14(2023-06-25)
|
||||
1. 欢迎加QQ群交流:[549833913](https://www.uvui.cn/components/addQQGroup.html)
|
||||
2. 优化 uv-count-down 增加外部样式customStyle参数
|
||||
3. 优化 文档的全面优化
|
||||
4. 修复 uv-count-to 1. 修复继续滚动的函数 2. 修改文档错误 4. 适配px和rpx的单位 4. 适配customStyle参数
|
||||
5. 修复 uv-load-more 修复customStyle参数设置背景等不生效的BUG
|
||||
6. 修复 uv-code-input 优化下边框
|
||||
7. 修复 uv-tabs 添加uv-icon依赖
|
||||
8. 修复 uv-grid 优化修改
|
||||
9. 修复 uv-cell 优化修改
|
||||
## 1.0.13(2023-06-20)
|
||||
1. 优化 uv-calendar formatter格式化中增加topInfo参数
|
||||
2. 优化 uv-tabs 增加customStyle参数
|
||||
3. 优化 文档优化,便于开发者直接开干
|
||||
4. 优化 uv-switch 优化size属性,适配单位传递
|
||||
5. 修复 uv-ui-tools、uv-form、uv-picker 修复vue3编译支付宝异常
|
||||
6. 修复 uv-ui-tools、uv-form、uv-picker 修复vue3编译支付宝异常
|
||||
7. 修复 uv-parse 修复在nvue不显示的BUG
|
||||
8. 修复 uv-form 修复某些条件下报错的BUG
|
||||
## 1.0.12(2023-06-14)
|
||||
1. 优化部分组件,优化文档部分细节
|
||||
2. uv-popup、uv-modal 修复遮罩层zIndex问题
|
||||
3. uv-form 在vue3的setup语法中ref使用uvForm会导致报错
|
||||
4. uv-tabs activeStyle设置字体大小,可能会导致下划线位置不对BUG
|
||||
5. uv-pick-color 百度小程序点击报错
|
||||
6. uv-transition 恢复this.$nextTick
|
||||
7. uv-picker 抖音小程序选择的时候报错,导致不能关闭的BUG
|
||||
8. uv-checkbox 多余的属性labelDisabled,导致APP中报错提示
|
||||
9. uv-tabbar 底部安全距离组件无效的BUG
|
||||
10. uv-vtabs 头部存在的时候,联动不准确的BUG
|
||||
## 1.0.11(2023-06-12)
|
||||
1. uv-radio-group、uv-checkbox-group 兼容自定义样式customStyle,方便通过样式调整整体位置等,数据较多时允许换行
|
||||
2. uv-ui-tools 优化内置样式等,解决微信小程序使用uvui提示 Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors,[详情](https://www.uvui.cn/components/problem.html)
|
||||
3. uv-datetime-picker 取消defaultIndex参数,目前传该值也没实际意义
|
||||
4. uv-tabbar 增加iconSize参数
|
||||
5. uv-calendar 增加change回调
|
||||
6. uv-calendar 修复BUG
|
||||
7. uv-rate 修复只读或禁止状态下设置value无效的问题
|
||||
8. uv-popup 修复zIndex问题
|
||||
9. uv-modal 修复zIndex问题
|
||||
10. 文档-扩展配置更新:[扩展配置](https://www.uvui.cn/components/setting.html)
|
||||
11. 文档-优化更新:[uv-ui文档](https://www.uvui.cn/components/changelog.html)
|
||||
12. 文档-新增常见问题:[常见问题](https://www.uvui.cn/components/problem.html)
|
||||
13. 优化其他
|
||||
## 1.0.10(2023-06-05)
|
||||
1. uv-navbar 渐变背景色兼容
|
||||
2. uv-calendar 日历选择BUG修复
|
||||
## 1.0.9(2023-06-05)
|
||||
1. 新增uv-vtabs垂直选项卡组件,主要用于分类展示,分类切换功能,支持联动和不联动两种模式
|
||||
2. uv-qrcode,uv-datetime-picker,uv-subsection等文档说明优化,避免开发困难;优化API相关说明
|
||||
3. uv-notice-bar 1. 修复在触发error函数报错的BUG;2. 修复在text值为undefined的时候,解决报错BUG
|
||||
4. uv-button 等组件修复触发两次事件的BUG
|
||||
5. uv-datetime-picker 1. 修复重置值存在不更新的BUG;2. 优化文档,增加filter使用方法说明
|
||||
6. uv-badge 修复type等属性为null或undefined的时候不显示徽标的BUG
|
||||
7. uv-ui-tools 优化工具组件,兼容更多功能,小程序分享功能优化等
|
||||
...
|
||||
## 1.0.8(2023-05-27)
|
||||
1. uv-waterfall修复在百度小程序中可能存在的BUG;去掉原有的slot方式
|
||||
2. uv-image修复可能报错的问题
|
||||
3. uv-pick-color 在文档预览模式中无法点击的问题
|
||||
4. uv-index-list 修复select事件不触发的问题
|
||||
5. 优化其他组件及示例项目等
|
||||
## 1.0.7(2023-05-25)
|
||||
1. uv-icon 将线上ttf字体包替换成base64,避免加载时或者网络差时候显示白色方块
|
||||
2. uv-text 去掉多余的data-index属性,避免警告
|
||||
3. uv-upload 在fileList的watch中增加deep属性
|
||||
4. uv-pick-color 去掉template中存在的this.导致头条小程序编译警告
|
||||
5. uv-image 去掉template中存在的this.导致头条小程序编译警告
|
||||
## 1.0.6(2023-05-23)
|
||||
1. 新增uv-pick-color颜色选择器组件
|
||||
2. uv-toolbar组件增加showBorder属性,是否显示下边框
|
||||
3. uv-transition组件在百度小程序等平台不支持this.$nextick导致下面的逻辑不执行,使用延时替换方案
|
||||
4. uv-ui-tools组件中bem()函数兼容百度/头条小程序等
|
||||
5. uv-waterfall组件修复在百度/头条小程序显示异常等BUG,增加changeList回调函数处理数据,同步更新示例等
|
||||
6. uv-image组件修复在百度/头条小程序等开启observeLazyLoad后显示异常BUG
|
||||
7. uv-tabs组件修复上次更新导致的在nvue中不滚动的BUG
|
||||
8. uv-qrcode组件修复在部分平台不显示加载的BUG
|
||||
9. 修复其他已知问题等
|
||||
## 1.0.5(2023-05-17)
|
||||
1. 新增uv-qrcode二维码组件
|
||||
2. 修复uv-tooltip在vue2模式下的BUG
|
||||
3. 优化部分问题
|
||||
## 1.0.4(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.3(2023-05-12)
|
||||
1. 修复uv-input在vue3模式下双向绑定问题
|
||||
2. 修复uv-textarea在vue3模式下双向绑定问题
|
||||
3. 修复uv-rate在vue3模式下双向绑定问题
|
||||
## 1.0.2(2023-05-11)
|
||||
1. 更新文档
|
||||
2. 增加插件下载入口
|
||||
## 1.0.1(2023-05-10)
|
||||
1. 所有组件依赖
|
||||
2. 上传示例项目
|
||||
## 1.0.0(2023-05-10)
|
||||
1. uv-ui
|
||||
7
uni_modules/uv-ui/components/uv-ui/uv-ui.vue
Normal file
7
uni_modules/uv-ui/components/uv-ui/uv-ui.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<view>占位组件,请勿使用;如需下载示例项目,请使用【下载插件并导入HBuilderX】或【使用 HBuilderX 导入示例项目】或【下载示例项目ZIP】</view>
|
||||
</template>
|
||||
<script>
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
162
uni_modules/uv-ui/package.json
Normal file
162
uni_modules/uv-ui/package.json
Normal file
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"id": "uv-ui",
|
||||
"displayName": "uv-ui 破釜沉舟之兼容vue3+2、app、h5、小程序等多端,灵活导入,利剑出击",
|
||||
"version": "1.1.20",
|
||||
"description": "uv-ui 是基于uni-app、部分组件基于uView2.x、全端兼容、支持独立导入、内容丰富的UI框架。破釜沉舟之兼容vue3+2、app、h5、小程序等多端,利剑出击,开箱即用。",
|
||||
"keywords": [
|
||||
"uv-ui",
|
||||
"uvui",
|
||||
"UI组件库",
|
||||
"ui框架",
|
||||
"ui库"
|
||||
],
|
||||
"repository": "https://github.com/climblee/uv-ui",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@climblee/uv-ui"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-skeletons",
|
||||
"uv-album",
|
||||
"uv-drop-down",
|
||||
"uv-calendars",
|
||||
"uv-scroll-list",
|
||||
"uv-vtabs",
|
||||
"uv-pick-color",
|
||||
"uv-qrcode",
|
||||
"uv-ui-tools",
|
||||
"uv-action-sheet",
|
||||
"uv-alert",
|
||||
"uv-avatar",
|
||||
"uv-back-top",
|
||||
"uv-badge",
|
||||
"uv-button",
|
||||
"uv-calendar",
|
||||
"uv-cell",
|
||||
"uv-checkbox",
|
||||
"uv-code",
|
||||
"uv-code-input",
|
||||
"uv-collapse",
|
||||
"uv-count-down",
|
||||
"uv-count-to",
|
||||
"uv-datetime-picker",
|
||||
"uv-divider",
|
||||
"uv-empty",
|
||||
"uv-form",
|
||||
"uv-gap",
|
||||
"uv-grid",
|
||||
"uv-icon",
|
||||
"uv-image",
|
||||
"uv-index-list",
|
||||
"uv-input",
|
||||
"uv-keyboard",
|
||||
"uv-line",
|
||||
"uv-line-progress",
|
||||
"uv-link",
|
||||
"uv-list",
|
||||
"uv-loading-icon",
|
||||
"uv-loading-page",
|
||||
"uv-load-more",
|
||||
"uv-modal",
|
||||
"uv-navbar",
|
||||
"uv-no-network",
|
||||
"uv-notice-bar",
|
||||
"uv-notify",
|
||||
"uv-number-box",
|
||||
"uv-overlay",
|
||||
"uv-parse",
|
||||
"uv-picker",
|
||||
"uv-popup",
|
||||
"uv-radio",
|
||||
"uv-rate",
|
||||
"uv-read-more",
|
||||
"uv-row",
|
||||
"uv-safe-bottom",
|
||||
"uv-search",
|
||||
"uv-skeleton",
|
||||
"uv-slider",
|
||||
"uv-status-bar",
|
||||
"uv-steps",
|
||||
"uv-sticky",
|
||||
"uv-subsection",
|
||||
"uv-swipe-action",
|
||||
"uv-swiper",
|
||||
"uv-switch",
|
||||
"uv-tabbar",
|
||||
"uv-tabs",
|
||||
"uv-tags",
|
||||
"uv-text",
|
||||
"uv-textarea",
|
||||
"uv-toast",
|
||||
"uv-tooltip",
|
||||
"uv-transition",
|
||||
"uv-upload",
|
||||
"uv-waterfall"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
164
uni_modules/uv-ui/readme.md
Normal file
164
uni_modules/uv-ui/readme.md
Normal file
@@ -0,0 +1,164 @@
|
||||
<p align="center">
|
||||
<span> </span><img alt="logo" src="https://www.uvui.cn/common/logo.png" width="120" height="120">
|
||||
</p>
|
||||
<h3 align="center">uv-ui</h3>
|
||||
<h3 align="center">兼容vue3+2多平台快速开发的UI框架</h3>
|
||||
|
||||
[](https://gitee.com/climblee/uv-ui)
|
||||
[](https://gitee.com/climblee/uv-ui)
|
||||
[](https://github.com/climblee/uv-ui)
|
||||
[](https://github.com/climblee/uv-ui/issues)
|
||||
[](https://www.uvui.cn)
|
||||
[](https://www.uvui.cn/components/changelog.html)
|
||||
[](https://en.wikipedia.org/wiki/MIT_License)
|
||||
|
||||
## 温馨提示:如需下载uv-ui示例项目,请不要使用【下载插件ZIP】按钮。
|
||||
|
||||
### uvui官方群1:<a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=aaoyDvfV7nSee9vzWfzyZM1vKlu3xrNZ&authKey=pdU6HDpyzGUoc1QvQvCmzCbwzsoHgBbToF%2F0ChP4lNjPIPgWHGRE4I99XYGiTcNI&noverify=0&group_code=549833913" target="_blank">549833913</a>
|
||||
### uvui官方群2:<a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=2QbEeKBn6ysCyQ09V4mgst1W8onxFybQ&authKey=aMTGL5zCYwsinG%2FeH0qMlAqXAdyKr5AjXVf2oMnsmj7NCg%2F2HraMU%2FNFxELLIPvp&noverify=0&group_code=206060892" target="_blank">206060892</a>
|
||||
|
||||
## uvui特点
|
||||
|
||||
1. **uv-ui的前世今生**,`uv-ui` 是基于 `uview2.x` 版本改造而来。重命名也是为了避开发布冲突和很多组件 `u-`在 `nvue` 中不能使用的情况,所以这才诞生了`uv-ui`。感谢 `uview-ui` 作者的开源奉献,再次为开源点赞。 同时 `uv-ui` 也是无条件开源。
|
||||
|
||||
2. **全端兼容**,`uv-ui`支持vue3、vue2、app-vue、app-nvue、h5、小程序等。`uv-ui`的组件都是多端自适应的,底层会抹平很多小程序平台的差异或bug。
|
||||
|
||||
3. **扩展配置**,`uv-ui`内置的方法默认不再挂载到`uni`对象之上,也就意味着默认情况下不能在项目中直接使用`uni.$uv.xxx`使用内置方法。但是可以通过扩展可以解决,通过如下方式进行配置即可,使用方式请参考[扩展配置](https://www.uvui.cn/components/setting.html)。其中包括[ JS工具库](https://www.uvui.cn/components/setting.html#%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE-js%E5%B7%A5%E5%85%B7%E5%BA%93)、[ 自定义主题](https://www.uvui.cn/components/setting.html#%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE-%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%BB%E9%A2%98)、[ 基础样式](https://www.uvui.cn/components/setting.html#%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE-%E5%9F%BA%E7%A1%80%E6%A0%B7%E5%BC%8F)、[ setconfig](https://www.uvui.cn/components/setting.html#%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE-setconfig)等。
|
||||
|
||||
## 预览
|
||||
|
||||
通过微信(APP下载不支持微信扫码)或浏览器扫码查看演示效果。
|
||||
|
||||
<img src="https://mp-31ed6237-7b7b-4597-8448-a53d6d6031cf.cdn.bspapp.com/uvui/download-wx.png" width="200" /> <img src="https://mp-31ed6237-7b7b-4597-8448-a53d6d6031cf.cdn.bspapp.com/uvui/download-app.png" width="200" /> <img src="https://mp-31ed6237-7b7b-4597-8448-a53d6d6031cf.cdn.bspapp.com/uvui/download-h5.png" width="200" />
|
||||
|
||||
## 链接
|
||||
|
||||
- [官方文档](https://www.uvui.cn)
|
||||
- [演示地址](https://h5.uvui.cn)
|
||||
- [更新日志](https://www.uvui.cn/components/changelog.html)
|
||||
- [关于我们](https://www.uvui.cn/cooperation/about.html)
|
||||
- <a href="#list">组件列表</a>
|
||||
|
||||
## 交流反馈
|
||||
|
||||
欢迎加入我们的QQ群交流反馈:[点此跳转](https://www.uvui.cn/components/addQQGroup.html)
|
||||
|
||||
## 快速开始
|
||||
|
||||
方式一:`uv-ui` 强烈建议通过 `下载插件并导入HbuilderX` 导入组件。
|
||||
|
||||
方式二:下载完整 [uv-ui项目](https://ext.dcloud.net.cn/plugin?id=12287) 将 `uni_modules` 复制到自己的项目。
|
||||
|
||||
方式三:通过 `npm i @climblee/uv-ui` 下载,此方法需要配置 easycom,配置详情可查看[安装](https://www.uvui.cn/components/install.html)。
|
||||
|
||||
请通过[快速上手](https://www.uvui.cn/components/quickstart.html)了解更详细的内容。
|
||||
|
||||
**注意:导入插件后,建议`HBuilderX`重新运行项目,可能新导入的插件不能实时更新而导致不能运行。**
|
||||
|
||||
## 使用方法
|
||||
|
||||
组件导入 `uni_modules` 后,直接在项目中使用,无需通过import引入组件。
|
||||
|
||||
```html
|
||||
<template>
|
||||
<uv-icon name="baidu" size="30" color="#909399"></uv-icon>
|
||||
</template>
|
||||
```
|
||||
|
||||
## 扩展功能
|
||||
|
||||
`uv-ui` 内置了强大的工具函数、请求封装等,可以根据自身需求进行扩展配置,详情请查看[扩展配置](https://www.uvui.cn/components/setting.html)。
|
||||
|
||||
**注意:只有[扩展配置](https://www.uvui.cn/components/setting.html)后才能在自己的项目页面中使用组件库内置方法和变量等**。
|
||||
|
||||
<div id="list"></div>
|
||||
|
||||
## 组件列表
|
||||
|
||||
下表为 `uv-ui` 的扩展组件清单,点击每个组件**点击下载&安装**即可在详情页面导入组件到项目下,导入后建议重新运行即可直接使用,组件无需import和注册。
|
||||
|
||||
| 组件名 | 组件说明 |
|
||||
| --- | --- |
|
||||
| uv-skeletons | [新版骨架屏(推荐)](https://www.uvui.cn/components/skeletons.html) |
|
||||
| uv-calendars | [新版日历(推荐)](https://www.uvui.cn/components/calendars.html) |
|
||||
| uv-drop-down | [下拉筛选](https://www.uvui.cn/components/dropDown.html) |
|
||||
| uv-scroll-list | [横向滚动列表](https://www.uvui.cn/components/scrollList.html) |
|
||||
| uv-vtabs | [垂直选项卡](https://www.uvui.cn/components/vtabs.html) |
|
||||
| uv-pick-color | [颜色选择器](https://www.uvui.cn/components/pickColor.html) |
|
||||
| uv-qrcode | [二维码](https://www.uvui.cn/components/qrcode.html) |
|
||||
| uv-waterfall | [瀑布流](https://www.uvui.cn/components/waterfall.html) |
|
||||
| uv-row | [Layout 布局](https://www.uvui.cn/components/layout.html) |
|
||||
| uv-icon | [图标](https://www.uvui.cn/components/icon.html) |
|
||||
| uv-button | [按钮](https://www.uvui.cn/components/button.html) |
|
||||
| uv-text | [文本](https://www.uvui.cn/components/text.html) |
|
||||
| uv-link | [超链接](https://www.uvui.cn/components/link.html) |
|
||||
| uv-image | [图片](https://www.uvui.cn/components/image.html) |
|
||||
| uv-transition | [动画](https://www.uvui.cn/components/transition.html) |
|
||||
| uv-form | [表单](https://www.uvui.cn/components/form.html) |
|
||||
| uv-input | [增强输入框](https://www.uvui.cn/components/input.html) |
|
||||
| uv-textarea | [增强文本域](https://www.uvui.cn/components/textarea.html) |
|
||||
| uv-checkbox | [复选框](https://www.uvui.cn/components/checkbox.html) |
|
||||
| uv-radio | [单选框](https://www.uvui.cn/components/radio.html) |
|
||||
| uv-switch | [开关选择器](https://www.uvui.cn/components/switch.html) |
|
||||
| uv-calendar | [日历](https://www.uvui.cn/components/calendar.html) |
|
||||
| uv-picker | [选择器](https://www.uvui.cn/components/picker.html) |
|
||||
| uv-datetime-picker | [时间选择器](https://www.uvui.cn/components/datetimePicker.html) |
|
||||
| uv-code | [验证码倒计时](https://www.uvui.cn/components/code.html) |
|
||||
| uv-keyboard | [键盘](https://www.uvui.cn/components/keyboard.html) |
|
||||
| uv-rate | [评分](https://www.uvui.cn/components/rate.html) |
|
||||
| uv-search | [多功能搜索框](https://www.uvui.cn/components/search.html) |
|
||||
| uv-number-box | [步进器](https://www.uvui.cn/components/numberBox.html) |
|
||||
| uv-upload | [上传](https://www.uvui.cn/components/upload.html) |
|
||||
| uv-slider | [滑动选择器](https://www.uvui.cn/components/slider.html) |
|
||||
| uv-list | [列表](https://www.uvui.cn/components/list.html) |
|
||||
| uv-index-list | [索引列表](https://www.uvui.cn/components/indexList.html) |
|
||||
| uv-tags | [标签](https://www.uvui.cn/components/tag.html) |
|
||||
| uv-line-progress | [线形进度条](https://www.uvui.cn/components/lineProgress.html) |
|
||||
| uv-badge | [徽标数](https://www.uvui.cn/components/badge.html) |
|
||||
| uv-count-down | [倒计时](https://www.uvui.cn/components/countDown.html) |
|
||||
| uv-count-to | [数字滚动](https://www.uvui.cn/components/countTo.html) |
|
||||
| uv-avatar | [头像](https://www.uvui.cn/components/avatar.html) |
|
||||
| uv-skeleton | [骨架屏](https://www.uvui.cn/components/skeleton.html) |
|
||||
| uv-loading-icon | [加载动画](https://www.uvui.cn/components/loadingIcon.html) |
|
||||
| uv-loading-page | [加载页](https://www.uvui.cn/components/loadingPage.html) |
|
||||
| uv-load-more | [加载更多](https://www.uvui.cn/components/loadMore.html) |
|
||||
| uv-empty | [内容为空](https://www.uvui.cn/components/empty.html) |
|
||||
| uv-tooltip | [长按提示](https://www.uvui.cn/components/tooltip.html) |
|
||||
| uv-alert | [警告提示](https://www.uvui.cn/components/alert.html) |
|
||||
| uv-toast | [消息提示](https://www.uvui.cn/components/toast.html) |
|
||||
| uv-notice-bar | [滚动通知](https://www.uvui.cn/components/noticeBar.html) |
|
||||
| uv-notify | [消息提示](https://www.uvui.cn/components/notify.html) |
|
||||
| uv-no-network | [无网络提示](https://www.uvui.cn/components/noNetwork.html) |
|
||||
| uv-popup | [弹出层](https://www.uvui.cn/components/popup.html) |
|
||||
| uv-modal | [模态框](https://www.uvui.cn/components/modal.html) |
|
||||
| uv-cell | [单元格](https://www.uvui.cn/components/cell.html) |
|
||||
| uv-swipe-action | [滑动单元格](https://www.uvui.cn/components/swipeAction.html) |
|
||||
| uv-swiper | [轮播图](https://www.uvui.cn/components/swiper.html) |
|
||||
| uv-collapse | [折叠面板](https://www.uvui.cn/components/collapse.html) |
|
||||
| uv-grid | [宫格布局](https://www.uvui.cn/components/grid.html) |
|
||||
| uv-album | [相册](https://www.uvui.cn/components/album.html) |
|
||||
| uv-tabbar | [底部导航栏](https://www.uvui.cn/components/tabbar.html) |
|
||||
| uv-back-top | [返回顶部](https://www.uvui.cn/components/backTop.html) |
|
||||
| uv-navbar | [自定义导航栏](https://www.uvui.cn/components/navbar.html) |
|
||||
| uv-action-sheet | [底部操作菜单](https://www.uvui.cn/components/actionSheet.html) |
|
||||
| uv-tabs | [标签选项卡](https://www.uvui.cn/components/tabs.html) |
|
||||
| uv-steps | [步骤条](https://www.uvui.cn/components/steps.html) |
|
||||
| uv-subsection | [分段器](https://www.uvui.cn/components/subsection.html) |
|
||||
| uv-sticky | [吸顶](https://www.uvui.cn/components/sticky.html) |
|
||||
| uv-parse | [富文本解析器](https://www.uvui.cn/components/parse.html) |
|
||||
| uv-overlay | [遮罩层](https://www.uvui.cn/components/overlay.html) |
|
||||
| uv-code-input | [验证码输入](https://www.uvui.cn/components/codeInput.html) |
|
||||
| uv-read-more | [展开阅读更多](https://www.uvui.cn/components/readMore.html) |
|
||||
| uv-line | [线条](https://www.uvui.cn/components/line.html) |
|
||||
| uv-gap | [间隔槽](https://www.uvui.cn/components/gap.html) |
|
||||
| uv-divider | [分割线](https://www.uvui.cn/components/divider.html) |
|
||||
|
||||
## 版权信息
|
||||
uv-ui遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uv-ui应用到您的产品中。
|
||||
|
||||
## 作者想说
|
||||
- 开源真的不易,不图大家的钱财,所以希望大家多多鼓励支持,希望不要恶意评论,有问题加群快速解决。
|
||||
- 遇到BUG,是一件很正常的事情,是程序肯定就有BUG,所以希望大家能以理解的心态去提出BUG,然后作者才有动力去努力修复。
|
||||
- 最后觉得好用的小伙伴,不要吝啬你的双手,给个好评就是给我们最大的鼓励。
|
||||
|
||||
# 恶评者手下留情,有事加QQ群解决:549833913
|
||||
15
uni_modules/zero-markdown-view/changelog.md
Normal file
15
uni_modules/zero-markdown-view/changelog.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## 2.0.5(2024-04-24)
|
||||
## 流式输出代码块解决方案
|
||||
## 2.0.4(2023-12-06)
|
||||
### 长按复制代码改为点击代码块复制
|
||||
## 2.0.3(2023-10-30)
|
||||
doc: 文档说明
|
||||
## 2.0.2(2023-10-30)
|
||||
- 新增长按复制代码-仅小程序可用
|
||||
- 新增代码块语言显示
|
||||
## 2.0.1(2023-10-27)
|
||||
##支持vue2,vue3
|
||||
## 2.0.0(2022-11-01)
|
||||
使用mp-html自带的插件,重新生成uniapp包,大幅减少插件体积
|
||||
## 1.0.0(2022-09-13)
|
||||
首次发布
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user