Bläddra i källkod

feat: 添加引入数据表功能

liaojiaxing 3 månader sedan
förälder
incheckning
d35ca60817

+ 13 - 4
apps/er-designer/src/api/index.ts

@@ -59,10 +59,19 @@ export const GetAllBusinessTableColumns = (data: commonParams) => {
  * @param data 
  * @returns 
  */
-export const GetAllDesignTables = (data: {
-  groupType: string
-}) => {
-  return request("/api/table/GetAllDesignTables", {
+export const GetAllDesignTables = () => {
+  return request("/api/table/GetAllTablesAndViews", {
+    method: "POST",
+  });
+};
+
+/**
+ * 获取表格详情
+ * @param data 
+ * @returns 
+ */
+export const GetBusinessTablesByTableId = (data: any) => {
+  return request("/api/table/GetBusinessTablesByTableId", {
     method: "POST",
     data
   });

+ 197 - 11
apps/er-designer/src/pages/detail/components/AddTable.tsx

@@ -1,12 +1,35 @@
-import { forwardRef, useImperativeHandle, useRef, useState } from "react";
-import { Col, Form, Input, Modal, Row, Select, Tabs, TabsProps } from "antd";
+import {
+  forwardRef,
+  useImperativeHandle,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import {
+  Col,
+  Form,
+  Input,
+  message,
+  Modal,
+  Row,
+  Select,
+  Tabs,
+  TabsProps,
+} from "antd";
 import LangInput from "@/components/LangInput";
 import LangInputTextarea from "@/components/LangInputTextarea";
 import { TableType } from "@/enum";
-import { createTable } from "@/utils";
+import { createColumn, createTable } from "@/utils";
 import { TableItemType } from "@/type";
-import { useModel } from "umi";
+import { useModel, useRequest } from "umi";
+import {
+  GetAllDesignTables,
+  GetAllBusinessTableColumns,
+  GetBusinessTablesByTableId,
+  ListLangByKey,
+} from "@/api";
 import { validateTableCode, validateAliasName } from "@/utils/validator";
+import { pick } from "lodash-es";
 
 export default forwardRef(function AddTable(
   props: {
@@ -18,6 +41,11 @@ export default forwardRef(function AddTable(
   const tableItemRef = useRef<TableItemType>();
   const { project } = useModel("erModel");
   const [tabActiveKey, setTabActiveKey] = useState("1");
+  const [form] = Form.useForm();
+  const [form1] = Form.useForm();
+  const [formModel, setFormModel] = useState<TableItemType["table"]>();
+  const [hideAddTab, setHideAddTab] = useState(false);
+
   useImperativeHandle(ref, () => ({
     open: () => {
       // 获取当前模型类型
@@ -25,13 +53,43 @@ export default forwardRef(function AddTable(
       setFormModel(tableItemRef.current.table);
       setOpen(true);
     },
+    openImportMode: () => {
+      setTabActiveKey("2");
+      run();
+      setHideAddTab(true);
+      setOpen(true);
+    },
     close: () => {
       setOpen(false);
     },
   }));
 
-  const [form] = Form.useForm();
-  const [formModel, setFormModel] = useState<TableItemType["table"]>();
+  const { data, loading, run } = useRequest(() => GetAllDesignTables(), {
+    manual: true,
+  });
+
+  const tableOptions = useMemo(() => {
+    const options =
+      data?.result?.appBusinessTables
+        ?.filter(
+          (item: any) =>
+            // 过滤当前数据表类型及存在相同schemaName、aliasName的表
+            item?.type == project?.type 
+            // && !project.tables.find(
+            //   (tableItem) =>
+            //     tableItem.table.schemaName === item.schemaName ||
+            //     tableItem.table.aliasName === item.aliasName
+            // )
+        )
+        ?.map((item: any) => {
+          return {
+            label: `${item?.schemaName}(${item.name})`,
+            value: item?.id,
+          };
+        }) || [];
+
+    return options;
+  }, [data]);
 
   const items: TabsProps["items"] = [
     {
@@ -124,9 +182,19 @@ export default forwardRef(function AddTable(
       label: `引入`,
       children: (
         <div>
-          <Form.Item label="选择主表">
-            <Select placeholder="请选择" />
-          </Form.Item>
+          <Form labelCol={{ span: 4 }} form={form1}>
+            <Form.Item
+              label="选择表"
+              name="table"
+              rules={[{ required: true, message: "请选择表" }]}
+            >
+              <Select
+                placeholder="请选择"
+                loading={loading}
+                options={tableOptions}
+              />
+            </Form.Item>
+          </Form>
         </div>
       ),
     },
@@ -139,6 +207,69 @@ export default forwardRef(function AddTable(
         [key]: value,
       });
   };
+
+  // 获取引入的表转换成模型表
+  const getNewTableByTable = async (
+    tableData: any,
+    columns: any[]
+  ): Promise<TableItemType> => {
+    const newTable = createTable(project.type, project.id);
+    const langKeyList: string[] = [];
+    if (tableData.langName) {
+      langKeyList.push(tableData.langName);
+    }
+    if (tableData.langDescription) {
+      langKeyList.push(tableData.langDescription);
+    }
+    columns.forEach((item) => {
+      if (item.langName) {
+        langKeyList.push(item.langName);
+      }
+    });
+    // 获取全部多语言数据
+    const langList = await Promise.all(
+      [...new Set(langKeyList)].map((key) =>
+        ListLangByKey({ key }).then((res) => res.result)
+      )
+    );
+
+    const langName = langList.find((item) => item.key === tableData.langName);
+    const descName = langList.find(
+      (item) => item.key === tableData.langDescription
+    );
+    return {
+      isTable: true,
+      // 表格数据
+      table: {
+        ...newTable.table,
+        ...pick(tableData, ["schemaName", "aliasName", "isDeleted"]),
+        langNameList: [
+          { name: "zh-CN", value: langName?.["zh-CN"] || "" },
+          { name: "en", value: langName?.["en"] || "" },
+        ],
+        langDescriptionList: [
+          { name: "zh-CN", value: descName?.["zh-CN"] || "" },
+          { name: "en", value: descName?.["en"] || "" },
+        ],
+      },
+      // 字段数据
+      tableColumnList: columns.map((item) => {
+        const column = createColumn(newTable.table.id);
+        const langName = langList.find((lang) => lang.key === item.langName);
+
+        return {
+          ...column,
+          ...pick(item, Object.keys(column)),
+          langNameList: [
+            { name: "zh-CN", value: langName?.["zh-CN"] || "" },
+            { name: "en", value: langName?.["en"] || "" },
+          ],
+        };
+      }),
+    };
+  };
+
+  const [loadingColumns, setLoadingColumns] = useState(false);
   const handleOk = () => {
     // 新建
     if (tabActiveKey === "1") {
@@ -149,22 +280,77 @@ export default forwardRef(function AddTable(
             table: formModel,
           });
         }
+        form.resetFields();
         setOpen(false);
       });
     }
     // 引入
+    if (tabActiveKey === "2") {
+      form1.validateFields().then(async () => {
+        // 加载表格字段
+        const values = form1.getFieldsValue();
+        try {
+          setLoadingColumns(true);
+          const resArr = await Promise.all([
+            GetBusinessTablesByTableId(values.table),
+            GetAllBusinessTableColumns({
+              currentPage: 1,
+              pageSize: 2000,
+              orderByProperty: "isPreDefined DESC, DisplayOrder",
+              Ascending: true,
+              totalPage: 1,
+              totalCount: 1,
+              filters: [
+                {
+                  name: "BusinessTableId",
+                  value: values.table,
+                },
+              ],
+            }),
+          ]);
+          if (resArr[0]?.result?.[0]) {
+            const tableItem = await getNewTableByTable(
+              resArr[0]?.result?.[0],
+              resArr[1]?.result?.model || []
+            );
+            props.onChange(tableItem);
+            console.log(tableItem);
+            form1.resetFields();
+            setOpen(false);
+          } else {
+            message.error("获取数据失败");
+          }
+        } finally {
+          setLoadingColumns(false);
+        }
+      });
+    }
+  };
+
+  const handleChangeTableActiveKey = (key: string) => {
+    setTabActiveKey(key);
+    if (key === "2") {
+      run();
+    }
   };
 
   return (
     <Modal
       open={open}
       title="添加表"
-      okText="确定"
+      okText={loadingColumns ? "加载中..." : "确定"}
       cancelText="取消"
       onCancel={() => setOpen(false)}
       onOk={handleOk}
+      okButtonProps={{
+        loading: loadingColumns,
+      }}
     >
-      <Tabs items={items} activeKey={tabActiveKey} onChange={setTabActiveKey} />
+      <Tabs
+        items={items.filter(item => hideAddTab ? item.key === '2' : true)}
+        activeKey={tabActiveKey}
+        onChange={handleChangeTableActiveKey}
+      />
     </Modal>
   );
 });

+ 51 - 10
apps/er-designer/src/pages/er/components/TablePanel.tsx

@@ -1,20 +1,34 @@
 import React, { useEffect, useState } from "react";
 import { Button, Modal, Input, Dropdown } from "antd";
-import { DownOutlined, ImportOutlined, PlusOutlined, SearchOutlined } from "@ant-design/icons";
+import {
+  DownOutlined,
+  ImportOutlined,
+  PlusOutlined,
+  SearchOutlined,
+} from "@ant-design/icons";
 import TableItem from "./TableItem";
 import { useModel } from "umi";
 import noData from "@/assets/no-data.png";
 import TableEdit from "@/components/TableEdit";
 import { ColumnItem, TableItemType } from "@/type";
+import AddTable from "@/pages/detail/components/AddTable";
 export default function TablePanel() {
-  const { project, updateTable, addTable, tableActive, setTableActive, graph } =
-    useModel("erModel");
+  const {
+    project,
+    setProject,
+    updateTable,
+    addTable,
+    tableActive,
+    setTableActive,
+    graph,
+  } = useModel("erModel");
   const contentRef = React.useRef<HTMLDivElement>(null);
   const [contentStyle, setContentStyle] = React.useState<React.CSSProperties>(
     {}
   );
   const [tableData, setTableData] = React.useState<TableItemType>();
   const [open, setOpen] = useState(false);
+  const addTableRef = React.useRef<{ openImportMode: () => void }>(null);
 
   useEffect(() => {
     graph?.on("node:dblclick", (args) => {
@@ -42,6 +56,15 @@ export default function TablePanel() {
     }
   };
 
+  // 引入表
+  const handleImport = (table: TableItemType) => {
+    setProject({
+      ...project,
+      tables: [...project.tables, table],
+    });
+    graph?.select(table.table.id);
+  };
+
   return (
     <div
       className="px-12px overflow-y-auto"
@@ -50,11 +73,28 @@ export default function TablePanel() {
     >
       <div className="search-box flex gap-4px mb-12px">
         <Input placeholder="输入关键字搜索" suffix={<SearchOutlined />} />
-        <Dropdown menu={{items: [
-          {key: 'add', label: '新建表', icon: <PlusOutlined />, onClick: () => addTable()},
-          {key: 'import', label: '导入表', icon: <ImportOutlined />}
-        ]}}>
-          <Button type="primary">添加表<DownOutlined/></Button>
+        <Dropdown
+          menu={{
+            items: [
+              {
+                key: "add",
+                label: "新建表",
+                icon: <PlusOutlined />,
+                onClick: () => addTable(),
+              },
+              {
+                key: "import",
+                label: "引入表",
+                icon: <ImportOutlined />,
+                onClick: () => addTableRef.current?.openImportMode(),
+              },
+            ],
+          }}
+        >
+          <Button type="primary">
+            添加表
+            <DownOutlined />
+          </Button>
         </Dropdown>
       </div>
       {project.tables.map((item) => {
@@ -78,8 +118,8 @@ export default function TablePanel() {
         title="字段详情"
         width={"80%"}
         open={open}
-        footer={(_, { CancelBtn}) => {
-          return <CancelBtn/>
+        footer={(_, { CancelBtn }) => {
+          return <CancelBtn />;
         }}
         onCancel={() => {
           setOpen(false);
@@ -93,6 +133,7 @@ export default function TablePanel() {
           onChange={handleChangeTableColumns}
         />
       </Modal>
+      <AddTable ref={addTableRef} onChange={handleImport} />
     </div>
   );
 }

+ 4 - 0
apps/er-designer/src/utils/index.ts

@@ -43,6 +43,10 @@ export const createTable = (tableType: TableType, dataModelId: string, parentId?
         { name: "zh-CN", value: "新建表" },
         { name: "en", value: "new table" },
       ],
+      langDescriptionList: [
+        { name: "zh-CN", value: "" },
+        { name: "en", value: "" },
+      ],
       style: {
         // 随机颜色
         color: "#" + Math.floor(Math.random() * 0x666666).toString(16),