From 177ffee766aea67c4cd62f01edd906849a2963bc Mon Sep 17 00:00:00 2001 From: Henry Yan Date: Fri, 25 Jan 2013 13:12:20 +0800 Subject: [PATCH 001/173] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e683d29e74..db00747311 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Demo提供Maven版本和no-maven版本,分别适用于会用mavne和不会用m ## Changelog -### 1.6.0(2013-01-06) +### 1.6.0(2013-01-06):+1: 1. 添加多实例(发文会签)演示 2. 添加自动部署流程定义演示 From e4af863f29963a7ad5c72e76e84497f8a5ab20bb Mon Sep 17 00:00:00 2001 From: Henry Yan Date: Thu, 7 Feb 2013 23:11:10 +0800 Subject: [PATCH 002/173] =?UTF-8?q?=E8=AF=BB=E5=8F=96=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=9A=84=E5=9B=BE=E7=89=87=E6=97=B6=E4=BB=8E?= =?UTF-8?q?=E9=9D=99=E6=80=81=E6=9C=8D=E5=8A=A1=E8=AF=BB=E5=8F=96=EF=BC=8C?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=EF=BC=9Ahttp://localhost:10000/leave-formkey?= =?UTF-8?q?/1/leave-formkey.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkflowProcessDefinitionService.java | 259 ++++++++++-------- .../demo/activiti/util/WorkflowUtils.java | 92 +++++-- .../web/workflow/ActivitiController.java | 50 ++-- src/main/resources/application.properties | 5 +- src/main/resources/applicationContext.xml | 79 ++---- .../dynamic/dynamic-form-process-list.jsp | 2 +- .../form/formkey/formkey-process-list.jsp | 2 +- .../WEB-INF/views/form/running-list.jsp | 4 +- .../webapp/WEB-INF/views/oa/leave/running.jsp | 2 +- .../WEB-INF/views/workflow/process-list.jsp | 11 +- src/main/webapp/common/global.jsp | 9 +- .../webapp/js/module/activiti/workflow.js | 4 +- .../activiti/process/ProcessTestDispatch.java | 7 - .../oa/leave/LeaveWorkflowServiceTest.java | 2 +- .../web/workflow/ActivitiControllerTest.java | 4 +- 15 files changed, 312 insertions(+), 220 deletions(-) diff --git a/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowProcessDefinitionService.java b/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowProcessDefinitionService.java index 1d92319863..b424884fb2 100644 --- a/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowProcessDefinitionService.java +++ b/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowProcessDefinitionService.java @@ -2,12 +2,16 @@ import java.io.IOException; import java.io.InputStream; +import java.util.List; import java.util.zip.ZipInputStream; +import me.kafeitu.demo.activiti.util.WorkflowUtils; + import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; @@ -22,124 +26,149 @@ * 工作流中流程以及流程实例相关Service * * @author HenryYan - * + * */ @Service public class WorkflowProcessDefinitionService { - protected Logger logger = LoggerFactory.getLogger(getClass()); - - @Autowired - protected RuntimeService runtimeService; - - @Autowired - protected RepositoryService repositoryService; - - @Autowired - protected HistoryService historyService; - - /** - * 根据流程实例ID查询流程定义对象{@link ProcessDefinition} - * @param processInstanceId 流程实例ID - * @return 流程定义对象{@link ProcessDefinition} - */ - public ProcessDefinition findProcessDefinitionByPid(String processInstanceId) { - HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() - .processInstanceId(processInstanceId).singleResult(); - String processDefinitionId = historicProcessInstance.getProcessDefinitionId(); - ProcessDefinition processDefinition = findProcessDefinition(processDefinitionId); - return processDefinition; - } - - /** - * 根据流程定义ID查询流程定义对象{@link ProcessDefinition} - * @param processDefinitionId 流程定义对象ID - * @return 流程定义对象{@link ProcessDefinition} - */ - public ProcessDefinition findProcessDefinition(String processDefinitionId) { - ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() - .processDefinitionId(processDefinitionId).singleResult(); - return processDefinition; - } - - /** - * 部署classpath下面的流程定义 - *

从属性配置文件中获取属性workflow.modules扫描**deployments**

- *

然后从每个**deployments/${module}**查找在属性配置文件中的属性**workflow.module.keys.${submodule}** - *

配置实例: - *

