@tmagic/editor 1.8.0-beta.25 → 1.8.0-beta.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +10 -16
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +5 -8
- package/dist/es/components/ViewForm.vue_vue_type_script_setup_true_lang.js +3 -5
- package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +3 -11
- package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +29 -124
- package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +5 -6
- package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +4 -5
- package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +6 -10
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +5 -7
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +1 -4
- package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +4 -6
- package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +9 -142
- package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +51 -326
- package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +2 -4
- package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +3 -34
- package/dist/es/fields/StyleSetter/configs.js +663 -0
- package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +5 -108
- package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +3 -9
- package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +5 -102
- package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +5 -265
- package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +5 -85
- package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +3 -22
- package/dist/es/fields/configs/codeSelect.js +98 -0
- package/dist/es/fields/configs/displayConds.js +158 -0
- package/dist/es/fields/configs/eventSelect.js +225 -0
- package/dist/es/fields/configs/stickyAddButton.js +20 -0
- package/dist/es/fields/headless-validation.js +139 -0
- package/dist/es/headless.js +2 -0
- package/dist/es/hooks/use-compare-form.js +6 -23
- package/dist/es/hooks/use-form-context.js +29 -0
- package/dist/es/index.js +2 -1
- package/dist/es/initService.js +18 -1
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +1 -7
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +1 -11
- package/dist/es/layouts/history-list/useHistoryRevert.js +3 -11
- package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +10 -23
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +3 -13
- package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/data-source/useContentMenu.js +1 -1
- package/dist/es/plugin.js +33 -32
- package/dist/es/services/events.js +2 -2
- package/dist/es/style.css +116 -60
- package/dist/es/utils/code-block.js +14 -7
- package/dist/es/utils/data-source/index.js +2 -1
- package/dist/es/utils/props.js +1 -4
- package/dist/es/utils/type-match-rules.js +2 -2
- package/dist/style.css +116 -60
- package/dist/themes/magic-admin.css +128 -67
- package/dist/tmagic-editor-headless.umd.cjs +10867 -0
- package/dist/tmagic-editor.umd.cjs +2237 -2116
- package/package.json +12 -7
- package/src/Editor.vue +12 -16
- package/src/components/CodeParams.vue +10 -4
- package/src/components/CompareForm.vue +4 -5
- package/src/components/ViewForm.vue +2 -3
- package/src/editorProps.ts +1 -2
- package/src/fields/Code.vue +2 -10
- package/src/fields/CodeSelect.vue +20 -116
- package/src/fields/CodeSelectCol.vue +3 -5
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +1 -1
- package/src/fields/DataSourceFieldSelect/Index.vue +3 -5
- package/src/fields/DataSourceFields.vue +0 -7
- package/src/fields/DataSourceMethodSelect.vue +2 -5
- package/src/fields/DataSourceMethods.vue +1 -6
- package/src/fields/DataSourceMocks.vue +1 -10
- package/src/fields/DataSourceSelect.vue +1 -1
- package/src/fields/DisplayConds.vue +17 -157
- package/src/fields/EventSelect.vue +28 -375
- package/src/fields/KeyValue.vue +3 -4
- package/src/fields/StyleSetter/components/Border.vue +4 -38
- package/src/fields/StyleSetter/configs.ts +690 -0
- package/src/fields/StyleSetter/pro/Background.vue +4 -104
- package/src/fields/StyleSetter/pro/Border.vue +3 -12
- package/src/fields/StyleSetter/pro/Font.vue +4 -123
- package/src/fields/StyleSetter/pro/Layout.vue +4 -219
- package/src/fields/StyleSetter/pro/Position.vue +6 -110
- package/src/fields/StyleSetter/pro/Transform.vue +4 -30
- package/src/fields/configs/codeSelect.ts +127 -0
- package/src/fields/configs/displayConds.ts +184 -0
- package/src/fields/configs/eventSelect.ts +309 -0
- package/src/fields/configs/stickyAddButton.ts +31 -0
- package/src/fields/headless-validation.ts +177 -0
- package/src/headless.ts +33 -0
- package/src/hooks/use-compare-form.ts +7 -25
- package/src/hooks/use-form-context.ts +56 -0
- package/src/index.ts +2 -0
- package/src/initService.ts +24 -1
- package/src/layouts/history-list/HistoryDiffDialog.vue +0 -10
- package/src/layouts/history-list/HistoryListPanel.vue +1 -13
- package/src/layouts/history-list/useHistoryRevert.ts +7 -13
- package/src/layouts/props-panel/FormPanel.vue +17 -28
- package/src/layouts/props-panel/PropsPanel.vue +1 -4
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -1
- package/src/layouts/sidebar/code-block/useContentMenu.ts +1 -1
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -1
- package/src/layouts/sidebar/data-source/useContentMenu.ts +1 -1
- package/src/plugin.ts +32 -33
- package/src/services/events.ts +5 -4
- package/src/theme/code-block.scss +0 -37
- package/src/theme/display-conds.scss +4 -0
- package/src/theme/event.scss +22 -45
- package/src/theme/props-panel.scss +17 -3
- package/src/theme/themes/magic-admin/index.scss +12 -1
- package/src/type.ts +16 -29
- package/src/utils/code-block.ts +1 -0
- package/src/utils/data-source/index.ts +1 -0
- package/src/utils/props.ts +1 -4
- package/src/utils/type-match-rules.ts +8 -3
- package/types/headless.d.ts +18 -0
- package/types/index.d.ts +154 -179
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
:init-values="values"
|
|
14
14
|
:config="config"
|
|
15
15
|
:type-match-valid="true"
|
|
16
|
-
:
|
|
16
|
+
:context="formContext"
|
|
17
17
|
:validate-on-init="true"
|
|
18
18
|
@change="submit"
|
|
19
19
|
@error="errorHandler"
|
|
@@ -45,17 +45,18 @@
|
|
|
45
45
|
</template>
|
|
46
46
|
|
|
47
47
|
<script setup lang="ts">
|
|
48
|
-
import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, useTemplateRef
|
|
48
|
+
import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, useTemplateRef } from 'vue';
|
|
49
49
|
import { Document as DocumentIcon } from '@element-plus/icons-vue';
|
|
50
50
|
|
|
51
51
|
import { TMagicButton, tMagicMessage, TMagicScrollbar } from '@tmagic/design';
|
|
52
|
-
import type { ContainerChangeEventData, FormConfig,
|
|
52
|
+
import type { ContainerChangeEventData, FormConfig, FormValue } from '@tmagic/form';
|
|
53
53
|
import { MForm, validateForm } from '@tmagic/form';
|
|
54
54
|
import { filterXSS } from '@tmagic/utils';
|
|
55
55
|
|
|
56
56
|
import MIcon from '@editor/components/Icon.vue';
|
|
57
57
|
import { ENABLE_PROPS_FORM_VALIDATE } from '@editor/editorProps';
|
|
58
58
|
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
|
|
59
|
+
import { useEditorFormContext } from '@editor/hooks/use-form-context';
|
|
59
60
|
import { useServices } from '@editor/hooks/use-services';
|
|
60
61
|
|
|
61
62
|
import CodeEditor from '../CodeEditor.vue';
|
|
@@ -74,8 +75,7 @@ const props = defineProps<{
|
|
|
74
75
|
disabledShowSrc?: boolean;
|
|
75
76
|
labelWidth?: string;
|
|
76
77
|
codeValueKey?: string;
|
|
77
|
-
labelPosition?:
|
|
78
|
-
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
78
|
+
labelPosition?: 'top' | 'left' | 'right';
|
|
79
79
|
}>();
|
|
80
80
|
|
|
81
81
|
const emit = defineEmits<{
|
|
@@ -89,23 +89,17 @@ const emit = defineEmits<{
|
|
|
89
89
|
const enablePropsFormValidate = inject(ENABLE_PROPS_FORM_VALIDATE, false);
|
|
90
90
|
|
|
91
91
|
const services = useServices();
|
|
92
|
-
const {
|
|
92
|
+
const { uiService } = services;
|
|
93
93
|
|
|
94
94
|
const codeOptions = inject('codeOptions', {});
|
|
95
95
|
|
|
96
96
|
const showSrc = ref(false);
|
|
97
97
|
const propsPanelSize = computed(() => uiService.get('propsPanelSize') || 'small');
|
|
98
98
|
const { height: editorContentHeight } = useEditorContentHeight();
|
|
99
|
-
const stage = computed(() => editorService.get('stage'));
|
|
100
99
|
|
|
101
|
-
const
|
|
100
|
+
const formContext = useEditorFormContext(() => services);
|
|
102
101
|
|
|
103
|
-
|
|
104
|
-
if (configFormRef.value) {
|
|
105
|
-
configFormRef.value.formState.stage = stage.value;
|
|
106
|
-
configFormRef.value.formState.services = services;
|
|
107
|
-
}
|
|
108
|
-
});
|
|
102
|
+
const configFormRef = useTemplateRef<InstanceType<typeof MForm>>('configForm');
|
|
109
103
|
|
|
110
104
|
const internalInstance = getCurrentInstance();
|
|
111
105
|
onMounted(() => {
|
|
@@ -158,23 +152,17 @@ const saveCode = async (values: any) => {
|
|
|
158
152
|
return;
|
|
159
153
|
}
|
|
160
154
|
|
|
161
|
-
//
|
|
162
|
-
//
|
|
155
|
+
// 启用校验联动:源码编辑器保存的值未经过表单交互,这里对最新配置做一次无渲染的静默校验
|
|
156
|
+
// (不挂载任何组件,也不影响页面上正在展示的表单),并将校验结果(错误信息)随提交
|
|
163
157
|
// 一并抛给上层记录,使源码保存的错误状态与表单编辑保持一致。
|
|
158
|
+
//
|
|
159
|
+
// 配置里的 display / rules 回调会从 formState 上读 services,因此必须带上 context。
|
|
164
160
|
try {
|
|
165
161
|
const error = await validateForm({
|
|
166
162
|
config: props.config,
|
|
167
163
|
typeMatchValid: true,
|
|
168
164
|
initValues: newValues,
|
|
169
|
-
|
|
170
|
-
// 合入 appContext,使临时 MForm 中的编辑器字段组件(DataSourceInput 等)能正常 inject
|
|
171
|
-
appContext: internalInstance?.appContext ? { ...internalInstance?.appContext, provides: { services } } : null,
|
|
172
|
-
extendState: (state) => {
|
|
173
|
-
if (configFormRef.value?.formState) {
|
|
174
|
-
return { ...(configFormRef.value?.formState || {}) };
|
|
175
|
-
}
|
|
176
|
-
return props.extendState?.(state) || {};
|
|
177
|
-
},
|
|
165
|
+
context: formContext.value,
|
|
178
166
|
});
|
|
179
167
|
|
|
180
168
|
if (error) {
|
|
@@ -187,9 +175,10 @@ const saveCode = async (values: any) => {
|
|
|
187
175
|
|
|
188
176
|
emit('submit', newValues, undefined, error ? new Error(error) : undefined);
|
|
189
177
|
} catch (e: any) {
|
|
190
|
-
console.
|
|
191
|
-
//
|
|
192
|
-
|
|
178
|
+
console.error('validateForm error', e);
|
|
179
|
+
// 嵌套配置 / initValue 等机制故障不得当成「校验通过」,
|
|
180
|
+
// 把 error 交给上层记录,同时仍提交源码,避免阻塞保存。
|
|
181
|
+
emit('submit', newValues, undefined, e instanceof Error ? e : new Error(String(e)));
|
|
193
182
|
}
|
|
194
183
|
};
|
|
195
184
|
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
:config="curFormConfig"
|
|
9
9
|
:values="values"
|
|
10
10
|
:disabledShowSrc="disabledShowSrc"
|
|
11
|
-
:extendState="extendState"
|
|
12
11
|
@submit="(v, eventData, error) => submit(v, eventData, error, 'props')"
|
|
13
12
|
@submit-error="errorHandler"
|
|
14
13
|
@form-error="errorHandler"
|
|
@@ -26,7 +25,6 @@
|
|
|
26
25
|
:config="styleFormConfig"
|
|
27
26
|
:values="values"
|
|
28
27
|
:disabledShowSrc="disabledShowSrc"
|
|
29
|
-
:extendState="extendState"
|
|
30
28
|
@submit="(v, eventData, error) => submit(v, eventData, error, 'style')"
|
|
31
29
|
@submit-error="errorHandler"
|
|
32
30
|
@form-error="errorHandler"
|
|
@@ -61,7 +59,7 @@ import type { OnDrag } from 'gesto';
|
|
|
61
59
|
|
|
62
60
|
import { type MNode } from '@tmagic/core';
|
|
63
61
|
import { TMagicButton } from '@tmagic/design';
|
|
64
|
-
import type { ContainerChangeEventData,
|
|
62
|
+
import type { ContainerChangeEventData, FormValue } from '@tmagic/form';
|
|
65
63
|
import { setValueByKeyPath } from '@tmagic/utils';
|
|
66
64
|
|
|
67
65
|
import MIcon from '@editor/components/Icon.vue';
|
|
@@ -84,7 +82,6 @@ defineOptions({
|
|
|
84
82
|
|
|
85
83
|
defineProps<{
|
|
86
84
|
disabledShowSrc?: boolean;
|
|
87
|
-
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
88
85
|
}>();
|
|
89
86
|
|
|
90
87
|
const emit = defineEmits<{
|
|
@@ -6,7 +6,7 @@ import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
|
6
6
|
import type { ContentMenuTarget, EventBus, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
|
|
7
7
|
|
|
8
8
|
export const useContentMenu = (deleteCode: (id: string) => void) => {
|
|
9
|
-
const eventBus = inject<EventBus>('eventBus');
|
|
9
|
+
const eventBus = inject<EventBus | null>('eventBus', null);
|
|
10
10
|
const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
|
|
11
11
|
|
|
12
12
|
let selectId = '';
|
|
@@ -75,7 +75,7 @@ const props = defineProps<{
|
|
|
75
75
|
customContentMenu: CustomContentMenuFunction;
|
|
76
76
|
}>();
|
|
77
77
|
|
|
78
|
-
const eventBus = inject<EventBus>('eventBus');
|
|
78
|
+
const eventBus = inject<EventBus | null>('eventBus', null);
|
|
79
79
|
const { dataSourceService } = useServices();
|
|
80
80
|
|
|
81
81
|
const { editDialog, dataSourceValues, dialogTitle, editable, editHandler, submitDataSourceHandler } =
|
|
@@ -6,7 +6,7 @@ import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
|
6
6
|
import type { ContentMenuTarget, EventBus, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
|
|
7
7
|
|
|
8
8
|
export const useContentMenu = () => {
|
|
9
|
-
const eventBus = inject<EventBus>('eventBus');
|
|
9
|
+
const eventBus = inject<EventBus | null>('eventBus', null);
|
|
10
10
|
const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
|
|
11
11
|
|
|
12
12
|
let selectId = '';
|
package/src/plugin.ts
CHANGED
|
@@ -20,8 +20,8 @@ import { type App } from 'vue';
|
|
|
20
20
|
|
|
21
21
|
import type { DesignPluginOptions } from '@tmagic/design';
|
|
22
22
|
import designPlugin from '@tmagic/design';
|
|
23
|
-
import type { FormInstallOptions } from '@tmagic/form';
|
|
24
|
-
import formPlugin, {
|
|
23
|
+
import type { FieldOptions, FormInstallOptions } from '@tmagic/form';
|
|
24
|
+
import formPlugin, { mergeFieldOptions } from '@tmagic/form';
|
|
25
25
|
import tablePlugin from '@tmagic/table';
|
|
26
26
|
|
|
27
27
|
import Code from './fields/Code.vue';
|
|
@@ -38,13 +38,13 @@ import DataSourceMocks from './fields/DataSourceMocks.vue';
|
|
|
38
38
|
import DataSourceSelect from './fields/DataSourceSelect.vue';
|
|
39
39
|
import DisplayConds from './fields/DisplayConds.vue';
|
|
40
40
|
import EventSelect from './fields/EventSelect.vue';
|
|
41
|
+
import { editorFields } from './fields/headless-validation';
|
|
41
42
|
import KeyValue from './fields/KeyValue.vue';
|
|
42
43
|
import PageFragmentSelect from './fields/PageFragmentSelect.vue';
|
|
43
44
|
import StyleSetter from './fields/StyleSetter/Index.vue';
|
|
44
45
|
import uiSelect from './fields/UISelect.vue';
|
|
45
46
|
import CodeEditor from './layouts/CodeEditor.vue';
|
|
46
47
|
import { setEditorConfig } from './utils/config';
|
|
47
|
-
import { editorTypeMatchRules } from './utils/type-match-rules';
|
|
48
48
|
import Editor from './Editor.vue';
|
|
49
49
|
import type { EditorInstallOptions } from './type';
|
|
50
50
|
|
|
@@ -60,44 +60,43 @@ const defaultInstallOpt: EditorInstallOptions = {
|
|
|
60
60
|
flat: false,
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
+
const editorFieldVue: Record<string, Pick<FieldOptions, 'component' | 'container'>> = {
|
|
64
|
+
'vs-code': { component: Code },
|
|
65
|
+
'ui-select': { component: uiSelect },
|
|
66
|
+
'cond-op-select': { component: CondOpSelect },
|
|
67
|
+
'page-fragment-select': { component: PageFragmentSelect },
|
|
68
|
+
'data-source-select': { component: DataSourceSelect },
|
|
69
|
+
'data-source-input': { component: DataSourceInput },
|
|
70
|
+
'code-link': { component: CodeLink },
|
|
71
|
+
'key-value': { component: KeyValue },
|
|
72
|
+
'code-select-col': { component: CodeSelectCol },
|
|
73
|
+
'data-source-fields': { component: DataSourceFields },
|
|
74
|
+
'data-source-mocks': { component: DataSourceMocks },
|
|
75
|
+
'data-source-methods': { component: DataSourceMethods },
|
|
76
|
+
'data-source-method-select': { component: DataSourceMethodSelect },
|
|
77
|
+
'data-source-field-select': { component: DataSourceFieldSelect },
|
|
78
|
+
'code-select': { component: CodeSelect },
|
|
79
|
+
'display-conds': { component: DisplayConds },
|
|
80
|
+
'event-select': { component: EventSelect },
|
|
81
|
+
'style-setter': { container: StyleSetter },
|
|
82
|
+
};
|
|
83
|
+
|
|
63
84
|
export default {
|
|
64
85
|
install: (app: App, opt?: Partial<EditorInstallOptions | DesignPluginOptions | FormInstallOptions>): void => {
|
|
65
|
-
const
|
|
86
|
+
const incoming = opt || {};
|
|
87
|
+
const option = { ...defaultInstallOpt, ...incoming };
|
|
88
|
+
const formOpt = incoming as FormInstallOptions;
|
|
66
89
|
|
|
67
|
-
app.use(designPlugin,
|
|
68
|
-
app.use(formPlugin,
|
|
90
|
+
app.use(designPlugin, incoming);
|
|
91
|
+
app.use(formPlugin, {
|
|
92
|
+
...formOpt,
|
|
93
|
+
fields: mergeFieldOptions(editorFields, editorFieldVue, formOpt.fields),
|
|
94
|
+
});
|
|
69
95
|
app.use(tablePlugin);
|
|
70
|
-
registerTypeMatchRules(editorTypeMatchRules);
|
|
71
|
-
registerSilentLeafFieldTypes([
|
|
72
|
-
'vs-code',
|
|
73
|
-
'ui-select',
|
|
74
|
-
'cond-op-select',
|
|
75
|
-
'page-fragment-select',
|
|
76
|
-
'data-source-select',
|
|
77
|
-
'data-source-input',
|
|
78
|
-
]);
|
|
79
96
|
|
|
80
97
|
app.config.globalProperties.$TMAGIC_EDITOR = option;
|
|
81
98
|
setEditorConfig(option);
|
|
82
99
|
app.component(`${Editor.name || 'MEditor'}`, Editor);
|
|
83
100
|
app.component('magic-code-editor', CodeEditor);
|
|
84
|
-
app.component('m-fields-ui-select', uiSelect);
|
|
85
|
-
app.component('m-fields-code-link', CodeLink);
|
|
86
|
-
app.component('m-fields-vs-code', Code);
|
|
87
|
-
app.component('m-fields-code-select', CodeSelect);
|
|
88
|
-
app.component('m-fields-code-select-col', CodeSelectCol);
|
|
89
|
-
app.component('m-fields-event-select', EventSelect);
|
|
90
|
-
app.component('m-fields-data-source-fields', DataSourceFields);
|
|
91
|
-
app.component('m-fields-data-source-mocks', DataSourceMocks);
|
|
92
|
-
app.component('m-fields-key-value', KeyValue);
|
|
93
|
-
app.component('m-fields-data-source-input', DataSourceInput);
|
|
94
|
-
app.component('m-fields-data-source-select', DataSourceSelect);
|
|
95
|
-
app.component('m-fields-data-source-methods', DataSourceMethods);
|
|
96
|
-
app.component('m-fields-data-source-method-select', DataSourceMethodSelect);
|
|
97
|
-
app.component('m-fields-data-source-field-select', DataSourceFieldSelect);
|
|
98
|
-
app.component('m-fields-page-fragment-select', PageFragmentSelect);
|
|
99
|
-
app.component('m-fields-display-conds', DisplayConds);
|
|
100
|
-
app.component('m-fields-cond-op-select', CondOpSelect);
|
|
101
|
-
app.component('m-form-style-setter', StyleSetter);
|
|
102
101
|
},
|
|
103
102
|
};
|
package/src/services/events.ts
CHANGED
|
@@ -35,8 +35,8 @@ const canUsePluginMethods = {
|
|
|
35
35
|
type AsyncMethodName = Writable<(typeof canUsePluginMethods)['async']>;
|
|
36
36
|
type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const eventMap: Record<string, EventOption[]> = reactive({});
|
|
39
|
+
const methodMap: Record<string, EventOption[]> = reactive({});
|
|
40
40
|
|
|
41
41
|
class Events extends BaseService {
|
|
42
42
|
constructor() {
|
|
@@ -75,8 +75,9 @@ class Events extends BaseService {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
public resetState() {
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
// 原地清空而不是重新赋值,保留 reactive 代理身份,已建立的 computed / 渲染副作用才能收到更新
|
|
79
|
+
Object.keys(eventMap).forEach((type) => delete eventMap[type]);
|
|
80
|
+
Object.keys(methodMap).forEach((type) => delete methodMap[type]);
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
public destroy() {
|
|
@@ -1,40 +1,3 @@
|
|
|
1
1
|
.m-fields-code-select {
|
|
2
2
|
width: 100%;
|
|
3
|
-
> .el-card.tmagic-design-card--flat {
|
|
4
|
-
background-color: transparent;
|
|
5
|
-
margin-bottom: 10px;
|
|
6
|
-
> .el-card__body {
|
|
7
|
-
padding-left: 0;
|
|
8
|
-
.code-select-content {
|
|
9
|
-
> .m-fields-group-list {
|
|
10
|
-
> .tmagic-design-card--flat.el-card {
|
|
11
|
-
padding-left: 16px;
|
|
12
|
-
padding-right: 16px;
|
|
13
|
-
margin-bottom: 10px;
|
|
14
|
-
border: 0 !important;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
.el-card__body {
|
|
21
|
-
.tmagic-design-form-item {
|
|
22
|
-
margin-bottom: 16px;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
.code-select-content {
|
|
26
|
-
> .m-fields-group-list {
|
|
27
|
-
> .tmagic-design-card--flat {
|
|
28
|
-
> .el-card__header {
|
|
29
|
-
padding: 16px 0;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
.create-button {
|
|
35
|
-
&.fullWidth {
|
|
36
|
-
width: 100%;
|
|
37
|
-
margin: 0 0 16px 0;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
3
|
}
|
package/src/theme/event.scss
CHANGED
|
@@ -1,49 +1,45 @@
|
|
|
1
1
|
.m-fields-event-select {
|
|
2
2
|
width: 100%;
|
|
3
|
+
|
|
3
4
|
.fullWidth {
|
|
4
5
|
width: 100%;
|
|
5
6
|
box-sizing: border-box;
|
|
6
|
-
&.create-button {
|
|
7
|
-
width: 100%;
|
|
8
|
-
}
|
|
9
7
|
&.m-container-ui-event {
|
|
10
8
|
width: calc(100% - 32px);
|
|
11
9
|
}
|
|
12
10
|
}
|
|
11
|
+
|
|
13
12
|
.event-select-container {
|
|
14
13
|
padding: 0 16px;
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
|
|
15
|
+
> .m-fields-group-list
|
|
16
|
+
> .m-fields-group-list-item.tmagic-design-card--flat {
|
|
17
|
+
> .el-card__header,
|
|
18
|
+
> .t-card__header {
|
|
17
19
|
border-bottom: 1px solid #ebeef5;
|
|
18
20
|
}
|
|
19
|
-
|
|
21
|
+
|
|
22
|
+
> .el-card__body,
|
|
23
|
+
> .t-card__body {
|
|
20
24
|
padding-bottom: 16px;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.el-card.tmagic-design-card--flat {
|
|
27
|
-
> .el-card__header {
|
|
25
|
+
|
|
26
|
+
.el-card.tmagic-design-card--flat,
|
|
27
|
+
.t-card.tmagic-design-card--flat {
|
|
28
|
+
> .el-card__header,
|
|
29
|
+
> .t-card__header {
|
|
28
30
|
padding: 16px 0;
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
}
|
|
36
|
+
|
|
34
37
|
.event-select-code {
|
|
35
38
|
margin-left: 20px;
|
|
36
39
|
width: auto;
|
|
37
40
|
}
|
|
38
|
-
|
|
39
|
-
.m-form-panel {
|
|
40
|
-
margin: 10px 0px;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.el-card.is-always-shadow {
|
|
44
|
-
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.12);
|
|
45
|
-
}
|
|
46
41
|
}
|
|
42
|
+
|
|
47
43
|
.m-fields-code-select-col,
|
|
48
44
|
.m-fields-data-source-method-select {
|
|
49
45
|
width: 100%;
|
|
@@ -63,10 +59,6 @@
|
|
|
63
59
|
}
|
|
64
60
|
}
|
|
65
61
|
|
|
66
|
-
.event-select-container {
|
|
67
|
-
padding: 0 16px;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
62
|
.event-select-header {
|
|
71
63
|
display: flex;
|
|
72
64
|
align-items: center;
|
|
@@ -79,28 +71,13 @@
|
|
|
79
71
|
line-height: 24px;
|
|
80
72
|
}
|
|
81
73
|
}
|
|
74
|
+
|
|
82
75
|
.event-item-header {
|
|
83
|
-
position: relative;
|
|
84
76
|
width: 100%;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
justify-content: space-between;
|
|
88
|
-
.event-item-title {
|
|
89
|
-
color: #0f1113;
|
|
90
|
-
font-size: 16px;
|
|
91
|
-
font-weight: 500;
|
|
92
|
-
line-height: 24px;
|
|
93
|
-
margin-bottom: 8px;
|
|
94
|
-
}
|
|
95
|
-
.event-item-delete-button {
|
|
96
|
-
color: #0f1113;
|
|
77
|
+
.tmagic-design-form-item {
|
|
78
|
+
margin-bottom: 0;
|
|
97
79
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.el-form-item {
|
|
101
|
-
&.is-error {
|
|
102
|
-
margin-bottom: 18px;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
80
|
+
.el-form-item .el-form-item.is-error {
|
|
81
|
+
margin-bottom: 18px;
|
|
105
82
|
}
|
|
106
83
|
}
|
|
@@ -125,14 +125,28 @@
|
|
|
125
125
|
.m-editor-props-form-panel-form {
|
|
126
126
|
padding-right: 10px;
|
|
127
127
|
padding-left: 10px;
|
|
128
|
+
// 吸顶标题避开绝对定位的 tabs header
|
|
129
|
+
--m-group-list-header-sticky-top: var(
|
|
130
|
+
--el-tabs-header-height,
|
|
131
|
+
var(--td-comp-size-xxl, 48px)
|
|
132
|
+
);
|
|
128
133
|
|
|
129
134
|
> .m-container-tab {
|
|
130
135
|
> .tmagic-design-tabs {
|
|
131
|
-
> .el-tabs__content
|
|
132
|
-
|
|
136
|
+
> .el-tabs__content,
|
|
137
|
+
> .t-tabs__content {
|
|
138
|
+
margin-top: var(--el-tabs-header-height, var(--td-comp-size-xxl, 48px));
|
|
133
139
|
padding-top: 15px;
|
|
140
|
+
// 允许吸底按钮相对属性面板滚动容器定位(tabs 默认 overflow:hidden 会截断 sticky)
|
|
141
|
+
overflow: visible;
|
|
142
|
+
|
|
143
|
+
> .el-tab-pane,
|
|
144
|
+
> .t-tab-panel {
|
|
145
|
+
overflow: visible;
|
|
146
|
+
}
|
|
134
147
|
}
|
|
135
|
-
> .el-tabs__header.is-top
|
|
148
|
+
> .el-tabs__header.is-top,
|
|
149
|
+
> .t-tabs__header {
|
|
136
150
|
position: absolute;
|
|
137
151
|
top: 0;
|
|
138
152
|
width: 100%;
|
|
@@ -137,7 +137,8 @@
|
|
|
137
137
|
.m-editor-props-form-panel-form {
|
|
138
138
|
> .m-container-tab {
|
|
139
139
|
> .tmagic-design-tabs {
|
|
140
|
-
> .el-tabs__content
|
|
140
|
+
> .el-tabs__content,
|
|
141
|
+
> .t-tabs__content {
|
|
141
142
|
background-color: #fafafa;
|
|
142
143
|
border-radius: 8px;
|
|
143
144
|
padding-left: 16px;
|
|
@@ -146,6 +147,16 @@
|
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
}
|
|
150
|
+
|
|
151
|
+
.m-fields-group-list-footer.is-sticky-full {
|
|
152
|
+
--m-group-list-footer-bg: #fafafa;
|
|
153
|
+
background-color: #fafafa;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.m-fields-group-list-item .m-fields-group-list-footer.is-sticky-full {
|
|
157
|
+
--m-group-list-footer-bg: #fff;
|
|
158
|
+
background-color: #fff;
|
|
159
|
+
}
|
|
149
160
|
}
|
|
150
161
|
|
|
151
162
|
.m-editor.m-theme--magic-admin {
|
package/src/type.ts
CHANGED
|
@@ -34,7 +34,7 @@ import type {
|
|
|
34
34
|
MPageFragment,
|
|
35
35
|
} from '@tmagic/core';
|
|
36
36
|
import type { FieldSize } from '@tmagic/design';
|
|
37
|
-
import type { ChangeRecord, FormConfig,
|
|
37
|
+
import type { ChangeRecord, FormConfig, TableColumnConfig, TypeFunction } from '@tmagic/form';
|
|
38
38
|
import type StageCore from '@tmagic/stage';
|
|
39
39
|
import type {
|
|
40
40
|
CanDropIn,
|
|
@@ -172,6 +172,15 @@ export interface Services {
|
|
|
172
172
|
}
|
|
173
173
|
// #endregion Services
|
|
174
174
|
|
|
175
|
+
declare module '@tmagic/form-schema' {
|
|
176
|
+
interface FormContext {
|
|
177
|
+
/** 编辑器服务集合(由 Editor / FormPanel provide) */
|
|
178
|
+
services?: Services;
|
|
179
|
+
/** 当前画布 Stage 实例(由 Editor / FormPanel provide) */
|
|
180
|
+
stage?: any;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
175
184
|
export interface StageOptions {
|
|
176
185
|
runtimeUrl?: string;
|
|
177
186
|
autoScrollIntoView?: boolean;
|
|
@@ -216,6 +225,7 @@ export interface StageOptions {
|
|
|
216
225
|
beforeDblclick?: (event: MouseEvent) => Promise<boolean | void> | boolean | void;
|
|
217
226
|
}
|
|
218
227
|
|
|
228
|
+
// #region NodeInvalidInfo
|
|
219
229
|
/**
|
|
220
230
|
* 节点校验错误信息,按来源(属性表单 / 样式表单)分别保存错误文案。
|
|
221
231
|
* 属性表单与样式表单是两个独立的 FormPanel,均指向同一节点,故以来源为键,
|
|
@@ -228,9 +238,12 @@ export interface NodeInvalidInfo {
|
|
|
228
238
|
/** 样式表单校验错误文案(可能为包含 <br> 的 HTML) */
|
|
229
239
|
style?: string;
|
|
230
240
|
}
|
|
241
|
+
// #endregion NodeInvalidInfo
|
|
231
242
|
|
|
243
|
+
// #region NodeInvalidSource
|
|
232
244
|
/** 节点校验错误来源 */
|
|
233
245
|
export type NodeInvalidSource = keyof NodeInvalidInfo;
|
|
246
|
+
// #endregion NodeInvalidSource
|
|
234
247
|
|
|
235
248
|
export interface StoreState {
|
|
236
249
|
root: MApp | null;
|
|
@@ -303,6 +316,7 @@ export interface StageRect {
|
|
|
303
316
|
height: number | string;
|
|
304
317
|
}
|
|
305
318
|
|
|
319
|
+
// #region UiState
|
|
306
320
|
export interface UiState {
|
|
307
321
|
/** 当前点击画布是否触发选中,true: 不触发,false: 触发,默认为false */
|
|
308
322
|
uiSelectMode: boolean;
|
|
@@ -360,6 +374,7 @@ export interface UiState {
|
|
|
360
374
|
height: number;
|
|
361
375
|
};
|
|
362
376
|
}
|
|
377
|
+
// #endregion UiState
|
|
363
378
|
|
|
364
379
|
// #region EditorNodeInfo
|
|
365
380
|
export interface EditorNodeInfo {
|
|
@@ -598,18 +613,6 @@ export interface CompareFormBaseProps {
|
|
|
598
613
|
* 避免 dialog / 面板使用方需要自行处理滚动。可传任意 CSS 长度,例如 `60vh` / `400px` / `100%`。
|
|
599
614
|
*/
|
|
600
615
|
height?: string;
|
|
601
|
-
/**
|
|
602
|
-
* 用户自定义注入到 MForm.formState 的扩展字段,与 Editor 顶层的 `extendFormState`、
|
|
603
|
-
* PropsPanel 的 `extend-state` 语义一致。表单 item 的 `display` / `disabled` 等
|
|
604
|
-
* filterFunction 经常依赖这里注入的字段(如 stage、自定义业务上下文等),
|
|
605
|
-
* 因此在对比 / 展示场景下也需要透传,避免出现 `formState.xxx is undefined` 的运行时错误。
|
|
606
|
-
*/
|
|
607
|
-
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
608
|
-
/**
|
|
609
|
-
* 外部透传的基础 formState(通常来自 PropsPanel 主属性表单)。
|
|
610
|
-
* 组件会提取其中的扩展字段覆盖到自己的 formState,保证 filterFunction 上下文一致。
|
|
611
|
-
*/
|
|
612
|
-
baseFormState?: FormState;
|
|
613
616
|
/**
|
|
614
617
|
* 表单内组件的尺寸(透传给 MForm 的 `size`),可选 'large' | 'default' | 'small'。
|
|
615
618
|
* 缺省时使用 MForm 内置默认尺寸。
|
|
@@ -1558,17 +1561,6 @@ export interface UseHistoryRevertOptions {
|
|
|
1558
1561
|
* (`getCurrentInstance()?.appContext`)。业务方若在组件 setup 之外调用,需手动传入(如 `editorApp._context`)。
|
|
1559
1562
|
*/
|
|
1560
1563
|
appContext?: AppContext | null;
|
|
1561
|
-
/**
|
|
1562
|
-
* 透传给差异确认弹窗的 `extendState`(即 Editor 的 `extendFormState`),
|
|
1563
|
-
* 使对比表单中依赖业务上下文的 `display` / `disabled` 等 filterFunction 正常工作。
|
|
1564
|
-
*/
|
|
1565
|
-
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
1566
|
-
/**
|
|
1567
|
-
* 返回 PropsPanel 主属性表单(FormPanel -> MForm)的 formState。
|
|
1568
|
-
* 仅页面历史「查看差异 / 回滚确认」场景会使用该 formState 覆盖 CompareForm 中同名扩展字段,
|
|
1569
|
-
* 以保证两处 filterFunction 读取到一致的运行态上下文。
|
|
1570
|
-
*/
|
|
1571
|
-
getPropsPanelFormState?: () => FormState | undefined;
|
|
1572
1564
|
/**
|
|
1573
1565
|
* 内置页面 / 数据源 / 代码块的差异 / 回滚确认弹窗默认宽度(透传给 TMagicDialog 的 `width`),
|
|
1574
1566
|
* 如 `'1200px'` / `'80%'`。缺省时使用弹窗内置默认宽度(900px)。
|
|
@@ -1590,11 +1582,6 @@ export interface CustomDiffFormOptions {
|
|
|
1590
1582
|
loadConfig?: CompareFormLoadConfig;
|
|
1591
1583
|
/** 需要走 self diff 的字段类型(如模块的 mod-cond)。 */
|
|
1592
1584
|
selfDiffFieldTypes?: string[];
|
|
1593
|
-
/**
|
|
1594
|
-
* 可选:外部提供的 formState(通常来自 PropsPanel 主表单),
|
|
1595
|
-
* 对比弹窗会用它覆盖 CompareForm 中同名扩展字段,避免上下文不一致。
|
|
1596
|
-
*/
|
|
1597
|
-
compareFormState?: FormState;
|
|
1598
1585
|
/**
|
|
1599
1586
|
* 差异 / 确认回滚弹窗宽度(透传给 HistoryDiffDialog 的 TMagicDialog `width`),
|
|
1600
1587
|
* 如 `'1200px'` / `'80%'`。缺省时使用弹窗内置默认宽度(900px)。
|
package/src/utils/code-block.ts
CHANGED
|
@@ -103,6 +103,7 @@ export const getCodeBlockFormConfig = (options: GetCodeBlockFormConfigOptions =
|
|
|
103
103
|
const list = [
|
|
104
104
|
{ text: '初始化前', value: 'beforeInit' },
|
|
105
105
|
{ text: '初始化后', value: 'afterInit' },
|
|
106
|
+
{ text: '页面渲染后', value: 'mounted' },
|
|
106
107
|
];
|
|
107
108
|
if (dataSourceType?.() !== 'base') {
|
|
108
109
|
list.push({ text: '请求前', value: 'beforeRequest' });
|