|
@@ -2,25 +2,44 @@ import { StructureType, TopicType } from "@/enum";
|
|
|
import { MindMapProjectInfo, TopicItem, HierarchyResult } from "@/types";
|
|
|
import { Graph, Cell, Node } from "@antv/x6";
|
|
|
import TopicComponent from "@/components/mindMap/Topic";
|
|
|
+import TopicBorder from "@/components/mindMap/Border";
|
|
|
+import SummaryBorder from "@/components/mindMap/SummaryBorder";
|
|
|
import { topicData } from "@/config/data";
|
|
|
import { uuid } from "@/utils";
|
|
|
import { hierarchyMethodMap } from "@/pages/mindmap/hierarchy";
|
|
|
import { createEdge } from "./edge";
|
|
|
import { getTheme } from "./theme";
|
|
|
import { topicMenu } from "@/utils/contentMenu";
|
|
|
+import {
|
|
|
+ cacluculateExtremeValue,
|
|
|
+ getBorderPositionAndSize,
|
|
|
+} from "@/utils/mindmapHander";
|
|
|
|
|
|
/**
|
|
|
* 渲染思维导图项目
|
|
|
* @param graph
|
|
|
*/
|
|
|
-export const renderMindMap = (graph: Graph, setMindProjectInfo: () => void) => {
|
|
|
- const projectInfo = getMindMapProjectByLocal();
|
|
|
- if (!projectInfo) return;
|
|
|
- const { topics, pageSetting } = projectInfo;
|
|
|
+export const renderMindMap = ({
|
|
|
+ topics,
|
|
|
+ pageSetting,
|
|
|
+ structure,
|
|
|
+ theme,
|
|
|
+ graph,
|
|
|
+ setMindProjectInfo,
|
|
|
+ returnCells = false
|
|
|
+}: {
|
|
|
+ topics: TopicItem[];
|
|
|
+ pageSetting: MindMapProjectInfo["pageSetting"];
|
|
|
+ structure: StructureType;
|
|
|
+ theme: string;
|
|
|
+ graph: Graph;
|
|
|
+ setMindProjectInfo: (info: MindMapProjectInfo) => void;
|
|
|
+ returnCells?: boolean;
|
|
|
+}) => {
|
|
|
const cells: Cell[] = [];
|
|
|
topics.forEach((topic) => {
|
|
|
// 遍历出层次结构
|
|
|
- const result: HierarchyResult = hierarchyMethodMap[projectInfo.structure]?.(
|
|
|
+ const result: HierarchyResult = hierarchyMethodMap[structure]?.(
|
|
|
topic,
|
|
|
pageSetting
|
|
|
);
|
|
@@ -53,34 +72,53 @@ export const renderMindMap = (graph: Graph, setMindProjectInfo: () => void) => {
|
|
|
id,
|
|
|
x: offsetX + x,
|
|
|
y: offsetY + y,
|
|
|
- tools: [{
|
|
|
- name: 'contextmenu',
|
|
|
- args: {
|
|
|
- menu: topicMenu,
|
|
|
+ tools: [
|
|
|
+ {
|
|
|
+ name: "contextmenu",
|
|
|
+ args: {
|
|
|
+ menu: topicMenu,
|
|
|
+ },
|
|
|
},
|
|
|
- },]
|
|
|
+ ],
|
|
|
});
|
|
|
+ // 渲染边框
|
|
|
+ if (data.border) {
|
|
|
+ cells.push(
|
|
|
+ createBorderComponent(hierarchyItem, offsetX, offsetY, graph)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // 渲染概要
|
|
|
+ if (data.summary) {
|
|
|
+ const summaryCells = createSummaryCells(
|
|
|
+ hierarchyItem,
|
|
|
+ data.summary,
|
|
|
+ structure,
|
|
|
+ pageSetting,
|
|
|
+ theme,
|
|
|
+ graph,
|
|
|
+ setMindProjectInfo,
|
|
|
+ offsetX,
|
|
|
+ offsetY
|
|
|
+ );
|
|
|
+ cells.push(...(summaryCells || []));
|
|
|
+ }
|
|
|
cells.push(node);
|
|
|
parent && parent.addChild(node);
|
|
|
- if(data?.links) {
|
|
|
- cells.push(...data.links.map(item => graph.createEdge(item)));
|
|
|
+ if (data?.links) {
|
|
|
+ cells.push(...data.links.map((item) => graph.createEdge(item)));
|
|
|
}
|
|
|
|
|
|
if (children) {
|
|
|
children.forEach((item: HierarchyResult, index) => {
|
|
|
- const isBracket = [StructureType.leftBracket, StructureType.rightBracket].includes(projectInfo.structure)
|
|
|
+ const isBracket = [
|
|
|
+ StructureType.leftBracket,
|
|
|
+ StructureType.rightBracket,
|
|
|
+ ].includes(structure);
|
|
|
// 括号图不绘制中间连线
|
|
|
- if(!isBracket || (index === 0 || index === children.length - 1)) {
|
|
|
- const edge = createEdge(
|
|
|
- graph,
|
|
|
- id,
|
|
|
- item,
|
|
|
- projectInfo.structure,
|
|
|
- projectInfo.theme,
|
|
|
- {
|
|
|
- onlyOneChild: children.length === 1
|
|
|
- }
|
|
|
- );
|
|
|
+ if (!isBracket || index === 0 || index === children.length - 1) {
|
|
|
+ const edge = createEdge(graph, id, item, structure, theme, {
|
|
|
+ onlyOneChild: children.length === 1,
|
|
|
+ });
|
|
|
cells.push(edge);
|
|
|
node.addChild(edge);
|
|
|
}
|
|
@@ -93,7 +131,7 @@ export const renderMindMap = (graph: Graph, setMindProjectInfo: () => void) => {
|
|
|
|
|
|
traverse(result);
|
|
|
});
|
|
|
-
|
|
|
+ if(returnCells) return cells;
|
|
|
const oldCells = graph.getCells();
|
|
|
// 移除不要的节点及对应的边
|
|
|
oldCells.forEach((cell) => {
|
|
@@ -115,23 +153,105 @@ export const renderMindMap = (graph: Graph, setMindProjectInfo: () => void) => {
|
|
|
cell.isNode() && updateNode(cell, graph);
|
|
|
});
|
|
|
// 添加所需的节点
|
|
|
- cells
|
|
|
- .filter((cell) => cell.isEdge())
|
|
|
- .forEach((cell) => {
|
|
|
- graph.addCell(cell);
|
|
|
+ const edgeCells = cells.filter((cell) => cell.isEdge());
|
|
|
+ graph.removeCells(edgeCells);
|
|
|
+ graph.addCell(edgeCells);
|
|
|
+};
|
|
|
+
|
|
|
+// 渲染概要
|
|
|
+const createSummaryCells = (
|
|
|
+ hierarchyItem: HierarchyResult,
|
|
|
+ summary: TopicItem['summary'],
|
|
|
+ structure: StructureType,
|
|
|
+ pageSetting: MindMapProjectInfo['pageSetting'],
|
|
|
+ theme: string,
|
|
|
+ graph: Graph,
|
|
|
+ setMindProjectInfo: (info: MindMapProjectInfo) => void,
|
|
|
+ offsetX: number,
|
|
|
+ offsetY: number
|
|
|
+): Cell[] => {
|
|
|
+ let cells: Cell[] = [];
|
|
|
+ if (summary) {
|
|
|
+ const positionAndSize = cacluculateExtremeValue(
|
|
|
+ hierarchyItem,
|
|
|
+ hierarchyItem.children
|
|
|
+ );
|
|
|
+ const totalHeight = positionAndSize.maxY - positionAndSize.minY;
|
|
|
+ const totalWidth = positionAndSize.maxX - positionAndSize.minX;
|
|
|
+
|
|
|
+ // 概要边框
|
|
|
+ const node = graph.createNode({
|
|
|
+ ...SummaryBorder,
|
|
|
+ data: summary.border,
|
|
|
+ id: summary.topic.id + "-border",
|
|
|
+ zIndex: 0,
|
|
|
+ position: {
|
|
|
+ x: offsetX + positionAndSize.minX - 2,
|
|
|
+ y: offsetY + positionAndSize.minY - 2,
|
|
|
+ },
|
|
|
+ size: {
|
|
|
+ width: totalWidth + 4,
|
|
|
+ height: totalHeight + 4,
|
|
|
+ },
|
|
|
});
|
|
|
+ cells.push(node);
|
|
|
+
|
|
|
+ // 概要节点
|
|
|
+ cells.push(...renderMindMap({
|
|
|
+ topics: [{
|
|
|
+ ...summary.topic,
|
|
|
+ x: offsetX + hierarchyItem.x + totalWidth + 40,
|
|
|
+ y: offsetY + hierarchyItem.y
|
|
|
+ }],
|
|
|
+ pageSetting,
|
|
|
+ structure,
|
|
|
+ theme,
|
|
|
+ graph,
|
|
|
+ setMindProjectInfo,
|
|
|
+ returnCells: true
|
|
|
+ }) || []);
|
|
|
+ }
|
|
|
+ return cells;
|
|
|
+}
|
|
|
+
|
|
|
+// 创建外框组件
|
|
|
+const createBorderComponent = (
|
|
|
+ hierarchyItem: HierarchyResult,
|
|
|
+ offsetX: number,
|
|
|
+ offsetY: number,
|
|
|
+ graph: Graph
|
|
|
+) => {
|
|
|
+ const positionAndSize = getBorderPositionAndSize(hierarchyItem);
|
|
|
+ return graph.createNode({
|
|
|
+ ...TopicBorder,
|
|
|
+ id: hierarchyItem.id + "-border",
|
|
|
+ data: {
|
|
|
+ ...hierarchyItem.data.border,
|
|
|
+ origin: hierarchyItem.id,
|
|
|
+ },
|
|
|
+ zIndex: 0,
|
|
|
+ position: {
|
|
|
+ x: offsetX + positionAndSize.x,
|
|
|
+ y: offsetY + positionAndSize.y,
|
|
|
+ },
|
|
|
+ size: {
|
|
|
+ width: positionAndSize.width,
|
|
|
+ height: positionAndSize.height,
|
|
|
+ },
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
const updateNode = (node: Node, graph: Graph) => {
|
|
|
const oldCell = graph.getCellById(node.id);
|
|
|
- if(oldCell.isNode()) {
|
|
|
+ if (oldCell.isNode()) {
|
|
|
oldCell.setData(node.data);
|
|
|
oldCell.position(node.position().x, node.position().y);
|
|
|
+ oldCell.setSize(node.size().width, node.size().height);
|
|
|
// oldCell.setAttrs(node.attrs);
|
|
|
// const cells = node.children?.map(item => graph.getCellById(item.id));
|
|
|
// oldCell.setChildren(cells ?? null);
|
|
|
}
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
/**
|
|
|
* 添加分支主题
|
|
@@ -150,6 +270,8 @@ export const addTopic = (
|
|
|
{
|
|
|
...(otherData || {}),
|
|
|
parentId: node?.id,
|
|
|
+ isSummary: node?.data?.isSummary,
|
|
|
+ summarySource: node?.data?.summarySource
|
|
|
},
|
|
|
node
|
|
|
);
|
|
@@ -168,6 +290,9 @@ export const addTopic = (
|
|
|
if (item.children) {
|
|
|
traverse(item.children);
|
|
|
}
|
|
|
+ if (item.summary) {
|
|
|
+ traverse([item.summary.topic])
|
|
|
+ }
|
|
|
});
|
|
|
};
|
|
|
traverse(projectInfo?.topics || []);
|
|
@@ -239,12 +364,14 @@ export const buildTopic = (
|
|
|
color: theme[type]?.edge.color,
|
|
|
},
|
|
|
...options,
|
|
|
- children: (options?.children || topicData.children || []).map((item: TopicItem) => {
|
|
|
- return {
|
|
|
- ...item,
|
|
|
- parentId: id
|
|
|
+ children: (options?.children || topicData.children || []).map(
|
|
|
+ (item: TopicItem) => {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ parentId: id,
|
|
|
+ };
|
|
|
}
|
|
|
- })
|
|
|
+ ),
|
|
|
};
|
|
|
};
|
|
|
|