@tmagic/editor 1.8.0-beta.27 → 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/initService.js +14 -2
- package/dist/es/layouts/history-list/useHistoryRevert.js +1 -1
- package/dist/es/style.css +40 -14
- package/dist/style.css +40 -14
- package/dist/themes/magic-admin.css +40 -14
- package/dist/tmagic-editor-headless.umd.cjs +3 -2
- package/dist/tmagic-editor.umd.cjs +18 -5
- package/package.json +7 -7
- package/src/fields/configs/stickyAddButton.ts +3 -2
- package/src/initService.ts +24 -2
- package/src/layouts/history-list/useHistoryRevert.ts +1 -4
|
@@ -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,
|
package/dist/es/initService.js
CHANGED
|
@@ -168,10 +168,20 @@ var initServiceEvents = (props, emit, { editorService, codeBlockService, dataSou
|
|
|
168
168
|
});
|
|
169
169
|
});
|
|
170
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);
|
|
171
180
|
const updateStageDsl = async (value) => {
|
|
172
181
|
const stage = await getStage();
|
|
173
182
|
const runtime = await stage.renderer?.getRuntime();
|
|
174
183
|
const app = await getTMagicApp();
|
|
184
|
+
if (isStaleRoot(value)) return;
|
|
175
185
|
if (!app?.dataSourceManager) runtime?.updateRootConfig?.(cloneDeep$1(toRaw(value)));
|
|
176
186
|
const page = editorService.get("page");
|
|
177
187
|
const node = editorService.get("node");
|
|
@@ -182,6 +192,7 @@ var initServiceEvents = (props, emit, { editorService, codeBlockService, dataSou
|
|
|
182
192
|
if (value) {
|
|
183
193
|
depService.clearIdleTasks();
|
|
184
194
|
await (typeof Worker === "undefined" ? collectIdle(value.items, true) : depService.collectByWorker(value));
|
|
195
|
+
if (isStaleRoot(value)) return;
|
|
185
196
|
const dsl = cloneDeep$1(toRaw(value));
|
|
186
197
|
if (dsl.dataSources && dsl.dataSourceDeps && app?.dataSourceManager) for (const node of getNodes(getDepNodeIds(dsl.dataSourceDeps), dsl.items)) updateNode(app.dataSourceManager.compiledNode(node), dsl);
|
|
187
198
|
runtime?.updateRootConfig?.(dsl);
|
|
@@ -192,7 +203,7 @@ var initServiceEvents = (props, emit, { editorService, codeBlockService, dataSou
|
|
|
192
203
|
depService.addTarget(createDataSourceMethodTarget(ds, reactive({})));
|
|
193
204
|
depService.addTarget(createDataSourceCondTarget(ds, reactive({})));
|
|
194
205
|
};
|
|
195
|
-
const rootChangeHandler = (value
|
|
206
|
+
const rootChangeHandler = (value) => {
|
|
196
207
|
if (!value) return;
|
|
197
208
|
value.codeBlocks = value.codeBlocks || {};
|
|
198
209
|
value.dataSources = value.dataSources || [];
|
|
@@ -218,7 +229,8 @@ var initServiceEvents = (props, emit, { editorService, codeBlockService, dataSou
|
|
|
218
229
|
editorService.set("parent", null);
|
|
219
230
|
editorService.set("page", null);
|
|
220
231
|
}
|
|
221
|
-
if (
|
|
232
|
+
if (isStaleRoot(value)) return;
|
|
233
|
+
if (toRaw(props.modelValue) !== toRaw(value)) emit("update:modelValue", value);
|
|
222
234
|
})();
|
|
223
235
|
};
|
|
224
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 / 多节点更新)回退到普通二次确认框。
|
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 {
|
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,
|
|
@@ -13941,7 +13941,7 @@
|
|
|
13941
13941
|
* 不弹差异弹窗,改用一个普通确认框替代「确定回滚」按钮,避免点击后无任何提示直接执行。
|
|
13942
13942
|
* 用户取消时返回 false,调用方据此中止回滚。
|
|
13943
13943
|
*/
|
|
13944
|
-
const confirmRevert = () => confirmHistoryAction("
|
|
13944
|
+
const confirmRevert = () => confirmHistoryAction("确定回滚该步骤吗?");
|
|
13945
13945
|
/**
|
|
13946
13946
|
* 「回滚」统一确认入口:可差异对比的步骤动态挂载 HistoryDiffDialog 走差异确认弹窗,
|
|
13947
13947
|
* 无法对比的步骤(add / remove / 多节点更新)回退到普通二次确认框。
|
|
@@ -20181,10 +20181,20 @@
|
|
|
20181
20181
|
});
|
|
20182
20182
|
});
|
|
20183
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);
|
|
20184
20193
|
const updateStageDsl = async (value) => {
|
|
20185
20194
|
const stage = await getStage();
|
|
20186
20195
|
const runtime = await stage.renderer?.getRuntime();
|
|
20187
20196
|
const app = await getTMagicApp();
|
|
20197
|
+
if (isStaleRoot(value)) return;
|
|
20188
20198
|
if (!app?.dataSourceManager) runtime?.updateRootConfig?.(cloneDeep$1((0, vue.toRaw)(value)));
|
|
20189
20199
|
const page = editorService.get("page");
|
|
20190
20200
|
const node = editorService.get("node");
|
|
@@ -20195,6 +20205,7 @@
|
|
|
20195
20205
|
if (value) {
|
|
20196
20206
|
depService.clearIdleTasks();
|
|
20197
20207
|
await (typeof Worker === "undefined" ? collectIdle(value.items, true) : depService.collectByWorker(value));
|
|
20208
|
+
if (isStaleRoot(value)) return;
|
|
20198
20209
|
const dsl = cloneDeep$1((0, vue.toRaw)(value));
|
|
20199
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);
|
|
20200
20211
|
runtime?.updateRootConfig?.(dsl);
|
|
@@ -20205,7 +20216,7 @@
|
|
|
20205
20216
|
depService.addTarget((0, _tmagic_core.createDataSourceMethodTarget)(ds, (0, vue.reactive)({})));
|
|
20206
20217
|
depService.addTarget((0, _tmagic_core.createDataSourceCondTarget)(ds, (0, vue.reactive)({})));
|
|
20207
20218
|
};
|
|
20208
|
-
const rootChangeHandler = (value
|
|
20219
|
+
const rootChangeHandler = (value) => {
|
|
20209
20220
|
if (!value) return;
|
|
20210
20221
|
value.codeBlocks = value.codeBlocks || {};
|
|
20211
20222
|
value.dataSources = value.dataSources || [];
|
|
@@ -20231,7 +20242,8 @@
|
|
|
20231
20242
|
editorService.set("parent", null);
|
|
20232
20243
|
editorService.set("page", null);
|
|
20233
20244
|
}
|
|
20234
|
-
if ((
|
|
20245
|
+
if (isStaleRoot(value)) return;
|
|
20246
|
+
if ((0, vue.toRaw)(props.modelValue) !== (0, vue.toRaw)(value)) emit("update:modelValue", value);
|
|
20235
20247
|
})();
|
|
20236
20248
|
};
|
|
20237
20249
|
const nodeAddHandler = (nodes) => {
|
|
@@ -20680,12 +20692,13 @@
|
|
|
20680
20692
|
//#endregion
|
|
20681
20693
|
//#region packages/editor/src/fields/configs/stickyAddButton.ts
|
|
20682
20694
|
/**
|
|
20683
|
-
*
|
|
20695
|
+
* 属性面板列表字段共用的吸底全宽「添加」按钮与吸顶标题,展开到 group-list 配置上。
|
|
20684
20696
|
*
|
|
20685
|
-
*
|
|
20697
|
+
* 吸底按钮会盖住列表底部,吸顶标题会盖住列表顶部,新增的项必须同时滚进视口才看得见。
|
|
20686
20698
|
*/
|
|
20687
20699
|
var stickyAddButton = (text) => ({
|
|
20688
20700
|
scrollLastItemIntoView: true,
|
|
20701
|
+
header: { sticky: true },
|
|
20689
20702
|
addButtonConfig: {
|
|
20690
20703
|
sticky: true,
|
|
20691
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/stage": "1.8.0-beta.
|
|
68
|
-
"@tmagic/
|
|
69
|
-
"@tmagic/form": "1.8.0-beta.
|
|
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,
|
package/src/initService.ts
CHANGED
|
@@ -427,12 +427,26 @@ export const initServiceEvents = (
|
|
|
427
427
|
});
|
|
428
428
|
};
|
|
429
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
|
+
|
|
430
440
|
const updateStageDsl = async (value: MApp | null) => {
|
|
431
441
|
const stage = await getStage();
|
|
432
442
|
|
|
433
443
|
const runtime = await stage.renderer?.getRuntime();
|
|
434
444
|
const app = await getTMagicApp();
|
|
435
445
|
|
|
446
|
+
// 等 stage / runtime 就绪期间 root 已被替换:新 root 的刷新可能已经完成,
|
|
447
|
+
// 再把旧 dsl 推给 runtime 会让画布回退到旧内容
|
|
448
|
+
if (isStaleRoot(value)) return;
|
|
449
|
+
|
|
436
450
|
if (!app?.dataSourceManager) {
|
|
437
451
|
runtime?.updateRootConfig?.(cloneDeep(toRaw(value))!);
|
|
438
452
|
}
|
|
@@ -449,6 +463,8 @@ export const initServiceEvents = (
|
|
|
449
463
|
|
|
450
464
|
await (typeof Worker === 'undefined' ? collectIdle(value.items, true) : depService.collectByWorker(value));
|
|
451
465
|
|
|
466
|
+
if (isStaleRoot(value)) return;
|
|
467
|
+
|
|
452
468
|
const dsl = cloneDeep(toRaw(value));
|
|
453
469
|
if (dsl.dataSources && dsl.dataSourceDeps && app?.dataSourceManager) {
|
|
454
470
|
for (const node of getNodes(getDepNodeIds(dsl.dataSourceDeps), dsl.items)) {
|
|
@@ -466,7 +482,7 @@ export const initServiceEvents = (
|
|
|
466
482
|
depService.addTarget(createDataSourceCondTarget(ds, reactive({})));
|
|
467
483
|
};
|
|
468
484
|
|
|
469
|
-
const rootChangeHandler = (value: MApp | null
|
|
485
|
+
const rootChangeHandler = (value: MApp | null) => {
|
|
470
486
|
if (!value) return;
|
|
471
487
|
|
|
472
488
|
value.codeBlocks = value.codeBlocks || {};
|
|
@@ -509,7 +525,13 @@ export const initServiceEvents = (
|
|
|
509
525
|
editorService.set('page', null);
|
|
510
526
|
}
|
|
511
527
|
|
|
512
|
-
|
|
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)) {
|
|
513
535
|
emit('update:modelValue', value);
|
|
514
536
|
}
|
|
515
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 走差异确认弹窗,
|