123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- import React, { useEffect, useMemo, useRef } from "react";
- import { register } from "@antv/x6-react-shape";
- import { Edge, Graph, Node } from "@antv/x6";
- import type { ColumnItem, TableItemType } from "@/type";
- import { DATA_TYPE_OPTIONS } from "@/constants";
- import { uuid } from "@/utils";
- function TableNode({ node, graph }: { node: Node; graph: Graph }) {
- const { table, tableColumnList } = node.getData<TableItemType>();
- const containerRef = useRef<HTMLDivElement>(null);
- useEffect(() => {
- const container = containerRef.current;
- if (container?.clientHeight) {
- node.setSize(container.clientWidth, container.clientHeight);
- }
- }, [tableColumnList.length]);
- const hasListener = useRef(false);
- const relationSource = useRef<any>();
- useEffect(() => {
- if (!hasListener.current) {
- hasListener.current = true;
- // 参考线添加完成
- graph.on("edge:added", (args) => {
- if (args.edge.data?.type === "refer") {
- relationSource.current = args.edge.source;
- }
- });
- // 参考线移除
- graph.on("edge:removed", (args) => {
- if (args.edge.data?.type === "refer") {
- relationSource.current = undefined;
- }
- });
- graph.on("edge:connected", (args) => {
- // 连接完成后删除refer类型的连线
- if (args.edge.data?.type === "refer") {
- graph.removeEdge(args.edge);
- const target: any = args.edge.target;
- const source: any = args.edge.source;
- if (target?.cell === node.id && target?.port?.includes("port1")) {
- node.prop("add:relation", {
- source: {
- tableId: source?.cell,
- columnId: source?.port?.slice(
- 0,
- source?.port?.indexOf("_port")
- ),
- },
- target: {
- tableId: node.id,
- columnId: target.port.slice(0, target.port.indexOf("_port")),
- },
- });
- }
- }
- });
- }
- }, []);
- // 连接桩,1用于开始连接拖拽,2用于关系连线连接
- useEffect(() => {
- const ports = node.getPorts();
- ports?.forEach((item) => {
- if (!tableColumnList.find((column) => item.id?.includes(column.id))) {
- node.removePort(item);
- }
- });
- tableColumnList.forEach((item, index) => {
- if (!ports.find((port) => port.id?.includes(item.id))) {
- node.addPort({
- id: item.id + "_port1",
- group: "columnPort",
- args: {
- y: 42 + 16 + index * 27,
- },
- attrs: {
- circle: {
- r: 4,
- magnet: true,
- stroke: "#31d0c6",
- strokeWidth: 2,
- fill: "#fff",
- },
- },
- zIndex: 5,
- });
- node.addPort({
- id: item.id + "_port2",
- group: "columnPort",
- args: {
- x: 0,
- y: 42 + index * 27,
- },
- attrs: {
- rect: {
- magnet: true,
- fill: "rgba(255,255,255,0)",
- strokeWidth: 0,
- width: node.size().width,
- height: 27,
- },
- },
- zIndex: 0,
- });
- }
- });
- }, [tableColumnList]);
- // 触发添加关系操作
- // 字段位置鼠标抬起,判断有没有开始连线操作
- const handleColumnMouseUp = (record: ColumnItem) => {
- if (relationSource.current) {
- node.prop("add:relation", {
- source: {
- tableId: relationSource.current?.cell,
- columnId: relationSource.current?.port.slice(
- 0,
- relationSource.current.port.indexOf("_port")
- ),
- },
- target: {
- tableId: node.id,
- columnId: record.id,
- },
- });
- }
- };
- const ColumnItem = ({ record }: { record: ColumnItem }) => {
- const type = DATA_TYPE_OPTIONS.find((item) => item.value === record.type);
- return (
- <div
- className="w-full flex py-4px px-8px"
- onMouseUp={() => handleColumnMouseUp(record)}
- >
- <span className="flex-1 truncate flex items-center justify-between">
- <span className="flex items-center">
- <span className=" w-6px h-6px rounded-full mr-4px bg-#5684bb inline-block cursor-pointer" />
- {record.schemaName}
- {record.cn_name ? `(${record.cn_name})` : ""}
- </span>
- <span>
- {record.isUnique ? (
- <span className="m-r-4px">
- <i className="iconfont icon-key-fill color-#efc553 m-r--4px" />
- <span className="text-12px color-#f15359">P</span>
- <span className="text-12px color-#8dafd1">F</span>
- </span>
- ) : (
- <span>
- <i className="iconfont icon-24_beizhu color-#efc553 m-r-4px text-12px" />
- </span>
- )}
- <span>{type?.label}</span>
- </span>
- </span>
- </div>
- );
- };
- return (
- <div
- ref={containerRef}
- className="w-full border border-1px border-solid border-#333 flex flex-col overflow-hidden rounded-8px"
- >
- <div
- className="w-full h-10px bg-#eee"
- style={{ background: table.style?.color || "#eee" }}
- ></div>
- <div
- className="
- header
- border-b-solid
- border-b-1px
- border-b-#333
- truncate
- bg-#e4e4e7
- py-4px
- font-bold
- text-14px
- min-h-32px
- px-8px
- "
- >
- {table.schemaName}({table.cn_name})
- </div>
- <div className="bg-#fafafa flex-1">
- <div className="field-info">
- {tableColumnList.map((item) => {
- return <ColumnItem key={item.id} record={item} />;
- })}
- </div>
- </div>
- </div>
- );
- }
- register({
- shape: "table-node",
- component: TableNode,
- width: 300,
- height: 220,
- effect: ["data"],
- });
|