king
2023-06-04 761eedb359fb5489fe54b60ef4875b8c1a9aa738
src/menu/components/chart/antv-X6/index.jsx
@@ -1,8 +1,8 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover } from 'antd'
import { ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import { Popover, Tooltip } from 'antd'
import { ToolOutlined, DeleteOutlined, FontColorsOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined } from '@ant-design/icons'
import { Graph, Shape } from '@antv/x6'
import { Stencil } from '@antv/x6-plugin-stencil'
import { Transform } from '@antv/x6-plugin-transform'
@@ -22,6 +22,222 @@
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
// #region 初始化图形
const groups = {
  top: {
    position: 'top',
    attrs: {
      circle: {
        r: 4,
        magnet: true,
        stroke: 'var(--mk-sys-color)',
        strokeWidth: 1,
        fill: '#fff',
        style: {
          visibility: 'hidden'
        }
      }
    }
  },
  right: {
    position: 'right',
    attrs: {
      circle: {
        r: 4,
        magnet: true,
        stroke: 'var(--mk-sys-color)',
        strokeWidth: 1,
        fill: '#fff',
        style: {
          visibility: 'hidden'
        }
      }
    }
  },
  bottom: {
    position: 'bottom',
    attrs: {
      circle: {
        r: 4,
        magnet: true,
        stroke: 'var(--mk-sys-color)',
        strokeWidth: 1,
        fill: '#fff',
        style: {
          visibility: 'hidden'
        }
      }
    }
  },
  left: {
    position: 'left',
    attrs: {
      circle: {
        r: 4,
        magnet: true,
        stroke: 'var(--mk-sys-color)',
        strokeWidth: 1,
        fill: '#fff',
        style: {
          visibility: 'hidden'
        }
      }
    }
  }
}
Graph.registerNode(
  'mk-rect',
  {
    inherit: 'rect',
    width: 66,
    height: 36,
    attrs: {
      body: {
        strokeWidth: 1,
        stroke: '#5F95FF',
        fill: '#EFF4FF'
      },
      text: {
        fontSize: 12,
        fill: '#262626'
      }
    },
    ports: {
      groups,
      items: [
        { group: 'top' },
        { group: 'right' },
        { group: 'bottom' },
        { group: 'left' }
      ]
    }
  },
  true
)
Graph.registerNode(
  'mk-polygon',
  {
    inherit: 'polygon',
    width: 66,
    height: 36,
    attrs: {
      body: {
        strokeWidth: 1,
        stroke: '#5F95FF',
        fill: '#EFF4FF'
      },
      text: {
        fontSize: 12,
        fill: '#262626'
      }
    },
    ports: {
      groups,
      items: [
        { group: 'top' },
        { group: 'right' },
        { group: 'bottom' },
        { group: 'left' }
      ]
    }
  },
  true
)
Graph.registerNode(
  'mk-circle',
  {
    inherit: 'circle',
    width: 36,
    height: 36,
    attrs: {
      body: {
        strokeWidth: 1,
        stroke: '#5F95FF',
        fill: '#EFF4FF'
      },
      text: {
        fontSize: 12,
        fill: '#262626'
      }
    },
    ports: {
      groups,
      items: [
        { group: 'top' },
        { group: 'right' },
        { group: 'bottom' },
        { group: 'left' }
      ]
    }
  },
  true
)
Graph.registerNode(
  'mk-ellipse',
  {
    inherit: 'ellipse',
    width: 66,
    height: 36,
    attrs: {
      body: {
        strokeWidth: 1,
        stroke: '#5F95FF',
        fill: '#EFF4FF'
      },
      text: {
        fontSize: 12,
        fill: '#262626'
      }
    },
    ports: {
      groups,
      items: [
        { group: 'top' },
        { group: 'right' },
        { group: 'bottom' },
        { group: 'left' }
      ]
    }
  },
  true
)
Graph.registerNode(
  'mk-star',
  {
    inherit: 'polygon',
    width: 36,
    height: 36,
    points: '100,10 40,198 190,78 10,78 160,198',
    attrs: {
      body: {
        fill: '#EFF4FF',
        stroke: '#5F95FF',
        strokeWidth: 1,
        fillRule: 'nonzero'
      },
      text: {
        fontSize: 12,
        fill: '#262626'
      }
    },
    ports: {
      groups,
      items: [
        { group: 'top' },
        { group: 'right' },
        { group: 'bottom' },
        { group: 'left' }
      ]
    }
  },
  true
)
class antvX6Chart extends Component {
  static propTpyes = {
@@ -113,27 +329,47 @@
    // #region 初始化画布
    const graph = new Graph({
      container: document.getElementById(card.uuid + 'container'),
      grid: true,
      // grid: true,
      grid: {
        visible: true,
        type: 'doubleMesh',
        args: [
          {
            color: '#eee', // 主网格线颜色
            thickness: 1   // 主网格线宽度
          },
          {
            color: '#ddd', // 次网格线颜色
            thickness: 1,  // 次网格线宽度
            factor: 4      // 主次网格线间隔
          }
        ]
      },
      autoResize: true,
      panning: true,
      background: {
        color: '#ffffff',
      },
      mousewheel: {
        enabled: true,
        zoomAtMousePosition: true,
        modifiers: 'ctrl',
        minScale: 0.5,
        maxScale: 3,
        maxScale: 5,
      },
      connecting: {
        router: 'manhattan',
        connector: {
          name: 'rounded',
          args: {
            radius: 8,
          },
            radius: 8
          }
        },
        anchor: 'center',
        connectionPoint: 'anchor',
        allowBlank: false,
        snap: {
          radius: 20,
          radius: 20
        },
        createEdge() {
          return new Shape.Edge({
@@ -167,57 +403,49 @@
        },
      },
    })
    // #endregion
    // #region 使用插件
    graph
      .use(
        new Transform({
          resizing: true,
          rotating: true,
        }),
          rotating: true
        })
      )
      .use(
        new Selection({
          rubberband: true,
          showNodeSelectionBox: true,
        }),
      )
      .use(new Selection())
      .use(new Snapline())
      .use(new Keyboard())
      .use(new Clipboard())
      .use(new History())
    // #endregion
    // #region 初始化 stencil
    const stencil = new Stencil({
      title: '流程图',
      target: graph,
      stencilGraphWidth: 200,
      stencilGraphWidth: 180,
      stencilGraphHeight: 180,
      // collapsable: true,
      groups: [
        {
          title: '通用节点',
          name: 'group1',
          name: 'group1'
        },
        {
          title: '系统设计图',
          title: '自定义',
          name: 'group2',
          graphHeight: 250,
          graphHeight: 120,
          layoutOptions: {
            rowHeight: 70,
          },
        },
            rowHeight: 70
          }
        }
      ],
      layoutOptions: {
        columns: 2,
        columnWidth: 80,
        rowHeight: 55,
      },
        rowHeight: 55
      }
    })
    document.getElementById(card.uuid + 'stencil').appendChild(stencil.container)
    // #endregion
    // #region 快捷键与事件
    graph.bindKey(['meta+c', 'ctrl+c'], () => {
@@ -303,300 +531,80 @@
      const ports = container.querySelectorAll('.x6-port-body')
      showPorts(ports, false)
    })
    // #endregion
    // #region 初始化图形
    const ports = {
      groups: {
        top: {
          position: 'top',
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: '#5F95FF',
              strokeWidth: 1,
              fill: '#fff',
              style: {
                visibility: 'hidden',
              },
            },
          },
        },
        right: {
          position: 'right',
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: '#5F95FF',
              strokeWidth: 1,
              fill: '#fff',
              style: {
                visibility: 'hidden',
              },
            },
          },
        },
        bottom: {
          position: 'bottom',
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: '#5F95FF',
              strokeWidth: 1,
              fill: '#fff',
              style: {
                visibility: 'hidden',
              },
            },
          },
        },
        left: {
          position: 'left',
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: '#5F95FF',
              strokeWidth: 1,
              fill: '#fff',
              style: {
                visibility: 'hidden',
              },
            },
          },
        },
      },
      items: [
        {
          group: 'top',
        },
        {
          group: 'right',
        },
        {
          group: 'bottom',
        },
        {
          group: 'left',
        },
      ],
    }
    Graph.registerNode(
      'custom-rect',
      {
        inherit: 'rect',
        width: 66,
        height: 36,
        attrs: {
          body: {
            strokeWidth: 1,
            stroke: '#5F95FF',
            fill: '#EFF4FF',
          },
          text: {
            fontSize: 12,
            fill: '#262626',
          },
        },
        ports: { ...ports },
      },
      true,
    )
    Graph.registerNode(
      'custom-polygon',
      {
        inherit: 'polygon',
        width: 66,
        height: 36,
        attrs: {
          body: {
            strokeWidth: 1,
            stroke: '#5F95FF',
            fill: '#EFF4FF',
          },
          text: {
            fontSize: 12,
            fill: '#262626',
          },
        },
        ports: {
          ...ports,
          items: [
            {
              group: 'top',
            },
            {
              group: 'bottom',
            },
          ],
        },
      },
      true,
    )
    Graph.registerNode(
      'custom-circle',
      {
        inherit: 'circle',
        width: 45,
        height: 45,
        attrs: {
          body: {
            strokeWidth: 1,
            stroke: '#5F95FF',
            fill: '#EFF4FF',
          },
          text: {
            fontSize: 12,
            fill: '#262626',
          },
        },
        ports: { ...ports },
      },
      true,
    )
    Graph.registerNode(
      'custom-image',
      {
        inherit: 'rect',
        width: 52,
        height: 52,
        markup: [
          {
            tagName: 'rect',
            selector: 'body',
          },
          {
            tagName: 'image',
          },
          {
            tagName: 'text',
            selector: 'label',
          },
        ],
        attrs: {
          body: {
            stroke: '#5F95FF',
            fill: '#5F95FF',
          },
          image: {
            width: 26,
            height: 26,
            refX: 13,
            refY: 16,
          },
          label: {
            refX: 3,
            refY: 2,
            textAnchor: 'left',
            textVerticalAnchor: 'top',
            fontSize: 12,
            fill: '#fff',
          },
        },
        ports: { ...ports },
      },
      true,
    )
    // graph.on('cell:click', ({ e, x, y, cell, view }) => {
    //   console.log(cell)
    //   console.log(view)
    // })
    graph.on('node:click', ({ e, x, y, node, view }) => {
      console.log(node)
    })
    graph.on('edge:click', ({ e, x, y, edge, view }) => {
      console.log(edge)
    })
    graph.on('blank:click', ({ e, x, y }) => {
      console.log(13)
    })
    const r1 = graph.createNode({
      shape: 'custom-rect',
      shape: 'mk-rect',
      label: '开始',
      attrs: {
        body: {
          rx: 20,
          ry: 26,
        },
      },
          ry: 26
        }
      }
    })
    const r2 = graph.createNode({
      shape: 'custom-rect',
      label: '过程',
      shape: 'mk-rect',
      label: '过程'
    })
    const r3 = graph.createNode({
      shape: 'custom-rect',
      shape: 'mk-rect',
      attrs: {
        body: {
          rx: 6,
          ry: 6,
        },
          ry: 6
        }
      },
      label: '可选过程',
      label: '可选过程'
    })
    const r4 = graph.createNode({
      shape: 'custom-polygon',
      shape: 'mk-polygon',
      attrs: {
        body: {
          refPoints: '0,10 10,0 20,10 10,20',
        },
          refPoints: '0,10 10,0 20,10 10,20'
        }
      },
      label: '决策',
      label: '决策'
    })
    const r5 = graph.createNode({
      shape: 'custom-polygon',
      shape: 'mk-polygon',
      attrs: {
        body: {
          refPoints: '10,0 40,0 30,20 0,20',
        },
          refPoints: '10,0 40,0 30,20 0,20'
        }
      },
      label: '数据',
      label: '数据'
    })
    const r6 = graph.createNode({
      shape: 'custom-circle',
      label: '连接',
      shape: 'mk-circle',
      label: '连接'
    })
    stencil.load([r1, r2, r3, r4, r5, r6], 'group1')
    const imageShapes = [
      {
        label: 'Client',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/687b6cb9-4b97-42a6-96d0-34b3099133ac.svg',
      },
      {
        label: 'Http',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/dc1ced06-417d-466f-927b-b4a4d3265791.svg',
      },
      {
        label: 'Api',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/c55d7ae1-8d20-4585-bd8f-ca23653a4489.svg',
      },
      {
        label: 'Sql',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/6eb71764-18ed-4149-b868-53ad1542c405.svg',
      },
      {
        label: 'Clound',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/c36fe7cb-dc24-4854-aeb5-88d8dc36d52e.svg',
      },
      {
        label: 'Mq',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/2010ac9f-40e7-49d4-8c4a-4fcf2f83033b.svg',
      },
    ]
    const imageNodes = imageShapes.map((item) =>
      graph.createNode({
        shape: 'custom-image',
        label: item.label,
        attrs: {
          image: {
            'xlink:href': item.image,
          },
        },
      }),
    )
    stencil.load(imageNodes, 'group2')
    const p1 = graph.createNode({
      shape: 'mk-ellipse',
      label: 'ellipse'
    })
    const p2 = graph.createNode({
      shape: 'mk-star',
      label: ''
    })
    stencil.load([p1, p2], 'group2')
  }
  updateComponent = (card) => {
@@ -659,6 +667,30 @@
          <ToolOutlined/>
        </Popover>
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <div className="mk-toolbar">
          <div className="left-tool">
            <Tooltip title="置前">
              <VerticalAlignTopOutlined />
            </Tooltip>
            <Tooltip title="置后">
              <VerticalAlignBottomOutlined />
            </Tooltip>
            <Tooltip title="保存">
              <SaveOutlined />
            </Tooltip>
          </div>
          <div className="right-tool">
            <Tooltip title="放大">
              <ZoomInOutlined />
            </Tooltip>
            <Tooltip title="缩小">
              <ZoomOutOutlined />
            </Tooltip>
            <Tooltip title="1:1">
              <OneToOneOutlined />
            </Tooltip>
          </div>
        </div>
        <div className="canvas" style={{width: '100%', minHeight: card.plot.height, height: card.plot.height}} id={card.uuid + 'canvas'}>
          <div id={card.uuid + 'stencil'} className="mk-stencil"></div>
          <div id={card.uuid + 'container'} className="mk-container"></div>