Commit f9dd2a4c authored by shanqiyun's avatar shanqiyun

新增任务流程组件

parent 011fb531
...@@ -220,7 +220,7 @@ export const FasSerUrl = { ...@@ -220,7 +220,7 @@ export const FasSerUrl = {
getTreeNodeTypeUrl: completePrefix(baseURI, 'api/riskModel/riskSource/getChildTypeByPid?riskSourceId={riskSourceId}'),// 根据节点ID获取子节点可能的类型 getTreeNodeTypeUrl: completePrefix(baseURI, 'api/riskModel/riskSource/getChildTypeByPid?riskSourceId={riskSourceId}'),// 根据节点ID获取子节点可能的类型
getAllUserUrl: completePrefix(baseURI, 'api/common/user/list'),//获取所有用户 getAllUserUrl: completePrefix(baseURI, 'api/common/user/list'),//获取所有用户
queryFmeaControlObjUrl: completePrefix(baseURI, 'api/riskModel/fmea/{ids}/controlObjCount'),//根据fmea id查询关联对象个数 queryFmeaControlObjUrl: completePrefix(baseURI, 'api/riskModel/fmea/{ids}/controlObjCount'),//根据fmea id查询关联对象个数
queryTopographyUrl: completePrefix(baseURI, 'api/Topography/{appId}'),//获取Topo图数据 queryTopographyUrl: completePrefix(baseURI, 'api/Topography/query/{type}/{appId}'),//获取Topo图数据
updateTopographyUrl: completePrefix(baseURI, 'api/Topography/updateTopo'),//更新Topo图数据 updateTopographyUrl: completePrefix(baseURI, 'api/Topography/updateTopo'),//更新Topo图数据
queryNodeDetailUrl: completePrefix(baseURI, 'api/Topography/detail/{id}'),//获取node节点详情 queryNodeDetailUrl: completePrefix(baseURI, 'api/Topography/detail/{id}'),//获取node节点详情
saveNodeDetailUrl:completePrefix(baseURI, 'api/Topography/detail'),//保存nodeDetail详情 saveNodeDetailUrl:completePrefix(baseURI, 'api/Topography/detail'),//保存nodeDetail详情
......
...@@ -197,8 +197,8 @@ export const queryAllUserAction = () => { ...@@ -197,8 +197,8 @@ export const queryAllUserAction = () => {
/** /**
* 获取节点 * 获取节点
*/ */
export const queryTopographyAction = (appId) => { export const queryTopographyAction = (type,appId) => {
return commonGet(formatUrl(FasSerUrl.queryTopographyUrl,{ appId })); return commonGet(formatUrl(FasSerUrl.queryTopographyUrl,{ type,appId }));
}; };
/** /**
......
...@@ -2,3 +2,4 @@ ...@@ -2,3 +2,4 @@
@import './plan.scss'; @import './plan.scss';
@import './leaderStruct.scss'; @import './leaderStruct.scss';
@import './text.scss'; @import './text.scss';
@import './taskTopo.scss';
.publish-view-task{
width: 300px;
right: 0 ; .task-topo{
top: 82 ;
bottom: 0 ;
overflow: auto !important;
position: absolute;
}
.task-topo{
height: 100%; height: 100%;
width: 300px; width: 300px;
right: 0 ; right: 0 ;
...@@ -76,4 +67,4 @@ ...@@ -76,4 +67,4 @@
} }
} }
} }
} }
import React , { Component } from 'react';
import _amosTool from 'amos-tool';
import { Modal,AmosAlert,Button,message } from 'amos-framework';
import 'amos-iot-webstudio/lib/styles';// 独立使用,需要引入样式
import go from 'amos-gojs';
import { queryTopographyAction, updateTopographyAction, nodeDetailTopoAction, deleteTopoAction } from './../../../services/preControlService';
const goObj = go.GraphObject.make;
/**
* 任务TOPO图
*
* @class TaskTopo
* @extends {Component}
*/
class TaskTopo extends Component {
constructor(props){
super(props);
this.state = {
nodeData: [],
linkData: [],
type: '2', //TOPO图类型 2 任务流程
selectNode: {},
selectNodeType: '',
};
this.diagram = null; //gojs图
this.updateTopologyData = {};
}
componentDidMount() {
let { appId } = this.props;
this.fetchData(appId);
}
fetchData = (appId) => {
queryTopographyAction(this.state.type, appId).then(res =>{
this.setState({nodeData: res.nodeData , linkData: res.linkData })
this.renderCanvas();
});
}
makePort = (name, spot, output, input) => {
// the port is basically just a small transparent square
return goObj(go.Shape, "Circle",
{
fill: null, // not seen, by default; set to a translucent gray by showSmallPorts, defined below
stroke: null,
desiredSize: new go.Size(7, 7),
alignment: spot, // align the port on the main Shape
alignmentFocus: spot, // just inside the Shape
portId: name, // declare this object to be a "port"
fromSpot: spot, toSpot: spot, // declare where links may connect at this port
fromLinkable: output, toLinkable: input, // declare whether the user may draw links to/from here
cursor: "pointer" // show a different cursor to indicate potential link point
});
}
//展示 连接点
showSmallPorts = (e,node) => {
node && node.ports.each(function(port) {
if (port.portId !== "") { // don't change the default port, which is the big shape
port.fill = "rgba(0,0,0,.3)";
}
});
}
hideSmallPorts = (e,node) => {
node && node.ports.each(function(port) {
if (port.portId !== "") { // don't change the default port, which is the big shape
port.fill = null;
}
});
}
// showContextMenu = (obj, diagram, tool) => {
// let cxElement = document.getElementById("contextMenu");
// var cmd = diagram.commandHandler;
// var hasMenuItem = false;
// if (cmd.canDeleteSelection()) {
// document.getElementById("delete").style.display = "block";
// hasMenuItem = true;
// } else {
// document.getElementById("delete").style.display = "none";
// }
// // Now show the whole context menu element
// if (hasMenuItem) {
// cxElement.classList.add("show-menu");
// // we don't bother overriding positionContextMenu, we just do it here:
// var mousePt = diagram.lastInput.viewPoint;
// cxElement.style.left = mousePt.x + 5 + "px";
// cxElement.style.top = mousePt.y + "px";
// }
// // Optional: Use a `window` click listener with event capture to
// // remove the context menu if the user clicks elsewhere on the page
// window.addEventListener("click", this.hideCX, true);
// }
// hideContextMenu = () => {
// let cxElement = document.getElementById("contextMenu");
// cxElement.classList.remove("show-menu");
// // Optional: Use a `window` click listener with event capture to
// // remove the context menu if the user clicks elsewhere on the page
// window.removeEventListener("click", this.hideCX, true);
// }
// 选择节点
nodeSelectionChanged = (node) => {
if(node.isSelected){
console.log(node.data,'selected');
if(node.type.name == "Link"){// 设置主任务连线样式
let fromNode = this.diagram.model.findNodeDataForKey(node.data.from);
let toNode = this.diagram.model.findNodeDataForKey(node.data.to);
if(fromNode.category == "mainTask" && toNode.category == "mainTask"){
this.diagram.model.setDataProperty(node,"category", "mainLink");
}
}
this.setState({ selectNode: node.data || {}, selectNodeType: node.type.name || ''});
}else{
this.setState({ selectNode: {}, selectNodeType: ''});
}
}
renderCanvas = () => {
let { nodeData, linkData } = this.state;
// let cxElement = document.getElementById("contextMenu");
// let myContextMenu = goObj(go.HTMLInfo, {
// show: this.showContextMenu,
// hide: this.hideContextMenu
// });
this.diagram = goObj(go.Diagram, this.refs.taskGoJsDiv, {
contentAlignment: go.Spot.TopLeft,
initialPosition: new go.Point(0, 0),
'undoManager.isEnabled': true, //// enable undo & redo 是否可撤回
'animationManager.isEnabled': false, // 过渡动画
ModelChanged: (e,value) => { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
this.updateTopologyData = JSON.parse(e.model.toJson());
}
}
});
this.diagram.groupTemplateMap.add("mainTask",
goObj(go.Group, "Auto",
{
resizable: true,
locationObjectName: "GROUP",
resizeObjectName: 'GROUP',
selectionObjectName: 'GROUP',
selectionChanged: this.nodeSelectionChanged,
},
new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
goObj(go.Shape, "RoundedRectangle",
{
name: "GROUP",
fill: "rgba(16,142,233, 0.4)", strokeWidth: 1.5, parameter1: 20,
spot1: go.Spot.TopLeft, spot2: go.Spot.BottomRight,minSize: new go.Size(290, 150)
},
new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify),
),
goObj(go.Panel, "Vertical",
{ margin: 5 },
goObj(
go.TextBlock,
{ font: "bold 10pt sans-serif", margin: new go.Margin(0, 0, 5, 0),editable: true, },
new go.Binding("text").makeTwoWay()
),
goObj(go.Shape,
{ name: "BODY", opacity: 0 })
),
{
selectionAdornmentTemplate:
goObj(go.Adornment, 'Auto',
goObj(go.Shape, 'RoundedRectangle',
{ fill: null, stroke: '#108ee9', strokeWidth: 3, parameter1: 20,
spot1: go.Spot.TopLeft, spot2: go.Spot.BottomRight}),
goObj(go.Placeholder)
) // end Adornment
},
this.makePort("T", go.Spot.Top, false, true),
// this.makePort("L", go.Spot.Left, true, true),
// this.makePort("R", go.Spot.Right, true, true),
this.makePort("B", go.Spot.Bottom, true, false),
{
mouseEnter: this.showSmallPorts,
mouseLeave: this.hideSmallPorts,
},
)
);
this.diagram.nodeTemplateMap.add('subTask',
goObj(go.Node, 'Spot',
{
locationSpot: go.Spot.Center,
selectionChanged: this.nodeSelectionChanged,
// contextMenu: myContextMenu
},
new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
goObj(go.Panel,'Auto',
goObj(go.Shape, 'Rectangle',
{ fill: 'white' }),
goObj(go.TextBlock,
{
margin: 8,
font: '12px sans-serif',
editable: true,
},
new go.Binding('text', 'text').makeTwoWay()
),
),
{
selectionAdornmentTemplate:
goObj(go.Adornment, 'Auto',
goObj(go.Shape, 'Rectangle',
{ fill: null, stroke: '#108ee9', strokeWidth: 2 }),
goObj(go.Placeholder)
) // end Adornment
},
this.makePort("T", go.Spot.Top, true, true),
this.makePort("L", go.Spot.Left, true, true),
this.makePort("R", go.Spot.Right, true, true),
this.makePort("B", go.Spot.Bottom, true, true),
{
mouseEnter: this.showSmallPorts,
mouseLeave: this.hideSmallPorts,
},
)
);
this.diagram.linkTemplateMap.add("",
goObj(go.Link,
{ routing: go.Link.Orthogonal,
corner: 10 ,
relinkableFrom: true,
relinkableTo: true,
reshapable: true,
selectionChanged: this.nodeSelectionChanged,
},
goObj(go.Shape, { strokeWidth: 2 }),
goObj(go.Shape, { toArrow: "OpenTriangle" })
));
this.diagram.linkTemplateMap.add("mainLink",
goObj(go.Link,
{ toShortLength: 12, toEndSegmentLength: 12 },
goObj(go.Shape,
{ strokeWidth: 10, stroke: 'rgba(255,140,0)' },),
goObj(go.Shape, // arrowhead
{ toArrow: "Triangle", stroke: null, scale: 2, fill: 'rgba(255,140,0)' },
)
)
);
this.diagram.model = goObj(go.GraphLinksModel,
{
linkFromPortIdProperty: 'fromPort', // required information:
linkToPortIdProperty: 'toPort', // identifies data property names
nodeDataArray: nodeData || [],
linkDataArray: linkData || []
}
);
// this.diagram.contextMenu = myContextMenu;
// cxElement.addEventListener("contextmenu", function(e) {
// e.preventDefault();
// return false;
// }, false);
}
// hideCX = () => {
// // if (this.diagram.currentTool instanceof go.ContextMenuTool) {
// // this.display.currentTool.doCancel();
// // }
// }
onButtonClick = (key) => {
const { selectNode, selectNodeType } = this.state;
if(key === 'mainTask'){//添加主任务
this.addMainTaskNode();
}else if(key === 'subTask'){//添加子任务
if( selectNode.category === 'mainTask'){
this.addSubTaskNode(selectNode);
}else{
message.danger('请选择一个主任务');
}
}else if (key === 'save'){
this.saveTopography();
}else if(key === 'delete'){
if(selectNode && selectNodeType){
selectNode.id && deleteTopoAction(selectNode.id, selectNodeType).then(data =>{
message.success('删除成功!');
});
this.diagram.commandHandler.deleteSelection();
this.setState({ selectNode: {}, selectNodeType: '' });
}else{
message.danger('请选择节点!');
}
}
}
addMainTaskNode = () => {
let mainNode = { category:'mainTask', text:'主任务',isGroup: true };
let loc = '';
let nodes = JSON.parse(this.diagram.model.toJson()).nodeDataArray || [];
let groupNodes = nodes.filter(e =>{ return e.isGroup == true });
if(groupNodes.length > 0){
let x,y,height = 0;
groupNodes.forEach(e => {
let locArr = e.loc.split(' ');
let sizeArr = e.size ? e.size.split(' ') : ['290','150'];
x = x > Number(locArr[0]) ? x : Number(locArr[0]);
y = y > Number(locArr[1]) ? y : Number(locArr[1]);
height = y > Number(locArr[1]) ? height : Number(sizeArr[1]);//竖直排列 y
});
loc = x + ' ' + (y + height + 25);
}
mainNode.loc = loc;
this.diagram.model.addNodeData(mainNode);
}
//组下 新增子任务
addSubTaskNode = ( groupNode ) => {
let groupLocArr = groupNode.loc.split(' ');
let groupSizeArr = groupNode.size ? groupNode.size.split(' ') : ['290','150'];
let loc = '';
let subNode = { category:'subTask', text:'子任务' ,group: groupNode.key };
let nodes = JSON.parse(this.diagram.model.toJson()).nodeDataArray || [];
let groupChildNodes = nodes.filter(e =>{ return e.group == groupNode.key });
if(groupChildNodes.length > 0){
let x,y = 0;
groupChildNodes.forEach(e => {
let arr = e.loc.split(' ');
x = x > Number(arr[0]) ? x : Number(arr[0]);
y = y > Number(arr[1]) ? y : Number(arr[1]);
});
// if(Number(x) + 100 < Number(groupLocArr[0]) + Number(groupSizeArr[0])
// && Number(y) + 50 < Number(groupLocArr[1]) + Number(groupSizeArr[1])){
loc = (x + 15) + ' ' + (y + 15);
// }else{
// loc = (Number(groupLocArr[0]) + 40) + ' ' + (Number(groupLocArr[1]) + 40);
// }
}else{
loc = (Number(groupLocArr[0]) + 40) + ' ' + (Number(groupLocArr[1]) + 40);
}
subNode.loc = loc;
this.diagram.model.addNodeData(subNode);
}
saveTopography = () => {
const { nodeDataArray,linkDataArray } = this.updateTopologyData;
const params = {
appId: this.props.appId,
type: this.state.type,
nodeData: nodeDataArray,
linkData: linkDataArray,
};
updateTopographyAction(params).then(data => {
AmosAlert.success('提示', '拓扑图保存成功!');
this.diagram.model = goObj(go.GraphLinksModel,
{
linkFromPortIdProperty: 'fromPort', // required information:
linkToPortIdProperty: 'toPort', // identifies data property names
nodeDataArray: data.nodeData || [],
linkDataArray: data.linkData || []
});
}).catch(e => {
AmosAlert.error('错误', '保存失败');
});;
}
// cxcommand = (event, val) => {
// if (val === undefined) val = event.currentTarget.id;
// switch (val) {
// case "delete": diagram.commandHandler.deleteSelection(); break;
// }
// // this.diagram.currentTool.stopTool();
// }
render() {
return (
<div className='task-topo'>
<div className='task-topo-button'>
<Button size='sm' onClick={() => this.onButtonClick('mainTask')}>主任务</Button>
<Button size='sm' onClick={() => this.onButtonClick('subTask')}>子任务</Button>
<Button size='sm' onClick={() => this.onButtonClick('save')}>保存</Button>
<Button size='sm' onClick={() => this.onButtonClick('delete')}>删除</Button>
</div>
<div className='task-topo-content'>
<div ref="taskGoJsDiv" className='task-topo-diagram'>
{/* <ul id="contextMenu" className="task-topo-ctxmenu">
<li id="delete" className="task-topo-menu-item" onClick={this.cxcommand(event)}>Delete</li>
</ul> */}
</div>
</div>
</div>
);
}
}
export default TaskTopo;
...@@ -28,7 +28,8 @@ class LeaderStruct extends Component { ...@@ -28,7 +28,8 @@ class LeaderStruct extends Component {
toolBarFlag: '', toolBarFlag: '',
selectNode: {}, selectNode: {},
selectNodeType: '', selectNodeType: '',
rightGridData: [] rightGridData: [],
type: '1',//topo 类型 1 领导架构
}; };
this.diagram = null; //gojs图 this.diagram = null; //gojs图
this.myPalette = null; //工具栏 this.myPalette = null; //工具栏
...@@ -41,7 +42,7 @@ class LeaderStruct extends Component { ...@@ -41,7 +42,7 @@ class LeaderStruct extends Component {
} }
fetchData = (appId) => { fetchData = (appId) => {
queryTopographyAction(appId).then(res =>{ queryTopographyAction(this.state.type, appId).then(res =>{
this.setState({nodeData: res.nodeData , linkData: res.linkData }) this.setState({nodeData: res.nodeData , linkData: res.linkData })
this.renderCanvas(); this.renderCanvas();
}); });
...@@ -267,6 +268,7 @@ class LeaderStruct extends Component { ...@@ -267,6 +268,7 @@ class LeaderStruct extends Component {
const { nodeDataArray,linkDataArray } = this.updateTopologyData; const { nodeDataArray,linkDataArray } = this.updateTopologyData;
const params = { const params = {
appId: this.props.location.state.appId, appId: this.props.location.state.appId,
type: this.state.type,
nodeData: nodeDataArray, nodeData: nodeDataArray,
linkData: linkDataArray, linkData: linkDataArray,
nodeDetail: nodeDetail nodeDetail: nodeDetail
......
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