Pārlūkot izejas kodu

perf: 新增utils模块,优化系统设计导出抖动

liaojiaxing 3 mēneši atpakaļ
vecāks
revīzija
62ca41d7c9

+ 7 - 3
apps/designer/src/components/ExportImage.tsx

@@ -5,6 +5,7 @@ import insertCss from "insert-css";
 import { useEffect, useRef, useState } from "react";
 import { Export } from "@antv/x6-plugin-export";
 import { Scroller } from "@antv/x6-plugin-scroller";
+import { getClassRules } from "@repo/utils";
 
 const ExportComponent = ({
   graph,
@@ -97,18 +98,21 @@ const ExportComponent = ({
       case "png":
         printGraph.current?.exportPNG("", {
           quality: formModel.quality === 1 ? 1 : 0.6,
-          // copyStyles: false,
+          copyStyles: false,
+          stylesheet: getClassRules()
         });
         break;
       case "jpg":
         printGraph.current?.exportJPEG("", {
           quality: formModel.quality === 1 ? 1 : 0.6,
-          // copyStyles: false,
+          copyStyles: false,
+          stylesheet: getClassRules()
         });
         break;
       default:
         printGraph.current?.exportSVG("", {
-          // copyStyles: false,
+          copyStyles: false,
+          stylesheet: getClassRules()
         });
     }
   };

+ 1 - 1
apps/designer/src/events/mindMapEvent.ts

@@ -4,7 +4,7 @@ import { addTopic, updateTopic } from "@/pages/mindmap/mindMap";
 import { cellStyle, MindMapProjectInfo, TopicItem } from "@/types";
 import { Dnd } from "@antv/x6-plugin-dnd";
 import { selectTopic } from "@/utils/mindmapHander";
-import { uuid } from "@/utils";
+import { uuid } from "@repo/utils";
 import { getTheme } from "@/pages/mindmap/theme";
 import { traverseNode } from "@/utils/mindmapHander";
 import { EditMindMapElement, AddMindMapElement } from "@/api/systemDesigner";

+ 5 - 3
apps/designer/src/pages/flow/components/MenuBar/index.tsx

@@ -1,6 +1,6 @@
 import { DownloadOutlined, LeftOutlined } from "@ant-design/icons";
 import { Button, Input, Dropdown, MenuProps, Tooltip, InputRef, message } from "antd";
-import React, { useEffect, useRef, useState } from "react";
+import { useEffect, useRef, useState } from "react";
 import logo from "@/assets/logo.png";
 import { Icon, useModel } from "umi";
 import { exportImage } from "@/components/ExportImage";
@@ -30,7 +30,7 @@ import { useFindReplace } from "@/hooks/useFindReplace";
 import { GraphType } from "@/enum";
 import { EditGraph, SaveAll, Copy } from "@/api/systemDesigner";
 import { UploadFile } from "@/api";
-import { base64ToFile } from "@/utils";
+import { getClassRules, base64ToFile } from "@repo/utils";
 
 InsertCss(`
   .custom-color-picker-popover {
@@ -151,7 +151,9 @@ export default function MenuBar() {
     }, {
       width: 300,
       height: 150,
-      quality: 0.2
+      quality: 0.2,
+      copyStyles: false,
+      stylesheet: getClassRules()
     });
   };
 

+ 5 - 2
apps/designer/src/pages/mindmap/components/HeaderToolbar/index.tsx

@@ -6,11 +6,12 @@ import { useModel, Icon } from "umi";
 import { addTopic } from "../../mindMap";
 import { TopicType, GraphType } from "@/enum";
 import { selectTopic, addBorder, addSummary } from "@/utils/mindmapHander";
-import { base64ToFile, createNew } from "@/utils";
+import { createNew } from "@/utils";
 import FindReplaceModal from "@/components/FindReplaceModal";
 import { useFindReplace } from "@/hooks/useFindReplace";
 import { Copy, SaveAll } from "@/api/systemDesigner";
 import { UploadFile } from "@/api";
+import { base64ToFile, getClassRules } from "@repo/utils";
 
 export default function index() {
   const {
@@ -92,7 +93,9 @@ export default function index() {
     }, {
       width: 300,
       height: 150,
-      quality: 0.2
+      quality: 0.2,
+      copyStyles: false,
+      stylesheet: getClassRules()
     });
   };
 

+ 1 - 1
apps/designer/src/pages/mindmap/mindMap.tsx

@@ -5,7 +5,7 @@ import Topic 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 { uuid } from "@repo/utils";
 import { hierarchyMethodMap } from "@/pages/mindmap/hierarchy";
 import { createEdge } from "./edge";
 import { getTheme } from "./theme";

+ 0 - 43
apps/designer/src/utils/index.ts

@@ -30,15 +30,6 @@ export const printHandle = (imgUri: string) => {
   });
 };
 
-/* uuid */
-export function uuid() {
-  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
-    var r = (Math.random() * 16) | 0,
-      v = c === "x" ? r : (r & 0x3) | 0x8;
-    return v.toString(16);
-  });
-}
-
 /**
  * 创建新的图形
  */
@@ -93,40 +84,6 @@ export const listToTree = (list: TreeNode[], parent: TreeNode): TreeNode => {
   return parent;
 };
 
-/**
- * base64 转 file
- * @param base64String
- * @param fileName
- * @param fileType
- * @returns
- */
-export function base64ToFile(
-  base64String: string,
-  fileName: string,
-  fileType: string
-): File {
-  // 移除Base64字符串中的前缀(如"data:image/png;base64,")
-  const base64Data = base64String.split(",")[1];
-
-  // 解码Base64字符串
-  const byteCharacters = atob(base64Data);
-
-  // 创建一个Uint8Array来存储二进制数据
-  const byteArrays = new Uint8Array(byteCharacters.length);
-
-  for (let i = 0; i < byteCharacters.length; i++) {
-    byteArrays[i] = byteCharacters.charCodeAt(i);
-  }
-
-  // 创建Blob对象
-  const blob = new Blob([byteArrays], { type: fileType });
-
-  // 创建File对象
-  const file = new File([blob], fileName, { type: fileType });
-
-  return file;
-}
-
 /**
  * 获取token
  */

+ 1 - 2
apps/designer/src/utils/mindmapHander.tsx

@@ -4,10 +4,9 @@ import { HierarchyResult, MindMapProjectInfo, TopicItem } from "@/types";
 import { Cell, Graph, Node, Edge } from "@antv/x6";
 import { message } from "antd";
 import { cloneDeep } from "lodash-es";
-import { uuid } from "@/utils";
+import { uuid } from "@repo/utils";
 import { ContextMenuTool } from "./contentMenu";
 import { MutableRefObject } from "react";
-import { exportImage } from "@/components/ExportImage";
 import TopicBorder from "@/components/mindMap/Border";
 import SummaryBorder from "@/components/mindMap/SummaryBorder";
 import { openInsertImageModal } from "@/components/ImageModal";

+ 2 - 22
apps/er-designer/src/models/erModel.tsx

@@ -8,8 +8,9 @@ import { Export } from "@antv/x6-plugin-export";
 import { Selection } from "@antv/x6-plugin-selection";
 import { SaveDataModel, UploadFile } from "@/api";
 import { useFullscreen, useSessionStorageState } from "ahooks";
-import { base64ToFile, createTable, uuid } from "@/utils";
+import { createTable } from "@/utils";
 import dayjs from "dayjs";
+import { getClassRules, base64ToFile, uuid } from "@repo/utils";
 
 import type {
   ColumnItem,
@@ -911,26 +912,6 @@ export default function erModel() {
     setPlayModeEnable(false);
   };
 
-  const getClassRules = (): string => {
-    let rules = ''
-    const { styleSheets } = document
-    for (let i = 0; i < styleSheets.length; i++) {
-      const sheet = styleSheets[i]
-      // 这里是为了过滤掉不同源 css 脚本,防止报错终止导出
-      try {
-        for (let j = 0; j < sheet.cssRules.length; j++) {
-          rules += sheet.cssRules[j].cssText
-        }
-      } catch (error) {
-        console.log(
-          'CSS scripts from different sources have been filtered out',
-        )
-      }
-    }
-
-    return rules
-  }
-
   /**
    * 保存项目
    */
@@ -1011,6 +992,5 @@ export default function erModel() {
     onSave,
     tableActive,
     setTableActive,
-    getClassRules
   };
 }

+ 1 - 1
apps/er-designer/src/pages/er/components/Menu.tsx

@@ -13,6 +13,7 @@ import { useModel } from "umi";
 import { useFullscreen } from "ahooks";
 import AddModel from "@/components/AddModel";
 import { TableType } from "@/enum";
+import { getClassRules } from "@repo/utils";
 export default function Menu() {
   const {
     project,
@@ -30,7 +31,6 @@ export default function Menu() {
     enterPlayMode,
     saveTime,
     onSave,
-    getClassRules,
   } = useModel("erModel");
   const [modal, contextHolder] = Modal.useModal();
   const [isFullscreen, { toggleFullscreen }] = useFullscreen(document.body);

+ 1 - 1
apps/er-designer/src/pages/er/components/TodoDrawer.tsx

@@ -14,7 +14,7 @@ import {
 } from "antd";
 import { useModel } from "umi";
 import { TodoItem } from "@/type";
-import { uuid } from "@/utils";
+import { uuid } from "@repo/utils";
 import noData from "@/assets/no-data.png";
 
 const TodoDrawer = forwardRef((props: {}, ref) => {

+ 1 - 1
apps/er-designer/src/pages/home/All.tsx

@@ -30,7 +30,7 @@ import DragItem from "./DragItem";
 import DropItem from "./DropItem";
 import { TableType } from "@/enum";
 import AddModel from "@/components/AddModel";
-import { uuid } from "@/utils";
+import { uuid } from "@repo/utils";
 import { ProjectInfo } from "@/type";
 
 type BreadcrumbItem = {

+ 1 - 45
apps/er-designer/src/utils/index.ts

@@ -1,50 +1,6 @@
 import { DataType, TableType } from "@/enum";
 import { ColumnItem, TableItemType } from "@/type";
-
-/**
- * 创建uuid
- * */
-export function uuid() {
-  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
-    var r = (Math.random() * 16) | 0,
-      v = c === "x" ? r : (r & 0x3) | 0x8;
-    return v.toString(16);
-  });
-}
-
-/**
- * base64 转 file
- * @param base64String
- * @param fileName
- * @param fileType
- * @returns
- */
-export function base64ToFile(
-  base64String: string,
-  fileName: string,
-  fileType: string
-): File {
-  // 移除Base64字符串中的前缀(如"data:image/png;base64,")
-  const base64Data = base64String.split(",")[1];
-
-  // 解码Base64字符串
-  const byteCharacters = atob(base64Data);
-
-  // 创建一个Uint8Array来存储二进制数据
-  const byteArrays = new Uint8Array(byteCharacters.length);
-
-  for (let i = 0; i < byteCharacters.length; i++) {
-    byteArrays[i] = byteCharacters.charCodeAt(i);
-  }
-
-  // 创建Blob对象
-  const blob = new Blob([byteArrays], { type: fileType });
-
-  // 创建File对象
-  const file = new File([blob], fileName, { type: fileType });
-
-  return file;
-}
+import { uuid } from "@repo/utils";
 
 /**
  * 获取token

+ 2 - 1
package.json

@@ -65,6 +65,7 @@
     "thememirror": "^2.0.1",
     "umi": "^4.3.18",
     "unocss": "^0.62.3",
-    "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
+    "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
+    "@repo/utils": "workspace:*"
   }
 }

+ 7 - 0
packages/utils/package.json

@@ -0,0 +1,7 @@
+{
+  "name": "@repo/utils",
+  "version": "0.0.0",
+  "private": true,
+  "module": "./src/index.ts",
+  "types": "./src/index.ts"
+}

+ 66 - 0
packages/utils/src/index.ts

@@ -0,0 +1,66 @@
+/**
+ * 获取全局的样式
+ * @returns 样式
+ */
+export const getClassRules = (): string => {
+  let rules = ''
+  const { styleSheets } = document
+  for (let i = 0; i < styleSheets.length; i++) {
+    const sheet = styleSheets[i]
+    // 这里是为了过滤掉不同源 css 脚本,防止报错终止导出
+    try {
+      for (let j = 0; j < sheet.cssRules.length; j++) {
+        rules += sheet.cssRules[j].cssText
+      }
+    } catch (error) {
+      console.log(
+        'CSS scripts from different sources have been filtered out',
+      )
+    }
+  }
+
+  return rules
+}
+
+/**
+ * base64 转 file
+ * @param base64String
+ * @param fileName
+ * @param fileType
+ * @returns
+ */
+export function base64ToFile(
+  base64String: string,
+  fileName: string,
+  fileType: string
+): File {
+  // 移除Base64字符串中的前缀(如"data:image/png;base64,")
+  const base64Data = base64String.split(",")[1];
+
+  // 解码Base64字符串
+  const byteCharacters = atob(base64Data);
+
+  // 创建一个Uint8Array来存储二进制数据
+  const byteArrays = new Uint8Array(byteCharacters.length);
+
+  for (let i = 0; i < byteCharacters.length; i++) {
+    byteArrays[i] = byteCharacters.charCodeAt(i);
+  }
+
+  // 创建Blob对象
+  const blob = new Blob([byteArrays], { type: fileType });
+
+  // 创建File对象
+  const file = new File([blob], fileName, { type: fileType });
+
+  return file;
+}
+
+/* uuid */
+export function uuid() {
+  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
+    var r = (Math.random() * 16) | 0,
+      v = c === "x" ? r : (r & 0x3) | 0x8;
+    return v.toString(16);
+  });
+}

+ 20 - 0
packages/utils/tsconfig.json

@@ -0,0 +1,20 @@
+{
+  "exclude": ["node_modules", "**/es", "**/lib"],
+  "compilerOptions": {
+    "module": "commonjs",
+    "moduleResolution": "node",
+    "sourceMap": true,
+    "declaration": true,
+    "skipLibCheck": true,
+    "esModuleInterop": true,
+    "noImplicitAny": true,
+    "noEmitOnError": true,
+    "noUnusedLocals": true,
+    "strictNullChecks": true,
+    "resolveJsonModule": true,
+    "experimentalDecorators": true,
+    "jsx": "react",
+    "target": "es6",
+    "lib": ["DOM", "ES2020"]
+  }
+}

+ 10 - 5
pnpm-lock.yaml

@@ -110,6 +110,9 @@ importers:
       '@emotion/css':
         specifier: ^11.13.0
         version: 11.13.0
+      '@repo/utils':
+        specifier: workspace:*
+        version: link:packages/utils
       '@types/lodash-es':
         specifier: ^4.17.12
         version: 4.17.12
@@ -322,11 +325,9 @@ importers:
         specifier: ^5.3.3
         version: 5.5.4
 
-  packages/x6-plugin-export:
-    devDependencies:
-      '@antv/x6':
-        specifier: ^2.x
-        version: 2.18.1
+  packages/utils: {}
+
+  packages/x6-plugin-export: {}
 
   packages/x6-plugin-selection: {}
 
@@ -759,9 +760,11 @@ packages:
     dependencies:
       lodash-es: 4.17.21
       utility-types: 3.11.0
+    dev: false
 
   /@antv/x6-geometry@2.0.5:
     resolution: {integrity: sha512-MId6riEQkxphBpVeTcL4ZNXL4lScyvDEPLyIafvWMcWNTGK0jgkK7N20XSzqt8ltJb0mGUso5s56mrk8ysHu2A==}
+    dev: false
 
   /@antv/x6-plugin-clipboard@2.1.6(@antv/x6@2.18.1):
     resolution: {integrity: sha512-roZPLnZx6PK8MBvee0QMo90fz/TXeF0WNe4EGin2NBq5M1I5XTWrYvA6N2XVIiWAAI67gjQeEE8TpkL7f8QdqA==}
@@ -862,6 +865,7 @@ packages:
       '@antv/x6-common': 2.0.17
       '@antv/x6-geometry': 2.0.5
       utility-types: 3.11.0
+    dev: false
 
   /@babel/code-frame@7.24.7:
     resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==}
@@ -14593,6 +14597,7 @@ packages:
   /utility-types@3.11.0:
     resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==}
     engines: {node: '>= 4'}
+    dev: false
 
   /utils-merge@1.0.1:
     resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}