AdminEAP框架中集成了Activiti工作流组件,使用了activiti-explorer中的在线流程设计器,其中在选择代理人(审批人)中,原生的操作是输入数据,没有和系统自动关联。同时,原生的在线流程设计器使用AngularJs写的,而框架使用的Jquery,两者之间集成需要注意几点,避免踩坑;
1、Activiti流程设计器
2、选择代理人、候选人、候选组
3、选择代理人(单选)
4、选择候选人(多选)
5、选择候选组(多选)
1、修改properties-assignment-controller.js
扩展候选人和候选组对象属性
第47行:$scope.assignment.candidateUsers = [{value: '', name: ''}];
第62行:$scope.assignment.candidateGroups = [{value: '', name: ''}];
这样在界面上既可以显示用户/用户组的名称,也显示实际存储的ID值
打开选择弹窗,数据回填的核心代码
//-----------add select User/Group button handler By billJiang--------------
//代理人(审批人)/候选人
$scope.selectUser = function (multiple) {
var title = "选择代理人(单选)"
var ids = ($scope.assignment.assignee ? $scope.assignment.assignee : 0);
if (multiple == 1) {
title = "选择候选人(多选)";
//候选人id
ids = 0;
if($scope.assignment.candidateUsers) {
var idsArr = [];
//alert( $scope.assignment.candidateUsers.length);
for (var i = 0; i < $scope.assignment.candidateUsers.length; i++) {
if ($scope.assignment.candidateUsers[i].value)
idsArr.push($scope.assignment.candidateUsers[i].value);
}
if (idsArr.length > 0) {
ids = idsArr.join(",");
}
}
}
modals.openWin({
winId: 'userSelectWin',
url: basePath + '/activiti/user/select/' + multiple + '/' + ids,
width: '800px',
title: title
})
};
//候选组
$scope.selectGroup = function () {
var ids = 0;
if($scope.assignment.candidateGroups) {
var idsArr = [];
for (var i = 0; i < $scope.assignment.candidateGroups.length; i++) {
if ($scope.assignment.candidateGroups[i].value)
idsArr.push($scope.assignment.candidateGroups[i].value);
}
if (idsArr.length > 0) {
ids = idsArr.join(",");
}
}
modals.openWin({
winId: 'groupSelectWin',
url: basePath + '/activiti/group/select/' + ids,
width: '1200px',
title: '选择候选组(多选)'
})
}
//回填受理人
$scope.setAssignee = function (assignee, userName) {
$scope.assignment.assignee = assignee;
$scope.assignment.assigneeName = userName;
//jQuery("#assigneeNameField").val(userName);
$scope.$apply();
};
//回填候选人
$scope.setCandidateUsers = function (userIds, userNames) {
var users = null;
if (!userIds) {
$scope.assignment.candidateUsers = users;
} else {
var userIdArr = userIds.split(",");
var userNameArr = userNames.split(",");
users = [];
for (var i = 0; i < userIdArr.length; i++) {
var userObj = {};
userObj["value"] = userIdArr[i];
userObj["name"] = userNameArr[i];
users.push(userObj);
}
$scope.assignment.candidateUsers = users;
}
$scope.$apply();
};
//回填候选组
$scope.setCandidateGroups = function (groupIds, groupNames) {
var groups = null;
if (!groupIds) {
$scope.assignment.candidateGroups = groups;
} else {
var groupIdArr = groupIds.split(",");
var groupNameArr = groupNames.split(",");
groups = [];
for (var i = 0; i < groupIdArr.length; i++) {
var groupObj = {};
groupObj["value"] = groupIdArr[i];
groupObj["name"] = groupNameArr[i];
groups.push(groupObj);
}
$scope.assignment.candidateGroups = groups;
}
//加上这句话回填后界面立即生效
$scope.$apply();
};
//--------------------------------------------------------------------------
以上代码需要注意 scope. apply(), 否则回填以后界面双向绑定不能立即生效;
代理人、候选人选择的核心代码
代理人和候选人选择器使用了同一个界面,通过multiple参数值进行区分
var userSelectTable;
var ids = "${ids?default(0)}";//回填ids
ids = ids == 0 ? '' : ids;
var multiple = "${multiple?default(0)}";//默认单选
//用户选择控制器
var userSelectCtrl = {
initTable: function () {
jQuery("#userIds").val(ids);
this.updateSelectedUserNames();
var self = this;
userSelectTable = new CommonTable("user_select_table", "id_user_list", "searchDiv_user_select");
//回调选中
userSelectTable.serverCallback = function () {
self.setCheckBoxState();
}
},
//查询 换页选择框回填
setCheckBoxState: function () {
var selectUserIds = jQuery("#userIds").val();
if (selectUserIds) {
var userIdArr = selectUserIds.split(",");
//选中增加的用户
jQuery.each(userIdArr, function (index, userId) {
if (userSelectTable.table.$("#" + userId).length > 0) {
userSelectTable.table.$("#" + userId).find(":checkbox.checkbox_user").prop("checked", true);
}
});
//删除已经选中的
userSelectTable.table.$("tr").find(":checkbox.checkbox_user:checked").each(function () {
var curUserId = jQuery(this).parents("tr").attr("id");
//找不到,已经被删除
if (selectUserIds.indexOf(curUserId) == -1) {
userSelectTable.table.$("#" + curUserId).find(":checkbox.checkbox_user").prop("checked", false);
}
});
} else {
jQuery(":checkbox.checkbox_user").prop("checked", false);
}
},
//绑定用户选择事件
bindSelectUserEvent: function () {
jQuery("#selectUser").click(function () {
var controllerScope = jQuery('div[ng-controller="KisBpmAssignmentPopupCtrl"]').scope(); // Get controller's scope
var userIds = jQuery("#userIds").val();
var userNames = jQuery("#userNames").val();
if (multiple == 0) {
controllerScope.setAssignee(userIds, userNames);
} else {
controllerScope.setCandidateUsers(userIds, userNames);
}
modals.hideWin("userSelectWin");
})
},
selectThis: function (obj) {
var isChecked = jQuery(obj).is(":checked");
//单选
var userIds = jQuery("#userIds").val();
if (userIds && userIds.split(',').length == 1 && multiple == 0 && isChecked) {
alert("只能选择一个用户");
jQuery(obj).attr("checked", false);
return;
}
var value = jQuery(obj).parents("tr").eq(0).attr("id");
var userArr = this.getSelectedUserArr(userIds, value, isChecked);
jQuery("#userIds").val(userArr.join(","));
this.updateSelectedUserNames();
},
updateSelectedUserNames: function () {
var userIds = jQuery("#userIds").val();
if (userIds == 0 || !userIds) {
jQuery("#userNames").val("");
} else {
ajaxPost(basePath + "/activiti/user/names", {ids: userIds}, function (map) {
jQuery("#userNames").val(map.name);
});
}
},
getSelectedUserArr: function (userIdss, curValue, isChecked) {
var userArr = [];
if (userIdss)
userArr = userIdss.split(",");
if (isChecked) {
var flag = true;
for (var i = 0; i < userArr.length; i++) {
if (userArr[i] == curValue) {
flag = false;
break;
}
}
if (flag)
userArr.push(curValue);
} else {
for (var i = 0; i < userArr.length; i++) {
var userIdValue = userArr[i];
if (userIdValue == curValue) {
userArr.splice(i, 1);
break;
}
}
}
return userArr;
}
}
function fnRenderSelectUser(value) {
return "";
}
//方法入口
jQuery(function () {
userSelectCtrl.initTable();
userSelectCtrl.bindSelectUserEvent();
})
以上代码有三点需要特别注意
(1)使用jQuery选择器时,使用jQuery而不用 ,否则报 (…)未定义的异常,因为弹出的选择器窗口依然在angularJs的域中,不能识别$。
(2)数据回填时,使用controllerScope = jQuery('div[ng-controller="KisBpmAssignmentPopupCtrl"]').scope()
获取回填于对象,然后执行相关操作
(3)因为modeler.html中引用了prototype-1.5.1.js,在使用JSON.stringify时,会调用Array的toJSON方法,从而导致带有数组的JSON格式的字符串参数到后台后无法转换为相应的对象。所以使用了以下toJSONString()对JSON对象进行字符串化。
CommonTable.prototype.toJSONString = function (value) {
var _array_tojson = Array.prototype.toJSON;
delete Array.prototype.toJSON;
var r = JSON.stringify(value);
Array.prototype.toJSON = _array_tojson;
return r;
}