@10yun/cv-mobile-ui 0.5.20 → 0.5.21

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.
Files changed (69) hide show
  1. package/package.json +1 -1
  2. package/ui-cv/components/cv-grid-item/cv-grid-item.vue +1 -1
  3. package/uni-ui/lib/uni-badge/uni-badge.vue +150 -1
  4. package/uni-ui/lib/uni-breadcrumb/uni-breadcrumb.vue +37 -1
  5. package/uni-ui/lib/uni-breadcrumb-item/uni-breadcrumb-item.vue +83 -1
  6. package/uni-ui/lib/uni-calendar/uni-calendar-item.vue +122 -1
  7. package/uni-ui/lib/uni-calendar/uni-calendar.vue +366 -1
  8. package/uni-ui/lib/uni-card/uni-card.vue +124 -1
  9. package/uni-ui/lib/uni-col/uni-col.vue +1 -1
  10. package/uni-ui/lib/uni-collapse/uni-collapse.vue +135 -1
  11. package/uni-ui/lib/uni-collapse-item/uni-collapse-item.vue +266 -1
  12. package/uni-ui/lib/uni-combox/uni-combox.vue +1 -1
  13. package/uni-ui/lib/uni-countdown/uni-countdown.vue +239 -1
  14. package/uni-ui/lib/uni-data-checkbox/uni-data-checkbox.vue +487 -1
  15. package/uni-ui/lib/uni-data-picker/uni-data-picker.vue +530 -1
  16. package/uni-ui/lib/uni-data-pickerview/uni-data-picker.js +157 -150
  17. package/uni-ui/lib/uni-data-pickerview/uni-data-pickerview.vue +166 -1
  18. package/uni-ui/lib/uni-data-select/uni-data-select.vue +289 -1
  19. package/uni-ui/lib/uni-datetime-picker/calendar-item.vue +70 -1
  20. package/uni-ui/lib/uni-datetime-picker/calendar.vue +629 -1
  21. package/uni-ui/lib/uni-datetime-picker/time-picker.vue +741 -1
  22. package/uni-ui/lib/uni-datetime-picker/uni-datetime-picker.vue +847 -1
  23. package/uni-ui/lib/uni-drawer/uni-drawer.vue +115 -1
  24. package/uni-ui/lib/uni-easyinput/uni-easyinput.vue +515 -1
  25. package/uni-ui/lib/uni-fab/uni-fab.vue +257 -1
  26. package/uni-ui/lib/uni-fav/uni-fav.vue +123 -1
  27. package/uni-ui/lib/uni-file-picker/uni-file-picker.vue +642 -1
  28. package/uni-ui/lib/uni-file-picker/upload-file.vue +177 -1
  29. package/uni-ui/lib/uni-file-picker/upload-image.vue +176 -1
  30. package/uni-ui/lib/uni-forms/uni-forms.vue +375 -1
  31. package/uni-ui/lib/uni-forms-item/uni-forms-item.vue +429 -1
  32. package/uni-ui/lib/uni-goods-nav/uni-goods-nav.vue +129 -1
  33. package/uni-ui/lib/uni-grid/uni-grid.vue +115 -1
  34. package/uni-ui/lib/uni-grid-item/uni-grid-item.vue +78 -1
  35. package/uni-ui/lib/uni-group/uni-group.vue +85 -1
  36. package/uni-ui/lib/uni-icons/uni-icons.vue +85 -1
  37. package/uni-ui/lib/uni-indexed-list/uni-indexed-list-item.vue +68 -1
  38. package/uni-ui/lib/uni-indexed-list/uni-indexed-list.vue +294 -1
  39. package/uni-ui/lib/uni-list/uni-list.vue +81 -1
  40. package/uni-ui/lib/uni-list-ad/uni-list-ad.vue +77 -1
  41. package/uni-ui/lib/uni-list-chat/uni-list-chat.vue +294 -1
  42. package/uni-ui/lib/uni-list-item/uni-list-item.vue +346 -1
  43. package/uni-ui/lib/uni-load-more/uni-load-more.vue +172 -1
  44. package/uni-ui/lib/uni-nav-bar/uni-nav-bar.vue +205 -1
  45. package/uni-ui/lib/uni-nav-bar/uni-status-bar.vue +18 -1
  46. package/uni-ui/lib/uni-notice-bar/uni-notice-bar.vue +331 -1
  47. package/uni-ui/lib/uni-number-box/uni-number-box.vue +166 -1
  48. package/uni-ui/lib/uni-pagination/uni-pagination.vue +323 -1
  49. package/uni-ui/lib/uni-popup/uni-popup.vue +1 -1
  50. package/uni-ui/lib/uni-popup-dialog/uni-popup-dialog.vue +173 -1
  51. package/uni-ui/lib/uni-popup-message/uni-popup-message.vue +74 -1
  52. package/uni-ui/lib/uni-popup-share/uni-popup-share.vue +106 -1
  53. package/uni-ui/lib/uni-rate/uni-rate.vue +322 -1
  54. package/uni-ui/lib/uni-row/uni-row.vue +1 -1
  55. package/uni-ui/lib/uni-search-bar/uni-search-bar.vue +236 -1
  56. package/uni-ui/lib/uni-section/uni-section.vue +109 -1
  57. package/uni-ui/lib/uni-segmented-control/uni-segmented-control.vue +103 -1
  58. package/uni-ui/lib/uni-status-bar/uni-status-bar.vue +1 -1
  59. package/uni-ui/lib/uni-steps/uni-steps.vue +120 -1
  60. package/uni-ui/lib/uni-swipe-action-item/uni-swipe-action-item.vue +226 -3
  61. package/uni-ui/lib/uni-swiper-dot/uni-swiper-dot.vue +167 -1
  62. package/uni-ui/lib/uni-table/uni-table.vue +297 -1
  63. package/uni-ui/lib/uni-tag/uni-tag.vue +100 -1
  64. package/uni-ui/lib/uni-td/uni-td.vue +78 -1
  65. package/uni-ui/lib/uni-th/filter-dropdown.vue +1 -1
  66. package/uni-ui/lib/uni-th/uni-th.vue +224 -1
  67. package/uni-ui/lib/uni-thead/uni-thead.vue +77 -1
  68. package/uni-ui/lib/uni-tr/table-checkbox.vue +79 -1
  69. package/uni-ui/lib/uni-tr/uni-tr.vue +135 -1
