liaojiaxing 2 months ago
parent
commit
3cecb03ef6

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

@@ -128,7 +128,7 @@ export const handleGraphApiEvent = (graph: Graph) => {
   let timer1: any;
   let map: Record<string, any> = {};
   graph.on("cell:change:*", (args: EventArgs["cell:change:*"]) => {
-    if(args.cell?.data?.isPage || args.key === 'tools') return;
+    if(args.cell?.data?.isPage || args.key === 'tools' || timer2) return;
     const setData = () => {
       const id = args.cell.id;
       const data = args.cell.toJSON();

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

@@ -93,9 +93,9 @@ export default function Content() {
         highlight: false,
         // anchor: "center",
         // connectionPoint: "anchor",
-        // snap: {
-        //   radius: 20,
-        // },
+        snap: {
+          radius: 20,
+        },
         createEdge() {
           return new Shape.Edge({
             ...BaseEdge,

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

@@ -422,7 +422,7 @@ export default function All({
           }}
           trigger={["contextMenu"]}
         >
-          <div>
+          <div style={{minHeight: "calc(100vh - 78px)"}}>
             {display === "card" ? (
               <>
                 {folderData.length ? (

+ 14 - 2
apps/er-designer/src/components/TableNode.tsx

@@ -3,10 +3,10 @@ import { register } from "@antv/x6-react-shape";
 import { Graph, Node } from "@antv/x6";
 import type { ColumnItem, TableItemType } from "@/type";
 import { DATA_TYPE_OPTIONS } from "@/constants";
-import { useSessionStorageState } from "ahooks";
+import { useSessionStorageState, useLocalStorageState } from "ahooks";
 
 function TableNode({ node, graph }: { node: Node; graph: Graph }) {
-  const { table, tableColumnList } = node.getData<TableItemType>();
+  const { table, tableColumnList: columnsList } = node.getData<TableItemType>();
   const containerRef = useRef<HTMLDivElement>(null);
   const [showEdit, setShowEdit] = React.useState(false);
   const [_tabActiveKey, setTabActiveKey] =
@@ -15,6 +15,18 @@ function TableNode({ node, graph }: { node: Node; graph: Graph }) {
   const [playModeEnable] = useSessionStorageState("playModeEnable", {
     listenStorageChange: true,
   });
+  // 隐藏默认字段
+  const [hideDefaultColumn] = useLocalStorageState(
+    "er-hideDefaultColumn",
+    {
+      defaultValue: false,
+      listenStorageChange: true
+    }
+  );
+
+  const tableColumnList = useMemo(() => {
+    return columnsList.filter(item => hideDefaultColumn ? !item.isPreDefined : true);
+  }, [columnsList, hideDefaultColumn]);
 
   useEffect(() => {
     const container = containerRef.current;

+ 48 - 2
apps/er-designer/src/pages/detail/index.tsx

@@ -8,6 +8,7 @@ import {
   Tooltip,
   Empty,
   Spin,
+  Modal
 } from "antd";
 import { ProDescriptions } from "@ant-design/pro-components";
 import type { DescriptionsProps, MenuProps } from "antd";
@@ -52,6 +53,20 @@ export default function index() {
   const [collapsed, setCollapsed] = useState(false);
   const [seachColumn, setSearchColumn] = useState("");
 
+  // 双击选中表数据
+  const [selectTableItem, setSelectTableItem] = React.useState<TableItemType>();
+  const [open, setOpen] = useState(false);
+
+  useEffect(() => {
+    graph?.on("node:dblclick", (args) => {
+      const data = args.node.getData();
+      if (data?.isTable) {
+        setOpen(true);
+        setSelectTableItem(data);
+      }
+    });
+  }, [graph]);
+
   useEffect(() => {
     insertCss(`
       .ant-descriptions-header {
@@ -210,9 +225,11 @@ export default function index() {
   };
 
   const handleEnterEdit = () => {
-    exitPlayMode();
+    const { origin, pathname } = window.location;
     const enterpriseCode = sessionStorage.getItem("enterpriseCode");
-    history.push(`/er/${project.id}?enterpriseCode=${enterpriseCode}`);
+    window.open(
+      `${origin}${pathname}#/er/${project.id}?enterpriseCode=${enterpriseCode}`
+    );
   };
 
   // 修改表格字段
@@ -224,6 +241,15 @@ export default function index() {
       });
   };
 
+  // 修改表格字段
+  const handleChangeSelectTableColumn = (columns: readonly ColumnItem[]) => {
+    selectTableItem &&
+      updateTable({
+        ...selectTableItem,
+        tableColumnList: [...columns],
+      });
+  };
+
   // 同步数据表
   const handleSync = () => {
     syncModalRef.current?.open();
@@ -521,6 +547,26 @@ export default function index() {
             </div>
           </div>
         </Content>
+        <Modal
+          title="字段详情"
+          width={"80%"}
+          open={open}
+          footer={(_, { CancelBtn }) => {
+            return <CancelBtn />;
+          }}
+          onCancel={() => {
+            setOpen(false);
+            setSelectTableItem(undefined);
+          }}
+        >
+          <TableEdit
+            key={selectTableItem?.table.id}
+            tableId={selectTableItem?.table?.id}
+            data={selectTableItem?.tableColumnList || []}
+            modelId={project.id}
+            onChange={handleChangeSelectTableColumn}
+          />
+        </Modal>
         <AddTable ref={addTableRef} onChange={handleAddTable} />
       </Layout>
     </Spin>

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

@@ -10,7 +10,7 @@ import {
 } from "antd";
 import type { MenuProps } from "antd";
 import { useModel } from "umi";
-import { useFullscreen } from "ahooks";
+import { useFullscreen, useLocalStorageState } from "ahooks";
 import AddModel from "@/components/AddModel";
 import { TableType } from "@/enum";
 import { getClassRules } from "@repo/utils";
@@ -41,6 +41,14 @@ export default function Menu() {
   const addModelRef = useRef<{
     open: (type: TableType, folder: string) => void;
   }>();
+  // 隐藏默认字段
+  const [hideDefaultColumn, setHideDefaultColumn] = useLocalStorageState(
+    "er-hideDefaultColumn",
+    {
+      defaultValue: false,
+      listenStorageChange: true
+    }
+  );
 
   useEffect(() => {
     setName(project.name);
@@ -249,6 +257,21 @@ export default function Menu() {
             </span>
           ),
         },
+        {
+          key: "1-11",
+          label: (
+            <span className="flex items-center justify-between">
+              <span>隐藏默认字段</span>
+              <Switch
+                size="small"
+                checked={hideDefaultColumn}
+                onChange={(checked) =>
+                  setHideDefaultColumn(checked)
+                }
+              />
+            </span>
+          ),
+        },
         {
           key: "1-5",
           label: (

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

@@ -384,7 +384,7 @@ export default function All({
           }}
           trigger={["contextMenu"]}
         >
-          <div>
+          <div style={{minHeight: "calc(100vh - 78px)"}}>
             {display === "card" ? (
               <>
                 {folderData.length && !currentFolder ? (

+ 108 - 91
apps/er-designer/src/pages/home/ProjectCard.tsx

@@ -1,7 +1,12 @@
 import React, { useEffect, useState } from "react";
 import { Card, Dropdown, Modal, Input, message, Tooltip } from "antd";
-import defaultImg from "@/assets/image/default.png"
+import defaultImg from "@/assets/image/default.png";
 import { GetFile, DeleteDataModel, SaveDataModel } from "@/api";
+import {
+  EditOutlined,
+  FileTextOutlined,
+  EllipsisOutlined,
+} from "@ant-design/icons";
 
 export default function ProjectCard({
   record,
@@ -16,8 +21,7 @@ export default function ProjectCard({
   onChangeLocation: (id: string) => void;
   hideRemove?: boolean;
 }) {
-  const [showMenu, setShowMenu] = useState(false);
-  const handleToEdit = () => {
+  const handleToDetail = () => {
     const { origin, pathname } = window.location;
     const enterpriseCode = sessionStorage.getItem("enterpriseCode");
     window.open(
@@ -25,19 +29,101 @@ export default function ProjectCard({
     );
   };
 
+  const handleToEdit = () => {
+    const { origin, pathname } = window.location;
+    const enterpriseCode = sessionStorage.getItem("enterpriseCode");
+    window.open(
+      `${origin}${pathname}#/er/${record.id}?enterpriseCode=${enterpriseCode}`
+    );
+  };
+
   const { confirm } = Modal;
 
   const [coverImg, setCoverImg] = useState<string>("");
   useEffect(() => {
     if (record.coverImage) {
       GetFile({ fileId: record.coverImage }).then((res) => {
-       const blob = new Blob([res], { type: "image/png" });
-       const url = URL.createObjectURL(blob);
-       setCoverImg(url);
+        const blob = new Blob([res], { type: "image/png" });
+        const url = URL.createObjectURL(blob);
+        setCoverImg(url);
       });
     }
   }, []);
 
+  const actions: React.ReactNode[] = [
+    <EditOutlined key="edit" onClick={handleToEdit}/>,
+    <FileTextOutlined key="setting" onClick={handleToDetail}/>,
+    <Dropdown
+      key="more"
+      menu={{
+        items: [
+          {
+            key: "1",
+            label: "重命名",
+            onClick: () => {
+              let name = record.name;
+              confirm({
+                title: "重命名",
+                centered: true,
+                icon: <></>,
+                content: (
+                  <Input
+                    defaultValue={name}
+                    onChange={(e) => {
+                      name = e.target.value;
+                    }}
+                  />
+                ),
+                onOk: async () => {
+                  await SaveDataModel({
+                    ...record,
+                    name,
+                  });
+                  message.success("更新成功");
+                  onFresh();
+                },
+              });
+            },
+          },
+          !hideRemove
+            ? {
+                key: "2",
+                label: "移动",
+                onClick: () => {
+                  onChangeLocation?.(record.id);
+                },
+              }
+            : null,
+          {
+            key: "3",
+            label: "删除",
+            danger: true,
+            onClick: () => {
+              confirm({
+                title: "删除",
+                content: "确定删除该模型?",
+                centered: true,
+                onOk: async () => {
+                  await DeleteDataModel({
+                    id: record.id,
+                  });
+                  onDelete?.();
+                  message.success("删除成功");
+                },
+              });
+            },
+          },
+        ],
+        onClick: (e) => {
+          e.domEvent.stopPropagation();
+        },
+      }}
+      trigger={["click"]}
+    >
+      <EllipsisOutlined/>
+    </Dropdown>,
+  ];
+
   return (
     <Card
       hoverable
@@ -48,99 +134,30 @@ export default function ProjectCard({
             objectFit: "cover",
             border: "solid 1px #f5f5f5",
           }}
-          src={
-            coverImg || defaultImg
-          }
+          src={coverImg || defaultImg}
+          onClick={handleToDetail}
         />
       }
-      onClick={() => handleToEdit()}
-      onMouseOver={() => setShowMenu(true)}
-      onMouseOut={() => setShowMenu(false)}
+      actions={actions}
     >
-      {showMenu && (
-        <Dropdown
-          menu={{
-            items: [
-              {
-                key: "1",
-                label: "重命名",
-                onClick: () => {
-                  let name = record.name;
-                  confirm({
-                    title: "重命名",
-                    centered: true,
-                    icon: <></>,
-                    content: (
-                      <Input
-                        defaultValue={name}
-                        onChange={(e) => {
-                          name = e.target.value;
-                        }}
-                      />
-                    ),
-                    onOk: async () => {
-                      await SaveDataModel({
-                        ...record,
-                        name
-                      });
-                      message.success('更新成功');
-                      onFresh();
-                    },
-                  });
-                },
-              },
-              !hideRemove
-                ? {
-                    key: "2",
-                    label: "移动",
-                    onClick: () => {
-                      onChangeLocation?.(record.id);
-                    },
-                  }
-                : null,
-              {
-                key: "3",
-                label: "删除",
-                danger: true,
-                onClick: () => {
-                  confirm({
-                    title: "删除",
-                    content: "确定删除该模型?",
-                    centered: true,
-                    onOk: async () => {
-                      await DeleteDataModel({
-                        id: record.id,
-                      });
-                      onDelete?.();
-                      message.success("删除成功");
-                    },
-                  });
-                },
-              },
-            ],
-            onClick: (e) => {
-              e.domEvent.stopPropagation();
-            },
-          }}
-        >
-          <div
-            className="absolute right-8px top-8px cursor-pointer bg-#adadad99 px-12px rounded-4px text-12px line-height-16px color-#fff"
-            onClick={(e) => {
-              e.stopPropagation();
-            }}
-          >
-            <i className="iconfont icon-a-zu10687" />
-          </div>
-        </Dropdown>
-      )}
       <Card.Meta
         title={
           <span className="flex items-center justify-between">
-            <Tooltip title={record.name}><span className="flex-1 truncate ">{record.name}</span></Tooltip>
-            <span className="text-12px font-normal color-#999">更新:{record.updateTime}</span>
+            <Tooltip title={record.name}>
+              <span className="flex-1 truncate ">{record.name}</span>
+            </Tooltip>
+            <span className="text-12px font-normal color-#999">
+              更新:{record.updateTime}
+            </span>
+          </span>
+        }
+        description={
+          <span className="block truncate">
+            <Tooltip title={record.description}>
+              {record.description || "暂无描述"}
+            </Tooltip>
           </span>
         }
-        description={<span className="block truncate"><Tooltip title={record.description}>{record.description || '暂无描述'}</Tooltip></span>}
       />
     </Card>
   );