| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Spin, Tooltip, Empty, message, Modal, notification } from 'antd' |
| | | import { VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, DownloadOutlined } from '@ant-design/icons' |
| | | import { Spin, Tooltip, message, Modal, notification } from 'antd' |
| | | import { UndoOutlined, RedoOutlined, 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' |
| | |
| | | import { Export } from '@antv/x6-plugin-export' |
| | | |
| | | import Api from '@/api' |
| | | import UtilsDM from '@/utils/utils-datamanage.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import NormalHeader from '@/tabviews/custom/components/share/normalheader' |
| | | import lanes from '@/menu/components/chart/antv-X6/lane.json' |
| | | import xflows from '@/menu/components/chart/antv-X6/xflow.json' |
| | | import './index.scss' |
| | | |
| | | const NodeUpdate = asyncComponent(() => import('./nodeupdate')) |
| | |
| | | |
| | | class antvX6Chart extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.object, |
| | | mainSearch: PropTypes.any |
| | | config: PropTypes.object |
| | | } |
| | | |
| | | state = { |
| | | config: null, |
| | | editing: false, |
| | | node: null, |
| | | arr_field: 'id,cells', |
| | | loading: false |
| | | } |
| | | |
| | | selectNode = null |
| | | mkGraph = null |
| | | cells = [] |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | |
| | | let BID = '' |
| | | let BData = '' |
| | | |
| | | if (config.setting.supModule) { |
| | | BData = window.GLOB.CacheData.get(config.setting.supModule) |
| | | _config.setting.supModule = '' |
| | | |
| | | if (_config.plot.supModule && _config.plot.supModule.length > 0) { |
| | | _config.setting.supModule = _config.plot.supModule.pop() |
| | | } |
| | | |
| | | if (_config.setting.supModule) { |
| | | BData = window.GLOB.CacheData.get(_config.setting.supModule) |
| | | } else { |
| | | BData = window.GLOB.CacheData.get(config.$pageId) |
| | | } |
| | |
| | | BData: BData || '', |
| | | plot: _config.plot |
| | | }, () => { |
| | | if (config.setting.onload === 'true') { |
| | | setTimeout(() => { |
| | | this.loadData() |
| | | }, _config.setting.delay || 0) |
| | | } |
| | | this.loadData() |
| | | }) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('reloadData', this.reloadData) |
| | | MKEmitter.addListener('resetSelectLine', this.resetParentParam) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | |
| | | MKEmitter.removeListener('reloadData', this.reloadData) |
| | | MKEmitter.removeListener('resetSelectLine', this.resetParentParam) |
| | | } |
| | | |
| | | reloadData = (menuId) => { |
| | | const { config } = this.state |
| | | |
| | | if (config.uuid !== menuId) return |
| | | |
| | | this.loadData() |
| | | } |
| | | |
| | | resetParentParam = (MenuID, id) => { |
| | | const { config } = this.state |
| | | |
| | | if (!config.setting.supModule || config.setting.supModule !== MenuID) return |
| | | if (id !== this.state.BID || id !== '') { |
| | | this.setState({ BID: id }, () => { |
| | | this.loadData() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | async loadData () { |
| | | const { mainSearch } = this.props |
| | | const { config, arr_field, BID } = this.state |
| | | const { config, BID } = this.state |
| | | |
| | | if (config.setting.supModule && !BID) { // BID 不存在时,不做查询 |
| | | if (!is(fromJS(this.data), fromJS([]))) { |
| | | this.data = [] |
| | | this.cells = [] |
| | | this.handleData() |
| | | } |
| | | return |
| | | } |
| | | |
| | | let searches = config.setting.useMSearch && mainSearch ? mainSearch : [] |
| | | |
| | | let requireFields = searches.filter(item => item.required && item.value === '') |
| | | if (requireFields.length > 0) { |
| | | return |
| | | } |
| | | |
| | |
| | | loading: true |
| | | }) |
| | | |
| | | let _orderBy = config.setting.order || '' |
| | | let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID) |
| | | if (config) { |
| | | if (config.plot.subtype === 'xflow') { |
| | | this.cells = xflows |
| | | } else { |
| | | this.cells = lanes |
| | | } |
| | | this.handleData() |
| | | |
| | | setTimeout(() => { |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | }, 2000) |
| | | return |
| | | } |
| | | |
| | | let param = { |
| | | func: '', |
| | | BID: BID |
| | | } |
| | | |
| | | let result = await Api.genericInterface(param) |
| | | if (result.status) { |
| | | if (config.$cache && config.setting.onload !== 'false') { |
| | | Api.writeCacheConfig(config.uuid, result.data || '') |
| | | } |
| | | |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | |
| | | if (!is(fromJS(this.data), fromJS(result.data || []))) { |
| | | this.data = result.data || [] |
| | | this.handleData() |
| | | } |
| | | this.cells = result.data || [] |
| | | this.handleData() |
| | | |
| | | if (result.message) { |
| | | if (result.ErrCode === 'Y') { |
| | |
| | | viewrender = () => { |
| | | const { plot } = this.state |
| | | |
| | | if (plot.subtype === 'xflow') { |
| | | this.xflowrender() |
| | | } else if (plot.subtype === 'lane') { |
| | | this.lanerender() |
| | | if (plot.function === 'show') { |
| | | if (plot.subtype === 'xflow') { |
| | | this.xflowSrender() |
| | | } else if (plot.subtype === 'lane') { |
| | | this.laneSrender() |
| | | } |
| | | } else { |
| | | if (plot.subtype === 'xflow') { |
| | | this.xflowrender() |
| | | } else if (plot.subtype === 'lane') { |
| | | this.lanerender() |
| | | } |
| | | } |
| | | } |
| | | |
| | | xflowSrender = () => { |
| | | const { config } = this.state |
| | | |
| | | const graph = new Graph({ |
| | | container: document.getElementById(config.uuid + 'container'), |
| | | grid: config.plot.grid, |
| | | scaling: { |
| | | min: 0.5, |
| | | max: 2 |
| | | }, |
| | | autoResize: true, |
| | | panning: true, |
| | | background: { |
| | | color: config.plot.backgroundColor || 'transparent' |
| | | }, |
| | | mousewheel: { |
| | | enabled: true, |
| | | zoomAtMousePosition: true, |
| | | modifiers: 'ctrl' |
| | | }, |
| | | connecting: { |
| | | router: 'manhattan', |
| | | connector: { |
| | | name: 'rounded', |
| | | args: { |
| | | radius: 8 |
| | | } |
| | | }, |
| | | anchor: 'center', |
| | | connectionPoint: 'anchor', |
| | | allowBlank: false, |
| | | snap: { |
| | | radius: 20 |
| | | }, |
| | | createEdge() { |
| | | return new Shape.Edge({ |
| | | attrs: { |
| | | line: { |
| | | stroke: '#000000', |
| | | strokeWidth: 1, |
| | | targetMarker: { |
| | | name: 'block', |
| | | width: 12, |
| | | height: 8 |
| | | } |
| | | } |
| | | }, |
| | | zIndex: 0 |
| | | }) |
| | | }, |
| | | validateConnection({ targetMagnet }) { |
| | | return !!targetMagnet |
| | | } |
| | | }, |
| | | highlighting: { |
| | | magnetAdsorbed: { |
| | | name: 'stroke', |
| | | args: { |
| | | attrs: { |
| | | fill: '#5F95FF', |
| | | stroke: '#5F95FF' |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | |
| | | if (this.cells.length > 0) { |
| | | let cells = [] |
| | | this.cells.forEach((item) => { |
| | | if (item.shape === 'edge') { |
| | | cells.push(graph.createEdge(item)) |
| | | } else { |
| | | cells.push(graph.createNode(item)) |
| | | } |
| | | }) |
| | | graph.resetCells(cells) |
| | | graph.positionContent('center') |
| | | } |
| | | } |
| | | |
| | | laneSrender = () => { |
| | | const { config } = this.state |
| | | |
| | | const graph = new Graph({ |
| | | container: document.getElementById(config.uuid + 'container'), |
| | | scaling: { |
| | | min: 0.5, |
| | | max: 2 |
| | | }, |
| | | autoResize: true, |
| | | panning: true, |
| | | background: { color: '#ffffff' }, |
| | | mousewheel: { |
| | | enabled: true, |
| | | zoomAtMousePosition: true, |
| | | modifiers: 'ctrl' |
| | | }, |
| | | connecting: { |
| | | router: 'manhattan', |
| | | connector: { |
| | | name: 'rounded', |
| | | args: { |
| | | radius: 8 |
| | | } |
| | | }, |
| | | anchor: 'center', |
| | | connectionPoint: 'anchor', |
| | | allowBlank: false, |
| | | snap: { |
| | | radius: 20 |
| | | }, |
| | | createEdge() { |
| | | return new Shape.Edge({ |
| | | attrs: { |
| | | line: { |
| | | stroke: '#000000', |
| | | strokeWidth: 1, |
| | | targetMarker: { |
| | | name: 'block', |
| | | width: 12, |
| | | height: 8 |
| | | } |
| | | } |
| | | }, |
| | | zIndex: 2 |
| | | }) |
| | | }, |
| | | validateConnection({ targetMagnet }) { |
| | | return !!targetMagnet |
| | | } |
| | | }, |
| | | highlighting: { |
| | | magnetAdsorbed: { |
| | | name: 'stroke', |
| | | args: { |
| | | attrs: { |
| | | fill: '#5F95FF', |
| | | stroke: '#5F95FF' |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | translating: { |
| | | restrict(cellView) { |
| | | const cell = cellView.cell |
| | | const parentId = cell.prop('parent') |
| | | |
| | | if (parentId) { |
| | | const parentNode = graph.getCellById(parentId) |
| | | if (parentNode) { |
| | | return parentNode.getBBox().moveAndExpand({ |
| | | x: 0, |
| | | y: 36, |
| | | width: 0, |
| | | height: -36, |
| | | }) |
| | | } |
| | | } |
| | | return cell.getBBox() |
| | | } |
| | | } |
| | | }) |
| | | |
| | | if (this.cells.length > 0) { |
| | | let cells = [] |
| | | this.cells.forEach((item) => { |
| | | if (item.shape === 'edge') { |
| | | cells.push(graph.createEdge(item)) |
| | | } else { |
| | | cells.push(graph.createNode(item)) |
| | | } |
| | | }) |
| | | graph.resetCells(cells) |
| | | graph.positionContent('top') |
| | | } |
| | | } |
| | | |
| | |
| | | }) |
| | | |
| | | stencil.load([p1, p2, p3], 'group2') |
| | | |
| | | if (this.cells.length > 0) { |
| | | let cells = [] |
| | | this.cells.forEach((item) => { |
| | | if (item.shape === 'edge') { |
| | | cells.push(graph.createEdge(item)) |
| | | } else { |
| | | cells.push(graph.createNode(item)) |
| | | } |
| | | }) |
| | | graph.resetCells(cells) |
| | | graph.positionContent('center') |
| | | } |
| | | |
| | | this.mkGraph = graph |
| | | } |
| | |
| | | |
| | | stencil.load([g1], 'group3') |
| | | |
| | | // let data = [{"id":"1","shape":"lane","width":260,"height":500,"position":{"x":0,"y":0},"label":"阶段1", preId: '', nextId: '2'},{"id":"2","shape":"lane","width":200,"height":500,"position":{"x":260,"y":0},"label":"<Function>", preId: '1', nextId: '3'},{"id":"3","shape":"lane","width":200,"height":500,"position":{"x":460,"y":0},"label":"<Function>", preId: '2', nextId: '4'},{"id":"4","shape":"lane","width":200,"height":500,"position":{"x":660,"y":0},"label":"<Function>", preId: '3', nextId: ''}] |
| | | // let cells = [] |
| | | // data.forEach((item) => { |
| | | // if (item.shape === 'edge') { |
| | | // cells.push(graph.createEdge(item)) |
| | | // } else { |
| | | // cells.push(graph.createNode(item)) |
| | | // } |
| | | // }) |
| | | // graph.resetCells(cells) |
| | | // graph.zoomToFit({ padding: 10, maxScale: 1 }) |
| | | if (this.cells.length > 0) { |
| | | let cells = [] |
| | | this.cells.forEach((item) => { |
| | | if (item.shape === 'edge') { |
| | | cells.push(graph.createEdge(item)) |
| | | } else { |
| | | cells.push(graph.createNode(item)) |
| | | } |
| | | }) |
| | | graph.resetCells(cells) |
| | | graph.positionContent('top') |
| | | } |
| | | |
| | | this.mkGraph = graph |
| | | } |
| | |
| | | } |
| | | |
| | | // zoom() 可获取或者设置缩放比例 |
| | | setback = () => { |
| | | if (this.mkGraph.canUndo()) { |
| | | this.mkGraph.undo() |
| | | } |
| | | } |
| | | |
| | | setprev = () => { |
| | | if (this.mkGraph.canRedo()) { |
| | | this.mkGraph.redo() |
| | | } |
| | | } |
| | | |
| | | setZoomIn = () => { |
| | | this.mkGraph.zoom(0.1) |
| | | } |
| | |
| | | |
| | | save = () => { |
| | | // let nodes = this.mkGraph.toJSON() |
| | | } |
| | | |
| | | savePicture = () => { |
| | | const { config } = this.state |
| | | this.mkGraph.exportPNG(config.name, {padding: 20}) |
| | | // this.mkGraph.toPNG((dataUri) => { |
| | | // Api.fileuploadbase64({ |
| | | // Base64Img: dataUri |
| | | // }).then(res => { |
| | | // }) |
| | | // }, {padding: 20}) |
| | | } |
| | | |
| | | addLane = (cell, graph) => { |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { loading, config, empty, node } = this.state |
| | | const { loading, config, node } = this.state |
| | | |
| | | let style = {...config.style} |
| | | |
| | | if (config.plot.function === 'show') { |
| | | if (config.plot.empty === 'hidden' && this.cells.length === 0) { |
| | | style.display = 'none' |
| | | } |
| | | |
| | | return ( |
| | | <div className="custom-x6-plot-box" id={'anchor' + config.uuid} style={config.style}> |
| | | {loading ? |
| | | <div className="loading-mask"> |
| | | <div className="ant-spin-blur"></div> |
| | | <Spin /> |
| | | </div> : null |
| | | } |
| | | <NormalHeader config={config} /> |
| | | <div className="canvas" style={{width: '100%', minHeight: config.plot.height, height: config.plot.height}} id={config.uuid + 'canvas'}> |
| | | <div id={config.uuid + 'container'} className="mk-container"></div> |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | |
| | | return ( |
| | | <div className="custom-x6-plot-box" id={'anchor' + config.uuid} style={config.style}> |
| | |
| | | </div> : null |
| | | } |
| | | <NormalHeader config={config} /> |
| | | {empty ? <Empty description={false}/> : null} |
| | | <div className="mk-toolbar"> |
| | | <div className="left-tool"> |
| | | {config.plot.subtype === 'xflow' ? <Tooltip title="置前"> |
| | |
| | | {config.plot.subtype === 'xflow' ? <Tooltip title="置后"> |
| | | <VerticalAlignBottomOutlined onClick={this.setBottom}/> |
| | | </Tooltip> : null} |
| | | <Tooltip title="保存"> |
| | | <SaveOutlined onClick={this.save}/> |
| | | </Tooltip> |
| | | {config.plot.export === 'png' ? <Tooltip title="导出图片"> |
| | | <DownloadOutlined onClick={this.savePicture}/> |
| | | </Tooltip> : null} |
| | | </div> |
| | | <div className="right-tool"> |
| | | <Tooltip title="放大"> |
| | | <ZoomInOutlined onClick={this.setZoomIn}/> |
| | | </Tooltip> |
| | |
| | | <Tooltip title="1:1"> |
| | | <OneToOneOutlined onClick={this.setZoomInt}/> |
| | | </Tooltip> |
| | | <Tooltip title="后退"> |
| | | <UndoOutlined onClick={this.setback}/> |
| | | </Tooltip> |
| | | <Tooltip title="前进"> |
| | | <RedoOutlined onClick={this.setprev}/> |
| | | </Tooltip> |
| | | </div> |
| | | <div className="right-tool"> |
| | | <Tooltip title="保存"> |
| | | <SaveOutlined onClick={this.save}/> |
| | | </Tooltip> |
| | | </div> |
| | | </div> |
| | | <div className="canvas" style={{width: '100%', minHeight: config.plot.height, height: config.plot.height}} id={config.uuid + 'canvas'}> |