Browse Source

feat: 添加数据渲染及子主题添加

liaojiaxing 6 months ago
parent
commit
90724712ce

+ 1 - 1
apps/designer/src/components/mindMap/Topic.tsx

@@ -37,7 +37,7 @@ const component = ({ node, graph }: { node: Node; graph: Graph }) => {
       addTopic(node, TopicType.sub);
     }
   }
-
+  
   return (
     <>
       <div

+ 3 - 2
apps/designer/src/config/data.ts

@@ -1,4 +1,4 @@
-import { ImageFillType, TopicType } from "@/enum"
+import { BorderSize, ImageFillType, TopicType } from "@/enum"
 import { MindMapProjectInfo } from "@/types";
 import { buildTopic } from "@/utils/mindMap";
 
@@ -130,6 +130,7 @@ export const defaultData = {
 export const topicData = {
   ...defaultData,
   type: TopicType.main,
+  borderSize: BorderSize.medium,
   children: [],
 }
 
@@ -188,7 +189,7 @@ export const defaultProject: MindMapProjectInfo = {
       }
     },
     sub: {
-      width: 54,
+      width: 65,
       height: 27,
       fill: {
         fillType: "color",

+ 12 - 5
apps/designer/src/events/mindMap.ts

@@ -1,8 +1,15 @@
 import { Graph, Node } from "@antv/x6";
 import Topic from "@/components/mindMap/Topic";
 import { BorderSize, TopicType } from "@/enum";
+import { addTopic } from "@/utils/mindMap";
+import { MindMapProjectInfo } from "@/types";
+import { topicData } from "@/config/data";
 
-export const bindMindMapEvents = (graph: Graph) => {
+export const bindMindMapEvents = (
+  graph: Graph,
+  mindProjectInfo?: MindMapProjectInfo,
+  setMindProjectInfo?: (info: MindMapProjectInfo) => void
+) => {
   graph.on("node:click", ({ cell }) => {
     console.log("node:click", cell);
   });
@@ -16,11 +23,11 @@ export const bindMindMapEvents = (graph: Graph) => {
       width: 104,
       height: 40,
       data: {
-        ...Topic.data,
-        type: TopicType.free,
+        ...topicData,
+        type: TopicType.branch,
         label: "自由主题",
-        borderSize: BorderSize.medium
+        borderSize: BorderSize.medium,
       },
     });
   });
-};
+};

+ 2 - 1
apps/designer/src/index.d.ts

@@ -1,2 +1,3 @@
 declare module 'insert-css';
-declare module 'lodash-es';
+declare module 'lodash-es';
+declare module '@antv/hierarchy';

+ 15 - 9
apps/designer/src/models/mindMapModel.ts

@@ -8,7 +8,7 @@ import { History } from "@antv/x6-plugin-history";
 import { Transform } from "@antv/x6-plugin-transform";
 import { Scroller } from "@antv/x6-plugin-scroller";
 import { MindMapProjectInfo } from "@/types";
-import { bindMindMapEvents } from "@/events/mindMap";
+import { bindMindMapEvents } from "@/events/mindMapEvent";
 import { useLocalStorageState } from "ahooks";
 import { renderMindMap } from "@/utils/mindMap";
 import { defaultProject } from "@/config/data";
