first commit

This commit is contained in:
liu
2026-07-13 15:23:29 +08:00
commit 50885a98c8
473 changed files with 33772 additions and 0 deletions
@@ -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]