Browse Source

feat: 优化主题宽高自动设置

liaojiaxing 6 months ago
parent
commit
f93b0cee28

+ 5 - 1
apps/designer/src/components/lane/Pool.tsx

@@ -2,7 +2,7 @@ import { Node } from "@antv/x6";
 import CustomInput from "../CustomInput";
 import { LaneItem, StageItem } from "@/types";
 import { useEffect, useRef, useState } from "react";
-import { Input, InputNumber, Popover } from "antd";
+import { InputNumber, Popover } from "antd";
 
 export default function Pool({
   node,
@@ -174,6 +174,7 @@ export default function Pool({
                           <InputNumber
                             min={10}
                             max={300}
+                            precision={0}
                             value={stageWidth}
                             onChange={(val) => handleChangeStageWidth(val)}
                           />
@@ -261,6 +262,7 @@ export default function Pool({
                     <span>宽度:</span>
                     <InputNumber
                       min={20}
+                      precision={0}
                       value={item.width}
                       onChange={(val) => handleChangeLaneWidth(index, val)}
                     />
@@ -356,6 +358,7 @@ export default function Pool({
                         <InputNumber
                           min={10}
                           max={300}
+                          precision={0}
                           value={stageWidth}
                           onChange={(val) => handleChangeStageWidth(val)}
                         />
@@ -427,6 +430,7 @@ export default function Pool({
                     <span>高度:</span>
                     <InputNumber
                       min={20}
+                      precision={0}
                       value={item.width}
                       onChange={(val) => handleChangeLaneWidth(index, val)}
                     />

+ 2 - 0
apps/designer/src/components/mindMap/Topic.tsx

@@ -108,10 +108,12 @@ const component = ({ node, graph }: { node: Node; graph: Graph }) => {
 
   const changeSize = () => {
     const { clientHeight = 0, clientWidth = 0 } = ref.current || {};
+    const size = node.size();
     if (
       clientHeight &&
       (size.width !== clientWidth || size.height !== clientHeight)
     ) {
+      node.size(clientWidth, clientHeight);
       node.setData({
         width: clientWidth,
         height: clientHeight,

+ 9 - 5
apps/designer/src/models/appModel.ts

@@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react";
 import { message } from "antd";
 import brushImg from "@/assets/image/brush.svg"
 import { cellStyle } from '@/types'
+import { useLocalStorageState } from "ahooks";
 
 interface PageSettings {
   // 背景颜色
@@ -25,11 +26,14 @@ interface PageSettings {
   watermarkText: string;
 }
 export default function appModel() {
-  const [projectInfo, setProjectInfo] = useState({
-    name: "新建流程图",
-    desc: "",
-    version: "",
-    author: "",
+  const [projectInfo, setProjectInfo] = useLocalStorageState('flow-project', {
+    defaultValue: {
+      name: "新建流程图",
+      desc: "",
+      version: "",
+      author: "",
+      cells: []
+    }
   });
   // 隐藏/显示右侧面板
   const [showRightPanel, setShowRightPanel] = useState(true);

+ 141 - 95
apps/designer/src/models/graphModel.ts

@@ -1,19 +1,19 @@
-import { useState, useRef, useEffect } from 'react'
-import { Cell, Graph, Node } from '@antv/x6'
-import { Dnd } from '@antv/x6-plugin-dnd'
-import { Transform } from '@antv/x6-plugin-transform'
-import { Snapline } from '@antv/x6-plugin-snapline'
-import { Clipboard } from '@antv/x6-plugin-clipboard'
-import { Selection } from '@repo/x6-plugin-selection/src/index'
-import { History } from '@antv/x6-plugin-history'
-import { Keyboard } from '@antv/x6-plugin-keyboard'
-import { Export } from '@antv/x6-plugin-export'
-import { useModel } from 'umi'
-import '@/components/PageContainer'
-import { handleGraphEvent } from '@/events/flowEvent'
-import { pageMenu, nodeMenu} from '@/utils/contentMenu';
-import { bindKeys } from '@/utils/fastKey'
-import { useFindReplace } from '@/hooks/useFindReplace'
+import { useState, useRef, useEffect } from "react";
+import { Cell, Graph, Node } from "@antv/x6";
+import { Dnd } from "@antv/x6-plugin-dnd";
+import { Transform } from "@antv/x6-plugin-transform";
+import { Snapline } from "@antv/x6-plugin-snapline";
+import { Clipboard } from "@antv/x6-plugin-clipboard";
+import { Selection } from "@repo/x6-plugin-selection/src/index";
+import { History } from "@antv/x6-plugin-history";
+import { Keyboard } from "@antv/x6-plugin-keyboard";
+import { Export } from "@antv/x6-plugin-export";
+import { useModel } from "umi";
+import "@/components/PageContainer";
+import { handleGraphEvent } from "@/events/flowEvent";
+import { pageMenu, nodeMenu } from "@/utils/contentMenu";
+import { bindKeys } from "@/utils/fastKey";
+import { useLocalStorageState } from "ahooks";
 
 export default function GraphModel() {
   const [graph, setGraph] = useState<Graph>();
@@ -23,159 +23,205 @@ export default function GraphModel() {
   const dndRef = useRef(dnd);
   // 画布
   const graphRef = useRef<Graph>();
-  const { pageState } = useModel('appModel');
+  const { pageState } = useModel("appModel");
   // 当前选中的节点
   const [selectedCell, setSelectedCell] = useState<Cell[]>([]);
   const [canRedo, setCanRedo] = useState(false);
   const [canUndo, setCanUndo] = useState(false);
 
+  const [projectInfo, setProjectInfo] = useLocalStorageState<{
+    name: string;
+    desc: string;
+    version: string;
+    author: string;
+    cells: Cell.Properties[];
+  }>("flow-project", {
+    defaultValue: {
+      name: "新建流程图",
+      desc: "",
+      version: "",
+      author: "",
+      cells: [],
+    },
+  });
+
+  const handleChangeAll = () => {
+    const cells = graph?.toJSON().cells || [];
+
+    projectInfo &&
+      setProjectInfo({
+        ...projectInfo,
+        cells: cells,
+      });
+  };
+
+  useEffect(() => {
+    console.log("画布加载完毕");
+    if (graph) {
+      graph.fromJSON(projectInfo?.cells || []);
+      graph.on("cell:change:*", handleChangeAll);
+    }
+  }, [graph]);
+
   /**初始化页面节点 */
   useEffect(() => {
-    if(pageState.width && graphRef.current && !pageNodeRef.current) {
+    if (pageState.width && graphRef.current && !pageNodeRef.current) {
       const graph = graphRef.current;
       pageNodeRef.current = graph?.addNode({
-        shape: 'page-container-node',
+        shape: "page-container-node",
         width: pageState.width,
         height: pageState.height,
         zIndex: -1,
         data: {
           isPage: true,
           ignoreDrag: true,
-          ...pageState
+          ...pageState,
         },
         tools: [
           {
-            name: 'contextmenu',
+            name: "contextmenu",
             args: {
               menu: pageMenu,
             },
           },
-        ]
+        ],
       });
-    };
-  }, [pageState.width, graphRef.current])
+    }
+  }, [pageState.width, graphRef.current]);
 
   useEffect(() => {
     pageNodeRef.current?.setData({
       background: pageState.backgroundColor,
-      ...pageState
+      ...pageState,
     });
     pageNodeRef.current?.setSize({
       width: pageState.width,
-      height: pageState.height
-    })
+      height: pageState.height,
+    });
   }, [pageState]);
 
   const enabledTransform = (node: Node) => {
-    const data = node.getData<{ isPage: boolean, lock: boolean }>();
+    const data = node.getData<{ isPage: boolean; lock: boolean }>();
     return !data?.isPage && !data?.lock;
-  }
+  };
   /**初始化画布 */
   const initGraph = (instance: Graph) => {
     // 添加插件
     instance
-    .use(
-      new Transform({
-        resizing: {
-          enabled: enabledTransform,
-          minWidth: 20,
-          minHeight: 20
-        },
-        rotating: {
-          enabled: enabledTransform,
-          grid: 1
-        },
-      }),
-    )
-    .use(
-      new Selection({
-        enabled: true,
-        multiple: true,
-        rubberband: true,
-        movable: true,
-        showNodeSelectionBox: true,
-        // showEdgeSelectionBox: true,
-        pointerEvents: 'none',
-        strict: true,
-        filter: (cell: Cell) => {
-          const data = cell.getData<{ isPage: boolean, lock: boolean }>();
-          return !data?.isPage && !data?.lock;
-        },
-      }),
-    )
-    .use(new Snapline({
-      sharp: true,
-      resizing: true
-    }))
-    .use(new Keyboard({
-      enabled: true,
-      global: true,
-    }))
-    .use(new Clipboard())
-    .use(new History({
-      enabled: true,
-      beforeAddCommand: (event, args) => {
-        // @ts-ignore 排除不用创建的节点
-        if(args?.cell?.data?.noCreate) return false;
-        // @ts-ignore 排除页面节点
-        return !(event === 'cell:added' && args?.cell?.getData()?.isPage);
-      },
-    }))
-    .use(new Export());
+      .use(
+        new Transform({
+          resizing: {
+            enabled: enabledTransform,
+            minWidth: 20,
+            minHeight: 20,
+          },
+          rotating: {
+            enabled: enabledTransform,
+            grid: 1,
+          },
+        })
+      )
+      .use(
+        new Selection({
+          enabled: true,
+          multiple: true,
+          rubberband: true,
+          movable: true,
+          showNodeSelectionBox: true,
+          // showEdgeSelectionBox: true,
+          pointerEvents: "none",
+          strict: true,
+          filter: (cell: Cell) => {
+            const data = cell.getData<{ isPage: boolean; lock: boolean }>();
+            return !data?.isPage && !data?.lock;
+          },
+        })
+      )
+      .use(
+        new Snapline({
+          sharp: true,
+          resizing: true,
+        })
+      )
+      .use(
+        new Keyboard({
+          enabled: true,
+          global: true,
+        })
+      )
+      .use(new Clipboard())
+      .use(
+        new History({
+          enabled: true,
+          beforeAddCommand: (event, args) => {
+            // @ts-ignore 排除不用创建的节点
+            if (args?.cell?.data?.noCreate) return false;
+            // @ts-ignore 排除页面节点
+            return !(event === "cell:added" && args?.cell?.getData()?.isPage);
+          },
+        })
+      )
+      .use(new Export());
 
     setGraph(instance);
     graphRef.current = instance;
 
     // 选中的节点/边发生改变(增删)时触发
-    instance.on('selection:changed', ({selected}: {added: Cell[]; removed: Cell[]; selected: Cell[];}) => {
-      setSelectedCell(selected);
-    })
-
-    instance.on('history:change', () => {
+    instance.on(
+      "selection:changed",
+      ({ selected }: { added: Cell[]; removed: Cell[]; selected: Cell[] }) => {
+        setSelectedCell(selected);
+      }
+    );
+
+    instance.on("history:change", () => {
       setCanRedo(instance.canRedo());
       setCanUndo(instance.canUndo());
-    })
+    });
 
     // 通用事件处理
     handleGraphEvent(instance);
 
     // 绑定快捷键
     bindKeys(instance);
-  }
+  };
 
   /**初始化拖拽 */
   const initDnd = (instance: Dnd) => {
     setDnd(instance);
     dndRef.current = instance;
-  }
+  };
 
   /**组件库拖拽生成 */
-  const startDrag = (e: React.MouseEvent<HTMLDivElement, MouseEvent>, node: Node.Metadata) => {
-    if(!dndRef.current || !graphRef.current) return;
+  const startDrag = (
+    e: React.MouseEvent<HTMLDivElement, MouseEvent>,
+    node: Node.Metadata
+  ) => {
+    if (!dndRef.current || !graphRef.current) return;
 
     // 往画布添加节点
     const n = graphRef.current.createNode(node);
     // 右键菜单
     n.addTools({
-      name: 'contextmenu',
+      name: "contextmenu",
       args: {
         menu: nodeMenu,
       },
     });
-    dndRef.current.start(n, e.nativeEvent as any)
+    dndRef.current.start(n, e.nativeEvent as any);
   };
 
   // 撤销
   const onUndo = () => {
     graphRef.current?.undo();
-  }
+  };
 
   // 重做
   const onRedo = () => {
     graphRef.current?.redo();
-  }
+  };
 
-  return { 
+  return {
     graph,
     dnd,
     initGraph,
@@ -185,6 +231,6 @@ export default function GraphModel() {
     canRedo,
     canUndo,
     onUndo,
-    onRedo
-   };
-};
+    onRedo,
+  };
+}

+ 0 - 5
apps/designer/src/models/mindMapModel.ts

@@ -112,10 +112,6 @@ export default function mindMapModel() {
     }
   }, [graph, mindProjectInfo?.pageSetting]);
 
-  const getMindProject = () => {
-    return mindProjectInfo;
-  };
-
   // 初始化脑图
   const initMindMap = (container: HTMLElement) => {
     const instance = new Graph({
@@ -210,7 +206,6 @@ export default function mindMapModel() {
       setRightToolbarActive,
       correlationEdgeRef,
       setMindProjectInfo,
-      getMindProject,
     };
 
     setGraph(instance);

+ 1 - 2
apps/designer/src/pages/home/index.tsx

@@ -60,8 +60,7 @@ const basicGraph = [
     subtitle: "结构化表单方式",
     color: "#dff4ea",
     icon: <Icon icon="local:mind" />,
-    path: "/mindmap",
-    onClick: () => createNew("flow"),
+    onClick: () => createNew("mindmap"),
   },
 ];