1、系统登录获取用户信息新增获取岗位信息

2、工作流待办任务分页展示实现
3、待办任务审批功能实现
4、工作流页面样式优化
5、工作流接口权限检验
pull/254/head
xjs 3 years ago
parent 0ffa1863c6
commit 978d67737c

@ -17,7 +17,7 @@
type="text"
icon="el-icon-edit"
@click="examineAndApprove (scope.row)"
v-hasPermi="['workflow:leave:edit']"
v-hasPermi="['activiti:task:query']"
>审批
</el-button>
</template>
@ -34,7 +34,7 @@
<!-- 审批对话框 -->
<el-dialog :title="title" :visible.sync="open" v-if="open" width="500px" append-to-body>
<leaveHistoryForm :businessKey="businessKey" v-if="'leave'==definitionKey"/>
<leaveHistoryForm :businessKey="businessKey" v-if="'leave'===definitionKey"/>
<el-form :model="form" ref="form" label-width="100px" class="demo-dynamic">
<el-form-item
@ -42,7 +42,7 @@
:label="domain.controlLable"
:key="index"
>
<el-radio-group v-model="domain.controlValue" v-if="'radio'==domain.controlType">
<el-radio-group v-model="domain.controlValue" v-if="'radio'===domain.controlType">
<el-radio v-for="(defaults,indexd) in domain.controlDefault.split('--__--')"
:label=indexd
:key="indexd"
@ -51,13 +51,13 @@
</el-radio>
</el-radio-group>
<el-input type="textarea" v-model="domain.controlValue" v-if="'textarea'==domain.controlType"
<el-input maxlength="1010" type="textarea" v-model="domain.controlValue" v-if="'textarea'===domain.controlType"
></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button type="primary" @click="submitForm" v-hasPermi="['activiti:task:save']"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>

