@tmagic/editor 1.8.0-beta.26 → 1.8.0-beta.28
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/fields/configs/stickyAddButton.js +3 -2
- package/dist/es/hooks/use-form-context.js +18 -8
- package/dist/es/initService.js +15 -2
- package/dist/es/layouts/history-list/useHistoryRevert.js +1 -1
- package/dist/es/services/events.js +2 -2
- package/dist/es/style.css +40 -14
- package/dist/es/utils/code-block.js +14 -7
- package/dist/style.css +40 -14
- package/dist/themes/magic-admin.css +40 -14
- package/dist/tmagic-editor-headless.umd.cjs +5 -4
- package/dist/tmagic-editor.umd.cjs +47 -21
- package/package.json +7 -7
- package/src/fields/configs/stickyAddButton.ts +3 -2
- package/src/hooks/use-form-context.ts +22 -6
- package/src/initService.ts +25 -2
- package/src/layouts/history-list/useHistoryRevert.ts +1 -4
- package/src/services/events.ts +5 -4
- package/src/type.ts +6 -0
- package/src/utils/code-block.ts +1 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
//#region packages/editor/src/fields/configs/stickyAddButton.ts
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* 属性面板列表字段共用的吸底全宽「添加」按钮与吸顶标题,展开到 group-list 配置上。
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* 吸底按钮会盖住列表底部,吸顶标题会盖住列表顶部,新增的项必须同时滚进视口才看得见。
|
|
6
6
|
*/
|
|
7
7
|
var stickyAddButton = (text) => ({
|
|
8
8
|
scrollLastItemIntoView: true,
|
|
9
|
+
header: { sticky: true },
|
|
9
10
|
addButtonConfig: {
|
|
10
11
|
sticky: true,
|
|
11
12
|
text,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FORM_CONTEXT_KEY, mergeFormContexts } from "@tmagic/form";
|
|
2
|
+
import { computed, inject, unref } from "vue";
|
|
2
3
|
//#region packages/editor/src/hooks/use-form-context.ts
|
|
3
4
|
/**
|
|
4
5
|
* 编辑器注入给表单的业务上下文:`services` 与当前画布 `stage`。
|
|
@@ -6,14 +7,23 @@ import { computed } from "vue";
|
|
|
6
7
|
* 由 `Editor.vue`(provide `FORM_CONTEXT_KEY`)、`FormPanel.vue` 与 `useCompareForm`
|
|
7
8
|
* 共用。`stage` 走 computed 而非快照,保证切换画布后配置回调读到的是最新实例。
|
|
8
9
|
*
|
|
10
|
+
* 宿主可能在 `<MEditor>` 外层 provide 了自己的业务字段,这里必须把那一层合并进来:
|
|
11
|
+
* 否则编辑器再 provide 一次会把宿主整层遮蔽掉,属性面板、对比表单里的配置回调就
|
|
12
|
+
* 读不到宿主字段了。`services` / `stage` 由编辑器兜底,优先级高于宿主同名字段。
|
|
13
|
+
*
|
|
9
14
|
* 字段类型见 `@editor/type` 里对 `@tmagic/form-schema` 的 `FormContext` 模块增强。
|
|
10
15
|
*/
|
|
11
|
-
var useEditorFormContext = (getServices) =>
|
|
12
|
-
const
|
|
13
|
-
return {
|
|
14
|
-
services
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
var useEditorFormContext = (getServices) => {
|
|
17
|
+
const hostContext = inject(FORM_CONTEXT_KEY, void 0);
|
|
18
|
+
return computed(() => {
|
|
19
|
+
const services = getServices();
|
|
20
|
+
const host = unref(hostContext);
|
|
21
|
+
if (host && host.services === services) return host;
|
|
22
|
+
return mergeFormContexts(host, {
|
|
23
|
+
services,
|
|
24
|
+
stage: services?.editorService.get("stage")
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
};
|
|
18
28
|
//#endregion
|
|
19
29
|
export { useEditorFormContext };
|
package/dist/es/initService.js
CHANGED
|
@@ -73,6 +73,7 @@ var initServiceState = (props, { editorService, historyService, componentListSer
|
|
|
73
73
|
uiService.resetState();
|
|
74
74
|
componentListService.resetState();
|
|
75
75
|
codeBlockService.resetState();
|
|
76
|
+
eventsService.resetState();
|
|
76
77
|
keybindingService.reset();
|
|
77
78
|
depService.reset();
|
|
78
79
|
});
|
|
@@ -167,10 +168,20 @@ var initServiceEvents = (props, emit, { editorService, codeBlockService, dataSou
|
|
|
167
168
|
});
|
|
168
169
|
});
|
|
169
170
|
};
|
|
171
|
+
/**
|
|
172
|
+
* root 是否已经不是编辑器当前的 root。
|
|
173
|
+
*
|
|
174
|
+
* `editorService.set('root', v)` 是同步赋值后再派发 `root-change`,因此派发那一刻 `v` 一定
|
|
175
|
+
* 就是当前 root;但处理 `root-change` 要等 stage / runtime / 依赖收集等异步过程,期间 root
|
|
176
|
+
* 可能被新的一次整体替换(外部重设 DSL、更新 root 节点、源码保存等)顶掉,此时手上的 `v`
|
|
177
|
+
* 已是过期快照,继续用它刷画布或回写给外部都会与新 root 互相覆盖。
|
|
178
|
+
*/
|
|
179
|
+
const isStaleRoot = (value) => toRaw(editorService.get("root")) !== toRaw(value);
|
|
170
180
|
const updateStageDsl = async (value) => {
|
|
171
181
|
const stage = await getStage();
|
|
172
182
|
const runtime = await stage.renderer?.getRuntime();
|
|
173
183
|
const app = await getTMagicApp();
|
|
184
|
+
if (isStaleRoot(value)) return;
|
|
174
185
|
if (!app?.dataSourceManager) runtime?.updateRootConfig?.(cloneDeep$1(toRaw(value)));
|
|
175
186
|
const page = editorService.get("page");
|
|
176
187
|
const node = editorService.get("node");
|
|
@@ -181,6 +192,7 @@ var initServiceEvents = (props, emit, { editorService, codeBlockService, dataSou
|
|
|
181
192
|
if (value) {
|
|
182
193
|
depService.clearIdleTasks();
|
|
183
194
|
await (typeof Worker === "undefined" ? collectIdle(value.items, true) : depService.collectByWorker(value));
|
|
195
|
+
if (isStaleRoot(value)) return;
|
|
184
196
|
const dsl = cloneDeep$1(toRaw(value));
|
|
185
197
|
if (dsl.dataSources && dsl.dataSourceDeps && app?.dataSourceManager) for (const node of getNodes(getDepNodeIds(dsl.dataSourceDeps), dsl.items)) updateNode(app.dataSourceManager.compiledNode(node), dsl);
|
|
186
198
|
runtime?.updateRootConfig?.(dsl);
|
|
@@ -191,7 +203,7 @@ var initServiceEvents = (props, emit, { editorService, codeBlockService, dataSou
|
|
|
191
203
|
depService.addTarget(createDataSourceMethodTarget(ds, reactive({})));
|
|
192
204
|
depService.addTarget(createDataSourceCondTarget(ds, reactive({})));
|
|
193
205
|
};
|
|
194
|
-
const rootChangeHandler = (value
|
|
206
|
+
const rootChangeHandler = (value) => {
|
|
195
207
|
if (!value) return;
|
|
196
208
|
value.codeBlocks = value.codeBlocks || {};
|
|
197
209
|
value.dataSources = value.dataSources || [];
|
|
@@ -217,7 +229,8 @@ var initServiceEvents = (props, emit, { editorService, codeBlockService, dataSou
|
|
|
217
229
|
editorService.set("parent", null);
|
|
218
230
|
editorService.set("page", null);
|
|
219
231
|
}
|
|
220
|
-
if (
|
|
232
|
+
if (isStaleRoot(value)) return;
|
|
233
|
+
if (toRaw(props.modelValue) !== toRaw(value)) emit("update:modelValue", value);
|
|
221
234
|
})();
|
|
222
235
|
};
|
|
223
236
|
const nodeAddHandler = (nodes) => {
|
|
@@ -135,7 +135,7 @@ var useHistoryRevert = (options = {}, services) => {
|
|
|
135
135
|
* 不弹差异弹窗,改用一个普通确认框替代「确定回滚」按钮,避免点击后无任何提示直接执行。
|
|
136
136
|
* 用户取消时返回 false,调用方据此中止回滚。
|
|
137
137
|
*/
|
|
138
|
-
const confirmRevert = () => confirmHistoryAction("
|
|
138
|
+
const confirmRevert = () => confirmHistoryAction("确定回滚该步骤吗?");
|
|
139
139
|
/**
|
|
140
140
|
* 「回滚」统一确认入口:可差异对比的步骤动态挂载 HistoryDiffDialog 走差异确认弹窗,
|
|
141
141
|
* 无法对比的步骤(add / remove / 多节点更新)回退到普通二次确认框。
|
|
@@ -47,8 +47,8 @@ var Events = class extends BaseService {
|
|
|
47
47
|
return cloneDeep(methodMap[toLine(type)]) || [];
|
|
48
48
|
}
|
|
49
49
|
resetState() {
|
|
50
|
-
eventMap
|
|
51
|
-
methodMap
|
|
50
|
+
Object.keys(eventMap).forEach((type) => delete eventMap[type]);
|
|
51
|
+
Object.keys(methodMap).forEach((type) => delete methodMap[type]);
|
|
52
52
|
}
|
|
53
53
|
destroy() {
|
|
54
54
|
this.resetState();
|
package/dist/es/style.css
CHANGED
|
@@ -478,18 +478,48 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
478
478
|
flex-shrink: 0;
|
|
479
479
|
gap: 8px;
|
|
480
480
|
}
|
|
481
|
-
.m-fields-group-list .m-fields-group-list-item
|
|
482
|
-
|
|
481
|
+
.m-fields-group-list > .m-fields-group-list-item {
|
|
482
|
+
--m-group-list-item-footer-bottom: var(
|
|
483
|
+
--m-group-list-nested-footer-bottom,
|
|
484
|
+
0px
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
.m-fields-group-list.is-footer-sticky > .m-fields-group-list-item {
|
|
488
|
+
--m-group-list-item-footer-bottom: calc(
|
|
489
|
+
var(--m-group-list-nested-footer-bottom, 0px) +
|
|
490
|
+
var(--m-group-list-footer-height)
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list {
|
|
494
|
+
--m-group-list-nested-footer-bottom: var(
|
|
495
|
+
--m-group-list-item-footer-bottom,
|
|
496
|
+
0px
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
.m-fields-group-list.is-header-sticky {
|
|
500
|
+
--m-group-list-nested-sticky-top: var(--m-group-list-child-list-sticky-top);
|
|
501
|
+
--m-group-list-nested-header-z: var(--m-group-list-child-list-header-z);
|
|
502
|
+
}
|
|
503
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item {
|
|
504
|
+
--m-group-list-item-sticky-top: var(
|
|
505
|
+
--m-group-list-nested-sticky-top,
|
|
506
|
+
var(--m-group-list-header-sticky-top, 0px)
|
|
507
|
+
);
|
|
508
|
+
--m-group-list-item-header-z: var(--m-group-list-nested-header-z, 7);
|
|
509
|
+
--m-group-list-child-list-sticky-top: calc(
|
|
510
|
+
var(--m-group-list-item-sticky-top) + var(--m-group-list-header-height)
|
|
511
|
+
);
|
|
512
|
+
--m-group-list-child-list-header-z: calc(
|
|
513
|
+
var(--m-group-list-item-header-z) - 1
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .el-card__header,
|
|
517
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .t-card__header {
|
|
483
518
|
position: sticky;
|
|
484
|
-
top: var(--m-group-list-
|
|
485
|
-
z-index:
|
|
519
|
+
top: var(--m-group-list-item-sticky-top);
|
|
520
|
+
z-index: var(--m-group-list-item-header-z);
|
|
486
521
|
background-color: var(--m-group-list-header-bg, #fff);
|
|
487
522
|
}
|
|
488
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .el-card__header,
|
|
489
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .t-card__header {
|
|
490
|
-
top: calc(var(--m-group-list-header-sticky-top, 0px) + var(--m-group-list-header-height));
|
|
491
|
-
z-index: 6;
|
|
492
|
-
}
|
|
493
523
|
.m-fields-group-list .el-table__empty-block {
|
|
494
524
|
width: 100%;
|
|
495
525
|
min-height: 0;
|
|
@@ -507,7 +537,7 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
507
537
|
}
|
|
508
538
|
.m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
|
|
509
539
|
position: sticky;
|
|
510
|
-
bottom:
|
|
540
|
+
bottom: var(--m-group-list-nested-footer-bottom, 0px);
|
|
511
541
|
z-index: 7;
|
|
512
542
|
margin-bottom: 0;
|
|
513
543
|
padding: var(--m-group-list-footer-padding-top) 0 var(--m-group-list-footer-padding-bottom);
|
|
@@ -521,10 +551,6 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
521
551
|
width: 100%;
|
|
522
552
|
height: var(--m-group-list-footer-button-height);
|
|
523
553
|
}
|
|
524
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
|
|
525
|
-
bottom: var(--m-group-list-footer-height);
|
|
526
|
-
z-index: 7;
|
|
527
|
-
}
|
|
528
554
|
|
|
529
555
|
/** 最外层的groupList需要每个item需要增加空白区域界限时,增加outer-gorup_list可以实现 */
|
|
530
556
|
.m-container-group-list.outer-gorup_list > .m-fields-group-list > .m-fields-group-list-item {
|
|
@@ -55,13 +55,20 @@ var getCodeBlockFormConfig = (options = {}) => {
|
|
|
55
55
|
name: "timing",
|
|
56
56
|
type: "select",
|
|
57
57
|
options: () => {
|
|
58
|
-
const list = [
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
const list = [
|
|
59
|
+
{
|
|
60
|
+
text: "初始化前",
|
|
61
|
+
value: "beforeInit"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
text: "初始化后",
|
|
65
|
+
value: "afterInit"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
text: "页面渲染后",
|
|
69
|
+
value: "mounted"
|
|
70
|
+
}
|
|
71
|
+
];
|
|
65
72
|
if (dataSourceType?.() !== "base") {
|
|
66
73
|
list.push({
|
|
67
74
|
text: "请求前",
|
package/dist/style.css
CHANGED
|
@@ -478,18 +478,48 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
478
478
|
flex-shrink: 0;
|
|
479
479
|
gap: 8px;
|
|
480
480
|
}
|
|
481
|
-
.m-fields-group-list .m-fields-group-list-item
|
|
482
|
-
|
|
481
|
+
.m-fields-group-list > .m-fields-group-list-item {
|
|
482
|
+
--m-group-list-item-footer-bottom: var(
|
|
483
|
+
--m-group-list-nested-footer-bottom,
|
|
484
|
+
0px
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
.m-fields-group-list.is-footer-sticky > .m-fields-group-list-item {
|
|
488
|
+
--m-group-list-item-footer-bottom: calc(
|
|
489
|
+
var(--m-group-list-nested-footer-bottom, 0px) +
|
|
490
|
+
var(--m-group-list-footer-height)
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list {
|
|
494
|
+
--m-group-list-nested-footer-bottom: var(
|
|
495
|
+
--m-group-list-item-footer-bottom,
|
|
496
|
+
0px
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
.m-fields-group-list.is-header-sticky {
|
|
500
|
+
--m-group-list-nested-sticky-top: var(--m-group-list-child-list-sticky-top);
|
|
501
|
+
--m-group-list-nested-header-z: var(--m-group-list-child-list-header-z);
|
|
502
|
+
}
|
|
503
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item {
|
|
504
|
+
--m-group-list-item-sticky-top: var(
|
|
505
|
+
--m-group-list-nested-sticky-top,
|
|
506
|
+
var(--m-group-list-header-sticky-top, 0px)
|
|
507
|
+
);
|
|
508
|
+
--m-group-list-item-header-z: var(--m-group-list-nested-header-z, 7);
|
|
509
|
+
--m-group-list-child-list-sticky-top: calc(
|
|
510
|
+
var(--m-group-list-item-sticky-top) + var(--m-group-list-header-height)
|
|
511
|
+
);
|
|
512
|
+
--m-group-list-child-list-header-z: calc(
|
|
513
|
+
var(--m-group-list-item-header-z) - 1
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .el-card__header,
|
|
517
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .t-card__header {
|
|
483
518
|
position: sticky;
|
|
484
|
-
top: var(--m-group-list-
|
|
485
|
-
z-index:
|
|
519
|
+
top: var(--m-group-list-item-sticky-top);
|
|
520
|
+
z-index: var(--m-group-list-item-header-z);
|
|
486
521
|
background-color: var(--m-group-list-header-bg, #fff);
|
|
487
522
|
}
|
|
488
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .el-card__header,
|
|
489
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .t-card__header {
|
|
490
|
-
top: calc(var(--m-group-list-header-sticky-top, 0px) + var(--m-group-list-header-height));
|
|
491
|
-
z-index: 6;
|
|
492
|
-
}
|
|
493
523
|
.m-fields-group-list .el-table__empty-block {
|
|
494
524
|
width: 100%;
|
|
495
525
|
min-height: 0;
|
|
@@ -507,7 +537,7 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
507
537
|
}
|
|
508
538
|
.m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
|
|
509
539
|
position: sticky;
|
|
510
|
-
bottom:
|
|
540
|
+
bottom: var(--m-group-list-nested-footer-bottom, 0px);
|
|
511
541
|
z-index: 7;
|
|
512
542
|
margin-bottom: 0;
|
|
513
543
|
padding: var(--m-group-list-footer-padding-top) 0 var(--m-group-list-footer-padding-bottom);
|
|
@@ -521,10 +551,6 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
521
551
|
width: 100%;
|
|
522
552
|
height: var(--m-group-list-footer-button-height);
|
|
523
553
|
}
|
|
524
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
|
|
525
|
-
bottom: var(--m-group-list-footer-height);
|
|
526
|
-
z-index: 7;
|
|
527
|
-
}
|
|
528
554
|
|
|
529
555
|
/** 最外层的groupList需要每个item需要增加空白区域界限时,增加outer-gorup_list可以实现 */
|
|
530
556
|
.m-container-group-list.outer-gorup_list > .m-fields-group-list > .m-fields-group-list-item {
|
|
@@ -509,18 +509,48 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
509
509
|
flex-shrink: 0;
|
|
510
510
|
gap: 8px;
|
|
511
511
|
}
|
|
512
|
-
.m-fields-group-list .m-fields-group-list-item
|
|
513
|
-
|
|
512
|
+
.m-fields-group-list > .m-fields-group-list-item {
|
|
513
|
+
--m-group-list-item-footer-bottom: var(
|
|
514
|
+
--m-group-list-nested-footer-bottom,
|
|
515
|
+
0px
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
.m-fields-group-list.is-footer-sticky > .m-fields-group-list-item {
|
|
519
|
+
--m-group-list-item-footer-bottom: calc(
|
|
520
|
+
var(--m-group-list-nested-footer-bottom, 0px) +
|
|
521
|
+
var(--m-group-list-footer-height)
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list {
|
|
525
|
+
--m-group-list-nested-footer-bottom: var(
|
|
526
|
+
--m-group-list-item-footer-bottom,
|
|
527
|
+
0px
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
.m-fields-group-list.is-header-sticky {
|
|
531
|
+
--m-group-list-nested-sticky-top: var(--m-group-list-child-list-sticky-top);
|
|
532
|
+
--m-group-list-nested-header-z: var(--m-group-list-child-list-header-z);
|
|
533
|
+
}
|
|
534
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item {
|
|
535
|
+
--m-group-list-item-sticky-top: var(
|
|
536
|
+
--m-group-list-nested-sticky-top,
|
|
537
|
+
var(--m-group-list-header-sticky-top, 0px)
|
|
538
|
+
);
|
|
539
|
+
--m-group-list-item-header-z: var(--m-group-list-nested-header-z, 7);
|
|
540
|
+
--m-group-list-child-list-sticky-top: calc(
|
|
541
|
+
var(--m-group-list-item-sticky-top) + var(--m-group-list-header-height)
|
|
542
|
+
);
|
|
543
|
+
--m-group-list-child-list-header-z: calc(
|
|
544
|
+
var(--m-group-list-item-header-z) - 1
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .el-card__header,
|
|
548
|
+
.m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .t-card__header {
|
|
514
549
|
position: sticky;
|
|
515
|
-
top: var(--m-group-list-
|
|
516
|
-
z-index:
|
|
550
|
+
top: var(--m-group-list-item-sticky-top);
|
|
551
|
+
z-index: var(--m-group-list-item-header-z);
|
|
517
552
|
background-color: var(--m-group-list-header-bg, #fff);
|
|
518
553
|
}
|
|
519
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .el-card__header,
|
|
520
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .t-card__header {
|
|
521
|
-
top: calc(var(--m-group-list-header-sticky-top, 0px) + var(--m-group-list-header-height));
|
|
522
|
-
z-index: 6;
|
|
523
|
-
}
|
|
524
554
|
.m-fields-group-list .el-table__empty-block {
|
|
525
555
|
width: 100%;
|
|
526
556
|
min-height: 0;
|
|
@@ -538,7 +568,7 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
538
568
|
}
|
|
539
569
|
.m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
|
|
540
570
|
position: sticky;
|
|
541
|
-
bottom:
|
|
571
|
+
bottom: var(--m-group-list-nested-footer-bottom, 0px);
|
|
542
572
|
z-index: 7;
|
|
543
573
|
margin-bottom: 0;
|
|
544
574
|
padding: var(--m-group-list-footer-padding-top) 0 var(--m-group-list-footer-padding-bottom);
|
|
@@ -552,10 +582,6 @@ fieldset.m-fieldset .m-form-tip {
|
|
|
552
582
|
width: 100%;
|
|
553
583
|
height: var(--m-group-list-footer-button-height);
|
|
554
584
|
}
|
|
555
|
-
.m-fields-group-list .m-fields-group-list-item .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
|
|
556
|
-
bottom: var(--m-group-list-footer-height);
|
|
557
|
-
z-index: 7;
|
|
558
|
-
}
|
|
559
585
|
|
|
560
586
|
/** 最外层的groupList需要每个item需要增加空白区域界限时,增加outer-gorup_list可以实现 */
|
|
561
587
|
.m-container-group-list.outer-gorup_list > .m-fields-group-list > .m-fields-group-list-item {
|
|
@@ -8813,12 +8813,13 @@
|
|
|
8813
8813
|
//#endregion
|
|
8814
8814
|
//#region packages/editor/src/fields/configs/stickyAddButton.ts
|
|
8815
8815
|
/**
|
|
8816
|
-
*
|
|
8816
|
+
* 属性面板列表字段共用的吸底全宽「添加」按钮与吸顶标题,展开到 group-list 配置上。
|
|
8817
8817
|
*
|
|
8818
|
-
*
|
|
8818
|
+
* 吸底按钮会盖住列表底部,吸顶标题会盖住列表顶部,新增的项必须同时滚进视口才看得见。
|
|
8819
8819
|
*/
|
|
8820
8820
|
var stickyAddButton = (text) => ({
|
|
8821
8821
|
scrollLastItemIntoView: true,
|
|
8822
|
+
header: { sticky: true },
|
|
8822
8823
|
addButtonConfig: {
|
|
8823
8824
|
sticky: true,
|
|
8824
8825
|
text,
|
|
@@ -9120,8 +9121,8 @@
|
|
|
9120
9121
|
return cloneDeep(methodMap[(0, _tmagic_utils.toLine)(type)]) || [];
|
|
9121
9122
|
}
|
|
9122
9123
|
resetState() {
|
|
9123
|
-
eventMap
|
|
9124
|
-
methodMap
|
|
9124
|
+
Object.keys(eventMap).forEach((type) => delete eventMap[type]);
|
|
9125
|
+
Object.keys(methodMap).forEach((type) => delete methodMap[type]);
|
|
9125
9126
|
}
|
|
9126
9127
|
destroy() {
|
|
9127
9128
|
this.resetState();
|
|
@@ -5057,13 +5057,18 @@
|
|
|
5057
5057
|
//#region packages/editor/src/hooks/use-form-context.ts
|
|
5058
5058
|
var useEditorFormContext;
|
|
5059
5059
|
var init_use_form_context = __esmMin((() => {
|
|
5060
|
-
useEditorFormContext = (getServices) =>
|
|
5061
|
-
const
|
|
5062
|
-
return {
|
|
5063
|
-
services
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5060
|
+
useEditorFormContext = (getServices) => {
|
|
5061
|
+
const hostContext = (0, vue.inject)(_tmagic_form.FORM_CONTEXT_KEY, void 0);
|
|
5062
|
+
return (0, vue.computed)(() => {
|
|
5063
|
+
const services = getServices();
|
|
5064
|
+
const host = (0, vue.unref)(hostContext);
|
|
5065
|
+
if (host && host.services === services) return host;
|
|
5066
|
+
return (0, _tmagic_form.mergeFormContexts)(host, {
|
|
5067
|
+
services,
|
|
5068
|
+
stage: services?.editorService.get("stage")
|
|
5069
|
+
});
|
|
5070
|
+
});
|
|
5071
|
+
};
|
|
5067
5072
|
}));
|
|
5068
5073
|
//#endregion
|
|
5069
5074
|
//#region packages/editor/src/utils/config.ts
|
|
@@ -5130,13 +5135,20 @@
|
|
|
5130
5135
|
name: "timing",
|
|
5131
5136
|
type: "select",
|
|
5132
5137
|
options: () => {
|
|
5133
|
-
const list = [
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5138
|
+
const list = [
|
|
5139
|
+
{
|
|
5140
|
+
text: "初始化前",
|
|
5141
|
+
value: "beforeInit"
|
|
5142
|
+
},
|
|
5143
|
+
{
|
|
5144
|
+
text: "初始化后",
|
|
5145
|
+
value: "afterInit"
|
|
5146
|
+
},
|
|
5147
|
+
{
|
|
5148
|
+
text: "页面渲染后",
|
|
5149
|
+
value: "mounted"
|
|
5150
|
+
}
|
|
5151
|
+
];
|
|
5140
5152
|
if (dataSourceType?.() !== "base") {
|
|
5141
5153
|
list.push({
|
|
5142
5154
|
text: "请求前",
|
|
@@ -11208,8 +11220,8 @@
|
|
|
11208
11220
|
return cloneDeep$1(methodMap[(0, _tmagic_utils.toLine)(type)]) || [];
|
|
11209
11221
|
}
|
|
11210
11222
|
resetState() {
|
|
11211
|
-
eventMap
|
|
11212
|
-
methodMap
|
|
11223
|
+
Object.keys(eventMap).forEach((type) => delete eventMap[type]);
|
|
11224
|
+
Object.keys(methodMap).forEach((type) => delete methodMap[type]);
|
|
11213
11225
|
}
|
|
11214
11226
|
destroy() {
|
|
11215
11227
|
this.resetState();
|
|
@@ -13929,7 +13941,7 @@
|
|
|
13929
13941
|
* 不弹差异弹窗,改用一个普通确认框替代「确定回滚」按钮,避免点击后无任何提示直接执行。
|
|
13930
13942
|
* 用户取消时返回 false,调用方据此中止回滚。
|
|
13931
13943
|
*/
|
|
13932
|
-
const confirmRevert = () => confirmHistoryAction("
|
|
13944
|
+
const confirmRevert = () => confirmHistoryAction("确定回滚该步骤吗?");
|
|
13933
13945
|
/**
|
|
13934
13946
|
* 「回滚」统一确认入口:可差异对比的步骤动态挂载 HistoryDiffDialog 走差异确认弹窗,
|
|
13935
13947
|
* 无法对比的步骤(add / remove / 多节点更新)回退到普通二次确认框。
|
|
@@ -20074,6 +20086,7 @@
|
|
|
20074
20086
|
uiService.resetState();
|
|
20075
20087
|
componentListService.resetState();
|
|
20076
20088
|
codeBlockService.resetState();
|
|
20089
|
+
eventsService.resetState();
|
|
20077
20090
|
keybindingService.reset();
|
|
20078
20091
|
depService.reset();
|
|
20079
20092
|
});
|
|
@@ -20168,10 +20181,20 @@
|
|
|
20168
20181
|
});
|
|
20169
20182
|
});
|
|
20170
20183
|
};
|
|
20184
|
+
/**
|
|
20185
|
+
* root 是否已经不是编辑器当前的 root。
|
|
20186
|
+
*
|
|
20187
|
+
* `editorService.set('root', v)` 是同步赋值后再派发 `root-change`,因此派发那一刻 `v` 一定
|
|
20188
|
+
* 就是当前 root;但处理 `root-change` 要等 stage / runtime / 依赖收集等异步过程,期间 root
|
|
20189
|
+
* 可能被新的一次整体替换(外部重设 DSL、更新 root 节点、源码保存等)顶掉,此时手上的 `v`
|
|
20190
|
+
* 已是过期快照,继续用它刷画布或回写给外部都会与新 root 互相覆盖。
|
|
20191
|
+
*/
|
|
20192
|
+
const isStaleRoot = (value) => (0, vue.toRaw)(editorService.get("root")) !== (0, vue.toRaw)(value);
|
|
20171
20193
|
const updateStageDsl = async (value) => {
|
|
20172
20194
|
const stage = await getStage();
|
|
20173
20195
|
const runtime = await stage.renderer?.getRuntime();
|
|
20174
20196
|
const app = await getTMagicApp();
|
|
20197
|
+
if (isStaleRoot(value)) return;
|
|
20175
20198
|
if (!app?.dataSourceManager) runtime?.updateRootConfig?.(cloneDeep$1((0, vue.toRaw)(value)));
|
|
20176
20199
|
const page = editorService.get("page");
|
|
20177
20200
|
const node = editorService.get("node");
|
|
@@ -20182,6 +20205,7 @@
|
|
|
20182
20205
|
if (value) {
|
|
20183
20206
|
depService.clearIdleTasks();
|
|
20184
20207
|
await (typeof Worker === "undefined" ? collectIdle(value.items, true) : depService.collectByWorker(value));
|
|
20208
|
+
if (isStaleRoot(value)) return;
|
|
20185
20209
|
const dsl = cloneDeep$1((0, vue.toRaw)(value));
|
|
20186
20210
|
if (dsl.dataSources && dsl.dataSourceDeps && app?.dataSourceManager) for (const node of (0, _tmagic_utils.getNodes)((0, _tmagic_utils.getDepNodeIds)(dsl.dataSourceDeps), dsl.items)) (0, _tmagic_core.updateNode)(app.dataSourceManager.compiledNode(node), dsl);
|
|
20187
20211
|
runtime?.updateRootConfig?.(dsl);
|
|
@@ -20192,7 +20216,7 @@
|
|
|
20192
20216
|
depService.addTarget((0, _tmagic_core.createDataSourceMethodTarget)(ds, (0, vue.reactive)({})));
|
|
20193
20217
|
depService.addTarget((0, _tmagic_core.createDataSourceCondTarget)(ds, (0, vue.reactive)({})));
|
|
20194
20218
|
};
|
|
20195
|
-
const rootChangeHandler = (value
|
|
20219
|
+
const rootChangeHandler = (value) => {
|
|
20196
20220
|
if (!value) return;
|
|
20197
20221
|
value.codeBlocks = value.codeBlocks || {};
|
|
20198
20222
|
value.dataSources = value.dataSources || [];
|
|
@@ -20218,7 +20242,8 @@
|
|
|
20218
20242
|
editorService.set("parent", null);
|
|
20219
20243
|
editorService.set("page", null);
|
|
20220
20244
|
}
|
|
20221
|
-
if ((
|
|
20245
|
+
if (isStaleRoot(value)) return;
|
|
20246
|
+
if ((0, vue.toRaw)(props.modelValue) !== (0, vue.toRaw)(value)) emit("update:modelValue", value);
|
|
20222
20247
|
})();
|
|
20223
20248
|
};
|
|
20224
20249
|
const nodeAddHandler = (nodes) => {
|
|
@@ -20667,12 +20692,13 @@
|
|
|
20667
20692
|
//#endregion
|
|
20668
20693
|
//#region packages/editor/src/fields/configs/stickyAddButton.ts
|
|
20669
20694
|
/**
|
|
20670
|
-
*
|
|
20695
|
+
* 属性面板列表字段共用的吸底全宽「添加」按钮与吸顶标题,展开到 group-list 配置上。
|
|
20671
20696
|
*
|
|
20672
|
-
*
|
|
20697
|
+
* 吸底按钮会盖住列表底部,吸顶标题会盖住列表顶部,新增的项必须同时滚进视口才看得见。
|
|
20673
20698
|
*/
|
|
20674
20699
|
var stickyAddButton = (text) => ({
|
|
20675
20700
|
scrollLastItemIntoView: true,
|
|
20701
|
+
header: { sticky: true },
|
|
20676
20702
|
addButtonConfig: {
|
|
20677
20703
|
sticky: true,
|
|
20678
20704
|
text,
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.8.0-beta.
|
|
2
|
+
"version": "1.8.0-beta.28",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -63,11 +63,11 @@
|
|
|
63
63
|
"moveable": "^0.53.0",
|
|
64
64
|
"serialize-javascript": "^7.0.7",
|
|
65
65
|
"sortablejs": "^1.15.7",
|
|
66
|
-
"@tmagic/design": "1.8.0-beta.
|
|
67
|
-
"@tmagic/
|
|
68
|
-
"@tmagic/
|
|
69
|
-
"@tmagic/
|
|
70
|
-
"@tmagic/
|
|
66
|
+
"@tmagic/design": "1.8.0-beta.28",
|
|
67
|
+
"@tmagic/stage": "1.8.0-beta.28",
|
|
68
|
+
"@tmagic/utils": "1.8.0-beta.28",
|
|
69
|
+
"@tmagic/form": "1.8.0-beta.28",
|
|
70
|
+
"@tmagic/table": "1.8.0-beta.28"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@types/events": "^3.0.3",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"type-fest": "^5.2.0",
|
|
82
82
|
"typescript": "^6.0.3",
|
|
83
83
|
"vue": "^3.5.41",
|
|
84
|
-
"@tmagic/core": "1.8.0-beta.
|
|
84
|
+
"@tmagic/core": "1.8.0-beta.28"
|
|
85
85
|
},
|
|
86
86
|
"peerDependenciesMeta": {
|
|
87
87
|
"typescript": {
|
|
@@ -17,12 +17,13 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* 属性面板列表字段共用的吸底全宽「添加」按钮与吸顶标题,展开到 group-list 配置上。
|
|
21
21
|
*
|
|
22
|
-
*
|
|
22
|
+
* 吸底按钮会盖住列表底部,吸顶标题会盖住列表顶部,新增的项必须同时滚进视口才看得见。
|
|
23
23
|
*/
|
|
24
24
|
export const stickyAddButton = (text: string) => ({
|
|
25
25
|
scrollLastItemIntoView: true as const,
|
|
26
|
+
header: { sticky: true as const },
|
|
26
27
|
addButtonConfig: {
|
|
27
28
|
sticky: true as const,
|
|
28
29
|
text,
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { computed, type ComputedRef } from 'vue';
|
|
19
|
+
import { computed, type ComputedRef, inject, unref } from 'vue';
|
|
20
20
|
|
|
21
|
-
import type
|
|
21
|
+
import { FORM_CONTEXT_KEY, type FormContext, mergeFormContexts } from '@tmagic/form';
|
|
22
22
|
|
|
23
23
|
import type { Services } from '@editor/type';
|
|
24
24
|
|
|
@@ -28,13 +28,29 @@ import type { Services } from '@editor/type';
|
|
|
28
28
|
* 由 `Editor.vue`(provide `FORM_CONTEXT_KEY`)、`FormPanel.vue` 与 `useCompareForm`
|
|
29
29
|
* 共用。`stage` 走 computed 而非快照,保证切换画布后配置回调读到的是最新实例。
|
|
30
30
|
*
|
|
31
|
+
* 宿主可能在 `<MEditor>` 外层 provide 了自己的业务字段,这里必须把那一层合并进来:
|
|
32
|
+
* 否则编辑器再 provide 一次会把宿主整层遮蔽掉,属性面板、对比表单里的配置回调就
|
|
33
|
+
* 读不到宿主字段了。`services` / `stage` 由编辑器兜底,优先级高于宿主同名字段。
|
|
34
|
+
*
|
|
31
35
|
* 字段类型见 `@editor/type` 里对 `@tmagic/form-schema` 的 `FormContext` 模块增强。
|
|
32
36
|
*/
|
|
33
|
-
export const useEditorFormContext = (getServices: () => Services | undefined): ComputedRef<FormContext> =>
|
|
34
|
-
|
|
37
|
+
export const useEditorFormContext = (getServices: () => Services | undefined): ComputedRef<FormContext> => {
|
|
38
|
+
// inject 只能在 setup 期取值,因此本 hook 必须在 setup 中调用(`use` 前缀即此约定)。
|
|
39
|
+
// 返回的 computed 可以随便传递,但 hook 本身不能延迟到事件回调或 onMounted 里再调。
|
|
40
|
+
const hostContext = inject(FORM_CONTEXT_KEY, undefined);
|
|
41
|
+
|
|
42
|
+
return computed(() => {
|
|
35
43
|
const services = getServices();
|
|
36
|
-
|
|
44
|
+
const host = unref(hostContext);
|
|
45
|
+
|
|
46
|
+
// 上层(通常是 Editor.vue)已经用同一份 services 合并过了。FormPanel / useCompareForm
|
|
47
|
+
// 都是它的后代,再合并一次只会多套一层 Proxy,让每次属性 miss 多一轮线性查找。
|
|
48
|
+
// services 相同即可判定 stage 也相同——两边都是从同一个 editorService 读的。
|
|
49
|
+
if (host && host.services === services) return host;
|
|
50
|
+
|
|
51
|
+
return mergeFormContexts(host, {
|
|
37
52
|
services,
|
|
38
53
|
stage: services?.editorService.get('stage'),
|
|
39
|
-
};
|
|
54
|
+
});
|
|
40
55
|
});
|
|
56
|
+
};
|
package/src/initService.ts
CHANGED
|
@@ -254,6 +254,7 @@ export const initServiceState = (
|
|
|
254
254
|
uiService.resetState();
|
|
255
255
|
componentListService.resetState();
|
|
256
256
|
codeBlockService.resetState();
|
|
257
|
+
eventsService.resetState();
|
|
257
258
|
keybindingService.reset();
|
|
258
259
|
depService.reset();
|
|
259
260
|
});
|
|
@@ -426,12 +427,26 @@ export const initServiceEvents = (
|
|
|
426
427
|
});
|
|
427
428
|
};
|
|
428
429
|
|
|
430
|
+
/**
|
|
431
|
+
* root 是否已经不是编辑器当前的 root。
|
|
432
|
+
*
|
|
433
|
+
* `editorService.set('root', v)` 是同步赋值后再派发 `root-change`,因此派发那一刻 `v` 一定
|
|
434
|
+
* 就是当前 root;但处理 `root-change` 要等 stage / runtime / 依赖收集等异步过程,期间 root
|
|
435
|
+
* 可能被新的一次整体替换(外部重设 DSL、更新 root 节点、源码保存等)顶掉,此时手上的 `v`
|
|
436
|
+
* 已是过期快照,继续用它刷画布或回写给外部都会与新 root 互相覆盖。
|
|
437
|
+
*/
|
|
438
|
+
const isStaleRoot = (value: MApp | null) => toRaw(editorService.get('root')) !== toRaw(value);
|
|
439
|
+
|
|
429
440
|
const updateStageDsl = async (value: MApp | null) => {
|
|
430
441
|
const stage = await getStage();
|
|
431
442
|
|
|
432
443
|
const runtime = await stage.renderer?.getRuntime();
|
|
433
444
|
const app = await getTMagicApp();
|
|
434
445
|
|
|
446
|
+
// 等 stage / runtime 就绪期间 root 已被替换:新 root 的刷新可能已经完成,
|
|
447
|
+
// 再把旧 dsl 推给 runtime 会让画布回退到旧内容
|
|
448
|
+
if (isStaleRoot(value)) return;
|
|
449
|
+
|
|
435
450
|
if (!app?.dataSourceManager) {
|
|
436
451
|
runtime?.updateRootConfig?.(cloneDeep(toRaw(value))!);
|
|
437
452
|
}
|
|
@@ -448,6 +463,8 @@ export const initServiceEvents = (
|
|
|
448
463
|
|
|
449
464
|
await (typeof Worker === 'undefined' ? collectIdle(value.items, true) : depService.collectByWorker(value));
|
|
450
465
|
|
|
466
|
+
if (isStaleRoot(value)) return;
|
|
467
|
+
|
|
451
468
|
const dsl = cloneDeep(toRaw(value));
|
|
452
469
|
if (dsl.dataSources && dsl.dataSourceDeps && app?.dataSourceManager) {
|
|
453
470
|
for (const node of getNodes(getDepNodeIds(dsl.dataSourceDeps), dsl.items)) {
|
|
@@ -465,7 +482,7 @@ export const initServiceEvents = (
|
|
|
465
482
|
depService.addTarget(createDataSourceCondTarget(ds, reactive({})));
|
|
466
483
|
};
|
|
467
484
|
|
|
468
|
-
const rootChangeHandler = (value: MApp | null
|
|
485
|
+
const rootChangeHandler = (value: MApp | null) => {
|
|
469
486
|
if (!value) return;
|
|
470
487
|
|
|
471
488
|
value.codeBlocks = value.codeBlocks || {};
|
|
@@ -508,7 +525,13 @@ export const initServiceEvents = (
|
|
|
508
525
|
editorService.set('page', null);
|
|
509
526
|
}
|
|
510
527
|
|
|
511
|
-
|
|
528
|
+
// 上面的 select 是异步的,期间 root 可能已被替换,过期快照不能再回写给外部:
|
|
529
|
+
// 两次整体替换各自持有一个快照时,回写会把对方的 root 顶掉,外部 modelValue 变化又会
|
|
530
|
+
// 重新 set root,两条链路无休止地交替下去(表现为编辑器卡死)
|
|
531
|
+
if (isStaleRoot(value)) return;
|
|
532
|
+
|
|
533
|
+
// 外部已经持有这个 root(如本次变化就是 modelValue 传进来的)时无需回写
|
|
534
|
+
if (toRaw(props.modelValue) !== toRaw(value)) {
|
|
512
535
|
emit('update:modelValue', value);
|
|
513
536
|
}
|
|
514
537
|
})();
|
|
@@ -204,10 +204,7 @@ export const useHistoryRevert = (options: UseHistoryRevertOptions = {}, services
|
|
|
204
204
|
* 不弹差异弹窗,改用一个普通确认框替代「确定回滚」按钮,避免点击后无任何提示直接执行。
|
|
205
205
|
* 用户取消时返回 false,调用方据此中止回滚。
|
|
206
206
|
*/
|
|
207
|
-
const confirmRevert = (): Promise<boolean> =>
|
|
208
|
-
confirmHistoryAction(
|
|
209
|
-
'确定回滚该步骤吗?回滚会将该操作作为一条新记录反向应用(新增将被删除、删除将被还原),不影响后续历史记录。',
|
|
210
|
-
);
|
|
207
|
+
const confirmRevert = (): Promise<boolean> => confirmHistoryAction('确定回滚该步骤吗?');
|
|
211
208
|
|
|
212
209
|
/**
|
|
213
210
|
* 「回滚」统一确认入口:可差异对比的步骤动态挂载 HistoryDiffDialog 走差异确认弹窗,
|
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() {
|
package/src/type.ts
CHANGED
|
@@ -225,6 +225,7 @@ export interface StageOptions {
|
|
|
225
225
|
beforeDblclick?: (event: MouseEvent) => Promise<boolean | void> | boolean | void;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
// #region NodeInvalidInfo
|
|
228
229
|
/**
|
|
229
230
|
* 节点校验错误信息,按来源(属性表单 / 样式表单)分别保存错误文案。
|
|
230
231
|
* 属性表单与样式表单是两个独立的 FormPanel,均指向同一节点,故以来源为键,
|
|
@@ -237,9 +238,12 @@ export interface NodeInvalidInfo {
|
|
|
237
238
|
/** 样式表单校验错误文案(可能为包含 <br> 的 HTML) */
|
|
238
239
|
style?: string;
|
|
239
240
|
}
|
|
241
|
+
// #endregion NodeInvalidInfo
|
|
240
242
|
|
|
243
|
+
// #region NodeInvalidSource
|
|
241
244
|
/** 节点校验错误来源 */
|
|
242
245
|
export type NodeInvalidSource = keyof NodeInvalidInfo;
|
|
246
|
+
// #endregion NodeInvalidSource
|
|
243
247
|
|
|
244
248
|
export interface StoreState {
|
|
245
249
|
root: MApp | null;
|
|
@@ -312,6 +316,7 @@ export interface StageRect {
|
|
|
312
316
|
height: number | string;
|
|
313
317
|
}
|
|
314
318
|
|
|
319
|
+
// #region UiState
|
|
315
320
|
export interface UiState {
|
|
316
321
|
/** 当前点击画布是否触发选中,true: 不触发,false: 触发,默认为false */
|
|
317
322
|
uiSelectMode: boolean;
|
|
@@ -369,6 +374,7 @@ export interface UiState {
|
|
|
369
374
|
height: number;
|
|
370
375
|
};
|
|
371
376
|
}
|
|
377
|
+
// #endregion UiState
|
|
372
378
|
|
|
373
379
|
// #region EditorNodeInfo
|
|
374
380
|
export interface EditorNodeInfo {
|
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' });
|