$(document).ready(function() {
nodes = JSON.parse(nodes);
$(window).resize(function() {
render(nodes, false);
});
render(nodes, false);
$('#submit').click(function() {
if(nodes.length <= 2) {
new $.zui.Messager(warningLang['needReview'], { close: false }).show();
return false;
}
var nodesText = JSON.stringify(nodes);
$('#nodes').val(nodesText);
isChanged = false;
})
/* warning for save. 提示保存修改. */
window.onbeforeunload = function() {
if(isChanged) {
return warningLang['save'];
}
}
});
var isChanged = false;
var modal;
function genID() {
return Math.random().toString(36).substr(2)
}
function genUserOptions(selectedUsers) {
var options = '';
for(let account in users) {
options += '' + users[account] + ' ';
}
return options;
}
function genConditionSelect(index, cond) {
if(typeof cond.type == 'undefined') {
cond.type = 'user';
cond.selectType = 'account';
cond.users = [];
}
html = '
' + nodeTypeLang['condition'] + '
';
html += '' + noticeTypeLang['when'] + '
';
html += '';
for(var key in conditionTypeLang) {
html += '' + conditionTypeLang[key].name + ' ';
}
html += '
';
html += '' + noticeTypeLang['type'] + '
';
html += '';
for(var key in conditionTypeLang[cond.type].selectType) {
var select = conditionTypeLang[cond.type].selectType[key];
html += '' + select.name + ' ';
}
html += '
';
var select = conditionTypeLang[cond.type].selectType[cond.selectType];
html += '' + select.tips + '
';
html += genOptions(select.options, cond);
html += '
';
return html;
}
function genOptions(opType, node) {
if(!opType) return [];
var data = {roles: roles, users: users, depts: depts};
var options = '';
for(let key in data[opType]) {
options += '' + data[opType][key] + ' ';
}
return options;
}
function genDeptOptions(selectedDepts) {
var options = '';
for(let id in depts) {
options += '' + depts[id] + ' ';
}
return options;
}
function bindConditionEvent(node) {
$('.form-condition .close').click(function() {
$(this).parent().remove();
return false;
})
$('select[name^="selectType"]').change(function(e) {
var index = $(this).attr("name").substring(10);
var cond = node.conditions[index];
if(typeof cond == 'undefined') {
cond = {type: 'user'};
}
cond.selectType = $(this).val();
$(this).closest('.condition-block').html(genConditionSelect(index, cond));
$('.chosen').chosen();
bindConditionEvent(node);
})
}
function bindNodeEvent() {
$('.chosen').chosen();
$('.form-reviewer .close').click(function() {
if($('.form-reviewer').length <= 1) { return false; }
$(this).parent().remove();
})
$('.form-cc .close').click(function() {
if($(this).closest('form').hasClass('cc') && $('.form-cc').length <= 1) { return false; }
$(this).parent().remove();
})
$('input[name="reviewType"]').change(function(e) {
if($(this).val() != 'manual') {
$('.reviewer-block').addClass('hidden');
$('.multiple-block').addClass('hidden');
$('.agent-block').addClass('hidden');
$('.addReviewer').addClass('hidden');
if($(this).val() == 'pass') {
$('.addCC').removeClass('hidden');
} else {
$('.addCC').addClass('hidden');
}
} else {
$('.addReviewer').removeClass('hidden');
$('.addCC').removeClass('hidden');
$('.reviewer-block').removeClass('hidden');
$('.multiple-block').removeClass('hidden');
$('.agent-block').removeClass('hidden');
$('.cc-block').removeClass('hidden');
}
})
$('select[name^="type"]').change(function(e) {
var type = $(this).val();
var options = reviewerTypeLang[type].options;
var $pa = $(this).parents('.reviewer-block');
$pa.find('.select-box').each(function() {
if($(this).hasClass(options + '-select')) {
$(this).removeClass('hidden')
} else {
$(this).addClass('hidden')
}
});
})
$('select[name^="ccType"]').change(function(e) {
var type = $(this).val();
var options = reviewerTypeLang[type].options;
var $pa = $(this).parents('.cc-block');
$pa.find('.select-box').each(function() {
if($(this).hasClass(options + '-select')) {
$(this).removeClass('hidden')
} else {
$(this).addClass('hidden')
}
});
})
$('input[name="agentType"]').change(function() {
if($(this).val() == 'appointee') {
$('.agentUser').removeClass('hidden');
} else {
$('.agentUser').addClass('hidden');
}
})
}
function showAddType(el) {
hideAddType();
var addText = '';
$(el).addClass('add-node-btn-active');
$(el).append(addText);
/* 点击添加评审人 */
$('.add-reviewer').click(function() {
var $pa = $(this).closest('.editor-node');
var isCondition = $pa.hasClass('condition');
if(isCondition) {
$pa = $pa.parent().closest('.editor-node');
}
var id = $pa.data('id');
getNode(id, function(index, father, index2, grandpa) {
index = isCondition ? parseInt(index) : parseInt(index) + 1;
if(isCondition) {
father = (index == 'default') ? father.default.nodes : father.branches[index].nodes;
index = 0;
}
var reviewNode = {id: genID(), title: nodeTypeLang['approval'], reviewType: "manual", type: "approval", reviewers: [{type: "select"}], agentType: "pass", ccs: []};
father.splice(index, 0, reviewNode);
render(nodes);
})
})
$('.add-cc').click(function() {
var $pa = $(this).closest('.editor-node');
var isCondition = $pa.hasClass('condition');
if(isCondition) {
$pa = $pa.next('.editor-node');
}
var id = $pa.data('id');
getNode(id, function(index, father, index2, grandpa) {
index = isCondition ? parseInt(index) : parseInt(index) + 1;
var reviewNode = {id: genID(), title: nodeTypeLang['cc'], type: "cc", ccs: [{type: "select"}]};
father.splice(index, 0, reviewNode);
render(nodes);
})
})
$('.add-branch').click(function() {
var $pa = $(this).closest('.editor-node');
var isCondition = $pa.hasClass('condition');
if(isCondition) {
$pa = $pa.next('.editor-node');
}
var id = $pa.data('id');
var branchType = $(this).hasClass('type-condition') ? 'condition' : 'parallel';
getNode(id, function(index, father, index2, grandpa) {
index = isCondition ? parseInt(index) : parseInt(index) + 1;
// var reviewNode = {id: genID(), type: "approval", reviewers: [{type: "select"}]};
var branchNode = {
id: genID(),
type: "branch",
branchType: branchType,
branches: [{
id: genID(),
conditions: [],
nodes:[{id: genID(), type: "approval", reviewers: [{type: "select"}]}]
}],
default: {
id: genID(),
nodes: [{id: genID(), type: "approval", reviewers: [{type: "select"}]}]
}
};
father.splice(index, 0, branchNode);
render(nodes);
})
})
}
function hideAddType(el) {
$('.add-node-types').remove();
$('.add-node-btn-active').removeClass('add-node-btn-active');
if(typeof el != 'undefined') {
el.stopPropagation();
}
}
$('#editor').click(function(el) {
hideAddType(el);
$('.panel').removeClass('visible');
el.stopPropagation();
})
// Render
function getNode(nodeID, callback) {
if(nodeID == 'start') {
callback(0, nodes)
return [0];
} else if(nodeID == 'end') {
callback(nodes.length-1, nodes)
return [nodes.length-1];
} else {
return findFromNodes(nodeID, nodes, callback);
}
}
function findFromNodes(nodeID, nodes, callback) {
for(let index in nodes) {
var node = nodes[index];
if(node.id == nodeID) {
callback(index, nodes);
return [index];
}
if(node.type == 'branch') {
for(var index2 in node.branches) {
var path = [index, 'branches', index2];
var branch = node.branches[index2];
if(branch.id == nodeID) {
callback(index2, node, index, nodes);
return path;
}
var result = findFromNodes(nodeID, branch.nodes, callback);
if(result.length > 0) {
path.push('nodes');
return path.concat(result);
}
}
// default
var path = [index, 'default'];
var branch = node.default;
if(branch.id == nodeID) {
callback('default', node, index, nodes);
return path;
}
var result = findFromNodes(nodeID, branch.nodes, callback);
if(result.length > 0) {
return path.concat(result);
}
}
}
return [];
}
function render(nodes, modify) {
if(typeof modify === 'undefined' || modify === true) {
isChanged = true;
}
var offsetTop = $('#graph').scrollTop();
var offsetLeft = $('#graph').scrollLeft();
$('#root').empty();
var graphHeight = $(window).height() - $('#header').outerHeight() - 100;
$('#graph').css('height', graphHeight);
var $root = $('#root');
$root.append(renderNodes(nodes));
$('i.delete-btn').click(function() {
var id = $(this).closest('.editor-node').data('id');
getNode(id, function(index, father) {
father.splice(index,1)
})
render(nodes);
});
$('button.delete-btn').click(function() {
var id = $(this).closest('.branch').data('id');
getNode(id, function(index, father, index2, grandpa) {
father.branches.splice(index, 1);
if(father.branches.length == 0) {
grandpa.splice(index2, 1)
}
})
render(nodes);
});
$('#graph').scrollTop(offsetTop).scrollLeft(offsetLeft);
// Actions.
$('.add-node-btn').click(function(el) {
showAddType(this);
el.stopPropagation();
})
$('.add-condition').click(function() {
var id = $(this).closest('.editor-node').data('id');
getNode(id, function(index, father) {
father[index].branches.push({
id: genID(),
conditions: [],
nodes:[{id: genID(), reviewType: "manual", type: "approval", reviewers: [{type: "select"}]}]
});
render(nodes);
});
})
function renderCondition(index, cond)
{
var type = cond.type ? cond.type : 'user';
html = '× ';
html += genConditionSelect(index, cond);
html += '
';
return html;
}
$('.condition .node-content').click(function() {
var $pa = $(this).closest('.editor-node').parent().closest('.editor-node');
var id = $pa.data('id');
getNode(id, function(index, father, index2, grandpa) {
if(index == 'default') return;
var selectedFather = father.branches;
var selectedIndex = index;
modal = new $.zui.ModalTrigger({title: noticeTypeLang['setCondition'], custom: function(el) {
var node = selectedFather[selectedIndex];
var html = '';
return html;
}});
modal.show({onShow: function() {
setTimeout(function() {
$('.chosen').chosen();
$('.addCondition .btn').click(function() {
var cond = {type: 'user', selectType: 'account', users: []};
$(this).parent().before(renderCondition(genID(), cond));
bindConditionEvent(selectedFather[selectedIndex]);
$('.chosen').chosen();
return false;
})
bindConditionEvent(selectedFather[selectedIndex]);
}, 20)
return false;
}})
modal.show();
})
})
function renderReviewer(reviewer, index) {
var html = '';
var type = reviewer.type ? reviewer.type : 'select';
html += '';
return html;
}
function renderCC(cc, index) {
var html = '';
var type = cc.type ? cc.type : 'select';
html += '';
return html;
}
/* 设置开始 结束 抄送节点 */
$('.start .node-content, .end .node-content, .cc .node-content').click(function() {
var $pa = $(this).closest('.editor-node');
var id = $pa.data('id');
getNode(id, function(index, father, index2, grandpa) {
var selectedFather = father;
var selectedIndex = index;
var node = selectedFather[selectedIndex];
modal = new $.zui.ModalTrigger({title: noticeTypeLang['set'] + nodeTypeLang[node.type] + noticeTypeLang['node'], custom: function(el) {
var title = node.title ? node.title : nodeTypeLang[node.type];
var html = '';
return html;
}});
modal.show({onShow: function() {
setTimeout(function() {
bindNodeEvent();
$('.addCC').click(function() {
$(this).parent().before(renderCC({type: 'select'}, genID()));
bindNodeEvent();
return false;
})
}, 20)
}})
})
})
$('.approval .node-content').click(function() {
var $pa = $(this).closest('.editor-node');
var id = $pa.data('id');
getNode(id, function(index, father, index2, grandpa) {
var selectedFather = father;
var selectedIndex = index;
modal = new $.zui.ModalTrigger({title: noticeTypeLang['setNode'], custom: function(el) {
var reviewIndex = 0;
var ccIndex = 0;
var node = selectedFather[selectedIndex];
var title = node.title ? node.title : nodeTypeLang[node.type];
var reviewType = node.reviewType ? node.reviewType : 'manual';
var html = '';
return html;
}});
modal.show({onShow: function() {
setTimeout(function() {
bindNodeEvent();
$('.addReviewer .btn').click(function() {
$(this).parent().before(renderReviewer({type: 'select'}, genID()));
bindNodeEvent();
return false;
})
$('.addCC .btn').click(function() {
$(this).parent().before(renderCC({type: 'select'}, genID()));
bindNodeEvent();
return false;
})
}, 20)
}})
})
})
}
function saveCondition(id) {
var dataArray = $('#edit').serializeArray();
getNode(id, function(index1, father, index2, grandpa) {
var conditions = {};
for(var d of dataArray) {
if(d.name.indexOf('type') === 0) {
var index = d.name.substring(4);
conditions[index] = {type: d.value};
} else if(d.name.indexOf('selectType') === 0) {
var index = d.name.substring(10);
conditions[index].selectType = d.value;
} else if(d.name.indexOf('roles') === 0) { // 角色
var index = d.name.substring(5);
if(typeof conditions[index].roles == 'undefined') conditions[index].roles = [];
conditions[index].roles.push(d.value);
} else if(d.name.indexOf('users') === 0) { // 人员
var index = d.name.substring(5);
if(typeof conditions[index].users == 'undefined') conditions[index].users = [];
conditions[index].users.push(d.value);
} else if(d.name.indexOf('depts') === 0) { // 部门
var index = d.name.substring(5);
if(typeof conditions[index].depts == 'undefined') conditions[index].depts = [];
conditions[index].depts.push(d.value);
}
}
var message = checkConditions(conditions);
if(message) {
new $.zui.Messager(message, { close: false }).show();
return;
}
father.branches[index1].conditions = conditions;
modal.close();
render(nodes);
})
}
function checkConditions(conditions) {
for(var i in conditions) {
var condition = conditions[i];
if(condition.type == 'user') {
if(condition.selectType == 'account') {
if(typeof condition.users == 'undefined' || condition.users.length == 0) {
return warningLang['selectUser'];
}
} else if(condition.selectType == 'dept') {
if(typeof condition.depts == 'undefined' || condition.depts.length == 0) {
return warningLang['selectDept'];
}
} else if(condition.selectType == 'role') {
if(typeof condition.roles == 'undefined' || condition.roles.length == 0) {
return warningLang['selectRole'];
}
}
}
}
return '';
}
function saveNode(id) {
var dataArray = $('#edit').serializeArray();
var data = {};
getNode(id, function(index1, father, index2, grandpa) {
var reviewers = {};
var ccs = {};
var node = father[index1];
if(node.type != 'start' && node.type != 'end') data.id = node.id;
data.type = node.type;
for(var d of dataArray) {
if(d.name == 'title') {
if(node.type == 'approval' || node.type == 'cc') { // 审批和抄送可以设置标题
data.title = d.value;
}
} else if (node.type == 'approval') { // 只有审批节点可以设置审批人
if(d.name == 'reviewType') {
data.reviewType = d.value;
if(d.value != 'manual') {
continue;
}
}
if(data.reviewType == 'manual') {
if(d.name.indexOf('type') === 0) {
var index = d.name.substring(4);
reviewers[index] = {type: d.value};
if(d.value == 'appointee') {
reviewers[index].users = [];
} else if(d.value == 'role') {
reviewers[index].roles = [];
}
} else if(d.name.indexOf('roles') === 0) {
var index = d.name.substring(5);
if(reviewers[index].type == 'role') { // 角色
reviewers[index].roles.push(d.value);
}
} else if(d.name.indexOf('users') === 0) { // 指定人员
var index = d.name.substring(5);
if(reviewers[index].type == 'appointee') {
reviewers[index].users.push(d.value);
}
} else if(d.name == 'multiple') {
data.multiple = d.value;
} else if(d.name == 'agentType') {
data.agentType = d.value;
} else if(d.name == 'agentUser') {
if(data.agentType == 'appointee') {
data.agentUser = d.value;
}
}
}
}
if(data.reviewType != 'reject') {
if (d.name.indexOf('ccType') === 0) { // 设置抄送
var index = d.name.substring(6);
ccs[index] = {type: d.value}; // 支持指定人员,发起人自选,上级,角色
if(d.value == 'appointee') { // 指定人员
ccs[index].users = [];
} else if(d.value == 'role') { // 角色
ccs[index].roles = [];
}
} else if(d.name.indexOf('ccroles') === 0) { //设置抄送角色
var index = d.name.substring(7);
if(ccs[index].type == 'role') {
ccs[index].roles.push(d.value);
}
} else if(d.name.indexOf('ccusers') === 0) { //设置抄送人
var index = d.name.substring(7);
if(ccs[index].type == 'appointee') {
ccs[index].users.push(d.value);
}
}
}
}
if(node.type == 'approval') {
data.reviewers = [];
for(var i in reviewers) {
data.reviewers.push(reviewers[i]);
}
}
data.ccs = [];
for(var i in ccs) {
data.ccs.push(ccs[i]);
}
var message = checkNode(node.type, data)
if(message) {
new $.zui.Messager(message, { close: false }).show();
return;
}
father[index1] = data;
modal.close();
render(nodes);
})
}
function checkNode(type, data) {
var reviewerSelectCount = 0;
if(typeof data.reviewers === 'undefined' || data.reviewers.length == 0) {
if(type == 'approval' && data.reviewType == 'manual') {
return warningLang['needReviewer'];
}
} else {
for(var reviewer of data.reviewers) {
if(reviewer.type == 'appointee' && reviewer.users.length === 0) {
return warningLang['selectUser'];
} else if(reviewer.type == 'role' && reviewer.roles.length === 0) {
return warningLang['selectRole'];
} else if(reviewer.type == 'select') {
if(reviewerSelectCount !== 0) return warningLang['oneSelect'];
reviewerSelectCount++;
}
}
}
var ccSelectCount = 0;
if(typeof data.ccs !== 'undefined') {
for(var cc of data.ccs) {
if(cc.type == 'appointee' && cc.users.length === 0) {
return warningLang['selectUser'];
} else if(cc.type == 'role' && cc.roles.length === 0) {
return warningLang['selectRole'];
} else if(cc.type == 'select') {
if(ccSelectCount !== 0) return warningLang['oneSelect'];
ccSelectCount++;
}
}
}
return '';
}
function renderNodes(nodes) {
var nodesText = '';
for(let index in nodes) {
var node = nodes[index];
if(node.type == 'branch') {
nodesText += renderBranch(node);
} else {
nodesText += renderNode(node);
}
}
return nodesText;
}
function renderConditions(conditions) {
var conditionText = '';
var conditionTitleText = '';
var conditionNum = 0;
for(let index in conditions) {
conditionNum++;
var condition = conditions[index];
if(condition.selectType == 'account' && condition.users.length > 0) {
var userConditionText = '';
for(let userIndex in condition.users) {
userConditionText += users.hasOwnProperty(condition.users[userIndex]) ? users[condition.users[userIndex]] + '、' : '';
}
if(conditionNum <= 2) conditionText += conditionTextLang.user + userConditionText.slice(0, -1) + ' ';
conditionTitleText += conditionTextLang.user + userConditionText.slice(0, -1);
}
if(condition.selectType == 'dept') {
var deptConditionText = '';
for(let deptIndex in condition.depts) {
deptConditionText += depts.hasOwnProperty(condition.depts[deptIndex]) ? depts[condition.depts[deptIndex]] + '、' : '';
}
if(conditionNum <= 2) conditionText += conditionTextLang.dept + deptConditionText.slice(0, -1) + ' ';
conditionTitleText += conditionTextLang.dept + deptConditionText.slice(0, -1);
}
if(condition.selectType == 'role') {
var roleConditionText = '';
for(let roleIndex in condition.roles) {
roleConditionText += roles.hasOwnProperty(condition.roles[roleIndex]) ? roles[condition.roles[roleIndex]] + '、' : '';
}
if(conditionNum <= 2) conditionText += conditionTextLang.role + roleConditionText.slice(0, -1) + ' ';
conditionTitleText += conditionTextLang.role + roleConditionText.slice(0, -1);
}
if(conditionNum == 3) conditionText += '...';
conditionTitleText += '
';
}
var returnData = {
text : conditionText,
titleText : conditionTitleText.slice(0, -5),
};
return returnData;
}
function renderBranch(branch) {
var branchType = branch.branchType == 'parallel' ? 'addParallel' : 'addCondition';
var branchesText = '
' + noticeTypeLang[branchType] + '
';
var branches = '';
/* Branches. */
for(var index in branch.branches) {
var nodes = branch.branches[index].nodes;
var conditions = branch.branches[index].conditions;
var conditionObj = renderConditions(conditions);
branches +=
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' + nodeTypeLang['condition'] + ' ' + (parseInt(index)+1) + ' ' +
'
' +
'
' +
'
' + conditionObj.text + '
' +
'
' +
'
' +
'
' +
'
';
branches += renderNodes(nodes);
branches += '
';
}
/* Default. */
branches += '
' + nodeTypeLang[branch.branchType == 'parallel' ? 'default' : 'other'] + '
' + noticeTypeLang[branch.branchType == 'condition' ? 'otherBranch' : 'defaultBranch'] + '
';
branches += renderNodes(branch.default.nodes);
branches += '
';
branches += '
';
/* Bottom. */
branches += '
';
branchesText +='' + branches + '
';
return branchesText;
}
function renderNode(node) {
var notice = '';
var id = '';
var title = '';
switch(node.type) {
case 'start':
case 'end':
title = noticeTypeLang['setCC'];
if(typeof node.ccs != 'undefined' && typeof node.ccs[0] != 'undefined' && typeof node.ccs[0].type != 'undefined') {
for(let cc of node.ccs ) {
notice = reviewerTypeLang[cc.type].name + ' ';
}
} else {
notice = noticeTypeLang['setCC'];
}
id = node.type;
break;
case 'approval':
if(node.reviewType == 'manual' || typeof node.reviewType === 'undefined') {
for(let reviewer of node.reviewers) {
notice = reviewerTypeLang[reviewer.type].name + ' ';
}
} else {
notice = reviewTypeLang[node.reviewType];
}
id = node.id;
title = noticeTypeLang['setReviewer'];
break;
case 'cc':
for(let cc of node.ccs ) {
notice = reviewerTypeLang[cc.type].name + ' ';
}
id = node.id;
title = noticeTypeLang['setCC'];
break;
}
$node = '' + (typeof node.title === 'undefined' ? nodeTypeLang[node.type] : node.title) + '
';
if(node.type != 'start' && node.type != 'end') $node += '
';
$node += '
';
if(node.type != 'end') $node += '
';
$node += '
';
return $node;
}