activiti自定义流程之整合(五):启动流程时获取自定义表单

简介: 流程定义部署之后,自然就是流程定义列表了,但和前一节一样的是,这里也是和之前单独的activiti没什么区别,因此也不多说。我们先看看列表页面以及对应的代码,然后在一步步说明点击启动按钮时如何调用自定义的form表单。<br><br><br> 流程定义列表页面如下:<br><img src="http://img.blog.csdn.net/20160414185557292?water
流程定义部署之后,自然就是流程定义列表了,但和前一节一样的是,这里也是和之前单独的activiti没什么区别,因此也不多说。我们先看看列表页面以及对应的代码,然后在一步步说明点击启动按钮时如何调用自定义的form表单。


流程定义列表页面如下:



对应的html代码:

<div id="logdiv1" ng-init="init();">  
   <p style="font-size:24px;margin:3px">流程列表</p>
   <center>
   <table border="1px" style="margin-top:1px;width:87%;font-size:14px;text-align:center;margin-top:1px;margin-left:2px;position:relative;float:left;" cellSpacing="0px" cellPadding="0px">
      <tr style="background-color:#ccc">
         <td>ID</td>
         <td>NAME</td>
         <td>DeploymentID</td>
         <td>KEY</td>
         <td>版本</td>
         <td>resourceName</td>
         <td>DiagramResourceName</td>
         <td>操 作</td>
      </tr>
      <tr ng-repeat="process in processList | orderBy:'id'" >
         <td>{{process.id}}</td>
         <td>{{process.name}}</td>
         <td>{{process.deploymentId}}</td>
         <td>{{process.key}}</td>
         <td>{{process.version}}</td>
         <td>{{process.resourceName}}</td>
         <td>{{process.diagramResourceName}}</td>
         <td><a href="script:;" ng-click="toProcess(process)">启动</a> 
         <a href="script:;" ng-click="deleteProcess(process)">删除</a> 
         </td>
      </tr>
   </table>  
   <div id="handleTemplate" ></div>
   </center>  
</div>  


对应的angularjs代码:
angular.module('activitiApp')  
.controller('processCtr', ['$rootScope','$scope','$http','$location', function($rootScope,$scope,$http,$location){  
$scope.init=function(){
        $http.post("./processList.do").success(function(result) {
        	if(result.isLogin==="yes"){
        	$rootScope.userName=result.userName;
    	    $scope.processList=result.data;
        	}else{
        		$location.path("/login");
        	}
        });
}     
   
    	//开始流程
        $scope.toProcess= function(process){
        	$rootScope.process=process;
        	$('#handleTemplate').html('').dialog({
        		title:'流程名称[' + process.name + ']',
    			modal: true,
    			width: $.common.window.getClientWidth() * 0.6,
    			height: $.common.window.getClientHeight() * 0.9,	
    			open: function() {
    				// 获取json格式的表单数据,就是流程定义中的所有field
    				readForm.call(this, process.deploymentId);
    			},
    			buttons: [{
    				text: '启动流程',
    				click: function() {
    					$("#handleTemplate").dialog("close");
    					sendStartupRequest();
    					setTimeout(function(){
    						window.location.href =("#/findFirstTask");
    					},1500);
    					
    				}
    			}]
    		}).position({
    			   //my: "center",
    			   //at: "center",
    			offset:'300 300',
    			   of: window,
    			   collision:"fit"
    			});
;
    	};
    	//读取流程启动表单
    	function readForm(deploymentId) {
    		var dialog = this;
    		// 读取启动时的表单
    		$.post('./getStartForm.do',deploymentId, function(result) {
    			// 获取的form是字符行,html格式直接显示在对话框内就可以了,然后用form包裹起来
    			
    			$(dialog).append("<div class='formContent' />");
    			$('.formContent').html('').wrap("<form id='startform' class='formkey-form' method='post' />");
    			
    			var $form = $('.formkey-form');


    			// 设置表单action    getStartFormAndStartProcess
    			$form.attr('action', './getStartFormAndStartProcess');
    			//设置部署的Id
    			$form.append("<input type='hidden' name='deploymentId' value="+deploymentId+">");
    			$form.append(result.form);
    			// 初始化日期组件
    			$form.find('.datetime').datetimepicker({
    		           stepMinute: 5
    		     });
    			$form.find('.date').datepicker();
    			
    			// 表单验证
    			$form.validate($.extend({}, $.common.plugin.validator));
    		});
    	}
    	
    	/**
    	 * 提交表单
    	 * @return {[type]} [description]
    	 */
    	function sendStartupRequest() {
    		if ($(".formkey-form").valid()) {
    			var url = './getStartFormAndStartProcess.do';
    			var args = $('#startform').serialize();
    			$.post(url, args, function(data){
    				$("#handleTemplate").dialog("close");
					$location.path("/findFirstTask");
    			});
    		}
    	}
      
  
}])  