@@ -35,12 +35,22 @@ export default function mindMapModel() {
   const [mindProjectInfo, setMindProjectInfo] =
     useLocalStorageState<MindMapProjectInfo>("minMapProjectInfo", {
       listenStorageChange: true,
+      // defaultValue: defaultProject,
     });
 
-  if(!mindProjectInfo) {
+  if (!mindProjectInfo) {
     setMindProjectInfo(defaultProject);
   }
 
+  useEffect(() => {
+    window.addEventListener("storage", (e) => {
+      console.log('storage change', e)
+    })
+    if(!graph || !mindProjectInfo) return;
+    console.log('准备渲染', mindProjectInfo);
+    renderMindMap(graph, setMindProjectInfo);
+  }, [mindProjectInfo, graph]);
+
   useEffect(() => {
     if (mindProjectInfo?.pageSetting && graph) {
       if (mindProjectInfo.pageSetting.fillType === "color") {
@@ -56,12 +66,6 @@ export default function mindMapModel() {
     }
   }, [mindProjectInfo?.pageSetting, graph]);
 
-  useEffect(() => {
-    if(!graph || !mindProjectInfo) return;
-    console.log('项目信息改变:', graph);
-    renderMindMap(mindProjectInfo, graph);
-  }, [graph, mindProjectInfo])
-
   // 初始化脑图
   const initMindMap = (container: HTMLElement) => {
     const instance = new Graph({
@@ -98,8 +102,10 @@ export default function mindMapModel() {
       setCanUndo(instance.canUndo());
     });
 
-    bindMindMapEvents(instance);
+    bindMindMapEvents(instance, mindProjectInfo, setMindProjectInfo);
     setGraph(instance);
+    renderMindMap(instance, setMindProjectInfo);
+    instance.centerContent();
   };
 
   const handleBrushClick = (args: EventArgs & { cell: Cell }) => {

+ 5 - 4
apps/designer/src/pages/mindmap/components/Config/PageStyle.tsx

@@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
 import CustomColorPicker from "@/components/CustomColorPicker";
 import { Checkbox, InputNumber, Select, Input, Divider } from "antd";
 import { useModel } from "umi";
+import { ColumnHeightOutlined, ColumnWidthOutlined } from "@ant-design/icons";
 
 export default function PageStyle() {
   const { mindProjectInfo, setMindProjectInfo } = useModel("mindMapModel");
@@ -59,7 +60,7 @@ export default function PageStyle() {
         <div className="flex justify-between gap-8px">
           <InputNumber
             className="flex-1"
-            suffix="W"
+            suffix={<ColumnHeightOutlined />}
             step={1}
             min={10}
             max={200}
@@ -69,7 +70,7 @@ export default function PageStyle() {
           />
           <InputNumber
             className="flex-1"
-            suffix="W"
+            suffix={<ColumnWidthOutlined />}
             step={1}
             min={20}
             max={200}
@@ -82,7 +83,7 @@ export default function PageStyle() {
         <div className="flex justify-between gap-8px">
           <InputNumber
             className="flex-1"
-            suffix="W"
+            suffix={<ColumnHeightOutlined />}
             step={1}
             min={5}
             max={100}
@@ -92,7 +93,7 @@ export default function PageStyle() {
           />
           <InputNumber
             className="flex-1"
-            suffix="W"
+            suffix={<ColumnWidthOutlined />}
             step={1}
             min={20}
             max={100}

+ 3 - 3
apps/designer/src/pages/mindmap/components/Footer/index.tsx

@@ -23,7 +23,7 @@ insertCss(`
 export default function Footer() {
   const [isFullscreen, { toggleFullscreen }] = useFullscreen(document.body);
   const navigationViewRef = useRef(null);
-  const { graph, selectedCell } = useModel("graphModel");
+  const { graph } = useModel("mindMapModel");
   const [showNavigation, setShowNavigation] = useState(false);
   const [countCell, setCountCell] = useState(0);
   const [scale, setScale] = useState(100);
@@ -69,8 +69,8 @@ export default function Footer() {
       <div className="absolute w-full h-24px left-0 bottom-0 bg-white flex justify-between items-center px-16px">
         <div className="footer-left"></div>
         <div className="footer-right flex items-center">
-          <div>字数:{selectedCell?.length}/{countCell}</div>
-          <div>主题数:{selectedCell?.length}/{countCell}</div>
+          <div>字数:{}/{countCell}</div>
+          <div>主题数:{}/{countCell}</div>
           <Divider type="vertical" />
           <Tooltip title="模板">
             <Button type="text" icon={<i className="iconfont icon-buju" />} />

+ 10 - 8
apps/designer/src/pages/mindmap/components/HeaderToolbar/index.tsx

@@ -145,14 +145,16 @@ export default function index() {
       </Dropdown>
 
       <div className="flex flex-col leading-32px">
-        <Input
-          className="text-16px max-w-100px"
-          variant="borderless"
-          value={mindProjectInfo.name}
-          onChange={(e) =>
-            setMindProjectInfo((state) => ({ ...state, name: e.target.value }))
-          }
-        />
+        {mindProjectInfo && (
+          <Input
+            className="text-16px max-w-100px"
+            variant="borderless"
+            value={mindProjectInfo.name}
+            onChange={(e) =>
+              setMindProjectInfo({ ...mindProjectInfo, name: e.target.value })
+            }
+          />
+        )}
       </div>
 
       <Tooltip placement="bottom" title="撤销">

+ 42 - 27
apps/designer/src/utils/mindMap.tsx

@@ -5,6 +5,7 @@ import TopicComponent from "@/components/mindMap/Topic";
 import Hierarchy from "@antv/hierarchy";
 import { topicData } from "@/config/data";
 import { uuid } from "@/utils";
+import { SetState } from "ahooks/lib/useSetState";
 
 interface HierarchyResult {
   id: string;
@@ -13,12 +14,17 @@ interface HierarchyResult {
   data: TopicItem;
   children?: HierarchyResult[];
 }
+/**
+ * 渲染思维导图项目
+ * @param graph 
+ */
 export const renderMindMap = (
-  projectInfo: MindMapProjectInfo,
-  graph: Graph
+  graph: Graph,
+  setMindProjectInfo: () => void
 ) => {
+  const projectInfo = getMindMapProjectByLocal();
+  if(!projectInfo) return;
   const { topics, pageSetting } = projectInfo;
-  console.log("主题:", topics);
   const cells: Cell[] = [];
   topics.forEach((topic) => {
     // 遍历出层次结构
@@ -31,24 +37,23 @@ export const renderMindMap = (
         return d.width;
       },
       getHGap(d: TopicItem) {
-        if (d.type === TopicType.main) return 0;
-        if (d.type === TopicType.branch) return pageSetting.branchY;
-        if (d.type === TopicType.sub) return pageSetting.subTopicY;
-        return 0;
+        if (d.type === TopicType.main) return pageSetting.branchX;
+        if (d.type === TopicType.branch) return pageSetting.subTopicX;
+        if (d.type === TopicType.sub) return pageSetting.subTopicX;
+        return 40;
       },
       getVGap(d: TopicItem) {
-        if (d.type === TopicType.main) return 0;
-        if (d.type === TopicType.branch) return pageSetting.branchX;
-        if (d.type === TopicType.sub) return pageSetting.subTopicX;
-        return 0;
+        if (d.type === TopicType.main) return pageSetting.subTopicY;
+        if (d.type === TopicType.branch) return pageSetting.subTopicY;
+        if (d.type === TopicType.sub) return pageSetting.subTopicY;
+        return 20;
       },
       getSide: () => {
         return "right";
       },
     });
     const traverse = (
-      hierarchyItem: HierarchyResult,
-      parent?: HierarchyResult
+      hierarchyItem: HierarchyResult
     ) => {
       if (hierarchyItem) {
         const { data, children, x, y } = hierarchyItem;
@@ -59,8 +64,11 @@ export const renderMindMap = (
             ...TopicComponent,
             width: data.width,
             height: data.height,
-            // parentId: parent?.id,
-            data,
+            data: {
+              ...data,
+              // 节点内部执行数据更新方法
+              setMindProjectInfo,
+            },
             id,
             x,
             y,
@@ -69,7 +77,6 @@ export const renderMindMap = (
 
         if (children) {
           children.forEach((item: HierarchyResult) => {
-            // const { id, data } = item;
             cells.push(
               // 创建连线
               graph.createEdge({
@@ -97,12 +104,20 @@ export const renderMindMap = (
         }
       }
     };
-    console.log('渲染结果', result)
+    
     traverse(result);
   });
 
-  graph.resetCells(cells);
-  graph.centerContent();
+  cells.forEach((cell) => {
+    // 存在更新位置,否则添加
+    if (graph.hasCell(cell.id) && cell.isNode()) {
+      const oldCell = graph.getCellById(cell.id);
+      oldCell.isNode() && oldCell.position(cell.position().x, cell.position().y);
+    } else {
+      graph.addCell(cell);
+    }
+  });
+  // graph.centerContent();
 };
 
 /**
@@ -134,8 +149,8 @@ export const addTopic = (
   };
 
   traverse(projectInfo?.topics || []);
-  console.log('新增结果:', projectInfo);
-  localStorage.setItem("minMapProjectInfo", JSON.stringify(projectInfo));
+
+  parentData?.setMindProjectInfo(projectInfo);
 };
 
 const topicMap = {
@@ -162,19 +177,19 @@ export const buildTopic = (
     id: uuid(),
     type,
     label: topicMap[type] || "自由主题",
-    width: theme[type].width,
-    height: theme[type].height,
+    width: theme[type]?.width || 206,
+    height: theme[type]?.height || 70,
     fill: {
       ...topicData.fill,
-      ...theme[type].fill,
+      ...theme[type]?.fill,
     },
     text: {
       ...topicData.text,
-      ...theme[type].text,
+      ...theme[type]?.text,
     },
     stroke: {
       ...topicData.stroke,
-      ...theme[type].stroke,
+      ...theme[type]?.stroke,
     },
     ...options,
   };
@@ -185,5 +200,5 @@ export const buildTopic = (
  * @returns
  */
 export const getMindMapProjectByLocal = (): MindMapProjectInfo | null => {
-  return JSON.parse(localStorage.getItem("minMapProjectInfo") || "");
+  return JSON.parse(localStorage.getItem("minMapProjectInfo") || "null");
 };