基礎(chǔ)環(huán)境搭建完畢,接下來就該正式著手代碼編寫了,在說代碼之前,我覺得有必要先說明一下activit自定義流程的操作。
拋開自定義的表單不談,通過之前的了解,我們知道一個新的流程開始,是在啟動流程實(shí)例(processIntence)的時(shí)候,而流程實(shí)例依賴于流程定義(processDefinition),流程定義又依賴于流程模型(model)。
我們用到的自定義表單需要在創(chuàng)建模型,畫模型圖的時(shí)候就指定表單的名稱formKey,需要保證這個formKey和我們創(chuàng)建的表單名稱一致。
表單并不在創(chuàng)建模型的時(shí)候使用,而是在部署的時(shí)候用到,因此只要是在部署流程定義之前創(chuàng)建自定義表單,那么無論是先創(chuàng)建模型還是先創(chuàng)建表單,只要名稱一致就行。
那么我這里就先創(chuàng)建表單,因?yàn)槲矣X得這樣的話,在創(chuàng)建模型時(shí)可以預(yù)覽,更能保證創(chuàng)建模型的正確性(雖然模型也可以修改);
與之前的自定義表單稍有不同的是,在這個整合的例子中,我用的是angularjs,同時(shí)預(yù)覽時(shí)也用到了jquery中的dialog對話框的功能,也就需要比之前導(dǎo)入更多前端的js,他們?nèi)缦聢D所示。
需要注意的是,dialog的樣式在jquery-ui.js中控制,這個也是網(wǎng)上下載的。
前端首頁index.html代碼如下,因?yàn)閍ngular js為單頁面應(yīng)用,因此實(shí)際上只有一個html聲明,所有的js以及css文件也都需要在index.html中一開始就導(dǎo)入進(jìn)來:
[html]
view plain copy<!DOCTYPE html>
<html ng-app="activitiApp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="./activi_css/activi.css" rel="stylesheet"/>
<script type="text/javascript">
var _root='http://form/index.php?s=/',_controller = 'index';
</script>
<script src="./angular-1.4.0-rc.2/angular.js"></script>
<script src='./angular-1.4.0-rc.2/angular-ui-router.js'></script>
<script src='./activi_js/app.js'></script>
<script src='./activi_js/createCtr.js'></script>
<script src='./activi_js/modelCtr.js'></script>
<script src='./activi_js/processCtr.js'></script>
<script src='./activi_js/taskCtr.js'></script>
<script src='./activi_js/findFirstTaskCtr.js'></script>
<script src='./activi_js/loginCtr.js'></script>
<script src='./activi_js/hisTaskCtr.js'></script>
<script src='./activi_js/completeTaskCtr.js'></script>
<script src='./activi_js/completeTaskTo1Ctr.js'></script>
<script src="./my_js/updateFormCtr.js"></script>
<script src="./my_js/formListCtr.js"></script>
<!-- 導(dǎo)入form相關(guān)的js -->
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link href="form_css/bootstrap/css/bootstrap.css?2023" rel="stylesheet" type="text/css" />
<link href="form_css/site.css?2023" rel="stylesheet" type="text/css" />-->
<link href="form_css/jquery-ui.css" rel="stylesheet" type="text/css" />
<link href="my_css/a.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
var _root='http://form/index.php?s=/',_controller = 'index';
</script>
<script src="form_js/jquery-1.7.2.min.js?2023"></script>
<script src="form_js/common.js"></script>
<script src="form_js/jquery-ui.js"></script>
<script src="form_js/jquery.form.js"></script>
<script src="form_js/ajax.js"></script>
<script src="form_js/common/plugins/validate/jquery.validate.pack.js"></script>
<script src="form_js/jquery.datetimepicker.js"></script>
<script src="form_js/ueditor/ueditor.config.js?2023"></script>
<script src="form_js/ueditor/ueditor.all.js?2023"> </script>
<script src="form_js/ueditor/lang/zh-cn/zh-cn.js?2023"></script>
<script src="form_js/ueditor/formdesign/leipi.formdesign.v4.js?2023"></script>
<!-- 導(dǎo)入form相關(guān)的js -->
</head>
<body style="width:100%;height:400px;margin:0;background-color:#fff">
<div style="height:70px;width:100%;border:1px solid #ccf">
<img id="rdiv" src="./images/activiti.png" style="width:30%;height:98%"/>
<a href="script:;" ng-show="userName!=undefined" style="margin-right:10px;float:right;margin-top:25px;" ng-click="logOut();">
[退出登陸]
</a>
<font ng-show="userName!=undefined" style="margin-right:10px;float:right;margin-top:25px;">當(dāng)前登陸用戶:{{userName}}</font>
</div>
<div style="width:100%;position: absolute;height:auto">
<div style="height:630px;width:12%;font-size:36px;position:relative;float:left;border:1px solid #ccf" ng-show="userName!=undefined">
<table style="width:100%;text-align:center;margin-top:0px" cellSpacing="5px" cellPadding="0px">
<tr>
<td style="background-color:#aac;"><a href="#/create">創(chuàng)建模型</a></td>
</tr>
<tr>
<td style="background-color:#acd;"> <a href="#/modelList">模型列表</a></td>
</tr>
<tr>
<td style="background-color:#aac;"><a href="#/processList">流程列表</a></td>
</tr>
<tr>
<td style="background-color:#acd;"><a href="#/findFirstTask">我的申請</a></td>
</tr>
<tr>
<td style="background-color:#aac;"><a href="#/taskList">我的任務(wù)</a></td>
</tr>
<tr>
<td style="background-color:#acd;"><a href="#/hisTask">歷史任務(wù)</a></td>
</tr>
<tr>
<td style="background-color:#aac;"><a href="#/createForm">創(chuàng)建表單</a></td>
</tr>
<tr>
<td style="background-color:#acd;"><a href="#/formList">表單列表</a></td>
</tr>
</table>
</div>
<div ui-view="view" ></div>
</div>
</body>
</html>
Angular js 控制路由跳轉(zhuǎn)app.js代碼:
[javascript]
view plain copyvar app=angular.module('activitiApp',['ui.router']);
app.run(function($rootScope) {
$rootScope.logOut=function(){
$http.post("./loginOut.do").success(function(loginOutResult){
$rootScope.userName=undefined;
$location.path("/login");
});
}
});
app.config(function($stateProvider,$urlRouterProvider){
$stateProvider
.state('createForm', {
url: "/createForm",
views: {
'view': {
templateUrl: 'my_views/updateForm.html',
controller: 'updateFormCtr'
}
}
});
});
新增form表單的頁面updateForm.html代碼如下,要注意的是,這個頁面也是有ueditor插件中的index.html改變過來的:
[html]
view plain copy<div id="formDiv" style="margin-top:20px;margin-left:50px;height:550px;width:70%;font-size:18px;position:relative;float:left;">
<div class="container">
<form method="post" id="saveform" name="saveform" action="/index.php?s=/index/parse.html">
<input type="hidden" name="fields" id="fields" value="0">
<div style="width:98%;height:500px;margin-top:20px;border:3px solid grey">
<p style="margin-top:10px;font-size:30px" >表單名稱:<input type="text" id="formType"></input></p>
<hr style="height:5px;border:none;border-top:5px ridge green;"/>
<p style="margin-top:10px;font-size:30px" >表單設(shè)計(jì):</p>
<div >
<p style="left:30px">
<button type="button" ng-click="leipiFormDesign.exec('text');" class="btn btn-info">文本框</button>
<button type="button" ng-click="leipiFormDesign.exec('textarea');" class="btn btn-info">多行文本</button>
<button type="button" ng-click="leipiFormDesign.exec('select');" class="btn btn-info">下拉菜單</button>
<button type="button" ng-click="leipiFormDesign.exec('radios');" class="btn btn-info">單選框</button>
<button type="button" ng-click="leipiFormDesign.exec('checkboxs');" class="btn btn-info">復(fù)選框</button>
<button type="button" ng-click="leipiFormDesign.exec('listctrl');" class="btn btn-info">列表控件</button>
<button type="button" ng-click="leipiFormDesign.findForm();" class="btn btn-info">form</button>
</p>
</div>
<!-- afsddddddddd -->
<div >
<script id="myFormDesign" type="text/plain" style="width:99.8%;">
</script>
</div>
</div>
<!-- afsddddddddd -->
<div class="row">
</div><!--end row-->
</form>
</div><!--end container-->
</div>
對應(yīng)的js代碼updateFormCtr.js,這里尤其需要注意的是leipiFormDesign.exec這個方法原本是ueditor插件中的,如果不做修改直接拿過來的話,在上便的頁面中是無法調(diào)用的,angularjs需要注意作用域的問題,因此在對應(yīng)的js中需要改成$scope. leipiFormDesign;除此之外,在保存和預(yù)覽時(shí)基本沒有什么變化,dialog對話框也是在后續(xù)流程中使用到:
[javascript]
view plain copyangular.module('activitiApp')
.controller('updateFormCtr', ['$rootScope','$scope','$http','$location','$state', function($rootScope,$scope,$http,$location,$state){
$http.post("createFlush.do").success(function(result){
if(result.isLogin==="yes"){
$rootScope.userName=result.userName;
}else{
$location.path("/login");
}
});
//預(yù)覽
UE.registerUI('button_preview',function(editor,uiName){
if(!this.options.toolleipi)
{
return false;
}
//注冊按鈕執(zhí)行時(shí)的command命令,使用命令默認(rèn)就會帶有回退操作
editor.registerCommand(uiName,{
execCommand:function(){
try {
$scope.leipiFormDesign.fnReview();
} catch ( e ) {
alert('leipiFormDesign.fnReview 預(yù)覽異常');
}
}
});
//創(chuàng)建一個button
var btn = new UE.ui.Button({
//按鈕的名字
name:uiName,
//提示
title:"預(yù)覽",
//需要添加的額外樣式,指定icon圖標(biāo),這里默認(rèn)使用一個重復(fù)的icon
cssRules :'background-position: -420px -19px;',
//點(diǎn)擊時(shí)執(zhí)行的命令
onclick:function () {
//這里可以不用執(zhí)行命令,做你自己的操作也可
editor.execCommand(uiName);
}
});
//因?yàn)槟闶翘砑觔utton,所以需要返回這個button
return btn;
});
//保存
UE.registerUI('button_save',function(editor,uiName){
if(!this.options.toolleipi)
{
return false;
}
//注冊按鈕執(zhí)行時(shí)的command命令,使用命令默認(rèn)就會帶有回退操作
editor.registerCommand(uiName,{
execCommand:function(){
try {
$scope.leipiFormDesign.fnCheckForm('save');
} catch ( e ) {
alert('leipiFormDesign.fnCheckForm("save") 保存異常');
}
}
});
//創(chuàng)建一個button
var btn = new UE.ui.Button({
//按鈕的名字
name:uiName,
//提示
title:"保存表單",
//需要添加的額外樣式,指定icon圖標(biāo),這里默認(rèn)使用一個重復(fù)的icon
cssRules :'background-position: -481px -20px;',
//點(diǎn)擊時(shí)執(zhí)行的命令
onclick:function () {
//這里可以不用執(zhí)行命令,做你自己的操作也可
editor.execCommand(uiName);
}
});
//因?yàn)槟闶翘砑觔utton,所以需要返回這個button
return btn;
});
//整合設(shè)計(jì)器
var leipiEditor = UE.getEditor('myFormDesign',{
toolleipi:true,//是否顯示,設(shè)計(jì)器的 toolbars
textarea: 'design_content',
//這里可以選擇自己需要的工具按鈕名稱,此處僅選擇如下五個
toolbars:[[
]],
//關(guān)閉字?jǐn)?shù)統(tǒng)計(jì)
wordCount:false,
//關(guān)閉elementPath
elementPathEnabled:false,
//默認(rèn)的編輯區(qū)域高度
initialFrameHeight:260
//,iframeCssUrl:"css/bootstrap/css/bootstrap.css" //引入自身 css使編輯器兼容你網(wǎng)站css
//更多其他參數(shù),請參考ueditor.config.js中的配置項(xiàng)
});
$scope.leipiFormDesign = {
findForm : function(){
window.location.href="my_views/formList.html";
},
/*執(zhí)行控件*/
exec : function (method) {
leipiEditor.execCommand(method);
},
/*
Javascript 解析表單
template 表單設(shè)計(jì)器里的Html內(nèi)容
fields 字段總數(shù)
*/
parse_form:function(template,fields)
{
//正則 radios|checkboxs|select 匹配的邊界 |--| 因?yàn)楫?dāng)使用 {} 時(shí)js報(bào)錯
var preg = /(\|-<span(((?!<span).)*leipiplugins=\"(radios|checkboxs|select)\".*?)>(.*?)<\/span>-\||<(img|input|textarea|select).*?(<\/select>|<\/textarea>|\/>))/gi,preg_attr =/(\w+)=\"(.?|.+?)\"/gi,preg_group =/<input.*?\/>/gi;
if(!fields) fields = 0;
var template_parse = template,template_data = new Array(),add_fields=new Object(),checkboxs=0;
var pno = 0;
template.replace(preg, function(plugin,p1,p2,p3,p4,p5,p6){
var parse_attr = new Array(),attr_arr_all = new Object(),name = '', select_dot = '' , is_new=false;
var p0 = plugin;
var tag = p6 ? p6 : p4;
//alert(tag + " \n- t1 - "+p1 +" \n-2- " +p2+" \n-3- " +p3+" \n-4- " +p4+" \n-5- " +p5+" \n-6- " +p6);
if(tag == 'radios' || tag == 'checkboxs')
{
plugin = p2;
}else if(tag == 'select')
{
plugin = plugin.replace('|-','');
plugin = plugin.replace('-|','');
}
plugin.replace(preg_attr, function(str0,attr,val) {
if(attr=='name')
{
if(val=='leipiNewField')
{
is_new=true;
fields++;
val = 'data_'+fields;
}
name = val;
}
if(tag=='select' && attr=='value')
{
if(!attr_arr_all[attr]) attr_arr_all[attr] = '';
attr_arr_all[attr] += select_dot + val;
select_dot = ',';
}else
{
attr_arr_all[attr] = val;
}
var oField = new Object();
oField[attr] = val;
parse_attr.push(oField);
})
/*alert(JSON.stringify(parse_attr));return;*/
if(tag =='checkboxs') /*復(fù)選組 多個字段 */
{
plugin = p0;
plugin = plugin.replace('|-','');
plugin = plugin.replace('-|','');
var name = 'checkboxs_'+checkboxs;
attr_arr_all['parse_name'] = name;
attr_arr_all['name'] = '';
attr_arr_all['value'] = '';
attr_arr_all['content'] = '<span leipiplugins="checkboxs" title="'+attr_arr_all['title']+'">';
var dot_name ='', dot_value = '';
p5.replace(preg_group, function(parse_group) {
var is_new=false,option = new Object();
parse_group.replace(preg_attr, function(str0,k,val) {
if(k=='name')
{
if(val=='leipiNewField')
{
is_new=true;
fields++;
val = 'data_'+fields;
}
attr_arr_all['name'] += dot_name + val;
dot_name = ',';
}
else if(k=='value')
{
attr_arr_all['value'] += dot_value + val;
dot_value = ',';
}
option[k] = val;
});
if(!attr_arr_all['options']) attr_arr_all['options'] = new Array();
attr_arr_all['options'].push(option);
//if(!option['checked']) option['checked'] = '';
var checked = option['checked'] !=undefined ? 'checked="checked"' : '';
attr_arr_all['content'] +='<input type="checkbox" name="'+option['name']+'" value="'+option['value']+'" '+checked+'/>'+option['value']+' ';
if(is_new)
{
var arr = new Object();
arr['name'] = option['name'];
arr['leipiplugins'] = attr_arr_all['leipiplugins'];
add_fields[option['name']] = arr;
}
});
attr_arr_all['content'] += '</span>';
//parse
template = template.replace(plugin,attr_arr_all['content']);
template_parse = template_parse.replace(plugin,'{'+name+'}');
template_parse = template_parse.replace('{|-','');
template_parse = template_parse.replace('-|}','');
template_data[pno] = attr_arr_all;
checkboxs++;
}else if(name)
{
if(tag =='radios') /*單選組 一個字段*/
{
plugin = p0;
plugin = plugin.replace('|-','');
plugin = plugin.replace('-|','');
attr_arr_all['value'] = '';
attr_arr_all['content'] = '<span leipiplugins="radios" name="'+attr_arr_all['name']+'" title="'+attr_arr_all['title']+'">';
var dot='';
p5.replace(preg_group, function(parse_group) {
var option = new Object();
parse_group.replace(preg_attr, function(str0,k,val) {
if(k=='value')
{
attr_arr_all['value'] += dot + val;
dot = ',';
}
option[k] = val;
});
option['name'] = attr_arr_all['name'];
if(!attr_arr_all['options']) attr_arr_all['options'] = new Array();
attr_arr_all['options'].push(option);
//if(!option['checked']) option['checked'] = '';
var checked = option['checked'] !=undefined ? 'checked="checked"' : '';
attr_arr_all['content'] +='<input type="radio" name="'+attr_arr_all['name']+'" value="'+option['value']+'" '+checked+'/>'+option['value']+' ';
});
attr_arr_all['content'] += '</span>';
}else
{
attr_arr_all['content'] = is_new ? plugin.replace(/leipiNewField/,name) : plugin;
}
template = template.replace(plugin,attr_arr_all['content']);
template_parse = template_parse.replace(plugin,'{'+name+'}');
template_parse = template_parse.replace('{|-','');
template_parse = template_parse.replace('-|}','');
if(is_new)
{
var arr = new Object();
arr['name'] = name;
arr['leipiplugins'] = attr_arr_all['leipiplugins'];
add_fields[arr['name']] = arr;
}
template_data[pno] = attr_arr_all;
}
pno++;
})
var parse_form = new Object({
'fields':fields,//總字段數(shù)
'template':template,//完整html
'parse':template_parse,//控件替換為{data_1}的html
'data':template_data,//控件屬性
'add_fields':add_fields//新增控件
});
return JSON.stringify(parse_form);
},
/*type = save 保存設(shè)計(jì) versions 保存版本 close關(guān)閉 */
fnCheckForm : function ( type ) {
var formType=document.getElementById("formType").value;
if(leipiEditor.queryCommandState( 'source' ))
leipiEditor.execCommand('source');//切換到編輯模式才提交,否則有bug
if(leipiEditor.hasContents()){
leipiEditor.sync();/*同步內(nèi)容*/
//--------------以下僅參考-----------------------------------------------------------------------------------------------------
var type_value='',formid=0,fields=$("#fields").val(),formeditor='';
if( typeof type!=='undefined' ){
type_value = type;
}
console.log(document.getElementById("formType"));
//獲取表單設(shè)計(jì)器里的內(nèi)容
formeditor=leipiEditor.getContent();
//解析表單設(shè)計(jì)器控件
var parse_form = this.parse_form(formeditor,fields);
//異步提交數(shù)據(jù)
$.ajax({
type: 'POST',
url : './addForm.do',
dataType : 'html',
async:false,
//contentType: 'application/json;charset=utf-8',
data : {'type' : type_value,'formid':formid,'parse_form':parse_form,"formType":formType},
success : function(data){
alert("保存成功");
window.location.href ="#/formList";
}
});
} else {
alert('表單內(nèi)容不能為空!')
$('#submitbtn').button('reset');
return false;
}
} ,
/*預(yù)覽表單*/
fnReview : function (){
console.log("111");
if(leipiEditor.queryCommandState( 'source' ))
leipiEditor.execCommand('source');/*切換到編輯模式才提交,否則部分瀏覽器有bug*/
if(leipiEditor.hasContents()){
console.log("222");
leipiEditor.sync(); /*同步內(nèi)容*/
//--------------以下僅參考-------------------------------------------------------------------
/*設(shè)計(jì)form的target 然后提交至一個新的窗口進(jìn)行預(yù)覽*/
var type_value='',formid=0,fields=$("#fields").val(),formeditor='';
var formType=document.getElementById("formType").value;
if( typeof type!=='undefined' ){
type_value = type;
}
console.log("333");
//獲取表單設(shè)計(jì)器里的內(nèi)容
formeditor=leipiEditor.getContent();
//解析表單設(shè)計(jì)器控件
var parse_form = this.parse_form(formeditor,fields);
var forms=JSON.parse(parse_form);
console.log(forms);
console.log(typeof forms);
console.log(forms.template);
var forms1=forms.template;
win_parse=window.open('','','width=800,height=400,alwaysRaised=yes,top=100,left=200');
//win_parse=window.open('','mywin',"menubar=0,toolbar=0,status=0,resizable=1,left=0,top=0,scrollbars=1,width=" +(screen.availWidth-10) + ",height=" + (screen.availHeight-50) + "\"");
var str='<div style="width:500px;height:300px;border:1px solid grey">'+forms1+'</div>';
win_parse.document.write(forms1);
win_parse.focus();
} else {
alert('表單內(nèi)容不能為空!');
return false;
}
}
};
}])
相對于前臺而言,后臺在這里就沒有什么變化了,可以參考之前的自定義表單,代碼便不再羅列。