formData.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. "use strict";
  2. import FieldCheck from "./fieldCheck";
  3. let hasOwnProperty = Object.prototype.hasOwnProperty;
  4. function hasOwn (obj, key) {
  5. return hasOwnProperty.call(obj, key)
  6. }
  7. /**
  8. * @typedef {object} formItemData 表单项数据
  9. * @property {string} [val] 表单项值
  10. * @property {string} [msg] 表单项错误信息
  11. * @property {number} [state] 表单项状态 0 通过 1 通过 2 不通过
  12. * @property {string} [showText] 表单项显示文本,用于在某些
  13. * @property {string} [label] 表单项显示文本
  14. * @property {string} [init] 表单项初始值
  15. * @property {Array} [options] 表单项枚举值
  16. * @property {string} [depend] 依赖字段, 该项存在将使用依赖字段的option中的checkField字段进行匹配验证规则
  17. * @property {string} [reCheckField] 该表单项用于匹配规则的字段
  18. * @property {Array} [disables] 禁用项
  19. */
  20. /**
  21. * @class FormItem 表单验证类
  22. * @description 表单项
  23. * @param {object} object 表单项数据
  24. * @param {FieldCheck} [fieldCheck] 字段验证对象
  25. * @param {object} [option] 配置项
  26. */
  27. class FormItem {
  28. formData = null;
  29. /**
  30. * @type {FieldCheck} 字段验证对象
  31. */
  32. fieldCheck = null;
  33. // 表单状态 默认 0 通过 1 不通过 2
  34. formState_default = 0;
  35. formState_pass = 1;
  36. formState_notPass = 2;
  37. defaultOption = {
  38. isMustMatchRule: false,// 表单字段是否必须匹配到验证规则
  39. }
  40. option = {};
  41. /**
  42. *
  43. * @param object
  44. * @param {FieldCheck} [fieldCheck] 字段验证对象
  45. * @param {object} [option] 配置项
  46. */
  47. constructor(object, fieldCheck, option) {
  48. this.fieldCheck = fieldCheck || new FieldCheck();
  49. // 合并配置项
  50. this.option = Object.assign(this.defaultOption, option);
  51. let errMsg;
  52. // 拿出其中的每一项来构建对应的表单项
  53. for (let key in object) {
  54. this[key] = object[key];
  55. // 验证表单项是否符合要求,不符合要求则抛出错误
  56. errMsg = FormItem.buildFormItem(object, key, object[key], this.fieldCheck, this.option.isMustMatchRule);
  57. if (errMsg) {
  58. throw new Error(`表单项${key}不符合要求,err:${errMsg}`);
  59. }
  60. }
  61. this.formData = object;
  62. }
  63. static isObject (obj) {
  64. return obj !== null && typeof obj === 'object'
  65. }
  66. /**
  67. * 检查表单项是否符合要求
  68. * @param { object } object 表单项数据
  69. * @param { string } field 字段名
  70. * @param { formItemData } formItemData 表单项数据
  71. * @param { FieldCheck } fieldCheck 字段验证对象
  72. * @param { boolean } isMustMatchRule 表单字段是否必须匹配到验证规则
  73. * @returns { string } errMsg 错误信息
  74. */
  75. static buildFormItem(object, field, formItemData, fieldCheck, isMustMatchRule) {
  76. if ( !FormItem.isObject(formItemData) ){
  77. return `form item ${field} must be object`;
  78. }
  79. // 是否需要从验证规则表中查找对应的验证规则
  80. let isNeedMatchRule = true;
  81. // 用于匹配的字段
  82. let checkFieldStr = field;
  83. let disables = formItemData.disables;
  84. // 设置默认值
  85. formItemData.val = formItemData.val || formItemData.init || '';
  86. // 设置默认提示词
  87. formItemData.msg = formItemData.msg || '';
  88. // 设置默认状态
  89. formItemData.state = formItemData.state || FormData.formState_default;
  90. // 设置默认显示文本
  91. formItemData.label = formItemData.label || '';
  92. // 判断是否有 options 选项有则判断是否有 init 选项,没有则设置第一个为 init
  93. if ( formItemData.options ){
  94. if( !formItemData.options.length || !formItemData.options[0] ){
  95. return `form item ${field} options must be array and has item`;
  96. }
  97. if ( !formItemData.init ){
  98. formItemData.init = formItemData.options[0].key;
  99. }
  100. // 判断 val 与 init 是否存在于 options 中
  101. let hasInit = false;
  102. for (let i = 0; i < formItemData.options.length; i++) {
  103. let option = formItemData.options[i];
  104. if ( option.key === formItemData.init ){
  105. hasInit = true;
  106. }
  107. // 判断该options是否为禁用项
  108. if ( disables && disables.indexOf(option.key) !== -1 ){
  109. option.disabled = true;
  110. }
  111. }
  112. if ( !hasInit ){
  113. return `form item ${field} init value must be in options`;
  114. }
  115. }
  116. // 判断是否有 depend 依赖字段 有依赖字段则依据依赖字段中的 option 中的 checkField 字段进行判断
  117. if( formItemData.depend && formItemData.reCheckField ){
  118. return `form item ${field} has depend and reCheckField, but depend and reCheckField can not exist at the same time`;
  119. }
  120. // 判断是否有 depend 依赖字段 有依赖字段则依据依赖字段中的 option 中的 checkField 字段进行判断
  121. if ( formItemData.depend ){
  122. // 判断依赖字段是否存在
  123. if ( !object[formItemData.depend] ){
  124. return `form item ${field} depend field ${formItemData.depend} but the field not exist`;
  125. }
  126. // 判断依赖字段的 option 是否存在
  127. if ( !object[formItemData.depend].options ){
  128. return `form item ${field} depend field ${formItemData.depend} has no options`;
  129. }
  130. // 判断依赖字段的 options 中是否有 checkField 字段
  131. let hasCheckField = false;
  132. for (let i = 0; i < object[formItemData.depend].options.length; i++) {
  133. let option = object[formItemData.depend].options[i];
  134. if ( option.checkField ){
  135. hasCheckField = true;
  136. checkFieldStr = option.checkField;
  137. break;
  138. }
  139. }
  140. if ( !hasCheckField ){
  141. return `form item ${field} depend field ${formItemData.depend} has no checkField`;
  142. }
  143. }
  144. // 判断是否有 reCheckField 有则使用该字段的值进行规则验证
  145. if ( formItemData.reCheckField ){
  146. checkFieldStr = formItemData.reCheckField;
  147. }
  148. // 判断是否有 rules 规则
  149. if(isMustMatchRule){
  150. if(fieldCheck.getRuleItem(checkFieldStr)){
  151. return `form item ${field} has no rules`;
  152. }
  153. }
  154. return '';
  155. }
  156. /**
  157. * 初始化表单项数据
  158. * @param { formObject } formObject 表单对象
  159. */
  160. static initFormItemData ( formObject ) {
  161. let keys = Object.keys(formObject);
  162. for(let i = 0; i < keys.length; i++){
  163. let key = keys[i];
  164. formObject[key].val = formObject[key].init;
  165. formObject[key].msg = '';
  166. formObject[key].state = FormData.formState_default;
  167. formObject[key].showText = '';
  168. }
  169. }
  170. /**
  171. * 检查表单项是否符合要求
  172. * @param {object} form 表单对象
  173. * @param isMustMatch 是否必须全部匹配到验证规则
  174. * @returns {boolean}
  175. */
  176. checkForm (form, isMustMatch) {
  177. let r = true;
  178. let n_checkPass = 0,
  179. n_checkTotal = 0;
  180. let msg = '';
  181. for (const fieldKey in form) {
  182. let formItem = form[fieldKey];
  183. let depend = form[formItem.depend];
  184. let checkField = fieldKey;
  185. let tmpInd = -1;
  186. n_checkTotal++;
  187. if(formItem.reCheckField){
  188. checkField = formItem.reCheckField;
  189. }
  190. // 禁用值判断 array
  191. if(formItem.disables){
  192. if(formItem.disables.indexOf(formItem.val) !== -1){
  193. formItem.msg = '该项内容不合法';
  194. r = false;
  195. }
  196. }
  197. // 枚举值判断
  198. if(formItem.options){
  199. // 有枚举字段,只判断是否在枚举中
  200. // console.log(`检测枚举字段:${checkField},值:${formItem.val}`);
  201. tmpInd = formItem.options.findIndex(item=>item.value == formItem.val);
  202. if(tmpInd === -1){
  203. console.log(`检测枚举字段:${checkField},值:${formItem.val}不在范围内`);
  204. formItem.msg = '选项不在范围内';
  205. formItem.state = 1;
  206. r = false;
  207. }else{
  208. // 判断值是否为禁用项
  209. if(formItem.options[tmpInd].disabled){
  210. formItem.msg = '该选项已经被禁用';
  211. r = false;
  212. }
  213. }
  214. // 枚举值判断完毕,继续下一个字段
  215. n_checkPass++;
  216. continue;
  217. }
  218. // 依赖字段判断
  219. if(depend){
  220. if(depend.options){
  221. // 依赖的对象有枚举类型,检查该枚举类型是否有有检测值
  222. let optionItem = depend.options.find(item=>item.value == depend.val);
  223. if(!optionItem){
  224. depend.msg = '选项不在范围内';
  225. formItem.msg = '该值依赖项输入异常';
  226. r = false;
  227. // continue;
  228. }
  229. if(optionItem.checkField){
  230. // console.log(`采用依赖项的检测字段${optionItem.checkField}`)
  231. checkField = optionItem.checkField;
  232. }
  233. }else{
  234. r = false;
  235. }
  236. if(!r)
  237. {
  238. depend.msg = '该项依赖项输入异常';
  239. formItem.msg = '该值依赖项输入异常';
  240. }
  241. }
  242. // 使用验证规则进行
  243. formItem.msg = this.fieldCheck.verify({
  244. [checkField]:formItem.val,
  245. })
  246. if (formItem.msg) r = false;
  247. if(r){
  248. n_checkPass++;
  249. formItem.state = this.formState_pass
  250. }else{
  251. formItem.state = this.formState_notPass
  252. }
  253. }
  254. msg = `检查表单项通过率:${n_checkPass}/${n_checkTotal}`;
  255. console.log(msg);
  256. return r;
  257. }
  258. }
  259. export default FormItem;