增加回退功能代码

This commit is contained in:
wanggeng 2022-04-29 21:01:52 +08:00
parent 11c9779f8a
commit d592a2b592
17 changed files with 643 additions and 310 deletions

View File

@ -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<String, Object> params) {
oaFormReportService.updateGoBack(processInstanceId, taskId, nodeId, params);
return new SuccessResult();
}
@GetMapping("get/code/{formCode}/version/{formVersion}/uid/{uid}")
public Map<String, Object> get(@PathVariable("formCode") String formCode, @PathVariable("formVersion") Integer formVersion, @PathVariable("uid") String uid) {
return oaFormReportService.get(formCode, formVersion, uid);

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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<String, Object> taskVariables;
private Map<String, Object> 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();
}

View File

@ -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<GoBackUserTaskVO> 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;
}

View File

@ -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;
}
}

View File

@ -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<UserTask> listNextUserTasksByUserTask(UserTask userTask);
/**
* 获取之前的用户任务列表
*
* @param userTask
* @return
*/
List<UserTask> listBeforeUserTaskByUserTask(UserTask userTask);
/**
* 获取第一个用户任务
*

View File

@ -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<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
List<UserTask> 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<UserTask> listBeforeUserTaskByUserTask(UserTask userTask) {
List<SequenceFlow> incomingFlows = userTask.getIncomingFlows();
List<UserTask> beforeUserTasks = new ArrayList<>();
setBeforeUserTasks(userTask, incomingFlows, beforeUserTasks);
return beforeUserTasks;
}
@Override
public UserTask getFirstUserTaskByProcessDefinitionId(String processDefinitionId) {
List<FlowNode> listFlowNode = listFlowNodeByProcessDefinitionId(processDefinitionId);
@ -223,7 +241,7 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct
@Override
public UserTask getNextUserTask(String currentTaskDefinitionKey, String processDefinitionId, Map<String, Object> reportForm) {
FlowNode currentFlowNode = getFlowNodeByTaskDefinitionKeyAndProcessDefinitionId(currentTaskDefinitionKey, processDefinitionId);
FlowNode currentFlowNode = getFlowNodeByNodeIdAndProcessDefinitionId(currentTaskDefinitionKey, processDefinitionId);
List<SequenceFlow> 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<SequenceFlow> incomingFlows, List<UserTask> 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
}
}
/**
* 获取运行流程图输入流
*

View File

@ -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<String, Object> params);
/**
* 更新回退
*
* @param processInstanceId
* @param currentTaskId
* @param jumpNodeId
* @param params
*/
void updateGoBack(String processInstanceId, String currentTaskId, String jumpNodeId, Map<String, Object> params);
/**
* 表单详情
*

View File

@ -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<String, Object> 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<String, Object> model) {
private void setPageFormButtonsAndHistoryUserTasks(String deploymentId, String currentTaskId, String processInstanceId, UserTask userTask, Map<String, Object> 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<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
.includeTaskLocalVariables()
.taskId(currentTaskId)
.processInstanceId(processInstanceId)
.finished()
.orderByHistoricTaskInstanceEndTime()
.asc()
.list();
List<GoBackUserTaskVO> goBackUserTaskVOs = historicTaskInstances.stream().map(historicTaskInstance -> {
String assigneeUserId = historicTaskInstance.getAssignee();
Map<String, Object> 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<UserTask> beforeUserTasks = activitiModelService.listBeforeUserTaskByUserTask(userTask);
// 去除历史流程中没有走的节点任务
List<GoBackUserTaskVO> 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<ConfirmAssigneeVO> confirmAssigneeVOs = new CopyOnWriteArrayList<>();
List<ConfirmAssigneeVO> confirmAssigneeVOs = new ArrayList<>();
for (int i = 0; i < sequenceFlows.size(); i++) {
SequenceFlow sequenceFlow = sequenceFlows.get(i);
String name = sequenceFlow.getName();

View File

@ -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<String, Object> 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<String, Object> 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<String, Object> 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<HistoricTaskInstance> 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<SequenceFlow> oldOutgoingFlows = new ArrayList<>();
oldOutgoingFlows.addAll(currentUserTask.getOutgoingFlows());
LOG.debug("4. 创建新连线");
currentUserTask.getOutgoingFlows().clear();
List<SequenceFlow> 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<String> 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<String> 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<OaFormReportRecordFieldVO> oaFormReportRecordFieldVOs, String userId, String userName, Map<String, Object> reportParams) {
private void setRecordFields(String processInstanceId, String taskId, List<OaFormReportRecordFieldVO> oaFormReportRecordFieldVOs, String userId, String userName, Map<String, Object> reportParams) {
if (oaFormReportRecordFieldVOs.isEmpty()) {
return;
}
String currentTime = DateUtil.getTime();
Map<String, Object> 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<String, Object> detail = formReportService.get(formCode, formVersion, uid);
// 查询会签列表
String processInstanceId = detail.get("process_instance_id").toString();
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).includeProcessVariables().singleResult();
Map<String, Object> processVariablesMap = historicProcessInstance.getProcessVariables();
for (Map.Entry<String, Object> 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<String, Object> processVariables = historicProcessInstance.getProcessVariables();
for (Map.Entry<String, Object> detailKV : detail.entrySet()) {
Object signObject = processVariables.get(detailKV.getKey() + EDIT_SIGN_KEY_SUFFIX);
if (signObject != null) {
detail.put(detailKV.getKey(), signObject);
}
}
List<Comment> 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<Comment> jointlySignComments = taskService.getProcessInstanceComments(processInstanceId, TaskCommentTypeEnum.JOINTLY_SIGN.getValue());
Map<String, List<TaskCommentBO>> 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<TaskCommentBO> taskCommentBOs = jointlySignMap.get(mapKey);
if (taskCommentBOs == null) {
taskCommentBOs = new ArrayList<>();
}
taskCommentBOs.add(taskCommentBO);
jointlySignMap.put(mapKey, taskCommentBOs);
}
detail.put("jointlySign", jointlySignMap);
return detail;
}

View File

@ -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<OaProcessLogDTO> listProcessLog(String processInstanceId) {
List<OaProcessLogDTO> oaProcessLogDTOs = new ArrayList<>();
Set<String> userIdSet = new HashSet<>();
// 批注列表
List<Comment> processInstanceComments = taskService.getProcessInstanceComments(processInstanceId);
// 已办
List<HistoricTaskInstance> 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<String, Object> 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<String, Object> 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<UserDTO> 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<UserDTO> 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;
}

View File

@ -323,7 +323,7 @@
<th>字段类型</th>
<th class="text-center">可见</th>
<th class="text-center">可操作</th>
<th class="text-center">编辑历史</th>
<th class="text-center">签批类型</th>
<th class="text-center">自动填充</th>
</tr>
</thead>
@ -342,9 +342,9 @@
</td>
<td class="text-center">
<select class="form-control input-sm" ng-model="formField.editHistory" >
<option value="noRecord">不记录</option>
<option value="latest" ng-if="formField.fieldTag == 'input' || formField.fieldTag == 'textarea'">最新</option>
<option value="all" ng-if="formField.fieldTag == 'textarea'">全部</option>
<option value="noRecord"></option>
<option value="latest" ng-if="formField.fieldTag == 'input' || formField.fieldTag == 'textarea'">签批</option>
<option value="all" ng-if="formField.fieldTag == 'textarea'">会签</option>
</select>
</td>
<td>

View File

@ -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";

View File

@ -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,");

View File

@ -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 += '<div class="item' + (isActive ? ' active' : '') + '" data-user-id="' + user.userId + '" data-user-username="' + user.userUsername + '" data-user-name="' + user.userName + '">';
itemHtml += '<div class="avatar">';
if (user.avatar) {
itemHtml += '<img src="route/file/download/true/' + user.avatar + '"/>';
} else {
itemHtml += '<img src="assets/images/profile-photo.jpg"/>';
}
itemHtml += '</div>';
itemHtml += '<div class="info">';
itemHtml += '<div class="text">' + user.userUsername + '</div>';
itemHtml += '<div class="text">' + user.userName + '</div>';
itemHtml += '</div>';
itemHtml += '<div class="checkbox">';
itemHtml += '<i class="fa fa-check-square-o"></i>';
itemHtml += '</div>';
itemHtml += '</div>';
}
var layIndex = layer.open({
type: 1,
area: ['300px', '400px'],
closeBtn: 0,
title: '选择候选人',
shadeClose: false,
scrollbar: false,
content: '<div class="select-user">' +
'<div class="list">'
+ itemHtml +
'</div>' +
'<div class="foot">' +
'<div class="layui-btn-group">' +
'<button type="button" class="layui-btn layui-btn-sm confirm-btn">确定</button>' +
'<button type="button" class="layui-btn layui-btn-sm layui-btn-primary close-btn">关闭</button>' +
'</div>' +
'</div>' +
'</div>',
end: function () {
onConfirm(selectedUsers);
}
});
addClick();
}
}

View File

@ -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 = '<div><span>记录</span>';
for (var i = 0, item; item = signList[i++];) {
for(var i = 0, item; item = jointlySigns[i++];) {
signListDom += [
'<div>',
' <span>' + item.userName + '</span>',
' <span>' + item.content + ' - </span>',
' <span>' + item.time + '</span>',
' <span>姓名:' + item.userName + '</span>',
' <span>内容:' + item.content + '</span>',
' <span>时间:' + item.time + '</span>',
'</div>'
].join('');
}
signListDom += '</div>';
$('#' + 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 = '<ul class="layui-timeline">';
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 += '<div class="log-sign-box">' +
'<span class="log-sign title" style="font-weight: bold;">【' + key.replace('RECORD:', '') + '】</span>' +
'<span class="log-sign content">内容:' + sign.content + '</span>' +
'<span class="log-sign time">时间:' + sign.time + '</span>' +
'</div>';
}
var li = [
'<li class="layui-timeline-item">',
' <i class="layui-icon layui-timeline-axis">&#xe63f;</i>',
@ -127,10 +132,8 @@ function OaFormUtil(layui) {
' <td>' + item.userNames + '</td>',
' </tr>',
' <tr>',
' <td class="row-title">签批</td>',
' <td>',
signDom,
' </td>',
' <td class="row-title">批注</td>',
' <td>'+ commentText +'</td>',
' </tr>',
' </tbody>',
' </table>',
@ -209,6 +212,7 @@ function OaFormUtil(layui) {
$(boxId).css('position', 'relative');
$(boxId).append('<div style="width: 100%; height: 100%; background-color: #fff0; position: absolute; top: 0; left: 0; cursor: not-allowed;"></div>');
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 += '<div class="layui-btn-group">'
if (formButton.btnAttachment) {
buttons += '<button id="attachmentBtn" type="button" class="layui-btn layui-btn-sm layui-btn-default">上传附件</button>';
buttons += '<button id="attachmentBtn" type="button" class="layui-btn layui-btn-sm layui-btn-default confirm-btn">上传附件</button>';
}
buttons += '<button id="showAttachmentBtn" type="button" class="layui-btn layui-btn-sm layui-btn-primary" title="附件列表"><i class="fa fa-list-ul" aria-hidden="true"></i></button>';
buttons += '<input type="hidden" name="attachments" id="attachments"/>';
buttons += '</div>';
if (formButton.btnGoBack) {
buttons += '<button id="goBackBtn" type="button" class="layui-btn layui-btn-sm layui-btn-danger">回退</button>';
buttons += '<button id="goBackBtn" type="button" class="layui-btn layui-btn-sm layui-btn-danger confirm-btn">回退</button>';
}
$('#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 += '<div class="item' + (isActive ? ' active' : '') + '" data-user-id="' + user.userId + '" data-user-username="' + user.userUsername + '" data-user-name="' + user.userName + '">';
itemHtml += '<div class="avatar">';
if (user.avatar) {
itemHtml += '<img src="route/file/download/true/' + user.avatar + '"/>';
} else {
itemHtml += '<img src="assets/images/profile-photo.jpg"/>';
}
itemHtml += '</div>';
itemHtml += '<div class="info">';
itemHtml += '<div class="text">' + user.userUsername + '</div>';
itemHtml += '<div class="text">' + user.userName + '</div>';
itemHtml += '</div>';
itemHtml += '<div class="checkbox">';
itemHtml += '<i class="fa fa-check-square-o"></i>';
itemHtml += '</div>';
itemHtml += '</div>';
}
var layIndex = layer.open({
type: 1,
area: ['300px', '400px'],
closeBtn: 0,
title: '选择候选人',
shadeClose: false,
scrollbar: false,
content: '<div class="select-user">' +
'<div class="list">'
+ itemHtml +
'</div>' +
'<div class="foot">' +
'<div class="layui-btn-group">' +
'<button type="button" class="layui-btn layui-btn-sm confirm-btn">确定</button>' +
'<button type="button" class="layui-btn layui-btn-sm layui-btn-primary close-btn">关闭</button>' +
'</div>' +
'</div>' +
'</div>',
end: function () {
onConfirm(selectedUsers);
}
});
addClick();
}
}