diff --git a/build.gradle b/build.gradle index 93474bb..373ff8b 100644 --- a/build.gradle +++ b/build.gradle @@ -60,6 +60,18 @@ dependencies { compile group: 'commons-lang', name: 'commons-lang', version: '2.6' + + compile group: 'org.projectlombok', name: 'lombok', version: '1.16.20' + + /*activiti start*/ + compile group: 'org.activiti', name: 'activiti-spring-boot-starter-basic', version: '6.0.0' + + /*activiti在线编辑器相关*/ + compile group: 'org.activiti', name: 'activiti-json-converter', version: '6.0.0' + compile group: 'org.apache.xmlgraphics', name: 'batik-codec', version: '1.7' + /*activiti end*/ + + compileOnly 'org.springframework.boot:spring-boot-configuration-processor' testCompile 'junit:junit:4.12' diff --git a/src/main/java/cn/palmte/work/config/activiti/ActConstant.java b/src/main/java/cn/palmte/work/config/activiti/ActConstant.java new file mode 100644 index 0000000..aa7df89 --- /dev/null +++ b/src/main/java/cn/palmte/work/config/activiti/ActConstant.java @@ -0,0 +1,22 @@ +package cn.palmte.work.config.activiti; + +public class ActConstant { + + /** + * 流程启动用户变量 + */ + public static final String START_PROCESS_USERID="startUserId"; + + + public static final String PROC_INS_ID="procInsId"; + + /** + * 第一个用户任务 即:发起申请任务 + */ + public static final int TASK_INDEX_FIRST_USER_TASK= 1; + + public static final int TYPE_APPROVE= 1; + public static final int TYPE_ROLLBACK= 2; + + +} diff --git a/src/main/java/cn/palmte/work/config/activiti/ActivitiConfig.java b/src/main/java/cn/palmte/work/config/activiti/ActivitiConfig.java new file mode 100644 index 0000000..513994d --- /dev/null +++ b/src/main/java/cn/palmte/work/config/activiti/ActivitiConfig.java @@ -0,0 +1,39 @@ +package cn.palmte.work.config.activiti; + +import org.activiti.spring.SpringProcessEngineConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; + +import javax.sql.DataSource; + + +@Configuration +public class ActivitiConfig { + + @Autowired + PlatformTransactionManager transactionManager; + + @Autowired + DataSource dataSource; + + @Bean + public SpringProcessEngineConfiguration getProcessEngineConfiguration() { + SpringProcessEngineConfiguration config = new SpringProcessEngineConfiguration(); + config.setDataSource(dataSource); + config.setTransactionManager(transactionManager); + config.setDbHistoryUsed(true); + config.setHistory("full"); + config.setActivityFontName("宋体"); + + //数据库更新策略 + //flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。(生产环境常用) + //true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。(开发时常用) + //create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。(单元测试常用) + //drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。 + config.setDatabaseSchemaUpdate("true"); + return config; + } + +} diff --git a/src/main/java/cn/palmte/work/controller/backend/ActModelController.java b/src/main/java/cn/palmte/work/controller/backend/ActModelController.java new file mode 100644 index 0000000..b625664 --- /dev/null +++ b/src/main/java/cn/palmte/work/controller/backend/ActModelController.java @@ -0,0 +1,82 @@ +package cn.palmte.work.controller.backend; + + +import cn.palmte.work.bean.ResponseMsg; +import cn.palmte.work.service.ActModelService; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 流程模型 + */ +@Controller +@RequestMapping("/actModel") +public class ActModelController extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(ActModelController.class); + + @Autowired + private ActModelService activitiModelService; + + @RequestMapping("/list") + public String list(@RequestParam(value = "keywords", required = false) String keywords, + @RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber, + @RequestParam(value = PAGE_SIZE, defaultValue = DEFAULT_PAGE_SIZE) int pageSize, + Map model) { + ConcurrentHashMap searchInfo = getSearchInfo(keywords, model); + model.put("pager", activitiModelService.list(searchInfo, pageNumber, pageSize)); + return "/admin/act_model_list"; + } + + @GetMapping(value = "/add") + public String add(Map model) { + return "/admin/act_model_input"; + } + + @RequestMapping("/save") + public String save(HttpServletRequest request) { + try { + activitiModelService.createModel(request.getParameter("procDefKey"), request.getParameter("modelName")); + } catch (Exception e) { + logger.error("", e); + } + return "redirect:/actModel/list"; + } + + + @ResponseBody + @GetMapping(value = "/delete") + public ResponseMsg delete(@RequestParam("ids") String ids) { + if ("".equals(ids)) { + return ResponseMsg.buildFailedMsg("删除失败,无选中项!"); + } else { + String[] deleteIds = ids.split("#%#"); + for (String id : deleteIds) { + activitiModelService.deleteModel(id); + } + return ResponseMsg.buildSuccessMsg("删除成功"); + } + } + + + @ResponseBody + @GetMapping(value = "/deploy") + public ResponseMsg deploy(@RequestParam("id") String id) { + try { + activitiModelService.deploy(id); + } catch (Exception e) { + logger.error("", e); + return ResponseMsg.buildFailedMsg(e.getMessage()); + } + return ResponseMsg.buildSuccessMsg("部署成功"); + } + +} diff --git a/src/main/java/cn/palmte/work/controller/backend/ActModelEditorController.java b/src/main/java/cn/palmte/work/controller/backend/ActModelEditorController.java new file mode 100644 index 0000000..9a1e038 --- /dev/null +++ b/src/main/java/cn/palmte/work/controller/backend/ActModelEditorController.java @@ -0,0 +1,132 @@ +package cn.palmte.work.controller.backend; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.activiti.editor.constants.ModelDataJsonConstants; +import org.activiti.engine.ActivitiException; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.repository.Model; +import org.apache.batik.transcoder.TranscoderInput; +import org.apache.batik.transcoder.TranscoderOutput; +import org.apache.batik.transcoder.image.PNGTranscoder; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * 流程网页编辑器 + */ +@RestController +public class ActModelEditorController implements ModelDataJsonConstants { + + protected static final Logger LOGGER = LoggerFactory.getLogger(ActModelEditorController.class); + + @Autowired + private RepositoryService repositoryService; + + @Autowired + private ObjectMapper objectMapper; + + + /** + * 获取编辑器汉化文件 + * + * @return + */ + @ResponseBody + @RequestMapping(value = "/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8") + public String getStencilset() { + InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json"); + try { + return IOUtils.toString(stencilsetStream, "utf-8"); + } catch (Exception e) { + //logger.error("an exception happens in try catch statement", e); + throw new ActivitiException("Error while loading stencil set", e); + } finally { + if (stencilsetStream != null) { + try { + stencilsetStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + + /** + * 根据模型id获取json格式的数据 + * + * @param modelId + * @return + */ + @RequestMapping(value = "/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json") + public ObjectNode getEditorJson(@PathVariable String modelId) { + ObjectNode modelNode = null; + Model model = repositoryService.getModel(modelId); + if (model != null) { + try { + if (StringUtils.isNotEmpty(model.getMetaInfo())) { + modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo()); + } else { + modelNode = objectMapper.createObjectNode(); + modelNode.put(MODEL_NAME, model.getName()); + } + modelNode.put(MODEL_ID, model.getId()); + String content = new String(repositoryService.getModelEditorSource(model.getId()), "utf-8"); + ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(content); + modelNode.put("model", editorJsonNode); + } catch (Exception e) { + LOGGER.error("an exception happens in try catch statement", e); + throw new ActivitiException("Error creating model JSON", e); + } + } + return modelNode; + } + + + /** + * 报错模型数据 + * + * @param modelId + * @param values + */ + @ResponseStatus(value = HttpStatus.OK) + @RequestMapping(value = "/model/{modelId}/save", method = RequestMethod.PUT) + public void saveModel(@PathVariable String modelId, @RequestParam MultiValueMap values) { + try { + Model model = repositoryService.getModel(modelId); + ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo()); + modelJson.put(MODEL_NAME, values.getFirst("name")); + modelJson.put(MODEL_DESCRIPTION, values.getFirst("description")); + model.setMetaInfo(modelJson.toString()); + model.setName(values.getFirst("name")); + repositoryService.saveModel(model); + repositoryService.addModelEditorSource(model.getId(), values.getFirst("json_xml").getBytes("utf-8")); + InputStream svgStream = new ByteArrayInputStream(values.getFirst("svg_xml").getBytes("utf-8")); + TranscoderInput input = new TranscoderInput(svgStream); + PNGTranscoder transcoder = new PNGTranscoder(); + // Setup output + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + TranscoderOutput output = new TranscoderOutput(outStream); + // Do the transformation + transcoder.transcode(input, output); + final byte[] result = outStream.toByteArray(); + repositoryService.addModelEditorSourceExtra(model.getId(), result); + outStream.close(); + } catch (Exception e) { + LOGGER.error("an exception happens in try catch statement", e); + throw new ActivitiException("Error saving model", e); + } + } +} diff --git a/src/main/java/cn/palmte/work/controller/backend/ActProcDefController.java b/src/main/java/cn/palmte/work/controller/backend/ActProcDefController.java new file mode 100644 index 0000000..e1d6625 --- /dev/null +++ b/src/main/java/cn/palmte/work/controller/backend/ActProcDefController.java @@ -0,0 +1,100 @@ +package cn.palmte.work.controller.backend; + + +import cn.palmte.work.bean.ResponseMsg; +import cn.palmte.work.service.ActProcDefService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 流程定义 + */ +@Controller +@RequestMapping("/actProcDef") +public class ActProcDefController extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(ActProcDefController.class); + + @Autowired + private ActProcDefService actProcDefService; + + @RequestMapping("/list") + public String list(@RequestParam(value = "keywords", required = false) String keywords, + @RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber, + @RequestParam(value = PAGE_SIZE, defaultValue = DEFAULT_PAGE_SIZE) int pageSize, + Map model) { + ConcurrentHashMap searchInfo = getSearchInfo(keywords, model); + model.put("pager", actProcDefService.list(searchInfo, pageNumber, pageSize)); + return "/admin/act_proc_def_list"; + } + + + /** + * 查看默认的未标红的流程图片 + * + * @param response + * @param deploymentId + * @throws Exception + */ + @RequestMapping("/procDefPng/{deploymentId}") + public void png(HttpServletResponse response, @PathVariable("deploymentId") String deploymentId) throws Exception { + actProcDefService.createProcDefPng(response, deploymentId); + } + + + /** + * 查看流程xml + * + * @param deploymentId + * @return + */ + @RequestMapping("/xml/{deploymentId}") + public void xml(HttpServletResponse response, @PathVariable("deploymentId") String deploymentId) throws Exception { + actProcDefService.getXmlByDeploymentId(response, deploymentId); + } + + + /** + * 删除流程 + * + * @param ids + * @return + */ + @ResponseBody + @GetMapping(value = "/delete") + public ResponseMsg delete(@RequestParam("ids") String ids) { + if ("".equals(ids)) { + return ResponseMsg.buildFailedMsg("删除失败,无选中项!"); + } else { + String[] deleteIds = ids.split("#%#"); + for (String id : deleteIds) { + actProcDefService.deleteDeployment(id); + } + return ResponseMsg.buildSuccessMsg("删除成功"); + } + } + + + /** + * 挂起与激活 + * + * @param id + * @param status 1-激活 2-挂起 + * @return + */ + @ResponseBody + @GetMapping(value = "/suspend") + public String suspend(@RequestParam String id, @RequestParam int status) { + actProcDefService.suspend(id, status); + return "redirect:/actProcDef/list"; + } + + +} diff --git a/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java b/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java new file mode 100644 index 0000000..49ca359 --- /dev/null +++ b/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java @@ -0,0 +1,92 @@ +package cn.palmte.work.controller.backend; + + +import cn.palmte.work.bean.ResponseMsg; +import cn.palmte.work.config.activiti.ActConstant; +import cn.palmte.work.service.ActProcInsService; +import cn.palmte.work.utils.InterfaceUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 流程实列相关 + */ +@Controller +@RequestMapping("/actProcIns") +public class ActProcInsController extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(ActProcInsController.class); + + @Autowired + private ActProcInsService actProcInsService; + + /** + * 列表 + * @param keywords + * @param pageNumber + * @param pageSize + * @param model + * @return + */ + @RequestMapping("/list") + public String list(@RequestParam(value = "keywords", required = false) String keywords, + @RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber, + @RequestParam(value = PAGE_SIZE, defaultValue = DEFAULT_PAGE_SIZE) int pageSize, + Map model) { + ConcurrentHashMap searchInfo = getSearchInfo(keywords, model); + model.put("pager", actProcInsService.list(searchInfo, pageNumber, pageSize)); + return "/admin/act_proc_ins_list"; + } + + + /** + * 删除流程实例 + * + * @param procInsId + * @param reason + * @return + */ + @ResponseBody + @GetMapping(value = "/deleteProcessInstance") + public ResponseMsg deleteProcessInstance(@RequestParam String procInsId, @RequestParam String reason) { + actProcInsService.deleteProcessInstance(procInsId, reason); + return ResponseMsg.buildSuccessMsg("撤销成功"); + } + + + /** + * 流程实列图片 + * + * @param response + * @param procInstId + * @throws Exception + */ + @RequestMapping("/procInsPng/{procInstId}") + public void png(HttpServletResponse response, @PathVariable("procInstId") String procInstId) throws Exception { + actProcInsService.createProcInsPng(response, procInstId); + } + + /** + * 启动流程 + * + * @return + */ + @ResponseBody + @GetMapping(value = "/startProcIns") + public ResponseMsg startProcessInstance(@RequestParam String procDefKey) throws Exception{ + Map variables = new HashMap<>(); + variables.put(ActConstant.START_PROCESS_USERID, InterfaceUtil.getAdminId()); + String procInsId = actProcInsService.startProcessInstance(procDefKey, variables); + return ResponseMsg.buildSuccessMsg("流程启动成功", procInsId); + } + + +} diff --git a/src/main/java/cn/palmte/work/controller/backend/ActScriptController.java b/src/main/java/cn/palmte/work/controller/backend/ActScriptController.java new file mode 100644 index 0000000..113a38b --- /dev/null +++ b/src/main/java/cn/palmte/work/controller/backend/ActScriptController.java @@ -0,0 +1,119 @@ +package cn.palmte.work.controller.backend; + + +import cn.palmte.work.bean.ResponseMsg; +import cn.palmte.work.model.ActScript; +import cn.palmte.work.model.ActScriptRepository; +import cn.palmte.work.service.ActScriptService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 流程脚本管理 + */ +@Controller +@RequestMapping("/actScript") +public class ActScriptController extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(ActScriptController.class); + + @Autowired + private ActScriptService actScriptService; + + @Autowired + private ActScriptRepository actScriptRepository; + + @RequestMapping("/list") + public String list(@RequestParam(value = "keywords", required = false) String keywords, + @RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber, + @RequestParam(value = PAGE_SIZE, defaultValue = DEFAULT_PAGE_SIZE) int pageSize, + Map model) { + ConcurrentHashMap searchInfo = getSearchInfo(keywords, model); + model.put("pager", actScriptService.list(searchInfo, pageNumber, pageSize)); + return "/admin/act_script_list"; + } + + @GetMapping(value = "/add") + public String add(Map model) { + List list = getScriptList(); + model.put("actScript", new ActScript()); + model.put("classList", list); + + List methodList = new ArrayList<>(); + for (String l : list) { + methodList.addAll(getMethodList(l)); + } + + model.put("methodList", methodList); + return "/admin/act_script_input"; + } + + private List getScriptList() { + List list = new ArrayList<>(1); + list.add("cn.palmte.work.service.ActCallbackScript"); + return list; + } + + private List getMethodList(String className) { + List list = new ArrayList<>(); + + try { + Method[] methods = Class.forName(className).getDeclaredMethods(); + for (Method method : methods) { + list.add(method.getName()); + } + } catch (ClassNotFoundException e) { + logger.error("", e); + } + + return list; + } + + @GetMapping(value = "/edit") + public String edit(@RequestParam int id, Map model) { + List list = getScriptList(); + model.put("actScript", actScriptRepository.findOne(id)); + model.put("classList", list); + List methodList = new ArrayList<>(); + for (String l : list) { + methodList.addAll(getMethodList(l)); + } + + model.put("methodList", methodList); + return "/admin/act_script_input"; + } + + @RequestMapping("/save") + public String save(ActScript actScript) { + actScriptService.save(actScript); + return "redirect:/actScript/list"; + } + + + @ResponseBody + @GetMapping(value = "/delete") + public ResponseMsg delete(@RequestParam("ids") String ids){ + if ("".equals(ids)){ + return ResponseMsg.buildFailedMsg("删除失败,无选中项!"); + }else { + String[] deleteIds=ids.split("#%#"); + for (String id : deleteIds) { + actScriptService.delete(Integer.parseInt(id)); + } + return ResponseMsg.buildSuccessMsg("删除成功"); + } + } + + +} diff --git a/src/main/java/cn/palmte/work/controller/backend/ActTaskDefController.java b/src/main/java/cn/palmte/work/controller/backend/ActTaskDefController.java new file mode 100644 index 0000000..f63e3cc --- /dev/null +++ b/src/main/java/cn/palmte/work/controller/backend/ActTaskDefController.java @@ -0,0 +1,91 @@ +package cn.palmte.work.controller.backend; + + +import cn.palmte.work.bean.ResponseMsg; +import cn.palmte.work.model.ActScriptRepository; +import cn.palmte.work.model.ActTaskDef; +import cn.palmte.work.model.AdminRepository; +import cn.palmte.work.service.ActTaskDefService; +import cn.palmte.work.service.SysRoleService; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + + +import java.util.List; +import java.util.Map; + +/** + * 流程任务 + */ +@Controller +@RequestMapping("/actTaskDef") +public class ActTaskDefController extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(ActTaskDefController.class); + + @Autowired + private AdminRepository adminRepository; + + @Autowired + private SysRoleService sysRoleService; + + @Autowired + private ActScriptRepository actScriptRepository; + + @Autowired + private ActTaskDefService actTaskDefService; + + /** + * 去任务配置页面 + * + * @param procDefId + * @param model + * @return + */ + @RequestMapping("/config/{procDefId}") + public String list(@PathVariable String procDefId, Map model) { + List list = actTaskDefService.findByProcDefId(procDefId); + model.put("procDefId", procDefId); + model.put("taskList", list); + model.put("procDefName", list.get(0).getProcDefName()); + model.put("roleList", sysRoleService.getAllEnableSysRole()); + model.put("adminList", adminRepository.getAllEnable()); + model.put("scriptList", actScriptRepository.findAll()); + + return "/admin/act_task_def"; + } + + + /** + * 任务配置保存 + * + * @param taskDef + * @return + */ + @ResponseBody + @GetMapping(value = "/saveConfig") + public ResponseMsg saveConfig(ActTaskDef taskDef) { + actTaskDefService.saveConfig(taskDef); + return ResponseMsg.buildSuccessMsg("成功"); + } + + + /** + * 完成某个任务 + * 审批通过或者驳回 + * + * @return + */ + @ResponseBody + @PostMapping(value = "/completeTask") + public ResponseMsg completeTask(@RequestBody String json) { + JSONObject jsonParam = JSON.parseObject(json); + actTaskDefService.completeTask(jsonParam); + return ResponseMsg.buildSuccessMsg("处理成功"); + } +} diff --git a/src/main/java/cn/palmte/work/model/ActScript.java b/src/main/java/cn/palmte/work/model/ActScript.java new file mode 100644 index 0000000..d09728a --- /dev/null +++ b/src/main/java/cn/palmte/work/model/ActScript.java @@ -0,0 +1,41 @@ +package cn.palmte.work.model; + +import lombok.Data; + +import javax.persistence.*; +import java.util.Date; + +/** + * 流程脚本 + */ +@Data +@Entity +@Table(name = "act_script") +public class ActScript { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column(name = "script_name") + private String scriptName; + + /** + * 脚本所在类 + */ + @Column(name = "class_name") + private String className; + + /** + * 脚本方法名 + */ + @Column(name = "class_method") + private String classMethod; + + @Column(name = "created_time") + private Date createdTime; + + @Column(name = "last_updated_time") + private Date lastUpdatedTime; + +} diff --git a/src/main/java/cn/palmte/work/model/ActScriptRepository.java b/src/main/java/cn/palmte/work/model/ActScriptRepository.java new file mode 100644 index 0000000..b90895e --- /dev/null +++ b/src/main/java/cn/palmte/work/model/ActScriptRepository.java @@ -0,0 +1,8 @@ +package cn.palmte.work.model; + +import org.springframework.data.jpa.repository.JpaRepository; + + +public interface ActScriptRepository extends JpaRepository { + +} diff --git a/src/main/java/cn/palmte/work/model/ActTaskDef.java b/src/main/java/cn/palmte/work/model/ActTaskDef.java new file mode 100644 index 0000000..ea390a8 --- /dev/null +++ b/src/main/java/cn/palmte/work/model/ActTaskDef.java @@ -0,0 +1,97 @@ +package cn.palmte.work.model; + +import lombok.Data; + +import javax.persistence.*; +import java.util.Date; +import java.util.List; + +/** + * 流程图里解析出来的任务定义 + */ +@Data +@Entity +@Table(name = "act_task_def") +public class ActTaskDef { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + /** + * 任务名称 + */ + @Column(name = "task_name") + private String taskName; + + @Column(name = "task_key") + private String taskKey; + + /** + * 任务类型 0-单实例(或签) 1-多实例(会签) + */ + @Column(name = "task_type") + private int taskType; + + @Column(name = "proc_def_id") + private String procDefId; + + @Column(name = "proc_def_name") + private String procDefName; + + @Column(name = "proc_def_key") + private String procDefKey; + + /** + * 回退任务key + */ + @Column(name = "rollback_task_key") + private String rollbackTaskKey; + + /** + * 节点位置 -1结束节点 0-开始节点 1-第一个用户任务 + */ + @Column(name = "task_index") + private int taskIndex; + + + /** + * 候选人 + */ + @Column(name = "candidate_users") + private String candidateUsers; + + /** + * 候选角色 + */ + @Column(name = "candidate_roles") + private String candidateRoles; + + + /** + * 审批通过执行的脚本 act_script表id + */ + @Column(name = "end_script") + private int endScript; + + /** + * 审批驳回执行的脚本 act_script表id + */ + @Column(name = "rollback_script") + private int rollbackScript; + + @Column(name = "created_time") + private Date createdTime; + + @Column(name = "last_updated_time") + private Date lastUpdatedTime; + + + + @Transient + private List candidateUserList; + + @Transient + private List candidateRoleList; + +} diff --git a/src/main/java/cn/palmte/work/model/ActTaskDefRepository.java b/src/main/java/cn/palmte/work/model/ActTaskDefRepository.java new file mode 100644 index 0000000..cfc4311 --- /dev/null +++ b/src/main/java/cn/palmte/work/model/ActTaskDefRepository.java @@ -0,0 +1,16 @@ +package cn.palmte.work.model; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ActTaskDefRepository extends JpaRepository { + + + List findByProcDefId(String procDefId); + + + ActTaskDef findFirstByProcDefIdAndTaskKey(String procDefId, String taskKey); + + void deleteByProcDefId(String procDefId); +} diff --git a/src/main/java/cn/palmte/work/model/AdminRepository.java b/src/main/java/cn/palmte/work/model/AdminRepository.java index 13b234c..d4891cb 100644 --- a/src/main/java/cn/palmte/work/model/AdminRepository.java +++ b/src/main/java/cn/palmte/work/model/AdminRepository.java @@ -34,4 +34,13 @@ public interface AdminRepository extends JpaRepository { @Query("from Admin where isDeleted=0 AND telephone=?1") Admin findByTelephone(String phone); + + + /** + * 查询所有未删除启用的账号 + * @return + */ + @Query("from Admin where isDeleted=0 AND enabled=1") + List getAllEnable(); + } diff --git a/src/main/java/cn/palmte/work/pojo/ActModel.java b/src/main/java/cn/palmte/work/pojo/ActModel.java new file mode 100644 index 0000000..3fdfe5e --- /dev/null +++ b/src/main/java/cn/palmte/work/pojo/ActModel.java @@ -0,0 +1,21 @@ +package cn.palmte.work.pojo; + +import lombok.Data; + +import java.util.Date; + +@Data +public class ActModel { + private int id; + + private String modelName; + + private int rev; + + private String procDefKey; + + private Date createdTime; + + private Date lastUpdatedTime; + +} diff --git a/src/main/java/cn/palmte/work/pojo/ActProcDef.java b/src/main/java/cn/palmte/work/pojo/ActProcDef.java new file mode 100644 index 0000000..026c656 --- /dev/null +++ b/src/main/java/cn/palmte/work/pojo/ActProcDef.java @@ -0,0 +1,19 @@ +package cn.palmte.work.pojo; + +import lombok.Data; + +import java.util.Date; + +@Data +public class ActProcDef { + private String id; + private String procName; + private String procKey; + private String version; + private String deploymentId; + private String resourceName; + private String dgrmResourceName; + private Date deployTime; + private int suspensionState; + +} diff --git a/src/main/java/cn/palmte/work/pojo/ActProcIns.java b/src/main/java/cn/palmte/work/pojo/ActProcIns.java new file mode 100644 index 0000000..a6e967f --- /dev/null +++ b/src/main/java/cn/palmte/work/pojo/ActProcIns.java @@ -0,0 +1,23 @@ +package cn.palmte.work.pojo; + +import lombok.Data; + +import java.util.Date; + +@Data +public class ActProcIns { + private String procInsId; + private String procName; + private String procKey; + private String version; + + private String user; + private Date startTime; + + private String currentTask; + private String currentTaskId; + private String candidateUsers; + + private Date endTime; + +} diff --git a/src/main/java/cn/palmte/work/service/AccountService.java b/src/main/java/cn/palmte/work/service/AccountService.java index 5dfa6dd..e7577f9 100644 --- a/src/main/java/cn/palmte/work/service/AccountService.java +++ b/src/main/java/cn/palmte/work/service/AccountService.java @@ -17,15 +17,15 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import top.jfunc.common.db.QueryHelper; import top.jfunc.common.db.bean.Page; +import top.jfunc.common.db.bean.Record; import top.jfunc.common.db.utils.Pagination; import javax.servlet.http.HttpServletResponse; import java.beans.Transient; import java.io.IOException; -import java.util.Collection; -import java.util.Date; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * Created by wang.lin@esstx.cn on 2018/4/20. @@ -260,4 +260,38 @@ public class AccountService { return null; } + + + /** + * 通过id查询姓名 + * @param id + * @return + */ + public String getNameById(int id) { + Admin one = adminRepository.findOne(id); + return one == null ? "" : one.getRealName(); + } + + /** + * 通过角色id查询用户姓名列表 + * @param roleIds + * @return + */ + public List getUserIsByRole(List roleIds) { + if (roleIds == null || roleIds.isEmpty()) { + return new ArrayList<>(); + } + String sql = "select u.id as id from sys_user_role ur left join sys_user u on u.id=ur.user_id where ur.role_id in (?)"; + String ids = roleIds.stream().collect(Collectors.joining()); + List records = pagination.find(sql, ids); + if (records == null || records.isEmpty()) { + return new ArrayList<>(); + } + + List userIds = new ArrayList<>(roleIds.size()); + for (Record record : records) { + userIds.add(record.getInt("id") + ""); + } + return userIds; + } } diff --git a/src/main/java/cn/palmte/work/service/ActCallbackScript.java b/src/main/java/cn/palmte/work/service/ActCallbackScript.java new file mode 100644 index 0000000..9d23550 --- /dev/null +++ b/src/main/java/cn/palmte/work/service/ActCallbackScript.java @@ -0,0 +1,35 @@ +package cn.palmte.work.service; + + +import cn.palmte.work.config.activiti.ActConstant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.*; + + +/** + * 流程回调脚本 参数必须为Map + */ +@Service +public class ActCallbackScript { + private static final Logger logger = LoggerFactory.getLogger(ActCallbackScript.class); + + + public void endScriptDemo(Map map) { + logger.info("--- endScriptDemo--- : {} ", map); + String startUserId = (String)map.get(ActConstant.START_PROCESS_USERID); + String procInsId = (String)map.get(ActConstant.START_PROCESS_USERID); + logger.info(" startUserId:{}, procInsId:{}", startUserId, procInsId); + } + + + public void rollbackScriptDemo(Map map) { + logger.info("--- rollbackScriptDemo--- : {} ", map); + String startUserId = (String)map.get(ActConstant.START_PROCESS_USERID); + String procInsId = (String)map.get(ActConstant.START_PROCESS_USERID); + logger.info(" startUserId:{}, procInsId:{}", startUserId, procInsId); + } + +} diff --git a/src/main/java/cn/palmte/work/service/ActListenerService.java b/src/main/java/cn/palmte/work/service/ActListenerService.java new file mode 100644 index 0000000..3b063c5 --- /dev/null +++ b/src/main/java/cn/palmte/work/service/ActListenerService.java @@ -0,0 +1,39 @@ +package cn.palmte.work.service; + + +import com.alibaba.fastjson.JSONObject; +import org.activiti.engine.delegate.DelegateTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + +import java.util.Set; + + +/** + * 流程节点创建监听 + */ +@Service +public class ActListenerService { + private static final Logger logger = LoggerFactory.getLogger(ActListenerService.class); + + + @Autowired + private ActTaskDefService actTaskDefService; + + public void create(DelegateTask delegateTask) throws Exception { + logger.info("--- {}", JSONObject.toJSONString(delegateTask)); + + // 每一个任务节点监听运行时都要初始化流程定义规则数据到 流程引擎中 + String procDefId = delegateTask.getProcessDefinitionId(); + String procInsId = delegateTask.getProcessInstanceId(); + String taskDefKey = delegateTask.getTaskDefinitionKey(); + Set candidateUsers = actTaskDefService.findCandidateUsers(procDefId, procInsId, taskDefKey); + logger.info("addCandidateUsers : {}", candidateUsers); + delegateTask.addCandidateUsers(candidateUsers); + } + + +} diff --git a/src/main/java/cn/palmte/work/service/ActModelService.java b/src/main/java/cn/palmte/work/service/ActModelService.java new file mode 100644 index 0000000..b451bcd --- /dev/null +++ b/src/main/java/cn/palmte/work/service/ActModelService.java @@ -0,0 +1,176 @@ +package cn.palmte.work.service; + +import cn.palmte.work.config.activiti.ActConstant; +import cn.palmte.work.model.ActTaskDef; +import cn.palmte.work.model.ActTaskDefRepository; +import cn.palmte.work.pojo.ActModel; +import cn.palmte.work.utils.InterfaceUtil; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.activiti.bpmn.converter.BpmnXMLConverter; +import org.activiti.bpmn.model.*; +import org.activiti.bpmn.model.Process; +import org.activiti.editor.language.json.converter.BpmnJsonConverter; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.delegate.TaskListener; +import org.activiti.engine.repository.Deployment; +import org.activiti.engine.repository.DeploymentBuilder; +import org.activiti.engine.repository.Model; +import org.activiti.engine.repository.ProcessDefinition; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import top.jfunc.common.db.QueryHelper; +import top.jfunc.common.db.bean.Page; +import top.jfunc.common.db.utils.Pagination; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + + +@Service +public class ActModelService { + private static final Logger logger = LoggerFactory.getLogger(ActModelService.class); + @Autowired + private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service + + @Autowired + private ActTaskDefRepository actTaskDefRepository; + + @Autowired + Pagination pagination; + + + public Page list(ConcurrentHashMap searchInfo, int pageNumber, int pageSize) { + String select = "a.ID_ as id,a.REV_ as rev,a.NAME_ as modelName,a.KEY_ as procDefKey,a.CREATE_TIME_ as createdTime,a.LAST_UPDATE_TIME_ as lastUpdatedTime"; + QueryHelper queryHelper = new QueryHelper(select, " act_re_model a"); + String name = searchInfo.get("name"); + queryHelper.addCondition(StringUtils.isNotEmpty(name), "a.NAME_=? or a.KEY_=?", name, name); + queryHelper.addOrderProperty("a.LAST_UPDATE_TIME_", false); + return pagination.paginate(queryHelper.getSql(), ActModel.class, pageNumber, pageSize); + } + + public void createModel(String processId, String modelName) throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + ObjectNode editorNode = objectMapper.createObjectNode(); + editorNode.put("id", "canvs"); + editorNode.put("resourceId", "canvs"); + ObjectNode stencilSetNode = objectMapper.createObjectNode(); + stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#"); //命名空间(禁止修改) + stencilSetNode.put("author", ""); //流程节点作者 + editorNode.set("stencilset", stencilSetNode); + ObjectNode propertiesNode = objectMapper.createObjectNode(); + propertiesNode.put("process_id", processId); //流程唯一标识 + propertiesNode.put("process_author", InterfaceUtil.getAdmin().getUserName()); //流程作者 + propertiesNode.put("name", modelName); //流程名称 + editorNode.set("properties", propertiesNode); + + ObjectNode modelObjectNode = objectMapper.createObjectNode(); + modelObjectNode.put("name", modelName); //模型名称 + modelObjectNode.put("revision", 1); //模型版本 + modelObjectNode.put("description", ""); //模型描述 + Model modelData = repositoryService.newModel(); + //modelData.setCategory(category); //模型分类 + modelData.setDeploymentId(null); + modelData.setKey(processId); + modelData.setMetaInfo(modelObjectNode.toString()); + modelData.setName(modelName); //模型名称 + modelData.setTenantId(""); + modelData.setVersion(1); + + //保存模型,存储数据到表:act_re_model 流程设计模型部署表 + repositoryService.saveModel(modelData); + + repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));//保存资源,存储数据到表:act_ge_bytearray 二进制数据表 + + } + + + /** + * 删除模型 + * act_re_model 和 act_ge_bytearray 两张表中相关数据都删除 + * + * @param modelId + */ + public void deleteModel(String modelId) { + repositoryService.deleteModel(modelId); + } + + /** + * 部署流程 + * + * @param modelId + * @throws Exception + */ + public void deploy(String modelId) throws Exception { + Model modelData = repositoryService.getModel(modelId); + ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId())); + byte[] bpmnBytes = null; + BpmnJsonConverter jsonConverter = new BpmnJsonConverter(); + BpmnModel model = jsonConverter.convertToBpmnModel(modelNode); + + ActivitiListener activitiListener = new ActivitiListener(); + activitiListener.setEvent(TaskListener.EVENTNAME_CREATE); + activitiListener.setImplementation("${actListenerService.create(task)}"); + activitiListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION); + List activitiListenerList = new ArrayList<>(1); + activitiListenerList.add(activitiListener); + + List taskList = new ArrayList<>(); + Process process = model.getMainProcess(); + Collection flowElements = process.getFlowElements(); + + int i = 0; + ActTaskDef task; + ActTaskDef first = null; + for (FlowElement element : flowElements) { + if (element instanceof UserTask) { + UserTask userTask = (UserTask) element; + userTask.setTaskListeners(activitiListenerList); + + task = new ActTaskDef(); + task.setTaskName(element.getName()); + task.setTaskKey(element.getId()); + MultiInstanceLoopCharacteristics loopCharacteristics = ((UserTask) element).getLoopCharacteristics(); + if (loopCharacteristics != null) { + task.setTaskType(1); + } + + if (i == 1) { + task.setTaskIndex(ActConstant.TASK_INDEX_FIRST_USER_TASK); + first = task; + } + taskList.add(task); + } + i ++; + } + + bpmnBytes = new BpmnXMLConverter().convertToXML(model); + String processName = modelData.getName() + ".bpmn20.xml"; + DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().name(modelData.getName()); //部署名称 + deploymentBuilder.addString(processName, new String(bpmnBytes, "utf-8")); + Deployment deployment = deploymentBuilder.deploy(); //完成部署 + + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult(); + for (ActTaskDef actTaskDef : taskList) { + if (first != null) { + actTaskDef.setRollbackTaskKey(first.getTaskKey()); + } + actTaskDef.setProcDefId(processDefinition.getId()); + actTaskDef.setProcDefName(processDefinition.getName()); + actTaskDef.setProcDefKey(processDefinition.getKey()); + actTaskDef.setCreatedTime(new Date()); + actTaskDef.setLastUpdatedTime(new Date()); + } + + actTaskDefRepository.save(taskList); + + logger.info("deploy success: deploymentId:{}, procDefName:{}, procDefKey:{}", deployment.getId(), processDefinition.getName(), processDefinition.getKey()); + } + +} diff --git a/src/main/java/cn/palmte/work/service/ActProcDefService.java b/src/main/java/cn/palmte/work/service/ActProcDefService.java new file mode 100644 index 0000000..3150618 --- /dev/null +++ b/src/main/java/cn/palmte/work/service/ActProcDefService.java @@ -0,0 +1,145 @@ +package cn.palmte.work.service; + +import cn.palmte.work.model.ActTaskDefRepository; +import cn.palmte.work.pojo.ActProcDef; +import org.activiti.bpmn.model.*; +import org.activiti.engine.ProcessEngine; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.image.ProcessDiagramGenerator; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import top.jfunc.common.db.QueryHelper; +import top.jfunc.common.db.bean.Page; +import top.jfunc.common.db.utils.Pagination; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + + +@Service +public class ActProcDefService { + private static final Logger logger = LoggerFactory.getLogger(ActProcDefService.class); + + @Autowired + private ProcessEngine processEngine; //流程引擎对象 + @Autowired + private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service + + @Autowired + private ActTaskDefRepository actTaskDefRepository; + + + @Autowired + Pagination pagination; + + + public Page list(ConcurrentHashMap searchInfo, int pageNumber, int pageSize) { + String select = "select p.ID_ as id,p.NAME_ as procName,p.KEY_ as procKey,p.VERSION_ as version,p.DEPLOYMENT_ID_ as deploymentId,p.RESOURCE_NAME_ as resourceName,\n" + + " p.DGRM_RESOURCE_NAME_ as dgrmResourceName,p.SUSPENSION_STATE_ as suspensionState, d.DEPLOY_TIME_ as deployTime "; + QueryHelper queryHelper = new QueryHelper(select, " act_re_procdef p LEFT JOIN act_re_deployment d on p.DEPLOYMENT_ID_ = d.ID_"); + String name = searchInfo.get("name"); + queryHelper.addCondition(StringUtils.isNotEmpty(name), "p.NAME_=? or p.KEY_=?", name, name); + queryHelper.addOrderProperty("p.KEY_,p.VERSION_", false); + return pagination.paginate(queryHelper.getSql(), ActProcDef.class, pageNumber, pageSize); + } + + public void getXmlByDeploymentId(HttpServletResponse response, String deploymentId) throws IOException { + InputStream pic=null; + try { + pic= getXmlStreamByDeploymentId(deploymentId); + byte[] b = new byte[1024]; + int len = -1; + while ((len = pic.read(b, 0, 1024)) != -1) { + response.getOutputStream().write(b, 0, len); + } + }catch (Exception e){ + logger.error("an exception happens in try catch statement", e); + }finally { + if(pic!=null) { + pic.close(); + } + } + } + + public InputStream getXmlStreamByDeploymentId(String deploymentId) throws IOException{ + List names = repositoryService.getDeploymentResourceNames(deploymentId); + for (String name : names) { + if(name.contains("xml") ) { + return repositoryService.getResourceAsStream(deploymentId, name); + } + } + return null; + } + + + + /** + * 创建默认的png + * + * @param response + * @param deploymentId + * @throws IOException + */ + public void createProcDefPng(HttpServletResponse response, String deploymentId) throws IOException { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); // 获取bpmnModel + InputStream inputStream = generateDiagramInputStream(bpmnModel, new ArrayList<>(), new ArrayList<>()); + responsePng(response, inputStream); + } + + public void responsePng(HttpServletResponse response, InputStream inputStream) throws IOException { + InputStream pic = null; + try { + pic = inputStream; + byte[] b = new byte[1024]; + int len = -1; + while ((len = pic.read(b, 0, 1024)) != -1) { + response.getOutputStream().write(b, 0, len); + } + } catch (Exception e) { + logger.error("an exception happens in try catch statement", e); + } finally { + if (pic != null) { + pic.close(); + } + } + } + + + public InputStream generateDiagramInputStream(BpmnModel bpmnModel, List executedActivityIdList, List flowIds) { + try { + ProcessDiagramGenerator processDiagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator(); + return processDiagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList, + flowIds, "宋体", "微软雅黑", "黑体", null, 2.0); //使用默认配置获得流程图表生成器,并生成追踪图片字符流 + } catch (Exception e) { + logger.error("an exception happens in try catch statement", e); + return null; + } + } + + @Transactional(rollbackFor = Exception.class) + public void deleteDeployment(String deploymentId) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); + actTaskDefRepository.deleteByProcDefId(processDefinition.getId()); + + //repositoryService.deleteDeployment(deploymentId); //不带级联的删除,此删除只能删除没有启动的流程,否则抛出异常 .act_re_deployment,act_re_procdef 和 act_ge_bytearray 三张表中相关数据都删除 + repositoryService.deleteDeployment(deploymentId, true); //级联删除,不管流程是否启动,都可以删除 + } + + public void suspend(String procDefId, int status) { + if (1 == status) { + repositoryService.activateProcessDefinitionById(procDefId, true, null); + }else{ + repositoryService.suspendProcessDefinitionById(procDefId, true, null); + } + } +} diff --git a/src/main/java/cn/palmte/work/service/ActProcInsService.java b/src/main/java/cn/palmte/work/service/ActProcInsService.java new file mode 100644 index 0000000..4dc0222 --- /dev/null +++ b/src/main/java/cn/palmte/work/service/ActProcInsService.java @@ -0,0 +1,299 @@ +package cn.palmte.work.service; + +import cn.palmte.work.config.activiti.ActConstant; +import cn.palmte.work.exception.ResponseException; +import cn.palmte.work.pojo.ActProcIns; +import cn.palmte.work.utils.InterfaceUtil; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.FlowNode; +import org.activiti.bpmn.model.SequenceFlow; +import org.activiti.engine.HistoryService; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.RuntimeService; +import org.activiti.engine.TaskService; +import org.activiti.engine.history.HistoricActivityInstance; +import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.task.IdentityLink; +import org.activiti.engine.task.Task; +import org.activiti.image.ProcessDiagramGenerator; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import top.jfunc.common.db.QueryHelper; +import top.jfunc.common.db.bean.Page; +import top.jfunc.common.db.bean.Record; +import top.jfunc.common.db.utils.Pagination; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + + +@Service +public class ActProcInsService { + private static final Logger logger = LoggerFactory.getLogger(ActProcInsService.class); + @Autowired + private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service + @Autowired + private TaskService taskService; //任务管理 与正在执行的任务管理相关的Service + + @Autowired + private AccountService accountService; + + @Autowired + private RuntimeService runtimeService; //与正在执行的流程实例和执行对象相关的Service(执行管理,包括启动、推进、删除流程实例等操作) + + @Autowired + Pagination pagination; + + @Autowired + private ActProcDefService actProcDefService; + + @Autowired + private HistoryService historyService; //历史管理(执行完的数据的管理) + + + public Page list(ConcurrentHashMap searchInfo, int pageNumber, int pageSize) { + String select = "select h.proc_inst_id_ as procInsId,h.proc_def_id_ as procDefId," + + "h.start_time_ as startTime,h.end_time_ as endTime,p.key_ as procKey," + + "p.name_ as procName,p.NAME_ as dgrmResourceName,p.version_ as version, GROUP_CONCAT(t.NAME_) as currentTask, GROUP_CONCAT(t.ID_) as currentTaskId"; + QueryHelper queryHelper = new QueryHelper(select, " act_hi_procinst h " + + "left join ACT_RE_PROCDEF p on h.PROC_DEF_ID_ =p.ID_ " + + "LEFT JOIN act_ru_task t on t.PROC_INST_ID_=h.proc_inst_id_ "); + queryHelper.addGroupProperty("h.PROC_INST_ID_"); + queryHelper.addOrderProperty("h.start_time_", false); + Page paginate = pagination.paginate(queryHelper.getSql(), ActProcIns.class, pageNumber, pageSize); + List list = paginate.getList(); + + for (ActProcIns ins : list) { + //查询流程发起人 + Record record = getVariable(ActConstant.START_PROCESS_USERID, ins.getProcInsId()); + if (record != null) { + String userId = getStartUserId(ins.getProcInsId()); + ins.setUser(accountService.getNameById(Integer.parseInt(userId))); + } + + + //查询当前任务审批人 + String currentTaskId = ins.getCurrentTaskId(); + if (StringUtils.isNotBlank(currentTaskId)) { + String[] split = currentTaskId.split(","); + String candidateUsers = ""; + for (String taskId : split) { + List identityLinksForTask = taskService.getIdentityLinksForTask(taskId); + for (IdentityLink identityLink : identityLinksForTask) { + if ("assignee".equals(identityLink.getType()) || "candidate".equals(identityLink.getType())) { + String userId = identityLink.getUserId(); + if (StringUtils.isNotBlank(candidateUsers)) { + candidateUsers = candidateUsers + ","; + } + candidateUsers += accountService.getNameById(Integer.parseInt(userId)); + } + } + } + ins.setCandidateUsers(candidateUsers); + } + } + + + return paginate; + } + + + /** + * 获取流程实例里的变量 + * + * @param variableName + * @param procInsId + * @return + */ + public Record getVariable(String variableName, String procInsId) { + String sql = "select TEXT_ as text from ACT_HI_VARINST where NAME_=? and PROC_INST_ID_=?"; + return pagination.findFirst(sql, variableName, procInsId); + } + + + public String getStartUserId(String procInsId) { + Record record = getVariable(ActConstant.START_PROCESS_USERID, procInsId); + if (record != null) { + return record.getStr("text"); + } + return "0"; + } + + + public List getVariables(String procInsId) { + String sql = "select NAME_ as name, TEXT_ as text from ACT_HI_VARINST where PROC_INST_ID_=?"; + return pagination.find(sql, procInsId); + } + + + public void deleteProcessInstance(String procInsId, String reason) { + runtimeService.deleteProcessInstance(procInsId, reason); //作废流程 + } + + + public void createProcInsPng(HttpServletResponse response, String procInsId) throws IOException { + try { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).singleResult(); //获取历史流程实例 + //获取流程中已经执行的节点,按照执行先后顺序排序 + List hai = historyService.createHistoricActivityInstanceQuery().processInstanceId(procInsId).orderByHistoricActivityInstanceStartTime().asc().list(); + // 历史流程节点中 + List newHisActInstanceList = new ArrayList(); + List newHisTaskInstanceList = new ArrayList(); + if (hai != null && hai.size() > 0) { + for (int i = 0; i < hai.size(); i++) { + HistoricActivityInstance historicActivityInstance = hai.get(i); + String activityType = historicActivityInstance.getActivityType(); + if (activityType.equals("startEvent") || activityType.equals("endEvent")) { + newHisActInstanceList.add(historicActivityInstance); + } else if (activityType.equals("serviceTask") || activityType.equals("userTask") || activityType.equals("exclusiveGateway") || activityType.equals("parallelGateway")) { + if (newHisTaskInstanceList.size() > 0) { + for (int j = 0; j < newHisTaskInstanceList.size(); j++) { + HistoricActivityInstance historicTaskInstance = newHisTaskInstanceList.get(j); + if (historicTaskInstance.getActivityId().equals(historicActivityInstance.getActivityId())) { //如果列表中已包括 + newHisTaskInstanceList.clear(); + newHisTaskInstanceList.add(historicActivityInstance); + break; + } else { + newHisTaskInstanceList.add(historicActivityInstance); + break; + } + } + } else { + newHisTaskInstanceList.add(historicActivityInstance); + } + } + } + } + for (int i = 0; i < newHisActInstanceList.size(); i++) { + HistoricActivityInstance historicActivityInstance = newHisActInstanceList.get(i); + newHisTaskInstanceList.add(historicActivityInstance); + } + + List executedActivityIdList = new ArrayList(); // 构造已执行的节点ID集合 + for (HistoricActivityInstance activityInstance : newHisTaskInstanceList) { + executedActivityIdList.add(activityInstance.getActivityId()); + } + BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId()); // 获取bpmnModel + List flowIds = this.getExecutedFlows(bpmnModel, newHisTaskInstanceList); // 获取流程已发生流转的线ID集合 + InputStream inputStream = actProcDefService.generateDiagramInputStream(bpmnModel, executedActivityIdList, flowIds); + actProcDefService.responsePng(response, inputStream); + + } catch (Exception e) { + logger.error("an exception happens in try catch statement", e); + } + + } + + public List getExecutedFlows(BpmnModel bpmnModel, List historicActivityInstances) { + List flowIdList = new ArrayList(); //流转线ID集合 + List historicFlowNodeList = new LinkedList(); //全部活动实例 + List finishedActivityInstanceList = new LinkedList(); //已完成的历史活动节点 + List list = new ArrayList(); + + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + historicFlowNodeList.add((FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true)); + if (historicActivityInstance.getEndTime() != null) { + finishedActivityInstanceList.add(historicActivityInstance); + } + + } + for (int x = 0; x < historicActivityInstances.size(); x++) { + HistoricActivityInstance historicActivityInstance = historicActivityInstances.get(x); + String activityType = historicActivityInstance.getActivityType(); + String activityId = historicActivityInstance.getActivityId(); + if (!list.contains(activityId) && ("userTask".equals(activityType) + || "serviceTask".equals(activityType) + || "endEvent".equals(activityType) + || "exclusiveGateway".equals(activityType) + || "parallelGateway".equals(activityType))) { + list.add(activityId); + } + } + /**遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的*/ + FlowNode currentFlowNode = null; + for (HistoricActivityInstance currentActivityInstance : finishedActivityInstanceList) { + /**获得当前活动对应的节点信息及outgoingFlows信息*/ + currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true); + List sequenceFlowList = currentFlowNode.getOutgoingFlows(); + /** + * 遍历outgoingFlows并找到已流转的 + * 满足如下条件任务已流转: + * 1.当前节点是并行网关或包含网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转 + * 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最近的流转节点视为有效流转 + */ + FlowNode targetFlowNode = null; + if ("parallelGateway".equals(currentActivityInstance.getActivityType()) + || "inclusiveGateway".equals(currentActivityInstance.getActivityType())) { + for (SequenceFlow sequenceFlow : sequenceFlowList) { //遍历历史活动节点,找到匹配Flow目标节点的 + targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true); + if (historicFlowNodeList.contains(targetFlowNode)) { + flowIdList.add(sequenceFlow.getId()); + } + } + } else { + List> tempMapList = new LinkedList>(); +// for(SequenceFlow sequenceFlow : sequenceFlowList) { //遍历历史活动节点,找到匹配Flow目标节点的 + for (int i = 0; i < sequenceFlowList.size(); i++) { //遍历历史活动节点,找到匹配Flow目标节点的 + SequenceFlow sequenceFlow = sequenceFlowList.get(i); + int taskSeq = list.indexOf(sequenceFlow.getSourceRef()); // 获取当前flow目标节点key在审批顺序 + String nextTaskKey = ""; // 下一个任务节点 + String beforeTaskKey = sequenceFlow.getSourceRef(); //上一个任务节点 + + if ((taskSeq + 1) < list.size()) { // 判断下一个任务节点是否存在 + nextTaskKey = String.valueOf(list.get((taskSeq + 1))); + } + if (taskSeq == list.size() - 1) { + nextTaskKey = String.valueOf(list.get((taskSeq))); + } + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef()) && sequenceFlow.getSourceRef().equals(beforeTaskKey) && sequenceFlow.getTargetRef().equals(nextTaskKey)) { + Map map = new HashMap<>(); + map.put("flowId", sequenceFlow.getId()); + map.put("activityStartTime", String.valueOf(historicActivityInstance.getStartTime().getTime())); + tempMapList.add(map); + } + } + } + String flowId = null; + for (Map map : tempMapList) { + flowId = map.get("flowId"); + flowIdList.add(flowId); + } + + } + } + return flowIdList; + } + + public String startProcessInstance(String procDefKey, Map variables) { + List list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).active().orderByProcessDefinitionVersion().desc().list(); + if (list == null || list.isEmpty()) { + throw new ResponseException("procDefKey:" + procDefKey + " 未定义"); + } + + //取最新版本的流程定义进行启动流程实列 + ProcessDefinition processDefinition = list.get(0); + + //启动流程 + ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), variables); + + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult(); + if (task == null) { + throw new ResponseException("procDefKey:" + procDefKey + " 启动异常"); + } + + //设置发起人为办理人 然后完成任务 任务转入下一个审批节点 + task.setAssignee(InterfaceUtil.getAdminId() + ""); + taskService.complete(task.getId()); + return processInstance.getId(); + } + +} diff --git a/src/main/java/cn/palmte/work/service/ActScriptService.java b/src/main/java/cn/palmte/work/service/ActScriptService.java new file mode 100644 index 0000000..ea8483c --- /dev/null +++ b/src/main/java/cn/palmte/work/service/ActScriptService.java @@ -0,0 +1,55 @@ +package cn.palmte.work.service; + +import cn.palmte.work.model.ActScript; +import cn.palmte.work.model.ActScriptRepository; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import top.jfunc.common.db.QueryHelper; +import top.jfunc.common.db.bean.Page; +import top.jfunc.common.db.utils.Pagination; + +import java.util.Date; +import java.util.concurrent.ConcurrentHashMap; + + +@Service +public class ActScriptService { + private static final Logger logger = LoggerFactory.getLogger(ActScriptService.class); + @Autowired + private ActScriptRepository actScriptRepository; + + @Autowired + Pagination pagination; + + + public Page list(ConcurrentHashMap searchInfo, int pageNumber, int pageSize) { + QueryHelper queryHelper = new QueryHelper("a.*", " act_script a"); + String name = searchInfo.get("name"); + queryHelper.addCondition(StringUtils.isNotEmpty(name), "a.script_name=? ", name); + queryHelper.addOrderProperty("a.last_updated_time", false); + return pagination.paginate(queryHelper.getSql(), ActScript.class, pageNumber, pageSize); + } + + public void save(ActScript actScript) { + Date now = new Date(); + int id = actScript.getId(); + if (id == 0) { + actScript.setCreatedTime(now); + }else { + ActScript one = actScriptRepository.findOne(id); + actScript.setCreatedTime(one.getCreatedTime()); + } + actScript.setLastUpdatedTime(now); + actScriptRepository.save(actScript); + } + + + public void delete(int id) { + actScriptRepository.delete(id); + } + + +} diff --git a/src/main/java/cn/palmte/work/service/ActTaskDefService.java b/src/main/java/cn/palmte/work/service/ActTaskDefService.java new file mode 100644 index 0000000..ab7f9ba --- /dev/null +++ b/src/main/java/cn/palmte/work/service/ActTaskDefService.java @@ -0,0 +1,240 @@ +package cn.palmte.work.service; + +import cn.palmte.work.config.activiti.ActConstant; +import cn.palmte.work.config.activiti.DeleteTaskCommand; +import cn.palmte.work.config.activiti.JumpCommand; +import cn.palmte.work.model.ActScript; +import cn.palmte.work.model.ActScriptRepository; +import cn.palmte.work.model.ActTaskDef; +import cn.palmte.work.model.ActTaskDefRepository; +import cn.palmte.work.utils.InterfaceUtil; +import com.alibaba.fastjson.JSONObject; +import org.activiti.bpmn.model.FlowNode; +import org.activiti.engine.*; +import org.activiti.engine.task.Task; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; +import top.jfunc.common.db.bean.Record; + +import javax.annotation.Resource; +import java.lang.reflect.Method; +import java.util.*; + + +@Service +public class ActTaskDefService { + private static final Logger logger = LoggerFactory.getLogger(ActTaskDefService.class); + @Autowired + private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service + @Autowired + private ProcessEngine processEngine; //流程引擎对象 + @Autowired + private RuntimeService runtimeService; //与正在执行的流程实例和执行对象相关的Service(执行管理,包括启动、推进、删除流程实例等操作) + @Autowired + private TaskService taskService; //任务管理 与正在执行的任务管理相关的Service + + @Autowired + private ActTaskDefRepository actTaskDefRepository; + + @Autowired + private AccountService accountService; + + @Autowired + private ActProcInsService actProcInsService; + + @Resource + private ApplicationContext applicationContext; + + @Autowired + private ActScriptRepository actScriptRepository; + + public List findByProcDefId(String procDefId) { + List list = actTaskDefRepository.findByProcDefId(procDefId); + for (ActTaskDef actTaskDef : list) { + ids2List(actTaskDef); + } + return list; + } + + + public ActTaskDef findFirstByProcDefIdAndTaskKey(String procDefId, String taskKey) { + ActTaskDef def = actTaskDefRepository.findFirstByProcDefIdAndTaskKey(procDefId, taskKey); + ids2List(def); + return def; + } + + + public void saveConfig(ActTaskDef taskDef) { + ActTaskDef one = actTaskDefRepository.findOne(taskDef.getId()); + one.setCandidateUsers(taskDef.getCandidateUsers()); + one.setCandidateRoles(taskDef.getCandidateRoles()); + one.setRollbackTaskKey(taskDef.getRollbackTaskKey()); + one.setEndScript(taskDef.getEndScript()); + one.setRollbackScript(taskDef.getRollbackScript()); + one.setLastUpdatedTime(new Date()); + + actTaskDefRepository.save(one); + logger.info("saveTaskConfig uerId:{}, config:{}", InterfaceUtil.getAdminId(), JSONObject.toJSONString(one)); + } + + + private void ids2List(ActTaskDef actTaskDef) { + String candidateUsers = actTaskDef.getCandidateUsers(); + List userIdList = new ArrayList<>(); + if (StringUtils.isNotBlank(candidateUsers)) { + userIdList = Arrays.asList(candidateUsers.split("#")); + } + actTaskDef.setCandidateUserList(userIdList); + + String candidateRoles = actTaskDef.getCandidateRoles(); + List roleIdList = new ArrayList<>(); + if (StringUtils.isNotBlank(candidateRoles)) { + roleIdList = Arrays.asList(candidateRoles.split("#")); + } + actTaskDef.setCandidateRoleList(roleIdList); + } + + + public Set findCandidateUsers(String procDefId, String procInsId, String taskDefKey) { + ActTaskDef taskDef = findFirstByProcDefIdAndTaskKey(procDefId, taskDefKey); + if (taskDef.getTaskIndex() == ActConstant.TASK_INDEX_FIRST_USER_TASK) { + String startUserId = actProcInsService.getStartUserId(procInsId); + Set res = new HashSet<>(1); + logger.info("findCandidateUsers-0-task:{}, startUserId:{}", taskDef.getTaskName(), startUserId); + res.add(startUserId); + return res; + } + + List resList = new ArrayList<>(); + List candidateUserList = taskDef.getCandidateUserList(); + logger.info("findCandidateUsers-1-task:{}, userList:{}", taskDef.getTaskName(), candidateUserList); + if (!candidateUserList.isEmpty()) { + resList.addAll(candidateUserList); + } + + List candidateRoleList = taskDef.getCandidateRoleList(); + logger.info("findCandidateUsers-2-task:{}, roleList:{}", taskDef.getTaskName(), candidateRoleList); + List list = accountService.getUserIsByRole(candidateRoleList); + logger.info("findCandidateUsers-3-task:{}, userIdListByRole:{}", taskDef.getTaskName(), list); + if (!list.isEmpty()) { + resList.addAll(list); + } + + Set res = new HashSet<>(resList); + logger.info("findCandidateUsers-4-task:{}, resIds:{}", taskDef.getTaskName(), res); + return res; + } + + + + /** + * 处理任务 + * @param json + */ + public void completeTask(JSONObject json) { + String taskId = json.getString("taskId"); + String procInstId = json.getString("procInsId"); + String message = json.getString("message"); + int type = json.getInteger("type"); + + taskService.addComment(taskId, procInstId, message); + + Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult(); + ActTaskDef actTaskDef = findFirstByProcDefIdAndTaskKey(currentTask.getProcessDefinitionId(), currentTask.getTaskDefinitionKey()); + + if (ActConstant.TYPE_APPROVE == type) { + //审批通过 + taskService.complete(taskId); + + //执行配置的审批通过脚本 + int endScript = actTaskDef.getEndScript(); + if (endScript != 0) { + invokeEventScript(endScript, procInstId); + } else { + logger.info("未配置审批通过脚本 task:{}", actTaskDef.getTaskName()); + } + + } else if (ActConstant.TYPE_ROLLBACK == type) { + //驳回 + String rollbackTaskKey = actTaskDef.getRollbackTaskKey(); + jumpToTargetTask(taskId, rollbackTaskKey); + + //执行配置的驳回脚本 + int rollbackScript = actTaskDef.getRollbackScript(); + if (rollbackScript != 0) { + invokeEventScript(rollbackScript, procInstId); + } else { + logger.info("未配置驳回脚本 task:{}", actTaskDef.getTaskName()); + } + } + + } + + /** + * 反射执行脚本 + * + * @param scriptId + * @param procInsId + */ + private void invokeEventScript(int scriptId, String procInsId) { + ActScript actScript = actScriptRepository.findOne(scriptId); + if (actScript == null) { + logger.info("脚本配置错误"); + return; + } + + Map map = new HashMap<>(); + map.put(ActConstant.PROC_INS_ID, procInsId); + List variables = actProcInsService.getVariables(procInsId); + for (Record variable : variables) { + map.put(variable.getStr("name"), variable.get("text")); + } + + //调用方法传递的参数 + Object[] args = new Object[1]; + args[0] = map; + + logger.info("invokeEventScript class:{}, methond:{}, param:{}", actScript.getClassName(), actScript.getClassMethod(), map); + try { + Class ownerClass = Class.forName(actScript.getClassName()); + Object bean = applicationContext.getBean(ownerClass); + Class[] paramsType = new Class[1]; + paramsType[0] = Class.forName("java.util.Map"); + //找到脚本方法对应的方法 注意:有且只有一个以Map为参数的方法 + Method method = ownerClass.getDeclaredMethod(actScript.getClassMethod(), paramsType); + method.invoke(bean, args); + } catch (Exception e) { + logger.error("", e); + } + + } + + /** + * 跳转到指定任务节点 + * + * @param currentTaskId 当前任务id + * @param targetTaskDefKey 跳转目的任务key + */ + public void jumpToTargetTask(String currentTaskId, String targetTaskDefKey) { + Task currentTask = taskService.createTaskQuery().taskId(currentTaskId).singleResult(); + // 获取流程定义 + org.activiti.bpmn.model.Process process = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess(); + //获取目标节点定义 + FlowNode targetNode = (FlowNode) process.getFlowElement(targetTaskDefKey); + + ManagementService managementService = processEngine.getManagementService(); + //删除当前运行任务 + String executionEntityId = managementService.executeCommand(new DeleteTaskCommand(currentTask.getId())); + //流程执行到来源节点 + managementService.executeCommand(new JumpCommand(targetNode, executionEntityId)); + + Task singleResult = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult(); + singleResult.setParentTaskId(currentTask.getTaskDefinitionKey()); + taskService.saveTask(singleResult); + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c36438a..b89f14a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -43,7 +43,7 @@ fourcal.token.pc.expires=60*60*24 fourcal.excluded.client.urls= fourcal.excluded.pc.urls= #\u6392\u9664\u67D0\u4E9B\u65E5\u5FD7\u7684\u6253\u5370 -fourcal.log.excluded.urls= +fourcal.log.excluded.urls=/editor/stencilset fourcal.slideInterval=1800000 diff --git a/src/main/resources/stencilset.json b/src/main/resources/stencilset.json new file mode 100644 index 0000000..c05ad66 --- /dev/null +++ b/src/main/resources/stencilset.json @@ -0,0 +1,1329 @@ +{ + "title" : "流程编辑器", + "namespace" : "http://b3mn.org/stencilset/bpmn2.0#", + "description" : "BPMN流程编辑器", + "propertyPackages" : [ { + "name" : "process_idpackage", + "properties" : [ { + "id" : "process_id", + "type" : "String", + "title" : "流程唯一标识", + "value" : "未定义", + "description" : "流程定义唯一的标识", + "popular" : true + } ] + }, { + "name" : "overrideidpackage", + "properties" : [ { + "id" : "overrideid", + "type" : "String", + "title" : "ID", + "value" : "", + "description" : "元素的唯一标识", + "popular" : true + } ] + }, { + "name" : "namepackage", + "properties" : [ { + "id" : "name", + "type" : "String", + "title" : "名称", + "value" : "", + "description" : "BPMN元素的描述名称.", + "popular" : true, + "refToView" : "text_name" + } ] + }, { + "name" : "documentationpackage", + "properties" : [ { + "id" : "documentation", + "type" : "Text", + "title" : "文档", + "value" : "", + "description" : "BPMN元素的描述名称.", + "popular" : true + } ] + }, { + "name" : "process_authorpackage", + "properties" : [ { + "id" : "process_author", + "type" : "String", + "title" : "流程作者", + "value" : "", + "description" : "流程定义的作者.", + "popular" : true + } ] + }, { + "name" : "process_versionpackage", + "properties" : [ { + "id" : "process_version", + "type" : "String", + "title" : "流程版本字符串(仅限于文档)", + "value" : "", + "description" : "文档的目的为版本标识", + "popular" : true + } ] + }, { + "name" : "process_namespacepackage", + "properties" : [ { + "id" : "process_namespace", + "type" : "String", + "title" : "目标命名空间", + "value" : "http://www.insight.com/", + "description" : "流程定义的目标命名空间.", + "popular" : true + } ] + }, { + "name" : "asynchronousdefinitionpackage", + "properties" : [ { + "id" : "asynchronousdefinition", + "type" : "Boolean", + "title" : "异步", + "value" : "false", + "description" : "定义异步的活动.", + "popular" : true + } ] + }, { + "name" : "exclusivedefinitionpackage", + "properties" : [ { + "id" : "exclusivedefinition", + "type" : "Boolean", + "title" : "排它性", + "value" : "false", + "description" : "定义排它的活动.", + "popular" : true + } ] + }, { + "name" : "executionlistenerspackage", + "properties" : [ { + "id" : "executionlisteners", + "type" : "multiplecomplex", + "title" : "执行监听器", + "value" : "", + "description" : "活动、流程、流程跳转,开始、结事事件的监听器", + "popular" : true + } ] + }, { + "name" : "tasklistenerspackage", + "properties" : [ { + "id" : "tasklisteners", + "type" : "multiplecomplex", + "title" : "任务监听器", + "value" : "", + "description" : "人工任务的监听器", + "popular" : true + } ] + }, { + "name" : "eventlistenerspackage", + "properties" : [ { + "id" : "eventlisteners", + "type" : "multiplecomplex", + "title" : "事件监听器", + "value" : "", + "description" : "监听Activiti引擎的任何发生的事件. 同样可能是任何抛出的信号、信息、出错的事件。", + "popular" : true + } ] + }, { + "name" : "usertaskassignmentpackage", + "properties" : [ { + "id" : "usertaskassignment", + "type" : "Complex", + "title" : "任务派遣", + "value" : "", + "description" : "人工任务的派遣的定义", + "popular" : true + } ] + }, { + "name" : "formpropertiespackage", + "properties" : [ { + "id" : "formproperties", + "type" : "Complex", + "title" : "表单属性", + "value" : "", + "description" : "定义带有属性列表的表单", + "popular" : true + } ] + }, { + "name" : "formkeydefinitionpackage", + "properties" : [ { + "id" : "formkeydefinition", + "type" : "String", + "title" : "表单的标识Key", + "value" : "", + "description" : "表单的Key(指向定义的Form).", + "popular" : true + } ] + }, { + "name" : "duedatedefinitionpackage", + "properties" : [ { + "id" : "duedatedefinition", + "type" : "String", + "title" : "到期的日期", + "value" : "", + "description" : "人工任务的到期日期", + "popular" : true + } ] + }, { + "name" : "prioritydefinitionpackage", + "properties" : [ { + "id" : "prioritydefinition", + "type" : "String", + "title" : "优先级", + "value" : "", + "description" : "人工任务的优先级.", + "popular" : true + } ] + }, { + "name" : "duedatedefinitionpackage", + "properties" : [ { + "id" : "duedatedefinition", + "type" : "String", + "title" : "到期的日期", + "value" : "", + "description" : "人工任务的到期日期.", + "popular" : true + } ] + }, { + "name" : "servicetaskclasspackage", + "properties" : [ { + "id" : "servicetaskclass", + "type" : "String", + "title" : "类名", + "value" : "", + "description" : "实现服务任务逻辑的类.", + "popular" : true + } ] + }, { + "name" : "servicetaskexpressionpackage", + "properties" : [ { + "id" : "servicetaskexpression", + "type" : "String", + "title" : "表达式", + "value" : "", + "description" : "定义服务任务逻辑的表达式.", + "popular" : true + } ] + }, { + "name" : "servicetaskdelegateexpressionpackage", + "properties" : [ { + "id" : "servicetaskdelegateexpression", + "type" : "String", + "title" : "代理的表达式", + "value" : "", + "description" : "通过代理表达式定义任务服务逻辑", + "popular" : true + } ] + }, { + "name" : "servicetaskfieldspackage", + "properties" : [ { + "id" : "servicetaskfields", + "type" : "Complex", + "title" : "类的字段", + "value" : "", + "description" : "字段扩展", + "popular" : true + } ] + }, { + "name" : "servicetaskresultvariablepackage", + "properties" : [ { + "id" : "servicetaskresultvariable", + "type" : "String", + "title" : "变量名结果", + "value" : "", + "description" : "流程变量存储服务任务的执行结果.", + "popular" : true + } ] + }, { + "name" : "scriptformatpackage", + "properties" : [ { + "id" : "scriptformat", + "type" : "String", + "title" : "脚本格式化", + "value" : "", + "description" : "脚本任务的脚本格式化.", + "popular" : true + } ] + }, { + "name" : "scripttextpackage", + "properties" : [ { + "id" : "scripttext", + "type" : "Text", + "title" : "脚本", + "value" : "", + "description" : "脚本任务的脚本内容.", + "popular" : true + } ] + }, { + "name" : "ruletask_rulespackage", + "properties" : [ { + "id" : "ruletask_rules", + "type" : "String", + "title" : "规则", + "value" : "", + "description" : "规则任务的规则.", + "popular" : true + } ] + }, { + "name" : "ruletask_variables_inputpackage", + "properties" : [ { + "id" : "ruletask_variables_input", + "type" : "String", + "title" : "输入变量", + "value" : "", + "description" : "规则任务的输入变量.", + "popular" : true + } ] + }, { + "name" : "ruletask_excludepackage", + "properties" : [ { + "id" : "ruletask_exclude", + "type" : "Boolean", + "title" : "排除", + "value" : "false", + "description" : "使用作为排它性的规则属性", + "popular" : true + } ] + }, { + "name" : "ruletask_resultpackage", + "properties" : [ { + "id" : "ruletask_result", + "type" : "String", + "title" : "结果变量", + "value" : "", + "description" : "规则任务的结果变量", + "popular" : true + } ] + }, { + "name" : "mailtasktopackage", + "properties" : [ { + "id" : "mailtaskto", + "type" : "Text", + "title" : "发往", + "value" : "", + "description" : "接收者,格式为邮件。多个接收者请用逗号分割的列表来定义 ", + "popular" : true + } ] + }, { + "name" : "mailtaskfrompackage", + "properties" : [ { + "id" : "mailtaskfrom", + "type" : "Text", + "title" : "来自", + "value" : "", + "description" : "发送者的邮箱.若不提供,默认将使用配置中的来源地址.", + "popular" : true + } ] + }, { + "name" : "mailtasksubjectpackage", + "properties" : [ { + "id" : "mailtasksubject", + "type" : "Text", + "title" : "标题", + "value" : "", + "description" : "Email中的标题.", + "popular" : true + } ] + }, { + "name" : "mailtaskccpackage", + "properties" : [ { + "id" : "mailtaskcc", + "type" : "Text", + "title" : "抄送", + "value" : "", + "description" : "抄送的Email地址,多个接收者请用逗号分隔开。", + "popular" : true + } ] + }, { + "name" : "mailtaskbccpackage", + "properties" : [ { + "id" : "mailtaskbcc", + "type" : "Text", + "title" : "暗抄送", + "value" : "", + "description" : "暗抄送的Email地址. 多个接收者请用逗号分隔开", + "popular" : true + } ] + }, { + "name" : "mailtasktextpackage", + "properties" : [ { + "id" : "mailtasktext", + "type" : "Text", + "title" : "内容", + "value" : "", + "description" : "Email中的内容, 案例一需要发送纯文件的邮件. 可使用Html格式的邮件进行发送,若邮件的接收的客户端不支持这种格式,客户端可转为纯文本的邮件", + "popular" : true + } ] + }, { + "name" : "mailtaskhtmlpackage", + "properties" : [ { + "id" : "mailtaskhtml", + "type" : "Text", + "title" : "Html", + "value" : "", + "description" : "HTML中的一片段作为邮件的内容.", + "popular" : true + } ] + }, { + "name" : "mailtaskcharsetpackage", + "properties" : [ { + "id" : "mailtaskcharset", + "type" : "String", + "title" : "字符类型", + "value" : "", + "description" : "对于很多非英语语言来说,允许更改邮件的编码设置是必要的 ", + "popular" : true + } ] + }, { + "name" : "callactivitycalledelementpackage", + "properties" : [ { + "id" : "callactivitycalledelement", + "type" : "String", + "title" : "调用元素", + "value" : "", + "description" : "流程引用.", + "popular" : true + } ] + }, { + "name" : "callactivityinparameterspackage", + "properties" : [ { + "id" : "callactivityinparameters", + "type" : "Complex", + "title" : "输入参数", + "value" : "", + "description" : "定义输入参数", + "popular" : true + } ] + }, { + "name" : "callactivityoutparameterspackage", + "properties" : [ { + "id" : "callactivityoutparameters", + "type" : "Complex", + "title" : "输出参数", + "value" : "", + "description" : "输出参数的定义", + "popular" : true + } ] + }, { + "name" : "cameltaskcamelcontextpackage", + "properties" : [ { + "id" : "cameltaskcamelcontext", + "type" : "String", + "title" : "Camel 上下文", + "value" : "", + "description" : "可选的Camel 上下文定义,若为空,则使用系统缺省的.", + "popular" : true + } ] + }, { + "name" : "muletaskendpointurlpackage", + "properties" : [ { + "id" : "muletaskendpointurl", + "type" : "String", + "title" : "端点URL", + "value" : "", + "description" : "发送消息到Mule的必须的端点URL", + "popular" : true + } ] + }, { + "name" : "muletasklanguagepackage", + "properties" : [ { + "id" : "muletasklanguage", + "type" : "String", + "title" : "语言", + "value" : "", + "description" : "必须的语言定义来解析装载的表达式,如JUEL.", + "popular" : true + } ] + }, { + "name" : "muletaskpayloadexpressionpackage", + "properties" : [ { + "id" : "muletaskpayloadexpression", + "type" : "String", + "title" : "装载的表达式", + "value" : "", + "description" : "发送至Mule的必须执行的消息定义", + "popular" : true + } ] + }, { + "name" : "muletaskresultvariablepackage", + "properties" : [ { + "id" : "muletaskresultvariable", + "type" : "String", + "title" : "结果的变量", + "value" : "", + "description" : "可选的装载返回的结果的变量", + "popular" : true + } ] + }, { + "name" : "conditionsequenceflowpackage", + "properties" : [ { + "id" : "conditionsequenceflow", + "type" : "Complex", + "title" : "跳转条件", + "value" : "", + "description" : "流程跳线的条件定义", + "popular" : true + } ] + }, { + "name" : "defaultflowpackage", + "properties" : [ { + "id" : "defaultflow", + "type" : "Boolean", + "title" : "默认跳线", + "value" : "false", + "description" : "定义默认为顺序跳转", + "popular" : true, + "refToView" : "default" + } ] + }, { + "name" : "conditionalflowpackage", + "properties" : [ { + "id" : "conditionalflow", + "type" : "Boolean", + "title" : "条件的跳线", + "value" : "false", + "description" : "定义条件的跳线", + "popular" : true + } ] + }, { + "name" : "timercycledefinitionpackage", + "properties" : [ { + "id" : "timercycledefinition", + "type" : "String", + "title" : "时间周期 (e.g. R3/PT10H)", + "value" : "", + "description" : "定义ISO-8601时间周期.", + "popular" : true + } ] + }, { + "name" : "timerdatedefinitionpackage", + "properties" : [ { + "id" : "timerdatedefinition", + "type" : "String", + "title" : "时间周期(ISO-8601格式标准)", + "value" : "", + "description" : "定义(ISO-8601格式标准)的定时器.", + "popular" : true + } ] + }, { + "name" : "timerdurationdefinitionpackage", + "properties" : [ { + "id" : "timerdurationdefinition", + "type" : "String", + "title" : "持续的时间 (e.g. PT5M)", + "value" : "", + "description" : "定义(ISO-8601)持续的定时器", + "popular" : true + } ] + }, { + "name" : "timerenddatedefinitionpackage", + "properties" : [ { + "id" : "timerenddatedefinition", + "type" : "String", + "title" : "结束的时间格式ISO-8601", + "value" : "", + "description" : "定义带(ISO-8601 duration)定时器.", + "popular" : true + } ] + }, { + "name" : "messagerefpackage", + "properties" : [ { + "id" : "messageref", + "type" : "String", + "title" : "消息引用", + "value" : "", + "description" : "Define the message name.", + "popular" : true + } ] + }, { + "name" : "signalrefpackage", + "properties" : [ { + "id" : "signalref", + "type" : "String", + "title" : "信号引用", + "value" : "", + "description" : "定义信号的名称.", + "popular" : true + } ] + }, { + "name" : "errorrefpackage", + "properties" : [ { + "id" : "errorref", + "type" : "String", + "title" : "错误引用", + "value" : "", + "description" : "定义错误.", + "popular" : true + } ] + }, { + "name" : "cancelactivitypackage", + "properties" : [ { + "id" : "cancelactivity", + "type" : "Boolean", + "title" : "取消的活动", + "value" : "true", + "description" : "活动允许取消", + "popular" : true, + "refToView" : [ "frame", "frame2" ] + } ] + }, { + "name" : "initiatorpackage", + "properties" : [ { + "id" : "initiator", + "type" : "String", + "title" : "初始化器", + "value" : "", + "description" : "流程定义的初始初始化器", + "popular" : true + } ] + }, { + "name" : "textpackage", + "properties" : [ { + "id" : "text", + "type" : "String", + "title" : "Text", + "value" : "", + "description" : "文本注释", + "popular" : true, + "refToView" : "text" + } ] + }, { + "name" : "multiinstance_typepackage", + "properties" : [ { + "id" : "multiinstance_type", + "type" : "kisbpm-multiinstance", + "title" : "多实例类型", + "value" : "None", + "description" : "通过不同的循环类型,重复的活动执行(并行、串行)可显示", + "popular" : true, + "refToView" : "multiinstance" + } ] + }, { + "name" : "multiinstance_cardinalitypackage", + "properties" : [ { + "id" : "multiinstance_cardinality", + "type" : "String", + "title" : "基数 (多实例)", + "value" : "", + "description" : "定义多实例的基数.", + "popular" : true + } ] + }, { + "name" : "multiinstance_collectionpackage", + "properties" : [ { + "id" : "multiinstance_collection", + "type" : "String", + "title" : "集合(多实例)", + "value" : "", + "description" : "定义多实例的集合.", + "popular" : true + } ] + }, { + "name" : "multiinstance_variablepackage", + "properties" : [ { + "id" : "multiinstance_variable", + "type" : "String", + "title" : "元素的变量(多实例)", + "value" : "", + "description" : "为多实例定义变量元素", + "popular" : true + } ] + }, { + "name" : "multiinstance_conditionpackage", + "properties" : [ { + "id" : "multiinstance_condition", + "type" : "String", + "title" : "完成条件(多实例)", + "value" : "", + "description" : "定义多实例的完成条件.", + "popular" : true + } ] + }, { + "name" : "isforcompensationpackage", + "properties" : [ { + "id" : "isforcompensation", + "type" : "Boolean", + "title" : "作为修正", + "value" : "false", + "description" : "标识当前活动为修正执行活动。", + "popular" : true, + "refToView" : "compensation" + } ] + }, { + "name" : "sequencefloworderpackage", + "properties" : [ { + "id" : "sequencefloworder", + "type" : "Complex", + "title" : "流程顺序", + "value" : "", + "description" : "流程跳出线的顺序", + "popular" : true + } ] + }, { + "name" : "signaldefinitionspackage", + "properties" : [ { + "id" : "signaldefinitions", + "type" : "multiplecomplex", + "title" : "信号定义", + "value" : "", + "description" : "信号定义", + "popular" : true + } ] + }, { + "name" : "messagedefinitionspackage", + "properties" : [ { + "id" : "messagedefinitions", + "type" : "multiplecomplex", + "title" : "消息定义", + "value" : "", + "description" : "消息定义", + "popular" : true + } ] + }, { + "name" : "istransactionpackage", + "properties" : [ { + "id" : "istransaction", + "type" : "Boolean", + "title" : "作为子流程的事务", + "value" : "false", + "description" : "标识子流程作为事务类型", + "popular" : true, + "refToView" : "border" + } ] + } ], + "stencils" : [ { + "type" : "node", + "id" : "BPMNDiagram", + "title" : "BPMN流程图", + "description" : "BPMN2的流程图.", + "view" : "\n\n \n \n \n \n \t\n \n", + "icon" : "diagram.png", + "groups" : [ "Diagram" ], + "mayBeRoot" : true, + "hide" : true, + "propertyPackages" : [ "process_idpackage", "namepackage", "documentationpackage", "process_authorpackage", "process_versionpackage", "process_namespacepackage", "executionlistenerspackage", "eventlistenerspackage", "signaldefinitionspackage", "messagedefinitionspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ ] + }, { + "type" : "node", + "id" : "StartNoneEvent", + "title" : "开始事件", + "description" : "无特定触发器的开始事件", + "view" : "\n\n \n \n \t\n \n \n \n\t\n \n", + "icon" : "startevent/none.png", + "groups" : [ "开始事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "initiatorpackage", "formkeydefinitionpackage", "formpropertiespackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "StartTimerEvent", + "title" : "开始事件(触发器)", + "description" : "带定时器触发的开始事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", + "icon" : "startevent/timer.png", + "groups" : [ "开始事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "StartSignalEvent", + "title" : "开始事件(信号)", + "description" : "通过信号触发开始事件", + "view" : "\n\n \n \n \t\n \n \n\n \n \n \n\t\n \n", + "icon" : "startevent/signal.png", + "groups" : [ "开始事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "StartMessageEvent", + "title" : "开始事件(消息)", + "description" : "通过消息触发开始事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", + "icon" : "startevent/message.png", + "groups" : [ "开始事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "messagerefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "StartErrorEvent", + "title" : "开始事件(错误)", + "description" : "用于捕获BPMN抛出的错误的开始事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "startevent/error.png", + "groups" : [ "开始事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "errorrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "UserTask", + "title" : "人工任务", + "description" : "指派给特定人来执行的人工任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.user.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "usertaskassignmentpackage", "formkeydefinitionpackage", "duedatedefinitionpackage", "prioritydefinitionpackage", "formpropertiespackage", "tasklistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "ServiceTask", + "title" : "服务任务", + "description" : "带有服务逻辑的自动任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.service.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "servicetaskclasspackage", "servicetaskexpressionpackage", "servicetaskdelegateexpressionpackage", "servicetaskfieldspackage", "servicetaskresultvariablepackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "ScriptTask", + "title" : "脚本任务", + "description" : "带有脚本逻辑的自动任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.script.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "scriptformatpackage", "scripttextpackage", "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "BusinessRule", + "title" : "业务规则的任务", + "description" : "带有业务规则的自动任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n \t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.business.rule.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "ruletask_rulespackage", "ruletask_variables_inputpackage", "ruletask_excludepackage", "ruletask_resultpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "ReceiveTask", + "title" : "接收任务", + "description" : "等待接收信号来触发的任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.receive.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "ManualTask", + "title" : "手工任务", + "description" : "不带任何逻辑的自动任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n \t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.manual.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "MailTask", + "title" : "邮件任务", + "description" : "邮箱任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.send.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "mailtasktopackage", "mailtaskfrompackage", "mailtasksubjectpackage", "mailtaskccpackage", "mailtaskbccpackage", "mailtasktextpackage", "mailtaskhtmlpackage", "mailtaskcharsetpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "CamelTask", + "title" : "Camel任务", + "description" : "发送消息给Camel容器的任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.camel.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "cameltaskcamelcontextpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "MuleTask", + "title" : "Mule 任务", + "description" : "发送消息给Mule容器的任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.mule.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "muletaskendpointurlpackage", "muletasklanguagepackage", "muletaskpayloadexpressionpackage", "muletaskresultvariablepackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "SendTask", + "title" : "发送任务", + "description" : "发送消息的任务", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.send.png", + "groups" : [ "活动" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "SubProcess", + "title" : "子流程", + "description" : "子流程范围的流程", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n \n\t\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n", + "icon" : "activity/expanded.subprocess.png", + "groups" : [ "结构模块" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "istransactionpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EventSubProcess", + "title" : "子流程的事件", + "description" : "子流程范围的事件", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n \t\n\t\t\n \t\n\t\n\t\n \n", + "icon" : "activity/event.subprocess.png", + "groups" : [ "结构模块" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "all" ] + }, { + "type" : "node", + "id" : "CallActivity", + "title" : "调用活动", + "description" : "调用的活动", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n \n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/task.png", + "groups" : [ "结构模块" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "callactivitycalledelementpackage", "callactivityinparameterspackage", "callactivityoutparameterspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "ExclusiveGateway", + "title" : "单一网关", + "description" : "单一选择的网关", + "view" : "\n\n \n \n \n \t\t\t\t\t\n \n \n \n \n \n \n \n\t\n\t\n\t\n \n\n", + "icon" : "gateway/exclusive.databased.png", + "groups" : [ "网关" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "ParallelGateway", + "title" : "并行网关", + "description" : "并行执行的网关", + "view" : "\n\n \n \n \n \n \n \n \n \n\t\n\t\n \n\n", + "icon" : "gateway/parallel.png", + "groups" : [ "网关" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "InclusiveGateway", + "title" : "包含网关", + "description" : "满足条件的包含性的网关", + "view" : "\n\n \n \n \n \n\n \n \n \n\t\n\t\n \n\n", + "icon" : "gateway/inclusive.png", + "groups" : [ "网关" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EventGateway", + "title" : "事件网关", + "description" : "事件网关", + "view" : "\n\n \n \n \n \n \n \t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\n\t\n\t\n\t\n\t\n \t\n\t\n\n", + "icon" : "gateway/eventbased.png", + "groups" : [ "网关" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "BoundaryErrorEvent", + "title" : "边界出错事件", + "description" : "捕获BPMN的错误的边界事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", + "icon" : "catching/error.png", + "groups" : [ "边界事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "errorrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundaryTimerEvent", + "title" : "边界的定时事件", + "description" : "A boundary event with a timer trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n \n \n \t\n\t\n \n", + "icon" : "catching/timer.png", + "groups" : [ "边界事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage", "timerenddatedefinitionpackage", "cancelactivitypackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundarySignalEvent", + "title" : "边界信号事件", + "description" : "带有事件触发器的边界事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n\t\n\t\n \n", + "icon" : "catching/signal.png", + "groups" : [ "边界事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "signalrefpackage", "cancelactivitypackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundaryMessageEvent", + "title" : "边界消息事件", + "description" : "带有消息触发器的边界事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \t\n \n \n \n\t\n\t\t\n\t\n\t\n\t\n \n", + "icon" : "catching/message.png", + "groups" : [ "边界事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "messagerefpackage", "cancelactivitypackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundaryCancelEvent", + "title" : "边界取消事件", + "description" : "边界取消事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n \n\t\n \n", + "icon" : "catching/cancel.png", + "groups" : [ "边界事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundaryCompensationEvent", + "title" : "边界修正事件", + "description" : "边界修正事件", + "view" : "\n\n \n \n \t\n \n \n \n\t\n \n \n \n \n \n\t\n \n", + "icon" : "catching/compensation.png", + "groups" : [ "边界事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary", "all" ] + }, { + "type" : "node", + "id" : "CatchTimerEvent", + "title" : "捕捉中间定时器的事件", + "description" : "带有捕捉定时器触发的事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n \n \n \t\n\t\n \n", + "icon" : "catching/timer.png", + "groups" : [ "中间捕获事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "CatchSignalEvent", + "title" : "中间信号捕获事件", + "description" : "信号触发的中间捕获事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n\t\n\t\n \n", + "icon" : "catching/signal.png", + "groups" : [ "中间捕获事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "CatchMessageEvent", + "title" : "中间消息捕获事件", + "description" : "消息触发的中间捕获事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \t\n \n \n \n\t\n\t\t\n\t\n\t\n\t\n \n", + "icon" : "catching/message.png", + "groups" : [ "中间捕获事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "messagerefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "ThrowNoneEvent", + "title" : "无触发的中间事件", + "description" : "无特定触发器的中间事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "throwing/none.png", + "groups" : [ "中间捕获事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ThrowEventsMorph", "sequence_start", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "ThrowSignalEvent", + "title" : "抛出信号的中间事件", + "description" : "通过信号触发器的中间事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "throwing/signal.png", + "groups" : [ "中间捕获事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ThrowEventsMorph", "sequence_start", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EndNoneEvent", + "title" : "结束事件", + "description" : "无特定触发器的结束事件", + "view" : "\n\n \n \n \t\n \n \n \n\t\n \n", + "icon" : "endevent/none.png", + "groups" : [ "结束事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "EndEventsMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EndErrorEvent", + "title" : "结束事件(出错)", + "description" : "抛出错误的结束事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "endevent/error.png", + "groups" : [ "结束事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "errorrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "EndEventsMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EndCancelEvent", + "title" : "结束事件(取消)", + "description" : "取消的结束事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n\t\n \n", + "icon" : "endevent/cancel.png", + "groups" : [ "结束事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "EndEventsMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EndTerminateEvent", + "title" : "结束事件(终止)", + "description" : "终止类型的结束事件", + "view" : "\n\n \n \n \t\n \n \n \n \n \n\t\n \n", + "icon" : "endevent/terminate.png", + "groups" : [ "结束事件" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "EndEventsMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "Pool", + "title" : "泳道", + "description" : "用来结构化流程定义的泳道", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \n \n \n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t \t\n \t\n \n \n\t\n\t\n\t\n\t\n \n \n \n", + "icon" : "swimlane/pool.png", + "groups" : [ "泳道" ], + "layout" : [ { + "type" : "layout.bpmn2_0.pool" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "process_idpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "canContainArtifacts", "all" ] + }, { + "type" : "node", + "id" : "Lane", + "title" : "区域", + "description" : "结构化流程定义的区域", + "view" : "\n\n \n \n \n \n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n \t\t\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n \n\t\n \n", + "icon" : "swimlane/lane.png", + "groups" : [ "泳道" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "PoolChild", "canContainArtifacts", "all" ] + }, { + "type" : "edge", + "id" : "SequenceFlow", + "title" : "顺序跳转线", + "description" : "顺序跳转线定义了不同活动节点执行的顺序", + "view" : "\r\n\r\n\t\r\n\t \t\r\n\t \t\t\r\n\t\t\t\r\n\t \t\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n", + "icon" : "connector/sequenceflow.png", + "groups" : [ "连接对象" ], + "layout" : [ { + "type" : "layout.bpmn2_0.sequenceflow" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "conditionsequenceflowpackage", "executionlistenerspackage", "defaultflowpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ConnectingObjectsMorph", "all" ] + }, { + "type" : "edge", + "id" : "MessageFlow", + "title" : "消息跳转线", + "description" : "用来连接不同泳道中的元素的消息跳转", + "view" : "\r\n\r\n\t\r\n\t\t\r\n\t \t\t\r\n\t \t\t\r\n\t \t\r\n\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", + "icon" : "connector/messageflow.png", + "groups" : [ "连接对象" ], + "layout" : [ { + "type" : "layout.bpmn2_0.sequenceflow" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ConnectingObjectsMorph", "all" ] + }, { + "type" : "edge", + "id" : "Association", + "title" : "关联说明", + "description" : "为元素关联文本说明", + "view" : "\r\n\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", + "icon" : "connector/association.undirected.png", + "groups" : [ "连接对象" ], + "layout" : [ { + "type" : "layout.bpmn2_0.sequenceflow" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ConnectingObjectsMorph", "all" ] + }, { + "type" : "edge", + "id" : "DataAssociation", + "title" : "数据关联说明", + "description" : "为活动节点关联数据元素", + "view" : "\r\n\r\n\t\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", + "icon" : "connector/association.unidirectional.png", + "groups" : [ "连接对象" ], + "layout" : [ { + "type" : "layout.bpmn2_0.sequenceflow" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ConnectingObjectsMorph", "all" ] + }, { + "type" : "node", + "id" : "TextAnnotation", + "title" : "文本关联", + "description" : "关联一组元素进行文本描述", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "artifact/text.annotation.png", + "groups" : [ "文档注释" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "textpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "all" ] + }, { + "type" : "node", + "id" : "DataStore", + "title" : "数据存储", + "description" : "引用一数据存储", + "view" : "\r\n\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t \t\r\n\t\t\r\n\t\t\t \r\n\t\r\n\r\n", + "icon" : "dataobject/data.store.png", + "groups" : [ "文档注释" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "all" ] + } ], + "rules" : { + "cardinalityRules" : [ { + "role" : "Startevents_all", + "incomingEdges" : [ { + "role" : "SequenceFlow", + "maximum" : 0 + } ] + }, { + "role" : "Endevents_all", + "outgoingEdges" : [ { + "role" : "SequenceFlow", + "maximum" : 0 + } ] + } ], + "connectionRules" : [ { + "role" : "SequenceFlow", + "connects" : [ { + "from" : "sequence_start", + "to" : [ "sequence_end" ] + } ] + }, { + "role" : "Association", + "connects" : [ { + "from" : "sequence_start", + "to" : [ "TextAnnotation" ] + }, { + "from" : "sequence_end", + "to" : [ "TextAnnotation" ] + }, { + "from" : "TextAnnotation", + "to" : [ "sequence_end" ] + }, { + "from" : "BoundaryCompensationEvent", + "to" : [ "sequence_end" ] + }, { + "from" : "TextAnnotation", + "to" : [ "sequence_start" ] + }, { + "from" : "BoundaryCompensationEvent", + "to" : [ "sequence_start" ] + } ] + }, { + "role" : "DataAssociation", + "connects" : [ { + "from" : "sequence_start", + "to" : [ "DataStore" ] + }, { + "from" : "sequence_end", + "to" : [ "DataStore" ] + }, { + "from" : "DataStore", + "to" : [ "sequence_end" ] + }, { + "from" : "DataStore", + "to" : [ "sequence_start" ] + } ] + }, { + "role" : "IntermediateEventOnActivityBoundary", + "connects" : [ { + "from" : "Activity", + "to" : [ "IntermediateEventOnActivityBoundary" ] + } ] + } ], + "containmentRules" : [ { + "role" : "BPMNDiagram", + "contains" : [ "all" ] + }, { + "role" : "SubProcess", + "contains" : [ "sequence_start", "sequence_end", "from_task_event", "to_task_event", "EventSubProcess", "TextAnnotation", "DataStore" ] + }, { + "role" : "EventSubProcess", + "contains" : [ "sequence_start", "sequence_end", "from_task_event", "to_task_event", "TextAnnotation", "DataStore" ] + }, { + "role" : "Pool", + "contains" : [ "Lane" ] + }, { + "role" : "Lane", + "contains" : [ "sequence_start", "sequence_end", "EventSubProcess", "TextAnnotation", "DataStore" ] + } ], + "morphingRules" : [ { + "role" : "ActivitiesMorph", + "baseMorphs" : [ "UserTask" ], + "preserveBounds" : true + }, { + "role" : "GatewaysMorph", + "baseMorphs" : [ "ExclusiveGateway" ] + }, { + "role" : "StartEventsMorph", + "baseMorphs" : [ "StartNoneEvent" ] + }, { + "role" : "EndEventsMorph", + "baseMorphs" : [ "StartNoneEvent" ] + }, { + "role" : "CatchEventsMorph", + "baseMorphs" : [ "CatchTimerEvent" ] + }, { + "role" : "ThrowEventsMorph", + "baseMorphs" : [ "ThrowNoneEvent" ] + }, { + "role" : "BoundaryEventsMorph", + "baseMorphs" : [ "ThrowNoneEvent" ] + }, { + "role" : "BoundaryCompensationEvent", + "baseMorphs" : [ "BoundaryCompensationEvent" ] + }, { + "role" : "TextAnnotation", + "baseMorphs" : [ "TextAnnotation" ] + }, { + "role" : "DataStore", + "baseMorphs" : [ "DataStore" ] + } ] + } +} \ No newline at end of file diff --git a/src/main/resources/templates/admin/act_model_input.ftl b/src/main/resources/templates/admin/act_model_input.ftl new file mode 100644 index 0000000..8b28f41 --- /dev/null +++ b/src/main/resources/templates/admin/act_model_input.ftl @@ -0,0 +1,233 @@ +<#assign base=request.contextPath /> +<#import "../common/defaultLayout.ftl" as defaultLayout> +<@defaultLayout.layout> + +
+
+
+
系统管理 / 工作流程管理
+
+
+ +
+ +
+
+ + + + + +
+
+ * + 模型(流程)名称 +
+
+ onKeyUp="clearValidInfo()" /> +
+
+
+ +
+
+ * + 流程标识 +
+
+ onKeyUp="clearValidInfo()" /> +
+
+
+ + + <#--
+
+ 描述 +
+
+ +
+
+
--> +
+
+
+ +
+ + +
+
+ +
+ +
+ + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/admin/act_model_list.ftl b/src/main/resources/templates/admin/act_model_list.ftl new file mode 100644 index 0000000..76e5b9a --- /dev/null +++ b/src/main/resources/templates/admin/act_model_list.ftl @@ -0,0 +1,214 @@ +<#assign base=request.contextPath /> +<#import "../common/defaultLayout.ftl" as defaultLayout> +<@defaultLayout.layout> + +
+
+ +
工作流程 / + 模型管理 +
+
+
+ +
+
+
+
+ <#--<@shiro.hasPermission name="ROLE_ADD">--> + + <#-- + <@shiro.hasPermission name="ROLE_DELRTE">--> + + <#----> +
+
+
+
+
+ + + + +
+
+
+
+
+
+ + + + + + + + + + + + + + + + <#if (pager.list)?exists> + <#list pager.list as list> + + + + + + + + + + + + + +
+ id模型(流程)名称流程标识最新版本创建日期最后更新日期操作
+ + ${list.id!}${list.modelName!}${list.procDefKey!}${list.rev!}<#if list.createdTime??>${list.createdTime?datetime}<#if list.lastUpdatedTime??>${list.lastUpdatedTime?datetime} +
+
+ + + + <#--<@shiro.hasPermission name="ROLE_EDIT">--> + + <#----> + +
+
+
+ +
+ + <#if (pager.list)?exists && (pager.list?size>0) > +
+ <#include "../common/common_pager.ftl"> +
+ <#else> +
+

没有找到任何记录!

+
+ +
+
+
+
+ + + + + diff --git a/src/main/resources/templates/admin/act_proc_def_list.ftl b/src/main/resources/templates/admin/act_proc_def_list.ftl new file mode 100644 index 0000000..49510ba --- /dev/null +++ b/src/main/resources/templates/admin/act_proc_def_list.ftl @@ -0,0 +1,267 @@ +<#assign base=request.contextPath /> +<#import "../common/defaultLayout.ftl" as defaultLayout> +<@defaultLayout.layout> + +
+
+ +
工作流程 / + 流程定义管理 +
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+ + + + +
+
+
+
+ <#--
+
+
Modal 标题 + × +
+
+ +
+
+
--> +
+
+ + + + + + + + + + + + + + + + + <#if (pager.list)?exists> + <#list pager.list as list> + + + + + + + + + + + + + + +
+ 流程id流程名称流程标识版本预览激活/挂起部署时间操作
+ + ${list.id!}${list.procName!}${list.procKey!}${list.version!} + + + + + +
+ <#--1激活 2挂起--> + checked/> +
+
<#if list.deployTime??>${list.deployTime?datetime} +
+
+ + + + + + +
+
+
+ +
+ + <#if (pager.list)?exists && (pager.list?size>0) > +
+ <#include "../common/common_pager.ftl"> +
+ <#else> +
+

没有找到任何记录!

+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/resources/templates/admin/act_proc_ins_list.ftl b/src/main/resources/templates/admin/act_proc_ins_list.ftl new file mode 100644 index 0000000..7c8e951 --- /dev/null +++ b/src/main/resources/templates/admin/act_proc_ins_list.ftl @@ -0,0 +1,240 @@ +<#assign base=request.contextPath /> +<#import "../common/defaultLayout.ftl" as defaultLayout> +<@defaultLayout.layout> + +
+
+ +
工作流程 / + 流程实例 +
+
+ +
+
+ + + + + + + + + + + + + + + + + <#if (pager.list)?exists> + <#list pager.list as list> + + + + + + + + + + + + + + + +
流程名称流程标识流程版本申请人申请时间当前任务当前审批人结束时间操作
${list.procName!}${list.procKey!}${list.version!}${list.user!}${list.startTime?datetime}${list.currentTask!}${list.candidateUsers!}<#if list.endTime??>${list.endTime?datetime} + <#if !list.endTime??> + + + + + + + + + + +
+ +
+ + <#if (pager.list)?exists && (pager.list?size>0) > +
+ <#include "../common/common_pager.ftl"> +
+ <#else> +
+

没有找到任何记录!

+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/resources/templates/admin/act_script_input.ftl b/src/main/resources/templates/admin/act_script_input.ftl new file mode 100644 index 0000000..b2e7d88 --- /dev/null +++ b/src/main/resources/templates/admin/act_script_input.ftl @@ -0,0 +1,203 @@ +<#assign base=request.contextPath /> +<#import "../common/defaultLayout.ftl" as defaultLayout> +<@defaultLayout.layout> + +
+
+
+
工作流程 / 流程脚本
+
+
+ +
+ +
+
+ + + + + +
+
+ * + 脚本名称 +
+
+ +
+
+
+ +
+
*脚本所在类
+
+ +
+
+
+ + +
+
*方法名称
+
+ +
+
+
+
+
+
+ +
+ + +
+
+ +
+ +
+ + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/admin/act_script_list.ftl b/src/main/resources/templates/admin/act_script_list.ftl new file mode 100644 index 0000000..89d299e --- /dev/null +++ b/src/main/resources/templates/admin/act_script_list.ftl @@ -0,0 +1,204 @@ +<#assign base=request.contextPath /> +<#import "../common/defaultLayout.ftl" as defaultLayout> +<@defaultLayout.layout> + +
+
+ +
工作流程 / + 模型管理 +
+
+
+ +
+
+
+
+ <#--<@shiro.hasPermission name="ROLE_ADD">--> + + <#-- + <@shiro.hasPermission name="ROLE_DELRTE">--> + + <#----> +
+
+
+
+
+ + + + +
+
+
+
+
+
+ + + + + + + + + + + + + + + + <#if (pager.list)?exists> + <#list pager.list as list> + + + + + + + + + + + + + +
+ id脚本名称脚本所在类脚本方法创建日期最后更新日期操作
+ + ${list.id!}${list.scriptName!}${list.className!}${list.classMethod!}<#if list.createdTime??>${list.createdTime?datetime}<#if list.lastUpdatedTime??>${list.lastUpdatedTime?datetime} +
+
+ + + +
+
+
+ +
+ + <#if (pager.list)?exists && (pager.list?size>0) > +
+ <#include "../common/common_pager.ftl"> +
+ <#else> +
+

没有找到任何记录!

+
+ +
+
+
+
+ + + + + diff --git a/src/main/resources/templates/admin/act_task_def.ftl b/src/main/resources/templates/admin/act_task_def.ftl new file mode 100644 index 0000000..a4a32a9 --- /dev/null +++ b/src/main/resources/templates/admin/act_task_def.ftl @@ -0,0 +1,196 @@ +<#assign base=request.contextPath /> +<#import "../common/defaultLayout.ftl" as defaultLayout> +<@defaultLayout.layout> + +
+
+ +
${procDefName!} / + 任务设置 +
+
+ +
+
+ + + + + + + + + + + + + + + + + + <#list taskList as list> + + + + + + + + + + + + + + + + + + + + + + +
序号任务名称任务类型回退任务审批人审批角色审批通过脚本审批驳回脚本操作
${list_index+1}${list.taskName!} + <#if list.taskIndex != 1> + <#if list.taskType == 0> + 或签 + <#else> + 会签 + + + + <#if list.taskIndex != 1> + + + + <#if list.taskIndex != 1> + + + + <#if list.taskIndex != 1> + + + + <#if list.taskIndex != 1> + + + + <#if list.taskIndex != 1> + + + + <#if list.taskIndex != 1> +
+
+ + +
+
+ +
+ + +
+
+ +
+ <#----> + +
+
+ + + +