From 42d40221c994caa470478c86605b2b006b7839b8 Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期三, 07 六月 2023 14:19:01 +0800 Subject: [PATCH] Merge branch 'develop' --- src/menu/components/chart/antv-X6/index.jsx | 767 ++++++++++++++++++++++++++++++++++------------------------ 1 files changed, 444 insertions(+), 323 deletions(-) diff --git a/src/menu/components/chart/antv-X6/index.jsx b/src/menu/components/chart/antv-X6/index.jsx index 815cdf0..5ace0da 100644 --- a/src/menu/components/chart/antv-X6/index.jsx +++ b/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, message } from 'antd' +import { ToolOutlined, DeleteOutlined, FontColorsOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, DoubleLeftOutlined } from '@ant-design/icons' import { Graph, Shape } from '@antv/x6' import { Stencil } from '@antv/x6-plugin-stencil' import { Transform } from '@antv/x6-plugin-transform' @@ -20,8 +20,225 @@ const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) +const NodeUpdate = asyncIconComponent(() => import('./nodeupdate')) 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 = { @@ -32,8 +249,14 @@ state = { card: null, - eventListener: null + eventListener: null, + toolunfold: true, + nodeunfold: true, + node: null } + + selectNode = null + mkGraph = null UNSAFE_componentWillMount () { const { card } = this.props @@ -113,27 +336,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: 2 }, 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({ @@ -144,16 +387,16 @@ targetMarker: { name: 'block', width: 12, - height: 8, - }, - }, + height: 8 + } + } }, - zIndex: 0, + zIndex: 0 }) }, validateConnection({ targetMagnet }) { return !!targetMagnet - }, + } }, highlighting: { magnetAdsorbed: { @@ -161,63 +404,53 @@ args: { attrs: { fill: '#5F95FF', - stroke: '#5F95FF', - }, - }, - }, - }, + stroke: '#5F95FF' + } + } + } + } }) - // #endregion // #region 浣跨敤鎻掍欢 graph - .use( - new Transform({ - resizing: true, - rotating: true, - }), - ) - .use( - new Selection({ - rubberband: true, - showNodeSelectionBox: true, - }), - ) + .use(new Transform({ + resizing: true, + rotating: 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'], () => { @@ -274,18 +507,18 @@ }) // zoom - graph.bindKey(['ctrl+1', 'meta+1'], () => { - const zoom = graph.zoom() - if (zoom < 1.5) { - graph.zoom(0.1) - } - }) - graph.bindKey(['ctrl+2', 'meta+2'], () => { - const zoom = graph.zoom() - if (zoom > 0.5) { - graph.zoom(-0.1) - } - }) + // graph.bindKey(['ctrl+1', 'meta+1'], () => { + // const zoom = graph.zoom() + // if (zoom < 1.5) { + // graph.zoom(0.1) + // } + // }) + // graph.bindKey(['ctrl+2', 'meta+2'], () => { + // const zoom = graph.zoom() + // if (zoom > 0.5) { + // graph.zoom(-0.1) + // } + // }) // 鎺у埗杩炴帴妗╂樉绀�/闅愯棌 const showPorts = (ports, show) => { @@ -303,300 +536,153 @@ 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 }) => { + // cell.attr('body/stroke', "red") + // }) + graph.on('node:click', ({ e, x, y, node, view }) => { + this.selectNode = node + + this.setState({node: this.selectNode.store.data}) + }) + graph.on('edge:click', ({ e, x, y, edge, view }) => { + this.selectNode = edge + + this.setState({node: this.selectNode.store.data}) + + let trans = document.querySelectorAll('.x6-widget-transform') + if (trans && trans[0]) { + trans[0].style.display = 'none' + } + }) + graph.on('blank:click', ({ e, x, y }) => { + this.selectNode = null + + this.setState({node: null}) + }) + 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 p1 = graph.createNode({ + shape: 'mk-ellipse', + label: 'ellipse' + }) + const p2 = graph.createNode({ + shape: 'mk-star', + label: '' + }) + + stencil.load([p1, p2], 'group2') + + this.mkGraph = graph + } + + setTop = () => { + if (!this.selectNode) { + message.warning('璇烽�夋嫨鑺傜偣锛�') + return + } + this.selectNode.toFront() + } - 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') + setBottom = () => { + if (!this.selectNode) { + message.warning('璇烽�夋嫨鑺傜偣锛�') + return + } + // let cells = this.mkGraph.getCells() + this.selectNode.toBack() + } + + setZoomIn = () => { + const zoom = this.mkGraph.zoom() + + if (zoom < 2) { + this.mkGraph.zoom(0.1) + } + } + + setZoomOut = () => { + const zoom = this.mkGraph.zoom() + + if (zoom > 0.5) { + this.mkGraph.zoom(-0.1) + } + } + + setZoomInt = () => { + this.mkGraph.zoomTo(1) + } + + save = () => { + // let nodes = this.mkGraph.toJSON() + } + + changeProps = (value, key) => { + const { node } = this.state + + if (node.shape === 'edge') { + + } else { + if (key === 'title') { + this.selectNode.attr('text/text', value) + } else if (key === 'fill') { + this.selectNode.attr('body/fill', value) + } else if (key === 'stroke') { + this.selectNode.attr('body/stroke', value) + } else if (key === 'fontSize') { + this.selectNode.attr('text/fontSize', value) + } else if (key === 'fontFill') { + this.selectNode.attr('text/fill', value) + } + } } updateComponent = (card) => { @@ -642,11 +728,11 @@ } render() { - const { card } = this.state + const { card, toolunfold, nodeunfold, node } = this.state let _style = resetStyle(card.style) return ( - <div className="menu-scatter-chart-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-x6-chart-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <ChartCompileForm config={card} plotchange={this.updateComponent}/> @@ -659,9 +745,44 @@ <ToolOutlined/> </Popover> <NormalHeader config={card} updateComponent={this.updateComponent}/> + <div className="mk-toolbar"> + <div className="left-tool"> + <Tooltip title="缃墠"> + <VerticalAlignTopOutlined onClick={this.setTop}/> + </Tooltip> + <Tooltip title="缃悗"> + <VerticalAlignBottomOutlined onClick={this.setBottom}/> + </Tooltip> + <Tooltip title="淇濆瓨"> + <SaveOutlined onClick={this.save}/> + </Tooltip> + </div> + <div className="right-tool"> + <Tooltip title="鏀惧ぇ"> + <ZoomInOutlined onClick={this.setZoomIn}/> + </Tooltip> + <Tooltip title="缂╁皬"> + <ZoomOutOutlined onClick={this.setZoomOut}/> + </Tooltip> + <Tooltip title="1:1"> + <OneToOneOutlined onClick={this.setZoomInt}/> + </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 + 'stencil'} className={'mk-stencil ' + (toolunfold ? '' : 'merge')}> + <div className="tool-control" onClick={() => this.setState({toolunfold: !toolunfold})}> + <DoubleLeftOutlined /> + </div> + </div> <div id={card.uuid + 'container'} className="mk-container"></div> + <div className={'mk-node-edit ' + (nodeunfold ? '' : 'merge')}> + <div className="tool-control" onClick={() => this.setState({nodeunfold: !nodeunfold})}> + <DoubleLeftOutlined /> + </div> + <div className="header">璁剧疆</div> + {!node ? <div className="empty">鏈�変腑</div> : <NodeUpdate node={node} onChange={this.changeProps}/>} + </div> </div> <div className="component-name"> <div className="center"> -- Gitblit v1.8.0