| | |
| | | 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' |
| | |
| | | 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 = { |
| | |
| | | // #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({ |
| | |
| | | }, |
| | | }, |
| | | }) |
| | | // #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'], () => { |
| | |
| | | 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) => { |
| | |
| | | <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> |