@carefrees/form-utils-vue-hooks 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +7 -0
  2. package/esm/hooks/attr/attr.FormItem.d.ts +94 -0
  3. package/esm/hooks/attr/attr.FormItem.js +104 -0
  4. package/esm/hooks/index.d.ts +13 -0
  5. package/esm/hooks/index.js +13 -0
  6. package/esm/hooks/register/register.FormHideItem.d.ts +9 -0
  7. package/esm/hooks/register/register.FormHideItem.js +26 -0
  8. package/esm/hooks/register/register.FormItem.d.ts +24 -0
  9. package/esm/hooks/register/register.FormItem.js +67 -0
  10. package/esm/hooks/register/register.FormList.d.ts +9 -0
  11. package/esm/hooks/register/register.FormList.js +42 -0
  12. package/esm/hooks/register/register.form.d.ts +4 -0
  13. package/esm/hooks/register/register.form.js +10 -0
  14. package/esm/hooks/useAttrs.d.ts +25 -0
  15. package/esm/hooks/useAttrs.js +26 -0
  16. package/esm/hooks/useEffect.d.ts +2 -0
  17. package/esm/hooks/useEffect.js +12 -0
  18. package/esm/hooks/useForm.d.ts +8 -0
  19. package/esm/hooks/useForm.js +21 -0
  20. package/esm/hooks/useFormItem.d.ts +8 -0
  21. package/esm/hooks/useFormItem.js +21 -0
  22. package/esm/hooks/useFormItemParentName.d.ts +18 -0
  23. package/esm/hooks/useFormItemParentName.js +47 -0
  24. package/esm/hooks/useFormList.d.ts +8 -0
  25. package/esm/hooks/useFormList.js +21 -0
  26. package/esm/hooks/useHtmlFor.d.ts +2 -0
  27. package/esm/hooks/useHtmlFor.js +7 -0
  28. package/esm/hooks/useMultipleForm.d.ts +8 -0
  29. package/esm/hooks/useMultipleForm.js +21 -0
  30. package/esm/hooks/useRule.d.ts +4 -0
  31. package/esm/hooks/useRule.js +12 -0
  32. package/esm/index.d.ts +4 -0
  33. package/esm/index.js +4 -0
  34. package/esm/instance/formInstance.d.ts +58 -0
  35. package/esm/instance/formInstance.js +132 -0
  36. package/esm/instance/formItemBaseInstance.d.ts +23 -0
  37. package/esm/instance/formItemBaseInstance.js +6 -0
  38. package/esm/instance/formItemInstance.d.ts +18 -0
  39. package/esm/instance/formItemInstance.js +11 -0
  40. package/esm/instance/formListInstance.d.ts +43 -0
  41. package/esm/instance/formListInstance.js +95 -0
  42. package/esm/instance/index.d.ts +5 -0
  43. package/esm/instance/index.js +5 -0
  44. package/esm/instance/multipleInstance.d.ts +32 -0
  45. package/esm/instance/multipleInstance.js +77 -0
  46. package/esm/instance/ruleIntsnace.d.ts +45 -0
  47. package/esm/instance/ruleIntsnace.js +52 -0
  48. package/esm/interface/index.d.ts +31 -0
  49. package/esm/interface/index.js +0 -0
  50. package/esm/utils/cloneByNamePathList.d.ts +3 -0
  51. package/esm/utils/cloneByNamePathList.js +11 -0
  52. package/esm/utils/get.d.ts +26 -0
  53. package/esm/utils/get.js +13 -0
  54. package/esm/utils/index.d.ts +4 -0
  55. package/esm/utils/index.js +4 -0
  56. package/esm/utils/interface.d.ts +3 -0
  57. package/esm/utils/interface.js +0 -0
  58. package/esm/utils/set.d.ts +32 -0
  59. package/esm/utils/set.js +29 -0
  60. package/esm/utils/utils.d.ts +172 -0
  61. package/esm/utils/utils.js +131 -0
  62. package/lib/hooks/attr/attr.FormItem.d.ts +94 -0
  63. package/lib/hooks/attr/attr.FormItem.js +138 -0
  64. package/lib/hooks/index.d.ts +13 -0
  65. package/lib/hooks/index.js +168 -0
  66. package/lib/hooks/register/register.FormHideItem.d.ts +9 -0
  67. package/lib/hooks/register/register.FormHideItem.js +60 -0
  68. package/lib/hooks/register/register.FormItem.d.ts +24 -0
  69. package/lib/hooks/register/register.FormItem.js +101 -0
  70. package/lib/hooks/register/register.FormList.d.ts +9 -0
  71. package/lib/hooks/register/register.FormList.js +76 -0
  72. package/lib/hooks/register/register.form.d.ts +4 -0
  73. package/lib/hooks/register/register.form.js +44 -0
  74. package/lib/hooks/useAttrs.d.ts +25 -0
  75. package/lib/hooks/useAttrs.js +63 -0
  76. package/lib/hooks/useEffect.d.ts +2 -0
  77. package/lib/hooks/useEffect.js +46 -0
  78. package/lib/hooks/useForm.d.ts +8 -0
  79. package/lib/hooks/useForm.js +61 -0
  80. package/lib/hooks/useFormItem.d.ts +8 -0
  81. package/lib/hooks/useFormItem.js +61 -0
  82. package/lib/hooks/useFormItemParentName.d.ts +18 -0
  83. package/lib/hooks/useFormItemParentName.js +84 -0
  84. package/lib/hooks/useFormList.d.ts +8 -0
  85. package/lib/hooks/useFormList.js +61 -0
  86. package/lib/hooks/useHtmlFor.d.ts +2 -0
  87. package/lib/hooks/useHtmlFor.js +41 -0
  88. package/lib/hooks/useMultipleForm.d.ts +8 -0
  89. package/lib/hooks/useMultipleForm.js +61 -0
  90. package/lib/hooks/useRule.d.ts +4 -0
  91. package/lib/hooks/useRule.js +46 -0
  92. package/lib/index.d.ts +4 -0
  93. package/lib/index.js +87 -0
  94. package/lib/instance/formInstance.d.ts +58 -0
  95. package/lib/instance/formInstance.js +166 -0
  96. package/lib/instance/formItemBaseInstance.d.ts +23 -0
  97. package/lib/instance/formItemBaseInstance.js +40 -0
  98. package/lib/instance/formItemInstance.d.ts +18 -0
  99. package/lib/instance/formItemInstance.js +45 -0
  100. package/lib/instance/formListInstance.d.ts +43 -0
  101. package/lib/instance/formListInstance.js +129 -0
  102. package/lib/instance/index.d.ts +5 -0
  103. package/lib/instance/index.js +96 -0
  104. package/lib/instance/multipleInstance.d.ts +32 -0
  105. package/lib/instance/multipleInstance.js +111 -0
  106. package/lib/instance/ruleIntsnace.d.ts +45 -0
  107. package/lib/instance/ruleIntsnace.js +96 -0
  108. package/lib/interface/index.d.ts +31 -0
  109. package/lib/interface/index.js +18 -0
  110. package/lib/utils/cloneByNamePathList.d.ts +3 -0
  111. package/lib/utils/cloneByNamePathList.js +45 -0
  112. package/lib/utils/get.d.ts +26 -0
  113. package/lib/utils/get.js +47 -0
  114. package/lib/utils/index.d.ts +4 -0
  115. package/lib/utils/index.js +87 -0
  116. package/lib/utils/interface.d.ts +3 -0
  117. package/lib/utils/interface.js +18 -0
  118. package/lib/utils/set.d.ts +32 -0
  119. package/lib/utils/set.js +63 -0
  120. package/lib/utils/utils.d.ts +172 -0
  121. package/lib/utils/utils.js +198 -0
  122. package/package.json +30 -0
  123. package/src/hooks/attr/attr.FormItem.tsx +185 -0
  124. package/src/hooks/index.ts +13 -0
  125. package/src/hooks/register/register.FormHideItem.ts +28 -0
  126. package/src/hooks/register/register.FormItem.ts +93 -0
  127. package/src/hooks/register/register.FormList.ts +49 -0
  128. package/src/hooks/register/register.form.ts +13 -0
  129. package/src/hooks/useAttrs.ts +64 -0
  130. package/src/hooks/useEffect.ts +13 -0
  131. package/src/hooks/useForm.ts +34 -0
  132. package/src/hooks/useFormItem.ts +33 -0
  133. package/src/hooks/useFormItemParentName.ts +49 -0
  134. package/src/hooks/useFormList.ts +33 -0
  135. package/src/hooks/useHtmlFor.ts +9 -0
  136. package/src/hooks/useMultipleForm.ts +30 -0
  137. package/src/hooks/useRule.ts +16 -0
  138. package/src/index.ts +4 -0
  139. package/src/instance/formInstance.ts +220 -0
  140. package/src/instance/formItemBaseInstance.ts +23 -0
  141. package/src/instance/formItemInstance.ts +23 -0
  142. package/src/instance/formListInstance.ts +108 -0
  143. package/src/instance/index.ts +5 -0
  144. package/src/instance/multipleInstance.ts +109 -0
  145. package/src/instance/ruleIntsnace.ts +89 -0
  146. package/src/interface/index.ts +38 -0
  147. package/src/utils/cloneByNamePathList.ts +13 -0
  148. package/src/utils/get.ts +53 -0
  149. package/src/utils/index.ts +4 -0
  150. package/src/utils/interface.ts +4 -0
  151. package/src/utils/set.ts +85 -0
  152. package/src/utils/utils.ts +504 -0
