fix(BasicForm): useForm 中 scheme 选项 slot 与 component冲突 (#3133)
* fix(BasicForm): useForm 中 scheme 选项 slot 与 component冲突 * chore: add type-predicate utils * chore: add FormSchemaInner type
This commit is contained in:
parent
d30fd1d546
commit
0bb76a86d2
|
|
@ -38,7 +38,7 @@
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { FormActionType, FormProps, FormSchema } from './types/form';
|
import type { FormActionType, FormProps, FormSchemaInner as FormSchema } from './types/form';
|
||||||
import type { AdvanceState } from './types/hooks';
|
import type { AdvanceState } from './types/hooks';
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
|
|
@ -125,7 +125,12 @@
|
||||||
isHandleDateDefaultValue = true,
|
isHandleDateDefaultValue = true,
|
||||||
} = schema;
|
} = schema;
|
||||||
// handle date type
|
// handle date type
|
||||||
if (isHandleDateDefaultValue && defaultValue && dateItemType.includes(component)) {
|
if (
|
||||||
|
isHandleDateDefaultValue &&
|
||||||
|
defaultValue &&
|
||||||
|
component &&
|
||||||
|
dateItemType.includes(component)
|
||||||
|
) {
|
||||||
const valueFormat = componentProps ? componentProps['valueFormat'] : null;
|
const valueFormat = componentProps ? componentProps['valueFormat'] : null;
|
||||||
if (!Array.isArray(defaultValue)) {
|
if (!Array.isArray(defaultValue)) {
|
||||||
schema.defaultValue = valueFormat
|
schema.defaultValue = valueFormat
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,12 @@
|
||||||
import { type Recordable, type Nullable } from '@vben/types';
|
import { type Recordable, type Nullable } from '@vben/types';
|
||||||
import type { PropType, Ref } from 'vue';
|
import type { PropType, Ref } from 'vue';
|
||||||
import { computed, defineComponent, toRefs, unref } from 'vue';
|
import { computed, defineComponent, toRefs, unref } from 'vue';
|
||||||
import type { FormActionType, FormProps, FormSchema } from '../types/form';
|
import {
|
||||||
|
isComponentFormSchema,
|
||||||
|
type FormActionType,
|
||||||
|
type FormProps,
|
||||||
|
type FormSchemaInner as FormSchema,
|
||||||
|
} from '../types/form';
|
||||||
import type { Rule as ValidationRule } from 'ant-design-vue/lib/form/interface';
|
import type { Rule as ValidationRule } from 'ant-design-vue/lib/form/interface';
|
||||||
import type { TableActionType } from '/@/components/Table';
|
import type { TableActionType } from '/@/components/Table';
|
||||||
import { Col, Divider, Form } from 'ant-design-vue';
|
import { Col, Divider, Form } from 'ant-design-vue';
|
||||||
|
|
@ -241,6 +246,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderComponent() {
|
function renderComponent() {
|
||||||
|
if (!isComponentFormSchema(props.schema)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
renderComponentContent,
|
renderComponentContent,
|
||||||
component,
|
component,
|
||||||
|
|
@ -352,7 +360,7 @@
|
||||||
const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
|
const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
|
||||||
|
|
||||||
// TODO 自定义组件验证会出现问题,因此这里框架默认将自定义组件设置手动触发验证,如果其他组件还有此问题请手动设置autoLink=false
|
// TODO 自定义组件验证会出现问题,因此这里框架默认将自定义组件设置手动触发验证,如果其他组件还有此问题请手动设置autoLink=false
|
||||||
if (NO_AUTO_LINK_COMPONENTS.includes(component)) {
|
if (component && NO_AUTO_LINK_COMPONENTS.includes(component)) {
|
||||||
props.schema &&
|
props.schema &&
|
||||||
(props.schema.itemProps! = {
|
(props.schema.itemProps! = {
|
||||||
autoLink: false,
|
autoLink: false,
|
||||||
|
|
@ -382,7 +390,7 @@
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { colProps = {}, colSlot, renderColContent, component, slot } = props.schema;
|
const { colProps = {}, colSlot, renderColContent, component, slot } = props.schema;
|
||||||
if (!componentMap.has(component) && !slot) {
|
if (!component || (!componentMap.has(component) && !slot)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { ColEx } from '../types';
|
import type { ColEx } from '../types';
|
||||||
import type { AdvanceState } from '../types/hooks';
|
import type { AdvanceState } from '../types/hooks';
|
||||||
import { ComputedRef, getCurrentInstance, Ref, shallowReactive, computed, unref, watch } from 'vue';
|
import { ComputedRef, getCurrentInstance, Ref, shallowReactive, computed, unref, watch } from 'vue';
|
||||||
import type { FormProps, FormSchema } from '../types/form';
|
import type { FormProps, FormSchemaInner as FormSchema } from '../types/form';
|
||||||
import { isBoolean, isFunction, isNumber, isObject } from '/@/utils/is';
|
import { isBoolean, isFunction, isNumber, isObject } from '/@/utils/is';
|
||||||
import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
|
import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
|
||||||
import { useDebounceFn } from '@vueuse/core';
|
import { useDebounceFn } from '@vueuse/core';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import type { ComputedRef, Ref } from 'vue';
|
import type { ComputedRef, Ref } from 'vue';
|
||||||
import type { FormSchema, FormActionType, FormProps } from '../types/form';
|
import {
|
||||||
|
type FormSchemaInner as FormSchema,
|
||||||
|
type FormActionType,
|
||||||
|
type FormProps,
|
||||||
|
} from '../types/form';
|
||||||
|
|
||||||
import { unref, nextTick, watchEffect } from 'vue';
|
import { unref, nextTick, watchEffect } from 'vue';
|
||||||
|
|
||||||
|
|
@ -29,7 +33,7 @@ export async function useAutoFocus({
|
||||||
|
|
||||||
const firstItem = schemas[0];
|
const firstItem = schemas[0];
|
||||||
// Only open when the first form item is input type
|
// Only open when the first form item is input type
|
||||||
if (!firstItem.component.includes('Input')) {
|
if (!firstItem.component || !firstItem.component.includes('Input')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form';
|
import type {
|
||||||
|
FormProps,
|
||||||
|
FormActionType,
|
||||||
|
UseFormReturnType,
|
||||||
|
FormSchemaInner as FormSchema,
|
||||||
|
} from '../types/form';
|
||||||
import type { NamePath } from 'ant-design-vue/lib/form/interface';
|
import type { NamePath } from 'ant-design-vue/lib/form/interface';
|
||||||
import type { DynamicProps } from '/#/utils';
|
import type { DynamicProps } from '/#/utils';
|
||||||
import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
|
import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { ComputedRef, Ref } from 'vue';
|
import type { ComputedRef, Ref } from 'vue';
|
||||||
import type { FormProps, FormSchema, FormActionType } from '../types/form';
|
import type { FormProps, FormSchemaInner as FormSchema, FormActionType } from '../types/form';
|
||||||
import type { NamePath } from 'ant-design-vue/lib/form/interface';
|
import type { NamePath } from 'ant-design-vue/lib/form/interface';
|
||||||
import { unref, toRaw, nextTick } from 'vue';
|
import { unref, toRaw, nextTick } from 'vue';
|
||||||
import {
|
import {
|
||||||
|
|
@ -335,7 +335,7 @@ export function useFormEvents({
|
||||||
*/
|
*/
|
||||||
function itemIsDateType(key: string) {
|
function itemIsDateType(key: string) {
|
||||||
return unref(getSchema).some((item) => {
|
return unref(getSchema).some((item) => {
|
||||||
return item.field === key ? dateItemType.includes(item.component) : false;
|
return item.field === key && item.component ? dateItemType.includes(item.component) : false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { isArray, isFunction, isNotEmpty, isObject, isString, isNullOrUnDef } fr
|
||||||
import { dateUtil } from '/@/utils/dateUtil';
|
import { dateUtil } from '/@/utils/dateUtil';
|
||||||
import { unref } from 'vue';
|
import { unref } from 'vue';
|
||||||
import type { Ref, ComputedRef } from 'vue';
|
import type { Ref, ComputedRef } from 'vue';
|
||||||
import type { FormProps, FormSchema } from '../types/form';
|
import type { FormProps, FormSchemaInner as FormSchema } from '../types/form';
|
||||||
import { cloneDeep, get, set, unset } from 'lodash-es';
|
import { cloneDeep, get, set, unset } from 'lodash-es';
|
||||||
|
|
||||||
interface UseFormValuesContext {
|
interface UseFormValuesContext {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
import { computed, unref } from 'vue';
|
import { computed, unref } from 'vue';
|
||||||
import type { FormProps, FormSchema } from '../types/form';
|
import type { FormProps, FormSchemaInner as FormSchema } from '../types/form';
|
||||||
import { isNumber } from '/@/utils/is';
|
import { isNumber } from '/@/utils/is';
|
||||||
|
|
||||||
export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<FormProps>) {
|
export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<FormProps>) {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export type Rule = RuleObject & {
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface RenderCallbackParams {
|
export interface RenderCallbackParams {
|
||||||
schema: FormSchema;
|
schema: FormSchemaInner;
|
||||||
values: Recordable;
|
values: Recordable;
|
||||||
model: Recordable;
|
model: Recordable;
|
||||||
field: string;
|
field: string;
|
||||||
|
|
@ -29,12 +29,12 @@ export interface FormActionType {
|
||||||
resetFields: () => Promise<void>;
|
resetFields: () => Promise<void>;
|
||||||
getFieldsValue: () => Recordable;
|
getFieldsValue: () => Recordable;
|
||||||
clearValidate: (name?: string | string[]) => Promise<void>;
|
clearValidate: (name?: string | string[]) => Promise<void>;
|
||||||
updateSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
|
updateSchema: (data: Partial<FormSchemaInner> | Partial<FormSchemaInner>[]) => Promise<void>;
|
||||||
resetSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
|
resetSchema: (data: Partial<FormSchemaInner> | Partial<FormSchemaInner>[]) => Promise<void>;
|
||||||
setProps: (formProps: Partial<FormProps>) => Promise<void>;
|
setProps: (formProps: Partial<FormProps>) => Promise<void>;
|
||||||
removeSchemaByField: (field: string | string[]) => Promise<void>;
|
removeSchemaByField: (field: string | string[]) => Promise<void>;
|
||||||
appendSchemaByField: (
|
appendSchemaByField: (
|
||||||
schema: FormSchema | FormSchema[],
|
schema: FormSchemaInner | FormSchemaInner[],
|
||||||
prefixField: string | undefined,
|
prefixField: string | undefined,
|
||||||
first?: boolean | undefined,
|
first?: boolean | undefined,
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
|
|
@ -127,7 +127,8 @@ export type RenderOpts = {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
export interface FormSchema {
|
|
||||||
|
interface BaseFormSchema {
|
||||||
// Field name
|
// Field name
|
||||||
field: string;
|
field: string;
|
||||||
// Extra Fields name[]
|
// Extra Fields name[]
|
||||||
|
|
@ -151,8 +152,6 @@ export interface FormSchema {
|
||||||
labelWidth?: string | number;
|
labelWidth?: string | number;
|
||||||
// Disable the adjustment of labelWidth with global settings of formModel, and manually set labelCol and wrapperCol by yourself
|
// Disable the adjustment of labelWidth with global settings of formModel, and manually set labelCol and wrapperCol by yourself
|
||||||
disabledLabelWidth?: boolean;
|
disabledLabelWidth?: boolean;
|
||||||
// render component
|
|
||||||
component: ComponentType;
|
|
||||||
// Component parameters
|
// Component parameters
|
||||||
componentProps?:
|
componentProps?:
|
||||||
| ((opt: {
|
| ((opt: {
|
||||||
|
|
@ -214,9 +213,6 @@ export interface FormSchema {
|
||||||
| VNode[]
|
| VNode[]
|
||||||
| string;
|
| string;
|
||||||
|
|
||||||
// Custom slot, in from-item
|
|
||||||
slot?: string;
|
|
||||||
|
|
||||||
// Custom slot, similar to renderColContent
|
// Custom slot, similar to renderColContent
|
||||||
colSlot?: string;
|
colSlot?: string;
|
||||||
|
|
||||||
|
|
@ -224,6 +220,29 @@ export interface FormSchema {
|
||||||
|
|
||||||
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
|
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
|
||||||
}
|
}
|
||||||
|
export interface ComponentFormSchema extends BaseFormSchema {
|
||||||
|
// render component
|
||||||
|
component: ComponentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SlotFormSchema extends BaseFormSchema {
|
||||||
|
// Custom slot, in from-item
|
||||||
|
slot: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FormSchema = ComponentFormSchema | SlotFormSchema;
|
||||||
|
|
||||||
|
export type FormSchemaInner = Partial<ComponentFormSchema> &
|
||||||
|
Partial<SlotFormSchema> &
|
||||||
|
BaseFormSchema;
|
||||||
|
|
||||||
|
export function isSlotFormSchema(schema: FormSchemaInner): schema is SlotFormSchema {
|
||||||
|
return 'slot' in schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isComponentFormSchema(schema: FormSchemaInner): schema is ComponentFormSchema {
|
||||||
|
return !isSlotFormSchema(schema);
|
||||||
|
}
|
||||||
export interface HelpComponentProps {
|
export interface HelpComponentProps {
|
||||||
maxWidth: string;
|
maxWidth: string;
|
||||||
// Whether to display the serial number
|
// Whether to display the serial number
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue