RelationPanel.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import { SearchOutlined, SwapOutlined } from "@ant-design/icons";
  2. import { Button, Descriptions, Form, Input, Popconfirm, Popover, Select } from "antd";
  3. import React from "react";
  4. import { RELATION_TYPE_OPTIONS } from "@/constants";
  5. import { useModel } from "umi";
  6. import noData from "@/assets/no-data.png";
  7. import { ColumnRelation } from "@/type";
  8. export default function RelationPanel() {
  9. const { project, addRelation, updateRelation, deleteRelation } =
  10. useModel("erModel");
  11. const [search, setSearch] = React.useState("");
  12. const list = React.useMemo(() => {
  13. return project.relations.filter((item) => item.name.includes(search));
  14. }, [search, project.relations]);
  15. const [active, setActive] = React.useState("");
  16. const handleChange = (index: number, key: string, value: any) => {
  17. const data = project.relations[index];
  18. updateRelation({
  19. ...data,
  20. [key]: value,
  21. });
  22. };
  23. const handleSwitchChange = (record: ColumnRelation) => {
  24. updateRelation({
  25. ...record,
  26. primaryTable: record.foreignTable,
  27. primaryKey: record.foreignKey,
  28. foreignTable: record.primaryTable,
  29. foreignKey: record.primaryKey,
  30. })
  31. }
  32. const getPrimaryColumn = (item: ColumnRelation) => {
  33. const tableItem = project.tables.find((table) => table.table.id === item.primaryTable);
  34. return {
  35. table: tableItem?.table,
  36. column: tableItem?.tableColumnList.find((column) => column.id === item.primaryKey)
  37. }
  38. };
  39. const getForeignColumn = (item: ColumnRelation) => {
  40. const tableItem = project.tables
  41. .find((table) => table.table.id === item.foreignTable);
  42. return {
  43. table: tableItem?.table,
  44. column: tableItem?.tableColumnList.find((column) => column.id === item.foreignKey)
  45. }
  46. };
  47. return (
  48. <div className="px-12px">
  49. <Input
  50. placeholder="输入关键字搜索"
  51. className="m-b-10px"
  52. suffix={<SearchOutlined />}
  53. value={search}
  54. onChange={(e) => setSearch(e.target.value)}
  55. />
  56. {list.map((item, index) => {
  57. return (
  58. <div
  59. className="
  60. border-b-solid
  61. border-b-[#e4e4e4]
  62. border-b-[1px]"
  63. key={item.id}
  64. >
  65. <div
  66. className="
  67. header
  68. flex
  69. items-center
  70. justify-between
  71. leading-[40px]
  72. hover:bg-[#fafafa]
  73. cursor-pointer
  74. m-b-[10px]"
  75. onClick={() => setActive(active === item.id ? '' : item.id)}
  76. >
  77. <div className="font-bold">{item.name}</div>
  78. <div>
  79. <i className="iconfont icon-open m-r-10px" />
  80. </div>
  81. </div>
  82. <div
  83. className="content overflow-hidden"
  84. style={{ height: active === item.id ? "auto" : 0 }}
  85. >
  86. <Form layout="vertical">
  87. <div className="flex justify-between">
  88. <Form.Item label="主键">
  89. {getPrimaryColumn(item)?.table?.schemaName}
  90. </Form.Item>
  91. <Form.Item label="外键">
  92. {getForeignColumn(item)?.table?.schemaName}
  93. </Form.Item>
  94. <Popover
  95. trigger="click"
  96. placement="right"
  97. content={<div className="min-w-200px">
  98. <Descriptions layout="vertical" bordered items={[
  99. {
  100. key: '1',
  101. label: '主键',
  102. children: <span>{getPrimaryColumn(item)?.table?.schemaName}({getPrimaryColumn(item)?.column?.schemaName})</span>
  103. },
  104. {
  105. key: '2',
  106. label: '外键',
  107. children: <span>{getForeignColumn(item)?.table?.schemaName}({getForeignColumn(item)?.column?.schemaName})</span>
  108. }
  109. ]}/>
  110. <Button className="w-full m-y-4px" icon={<SwapOutlined/>} type="primary" onClick={() => handleSwitchChange(item)}>交换</Button>
  111. </div>}
  112. >
  113. <div className="rounded-4px cus-btn w-32px h-32px bg-#eee flex-none text-center leading-32px cursor-pointer hover:bg-#ddd">
  114. <i className="iconfont icon-gengduo" />
  115. </div>
  116. </Popover>
  117. </div>
  118. <Form.Item label="对应关系" layout="vertical">
  119. <Select
  120. placeholder="请选择对应关系"
  121. className="w-full"
  122. options={RELATION_TYPE_OPTIONS}
  123. value={item.relationType}
  124. onChange={(val) => handleChange(index, "relationType", val)}
  125. ></Select>
  126. </Form.Item>
  127. <div>
  128. <Popconfirm
  129. okType="default"
  130. title="确定删除该关系?"
  131. okText="确定"
  132. cancelText="取消"
  133. onConfirm={() => deleteRelation(item.id)}
  134. >
  135. <Button color="danger" danger className="m-y-10px w-full">
  136. 删除
  137. </Button>
  138. </Popconfirm>
  139. </div>
  140. </Form>
  141. </div>
  142. </div>
  143. );
  144. })}
  145. {list.length === 0 && (
  146. <div className="flex flex-col items-center justify-center h-[300px]">
  147. <img src={noData} alt="暂无数据" className="w-[200px] h-[200px]" />
  148. <div className="text-gray-400">添加额外注释内容!</div>
  149. </div>
  150. )}
  151. </div>
  152. );
  153. }