@tmagic/editor 1.7.13-beta.0 → 1.7.14-beta.0
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 +17 -3
- package/dist/es/components/Tree.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/es/components/TreeNode.vue_vue_type_script_setup_true_lang.js +8 -3
- package/dist/es/editorProps.js +1 -0
- package/dist/es/hooks/use-stage.js +5 -0
- package/dist/es/initService.js +3 -0
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +10 -3
- package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +18 -5
- package/dist/es/layouts/sidebar/layer/use-click.js +22 -3
- package/dist/es/layouts/sidebar/layer/use-drag.js +28 -6
- package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +13 -2
- package/dist/es/services/editor.js +2 -1
- package/dist/es/services/props.js +12 -0
- package/dist/es/utils/dep/worker.js +1 -1
- package/dist/tmagic-editor.umd.cjs +141 -27
- package/package.json +7 -7
- package/src/Editor.vue +15 -0
- package/src/components/Tree.vue +1 -0
- package/src/components/TreeNode.vue +6 -1
- package/src/editorProps.ts +20 -0
- package/src/hooks/use-stage.ts +9 -0
- package/src/initService.ts +10 -0
- package/src/layouts/sidebar/Sidebar.vue +15 -0
- package/src/layouts/sidebar/layer/LayerPanel.vue +26 -2
- package/src/layouts/sidebar/layer/use-click.ts +36 -3
- package/src/layouts/sidebar/layer/use-drag.ts +62 -6
- package/src/layouts/workspace/viewer/Stage.vue +24 -2
- package/src/services/editor.ts +1 -0
- package/src/services/props.ts +16 -0
- package/src/type.ts +44 -0
- package/types/index.d.ts +73 -4
|
@@ -4787,6 +4787,9 @@
|
|
|
4787
4787
|
});
|
|
4788
4788
|
this.emit("props-configs-change");
|
|
4789
4789
|
}
|
|
4790
|
+
getPropsConfigs() {
|
|
4791
|
+
return this.state.propsConfigMap;
|
|
4792
|
+
}
|
|
4790
4793
|
async fillConfig(config, labelWidth) {
|
|
4791
4794
|
return fillConfig(config, {
|
|
4792
4795
|
labelWidth: typeof labelWidth !== "function" ? labelWidth : "80px",
|
|
@@ -4809,11 +4812,17 @@
|
|
|
4809
4812
|
if (type === "area") return await this.getPropsConfig("button", data);
|
|
4810
4813
|
return cloneDeep(this.state.propsConfigMap[(0, _tmagic_utils.toLine)(type)] || await this.fillConfig([]));
|
|
4811
4814
|
}
|
|
4815
|
+
hasPropsConfig(type) {
|
|
4816
|
+
return !!this.state.propsConfigMap[(0, _tmagic_utils.toLine)(type)];
|
|
4817
|
+
}
|
|
4812
4818
|
setPropsValues(values) {
|
|
4813
4819
|
Object.keys(values).forEach((type) => {
|
|
4814
4820
|
this.setPropsValue((0, _tmagic_utils.toLine)(type), values[type]);
|
|
4815
4821
|
});
|
|
4816
4822
|
}
|
|
4823
|
+
getPropsValues() {
|
|
4824
|
+
return this.state.propsValueMap;
|
|
4825
|
+
}
|
|
4817
4826
|
/**
|
|
4818
4827
|
* 为指点类型组件设置组件初始值
|
|
4819
4828
|
* @param type 组件类型
|
|
@@ -4850,6 +4859,9 @@
|
|
|
4850
4859
|
...mergeWith({}, cloneDeep(this.state.propsValueMap[type] || {}), data)
|
|
4851
4860
|
};
|
|
4852
4861
|
}
|
|
4862
|
+
hasPropsValue(type) {
|
|
4863
|
+
return !!this.state.propsValueMap[(0, _tmagic_utils.toLine)(type)];
|
|
4864
|
+
}
|
|
4853
4865
|
createId(type) {
|
|
4854
4866
|
return `${type}_${(0, _tmagic_utils.guid)()}`;
|
|
4855
4867
|
}
|
|
@@ -5794,7 +5806,8 @@
|
|
|
5794
5806
|
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
5795
5807
|
pageLength: 0,
|
|
5796
5808
|
pageFragmentLength: 0,
|
|
5797
|
-
disabledMultiSelect: false
|
|
5809
|
+
disabledMultiSelect: false,
|
|
5810
|
+
alwaysMultiSelect: false
|
|
5798
5811
|
});
|
|
5799
5812
|
isHistoryStateChange = false;
|
|
5800
5813
|
selectionBeforeOp = null;
|
|
@@ -6670,6 +6683,7 @@
|
|
|
6670
6683
|
zoom: stageOptions.zoom ?? zoom.value,
|
|
6671
6684
|
autoScrollIntoView: stageOptions.autoScrollIntoView,
|
|
6672
6685
|
isContainer: stageOptions.isContainer,
|
|
6686
|
+
canDropIn: stageOptions.canDropIn,
|
|
6673
6687
|
containerHighlightClassName: stageOptions.containerHighlightClassName,
|
|
6674
6688
|
containerHighlightDuration: stageOptions.containerHighlightDuration,
|
|
6675
6689
|
containerHighlightType: stageOptions.containerHighlightType,
|
|
@@ -6688,12 +6702,16 @@
|
|
|
6688
6702
|
updateDragEl: stageOptions.updateDragEl,
|
|
6689
6703
|
guidesOptions: stageOptions.guidesOptions,
|
|
6690
6704
|
disabledMultiSelect: stageOptions.disabledMultiSelect,
|
|
6705
|
+
alwaysMultiSelect: stageOptions.alwaysMultiSelect,
|
|
6691
6706
|
disabledRule: stageOptions.disabledRule
|
|
6692
6707
|
});
|
|
6693
6708
|
(0, vue.watch)(() => editor_default.get("disabledMultiSelect"), (disabledMultiSelect) => {
|
|
6694
6709
|
if (disabledMultiSelect) stage.disableMultiSelect();
|
|
6695
6710
|
else stage.enableMultiSelect();
|
|
6696
6711
|
});
|
|
6712
|
+
(0, vue.watch)(() => editor_default.get("alwaysMultiSelect"), (alwaysMultiSelect) => {
|
|
6713
|
+
stage.setAlwaysMultiSelect(Boolean(alwaysMultiSelect));
|
|
6714
|
+
});
|
|
6697
6715
|
const hGuidesCache = getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY));
|
|
6698
6716
|
const vGuidesCache = getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY));
|
|
6699
6717
|
stage.mask?.setGuides([hGuidesCache, vGuidesCache]);
|
|
@@ -9874,7 +9892,8 @@
|
|
|
9874
9892
|
"node-dragend",
|
|
9875
9893
|
"node-contextmenu",
|
|
9876
9894
|
"node-mouseenter",
|
|
9877
|
-
"node-click"
|
|
9895
|
+
"node-click",
|
|
9896
|
+
"node-dblclick"
|
|
9878
9897
|
],
|
|
9879
9898
|
setup(__props, { emit: __emit }) {
|
|
9880
9899
|
const treeEmit = (0, vue.inject)("treeEmit");
|
|
@@ -9910,6 +9929,9 @@
|
|
|
9910
9929
|
const nodeClickHandler = (event) => {
|
|
9911
9930
|
treeEmit?.("node-click", event, props.data);
|
|
9912
9931
|
};
|
|
9932
|
+
const nodeDblclickHandler = (event) => {
|
|
9933
|
+
treeEmit?.("node-dblclick", event, props.data);
|
|
9934
|
+
};
|
|
9913
9935
|
return (_ctx, _cache) => {
|
|
9914
9936
|
const _component_TreeNode = (0, vue.resolveComponent)("TreeNode", true);
|
|
9915
9937
|
return (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
@@ -9937,8 +9959,9 @@
|
|
|
9937
9959
|
onClick: expandHandler
|
|
9938
9960
|
}, null, 8, ["style", "icon"]), (0, vue.createElementVNode)("div", {
|
|
9939
9961
|
class: "tree-node-content",
|
|
9940
|
-
onClick: nodeClickHandler
|
|
9941
|
-
|
|
9962
|
+
onClick: nodeClickHandler,
|
|
9963
|
+
onDblclick: nodeDblclickHandler
|
|
9964
|
+
}, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-content", { data: __props.data }, () => [(0, vue.createElementVNode)("div", _hoisted_2$15, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-label", { data: __props.data }, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)(`${__props.data.name} (${__props.data.id})`), 1)])]), (0, vue.createElementVNode)("div", _hoisted_3$4, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-tool", { data: __props.data })])])], 32)], 38), __props.isExpandable(__props.data, __props.nodeStatusMap) && expanded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$3, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.data.items, (item) => {
|
|
9942
9965
|
return (0, vue.openBlock)(), (0, vue.createBlock)(_component_TreeNode, {
|
|
9943
9966
|
key: item.id,
|
|
9944
9967
|
data: item,
|
|
@@ -9991,7 +10014,8 @@
|
|
|
9991
10014
|
"node-dragend",
|
|
9992
10015
|
"node-contextmenu",
|
|
9993
10016
|
"node-mouseenter",
|
|
9994
|
-
"node-click"
|
|
10017
|
+
"node-click",
|
|
10018
|
+
"node-dblclick"
|
|
9995
10019
|
],
|
|
9996
10020
|
setup(__props, { emit: __emit }) {
|
|
9997
10021
|
const emit = __emit;
|
|
@@ -11066,7 +11090,7 @@
|
|
|
11066
11090
|
//#endregion
|
|
11067
11091
|
//#region packages/editor/src/layouts/sidebar/layer/use-click.ts
|
|
11068
11092
|
var useClick = ({ editorService, stageOverlayService, uiService }, isCtrlKeyDown, nodeStatusMap, menuRef) => {
|
|
11069
|
-
const isMultiSelect = (0, vue.computed)(() => isCtrlKeyDown.value
|
|
11093
|
+
const isMultiSelect = (0, vue.computed)(() => !editorService.get("disabledMultiSelect") && (isCtrlKeyDown.value || editorService.get("alwaysMultiSelect")));
|
|
11070
11094
|
const select = async (data) => {
|
|
11071
11095
|
if (!data.id) throw new Error("没有id");
|
|
11072
11096
|
if (isMultiSelect.value) multiSelect(data);
|
|
@@ -11102,6 +11126,15 @@
|
|
|
11102
11126
|
editorService.get("stage")?.highlight(data.id);
|
|
11103
11127
|
stageOverlayService.get("stage")?.highlight(data.id);
|
|
11104
11128
|
};
|
|
11129
|
+
const isNodeCanSelect = async (data) => {
|
|
11130
|
+
const canSelect = stageOverlayService.get("stageOptions")?.canSelect;
|
|
11131
|
+
if (!canSelect) return true;
|
|
11132
|
+
const doc = editorService.get("stage")?.renderer?.contentWindow?.document;
|
|
11133
|
+
if (!doc) return true;
|
|
11134
|
+
const el = (0, _tmagic_utils.getElById)()(doc, data.id);
|
|
11135
|
+
if (!el) return true;
|
|
11136
|
+
return Boolean(await canSelect(el));
|
|
11137
|
+
};
|
|
11105
11138
|
const nodeClickHandler = (event, data) => {
|
|
11106
11139
|
if (!nodeStatusMap?.value) return;
|
|
11107
11140
|
if (uiService.get("uiSelectMode")) {
|
|
@@ -11109,13 +11142,23 @@
|
|
|
11109
11142
|
return;
|
|
11110
11143
|
}
|
|
11111
11144
|
if (data.items && data.items.length > 0 && !isMultiSelect.value) updateStatus(nodeStatusMap.value, data.id, { expand: true });
|
|
11112
|
-
(0, vue.nextTick)(() => {
|
|
11145
|
+
(0, vue.nextTick)(async () => {
|
|
11146
|
+
if (!await isNodeCanSelect(data)) return;
|
|
11113
11147
|
select(data);
|
|
11114
11148
|
});
|
|
11115
11149
|
};
|
|
11150
|
+
const nodeDblclickHandler = (event, data) => {
|
|
11151
|
+
if (!nodeStatusMap?.value) return;
|
|
11152
|
+
if (uiService.get("uiSelectMode")) return;
|
|
11153
|
+
if (data.items && data.items.length > 0) {
|
|
11154
|
+
const status = nodeStatusMap.value.get(data.id);
|
|
11155
|
+
updateStatus(nodeStatusMap.value, data.id, { expand: !status?.expand });
|
|
11156
|
+
}
|
|
11157
|
+
};
|
|
11116
11158
|
return {
|
|
11117
11159
|
menuRef,
|
|
11118
11160
|
nodeClickHandler,
|
|
11161
|
+
nodeDblclickHandler,
|
|
11119
11162
|
nodeContentMenuHandler(event, data) {
|
|
11120
11163
|
event.preventDefault();
|
|
11121
11164
|
const nodes = editorService.get("nodes") || [];
|
|
@@ -11153,7 +11196,7 @@
|
|
|
11153
11196
|
* dragover 属于目标节点
|
|
11154
11197
|
* 这些方法并不是同一个dom事件触发的
|
|
11155
11198
|
*/
|
|
11156
|
-
var useDrag = ({ editorService }) => {
|
|
11199
|
+
var useDrag = ({ editorService }, options = {}) => {
|
|
11157
11200
|
const handleDragStart = (event) => {
|
|
11158
11201
|
if (!event.dataTransfer || !event.target || !event.currentTarget) return;
|
|
11159
11202
|
const targetEl = getNodeEl(event.target);
|
|
@@ -11185,19 +11228,34 @@
|
|
|
11185
11228
|
if (parentsId.includes(`${nodeId}`) && i >= targetIdIndex) return;
|
|
11186
11229
|
}
|
|
11187
11230
|
}
|
|
11188
|
-
|
|
11231
|
+
let canDropInTarget = isContainer;
|
|
11232
|
+
let redirectedTargetId;
|
|
11233
|
+
if (canDropInTarget && options.canDropIn && nodeId && targetNodeId !== nodeId) {
|
|
11234
|
+
const result = options.canDropIn([nodeId], targetNodeId);
|
|
11235
|
+
if (result === false) canDropInTarget = false;
|
|
11236
|
+
else if (typeof result === "string" || typeof result === "number") redirectedTargetId = result;
|
|
11237
|
+
}
|
|
11238
|
+
let canDropAsSibling = true;
|
|
11239
|
+
const directParentId = parentsId?.[parentsId.length - 1];
|
|
11240
|
+
if (options.canDropIn && nodeId && directParentId && directParentId !== nodeId) {
|
|
11241
|
+
const siblingResult = options.canDropIn([nodeId], directParentId);
|
|
11242
|
+
if (siblingResult === false || typeof siblingResult === "string" || typeof siblingResult === "number") canDropAsSibling = false;
|
|
11243
|
+
}
|
|
11244
|
+
dragState.dropType = "";
|
|
11245
|
+
if (distance < targetHeight / 3 && canDropAsSibling) {
|
|
11189
11246
|
dragState.dropType = "before";
|
|
11190
11247
|
(0, _tmagic_utils.addClassName)(labelEl, globalThis.document, "drag-before");
|
|
11191
|
-
} else if (distance > targetHeight * 2 / 3) {
|
|
11248
|
+
} else if (distance > targetHeight * 2 / 3 && canDropAsSibling) {
|
|
11192
11249
|
dragState.dropType = "after";
|
|
11193
11250
|
(0, _tmagic_utils.addClassName)(labelEl, globalThis.document, "drag-after");
|
|
11194
|
-
} else if (
|
|
11251
|
+
} else if (canDropInTarget) {
|
|
11195
11252
|
dragState.dropType = "inner";
|
|
11196
11253
|
(0, _tmagic_utils.addClassName)(labelEl, globalThis.document, "drag-inner");
|
|
11197
11254
|
}
|
|
11198
11255
|
if (!dragState.dropType) return;
|
|
11199
11256
|
dragState.dragOverNodeId = targetNodeId;
|
|
11200
11257
|
dragState.container = event.currentTarget;
|
|
11258
|
+
dragState.redirectedTargetId = dragState.dropType === "inner" ? redirectedTargetId : void 0;
|
|
11201
11259
|
event.preventDefault();
|
|
11202
11260
|
};
|
|
11203
11261
|
const handleDragLeave = (event) => {
|
|
@@ -11219,10 +11277,16 @@
|
|
|
11219
11277
|
let targetParent = targetInfo.parent;
|
|
11220
11278
|
if (!targetParent || !targetNode) return;
|
|
11221
11279
|
let targetIndex = -1;
|
|
11222
|
-
if (Array.isArray(targetNode.items) && dragState.dropType === "inner") {
|
|
11280
|
+
if (Array.isArray(targetNode.items) && dragState.dropType === "inner") if (dragState.redirectedTargetId !== void 0) {
|
|
11281
|
+
const redirectedNode = editorService.getNodeInfo(dragState.redirectedTargetId, false).node;
|
|
11282
|
+
if (!redirectedNode || !Array.isArray(redirectedNode.items)) return;
|
|
11283
|
+
targetParent = redirectedNode;
|
|
11284
|
+
targetIndex = redirectedNode.items.length;
|
|
11285
|
+
} else {
|
|
11223
11286
|
targetIndex = targetNode.items.length;
|
|
11224
11287
|
targetParent = targetNode;
|
|
11225
|
-
}
|
|
11288
|
+
}
|
|
11289
|
+
else targetIndex = getNodeIndex(dragState.dragOverNodeId, targetParent);
|
|
11226
11290
|
if (dragState.dropType === "after") targetIndex += 1;
|
|
11227
11291
|
const selectedNodes = editorService.get("nodes");
|
|
11228
11292
|
if (selectedNodes.find((n) => `${n.id}` === `${node.id}`)) editorService.dragTo(selectedNodes, targetParent, targetIndex);
|
|
@@ -11231,6 +11295,7 @@
|
|
|
11231
11295
|
dragState.dragOverNodeId = "";
|
|
11232
11296
|
dragState.dropType = "";
|
|
11233
11297
|
dragState.container = null;
|
|
11298
|
+
dragState.redirectedTargetId = void 0;
|
|
11234
11299
|
};
|
|
11235
11300
|
return {
|
|
11236
11301
|
handleDragStart,
|
|
@@ -11457,9 +11522,14 @@
|
|
|
11457
11522
|
indent: {},
|
|
11458
11523
|
nextLevelIndentIncrement: {},
|
|
11459
11524
|
customContentMenu: { type: Function },
|
|
11460
|
-
isExpandable: { type: Function }
|
|
11525
|
+
isExpandable: { type: Function },
|
|
11526
|
+
canDropIn: { type: Function },
|
|
11527
|
+
beforeNodeDblclick: { type: Function }
|
|
11461
11528
|
},
|
|
11462
|
-
|
|
11529
|
+
emits: ["node-dblclick"],
|
|
11530
|
+
setup(__props, { emit: __emit }) {
|
|
11531
|
+
const props = __props;
|
|
11532
|
+
const emit = __emit;
|
|
11463
11533
|
const services = useServices();
|
|
11464
11534
|
const { editorService } = services;
|
|
11465
11535
|
const treeRef = (0, vue.useTemplateRef)("tree");
|
|
@@ -11482,8 +11552,15 @@
|
|
|
11482
11552
|
status.expand = false;
|
|
11483
11553
|
}
|
|
11484
11554
|
};
|
|
11485
|
-
const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useDrag(services);
|
|
11486
|
-
const { nodeClickHandler, nodeContentMenuHandler, highlightHandler: mouseenterHandler } = useClick(services, isCtrlKeyDown, nodeStatusMap, (0, vue.useTemplateRef)("menu"));
|
|
11555
|
+
const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useDrag(services, { canDropIn: (sourceIds, targetId) => props.canDropIn?.(sourceIds, targetId, "layer") });
|
|
11556
|
+
const { nodeClickHandler, nodeDblclickHandler, nodeContentMenuHandler, highlightHandler: mouseenterHandler } = useClick(services, isCtrlKeyDown, nodeStatusMap, (0, vue.useTemplateRef)("menu"));
|
|
11557
|
+
const dblclickHandler = async (event, data) => {
|
|
11558
|
+
if (props.beforeNodeDblclick) {
|
|
11559
|
+
if (await props.beforeNodeDblclick(event, data) === false) return;
|
|
11560
|
+
}
|
|
11561
|
+
nodeDblclickHandler(event, data);
|
|
11562
|
+
emit("node-dblclick", event, data);
|
|
11563
|
+
};
|
|
11487
11564
|
return (_ctx, _cache) => {
|
|
11488
11565
|
return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicScrollbar), { class: "m-editor-layer-panel" }, {
|
|
11489
11566
|
default: (0, vue.withCtx)(() => [
|
|
@@ -11504,7 +11581,8 @@
|
|
|
11504
11581
|
onNodeDragend: (0, vue.unref)(handleDragEnd),
|
|
11505
11582
|
onNodeContextmenu: (0, vue.unref)(nodeContentMenuHandler),
|
|
11506
11583
|
onNodeMouseenter: (0, vue.unref)(mouseenterHandler),
|
|
11507
|
-
onNodeClick: (0, vue.unref)(nodeClickHandler)
|
|
11584
|
+
onNodeClick: (0, vue.unref)(nodeClickHandler),
|
|
11585
|
+
onNodeDblclick: dblclickHandler
|
|
11508
11586
|
}, {
|
|
11509
11587
|
"tree-node-content": (0, vue.withCtx)(({ data: nodeData }) => [(0, vue.renderSlot)(_ctx.$slots, "layer-node-content", { data: nodeData })]),
|
|
11510
11588
|
"tree-node-tool": (0, vue.withCtx)(({ data: nodeData }) => [(0, vue.renderSlot)(_ctx.$slots, "layer-node-tool", { data: nodeData }, () => [(0, vue.createVNode)(LayerNodeTool_default, { data: nodeData }, null, 8, ["data"])])]),
|
|
@@ -11692,9 +11770,13 @@
|
|
|
11692
11770
|
indent: {},
|
|
11693
11771
|
nextLevelIndentIncrement: {},
|
|
11694
11772
|
customContentMenu: {},
|
|
11695
|
-
layerNodeIsExpandable: {}
|
|
11773
|
+
layerNodeIsExpandable: {},
|
|
11774
|
+
canDropIn: {},
|
|
11775
|
+
beforeLayerNodeDblclick: {}
|
|
11696
11776
|
},
|
|
11697
|
-
|
|
11777
|
+
emits: ["layer-node-dblclick"],
|
|
11778
|
+
setup(__props, { expose: __expose, emit: __emit }) {
|
|
11779
|
+
const emit = __emit;
|
|
11698
11780
|
const props = __props;
|
|
11699
11781
|
const { depService, uiService, propsService } = useServices();
|
|
11700
11782
|
const collecting = (0, vue.computed)(() => depService.get("collecting"));
|
|
@@ -11732,8 +11814,11 @@
|
|
|
11732
11814
|
customContentMenu: props.customContentMenu,
|
|
11733
11815
|
indent: props.indent,
|
|
11734
11816
|
nextLevelIndentIncrement: props.nextLevelIndentIncrement,
|
|
11735
|
-
isExpandable: props.layerNodeIsExpandable
|
|
11817
|
+
isExpandable: props.layerNodeIsExpandable,
|
|
11818
|
+
canDropIn: props.canDropIn,
|
|
11819
|
+
beforeNodeDblclick: props.beforeLayerNodeDblclick
|
|
11736
11820
|
},
|
|
11821
|
+
listeners: { "node-dblclick": (event, nodeData) => emit("layer-node-dblclick", event, nodeData) },
|
|
11737
11822
|
component: LayerPanel_default,
|
|
11738
11823
|
slots: {}
|
|
11739
11824
|
},
|
|
@@ -12638,9 +12723,20 @@
|
|
|
12638
12723
|
const doc = stage?.renderer?.contentWindow?.document;
|
|
12639
12724
|
const parentEl = doc?.querySelector(`.${props.stageOptions?.containerHighlightClassName}`);
|
|
12640
12725
|
let parent = page.value;
|
|
12726
|
+
let resolvedParentEl = parentEl;
|
|
12641
12727
|
const parentId = (0, _tmagic_utils.getIdFromEl)()(parentEl);
|
|
12642
12728
|
if (parentId) parent = editorService.getNodeById(parentId, false);
|
|
12643
12729
|
if (parent && stageContainerEl.value && stage) {
|
|
12730
|
+
if (props.stageOptions.canDropIn) {
|
|
12731
|
+
const result = props.stageOptions.canDropIn([], parent.id);
|
|
12732
|
+
if (result === false) return;
|
|
12733
|
+
if (typeof result === "string" || typeof result === "number") {
|
|
12734
|
+
const redirectedNode = editorService.getNodeById(result, false);
|
|
12735
|
+
if (!redirectedNode) return;
|
|
12736
|
+
parent = redirectedNode;
|
|
12737
|
+
resolvedParentEl = stage.renderer?.getTargetElement(result) ?? null;
|
|
12738
|
+
}
|
|
12739
|
+
}
|
|
12644
12740
|
const layout = await editorService.getLayout(parent);
|
|
12645
12741
|
const containerRect = stageContainerEl.value.getBoundingClientRect();
|
|
12646
12742
|
const { scrollTop, scrollLeft } = stage.mask;
|
|
@@ -12656,8 +12752,8 @@
|
|
|
12656
12752
|
position = "absolute";
|
|
12657
12753
|
top = e.clientY - containerRect.top + scrollTop;
|
|
12658
12754
|
left = e.clientX - containerRect.left + scrollLeft;
|
|
12659
|
-
if (
|
|
12660
|
-
const { left: parentLeft, top: parentTop } = (0, _tmagic_stage.getOffset)(
|
|
12755
|
+
if (resolvedParentEl) {
|
|
12756
|
+
const { left: parentLeft, top: parentTop } = (0, _tmagic_stage.getOffset)(resolvedParentEl);
|
|
12661
12757
|
left = left - parentLeft * zoom.value;
|
|
12662
12758
|
top = top - parentTop * zoom.value;
|
|
12663
12759
|
}
|
|
@@ -13295,7 +13391,7 @@
|
|
|
13295
13391
|
var dataSource_default = new DataSource();
|
|
13296
13392
|
//#endregion
|
|
13297
13393
|
//#region packages/editor/src/utils/dep/worker.ts?worker&inline
|
|
13298
|
-
var jsContent = "(function() {\n //#region packages/schema/src/index.ts\n const NODE_CONDS_KEY = \"displayConds\";\n const NODE_DISABLE_DATA_SOURCE_KEY = \"_tmagic_node_disabled_data_source\";\n const NODE_DISABLE_CODE_BLOCK_KEY = \"_tmagic_node_disabled_code_block\";\n let HookType = /* @__PURE__ */ function(HookType) {\n /** 代码块钩子标识 */\n HookType[\"CODE\"] = \"code\";\n return HookType;\n }({});\n //#endregion\n //#region packages/utils/src/const.ts\n const DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX = \"ds-field::\";\n //#endregion\n //#region packages/utils/src/index.ts\n const isObject = (obj) => Object.prototype.toString.call(obj) === \"[object Object]\";\n const getKeysArray = (keys) => `${keys}`.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\");\n const dataSourceTemplateRegExp = /\\$\\{([\\s\\S]+?)\\}/g;\n //#endregion\n //#region packages/dep/src/types.ts\n /** 依赖收集的目标类型 */\n let DepTargetType = /* @__PURE__ */ function(DepTargetType) {\n DepTargetType[\"DEFAULT\"] = \"default\";\n /** 代码块 */\n DepTargetType[\"CODE_BLOCK\"] = \"code-block\";\n /** 数据源 */\n DepTargetType[\"DATA_SOURCE\"] = \"data-source\";\n /** 数据源方法 */\n DepTargetType[\"DATA_SOURCE_METHOD\"] = \"data-source-method\";\n /** 数据源条件 */\n DepTargetType[\"DATA_SOURCE_COND\"] = \"data-source-cond\";\n return DepTargetType;\n }({});\n //#endregion\n //#region packages/dep/src/Target.ts\n /**\n * 需要收集依赖的目标\n * 例如:一个代码块可以为一个目标\n */\n var Target = class {\n /**\n * 如何识别目标\n */\n isTarget;\n /**\n * 目标id,不可重复\n * 例如目标是代码块,则为代码块id\n */\n id;\n /**\n * 目标名称,用于显示在依赖列表中\n */\n name;\n /**\n * 不同的目标可以进行分类,例如代码块,数据源可以为两个不同的type\n */\n type = DepTargetType.DEFAULT;\n /**\n * 依赖详情\n * 实例:{ 'node_id': { name: 'node_name', keys: [ created, mounted ] } }\n */\n deps = {};\n /**\n * 是否默认收集,默认为true,当值为false时需要传入type参数给collect方法才会被收集\n */\n isCollectByDefault;\n constructor(options) {\n this.isTarget = options.isTarget;\n this.id = options.id;\n this.name = options.name;\n this.isCollectByDefault = options.isCollectByDefault ?? true;\n if (options.type) this.type = options.type;\n if (options.initialDeps) this.deps = options.initialDeps;\n }\n /**\n * 更新依赖\n * @param option 节点配置\n * @param key 哪个key配置了这个目标的id\n */\n updateDep({ id, name, key, data }) {\n const dep = this.deps[id] || {\n name,\n keys: []\n };\n dep.name = name;\n dep.data = data;\n this.deps[id] = dep;\n if (!dep.keys.includes(key)) dep.keys.push(key);\n }\n /**\n * 删除依赖\n * @param node 哪个节点的依赖需要移除,如果为空,则移除所有依赖\n * @param key 节点下哪个key需要移除,如果为空,则移除改节点下的所有依赖key\n * @returns void\n */\n removeDep(id, key) {\n if (typeof id === \"undefined\") {\n Object.keys(this.deps).forEach((depKey) => {\n delete this.deps[depKey];\n });\n return;\n }\n const dep = this.deps[id];\n if (!dep) return;\n if (key) {\n const index = dep.keys.indexOf(key);\n dep.keys.splice(index, 1);\n if (dep.keys.length === 0) delete this.deps[id];\n } else delete this.deps[id];\n }\n /**\n * 判断指定节点下的指定key是否存在在依赖列表中\n * @param node 哪个节点\n * @param key 哪个key\n * @returns boolean\n */\n hasDep(id, key) {\n return this.deps[id]?.keys.includes(key) ?? false;\n }\n destroy() {\n this.deps = {};\n }\n };\n //#endregion\n //#region packages/dep/src/utils.ts\n const INTEGER_REGEXP = /^\\d+$/;\n const createCodeBlockTarget = (id, codeBlock, initialDeps = {}) => new Target({\n type: DepTargetType.CODE_BLOCK,\n id,\n initialDeps,\n name: codeBlock.name,\n isTarget: (_key, value) => {\n if (id === value) return true;\n if (value?.hookType === HookType.CODE && Array.isArray(value.hookData)) return value.hookData.some((item) => item.codeId === id);\n return false;\n }\n });\n /**\n * ['array'] ['array', '0'] ['array', '0', 'a'] 这种返回false\n * ['array', 'a'] 这种返回true\n * @param keys\n * @param fields\n * @returns boolean\n */\n const isIncludeArrayField = (keys, fields) => {\n let f = fields;\n return keys.some((key, index) => {\n const field = f.find(({ name }) => name === key);\n f = field?.fields || [];\n return field?.type === \"array\" && index < keys.length - 1 && !INTEGER_REGEXP.test(keys[index + 1]);\n });\n };\n /**\n * 判断模板(value)是不是使用数据源Id(dsId),如:`xxx${dsId.field}xxx${dsId.field}`\n * @param value any\n * @param dsId string | number\n * @param hasArray boolean true: 一定要包含有需要迭代的模板; false: 一定要包含普通模板;\n * @returns boolean\n */\n const isDataSourceTemplate = (value, ds, hasArray = false) => {\n const templates = value.match(dataSourceTemplateRegExp) || [];\n if (templates.length <= 0) return false;\n for (const tpl of templates) {\n const keys = getKeysArray(tpl.substring(2, tpl.length - 1));\n const dsId = keys.shift();\n if (!dsId || dsId !== ds.id) continue;\n if (hasArray === isIncludeArrayField(keys, ds.fields)) return true;\n }\n return false;\n };\n /**\n * 指定数据源的字符串模板,如:{ isBindDataSourceField: true, dataSourceId: 'id', template: `xxx${field}xxx`}\n * @param value any\n * @param dsId string | number\n * @returns boolean\n */\n const isSpecificDataSourceTemplate = (value, dsId) => value?.isBindDataSourceField && value.dataSourceId && value.dataSourceId === dsId && typeof value.template === \"string\";\n /**\n * 关联数据源字段,格式为 [前缀+数据源ID, 字段名]\n * 使用data-source-field-select value: 'value' 可以配置出来\n * @param value any[]\n * @param id string | number\n * @returns boolean\n */\n const isUseDataSourceField = (value, id) => {\n if (!Array.isArray(value) || typeof value[0] !== \"string\") return false;\n const [prefixId] = value;\n const prefixIndex = prefixId.indexOf(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX);\n if (prefixIndex === -1) return false;\n return prefixId.substring(prefixIndex + DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX.length) === id;\n };\n const isDataSourceTarget = (ds, key, value, hasArray = false) => {\n if (!value) return false;\n const valueType = typeof value;\n if (valueType !== \"string\" && valueType !== \"object\") return false;\n if (`${key}`.startsWith(\"displayConds\")) return false;\n if (valueType === \"string\") return isDataSourceTemplate(value, ds, hasArray);\n if (isObject(value) && value.isBindDataSource && value.dataSourceId === ds.id) return true;\n if (isSpecificDataSourceTemplate(value, ds.id)) return true;\n if (isUseDataSourceField(value, ds.id)) {\n const [, ...keys] = value;\n const includeArray = isIncludeArrayField(keys, ds.fields);\n return hasArray ? includeArray : !includeArray;\n }\n return false;\n };\n const isDataSourceCondTarget = (ds, key, value, hasArray = false) => {\n if (!Array.isArray(value) || !ds) return false;\n const [dsId, ...keys] = value;\n if (dsId !== ds.id || !`${key}`.startsWith(\"displayConds\")) return false;\n if (ds.fields?.some((field) => field.name === keys[0])) {\n const includeArray = isIncludeArrayField(keys, ds.fields);\n return hasArray ? includeArray : !includeArray;\n }\n return false;\n };\n const createDataSourceTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE,\n id: ds.id,\n initialDeps,\n isTarget: (key, value) => isDataSourceTarget(ds, key, value)\n });\n const createDataSourceCondTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE_COND,\n id: ds.id,\n initialDeps,\n isTarget: (key, value) => isDataSourceCondTarget(ds, key, value)\n });\n const createDataSourceMethodTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE_METHOD,\n id: ds.id,\n initialDeps,\n isTarget: (_key, value) => {\n if (!Array.isArray(value)) return false;\n const [dsId, methodName] = value;\n if (!methodName || dsId !== ds.id) return false;\n if (ds.methods?.some((method) => method.name === methodName)) return true;\n if (ds.fields?.some((field) => field.name === methodName)) return false;\n return true;\n }\n });\n const traverseTarget = (targetsList, cb, type) => {\n if (type) {\n const targets = targetsList[type];\n if (targets) for (const target of Object.values(targets)) cb(target);\n return;\n }\n for (const targets of Object.values(targetsList)) for (const target of Object.values(targets)) cb(target);\n };\n //#endregion\n //#region packages/dep/src/Watcher.ts\n const DATA_SOURCE_TARGET_TYPES = new Set([\n DepTargetType.DATA_SOURCE,\n DepTargetType.DATA_SOURCE_COND,\n DepTargetType.DATA_SOURCE_METHOD\n ]);\n var Watcher = class {\n targetsList = {};\n childrenProp = \"items\";\n idProp = \"id\";\n nameProp = \"name\";\n constructor(options) {\n if (options?.initialTargets) this.targetsList = options.initialTargets;\n if (options?.childrenProp) this.childrenProp = options.childrenProp;\n }\n getTargetsList() {\n return this.targetsList;\n }\n /**\n * 获取指定类型中的所有target\n * @param type 分类\n * @returns Target[]\n */\n getTargets(type = DepTargetType.DEFAULT) {\n return this.targetsList[type] || {};\n }\n /**\n * 添加新的目标\n * @param target Target\n */\n addTarget(target) {\n const targets = this.getTargets(target.type) || {};\n this.targetsList[target.type] = targets;\n targets[target.id] = target;\n }\n /**\n * 获取指定id的target\n * @param id target id\n * @returns Target\n */\n getTarget(id, type = DepTargetType.DEFAULT) {\n return this.getTargets(type)[id];\n }\n /**\n * 判断是否存在指定id的target\n * @param id target id\n * @returns boolean\n */\n hasTarget(id, type = DepTargetType.DEFAULT) {\n return Boolean(this.getTarget(id, type));\n }\n /**\n * 判断是否存在指定类型的target\n * @param type target type\n * @returns boolean\n */\n hasSpecifiedTypeTarget(type = DepTargetType.DEFAULT) {\n return Object.keys(this.getTargets(type)).length > 0;\n }\n /**\n * 删除指定id的target\n * @param id target id\n */\n removeTarget(id, type = DepTargetType.DEFAULT) {\n const targets = this.getTargets(type);\n if (targets[id]) {\n targets[id].destroy();\n delete targets[id];\n }\n }\n /**\n * 删除指定分类的所有target\n * @param type 分类\n * @returns void\n */\n removeTargets(type = DepTargetType.DEFAULT) {\n const targets = this.targetsList[type];\n if (!targets) return;\n for (const target of Object.values(targets)) target.destroy();\n delete this.targetsList[type];\n }\n /**\n * 删除所有target\n */\n clearTargets() {\n for (const key of Object.keys(this.targetsList)) delete this.targetsList[key];\n }\n /**\n * 收集依赖\n * @param nodes 需要收集的节点\n * @param deep 是否需要收集子节点\n * @param type 强制收集指定类型的依赖\n */\n collect(nodes, depExtendedData = {}, deep = false, type) {\n this.collectByCallback(nodes, type, ({ node, target }) => {\n this.removeTargetDep(target, node);\n this.collectItem(node, target, depExtendedData, deep);\n });\n }\n collectByCallback(nodes, type, cb) {\n traverseTarget(this.targetsList, (target) => {\n if (!type && !target.isCollectByDefault) return;\n for (const node of nodes) cb({\n node,\n target\n });\n }, type);\n }\n /**\n * 清除所有目标的依赖\n * @param nodes 需要清除依赖的节点\n */\n clear(nodes, type) {\n let { targetsList } = this;\n if (type) targetsList = { [type]: this.getTargets(type) };\n const clearedItemsNodeIds = /* @__PURE__ */ new Set();\n traverseTarget(targetsList, (target) => {\n if (nodes) for (const node of nodes) {\n target.removeDep(node[this.idProp]);\n if (Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length && !clearedItemsNodeIds.has(node[this.idProp])) {\n clearedItemsNodeIds.add(node[this.idProp]);\n this.clear(node[this.childrenProp]);\n }\n }\n else target.removeDep();\n });\n }\n /**\n * 清除指定类型的依赖\n * @param type 类型\n * @param nodes 需要清除依赖的节点\n */\n clearByType(type, nodes) {\n this.clear(nodes, type);\n }\n collectItem(node, target, depExtendedData = {}, deep = false) {\n if (node[\"_tmagic_node_disabled_data_source\"] && DATA_SOURCE_TARGET_TYPES.has(target.type)) return;\n if (node[\"_tmagic_node_disabled_code_block\"] && target.type === DepTargetType.CODE_BLOCK) return;\n const collectTarget = (config, prop = \"\") => {\n const doCollect = (key, value) => {\n const keyIsItems = key === this.childrenProp;\n const fullKey = prop ? `${prop}.${key}` : key;\n if (target.isTarget(fullKey, value)) target.updateDep({\n id: node[this.idProp],\n name: `${node[this.nameProp] || node[this.idProp]}`,\n data: depExtendedData,\n key: fullKey\n });\n else if (!keyIsItems && Array.isArray(value)) for (let i = 0, l = value.length; i < l; i++) {\n const item = value[i];\n if (isObject(item)) collectTarget(item, `${fullKey}[${i}]`);\n }\n else if (isObject(value)) collectTarget(value, fullKey);\n if (keyIsItems && deep && Array.isArray(value)) for (const child of value) this.collectItem(child, target, depExtendedData, deep);\n };\n for (const [key, value] of Object.entries(config)) {\n if (typeof value === \"undefined\" || value === \"\") continue;\n doCollect(key, value);\n }\n };\n collectTarget(node);\n }\n removeTargetDep(target, node, key) {\n target.removeDep(node[this.idProp], key);\n if (typeof key === \"undefined\" && Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length) for (const item of node[this.childrenProp]) this.removeTargetDep(target, item, key);\n }\n };\n //#endregion\n //#region packages/editor/src/utils/logger.ts\n const error = (...args) => {\n console.error(\"magic editor: \", ...args);\n };\n //#endregion\n //#region packages/editor/src/utils/dep/worker.ts\n onmessage = (e) => {\n const watcher = new Watcher({ initialTargets: {} });\n const { dsl } = e.data;\n try {\n const mApp = eval(`(${dsl})`);\n if (!mApp) postMessage({});\n watcher.clearTargets();\n if (mApp.codeBlocks) for (const [id, code] of Object.entries(mApp.codeBlocks)) watcher.addTarget(createCodeBlockTarget(id, code));\n if (mApp.dataSources) for (const ds of mApp.dataSources) {\n watcher.addTarget(createDataSourceTarget(ds, {}));\n watcher.addTarget(createDataSourceMethodTarget(ds, {}));\n watcher.addTarget(createDataSourceCondTarget(ds, {}));\n }\n watcher.collectByCallback(mApp.items, void 0, ({ node, target }) => {\n watcher.collectItem(node, target, { pageId: node.id }, true);\n });\n const data = {\n [DepTargetType.DATA_SOURCE]: {},\n [DepTargetType.DATA_SOURCE_METHOD]: {},\n [DepTargetType.DATA_SOURCE_COND]: {},\n [DepTargetType.CODE_BLOCK]: {}\n };\n traverseTarget(watcher.getTargetsList(), (target) => {\n data[target.type][target.id] = target.deps;\n });\n postMessage(data);\n } catch (e) {\n error(e);\n postMessage({});\n }\n };\n //#endregion\n})();\n";
|
|
13394
|
+
var jsContent = "(function() {\n //#region packages/schema/src/index.ts\n const NODE_CONDS_KEY = \"displayConds\";\n const NODE_DISABLE_DATA_SOURCE_KEY = \"_tmagic_node_disabled_data_source\";\n const NODE_DISABLE_CODE_BLOCK_KEY = \"_tmagic_node_disabled_code_block\";\n let HookType = /* @__PURE__ */ function(HookType) {\n /** 代码块钩子标识 */\n HookType[\"CODE\"] = \"code\";\n return HookType;\n }({});\n //#endregion\n //#region packages/utils/src/const.ts\n const DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX = \"ds-field::\";\n //#endregion\n //#region packages/utils/src/index.ts\n const isObject = (obj) => Object.prototype.toString.call(obj) === \"[object Object]\";\n const getKeysArray = (keys) => `${keys}`.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\");\n const dataSourceTemplateRegExp = /\\$\\{([\\s\\S]+?)\\}/g;\n //#endregion\n //#region packages/dep/src/types.ts\n /** 依赖收集的目标类型 */\n let DepTargetType = /* @__PURE__ */ function(DepTargetType) {\n DepTargetType[\"DEFAULT\"] = \"default\";\n /** 代码块 */\n DepTargetType[\"CODE_BLOCK\"] = \"code-block\";\n /** 数据源 */\n DepTargetType[\"DATA_SOURCE\"] = \"data-source\";\n /** 数据源方法 */\n DepTargetType[\"DATA_SOURCE_METHOD\"] = \"data-source-method\";\n /** 数据源条件 */\n DepTargetType[\"DATA_SOURCE_COND\"] = \"data-source-cond\";\n return DepTargetType;\n }({});\n //#endregion\n //#region packages/dep/src/Target.ts\n /**\n * 需要收集依赖的目标\n * 例如:一个代码块可以为一个目标\n */\n var Target = class {\n /**\n * 如何识别目标\n */\n isTarget;\n /**\n * 目标id,不可重复\n * 例如目标是代码块,则为代码块id\n */\n id;\n /**\n * 目标名称,用于显示在依赖列表中\n */\n name;\n /**\n * 不同的目标可以进行分类,例如代码块,数据源可以为两个不同的type\n */\n type = DepTargetType.DEFAULT;\n /**\n * 依赖详情\n * 实例:{ 'node_id': { name: 'node_name', keys: [ created, mounted ] } }\n */\n deps = {};\n /**\n * 是否默认收集,默认为true,当值为false时需要传入type参数给collect方法才会被收集\n */\n isCollectByDefault;\n constructor(options) {\n this.isTarget = options.isTarget;\n this.id = options.id;\n this.name = options.name;\n this.isCollectByDefault = options.isCollectByDefault ?? true;\n if (options.type) this.type = options.type;\n if (options.initialDeps) this.deps = options.initialDeps;\n }\n /**\n * 更新依赖\n * @param option 节点配置\n * @param key 哪个key配置了这个目标的id\n */\n updateDep({ id, name, key, data }) {\n const dep = this.deps[id] || {\n name,\n keys: []\n };\n dep.name = name;\n dep.data = data;\n this.deps[id] = dep;\n if (!dep.keys.includes(key)) dep.keys.push(key);\n }\n /**\n * 删除依赖\n * @param node 哪个节点的依赖需要移除,如果为空,则移除所有依赖\n * @param key 节点下哪个key需要移除,如果为空,则移除改节点下的所有依赖key\n * @returns void\n */\n removeDep(id, key) {\n if (typeof id === \"undefined\") {\n Object.keys(this.deps).forEach((depKey) => {\n delete this.deps[depKey];\n });\n return;\n }\n const dep = this.deps[id];\n if (!dep) return;\n if (key) {\n const index = dep.keys.indexOf(key);\n dep.keys.splice(index, 1);\n if (dep.keys.length === 0) delete this.deps[id];\n } else delete this.deps[id];\n }\n /**\n * 判断指定节点下的指定key是否存在在依赖列表中\n * @param node 哪个节点\n * @param key 哪个key\n * @returns boolean\n */\n hasDep(id, key) {\n return this.deps[id]?.keys.includes(key) ?? false;\n }\n destroy() {\n this.deps = {};\n }\n };\n //#endregion\n //#region packages/dep/src/utils.ts\n const INTEGER_REGEXP = /^\\d+$/;\n const createCodeBlockTarget = (id, codeBlock, initialDeps = {}) => new Target({\n type: DepTargetType.CODE_BLOCK,\n id,\n initialDeps,\n name: codeBlock.name,\n isTarget: (_key, value) => {\n if (id === value) return true;\n if (value?.hookType === HookType.CODE && Array.isArray(value.hookData)) return value.hookData.some((item) => item.codeId === id);\n return false;\n }\n });\n /**\n * ['array'] ['array', '0'] ['array', '0', 'a'] 这种返回false\n * ['array', 'a'] 这种返回true\n * @param keys\n * @param fields\n * @returns boolean\n */\n const isIncludeArrayField = (keys, fields) => {\n let f = fields;\n return keys.some((key, index) => {\n const field = f.find(({ name }) => name === key);\n f = field?.fields || [];\n return field?.type === \"array\" && index < keys.length - 1 && !INTEGER_REGEXP.test(keys[index + 1]);\n });\n };\n /**\n * 判断模板(value)是不是使用数据源Id(dsId),如:`xxx${dsId.field}xxx${dsId.field}`\n * @param value any\n * @param dsId string | number\n * @param hasArray boolean true: 一定要包含有需要迭代的模板; false: 一定要包含普通模板;\n * @returns boolean\n */\n const isDataSourceTemplate = (value, ds, hasArray = false) => {\n const templates = value.match(dataSourceTemplateRegExp) || [];\n if (templates.length <= 0) return false;\n for (const tpl of templates) {\n const keys = getKeysArray(tpl.substring(2, tpl.length - 1));\n const dsId = keys.shift();\n if (!dsId || dsId !== ds.id) continue;\n if (hasArray === isIncludeArrayField(keys, ds.fields)) return true;\n }\n return false;\n };\n /**\n * 指定数据源的字符串模板,如:{ isBindDataSourceField: true, dataSourceId: 'id', template: `xxx${field}xxx`}\n * @param value any\n * @param dsId string | number\n * @returns boolean\n */\n const isSpecificDataSourceTemplate = (value, dsId) => value?.isBindDataSourceField && value.dataSourceId && value.dataSourceId === dsId && typeof value.template === \"string\";\n /**\n * 关联数据源字段,格式为 [前缀+数据源ID, 字段名]\n * 使用data-source-field-select value: 'value' 可以配置出来\n * @param value any[]\n * @param id string | number\n * @returns boolean\n */\n const isUseDataSourceField = (value, id) => {\n if (!Array.isArray(value) || typeof value[0] !== \"string\") return false;\n const [prefixId] = value;\n const prefixIndex = prefixId.indexOf(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX);\n if (prefixIndex === -1) return false;\n return prefixId.substring(prefixIndex + DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX.length) === id;\n };\n const isDataSourceTarget = (ds, key, value, hasArray = false) => {\n if (!value) return false;\n const valueType = typeof value;\n if (valueType !== \"string\" && valueType !== \"object\") return false;\n if (`${key}`.startsWith(\"displayConds\")) return false;\n if (valueType === \"string\") return isDataSourceTemplate(value, ds, hasArray);\n if (isObject(value) && value.isBindDataSource && value.dataSourceId === ds.id) return true;\n if (isSpecificDataSourceTemplate(value, ds.id)) return true;\n if (isUseDataSourceField(value, ds.id)) {\n const [, ...keys] = value;\n const includeArray = isIncludeArrayField(keys, ds.fields);\n return hasArray ? includeArray : !includeArray;\n }\n return false;\n };\n const isDataSourceCondTarget = (ds, key, value, hasArray = false) => {\n if (!Array.isArray(value) || !ds) return false;\n const [dsId, ...keys] = value;\n if (dsId !== ds.id || !`${key}`.startsWith(\"displayConds\")) return false;\n if (ds.fields?.some((field) => field.name === keys[0])) {\n const includeArray = isIncludeArrayField(keys, ds.fields);\n return hasArray ? includeArray : !includeArray;\n }\n return false;\n };\n const createDataSourceTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE,\n id: ds.id,\n initialDeps,\n isTarget: (key, value) => isDataSourceTarget(ds, key, value)\n });\n const createDataSourceCondTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE_COND,\n id: ds.id,\n initialDeps,\n isTarget: (key, value) => isDataSourceCondTarget(ds, key, value)\n });\n const createDataSourceMethodTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE_METHOD,\n id: ds.id,\n initialDeps,\n isTarget: (_key, value) => {\n if (!Array.isArray(value)) return false;\n const [dsId, methodName] = value;\n if (!methodName || dsId !== ds.id) return false;\n if (ds.methods?.some((method) => method.name === methodName)) return true;\n if (ds.fields?.some((field) => field.name === methodName)) return false;\n return true;\n }\n });\n const traverseTarget = (targetsList, cb, type) => {\n if (type) {\n const targets = targetsList[type];\n if (targets) for (const target of Object.values(targets)) cb(target);\n return;\n }\n for (const targets of Object.values(targetsList)) for (const target of Object.values(targets)) cb(target);\n };\n //#endregion\n //#region packages/dep/src/Watcher.ts\n const DATA_SOURCE_TARGET_TYPES = new Set([\n DepTargetType.DATA_SOURCE,\n DepTargetType.DATA_SOURCE_COND,\n DepTargetType.DATA_SOURCE_METHOD\n ]);\n var Watcher = class {\n targetsList = {};\n childrenProp = \"items\";\n idProp = \"id\";\n nameProp = \"name\";\n constructor(options) {\n if (options?.initialTargets) this.targetsList = options.initialTargets;\n if (options?.childrenProp) this.childrenProp = options.childrenProp;\n }\n getTargetsList() {\n return this.targetsList;\n }\n /**\n * 获取指定类型中的所有target\n * @param type 分类\n * @returns Target[]\n */\n getTargets(type = DepTargetType.DEFAULT) {\n return this.targetsList[type] || {};\n }\n /**\n * 添加新的目标\n * @param target Target\n */\n addTarget(target) {\n const targets = this.getTargets(target.type) || {};\n this.targetsList[target.type] = targets;\n targets[target.id] = target;\n }\n /**\n * 获取指定id的target\n * @param id target id\n * @returns Target\n */\n getTarget(id, type = DepTargetType.DEFAULT) {\n return this.getTargets(type)[id];\n }\n /**\n * 判断是否存在指定id的target\n * @param id target id\n * @returns boolean\n */\n hasTarget(id, type = DepTargetType.DEFAULT) {\n return Boolean(this.getTarget(id, type));\n }\n /**\n * 判断是否存在指定类型的target\n * @param type target type\n * @returns boolean\n */\n hasSpecifiedTypeTarget(type = DepTargetType.DEFAULT) {\n return Object.keys(this.getTargets(type)).length > 0;\n }\n /**\n * 删除指定id的target\n * @param id target id\n */\n removeTarget(id, type = DepTargetType.DEFAULT) {\n const targets = this.getTargets(type);\n if (targets[id]) {\n targets[id].destroy();\n delete targets[id];\n }\n }\n /**\n * 删除指定分类的所有target\n * @param type 分类\n * @returns void\n */\n removeTargets(type = DepTargetType.DEFAULT) {\n const targets = this.targetsList[type];\n if (!targets) return;\n for (const target of Object.values(targets)) target.destroy();\n delete this.targetsList[type];\n }\n /**\n * 删除所有target\n */\n clearTargets() {\n for (const key of Object.keys(this.targetsList)) delete this.targetsList[key];\n }\n /**\n * 收集依赖\n * @param nodes 需要收集的节点\n * @param deep 是否需要收集子节点\n * @param type 强制收集指定类型的依赖\n */\n collect(nodes, depExtendedData = {}, deep = false, type) {\n this.collectByCallback(nodes, type, ({ node, target }) => {\n this.removeTargetDep(target, node);\n this.collectItem(node, target, depExtendedData, deep);\n });\n }\n collectByCallback(nodes, type, cb) {\n traverseTarget(this.targetsList, (target) => {\n if (!type && !target.isCollectByDefault) return;\n for (const node of nodes) cb({\n node,\n target\n });\n }, type);\n }\n /**\n * 清除所有目标的依赖\n * @param nodes 需要清除依赖的节点\n */\n clear(nodes, type) {\n let { targetsList } = this;\n if (type) targetsList = { [type]: this.getTargets(type) };\n const clearedItemsNodeIds = /* @__PURE__ */ new Set();\n traverseTarget(targetsList, (target) => {\n if (nodes) for (const node of nodes) {\n target.removeDep(node[this.idProp]);\n if (Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length && !clearedItemsNodeIds.has(node[this.idProp])) {\n clearedItemsNodeIds.add(node[this.idProp]);\n this.clear(node[this.childrenProp]);\n }\n }\n else target.removeDep();\n });\n }\n /**\n * 清除指定类型的依赖\n * @param type 类型\n * @param nodes 需要清除依赖的节点\n */\n clearByType(type, nodes) {\n this.clear(nodes, type);\n }\n collectItem(node, target, depExtendedData = {}, deep = false) {\n if (node[\"_tmagic_node_disabled_data_source\"] && DATA_SOURCE_TARGET_TYPES.has(target.type)) return;\n if (node[\"_tmagic_node_disabled_code_block\"] && target.type === DepTargetType.CODE_BLOCK) return;\n const collectTarget = (config, prop = \"\") => {\n const doCollect = (key, value) => {\n const keyIsItems = key === this.childrenProp;\n const fullKey = prop ? `${prop}.${key}` : key;\n if (target.isTarget(fullKey, value)) target.updateDep({\n id: node[this.idProp],\n name: `${node[this.nameProp] || node[this.idProp]}`,\n data: depExtendedData,\n key: fullKey\n });\n else if (!keyIsItems && Array.isArray(value)) for (let i = 0, l = value.length; i < l; i++) {\n const item = value[i];\n if (isObject(item)) collectTarget(item, `${fullKey}[${i}]`);\n }\n else if (isObject(value)) collectTarget(value, fullKey);\n if (keyIsItems && deep && Array.isArray(value)) for (const child of value) this.collectItem(child, target, depExtendedData, deep);\n };\n for (const [key, value] of Object.entries(config)) {\n if (typeof value === \"undefined\" || value === \"\") continue;\n doCollect(key, value);\n }\n };\n collectTarget(node);\n }\n removeTargetDep(target, node, key) {\n target.removeDep(node[this.idProp], key);\n if (typeof key === \"undefined\" && Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length) for (const item of node[this.childrenProp]) this.removeTargetDep(target, item, key);\n }\n };\n //#endregion\n //#region packages/editor/src/utils/logger.ts\n const error = (...args) => {\n if (process.env.NODE_ENV === \"development\") console.error(\"magic editor: \", ...args);\n };\n //#endregion\n //#region packages/editor/src/utils/dep/worker.ts\n onmessage = (e) => {\n const watcher = new Watcher({ initialTargets: {} });\n const { dsl } = e.data;\n try {\n const mApp = eval(`(${dsl})`);\n if (!mApp) postMessage({});\n watcher.clearTargets();\n if (mApp.codeBlocks) for (const [id, code] of Object.entries(mApp.codeBlocks)) watcher.addTarget(createCodeBlockTarget(id, code));\n if (mApp.dataSources) for (const ds of mApp.dataSources) {\n watcher.addTarget(createDataSourceTarget(ds, {}));\n watcher.addTarget(createDataSourceMethodTarget(ds, {}));\n watcher.addTarget(createDataSourceCondTarget(ds, {}));\n }\n watcher.collectByCallback(mApp.items, void 0, ({ node, target }) => {\n watcher.collectItem(node, target, { pageId: node.id }, true);\n });\n const data = {\n [DepTargetType.DATA_SOURCE]: {},\n [DepTargetType.DATA_SOURCE_METHOD]: {},\n [DepTargetType.DATA_SOURCE_COND]: {},\n [DepTargetType.CODE_BLOCK]: {}\n };\n traverseTarget(watcher.getTargetsList(), (target) => {\n data[target.type][target.id] = target.deps;\n });\n postMessage(data);\n } catch (e) {\n error(e);\n postMessage({});\n }\n };\n //#endregion\n})();\n";
|
|
13299
13395
|
var blob = typeof self !== "undefined" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", jsContent], { type: "text/javascript;charset=utf-8" });
|
|
13300
13396
|
function WorkerWrapper(options) {
|
|
13301
13397
|
let objURL;
|
|
@@ -13869,6 +13965,7 @@
|
|
|
13869
13965
|
var defaultEditorProps = {
|
|
13870
13966
|
renderType: _tmagic_stage.RenderType.IFRAME,
|
|
13871
13967
|
disabledMultiSelect: false,
|
|
13968
|
+
alwaysMultiSelect: false,
|
|
13872
13969
|
disabledPageFragment: false,
|
|
13873
13970
|
disabledStageOverlay: false,
|
|
13874
13971
|
containerHighlightClassName: _tmagic_stage.CONTAINER_HIGHLIGHT_CLASS_NAME,
|
|
@@ -13904,6 +14001,9 @@
|
|
|
13904
14001
|
(0, vue.watch)(() => props.disabledMultiSelect, (disabledMultiSelect) => {
|
|
13905
14002
|
editorService.set("disabledMultiSelect", disabledMultiSelect || false);
|
|
13906
14003
|
}, { immediate: true });
|
|
14004
|
+
(0, vue.watch)(() => props.alwaysMultiSelect, (alwaysMultiSelect) => {
|
|
14005
|
+
editorService.set("alwaysMultiSelect", alwaysMultiSelect || false);
|
|
14006
|
+
}, { immediate: true });
|
|
13907
14007
|
(0, vue.watch)(() => props.componentGroupList, (componentGroupList) => componentGroupList && componentListService.setList(componentGroupList), { immediate: true });
|
|
13908
14008
|
(0, vue.watch)(() => props.datasourceList, (datasourceList) => datasourceList && dataSourceService.set("datasourceTypeList", datasourceList), { immediate: true });
|
|
13909
14009
|
(0, vue.watch)(() => props.propsConfigs, (configs) => configs && propsService.setPropsConfigs(configs), { immediate: true });
|
|
@@ -14313,6 +14413,7 @@
|
|
|
14313
14413
|
disabledDragStart: { type: Boolean },
|
|
14314
14414
|
guidesOptions: {},
|
|
14315
14415
|
disabledMultiSelect: { type: Boolean },
|
|
14416
|
+
alwaysMultiSelect: { type: Boolean },
|
|
14316
14417
|
disabledPageFragment: { type: Boolean },
|
|
14317
14418
|
disabledStageOverlay: { type: Boolean },
|
|
14318
14419
|
disabledShowSrc: { type: Boolean },
|
|
@@ -14326,7 +14427,9 @@
|
|
|
14326
14427
|
isContainer: { type: Function },
|
|
14327
14428
|
customContentMenu: { type: Function },
|
|
14328
14429
|
layerNodeIsExpandable: { type: Function },
|
|
14430
|
+
canDropIn: { type: Function },
|
|
14329
14431
|
beforeDblclick: { type: Function },
|
|
14432
|
+
beforeLayerNodeDblclick: { type: Function },
|
|
14330
14433
|
extendFormState: { type: Function },
|
|
14331
14434
|
pageBarSortOptions: {},
|
|
14332
14435
|
pageFilterFunction: { type: Function }
|
|
@@ -14336,7 +14439,8 @@
|
|
|
14336
14439
|
"props-panel-unmounted",
|
|
14337
14440
|
"update:modelValue",
|
|
14338
14441
|
"props-form-error",
|
|
14339
|
-
"props-submit-error"
|
|
14442
|
+
"props-submit-error",
|
|
14443
|
+
"layer-node-dblclick"
|
|
14340
14444
|
],
|
|
14341
14445
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
14342
14446
|
const emit = __emit;
|
|
@@ -14367,6 +14471,7 @@
|
|
|
14367
14471
|
canSelect: props.canSelect,
|
|
14368
14472
|
updateDragEl: props.updateDragEl,
|
|
14369
14473
|
isContainer: props.isContainer,
|
|
14474
|
+
canDropIn: props.canDropIn ? (sourceIds, targetId) => props.canDropIn(sourceIds, targetId, sourceIds.length === 0 ? "stage-add" : "stage-drag") : void 0,
|
|
14370
14475
|
containerHighlightClassName: props.containerHighlightClassName,
|
|
14371
14476
|
containerHighlightDuration: props.containerHighlightDuration,
|
|
14372
14477
|
containerHighlightType: props.containerHighlightType,
|
|
@@ -14374,6 +14479,7 @@
|
|
|
14374
14479
|
renderType: props.renderType,
|
|
14375
14480
|
guidesOptions: props.guidesOptions,
|
|
14376
14481
|
disabledMultiSelect: props.disabledMultiSelect,
|
|
14482
|
+
alwaysMultiSelect: props.alwaysMultiSelect,
|
|
14377
14483
|
beforeDblclick: props.beforeDblclick
|
|
14378
14484
|
};
|
|
14379
14485
|
stageOverlay_default.set("stageOptions", stageOptions);
|
|
@@ -14393,6 +14499,9 @@
|
|
|
14393
14499
|
const propsPanelFormErrorHandler = (e) => {
|
|
14394
14500
|
emit("props-form-error", e);
|
|
14395
14501
|
};
|
|
14502
|
+
const layerNodeDblclickHandler = (event, data) => {
|
|
14503
|
+
emit("layer-node-dblclick", event, data);
|
|
14504
|
+
};
|
|
14396
14505
|
__expose(services);
|
|
14397
14506
|
return (_ctx, _cache) => {
|
|
14398
14507
|
return (0, vue.openBlock)(), (0, vue.createBlock)(Framework_default, {
|
|
@@ -14410,7 +14519,10 @@
|
|
|
14410
14519
|
"custom-content-menu": __props.customContentMenu,
|
|
14411
14520
|
indent: __props.treeIndent,
|
|
14412
14521
|
"next-level-indent-increment": __props.treeNextLevelIndentIncrement,
|
|
14413
|
-
"layer-node-is-expandable": __props.layerNodeIsExpandable
|
|
14522
|
+
"layer-node-is-expandable": __props.layerNodeIsExpandable,
|
|
14523
|
+
"can-drop-in": __props.canDropIn,
|
|
14524
|
+
"before-layer-node-dblclick": __props.beforeLayerNodeDblclick,
|
|
14525
|
+
onLayerNodeDblclick: layerNodeDblclickHandler
|
|
14414
14526
|
}, {
|
|
14415
14527
|
"layer-panel-header": (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "layer-panel-header")]),
|
|
14416
14528
|
"layer-node-content": (0, vue.withCtx)(({ data }) => [(0, vue.renderSlot)(_ctx.$slots, "layer-node-content", { data })]),
|
|
@@ -14434,7 +14546,9 @@
|
|
|
14434
14546
|
"custom-content-menu",
|
|
14435
14547
|
"indent",
|
|
14436
14548
|
"next-level-indent-increment",
|
|
14437
|
-
"layer-node-is-expandable"
|
|
14549
|
+
"layer-node-is-expandable",
|
|
14550
|
+
"can-drop-in",
|
|
14551
|
+
"before-layer-node-dblclick"
|
|
14438
14552
|
])])]),
|
|
14439
14553
|
workspace: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "workspace", { editorService: (0, vue.unref)(editor_default) }, () => [(0, vue.createVNode)(Workspace_default, {
|
|
14440
14554
|
"disabled-stage-overlay": __props.disabledStageOverlay,
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.7.
|
|
2
|
+
"version": "1.7.14-beta.0",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
"moveable": "^0.53.0",
|
|
59
59
|
"serialize-javascript": "^7.0.0",
|
|
60
60
|
"sortablejs": "^1.15.6",
|
|
61
|
-
"@tmagic/design": "1.7.
|
|
62
|
-
"@tmagic/form": "1.7.
|
|
63
|
-
"@tmagic/table": "1.7.
|
|
64
|
-
"@tmagic/stage": "1.7.
|
|
65
|
-
"@tmagic/utils": "1.7.
|
|
61
|
+
"@tmagic/design": "1.7.14-beta.0",
|
|
62
|
+
"@tmagic/form": "1.7.14-beta.0",
|
|
63
|
+
"@tmagic/table": "1.7.14-beta.0",
|
|
64
|
+
"@tmagic/stage": "1.7.14-beta.0",
|
|
65
|
+
"@tmagic/utils": "1.7.14-beta.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/events": "^3.0.3",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"type-fest": "^5.2.0",
|
|
77
77
|
"typescript": "^6.0.3",
|
|
78
78
|
"vue": "^3.5.33",
|
|
79
|
-
"@tmagic/core": "1.7.
|
|
79
|
+
"@tmagic/core": "1.7.14-beta.0"
|
|
80
80
|
},
|
|
81
81
|
"peerDependenciesMeta": {
|
|
82
82
|
"typescript": {
|
package/src/Editor.vue
CHANGED
|
@@ -27,6 +27,9 @@
|
|
|
27
27
|
:indent="treeIndent"
|
|
28
28
|
:next-level-indent-increment="treeNextLevelIndentIncrement"
|
|
29
29
|
:layer-node-is-expandable="layerNodeIsExpandable"
|
|
30
|
+
:can-drop-in="canDropIn"
|
|
31
|
+
:before-layer-node-dblclick="beforeLayerNodeDblclick"
|
|
32
|
+
@layer-node-dblclick="layerNodeDblclickHandler"
|
|
30
33
|
>
|
|
31
34
|
<template #layer-panel-header>
|
|
32
35
|
<slot name="layer-panel-header"></slot>
|
|
@@ -156,6 +159,7 @@ import uiService from './services/ui';
|
|
|
156
159
|
import keybindingConfig from './utils/keybinding-config';
|
|
157
160
|
import { defaultEditorProps, EditorProps } from './editorProps';
|
|
158
161
|
import { initServiceEvents, initServiceState } from './initService';
|
|
162
|
+
import type { TreeNodeData } from './type';
|
|
159
163
|
import type { EditorSlots, EventBus, Services, StageOptions } from './type';
|
|
160
164
|
|
|
161
165
|
defineSlots<EditorSlots>();
|
|
@@ -170,6 +174,7 @@ const emit = defineEmits<{
|
|
|
170
174
|
'update:modelValue': [value: MApp | null];
|
|
171
175
|
'props-form-error': [e: any];
|
|
172
176
|
'props-submit-error': [e: any];
|
|
177
|
+
'layer-node-dblclick': [event: MouseEvent, data: TreeNodeData];
|
|
173
178
|
}>();
|
|
174
179
|
|
|
175
180
|
const props = withDefaults(defineProps<EditorProps>(), defaultEditorProps);
|
|
@@ -202,6 +207,11 @@ const stageOptions: StageOptions = {
|
|
|
202
207
|
canSelect: props.canSelect,
|
|
203
208
|
updateDragEl: props.updateDragEl,
|
|
204
209
|
isContainer: props.isContainer,
|
|
210
|
+
// sourceIds 为空表示从组件列表新增(尚无 id),否则是画布上拖动已有组件
|
|
211
|
+
canDropIn: props.canDropIn
|
|
212
|
+
? (sourceIds, targetId) =>
|
|
213
|
+
props.canDropIn!(sourceIds, targetId, sourceIds.length === 0 ? 'stage-add' : 'stage-drag')
|
|
214
|
+
: undefined,
|
|
205
215
|
containerHighlightClassName: props.containerHighlightClassName,
|
|
206
216
|
containerHighlightDuration: props.containerHighlightDuration,
|
|
207
217
|
containerHighlightType: props.containerHighlightType,
|
|
@@ -209,6 +219,7 @@ const stageOptions: StageOptions = {
|
|
|
209
219
|
renderType: props.renderType,
|
|
210
220
|
guidesOptions: props.guidesOptions,
|
|
211
221
|
disabledMultiSelect: props.disabledMultiSelect,
|
|
222
|
+
alwaysMultiSelect: props.alwaysMultiSelect,
|
|
212
223
|
beforeDblclick: props.beforeDblclick,
|
|
213
224
|
};
|
|
214
225
|
|
|
@@ -236,5 +247,9 @@ const propsPanelFormErrorHandler = (e: any) => {
|
|
|
236
247
|
emit('props-form-error', e);
|
|
237
248
|
};
|
|
238
249
|
|
|
250
|
+
const layerNodeDblclickHandler = (event: MouseEvent, data: TreeNodeData) => {
|
|
251
|
+
emit('layer-node-dblclick', event, data);
|
|
252
|
+
};
|
|
253
|
+
|
|
239
254
|
defineExpose(services);
|
|
240
255
|
</script>
|
package/src/components/Tree.vue
CHANGED
|
@@ -56,6 +56,7 @@ const emit = defineEmits<{
|
|
|
56
56
|
'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
|
|
57
57
|
'node-mouseenter': [event: MouseEvent, data: TreeNodeData];
|
|
58
58
|
'node-click': [event: MouseEvent, data: TreeNodeData];
|
|
59
|
+
'node-dblclick': [event: MouseEvent, data: TreeNodeData];
|
|
59
60
|
}>();
|
|
60
61
|
|
|
61
62
|
provide('treeEmit', emit);
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
@click="expandHandler"
|
|
26
26
|
></MIcon>
|
|
27
27
|
|
|
28
|
-
<div class="tree-node-content" @click="nodeClickHandler">
|
|
28
|
+
<div class="tree-node-content" @click="nodeClickHandler" @dblclick="nodeDblclickHandler">
|
|
29
29
|
<slot name="tree-node-content" :data="data">
|
|
30
30
|
<div class="tree-node-label">
|
|
31
31
|
<slot name="tree-node-label" :data="data">{{ `${data.name} (${data.id})` }}</slot>
|
|
@@ -89,6 +89,7 @@ const emit = defineEmits<{
|
|
|
89
89
|
'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
|
|
90
90
|
'node-mouseenter': [event: MouseEvent, data: TreeNodeData];
|
|
91
91
|
'node-click': [event: MouseEvent, data: TreeNodeData];
|
|
92
|
+
'node-dblclick': [event: MouseEvent, data: TreeNodeData];
|
|
92
93
|
}>();
|
|
93
94
|
|
|
94
95
|
const treeEmit = inject<typeof emit>('treeEmit');
|
|
@@ -156,4 +157,8 @@ const expandHandler = () => {
|
|
|
156
157
|
const nodeClickHandler = (event: MouseEvent) => {
|
|
157
158
|
treeEmit?.('node-click', event, props.data);
|
|
158
159
|
};
|
|
160
|
+
|
|
161
|
+
const nodeDblclickHandler = (event: MouseEvent) => {
|
|
162
|
+
treeEmit?.('node-dblclick', event, props.data);
|
|
163
|
+
};
|
|
159
164
|
</script>
|