DiffTable.tsx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. import type { TableItemType, ColumnItem } from "@/type";
  2. import React, { useEffect, useState } from "react";
  3. import {
  4. ProDescriptions,
  5. ProDescriptionsProps,
  6. } from "@ant-design/pro-components";
  7. import LangInput from "@/components/LangInput";
  8. import LangInputTextarea from "@/components/LangInputTextarea";
  9. import { Button, Table, Tooltip, TableProps, Spin } from "antd";
  10. import { validateAliasName, validateTableCode } from "@/utils/validator";
  11. import { GetBusinessTablesByTableId, GetAllBusinessTableColumns, ListLangByKey } from "@/api";
  12. import { useRequest } from "umi";
  13. import { DoubleLeftOutlined } from "@ant-design/icons";
  14. import { createColumn } from "@/utils";
  15. import { pick } from "lodash-es";
  16. const baseColumns: TableProps["columns"] = [
  17. {
  18. title: "字段代码",
  19. dataIndex: "schemaName",
  20. },
  21. {
  22. title: "字段名称",
  23. dataIndex: "name",
  24. render: (_dom, entity) => {
  25. return entity.langNameList
  26. ? entity.langNameList.find(
  27. (item: Record<string, string>) => item.name === "zh-CN"
  28. )?.value || "-"
  29. : entity.name;
  30. },
  31. },
  32. {
  33. title: "类型",
  34. dataIndex: "type",
  35. },
  36. {
  37. title: "长度",
  38. dataIndex: "maxLength",
  39. },
  40. {
  41. title: "必填",
  42. dataIndex: "isRequired",
  43. },
  44. {
  45. title: "唯一",
  46. dataIndex: "isUnique",
  47. },
  48. {
  49. title: "默认值",
  50. dataIndex: "defaultValue",
  51. },
  52. {
  53. title: "字符集",
  54. dataIndex: "chartset",
  55. },
  56. {
  57. title: "内容",
  58. dataIndex: "whereInputContent",
  59. },
  60. {
  61. title: "描述",
  62. dataIndex: "memo",
  63. },
  64. ];
  65. // 表详情组件
  66. const DescComp = function ({
  67. detail,
  68. editable,
  69. title,
  70. }: {
  71. detail: TableItemType["table"];
  72. editable?: ProDescriptionsProps["editable"];
  73. title?: string;
  74. }) {
  75. return (
  76. <ProDescriptions
  77. title={title}
  78. dataSource={detail}
  79. editable={editable}
  80. columns={[
  81. {
  82. label: "类型",
  83. dataIndex: "type",
  84. valueType: "select",
  85. valueEnum: {
  86. 3: "业务表",
  87. 2: "流程表",
  88. },
  89. editable: false,
  90. },
  91. {
  92. label: "编码",
  93. dataIndex: "schemaName",
  94. valueType: "text",
  95. formItemProps: {
  96. rules: [
  97. { required: true, message: "请输入编码" },
  98. validateTableCode,
  99. ],
  100. },
  101. },
  102. {
  103. label: "别名",
  104. dataIndex: "aliasName",
  105. valueType: "text",
  106. formItemProps: {
  107. rules: [
  108. { required: true, message: "请输入别名" },
  109. validateAliasName,
  110. ],
  111. },
  112. },
  113. {
  114. label: "名称",
  115. dataIndex: "langNameList",
  116. render: (_, record) => {
  117. return (
  118. record.langNameList?.find((item: any) => item.name === "zh-CN")
  119. ?.value || "-"
  120. );
  121. },
  122. renderFormItem: (_schema, config, form) => {
  123. return (
  124. <LangInput
  125. style={{ width: 200 }}
  126. onChange={(val) => form.setFieldValue("langNameList", val)}
  127. />
  128. );
  129. },
  130. },
  131. {
  132. label: "描述",
  133. dataIndex: "langDescriptionList",
  134. render: (_, record) => {
  135. return (
  136. record?.langDescriptionList?.find(
  137. (item: any) => item.name === "zh-CN"
  138. )?.value || "-"
  139. );
  140. },
  141. renderFormItem: (_schema, config, form) => {
  142. return (
  143. <>
  144. <LangInputTextarea
  145. value={form.getFieldValue("langDescriptionList")}
  146. onChange={(val) =>
  147. form.setFieldValue("langDescriptionList", val)
  148. }
  149. />
  150. </>
  151. );
  152. },
  153. },
  154. ]}
  155. ></ProDescriptions>
  156. );
  157. };
  158. export default function DiffTable({
  159. sourceTable,
  160. targetTableId,
  161. onChange
  162. }: {
  163. sourceTable: TableItemType;
  164. targetTableId?: string;
  165. onChange: (tableItem: TableItemType) => void;
  166. }) {
  167. const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
  168. const [selectedRows, setSelectedRows] = useState<any[]>([]);
  169. const {
  170. data: tableDetailRes,
  171. run: run1,
  172. loading: loading1,
  173. } = useRequest(GetBusinessTablesByTableId, { manual: true });
  174. const {
  175. data: tableColumnRes,
  176. run: run2,
  177. loading: loading2,
  178. } = useRequest(GetAllBusinessTableColumns, { manual: true });
  179. useEffect(() => {
  180. if (targetTableId) {
  181. run1(targetTableId);
  182. run2({
  183. currentPage: 1,
  184. pageSize: 2000,
  185. orderByProperty: "isPreDefined DESC, DisplayOrder",
  186. Ascending: true,
  187. totalPage: 1,
  188. totalCount: 1,
  189. filters: [
  190. {
  191. name: "BusinessTableId",
  192. value: targetTableId,
  193. },
  194. ],
  195. });
  196. }
  197. }, []);
  198. // 右侧选中数据覆盖左侧数据
  199. const handleCoverTable = async () => {
  200. if(!selectedRows.length) return;
  201. const arr = [...sourceTable.tableColumnList];
  202. // 获取全部多语言数据
  203. const langList = await Promise.all(
  204. [...new Set(selectedRows.map(item => item.langName))].map((key) =>
  205. ListLangByKey({ key }).then((res) => res.result)
  206. )
  207. );
  208. // 1、存在的数据进行更新
  209. // 2、不存在的数据进行新增
  210. selectedRows.forEach((item) => {
  211. const index = arr.findIndex(
  212. (item2: any) => item2.schemaName === item.schemaName
  213. );
  214. const newColumn = createColumn(sourceTable.table.id);
  215. const langName = langList.find((lang) => lang.key === item.langName);
  216. const column = {
  217. ...newColumn,
  218. ...pick(item, Object.keys(newColumn)),
  219. langNameList: [
  220. { name: "zh-CN", value: langName?.["zh-CN"] || "" },
  221. { name: "en", value: langName?.["en"] || "" },
  222. ],
  223. };
  224. if (index !== -1) {
  225. arr[index] = column;
  226. } else {
  227. arr.push(column);
  228. }
  229. });
  230. onChange({
  231. ...sourceTable,
  232. tableColumnList: arr,
  233. });
  234. setSelectedKeys([]);
  235. setSelectedRows([]);
  236. };
  237. return (
  238. <Spin spinning={loading1 || loading2}>
  239. <div className="flex">
  240. <div className="left rounded-8px border border-1px border-solid border-#979797 overflow-hidden">
  241. <div className="h-120px p-y-10px p-l-20px">
  242. <DescComp
  243. title="当前模型"
  244. detail={sourceTable.table}
  245. editable={{
  246. onSave: async (keypath, newInfo, oriInfo) => {
  247. onChange({
  248. ...sourceTable,
  249. table: {
  250. ...sourceTable.table,
  251. ...newInfo
  252. }
  253. });
  254. return true;
  255. },
  256. }}
  257. />
  258. </div>
  259. <Table
  260. pagination={false}
  261. columns={baseColumns}
  262. rowKey={'id'}
  263. dataSource={sourceTable.tableColumnList || []}
  264. />
  265. </div>
  266. <div className="middle w-100px flex-shrink-0">
  267. <Tooltip title="使用右侧数据">
  268. <Button
  269. className="block m-x-auto m-y-0 m-t-140px"
  270. icon={<DoubleLeftOutlined />}
  271. disabled={!selectedKeys.length}
  272. onClick={handleCoverTable}
  273. />
  274. </Tooltip>
  275. </div>
  276. <div className="right rounded-8px border border-1px border-solid border-#979797 overflow-hidden">
  277. <div className="h-120px p-y-10px p-l-20px">
  278. <DescComp
  279. title="数据表"
  280. detail={tableDetailRes?.result?.[0] || {}}
  281. />
  282. </div>
  283. <Table
  284. pagination={false}
  285. rowKey={'id'}
  286. columns={baseColumns}
  287. dataSource={tableColumnRes?.result?.model || []}
  288. rowSelection={{
  289. type: "checkbox",
  290. selectedRowKeys: selectedKeys,
  291. onChange: (keys, selectedRows) => {
  292. setSelectedKeys(keys);
  293. setSelectedRows(selectedRows);
  294. },
  295. }}
  296. />
  297. </div>
  298. </div>
  299. </Spin>
  300. );
  301. }