From 0ddfcfba96d47f22b1daec5981af07357f450407 Mon Sep 17 00:00:00 2001 From: SonyLeo <746591437@qq.com> Date: Fri, 28 Feb 2025 02:18:37 -0800 Subject: [PATCH 1/7] =?UTF-8?q?fix=EF=BC=9Aclick=20node?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../canvas/container/src/CanvasContainer.vue | 8 ++-- packages/canvas/container/src/container.js | 44 +++++++++---------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/packages/canvas/container/src/CanvasContainer.vue b/packages/canvas/container/src/CanvasContainer.vue index a050fc1c0a..2b1cc7c458 100644 --- a/packages/canvas/container/src/CanvasContainer.vue +++ b/packages/canvas/container/src/CanvasContainer.vue @@ -111,7 +111,7 @@ export default { const multiStateLength = computed(() => multiSelectedStates.value.length) - const setCurrentNode = async (event, doc = null) => { + const setCurrentNode = async (event) => { const { clientX, clientY } = event const element = getElement(event.target) closeMenu() @@ -121,7 +121,7 @@ export default { const currentElement = querySelectById(getCurrent().schema?.id) if (!currentElement?.contains(element) || event.button === 0) { - const selectedState = getMultiState(element, doc) + const selectedState = getMultiState(element) setMultiState(multiSelectedStates, selectedState) const loopId = element.getAttribute(NODE_LOOP) @@ -212,7 +212,7 @@ export default { // 多选组合键触发 if (element) { - const selectedState = getMultiState(element, doc) + const selectedState = getMultiState(element) if ((event.ctrlKey || event.metaKey) && event.button === 0) { handleMultiState(multiSelectedStates, selectedState) return @@ -221,7 +221,7 @@ export default { insertPosition.value = false insertContainer.value = false - setCurrentNode(event, doc) + setCurrentNode(event) target.value = event.target }) }) diff --git a/packages/canvas/container/src/container.js b/packages/canvas/container/src/container.js index 723e9de3f9..42590c204b 100644 --- a/packages/canvas/container/src/container.js +++ b/packages/canvas/container/src/container.js @@ -123,29 +123,6 @@ export const lineState = reactive({ ...initialLineState }) -// 获取多选节点 -export const getMultiState = (element, doc) => { - const { top, left, width, height } = element.getBoundingClientRect() - const nodeTag = element?.getAttribute(NODE_TAG) - const nodeId = element?.getAttribute(NODE_UID) - - const { node, parent } = useCanvas().getNodeWithParentById(nodeId) || {} - - if (node && parent) { - return { - id: nodeId, - componentName: nodeTag, - doc, - top, - left, - width, - height, - schema: toRaw(node), - parent: toRaw(parent) - } - } -} - // 设置多选节点 export function setMultiState(multiSelectedStates, node, append = false) { if (!node || typeof node !== 'object') { @@ -328,6 +305,27 @@ const getRect = (element) => { } return element.getBoundingClientRect() } + +// 获取多选节点 +export const getMultiState = (element) => { + const { top, left, width, height } = getRect(element) + const nodeTag = element?.getAttribute(NODE_TAG) + const nodeId = element?.getAttribute(NODE_UID) || 'body' + + const { node } = useCanvas().getNodeWithParentById(nodeId) || {} + + return { + id: nodeId, + componentName: nodeTag, + doc: getDocument(element), + top, + left, + width, + height, + schema: toRaw(node) + } +} + const insertAfter = ({ parent, node, data }) => { if (!data.id) { data.id = utils.guid() From 28188cb08df0b1097b9a84bdda5dcead0dc4495f Mon Sep 17 00:00:00 2001 From: SonyLeo <746591437@qq.com> Date: Sun, 2 Mar 2025 18:38:24 -0800 Subject: [PATCH 2/7] fix: node click and multi-select the issue after node copy --- .../canvas/DesignCanvas/src/DesignCanvas.vue | 3 + .../canvas/container/src/CanvasContainer.vue | 23 ++-- .../src/composables/useMultiSelect.js | 103 ++++++++++++++++++ packages/canvas/container/src/container.js | 56 +--------- packages/canvas/container/src/keyboard.js | 14 ++- 5 files changed, 128 insertions(+), 71 deletions(-) create mode 100644 packages/canvas/container/src/composables/useMultiSelect.js diff --git a/packages/canvas/DesignCanvas/src/DesignCanvas.vue b/packages/canvas/DesignCanvas/src/DesignCanvas.vue index 27d99cd9e1..17ccad33de 100644 --- a/packages/canvas/DesignCanvas/src/DesignCanvas.vue +++ b/packages/canvas/DesignCanvas/src/DesignCanvas.vue @@ -160,6 +160,9 @@ export default { const schemaItem = useCanvas().getNodeById(id) const pageSchema = getSchema() + if (!schemaItem) { + pageSchema.id = 'body' + } // 如果选中的节点是画布,就设置成默认选中最外层schema useProperties().getProps(schemaItem || pageSchema, parent) diff --git a/packages/canvas/container/src/CanvasContainer.vue b/packages/canvas/container/src/CanvasContainer.vue index 2b1cc7c458..77bc9def61 100644 --- a/packages/canvas/container/src/CanvasContainer.vue +++ b/packages/canvas/container/src/CanvasContainer.vue @@ -48,7 +48,7 @@ import { onMounted, ref, computed, onUnmounted, watch, watchEffect } from 'vue' import { iframeMonitoring } from '@opentiny/tiny-engine-common/js/monitor' import { useTranslate, useCanvas, useMessage, useResource } from '@opentiny/tiny-engine-meta-register' import { NODE_UID, NODE_LOOP, DESIGN_MODE } from '../../common' -import { registerHotkeyEvent, removeHotkeyEvent, multiSelectedStates } from './keyboard' +import { registerHotkeyEvent, removeHotkeyEvent } from './keyboard' import CanvasMenu, { closeMenu, openMenu } from './components/CanvasMenu.vue' import CanvasAction from './components/CanvasAction.vue' import CanvasRouterJumper from './components/CanvasRouterJumper.vue' @@ -56,6 +56,7 @@ import CanvasViewerSwitcher from './components/CanvasViewerSwitcher.vue' import CanvasResize from './components/CanvasResize.vue' import CanvasDivider from './components/CanvasDivider.vue' import CanvasResizeBorder from './components/CanvasResizeBorder.vue' +import { useMultiSelect } from './composables/useMultiSelect' import { canvasState, onMouseUp, @@ -74,10 +75,7 @@ import { clearLineState, querySelectById, getCurrent, - canvasApi, - getMultiState, - setMultiState, - handleMultiState + canvasApi } from './container' export default { @@ -109,7 +107,8 @@ export default { const containerPanel = ref(null) const insertContainer = ref(false) - const multiStateLength = computed(() => multiSelectedStates.value.length) + const { multiSelectedStates, multiStateLength, setMultiSelection, getMultiSelectionState, toggleMultiSelection } = + useMultiSelect() const setCurrentNode = async (event) => { const { clientX, clientY } = event @@ -121,8 +120,10 @@ export default { const currentElement = querySelectById(getCurrent().schema?.id) if (!currentElement?.contains(element) || event.button === 0) { - const selectedState = getMultiState(element) - setMultiState(multiSelectedStates, selectedState) + const selectedState = getMultiSelectionState(element) + if (selectedState) { + setMultiSelection(selectedState) + } const loopId = element.getAttribute(NODE_LOOP) if (loopId) { @@ -212,9 +213,11 @@ export default { // 多选组合键触发 if (element) { - const selectedState = getMultiState(element) + const selectedState = getMultiSelectionState(element) if ((event.ctrlKey || event.metaKey) && event.button === 0) { - handleMultiState(multiSelectedStates, selectedState) + if (selectedState) { + toggleMultiSelection(selectedState) + } return } } diff --git a/packages/canvas/container/src/composables/useMultiSelect.js b/packages/canvas/container/src/composables/useMultiSelect.js new file mode 100644 index 0000000000..6f03b3baa5 --- /dev/null +++ b/packages/canvas/container/src/composables/useMultiSelect.js @@ -0,0 +1,103 @@ +import { ref, computed, toRaw } from 'vue' +import { useCanvas } from '@opentiny/tiny-engine-meta-register' +import { NODE_TAG, NODE_UID } from '../../../common' +import { getRect, getDocument } from '../container' + +// 初始化多选节点 +const multiSelectedStates = ref([{ id: 'body', componentName: 'body' }]) + +// 节点位置缓存 +let nodeRectCache = new WeakMap() + +// 获取带缓存的节点位置 +const getCachedRect = (element) => { + if (nodeRectCache.has(element)) { + return nodeRectCache.get(element) + } + const rect = getRect(element) + nodeRectCache.set(element, rect) + return rect +} + +export const useMultiSelect = () => { + // 记录最后选择的节点 + const lastSelectedNode = ref(null) + + const multiStateLength = computed(() => multiSelectedStates.value.length) + + // 设置多选节点 + const setMultiSelection = (node, append = false) => { + if (!node || typeof node !== 'object') { + multiSelectedStates.value = [] + return + } + + if (append) { + const nodeIds = new Set(multiSelectedStates.value.map((state) => state.id)) + if (!nodeIds.has(node.id)) { + multiSelectedStates.value.push(node) + } + } else { + if (Array.isArray(node)) { + multiSelectedStates.value = node + } else { + multiSelectedStates.value = [node] + } + } + } + + // 处理多选节点 + const toggleMultiSelection = (selectState) => { + const nodeId = selectState?.id + const isExistNode = multiSelectedStates.value.map((state) => state.id).includes(nodeId) + + if (nodeId && isExistNode) { + const exList = multiSelectedStates.value.filter((state) => state.id !== nodeId) + setMultiSelection(exList) + } else { + setMultiSelection(selectState, true) + } + } + + // 获取多选节点(带缓存) + const getMultiSelectionState = (element) => { + if (!element) { + return null + } + + // 使用缓存的位置信息 + const { top, left, width, height } = getCachedRect(element) + const nodeTag = element?.getAttribute(NODE_TAG) + const nodeId = element?.getAttribute(NODE_UID) || 'body' + + // 获取节点信息 + const { node } = useCanvas().getNodeWithParentById(nodeId) || {} + lastSelectedNode.value = nodeId + + return { + id: nodeId, + componentName: nodeTag, + doc: getDocument(element), + top, + left, + width, + height, + schema: toRaw(node) + } + } + + const clearMultiSelection = () => { + multiSelectedStates.value = [] + lastSelectedNode.value = null + nodeRectCache = new WeakMap() // 清空缓存 + } + + return { + multiSelectedStates, + multiStateLength, + setMultiSelection, + getMultiSelectionState, + toggleMultiSelection, + clearMultiSelection + } +} diff --git a/packages/canvas/container/src/container.js b/packages/canvas/container/src/container.js index 42590c204b..b8edfc975a 100644 --- a/packages/canvas/container/src/container.js +++ b/packages/canvas/container/src/container.js @@ -123,40 +123,6 @@ export const lineState = reactive({ ...initialLineState }) -// 设置多选节点 -export function setMultiState(multiSelectedStates, node, append = false) { - if (!node || typeof node !== 'object') { - multiSelectedStates.value = [] - return - } - - if (append) { - const nodeIds = new Set(multiSelectedStates.value.map((state) => state.id)) - if (!nodeIds.has(node.id)) { - multiSelectedStates.value = [...toRaw(multiSelectedStates.value), node] - } - } else { - if (Array.isArray(node)) { - multiSelectedStates.value = node - } else { - multiSelectedStates.value = [node] - } - } -} - -// 处理多选节点 -export function handleMultiState(multiSelectedStates, selectState) { - const nodeId = selectState?.id - const isExistNode = multiSelectedStates.value.map((state) => state.id).includes(nodeId) - - if (nodeId && isExistNode) { - const exList = multiSelectedStates.value.filter((state) => state.id !== nodeId) - setMultiState(multiSelectedStates, exList) - } else { - setMultiState(multiSelectedStates, selectState, true) - } -} - export const clearHover = () => { Object.assign(hoverState, initialRectState, { slot: null }) Object.assign(inactiveHoverState, initialRectState, { slot: null }) @@ -289,7 +255,7 @@ export const getInactiveElement = (element) => { return undefined } -const getRect = (element) => { +export const getRect = (element) => { if (element === getDocument().body) { const { innerWidth: width, innerHeight: height } = getWindow() return { @@ -306,26 +272,6 @@ const getRect = (element) => { return element.getBoundingClientRect() } -// 获取多选节点 -export const getMultiState = (element) => { - const { top, left, width, height } = getRect(element) - const nodeTag = element?.getAttribute(NODE_TAG) - const nodeId = element?.getAttribute(NODE_UID) || 'body' - - const { node } = useCanvas().getNodeWithParentById(nodeId) || {} - - return { - id: nodeId, - componentName: nodeTag, - doc: getDocument(element), - top, - left, - width, - height, - schema: toRaw(node) - } -} - const insertAfter = ({ parent, node, data }) => { if (!data.id) { data.id = utils.guid() diff --git a/packages/canvas/container/src/keyboard.js b/packages/canvas/container/src/keyboard.js index 46ede12052..48da8e51b4 100644 --- a/packages/canvas/container/src/keyboard.js +++ b/packages/canvas/container/src/keyboard.js @@ -10,11 +10,11 @@ * */ -import { ref } from 'vue' import { useHistory, useCanvas, getMetaApi, META_APP } from '@opentiny/tiny-engine-meta-register' import { getCurrent, insertNode, selectNode, POSITION, removeNodeById, allowInsert, getConfigure } from './container' import { copyObject } from '../../common' import { getClipboardSchema, setClipboardSchema } from './utils' +import { useMultiSelect } from './composables/useMultiSelect' const KEY_S = 83 const KEY_Y = 89 @@ -25,9 +25,6 @@ const KEY_UP = 38 const KEY_DOWN = 40 const KEY_DEL = 46 -// 多选节点 -const multiSelectedStates = ref([]) - function handlerLeft({ parent }) { selectNode(parent?.id) } @@ -43,12 +40,15 @@ function handlerDown({ index, parent }) { const id = parent?.children[index + 1]?.id id && selectNode(id) } + +const { multiSelectedStates, clearMultiSelection } = useMultiSelect() + function handlerDelete() { multiSelectedStates.value.forEach(({ id: schemaId }) => { removeNodeById(schemaId) }) - multiSelectedStates.value = [] + clearMultiSelection() } const handlerArrow = (keyCode) => { @@ -119,6 +119,8 @@ const handleCopyEvent = (event) => { const dataToCopy = JSON.stringify(selectedNodes) setClipboardSchema(event, dataToCopy) + + clearMultiSelection() } const handlerClipboardEvent = (event) => { @@ -165,4 +167,4 @@ const registerHotkeyEvent = (dom) => { dom.addEventListener('paste', handlerClipboardEvent) } -export { registerHotkeyEvent, removeHotkeyEvent, multiSelectedStates } +export { registerHotkeyEvent, removeHotkeyEvent } From e996bacd67fef7c5c6f9ca257271a5edb643638d Mon Sep 17 00:00:00 2001 From: SonyLeo <746591437@qq.com> Date: Mon, 3 Mar 2025 04:31:42 -0800 Subject: [PATCH 3/7] fix: optimize click outline tree and multi-select node logic conflicts --- .../canvas/container/src/composables/useMultiSelect.js | 10 +++++++++- packages/canvas/container/src/container.js | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/canvas/container/src/composables/useMultiSelect.js b/packages/canvas/container/src/composables/useMultiSelect.js index 6f03b3baa5..927973260e 100644 --- a/packages/canvas/container/src/composables/useMultiSelect.js +++ b/packages/canvas/container/src/composables/useMultiSelect.js @@ -3,8 +3,10 @@ import { useCanvas } from '@opentiny/tiny-engine-meta-register' import { NODE_TAG, NODE_UID } from '../../../common' import { getRect, getDocument } from '../container' +const initMultiState = { id: 'body' } + // 初始化多选节点 -const multiSelectedStates = ref([{ id: 'body', componentName: 'body' }]) +const multiSelectedStates = ref([]) // 节点位置缓存 let nodeRectCache = new WeakMap() @@ -25,6 +27,11 @@ export const useMultiSelect = () => { const multiStateLength = computed(() => multiSelectedStates.value.length) + // 初始化多选节点 + const initMultiSelect = () => { + multiSelectedStates.value = [initMultiState] + } + // 设置多选节点 const setMultiSelection = (node, append = false) => { if (!node || typeof node !== 'object') { @@ -95,6 +102,7 @@ export const useMultiSelect = () => { return { multiSelectedStates, multiStateLength, + initMultiSelect, setMultiSelection, getMultiSelectionState, toggleMultiSelection, diff --git a/packages/canvas/container/src/container.js b/packages/canvas/container/src/container.js index b8edfc975a..f4f741da74 100644 --- a/packages/canvas/container/src/container.js +++ b/packages/canvas/container/src/container.js @@ -24,6 +24,7 @@ import { useCanvas, useLayout, useTranslate, useMaterial } from '@opentiny/tiny- import { utils } from '@opentiny/tiny-engine-utils' import { isVsCodeEnv } from '@opentiny/tiny-engine-common/js/environments' import Builtin from '../../render/src/builtin/builtin.json' //TODO 画布内外应该分开 +import { useMultiSelect } from './composables/useMultiSelect' export const POSITION = Object.freeze({ TOP: 'top', @@ -709,6 +710,8 @@ export const dragMove = (event, isHover) => { } } +const { clearMultiSelection, initMultiSelect } = useMultiSelect() + // type == clickTree, 为点击大纲; type == loop-id=xxx ,为点击循环数据 export const selectNode = async (id, type) => { if (type && type.indexOf('loop-id') > -1) { @@ -716,6 +719,11 @@ export const selectNode = async (id, type) => { canvasState.loopId = loopId } + if (type === 'clickTree') { + clearMultiSelection() + initMultiSelect() + } + const { node, parent } = useCanvas().getNodeWithParentById(id) || {} let element = querySelectById(id, type) From 53371bdfca3e9346967b80c77aba3a4998f28163 Mon Sep 17 00:00:00 2001 From: SonyLeo <746591437@qq.com> Date: Thu, 6 Mar 2025 00:23:52 -0800 Subject: [PATCH 4/7] fix: box selection effect is misplaced when the multi-selection node scrolls --- .../canvas/container/src/CanvasContainer.vue | 4 +-- .../src/composables/useMultiSelect.js | 30 +++++++++---------- packages/canvas/container/src/container.js | 28 +++++++++++++++-- packages/canvas/container/src/keyboard.js | 2 -- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/packages/canvas/container/src/CanvasContainer.vue b/packages/canvas/container/src/CanvasContainer.vue index 77bc9def61..68a8e0facb 100644 --- a/packages/canvas/container/src/CanvasContainer.vue +++ b/packages/canvas/container/src/CanvasContainer.vue @@ -67,7 +67,7 @@ import { selectState, lineState, removeNodeById, - updateRect, + syncNodeScroll, getElement, dragStart, selectNode, @@ -268,7 +268,7 @@ export default { registerHotkeyEvent(doc) - win.addEventListener('scroll', updateRect, true) + win.addEventListener('scroll', syncNodeScroll, true) } } // 设置弹窗 diff --git a/packages/canvas/container/src/composables/useMultiSelect.js b/packages/canvas/container/src/composables/useMultiSelect.js index 927973260e..9b3a7b8717 100644 --- a/packages/canvas/container/src/composables/useMultiSelect.js +++ b/packages/canvas/container/src/composables/useMultiSelect.js @@ -33,23 +33,23 @@ export const useMultiSelect = () => { } // 设置多选节点 - const setMultiSelection = (node, append = false) => { - if (!node || typeof node !== 'object') { + const setMultiSelection = (nodes) => { + if (Array.isArray(nodes)) { + multiSelectedStates.value = nodes + } else if (nodes && typeof nodes === 'object') { + multiSelectedStates.value = [nodes] + } else { multiSelectedStates.value = [] - return } + } - if (append) { - const nodeIds = new Set(multiSelectedStates.value.map((state) => state.id)) - if (!nodeIds.has(node.id)) { - multiSelectedStates.value.push(node) - } - } else { - if (Array.isArray(node)) { - multiSelectedStates.value = node - } else { - multiSelectedStates.value = [node] - } + // 添加节点到多选列表 + const addMultiSelection = (node) => { + if (!node || typeof node !== 'object') return + + const nodeIds = multiSelectedStates.value.map((state) => state.id) + if (!nodeIds.includes(node.id)) { + multiSelectedStates.value.push(node) } } @@ -62,7 +62,7 @@ export const useMultiSelect = () => { const exList = multiSelectedStates.value.filter((state) => state.id !== nodeId) setMultiSelection(exList) } else { - setMultiSelection(selectState, true) + addMultiSelection(selectState) } } diff --git a/packages/canvas/container/src/container.js b/packages/canvas/container/src/container.js index f4f741da74..3599af9fc7 100644 --- a/packages/canvas/container/src/container.js +++ b/packages/canvas/container/src/container.js @@ -391,7 +391,10 @@ export const scrollToNode = (element) => { return nextTick() } -const setSelectRect = (element) => { + +const { clearMultiSelection, initMultiSelect, multiSelectedStates, multiStateLength } = useMultiSelect() + +const setSelectRect = (element, multiNodeId) => { element = element || getDocument().body const { left, height, top, width } = getRect(element) @@ -405,6 +408,14 @@ const setSelectRect = (element) => { componentName, doc: getDocument() }) + + if (multiNodeId) { + multiSelectedStates.value.map((state) => { + if (state.id === multiNodeId) { + return Object.assign(state, selectState) + } + }) + } } export const updateRect = (id) => { @@ -422,6 +433,18 @@ export const updateRect = (id) => { } } +export const syncNodeScroll = (id) => { + if (multiStateLength.value > 1) { + multiSelectedStates.value.forEach((state) => { + const multiNodeId = state.id + const element = querySelectById(multiNodeId) + setTimeout(() => setSelectRect(element, multiNodeId)) + }) + } else { + updateRect(id) + } +} + export const getConfigure = (targetName) => { const material = getController().getMaterial(targetName) @@ -710,8 +733,6 @@ export const dragMove = (event, isHover) => { } } -const { clearMultiSelection, initMultiSelect } = useMultiSelect() - // type == clickTree, 为点击大纲; type == loop-id=xxx ,为点击循环数据 export const selectNode = async (id, type) => { if (type && type.indexOf('loop-id') > -1) { @@ -882,6 +903,7 @@ export const canvasDispatch = (name, data, doc = getDocument()) => { export const canvasApi = { dragStart, updateRect, + syncNodeScroll, dragMove, setLocales, getRenderer, diff --git a/packages/canvas/container/src/keyboard.js b/packages/canvas/container/src/keyboard.js index 48da8e51b4..bb47b33910 100644 --- a/packages/canvas/container/src/keyboard.js +++ b/packages/canvas/container/src/keyboard.js @@ -119,8 +119,6 @@ const handleCopyEvent = (event) => { const dataToCopy = JSON.stringify(selectedNodes) setClipboardSchema(event, dataToCopy) - - clearMultiSelection() } const handlerClipboardEvent = (event) => { From 7672a14ef19501b9c7b611afee664cc9e5f619af Mon Sep 17 00:00:00 2001 From: SonyLeo <746591437@qq.com> Date: Thu, 6 Mar 2025 05:07:47 -0800 Subject: [PATCH 5/7] fix: review --- .../canvas/container/src/composables/useMultiSelect.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/canvas/container/src/composables/useMultiSelect.js b/packages/canvas/container/src/composables/useMultiSelect.js index 9b3a7b8717..c77d247001 100644 --- a/packages/canvas/container/src/composables/useMultiSelect.js +++ b/packages/canvas/container/src/composables/useMultiSelect.js @@ -47,8 +47,7 @@ export const useMultiSelect = () => { const addMultiSelection = (node) => { if (!node || typeof node !== 'object') return - const nodeIds = multiSelectedStates.value.map((state) => state.id) - if (!nodeIds.includes(node.id)) { + if (!multiSelectedStates.value.some((state) => state.id === node.id)) { multiSelectedStates.value.push(node) } } @@ -56,10 +55,10 @@ export const useMultiSelect = () => { // 处理多选节点 const toggleMultiSelection = (selectState) => { const nodeId = selectState?.id - const isExistNode = multiSelectedStates.value.map((state) => state.id).includes(nodeId) + const isExistNode = multiSelectedStates.value.some((state) => state.id === nodeId) if (nodeId && isExistNode) { - const exList = multiSelectedStates.value.filter((state) => state.id !== nodeId) + const exList = toRaw(multiSelectedStates.value).filter((state) => state.id !== nodeId) setMultiSelection(exList) } else { addMultiSelection(selectState) From 8481624a0607fd8dac63a27aed1551f21a1b7540 Mon Sep 17 00:00:00 2001 From: SonyLeo <746591437@qq.com> Date: Thu, 6 Mar 2025 17:59:08 -0800 Subject: [PATCH 6/7] fix: refactor multiSelect logic --- .../canvas/container/src/CanvasContainer.vue | 22 +++------- .../src/composables/useMultiSelect.js | 42 +++++++++++++------ 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/packages/canvas/container/src/CanvasContainer.vue b/packages/canvas/container/src/CanvasContainer.vue index 68a8e0facb..735d1f571f 100644 --- a/packages/canvas/container/src/CanvasContainer.vue +++ b/packages/canvas/container/src/CanvasContainer.vue @@ -34,12 +34,8 @@
- + +
@@ -211,16 +207,7 @@ export default { return } - // 多选组合键触发 - if (element) { - const selectedState = getMultiSelectionState(element) - if ((event.ctrlKey || event.metaKey) && event.button === 0) { - if (selectedState) { - toggleMultiSelection(selectedState) - } - return - } - } + if (toggleMultiSelection(event, element)) return insertPosition.value = false insertContainer.value = false @@ -367,15 +354,18 @@ export default { top: 200px; left: 400px; width: 480px; + :deep(.components-wrap) { & > .tiny-collapse { max-height: 300px; } } + :deep(#pane-blocks) { max-height: 400px; } } + .datainit-tip { display: flex; height: 100%; diff --git a/packages/canvas/container/src/composables/useMultiSelect.js b/packages/canvas/container/src/composables/useMultiSelect.js index c77d247001..c7c26b2962 100644 --- a/packages/canvas/container/src/composables/useMultiSelect.js +++ b/packages/canvas/container/src/composables/useMultiSelect.js @@ -52,19 +52,6 @@ export const useMultiSelect = () => { } } - // 处理多选节点 - const toggleMultiSelection = (selectState) => { - const nodeId = selectState?.id - const isExistNode = multiSelectedStates.value.some((state) => state.id === nodeId) - - if (nodeId && isExistNode) { - const exList = toRaw(multiSelectedStates.value).filter((state) => state.id !== nodeId) - setMultiSelection(exList) - } else { - addMultiSelection(selectState) - } - } - // 获取多选节点(带缓存) const getMultiSelectionState = (element) => { if (!element) { @@ -98,6 +85,35 @@ export const useMultiSelect = () => { nodeRectCache = new WeakMap() // 清空缓存 } + // 处理多选节点 + const toggleMultiSelection = (event, element) => { + const isCtrlKey = event.ctrlKey || event.metaKey + const selectState = getMultiSelectionState(element) + + if (!selectState) { + return false // 如果没有有效的 selectState,返回 false + } + + const nodeId = selectState?.id + const isExistNode = multiSelectedStates.value.some((state) => state.id === nodeId) + + if (isCtrlKey && event.button === 0) { + // 按住Ctrl或Meta键时,切换多选状态 + if (isExistNode && nodeId) { + const exList = toRaw(multiSelectedStates.value).filter((state) => state.id !== nodeId) + setMultiSelection(exList) + } else { + addMultiSelection(selectState) + } + return true + } else { + // 没有按住Ctrl或Meta键时,清除所有多选状态并添加当前节点 + clearMultiSelection() + addMultiSelection(selectState) + return false + } + } + return { multiSelectedStates, multiStateLength, From 9d41f43d0853238bde385ac5dcdfb7d255f56445 Mon Sep 17 00:00:00 2001 From: SonyLeo <746591437@qq.com> Date: Thu, 6 Mar 2025 18:06:31 -0800 Subject: [PATCH 7/7] fix: remove format change --- packages/canvas/container/src/CanvasContainer.vue | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/canvas/container/src/CanvasContainer.vue b/packages/canvas/container/src/CanvasContainer.vue index 735d1f571f..0fd5269828 100644 --- a/packages/canvas/container/src/CanvasContainer.vue +++ b/packages/canvas/container/src/CanvasContainer.vue @@ -34,8 +34,12 @@
- - +
@@ -354,18 +358,15 @@ export default { top: 200px; left: 400px; width: 480px; - :deep(.components-wrap) { & > .tiny-collapse { max-height: 300px; } } - :deep(#pane-blocks) { max-height: 400px; } } - .datainit-tip { display: flex; height: 100%;