useFormEvents.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import type { ComputedRef, Ref } from 'vue';
  2. import type { FormProps, FormSchema, FormActionType } from '../types/form';
  3. import type { NamePath } from 'ant-design-vue/lib/form/interface';
  4. import { unref, toRaw } from 'vue';
  5. import { isArray, isFunction, isObject, isString } from '/@/utils/is';
  6. import { deepMerge } from '/@/utils';
  7. import { dateItemType, handleInputNumberValue } from '../helper';
  8. import { dateUtil } from '/@/utils/dateUtil';
  9. import { cloneDeep, uniqBy } from 'lodash-es';
  10. import { error } from '/@/utils/log';
  11. interface UseFormActionContext {
  12. emit: EmitType;
  13. getProps: ComputedRef<FormProps>;
  14. getSchema: ComputedRef<FormSchema[]>;
  15. formModel: Recordable;
  16. defaultValueRef: Ref<Recordable>;
  17. formElRef: Ref<FormActionType>;
  18. schemaRef: Ref<FormSchema[]>;
  19. handleFormValues: Fn;
  20. }
  21. export function useFormEvents({
  22. emit,
  23. getProps,
  24. formModel,
  25. getSchema,
  26. defaultValueRef,
  27. formElRef,
  28. schemaRef,
  29. handleFormValues,
  30. }: UseFormActionContext) {
  31. async function resetFields(): Promise<void> {
  32. const { resetFunc, submitOnReset } = unref(getProps);
  33. resetFunc && isFunction(resetFunc) && (await resetFunc());
  34. const formEl = unref(formElRef);
  35. if (!formEl) return;
  36. Object.keys(formModel).forEach((key) => {
  37. formModel[key] = defaultValueRef.value[key];
  38. });
  39. clearValidate();
  40. emit('reset', toRaw(formModel));
  41. submitOnReset && handleSubmit();
  42. }
  43. /**
  44. * @description: Set form value
  45. */
  46. async function setFieldsValue(values: Recordable): Promise<void> {
  47. const fields = unref(getSchema)
  48. .map((item) => item.field)
  49. .filter(Boolean);
  50. const validKeys: string[] = [];
  51. Object.keys(values).forEach((key) => {
  52. const schema = unref(getSchema).find((item) => item.field === key);
  53. let value = values[key];
  54. const hasKey = Reflect.has(values, key);
  55. value = handleInputNumberValue(schema?.component, value);
  56. // 0| '' is allow
  57. if (hasKey && fields.includes(key)) {
  58. // time type
  59. if (itemIsDateType(key)) {
  60. if (Array.isArray(value)) {
  61. const arr: any[] = [];
  62. for (const ele of value) {
  63. arr.push(ele ? dateUtil(ele) : null);
  64. }
  65. formModel[key] = arr;
  66. } else {
  67. const { componentProps } = schema || {};
  68. let _props = componentProps as any;
  69. if (typeof componentProps === 'function') {
  70. _props = _props({ formModel });
  71. }
  72. formModel[key] = value ? (_props?.valueFormat ? value : dateUtil(value)) : null;
  73. }
  74. } else {
  75. formModel[key] = value;
  76. }
  77. validKeys.push(key);
  78. }
  79. });
  80. validateFields(validKeys).catch((_) => {});
  81. }
  82. /**
  83. * @description: Delete based on field name
  84. */
  85. async function removeSchemaByFiled(fields: string | string[]): Promise<void> {
  86. const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
  87. if (!fields) {
  88. return;
  89. }
  90. let fieldList: string[] = isString(fields) ? [fields] : fields;
  91. if (isString(fields)) {
  92. fieldList = [fields];
  93. }
  94. for (const field of fieldList) {
  95. _removeSchemaByFiled(field, schemaList);
  96. }
  97. schemaRef.value = schemaList;
  98. }
  99. /**
  100. * @description: Delete based on field name
  101. */
  102. function _removeSchemaByFiled(field: string, schemaList: FormSchema[]): void {
  103. if (isString(field)) {
  104. const index = schemaList.findIndex((schema) => schema.field === field);
  105. if (index !== -1) {
  106. delete formModel[field];
  107. schemaList.splice(index, 1);
  108. }
  109. }
  110. }
  111. /**
  112. * @description: Insert after a certain field, if not insert the last
  113. */
  114. async function appendSchemaByField(schema: FormSchema, prefixField?: string, first = false) {
  115. const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
  116. const index = schemaList.findIndex((schema) => schema.field === prefixField);
  117. const hasInList = schemaList.some((item) => item.field === prefixField || schema.field);
  118. if (!hasInList) return;
  119. if (!prefixField || index === -1 || first) {
  120. first ? schemaList.unshift(schema) : schemaList.push(schema);
  121. schemaRef.value = schemaList;
  122. return;
  123. }
  124. if (index !== -1) {
  125. schemaList.splice(index + 1, 0, schema);
  126. }
  127. schemaRef.value = schemaList;
  128. }
  129. async function resetSchema(data: Partial<FormSchema> | Partial<FormSchema>[]) {
  130. let updateData: Partial<FormSchema>[] = [];
  131. if (isObject(data)) {
  132. updateData.push(data as FormSchema);
  133. }
  134. if (isArray(data)) {
  135. updateData = [...data];
  136. }
  137. const hasField = updateData.every(
  138. (item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
  139. );
  140. if (!hasField) {
  141. error(
  142. 'All children of the form Schema array that need to be updated must contain the `field` field',
  143. );
  144. return;
  145. }
  146. schemaRef.value = updateData as FormSchema[];
  147. }
  148. async function updateSchema(data: Partial<FormSchema> | Partial<FormSchema>[]) {
  149. let updateData: Partial<FormSchema>[] = [];
  150. if (isObject(data)) {
  151. updateData.push(data as FormSchema);
  152. }
  153. if (isArray(data)) {
  154. updateData = [...data];
  155. }
  156. const hasField = updateData.every(
  157. (item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
  158. );
  159. if (!hasField) {
  160. error(
  161. 'All children of the form Schema array that need to be updated must contain the `field` field',
  162. );
  163. return;
  164. }
  165. const schema: FormSchema[] = [];
  166. updateData.forEach((item) => {
  167. unref(getSchema).forEach((val) => {
  168. if (val.field === item.field) {
  169. const newSchema = deepMerge(val, item);
  170. schema.push(newSchema as FormSchema);
  171. } else {
  172. schema.push(val);
  173. }
  174. });
  175. });
  176. schemaRef.value = uniqBy(schema, 'field');
  177. }
  178. function getFieldsValue(): Recordable {
  179. const formEl = unref(formElRef);
  180. if (!formEl) return {};
  181. return handleFormValues(toRaw(unref(formModel)));
  182. }
  183. /**
  184. * @description: Is it time
  185. */
  186. function itemIsDateType(key: string) {
  187. return unref(getSchema).some((item) => {
  188. return item.field === key ? dateItemType.includes(item.component) : false;
  189. });
  190. }
  191. async function validateFields(nameList?: NamePath[] | undefined) {
  192. return unref(formElRef)?.validateFields(nameList);
  193. }
  194. async function validate(nameList?: NamePath[] | undefined) {
  195. return await unref(formElRef)?.validate(nameList);
  196. }
  197. async function clearValidate(name?: string | string[]) {
  198. await unref(formElRef)?.clearValidate(name);
  199. }
  200. async function scrollToField(name: NamePath, options?: ScrollOptions | undefined) {
  201. await unref(formElRef)?.scrollToField(name, options);
  202. }
  203. /**
  204. * @description: Form submission
  205. */
  206. async function handleSubmit(e?: Event): Promise<void> {
  207. e && e.preventDefault();
  208. const { submitFunc } = unref(getProps);
  209. if (submitFunc && isFunction(submitFunc)) {
  210. await submitFunc();
  211. return;
  212. }
  213. const formEl = unref(formElRef);
  214. if (!formEl) return;
  215. try {
  216. const values = await validate();
  217. const res = handleFormValues(values);
  218. emit('submit', res);
  219. } catch (error: any) {
  220. throw new Error(error);
  221. }
  222. }
  223. return {
  224. handleSubmit,
  225. clearValidate,
  226. validate,
  227. validateFields,
  228. getFieldsValue,
  229. updateSchema,
  230. resetSchema,
  231. appendSchemaByField,
  232. removeSchemaByFiled,
  233. resetFields,
  234. setFieldsValue,
  235. scrollToField,
  236. };
  237. }