feat(editor,form): 支持按需设置表单组件

This commit is contained in:
roymondchen 2026-03-18 20:19:05 +08:00
parent 88e6c7d377
commit c79034befc
15 changed files with 279 additions and 186 deletions

View File

@ -189,6 +189,8 @@
import hljs from 'highlight.js';
import serialize from 'serialize-javascript';
import { MForm } from '@tmagic/form';
export function stripScript(content) {
const result = content.match(/<(script)>([\s\S]+)<\/\1>/);
return result && result[2] ? result[2].trim() : '';
@ -210,6 +212,10 @@ export function stripTemplate(content) {
export default {
props: ['type', 'config'],
components: {
MForm,
},
data() {
return {
codepen: {

View File

@ -1,12 +1,12 @@
<template>
<m-fields-link :config="formConfig" :model="modelValue" name="form" @change="changeHandler"></m-fields-link>
<MLink :config="formConfig" :model="modelValue" name="form" @change="changeHandler"></MLink>
</template>
<script lang="ts" setup>
import { computed, reactive, watch } from 'vue';
import serialize from 'serialize-javascript';
import type { CodeLinkConfig, FieldProps } from '@tmagic/form';
import type { CodeLinkConfig, FieldProps, MLink } from '@tmagic/form';
import { getEditorConfig } from '@editor/utils/config';

View File

@ -47,7 +47,13 @@ import { Coin } from '@element-plus/icons-vue';
import { DataSchema } from '@tmagic/core';
import { TMagicButton, tMagicMessage, TMagicTooltip } from '@tmagic/design';
import type { ContainerChangeEventData, DataSourceFieldSelectConfig, FieldProps, FormState } from '@tmagic/form';
import {
type ContainerChangeEventData,
type DataSourceFieldSelectConfig,
type FieldProps,
type FormState,
getFormField,
} from '@tmagic/form';
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, removeDataSourceFieldPrefix } from '@tmagic/utils';
import MIcon from '@editor/components/Icon.vue';
@ -104,7 +110,9 @@ const type = computed((): string => {
});
const tagName = computed(() => {
const component = resolveComponent(`m-${props.config.items ? 'form' : 'fields'}-${type.value}`);
const component =
getFormField(type.value || 'container') ||
resolveComponent(`m-${props.config.items ? 'form' : 'fields'}-${type.value}`);
if (typeof component !== 'string') return component;
return 'm-fields-text';
});

View File

@ -1,6 +1,6 @@
<template>
<div class="m-fields-event-select">
<m-form-table
<MTable
v-if="isOldVersion"
name="events"
:size="size"
@ -8,7 +8,7 @@
:model="model"
:config="tableConfig"
@change="onChangeHandler"
></m-form-table>
></MTable>
<div v-else class="fullWidth">
<TMagicButton class="create-button" type="primary" :size="size" :disabled="disabled" @click="addEvent()"
@ -68,8 +68,9 @@ import type {
FormState,
OnChangeHandlerData,
PanelConfig,
TableConfig,
} from '@tmagic/form';
import { MContainer as MFormContainer, MPanel } from '@tmagic/form';
import { MContainer as MFormContainer, MPanel, MTable } from '@tmagic/form';
import { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, traverseNode } from '@tmagic/utils';
import { useServices } from '@editor/hooks/use-services';
@ -304,7 +305,7 @@ const dataSourceActionConfig = computed(() => {
});
//
const tableConfig = computed(() => ({
const tableConfig = computed<TableConfig>(() => ({
type: 'table',
name: 'events',
items: [

View File

@ -15,38 +15,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { App } from 'vue';
import type { DesignPluginOptions } from '@tmagic/design';
import designPlugin from '@tmagic/design';
import type { FormInstallOptions } from '@tmagic/form';
import formPlugin from '@tmagic/form';
import tablePlugin from '@tmagic/table';
import Code from './fields/Code.vue';
import CodeLink from './fields/CodeLink.vue';
import CodeSelect from './fields/CodeSelect.vue';
import CodeSelectCol from './fields/CodeSelectCol.vue';
import CondOpSelect from './fields/CondOpSelect.vue';
import DataSourceFields from './fields/DataSourceFields.vue';
import DataSourceFieldSelect from './fields/DataSourceFieldSelect/Index.vue';
import DataSourceInput from './fields/DataSourceInput.vue';
import DataSourceMethods from './fields/DataSourceMethods.vue';
import DataSourceMethodSelect from './fields/DataSourceMethodSelect.vue';
import DataSourceMocks from './fields/DataSourceMocks.vue';
import DataSourceSelect from './fields/DataSourceSelect.vue';
import DisplayConds from './fields/DisplayConds.vue';
import EventSelect from './fields/EventSelect.vue';
import KeyValue from './fields/KeyValue.vue';
import PageFragmentSelect from './fields/PageFragmentSelect.vue';
import StyleSetter from './fields/StyleSetter/Index.vue';
import uiSelect from './fields/UISelect.vue';
import CodeEditor from './layouts/CodeEditor.vue';
import { setEditorConfig } from './utils/config';
import Editor from './Editor.vue';
import type { EditorInstallOptions } from './type';
import './theme/index.scss';
export * from '@tmagic/form';
export { default as formPlugin } from '@tmagic/form';
@ -110,44 +78,4 @@ export { default as DisplayConds } from './fields/DisplayConds.vue';
export { default as CondOpSelect } from './fields/CondOpSelect.vue';
export { default as StyleSetter } from './fields/StyleSetter/Index.vue';
const defaultInstallOpt: EditorInstallOptions = {
// eslint-disable-next-line no-eval
parseDSL: (dsl: string) => eval(dsl),
customCreateMonacoEditor: (monaco, codeEditorEl, options) => monaco.editor.create(codeEditorEl, options),
customCreateMonacoDiffEditor: (monaco, codeEditorEl, options) =>
monaco.editor.createDiffEditor(codeEditorEl, options),
};
export default {
install: (app: App, opt?: Partial<EditorInstallOptions | DesignPluginOptions | FormInstallOptions>): void => {
const option = Object.assign(defaultInstallOpt, opt || {});
app.use(designPlugin, opt || {});
app.use(formPlugin, opt || {});
app.use(tablePlugin);
app.config.globalProperties.$TMAGIC_EDITOR = option;
setEditorConfig(option);
app.component(`${Editor.name || 'MEditor'}`, Editor);
app.component('magic-code-editor', CodeEditor);
app.component('m-fields-ui-select', uiSelect);
app.component('m-fields-code-link', CodeLink);
app.component('m-fields-vs-code', Code);
app.component('m-fields-code-select', CodeSelect);
app.component('m-fields-code-select-col', CodeSelectCol);
app.component('m-fields-event-select', EventSelect);
app.component('m-fields-data-source-fields', DataSourceFields);
app.component('m-fields-data-source-mocks', DataSourceMocks);
app.component('m-fields-key-value', KeyValue);
app.component('m-fields-data-source-input', DataSourceInput);
app.component('m-fields-data-source-select', DataSourceSelect);
app.component('m-fields-data-source-methods', DataSourceMethods);
app.component('m-fields-data-source-method-select', DataSourceMethodSelect);
app.component('m-fields-data-source-field-select', DataSourceFieldSelect);
app.component('m-fields-page-fragment-select', PageFragmentSelect);
app.component('m-fields-display-conds', DisplayConds);
app.component('m-fields-cond-op-select', CondOpSelect);
app.component('m-form-style-setter', StyleSetter);
},
};
export { default } from './plugin';

View File

@ -0,0 +1,92 @@
/*
* Tencent is pleased to support the open source community by making TMagicEditor available.
*
* Copyright (C) 2025 Tencent. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { App } from 'vue';
import type { DesignPluginOptions } from '@tmagic/design';
import designPlugin from '@tmagic/design';
import type { FormInstallOptions } from '@tmagic/form';
import formPlugin from '@tmagic/form';
import tablePlugin from '@tmagic/table';
import Code from './fields/Code.vue';
import CodeLink from './fields/CodeLink.vue';
import CodeSelect from './fields/CodeSelect.vue';
import CodeSelectCol from './fields/CodeSelectCol.vue';
import CondOpSelect from './fields/CondOpSelect.vue';
import DataSourceFields from './fields/DataSourceFields.vue';
import DataSourceFieldSelect from './fields/DataSourceFieldSelect/Index.vue';
import DataSourceInput from './fields/DataSourceInput.vue';
import DataSourceMethods from './fields/DataSourceMethods.vue';
import DataSourceMethodSelect from './fields/DataSourceMethodSelect.vue';
import DataSourceMocks from './fields/DataSourceMocks.vue';
import DataSourceSelect from './fields/DataSourceSelect.vue';
import DisplayConds from './fields/DisplayConds.vue';
import EventSelect from './fields/EventSelect.vue';
import KeyValue from './fields/KeyValue.vue';
import PageFragmentSelect from './fields/PageFragmentSelect.vue';
import StyleSetter from './fields/StyleSetter/Index.vue';
import uiSelect from './fields/UISelect.vue';
import CodeEditor from './layouts/CodeEditor.vue';
import { setEditorConfig } from './utils/config';
import Editor from './Editor.vue';
import type { EditorInstallOptions } from './type';
import './theme/index.scss';
const defaultInstallOpt: EditorInstallOptions = {
// eslint-disable-next-line no-eval
parseDSL: (dsl: string) => eval(dsl),
customCreateMonacoEditor: (monaco, codeEditorEl, options) => monaco.editor.create(codeEditorEl, options),
customCreateMonacoDiffEditor: (monaco, codeEditorEl, options) =>
monaco.editor.createDiffEditor(codeEditorEl, options),
};
export default {
install: (app: App, opt?: Partial<EditorInstallOptions | DesignPluginOptions | FormInstallOptions>): void => {
const option = Object.assign(defaultInstallOpt, opt || {});
app.use(designPlugin, opt || {});
app.use(formPlugin, opt || {});
app.use(tablePlugin);
app.config.globalProperties.$TMAGIC_EDITOR = option;
setEditorConfig(option);
app.component(`${Editor.name || 'MEditor'}`, Editor);
app.component('magic-code-editor', CodeEditor);
app.component('m-fields-ui-select', uiSelect);
app.component('m-fields-code-link', CodeLink);
app.component('m-fields-vs-code', Code);
app.component('m-fields-code-select', CodeSelect);
app.component('m-fields-code-select-col', CodeSelectCol);
app.component('m-fields-event-select', EventSelect);
app.component('m-fields-data-source-fields', DataSourceFields);
app.component('m-fields-data-source-mocks', DataSourceMocks);
app.component('m-fields-key-value', KeyValue);
app.component('m-fields-data-source-input', DataSourceInput);
app.component('m-fields-data-source-select', DataSourceSelect);
app.component('m-fields-data-source-methods', DataSourceMethods);
app.component('m-fields-data-source-method-select', DataSourceMethodSelect);
app.component('m-fields-data-source-field-select', DataSourceFieldSelect);
app.component('m-fields-page-fragment-select', PageFragmentSelect);
app.component('m-fields-display-conds', DisplayConds);
app.component('m-fields-cond-op-select', CondOpSelect);
app.component('m-form-style-setter', StyleSetter);
},
};

View File

@ -19,7 +19,7 @@
import type { Component } from 'vue';
import type EventEmitter from 'events';
import type * as Monaco from 'monaco-editor';
import Sortable, { type Options, type SortableEvent } from 'sortablejs';
import type { default as Sortable, Options, SortableEvent } from 'sortablejs';
import type { PascalCasedProperties } from 'type-fest';
import type { CodeBlockContent, CodeBlockDSL, Id, MApp, MContainer, MNode, MPage, MPageFragment } from '@tmagic/core';

View File

@ -27,3 +27,4 @@ export * from './scroll-viewer';
export * from './tree';
export * from './undo-redo';
export * from './const';
export { default as loadMonaco } from './monaco-editor';

View File

@ -5,7 +5,7 @@
: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>
<MHidden v-if="type === 'hidden'" :name="`${name}`" :prop="itemProp" :model="model"></MHidden>
<component
v-else-if="items && !text && type && display"
@ -172,6 +172,7 @@ import { isEqual } from 'lodash-es';
import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
import { getValueByKeyPath } from '@tmagic/utils';
import MHidden from '../fields/Hidden.vue';
import type {
ChildConfig,
ContainerChangeEventData,
@ -180,6 +181,7 @@ import type {
FormValue,
ToolTipConfigType,
} from '../schema';
import { getField } from '../utils/config';
import { createObjectProp, display as displayFunction, filterFunction, getRules } from '../utils/form';
import FormLabel from './FormLabel.vue';
@ -248,11 +250,23 @@ const itemProp = computed(() => {
return `${n}`;
});
const type = computed((): string => {
let { type } = props.config;
type = type && filterFunction<string>(mForm, type, props);
if (type === 'form') return '';
if (type === 'container') return '';
return type?.replace(/([A-Z])/g, '-$1').toLowerCase() || (items.value ? '' : 'text');
});
const tagName = computed(() => {
if (type.value === 'component' && props.config.component) {
return props.config.component;
}
return `m-${items.value ? 'form' : 'fields'}-${type.value}`;
if (!getField(type.value || 'container')) {
console.log(type.value, 'type.value');
}
return getField(type.value || 'container') || `m-${items.value ? 'form' : 'fields'}-${type.value}`;
});
const disabled = computed(() => props.disabled || filterFunction(mForm, props.config.disabled, props));
@ -276,14 +290,6 @@ const tooltip = computed(() => {
const rule = computed(() => getRules(mForm, props.config.rules, props));
const type = computed((): string => {
let { type } = props.config;
type = type && filterFunction<string>(mForm, type, props);
if (type === 'form') return '';
if (type === 'container') return '';
return type?.replace(/([A-Z])/g, '-$1').toLowerCase() || (items.value ? '' : 'text');
});
const display = computed((): boolean => {
const value = displayFunction(mForm, props.config.display, props);

View File

@ -3,14 +3,18 @@
</template>
<script setup lang="ts">
import type { FieldProps, HiddenConfig } from '../schema';
import type { FormValue } from '../schema';
import { useAddField } from '../utils/useAddField';
defineOptions({
name: 'MFormHidden',
});
const props = defineProps<FieldProps<HiddenConfig>>();
const props = defineProps<{
model: FormValue;
name: string;
prop: string;
}>();
useAddField(props.prop);
</script>

View File

@ -16,44 +16,8 @@
* limitations under the License.
*/
import type { App } from 'vue';
import Container from './containers/Container.vue';
import Fieldset from './containers/Fieldset.vue';
import FlexLayout from './containers/FlexLayout.vue';
import GroupList from './containers/GroupList.vue';
import Panel from './containers/Panel.vue';
import Row from './containers/Row.vue';
import MStep from './containers/Step.vue';
import Tabs from './containers/Tabs.vue';
import Cascader from './fields/Cascader.vue';
import Checkbox from './fields/Checkbox.vue';
import CheckboxGroup from './fields/CheckboxGroup.vue';
import ColorPicker from './fields/ColorPicker.vue';
import Date from './fields/Date.vue';
import Daterange from './fields/Daterange.vue';
import DateTime from './fields/DateTime.vue';
import Display from './fields/Display.vue';
import DynamicField from './fields/DynamicField.vue';
import Hidden from './fields/Hidden.vue';
import Link from './fields/Link.vue';
import Number from './fields/Number.vue';
import NumberRange from './fields/NumberRange.vue';
import RadioGroup from './fields/RadioGroup.vue';
import Select from './fields/Select.vue';
import Switch from './fields/Switch.vue';
import Text from './fields/Text.vue';
import Textarea from './fields/Textarea.vue';
import Time from './fields/Time.vue';
import Timerange from './fields/Timerange.vue';
import Table from './table/Table.vue';
import { setConfig } from './utils/config';
import Form from './Form.vue';
import FormDialog from './FormDialog.vue';
import type { FormConfig } from './schema';
import './theme/index.scss';
export * from './schema';
export * from './utils/form';
export * from './utils/useAddField';
@ -91,52 +55,14 @@ export { default as MSelect } from './fields/Select.vue';
export { default as MCascader } from './fields/Cascader.vue';
export { default as MDynamicField } from './fields/DynamicField.vue';
export {
deleteField as deleteFormField,
getField as getFormField,
registerField as registerFormField,
} from './utils/config';
export type { FormInstallOptions } from './plugin';
export const createForm = <T extends [] = []>(config: FormConfig | T) => config;
export interface FormInstallOptions {
[key: string]: any;
}
const defaultInstallOpt: FormInstallOptions = {};
export default {
install(app: App, opt: FormInstallOptions = {}) {
const option = Object.assign(defaultInstallOpt, opt);
app.config.globalProperties.$MAGIC_FORM = option;
setConfig(option);
app.component('m-form', Form);
app.component('m-form-dialog', FormDialog);
app.component('m-form-container', Container);
app.component('m-form-fieldset', Fieldset);
app.component('m-form-group-list', GroupList);
app.component('m-form-panel', Panel);
app.component('m-form-row', Row);
app.component('m-form-step', MStep);
app.component('m-form-table', Table);
app.component('m-form-tab', Tabs);
app.component('m-form-flex-layout', FlexLayout);
app.component('m-fields-text', Text);
app.component('m-fields-img-upload', Text);
app.component('m-fields-number', Number);
app.component('m-fields-number-range', NumberRange);
app.component('m-fields-textarea', Textarea);
app.component('m-fields-hidden', Hidden);
app.component('m-fields-date', Date);
app.component('m-fields-datetime', DateTime);
app.component('m-fields-daterange', Daterange);
app.component('m-fields-timerange', Timerange);
app.component('m-fields-time', Time);
app.component('m-fields-checkbox', Checkbox);
app.component('m-fields-switch', Switch);
app.component('m-fields-color-picker', ColorPicker);
app.component('m-fields-checkbox-group', CheckboxGroup);
app.component('m-fields-radio-group', RadioGroup);
app.component('m-fields-display', Display);
app.component('m-fields-link', Link);
app.component('m-fields-select', Select);
app.component('m-fields-cascader', Cascader);
app.component('m-fields-dynamic-field', DynamicField);
},
};
export { default } from './plugin';

102
packages/form/src/plugin.ts Normal file
View File

@ -0,0 +1,102 @@
/*
* Tencent is pleased to support the open source community by making TMagicEditor available.
*
* Copyright (C) 2025 Tencent. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type App } from 'vue';
import Container from './containers/Container.vue';
import Fieldset from './containers/Fieldset.vue';
import FlexLayout from './containers/FlexLayout.vue';
import GroupList from './containers/GroupList.vue';
import Panel from './containers/Panel.vue';
import Row from './containers/Row.vue';
import MStep from './containers/Step.vue';
import Tabs from './containers/Tabs.vue';
import Cascader from './fields/Cascader.vue';
import Checkbox from './fields/Checkbox.vue';
import CheckboxGroup from './fields/CheckboxGroup.vue';
import ColorPicker from './fields/ColorPicker.vue';
import Date from './fields/Date.vue';
import Daterange from './fields/Daterange.vue';
import DateTime from './fields/DateTime.vue';
import Display from './fields/Display.vue';
import DynamicField from './fields/DynamicField.vue';
import Hidden from './fields/Hidden.vue';
import Link from './fields/Link.vue';
import Number from './fields/Number.vue';
import NumberRange from './fields/NumberRange.vue';
import RadioGroup from './fields/RadioGroup.vue';
import Select from './fields/Select.vue';
import Switch from './fields/Switch.vue';
import Text from './fields/Text.vue';
import Textarea from './fields/Textarea.vue';
import Time from './fields/Time.vue';
import Timerange from './fields/Timerange.vue';
import Table from './table/Table.vue';
import { setConfig } from './utils/config';
import Form from './Form.vue';
import FormDialog from './FormDialog.vue';
import './theme/index.scss';
export interface FormInstallOptions {
[key: string]: any;
}
const defaultInstallOpt: FormInstallOptions = {};
export default {
install(app: App, opt: FormInstallOptions = {}) {
const option = Object.assign(defaultInstallOpt, opt);
app.config.globalProperties.$MAGIC_FORM = option;
setConfig(option);
app.component('m-form', Form);
app.component('m-form-dialog', FormDialog);
app.component('m-form-container', Container);
app.component('m-form-fieldset', Fieldset);
app.component('m-form-group-list', GroupList);
app.component('m-form-panel', Panel);
app.component('m-form-row', Row);
app.component('m-form-step', MStep);
app.component('m-form-table', Table);
app.component('m-form-tab', Tabs);
app.component('m-form-flex-layout', FlexLayout);
app.component('m-fields-text', Text);
app.component('m-fields-img-upload', Text);
app.component('m-fields-number', Number);
app.component('m-fields-number-range', NumberRange);
app.component('m-fields-textarea', Textarea);
app.component('m-fields-hidden', Hidden);
app.component('m-fields-date', Date);
app.component('m-fields-datetime', DateTime);
app.component('m-fields-daterange', Daterange);
app.component('m-fields-timerange', Timerange);
app.component('m-fields-time', Time);
app.component('m-fields-checkbox', Checkbox);
app.component('m-fields-switch', Switch);
app.component('m-fields-color-picker', ColorPicker);
app.component('m-fields-checkbox-group', CheckboxGroup);
app.component('m-fields-radio-group', RadioGroup);
app.component('m-fields-display', Display);
app.component('m-fields-link', Link);
app.component('m-fields-select', Select);
app.component('m-fields-cascader', Cascader);
app.component('m-fields-dynamic-field', DynamicField);
},
};

View File

@ -1,5 +1,5 @@
import { inject, nextTick, type Ref, type ShallowRef, watchEffect } from 'vue';
import Sortable, { type SortableEvent } from 'sortablejs';
import type { default as SortableType, SortableEvent } from 'sortablejs';
import { type TMagicTable } from '@tmagic/design';
import type { FormState } from '@tmagic/form-schema';
@ -8,6 +8,9 @@ import { sortArray } from '../utils/form';
import type { TableProps } from './type';
let SortablePromise: Promise<typeof SortableType> | undefined;
const loadSortable = () => (SortablePromise ??= import('sortablejs').then((m) => m.default));
export const useSortable = (
props: TableProps,
emit: (event: 'select' | 'change' | 'addDiffCount', ...args: any[]) => void,
@ -17,15 +20,16 @@ export const useSortable = (
) => {
const mForm = inject<FormState | undefined>('mForm');
let sortable: Sortable | undefined;
const rowDrop = () => {
let sortable: SortableType | undefined;
const rowDrop = async () => {
sortable?.destroy();
const tableEl = tMagicTableRef.value?.getEl();
const tBodyEl = tableEl?.querySelector('.el-table__body > tbody') || tableEl?.querySelector('.t-table__body');
if (!tBodyEl) {
return;
}
sortable = Sortable.create(tBodyEl, {
sortable = (await loadSortable()).create(tBodyEl, {
draggable: '.tmagic-design-table-row',
filter: 'input', // 表单组件选字操作和触发拖拽会冲突,优先保证选字操作
preventOnFilter: false, // 允许选字

View File

@ -16,6 +16,8 @@
* limitations under the License.
*/
import type { Component } from 'vue';
let $MAGIC_FORM = {} as any;
const setConfig = (option: any): void => {
@ -24,4 +26,17 @@ const setConfig = (option: any): void => {
const getConfig = <T = unknown>(key: string): T => $MAGIC_FORM[key];
export { getConfig, setConfig };
const fieldRegistry = new Map<string, Component>();
const registerField = (tagName: string, component: Component): void => {
if (fieldRegistry.has(tagName)) {
return;
}
fieldRegistry.set(tagName, component);
};
const getField = (tagName: string): Component | undefined => fieldRegistry.get(tagName);
const deleteField = (tagName: string): boolean => fieldRegistry.delete(tagName);
export { deleteField, getConfig, getField, registerField, setConfig };

View File

@ -3,7 +3,7 @@
<nav-menu :data="menu"></nav-menu>
<div class="diff-form">
<div>开启表单对比功能</div>
<m-form
<MForm
ref="form"
:config="diffFormConfig"
:is-compare="true"
@ -11,12 +11,12 @@
:last-values="lastVersion"
size="small"
height="100%"
></m-form>
></MForm>
</div>
<div class="title">表单字段展示</div>
<div class="form-content">
<m-form ref="form" :config="config" :init-values="initValue" size="small" height="100%"></m-form>
<magic-code-editor class="code-editor-content" :init-values="config" @save="change"></magic-code-editor>
<MForm ref="form" :config="config" :init-values="initValue" size="small" height="100%"></MForm>
<TMagicCodeEditor class="code-editor-content" :init-values="config" @save="change"></TMagicCodeEditor>
</div>
</div>