Przeglądaj źródła

优化表达构建器.

kindring 1 rok temu
rodzic
commit
b9c42840c0
3 zmienionych plików z 648 dodań i 0 usunięć
  1. 266 0
      lib/esm/fieldCheck.js
  2. 364 0
      lib/esm/formVerify.js
  3. 18 0
      lib/esm/index.js

+ 266 - 0
lib/esm/fieldCheck.js

@@ -0,0 +1,266 @@
+"use strict";
+var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
+    if (kind === "m") throw new TypeError("Private method is not writable");
+    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
+    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
+    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
+};
+var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
+    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
+    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
+    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
+};
+var _FieldCheck_ruleItems;
+/**
+ * 表单字段验证库
+ * author:kindring
+ * date:2023/10/08
+ */
+// 在 types 中定义的 enum 在此处使用会导致异常
+/**
+ * 规则匹配结果
+ * @property code_pass 验证通过
+ * @property code_notPass 验证未通过
+ * @property code_notMatch 未匹配到规则
+ */
+var checkCode;
+(function (checkCode) {
+    checkCode[checkCode["code_pass"] = 1] = "code_pass";
+    checkCode[checkCode["code_notPass"] = 2] = "code_notPass";
+    checkCode[checkCode["code_notMatch"] = 3] = "code_notMatch";
+})(checkCode || (checkCode = {}));
+/**
+ * @class FieldCheck
+ * @description 表单字段验证类
+ * @property {Array<ruleItem>} ruleItems 验证规则
+ * @property {function} addRuleItem 添加一条验证规则
+ * @property {function} verify 检查表单是否符合规则
+ * @example
+ * let fieldCheck = new FieldCheck();
+ * fieldCheck.addRuleItem('rule1',['name'],[
+ *    {
+ *    type: 'string',
+ *    minLength: 2,
+ *    maxLength: 10,
+ *    message: '姓名必须为2-10个字符'
+ *    }
+ *    ]);
+ *    fieldCheck.addRuleItem('rule2',['age'],[
+ *    {
+ *    type: 'number',
+ *    min: 18,
+ *    max: 100,
+ *    message: '年龄必须为18-100岁'
+ *    }]);
+ *    let errMsg = fieldCheck.verify({
+ *    name: 'kindring',
+ *    age: 18});
+ *    console.log(errMsg);
+ *    // null
+ *    let errMsg = fieldCheck.verify({
+ *    name: 'kindring',
+ *    age: 17});
+ *    console.log(errMsg);
+ *    // 年龄必须为18-100岁
+ */
+class FieldCheck {
+    constructor(ruleItems) {
+        // 通过
+        this.code_pass = checkCode.code_pass;
+        // 未通过
+        this.code_notPass = checkCode.code_notPass;
+        // 无法匹配到验证规则
+        this.code_notMatch = checkCode.code_notMatch;
+        /**
+         * @type {Array< ruleItem >}
+         */
+        _FieldCheck_ruleItems.set(this, []);
+        this._toString = Object.prototype.toString;
+        __classPrivateFieldSet(this, _FieldCheck_ruleItems, [], "f");
+        if (ruleItems && Array.isArray(ruleItems)) {
+            // 使用 addRuleItem 添加规则
+            for (const ruleItem of ruleItems) {
+                this.addRuleItem(ruleItem.name || "", ruleItem.checkFields, ruleItem.rules);
+            }
+        }
+    }
+    /**
+     * 判断值是否定义
+     * @param v
+     * @returns {boolean}
+     * @private
+     */
+    _isDef(v) {
+        return v !== undefined && v !== null;
+    }
+    /**
+     * 判断是否为空
+     * @param v 要检验的值
+     */
+    _isEmpty(v) {
+        return v === undefined || v === '';
+    }
+    /**
+     * 判断是否为正则
+     * @param v 要检验的值
+     */
+    _isRegExp(v) {
+        return this._toString.call(v) === '[object RegExp]';
+    }
+    /**
+     * 构建验证规则
+     * @param {Array<string | RegExp>} checkFields 需要验证的字段
+     * @param {Array<validatorFunction | checkRule>} ruleArr 验证规则
+     * @returns {ruleItem} 验证规则对象
+     */
+    buildRuleItem(name, checkFields, ruleArr) {
+        //  检测checkFields是否为数组
+        //  检测ruleArr是否为数组
+        if (!Array.isArray(checkFields) || !Array.isArray(ruleArr)) {
+            throw new Error('checkFields or ruleArr is not Array');
+        }
+        //  检测checkFields中的每一项是否为字符串或者正则
+        for (let field of checkFields) {
+            if (typeof field !== 'string' && !this._isRegExp(field)) {
+                throw new Error('checkFields item is not string or RegExp');
+            }
+        }
+        //  检测ruleArr中的每一项是否为函数或者对象
+        for (let rule of ruleArr) {
+            if (typeof rule !== 'function' && typeof rule !== 'object') {
+                throw new Error('ruleArr item is not function or object');
+            }
+        }
+        let ruleItem = {
+            name: name || "",
+            checkFields: checkFields,
+            rules: ruleArr
+        };
+        // this.ruleItems = this.ruleItems.push(ruleItem);
+        return ruleItem;
+    }
+    /**
+     * 添加一条验证规则
+     * @param ruleName 验证规则名,用于区分
+     * @param checkFields 用于匹配字段的字符或者正则数组
+     * @param ruleArr 验证规则
+     * @returns  返回当前对象
+     */
+    addRuleItem(ruleName, checkFields, ruleArr) {
+        let ruleItem = this.buildRuleItem(ruleName, checkFields, ruleArr);
+        __classPrivateFieldGet(this, _FieldCheck_ruleItems, "f").push(ruleItem);
+        return this;
+    }
+    /**
+     * 获取验证规则
+     * @param field 字段名
+     * @returns 验证规则
+     */
+    getRuleItem(field) {
+        return __classPrivateFieldGet(this, _FieldCheck_ruleItems, "f").find(item => {
+            // 判断是否为正则
+            for (const _matchKey of item.checkFields) {
+                // 判断是否为正则
+                if (this._isRegExp(_matchKey)) {
+                    // 确定为正则
+                    let reg = _matchKey;
+                    // console.log(`使用正则进行匹配,${_matchKey.test(key)}`);
+                    if (reg.test(field)) {
+                        // console.log(`通过正则匹配规则成功,${_matchKey.test(key)}`);
+                        return true;
+                    }
+                }
+                else {
+                    // console.log(`比较是否全等,${_matchKey} === ${key} ?${_matchKey === key}`);
+                    if (_matchKey === field) {
+                        // console.log(`通过字符${_matchKey}匹配成功`);
+                        return true;
+                    }
+                }
+            }
+            return false;
+        });
+    }
+    /**
+     * 检查字段是否符合规则
+     * @param field 字段名
+     * @param value 字段值
+     * @returns {Array<checkCode | ?errMessage>} 错误码或错误信息
+     */
+    checkField(field, value) {
+        let ruleItem = this.getRuleItem(field);
+        if (!ruleItem || !ruleItem.rules) {
+            return [this.code_notMatch];
+        }
+        // 判断值是否为undefined
+        if (value === undefined) {
+            return [this.code_notPass, '字段值为undefined'];
+        }
+        // 开始匹配规则
+        for (let _rule of ruleItem.rules) {
+            // 判断是否有自定义验证函数
+            if (typeof _rule === 'function') {
+                let _msg = _rule(value);
+                // console.log(_msg)
+                if (_msg) {
+                    return [this.code_notPass, _msg];
+                }
+            }
+            let rule = _rule;
+            // 判断类型
+            if (rule.type && typeof value !== rule.type) {
+                return [this.code_notPass, rule.message];
+            }
+            // 判断是否为必填项
+            if (rule.require && this._isEmpty(value)) {
+                return [this.code_notPass, rule.message];
+            }
+            // 判断最小值
+            if (rule.min && value < rule.min) {
+                return [this.code_notPass, rule.message];
+            }
+            // 判断最大值
+            if (rule.max && value > rule.max) {
+                return [this.code_notPass, rule.message];
+            }
+            // 判断值是否达到指定长度
+            if (rule.length && value.length && value.length !== rule.length) {
+                return [this.code_notPass, rule.message];
+            }
+            // 判断最小长度
+            if (rule.minLength && value.length && value.length < rule.minLength) {
+                return [this.code_notPass, rule.message];
+            }
+            // 判断最大长度
+            if (rule.maxLength && value.length && value.length > rule.maxLength) {
+                return [this.code_notPass, rule.message];
+            }
+            // 判断是否符合正则
+            if (rule.regex && !rule.regex.test(value)) {
+                return [this.code_notPass, rule.message];
+            }
+        }
+        return [this.code_pass];
+    }
+    /**
+     * 检查表单是否符合规则
+     * @param {verifyForm} formObject 需要检验的表单项 字段:值
+     * @param [isMustMatch] 是否强制要求匹配规则
+     * @returns errMessage 错误码或错误信息
+     */
+    verify(formObject, isMustMatch = false) {
+        for (const _oKey in formObject) {
+            let value = formObject[_oKey];
+            let r = this.checkField(_oKey, value);
+            if (r[0] === this.code_notPass) {
+                return r[1];
+            }
+            else if (isMustMatch && r[0] === this.code_notMatch) {
+                return `字段没有对应匹配项`;
+            }
+        }
+    }
+}
+_FieldCheck_ruleItems = new WeakMap();
+export default FieldCheck;
+//# sourceMappingURL=fieldCheck.js.map

