import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Modal, Button, notification, Spin } from 'antd'
|
import { ForkOutlined } from '@ant-design/icons'
|
|
import Api from '@/api'
|
import G6 from "@antv/g6"
|
import MKEmitter from '@/utils/events.js'
|
import './index.scss'
|
|
class Versions extends Component {
|
static propTpyes = {
|
config: PropTypes.object,
|
MenuId: PropTypes.string
|
}
|
|
state = {
|
visible: false,
|
loading: false,
|
empty: false
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
trigger = () => {
|
const { MenuId, config } = this.props
|
|
this.setState({visible: true, loading: true, empty: false}, () => {
|
let param = {
|
func: 's_get_menu_used_list',
|
TypeCharOne: sessionStorage.getItem('kei_no'),
|
typename: sessionStorage.getItem('typename'),
|
par_menuid: MenuId
|
}
|
|
Api.getCloudConfig(param).then(result => {
|
if (!result.status) {
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
|
this.setState({empty: true, loading: false})
|
|
return
|
}
|
|
let data = {
|
label: config.MenuName || '空',
|
id: MenuId,
|
MenuID: config.MenuID,
|
MenuName: config.MenuName,
|
MenuNo: config.MenuNo,
|
children: []
|
}
|
|
let allMenus = JSON.parse(sessionStorage.getItem('allMenus'))
|
let menuObj = {}
|
|
allMenus.forEach(item => {
|
menuObj[item.MenuID] = item
|
})
|
|
if (result.par_data) {
|
result.par_data.forEach((item, i) => {
|
|
let cell = {
|
label: item.par_menuname,
|
id: 'par' + i,
|
MenuID: item.par_menuid,
|
MenuName: item.par_menuname,
|
MenuNo: item.par_menuno,
|
deleted: false,
|
direction: 'left'
|
}
|
|
if (menuObj[item.par_menuid]) {
|
cell.color = '#5AD8A6'
|
|
cell.label = menuObj[item.par_menuid].MenuName || item.par_menuname
|
cell.MenuName = menuObj[item.par_menuid].MenuName || item.par_menuname
|
cell.MenuNo = menuObj[item.par_menuid].MenuNo || item.par_menuno
|
} else {
|
cell.color = '#dddddd'
|
cell.deleted = true
|
}
|
|
data.children.push(cell)
|
})
|
}
|
|
if (result.used_data) {
|
result.used_data.forEach((item, i) => {
|
|
let cell = {
|
label: item.used_menuname,
|
id: 'sub' + i,
|
MenuID: item.used_menuid,
|
MenuName: item.used_menuname,
|
MenuNo: '',
|
deleted: false,
|
direction: 'right'
|
}
|
|
if (menuObj[item.used_menuid]) {
|
cell.color = '#5AD8A6'
|
|
cell.label = menuObj[item.used_menuid].MenuName || item.used_menuname
|
cell.MenuName = menuObj[item.used_menuid].MenuName || item.used_menuname
|
cell.MenuNo = menuObj[item.used_menuid].MenuNo
|
} else {
|
cell.color = '#dddddd'
|
cell.deleted = true
|
}
|
|
data.children.push(cell)
|
})
|
}
|
|
if (data.children.length === 0) {
|
this.setState({empty: true, loading: false})
|
} else {
|
this.setState({loading: false})
|
this.getForks(data)
|
}
|
})
|
})
|
}
|
|
changeMenu = (menu) => {
|
if (menu.depth === 0) return
|
|
MKEmitter.emit('changeEditMenu', menu)
|
}
|
|
getForks = (data) => {
|
const { Util } = G6
|
const that = this
|
|
G6.registerNode(
|
'dice-mind-map-root', {
|
jsx: (cfg) => {
|
const width = Util.getTextSize(cfg.label, 14)[0] + 12;
|
const stroke = cfg.style.stroke || '#096dd9';
|
|
return `
|
<group>
|
<rect draggable="true" style={{width: ${width}, height: 30, stroke: ${stroke}, radius: 4}} keyshape>
|
<text style={{ fontSize: 14, marginLeft: 6, marginTop: 6 }}>${cfg.label}</text>
|
</rect>
|
</group>
|
`;
|
},
|
getAnchorPoints() {
|
return [
|
[0, 0.5],
|
[1, 0.5],
|
];
|
},
|
},
|
'single-node',
|
);
|
|
G6.registerNode(
|
'dice-mind-map-leaf', {
|
jsx: (cfg) => {
|
const width = Util.getTextSize(cfg.label, 12)[0] + 24;
|
const color = cfg.color;
|
|
return `
|
<group>
|
<rect draggable="true" style={{width: ${width}, height: 26, cursor: 'pointer', fill: 'transparent' }}>
|
<text style={{ fontSize: 12, fill: ${cfg.deleted ? '#959595' : 'black'}, cursor: 'pointer', marginLeft: 12, marginTop: 6 }}>${cfg.label}</text>
|
</rect>
|
<rect style={{ fill: ${color}, width: ${width}, cursor: 'pointer', height: 2, x: 0, y: 32 }} />
|
</group>
|
`;
|
},
|
getAnchorPoints() {
|
return [
|
[0, 0.965],
|
[1, 0.965],
|
];
|
},
|
},
|
'single-node',
|
);
|
G6.registerBehavior('dice-mindmap', {
|
getEvents() {
|
return {
|
'node:dblclick': 'editNode',
|
};
|
},
|
editNode(evt) {
|
const item = evt.item;
|
const model = item.get('model');
|
|
that.changeMenu(model)
|
}
|
});
|
G6.registerBehavior('scroll-canvas', {
|
getEvents: function getEvents() {
|
return {
|
wheel: 'onWheel',
|
};
|
},
|
|
onWheel: function onWheel(ev) {
|
const {
|
graph
|
} = this;
|
if (!graph) {
|
return;
|
}
|
if (ev.ctrlKey) {
|
const canvas = graph.get('canvas');
|
const point = canvas.getPointByClient(ev.clientX, ev.clientY);
|
let ratio = graph.getZoom();
|
if (ev.wheelDelta > 0) {
|
ratio += ratio * 0.05;
|
} else {
|
ratio *= ratio * 0.05;
|
}
|
graph.zoomTo(ratio, {
|
x: point.x,
|
y: point.y,
|
});
|
} else {
|
const x = ev.deltaX || ev.movementX;
|
const y = ev.deltaY || ev.movementY || (-ev.wheelDelta * 125) / 3;
|
graph.translate(-x, -y);
|
}
|
ev.preventDefault();
|
},
|
});
|
|
const dataTransform = (data) => {
|
const changeData = (d, level = 0, color) => {
|
const data = {
|
...d,
|
};
|
switch (level) {
|
case 0:
|
data.type = 'dice-mind-map-root';
|
break;
|
default:
|
data.type = 'dice-mind-map-leaf';
|
break;
|
}
|
|
data.hover = false;
|
|
if (color) {
|
data.color = color;
|
}
|
|
if (d.children) {
|
data.children = d.children.map((child) => changeData(child, level + 1, data.color));
|
}
|
return data;
|
};
|
return changeData(data);
|
};
|
|
const tree = new G6.TreeGraph({
|
container: 'mountNode',
|
width: 600,
|
height: 350,
|
fitView: true,
|
fitViewPadding: [10, 20],
|
layout: {
|
type: 'mindmap',
|
direction: 'H',
|
getHeight: () => {
|
return 16;
|
},
|
getWidth: (node) => {
|
return node.level === 0 ?
|
Util.getTextSize(node.label, 16)[0] + 12 :
|
Util.getTextSize(node.label, 12)[0];
|
},
|
getVGap: () => {
|
return 10;
|
},
|
getHGap: () => {
|
return 60;
|
},
|
getSide: (node) => {
|
return node.data.direction;
|
},
|
},
|
defaultEdge: {
|
type: 'cubic-horizontal',
|
style: {
|
lineWidth: 2,
|
},
|
},
|
minZoom: 0.5,
|
modes: {
|
default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'],
|
},
|
});
|
|
tree.data(dataTransform(data));
|
|
tree.render();
|
}
|
|
render() {
|
const { visible, loading, empty } = this.state
|
|
return (
|
<div style={{display: 'inline-block'}}>
|
<Button style={{borderColor: 'orange', color: 'orange'}} onClick={this.trigger}><ForkOutlined /> 页面关系图</Button>
|
<Modal
|
title=""
|
wrapClassName="view-nodes-modal"
|
visible={visible}
|
width={700}
|
closable={false}
|
maskClosable={false}
|
footer={[]}
|
destroyOnClose
|
>
|
<div className="header">页面关系图</div>
|
<div className="wrap">
|
{loading ? <Spin size="large" /> : null}
|
{empty ? <div className="empty">未查询到页面关联菜单。</div> : null}
|
<div className="mountNode" id="mountNode"></div>
|
</div>
|
<div className="footer">
|
<Button key="cancel" onClick={() => { this.setState({ visible: false })}}>关闭</Button>
|
</div>
|
</Modal>
|
</div>
|
)
|
}
|
}
|
|
export default Versions
|