@@ -1 +1,375 @@
1
- <template>
2
1
  <view class="uni-forms">
3
2
  <form>
4
3
  <slot></slot>
5
4
  </form>
6
5
  </view>
7
6
  deepCopy,
8
7
  getValue,
9
8
  isRequiredField,
10
9
  setDataValue,
11
10
  getDataValue,
12
11
  realName,
13
12
  isRealName,
14
13
  rawData,
15
14
  isEqual
16
15
  if (formName) {
17
16
  this.$refs[formName].setValue(name, value);
18
17
  } else {
19
18
  let formVm;
20
19
  for (let i in this.$refs) {
21
20
  const vm = this.$refs[i];
22
21
  if (vm && vm.$options && vm.$options.name === 'uniForms') {
23
22
  formVm = vm;
24
23
  break;
25
24
  }
26
25
  }
27
26
  if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
28
27
  formVm.setValue(name, value);
29
28
  }
30
29
  * Forms 表单
31
30
  * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据
32
31
  * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
33
32
  * @property {Object} rules 表单校验规则
34
33
  * @property {String} validateTrigger = [bind|submit|blur] 校验触发器方式 默认 submit
35
34
  * @value bind 发生变化时触发
36
35
  * @value submit 提交时触发
37
36
  * @value blur 失去焦点时触发
38
37
  * @property {String} labelPosition = [top|left] label 位置 默认 left
39
38
  * @value top 顶部显示 label
40
39
  * @value left 左侧显示 label
41
40
  * @property {String} labelWidth label 宽度,默认 65px
