提交 724470d5 编写于 作者: DCloud_JSON's avatar DCloud_JSON

Merge branch 'dev' into 'master'

Dev

See merge request !6
...@@ -128,7 +128,7 @@ ...@@ -128,7 +128,7 @@
"uniStatistics" : { "uniStatistics" : {
"enable" : false "enable" : false
}, },
"vueVersion" : "2", "vueVersion" : "3",
"h5" : { "h5" : {
"unipush" : { "unipush" : {
"enable" : false "enable" : false
......
## 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)
## 1.1.7(2021-11-08) ## 1.1.7(2021-11-08)
- 优化 升级ui - 优化 升级ui
- 修改 size 属性默认值调整为 small - 修改 size 属性默认值调整为 small
- 修改 type 属性,默认值调整为 error,info 替换 default - 修改 type 属性,默认值调整为 error,info 替换 default
## 1.1.6(2021-09-22) ## 1.1.6(2021-09-22)
- 修复 在字节小程序上样式不生效的 bug - 修复 在字节小程序上样式不生效的 bug
## 1.1.5(2021-07-30) ## 1.1.5(2021-07-30)
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.4(2021-07-29) ## 1.1.4(2021-07-29)
- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性 - 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
## 1.1.3(2021-06-24) ## 1.1.3(2021-06-24)
- 优化 示例项目 - 优化 示例项目
## 1.1.1(2021-05-12) ## 1.1.1(2021-05-12)
- 新增 组件示例地址 - 新增 组件示例地址
## 1.1.0(2021-05-12) ## 1.1.0(2021-05-12)
- 新增 uni-badge 的 absolute 属性,支持定位 - 新增 uni-badge 的 absolute 属性,支持定位
- 新增 uni-badge 的 offset 属性,支持定位偏移 - 新增 uni-badge 的 offset 属性,支持定位偏移
- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点 - 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+ - 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式 - 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
## 1.0.7(2021-05-07) ## 1.0.7(2021-05-07)
- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug - 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug - 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
- 新增 uni-badge 属性 custom-style, 支持自定义样式 - 新增 uni-badge 属性 custom-style, 支持自定义样式
## 1.0.6(2021-02-04) ## 1.0.6(2021-02-04)
- 调整为uni_modules目录规范 - 调整为uni_modules目录规范
<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>
...@@ -21,11 +21,11 @@ ...@@ -21,11 +21,11 @@
* @value error 红色 * @value error 红色
* @property {String} inverted = [true|false] 是否无需背景颜色 * @property {String} inverted = [true|false] 是否无需背景颜色
* @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+ * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
* @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
* @value rightTop 右上 * @value rightTop 右上
* @value rightBottom 右下 * @value rightBottom 右下
* @value leftTop 左上 * @value leftTop 左上
* @value leftBottom 左下 * @value leftBottom 左下
* @property {Array[number]} offset 距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px * @property {Array[number]} offset 距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
* @property {String} isDot = [true|false] 是否显示为一个小点 * @property {String} isDot = [true|false] 是否显示为一个小点
* @event {Function} click 点击 Badge 触发事件 * @event {Function} click 点击 Badge 触发事件
...@@ -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;
...@@ -265,4 +265,4 @@ ...@@ -265,4 +265,4 @@
} }
} }
</style> </style>
{ {
"id": "uni-badge", "id": "uni-badge",
"displayName": "uni-badge 数字角标", "displayName": "uni-badge 数字角标",
"version": "1.2.0", "version": "1.2.1",
"description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。", "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
"keywords": [ "keywords": [
"", "",
"badge", "badge",
"uni-ui", "uni-ui",
"uniui", "uniui",
"数字角标", "数字角标",
"徽章" "徽章"
], ],
"repository": "https://github.com/dcloudio/uni-ui", "repository": "https://github.com/dcloudio/uni-ui",
"engines": { "engines": {
"HBuilderX": "" "HBuilderX": ""
}, },
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
}, },
"dcloudext": { "dcloudext": {
"category": [ "sale": {
"前端组件", "regular": {
"通用组件" "price": "0.00"
], },
"sale": { "sourcecode": {
"regular": { "price": "0.00"
"price": "0.00" }
}, },
"sourcecode": { "contact": {
"price": "0.00" "qq": ""
} },
}, "declaration": {
"contact": { "ads": "无",
"qq": "" "data": "无",
}, "permissions": "无"
"declaration": { },
"ads": "无", "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"data": "无", "type": "component-vue"
"permissions": "无" },
}, "uni_modules": {
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" "dependencies": ["uni-scss"],
}, "encrypt": [],
"uni_modules": { "platforms": {
"dependencies": [], "cloud": {
"encrypt": [], "tcb": "y",
"platforms": { "aliyun": "y"
"cloud": { },
"tcb": "y", "client": {
"aliyun": "y" "App": {
}, "app-vue": "y",
"client": { "app-nvue": "y"
"App": { },
"app-vue": "y", "H5-mobile": {
"app-nvue": "y" "Safari": "y",
}, "Android Browser": "y",
"H5-mobile": { "微信浏览器(Android)": "y",
"Safari": "y", "QQ浏览器(Android)": "y"
"Android Browser": "y", },
"微信浏览器(Android)": "y", "H5-pc": {
"QQ浏览器(Android)": "y" "Chrome": "y",
}, "IE": "y",
"H5-pc": { "Edge": "y",
"Chrome": "y", "Firefox": "y",
"IE": "y", "Safari": "y"
"Edge": "y", },
"Firefox": "y", "小程序": {
"Safari": "y" "微信": "y",
}, "阿里": "y",
"小程序": { "百度": "y",
"微信": "y", "字节跳动": "y",
"阿里": "y", "QQ": "y"
"百度": "y", },
"字节跳动": "y", "快应用": {
"QQ": "y" "华为": "y",
}, "联盟": "y"
"快应用": { },
"华为": "y", "Vue": {
"联盟": "y" "vue2": "y",
}, "vue3": "y"
"Vue": { }
"vue2": "y", }
"vue3": "y" }
} }
}
}
}
} }
\ No newline at end of file
## 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
}, },
/** /**
...@@ -383,12 +383,14 @@ ...@@ -383,12 +383,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.mode !== 'list') { if (this.selectedColor) {
styles['border-color'] = item.selected?selectedColor:'#DCDFE6' if (this.mode !== 'list') {
} styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
if (this.mode === 'tag') { }
styles['background-color'] = item.selected? selectedColor:'#f5f5f5' if (this.mode === 'tag') {
styles['background-color'] = item.selected? selectedColor:'#f5f5f5'
}
} }
let classles = '' let classles = ''
for (let i in styles) { for (let i in styles) {
...@@ -398,16 +400,17 @@ ...@@ -398,16 +400,17 @@
}, },
setStyleIcon(item) { setStyleIcon(item) {
let styles = {} let styles = {}
let classles = '' let classles = ''
let selectedColor = this.selectedColor?this.selectedColor:'#2979ff' if (this.selectedColor) {
styles['background-color'] = item.selected?selectedColor:'#fff' let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
styles['border-color'] = item.selected?selectedColor:'#DCDFE6' styles['background-color'] = item.selected?selectedColor:'#fff'
styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
if(!item.selected && item.disabled){
styles['background-color'] = '#F2F6FC' if(!item.selected && item.disabled){
styles['border-color'] = item.selected?selectedColor:'#DCDFE6' styles['background-color'] = '#F2F6FC'
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]};`
} }
...@@ -415,17 +418,18 @@ ...@@ -415,17 +418,18 @@
}, },
setStyleIconText(item) { setStyleIconText(item) {
let styles = {} let styles = {}
let classles = '' let classles = ''
let selectedColor = this.selectedColor?this.selectedColor:'#2979ff' if (this.selectedColor) {
if (this.mode === 'tag') { let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:'#fff'):'#666' if (this.mode === 'tag') {
} else { styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:'#fff'):'#666'
styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:selectedColor):'#666' } else {
} styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:selectedColor):'#666'
if(!item.selected && item.disabled){ }
styles.color = '#999' if(!item.selected && item.disabled){
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
}
export default { function obj2strStyle(obj) {
let style = ''
for (let key in obj) {
const val = obj[key]
style += `${key}:${val};`
}
return style
}
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)
}, },
onFocus(event) { /**
* 外部调用方法
* 获取焦点时触发
* @param {Object} event
*/
onFocus() {
this.$nextTick(() => {
this.focused = true
})
this.$emit('focus', null);
},
_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,12 +589,12 @@ ...@@ -450,12 +589,12 @@
} }
.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;
} }
} }
</style> </style>
{ {
"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: {
labelPosition() { handler: function(val, oldVal) {
this.childrens.forEach(vm => { this.setRules(val)
vm.init() },
}) deep: true,
immediate: true
} }
}, },
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 {Array} keepitem 保留不参与校验的字段
* @param {type} callback 方法回调
*/
validate(keepitem, callback) {
return this.checkAll(this.formData, keepitem, callback);
}, },
/** /**
* 表单重置 * 外部调用方法
* @param {Object} event * 部分表单校验
* @param {Array|String} props 需要校验的字段
* @param {Function} 回调函数
*/ */
resetForm(event) { 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('['); if (result) {
const fieldName = fieldData[0]; results.push(result);
const fieldValue = fieldData[1].replace(']', ''); // toast ,modal 只需要执行第一次就可以
if (!newFormData[fieldName]) { if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
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) {
results.push(result);
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) {
props = [].concat(props);
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);
},
/**
* 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
*/ */
resetFields() { validateCheck(result) {
this.resetForm(); this.$emit('validate', result);
}, },
_getValue: getValue,
/** _isRequiredField: isRequiredField,
* 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果 _setDataValue: setDataValue,
*/ _getDataValue: getDataValue,
clearValidate(props) { _realName: realName,
props = [].concat(props); _isRealName: isRealName,
this.childrens.forEach(item => { _isEqual: isEqual
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; </style>
// padding: 10px 15px;
}
.uni-forms--top {
// padding: 10px 15px;
// padding-top: 22px;
}
</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.22(2022-09-23)
- 修复 某些情况下,修改密码报“两次输入密码不一致”的bug
## 1.0.21(2022-09-21)
- 修复 store.hasLogin的值在某些情况下会出错的bug
## 1.0.20(2022-09-21)
- 新增 store 账号信息状态管理,详情:用户中心页面 路径:`/uni_modules/uni-id-pages/pages/userinfo/userinfo`
## 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)
......
import pagesJson from '@/pages.json'
const uniIdCo = uniCloud.importObject("uni-id-co")
export default {
async logout() {
await uniIdCo.logout()
uni.removeStorageSync('uni_id_token');
uni.setStorageSync('uni_id_token_expired', 0)
uni.redirectTo({
url: `/${pagesJson.uniIdRouter?.loginPage ?? 'uni_modules/uni-id-pages/pages/login/login-withoutpwd'}`,
});
uni.$emit('uni-id-pages-logout')
},
}
import loginSuccess from './loginSuccess.js'; import {
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
import config from '@/uni_modules/uni-id-pages/config.js' import config from '@/uni_modules/uni-id-pages/config.js'
let mixin = { let mixin = {
data() { data() {
...@@ -75,7 +78,7 @@ let mixin = { ...@@ -75,7 +78,7 @@ let mixin = {
}, },
methods: { methods: {
loginSuccess(e) { loginSuccess(e) {
loginSuccess({ mutations.loginSuccess({
...e, ...e,
uniIdRedirectUrl: this.uniIdRedirectUrl uniIdRedirectUrl: this.uniIdRedirectUrl
}) })
......
...@@ -51,7 +51,12 @@ ...@@ -51,7 +51,12 @@
.register-back{ .register-back{
display: none; display: none;
} }
uni-button{
padding-bottom: 1px;
}
/* #endif */ /* #endif */
} }
...@@ -79,17 +84,23 @@ ...@@ -79,17 +84,23 @@
font-size: 11px; font-size: 11px;
margin: 6px 0; margin: 6px 0;
} }
/* #ifndef APP-NVUE */
// 解决小程序端开启虚拟节点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; height: 44px;
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 */
display: flex; display: flex;
/* #endif */ /* #endif */
flex: 1; flex: 1;
} }
.link { .link {
color: #04498c; color: #04498c;
......
import pagesJson from '@/pages.json'
export default function(e = {}) {
const {
showToast = true, toastText = '登录成功', autoBack = true, uniIdRedirectUrl = ''
} = e
console.log({
toastText,
autoBack
});
if (showToast) {
uni.showToast({
title: toastText,
icon: 'none'
});
}
if (autoBack) {
let delta = 0; //判断需要返回几层
let pages = getCurrentPages();
uni.$emit('uni-id-pages-login-success',pages)
console.log(pages);
pages.forEach((page, index) => {
if (pages[pages.length - index - 1].route.split('/')[3] == 'login') {
delta++
}
})
console.log('判断需要返回几层:',pages, delta);
if (uniIdRedirectUrl) {
return uni.reLaunch({
url: uniIdRedirectUrl
})
}
// #ifdef H5
if(e.loginType == 'weixin'){
console.log('window.history',window.history);
return window.history.go(-3)
}
// #endif
if (delta) {
const page = pagesJson.pages[0]
return uni.reLaunch({
url: `/${page.path}`
})
}
uni.navigateBack({
delta
})
}
}
...@@ -66,7 +66,7 @@ function getPwdRules(pwdName = 'password', rePwdName = 'password2') { ...@@ -66,7 +66,7 @@ function getPwdRules(pwdName = 'password', rePwdName = 'password2') {
}, },
{ {
validateFunction: function(rule, value, data, callback) { validateFunction: function(rule, value, data, callback) {
if (value != data.password) { if (value != data[pwdName]) {
callback(ERROR.normal.rePwdErr) callback(ERROR.normal.rePwdErr)
} }
return true return true
......
import pagesJson from '@/pages.json'
const uniIdCo = uniCloud.importObject("uni-id-co")
const db = uniCloud.database();
const usersTable = db.collection('uni-id-users')
let hostUserInfo = uni.getStorageSync('uni-id-pages-userInfo')||{}
console.log( hostUserInfo);
const data = {
userInfo: hostUserInfo,
hasLogin: Object.keys(hostUserInfo).length != 0
}
console.log('data', data);
// 定义 mutations, 修改属性
export const mutations = {
// data不为空,表示传递要更新的值(注意不是覆盖是合并),什么也不传时,直接查库获取更新
async updateUserInfo(data = false) {
if (data) {
usersTable.where('_id==$env.uid').update(data).then(e => {
console.log(e);
if (e.result.updated) {
uni.showToast({
title: "更新成功",
icon: 'none'
});
this.setUserInfo(data)
} else {
uni.showToast({
title: "没有改变",
icon: 'none'
});
}
})
} else {
try {
let res = await usersTable.where("'_id' == $cloudEnv_uid")
.field('mobile,nickname,username,email,avatar_file')
.get()
console.log('fromDbData',res.result.data);
this.setUserInfo(res.result.data[0])
} catch (e) {
this.setUserInfo({},{cover:true})
console.error(e.message, e.errCode);
}
}
},
async setUserInfo(data, {cover}={cover:false}) {
console.log('set-userInfo', data);
let userInfo = cover?data:Object.assign(store.userInfo,data)
store.userInfo = Object.assign({},userInfo)
store.hasLogin = Object.keys(store.userInfo).length != 0
console.log('store.userInfo', store.userInfo);
uni.setStorage({
key: "uni-id-pages-userInfo",
data:store.userInfo
})
return data
},
async logout() {
await uniIdCo.logout()
uni.removeStorageSync('uni_id_token');
uni.setStorageSync('uni_id_token_expired', 0)
uni.redirectTo({
url: `/${pagesJson.uniIdRouter?.loginPage ?? 'uni_modules/uni-id-pages/pages/login/login-withoutpwd'}`,
});
uni.$emit('uni-id-pages-logout')
this.setUserInfo({},{cover:true})
},
loginSuccess(e){
const {
showToast = true, toastText = '登录成功', autoBack = true, uniIdRedirectUrl = ''
} = e
console.log({
toastText,
autoBack
});
if (showToast) {
uni.showToast({
title: toastText,
icon: 'none'
});
}
this.updateUserInfo()
uni.$emit('uni-id-pages-login-success')
if (autoBack) {
let delta = 0; //判断需要返回几层
let pages = getCurrentPages();
// console.log(pages);
pages.forEach((page, index) => {
if (pages[pages.length - index - 1].route.split('/')[3] == 'login') {
delta++
}
})
console.log('判断需要返回几层:', pages, delta);
if (uniIdRedirectUrl) {
return uni.reLaunch({
url: uniIdRedirectUrl
})
}
// #ifdef H5
if (e.loginType == 'weixin') {
console.log('window.history', window.history);
return window.history.go(-3)
}
// #endif
if (delta) {
const page = pagesJson.pages[0]
return uni.reLaunch({
url: `/${page.path}`
})
}
uni.navigateBack({
delta
})
}
}
}
// #ifdef VUE2
import Vue from 'vue'
// 通过Vue.observable创建一个可响应的对象
export const store = Vue.observable(data)
// #endif
// #ifdef VUE3
import {
reactive
} from 'vue'
// 通过Vue.observable创建一个可响应的对象
export const store = reactive(data)
// #endif
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
}, },
methods: { methods: {
popupConfirm(){ popupConfirm(){
console.log("popupConfirm"); // console.log("popupConfirm");
this.isAgree = true this.isAgree = true
retryFun() retryFun()
// this.$emit('popupConfirm') // this.$emit('popupConfirm')
......
<template> <template>
<view @click="uploadAvatarImg"> <view @click="uploadAvatarImg" class="box" :class="{'showBorder':border}" :style="{width,height,lineHeight:height}">
<cloud-image v-if="avatar_file" :src="avatar_file.url" :width="width" :height="height"></cloud-image> <cloud-image v-if="avatar_file" :src="avatar_file.url" :width="width" :height="height"></cloud-image>
<uni-icons v-else :style="{width,height,lineHeight:height}" class="chooseAvatar" type="plusempty" size="30" <uni-icons v-else :style="{width,height,lineHeight:height}" class="chooseAvatar" type="plusempty" size="30"
color="#dddddd"></uni-icons> color="#dddddd"></uni-icons>
...@@ -7,20 +7,20 @@ ...@@ -7,20 +7,20 @@
</template> </template>
<script> <script>
const db = uniCloud.database(); import {
const usersTable = db.collection('uni-id-users') store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
/** /**
* uni-id-pages-avatar * uni-id-pages-avatar
* @description 用户头像组件 * @description 用户头像组件
* @property {String} width 图片的宽,默认为:50px * @property {String} width 图片的宽,默认为:50px
* @property {String} height 图片的高,默认为:50px * @property {String} height 图片的高,默认为:50px
*/ */
export default { export default {
data() { data() {
return { return {
userInfo: {}, isPC: false
isPC: false,
hasLogin:false
} }
}, },
props: { props: {
...@@ -37,71 +37,38 @@ ...@@ -37,71 +37,38 @@
default () { default () {
return "50px" return "50px"
} }
},
border:{
type: Boolean,
default () {
return false
}
} }
}, },
async mounted() { async mounted() {
usersTable.where("'_id' == $cloudEnv_uid").field('avatar_file,mobile,nickname').get().then(res=>{
this.userInfo = res.result.data[0]||{}
console.log('this.userInfo', this.userInfo);
this.hasLogin = true
}).catch (e=>{
this.userInfo = {}
this.hasLogin = false
console.log(e.message, e.errCode);
})
// try {
// let res = await usersTable.where("'_id' == $cloudEnv_uid").field('avatar_file').get()
// this.userInfo = res.result.data[0]
// console.log('this.userInfo', this.userInfo);
// } catch (e) {
// console.log(e.message);
// }
// #ifdef H5 // #ifdef H5
this.isPC = !['ios', 'android'].includes(uni.getSystemInfoSync().platform); this.isPC = !['ios', 'android'].includes(uni.getSystemInfoSync().platform);
console.log(' this.isPC', this.isPC, uni.getSystemInfoSync().platform); console.log(' this.isPC', this.isPC, uni.getSystemInfoSync().platform);
// #endif // #endif
}, },
computed: { computed: {
avatar_file() { hasLogin() {
if (this.userInfo.avatar_file && this.userInfo.avatar_file.url) { return store.hasLogin
return this.userInfo.avatar_file },
} userInfo() {
return store.userInfo
},
avatar_file() {
return store.userInfo.avatar_file
} }
}, },
methods: { methods: {
setAvatarFile(avatar_file) { setAvatarFile(avatar_file) {
uni.showLoading({ // 使用 clientDB 提交数据
title: "设置中", mutations.updateUserInfo({avatar_file})
mask: true
});
// 使用 clientDB 提交数据
usersTable.where('_id==$env.uid').update({
avatar_file
}).then((res) => {
console.log(res);
if (avatar_file) {
uni.showToast({
icon: 'none',
title: "更新成功"
})
} else {
uni.showToast({
icon: 'none',
title: "删除成功"
})
}
this.$set(this.userInfo, 'avatar_file', avatar_file)
}).catch((err) => {
uni.showModal({
content: err.message || "请求失败",
showCancel: false
})
}).finally(() => {
uni.hideLoading()
})
}, },
uploadAvatarImg(res) { uploadAvatarImg(res) {
console.log(this.hasLogin);
if(!this.hasLogin){ if(!this.hasLogin){
return uni.navigateTo({ return uni.navigateTo({
url:'/uni_modules/uni-id-pages/pages/login/login-withoutpwd' url:'/uni_modules/uni-id-pages/pages/login/login-withoutpwd'
...@@ -176,13 +143,24 @@ ...@@ -176,13 +143,24 @@
} }
</script> </script>
<style> <style>
/* #ifndef APP-NVUE */
.box{
overflow: hidden;
}
/* #endif */
.chooseAvatar { .chooseAvatar {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: inline-block; display: inline-block;
box-sizing: border-box;
/* #endif */ /* #endif */
border: dotted 1px #ddd; border: dotted 1px #ddd;
border-radius: 10px; border-radius: 10px;
text-align: center; text-align: center;
padding: 1px;
}
.showBorder{
border: solid 1px #ddd;
} }
</style> </style>
...@@ -14,8 +14,11 @@ ...@@ -14,8 +14,11 @@
</template> </template>
<script> <script>
import config from '@/uni_modules/uni-id-pages/config.js' import config from '@/uni_modules/uni-id-pages/config.js'
//前一个窗口的页面地址。控制点击切换快捷登录方式是创建还是返回 //前一个窗口的页面地址。控制点击切换快捷登录方式是创建还是返回
import loginSuccess from '../../common/loginSuccess.js'; import {
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
const db = uniCloud.database(); const db = uniCloud.database();
const usersTable = db.collection('uni-id-users') const usersTable = db.collection('uni-id-users')
...@@ -438,8 +441,8 @@ ...@@ -438,8 +441,8 @@
}); });
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
//如果是微信小程序端的微信登录,且为首次登录,就弹出获取微信昵称+头像用于绑定资料 //如果是微信小程序端的微信登录,且为首次登录,就弹出获取微信昵称+头像用于绑定资料
if (type == 'weixin' && result.type == "register") { if (type == 'weixin' && result.type == "register") {
loginSuccess({ mutations.loginSuccess({
...result, ...result,
showToast: false, showToast: false,
autoBack: false autoBack: false
...@@ -450,7 +453,7 @@ ...@@ -450,7 +453,7 @@
// #ifdef H5 // #ifdef H5
result.loginType = type result.loginType = type
// #endif // #endif
loginSuccess(result) mutations.loginSuccess(result)
}) })
.catch(e=>{ .catch(e=>{
console.log(e); console.log(e);
...@@ -469,7 +472,7 @@ ...@@ -469,7 +472,7 @@
}, },
doUserProfileNext() { doUserProfileNext() {
try { try {
loginSuccess() mutations.loginSuccess()
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
......
{ {
"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.22",
"description": "云端一体简单、统一、可扩展的用户中心页面模版", "description": "云端一体简单、统一、可扩展的用户中心页面模版",
"keywords": [ "keywords": [
"用户管理", "用户管理",
......
...@@ -56,8 +56,8 @@ ...@@ -56,8 +56,8 @@
}, },
async onLoad(e) { async onLoad(e) {
console.log(e); console.log(e);
let type = e.type //获取通过url传递的参数type设置当前登录方式,如果没传递直接默认以配置的登录
// console.log({type}); let type = e.type || config.loginTypes[0]
this.type = type this.type = type
if(type != 'univerify'){ if(type != 'univerify'){
this.focusPhone = true this.focusPhone = true
...@@ -65,8 +65,7 @@ ...@@ -65,8 +65,7 @@
this.$nextTick(() => { this.$nextTick(() => {
//关闭重复显示的登录快捷方式 //关闭重复显示的登录快捷方式
if (['weixin', 'apple'].includes(type)) { if (['weixin', 'apple'].includes(type)) {
this.$refs.uniFabLogin.servicesList = this.$refs.uniFabLogin.servicesList.filter(item => this.$refs.uniFabLogin.servicesList = this.$refs.uniFabLogin.servicesList.filter(item =>item.id != type)
item.id != type)
} }
}) })
uni.$on('uni-id-pages-set-login-type', type => { uni.$on('uni-id-pages-set-login-type', type => {
...@@ -169,7 +168,11 @@ ...@@ -169,7 +168,11 @@
left: 3px; left: 3px;
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;
......
<!-- 账号密码登录页 --> <!-- 账号密码登录页 -->
<template> <template>
<view class="uni-content"> <view class="uni-content">
<view class="login-logo"> <view class="login-logo">
<image :src="logo"></image> <image :src="logo"></image>
</view> </view>
<!-- 顶部文字 --> <!-- 顶部文字 -->
<text class="title title-box">账号密码登录</text> <text class="title title-box">账号密码登录</text>
<uni-forms> <uni-forms>
<uni-forms-item name="username"> <uni-forms-item name="username">
<uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box" :inputBorder="false" v-model="username" placeholder="请输入手机号/用户名/邮箱" /> <uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box"
</uni-forms-item> :inputBorder="false" v-model="username" placeholder="请输入手机号/用户名/邮箱" />
<uni-forms-item name="password"> </uni-forms-item>
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable type="password" :inputBorder="false" v-model="password" <uni-forms-item name="password">
placeholder="请输入密码" /> <uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable
</uni-forms-item> type="password" :inputBorder="false" v-model="password" placeholder="请输入密码" />
</uni-forms> </uni-forms-item>
<uni-captcha v-if="needCaptcha" focus ref="captcha" scene="login-by-pwd" v-model="captcha" /> </uni-forms>
<!-- 带选择框的隐私政策协议组件 --> <uni-captcha v-if="needCaptcha" focus ref="captcha" scene="login-by-pwd" v-model="captcha" />
<uni-id-pages-agreements scope="login" ref="agreements" ></uni-id-pages-agreements> <!-- 带选择框的隐私政策协议组件 -->
<button class="uni-btn" type="primary" @click="pwdLogin">登录</button> <uni-id-pages-agreements scope="login" ref="agreements"></uni-id-pages-agreements>
<!-- 忘记密码 --> <button class="uni-btn" type="primary" @click="pwdLogin">登录</button>
<view class="link-box"> <!-- 忘记密码 -->
<view v-if="!config.isAdmin"> <view class="link-box">
<text class="forget">忘记了?</text> <view v-if="!config.isAdmin">
<text class="link" @click="toRetrievePwd">找回密码</text> <text class="forget">忘记了?</text>
</view> <text class="link" @click="toRetrievePwd">找回密码</text>
<text class="link" @click="toRegister">{{config.isAdmin ? '注册管理员账号': '注册账号'}}</text> </view>
<!-- <text class="link" @click="toRegister" v-if="!config.isAdmin">注册账号</text> --> <text class="link" @click="toRegister">{{config.isAdmin ? '注册管理员账号': '注册账号'}}</text>
</view> <!-- <text class="link" @click="toRegister" v-if="!config.isAdmin">注册账号</text> -->
<!-- 悬浮登录方式组件 --> </view>
<uni-id-pages-fab-login ref="uniFabLogin"></uni-id-pages-fab-login> <!-- 悬浮登录方式组件 -->
</view> <uni-id-pages-fab-login ref="uniFabLogin"></uni-id-pages-fab-login>
</template> </view>
</template>
<script>
import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js'; <script>
const uniIdCo = uniCloud.importObject("uni-id-co",{ import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js';
errorOptions:{ const uniIdCo = uniCloud.importObject("uni-id-co", {
type:'toast' errorOptions: {
} type: 'toast'
}) }
export default { })
mixins: [mixin], export default {
data() { mixins: [mixin],
return { data() {
"password": "", return {
"username": "", "password": "",
"captcha": "", "username": "",
"needCaptcha": false, "captcha": "",
"focusUsername":false, "needCaptcha": false,
"focusPassword":false, "focusUsername": false,
"logo": "/static/logo.png" "focusPassword": false,
} "logo": "/static/logo.png"
}, }
onShow() { },
// #ifdef H5 onShow() {
document.onkeydown = event => { // #ifdef H5
var e = event || window.event; document.onkeydown = event => {
if (e && e.keyCode == 13) { //回车键的键值为13 var e = event || window.event;
this.pwdLogin() if (e && e.keyCode == 13) { //回车键的键值为13
} this.pwdLogin()
}; }
// #endif };
}, // #endif
methods: { },
// 页面跳转,找回密码 methods: {
toRetrievePwd() { // 页面跳转,找回密码
let url = '/uni_modules/uni-id-pages/pages/retrieve/retrieve' toRetrievePwd() {
//如果刚好用户名输入框的值为手机号码,就把它传到retrieve页面,根据该手机号找回密码 let url = '/uni_modules/uni-id-pages/pages/retrieve/retrieve'
if (/^1\d{10}$/.test(this.username)) { //如果刚好用户名输入框的值为手机号码,就把它传到retrieve页面,根据该手机号找回密码
url += `?phoneNumber=${this.username}` if (/^1\d{10}$/.test(this.username)) {
} url += `?phoneNumber=${this.username}`
uni.navigateTo({ }
url uni.navigateTo({
}) url
}, })
/** },
* 密码登录 /**
*/ * 密码登录
pwdLogin() { */
if(!this.password.length){ pwdLogin() {
this.focusPassword = true if (!this.password.length) {
return uni.showToast({ this.focusPassword = true
title: '请输入密码', return uni.showToast({
icon: 'none' title: '请输入密码',
}); icon: 'none'
} });
if(!this.username.length){ }
this.focusUsername = true if (!this.username.length) {
return uni.showToast({ this.focusUsername = true
title: '请输入手机号/用户名/邮箱', return uni.showToast({
icon: 'none' title: '请输入手机号/用户名/邮箱',
}); icon: 'none'
} });
if(this.needCaptcha && this.captcha.length!=4){ }
this.$refs.captcha.getImageCaptcha() if (this.needCaptcha && this.captcha.length != 4) {
return uni.showToast({ this.$refs.captcha.getImageCaptcha()
title: '请输入验证码', return uni.showToast({
icon: 'none' title: '请输入验证码',
}); icon: 'none'
} });
}
if (this.needAgreements && !this.agree) {
return this.$refs.agreements.popup(this.pwdLogin) if (this.needAgreements && !this.agree) {
} return this.$refs.agreements.popup(this.pwdLogin)
}
let data = {
"password": this.password, let data = {
"captcha": this.captcha "password": this.password,
} "captcha": this.captcha
}
if (/^1\d{10}$/.test(this.username)) {
data.mobile = this.username if (/^1\d{10}$/.test(this.username)) {
}else if(/@/.test(this.username)) { data.mobile = this.username
data.email = this.username } else if (/@/.test(this.username)) {
}else{ data.email = this.username
data.username = this.username } else {
} data.username = this.username
}
uniIdCo.login(data).then(e => {
this.loginSuccess(e) uniIdCo.login(data).then(e => {
}).catch(e => { this.loginSuccess(e)
if(e.errCode == 'uni-id-captcha-required'){ }).catch(e => {
this.needCaptcha = true if (e.errCode == 'uni-id-captcha-required') {
}else if(this.needCaptcha){ this.needCaptcha = true
//登录失败,自动重新获取验证码 } else if (this.needCaptcha) {
this.$refs.captcha.getImageCaptcha() //登录失败,自动重新获取验证码
} this.$refs.captcha.getImageCaptcha()
}) }
}, })
/* 前往注册 */ },
toRegister() { /* 前往注册 */
uni.navigateTo({ toRegister() {
url: this.config.isAdmin ? '/uni_modules/uni-id-pages/pages/register/register-admin': '/uni_modules/uni-id-pages/pages/register/register', uni.navigateTo({
fail(e) { url: this.config.isAdmin ? '/uni_modules/uni-id-pages/pages/register/register-admin' :
console.error(e); '/uni_modules/uni-id-pages/pages/register/register',
} fail(e) {
}) console.error(e);
} }
} })
} }
</script> }
}
<style lang="scss" scoped> </script>
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
@media screen and (min-width: 690px) { <style lang="scss" scoped>
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
}
.forget{ @media screen and (min-width: 690px) {
font-size: 12px; .uni-content {
color: #8a8f8b; max-height: 650px;
} }
}
.link-box {
/* #ifndef APP-NVUE */ .forget {
display: flex; font-size: 12px;
/* #endif */ color: #8a8f8b;
flex-direction: row; }
justify-content: space-between;
margin-top: 20px; .link-box {
} /* #ifndef APP-NVUE */
display: flex;
.link { /* #endif */
font-size: 12px; flex-direction: row;
} justify-content: space-between;
margin-top: 20px;
}
.link {
font-size: 12px;
}
</style> </style>
...@@ -191,7 +191,7 @@ ...@@ -191,7 +191,7 @@
@media screen and (min-width: 690px) { @media screen and (min-width: 690px) {
.uni-content{ .uni-content{
padding: 30px 40px; padding: 30px 40px;
max-height: 550px; max-height: 650px;
} }
.link-box { .link-box {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
......
<!-- 账号注册页 --> <!-- 账号注册页 -->
<template> <template>
<view class="uni-content"> <view class="uni-content">
<match-media :min-width="690"> <match-media :min-width="690">
<view class="login-logo"> <view class="login-logo">
<image :src="logo"></image> <image :src="logo"></image>
</view> </view>
<!-- 顶部文字 --> <!-- 顶部文字 -->
<text class="title title-box">用户名密码注册</text> <text class="title title-box">用户名密码注册</text>
</match-media> </match-media>
<uni-forms ref="form" :value="formData" :rules="rules" validate-trigger="submit" err-show-type="toast"> <uni-forms ref="form" :value="formData" :rules="rules" validate-trigger="submit" err-show-type="toast">
<uni-forms-item name="username" required> <uni-forms-item name="username" required>
<uni-easyinput :inputBorder="false" :focus="focusUsername" @blur="focusUsername = false" <uni-easyinput :inputBorder="false" :focus="focusUsername" @blur="focusUsername = false"
class="input-box" placeholder="请输入用户名" v-model="formData.username" trim="both" /> class="input-box" placeholder="请输入用户名" v-model="formData.username" trim="both" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="nickname"> <uni-forms-item name="nickname">
<uni-easyinput :inputBorder="false" :focus="focusNickname" @blur="focusNickname = false" class="input-box" placeholder="请输入用户昵称" v-model="formData.nickname" <uni-easyinput :inputBorder="false" :focus="focusNickname" @blur="focusNickname = false"
trim="both" /> class="input-box" placeholder="请输入用户昵称" v-model="formData.nickname" trim="both" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="password" v-model="formData.password" required> <uni-forms-item name="password" v-model="formData.password" required>
<uni-easyinput :inputBorder="false" :focus="focusPassword" @blur="focusPassword = false" <uni-easyinput :inputBorder="false" :focus="focusPassword" @blur="focusPassword = false"
class="input-box" maxlength="20" :placeholder="'请输入' + (config.passwordStrength == 'weak'?'6':'8') + '-16位密码'" type="password" class="input-box" maxlength="20"
v-model="formData.password" trim="both" /> :placeholder="'请输入' + (config.passwordStrength == 'weak'?'6':'8') + '-16位密码'" type="password"
</uni-forms-item> v-model="formData.password" trim="both" />
<uni-forms-item name="password2" v-model="formData.password2" required> </uni-forms-item>
<uni-easyinput :inputBorder="false" :focus="focusPassword2" @blur="focusPassword2 =false" <uni-forms-item name="password2" v-model="formData.password2" required>
class="input-box" placeholder="再次输入密码" maxlength="20" type="password" v-model="formData.password2" <uni-easyinput :inputBorder="false" :focus="focusPassword2" @blur="focusPassword2 =false"
trim="both" /> class="input-box" placeholder="再次输入密码" maxlength="20" type="password" v-model="formData.password2"
</uni-forms-item> trim="both" />
<uni-forms-item> </uni-forms-item>
<uni-captcha ref="captcha" scene="register" v-model="formData.captcha" /> <uni-forms-item>
</uni-forms-item> <uni-captcha ref="captcha" scene="register" v-model="formData.captcha" />
<uni-id-pages-agreements scope="register" ref="agreements" ></uni-id-pages-agreements> </uni-forms-item>
<button class="uni-btn" type="primary" @click="submit">注册</button> <uni-id-pages-agreements scope="register" ref="agreements"></uni-id-pages-agreements>
<button @click="navigateBack" class="register-back">返回</button> <button class="uni-btn" type="primary" @click="submit">注册</button>
<match-media :min-width="690"> <button @click="navigateBack" class="register-back">返回</button>
<view class="link-box"> <match-media :min-width="690">
<text class="link" @click="registerByEmail">邮箱验证码注册</text> <view class="link-box">
<text class="link" @click="toLogin">已有账号?点此登录</text> <text class="link" @click="registerByEmail">邮箱验证码注册</text>
</view> <text class="link" @click="toLogin">已有账号?点此登录</text>
</match-media> </view>
</uni-forms> </match-media>
</view> </uni-forms>
</template> </view>
</template>
<script>
import rules from './validator.js'; <script>
import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js'; import rules from './validator.js';
import config from '@/uni_modules/uni-id-pages/config.js' import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js';
const uniIdCo = uniCloud.importObject("uni-id-co") import config from '@/uni_modules/uni-id-pages/config.js'
export default { import {
mixins: [mixin], store,
data() { mutations
return { } from '@/uni_modules/uni-id-pages/common/store.js'
formData: {
username: "", const {
nickname: "", loginSuccess
password: "", } = mutations
password2: "", const uniIdCo = uniCloud.importObject("uni-id-co")
captcha: "" export default {
}, mixins: [mixin],
rules, data() {
focusUsername:false, return {
focusNickname:false, formData: {
focusPassword:false, username: "",
focusPassword2:false, nickname: "",
logo: "/static/logo.png" password: "",
} password2: "",
}, captcha: ""
onReady() { },
this.$refs.form.setRules(this.rules) rules,
}, focusUsername: false,
onShow() { focusNickname: false,
// #ifdef H5 focusPassword: false,
document.onkeydown = event => { focusPassword2: false,
var e = event || window.event; logo: "/static/logo.png"
if (e && e.keyCode == 13) { //回车键的键值为13 }
this.submit() },
} onReady() {
}; this.$refs.form.setRules(this.rules)
// #endif },
}, onShow() {
methods: { // #ifdef H5
/** document.onkeydown = event => {
* 触发表单提交 var e = event || window.event;
*/ if (e && e.keyCode == 13) { //回车键的键值为13
submit() { this.submit()
this.$refs.form.validate().then((res) => { }
if(this.formData.captcha.length != 4){ };
this.$refs.captcha.focusCaptchaInput = true // #endif
return uni.showToast({ },
title: '请输入验证码', methods: {
icon: 'none' /**
}); * 触发表单提交
} */
if (this.needAgreements && !this.agree) { submit() {
return this.$refs.agreements.popup(()=>{ this.$refs.form.validate().then((res) => {
this.submitForm(res) if (this.formData.captcha.length != 4) {
}) this.$refs.captcha.focusCaptchaInput = true
} return uni.showToast({
this.submitForm(res) title: '请输入验证码',
}).catch((errors) => { icon: 'none'
let key = errors[0].key });
key = key.replace(key[0], key[0].toUpperCase()) }
console.log(key); if (this.needAgreements && !this.agree) {
this['focus'+key] = true return this.$refs.agreements.popup(() => {
}) this.submitForm(res)
}, })
submitForm(params) { }
uniIdCo.registerUser(this.formData).then(e => { this.submitForm(res)
console.log(e); }).catch((errors) => {
uni.navigateBack() let key = errors[0].key
}) key = key.replace(key[0], key[0].toUpperCase())
.catch(e => { console.log(key);
console.log(e); this['focus' + key] = true
console.log(e.message); })
//更好的体验:登录错误,直接刷新验证码 },
this.$refs.captcha.getImageCaptcha() submitForm(params) {
}) uniIdCo.registerUser(this.formData).then(e => {
}, console.log(e);
navigateBack() { loginSuccess()
uni.navigateBack() })
}, .catch(e => {
toLogin() { console.log(e);
uni.navigateTo({ console.log(e.message);
url: '/uni_modules/uni-id-pages/pages/login/login-withpwd' //更好的体验:登录错误,直接刷新验证码
}) this.$refs.captcha.getImageCaptcha()
}, })
registerByEmail() { },
uni.navigateTo({ navigateBack() {
url: '/uni_modules/uni-id-pages/pages/register/register-by-email' uni.navigateBack()
}) },
} toLogin() {
} uni.navigateTo({
} url: '/uni_modules/uni-id-pages/pages/login/login-withpwd'
</script> })
},
<style lang="scss"> registerByEmail() {
@import "@/uni_modules/uni-id-pages/common/login-page.scss"; uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/register/register-by-email'
@media screen and (max-width: 690px) { })
.uni-content{ }
margin-top: 15px; }
height: 100%; }
</script>
<style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
@media screen and (max-width: 690px) {
.uni-content {
margin-top: 15px;
height: 100%;
background-color: #fff; background-color: #fff;
} }
} }
@media screen and (min-width: 690px) {
.uni-content{ @media screen and (min-width: 690px) {
.uni-content {
padding: 30px 40px 60px; padding: 30px 40px 60px;
} max-height: 530px;
}
.link-box {
/* #ifndef APP-NVUE */ .link-box {
display: flex; /* #ifndef APP-NVUE */
/* #endif */ display: flex;
flex-direction: row; /* #endif */
justify-content: space-between; flex-direction: row;
margin-top: 10px; justify-content: space-between;
} margin-top: 10px;
}
.link {
font-size: 12px; .link {
} font-size: 12px;
} }
}
.uni-content ::v-deep .uni-forms-item__label {
position: absolute; .uni-content ::v-deep .uni-forms-item__label {
left: -15px; position: absolute;
} left: -15px;
}
button {
margin-top: 15px; button {
} margin-top: 15px;
}
</style> </style>
...@@ -204,6 +204,7 @@ ...@@ -204,6 +204,7 @@
@media screen and (min-width: 690px) { @media screen and (min-width: 690px) {
.uni-content{ .uni-content{
padding: 30px 40px 40px; padding: 30px 40px 40px;
max-height: 650px;
} }
.link-box { .link-box {
......
...@@ -228,6 +228,7 @@ ...@@ -228,6 +228,7 @@
@media screen and (min-width: 690px) { @media screen and (min-width: 690px) {
.uni-content{ .uni-content{
padding: 30px 40px 40px; padding: 30px 40px 40px;
max-height: 650px;
} }
.link-box { .link-box {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
......
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
</view> </view>
</template> </template>
<script> <script>
import {
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
export default { export default {
data() { data() {
return { return {
...@@ -73,7 +77,7 @@ ...@@ -73,7 +77,7 @@
// #ifndef APP-NVUE // #ifndef APP-NVUE
const eventChannel = this.getOpenerEventChannel(); const eventChannel = this.getOpenerEventChannel();
// #endif // #endif
eventChannel.emit('getUserInfo') mutations.setUserInfo(this.formData)
uni.navigateBack() uni.navigateBack()
}).catch(e => { }).catch(e => {
console.log(e); console.log(e);
......
...@@ -22,9 +22,9 @@ ...@@ -22,9 +22,9 @@
placeholder="请输入要设置的昵称"> placeholder="请输入要设置的昵称">
</uni-popup-dialog> </uni-popup-dialog>
</uni-popup> </uni-popup>
<uni-id-pages-bind-mobile ref="bind-mobile-by-sms" @success="getUserInfo"></uni-id-pages-bind-mobile> <uni-id-pages-bind-mobile ref="bind-mobile-by-sms" @success="bindMobileSuccess"></uni-id-pages-bind-mobile>
<template v-if="showLoginManage"> <template v-if="showLoginManage">
<button v-if="hasLogin" @click="logout">退出登录</button> <button v-if="userInfo._id" @click="logout">退出登录</button>
<button v-else @click="login">去登录</button> <button v-else @click="login">去登录</button>
</template> </template>
</view> </view>
...@@ -33,8 +33,16 @@ ...@@ -33,8 +33,16 @@
const db = uniCloud.database(); const db = uniCloud.database();
const usersTable = db.collection('uni-id-users') const usersTable = db.collection('uni-id-users')
const uniIdCo = uniCloud.importObject("uni-id-co") const uniIdCo = uniCloud.importObject("uni-id-co")
import common from '@/uni_modules/uni-id-pages/common/common.js'; import {
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
export default { export default {
computed: {
userInfo() {
return store.userInfo
}
},
data() { data() {
return { return {
univerifyStyle: { univerifyStyle: {
...@@ -45,11 +53,10 @@ ...@@ -45,11 +53,10 @@
"title": "其他号码绑定", "title": "其他号码绑定",
} }
}, },
userInfo: { // userInfo: {
mobile:'', // mobile:'',
nickname:'' // nickname:''
}, // },
hasLogin: false,
hasPwd:false, hasPwd:false,
showLoginManage:false//通过页面传参隐藏登录&退出登录按钮 showLoginManage:false//通过页面传参隐藏登录&退出登录按钮
} }
...@@ -62,7 +69,6 @@ ...@@ -62,7 +69,6 @@
if(e.showLoginManage){ if(e.showLoginManage){
this.showLoginManage = true//通过页面传参隐藏登录&退出登录按钮 this.showLoginManage = true//通过页面传参隐藏登录&退出登录按钮
} }
this.getUserInfo()
//判断当前用户是否有密码,否则就不显示密码修改功能 //判断当前用户是否有密码,否则就不显示密码修改功能
let res = await uniIdCo.getAccountInfo() let res = await uniIdCo.getAccountInfo()
this.hasPwd = res.isPasswordSet this.hasPwd = res.isPasswordSet
...@@ -76,7 +82,12 @@ ...@@ -76,7 +82,12 @@
} }
}) })
}, },
logout:common.logout, logout(){
mutations.logout()
},
bindMobileSuccess(){
mutations.updateUserInfo()
},
changePassword(){ changePassword(){
uni.navigateTo({ uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd', url: '/uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd',
...@@ -85,24 +96,6 @@ ...@@ -85,24 +96,6 @@
} }
}) })
}, },
getUserInfo(e) {
uni.showLoading({
mask: true
});
usersTable.where("'_id' == $cloudEnv_uid").field('mobile,nickname,email').get().then(res => {
console.log({res});
this.userInfo = res.result.data[0]
console.log('this.userInfo', this.userInfo);
this.hasLogin = true
}).catch(e => {
this.userInfo = {}
this.hasLogin = false
console.log(e.message, e.errCode);
}).finally(e => {
// console.log(e);
uni.hideLoading()
})
},
bindMobile() { bindMobile() {
// #ifdef APP-PLUS // #ifdef APP-PLUS
uni.preLogin({ uni.preLogin({
...@@ -133,7 +126,7 @@ ...@@ -133,7 +126,7 @@
console.log(e.authResult); console.log(e.authResult);
uniIdCo.bindMobileByUniverify(e.authResult).then(res => { uniIdCo.bindMobileByUniverify(e.authResult).then(res => {
console.log(res); console.log(res);
this.getUserInfo() mutations.updateUserInfo()
}).catch(e => { }).catch(e => {
console.log(e); console.log(e);
}).finally(e=>{ }).finally(e=>{
...@@ -151,37 +144,13 @@ ...@@ -151,37 +144,13 @@
}, },
bindMobileBySmsCode() { bindMobileBySmsCode() {
uni.navigateTo({ uni.navigateTo({
url: './bind-mobile/bind-mobile', url: './bind-mobile/bind-mobile'
events: {
getUserInfo: () => {
this.getUserInfo()
}
},
complete(e) {
console.log(e);
}
}) })
}, },
setNickname(nickname) { setNickname(nickname) {
console.log(nickname); console.log(nickname);
if (nickname) { if (nickname) {
usersTable.where('_id==$env.uid').update({ mutations.updateUserInfo({nickname})
nickname
}).then(e => {
console.log(e);
if (e.result.updated) {
uni.showToast({
title: "更新成功",
icon: 'none'
});
this.userInfo.nickname = nickname
} else {
uni.showToast({
title: "没有改变",
icon: 'none'
});
}
})
this.$refs.dialog.close() this.$refs.dialog.close()
} else { } else {
this.$refs.dialog.open() this.$refs.dialog.open()
...@@ -196,7 +165,8 @@ ...@@ -196,7 +165,8 @@
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import url("/uni_modules/uni-id-pages/common/login-page.scss");
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
.uni-content { .uni-content {
padding: 0; padding: 0;
......
...@@ -12,7 +12,7 @@ const sentence = { ...@@ -12,7 +12,7 @@ const sentence = {
'uni-id-account-audit-failed': 'Account audit failed', 'uni-id-account-audit-failed': 'Account audit failed',
'uni-id-account-closed': 'Account has been closed', 'uni-id-account-closed': 'Account has been closed',
'uni-id-captcha-required': 'Captcha required', 'uni-id-captcha-required': 'Captcha required',
'uni-id-password-error': 'Username or password error', 'uni-id-password-error': 'Password error',
'uni-id-password-error-exceed-limit': 'The number of password errors is excessive', 'uni-id-password-error-exceed-limit': 'The number of password errors is excessive',
'uni-id-invalid-username': 'Invalid username', 'uni-id-invalid-username': 'Invalid username',
'uni-id-invalid-password': 'invalid password', 'uni-id-invalid-password': 'invalid password',
......
...@@ -12,7 +12,7 @@ const sentence = { ...@@ -12,7 +12,7 @@ const sentence = {
'uni-id-account-audit-failed': '此账号审核失败', 'uni-id-account-audit-failed': '此账号审核失败',
'uni-id-account-closed': '此账号已注销', 'uni-id-account-closed': '此账号已注销',
'uni-id-captcha-required': '请输入图形验证码', 'uni-id-captcha-required': '请输入图形验证码',
'uni-id-password-error': '用户名或密码错误', 'uni-id-password-error': '密码错误',
'uni-id-password-error-exceed-limit': '密码错误次数过多,请稍后再试', 'uni-id-password-error-exceed-limit': '密码错误次数过多,请稍后再试',
'uni-id-invalid-username': '用户名不合法', 'uni-id-invalid-username': '用户名不合法',
'uni-id-invalid-password': '密码不合法', 'uni-id-invalid-password': '密码不合法',
......
{ {
"name": "uni-id-co", "name": "uni-id-co",
"version": "1.0.18", "version": "1.0.22",
"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.22",
"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.22",
"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)
## 1.1.3(2021-08-30) ## 1.1.3(2021-08-30)
- 修复 在vue3中to属性在发行应用的时候报错的bug - 修复 在vue3中to属性在发行应用的时候报错的bug
## 1.1.2(2021-07-30) ## 1.1.2(2021-07-30)
- 优化 vue3下事件警告的问题 - 优化 vue3下事件警告的问题
## 1.1.1(2021-07-21) ## 1.1.1(2021-07-21)
- 修复 与其他组件嵌套使用时,点击失效的Bug - 修复 与其他组件嵌套使用时,点击失效的Bug
## 1.1.0(2021-07-13) ## 1.1.0(2021-07-13)
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.0.17(2021-05-12) ## 1.0.17(2021-05-12)
- 新增 组件示例地址 - 新增 组件示例地址
## 1.0.16(2021-02-05) ## 1.0.16(2021-02-05)
- 优化 组件引用关系,通过uni_modules引用组件 - 优化 组件引用关系,通过uni_modules引用组件
## 1.0.15(2021-02-05) ## 1.0.15(2021-02-05)
- 调整为uni_modules目录规范 - 调整为uni_modules目录规范
- 修复 uni-list-chat 角标显示不正常的问题 - 修复 uni-list-chat 角标显示不正常的问题
...@@ -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;
...@@ -104,4 +104,4 @@ ...@@ -104,4 +104,4 @@
} }
/* #endif */ /* #endif */
</style> </style>
...@@ -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,10 +217,10 @@ ...@@ -217,10 +217,10 @@
}; };
</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;
$uni-spacing-row-lg: 15px; $uni-spacing-row-lg: 15px;
$background-color: #fff; $background-color: #fff;
$divide-line-color: #e5e5e5; $divide-line-color: #e5e5e5;
...@@ -535,4 +535,4 @@ ...@@ -535,4 +535,4 @@
left: 0; left: 0;
/* #endif */ /* #endif */
} }
</style> </style>
...@@ -54,8 +54,8 @@ export default { ...@@ -54,8 +54,8 @@ 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 {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
...@@ -105,4 +105,4 @@ $uni-border-color:#e5e5e5; ...@@ -105,4 +105,4 @@ $uni-border-color:#e5e5e5;
} }
/* #endif */ /* #endif */
</style> </style>
<template> <template>
<!-- #ifdef APP-NVUE --> <!-- #ifdef APP-NVUE -->
<refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown"> <refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
<slot /> <slot />
</refresh> </refresh>
<!-- #endif --> <!-- #endif -->
<!-- #ifndef APP-NVUE --> <!-- #ifndef APP-NVUE -->
<view ref="uni-refresh" class="uni-refresh" v-show="isShow"> <view ref="uni-refresh" class="uni-refresh" v-show="isShow">
<slot /> <slot />
</view> </view>
<!-- #endif --> <!-- #endif -->
</template> </template>
<script> <script>
export default { export default {
name: 'UniRefresh', name: 'UniRefresh',
props: { props: {
display: { display: {
type: [String], type: [String],
default: "hide" default: "hide"
} }
}, },
data() { data() {
return { return {
pulling: false pulling: false
} }
}, },
computed: { computed: {
isShow() { isShow() {
if (this.display === "show" || this.pulling === true) { if (this.display === "show" || this.pulling === true) {
return true; return true;
} }
return false; return false;
} }
}, },
created() {}, created() {},
methods: { methods: {
onchange(value) { onchange(value) {
this.pulling = value; this.pulling = value;
}, },
onrefresh(e) { onrefresh(e) {
this.$emit("refresh", e); this.$emit("refresh", e);
}, },
onpullingdown(e) { onpullingdown(e) {
// #ifdef APP-NVUE // #ifdef APP-NVUE
this.$emit("pullingdown", e); this.$emit("pullingdown", e);
// #endif // #endif
// #ifndef APP-NVUE // #ifndef APP-NVUE
var detail = { var detail = {
viewHeight: 90, viewHeight: 90,
pullingDistance: e.height pullingDistance: e.height
} }
this.$emit("pullingdown", detail); this.$emit("pullingdown", detail);
// #endif // #endif
} }
} }
} }
</script> </script>
<style> <style>
.uni-refresh { .uni-refresh {
height: 0; height: 0;
overflow: hidden; overflow: hidden;
} }
</style> </style>
此差异已折叠。
此差异已折叠。
## 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",
......
# uni-open-bridge-common # uni-open-bridge-common
`uni-open-bridge-common` 是统一接管微信等三方平台认证凭据(包括但不限于`access_token``session_key``encrypt_key``ticket`)的开源库。 `uni-open-bridge-common` 是统一接管微信等三方平台认证凭据(包括但不限于`access_token``session_key``encrypt_key``ticket`)的开源库。
文档链接 [https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common](https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common) 文档链接 [https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common](https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common)
'use strict'; 'use strict';
class BridgeError extends Error { class BridgeError extends Error {
...@@ -20,7 +20,7 @@ class BridgeError extends Error { ...@@ -20,7 +20,7 @@ class BridgeError extends Error {
return this.message return this.message
} }
} }
module.exports = { module.exports = {
BridgeError BridgeError
} }
'use strict'; 'use strict';
const TAG = "UNI_OPEN_BRIDGE" const TAG = "UNI_OPEN_BRIDGE"
const HTTP_STATUS = { const HTTP_STATUS = {
SUCCESS: 200 SUCCESS: 200
} }
const PlatformType = { const PlatformType = {
WEIXIN_MP: 'weixin-mp', WEIXIN_MP: 'weixin-mp',
WEIXIN_H5: 'weixin-h5', WEIXIN_H5: 'weixin-h5',
WEIXIN_APP: 'weixin-app', WEIXIN_APP: 'weixin-app',
WEIXIN_WEB: 'weixin-web', WEIXIN_WEB: 'weixin-web',
QQ_MP: 'qq-mp', QQ_MP: 'qq-mp',
QQ_APP: 'qq-app' QQ_APP: 'qq-app'
} }
const ErrorCodeType = { const ErrorCodeType = {
SYSTEM_ERROR: TAG + "_SYSTEM_ERROR" SYSTEM_ERROR: TAG + "_SYSTEM_ERROR"
} }
module.exports = { module.exports = {
HTTP_STATUS, HTTP_STATUS,
PlatformType, PlatformType,
ErrorCodeType ErrorCodeType
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册