TablePanel.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import React, { useEffect, useState } from "react";
  2. import { Button, Modal, Input, Dropdown } from "antd";
  3. import {
  4. DownOutlined,
  5. ImportOutlined,
  6. PlusOutlined,
  7. SearchOutlined,
  8. } from "@ant-design/icons";
  9. import TableItem from "./TableItem";
  10. import { useModel } from "umi";
  11. import noData from "@/assets/no-data.png";
  12. import TableEdit from "@/components/TableEdit";
  13. import { ColumnItem, TableItemType } from "@/type";
  14. import AddTable from "@/pages/detail/components/AddTable";
  15. export default function TablePanel() {
  16. const {
  17. project,
  18. setProject,
  19. updateTable,
  20. addTable,
  21. tableActive,
  22. setTableActive,
  23. graph,
  24. } = useModel("erModel");
  25. const contentRef = React.useRef<HTMLDivElement>(null);
  26. const [contentStyle, setContentStyle] = React.useState<React.CSSProperties>(
  27. {}
  28. );
  29. const [tableData, setTableData] = React.useState<TableItemType>();
  30. const [open, setOpen] = useState(false);
  31. const addTableRef = React.useRef<{ openImportMode: () => void }>(null);
  32. useEffect(() => {
  33. graph?.on("node:dblclick", (args) => {
  34. const data = args.node.getData();
  35. if (data?.isTable) {
  36. setOpen(true);
  37. setTableData(data);
  38. }
  39. });
  40. }, [graph]);
  41. useEffect(() => {
  42. // 计算高度
  43. setContentStyle({
  44. height: `calc(100vh - ${contentRef.current?.getBoundingClientRect().top}px)`,
  45. });
  46. }, []);
  47. const handleChangeTableColumns = (columnList: readonly ColumnItem[]) => {
  48. if (tableData) {
  49. updateTable({
  50. ...tableData,
  51. tableColumnList: columnList as ColumnItem[],
  52. });
  53. }
  54. };
  55. // 引入表
  56. const handleImport = (tables: TableItemType[]) => {
  57. setProject({
  58. ...project,
  59. tables: [...tables, ...project.tables],
  60. });
  61. setTableActive(tables[0].table.id);
  62. graph?.select(tables[0].table.id);
  63. };
  64. return (
  65. <div
  66. className="px-12px overflow-y-auto"
  67. ref={contentRef}
  68. style={contentStyle}
  69. >
  70. <div className="search-box flex gap-4px mb-12px">
  71. <Input placeholder="输入关键字搜索" suffix={<SearchOutlined />} />
  72. <Dropdown
  73. menu={{
  74. items: [
  75. {
  76. key: "add",
  77. label: "新建表",
  78. icon: <PlusOutlined />,
  79. onClick: () => addTable(),
  80. },
  81. {
  82. key: "import",
  83. label: "引入表",
  84. icon: <ImportOutlined />,
  85. onClick: () => addTableRef.current?.openImportMode(),
  86. },
  87. ],
  88. }}
  89. >
  90. <Button type="primary">
  91. 添加表
  92. <DownOutlined />
  93. </Button>
  94. </Dropdown>
  95. </div>
  96. {project.tables.map((item) => {
  97. return (
  98. <TableItem
  99. data={item}
  100. onChange={updateTable}
  101. key={item.table.id}
  102. active={tableActive}
  103. setActive={setTableActive}
  104. />
  105. );
  106. })}
  107. {project.tables.length === 0 && (
  108. <div className="flex flex-col items-center justify-center h-[300px]">
  109. <img src={noData} alt="暂无数据" className="w-[200px] h-[200px]" />
  110. <div className="text-gray-400">暂无数据表,快来创建!</div>
  111. </div>
  112. )}
  113. <Modal
  114. title="字段详情"
  115. width={"80%"}
  116. open={open}
  117. footer={(_, { CancelBtn }) => {
  118. return <CancelBtn />;
  119. }}
  120. onCancel={() => {
  121. setOpen(false);
  122. setTableData(undefined);
  123. }}
  124. >
  125. <TableEdit
  126. tableId={tableData?.table?.id}
  127. data={tableData?.tableColumnList || []}
  128. modelId={project.id}
  129. onChange={handleChangeTableColumns}
  130. />
  131. </Modal>
  132. <AddTable ref={addTableRef} onChange={handleImport} />
  133. </div>
  134. );
  135. }