42
41
  * @property {String} labelAlign = [left|center|right] label 居中方式 默认 left
43
42
  * @value left label 左侧显示
44
43
  * @value center label 居中
45
44
  * @value right label 右侧对齐
46
45
  * @property {String} errShowType = [undertext|toast|modal] 校验错误信息提示方式
47
46
  * @value undertext 错误信息在底部显示
48
47
  * @value toast 错误信息toast显示
49
48
  * @value modal 错误信息modal显示
50
49
  * @event {Function} submit 提交时触发
51
50
  * @event {Function} validate 校验结果发生变化触发
52
51
  */
53
52
  name: 'uniForms',
54
53
  emits: ['validate', 'submit'],
55
54
  options: {
56
55
  virtualHost: true
57
56
  },
58
57
  props: {
59
58
  // 即将弃用
60
59
  value: {
61
60
  type: Object,
62
61
  default() {
63
62
  return null;
64
63
  }
65
64
  },
66
65
  // vue3 替换 value 属性
67
66
  modelValue: {
68
67
  type: Object,
69
68
  default() {
70
69
  return null;
71
70
  }
72
71
  },
73
72
  // 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValue
74
73
  model: {
75
74
  type: Object,
76
75
  default() {
77
76
  return null;
78
77
  }
79
78
  },
80
79
  // 表单校验规则
81
80
  rules: {
82
81
  type: Object,
83
82
  default() {
84
83
  return {};
85
84
  }
86
85
  },
87
86
  //校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal]
88
87
  errShowType: {
89
88
  type: String,
90
89
  default: 'undertext'
91
90
  },
92
91
  // 校验触发器方式 默认 bind 取值 [bind|submit]
93
92
  validateTrigger: {
94
93
  type: String,
95
94
  default: 'submit'
96
95
  },
97
96
  // label 位置,默认 left 取值 top/left
98
97
  labelPosition: {
99
98
  type: String,
100
99
  default: 'left'
101
100
  },
102
101
  // label 宽度
103
102
  labelWidth: {
104
103
  type: [String, Number],
105
104
  default: ''
106
105
  },
107
106
  // label 居中方式,默认 left 取值 left/center/right
108
107
  labelAlign: {
109
108
  type: String,
110
109
  default: 'left'
111
110
  },
112
111
  border: {
113
112
  type: Boolean,
114
113
  default: false
115
114
  }
116
115
  },
117
116
  provide() {
118
117
  return {
119
118
  uniForm: this
120
119
  };
121
120
  },
122
121
  data() {
123
122
  return {
124
123
  // 表单本地值的记录,不应该与传如的值进行关联
125
124
  formData: {},
126
125
  formRules: {}
127
126
  };
128
127
  },
129
128
  computed: {
130
129
  // 计算数据源变化的
131
130
  localData() {
132
131
  const localVal = this.model || this.modelValue || this.value;
133
132
  if (localVal) {
134
133
  return deepCopy(localVal);
135
134
  }
136
135
  return {};
137
136
  }
138
137
  },
139
138
  watch: {
140
139
  // 监听数据变化 ,暂时不使用,需要单独赋值
141
140
  // localData: {},
142
141
  // 监听规则变化
143
142
  rules: {
144
143
  handler: function (val, oldVal) {
145
144
  this.setRules(val);
146
145
  },
147
146
  deep: true,
148
147
  immediate: true
149
148
  }
150
149
  },
151
150
  created() {
152
151
  // #ifdef VUE3
153
152
  let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddata;
154
153
  if (!getbinddata) {
155
154
  getApp().$vm.$.appContext.config.globalProperties.binddata = function (name, value, formName) {
156
155
  if (formName) {
157
156
  this.$refs[formName].setValue(name, value);
158
157
  } else {
159
158
  let formVm;
160
159
  for (let i in this.$refs) {
161
160
  const vm = this.$refs[i];
162
161
  if (vm && vm.$options && vm.$options.name === 'uniForms') {
163
162
  formVm = vm;
164
163
  break;
165
164
  }
166
165
  }
167
166
  if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
168
167
  formVm.setValue(name, value);
169
168
  }
170
169
  };
171
170
  }
172
171
  // #endif
173
172
  // 子组件实例数组
174
173
  this.childrens = [];
175
174
  // TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错
176
175
  this.inputChildrens = [];
177
176
  this.setRules(this.rules);
178
177
  },
