feat: vben-form添加arrayToStringFields属性 (#5957)
* feat: vben-form添加arrayToStringFields属性 * feat: 修改handleArrayToStringFields和handleStringToArrayFields中嵌套数组格式的处理不一致 --------- Co-authored-by: 米山 <17726957223@189.cn>
This commit is contained in:
parent
fcdc1a1602
commit
d864085c13
@ -295,6 +295,7 @@ export class FormApi {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
const filteredFields = fieldMergeFn(fields, form.values);
|
const filteredFields = fieldMergeFn(fields, form.values);
|
||||||
|
this.handleStringToArrayFields(filteredFields);
|
||||||
form.setValues(filteredFields, shouldValidate);
|
form.setValues(filteredFields, shouldValidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,6 +305,7 @@ export class FormApi {
|
|||||||
const form = await this.getForm();
|
const form = await this.getForm();
|
||||||
await form.submitForm();
|
await form.submitForm();
|
||||||
const rawValues = toRaw(await this.getValues());
|
const rawValues = toRaw(await this.getValues());
|
||||||
|
this.handleArrayToStringFields(rawValues);
|
||||||
await this.state?.handleSubmit?.(rawValues);
|
await this.state?.handleSubmit?.(rawValues);
|
||||||
|
|
||||||
return rawValues;
|
return rawValues;
|
||||||
@ -392,10 +394,53 @@ export class FormApi {
|
|||||||
return this.form;
|
return this.form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleArrayToStringFields = (originValues: Record<string, any>) => {
|
||||||
|
const arrayToStringFields = this.state?.arrayToStringFields;
|
||||||
|
if (!arrayToStringFields || !Array.isArray(arrayToStringFields)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const processFields = (fields: string[], separator: string = ',') => {
|
||||||
|
this.processFields(fields, separator, originValues, (value, sep) =>
|
||||||
|
Array.isArray(value) ? value.join(sep) : value,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理简单数组格式 ['field1', 'field2', ';'] 或 ['field1', 'field2']
|
||||||
|
if (arrayToStringFields.every((item) => typeof item === 'string')) {
|
||||||
|
const lastItem =
|
||||||
|
arrayToStringFields[arrayToStringFields.length - 1] || '';
|
||||||
|
const fields =
|
||||||
|
lastItem.length === 1
|
||||||
|
? arrayToStringFields.slice(0, -1)
|
||||||
|
: arrayToStringFields;
|
||||||
|
const separator = lastItem.length === 1 ? lastItem : ',';
|
||||||
|
processFields(fields, separator);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理嵌套数组格式 [['field1'], ';']
|
||||||
|
arrayToStringFields.forEach((fieldConfig) => {
|
||||||
|
if (Array.isArray(fieldConfig)) {
|
||||||
|
const [fields, separator = ','] = fieldConfig;
|
||||||
|
// 根据类型定义,fields 应该始终是字符串数组
|
||||||
|
if (!Array.isArray(fields)) {
|
||||||
|
console.warn(
|
||||||
|
`Invalid field configuration: fields should be an array of strings, got ${typeof fields}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
processFields(fields, separator);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
private handleRangeTimeValue = (originValues: Record<string, any>) => {
|
private handleRangeTimeValue = (originValues: Record<string, any>) => {
|
||||||
const values = { ...originValues };
|
const values = { ...originValues };
|
||||||
const fieldMappingTime = this.state?.fieldMappingTime;
|
const fieldMappingTime = this.state?.fieldMappingTime;
|
||||||
|
|
||||||
|
this.handleStringToArrayFields(values);
|
||||||
|
|
||||||
if (!fieldMappingTime || !Array.isArray(fieldMappingTime)) {
|
if (!fieldMappingTime || !Array.isArray(fieldMappingTime)) {
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
@ -441,6 +486,80 @@ export class FormApi {
|
|||||||
return values;
|
return values;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private handleStringToArrayFields = (originValues: Record<string, any>) => {
|
||||||
|
const arrayToStringFields = this.state?.arrayToStringFields;
|
||||||
|
if (!arrayToStringFields || !Array.isArray(arrayToStringFields)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const processFields = (fields: string[], separator: string = ',') => {
|
||||||
|
this.processFields(fields, separator, originValues, (value, sep) => {
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
// 处理空字符串的情况
|
||||||
|
if (value === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
// 处理复杂分隔符的情况
|
||||||
|
const escapedSeparator = sep.replaceAll(
|
||||||
|
/[.*+?^${}()|[\]\\]/g,
|
||||||
|
String.raw`\$&`,
|
||||||
|
);
|
||||||
|
return value.split(new RegExp(escapedSeparator));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理简单数组格式 ['field1', 'field2', ';'] 或 ['field1', 'field2']
|
||||||
|
if (arrayToStringFields.every((item) => typeof item === 'string')) {
|
||||||
|
const lastItem =
|
||||||
|
arrayToStringFields[arrayToStringFields.length - 1] || '';
|
||||||
|
const fields =
|
||||||
|
lastItem.length === 1
|
||||||
|
? arrayToStringFields.slice(0, -1)
|
||||||
|
: arrayToStringFields;
|
||||||
|
const separator = lastItem.length === 1 ? lastItem : ',';
|
||||||
|
processFields(fields, separator);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理嵌套数组格式 [['field1'], ';']
|
||||||
|
arrayToStringFields.forEach((fieldConfig) => {
|
||||||
|
if (Array.isArray(fieldConfig)) {
|
||||||
|
const [fields, separator = ','] = fieldConfig;
|
||||||
|
if (Array.isArray(fields)) {
|
||||||
|
processFields(fields, separator);
|
||||||
|
} else if (typeof originValues[fields] === 'string') {
|
||||||
|
const value = originValues[fields];
|
||||||
|
if (value === '') {
|
||||||
|
originValues[fields] = [];
|
||||||
|
} else {
|
||||||
|
const escapedSeparator = separator.replaceAll(
|
||||||
|
/[.*+?^${}()|[\]\\]/g,
|
||||||
|
String.raw`\$&`,
|
||||||
|
);
|
||||||
|
originValues[fields] = value.split(new RegExp(escapedSeparator));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private processFields = (
|
||||||
|
fields: string[],
|
||||||
|
separator: string,
|
||||||
|
originValues: Record<string, any>,
|
||||||
|
transformFn: (value: any, separator: string) => any,
|
||||||
|
) => {
|
||||||
|
fields.forEach((field) => {
|
||||||
|
const value = originValues[field];
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
originValues[field] = transformFn(value, separator);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
private updateState() {
|
private updateState() {
|
||||||
const currentSchema = this.state?.schema ?? [];
|
const currentSchema = this.state?.schema ?? [];
|
||||||
const prevSchema = this.prevState?.schema ?? [];
|
const prevSchema = this.prevState?.schema ?? [];
|
||||||
|
@ -232,6 +232,12 @@ export type FieldMappingTime = [
|
|||||||
)?,
|
)?,
|
||||||
][];
|
][];
|
||||||
|
|
||||||
|
export type ArrayToStringFields = Array<
|
||||||
|
| [string[], string?] // 嵌套数组格式,可选分隔符
|
||||||
|
| string // 单个字段,使用默认分隔符
|
||||||
|
| string[] // 简单数组格式,最后一个元素可以是分隔符
|
||||||
|
>;
|
||||||
|
|
||||||
export interface FormSchema<
|
export interface FormSchema<
|
||||||
T extends BaseFormComponentType = BaseFormComponentType,
|
T extends BaseFormComponentType = BaseFormComponentType,
|
||||||
> extends FormCommonConfig {
|
> extends FormCommonConfig {
|
||||||
@ -266,6 +272,10 @@ export interface FormFieldProps extends FormSchema {
|
|||||||
export interface FormRenderProps<
|
export interface FormRenderProps<
|
||||||
T extends BaseFormComponentType = BaseFormComponentType,
|
T extends BaseFormComponentType = BaseFormComponentType,
|
||||||
> {
|
> {
|
||||||
|
/**
|
||||||
|
* 表单字段数组映射字符串配置 默认使用","
|
||||||
|
*/
|
||||||
|
arrayToStringFields?: ArrayToStringFields;
|
||||||
/**
|
/**
|
||||||
* 是否展开,在showCollapseButton=true下生效
|
* 是否展开,在showCollapseButton=true下生效
|
||||||
*/
|
*/
|
||||||
@ -296,6 +306,10 @@ export interface FormRenderProps<
|
|||||||
* 组件集合
|
* 组件集合
|
||||||
*/
|
*/
|
||||||
componentMap: Record<BaseFormComponentType, Component>;
|
componentMap: Record<BaseFormComponentType, Component>;
|
||||||
|
/**
|
||||||
|
* 表单字段映射到时间格式
|
||||||
|
*/
|
||||||
|
fieldMappingTime?: FieldMappingTime;
|
||||||
/**
|
/**
|
||||||
* 表单实例
|
* 表单实例
|
||||||
*/
|
*/
|
||||||
@ -308,10 +322,15 @@ export interface FormRenderProps<
|
|||||||
* 表单定义
|
* 表单定义
|
||||||
*/
|
*/
|
||||||
schema?: FormSchema<T>[];
|
schema?: FormSchema<T>[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示展开/折叠
|
* 是否显示展开/折叠
|
||||||
*/
|
*/
|
||||||
showCollapseButton?: boolean;
|
showCollapseButton?: boolean;
|
||||||
|
/**
|
||||||
|
* 格式化日期
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表单栅格布局
|
* 表单栅格布局
|
||||||
* @default "grid-cols-1"
|
* @default "grid-cols-1"
|
||||||
@ -339,6 +358,11 @@ export interface VbenFormProps<
|
|||||||
* 表单操作区域class
|
* 表单操作区域class
|
||||||
*/
|
*/
|
||||||
actionWrapperClass?: ClassType;
|
actionWrapperClass?: ClassType;
|
||||||
|
/**
|
||||||
|
* 表单字段数组映射字符串配置 默认使用","
|
||||||
|
*/
|
||||||
|
arrayToStringFields?: ArrayToStringFields;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表单字段映射
|
* 表单字段映射
|
||||||
*/
|
*/
|
||||||
@ -359,6 +383,7 @@ export interface VbenFormProps<
|
|||||||
* 重置按钮参数
|
* 重置按钮参数
|
||||||
*/
|
*/
|
||||||
resetButtonOptions?: ActionButtonOptions;
|
resetButtonOptions?: ActionButtonOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示默认操作按钮
|
* 是否显示默认操作按钮
|
||||||
* @default true
|
* @default true
|
||||||
|
Loading…
Reference in New Issue
Block a user