流程和表单结合

This commit is contained in:
jinqiming 2021-12-06 19:01:51 +08:00
parent 86d5de4a51
commit e02ab9e343
18 changed files with 364 additions and 12 deletions

View File

@ -42,6 +42,10 @@ public class SequenceConstants {
*/
public static final String OA_TASK_SEQUENCE="OA_RW";
/**
* 表单
*/
public static final String OA_FORM_SEQUENCE="BD";
/**
* 工号前缀

View File

@ -0,0 +1,30 @@
package com.snow.common.core.domain;
import lombok.Data;
import org.springframework.context.ApplicationEvent;
import java.io.Serializable;
/**
* @author qimingjin
* @Title: 流程监听
* @Description:
* @date 2021/12/6 15:42
*/
@Data
public class ProcessEventRequest extends ApplicationEvent implements Serializable {
private static final long serialVersionUID = 4565185183548903691L;
/**
* 业务参数
*/
private String businessKey;
/** 流程状态 */
private String processStatus;
public ProcessEventRequest(Object source) {
super(source);
}
}

View File

@ -42,9 +42,15 @@ public class FlowConstants {
*/
public static final String START_USER_ID="startUserId";
/**
* 表单数据
*/
public static final String FORM_DATA="formData";
/**
* 流程类型
*/
public static final String PROCESS_TYPE="oaProcessType";
/** 动态流程图颜色定义 **/
public static final Color COLOR_NORMAL = new Color(0, 205, 0);
public static final Color COLOR_CURRENT = new Color(255, 0, 0);

View File

@ -0,0 +1,44 @@
package com.snow.flowable.common.enums;
/**
* @author qimingjin
* @Title: 流程类型
* @Description:
* @date 2021/12/6 15:18
*/
public enum FlowTypeEnum {
API_PROCESS("API_PROCESS", "api流程"),
FORM_PROCESS("FORM_PROCESS", "表单流程"),
;
private final String code;
private final String info;
FlowTypeEnum(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
public static FlowTypeEnum getByCode(String code) {
for (FlowTypeEnum value : FlowTypeEnum.values()) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}
}

View File

@ -1,5 +1,6 @@
package com.snow.flowable.domain;
import com.snow.flowable.common.enums.FlowTypeEnum;
import lombok.Data;
import java.io.Serializable;
@ -16,11 +17,24 @@ public class StartProcessDTO implements Serializable {
private static final long serialVersionUID = -7725494125601536828L;
/**
* 流程发起人id
*/
private String startUserId;
/**
* 流程定于key
*/
private String processDefinitionKey;
/**
* 业务参数
*/
private String businessKey;
/**
* 自定义参数
*/
private Map<String, Object> variables;
}

View File

@ -23,9 +23,13 @@ public class GlobalListenerConfig implements ApplicationListener<ContextRefreshe
private final ProcessEndListener processEndListener;
private final ProcessStartListener processStartListener;
@Override
public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
FlowableEventDispatcher dispatcher = configuration.getEventDispatcher();
//流程开始
dispatcher.addEventListener(taskCreateListener, FlowableEngineEventType.PROCESS_STARTED);
// 流程结束事件
dispatcher.addEventListener(processEndListener, FlowableEngineEventType.PROCESS_COMPLETED);
//任务创建

View File

@ -1,13 +1,18 @@
package com.snow.flowable.listener.common;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormater;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.snow.common.constant.MessageConstants;
import com.snow.common.core.domain.ProcessEventRequest;
import com.snow.common.enums.MessageEventType;
import com.snow.common.enums.ProcessStatus;
import com.snow.flowable.common.constants.FlowConstants;
import com.snow.flowable.common.enums.FlowDefEnum;
import com.snow.flowable.common.enums.FlowTypeEnum;
import com.snow.flowable.service.FlowableService;
import com.snow.common.core.domain.MessageEventDTO;
import lombok.RequiredArgsConstructor;
@ -50,6 +55,23 @@ public class ProcessEndListener implements FlowableEventListener {
if(ObjectUtil.isNull(processDefinition)){
return;
}
//获取流程类型
Object processType = flowableService.getHisVariable(flowableEngineEvent.getProcessInstanceId(), FlowConstants.PROCESS_TYPE);
//修改表单流程的状态---针对表单流程
if(ObjectUtil.isNull(processType)&&processType.equals(FlowTypeEnum.FORM_PROCESS.getCode())){
HistoricProcessInstance processInstance = flowableService.getHistoricProcessInstanceById(flowableEngineEvent.getProcessInstanceId());
ProcessEventRequest processEventRequest=new ProcessEventRequest(processInstance);
processEventRequest.setBusinessKey(processInstance.getBusinessKey());
//获取最后一个节点是通过还是驳回
Object isPass = flowableService.getHisVariable(flowableEngineEvent.getProcessInstanceId(), FlowConstants.IS_PASS);
if(ObjectUtil.isNotNull(isPass)&&(boolean)isPass){
processEventRequest.setProcessStatus(ProcessStatus.PASS.name());
}else {
processEventRequest.setProcessStatus(ProcessStatus.REJECT.name());
}
applicationContext.publishEvent(processEventRequest);
}
String key = Optional.ofNullable(processDefinition.getKey()).orElse("");
for (FlowDefEnum flowDefEnum : flowableService.getAllFlowDefEnumsSet()) {
//在流程中存在的才监听
@ -59,8 +81,6 @@ public class ProcessEndListener implements FlowableEventListener {
sendInnerMessage(processInstance);
}
}
}
}

View File

@ -0,0 +1,78 @@
package com.snow.flowable.listener.common;
import cn.hutool.core.util.ObjectUtil;
import com.snow.common.core.domain.ProcessEventRequest;
import com.snow.common.enums.ProcessStatus;
import com.snow.flowable.common.constants.FlowConstants;
import com.snow.flowable.common.enums.FlowTypeEnum;
import com.snow.flowable.service.FlowableService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author qimingjin
* @Title: 流程完结监听
* @Description:
* @date 2021/7/16 13:29
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ProcessStartListener implements FlowableEventListener {
@Resource
private FlowableService flowableService;
@Resource
private ApplicationContext applicationContext;
@Override
public void onEvent(FlowableEvent flowableEvent) {
if (flowableEvent instanceof FlowableEngineEntityEvent) {
FlowableEngineEntityEvent flowableEngineEvent = (FlowableEngineEntityEvent) flowableEvent;
ProcessDefinitionEntity processDefinition = flowableService.getProcessDefinition(flowableEngineEvent);
if(ObjectUtil.isNull(processDefinition)){
return;
}
//获取流程类型
Object processType = flowableService.getHisVariable(flowableEngineEvent.getProcessInstanceId(), FlowConstants.PROCESS_TYPE);
//修改表单流程的状态---针对表单流程
if(ObjectUtil.isNull(processType)&&processType.equals(FlowTypeEnum.FORM_PROCESS.getCode())){
HistoricProcessInstance processInstance = flowableService.getHistoricProcessInstanceById(flowableEngineEvent.getProcessInstanceId());
ProcessEventRequest processEventRequest=new ProcessEventRequest(processInstance);
processEventRequest.setBusinessKey(processInstance.getBusinessKey());
processEventRequest.setProcessStatus(ProcessStatus.CHECKING.name());
applicationContext.publishEvent(processEventRequest);
}
}
}
@Override
public boolean isFailOnException() {
return false;
}
@Override
public boolean isFireOnTransactionLifecycleEvent() {
return false;
}
@Override
public String getOnTransaction() {
return null;
}
}

View File

@ -85,7 +85,6 @@ public interface FlowableService {
* @param startProcessDTO
* @return
*/
@Deprecated
ProcessInstance startProcessInstanceByKey(StartProcessDTO startProcessDTO);
/**
@ -213,4 +212,12 @@ public interface FlowableService {
* @return 流程集合
*/
List<ProcessDefinitionResponse> getProcessDefByKey(String processDefinitionKey);
/**
* 获取流程历史参数
* @param processId 流程实例id
* @param key 参数key
* @return 参数值
*/
Object getHisVariable(String processId, String key);
}

View File

@ -1,6 +1,7 @@
package com.snow.flowable.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.BetweenFormater;
@ -58,6 +59,7 @@ import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.ui.modeler.domain.Model;
import org.flowable.ui.modeler.service.ModelServiceImpl;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -314,13 +316,13 @@ public class FlowableServiceImpl implements FlowableService {
public ProcessInstance startProcessInstanceByKey(StartProcessDTO startProcessDTO) {
ProcessInstance processInstance=null;
String startUserId=startProcessDTO.getStartUserId();
if(!StringUtils.isEmpty(startUserId)){
if(StrUtil.isNotBlank(startUserId)){
identityService.setAuthenticatedUserId(startUserId);
}
Map<String, Object> paramMap =CollectionUtils.isEmpty(startProcessDTO.getVariables())?Maps.newHashMap():startProcessDTO.getVariables();
paramMap.put(FlowConstants.START_USER_ID,startUserId);
if(!CollectionUtils.isEmpty(paramMap)){
if(CollUtil.isNotEmpty(paramMap)){
processInstance = runtimeService.startProcessInstanceByKey(startProcessDTO.getProcessDefinitionKey(),startProcessDTO.getBusinessKey(),paramMap);
}else {
processInstance = runtimeService.startProcessInstanceByKey(startProcessDTO.getProcessDefinitionKey(),startProcessDTO.getBusinessKey());
@ -1044,7 +1046,19 @@ public class FlowableServiceImpl implements FlowableService {
return cn.hutool.core.convert.Convert.toList(ProcessDefinitionResponse.class,list);
}
public Object getHisVariable(String processId, String key) {
Object variable = null;
List<HistoricVariableInstance> list = historyService
.createHistoricVariableInstanceQuery()
.taskId(processId)
.list();
for (HistoricVariableInstance historicVariableInstance:list) {
if (historicVariableInstance.getVariableName().equals(key)) {
variable = historicVariableInstance.getValue();
}
}
return variable;
}
/**
* 构建ProcessInstanceVO对象
* @param processInstanceVO

View File

@ -1,8 +1,8 @@
package com.snow.from.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
@ -10,10 +10,15 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.snow.common.constant.CacheConstants;
import com.snow.common.constant.SequenceConstants;
import com.snow.common.core.domain.AjaxResult;
import com.snow.common.enums.FormFieldTypeEnums;
import com.snow.common.utils.CacheUtils;
import com.snow.common.utils.StringUtils;
import com.snow.flowable.common.constants.FlowConstants;
import com.snow.flowable.common.enums.FlowTypeEnum;
import com.snow.flowable.domain.StartProcessDTO;
import com.snow.flowable.service.FlowableService;
import com.snow.framework.util.ShiroUtils;
import com.snow.from.domain.SysFormDataRecord;
import com.snow.from.domain.SysFormField;
@ -24,7 +29,9 @@ import com.snow.from.service.impl.SysFormDataRecordServiceImpl;
import com.snow.from.service.impl.SysFormFieldServiceImpl;
import com.snow.from.service.impl.SysFormInstanceServiceImpl;
import com.snow.from.util.FormUtils;
import com.snow.system.service.ISysSequenceService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
@ -38,6 +45,7 @@ import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
/**
@ -59,6 +67,12 @@ public class FormController{
@Autowired
private SysFormDataRecordServiceImpl sysFormDataRecordService;
@Autowired
private FlowableService flowableService;
@Autowired
private ISysSequenceService sequenceService;
/**
* 跳转form表单首页
* @return 首页url路径
@ -156,7 +170,8 @@ public class FormController{
public AjaxResult saveFormRecord(@RequestParam String formId ,
@RequestParam String formData,
@RequestParam String formField){
//生成单号
String formNo = sequenceService.getNewSequenceNo(SequenceConstants.OA_FORM_SEQUENCE);
//把用户填写的值赋值到表单里面去
String newFormData = FormUtils.fillFormFieldValue(formData, formField);
Long userId = ShiroUtils.getUserId();
@ -170,6 +185,7 @@ public class FormController{
Integer maxVersion = sysFormDataRecordService.getMaxVersionByUsrId(userId);
//版本号+1组成最新版本号
sysFormDataRecord.setVersion(Optional.ofNullable(maxVersion).orElse(0)+1);
sysFormDataRecord.setFormNo(formNo);
sysFormDataRecordService.insertSysFormDataRecord(sysFormDataRecord);
return AjaxResult.success();
}
@ -202,6 +218,31 @@ public class FormController{
SysFormDataRecord sysFormDataRecord = sysFormDataRecordService.selectSysFormDataRecordById(id);
return AjaxResult.success(sysFormDataRecord.getFormData());
}
/**
* 发起流程
* @param id 表单记录id
* @return 是否发起成功
*/
@PostMapping("/form/startProcess")
@ResponseBody
public AjaxResult startProcess(Integer id){
SysFormDataRecord sysFormDataRecord = sysFormDataRecordService.selectSysFormDataRecordById(id);
SysFormInstance sysFormInstance = sysFormInstanceService.selectSysFormInstanceById(Long.parseLong(sysFormDataRecord.getFormId()));
StartProcessDTO startProcessDTO=new StartProcessDTO();
startProcessDTO.setStartUserId(String.valueOf(ShiroUtils.getUserId()));
startProcessDTO.setBusinessKey(sysFormDataRecord.getFormNo());
startProcessDTO.setProcessDefinitionKey(sysFormInstance.getProcessKey());
String formData=sysFormDataRecord.getFormData();
String formField = sysFormDataRecord.getFormField();
Map<String, Object> variables = Convert.toMap(String.class, Object.class, JSON.parseArray(formField));
variables.put(FlowConstants.FORM_DATA,formData);
variables.put(FlowConstants.PROCESS_TYPE,FlowTypeEnum.FORM_PROCESS.getCode());
startProcessDTO.setVariables(variables);
ProcessInstance processInstance = flowableService.startProcessInstanceByKey(startProcessDTO);
log.info("@@表单编号:{},发起流程:{}",sysFormDataRecord.getFormNo(),JSON.toJSONString(processInstance));
return AjaxResult.success(sysFormDataRecord.getFormData());
}
/**
* 构建子表数据
* @param formId 表单id

View File

@ -17,6 +17,11 @@ public class SysFormDataRecord extends BaseEntity
/** 主键ID */
private Integer id;
/**
* 表单记录编号
*/
private String formNo;
/** 表单定义code */
private String formId;
@ -35,6 +40,11 @@ public class SysFormDataRecord extends BaseEntity
*/
private String formField;
/**
* 表单状态
*/
private String formStatus;
/** 表单url */
private String formUrl;

View File

@ -51,6 +51,14 @@ public interface SysFormDataRecordMapper
*/
public int updateSysFormDataRecord(SysFormDataRecord sysFormDataRecord);
/**
* 修改单数据记录单号
*
* @param sysFormDataRecord 单数据记录
* @return 结果
*/
public int updateSysFormDataRecordByNo(SysFormDataRecord sysFormDataRecord);
/**
* 删除单数据记录
*

View File

@ -0,0 +1,33 @@
package com.snow.from.service;
import com.alibaba.fastjson.JSON;
import com.snow.common.core.domain.ProcessEventRequest;
import com.snow.from.domain.SysFormDataRecord;
import com.snow.from.service.impl.SysFormDataRecordServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2021/12/6 16:02
*/
@Component
@Slf4j
public class FormProcessHandler implements ApplicationListener<ProcessEventRequest> {
@Autowired
private SysFormDataRecordServiceImpl formDataRecordService;
@Override
public void onApplicationEvent(ProcessEventRequest processEventRequest) {
log.info("@@流程状态变更监听器监听到的数据:{}", JSON.toJSON(processEventRequest));
SysFormDataRecord sysFormDataRecord=new SysFormDataRecord();
sysFormDataRecord.setFormNo(processEventRequest.getBusinessKey());
sysFormDataRecord.setFormStatus(processEventRequest.getProcessStatus());
formDataRecordService.updateSysFormDataRecordByNo(sysFormDataRecord);
}
}

View File

@ -2,7 +2,6 @@ package com.snow.from.service;
import com.snow.flowable.domain.response.ProcessDefinitionResponse;
import com.snow.flowable.service.FlowableService;
import com.snow.system.domain.SysDictData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

View File

@ -50,6 +50,13 @@ public interface ISysFormDataRecordService
*/
public int updateSysFormDataRecord(SysFormDataRecord sysFormDataRecord);
/**
* 修改表单记录通过单号
* @param sysFormDataRecord 单数据记录
* @return
*/
public int updateSysFormDataRecordByNo(SysFormDataRecord sysFormDataRecord);
/**
* 批量删除单数据记录
*

View File

@ -77,6 +77,12 @@ public class SysFormDataRecordServiceImpl implements ISysFormDataRecordService
return sysFormDataRecordMapper.updateSysFormDataRecord(sysFormDataRecord);
}
@Override
public int updateSysFormDataRecordByNo(SysFormDataRecord sysFormDataRecord) {
sysFormDataRecord.setUpdateTime(DateUtils.getNowDate());
return sysFormDataRecordMapper.updateSysFormDataRecordByNo(sysFormDataRecord);
}
/**
* 删除单数据记录对象
*

View File

@ -7,6 +7,8 @@
<resultMap type="SysFormDataRecord" id="SysFormDataRecordResult">
<result property="id" column="id" />
<result property="formId" column="form_id" />
<result property="formNo" column="form_no" />
<result property="formStatus" column="form_status" />
<result property="formData" column="form_data" />
<result property="formField" column="form_field" />
<result property="formUrl" column="form_url" />
@ -19,13 +21,15 @@
</resultMap>
<sql id="selectSysFormDataRecordVo">
select id, form_id, form_data, form_field,form_url, belong_user_id, create_by, create_time, update_time, update_by, version from sys_form_data_record
select id, form_id,form_no, form_data,form_status, form_field,form_url, belong_user_id, create_by, create_time, update_time, update_by, version from sys_form_data_record
</sql>
<select id="selectSysFormDataRecordList" parameterType="SysFormDataRecord" resultMap="SysFormDataRecordResult">
<include refid="selectSysFormDataRecordVo"/>
<where>
<if test="formId != null and formId != ''"> and form_id = #{formId}</if>
<if test="formNo != null and formNo != ''"> and form_no = #{formNo}</if>
<if test="formStatus != null and formStatus != ''"> and form_status = #{formStatus}</if>
<if test="formData != null and formData != ''"> and form_data = #{formData}</if>
<if test="formUrl != null and formUrl != ''"> and form_url = #{formUrl}</if>
<if test="belongUserId != null and belongUserId != ''"> and belong_user_id = #{belongUserId}</if>
@ -54,6 +58,8 @@
insert into sys_form_data_record
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="formId != null and formId != ''">form_id,</if>
<if test="formNo != null and formNo != ''"> form_no,</if>
<if test="formStatus != null and formStatus != ''"> form_status ,</if>
<if test="formData != null">form_data,</if>
<if test="formField != null">form_field,</if>
<if test="formUrl != null and formUrl != ''">form_url,</if>
@ -66,6 +72,8 @@
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="formId != null and formId != ''">#{formId},</if>
<if test="formNo != null and formNo != ''"> #{formNo},</if>
<if test="formStatus != null and formStatus != ''"> #{formStatus},</if>
<if test="formData != null">#{formData},</if>
<if test="formField != null">#{formField},</if>
<if test="formUrl != null and formUrl != ''">#{formUrl},</if>
@ -82,6 +90,8 @@
update sys_form_data_record
<trim prefix="SET" suffixOverrides=",">
<if test="formId != null and formId != ''">form_id = #{formId},</if>
<if test="formNo != null and formNo != ''"> form_no = #{formNo},</if>
<if test="formStatus != null and formStatus != ''"> form_status = #{formStatus},</if>
<if test="formData != null">form_data = #{formData},</if>
<if test="formField != null">form_field=#{formField},</if>
<if test="formUrl != null and formUrl != ''">form_url = #{formUrl},</if>
@ -95,6 +105,23 @@
where id = #{id}
</update>
<update id="updateSysFormDataRecordByNo" parameterType="SysFormDataRecord">
update sys_form_data_record
<trim prefix="SET" suffixOverrides=",">
<if test="formData != null">form_data = #{formData},</if>
<if test="formField != null">form_field=#{formField},</if>
<if test="formStatus != null and formStatus != ''"> form_status = #{formStatus},</if>
<if test="formUrl != null and formUrl != ''">form_url = #{formUrl},</if>
<if test="belongUserId != null">belong_user_id = #{belongUserId},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="version != null">version = #{version},</if>
</trim>
where form_no = #{formNo}
</update>
<delete id="deleteSysFormDataRecordById" parameterType="Integer">
delete from sys_form_data_record where id = #{id}
</delete>