mirror of
https://github.com/imdap/ruoyi-plus-vben5.git
synced 2026-04-23 00:38:34 +08:00
feat: Schema 中 componentProps 随注册组件联动类型提示
This commit is contained in:
96
apps/web-antd/src/adapter/form-schema.ts
Normal file
96
apps/web-antd/src/adapter/form-schema.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import type {
|
||||
AutoCompleteProps,
|
||||
ButtonProps,
|
||||
CascaderProps,
|
||||
CheckboxGroupProps,
|
||||
CheckboxProps,
|
||||
DatePickerProps,
|
||||
DividerProps,
|
||||
InputNumberProps,
|
||||
InputProps,
|
||||
MentionsProps,
|
||||
RadioGroupProps,
|
||||
RadioProps,
|
||||
RateProps,
|
||||
SelectProps,
|
||||
SpaceProps,
|
||||
SwitchProps,
|
||||
TextAreaProps,
|
||||
TimePickerProps,
|
||||
TreeSelectProps,
|
||||
UploadProps,
|
||||
} from 'ant-design-vue';
|
||||
import type { RangePickerProps } from 'ant-design-vue/es/date-picker';
|
||||
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type {
|
||||
ApiComponentSharedProps,
|
||||
VbenFormSchema as CoreFormSchema,
|
||||
IconPickerProps,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
|
||||
/**
|
||||
* 对象形式:使用适配器里为各 `component` 声明的 Props 类型 `P`;
|
||||
* 与 `Record<string, any>` 相交是为了满足核心库 `MaybeComponentProps` 的索引签名。
|
||||
* 函数形式:通过联合 `CoreFormSchema['componentProps']`,与表单核心对动态 `componentProps` 的约定保持一致。
|
||||
*/
|
||||
type SchemaComponentProps<P> =
|
||||
| CoreFormSchema<ComponentType>['componentProps']
|
||||
| (P & Record<string, any>);
|
||||
|
||||
/**
|
||||
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
|
||||
*/
|
||||
interface FormSchemaComponentPropsMap {
|
||||
ApiCascader: ApiComponentSharedProps & CascaderProps;
|
||||
ApiSelect: ApiComponentSharedProps & SelectProps;
|
||||
ApiTreeSelect: ApiComponentSharedProps & TreeSelectProps;
|
||||
AutoComplete: AutoCompleteProps;
|
||||
Cascader: CascaderProps;
|
||||
Checkbox: CheckboxProps;
|
||||
CheckboxGroup: CheckboxGroupProps;
|
||||
DatePicker: DatePickerProps;
|
||||
DefaultButton: ButtonProps;
|
||||
Divider: DividerProps;
|
||||
IconPicker: IconPickerProps;
|
||||
Input: InputProps;
|
||||
InputNumber: InputNumberProps;
|
||||
InputPassword: InputProps;
|
||||
Mentions: MentionsProps;
|
||||
PrimaryButton: ButtonProps;
|
||||
Radio: RadioProps;
|
||||
RadioGroup: RadioGroupProps;
|
||||
RangePicker: RangePickerProps;
|
||||
Rate: RateProps;
|
||||
Select: SelectProps;
|
||||
Space: SpaceProps;
|
||||
Switch: SwitchProps;
|
||||
Textarea: TextAreaProps;
|
||||
TimePicker: TimePickerProps;
|
||||
TreeSelect: TreeSelectProps;
|
||||
Upload: UploadProps;
|
||||
}
|
||||
|
||||
type BaseSchema = Omit<
|
||||
CoreFormSchema<ComponentType>,
|
||||
'component' | 'componentProps'
|
||||
>;
|
||||
|
||||
type RegisteredName = keyof FormSchemaComponentPropsMap;
|
||||
|
||||
type DiscriminatedFormSchema = {
|
||||
[K in RegisteredName]: BaseSchema & {
|
||||
component: K;
|
||||
componentProps?: SchemaComponentProps<FormSchemaComponentPropsMap[K]>;
|
||||
};
|
||||
}[RegisteredName];
|
||||
|
||||
type FallbackFormSchema = BaseSchema & {
|
||||
component: Component | Exclude<ComponentType, RegisteredName>;
|
||||
componentProps?: CoreFormSchema<ComponentType>['componentProps'];
|
||||
};
|
||||
|
||||
export type VbenFormSchema = DiscriminatedFormSchema | FallbackFormSchema;
|
||||
@@ -1,9 +1,7 @@
|
||||
import type {
|
||||
VbenFormSchema as FormSchema,
|
||||
VbenFormProps,
|
||||
} from '@vben/common-ui';
|
||||
import type { VbenFormProps as CoreFormProps } from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
import type { VbenFormSchema } from './form-schema';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -41,9 +39,14 @@ async function initSetupVbenForm() {
|
||||
});
|
||||
}
|
||||
|
||||
const useVbenForm = useForm<ComponentType>;
|
||||
type VbenFormProps = Omit<CoreFormProps<ComponentType>, 'schema'> & {
|
||||
schema?: VbenFormSchema[];
|
||||
};
|
||||
|
||||
function useVbenForm(options: VbenFormProps) {
|
||||
return useForm<ComponentType>(options as CoreFormProps<ComponentType>);
|
||||
}
|
||||
|
||||
export { initSetupVbenForm, useVbenForm, z };
|
||||
|
||||
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||
export type { VbenFormProps };
|
||||
export type { VbenFormProps, VbenFormSchema };
|
||||
|
||||
96
apps/web-antdv-next/src/adapter/form-schema.ts
Normal file
96
apps/web-antdv-next/src/adapter/form-schema.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import type {
|
||||
AutoCompleteProps,
|
||||
ButtonProps,
|
||||
CascaderProps,
|
||||
CheckboxGroupProps,
|
||||
CheckboxProps,
|
||||
DatePickerProps,
|
||||
DividerProps,
|
||||
InputNumberProps,
|
||||
InputProps,
|
||||
MentionsProps,
|
||||
RadioGroupProps,
|
||||
RadioProps,
|
||||
RangePickerProps,
|
||||
RateProps,
|
||||
SelectProps,
|
||||
SpaceProps,
|
||||
SwitchProps,
|
||||
TextAreaProps,
|
||||
TimePickerProps,
|
||||
TreeSelectProps,
|
||||
UploadProps,
|
||||
} from 'antdv-next';
|
||||
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type {
|
||||
ApiComponentSharedProps,
|
||||
VbenFormSchema as CoreFormSchema,
|
||||
IconPickerProps,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
|
||||
/**
|
||||
* 对象形式:使用适配器里为各 `component` 声明的 Props 类型 `P`;
|
||||
* 与 `Record<string, any>` 相交是为了满足核心库 `MaybeComponentProps` 的索引签名。
|
||||
* 函数形式:通过联合 `CoreFormSchema['componentProps']`,与表单核心对动态 `componentProps` 的约定保持一致。
|
||||
*/
|
||||
type SchemaComponentProps<P> =
|
||||
| CoreFormSchema<ComponentType>['componentProps']
|
||||
| (P & Record<string, any>);
|
||||
|
||||
/**
|
||||
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
|
||||
*/
|
||||
interface FormSchemaComponentPropsMap {
|
||||
ApiCascader: ApiComponentSharedProps & CascaderProps;
|
||||
ApiSelect: ApiComponentSharedProps & SelectProps;
|
||||
ApiTreeSelect: ApiComponentSharedProps & TreeSelectProps;
|
||||
AutoComplete: AutoCompleteProps;
|
||||
Cascader: CascaderProps;
|
||||
Checkbox: CheckboxProps;
|
||||
CheckboxGroup: CheckboxGroupProps;
|
||||
DatePicker: DatePickerProps;
|
||||
DefaultButton: ButtonProps;
|
||||
Divider: DividerProps;
|
||||
IconPicker: IconPickerProps;
|
||||
Input: InputProps;
|
||||
InputNumber: InputNumberProps;
|
||||
InputPassword: InputProps;
|
||||
Mentions: MentionsProps;
|
||||
PrimaryButton: ButtonProps;
|
||||
Radio: RadioProps;
|
||||
RadioGroup: RadioGroupProps;
|
||||
RangePicker: RangePickerProps;
|
||||
Rate: RateProps;
|
||||
Select: SelectProps;
|
||||
Space: SpaceProps;
|
||||
Switch: SwitchProps;
|
||||
Textarea: TextAreaProps;
|
||||
TimePicker: TimePickerProps;
|
||||
TreeSelect: TreeSelectProps;
|
||||
Upload: UploadProps;
|
||||
}
|
||||
|
||||
type BaseSchema = Omit<
|
||||
CoreFormSchema<ComponentType>,
|
||||
'component' | 'componentProps'
|
||||
>;
|
||||
|
||||
type RegisteredName = keyof FormSchemaComponentPropsMap;
|
||||
|
||||
type DiscriminatedFormSchema = {
|
||||
[K in RegisteredName]: BaseSchema & {
|
||||
component: K;
|
||||
componentProps?: SchemaComponentProps<FormSchemaComponentPropsMap[K]>;
|
||||
};
|
||||
}[RegisteredName];
|
||||
|
||||
type FallbackFormSchema = BaseSchema & {
|
||||
component: Component | Exclude<ComponentType, RegisteredName>;
|
||||
componentProps?: CoreFormSchema<ComponentType>['componentProps'];
|
||||
};
|
||||
|
||||
export type VbenFormSchema = DiscriminatedFormSchema | FallbackFormSchema;
|
||||
@@ -1,9 +1,7 @@
|
||||
import type {
|
||||
VbenFormSchema as FormSchema,
|
||||
VbenFormProps,
|
||||
} from '@vben/common-ui';
|
||||
import type { VbenFormProps as CoreFormProps } from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
import type { VbenFormSchema } from './form-schema';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -41,9 +39,14 @@ async function initSetupVbenForm() {
|
||||
});
|
||||
}
|
||||
|
||||
const useVbenForm = useForm<ComponentType>;
|
||||
type VbenFormProps = Omit<CoreFormProps<ComponentType>, 'schema'> & {
|
||||
schema?: VbenFormSchema[];
|
||||
};
|
||||
|
||||
function useVbenForm(options: VbenFormProps) {
|
||||
return useForm<ComponentType>(options as CoreFormProps<ComponentType>);
|
||||
}
|
||||
|
||||
export { initSetupVbenForm, useVbenForm, z };
|
||||
|
||||
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||
export type { VbenFormProps };
|
||||
export type { VbenFormProps, VbenFormSchema };
|
||||
|
||||
80
apps/web-ele/src/adapter/form-schema.ts
Normal file
80
apps/web-ele/src/adapter/form-schema.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import type {
|
||||
CheckboxGroupProps,
|
||||
CheckboxProps,
|
||||
DatePickerProps,
|
||||
DividerProps,
|
||||
ElTimePicker,
|
||||
ElTreeSelect,
|
||||
InputNumberProps,
|
||||
InputProps,
|
||||
RadioGroupProps,
|
||||
SelectV2Props,
|
||||
SpaceProps,
|
||||
SwitchProps,
|
||||
UploadProps,
|
||||
} from 'element-plus';
|
||||
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type {
|
||||
ApiComponentSharedProps,
|
||||
VbenFormSchema as CoreFormSchema,
|
||||
IconPickerProps,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
|
||||
type ElTreeSelectSchemaProps = InstanceType<typeof ElTreeSelect>['$props'];
|
||||
type ElTimePickerSchemaProps = InstanceType<typeof ElTimePicker>['$props'];
|
||||
|
||||
/**
|
||||
* 对象形式:使用适配器里为各 `component` 声明的 Props 类型 `P`;
|
||||
* 与 `Record<string, any>` 相交是为了满足核心库 `MaybeComponentProps` 的索引签名。
|
||||
* 函数形式:通过联合 `CoreFormSchema['componentProps']`,与表单核心对动态 `componentProps` 的约定保持一致。
|
||||
*/
|
||||
type SchemaComponentProps<P> =
|
||||
| CoreFormSchema<ComponentType>['componentProps']
|
||||
| (P & Record<string, any>);
|
||||
|
||||
/**
|
||||
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
|
||||
*/
|
||||
interface FormSchemaComponentPropsMap {
|
||||
ApiSelect: ApiComponentSharedProps & SelectV2Props;
|
||||
ApiTreeSelect: ApiComponentSharedProps & ElTreeSelectSchemaProps;
|
||||
Checkbox: CheckboxProps;
|
||||
CheckboxGroup: CheckboxGroupProps;
|
||||
DatePicker: DatePickerProps;
|
||||
Divider: DividerProps;
|
||||
IconPicker: IconPickerProps;
|
||||
Input: InputProps;
|
||||
InputNumber: InputNumberProps;
|
||||
RadioGroup: RadioGroupProps;
|
||||
Select: SelectV2Props;
|
||||
Space: SpaceProps;
|
||||
Switch: SwitchProps;
|
||||
TimePicker: ElTimePickerSchemaProps;
|
||||
TreeSelect: ElTreeSelectSchemaProps;
|
||||
Upload: UploadProps;
|
||||
}
|
||||
|
||||
type BaseSchema = Omit<
|
||||
CoreFormSchema<ComponentType>,
|
||||
'component' | 'componentProps'
|
||||
>;
|
||||
|
||||
type RegisteredName = keyof FormSchemaComponentPropsMap;
|
||||
|
||||
type DiscriminatedFormSchema = {
|
||||
[K in RegisteredName]: BaseSchema & {
|
||||
component: K;
|
||||
componentProps?: SchemaComponentProps<FormSchemaComponentPropsMap[K]>;
|
||||
};
|
||||
}[RegisteredName];
|
||||
|
||||
type FallbackFormSchema = BaseSchema & {
|
||||
component: Component | Exclude<ComponentType, RegisteredName>;
|
||||
componentProps?: CoreFormSchema<ComponentType>['componentProps'];
|
||||
};
|
||||
|
||||
export type VbenFormSchema = DiscriminatedFormSchema | FallbackFormSchema;
|
||||
@@ -1,9 +1,7 @@
|
||||
import type {
|
||||
VbenFormSchema as FormSchema,
|
||||
VbenFormProps,
|
||||
} from '@vben/common-ui';
|
||||
import type { VbenFormProps as CoreFormProps } from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
import type { VbenFormSchema } from './form-schema';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -33,9 +31,14 @@ async function initSetupVbenForm() {
|
||||
});
|
||||
}
|
||||
|
||||
const useVbenForm = useForm<ComponentType>;
|
||||
type VbenFormProps = Omit<CoreFormProps<ComponentType>, 'schema'> & {
|
||||
schema?: VbenFormSchema[];
|
||||
};
|
||||
|
||||
function useVbenForm(options: VbenFormProps) {
|
||||
return useForm<ComponentType>(options as CoreFormProps<ComponentType>);
|
||||
}
|
||||
|
||||
export { initSetupVbenForm, useVbenForm, z };
|
||||
|
||||
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||
export type { VbenFormProps };
|
||||
export type { VbenFormProps, VbenFormSchema };
|
||||
|
||||
77
apps/web-naive/src/adapter/form-schema.ts
Normal file
77
apps/web-naive/src/adapter/form-schema.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import type {
|
||||
CheckboxGroupProps,
|
||||
CheckboxProps,
|
||||
DatePickerProps,
|
||||
DividerProps,
|
||||
InputNumberProps,
|
||||
InputProps,
|
||||
RadioGroupProps,
|
||||
SelectProps,
|
||||
SpaceProps,
|
||||
SwitchProps,
|
||||
TimePickerProps,
|
||||
TreeSelectProps,
|
||||
UploadProps,
|
||||
} from 'naive-ui';
|
||||
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type {
|
||||
ApiComponentSharedProps,
|
||||
VbenFormSchema as CoreFormSchema,
|
||||
IconPickerProps,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
|
||||
/**
|
||||
* 对象形式:使用适配器里为各 `component` 声明的 Props 类型 `P`;
|
||||
* 与 `Record<string, any>` 相交是为了满足核心库 `MaybeComponentProps` 的索引签名。
|
||||
* 函数形式:通过联合 `CoreFormSchema['componentProps']`,与表单核心对动态 `componentProps` 的约定保持一致。
|
||||
*/
|
||||
type SchemaComponentProps<P> =
|
||||
| CoreFormSchema<ComponentType>['componentProps']
|
||||
| (P & Record<string, any>);
|
||||
|
||||
/**
|
||||
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
|
||||
*/
|
||||
interface FormSchemaComponentPropsMap {
|
||||
ApiSelect: ApiComponentSharedProps & SelectProps;
|
||||
ApiTreeSelect: ApiComponentSharedProps & TreeSelectProps;
|
||||
Checkbox: CheckboxProps;
|
||||
CheckboxGroup: CheckboxGroupProps;
|
||||
DatePicker: DatePickerProps;
|
||||
Divider: DividerProps;
|
||||
IconPicker: IconPickerProps;
|
||||
Input: InputProps;
|
||||
InputNumber: InputNumberProps;
|
||||
RadioGroup: RadioGroupProps;
|
||||
Select: SelectProps;
|
||||
Space: SpaceProps;
|
||||
Switch: SwitchProps;
|
||||
TimePicker: TimePickerProps;
|
||||
TreeSelect: TreeSelectProps;
|
||||
Upload: UploadProps;
|
||||
}
|
||||
|
||||
type BaseSchema = Omit<
|
||||
CoreFormSchema<ComponentType>,
|
||||
'component' | 'componentProps'
|
||||
>;
|
||||
|
||||
type RegisteredName = keyof FormSchemaComponentPropsMap;
|
||||
|
||||
type DiscriminatedFormSchema = {
|
||||
[K in RegisteredName]: BaseSchema & {
|
||||
component: K;
|
||||
componentProps?: SchemaComponentProps<FormSchemaComponentPropsMap[K]>;
|
||||
};
|
||||
}[RegisteredName];
|
||||
|
||||
type FallbackFormSchema = BaseSchema & {
|
||||
component: Component | Exclude<ComponentType, RegisteredName>;
|
||||
componentProps?: CoreFormSchema<ComponentType>['componentProps'];
|
||||
};
|
||||
|
||||
export type VbenFormSchema = DiscriminatedFormSchema | FallbackFormSchema;
|
||||
@@ -1,9 +1,7 @@
|
||||
import type {
|
||||
VbenFormSchema as FormSchema,
|
||||
VbenFormProps,
|
||||
} from '@vben/common-ui';
|
||||
import type { VbenFormProps as CoreFormProps } from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
import type { VbenFormSchema } from './form-schema';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -37,9 +35,14 @@ async function initSetupVbenForm() {
|
||||
});
|
||||
}
|
||||
|
||||
const useVbenForm = useForm<ComponentType>;
|
||||
type VbenFormProps = Omit<CoreFormProps<ComponentType>, 'schema'> & {
|
||||
schema?: VbenFormSchema[];
|
||||
};
|
||||
|
||||
function useVbenForm(options: VbenFormProps) {
|
||||
return useForm<ComponentType>(options as CoreFormProps<ComponentType>);
|
||||
}
|
||||
|
||||
export { initSetupVbenForm, useVbenForm, z };
|
||||
|
||||
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||
export type { VbenFormProps };
|
||||
export type { VbenFormProps, VbenFormSchema };
|
||||
|
||||
90
apps/web-tdesign/src/adapter/form-schema.ts
Normal file
90
apps/web-tdesign/src/adapter/form-schema.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import type {
|
||||
AutoCompleteProps,
|
||||
ButtonProps,
|
||||
CheckboxGroupProps,
|
||||
CheckboxProps,
|
||||
DatePickerProps,
|
||||
DateRangePickerProps,
|
||||
DividerProps,
|
||||
InputNumberProps,
|
||||
InputProps,
|
||||
RadioGroupProps,
|
||||
RadioProps,
|
||||
SelectProps,
|
||||
SpaceProps,
|
||||
SwitchProps,
|
||||
TextareaProps,
|
||||
TimePickerProps,
|
||||
TreeSelectProps,
|
||||
} from 'tdesign-vue-next';
|
||||
import type { TdRateProps } from 'tdesign-vue-next/es/rate/type';
|
||||
import type { UploadProps } from 'tdesign-vue-next/es/upload/types';
|
||||
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type {
|
||||
ApiComponentSharedProps,
|
||||
VbenFormSchema as CoreFormSchema,
|
||||
IconPickerProps,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
|
||||
/**
|
||||
* 对象形式:使用适配器里为各 `component` 声明的 Props 类型 `P`;
|
||||
* 与 `Record<string, any>` 相交是为了满足核心库 `MaybeComponentProps` 的索引签名。
|
||||
* 函数形式:通过联合 `CoreFormSchema['componentProps']`,与表单核心对动态 `componentProps` 的约定保持一致。
|
||||
*/
|
||||
type SchemaComponentProps<P> =
|
||||
| CoreFormSchema<ComponentType>['componentProps']
|
||||
| (P & Record<string, any>);
|
||||
|
||||
/**
|
||||
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
|
||||
*/
|
||||
interface FormSchemaComponentPropsMap {
|
||||
ApiSelect: ApiComponentSharedProps & SelectProps;
|
||||
ApiTreeSelect: ApiComponentSharedProps & TreeSelectProps;
|
||||
AutoComplete: AutoCompleteProps;
|
||||
Checkbox: CheckboxProps;
|
||||
CheckboxGroup: CheckboxGroupProps;
|
||||
DatePicker: DatePickerProps;
|
||||
DefaultButton: ButtonProps;
|
||||
Divider: DividerProps;
|
||||
IconPicker: IconPickerProps;
|
||||
Input: InputProps;
|
||||
InputNumber: InputNumberProps;
|
||||
PrimaryButton: ButtonProps;
|
||||
Radio: RadioProps;
|
||||
RadioGroup: RadioGroupProps;
|
||||
RangePicker: DateRangePickerProps;
|
||||
Rate: TdRateProps;
|
||||
Select: SelectProps;
|
||||
Space: SpaceProps;
|
||||
Switch: SwitchProps;
|
||||
Textarea: TextareaProps;
|
||||
TimePicker: TimePickerProps;
|
||||
TreeSelect: TreeSelectProps;
|
||||
Upload: UploadProps;
|
||||
}
|
||||
|
||||
type BaseSchema = Omit<
|
||||
CoreFormSchema<ComponentType>,
|
||||
'component' | 'componentProps'
|
||||
>;
|
||||
|
||||
type RegisteredName = keyof FormSchemaComponentPropsMap;
|
||||
|
||||
type DiscriminatedFormSchema = {
|
||||
[K in RegisteredName]: BaseSchema & {
|
||||
component: K;
|
||||
componentProps?: SchemaComponentProps<FormSchemaComponentPropsMap[K]>;
|
||||
};
|
||||
}[RegisteredName];
|
||||
|
||||
type FallbackFormSchema = BaseSchema & {
|
||||
component: Component | Exclude<ComponentType, RegisteredName>;
|
||||
componentProps?: CoreFormSchema<ComponentType>['componentProps'];
|
||||
};
|
||||
|
||||
export type VbenFormSchema = DiscriminatedFormSchema | FallbackFormSchema;
|
||||
@@ -1,9 +1,7 @@
|
||||
import type {
|
||||
VbenFormSchema as FormSchema,
|
||||
VbenFormProps,
|
||||
} from '@vben/common-ui';
|
||||
import type { VbenFormProps as CoreFormProps } from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
import type { VbenFormSchema } from './form-schema';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -41,9 +39,14 @@ async function initSetupVbenForm() {
|
||||
});
|
||||
}
|
||||
|
||||
const useVbenForm = useForm<ComponentType>;
|
||||
type VbenFormProps = Omit<CoreFormProps<ComponentType>, 'schema'> & {
|
||||
schema?: VbenFormSchema[];
|
||||
};
|
||||
|
||||
function useVbenForm(options: VbenFormProps) {
|
||||
return useForm<ComponentType>(options as CoreFormProps<ComponentType>);
|
||||
}
|
||||
|
||||
export { initSetupVbenForm, useVbenForm, z };
|
||||
|
||||
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||
export type { VbenFormProps };
|
||||
export type { VbenFormProps, VbenFormSchema };
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type { AnyPromiseFunction } from '@vben/types';
|
||||
import type {
|
||||
ApiComponentProps,
|
||||
ApiComponentOptionsItem as OptionsItem,
|
||||
} from './types';
|
||||
|
||||
import { computed, nextTick, ref, unref, useAttrs, watch } from 'vue';
|
||||
|
||||
@@ -11,72 +12,9 @@ import { cloneDeep, get, isEqual, isFunction } from '@vben-core/shared/utils';
|
||||
|
||||
import { objectOmit } from '@vueuse/core';
|
||||
|
||||
type OptionsItem = {
|
||||
[name: string]: any;
|
||||
children?: OptionsItem[];
|
||||
disabled?: boolean;
|
||||
label?: string;
|
||||
value?: string;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
/** 组件 */
|
||||
component: Component;
|
||||
/** 是否将value从数字转为string */
|
||||
numberToString?: boolean;
|
||||
/** 获取options数据的函数 */
|
||||
api?: (arg?: any) => Promise<OptionsItem[] | Record<string, any>>;
|
||||
/** 传递给api的参数 */
|
||||
params?: Record<string, any>;
|
||||
/** 从api返回的结果中提取options数组的字段名 */
|
||||
resultField?: string;
|
||||
/** label字段名 */
|
||||
labelField?: string;
|
||||
/** children字段名,需要层级数据的组件可用 */
|
||||
childrenField?: string;
|
||||
/** value字段名 */
|
||||
valueField?: string;
|
||||
/** disabled字段名 */
|
||||
disabledField?: string;
|
||||
/** 组件接收options数据的属性名 */
|
||||
optionsPropName?: string;
|
||||
/** 是否立即调用api */
|
||||
immediate?: boolean;
|
||||
/** 每次`visibleEvent`事件发生时都重新请求数据 */
|
||||
alwaysLoad?: boolean;
|
||||
/** 在api请求之前的回调函数 */
|
||||
beforeFetch?: AnyPromiseFunction<any, any>;
|
||||
/** 在api请求之前的判断是否允许请求的回调函数 */
|
||||
shouldFetch?: AnyPromiseFunction<any, boolean>;
|
||||
/** 在api请求之后的回调函数 */
|
||||
afterFetch?: AnyPromiseFunction<any, any>;
|
||||
/** 直接传入选项数据,也作为api返回空数据时的后备数据 */
|
||||
options?: OptionsItem[];
|
||||
/** 组件的插槽名称,用来显示一个"加载中"的图标 */
|
||||
loadingSlot?: string;
|
||||
/** 触发api请求的事件名 */
|
||||
visibleEvent?: string;
|
||||
/** 组件的v-model属性名,默认为modelValue。部分组件可能为value */
|
||||
modelPropName?: string;
|
||||
/**
|
||||
* 自动选择
|
||||
* - `first`:自动选择第一个选项
|
||||
* - `last`:自动选择最后一个选项
|
||||
* - `one`: 当请求的结果只有一个选项时,自动选择该选项
|
||||
* - 函数:自定义选择逻辑,函数的参数为请求的结果数组,返回值为选择的选项
|
||||
* - false:不自动选择(默认)
|
||||
*/
|
||||
autoSelect?:
|
||||
| 'first'
|
||||
| 'last'
|
||||
| 'one'
|
||||
| ((item: OptionsItem[]) => OptionsItem)
|
||||
| false;
|
||||
}
|
||||
|
||||
defineOptions({ name: 'ApiComponent', inheritAttrs: false });
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<ApiComponentProps>(), {
|
||||
labelField: 'label',
|
||||
valueField: 'value',
|
||||
disabledField: 'disabled',
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
export { default as ApiComponent } from './api-component.vue';
|
||||
export type {
|
||||
ApiComponentOptionsItem,
|
||||
ApiComponentProps,
|
||||
ApiComponentSharedProps,
|
||||
} from './types';
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type { AnyPromiseFunction } from '@vben/types';
|
||||
|
||||
export type ApiComponentOptionsItem = {
|
||||
[name: string]: any;
|
||||
children?: ApiComponentOptionsItem[];
|
||||
disabled?: boolean;
|
||||
label?: string;
|
||||
value?: string;
|
||||
};
|
||||
|
||||
export interface ApiComponentProps {
|
||||
/** 组件 */
|
||||
component: Component;
|
||||
/** 是否将value从数字转为string */
|
||||
numberToString?: boolean;
|
||||
/** 获取options数据的函数 */
|
||||
api?: (arg?: any) => Promise<ApiComponentOptionsItem[] | Record<string, any>>;
|
||||
/** 传递给api的参数 */
|
||||
params?: Record<string, any>;
|
||||
/** 从api返回的结果中提取options数组的字段名 */
|
||||
resultField?: string;
|
||||
/** label字段名 */
|
||||
labelField?: string;
|
||||
/** children字段名,需要层级数据的组件可用 */
|
||||
childrenField?: string;
|
||||
/** value字段名 */
|
||||
valueField?: string;
|
||||
/** disabled字段名 */
|
||||
disabledField?: string;
|
||||
/** 组件接收options数据的属性名 */
|
||||
optionsPropName?: string;
|
||||
/** 是否立即调用api */
|
||||
immediate?: boolean;
|
||||
/** 每次`visibleEvent`事件发生时都重新请求数据 */
|
||||
alwaysLoad?: boolean;
|
||||
/** 在api请求之前的回调函数 */
|
||||
beforeFetch?: AnyPromiseFunction<any, any>;
|
||||
/** 在api请求之前的判断是否允许请求的回调函数 */
|
||||
shouldFetch?: AnyPromiseFunction<any, boolean>;
|
||||
/** 在api请求之后的回调函数 */
|
||||
afterFetch?: AnyPromiseFunction<any, any>;
|
||||
/** 直接传入选项数据,也作为api返回空数据时的后备数据 */
|
||||
options?: ApiComponentOptionsItem[];
|
||||
/** 组件的插槽名称,用来显示一个"加载中"的图标 */
|
||||
loadingSlot?: string;
|
||||
/** 触发api请求的事件名 */
|
||||
visibleEvent?: string;
|
||||
/** 组件的v-model属性名,默认为modelValue。部分组件可能为value */
|
||||
modelPropName?: string;
|
||||
/**
|
||||
* 自动选择
|
||||
* - `first`:自动选择第一个选项
|
||||
* - `last`:自动选择最后一个选项
|
||||
* - `one`: 当请求的结果只有一个选项时,自动选择该选项
|
||||
* - 函数:自定义选择逻辑,函数的参数为请求的结果数组,返回值为选择的选项
|
||||
* - false:不自动选择(默认)
|
||||
*/
|
||||
autoSelect?:
|
||||
| 'first'
|
||||
| 'last'
|
||||
| 'one'
|
||||
| ((item: ApiComponentOptionsItem[]) => ApiComponentOptionsItem)
|
||||
| false;
|
||||
}
|
||||
|
||||
export type ApiComponentSharedProps = Omit<ApiComponentProps, 'component'>;
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { VNode } from 'vue';
|
||||
import type { IconPickerProps } from './types';
|
||||
|
||||
import { computed, ref, useAttrs, watch, watchEffect } from 'vue';
|
||||
|
||||
@@ -28,28 +28,7 @@ import { objectOmit, refDebounced, watchDebounced } from '@vueuse/core';
|
||||
|
||||
import { fetchIconsData } from './icons';
|
||||
|
||||
interface Props {
|
||||
pageSize?: number;
|
||||
/** 图标集的名字 */
|
||||
prefix?: string;
|
||||
/** 是否自动请求API以获得图标集的数据.提供prefix时有效 */
|
||||
autoFetchApi?: boolean;
|
||||
/**
|
||||
* 图标列表
|
||||
*/
|
||||
icons?: string[];
|
||||
/** Input组件 */
|
||||
inputComponent?: VNode;
|
||||
/** 图标插槽名,预览图标将被渲染到此插槽中 */
|
||||
iconSlot?: string;
|
||||
/** input组件的值属性名称 */
|
||||
modelValueProp?: string;
|
||||
/** 图标样式 */
|
||||
iconClass?: string;
|
||||
type?: 'icon' | 'input';
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<IconPickerProps>(), {
|
||||
prefix: 'ant-design',
|
||||
pageSize: 36,
|
||||
icons: () => [],
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { default as IconPicker } from './icon-picker.vue';
|
||||
export type { IconPickerProps } from './types';
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { VNode } from 'vue';
|
||||
|
||||
export interface IconPickerProps {
|
||||
pageSize?: number;
|
||||
/** 图标集的名字 */
|
||||
prefix?: string;
|
||||
/** 是否自动请求API以获得图标集的数据.提供prefix时有效 */
|
||||
autoFetchApi?: boolean;
|
||||
/**
|
||||
* 图标列表
|
||||
*/
|
||||
icons?: string[];
|
||||
/** Input组件 */
|
||||
inputComponent?: VNode;
|
||||
/** 图标插槽名,预览图标将被渲染到此插槽中 */
|
||||
iconSlot?: string;
|
||||
/** input组件的值属性名称 */
|
||||
modelValueProp?: string;
|
||||
/** 图标样式 */
|
||||
iconClass?: string;
|
||||
type?: 'icon' | 'input';
|
||||
}
|
||||
96
playground/src/adapter/form-schema.ts
Normal file
96
playground/src/adapter/form-schema.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import type {
|
||||
AutoCompleteProps,
|
||||
ButtonProps,
|
||||
CascaderProps,
|
||||
CheckboxGroupProps,
|
||||
CheckboxProps,
|
||||
DatePickerProps,
|
||||
DividerProps,
|
||||
InputNumberProps,
|
||||
InputProps,
|
||||
MentionsProps,
|
||||
RadioGroupProps,
|
||||
RadioProps,
|
||||
RateProps,
|
||||
SelectProps,
|
||||
SpaceProps,
|
||||
SwitchProps,
|
||||
TextAreaProps,
|
||||
TimePickerProps,
|
||||
TreeSelectProps,
|
||||
UploadProps,
|
||||
} from 'ant-design-vue';
|
||||
import type { RangePickerProps } from 'ant-design-vue/es/date-picker';
|
||||
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type {
|
||||
ApiComponentSharedProps,
|
||||
VbenFormSchema as CoreFormSchema,
|
||||
IconPickerProps,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
|
||||
/**
|
||||
* 对象形式:使用适配器里为各 `component` 声明的 Props 类型 `P`;
|
||||
* 与 `Record<string, any>` 相交是为了满足核心库 `MaybeComponentProps` 的索引签名。
|
||||
* 函数形式:通过联合 `CoreFormSchema['componentProps']`,与表单核心对动态 `componentProps` 的约定保持一致。
|
||||
*/
|
||||
type SchemaComponentProps<P> =
|
||||
| CoreFormSchema<ComponentType>['componentProps']
|
||||
| (P & Record<string, any>);
|
||||
|
||||
/**
|
||||
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
|
||||
*/
|
||||
interface FormSchemaComponentPropsMap {
|
||||
ApiCascader: ApiComponentSharedProps & CascaderProps;
|
||||
ApiSelect: ApiComponentSharedProps & SelectProps;
|
||||
ApiTreeSelect: ApiComponentSharedProps & TreeSelectProps;
|
||||
AutoComplete: AutoCompleteProps;
|
||||
Cascader: CascaderProps;
|
||||
Checkbox: CheckboxProps;
|
||||
CheckboxGroup: CheckboxGroupProps;
|
||||
DatePicker: DatePickerProps;
|
||||
DefaultButton: ButtonProps;
|
||||
Divider: DividerProps;
|
||||
IconPicker: IconPickerProps;
|
||||
Input: InputProps;
|
||||
InputNumber: InputNumberProps;
|
||||
InputPassword: InputProps;
|
||||
Mentions: MentionsProps;
|
||||
PrimaryButton: ButtonProps;
|
||||
Radio: RadioProps;
|
||||
RadioGroup: RadioGroupProps;
|
||||
RangePicker: RangePickerProps;
|
||||
Rate: RateProps;
|
||||
Select: SelectProps;
|
||||
Space: SpaceProps;
|
||||
Switch: SwitchProps;
|
||||
Textarea: TextAreaProps;
|
||||
TimePicker: TimePickerProps;
|
||||
TreeSelect: TreeSelectProps;
|
||||
Upload: UploadProps;
|
||||
}
|
||||
|
||||
type BaseSchema = Omit<
|
||||
CoreFormSchema<ComponentType>,
|
||||
'component' | 'componentProps'
|
||||
>;
|
||||
|
||||
type RegisteredName = keyof FormSchemaComponentPropsMap;
|
||||
|
||||
type DiscriminatedFormSchema = {
|
||||
[K in RegisteredName]: BaseSchema & {
|
||||
component: K;
|
||||
componentProps?: SchemaComponentProps<FormSchemaComponentPropsMap[K]>;
|
||||
};
|
||||
}[RegisteredName];
|
||||
|
||||
type FallbackFormSchema = BaseSchema & {
|
||||
component: Component | Exclude<ComponentType, RegisteredName>;
|
||||
componentProps?: CoreFormSchema<ComponentType>['componentProps'];
|
||||
};
|
||||
|
||||
export type VbenFormSchema = DiscriminatedFormSchema | FallbackFormSchema;
|
||||
@@ -1,9 +1,7 @@
|
||||
import type {
|
||||
VbenFormSchema as FormSchema,
|
||||
VbenFormProps,
|
||||
} from '@vben/common-ui';
|
||||
import type { VbenFormProps as CoreFormProps } from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
import type { VbenFormSchema } from './form-schema';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -40,8 +38,13 @@ async function initSetupVbenForm() {
|
||||
});
|
||||
}
|
||||
|
||||
const useVbenForm = useForm<ComponentType>;
|
||||
type VbenFormProps = Omit<CoreFormProps<ComponentType>, 'schema'> & {
|
||||
schema?: VbenFormSchema[];
|
||||
};
|
||||
|
||||
function useVbenForm(options: VbenFormProps) {
|
||||
return useForm<ComponentType>(options as CoreFormProps<ComponentType>);
|
||||
}
|
||||
|
||||
export { initSetupVbenForm, useVbenForm, z };
|
||||
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||
export type { VbenFormProps };
|
||||
export type { VbenFormProps, VbenFormSchema };
|
||||
|
||||
Reference in New Issue
Block a user