From d592a2b592754dd0323c136f9bce77e0c5f2f0c3 Mon Sep 17 00:00:00 2001 From: wanggeng <450292408@qq.com> Date: Fri, 29 Apr 2022 21:01:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9B=9E=E9=80=80=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/oa/OaFormReportController.java | 14 ++ .../enums/oa/TaskCommentTypeEnum.java | 30 +++ .../activiti/pojo/bos/oa/TaskCommentBO.java | 79 ++++++ .../pojo/dtos/oa/OaProcessLogDTO.java | 12 + .../pojo/vos/oa/page/FormButtonVO.java | 18 ++ .../pojo/vos/oa/page/GoBackUserTaskVO.java | 27 -- .../activiti/IActivitiModelService.java | 18 +- .../impl/ActivitiModelServiceImpl.java | 52 +++- .../service/oa/IOaFormReportService.java | 20 +- .../oa/impl/OaFormReportRouteServiceImpl.java | 57 +++-- .../oa/impl/OaFormReportServiceImpl.java | 234 +++++++++++++----- .../service/oa/impl/OaServiceImpl.java | 40 +-- .../properties/oa-node-manage-popup.html | 8 +- .../service/design/IFormDesignService.java | 1 + .../design/impl/FormDesignServiceImpl.java | 3 +- .../resources/static/form/js/form-util.js | 129 ---------- .../resources/static/form/js/oa-form-util.js | 211 +++++++++++++--- 17 files changed, 643 insertions(+), 310 deletions(-) create mode 100644 module-activiti/src/main/java/ink/wgink/module/activiti/enums/oa/TaskCommentTypeEnum.java create mode 100644 module-activiti/src/main/java/ink/wgink/module/activiti/pojo/bos/oa/TaskCommentBO.java diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/oa/OaFormReportController.java b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/oa/OaFormReportController.java index d4917f78..794ef3c8 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/oa/OaFormReportController.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/oa/OaFormReportController.java @@ -71,6 +71,20 @@ public class OaFormReportController extends DefaultBaseController { return new SuccessResult(); } + @ApiOperation(value = "更新回退", notes = "更新回退接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "taskId", value = "当前任务ID", paramType = "path"), + @ApiImplicitParam(name = "nodeId", value = "跳转节点ID", paramType = "path") + }) + @PutMapping("update-go-back/process-instance-id/{processInstanceId}/task-id/{taskId}/node-id/{nodeId}") + public SuccessResult update(@PathVariable("processInstanceId") String processInstanceId, + @PathVariable("taskId") String taskId, + @PathVariable("nodeId") String nodeId, + @RequestBody Map params) { + oaFormReportService.updateGoBack(processInstanceId, taskId, nodeId, params); + return new SuccessResult(); + } + @GetMapping("get/code/{formCode}/version/{formVersion}/uid/{uid}") public Map get(@PathVariable("formCode") String formCode, @PathVariable("formVersion") Integer formVersion, @PathVariable("uid") String uid) { return oaFormReportService.get(formCode, formVersion, uid); diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/enums/oa/TaskCommentTypeEnum.java b/module-activiti/src/main/java/ink/wgink/module/activiti/enums/oa/TaskCommentTypeEnum.java new file mode 100644 index 00000000..a03af907 --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/enums/oa/TaskCommentTypeEnum.java @@ -0,0 +1,30 @@ +package ink.wgink.module.activiti.enums.oa; + +/** + * @ClassName: TaskCommentEnum + * @Description: 任务批注类型 + * @Author: wanggeng + * @Date: 2022/4/28 22:47 + * @Version: 1.0 + */ +public enum TaskCommentTypeEnum { + SIGN("sign", "签批"), + JOINTLY_SIGN("jointlySign", "会签"), + GO_BACK("goBack", "回退"); + + private String value; + private String text; + + TaskCommentTypeEnum(String value, String text) { + this.value = value; + this.text = text; + } + + public String getValue() { + return value == null ? "" : value.trim(); + } + + public String getText() { + return text == null ? "" : text.trim(); + } +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/bos/oa/TaskCommentBO.java b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/bos/oa/TaskCommentBO.java new file mode 100644 index 00000000..ee3d3ea9 --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/bos/oa/TaskCommentBO.java @@ -0,0 +1,79 @@ +package ink.wgink.module.activiti.pojo.bos.oa; + +import ink.wgink.module.activiti.enums.oa.TaskCommentTypeEnum; + +/** + * @ClassName: TaskCommentBO + * @Description: 任务批注 + * @Author: wanggeng + * @Date: 2022/4/28 22:46 + * @Version: 1.0 + */ +public class TaskCommentBO { + + private TaskCommentTypeEnum type; + private String userId; + private String userName; + private String fieldName; + private String fieldExplain; + private String content; + private String time; + + public TaskCommentTypeEnum getType() { + return type; + } + + public void setType(TaskCommentTypeEnum type) { + this.type = type; + } + + public String getUserId() { + return userId == null ? "" : userId.trim(); + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getUserName() { + return userName == null ? "" : userName.trim(); + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getFieldName() { + return fieldName == null ? "" : fieldName.trim(); + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public String getFieldExplain() { + return fieldExplain == null ? "" : fieldExplain.trim(); + } + + public void setFieldExplain(String fieldExplain) { + this.fieldExplain = fieldExplain; + } + + public String getContent() { + return content == null ? "" : content.trim(); + } + + public void setContent(String content) { + this.content = content; + } + + public String getTime() { + return time == null ? "" : time.trim(); + } + + public void setTime(String time) { + this.time = time; + } + + +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/dtos/oa/OaProcessLogDTO.java b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/dtos/oa/OaProcessLogDTO.java index 40d27cc7..b38c8de2 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/dtos/oa/OaProcessLogDTO.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/dtos/oa/OaProcessLogDTO.java @@ -1,5 +1,6 @@ package ink.wgink.module.activiti.pojo.dtos.oa; +import ink.wgink.module.activiti.pojo.bos.oa.TaskCommentBO; import io.swagger.annotations.ApiModel; import java.util.Map; @@ -24,6 +25,7 @@ public class OaProcessLogDTO { private String taskStatus; private Map taskVariables; private Map processVariables; + private TaskCommentBO comment; public String getTaskId() { @@ -106,6 +108,14 @@ public class OaProcessLogDTO { this.processVariables = processVariables; } + public TaskCommentBO getComment() { + return comment; + } + + public void setComment(TaskCommentBO comment) { + this.comment = comment; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder("{"); @@ -129,6 +139,8 @@ public class OaProcessLogDTO { .append(taskVariables); sb.append(",\"processVariables\":") .append(processVariables); + sb.append(",\"comment\":") + .append(comment); sb.append('}'); return sb.toString(); } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/vos/oa/page/FormButtonVO.java b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/vos/oa/page/FormButtonVO.java index 9414c688..283f8cee 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/vos/oa/page/FormButtonVO.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/vos/oa/page/FormButtonVO.java @@ -13,6 +13,8 @@ import java.util.List; public class FormButtonVO { private Integer btnAttachment; + private Integer btnPrint; + private Integer btnCC; private Integer btnGoBack; private List goBackUserTasks; @@ -24,6 +26,22 @@ public class FormButtonVO { this.btnAttachment = btnAttachment; } + public Integer getBtnPrint() { + return btnPrint == null ? 0 : btnPrint; + } + + public void setBtnPrint(Integer btnPrint) { + this.btnPrint = btnPrint; + } + + public Integer getBtnCC() { + return btnCC == null ? 0 : btnCC; + } + + public void setBtnCC(Integer btnCC) { + this.btnCC = btnCC; + } + public Integer getBtnGoBack() { return btnGoBack == null ? 0 : btnGoBack; } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/vos/oa/page/GoBackUserTaskVO.java b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/vos/oa/page/GoBackUserTaskVO.java index cb3886ed..dd06309b 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/vos/oa/page/GoBackUserTaskVO.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/vos/oa/page/GoBackUserTaskVO.java @@ -9,19 +9,8 @@ package ink.wgink.module.activiti.pojo.vos.oa.page; */ public class GoBackUserTaskVO { - private String taskId; private String nodeId; private String taskName; - private String userId; - private String userName; - - public String getTaskId() { - return taskId == null ? "" : taskId.trim(); - } - - public void setTaskId(String taskId) { - this.taskId = taskId; - } public String getNodeId() { return nodeId == null ? "" : nodeId.trim(); @@ -38,20 +27,4 @@ public class GoBackUserTaskVO { public void setTaskName(String taskName) { this.taskName = taskName; } - - public String getUserId() { - return userId == null ? "" : userId.trim(); - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getUserName() { - return userName == null ? "" : userName.trim(); - } - - public void setUserName(String userName) { - this.userName = userName; - } } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiModelService.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiModelService.java index 1514e617..46d1402d 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiModelService.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiModelService.java @@ -42,6 +42,10 @@ public interface IActivitiModelService { * 多实例集合名称 */ String ASSIGNEE_LIST = "assigneeList"; + /** + * 候选人用户 + */ + String ASSIGNEE_USER = "assigneeUser"; /** * 多实例集合 */ @@ -59,6 +63,10 @@ public interface IActivitiModelService { * 实例数量 */ String NR_OF_INSTANCES = "nrOfInstances"; + /** + * 回退连线ID + */ + String GO_BACK_FLOW_ID = "goBackFlow"; /** * 保存模型 @@ -108,7 +116,7 @@ public interface IActivitiModelService { * @param processDefinitionId 流程定义ID * @return */ - FlowNode getFlowNodeByTaskDefinitionKeyAndProcessDefinitionId(String currentTaskDefinitionKey, String processDefinitionId); + FlowNode getFlowNodeByNodeIdAndProcessDefinitionId(String currentTaskDefinitionKey, String processDefinitionId); /** * 获取后续用户任务列表的输入序列流 @@ -134,6 +142,14 @@ public interface IActivitiModelService { */ List listNextUserTasksByUserTask(UserTask userTask); + /** + * 获取之前的用户任务列表 + * + * @param userTask + * @return + */ + List listBeforeUserTaskByUserTask(UserTask userTask); + /** * 获取第一个用户任务 * diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiModelServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiModelServiceImpl.java index 91636c3b..63e4bfb1 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiModelServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiModelServiceImpl.java @@ -139,7 +139,7 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct } @Override - public FlowNode getFlowNodeByTaskDefinitionKeyAndProcessDefinitionId(String currentTaskDefinitionKey, String processDefinitionId) { + public FlowNode getFlowNodeByNodeIdAndProcessDefinitionId(String currentTaskDefinitionKey, String processDefinitionId) { BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); return (FlowNode) bpmnModel.getFlowElement(currentTaskDefinitionKey); } @@ -178,9 +178,27 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct List outgoingFlows = userTask.getOutgoingFlows(); List nextUserTasks = new ArrayList<>(); setNextUserTasks(userTask, outgoingFlows, nextUserTasks); + // 去重 + for (int i = 0; i < nextUserTasks.size(); i++) { + for (int j = i + 1; j < nextUserTasks.size(); j++) { + if (StringUtils.equals(nextUserTasks.get(i).getId(), nextUserTasks.get(j).getId())) { + nextUserTasks.remove(j); + i--; + break; + } + } + } return nextUserTasks; } + @Override + public List listBeforeUserTaskByUserTask(UserTask userTask) { + List incomingFlows = userTask.getIncomingFlows(); + List beforeUserTasks = new ArrayList<>(); + setBeforeUserTasks(userTask, incomingFlows, beforeUserTasks); + return beforeUserTasks; + } + @Override public UserTask getFirstUserTaskByProcessDefinitionId(String processDefinitionId) { List listFlowNode = listFlowNodeByProcessDefinitionId(processDefinitionId); @@ -223,7 +241,7 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct @Override public UserTask getNextUserTask(String currentTaskDefinitionKey, String processDefinitionId, Map reportForm) { - FlowNode currentFlowNode = getFlowNodeByTaskDefinitionKeyAndProcessDefinitionId(currentTaskDefinitionKey, processDefinitionId); + FlowNode currentFlowNode = getFlowNodeByNodeIdAndProcessDefinitionId(currentTaskDefinitionKey, processDefinitionId); List outgoingFlows = currentFlowNode.getOutgoingFlows(); for (SequenceFlow sequenceFlow : outgoingFlows) { FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement(); @@ -432,6 +450,35 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct } } + /** + * 设置之前的用户任务 + * + * @param currentFlowNode + * @param incomingFlows + * @param beforeUserTasks + */ + private void setBeforeUserTasks(FlowNode currentFlowNode, List incomingFlows, List beforeUserTasks) { + if (currentFlowNode instanceof StartEvent) { + return; + } + if (incomingFlows.isEmpty()) { + throw new SearchException("流程错误,用户任务输入序列流不存在"); + } + for (SequenceFlow incomingFlow : incomingFlows) { + FlowElement sourceFlowElement = incomingFlow.getSourceFlowElement(); + if (sourceFlowElement instanceof UserTask) { + UserTask beforeUserTask = (UserTask) sourceFlowElement; + setBeforeUserTasks(beforeUserTask, beforeUserTask.getIncomingFlows(), beforeUserTasks); + beforeUserTasks.add(beforeUserTask); + continue; + } + if (sourceFlowElement instanceof ExclusiveGateway) { + ExclusiveGateway exclusiveGateway = (ExclusiveGateway) sourceFlowElement; + setBeforeUserTasks(exclusiveGateway, exclusiveGateway.getIncomingFlows(), beforeUserTasks); + } + } + } + /** * 设置下一个用户任务列表 * @@ -460,6 +507,7 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct } } + /** * 获取运行流程图输入流 * diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/IOaFormReportService.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/IOaFormReportService.java index 5318b0f7..2b7bb5d6 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/IOaFormReportService.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/IOaFormReportService.java @@ -19,20 +19,20 @@ public interface IOaFormReportService { String KEY_FORM_VERSION = "formVersion"; String KEY_REPORT_UID = "reportUid"; String KEY_ASSIGNEE_USER = "assigneeUser"; + String KEY_ASSIGNEE_USER_NAME = "assigneeUserName"; String KEY_START_ASSIGNEE_USER = "startAssigneeUser"; String KEY_ASSIGNEES = "assignees"; String KEY_SELECT_TYPE = "selectType"; String KEY_IS_NEXT_END_EVENT = "isNextEndEvent"; String KEY_RECORD_FIELDS = "recordFields"; - String KEY_ASSIGNEE_USER_NAME = "assigneeUserName"; /** - * 编辑记录分隔符 + * 签批关键字后缀 */ - String EDIT_RECORD_SEPARATOR = "_$RECORD$_"; + String EDIT_SIGN_KEY_SUFFIX = "Sign"; /** - * 编辑记录关键字前缀 + * 会签关键字后缀 */ - String EDIT_RECORD_KEY_PREFIX = "RECORD:"; + String EDIT_JOINTLY_SIGN_KEY_SUFFIX = "JointlySign"; /** * 保存表单 @@ -106,6 +106,16 @@ public interface IOaFormReportService { */ void updateByUserIdAndUserName(String userId, String userName, String taskId, String formCode, Integer formVersion, Integer isNeedClaim, String uid, Map params); + /** + * 更新回退 + * + * @param processInstanceId + * @param currentTaskId + * @param jumpNodeId + * @param params + */ + void updateGoBack(String processInstanceId, String currentTaskId, String jumpNodeId, Map params); + /** * 表单详情 * diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportRouteServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportRouteServiceImpl.java index c02ebbcf..b282b76d 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportRouteServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportRouteServiceImpl.java @@ -33,9 +33,9 @@ import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; /** @@ -86,12 +86,11 @@ public class OaFormReportRouteServiceImpl extends DefaultBaseService implements model.put("confirmAssignees", JSON.toJSONString(confirmAssigneeVOs)); setPageFields(deploymentId, firstUserTask, model); - setPageFormButtonsAndHistoryUserTasks(deploymentId, null, firstUserTask, model); + setPageFormButtonsAndHistoryUserTasks(deploymentId, null, null, firstUserTask, model); setPageCurrentUser(model); formReportRouteService.save(formCode, formVersion, httpSession, httpServletRequest, httpServletResponse, model); } - @Override public void update(String taskId, String formCode, Integer formVersion, Integer isNeedClaim, HttpSession httpSession, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); @@ -104,7 +103,7 @@ public class OaFormReportRouteServiceImpl extends DefaultBaseService implements String deploymentId = processDefinition.getDeploymentId(); LOG.debug("获取下一个用户任务"); - FlowNode flowNode = activitiModelService.getFlowNodeByTaskDefinitionKeyAndProcessDefinitionId(task.getTaskDefinitionKey(), task.getProcessDefinitionId()); + FlowNode flowNode = activitiModelService.getFlowNodeByNodeIdAndProcessDefinitionId(task.getTaskDefinitionKey(), task.getProcessDefinitionId()); UserTask currentUserTask = (UserTask) flowNode; Map model = getHashMap(10); @@ -117,7 +116,7 @@ public class OaFormReportRouteServiceImpl extends DefaultBaseService implements model.put("confirmAssignees", JSON.toJSONString(confirmAssigneeVOs)); setPageFields(deploymentId, currentUserTask, model); - setPageFormButtonsAndHistoryUserTasks(deploymentId, null, currentUserTask, model); + setPageFormButtonsAndHistoryUserTasks(deploymentId, task.getId(), task.getProcessInstanceId(), currentUserTask, model); setPageCurrentUser(model); // 设置代理人 formReportRouteService.update(formCode, formVersion, httpSession, httpServletRequest, httpServletResponse, model); @@ -190,10 +189,12 @@ public class OaFormReportRouteServiceImpl extends DefaultBaseService implements * 设置页面按钮与历史任务,如果没有回退按钮,不设置回退 * * @param deploymentId + * @param currentTaskId + * @param processInstanceId * @param userTask * @param model */ - private void setPageFormButtonsAndHistoryUserTasks(String deploymentId, String currentTaskId, UserTask userTask, Map model) { + private void setPageFormButtonsAndHistoryUserTasks(String deploymentId, String currentTaskId, String processInstanceId, UserTask userTask, Map model) { NodeButtonDTO nodeButtonDTO = nodeButtonService.getByDeploymentIdAndNodeId(deploymentId, userTask.getId()); FormButtonVO formButtonVO = new FormButtonVO(); if (nodeButtonDTO == null) { @@ -206,35 +207,37 @@ public class OaFormReportRouteServiceImpl extends DefaultBaseService implements } else { formButtonVO.setBtnGoBack(nodeButtonDTO.getBtnGoBack()); } - if (nodeButtonDTO.getBtnGoBack() == 1) { + if (formButtonVO.getBtnGoBack() == 1) { LOG.debug("存在回退按钮,查询历史节点"); List historicTaskInstances = historyService.createHistoricTaskInstanceQuery() .includeTaskLocalVariables() - .taskId(currentTaskId) + .processInstanceId(processInstanceId) .finished() .orderByHistoricTaskInstanceEndTime() .asc() .list(); - List goBackUserTaskVOs = historicTaskInstances.stream().map(historicTaskInstance -> { - String assigneeUserId = historicTaskInstance.getAssignee(); - Map localVariables = historicTaskInstance.getTaskLocalVariables(); - Object assigneeUserNameObject = localVariables.get(IOaFormReportService.KEY_ASSIGNEE_USER_NAME); - String assigneeUserName = localVariables.get(IOaFormReportService.KEY_ASSIGNEE_USER_NAME).toString(); - if (assigneeUserNameObject != null) { - assigneeUserName = assigneeUserNameObject.toString(); + List beforeUserTasks = activitiModelService.listBeforeUserTaskByUserTask(userTask); + // 去除历史流程中没有走的节点任务 + List goBackUserTaskVOs = new ArrayList<>(); + for (int i = 0; i < beforeUserTasks.size(); i++) { + UserTask beforeUserTask = beforeUserTasks.get(i); + boolean isExist = false; + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + if (StringUtils.equals(beforeUserTask.getId(), historicTaskInstance.getTaskDefinitionKey())) { + isExist = true; + break; + } + } + if (!isExist) { + beforeUserTasks.remove(i); + i--; + continue; } - String nodeId = historicTaskInstance.getTaskDefinitionKey(); - String taskId = historicTaskInstance.getId(); - String taskName = historicTaskInstance.getName(); - GoBackUserTaskVO goBackUserTaskVO = new GoBackUserTaskVO(); - goBackUserTaskVO.setTaskId(taskId); - goBackUserTaskVO.setNodeId(nodeId); - goBackUserTaskVO.setTaskName(taskName); - goBackUserTaskVO.setUserId(assigneeUserId); - goBackUserTaskVO.setUserName(assigneeUserName); - return goBackUserTaskVO; - }).collect(Collectors.toList()); + goBackUserTaskVO.setNodeId(beforeUserTask.getId()); + goBackUserTaskVO.setTaskName(beforeUserTask.getName()); + goBackUserTaskVOs.add(goBackUserTaskVO); + } formButtonVO.setGoBackUserTasks(goBackUserTaskVOs); } model.put("formButton", JSONObject.toJSONString(formButtonVO)); @@ -264,7 +267,7 @@ public class OaFormReportRouteServiceImpl extends DefaultBaseService implements LOG.debug("3.遍历后续的用户列表"); // 按照流入序列流进行区分,页面上体现出为按钮中对应的不同的代理人列表 - List confirmAssigneeVOs = new CopyOnWriteArrayList<>(); + List confirmAssigneeVOs = new ArrayList<>(); for (int i = 0; i < sequenceFlows.size(); i++) { SequenceFlow sequenceFlow = sequenceFlows.get(i); String name = sequenceFlow.getName(); diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportServiceImpl.java index 7f147991..0f82665a 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportServiceImpl.java @@ -6,9 +6,12 @@ import com.alibaba.fastjson.JSONObject; import ink.wgink.common.base.DefaultBaseService; import ink.wgink.exceptions.ParamsException; import ink.wgink.exceptions.SearchException; +import ink.wgink.exceptions.base.SystemException; import ink.wgink.module.activiti.enums.oa.SelectAssigneeTypeEnum; +import ink.wgink.module.activiti.enums.oa.TaskCommentTypeEnum; import ink.wgink.module.activiti.enums.oa.field.FieldEditRecordEnum; import ink.wgink.module.activiti.pojo.bos.oa.OaFormReportUnWantedValueBO; +import ink.wgink.module.activiti.pojo.bos.oa.TaskCommentBO; import ink.wgink.module.activiti.pojo.vos.oa.OaFormReportRecordFieldVO; import ink.wgink.module.activiti.service.activiti.IActivitiModelService; import ink.wgink.module.activiti.service.oa.IOaFormReportService; @@ -19,19 +22,21 @@ import ink.wgink.pojo.app.AppTokenUser; import ink.wgink.pojo.bos.UserInfoBO; import ink.wgink.pojo.result.SuccessResultList; import ink.wgink.util.date.DateUtil; -import org.activiti.engine.HistoryService; -import org.activiti.engine.IdentityService; -import org.activiti.engine.RuntimeService; -import org.activiti.engine.TaskService; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.MultiInstanceLoopCharacteristics; +import org.activiti.bpmn.model.SequenceFlow; +import org.activiti.bpmn.model.UserTask; +import org.activiti.engine.*; import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.task.Comment; import org.activiti.engine.task.Task; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @ClassName: OaFormReportServiceImpl @@ -48,6 +53,8 @@ public class OaFormReportServiceImpl extends DefaultBaseService implements IOaFo @Autowired private IFormReportService formReportService; @Autowired + private RepositoryService repositoryService; + @Autowired private RuntimeService runtimeService; @Autowired private HistoryService historyService; @@ -55,6 +62,10 @@ public class OaFormReportServiceImpl extends DefaultBaseService implements IOaFo private TaskService taskService; @Autowired private IdentityService identityService; + @Autowired + private ManagementService managementService; + @Autowired + private IActivitiModelService activitiModelService; @Override public void save(String processDefinitionId, String formCode, Integer formVersion, Map params) { @@ -99,10 +110,10 @@ public class OaFormReportServiceImpl extends DefaultBaseService implements IOaFo if (!oaFormReportUnWantedValueBO.getNextEndEvent()) { setFormReportAssignee(oaFormReportUnWantedValueBO.getSelectType(), oaFormReportUnWantedValueBO.getAssignees(), params); } - setRecordFields(task.getId(), oaFormReportUnWantedValueBO.getRecordFields(), userId, userName, params); + setRecordFields(task.getProcessInstanceId(), task.getId(), oaFormReportUnWantedValueBO.getRecordFields(), userId, userName, params); // 保存代理人昵称 params.put(KEY_ASSIGNEE_USER_NAME, userName); - taskService.setVariablesLocal(task.getId(), params); + // 保存表单日志 taskService.complete(task.getId(), params); } @@ -120,6 +131,10 @@ public class OaFormReportServiceImpl extends DefaultBaseService implements IOaFo @Override public void updateByUserIdAndUserName(String userId, String userName, String taskId, String formCode, Integer formVersion, Integer isNeedClaim, String uid, Map params) { + Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult(); + if (currentTask == null) { + throw new SearchException("任务不存在或已被处理"); + } OaFormReportUnWantedValueBO oaFormReportUnWantedValueBO = getOaFormReportUnWantedValue(params); formReportService.update(formCode, formVersion, uid, params); if (isNeedClaim == 1) { @@ -133,58 +148,153 @@ public class OaFormReportServiceImpl extends DefaultBaseService implements IOaFo if (!oaFormReportUnWantedValueBO.getNextEndEvent()) { setFormReportAssignee(oaFormReportUnWantedValueBO.getSelectType(), oaFormReportUnWantedValueBO.getAssignees(), params); } - setRecordFields(taskId, oaFormReportUnWantedValueBO.getRecordFields(), userId, userName, params); + setRecordFields(currentTask.getProcessInstanceId(), taskId, oaFormReportUnWantedValueBO.getRecordFields(), userId, userName, params); // 保存代理人昵称 params.put(KEY_ASSIGNEE_USER_NAME, userName); - taskService.setVariablesLocal(taskId, params); + // 保存表单日志 taskService.complete(taskId, params); } + @Override + public void updateGoBack(String processInstanceId, String currentTaskId, String jumpNodeId, Map requestParams) { + LOG.debug("OA流程回退"); + Task currentTask = taskService.createTaskQuery().taskId(currentTaskId).singleResult(); + if (currentTask == null) { + throw new SearchException("任务不存在或已被处理"); + } + UserInfoBO currentUser = securityComponent.getCurrentUser(); + String userId = currentUser.getUserId(); + String userName = currentUser.getUserName(); + + List historicTaskInstances = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list(); + BpmnModel bpmnModel = activitiModelService.getBpmnModelByProcessDefinitionId(currentTask.getProcessDefinitionId()); + LOG.debug("1. 查询当流程节点"); + UserTask currentUserTask = (UserTask) bpmnModel.getFlowElement(currentTask.getTaskDefinitionKey()); + LOG.debug("2. 查询回退的节点"); + UserTask goBackUserTask = (UserTask) bpmnModel.getFlowElement(jumpNodeId); + LOG.debug("3. 缓存现有的下一步连线"); + List oldOutgoingFlows = new ArrayList<>(); + oldOutgoingFlows.addAll(currentUserTask.getOutgoingFlows()); + LOG.debug("4. 创建新连线"); + currentUserTask.getOutgoingFlows().clear(); + List newOutgoingFlows = new ArrayList<>(); + SequenceFlow newOutgoingFlow = new SequenceFlow(); + newOutgoingFlow.setId(IActivitiModelService.GO_BACK_FLOW_ID); + newOutgoingFlow.setSourceFlowElement(currentUserTask); + newOutgoingFlow.setTargetFlowElement(goBackUserTask); + newOutgoingFlows.add(newOutgoingFlow); + currentUserTask.setOutgoingFlows(newOutgoingFlows); + + try { + LOG.debug("5 判断回退节点的类型"); + MultiInstanceLoopCharacteristics goBackUserTaskLoopCharacteristics = goBackUserTask.getLoopCharacteristics(); + Set historicUserTaskUserIdSet = new HashSet<>(); + if (goBackUserTaskLoopCharacteristics == null) { + LOG.debug("5.1 回退节点为普通节点(单实例)。"); + LOG.debug("5.1.1 查询原节点处理人"); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + if (StringUtils.equals(historicTaskInstance.getTaskDefinitionKey(), jumpNodeId)) { + historicUserTaskUserIdSet.add(historicTaskInstance.getAssignee()); + break; + } + } + } else { + LOG.debug("5.2 回退节点为会签节点(多实例)。"); + LOG.debug("5.2.1 查询会签节点代理人"); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + if (StringUtils.equals(historicTaskInstance.getTaskDefinitionKey(), jumpNodeId)) { + historicUserTaskUserIdSet.add(historicTaskInstance.getAssignee()); + } + } + } + LOG.debug("6. 判断当前节点类型"); + MultiInstanceLoopCharacteristics currentUserTaskLoopCharacteristics = currentUserTask.getLoopCharacteristics(); + if (currentUserTaskLoopCharacteristics == null) { + LOG.debug("6.1 当前节点为普通节点"); + } else { + LOG.debug("6.2 当前节点为会签节点(多实例)"); + LOG.debug("6.2.1 删除未完成的任务(当前任务除外)"); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + if (!StringUtils.equals(historicTaskInstance.getId(), currentTaskId)) { + continue; + } + if (historicTaskInstance.getEndTime() != null) { + continue; + } + TaskCommentBO taskCommentBO = new TaskCommentBO(); + taskCommentBO.setType(TaskCommentTypeEnum.GO_BACK); + taskCommentBO.setContent("其他人回退(自动完成)"); + taskCommentBO.setTime(DateUtil.getTime()); + taskCommentBO.setUserId(userId); + taskCommentBO.setUserName(userName); + taskService.addComment(currentTaskId, processInstanceId, TaskCommentTypeEnum.GO_BACK.getValue(), JSONObject.toJSONString(taskCommentBO)); + taskService.complete(historicTaskInstance.getId()); + } + } + LOG.debug("7. 开始完成任务"); + List historicUserTaskUserIds = new ArrayList<>(historicUserTaskUserIdSet); + if (historicUserTaskUserIdSet.size() == 1) { + LOG.debug("7.1 设置代理人"); + requestParams.put(IOaFormReportService.KEY_ASSIGNEE_USER, historicUserTaskUserIds.get(0)); + } else if (historicTaskInstances.size() > 1) { + LOG.debug("7.2 设置代理人(多实例)"); + requestParams.put(IActivitiModelService.ASSIGNEE_LIST, historicUserTaskUserIds); + } else { + throw new SearchException("找不到回退代理人"); + } + LOG.debug("7.3 完成任务"); + TaskCommentBO taskCommentBO = new TaskCommentBO(); + taskCommentBO.setType(TaskCommentTypeEnum.GO_BACK); + taskCommentBO.setContent(requestParams.get("content").toString()); + taskCommentBO.setTime(DateUtil.getTime()); + taskCommentBO.setUserId(userId); + taskCommentBO.setUserName(userName); + taskService.addComment(currentTaskId, processInstanceId, TaskCommentTypeEnum.GO_BACK.getValue(), JSONObject.toJSONString(taskCommentBO)); + taskService.complete(currentTaskId, requestParams); + } catch (Exception e) { + throw new SystemException(e); + } finally { + LOG.debug("9. 恢复原有的下一步连线"); + currentUserTask.setOutgoingFlows(oldOutgoingFlows); + } + } + + /** * 保存记录的字段列表 * + * @param processInstanceId * @param taskId * @param oaFormReportRecordFieldVOs * @param userId * @param userName * @param reportParams */ - private void setRecordFields(String taskId, List oaFormReportRecordFieldVOs, String userId, String userName, Map reportParams) { + private void setRecordFields(String processInstanceId, String taskId, List oaFormReportRecordFieldVOs, String userId, String userName, Map reportParams) { if (oaFormReportRecordFieldVOs.isEmpty()) { return; } String currentTime = DateUtil.getTime(); - Map processVariables = taskService.getVariables(taskId); for (OaFormReportRecordFieldVO oaFormReportRecordFieldVO : oaFormReportRecordFieldVOs) { Object reportRecordObject = reportParams.get(oaFormReportRecordFieldVO.getFieldName()); String reportRecordValue = reportRecordObject == null ? "" : reportRecordObject.toString(); - - // 任务中存储的签批变量关键字 - String taskVariableKey = EDIT_RECORD_KEY_PREFIX + oaFormReportRecordFieldVO.getFieldExplain(); - JSONObject taskSignJsonObject = new JSONObject(); - taskSignJsonObject.put("userId", userId); - taskSignJsonObject.put("userName", userName); - taskSignJsonObject.put("content", reportRecordValue); - taskSignJsonObject.put("time", currentTime); - reportParams.put(taskVariableKey, taskSignJsonObject.toJSONString()); + // 创建批注 if (StringUtils.equals(oaFormReportRecordFieldVO.getEditHistory(), FieldEditRecordEnum.LATEST.getValue())) { - // 内容变更为 [签批人:XX。 内容:XXXXXX。 时间:XXXX-XX-XX XX:XX:XX] - reportParams.put(oaFormReportRecordFieldVO.getFieldName(), String.format("签批人:%s。 内容:%s。 时间:%s。", userName, reportRecordValue, currentTime)); + // 签批批注,存入流程变量 + reportParams.put(oaFormReportRecordFieldVO.getFieldName() + EDIT_SIGN_KEY_SUFFIX, String.format("姓名:%s。 内容:%s。 时间:%s。", userName, reportRecordValue, currentTime)); continue; } if (StringUtils.equals(oaFormReportRecordFieldVO.getEditHistory(), FieldEditRecordEnum.ALL.getValue())) { - // 流程中存储的签批变量关键字 - String processSignKey = String.format("%s%s:%s", EDIT_RECORD_KEY_PREFIX, oaFormReportRecordFieldVO.getFieldName(), oaFormReportRecordFieldVO.getFieldExplain()); - // 合并后的会签存储在流程变量中 - Object processSignValueObj = processVariables.get(processSignKey); - JSONArray processSignValueJsonArray; - if (processSignValueObj != null) { - processSignValueJsonArray = JSONArray.parseArray(processSignValueObj.toString()); - } else { - processSignValueJsonArray = new JSONArray(); - } - processSignValueJsonArray.add(taskSignJsonObject); - taskService.setVariable(taskId, processSignKey, processSignValueJsonArray.toJSONString()); + // 会签批注 + TaskCommentBO taskCommentBO = new TaskCommentBO(); + taskCommentBO.setUserId(userId); + taskCommentBO.setUserName(userName); + taskCommentBO.setContent(reportRecordValue); + taskCommentBO.setTime(currentTime); + taskCommentBO.setFieldName(oaFormReportRecordFieldVO.getFieldName()); + taskCommentBO.setFieldExplain(oaFormReportRecordFieldVO.getFieldExplain()); + taskCommentBO.setType(TaskCommentTypeEnum.JOINTLY_SIGN); + taskService.addComment(taskId, processInstanceId, TaskCommentTypeEnum.JOINTLY_SIGN.getValue(), JSONObject.toJSONString(taskCommentBO)); continue; } throw new ParamsException("记录类型错误"); @@ -239,29 +349,39 @@ public class OaFormReportServiceImpl extends DefaultBaseService implements IOaFo Map detail = formReportService.get(formCode, formVersion, uid); // 查询会签列表 String processInstanceId = detail.get("process_instance_id").toString(); - HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).includeProcessVariables().singleResult(); - Map processVariablesMap = historicProcessInstance.getProcessVariables(); - for (Map.Entry entry : processVariablesMap.entrySet()) { - String key = entry.getKey(); - if (!key.startsWith(IOaFormReportService.EDIT_RECORD_KEY_PREFIX)) { - continue; - } - Object valueObj = entry.getValue(); - if (valueObj == null) { - continue; - } - String value = valueObj.toString(); - if (StringUtils.isBlank(value)) { - continue; - } - String[] keyArray = key.split(":"); - // 普通签批不处理,普通签批格式(RECORD:fieldName),会签格式(RECORD:fieldName:fieldExplain) - if (keyArray.length == 2) { - continue; - } - String fieldName = keyArray[1]; - detail.put("_sign_" + fieldName, JSONArray.parseArray(value)); + LOG.debug("设置签批内容(流程变量)"); + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().includeProcessVariables().processInstanceId(processInstanceId).singleResult(); + if (historicProcessInstance == null) { + throw new SearchException("流程实例不存在"); } + Map processVariables = historicProcessInstance.getProcessVariables(); + for (Map.Entry detailKV : detail.entrySet()) { + Object signObject = processVariables.get(detailKV.getKey() + EDIT_SIGN_KEY_SUFFIX); + if (signObject != null) { + detail.put(detailKV.getKey(), signObject); + } + } + List signComments = taskService.getProcessInstanceComments(processInstanceId, TaskCommentTypeEnum.SIGN.getValue()); + for (Comment comment : signComments) { + TaskCommentBO taskCommentBO = JSONObject.parseObject(comment.getFullMessage(), TaskCommentBO.class); + detail.put(taskCommentBO.getFieldName(), String.format("姓名:%s。 内容:%s。 时间:%s。", taskCommentBO.getUserName(), taskCommentBO.getContent(), taskCommentBO.getTime())); + } + + LOG.debug("会签的内容"); + List jointlySignComments = taskService.getProcessInstanceComments(processInstanceId, TaskCommentTypeEnum.JOINTLY_SIGN.getValue()); + Map> jointlySignMap = new HashMap<>(6); + // 会签列表 + for (Comment comment : jointlySignComments) { + TaskCommentBO taskCommentBO = JSONObject.parseObject(comment.getFullMessage(), TaskCommentBO.class); + String mapKey = taskCommentBO.getFieldName() + EDIT_JOINTLY_SIGN_KEY_SUFFIX; + List taskCommentBOs = jointlySignMap.get(mapKey); + if (taskCommentBOs == null) { + taskCommentBOs = new ArrayList<>(); + } + taskCommentBOs.add(taskCommentBO); + jointlySignMap.put(mapKey, taskCommentBOs); + } + detail.put("jointlySign", jointlySignMap); return detail; } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaServiceImpl.java index 4fe6b992..74e9ff0c 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaServiceImpl.java @@ -1,10 +1,12 @@ package ink.wgink.module.activiti.service.oa.impl; +import com.alibaba.fastjson.JSONObject; import ink.wgink.common.base.DefaultBaseService; import ink.wgink.interfaces.department.IDepartmentBaseService; import ink.wgink.interfaces.department.IDepartmentUserBaseService; import ink.wgink.interfaces.user.IUserBaseService; import ink.wgink.module.activiti.enums.oa.ProcessTaskStatusEnum; +import ink.wgink.module.activiti.pojo.bos.oa.TaskCommentBO; import ink.wgink.module.activiti.pojo.dtos.oa.OaHistoryTaskDTO; import ink.wgink.module.activiti.pojo.dtos.oa.OaProcdefDTO; import ink.wgink.module.activiti.pojo.dtos.oa.OaProcessLogDTO; @@ -28,6 +30,7 @@ import org.activiti.engine.history.HistoricTaskInstanceQuery; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.task.Comment; import org.activiti.engine.task.IdentityLink; import org.activiti.engine.task.Task; import org.activiti.engine.task.TaskQuery; @@ -214,6 +217,8 @@ public class OaServiceImpl extends DefaultBaseService implements IOaService { public List listProcessLog(String processInstanceId) { List oaProcessLogDTOs = new ArrayList<>(); Set userIdSet = new HashSet<>(); + // 批注列表 + List processInstanceComments = taskService.getProcessInstanceComments(processInstanceId); // 已办 List historicTaskInstances = historyService.createHistoricTaskInstanceQuery().includeTaskLocalVariables().processInstanceId(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().asc().list(); historicTaskInstances.forEach(historicTaskInstance -> { @@ -224,15 +229,18 @@ public class OaServiceImpl extends DefaultBaseService implements IOaService { oaProcessLogDTO.setTaskId(historicTaskInstance.getId()); oaProcessLogDTO.setTaskName(historicTaskInstance.getName()); oaProcessLogDTO.setTaskStatus(ProcessTaskStatusEnum.ALREADY_DONE.getValue()); - - Map taskLocalVariables = historicTaskInstance.getTaskLocalVariables(); - Object assigneeUserNameObj = taskLocalVariables.get(IOaFormReportService.KEY_ASSIGNEE_USER_NAME); - oaProcessLogDTO.setUserIds(userIds); - oaProcessLogDTO.setUserNames(assigneeUserNameObj == null ? "" : assigneeUserNameObj.toString()); + oaProcessLogDTO.setUserNames(userIds); oaProcessLogDTO.setStartTime(DateUtil.getDateTime(historicTaskInstance.getCreateTime())); oaProcessLogDTO.setEndTime(DateUtil.getDateTime(historicTaskInstance.getEndTime())); oaProcessLogDTO.setUsedTime(DateUtil.getUsedTime(historicTaskInstance.getDurationInMillis())); + + for (Comment comment : processInstanceComments) { + if (StringUtils.equals(comment.getTaskId(), historicTaskInstance.getId())) { + oaProcessLogDTO.setComment(JSONObject.parseObject(comment.getFullMessage(), TaskCommentBO.class)); + break; + } + } oaProcessLogDTOs.add(oaProcessLogDTO); }); // 待办 @@ -245,25 +253,21 @@ public class OaServiceImpl extends DefaultBaseService implements IOaService { oaProcessLogDTO.setTaskId(task.getId()); oaProcessLogDTO.setTaskName(task.getName()); oaProcessLogDTO.setTaskStatus(ProcessTaskStatusEnum.NEED_TO_BE_DEALT_WITH.getValue()); - - Map taskLocalVariables = task.getTaskLocalVariables(); - Object assigneeUserNameObj = taskLocalVariables.get(IOaFormReportService.KEY_ASSIGNEE_USER_NAME); - String userIdString = WStringUtil.listToStr(userIds, ","); oaProcessLogDTO.setUserIds(userIdString); - oaProcessLogDTO.setUserNames(assigneeUserNameObj == null ? "" : assigneeUserNameObj.toString()); + oaProcessLogDTO.setUserNames(userIdString); oaProcessLogDTO.setStartTime(DateUtil.getDateTime(task.getCreateTime())); oaProcessLogDTOs.add(oaProcessLogDTO); }); // 查询用户 -// List userDTOs = userBaseService.listByUserIds(userIdSet.stream().collect(Collectors.toList())); -// oaProcessLogDTOs.forEach(oaProcessLogDTO -> { -// userDTOs.forEach(userDTO -> { -// if (StringUtils.contains(oaProcessLogDTO.getUserNames(), userDTO.getUserId())) { -// oaProcessLogDTO.setUserNames(oaProcessLogDTO.getUserNames().replaceAll(userDTO.getUserId(), userDTO.getUserName())); -// } -// }); -// }); + List userDTOs = userBaseService.listByUserIds(userIdSet.stream().collect(Collectors.toList())); + oaProcessLogDTOs.forEach(oaProcessLogDTO -> { + userDTOs.forEach(userDTO -> { + if (StringUtils.contains(oaProcessLogDTO.getUserNames(), userDTO.getUserId())) { + oaProcessLogDTO.setUserNames(oaProcessLogDTO.getUserNames().replaceAll(userDTO.getUserId(), userDTO.getUserName())); + } + }); + }); return oaProcessLogDTOs; } diff --git a/module-activiti/src/main/resources/static/editor-app/configuration/properties/oa-node-manage-popup.html b/module-activiti/src/main/resources/static/editor-app/configuration/properties/oa-node-manage-popup.html index 29c03e44..1c3e0850 100644 --- a/module-activiti/src/main/resources/static/editor-app/configuration/properties/oa-node-manage-popup.html +++ b/module-activiti/src/main/resources/static/editor-app/configuration/properties/oa-node-manage-popup.html @@ -323,7 +323,7 @@ 字段类型 可见 可操作 - 编辑历史 + 签批类型 自动填充 @@ -342,9 +342,9 @@ diff --git a/module-form/src/main/java/ink/wgink/module/form/service/design/IFormDesignService.java b/module-form/src/main/java/ink/wgink/module/form/service/design/IFormDesignService.java index a6843b45..950b7092 100644 --- a/module-form/src/main/java/ink/wgink/module/form/service/design/IFormDesignService.java +++ b/module-form/src/main/java/ink/wgink/module/form/service/design/IFormDesignService.java @@ -17,6 +17,7 @@ public interface IFormDesignService { String FIELD_UID = "uid"; String FIELD_UIDS = "uids"; String PROCESS_INSTANCE_ID = "process_instance_id"; + String FIELD_ATTACHMENTS = "attachments"; String FIELD_GMT_CREATE = "gmt_create"; String FIELD_CREATOR = "creator"; String FIELD_GMT_MODIFIED = "gmt_modified"; diff --git a/module-form/src/main/java/ink/wgink/module/form/service/design/impl/FormDesignServiceImpl.java b/module-form/src/main/java/ink/wgink/module/form/service/design/impl/FormDesignServiceImpl.java index 623eaeaa..44177a7b 100644 --- a/module-form/src/main/java/ink/wgink/module/form/service/design/impl/FormDesignServiceImpl.java +++ b/module-form/src/main/java/ink/wgink/module/form/service/design/impl/FormDesignServiceImpl.java @@ -264,8 +264,9 @@ public class FormDesignServiceImpl extends DefaultBaseService implements IFormDe createTableSB.append("`" + IFormDesignService.PROCESS_INSTANCE_ID + "` char(36) DEFAULT NULL,"); createTableSB.append("`" + IFormDesignService.FIELD_MAIN_TITLE + "` varchar(500),"); for (FormFieldVO formFieldVO : formFieldVOs) { - createTableSB.append("`").append(formFieldVO.getFieldName()).append("` ").append(formFieldVO.getFieldType()).append(" NOT NULL COMMENT '").append(formFieldVO.getFieldExplain()).append("',"); + createTableSB.append("`").append(formFieldVO.getFieldName()).append("` ").append(formFieldVO.getFieldType()).append(" DEFAULT NULL COMMENT '").append(formFieldVO.getFieldExplain()).append("',"); } + createTableSB.append("`" + IFormDesignService.FIELD_ATTACHMENTS + "` text DEFAULT NULL,"); createTableSB.append("`" + IFormDesignService.FIELD_CREATOR + "` char(36) DEFAULT NULL,"); createTableSB.append("`" + IFormDesignService.FIELD_GMT_CREATE + "` datetime DEFAULT NULL,"); createTableSB.append("`" + IFormDesignService.FIELD_MODIFIER + "` char(36) DEFAULT NULL,"); diff --git a/module-form/src/main/resources/static/form/js/form-util.js b/module-form/src/main/resources/static/form/js/form-util.js index 9142bfdd..55680f77 100644 --- a/module-form/src/main/resources/static/form/js/form-util.js +++ b/module-form/src/main/resources/static/form/js/form-util.js @@ -830,133 +830,4 @@ function FormUtil(layui, viewer) { }); } - /** - * @callback onConfirm - * @param selectedUsers {Array} [{userId: '', userName: '', userUsername: ''}] - */ - /** - * @description 选择用户列表 - * @param opt {object} - * @param {String} opt.selectType 'radio|checkbox' 必传,2选1 - * @param {onConfirm} opt.onConfirm 确定按钮回调函数,必传 - * @param {Array} opt.users 参与选择的用户列表,必传,格式:[{userId: '', userUsername: '', userName: ''}] - * @param {Array} opt.selectedUserIds 默认选中的用户ID列表,非必传,如果selectType为 radio,默认选中[0]。格式:['userId1', 'userId2'] - */ - this.selectUsers = function (opt) { - var selectType = opt.selectType, - onConfirm = opt.onConfirm, - users = opt.users, - selectedUserIds = opt.selectedUserIds; - if (selectType != 'radio' && selectType != 'checkbox') { - throw 'selectType(arg1): [radio|checkbox]'; - return; - } - if (!users && !(users instanceof Array)) { - onConfirm([]); - } - - selectedUserIds = selectedUserIds && (selectedUserIds instanceof Array) ? selectedUserIds : []; - selectedUserIds = selectType == 'radio' && selectedUserIds.length > 1 ? selectedUserIds[0] : selectedUserIds; - - var selectedUserMap = {}; - var selectedUsers = []; - var itemHtml = ''; - - function addUserToMap(userId, userUsername, userName) { - selectedUserMap[userId] = { - userId: userId, - userUsername: userUsername, - userName: userName, - } - } - - function addClick() { - $('.select-user .list .item').click(function () { - var dataset = this.dataset; - var userId = dataset.userId; - if (selectType === 'radio') { - $('.select-user .list .item').removeClass('active'); - $(this).addClass('active'); - selectedUserMap = {}; - addUserToMap(userId, dataset.userUsername, dataset.userName); - } else { - if (selectedUserMap[userId]) { - delete selectedUserMap[userId]; - $(this).removeClass('active'); - } else { - addUserToMap(userId, dataset.userUsername, dataset.userName); - $(this).addClass('active'); - } - } - }); - $('.select-user .foot .confirm-btn').click(function () { - for (var key in selectedUserMap) { - selectedUsers.push(selectedUserMap[key]); - } - if (selectedUsers.length == 0) { - layer.msg('请选择人员'); - return; - } - layer.close(layIndex); - }); - $('.select-user .foot .close-btn').click(function () { - selectedUsers = null; - layer.close(layIndex); - }); - } - - // 添加用户到map - for (var i = 0, user; user = users[i++];) { - var isActive = false; - for (var j = 0, selectedUserId; selectedUserId = selectedUserIds[j++];) { - if (user.userId === selectedUserId) { - isActive = true; - addUserToMap(user.userId, user.userUsername, user.userName); - break; - } - } - itemHtml += '
'; - itemHtml += '
'; - if (user.avatar) { - itemHtml += ''; - } else { - itemHtml += ''; - } - itemHtml += '
'; - itemHtml += '
'; - itemHtml += '
' + user.userUsername + '
'; - itemHtml += '
' + user.userName + '
'; - itemHtml += '
'; - itemHtml += '
'; - itemHtml += ''; - itemHtml += '
'; - itemHtml += '
'; - } - - var layIndex = layer.open({ - type: 1, - area: ['300px', '400px'], - closeBtn: 0, - title: '选择候选人', - shadeClose: false, - scrollbar: false, - content: '
' + - '
' - + itemHtml + - '
' + - '
' + - '
' + - '' + - '' + - '
' + - '
' + - '
', - end: function () { - onConfirm(selectedUsers); - } - }); - - addClick(); - } - } \ No newline at end of file diff --git a/module-form/src/main/resources/static/form/js/oa-form-util.js b/module-form/src/main/resources/static/form/js/oa-form-util.js index 893d1e29..7c56a175 100644 --- a/module-form/src/main/resources/static/form/js/oa-form-util.js +++ b/module-form/src/main/resources/static/form/js/oa-form-util.js @@ -25,31 +25,41 @@ function OaFormUtil(layui) { formData.field.recordFields = recordFields; } + /** + * 获取会签内容 + * @param signItem + * @return {string} + */ + function getJointlySignText(signItem) { + return + } + /** * 设置签字列表 * @param formData */ this.initSignList = function (formData) { - for (var key in formData) { - if (key.indexOf('_sign_') != 0) { + if(formData.jointlySign) { + return; + } + var jointlySign = formData.jointlySign; + for(var key in formData) { + var jointlySigns = jointlySign[key +'JointlySign']; + if(!jointlySigns) { continue; } - var signPreDomKey = key.substring(6, key.length); - var signList = formData[key]; var signListDom = '
记录'; - for (var i = 0, item; item = signList[i++];) { + for(var i = 0, item; item = jointlySigns[i++];) { signListDom += [ '
', - ' ' + item.userName + ':', - ' ' + item.content + ' - ', - ' ' + item.time + '', + ' 姓名:' + item.userName + '。 ', + ' 内容:' + item.content + '。', + ' 时间:' + item.time + '。', '
' ].join(''); } signListDom += '
'; - $('#' + signPreDomKey + 'Block').append(signListDom); - delete formData[key]; - delete formData[signPreDomKey]; + $('#' + key + 'Block').append(signListDom); } } @@ -58,18 +68,20 @@ function OaFormUtil(layui) { * @param formData */ this.initTextareaSignList = function (formData) { - for (var key in formData) { - if (key.indexOf('_sign_') != 0) { + if(formData.jointlySign) { + return; + } + var jointlySign = formData.jointlySign; + for(var key in formData) { + var jointlySigns = jointlySign[key+'JointlySign']; + if(!jointlySigns) { continue; } - var signPreDomKey = key.substring(6, key.length); - var signList = formData[key]; - var signListText = ''; - for (var i = 0, item; item = signList[i++];) { - signListText += item.userName + ':' + item.content + ' - ' + item.time + '\n'; + var jointlySignListText = ''; + for(var i = 0, item; item = jointlySigns[i++];) { + jointlySignListText += '姓名:'+ item.userName +'。 内容:'+ item.content +'。 时间:'+ item.time +'。\n'; } - formData[signPreDomKey] = signListText; - delete formData[key]; + formData[key] = jointlySignListText; } } @@ -80,21 +92,14 @@ function OaFormUtil(layui) { restAjax.get(restAjax.path('api/oa/list-process-log/process-instance-id/{processInstanceId}', [processInstanceId]), {}, null, function (code, data) { var ul = '
    '; for (var i = 0, item; item = data[i++];) { - // 处理签批内容 - var taskVariables = item.taskVariables; - var signDom = ''; - for (var key in taskVariables) { - if (key.indexOf('RECORD:') != 0) { - continue; + // 批注 + var commentText = ''; + var comment = item.comment; + if(comment) { + if(comment.type === 'JOINTLY_SIGN') { + commentText = '类型:会签。内容:'+ comment.content + '。时间:'+ comment.time; } - var sign = JSON.parse(taskVariables[key]); - signDom += '
    ' + - '【' + key.replace('RECORD:', '') + '】' + - '内容:' + sign.content + '' + - '时间:' + sign.time + '' + - '
    '; } - var li = [ '
  • ', ' ', @@ -127,10 +132,8 @@ function OaFormUtil(layui) { ' ' + item.userNames + '', ' ', ' ', - ' 签批', - ' ', - signDom, - ' ', + ' 批注', + ' '+ commentText +'', ' ', ' ', ' ', @@ -209,6 +212,7 @@ function OaFormUtil(layui) { $(boxId).css('position', 'relative'); $(boxId).append('
    '); var doms = $(boxId).find('input,button,textarea'); + doms.removeAttr('name'); doms.attr('disabled', 'disabled'); doms.attr('lay-verify', ''); } @@ -251,13 +255,13 @@ function OaFormUtil(layui) { var buttons = ''; buttons += '
    ' if (formButton.btnAttachment) { - buttons += ''; + buttons += ''; } buttons += ''; buttons += ''; buttons += '
    '; if (formButton.btnGoBack) { - buttons += ''; + buttons += ''; } $('#formButtonGroup').append(buttons); } @@ -380,4 +384,133 @@ function OaFormUtil(layui) { addClick(); } + /** + * @callback onConfirm + * @param selectedUsers {Array} [{userId: '', userName: '', userUsername: ''}] + */ + /** + * @description 选择用户列表 + * @param opt {object} + * @param {String} opt.selectType 'radio|checkbox' 必传,2选1 + * @param {onConfirm} opt.onConfirm 确定按钮回调函数,必传 + * @param {Array} opt.users 参与选择的用户列表,必传,格式:[{userId: '', userUsername: '', userName: ''}] + * @param {Array} opt.selectedUserIds 默认选中的用户ID列表,非必传,如果selectType为 radio,默认选中[0]。格式:['userId1', 'userId2'] + */ + this.selectUsers = function (opt) { + var selectType = opt.selectType, + onConfirm = opt.onConfirm, + users = opt.users, + selectedUserIds = opt.selectedUserIds; + if (selectType != 'radio' && selectType != 'checkbox') { + throw 'selectType(arg1): [radio|checkbox]'; + return; + } + if (!users && !(users instanceof Array)) { + onConfirm([]); + } + + selectedUserIds = selectedUserIds && (selectedUserIds instanceof Array) ? selectedUserIds : []; + selectedUserIds = selectType == 'radio' && selectedUserIds.length > 1 ? selectedUserIds[0] : selectedUserIds; + + var selectedUserMap = {}; + var selectedUsers = []; + var itemHtml = ''; + + function addUserToMap(userId, userUsername, userName) { + selectedUserMap[userId] = { + userId: userId, + userUsername: userUsername, + userName: userName, + } + } + + function addClick() { + $('.select-user .list .item').click(function () { + var dataset = this.dataset; + var userId = dataset.userId; + if (selectType === 'radio') { + $('.select-user .list .item').removeClass('active'); + $(this).addClass('active'); + selectedUserMap = {}; + addUserToMap(userId, dataset.userUsername, dataset.userName); + } else { + if (selectedUserMap[userId]) { + delete selectedUserMap[userId]; + $(this).removeClass('active'); + } else { + addUserToMap(userId, dataset.userUsername, dataset.userName); + $(this).addClass('active'); + } + } + }); + $('.select-user .foot .confirm-btn').click(function () { + for (var key in selectedUserMap) { + selectedUsers.push(selectedUserMap[key]); + } + if (selectedUsers.length == 0) { + layer.msg('请选择人员'); + return; + } + layer.close(layIndex); + }); + $('.select-user .foot .close-btn').click(function () { + selectedUsers = null; + layer.close(layIndex); + }); + } + + // 添加用户到map + for (var i = 0, user; user = users[i++];) { + var isActive = false; + for (var j = 0, selectedUserId; selectedUserId = selectedUserIds[j++];) { + if (user.userId === selectedUserId) { + isActive = true; + addUserToMap(user.userId, user.userUsername, user.userName); + break; + } + } + itemHtml += '
    '; + itemHtml += '
    '; + if (user.avatar) { + itemHtml += ''; + } else { + itemHtml += ''; + } + itemHtml += '
    '; + itemHtml += '
    '; + itemHtml += '
    ' + user.userUsername + '
    '; + itemHtml += '
    ' + user.userName + '
    '; + itemHtml += '
    '; + itemHtml += '
    '; + itemHtml += ''; + itemHtml += '
    '; + itemHtml += '
    '; + } + + var layIndex = layer.open({ + type: 1, + area: ['300px', '400px'], + closeBtn: 0, + title: '选择候选人', + shadeClose: false, + scrollbar: false, + content: '
    ' + + '
    ' + + itemHtml + + '
    ' + + '
    ' + + '
    ' + + '' + + '' + + '
    ' + + '
    ' + + '
    ', + end: function () { + onConfirm(selectedUsers); + } + }); + + addClick(); + } + } \ No newline at end of file