/* eslint-disable prefer-destructuring */ import * as React from 'react'; import { useEffect, useMemo, useState, useCallback, } from 'react'; import * as moment from "moment"; import { FastForm, } from 'components/ui'; import Action from 'components/basic/Action'; import { Component } from 'components/types'; import { App } from 'utils/types'; import { setDefaultValue } from 'utils/tool'; import { isArray } from 'utils/isType'; import { FormTypes } from './types'; const useForm = (props: FormTypes.FormProps) => { const { loaderUuid, config, handle, compRef, dict, } = props; const { uuid, forms, action = [], // ajax, } = config; // 生成表单初始值 const initialValues = useMemo(() => { const defaultData = {}; for (let i = 0, len = forms.length; i < len; i += 1) { const item = forms[i]; const { key, type, defaultValue } = item; if (type === 'multuploadimage') { defaultData[key] = ((defaultValue as string[]) || []) .map((_item: string) => ({ url: _item })); } else { defaultData[key] = setDefaultValue(defaultValue); } } return defaultData; }, [forms]); const [formInstance] = FastForm.useForm(); const [values, setValues] = useState(initialValues); const [formList, setFormList] = useState(forms); // 格式化输出数据 const formatData = (rawData: App.Dict) => { const newData: App.Dict = {}; for (let i = 0, len = forms.length; i < len; i += 1) { const item = forms[i]; const { notSubmit, key, type, exportFormat, ajaxKey, notSwitchArrToStr, switchArrToStrSeparator = ",", keys, } = item; if (!notSubmit && !keys) { if (isArray(rawData[key]) && !notSwitchArrToStr) { newData[ajaxKey || key] = rawData[key].join(switchArrToStrSeparator); } else { newData[ajaxKey || key] = rawData[key]; } if (type === "multuploadimage") { newData[key] = rawData[key] .map((_item: any) => _item.url) .join(switchArrToStrSeparator); } if (exportFormat === "expand") { if (rawData[key]) { Object.keys(rawData[key]).forEach((childKey: string) => { newData[childKey] = rawData[key][childKey]; }); delete newData[key]; } } if (exportFormat === "json2Str") { newData[key] = JSON.stringify(rawData[key]); } } if (keys?.length) { newData[keys[0]] = rawData[key] ? rawData[key][0] : ""; newData[keys[1]] = rawData[key] ? rawData[key][1] : ""; // delete rawData[key]; } } return newData; }; // 格式化输入数据 const formatImportData = (rawData: App.Dict) => { const newData = {}; for (let i = 0, len = forms.length; i < len; i += 1) { const item = forms[i]; const { key, resKey, defaultValue, dataSrc, importFormat, format, keys } = item; if (dataSrc === "default") { newData[key] = defaultValue; } else { newData[key] = rawData[resKey || key]; } // importFormat 格式化 if (importFormat === "number") { newData[key] = Number(newData[key]); } else if (importFormat === "string") { newData[key] = newData[key].toString(); } else if (importFormat === "json2Str") { newData[key] = JSON.stringify(newData[key]); } else if (importFormat === "str2Json") { newData[key] = JSON.parse(newData[key]); } else if (importFormat === "str2arr") { newData[key] = newData[key] ? newData[key].split(",") : []; } else if (importFormat === "time") { newData[key] = newData[key] ? moment(newData[key]).format(format) : ""; } if (keys?.length) { newData[key] = [rawData[keys[0]], rawData[keys[1]]]; newData[keys[0]] = rawData[keys[0]]; newData[keys[1]] = rawData[keys[1]]; } } return newData; }; // 获取表单详情 const handleFetchData = useCallback((data: App.Dict) => { const formatedData = formatImportData(data); setValues(formatedData); formInstance.setFieldsValue(formatedData); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // 重置表单 const resetHandler = () => { setValues(initialValues); }; // 更新form列表 const updateFormList = () => { const newForms = []; for (let i = 0, len = forms.length; i < len; i += 1) { const item = forms[i]; const { interact } = item; if (interact) { const { type, trigger, triggerKey } = interact; if (trigger === "contain") { const { triggerValue = [] } = interact; if (type === "show") { if (isArray(triggerKey)) { const isShow = (triggerKey as string[]).every((triggerKeyItem: string, index: number) => { return ( triggerValue[index].includes(values[triggerKeyItem as string]) || (values[triggerKeyItem] === undefined && triggerValue[index].includes("undefined")) ) }); if (isShow) { newForms.push(item); } } else { if ( triggerValue.includes(values[triggerKey as string]) || (values[triggerKey as string] === undefined && triggerValue.includes("undefined")) ) { newForms.push(item); } } } else if (type === "disabled") { if (triggerValue.includes(values[triggerKey as string])) { newForms.push({ ...item, notModify: true }); } else { newForms.push(item); } } } else if (trigger === "notContain") { const { triggerValue = [] } = interact; if (type === "show") { if (isArray(triggerKey)) { const isShow = (triggerKey as string[]).every((triggerKeyItem: string, index: number) => { return ( !triggerValue[index].includes(values[triggerKeyItem as string]) && !( values[triggerKeyItem] === undefined && triggerValue[index].includes("undefined") ) ) }); if (isShow) { newForms.push(item); } } else { if ( !triggerValue.includes(values[triggerKey as string]) && !( values[triggerKey as string] === undefined && (triggerValue as string[]).includes("undefined") ) ) { newForms.push(item); } } } else if (type === "disabled") { if (!triggerValue.includes(values[triggerKey as string])) { newForms.push({ ...item, notModify: true }); } else { newForms.push(item); } } } else { newForms.push(item); } } else { newForms.push(item); } } setFormList(newForms); }; useEffect(updateFormList, [forms, values]); // 生成行为按钮 const createActionBtns = ( actionList: Component.Business.Action[], data?: App.Dict ) => actionList.map((actionItem: Component.Business.Action) => { const { type } = actionItem; let handleActionClick = null; let bindActionClick = null; let formatedData = data; if (type === Component.Business.TriggerType.reset) { handleActionClick = resetHandler; } if (type === Component.Business.TriggerType.submit) { bindActionClick = () => formInstance.validateFields(); formatedData = formatData(values); } return ( ); }); // 向父组件暴露实例方法 const getInstance = () => { compRef.current = { ...compRef.current, [uuid]: { fetchData: handleFetchData, }, }; }; // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(getInstance, []); return { formList, dict, actionList: action, formInstance, initialValues, values, setValues, createActionBtns, }; }; export default useForm;