$(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 += ''; } 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 += '
'; html += '
' + noticeTypeLang['type'] + '
'; html += '
'; var select = conditionTypeLang[cond.type].selectType[cond.selectType]; html += '
' + select.tips + '
'; 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 += ''; } return options; } function genDeptOptions(selectedDepts) { var options = ''; for(let id in depts) { options += ''; } 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 = '
'; if(node.conditions.length == 0) { node.conditions.push({}); } for(var index in node.conditions) { var cond = node.conditions[index]; html += renderCondition(index, cond); } html += '
' + noticeTypeLang['conditionOr'] + '
'; html += '
'; 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 += '
' + userTypeLang['reviewer'] + '
'; html += '
' + noticeTypeLang['reviewType'] + '
'; var opType = reviewerTypeLang[type].options; var types = {'': true}; for(let reviewType in reviewerTypeLang) { var info = reviewerTypeLang[reviewType]; if(typeof types[info.options] !== 'undefined') { continue; } types[info.options] = true; html += '
'; if(info.options) html += '
' + info.tips + '
'; html += '
'; } html += '
'; return html; } function renderCC(cc, index) { var html = ''; var type = cc.type ? cc.type : 'select'; html += '
' + userTypeLang['cc'] + '
'; html += '
' + noticeTypeLang['ccType'] + '
'; var opType = reviewerTypeLang[type].options; var types = {'': true}; for(let reviewType in reviewerTypeLang) { var info = reviewerTypeLang[reviewType]; if(typeof types[info.options] !== 'undefined') { continue; } types[info.options] = true; html += '
'; if(info.options) html += '
' + info.tips + '
'; html += '
'; } 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 = '
'; html += '
' + noticeTypeLang['title'] + '
'; var ccs = node.ccs ? node.ccs : []; for(var index in ccs) { var cc = ccs[index]; html += renderCC(cc, index); } html += '
'; html += '
'; 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 = '
'; if(node.type == 'approval' || node.type == 'cc') html += '
' + noticeTypeLang['title'] + '
'; html += '
' + noticeTypeLang['reviewType'] + '
'; for(var index in node.reviewers) { var reviewer = node.reviewers[index]; html += renderReviewer(reviewer, index); reviewIndex = index; } html += '
'; var multiple = node.multiple ? node.multiple : 'and'; html += '
' + noticeTypeLang['multipleType'] + '
'; var agent = node.agentType ? node.agentType : 'pass'; html += '
'; html += '
' + noticeTypeLang['agentType'] + '
'; html += '
'; html += '
'; /* cc. */ var ccs = node.ccs ? node.ccs : []; for(var index in ccs) { var cc = ccs[index]; html += renderCC(cc, index); ccIndex = index; } html += '
'; html += '
'; 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) + '
' + notice + '
'; if(node.type != 'start' && node.type != 'end') $node += ''; $node += '
'; if(node.type != 'end') $node += '
'; $node += '
'; return $node; }