179
178
  methods: {
180
179
  /**
181
180
  * 外部调用方法
182
181
  * 设置规则 ,主要用于小程序自定义检验规则
183
182
  * @param {Array} rules 规则源数据
184
183
  */
185
184
  setRules(rules) {
186
185
  // TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖
187
186
  this.formRules = Object.assign({}, this.formRules, rules);
188
187
  // 初始化校验函数
189
188
  this.validator = new Validator(rules);
190
189
  },
191
190
  /**
192
191
  * 外部调用方法
193
192
  * 设置数据,用于设置表单数据,公开给用户使用 , 不支持在动态表单中使用
194
193
  * @param {Object} key
195
194
  * @param {Object} value
196
195
  */
197
196
  setValue(key, value) {
198
197
  let example = this.childrens.find((child) => child.name === key);
199
198
  if (!example) return null;
200
199
  this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || []);
201
200
  return example.onFieldChange(this.formData[key]);
202
201
  },
203
202
  /**
204
203
  * 外部调用方法
205
204
  * 手动提交校验表单
206
205
  * 对整个表单进行校验的方法,参数为一个回调函数。
207
206
  * @param {Array} keepitem 保留不参与校验的字段
208
207
  * @param {type} callback 方法回调
209
208
  */
210
209
  validate(keepitem, callback) {
211
210
  return this.checkAll(this.formData, keepitem, callback);
212
211
  },
213
212
  /**
214
213
  * 外部调用方法
215
214
  * 部分表单校验
216
215
  * @param {Array|String} props 需要校验的字段
217
216
  * @param {Function} 回调函数
218
217
  */
219
218
  validateField(props = [], callback) {
220
219
  props = [].concat(props);
221
220
  let invalidFields = {};
222
221
  this.childrens.forEach((item) => {
223
222
  const name = realName(item.name);
224
223
  if (props.indexOf(name) !== -1) {
225
224
  invalidFields = Object.assign({}, invalidFields, {
226
225
  [name]: this.formData[name]
227
226
  });
228
227
  }
229
228
  });
230
229
  return this.checkAll(invalidFields, [], callback);
231
230
  },
232
231
  /**
233
232
  * 外部调用方法
234
233
  * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
235
234
  * @param {Array|String} props 需要移除校验的字段 ,不填为所有
236
235
  */
237
236
  clearValidate(props = []) {
238
237
  props = [].concat(props);
239
238
  this.childrens.forEach((item) => {
240
239
  if (props.length === 0) {
241
240
  item.errMsg = '';
242
241
  } else {
243
242
  const name = realName(item.name);
244
243
  if (props.indexOf(name) !== -1) {
245
244
  item.errMsg = '';
246
245
  }
247
246
  }
248
247
  });
249
248
  },
250
249
  /**
251
250
  * 外部调用方法 ,即将废弃
252
251
  * 手动提交校验表单
253
252
  * 对整个表单进行校验的方法,参数为一个回调函数。
254
253
  * @param {Array} keepitem 保留不参与校验的字段
255
254
  * @param {type} callback 方法回调
256
255
  */
257
256
  submit(keepitem, callback, type) {
258
257
  for (let i in this.dataValue) {
259
258
  const itemData = this.childrens.find((v) => v.name === i);
260
259
  if (itemData) {
261
260
  if (this.formData[i] === undefined) {
262
261
  this.formData[i] = this._getValue(i, this.dataValue[i]);
263
262
  }
264
263
  }
265
264
  }
266
265
  if (!type) {
267
266
  console.warn('submit 方法即将废弃,请使用validate方法代替!');
268
267
  }
269
268
  return this.checkAll(this.formData, keepitem, callback, 'submit');
270
269
  },