-	 *	#workflow for deploy
-	 *	workflow.modules=budget,erp,oa
-	 *	workflow.module.keys.budget=budget
-	 *	workflow.module.keys.erp=acceptInsurance,billing,effectInsurance,endorsement,payment
-	 *	workflow.module.keys.oa=caruse,leave,officalstamp,officesupply,out,overtime
-	 *	

- * @param processKey 流程定义KEY - * @throws Exception - */ - public void deployFromClasspath(String... processKey) throws Exception { - ResourceLoader resourceLoader = new DefaultResourceLoader(); - String[] processKeys = { "leave", "leave-dynamic-from", "leave-formkey", "dispatch" }; - for (String loopProcessKey : processKeys) { - - /* - * 需要过滤指定流程 - */ - if (ArrayUtils.isNotEmpty(processKey)) { - if (ArrayUtils.contains(processKey, loopProcessKey)) { - logger.debug("hit module of {}", processKey); - deploySingleProcess(resourceLoader, loopProcessKey); - } else { - logger.debug("module: {} not equals process key: {}, ignore and continue find next.", loopProcessKey, - processKey); - } - } else { - /* - * 所有流程 - */ - deploySingleProcess(resourceLoader, loopProcessKey); - } - } - } - - /** - * 部署单个流程定义 - * @param resourceLoader {@link ResourceLoader} - * @param processKey 模块名称 - * @param subModule 流程定义名称 - * @throws IOException 找不到zip文件时 - */ - private void deploySingleProcess(ResourceLoader resourceLoader, String processKey) throws IOException { - String classpathResourceUrl = "classpath:/deployments/" + processKey + ".bar"; - logger.debug("read workflow from: {}", classpathResourceUrl); - Resource resource = resourceLoader.getResource(classpathResourceUrl); - InputStream inputStream = resource.getInputStream(); - if (inputStream == null) { - logger.warn("ignore deploy workflow module: {}", classpathResourceUrl); - } else { - logger.debug("finded workflow module: {}, deploy it!", classpathResourceUrl); - ZipInputStream zis = new ZipInputStream(inputStream); - repositoryService.createDeployment().addZipInputStream(zis).deploy(); - } - } - - /** - * 重新部署单个流程定义 - * @param processKey 流程定义KEY - * @throws Exception - * @see #deployFromClasspath - */ - public void redeploy(String... processKey) throws Exception { - this.deployFromClasspath(processKey); - } - - /** - * 重新部署所有流程定义,调用:{@link #deployFromClasspath()}完成功能 - * @throws Exception - * @see #deployFromClasspath - */ - public void deployAllFromClasspath() throws Exception { - this.deployFromClasspath(); - } + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + protected RuntimeService runtimeService; + + @Autowired + protected RepositoryService repositoryService; + + @Autowired + protected HistoryService historyService; + + /** + * 根据流程实例ID查询流程定义对象{@link ProcessDefinition} + * + * @param processInstanceId + * 流程实例ID + * @return 流程定义对象{@link ProcessDefinition} + */ + public ProcessDefinition findProcessDefinitionByPid(String processInstanceId) { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + String processDefinitionId = historicProcessInstance.getProcessDefinitionId(); + ProcessDefinition processDefinition = findProcessDefinition(processDefinitionId); + return processDefinition; + } + + /** + * 根据流程定义ID查询流程定义对象{@link ProcessDefinition} + * + * @param processDefinitionId + * 流程定义对象ID + * @return 流程定义对象{@link ProcessDefinition} + */ + public ProcessDefinition findProcessDefinition(String processDefinitionId) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); + return processDefinition; + } + + /** + * 部署classpath下面的流程定义 + *

+ * 从属性配置文件中获取属性workflow.modules扫描**deployments** + *

+ *

+ * 然后从每个**deployments/${module}**查找在属性配置文件中的属性**workflow.module.keys.${ + * submodule}** + *

+ * 配置实例: + * + *

+   * #workflow for deploy
+   * workflow.modules=budget,erp,oa
+   * workflow.module.keys.budget=budget
+   * workflow.module.keys.erp=acceptInsurance,billing,effectInsurance,endorsement,payment
+   * workflow.module.keys.oa=caruse,leave,officalstamp,officesupply,out,overtime
+   * 
+ * + *

+ * + * @param processKey + * 流程定义KEY + * @throws Exception + */ + public void deployFromClasspath(String exportDir, String... processKey) throws Exception { + ResourceLoader resourceLoader = new DefaultResourceLoader(); + String[] processKeys = { "leave", "leave-dynamic-from", "leave-formkey", "dispatch" }; + for (String loopProcessKey : processKeys) { + + /* + * 需要过滤指定流程 + */ + if (ArrayUtils.isNotEmpty(processKey)) { + if (ArrayUtils.contains(processKey, loopProcessKey)) { + logger.debug("hit module of {}", processKey); + deploySingleProcess(resourceLoader, loopProcessKey, exportDir); + } else { + logger.debug("module: {} not equals process key: {}, ignore and continue find next.", loopProcessKey, processKey); + } + } else { + /* + * 所有流程 + */ + deploySingleProcess(resourceLoader, loopProcessKey, exportDir); + } + } + } + + /** + * 部署单个流程定义 + * + * @param resourceLoader + * {@link ResourceLoader} + * @param processKey + * 模块名称 + * @param subModule + * 流程定义名称 + * @throws IOException + * 找不到zip文件时 + */ + private void deploySingleProcess(ResourceLoader resourceLoader, String processKey, String exportDir) throws IOException { + String classpathResourceUrl = "classpath:/deployments/" + processKey + ".bar"; + logger.debug("read workflow from: {}", classpathResourceUrl); + Resource resource = resourceLoader.getResource(classpathResourceUrl); + InputStream inputStream = resource.getInputStream(); + if (inputStream == null) { + logger.warn("ignore deploy workflow module: {}", classpathResourceUrl); + } else { + logger.debug("finded workflow module: {}, deploy it!", classpathResourceUrl); + ZipInputStream zis = new ZipInputStream(inputStream); + Deployment deployment = repositoryService.createDeployment().addZipInputStream(zis).deploy(); + + // export diagram + List list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list(); + for (ProcessDefinition processDefinition : list) { + WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir); + } + } + } + + /** + * 重新部署单个流程定义 + * + * @param processKey + * 流程定义KEY + * @throws Exception + * @see #deployFromClasspath + */ + public void redeploy(String exportDir, String... processKey) throws Exception { + this.deployFromClasspath(exportDir, processKey); + } + + /** + * 重新部署所有流程定义,调用:{@link #deployFromClasspath()}完成功能 + * + * @throws Exception + * @see #deployFromClasspath + */ + public void deployAllFromClasspath(String exportDir) throws Exception { + this.deployFromClasspath(exportDir); + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/util/WorkflowUtils.java b/src/main/java/me/kafeitu/demo/activiti/util/WorkflowUtils.java index 72085c17be..b4fbd03d4d 100644 --- a/src/main/java/me/kafeitu/demo/activiti/util/WorkflowUtils.java +++ b/src/main/java/me/kafeitu/demo/activiti/util/WorkflowUtils.java @@ -1,30 +1,86 @@ package me.kafeitu.demo.activiti.util; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.Map; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.repository.ProcessDefinition; +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * - * + * * @author HenryYan */ public class WorkflowUtils { - /** - * 转换流程节点类型为中文说明 - * @param type 英文名称 - * @return 翻译后的中文名称 - */ - public static String parseToZhType(String type) { - Map types = new HashMap(); - types.put("userTask", "用户任务"); - types.put("serviceTask", "系统任务"); - types.put("startEvent", "开始节点"); - types.put("endEvent", "结束节点"); - types.put("exclusiveGateway", "条件判断节点(系统自动根据条件处理)"); - types.put("inclusiveGateway", "并行处理任务"); - types.put("callActivity", "子流程"); - return types.get(type) == null ? type: types.get(type); - } - + private static Logger logger = LoggerFactory.getLogger(WorkflowUtils.class); + + /** + * 转换流程节点类型为中文说明 + * + * @param type + * 英文名称 + * @return 翻译后的中文名称 + */ + public static String parseToZhType(String type) { + Map types = new HashMap(); + types.put("userTask", "用户任务"); + types.put("serviceTask", "系统任务"); + types.put("startEvent", "开始节点"); + types.put("endEvent", "结束节点"); + types.put("exclusiveGateway", "条件判断节点(系统自动根据条件处理)"); + types.put("inclusiveGateway", "并行处理任务"); + types.put("callActivity", "子流程"); + return types.get(type) == null ? type : types.get(type); + } + + /** + * 导出图片文件到硬盘 + * + * @return 文件的全路径 + */ + public static String exportDiagramToFile(RepositoryService repositoryService, ProcessDefinition processDefinition, String exportDir) throws IOException { + String diagramResourceName = processDefinition.getDiagramResourceName(); + String key = processDefinition.getKey(); + int version = processDefinition.getVersion(); + String diagramPath = ""; + + InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), diagramResourceName); + byte[] b = new byte[resourceAsStream.available()]; + + @SuppressWarnings("unused") + int len = -1; + resourceAsStream.read(b, 0, b.length); + + // create file if not exist + String diagramDir = exportDir + "/" + key + "/" + version; + File diagramDirFile = new File(diagramDir); + if (!diagramDirFile.exists()) { + diagramDirFile.mkdirs(); + } + diagramPath = diagramDir + "/" + diagramResourceName; + File file = new File(diagramPath); + + // 文件存在退出 + if (file.exists()) { + // 文件大小相同时直接返回否则重新创建文件(可能损坏) + logger.debug("diagram exist, ignore... : {}", diagramPath); + return diagramPath; + } else { + file.createNewFile(); + } + + logger.debug("export diagram to : {}", diagramPath); + + // wirte bytes to file + FileUtils.writeByteArrayToFile(file, b, true); + return diagramPath; + } + } diff --git a/src/main/java/me/kafeitu/demo/activiti/web/workflow/ActivitiController.java b/src/main/java/me/kafeitu/demo/activiti/web/workflow/ActivitiController.java index 08ffb3aad5..ae037b0916 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/workflow/ActivitiController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/workflow/ActivitiController.java @@ -1,5 +1,6 @@ package me.kafeitu.demo.activiti.web.workflow; +import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -14,8 +15,8 @@ import me.kafeitu.demo.activiti.service.activiti.WorkflowProcessDefinitionService; import me.kafeitu.demo.activiti.service.activiti.WorkflowTraceService; import me.kafeitu.demo.activiti.util.UserUtil; +import me.kafeitu.demo.activiti.util.WorkflowUtils; -import org.activiti.engine.ActivitiException; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; @@ -28,6 +29,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -93,8 +95,8 @@ public ModelAndView processList() { * @throws Exception */ @RequestMapping(value = "/redeploy/all") - public String redeployAll() throws Exception { - workflowProcessDefinitionService.deployAllFromClasspath(); + public String redeployAll(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir) throws Exception { + workflowProcessDefinitionService.deployAllFromClasspath(exportDir); return "redirect:/workflow/process-list"; } @@ -178,30 +180,28 @@ public List> traceProcess(@RequestParam("pid") String proces } @RequestMapping(value = "/deploy") - public String deploy(@RequestParam(value = "file", required = false) MultipartFile file) { + public String deploy(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir, @RequestParam(value = "file", required = false) MultipartFile file) { String fileName = file.getOriginalFilename(); try { InputStream fileInputStream = file.getInputStream(); + Deployment deployment = null; String extension = FilenameUtils.getExtension(fileName); if (extension.equals("zip") || extension.equals("bar")) { ZipInputStream zip = new ZipInputStream(fileInputStream); - repositoryService.createDeployment().addZipInputStream(zip).deploy(); - } else if (extension.equals("png")) { - repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy(); - } else if (fileName.indexOf("bpmn20.xml") != -1) { - repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy(); - } else if (extension.equals("bpmn")) { - /* - * bpmn扩展名特殊处理,转换为bpmn20.xml - */ - String baseName = FilenameUtils.getBaseName(fileName); - repositoryService.createDeployment().addInputStream(baseName + ".bpmn20.xml", fileInputStream).deploy(); + deployment = repositoryService.createDeployment().addZipInputStream(zip).deploy(); } else { - throw new ActivitiException("no support file type of " + extension); + deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy(); } + + List list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list(); + + for (ProcessDefinition processDefinition : list) { + WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir); + } + } catch (Exception e) { logger.error("error on deploy process, because of file input stream", e); } @@ -280,6 +280,24 @@ public String updateState(@PathVariable("state") String state, @PathVariable("pr return "redirect:/workflow/process-list"; } + /** + * 导出图片文件到硬盘 + * + * @return + */ + @RequestMapping(value = "export/diagrams") + @ResponseBody + public List exportDiagrams(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir) throws IOException { + List files = new ArrayList(); + List list = repositoryService.createProcessDefinitionQuery().list(); + + for (ProcessDefinition processDefinition : list) { + files.add(WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir)); + } + + return files; + } + @Autowired public void setWorkflowProcessDefinitionService(WorkflowProcessDefinitionService workflowProcessDefinitionService) { this.workflowProcessDefinitionService = workflowProcessDefinitionService; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c672a4c506..d2bdd7be42 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -25,4 +25,7 @@ dbcp.maxIdle=10 #versions system.version=${project.version} -activiti.version=${activiti.version} \ No newline at end of file +activiti.version=${activiti.version} + +export.diagram.path=/tmp/kft-activiti-demo +diagram.http.url=http://localhost:10000 \ No newline at end of file diff --git a/src/main/resources/applicationContext.xml b/src/main/resources/applicationContext.xml index d763674700..b78cedce45 100644 --- a/src/main/resources/applicationContext.xml +++ b/src/main/resources/applicationContext.xml @@ -1,17 +1,40 @@ Spring公共配置 + + + + + + + + + + + + + + + + + + + + + @@ -21,7 +44,7 @@ - + ${hibernate.dialect} @@ -53,14 +76,14 @@ - + classpath*:/deployments/* - + @@ -81,50 +104,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-process-list.jsp b/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-process-list.jsp index c9c447eaf9..1fe070f3c6 100644 --- a/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-process-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-process-list.jsp @@ -53,7 +53,7 @@ ${process.key } ${process.version } ${process.resourceName } - ${process.diagramResourceName } + ${process.diagramResourceName } 启动 diff --git a/src/main/webapp/WEB-INF/views/form/formkey/formkey-process-list.jsp b/src/main/webapp/WEB-INF/views/form/formkey/formkey-process-list.jsp index e4cf82fb95..04aeb69780 100644 --- a/src/main/webapp/WEB-INF/views/form/formkey/formkey-process-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/formkey/formkey-process-list.jsp @@ -54,7 +54,7 @@ ${process.key } ${process.version } ${process.resourceName } - ${process.diagramResourceName } + ${process.diagramResourceName } 启动 diff --git a/src/main/webapp/WEB-INF/views/form/running-list.jsp b/src/main/webapp/WEB-INF/views/form/running-list.jsp index 8c8b759853..6b824293d9 100644 --- a/src/main/webapp/WEB-INF/views/form/running-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/running-list.jsp @@ -46,11 +46,13 @@ + ${p.id } ${p.processInstanceId } ${p.processDefinitionId } - <%=ProcessDefinitionCache.getActivityName(pageContext.getAttribute("pdid").toString(), ObjectUtils.toString(pageContext.getAttribute("activityId"))) %> + + <%=ProcessDefinitionCache.getActivityName(pageContext.getAttribute("pdid").toString(), ObjectUtils.toString(pageContext.getAttribute("activityId"))) %> ${p.suspended } diff --git a/src/main/webapp/WEB-INF/views/oa/leave/running.jsp b/src/main/webapp/WEB-INF/views/oa/leave/running.jsp index aa9a29328d..905a27383c 100644 --- a/src/main/webapp/WEB-INF/views/oa/leave/running.jsp +++ b/src/main/webapp/WEB-INF/views/oa/leave/running.jsp @@ -53,7 +53,7 @@ ${leave.startTime } ${leave.endTime } - ${task.name } + ${task.name } ${task.createTime } ${pi.suspended ? "已挂起" : "正常" };V: ${leave.processDefinition.version } diff --git a/src/main/webapp/WEB-INF/views/workflow/process-list.jsp b/src/main/webapp/WEB-INF/views/workflow/process-list.jsp index 6bfbed729f..48534833c4 100644 --- a/src/main/webapp/WEB-INF/views/workflow/process-list.jsp +++ b/src/main/webapp/WEB-INF/views/workflow/process-list.jsp @@ -30,6 +30,12 @@ }).click(function() { $('#deployFieldset').toggle('normal'); }); + + $('#export-diagram').button({ + icons: { + primary: 'ui-icon-image' + } + }); }); @@ -45,7 +51,8 @@
提示:点击xml或者png链接可以查看具体内容!
部署流程 - 重新部署流程 + 重新部署流程 + 手动导出流程图片