mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-01-07 02:08:10 +00:00
123 lines
3.3 KiB
TypeScript
123 lines
3.3 KiB
TypeScript
import { computed, type ComputedRef, nextTick, type Ref, ref } from 'vue';
|
|
import { throttle } from 'lodash-es';
|
|
|
|
import { Id, MNode } from '@tmagic/schema';
|
|
import { isPage, isPageFragment } from '@tmagic/utils';
|
|
|
|
import { LayerNodeStatus, Services, TreeNodeData, UI_SELECT_MODE_EVENT_NAME } from '@editor/type';
|
|
import { updateStatus } from '@editor/utils/tree';
|
|
|
|
import LayerMenu from './LayerMenu.vue';
|
|
|
|
export const useClick = (
|
|
services: Services | undefined,
|
|
isCtrlKeyDown: Ref<boolean>,
|
|
nodeStatusMap: ComputedRef<Map<Id, LayerNodeStatus> | undefined>,
|
|
) => {
|
|
const isMultiSelect = computed(() => isCtrlKeyDown.value && !services?.editorService.get('disabledMultiSelect'));
|
|
|
|
// 触发画布选中
|
|
const select = async (data: MNode) => {
|
|
if (!data.id) {
|
|
throw new Error('没有id');
|
|
}
|
|
|
|
if (isMultiSelect.value) {
|
|
multiSelect(data);
|
|
} else {
|
|
await services?.editorService.select(data);
|
|
services?.editorService.get('stage')?.select(data.id);
|
|
services?.stageOverlayService.get('stage')?.select(data.id);
|
|
}
|
|
};
|
|
|
|
const multiSelect = async (data: MNode) => {
|
|
if (isPage(data) || isPageFragment(data)) {
|
|
return;
|
|
}
|
|
|
|
const nodes = services?.editorService.get('nodes') || [];
|
|
|
|
const newNodes: Id[] = [];
|
|
let isCancel = false;
|
|
nodes.forEach((node) => {
|
|
if (node.id === data.id) {
|
|
isCancel = true;
|
|
return;
|
|
}
|
|
|
|
if (isPage(node) || isPageFragment(node)) {
|
|
return;
|
|
}
|
|
|
|
newNodes.push(node.id);
|
|
});
|
|
|
|
// 只剩一个不能取消选中
|
|
if (!isCancel || newNodes.length === 0) {
|
|
newNodes.push(data.id);
|
|
}
|
|
|
|
await services?.editorService.multiSelect(newNodes);
|
|
services?.editorService.get('stage')?.multiSelect(newNodes);
|
|
services?.stageOverlayService.get('stage')?.multiSelect(newNodes);
|
|
};
|
|
|
|
const throttleTime = 300;
|
|
// 鼠标在组件树移动触发高亮
|
|
const highlightHandler: (event: MouseEvent, data: TreeNodeData) => void = throttle(
|
|
(event: MouseEvent, data: TreeNodeData) => {
|
|
highlight(data);
|
|
},
|
|
throttleTime,
|
|
);
|
|
|
|
// 触发画布高亮
|
|
const highlight = (data: TreeNodeData) => {
|
|
services?.editorService?.highlight(data);
|
|
services?.editorService?.get('stage')?.highlight(data.id);
|
|
services?.stageOverlayService?.get('stage')?.highlight(data.id);
|
|
};
|
|
|
|
const nodeClickHandler = (event: MouseEvent, data: TreeNodeData): void => {
|
|
if (!nodeStatusMap?.value) return;
|
|
|
|
if (services?.uiService.get('uiSelectMode')) {
|
|
document.dispatchEvent(new CustomEvent(UI_SELECT_MODE_EVENT_NAME, { detail: data }));
|
|
return;
|
|
}
|
|
|
|
if (data.items && data.items.length > 0 && !isMultiSelect.value) {
|
|
updateStatus(nodeStatusMap.value, data.id, {
|
|
expand: true,
|
|
});
|
|
}
|
|
|
|
nextTick(() => {
|
|
select(data);
|
|
});
|
|
};
|
|
|
|
// 右键菜单
|
|
const menu = ref<InstanceType<typeof LayerMenu>>();
|
|
|
|
return {
|
|
menu,
|
|
|
|
nodeClickHandler,
|
|
|
|
nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData): void {
|
|
event.preventDefault();
|
|
|
|
const nodes = services?.editorService.get('nodes') || [];
|
|
if (nodes.length < 2 || !nodes.includes(data)) {
|
|
nodeClickHandler(event, data);
|
|
}
|
|
|
|
menu.value?.show(event);
|
|
},
|
|
|
|
highlightHandler,
|
|
};
|
|
};
|