@ -6,6 +6,7 @@
v-model="queryParams.title"
placeholder="请输入标题"
clearable
maxlength="10"
size="small"
@keyup.enter.native="handleQuery"
/>
@ -353,6 +354,7 @@ export default {
this.reset()
getLeave(row.id).then(response => {
this.form = response.data
this.form.betDateTime =[response.data.leaveStartTime,response.data.leaveEndTime]
this.open = true
this.title = '修改请假'
})

@ -21,19 +21,27 @@
<el-form-item label="结束时间">
<at-alert show-icon :message="form.leaveEndTime" type="info"></at-alert>
</el-form-item>
<div v-for="(historyData, index) in fromData"
:key="index">
<el-form-item label="">
<at-alert show-icon :message="historyData.taskNodeName" type="warning"></at-alert>
</el-form-item>
<el-form-item label="审批人">
<at-alert show-icon :message="historyData.createName" type="info"></at-alert>
</el-form-item>
<el-form-item label="审批时间">
<at-alert show-icon :message="historyData.createdDate" type="info"></at-alert>
</el-form-item>
<el-form v-for="(fistoryFormData, indexH) in historyData.formHistoryDataDTO" :key="indexH" label-width="80px">
<el-form-item :label=fistoryFormData.title>
<el-input type="textarea" :rows="1" disabled v-model="fistoryFormData.value"/>
</el-form-item>
</el-form>
</div>
</el-form>
</div>
<div v-for="(historyData, index) in fromData"
:key="index">
<h2>{{ historyData.taskNodeName }}</h2>
<h3>审批人:{{ historyData.createName }}</h3>
<h3>审批时间:{{ historyData.createdDate }}</h3>
<el-form v-for="(fistoryFormData, indexH) in historyData.formHistoryDataDTO" :key="indexH" label-width="80px">
<el-form-item :label=fistoryFormData.title>
<el-input v-model="fistoryFormData.value"/>
</el-form-item>
</el-form>
</div>
</div>
</template>

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.kafeitu.me/activiti/leave">
<process id="leave" name="请假流程-普通表单" isExecutable="true">
<documentation>请假流程演示</documentation>
<startEvent id="startevent1" name="Start" />
<userTask id="deptLeaderVerify" name="部门领导审批" activiti:formKey="deptLeaderVerify" activiti:candidateUsers="${deptLeader}">
<extensionElements>
<activiti:formProperty id="FormProperty_3qipis2--__!!radio--__!!审批意见--__!!i--__!!同意--__--不同意" type="string" />
<activiti:formProperty id="FormProperty_0lffpcm--__!!textarea--__!!批注--__!!f__!!null" type="string" />
</extensionElements>
</userTask>
<exclusiveGateway id="exclusivegateway5">
<outgoing>Flow_0q3bbjl</outgoing>
</exclusiveGateway>
<userTask id="hrVerify" name="人事审批" activiti:formKey="hrVerify" activiti:candidateGroups="hr">
<extensionElements>
<activiti:formProperty id="FormProperty_23u95jb--__!!radio--__!!审批意见--__!!i--__!!同意--__--不同意" type="string" />
<activiti:formProperty id="FormProperty_3t7tfkv--__!!textarea--__!!批注--__!!f--__!!null" type="string" />
</extensionElements>
</userTask>
<exclusiveGateway id="exclusivegateway6">
<outgoing>Flow_0p85954</outgoing>
<outgoing>Flow_0ji7qcv</outgoing>
</exclusiveGateway>
<endEvent id="endevent1" name="End">
<incoming>Flow_0p85954</incoming>
<incoming>Flow_0ji7qcv</incoming>
<incoming>Flow_0q3bbjl</incoming>
</endEvent>
<sequenceFlow id="flow2" sourceRef="startevent1" targetRef="deptLeaderVerify" />
<sequenceFlow id="flow3" sourceRef="deptLeaderVerify" targetRef="exclusivegateway5" />
<sequenceFlow id="flow5" name="同意" sourceRef="exclusivegateway5" targetRef="hrVerify">
<conditionExpression xsi:type="tFormalExpression">${FormProperty_3qipis2==0}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow6" sourceRef="hrVerify" targetRef="exclusivegateway6" />
<sequenceFlow id="Flow_0p85954" sourceRef="exclusivegateway6" targetRef="endevent1">
<extensionElements>
<activiti:executionListener class="com.xjs.workflow.leave.instener.LeaveEndStateListener" event="take">
<activiti:field name="state">
<activiti:string>1</activiti:string>
</activiti:field>
</activiti:executionListener>
</extensionElements>
<conditionExpression xsi:type="tFormalExpression">${FormProperty_23u95jb==0}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="Flow_0ji7qcv" sourceRef="exclusivegateway6" targetRef="endevent1">
<extensionElements>
<activiti:executionListener class="com.xjs.workflow.leave.instener.LeaveEndStateListener" event="take">
<activiti:field name="state">
<activiti:string>2</activiti:string>
</activiti:field>
</activiti:executionListener>
</extensionElements>
</sequenceFlow>
<sequenceFlow id="Flow_0q3bbjl" sourceRef="exclusivegateway5" targetRef="endevent1">
<extensionElements>
<activiti:executionListener class="com.xjs.workflow.leave.instener.LeaveEndStateListener" event="take">
<activiti:field name="state">
<activiti:string>2</activiti:string>
</activiti:field>
</activiti:executionListener>
</extensionElements>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_leave">
<bpmndi:BPMNPlane id="BPMNPlane_leave" bpmnElement="leave">
<bpmndi:BPMNEdge id="Flow_0q3bbjl_di" bpmnElement="Flow_0q3bbjl">
<omgdi:waypoint x="260" y="83" />
<omgdi:waypoint x="260" y="320" />
<omgdi:waypoint x="600" y="320" />
<omgdi:waypoint x="600" y="157" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ji7qcv_di" bpmnElement="Flow_0ji7qcv">
<omgdi:waypoint x="505" y="83" />
<omgdi:waypoint x="505" y="140" />
<omgdi:waypoint x="582" y="140" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0p85954_di" bpmnElement="Flow_0p85954">
<omgdi:waypoint x="525" y="63" />
<omgdi:waypoint x="600" y="63" />
<omgdi:waypoint x="600" y="122" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_flow6" bpmnElement="flow6">
<omgdi:waypoint x="453" y="63" />
<omgdi:waypoint x="485" y="63" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_flow5" bpmnElement="flow5">
<omgdi:waypoint x="280" y="63" />
<omgdi:waypoint x="348" y="63" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="300" y="46" width="22" height="11" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_flow3" bpmnElement="flow3">
<omgdi:waypoint x="185" y="63" />
<omgdi:waypoint x="240" y="63" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_flow2" bpmnElement="flow2">
<omgdi:waypoint x="35" y="63" />
<omgdi:waypoint x="80" y="63" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="BPMNShape_startevent1" bpmnElement="startevent1">
<omgdc:Bounds x="0" y="46" width="35" height="35" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="5" y="81" width="25" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_deptLeaderVerify" bpmnElement="deptLeaderVerify">
<omgdc:Bounds x="80" y="36" width="105" height="55" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_exclusivegateway5" bpmnElement="exclusivegateway5" isMarkerVisible="true">
<omgdc:Bounds x="240" y="43" width="40" height="40" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_hrVerify" bpmnElement="hrVerify">
<omgdc:Bounds x="348" y="36" width="105" height="55" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_exclusivegateway6" bpmnElement="exclusivegateway6" isMarkerVisible="true">
<omgdc:Bounds x="485" y="43" width="40" height="40" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_endevent1" bpmnElement="endevent1">
<omgdc:Bounds x="582" y="122" width="35" height="35" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="627" y="133" width="20" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

@ -13,6 +13,7 @@ import com.xjs.activiti.domain.dto.ActWorkflowFormDataDTO;
import com.xjs.activiti.service.IActTaskService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import java.text.ParseException;
@ -36,13 +37,12 @@ public class TaskController extends BaseController {
PageDomain pageDomain = TableSupport.buildPageRequest();
Page<ActTaskDTO> hashMaps = actTaskService.selectProcessDefinitionList(pageDomain);
return getDataTable(hashMaps);
}
//渲染表单
@GetMapping(value = "/formDataShow/{taskID}")
@RequiresPermissions("activiti:task:query")
public AjaxResult formDataShow(@PathVariable("taskID") String taskID) {
return AjaxResult.success(actTaskService.formDataShow(taskID));
@ -50,8 +50,16 @@ public class TaskController extends BaseController {
//保存表单
@PostMapping(value = "/formDataSave/{taskID}")
@RequiresPermissions("activiti:task:save")
public AjaxResult formDataSave(@PathVariable("taskID") String taskID,
@RequestBody List<ActWorkflowFormDataDTO> formData) throws ParseException {
for (ActWorkflowFormDataDTO formDatum : formData) {
Assert.notNull(formDatum.getControlValue(),"参数不能为空");
if (formDatum.getControlValue().length() > 100) {
throw new IllegalArgumentException("长度超出 100 限制");
}
}
return toAjax(actTaskService.formDataSave(taskID, formData));
}

@ -18,6 +18,8 @@ public class ActTaskDTO extends BaseEntity {
private String id;
private String processInstanceId;
private String name;
private String status;
@ -28,11 +30,17 @@ public class ActTaskDTO extends BaseEntity {
private String definitionKey;
private String businessKey;
/**
*
*/
private String assignee;
public ActTaskDTO() {
}
public ActTaskDTO(Task task, ProcessInstance processInstance) {
this.id = task.getId();
this.processInstanceId = task.getProcessInstanceId();
this.name = task.getName();
this.status = task.getStatus().toString();
this.createdDate = task.getCreatedDate();
@ -41,6 +49,22 @@ public class ActTaskDTO extends BaseEntity {
this.businessKey = processInstance.getBusinessKey();
}
public String getProcessInstanceId() {
return processInstanceId;
}
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public String getAssignee() {
return assignee;
}
public void setAssignee(String assignee) {
this.assignee = assignee;
}
public String getId() {
return id;
}

@ -2,6 +2,7 @@
package com.xjs.activiti.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.Page;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.security.utils.SecurityUtils;
@ -12,14 +13,15 @@ import com.xjs.activiti.service.IActTaskService;
import com.xjs.activiti.service.IActWorkflowFormDataService;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.BaseElement;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.TaskQuery;
import org.activiti.runtime.api.model.impl.APITaskConverter;
@ -28,7 +30,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
@ -52,9 +57,10 @@ public class ActTaskServiceImpl implements IActTaskService {
private RuntimeService runtimeService;
@Autowired
private IActWorkflowFormDataService actWorkflowFormDataService;
@Autowired
private APITaskConverter taskConverter;
@Autowired
private HistoryService historyService;
@Override
@ -72,7 +78,26 @@ public class ActTaskServiceImpl implements IActTaskService {
if (totalItems != 0) {
Set<String> processInstanceIdIds = tasks.parallelStream().map(Task::getProcessInstanceId).collect(Collectors.toSet());
List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIdIds).list();
List<ActTaskDTO> actTaskDTOS = tasks.stream().map(t -> new ActTaskDTO(t, processInstanceList.parallelStream().filter(pi -> t.getProcessInstanceId().equals(pi.getId())).findAny().get())).collect(Collectors.toList());
List<ActTaskDTO> actTaskDTOS = tasks.stream()
.map(t -> {
ActTaskDTO actTaskDTO = new ActTaskDTO(t, processInstanceList.parallelStream()
.filter(pi ->
t.getProcessInstanceId().equals(pi.getId())).findAny().get());
//根据开始时间获取历史任务中的办理人
List<HistoricTaskInstance> instanceList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(actTaskDTO.getProcessInstanceId())
.orderByHistoricTaskInstanceStartTime()
.asc()
.list();
if (CollUtil.isNotEmpty(instanceList)) {
actTaskDTO.setAssignee(instanceList.get(0).getAssignee());
}
return actTaskDTO;
})
.collect(Collectors.toList());
list.addAll(actTaskDTOS);
}
return list;
@ -117,7 +142,6 @@ public class ActTaskServiceImpl implements IActTaskService {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
boolean hasVariables = false;//没有任何参数
HashMap<String, Object> variables = new HashMap<String, Object>();
//前端传来的字符串,拆分成每个控件
List<ActWorkflowFormData> acwfds = new ArrayList<>();
@ -127,19 +151,21 @@ public class ActTaskServiceImpl implements IActTaskService {
//构建参数集合
if (!"f".equals(awf.getControlIsParam())) {
variables.put(awf.getControlId(), awf.getControlValue());
hasVariables = true;
}
}//for结束
if (task.getAssignee() == null) {
taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
}
if (hasVariables) {
//带参数完成任务
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID).withVariables(variables).build());
} else {
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID).build());
//taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
String username = SecurityUtils.getUsername();
taskService.claim(task.getId(), username);
}
//带参数完成任务
//taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID).withVariables(variables).build());
taskService.complete(task.getId(), variables, true);
//taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID).build());
//写入数据库
return actWorkflowFormDataService.insertActWorkflowFormDatas(acwfds);

@ -84,6 +84,7 @@ public class ProcessDefinitionServiceImpl implements IProcessDefinitionService {
@Override
public int deleteProcessDefinitionById(String id) {
try {
//true级联删除 false有关联则抛异常
repositoryService.deleteDeployment(id, true);
} catch (Exception e) {
throw new ActivitiException("该流程已使用!无法删除!如需删除,请先删除相关任务!");

@ -9,11 +9,15 @@ import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.xjs.validation.group.AddGroup;
import com.xjs.validation.group.SelectGroup;
import com.xjs.validation.group.UpdateGroup;
import com.xjs.workflow.leave.domain.WorkflowLeave;
import com.xjs.workflow.leave.service.IWorkflowLeaveService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
@ -38,7 +42,7 @@ public class WorkflowLeaveController extends BaseController {
@GetMapping("/list")
@RequiresPermissions("workflow:leave:list")
@ApiOperation("查询请假列表")
public TableDataInfo list(WorkflowLeave workflowLeave) {
public TableDataInfo list(@Validated(SelectGroup.class) WorkflowLeave workflowLeave) {
startPage();
workflowLeave.setCreateBy(SecurityUtils.getUsername());
List<WorkflowLeave> list = workflowLeaveService.selectWorkflowLeaveAndTaskNameList(workflowLeave);
@ -98,7 +102,7 @@ public class WorkflowLeaveController extends BaseController {
@Log(title = "请假", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation("新增请假")
public AjaxResult add(@RequestBody WorkflowLeave workflowLeave) {
public AjaxResult add(@Validated(AddGroup.class)@RequestBody WorkflowLeave workflowLeave) {
return toAjax(workflowLeaveService.insertWorkflowLeave(workflowLeave));
}
@ -109,7 +113,7 @@ public class WorkflowLeaveController extends BaseController {
@ApiOperation("修改请假")
@PutMapping
@RequiresPermissions("workflow:leave:edit")
public AjaxResult edit(@RequestBody WorkflowLeave workflowLeave) {
public AjaxResult edit(@Validated(UpdateGroup.class)@RequestBody WorkflowLeave workflowLeave) {
return toAjax(workflowLeaveService.insertWorkflowLeave(workflowLeave));
}

@ -2,9 +2,14 @@ package com.xjs.workflow.leave.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import com.xjs.validation.group.AddGroup;
import com.xjs.validation.group.SelectGroup;
import com.xjs.validation.group.UpdateGroup;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.Date;
/**
@ -25,18 +30,24 @@ public class WorkflowLeave extends BaseEntity {
*
*/
@Excel(name = "请假类型")
@NotBlank(message = "请假类型不能为空",groups = {AddGroup.class, UpdateGroup.class})
@Size(min = 1, max = 5, message = "请假类型长度不能超过 10 个字符", groups = {SelectGroup.class, AddGroup.class, UpdateGroup.class})
private String type;
/**
*
*/
@Excel(name = "标题")
@NotBlank(message = "请假标题不能为空",groups = {AddGroup.class, UpdateGroup.class})
@Size(min = 1, max = 100, message = "请假标题长度不能超过 10 个字符", groups = {SelectGroup.class, AddGroup.class, UpdateGroup.class})
private String title;
/**
*
*/
@Excel(name = "原因")
@NotBlank(message = "请假原因不能为空",groups = {AddGroup.class, UpdateGroup.class})
@Size(min = 1, max = 500, message = "请假原因长度不能超过 500 个字符", groups = {AddGroup.class, UpdateGroup.class})
private String reason;
/**
@ -58,7 +69,8 @@ public class WorkflowLeave extends BaseEntity {
/**
*
*/
@Excel(name = "状态",readConverterExp = "0=进行中,1=成功,2=失败")
@Excel(name = "状态", readConverterExp = "0=进行中,1=成功,2=失败")
@Size(min = 1, max = 1, message = "请假状态长度不能超过 1 个字符", groups = {SelectGroup.class})
private String state;
/**

Loading…
Cancel
Save