271
270
  // 校验所有
272
271
  async checkAll(invalidFields, keepitem, callback, type) {
273
272
  // 不存在校验规则 ,则停止校验流程
274
273
  if (!this.validator) return;
275
274
  let childrens = [];
276
275
  // 处理参与校验的item实例
277
276
  for (let i in invalidFields) {
278
277
  const item = this.childrens.find((v) => realName(v.name) === i);
279
278
  if (item) {
280
279
  childrens.push(item);
281
280
  }
282
281
  }
283
282
  // 如果validate第一个参数是funciont ,那就走回调
284
283
  if (!callback && typeof keepitem === 'function') {
285
284
  callback = keepitem;
286
285
  }
287
286
  let promise;
288
287
  // 如果不存在回调,那么使用 Promise 方式返回
289
288
  if (!callback && typeof callback !== 'function' && Promise) {
290
289
  promise = new Promise((resolve, reject) => {
291
290
  callback = function (valid, invalidFields) {
292
291
  !valid ? resolve(invalidFields) : reject(valid);
293
292
  };
294
293
  });
295
294
  }
296
295
  let results = [];
297
296
  // 避免引用错乱 ,建议拷贝对象处理
298
297
  let tempFormData = JSON.parse(JSON.stringify(invalidFields));
299
298
  // 所有子组件参与校验,使用 for 可以使用 awiat
300
299
  for (let i in childrens) {
301
300
  const child = childrens[i];
302
301
  let name = realName(child.name);
303
302
  const result = await child.onFieldChange(tempFormData[name]);
304
303
  if (result) {
305
304
  results.push(result);
306
305
  // toast ,modal 只需要执行第一次就可以
307
306
  if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
308
307
  }
309
308
  }
310
309
  if (Array.isArray(results)) {
311
310
  if (results.length === 0) results = null;
312
311
  }
313
312
  if (Array.isArray(keepitem)) {
314
313
  keepitem.forEach((v) => {
315
314
  let vName = realName(v);
316
315
  let value = getDataValue(v, this.localData);
317
316
  if (value !== undefined) {
318
317
  tempFormData[vName] = value;
319
318
  }
320
319
  });
321
320
  }
322
321
  // TODO submit 即将废弃
323
322
  if (type === 'submit') {
324
323
  this.$emit('submit', {
325
324
  detail: {
326
325
  value: tempFormData,
327
326
  errors: results
328
327
  }
329
328
  });
330
329
  } else {
331
330
  this.$emit('validate', results);
332
331
  }
333
332
  // const resetFormData = rawData(tempFormData, this.localData, this.name)
334
333
  let resetFormData = {};
335
334
  resetFormData = rawData(tempFormData, this.name);
336
335
  callback && typeof callback === 'function' && callback(results, resetFormData);
337
336
  if (promise && callback) {
338
337
  return promise;
339
338
  } else {
340
339
  return null;
341
340
  }
342
341
  },
343
342
  /**
344
343
  * 返回validate事件
345
344
  * @param {Object} result
346
345
  */
347
346
  validateCheck(result) {
348
347
  this.$emit('validate', result);
349
348
  },
350
349
  _getValue: getValue,
351
350
  _isRequiredField: isRequiredField,
352
351
  _setDataValue: setDataValue,
353
352
  _getDataValue: getDataValue,
354
353
  _realName: realName,
355
354
  _isRealName: isRealName,
356
355
  _isEqual: isEqual
357
356
  }
