Commit 4d8b078c authored by zhengjiangtao's avatar zhengjiangtao

虚拟云监控平台和金融城域网菜单和demo增加

parent 05fc2e02
...@@ -94,6 +94,9 @@ const AsyncDynamicRing = props => <AsyncLoader load={import('./../view/bank/dyna ...@@ -94,6 +94,9 @@ const AsyncDynamicRing = props => <AsyncLoader load={import('./../view/bank/dyna
const AsyncEqpAndMovingRing = props => <AsyncLoader load={import('./../view/bank/eqpAndMovingRing/index')} componentProps={props} />; const AsyncEqpAndMovingRing = props => <AsyncLoader load={import('./../view/bank/eqpAndMovingRing/index')} componentProps={props} />;
const AsyncEquipMonitor = props => <AsyncLoader load={import('./../view/bank/equipMonitor')} componentProps={props} />; const AsyncEquipMonitor = props => <AsyncLoader load={import('./../view/bank/equipMonitor')} componentProps={props} />;
const AsyncSelfSupport = props => <AsyncLoader load={import('./../view/bizview/selfSupport/index')} componentProps={props} />; const AsyncSelfSupport = props => <AsyncLoader load={import('./../view/bizview/selfSupport/index')} componentProps={props} />;
const AsyncVirtualCloudPlatformSupport = props => <AsyncLoader load={import('./../view/bank/virtualCloudPlatform/index')} componentProps={props} />;
const AsyncFinancialCityLanSupport = props => <AsyncLoader load={import('./../view/bank/financialCityLan/index')} componentProps={props} />;
const Routes = { const Routes = {
// 添加 rules 路由 // 添加 rules 路由
...@@ -175,7 +178,9 @@ const Routes = { ...@@ -175,7 +178,9 @@ const Routes = {
donghuan: AsyncDynamicRing, donghuan: AsyncDynamicRing,
deviceMonitor: AsyncEquipMonitor, deviceMonitor: AsyncEquipMonitor,
eqpAndMovingRing: AsyncEqpAndMovingRing, eqpAndMovingRing: AsyncEqpAndMovingRing,
selfSupport:AsyncSelfSupport selfSupport:AsyncSelfSupport,
financialCityLan:AsyncVirtualCloudPlatformSupport,
virtualCloudPlatform:AsyncFinancialCityLanSupport
}; };
......
...@@ -87,6 +87,8 @@ import PamsTable from './../view/pamsTable'; ...@@ -87,6 +87,8 @@ import PamsTable from './../view/pamsTable';
import DynamicRing from './../view/bank/dynamicRing'; import DynamicRing from './../view/bank/dynamicRing';
import EquipMonitor from './../view/bank/equipMonitor'; import EquipMonitor from './../view/bank/equipMonitor';
import EqpAndMovingRing from './../view/bank/eqpAndMovingRing/index'; import EqpAndMovingRing from './../view/bank/eqpAndMovingRing/index';
import VirtualCloudPlatform from './../view/bank/virtualCloudPlatform/index';
import FinancialCityLan from './../view/bank/financialCityLan/index';
const Routes = { const Routes = {
...@@ -171,7 +173,11 @@ const Routes = { ...@@ -171,7 +173,11 @@ const Routes = {
deviceMonitor: EquipMonitor, deviceMonitor: EquipMonitor,
eqpAndMovingRing: EqpAndMovingRing, eqpAndMovingRing: EqpAndMovingRing,
//自建系统 //自建系统
selfSupport: SelfSupport selfSupport: SelfSupport,
//虚拟云平台监控
virtualCloudPlatform : VirtualCloudPlatform,
//金融城域网
financialCityLan : FinancialCityLan
}; };
const pageCompontent = key => { const pageCompontent = key => {
......
.financialCityLan-dy-wrapper {
height: 100%;
display: flex;
.left-content {
width: 300px;
position: relative;
z-index: 1;
background: #fff;
.tree-wrapper {
height: 100%;
.tree-btn {
height: 42px;
line-height: 42px;
background: #f3f3f3;
border:1px solid rgba(234,234,234,1);
border-right: none;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 42px;
.add-topo {
width: 36px;
height: 36px;
background: rgba(255, 255, 255, 1);
opacity: 1;
border-radius: 4px;
padding: 8px;
cursor: pointer;
img {
height: 20px;
}
}
}
.ant-tree {
height: calc(100% - 42px);
padding-left: 24px;
border:1px solid rgba(234,234,234,1);
border-top: none;
padding-top: 7px;
.ant-tree-title {
font-size: 16px;
font-weight: bold;
}
li .ant-tree-node-content-wrapper.ant-tree-node-selected {
background-color: rgba(230, 247, 255, 1);
}
li span.ant-tree-switcher.ant-tree-switcher_open:after {
display: inline-block;
width: 17px;
height: 17px;
content: '';
transform: unset;
transition: unset;
background: url('/src/assets/bizView/netTopology/tree-folder.png');
background-size: cover;
vertical-align: sub;
}
li span.ant-tree-switcher.ant-tree-switcher_close:after {
display: inline-block;
width: 17px;
height: 17px;
content: '';
transform: unset;
transition: unset;
background: url('/src/assets/bizView/netTopology/tree-folder.png');
background-size: cover;
vertical-align: sub;
}
.ant-tree-child-tree {
.ant-tree-switcher:before {
display: inline-block;
width: 16px;
height: 16px;
content: '';
transform: unset;
transition: unset;
background: url('/src/assets/bizView/netTopology/tree-floor.png');
background-size: cover;
vertical-align: sub;
}
.ant-tree-title {
font-size: 14px;
}
}
}
.tree-right {
.ant-menu-item:hover,
.ant-menu-item-active,
.ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,
.ant-menu-submenu-active,
.ant-menu-submenu-title:hover {
background-color: rgba(230, 247, 255, 1);
color: #3f3f3f;
}
.ant-menu-item {
font-size: 14px;
height: 36px;
line-height: 36px;
.tree-add-img {
width: 16px;
height: 16px;
vertical-align: sub;
margin-right: 4px;
}
.tree-del-img {
width: 16px;
height: 16px;
vertical-align: sub;
margin-right: 4px;
}
}
}
}
}
.right-content {
flex: 1;
.financialCityLan-topo-header {
height: 42px;
line-height: 42px;
background:rgba(243,243,243,1);
border:1px solid rgba(234,234,234,1);
border-left: none;
padding-right: 42px;
text-align: right;
padding-top: 2px;
position: relative;
z-index: 1;
img {
height: 20px;
}
.financialCityLan-topo-save {
display: inline-block;
width: 36px;
height: 36px;
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(234, 234, 234, 1);
opacity: 1;
border-radius: 4px 0px 0px 4px;
cursor: pointer;
padding: 8px;
}
.financialCityLan-topo-refresh {
display: inline-block;
width: 36px;
height: 36px;
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(234, 234, 234, 1);
opacity: 1;
border-radius: 0px 4px 4px 0px;
padding: 8px;
cursor: pointer;
}
}
.financialCityLan-topo-content {
height: calc(100% - 42px);
.topology-financialCityLan {
canvas {
outline: none;
}
.tooltip-content {
width: 251px;
background: #345fa6;
box-shadow: inset 0px 3px 6px rgba(0,0,0,0.16);
opacity: 1;
border-radius: 7px;
padding: 22px 24px;
.tooltip-item {
height: 24px;
line-height: 24px;
font-size: 13px;
font-weight: bold;
color: white;
.item-name {
display: inline-block;
}
.item-value {
display: inline-block;
padding-left: 10px;
}
.amosicon {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
}
}
}
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
@import './dynamicRing/index.scss'; @import './dynamicRing/index.scss';
@import './equipMonitor/index.scss'; @import './equipMonitor/index.scss';
@import './selfsupport/index.scss'; @import './selfsupport/index.scss';
@import './financialCityLan/index.scss';
@import './virtualCloudPlatform/index.scss';
.ant-calendar-picker-container { .ant-calendar-picker-container {
&.ant-calendar-picker-container-placement-bottomRight { &.ant-calendar-picker-container-placement-bottomRight {
......
.virtualCloudPlatform-dy-wrapper {
height: 100%;
display: flex;
.left-content {
width: 300px;
position: relative;
z-index: 1;
background: #fff;
.tree-wrapper {
height: 100%;
.tree-btn {
height: 42px;
line-height: 42px;
background: #f3f3f3;
border:1px solid rgba(234,234,234,1);
border-right: none;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 42px;
.add-topo {
width: 36px;
height: 36px;
background: rgba(255, 255, 255, 1);
opacity: 1;
border-radius: 4px;
padding: 8px;
cursor: pointer;
img {
height: 20px;
}
}
}
.ant-tree {
height: calc(100% - 42px);
padding-left: 24px;
border:1px solid rgba(234,234,234,1);
border-top: none;
padding-top: 7px;
.ant-tree-title {
font-size: 16px;
font-weight: bold;
}
li .ant-tree-node-content-wrapper.ant-tree-node-selected {
background-color: rgba(230, 247, 255, 1);
}
li span.ant-tree-switcher.ant-tree-switcher_open:after {
display: inline-block;
width: 17px;
height: 17px;
content: '';
transform: unset;
transition: unset;
background: url('/src/assets/bizView/netTopology/tree-folder.png');
background-size: cover;
vertical-align: sub;
}
li span.ant-tree-switcher.ant-tree-switcher_close:after {
display: inline-block;
width: 17px;
height: 17px;
content: '';
transform: unset;
transition: unset;
background: url('/src/assets/bizView/netTopology/tree-folder.png');
background-size: cover;
vertical-align: sub;
}
.ant-tree-child-tree {
.ant-tree-switcher:before {
display: inline-block;
width: 16px;
height: 16px;
content: '';
transform: unset;
transition: unset;
background: url('/src/assets/bizView/netTopology/tree-floor.png');
background-size: cover;
vertical-align: sub;
}
.ant-tree-title {
font-size: 14px;
}
}
}
.tree-right {
.ant-menu-item:hover,
.ant-menu-item-active,
.ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,
.ant-menu-submenu-active,
.ant-menu-submenu-title:hover {
background-color: rgba(230, 247, 255, 1);
color: #3f3f3f;
}
.ant-menu-item {
font-size: 14px;
height: 36px;
line-height: 36px;
.tree-add-img {
width: 16px;
height: 16px;
vertical-align: sub;
margin-right: 4px;
}
.tree-del-img {
width: 16px;
height: 16px;
vertical-align: sub;
margin-right: 4px;
}
}
}
}
}
.right-content {
flex: 1;
.virtualCloudPlatform-topo-header {
height: 42px;
line-height: 42px;
background:rgba(243,243,243,1);
border:1px solid rgba(234,234,234,1);
border-left: none;
padding-right: 42px;
text-align: right;
padding-top: 2px;
position: relative;
z-index: 1;
img {
height: 20px;
}
.virtualCloudPlatform-topo-save {
display: inline-block;
width: 36px;
height: 36px;
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(234, 234, 234, 1);
opacity: 1;
border-radius: 4px 0px 0px 4px;
cursor: pointer;
padding: 8px;
}
.virtualCloudPlatform-topo-refresh {
display: inline-block;
width: 36px;
height: 36px;
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(234, 234, 234, 1);
opacity: 1;
border-radius: 0px 4px 4px 0px;
padding: 8px;
cursor: pointer;
}
}
.virtualCloudPlatform-topo-content {
height: calc(100% - 42px);
.topology-virtualCloudPlatform {
canvas {
outline: none;
}
.tooltip-content {
width: 251px;
background: #345fa6;
box-shadow: inset 0px 3px 6px rgba(0,0,0,0.16);
opacity: 1;
border-radius: 7px;
padding: 22px 24px;
.tooltip-item {
height: 24px;
line-height: 24px;
font-size: 13px;
font-weight: bold;
color: white;
.item-name {
display: inline-block;
}
.item-value {
display: inline-block;
padding-left: 10px;
}
.amosicon {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
}
}
}
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { deepEqual, pwdPolicy } from 'amos-tool';
import go from 'amos-gojs';
import classnames from 'classnames';
import { nodeDetailTopoAction } from './../../../services/dynamicRingService';
const goObj = go.GraphObject.make;
const deviceSource = '/src/assets/bizView/dynamicRing';
class TopologyComponent extends Component {
constructor(props) {
super(props);
this.state = {
detailData: []
};
this.diagram = null; //gojs图
this.customEditor = null;
this.updateTopologyData = {};
}
componentDidMount() {
this.renderCanvas();
}
componentDidUpdate(prevProps, prevState) {
const { topologyData } = this.props;
const { nodeData, linkData } = topologyData;
if (!deepEqual(prevProps.topologyData,this.props.topologyData)) {
this.diagram.model = new go.GraphLinksModel(nodeData, linkData);
this.initTop = 0;
this.initLeft = 0;
}
}
// this function is the Node.dragComputation, to limit the movement of the parts
stayInFixedArea = (part, pt, gridpt) => {
let diagram = part.diagram;
if (diagram === null) {return pt;}
// compute the document area without padding
let v = diagram.documentBounds.copy();
v.subtractMargin(diagram.padding);
// get the bounds of the part being dragged
let b = part.actualBounds;
let loc = part.location;
// now limit the location appropriately
let x = Math.max(v.x, Math.min(pt.x, v.right - b.width)) + (loc.x - b.x);
let y = Math.max(v.y, Math.min(pt.y, v.bottom - b.height)) + (loc.y - b.y);
return new go.Point(x, y);
}
// 选择节点
nodeSelectionChanged = (node) => {
this.props.nodeSelectionChanged(node);
}
// 设备资源图片
getDeviceSource = (v) => {
return `${deviceSource}/${v}.png`;
}
// 告警图片
getWarnPic = (v) => {
if (v) {
return '/src/assets/bizView/netTopology/alarm.png';
}
}
// 告警高亮
warnHighlights = (d,v) => {
if (d.warnState) {
this.showWarnHighlights(d, v);
return d.text;
}
return d.text;
}
// 获取线颜色
getLinkColor = (v) => {
if (v) {
return '#FF0000';
}
return 'rgba(0,255,8,1)';
}
showWarnHighlights = (d, v) => {
const oldDom = this[d.key];
this.isDrag = true;
if (oldDom) {
let pos = this.diagram.transformDocToView(go.Point.parse(d.loc));
oldDom.style.width = '100px';
oldDom.style.height = '100px';
oldDom.style.left = `${pos.x + 18}px`;
oldDom.style.top = `${pos.y + 20}px`;
} else {
let pos = this.diagram.transformDocToView(go.Point.parse(d.loc));
let customBox = document.createElement('div');
customBox.style.left = `${pos.x + 10}px`;
customBox.style.top = `${pos.y + 26}px`;
customBox.style.position = 'absolute';
customBox.style.zIndex = 1;
customBox.style.width = '100px';
customBox.style.height = '100px';
customBox.style.backgroundPosition = 'center';
customBox.id = d.key;
customBox.setAttribute('class','amos-help-tip-pulse-second');
this.diagram.div.appendChild(customBox);
}
};
// 更新位置信息
updateTopo = () => {
const { nodeDataArray } = this.updateTopologyData;
let pos;
nodeDataArray.filter(item => item.warnState).map(item => {
pos = this.diagram.transformDocToView(go.Point.parse(item.loc));
this[item.key].style.left = `${pos.x + 18}px`;
this[item.key].style.top = `${pos.y + 20}px`;
});
}
getNodeDetail = (id) => {
nodeDetailTopoAction(id).then(data => {
this.setState({
detailData: data
});
});
}
renderDetail = () => {
const { detailData } = this.state;
return (<div id="toolTipDIV" className="tooltip-content" style={{ position: 'absolute', zIndex: 1000, display: 'none' }}>
{detailData.map(item => {
return (<div key={item.name} className="tooltip-item">
<div className="item-name">{item.name}: </div>
<div className="item-value">{item.value}</div>
</div>);
})}
</div>);
}
// 提示框
showToolTip = (obj, diagram, tool) => {
let toolTipDIV = document.getElementById('toolTipDIV');
let pt = diagram.lastInput.viewPoint;
toolTipDIV.style.left = `${pt.x + 12}px`;
toolTipDIV.style.top = `${pt.y}px`;
toolTipDIV.style.display = 'block';
this.getNodeDetail(obj.data.id);
}
hideToolTip = (diagram, tool) => {
let toolTipDIV = document.getElementById('toolTipDIV');
toolTipDIV.style.display = 'none';
}
renderCanvas = () => {
const { topologyData } = this.props;
const { nodeData, linkData } = topologyData;
const myToolTip = goObj(go.HTMLInfo, {
show: this.showToolTip,
hide: this.hideToolTip
});
this.customEditor = goObj(go.HTMLInfo,{
show: this.showWarnHighlights
});
this.diagram = goObj(go.Diagram, this.refs.goJsDiv, {
// allowHorizontalScroll: false, // disallow scrolling or panning
// allowVerticalScroll: false,
allowZoom: false, // disallow zooming
initialContentAlignment: go.Spot.TopLeft,
initialPosition: new go.Point(0, 0),
'undoManager.isEnabled': true, //// enable undo & redo 是否可撤回
'animationManager.isEnabled': false, // 过渡动画
'textEditingTool.defaultTextEditor': this.customEditor,
// fixedBounds: new go.Rect(0, 0, this.refs.goJsDiv.clientWidth, this.refs.goJsDiv.clientHeight),
ModelChanged: (e) => { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
// console.log(e.model.toJson(), 'model');
this.updateTopologyData = JSON.parse(e.model.toJson());
this.props.nodeChange(e);
}
},
SelectionMoved: (e) => {
setTimeout(()=> {
this.updateTopo();
},0);
},
ViewportBoundsChanged: () => {
setTimeout(()=> {
this.updateTopo();
},0);
}
});
this.diagram.nodeTemplateMap.add('Circle',
goObj(go.Node, 'Vertical',
{
selectionObjectName: 'ICON',
locationObjectName: 'ICON'
},
new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
goObj(go.Panel, 'Auto',
goObj(go.Shape, 'Circle', { name: 'ICON',portId: '',
width: 22, height: 22, strokeWidth: 0,fill: '#009dd9' },
),
),
goObj(go.TextBlock,
{ margin: 15,cursor: 'pointer',font: '15px sans-serif' },
new go.Binding('text', 'text' )),
{
selectionAdornmentTemplate:
goObj(go.Adornment, 'Auto',
goObj(go.Shape, 'Circle',
{ fill: null, stroke: '#fbfb7b', strokeWidth: 3 }),
goObj(go.Placeholder)
) // end Adornment
},
));
this.diagram.nodeTemplateMap.add('Picture',
goObj(go.Node, 'Vertical',
{
locationSpot: go.Spot.Center,
locationObjectName: 'ICON',
selectionObjectName: 'ICON',
// dragComputation: this.stayInFixedArea
selectionChanged: this.nodeSelectionChanged,
toolTip: myToolTip
},
new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
goObj(go.Panel,'Spot',
goObj(go.Shape, 'Rectangle',
{ fill: 'lightgreen', stroke: null, width: 1, height: 1 }),
goObj(go.Picture,
{
width: 65,
height: 45,
alignment: new go.Spot(1, 0, 100 ,0 )
},
new go.Binding('source','warnState',(v) => this.getWarnPic(v))
),
goObj(go.TextBlock,
{
alignment: new go.Spot(1, 0, 100 ,-1),
stroke: 'white',
font: '15px sans-serif'
},
new go.Binding('text', 'warnMessage')
),
),
goObj(go.Picture,
{
margin: 0,
name: 'ICON',
width: 55,
height: 55,
cursor: 'pointer',
portId: ''
},
new go.Binding('source','source',(v) => this.getDeviceSource(v))
),
goObj(go.TextBlock, '无',
{ margin: 3, stroke: 'rgba(63,63,63,1)', font: '14px sans-serif' },
new go.Binding('text','', (v,d) => this.warnHighlights(v,d)),
),
{
selectionAdornmentTemplate:
goObj(go.Adornment, 'Auto',
goObj(go.Shape,
{ fill: null, stroke: '#fbfb7b', strokeWidth: 3 }),
goObj(go.Placeholder)
) // end Adornment
}
)
);
this.diagram.groupTemplate = goObj(go.Group, 'Vertical',
{
resizable: true,
locationObjectName: 'SHAPE',
resizeObjectName: 'SHAPE',
selectionObjectName: 'SHAPE'
// dragComputation: this.stayInFixedArea,
// selectionChanged: this.nodeSelectionChanged
},
new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
goObj(go.TextBlock, // group title
{
width: 100,
height: 24,
font: 'Bold 14px Sans-Serif',
stroke: 'white',
background: '#1c9ad2',
margin: 5,
textAlign: 'center',
verticalAlignment: go.Spot.Center
},
new go.Binding('text')),
goObj(go.Shape, 'Rectangle',
{
name: 'SHAPE',
parameter1: 14,
fill: 'rgba(185,185,185,0.2)',
stroke: 'rgba(28,154,210,1)',
strokeWidth: 1
},
new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify),
)
);
this.diagram.linkTemplate =
goObj(go.Link,
goObj(go.Shape, { strokeWidth: 3 },
new go.Binding('stroke', 'warnState', (v) => this.getLinkColor(v))
)
);
this.diagram.model = new go.GraphLinksModel(nodeData, linkData);
}
render() {
const { className,style, topologyData } = this.props;
const { nodeData = [] } = topologyData || {};
return (
<div ref="goJsDiv" style={style} className={classnames('topology-financialCityLan', className)}>
{
nodeData.filter(e => e.warnState).map(e => <div className="amos-help-tip-pulse-second warn-node" ref={node => this[e.key] = node} key={e.key} id={e.key} />)
}
{nodeData.length > 0 && this.renderDetail()}
</div>
);
}
}
TopologyComponent.propTypes = {
className: PropTypes.string,
style: PropTypes.object,
topologyData: PropTypes.object,
nodeChange: PropTypes.func,
nodeSelectionChanged: PropTypes.func
};
TopologyComponent.defaultProps = {
style: { height: '100%' },
topologyData: {
nodeData: [],
linkData: []
}
};
export default TopologyComponent;
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Tree,Menu,Icon,Button } from 'amos-antd';
import { deepCopy } from 'amos-tool';
import { getDyTreeAction } from './../../../services/dynamicRingService';
const TreeNode = Tree.TreeNode;
class TreeComponent extends Component {
constructor(props) {
super(props);
this.state = {
treeData: [
{
name: '',
id: '1',
children: []
}
], //树数据
autoExpandParent: true,
selectedKeys: [],
expandedKeys: [],
rightClickNodeTreeItem: {},
isMenuVisible: false
};
this.treeLists = [];
this.activeKey = null;
this.activeValue = '';
}
componentDidMount() {
document.addEventListener('click', this.bindBodyClick, false);
this.initData();
}
componentWillUnmount() {
document.removeEventListener('click', this.bindBodyClick);
}
componentWillReceiveProps(nextProps) {
if (nextProps.wSelectedKeys && nextProps.wSelectedKeys !== this.props.wSelectedKeys) {
this.setState({
selectedKeys: nextProps.wSelectedKeys
});
}
}
// 绑定body
bindBodyClick = (e) => {
e.stopPropagation();
this.setState({
isMenuVisible: false
});
}
// 初始化树数据
initData = (treeData) => {
const { onSelect } = this.props;
const expandedKeysData = [];
getDyTreeAction().then(data => {
data.map(item => {
expandedKeysData.push(item.id);
});
this.treeLists = data;
onSelect(data[0].id);
this.setState({
treeData: data,
selectedKeys: [data[0].id],
expandedKeys: expandedKeysData
});
});
}
// 树选择
onSelect = (selectedKeys,e) => {
const { onSelect } = this.props;
if (!selectedKeys.length) {return;}
if (!e.node.props.parent) {
onSelect(selectedKeys[0]);
}
this.setState({
selectedKeys
});
}
// 树展开
onExpand = (expandedKeys) => {
this.setState({
expandedKeys,
autoExpandParent: false
});
};
// 节点右键事件
treeNodeonRightClick = (e) => {
// if (e.node.props.parent) {
// return;
// }
const x = e.event.currentTarget.offsetLeft + e.event.currentTarget.clientWidth;
const y = e.event.currentTarget.offsetTop;
this.activeKey = e.node.props.id;
this.setState({
rightClickNodeTreeItem: {
pageX: x,
pageY: y,
id: e.node.props.id,
parent: e.node.props.parent
},
isMenuVisible: true
});
}
// 节点右键菜单
getNodeTreeRightClickMenu = () => {
const { rightClickNodeTreeItem } = this.state;
const { pageX, pageY, id, parent } = rightClickNodeTreeItem;
if (!rightClickNodeTreeItem.id) {
return null;
}
const style = {
position: 'absolute',
left: `${pageX}px`,
top: `${pageY}px`
};
const menu = (
<Menu
onClick={(e) => this.handleMenuClick(e, id)}
style={style}
className="tree-right"
>
{!parent && <Menu.Item key='1'><img src="/src/assets/bizView/netTopology/add-node.png" alt="添加子图" className="tree-add-img" />{'添加子图'}</Menu.Item>}
<Menu.Item key='2'><img src="/src/assets/bizView/netTopology/del-node.png" alt="删除子图" className="tree-del-img" />{'删除'}</Menu.Item>
</Menu>
);
return menu;
}
// 选择菜单
handleMenuClick = (value, id) => {
let { expandedKeys } = this.state;
if (!expandedKeys.includes(id)) {
expandedKeys = [...expandedKeys, id];
}
if (value.key === '1') {
this.addNode(id);
} else {
this.deleteNode(id);
}
this.setState({
isMenuVisible: false,
expandedKeys
});
}
// 添加拓扑插件
addTopology = () => {
this.treeLists.push({
name: '',
id: Math.random(100),
isAdd: true,
children: [],
parent: null
});
this.setState({
treeData: this.treeLists
});
}
// 添加节点
addNode = (id) => {
this.treeLists.map(item => {
if (item.id === id) {
item.children.push({
name: '',
id: id + Math.random(100),
isAdd: true,
children: [],
parent: null
});
}
});
this.setState({
treeData: this.treeLists
});
}
onInputChange = (e, id) => {
this.activeValue = e.target.value;
this.changeNode(id, e.target.value, this.treeLists);
this.setState({
treeData: this.treeLists
});
}
// 改变节点
changeNode = (id, value, data) => data.map((item) => {
if (item.isAdd) {
item.name = value;
return;
}
if (item.children.length) {
this.changeNode(id, value, item.children);
}
})
onClose = (id) => {
this.closeNode(id, this.treeLists);
// this.setState({
// treeData: this.treeLists
// });
this.initData();
}
// 关闭节点
closeNode = (id, data) => data.map((item,index) => {
if (item.id === id) {
data.splice(index, 1);
return;
}
if (item.children.length) {
this.closeNode(id, item.children);
}
})
// 保存节点
onSave = () => {
const params = {
name: this.activeValue,
parent: this.activeKey
};
addWebTreeAction(params).then(() => {
this.initData();
});
}
// 删除节点
deleteNode = (id) => {
delWebTreeAction(id).then(() => {
this.initData();
});
}
renderTreeNodes = (data) => {
let operableTreeData = deepCopy(data);
return operableTreeData.map((item) => {
if (item.isAdd) {
item.name = (
<div>
<input
value={item.name}
onChange={(e) => this.onInputChange(e, item.id)}
/>
<Icon type='close' style={{ marginLeft: 10 }} onClick={() => this.onClose(item.id)} />
<Icon type='check' style={{ marginLeft: 10 }} onClick={() => this.onSave(item.id)} />
</div>
);
}
if (item.children && item.children.length) {
return (
<TreeNode title={item.name}
key={item.id}
id={item.id}
dataRef={item}
parent={item.parent}
group={item.group}
>
{this.renderTreeNodes(item.children)}
</TreeNode>
);
}
return (<TreeNode key={item.id}
title={item.name}
id={item.id}
dataRef={item}
parent={item.parent}
group={item.group}
/>);
});
}
render() {
const { treeData,selectedKeys,expandedKeys,autoExpandParent,isMenuVisible } = this.state;
const { className } = this.props;
return (
<div className={classnames('tree-wrapper', className)}>
<div className="tree-btn">
{/**<div className="add-topo" onClick={this.addTopology}>
<img src="/src/assets/bizView/netTopology/add-topo.png" alt="添加拓扑图" />
</div>*/}
</div>
<Tree
selectedKeys={selectedKeys}
expandedKeys={expandedKeys}
onSelect={this.onSelect}
onExpand={this.onExpand}
autoExpandParent={autoExpandParent}
// onRightClick={this.treeNodeonRightClick}
>
{this.renderTreeNodes(treeData)}
</Tree>
{isMenuVisible && this.getNodeTreeRightClickMenu()}
</div>
);
}
}
TreeComponent.propTypes = {
className: PropTypes.string,
treeData: PropTypes.object,
onSelect: PropTypes.func,
wSelectedKeys: PropTypes.string
};
TreeComponent.defaultProps = {
wSelectedKeys: ''
};
export default TreeComponent;
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { message } from 'amos-framework';
import AmosWebSocket from 'amos-websocket';
import TopologyComponent from './TopologyComponent';
import TreeComponent from './TreeComponent';
import { getDyTopoAction,updateDyTopoAction } from './../../../services/dynamicRingService';
import SysWsURL from './../../../consts/wsUrlConsts';
class FinancialCityLan extends Component {
constructor(props) {
super(props);
this.state = {
selectedKeys: [],
wSelectedKeys: '',
topologyData: {} //拓扑图数据
};
}
// 拓扑图数据初始化
initTopologyData = (id,value = '') => {
getDyTopoAction(id).then(data => {
if (value === 'refresh') {
message.success('拓扑图刷新成功!');
}
this.setState({
topologyData: data
});
});
}
// 树选择
onSelect = (selectedKeys) => {
this.initTopologyData(selectedKeys);
this.setState({
selectedKeys,
wSelectedKeys: ''
});
}
// 节点数据改变
nodeChange = (e) => {
// console.log(e.model.toJson());
this.updateTopologyData = JSON.parse(e.model.toJson());
}
// 保存节点数据
saveTopologyData = () => {
const { selectedKeys } = this.state;
const { nodeDataArray,linkDataArray } = this.updateTopologyData;
const params = {
treeid: selectedKeys,
nodeData: nodeDataArray,
linkData: linkDataArray
};
updateDyTopoAction(params).then(data => {
message.success('拓扑图保存成功!');
});
}
// 刷新节点
refreshTopologyData = () => {
const { selectedKeys } = this.state;
this.initTopologyData(selectedKeys, 'refresh');
}
// 选择节点
nodeSelectionChanged = (e) => {
// console.log('e',e);
if (e.isSelected) { }
}
// // webSocket 接收消息
handleData = (data) => {
this.onSelect(data);
this.setState({
wSelectedKeys: data
});
}
render() {
const { topologyData,wSelectedKeys } = this.state;
return (
<div className="financialCityLan-dy-wrapper">
<AmosWebSocket
ref={node => this.aws = node}
url={SysWsURL.dyTopoURI}
onMessage={this.handleData}
reconnect
debug
/>
<div className="left-content">
<TreeComponent
onSelect={this.onSelect}
wSelectedKeys={wSelectedKeys}
/>
</div>
<div className="right-content">
<div className="financialCityLan-topo-header">
<div className="financialCityLan-topo-save">
<img src="/src/assets/bizView/netTopology/save.png" alt="保存" onClick={this.saveTopologyData} />
</div>
<div className="financialCityLan-topo-refresh">
<img src="/src/assets/bizView/netTopology/refresh.png" alt="刷新" onClick={this.refreshTopologyData} />
</div>
</div>
<div className="financialCityLan-topo-content">
<TopologyComponent
topologyData={topologyData}
nodeChange={this.nodeChange}
nodeSelectionChanged={this.nodeSelectionChanged}
/>
</div>
</div>
</div>
);
}
}
FinancialCityLan.propTypes = {
};
export default FinancialCityLan;
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { deepEqual, pwdPolicy } from 'amos-tool';
import go from 'amos-gojs';
import classnames from 'classnames';
import { nodeDetailTopoAction } from './../../../services/dynamicRingService';
const goObj = go.GraphObject.make;
const deviceSource = '/src/assets/bizView/dynamicRing';
class TopologyComponent extends Component {
constructor(props) {
super(props);
this.state = {
detailData: []
};
this.diagram = null; //gojs图
this.customEditor = null;
this.updateTopologyData = {};
}
componentDidMount() {
this.renderCanvas();
}
componentDidUpdate(prevProps, prevState) {
const { topologyData } = this.props;
const { nodeData, linkData } = topologyData;
if (!deepEqual(prevProps.topologyData,this.props.topologyData)) {
this.diagram.model = new go.GraphLinksModel(nodeData, linkData);
this.initTop = 0;
this.initLeft = 0;
}
}
// this function is the Node.dragComputation, to limit the movement of the parts
stayInFixedArea = (part, pt, gridpt) => {
let diagram = part.diagram;
if (diagram === null) {return pt;}
// compute the document area without padding
let v = diagram.documentBounds.copy();
v.subtractMargin(diagram.padding);
// get the bounds of the part being dragged
let b = part.actualBounds;
let loc = part.location;
// now limit the location appropriately
let x = Math.max(v.x, Math.min(pt.x, v.right - b.width)) + (loc.x - b.x);
let y = Math.max(v.y, Math.min(pt.y, v.bottom - b.height)) + (loc.y - b.y);
return new go.Point(x, y);
}
// 选择节点
nodeSelectionChanged = (node) => {
this.props.nodeSelectionChanged(node);
}
// 设备资源图片
getDeviceSource = (v) => {
return `${deviceSource}/${v}.png`;
}
// 告警图片
getWarnPic = (v) => {
if (v) {
return '/src/assets/bizView/netTopology/alarm.png';
}
}
// 告警高亮
warnHighlights = (d,v) => {
if (d.warnState) {
this.showWarnHighlights(d, v);
return d.text;
}
return d.text;
}
// 获取线颜色
getLinkColor = (v) => {
if (v) {
return '#FF0000';
}
return 'rgba(0,255,8,1)';
}
showWarnHighlights = (d, v) => {
const oldDom = this[d.key];
this.isDrag = true;
if (oldDom) {
let pos = this.diagram.transformDocToView(go.Point.parse(d.loc));
oldDom.style.width = '100px';
oldDom.style.height = '100px';
oldDom.style.left = `${pos.x + 18}px`;
oldDom.style.top = `${pos.y + 20}px`;
} else {
let pos = this.diagram.transformDocToView(go.Point.parse(d.loc));
let customBox = document.createElement('div');
customBox.style.left = `${pos.x + 10}px`;
customBox.style.top = `${pos.y + 26}px`;
customBox.style.position = 'absolute';
customBox.style.zIndex = 1;
customBox.style.width = '100px';
customBox.style.height = '100px';
customBox.style.backgroundPosition = 'center';
customBox.id = d.key;
customBox.setAttribute('class','amos-help-tip-pulse-second');
this.diagram.div.appendChild(customBox);
}
};
// 更新位置信息
updateTopo = () => {
const { nodeDataArray } = this.updateTopologyData;
let pos;
nodeDataArray.filter(item => item.warnState).map(item => {
pos = this.diagram.transformDocToView(go.Point.parse(item.loc));
this[item.key].style.left = `${pos.x + 18}px`;
this[item.key].style.top = `${pos.y + 20}px`;
});
}
getNodeDetail = (id) => {
nodeDetailTopoAction(id).then(data => {
this.setState({
detailData: data
});
});
}
renderDetail = () => {
const { detailData } = this.state;
return (<div id="toolTipDIV" className="tooltip-content" style={{ position: 'absolute', zIndex: 1000, display: 'none' }}>
{detailData.map(item => {
return (<div key={item.name} className="tooltip-item">
<div className="item-name">{item.name}: </div>
<div className="item-value">{item.value}</div>
</div>);
})}
</div>);
}
// 提示框
showToolTip = (obj, diagram, tool) => {
let toolTipDIV = document.getElementById('toolTipDIV');
let pt = diagram.lastInput.viewPoint;
toolTipDIV.style.left = `${pt.x + 12}px`;
toolTipDIV.style.top = `${pt.y}px`;
toolTipDIV.style.display = 'block';
this.getNodeDetail(obj.data.id);
}
hideToolTip = (diagram, tool) => {
let toolTipDIV = document.getElementById('toolTipDIV');
toolTipDIV.style.display = 'none';
}
renderCanvas = () => {
const { topologyData } = this.props;
const { nodeData, linkData } = topologyData;
const myToolTip = goObj(go.HTMLInfo, {
show: this.showToolTip,
hide: this.hideToolTip
});
this.customEditor = goObj(go.HTMLInfo,{
show: this.showWarnHighlights
});
this.diagram = goObj(go.Diagram, this.refs.goJsDiv, {
// allowHorizontalScroll: false, // disallow scrolling or panning
// allowVerticalScroll: false,
allowZoom: false, // disallow zooming
initialContentAlignment: go.Spot.TopLeft,
initialPosition: new go.Point(0, 0),
'undoManager.isEnabled': true, //// enable undo & redo 是否可撤回
'animationManager.isEnabled': false, // 过渡动画
'textEditingTool.defaultTextEditor': this.customEditor,
// fixedBounds: new go.Rect(0, 0, this.refs.goJsDiv.clientWidth, this.refs.goJsDiv.clientHeight),
ModelChanged: (e) => { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
// console.log(e.model.toJson(), 'model');
this.updateTopologyData = JSON.parse(e.model.toJson());
this.props.nodeChange(e);
}
},
SelectionMoved: (e) => {
setTimeout(()=> {
this.updateTopo();
},0);
},
ViewportBoundsChanged: () => {
setTimeout(()=> {
this.updateTopo();
},0);
}
});
this.diagram.nodeTemplateMap.add('Circle',
goObj(go.Node, 'Vertical',
{
selectionObjectName: 'ICON',
locationObjectName: 'ICON'
},
new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
goObj(go.Panel, 'Auto',
goObj(go.Shape, 'Circle', { name: 'ICON',portId: '',
width: 22, height: 22, strokeWidth: 0,fill: '#009dd9' },
),
),
goObj(go.TextBlock,
{ margin: 15,cursor: 'pointer',font: '15px sans-serif' },
new go.Binding('text', 'text' )),
{
selectionAdornmentTemplate:
goObj(go.Adornment, 'Auto',
goObj(go.Shape, 'Circle',
{ fill: null, stroke: '#fbfb7b', strokeWidth: 3 }),
goObj(go.Placeholder)
) // end Adornment
},
));
this.diagram.nodeTemplateMap.add('Picture',
goObj(go.Node, 'Vertical',
{
locationSpot: go.Spot.Center,
locationObjectName: 'ICON',
selectionObjectName: 'ICON',
// dragComputation: this.stayInFixedArea
selectionChanged: this.nodeSelectionChanged,
toolTip: myToolTip
},
new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
goObj(go.Panel,'Spot',
goObj(go.Shape, 'Rectangle',
{ fill: 'lightgreen', stroke: null, width: 1, height: 1 }),
goObj(go.Picture,
{
width: 65,
height: 45,
alignment: new go.Spot(1, 0, 100 ,0 )
},
new go.Binding('source','warnState',(v) => this.getWarnPic(v))
),
goObj(go.TextBlock,
{
alignment: new go.Spot(1, 0, 100 ,-1),
stroke: 'white',
font: '15px sans-serif'
},
new go.Binding('text', 'warnMessage')
),
),
goObj(go.Picture,
{
margin: 0,
name: 'ICON',
width: 55,
height: 55,
cursor: 'pointer',
portId: ''
},
new go.Binding('source','source',(v) => this.getDeviceSource(v))
),
goObj(go.TextBlock, '无',
{ margin: 3, stroke: 'rgba(63,63,63,1)', font: '14px sans-serif' },
new go.Binding('text','', (v,d) => this.warnHighlights(v,d)),
),
{
selectionAdornmentTemplate:
goObj(go.Adornment, 'Auto',
goObj(go.Shape,
{ fill: null, stroke: '#fbfb7b', strokeWidth: 3 }),
goObj(go.Placeholder)
) // end Adornment
}
)
);
this.diagram.groupTemplate = goObj(go.Group, 'Vertical',
{
resizable: true,
locationObjectName: 'SHAPE',
resizeObjectName: 'SHAPE',
selectionObjectName: 'SHAPE'
// dragComputation: this.stayInFixedArea,
// selectionChanged: this.nodeSelectionChanged
},
new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
goObj(go.TextBlock, // group title
{
width: 100,
height: 24,
font: 'Bold 14px Sans-Serif',
stroke: 'white',
background: '#1c9ad2',
margin: 5,
textAlign: 'center',
verticalAlignment: go.Spot.Center
},
new go.Binding('text')),
goObj(go.Shape, 'Rectangle',
{
name: 'SHAPE',
parameter1: 14,
fill: 'rgba(185,185,185,0.2)',
stroke: 'rgba(28,154,210,1)',
strokeWidth: 1
},
new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify),
)
);
this.diagram.linkTemplate =
goObj(go.Link,
goObj(go.Shape, { strokeWidth: 3 },
new go.Binding('stroke', 'warnState', (v) => this.getLinkColor(v))
)
);
this.diagram.model = new go.GraphLinksModel(nodeData, linkData);
}
render() {
const { className,style, topologyData } = this.props;
const { nodeData = [] } = topologyData || {};
return (
<div ref="goJsDiv" style={style} className={classnames('topology-virtualCloudPlatform', className)}>
{
nodeData.filter(e => e.warnState).map(e => <div className="amos-help-tip-pulse-second warn-node" ref={node => this[e.key] = node} key={e.key} id={e.key} />)
}
{nodeData.length > 0 && this.renderDetail()}
</div>
);
}
}
TopologyComponent.propTypes = {
className: PropTypes.string,
style: PropTypes.object,
topologyData: PropTypes.object,
nodeChange: PropTypes.func,
nodeSelectionChanged: PropTypes.func
};
TopologyComponent.defaultProps = {
style: { height: '100%' },
topologyData: {
nodeData: [],
linkData: []
}
};
export default TopologyComponent;
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Tree,Menu,Icon,Button } from 'amos-antd';
import { deepCopy } from 'amos-tool';
import { getDyTreeAction } from './../../../services/dynamicRingService';
const TreeNode = Tree.TreeNode;
class TreeComponent extends Component {
constructor(props) {
super(props);
this.state = {
treeData: [
{
name: '',
id: '1',
children: []
}
], //树数据
autoExpandParent: true,
selectedKeys: [],
expandedKeys: [],
rightClickNodeTreeItem: {},
isMenuVisible: false
};
this.treeLists = [];
this.activeKey = null;
this.activeValue = '';
}
componentDidMount() {
document.addEventListener('click', this.bindBodyClick, false);
this.initData();
}
componentWillUnmount() {
document.removeEventListener('click', this.bindBodyClick);
}
componentWillReceiveProps(nextProps) {
if (nextProps.wSelectedKeys && nextProps.wSelectedKeys !== this.props.wSelectedKeys) {
this.setState({
selectedKeys: nextProps.wSelectedKeys
});
}
}
// 绑定body
bindBodyClick = (e) => {
e.stopPropagation();
this.setState({
isMenuVisible: false
});
}
// 初始化树数据
initData = (treeData) => {
const { onSelect } = this.props;
const expandedKeysData = [];
getDyTreeAction().then(data => {
data.map(item => {
expandedKeysData.push(item.id);
});
this.treeLists = data;
onSelect(data[0].id);
this.setState({
treeData: data,
selectedKeys: [data[0].id],
expandedKeys: expandedKeysData
});
});
}
// 树选择
onSelect = (selectedKeys,e) => {
const { onSelect } = this.props;
if (!selectedKeys.length) {return;}
if (!e.node.props.parent) {
onSelect(selectedKeys[0]);
}
this.setState({
selectedKeys
});
}
// 树展开
onExpand = (expandedKeys) => {
this.setState({
expandedKeys,
autoExpandParent: false
});
};
// 节点右键事件
treeNodeonRightClick = (e) => {
// if (e.node.props.parent) {
// return;
// }
const x = e.event.currentTarget.offsetLeft + e.event.currentTarget.clientWidth;
const y = e.event.currentTarget.offsetTop;
this.activeKey = e.node.props.id;
this.setState({
rightClickNodeTreeItem: {
pageX: x,
pageY: y,
id: e.node.props.id,
parent: e.node.props.parent
},
isMenuVisible: true
});
}
// 节点右键菜单
getNodeTreeRightClickMenu = () => {
const { rightClickNodeTreeItem } = this.state;
const { pageX, pageY, id, parent } = rightClickNodeTreeItem;
if (!rightClickNodeTreeItem.id) {
return null;
}
const style = {
position: 'absolute',
left: `${pageX}px`,
top: `${pageY}px`
};
const menu = (
<Menu
onClick={(e) => this.handleMenuClick(e, id)}
style={style}
className="tree-right"
>
{!parent && <Menu.Item key='1'><img src="/src/assets/bizView/netTopology/add-node.png" alt="添加子图" className="tree-add-img" />{'添加子图'}</Menu.Item>}
<Menu.Item key='2'><img src="/src/assets/bizView/netTopology/del-node.png" alt="删除子图" className="tree-del-img" />{'删除'}</Menu.Item>
</Menu>
);
return menu;
}
// 选择菜单
handleMenuClick = (value, id) => {
let { expandedKeys } = this.state;
if (!expandedKeys.includes(id)) {
expandedKeys = [...expandedKeys, id];
}
if (value.key === '1') {
this.addNode(id);
} else {
this.deleteNode(id);
}
this.setState({
isMenuVisible: false,
expandedKeys
});
}
// 添加拓扑插件
addTopology = () => {
this.treeLists.push({
name: '',
id: Math.random(100),
isAdd: true,
children: [],
parent: null
});
this.setState({
treeData: this.treeLists
});
}
// 添加节点
addNode = (id) => {
this.treeLists.map(item => {
if (item.id === id) {
item.children.push({
name: '',
id: id + Math.random(100),
isAdd: true,
children: [],
parent: null
});
}
});
this.setState({
treeData: this.treeLists
});
}
onInputChange = (e, id) => {
this.activeValue = e.target.value;
this.changeNode(id, e.target.value, this.treeLists);
this.setState({
treeData: this.treeLists
});
}
// 改变节点
changeNode = (id, value, data) => data.map((item) => {
if (item.isAdd) {
item.name = value;
return;
}
if (item.children.length) {
this.changeNode(id, value, item.children);
}
})
onClose = (id) => {
this.closeNode(id, this.treeLists);
// this.setState({
// treeData: this.treeLists
// });
this.initData();
}
// 关闭节点
closeNode = (id, data) => data.map((item,index) => {
if (item.id === id) {
data.splice(index, 1);
return;
}
if (item.children.length) {
this.closeNode(id, item.children);
}
})
// 保存节点
onSave = () => {
const params = {
name: this.activeValue,
parent: this.activeKey
};
addWebTreeAction(params).then(() => {
this.initData();
});
}
// 删除节点
deleteNode = (id) => {
delWebTreeAction(id).then(() => {
this.initData();
});
}
renderTreeNodes = (data) => {
let operableTreeData = deepCopy(data);
return operableTreeData.map((item) => {
if (item.isAdd) {
item.name = (
<div>
<input
value={item.name}
onChange={(e) => this.onInputChange(e, item.id)}
/>
<Icon type='close' style={{ marginLeft: 10 }} onClick={() => this.onClose(item.id)} />
<Icon type='check' style={{ marginLeft: 10 }} onClick={() => this.onSave(item.id)} />
</div>
);
}
if (item.children && item.children.length) {
return (
<TreeNode title={item.name}
key={item.id}
id={item.id}
dataRef={item}
parent={item.parent}
group={item.group}
>
{this.renderTreeNodes(item.children)}
</TreeNode>
);
}
return (<TreeNode key={item.id}
title={item.name}
id={item.id}
dataRef={item}
parent={item.parent}
group={item.group}
/>);
});
}
render() {
const { treeData,selectedKeys,expandedKeys,autoExpandParent,isMenuVisible } = this.state;
const { className } = this.props;
return (
<div className={classnames('tree-wrapper', className)}>
<div className="tree-btn">
{/**<div className="add-topo" onClick={this.addTopology}>
<img src="/src/assets/bizView/netTopology/add-topo.png" alt="添加拓扑图" />
</div>*/}
</div>
<Tree
selectedKeys={selectedKeys}
expandedKeys={expandedKeys}
onSelect={this.onSelect}
onExpand={this.onExpand}
autoExpandParent={autoExpandParent}
// onRightClick={this.treeNodeonRightClick}
>
{this.renderTreeNodes(treeData)}
</Tree>
{isMenuVisible && this.getNodeTreeRightClickMenu()}
</div>
);
}
}
TreeComponent.propTypes = {
className: PropTypes.string,
treeData: PropTypes.object,
onSelect: PropTypes.func,
wSelectedKeys: PropTypes.string
};
TreeComponent.defaultProps = {
wSelectedKeys: ''
};
export default TreeComponent;
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { message } from 'amos-framework';
import AmosWebSocket from 'amos-websocket';
import TopologyComponent from './TopologyComponent';
import TreeComponent from './TreeComponent';
import { getDyTopoAction,updateDyTopoAction } from './../../../services/dynamicRingService';
import SysWsURL from './../../../consts/wsUrlConsts';
class VirtualCloudPlatform extends Component {
constructor(props) {
super(props);
this.state = {
selectedKeys: [],
wSelectedKeys: '',
topologyData: {} //拓扑图数据
};
}
// 拓扑图数据初始化
initTopologyData = (id,value = '') => {
getDyTopoAction(id).then(data => {
if (value === 'refresh') {
message.success('拓扑图刷新成功!');
}
this.setState({
topologyData: data
});
});
}
// 树选择
onSelect = (selectedKeys) => {
this.initTopologyData(selectedKeys);
this.setState({
selectedKeys,
wSelectedKeys: ''
});
}
// 节点数据改变
nodeChange = (e) => {
// console.log(e.model.toJson());
this.updateTopologyData = JSON.parse(e.model.toJson());
}
// 保存节点数据
saveTopologyData = () => {
const { selectedKeys } = this.state;
const { nodeDataArray,linkDataArray } = this.updateTopologyData;
const params = {
treeid: selectedKeys,
nodeData: nodeDataArray,
linkData: linkDataArray
};
updateDyTopoAction(params).then(data => {
message.success('拓扑图保存成功!');
});
}
// 刷新节点
refreshTopologyData = () => {
const { selectedKeys } = this.state;
this.initTopologyData(selectedKeys, 'refresh');
}
// 选择节点
nodeSelectionChanged = (e) => {
// console.log('e',e);
if (e.isSelected) { }
}
// // webSocket 接收消息
handleData = (data) => {
this.onSelect(data);
this.setState({
wSelectedKeys: data
});
}
render() {
const { topologyData,wSelectedKeys } = this.state;
return (
<div className="virtualCloudPlatform-dy-wrapper">
<AmosWebSocket
ref={node => this.aws = node}
url={SysWsURL.dyTopoURI}
onMessage={this.handleData}
reconnect
debug
/>
<div className="left-content">
<TreeComponent
onSelect={this.onSelect}
wSelectedKeys={wSelectedKeys}
/>
</div>
<div className="right-content">
<div className="virtualCloudPlatform-topo-header">
<div className="virtualCloudPlatform-topo-save">
<img src="/src/assets/bizView/netTopology/save.png" alt="保存" onClick={this.saveTopologyData} />
</div>
<div className="virtualCloudPlatform-topo-refresh">
<img src="/src/assets/bizView/netTopology/refresh.png" alt="刷新" onClick={this.refreshTopologyData} />
</div>
</div>
<div className="virtualCloudPlatform-topo-content">
<TopologyComponent
topologyData={topologyData}
nodeChange={this.nodeChange}
nodeSelectionChanged={this.nodeSelectionChanged}
/>
</div>
</div>
</div>
);
}
}
VirtualCloudPlatform.propTypes = {
};
export default VirtualCloudPlatform;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment