2024 / 1 / 3 日更新
// todo 组件只用于渲染 Form.Item 层 | 不包含 Form
// 调用示例
/* <FormItem<FormCodeType>
label="项目名称"
name="projectName"
type="Input"
input_disabled={modalStateText === "edit"}
input_maxLength={64}
style={{ width: 240 }}
rules={[{ required: true, message: "请输入项目名称!" }]}
/>; */
import {
AutoComplete,
Button,
Cascader,
Checkbox,
DatePicker,
Form,
Input,
InputNumber,
InputRef,
QRCode,
Radio,
Select,
Slider,
Upload,
} from "antd";
import { Rule } from "antd/es/form";
import { SelectValue } from "antd/es/select";
import { RcFile } from "antd/es/upload";
import { Dayjs } from "dayjs";
import { ChangeEvent, KeyboardEvent } from "react";
const { RangePicker } = DatePicker;
type FormItemComponentType =
| "Upload"
| "Radio"
| "Input"
| "QRCode"
| "Slider"
| "Selector"
| "Cascader"
| "Checkbox"
| "DatePicker"
| "InputNumber"
| "RangePicker"
| "AutoComplete";
type CascaderOptionType = {
label: React.ReactNode;
value: string;
disabled?: boolean;
children?: Array<CascaderOptionType>;
};
type UploadType = {
file: RcFile;
data: any;
filename: string;
withCredentials: boolean;
action: string;
headers: { [key: string]: any };
method: string;
onSuccess: (response: any, file: RcFile) => void;
onError: (error: Error, response: any, file: RcFile) => void;
onProgress: (event: { percent: number }, file: RcFile) => void;
};
type GenericFormItemProps<T> = {
type: FormItemComponentType;
label: string;
name: keyof T & string;
rules: Array<Rule>;
style?: React.CSSProperties;
selector_showSearch?: boolean;
selector_placeholder?: string;
selector_options?: Array<{ value: string; label: string }>;
selector_allowClear?: boolean;
selector_disabled?: boolean;
select_onChange?: (
value: SelectValue,
option:
| { value: string; label: string }
| { value: string; label: string }[],
) => void;
input_ref?: React.RefObject<InputRef>;
input_value?: string;
input_border?: boolean;
input_disabled?: boolean;
input_maxLength?: number;
input_showCount?: boolean;
input_addonAfter?: string;
input_placeholder?: string;
input_defaultValue?: string;
input_prefix?: React.ReactNode;
input_suffix?: React.ReactNode;
input_onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
input_onPressEnter?: (e: KeyboardEvent<HTMLInputElement>) => void;
date_placeholder?: string;
date_picker?: "time" | "date" | "week" | "month" | "quarter" | "year";
date_allowClear?: boolean;
date_autoFocus?: boolean;
date_bordered?: boolean;
date_disabled?: boolean;
date_showToday?: boolean;
date_value?: Dayjs;
date_defaultValue?: Dayjs;
date_disabledDate?: (currentDate: Dayjs) => boolean;
date_pickerOnChange?: (date: Dayjs | null, dateString: string) => void;
inputNumber_min?: number;
inputNumber_max?: number;
inputNumber_disabled?: boolean;
inputNumber_size?: "large" | "middle" | "small";
radio_options?: Array<{ value: string; label: string }>;
radio_value?: number;
radio_disabled?: boolean;
slider_min?: number;
slider_max?: number;
slider_disabled?: boolean;
slider_tooltip?: boolean;
autoComplete_placeholder?: string;
autoComplete_disabled?: boolean;
autoComplete_options?: Array<Record<string, string>>;
autoComplete_maxlength?: number;
cascader_options?: Array<CascaderOptionType>;
cascader_disabled?: boolean;
checkbox_options?: Array<{ value: string; label: string }>;
checkbox_disabled?: boolean;
QRCode_value?: string;
upload_accept?: string;
upload_fileList?: Array<string>;
upload_button_title?: string;
upload_button_disabled?: boolean;
upload_showUploadList?: boolean;
upload_button_icon?: React.ReactNode;
upload_button_loading?: boolean;
upload_button_type?: "link" | "text" | "default" | "primary" | "dashed";
upload_customRequest?: (options: UploadType) => void;
};
const filterOption = (
input: string,
option?: { label: string; value: string | number },
): boolean => (option?.label ?? "").toLowerCase().includes(input.toLowerCase());
const FormItem = <T extends Record<string, any>>(
PropsInfo: GenericFormItemProps<T>,
) => {
// 基础信息
const { type, label, name, rules, style } = PropsInfo;
// 下拉框信息
const {
selector_options,
selector_disabled,
selector_allowClear,
selector_showSearch,
selector_placeholder,
select_onChange,
} = PropsInfo;
// 输入框信息
const {
input_ref,
input_value,
input_border,
input_prefix,
input_suffix,
input_disabled,
input_maxLength,
input_showCount,
input_addonAfter,
input_placeholder,
input_defaultValue,
input_onChange,
input_onPressEnter,
} = PropsInfo;
// 日期选择器信息
const {
date_value,
date_picker,
date_disabled,
date_bordered,
date_showToday,
date_autoFocus,
date_allowClear,
date_placeholder,
date_defaultValue,
date_disabledDate,
date_pickerOnChange,
} = PropsInfo;
// 数字输入框信息
const {
inputNumber_min,
inputNumber_max,
inputNumber_size,
inputNumber_disabled,
} = PropsInfo;
// 单选框 Radio 信息
const { radio_options, radio_value, radio_disabled } = PropsInfo;
// 移动数字滑块 信息
const { slider_disabled, slider_min, slider_max, slider_tooltip } = PropsInfo;
// 级联选择器信息
const { cascader_options, cascader_disabled } = PropsInfo;
// 输入框自动完成信息
const {
autoComplete_placeholder,
autoComplete_options,
autoComplete_disabled,
autoComplete_maxlength,
} = PropsInfo;
// 复选框信息
const { checkbox_options, checkbox_disabled } = PropsInfo;
// 二维码信息
const { QRCode_value } = PropsInfo;
// upload 上传文件信息
const {
upload_accept,
upload_fileList,
upload_button_disabled,
upload_button_icon,
upload_button_type,
upload_button_title,
upload_showUploadList,
upload_button_loading,
upload_customRequest,
} = PropsInfo;
const renderItem = (): React.ReactNode => {
switch (type) {
case "Selector":
return (
<Select
getPopupContainer={(): any =>
document.getElementById("filterWrapper")
}
style={style}
optionFilterProp="children"
options={selector_options}
disabled={selector_disabled ?? false}
showSearch={selector_showSearch ?? true}
allowClear={selector_allowClear ?? true}
placeholder={selector_placeholder ?? ""}
filterOption={filterOption}
onChange={(value, option) =>
select_onChange?.(
value,
Array.isArray(option) ? option : [option],
)
}
/>
);
case "Input":
return (
<Input
style={style}
ref={input_ref}
value={input_value}
prefix={input_prefix}
suffix={input_suffix}
bordered={input_border}
disabled={input_disabled ?? false}
showCount={input_showCount}
maxLength={input_maxLength}
addonAfter={input_addonAfter}
placeholder={input_placeholder ?? ""}
defaultValue={input_defaultValue}
onChange={input_onChange}
onPressEnter={input_onPressEnter}
/>
);
case "DatePicker":
return (
<DatePicker
getPopupContainer={(): any =>
document.getElementById("filterWrapper")
}
style={style}
value={date_value}
picker={date_picker}
disabled={date_disabled}
bordered={date_bordered}
showToday={date_showToday ?? false}
autoFocus={date_autoFocus}
allowClear={date_allowClear ?? true}
placeholder={date_placeholder ?? ""}
defaultValue={date_defaultValue}
onChange={date_pickerOnChange}
disabledDate={date_disabledDate}
/>
);
case "AutoComplete":
return (
<AutoComplete
getPopupContainer={(): any =>
document.getElementById("filterWrapper")
}
maxLength={autoComplete_maxlength}
style={style}
disabled={autoComplete_disabled ?? false}
options={autoComplete_options}
placeholder={autoComplete_placeholder ?? ""}
filterOption={(input_value, option) =>
String(option!.value)
.toUpperCase()
.indexOf(input_value.toUpperCase()) !== -1
}
/>
);
case "Upload":
return (
<Upload
customRequest={upload_customRequest as any}
accept={upload_accept}
fileList={upload_fileList ?? ([] as any)}
// disabled={upload_button_disabled}
showUploadList={upload_showUploadList ?? false}
>
<Button
loading={upload_button_loading}
style={style}
icon={upload_button_icon}
disabled={upload_button_disabled ?? false}
type={upload_button_type ?? "text"}
>
{upload_button_title ?? "上传"}
</Button>
</Upload>
);
case "RangePicker":
return <RangePicker style={style} />;
case "Radio":
return (
<Radio.Group
style={style}
disabled={radio_disabled ?? false}
value={radio_value}
>
{radio_options?.map((item) => (
<Radio key={item.value} value={item.value}>
{item.label}
</Radio>
))}
</Radio.Group>
);
case "InputNumber":
return (
<InputNumber
style={style}
size={inputNumber_size ?? "small"}
disabled={inputNumber_disabled ?? false}
min={inputNumber_min}
max={inputNumber_max}
/>
);
case "Slider":
return (
<Slider
style={style}
min={slider_min}
max={slider_max}
disabled={slider_disabled ?? false}
tooltip={{ open: slider_tooltip ?? false }}
/>
);
case "Cascader":
return (
<Cascader
style={style}
getPopupContainer={(): any =>
document.getElementById("filterWrapper")
}
disabled={cascader_disabled ?? false}
options={cascader_options}
expandTrigger="hover"
/>
);
case "Checkbox":
return (
<Checkbox.Group
style={style}
disabled={checkbox_disabled ?? false}
options={checkbox_options}
/>
);
case "QRCode":
return <QRCode style={style} value={QRCode_value || "-"} />;
default:
return <div style={{ color: "red" }}>传入的 type 不存在,请检查</div>;
}
};
return (
<Form.Item label={label} name={name as any} rules={rules}>
{renderItem()}
</Form.Item>
);
};
export default FormItem;
2024 1.9 日更新 ( 拆分 TS 类型 ,简化代码 )
Type.ts
import { InputRef } from "antd";
import { Rule } from "antd/es/form";
import { SelectValue } from "antd/es/select";
import { RcFile } from "antd/es/upload";
import { Dayjs } from "dayjs";
import { ChangeEvent, KeyboardEvent } from "react";
export type FormItemComponentType =
| "Upload"
| "Radio"
| "Input"
| "QRCode"
| "Slider"
| "Selector"
| "Cascader"
| "Checkbox"
| "DatePicker"
| "InputNumber"
| "RangePicker"
| "AutoComplete";
export type CascaderOptionType = {
value: string;
disabled?: boolean;
children?: Array<CascaderOptionType>;
} & { [key in "label"]: React.ReactNode };
export type UploadType = {
file: RcFile;
data: any;
filename: string;
withCredentials: boolean;
action: string;
headers: { [key: string]: any };
method: string;
onSuccess: (response: any, file: RcFile) => void;
onError: (error: Error, response: any, file: RcFile) => void;
onProgress: (event: { percent: number }, file: RcFile) => void;
};
type date_picker_type = "time" | "date" | "week" | "month" | "quarter" | "year";
type upload_button_type = "link" | "text" | "default" | "primary" | "dashed";
type inputNumber_size_type = "large" | "middle" | "small";
export type GenericFormItemProps<T> = {
type: FormItemComponentType;
label: string;
name: keyof T & string;
rules: Array<Rule>;
style?: React.CSSProperties;
input_ref?: React.RefObject<InputRef>;
date_picker?: date_picker_type;
inputNumber_size?: inputNumber_size_type;
autoComplete_options?: Array<Record<string, string>>;
cascader_options?: Array<CascaderOptionType>;
upload_fileList?: Array<string>;
upload_button_type?: upload_button_type;
select_onChange?: (
value: SelectValue,
option:
| { value: string; label: string }
| { value: string; label: string }[],
) => void;
upload_customRequest?: (options: UploadType) => void;
date_pickerOnChange?: (date: Dayjs | null, dateString: string) => void;
date_disabledDate?: (currentDate: Dayjs) => boolean;
input_onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
input_onPressEnter?: (e: KeyboardEvent<HTMLInputElement>) => void;
} & {
[key in
| "selector_showSearch"
| "selector_allowClear"
| "selector_disabled"
| "input_border"
| "input_showCount"
| "date_allowClear"
| "date_autoFocus"
| "date_bordered"
| "date_disabled"
| "date_showToday"
| "inputNumber_disabled"
| "radio_disabled"
| "slider_disabled"
| "slider_tooltip"
| "autoComplete_disabled"
| "cascader_disabled"
| "checkbox_disabled"
| "upload_button_disabled"
| "upload_showUploadList"
| "upload_button_loading"
| "input_disabled"]?: boolean;
} & {
[key in
| "input_value"
| "input_addonAfter"
| "input_placeholder"
| "input_defaultValue"
| "date_placeholder"
| "autoComplete_placeholder"
| "QRCode_value"
| "upload_accept"
| "selector_placeholder"
| "upload_button_title"]?: string;
} & {
[key in
| "input_maxLength"
| "inputNumber_min"
| "inputNumber_max"
| "radio_value"
| "slider_min"
| "slider_max"
| "autoComplete_maxlength"]?: number;
} & {
[key in "selector_options" | "radio_options" | "checkbox_options"]?: Array<{
value: string;
label: string;
}>;
} & {
[key in
| "input_prefix"
| "input_suffix"
| "upload_button_icon"]?: React.ReactNode;
} & { [key in "date_value" | "date_defaultValue"]?: Dayjs };
FormItme:
// todo 组件只用于渲染 Form.Item 层 | 不包含 Form
// 调用示例
/* <FormItem<FormCodeType>
label="项目名称"
name="projectName"
type="Input"
input_disabled={modalStateText === "edit"}
input_maxLength={64}
style={{ width: 240 }}
rules={[{ required: true, message: "请输入项目名称!" }]}
/>; */
import {
AutoComplete,
Button,
Cascader,
Checkbox,
DatePicker,
Form,
Input,
InputNumber,
QRCode,
Radio,
Select,
Slider,
Upload,
} from "antd";
import { GenericFormItemProps } from "./type";
const { RangePicker } = DatePicker;
const filterOption = (
input: string,
option?: { label: string; value: string | number },
): boolean => (option?.label ?? "").toLowerCase().includes(input.toLowerCase());
const FormItem = <T extends Record<string, any>>(
PropsInfo: GenericFormItemProps<T>,
) => {
// 基础信息
const { type, label, name, rules, style } = PropsInfo;
// 下拉框信息
const {
selector_options,
selector_disabled,
selector_allowClear,
selector_showSearch,
selector_placeholder,
select_onChange,
} = PropsInfo;
// 输入框信息
const {
input_ref,
input_value,
input_border,
input_prefix,
input_suffix,
input_disabled,
input_maxLength,
input_showCount,
input_addonAfter,
input_placeholder,
input_defaultValue,
input_onChange,
input_onPressEnter,
} = PropsInfo;
// 日期选择器信息
const {
date_value,
date_picker,
date_disabled,
date_bordered,
date_showToday,
date_autoFocus,
date_allowClear,
date_placeholder,
date_defaultValue,
date_disabledDate,
date_pickerOnChange,
} = PropsInfo;
// 数字输入框信息
const {
inputNumber_min,
inputNumber_max,
inputNumber_size,
inputNumber_disabled,
} = PropsInfo;
// 单选框 Radio 信息
const { radio_options, radio_value, radio_disabled } = PropsInfo;
// 移动数字滑块 信息
const { slider_disabled, slider_min, slider_max, slider_tooltip } = PropsInfo;
// 级联选择器信息
const { cascader_options, cascader_disabled } = PropsInfo;
// 输入框自动完成信息
const {
autoComplete_placeholder,
autoComplete_options,
autoComplete_disabled,
autoComplete_maxlength,
} = PropsInfo;
// 复选框信息
const { checkbox_options, checkbox_disabled } = PropsInfo;
// 二维码信息
const { QRCode_value } = PropsInfo;
// upload 上传文件信息
const {
upload_accept,
upload_fileList,
upload_button_disabled,
upload_button_icon,
upload_button_type,
upload_button_title,
upload_showUploadList,
upload_button_loading,
upload_customRequest,
} = PropsInfo;
const renderItem = (): React.ReactNode => {
switch (type) {
case "Selector":
return (
<Select
getPopupContainer={(): any =>
document.getElementById("filterWrapper")
}
style={style}
optionFilterProp="children"
options={selector_options}
disabled={selector_disabled ?? false}
showSearch={selector_showSearch ?? true}
allowClear={selector_allowClear ?? true}
placeholder={selector_placeholder ?? ""}
filterOption={filterOption}
onChange={(value, option) =>
select_onChange?.(
value,
Array.isArray(option) ? option : [option],
)
}
/>
);
case "Input":
return (
<Input
style={style}
ref={input_ref}
value={input_value}
prefix={input_prefix}
suffix={input_suffix}
bordered={input_border}
disabled={input_disabled ?? false}
showCount={input_showCount}
maxLength={input_maxLength}
addonAfter={input_addonAfter}
placeholder={input_placeholder ?? ""}
defaultValue={input_defaultValue}
onChange={input_onChange}
onPressEnter={input_onPressEnter}
/>
);
case "DatePicker":
return (
<DatePicker
getPopupContainer={(): any =>
document.getElementById("filterWrapper")
}
style={style}
value={date_value}
picker={date_picker}
disabled={date_disabled}
bordered={date_bordered}
showToday={date_showToday ?? false}
autoFocus={date_autoFocus}
allowClear={date_allowClear ?? true}
placeholder={date_placeholder ?? ""}
defaultValue={date_defaultValue}
onChange={date_pickerOnChange}
disabledDate={date_disabledDate}
/>
);
case "AutoComplete":
return (
<AutoComplete
getPopupContainer={(): any =>
document.getElementById("filterWrapper")
}
maxLength={autoComplete_maxlength}
style={style}
disabled={autoComplete_disabled ?? false}
options={autoComplete_options}
placeholder={autoComplete_placeholder ?? ""}
filterOption={(input_value, option) =>
String(option!.value)
.toUpperCase()
.indexOf(input_value.toUpperCase()) !== -1
}
/>
);
case "Upload":
return (
<Upload
customRequest={upload_customRequest as any}
accept={upload_accept}
fileList={upload_fileList ?? ([] as any)}
multiple
// disabled={upload_button_disabled}
showUploadList={upload_showUploadList ?? false}
>
<Button
loading={upload_button_loading}
style={style}
icon={upload_button_icon}
disabled={upload_button_disabled ?? false}
type={upload_button_type ?? "text"}
>
{upload_button_title ?? "上传"}
</Button>
</Upload>
);
case "RangePicker":
return <RangePicker style={style} />;
case "Radio":
return (
<Radio.Group
style={style}
disabled={radio_disabled ?? false}
value={radio_value}
>
{radio_options?.map((item) => (
<Radio key={item.value} value={item.value}>
{item.label}
</Radio>
))}
</Radio.Group>
);
case "InputNumber":
return (
<InputNumber
style={style}
size={inputNumber_size ?? "small"}
disabled={inputNumber_disabled ?? false}
min={inputNumber_min}
max={inputNumber_max}
/>
);
case "Slider":
return (
<Slider
style={style}
min={slider_min}
max={slider_max}
disabled={slider_disabled ?? false}
tooltip={{ open: slider_tooltip ?? false }}
/>
);
case "Cascader":
return (
<Cascader
style={style}
getPopupContainer={(): any =>
document.getElementById("filterWrapper")
}
disabled={cascader_disabled ?? false}
options={cascader_options}
expandTrigger="hover"
/>
);
case "Checkbox":
return (
<Checkbox.Group
style={style}
disabled={checkbox_disabled ?? false}
options={checkbox_options}
/>
);
case "QRCode":
return <QRCode style={style} value={QRCode_value || "-"} />;
default:
return <div style={{ color: "red" }}>传入的 type 不存在,请检查</div>;
}
};
return (
<Form.Item label={label} name={name as any} rules={rules}>
{renderItem()}
</Form.Item>
);
};
export default FormItem;
2024 / 1 / 31 日更新
import { InputRef } from "antd";
import { Rule } from "antd/es/form";
import { SelectValue } from "antd/es/select";
import { RcFile } from "antd/es/upload";
import { Dayjs } from "dayjs";
import { ChangeEvent, KeyboardEvent } from "react";
export type FormItemComponentType =
| "Radio"
| "Input"
| "Slider"
| "QRCode"
| "Upload"
| "Selector"
| "Cascader"
| "Checkbox"
| "TextArea"
| "DatePicker"
| "InputNumber"
| "RangePicker"
| "AutoComplete";
export type CascaderOptionType = {
value: string;
disabled?: boolean;
children?: Array<CascaderOptionType>;
} & { [key in "label"]: React.ReactNode };
export type UploadType = {
data: any;
file: RcFile;
method: string;
action: string;
filename: string;
withCredentials: boolean;
headers: { [key: string]: any };
onSuccess: (response: any, file: RcFile) => void;
onError: (error: Error, response: any, file: RcFile) => void;
onProgress: (event: { percent: number }, file: RcFile) => void;
};
type date__picker__type =
| "time"
| "date"
| "week"
| "year"
| "month"
| "quarter";
type inputNumber__size__type = "large" | "middle" | "small";
type upload__button__type = "link" | "text" | "default" | "primary" | "dashed";
export type GenericFormItemProps<T> = {
label: string;
rules: Array<Rule>;
name: keyof T & string;
type: FormItemComponentType;
style?: React.CSSProperties;
upload__fileList?: Array<string>;
date__picker?: date__picker__type;
input__ref?: React.RefObject<InputRef>;
inputNumber__size?: inputNumber__size__type;
upload__button__type?: upload__button__type;
cascader__options?: Array<CascaderOptionType>;
autoComplete__options?: Array<Record<string, string>>;
date__disabledDate?: (currentDate: Dayjs) => boolean;
upload__customRequest?: (options: UploadType) => void;
input__onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
input__onPressEnter?: (e: KeyboardEvent<HTMLInputElement>) => void;
date__pickerOnChange?: (date: Dayjs | null, dateString: string) => void;
select__onChange?: (
value: SelectValue,
option:
| { value: string | any; label: string }
| { value: string | any; label: string }[]
) => void;
} & {
[key in
| "input__border"
| "date__bordered"
| "date__disabled"
| "radio__disabled"
| "date__showToday"
| "date__autoFocus"
| "slider__tooltip"
| "input__showCount"
| "date__allowClear"
| "slider__disabled"
| "upload__multiple"
| "cascader__disabled"
| "checkbox__disabled"
| "selector__disabled"
| "textArea__showCount"
| "selector__allowClear"
| "selector__showSearch"
| "inputNumber__disabled"
| "autoComplete__disabled"
| "upload__showUploadList"
| "upload__button__loading"
| "upload__button__disabled"
| "textArea__style__stretch"
| "input__disabled"]?: boolean;
} & {
[key in
| "input__value"
| "QRCode__value"
| "upload__accept"
| "date__placeholder"
| "input__addonAfter"
| "input__placeholder"
| "input__defaultValue"
| "selector__placeholder"
| "textArea__placeholder"
| "autoComplete__placeholder"
| "upload__button__title"]?: string;
} & {
[key in
| "slider__max"
| "slider__min"
| "radio__value"
| "textArea__row"
| "input__maxLength"
| "inputNumber__min"
| "inputNumber__max"
| "textArea__maxLength"
| "autoComplete__maxlength"]?: number;
} & {
[key in "radio__options" | "selector__options" | "checkbox__options"]?: {
label: string;
value: string | boolean;
}[];
} & {
[key in
| "input__prefix"
| "input__suffix"
| "upload__button__icon"]?: React.ReactNode;
} & { [key in "date__value" | "date__defaultValue"]?: Dayjs };
// todo 组件只用于渲染 Form.Item 层 | 不包含 Form
// 调用示例
/* <FormItem<FormFieldsNameType>
label="项目名称"
name="projectName"
type="Input"
input__disabled={modalStateText === "edit"}
input__maxLength={64}
style={{ width: 240 }}
rules={[{ required: true, message: "请输入项目名称!" }]}
/>; */
import {
AutoComplete,
Button,
Cascader,
Checkbox,
DatePicker,
Form,
Input,
InputNumber,
QRCode,
Radio,
Select,
Slider,
Upload,
} from "antd";
import TextArea from "antd/es/input/TextArea";
import { GenericFormItemProps } from "./type";
const { RangePicker } = DatePicker;
// 下拉框可搜索函数
const filterOption = (
input: string,
option?: { label: string; value: string | number }
): boolean => (option?.label ?? "").toLowerCase().includes(input.toLowerCase());
const FormItem = <T extends Record<string, any>>(
PropsInfo: GenericFormItemProps<T>
) => {
// 基础信息
const { type, label, name, rules, style } = PropsInfo;
// 下拉框信息
const {
selector__options,
selector__disabled,
selector__allowClear,
selector__showSearch,
selector__placeholder,
select__onChange,
} = PropsInfo;
// 输入框信息
const {
input__ref,
input__value,
// input__border,
input__prefix,
input__suffix,
input__disabled,
input__maxLength,
input__showCount,
input__addonAfter,
input__placeholder,
input__defaultValue,
input__onChange,
input__onPressEnter,
} = PropsInfo;
// 日期选择器信息
const {
date__value,
date__picker,
date__disabled,
// date__bordered,
date__showToday,
date__autoFocus,
date__allowClear,
date__placeholder,
date__defaultValue,
date__disabledDate,
date__pickerOnChange,
} = PropsInfo;
// 数字输入框信息
const {
inputNumber__min,
inputNumber__max,
inputNumber__size,
inputNumber__disabled,
} = PropsInfo;
// 单选框 Radio 信息
const { radio__options, radio__value, radio__disabled } = PropsInfo;
// 移动数字滑块 信息
const { slider__disabled, slider__min, slider__max, slider__tooltip } =
PropsInfo;
// 级联选择器信息
const { cascader__options, cascader__disabled } = PropsInfo;
// 输入框自动完成信息
const {
autoComplete__options,
autoComplete__disabled,
autoComplete__maxlength,
autoComplete__placeholder,
} = PropsInfo;
// 复选框信息
const { checkbox__options, checkbox__disabled } = PropsInfo;
// 文本域信息
const {
textArea__row,
textArea__showCount,
textArea__maxLength,
textArea__placeholder,
textArea__style__stretch,
} = PropsInfo;
// 二维码信息
const { QRCode__value } = PropsInfo;
// upload 上传文件信息
const {
upload__accept,
upload__multiple,
upload__fileList,
upload__button__icon,
upload__button__type,
upload__button__title,
upload__showUploadList,
upload__button__loading,
upload__button__disabled,
upload__customRequest,
} = PropsInfo;
const renderItem = (): React.ReactNode => {
switch (type) {
case "Selector":
return (
<Select
style={style}
optionFilterProp="children"
filterOption={filterOption}
disabled={selector__disabled ?? false}
showSearch={selector__showSearch ?? true}
allowClear={selector__allowClear ?? true}
placeholder={selector__placeholder ?? ""}
options={selector__options as { label: string; value: string }[]}
onChange={(value, option) =>
select__onChange?.(
value,
Array.isArray(option) ? option : [option]
)
}
/>
);
case "TextArea":
return (
<TextArea
rows={textArea__row ?? 3}
maxLength={textArea__maxLength ?? 50}
showCount={textArea__showCount ?? true}
placeholder={textArea__placeholder ?? ""}
style={textArea__style__stretch ? { resize: "none" } : undefined}
/>
);
case "Input":
return (
<Input
style={style}
ref={input__ref}
value={input__value}
prefix={input__prefix}
suffix={input__suffix}
// bordered={input__border}
showCount={input__showCount}
maxLength={input__maxLength}
addonAfter={input__addonAfter}
defaultValue={input__defaultValue}
disabled={input__disabled ?? false}
placeholder={input__placeholder ?? ""}
onChange={input__onChange}
onPressEnter={input__onPressEnter}
/>
);
case "DatePicker":
return (
<DatePicker
style={style}
value={date__value}
picker={date__picker}
disabled={date__disabled}
// bordered={date__bordered}
autoFocus={date__autoFocus}
defaultValue={date__defaultValue}
showToday={date__showToday ?? false}
allowClear={date__allowClear ?? true}
placeholder={date__placeholder ?? ""}
onChange={date__pickerOnChange}
disabledDate={date__disabledDate}
/>
);
case "AutoComplete":
return (
<AutoComplete
style={style}
options={autoComplete__options}
maxLength={autoComplete__maxlength}
disabled={autoComplete__disabled ?? false}
placeholder={autoComplete__placeholder ?? ""}
filterOption={(input__value, option) =>
String(option!.value)
.toUpperCase()
.indexOf(input__value.toUpperCase()) !== -1
}
/>
);
case "Upload":
return (
<Upload
accept={upload__accept}
multiple={upload__multiple ?? true}
fileList={upload__fileList ?? ([] as any)}
customRequest={upload__customRequest as any}
showUploadList={upload__showUploadList ?? false}
>
<Button
style={style}
icon={upload__button__icon}
type={upload__button__type ?? "text"}
loading={upload__button__loading ?? false}
disabled={upload__button__disabled ?? false}
>
{upload__button__title ?? "上传"}
</Button>
</Upload>
);
case "RangePicker":
return <RangePicker style={style} />;
case "Radio":
return (
<Radio.Group
style={style}
value={radio__value}
disabled={radio__disabled ?? false}
>
{(
radio__options ?? [
{ value: "radio__options 无值", label: "radio__options 无值" },
]
).map((item) => (
<Radio key={`${item.value}`} value={item.value}>
{item.label}
</Radio>
))}
</Radio.Group>
);
case "InputNumber":
return (
<InputNumber
style={style}
min={inputNumber__min}
max={inputNumber__max}
size={inputNumber__size ?? "small"}
disabled={inputNumber__disabled ?? false}
/>
);
case "Slider":
return (
<Slider
style={style}
min={slider__min}
max={slider__max}
disabled={slider__disabled ?? false}
tooltip={{ open: slider__tooltip ?? false }}
/>
);
case "Cascader":
return (
<Cascader
style={style}
expandTrigger="hover"
options={cascader__options}
disabled={cascader__disabled ?? false}
/>
);
case "Checkbox":
return (
<Checkbox.Group
style={style}
disabled={checkbox__disabled ?? false}
options={
checkbox__options ?? [
{
value: "checkbox__options 无值",
label: "checkbox__options 无值",
},
]
}
/>
);
case "QRCode":
return <QRCode style={style} value={QRCode__value || "-"} />;
default:
return <div style={{ color: "red" }}>传入的 type 不存在,请检查</div>;
}
};
return (
<Form.Item label={label} name={name as any} rules={rules}>
{renderItem()}
</Form.Item>
);
};
export default FormItem;
时小记,终有成。