From 0396d398bea811f5650d04ce5b55a232b4f58b98 Mon Sep 17 00:00:00 2001 From: Tevin <tingquanren@163.com> Date: Thu, 27 Mar 2025 17:07:52 +0800 Subject: [PATCH] 移除 link-rules --- forms/form/CFormItem.vue | 198 +++++++++++++++++++++++++++++++++++-------------- 1 files changed, 140 insertions(+), 58 deletions(-) diff --git a/forms/form/CFormItem.vue b/forms/form/CFormItem.vue index a8e57fc..a47639f 100644 --- a/forms/form/CFormItem.vue +++ b/forms/form/CFormItem.vue @@ -1,40 +1,83 @@ /** - * CFormItem + * CFormItem - 表单套装组件,单项包囊器 * @author Tevin * @tutorial rules see https://github.com/yiminghe/async-validator#type */ <template> - <view class="c-form-item"> - <view class="c-form-item-label"> - <text - class="required" - v-if="required" - >*</text> - <text>{{label || name}}</text> - </view> - <slot - :value="formData[name]" - :onChange="evt=>onChange(evt)" - /> + <view + class="c-form-item" + ref="formItem" + > + <slot :itemRes="itemRes" /> </view> </template> <script> +import { $ } from '@tarojs/extend'; import Schema from 'async-validator'; import { validateMsgs } from './validateMsgs.js'; export default { name: 'CFormItem', props: { + // 表单数据资源(表单组件内部机制专用) + formRes: Object, + // 表单项字段键名 name: String, + // 表单项中文名 label: String, + // 表单项验证规则之是否必填 required: Boolean, + // 表单项验证规则之复合规则 + // 例如:[{type:'string', min: 2, max: 100}] + // 常用项: + // type string 类型,常见有 string、number、boolean、array、object、url、email + // len number string 类型时为字符串长度;number 类型时为确定数字; array 类型时为数组长度 + // max number 必须设置 type:string 类型为字符串最大长度;number 类型时为最大值;array 类型时为数组最大长度 + // min number 必须设置 type:string 类型为字符串最小长度;number 类型时为最小值;array 类型时为数组最小长度 + // pattern RegExp 正则表达式匹配 + // required boolean 是否为必选字段 + // transform (value) => any 将字段值转换成目标值后进行校验 + // message string 错误信息,不设置时会通过模板自动生成 rules: Array, - formData: Object, + // 表单是否禁用 + disabled: Boolean, }, data() { - return {}; + return { + error: false, + errTimer: -1, + }; + }, + computed: { + itemRes() { + return { + formData: this.formRes.formData, + name: this.name, + label: this.label, + required: this.isRequired, + disabled: this.disabled, + error: this.error, + onChange: evt => this.onChange(evt), + }; + }, + isRequired() { + if (this.required) { + return true; + } else { + if (!this.rules || this.rules.length === 0) { + return false; + } else if (this.rules.length > 0) { + for (let rule of this.rules) { + if (rule.required) { + return true; + } + } + return false; + } + } + }, }, methods: { onChange(evt) { @@ -46,69 +89,108 @@ !hasOwn.call(evt, 'constructor') && !hasOwn.call(evt.constructor.prototype, 'isPrototypeOf') ) { - throw new Error('错误的表单项 onChange 参数类型!(At: ' + this.name + ')'); - return; + throw new Error( + '错误的表单项 onChange 参数类型!(At: ' + this.name + ')' + ); } } // 未改变值不触发 - if (this.formData[this.name] === evt) { + if (this.formRes.formData[this.name] === evt) { return; } - this.formData.$handleChange({ + this.formRes.$handleChange({ [this.name]: evt, }); + }, + $setError() { + this.error = true; + clearTimeout(this.errTimer); + this.errTimer = setTimeout(() => { + this.error = false; + }, 5000); }, }, mounted() { this.$nextTick(() => { - // 未设置验证 - if (!this.required && !this.rules) { - this.formData.$regItemValidator(this.name, () => { + // 注册验证 + this.formRes.$regItemValidator(this.name, (validateType, errMsg) => { + // 直接设定错误 + if (validateType === 'setError') { + this.$setError(); + return new Promise((resolve, reject) => { + $(this.$refs.formItem) + .offset() + .then(offset => { + resolve({ + name: this.name, + passed: false, + msg: errMsg, + offset, + }); + }); + }); + } + // 未设置验证 + else if (!this.required && !this.rules) { + this.error = false; return Promise.resolve({ name: this.name, passed: true, }); - }); - } else { - const descriptor = this.rules || []; - if (this.required) { - descriptor.unshift({ - required: true, + } + // 正常验证 + else { + // 验证规则 + const descriptor = this.rules || []; + if (this.required) { + descriptor.unshift({ + required: true, + }); + } + const validator = new Schema({ + [this.name]: descriptor, + }); + // 汉化通用验证消息 + validator.messages(validateMsgs); + return new Promise((resolve, reject) => { + validator + .validate({ + [this.name]: this.formRes.formData[this.name], + }) + .then( + res => { + this.error = false; + resolve({ + name: this.name, + passed: true, + }); + }, + ({ errors, fields }) => { + if (validateType !== 'msgOnly') { + this.$setError(); + } + $(this.$refs.formItem) + .offset() + .then(offset => { + resolve({ + name: this.name, + passed: false, + msg: errors[0].message.replace( + this.name, + this.label || this.name + ), + offset, + }); + }); + } + ); }); } - const validator = new Schema({ - [this.name]: descriptor, - }); - validator.messages(validateMsgs); // 自定义验证消息 - this.formData.$regItemValidator(this.name, () => { - return validator - .validate({ - [this.name]: this.formData[this.name], - }) - .then( - (res) => { - return { - name: this.name, - passed: true, - }; - }, - ({ errors, fields }) => { - return { - name: this.name, - passed: false, - msg: errors[0].message.replace( - this.name, - this.label || this.name - ), - }; - } - ); - }); - } + }); }); }, beforeDestroy() { - this.formData.$regItemValidator(this.name, null); + this.formRes.$regItemValidator(this.name, null); }, }; </script> \ No newline at end of file -- Gitblit v1.9.1