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

365 lines
15 KiB
JavaScript

$(function(){
if (methodId != 'process.subprocess') { // 如果当前打开的模型不是端到端总图 那么整个js也没有执行的必要
return;
}
// 1. 子流程展开 事件:获取当前子流程所代表的模型文件
// (function (Model, ruuid, sid) {
// })(Model, ruuid, sid);
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)
}
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') { // 当前元素为子流程节点 渲染展开图标 并绑定展开事件
let expandIcon = "<span id='icon_"+shapeId+"' class='iconfont icon-zhankaishousuo' style='position: absolute;cursor: pointer;'></span>";
$('#'+shapeId).append(expandIcon);
$('#icon_'+shapeId).on('click', '', {shapeId: shapeId, Model: this.Model, repositoryId: this.repositoryId, sid: this.sid}, this.shapeExpand);
}else { // 当前元素为虚线范围限制框的话 渲染关闭图标 并绑定关闭事件
let closeIcon = "<span id='icon_"+shapeId+"' class='iconfont icon-quanpingshouqi' style='position: absolute;cursor: pointer;'></span>";
$('#'+shapeId).append(closeIcon);
$('#icon_'+shapeId).on('click', '', {shapeId: shapeId, Model: this.Model, repositoryId: this.repositoryId, sid: this.sid}, this.shapeClose);
}
}
}
}
// 子流程节点拖拽到画布后 渲染展开按钮
shapeOpenIconRender(ele){
if (ele.name != 'subProcess'){
return;
}
let shapeId = ele.id;
let expandIcon = "<span id='icon_"+shapeId+"' class='iconfont icon-zhankaishousuo' style='position: absolute;cursor: pointer;'></span>";
$('#'+shapeId).append(expandIcon);
$('#icon_'+shapeId).on('click', '', {shapeId: shapeId, Model: this.Model, repositoryId: this.repositoryId, sid: this.sid}, this.shapeExpand);
}
// 范围选择框的事件绑定处理
handleScopeShapeEvent(){
let c = $("#designer_canvas");
c.off("mousemove").on("mousemove",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) {
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").on("mousedown", function (f) {
Utils.unselect();
Utils.selectShape(e);
});
}else {
// 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){ // 当前鼠标所在位置为范围选择框范围内
Utils.unselect();
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);
}
}
}
}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;
}
// 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;
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);
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
}
// 根据当前元素的坐标设置元素类型
calculateShapeElementType(shape){
let elementType = "OUTER_NODE"; // 默认指定外部节点
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){
elementType = "INNER_NODE";
}
}
}
return elementType;
}
}