WebApp【公共组件库】@前端(For Git Submodule)
Tevin
2023-11-17 a4563d338b4df06d3fe6ca9123dcd1ec9c23a81b
表单体验升级,支持设定错误集,支持错误自动滚动
3 files modified
132 ■■■■ changed files
forms/form/CForm.vue 72 ●●●●● patch | view | raw | blame | history
forms/form/CFormItem.vue 53 ●●●● patch | view | raw | blame | history
forms/form/cForm.scss 7 ●●●●● patch | view | raw | blame | history
forms/form/CForm.vue
@@ -4,12 +4,30 @@
 */
<template>
    <view :class="'c-form-outer ' + (autoScrollToError==='on'?'auto-scroll':'')">
        <form
            class="c-form"
            v-if="autoScrollToError==='off'"
            @submit="evt=>handleSubmit()"
        >
            <slot :formRes="formRes" />
        </form>
        <scroll-view
            class="c-form-scroller"
            v-else-if="autoScrollToError==='on'"
            :scrollY="true"
            :scroll-top="scrollTop"
            :scroll-with-animation="true"
            @scroll="evt => handleScroll(evt)"
        >
    <form
        class="c-form"
        @submit="evt=>handleSubmit()"
    >
        <slot :formRes="formRes" />
    </form>
        </scroll-view>
    </view>
</template>
<script>
@@ -21,6 +39,11 @@
    props: {
        // 表单数据主体
        formData: Object,
        // 是否自动滚动到错误位置,on/off
        autoScrollToError: {
            type: String,
            default: 'off',
        },
        // 表单项变化的回调
        //   回调传参只有单项数据
        onChange: Function,
@@ -35,9 +58,13 @@
                formData: this.formData,
            },
            validators: {},
            scrollTop: '',
        };
    },
    methods: {
        handleScroll(evt) {
            this.scrollTop = evt.target.scrollTop;
        },
        handleSubmit() {
            const checklist = [];
            // 所有项验证
@@ -51,6 +78,9 @@
                for (let validation of validations) {
                    // 第一个不通过项提示
                    if (!validation.passed) {
                        if (this.autoScrollToError === 'on') {
                            this.scrollTop = validation.offset.top;
                        }
                        Taro.showToast({
                            title: validation.msg,
                            icon: 'none',
@@ -64,7 +94,12 @@
                this.onFinish && this.onFinish();
            });
        },
        preCheckValidators(keys, callback) {
        // 手工提交
        $submit() {
            this.handleSubmit();
        },
        // 提前验证指定项
        $preVerify(keys, callback) {
            const checklist = [];
            // 从选定的项中验证
            keys.forEach(key => {
@@ -77,6 +112,9 @@
                for (let validation of validations) {
                    // 第一个不通过项提示
                    if (!validation.passed) {
                        if (this.autoScrollToError === 'on') {
                            this.scrollTop = validation.offset.top;
                        }
                        Taro.showToast({
                            title: validation.msg,
                            icon: 'none',
@@ -92,11 +130,33 @@
                callback && callback(true);
            });
        },
        $submit() {
            this.handleSubmit();
        },
        $preVerify(keys, callback) {
            this.preCheckValidators(keys, callback);
        // 直接设定错误
        $setErrors(errors) {
            const checklist = [];
            errors.forEach(errorItem => {
                if (typeof this.validators[errorItem.key] !== 'undefined') {
                    checklist.push(
                        this.validators[errorItem.key]('setError', errorItem.msg)
                    );
                }
            });
            Promise.all(checklist).then(validations => {
                for (let validation of validations) {
                    // 第一个不通过项提示
                    if (!validation.passed) {
                        if (this.autoScrollToError === 'on') {
                            this.scrollTop = validation.offset.top;
                        }
                        Taro.showToast({
                            title: validation.msg,
                            icon: 'none',
                            mask: false,
                            duration: 2000,
                        });
                        return;
                    }
                }
            });
        },
    },
    mounted() {
forms/form/CFormItem.vue
@@ -5,13 +5,17 @@
 */
<template>
    <view class="c-form-item">
    <view
        class="c-form-item"
        ref="formItem"
    >
        <slot :itemRes="itemRes" />
    </view>
</template>
<script>
import Schema from 'async-validator';
import { $ } from '@tarojs/extend';
import { validateMsgs } from './validateMsgs.js';
export default {
@@ -109,15 +113,33 @@
    mounted() {
        this.$nextTick(() => {
            // 注册验证
            this.formRes.$regItemValidator(this.name, validateType => {
            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,
                                });
                            });
                    });
                }
                // 未设置验证
                if (!this.required && !this.rules) {
                else if (!this.required && !this.rules) {
                    this.error = false;
                    return Promise.resolve({
                        name: this.name,
                        passed: true,
                    });
                } else {
                }
                // 正常验证
                else {
                    // 验证规则
                    const descriptor = this.rules || [];
                    if (this.required) {
@@ -130,36 +152,39 @@
                    });
                    // 汉化通用验证消息
                    validator.messages(validateMsgs);
                    return validator
                    return new Promise((resolve, reject) => {
                        validator
                        .validate({
                            [this.name]: this.formRes.formData[this.name],
                        })
                        .then(
                            res => {
                                this.error = false;
                                return {
                                    resolve({
                                    name: this.name,
                                    passed: true,
                                };
                                    });
                            },
                            ({ errors, fields }) => {
                                if (validateType !== 'msgOnly') {
                                    this.error = true;
                                    clearTimeout(this.errTimer);
                                    this.errTimer = setTimeout(() => {
                                        this.error = false;
                                    }, 5000);
                                        this.$setError();
                                }
                                return {
                                    $(this.$refs.formItem)
                                        .offset()
                                        .then(offset => {
                                            resolve({
                                    name: this.name,
                                    passed: false,
                                    msg: errors[0].message.replace(
                                        this.name,
                                        this.label || this.name
                                    ),
                                };
                                                offset,
                                            });
                                        });
                            }
                        );
                    });
                }
            });
        });
forms/form/cForm.scss
@@ -5,6 +5,13 @@
@import "../../common/sassMixin";
.c-form-outer.auto-scroll {
    height: 100%;
    .c-form-scroller {
        height: 100%;
    }
}
.c-form {
    display: block;
    width: 100%;