|
@@ -0,0 +1,311 @@
|
|
|
|
+import type { TableItemType, ColumnItem } from "@/type";
|
|
|
|
+import React, { useEffect, useState } from "react";
|
|
|
|
+import {
|
|
|
|
+ ProDescriptions,
|
|
|
|
+ ProDescriptionsProps,
|
|
|
|
+} from "@ant-design/pro-components";
|
|
|
|
+import LangInput from "@/components/LangInput";
|
|
|
|
+import LangInputTextarea from "@/components/LangInputTextarea";
|
|
|
|
+import { Button, Table, Tooltip, TableProps, Spin } from "antd";
|
|
|
|
+import { validateAliasName, validateTableCode } from "@/utils/validator";
|
|
|
|
+import { GetBusinessTablesByTableId, GetAllBusinessTableColumns, ListLangByKey } from "@/api";
|
|
|
|
+import { useRequest } from "umi";
|
|
|
|
+import { DoubleLeftOutlined } from "@ant-design/icons";
|
|
|
|
+import { createColumn } from "@/utils";
|
|
|
|
+import { pick } from "lodash-es";
|
|
|
|
+
|
|
|
|
+const baseColumns: TableProps["columns"] = [
|
|
|
|
+ {
|
|
|
|
+ title: "字段代码",
|
|
|
|
+ dataIndex: "schemaName",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "字段名称",
|
|
|
|
+ dataIndex: "name",
|
|
|
|
+ render: (_dom, entity) => {
|
|
|
|
+ return entity.langNameList
|
|
|
|
+ ? entity.langNameList.find(
|
|
|
|
+ (item: Record<string, string>) => item.name === "zh-CN"
|
|
|
|
+ )?.value || "-"
|
|
|
|
+ : entity.name;
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "类型",
|
|
|
|
+ dataIndex: "type",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "长度",
|
|
|
|
+ dataIndex: "maxLength",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "必填",
|
|
|
|
+ dataIndex: "isRequired",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "唯一",
|
|
|
|
+ dataIndex: "isUnique",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "默认值",
|
|
|
|
+ dataIndex: "defaultValue",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "字符集",
|
|
|
|
+ dataIndex: "chartset",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "内容",
|
|
|
|
+ dataIndex: "whereInputContent",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: "描述",
|
|
|
|
+ dataIndex: "memo",
|
|
|
|
+ },
|
|
|
|
+];
|
|
|
|
+
|
|
|
|
+// 表详情组件
|
|
|
|
+const DescComp = function ({
|
|
|
|
+ detail,
|
|
|
|
+ editable,
|
|
|
|
+ title,
|
|
|
|
+}: {
|
|
|
|
+ detail: TableItemType["table"];
|
|
|
|
+ editable?: ProDescriptionsProps["editable"];
|
|
|
|
+ title?: string;
|
|
|
|
+}) {
|
|
|
|
+ return (
|
|
|
|
+ <ProDescriptions
|
|
|
|
+ title={title}
|
|
|
|
+ dataSource={detail}
|
|
|
|
+ editable={editable}
|
|
|
|
+ columns={[
|
|
|
|
+ {
|
|
|
|
+ label: "类型",
|
|
|
|
+ dataIndex: "type",
|
|
|
|
+ valueType: "select",
|
|
|
|
+ valueEnum: {
|
|
|
|
+ 3: "业务表",
|
|
|
|
+ 2: "流程表",
|
|
|
|
+ },
|
|
|
|
+ editable: false,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: "编码",
|
|
|
|
+ dataIndex: "schemaName",
|
|
|
|
+ valueType: "text",
|
|
|
|
+ formItemProps: {
|
|
|
|
+ rules: [
|
|
|
|
+ { required: true, message: "请输入编码" },
|
|
|
|
+ validateTableCode,
|
|
|
|
+ ],
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: "别名",
|
|
|
|
+ dataIndex: "aliasName",
|
|
|
|
+ valueType: "text",
|
|
|
|
+ formItemProps: {
|
|
|
|
+ rules: [
|
|
|
|
+ { required: true, message: "请输入别名" },
|
|
|
|
+ validateAliasName,
|
|
|
|
+ ],
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: "名称",
|
|
|
|
+ dataIndex: "langNameList",
|
|
|
|
+ render: (_, record) => {
|
|
|
|
+ return (
|
|
|
|
+ record.langNameList?.find((item: any) => item.name === "zh-CN")
|
|
|
|
+ ?.value || "-"
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ renderFormItem: (_schema, config, form) => {
|
|
|
|
+ return (
|
|
|
|
+ <LangInput
|
|
|
|
+ style={{ width: 200 }}
|
|
|
|
+ onChange={(val) => form.setFieldValue("langNameList", val)}
|
|
|
|
+ />
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: "描述",
|
|
|
|
+ dataIndex: "langDescriptionList",
|
|
|
|
+ render: (_, record) => {
|
|
|
|
+ return (
|
|
|
|
+ record?.langDescriptionList?.find(
|
|
|
|
+ (item: any) => item.name === "zh-CN"
|
|
|
|
+ )?.value || "-"
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ renderFormItem: (_schema, config, form) => {
|
|
|
|
+ return (
|
|
|
|
+ <>
|
|
|
|
+ <LangInputTextarea
|
|
|
|
+ value={form.getFieldValue("langDescriptionList")}
|
|
|
|
+ onChange={(val) =>
|
|
|
|
+ form.setFieldValue("langDescriptionList", val)
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </>
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ ]}
|
|
|
|
+ ></ProDescriptions>
|
|
|
|
+ );
|
|
|
|
+};
|
|
|
|
+export default function DiffTable({
|
|
|
|
+ sourceTable,
|
|
|
|
+ targetTableId,
|
|
|
|
+ onChange
|
|
|
|
+}: {
|
|
|
|
+ sourceTable: TableItemType;
|
|
|
|
+ targetTableId?: string;
|
|
|
|
+ onChange: (tableItem: TableItemType) => void;
|
|
|
|
+}) {
|
|
|
|
+ const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
|
|
|
|
+ const [selectedRows, setSelectedRows] = useState<any[]>([]);
|
|
|
|
+
|
|
|
|
+ const {
|
|
|
|
+ data: tableDetailRes,
|
|
|
|
+ run: run1,
|
|
|
|
+ loading: loading1,
|
|
|
|
+ } = useRequest(GetBusinessTablesByTableId, { manual: true });
|
|
|
|
+
|
|
|
|
+ const {
|
|
|
|
+ data: tableColumnRes,
|
|
|
|
+ run: run2,
|
|
|
|
+ loading: loading2,
|
|
|
|
+ } = useRequest(GetAllBusinessTableColumns, { manual: true });
|
|
|
|
+
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ if (targetTableId) {
|
|
|
|
+ run1(targetTableId);
|
|
|
|
+ run2({
|
|
|
|
+ currentPage: 1,
|
|
|
|
+ pageSize: 2000,
|
|
|
|
+ orderByProperty: "isPreDefined DESC, DisplayOrder",
|
|
|
|
+ Ascending: true,
|
|
|
|
+ totalPage: 1,
|
|
|
|
+ totalCount: 1,
|
|
|
|
+ filters: [
|
|
|
|
+ {
|
|
|
|
+ name: "BusinessTableId",
|
|
|
|
+ value: targetTableId,
|
|
|
|
+ },
|
|
|
|
+ ],
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }, []);
|
|
|
|
+
|
|
|
|
+ // 右侧选中数据覆盖左侧数据
|
|
|
|
+ const handleCoverTable = async () => {
|
|
|
|
+ if(!selectedRows.length) return;
|
|
|
|
+ const arr = [...sourceTable.tableColumnList];
|
|
|
|
+
|
|
|
|
+ // 获取全部多语言数据
|
|
|
|
+ const langList = await Promise.all(
|
|
|
|
+ [...new Set(selectedRows.map(item => item.langName))].map((key) =>
|
|
|
|
+ ListLangByKey({ key }).then((res) => res.result)
|
|
|
|
+ )
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ // 1、存在的数据进行更新
|
|
|
|
+ // 2、不存在的数据进行新增
|
|
|
|
+ selectedRows.forEach((item) => {
|
|
|
|
+ const index = arr.findIndex(
|
|
|
|
+ (item2: any) => item2.schemaName === item.schemaName
|
|
|
|
+ );
|
|
|
|
+ const newColumn = createColumn(sourceTable.table.id);
|
|
|
|
+ const langName = langList.find((lang) => lang.key === item.langName);
|
|
|
|
+
|
|
|
|
+ const column = {
|
|
|
|
+ ...newColumn,
|
|
|
|
+ ...pick(item, Object.keys(newColumn)),
|
|
|
|
+ langNameList: [
|
|
|
|
+ { name: "zh-CN", value: langName?.["zh-CN"] || "" },
|
|
|
|
+ { name: "en", value: langName?.["en"] || "" },
|
|
|
|
+ ],
|
|
|
|
+ };
|
|
|
|
+ if (index !== -1) {
|
|
|
|
+ arr[index] = column;
|
|
|
|
+ } else {
|
|
|
|
+ arr.push(column);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ onChange({
|
|
|
|
+ ...sourceTable,
|
|
|
|
+ tableColumnList: arr,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ setSelectedKeys([]);
|
|
|
|
+ setSelectedRows([]);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ return (
|
|
|
|
+ <Spin spinning={loading1 || loading2}>
|
|
|
|
+ <div className="flex">
|
|
|
|
+ <div className="left rounded-8px border border-1px border-solid border-#979797 overflow-hidden">
|
|
|
|
+ <div className="h-120px p-y-10px p-l-20px">
|
|
|
|
+ <DescComp
|
|
|
|
+ title="当前模型表"
|
|
|
|
+ detail={sourceTable.table}
|
|
|
|
+ editable={{
|
|
|
|
+ onSave: async (keypath, newInfo, oriInfo) => {
|
|
|
|
+ onChange({
|
|
|
|
+ ...sourceTable,
|
|
|
|
+ table: {
|
|
|
|
+ ...sourceTable.table,
|
|
|
|
+ ...newInfo
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return true;
|
|
|
|
+ },
|
|
|
|
+ }}
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <Table
|
|
|
|
+ pagination={false}
|
|
|
|
+ columns={baseColumns}
|
|
|
|
+ dataSource={sourceTable.tableColumnList || []}
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div className="middle w-100px flex-shrink-0">
|
|
|
|
+ <Tooltip title="使用右侧数据">
|
|
|
|
+ <Button
|
|
|
|
+ className="block m-x-auto m-y-0 m-t-140px"
|
|
|
|
+ icon={<DoubleLeftOutlined />}
|
|
|
|
+ disabled={!selectedKeys.length}
|
|
|
|
+ onClick={handleCoverTable}
|
|
|
|
+ />
|
|
|
|
+ </Tooltip>
|
|
|
|
+ </div>
|
|
|
|
+ <div className="right rounded-8px border border-1px border-solid border-#979797 overflow-hidden">
|
|
|
|
+ <div className="h-120px p-y-10px p-l-20px">
|
|
|
|
+ <DescComp
|
|
|
|
+ title="远程数据表"
|
|
|
|
+ detail={tableDetailRes?.result?.[0] || {}}
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <Table
|
|
|
|
+ pagination={false}
|
|
|
|
+ columns={baseColumns}
|
|
|
|
+ dataSource={tableColumnRes?.result?.model || []}
|
|
|
|
+ rowSelection={{
|
|
|
|
+ type: "checkbox",
|
|
|
|
+ selectedRowKeys: selectedKeys,
|
|
|
|
+ onChange: (keys, selectedRows) => {
|
|
|
|
+ setSelectedKeys(keys);
|
|
|
|
+ setSelectedRows(selectedRows);
|
|
|
|
+ },
|
|
|
|
+ }}
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </Spin>
|
|
|
|
+ );
|
|
|
|
+}
|