357
+ <template>
358
+ <view class="uni-forms">
359
+ <form>
360
+ <slot></slot>
361
+ </form>
362
+ </view>
363
+ </template>
364
+ <script>
365
+ import Validator from './validate.js';
366
+ import {
367
+ deepCopy,
368
+ getValue,
369
+ isRequiredField,
370
+ setDataValue,
371
+ getDataValue,
372
+ realName,
373
+ isRealName,
374
+ rawData,
375
+ isEqual
376
+ } from './utils.js';
377
+ // #ifndef VUE3
378
+ // 后续会慢慢废弃这个方法
379
+ import Vue from 'vue';
380
+ Vue.prototype.binddata = function (name, value, formName) {
381
+ if (formName) {
382
+ this.$refs[formName].setValue(name, value);
383
+ } else {
384
+ let formVm;
385
+ for (let i in this.$refs) {
386
+ const vm = this.$refs[i];
387
+ if (vm && vm.$options && vm.$options.name === 'uniForms') {
388
+ formVm = vm;
389
+ break;
390
+ }
391
+ }
392
+ if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
393
+ formVm.setValue(name, value);
394
+ }
395
+ };
396
+ // #endif
397
+ /**
398
+ * Forms 表单
399
+ * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据
400
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
401
+ * @property {Object} rules 表单校验规则
402
+ * @property {String} validateTrigger = [bind|submit|blur] 校验触发器方式 默认 submit
403
+ * @value bind 发生变化时触发
404
+ * @value submit 提交时触发
405
+ * @value blur 失去焦点时触发
406
+ * @property {String} labelPosition = [top|left] label 位置 默认 left
407
+ * @value top 顶部显示 label
408
+ * @value left 左侧显示 label
409
+ * @property {String} labelWidth label 宽度,默认 65px
410
+ * @property {String} labelAlign = [left|center|right] label 居中方式 默认 left
411
+ * @value left label 左侧显示
412
+ * @value center label 居中
413
+ * @value right label 右侧对齐
414
+ * @property {String} errShowType = [undertext|toast|modal] 校验错误信息提示方式
415
+ * @value undertext 错误信息在底部显示
416
+ * @value toast 错误信息toast显示
417
+ * @value modal 错误信息modal显示
418
+ * @event {Function} submit 提交时触发
419
+ * @event {Function} validate 校验结果发生变化触发
420
+ */
421
+ export default {
422
+ name: 'uniForms',
423
+ emits: ['validate', 'submit'],
424
+ options: {
425
+ virtualHost: true
426
+ },
427
+ props: {
428
+ // 即将弃用
429
+ value: {
430
+ type: Object,
431
+ default() {
432
+ return null;
433
+ }
434
+ },
435
+ // vue3 替换 value 属性
436
+ modelValue: {
437
+ type: Object,
438
+ default() {
439
+ return null;
440
+ }
441
+ },
442
+ // 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValue
443
+ model: {
444
+ type: Object,
445
+ default() {
446
+ return null;
447
+ }
448
+ },
449
+ // 表单校验规则
450
+ rules: {
451
+ type: Object,
452
+ default() {
453
+ return {};
454
+ }
455
+ },
456
+ //校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal]
457
+ errShowType: {
458
+ type: String,
459
+ default: 'undertext'
460
+ },
461
+ // 校验触发器方式 默认 bind 取值 [bind|submit]
462
+ validateTrigger: {
463
+ type: String,
464
+ default: 'submit'
465
+ },
466
+ // label 位置,默认 left 取值 top/left
467
+ labelPosition: {
468
+ type: String,
469
+ default: 'left'
470
+ },
471
+ // label 宽度
472
+ labelWidth: {
473
+ type: [String, Number],
474
+ default: ''
475
+ },
476
+ // label 居中方式,默认 left 取值 left/center/right
477
+ labelAlign: {
478
+ type: String,
479
+ default: 'left'
480
+ },
481
+ border: {
482
+ type: Boolean,
483
+ default: false
484
+ }
485
+ },
486
+ provide() {
487
+ return {
488
+ uniForm: this
489
+ };
490
+ },
491
+ data() {
492
+ return {
493
+ // 表单本地值的记录,不应该与传如的值进行关联
494
+ formData: {},
495
+ formRules: {}
496
+ };
497
+ },
498
+ computed: {
499
+ // 计算数据源变化的
500
+ localData() {
501
+ const localVal = this.model || this.modelValue || this.value;
502
+ if (localVal) {
503
+ return deepCopy(localVal);
504
+ }
505
+ return {};
506
+ }
507
+ },
508
+ watch: {
509
+ // 监听数据变化 ,暂时不使用,需要单独赋值
510
+ // localData: {},
511
+ // 监听规则变化
512
+ rules: {
513
+ handler: function (val, oldVal) {
514
+ this.setRules(val);
515
+ },
516
+ deep: true,
517
+ immediate: true
518
+ }
519
+ },
520
+ created() {
521
+ // #ifdef VUE3
522
+ let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddata;
523
+ if (!getbinddata) {
524
+ getApp().$vm.$.appContext.config.globalProperties.binddata = function (name, value, formName) {
525
+ if (formName) {
526
+ this.$refs[formName].setValue(name, value);
527
+ } else {
528
+ let formVm;
529
+ for (let i in this.$refs) {
530
+ const vm = this.$refs[i];
531
+ if (vm && vm.$options && vm.$options.name === 'uniForms') {
532
+ formVm = vm;
533
+ break;
534
+ }
535
+ }
536
+ if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
537
+ formVm.setValue(name, value);
538
+ }
539
+ };
540
+ }
541
+ // #endif
542
+ // 子组件实例数组
543
+ this.childrens = [];
544
+ // TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错
545
+ this.inputChildrens = [];
546
+ this.setRules(this.rules);
547
+ },
548
+ methods: {
549
+ /**
550
+ * 外部调用方法
551
+ * 设置规则 ,主要用于小程序自定义检验规则
552
+ * @param {Array} rules 规则源数据
553
+ */
554
+ setRules(rules) {
555
+ // TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖
556
+ this.formRules = Object.assign({}, this.formRules, rules);
557
+ // 初始化校验函数
558
+ this.validator = new Validator(rules);
559
+ },
560
+ /**
561
+ * 外部调用方法
562
+ * 设置数据,用于设置表单数据,公开给用户使用 , 不支持在动态表单中使用
563
+ * @param {Object} key
564
+ * @param {Object} value
565
+ */
566
+ setValue(key, value) {
567
+ let example = this.childrens.find((child) => child.name === key);
568
+ if (!example) return null;
569
+ this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || []);
570
+ return example.onFieldChange(this.formData[key]);
571
+ },
572
+ /**
573
+ * 外部调用方法
574
+ * 手动提交校验表单
575
+ * 对整个表单进行校验的方法,参数为一个回调函数。
576
+ * @param {Array} keepitem 保留不参与校验的字段
577
+ * @param {type} callback 方法回调
578
+ */
579
+ validate(keepitem, callback) {
580
+ return this.checkAll(this.formData, keepitem, callback);
581
+ },
582
+ /**
583
+ * 外部调用方法
584
+ * 部分表单校验
585
+ * @param {Array|String} props 需要校验的字段
586
+ * @param {Function} 回调函数
587
+ */
588
+ validateField(props = [], callback) {
589
+ props = [].concat(props);
590
+ let invalidFields = {};
591
+ this.childrens.forEach((item) => {
592
+ const name = realName(item.name);
593
+ if (props.indexOf(name) !== -1) {
594
+ invalidFields = Object.assign({}, invalidFields, {
595
+ [name]: this.formData[name]
596
+ });
597
+ }
598
+ });
599
+ return this.checkAll(invalidFields, [], callback);
600
+ },
601
+ /**
602
+ * 外部调用方法
603
+ * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
604
+ * @param {Array|String} props 需要移除校验的字段 ,不填为所有
605
+ */
606
+ clearValidate(props = []) {
607
+ props = [].concat(props);
608
+ this.childrens.forEach((item) => {
609
+ if (props.length === 0) {
610
+ item.errMsg = '';
611
+ } else {
612
+ const name = realName(item.name);
613
+ if (props.indexOf(name) !== -1) {
614
+ item.errMsg = '';
615
+ }
616
+ }
617
+ });
618
+ },
619
+ /**
620
+ * 外部调用方法 ,即将废弃
621
+ * 手动提交校验表单
622
+ * 对整个表单进行校验的方法,参数为一个回调函数。
623
+ * @param {Array} keepitem 保留不参与校验的字段
624
+ * @param {type} callback 方法回调
625
+ */
626
+ submit(keepitem, callback, type) {
627
+ for (let i in this.dataValue) {
628
+ const itemData = this.childrens.find((v) => v.name === i);
629
+ if (itemData) {
630
+ if (this.formData[i] === undefined) {
631
+ this.formData[i] = this._getValue(i, this.dataValue[i]);
632
+ }
633
+ }
634
+ }
635
+ if (!type) {
636
+ console.warn('submit 方法即将废弃,请使用validate方法代替!');
637
+ }
638
+ return this.checkAll(this.formData, keepitem, callback, 'submit');
639
+ },
640
+ // 校验所有
641
+ async checkAll(invalidFields, keepitem, callback, type) {
642
+ // 不存在校验规则 ,则停止校验流程
643
+ if (!this.validator) return;
644
+ let childrens = [];
645
+ // 处理参与校验的item实例
646
+ for (let i in invalidFields) {
647
+ const item = this.childrens.find((v) => realName(v.name) === i);
648
+ if (item) {
649
+ childrens.push(item);
650
+ }
651
+ }
652
+ // 如果validate第一个参数是funciont ,那就走回调
653
+ if (!callback && typeof keepitem === 'function') {
654
+ callback = keepitem;
655
+ }
656
+ let promise;
657
+ // 如果不存在回调,那么使用 Promise 方式返回
658
+ if (!callback && typeof callback !== 'function' && Promise) {
659
+ promise = new Promise((resolve, reject) => {
660
+ callback = function (valid, invalidFields) {
661
+ !valid ? resolve(invalidFields) : reject(valid);
662
+ };
663
+ });
664
+ }
665
+ let results = [];
666
+ // 避免引用错乱 ,建议拷贝对象处理
667
+ let tempFormData = JSON.parse(JSON.stringify(invalidFields));
668
+ // 所有子组件参与校验,使用 for 可以使用 awiat
669
+ for (let i in childrens) {
670
+ const child = childrens[i];
671
+ let name = realName(child.name);
672
+ const result = await child.onFieldChange(tempFormData[name]);
673
+ if (result) {
674
+ results.push(result);
675
+ // toast ,modal 只需要执行第一次就可以
676
+ if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
677
+ }
678
+ }
679
+ if (Array.isArray(results)) {
680
+ if (results.length === 0) results = null;
681
+ }
682
+ if (Array.isArray(keepitem)) {
683
+ keepitem.forEach((v) => {
684
+ let vName = realName(v);
685
+ let value = getDataValue(v, this.localData);
686
+ if (value !== undefined) {
687
+ tempFormData[vName] = value;
688
+ }
689
+ });
690
+ }
691
+ // TODO submit 即将废弃
692
+ if (type === 'submit') {
693
+ this.$emit('submit', {
694
+ detail: {
695
+ value: tempFormData,
696
+ errors: results
697
+ }
698
+ });
699
+ } else {
700
+ this.$emit('validate', results);
701
+ }
702
+ // const resetFormData = rawData(tempFormData, this.localData, this.name)
703
+ let resetFormData = {};
704
+ resetFormData = rawData(tempFormData, this.name);
705
+ callback && typeof callback === 'function' && callback(results, resetFormData);
706
+ if (promise && callback) {
707
+ return promise;
708
+ } else {
709
+ return null;
710
+ }
711
+ },
712
+ /**
713
+ * 返回validate事件
714
+ * @param {Object} result
715
+ */
716
+ validateCheck(result) {
717
+ this.$emit('validate', result);
718
+ },
719
+ _getValue: getValue,
720
+ _isRequiredField: isRequiredField,
721
+ _setDataValue: setDataValue,
722
+ _getDataValue: getDataValue,
723
+ _realName: realName,
724
+ _isRealName: isRealName,
725
+ _isEqual: isEqual
726
+ }
727
+ };
728
+ </script>
729
+ <style>
730
+ @import 'style.css';
731
+ </style>