UNPKG

xph-form

Version:

This is a configurable form component that supports React

228 lines (227 loc) 8.37 kB
import { isObject, isArray, isFunction, isString, set } from "lodash-es"; import dayjs from "dayjs"; import { dateComponents } from "../helper"; import { isComponentFormItemProps, isRenderFormItemProps } from "../types"; /** * @description 构建值数组 * @param field - '[key1, key2, key3] * @param values - { key1: 'value1', key2: 'value2', key3: 'value3' } * @returns ['value1', 'value2', 'value3'] */ function tryConstructArray(field, values = {}) { const pattern = /^\[(.+)\]$/; if (pattern.test(field)) { const match = field.match(pattern); if (match && match[1]) { const keys = match[1].split(","); if (!keys.length) { return undefined; } const result = []; keys.forEach((k, index) => { set(result, index, values[k.trim()]); }); return result.filter(Boolean).length ? result : undefined; } } } /** * @description 构建值对象 * @param field - '{key1, key2, key3}' * @param values - { key1: 'value1', key2: 'value2', key3: 'value3' } * @returns { key1: 'value1', key2: 'value2', key3: 'value3' } */ function tryConstructObject(field, values = {}) { const pattern = /^\{(.+)\}$/; if (pattern.test(field)) { const match = field.match(pattern); if (match && match[1]) { const keys = match[1].split(","); if (!keys.length) { return; } const result = {}; keys.forEach((k) => { set(result, k.trim(), values[k.trim()]); }); return Object.values(result).filter(Boolean).length ? result : undefined; } } } /** * @desription deconstruct array-link key. This method will mutate the target. */ function tryDeconstructArray(key, value, target) { const pattern = /^\[(.+)\]$/; if (pattern.test(key)) { const match = key.match(pattern); if (match && match[1]) { const keys = match[1].split(","); value = Array.isArray(value) ? value : [value]; keys.forEach((k, index) => { set(target, k.trim(), value[index]); }); return true; } } } /** * @desription deconstruct object-link key. This method will mutate the target. */ function tryDeconstructObject(key, value, target) { const pattern = /^\{(.+)\}$/; if (pattern.test(key)) { const match = key.match(pattern); if (match && match[1]) { const keys = match[1].split(","); value = isObject(value) ? value : {}; keys.forEach((k) => { set(target, k.trim(), value[k.trim()]); }); return true; } } } /** * @description Processing time interval parameters */ function handleRangeTimeValue(values, formProps) { const fieldMapToTime = formProps.fieldMapToTime; if (!fieldMapToTime || !Array.isArray(fieldMapToTime)) { return values; } for (const [field, [startTimeKey, endTimeKey], format = "YYYY-MM-DD",] of fieldMapToTime) { if (!field || !startTimeKey || !endTimeKey) { continue; } // If the value to be converted is empty, remove the field if (!values[field]) { Reflect.deleteProperty(values, field); continue; } const [startTime, endTime] = values[field]; const [startTimeFormat, endTimeFormat] = Array.isArray(format) ? format : [format, format]; values[startTimeKey] = dayjs(startTime).format(startTimeFormat); values[endTimeKey] = dayjs(endTime).format(endTimeFormat); Reflect.deleteProperty(values, field); } return values; } const useFormValues = (formItems, formProps, formItemRefs) => { const allItems = formItems.filter((item) => item.name); /** 处理渲染时的值 */ const handleFormatRenderValues = (values) => { const renderValues = {}; const validKeys = []; allItems.forEach((item) => { const hasKey = Reflect.has(values, item.name); // 当前name是`{}` || `[]`嵌套写法时,获取其值 const constructValue = tryConstructArray(item.name, values) || tryConstructObject(item.name, values); // values中有值 || (当前name是`{}` || `[]`嵌套写法时且有值时) if (hasKey || !!constructValue) { const fieldValue = constructValue || values[item.name]; if (isComponentFormItemProps(item)) { /** 时间类型组件需处理一下 */ if (dateComponents.includes(item.component)) { if (isArray(fieldValue)) { const arr = []; for (const ele of fieldValue) { arr.push(ele ? dayjs(ele) : null); } renderValues[item.name] = arr; } else { renderValues[item.name] = fieldValue ? dayjs(fieldValue) : null; } validKeys.push(item.name); } else { renderValues[item.name] = fieldValue; validKeys.push(item.name); } } if (isRenderFormItemProps(item)) { renderValues[item.name] = fieldValue; validKeys.push(item.name); } } // else { // try { // // a.b.c 的嵌套写法 // const hasDelimiter = item.name.includes(`.`); // if (hasDelimiter) { // const value = item.name // .split(".") // .reduce((out, key) => out[key], values); // if (typeof value !== "undefined") { // renderValues[item.name] = value; // validKeys.push(item.name); // } // } // } catch (e) { // // key not exist // } // } }); return { renderValues, validKeys, }; }; /** 处理返回的值 */ const handleFormatReturnValues = (values) => { if (!isObject(values)) { return {}; } const res = {}; for (const item of Object.entries(values)) { let [, value] = item; const [key] = item; if (!key || isFunction(value)) { continue; } // transformDateFunc是全局时间处理函数,formItem的componentProps中的valueFormat优先级最高 const { transformDateFunc } = formProps; const componentProps = formItemRefs.current?.get(key)?.current?.componentProps; const valueFormat = componentProps?.valueFormat; // 数组也会进来这里 if (isObject(value)) { const objValue = value; // day类型 if (objValue.format) { value = transformDateFunc?.(objValue, valueFormat); } } if (isArray(value) && value[0]?.format && value[1]?.format) { value = value.map((valueItem) => transformDateFunc?.(valueItem, valueFormat)); } // Remove spaces if (isString(value)) { // remove params from URL if (value === "") { value = undefined; } else { value = value.trim(); } } // if ( // !tryDeconstructArray(key, value, res) && // !tryDeconstructObject(key, value, res) // ) { // // 没有解构成功的,按原样赋值 // res[key] = value; // } res[key] = value; } return handleRangeTimeValue(res, formProps); }; return { handleFormatRenderValues, handleFormatReturnValues, }; }; export default useFormValues;