@10yun/cv-mobile-ui 0.5.20 → 0.5.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugins/jumps.js +57 -12
- package/plugins/lbs.js +17 -8
- package/ui-cv/components/cv-grid-item/cv-grid-item.vue +1 -1
- package/uni-ui/lib/uni-badge/uni-badge.vue +150 -1
- package/uni-ui/lib/uni-breadcrumb/uni-breadcrumb.vue +37 -1
- package/uni-ui/lib/uni-breadcrumb-item/uni-breadcrumb-item.vue +83 -1
- package/uni-ui/lib/uni-calendar/uni-calendar-item.vue +122 -1
- package/uni-ui/lib/uni-calendar/uni-calendar.vue +366 -1
- package/uni-ui/lib/uni-card/uni-card.vue +124 -1
- package/uni-ui/lib/uni-col/uni-col.vue +1 -1
- package/uni-ui/lib/uni-collapse/uni-collapse.vue +135 -1
- package/uni-ui/lib/uni-collapse-item/uni-collapse-item.vue +266 -1
- package/uni-ui/lib/uni-combox/uni-combox.vue +1 -1
- package/uni-ui/lib/uni-countdown/uni-countdown.vue +239 -1
- package/uni-ui/lib/uni-data-checkbox/uni-data-checkbox.vue +487 -1
- package/uni-ui/lib/uni-data-picker/uni-data-picker.vue +530 -1
- package/uni-ui/lib/uni-data-pickerview/uni-data-picker.js +157 -150
- package/uni-ui/lib/uni-data-pickerview/uni-data-pickerview.vue +166 -1
- package/uni-ui/lib/uni-data-select/uni-data-select.vue +289 -1
- package/uni-ui/lib/uni-datetime-picker/calendar-item.vue +70 -1
- package/uni-ui/lib/uni-datetime-picker/calendar.vue +629 -1
- package/uni-ui/lib/uni-datetime-picker/time-picker.vue +741 -1
- package/uni-ui/lib/uni-datetime-picker/uni-datetime-picker.vue +847 -1
- package/uni-ui/lib/uni-drawer/uni-drawer.vue +115 -1
- package/uni-ui/lib/uni-easyinput/uni-easyinput.vue +515 -1
- package/uni-ui/lib/uni-fab/uni-fab.vue +257 -1
- package/uni-ui/lib/uni-fav/uni-fav.vue +123 -1
- package/uni-ui/lib/uni-file-picker/uni-file-picker.vue +642 -1
- package/uni-ui/lib/uni-file-picker/upload-file.vue +177 -1
- package/uni-ui/lib/uni-file-picker/upload-image.vue +176 -1
- package/uni-ui/lib/uni-forms/uni-forms.vue +375 -1
- package/uni-ui/lib/uni-forms-item/uni-forms-item.vue +429 -1
- package/uni-ui/lib/uni-goods-nav/uni-goods-nav.vue +129 -1
- package/uni-ui/lib/uni-grid/uni-grid.vue +115 -1
- package/uni-ui/lib/uni-grid-item/uni-grid-item.vue +78 -1
- package/uni-ui/lib/uni-group/uni-group.vue +85 -1
- package/uni-ui/lib/uni-icons/uni-icons.vue +85 -1
- package/uni-ui/lib/uni-indexed-list/uni-indexed-list-item.vue +68 -1
- package/uni-ui/lib/uni-indexed-list/uni-indexed-list.vue +294 -1
- package/uni-ui/lib/uni-list/uni-list.vue +81 -1
- package/uni-ui/lib/uni-list-ad/uni-list-ad.vue +77 -1
- package/uni-ui/lib/uni-list-chat/uni-list-chat.vue +294 -1
- package/uni-ui/lib/uni-list-item/uni-list-item.vue +346 -1
- package/uni-ui/lib/uni-load-more/uni-load-more.vue +172 -1
- package/uni-ui/lib/uni-nav-bar/uni-nav-bar.vue +205 -1
- package/uni-ui/lib/uni-nav-bar/uni-status-bar.vue +18 -1
- package/uni-ui/lib/uni-notice-bar/uni-notice-bar.vue +331 -1
- package/uni-ui/lib/uni-number-box/uni-number-box.vue +166 -1
- package/uni-ui/lib/uni-pagination/uni-pagination.vue +323 -1
- package/uni-ui/lib/uni-popup/uni-popup.vue +1 -1
- package/uni-ui/lib/uni-popup-dialog/uni-popup-dialog.vue +173 -1
- package/uni-ui/lib/uni-popup-message/uni-popup-message.vue +74 -1
- package/uni-ui/lib/uni-popup-share/uni-popup-share.vue +106 -1
- package/uni-ui/lib/uni-rate/uni-rate.vue +322 -1
- package/uni-ui/lib/uni-row/uni-row.vue +1 -1
- package/uni-ui/lib/uni-search-bar/uni-search-bar.vue +236 -1
- package/uni-ui/lib/uni-section/uni-section.vue +109 -1
- package/uni-ui/lib/uni-segmented-control/uni-segmented-control.vue +103 -1
- package/uni-ui/lib/uni-status-bar/uni-status-bar.vue +1 -1
- package/uni-ui/lib/uni-steps/uni-steps.vue +120 -1
- package/uni-ui/lib/uni-swipe-action-item/uni-swipe-action-item.vue +226 -3
- package/uni-ui/lib/uni-swiper-dot/uni-swiper-dot.vue +167 -1
- package/uni-ui/lib/uni-table/uni-table.vue +297 -1
- package/uni-ui/lib/uni-tag/uni-tag.vue +100 -1
- package/uni-ui/lib/uni-td/uni-td.vue +78 -1
- package/uni-ui/lib/uni-th/filter-dropdown.vue +1 -1
- package/uni-ui/lib/uni-th/uni-th.vue +224 -1
- package/uni-ui/lib/uni-thead/uni-thead.vue +77 -1
- package/uni-ui/lib/uni-tr/table-checkbox.vue +79 -1
- package/uni-ui/lib/uni-tr/uni-tr.vue +135 -1
|
@@ -1 +1,429 @@
|
|
|
1
|
-
<template>
|
|
2
1
|
<view
|
|
3
2
|
class="uni-forms-item"
|
|
4
3
|
:class="[
|
|
5
4
|
'is-direction-' + localLabelPos,
|
|
6
5
|
border ? 'uni-forms-item--border' : '',
|
|
7
6
|
border && isFirstBorder ? 'is-first-border' : ''
|
|
8
7
|
]"
|
|
9
8
|
>
|
|
10
9
|
<slot name="label">
|
|
11
10
|
<view
|
|
12
11
|
class="uni-forms-item__label"
|
|
13
12
|
:class="{ 'no-label': !label && !required }"
|
|
14
13
|
:style="{ width: localLabelWidth, justifyContent: localLabelAlign }"
|
|
15
14
|
>
|
|
16
15
|
<text v-if="required" class="is-required">*</text>
|
|
17
16
|
<text>{{ label }}</text>
|
|
18
17
|
</view>
|
|
19
18
|
</slot>
|
|
20
19
|
<!-- #ifndef APP-NVUE -->
|
|
21
20
|
<view class="uni-forms-item__content">
|
|
22
21
|
<slot></slot>
|
|
23
22
|
<view class="uni-forms-item__error" :class="{ 'msg--active': msg }">
|
|
24
23
|
<text>{{ msg }}</text>
|
|
25
24
|
</view>
|
|
26
25
|
</view>
|
|
27
26
|
<!-- #endif -->
|
|
28
27
|
<!-- #ifdef APP-NVUE -->
|
|
29
28
|
<view class="uni-forms-item__nuve-content">
|
|
30
29
|
<view class="uni-forms-item__content">
|
|
31
30
|
<slot></slot>
|
|
32
31
|
</view>
|
|
33
32
|
<view class="uni-forms-item__error" :class="{ 'msg--active': msg }">
|
|
34
33
|
<text class="error-text">{{ msg }}</text>
|
|
35
34
|
</view>
|
|
36
35
|
</view>
|
|
37
36
|
<!-- #endif -->
|
|
38
37
|
</view>
|
|
39
38
|
* uni-fomrs-item 表单子组件
|
|
40
39
|
* @description uni-fomrs-item 表单子组件,提供了基础布局已经校验能力
|
|
41
40
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=2773
|
|
42
41
|
* @property {Boolean} required 是否必填,左边显示红色"*"号
|
|
43
42
|
* @property {String } label 输入框左边的文字提示
|
|
44
43
|
* @property {Number } labelWidth label的宽度,单位px(默认65)
|
|
45
44
|
* @property {String } labelAlign = [left|center|right] label的文字对齐方式(默认left)
|
|
46
45
|
* @value left label 左侧显示
|
|
47
46
|
* @value center label 居中
|
|
48
47
|
* @value right label 右侧对齐
|
|
49
48
|
* @property {String } errorMessage 显示的错误提示内容,如果为空字符串或者false,则不显示错误信息
|
|
50
49
|
* @property {String } name 表单域的属性名,在使用校验规则时必填
|
|
51
50
|
* @property {String } leftIcon 【1.4.0废弃】label左边的图标,限 uni-ui 的图标名称
|
|
52
51
|
* @property {String } iconColor 【1.4.0废弃】左边通过icon配置的图标的颜色(默认#606266)
|
|
53
52
|
* @property {String} validateTrigger = [bind|submit|blur] 【1.4.0废弃】校验触发器方式 默认 submit
|
|
54
53
|
* @value bind 发生变化时触发
|
|
55
54
|
* @value submit 提交时触发
|
|
56
55
|
* @value blur 失去焦点触发
|
|
57
56
|
* @property {String } labelPosition = [top|left] 【1.4.0废弃】label的文字的位置(默认left)
|
|
58
57
|
* @value top 顶部显示 label
|
|
59
58
|
* @value left 左侧显示 label
|
|
60
59
|
*/
|
|
61
60
|
name: 'uniFormsItem',
|
|
62
61
|
options: {
|
|
63
62
|
virtualHost: true
|
|
64
63
|
},
|
|
65
64
|
provide() {
|
|
66
65
|
return {
|
|
67
66
|
uniFormItem: this
|
|
68
67
|
};
|
|
69
68
|
},
|
|
70
69
|
inject: {
|
|
71
70
|
form: {
|
|
72
71
|
from: 'uniForm',
|
|
73
72
|
default: null
|
|
74
73
|
}
|
|
75
74
|
},
|
|
76
75
|
props: {
|
|
77
76
|
// 表单校验规则
|
|
78
77
|
rules: {
|
|
79
78
|
type: Array,
|
|
80
79
|
default() {
|
|
81
80
|
return null;
|
|
82
81
|
}
|
|
83
82
|
},
|
|
84
83
|
// 表单域的属性名,在使用校验规则时必填
|
|
85
84
|
name: {
|
|
86
85
|
type: [String, Array],
|
|
87
86
|
default: ''
|
|
88
87
|
},
|
|
89
88
|
required: {
|
|
90
89
|
type: Boolean,
|
|
91
90
|
default: false
|
|
92
91
|
},
|
|
93
92
|
label: {
|
|
94
93
|
type: String,
|
|
95
94
|
default: ''
|
|
96
95
|
},
|
|
97
96
|
// label的宽度 ,默认 80
|
|
98
97
|
labelWidth: {
|
|
99
98
|
type: [String, Number],
|
|
100
99
|
default: ''
|
|
101
100
|
},
|
|
102
101
|
// label 居中方式,默认 left 取值 left/center/right
|
|
103
102
|
labelAlign: {
|
|
104
103
|
type: String,
|
|
105
104
|
default: ''
|
|
106
105
|
},
|
|
107
106
|
// 强制显示错误信息
|
|
108
107
|
errorMessage: {
|
|
109
108
|
type: [String, Boolean],
|
|
110
109
|
default: ''
|
|
111
110
|
},
|
|
112
111
|
// 1.4.0 弃用,统一使用 form 的校验时机
|
|
113
112
|
// validateTrigger: {
|
|
114
113
|
// type: String,
|
|
115
114
|
// default: ''
|
|
116
115
|
// },
|
|
117
116
|
// 1.4.0 弃用,统一使用 form 的label 位置
|
|
118
117
|
// labelPosition: {
|
|
119
118
|
// type: String,
|
|
120
119
|
// default: ''
|
|
121
120
|
// },
|
|
122
121
|
// 1.4.0 以下属性已经废弃,请使用 #label 插槽代替
|
|
123
122
|
leftIcon: String,
|
|
124
123
|
iconColor: {
|
|
125
124
|
type: String,
|
|
126
125
|
default: '#606266'
|
|
127
126
|
}
|
|
128
127
|
},
|
|
129
128
|
data() {
|
|
130
129
|
return {
|
|
131
130
|
errMsg: '',
|
|
132
131
|
userRules: null,
|
|
133
132
|
localLabelAlign: 'left',
|
|
134
133
|
localLabelWidth: '65px',
|
|
135
134
|
localLabelPos: 'left',
|
|
136
135
|
border: false,
|
|
137
136
|
isFirstBorder: false
|
|
138
137
|
};
|
|
139
138
|
},
|
|
140
139
|
computed: {
|
|
141
140
|
// 处理错误信息
|
|
142
141
|
msg() {
|
|
143
142
|
return this.errorMessage || this.errMsg;
|
|
144
143
|
}
|
|
145
144
|
},
|
|
146
145
|
watch: {
|
|
147
146
|
// 规则发生变化通知子组件更新
|
|
148
147
|
'form.formRules'(val) {
|
|
149
148
|
// TODO 处理头条vue3 watch不生效的问题
|
|
150
149
|
// #ifndef MP-TOUTIAO
|
|
151
150
|
this.init();
|
|
152
151
|
// #endif
|
|
153
152
|
},
|
|
154
153
|
'form.labelWidth'(val) {
|
|
155
154
|
// 宽度
|
|
156
155
|
this.localLabelWidth = this._labelWidthUnit(val);
|
|
157
156
|
},
|
|
158
157
|
'form.labelPosition'(val) {
|
|
159
158
|
// 标签位置
|
|
160
159
|
this.localLabelPos = this._labelPosition();
|
|
161
160
|
},
|
|
162
161
|
'form.labelAlign'(val) {}
|
|
163
162
|
},
|
|
164
163
|
created() {
|
|
165
164
|
this.init(true);
|
|
166
165
|
if (this.name && this.form) {
|
|
167
166
|
// TODO 处理头条vue3 watch不生效的问题
|
|
168
167
|
// #ifdef MP-TOUTIAO
|
|
169
168
|
this.$watch('form.formRules', () => {
|
|
170
169
|
this.init();
|
|
171
170
|
});
|
|
172
171
|
// #endif
|
|
173
172
|
// 监听变化
|
|
174
173
|
this.$watch(
|
|
175
174
|
() => {
|
|
176
175
|
const val = this.form._getDataValue(this.name, this.form.localData);
|
|
177
176
|
return val;
|
|
178
177
|
},
|
|
179
178
|
(value, oldVal) => {
|
|
180
179
|
const isEqual = this.form._isEqual(value, oldVal);
|
|
181
180
|
// 简单判断前后值的变化,只有发生变化才会发生校验
|
|
182
181
|
// TODO 如果 oldVal = undefined ,那么大概率是源数据里没有值导致 ,这个情况不哦校验 ,可能不严谨 ,需要在做观察
|
|
183
182
|
// fix by mehaotian 暂时取消 && oldVal !== undefined ,如果formData 中不存在,可能会不校验
|
|
184
183
|
if (!isEqual) {
|
|
185
184
|
const val = this.itemSetValue(value);
|
|
186
185
|
this.onFieldChange(val, false);
|
|
187
186
|
}
|
|
188
187
|
},
|
|
189
188
|
{
|
|
190
189
|
immediate: false
|
|
191
190
|
}
|
|
192
191
|
);
|
|
193
192
|
}
|
|
194
193
|
},
|
|
195
194
|
// #ifndef VUE3
|
|
196
195
|
destroyed() {
|
|
197
196
|
if (this.__isUnmounted) return;
|
|
198
197
|
this.unInit();
|
|
199
198
|
},
|
|
200
199
|
// #endif
|
|
201
200
|
// #ifdef VUE3
|
|
202
201
|
unmounted() {
|
|
203
202
|
this.__isUnmounted = true;
|
|
204
203
|
this.unInit();
|
|
205
204
|
},
|
|
206
205
|
// #endif
|
|
207
206
|
methods: {
|
|
208
207
|
/**
|
|
209
208
|
* 外部调用方法
|
|
210
209
|
* 设置规则 ,主要用于小程序自定义检验规则
|
|
211
210
|
* @param {Array} rules 规则源数据
|
|
212
211
|
*/
|
|
213
212
|
setRules(rules = null) {
|
|
214
213
|
this.userRules = rules;
|
|
215
214
|
this.init(false);
|
|
216
215
|
},
|
|
217
216
|
// 兼容老版本表单组件
|
|
218
217
|
setValue() {
|
|
219
218
|
// console.log('setValue 方法已经弃用,请使用最新版本的 uni-forms 表单组件以及其他关联组件。');
|
|
220
219
|
},
|
|
221
220
|
/**
|
|
222
221
|
* 外部调用方法
|
|
223
222
|
* 校验数据
|
|
224
223
|
* @param {any} value 需要校验的数据
|
|
225
224
|
* @param {boolean} 是否立即校验
|
|
226
225
|
* @return {Array|null} 校验内容
|
|
227
226
|
*/
|
|
228
227
|
async onFieldChange(value, formtrigger = true) {
|
|
229
228
|
const { formData, localData, errShowType, validateCheck, validateTrigger, _isRequiredField, _realName } = this.form;
|
|
230
229
|
const name = _realName(this.name);
|
|
231
230
|
if (!value) {
|
|
232
231
|
value = this.form.formData[name];
|
|
233
232
|
}
|
|
234
233
|
// fixd by mehaotian 不在校验前清空信息,解决闪屏的问题
|
|
235
234
|
// this.errMsg = '';
|
|
236
235
|
// fix by mehaotian 解决没有检验规则的情况下,抛出错误的问题
|
|
237
236
|
const ruleLen = this.itemRules.rules && this.itemRules.rules.length;
|
|
238
237
|
if (!this.validator || !ruleLen || ruleLen === 0) return;
|
|
239
238
|
// 检验时机
|
|
240
239
|
// let trigger = this.isTrigger(this.itemRules.validateTrigger, this.validateTrigger, validateTrigger);
|
|
241
240
|
const isRequiredField = _isRequiredField(this.itemRules.rules || []);
|
|
242
241
|
let result = null;
|
|
243
242
|
// 只有等于 bind 时 ,才能开启时实校验
|
|
244
243
|
if (validateTrigger === 'bind' || formtrigger) {
|
|
245
244
|
// 校验当前表单项
|
|
246
245
|
result = await this.validator.validateUpdate(
|
|
247
246
|
{
|
|
248
247
|
[name]: value
|
|
249
248
|
},
|
|
250
249
|
formData
|
|
251
250
|
);
|
|
252
251
|
// 判断是否必填,非必填,不填不校验,填写才校验 ,暂时只处理 undefined 和空的情况
|
|
253
252
|
if (!isRequiredField && (value === undefined || value === '')) {
|
|
254
253
|
result = null;
|
|
255
254
|
}
|
|
256
255
|
// 判断错误信息显示类型
|
|
257
256
|
if (result && result.errorMessage) {
|
|
258
257
|
if (errShowType === 'undertext') {
|
|
259
258
|
// 获取错误信息
|
|
260
259
|
this.errMsg = !result ? '' : result.errorMessage;
|
|
261
260
|
}
|
|
262
261
|
if (errShowType === 'toast') {
|
|
263
262
|
uni.showToast({
|
|
264
263
|
title: result.errorMessage || '校验错误',
|
|
265
264
|
icon: 'none'
|
|
266
265
|
});
|
|
267
266
|
}
|
|
268
267
|
if (errShowType === 'modal') {
|
|
269
268
|
uni.showModal({
|
|
270
269
|
title: '提示',
|
|
271
270
|
content: result.errorMessage || '校验错误'
|
|
272
271
|
});
|
|
273
272
|
}
|
|
274
273
|
} else {
|
|
275
274
|
this.errMsg = '';
|
|
276
275
|
}
|
|
277
276
|
// 通知 form 组件更新事件
|
|
278
277
|
validateCheck(result ? result : null);
|
|
279
278
|
} else {
|
|
280
279
|
this.errMsg = '';
|
|
281
280
|
}
|
|
282
281
|
return result ? result : null;
|
|
283
282
|
},
|
|
284
283
|
/**
|
|
285
284
|
* 初始组件数据
|
|
286
285
|
*/
|
|
287
286
|
init(type = false) {
|
|
288
287
|
const { validator, formRules, childrens, formData, localData, _realName, labelWidth, _getDataValue, _setDataValue } =
|
|
289
288
|
this.form || {};
|
|
290
289
|
// 对齐方式
|
|
291
290
|
this.localLabelAlign = this._justifyContent();
|
|
292
291
|
// 宽度
|
|
293
292
|
this.localLabelWidth = this._labelWidthUnit(labelWidth);
|
|
294
293
|
// 标签位置
|
|
295
294
|
this.localLabelPos = this._labelPosition();
|
|
296
295
|
// 将需要校验的子组件加入form 队列
|
|
297
296
|
this.form && type && childrens.push(this);
|
|
298
297
|
if (!validator || !formRules) return;
|
|
299
298
|
// 判断第一个 item
|
|
300
299
|
if (!this.form.isFirstBorder) {
|
|
301
300
|
this.form.isFirstBorder = true;
|
|
302
301
|
this.isFirstBorder = true;
|
|
303
302
|
}
|
|
304
303
|
// 判断 group 里的第一个 item
|
|
305
304
|
if (this.group) {
|
|
306
305
|
if (!this.group.isFirstBorder) {
|
|
307
306
|
this.group.isFirstBorder = true;
|
|
308
307
|
this.isFirstBorder = true;
|
|
309
308
|
}
|
|
310
309
|
}
|
|
311
310
|
this.border = this.form.border;
|
|
312
311
|
// 获取子域的真实名称
|
|
313
312
|
const name = _realName(this.name);
|
|
314
313
|
const itemRule = this.userRules || this.rules;
|
|
315
314
|
if (typeof formRules === 'object' && itemRule) {
|
|
316
315
|
// 子规则替换父规则
|
|
317
316
|
formRules[name] = {
|
|
318
317
|
rules: itemRule
|
|
319
318
|
};
|
|
320
319
|
validator.updateSchema(formRules);
|
|
321
320
|
}
|
|
322
321
|
// 注册校验规则
|
|
323
322
|
const itemRules = formRules[name] || {};
|
|
324
323
|
this.itemRules = itemRules;
|
|
325
324
|
// 注册校验函数
|
|
326
325
|
this.validator = validator;
|
|
327
326
|
// 默认值赋予
|
|
328
327
|
this.itemSetValue(_getDataValue(this.name, localData));
|
|
329
328
|
},
|
|
330
329
|
unInit() {
|
|
331
330
|
if (this.form) {
|
|
332
331
|
const { childrens, formData, _realName } = this.form;
|
|
333
332
|
childrens.forEach((item, index) => {
|
|
334
333
|
if (item === this) {
|
|
335
334
|
this.form.childrens.splice(index, 1);
|
|
336
335
|
delete formData[_realName(item.name)];
|
|
337
336
|
}
|
|
338
337
|
});
|
|
339
338
|
}
|
|
340
339
|
},
|
|
341
340
|
// 设置item 的值
|
|
342
341
|
itemSetValue(value) {
|
|
343
342
|
const name = this.form._realName(this.name);
|
|
344
343
|
const rules = this.itemRules.rules || [];
|
|
345
344
|
const val = this.form._getValue(name, value, rules);
|
|
346
345
|
this.form._setDataValue(name, this.form.formData, val);
|
|
347
346
|
return val;
|
|
348
347
|
},
|
|
349
348
|
/**
|
|
350
349
|
* 移除该表单项的校验结果
|
|
351
350
|
*/
|
|
352
351
|
clearValidate() {
|
|
353
352
|
this.errMsg = '';
|
|
354
353
|
},
|
|
355
354
|
// 是否显示星号
|
|
356
355
|
_isRequired() {
|
|
357
356
|
// TODO 不根据规则显示 星号,考虑后续兼容
|
|
358
357
|
// if (this.form) {
|
|
359
358
|
// if (this.form._isRequiredField(this.itemRules.rules || []) && this.required) {
|
|
360
359
|
// return true
|
|
361
360
|
// }
|
|
362
361
|
// return false
|
|
363
362
|
// }
|
|
364
363
|
return this.required;
|
|
365
364
|
},
|
|
366
365
|
// 处理对齐方式
|
|
367
366
|
_justifyContent() {
|
|
368
367
|
if (this.form) {
|
|
369
368
|
const { labelAlign } = this.form;
|
|
370
369
|
let labelAli = this.labelAlign ? this.labelAlign : labelAlign;
|
|
371
370
|
if (labelAli === 'left') return 'flex-start';
|
|
372
371
|
if (labelAli === 'center') return 'center';
|
|
373
372
|
if (labelAli === 'right') return 'flex-end';
|
|
374
373
|
}
|
|
375
374
|
return 'flex-start';
|
|
376
375
|
},
|
|
377
376
|
// 处理 label宽度单位 ,继承父元素的值
|
|
378
377
|
_labelWidthUnit(labelWidth) {
|
|
379
378
|
// if (this.form) {
|
|
380
379
|
// const {
|
|
381
380
|
// labelWidth
|
|
382
381
|
// } = this.form
|
|
383
382
|
return this.num2px(this.labelWidth ? this.labelWidth : labelWidth || (this.label ? 65 : 'auto'));
|
|
384
383
|
// }
|
|
385
384
|
// return '65px'
|
|
386
385
|
},
|
|
387
386
|
// 处理 label 位置
|
|
388
387
|
_labelPosition() {
|
|
389
388
|
if (this.form) return this.form.labelPosition || 'left';
|
|
390
389
|
return 'left';
|
|
391
390
|
},
|
|
392
391
|
/**
|
|
393
392
|
* 触发时机
|
|
394
393
|
* @param {Object} rule 当前规则内时机
|
|
395
394
|
* @param {Object} itemRlue 当前组件时机
|
|
396
395
|
* @param {Object} parentRule 父组件时机
|
|
397
396
|
*/
|
|
398
397
|
isTrigger(rule, itemRlue, parentRule) {
|
|
399
398
|
// bind submit
|
|
400
399
|
if (rule === 'submit' || !rule) {
|
|
401
400
|
if (rule === undefined) {
|
|
402
401
|
if (itemRlue !== 'bind') {
|
|
403
402
|
if (!itemRlue) {
|
|
404
403
|
return parentRule === '' ? 'bind' : 'submit';
|
|
405
404
|
}
|
|
406
405
|
return 'submit';
|
|
407
406
|
}
|
|
408
407
|
return 'bind';
|
|
409
408
|
}
|
|
410
409
|
return 'submit';
|
|
411
410
|
}
|
|
412
411
|
return 'bind';
|
|
413
412
|
},
|
|
414
413
|
num2px(num) {
|
|
415
414
|
if (typeof num === 'number') {
|
|
416
415
|
return `${num}px`;
|
|
417
416
|
}
|
|
418
417
|
return num;
|
|
419
418
|
}
|
|
420
419
|
}
|
|
420
|
+
<template>
|
|
421
|
+
<view
|
|
422
|
+
class="uni-forms-item"
|
|
423
|
+
:class="[
|
|
424
|
+
'is-direction-' + localLabelPos,
|
|
425
|
+
border ? 'uni-forms-item--border' : '',
|
|
426
|
+
border && isFirstBorder ? 'is-first-border' : ''
|
|
427
|
+
]"
|
|
428
|
+
>
|
|
429
|
+
<slot name="label">
|
|
430
|
+
<view
|
|
431
|
+
class="uni-forms-item__label"
|
|
432
|
+
:class="{ 'no-label': !label && !required }"
|
|
433
|
+
:style="{ width: localLabelWidth, justifyContent: localLabelAlign }"
|
|
434
|
+
>
|
|
435
|
+
<text v-if="required" class="is-required">*</text>
|
|
436
|
+
<text>{{ label }}</text>
|
|
437
|
+
</view>
|
|
438
|
+
</slot>
|
|
439
|
+
<!-- #ifndef APP-NVUE -->
|
|
440
|
+
<view class="uni-forms-item__content">
|
|
441
|
+
<slot></slot>
|
|
442
|
+
<view class="uni-forms-item__error" :class="{ 'msg--active': msg }">
|
|
443
|
+
<text>{{ msg }}</text>
|
|
444
|
+
</view>
|
|
445
|
+
</view>
|
|
446
|
+
<!-- #endif -->
|
|
447
|
+
<!-- #ifdef APP-NVUE -->
|
|
448
|
+
<view class="uni-forms-item__nuve-content">
|
|
449
|
+
<view class="uni-forms-item__content">
|
|
450
|
+
<slot></slot>
|
|
451
|
+
</view>
|
|
452
|
+
<view class="uni-forms-item__error" :class="{ 'msg--active': msg }">
|
|
453
|
+
<text class="error-text">{{ msg }}</text>
|
|
454
|
+
</view>
|
|
455
|
+
</view>
|
|
456
|
+
<!-- #endif -->
|
|
457
|
+
</view>
|
|
458
|
+
</template>
|
|
459
|
+
<script>
|
|
460
|
+
/**
|
|
461
|
+
* uni-fomrs-item 表单子组件
|
|
462
|
+
* @description uni-fomrs-item 表单子组件,提供了基础布局已经校验能力
|
|
463
|
+
* @tutorial https://ext.dcloud.net.cn/plugin?id=2773
|
|
464
|
+
* @property {Boolean} required 是否必填,左边显示红色"*"号
|
|
465
|
+
* @property {String } label 输入框左边的文字提示
|
|
466
|
+
* @property {Number } labelWidth label的宽度,单位px(默认65)
|
|
467
|
+
* @property {String } labelAlign = [left|center|right] label的文字对齐方式(默认left)
|
|
468
|
+
* @value left label 左侧显示
|
|
469
|
+
* @value center label 居中
|
|
470
|
+
* @value right label 右侧对齐
|
|
471
|
+
* @property {String } errorMessage 显示的错误提示内容,如果为空字符串或者false,则不显示错误信息
|
|
472
|
+
* @property {String } name 表单域的属性名,在使用校验规则时必填
|
|
473
|
+
* @property {String } leftIcon 【1.4.0废弃】label左边的图标,限 uni-ui 的图标名称
|
|
474
|
+
* @property {String } iconColor 【1.4.0废弃】左边通过icon配置的图标的颜色(默认#606266)
|
|
475
|
+
* @property {String} validateTrigger = [bind|submit|blur] 【1.4.0废弃】校验触发器方式 默认 submit
|
|
476
|
+
* @value bind 发生变化时触发
|
|
477
|
+
* @value submit 提交时触发
|
|
478
|
+
* @value blur 失去焦点触发
|
|
479
|
+
* @property {String } labelPosition = [top|left] 【1.4.0废弃】label的文字的位置(默认left)
|
|
480
|
+
* @value top 顶部显示 label
|
|
481
|
+
* @value left 左侧显示 label
|
|
482
|
+
*/
|
|
483
|
+
export default {
|
|
484
|
+
name: 'uniFormsItem',
|
|
485
|
+
options: {
|
|
486
|
+
virtualHost: true
|
|
487
|
+
},
|
|
488
|
+
provide() {
|
|
489
|
+
return {
|
|
490
|
+
uniFormItem: this
|
|
491
|
+
};
|
|
492
|
+
},
|
|
493
|
+
inject: {
|
|
494
|
+
form: {
|
|
495
|
+
from: 'uniForm',
|
|
496
|
+
default: null
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
props: {
|
|
500
|
+
// 表单校验规则
|
|
501
|
+
rules: {
|
|
502
|
+
type: Array,
|
|
503
|
+
default() {
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
// 表单域的属性名,在使用校验规则时必填
|
|
508
|
+
name: {
|
|
509
|
+
type: [String, Array],
|
|
510
|
+
default: ''
|
|
511
|
+
},
|
|
512
|
+
required: {
|
|
513
|
+
type: Boolean,
|
|
514
|
+
default: false
|
|
515
|
+
},
|
|
516
|
+
label: {
|
|
517
|
+
type: String,
|
|
518
|
+
default: ''
|
|
519
|
+
},
|
|
520
|
+
// label的宽度 ,默认 80
|
|
521
|
+
labelWidth: {
|
|
522
|
+
type: [String, Number],
|
|
523
|
+
default: ''
|
|
524
|
+
},
|
|
525
|
+
// label 居中方式,默认 left 取值 left/center/right
|
|
526
|
+
labelAlign: {
|
|
527
|
+
type: String,
|
|
528
|
+
default: ''
|
|
529
|
+
},
|
|
530
|
+
// 强制显示错误信息
|
|
531
|
+
errorMessage: {
|
|
532
|
+
type: [String, Boolean],
|
|
533
|
+
default: ''
|
|
534
|
+
},
|
|
535
|
+
// 1.4.0 弃用,统一使用 form 的校验时机
|
|
536
|
+
// validateTrigger: {
|
|
537
|
+
// type: String,
|
|
538
|
+
// default: ''
|
|
539
|
+
// },
|
|
540
|
+
// 1.4.0 弃用,统一使用 form 的label 位置
|
|
541
|
+
// labelPosition: {
|
|
542
|
+
// type: String,
|
|
543
|
+
// default: ''
|
|
544
|
+
// },
|
|
545
|
+
// 1.4.0 以下属性已经废弃,请使用 #label 插槽代替
|
|
546
|
+
leftIcon: String,
|
|
547
|
+
iconColor: {
|
|
548
|
+
type: String,
|
|
549
|
+
default: '#606266'
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
data() {
|
|
553
|
+
return {
|
|
554
|
+
errMsg: '',
|
|
555
|
+
userRules: null,
|
|
556
|
+
localLabelAlign: 'left',
|
|
557
|
+
localLabelWidth: '65px',
|
|
558
|
+
localLabelPos: 'left',
|
|
559
|
+
border: false,
|
|
560
|
+
isFirstBorder: false
|
|
561
|
+
};
|
|
562
|
+
},
|
|
563
|
+
computed: {
|
|
564
|
+
// 处理错误信息
|
|
565
|
+
msg() {
|
|
566
|
+
return this.errorMessage || this.errMsg;
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
watch: {
|
|
570
|
+
// 规则发生变化通知子组件更新
|
|
571
|
+
'form.formRules'(val) {
|
|
572
|
+
// TODO 处理头条vue3 watch不生效的问题
|
|
573
|
+
// #ifndef MP-TOUTIAO
|
|
574
|
+
this.init();
|
|
575
|
+
// #endif
|
|
576
|
+
},
|
|
577
|
+
'form.labelWidth'(val) {
|
|
578
|
+
// 宽度
|
|
579
|
+
this.localLabelWidth = this._labelWidthUnit(val);
|
|
580
|
+
},
|
|
581
|
+
'form.labelPosition'(val) {
|
|
582
|
+
// 标签位置
|
|
583
|
+
this.localLabelPos = this._labelPosition();
|
|
584
|
+
},
|
|
585
|
+
'form.labelAlign'(val) {}
|
|
586
|
+
},
|
|
587
|
+
created() {
|
|
588
|
+
this.init(true);
|
|
589
|
+
if (this.name && this.form) {
|
|
590
|
+
// TODO 处理头条vue3 watch不生效的问题
|
|
591
|
+
// #ifdef MP-TOUTIAO
|
|
592
|
+
this.$watch('form.formRules', () => {
|
|
593
|
+
this.init();
|
|
594
|
+
});
|
|
595
|
+
// #endif
|
|
596
|
+
// 监听变化
|
|
597
|
+
this.$watch(
|
|
598
|
+
() => {
|
|
599
|
+
const val = this.form._getDataValue(this.name, this.form.localData);
|
|
600
|
+
return val;
|
|
601
|
+
},
|
|
602
|
+
(value, oldVal) => {
|
|
603
|
+
const isEqual = this.form._isEqual(value, oldVal);
|
|
604
|
+
// 简单判断前后值的变化,只有发生变化才会发生校验
|
|
605
|
+
// TODO 如果 oldVal = undefined ,那么大概率是源数据里没有值导致 ,这个情况不哦校验 ,可能不严谨 ,需要在做观察
|
|
606
|
+
// fix by mehaotian 暂时取消 && oldVal !== undefined ,如果formData 中不存在,可能会不校验
|
|
607
|
+
if (!isEqual) {
|
|
608
|
+
const val = this.itemSetValue(value);
|
|
609
|
+
this.onFieldChange(val, false);
|
|
610
|
+
}
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
immediate: false
|
|
614
|
+
}
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
},
|
|
618
|
+
// #ifndef VUE3
|
|
619
|
+
destroyed() {
|
|
620
|
+
if (this.__isUnmounted) return;
|
|
621
|
+
this.unInit();
|
|
622
|
+
},
|
|
623
|
+
// #endif
|
|
624
|
+
// #ifdef VUE3
|
|
625
|
+
unmounted() {
|
|
626
|
+
this.__isUnmounted = true;
|
|
627
|
+
this.unInit();
|
|
628
|
+
},
|
|
629
|
+
// #endif
|
|
630
|
+
methods: {
|
|
631
|
+
/**
|
|
632
|
+
* 外部调用方法
|
|
633
|
+
* 设置规则 ,主要用于小程序自定义检验规则
|
|
634
|
+
* @param {Array} rules 规则源数据
|
|
635
|
+
*/
|
|
636
|
+
setRules(rules = null) {
|
|
637
|
+
this.userRules = rules;
|
|
638
|
+
this.init(false);
|
|
639
|
+
},
|
|
640
|
+
// 兼容老版本表单组件
|
|
641
|
+
setValue() {
|
|
642
|
+
// console.log('setValue 方法已经弃用,请使用最新版本的 uni-forms 表单组件以及其他关联组件。');
|
|
643
|
+
},
|
|
644
|
+
/**
|
|
645
|
+
* 外部调用方法
|
|
646
|
+
* 校验数据
|
|
647
|
+
* @param {any} value 需要校验的数据
|
|
648
|
+
* @param {boolean} 是否立即校验
|
|
649
|
+
* @return {Array|null} 校验内容
|
|
650
|
+
*/
|
|
651
|
+
async onFieldChange(value, formtrigger = true) {
|
|
652
|
+
const { formData, localData, errShowType, validateCheck, validateTrigger, _isRequiredField, _realName } = this.form;
|
|
653
|
+
const name = _realName(this.name);
|
|
654
|
+
if (!value) {
|
|
655
|
+
value = this.form.formData[name];
|
|
656
|
+
}
|
|
657
|
+
// fixd by mehaotian 不在校验前清空信息,解决闪屏的问题
|
|
658
|
+
// this.errMsg = '';
|
|
659
|
+
// fix by mehaotian 解决没有检验规则的情况下,抛出错误的问题
|
|
660
|
+
const ruleLen = this.itemRules.rules && this.itemRules.rules.length;
|
|
661
|
+
if (!this.validator || !ruleLen || ruleLen === 0) return;
|
|
662
|
+
// 检验时机
|
|
663
|
+
// let trigger = this.isTrigger(this.itemRules.validateTrigger, this.validateTrigger, validateTrigger);
|
|
664
|
+
const isRequiredField = _isRequiredField(this.itemRules.rules || []);
|
|
665
|
+
let result = null;
|
|
666
|
+
// 只有等于 bind 时 ,才能开启时实校验
|
|
667
|
+
if (validateTrigger === 'bind' || formtrigger) {
|
|
668
|
+
// 校验当前表单项
|
|
669
|
+
result = await this.validator.validateUpdate(
|
|
670
|
+
{
|
|
671
|
+
[name]: value
|
|
672
|
+
},
|
|
673
|
+
formData
|
|
674
|
+
);
|
|
675
|
+
// 判断是否必填,非必填,不填不校验,填写才校验 ,暂时只处理 undefined 和空的情况
|
|
676
|
+
if (!isRequiredField && (value === undefined || value === '')) {
|
|
677
|
+
result = null;
|
|
678
|
+
}
|
|
679
|
+
// 判断错误信息显示类型
|
|
680
|
+
if (result && result.errorMessage) {
|
|
681
|
+
if (errShowType === 'undertext') {
|
|
682
|
+
// 获取错误信息
|
|
683
|
+
this.errMsg = !result ? '' : result.errorMessage;
|
|
684
|
+
}
|
|
685
|
+
if (errShowType === 'toast') {
|
|
686
|
+
uni.showToast({
|
|
687
|
+
title: result.errorMessage || '校验错误',
|
|
688
|
+
icon: 'none'
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
if (errShowType === 'modal') {
|
|
692
|
+
uni.showModal({
|
|
693
|
+
title: '提示',
|
|
694
|
+
content: result.errorMessage || '校验错误'
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
} else {
|
|
698
|
+
this.errMsg = '';
|
|
699
|
+
}
|
|
700
|
+
// 通知 form 组件更新事件
|
|
701
|
+
validateCheck(result ? result : null);
|
|
702
|
+
} else {
|
|
703
|
+
this.errMsg = '';
|
|
704
|
+
}
|
|
705
|
+
return result ? result : null;
|
|
706
|
+
},
|
|
707
|
+
/**
|
|
708
|
+
* 初始组件数据
|
|
709
|
+
*/
|
|
710
|
+
init(type = false) {
|
|
711
|
+
const { validator, formRules, childrens, formData, localData, _realName, labelWidth, _getDataValue, _setDataValue } =
|
|
712
|
+
this.form || {};
|
|
713
|
+
// 对齐方式
|
|
714
|
+
this.localLabelAlign = this._justifyContent();
|
|
715
|
+
// 宽度
|
|
716
|
+
this.localLabelWidth = this._labelWidthUnit(labelWidth);
|
|
717
|
+
// 标签位置
|
|
718
|
+
this.localLabelPos = this._labelPosition();
|
|
719
|
+
// 将需要校验的子组件加入form 队列
|
|
720
|
+
this.form && type && childrens.push(this);
|
|
721
|
+
if (!validator || !formRules) return;
|
|
722
|
+
// 判断第一个 item
|
|
723
|
+
if (!this.form.isFirstBorder) {
|
|
724
|
+
this.form.isFirstBorder = true;
|
|
725
|
+
this.isFirstBorder = true;
|
|
726
|
+
}
|
|
727
|
+
// 判断 group 里的第一个 item
|
|
728
|
+
if (this.group) {
|
|
729
|
+
if (!this.group.isFirstBorder) {
|
|
730
|
+
this.group.isFirstBorder = true;
|
|
731
|
+
this.isFirstBorder = true;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
this.border = this.form.border;
|
|
735
|
+
// 获取子域的真实名称
|
|
736
|
+
const name = _realName(this.name);
|
|
737
|
+
const itemRule = this.userRules || this.rules;
|
|
738
|
+
if (typeof formRules === 'object' && itemRule) {
|
|
739
|
+
// 子规则替换父规则
|
|
740
|
+
formRules[name] = {
|
|
741
|
+
rules: itemRule
|
|
742
|
+
};
|
|
743
|
+
validator.updateSchema(formRules);
|
|
744
|
+
}
|
|
745
|
+
// 注册校验规则
|
|
746
|
+
const itemRules = formRules[name] || {};
|
|
747
|
+
this.itemRules = itemRules;
|
|
748
|
+
// 注册校验函数
|
|
749
|
+
this.validator = validator;
|
|
750
|
+
// 默认值赋予
|
|
751
|
+
this.itemSetValue(_getDataValue(this.name, localData));
|
|
752
|
+
},
|
|
753
|
+
unInit() {
|
|
754
|
+
if (this.form) {
|
|
755
|
+
const { childrens, formData, _realName } = this.form;
|
|
756
|
+
childrens.forEach((item, index) => {
|
|
757
|
+
if (item === this) {
|
|
758
|
+
this.form.childrens.splice(index, 1);
|
|
759
|
+
delete formData[_realName(item.name)];
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
},
|
|
764
|
+
// 设置item 的值
|
|
765
|
+
itemSetValue(value) {
|
|
766
|
+
const name = this.form._realName(this.name);
|
|
767
|
+
const rules = this.itemRules.rules || [];
|
|
768
|
+
const val = this.form._getValue(name, value, rules);
|
|
769
|
+
this.form._setDataValue(name, this.form.formData, val);
|
|
770
|
+
return val;
|
|
771
|
+
},
|
|
772
|
+
/**
|
|
773
|
+
* 移除该表单项的校验结果
|
|
774
|
+
*/
|
|
775
|
+
clearValidate() {
|
|
776
|
+
this.errMsg = '';
|
|
777
|
+
},
|
|
778
|
+
// 是否显示星号
|
|
779
|
+
_isRequired() {
|
|
780
|
+
// TODO 不根据规则显示 星号,考虑后续兼容
|
|
781
|
+
// if (this.form) {
|
|
782
|
+
// if (this.form._isRequiredField(this.itemRules.rules || []) && this.required) {
|
|
783
|
+
// return true
|
|
784
|
+
// }
|
|
785
|
+
// return false
|
|
786
|
+
// }
|
|
787
|
+
return this.required;
|
|
788
|
+
},
|
|
789
|
+
// 处理对齐方式
|
|
790
|
+
_justifyContent() {
|
|
791
|
+
if (this.form) {
|
|
792
|
+
const { labelAlign } = this.form;
|
|
793
|
+
let labelAli = this.labelAlign ? this.labelAlign : labelAlign;
|
|
794
|
+
if (labelAli === 'left') return 'flex-start';
|
|
795
|
+
if (labelAli === 'center') return 'center';
|
|
796
|
+
if (labelAli === 'right') return 'flex-end';
|
|
797
|
+
}
|
|
798
|
+
return 'flex-start';
|
|
799
|
+
},
|
|
800
|
+
// 处理 label宽度单位 ,继承父元素的值
|
|
801
|
+
_labelWidthUnit(labelWidth) {
|
|
802
|
+
// if (this.form) {
|
|
803
|
+
// const {
|
|
804
|
+
// labelWidth
|
|
805
|
+
// } = this.form
|
|
806
|
+
return this.num2px(this.labelWidth ? this.labelWidth : labelWidth || (this.label ? 65 : 'auto'));
|
|
807
|
+
// }
|
|
808
|
+
// return '65px'
|
|
809
|
+
},
|
|
810
|
+
// 处理 label 位置
|
|
811
|
+
_labelPosition() {
|
|
812
|
+
if (this.form) return this.form.labelPosition || 'left';
|
|
813
|
+
return 'left';
|
|
814
|
+
},
|
|
815
|
+
/**
|
|
816
|
+
* 触发时机
|
|
817
|
+
* @param {Object} rule 当前规则内时机
|
|
818
|
+
* @param {Object} itemRlue 当前组件时机
|
|
819
|
+
* @param {Object} parentRule 父组件时机
|
|
820
|
+
*/
|
|
821
|
+
isTrigger(rule, itemRlue, parentRule) {
|
|
822
|
+
// bind submit
|
|
823
|
+
if (rule === 'submit' || !rule) {
|
|
824
|
+
if (rule === undefined) {
|
|
825
|
+
if (itemRlue !== 'bind') {
|
|
826
|
+
if (!itemRlue) {
|
|
827
|
+
return parentRule === '' ? 'bind' : 'submit';
|
|
828
|
+
}
|
|
829
|
+
return 'submit';
|
|
830
|
+
}
|
|
831
|
+
return 'bind';
|
|
832
|
+
}
|
|
833
|
+
return 'submit';
|
|
834
|
+
}
|
|
835
|
+
return 'bind';
|
|
836
|
+
},
|
|
837
|
+
num2px(num) {
|
|
838
|
+
if (typeof num === 'number') {
|
|
839
|
+
return `${num}px`;
|
|
840
|
+
}
|
|
841
|
+
return num;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
</script>
|
|
846
|
+
<style>
|
|
847
|
+
@import 'style.css';
|
|
848
|
+
</style>
|