apps/com.actionsoft.apps.coe.pal/web/com.actionsoft.apps.coe.pal/lib/designer/scripts/diagraming/designer.method.subprocess.js

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);
}
}