515 lines
20 KiB
JavaScript
515 lines
20 KiB
JavaScript
$(function(){
|
|
if (methodId != 'process.subprocess') { // 如果当前打开的模型不是端到端总图 那么整个js也没有执行的必要
|
|
return;
|
|
}
|
|
|
|
const subProcess = new SubProcess(Model, ruuid, sid);
|
|
|
|
subProcess.init();
|
|
|
|
window.subProcess = subProcess;
|
|
});
|
|
|
|
class SubProcess {
|
|
// 构造函数
|
|
constructor(Model, ruuid, sid){
|
|
this.Model = Model;
|
|
this.repositoryId = ruuid;
|
|
this.sid = sid;
|
|
this.scopeEle = {}; // 范围框元素以及其内部元素
|
|
this.movingEle = null; // 范围框内移动中的元素
|
|
this.scopeRang = null; // 范围限制框左右两边以及上下两边的坐标 x1 x2 y1 y2
|
|
}
|
|
|
|
init(){
|
|
this.shapeIconRender();
|
|
this.handleScopeShapeEvent();
|
|
this.linkerBoxPointerEvent();
|
|
this.scopeShapeRenderTitle(this.Model.define.elements);
|
|
|
|
this.sourceNodeDiffMsgHandle();
|
|
}
|
|
|
|
linkerBoxPointerEvent(){
|
|
// 连线框 鼠标指针样式设置 防止因为连线z-index层级较高 会导致节点展开图标点击不到
|
|
$('.shape_box.linker_box').css({
|
|
'pointer-events': 'none'
|
|
});
|
|
}
|
|
|
|
// 子流程节点以及范围框 渲染关联文件跳转链接
|
|
shapeIconRender(){
|
|
let elements = this.Model.define.elements;
|
|
for (let shapeId in elements) {
|
|
let shape = elements[shapeId];
|
|
if (shape.name == 'linker') continue; // 当前元素为连线的话 直接略过
|
|
if (shape.name == 'scopeLimitation' || shape.name == 'subProcess'){ // 只有子流程或者范围选择框才有对应的图标渲染
|
|
if (shape.name == 'subProcess' || shape.name == 'scopeLimitation') {
|
|
let expandIcon = "<span id='icon_"+shapeId+"' class='iconfont icon-lianjietiaozhuan' style='position: absolute;cursor: pointer;'></span>";
|
|
$('#'+shapeId).append(expandIcon);
|
|
$('#icon_'+shapeId).on('click', '', {shape: shape, sid: this.sid}, this.subProcessNodeLink);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 子流程节点拖拽到画布后 渲染展开按钮
|
|
shapeOpenIconRender(ele){
|
|
if (ele.name != 'subProcess'){
|
|
return;
|
|
}
|
|
let shapeId = ele.id;
|
|
let shape = this.Model.getShapeById(shapeId);
|
|
let expandIcon = "<span id='icon_"+shapeId+"' class='iconfont icon-lianjietiaozhuan' style='position: absolute;cursor: pointer;'></span>";
|
|
$('#'+shapeId).append(expandIcon);
|
|
$('#icon_'+shapeId).on('click', '', {shape: shape, sid: this.sid}, this.subProcessNodeLink);
|
|
}
|
|
|
|
// 范围选择框的事件绑定处理
|
|
handleScopeShapeEvent(){
|
|
let c = $("#designer_canvas");
|
|
c.off("mousemove.scope").on("mousemove.scope",function (a) {
|
|
let b = Utils.getRelativePos(a.pageX, a.pageY, c); // 实时获取鼠标移动的坐标
|
|
let j = Utils.getShapeByPosition(b.x, b.y); // 根据鼠标当前移动的位置获取当前图形 如果有的话
|
|
// console.log("当前图形", j);
|
|
if (j != null) {
|
|
let tempSelectArr = [];
|
|
if (j.shape.name == 'scopeLimitation'){
|
|
let range = {
|
|
x: j.shape.props.x,
|
|
y: j.shape.props.y,
|
|
w: j.shape.props.w,
|
|
h: j.shape.props.h
|
|
};
|
|
let e = Utils.getShapesByRange(range);
|
|
e = e.filter(id => Model.getShapeById(id).elementType !== "OUTER_NODE").filter(id => Model.getShapeById(id).elementType !== "OUTER_LINKER"); // 因为范围框人工改变大小后 可能包含外部元素
|
|
// 将当前范围选择框元素以及范围内的元素 存储到subProcess中 方便后续 范围框内的元素移动时做范围框限制
|
|
window.subProcess.scopeEle[j.shape.id] = e;
|
|
// $('#'+j.shape.id).off("mousedown.scope").on("mousedown.scope", function (f) {
|
|
// Utils.unselect();
|
|
// if ((range.x < b.x && b.x < range.x + 20 && range.y < b.y && b.y < range.y + 20)
|
|
// || (range.x + range.w - 20 < b.x && b.x < range.x + range.w && range.y < b.y && b.y < range.y + 20)
|
|
// || (range.x < b.x && b.x < range.x + 20 && range.y + range.h - 20 < b.y && b.y < range.y + range.h)
|
|
// || (range.x + range.w - 20 < b.x && b.x < range.x + range.w && range.y + range.h - 20 < b.y && b.y < range.y + range.h)){
|
|
//
|
|
// Utils.selectShape(e);
|
|
// Designer.op.shapeDraggable();
|
|
//
|
|
// }
|
|
// });
|
|
tempSelectArr = e;
|
|
}else if (j.shape.elementType == 'INNER_NODE' || j.shape.elementType == 'INNER_LINKER') {
|
|
// console.log('范围标注框的图形是否存了下来', window.subProcess.scopeEle);
|
|
let scopeEle = window.subProcess.scopeEle;
|
|
for (const scopeShapeId in scopeEle) {
|
|
let inRangeEles = scopeEle[scopeShapeId];
|
|
if (inRangeEles.indexOf(j.shape.id) != -1){ // 当前鼠标所在位置为范围选择框范围内
|
|
let currentScopeEle = Model.getShapeById(scopeShapeId); // 获取当前范围选择框
|
|
let bound = {
|
|
x: currentScopeEle.props.x,
|
|
y: currentScopeEle.props.y,
|
|
w: currentScopeEle.props.w,
|
|
h: currentScopeEle.props.h
|
|
};
|
|
let rang = {
|
|
x1: bound.x,
|
|
y1: bound.y,
|
|
x2: bound.x + bound.w,
|
|
y2: bound.y + bound.h
|
|
};
|
|
|
|
window.subProcess.scopeRang = rang;
|
|
window.subProcess.movingEle = Model.getShapeById(j.shape.id);
|
|
// Utils.selectShape(j.shape.id);
|
|
tempSelectArr = [];
|
|
tempSelectArr.push(j.shape.id);
|
|
}
|
|
}
|
|
}else {
|
|
window.subProcess.movingEle = null;
|
|
window.subProcess.scopeRang = null;
|
|
}
|
|
if (tempSelectArr.length){
|
|
$('#'+j.shape.id).off("mousedown.scope").on("mousedown.scope", function (f) {
|
|
Utils.unselect();
|
|
Utils.selectShape(tempSelectArr);
|
|
|
|
$(document).bind("mouseup.select",function () {
|
|
tempSelectArr = [];
|
|
});
|
|
});
|
|
}
|
|
}else {
|
|
window.subProcess.movingEle = null;
|
|
window.subProcess.scopeRang = null;
|
|
}
|
|
});
|
|
}
|
|
|
|
// 节点展开事件
|
|
shapeExpand(event){
|
|
let param = event.data;
|
|
// alert('节点展开事件 ' + param.Model.define.elements[event.data.shapeId].text);
|
|
// 1、同时只能支持一个子流程节点展开
|
|
let elements = param.Model.define.elements;
|
|
let shapeText = ''; // 当前要展开的节点文本
|
|
for (let key in elements) {
|
|
let shape = elements[key];
|
|
if (shape.name == 'linker') continue;
|
|
if (key == param.shapeId){
|
|
shapeText = shape.text;
|
|
}
|
|
}
|
|
if (window.subProcess.checkLayoutIsReasonable()){
|
|
return;
|
|
}
|
|
param.Model.define.nodeLinkerRecord = definition.nodeLinkerRecord;
|
|
// 2、传递当前模型文件ID、子流程节点ID
|
|
awsui.ajax.request({
|
|
url: './jd',
|
|
method: 'POST',
|
|
data: {
|
|
cmd: 'com.actionsoft.apps.coe.method.process.subprocess.shape_expand',
|
|
sid: param.sid,
|
|
repositoryId: param.repositoryId,
|
|
shapeId: param.shapeId,
|
|
endToEndProcessDefineStr: JSON.stringify(param.Model.define)
|
|
},
|
|
ok: function(r){
|
|
// console.log(JSON.stringify(r.data));
|
|
definition.elements = r.data.elements;
|
|
definition.page = r.data.page;
|
|
Designer.open(definition); // 节点重新渲染
|
|
// 针对范围标识框渲染 节点关闭按钮
|
|
window.subProcess.shapeIconRender();
|
|
window.subProcess.linkerBoxPointerEvent();
|
|
window.subProcess.scopeShapeRenderTitle(r.data.elements);
|
|
// 提示用户文件已修改
|
|
window.subProcess.fileModifiedTip();
|
|
},
|
|
err: function(r){
|
|
}
|
|
});
|
|
// 3、刷新当前画布
|
|
}
|
|
|
|
scopeShapeRenderTitle(elements){
|
|
for (let key in elements) {
|
|
let element = elements[key];
|
|
if (element.name == 'linker') continue;
|
|
if (element.name == 'scopeLimitation'){ // 范围标识框
|
|
let titleHtml = "<span style='position: absolute; left: 35px; top: 25px;'>"+element.relationFileName+"</span>";
|
|
$('#'+key).prepend(titleHtml);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 节点关闭事件
|
|
shapeClose(event){
|
|
// console.log('sss');
|
|
if (window.subProcess.checkLayoutIsReasonable()){
|
|
return;
|
|
}
|
|
let param = event.data;
|
|
param.Model.define.nodeLinkerRecord = definition.nodeLinkerRecord;
|
|
awsui.ajax.request({
|
|
url: './jd',
|
|
method: 'POST',
|
|
data: {
|
|
cmd: 'com.actionsoft.apps.coe.method.process.subprocess.shape_close',
|
|
sid: param.sid,
|
|
repositoryId: param.repositoryId,
|
|
shapeId: param.shapeId,
|
|
endToEndProcessDefineStr: JSON.stringify(param.Model.define)
|
|
},
|
|
ok: function (r) {
|
|
definition.elements = r.data.elements;
|
|
definition.page = r.data.page;
|
|
Designer.open(definition); // 节点重新渲染
|
|
|
|
// 针对范围标识框渲染 节点关闭按钮
|
|
window.subProcess.shapeIconRender();
|
|
window.subProcess.linkerBoxPointerEvent();
|
|
// 提示用户文件已修改
|
|
window.subProcess.fileModifiedTip();
|
|
},
|
|
err: function (r) {
|
|
|
|
}
|
|
});
|
|
}
|
|
|
|
// 一键展开或闭合
|
|
oneClickOperate(action){
|
|
if (window.subProcess.checkLayoutIsReasonable()){
|
|
return;
|
|
}
|
|
// console.log('oneClickExpand',this);
|
|
this.Model.define.nodeLinkerRecord = definition.nodeLinkerRecord;
|
|
awsui.ajax.request({
|
|
url: './jd',
|
|
method: 'POST',
|
|
data: {
|
|
cmd: 'com.actionsoft.apps.coe.method.process.subprocess.shape_one_click',
|
|
sid: this.sid,
|
|
action: action,
|
|
repositoryId: this.repositoryId,
|
|
define: JSON.stringify(this.Model.define)
|
|
},
|
|
ok: function (r){
|
|
definition.elements = r.data.elements;
|
|
definition.page = r.data.page;
|
|
Designer.open(definition); // 节点重新渲染
|
|
|
|
// 针对范围标识框渲染 节点关闭按钮
|
|
window.subProcess.shapeIconRender();
|
|
window.subProcess.linkerBoxPointerEvent();
|
|
if (action == 'expand') {
|
|
window.subProcess.scopeShapeRenderTitle(r.data.elements);
|
|
}
|
|
// 提示用户文件已修改
|
|
window.subProcess.fileModifiedTip();
|
|
}
|
|
});
|
|
}
|
|
|
|
// 是否显示一键展开或者一键关闭
|
|
oneClickExpandAndCloseIconShow(){
|
|
let showExpandFlag = false;
|
|
let showCloseFlag = false;
|
|
let elements = this.Model.define.elements;
|
|
awsui.ajax.request({
|
|
url: './jd',
|
|
method: 'POST',
|
|
async: false,
|
|
data: {
|
|
cmd: 'com.actionsoft.apps.coe.method.process.subprocess.shape_expand_and_close_icon_show',
|
|
sid: this.sid,
|
|
repositoryId: this.repositoryId,
|
|
elements: JSON.stringify(elements)
|
|
},
|
|
ok: function (r) {
|
|
let menu = $("#designer_contextmenu");
|
|
if (r.data.showExpandFlag){
|
|
menu.children("li[ac=oneClickExpand]").show();
|
|
}
|
|
if (r.data.showCloseFlag){
|
|
menu.children("li[ac=oneClickClose]").show();
|
|
}
|
|
},
|
|
err: function (r) {
|
|
$.simpleAlert(r.msg);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 文件修改提示
|
|
fileModifiedTip(){
|
|
if (isAutoSave == "0") {
|
|
$("#saving_tip").css("color", "rgb(255, 0, 0)");
|
|
$("#saving_tip").text("文件已修改,未保存");
|
|
}
|
|
}
|
|
|
|
// 节点展开或者闭合前 检查布局是否合理
|
|
checkLayoutIsReasonable(){
|
|
let result = false;
|
|
let elements = Model.define.elements;
|
|
for (let key in elements) {
|
|
let ele = elements[key];
|
|
if (ele.elementType == "SCOPE_NODE"){ // 如果存在范围框
|
|
let eleInRange = this.getShapesByRange(ele.props); // 获取此时范围框内部元素
|
|
if (eleInRange.length > 0){
|
|
let outerNodeIndex = eleInRange.findIndex(id => Model.getShapeById(id).elementType == "OUTER_NODE");
|
|
let outerLinerIndex = eleInRange.findIndex(id => Model.getShapeById(id).elementType == "OUTER_LINKER");
|
|
if (outerLinerIndex != -1 || outerNodeIndex != -1){
|
|
$.simpleAlert("当前布局不合理,范围框内包含了外部元素!");
|
|
result = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// 获取范围内元素 只要部分包含也算在内
|
|
getShapesByRange(range, elements){
|
|
let g = [];
|
|
for (let h in Model.define.elements) {
|
|
let f = Model.getShapeById(h);
|
|
let i = [];
|
|
if (f.name == "linker") {
|
|
i = [...f.points];
|
|
i.push({x: f.from.x, y: f.from.y});
|
|
i.push({x: f.to.x, y: f.to.y});
|
|
} else {
|
|
i.push({x: f.props.x, y: f.props.y});
|
|
i.push({x: f.props.x + f.props.w, y: f.props.y});
|
|
i.push({x: f.props.x + f.props.w, y: f.props.y + f.props.h});
|
|
i.push({x: f.props.x, y: f.props.y + f.props.h});
|
|
}
|
|
if (this.pointInRect(i, range)) {
|
|
g.push(f.id)
|
|
}
|
|
}
|
|
return g
|
|
}
|
|
|
|
pointInRect(points, range){
|
|
for (let point of points) {
|
|
if (range.x < point.x && point.x < range.x + range.w && range.y < point.y && point.y < range.y + range.h) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// 判断图形在哪个范围框中 返回范围框的图形ID
|
|
calculateShapeInWhichScope(shape){
|
|
let scopeShapeKey = "";
|
|
let props = shape.props;
|
|
let elements = Model.define.elements;
|
|
for (let key in elements) {
|
|
let ele = elements[key];
|
|
if (ele.elementType == "SCOPE_NODE"){ // 查找范围框元素
|
|
let scopeX = ele.props.x;
|
|
let scopeY = ele.props.y;
|
|
let scopeW = ele.props.w;
|
|
let scopeH = ele.props.h;
|
|
if (scopeX < props.x && props.x < scopeX + scopeW && scopeY < props.y && props.y < scopeY + scopeH){
|
|
scopeShapeKey = key;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return scopeShapeKey;
|
|
}
|
|
|
|
// 判断当前连线在哪个范围框中
|
|
calculateLinkerInWhichScope(linker){
|
|
let scopeShapeKey = "";
|
|
let fromObj = linker.from;
|
|
let toObj = linker.to;
|
|
let fromX = fromObj.x, fromY = fromObj.y;
|
|
let toX = toObj.x, toY = toObj.y;
|
|
let elements = Model.define.elements;
|
|
for (let key in elements) {
|
|
let ele = elements[key];
|
|
if (ele.elementType == "SCOPE_NODE"){
|
|
let scopeX = ele.props.x;
|
|
let scopeY = ele.props.y;
|
|
let scopeW = ele.props.w;
|
|
let scopeH = ele.props.h;
|
|
if (scopeX < fromX && fromX < scopeX + scopeW && scopeY < fromY && fromY < scopeY + scopeH
|
|
&& scopeX < toX && toX < scopeX + scopeW && scopeY < toY && toY < scopeY + scopeH){
|
|
scopeShapeKey = key;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return scopeShapeKey;
|
|
}
|
|
|
|
// 向范围框上存储内部元素的位置 添加元素ID
|
|
addScopeShapeInnerEles(scopeKey, eleId){
|
|
let elements = Model.define.elements;
|
|
for (let key in elements) {
|
|
let ele = elements[key];
|
|
if (key == scopeKey){
|
|
if (ele.innerElements.indexOf(eleId) == -1){
|
|
ele.innerElements.push(eleId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 根据连线 处理from to 两个外部节点的extendAttr扩展属性
|
|
outerNodeExtendAttrHandle(linker){
|
|
let fromId = linker.from.id;
|
|
let toId = linker.to.id;
|
|
let fromShape = Model.getShapeById(fromId);
|
|
let toShape = Model.getShapeById(toId);
|
|
let extendAttr = {
|
|
leadNodeArr: [],
|
|
rearNodeArr: []
|
|
}
|
|
// 更新后置节点
|
|
let rearNodeArr = [];
|
|
if (fromShape.extendAttr){
|
|
rearNodeArr = [...fromShape.extendAttr.rearNodeArr];
|
|
}else {
|
|
fromShape.extendAttr = extendAttr;
|
|
}
|
|
rearNodeArr.push(toId);
|
|
fromShape.extendAttr.rearNodeArr = rearNodeArr;
|
|
// 更新前置节点
|
|
let leadNodeArr = [];
|
|
if (toShape.extendAttr){
|
|
leadNodeArr = [...toShape.extendAttr.leadNodeArr];
|
|
}else {
|
|
toShape.extendAttr = extendAttr;
|
|
}
|
|
leadNodeArr.push(fromId);
|
|
toShape.extendAttr.leadNodeArr = leadNodeArr;
|
|
}
|
|
|
|
// 子流程节点关联的源文件中的节点发生变动 给出提示
|
|
sourceNodeDiffMsgHandle(){
|
|
if (definition.sourceNodeDiffMsg){
|
|
let multipleMsg = "";
|
|
let toDeleteMsgKey = [];
|
|
for (let shapeKey in definition.sourceNodeDiffMsg) {
|
|
if (Model.define.elements[shapeKey] != undefined){
|
|
// 提示
|
|
multipleMsg = multipleMsg.concat('<br><br>', definition.sourceNodeDiffMsg[shapeKey]);
|
|
}
|
|
toDeleteMsgKey.push(shapeKey);
|
|
}
|
|
if (toDeleteMsgKey.length){
|
|
for (let shapeKey in toDeleteMsgKey) {
|
|
delete definition.sourceNodeDiffMsg[shapeKey];
|
|
}
|
|
awsui.ajax.request({
|
|
url: './jd',
|
|
method: 'POST',
|
|
data: {
|
|
cmd: 'com.actionsoft.apps.coe.method.process.subprocess_source_node_diff_msg_clear',
|
|
sid: this.sid,
|
|
repositoryId: this.repositoryId
|
|
},
|
|
ok: function (r){
|
|
|
|
},
|
|
err: function (r) {
|
|
$.simpleAlert(r.msg);
|
|
}
|
|
});
|
|
}
|
|
if (multipleMsg){
|
|
$.notification({
|
|
title:'源文件节点变动提示',
|
|
description: multipleMsg,
|
|
position: "topRight",
|
|
delay: 0,
|
|
distance: 100
|
|
});
|
|
$('.awsui-public-box-main').css('width', '325px');
|
|
}
|
|
}
|
|
}
|
|
|
|
subProcessNodeLink(event) {
|
|
let param = event.data;
|
|
let shape = param.shape;
|
|
if (shape.extendAttr == undefined){
|
|
$.simpleAlert('请先绑定子流程模型,在进行跳转操作');
|
|
}
|
|
let uuid = shape.extendAttr.id;
|
|
let url="./w?uuid=" + uuid +"&teamId=" + teamId
|
|
+ "&cmd=com.actionsoft.apps.coe.pal_pl_repository_designer&sid=" + encodeURIComponent($('#sid').val());
|
|
window.open(url);
|
|
}
|
|
}
|
|
|