From cbd069ca0aa68f4a7944697b19071eb1b65cf375 Mon Sep 17 00:00:00 2001 From: baiqi Date: Tue, 30 Jul 2024 18:02:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=84=91=E5=9B=BE):=20=E8=84=91=E5=9B=BE?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E7=BB=84=E4=BB=B6=E6=94=AF=E6=8C=81=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E9=94=AE&=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E5=92=8C=E5=8A=9F=E8=83=BD=E7=94=A8=E4=BE=8B=E8=84=91=E5=9B=BE?= =?UTF-8?q?=E5=BF=AB=E6=8D=B7=E9=94=AE=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../featureCaseMinder/useMinderBaseApi.ts | 5 +- .../ms-minders/testPlanMinder/index.vue | 15 ++ .../hooks/useMinderOperation.ts | 237 ++++++++++++++++++ .../ms-minder-editor/hooks/useShortCut.ts | 71 +++++- .../pure/ms-minder-editor/main/mainEditor.vue | 2 - .../pure/ms-minder-editor/main/navigator.vue | 25 +- .../ms-minder-editor/menu/edit/editDel.vue | 73 ------ .../ms-minder-editor/menu/edit/editMenu.vue | 117 --------- .../ms-minder-editor/menu/edit/expand.vue | 22 -- .../ms-minder-editor/menu/edit/insertBox.vue | 91 ------- .../ms-minder-editor/menu/edit/moveBox.vue | 81 ------ .../menu/edit/progressBox.vue | 97 ------- .../ms-minder-editor/menu/edit/selection.vue | 123 --------- .../menu/edit/sequenceBox.vue | 157 ------------ .../ms-minder-editor/menu/edit/tagBox.vue | 130 ---------- .../ms-minder-editor/menu/nodeFloatMenu.vue | 81 +----- .../pure/ms-minder-editor/minderEditor.vue | 67 ++++- .../components/pure/ms-minder-editor/props.ts | 11 +- .../ms-minder-editor/script/tool/utils.ts | 28 ++- frontend/src/enums/minderEnum.ts | 1 + .../modules/components/minder-editor/index.ts | 10 +- .../management/api/preview/index.vue | 2 +- 22 files changed, 452 insertions(+), 994 deletions(-) create mode 100644 frontend/src/components/pure/ms-minder-editor/hooks/useMinderOperation.ts delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/editDel.vue delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/editMenu.vue delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/expand.vue delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/insertBox.vue delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/moveBox.vue delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/progressBox.vue delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/selection.vue delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/sequenceBox.vue delete mode 100644 frontend/src/components/pure/ms-minder-editor/menu/edit/tagBox.vue diff --git a/frontend/src/components/business/ms-minders/featureCaseMinder/useMinderBaseApi.ts b/frontend/src/components/business/ms-minders/featureCaseMinder/useMinderBaseApi.ts index 261a8d7b09..e212032923 100644 --- a/frontend/src/components/business/ms-minders/featureCaseMinder/useMinderBaseApi.ts +++ b/frontend/src/components/business/ms-minders/featureCaseMinder/useMinderBaseApi.ts @@ -432,7 +432,10 @@ export default function useMinderBaseApi({ hasEditPermission }: { hasEditPermiss } else if (node.data?.resource?.includes(prerequisiteTag) && (!node.children || node.children.length === 0)) { // 当前节点是前置操作,则默认添加一个文本节点 execInert('AppendChildNode'); - } else { + } else if ( + (!node.data?.resource || node.data?.resource?.length === 0) && + (!node.parent?.data?.resource || node.parent?.data?.resource?.length === 0) + ) { // 文本节点下可添加文本节点 execInert('AppendChildNode'); } diff --git a/frontend/src/components/business/ms-minders/testPlanMinder/index.vue b/frontend/src/components/business/ms-minders/testPlanMinder/index.vue index 6ad23568ba..a61cab048d 100644 --- a/frontend/src/components/business/ms-minders/testPlanMinder/index.vue +++ b/frontend/src/components/business/ms-minders/testPlanMinder/index.vue @@ -373,6 +373,12 @@ * @param value 插入值 */ function insertNode(node: PlanMinderNode, type: string) { + if ( + (node.data?.level === 2 && type === 'AppendChildNode') || + (node.data?.level === 1 && type === 'AppendSiblingNode') + ) { + return; + } let child: PlanMinderNodeData | undefined; // 用例数子节点 const caseCountNodeData = { @@ -633,6 +639,15 @@ } ); + watch( + () => minderStore.event.eventId, + () => { + if ([MinderEventName.EXPAND, MinderEventName.COLLAPSE].includes(minderStore.event.name)) { + setCustomPriorityView(priorityTextMap); + } + } + ); + function handleConfigCancel() { clearSelectedCases(); extraVisible.value = false; diff --git a/frontend/src/components/pure/ms-minder-editor/hooks/useMinderOperation.ts b/frontend/src/components/pure/ms-minder-editor/hooks/useMinderOperation.ts new file mode 100644 index 0000000000..ba7343a8ba --- /dev/null +++ b/frontend/src/components/pure/ms-minder-editor/hooks/useMinderOperation.ts @@ -0,0 +1,237 @@ +import useMinderStore from '@/store/modules/components/minder-editor'; +import { getGenerateId } from '@/utils'; + +import { MinderEventName } from '@/enums/minderEnum'; + +import type { MinderJsonNode } from '../props'; +import { markDeleteNode, resetNodes } from '../script/tool/utils'; + +interface IData { + getRegisterProtocol(protocol: string): { + encode: (nodes: Array) => Array; + decode: (nodes: Array) => Array; + }; +} + +export interface MinderOperationProps { + insertNode?: (node: MinderJsonNode, command: string, value?: string) => void; + canShowMoreMenuNodeOperation?: boolean; + canShowPasteMenu?: boolean; +} + +export default function useMinderOperation({ + insertNode, + canShowMoreMenuNodeOperation, + canShowPasteMenu, +}: MinderOperationProps) { + const minderStore = useMinderStore(); + + function encode(nodes: Array): string { + const { editor } = window; + const { minder, MimeType } = editor; + const Data: IData = window.kityminder.data; + const kmencode = MimeType.getMimeTypeProtocol('application/km'); + const _nodes = []; + for (let i = 0, l = nodes.length; i < l; i++) { + // @ts-ignore + _nodes.push(minder.exportNode(nodes[i])); + } + return kmencode(Data.getRegisterProtocol('json').encode(_nodes)); + } + + /** + * 执行复制 + */ + const minderCopy = (e?: ClipboardEvent) => { + if (!canShowMoreMenuNodeOperation) { + return; + } + const { editor } = window; + const { minder, fsm } = editor; + const state = fsm.state(); + switch (state) { + case 'input': { + break; + } + case 'normal': { + const selectedNodes = minder.getSelectedNodes(); + minderStore.dispatchEvent(MinderEventName.COPY_NODE, undefined, undefined, undefined, selectedNodes); + minder.execCommand('Copy'); + e?.preventDefault(); + break; + } + default: + } + }; + + /** + * 执行剪切 + */ + const minderCut = (e?: ClipboardEvent) => { + if (!canShowMoreMenuNodeOperation) { + return; + } + const { editor } = window; + const { minder, fsm } = editor; + if (minder.getStatus() !== 'normal') { + e?.preventDefault(); + return; + } + + const state = fsm.state(); + + switch (state) { + case 'input': { + break; + } + case 'normal': { + markDeleteNode(minder); + const selectedNodes = minder.getSelectedNodes(); + if (selectedNodes.length) { + e?.clipboardData?.setData('text/plain', encode(selectedNodes)); + minder.execCommand('Cut'); + } + e?.preventDefault(); + minderStore.dispatchEvent(MinderEventName.CUT_NODE, undefined, undefined, undefined, selectedNodes); + break; + } + default: + } + }; + + /** + * 执行粘贴 + */ + const minderPaste = (e?: ClipboardEvent) => { + if (!canShowMoreMenuNodeOperation || !canShowPasteMenu) { + return; + } + const { editor } = window; + const { minder, fsm, MimeType } = editor; + const Data: IData = window.kityminder.data; + const { decode } = Data.getRegisterProtocol('json'); + if (minder.getStatus() !== 'normal') { + e?.preventDefault(); + return; + } + + const state = fsm.state(); + const textData = e?.clipboardData?.getData('text/plain'); + + switch (state) { + case 'input': { + // input状态下如果格式为application/km则不进行paste操作 + if (!MimeType.isPureText(textData)) { + e?.preventDefault(); + } + break; + } + case 'normal': { + /* + * 针对normal状态下通过对选中节点粘贴导入子节点文本进行单独处理 + */ + const sNodes = minder.getSelectedNodes(); + const selectedNodes: MinderJsonNode[] = []; + minderStore.dispatchEvent(MinderEventName.PASTE_NODE, undefined, undefined, undefined, selectedNodes); + if (MimeType.whichMimeType(textData) === 'application/km') { + const nodes = decode(MimeType.getPureText(textData)); + sNodes.forEach((node: MinderJsonNode) => { + const noFakeNodeTree = resetNodes(nodes); // 每次粘贴复制的节点集合到新的节点之前,都需要重置节点集合的信息 + let _node; + // 由于粘贴逻辑中为了排除子节点重新排序导致逆序,因此复制的时候倒过来 + for (let i = noFakeNodeTree.length - 1; i >= 0; i--) { + _node = minder.createNode(null, node); + minder.importNode(_node, noFakeNodeTree[i]); + selectedNodes.push(_node); + node.appendChild(_node); + } + }); + window.minder.execCommand('Expand'); // 展开当前所有选中的节点,避免无子节点的节点在粘贴后还是折叠状态 + minder.select(selectedNodes, true); + minder.refresh(); + } else if (e?.clipboardData && e.clipboardData.items[0].type.indexOf('image') > -1) { + const imageFile = e?.clipboardData.items[0].getAsFile(); + const serverService = window.angular.element(document.body).injector().get('server'); + + return serverService.uploadImage(imageFile).then((json: Record) => { + const resp = json.data; + if (resp.errno === 0) { + minder.execCommand('image', resp.data.url); + } + }); + } else { + sNodes.forEach((node: MinderJsonNode) => { + minder.Text2Children(node, textData); + }); + } + e?.preventDefault(); + break; + } + default: + } + }; + + /** + * 执行插入 + * @param command 插入命令 + * @param value 携带的参数 + */ + const execInsertCommand = (command: string, value?: string) => { + const node: MinderJsonNode = window.minder.getSelectedNode(); + if (insertNode) { + insertNode(node, command, value); + return; + } + if (window.minder.queryCommandState(command) !== -1) { + window.minder.execCommand(command); + nextTick(() => { + const newNode: MinderJsonNode = window.minder.getSelectedNode(); + if (!newNode.data) { + newNode.data = { + id: getGenerateId(), + text: '', + }; + } + newNode.data.isNew = true; // 新建的节点标记为新建 + }); + } + }; + + /** + * 插入子节点 + * @param selectedNodes 当前选中的节点集合 + * @param value 携带的参数 + */ + const appendChildNode = (selectedNodes: MinderJsonNode[], value?: string) => { + execInsertCommand('AppendChildNode', value); + minderStore.dispatchEvent(MinderEventName.INSERT_CHILD, value, undefined, undefined, selectedNodes); + }; + + /** + * 插入兄弟节点 + * @param selectedNodes 当前选中的节点集合 + * @param value 携带的参数 + */ + const appendSiblingNode = (selectedNodes: MinderJsonNode[], value?: string) => { + execInsertCommand('AppendSiblingNode', value); + minderStore.dispatchEvent(MinderEventName.INSERT_SIBLING, value, undefined, undefined, selectedNodes); + }; + + /** + * 删除节点 + * @param selectedNodes 当前选中的节点集合 + */ + const minderDelete = (selectedNodes: MinderJsonNode[]) => { + minderStore.dispatchEvent(MinderEventName.DELETE_NODE, undefined, undefined, undefined, selectedNodes); + window.minder.execCommand('RemoveNode'); + }; + + return { + minderCopy, + minderCut, + minderPaste, + appendChildNode, + appendSiblingNode, + minderDelete, + }; +} diff --git a/frontend/src/components/pure/ms-minder-editor/hooks/useShortCut.ts b/frontend/src/components/pure/ms-minder-editor/hooks/useShortCut.ts index a6e8008326..9153a4fa8d 100644 --- a/frontend/src/components/pure/ms-minder-editor/hooks/useShortCut.ts +++ b/frontend/src/components/pure/ms-minder-editor/hooks/useShortCut.ts @@ -1 +1,70 @@ -export default function useShortCut() {} +import useMinderOperation, { type MinderOperationProps } from './useMinderOperation'; + +type ShortcutKey = 'expand' | 'enter' | 'appendSiblingNode' | 'appendChildNode' | 'undo' | 'redo' | 'delete'; +// 快捷键事件映射,combinationShortcuts中定义了组合键事件,key为组合键,value为事件名称; +type Shortcuts = { + [key in ShortcutKey]?: () => void; +}; + +export default function useShortCut(shortcuts: Shortcuts, options: MinderOperationProps) { + const { minderCopy, minderCut, minderPaste } = useMinderOperation(options); + + const handleKeyDown = (event: KeyboardEvent) => { + const key = event.key.toLowerCase(); + const isCtrlOrCmd = event.ctrlKey || event.metaKey; + + // 定义组合键事件 + const combinationShortcuts: { [key: string]: ShortcutKey } = { + z: 'undo', // 撤销 + y: 'redo', // 重做 + enter: 'enter', // 进入节点 + }; + // 定义单键事件 + const singleShortcuts: { [key: string]: ShortcutKey } = { + '/': 'expand', // 展开/折叠 + 'enter': 'appendSiblingNode', + 'tab': 'appendChildNode', + 'backspace': 'delete', + }; + + if (isCtrlOrCmd && combinationShortcuts[key]) { + // 执行组合键事件 + event.preventDefault(); + const action = combinationShortcuts[key]; + if (shortcuts[action]) { + shortcuts[action]!(); + } + } else if (singleShortcuts[key]) { + // 执行单键事件 + event.preventDefault(); + const action = singleShortcuts[key]; + if (shortcuts[action]) { + shortcuts[action]!(); + } + } + }; + + onMounted(() => { + const minderContainer = document.querySelector('.ms-minder-container'); + if (minderContainer) { + minderContainer.addEventListener('keydown', (e) => handleKeyDown(e as KeyboardEvent)); + minderContainer.addEventListener('copy', (e) => minderCopy(e as ClipboardEvent)); + minderContainer.addEventListener('cut', (e) => minderCut(e as ClipboardEvent)); + minderContainer.addEventListener('paste', (e) => minderPaste(e as ClipboardEvent)); + } + }); + + function unbindShortcuts() { + const minderContainer = document.querySelector('.ms-minder-container'); + if (minderContainer) { + minderContainer.removeEventListener('keydown', (e) => handleKeyDown(e as KeyboardEvent)); + minderContainer.removeEventListener('copy', (e) => minderCopy(e as ClipboardEvent)); + minderContainer.removeEventListener('cut', (e) => minderCut(e as ClipboardEvent)); + minderContainer.removeEventListener('paste', (e) => minderPaste(e as ClipboardEvent)); + } + } + + return { + unbindShortcuts, + }; +} diff --git a/frontend/src/components/pure/ms-minder-editor/main/mainEditor.vue b/frontend/src/components/pure/ms-minder-editor/main/mainEditor.vue index c89e368c1f..d3712b4164 100644 --- a/frontend/src/components/pure/ms-minder-editor/main/mainEditor.vue +++ b/frontend/src/components/pure/ms-minder-editor/main/mainEditor.vue @@ -50,7 +50,6 @@ editMenuProps, floatMenuProps, headerProps, - insertProps, mainEditorProps, MinderJson, MinderJsonNode, @@ -66,7 +65,6 @@ ...headerProps, ...floatMenuProps, ...editMenuProps, - ...insertProps, ...mainEditorProps, ...tagProps, ...priorityProps, diff --git a/frontend/src/components/pure/ms-minder-editor/main/navigator.vue b/frontend/src/components/pure/ms-minder-editor/main/navigator.vue index 2080b28394..2ac1c29f43 100644 --- a/frontend/src/components/pure/ms-minder-editor/main/navigator.vue +++ b/frontend/src/components/pure/ms-minder-editor/main/navigator.vue @@ -39,7 +39,7 @@ - +
@@ -325,7 +334,7 @@ }); } - // const shortcutTriggerVisible = ref(false); + const shortcutTriggerVisible = ref(false); onMounted(() => { nextTick(() => { diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/editDel.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/editDel.vue deleted file mode 100644 index 208b554d74..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/editDel.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/editMenu.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/editMenu.vue deleted file mode 100644 index 4506311dea..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/editMenu.vue +++ /dev/null @@ -1,117 +0,0 @@ - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/expand.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/expand.vue deleted file mode 100644 index 975c13a9a9..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/expand.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/insertBox.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/insertBox.vue deleted file mode 100644 index b2578a6607..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/insertBox.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/moveBox.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/moveBox.vue deleted file mode 100644 index e828d66d40..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/moveBox.vue +++ /dev/null @@ -1,81 +0,0 @@ - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/progressBox.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/progressBox.vue deleted file mode 100644 index 95eef9e966..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/progressBox.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/selection.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/selection.vue deleted file mode 100644 index 12715475fd..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/selection.vue +++ /dev/null @@ -1,123 +0,0 @@ - - - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/sequenceBox.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/sequenceBox.vue deleted file mode 100644 index 0847ecf68c..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/sequenceBox.vue +++ /dev/null @@ -1,157 +0,0 @@ - - - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/edit/tagBox.vue b/frontend/src/components/pure/ms-minder-editor/menu/edit/tagBox.vue deleted file mode 100644 index 2dfbbe0637..0000000000 --- a/frontend/src/components/pure/ms-minder-editor/menu/edit/tagBox.vue +++ /dev/null @@ -1,130 +0,0 @@ - - - - - diff --git a/frontend/src/components/pure/ms-minder-editor/menu/nodeFloatMenu.vue b/frontend/src/components/pure/ms-minder-editor/menu/nodeFloatMenu.vue index 3021d39c71..079a2554c6 100644 --- a/frontend/src/components/pure/ms-minder-editor/menu/nodeFloatMenu.vue +++ b/frontend/src/components/pure/ms-minder-editor/menu/nodeFloatMenu.vue @@ -195,25 +195,17 @@ import { useI18n } from '@/hooks/useI18n'; import useMinderStore from '@/store/modules/components/minder-editor/index'; import { MinderNodePosition } from '@/store/modules/components/minder-editor/types'; - import { getGenerateId, sleep } from '@/utils'; + import { sleep } from '@/utils'; import { MinderEventName } from '@/enums/minderEnum'; - import { - floatMenuProps, - insertProps, - mainEditorProps, - MinderJsonNode, - MinderJsonNodeData, - priorityProps, - tagProps, - } from '../props'; + import useMinderOperation from '../hooks/useMinderOperation'; + import { floatMenuProps, mainEditorProps, MinderJsonNode, priorityProps, tagProps } from '../props'; import { isDisableNode, isNodeInMinderView, setPriorityView } from '../script/tool/utils'; const props = defineProps({ ...mainEditorProps, ...floatMenuProps, - ...insertProps, ...tagProps, ...priorityProps, }); @@ -277,31 +269,6 @@ const priorityMenuVisible = ref(false); const moreMenuVisible = ref(false); - /** - * 执行插入 - * @param command 插入命令 - */ - function execInsertCommand(command: string, value?: string) { - const node: MinderJsonNode = window.minder.getSelectedNode(); - if (props.insertNode) { - props.insertNode(node, command, value); - return; - } - if (window.minder.queryCommandState(command) !== -1) { - window.minder.execCommand(command); - nextTick(() => { - const newNode: MinderJsonNode = window.minder.getSelectedNode(); - if (!newNode.data) { - newNode.data = { - id: getGenerateId(), - text: '', - }; - } - newNode.data.isNew = true; // 新建的节点标记为新建 - }); - } - } - /** * 切换标签 * @param value 切换后的标签 @@ -359,6 +326,10 @@ return !!window.minder.queryCommandState && window.minder.queryCommandState('priority') === -1; } + const { minderCopy, minderCut, minderPaste, appendChildNode, appendSiblingNode, minderDelete } = useMinderOperation({ + insertNode: props.insertNode, + }); + /** * 处理快捷菜单选择 * @param type 选择的菜单项 @@ -368,48 +339,22 @@ if (selectedNodes.length > 0) { switch (type) { case 'AppendChildNode': - execInsertCommand('AppendChildNode', value); - minderStore.dispatchEvent(MinderEventName.INSERT_CHILD, value, undefined, undefined, selectedNodes); + appendChildNode(selectedNodes, value); break; case 'AppendSiblingNode': - execInsertCommand('AppendSiblingNode', value); - minderStore.dispatchEvent(MinderEventName.INSERT_SIBLING, value, undefined, undefined, selectedNodes); + appendSiblingNode(selectedNodes, value); break; case 'copy': - minderStore.dispatchEvent(MinderEventName.COPY_NODE, undefined, undefined, undefined, selectedNodes); - window.minder.execCommand('Copy'); + minderCopy(); break; case 'cut': - minderStore.dispatchEvent(MinderEventName.CUT_NODE, undefined, undefined, undefined, selectedNodes); - window.minder.execCommand('Cut'); + minderCut(); break; case 'paste': - minderStore.dispatchEvent(MinderEventName.PASTE_NODE, undefined, undefined, undefined, selectedNodes); - window.minder.execCommand('Paste'); - let pastedNodes: MinderJsonNode[] = window.minder.getSelectedNodes(); - if (pastedNodes.length > 0) { - pastedNodes = pastedNodes - .filter((e) => { - if (e.data?.id !== 'fakeNode' && e.data?.type !== 'tmp') { - return true; - } - window.minder.removeNode(e); - return false; - }) - .map((e) => { - e.data = { - ...(e.data as MinderJsonNodeData), - isNew: true, - id: getGenerateId(), - count: e.children?.length || 0, - }; - return e; - }); - } + minderPaste(); break; case 'delete': - minderStore.dispatchEvent(MinderEventName.DELETE_NODE, undefined, undefined, undefined, selectedNodes); - window.minder.execCommand('RemoveNode'); + minderDelete(selectedNodes); break; case 'enterNode': minderStore.dispatchEvent(MinderEventName.ENTER_NODE, undefined, undefined, undefined, [selectedNodes[0]]); diff --git a/frontend/src/components/pure/ms-minder-editor/minderEditor.vue b/frontend/src/components/pure/ms-minder-editor/minderEditor.vue index 36a644e480..8a9ef924f9 100644 --- a/frontend/src/components/pure/ms-minder-editor/minderEditor.vue +++ b/frontend/src/components/pure/ms-minder-editor/minderEditor.vue @@ -34,12 +34,13 @@ import { MinderEventName } from '@/enums/minderEnum'; import useMinderEventListener from './hooks/useMinderEventListener'; + import useMinderOperation from './hooks/useMinderOperation'; + import useShortCut from './hooks/useShortCut'; import { delProps, editMenuProps, floatMenuProps, headerProps, - insertProps, mainEditorProps, MinderEvent, MinderJson, @@ -49,7 +50,7 @@ tagProps, viewMenuProps, } from './props'; - import { isNodeInMinderView } from './script/tool/utils'; + import { isNodeInMinderView, setPriorityView } from './script/tool/utils'; const emit = defineEmits<{ (e: 'moldChange', data: number): void; @@ -66,7 +67,6 @@ const props = defineProps({ ...headerProps, ...floatMenuProps, - ...insertProps, ...editMenuProps, ...mainEditorProps, ...moleProps, @@ -115,6 +115,63 @@ emit('save', data, callback); } + const { appendChildNode, appendSiblingNode, minderDelete } = useMinderOperation({ + insertNode: props.insertNode, + }); + const { unbindShortcuts } = useShortCut( + { + undo: () => { + window.minderHistory?.undo(); + }, + redo: () => { + window.minderHistory?.redo(); + }, + enter: () => { + if (props.canShowEnterNode) { + const selectedNodes: MinderJsonNode[] = window.minder.getSelectedNodes(); + minderStore.dispatchEvent(MinderEventName.ENTER_NODE, undefined, undefined, undefined, [selectedNodes[0]]); + } + }, + delete: () => { + if (props.canShowMoreMenuNodeOperation && props.canShowDeleteMenu) { + const selectedNodes: MinderJsonNode[] = window.minder.getSelectedNodes(); + minderDelete(selectedNodes); + } + }, + expand: () => { + const selectedNodes: MinderJsonNode[] = window.minder.getSelectedNodes(); + if (selectedNodes.every((node) => node.isExpanded())) { + // 选中的节点集合全部展开,则全部收起 + window.minder.execCommand('Collapse'); + minderStore.dispatchEvent(MinderEventName.COLLAPSE, undefined, undefined, undefined, selectedNodes); + } else { + // 选中的节点集合中有一个节点未展开,则全部展开 + window.minder.execCommand('Expand'); + if (!props.customPriority) { + // 展开后,需要设置一次优先级展示,避免展开后优先级显示成脑图内置文案;如果设置了自定义优先级,则不在此设置,由外部自行处理 + setPriorityView(props.priorityStartWithZero, props.priorityPrefix); + } + minderStore.dispatchEvent(MinderEventName.EXPAND, undefined, undefined, undefined, selectedNodes); + } + }, + appendChildNode: () => { + if (props.insertSonMenus.length > 0 || props.insertNode) { + const selectedNodes: MinderJsonNode[] = window.minder.getSelectedNodes(); + appendChildNode(selectedNodes); + } + }, + appendSiblingNode: () => { + if (props.insertSiblingMenus.length > 0 || props.insertNode) { + const selectedNodes: MinderJsonNode[] = window.minder.getSelectedNodes(); + appendSiblingNode(selectedNodes); + } + }, + }, + { + insertNode: props.insertNode, + } + ); + onMounted(() => { window.minderProps = props; useMinderEventListener({ @@ -157,6 +214,10 @@ }, }); }); + + onUnmounted(() => { + unbindShortcuts(); + });