first commit
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
import type { FormColumn } from "./typings";
|
||||
import {
|
||||
Input,
|
||||
InputNumber,
|
||||
Select,
|
||||
Radio,
|
||||
Checkbox,
|
||||
Switch,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
TreeSelect,
|
||||
Cascader,
|
||||
Rate,
|
||||
Slider,
|
||||
ColorPicker
|
||||
} from 'antd';
|
||||
import type {
|
||||
InputProps,
|
||||
InputNumberProps,
|
||||
SelectProps,
|
||||
TreeSelectProps,
|
||||
RadioGroupProps,
|
||||
SwitchProps,
|
||||
RateProps,
|
||||
SliderSingleProps,
|
||||
DatePickerProps,
|
||||
TimePickerProps,
|
||||
ColorPickerProps
|
||||
} from 'antd';
|
||||
import type { PasswordProps, TextAreaProps } from "antd/es/input";
|
||||
import type { RangePickerProps } from "antd/es/date-picker";
|
||||
import type { CheckboxGroupProps } from 'antd/es/checkbox';
|
||||
import IconSelector from '@/components/XinFormField/IconSelector';
|
||||
import ImageUploader from '@/components/XinFormField/ImageUploader';
|
||||
import UserSelector from '@/components/XinFormField/UserSelector';
|
||||
import type { IconSelectProps } from '@/components/XinFormField/IconSelector/typings';
|
||||
import type { ImageUploaderProps } from '@/components/XinFormField/ImageUploader/typings';
|
||||
import type { UserSelectorProps } from '@/components/XinFormField/UserSelector/typings';
|
||||
import type {ReactNode} from "react";
|
||||
|
||||
const { TextArea, Password } = Input;
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
interface FieldsRenderProps<T> extends Record<string, any> {
|
||||
valueType: FormColumn<T>['valueType'];
|
||||
}
|
||||
|
||||
export default function FieldRender<T>(props: FieldsRenderProps<T>) {
|
||||
const { valueType, ...fieldProps } = props;
|
||||
let dom: ReactNode;
|
||||
switch (valueType) {
|
||||
case 'password':
|
||||
dom = <Password {...fieldProps as PasswordProps}/>;
|
||||
break;
|
||||
case 'textarea':
|
||||
dom = <TextArea rows={4} {...fieldProps as TextAreaProps} />;
|
||||
break;
|
||||
case 'digit':
|
||||
dom = <InputNumber style={{ width: '100%' }} {...fieldProps as InputNumberProps} />;
|
||||
break;
|
||||
case 'money':
|
||||
dom = <InputNumber style={{ width: '100%' }} precision={2} prefix="¥" {...fieldProps as InputNumberProps} />;
|
||||
break;
|
||||
case 'select':
|
||||
dom = <Select {...fieldProps as SelectProps} />;
|
||||
break;
|
||||
case 'treeSelect':
|
||||
dom = <TreeSelect {...fieldProps as TreeSelectProps} />;
|
||||
break;
|
||||
case 'cascader':
|
||||
dom = <Cascader {...fieldProps as any} />;
|
||||
break;
|
||||
case 'radio':
|
||||
dom = <Radio.Group options={[]} optionType="default" {...fieldProps as RadioGroupProps} />;
|
||||
break;
|
||||
case 'radioButton':
|
||||
dom = <Radio.Group options={[]} optionType="button" {...fieldProps as RadioGroupProps} />;
|
||||
break;
|
||||
case 'checkbox':
|
||||
dom = <Checkbox.Group options={[]} {...fieldProps as CheckboxGroupProps} />;
|
||||
break;
|
||||
case 'switch':
|
||||
dom = <Switch {...fieldProps as SwitchProps} />;
|
||||
break;
|
||||
case 'rate':
|
||||
dom = <Rate {...fieldProps as RateProps} />;
|
||||
break;
|
||||
case 'slider':
|
||||
dom = <Slider {...fieldProps as SliderSingleProps} />;
|
||||
break;
|
||||
case 'date':
|
||||
dom = <DatePicker style={{ width: '100%' }} {...fieldProps as DatePickerProps} />;
|
||||
break;
|
||||
case 'dateTime':
|
||||
dom = <DatePicker style={{ width: '100%' }} showTime {...fieldProps as DatePickerProps} />;
|
||||
break;
|
||||
case 'dateRange':
|
||||
dom = <RangePicker style={{ width: '100%' }} {...fieldProps as RangePickerProps} />;
|
||||
break;
|
||||
case 'time':
|
||||
dom = <TimePicker style={{ width: '100%' }} {...fieldProps as TimePickerProps} />;
|
||||
break;
|
||||
case 'timeRange':
|
||||
dom = <TimePicker.RangePicker style={{ width: '100%' }} {...fieldProps as RangePickerProps} />;
|
||||
break;
|
||||
case 'week':
|
||||
dom = <DatePicker style={{ width: '100%' }} picker="week" {...fieldProps as DatePickerProps} />;
|
||||
break;
|
||||
case 'month':
|
||||
dom = <DatePicker style={{ width: '100%' }} picker="month" {...fieldProps as DatePickerProps} />;
|
||||
break;
|
||||
case 'quarter':
|
||||
dom = <DatePicker style={{ width: '100%' }} picker="quarter" {...fieldProps as DatePickerProps} />;
|
||||
break;
|
||||
case 'year':
|
||||
dom = <DatePicker style={{ width: '100%' }} picker="year" {...fieldProps as DatePickerProps} />;
|
||||
break;
|
||||
case 'color':
|
||||
dom = <ColorPicker {...fieldProps as ColorPickerProps} />;
|
||||
break;
|
||||
case 'image':
|
||||
dom = <ImageUploader {...fieldProps as ImageUploaderProps} />;
|
||||
break;
|
||||
case 'icon':
|
||||
dom = <IconSelector {...fieldProps as IconSelectProps} />;
|
||||
break;
|
||||
case 'user':
|
||||
dom = <UserSelector {...fieldProps as UserSelectorProps} />;
|
||||
break;
|
||||
case 'text':
|
||||
default:
|
||||
dom = <Input {...fieldProps as InputProps} />;
|
||||
break;
|
||||
}
|
||||
return dom;
|
||||
}
|
||||
|
||||
export type { FieldsRenderProps, FormColumn };
|
||||
@@ -0,0 +1,134 @@
|
||||
import type {
|
||||
FormItemProps,
|
||||
ColProps,
|
||||
FormInstance,
|
||||
InputProps,
|
||||
InputNumberProps,
|
||||
SelectProps,
|
||||
TreeSelectProps,
|
||||
CascaderProps,
|
||||
RadioGroupProps,
|
||||
SwitchProps,
|
||||
RateProps,
|
||||
SliderSingleProps,
|
||||
DatePickerProps,
|
||||
TimePickerProps,
|
||||
TimeRangePickerProps,
|
||||
ColorPickerProps
|
||||
} from 'antd';
|
||||
import type { TextAreaProps, PasswordProps } from 'antd/es/input';
|
||||
import type { RangePickerProps } from 'antd/es/date-picker';
|
||||
import type { CheckboxGroupProps } from 'antd/es/checkbox';
|
||||
import {type Key, type ReactNode} from 'react';
|
||||
import type { IconSelectProps } from '@/components/XinFormField/IconSelector/typings';
|
||||
import type { ImageUploaderProps } from '@/components/XinFormField/ImageUploader/typings';
|
||||
import type { UserSelectorProps } from '@/components/XinFormField/UserSelector/typings';
|
||||
|
||||
/**
|
||||
* 表单字段类型
|
||||
*/
|
||||
export type FieldValue =
|
||||
| 'text' // 文本输入
|
||||
| 'password' // 密码输入
|
||||
| 'textarea' // 多行文本
|
||||
| 'digit' // 数字输入
|
||||
| 'money' // 金额输入
|
||||
| 'select' // 下拉选择
|
||||
| 'treeSelect' // 树形选择
|
||||
| 'cascader' // 级联选择
|
||||
| 'radio' // 单选框
|
||||
| 'radioButton' // 单选按钮
|
||||
| 'checkbox' // 多选框
|
||||
| 'switch' // 开关
|
||||
| 'rate' // 评分
|
||||
| 'slider' // 滑动条
|
||||
| 'date' // 日期选择
|
||||
| 'dateTime' // 日期时间选择
|
||||
| 'dateRange' // 日期范围
|
||||
| 'time' // 时间选择
|
||||
| 'timeRange' // 时间范围
|
||||
| 'week' // 周选择
|
||||
| 'month' // 月选择
|
||||
| 'quarter' // 季度选择
|
||||
| 'year' // 年选择
|
||||
| 'image' // 图片上传
|
||||
| 'color' // 颜色选择
|
||||
| 'icon' // 图标选择
|
||||
| 'user' // 用户选择
|
||||
|
||||
/**
|
||||
* valueType 到组件 Props 的类型映射
|
||||
*/
|
||||
export interface FieldPropsMap {
|
||||
text: InputProps;
|
||||
password: PasswordProps;
|
||||
textarea: TextAreaProps;
|
||||
digit: InputNumberProps;
|
||||
money: InputNumberProps;
|
||||
select: SelectProps;
|
||||
treeSelect: TreeSelectProps;
|
||||
cascader: CascaderProps;
|
||||
radio: Omit<RadioGroupProps, 'optionType'>;
|
||||
radioButton: Omit<RadioGroupProps, 'optionType'>;
|
||||
checkbox: CheckboxGroupProps;
|
||||
switch: SwitchProps;
|
||||
rate: RateProps;
|
||||
slider: SliderSingleProps;
|
||||
date: DatePickerProps;
|
||||
dateTime: DatePickerProps;
|
||||
dateRange: RangePickerProps;
|
||||
time: TimePickerProps;
|
||||
timeRange: TimeRangePickerProps;
|
||||
week: DatePickerProps;
|
||||
month: DatePickerProps;
|
||||
quarter: DatePickerProps;
|
||||
year: DatePickerProps;
|
||||
image: ImageUploaderProps;
|
||||
color: ColorPickerProps;
|
||||
icon: IconSelectProps;
|
||||
user: UserSelectorProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段依赖配置
|
||||
*/
|
||||
export interface FieldDependency<T = any> {
|
||||
/** 依赖的字段名 */
|
||||
dependencies: (keyof T)[];
|
||||
/** 根据依赖值判断是否显示 */
|
||||
visible?: (values: Partial<T>) => boolean;
|
||||
/** 根据依赖值判断是否禁用 */
|
||||
disabled?: (values: Partial<T>) => boolean;
|
||||
/** 根据依赖值动态修改 fieldProps */
|
||||
fieldProps?: (values: Partial<T>) => Record<string, any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 valueType 映射 fieldProps 类型的表单列配置
|
||||
*/
|
||||
type FormColumnMap<T> = {
|
||||
[K in FieldValue]: FormItemProps<T> & {
|
||||
/** 唯一标识 */
|
||||
key?: Key;
|
||||
/** 字段名 */
|
||||
dataIndex?: string | number | (string | number)[];
|
||||
/** 字段标签 */
|
||||
title?: string;
|
||||
/** 字段类型 */
|
||||
valueType?: K;
|
||||
/** 自定义字段渲染 */
|
||||
fieldRender?: (form: FormInstance<T>) => ReactNode;
|
||||
/** Col 属性 表单开启 grid 时生效 */
|
||||
colProps?: ColProps;
|
||||
/** 字段组件的属性,根据 valueType 自动推断类型 */
|
||||
fieldProps?: FieldPropsMap[K];
|
||||
/** 字段依赖配置 */
|
||||
dependency?: FieldDependency<T>;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单列配置
|
||||
* fieldProps 类型会根据 valueType 自动推断
|
||||
*/
|
||||
export type FormColumn<T> = FormColumnMap<T>[FieldValue]
|
||||
Reference in New Issue
Block a user