前端爱码士
2022-10-17 9aa2cf3ebff6f3d4087a1080208ec5f3c2c50f33
提交 | 用户 | age
84c9d7 1 import type { ComputedRef, Ref } from 'vue';
2407b3 2 import type { FormProps, FormSchema, FormActionType } from '../types/form';
V 3 import type { NamePath } from 'ant-design-vue/lib/form/interface';
6b594a 4 import { unref, toRaw, nextTick } from 'vue';
a0920d 5 import { isArray, isFunction, isObject, isString, isDef, isNullOrUnDef } from '/@/utils/is';
be3a3e 6 import { deepMerge } from '/@/utils';
2423ae 7 import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper';
3509eb 8 import { dateUtil } from '/@/utils/dateUtil';
be3a3e 9 import { cloneDeep, uniqBy } from 'lodash-es';
4ff1c4 10 import { error } from '/@/utils/log';
84c9d7 11
V 12 interface UseFormActionContext {
13   emit: EmitType;
14   getProps: ComputedRef<FormProps>;
15   getSchema: ComputedRef<FormSchema[]>;
4ff1c4 16   formModel: Recordable;
V 17   defaultValueRef: Ref<Recordable>;
2407b3 18   formElRef: Ref<FormActionType>;
84c9d7 19   schemaRef: Ref<FormSchema[]>;
V 20   handleFormValues: Fn;
21 }
4ff1c4 22 export function useFormEvents({
84c9d7 23   emit,
V 24   getProps,
25   formModel,
26   getSchema,
27   defaultValueRef,
28   formElRef,
29   schemaRef,
30   handleFormValues,
31 }: UseFormActionContext) {
4ff1c4 32   async function resetFields(): Promise<void> {
84c9d7 33     const { resetFunc, submitOnReset } = unref(getProps);
V 34     resetFunc && isFunction(resetFunc) && (await resetFunc());
4ff1c4 35
84c9d7 36     const formEl = unref(formElRef);
V 37     if (!formEl) return;
4ff1c4 38
84c9d7 39     Object.keys(formModel).forEach((key) => {
2423ae 40       const schema = unref(getSchema).find((item) => item.field === key);
W 41       const isInput = schema?.component && defaultValueComponents.includes(schema.component);
d21578 42       const defaultValue = cloneDeep(defaultValueRef.value[key]);
A 43       formModel[key] = isInput ? defaultValue || '' : defaultValue;
84c9d7 44     });
6b594a 45     nextTick(() => clearValidate());
L 46
84c9d7 47     emit('reset', toRaw(formModel));
V 48     submitOnReset && handleSubmit();
49   }
50
51   /**
4ff1c4 52    * @description: Set form value
84c9d7 53    */
ac1a36 54   async function setFieldsValue(values: Recordable): Promise<void> {
84c9d7 55     const fields = unref(getSchema)
V 56       .map((item) => item.field)
57       .filter(Boolean);
1db72c 58
d09e99 59     // key 支持 a.b.c 的嵌套写法
J 60     const delimiter = '.';
61     const nestKeyArray = fields.filter((item) => item.indexOf(delimiter) >= 0);
62
1db72c 63     const validKeys: string[] = [];
84c9d7 64     Object.keys(values).forEach((key) => {
ac1a36 65       const schema = unref(getSchema).find((item) => item.field === key);
V 66       let value = values[key];
67
8f76ef 68       const hasKey = Reflect.has(values, key);
V 69
ac1a36 70       value = handleInputNumberValue(schema?.component, value);
4ff1c4 71       // 0| '' is allow
8f76ef 72       if (hasKey && fields.includes(key)) {
46e087 73         // time type
84c9d7 74         if (itemIsDateType(key)) {
ac1a36 75           if (Array.isArray(value)) {
e689ee 76             const arr: any[] = [];
ac1a36 77             for (const ele of value) {
e689ee 78               arr.push(ele ? dateUtil(ele) : null);
84c9d7 79             }
4ff1c4 80             formModel[key] = arr;
84c9d7 81           } else {
cb3534 82             const { componentProps } = schema || {};
V 83             let _props = componentProps as any;
84             if (typeof componentProps === 'function') {
7c41c8 85               _props = _props({ formModel });
cb3534 86             }
V 87             formModel[key] = value ? (_props?.valueFormat ? value : dateUtil(value)) : null;
84c9d7 88           }
V 89         } else {
ac1a36 90           formModel[key] = value;
84c9d7 91         }
1db72c 92         validKeys.push(key);
d09e99 93       } else {
J 94         nestKeyArray.forEach((nestKey: string) => {
95           try {
96             const value = eval('values' + delimiter + nestKey);
97             if (isDef(value)) {
98               formModel[nestKey] = value;
99               validKeys.push(nestKey);
100             }
101           } catch (e) {
102             // key not exist
103             if (isDef(defaultValueRef.value[nestKey])) {
d21578 104               formModel[nestKey] = cloneDeep(defaultValueRef.value[nestKey]);
d09e99 105             }
J 106           }
107         });
84c9d7 108       }
V 109     });
8d185b 110     validateFields(validKeys).catch((_) => {});
84c9d7 111   }
V 112   /**
46e087 113    * @description: Delete based on field name
84c9d7 114    */
9aa2cf 115   async function removeSchemaByFeild(fields: string | string[]): Promise<void> {
84c9d7 116     const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
38f507 117     if (!fields) {
V 118       return;
119     }
4ff1c4 120
V 121     let fieldList: string[] = isString(fields) ? [fields] : fields;
84c9d7 122     if (isString(fields)) {
V 123       fieldList = [fields];
124     }
125     for (const field of fieldList) {
9aa2cf 126       _removeSchemaByFeild(field, schemaList);
84c9d7 127     }
4ff1c4 128     schemaRef.value = schemaList;
84c9d7 129   }
V 130
131   /**
46e087 132    * @description: Delete based on field name
84c9d7 133    */
9aa2cf 134   function _removeSchemaByFeild(field: string, schemaList: FormSchema[]): void {
84c9d7 135     if (isString(field)) {
V 136       const index = schemaList.findIndex((schema) => schema.field === field);
137       if (index !== -1) {
38f507 138         delete formModel[field];
84c9d7 139         schemaList.splice(index, 1);
V 140       }
141     }
142   }
143
144   /**
46e087 145    * @description: Insert after a certain field, if not insert the last
84c9d7 146    */
4ff1c4 147   async function appendSchemaByField(schema: FormSchema, prefixField?: string, first = false) {
84c9d7 148     const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
V 149
150     const index = schemaList.findIndex((schema) => schema.field === prefixField);
4ff1c4 151
V 152     if (!prefixField || index === -1 || first) {
153       first ? schemaList.unshift(schema) : schemaList.push(schema);
154       schemaRef.value = schemaList;
aaa30f 155       _setDefaultValue(schema);
84c9d7 156       return;
V 157     }
158     if (index !== -1) {
159       schemaList.splice(index + 1, 0, schema);
160     }
aaa30f 161     _setDefaultValue(schema);
L 162
4ff1c4 163     schemaRef.value = schemaList;
84c9d7 164   }
V 165
c639e4 166   async function resetSchema(data: Partial<FormSchema> | Partial<FormSchema>[]) {
Z 167     let updateData: Partial<FormSchema>[] = [];
168     if (isObject(data)) {
169       updateData.push(data as FormSchema);
170     }
171     if (isArray(data)) {
172       updateData = [...data];
173     }
174
47a448 175     const hasField = updateData.every(
56a966 176       (item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
47a448 177     );
c639e4 178
Z 179     if (!hasField) {
180       error(
56a966 181         'All children of the form Schema array that need to be updated must contain the `field` field',
c639e4 182       );
Z 183       return;
184     }
185     schemaRef.value = updateData as FormSchema[];
186   }
187
4ff1c4 188   async function updateSchema(data: Partial<FormSchema> | Partial<FormSchema>[]) {
84c9d7 189     let updateData: Partial<FormSchema>[] = [];
V 190     if (isObject(data)) {
191       updateData.push(data as FormSchema);
192     }
193     if (isArray(data)) {
194       updateData = [...data];
195     }
4ff1c4 196
47a448 197     const hasField = updateData.every(
56a966 198       (item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
47a448 199     );
4ff1c4 200
84c9d7 201     if (!hasField) {
4ff1c4 202       error(
56a966 203         'All children of the form Schema array that need to be updated must contain the `field` field',
4ff1c4 204       );
116a1f 205       return;
84c9d7 206     }
V 207     const schema: FormSchema[] = [];
208     updateData.forEach((item) => {
209       unref(getSchema).forEach((val) => {
210         if (val.field === item.field) {
1db72c 211           const newSchema = deepMerge(val, item);
V 212           schema.push(newSchema as FormSchema);
84c9d7 213         } else {
V 214           schema.push(val);
215         }
216       });
217     });
aaa30f 218     _setDefaultValue(schema);
L 219
be3a3e 220     schemaRef.value = uniqBy(schema, 'field');
84c9d7 221   }
V 222
aaa30f 223   function _setDefaultValue(data: FormSchema | FormSchema[]) {
L 224     let schemas: FormSchema[] = [];
225     if (isObject(data)) {
226       schemas.push(data as FormSchema);
227     }
228     if (isArray(data)) {
229       schemas = [...data];
230     }
231
232     const obj: Recordable = {};
3cc72d 233     const currentFieldsValue = getFieldsValue();
aaa30f 234     schemas.forEach((item) => {
L 235       if (
236         item.component != 'Divider' &&
237         Reflect.has(item, 'field') &&
238         item.field &&
3cc72d 239         !isNullOrUnDef(item.defaultValue) &&
T 240         !(item.field in currentFieldsValue)
aaa30f 241       ) {
L 242         obj[item.field] = item.defaultValue;
243       }
244     });
245     setFieldsValue(obj);
246   }
247
4ff1c4 248   function getFieldsValue(): Recordable {
84c9d7 249     const formEl = unref(formElRef);
4ff1c4 250     if (!formEl) return {};
84c9d7 251     return handleFormValues(toRaw(unref(formModel)));
V 252   }
253
254   /**
46e087 255    * @description: Is it time
84c9d7 256    */
V 257   function itemIsDateType(key: string) {
258     return unref(getSchema).some((item) => {
4ff1c4 259       return item.field === key ? dateItemType.includes(item.component) : false;
84c9d7 260     });
V 261   }
262
4ff1c4 263   async function validateFields(nameList?: NamePath[] | undefined) {
a305e5 264     return unref(formElRef)?.validateFields(nameList);
84c9d7 265   }
43a45b 266
4ff1c4 267   async function validate(nameList?: NamePath[] | undefined) {
a305e5 268     return await unref(formElRef)?.validate(nameList);
84c9d7 269   }
V 270
4ff1c4 271   async function clearValidate(name?: string | string[]) {
V 272     await unref(formElRef)?.clearValidate(name);
273   }
274
275   async function scrollToField(name: NamePath, options?: ScrollOptions | undefined) {
276     await unref(formElRef)?.scrollToField(name, options);
84c9d7 277   }
V 278
279   /**
46e087 280    * @description: Form submission
84c9d7 281    */
V 282   async function handleSubmit(e?: Event): Promise<void> {
283     e && e.preventDefault();
284     const { submitFunc } = unref(getProps);
285     if (submitFunc && isFunction(submitFunc)) {
286       await submitFunc();
287       return;
288     }
289     const formEl = unref(formElRef);
290     if (!formEl) return;
291     try {
94bf85 292       const values = await validate();
84c9d7 293       const res = handleFormValues(values);
V 294       emit('submit', res);
a248e2 295     } catch (error: any) {
9a21b8 296       throw new Error(error);
LY 297     }
84c9d7 298   }
V 299
300   return {
301     handleSubmit,
302     clearValidate,
303     validate,
304     validateFields,
305     getFieldsValue,
306     updateSchema,
c639e4 307     resetSchema,
84c9d7 308     appendSchemaByField,
9aa2cf 309     removeSchemaByFeild,
84c9d7 310     resetFields,
V 311     setFieldsValue,
4ff1c4 312     scrollToField,
84c9d7 313   };
V 314 }