Browse Source

feat: 添加快捷键功能

liaojiaxing 5 months ago
parent
commit
071d5a484c

+ 1 - 0
apps/er-designer/src/components/TableNode.tsx

@@ -202,6 +202,7 @@ function TableNode({ node, graph }: { node: Node; graph: Graph }) {
         "
       >
         <div className="truncate flex-1">
+          <span className="text-12px font-normal">{table.parentBusinessTableId && '[子]'}</span>
           {table.schemaName}({table.cn_name})
         </div>
         {showEdit && (

+ 67 - 32
apps/er-designer/src/models/erModel.tsx

@@ -225,6 +225,26 @@ export default function erModel() {
         updateRemark(args.current);
       }
     );
+
+    instance.bindKey("ctrl+z", onUndo);
+    instance.bindKey("ctrl+y", onRedo);
+    instance.bindKey("ctrl+c", onCopy);
+    instance.bindKey("ctrl+x", onCut);
+    instance.bindKey("ctrl+v", onPaste);
+    instance.bindKey("ctrl+down", () => {
+      const scale = instance.zoom() - 0.1;
+      instance.zoom(scale < 0.2 ? 0.2 : scale);
+    });
+    instance.bindKey("ctrl+up", () => {
+      const scale = instance.zoom() + 0.1;
+      instance.zoom(scale > 2 ? 2 : scale);
+    });
+    instance.bindKey("ctrl+n", () => {
+      // todo 新建
+    });
+    instance.bindKey("ctrl+s", () => {
+      // todo 保存
+    });
   };
 
   // 能否重做
@@ -325,15 +345,17 @@ export default function erModel() {
     };
 
     // 子表插入到父表后面
-    const tables = [...project.tables];
-    tables.splice(
-      tables.findIndex((item) => item.table.id === parentId) + 1,
-      0,
-      newTable
-    );
-    setProject({
-      ...project,
-      tables: parentId ? tables : [...project.tables, newTable],
+    setProject((state) => {
+      const tables = [...state.tables];
+      tables.splice(
+        tables.findIndex((item) => item.table.id === parentId) + 1,
+        0,
+        newTable
+      );
+      return {
+        ...state,
+        tables: parentId ? tables : [...state.tables, newTable],
+      };
     });
   };
 
@@ -358,6 +380,9 @@ export default function erModel() {
    * @param tableId
    */
   const deleteTable = (tableId: string) => {
+    const childTableIds = project.tables
+      .filter((item) => item.table.parentBusinessTableId === tableId)
+      .map((item) => item.table.id);
     setProject({
       ...project,
       tables: project.tables.filter(
@@ -365,18 +390,15 @@ export default function erModel() {
           item.table.id !== tableId ||
           item.table.parentBusinessTableId !== tableId
       ),
-      // todo 处理子表对应关系
+      // 对应关系
       relations: project.relations.filter(
-        (item) => item.primaryTable !== tableId && item.foreignTable !== tableId
+        (item) =>
+          item.primaryTable !== tableId &&
+          item.foreignTable !== tableId &&
+          !childTableIds.includes(item.primaryTable) &&
+          !childTableIds.includes(item.foreignTable)
       ),
     });
-    graphRef.current?.removeCell(tableId);
-    // 删除关联关系
-    project.relations.forEach((item) => {
-      if (item.primaryTable === tableId || item.foreignTable === tableId) {
-        graphRef.current?.removeCell(item.id);
-      }
-    });
   };
 
   /**
@@ -424,7 +446,6 @@ export default function erModel() {
       ...project,
       topicAreas: project.topicAreas.filter((item) => item.id !== topicAreaId),
     });
-    graphRef.current?.removeCell(topicAreaId);
   };
 
   /**
@@ -585,8 +606,6 @@ export default function erModel() {
       ...project,
       relations: project.relations.filter((item) => item.id !== relationId),
     });
-    // 删除连线
-    graphRef.current?.removeCell(relationId);
   };
 
   /**
@@ -619,9 +638,23 @@ export default function erModel() {
       const data = cell.data;
       setClipboardCache(data);
       if (data?.isTable) {
+        const childTableIds = project.tables
+          .filter((item) => item.table.parentBusinessTableId === cell.id)
+          .map((item) => item.table.id);
         setProject({
           ...project,
-          tables: project.tables.filter((item) => item.table.id !== cell.id),
+          tables: project.tables.filter(
+            (item) =>
+              item.table.id !== cell.id &&
+              !childTableIds.includes(item.table.id)
+          ),
+          relations: project.relations.filter(
+            (item) =>
+              item.primaryTable !== cell.id &&
+              item.foreignTable !== cell.id &&
+              !childTableIds.includes(item.primaryTable) &&
+              !childTableIds.includes(item.foreignTable)
+          ),
         });
       }
       if (data?.isTopicArea) {
@@ -669,16 +702,16 @@ export default function erModel() {
               ...data.table.style,
               x: data.table.style.x + 20,
               y: data.table.style.y + 20,
-            }
+            },
           },
           tableColumnList: data.tableColumnList.map((item: ColumnItem) => {
             return {
               ...item,
               id: uuid(),
-              parentBusinessTableId: tableId
-            }
-          })
-        }
+              parentBusinessTableId: tableId,
+            };
+          }),
+        };
         setProject({
           ...project,
           tables: [...project.tables, newTable],
@@ -694,7 +727,7 @@ export default function erModel() {
             ...data.style,
             x: data.style.x + 20,
             y: data.style.y + 20,
-          }
+          },
         };
         setProject({
           ...project,
@@ -711,7 +744,7 @@ export default function erModel() {
             ...data.style,
             x: data.style.x + 20,
             y: data.style.y + 20,
-          }
+          },
         };
         setProject({
           ...project,
@@ -736,9 +769,11 @@ export default function erModel() {
       }
       if (data?.isTopicArea) {
         setProject({
-         ...project,
-         topicAreas: project.topicAreas.filter((item) => item.id !== cell[0].id),
-        })
+          ...project,
+          topicAreas: project.topicAreas.filter(
+            (item) => item.id !== cell[0].id
+          ),
+        });
       }
       if (data?.isRemark) {
         setProject({

+ 1 - 1
apps/er-designer/src/models/renderer.ts

@@ -10,7 +10,7 @@ export const render = (graph: Graph, project: ProjectInfo) => {
       shape: "table-node",
       x: tableItem.table.style?.x || 1000,
       y: tableItem.table.style?.y || 1000,
-      width: 220,
+      width: project.setting.tableWidth,
       height: 69,
       id: tableItem.table.id,
       data: tableItem,

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

@@ -1,5 +1,5 @@
 import React, { useState } from "react";
-import { Button, Dropdown, Input, Modal, Switch } from "antd";
+import { Button, Dropdown, Input, Modal, Switch, InputNumber } from "antd";
 import type { DropDownProps, MenuProps } from "antd";
 import { useModel } from "umi";
 import { useFullscreen } from "ahooks";
@@ -21,6 +21,7 @@ export default function Menu() {
   const [modal, contextHolder] = Modal.useModal();
   const [isFullscreen, { toggleFullscreen }] = useFullscreen(document.body);
   const [openKey, setOpenKey] = useState("");
+  const [open, setOpen] = useState(false);
   const handleClean = () => {
     modal.confirm({
       title: "确认清除画布全部内容?",
@@ -33,7 +34,7 @@ export default function Menu() {
     });
   };
 
-  const handleChangeSetting = (key: string, value: boolean) => {
+  const handleChangeSetting = (key: string, value: boolean | number | null) => {
     setProject({ ...project, setting: { ...project.setting, [key]: value } });
   };
 
@@ -214,6 +215,7 @@ export default function Menu() {
         {
           key: "1-4",
           label: "表格宽度",
+          onClick: () => setOpen(true)
         },
       ],
     },
@@ -239,6 +241,7 @@ export default function Menu() {
   };
 
   return (
+    <>
     <div className="flex-1 flex items-center">
       {contextHolder}
       <div className="logo h-48px m-l-12px">
@@ -278,5 +281,27 @@ export default function Menu() {
         </div>
       </div>
     </div>
+    <Modal
+      title="设置表格宽度"
+      centered
+      width={440}
+      open={open}
+      okText="确定"
+      onOk={() => setOpen(false)}
+      onCancel={() => setOpen(false)}
+      footer={(_, {OkBtn}) => {
+        return <OkBtn/>
+      }}
+    >
+      <InputNumber
+        className="w-full"
+        min={150}
+        max={1000}
+        value={project.setting.tableWidth}
+        onChange={(value) => handleChangeSetting("tableWidth", value)}
+      />
+    </Modal>
+    </>
+    
   );
 }