瀏覽代碼

基础表单验证类开发

kindring 2 年之前
父節點
當前提交
35c061bb94

+ 2 - 0
buildTools/build.js

@@ -0,0 +1,2 @@
+// 连接数据库导出数据
+

+ 9 - 7
model/ckeditor/ckeditor.d.ts

@@ -3,26 +3,28 @@
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  */
 import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic';
+import { Alignment } from '@ckeditor/ckeditor5-alignment';
 import { Autoformat } from '@ckeditor/ckeditor5-autoformat';
 import { Bold, Italic } from '@ckeditor/ckeditor5-basic-styles';
 import { BlockQuote } from '@ckeditor/ckeditor5-block-quote';
-import { CloudServices } from '@ckeditor/ckeditor5-cloud-services';
 import { Essentials } from '@ckeditor/ckeditor5-essentials';
-import { FontSize } from '@ckeditor/ckeditor5-font';
+import { FontBackgroundColor, FontColor, FontFamily, FontSize } from '@ckeditor/ckeditor5-font';
 import { Heading } from '@ckeditor/ckeditor5-heading';
-import { Highlight } from '@ckeditor/ckeditor5-highlight';
-import { Image, ImageCaption, ImageResize, ImageStyle, ImageToolbar, ImageUpload } from '@ckeditor/ckeditor5-image';
-import { Indent } from '@ckeditor/ckeditor5-indent';
+import { HorizontalLine } from '@ckeditor/ckeditor5-horizontal-line';
+import { Image, ImageCaption, ImageResize, ImageStyle, ImageToolbar } from '@ckeditor/ckeditor5-image';
+import { Indent, IndentBlock } from '@ckeditor/ckeditor5-indent';
 import { Link } from '@ckeditor/ckeditor5-link';
-import { List } from '@ckeditor/ckeditor5-list';
+import { List, ListProperties } from '@ckeditor/ckeditor5-list';
 import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed';
 import { Paragraph } from '@ckeditor/ckeditor5-paragraph';
 import { PasteFromOffice } from '@ckeditor/ckeditor5-paste-from-office';
