feat(form-schema,form,editor): 完善表单配置类型

This commit is contained in:
roymondchen 2026-03-20 12:31:55 +08:00
parent 1664559d8f
commit 55eb546ad6
19 changed files with 234 additions and 185 deletions

View File

@ -63,13 +63,7 @@ import { computed, inject, nextTick, Ref, ref, useTemplateRef, watch } from 'vue
import type { CodeBlockContent } from '@tmagic/core';
import { TMagicButton, TMagicDialog, tMagicMessage, tMagicMessageBox, TMagicTag } from '@tmagic/design';
import {
type ContainerChangeEventData,
type FormConfig,
type FormState,
MFormBox,
type TableColumnConfig,
} from '@tmagic/form';
import { type ContainerChangeEventData, type FormConfig, type FormState, MFormBox } from '@tmagic/form';
import FloatingBox from '@editor/components/FloatingBox.vue';
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
@ -118,7 +112,7 @@ const diffChange = () => {
difVisible.value = false;
};
const defaultParamColConfig: TableColumnConfig = {
const defaultParamColConfig = {
type: 'row',
label: '参数类型',
items: [

View File

@ -115,7 +115,7 @@ watch(
const selectConfig: SelectConfig = {
type: 'select',
name: props.name,
disable: props.disabled,
disabled: props.disabled,
options: () => {
if (codeDsl.value) {
return map(codeDsl.value, (value, key) => ({

View File

@ -106,13 +106,18 @@ const type = computed((): string => {
}
if (type === 'form') return '';
if (type === 'container') return '';
return type?.replace(/([A-Z])/g, '-$1').toLowerCase() || (props.config.items ? '' : 'text');
return (
type?.replace(/([A-Z])/g, '-$1').toLowerCase() ||
(props.config.fieldConfig && 'items' in props.config.fieldConfig ? '' : 'text')
);
});
const tagName = computed(() => {
const component =
getFormField(type.value || 'container') ||
resolveComponent(`m-${props.config.items ? 'form' : 'fields'}-${type.value}`);
resolveComponent(
`m-${props.config.fieldConfig && 'items' in props.config.fieldConfig ? 'form' : 'fields'}-${type.value}`,
);
if (typeof component !== 'string') return component;
return 'm-fields-text';
});

View File

@ -52,12 +52,15 @@ import { inject, Ref, ref } from 'vue';
import type { DataSchema } from '@tmagic/core';
import { TMagicButton, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
import {
type CodeConfig,
type ContainerChangeEventData,
type DataSourceFieldsConfig,
type FieldProps,
type FormConfig,
type FormState,
MFormBox,
type NumberConfig,
type TextConfig,
} from '@tmagic/form';
import { type ColumnConfig, MagicTable } from '@tmagic/table';
import { getDefaultValueFromFields } from '@tmagic/utils';
@ -247,7 +250,7 @@ const dataSourceFieldsConfig: FormConfig = [
{ text: 'true', value: true },
{ text: 'false', value: false },
],
},
} as unknown as CodeConfig | NumberConfig | TextConfig,
{
name: 'enable',
text: '是否可用',

View File

@ -59,7 +59,6 @@ import { ActionType } from '@tmagic/core';
import { TMagicButton } from '@tmagic/design';
import type {
CascaderOption,
ChildConfig,
CodeSelectColConfig,
ContainerChangeEventData,
DataSourceMethodSelectConfig,
@ -90,10 +89,10 @@ const { editorService, dataSourceService, eventsService, codeBlockService, props
//
const eventNameConfig = computed(() => {
const defaultEventNameConfig: ChildConfig = {
const defaultEventNameConfig = {
name: 'name',
text: '事件',
type: (mForm, { formValue }: any) => {
type: (mForm: FormState | undefined, { formValue }: any) => {
if (
props.config.src !== 'component' ||
(formValue.type === 'page-fragment-container' && formValue.pageFragmentId)
@ -227,10 +226,10 @@ const targetCompConfig = computed(() => {
//
const compActionConfig = computed(() => {
const defaultCompActionConfig: ChildConfig = {
const defaultCompActionConfig = {
name: 'method',
text: '动作',
type: (mForm, { model }: any) => {
type: (mForm: FormState | undefined, { model }: any) => {
const to = editorService.getNodeById(model.to);
if (to && to.type === 'page-fragment-container' && to.pageFragmentId) {
@ -240,7 +239,7 @@ const compActionConfig = computed(() => {
return 'select';
},
checkStrictly: () => props.config.src !== 'component',
display: (mForm, { model }: any) => model.actionType === ActionType.COMP,
display: (mForm: FormState | undefined, { model }: any) => model.actionType === ActionType.COMP,
options: (mForm: FormState, { model }: any) => {
const node = editorService.getNodeById(model.to);
if (!node?.type) return [];

View File

@ -28,10 +28,10 @@
<script lang="ts" setup>
import { TMagicButton, TMagicInput } from '@tmagic/design';
import type { FieldProps, FormItem } from '@tmagic/form';
import type { FieldProps, StyleSetterConfig } from '@tmagic/form';
const emit = defineEmits(['change']);
defineProps<FieldProps<{ type: 'style-setter' } & FormItem>>();
defineProps<FieldProps<StyleSetterConfig>>();
const horizontalList = [
{

View File

@ -12,8 +12,8 @@
<script lang="ts" setup>
import { markRaw } from 'vue';
import type { ContainerChangeEventData, FormState } from '@tmagic/form';
import { MContainer } from '@tmagic/form';
import type { ContainerChangeEventData } from '@tmagic/form';
import { defineFormItem, MContainer } from '@tmagic/form';
import type { StyleSchema } from '@tmagic/schema';
import Box from '../components/Box.vue';
@ -42,7 +42,7 @@ const emit = defineEmits<{
change: [v: string | StyleSchema, eventData: ContainerChangeEventData];
}>();
const config = {
const config = defineFormItem({
items: [
{
name: 'display',
@ -74,7 +74,7 @@ const config = {
tooltip: '垂直方向 起点在下沿 column-reverse',
},
],
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
display: (_mForm, { model }: { model: Record<any, any> }) => model.display === 'flex',
},
{
name: 'justifyContent',
@ -89,7 +89,7 @@ const config = {
{ value: 'space-between', icon: markRaw(JustifyContentSpaceBetween), tooltip: '两端对齐 space-between' },
{ value: 'space-around', icon: markRaw(JustifyContentSpaceAround), tooltip: '横向平分 space-around' },
],
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
display: (_mForm, { model }: { model: Record<any, any> }) => model.display === 'flex',
},
{
name: 'alignItems',
@ -104,7 +104,7 @@ const config = {
{ value: 'space-between', icon: markRaw(JustifyContentSpaceBetween), tooltip: '两端对齐 space-between' },
{ value: 'space-around', icon: markRaw(JustifyContentSpaceAround), tooltip: '横向平分 space-around' },
],
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
display: (_mForm, { model }: { model: Record<any, any> }) => model.display === 'flex',
},
{
name: 'flexWrap',
@ -117,7 +117,7 @@ const config = {
{ value: 'wrap', text: '正换行', tooltip: '第一行在上方 wrap' },
{ value: 'wrap-reverse', text: '逆换行', tooltip: '第一行在下方 wrap-reverse' },
],
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
display: (_mForm, { model }: { model: Record<any, any> }) => model.display === 'flex',
},
{
type: 'row',
@ -180,7 +180,7 @@ const config = {
],
},
],
};
});
const change = (value: string | StyleSchema, eventData: ContainerChangeEventData) => {
emit('change', value, eventData);

View File

@ -102,9 +102,11 @@ class Props extends BaseService {
}
public async setPropsConfig(type: string, config: FormConfig | PropsFormConfigFunction) {
let c = config;
let c: FormConfig;
if (typeof config === 'function') {
c = config({ editorService });
} else {
c = config;
}
this.state.propsConfigMap[toLine(type)] = await this.fillConfig(Array.isArray(c) ? c : [c]);

View File

@ -5,79 +5,77 @@ import { dataSourceTemplateRegExp, getKeysArray, isNumber } from '@tmagic/utils'
import BaseFormConfig from './formConfigs/base';
import HttpFormConfig from './formConfigs/http';
const fillConfig = (config: FormConfig): FormConfig => [
...BaseFormConfig(),
...config,
{
type: 'tab',
items: [
{
title: '数据定义',
items: [
{
name: 'fields',
type: 'data-source-fields',
defaultValue: () => [],
},
],
},
{
title: '方法定义',
items: [
{
name: 'methods',
type: 'data-source-methods',
defaultValue: () => [],
},
],
},
{
title: '事件配置',
items: [
{
name: 'events',
src: 'datasource',
type: 'event-select',
},
],
},
{
title: 'mock数据',
items: [
{
name: 'mocks',
type: 'data-source-mocks',
defaultValue: () => [],
},
],
},
{
title: '请求参数裁剪',
display: (_formState: FormState, { model }: any) => model.type === 'http',
items: [
{
name: 'beforeRequest',
type: 'vs-code',
parse: true,
autosize: { minRows: 10, maxRows: 30 },
},
],
},
{
title: '响应数据裁剪',
display: (_formState: FormState, { model }: any) => model.type === 'http',
items: [
{
name: 'afterResponse',
type: 'vs-code',
parse: true,
autosize: { minRows: 10, maxRows: 30 },
},
],
},
],
},
];
const dataSourceFormConfig = {
type: 'tab',
items: [
{
title: '数据定义',
items: [
{
name: 'fields',
type: 'data-source-fields',
defaultValue: () => [],
},
],
},
{
title: '方法定义',
items: [
{
name: 'methods',
type: 'data-source-methods',
defaultValue: () => [],
},
],
},
{
title: '事件配置',
items: [
{
name: 'events',
src: 'datasource',
type: 'event-select',
},
],
},
{
title: 'mock数据',
items: [
{
name: 'mocks',
type: 'data-source-mocks',
defaultValue: () => [],
},
],
},
{
title: '请求参数裁剪',
display: (_formState: FormState, { model }: any) => model.type === 'http',
items: [
{
name: 'beforeRequest',
type: 'vs-code',
parse: true,
autosize: { minRows: 10, maxRows: 30 },
},
],
},
{
title: '响应数据裁剪',
display: (_formState: FormState, { model }: any) => model.type === 'http',
items: [
{
name: 'afterResponse',
type: 'vs-code',
parse: true,
autosize: { minRows: 10, maxRows: 30 },
},
],
},
],
};
const fillConfig = (config: FormConfig): FormConfig => [...BaseFormConfig(), ...config, dataSourceFormConfig];
export const getFormConfig = (type: string, configs: Record<string, FormConfig>): FormConfig => {
switch (type) {

View File

@ -24,7 +24,7 @@ import {
NODE_DISABLE_DATA_SOURCE_KEY,
} from '@tmagic/core';
import { tMagicMessage } from '@tmagic/design';
import type { FormConfig, FormState, TabConfig, TabPaneConfig } from '@tmagic/form';
import type { ChildConfig, FormConfig, TabConfig, TabPaneConfig } from '@tmagic/form';
export const arrayOptions = [
{ text: '包含', value: 'include' },
@ -107,7 +107,7 @@ export const styleTabConfig: TabPaneConfig = {
'borderStyle',
'borderColor',
],
},
} as unknown as ChildConfig,
],
},
],
@ -170,7 +170,7 @@ export const advancedTabConfig: TabPaneConfig = {
export const displayTabConfig: TabPaneConfig = {
title: '显示条件',
display: (_state: FormState, { model }: any) => model.type !== 'page',
display: (_state, { model }) => model.type !== 'page',
items: [
{
name: NODE_CONDS_RESULT_KEY,
@ -209,7 +209,7 @@ export const fillConfig = (
const propsConfig: FormConfig = [];
// 组件类型,必须要有
if (!config.find((item) => item.name === 'type')) {
if (!config.find((item) => 'name' in item && item.name === 'type')) {
propsConfig.push({
text: 'type',
name: 'type',
@ -217,7 +217,7 @@ export const fillConfig = (
});
}
if (!config.find((item) => item.name === 'id')) {
if (!config.find((item) => 'name' in item && item.name === 'id')) {
// 组件id必须要有
propsConfig.push({
name: 'id',
@ -241,14 +241,16 @@ export const fillConfig = (
});
}
if (!config.find((item) => item.name === 'name')) {
if (!config.find((item) => 'name' in item && item.name === 'name')) {
propsConfig.push({
name: 'name',
text: '组件名称',
});
}
const noCodeAdvancedTabItems = advancedTabConfig.items.filter((item) => item.type !== 'code-select');
const noCodeAdvancedTabItems = advancedTabConfig.items.filter(
(item) => 'type' in item && item.type !== 'code-select',
);
if (noCodeAdvancedTabItems.length > 0 && disabledCodeBlock) {
advancedTabConfig.items = noCodeAdvancedTabItems;

View File

@ -129,11 +129,11 @@ export interface FormItem {
expand?: boolean;
style?: Record<string, any>;
fieldStyle?: Record<string, any>;
[key: string]: any;
labelPosition?: 'top' | 'left' | 'right';
}
export interface ContainerCommonConfig {
items: FormConfig;
export interface ContainerCommonConfig<T extends Record<string, any> = never> {
items: FormConfig<T>;
onInitValue?: (
mForm: FormState | undefined,
data: {
@ -351,6 +351,8 @@ export interface DisplayConfig extends FormItem {
export interface TextConfig extends FormItem, Input {
type?: 'text';
tooltip?: string;
/** 是否可清空 */
clearable?: boolean;
prepend?: string;
/** 后置元素,一般为标签或按钮 */
append?:
@ -436,6 +438,17 @@ export interface TimeConfig extends FormItem, Input {
valueFormat?: 'HH:mm:ss' | string;
}
/**
*
*/
export interface TimerangeConfig extends FormItem {
type: 'timerange';
names?: string[];
defaultTime?: Date[];
format?: 'HH:mm:ss' | string;
valueFormat?: 'HH:mm:ss' | string;
}
/**
*
*/
@ -459,11 +472,11 @@ export interface SwitchConfig extends FormItem {
*
*/
export interface RadioGroupConfig extends FormItem {
type: 'radio-group';
type: 'radio-group' | 'radioGroup';
childType?: 'default' | 'button';
options: {
value: string | number | boolean;
text: string;
text?: string;
icon?: any;
tooltip?: string;
}[];
@ -533,7 +546,7 @@ export interface SelectConfig extends FormItem, Input {
/**
*
*/
export interface LinkConfig extends FormItem {
export interface LinkConfig<T extends Record<string, any> = never> extends FormItem {
type: 'link';
href?: string | ((model: Record<string, any>) => string);
css?: {
@ -553,7 +566,7 @@ export interface LinkConfig extends FormItem {
) => string)
| string;
form:
| FormConfig
| FormConfig<T>
| ((
mForm: FormState | undefined,
data: {
@ -561,7 +574,7 @@ export interface LinkConfig extends FormItem {
values?: Readonly<FormValue> | null;
formValue?: FormValue;
},
) => FormConfig);
) => FormConfig<T>);
fullscreen?: boolean;
}
@ -618,32 +631,38 @@ export interface DynamicFieldConfig extends FormItem {
/**
*
*/
export interface RowConfig extends FormItem {
export interface RowConfig<T extends Record<string, any> = never> extends FormItem {
type: 'row';
span: number;
items: ({ span?: number } & (ChildConfig | EditorChildConfig))[];
items: ({ span?: number } & (ChildConfig<T> | EditorChildConfig | NoInfer<T>))[];
}
/**
*
*/
export interface TabPaneConfig {
export interface TabPaneConfig<T extends Record<string, any> = never> {
status?: string;
/** 标签页名称,用于关联 model 中的数据 */
name?: string | number;
title: string;
lazy?: boolean;
labelWidth?: string;
items: FormConfig;
items: FormConfig<T>;
display?: boolean | 'expand' | FilterFunction<boolean | 'expand'>;
onTabClick?: (mForm: FormState | undefined, tab: any, data: any) => void;
[key: string]: any;
}
export interface TabConfig extends FormItem, ContainerCommonConfig {
export interface TabConfig<T extends Record<string, any> = never> extends FormItem, ContainerCommonConfig<T> {
type: 'tab' | 'dynamic-tab';
tabType?: string;
editable?: boolean;
dynamic?: boolean;
tabPosition?: 'top' | 'right' | 'bottom' | 'left';
items: TabPaneConfig[];
/** 当前激活的标签页,可以是固定值或动态函数 */
active?:
| string
| ((mForm: FormState | undefined, data: { model: FormValue; formValue?: FormValue; prop: string }) => string);
items: TabPaneConfig<T>[];
onChange?: (mForm: FormState | undefined, data: any) => void;
onTabAdd?: (mForm: FormState | undefined, data: any) => void;
onTabRemove?: (mForm: FormState | undefined, tabName: string, data: any) => void;
@ -654,7 +673,7 @@ export interface TabConfig extends FormItem, ContainerCommonConfig {
/**
*
*/
export interface FieldsetConfig extends FormItem, ContainerCommonConfig {
export interface FieldsetConfig<T extends Record<string, any> = never> extends FormItem, ContainerCommonConfig<T> {
type: 'fieldset';
checkbox?:
| boolean
@ -671,7 +690,7 @@ export interface FieldsetConfig extends FormItem, ContainerCommonConfig {
/**
*
*/
export interface PanelConfig extends FormItem, ContainerCommonConfig {
export interface PanelConfig<T extends Record<string, any> = never> extends FormItem, ContainerCommonConfig<T> {
type: 'panel';
expand?: boolean;
title?: string;
@ -683,7 +702,9 @@ export interface TableColumnConfig extends FormItem {
label: string;
width?: string | number;
sortable?: boolean;
[key: string]: any;
items?: FormConfig;
itemsFunction?: (row: any) => FormConfig;
titleTip?: FilterFunction<string>;
}
/**
@ -715,10 +736,11 @@ export interface TableConfig extends FormItem {
importable?: (mForm: FormState | undefined, data: any) => boolean | 'undefined' | boolean;
/** 是否显示checkbox */
selection?: (mForm: FormState | undefined, data: any) => boolean | boolean | 'single';
/** 新增的默认行 */
defaultAdd?: (mForm: FormState | undefined, data: any) => any;
/** 新增的默认行,可以是函数动态生成或静态对象 */
defaultAdd?: ((mForm: FormState | undefined, data: any) => any) | Record<string, any>;
copyHandler?: (mForm: FormState | undefined, data: any) => any;
onSelect?: (mForm: FormState | undefined, data: any) => any;
/** @deprecated 请使用 defaultSort */
defautSort?: SortProp;
defaultSort?: SortProp;
/** 是否支持拖拽排序 */
@ -739,15 +761,17 @@ export interface TableConfig extends FormItem {
props?: Record<string, any>;
text?: string;
};
sort?: boolean;
sortKey?: string;
}
export interface GroupListConfig extends FormItem {
export interface GroupListConfig<T extends Record<string, any> = never> extends FormItem {
type: 'table' | 'groupList' | 'group-list';
span?: number;
enableToggleMode?: boolean;
items: FormConfig;
groupItems?: FormConfig;
tableItems?: FormConfig;
items: FormConfig<T>;
groupItems?: FormConfig<T>;
tableItems?: FormConfig<T>;
titleKey?: string;
titlePrefix?: string;
title?: string | FilterFunction<string>;
@ -760,7 +784,8 @@ export interface GroupListConfig extends FormItem {
*/
defaultExpandQuantity?: number;
addable?: (mForm: FormState | undefined, data: any) => boolean | 'undefined' | boolean;
defaultAdd?: (mForm: FormState | undefined, data: any) => any;
/** 新增的默认值,可以是函数动态生成或静态对象 */
defaultAdd?: ((mForm: FormState | undefined, data: any) => any) | Record<string, any>;
delete?: (model: any, index: number | string | symbol, values: any) => boolean | boolean;
copyable?: FilterFunction<boolean>;
movable?: (
@ -774,18 +799,17 @@ export interface GroupListConfig extends FormItem {
props?: Record<string, any>;
text?: string;
};
[key: string]: any;
}
interface StepItemConfig extends FormItem, ContainerCommonConfig {
interface StepItemConfig<T extends Record<string, any> = never> extends FormItem, ContainerCommonConfig<T> {
title: string;
}
export interface StepConfig extends FormItem {
export interface StepConfig<T extends Record<string, any> = never> extends FormItem {
type: 'step';
/** 每个 step 的间距,不填写将自适应间距。支持百分比。 */
space?: string | number;
items: StepItemConfig[];
items: StepItemConfig<T>[];
}
export interface ComponentConfig extends FormItem {
@ -793,26 +817,32 @@ export interface ComponentConfig extends FormItem {
id: string;
extend: any;
display: any;
component: any;
}
export interface FlexLayoutConfig extends FormItem, ContainerCommonConfig {
export interface FlexLayoutConfig<T extends Record<string, any> = never> extends FormItem, ContainerCommonConfig<T> {
type: 'flex-layout';
/** flex 子项间距,默认 '16px' */
gap?: string;
}
export type ChildConfig =
| FormItem
| TabConfig
| RowConfig
| FieldsetConfig
| PanelConfig
export type ChildConfig<T extends Record<string, any> = never> =
| (FormItem & Partial<ContainerCommonConfig<T>>)
| TabConfig<T>
| RowConfig<T>
| FieldsetConfig<T>
| PanelConfig<T>
| TableConfig
| GroupListConfig
| StepConfig
| GroupListConfig<T>
| StepConfig<T>
| DisplayConfig
| TextConfig
| NumberConfig
| NumberRangeConfig
| HiddenConfig
| LinkConfig
| LinkConfig<T>
| DaterangeConfig
| TimerangeConfig
| SelectConfig
| CascaderConfig
| HtmlField
@ -823,8 +853,12 @@ export type ChildConfig =
| CheckboxConfig
| SwitchConfig
| RadioGroupConfig
| CheckboxGroupConfig
| TextareaConfig
| DynamicFieldConfig
| ComponentConfig;
| ComponentConfig
| FlexLayoutConfig<T>;
export type FormConfig = (ChildConfig | EditorChildConfig)[];
export type FormItemConfig<T extends Record<string, any> = never> = ChildConfig<T> | EditorChildConfig<T> | NoInfer<T>;
export type FormConfig<T extends Record<string, any> = never> = FormItemConfig<T>[];

View File

@ -1,8 +1,8 @@
import type { DataSourceFieldType, DataSourceSchema } from '@tmagic/schema';
import type { ChildConfig, FilterFunction, FormItem, FormState, Input } from './base';
import type { FilterFunction, FormItem, FormItemConfig, FormState, Input } from './base';
export interface DataSourceFieldSelectConfig extends FormItem {
export interface DataSourceFieldSelectConfig<T extends Record<string, any> = never> extends FormItem {
type: 'data-source-field-select';
/**
* data
@ -26,13 +26,13 @@ export interface DataSourceFieldSelectConfig extends FormItem {
},
) => boolean);
dataSourceFieldType?: DataSourceFieldType[];
fieldConfig?: ChildConfig;
fieldConfig?: FormItemConfig<T>;
/** 是否可以编辑数据源disable表示的是是否可以选择数据源 */
notEditable?: boolean | FilterFunction;
}
export interface CodeConfig extends FormItem {
type: 'code';
type: 'vs-code';
language?: string;
options?: {
[key: string]: any;
@ -140,8 +140,12 @@ export interface UISelectConfig extends FormItem {
type: 'ui-select';
}
export type EditorChildConfig =
| DataSourceFieldSelectConfig
export interface StyleSetterConfig extends FormItem {
type: 'style-setter';
}
export type EditorChildConfig<T extends Record<string, any> = never> =
| DataSourceFieldSelectConfig<T>
| CodeConfig
| CodeLinkConfig
| CodeSelectConfig
@ -157,4 +161,5 @@ export type EditorChildConfig =
| EventSelectConfig
| KeyValueConfig
| PageFragmentSelectConfig
| UISelectConfig;
| UISelectConfig
| StyleSetterConfig;

View File

@ -1,6 +1,9 @@
import type { FormConfig } from './base';
import type { FormConfig, FormItemConfig } from './base';
export * from './base';
export * from './editor';
export const defineFormConfig = <T = FormConfig>(config: T): T => config;
export const defineFormConfig = <T extends Record<string, any> = never>(config: FormConfig<T>): FormConfig<T> => config;
export const defineFormItem = <T extends Record<string, any> = never>(config: FormItemConfig<T>): FormItemConfig<T> =>
config;

View File

@ -218,13 +218,13 @@ const getTextByName = (name: string, config: FormConfig = props.config): string
return typeof item.text === 'string' ? item.text : undefined;
}
if (item.items && Array.isArray(item.items)) {
if ('items' in item && Array.isArray(item.items)) {
const result = findInConfig(item.items, remainingParts);
if (result !== undefined) return result;
}
}
if (item.items && Array.isArray(item.items)) {
if ('items' in item && Array.isArray(item.items)) {
const result = findInConfig(item.items, parts);
if (result !== undefined) return result;
}

View File

@ -1,6 +1,6 @@
<template>
<div
:data-tmagic-id="config.id"
:data-tmagic-id="(config as Record<string, any>).id"
:data-tmagic-form-item-prop="itemProp"
:class="`m-form-container m-container-${type || ''} ${config.className || ''}${config.tip ? ' has-tip' : ''}`"
:style="config.style"
@ -28,7 +28,7 @@
<FormLabel
:tip="config.tip"
:type="type"
:use-label="config.useLabel"
:use-label="(config as CheckboxConfig).useLabel"
:label-title="config.labelTitle"
:text="text"
></FormLabel>
@ -61,7 +61,7 @@
></component>
</TMagicFormItem>
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !config.useLabel" placement="top">
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel" placement="top">
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
<template #content>
<div v-html="config.tip"></div>
@ -80,7 +80,7 @@
<FormLabel
:tip="config.tip"
:type="type"
:use-label="config.useLabel"
:use-label="(config as CheckboxConfig).useLabel"
:label-title="config.labelTitle"
:text="text"
></FormLabel>
@ -95,7 +95,7 @@
<component v-else v-bind="fieldsProps" :is="tagName" :model="lastValues" @change="onChangeHandler"></component>
</TMagicFormItem>
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !config.useLabel" placement="top">
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel" placement="top">
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
<template #content>
<div v-html="config.tip"></div>
@ -112,7 +112,7 @@
<FormLabel
:tip="config.tip"
:type="type"
:use-label="config.useLabel"
:use-label="(config as CheckboxConfig).useLabel"
:label-title="config.labelTitle"
:text="text"
></FormLabel>
@ -127,7 +127,7 @@
<component v-else v-bind="fieldsProps" :is="tagName" :model="model" @change="onChangeHandler"></component>
</TMagicFormItem>
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !config.useLabel" placement="top">
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel" placement="top">
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
<template #content>
<div v-html="config.tip"></div>
@ -174,7 +174,9 @@ import { getValueByKeyPath } from '@tmagic/utils';
import MHidden from '../fields/Hidden.vue';
import type {
CheckboxConfig,
ChildConfig,
ComponentConfig,
ContainerChangeEventData,
ContainerCommonConfig,
FormState,
@ -259,13 +261,10 @@ const type = computed((): string => {
});
const tagName = computed(() => {
if (type.value === 'component' && props.config.component) {
return props.config.component;
if (type.value === 'component' && (props.config as ComponentConfig).component) {
return (props.config as ComponentConfig).component;
}
if (!getField(type.value || 'container')) {
console.log(type.value, 'type.value');
}
return getField(type.value || 'container') || `m-${items.value ? 'form' : 'fields'}-${type.value}`;
});
@ -305,7 +304,7 @@ const fieldsProps = computed(() => ({
name: name.value,
disabled: disabled.value,
prop: itemProp.value,
key: props.config[mForm?.keyProps],
key: (props.config as Record<string, any>)[mForm?.keyProps],
style: props.config.fieldStyle,
}));

View File

@ -144,7 +144,9 @@ const rowConfig = computed(() => ({
span: props.config.span || 24,
items: props.config.items,
labelWidth: props.config.labelWidth,
[mForm?.keyProp || '__key']: `${props.config[mForm?.keyProp || '__key']}${String(props.index)}`,
[mForm?.keyProp || '__key']: `${(props.config as Record<string, any>)[mForm?.keyProp || '__key']}${String(
props.index,
)}`,
}));
const title = computed(() => {

View File

@ -10,7 +10,7 @@
<TMagicTooltip :disabled="!Boolean(option.tooltip)" placement="top-start" :content="option.tooltip">
<div>
<TMagicIcon v-if="option.icon" :size="iconSize"><component :is="option.icon"></component></TMagicIcon>
<span>{{ option.text }}</span>
<span v-if="option.text">{{ option.text }}</span>
</div>
</TMagicTooltip>
</component>

View File

@ -21,7 +21,7 @@ import dayjs from 'dayjs';
import { TMagicTimePicker } from '@tmagic/design';
import type { ChangeRecord, DaterangeConfig, FieldProps } from '../schema';
import type { ChangeRecord, FieldProps, TimerangeConfig } from '../schema';
import { datetimeFormatter } from '../utils/form';
import { useAddField } from '../utils/useAddField';
@ -29,7 +29,7 @@ defineOptions({
name: 'MFormTimeRange',
});
const props = defineProps<FieldProps<DaterangeConfig>>();
const props = defineProps<FieldProps<TimerangeConfig>>();
const emit = defineEmits(['change']);

View File

@ -29,11 +29,13 @@ import {
DaterangeConfig,
FilterFunction,
FormConfig,
FormItem,
FormState,
FormValue,
HtmlField,
Rule,
SortProp,
TableConfig,
TabPaneConfig,
TypeFunction,
} from '../schema';
@ -118,7 +120,7 @@ const initValueItem = function (
) {
const { items } = item as ContainerCommonConfig;
const { names } = item as DaterangeConfig;
const { type, name } = item as ChildConfig;
const { type, name } = item as FormItem;
if (isTableSelect(type) && name) {
value[name] = initValue[name] ?? '';
@ -148,14 +150,15 @@ const initValueItem = function (
setValue(mForm, value, initValue, item);
if (type === 'table') {
if (item.defautSort) {
sortChange(value[name], item.defautSort);
} else if (item.defaultSort) {
sortChange(value[name], item.defaultSort);
const tableConfig = item as TableConfig;
if (tableConfig.defautSort) {
sortChange(value[name], tableConfig.defautSort);
} else if (tableConfig.defaultSort) {
sortChange(value[name], tableConfig.defaultSort);
}
if (item.sort && item.sortKey) {
value[name].sort((a: any, b: any) => b[item.sortKey] - a[item.sortKey]);
if (tableConfig.sort && tableConfig.sortKey) {
value[name].sort((a: any, b: any) => b[tableConfig.sortKey!] - a[tableConfig.sortKey!]);
}
}