提交 5928f309 编写于 作者: DCloud_JSON's avatar DCloud_JSON 提交者: study夏羽

使用旧版uni-ui组件

上级 72a800a9
## 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)
......
const events = {
load: 'load',
error: 'error'
}
const pageMode = {
add: 'add',
replace: 'replace'
}
const attrs = [
'pageCurrent',
'pageSize',
'collection',
'action',
'field',
'getcount',
'orderby',
'where'
]
export default {
data() {
return {
loading: false,
listData: this.getone ? {} : [],
paginationInternal: {
current: this.pageCurrent,
size: this.pageSize,
count: 0
},
errorMessage: ''
}
},
created() {
let db = null;
let dbCmd = null;
if(this.collection){
this.db = uniCloud.database();
this.dbCmd = this.db.command;
}
this._isEnded = false
this.$watch(() => {
var al = []
attrs.forEach(key => {
al.push(this[key])
})
return al
}, (newValue, oldValue) => {
this.paginationInternal.pageSize = this.pageSize
let needReset = false
for (let i = 2; i < newValue.length; i++) {
if (newValue[i] != oldValue[i]) {
needReset = true
break
}
}
if (needReset) {
this.clear()
this.reset()
}
if (newValue[0] != oldValue[0]) {
this.paginationInternal.current = this.pageCurrent
}
this._execLoadData()
})
// #ifdef H5
if (process.env.NODE_ENV === 'development') {
this._debugDataList = []
if (!window.unidev) {
window.unidev = {
clientDB: {
data: []
}
}
}
unidev.clientDB.data.push(this._debugDataList)
}
// #endif
// #ifdef MP-TOUTIAO
let changeName
let events = this.$scope.dataset.eventOpts
for (var i = 0; i < events.length; i++) {
let event = events[i]
if (event[0].includes('^load')) {
changeName = event[1][0][0]
}
}
if (changeName) {
let parent = this.$parent
let maxDepth = 16
this._changeDataFunction = null
while (parent && maxDepth > 0) {
let fun = parent[changeName]
if (fun && typeof fun === 'function') {
this._changeDataFunction = fun
maxDepth = 0
break
}
parent = parent.$parent
maxDepth--;
}
}
// #endif
// if (!this.manual) {
// this.loadData()
// }
},
// #ifdef H5
beforeDestroy() {
if (process.env.NODE_ENV === 'development' && window.unidev) {
var cd = this._debugDataList
var dl = unidev.clientDB.data
for (var i = dl.length - 1; i >= 0; i--) {
if (dl[i] === cd) {
dl.splice(i, 1)
break
}
}
}
},
// #endif
methods: {
loadData(args1, args2) {
let callback = null
if (typeof args1 === 'object') {
if (args1.clear) {
this.clear()
this.reset()
}
if (args1.current !== undefined) {
this.paginationInternal.current = args1.current
}
if (typeof args2 === 'function') {
callback = args2
}
} else if (typeof args1 === 'function') {
callback = args1
}
this._execLoadData(callback)
},
loadMore() {
if (this._isEnded) {
return
}
this._execLoadData()
},
refresh() {
this.clear()
this._execLoadData()
},
clear() {
this._isEnded = false
this.listData = []
},
reset() {
this.paginationInternal.current = 1
},
remove(id, {
action,
callback,
confirmTitle,
confirmContent
} = {}) {
if (!id || !id.length) {
return
}
uni.showModal({
title: confirmTitle || '提示',
content: confirmContent || '是否删除该数据',
showCancel: true,
success: (res) => {
if (!res.confirm) {
return
}
this._execRemove(id, action, callback)
}
})
},
_execLoadData(callback) {
if (this.loading) {
return
}
this.loading = true
this.errorMessage = ''
this._getExec().then((res) => {
this.loading = false
const {
data,
count
} = res.result
this._isEnded = data.length < this.pageSize
callback && callback(data, this._isEnded)
this._dispatchEvent(events.load, data)
if (this.getone) {
this.listData = data.length ? data[0] : undefined
} else if (this.pageData === pageMode.add) {
this.listData.push(...data)
if (this.listData.length) {
this.paginationInternal.current++
}
} else if (this.pageData === pageMode.replace) {
this.listData = data
this.paginationInternal.count = count
}
// #ifdef H5
if (process.env.NODE_ENV === 'development') {
this._debugDataList.length = 0
this._debugDataList.push(...JSON.parse(JSON.stringify(this.listData)))
}
// #endif
}).catch((err) => {
this.loading = false
this.errorMessage = err
callback && callback()
this.$emit(events.error, err)
})
},
_getExec() {
let exec = this.db
if (this.action) {
exec = exec.action(this.action)
}
exec = exec.collection(this.collection)
if (!(!this.where || !Object.keys(this.where).length)) {
exec = exec.where(this.where)
}
if (this.field) {
exec = exec.field(this.field)
}
if (this.orderby) {
exec = exec.orderBy(this.orderby)
}
const {
current,
size
} = this.paginationInternal
exec = exec.skip(size * (current - 1)).limit(size).get({
getCount: this.getcount
})
return exec
},
_execRemove(id, action, callback) {
if (!this.collection || !id) {
return
}
const ids = Array.isArray(id) ? id : [id]
if (!ids.length) {
return
}
uni.showLoading({
mask: true
})
let exec = this.db
if (action) {
exec = exec.action(action)
}
exec.collection(this.collection).where({
_id: dbCmd.in(ids)
}).remove().then((res) => {
callback && callback(res.result)
if (this.pageData === pageMode.replace) {
this.refresh()
} else {
this.removeData(ids)
}
}).catch((err) => {
uni.showModal({
content: err.message,
showCancel: false
})
}).finally(() => {
uni.hideLoading()
})
},
removeData(ids) {
let il = ids.slice(0)
let dl = this.listData
for (let i = dl.length - 1; i >= 0; i--) {
let index = il.indexOf(dl[i]._id)
if (index >= 0) {
dl.splice(i, 1)
il.splice(index, 1)
}
}
},
_dispatchEvent(type, data) {
if (this._changeDataFunction) {
this._changeDataFunction(data, this._isEnded)
} else {
this.$emit(type, data, this._isEnded)
}
}
}
}
...@@ -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.length > 0 ? this.dataValue : selectedArr return this.dataValue && this.dataValue.length > 0 ? this.dataValue : selectedArr
}, },
/** /**
......
{ {
"id": "uni-data-checkbox", "id": "uni-data-checkbox",
"displayName": "uni-data-checkbox 数据选择器", "displayName": "uni-data-checkbox 数据选择器",
"version": "1.0.2", "version": "1.0.1",
"description": "通过数据驱动的单选框和复选框", "description": "通过数据驱动的单选框和复选框",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
......
## 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="boxStyle"> <view class="uni-easyinput" :class="{'uni-easyinput-error':msg}" :style="{color:inputBorder && msg?'#e43d33':styles.color}">
<view class="uni-easyinput__content" :class="inputContentClass" :style="inputContentStyle"> <view class="uni-easyinput__content" :class="{'is-input-border':inputBorder ,'is-input-error-border':inputBorder && msg,'is-textarea':type==='textarea','is-disabled':disabled}"
<uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" :style="{'border-color':inputBorder && msg?'#dd524d':styles.borderColor,'background-color':disabled?styles.disableColor:''}">
@click="onClickIcon('prefix')" size="22"></uni-icons> <uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')"></uni-icons>
<textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea" <textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea" :class="{'input-padding':inputBorder}"
:class="{'input-padding':inputBorder}" :name="name" :value="val" :placeholder="placeholder" :name="name" :value="val" :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" placeholder-class="uni-easyinput__placeholder-class"
:placeholderStyle="placeholderStyle" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" :autoHeight="autoHeight" @input="onInput" @blur="onBlur" @focus="onFocus"
placeholder-class="uni-easyinput__placeholder-class" :maxlength="inputMaxlength" :focus="focused" @confirm="onConfirm"></textarea>
:autoHeight="autoHeight" @input="onInput" @blur="_Blur" @focus="_Focus" @confirm="onConfirm"></textarea> <input v-else :type="type === 'password'?'text':type" class="uni-easyinput__content-input" :style="{
<input v-else :type="type === 'password'?'text':type" class="uni-easyinput__content-input" 'padding-right':type === 'password' ||clearable || prefixIcon?'':'10px',
:style="inputStyle" :name="name" :value="val" :password="!showPassword && type === 'password'" 'padding-left':prefixIcon?'':'10px'
:placeholder="placeholder" :placeholderStyle="placeholderStyle" }"
placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength" :name="name" :value="val" :password="!showPassword && type === 'password'" :placeholder="placeholder"
:focus="focused" :confirmType="confirmType" @focus="_Focus" @blur="_Blur" @input="onInput" :placeholderStyle="placeholderStyle" placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" :confirmType="confirmType" @focus="onFocus"
@confirm="onConfirm" /> @blur="onBlur" @input="onInput" @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'"
<uni-icons v-if="isVal" class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}" :size="18" color="#c0c4cc" @click="onEyes"></uni-icons>
: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" <uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')"></uni-icons>
@click="onClickIcon('suffix')" size="22"></uni-icons>
</template> </template>
<template v-else> <template v-else>
<uni-icons v-if="clearable && isVal && !disabled && type !== 'textarea'" class="content-clear-icon" <uni-icons class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}" type="clear" :size="clearSize"
:class="{'is-textarea-icon':type==='textarea'}" type="clear" :size="clearSize" v-if="clearable && val && !disabled" color="#c0c4cc" @click="onClear"></uni-icons>
:color="msg?'#dd524d':(focusShow?'#2979ff':'#c0c4cc')" @click="onClear"></uni-icons>
</template> </template>
<slot name="right"></slot> <slot name="right"></slot>
</view> </view>
...@@ -36,6 +31,10 @@ ...@@ -36,6 +31,10 @@
</template> </template>
<script> <script>
// import {
// debounce,
// throttle
// } from './common.js'
/** /**
* Easyinput 输入框 * Easyinput 输入框
* @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。 * @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。
...@@ -77,44 +76,13 @@ ...@@ -77,44 +76,13 @@
* @event {Function} iconClick 点击图标时触发 * @event {Function} iconClick 点击图标时触发
* @example <uni-easyinput v-model="mobile"></uni-easyinput> * @example <uni-easyinput v-model="mobile"></uni-easyinput>
*/ */
function obj2strClass(obj) {
let classess = ''
for (let key in obj) {
const val = obj[key]
if (val) {
classess += `${key} `
}
}
return classess
}
function obj2strStyle(obj) { export default {
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', 'clear', 'eyes', 'change'], emits:['click','iconClick','update:modelValue','input','focus','blur','confirm'],
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,
...@@ -132,10 +100,7 @@ ...@@ -132,10 +100,7 @@
type: Boolean, type: Boolean,
default: false default: false
}, },
placeholder: { placeholder: String,
type: String,
default: ' '
},
placeholderStyle: String, placeholderStyle: String,
focus: { focus: {
type: Boolean, type: Boolean,
...@@ -155,7 +120,7 @@ ...@@ -155,7 +120,7 @@
}, },
clearSize: { clearSize: {
type: [Number, String], type: [Number, String],
default: 24 default: 15
}, },
inputBorder: { inputBorder: {
type: Boolean, type: Boolean,
...@@ -173,7 +138,7 @@ ...@@ -173,7 +138,7 @@
type: [Boolean, String], type: [Boolean, String],
default: true default: true
}, },
passwordIcon: { passwordIcon:{
type: Boolean, type: Boolean,
default: true default: true
}, },
...@@ -187,105 +152,79 @@ ...@@ -187,105 +152,79 @@
} }
} }
}, },
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: ''
}; };
}, },
computed: { computed: {
// 输入框内是否有值
isVal() {
const val = this.val
// fixed by mehaotian 处理值为0的情况,字符串0不在处理范围
if (val || val === 0) {
return true
}
return false
},
msg() { msg() {
// console.log('computed', this.form, this.formItem); return this.errorMessage || this.errMsg;
// 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() {
this.init() if(!this.value && this.value !== 0){
// TODO 处理头条vue3 computed 不监听 inject 更改的问题(formItem.errMsg) this.val = this.modelValue
}
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) {
this.$watch('formItem.errMsg', (newVal) => { if (this.formItem.name) {
this.localMsg = newVal if(!this.is_reset){
}) 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: {
...@@ -293,35 +232,28 @@ ...@@ -293,35 +232,28 @@
* 初始化变量值 * 初始化变量值
*/ */
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;
// 判断是否去除空格 // 判断是否去除空格
...@@ -338,79 +270,30 @@ ...@@ -338,79 +270,30 @@
// 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
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', this.val); this.$emit('confirm', e.detail.value);
this.$emit('change', this.val)
}, },
/**
* 清理内容
* @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','')
// 点击叉号触发 },
this.$emit('clear') fieldClick() {
this.$emit('click');
}, },
/**
* 去除空格
*/
trimStr(str, pos = 'both') { trimStr(str, pos = 'both') {
if (pos === 'both') { if (pos === 'both') {
return str.trim(); return str.trim();
...@@ -433,10 +316,9 @@ ...@@ -433,10 +316,9 @@
}; };
</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%;
...@@ -454,14 +336,10 @@ ...@@ -454,14 +336,10 @@
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 {
...@@ -473,16 +351,12 @@ ...@@ -473,16 +351,12 @@
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;
} }
...@@ -497,10 +371,9 @@ ...@@ -497,10 +371,9 @@
flex: 1; flex: 1;
line-height: 1.5; line-height: 1.5;
font-size: 14px; font-size: 14px;
margin: 6px; padding-top: 6px;
margin-left: 0; padding-bottom: 10px;
height: 80px; height: 80px;
min-height: 80px;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
min-height: 80px; min-height: 80px;
width: auto; width: auto;
...@@ -530,9 +403,6 @@ ...@@ -530,9 +403,6 @@
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 {
...@@ -553,10 +423,8 @@ ...@@ -553,10 +423,8 @@
.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%);;
;
} }
} }
...@@ -582,9 +450,9 @@ ...@@ -582,9 +450,9 @@
} }
.is-disabled { .is-disabled {
border-color: red;
background-color: #F7F6F6; background-color: #F7F6F6;
color: #D5D5D5; color: #D5D5D5;
.uni-easyinput__placeholder-class { .uni-easyinput__placeholder-class {
color: #D5D5D5; color: #D5D5D5;
font-size: 12px; font-size: 12px;
......
{ {
"id": "uni-easyinput", "id": "uni-easyinput",
"displayName": "uni-easyinput 增强输入框", "displayName": "uni-easyinput 增强输入框",
"version": "1.1.0", "version": "1.0.3",
"description": "Easyinput 组件是对原生input组件的增强", "description": "Easyinput 组件是对原生input组件的增强",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
......
## 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"> <view class="uni-forms" :class="{ 'uni-forms--top': !border }">
<form> <form @submit.stop="submitForm" @reset="resetForm">
<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) {
...@@ -40,15 +26,18 @@ ...@@ -40,15 +26,18 @@
} }
}; };
// #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|blur] 校验触发器方式 默认 submit * @property {String} validateTrigger = [bind|submit] 校验触发器方式 默认 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
...@@ -62,34 +51,25 @@ ...@@ -62,34 +51,25 @@
* @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',
emits: ['validate', 'submit'], components: {},
options: { emits:['input','reset','validate','submit'],
virtualHost: true
},
props: { props: {
// 即将弃用 // 即将弃用
value: { value: {
type: Object, type: Object,
default () { default () {
return null; return {};
} }
}, },
// vue3 替换 value 属性 // 替换 value 属性
modelValue: { modelValue: {
type: Object, type: Object,
default () { default () {
return null; return {};
}
},
// 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValue
model: {
type: Object,
default () {
return null;
} }
}, },
// 表单校验规则 // 表单校验规则
...@@ -99,68 +79,58 @@ ...@@ -99,68 +79,58 @@
return {}; return {};
} }
}, },
//校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal] // 校验触发器方式,默认 关闭
errShowType: {
type: String,
default: 'undertext'
},
// 校验触发器方式 默认 bind 取值 [bind|submit]
validateTrigger: { validateTrigger: {
type: String, type: String,
default: 'submit' default: ''
}, },
// label 位置,默认 left 取值 top/left // label 位置,可选值 top/left
labelPosition: { labelPosition: {
type: String, type: String,
default: 'left' default: 'left'
}, },
// label 宽度 // label 宽度,单位 px
labelWidth: { labelWidth: {
type: [String, Number], type: [String, Number],
default: '' default: ''
}, },
// label 居中方式,默认 left 取值 left/center/right // label 居中方式,可选值 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() {
localData() { if (JSON.stringify(this.modelValue) === '{}') {
const localVal = this.model || this.modelValue || this.value return this.value
if (localVal) { } else {
return deepCopy(localVal) return this.modelValue
} }
return {}
} }
}, },
watch: { watch: {
// 监听数据变化 ,暂时不使用,需要单独赋值 rules(newVal) {
// localData: {}, // 如果规则发生变化,要初始化组件
// 监听规则变化 this.init(newVal);
rules: { },
handler: function(val, oldVal) { labelPosition() {
this.setRules(val) this.childrens.forEach(vm => {
}, vm.init()
deep: true, })
immediate: true
} }
}, },
created() { created() {
...@@ -186,132 +156,137 @@ ...@@ -186,132 +156,137 @@
} }
// #endif // #endif
// 子组件实例数组 // 存放watch 监听数组
this.childrens = [] this.unwatchs = [];
// TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错 // 存放子组件数组
this.inputChildrens = [] this.childrens = [];
this.setRules(this.rules) // 存放 easyInput 组件
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) {
* @param {Array} rules 规则源数据 this.formData = this.dataValue
*/ return
setRules(rules) { };
// TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖 this.formRules = formRules;
this.formRules = Object.assign({}, this.formRules, rules) this.validator = new Validator(formRules);
// 初始化校验函数 this.registerWatch();
this.validator = new Validator(rules); },
// 监听 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} key * @param {Object} formRules
* @param {Object} value
*/ */
setValue(key, value) { setRules(formRules) {
let example = this.childrens.find(child => child.name === key); this.init(formRules);
if (!example) return null;
this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || [])
return example.onFieldChange(this.formData[key]);
}, },
/** /**
* 外部调用方法 * 公开给用户使用
* 手动提交校验表单 * 设置自定义表单组件 value 值
* 对整个表单进行校验的方法,参数为一个回调函数。 * @param {String} name 字段名称
* @param {Array} keepitem 保留不参与校验的字段 * @param {String} value 字段值
* @param {type} callback 方法回调
*/ */
validate(keepitem, callback) { setValue(name, value, callback) {
return this.checkAll(this.formData, keepitem, callback); let example = this.childrens.find(child => child.name === name);
if (!example) return null;
value = this._getValue(example.name, value);
this.formData[name] = value;
example.val = value;
return example.triggerCheck(value, callback);
}, },
/** /**
* 外部调用方法 * 表单重置
* 部分表单校验 * @param {Object} event
* @param {Array|String} props 需要校验的字段
* @param {Function} 回调函数
*/ */
validateField(props = [], callback) { resetForm(event) {
props = [].concat(props);
let invalidFields = {};
this.childrens.forEach(item => { this.childrens.forEach(item => {
const name = realName(item.name) item.errMsg = '';
if (props.indexOf(name) !== -1) { const inputComp = this.inputChildrens.find(child => child.rename === item.name);
invalidFields = Object.assign({}, invalidFields, { if (inputComp) {
[name]: this.formData[name] inputComp.errMsg = '';
}); // 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 (props.length === 0) { if (item.name) {
item.errMsg = ''; this.formData[item.name] = this._getValue(item.name, '');
} 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 方法回调
*/ */
submit(keepitem, callback, type) { validateCheck(validate) {
for (let i in this.dataValue) { if (validate === null) validate = null;
const itemData = this.childrens.find(v => v.name === i); this.$emit('validate', validate);
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 => realName(v.name) === i) const item = this.childrens.find(v => 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) {
...@@ -321,39 +296,47 @@ ...@@ -321,39 +296,47 @@
} }
let results = []; let results = [];
// 避免引用错乱 ,建议拷贝对象处理 let newFormData = {};
let tempFormData = JSON.parse(JSON.stringify(invalidFields)) if (this.validator) {
// 所有子组件参与校验,使用 for 可以使用 awiat for (let key in childrens) {
for (let i in childrens) { const child = childrens[key];
const child = childrens[i] let name = child.isArray ? child.arrayField : child.name;
let name = realName(child.name); if (child.isArray) {
const result = await child.onFieldChange(tempFormData[name]); if (child.name.indexOf('[') !== -1 && child.name.indexOf(']') !== -1) {
if (result) { const fieldData = child.name.split('[');
results.push(result); const fieldName = fieldData[0];
// toast ,modal 只需要执行第一次就可以 const fieldValue = fieldData[1].replace(']', '');
if (this.errShowType === 'toast' || this.errShowType === 'modal') break; if (!newFormData[fieldName]) {
newFormData[fieldName] = {};
}
newFormData[fieldName][fieldValue] = this._getValue(name, invalidFields[name]);
}
} else {
newFormData[name] = this._getValue(name, invalidFields[name]);
}
const result = await child.triggerCheck(invalidFields[name], true);
if (result) {
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 => {
let vName = realName(v); newFormData[v] = this.dataValue[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: tempFormData, value: newFormData,
errors: results errors: results
} }
}); });
...@@ -361,37 +344,129 @@ ...@@ -361,37 +344,129 @@
this.$emit('validate', results); this.$emit('validate', results);
} }
// const resetFormData = rawData(tempFormData, this.localData, this.name) callback && typeof callback === 'function' && callback(results, newFormData);
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} result * @param {Object} props
* @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);
},
/**
* 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
*/ */
validateCheck(result) { resetFields() {
this.$emit('validate', result); this.resetForm();
}, },
_getValue: getValue,
_isRequiredField: isRequiredField, /**
_setDataValue: setDataValue, * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
_getDataValue: getDataValue, */
_realName: realName, clearValidate(props) {
_isRealName: isRealName, props = [].concat(props);
_isEqual: isEqual this.childrens.forEach(item => {
const inputComp = this.inputChildrens.find(child => child.rename === item.name);
if (props.length === 0) {
item.errMsg = '';
if (inputComp) {
inputComp.errMsg = '';
}
} else {
if (props.indexOf(item.name) !== -1) {
item.errMsg = '';
if (inputComp) {
inputComp.errMsg = '';
}
}
}
});
},
/**
* 把 value 转换成指定的类型
* @param {Object} key
* @param {Object} value
*/
_getValue(key, value) {
const rules = (this.formRules[key] && this.formRules[key].rules) || [];
const isRuleNum = rules.find(val => val.format && this.type_filter(val.format));
const isRuleBool = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
// 输入值为 number
if (isRuleNum) {
value = isNaN(value) ? value : value === '' || value === null ? null : Number(value);
}
// 简单判断真假值
if (isRuleBool) {
value = !value ? false : true;
}
return value;
},
/**
* 过滤数字类型
* @param {Object} format
*/
type_filter(format) {
return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
}
} }
}; };
</script> </script>
<style lang="scss"> <style lang="scss" >
.uni-forms {} .uni-forms {
</style> // overflow: hidden;
// padding: 10px 15px;
}
.uni-forms--top {
// padding: 10px 15px;
// padding-top: 22px;
}
</style>
{ {
"id": "uni-forms", "id": "uni-forms",
"displayName": "uni-forms 表单", "displayName": "uni-forms 表单",
"version": "1.4.8", "version": "1.3.2",
"description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据", "description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
...@@ -17,7 +17,11 @@ ...@@ -17,7 +17,11 @@
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
}, },
"dcloudext": { "dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": { "sale": {
"regular": { "regular": {
"price": "0.00" "price": "0.00"
...@@ -34,8 +38,7 @@ ...@@ -34,8 +38,7 @@
"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": [
...@@ -71,8 +74,7 @@ ...@@ -71,8 +74,7 @@
"阿里": "y", "阿里": "y",
"百度": "y", "百度": "y",
"字节跳动": "y", "字节跳动": "y",
"QQ": "y", "QQ": "y"
"京东": "u"
}, },
"快应用": { "快应用": {
"华为": "u", "华为": "u",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册