+ 364 - 0
lib/esm/formVerify.js

@@ -0,0 +1,364 @@
+"use strict";
+import FieldCheck from "./fieldCheck";
+// import {formItemData, formObject, formOption, FormVerifyOption} from "./types/formVerify";
+let hasOwnProperty = Object.prototype.hasOwnProperty;
+function hasOwn(obj, key) {
+    return hasOwnProperty.call(obj, key);
+}
+/**
+ * @class FormItem 表单验证类
+ * @description 表单项
+ * @param {formObject} formObject 表单项数据
+ * @param {FieldCheck} [fieldCheck] 字段验证对象
+ * @param {object} [option] 配置项
+ */
+class FormVerify {
+    constructor(formObject, fieldCheck, option) {
+        this.formData = null;
+        this.defaultOption = {
+            isMustMatchRule: false,
+        };
+        this.option = {
+            isMustMatchRule: false,
+        };
+        this.formState_default = 0;
+        this.formState_pass = 1;
+        this.formState_notPass = 2;
+        // onLog函数
+        this.onLog = (msg) => {
+            // 不进行任何操作.
+        };
+        this.fieldCheck = fieldCheck || new FieldCheck();
+        // 合并配置项
+        this.option = Object.assign(this.defaultOption, option);
+        let errMsg;
+        // 拿出其中的每一项来构建对应的表单项
+        for (let key in formObject) {
+            // this.formData[key] = object[key];
+            // 验证表单项是否符合要求,不符合要求则抛出错误
+            errMsg = FormVerify.buildFormItem(formObject, key, formObject[key], this.fieldCheck, this.option.isMustMatchRule);
+            if (errMsg) {
+                throw new Error(`表单项${key}不符合要求,err:${errMsg}`);
+            }
+        }
+        this.formData = formObject;
+    }
+    static isObject(obj) {
+        return obj !== null && typeof obj === 'object';
+    }
+    /**
+     * 检查表单项是否符合要求
+     * @param  object 表单项数据
+     * @param  field 字段名
+     * @param  formItemData 表单项数据
+     * @param  fieldCheck 字段验证对象
+     * @param  isMustMatchRule 表单字段是否必须匹配到验证规则
+     * @returns  errMsg 错误信息
+     */
+    static buildFormItem(object, field, formItemData, fieldCheck, isMustMatchRule) {
+        if (!FormVerify.isObject(formItemData)) {
+            return `form item ${field} must be object`;
+        }
+        // 是否需要从验证规则表中查找对应的验证规则
+        let isNeedMatchRule = true;
+        // 用于匹配的字段
+        let checkFieldStr = field;
+        let disables = formItemData.disables;
+        // 设置默认值
+        formItemData.val = formItemData.val || formItemData.init || '';
+        // 设置默认提示词
+        formItemData.msg = formItemData.msg || '';
+        // 设置默认状态
+        formItemData.state = formItemData.state || FormVerify.formState_default;
+        // 设置默认显示文本
+        formItemData.label = formItemData.label || '';
+        // 判断是否有 options 选项有则判断是否有 init 选项,没有则设置第一个为 init
+        if (formItemData.options) {
+            if (!formItemData.options.length || !formItemData.options[0]) {
+                return `form item ${field} options must be array and has item`;
+            }
+            if (!formItemData.init) {
+                formItemData.init = formItemData.options[0].key;
+            }
+            // 判断 val 与 init 是否存在于 options 中
+            let hasInit = false;
+            for (let i = 0; i < formItemData.options.length; i++) {
+                let option = formItemData.options[i];
+                if (option.key === formItemData.init) {
+                    hasInit = true;
+                }
+                // 判断该options是否为禁用项
+                if (disables && disables.find(item => item === option.key)) {
+                    option.disabled = true;
+                }
+            }
+            if (!hasInit) {
+                return `form item ${field} init value must be in options`;
+            }
+        }
+        // 判断是否有 depend 依赖字段 有依赖字段则依据依赖字段中的 option 中的 checkField 字段进行判断
+        if (formItemData.depend && formItemData.reCheckField) {
+            return `form item ${field} has depend and reCheckField, but depend and reCheckField can not exist at the same time`;
+        }
+        // 判断是否有 depend 依赖字段 有依赖字段则依据依赖字段中的 option 中的 checkField 字段进行判断
+        if (formItemData.depend) {
+            let hasCheckField = false;
+            let dependStr = formItemData.depend;
+            let dependOptions = [];
+            // 判断object 是否为 formObject 并且不为undefined
+            if (!object) {
+                return `form item ${field} depend field ${dependStr} but the field not exist`;
+            }
+            // 设置 object 不为undefined
+            object = object;
+            // 判断依赖字段是否存在
+            if (!object[dependStr]) {
+                return `form item ${field} depend field ${dependStr} but the field not exist`;
+            }
+            // 判断依赖字段的 option 是否存在
+            if (!object[dependStr].options) {
+                return `form item ${field} depend field ${dependStr} has no options`;
+            }
+            // 判断依赖字段的 options 中是否有 checkField 字段
+            dependOptions = object[dependStr].options;
+            for (let i = 0; i < dependOptions.length; i++) {
+                let option = object ? dependOptions[i] : null;
+                if (option === null || option === void 0 ? void 0 : option.checkField) {
+                    hasCheckField = true;
+                    checkFieldStr = option.checkField;
+                    break;
+                }
+            }
+            if (!hasCheckField) {
+                return `form item ${field} depend field ${dependStr} has no checkField`;
+            }
+        }
+        // 判断是否有 reCheckField 有则使用该字段的值进行规则验证
+        if (formItemData.reCheckField) {
+            checkFieldStr = formItemData.reCheckField;
+        }
+        // 判断是否有 rules 规则
+        if (isMustMatchRule) {
+            if (fieldCheck.getRuleItem(checkFieldStr)) {
+                return `form item ${field} has no rules`;
+            }
+        }
+        return '';
+    }
+    /**
+     * 初始化表单项数据
+     * @param { formObject } formObject 表单对象
+     */
+    static initFormItemData(formObject) {
+        let keys = Object.keys(formObject);
+        for (let i = 0; i < keys.length; i++) {
+            let key = keys[i];
+            formObject[key].val = formObject[key].init;
+            formObject[key].msg = '';
+            formObject[key].state = FormVerify.formState_default;
+            formObject[key].showText = '';
+        }
+    }
+    /**
+     * 检查表单项是否符合要求
+     * @param {formObject} form 表单对象
+     * @param isMustMatch 是否必须全部匹配到验证规则
+     * @returns {boolean}
+     */
+    checkForm(form, isMustMatch) {
+        let r = true;
+        let n_checkPass = 0, n_checkTotal = 0;
+        let tmpOption = {};
+        let logStr = '';
+        let logHandle = (_str) => {
+            try {
+                this.onLog(_str);
+            }
+            catch (e) {
+                console.log(_str);
+                console.error(e);
+            }
+        };
+        for (const fieldKey in form) {
+            let formItem = form[fieldKey];
+            logStr = '';
+            let isFailed = false;
+            if (!formItem) {
+                continue;
+            }
+            let depend = form[formItem.depend || ''];
+            let checkField = fieldKey;
+            logHandle(`检测字段:${checkField},值:${formItem.val}`);
+            n_checkTotal++;
+            if (formItem.notCheck) {
+                n_checkPass++;
+                logStr = `项${fieldKey} 不进行检查`;
+                formItem.state = this.formState_pass;
+                formItem.msg = '';
+                logHandle(logStr);
+                continue;
+            }
+            if (formItem.reCheckField) {
+                checkField = formItem.reCheckField;
+            }
+            // 禁用值判断 array
+            if (formItem.disables) {
+                if (formItem.disables.find(item => item === formItem.val)) {
+                    // console.log(`项${fieldKey} 的值为禁用值`)
+                    logStr = `项${fieldKey} 检测到禁用值`;
+                    formItem.msg = '该项内容不合法';
+                    formItem.state = this.formState_notPass;
+                    isFailed = true;
+                    if (logStr)
+                        logHandle(logStr);
+                    // 如果是匹配到禁用字段, 后续的检测不进行
+                    continue;
+                }
+            }
+            // 枚举值判断
+            if (formItem.options) {
+                // 有枚举字段,只判断是否在枚举中
+                // console.log(`检测枚举字段:${checkField},值:${formItem.val}`);
+                tmpOption = formItem.options.find(item => item.value == formItem.val);
+                // tmpInd = formItem.options.findIndex(item=>item.value == formItem.val);
+                if (tmpOption) {
+                    if (tmpOption.disabled) {
+                        logStr = `项${fieldKey} 检测枚举字段:${checkField},值:${formItem.val}被禁用`;
+                        formItem.msg = '该选项已经被禁用';
+                        formItem.state = this.formState_notPass;
+                        isFailed = true;
+                    }
+                    // 检查通过
+                    formItem.state = this.formState_pass;
+                    formItem.msg = '';
+                }
+                else {
+                    logStr = `项${fieldKey} 检测枚举字段:${checkField},值:${formItem.val}不在范围内`;
+                    formItem.msg = '选项不在范围内';
+                    formItem.state = this.formState_notPass;
+                    isFailed = true;
+                }
+                if (logStr)
+                    logHandle(logStr);
+                // 枚举值判断完毕,继续下一个字段
+                n_checkPass++;
+                continue;
+            }
+            // 依赖字段判断
+            if (depend) {
+                depend = depend;
+                if (depend.options) {
+                    // 依赖的对象有枚举类型,检查该枚举类型是否有有检测值
+                    let optionItem = depend.options.find(item => item.value == formItem.val);
+                    if (!optionItem) {
+                        logStr = `检测依赖字段:${depend},但是选项${formItem.val}不在范围内`;
+                        depend.msg = '选项不在范围内';
+                        formItem.msg = '该值依赖项输入异常';
+                        isFailed = true;
+                        // continue;
+                    }
+                    optionItem = optionItem;
+                    if (optionItem.checkField) {
+                        // console.log(`采用依赖项的检测字段${optionItem.checkField}`)
+                        checkField = optionItem.checkField;
+                    }
+                }
+                else {
+                    logStr = `项${fieldKey} 依赖表单项:${depend},没有对应 options 内容`;
+                    isFailed = true;
+                }
+                if (!r) {
+                    logStr = `项${fieldKey} 检测依赖字段:${depend},但是选项${formItem.val}不在范围内`;
+                    depend.msg = '该项依赖项输入异常';
+                    formItem.msg = '该值依赖项输入异常';
+                    formItem.state = this.formState_notPass;
+                }
+            }
+            // 使用验证规则进行
+            formItem.msg = this.fieldCheck.verify({
+                [checkField]: formItem.val,
+                isMustMatch
+            });
+            if (formItem.msg) {
+                isFailed = true;
+                logStr = `检测字段:${checkField},值:${formItem.val}不符合规则,${formItem.msg}`;
+            }
+            if (isFailed) {
+                logStr = `检测字段:${checkField},值:${formItem.val}不符合规则,${formItem.msg}`;
+                formItem.state = this.formState_notPass;
+                r = false;
+            }
+            else {
+                n_checkPass++;
+                logStr = `检测字段:${checkField},值:${formItem.val}符合规则`;
+                formItem.state = this.formState_pass;
+                formItem.msg = '';
+            }
+            if (logStr)
+                logHandle(logStr);
+        }
+        logHandle(`检查表单项通过率:${n_checkPass}/${n_checkTotal}`);
+        return r;
+    }
+    /**
+     * 验证当前的表单是否符合要求
+     * @param [isMustMatch] 是否必须全部匹配到验证规则
+     */
+    check(isMustMatch = false) {
+        return this.checkForm(this.formData, isMustMatch);
+    }
+    /**
+     * 检测特定表单项的内容是否符合规则
+     * @param field 字段名
+     * @param isMustMatch 是否必须匹配到验证规则 默认 true
+     */
+    checkItem(field, isMustMatch = true) {
+        var _a, _b;
+        // 获取表单项
+        let formItem;
+        let depend;
+        let formObject = {};
+        formItem = (_a = this === null || this === void 0 ? void 0 : this.formData) === null || _a === void 0 ? void 0 : _a[field];
+        if (!formItem) {
+            return null;
+        }
+        formObject[field] = formItem;
+        // 判断是否有depend字段
+        if (formItem.depend) {
+            formObject[formItem.depend] = (_b = this.formData) === null || _b === void 0 ? void 0 : _b[formItem.depend];
+        }
+        let pass = this.checkForm(formObject, isMustMatch);
+        // 检查表单项是否符合要求
+        return formObject[field].msg ? formObject[field].msg : null;
+    }
+    /**
+     * 使用该表单绑定的验证器进行验证字段与值是否符合规则
+     * @param field 要验证的字段
+     * @param value 要验证的值
+     * @param isMustMatch
+     */
+    verifyKnV(field, value, isMustMatch = true) {
+        return this.fieldCheck.verify({
+            [field]: value,
+        }, isMustMatch);
+    }
+    /**
+     * 获取表单keyValue数据对
+     * @returns {verifyForm} key:value
+     */
+    getFormData() {
+        let formData = {};
+        for (const key in this.formData) {
+            if (hasOwn(this.formData, key)) {
+                const formItem = this.formData[key];
+                formData[key] = formItem.val;
+            }
+        }
+        return formData;
+    }
+    init() {
+        FormVerify.initFormItemData(this.formData);
+    }
+}
+export default FormVerify;
+//# sourceMappingURL=formVerify.js.map

+ 18 - 0
lib/esm/index.js

@@ -0,0 +1,18 @@
+/**
+ * @module kind-form-verify
+ */
+// import "./types";
+// 导入 types
+export { default as FormVerify } from "./formVerify";
+export { default as FieldCheck } from "./fieldCheck";
+// 导出模块
+// export default {
+//     FormVerify,
+//     FieldCheck,
+// };
+// 示例
+/**
+ * @example
+ * import {FormItem,FieldCheck} from "kind-form-verify"
+ */
+//# sourceMappingURL=index.js.map