feat: 表单 Schema 支持组件 Props 映射泛型,同步适配VxeGrid

This commit is contained in:
dullathanol
2026-04-04 23:40:27 +08:00
committed by allen
parent cb5e7e00f1
commit 064a6a20f0
29 changed files with 516 additions and 662 deletions

View File

@@ -3,9 +3,29 @@
* 可用于 vben-form、vben-modal、vben-drawer 等组件使用,
*/
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 { BaseFormComponentType } from '@vben/common-ui';
import type {
ApiComponentSharedProps,
BaseFormComponentType,
IconPickerProps,
} from '@vben/common-ui';
import type { Recordable } from '@vben/types';
import { defineAsyncComponent, defineComponent, h, ref } from 'vue';
@@ -118,6 +138,28 @@ export type ComponentType =
| 'Upload'
| BaseFormComponentType;
/**
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
*/
export interface ComponentPropsMap {
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;
}
async function initComponentAdapter() {
const components: Partial<Record<ComponentType, Component>> = {
// 如果你的组件体积比较大,可以使用异步加载

View File

@@ -1,76 +0,0 @@
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,
FormActions,
IconPickerProps,
} from '@vben/common-ui';
import type { ComponentType } from './component';
type ComponentProps<P> =
| ((
value: Partial<Record<string, any>>,
actions: FormActions,
) => P & Record<string, any>)
| (P & Record<string, any>);
/**
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
*/
interface ComponentPropsMap {
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 ComponentPropsMap;
type DiscriminatedFormSchema = {
[K in RegisteredName]: BaseSchema & {
component: K;
componentProps?: ComponentProps<ComponentPropsMap[K]>;
};
}[RegisteredName];
type FallbackFormSchema = BaseSchema & {
component: Component | Exclude<ComponentType, RegisteredName>;
componentProps?: CoreFormSchema<ComponentType>['componentProps'];
};
export type VbenFormSchema = DiscriminatedFormSchema | FallbackFormSchema;

View File

@@ -1,7 +1,9 @@
import type { VbenFormProps as CoreFormProps } from '@vben/common-ui';
import type {
VbenFormProps as FormProps,
VbenFormSchema as FormSchema,
} from '@vben/common-ui';
import type { ComponentType } from './component';
import type { VbenFormSchema } from './form-schema';
import type { ComponentPropsMap, ComponentType } from './component';
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
import { $t } from '@vben/locales';
@@ -35,14 +37,9 @@ async function initSetupVbenForm() {
});
}
type VbenFormProps = Omit<CoreFormProps<ComponentType>, 'schema'> & {
schema?: VbenFormSchema[];
};
function useVbenForm(options: VbenFormProps) {
return useForm<ComponentType>(options as CoreFormProps<ComponentType>);
}
const useVbenForm = useForm<ComponentType, ComponentPropsMap>;
export { initSetupVbenForm, useVbenForm, z };
export type { VbenFormProps, VbenFormSchema };
export type VbenFormSchema = FormSchema<ComponentType, ComponentPropsMap>;
export type VbenFormProps = FormProps<ComponentType, ComponentPropsMap>;

View File

@@ -1,8 +1,14 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { ComponentPropsMap, ComponentType } from './component';
import { h } from 'vue';
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
import { useVbenForm as useForm } from '@vben/common-ui';
import {
setupVbenVxeTable,
useVbenVxeGrid as useGrid,
} from '@vben/plugins/vxe-table';
import { NButton, NImage } from 'naive-ui';
@@ -62,9 +68,11 @@ setupVbenVxeTable({
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
// vxeUI.formats.add
},
useVbenForm,
useVbenForm: useVbenForm as typeof useForm,
});
export { useVbenVxeGrid };
export const useVbenVxeGrid = <T extends Record<string, any>>(
...rest: Parameters<typeof useGrid<T, ComponentType, ComponentPropsMap>>
) => useGrid<T, ComponentType, ComponentPropsMap>(...rest);
export type * from '@vben/plugins/vxe-table';