{{ `${data.name} (${data.id})` }}
@@ -89,6 +89,7 @@ const emit = defineEmits<{
'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
'node-mouseenter': [event: MouseEvent, data: TreeNodeData];
'node-click': [event: MouseEvent, data: TreeNodeData];
+ 'node-dblclick': [event: MouseEvent, data: TreeNodeData];
}>();
const treeEmit = inject('treeEmit');
@@ -156,4 +157,8 @@ const expandHandler = () => {
const nodeClickHandler = (event: MouseEvent) => {
treeEmit?.('node-click', event, props.data);
};
+
+const nodeDblclickHandler = (event: MouseEvent) => {
+ treeEmit?.('node-dblclick', event, props.data);
+};
diff --git a/packages/editor/src/editorProps.ts b/packages/editor/src/editorProps.ts
index 1cbfb0be..17a4b0b7 100644
--- a/packages/editor/src/editorProps.ts
+++ b/packages/editor/src/editorProps.ts
@@ -22,6 +22,7 @@ import type {
PageBarSortOptions,
SideBarData,
StageRect,
+ TreeNodeData,
} from './type';
export interface EditorProps {
@@ -114,6 +115,8 @@ export interface EditorProps {
canDropIn?: CanDropInFunction;
/** 画布双击前的钩子函数,返回 false 则阻止默认的双击行为 */
beforeDblclick?: (event: MouseEvent) => Promise | boolean | void;
+ /** 组件树节点双击前的钩子函数,返回 false 则阻止默认的双击行为 */
+ beforeLayerNodeDblclick?: (event: MouseEvent, data: TreeNodeData) => Promise | boolean | void;
extendFormState?: (state: FormState) => Record | Promise>;
/** 页面顺序拖拽配置参数 */
pageBarSortOptions?: PageBarSortOptions;
diff --git a/packages/editor/src/layouts/sidebar/Sidebar.vue b/packages/editor/src/layouts/sidebar/Sidebar.vue
index 20e14e32..fc2378f1 100644
--- a/packages/editor/src/layouts/sidebar/Sidebar.vue
+++ b/packages/editor/src/layouts/sidebar/Sidebar.vue
@@ -173,6 +173,7 @@ import {
type SideComponent,
type SideItem,
SideItemKey,
+ type TreeNodeData,
} from '@editor/type';
import CodeBlockListPanel from './code-block/CodeBlockListPanel.vue';
@@ -186,6 +187,10 @@ defineOptions({
name: 'MEditorSidebar',
});
+const emit = defineEmits<{
+ 'layer-node-dblclick': [event: MouseEvent, data: TreeNodeData];
+}>();
+
const props = withDefaults(
defineProps<{
data?: SideBarData;
@@ -197,6 +202,8 @@ const props = withDefaults(
layerNodeIsExpandable?: IsExpandableFunction;
/** 自定义判断当前正在拖动的源是否可以拖入目标节点内部,详见 EditorProps.canDropIn */
canDropIn?: CanDropInFunction;
+ /** 组件树节点双击前的钩子函数,返回 false 则阻止默认的双击行为 */
+ beforeLayerNodeDblclick?: (_event: MouseEvent, _data: TreeNodeData) => Promise | boolean | void;
}>(),
{
data: () => ({
@@ -256,6 +263,10 @@ const getItemConfig = (data: SideItem): SideComponent => {
nextLevelIndentIncrement: props.nextLevelIndentIncrement,
isExpandable: props.layerNodeIsExpandable,
canDropIn: props.canDropIn,
+ beforeNodeDblclick: props.beforeLayerNodeDblclick,
+ },
+ listeners: {
+ 'node-dblclick': (event: MouseEvent, nodeData: TreeNodeData) => emit('layer-node-dblclick', event, nodeData),
},
component: LayerPanel,
slots: {},
diff --git a/packages/editor/src/layouts/sidebar/layer/LayerPanel.vue b/packages/editor/src/layouts/sidebar/layer/LayerPanel.vue
index 5778a5a8..4b1e15d5 100644
--- a/packages/editor/src/layouts/sidebar/layer/LayerPanel.vue
+++ b/packages/editor/src/layouts/sidebar/layer/LayerPanel.vue
@@ -20,6 +20,7 @@
@node-contextmenu="nodeContentMenuHandler"
@node-mouseenter="mouseenterHandler"
@node-click="nodeClickHandler"
+ @node-dblclick="dblclickHandler"
>
@@ -89,6 +90,12 @@ const props = defineProps<{
isExpandable?: IsExpandableFunction;
/** 自定义判断当前拖动节点是否可以拖入目标节点内部的函数,返回 false 则禁止拖入 */
canDropIn?: CanDropInFunction;
+ /** 组件树节点双击前的钩子函数,返回 false 则阻止默认的双击行为 */
+ beforeNodeDblclick?: (_event: MouseEvent, _data: TreeNodeData) => Promise | boolean | void;
+}>();
+
+const emit = defineEmits<{
+ 'node-dblclick': [event: MouseEvent, data: TreeNodeData];
}>();
const services = useServices();
@@ -134,7 +141,19 @@ const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useD
const menuRef = useTemplateRef>('menu');
const {
nodeClickHandler,
+ nodeDblclickHandler,
nodeContentMenuHandler,
highlightHandler: mouseenterHandler,
} = useClick(services, isCtrlKeyDown, nodeStatusMap, menuRef);
+
+const dblclickHandler = async (event: MouseEvent, data: TreeNodeData) => {
+ if (props.beforeNodeDblclick) {
+ const result = await props.beforeNodeDblclick(event, data);
+ if (result === false) return;
+ }
+
+ nodeDblclickHandler(event, data);
+
+ emit('node-dblclick', event, data);
+};
diff --git a/packages/editor/src/layouts/sidebar/layer/use-click.ts b/packages/editor/src/layouts/sidebar/layer/use-click.ts
index 46d4e32f..cc6a3fd4 100644
--- a/packages/editor/src/layouts/sidebar/layer/use-click.ts
+++ b/packages/editor/src/layouts/sidebar/layer/use-click.ts
@@ -100,11 +100,27 @@ export const useClick = (
});
};
+ const nodeDblclickHandler = (event: MouseEvent, data: TreeNodeData): void => {
+ if (!nodeStatusMap?.value) return;
+
+ if (uiService.get('uiSelectMode')) return;
+
+ // 双击切换展开/收起状态
+ if (data.items && data.items.length > 0) {
+ const status = nodeStatusMap.value.get(data.id);
+ updateStatus(nodeStatusMap.value, data.id, {
+ expand: !status?.expand,
+ });
+ }
+ };
+
return {
menuRef,
nodeClickHandler,
+ nodeDblclickHandler,
+
nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData): void {
event.preventDefault();