@tmagic/editor 1.8.0-beta.24 → 1.8.0-beta.26
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/CondOpSelect.vue_vue_type_script_setup_true_lang.js +3 -2
- 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 +7 -6
- 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 -137
- 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 +6 -103
- 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 +19 -0
- package/dist/es/index.js +3 -2
- package/dist/es/initService.js +17 -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/style.css +120 -60
- 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 +23 -22
- package/dist/style.css +120 -60
- package/dist/themes/magic-admin.css +132 -67
- package/dist/tmagic-editor-headless.umd.cjs +10867 -0
- package/dist/tmagic-editor.umd.cjs +2151 -2034
- 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/CondOpSelect.vue +3 -2
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +1 -1
- package/src/fields/DataSourceFieldSelect/Index.vue +7 -6
- 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 -153
- 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 +5 -124
- 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 +40 -0
- package/src/index.ts +2 -0
- package/src/initService.ts +23 -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/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 +10 -29
- package/src/utils/data-source/index.ts +1 -0
- package/src/utils/props.ts +1 -4
- package/src/utils/type-match-rules.ts +37 -31
- package/types/headless.d.ts +18 -0
- package/types/index.d.ts +155 -180
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.8.0-beta.
|
|
2
|
+
"version": "1.8.0-beta.26",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"import": "./dist/es/index.js",
|
|
18
18
|
"require": "./dist/tmagic-editor.umd.cjs"
|
|
19
19
|
},
|
|
20
|
+
"./headless": {
|
|
21
|
+
"types": "./types/headless.d.ts",
|
|
22
|
+
"import": "./dist/es/headless.js",
|
|
23
|
+
"require": "./dist/tmagic-editor-headless.umd.cjs"
|
|
24
|
+
},
|
|
20
25
|
"./dist/style.css": {
|
|
21
26
|
"import": "./dist/style.css",
|
|
22
27
|
"require": "./dist/style.css"
|
|
@@ -58,11 +63,11 @@
|
|
|
58
63
|
"moveable": "^0.53.0",
|
|
59
64
|
"serialize-javascript": "^7.0.7",
|
|
60
65
|
"sortablejs": "^1.15.7",
|
|
61
|
-
"@tmagic/design": "1.8.0-beta.
|
|
62
|
-
"@tmagic/form": "1.8.0-beta.
|
|
63
|
-
"@tmagic/
|
|
64
|
-
"@tmagic/
|
|
65
|
-
"@tmagic/
|
|
66
|
+
"@tmagic/design": "1.8.0-beta.26",
|
|
67
|
+
"@tmagic/form": "1.8.0-beta.26",
|
|
68
|
+
"@tmagic/stage": "1.8.0-beta.26",
|
|
69
|
+
"@tmagic/table": "1.8.0-beta.26",
|
|
70
|
+
"@tmagic/utils": "1.8.0-beta.26"
|
|
66
71
|
},
|
|
67
72
|
"devDependencies": {
|
|
68
73
|
"@types/events": "^3.0.3",
|
|
@@ -76,7 +81,7 @@
|
|
|
76
81
|
"type-fest": "^5.2.0",
|
|
77
82
|
"typescript": "^6.0.3",
|
|
78
83
|
"vue": "^3.5.41",
|
|
79
|
-
"@tmagic/core": "1.8.0-beta.
|
|
84
|
+
"@tmagic/core": "1.8.0-beta.26"
|
|
80
85
|
},
|
|
81
86
|
"peerDependenciesMeta": {
|
|
82
87
|
"typescript": {
|
package/src/Editor.vue
CHANGED
|
@@ -101,7 +101,6 @@
|
|
|
101
101
|
<template #props-panel>
|
|
102
102
|
<slot name="props-panel">
|
|
103
103
|
<PropsPanel
|
|
104
|
-
:extend-state="extendFormState"
|
|
105
104
|
:disabled-show-src="disabledShowSrc"
|
|
106
105
|
@mounted="propsPanelMountedHandler"
|
|
107
106
|
@unmounted="propsPanelUnmountedHandler"
|
|
@@ -136,11 +135,13 @@
|
|
|
136
135
|
<script lang="ts" setup>
|
|
137
136
|
import { EventEmitter } from 'events';
|
|
138
137
|
|
|
139
|
-
import { computed, provide
|
|
138
|
+
import { computed, provide } from 'vue';
|
|
140
139
|
|
|
141
140
|
import type { MApp } from '@tmagic/core';
|
|
142
141
|
import { M_THEME_KEY } from '@tmagic/design';
|
|
142
|
+
import { FORM_CONTEXT_KEY } from '@tmagic/form';
|
|
143
143
|
|
|
144
|
+
import { useEditorFormContext } from './hooks/use-form-context';
|
|
144
145
|
import Framework from './layouts/Framework.vue';
|
|
145
146
|
import TMagicNavMenu from './layouts/NavMenu.vue';
|
|
146
147
|
import FormPanel from './layouts/props-panel/FormPanel.vue';
|
|
@@ -230,8 +231,6 @@ const stageOptions: StageOptions = {
|
|
|
230
231
|
|
|
231
232
|
stageOverlayService.set('stageOptions', stageOptions);
|
|
232
233
|
|
|
233
|
-
const propsPanelRef = ref<InstanceType<typeof FormPanel> | null>(null);
|
|
234
|
-
|
|
235
234
|
provide('services', services);
|
|
236
235
|
|
|
237
236
|
provide('codeOptions', props.codeOptions);
|
|
@@ -239,11 +238,16 @@ provide('stageOptions', stageOptions);
|
|
|
239
238
|
/** 是否启用「属性配置表单校验」联动能力,供 PropsPanel / FormPanel 判断校验失败时是否仍更新节点并记录错误 */
|
|
240
239
|
provide(ENABLE_PROPS_FORM_VALIDATE, props.enablePropsFormValidate ?? false);
|
|
241
240
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
241
|
+
* 编辑器注入给整棵表单树的业务上下文(`services` / `stage`),属性面板、对比表单、
|
|
242
|
+
* 侧边栏里的嵌套 MForm 都通过 inject 自动继承。
|
|
243
|
+
*
|
|
244
|
+
* 业务方要追加自己的字段,在 `<MEditor>` 外层再 `provide(FORM_CONTEXT_KEY, computed(...))`
|
|
245
|
+
* 即可,配置回调统一通过 `mForm.xxx` 读取。
|
|
245
246
|
*/
|
|
246
|
-
provide(
|
|
247
|
+
provide(
|
|
248
|
+
FORM_CONTEXT_KEY,
|
|
249
|
+
useEditorFormContext(() => services),
|
|
250
|
+
);
|
|
247
251
|
|
|
248
252
|
// 用 computed 包一层再 provide,否则传下去的是 provide 那一刻的值快照,
|
|
249
253
|
// props.isLargeStageContainer 后续变化不会同步到子孙(如 @tmagic/design/ColorPicker)。
|
|
@@ -253,12 +257,6 @@ provide(
|
|
|
253
257
|
'isLargeStageContainer',
|
|
254
258
|
computed(() => props.isLargeStageContainer),
|
|
255
259
|
);
|
|
256
|
-
/**
|
|
257
|
-
* 提供 PropsPanel 主属性表单的 formState getter,供历史差异弹窗复用,
|
|
258
|
-
* 让 CompareForm 与 PropsPanel 的 filterFunction 上下文保持一致。
|
|
259
|
-
*/
|
|
260
|
-
provide('getPropsPanelFormState', () => propsPanelRef.value?.configForm?.formState);
|
|
261
|
-
|
|
262
260
|
/**
|
|
263
261
|
* 把历史记录面板的自定义扩展 tab 提供给深层的 HistoryListPanel(它挂在 NavMenu 中,
|
|
264
262
|
* 以 markRaw component 形式渲染,无法直接通过 props 透传)。业务方可借此在历史记录
|
|
@@ -279,11 +277,9 @@ provide(
|
|
|
279
277
|
);
|
|
280
278
|
|
|
281
279
|
const propsPanelMountedHandler = (e: InstanceType<typeof FormPanel>) => {
|
|
282
|
-
propsPanelRef.value = e;
|
|
283
280
|
emit('props-panel-mounted', e);
|
|
284
281
|
};
|
|
285
282
|
const propsPanelUnmountedHandler = () => {
|
|
286
|
-
propsPanelRef.value = null;
|
|
287
283
|
emit('props-panel-unmounted');
|
|
288
284
|
};
|
|
289
285
|
|
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
<script lang="ts" setup>
|
|
16
16
|
import { computed, useTemplateRef } from 'vue';
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
type ContainerChangeEventData,
|
|
20
|
+
defineFormItem,
|
|
21
|
+
type FormItemConfig,
|
|
22
|
+
type FormValue,
|
|
23
|
+
MForm,
|
|
24
|
+
} from '@tmagic/form';
|
|
19
25
|
|
|
20
26
|
import type { CodeParamStatement } from '@editor/type';
|
|
21
27
|
import { error } from '@editor/utils';
|
|
@@ -41,13 +47,13 @@ const emit = defineEmits(['change']);
|
|
|
41
47
|
const formRef = useTemplateRef<InstanceType<typeof MForm>>('form');
|
|
42
48
|
|
|
43
49
|
const getFormConfig = (items: FormItemConfig[] = []) => [
|
|
44
|
-
{
|
|
50
|
+
defineFormItem({
|
|
45
51
|
type: 'fieldset',
|
|
46
52
|
items,
|
|
47
53
|
legend: '参数',
|
|
48
|
-
|
|
54
|
+
labelPosition: 'top',
|
|
49
55
|
name: props.name,
|
|
50
|
-
},
|
|
56
|
+
}),
|
|
51
57
|
];
|
|
52
58
|
|
|
53
59
|
const codeParamsConfig = computed(() =>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
:is-compare="true"
|
|
11
11
|
:disabled="true"
|
|
12
12
|
:label-width="labelWidth"
|
|
13
|
-
:
|
|
13
|
+
:context="formContext"
|
|
14
14
|
:show-diff="showDiff"
|
|
15
15
|
:self-diff-field-types="selfDiffFieldTypes"
|
|
16
16
|
:size="size"
|
|
@@ -47,7 +47,7 @@ const props = withDefaults(
|
|
|
47
47
|
},
|
|
48
48
|
);
|
|
49
49
|
|
|
50
|
-
const { config, currentValues, wrapperStyle,
|
|
50
|
+
const { config, currentValues, wrapperStyle, formContext, loadConfig, formRef, normalizeCodeBlockValue } =
|
|
51
51
|
useCompareForm(props);
|
|
52
52
|
|
|
53
53
|
const lastValuesProcessed = computed<FormValue>(() => {
|
|
@@ -60,9 +60,8 @@ const lastValuesProcessed = computed<FormValue>(() => {
|
|
|
60
60
|
/**
|
|
61
61
|
* `code-select` 字段在历史数据中存在两种"语义为空"的形态:
|
|
62
62
|
* - 字符串 `''`(旧数据 / 用户从未配置过钩子);
|
|
63
|
-
* - `{ hookType: HookType.CODE, hookData: [] }
|
|
64
|
-
*
|
|
65
|
-
* `props.model[props.name] = { hookType: HookType.CODE, hookData: [] }`)。
|
|
63
|
+
* - `{ hookType: HookType.CODE, hookData: [] }`(`normalizeCodeSelectValue`
|
|
64
|
+
* 写入的默认结构)。
|
|
66
65
|
*
|
|
67
66
|
* 直接 `isEqual` 会把两者判为不等,从而在历史对比里对每个未配置过钩子的组件
|
|
68
67
|
* 都展示一份"差异",体验很糟糕。这里把它们视为相等,跳过对比。
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
:init-values="currentValues"
|
|
9
9
|
:disabled="disabled"
|
|
10
10
|
:label-width="labelWidth"
|
|
11
|
-
:
|
|
11
|
+
:context="formContext"
|
|
12
12
|
:size="size"
|
|
13
13
|
></MForm>
|
|
14
14
|
</div>
|
|
@@ -37,11 +37,10 @@ const props = withDefaults(
|
|
|
37
37
|
category: 'node',
|
|
38
38
|
labelWidth: '120px',
|
|
39
39
|
disabled: true,
|
|
40
|
-
// extendState 的默认值由 useCompareForm 内部兜底(props.extendState ?? ...),此处无需重复提供
|
|
41
40
|
},
|
|
42
41
|
);
|
|
43
42
|
|
|
44
|
-
const { config, currentValues, wrapperStyle,
|
|
43
|
+
const { config, currentValues, wrapperStyle, formContext, loadConfig, formRef } = useCompareForm(props);
|
|
45
44
|
|
|
46
45
|
defineExpose<{
|
|
47
46
|
form: ShallowRef<InstanceType<typeof MForm> | null>;
|
package/src/editorProps.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { InjectionKey } from 'vue';
|
|
2
2
|
|
|
3
3
|
import type { DataSourceSchema, EventOption, Id, MApp, MNode, MPage, MPageFragment } from '@tmagic/core';
|
|
4
|
-
import type { FormConfig
|
|
4
|
+
import type { FormConfig } from '@tmagic/form';
|
|
5
5
|
import StageCore, {
|
|
6
6
|
CONTAINER_HIGHLIGHT_CLASS_NAME,
|
|
7
7
|
ContainerHighlightType,
|
|
@@ -149,7 +149,6 @@ export interface EditorProps {
|
|
|
149
149
|
beforeDblclick?: (event: MouseEvent) => Promise<boolean | void> | boolean | void;
|
|
150
150
|
/** 组件树节点双击前的钩子函数,返回 false 则阻止默认的双击行为 */
|
|
151
151
|
beforeLayerNodeDblclick?: (event: MouseEvent, data: TreeNodeData) => Promise<boolean | void> | boolean | void;
|
|
152
|
-
extendFormState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
153
152
|
/** 历史记录面板的自定义扩展 tab,追加在内置的页面/数据源/代码块 tab 之后 */
|
|
154
153
|
historyListExtraTabs?: HistoryListExtraTab[];
|
|
155
154
|
/** 页面顺序拖拽配置参数 */
|
package/src/fields/Code.vue
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<MagicCodeEditor
|
|
3
|
-
v-if="!silentMode"
|
|
4
3
|
:height="config.height"
|
|
5
4
|
:type="diffMode ? 'diff' : undefined"
|
|
6
5
|
:init-values="diffMode ? (lastValues || {})[name] : model[name]"
|
|
@@ -18,9 +17,9 @@
|
|
|
18
17
|
</template>
|
|
19
18
|
|
|
20
19
|
<script lang="ts" setup>
|
|
21
|
-
import { computed
|
|
20
|
+
import { computed } from 'vue';
|
|
22
21
|
|
|
23
|
-
import { type CodeConfig, type FieldProps
|
|
22
|
+
import { type CodeConfig, type FieldProps } from '@tmagic/form';
|
|
24
23
|
|
|
25
24
|
import MagicCodeEditor from '@editor/layouts/CodeEditor.vue';
|
|
26
25
|
|
|
@@ -28,13 +27,6 @@ defineOptions({
|
|
|
28
27
|
name: 'MFieldsVsCode',
|
|
29
28
|
});
|
|
30
29
|
|
|
31
|
-
/**
|
|
32
|
-
* 静默模式(submitForm/validateForm 隐藏挂载)下跳过 monaco 渲染:
|
|
33
|
-
* 校验由 FormItem 针对 model 中的值完成,与编辑器实例无关;本组件挂载无值副作用
|
|
34
|
-
* (save 仅由用户操作/编辑器内容变更触发),跳过可省去 monaco worker/model 的无谓实例化。
|
|
35
|
-
*/
|
|
36
|
-
const silentMode = inject(FORM_SILENT_MODE_KEY, false);
|
|
37
|
-
|
|
38
30
|
const emit = defineEmits<{
|
|
39
31
|
change: [value: string | any];
|
|
40
32
|
}>();
|
|
@@ -1,36 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-fields-code-select" :class="config.className">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
>添加{{ config.text }}</TMagicButton
|
|
18
|
-
>
|
|
19
|
-
</TMagicCard>
|
|
3
|
+
<MContainer
|
|
4
|
+
:config="codeConfig"
|
|
5
|
+
:size="size"
|
|
6
|
+
class="code-select-content"
|
|
7
|
+
:prop="prop"
|
|
8
|
+
:disabled="disabled"
|
|
9
|
+
:is-compare="isCompareMode"
|
|
10
|
+
:last-values="lastValues?.[name]"
|
|
11
|
+
:model="model[name]"
|
|
12
|
+
:label-position="config.labelPosition"
|
|
13
|
+
:label-width="config.labelWidth"
|
|
14
|
+
@change="changeHandler"
|
|
15
|
+
>
|
|
16
|
+
</MContainer>
|
|
20
17
|
</div>
|
|
21
18
|
</template>
|
|
22
19
|
|
|
23
20
|
<script lang="ts" setup>
|
|
24
21
|
import { computed, watch } from 'vue';
|
|
25
|
-
import { Plus } from '@element-plus/icons-vue';
|
|
26
|
-
import { isEmpty } from 'lodash-es';
|
|
27
22
|
|
|
28
|
-
import {
|
|
29
|
-
import { TMagicButton, TMagicCard } from '@tmagic/design';
|
|
30
|
-
import type { CodeSelectConfig, ContainerChangeEventData, FieldProps, GroupListConfig } from '@tmagic/form';
|
|
23
|
+
import type { CodeSelectConfig, ContainerChangeEventData, FieldProps } from '@tmagic/form';
|
|
31
24
|
import { MContainer } from '@tmagic/form';
|
|
32
25
|
|
|
33
|
-
import {
|
|
26
|
+
import { createCodeSelectConfig, normalizeCodeSelectValue } from '@editor/fields/configs/codeSelect';
|
|
34
27
|
|
|
35
28
|
defineOptions({
|
|
36
29
|
name: 'MFieldsCodeSelect',
|
|
@@ -40,8 +33,6 @@ const emit = defineEmits<{
|
|
|
40
33
|
change: [v: any, eventData: ContainerChangeEventData];
|
|
41
34
|
}>();
|
|
42
35
|
|
|
43
|
-
const { dataSourceService, codeBlockService } = useServices();
|
|
44
|
-
|
|
45
36
|
const props = withDefaults(defineProps<FieldProps<CodeSelectConfig>>(), {});
|
|
46
37
|
|
|
47
38
|
/**
|
|
@@ -58,101 +49,14 @@ const props = withDefaults(defineProps<FieldProps<CodeSelectConfig>>(), {});
|
|
|
58
49
|
* 仅当存在历史值时才启用对比,避免 lastValues 缺失时退化为「全部新增」的空对比。
|
|
59
50
|
*/
|
|
60
51
|
const isCompareMode = computed(() => Boolean(props.isCompare && props.lastValues));
|
|
61
|
-
const newHandler = () => {
|
|
62
|
-
const defaultCode = {
|
|
63
|
-
codeType: HookCodeType.CODE,
|
|
64
|
-
codeId: '',
|
|
65
|
-
};
|
|
66
|
-
const name = props.config.name || '';
|
|
67
|
-
const hookData = props.model[name]?.hookData || [];
|
|
68
|
-
emit('change', defaultCode, {
|
|
69
|
-
modifyKey: `hookData.${hookData.length}`,
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
const codeConfig = computed<GroupListConfig>(() => ({
|
|
73
|
-
type: 'group-list',
|
|
74
|
-
name: 'hookData',
|
|
75
|
-
enableToggleMode: false,
|
|
76
|
-
expandAll: true,
|
|
77
|
-
addable: () => false,
|
|
78
|
-
title: (mForm, { model, index }: any) => {
|
|
79
|
-
if (model.codeType === HookCodeType.DATA_SOURCE_METHOD) {
|
|
80
|
-
if (Array.isArray(model.codeId)) {
|
|
81
|
-
if (model.codeId.length < 2) {
|
|
82
|
-
return index;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const ds = dataSourceService.getDataSourceById(model.codeId[0]);
|
|
86
|
-
return `${ds?.title} / ${model.codeId[1]}`;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return Array.isArray(model.codeId) ? model.codeId.join('/') : index;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const codeContent = codeBlockService.getCodeContentById(model.codeId);
|
|
93
52
|
|
|
94
|
-
|
|
95
|
-
return codeContent.name;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return model.codeId || index;
|
|
99
|
-
},
|
|
100
|
-
titlePrefix: props.config.name === undefined ? undefined : String(props.config.name),
|
|
101
|
-
items: [
|
|
102
|
-
{
|
|
103
|
-
text: '代码类型',
|
|
104
|
-
type: 'select',
|
|
105
|
-
name: 'codeType',
|
|
106
|
-
labelPosition: 'right',
|
|
107
|
-
rules: [{ typeMatch: true, trigger: 'change' }],
|
|
108
|
-
options: [
|
|
109
|
-
{ value: HookCodeType.CODE, text: '代码块' },
|
|
110
|
-
{ value: HookCodeType.DATA_SOURCE_METHOD, text: '数据源方法' },
|
|
111
|
-
],
|
|
112
|
-
defaultValue: HookCodeType.CODE,
|
|
113
|
-
onChange: (_mForm, v: HookCodeType, { setModel }) => {
|
|
114
|
-
if (v === HookCodeType.DATA_SOURCE_METHOD) {
|
|
115
|
-
setModel('codeId', []);
|
|
116
|
-
} else {
|
|
117
|
-
setModel('codeId', '');
|
|
118
|
-
}
|
|
119
|
-
return v;
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
type: 'code-select-col',
|
|
124
|
-
name: 'codeId',
|
|
125
|
-
text: '代码块',
|
|
126
|
-
rules: [{ typeMatch: true, trigger: 'change' }],
|
|
127
|
-
|
|
128
|
-
display: (_mForm, { model }) => model.codeType !== HookCodeType.DATA_SOURCE_METHOD,
|
|
129
|
-
notEditable: () => !codeBlockService.getEditStatus(),
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
type: 'data-source-method-select',
|
|
133
|
-
name: 'codeId',
|
|
134
|
-
text: '数据源字段',
|
|
135
|
-
rules: [{ typeMatch: true, trigger: 'change' }],
|
|
136
|
-
display: (_mForm, { model }) => model.codeType === HookCodeType.DATA_SOURCE_METHOD,
|
|
137
|
-
notEditable: () => !dataSourceService.get('editable'),
|
|
138
|
-
},
|
|
139
|
-
],
|
|
140
|
-
}));
|
|
53
|
+
const codeConfig = computed(() => createCodeSelectConfig(props.config));
|
|
141
54
|
|
|
55
|
+
// 挂载时的归一化由 applyMountValueEffects → code-select 的 effect 完成,这里只兜运行期被置空
|
|
142
56
|
watch(
|
|
143
57
|
() => props.model[props.name],
|
|
144
|
-
(
|
|
145
|
-
|
|
146
|
-
if (isEmpty(value)) {
|
|
147
|
-
// 空值或者空数组
|
|
148
|
-
props.model[props.name] = {
|
|
149
|
-
hookType: HookType.CODE,
|
|
150
|
-
hookData: [],
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
immediate: true,
|
|
58
|
+
() => {
|
|
59
|
+
normalizeCodeSelectValue(props.model, props.name);
|
|
156
60
|
},
|
|
157
61
|
);
|
|
158
62
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
:prop="prop"
|
|
16
16
|
></MFormContainer>
|
|
17
17
|
<MSelect
|
|
18
|
-
v-else
|
|
18
|
+
v-else
|
|
19
19
|
class="select"
|
|
20
20
|
:config="selectConfig"
|
|
21
21
|
:name="name"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
<!-- 查看/编辑按钮:对比模式为只读,不展示 -->
|
|
29
29
|
<TMagicButton
|
|
30
|
-
v-if="!isCompareMode &&
|
|
30
|
+
v-if="!isCompareMode && model[name] && hasCodeBlockSidePanel"
|
|
31
31
|
class="m-fields-select-action-button"
|
|
32
32
|
:size="size"
|
|
33
33
|
@click="editCode(model[name])"
|
|
@@ -65,7 +65,6 @@ import {
|
|
|
65
65
|
createValues,
|
|
66
66
|
type FieldProps,
|
|
67
67
|
filterFunction,
|
|
68
|
-
FORM_SILENT_MODE_KEY,
|
|
69
68
|
type FormItemConfig,
|
|
70
69
|
type FormState,
|
|
71
70
|
MContainer as MFormContainer,
|
|
@@ -84,9 +83,8 @@ defineOptions({
|
|
|
84
83
|
});
|
|
85
84
|
|
|
86
85
|
const mForm = inject<FormState | undefined>('mForm');
|
|
87
|
-
const silentMode = inject(FORM_SILENT_MODE_KEY, false);
|
|
88
86
|
const { codeBlockService, uiService } = useServices();
|
|
89
|
-
const eventBus = inject<EventBus>('eventBus');
|
|
87
|
+
const eventBus = inject<EventBus | null>('eventBus', null);
|
|
90
88
|
const emit = defineEmits<{
|
|
91
89
|
change: [v: any, eventData: ContainerChangeEventData];
|
|
92
90
|
}>();
|
|
@@ -31,6 +31,7 @@ import { computed } from 'vue';
|
|
|
31
31
|
|
|
32
32
|
import { getDesignConfig, TMagicSelect } from '@tmagic/design';
|
|
33
33
|
import type { CondOpSelectConfig, FieldProps } from '@tmagic/form';
|
|
34
|
+
import { removeDataSourceFieldPrefix } from '@tmagic/utils';
|
|
34
35
|
|
|
35
36
|
import { useServices } from '@editor/hooks/use-services';
|
|
36
37
|
import { getCondOpOptionsByFieldType, getFieldType } from '@editor/utils';
|
|
@@ -50,8 +51,8 @@ const props = defineProps<FieldProps<CondOpSelectConfig>>();
|
|
|
50
51
|
const optionComponent = getDesignConfig('components')?.option;
|
|
51
52
|
|
|
52
53
|
const options = computed(() => {
|
|
53
|
-
const [id, ...fieldNames] = [...(props.config.parentFields || []), ...props.model.field];
|
|
54
|
-
const ds = dataSourceService.getDataSourceById(id);
|
|
54
|
+
const [id, ...fieldNames] = [...(props.config.parentFields || []), ...(props.model.field || [])];
|
|
55
|
+
const ds = id ? dataSourceService.getDataSourceById(removeDataSourceFieldPrefix(id)) : undefined;
|
|
55
56
|
const type = getFieldType(ds, fieldNames);
|
|
56
57
|
return getCondOpOptionsByFieldType(type);
|
|
57
58
|
});
|
|
@@ -124,7 +124,7 @@ const optionComponent = getDesignConfig('components')?.option;
|
|
|
124
124
|
|
|
125
125
|
const { dataSourceService, uiService } = useServices();
|
|
126
126
|
const mForm = inject<FormState | undefined>('mForm');
|
|
127
|
-
const eventBus = inject<EventBus>('eventBus');
|
|
127
|
+
const eventBus = inject<EventBus | null>('eventBus', null);
|
|
128
128
|
|
|
129
129
|
const allDataSources = computed(() => dataSourceService.get('dataSources') || []);
|
|
130
130
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
}"
|
|
7
7
|
>
|
|
8
8
|
<FieldSelect
|
|
9
|
-
v-if="isSelectValid
|
|
9
|
+
v-if="isSelectValid"
|
|
10
10
|
:model-value="model[name]"
|
|
11
11
|
:disabled="disabled"
|
|
12
12
|
:size="size"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
></FieldSelect>
|
|
19
19
|
|
|
20
20
|
<component
|
|
21
|
-
v-else
|
|
21
|
+
v-else
|
|
22
22
|
:is="tagName"
|
|
23
23
|
:config="config.fieldConfig"
|
|
24
24
|
:model="model"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
></component>
|
|
34
34
|
|
|
35
35
|
<TMagicTooltip
|
|
36
|
-
v-if="
|
|
36
|
+
v-if="config.fieldConfig && !disabledDataSource && !mForm?.isCompare"
|
|
37
37
|
:disabled="showDataSourceFieldSelect"
|
|
38
38
|
content="选择数据源"
|
|
39
39
|
>
|
|
@@ -57,7 +57,6 @@ import {
|
|
|
57
57
|
type ContainerChangeEventData,
|
|
58
58
|
type DataSourceFieldSelectConfig,
|
|
59
59
|
type FieldProps,
|
|
60
|
-
FORM_SILENT_MODE_KEY,
|
|
61
60
|
type FormState,
|
|
62
61
|
getFormField,
|
|
63
62
|
} from '@tmagic/form';
|
|
@@ -105,7 +104,6 @@ watch(
|
|
|
105
104
|
|
|
106
105
|
const { dataSourceService, propsService } = useServices();
|
|
107
106
|
const mForm = inject<FormState | undefined>('mForm');
|
|
108
|
-
const silentMode = inject(FORM_SILENT_MODE_KEY, false);
|
|
109
107
|
|
|
110
108
|
const dataSources = computed(() => dataSourceService.get('dataSources') || []);
|
|
111
109
|
const disabledDataSource = computed(() => propsService.getDisabledDataSource());
|
|
@@ -143,7 +141,10 @@ const checkStrictly = computed(() => {
|
|
|
143
141
|
if (typeof props.config.checkStrictly !== 'function') {
|
|
144
142
|
value = props.config.checkStrictly;
|
|
145
143
|
} else {
|
|
146
|
-
const
|
|
144
|
+
const fieldValue = props.model[props.name];
|
|
145
|
+
// 指定了 dataSourceId 时取值里只有字段名,数据源 id 只能取自 config
|
|
146
|
+
const rawDsId = props.config.dataSourceId ?? (Array.isArray(fieldValue) ? fieldValue[0] : fieldValue);
|
|
147
|
+
const dsId = removeDataSourceFieldPrefix(`${rawDsId}`);
|
|
147
148
|
const dataSource = dataSources.value.find((ds) => ds.id === dsId);
|
|
148
149
|
|
|
149
150
|
value = props.config.checkStrictly(mForm, {
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
10
|
<FloatingBox
|
|
11
|
-
v-if="!silentMode"
|
|
12
11
|
:body-style="{ padding: '0 16px' }"
|
|
13
12
|
v-model:visible="addDialogVisible"
|
|
14
13
|
v-model:width="width"
|
|
@@ -31,7 +30,6 @@
|
|
|
31
30
|
</FloatingBox>
|
|
32
31
|
|
|
33
32
|
<FloatingBox
|
|
34
|
-
v-if="!silentMode"
|
|
35
33
|
:body-style="{ padding: '0 16px' }"
|
|
36
34
|
v-model:visible="addFromJsonDialogVisible"
|
|
37
35
|
v-model:width="width"
|
|
@@ -62,7 +60,6 @@ import {
|
|
|
62
60
|
type ContainerChangeEventData,
|
|
63
61
|
type DataSourceFieldsConfig,
|
|
64
62
|
type FieldProps,
|
|
65
|
-
FORM_SILENT_MODE_KEY,
|
|
66
63
|
type FormConfig,
|
|
67
64
|
type FormState,
|
|
68
65
|
MFormBox,
|
|
@@ -92,8 +89,6 @@ const emit = defineEmits<{
|
|
|
92
89
|
|
|
93
90
|
const { uiService } = useServices();
|
|
94
91
|
const mForm = inject<FormState | undefined>('mForm');
|
|
95
|
-
const silentMode = inject(FORM_SILENT_MODE_KEY, false);
|
|
96
|
-
|
|
97
92
|
/** 对比模式下隐藏新增/编辑/删除等操作按钮,仅保留只读展示。 */
|
|
98
93
|
const isCompare = computed(() => Boolean(mForm?.isCompare));
|
|
99
94
|
|
|
@@ -383,8 +378,6 @@ provide(
|
|
|
383
378
|
);
|
|
384
379
|
|
|
385
380
|
onMounted(() => {
|
|
386
|
-
if (silentMode) return;
|
|
387
|
-
|
|
388
381
|
const path = editingFieldPath.value;
|
|
389
382
|
if (!path.length) return;
|
|
390
383
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
<div class="m-fields-data-source-method-select">
|
|
3
3
|
<div class="data-source-method-select-container">
|
|
4
4
|
<MCascader
|
|
5
|
-
v-if="!silentMode"
|
|
6
5
|
class="select"
|
|
7
6
|
:config="cascaderConfig"
|
|
8
7
|
:model="model"
|
|
@@ -14,7 +13,7 @@
|
|
|
14
13
|
></MCascader>
|
|
15
14
|
|
|
16
15
|
<TMagicTooltip
|
|
17
|
-
v-if="
|
|
16
|
+
v-if="model[name] && isCustomMethod && dataSourceSidePanel && !isCompare"
|
|
18
17
|
:content="notEditable ? '查看' : '编辑'"
|
|
19
18
|
>
|
|
20
19
|
<TMagicButton class="m-fields-select-action-button" :size="size" @click="editCodeHandler">
|
|
@@ -49,7 +48,6 @@ import {
|
|
|
49
48
|
type DataSourceMethodSelectConfig,
|
|
50
49
|
type FieldProps,
|
|
51
50
|
filterFunction,
|
|
52
|
-
FORM_SILENT_MODE_KEY,
|
|
53
51
|
type FormItemConfig,
|
|
54
52
|
type FormState,
|
|
55
53
|
MCascader,
|
|
@@ -69,8 +67,7 @@ defineOptions({
|
|
|
69
67
|
|
|
70
68
|
const { dataSourceService, uiService } = useServices();
|
|
71
69
|
const mForm = inject<FormState | undefined>('mForm');
|
|
72
|
-
const
|
|
73
|
-
const eventBus = inject<EventBus>('eventBus');
|
|
70
|
+
const eventBus = inject<EventBus | null>('eventBus', null);
|
|
74
71
|
|
|
75
72
|
const emit = defineEmits(['change']);
|
|
76
73
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<CodeBlockEditor
|
|
12
|
-
v-if="codeConfig
|
|
12
|
+
v-if="codeConfig"
|
|
13
13
|
ref="codeBlockEditor"
|
|
14
14
|
:disabled="disabled"
|
|
15
15
|
:content="codeConfig"
|
|
@@ -30,7 +30,6 @@ import {
|
|
|
30
30
|
type ContainerChangeEventData,
|
|
31
31
|
type DataSourceMethodsConfig,
|
|
32
32
|
type FieldProps,
|
|
33
|
-
FORM_SILENT_MODE_KEY,
|
|
34
33
|
type FormState,
|
|
35
34
|
} from '@tmagic/form';
|
|
36
35
|
import { type ColumnConfig, MagicTable } from '@tmagic/table';
|
|
@@ -49,8 +48,6 @@ const props = withDefaults(defineProps<FieldProps<DataSourceMethodsConfig>>(), {
|
|
|
49
48
|
const emit = defineEmits(['change']);
|
|
50
49
|
|
|
51
50
|
const mForm = inject<FormState | undefined>('mForm');
|
|
52
|
-
const silentMode = inject(FORM_SILENT_MODE_KEY, false);
|
|
53
|
-
|
|
54
51
|
/** 对比模式下隐藏新增/编辑/删除等操作按钮,仅保留只读展示。 */
|
|
55
52
|
const isCompare = computed(() => Boolean(mForm?.isCompare));
|
|
56
53
|
|
|
@@ -177,8 +174,6 @@ const editingMethodName = inject<ComputedRef<string | undefined>>(
|
|
|
177
174
|
);
|
|
178
175
|
|
|
179
176
|
onMounted(() => {
|
|
180
|
-
if (silentMode) return;
|
|
181
|
-
|
|
182
177
|
const methodName = editingMethodName.value;
|
|
183
178
|
if (!methodName) return;
|
|
184
179
|
|