import React, { useEffect, useMemo, useRef, useState } from "react"; import { Layout, Menu, Button, Descriptions, Input, Tooltip, Empty, Spin, Modal, } from "antd"; import { ProDescriptions } from "@ant-design/pro-components"; import type { DescriptionsProps, MenuProps } from "antd"; import { DownOutlined, PlusOutlined, SearchOutlined } from "@ant-design/icons"; import TableEdit from "@/components/TableEdit"; import ER from "./components/ER"; import AddTable from "@/components/AddTable"; import { useModel, useRequest, useParams } from "umi"; import { GetDataModelDetail } from "@/api"; import NoData from "@/assets/no-data.png"; import { ColumnItem, ProjectInfo, TableItemType } from "@/type"; import { useFullscreen, useLocalStorageState } from "ahooks"; import AddModel from "@/components/AddModel"; import insertCss from "insert-css"; import LangInput from "@/components/LangInput"; import LangInputTextarea from "@/components/LangInputTextarea"; import { validateAliasName, validateTableCode } from "@/utils/validator"; import SyncModal from "@/components/SyncModal"; import AICreator from "@/pages/er/components/AICreator"; const { Content, Header } = Layout; export default function index() { const [active, setActive] = useState(0); const [showNavigator, setShowNavigator] = useState(true); const addTableRef = useRef<{ open: () => void }>(); const { project, setProject, setPlayModeEnable, exitPlayMode, updateTable, graph, onCreateByAi } = useModel("erModel"); const [searchKeyword, setSearchKeyword] = useState(""); const [selectKey, setSelectKey] = useState( project.tables?.[0]?.table?.id || "" ); const erRef = useRef(null); const addModelRef = useRef<{ edit: (info: ProjectInfo) => void }>(); const syncModalRef = useRef<{ open: () => void }>(); const [isFullscreen, { enterFullscreen, exitFullscreen }] = useFullscreen(erRef); const [collapsed, setCollapsed] = useState(true); const [seachColumn, setSearchColumn] = useState(""); // 双击选中表数据 const [selectTableItem, setSelectTableItem] = React.useState(); const [open, setOpen] = useState(false); useEffect(() => { graph?.on("node:dblclick", (args) => { const data = args.node.getData(); if (data?.isTable) { setOpen(true); setSelectTableItem(data); } }); }, [graph]); useEffect(() => { insertCss(` .ant-descriptions-header { margin-bottom: ${collapsed ? "0 !important" : "20px !important"}; } `); }, [collapsed]); useEffect(() => { setPlayModeEnable(true); graph?.disableKeyboard(); }, [project, graph]); useEffect(() => { // 监听浏览器tab切换 刷新数据 const handleVisibilityChange = () => { if (document.visibilityState === "visible") { refresh(); } }; document.addEventListener("visibilitychange", handleVisibilityChange); return () => { document.removeEventListener("visibilitychange", handleVisibilityChange); }; }); const params = useParams(); const { run, loading, refresh } = useRequest(GetDataModelDetail, { manual: true, onSuccess: (res) => { console.log("模型详情:", res); const result = res?.result; setSelectKey(result?.tables?.[0]?.table?.id || ""); if (result) { setProject(result, false, true); } }, }); const [hideDefaultColumn, setHideDefaultColumn] = useLocalStorageState( "er-hideDefaultColumn", { defaultValue: false, listenStorageChange: true, } ); useEffect(() => { if (params?.id) { run({ id: params.id }); } }, []); const descItems: DescriptionsProps["items"] = useMemo(() => { return [ { key: "1", label: "模型名称", children: project?.name || "-", }, { key: "2", label: "创建用户", children: project?.createdByName || "-", }, { key: "3", label: "创建时间", children: project?.createTime || "-", }, // { // key: "5", // label: "发布状态", // children: project?.publishStatus || "-", // }, { key: "4-1", label: "更新用户", children: project?.updateByName || "-", }, { key: "4", label: "更新时间", children: project?.updateTime || "-", }, { key: "6", label: "表", children: `${project.tables.length}张`, }, { key: "7", label: "描述", children: project?.description || "-", }, ]; }, [project]); const tableData: MenuProps["items"] = useMemo(() => { const { tables } = project; const treeList: { key: string; label: string | React.ReactNode; icon: React.ReactNode; children?: MenuProps["items"]; }[] = []; tables .filter((item) => { const tableName = item.table.langNameList?.find( (item) => item.name === "zh-CN" )?.value; return ( item.table.schemaName.includes(searchKeyword) || tableName?.includes(searchKeyword) ); }) .forEach((item) => { const name = item.table.langNameList?.find( (item) => item.name === "zh-CN" )?.value; const newItem = { key: item.table.id, label: item.table.schemaName + `${name ? `(${name})` : ""}`, icon: , }; if (!item.table.parentBusinessTableId) { treeList.push(newItem); } else { const parent = treeList.find( (tableItem) => tableItem?.key === item.table.parentBusinessTableId ); if (parent) { if (!parent?.children) { parent.children = []; } parent.children?.push(newItem); } } }); return treeList; }, [project, searchKeyword]); const currentTable = useMemo(() => { return project.tables.find((item) => item.table.id === selectKey); }, [project, selectKey]); const currentColumns = useMemo(() => { return (currentTable?.tableColumnList || []).filter((item) => { if (seachColumn) { return item.langName?.includes(seachColumn); } return true; }); }, [currentTable, seachColumn]); // 处理添加表 const handleAddTable = (tables: TableItemType[]) => { setProject({ ...project, tables: [...tables, ...project.tables], }); setSelectKey(tables[0].table.id); graph?.select(tables[0].table.id); }; const handleEnterFullscreen = () => { enterFullscreen(); }; const handleExitFullscreen = () => { exitFullscreen(); }; const handleSelectTable = (key: string) => { graph?.resetSelection(key); graph?.centerCell(graph.getCellById(key)); setSelectKey(key); }; const handleEnterEdit = () => { const { origin, pathname } = window.location; const enterpriseCode = sessionStorage.getItem("enterpriseCode"); window.open( `${origin}${pathname}#/er/${project.id}?enterpriseCode=${enterpriseCode}` ); }; // 修改表格字段 const handleChangeColumn = (columns: readonly ColumnItem[]) => { currentTable && updateTable({ ...currentTable, tableColumnList: [...columns], }); }; // 修改表格字段 const handleChangeSelectTableColumn = (columns: readonly ColumnItem[]) => { selectTableItem && updateTable({ ...selectTableItem, tableColumnList: [...columns], }); }; // 同步数据表 const handleSync = () => { syncModalRef.current?.open(); }; const extra = (
数据表同步 project.id && addModelRef.current?.edit(project)}> 基础信息 模型编辑 保存为模板
); const handleAiCreate = async (data: any) => { await onCreateByAi(data); refresh(); } return ( {/* 基础信息修改弹窗 */} { typeof info === "object" && setProject(info); }} /> {/* 同步弹窗 */}
{project?.name || "-"}
数据表
} value={searchKeyword} onChange={(e) => setSearchKeyword(e.target.value)} />
handleSelectTable(key)} /> {!tableData.length && ( )}
{active === 0 ? ( <> {/* } /> */} ) : ( <> } value={seachColumn} onChange={(e) => setSearchColumn(e.target.value)} /> )}
{active === 0 ? (
) : (
{ currentTable && updateTable({ ...currentTable, table: { ...currentTable?.table, ...newInfo, langName: "", langDescription: "", }, }); return true; }, }} 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) => item.name === "zh-CN" )?.value || "-" ); }, renderFormItem: (_schema, config, form) => { return ( form.setFieldValue("langNameList", val) } /> ); }, }, { label: "描述", dataIndex: "langDescriptionList", render: (_, record) => { return ( record?.langDescriptionList?.find( (item) => item.name === "zh-CN" )?.value || "-" ); }, renderFormItem: (_schema, config, form) => { return ( <> form.setFieldValue( "langDescriptionList", val ) } /> ); }, }, ]} >
)}
{ return ; }} onCancel={() => { setOpen(false); setSelectTableItem(undefined); }} >
); }