feat(form): 新增style,fieldStyle配置;tooltip支持配置placement;配置中的函数新增getFormValue方法

This commit is contained in:
roymondchen 2025-10-23 19:54:14 +08:00
parent cea6569020
commit 1eeabc8220
5 changed files with 62 additions and 18 deletions

View File

@ -84,6 +84,8 @@ export interface SortProp {
order: 'ascending' | 'descending';
}
export type ToolTipConfigType = string | { text?: string; placement?: string };
export interface FormItem {
/** vnode的key值默认是遍历数组时的index */
__key?: string | number;
@ -99,7 +101,7 @@ export interface FormItem {
/** 额外的提示信息,和 help 类似,当提示文案同时出现时,可以使用这个。 */
extra?: string | FilterFunction<string>;
/** 配置提示信息 */
tooltip?: string | FilterFunction<string>;
tooltip?: ToolTipConfigType | FilterFunction<ToolTipConfigType>;
/** 是否置灰 */
disabled?: boolean | FilterFunction;
/** 使用表单中的值作为key例如配置了text则使用model.text作为key */
@ -124,6 +126,8 @@ export interface FormItem {
dynamicKey?: string;
/** 是否需要显示`展开更多配置` */
expand?: boolean;
style?: Record<string, any>;
fieldStyle?: Record<string, any>;
[key: string]: any;
}
@ -194,6 +198,7 @@ export type FilterFunction<T = boolean> = (
prop: string;
config: any;
index?: number;
getFormValue: (prop: string) => any;
},
) => T;
@ -344,6 +349,7 @@ export interface DisplayConfig extends FormItem {
export interface TextConfig extends FormItem, Input {
type?: 'text';
tooltip?: string;
prepend?: string;
/** 后置元素,一般为标签或按钮 */
append?:
| string
@ -431,6 +437,7 @@ export interface CheckboxConfig extends FormItem {
type: 'checkbox';
activeValue?: number | string;
inactiveValue?: number | string;
useLabel?: boolean;
}
/**
@ -642,7 +649,13 @@ export interface TabConfig extends FormItem, ContainerCommonConfig {
*/
export interface FieldsetConfig extends FormItem, ContainerCommonConfig {
type: 'fieldset';
checkbox?: boolean;
checkbox?:
| boolean
| {
name: string;
trueValue?: string | number;
falseValue?: string | number;
};
expand?: boolean;
legend?: string;
schematic?: string;

View File

@ -28,7 +28,7 @@
</template>
<script setup lang="ts">
import { provide, reactive, ref, shallowRef, toRaw, watch, watchEffect } from 'vue';
import { provide, reactive, ref, shallowRef, toRaw, useTemplateRef, watch, watchEffect } from 'vue';
import { cloneDeep, isEqual } from 'lodash-es';
import { TMagicForm, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
@ -84,7 +84,7 @@ const props = withDefaults(
const emit = defineEmits(['change', 'error', 'field-input', 'field-change', 'update:stepActive']);
const tMagicForm = ref<InstanceType<typeof TMagicForm>>();
const tMagicFormRef = useTemplateRef('tMagicForm');
const initialized = ref(false);
const values = ref<FormValue>({});
const lastValuesProcessed = ref<FormValue>({});
@ -206,13 +206,13 @@ defineExpose({
changeHandler,
resetForm: () => {
tMagicForm.value?.resetFields();
tMagicFormRef.value?.resetFields();
changeRecords.value = [];
},
submitForm: async (native?: boolean): Promise<any> => {
try {
await tMagicForm.value?.validate();
await tMagicFormRef.value?.validate();
changeRecords.value = [];
return native ? values.value : cloneDeep(toRaw(values.value));
} catch (invalidFields: any) {

View File

@ -3,6 +3,7 @@
:data-tmagic-id="config.id"
:data-tmagic-form-item-prop="itemProp"
:class="`m-form-container m-container-${type || ''} ${config.className || ''}${config.tip ? ' has-tip' : ''}`"
:style="config.style"
>
<m-fields-hidden v-if="type === 'hidden'" v-bind="fieldsProps" :model="model"></m-fields-hidden>
@ -16,14 +17,17 @@
:step-active="stepActive"
:expand-more="expand"
:label-width="itemLabelWidth"
:style="config.fieldStyle"
@change="onChangeHandler"
@addDiffCount="onAddDiffCount"
></component>
<template v-else-if="type && display && !showDiff">
<TMagicFormItem v-bind="formItemProps" :class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }">
<template #label><span v-html="type === 'checkbox' ? '' : text" :title="config.labelTitle"></span></template>
<TMagicTooltip v-if="tooltip">
<template #label
><span v-html="type === 'checkbox' && !config.useLabel ? '' : text" :title="config.labelTitle"></span
></template>
<TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
<component
v-bind="fieldsProps"
:is="tagName"
@ -32,8 +36,8 @@
@change="onChangeHandler"
@addDiffCount="onAddDiffCount"
></component>
<template #content v-if="tooltip">
<div v-html="tooltip"></div>
<template #content>
<div v-html="tooltip.text"></div>
</template>
</TMagicTooltip>
@ -64,10 +68,10 @@
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text, 'show-diff': true }"
>
<template #label><span v-html="type === 'checkbox' ? '' : text" :title="config.labelTitle"></span></template>
<TMagicTooltip v-if="tooltip">
<TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
<component v-bind="fieldsProps" :is="tagName" :model="lastValues" @change="onChangeHandler"></component>
<template #content v-if="tooltip">
<div v-html="tooltip"></div>
<template #content>
<div v-html="tooltip.text"></div>
</template>
</TMagicTooltip>
@ -88,10 +92,10 @@
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text, 'show-diff': true }"
>
<template #label><span v-html="type === 'checkbox' ? '' : text" :title="config.labelTitle"></span></template>
<TMagicTooltip v-if="tooltip">
<TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
<component v-bind="fieldsProps" :is="tagName" :model="model" @change="onChangeHandler"></component>
<template #content>
<div v-html="tooltip"></div>
<div v-html="tooltip.text"></div>
</template>
</TMagicTooltip>
@ -141,8 +145,16 @@ import { WarningFilled } from '@element-plus/icons-vue';
import { isEqual } from 'lodash-es';
import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
import { getValueByKeyPath } from '@tmagic/utils';
import type { ChildConfig, ContainerChangeEventData, ContainerCommonConfig, FormState, FormValue } from '../schema';
import type {
ChildConfig,
ContainerChangeEventData,
ContainerCommonConfig,
FormState,
FormValue,
ToolTipConfigType,
} from '../schema';
import { display as displayFunction, filterFunction, getRules } from '../utils/form';
defineOptions({
@ -223,7 +235,20 @@ const disabled = computed(() => props.disabled || filterFunction(mForm, props.co
const text = computed(() => filterFunction(mForm, props.config.text, props));
const tooltip = computed(() => filterFunction(mForm, props.config.tooltip, props));
const tooltip = computed(() => {
const config = filterFunction<ToolTipConfigType>(mForm, props.config.tooltip, props);
if (typeof config === 'string') {
return {
text: config,
placement: 'top',
};
}
return {
text: config?.text,
placement: config?.placement || 'top',
};
});
const rule = computed(() => getRules(mForm, props.config.rules, props));
@ -251,6 +276,7 @@ const fieldsProps = computed(() => ({
disabled: disabled.value,
prop: itemProp.value,
key: props.config[mForm?.keyProps],
style: props.config.fieldStyle,
}));
const formItemProps = computed(() => ({
@ -294,6 +320,7 @@ const filterHandler = (filter: any, value: FormValue | number | string) => {
formValue: mForm?.values,
prop: itemProp.value,
config: props.config,
getFormValue: (prop: string) => getValueByKeyPath(prop, mForm?.values || props.model),
});
}
@ -386,6 +413,7 @@ const onChangeHandler = async function (v: any, eventData: ContainerChangeEventD
changeRecords: newChangeRecords,
setModel,
setFormValue,
getFormValue: (prop: string) => getValueByKeyPath(prop, mForm?.values || props.model),
})) ?? value;
}
value = trimHandler(trim, value) ?? value;

View File

@ -6,7 +6,7 @@
:falseValue="inactiveValue"
:disabled="disabled"
@update:model-value="changeHandler"
>{{ config.text }}</TMagicCheckbox
><template #default v-if="!config.useLabel">{{ config.text }}</template></TMagicCheckbox
>
</template>

View File

@ -21,6 +21,8 @@ import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { cloneDeep } from 'lodash-es';
import { getValueByKeyPath } from '@tmagic/utils';
import {
ChildConfig,
ContainerCommonConfig,
@ -215,6 +217,7 @@ export const filterFunction = <T = any>(
prop: props.prop,
config: props.config,
index: props.index,
getFormValue: (prop: string) => getValueByKeyPath(prop, mForm?.values || props.model),
});
}