feat: 优化表单提示
parent
eeed362320
commit
17c695d065
|
|
@ -1,4 +1,5 @@
|
|||
import { Form, FormInstance, FormItem } from "@arco-design/web-vue";
|
||||
import { Form, FormInstance } from "@arco-design/web-vue";
|
||||
import { useVModel } from "@vueuse/core";
|
||||
import { PropType } from "vue";
|
||||
import { FormContextKey } from "../core/useFormContext";
|
||||
import { useFormItems } from "../core/useFormItems";
|
||||
|
|
@ -6,7 +7,6 @@ import { useFormModel } from "../core/useFormModel";
|
|||
import { useFormRef } from "../core/useFormRef";
|
||||
import { useFormSubmit } from "../core/useFormSubmit";
|
||||
import { AnFormItem, IAnFormItem } from "./FormItem";
|
||||
import { useVModel } from "@vueuse/core";
|
||||
|
||||
/**
|
||||
* 表单组件
|
||||
|
|
@ -16,6 +16,12 @@ export const AnForm = defineComponent({
|
|||
props: {
|
||||
/**
|
||||
* 表单数据
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* id: undefined
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
model: {
|
||||
type: Object as PropType<Recordable>,
|
||||
|
|
@ -30,12 +36,24 @@ export const AnForm = defineComponent({
|
|||
},
|
||||
/**
|
||||
* 提交表单
|
||||
* @example
|
||||
* ```ts
|
||||
* (model) => {
|
||||
* return api.user.addUser(model)
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
submit: {
|
||||
type: [String, Function, Object] as PropType<IAnFormSubmit>,
|
||||
},
|
||||
/**
|
||||
* 传给Form组件的参数
|
||||
* @exmaple
|
||||
* ```ts
|
||||
* {
|
||||
* layout: 'vertical'
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
formProps: {
|
||||
type: Object as IAnFormProps,
|
||||
|
|
|
|||
|
|
@ -59,14 +59,12 @@ export const AnFormItem = defineComponent({
|
|||
if (Slot) {
|
||||
return <Slot {...props} />;
|
||||
}
|
||||
|
||||
const Setter = setterMap[props.item.setter as SetterType]?.render as any;
|
||||
const Setter = setterMap[props.item.setter as SetterType]?.setter as any;
|
||||
if (!Setter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Setter {...props.item.nodeProps} v-model={props.model[props.item.field]}>
|
||||
<Setter {...props.item.setterProps} v-model={props.model[props.item.field]}>
|
||||
{setterSlots.value}
|
||||
</Setter>
|
||||
);
|
||||
|
|
@ -152,13 +150,19 @@ export type IAnFormItemBase = {
|
|||
/**
|
||||
* 字段名
|
||||
* @description 字段名唯一,支持特殊语法
|
||||
* @required
|
||||
* @example
|
||||
* ```ts
|
||||
* 'username'
|
||||
* ```
|
||||
*/
|
||||
field: string;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
* @example '昵称'
|
||||
* @example
|
||||
* ```ts
|
||||
* '昵称'
|
||||
* ```
|
||||
*/
|
||||
label?: string;
|
||||
|
||||
|
|
@ -170,19 +174,29 @@ export type IAnFormItemBase = {
|
|||
|
||||
/**
|
||||
* 是否可见
|
||||
* @example (model) => Boolean(model.id)
|
||||
* @example
|
||||
* ```ts
|
||||
* (props) => Boolean(props.model.id)
|
||||
* ```
|
||||
*/
|
||||
visible?: IAnFormItemBoolFn;
|
||||
|
||||
/**
|
||||
* 是否禁用
|
||||
* @example (model) => Boolean(model.id)
|
||||
* @example
|
||||
* ```ts
|
||||
* (props) => Boolean(props.model.id)
|
||||
* ```
|
||||
*/
|
||||
disable?: IAnFormItemBoolFn;
|
||||
|
||||
/**
|
||||
* 选项
|
||||
* @description 适用于下拉框等组件
|
||||
* @example
|
||||
* ```ts
|
||||
* [{ label: '方式1', value: 1 }]
|
||||
* ```
|
||||
*/
|
||||
options?: IAnFormItemOption[] | ((args: IAnFormItemFnProps) => IAnFormItemOption[] | Promise<IAnFormItemOption[]>);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useVisible } from "@/hooks/useVisible";
|
||||
import { Button, ButtonInstance, Modal } from "@arco-design/web-vue";
|
||||
import { PropType } from "vue";
|
||||
import { IAnFormItem } from "./FormItem";
|
||||
import { AnForm, IAnFormProps, IAnFormSubmit } from "./Form";
|
||||
import { useModalTrigger } from "../core/useModalTrigger";
|
||||
import { useModalSubmit } from "../core/useModalSubmit";
|
||||
import { useVisible } from "@/hooks/useVisible";
|
||||
import { useModalTrigger } from "../core/useModalTrigger";
|
||||
import { AnForm, IAnFormProps, IAnFormSubmit } from "./Form";
|
||||
import { IAnFormItem } from "./FormItem";
|
||||
|
||||
/**
|
||||
* 表单组件
|
||||
|
|
@ -14,11 +14,11 @@ export const AnFormModal = defineComponent({
|
|||
props: {
|
||||
/**
|
||||
* 弹窗标题
|
||||
* @default '添加'
|
||||
* @default '新增'
|
||||
*/
|
||||
title: {
|
||||
type: [String, Function] as PropType<ModalType>,
|
||||
default: "添加",
|
||||
default: "新增",
|
||||
},
|
||||
/**
|
||||
* 触发元素
|
||||
|
|
|
|||
|
|
@ -4,24 +4,42 @@ export type SetterMap = typeof setterMap;
|
|||
|
||||
export type SetterType = keyof SetterMap;
|
||||
|
||||
export type SetterItem = {
|
||||
[key in SetterType]: Partial<
|
||||
Omit<SetterMap[key], 'setter'> & {
|
||||
/**
|
||||
* 控件类型
|
||||
* @example 'input'
|
||||
*/
|
||||
setter: key;
|
||||
/**
|
||||
* 控件插槽
|
||||
*/
|
||||
setterSlots: Recordable;
|
||||
/**
|
||||
* 控件参数
|
||||
*/
|
||||
setterProps: Recordable;
|
||||
}
|
||||
>;
|
||||
}[SetterType];
|
||||
export type SetterItemMap = {
|
||||
[key in SetterType]: {
|
||||
/**
|
||||
* 控件类型
|
||||
* @example
|
||||
* ```ts
|
||||
* 'input'
|
||||
* ```
|
||||
*/
|
||||
setter?: key;
|
||||
/**
|
||||
* 控件参数
|
||||
* @example
|
||||
* ```tsx
|
||||
* { type: "password" }
|
||||
* ```
|
||||
*/
|
||||
setterProps?: SetterMap[key]['setterProps'];
|
||||
/**
|
||||
* 控件插槽
|
||||
* @example
|
||||
* ```tsx
|
||||
* {
|
||||
* help: (props) => {
|
||||
* return <span>
|
||||
* {props.item.label}
|
||||
* </span>
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
setterSlots?: SetterMap[key]['setterSlots'];
|
||||
};
|
||||
};
|
||||
|
||||
export type SetterItem = SetterItemMap[SetterType];
|
||||
|
||||
export { setterMap };
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export function useFormItems(items: Ref<IAnFormItem[]>, model: Ref<Recordable>)
|
|||
const getItemOptions = (field: string) => {
|
||||
const item = getItem(field);
|
||||
if (item) {
|
||||
return (item.nodeProps as any)?.options;
|
||||
return (item.setterProps as any)?.options;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
import { FormItem, useItems } from "./useItems";
|
||||
import { AnForm, IAnForm } from "../components/Form";
|
||||
import { FormItem, useItems } from "./useItems";
|
||||
|
||||
export type FormUseOptions = Partial<Omit<IAnForm, "items">> & {
|
||||
/**
|
||||
* 表单项
|
||||
* @example
|
||||
* ```ts
|
||||
* [{
|
||||
* field: 'name',
|
||||
* label: '昵称',
|
||||
* setter: 'input'
|
||||
* }]
|
||||
* ```
|
||||
*/
|
||||
items?: FormItem[];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,39 +1,49 @@
|
|||
import { defaultsDeep, merge, omit } from "lodash-es";
|
||||
import { Rule, useRules } from "./useRules";
|
||||
import { IAnFormItem } from "../components/FormItem";
|
||||
import { setterMap } from "../components/FormSetter";
|
||||
import { defaultsDeep, merge, omit } from 'lodash-es';
|
||||
import { IAnFormItem, IAnFormItemBase } from '../components/FormItem';
|
||||
import { SetterItem, setterMap } from '../components/FormSetter';
|
||||
import { Rule, useRules } from './useRules';
|
||||
|
||||
/**
|
||||
* 表单项数据
|
||||
*/
|
||||
export type FormItem = Omit<IAnFormItem, "rules"> & {
|
||||
/**
|
||||
* 默认值
|
||||
* @example 1
|
||||
*/
|
||||
value?: any;
|
||||
export type FormItem = Omit<IAnFormItemBase, 'rules'> &
|
||||
SetterItem & {
|
||||
/**
|
||||
* 默认值
|
||||
* @example
|
||||
* ```ts
|
||||
* '1'
|
||||
* ```
|
||||
*/
|
||||
value?: any;
|
||||
|
||||
/**
|
||||
* 是否必填
|
||||
* @default false
|
||||
*/
|
||||
required?: boolean;
|
||||
/**
|
||||
* 是否必填
|
||||
* @default
|
||||
* ```ts
|
||||
* false
|
||||
* ```
|
||||
*/
|
||||
required?: boolean;
|
||||
|
||||
/**
|
||||
* 校验规则
|
||||
* @example ['email']
|
||||
*/
|
||||
rules?: Rule[];
|
||||
};
|
||||
/**
|
||||
* 校验规则
|
||||
* @example
|
||||
* ```ts
|
||||
* ['email']
|
||||
* ```
|
||||
*/
|
||||
rules?: Rule[];
|
||||
};
|
||||
|
||||
const ITEM: Partial<FormItem> = {
|
||||
setter: "input",
|
||||
setter: 'input',
|
||||
itemProps: {},
|
||||
};
|
||||
|
||||
const SUBMIT_ITEM: FormItem = {
|
||||
field: "id",
|
||||
setter: "submit",
|
||||
field: 'id',
|
||||
setter: 'submit',
|
||||
itemProps: {
|
||||
hideLabel: true,
|
||||
},
|
||||
|
|
@ -46,19 +56,19 @@ export function useItems(list: FormItem[], model: Recordable, submit: boolean) {
|
|||
for (const item of list) {
|
||||
let target: any = defaultsDeep({}, ITEM);
|
||||
|
||||
if (!item.setter || typeof item.setter === "string") {
|
||||
const defaults = setterMap[item.setter ?? "input"];
|
||||
if (!item.setter || typeof item.setter === 'string') {
|
||||
const defaults = setterMap[item.setter ?? 'input'];
|
||||
if (defaults) {
|
||||
defaultsDeep(target, defaults);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.setter === "submit") {
|
||||
if (item.setter === 'submit') {
|
||||
target = merge(target, SUBMIT_ITEM);
|
||||
hasSubmit = true;
|
||||
}
|
||||
|
||||
target = merge(target, omit(item, ["required", "rules"]));
|
||||
target = merge(target, omit(item, ['required', 'rules']));
|
||||
|
||||
const rules = useRules(item);
|
||||
if (rules) {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
import { Cascader, CascaderInstance } from "@arco-design/web-vue";
|
||||
import { initOptions } from "../utils/initOptions";
|
||||
import { Cascader, CascaderInstance } from '@arco-design/web-vue';
|
||||
import { initOptions } from '../utils/initOptions';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = CascaderInstance["$props"];
|
||||
type CascaderProps = CascaderInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: Cascader,
|
||||
init: initOptions,
|
||||
nodeProps: {
|
||||
placeholder: "请选择",
|
||||
type CascaderSlots = 'label' | 'prefix' | 'arrowIcon' | 'loadingIcon' | 'searchIcon' | 'empty' | 'option';
|
||||
|
||||
export default defineSetter<CascaderProps, CascaderSlots>({
|
||||
setter: Cascader,
|
||||
setterProps: {
|
||||
placeholder: '请选择',
|
||||
allowClear: true,
|
||||
expandTrigger: "hover",
|
||||
} as Props,
|
||||
};
|
||||
expandTrigger: 'hover',
|
||||
},
|
||||
onSetup: initOptions as any,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
export default {
|
||||
render: () => {
|
||||
return "1";
|
||||
},
|
||||
nodeProps: {},
|
||||
};
|
||||
import { defineSetter } from './util';
|
||||
|
||||
export default defineSetter<{ a: number }, '11'>({
|
||||
setter: () => '1',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import { DatePicker, DatePickerInstance } from "@arco-design/web-vue";
|
||||
import { DatePicker, DatePickerInstance } from '@arco-design/web-vue';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = DatePickerInstance["$props"];
|
||||
type DateProps = DatePickerInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: DatePicker,
|
||||
nodeProps: {
|
||||
placeholder: "请选择",
|
||||
type DateSlots = 'prefix' | 'suffixIcon' | 'iconNextDouble' | 'iconPrevDouble' | 'iconNext' | 'iconPrev' | 'cell' | 'extra';
|
||||
|
||||
export default defineSetter<DateProps, DateSlots>({
|
||||
setter: DatePicker,
|
||||
setterProps: {
|
||||
placeholder: '请选择',
|
||||
allowClear: true,
|
||||
} as Props,
|
||||
};
|
||||
} as any,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import { RangePicker, RangePickerInstance } from "@arco-design/web-vue";
|
||||
import { RangePicker, RangePickerInstance } from '@arco-design/web-vue';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = RangePickerInstance["$props"];
|
||||
type RangeProps = RangePickerInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: RangePicker,
|
||||
nodeProps: {
|
||||
type RangeSlots = "1";
|
||||
|
||||
export default defineSetter<RangeProps, RangeSlots>({
|
||||
setter: RangePicker,
|
||||
setterProps: {
|
||||
allowClear: true,
|
||||
} as Props,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import { Input, InputInstance } from "@arco-design/web-vue";
|
||||
import { Input, InputInstance } from '@arco-design/web-vue';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = InputInstance["$props"];
|
||||
type InputProps = InputInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: Input,
|
||||
nodeProps: {
|
||||
placeholder: "请输入",
|
||||
type InputSlots = "2";
|
||||
|
||||
export default defineSetter<InputProps, InputSlots>({
|
||||
setter: Input,
|
||||
setterProps: {
|
||||
placeholder: '请输入',
|
||||
allowClear: true,
|
||||
} as Props,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
import { InputInstance, InputNumber, InputNumberInstance } from "@arco-design/web-vue";
|
||||
import { InputInstance, InputNumber, InputNumberInstance } from '@arco-design/web-vue';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = InputInstance["$props"] & InputNumberInstance["$props"];
|
||||
type NumberProps = InputInstance['$props'] | InputNumberInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: InputNumber,
|
||||
nodeProps: {
|
||||
placeholder: "请输入",
|
||||
type NumberSlots = "3";
|
||||
|
||||
export default defineSetter<NumberProps, NumberSlots>({
|
||||
setter: InputNumber,
|
||||
setterProps: {
|
||||
placeholder: '请输入',
|
||||
defaultValue: 0,
|
||||
allowClear: true,
|
||||
} as Props,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import { InputInstance, InputPassword, InputPasswordInstance } from "@arco-design/web-vue";
|
||||
import { InputInstance, InputPassword, InputPasswordInstance } from '@arco-design/web-vue';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = InputInstance["$props"] & InputPasswordInstance["$props"];
|
||||
type PasswordProps = InputInstance['$props'] & InputPasswordInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: InputPassword,
|
||||
nodeProps: {
|
||||
placeholder: "请输入",
|
||||
} as Props,
|
||||
};
|
||||
type PasswordSlots = "4";
|
||||
|
||||
export default defineSetter<PasswordProps, PasswordSlots>({
|
||||
setter: InputPassword,
|
||||
setterProps: {
|
||||
placeholder: '请输入',
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import { InputInstance, InputSearch, InputSearchInstance } from "@arco-design/web-vue";
|
||||
import { InputInstance, InputSearch, InputSearchInstance } from '@arco-design/web-vue';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = InputInstance["$props"] & InputSearchInstance["$props"];
|
||||
type SearchProps = InputInstance['$props'] & InputSearchInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: InputSearch,
|
||||
nodeProps: {
|
||||
placeholder: "请输入",
|
||||
type SearchSlots = "5";
|
||||
|
||||
export default defineSetter<SearchProps, SearchSlots>({
|
||||
setter: InputSearch,
|
||||
setterProps: {
|
||||
placeholder: '请输入',
|
||||
allowClear: true,
|
||||
} as Props,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
import { Select, SelectInstance, SelectOptionData } from "@arco-design/web-vue";
|
||||
import { initOptions } from "../utils/initOptions";
|
||||
import { Select, SelectInstance } from '@arco-design/web-vue';
|
||||
import { initOptions } from '../utils/initOptions';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
export default {
|
||||
render: Select,
|
||||
init: initOptions,
|
||||
nodeProps: {
|
||||
placeholder: "请选择",
|
||||
type SelectProps = SelectInstance['$props'];
|
||||
|
||||
type SelectSlots = "6";
|
||||
|
||||
export default defineSetter<SelectProps, SelectSlots>({
|
||||
setter: Select,
|
||||
onSetup: initOptions as any,
|
||||
setterProps: {
|
||||
placeholder: '请选择',
|
||||
allowClear: true,
|
||||
allowSearch: true,
|
||||
options: [],
|
||||
} as SelectInstance["$props"],
|
||||
options: [] as SelectOptionData[] | ((arg: any) => Recordable[] | Promise<Recordable[]>) | undefined,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { Button } from "@arco-design/web-vue";
|
||||
import { FormContextKey } from "../core/useFormContext";
|
||||
import { defineSetter } from "./util";
|
||||
|
||||
export default {
|
||||
render() {
|
||||
export default defineSetter<{ a1?: number }, "10">({
|
||||
setter() {
|
||||
const { loading, submitForm, resetModel } = inject(FormContextKey)!;
|
||||
return (
|
||||
<>
|
||||
|
|
@ -15,5 +16,5 @@ export default {
|
|||
</>
|
||||
);
|
||||
},
|
||||
nodeProps: {},
|
||||
};
|
||||
setterProps: {},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import { InputInstance, Textarea, TextareaInstance } from "@arco-design/web-vue";
|
||||
import { InputInstance, Textarea, TextareaInstance } from '@arco-design/web-vue';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = InputInstance["$props"] & TextareaInstance["$props"];
|
||||
type TextareaProps = InputInstance['$props'] & TextareaInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: Textarea,
|
||||
nodeProps: {
|
||||
placeholder: "请输入",
|
||||
type TextareaSlots = "7";
|
||||
|
||||
export default defineSetter<TextareaProps, TextareaSlots>({
|
||||
setter: Textarea,
|
||||
setterProps: {
|
||||
placeholder: '请输入',
|
||||
allowClear: true,
|
||||
} as Props,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import { TimePicker, TimePickerInstance } from "@arco-design/web-vue";
|
||||
import { TimePicker, TimePickerInstance } from '@arco-design/web-vue';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = TimePickerInstance["$props"];
|
||||
type TimeProps = TimePickerInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: TimePicker,
|
||||
nodeProps: {
|
||||
type TimeSlots = "8";
|
||||
|
||||
export default defineSetter<TimeProps, TimeSlots>({
|
||||
setter: TimePicker,
|
||||
setterProps: {
|
||||
allowClear: true,
|
||||
} as Props,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
import { TreeSelect, TreeSelectInstance } from "@arco-design/web-vue";
|
||||
import { initOptions } from "../utils/initOptions";
|
||||
import { TreeSelect, TreeSelectInstance } from '@arco-design/web-vue';
|
||||
import { initOptions } from '../utils/initOptions';
|
||||
import { defineSetter } from './util';
|
||||
|
||||
type Props = TreeSelectInstance["$props"];
|
||||
type TreeSelectProps = TreeSelectInstance['$props'];
|
||||
|
||||
export default {
|
||||
render: TreeSelect,
|
||||
init: (arg: any) => initOptions(arg, "data"),
|
||||
nodeProps: {
|
||||
placeholder: "请选择",
|
||||
type TreeSelectSlots = "9";
|
||||
|
||||
export default defineSetter<TreeSelectProps, TreeSelectSlots>({
|
||||
setter: TreeSelect,
|
||||
onSetup: (arg: any) => initOptions(arg, 'data') as any,
|
||||
setterProps: {
|
||||
placeholder: '请选择',
|
||||
allowClear: true,
|
||||
allowSearch: true,
|
||||
options: [],
|
||||
} as Props,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import cascader from "./Cascader";
|
||||
import custom from "./Custom";
|
||||
import date from "./Date";
|
||||
import input from "./Input";
|
||||
import number from "./Number";
|
||||
import password from "./Password";
|
||||
import search from "./Search";
|
||||
import select from "./Select";
|
||||
import submit from "./Submit";
|
||||
import textarea from "./Textarea";
|
||||
import time from "./Time";
|
||||
import treeSelect from "./TreeSelect";
|
||||
import dateRange from "./DateRange";
|
||||
import cascader from './Cascader';
|
||||
import custom from './Custom';
|
||||
import date from './Date';
|
||||
import dateRange from './DateRange';
|
||||
import input from './Input';
|
||||
import number from './Number';
|
||||
import password from './Password';
|
||||
import search from './Search';
|
||||
import select from './Select';
|
||||
import submit from './Submit';
|
||||
import textarea from './Textarea';
|
||||
import time from './Time';
|
||||
import treeSelect from './TreeSelect';
|
||||
|
||||
export default {
|
||||
input,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
import { Component } from 'vue';
|
||||
import { IAnFormItemBase, IAnFormItemSlot } from '../components/FormItem';
|
||||
|
||||
export interface ItemSetter<P extends object, S extends string> {
|
||||
/**
|
||||
* 输入组件
|
||||
*/
|
||||
setter: Component;
|
||||
|
||||
/**
|
||||
* 输入组件参数
|
||||
*/
|
||||
setterProps?: P;
|
||||
|
||||
/**
|
||||
* 空间插槽
|
||||
*/
|
||||
setterSlots?: {
|
||||
/**
|
||||
* 控件插槽
|
||||
* @example
|
||||
* ```tsx
|
||||
* (props) => {
|
||||
* return <span>{props.item.label}</span>
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
[key in S]?: IAnFormItemSlot;
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化钩子
|
||||
*/
|
||||
onSetup?: (model: Recordable, item: IAnFormItemBase, items: IAnFormItemBase[]) => void;
|
||||
}
|
||||
|
||||
export function defineSetter<P extends object, S extends string>(setter: ItemSetter<P, S>) {
|
||||
return setter;
|
||||
}
|
||||
|
|
@ -1,27 +1,26 @@
|
|||
import { Component } from "vue";
|
||||
import { IAnFormItem, IAnFormItemBase } from "../components/FormItem";
|
||||
import { Component } from 'vue';
|
||||
import { IAnFormItemBase, IAnFormItemSlot } from '../components/FormItem';
|
||||
|
||||
interface Setter<T extends Component, P = T extends new (...args: any) => any ? InstanceType<T>["$props"] : any> {
|
||||
export interface ItemSetter<P extends object, S extends string> {
|
||||
/**
|
||||
* 输入组件
|
||||
*/
|
||||
component: T;
|
||||
setter: Component;
|
||||
|
||||
/**
|
||||
* 输入组件参数
|
||||
*/
|
||||
componentProps?: P;
|
||||
setterProps?: P;
|
||||
|
||||
/**
|
||||
* 空间插槽
|
||||
*/
|
||||
setterSlots?: {
|
||||
[key in S]?: IAnFormItemSlot;
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化钩子
|
||||
* @param model 表单数据
|
||||
* @param item 表单项
|
||||
* @param items 表单项列表
|
||||
* @returns
|
||||
*/
|
||||
onSetup?: (model: Recordable, item: IAnFormItemBase, items: IAnFormItemBase[]) => void;
|
||||
}
|
||||
|
||||
export function defineSetter<T extends Component>(options: Setter<T>): Setter<T> {
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ const { component: UpForm, model: emodel } = useForm({
|
|||
{
|
||||
field: 'xsa',
|
||||
label: '动态渲染',
|
||||
setter: 'input',
|
||||
setter: 'cascader',
|
||||
visible: props => props.model.id,
|
||||
},
|
||||
{
|
||||
|
|
@ -93,7 +93,7 @@ const { component: UpForm, model: emodel } = useForm({
|
|||
},
|
||||
},
|
||||
],
|
||||
nodeProps: {
|
||||
setterProps: {
|
||||
valueKey: 'value',
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue