@tmagic/editor 1.7.9 → 1.7.11
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 +3 -1
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +17 -7
- package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +38 -9
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +3 -1
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +38 -5
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +5 -0
- package/dist/es/fields/StyleSetter/pro/Transform.js +5 -0
- package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/es/hooks/use-code-block-edit.js +3 -2
- package/dist/es/hooks/use-stage.js +5 -1
- package/dist/es/index.js +3 -3
- package/dist/es/initService.js +4 -4
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +2 -0
- package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +64 -1
- package/dist/es/layouts/workspace/viewer/StageOverlay.vue_vue_type_script_setup_true_lang.js +1 -5
- package/dist/es/services/editor.js +191 -174
- package/dist/es/services/history.js +1 -9
- package/dist/es/services/props.js +2 -0
- package/dist/es/services/ui.js +1 -0
- package/dist/es/type.js +28 -1
- package/dist/es/utils/dep/worker.js +1 -1
- package/dist/es/utils/editor-history.js +100 -0
- package/dist/es/utils/editor.js +178 -4
- package/dist/es/utils/props.js +6 -2
- package/dist/es/utils/undo-redo.js +7 -4
- package/dist/tmagic-editor.umd.cjs +768 -246
- package/package.json +9 -9
- package/src/Editor.vue +1 -0
- package/src/components/CodeBlockEditor.vue +1 -1
- package/src/components/CodeParams.vue +23 -7
- package/src/editorProps.ts +2 -0
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +39 -6
- package/src/fields/DataSourceFieldSelect/Index.vue +1 -0
- package/src/fields/DataSourceMethodSelect.vue +54 -13
- package/src/fields/DataSourceMethods.vue +9 -5
- package/src/fields/DisplayConds.vue +1 -0
- package/src/fields/StyleSetter/Index.vue +5 -1
- package/src/fields/StyleSetter/pro/Transform.vue +54 -0
- package/src/fields/StyleSetter/pro/index.ts +1 -0
- package/src/hooks/use-code-block-edit.ts +8 -4
- package/src/hooks/use-stage.ts +11 -4
- package/src/initService.ts +6 -6
- package/src/layouts/NavMenu.vue +2 -0
- package/src/layouts/workspace/viewer/Stage.vue +89 -1
- package/src/layouts/workspace/viewer/StageOverlay.vue +1 -6
- package/src/services/editor.ts +231 -270
- package/src/services/history.ts +1 -9
- package/src/services/ui.ts +1 -0
- package/src/type.ts +67 -5
- package/src/utils/editor-history.ts +138 -0
- package/src/utils/editor.ts +249 -4
- package/src/utils/props.ts +5 -0
- package/src/utils/undo-redo.ts +7 -6
- package/types/index.d.ts +611 -491
|
@@ -1,43 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Layout, canUsePluginMethods } from "../type.js";
|
|
2
2
|
import BaseService_default from "./BaseService.js";
|
|
3
3
|
import props_default from "./props.js";
|
|
4
4
|
import history_default from "./history.js";
|
|
5
5
|
import storage_default, { Protocol } from "./storage.js";
|
|
6
|
-
import { COPY_STORAGE_KEY,
|
|
6
|
+
import { COPY_STORAGE_KEY, calcAlignCenterStyle, calcLayerTargetIndex, calcMoveStyle, classifyDragSources, collectRelatedNodes, editorNodeMergeCustomizer, fixNodePosition, getInitPositionStyle, getNodeIndex, getPageFragmentList, getPageList, moveItemsInContainer, resolveSelectedNode, setChildrenLayout, setLayout, toggleFixedPosition } from "../utils/editor.js";
|
|
7
|
+
import { applyHistoryAddOp, applyHistoryRemoveOp, applyHistoryUpdateOp } from "../utils/editor-history.js";
|
|
7
8
|
import { beforePaste, getAddParent } from "../utils/operator.js";
|
|
8
9
|
import { isFixed } from "@tmagic/stage";
|
|
9
|
-
import {
|
|
10
|
-
import { NodeType
|
|
10
|
+
import { getNodeInfo, getNodePath, isPage, isPageFragment } from "@tmagic/utils";
|
|
11
|
+
import { NodeType } from "@tmagic/core";
|
|
11
12
|
import { reactive, toRaw } from "vue";
|
|
12
|
-
import { cloneDeep,
|
|
13
|
+
import { cloneDeep, isObject, mergeWith, uniq } from "lodash-es";
|
|
13
14
|
//#region packages/editor/src/services/editor.ts
|
|
14
|
-
var canUsePluginMethods = {
|
|
15
|
-
async: [
|
|
16
|
-
"getLayout",
|
|
17
|
-
"highlight",
|
|
18
|
-
"select",
|
|
19
|
-
"multiSelect",
|
|
20
|
-
"doAdd",
|
|
21
|
-
"add",
|
|
22
|
-
"doRemove",
|
|
23
|
-
"remove",
|
|
24
|
-
"doUpdate",
|
|
25
|
-
"update",
|
|
26
|
-
"sort",
|
|
27
|
-
"copy",
|
|
28
|
-
"paste",
|
|
29
|
-
"doPaste",
|
|
30
|
-
"doAlignCenter",
|
|
31
|
-
"alignCenter",
|
|
32
|
-
"moveLayer",
|
|
33
|
-
"moveToContainer",
|
|
34
|
-
"dragTo",
|
|
35
|
-
"undo",
|
|
36
|
-
"redo",
|
|
37
|
-
"move"
|
|
38
|
-
],
|
|
39
|
-
sync: []
|
|
40
|
-
};
|
|
41
15
|
var Editor = class extends BaseService_default {
|
|
42
16
|
state = reactive({
|
|
43
17
|
root: null,
|
|
@@ -54,6 +28,7 @@ var Editor = class extends BaseService_default {
|
|
|
54
28
|
disabledMultiSelect: false
|
|
55
29
|
});
|
|
56
30
|
isHistoryStateChange = false;
|
|
31
|
+
selectionBeforeOp = null;
|
|
57
32
|
constructor() {
|
|
58
33
|
super(canUsePluginMethods.async.map((methodName) => ({
|
|
59
34
|
name: methodName,
|
|
@@ -249,6 +224,7 @@ var Editor = class extends BaseService_default {
|
|
|
249
224
|
* @returns 添加后的节点
|
|
250
225
|
*/
|
|
251
226
|
async add(addNode, parent) {
|
|
227
|
+
this.captureSelectionBeforeOp();
|
|
252
228
|
const stage = this.get("stage");
|
|
253
229
|
const addNodes = [];
|
|
254
230
|
if (!Array.isArray(addNode)) {
|
|
@@ -273,7 +249,20 @@ var Editor = class extends BaseService_default {
|
|
|
273
249
|
else if (isPageFragment(newNodes[0])) this.state.pageFragmentLength += 1;
|
|
274
250
|
else stage?.select(newNodes[0].id);
|
|
275
251
|
}
|
|
276
|
-
if (!(isPage(newNodes[0]) || isPageFragment(newNodes[0])))
|
|
252
|
+
if (!(isPage(newNodes[0]) || isPageFragment(newNodes[0]))) {
|
|
253
|
+
const pageForOp = this.getNodeInfo(newNodes[0].id, false).page;
|
|
254
|
+
this.pushOpHistory("add", {
|
|
255
|
+
nodes: newNodes.map((n) => cloneDeep(toRaw(n))),
|
|
256
|
+
parentId: (this.getParentById(newNodes[0].id, false) ?? this.get("root")).id,
|
|
257
|
+
indexMap: Object.fromEntries(newNodes.map((n) => {
|
|
258
|
+
const p = this.getParentById(n.id, false);
|
|
259
|
+
return [n.id, p ? getNodeIndex(n.id, p) : -1];
|
|
260
|
+
}))
|
|
261
|
+
}, {
|
|
262
|
+
name: pageForOp?.name || "",
|
|
263
|
+
id: pageForOp.id
|
|
264
|
+
});
|
|
265
|
+
}
|
|
277
266
|
this.emit("add", newNodes);
|
|
278
267
|
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
279
268
|
}
|
|
@@ -322,9 +311,27 @@ var Editor = class extends BaseService_default {
|
|
|
322
311
|
* @param {Object} node
|
|
323
312
|
*/
|
|
324
313
|
async remove(nodeOrNodeList) {
|
|
314
|
+
this.captureSelectionBeforeOp();
|
|
325
315
|
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
316
|
+
const removedItems = [];
|
|
317
|
+
let pageForOp = null;
|
|
318
|
+
if (!(isPage(nodes[0]) || isPageFragment(nodes[0]))) for (const n of nodes) {
|
|
319
|
+
const { parent, node: curNode, page } = this.getNodeInfo(n.id, false);
|
|
320
|
+
if (parent && curNode) {
|
|
321
|
+
if (!pageForOp && page) pageForOp = {
|
|
322
|
+
name: page.name || "",
|
|
323
|
+
id: page.id
|
|
324
|
+
};
|
|
325
|
+
const idx = getNodeIndex(curNode.id, parent);
|
|
326
|
+
removedItems.push({
|
|
327
|
+
node: cloneDeep(toRaw(curNode)),
|
|
328
|
+
parentId: parent.id,
|
|
329
|
+
index: typeof idx === "number" ? idx : -1
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
326
333
|
await Promise.all(nodes.map((node) => this.doRemove(node)));
|
|
327
|
-
if (
|
|
334
|
+
if (removedItems.length > 0 && pageForOp) this.pushOpHistory("remove", { removedItems }, pageForOp);
|
|
328
335
|
this.emit("remove", nodes);
|
|
329
336
|
}
|
|
330
337
|
async doUpdate(config, { changeRecords = [] } = {}) {
|
|
@@ -334,12 +341,8 @@ var Editor = class extends BaseService_default {
|
|
|
334
341
|
const info = this.getNodeInfo(config.id, false);
|
|
335
342
|
if (!info.node) throw new Error(`获取不到id为${config.id}的节点`);
|
|
336
343
|
const node = toRaw(info.node);
|
|
337
|
-
let newConfig = await
|
|
338
|
-
newConfig = mergeWith(cloneDeep(node), newConfig,
|
|
339
|
-
if (typeof srcValue === "undefined" && Object.hasOwn(source, key)) return "";
|
|
340
|
-
if (isObject(srcValue) && Array.isArray(objValue)) return srcValue;
|
|
341
|
-
if (Array.isArray(srcValue)) return srcValue;
|
|
342
|
-
});
|
|
344
|
+
let newConfig = await toggleFixedPosition(toRaw(config), node, root, this.getLayout);
|
|
345
|
+
newConfig = mergeWith(cloneDeep(node), newConfig, editorNodeMergeCustomizer);
|
|
343
346
|
if (!newConfig.type) throw new Error("配置缺少type值");
|
|
344
347
|
if (newConfig.type === NodeType.ROOT) {
|
|
345
348
|
this.set("root", newConfig);
|
|
@@ -377,9 +380,23 @@ var Editor = class extends BaseService_default {
|
|
|
377
380
|
* @returns 更新后的节点配置
|
|
378
381
|
*/
|
|
379
382
|
async update(config, data = {}) {
|
|
383
|
+
this.captureSelectionBeforeOp();
|
|
380
384
|
const nodes = Array.isArray(config) ? config : [config];
|
|
381
385
|
const updateData = await Promise.all(nodes.map((node) => this.doUpdate(node, data)));
|
|
382
|
-
if (updateData[0].oldNode?.type !== NodeType.ROOT)
|
|
386
|
+
if (updateData[0].oldNode?.type !== NodeType.ROOT) {
|
|
387
|
+
const curNodes = this.get("nodes");
|
|
388
|
+
if (!this.isHistoryStateChange && curNodes.length) {
|
|
389
|
+
const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
|
|
390
|
+
this.pushOpHistory("update", { updatedItems: updateData.map((d) => ({
|
|
391
|
+
oldNode: cloneDeep(d.oldNode),
|
|
392
|
+
newNode: cloneDeep(toRaw(d.newNode))
|
|
393
|
+
})) }, {
|
|
394
|
+
name: pageForOp?.name || "",
|
|
395
|
+
id: pageForOp.id
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
this.isHistoryStateChange = false;
|
|
399
|
+
}
|
|
383
400
|
this.emit("update", updateData);
|
|
384
401
|
return Array.isArray(config) ? updateData.map((item) => item.newNode) : updateData[0].newNode;
|
|
385
402
|
}
|
|
@@ -390,6 +407,7 @@ var Editor = class extends BaseService_default {
|
|
|
390
407
|
* @returns void
|
|
391
408
|
*/
|
|
392
409
|
async sort(id1, id2) {
|
|
410
|
+
this.captureSelectionBeforeOp();
|
|
393
411
|
const root = this.get("root");
|
|
394
412
|
if (!root) throw new Error("root为空");
|
|
395
413
|
const node = this.get("node");
|
|
@@ -407,8 +425,6 @@ var Editor = class extends BaseService_default {
|
|
|
407
425
|
parentId: parent.id,
|
|
408
426
|
root: cloneDeep(root)
|
|
409
427
|
});
|
|
410
|
-
this.addModifiedNodeId(parent.id);
|
|
411
|
-
this.pushHistoryState();
|
|
412
428
|
}
|
|
413
429
|
/**
|
|
414
430
|
* 将组件节点配置存储到localStorage中
|
|
@@ -425,23 +441,7 @@ var Editor = class extends BaseService_default {
|
|
|
425
441
|
*/
|
|
426
442
|
copyWithRelated(config, collectorOptions) {
|
|
427
443
|
const copyNodes = Array.isArray(config) ? config : [config];
|
|
428
|
-
if (collectorOptions && typeof collectorOptions.isTarget === "function")
|
|
429
|
-
const customTarget = new Target({ ...collectorOptions });
|
|
430
|
-
const coperWatcher = new Watcher();
|
|
431
|
-
coperWatcher.addTarget(customTarget);
|
|
432
|
-
coperWatcher.collect(copyNodes, {}, true, collectorOptions.type);
|
|
433
|
-
Object.keys(customTarget.deps).forEach((nodeId) => {
|
|
434
|
-
const node = this.getNodeById(nodeId);
|
|
435
|
-
if (!node) return;
|
|
436
|
-
customTarget.deps[nodeId].keys.forEach((key) => {
|
|
437
|
-
const relateNodeId = get(node, key);
|
|
438
|
-
if (!copyNodes.find((node) => node.id === relateNodeId)) {
|
|
439
|
-
const relateNode = this.getNodeById(relateNodeId);
|
|
440
|
-
if (relateNode) copyNodes.push(relateNode);
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
}
|
|
444
|
+
if (collectorOptions && typeof collectorOptions.isTarget === "function") collectRelatedNodes(copyNodes, collectorOptions, (id) => this.getNodeById(id));
|
|
445
445
|
storage_default.setItem(COPY_STORAGE_KEY, copyNodes, { protocol: Protocol.OBJECT });
|
|
446
446
|
}
|
|
447
447
|
/**
|
|
@@ -472,20 +472,10 @@ var Editor = class extends BaseService_default {
|
|
|
472
472
|
if (!parent) throw new Error("找不到父节点");
|
|
473
473
|
const node = cloneDeep(toRaw(config));
|
|
474
474
|
const layout = await this.getLayout(parent, node);
|
|
475
|
-
if (layout === Layout.RELATIVE) return config;
|
|
476
|
-
if (!node.style) return config;
|
|
477
475
|
const doc = this.get("stage")?.renderer?.contentWindow?.document;
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
if (parentEl && el) {
|
|
482
|
-
node.style.left = calcValueByFontsize(doc, (parentEl.clientWidth - el.clientWidth) / 2);
|
|
483
|
-
node.style.right = "";
|
|
484
|
-
}
|
|
485
|
-
} else if (parent.style && isNumber(parent.style?.width) && isNumber(node.style?.width)) {
|
|
486
|
-
node.style.left = (parent.style.width - node.style.width) / 2;
|
|
487
|
-
node.style.right = "";
|
|
488
|
-
}
|
|
476
|
+
const newStyle = calcAlignCenterStyle(node, parent, layout, doc);
|
|
477
|
+
if (!newStyle) return config;
|
|
478
|
+
node.style = newStyle;
|
|
489
479
|
return node;
|
|
490
480
|
}
|
|
491
481
|
/**
|
|
@@ -507,6 +497,7 @@ var Editor = class extends BaseService_default {
|
|
|
507
497
|
* @param offset 偏移量
|
|
508
498
|
*/
|
|
509
499
|
async moveLayer(offset) {
|
|
500
|
+
this.captureSelectionBeforeOp();
|
|
510
501
|
const root = this.get("root");
|
|
511
502
|
if (!root) throw new Error("root为空");
|
|
512
503
|
const parent = this.get("parent");
|
|
@@ -516,11 +507,9 @@ var Editor = class extends BaseService_default {
|
|
|
516
507
|
const brothers = parent.items || [];
|
|
517
508
|
const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
|
|
518
509
|
const isRelative = await this.getLayout(parent, node) === Layout.RELATIVE;
|
|
519
|
-
|
|
520
|
-
if (offset === LayerOffset.TOP) offsetIndex = isRelative ? 0 : brothers.length;
|
|
521
|
-
else if (offset === LayerOffset.BOTTOM) offsetIndex = isRelative ? brothers.length : 0;
|
|
522
|
-
else offsetIndex = index + (isRelative ? -offset : offset);
|
|
510
|
+
const offsetIndex = calcLayerTargetIndex(index, offset, brothers.length, isRelative);
|
|
523
511
|
if (offsetIndex > 0 && offsetIndex > brothers.length || offsetIndex < 0) return;
|
|
512
|
+
const oldParent = cloneDeep(toRaw(parent));
|
|
524
513
|
brothers.splice(index, 1);
|
|
525
514
|
brothers.splice(offsetIndex, 0, node);
|
|
526
515
|
const grandparent = this.getParentById(parent.id);
|
|
@@ -530,7 +519,14 @@ var Editor = class extends BaseService_default {
|
|
|
530
519
|
root: cloneDeep(root)
|
|
531
520
|
});
|
|
532
521
|
this.addModifiedNodeId(parent.id);
|
|
533
|
-
this.
|
|
522
|
+
const pageForOp = this.getNodeInfo(node.id, false).page;
|
|
523
|
+
this.pushOpHistory("update", { updatedItems: [{
|
|
524
|
+
oldNode: oldParent,
|
|
525
|
+
newNode: cloneDeep(toRaw(parent))
|
|
526
|
+
}] }, {
|
|
527
|
+
name: pageForOp?.name || "",
|
|
528
|
+
id: pageForOp.id
|
|
529
|
+
});
|
|
534
530
|
this.emit("move-layer", offset);
|
|
535
531
|
}
|
|
536
532
|
/**
|
|
@@ -539,11 +535,14 @@ var Editor = class extends BaseService_default {
|
|
|
539
535
|
* @param targetId 容器ID
|
|
540
536
|
*/
|
|
541
537
|
async moveToContainer(config, targetId) {
|
|
538
|
+
this.captureSelectionBeforeOp();
|
|
542
539
|
const root = this.get("root");
|
|
543
|
-
const { node, parent } = this.getNodeInfo(config.id, false);
|
|
540
|
+
const { node, parent, page: pageForOp } = this.getNodeInfo(config.id, false);
|
|
544
541
|
const target = this.getNodeById(targetId, false);
|
|
545
542
|
const stage = this.get("stage");
|
|
546
543
|
if (root && node && parent && stage) {
|
|
544
|
+
const oldSourceParent = cloneDeep(toRaw(parent));
|
|
545
|
+
const oldTarget = cloneDeep(toRaw(target));
|
|
547
546
|
const index = getNodeIndex(node.id, parent);
|
|
548
547
|
parent.items?.splice(index, 1);
|
|
549
548
|
await stage.remove({
|
|
@@ -568,36 +567,42 @@ var Editor = class extends BaseService_default {
|
|
|
568
567
|
stage.select(newConfig.id);
|
|
569
568
|
this.addModifiedNodeId(target.id);
|
|
570
569
|
this.addModifiedNodeId(parent.id);
|
|
571
|
-
this.
|
|
570
|
+
this.pushOpHistory("update", { updatedItems: [{
|
|
571
|
+
oldNode: oldSourceParent,
|
|
572
|
+
newNode: cloneDeep(toRaw(parent))
|
|
573
|
+
}, {
|
|
574
|
+
oldNode: oldTarget,
|
|
575
|
+
newNode: cloneDeep(toRaw(target))
|
|
576
|
+
}] }, {
|
|
577
|
+
name: pageForOp?.name || "",
|
|
578
|
+
id: pageForOp.id
|
|
579
|
+
});
|
|
572
580
|
return newConfig;
|
|
573
581
|
}
|
|
574
582
|
}
|
|
575
583
|
async dragTo(config, targetParent, targetIndex) {
|
|
584
|
+
this.captureSelectionBeforeOp();
|
|
576
585
|
if (!targetParent || !Array.isArray(targetParent.items)) return;
|
|
577
586
|
const configs = Array.isArray(config) ? config : [config];
|
|
578
|
-
const
|
|
579
|
-
const
|
|
587
|
+
const beforeSnapshots = /* @__PURE__ */ new Map();
|
|
588
|
+
for (const cfg of configs) {
|
|
589
|
+
const { parent } = this.getNodeInfo(cfg.id, false);
|
|
590
|
+
if (parent && !beforeSnapshots.has(`${parent.id}`)) beforeSnapshots.set(`${parent.id}`, cloneDeep(toRaw(parent)));
|
|
591
|
+
}
|
|
592
|
+
if (!beforeSnapshots.has(`${targetParent.id}`)) beforeSnapshots.set(`${targetParent.id}`, cloneDeep(toRaw(targetParent)));
|
|
580
593
|
const newLayout = await this.getLayout(targetParent);
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
if (typeof index !== "number" || index === -1) return;
|
|
589
|
-
sourceIndicesInTargetParent.push(index);
|
|
590
|
-
} else {
|
|
591
|
-
if (newLayout !== await this.getLayout(parent)) setLayout(config, newLayout);
|
|
592
|
-
parent.items?.splice(index, 1);
|
|
593
|
-
sourceOutTargetParent.push(config);
|
|
594
|
-
this.addModifiedNodeId(parent.id);
|
|
595
|
-
}
|
|
594
|
+
const { sameParentIndices, crossParentConfigs, aborted } = classifyDragSources(configs, targetParent, (id, raw) => this.getNodeInfo(id, raw));
|
|
595
|
+
if (aborted) return;
|
|
596
|
+
for (const { config: crossConfig, parent } of crossParentConfigs) {
|
|
597
|
+
if (newLayout !== await this.getLayout(parent)) setLayout(crossConfig, newLayout);
|
|
598
|
+
const index = getNodeIndex(crossConfig.id, parent);
|
|
599
|
+
parent.items?.splice(index, 1);
|
|
600
|
+
this.addModifiedNodeId(parent.id);
|
|
596
601
|
}
|
|
597
|
-
moveItemsInContainer(
|
|
598
|
-
|
|
599
|
-
targetParent.items?.splice(targetIndex + index, 0,
|
|
600
|
-
this.addModifiedNodeId(
|
|
602
|
+
moveItemsInContainer(sameParentIndices, targetParent, targetIndex);
|
|
603
|
+
crossParentConfigs.forEach(({ config: crossConfig }, index) => {
|
|
604
|
+
targetParent.items?.splice(targetIndex + index, 0, crossConfig);
|
|
605
|
+
this.addModifiedNodeId(crossConfig.id);
|
|
601
606
|
});
|
|
602
607
|
const page = this.get("page");
|
|
603
608
|
const root = this.get("root");
|
|
@@ -607,7 +612,19 @@ var Editor = class extends BaseService_default {
|
|
|
607
612
|
parentId: root.id,
|
|
608
613
|
root: cloneDeep(root)
|
|
609
614
|
});
|
|
610
|
-
|
|
615
|
+
const updatedItems = [];
|
|
616
|
+
for (const oldNode of beforeSnapshots.values()) {
|
|
617
|
+
const newNode = this.getNodeById(oldNode.id, false);
|
|
618
|
+
if (newNode) updatedItems.push({
|
|
619
|
+
oldNode,
|
|
620
|
+
newNode: cloneDeep(toRaw(newNode))
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
const pageForOp = this.getNodeInfo(configs[0].id, false).page;
|
|
624
|
+
this.pushOpHistory("update", { updatedItems }, {
|
|
625
|
+
name: pageForOp?.name || "",
|
|
626
|
+
id: pageForOp.id
|
|
627
|
+
});
|
|
611
628
|
this.emit("drag-to", {
|
|
612
629
|
targetIndex,
|
|
613
630
|
configs,
|
|
@@ -616,56 +633,32 @@ var Editor = class extends BaseService_default {
|
|
|
616
633
|
}
|
|
617
634
|
/**
|
|
618
635
|
* 撤销当前操作
|
|
619
|
-
* @returns
|
|
636
|
+
* @returns 被撤销的操作
|
|
620
637
|
*/
|
|
621
638
|
async undo() {
|
|
622
639
|
const value = history_default.undo();
|
|
623
|
-
await this.
|
|
640
|
+
if (value) await this.applyHistoryOp(value, true);
|
|
624
641
|
return value;
|
|
625
642
|
}
|
|
626
643
|
/**
|
|
627
644
|
* 恢复到下一步
|
|
628
|
-
* @returns
|
|
645
|
+
* @returns 被恢复的操作
|
|
629
646
|
*/
|
|
630
647
|
async redo() {
|
|
631
648
|
const value = history_default.redo();
|
|
632
|
-
await this.
|
|
649
|
+
if (value) await this.applyHistoryOp(value, false);
|
|
633
650
|
return value;
|
|
634
651
|
}
|
|
635
652
|
async move(left, top) {
|
|
636
653
|
const node = toRaw(this.get("node"));
|
|
637
654
|
if (!node || isPage(node)) return;
|
|
638
|
-
const
|
|
639
|
-
if (!
|
|
640
|
-
|
|
641
|
-
id,
|
|
642
|
-
type,
|
|
643
|
-
style
|
|
655
|
+
const newStyle = calcMoveStyle(node.style || {}, left, top);
|
|
656
|
+
if (!newStyle) return;
|
|
657
|
+
await this.update({
|
|
658
|
+
id: node.id,
|
|
659
|
+
type: node.type,
|
|
660
|
+
style: newStyle
|
|
644
661
|
});
|
|
645
|
-
if (top) {
|
|
646
|
-
if (isNumber(style.top)) update({
|
|
647
|
-
...style,
|
|
648
|
-
top: Number(style.top) + Number(top),
|
|
649
|
-
bottom: ""
|
|
650
|
-
});
|
|
651
|
-
else if (isNumber(style.bottom)) update({
|
|
652
|
-
...style,
|
|
653
|
-
bottom: Number(style.bottom) - Number(top),
|
|
654
|
-
top: ""
|
|
655
|
-
});
|
|
656
|
-
}
|
|
657
|
-
if (left) {
|
|
658
|
-
if (isNumber(style.left)) update({
|
|
659
|
-
...style,
|
|
660
|
-
left: Number(style.left) + Number(left),
|
|
661
|
-
right: ""
|
|
662
|
-
});
|
|
663
|
-
else if (isNumber(style.right)) update({
|
|
664
|
-
...style,
|
|
665
|
-
right: Number(style.right) - Number(left),
|
|
666
|
-
left: ""
|
|
667
|
-
});
|
|
668
|
-
}
|
|
669
662
|
}
|
|
670
663
|
resetState() {
|
|
671
664
|
this.set("root", null);
|
|
@@ -701,50 +694,74 @@ var Editor = class extends BaseService_default {
|
|
|
701
694
|
addModifiedNodeId(id) {
|
|
702
695
|
if (!this.isHistoryStateChange) this.get("modifiedNodeIds").set(id, id);
|
|
703
696
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
697
|
+
captureSelectionBeforeOp() {
|
|
698
|
+
if (this.isHistoryStateChange || this.selectionBeforeOp) return;
|
|
699
|
+
this.selectionBeforeOp = this.get("nodes").map((n) => n.id);
|
|
700
|
+
}
|
|
701
|
+
pushOpHistory(opType, extra, pageData) {
|
|
702
|
+
if (this.isHistoryStateChange) {
|
|
703
|
+
this.selectionBeforeOp = null;
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
const step = {
|
|
707
|
+
data: pageData,
|
|
708
|
+
opType,
|
|
709
|
+
selectedBefore: this.selectionBeforeOp ?? [],
|
|
710
|
+
selectedAfter: this.get("nodes").map((n) => n.id),
|
|
711
|
+
modifiedNodeIds: new Map(this.get("modifiedNodeIds")),
|
|
712
|
+
...extra
|
|
713
|
+
};
|
|
714
|
+
history_default.push(step);
|
|
715
|
+
this.selectionBeforeOp = null;
|
|
712
716
|
this.isHistoryStateChange = false;
|
|
713
717
|
}
|
|
714
|
-
|
|
715
|
-
|
|
718
|
+
/**
|
|
719
|
+
* 应用历史操作(撤销 / 重做)
|
|
720
|
+
* @param step 操作记录
|
|
721
|
+
* @param reverse true = 撤销,false = 重做
|
|
722
|
+
*/
|
|
723
|
+
async applyHistoryOp(step, reverse) {
|
|
716
724
|
this.isHistoryStateChange = true;
|
|
717
|
-
|
|
718
|
-
this.
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
725
|
+
const root = this.get("root");
|
|
726
|
+
const stage = this.get("stage");
|
|
727
|
+
if (!root) return;
|
|
728
|
+
const ctx = {
|
|
729
|
+
root,
|
|
730
|
+
stage,
|
|
731
|
+
getNodeById: (id, raw) => this.getNodeById(id, raw),
|
|
732
|
+
getNodeInfo: (id, raw) => this.getNodeInfo(id, raw),
|
|
733
|
+
setRoot: (r) => this.set("root", r),
|
|
734
|
+
setPage: (p) => this.set("page", p),
|
|
735
|
+
getPage: () => this.get("page")
|
|
736
|
+
};
|
|
737
|
+
switch (step.opType) {
|
|
738
|
+
case "add":
|
|
739
|
+
await applyHistoryAddOp(step, reverse, ctx);
|
|
740
|
+
break;
|
|
741
|
+
case "remove":
|
|
742
|
+
await applyHistoryRemoveOp(step, reverse, ctx);
|
|
743
|
+
break;
|
|
744
|
+
case "update":
|
|
745
|
+
await applyHistoryUpdateOp(step, reverse, ctx);
|
|
746
|
+
break;
|
|
732
747
|
}
|
|
733
|
-
|
|
748
|
+
this.set("modifiedNodeIds", step.modifiedNodeIds);
|
|
749
|
+
const page = toRaw(this.get("page"));
|
|
750
|
+
if (page) {
|
|
751
|
+
const selectIds = reverse ? step.selectedBefore : step.selectedAfter;
|
|
752
|
+
setTimeout(() => {
|
|
753
|
+
if (!selectIds.length) return;
|
|
754
|
+
if (selectIds.length > 1) {
|
|
755
|
+
this.multiSelect(selectIds);
|
|
756
|
+
stage?.multiSelect(selectIds);
|
|
757
|
+
} else this.select(selectIds[0]).then(() => stage?.select(selectIds[0])).catch(() => {});
|
|
758
|
+
}, 0);
|
|
759
|
+
this.emit("history-change", page);
|
|
760
|
+
}
|
|
761
|
+
this.isHistoryStateChange = false;
|
|
734
762
|
}
|
|
735
763
|
selectedConfigExceptionHandler(config) {
|
|
736
|
-
|
|
737
|
-
if (typeof config === "string" || typeof config === "number") id = config;
|
|
738
|
-
else id = config.id;
|
|
739
|
-
if (!id) throw new Error("没有ID,无法选中");
|
|
740
|
-
const { node, parent, page } = this.getNodeInfo(id);
|
|
741
|
-
if (!node) throw new Error("获取不到组件信息");
|
|
742
|
-
if (node.id === this.state.root?.id) throw new Error("不能选根节点");
|
|
743
|
-
return {
|
|
744
|
-
node,
|
|
745
|
-
parent,
|
|
746
|
-
page
|
|
747
|
-
};
|
|
764
|
+
return resolveSelectedNode(config, (id) => this.getNodeInfo(id), this.state.root?.id);
|
|
748
765
|
}
|
|
749
766
|
};
|
|
750
767
|
var editor_default = new Editor();
|
|
@@ -25,15 +25,7 @@ var History = class extends BaseService_default {
|
|
|
25
25
|
changePage(page) {
|
|
26
26
|
if (!page) return;
|
|
27
27
|
this.state.pageId = page.id;
|
|
28
|
-
if (!this.state.pageSteps[this.state.pageId])
|
|
29
|
-
const undoRedo = new UndoRedo();
|
|
30
|
-
undoRedo.pushElement({
|
|
31
|
-
data: page,
|
|
32
|
-
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
33
|
-
nodeId: page.id
|
|
34
|
-
});
|
|
35
|
-
this.state.pageSteps[this.state.pageId] = undoRedo;
|
|
36
|
-
}
|
|
28
|
+
if (!this.state.pageSteps[this.state.pageId]) this.state.pageSteps[this.state.pageId] = new UndoRedo();
|
|
37
29
|
this.setCanUndoRedo();
|
|
38
30
|
this.emit("page-change", this.state.pageSteps[this.state.pageId]);
|
|
39
31
|
}
|
package/dist/es/services/ui.js
CHANGED
package/dist/es/type.js
CHANGED
|
@@ -86,5 +86,32 @@ var DragType = /* @__PURE__ */ function(DragType) {
|
|
|
86
86
|
DragType["LAYER_TREE"] = "layer-tree";
|
|
87
87
|
return DragType;
|
|
88
88
|
}({});
|
|
89
|
+
var canUsePluginMethods = {
|
|
90
|
+
async: [
|
|
91
|
+
"getLayout",
|
|
92
|
+
"highlight",
|
|
93
|
+
"select",
|
|
94
|
+
"multiSelect",
|
|
95
|
+
"doAdd",
|
|
96
|
+
"add",
|
|
97
|
+
"doRemove",
|
|
98
|
+
"remove",
|
|
99
|
+
"doUpdate",
|
|
100
|
+
"update",
|
|
101
|
+
"sort",
|
|
102
|
+
"copy",
|
|
103
|
+
"paste",
|
|
104
|
+
"doPaste",
|
|
105
|
+
"doAlignCenter",
|
|
106
|
+
"alignCenter",
|
|
107
|
+
"moveLayer",
|
|
108
|
+
"moveToContainer",
|
|
109
|
+
"dragTo",
|
|
110
|
+
"undo",
|
|
111
|
+
"redo",
|
|
112
|
+
"move"
|
|
113
|
+
],
|
|
114
|
+
sync: []
|
|
115
|
+
};
|
|
89
116
|
//#endregion
|
|
90
|
-
export { CODE_DRAFT_STORAGE_KEY, CodeDeleteErrorType, ColumnLayout, DragType, KeyBindingCommand, Keys, LayerOffset, Layout, SideItemKey };
|
|
117
|
+
export { CODE_DRAFT_STORAGE_KEY, CodeDeleteErrorType, ColumnLayout, DragType, KeyBindingCommand, Keys, LayerOffset, Layout, SideItemKey, canUsePluginMethods };
|