提交 25d5eda6 编写于 作者: DCloud_JSON's avatar DCloud_JSON
上级 067bc559
## 1.2.1(2022-09-05)
- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
## 1.2.0(2021-11-19) ## 1.2.0(2021-11-19)
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge) - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
......
<template> <template>
<view class="uni-badge--x"> <view class="uni-badge--x">
<slot /> <slot />
<text v-if="text" :class="classNames" :style="[badgeWidth, positionStyle, customStyle, dotStyle]" <text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
class="uni-badge" @click="onClick()">{{displayValue}}</text> class="uni-badge" @click="onClick()">{{displayValue}}</text>
</view> </view>
</template> </template>
...@@ -130,16 +130,13 @@ ...@@ -130,16 +130,13 @@
const match = whiteList[this.absolute] const match = whiteList[this.absolute]
return match ? match : whiteList['rightTop'] return match ? match : whiteList['rightTop']
}, },
badgeWidth() {
return {
width: `${this.width}px`
}
},
dotStyle() { dotStyle() {
if (!this.isDot) return {} if (!this.isDot) return {}
return { return {
width: '10px', width: '10px',
minWidth: '0',
height: '10px', height: '10px',
padding: '0',
borderRadius: '10px' borderRadius: '10px'
} }
}, },
...@@ -160,7 +157,7 @@ ...@@ -160,7 +157,7 @@
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" >
$uni-primary: #2979ff !default; $uni-primary: #2979ff !default;
$uni-success: #4cd964 !default; $uni-success: #4cd964 !default;
$uni-warning: #f0ad4e !default; $uni-warning: #f0ad4e !default;
...@@ -199,6 +196,8 @@ ...@@ -199,6 +196,8 @@
justify-content: center; justify-content: center;
flex-direction: row; flex-direction: row;
height: 20px; height: 20px;
min-width: 20px;
padding: 0 4px;
line-height: 18px; line-height: 18px;
color: #fff; color: #fff;
border-radius: 100px; border-radius: 100px;
...@@ -207,6 +206,7 @@ ...@@ -207,6 +206,7 @@
border: 1px solid #fff; border: 1px solid #fff;
text-align: center; text-align: center;
font-family: 'Helvetica Neue', Helvetica, sans-serif; font-family: 'Helvetica Neue', Helvetica, sans-serif;
font-feature-settings: "tnum";
font-size: $bage-size; font-size: $bage-size;
/* #ifdef H5 */ /* #ifdef H5 */
z-index: 999; z-index: 999;
......
{ {
"id": "uni-badge", "id": "uni-badge",
"displayName": "uni-badge 数字角标", "displayName": "uni-badge 数字角标",
"version": "1.2.0", "version": "1.2.1",
"description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。", "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
"keywords": [ "keywords": [
"", "",
...@@ -18,11 +18,7 @@ ...@@ -18,11 +18,7 @@
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
}, },
"dcloudext": { "dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": { "sale": {
"regular": { "regular": {
"price": "0.00" "price": "0.00"
...@@ -39,10 +35,11 @@ ...@@ -39,10 +35,11 @@
"data": "无", "data": "无",
"permissions": "无" "permissions": "无"
}, },
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
}, },
"uni_modules": { "uni_modules": {
"dependencies": [], "dependencies": ["uni-scss"],
"encrypt": [], "encrypt": [],
"platforms": { "platforms": {
"cloud": { "cloud": {
......
## 1.0.3(2022-09-16)
- 可以使用 uni-scss 控制主题色
## 1.0.2(2022-06-30)
- 优化 在 uni-forms 中的依赖注入方式
## 1.0.1(2022-02-07) ## 1.0.1(2022-02-07)
- 修复 multiple 为 true 时,v-model 的值为 null 报错的 bug - 修复 multiple 为 true 时,v-model 的值为 null 报错的 bug
## 1.0.0(2021-11-19) ## 1.0.0(2021-11-19)
......
...@@ -155,17 +155,17 @@ ...@@ -155,17 +155,17 @@
value(newVal) { value(newVal) {
this.dataList = this.getDataList(newVal) this.dataList = this.getDataList(newVal)
// fix by mehaotian is_reset 在 uni-forms 中定义 // fix by mehaotian is_reset 在 uni-forms 中定义
if(!this.is_reset){ // if(!this.is_reset){
this.is_reset = false // this.is_reset = false
this.formItem && this.formItem.setValue(newVal) // this.formItem && this.formItem.setValue(newVal)
} // }
}, },
modelValue(newVal) { modelValue(newVal) {
this.dataList = this.getDataList(newVal); this.dataList = this.getDataList(newVal);
if(!this.is_reset){ // if(!this.is_reset){
this.is_reset = false // this.is_reset = false
this.formItem && this.formItem.setValue(newVal) // this.formItem && this.formItem.setValue(newVal)
} // }
} }
}, },
data() { data() {
...@@ -193,22 +193,22 @@ ...@@ -193,22 +193,22 @@
} }
}, },
created() { created() {
this.form = this.getForm('uniForms') // this.form = this.getForm('uniForms')
this.formItem = this.getForm('uniFormsItem') // this.formItem = this.getForm('uniFormsItem')
// this.formItem && this.formItem.setValue(this.value) // this.formItem && this.formItem.setValue(this.value)
if (this.formItem) { // if (this.formItem) {
this.isTop = 6 // this.isTop = 6
if (this.formItem.name) { // if (this.formItem.name) {
// 如果存在name添加默认值,否则formData 中不存在这个字段不校验 // // 如果存在name添加默认值,否则formData 中不存在这个字段不校验
if(!this.is_reset){ // if(!this.is_reset){
this.is_reset = false // this.is_reset = false
this.formItem.setValue(this.dataValue) // this.formItem.setValue(this.dataValue)
} // }
this.rename = this.formItem.name // this.rename = this.formItem.name
this.form.inputChildrens.push(this) // this.form.inputChildrens.push(this)
} // }
} // }
if (this.localdata && this.localdata.length !== 0) { if (this.localdata && this.localdata.length !== 0) {
this.isLocal = true this.isLocal = true
...@@ -273,7 +273,7 @@ ...@@ -273,7 +273,7 @@
} }
} }
} }
this.formItem && this.formItem.setValue(detail.value) // this.formItem && this.formItem.setValue(detail.value)
// TODO 兼容 vue2 // TODO 兼容 vue2
this.$emit('input', detail.value); this.$emit('input', detail.value);
// // TOTO 兼容 vue3 // // TOTO 兼容 vue3
...@@ -375,7 +375,7 @@ ...@@ -375,7 +375,7 @@
selectedArr.push(item[this.map.value]) selectedArr.push(item[this.map.value])
} }
}) })
return this.dataValue && this.dataValue.length > 0 ? this.dataValue : selectedArr return this.dataValue.length > 0 ? this.dataValue : selectedArr
}, },
/** /**
...@@ -384,12 +384,14 @@ ...@@ -384,12 +384,14 @@
setStyleBackgroud(item) { setStyleBackgroud(item) {
let styles = {} let styles = {}
let selectedColor = this.selectedColor?this.selectedColor:'#2979ff' let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
if (this.selectedColor) {
if (this.mode !== 'list') { if (this.mode !== 'list') {
styles['border-color'] = item.selected?selectedColor:'#DCDFE6' styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
} }
if (this.mode === 'tag') { if (this.mode === 'tag') {
styles['background-color'] = item.selected? selectedColor:'#f5f5f5' styles['background-color'] = item.selected? selectedColor:'#f5f5f5'
} }
}
let classles = '' let classles = ''
for (let i in styles) { for (let i in styles) {
classles += `${i}:${styles[i]};` classles += `${i}:${styles[i]};`
...@@ -399,6 +401,7 @@ ...@@ -399,6 +401,7 @@
setStyleIcon(item) { setStyleIcon(item) {
let styles = {} let styles = {}
let classles = '' let classles = ''
if (this.selectedColor) {
let selectedColor = this.selectedColor?this.selectedColor:'#2979ff' let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
styles['background-color'] = item.selected?selectedColor:'#fff' styles['background-color'] = item.selected?selectedColor:'#fff'
styles['border-color'] = item.selected?selectedColor:'#DCDFE6' styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
...@@ -407,7 +410,7 @@ ...@@ -407,7 +410,7 @@
styles['background-color'] = '#F2F6FC' styles['background-color'] = '#F2F6FC'
styles['border-color'] = item.selected?selectedColor:'#DCDFE6' styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
} }
}
for (let i in styles) { for (let i in styles) {
classles += `${i}:${styles[i]};` classles += `${i}:${styles[i]};`
} }
...@@ -416,6 +419,7 @@ ...@@ -416,6 +419,7 @@
setStyleIconText(item) { setStyleIconText(item) {
let styles = {} let styles = {}
let classles = '' let classles = ''
if (this.selectedColor) {
let selectedColor = this.selectedColor?this.selectedColor:'#2979ff' let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
if (this.mode === 'tag') { if (this.mode === 'tag') {
styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:'#fff'):'#666' styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:'#fff'):'#666'
...@@ -425,7 +429,7 @@ ...@@ -425,7 +429,7 @@
if(!item.selected && item.disabled){ if(!item.selected && item.disabled){
styles.color = '#999' styles.color = '#999'
} }
}
for (let i in styles) { for (let i in styles) {
classles += `${i}:${styles[i]};` classles += `${i}:${styles[i]};`
} }
...@@ -448,7 +452,7 @@ ...@@ -448,7 +452,7 @@
</script> </script>
<style lang="scss"> <style lang="scss">
$checked-color: #2979ff; $uni-primary: #2979ff !default;
$border-color: #DCDFE6; $border-color: #DCDFE6;
$disable:0.4; $disable:0.4;
...@@ -614,8 +618,8 @@ ...@@ -614,8 +618,8 @@
// 选中 // 选中
&.is-checked { &.is-checked {
.checkbox__inner { .checkbox__inner {
border-color: $checked-color; border-color: $uni-primary;
background-color: $checked-color; background-color: $uni-primary;
.checkbox__inner-icon { .checkbox__inner-icon {
opacity: 1; opacity: 1;
...@@ -623,14 +627,14 @@ ...@@ -623,14 +627,14 @@
} }
} }
.radio__inner { .radio__inner {
border-color: $checked-color; border-color: $uni-primary;
.radio__inner-icon { .radio__inner-icon {
opacity: 1; opacity: 1;
background-color: $checked-color; background-color: $uni-primary;
} }
} }
.checklist-text { .checklist-text {
color: $checked-color; color: $uni-primary;
} }
// 选中禁用 // 选中禁用
&.is-disable { &.is-disable {
...@@ -683,10 +687,10 @@ ...@@ -683,10 +687,10 @@
} }
&.is-checked { &.is-checked {
border-color: $checked-color; border-color: $uni-primary;
.checkbox__inner { .checkbox__inner {
border-color: $checked-color; border-color: $uni-primary;
background-color: $checked-color; background-color: $uni-primary;
.checkbox__inner-icon { .checkbox__inner-icon {
opacity: 1; opacity: 1;
transform: rotate(45deg); transform: rotate(45deg);
...@@ -694,16 +698,16 @@ ...@@ -694,16 +698,16 @@
} }
.radio__inner { .radio__inner {
border-color: $checked-color; border-color: $uni-primary;
.radio__inner-icon { .radio__inner-icon {
opacity: 1; opacity: 1;
background-color: $checked-color; background-color: $uni-primary;
} }
} }
.checklist-text { .checklist-text {
color: $checked-color; color: $uni-primary;
} }
// 选中禁用 // 选中禁用
...@@ -735,8 +739,8 @@ ...@@ -735,8 +739,8 @@
} }
&.is-checked { &.is-checked {
background-color: $checked-color; background-color: $uni-primary;
border-color: $checked-color; border-color: $uni-primary;
.checklist-text { .checklist-text {
color: #fff; color: #fff;
...@@ -775,8 +779,8 @@ ...@@ -775,8 +779,8 @@
&.is-checked { &.is-checked {
.checkbox__inner { .checkbox__inner {
border-color: $checked-color; border-color: $uni-primary;
background-color: $checked-color; background-color: $uni-primary;
.checkbox__inner-icon { .checkbox__inner-icon {
opacity: 1; opacity: 1;
...@@ -789,13 +793,13 @@ ...@@ -789,13 +793,13 @@
} }
} }
.checklist-text { .checklist-text {
color: $checked-color; color: $uni-primary;
} }
.checklist-content { .checklist-content {
.checkobx__list { .checkobx__list {
opacity: 1; opacity: 1;
border-color: $checked-color; border-color: $uni-primary;
} }
} }
......
{ {
"id": "uni-data-checkbox", "id": "uni-data-checkbox",
"displayName": "uni-data-checkbox 数据选择器", "displayName": "uni-data-checkbox 数据选择器",
"version": "1.0.1", "version": "1.0.3",
"description": "通过数据驱动的单选框和复选框", "description": "通过数据驱动的单选框和复选框",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
...@@ -17,11 +17,7 @@ ...@@ -17,11 +17,7 @@
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
}, },
"dcloudext": { "dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": { "sale": {
"regular": { "regular": {
"price": "0.00" "price": "0.00"
...@@ -38,7 +34,8 @@ ...@@ -38,7 +34,8 @@
"data": "无", "data": "无",
"permissions": "无" "permissions": "无"
}, },
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
}, },
"uni_modules": { "uni_modules": {
"dependencies": ["uni-load-more","uni-scss"], "dependencies": ["uni-load-more","uni-scss"],
......
## 1.1.1(2022-09-19)
- 修复,输入后回车,change 事件触发两次,[详情](https://ask.dcloud.net.cn/question/152149)
## 1.1.0(2022-06-30)
- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
- 新增 clear 事件,点击右侧叉号图标触发
- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
-
## 1.0.5(2022-06-07)
- 优化 clearable 显示策略
## 1.0.4(2022-06-07)
- 优化 clearable 显示策略
## 1.0.3(2022-05-20) ## 1.0.3(2022-05-20)
- 修复 关闭图标某些情况下无法取消的bug - 修复 关闭图标某些情况下无法取消的bug
## 1.0.2(2022-04-12) ## 1.0.2(2022-04-12)
......
<template> <template>
<view class="uni-easyinput" :class="{'uni-easyinput-error':msg}" :style="{color:inputBorder && msg?'#e43d33':styles.color}"> <view class="uni-easyinput" :class="{'uni-easyinput-error':msg}" :style="boxStyle">
<view class="uni-easyinput__content" :class="{'is-input-border':inputBorder ,'is-input-error-border':inputBorder && msg,'is-textarea':type==='textarea','is-disabled':disabled}" <view class="uni-easyinput__content" :class="inputContentClass" :style="inputContentStyle">
:style="{'border-color':inputBorder && msg?'#dd524d':styles.borderColor,'background-color':disabled?styles.disableColor:''}"> <uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc"
<uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')"></uni-icons> @click="onClickIcon('prefix')" size="22"></uni-icons>
<textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea" :class="{'input-padding':inputBorder}" <textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea"
:name="name" :value="val" :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" placeholder-class="uni-easyinput__placeholder-class" :class="{'input-padding':inputBorder}" :name="name" :value="val" :placeholder="placeholder"
:maxlength="inputMaxlength" :focus="focused" :autoHeight="autoHeight" @input="onInput" @blur="onBlur" @focus="onFocus" :placeholderStyle="placeholderStyle" :disabled="disabled"
@confirm="onConfirm"></textarea> placeholder-class="uni-easyinput__placeholder-class" :maxlength="inputMaxlength" :focus="focused"
<input v-else :type="type === 'password'?'text':type" class="uni-easyinput__content-input" :style="{ :autoHeight="autoHeight" @input="onInput" @blur="_Blur" @focus="_Focus" @confirm="onConfirm"></textarea>
'padding-right':type === 'password' ||clearable || prefixIcon?'':'10px', <input v-else :type="type === 'password'?'text':type" class="uni-easyinput__content-input"
'padding-left':prefixIcon?'':'10px' :style="inputStyle" :name="name" :value="val" :password="!showPassword && type === 'password'"
}" :placeholder="placeholder" :placeholderStyle="placeholderStyle"
:name="name" :value="val" :password="!showPassword && type === 'password'" :placeholder="placeholder" placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength"
:placeholderStyle="placeholderStyle" placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" :confirmType="confirmType" @focus="onFocus" :focus="focused" :confirmType="confirmType" @focus="_Focus" @blur="_Blur" @input="onInput"
@blur="onBlur" @input="onInput" @confirm="onConfirm" /> @confirm="onConfirm" />
<template v-if="type === 'password' && passwordIcon" > <template v-if="type === 'password' && passwordIcon">
<uni-icons v-if="val" class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}" :type="showPassword?'eye-slash-filled':'eye-filled'" <!-- 开启密码时显示小眼睛 -->
:size="18" color="#c0c4cc" @click="onEyes"></uni-icons> <uni-icons v-if="isVal" class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}"
:type="showPassword?'eye-slash-filled':'eye-filled'" :size="22"
:color="focusShow?'#2979ff':'#c0c4cc'" @click="onEyes">
</uni-icons>
</template> </template>
<template v-else-if="suffixIcon"> <template v-else-if="suffixIcon">
<uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')"></uni-icons> <uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc"
@click="onClickIcon('suffix')" size="22"></uni-icons>
</template> </template>
<template v-else> <template v-else>
<uni-icons class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}" type="clear" :size="clearSize" <uni-icons v-if="clearable && isVal && !disabled && type !== 'textarea'" class="content-clear-icon"
v-if="clearable && val && !disabled" color="#c0c4cc" @click="onClear"></uni-icons> :class="{'is-textarea-icon':type==='textarea'}" type="clear" :size="clearSize"
:color="msg?'#dd524d':(focusShow?'#2979ff':'#c0c4cc')" @click="onClear"></uni-icons>
</template> </template>
<slot name="right"></slot> <slot name="right"></slot>
</view> </view>
...@@ -31,10 +36,6 @@ ...@@ -31,10 +36,6 @@
</template> </template>
<script> <script>
// import {
// debounce,
// throttle
// } from './common.js'
/** /**
* Easyinput 输入框 * Easyinput 输入框
* @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。 * @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。
...@@ -48,7 +49,7 @@ ...@@ -48,7 +49,7 @@
* @value idcard 身份证输入键盘,信、支付宝、百度、QQ小程序 * @value idcard 身份证输入键盘,信、支付宝、百度、QQ小程序
* @value digit 带小数点的数字键盘 ,App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持 * @value digit 带小数点的数字键盘 ,App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持
* @property {Boolean} clearable 是否显示右侧清空内容的图标控件,点击可清空输入框内容(默认true) * @property {Boolean} clearable 是否显示右侧清空内容的图标控件,点击可清空输入框内容(默认true)
* @property {Boolean} autoHeight 是否自动增高输入区域,type为textarea时有效(默认false) * @property {Boolean} autoHeight 是否自动增高输入区域,type为textarea时有效(默认true)
* @property {String } placeholder 输入框的提示文字 * @property {String } placeholder 输入框的提示文字
* @property {String } placeholderStyle placeholder的样式(内联样式,字符串),如"color: #ddd" * @property {String } placeholderStyle placeholder的样式(内联样式,字符串),如"color: #ddd"
* @property {Boolean} focus 是否自动获得焦点(默认false) * @property {Boolean} focus 是否自动获得焦点(默认false)
...@@ -76,13 +77,44 @@ ...@@ -76,13 +77,44 @@
* @event {Function} iconClick 点击图标时触发 * @event {Function} iconClick 点击图标时触发
* @example <uni-easyinput v-model="mobile"></uni-easyinput> * @example <uni-easyinput v-model="mobile"></uni-easyinput>
*/ */
function obj2strClass(obj) {
let classess = ''
for (let key in obj) {
const val = obj[key]
if (val) {
classess += `${key} `
}
}
return classess
}
function obj2strStyle(obj) {
let style = ''
for (let key in obj) {
const val = obj[key]
style += `${key}:${val};`
}
return style
}
export default { export default {
name: 'uni-easyinput', name: 'uni-easyinput',
emits:['click','iconClick','update:modelValue','input','focus','blur','confirm'], emits: ['click', 'iconClick', 'update:modelValue', 'input', 'focus', 'blur', 'confirm', 'clear', 'eyes', 'change'],
model:{ model: {
prop:'modelValue', prop: 'modelValue',
event:'update:modelValue' event: 'update:modelValue'
},
options: {
virtualHost: true
},
inject: {
form: {
from: 'uniForm',
default: null
},
formItem: {
from: 'uniFormItem',
default: null
},
}, },
props: { props: {
name: String, name: String,
...@@ -100,7 +132,10 @@ ...@@ -100,7 +132,10 @@
type: Boolean, type: Boolean,
default: false default: false
}, },
placeholder: String, placeholder: {
type: String,
default: ' '
},
placeholderStyle: String, placeholderStyle: String,
focus: { focus: {
type: Boolean, type: Boolean,
...@@ -120,7 +155,7 @@ ...@@ -120,7 +155,7 @@
}, },
clearSize: { clearSize: {
type: [Number, String], type: [Number, String],
default: 15 default: 24
}, },
inputBorder: { inputBorder: {
type: Boolean, type: Boolean,
...@@ -138,7 +173,7 @@ ...@@ -138,7 +173,7 @@
type: [Boolean, String], type: [Boolean, String],
default: true default: true
}, },
passwordIcon:{ passwordIcon: {
type: Boolean, type: Boolean,
default: true default: true
}, },
...@@ -152,79 +187,106 @@ ...@@ -152,79 +187,106 @@
} }
} }
}, },
errorMessage:{ errorMessage: {
type:[String,Boolean], type: [String, Boolean],
default:'' default: ''
} }
}, },
data() { data() {
return { return {
focused: false, focused: false,
errMsg: '',
val: '', val: '',
showMsg: '', showMsg: '',
border: false, border: false,
isFirstBorder: false, isFirstBorder: false,
showClearIcon: false, showClearIcon: false,
showPassword: false showPassword: false,
focusShow: false,
localMsg: '',
isEnter: false // 用于判断当前是否是使用回车操作
}; };
}, },
computed: { computed: {
// 输入框内是否有值
isVal() {
const val = this.val
// fixed by mehaotian 处理值为0的情况,字符串0不在处理范围
if (val || val === 0) {
return true
}
return false
},
msg() { msg() {
return this.errorMessage || this.errMsg; // console.log('computed', this.form, this.formItem);
// if (this.form) {
// return this.errorMessage || this.formItem.errMsg;
// }
// TODO 处理头条 formItem 中 errMsg 不更新的问题
return this.localMsg || this.errorMessage
}, },
// 因为uniapp的input组件的maxlength组件必须要数值,这里转为数值,用户可以传入字符串数值 // 因为uniapp的input组件的maxlength组件必须要数值,这里转为数值,用户可以传入字符串数值
inputMaxlength() { inputMaxlength() {
return Number(this.maxlength); return Number(this.maxlength);
}, },
// 处理外层样式的style
boxStyle() {
return `color:${this.inputBorder && this.msg?'#e43d33':this.styles.color};`
},
// input 内容的类和样式处理
inputContentClass() {
return obj2strClass({
'is-input-border': this.inputBorder,
'is-input-error-border': this.inputBorder && this.msg,
'is-textarea': this.type === 'textarea',
'is-disabled': this.disabled
})
},
inputContentStyle() {
const focusColor = this.focusShow ? '#2979ff' : this.styles.borderColor
const borderColor = this.inputBorder && this.msg ? '#dd524d' : focusColor
return obj2strStyle({
'border-color': borderColor || '#e5e5e5',
'background-color': this.disabled ? this.styles.disableColor : '#fff'
})
},
// input右侧样式
inputStyle() {
const paddingRight = this.type === 'password' || this.clearable || this.prefixIcon ? '' : '10px'
return obj2strStyle({
'padding-right': paddingRight,
'padding-left': this.prefixIcon ? '' : '10px'
})
}
}, },
watch: { watch: {
value(newVal) { value(newVal) {
if (this.errMsg) this.errMsg = ''
this.val = newVal this.val = newVal
// fix by mehaotian is_reset 在 uni-forms 中定义
if (this.form && this.formItem &&!this.is_reset) {
this.is_reset = false
this.formItem.setValue(newVal)
}
}, },
modelValue(newVal) { modelValue(newVal) {
if (this.errMsg) this.errMsg = ''
this.val = newVal this.val = newVal
if (this.form && this.formItem &&!this.is_reset) {
this.is_reset = false
this.formItem.setValue(newVal)
}
}, },
focus(newVal) { focus(newVal) {
this.$nextTick(() => { this.$nextTick(() => {
this.focused = this.focus this.focused = this.focus
this.focusShow = this.focus
}) })
} }
}, },
created() { created() {
if(!this.value && this.value !== 0){ this.init()
this.val = this.modelValue // TODO 处理头条vue3 computed 不监听 inject 更改的问题(formItem.errMsg)
}
if(!this.modelValue && this.modelValue !== 0){
this.val = this.value
}
this.form = this.getForm('uniForms')
this.formItem = this.getForm('uniFormsItem')
if (this.form && this.formItem) { if (this.form && this.formItem) {
if (this.formItem.name) { this.$watch('formItem.errMsg', (newVal) => {
if(!this.is_reset){ this.localMsg = newVal
this.is_reset = false })
this.formItem.setValue(this.val)
}
this.rename = this.formItem.name
this.form.inputChildrens.push(this)
}
} }
}, },
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
this.focused = this.focus this.focused = this.focus
this.focusShow = this.focus
}) })
}, },
methods: { methods: {
...@@ -232,28 +294,35 @@ ...@@ -232,28 +294,35 @@
* 初始化变量值 * 初始化变量值
*/ */
init() { init() {
if (this.value || this.value === 0) {
this.val = this.value
} else if (this.modelValue || this.modelValue === 0) {
this.val = this.modelValue
} else {
this.val = null
}
}, },
/**
* 点击图标时触发
* @param {Object} type
*/
onClickIcon(type) { onClickIcon(type) {
this.$emit('iconClick', type) this.$emit('iconClick', type)
}, },
/** /**
* 获取父元素实例 * 显示隐藏内容,密码框时生效
*/ */
getForm(name = 'uniForms') {
let parent = this.$parent;
let parentName = parent.$options.name;
while (parentName !== name) {
parent = parent.$parent;
if (!parent) return false;
parentName = parent.$options.name;
}
return parent;
},
onEyes() { onEyes() {
this.showPassword = !this.showPassword this.showPassword = !this.showPassword
this.$emit('eyes', this.showPassword)
}, },
/**
* 输入时触发
* @param {Object} event
*/
onInput(event) { onInput(event) {
let value = event.detail.value; let value = event.detail.value;
// 判断是否去除空格 // 判断是否去除空格
...@@ -270,30 +339,85 @@ ...@@ -270,30 +339,85 @@
// TODO 兼容 vue2 // TODO 兼容 vue2
this.$emit('input', value); this.$emit('input', value);
// TODO 兼容 vue3 // TODO 兼容 vue3
this.$emit('update:modelValue',value) this.$emit('update:modelValue', value)
},
/**
* 外部调用方法
* 获取焦点时触发
* @param {Object} event
*/
onFocus() {
this.$nextTick(() => {
this.focused = true
})
this.$emit('focus', null);
}, },
onFocus(event) { _Focus(event) {
this.focusShow = true
this.$emit('focus', event); this.$emit('focus', event);
}, },
onBlur(event) {
/**
* 外部调用方法
* 失去焦点时触发
* @param {Object} event
*/
onBlur() {
this.focused = false
this.$emit('focus', null);
},
_Blur(event) {
let value = event.detail.value; let value = event.detail.value;
this.focusShow = false
this.$emit('blur', event); this.$emit('blur', event);
// 根据类型返回值,在event中获取的值理论上讲都是string
if (this.isEnter === false) {
this.$emit('change', this.val)
}
// 失去焦点时参与表单校验
if (this.form && this.formItem) {
const {
validateTrigger
} = this.form
if (validateTrigger === 'blur') {
this.formItem.onFieldChange()
}
}
}, },
/**
* 按下键盘的发送键
* @param {Object} e
*/
onConfirm(e) { onConfirm(e) {
this.$emit('confirm', e.detail.value); this.$emit('confirm', this.val);
this.isEnter = true;
this.$emit('change', this.val)
this.$nextTick(() => {
this.isEnter = false
})
}, },
/**
* 清理内容
* @param {Object} event
*/
onClear(event) { onClear(event) {
this.val = ''; this.val = '';
// TODO 兼容 vue2 // TODO 兼容 vue2
this.$emit('input', ''); this.$emit('input', '');
// TODO 兼容 vue2 // TODO 兼容 vue2
// TODO 兼容 vue3 // TODO 兼容 vue3
this.$emit('update:modelValue','') this.$emit('update:modelValue', '')
}, // 点击叉号触发
fieldClick() { this.$emit('clear')
this.$emit('click');
}, },
/**
* 去除空格
*/
trimStr(str, pos = 'both') { trimStr(str, pos = 'both') {
if (pos === 'both') { if (pos === 'both') {
return str.trim(); return str.trim();
...@@ -316,9 +440,10 @@ ...@@ -316,9 +440,10 @@
}; };
</script> </script>
<style lang="scss" > <style lang="scss">
$uni-error: #e43d33; $uni-error: #e43d33;
$uni-border-1: #DCDFE6 !default; $uni-border-1: #DCDFE6 !default;
.uni-easyinput { .uni-easyinput {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
width: 100%; width: 100%;
...@@ -336,10 +461,14 @@ ...@@ -336,10 +461,14 @@
width: 100%; width: 100%;
display: flex; display: flex;
box-sizing: border-box; box-sizing: border-box;
min-height: 36px; // min-height: 36px;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
// 处理border动画刚开始显示黑色的问题
border-color: #fff;
transition-property: border-color;
transition-duration: 0.3s;
} }
.uni-easyinput__content-input { .uni-easyinput__content-input {
...@@ -351,12 +480,16 @@ ...@@ -351,12 +480,16 @@
flex: 1; flex: 1;
line-height: 1; line-height: 1;
font-size: 14px; font-size: 14px;
height: 35px;
// min-height: 36px;
} }
.uni-easyinput__placeholder-class { .uni-easyinput__placeholder-class {
color: #999; color: #999;
font-size: 12px; font-size: 12px;
font-weight: 200; // font-weight: 200;
} }
.is-textarea { .is-textarea {
align-items: flex-start; align-items: flex-start;
} }
...@@ -371,9 +504,10 @@ ...@@ -371,9 +504,10 @@
flex: 1; flex: 1;
line-height: 1.5; line-height: 1.5;
font-size: 14px; font-size: 14px;
padding-top: 6px; margin: 6px;
padding-bottom: 10px; margin-left: 0;
height: 80px; height: 80px;
min-height: 80px;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
min-height: 80px; min-height: 80px;
width: auto; width: auto;
...@@ -403,6 +537,9 @@ ...@@ -403,6 +537,9 @@
align-items: center; align-items: center;
border: 1px solid $uni-border-1; border: 1px solid $uni-border-1;
border-radius: 4px; border-radius: 4px;
/* #ifdef MP-ALIPAY */
overflow: hidden;
/* #endif */
} }
.uni-error-message { .uni-error-message {
...@@ -423,8 +560,10 @@ ...@@ -423,8 +560,10 @@
.is-input-error-border { .is-input-error-border {
border-color: $uni-error; border-color: $uni-error;
.uni-easyinput__placeholder-class { .uni-easyinput__placeholder-class {
color: mix(#fff, $uni-error, 50%);; color: mix(#fff, $uni-error, 50%);
;
} }
} }
...@@ -450,9 +589,9 @@ ...@@ -450,9 +589,9 @@
} }
.is-disabled { .is-disabled {
border-color: red;
background-color: #F7F6F6; background-color: #F7F6F6;
color: #D5D5D5; color: #D5D5D5;
.uni-easyinput__placeholder-class { .uni-easyinput__placeholder-class {
color: #D5D5D5; color: #D5D5D5;
font-size: 12px; font-size: 12px;
......
{ {
"id": "uni-easyinput", "id": "uni-easyinput",
"displayName": "uni-easyinput 增强输入框", "displayName": "uni-easyinput 增强输入框",
"version": "1.0.3", "version": "1.1.1",
"description": "Easyinput 组件是对原生input组件的增强", "description": "Easyinput 组件是对原生input组件的增强",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
...@@ -17,11 +17,7 @@ ...@@ -17,11 +17,7 @@
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
}, },
"dcloudext": { "dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": { "sale": {
"regular": { "regular": {
"price": "0.00" "price": "0.00"
...@@ -38,7 +34,8 @@ ...@@ -38,7 +34,8 @@
"data": "无", "data": "无",
"permissions": "无" "permissions": "无"
}, },
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
}, },
"uni_modules": { "uni_modules": {
"dependencies": [ "dependencies": [
......
## 1.4.8(2022-08-23)
- 优化 根据 rules 自动添加 required 的问题
## 1.4.7(2022-08-22)
- 修复 item 未设置 require 属性,rules 设置 require 后,星号也显示的 bug,详见:[https://ask.dcloud.net.cn/question/151540](https://ask.dcloud.net.cn/question/151540)
## 1.4.6(2022-07-13)
- 修复 model 需要校验的值没有声明对应字段时,导致第一次不触发校验的bug
## 1.4.5(2022-07-05)
- 新增 更多表单示例
- 优化 子表单组件过期提示的问题
- 优化 子表单组件uni-datetime-picker、uni-data-select、uni-data-picker的显示样式
## 1.4.4(2022-07-04)
- 更新 删除组件日志
## 1.4.3(2022-07-04)
- 修复 由 1.4.0 引发的 label 插槽不生效的bug
## 1.4.2(2022-07-04)
- 修复 子组件找不到 setValue 报错的bug
## 1.4.1(2022-07-04)
- 修复 uni-data-picker 在 uni-forms-item 中报错的bug
- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug
## 1.4.0(2022-06-30)
- 【重要】组件逻辑重构,部分用法用旧版本不兼容,请注意兼容问题
- 【重要】组件使用 Provide/Inject 方式注入依赖,提供了自定义表单组件调用 uni-forms 校验表单的能力
- 新增 model 属性,等同于原 value/modelValue 属性,旧属性即将废弃
- 新增 validateTrigger 属性的 blur 值,仅 uni-easyinput 生效
- 新增 onFieldChange 方法,可以对子表单进行校验,可替代binddata方法
- 新增 子表单的 setRules 方法,配合自定义校验函数使用
- 新增 uni-forms-item 的 setRules 方法,配置动态表单使用可动态更新校验规则
- 优化 动态表单校验方式,废弃拼接name的方式
## 1.3.3(2022-06-22)
- 修复 表单校验顺序无序问题
## 1.3.2(2021-12-09) ## 1.3.2(2021-12-09)
- -
## 1.3.1(2021-11-19) ## 1.3.1(2021-11-19)
......
<template> <template>
<view class="uni-forms" :class="{ 'uni-forms--top': !border }"> <view class="uni-forms">
<form @submit.stop="submitForm" @reset="resetForm"> <form>
<slot></slot> <slot></slot>
</form> </form>
</view> </view>
</template> </template>
<script> <script>
import Validator from './validate.js';
import {
deepCopy,
getValue,
isRequiredField,
setDataValue,
getDataValue,
realName,
isRealName,
rawData,
isEqual
} from './utils.js'
// #ifndef VUE3 // #ifndef VUE3
// 后续会慢慢废弃这个方法
import Vue from 'vue'; import Vue from 'vue';
Vue.prototype.binddata = function(name, value, formName) { Vue.prototype.binddata = function(name, value, formName) {
if (formName) { if (formName) {
...@@ -26,18 +40,15 @@ ...@@ -26,18 +40,15 @@
} }
}; };
// #endif // #endif
import Validator from './validate.js';
/** /**
* Forms 表单 * Forms 表单
* @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据 * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据
* @tutorial https://ext.dcloud.net.cn/plugin?id=2773 * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
* @property {Object} rules 表单校验规则 * @property {Object} rules 表单校验规则
* @property {String} validateTrigger = [bind|submit] 校验触发器方式 默认 submit * @property {String} validateTrigger = [bind|submit|blur] 校验触发器方式 默认 submit
* @value bind 发生变化时触发 * @value bind 发生变化时触发
* @value submit 提交时触发 * @value submit 提交时触发
* @value blur 失去焦点时触发
* @property {String} labelPosition = [top|left] label 位置 默认 left * @property {String} labelPosition = [top|left] label 位置 默认 left
* @value top 顶部显示 label * @value top 顶部显示 label
* @value left 左侧显示 label * @value left 左侧显示 label
...@@ -51,25 +62,34 @@ ...@@ -51,25 +62,34 @@
* @value toast 错误信息toast显示 * @value toast 错误信息toast显示
* @value modal 错误信息modal显示 * @value modal 错误信息modal显示
* @event {Function} submit 提交时触发 * @event {Function} submit 提交时触发
* @event {Function} validate 校验结果发生变化触发
*/ */
export default { export default {
name: 'uniForms', name: 'uniForms',
components: {}, emits: ['validate', 'submit'],
emits:['input','reset','validate','submit'], options: {
virtualHost: true
},
props: { props: {
// 即将弃用 // 即将弃用
value: { value: {
type: Object, type: Object,
default () { default () {
return {}; return null;
} }
}, },
// 替换 value 属性 // vue3 替换 value 属性
modelValue: { modelValue: {
type: Object, type: Object,
default () { default () {
return {}; return null;
}
},
// 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValue
model: {
type: Object,
default () {
return null;
} }
}, },
// 表单校验规则 // 表单校验规则
...@@ -79,58 +99,68 @@ ...@@ -79,58 +99,68 @@
return {}; return {};
} }
}, },
// 校验触发器方式,默认 关闭 //校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal]
errShowType: {
type: String,
default: 'undertext'
},
// 校验触发器方式 默认 bind 取值 [bind|submit]
validateTrigger: { validateTrigger: {
type: String, type: String,
default: '' default: 'submit'
}, },
// label 位置,可选值 top/left // label 位置,默认 left 取值 top/left
labelPosition: { labelPosition: {
type: String, type: String,
default: 'left' default: 'left'
}, },
// label 宽度,单位 px // label 宽度
labelWidth: { labelWidth: {
type: [String, Number], type: [String, Number],
default: '' default: ''
}, },
// label 居中方式,可选值 left/center/right // label 居中方式,默认 left 取值 left/center/right
labelAlign: { labelAlign: {
type: String, type: String,
default: 'left' default: 'left'
}, },
errShowType: {
type: String,
default: 'undertext'
},
border: { border: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
provide() {
return {
uniForm: this
}
},
data() { data() {
return { return {
formData: {} // 表单本地值的记录,不应该与传如的值进行关联
formData: {},
formRules: {}
}; };
}, },
computed: { computed: {
dataValue() { // 计算数据源变化的
if (JSON.stringify(this.modelValue) === '{}') { localData() {
return this.value const localVal = this.model || this.modelValue || this.value
} else { if (localVal) {
return this.modelValue return deepCopy(localVal)
} }
return {}
} }
}, },
watch: { watch: {
rules(newVal) { // 监听数据变化 ,暂时不使用,需要单独赋值
// 如果规则发生变化,要初始化组件 // localData: {},
this.init(newVal); // 监听规则变化
rules: {
handler: function(val, oldVal) {
this.setRules(val)
}, },
labelPosition() { deep: true,
this.childrens.forEach(vm => { immediate: true
vm.init()
})
} }
}, },
created() { created() {
...@@ -156,137 +186,132 @@ ...@@ -156,137 +186,132 @@
} }
// #endif // #endif
// 存放watch 监听数组 // 子组件实例数组
this.unwatchs = []; this.childrens = []
// 存放子组件数组 // TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错
this.childrens = []; this.inputChildrens = []
// 存放 easyInput 组件 this.setRules(this.rules)
this.inputChildrens = [];
// 存放 dataCheckbox 组件
this.checkboxChildrens = [];
// 存放规则
this.formRules = [];
this.init(this.rules);
}, },
// mounted() {
// this.init(this.rules)
// },
methods: { methods: {
init(formRules) {
// 判断是否有规则
if (Object.keys(formRules).length === 0) {
this.formData = this.dataValue
return
};
this.formRules = formRules;
this.validator = new Validator(formRules);
this.registerWatch();
},
// 监听 watch
registerWatch() {
// 取消监听,避免多次调用 init 重复执行 $watch
this.unwatchs.forEach(v => v());
this.childrens.forEach((v) => {
v.init()
})
// watch 每个属性 ,需要知道具体那个属性发变化
Object.keys(this.dataValue).forEach(key => {
let watch = this.$watch(
'dataValue.' + key,
value => {
if (!value) return
// 如果是对象 ,则平铺内容
if (value.toString() === '[object Object]') {
for (let i in value) {
let name = `${key}[${i}]`;
this.formData[name] = this._getValue(name, value[i]);
}
} else {
this.formData[key] = this._getValue(key, value);
}
},
{
deep: true,
immediate: true
}
);
this.unwatchs.push(watch);
});
},
/** /**
* 公开给用户使用 * 外部调用方法
* 设置验规则 * 设置规则 ,主要用于小程序自定义检验规则
* @param {Object} formRules * @param {Array} rules 规则源数据
*/ */
setRules(formRules) { setRules(rules) {
this.init(formRules); // TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖
this.formRules = Object.assign({}, this.formRules, rules)
// 初始化校验函数
this.validator = new Validator(rules);
}, },
/** /**
* 公开给用户使用 * 外部调用方法
* 设置自定义表单组件 value 值 * 设置数据,用于设置表单数据,公开给用户使用 , 不支持在动态表单中使用
* @param {String} name 字段名称 * @param {Object} key
* @param {String} value 字段值 * @param {Object} value
*/ */
setValue(name, value, callback) { setValue(key, value) {
let example = this.childrens.find(child => child.name === name); let example = this.childrens.find(child => child.name === key);
if (!example) return null; if (!example) return null;
value = this._getValue(example.name, value); this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || [])
this.formData[name] = value; return example.onFieldChange(this.formData[key]);
example.val = value;
return example.triggerCheck(value, callback);
}, },
/** /**
* 表单重置 * 外部调用方法
* @param {Object} event * 手动提交校验表单
* 对整个表单进行校验的方法,参数为一个回调函数。
* @param {Array} keepitem 保留不参与校验的字段
* @param {type} callback 方法回调
*/ */
resetForm(event) { validate(keepitem, callback) {
return this.checkAll(this.formData, keepitem, callback);
},
/**
* 外部调用方法
* 部分表单校验
* @param {Array|String} props 需要校验的字段
* @param {Function} 回调函数
*/
validateField(props = [], callback) {
props = [].concat(props);
let invalidFields = {};
this.childrens.forEach(item => { this.childrens.forEach(item => {
item.errMsg = ''; const name = realName(item.name)
const inputComp = this.inputChildrens.find(child => child.rename === item.name); if (props.indexOf(name) !== -1) {
if (inputComp) { invalidFields = Object.assign({}, invalidFields, {
inputComp.errMsg = ''; [name]: this.formData[name]
// fix by mehaotian 不触发其他组件的 setValue });
inputComp.is_reset = true
inputComp.$emit('input', inputComp.multiple ? [] : '');
inputComp.$emit('update:modelValue', inputComp.multiple ? [] : '');
} }
}); });
return this.checkAll(invalidFields, [], callback);
},
/**
* 外部调用方法
* 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
* @param {Array|String} props 需要移除校验的字段 ,不填为所有
*/
clearValidate(props = []) {
props = [].concat(props);
this.childrens.forEach(item => { this.childrens.forEach(item => {
if (item.name) { if (props.length === 0) {
this.formData[item.name] = this._getValue(item.name, ''); item.errMsg = '';
} else {
const name = realName(item.name)
if (props.indexOf(name) !== -1) {
item.errMsg = '';
}
} }
}); });
this.$emit('reset', event);
}, },
/** /**
* 触发表单校验,通过 @validate 获取 * 外部调用方法 ,即将废弃
* @param {Object} validate * 手动提交校验表单
* 对整个表单进行校验的方法,参数为一个回调函数。
* @param {Array} keepitem 保留不参与校验的字段
* @param {type} callback 方法回调
*/ */
validateCheck(validate) { submit(keepitem, callback, type) {
if (validate === null) validate = null; for (let i in this.dataValue) {
this.$emit('validate', validate); const itemData = this.childrens.find(v => v.name === i);
if (itemData) {
if (this.formData[i] === undefined) {
this.formData[i] = this._getValue(i, this.dataValue[i]);
}
}
}
if (!type) {
console.warn('submit 方法即将废弃,请使用validate方法代替!');
}
return this.checkAll(this.formData, keepitem, callback, 'submit');
}, },
/**
* 校验所有或者部分表单 // 校验所有
*/ async checkAll(invalidFields, keepitem, callback, type) {
async validateAll(invalidFields, type, keepitem, callback) { // 不存在校验规则 ,则停止校验流程
if (!this.validator) return
let childrens = [] let childrens = []
// 处理参与校验的item实例
for (let i in invalidFields) { for (let i in invalidFields) {
const item = this.childrens.find(v => v.name === i) const item = this.childrens.find(v => realName(v.name) === i)
if (item) { if (item) {
childrens.push(item) childrens.push(item)
} }
} }
// 如果validate第一个参数是funciont ,那就走回调
if (!callback && typeof keepitem === 'function') { if (!callback && typeof keepitem === 'function') {
callback = keepitem; callback = keepitem;
} }
let promise; let promise;
// 如果不存在回调,那么使用 Promise 方式返回
if (!callback && typeof callback !== 'function' && Promise) { if (!callback && typeof callback !== 'function' && Promise) {
promise = new Promise((resolve, reject) => { promise = new Promise((resolve, reject) => {
callback = function(valid, invalidFields) { callback = function(valid, invalidFields) {
...@@ -296,47 +321,39 @@ ...@@ -296,47 +321,39 @@
} }
let results = []; let results = [];
let newFormData = {}; // 避免引用错乱 ,建议拷贝对象处理
if (this.validator) { let tempFormData = JSON.parse(JSON.stringify(invalidFields))
for (let key in childrens) { // 所有子组件参与校验,使用 for 可以使用 awiat
const child = childrens[key]; for (let i in childrens) {
let name = child.isArray ? child.arrayField : child.name; const child = childrens[i]
if (child.isArray) { let name = realName(child.name);
if (child.name.indexOf('[') !== -1 && child.name.indexOf(']') !== -1) { const result = await child.onFieldChange(tempFormData[name]);
const fieldData = child.name.split('[');
const fieldName = fieldData[0];
const fieldValue = fieldData[1].replace(']', '');
if (!newFormData[fieldName]) {
newFormData[fieldName] = {};
}
newFormData[fieldName][fieldValue] = this._getValue(name, invalidFields[name]);
}
} else {
newFormData[name] = this._getValue(name, invalidFields[name]);
}
const result = await child.triggerCheck(invalidFields[name], true);
if (result) { if (result) {
results.push(result); results.push(result);
// toast ,modal 只需要执行第一次就可以
if (this.errShowType === 'toast' || this.errShowType === 'modal') break; if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
} }
} }
} else {
newFormData = invalidFields
}
if (Array.isArray(results)) { if (Array.isArray(results)) {
if (results.length === 0) results = null; if (results.length === 0) results = null;
} }
if (Array.isArray(keepitem)) { if (Array.isArray(keepitem)) {
keepitem.forEach(v => { keepitem.forEach(v => {
newFormData[v] = this.dataValue[v]; let vName = realName(v);
let value = getDataValue(v, this.localData)
if (value !== undefined) {
tempFormData[vName] = value
}
}); });
} }
// TODO submit 即将废弃
if (type === 'submit') { if (type === 'submit') {
this.$emit('submit', { this.$emit('submit', {
detail: { detail: {
value: newFormData, value: tempFormData,
errors: results errors: results
} }
}); });
...@@ -344,129 +361,37 @@ ...@@ -344,129 +361,37 @@
this.$emit('validate', results); this.$emit('validate', results);
} }
callback && typeof callback === 'function' && callback(results, newFormData); // const resetFormData = rawData(tempFormData, this.localData, this.name)
let resetFormData = {}
resetFormData = rawData(tempFormData, this.name)
callback && typeof callback === 'function' && callback(results, resetFormData);
if (promise && callback) { if (promise && callback) {
return promise; return promise;
} else { } else {
return null; return null;
} }
},
submitForm() {},
/**
* 外部调用方法
* 手动提交校验表单
* 对整个表单进行校验的方法,参数为一个回调函数。
*/
submit(keepitem, callback, type) {
for (let i in this.dataValue) {
const itemData = this.childrens.find(v => v.name === i);
if (itemData) {
if (this.formData[i] === undefined) {
this.formData[i] = this._getValue(i, this.dataValue[i]);
}
}
}
if (!type) {
console.warn('submit 方法即将废弃,请使用validate方法代替!');
}
return this.validateAll(this.formData, 'submit', keepitem, callback);
},
/**
* 外部调用方法
* 校验表单
* 对整个表单进行校验的方法,参数为一个回调函数。
*/
validate(keepitem, callback) {
return this.submit(keepitem, callback, true);
}, },
/** /**
* 部分表单校验 * 返回validate事件
* @param {Object} props * @param {Object} result
* @param {Object} cb
*/ */
validateField(props, callback) { validateCheck(result) {
props = [].concat(props); this.$emit('validate', result);
let invalidFields = {};
this.childrens.forEach(item => {
if (props.indexOf(item.name) !== -1) {
invalidFields = Object.assign({}, invalidFields, {
[item.name]: this.formData[item.name]
});
}
});
return this.validateAll(invalidFields, 'submit', [], callback);
}, },
_getValue: getValue,
/** _isRequiredField: isRequiredField,
* 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果 _setDataValue: setDataValue,
*/ _getDataValue: getDataValue,
resetFields() { _realName: realName,
this.resetForm(); _isRealName: isRealName,
}, _isEqual: isEqual
/**
* 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
*/
clearValidate(props) {
props = [].concat(props);
this.childrens.forEach(item => {
const inputComp = this.inputChildrens.find(child => child.rename === item.name);
if (props.length === 0) {
item.errMsg = '';
if (inputComp) {
inputComp.errMsg = '';
}
} else {
if (props.indexOf(item.name) !== -1) {
item.errMsg = '';
if (inputComp) {
inputComp.errMsg = '';
}
}
}
});
},
/**
* 把 value 转换成指定的类型
* @param {Object} key
* @param {Object} value
*/
_getValue(key, value) {
const rules = (this.formRules[key] && this.formRules[key].rules) || [];
const isRuleNum = rules.find(val => val.format && this.type_filter(val.format));
const isRuleBool = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
// 输入值为 number
if (isRuleNum) {
value = isNaN(value) ? value : value === '' || value === null ? null : Number(value);
}
// 简单判断真假值
if (isRuleBool) {
value = !value ? false : true;
}
return value;
},
/**
* 过滤数字类型
* @param {Object} format
*/
type_filter(format) {
return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
}
} }
}; };
</script> </script>
<style lang="scss" > <style lang="scss">
.uni-forms { .uni-forms {}
// overflow: hidden;
// padding: 10px 15px;
}
.uni-forms--top {
// padding: 10px 15px;
// padding-top: 22px;
}
</style> </style>
/**
* 简单处理对象拷贝
* @param {Obejct} 被拷贝对象
* @@return {Object} 拷贝对象
*/
export const deepCopy = (val) => {
return JSON.parse(JSON.stringify(val))
}
/**
* 过滤数字类型
* @param {String} format 数字类型
* @@return {Boolean} 返回是否为数字类型
*/
export const typeFilter = (format) => {
return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
}
/**
* 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined
* @param {String} key 字段名
* @param {any} value 字段值
* @param {Object} rules 表单校验规则
*/
export const getValue = (key, value, rules) => {
const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
// 输入类型为 number
if (!!isRuleNumType) {
if (!value && value !== 0) {
value = null
} else {
value = isNumber(Number(value)) ? Number(value) : value
}
}
// 输入类型为 boolean
if (!!isRuleBoolType) {
value = isBoolean(value) ? value : false
}
return value;
}
/**
* 获取表单数据
* @param {String|Array} name 真实名称,需要使用 realName 获取
* @param {Object} data 原始数据
* @param {any} value 需要设置的值
*/
export const setDataValue = (field, formdata, value) => {
formdata[field] = value
return value || ''
}
/**
* 获取表单数据
* @param {String|Array} field 真实名称,需要使用 realName 获取
* @param {Object} data 原始数据
*/
export const getDataValue = (field, data) => {
return objGet(data, field)
}
/**
* 获取表单类型
* @param {String|Array} field 真实名称,需要使用 realName 获取
*/
export const getDataValueType = (field, data) => {
const value = getDataValue(field, data)
return {
type: type(value),
value
}
}
/**
* 获取表单可用的真实name
* @param {String|Array} name 表单name
* @@return {String} 表单可用的真实name
*/
export const realName = (name, data = {}) => {
const base_name = _basePath(name)
if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
return realname
}
return base_name[0] || name
}
/**
* 判断是否表单可用的真实name
* @param {String|Array} name 表单name
* @@return {String} 表单可用的真实name
*/
export const isRealName = (name) => {
const reg = /^_formdata_#*/
return reg.test(name)
}
/**
* 获取表单数据的原始格式
* @@return {Object|Array} object 需要解析的数据
*/
export const rawData = (object = {}, name) => {
let newData = JSON.parse(JSON.stringify(object))
let formData = {}
for(let i in newData){
let path = name2arr(i)
objSet(formData,path,newData[i])
}
return formData
}
/**
* 真实name还原为 array
* @param {*} name
*/
export const name2arr = (name) => {
let field = name.replace('_formdata_#', '')
field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
return field
}
/**
* 对象中设置值
* @param {Object|Array} object 源数据
* @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
* @param {String} value 需要设置的值
*/
export const objSet = (object, path, value) => {
if (typeof object !== 'object') return object;
_basePath(path).reduce((o, k, i, _) => {
if (i === _.length - 1) {
// 若遍历结束直接赋值
o[k] = value
return null
} else if (k in o) {
// 若存在对应路径,则返回找到的对象,进行下一次遍历
return o[k]
} else {
// 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
return o[k]
}
}, object)
// 返回object
return object;
}
// 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用
function _basePath(path) {
// 若是数组,则直接返回
if (Array.isArray(path)) return path
// 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'
return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
}
/**
* 从对象中获取值
* @param {Object|Array} object 源数据
* @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
* @param {String} defaultVal 如果无法从调用链中获取值的默认值
*/
export const objGet = (object, path, defaultVal = 'undefined') => {
// 先将path处理成统一格式
let newPath = _basePath(path)
// 递归处理,返回最后结果
let val = newPath.reduce((o, k) => {
return (o || {})[k]
}, object);
return !val || val !== undefined ? val : defaultVal
}
/**
* 是否为 number 类型
* @param {any} num 需要判断的值
* @return {Boolean} 是否为 number
*/
export const isNumber = (num) => {
return !isNaN(Number(num))
}
/**
* 是否为 boolean 类型
* @param {any} bool 需要判断的值
* @return {Boolean} 是否为 boolean
*/
export const isBoolean = (bool) => {
return (typeof bool === 'boolean')
}
/**
* 是否有必填字段
* @param {Object} rules 规则
* @return {Boolean} 是否有必填字段
*/
export const isRequiredField = (rules) => {
let isNoField = false;
for (let i = 0; i < rules.length; i++) {
const ruleData = rules[i];
if (ruleData.required) {
isNoField = true;
break;
}
}
return isNoField;
}
/**
* 获取数据类型
* @param {Any} obj 需要获取数据类型的值
*/
export const type = (obj) => {
var class2type = {};
// 生成class2type映射
"Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
class2type["[object " + item + "]"] = item.toLowerCase();
})
if (obj == null) {
return obj + "";
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[Object.prototype.toString.call(obj)] || "object" :
typeof obj;
}
/**
* 判断两个值是否相等
* @param {any} a 值
* @param {any} b 值
* @return {Boolean} 是否相等
*/
export const isEqual = (a, b) => {
//如果a和b本来就全等
if (a === b) {
//判断是否为0和-0
return a !== 0 || 1 / a === 1 / b;
}
//判断是否为null和undefined
if (a == null || b == null) {
return a === b;
}
//接下来判断a和b的数据类型
var classNameA = toString.call(a),
classNameB = toString.call(b);
//如果数据类型不相等,则返回false
if (classNameA !== classNameB) {
return false;
}
//如果数据类型相等,再根据不同数据类型分别判断
switch (classNameA) {
case '[object RegExp]':
case '[object String]':
//进行字符串转换比较
return '' + a === '' + b;
case '[object Number]':
//进行数字转换比较,判断是否为NaN
if (+a !== +a) {
return +b !== +b;
}
//判断是否为0或-0
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]':
case '[object Boolean]':
return +a === +b;
}
//如果是对象类型
if (classNameA == '[object Object]') {
//获取a和b的属性长度
var propsA = Object.getOwnPropertyNames(a),
propsB = Object.getOwnPropertyNames(b);
if (propsA.length != propsB.length) {
return false;
}
for (var i = 0; i < propsA.length; i++) {
var propName = propsA[i];
//如果对应属性对应值不相等,则返回false
if (a[propName] !== b[propName]) {
return false;
}
}
return true;
}
//如果是数组类型
if (classNameA == '[object Array]') {
if (a.toString() == b.toString()) {
return true;
}
return false;
}
}
{ {
"id": "uni-forms", "id": "uni-forms",
"displayName": "uni-forms 表单", "displayName": "uni-forms 表单",
"version": "1.3.2", "version": "1.4.8",
"description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据", "description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
...@@ -17,11 +17,7 @@ ...@@ -17,11 +17,7 @@
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
}, },
"dcloudext": { "dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": { "sale": {
"regular": { "regular": {
"price": "0.00" "price": "0.00"
...@@ -38,7 +34,8 @@ ...@@ -38,7 +34,8 @@
"data": "无", "data": "无",
"permissions": "无" "permissions": "无"
}, },
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
}, },
"uni_modules": { "uni_modules": {
"dependencies": [ "dependencies": [
...@@ -74,7 +71,8 @@ ...@@ -74,7 +71,8 @@
"阿里": "y", "阿里": "y",
"百度": "y", "百度": "y",
"字节跳动": "y", "字节跳动": "y",
"QQ": "y" "QQ": "y",
"京东": "u"
}, },
"快应用": { "快应用": {
"华为": "u", "华为": "u",
......
## 1.0.19(2022-09-20)
- 修复 小程序端,使用将自定义节点设置成[虚拟节点](https://uniapp.dcloud.net.cn/tutorial/vue-api.html#%E5%85%B6%E4%BB%96%E9%85%8D%E7%BD%AE)的uni-ui组件,样式错乱的问题
## 1.0.18(2022-09-20) ## 1.0.18(2022-09-20)
- 修复 微信小程序端 WXSS 编译报错的bug - 修复 微信小程序端 WXSS 编译报错的bug
## 1.0.17(2022.09-19) ## 1.0.17(2022.09-19)
......
...@@ -80,9 +80,15 @@ ...@@ -80,9 +80,15 @@
margin: 6px 0; margin: 6px 0;
} }
/* #ifdef MP */
// 解决小程序端开启虚拟节点virtualHost引起的 class = input-box丢失的问题 [详情参考](https://uniapp.dcloud.net.cn/matter.html#%E5%90%84%E5%AE%B6%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%AE%9E%E7%8E%B0%E6%9C%BA%E5%88%B6%E4%B8%8D%E5%90%8C-%E5%8F%AF%E8%83%BD%E5%AD%98%E5%9C%A8%E7%9A%84%E5%B9%B3%E5%8F%B0%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98)
.uni-content ::v-deep .uni-easyinput__content,
/* #endif */
.input-box { .input-box {
padding: 4px; padding: 4px;
background-color: #F8F8F8; background-color: #F8F8F8 !important;
border-radius: 0; border-radius: 0;
font-size: 14px; font-size: 14px;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
......
{ {
"name": "uni-id-pages", "name": "uni-id-pages",
"version": "1.0.7", "version": "1.0.19",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"version": "1.0.7", "version": "1.0.19",
"dependencies": { "dependencies": {
"jweixin-module": "^1.6.0" "jweixin-module": "^1.6.0"
}, },
......
{ {
"id": "uni-id-pages", "id": "uni-id-pages",
"displayName": "uni-id-pages", "displayName": "uni-id-pages",
"version": "1.0.18", "version": "1.0.19",
"description": "云端一体简单、统一、可扩展的用户中心页面模版", "description": "云端一体简单、统一、可扩展的用户中心页面模版",
"keywords": [ "keywords": [
"用户管理", "用户管理",
......
...@@ -170,6 +170,10 @@ ...@@ -170,6 +170,10 @@
position: relative; position: relative;
} }
/* #ifdef MP */
// 解决小程序端开启虚拟节点virtualHost引起的 class = input-box丢失的问题 [详情参考](https://uniapp.dcloud.net.cn/matter.html#%E5%90%84%E5%AE%B6%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%AE%9E%E7%8E%B0%E6%9C%BA%E5%88%B6%E4%B8%8D%E5%90%8C-%E5%8F%AF%E8%83%BD%E5%AD%98%E5%9C%A8%E7%9A%84%E5%B9%B3%E5%8F%B0%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98)
.phone-box ::v-deep .uni-easyinput__content,
/* #endif */
.input-box { .input-box {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
box-sizing: border-box; box-sizing: border-box;
......
{ {
"name": "uni-id-co", "name": "uni-id-co",
"version": "1.0.18", "version": "1.0.19",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "uni-id-co", "name": "uni-id-co",
"version": "1.0.12", "version": "1.0.19",
"dependencies": { "dependencies": {
"jsonwebtoken": "8.5.1", "jsonwebtoken": "8.5.1",
"lodash.merge": "^4.6.2", "lodash.merge": "^4.6.2",
......
{ {
"name": "uni-id-co", "name": "uni-id-co",
"version": "1.0.18", "version": "1.0.19",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"keywords": [], "keywords": [],
......
## 1.2.1(2022-03-30)
- 删除无用文件
## 1.2.0(2021-11-23) ## 1.2.0(2021-11-23)
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list) - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list)
......
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" >
.uni-list-ad { .uni-list-ad {
position: relative; position: relative;
border: 1px red solid; border: 1px red solid;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<view class="uni-list-chat__container"> <view class="uni-list-chat__container">
<view class="uni-list-chat__header-warp"> <view class="uni-list-chat__header-warp">
<view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }"> <view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
<image class="uni-list-chat__header-image" :src="avatar" mode="aspectFill"></image> <image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatar" mode="aspectFill"></image>
</view> </view>
<!-- 头像组 --> <!-- 头像组 -->
<view v-else class="uni-list-chat__header"> <view v-else class="uni-list-chat__header">
...@@ -217,7 +217,7 @@ ...@@ -217,7 +217,7 @@
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" >
$uni-font-size-lg:16px; $uni-font-size-lg:16px;
$uni-spacing-row-sm: 5px; $uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px; $uni-spacing-row-base: 10px;
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra" <view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra"
:class="{ 'flex--justify': direction === 'column' }"> :class="{ 'flex--justify': direction === 'column' }">
<text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text> <text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text>
<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" /> <uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" :custom-style="badgeStyle" />
<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked" <switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked"
@change="onSwitchChange" /> @change="onSwitchChange" />
</view> </view>
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
* @value sm 小图 * @value sm 小图
* @property {String} badgeText 数字角标内容 * @property {String} badgeText 数字角标内容
* @property {String} badgeType 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21) * @property {String} badgeType 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
* @property {Object} badgeStyle 数字角标样式
* @property {String} rightText 右侧文字内容 * @property {String} rightText 右侧文字内容
* @property {Boolean} disabled = [true|false] 是否禁用 * @property {Boolean} disabled = [true|false] 是否禁用
* @property {Boolean} clickable = [true|false] 是否开启点击反馈 * @property {Boolean} clickable = [true|false] 是否开启点击反馈
...@@ -138,6 +139,12 @@ ...@@ -138,6 +139,12 @@
type: String, type: String,
default: 'success' default: 'success'
}, },
badgeStyle:{
type: Object,
default () {
return {}
}
},
rightText: { rightText: {
type: String, type: String,
default: '' default: ''
...@@ -158,7 +165,7 @@ ...@@ -158,7 +165,7 @@
type: Object, type: Object,
default () { default () {
return { return {
type: 'contact', type: '',
color: '#000000', color: '#000000',
size: 20 size: 20
}; };
...@@ -268,7 +275,6 @@ ...@@ -268,7 +275,6 @@
$uni-bg-color-hover:#f1f1f1; $uni-bg-color-hover:#f1f1f1;
$uni-text-color-grey:#999; $uni-text-color-grey:#999;
$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg; $list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
.uni-list-item { .uni-list-item {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
...@@ -283,15 +289,12 @@ ...@@ -283,15 +289,12 @@
cursor: pointer; cursor: pointer;
/* #endif */ /* #endif */
} }
.uni-list-item--disabled { .uni-list-item--disabled {
opacity: 0.3; opacity: 0.3;
} }
.uni-list-item--hover { .uni-list-item--hover {
background-color: $uni-bg-color-hover; background-color: $uni-bg-color-hover;
} }
.uni-list-item__container { .uni-list-item__container {
position: relative; position: relative;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
...@@ -304,15 +307,12 @@ ...@@ -304,15 +307,12 @@
overflow: hidden; overflow: hidden;
// align-items: center; // align-items: center;
} }
.container--right { .container--right {
padding-right: 0; padding-right: 0;
} }
// .border--left { // .border--left {
// margin-left: $uni-spacing-row-lg; // margin-left: $uni-spacing-row-lg;
// } // }
.uni-list--border { .uni-list--border {
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -324,7 +324,6 @@ ...@@ -324,7 +324,6 @@
border-top-width: 0.5px; border-top-width: 0.5px;
/* #endif */ /* #endif */
} }
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
.uni-list--border:after { .uni-list--border:after {
position: absolute; position: absolute;
...@@ -337,9 +336,7 @@ ...@@ -337,9 +336,7 @@
transform: scaleY(0.5); transform: scaleY(0.5);
background-color: $uni-border-color; background-color: $uni-border-color;
} }
/* #endif */ /* #endif */
.uni-list-item__content { .uni-list-item__content {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
...@@ -352,24 +349,20 @@ ...@@ -352,24 +349,20 @@
justify-content: space-between; justify-content: space-between;
overflow: hidden; overflow: hidden;
} }
.uni-list-item__content--center { .uni-list-item__content--center {
justify-content: center; justify-content: center;
} }
.uni-list-item__content-title { .uni-list-item__content-title {
font-size: $uni-font-size-base; font-size: $uni-font-size-base;
color: #3b4144; color: #3b4144;
overflow: hidden; overflow: hidden;
} }
.uni-list-item__content-note { .uni-list-item__content-note {
margin-top: 6rpx; margin-top: 6rpx;
color: $uni-text-color-grey; color: $uni-text-color-grey;
font-size: $uni-font-size-sm; font-size: $uni-font-size-sm;
overflow: hidden; overflow: hidden;
} }
.uni-list-item__extra { .uni-list-item__extra {
// width: 25%; // width: 25%;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
...@@ -379,7 +372,6 @@ ...@@ -379,7 +372,6 @@
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
} }
.uni-list-item__header { .uni-list-item__header {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
...@@ -387,14 +379,12 @@ ...@@ -387,14 +379,12 @@
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
} }
.uni-list-item__icon { .uni-list-item__icon {
margin-right: 18rpx; margin-right: 18rpx;
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.uni-list-item__icon-img { .uni-list-item__icon-img {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: block; display: block;
...@@ -403,7 +393,6 @@ ...@@ -403,7 +393,6 @@
width: $uni-img-size-base; width: $uni-img-size-base;
margin-right: 10px; margin-right: 10px;
} }
.uni-icon-wrapper { .uni-icon-wrapper {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
...@@ -411,40 +400,33 @@ ...@@ -411,40 +400,33 @@
align-items: center; align-items: center;
padding: 0 10px; padding: 0 10px;
} }
.flex--direction { .flex--direction {
flex-direction: column; flex-direction: column;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
align-items: initial; align-items: initial;
/* #endif */ /* #endif */
} }
.flex--justify { .flex--justify {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
justify-content: initial; justify-content: initial;
/* #endif */ /* #endif */
} }
.uni-list--lg { .uni-list--lg {
height: $uni-img-size-lg; height: $uni-img-size-lg;
width: $uni-img-size-lg; width: $uni-img-size-lg;
} }
.uni-list--base { .uni-list--base {
height: $uni-img-size-base; height: $uni-img-size-base;
width: $uni-img-size-base; width: $uni-img-size-base;
} }
.uni-list--sm { .uni-list--sm {
height: $uni-img-size-sm; height: $uni-img-size-sm;
width: $uni-img-size-sm; width: $uni-img-size-sm;
} }
.uni-list-item__extra-text { .uni-list-item__extra-text {
color: $uni-text-color-grey; color: $uni-text-color-grey;
font-size: $uni-font-size-sm; font-size: $uni-font-size-sm;
} }
.uni-ellipsis-1 { .uni-ellipsis-1 {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
overflow: hidden; overflow: hidden;
...@@ -456,7 +438,6 @@ ...@@ -456,7 +438,6 @@
text-overflow:ellipsis; text-overflow:ellipsis;
/* #endif */ /* #endif */
} }
.uni-ellipsis-2 { .uni-ellipsis-2 {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
overflow: hidden; overflow: hidden;
...@@ -465,7 +446,6 @@ ...@@ -465,7 +446,6 @@
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
/* #endif */ /* #endif */
/* #ifdef APP-NVUE */ /* #ifdef APP-NVUE */
lines: 2; lines: 2;
text-overflow:ellipsis; text-overflow:ellipsis;
......
...@@ -54,7 +54,7 @@ export default { ...@@ -54,7 +54,7 @@ export default {
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" >
$uni-bg-color:#ffffff; $uni-bg-color:#ffffff;
$uni-border-color:#e5e5e5; $uni-border-color:#e5e5e5;
.uni-list { .uni-list {
......
{ {
"id": "uni-list", "id": "uni-list",
"displayName": "uni-list 列表", "displayName": "uni-list 列表",
"version": "1.2.0", "version": "1.2.1",
"description": "List 组件 ,帮助使用者快速构建列表。", "description": "List 组件 ,帮助使用者快速构建列表。",
"keywords": [ "keywords": [
"", "",
......
## List 列表 ## List 列表
> **组件名:uni-list** > **组件名:uni-list**
> 代码块: `uList`、`uListItem` > 代码块: `uList`、`uListItem`
...@@ -125,7 +123,7 @@ uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-l ...@@ -125,7 +123,7 @@ uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-l
<!-- 显示圆形头像 --> <!-- 显示圆形头像 -->
<uni-list-chat :avatar-circle="true" title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" ></uni-list-chat> <uni-list-chat :avatar-circle="true" title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" ></uni-list-chat>
<!-- 右侧带角标 --> <!-- 右侧带角标 -->
<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-text="12"></uni-list-chat> <uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-text="12" :badge-style="{backgroundColor:'#FF80AB'}"></uni-list-chat>
<!-- 头像显示圆点 --> <!-- 头像显示圆点 -->
<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat> <uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
<!-- 头像显示角标 --> <!-- 头像显示角标 -->
...@@ -205,6 +203,7 @@ thumbSize |String |medium | 略缩图尺寸,可选值,lg:大图; medium: ...@@ -205,6 +203,7 @@ thumbSize |String |medium | 略缩图尺寸,可选值,lg:大图; medium:
showBadge |Boolean |false | 是否显示数字角标 showBadge |Boolean |false | 是否显示数字角标
badgeText |String |- | 数字角标内容 badgeText |String |- | 数字角标内容
badgeType |String |- | 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21) badgeType |String |- | 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
badgeStyle |Object |- | 数字角标样式,使用uni-badge的custom-style参数
rightText |String |- | 右侧文字内容 rightText |String |- | 右侧文字内容
disabled |Boolean |false | 是否禁用 disabled |Boolean |false | 是否禁用
showArrow |Boolean |true | 是否显示箭头图标 showArrow |Boolean |true | 是否显示箭头图标
......
## 1.0.3(2022-09-06)
- 修复 过期时间问题,容错 AccessToken 默认 fallback 逻辑,当微信服务器没有返回过期时间时设置为2小时后过期
## 1.0.2(2022-09-02) ## 1.0.2(2022-09-02)
- 新增 依赖数据表schema opendb-open-data - 新增 依赖数据表schema opendb-open-data
## 1.0.0(2022-08-22) ## 1.0.0(2022-08-22)
......
{ {
"id": "uni-open-bridge-common", "id": "uni-open-bridge-common",
"displayName": "uni-open-bridge-common", "displayName": "uni-open-bridge-common",
"version": "1.0.2", "version": "1.0.3",
"description": "统一接管微信等三方平台认证凭据", "description": "统一接管微信等三方平台认证凭据",
"keywords": [ "keywords": [
"uni-open-bridge-common", "uni-open-bridge-common",
......
...@@ -43,7 +43,7 @@ class AccessToken extends Storage { ...@@ -43,7 +43,7 @@ class AccessToken extends Storage {
const responseData = await WeixinServer[methodName](oauthConfig) const responseData = await WeixinServer[methodName](oauthConfig)
const duration = responseData.expires_in const duration = responseData.expires_in || (60 * 60 * 2)
delete responseData.expires_in delete responseData.expires_in
return { return {
......
...@@ -61,7 +61,7 @@ class DatabaseCache { ...@@ -61,7 +61,7 @@ class DatabaseCache {
value = this._serializeValue(value) value = this._serializeValue(value)
await this.collection.doc(key).set({ await this.collection.doc(key).set({
value, value,
expired: duration && duration !== -1 ? Date.now() + duration : -1 expired: duration && duration !== -1 ? Date.now() + (duration * 1000) : -1
}) })
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册