mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-03-21 04:59:50 +00:00
feat(form-schema,form,editor): 完善表单配置类型
This commit is contained in:
parent
1664559d8f
commit
55eb546ad6
@ -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: [
|
||||
|
||||
@ -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) => ({
|
||||
|
||||
@ -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';
|
||||
});
|
||||
|
||||
@ -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: '是否可用',
|
||||
|
||||
@ -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 [];
|
||||
|
||||
@ -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 = [
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>[];
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}));
|
||||
|
||||
|
||||
@ -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(() => {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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']);
|
||||
|
||||
|
||||
@ -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!]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user