在上边的代码中就有需要注意的地方了,从代码中可以看到,当我们点击页面的启动按钮时,会触发toProcess方法,而这个方法就使用到了dialog对话框,对话框中显示的内容便是之前自定义的表单,从后台数据库中请求过来。


那么读取的时候发送了getStartForm.do的请求,后台对应的代码如下:
@RequestMapping(value = "/getStartForm.do", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
	@ResponseBody
	public Object getStartForm(@RequestBody String deploymentId) {
		Map<String, String> map = new HashMap<String, String>();
		String deString = null;
		deString = deploymentId.replaceAll("=", "");
		String form = this.getStartForm1(deString);
		map.put("form", form);
		return map;
	}


	public String getStartForm1(String deploymentId) {
		String deString = null;
		deString = deploymentId.replaceAll("=", "");
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
				.deploymentId(deString).singleResult();
		String form = (String) formService.getRenderedStartForm(pd.getId());
		return form;
	}




要说明的是这里之所以能使用formService.getRenderedStartForm方法,便是因为在上一节部署的时候进行了设置,否则这个方法是无法正常使用的。


那么这个对话框弹出界面视图如下:


需要注意的是dialog的css样式在jquery-ui.css中,不要忘了导入进来,当然了,也可以按自己的喜好修改。


那么填写好相关的数据点击提交,同过上边的js可以知道就走到了后台getStartFormAndStartProcess这里,启动流程实例:

/**
	 * @throws XMLStreamException
	 *             启动流程
	 * 
	 * @author:tuzongxun
	 * @Title: startProcess
	 * @param @return
	 * @return Object
	 * @date Mar 17, 2016 2:06:34 PM
	 * @throws
	 */
	@RequestMapping(value = "/getStartFormAndStartProcess.do", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
	@ResponseBody
	public Object startProcess1(HttpServletRequest req)
			throws XMLStreamException {
		Map<String, String[]> formMap = req.getParameterMap();
		String deploymentId = formMap.get("deploymentId")[0];
		// 拿到第一个data_1设置申请人
		String person1 = (String) formMap.get("data_1")[0];
		Map<String, String> map = new HashMap<String, String>();
		boolean isLogin = this.isLogin(req);
		if (isLogin) {
			if (deploymentId != null) {
				HttpSession session = req.getSession();
				String assginee = (String) session.getAttribute("userName");
				ProcessDefinition pd = repositoryService
						.createProcessDefinitionQuery()
						.deploymentId(deploymentId).singleResult();
				String processDefinitionId = pd.getId();
				Map<String, String> formProperties = new HashMap<String, String>();
				Iterator<FlowElement> iterator1 = this
						.findFlow(processDefinitionId);
				// 取第一个节点,开始节点的行号
				String row = null;
				while (iterator1.hasNext()) {
					FlowElement flowElement = iterator1.next();
					row = flowElement.getXmlRowNumber() + "";
					break;
				}

				// 从request中读取参数然后转换
				Set<Entry<String, String[]>> entrySet = formMap.entrySet();
				for (Entry<String, String[]> entry : entrySet) {
					String key = entry.getKey();
					String value = entry.getValue()[0];
					if (!key.equals("deploymentId")) {
						String keyString = key + row;
						formProperties.put(keyString, value);
					}
				}
				formProperties.put("deploymentId", deploymentId);
				Iterator<FlowElement> iterator = this.findFlow(pd.getId());
				int i = 1;
				while (iterator.hasNext()) {
					FlowElement flowElement = iterator.next(); // 申请人
					if (flowElement.getClass().getSimpleName()
							.equals("UserTask")
							&& i == 1) {
						UserTask userTask = (UserTask) flowElement;
						String assignee = userTask.getAssignee();
						int index1 = assignee.indexOf("{");
						int index2 = assignee.indexOf("}");
						formProperties
								.put(assignee.substring(index1 + 1, index2),
										person1);
						break;
					}
				}
				identityService.setAuthenticatedUserId(assginee);
				ProcessInstance processInstance = formService
						.submitStartFormData(processDefinitionId,
								formProperties);
				map.put("userName",
						(String) req.getSession().getAttribute("userName"));
				map.put("isLogin", "yes");
				map.put("result", "success");
			} else {
				map.put("result", "fail");
			}
		} else {
			map.put("isLogin", "no");
		}
		return map;
	}

而这里最重要的是对前台数据的处理,如果大家使用了ueditor插件,会发现他传递到后台的数据是存放在request中的一个map中,而map的key都是data_1、data_2、data_3的形式。


这样问题就来了,到后边对任务进行操作的时候,这些数据还是这样从data_1开始,那么如果我们原样保存到数据库,以后查询时自然就会有问题了,所以这里就根据每个流程中流程节点行号的唯一性进行了重新组合,然后把这些数据保存为流程变量。


目录
打赏
0
0
0
0
1249
分享
相关文章
首个云超算国标正式发布!
近日,我国首个云超算国家标准GB/T 45400-2025正式发布,将于今年10月实施。该标准由阿里云联合多家机构起草,为云超算在高性能计算领域的应用提供规范。云超算结合传统HPC与云计算优势,解决传统HPC复杂、昂贵等问题。阿里云E-HPC V2.0是国内首批通过该标准认证的产品,支持大规模弹性计算,显著降低成本。新标准将推动算力基础设施迈向标准化、智能化新时代。
快速部署实现Bolt.diy
Bolt.diy 是 Bolt.new 的开源版本,提供灵活的自然语言交互与全栈开发支持。基于阿里云函数计算 FC 和百炼模型服务,最快5分钟完成部署。新手注册阿里云账号后可领取免费额度,按指引开通相关服务并授权。通过项目模板一键部署,配置 API-KEY 后即可使用。Bolt.diy 支持多种场景,如物联网原型开发、久坐提醒、语音控制灯光等,助力快速实现创意应用。
2244 19
【MCP教程系列】在阿里云百炼,实现超级简单的MCP服务部署
阿里云百炼推出业界首个全生命周期MCP服务,支持一键在线注册托管。企业可将自研或外部MCP服务部署于阿里云百炼平台,借助FC函数计算能力,免去资源购买与服务部署的复杂流程,快速实现开发。创建MCP服务仅需四步,平台提供预置服务与自定义部署选项,如通过npx安装代码配置Flomo等服务。还可直接在控制台开通预置服务,体验高效便捷的企业级解决方案。
【MCP教程系列】在阿里云百炼,实现超级简单的MCP服务部署
快速带你上手通义灵码 2.0,体验飞一般的感觉
通义灵码个人版为开发者免费提供智能编码能力,专业版限免期内开放更多功能。使用需先注册阿里云账号,支持JetBrains IDEs、Visual Studio Code等开发工具。以Visual Studio Code为例,安装插件并登录后即可体验其强大功能。通义灵码2.0在代码生成、需求理解及单元测试自动化等方面有显著提升,支持多语言和复杂场景,大幅提高开发效率。
234891 36
快速带你上手通义灵码 2.0,体验飞一般的感觉
一键部署 Dify + MCP Server,高效开发 AI 智能体应用
本文将着重介绍如何通过 SAE 快速搭建 Dify AI 研发平台,依托 Serverless 架构提供全托管、免运维的解决方案,高效开发 AI 智能体应用。
1884 6
阿里云百炼 MCP服务使用教程合集
阿里云百炼推出首个全生命周期MCP服务,支持一键部署、无需运维,具备高可用与低成本特点。该服务提供多类型供给、低成本托管及全链路工具兼容,帮助企业快速构建专属智能体。MCP(模型上下文协议)作为标准化开源协议,助力大模型与外部工具高效交互。教程涵盖简单部署、GitHub运营、数据分析可视化及文档自动化等场景,助您快速上手。欢迎加入阿里云百炼生态,共同推动AI技术发展!
利用通义灵码AI在VS Code中快速开发扫雷游戏:Qwen2.5-Max模型的应用实例
本文介绍了如何利用阿里云通义灵码AI程序员的Qwen2.5-Max模型,在VS Code中一键生成扫雷小游戏。通过安装通义灵码插件并配置模型,输入指令即可自动生成包含游戏逻辑与UI设计的Python代码。生成的游戏支持难度选择,运行稳定无Bug。实践表明,AI工具显著提升开发效率,但人机协作仍是未来趋势。建议开发者积极拥抱新技术,同时不断提升自身技能以适应行业发展需求。
22202 17
MCP Server 开发实战 | 大模型无缝对接 Grafana
以 AI 世界的“USB-C”标准接口——MCP(Model Context Protocol)为例,演示如何通过 MCP Server 实现大模型与阿里云 Grafana 服务的无缝对接,让智能交互更加高效、直观。
475 110
MCP 正当时:FunctionAI MCP 开发平台来了!
Function AI 是基于函数计算构建的 Serverless AI 应用开发平台,基于函数计算的运行时能力上线了完整的 MCP 开发能力,您可以进入 FunctionAI 控制台,快速体验 MCP 服务的能力。
404 10

热门文章

最新文章