@@ -0,0 +1,220 @@
1
+ import { FormListInstanceBase } from './formListInstance';
2
+ import { FormItemInstanceBase } from './formItemInstance';
3
+ import { ErrorDataField, ValidateErrorEntity } from '../interface';
4
+ import { get, set, cloneByNamePathList, has } from './../utils';
5
+ import { Ref, ref, toValue } from 'vue';
6
+
7
+ /**基础实例*/
8
+ export class FormInstanceBase<T = any> {
9
+ /**表单数据*/
10
+ formData: Ref<Partial<T>> = ref({});
11
+ /**表单每一项实例*/
12
+ formItemInstances: Ref<FormItemInstanceBase>[] = [];
13
+ /**表单中List实例集合*/
14
+ formListInstances: Map<string, Ref<FormListInstanceBase>> = new Map([]);
15
+
16
+ // ======================================隐藏组件=====================================
17
+ /**隐藏组件字段对应的值*/
18
+ hideState: Ref<Record<string, boolean>> = ref({});
19
+
20
+ /**是否保护值(不进行表单项组件卸载重置初始值)*/
21
+ preserve?: boolean = true;
22
+
23
+ //===================================挂载方法====================================================
24
+ /**值更新触发*/
25
+ onValuesChange?: (changedValues: any, values: T) => void;
26
+ /**提交保存 验证成功*/
27
+ onFinish?: (values: T) => void;
28
+ /**提交保存 验证失败*/
29
+ onFinishFailed?: (errorInfo: ValidateErrorEntity<T>) => void;
30
+
31
+ /**
32
+ * 重置字段数据值
33
+ */
34
+ resetFieldsValue = (initial: Partial<T> = {}) => {
35
+ this.formData.value = Object.assign(this.formData.value, initial);
36
+ return this;
37
+ };
38
+
39
+ /**注册一个 formIList 实例*/
40
+ registerFormList = (name: string, itemInstance: Ref<FormListInstanceBase>) => {
41
+ this.formListInstances.set(name, itemInstance);
42
+ return () => {
43
+ this.formListInstances.delete(name);
44
+ };
45
+ };
46
+
47
+ /**注册一个 formItem 实例*/
48
+ registerFormItem = (itemInstance: Ref<FormItemInstanceBase>) => {
49
+ this.formItemInstances.push(itemInstance);
50
+ return () => {
51
+ const instanceItem = toValue(itemInstance);
52
+ this.formItemInstances = this.formItemInstances.filter((ite) => ite !== itemInstance);
53
+ let preserve = this.preserve;
54
+ if (instanceItem?.preserve === false) {
55
+ preserve = instanceItem.preserve;
56
+ }
57
+ const name = `${instanceItem?.name}`;
58
+ const formData = toValue(this.formData);
59
+ // 判断路径是否存在
60
+ if (name && has(formData, name) && !preserve) {
61
+ this.formData.value = set(formData, instanceItem.name, undefined);
62
+ }
63
+ };
64
+ };
65
+
66
+ /**更新字段是否隐藏*/
67
+ updatedFieldHideValue = (value: Record<string, boolean>) => {
68
+ // 字段对应的 form item 进行更新
69
+ const names = Object.keys(value || {});
70
+ names.forEach((key) => {
71
+ this.hideState.value = set(this.hideState.value, key, value[key]);
72
+ });
73
+ return this;
74
+ };
75
+
76
+ /**更新字段value值
77
+ *
78
+ * @param name 字段
79
+ * @param value 字段值
80
+ * @param validateType 校验规则处理
81
+ * @param isOnlySave 仅用于存储
82
+ *
83
+ */
84
+ updatedFieldValue = (name: string, value: any, validateType: 'validate' | 'clear' | 'none' = 'validate') => {
85
+ // 字段对应的 form item 进行更新
86
+ this.formData.value = set(this.formData.value, name, value);
87
+ /**验证数据 */
88
+ if (validateType === 'validate') {
89
+ this.onlyValidate(name);
90
+ } else if (validateType === 'clear') {
91
+ /**清空验证提示信息*/
92
+ const formItemInstance = this.formItemInstances.find((ite) => ite.value.name === name);
93
+ const instanceItem = toValue(formItemInstance);
94
+ const instanceItemRule = toValue(instanceItem?.rule);
95
+ if (instanceItemRule) {
96
+ instanceItemRule?.updatedMessages?.([]);
97
+ }
98
+ }
99
+ return this;
100
+ };
101
+
102
+ /**获取 formList 实例或者集合*/
103
+ getFormListInstance = (name: string) => {
104
+ return this.formListInstances.get(name);
105
+ };
106
+
107
+ /**获取字段值*/
108
+ getFieldValue = (name?: string) => {
109
+ const fromData = toValue(this.formData);
110
+ if (name) {
111
+ if (has(fromData, name)) {
112
+ return get(fromData, name);
113
+ }
114
+ return undefined;
115
+ }
116
+ return fromData;
117
+ };
118
+
119
+ /**获取字段隐藏值*/
120
+ getFieldHideValue = (name?: string) => {
121
+ const hideData = toValue(this.hideState);
122
+ if (name) {
123
+ return get(hideData, name);
124
+ }
125
+ return hideData;
126
+ };
127
+
128
+ /**
129
+ * 只进行验证,没有返回值
130
+ * */
131
+ onlyValidate = async (name: string | string[]) => {
132
+ try {
133
+ /**校验数据*/
134
+ if (Array.isArray(name)) {
135
+ await this.validate(name, false);
136
+ } else {
137
+ await this.validate([name], false);
138
+ }
139
+ } catch (err) {
140
+ console.log(err);
141
+ }
142
+ return this;
143
+ };
144
+
145
+ /**规则验证 ,默认不传递验证所有 */
146
+ validate = (names?: string[], isGetAllData: boolean = true): Promise<T> => {
147
+ return new Promise(async (resolve, reject) => {
148
+ const errorFields: ErrorDataField[] = [];
149
+ const notErrorFields: ErrorDataField[] = [];
150
+
151
+ /**去除 watch 字段*/
152
+ const newFormItemInstances = this.formItemInstances;
153
+ const nameListPath = newFormItemInstances.map((item) => item.value.name);
154
+ const lg = newFormItemInstances.length;
155
+ const isNames = Array.isArray(names) && names.length;
156
+ for (let index = 0; index < lg; index++) {
157
+ const instanceItemRef = newFormItemInstances[index];
158
+ const instanceItem = toValue(instanceItemRef);
159
+ const rule = toValue(instanceItem.rule);
160
+ /**判断实例是否存在 & 是否需要验证规则*/
161
+ if (rule && rule.isValidate()) {
162
+ let isValidate = true;
163
+ if (isNames) {
164
+ /**判断是否存在当前需要验证的项*/
165
+ const findx = names.find((name) => name === instanceItem.name);
166
+ if (!findx) {
167
+ isValidate = false;
168
+ }
169
+ }
170
+ try {
171
+ /**判断是否需要进行验证*/
172
+ if (isValidate) {
173
+ await rule.validate();
174
+ notErrorFields.push({
175
+ errors: [],
176
+ sort: instanceItem.sort,
177
+ name: instanceItem.name,
178
+ });
179
+ }
180
+ } catch (errors: any) {
181
+ if (errors)
182
+ errorFields.push({
183
+ errors,
184
+ sort: instanceItem.sort,
185
+ name: instanceItem.name,
186
+ });
187
+ }
188
+ } else {
189
+ notErrorFields.push({
190
+ errors: [],
191
+ sort: instanceItem.sort,
192
+ name: instanceItem.name,
193
+ });
194
+ }
195
+ }
196
+ /**所有值*/
197
+ const values = isGetAllData ? (cloneByNamePathList(this.getFieldValue(), nameListPath) as T) : ({} as T);
198
+ /**判断是否存在验证失败的*/
199
+ if (errorFields.length) {
200
+ reject({ errorFields, values: values });
201
+ } else {
202
+ resolve(values);
203
+ }
204
+ });
205
+ };
206
+
207
+ /**
208
+ * 提交
209
+ */
210
+ submit = async () => {
211
+ try {
212
+ const result = await this.validate();
213
+ if (result) {
214
+ this?.onFinish?.(result);
215
+ }
216
+ } catch (error: any) {
217
+ this.onFinishFailed?.(error);
218
+ }
219
+ };
220
+ }
@@ -0,0 +1,23 @@
1
+ import { Ref } from 'vue';
2
+ import { FormInstanceBase } from './formInstance';
3
+ export class FormItemBaseInstance {
4
+ /**
5
+ * 顺序
6
+ * @example
7
+ * "0"
8
+ * "0-0"
9
+ * "0-0-0"
10
+ */
11
+ sort?: string;
12
+ /**
13
+ * 字段 ,分割方式与lodash的get和set方法值更新或设置路径一致
14
+ * @example
15
+ * 默认:"name"
16
+ * 嵌套字段:"name.a.doc"
17
+ * 嵌套字段:"name[1].a.doc"
18
+ * 嵌套字段:"name.a[2].doc"
19
+ */
20
+ name: string = '';
21
+ /**表单实例*/
22
+ instance?: Ref<FormInstanceBase>;
23
+ }
@@ -0,0 +1,23 @@
1
+ import { RuleInstanceBase } from './ruleIntsnace';
2
+ import { FormInstanceBase } from './formInstance';
3
+ import { FormItemBaseInstance } from './formItemBaseInstance';
4
+ import { Ref } from 'vue';
5
+ export class FormItemInstanceBase extends FormItemBaseInstance {
6
+ /**父级字段*/
7
+ parentDataField?: string;
8
+ /**通知 只用于校验规则提示 字段 */
9
+ noticeOnlyRuleDataField?: string[];
10
+ htmlFor?: string;
11
+ control?: Ref<any>;
12
+ /**规则*/
13
+ rule?: Ref<RuleInstanceBase>;
14
+ /**是否保护值(不进行表单项组件卸载重置初始值)*/
15
+ preserve?: boolean = true;
16
+ /**触发数据更新之后触发(用于数据联动之类的)*/
17
+ onAfterUpdate?: (
18
+ value: any,
19
+ instance: Ref<FormInstanceBase>,
20
+ instanceAttr: Ref<FormItemInstanceBase>,
21
+ event: any,
22
+ ) => void;
23
+ }
@@ -0,0 +1,108 @@
1
+ import { FormItemBaseInstance } from './formItemBaseInstance';
2
+ import { RuleInstanceBase } from './ruleIntsnace';
3
+ import { FormItemInstanceBase } from './formItemInstance';
4
+ import { Ref, toValue } from 'vue';
5
+
6
+ export class FormListInstanceBase extends FormItemBaseInstance {
7
+ /**规则*/
8
+ rule?: Ref<RuleInstanceBase>;
9
+ /**表单实例*/
10
+ formItemInstance?: Ref<FormItemInstanceBase>;
11
+ /**父级字段*/
12
+ parentDataField?: string;
13
+ /**记录key值*/
14
+ keys: number[] = [];
15
+ /**累加数据,唯一性*/
16
+ id: number = 0;
17
+ /**
18
+ * 初始化
19
+ * @param name 字段
20
+ */
21
+ ctor = (name: string) => {
22
+ this.name = name;
23
+ return this;
24
+ };
25
+
26
+ /**获取值*/
27
+ getLastValue = () => {
28
+ const form = toValue(this.instance);
29
+ const value = form?.getFieldValue?.(this.name);
30
+ /**对值进行处理*/
31
+ const lastValue = Array.isArray(value) ? value : [];
32
+ return lastValue;
33
+ };
34
+
35
+ /**
36
+ * 添加一条
37
+ * @param initialValue 初始值
38
+ * @param unshift 是否加入数组前面
39
+ */
40
+ onAdd = (initialValue: Object = {}, unshift?: boolean) => {
41
+ const form = toValue(this.instance);
42
+ /**获取值*/
43
+ const value = this.getLastValue();
44
+ if (unshift) {
45
+ const listData = [initialValue || {}, ...value];
46
+ this.keys = [this.id, ...this.keys];
47
+ this.id++; // 累加
48
+ form?.updatedFieldValue?.(this.name, listData);
49
+ } else {
50
+ const listData = [...value, initialValue || {}];
51
+ this.keys = [...this.keys, this.id];
52
+ this.id++; // 累加
53
+ form?.updatedFieldValue?.(this.name, listData);
54
+ }
55
+ };
56
+
57
+ /**
58
+ * 删除
59
+ * @param index 删除数据下标
60
+ */
61
+ onDelete = (index: number | number[]) => {
62
+ const form = toValue(this.instance);
63
+ /**获取值*/
64
+ const value = this.getLastValue();
65
+ const newIndexs = Array.isArray(index) ? index : [index];
66
+ this.keys = this.keys.filter((_, index) => !newIndexs.includes(index));
67
+ const listData = value.filter((_, index) => !newIndexs.includes(index));
68
+ form?.updatedFieldValue?.(this.name, listData);
69
+ };
70
+
71
+ /**移动*/
72
+ onMove = (from: number, to: number) => {
73
+ const form = toValue(this.instance);
74
+ /**从那个移动到那个*/
75
+ const newList = this.getLastValue();
76
+ const fromItem = newList[from];
77
+ const toItem = newList[to];
78
+ newList[from] = toItem;
79
+ newList[to] = fromItem;
80
+ form?.updatedFieldValue?.(this.name, [...newList]);
81
+ };
82
+
83
+ /**更新某个item数据*/
84
+ updatedItem = (index: number, item: any) => {
85
+ const form = toValue(this.instance);
86
+ const newList = this.getLastValue();
87
+ const newItem = newList[index];
88
+ newList[index] = { ...newItem, ...item };
89
+ form?.updatedFieldValue?.(this.name, [...newList]);
90
+ };
91
+
92
+ /**获取渲染 list 字段拼接*/
93
+ getFields = () => {
94
+ const values = this.getLastValue();
95
+ return values.map((__, index) => {
96
+ let key = this.keys[index];
97
+ if (key === undefined) {
98
+ this.keys[index] = this.id;
99
+ key = this.keys[index];
100
+ this.id++; // 累加
101
+ }
102
+ return {
103
+ name: index,
104
+ key,
105
+ };
106
+ });
107
+ };
108
+ }
@@ -0,0 +1,5 @@
1
+ export * from './formInstance';
2
+ export * from './formItemInstance';
3
+ export * from './formListInstance';
4
+ export * from './multipleInstance';
5
+ export * from './ruleIntsnace';
@@ -0,0 +1,109 @@
1
+ import type { FormInstanceBase } from './formInstance';
2
+ import { cloneByNamePathList } from '../utils';
3
+ import { ValidateErrorEntity } from '../interface';
4
+ import { Ref, toValue } from 'vue';
5
+
6
+ export class MultipleInstanceBase {
7
+ instanceMap: Map<string, Ref<FormInstanceBase>> = new Map([]);
8
+ /**
9
+ * 注册表单实例
10
+ * @param name 表单名称
11
+ * @param form 表单实例
12
+ */
13
+ ctor = (name: string, form: Ref<FormInstanceBase>) => {
14
+ this.instanceMap.set(name, form);
15
+ return () => {
16
+ this.instanceMap.delete(name);
17
+ };
18
+ };
19
+ /**
20
+ * 获取表单实例
21
+ * @param name 表单名称
22
+ */
23
+ getInstance = (name?: string) => {
24
+ if (name) {
25
+ return this.instanceMap.get(name);
26
+ }
27
+ return this.instanceMap;
28
+ };
29
+
30
+ /**
31
+ * 验证表单规则
32
+ * @param namePath 表单名称(如果不传递表单名称,则验证所有表单)
33
+ *
34
+ * @example
35
+ */
36
+ validate = (namePath?: string | string[] | Record<string, string[]>) => {
37
+ return new Promise(async (resolve, reject) => {
38
+ const listFormErrors: Record<string, ValidateErrorEntity> = {};
39
+ let isSuccess = true;
40
+ let nameKeys: string[] = [];
41
+ let isObject = false;
42
+ if (namePath) {
43
+ if (Array.isArray(namePath)) {
44
+ nameKeys = namePath;
45
+ } else if (Object.prototype.toString.call(namePath) === '[object Object]') {
46
+ isObject = true;
47
+ nameKeys = Object.keys(namePath);
48
+ } else {
49
+ nameKeys = [namePath] as string[];
50
+ }
51
+ } else {
52
+ nameKeys = Array.from(this.instanceMap.keys());
53
+ }
54
+
55
+ const lg = nameKeys.length;
56
+ for (let index = 0; index < lg; index++) {
57
+ const name = nameKeys[index];
58
+ const form = this.instanceMap.get(name);
59
+ const formInstacne = toValue(form);
60
+ try {
61
+ if (formInstacne) {
62
+ const paths = isObject ? (namePath as Record<string, string[]>)[name] : undefined;
63
+ const result = await formInstacne.validate(paths);
64
+ listFormErrors[name] = { errorFields: [], values: result };
65
+ }
66
+ } catch (errs: any) {
67
+ isSuccess = false;
68
+ listFormErrors[name] = errs;
69
+ }
70
+ }
71
+ /**成功抛出数据*/
72
+ if (isSuccess) {
73
+ resolve(listFormErrors);
74
+ } else {
75
+ /**失败抛出数据*/
76
+ reject(listFormErrors);
77
+ }
78
+ });
79
+ };
80
+ /**
81
+ * 获取表单中值
82
+ * @param name 表单名称 (不存在时,获取所有表单值)
83
+ * @param path 字段路径 (不存在的时候直接获取对应表单所有值)
84
+ *
85
+ */
86
+ getFormFieldValue = (name?: string, dataField?: string | string[]) => {
87
+ if (!name) {
88
+ const data: Record<string, unknown> = {};
89
+ this.instanceMap.forEach((form, key) => {
90
+ data[key] = form.value.getFieldValue();
91
+ });
92
+ return data;
93
+ }
94
+ const form = this.instanceMap.get(name);
95
+ const formInstacne = toValue(form);
96
+
97
+ if (formInstacne) {
98
+ if (typeof dataField === 'string') {
99
+ return { [name]: formInstacne.getFieldValue(dataField) };
100
+ }
101
+ if (dataField) {
102
+ const formData = formInstacne.getFieldValue();
103
+ const data = cloneByNamePathList(formData, dataField);
104
+ return { [name]: data };
105
+ }
106
+ }
107
+ return { [name]: {} };
108
+ };
109
+ }
@@ -0,0 +1,89 @@
1
+ import AsyncValidator, { RuleItem } from 'async-validator';
2
+ import { FormInstanceBase } from './formInstance';
3
+ import { MessageType } from '../interface';
4
+ import { Ref, ref, toValue } from 'vue';
5
+
6
+ export class RuleInstanceBase {
7
+ /**
8
+ * 顺序
9
+ * @example
10
+ * "0"
11
+ * "0-0"
12
+ * "0-0-0"
13
+ */
14
+ sort?: string;
15
+ /**表单实例*/
16
+ instance?: Ref<FormInstanceBase<any>>;
17
+ /**
18
+ * 字段 ,分割方式与lodash的get和set方法值更新或设置路径一致
19
+ * @example
20
+ * 默认:"name"
21
+ * 嵌套字段:"name.a.doc"
22
+ * 嵌套字段:"name[1].a.doc"
23
+ * 嵌套字段:"name.a[2].doc"
24
+ */
25
+ name: string = '';
26
+ /**规则*/
27
+ rules: Ref<RuleItem[]> = ref([]);
28
+ /**错误提示内容*/
29
+ messages: Ref<MessageType[] | undefined> = ref([]);
30
+ /**判断是否必填*/
31
+ isRequired = () => {
32
+ const findItem = (toValue(this.rules) || []).find((item) => item?.required);
33
+ return !!findItem;
34
+ };
35
+
36
+ /**判断是否需要验证*/
37
+ isValidate = () => {
38
+ const rules = toValue(this.rules);
39
+ return Array.isArray(rules) && rules.length;
40
+ };
41
+ /**更新提示信息*/
42
+ updatedMessages = (messages?: MessageType[]) => {
43
+ this.messages.value = messages;
44
+ };
45
+
46
+ /**更新规则*/
47
+ updatedRules = (rules: RuleItem[]) => {
48
+ /**更新当前规则*/
49
+ this.rules.value = rules;
50
+ /**当前组件重新渲染*/
51
+ this.updatedMessages?.([]);
52
+ };
53
+
54
+ /**验证规则
55
+ */
56
+ validate = () => {
57
+ return new Promise((resolve, reject) => {
58
+ const rules = toValue(this.rules);
59
+ const form = toValue(this.instance);
60
+ const value = form?.getFieldValue?.(this.name);
61
+ new AsyncValidator({ [this.name]: rules || [] })
62
+ .validate({ [this.name]: value })
63
+ .then((values) => {
64
+ this.updatedMessages([]);
65
+ resolve(values);
66
+ })
67
+ .catch(({ errors }) => {
68
+ if (Array.isArray(errors)) {
69
+ this.updatedMessages(errors);
70
+ reject(errors);
71
+ } else {
72
+ reject();
73
+ }
74
+ });
75
+ });
76
+ };
77
+
78
+ /**获取校验结果*/
79
+ getValidateResult = () => {
80
+ const msg = toValue(this.messages);
81
+ const tip = Array.isArray(msg) ? msg.map((it) => it.message) : '';
82
+ const isInvalid = Array.isArray(tip) ? !!tip.length : !!tip;
83
+
84
+ return {
85
+ tip,
86
+ isInvalid,
87
+ };
88
+ };
89
+ }
@@ -0,0 +1,38 @@
1
+ import { ComputedRef, Ref } from 'vue';
2
+
3
+ export interface MessageType {
4
+ /**信息*/
5
+ message?: string;
6
+ [s: string]: unknown;
7
+ }
8
+
9
+ export interface ErrorDataField {
10
+ /**字段*/
11
+ name: string;
12
+ /**排序*/
13
+ sort?: string;
14
+ /**错误信息*/
15
+ errors: MessageType[];
16
+ }
17
+
18
+ export interface ValidateErrorEntity<Values = any> {
19
+ /*值*/
20
+ values: Values;
21
+ /**错误信息*/
22
+ errorFields: ErrorDataField[];
23
+ }
24
+
25
+ export interface Callbacks<Values = any> {
26
+ /**值更新触发*/
27
+ onValuesChange?: (changedValues: any, values: Values) => void;
28
+ /**提交保存 验证成功*/
29
+ onFinish?: (values: Values) => void;
30
+ /**提交保存 验证失败*/
31
+ onFinishFailed?: (errorInfo: ValidateErrorEntity<Values>) => void;
32
+ }
33
+
34
+ export type ComputedRefBase<T> = ComputedRef<T> | Ref<T>;
35
+
36
+ export type PartialComputedRefs<T> = {
37
+ [K in keyof T]: ComputedRefBase<T[K]>;
38
+ };
@@ -0,0 +1,13 @@
1
+ import { PropertyName } from './interface';
2
+ import { get } from './get';
3
+ import { set } from './set';
4
+
5
+ /**获取路径数据*/
6
+ export function cloneByNamePathList(store: Record<string, any>, namePathList: PropertyName[]): Record<string, any> {
7
+ let newStore = {};
8
+ namePathList.forEach((namePath) => {
9
+ const value = get(store, namePath);
10
+ newStore = set(newStore, namePath, value);
11
+ });
12
+ return newStore;
13
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @description [从lodash中搬了部分需要的代码块](https://www.lodashjs.com/)
3
+ */
4
+ import { castPath, toKey } from './utils';
5
+ import { PropertyPath } from './interface';
6
+
7
+ /**
8
+ * The base implementation of `get` without support for default values.
9
+ *
10
+ * @private
11
+ * @param {Object} object The object to query.
12
+ * @param {Array|string} path The path of the property to get.
13
+ * @returns {*} Returns the resolved value.
14
+ */
15
+ function baseGet(object: any, path: PropertyPath) {
16
+ path = castPath(path, object);
17
+ let index = 0;
18
+ const length = path.length;
19
+
20
+ while (object != null && index < length) {
21
+ object = object[toKey(path[index++])];
22
+ }
23
+ return index && index === length ? object : undefined;
24
+ }
25
+
26
+ /**
27
+ * Gets the value at `path` of `object`. If the resolved value is
28
+ * `undefined`, the `defaultValue` is returned in its place.
29
+ *
30
+ * @since 3.7.0
31
+ * @category Object
32
+ * @param {Object} object The object to query.
33
+ * @param {Array|string} path The path of the property to get.
34
+ * @param {*} [defaultValue] The value returned for `undefined` resolved values.
35
+ * @returns {*} Returns the resolved value.
36
+ * @see has, hasIn, set, unset
37
+ * @example
38
+ *
39
+ * const object = { 'a': [{ 'b': { 'c': 3 } }] }
40
+ *
41
+ * get(object, 'a[0].b.c')
42
+ * // => 3
43
+ *
44
+ * get(object, ['a', '0', 'b', 'c'])
45
+ * // => 3
46
+ *
47
+ * get(object, 'a.b.c', 'default')
48
+ * // => 'default'
49
+ */
50
+ export const get = (object: Object, path: PropertyPath, defaultValue?: any) => {
51
+ const result = object == null ? undefined : baseGet(object, path);
52
+ return result === undefined ? defaultValue : result;
53
+ };
@@ -0,0 +1,4 @@
1
+ export * from './get';
2
+ export * from './set';
3
+ export * from './utils';
4
+ export * from './cloneByNamePathList';
@@ -0,0 +1,4 @@
1
+ export type Many<T> = T | readonly T[];
2
+
3
+ export type PropertyName = string | number | symbol | undefined;
4
+ export type PropertyPath = Many<PropertyName>;