feat(脑图): 脑图拖拽拦截&空白节点保存&部分 bug 修复

This commit is contained in:
baiqi 2024-06-04 19:45:25 +08:00 committed by 刘瑞斌
parent 7ee89429c7
commit 99328a50e5
14 changed files with 361 additions and 182 deletions

View File

@ -94,9 +94,11 @@
const stepTag = t('ms.minders.stepDesc');
const textTag = t('ms.minders.textDesc');
const prerequisiteTag = t('ms.minders.precondition');
const remarkTag = t('common.remark');
const stepExpectTag = t('ms.minders.stepExpect');
const remarkTag = t('ms.minders.remark');
const descTags = [stepTag, textTag];
const caseChildTags = [prerequisiteTag, stepTag, textTag, remarkTag];
const caseOffspringTags = [...caseChildTags, stepTag, stepExpectTag, textTag, remarkTag];
const importJson = ref<MinderJson>({
root: {} as MinderJsonNode,
template: 'default',
@ -110,6 +112,7 @@
updateCaseList: [],
updateModuleList: [],
deleteResourceList: [],
additionalNodeList: [],
});
const templateId = ref('');
@ -153,6 +156,7 @@
id: 'NONE',
text: t('ms.minders.allModule'),
resource: [moduleTag],
disabled: true,
},
};
window.minder.importJson(importJson.value);
@ -217,31 +221,31 @@
let remarkNode: MinderJsonNode | undefined; //
const stepNodes: MinderJsonNode[] = []; //
node.children?.forEach((item) => {
if (item.data.resource?.includes(textTag)) {
if (item.data?.resource?.includes(textTag)) {
textStep = item;
} else if (item.data.resource?.includes(stepTag)) {
} else if (item.data?.resource?.includes(stepTag)) {
stepNodes.push(item);
} else if (item.data.resource?.includes(prerequisiteTag)) {
} else if (item.data?.resource?.includes(prerequisiteTag)) {
prerequisiteNode = item;
} else if (item.data.resource?.includes(remarkTag)) {
} else if (item.data?.resource?.includes(remarkTag)) {
remarkNode = item;
}
});
const steps: FeatureCaseMinderStepItem[] = stepNodes.map((child, i) => {
return {
id: child.data.id,
id: child.data?.id || getGenerateId(),
num: i,
desc: child.data.text,
result: child.children?.[0].data.text || '',
desc: child.data?.text || '',
result: child.children?.[0].data?.text || '',
};
});
return {
prerequisite: prerequisiteNode?.data.text || '',
prerequisite: prerequisiteNode?.data?.text || '',
caseEditType: steps.length > 0 ? 'STEP' : ('TEXT' as FeatureCaseMinderEditType),
steps: JSON.stringify(steps),
textDescription: textStep?.data.text || '',
expectedResult: textStep?.children?.[0]?.data.text || '',
description: remarkNode?.data.text || '',
textDescription: textStep?.data?.text || '',
expectedResult: textStep?.children?.[0]?.data?.text || '',
description: remarkNode?.data?.text || '',
};
}
@ -250,15 +254,14 @@
* @param node 节点
* @param parent 父节点
*/
function getNodeMoveInfo(node: MinderJsonNode, parent?: MinderJsonNode): { moveMode: MoveMode; targetId?: string } {
const nodeIndex = parent?.children?.findIndex((e) => e.data.id === node.data.id);
const moveMode = nodeIndex === 0 ? 'BEFORE' : 'AFTER';
function getNodeMoveInfo(nodeIndex: number, parent?: MinderJsonNode): { moveMode: MoveMode; targetId?: string } {
const moveMode = nodeIndex === 0 ? 'BEFORE' : 'AFTER'; //
return {
moveMode,
targetId:
moveMode === 'BEFORE'
? parent?.children?.[1]?.data.id
: parent?.children?.[(nodeIndex || parent.children.length - 1) - 1]?.data.id,
? parent?.children?.[1]?.data?.id
: parent?.children?.[(nodeIndex || parent.children.length - 1) - 1]?.data?.id,
};
}
@ -267,17 +270,19 @@
*/
function makeMinderParams(): FeatureCaseMinderUpdateParams {
const fullJson: MinderJson = window.minder.exportJson();
filterTree(fullJson.root.children, (node, parent) => {
filterTree(fullJson.root.children, (node, nodeIndex, parent) => {
if (node.data.isNew !== false || node.data.changed === true) {
if (node.data.resource?.includes(moduleTag)) {
//
tempMinderParams.value.updateModuleList.push({
id: node.data.id,
name: node.data.text,
parentId: parent?.data.id || 'NONE',
type: node.data.isNew !== false ? 'ADD' : 'UPDATE',
...getNodeMoveInfo(node as MinderJsonNode, parent as MinderJsonNode),
...getNodeMoveInfo(nodeIndex, parent as MinderJsonNode),
});
} else if (node.data.resource?.includes(caseTag)) {
//
const caseNodeInfo = getCaseNodeInfo(node as MinderJsonNode);
const caseBaseInfo = baseInfoRef.value?.makeParams();
tempMinderParams.value.updateCaseList.push({
@ -288,10 +293,19 @@
tags: caseBaseInfo?.tags || [],
customFields: caseBaseInfo?.customFields || [],
name: caseBaseInfo?.name || node.data.text,
...getNodeMoveInfo(node as MinderJsonNode, parent as MinderJsonNode),
...getNodeMoveInfo(nodeIndex, parent as MinderJsonNode),
...caseNodeInfo,
});
return false; //
} else if (!node.data.resource) {
//
tempMinderParams.value.additionalNodeList.push({
id: node.data.id,
parentId: parent?.data.id || 'NONE',
type: node.data.isNew !== false ? 'ADD' : 'UPDATE',
name: node.data.text,
...getNodeMoveInfo(nodeIndex, parent as MinderJsonNode),
});
}
}
return true;
@ -316,7 +330,7 @@
* 已选中节点的可替换标签判断
* @param node 选中节点
*/
function replaceableTags(node: MinderJsonNode, nodes: MinderJsonNode[]) {
function replaceableTags(nodes: MinderJsonNode[]) {
if (nodes.length > 1) {
// 1
if (nodes.some((e) => (e.data?.resource || []).length > 0)) {
@ -328,10 +342,11 @@
return [moduleTag];
}
}
const node = nodes[0];
if (
Object.keys(node.data || {}).length === 0 ||
node.data?.id === 'root' ||
(node.parent?.data.resource || []).length === 0
(node.parent?.data?.resource || []).length === 0
) {
//
return [];
@ -357,18 +372,21 @@
//
return caseChildTags;
}
if (
(!node.data?.resource || node.data.resource.length === 0) &&
(!node.parent?.data?.resource ||
node.parent?.data?.resource.length === 0 ||
node.parent?.data?.resource?.some((e) => topTags.includes(e)))
) {
//
return node.children &&
(node.children.some((e) => e.data?.resource?.includes(caseTag)) ||
node.children.some((e) => e.data?.resource?.includes(moduleTag)))
? topTags.filter((e) => e !== caseTag)
: topTags;
if ((!node.data?.resource || node.data.resource.length === 0) && node.parent?.data?.resource?.includes(moduleTag)) {
//
if (
(node.children &&
(node.children.some((e) => e.data?.resource?.includes(caseTag)) ||
node.children.some((e) => e.data?.resource?.includes(moduleTag)))) ||
node.parent?.data?.id === 'NONE'
) {
// NONE
return [moduleTag];
}
if (!node.children || node.children.length === 0) {
//
return topTags;
}
}
return [];
}
@ -383,7 +401,22 @@
window.minder.execCommand(command, node);
nextTick(() => {
const newNode: MinderJsonNode = window.minder.getSelectedNode();
if (!newNode.data) {
newNode.data = {
id: getGenerateId(),
text: '',
};
}
newNode.data.isNew = true; //
if (newNode.data?.resource?.some((e) => caseOffspringTags.includes(e))) {
//
if (newNode.parent?.data?.resource?.includes(caseTag)) {
newNode.parent.data.changed = true;
} else if (newNode.parent?.parent?.data?.resource?.includes(caseTag)) {
//
newNode.parent.parent.data.changed = true;
}
}
});
}
}
@ -437,8 +470,8 @@
parent: node,
data: {
id: getGenerateId(),
text: t('ms.minders.stepDesc'),
resource: [t('ms.minders.stepDesc')],
text: stepTag,
resource: [stepTag],
isNew: true,
},
children: [],
@ -447,8 +480,8 @@
parent: child,
data: {
id: getGenerateId(),
text: t('ms.minders.stepExpect'),
resource: [t('ms.minders.stepExpect')],
text: stepExpectTag,
resource: [stepExpectTag],
isNew: true,
},
};
@ -468,8 +501,8 @@
parent: node,
data: {
id: getGenerateId(),
text: t('ms.minders.stepExpect'),
resource: [t('ms.minders.stepExpect')],
text: stepExpectTag,
resource: [stepExpectTag],
isNew: true,
},
children: [],
@ -587,14 +620,22 @@
if (tag === moduleTag && node.data) {
//
tempMinderParams.value.updateCaseList = tempMinderParams.value.updateCaseList.filter(
(e) => e.id !== node.data.id
(e) => e.id !== node.data?.id
);
window.minder.execCommand('priority');
} else if (node.data.resource?.includes(caseTag)) {
} else if (node.data?.resource?.includes(caseTag)) {
//
tempMinderParams.value.updateModuleList = tempMinderParams.value.updateModuleList.filter(
(e) => e.id !== node.data.id
(e) => e.id !== node.data?.id
);
} else if (node.data?.resource?.some((e) => caseOffspringTags.includes(e))) {
//
if (node.parent?.data?.resource?.includes(caseTag)) {
node.parent.data.changed = true;
} else if (node.parent?.parent?.data?.resource?.includes(caseTag)) {
//
node.parent.parent.data.changed = true;
}
}
}
const baseInfoLoading = ref(false);
@ -792,9 +833,12 @@
node.expand();
node.renderTree();
window.minder.layout();
window.minder.execCommand('camera', node, 600);
if (node.data) {
node.data.isLoaded = true;
}
// importJson
importJson.value = window.minder.exportJson();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
@ -812,25 +856,33 @@
* @param event 脑图事件对象
*/
function handleAction(event: MinderCustomEvent) {
const { node, name } = event;
if (node) {
const { nodes, name } = event;
if (nodes && nodes.length > 0) {
switch (name) {
case MinderEventName.DELETE_NODE:
tempMinderParams.value.deleteResourceList.push({
id: node.data.id,
type: node.data?.resource?.[0] || moduleTag,
// TODO:
nodes.forEach((node) => {
tempMinderParams.value.deleteResourceList.push({
id: node.data?.id || getGenerateId(),
type: node.data?.resource?.[0] || moduleTag,
});
if (node.data?.resource?.includes(caseTag)) {
//
tempMinderParams.value.updateCaseList = tempMinderParams.value.updateCaseList.filter(
(e) => e.id !== node.data?.id
);
} else if (node.data?.resource?.includes(moduleTag)) {
//
tempMinderParams.value.updateModuleList = tempMinderParams.value.updateModuleList.filter(
(e) => e.id !== node.data?.id
);
} else if (!node.data?.resource) {
//
tempMinderParams.value.additionalNodeList = tempMinderParams.value.additionalNodeList.filter(
(e) => e.id !== node.data?.id
);
}
});
if (node.data?.resource?.includes(caseTag)) {
//
tempMinderParams.value.updateCaseList = tempMinderParams.value.updateCaseList.filter(
(e) => e.id !== node.data.id
);
} else if (node.data?.resource?.includes(moduleTag)) {
//
tempMinderParams.value.updateModuleList = tempMinderParams.value.updateModuleList.filter(
(e) => e.id !== node.data.id
);
}
break;
default:
break;
@ -838,10 +890,111 @@
}
}
/**
* 是否停止拖拽动作
* @param dragNode 拖动节点
* @param dropNode 目标节点
* @param mode 拖拽模式
*/
function stopDrag(
dragNodes: MinderJsonNode | MinderJsonNode[],
dropNode: MinderJsonNode,
mode: 'movetoparent' | 'arrange'
) {
if (!Array.isArray(dragNodes)) {
dragNodes = [dragNodes];
}
for (let i = 0; i < dragNodes.length; i++) {
const dragNode = (dragNodes as MinderJsonNode[])[i];
if (mode === 'movetoparent') {
//
if (dragNode.data?.resource?.includes(caseTag) && dropNode.data?.id === 'NONE') {
//
return true;
}
if (
(dragNode.data?.resource?.includes(moduleTag) || dragNode.data?.resource?.includes(caseTag)) &&
dropNode.data?.resource?.includes(moduleTag)
) {
//
if (dragNode.data) {
dragNode.data.changed = true;
}
return false;
}
if (!dragNode.data?.resource && (dropNode.data?.resource?.includes(moduleTag) || !dropNode.data?.resource)) {
//
if (dragNode.data) {
dragNode.data.changed = true;
}
return false;
}
if (
dragNode.data?.resource?.some((e) => caseChildTags.includes(e)) &&
dropNode.data?.resource?.includes(caseTag) &&
dragNode.parent?.data?.id === dropNode.data?.id
) {
//
if (dragNode.parent?.data) {
dragNode.parent.data.changed = true;
}
return false;
}
} else if (mode === 'arrange') {
//
if (
(dragNode.data?.resource?.includes(moduleTag) ||
dragNode.data?.resource?.includes(caseTag) ||
!dragNode.data?.resource) &&
(dropNode.data?.resource?.includes(moduleTag) ||
dropNode.data?.resource?.includes(caseTag) ||
!dropNode.data?.resource)
) {
if (dragNode.data) {
dragNode.data.changed = true;
}
//
return false;
}
if (dragNode.data?.resource?.includes(stepTag) && dropNode.data?.resource?.includes(stepTag)) {
if (dragNode.parent?.data) {
dragNode.parent.data.changed = true;
}
//
return false;
}
}
}
return true;
}
/**
* 脑图命令执行前拦截
* @param event 命令执行事件
*/
function handleBeforeExecCommand(event: MinderEvent) {
if (event.commandName === 'movetoparent') {
// TODO:
event.stopPropagation();
//
if (stopDrag(event.commandArgs[0] as MinderJsonNode, event.commandArgs[1] as MinderJsonNode, 'movetoparent')) {
event.stopPropagation();
}
} else if (event.commandName === 'arrange') {
//
const dragNodes: MinderJsonNode[] = window.minder.getSelectedNodes();
let dropNode: MinderJsonNode;
if (dragNodes[0].parent?.children?.[event.commandArgs[0] as number]) {
//
dropNode = dragNodes[0].parent?.children?.[event.commandArgs[0] as number];
} else if (dragNodes[0].parent?.children?.[(event.commandArgs[0] as number) - 1]) {
//
dropNode = dragNodes[0].parent?.children?.[(event.commandArgs[0] as number) - 1];
} else {
//
dropNode = dragNodes[dragNodes.length - 1];
}
if (stopDrag(dragNodes, dropNode, 'arrange')) {
event.stopPropagation();
}
}
}
</script>

View File

@ -4,6 +4,7 @@ export default {
'ms.minders.stepDesc': 'Step Description',
'ms.minders.stepExpect': 'Expected Result',
'ms.minders.textDesc': 'Text Description',
'ms.minders.remark': 'Remark Information',
'ms.minders.caseName': 'Test Case Name',
'ms.minders.caseNameNotNull': 'Test Case Name cannot be empty',
'ms.minders.commentTotal': '{num} Comments in Total',

View File

@ -4,6 +4,7 @@ export default {
'ms.minders.stepDesc': '步骤描述',
'ms.minders.stepExpect': '预期结果',
'ms.minders.textDesc': '文本描述',
'ms.minders.remark': '备注信息',
'ms.minders.caseName': '用例名称',
'ms.minders.caseNameNotNull': '用例名称不能为空',
'ms.minders.commentTotal': '共 {num} 评论',

View File

@ -44,7 +44,8 @@ export default function useEventListener(listener: UseEventListenerProps) {
// console.log('dragFinish', minder.history);
// });
minder.on('beforeExecCommand', (e: any) => {
// 监听脑图执行命令前可通过e.stopPropagation拦截命令执行
minder.on('beforeExecCommand', (e: MinderEvent) => {
if (listener.handleBeforeExecCommand) {
listener.handleBeforeExecCommand(e);
}

View File

@ -84,7 +84,7 @@
import { useI18n } from '@/hooks/useI18n';
import useMinderStore from '@/store/modules/components/minder-editor';
import { findNodePathByKey } from '@/utils';
import { findNodePathByKey, getGenerateId } from '@/utils';
import { MinderEventName } from '@/enums/minderEnum';
@ -94,6 +94,7 @@
mainEditorProps,
MinderJson,
MinderJsonNode,
MinderJsonNodeData,
priorityProps,
tagProps,
} from '../props';
@ -214,14 +215,6 @@
init();
});
watch(
() => props.importJson,
(val) => {
innerImportJson.value = val;
window.minder.importJson(val);
}
);
const menuVisible = ref(false);
const menuPopupOffset = ref([0, 0]);
@ -229,12 +222,17 @@
* 切换脑图展示的节点层级
* @param node 切换的节点
*/
function switchNode(node: MinderJsonNode) {
innerImportJson.value = cloneDeep(findNodePathByKey([props.importJson.root], node.data?.id, 'data', 'id'));
function switchNode(node: MinderJsonNode | MinderJsonNodeData) {
if (node.data) {
innerImportJson.value = cloneDeep(findNodePathByKey([props.importJson.root], node.data.id, 'data', 'id'));
} else {
innerImportJson.value = cloneDeep(findNodePathByKey([props.importJson.root], node.id, 'data', 'id'));
}
innerImportJson.value.data.expandState = 'expand';
window.minder.importJson(innerImportJson.value);
window.minder.execCommand('template', Object.keys(window.kityminder.Minder.getTemplateList())[minderStore.mold]);
minderStore.dispatchEvent(MinderEventName.ENTER_NODE, undefined, undefined, node);
setTimeout(() => {
window.minder.execCommand('camera', window.minder.getRoot(), 600);
}, 100); // TODO:
}
watch(
@ -248,8 +246,8 @@
];
menuVisible.value = true;
}
if (minderStore.event.name === MinderEventName.ENTER_NODE && minderStore.event.node) {
switchNode(minderStore.event.node);
if (minderStore.event.name === MinderEventName.ENTER_NODE && minderStore.event.nodes) {
switchNode(minderStore.event.nodes[0]);
}
}
);
@ -268,6 +266,12 @@
window.minder.execCommand(command);
nextTick(() => {
const newNode: MinderJsonNode = window.minder.getSelectedNode();
if (!newNode.data) {
newNode.data = {
id: getGenerateId(),
text: '',
};
}
newNode.data.isNew = true; //
});
}
@ -278,49 +282,52 @@
* @param val 选择的菜单项
*/
function handleMinderMenuSelect(val: string | number | Record<string, any> | undefined) {
const selectedNode = window.minder.getSelectedNode();
switch (val) {
case 'expand':
if (selectedNode.data.expandState === 'collapse') {
window.minder.execCommand('Expand');
} else {
window.minder.execCommand('Collapse');
}
minderStore.dispatchEvent(MinderEventName.EXPAND, undefined, undefined, selectedNode);
break;
case 'insetParent':
execInsertCommand('AppendParentNode');
minderStore.dispatchEvent(MinderEventName.INSERT_PARENT, undefined, undefined, selectedNode);
break;
case 'insetSon':
execInsertCommand('AppendChildNode');
minderStore.dispatchEvent(MinderEventName.INSERT_CHILD, undefined, undefined, selectedNode);
break;
case 'insetBrother':
execInsertCommand('AppendSiblingNode');
minderStore.dispatchEvent(MinderEventName.INSERT_SIBLING, undefined, undefined, selectedNode);
break;
case 'copy':
window.minder.execCommand('Copy');
minderStore.dispatchEvent(MinderEventName.COPY_NODE, undefined, undefined, selectedNode);
break;
case 'cut':
window.minder.execCommand('Cut');
minderStore.dispatchEvent(MinderEventName.CUT_NODE, undefined, undefined, selectedNode);
break;
case 'paste':
window.minder.execCommand('Paste');
minderStore.dispatchEvent(MinderEventName.PASTE_NODE, undefined, undefined, selectedNode);
break;
case 'delete':
window.minder.execCommand('RemoveNode');
minderStore.dispatchEvent(MinderEventName.DELETE_NODE, undefined, undefined, selectedNode);
break;
case 'enterNode':
switchNode(selectedNode.data);
break;
default:
break;
const selectedNodes: MinderJsonNode[] = window.minder.getSelectedNodes();
if (selectedNodes.length > 0) {
switch (val) {
case 'expand':
if (selectedNodes.some((node) => node.data?.expandState === 'collapse')) {
window.minder.execCommand('Expand');
} else {
window.minder.execCommand('Collapse');
}
minderStore.dispatchEvent(MinderEventName.EXPAND, undefined, undefined, selectedNodes);
break;
case 'insetParent':
execInsertCommand('AppendParentNode');
minderStore.dispatchEvent(MinderEventName.INSERT_PARENT, undefined, undefined, selectedNodes);
break;
case 'insetSon':
execInsertCommand('AppendChildNode');
minderStore.dispatchEvent(MinderEventName.INSERT_CHILD, undefined, undefined, selectedNodes);
break;
case 'insetBrother':
execInsertCommand('AppendSiblingNode');
minderStore.dispatchEvent(MinderEventName.INSERT_SIBLING, undefined, undefined, selectedNodes);
break;
case 'copy':
window.minder.execCommand('Copy');
minderStore.dispatchEvent(MinderEventName.COPY_NODE, undefined, undefined, selectedNodes);
break;
case 'cut':
window.minder.execCommand('Cut');
minderStore.dispatchEvent(MinderEventName.CUT_NODE, undefined, undefined, selectedNodes);
break;
case 'paste':
window.minder.execCommand('Paste');
minderStore.dispatchEvent(MinderEventName.PASTE_NODE, undefined, undefined, selectedNodes);
break;
case 'delete':
window.minder.execCommand('RemoveNode');
minderStore.dispatchEvent(MinderEventName.DELETE_NODE, undefined, undefined, selectedNodes);
break;
case 'enterNode':
switchNode(selectedNodes[0]);
minderStore.dispatchEvent(MinderEventName.ENTER_NODE, undefined, undefined, [selectedNodes[0]]);
break;
default:
break;
}
}
}
</script>

View File

@ -24,7 +24,7 @@
import { MinderEventName } from '@/enums/minderEnum';
import { delProps } from '../../props';
import { delProps, MinderJsonNode } from '../../props';
import { isDeleteDisableNode } from '../../script/tool/utils';
const minderStore = useMinderStore();
@ -59,19 +59,19 @@
if (removeNodeDisabled.value || !minder.queryCommandState || !minder.execCommand) {
return;
}
const node = minder.getSelectedNode();
const nodes: MinderJsonNode[] = minder.getSelectedNodes();
let position: MinderNodePosition | undefined;
if (node) {
if (nodes.length > 0) {
if (props.delConfirm) {
props.delConfirm(node);
props.delConfirm(nodes);
return;
}
const box = node.getRenderBox();
const box = nodes[0].getRenderBox();
position = {
x: box.cx,
y: box.cy,
};
minderStore.dispatchEvent(MinderEventName.DELETE_NODE, position, node.rc.node, node.data);
minderStore.dispatchEvent(MinderEventName.DELETE_NODE, position, nodes[0].rc.node, nodes);
}
minder.forceRemoveNode();
}

View File

@ -47,11 +47,10 @@
minder.on('selectionchange', () => {
commandDisabled.value = isDisable();
const nodes: MinderJsonNode[] = window.minder.getSelectedNodes();
const node: MinderJsonNode = minder.getSelectedNode();
if (commandDisabled.value) {
tagList.value = [];
} else if (props.replaceableTags) {
tagList.value = props.replaceableTags(node, nodes);
tagList.value = props.replaceableTags(nodes);
} else {
tagList.value = [];
}
@ -70,8 +69,8 @@
return;
}
if (props.tagEditCheck) {
const node: MinderJsonNode = minder.getSelectedNode();
if (!props.tagEditCheck(node, resourceName)) {
const nodes: MinderJsonNode[] = minder.getSelectedNodes();
if (!props.tagEditCheck(nodes, resourceName)) {
return;
}
}
@ -100,13 +99,12 @@
}
window.minder.execCommand('resource', origin);
const nodes: MinderJsonNode[] = window.minder.getSelectedNodes();
const node: MinderJsonNode = minder.getSelectedNode();
minderStore.dispatchEvent(MinderEventName.SET_TAG, undefined, undefined, node);
minderStore.dispatchEvent(MinderEventName.SET_TAG, undefined, undefined, nodes);
if (props.replaceableTags) {
tagList.value = props.replaceableTags(node, nodes);
tagList.value = props.replaceableTags(nodes);
}
if (props.afterTagEdit) {
props.afterTagEdit(node, resourceName);
props.afterTagEdit(nodes, resourceName);
}
}
</script>

View File

@ -6,19 +6,6 @@ import type { MoveMode } from '@/models/common';
import type { PropType } from 'vue';
export interface MinderClass {
stopPropagation: () => void; // 阻止事件冒泡
stopPropagationImmediately: () => void; // 立即阻止事件冒泡
[key: string]: any; // TODO: 其他事件属性
}
// TODO:脑图事件类型补充
export interface MinderEvent extends MinderClass {
command: any;
commandArgs: Record<string, any>[];
commandName: string;
minder: any;
type: string;
}
export interface MinderIconButtonItem {
icon: string;
tooltip: string;
@ -35,10 +22,11 @@ export interface MinderJsonNodeData {
changed?: boolean; // 脑图节点是否发生过变化
moveMode?: MoveMode; // 移动方式(节点移动或新增时需要)
targetId?: string; // 目标节点 id节点移动或新增时需要
disabled?: boolean; // 是否禁用
[key: string]: any;
}
export interface MinderJsonNode {
data: MinderJsonNodeData;
data?: MinderJsonNodeData;
parent?: MinderJsonNode;
children?: MinderJsonNode[];
[key: string]: any; // minder 内置字段
@ -49,6 +37,20 @@ export interface MinderJson {
template: string;
treePath: Record<string, MinderJsonNode>[];
}
// 脑图类
export interface MinderClass {
stopPropagation: () => void; // 阻止事件冒泡
stopPropagationImmediately: () => void; // 立即阻止事件冒泡
[key: string]: any; // TODO: 其他事件属性
}
// TODO:脑图事件类型补充
export interface MinderEvent extends MinderClass {
command: any;
commandArgs: ((Record<string, any> & MinderJsonNode) | (Record<string, any> & MinderJsonNode)[] | number)[];
commandName: string;
minder: any;
type: string;
}
export const mainEditorProps = {
importJson: {
@ -122,10 +124,10 @@ export const tagProps = {
type: Boolean,
default: false,
},
replaceableTags: Function as PropType<(node: MinderJsonNode, nodes: MinderJsonNode[]) => string[]>,
replaceableTags: Function as PropType<(nodes: MinderJsonNode[]) => string[]>,
tagDisableCheck: Function,
tagEditCheck: Function as PropType<(node: MinderJsonNode, tag: string) => boolean>,
afterTagEdit: Function as PropType<(node: MinderJsonNode, tag: string) => void>,
tagEditCheck: Function as PropType<(nodes: MinderJsonNode[], tag: string) => boolean>,
afterTagEdit: Function as PropType<(nodes: MinderJsonNode[], tag: string) => void>,
};
export const insertProps = {

View File

@ -1,41 +1,41 @@
import type { MinderJsonNode } from '../../props';
export function isDisableNode(minder: any) {
let node;
let node: MinderJsonNode;
if (minder && minder.getSelectedNode) {
node = minder.getSelectedNode();
}
if (node && node.data.disable === true) {
return true;
if (node && node.data?.disabled === true) {
return true;
}
}
return false;
}
export function isDeleteDisableNode(minder: any) {
let node;
let node: MinderJsonNode;
if (minder && minder.getSelectedNode) {
node = minder.getSelectedNode();
}
if (node && node.data.disable === true && !node.data.allowDelete) {
return true;
if (node && node.data?.disabled === true && !node.data.allowDelete) {
return true;
}
}
return false;
}
export function isTagEnableNode(node: MinderJsonNode) {
if (node && (node.data.tagEnable === true || node.data.allowDisabledTag === true)) {
if (node.data && (node.data.tagEnable === true || node.data.allowDisabledTag === true)) {
return true;
}
return false;
}
export function isTagEnable(minder: any) {
let node;
let node: MinderJsonNode;
if (minder && minder.getSelectedNode) {
node = minder.getSelectedNode();
}
if (isTagEnableNode(node)) {
return true;
if (isTagEnableNode(node)) {
return true;
}
}
return false;
}
@ -46,10 +46,10 @@ export function markChangeNode(node: MinderJsonNode) {
}
}
function markDelNode(node: MinderJsonNode, deleteChild: any) {
function markDelNode(node: MinderJsonNode, deleteChild: MinderJsonNode) {
deleteChild.push(node.data);
if (node.children) {
node.children.forEach((child: any) => {
node.children.forEach((child: MinderJsonNode) => {
markDelNode(child, deleteChild);
});
}
@ -58,9 +58,9 @@ function markDelNode(node: MinderJsonNode, deleteChild: any) {
// 在父节点记录删除的节点
export function markDeleteNode(minder: any) {
if (minder) {
const nodes = minder.getSelectedNodes();
const nodes: MinderJsonNode[] = minder.getSelectedNodes();
nodes.forEach((node: MinderJsonNode) => {
if (node && node.parent) {
if (node.parent?.data) {
const pData = node.parent.data;
if (!pData.deleteChild) {
pData.deleteChild = [];
@ -101,7 +101,7 @@ export function setPriorityView(priorityStartWithZero: boolean, priorityPrefix:
* id置为nullchanged true
* @param node
*/
export function resetNodes(nodes: any) {
export function resetNodes(nodes: MinderJsonNode[]) {
if (nodes) {
nodes.forEach((item: any) => {
if (item.data) {
@ -115,7 +115,7 @@ export function resetNodes(nodes: any) {
}
export function isDisableForNode(node: MinderJsonNode) {
if (node && node.data.disable === true) {
if (node && node.data?.disabled === true) {
return true;
}
return false;

View File

@ -382,7 +382,15 @@ export interface FeatureCaseMinderUpdateModuleItem {
moveMode?: MoveMode;
targetId?: string;
}
// 脑图新增/修改的文本节点集合
export interface FeatureCaseMinderUpdateTextNodeItem {
id: string;
name: string;
parentId: string;
type: FeatureCaseMinderActionType;
moveMode?: MoveMode;
targetId?: string;
}
export interface CustomField {
fieldId: string;
value: string;
@ -419,4 +427,5 @@ export interface FeatureCaseMinderUpdateParams {
updateCaseList: FeatureCaseMinderUpdateCaseItem[];
updateModuleList: FeatureCaseMinderUpdateModuleItem[];
deleteResourceList: FeatureCaseMinderDeleteResourceItem[];
additionalNodeList: FeatureCaseMinderUpdateTextNodeItem[];
}

View File

@ -17,7 +17,7 @@ const useMinderStore = defineStore('minder', {
y: 0,
},
nodeDom: undefined,
node: undefined,
nodes: undefined,
},
mold: 0,
}),
@ -27,15 +27,20 @@ const useMinderStore = defineStore('minder', {
* @param name
* @param position /
* @param nodeDom DOM
* @param node
* @param nodes
*/
dispatchEvent(name: MinderEventName, position?: MinderNodePosition, nodeDom?: HTMLElement, node?: MinderJsonNode) {
dispatchEvent(
name: MinderEventName,
position?: MinderNodePosition,
nodeDom?: HTMLElement,
nodes?: MinderJsonNode[]
) {
this.event = {
name,
timestamp: Date.now(),
nodePosition: position,
nodeDom,
node,
nodes,
};
},
setMold(val: number) {

View File

@ -12,7 +12,7 @@ export interface MinderCustomEvent {
timestamp: number;
nodePosition?: MinderNodePosition;
nodeDom?: HTMLElement;
node?: MinderJsonNode;
nodes?: MinderJsonNode[];
}
export interface MinderState {

View File

@ -281,7 +281,7 @@ export function mapTree<T>(
*/
export function filterTree<T>(
tree: TreeNode<T> | TreeNode<T>[] | T | T[],
filterFn: (node: TreeNode<T>, parent?: TreeNode<T> | null) => boolean,
filterFn: (node: TreeNode<T>, nodeIndex: number, parent?: TreeNode<T> | null) => boolean,
customChildrenKey = 'children',
parentNode: TreeNode<T> | null = null
): TreeNode<T>[] {
@ -292,7 +292,7 @@ export function filterTree<T>(
for (let i = 0; i < tree.length; i++) {
const node = (tree as TreeNode<T>[])[i];
// 如果节点满足过滤条件,则保留该节点,并递归过滤子节点
if (filterFn(node, parentNode)) {
if (filterFn(node, i, parentNode)) {
const newNode = cloneDeep(node);
if (node[customChildrenKey] && node[customChildrenKey].length > 0) {
// 递归过滤子节点,并将过滤后的子节点添加到当前节点中

View File

@ -855,6 +855,7 @@
/** 环境管理-环境组 end */
const defaultLineData = ref(cloneDeep(props.defaultParamItem));
/**
* 当表格输入框变化时给参数表格添加一行数据行
* @param val 输入值
@ -875,7 +876,7 @@
const nextLine = {
id,
enable: true, //
...cloneDeep(props.defaultParamItem), //
...cloneDeep(defaultLineData.value), //
} as any;
selectColumnKeys.forEach((key) => {
// 便
@ -894,6 +895,7 @@
}
});
paramsData.value.push(nextLine);
defaultLineData.value = cloneDeep(nextLine);
}
emitChange('addTableLine', isInit);
handleMustContainColChange(true);
@ -910,7 +912,7 @@
// undefined
hasNoIdItem = true;
return {
...cloneDeep(props.defaultParamItem),
...cloneDeep(defaultLineData.value),
id: getGenerateId(),
};
}
@ -927,7 +929,7 @@
if (
(!props.disabledExceptParam || !props.disabledParamValue) &&
hasNoIdItem &&
!filterKeyValParams(arr, props.defaultParamItem, !props.selectable).lastDataIsDefault &&
!filterKeyValParams(arr, defaultLineData.value, !props.selectable).lastDataIsDefault &&
!props.isTreeTable
) {
addTableLine(arr.length - 1, false, true);
@ -939,7 +941,7 @@
{
id, // id props.defaultParamItem id
enable: true, //
...cloneDeep(props.defaultParamItem),
...cloneDeep(defaultLineData.value),
},
] as any[];
emitChange('watch props.params', true);