+import { SelectAll } from '@ckeditor/ckeditor5-select-all';
+import { SpecialCharacters } from '@ckeditor/ckeditor5-special-characters';
 import { Table, TableToolbar } from '@ckeditor/ckeditor5-table';
 import { TextTransformation } from '@ckeditor/ckeditor5-typing';
 import MyCustomPlugin from './customPluugs';
 declare class Editor extends ClassicEditor {
-    static builtinPlugins: (typeof Autoformat | typeof BlockQuote | typeof Bold | typeof CloudServices | typeof Essentials | typeof FontSize | typeof Heading | typeof Highlight | typeof Image | typeof ImageCaption | typeof ImageResize | typeof ImageStyle | typeof ImageToolbar | typeof ImageUpload | typeof Indent | typeof Italic | typeof Link | typeof List | typeof MediaEmbed | typeof Paragraph | typeof PasteFromOffice | typeof Table | typeof TableToolbar | typeof TextTransformation)[];
+    static builtinPlugins: (typeof Alignment | typeof Autoformat | typeof BlockQuote | typeof Bold | typeof Essentials | typeof FontBackgroundColor | typeof FontColor | typeof FontFamily | typeof FontSize | typeof Heading | typeof HorizontalLine | typeof Image | typeof ImageCaption | typeof ImageResize | typeof ImageStyle | typeof ImageToolbar | typeof Indent | typeof IndentBlock | typeof Italic | typeof Link | typeof List | typeof ListProperties | typeof MediaEmbed | typeof Paragraph | typeof PasteFromOffice | typeof SelectAll | typeof SpecialCharacters | typeof Table | typeof TableToolbar | typeof TextTransformation)[];
     static defaultConfig: {
         toolbar: {
             items: string[];

文件差異過大導致無法顯示
+ 0 - 0
model/ckeditor/ckeditor.js


文件差異過大導致無法顯示
+ 0 - 0
model/ckeditor/translations/zh.js


+ 1 - 1
package.json

@@ -4,7 +4,7 @@
   "private": true,
   "scripts": {
     "dev": "nuxt --NODE_ENV=development",
-    "build": "nuxt build --NODE_ENV=production",
+    "build": "nuxt build --NODE_ENV=production && node ./buildTools/build.js",
     "start": "nuxt start --PORT=production ",
     "generate": "nuxt generate"
   },

+ 4 - 2
pages/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="w-screen pad:w-full bg-amber-200 relative">
+  <div class="w-screen pad:w-full relative">
 <!--    header 部分布局-->
     <lucency-header :lang="lang" page-key="index" :is-phone="isPhone" />
     <banner :banners="carousel" :wait-time="2500"/>
@@ -66,5 +66,7 @@ export default {
 </script>
 
 <style>
-
+body{
+  background-color: #FDEEB7;
+}
 </style>

+ 24 - 5
pages/manger/news/add.vue

@@ -54,7 +54,13 @@ export default {
       }
       if (arr[0].key !== 'all'){
         // 添加 all
-        arr.unshift({text: '全部', key: 'all' });
+        arr.unshift(
+          {
+            text: '全部',
+            key: 'all',
+            value: 'all',
+          }
+        );
       }
 
       return arr;
@@ -79,9 +85,9 @@ export default {
           msg: '',
           state: 0,
           options: [
-            {text: '全部', key: dbField_esm.db_base.newsType.all},
-            {text: '新闻', key: dbField_esm.db_base.newsType.news},
-            {text: '解决方案', key: dbField_esm.db_base.newsType.solution},
+            {text: '全部', key: dbField_esm.db_base.newsType.all, value: dbField_esm.db_base.newsType.all},
+            {text: '新闻', key: dbField_esm.db_base.newsType.news, value: dbField_esm.db_base.newsType.news},
+            {text: '解决方案', key: dbField_esm.db_base.newsType.solution, value: dbField_esm.db_base.newsType.solution},
           ]
         },
         type: {
@@ -89,7 +95,8 @@ export default {
           init: '',
           msg: '',
           state: 0,
-          options: []
+          options: [],
+          disables: ['all'],
         },
         title: {
           val: '',
@@ -113,6 +120,7 @@ export default {
           val: '',
           init: '',
           msg: '',
+          reCheckField: 'url',
           state: 0
         },
         remark: {
@@ -127,6 +135,7 @@ export default {
   beforeMount() {
     // 插入toolbar
     this.editorConfig.customFunction = () => {
+      console.log('自定义插入图片按钮');
       this.openImageSelect();
     };
     this.initForm();
@@ -178,9 +187,11 @@ export default {
     async onSubmitHandle(){
       // 提交文章
       console.log('提交文章');
+      console.log(this.editorData);
       let formData = {};
       let isPass = checkFormItem(this.form);
       if(!isPass){
+        console.log(this.form);
         return console.log('数据验证不通过');
       }
       formData.content = this.editorData;
@@ -232,24 +243,32 @@ export default {
         :options="form.type.options"
         v-model="form.type.val"
       />
+      <div v-if="form.type.msg" class="flex items-center pl-2 text-red-500 font-bold border-l border-b-orange-700">
+        {{form.type.msg}}
+      </div>
     </div>
+
     <input-row class="mt-2" :msg="form.author.msg"
                label="作者">
       <a-input v-model="form.author.val" placeholder="请输入作者"></a-input>
     </input-row>
+
     <input-row class="mt-2" :msg="form.source.msg"
                label="来源">
       <a-input v-model="form.source.val" placeholder="请输入来源"></a-input>
     </input-row>
+
     <input-row class="mt-2" :msg="form.title.msg"
                label="标题">
       <a-input v-model="form.title.val" placeholder="请输入标题"></a-input>
     </input-row>
+
     <input-row class="mt-2" :msg="form.remark.msg"
                remark="文章的简介摘要部分,用于外部展示"
                label="摘要" >
       <a-input v-model="form.remark.val" placeholder="请输入摘要"></a-input>
     </input-row>
+
     <input-row class="my-2" :msg="form.cover.msg"
                label="文章封面">
       <div class="rounded relative" style="width: 524px;height: 360px" >

+ 1 - 0
server/database/pool.js

@@ -15,6 +15,7 @@ const pool = mysql.createPool({
     connectionLimit: databseConfig.connectionLimit || 100, //连接限制
     host: databseConfig.host, //地址
     user: databseConfig.user, //用户
+    port: databseConfig.port, //端口
     password: databseConfig.password, // 密码
     database: databseConfig.database, // 数据库名称
     multipleStatements: true,// 允许多条sql同时执行

+ 1 - 0
store/index.js

@@ -12,6 +12,7 @@ function _transform(arr){
     item.key = item.type_key;
     item.typeKey = item.type_key;
     item.href = `/${item.type_key}`;
+    item.value = item.type_key;
     return item;
   })
   return arr;

+ 16 - 16
until/fieldIsAllow.js

@@ -148,15 +148,15 @@ const paramsRules = [
         rules:ownerRule
     },
     {
-        keys:['passwd','password'],
+        keys:['passwd', 'password'],
         rules:passwordRule
     },
     {
-        keys: ['card','workerCard'],
+        keys: ['card', 'workerCard'],
         rules: cardRule,
     },
     {
-        keys: ['href'],
+        keys: ['href', 'url'],
         rules: hrefRule,
     },
     {
@@ -200,7 +200,7 @@ function _c(key,value){
       return false;
     });
     console.log(_obj)
-    if(!_obj||!_obj.rules){
+    if(!_obj || !_obj.rules){
         return [code_notMatch];
     }
     // 开始匹配规则
@@ -212,23 +212,23 @@ function _c(key,value){
                 return [code_notPass,_msg]
             }
         }
-        if(_rule.require&&_isEmpty(value)){
-            return [code_notPass,_rule.message]
+        if(_rule.require && _isEmpty(value)){
+            return [code_notPass, _rule.message]
         }
-        if(_rule.type&&typeof value !== _rule.type){
-            return [code_notPass,_rule.message]
+        if(_rule.type && typeof value !== _rule.type){
+            return [code_notPass, _rule.message]
         }
-        if(_rule.length&&value.length !== _rule.length){
-            return [code_notPass,_rule.message]
+        if(_rule.length && value.length !== _rule.length){
+            return [code_notPass, _rule.message]
         }
-        if(_rule.minLength&&value.length < _rule.minLength){
-            return [code_notPass,_rule.message]
+        if(_rule.minLength && value.length < _rule.minLength){
+            return [code_notPass, _rule.message]
         }
-        if(_rule.maxLength&&value.length > _rule.maxLength){
-            return [code_notPass,_rule.message]
+        if(_rule.maxLength && value.length > _rule.maxLength){
+            return [code_notPass, _rule.message]
         }
-        if(_rule.regex&&!_rule.regex.test(value)){
-            return [code_notPass,_rule.message]
+        if(_rule.regex && !_rule.regex.test(value)){
+            return [code_notPass, _rule.message]
         }
     }
     return [code_pass]

+ 13 - 0
until/formFieldCheck/README.md

@@ -0,0 +1,13 @@
+# 表单字段验证
+> 该简易库用于快捷验证字段是否合法
+
+## 安装
+> 跳过,目前暂时引用 `index.js`
+
+## 介绍
+### 使用方法
+1. 创建字段验证规则
+2. 给验证规则绑定对应的字段 array
+3. 创建验证器
+4. 创建验证表单实例,使用 json 对象传入表单值
+5. 使用方法验证表单

+ 291 - 0
until/formFieldCheck/fieldCheck.js

@@ -0,0 +1,291 @@
+/**
+ * 表单字段验证库
+ * author:kindring
+ * date:2023/10/08
+ */
+
+/**
+ * @typedef {string} errMessage 错误信息
+ */
+
+
+/**
+ * @typedef { Array<string | RegExp> } checkFields 验证字段匹配项
+ */
+/**
+ * @typedef {Object} checkRule 规则对象
+ * @property {string} [type] 类型
+ * @property {number} [min] 最小值
+ * @property {number} [max] 最大值
+ * @property {number} [length] 长度
+ * @property {RegExp} [regex] 正则表达式
+ * @property {errMessage} [message] 错误信息
+ * @property {boolean} [require] 是否必须
+ * @property {number} [minLength] 最小长度
+ * @property {number} [maxLength] 最大长度
+ * @property {validatorFunction} [validator] 自定义验证函数
+ */
+
+/**
+ * @typedef {function} validatorFunction 自定义验证函数
+ * @param {any} value 需要验证的值
+ * @returns {string} 返回错误信息或者 null
+ */
+
+/**
+ * @typedef {Object} ruleItem 验证规则对象
+ * @property {Array<string>} checkFields 需要验证的字段
+ * @property {Array<validatorFunction | checkRule>} rules 验证规则
+ */
+
+/**
+ * @typedef {number} checkCode 验证码
+ * @property {1} code_pass 验证通过
+ * @property {2} code_notPass 验证不通过
+ * @property {3} code_notMatch 未匹配到验证规则
+ */
+
+
+/**
+ * @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{
+    // 通过
+    #code_pass = 1;
+    // 未通过
+    #code_notPass = 2;
+
+    // 无法匹配到验证规则
+    #code_notMatch = 3;
+
+    /**
+     * @type {Array< ruleItem >}
+     */
+    #ruleItems = [];
+    constructor() {
+        this.#ruleItems = [];
+    }
+
+    /**
+     * 判断值是否定义
+     * @param v
+     * @returns {boolean}
+     * @private
+     */
+    _isDef (v) {
+        return v !== undefined && v !== null
+    }
+    _toString = Object.prototype.toString;
+    /**
+     * 判断是否为空
+     * @param v
+     * @returns {boolean}
+     */
+    _isEmpty(v){
+        return v === undefined || v === '';
+    }
+    _isRegExp (v) {
+        return this._toString.call(v) === '[object RegExp]'
+    }
+
+
+    /**
+     * 构建验证规则
+     * @param {Array<string | RegExp>} checkFields 需要验证的字段
+     * @param {Array<validatorFunction | checkRule>} ruleArr 验证规则
+     * @returns {ruleItem} 验证规则对象
+     */
+    buildRuleItem( 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' && !(field instanceof RegExp)){
+                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');
+            }
+        }
+        /**
+         * @type {ruleItem}
+         */
+        let ruleItem = {
+            checkFields: checkFields,
+            rules: ruleArr
+        }
+        // this.ruleItems = this.ruleItems.push(ruleItem);
+        return ruleItem;
+    }
+
+    /**
+     * 添加一条验证规则
+     * @param { string } ruleName 验证规则名,用于区分
+     * @param { Array<string | RegExp> } checkFields 用于匹配字段的字符或者正则数组
+     * @param { Array<validatorFunction | checkRule> } ruleArr 验证规则
+     * @returns { FieldCheck } 返回当前对象
+     */
+    addRuleItem( ruleName, checkFields , ruleArr) {
+        let ruleItem = this.buildRuleItem(checkFields,ruleArr);
+        this.#ruleItems.push(ruleItem);
+        return this;
+    }
+
+    /**
+     * 获取验证规则
+     * @param { string } field 字段名
+     * @returns { ruleItem } 验证规则
+     */
+    getRuleItem(field){
+        let ruleItem = this.#ruleItems.find(item=>{
+            // 判断是否为正则
+            for (const _matchKey of item.checkFields) {
+                // 判断是否为正则
+                if(_matchKey instanceof RegExp){
+                    // console.log(`使用正则进行匹配,${_matchKey.test(key)}`);
+                    if(_matchKey.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;
+        });
+        return ruleItem;
+    }
+
+    /**
+     * 检查字段是否符合规则
+     * @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]
+                }
+            }
+
+            // 判断类型
+            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 { Object } formObject 需要检验的表单项 字段:值
+     * @param [isMustMatch] 是否强制要求匹配规则
+     * @returns { errMessage } 错误码或错误信息
+     */
+    verify(formObject, isMustMatch){
+        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 `字段没有对应匹配项`
+            }
+        }
+    }
+}
+
+export default FieldCheck;

+ 295 - 0
until/formFieldCheck/formData.js

@@ -0,0 +1,295 @@
+import FieldCheck from "./fieldCheck";
+import fieldIsAllow from "@/until/fieldIsAllow";
+
+let hasOwnProperty = Object.prototype.hasOwnProperty;
+function hasOwn (obj, key) {
+    return hasOwnProperty.call(obj, key)
+}
+
+/**
+ * @typedef {object} formItemData 表单项数据
+ * @property {string} [val] 表单项值
+ * @property {string} [msg] 表单项错误信息
+ * @property {number} [state] 表单项状态 0 通过 1 通过 2 不通过
+ * @property {string} [showText] 表单项显示文本,用于在某些
+ * @property {string} [label] 表单项显示文本
+ * @property {string} [init] 表单项初始值
+ * @property {Array} [options] 表单项枚举值
+ * @property {string} [depend] 依赖字段, 该项存在将使用依赖字段的option中的checkField字段进行匹配验证规则
+ * @property {string} [reCheckField] 该表单项用于匹配规则的字段
+ * @property {Array} [disables] 禁用项
+ */
+
+
+/**
+ * @class FormItem
+ * @description 表单项
+ * @param {object} object 表单项数据
+ * @param {FieldCheck} [fieldCheck] 字段验证对象
+ * @param {object} [option] 配置项
+ */
+class FormItem {
+    formData;
+    /**
+     * @type {FieldCheck} 字段验证对象
+     */
+    fieldCheck;
+    // 表单状态 默认 0 通过 1 不通过 2
+    formState_default = 0;
+    formState_pass = 1;
+    formState_notPass = 2;
+
+    defaultOption = {
+        isMustMatchRule: false,// 表单字段是否必须匹配到验证规则
+    }
+    option = {};
+    /**
+     *
+     * @param object
+     * @param {FieldCheck} [fieldCheck] 字段验证对象
+     * @param {object} [option] 配置项
+     */
+    constructor(object, fieldCheck, option) {
+        this.fieldCheck = fieldCheck || new FieldCheck();
+        // 合并配置项
+        this.option = Object.assign(this.defaultOption, option);
+        let errMsg;
+        // 拿出其中的每一项来构建对应的表单项
+        for (let key in object) {
+            this[key] = object[key];
+            // 验证表单项是否符合要求,不符合要求则抛出错误
+            errMsg = FormItem.buildFormItem(object, key, object[key], this.fieldCheck, this.option.isMustMatchRule);
+            if (errMsg) {
+                throw new Error(`表单项${key}不符合要求,err:${errMsg}`);
+            }
+        }
+        this.formData = object;
+    }
+    static isObject (obj) {
+        return obj !== null && typeof obj === 'object'
+    }
+
+    /**
+     * 检查表单项是否符合要求
+     * @param { object } object 表单项数据
+     * @param { string } field 字段名
+     * @param { formItemData } formItemData 表单项数据
+     * @param { FieldCheck } fieldCheck 字段验证对象
+     * @param { boolean } isMustMatchRule 表单字段是否必须匹配到验证规则
+     * @returns { string } errMsg 错误信息
+     */
+    static buildFormItem(object, field, formItemData, fieldCheck, isMustMatchRule) {
+        if ( !FormItem.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 || FormData.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.indexOf(option.key) !== -1 ){
+                    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 ){
+            // 判断依赖字段是否存在
+            if ( !object[formItemData.depend] ){
+                return `form item ${field} depend field ${formItemData.depend} but the field not exist`;
+            }
+            // 判断依赖字段的 option 是否存在
+            if ( !object[formItemData.depend].options ){
+                return `form item ${field} depend field ${formItemData.depend} has no options`;
+            }
+            // 判断依赖字段的 options 中是否有 checkField 字段
+            let hasCheckField = false;
+            for (let i = 0; i < object[formItemData.depend].options.length; i++) {
+                let option = object[formItemData.depend].options[i];
+                if ( option.checkField ){
+                    hasCheckField = true;
+                    checkFieldStr = option.checkField;
+                    break;
+                }
+            }
+            if ( !hasCheckField ){
+                return `form item ${field} depend field ${formItemData.depend} 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 = FormData.formState_default;
+            formObject[key].showText = '';
+        }
+    }
+
+
+    /**
+     * 检查表单项是否符合要求
+     * @param {object} form 表单对象
+     * @param isMustMatch 是否必须全部匹配到验证规则
+     * @returns {boolean}
+     */
+    checkForm (form, isMustMatch) {
+        let r = true;
+        let n_checkPass = 0,
+            n_checkTotal = 0;
+        let msg = '';
+        for (const fieldKey in form) {
+            let formItem = form[fieldKey];
+            let depend = form[formItem.depend];
+            let checkField = fieldKey;
+            let tmpInd = -1;
+
+            n_checkTotal++;
+
+            if(formItem.reCheckField){
+                checkField = formItem.reCheckField;
+            }
+
+            // 禁用值判断 array
+            if(formItem.disables){
+                if(formItem.disables.indexOf(formItem.val) !== -1){
+                    formItem.msg = '该项内容不合法';
+                    r = false;
+                }
+            }
+
+            // 枚举值判断
+            if(formItem.options){
+                // 有枚举字段,只判断是否在枚举中
+                // console.log(`检测枚举字段:${checkField},值:${formItem.val}`);
+                tmpInd = formItem.options.findIndex(item=>item.value == formItem.val);
+                if(tmpInd === -1){
+                    console.log(`检测枚举字段:${checkField},值:${formItem.val}不在范围内`);
+                    formItem.msg = '选项不在范围内';
+                    formItem.state = 1;
+                    r = false;
+                }else{
+                    // 判断值是否为禁用项
+                    if(formItem.options[tmpInd].disabled){
+                        formItem.msg = '该选项已经被禁用';
+                        r = false;
+                    }
+                }
+                // 枚举值判断完毕,继续下一个字段
+                n_checkPass++;
+                continue;
+            }
+
+            // 依赖字段判断
+            if(depend){
+                if(depend.options){
+                    // 依赖的对象有枚举类型,检查该枚举类型是否有有检测值
+                    let optionItem = depend.options.find(item=>item.value == depend.val);
+                    if(!optionItem){
+                        depend.msg = '选项不在范围内';
+                        formItem.msg = '该值依赖项输入异常';
+                        r = false;
+                        // continue;
+                    }
+                    if(optionItem.checkField){
+                        // console.log(`采用依赖项的检测字段${optionItem.checkField}`)
+                        checkField = optionItem.checkField;
+                    }
+
+                }else{
+                    r = false;
+                }
+                if(!r)
+                {
+                    depend.msg = '该项依赖项输入异常';
+                    formItem.msg = '该值依赖项输入异常';
+                }
+            }
+
+            // 使用验证规则进行
+            formItem.msg = this.fieldCheck.verify({
+                [checkField]:formItem.val,
+            })
+
+
+            if (formItem.msg) r = false;
+            if(r){
+                n_checkPass++;
+                formItem.state = this.formState_pass
+            }else{
+                formItem.state = this.formState_notPass
+            }
+        }
+
+        msg = `检查表单项通过率:${n_checkPass}/${n_checkTotal}`;
+        console.log(msg);
+        return r;
+    }
+
+}
+
+export default FormItem;

+ 2 - 0
until/formFieldCheck/index.js

@@ -0,0 +1,2 @@
+import FieldCheck from "./fieldCheck";
+import FormItem from "./formData";

+ 14 - 2
until/formTool.js

@@ -1,5 +1,6 @@
 import fieldIsAllow from "./fieldIsAllow";
 
+
 export function initForm(formObject){
   let keys = Object.keys(formObject);
   for(let i = 0; i < keys.length; i++){
@@ -17,7 +18,7 @@ export function initForm(formObject){
 export function checkFormItem(form,field,enumOptions,reCheckField){
   let formItem = form[field];
   if (formItem){
-    if (enumOptions){
+    if (enumOptions) {
       // 遍历枚举
       for (let i = 0; i < enumOptions.length; i++) {
         let enumOption = enumOptions[i];
@@ -28,7 +29,7 @@ export function checkFormItem(form,field,enumOptions,reCheckField){
       formItem.msg = '选项不在范围内';
       return false;
     }
-    if(reCheckField){
+    if (reCheckField) {
       // 检查用字段
       formItem.msg = fieldIsAllow({
         [reCheckField]:formItem.val,
@@ -48,10 +49,21 @@ export function checkFormItem(form,field,enumOptions,reCheckField){
       if(formItem.reCheckField){
         checkField = formItem.reCheckField;
       }
+
+      // 禁用值判断 array
+      if(formItem.disables){
+        if(formItem.disables.indexOf(formItem.val) !== -1){
+          formItem.msg = '该项内容不合法';
+          r = false;
+        }
+      }
+
       // 枚举值判断
       if(formItem.options){
         // 有枚举字段,只判断是否在枚举中
+        console.log(`检测枚举字段:${checkField},值:${formItem.val}`);
         if(formItem.options.findIndex(item=>item.value == formItem.val) === -1){
+          console.log(`检测枚举字段:${checkField},值:${formItem.val}不在范围内`);
           formItem.msg = '选项不在范围内';
           r = false;
         }

+ 0 - 1
until/typeTool.js

@@ -9,7 +9,6 @@ function toString(v){
         return v + ''
     }
     return v + '';
-
 }
 
 // 转换为number类型,先用toBoolean转换为布尔类型

部分文件因文件數量過多而無法顯示