yxk-20260409-集成流程引擎bpm代码
This commit is contained in:
+64
@@ -0,0 +1,64 @@
|
||||
///* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// * you may not use this file except in compliance with the License.
|
||||
// * You may obtain a copy of the License at
|
||||
// *
|
||||
// * http://www.apache.org/licenses/LICENSE-2.0
|
||||
// *
|
||||
// * Unless required by applicable law or agreed to in writing, software
|
||||
// * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// * See the License for the specific language governing permissions and
|
||||
// * limitations under the License.
|
||||
// */
|
||||
//package org.activiti.spring.boot;
|
||||
//
|
||||
//import java.io.IOException;
|
||||
//
|
||||
//import javax.sql.DataSource;
|
||||
//
|
||||
//import org.activiti.spring.SpringAsyncExecutor;
|
||||
//import org.activiti.spring.SpringProcessEngineConfiguration;
|
||||
//import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
//import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
//import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
//import org.springframework.transaction.PlatformTransactionManager;
|
||||
//
|
||||
///**
|
||||
// * 重构此类强制走Mybatis: 原来的逻辑是Activiti判断,如果项目使用了JPA,那走JPA,如果没有,则走Mybatis
|
||||
// * @author scott
|
||||
// * @参考链接:https://blog.csdn.net/jiaoshaoping/article/details/NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
// * @源码jar: activiti-spring-boot-starter-basic-5.22.0.jar
|
||||
// * @date: 2019-04-13
|
||||
// */
|
||||
//@Configuration
|
||||
//@AutoConfigureAfter(DataSourceAutoConfiguration.class)
|
||||
//public class DataSourceProcessEngineAutoConfiguration {
|
||||
//
|
||||
// @Configuration
|
||||
// //@ConditionalOnMissingClass(name= "javax.persistence.EntityManagerFactory")
|
||||
// @EnableConfigurationProperties(ActivitiProperties.class)
|
||||
// public static class DataSourceProcessEngineConfiguration extends AbstractProcessEngineAutoConfiguration {
|
||||
//
|
||||
// @Bean
|
||||
// @ConditionalOnMissingBean
|
||||
// public PlatformTransactionManager transactionManager(DataSource dataSource) {
|
||||
// return new DataSourceTransactionManager(dataSource);
|
||||
// }
|
||||
//
|
||||
// @Bean
|
||||
// @ConditionalOnMissingBean
|
||||
// public SpringProcessEngineConfiguration springProcessEngineConfiguration(
|
||||
// DataSource dataSource,
|
||||
// PlatformTransactionManager transactionManager,
|
||||
// SpringAsyncExecutor springAsyncExecutor) throws IOException {
|
||||
//
|
||||
// return this.baseSpringProcessEngineConfiguration(dataSource, transactionManager, springAsyncExecutor);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
///* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// * you may not use this file except in compliance with the License.
|
||||
// * You may obtain a copy of the License at
|
||||
// *
|
||||
// * http://www.apache.org/licenses/LICENSE-2.0
|
||||
// *
|
||||
// * Unless required by applicable law or agreed to in writing, software
|
||||
// * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// * See the License for the specific language governing permissions and
|
||||
// * limitations under the License.
|
||||
// */
|
||||
//package org.activiti.spring.boot;
|
||||
//
|
||||
//import java.io.IOException;
|
||||
//
|
||||
//import javax.persistence.EntityManagerFactory;
|
||||
//import javax.sql.DataSource;
|
||||
//
|
||||
//import org.activiti.spring.SpringAsyncExecutor;
|
||||
//import org.activiti.spring.SpringProcessEngineConfiguration;
|
||||
//import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
//import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
//import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
//import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
//import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
//import org.springframework.transaction.PlatformTransactionManager;
|
||||
//
|
||||
///**
|
||||
// * 重构此类强制走Mybatis: 原来的逻辑是Activiti判断,如果项目使用了JPA,那走JPA,如果没有,则走Mybatis
|
||||
// * @author scott
|
||||
// * @参考链接:https://blog.csdn.net/jiaoshaoping/article/details/NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
// * @源码jar: activiti-spring-boot-starter-basic-5.22.0.jar
|
||||
// * @date: 2019-04-13
|
||||
// */
|
||||
//@Configuration
|
||||
//@AutoConfigureBefore(DataSourceProcessEngineAutoConfiguration.class)
|
||||
//@AutoConfigureAfter(DataSourceAutoConfiguration.class)
|
||||
//public class JpaProcessEngineAutoConfiguration {
|
||||
//
|
||||
//// @Configuration
|
||||
//// @ConditionalOnClass(name= "javax.persistence.EntityManagerFactory")
|
||||
//// @EnableConfigurationProperties(ActivitiProperties.class)
|
||||
//// public static class JpaConfiguration extends AbstractProcessEngineAutoConfiguration {
|
||||
////
|
||||
//// @Bean
|
||||
//// @ConditionalOnMissingBean
|
||||
//// public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
|
||||
//// return new JpaTransactionManager(emf);
|
||||
//// }
|
||||
////
|
||||
//// @Bean
|
||||
//// @ConditionalOnMissingBean
|
||||
//// public SpringProcessEngineConfiguration springProcessEngineConfiguration(
|
||||
//// DataSource dataSource, EntityManagerFactory entityManagerFactory,
|
||||
//// PlatformTransactionManager transactionManager, SpringAsyncExecutor springAsyncExecutor) throws IOException {
|
||||
////
|
||||
//// SpringProcessEngineConfiguration config = this.baseSpringProcessEngineConfiguration(dataSource,
|
||||
//// transactionManager, springAsyncExecutor);
|
||||
//// config.setJpaEntityManagerFactory(entityManagerFactory);
|
||||
//// config.setTransactionManager(transactionManager);
|
||||
//// config.setJpaHandleTransaction(false);
|
||||
//// config.setJpaCloseEntityManager(false);
|
||||
//// return config;
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
//}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
//package org.jeecg;
|
||||
//
|
||||
//import org.springframework.boot.SpringApplication;
|
||||
//import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
//import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
//
|
||||
///**
|
||||
// *
|
||||
// * @author scott
|
||||
// *
|
||||
// */
|
||||
//@SpringBootApplication
|
||||
//@EnableAutoConfiguration(exclude={org.flowable.spring.boot.FlowableSecurityAutoConfiguration.class})
|
||||
//public class JeecgBpmApplication {
|
||||
//
|
||||
// public static void main(String[] args) {
|
||||
// System.setProperty("spring.devtools.restart.enabled", "false");
|
||||
// SpringApplication.run(JeecgBpmApplication.class, args);
|
||||
// }
|
||||
//}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package org.jeecg.modules.aspect;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* 拦截器——同步流程用户、角色、部门、职务
|
||||
*/
|
||||
@Configuration("synFlowUserPrincipalDataConfiguration")
|
||||
public class SynFlowUserPrincipalDataConfiguration implements WebMvcConfigurer {
|
||||
private static String[] URL_PATTERNS = new String[]{
|
||||
"/sys/role/add",
|
||||
"/sys/role/edit",
|
||||
"/sys/role/delete",
|
||||
"/sys/sysDepart/add",
|
||||
"/sys/sysDepart/delete",
|
||||
"/sys/user/doUpdateDepartInfo",
|
||||
"/sys/user/deleteUserRoleBatch",
|
||||
"/sys/tenant/invitationUser",
|
||||
"/sys/user/userQuitAgent",
|
||||
"/sys/user/batchEditUsers",
|
||||
"/sys/user/addSysUserRole",
|
||||
"/sys/position/removePositionUser",
|
||||
"/sys/position/savePositionUser",
|
||||
"/sys/position/add",
|
||||
"/sys/position/edit",
|
||||
"/sys/user/editTenantUser",
|
||||
};
|
||||
|
||||
@Bean("synFlowUserPrincipalDataInterceptor")
|
||||
public SynFlowUserPrincipalDataInterceptor dynFlowUserPrincipalDataInterceptor() {
|
||||
return new SynFlowUserPrincipalDataInterceptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(dynFlowUserPrincipalDataInterceptor()).addPathPatterns(URL_PATTERNS);
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package org.jeecg.modules.aspect;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.util.TokenUtils;
|
||||
import org.jeecg.modules.extbpm.process.controller.SyncTenantUserThreadTask;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* 注意:这里同步是同步用户下的所有数据(不区分租户)
|
||||
*
|
||||
* 针对零代码应用的操作请求,自动同步流程用户的 角色、部门、职务到流程中(用户下的所有租户数据一次性同步)
|
||||
* @author zhang
|
||||
*/
|
||||
@Slf4j
|
||||
public class SynFlowUserPrincipalDataInterceptor implements HandlerInterceptor {
|
||||
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
|
||||
//触发同步流程主数据
|
||||
log.info("===== 同步流程主数据 ===== ,URL:"+ request.getRequestURI());
|
||||
String syncUserFlag = SyncTenantUserThreadTask.syncUserFlag;
|
||||
if (syncUserFlag != null && "1".equals(syncUserFlag)) {
|
||||
log.info("===== 正在同步中===== ");
|
||||
} else {
|
||||
SyncTenantUserThreadTask.syncUserFlag = "1";
|
||||
String username = JwtUtil.getUserNameByToken(request);
|
||||
//获取登录租户ID
|
||||
String tenantId = TokenUtils.getTenantIdByRequest(request);
|
||||
FutureTask<Boolean> futureTask = new FutureTask<Boolean>(new SyncTenantUserThreadTask(username, tenantId));
|
||||
Thread newThread = new Thread(futureTask);
|
||||
newThread.start();
|
||||
try {
|
||||
Boolean threadResult = futureTask.get(200, TimeUnit.MILLISECONDS);;
|
||||
}catch (TimeoutException e) {
|
||||
log.error("同步流程租户数据,等待数据200毫秒以上,异常信息!");
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("fail:", e);
|
||||
}
|
||||
log.info("===== 同步流程主数据 完成 =====");
|
||||
}
|
||||
}
|
||||
}
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
package org.jeecg.modules.aspect;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.system.vo.UserAccountInfo;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.pojo.DepInfo;
|
||||
import org.jeecg.modules.extbpm.process.pojo.PositionInfo;
|
||||
import org.jeecg.modules.extbpm.process.pojo.RoleInfo;
|
||||
import org.jeecg.modules.extbpm.process.pojo.UserInfo;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
*
|
||||
* 用户同步到工作流
|
||||
* @author zhoujf
|
||||
*
|
||||
*/
|
||||
@Aspect
|
||||
@Slf4j
|
||||
@Component("sysUserAspect")
|
||||
public class SysUserAspect {
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
@Autowired
|
||||
private IExtActProcessService extActProcessService;
|
||||
|
||||
@Pointcut("execution(public * org.jeecg.modules.*.controller.SysUserController.add(..))")
|
||||
public void excudeServiceAdd() {
|
||||
}
|
||||
|
||||
@Around("excudeServiceAdd()")
|
||||
public Object doAroundAdd(ProceedingJoinPoint pjp) throws Throwable {
|
||||
Object result = pjp.proceed();
|
||||
try {
|
||||
Object[] args = pjp.getArgs();
|
||||
JSONObject param = (JSONObject)args[0];
|
||||
String userName = param.getString("username");
|
||||
log.info("------------SysUserAspect------add----"+userName);
|
||||
LoginUser user = sysBaseAPI.getUserByName(userName);
|
||||
if(user!=null) {
|
||||
if(CommonConstant.ACT_SYNC_1.equals(user.getActivitiSync())) {
|
||||
//同步则进行同步用户和角色信息
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setUuid(user.getId());
|
||||
userInfo.setFirstName(user.getRealname());
|
||||
userInfo.setEmail(user.getEmail());
|
||||
userInfo.setId(user.getUsername());
|
||||
//将用户的角色同步到流程
|
||||
List<RoleInfo> roleList = extActProcessService.getSysRolesByUserId(userInfo.getUuid());
|
||||
//将用户的部门同步到流程
|
||||
List<DepInfo> depList = extActProcessService.getSysDepsByUserId(userInfo.getUuid());
|
||||
//将用户的职务同步到流程
|
||||
List<PositionInfo> positionList = extActProcessService.getSysPositionsByUserId(userInfo.getUuid());
|
||||
extActProcessService.saveActIdMembership(userInfo, roleList,depList,positionList);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Pointcut("execution(public * org.jeecg.modules.*.controller.SysUserController.edit(..))")
|
||||
public void excudeServiceEdit() {
|
||||
}
|
||||
|
||||
@Around("excudeServiceEdit()")
|
||||
public Object doAroundEdit(ProceedingJoinPoint pjp) throws Throwable {
|
||||
Object result = pjp.proceed();
|
||||
try {
|
||||
Object[] args = pjp.getArgs();
|
||||
JSONObject param = (JSONObject)args[0];
|
||||
String userName = param.getString("username");
|
||||
log.info("------------SysUserAspect------edit----"+userName);
|
||||
LoginUser user = sysBaseAPI.getUserByName(userName);
|
||||
if(user!=null) {
|
||||
if(CommonConstant.ACT_SYNC_1.equals(user.getActivitiSync())) {
|
||||
// NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
//同步则进行同步用户和角色信息
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setUuid(user.getId());
|
||||
userInfo.setFirstName(user.getRealname());
|
||||
userInfo.setEmail(user.getEmail());
|
||||
userInfo.setId(user.getUsername());
|
||||
//将用户的角色同步到流程
|
||||
List<RoleInfo> roleList = extActProcessService.getSysRolesByUserId(userInfo.getUuid());
|
||||
//将用户的部门同步到流程中
|
||||
List<DepInfo> depList = extActProcessService.getSysDepsByUserId(userInfo.getUuid());
|
||||
//将用户的职务同步到流程
|
||||
List<PositionInfo> positionList = extActProcessService.getSysPositionsByUserId(userInfo.getUuid());
|
||||
extActProcessService.saveActIdMembership(userInfo, roleList,depList,positionList);
|
||||
}else {
|
||||
//不同步删除用户信息
|
||||
extActProcessService.deleteActIdMembership(userName);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Pointcut("execution(public * org.jeecg.modules.*.controller.SysUserController.putRecycleBin(..))")
|
||||
public void excudeServicePutRecycleBin() {
|
||||
}
|
||||
|
||||
@Around("excudeServicePutRecycleBin()")
|
||||
public Object doAroundPutRecycleBin(ProceedingJoinPoint pjp) throws Throwable {
|
||||
Object result = pjp.proceed();
|
||||
try {
|
||||
Object[] args = pjp.getArgs();
|
||||
JSONObject param = (JSONObject) args[0];
|
||||
String userIds = param.getString("userIds");
|
||||
log.info("------------SysUserAspect------PutRecycleBin----" + userIds);
|
||||
if (oConvertUtils.isNotEmpty(userIds)) {
|
||||
List<UserAccountInfo> userList = sysBaseAPI.queryAllUserByIds((userIds.split(",")));
|
||||
for (UserAccountInfo user : userList) {
|
||||
if (CommonConstant.ACT_SYNC_1.equals(user.getActivitiSync())) {
|
||||
//同步则进行同步用户和角色信息
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setUuid(user.getId());
|
||||
userInfo.setFirstName(user.getRealname());
|
||||
userInfo.setEmail(user.getEmail());
|
||||
userInfo.setId(user.getUsername());
|
||||
//将用户的角色同步到流程
|
||||
List<RoleInfo> roleList = extActProcessService.getSysRolesByUserId(userInfo.getUuid());
|
||||
//将用户的部门同步到流程
|
||||
List<DepInfo> depList = extActProcessService.getSysDepsByUserId(userInfo.getUuid());
|
||||
//将用户的职务同步到流程
|
||||
List<PositionInfo> positionList = extActProcessService.getSysPositionsByUserId(userInfo.getUuid());
|
||||
extActProcessService.saveActIdMembership(userInfo, roleList,depList,positionList);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Pointcut("execution(public * org.jeecg.modules.*.controller.SysUserController.delete(..))")
|
||||
public void excudeServiceDelete() {
|
||||
}
|
||||
|
||||
@Around("excudeServiceDelete()")
|
||||
public Object doAroundDelete(ProceedingJoinPoint pjp) throws Throwable {
|
||||
try {
|
||||
Object[] args = pjp.getArgs();
|
||||
String id = (String)args[0];
|
||||
log.info("------------SysUserAspect------delete----"+id);
|
||||
LoginUser user = sysBaseAPI.getUserById(id);
|
||||
if(user!=null) {
|
||||
//不同步删除用户信息
|
||||
extActProcessService.deleteActIdMembership(user.getUsername());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
}
|
||||
Object result = pjp.proceed();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Pointcut("execution(public * org.jeecg.modules.*.controller.SysUserController.deleteBatch(..))")
|
||||
public void excudeServiceDeleteBatch() {
|
||||
}
|
||||
|
||||
@Around("excudeServiceDeleteBatch()")
|
||||
public Object doAroundDeleteBatch(ProceedingJoinPoint pjp) throws Throwable {
|
||||
try {
|
||||
Object[] args = pjp.getArgs();
|
||||
String ids = (String)args[0];
|
||||
log.info("------------SysUserAspect------deleteBatch----"+ids);
|
||||
String[] idArr = ids.split(",");
|
||||
for(String id :idArr) {
|
||||
LoginUser user = sysBaseAPI.getUserById(id);
|
||||
if(user!=null) {
|
||||
//不同步删除用户信息
|
||||
extActProcessService.deleteActIdMembership(user.getUsername());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
Object result = pjp.proceed();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* 系统角色删除,同步删除流程中的角色
|
||||
*/
|
||||
@Pointcut("execution(public * org.jeecg.modules.*.controller.SysRoleController.delete(..))")
|
||||
public void excudeServiceRoleDelete() {
|
||||
}
|
||||
|
||||
@Pointcut("execution(public * org.jeecg.modules.*.controller.SysRoleController.deleteBatch(..))")
|
||||
public void excudeServiceRoleDeleteBatch() {
|
||||
}
|
||||
|
||||
@Around("excudeServiceRoleDelete()")
|
||||
public Object doAroundRoleDelete(ProceedingJoinPoint pjp) throws Throwable {
|
||||
try {
|
||||
Object[] args = pjp.getArgs();
|
||||
String id = (String) args[0];
|
||||
log.info("------------SysUserAspect---Role---delete----" + id);
|
||||
//同步删除流程中的角色
|
||||
String roleCode = sysBaseAPI.getRoleCodeById(id);
|
||||
extActProcessService.deleteFlowRoleSet(roleCode);
|
||||
|
||||
} catch (Exception e) {
|
||||
}
|
||||
Object result = pjp.proceed();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Around("excudeServiceRoleDeleteBatch()")
|
||||
public Object doAroundRoleDeleteBatch(ProceedingJoinPoint pjp) throws Throwable {
|
||||
try {
|
||||
Object[] args = pjp.getArgs();
|
||||
String ids = (String) args[0];
|
||||
log.info("------------SysUserAspect---Roles---deleteBatch----" + ids);
|
||||
String[] idArr = ids.split(",");
|
||||
for (String id : idArr) {
|
||||
//同步删除流程中的角色
|
||||
String roleCode = sysBaseAPI.getRoleCodeById(id);
|
||||
extActProcessService.deleteFlowRoleSet(roleCode);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
Object result = pjp.proceed();
|
||||
return result;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package org.jeecg.modules.aspect.event;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.base.BaseMap;
|
||||
import org.jeecg.common.config.mqtoken.UserTokenContext;
|
||||
import org.jeecg.common.constant.FlowEventTypeConst;
|
||||
import org.jeecg.common.modules.redis.listener.JeecgRedisListener;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* 说明:系统角色删除,同步删除BPM中的角色
|
||||
* <p>
|
||||
*
|
||||
* @author: scott
|
||||
* @date: 2024-05-27
|
||||
*/
|
||||
@Slf4j
|
||||
@Component(FlowEventTypeConst.DELETE_ROLE_2_BPM_REDIS_HANDLER)
|
||||
@ConditionalOnMissingClass("org.jeecg.modules.system.controller.SysUserController") //与SysUserAspect互斥关系
|
||||
public class DeleteRole2BpmRedisHandler implements JeecgRedisListener {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
|
||||
@Autowired
|
||||
private IExtActProcessService extActProcessService;
|
||||
|
||||
@Override
|
||||
public void onMessage(BaseMap map) {
|
||||
//1.设置线程会话Token
|
||||
UserTokenContext.setToken(UpdateUser2BpmRedisHandler.getTemporaryToken());
|
||||
|
||||
log.info("【同步删除流程角色】redis Listener: {},参数:{}", FlowEventTypeConst.DELETE_ROLE_2_BPM_REDIS_HANDLER, map.toString());
|
||||
String ids = map.get("roleIds");
|
||||
log.info("------------DeleteRole2BpmRedisHandler---Roles---deleteBatch----" + ids);
|
||||
String[] idArr = ids.split(",");
|
||||
for (String id : idArr) {
|
||||
//同步删除流程中的角色
|
||||
String roleCode = sysBaseAPI.getRoleCodeById(id);
|
||||
extActProcessService.deleteFlowRoleSet(roleCode);
|
||||
}
|
||||
|
||||
//2.使用完删除Token,避免性能(这一步可以不做,但是为了性能建议执行)
|
||||
UserTokenContext.remove();
|
||||
}
|
||||
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package org.jeecg.modules.aspect.event;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.base.BaseMap;
|
||||
import org.jeecg.common.config.mqtoken.UserTokenContext;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.FlowEventTypeConst;
|
||||
import org.jeecg.common.modules.redis.listener.JeecgRedisListener;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.pojo.DepInfo;
|
||||
import org.jeecg.modules.extbpm.process.pojo.PositionInfo;
|
||||
import org.jeecg.modules.extbpm.process.pojo.RoleInfo;
|
||||
import org.jeecg.modules.extbpm.process.pojo.UserInfo;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 说明:BPM作为独立微服务模块允许,编辑用户,不会自动同步用户到工作流中
|
||||
* <p>
|
||||
* 此类解决:: 微服务情况下,同步用户信息到流程中的问题
|
||||
*
|
||||
* @author: scott
|
||||
* @date: 2024-05-27
|
||||
*/
|
||||
@Slf4j
|
||||
@Component(FlowEventTypeConst.UPDATE_USER_2_BPM_REDIS_HANDLER)
|
||||
@ConditionalOnMissingClass("org.jeecg.modules.system.controller.SysUserController") //与SysUserAspect互斥关系
|
||||
public class UpdateUser2BpmRedisHandler implements JeecgRedisListener {
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
|
||||
@Autowired
|
||||
private IExtActProcessService extActProcessService;
|
||||
|
||||
@Override
|
||||
public void onMessage(BaseMap map) {
|
||||
//1.设置线程会话Token
|
||||
UserTokenContext.setToken(getTemporaryToken());
|
||||
|
||||
log.info("【同步流程用户】redis Listener: {},参数:{}", FlowEventTypeConst.UPDATE_USER_2_BPM_REDIS_HANDLER, map.toString());
|
||||
String userNames = map.get("userNames");
|
||||
if (StringUtils.isEmpty(userNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (userNames.contains(",")) {
|
||||
// 判断传入的是多个用户
|
||||
String[] userNamesArray = userNames.split(",");
|
||||
for (String userName : userNamesArray) {
|
||||
if (StringUtils.isEmpty(userName)) {
|
||||
continue;
|
||||
}
|
||||
// 进行处理
|
||||
synchronizeUser(userName);
|
||||
}
|
||||
} else {
|
||||
// 判断传入的是单个用户
|
||||
// 进行处理
|
||||
synchronizeUser(userNames);
|
||||
}
|
||||
|
||||
//2.使用完删除Token,避免性能(这一步可以不做,但是为了性能建议执行)
|
||||
UserTokenContext.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步单个用户
|
||||
*
|
||||
* @param userName
|
||||
*/
|
||||
private void synchronizeUser(String userName) {
|
||||
log.info("------------SysUserAspect------Synch----userName=" + userName);
|
||||
LoginUser user = sysBaseAPI.getUserByName(userName);
|
||||
if (user != null) {
|
||||
if (CommonConstant.ACT_SYNC_1.equals(user.getActivitiSync())) {
|
||||
// NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
//同步则进行同步用户和角色信息
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setUuid(user.getId());
|
||||
userInfo.setFirstName(user.getRealname());
|
||||
userInfo.setEmail(user.getEmail());
|
||||
userInfo.setId(user.getUsername());
|
||||
//将用户的角色同步到流程
|
||||
List<RoleInfo> roleList = extActProcessService.getSysRolesByUserId(userInfo.getUuid());
|
||||
//将用户的部门同步到流程中
|
||||
List<DepInfo> depList = extActProcessService.getSysDepsByUserId(userInfo.getUuid());
|
||||
//将用户的职务同步到流程
|
||||
List<PositionInfo> positionList = extActProcessService.getSysPositionsByUserId(userInfo.getUuid());
|
||||
extActProcessService.saveActIdMembership(userInfo, roleList, depList, positionList);
|
||||
} else {
|
||||
// 从流程中删除用户信息(逻辑删除用户 或 用户变更为不同步流程走此逻辑)
|
||||
extActProcessService.deleteActIdMembership(userName);
|
||||
}
|
||||
} else {
|
||||
// 从流程中删除用户信息(逻辑删除用户 或 用户变更为不同步流程走此逻辑)
|
||||
extActProcessService.deleteActIdMembership(userName);
|
||||
}
|
||||
}
|
||||
|
||||
//*********************************************************************************************************
|
||||
/**
|
||||
* TODO 有风险,考虑更好方案
|
||||
* 模拟登陆临时账号密码
|
||||
* _reserve_user_external
|
||||
* jeecg@123
|
||||
*/
|
||||
private static final String EXTERNAL_USERNAME = "X3Jlc2VydmVfdXNlcl9leHRlcm5hbA==";
|
||||
private static final String EXTERNAL_PASSWORD = "amVlY2dAMTIz";
|
||||
|
||||
/**
|
||||
* 获取临时登录令牌
|
||||
* <p>
|
||||
* 模拟登陆接口,获取模拟 Token
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getTemporaryToken() {
|
||||
RedisUtil redisUtil = SpringContextUtils.getBean(RedisUtil.class);
|
||||
//模拟登录生成临时Token
|
||||
//参数说明:第一个参数是用户名、第二个参数是密码的加密串
|
||||
String token = JwtUtil.sign(oConvertUtils.decodeBase64Str(EXTERNAL_USERNAME), oConvertUtils.decodeBase64Str(EXTERNAL_PASSWORD));
|
||||
// 设置Token缓存有效时间为 5 分钟
|
||||
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
|
||||
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, 5 * 60 * 1000);
|
||||
return token;
|
||||
}
|
||||
//*********************************************************************************************************
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.compatibility.Flowable5CompatibilityHandler;
|
||||
import org.flowable.engine.impl.persistence.entity.CommentEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.impl.util.Flowable5Util;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.engine.task.Comment;
|
||||
import org.flowable.engine.task.Event;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.jeecg.modules.bpm.constant.enums.CommentTypeEnum;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: Bruce.liu
|
||||
* @Since:19:01 2018/11/24
|
||||
* 爱拼才会赢 2019 ~ 2030 版权所有
|
||||
*/
|
||||
public class AddCommentCmd implements Command<Comment> {
|
||||
|
||||
protected String taskId;
|
||||
protected String userId;
|
||||
protected String processInstanceId;
|
||||
protected String type;
|
||||
protected String message;
|
||||
|
||||
public AddCommentCmd(String userId, String processInstanceId, String type, String message) {
|
||||
this.processInstanceId = processInstanceId;
|
||||
this.message = message;
|
||||
this.type = type;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public AddCommentCmd(String taskId, String userId, String processInstanceId, String type, String message) {
|
||||
this.taskId = taskId;
|
||||
this.processInstanceId = processInstanceId;
|
||||
this.type = type;
|
||||
this.message = message;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comment execute(CommandContext commandContext) {
|
||||
TaskEntity task = null;
|
||||
ExecutionEntity execution = null;
|
||||
if (processInstanceId != null) {
|
||||
execution = CommandContextUtil.getExecutionEntityManager(commandContext).findById(processInstanceId);
|
||||
if (execution == null) {
|
||||
throw new FlowableObjectNotFoundException("execution " + processInstanceId + " doesn't exist", Execution.class);
|
||||
}
|
||||
if (execution.isSuspended()) {
|
||||
throw new FlowableException(getSuspendedExceptionMessage());
|
||||
}
|
||||
}
|
||||
|
||||
String processDefinitionId = null;
|
||||
if (execution != null) {
|
||||
processDefinitionId = execution.getProcessDefinitionId();
|
||||
} else if (task != null) {
|
||||
processDefinitionId = task.getProcessDefinitionId();
|
||||
}
|
||||
|
||||
if (processDefinitionId != null && Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, processDefinitionId)) {
|
||||
Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
|
||||
if (org.apache.commons.lang.StringUtil.isBlank(message)){
|
||||
message = "";
|
||||
}
|
||||
return compatibilityHandler.addComment(taskId, processInstanceId, type, message);
|
||||
}
|
||||
CommentEntity comment = CommandContextUtil.getCommentEntityManager(commandContext).create();
|
||||
comment.setUserId(userId);
|
||||
comment.setType((type == null) ? CommentTypeEnum.SP.toString() : type);
|
||||
comment.setTime(CommandContextUtil.getProcessEngineConfiguration(commandContext).getClock().getCurrentTime());
|
||||
comment.setTaskId(taskId);
|
||||
comment.setProcessInstanceId(processInstanceId);
|
||||
comment.setAction(Event.ACTION_ADD_COMMENT);
|
||||
|
||||
String eventMessage = org.apache.commons.lang.StringUtil.isNotBlank(message)?message.replaceAll("\\s+", " "):"";
|
||||
if (eventMessage.length() > 3900) {
|
||||
eventMessage = eventMessage.substring(0, 3900) + "...";
|
||||
}
|
||||
comment.setMessage(eventMessage);
|
||||
comment.setFullMessage(message);
|
||||
CommandContextUtil.getCommentEntityManager(commandContext).insert(comment);
|
||||
|
||||
return comment;
|
||||
}
|
||||
protected String getSuspendedTaskException() {
|
||||
return "Cannot add a comment to a suspended task";
|
||||
}
|
||||
protected String getSuspendedExceptionMessage() {
|
||||
return "Cannot add a comment to a suspended execution";
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.CommentEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.task.Comment;
|
||||
import org.flowable.engine.task.Event;
|
||||
import org.jeecg.modules.bpm.constant.enums.CommentTypeEnum;
|
||||
|
||||
/**
|
||||
* 网上的参考代码(目前未使用)
|
||||
*
|
||||
* @Description: 添加历史审批记录
|
||||
* @Author: scoot
|
||||
* @Since:19:01 2022-12-06
|
||||
*/
|
||||
public class AddHisCommentCmd implements Command<Comment> {
|
||||
|
||||
protected String taskId;
|
||||
protected String userId;
|
||||
protected String processInstanceId;
|
||||
protected String type;
|
||||
protected String message;
|
||||
|
||||
public AddHisCommentCmd(String taskId, String userId, String processInstanceId, String type, String message) {
|
||||
this.taskId = taskId;
|
||||
this.userId = userId;
|
||||
this.processInstanceId = processInstanceId;
|
||||
this.type = type;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comment execute(CommandContext commandContext) {
|
||||
HistoricProcessInstanceEntity hisProIns = null;
|
||||
if (processInstanceId != null) {
|
||||
hisProIns = CommandContextUtil.getHistoricProcessInstanceEntityManager(commandContext).findById(processInstanceId);
|
||||
if (hisProIns == null) {
|
||||
throw new FlowableObjectNotFoundException("HistoricProcessInstance " + processInstanceId + " doesn't exist", HistoricProcessInstanceEntity.class);
|
||||
}
|
||||
}
|
||||
CommentEntity comment = CommandContextUtil.getCommentEntityManager(commandContext).create();
|
||||
comment.setUserId(userId);
|
||||
comment.setType((type == null) ? CommentTypeEnum.SP.toString() : type);
|
||||
comment.setTime(CommandContextUtil.getProcessEngineConfiguration(commandContext).getClock().getCurrentTime());
|
||||
comment.setTaskId(taskId);
|
||||
comment.setProcessInstanceId(processInstanceId);
|
||||
comment.setAction(Event.ACTION_ADD_COMMENT);
|
||||
|
||||
String eventMessage = org.apache.commons.lang.StringUtil.isNotBlank(message) ? message.replaceAll("\\s+", " ") : "";
|
||||
if (eventMessage.length() > 3900) {
|
||||
eventMessage = eventMessage.substring(0, 3900) + "...";
|
||||
}
|
||||
comment.setMessage(eventMessage);
|
||||
comment.setFullMessage(message);
|
||||
CommandContextUtil.getCommentEntityManager(commandContext).insert(comment);
|
||||
return comment;
|
||||
}
|
||||
|
||||
protected String getSuspendedTaskException() {
|
||||
return "Cannot add a comment to a suspended task";
|
||||
}
|
||||
|
||||
protected String getSuspendedExceptionMessage() {
|
||||
return "Cannot add a comment to a suspended execution";
|
||||
}
|
||||
}
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import org.flowable.bpmn.BpmnAutoLayout;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.cmd.AbstractDynamicInjectionCmd;
|
||||
import org.flowable.engine.impl.context.Context;
|
||||
import org.flowable.engine.impl.dynamic.BaseDynamicSubProcessInjectUtil;
|
||||
import org.flowable.engine.impl.dynamic.DynamicUserTaskBuilder;
|
||||
import org.flowable.engine.impl.persistence.entity.DeploymentEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||
import org.flowable.task.service.TaskService;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.jeecg.modules.bpm.cmd.dto.TaskAddRequest;
|
||||
import org.jeecg.modules.bpm.cmd.util.ApiAssert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description: 动态添加用户节点(向后加签)
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-06
|
||||
*/
|
||||
public class AfterSignUserTaskCmd extends AbstractDynamicInjectionCmd implements Command<Void> {
|
||||
|
||||
protected String processInstanceId;
|
||||
protected String currentTaskDefKey;
|
||||
protected TaskAddRequest taskAddRequest;
|
||||
|
||||
|
||||
private boolean autoLayout = true;
|
||||
|
||||
|
||||
public AfterSignUserTaskCmd(TaskAddRequest taskAddRequest) {
|
||||
this.processInstanceId = taskAddRequest.getProcInsId();
|
||||
this.currentTaskDefKey = taskAddRequest.getCurrentTaskDefKey();
|
||||
this.taskAddRequest = taskAddRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void execute(CommandContext commandContext) {
|
||||
createDerivedProcessDefinitionForProcessInstance(commandContext, processInstanceId);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateBpmnProcess(CommandContext commandContext, Process process, BpmnModel bpmnModel, ProcessDefinitionEntity originalProcessDefinitionEntity, DeploymentEntity newDeploymentEntity) {
|
||||
String dynamicTaskId = "Task_" + RandomUtil.randomString(7);
|
||||
DynamicUserTaskBuilder dynamicUserTaskBuilder = new DynamicUserTaskBuilder();
|
||||
dynamicUserTaskBuilder.setId(dynamicTaskId);
|
||||
dynamicUserTaskBuilder.setName(taskAddRequest.getTaskName());
|
||||
dynamicUserTaskBuilder.setAssignee(taskAddRequest.getAssignee());
|
||||
|
||||
FlowElement currentFlowElement = process.getFlowElement(currentTaskDefKey);
|
||||
if (ObjectUtil.isNotEmpty(currentFlowElement)) {
|
||||
if (!(currentFlowElement instanceof Task)) {
|
||||
ApiAssert.failure("非任务节点");
|
||||
}
|
||||
UserTask currentUserTask = (UserTask) currentFlowElement;
|
||||
//定义新的节点
|
||||
UserTask newUserTask = new UserTask();
|
||||
if (dynamicUserTaskBuilder.getId() != null) {
|
||||
newUserTask.setId(dynamicUserTaskBuilder.getId());
|
||||
} else {
|
||||
newUserTask.setId(dynamicUserTaskBuilder.nextTaskId(process.getFlowElementMap()));
|
||||
}
|
||||
dynamicUserTaskBuilder.setDynamicTaskId(newUserTask.getId());
|
||||
newUserTask.setName(dynamicUserTaskBuilder.getName());
|
||||
newUserTask.setAssignee(dynamicUserTaskBuilder.getAssignee());
|
||||
|
||||
List<SequenceFlow> outgoingFlows = new ArrayList<>();
|
||||
//获取当前流程节点流出的sequence
|
||||
List<SequenceFlow> currentOutgoingFlows = currentUserTask.getOutgoingFlows();
|
||||
for (SequenceFlow sequenceFlow : currentOutgoingFlows) {
|
||||
SequenceFlow outgoingFlow = new SequenceFlow(newUserTask.getId(), sequenceFlow.getTargetRef());
|
||||
outgoingFlow.setSkipExpression(sequenceFlow.getSkipExpression());
|
||||
outgoingFlow.setConditionExpression(sequenceFlow.getConditionExpression());
|
||||
outgoingFlow.setExtensionElements(sequenceFlow.getExtensionElements());
|
||||
outgoingFlow.setExecutionListeners(sequenceFlow.getExecutionListeners());
|
||||
outgoingFlow.setName(sequenceFlow.getName());
|
||||
outgoingFlow.setId("Flow_" + RandomUtil.randomString(7));
|
||||
outgoingFlows.add(outgoingFlow);
|
||||
//删除原先节点的出线
|
||||
process.removeFlowElement(sequenceFlow.getId());
|
||||
process.addFlowElement(outgoingFlow);
|
||||
}
|
||||
|
||||
List<SequenceFlow> incomingFlows = new ArrayList<>();
|
||||
SequenceFlow incomingFlow = new SequenceFlow(currentFlowElement.getId(), newUserTask.getId());
|
||||
//设置唯一编
|
||||
incomingFlow.setId("Flow_" + RandomUtil.randomString(7));
|
||||
incomingFlows.add(incomingFlow);
|
||||
process.addFlowElement(incomingFlow);
|
||||
newUserTask.setOutgoingFlows(outgoingFlows);
|
||||
newUserTask.setIncomingFlows(incomingFlows);
|
||||
process.addFlowElement(newUserTask);
|
||||
|
||||
//新增坐标 点
|
||||
GraphicInfo elementGraphicInfo = bpmnModel.getGraphicInfo(currentFlowElement.getId());
|
||||
if (elementGraphicInfo != null) {
|
||||
//自动排版
|
||||
if (autoLayout) {
|
||||
new BpmnAutoLayout(bpmnModel).execute();
|
||||
} else {
|
||||
drawNode(bpmnModel, elementGraphicInfo, newUserTask, outgoingFlows, incomingFlows, process);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
drawNode(process, bpmnModel, dynamicUserTaskBuilder);
|
||||
}
|
||||
BaseDynamicSubProcessInjectUtil.processFlowElements(commandContext, process, bpmnModel, originalProcessDefinitionEntity, newDeploymentEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateExecutions(CommandContext commandContext, ProcessDefinitionEntity processDefinitionEntity, ExecutionEntity processInstance, List<ExecutionEntity> childExecutions) {
|
||||
}
|
||||
|
||||
|
||||
private void drawNode(BpmnModel bpmnModel, GraphicInfo elementGraphicInfo, UserTask userTask, List<SequenceFlow> outgoingFlows, List<SequenceFlow> incomingFlows, Process process) {
|
||||
double yDiff = 0;
|
||||
double xDiff = 80;
|
||||
if (elementGraphicInfo.getY() < 173) {
|
||||
yDiff = 173 - elementGraphicInfo.getY();
|
||||
elementGraphicInfo.setY(173);
|
||||
}
|
||||
StartEvent initialStartEvent = getStartEvent(process);
|
||||
Map<String, GraphicInfo> locationMap = bpmnModel.getLocationMap();
|
||||
for (String locationId : locationMap.keySet()) {
|
||||
if (initialStartEvent.getId().equals(locationId)) {
|
||||
continue;
|
||||
}
|
||||
GraphicInfo locationGraphicInfo = locationMap.get(locationId);
|
||||
locationGraphicInfo.setX(locationGraphicInfo.getX() + xDiff);
|
||||
locationGraphicInfo.setY(locationGraphicInfo.getY() + yDiff);
|
||||
}
|
||||
|
||||
Map<String, List<GraphicInfo>> flowLocationMap = bpmnModel.getFlowLocationMap();
|
||||
for (String flowId : flowLocationMap.keySet()) {
|
||||
//if (flowFromStart.getId().equals(flowId)) {
|
||||
//continue;
|
||||
//}
|
||||
List<GraphicInfo> flowGraphicInfoList = flowLocationMap.get(flowId);
|
||||
for (GraphicInfo flowGraphicInfo : flowGraphicInfoList) {
|
||||
flowGraphicInfo.setX(flowGraphicInfo.getX() + xDiff);
|
||||
flowGraphicInfo.setY(flowGraphicInfo.getY() + yDiff);
|
||||
|
||||
}
|
||||
}
|
||||
//绘制节点
|
||||
GraphicInfo newTaskGraphicInfo = new GraphicInfo(elementGraphicInfo.getX() + 185, elementGraphicInfo.getY() - 163, 80, 100);
|
||||
bpmnModel.addGraphicInfo(userTask.getId(), newTaskGraphicInfo);
|
||||
bpmnModel.addFlowGraphicInfoList(userTask.getId(), createWayPoints(elementGraphicInfo.getX() + 95, elementGraphicInfo.getY() - 5, elementGraphicInfo.getX() + 95, elementGraphicInfo.getY() - 123, elementGraphicInfo.getX() + 185, elementGraphicInfo.getY() - 123));
|
||||
|
||||
List<SequenceFlow> addFlows = new ArrayList<>();
|
||||
addFlows.addAll(outgoingFlows);
|
||||
addFlows.addAll(incomingFlows);
|
||||
|
||||
/* 绘制连线 */
|
||||
for (SequenceFlow sequenceFlow1 : addFlows) {
|
||||
bpmnModel.addFlowGraphicInfoList(sequenceFlow1.getId(), createWayPoints(elementGraphicInfo.getX() + 30, elementGraphicInfo.getY() + 15, elementGraphicInfo.getX() + 75, elementGraphicInfo.getY() + 15));
|
||||
}
|
||||
}
|
||||
|
||||
private void drawNode(Process process, BpmnModel bpmnModel, DynamicUserTaskBuilder dynamicUserTaskBuilder) {
|
||||
StartEvent initialStartEvent = getStartEvent(process);
|
||||
ParallelGateway parallelGateway = new ParallelGateway();
|
||||
parallelGateway.setId(dynamicUserTaskBuilder.nextForkGatewayId(process.getFlowElementMap()));
|
||||
process.addFlowElement(parallelGateway);
|
||||
|
||||
UserTask newUserTask = new UserTask();
|
||||
if (dynamicUserTaskBuilder.getId() != null) {
|
||||
newUserTask.setId(dynamicUserTaskBuilder.getId());
|
||||
} else {
|
||||
newUserTask.setId(dynamicUserTaskBuilder.nextTaskId(process.getFlowElementMap()));
|
||||
}
|
||||
dynamicUserTaskBuilder.setDynamicTaskId(newUserTask.getId());
|
||||
|
||||
newUserTask.setName(dynamicUserTaskBuilder.getName());
|
||||
newUserTask.setAssignee(dynamicUserTaskBuilder.getAssignee());
|
||||
process.addFlowElement(newUserTask);
|
||||
|
||||
EndEvent endEvent = new EndEvent();
|
||||
endEvent.setId(dynamicUserTaskBuilder.nextEndEventId(process.getFlowElementMap()));
|
||||
process.addFlowElement(endEvent);
|
||||
|
||||
SequenceFlow flowToUserTask = new SequenceFlow(parallelGateway.getId(), newUserTask.getId());
|
||||
flowToUserTask.setId(dynamicUserTaskBuilder.nextFlowId(process.getFlowElementMap()));
|
||||
process.addFlowElement(flowToUserTask);
|
||||
|
||||
SequenceFlow flowFromUserTask = new SequenceFlow(newUserTask.getId(), endEvent.getId());
|
||||
flowFromUserTask.setId(dynamicUserTaskBuilder.nextFlowId(process.getFlowElementMap()));
|
||||
process.addFlowElement(flowFromUserTask);
|
||||
|
||||
SequenceFlow initialFlow = initialStartEvent.getOutgoingFlows().get(0);
|
||||
initialFlow.setSourceRef(parallelGateway.getId());
|
||||
|
||||
SequenceFlow flowFromStart = new SequenceFlow(initialStartEvent.getId(), parallelGateway.getId());
|
||||
flowFromStart.setId(dynamicUserTaskBuilder.nextFlowId(process.getFlowElementMap()));
|
||||
process.addFlowElement(flowFromStart);
|
||||
//跳整节点的布局
|
||||
GraphicInfo elementGraphicInfo = bpmnModel.getGraphicInfo(initialStartEvent.getId());
|
||||
if (elementGraphicInfo != null) {
|
||||
double yDiff = 0;
|
||||
double xDiff = 80;
|
||||
if (elementGraphicInfo.getY() < 173) {
|
||||
yDiff = 173 - elementGraphicInfo.getY();
|
||||
elementGraphicInfo.setY(173);
|
||||
}
|
||||
|
||||
Map<String, GraphicInfo> locationMap = bpmnModel.getLocationMap();
|
||||
for (String locationId : locationMap.keySet()) {
|
||||
if (initialStartEvent.getId().equals(locationId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GraphicInfo locationGraphicInfo = locationMap.get(locationId);
|
||||
locationGraphicInfo.setX(locationGraphicInfo.getX() + xDiff);
|
||||
locationGraphicInfo.setY(locationGraphicInfo.getY() + yDiff);
|
||||
}
|
||||
|
||||
Map<String, List<GraphicInfo>> flowLocationMap = bpmnModel.getFlowLocationMap();
|
||||
for (String flowId : flowLocationMap.keySet()) {
|
||||
if (flowFromStart.getId().equals(flowId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<GraphicInfo> flowGraphicInfoList = flowLocationMap.get(flowId);
|
||||
for (GraphicInfo flowGraphicInfo : flowGraphicInfoList) {
|
||||
flowGraphicInfo.setX(flowGraphicInfo.getX() + xDiff);
|
||||
flowGraphicInfo.setY(flowGraphicInfo.getY() + yDiff);
|
||||
}
|
||||
}
|
||||
|
||||
GraphicInfo forkGraphicInfo = new GraphicInfo(elementGraphicInfo.getX() + 75, elementGraphicInfo.getY() - 5, 40, 40);
|
||||
bpmnModel.addGraphicInfo(parallelGateway.getId(), forkGraphicInfo);
|
||||
bpmnModel.addFlowGraphicInfoList(flowFromStart.getId(), createWayPoints(elementGraphicInfo.getX() + 30, elementGraphicInfo.getY() + 15, elementGraphicInfo.getX() + 75, elementGraphicInfo.getY() + 15));
|
||||
|
||||
GraphicInfo newTaskGraphicInfo = new GraphicInfo(elementGraphicInfo.getX() + 185, elementGraphicInfo.getY() - 163, 80, 100);
|
||||
bpmnModel.addGraphicInfo(newUserTask.getId(), newTaskGraphicInfo);
|
||||
bpmnModel.addFlowGraphicInfoList(flowToUserTask.getId(), createWayPoints(elementGraphicInfo.getX() + 95, elementGraphicInfo.getY() - 5, elementGraphicInfo.getX() + 95, elementGraphicInfo.getY() - 123, elementGraphicInfo.getX() + 185, elementGraphicInfo.getY() - 123));
|
||||
|
||||
GraphicInfo endGraphicInfo = new GraphicInfo(elementGraphicInfo.getX() + 335, elementGraphicInfo.getY() - 137, 28, 28);
|
||||
bpmnModel.addGraphicInfo(endEvent.getId(), endGraphicInfo);
|
||||
bpmnModel.addFlowGraphicInfoList(flowFromUserTask.getId(), createWayPoints(elementGraphicInfo.getX() + 285, elementGraphicInfo.getY() - 123, elementGraphicInfo.getX() + 335, elementGraphicInfo.getY() - 123));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateExecutions(CommandContext commandContext, ExecutionEntity processInstance, ProcessDefinitionEntity processDefinitionEntity, DynamicUserTaskBuilder dynamicUserTaskBuilder) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
|
||||
List<ExecutionEntity> oldExecution = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstance.getProcessInstanceId());
|
||||
ExecutionEntity execution = executionEntityManager.createChildExecution(processInstance);
|
||||
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionEntity.getId());
|
||||
|
||||
TaskService taskService = CommandContextUtil.getTaskService(commandContext);
|
||||
List<TaskEntity> taskEntities = taskService.findTasksByProcessInstanceId(processInstanceId);
|
||||
// 删除当前活动任务
|
||||
for (TaskEntity taskEntity : taskEntities) {
|
||||
taskEntity.getIdentityLinks().stream().forEach(identityLinkEntity -> {
|
||||
if (identityLinkEntity.isGroup()) {
|
||||
taskEntity.deleteGroupIdentityLink(identityLinkEntity.getGroupId(), "candidate");
|
||||
} else {
|
||||
taskEntity.deleteUserIdentityLink(identityLinkEntity.getUserId(), "participant");
|
||||
}
|
||||
});
|
||||
if (taskEntity.getTaskDefinitionKey().equals(currentTaskDefKey)) {
|
||||
taskService.deleteTask(taskEntity, false);
|
||||
}
|
||||
}
|
||||
//设置活动后的节点
|
||||
UserTask userTask = (UserTask) bpmnModel.getProcessById(processDefinitionEntity.getKey()).getFlowElement(dynamicUserTaskBuilder.getId());
|
||||
execution.setCurrentFlowElement(userTask);
|
||||
Context.getAgenda().planContinueProcessOperation(execution);
|
||||
}
|
||||
|
||||
private StartEvent getStartEvent(Process process) {
|
||||
List<StartEvent> startEvents = process.findFlowElementsOfType(StartEvent.class);
|
||||
StartEvent initialStartEvent = null;
|
||||
for (StartEvent startEvent : startEvents) {
|
||||
if (startEvent.getEventDefinitions().size() == 0) {
|
||||
initialStartEvent = startEvent;
|
||||
break;
|
||||
|
||||
} else if (initialStartEvent == null) {
|
||||
initialStartEvent = startEvent;
|
||||
}
|
||||
}
|
||||
return initialStartEvent;
|
||||
}
|
||||
}
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.common.engine.impl.calendar.CronExpression;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.common.engine.impl.util.DefaultClockImpl;
|
||||
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.job.api.Job;
|
||||
import org.flowable.job.service.TimerJobService;
|
||||
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.job.CustomTimeStartJobEventHandler;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 使用flowable内部Api手动创建作业(Job)
|
||||
*
|
||||
* 参考博客
|
||||
* https://blog.csdn.net/II_bat/article/details/51329399
|
||||
* https://blog.csdn.net/oouuyy/article/details/118890552
|
||||
*/
|
||||
@Slf4j
|
||||
public class CustomTimeStartJobCmd implements Command<Void>, Serializable {
|
||||
//流程定义key
|
||||
protected String processKey;
|
||||
//表单编码或者表名
|
||||
protected String formKey;
|
||||
//表单数据id
|
||||
protected String dataId;
|
||||
//流程发起人
|
||||
protected String applyUserId;
|
||||
//定时开始时间
|
||||
protected Date dueDate;
|
||||
//触发字段
|
||||
protected String triggerField;
|
||||
//定时频率表达式
|
||||
protected String repeat;
|
||||
|
||||
public CustomTimeStartJobCmd(String processKey, String formKey, String dataId, Date dueDate, String applyUserId, String triggerField) {
|
||||
this.formKey = formKey;
|
||||
this.dataId = dataId;
|
||||
this.processKey = processKey;
|
||||
this.applyUserId = applyUserId;
|
||||
this.dueDate = dueDate;
|
||||
this.triggerField = triggerField;
|
||||
}
|
||||
|
||||
public CustomTimeStartJobCmd(String processKey, String formKey, String dataId, Date dueDate, String applyUserId,String repeat, String triggerField) {
|
||||
this.formKey = formKey;
|
||||
this.dataId = dataId;
|
||||
this.processKey = processKey;
|
||||
this.applyUserId = applyUserId;
|
||||
this.dueDate = dueDate;
|
||||
this.repeat = repeat;
|
||||
this.triggerField = triggerField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void execute(CommandContext commandContext) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("activityId", "start");
|
||||
jsonObject.put(WorkFlowGlobals.BPM_DATA_ID, this.dataId);
|
||||
jsonObject.put(WorkFlowGlobals.BPM_FORM_KEY, this.formKey);
|
||||
jsonObject.put(WorkFlowGlobals.APPLY_USER_ID, this.applyUserId);
|
||||
jsonObject.put(WorkFlowGlobals.TIME_TRIGGER_FIELD, this.triggerField);
|
||||
|
||||
TimerJobService timerJobService = CommandContextUtil.getTimerJobService(commandContext);
|
||||
TimerJobEntity job = timerJobService.createTimerJob();
|
||||
job.setJobType(Job.JOB_TYPE_TIMER);
|
||||
job.setExclusive(true);
|
||||
// 自定义作业处理器
|
||||
//job.setJobHandlerType(TimerStartEventJobHandler.TYPE);
|
||||
job.setJobHandlerType(CustomTimeStartJobEventHandler.TYPE);
|
||||
// 处理时间
|
||||
job.setDuedate(this.dueDate);
|
||||
|
||||
job.setExclusive(true);
|
||||
if(oConvertUtils.isNotEmpty(this.repeat)){
|
||||
job.setRepeat(this.repeat);
|
||||
//--------------------------------------------------------------------------------
|
||||
//测试发现flowable可以自动调整开始时间改为下一次有效日期,但是发现会发起一次流程,这个不应该发起,所以还是需要手工计算下次有效期
|
||||
//判断开始时间 dueDate小于当前时间,则生成下次有效执行时间
|
||||
try {
|
||||
if (!this.dueDate.after(new Date())) {
|
||||
CronExpression cronExpression = new CronExpression(this.repeat, new DefaultClockImpl());
|
||||
Date nextDuteDate = cronExpression.getNextValidTimeAfter(new Date());
|
||||
log.info("执行日期小于当前时间,重新计算下次执行时间!执行日期:{},通过计算获取下次执行有效期:{},循环表达式:{}",
|
||||
DateUtils.datetimeFormat.get().format(this.dueDate), DateUtils.datetimeFormat.get().format(nextDuteDate), this.repeat);
|
||||
job.setDuedate(nextDuteDate);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
log.error("重新计算下次执行时间异常:" + e.getMessage());
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
//流程key
|
||||
ProcessDefinitionEntity processDefinition = CommandContextUtil.getProcessDefinitionEntityManager().findLatestProcessDefinitionByKey(processKey);
|
||||
String processDefinitionId = processDefinition.getId();
|
||||
job.setProcessDefinitionId(processDefinitionId);
|
||||
job.setJobHandlerConfiguration(jsonObject.toJSONString());
|
||||
timerJobService.scheduleTimerJob(job);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Description: 删除执行数据命令
|
||||
* @Author: zyf
|
||||
* @Date: 2022-06-01
|
||||
*/
|
||||
public class DeleteExecutionCmd implements Command<String>, Serializable {
|
||||
|
||||
/**
|
||||
* 执行id
|
||||
*/
|
||||
private String executionId;
|
||||
|
||||
public DeleteExecutionCmd(String executionId) {
|
||||
this.executionId = executionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(CommandContext commandContext) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
|
||||
executionEntityManager.delete(executionId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.cmd.NeedsActiveTaskCmd;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.task.service.TaskService;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
|
||||
/**
|
||||
* @Description: 删除任务命令
|
||||
* @Author: zyf
|
||||
* @Date: 2022-06-01
|
||||
*/
|
||||
public class DeleteTaskCmd extends NeedsActiveTaskCmd<String> {
|
||||
|
||||
/**
|
||||
* 当前任务对应的 act_ru_task 任务id
|
||||
*/
|
||||
public DeleteTaskCmd(String taskId) {
|
||||
super(taskId);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String execute(CommandContext commandContext, TaskEntity task) {
|
||||
TaskService taskService = CommandContextUtil.getTaskService(commandContext);
|
||||
taskService.deleteTask(task,true);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import cn.hutool.core.text.StrFormatter;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.cmd.util.ApiAssert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Description: 获取流程定义
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-06
|
||||
*/
|
||||
@Slf4j
|
||||
public class GetProcessDefinitionCmd implements Command<ProcessDefinition>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 流程定义ID
|
||||
*/
|
||||
protected String processDefinitionId;
|
||||
/**
|
||||
* 流程KEY
|
||||
*/
|
||||
protected String processDefinitionKey;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
protected String tenantId;
|
||||
|
||||
public GetProcessDefinitionCmd(String processDefinitionId, String processDefinitionKey, String tenantId) {
|
||||
this.processDefinitionId = processDefinitionId;
|
||||
this.processDefinitionKey = processDefinitionKey;
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
public GetProcessDefinitionCmd(String processDefinitionId) {
|
||||
this.processDefinitionId = processDefinitionId;
|
||||
}
|
||||
|
||||
public GetProcessDefinitionCmd(String processDefinitionId, String processDefinitionKey) {
|
||||
this.processDefinitionId = processDefinitionId;
|
||||
this.processDefinitionKey = processDefinitionKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ProcessDefinition execute(CommandContext commandContext) {
|
||||
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||
//获取流程定义管理器
|
||||
ProcessDefinitionEntityManager processDefinitionEntityManager = processEngineConfiguration.getProcessDefinitionEntityManager();
|
||||
ProcessDefinition processDefinition = null;
|
||||
if (processDefinitionId != null) {
|
||||
processDefinition = processDefinitionEntityManager.findById(processDefinitionId);
|
||||
log.error(StrFormatter.format("流程定义不存在,processDefinitionId:{}", processDefinitionId));
|
||||
ApiAssert.isNotEmpty("流程定义不存在", processDefinition);
|
||||
} else if (processDefinitionKey != null && ObjectUtil.isEmpty(tenantId)) {
|
||||
processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKey(processDefinitionKey);
|
||||
log.error(StrFormatter.format("流程定义不存在,processDefinitionKey:{}", processDefinitionKey));
|
||||
ApiAssert.isNotEmpty("流程定义不存在", processDefinition);
|
||||
} else if (processDefinitionKey != null && oConvertUtils.isNotEmpty(tenantId)) {
|
||||
processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, tenantId);
|
||||
if (processDefinition == null) {
|
||||
if (processEngineConfiguration.isFallbackToDefaultTenant()) {
|
||||
if (org.apache.commons.lang.StringUtil.isNotEmpty(processEngineConfiguration.getDefaultTenantValue())) {
|
||||
processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, processEngineConfiguration.getDefaultTenantValue());
|
||||
} else {
|
||||
processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKey(processDefinitionKey);
|
||||
}
|
||||
log.error(StrFormatter.format("流程定义不存在,还应用了默认租户的回退,processDefinitionKey:{}", processDefinitionKey));
|
||||
ApiAssert.isNotEmpty("流程定义不存在", processDefinition);
|
||||
} else {
|
||||
log.error(StrFormatter.format("流程定义不存在,processDefinitionKey:{},and 租户ID:{1}", processDefinitionKey, tenantId));
|
||||
ApiAssert.failure("流程定义不存在");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ApiAssert.failure("参数异常");
|
||||
}
|
||||
return processDefinition;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.ProcessEngineConfiguration;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.flowable.engine.repository.ProcessDefinitionQuery;
|
||||
import org.jeecg.modules.bpm.cmd.util.ApiAssert;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActProcess;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Description: 流程级联删除命令
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-06
|
||||
*/
|
||||
public class ProcessDeleteCmd implements Command<Boolean>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 管理控制部署与流程定义
|
||||
*/
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
|
||||
private ExtActProcess flowProcess;
|
||||
|
||||
public ProcessDeleteCmd(ExtActProcess flowProcess) {
|
||||
this.flowProcess = flowProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean execute(CommandContext commandContext) {
|
||||
ProcessEngineConfiguration processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||
this.repositoryService = processEngineConfiguration.getRepositoryService();
|
||||
ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
|
||||
String processKey = flowProcess.getProcessKey();
|
||||
definitionQuery.processDefinitionKey(processKey);
|
||||
long procDefCount = definitionQuery.count();
|
||||
if (procDefCount > 0) {
|
||||
ApiAssert.failure("流程已发布,禁止删除");
|
||||
}
|
||||
String procModelId = flowProcess.getProcessKey();
|
||||
if (ObjectUtil.isNotEmpty(procModelId)) {
|
||||
Model model = repositoryService.getModel(procModelId);
|
||||
if (ObjectUtil.isNotEmpty(model)) {
|
||||
repositoryService.deleteModel(procModelId);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.DeploymentBuilder;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.cmd.util.ApiAssert;
|
||||
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Description: 流程部署命令
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-06
|
||||
*/
|
||||
public class ProcessDeployCmd implements Command<Deployment>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 流程模型ID
|
||||
*/
|
||||
private String modelId;
|
||||
|
||||
private Model model;
|
||||
|
||||
public ProcessDeployCmd(String modelId, Model model) {
|
||||
this.modelId = modelId;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deployment execute(CommandContext commandContext) {
|
||||
Deployment deployment = null;
|
||||
RepositoryService repositoryService = CommandContextUtil.getProcessEngineConfiguration(commandContext).getRepositoryService();
|
||||
if (model == null) {
|
||||
ApiAssert.failure("流程模型不存在:" + modelId);
|
||||
}
|
||||
if (!model.hasEditorSource()) {
|
||||
ApiAssert.failure("资源不存在,流程模型:" + modelId);
|
||||
}
|
||||
byte[] bpmnBytes = CommandContextUtil.getProcessEngineConfiguration(commandContext).getModelEntityManager().findEditorSourceByModelId(modelId);
|
||||
if (bpmnBytes == null) {
|
||||
ApiAssert.failure("资源不存在,流程模型:" + modelId);
|
||||
}
|
||||
try {
|
||||
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
|
||||
String fileName = model.getId() + ".bpmn20.xml";
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(bpmnBytes);
|
||||
deploymentBuilder.addInputStream(fileName, bis);
|
||||
deploymentBuilder.name(fileName);
|
||||
// modelId设置为部署的分类字段作为后续关联的需要
|
||||
deploymentBuilder.category(model.getCategory());
|
||||
|
||||
XMLInputFactory xif = XMLInputFactory.newInstance();
|
||||
InputStreamReader xmlIn = new InputStreamReader(new ByteArrayInputStream(bpmnBytes), "UTF-8");
|
||||
XMLStreamReader xtr = xif.createXMLStreamReader(xmlIn);
|
||||
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
|
||||
org.flowable.bpmn.model.Process process = bpmnModel.getMainProcess();
|
||||
deploymentBuilder.key(process.getId());
|
||||
//租户ID
|
||||
String tenantId = model.getTenantId();
|
||||
if (oConvertUtils.isNotEmpty(tenantId)) {
|
||||
//设置租户ID
|
||||
deploymentBuilder.tenantId(tenantId);
|
||||
}
|
||||
deployment = deploymentBuilder.deploy();
|
||||
if (deployment != null) {
|
||||
model.setDeploymentId(deployment.getId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ApiAssert.failure("发布失败");
|
||||
}
|
||||
return deployment;
|
||||
}
|
||||
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import com.google.common.io.CharStreams;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.common.engine.impl.util.io.InputStreamSource;
|
||||
import org.flowable.common.engine.impl.util.io.StreamSource;
|
||||
import org.flowable.engine.ProcessEngineConfiguration;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.repository.DeploymentBuilder;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.cmd.util.ApiAssert;
|
||||
import org.jeecg.modules.bpm.cmd.util.FlowableUtils;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActProcess;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @Description: 根据导入文件构建FlowProcess
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-06
|
||||
*/
|
||||
@Slf4j
|
||||
public class ProcessImportCmd implements Command<ExtActProcess>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
/**
|
||||
* 上传文件对象
|
||||
*/
|
||||
private MultipartFile file;
|
||||
|
||||
public ProcessImportCmd(HttpServletRequest request) {
|
||||
if (!(request instanceof MultipartHttpServletRequest)) {
|
||||
log.error("请求必须是MultipartHttpServletRequest的实例");
|
||||
ApiAssert.failure("导入失败");
|
||||
}
|
||||
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
|
||||
if (multipartRequest.getFileMap().size() == 0) {
|
||||
log.error("请求文件为空");
|
||||
ApiAssert.failure("导入失败");
|
||||
}
|
||||
this.file = multipartRequest.getFileMap().values().iterator().next();
|
||||
this.fileName = this.file.getOriginalFilename();
|
||||
//检测文件是否合法
|
||||
FlowableUtils.checkImportFileName(this.fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtActProcess execute(CommandContext commandContext) {
|
||||
ProcessEngineConfiguration processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||
RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();
|
||||
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
|
||||
boolean isBpmnFile = FlowableUtils.isBpmnFile(fileName);
|
||||
ExtActProcess flowProcess = new ExtActProcess();
|
||||
try {
|
||||
if (isBpmnFile) {
|
||||
deploymentBuilder.addInputStream(fileName, file.getInputStream());
|
||||
StreamSource xmlSource = new InputStreamSource(file.getInputStream());
|
||||
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xmlSource, false, false, "UTF-8");
|
||||
Process process = bpmnModel.getMainProcess();
|
||||
if (oConvertUtils.isNotEmpty(process)) {
|
||||
//添加自定义流程定义
|
||||
String processXml = CharStreams.toString(new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8));
|
||||
flowProcess.setProcessXml(processXml.getBytes());
|
||||
flowProcess.setProcessKey(process.getId());
|
||||
flowProcess.setProcessName(process.getName());
|
||||
flowProcess.setNote(process.getDocumentation());
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("导入异常:", e.getMessage());
|
||||
}
|
||||
return flowProcess;
|
||||
}
|
||||
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import cn.hutool.core.text.StrFormatter;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.flowable.bpmn.model.FlowNode;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.jeecg.modules.bpm.cmd.util.ApiAssert;
|
||||
import org.jeecg.modules.bpm.cmd.util.FlowableUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @TODO 此方法暂时未用上,是从 yf 项目迁移过来
|
||||
*
|
||||
* @Description: 驳回任务(指定节点)
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-10
|
||||
*/
|
||||
public class RejectTaskCmd implements Command<String>, Serializable {
|
||||
|
||||
protected RuntimeService runtimeService;
|
||||
/**
|
||||
* 当前节点
|
||||
*/
|
||||
protected String taskId;
|
||||
/**
|
||||
* 跳转目标节点ID
|
||||
*/
|
||||
protected String targetActivityId;
|
||||
|
||||
public RejectTaskCmd(RuntimeService runtimeService, String taskId, String targetActivityId) {
|
||||
this.runtimeService = runtimeService;
|
||||
this.taskId = taskId;
|
||||
this.targetActivityId = targetActivityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(CommandContext commandContext) {
|
||||
// NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
ApiAssert.isNotEmpty("驳回节点ID不能为空", this.targetActivityId);
|
||||
//当前任务节点对象
|
||||
TaskEntity task = CommandContextUtil.getProcessEngineConfiguration().getTaskServiceConfiguration().getTaskService().getTask(taskId);
|
||||
ApiAssert.isNotEmpty("任务不存在", task);
|
||||
//流程定义ID
|
||||
String processDefinitionId = task.getProcessDefinitionId();
|
||||
//流程对象
|
||||
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
|
||||
//当然任务节点key
|
||||
String taskDefinitionKey = task.getTaskDefinitionKey();
|
||||
//当前节点对象
|
||||
FlowNode sourceFlowElement = (FlowNode) process.getFlowElement(taskDefinitionKey, true);
|
||||
// 只支持从用户任务退回
|
||||
if (!(sourceFlowElement instanceof UserTask)) {
|
||||
ApiAssert.failure("当前节点不是UserTask对象");
|
||||
}
|
||||
//目标节点对象
|
||||
FlowNode targetFlowElement = (FlowNode) process.getFlowElement(this.targetActivityId, true);
|
||||
//检测目标节点是否可访问
|
||||
if (!FlowableUtils.isReachable(process, targetFlowElement, sourceFlowElement)) {
|
||||
ApiAssert.failure(StrFormatter.format("无法驳回到指定节点,targetActivityId:{}", this.targetActivityId));
|
||||
}
|
||||
//目标节点如果相对当前节点是在子流程内部,则无法直接退回,目前处理是只能退回到子流程开始节点
|
||||
String[] sourceAndTargetRealActivityId = FlowableUtils.getSourceAndTargetRealActivityId(sourceFlowElement, targetFlowElement);
|
||||
|
||||
// 实际应操作的当前节点ID
|
||||
String sourceRealActivityId = sourceAndTargetRealActivityId[0];
|
||||
// 实际应操作的目标节点ID
|
||||
String targetRealActivityId = sourceAndTargetRealActivityId[1];
|
||||
|
||||
//获取特殊网关节点
|
||||
Map<String, Set<String>> specialGatewayNodes = FlowableUtils.getSpecialGatewayElements(process);
|
||||
// 当前节点处在的并行网关list
|
||||
List<String> sourceInSpecialGatewayList = new ArrayList<>();
|
||||
// 目标节点处在的并行网关list
|
||||
List<String> targetInSpecialGatewayList = new ArrayList<>();
|
||||
|
||||
FlowableUtils.setSpecialGatewayList(sourceRealActivityId, targetRealActivityId, specialGatewayNodes, sourceInSpecialGatewayList, targetInSpecialGatewayList);
|
||||
|
||||
// 实际应筛选的节点ID
|
||||
Set<String> sourceRealAcitivtyIds = null;
|
||||
// 若退回目标节点相对当前节点在并行网关中,则要找到相对当前节点最近的这个并行网关,后续做特殊处理
|
||||
String targetRealSpecialGateway = null;
|
||||
// 1.目标节点和当前节点都不在并行网关中
|
||||
if (targetInSpecialGatewayList.isEmpty() && sourceInSpecialGatewayList.isEmpty()) {
|
||||
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
|
||||
}
|
||||
// 2.目标节点不在并行网关中、当前节点在并行网关中
|
||||
else if (targetInSpecialGatewayList.isEmpty() && !sourceInSpecialGatewayList.isEmpty()) {
|
||||
sourceRealAcitivtyIds = specialGatewayNodes.get(sourceInSpecialGatewayList.get(0));
|
||||
}
|
||||
// 3.目标节点在并行网关中、当前节点不在并行网关中
|
||||
else if (!targetInSpecialGatewayList.isEmpty() && sourceInSpecialGatewayList.isEmpty()) {
|
||||
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
|
||||
targetRealSpecialGateway = targetInSpecialGatewayList.get(0);
|
||||
}
|
||||
// 4.目标节点和当前节点都在并行网关中
|
||||
else {
|
||||
int diffSpecialGatewayLevel = FlowableUtils.getDiffLevel(sourceInSpecialGatewayList,
|
||||
targetInSpecialGatewayList);
|
||||
// 在并行网关同一层且在同一分支
|
||||
if (diffSpecialGatewayLevel == -1) {
|
||||
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
|
||||
} else {
|
||||
// 当前节点最内层并行网关不被目标节点最内层并行网关包含
|
||||
// 或理解为当前节点相对目标节点在并行网关外
|
||||
// 只筛选当前节点的execution
|
||||
if (sourceInSpecialGatewayList.size() == diffSpecialGatewayLevel) {
|
||||
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
|
||||
}
|
||||
// 当前节点相对目标节点在并行网关内,应筛选相对目标节点最近的并行网关的所有节点的execution
|
||||
else {
|
||||
sourceRealAcitivtyIds = specialGatewayNodes
|
||||
.get(sourceInSpecialGatewayList.get(diffSpecialGatewayLevel));
|
||||
}
|
||||
// 目标节点最内层并行网关包含当前节点最内层并行网关
|
||||
// 或理解为目标节点相对当前节点在并行网关外
|
||||
// 不做处理
|
||||
if (targetInSpecialGatewayList.size() == diffSpecialGatewayLevel) {
|
||||
}
|
||||
// 目标节点相对当前节点在并行网关内
|
||||
else {
|
||||
targetRealSpecialGateway = targetInSpecialGatewayList.get(diffSpecialGatewayLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
String processInstanceId = task.getProcessInstanceId();
|
||||
// 筛选需要处理的execution
|
||||
List<ExecutionEntity> realExecutions = FlowableUtils.getRealExecutions(commandContext, processInstanceId, task.getExecutionId(), sourceRealActivityId, sourceRealAcitivtyIds);
|
||||
// 执行退回,直接跳转到实际的 targetRealActivityId
|
||||
List<String> realExecutionIds = realExecutions.stream().map(ExecutionEntity::getId).collect(Collectors.toList());
|
||||
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveExecutionsToSingleActivityId(realExecutionIds, targetRealActivityId).changeState();
|
||||
// 目标节点相对当前节点处于并行网关内,需要特殊处理,需要手动生成并行网关汇聚节点(_end)的execution数据
|
||||
if (targetRealSpecialGateway != null) {
|
||||
FlowableUtils.createTargetInSpecialGatewayEndExecutions(commandContext, realExecutions, process, targetInSpecialGatewayList, targetRealSpecialGateway);
|
||||
}
|
||||
return targetRealActivityId;
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.jeecg.modules.bpm.constant.FlowableConstant;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @Description: 串行任务加签
|
||||
* @Author: zyf NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
* @Date: 2022-05-24
|
||||
*/
|
||||
public class SequenceMultiInstanceAddCmd implements Command<Void> {
|
||||
|
||||
/**
|
||||
* 会签人员集合KEY
|
||||
*/
|
||||
private String assigneeListKey;
|
||||
|
||||
|
||||
/**
|
||||
* 任务ID
|
||||
*/
|
||||
private String executionId;
|
||||
|
||||
/**
|
||||
* 加签人员
|
||||
*/
|
||||
private List<String> assignees;
|
||||
|
||||
public SequenceMultiInstanceAddCmd(String executionId, String assigneeListKey, List<String> assignees) {
|
||||
this.executionId = executionId;
|
||||
this.assigneeListKey = assigneeListKey;
|
||||
this.assignees = assignees;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void execute(CommandContext commandContext) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
|
||||
//会签参数是否是字符串类型(逗号分割)
|
||||
boolean isStringVals = false;
|
||||
|
||||
// 查询执行实例
|
||||
ExecutionEntity executionEntity = executionEntityManager.findById(executionId);
|
||||
//多实例任务总数加一
|
||||
Integer nrOfInstances = executionEntity.getVariable(FlowableConstant.NUMBER_OF_INSTANCES, Integer.class);
|
||||
executionEntity.setVariable(FlowableConstant.NUMBER_OF_INSTANCES, nrOfInstances + assignees.size());
|
||||
// 设置流程变量
|
||||
List<String> userIds = null;
|
||||
//兼容当前默认会签配置传递的是,逗号分割的用户账号字符串
|
||||
Object userIdsStr = executionEntity.getVariable(assigneeListKey);
|
||||
if(userIdsStr instanceof String){
|
||||
isStringVals = true;
|
||||
userIds = Arrays.asList(((String)userIdsStr).split(","));
|
||||
}else{
|
||||
userIds = executionEntity.getVariable(assigneeListKey, List.class);
|
||||
isStringVals = false;
|
||||
}
|
||||
List<String> assigneeList = new ArrayList<>();
|
||||
if (ObjectUtil.isNotEmpty(userIds)) {
|
||||
assigneeList.addAll(userIds);
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(assignees)) {
|
||||
assigneeList.addAll(assignees);
|
||||
}
|
||||
Map<String, Object> variables = new HashMap<>(5);
|
||||
if(isStringVals){
|
||||
variables.put(assigneeListKey, String.join(",", assigneeList));
|
||||
}else{
|
||||
variables.put(assigneeListKey, assigneeList);
|
||||
}
|
||||
|
||||
executionEntity.setVariables(variables);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.jeecg.modules.bpm.constant.FlowableConstant;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 串行任务减签
|
||||
* @Author: zyf NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
* @Date: 2022-05-24
|
||||
*/
|
||||
public class SequenceMultiInstanceDeleteCmd implements Command<Void> {
|
||||
|
||||
/**
|
||||
* 当前节点审批人员id
|
||||
*/
|
||||
private String currentUserId;
|
||||
|
||||
/**
|
||||
* 执行id
|
||||
*/
|
||||
private String executionId;
|
||||
|
||||
/**
|
||||
* 会签人员集合KEY
|
||||
*/
|
||||
private String assigneeListKey;
|
||||
|
||||
/**
|
||||
* 减签人员
|
||||
*/
|
||||
private List<String> assignees;
|
||||
|
||||
public SequenceMultiInstanceDeleteCmd(String currentUserId, String executionId, String assigneeListKey, List<String> assignees) {
|
||||
this.currentUserId = currentUserId;
|
||||
this.executionId = executionId;
|
||||
this.assigneeListKey = assigneeListKey;
|
||||
this.assignees = assignees;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void execute(CommandContext commandContext) {
|
||||
//会签参数是否是字符串类型(逗号分割)
|
||||
boolean isStringVals = false;
|
||||
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
|
||||
ExecutionEntity entity = executionEntityManager.findById(executionId);
|
||||
//多实例任务总数加
|
||||
Integer nrOfInstances = entity.getVariable(FlowableConstant.NUMBER_OF_INSTANCES, Integer.class);
|
||||
entity.setVariable(FlowableConstant.NUMBER_OF_INSTANCES, nrOfInstances + assignees.size());
|
||||
// 设置流程变量
|
||||
List<String> userIds = null;
|
||||
//兼容当前默认会签配置传递的是,逗号分割的用户账号字符串
|
||||
Object userIdsStr = entity.getVariable(assigneeListKey);
|
||||
if(userIdsStr instanceof String) {
|
||||
isStringVals = true;
|
||||
userIds = Arrays.asList(((String)userIdsStr).split(","));
|
||||
}else{
|
||||
isStringVals = false;
|
||||
userIds = entity.getVariable(assigneeListKey,List.class);
|
||||
}
|
||||
|
||||
List<String> userIdList = new ArrayList<>();
|
||||
//遍历计算出剩余会签人
|
||||
userIds.forEach(e -> {
|
||||
String userId = assignees.stream().filter(id -> id.equals(e)).findFirst().orElse(null);
|
||||
if (userId == null) {
|
||||
userIdList.add(e);
|
||||
}
|
||||
});
|
||||
//当前任务执行位置
|
||||
int loopCounterIndex = -1;
|
||||
for (int i = 0; i < userIdList.size(); i++) {
|
||||
String userId = userIdList.get(i);
|
||||
if (currentUserId.equals(userId)) {
|
||||
loopCounterIndex = i;
|
||||
}
|
||||
}
|
||||
Map<String, Object> variables = new HashMap<>(5);
|
||||
variables.put(FlowableConstant.NUMBER_OF_INSTANCES, userIdList.size());
|
||||
if(isStringVals){
|
||||
variables.put(assigneeListKey, String.join(",", userIdList));
|
||||
}else{
|
||||
variables.put(assigneeListKey, userIdList);
|
||||
}
|
||||
|
||||
variables.put(FlowableConstant.LOOP_COUNTER, loopCounterIndex);
|
||||
entity.setVariables(variables);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package org.jeecg.modules.bpm.cmd;
|
||||
|
||||
import org.flowable.bpmn.model.Activity;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.FlowableEngineAgenda;
|
||||
import org.flowable.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
|
||||
import org.flowable.engine.impl.history.HistoryManager;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||
import org.flowable.task.service.TaskService;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.modules.bpm.cmd.dto.TaskJumpRequest;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: 任务跳转命令
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-19
|
||||
*/
|
||||
public class TaskJumpCmd implements Command<Void>, Serializable {
|
||||
|
||||
private TaskJumpRequest taskJumpRequest;
|
||||
|
||||
public TaskJumpCmd(TaskJumpRequest taskJumpRequest) {
|
||||
super();
|
||||
this.taskJumpRequest = taskJumpRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void execute(CommandContext commandContext) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
|
||||
// 查询当前任务节点
|
||||
TaskService taskService = CommandContextUtil.getProcessEngineConfiguration().getTaskServiceConfiguration().getTaskService();
|
||||
TaskEntity taskEntity = taskService.getTask(taskJumpRequest.getTaskId());
|
||||
// 查询执行实例
|
||||
ExecutionEntity executionEntity = executionEntityManager.findById(taskEntity.getExecutionId());
|
||||
// 查询流程
|
||||
Process process = ProcessDefinitionUtil.getProcess(taskEntity.getProcessDefinitionId());
|
||||
// 当前任务的key
|
||||
String currentTaskDefinitionKey = taskEntity.getTaskDefinitionKey();
|
||||
|
||||
// 当前任务
|
||||
Activity currentActivity = (Activity) process.getFlowElement(currentTaskDefinitionKey);
|
||||
Object currentBehavior = currentActivity.getBehavior();
|
||||
// 父执行实例
|
||||
ExecutionEntity parentExecutionEntity = executionEntity.getParent();
|
||||
//是否是会签节点
|
||||
if (currentBehavior instanceof MultiInstanceActivityBehavior) {
|
||||
executionEntityManager.deleteChildExecutions(parentExecutionEntity, "", false);
|
||||
// 修改is_mi_root_字段
|
||||
parentExecutionEntity.setMultiInstanceRoot(false);
|
||||
// 修改is_active_
|
||||
parentExecutionEntity.setActive(true);
|
||||
// 需要更新数据
|
||||
executionEntityManager.update(parentExecutionEntity);
|
||||
} else {
|
||||
// 删除跳转前的任务节点
|
||||
taskService.deleteTask(taskEntity, true);
|
||||
HistoryManager historyManager = CommandContextUtil.getHistoryManager();
|
||||
historyManager.recordTaskEnd(taskEntity, executionEntity, "", DateUtils.getDate());
|
||||
historyManager.recordActivityEnd(parentExecutionEntity, "", DateUtils.getDate());
|
||||
}
|
||||
|
||||
//----------------------------执行节点跳转-------------------------------
|
||||
|
||||
// 获取目标节点
|
||||
FlowElement targetFlowElement = process.getFlowElement(taskJumpRequest.getTargetNode());
|
||||
// 指定当前节点为目标节点
|
||||
executionEntity.setCurrentFlowElement(targetFlowElement);
|
||||
|
||||
FlowableEngineAgenda flowableEngineAgenda = CommandContextUtil.getAgenda();
|
||||
|
||||
if (!(currentBehavior instanceof MultiInstanceActivityBehavior)) {
|
||||
flowableEngineAgenda.planContinueProcessInCompensation(executionEntity);
|
||||
} else {
|
||||
// 触发一下,让执行实例往下运行 NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
ExecutionEntity rootExecutionEntity = parentExecutionEntity.getParent();
|
||||
List<ExecutionEntity> executionEntities = executionEntityManager.findChildExecutionsByParentExecutionId(rootExecutionEntity.getId());
|
||||
if (executionEntities.size() > 0) {
|
||||
ExecutionEntity oneExecutionEntity = executionEntities.get(0);
|
||||
oneExecutionEntity.setCurrentFlowElement(targetFlowElement);
|
||||
// 让流程实例运转
|
||||
flowableEngineAgenda.planContinueProcessInCompensation(oneExecutionEntity);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package org.jeecg.modules.bpm.cmd.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description: 动态添加节点
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-26
|
||||
*/
|
||||
@Data
|
||||
public class TaskAddRequest {
|
||||
/**
|
||||
* 流程实例ID
|
||||
*/
|
||||
private String procInsId;
|
||||
/**
|
||||
* 当前任务节点
|
||||
*/
|
||||
private String currentTaskDefKey;
|
||||
|
||||
/**
|
||||
* 添加节点的名字
|
||||
*/
|
||||
private String taskName;
|
||||
/**
|
||||
* 添加节点处理人
|
||||
*/
|
||||
private String assignee;
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package org.jeecg.modules.bpm.cmd.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description: 任务办理请求参数对象
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-10
|
||||
*/
|
||||
@Data
|
||||
public class TaskJumpRequest {
|
||||
|
||||
/**
|
||||
* 流程实例ID
|
||||
*/
|
||||
private String procInsId;
|
||||
|
||||
/**
|
||||
* 当前任务ID
|
||||
*/
|
||||
private String taskId;
|
||||
|
||||
|
||||
/**
|
||||
* 目标任务ID
|
||||
*/
|
||||
private String targetNode;
|
||||
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package org.jeecg.modules.bpm.cmd.util;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @Description: API断言工具类
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-07
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class ApiAssert {
|
||||
|
||||
/**
|
||||
* obj1 eq obj2
|
||||
*
|
||||
* @param obj1
|
||||
* @param obj2
|
||||
* @param info
|
||||
*/
|
||||
public static void eq(String info, Object obj1, Object obj2) {
|
||||
if (!Objects.equals(obj1, obj2)) {
|
||||
failure(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void isTrue(String info, boolean condition) {
|
||||
if (!condition) {
|
||||
failure(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void isFalse(String info, boolean condition) {
|
||||
if (condition) {
|
||||
failure(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void isEmpty(String info, Object obj) {
|
||||
if (ObjectUtils.isNotEmpty(obj)) {
|
||||
failure(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void isNotEmpty(String info, Object obj) {
|
||||
if (ObjectUtils.isEmpty(obj)) {
|
||||
failure(info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败结果
|
||||
*
|
||||
* @param info 错误信息
|
||||
*/
|
||||
public static void failure(String info) {
|
||||
throw new JeecgBootException(info);
|
||||
}
|
||||
}
|
||||
+461
@@ -0,0 +1,461 @@
|
||||
package org.jeecg.modules.bpm.cmd.util;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.impl.delegate.ActivityBehavior;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.constant.FlowableConstant;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @Description: 流程工具类
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-07
|
||||
*/
|
||||
public class FlowableUtils {
|
||||
|
||||
/**
|
||||
* 检测导入文件名是否符合flowable导入规范
|
||||
*
|
||||
* @param fileName
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkImportFileName(String fileName) {
|
||||
boolean check = oConvertUtils.isNotEmpty(fileName) && (fileName.endsWith(".bpmn20.xml") || fileName.endsWith(".bpmn") || fileName.toLowerCase().endsWith(".bar") || fileName.toLowerCase().endsWith(".zip"));
|
||||
if (!check) {
|
||||
ApiAssert.failure("请求文件必须以.bpmn20.xml,.bpmn,.bar,.zip结尾");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测文件是否是BpmnFile
|
||||
*
|
||||
* @param fileName
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBpmnFile(String fileName) {
|
||||
return fileName.endsWith(".bpmn20.xml") || fileName.endsWith(".bpmn");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否可访问
|
||||
*
|
||||
* @param process
|
||||
* @param sourceElement
|
||||
* @param targetElement
|
||||
* @return
|
||||
*/
|
||||
public static boolean isReachable(Process process, FlowNode sourceElement, FlowNode targetElement) {
|
||||
return isReachable(process, sourceElement, targetElement, Sets.newHashSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可访问
|
||||
*
|
||||
* @param process
|
||||
* @param sourceElement
|
||||
* @param targetElement
|
||||
* @param visitedElements
|
||||
* @return
|
||||
*/
|
||||
public static boolean isReachable(Process process, FlowNode sourceElement, FlowNode targetElement,
|
||||
Set<String> visitedElements) {
|
||||
//特殊情况:事件子流程中的启动事件可能作为执行存在,并且最有可能达到目标
|
||||
//当目标位于事件子流程中,但应忽略,因为它们不是“真正的”运行时执行,(而是在等待/触发器)
|
||||
if (sourceElement instanceof StartEvent && isInEventSubprocess(sourceElement)) {
|
||||
return false;
|
||||
}
|
||||
// 没有传出序列流:可能是eg的结束。进程或嵌入式子进程
|
||||
if (sourceElement.getOutgoingFlows().size() == 0) {
|
||||
visitedElements.add(sourceElement.getId());
|
||||
FlowElementsContainer parentElement = process.findParent(sourceElement);
|
||||
if (parentElement instanceof SubProcess) {
|
||||
sourceElement = (SubProcess) parentElement;
|
||||
// 子流程的结束节点,若目标节点在该子流程中,说明无法到达,返回false
|
||||
if (((SubProcess) sourceElement).getFlowElement(targetElement.getId()) != null) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (sourceElement.getId().equals(targetElement.getId())) {
|
||||
return true;
|
||||
}
|
||||
// 为了避免无限循环,我们必须捕获我们访问的每个节点
|
||||
visitedElements.add(sourceElement.getId());
|
||||
// 当前节点能够到达子流程,且目标节点在子流程中,说明可以到达,返回true
|
||||
if (sourceElement instanceof SubProcess
|
||||
&& ((SubProcess) sourceElement).getFlowElement(targetElement.getId()) != null) {
|
||||
return true;
|
||||
}
|
||||
List<SequenceFlow> sequenceFlows = sourceElement.getOutgoingFlows();
|
||||
if (sequenceFlows != null && sequenceFlows.size() > 0) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
String targetRef = sequenceFlow.getTargetRef();
|
||||
FlowNode sequenceFlowTarget = (FlowNode) process.getFlowElement(targetRef, true);
|
||||
if (sequenceFlowTarget != null && !visitedElements.contains(sequenceFlowTarget.getId())) {
|
||||
boolean reachable = isReachable(process, sequenceFlowTarget, targetElement, visitedElements);
|
||||
if (reachable) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是在事件子进程中
|
||||
*
|
||||
* @param flowNode
|
||||
* @return
|
||||
*/
|
||||
protected static boolean isInEventSubprocess(FlowNode flowNode) {
|
||||
FlowElementsContainer flowElementsContainer = flowNode.getParentContainer();
|
||||
while (flowElementsContainer != null) {
|
||||
if (flowElementsContainer instanceof EventSubProcess) {
|
||||
return true;
|
||||
}
|
||||
if (flowElementsContainer instanceof FlowElement) {
|
||||
flowElementsContainer = ((FlowElement) flowElementsContainer).getParentContainer();
|
||||
} else {
|
||||
flowElementsContainer = null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<String> getParentProcessIds(FlowNode flowNode) {
|
||||
List<String> result = new ArrayList<>();
|
||||
FlowElementsContainer flowElementsContainer = flowNode.getParentContainer();
|
||||
while (flowElementsContainer != null) {
|
||||
if (flowElementsContainer instanceof SubProcess) {
|
||||
SubProcess flowElement = (SubProcess) flowElementsContainer;
|
||||
result.add(flowElement.getId());
|
||||
flowElementsContainer = flowElement.getParentContainer();
|
||||
} else if (flowElementsContainer instanceof Process) {
|
||||
Process flowElement = (Process) flowElementsContainer;
|
||||
result.add(flowElement.getId());
|
||||
flowElementsContainer = null;
|
||||
}
|
||||
}
|
||||
// 第一层Process为第0个
|
||||
Collections.reverse(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询不同层级
|
||||
*
|
||||
* @param sourceList
|
||||
* @param targetList
|
||||
* @return 返回不同的层级,如果其中一个层级较深,则返回层级小的+1,从第0层开始,请注意判断是否会出现下标越界异常;返回 -1 表示在同一层
|
||||
*/
|
||||
public static Integer getDiffLevel(List<String> sourceList, List<String> targetList) {
|
||||
if (sourceList == null || sourceList.isEmpty() || targetList == null || targetList.isEmpty()) {
|
||||
throw new FlowableException("sourceList and targetList cannot be empty");
|
||||
}
|
||||
if (sourceList.size() == 1 && targetList.size() == 1) {
|
||||
// 都在第0层且不相等
|
||||
if (!sourceList.get(0).equals(targetList.get(0))) {
|
||||
return 0;
|
||||
} else {// 都在第0层且相等
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int minSize = sourceList.size() < targetList.size() ? sourceList.size() : targetList.size();
|
||||
Integer targetLevel = null;
|
||||
for (int i = 0; i < minSize; i++) {
|
||||
if (!sourceList.get(i).equals(targetList.get(i))) {
|
||||
targetLevel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetLevel == null) {
|
||||
if (sourceList.size() == targetList.size()) {
|
||||
targetLevel = -1;
|
||||
} else {
|
||||
targetLevel = minSize;
|
||||
}
|
||||
}
|
||||
return targetLevel;
|
||||
}
|
||||
|
||||
public static Map<String, Set<String>> getSpecialGatewayElements(FlowElementsContainer container) {
|
||||
return getSpecialGatewayElements(container, null);
|
||||
}
|
||||
|
||||
public static Map<String, Set<String>> getSpecialGatewayElements(FlowElementsContainer container, Map<String, Set<String>> specialGatewayElements) {
|
||||
if (specialGatewayElements == null) {
|
||||
specialGatewayElements = new HashMap<>(16);
|
||||
}
|
||||
Collection<FlowElement> flowelements = container.getFlowElements();
|
||||
for (FlowElement flowElement : flowelements) {
|
||||
boolean isBeginSpecialGateway = flowElement.getId().endsWith(FlowableConstant.SPECIAL_GATEWAY_BEGIN_SUFFIX)
|
||||
&& (flowElement instanceof ParallelGateway || flowElement instanceof InclusiveGateway
|
||||
|| flowElement instanceof ComplexGateway);
|
||||
if (isBeginSpecialGateway) {
|
||||
String gatewayBeginRealId = flowElement.getId();
|
||||
String gatewayId = gatewayBeginRealId.substring(0, gatewayBeginRealId.length() - 6);
|
||||
Set<String> gatewayIdContainFlowelements = specialGatewayElements.computeIfAbsent(gatewayId,
|
||||
k -> new HashSet<>());
|
||||
findElementsBetweenSpecialGateway(flowElement, gatewayId + FlowableConstant.SPECIAL_GATEWAY_END_SUFFIX,
|
||||
gatewayIdContainFlowelements);
|
||||
} else if (flowElement instanceof SubProcess) {
|
||||
getSpecialGatewayElements((SubProcess) flowElement, specialGatewayElements);
|
||||
}
|
||||
}
|
||||
|
||||
// 外层到里层排序
|
||||
Map<String, Set<String>> specialGatewayNodesSort = new LinkedHashMap<>();
|
||||
specialGatewayElements.entrySet().stream().sorted((o1, o2) -> o2.getValue().size() - o1.getValue().size())
|
||||
.forEach(entry -> specialGatewayNodesSort.put(entry.getKey(), entry.getValue()));
|
||||
|
||||
return specialGatewayNodesSort;
|
||||
}
|
||||
|
||||
public static void findElementsBetweenSpecialGateway(FlowElement specialGatewayBegin, String specialGatewayEndId,
|
||||
Set<String> elements) {
|
||||
elements.add(specialGatewayBegin.getId());
|
||||
List<SequenceFlow> sequenceFlows = ((FlowNode) specialGatewayBegin).getOutgoingFlows();
|
||||
if (sequenceFlows != null && sequenceFlows.size() > 0) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||
String targetFlowElementId = targetFlowElement.getId();
|
||||
elements.add(specialGatewayEndId);
|
||||
if (targetFlowElementId.equals(specialGatewayEndId)) {
|
||||
continue;
|
||||
} else {
|
||||
findElementsBetweenSpecialGateway(targetFlowElement, specialGatewayEndId, elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String[] getSourceAndTargetRealActivityId(FlowNode sourceFlowElement, FlowNode targetFlowElement) {
|
||||
// 实际应操作的当前节点ID
|
||||
String sourceRealActivityId = sourceFlowElement.getId();
|
||||
// 实际应操作的目标节点ID
|
||||
String targetRealActivityId = targetFlowElement.getId();
|
||||
List<String> sourceParentProcesss = FlowableUtils.getParentProcessIds(sourceFlowElement);
|
||||
List<String> targetParentProcesss = getParentProcessIds(targetFlowElement);
|
||||
int diffParentLevel = getDiffLevel(sourceParentProcesss, targetParentProcesss);
|
||||
if (diffParentLevel != -1) {
|
||||
sourceRealActivityId = sourceParentProcesss.size() == diffParentLevel ? sourceRealActivityId : sourceParentProcesss.get(diffParentLevel);
|
||||
targetRealActivityId = targetParentProcesss.size() == diffParentLevel ? targetRealActivityId : targetParentProcesss.get(diffParentLevel);
|
||||
}
|
||||
return new String[]{sourceRealActivityId, targetRealActivityId};
|
||||
}
|
||||
|
||||
public static void setSpecialGatewayList(String sourceActivityId, String targetActivityId, Map<String, Set<String>> specialGatewayNodes, List<String> sourceInSpecialGatewayList, List<String> targetInSpecialGatewayList) {
|
||||
for (Map.Entry<String, Set<String>> entry : specialGatewayNodes.entrySet()) {
|
||||
if (entry.getValue().contains(sourceActivityId)) {
|
||||
sourceInSpecialGatewayList.add(entry.getKey());
|
||||
}
|
||||
if (entry.getValue().contains(targetActivityId)) {
|
||||
targetInSpecialGatewayList.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFlowElementMultiInstance(FlowElement flowElement) {
|
||||
if (flowElement instanceof Activity) {
|
||||
return ((Activity) flowElement).getLoopCharacteristics() != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static Optional<String> getFlowElementMultiInstanceParentId(FlowElement flowElement) {
|
||||
FlowElementsContainer parentContainer = flowElement.getParentContainer();
|
||||
while (parentContainer instanceof Activity) {
|
||||
if (isFlowElementMultiInstance((Activity) parentContainer)) {
|
||||
return Optional.of(((Activity) parentContainer).getId());
|
||||
}
|
||||
parentContainer = ((Activity) parentContainer).getParentContainer();
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static boolean isExecutionInsideMultiInstance(ExecutionEntity execution) {
|
||||
return getFlowElementMultiInstanceParentId(execution.getCurrentFlowElement()).isPresent();
|
||||
}
|
||||
|
||||
public static Set<String> getParentExecutionIdsByActivityId(List<ExecutionEntity> executions, String activityId) {
|
||||
List<ExecutionEntity> activityIdExecutions = executions.stream()
|
||||
.filter(e -> activityId.equals(e.getActivityId())).collect(Collectors.toList());
|
||||
if (activityIdExecutions.isEmpty()) {
|
||||
throw new FlowableException("Active execution could not be found with activity id " + activityId);
|
||||
}
|
||||
// check for a multi instance root execution
|
||||
ExecutionEntity miExecution = null;
|
||||
boolean isInsideMultiInstance = false;
|
||||
for (ExecutionEntity possibleMiExecution : activityIdExecutions) {
|
||||
if (possibleMiExecution.isMultiInstanceRoot()) {
|
||||
miExecution = possibleMiExecution;
|
||||
isInsideMultiInstance = true;
|
||||
break;
|
||||
}
|
||||
if (isExecutionInsideMultiInstance(possibleMiExecution)) {
|
||||
isInsideMultiInstance = true;
|
||||
}
|
||||
}
|
||||
Set<String> parentExecutionIds = new HashSet<>();
|
||||
if (isInsideMultiInstance) {
|
||||
Stream<ExecutionEntity> executionEntitiesStream = activityIdExecutions.stream();
|
||||
if (miExecution != null) {
|
||||
executionEntitiesStream = executionEntitiesStream.filter(ExecutionEntity::isMultiInstanceRoot);
|
||||
}
|
||||
executionEntitiesStream.forEach(childExecution -> {
|
||||
parentExecutionIds.add(childExecution.getParentId());
|
||||
});
|
||||
} else {
|
||||
ExecutionEntity execution = activityIdExecutions.iterator().next();
|
||||
parentExecutionIds.add(execution.getParentId());
|
||||
}
|
||||
return parentExecutionIds;
|
||||
}
|
||||
|
||||
|
||||
public static String getParentExecutionIdFromParentIds(ExecutionEntity execution, Set<String> parentExecutionIds) {
|
||||
ExecutionEntity taskParentExecution = execution.getParent();
|
||||
String realParentExecutionId = null;
|
||||
while (taskParentExecution != null) {
|
||||
if (parentExecutionIds.contains(taskParentExecution.getId())) {
|
||||
realParentExecutionId = taskParentExecution.getId();
|
||||
break;
|
||||
}
|
||||
taskParentExecution = taskParentExecution.getParent();
|
||||
}
|
||||
if (realParentExecutionId == null || realParentExecutionId.length() == 0) {
|
||||
throw new FlowableException("Parent execution could not be found with executionId id " + execution.getId());
|
||||
}
|
||||
return realParentExecutionId;
|
||||
}
|
||||
|
||||
public static List<ExecutionEntity> getRealExecutions(CommandContext commandContext, String processInstanceId,
|
||||
String taskExecutionId, String sourceRealActivityId, Set<String> activityIds) {
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
|
||||
ExecutionEntity taskExecution = executionEntityManager.findById(taskExecutionId);
|
||||
List<ExecutionEntity> executions = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstanceId);
|
||||
Set<String> parentExecutionIds = getParentExecutionIdsByActivityId(executions, sourceRealActivityId);
|
||||
String realParentExecutionId = getParentExecutionIdFromParentIds(taskExecution,
|
||||
parentExecutionIds);
|
||||
|
||||
List<ExecutionEntity> childExecutions = executionEntityManager.findExecutionsByParentExecutionAndActivityIds(realParentExecutionId, activityIds);
|
||||
return childExecutions;
|
||||
}
|
||||
|
||||
public static void createTargetInSpecialGatewayEndExecutions(CommandContext commandContext, List<ExecutionEntity> excutionEntitys, Process process, List<String> targetInSpecialGatewayList, String targetRealSpecialGateway) {
|
||||
// 目标节点相对当前节点处于并行网关,需要手动生成并行网关汇聚节点(_end)的execution数据
|
||||
String parentExecutionId = excutionEntitys.iterator().next().getParentId();
|
||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
|
||||
ExecutionEntity parentExecutionEntity = executionEntityManager.findById(parentExecutionId);
|
||||
|
||||
int index = targetInSpecialGatewayList.indexOf(targetRealSpecialGateway);
|
||||
for (; index < targetInSpecialGatewayList.size(); index++) {
|
||||
String targetInSpecialGateway = targetInSpecialGatewayList.get(index);
|
||||
String targetInSpecialGatewayEndId = targetInSpecialGateway + FlowableConstant.SPECIAL_GATEWAY_END_SUFFIX;
|
||||
FlowNode targetInSpecialGatewayEnd = (FlowNode) process.getFlowElement(targetInSpecialGatewayEndId, true);
|
||||
int nbrOfExecutionsToJoin = targetInSpecialGatewayEnd.getIncomingFlows().size();
|
||||
// 处理目标节点所处的分支以外的分支,即 总分枝数-1 = nbrOfExecutionsToJoin - 1
|
||||
for (int i = 0; i < nbrOfExecutionsToJoin - 1; i++) {
|
||||
ExecutionEntity childExecution = executionEntityManager.createChildExecution(parentExecutionEntity);
|
||||
childExecution.setCurrentFlowElement(targetInSpecialGatewayEnd);
|
||||
ActivityBehavior activityBehavior = (ActivityBehavior) targetInSpecialGatewayEnd.getBehavior();
|
||||
activityBehavior.execute(childExecution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* long类型日期转换为x天x时x分格式
|
||||
*
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
* @return
|
||||
*/
|
||||
public static String longTimeToStr(Date startTime, Date endTime) {
|
||||
long start = startTime.getTime();
|
||||
long end = DateUtils.getDate().getTime();
|
||||
if (ObjectUtil.isNotEmpty(endTime)) {
|
||||
end = endTime.getTime();
|
||||
}
|
||||
long mu=end-start;
|
||||
return longTimeToStr(mu);
|
||||
}
|
||||
|
||||
/**
|
||||
* long类型日期转换为x天x时x分格式
|
||||
*
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
public static String longTimeToStr(Long time) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (ObjectUtil.isNotEmpty(time)) {
|
||||
try {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
format.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
|
||||
String dateTime = format.format(time);
|
||||
Date date = format.parse(dateTime);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
Calendar orgin = Calendar.getInstance();
|
||||
orgin.setTimeInMillis(0);
|
||||
int year = calendar.get(Calendar.YEAR) - orgin.get(Calendar.YEAR);
|
||||
int month = calendar.get(Calendar.MONTH) - orgin.get(Calendar.MONTH);
|
||||
int day = calendar.get(Calendar.DATE) - orgin.get(Calendar.DATE);
|
||||
int hour = calendar.get(Calendar.HOUR_OF_DAY) - orgin.get(Calendar.HOUR_OF_DAY);
|
||||
int minute = calendar.get(Calendar.MINUTE) - orgin.get(Calendar.MINUTE);
|
||||
int second = calendar.get(Calendar.SECOND) - orgin.get(Calendar.SECOND);
|
||||
int millisecond = calendar.get(Calendar.MILLISECOND) - orgin.get(Calendar.MILLISECOND);
|
||||
if (year != 0) {
|
||||
builder.append(year).append("年");
|
||||
}
|
||||
if (month != 0) {
|
||||
builder.append(month).append("月");
|
||||
}
|
||||
if (day != 0) {
|
||||
builder.append(day).append("天");
|
||||
}
|
||||
if (hour != 0) {
|
||||
builder.append(Math.abs(hour)).append("小时");
|
||||
}
|
||||
if (minute != 0) {
|
||||
builder.append(minute).append("分");
|
||||
}
|
||||
if (second != 0 && day <= 0) {
|
||||
builder.append(second).append("秒");
|
||||
}
|
||||
if (millisecond != 0 && second <= 0) {
|
||||
builder.append(millisecond).append("毫秒");
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
ApiAssert.failure("格式化日期出错");
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package org.jeecg.modules.bpm.config;
|
||||
|
||||
/**
|
||||
* 项目名称:jeecg
|
||||
* 类名称:Globals
|
||||
* 类描述: 全局变量定义
|
||||
* 创建人:scott
|
||||
* @version
|
||||
*
|
||||
*/
|
||||
public final class BpmGlobals {
|
||||
|
||||
/**
|
||||
* 我发起流程: 根据不同关键词查询不同状态流程
|
||||
* isUnfinished/查询未完成流程
|
||||
* isFinished/查询已完成流程
|
||||
*/
|
||||
public static final String IS_UN_FINISHED = "isUnfinished";
|
||||
public static final String IS_FINISHED = "isFinished";
|
||||
public static final String XX_SIGN_GG = "NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=";
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
//package org.jeecg.modules.bpm.config;
|
||||
//
|
||||
//import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
|
||||
//import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
|
||||
//import org.flowable.spring.SpringProcessEngineConfiguration;
|
||||
//import org.jeecg.modules.bpm.config.flowable.GlobalProcessStartedListener;
|
||||
//import org.jeecg.modules.bpm.config.flowable.GlobalProcistEndListener;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.context.ApplicationListener;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//import org.springframework.context.event.ContextRefreshedEvent;
|
||||
//
|
||||
///**
|
||||
// * @TODO 待实现未用上1
|
||||
// *
|
||||
// * Flowable全局监听配置
|
||||
// * 用途:在任务特殊节点或者流程的特殊节点做一些自定义操作
|
||||
// *
|
||||
// * @author gblfy
|
||||
// * @Date 2022-06-21
|
||||
// **/
|
||||
//@Configuration("flowableGlobListenerConfig")
|
||||
//public class FlowableGlobListenerConfig implements ApplicationListener<ContextRefreshedEvent> {
|
||||
// @Autowired
|
||||
// private SpringProcessEngineConfiguration configuration;
|
||||
// @Autowired
|
||||
// private GlobalProcessStartedListener globalProcessStartedListener;
|
||||
// @Autowired
|
||||
// private GlobalProcistEndListener globalProcistEndListener;
|
||||
//
|
||||
// @Override
|
||||
// public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
// FlowableEventDispatcher dispatcher = configuration.getEventDispatcher();
|
||||
//
|
||||
// //流程开始全局监听
|
||||
// dispatcher.addEventListener(globalProcessStartedListener, FlowableEngineEventType.PROCESS_STARTED);
|
||||
//
|
||||
// //流程结束全局监听
|
||||
// dispatcher.addEventListener(globalProcistEndListener, FlowableEngineEventType.PROCESS_COMPLETED,
|
||||
// FlowableEngineEventType.PROCESS_CANCELLED,
|
||||
// FlowableEngineEventType.PROCESS_COMPLETED_WITH_ERROR_END_EVENT,
|
||||
// FlowableEngineEventType.PROCESS_COMPLETED_WITH_TERMINATE_END_EVENT);
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
package org.jeecg.modules.bpm.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
|
||||
import org.flowable.common.engine.impl.cfg.IdGenerator;
|
||||
import org.flowable.image.ProcessDiagramGenerator;
|
||||
import org.flowable.spring.SpringProcessEngineConfiguration;
|
||||
import org.flowable.spring.boot.EngineConfigurationConfigurer;
|
||||
import org.jeecg.modules.bpm.job.CustomTimeStartJobEventHandler;
|
||||
import org.jeecg.modules.bpm.constant.FlowableConstant;
|
||||
import org.jeecg.modules.bpm.service.impl.image.CustomProcessDiagramGenerator;
|
||||
import org.jeecg.modules.extbpm.listener.global.GlobalEventListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程配置信息
|
||||
* @date 2019/03/06
|
||||
* @author scott
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration("flowableEngineConfiguration")
|
||||
public class ProcessEngineConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
|
||||
@Autowired
|
||||
public DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
|
||||
//------------------------------------------------------------------------
|
||||
// 1.流程图渲染设置
|
||||
springProcessEngineConfiguration.setProcessDiagramGenerator(processDiagramGenerator());
|
||||
//设置流程图字体(防止乱码)
|
||||
springProcessEngineConfiguration.setActivityFontName(FlowableConstant.FONT_NAME);
|
||||
//设置label字体
|
||||
springProcessEngineConfiguration.setLabelFontName(FlowableConstant.FONT_NAME);
|
||||
//设置注释字体
|
||||
springProcessEngineConfiguration.setAnnotationFontName(FlowableConstant.FONT_NAME);
|
||||
//关闭定时任务,有需要再开启 NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
//springProcessEngineConfiguration.setAsyncExecutorActivate(false);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 2.自定义id生成规则
|
||||
springProcessEngineConfiguration.setIdGenerator(new IdGenerator() {
|
||||
@Override
|
||||
public String getNextId() {
|
||||
try {
|
||||
return IdWorker.getIdStr(); //id生成方法
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
//------------------------------------------------------------------------
|
||||
// 3.国产化数据库适配
|
||||
this.setFlowableDataSource(springProcessEngineConfiguration);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 4.全局监听器
|
||||
Map<String, String> handlers = new HashMap<String, String>();
|
||||
List<FlowableEventListener> eventListeners = new ArrayList<FlowableEventListener>();
|
||||
GlobalEventListener global = new GlobalEventListener();
|
||||
global.setHandlers(handlers);
|
||||
eventListeners.add(global);
|
||||
springProcessEngineConfiguration.setEventListeners(eventListeners);
|
||||
|
||||
|
||||
//5.注册自定义作业处理器
|
||||
springProcessEngineConfiguration.addCustomJobHandler(new CustomTimeStartJobEventHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* 国产化数据库适配兼容
|
||||
* @param springProcessEngineConfiguration
|
||||
*/
|
||||
private void setFlowableDataSource(SpringProcessEngineConfiguration springProcessEngineConfiguration){
|
||||
long time1=System.currentTimeMillis();
|
||||
try {
|
||||
Connection connection = dataSource.getConnection();
|
||||
DatabaseMetaData md = connection.getMetaData();
|
||||
String dbType = md.getDatabaseProductName();
|
||||
//log.info("DataSource Customize DbType = " + dbType);
|
||||
//log.info("ProcessEngine databaseType = " + springProcessEngineConfiguration.getDatabaseType());
|
||||
//达梦数据库兼容,采用oracle类型
|
||||
if (dbType.toLowerCase().indexOf("dm") >= 0) {
|
||||
springProcessEngineConfiguration.setDataSource(dataSource);
|
||||
springProcessEngineConfiguration.setDatabaseType("oracle");
|
||||
long time2=System.currentTimeMillis();
|
||||
log.info("ProcessEngine 兼容达梦逻辑耗时:"+(time2-time1)+"ms");
|
||||
}
|
||||
//人大金仓数据库兼容,采用PostgreSQL类型
|
||||
if (dbType.toLowerCase().indexOf("kingbase") >= 0) {
|
||||
springProcessEngineConfiguration.setDataSource(dataSource);
|
||||
springProcessEngineConfiguration.setDatabaseType("postgres");
|
||||
long time2=System.currentTimeMillis();
|
||||
log.info("ProcessEngine 兼容人大金仓逻辑耗时:"+(time2-time1)+"ms");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义流程进度图
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean("customProcessDiagramGenerator")
|
||||
public ProcessDiagramGenerator processDiagramGenerator() {
|
||||
return new CustomProcessDiagramGenerator();
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package org.jeecg.modules.bpm.config.flowable;
|
||||
|
||||
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
|
||||
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
|
||||
import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 全局的流程启动的监听器(有效,但未写逻辑)
|
||||
*
|
||||
* @author: gblfy
|
||||
* @date 2022-06-21
|
||||
*/
|
||||
@Component("globalProcessStartedListener")
|
||||
public class GlobalProcessStartedListener extends AbstractFlowableEngineEventListener {
|
||||
protected Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
protected void processStarted(FlowableProcessStartedEvent event) {
|
||||
// logger.info("进入流程开始监听器------------------------Start---------------------->");
|
||||
|
||||
String eventName = event.getType().name();
|
||||
|
||||
FlowableEntityEventImpl flowableEntityEvent = (FlowableEntityEventImpl) event;
|
||||
ExecutionEntityImpl processInstance = (ExecutionEntityImpl) flowableEntityEvent.getEntity();
|
||||
|
||||
Date startTime = processInstance.getStartTime();
|
||||
String processDefinitionKey = processInstance.getProcessDefinitionKey();
|
||||
String processInstanceId = processInstance.getProcessInstanceId();
|
||||
String processInstanceBusinessKey = processInstance.getProcessInstanceBusinessKey();
|
||||
int suspensionState = processInstance.getSuspensionState();
|
||||
|
||||
// logger.info("流程事件类型->{}", eventName);
|
||||
// logger.info("流程开始时间->{}", startTime);
|
||||
// logger.info("流程定义Key->{}", processDefinitionKey);
|
||||
// logger.info("流程实例ID->{}", processInstanceId);
|
||||
// logger.info("流程业务key->{}", processInstanceBusinessKey);
|
||||
// logger.info("流程是否挂起标志->{}", suspensionState);
|
||||
|
||||
// logger.info("流程开始监听器------------------------End---------------------->");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package org.jeecg.modules.bpm.config.flowable;
|
||||
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
|
||||
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
|
||||
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程结束全局监听器(有效,但未写逻辑)
|
||||
*
|
||||
* @author: gblfy
|
||||
* @date 2022-06-21
|
||||
*/
|
||||
@Component("globalProcistEndListener")
|
||||
public class GlobalProcistEndListener extends AbstractFlowableEngineEventListener {
|
||||
protected Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
protected void processCompleted(FlowableEngineEntityEvent event) {
|
||||
// logger.info("进入流程完成监听器------------------------Start---------------------->");
|
||||
String eventName = event.getType().name();
|
||||
|
||||
FlowableEntityEventImpl flowableEntityEvent = (FlowableEntityEventImpl) event;
|
||||
ExecutionEntityImpl processInstance = (ExecutionEntityImpl) flowableEntityEvent.getEntity();
|
||||
|
||||
Date startTime = processInstance.getStartTime();
|
||||
String processDefinitionKey = processInstance.getProcessDefinitionKey();
|
||||
String processInstanceId = processInstance.getProcessInstanceId();
|
||||
String processInstanceBusinessKey = processInstance.getProcessInstanceBusinessKey();
|
||||
int suspensionState = processInstance.getSuspensionState();
|
||||
|
||||
|
||||
// logger.info("流程事件类型->{}", eventName);
|
||||
// logger.info("流程开始时间->{}", startTime);
|
||||
// logger.info("流程定义Key->{}", processDefinitionKey);
|
||||
// logger.info("流程实例ID->{}", processInstanceId);
|
||||
// logger.info("流程业务key->{}", processInstanceBusinessKey);
|
||||
// logger.info("流程是否挂起标志->{}", suspensionState);
|
||||
|
||||
// logger.info("流程完成监听器------------------------End---------------------->");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package org.jeecg.modules.bpm.constant;
|
||||
|
||||
/**
|
||||
* @Description: 流程常量定义
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-05
|
||||
*/
|
||||
public final class FlowableConstant {
|
||||
//TODO 待测试
|
||||
public final static String SPECIAL_GATEWAY_BEGIN_SUFFIX = "_begin";
|
||||
//TODO 待测试
|
||||
public final static String SPECIAL_GATEWAY_END_SUFFIX = "_end";
|
||||
|
||||
/**
|
||||
* 流程图字体
|
||||
*/
|
||||
public static final String FONT_NAME = "宋体";
|
||||
|
||||
/**
|
||||
* 会签任务总数
|
||||
*/
|
||||
public static final String NUMBER_OF_INSTANCES = "nrOfInstances";
|
||||
|
||||
/**
|
||||
* 【自定义变量:串行会签人员集合】
|
||||
* 简流模式支持选固定会签人员,进行加减签
|
||||
*/
|
||||
public static final String LOOP_ASSIGNEE_COLLECTION = "loopAssigneeCollection";
|
||||
|
||||
/**
|
||||
* 正在执行的会签总数
|
||||
*/
|
||||
public static final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
|
||||
|
||||
/**
|
||||
* 已完成的会签任务总数
|
||||
*/
|
||||
public static final String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
|
||||
|
||||
|
||||
/**
|
||||
* 循环的索引值,可以使用elementIndexVariable属性修改loopCounter的变量名 NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
*/
|
||||
public static final String LOOP_COUNTER = "loopCounter";
|
||||
|
||||
|
||||
//后加签
|
||||
public static final String AFTER_ADDSIGN = "after";
|
||||
//前加签
|
||||
public static final String BEFORE_ADDSIGN = "before";
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package org.jeecg.modules.bpm.constant.enums;
|
||||
|
||||
/**
|
||||
* @TODO 待实现未用上1
|
||||
*
|
||||
* @Description: 业务状态
|
||||
* @Author: zyf
|
||||
* @Date: 2022-06-31
|
||||
*/
|
||||
public enum BusinessStatusEnum {
|
||||
|
||||
/**
|
||||
* 枚举字段
|
||||
*/
|
||||
NOTSUBMIT("1", "待提交"), PROCESSING("2", "处理中"), FINISH("3", "已完成"), DELETE("4", "已作废"), SUSPEND("5", "已挂起");
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String statusName;
|
||||
|
||||
public static String getStatusName(String status) {
|
||||
for (BusinessStatusEnum e : BusinessStatusEnum.values()) {
|
||||
if (e.status.equals(status)) {
|
||||
return e.statusName;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
BusinessStatusEnum(String status, String statusName) {
|
||||
this.status = status;
|
||||
this.statusName = statusName;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package org.jeecg.modules.bpm.constant.enums;
|
||||
|
||||
/**
|
||||
* @TODO 待实现未用上1
|
||||
*
|
||||
* @author : scott
|
||||
* @title: : CommentTypeEnum
|
||||
* @projectName : flowable
|
||||
* @description: 审批意见的类型
|
||||
* @date : 2019/11/2412:53
|
||||
*/
|
||||
public enum CommentTypeEnum {
|
||||
SP("审批"),
|
||||
BH("驳回"),
|
||||
CH("撤回"),
|
||||
ZC("暂存"),
|
||||
QS("签收"),
|
||||
WP("委派"),
|
||||
ZH("知会"),
|
||||
ZY("转阅"),
|
||||
YY("已阅"),
|
||||
ZB("转办"),
|
||||
QJQ("前加签"),
|
||||
HJQ("后加签"),
|
||||
XTZX("系统执行"),
|
||||
TJ("提交"),
|
||||
CXTJ("重新提交"),
|
||||
SPJS("审批结束"),
|
||||
LCZZ("流程终止"),
|
||||
SQ("授权"),
|
||||
CFTG("重复跳过"),
|
||||
XT("协同"),
|
||||
PS("评审");
|
||||
private String name;//名称
|
||||
|
||||
/**
|
||||
* 通过type获取Msg
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
* @Description:
|
||||
*/
|
||||
public static String getEnumMsgByType(String type) {
|
||||
for (CommentTypeEnum e : CommentTypeEnum.values()) {
|
||||
if (e.toString().equals(type)) {
|
||||
return e.name;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
private CommentTypeEnum(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
//package org.jeecg.modules.bpm.controller;
|
||||
//
|
||||
//import java.util.Arrays;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import javax.servlet.http.HttpServletRequest;
|
||||
//import javax.servlet.http.HttpServletResponse;
|
||||
//
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.activiti.engine.repository.Model;
|
||||
//import org.jeecg.common.api.vo.Result;
|
||||
//import org.jeecg.common.util.oConvertUtils;
|
||||
//import org.jeecg.modules.bpm.dto.ModelDTO;
|
||||
//import org.jeecg.modules.bpm.service.impl.ActModelService;
|
||||
//import org.jeecg.modules.extbpm.util.CommonRandomUtil;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
//import org.springframework.web.bind.annotation.GetMapping;
|
||||
//import org.springframework.web.bind.annotation.PathVariable;
|
||||
//import org.springframework.web.bind.annotation.RequestBody;
|
||||
//import org.springframework.web.bind.annotation.RequestMapping;
|
||||
//import org.springframework.web.bind.annotation.RequestParam;
|
||||
//import org.springframework.web.bind.annotation.RestController;
|
||||
//
|
||||
//import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
//
|
||||
//import springfox.documentation.annotations.ApiIgnore;
|
||||
//
|
||||
///**
|
||||
// * 流程设计管理
|
||||
// *
|
||||
// * @author scott
|
||||
// * @date 2019/03/06
|
||||
// * @desc
|
||||
// */
|
||||
//@Slf4j
|
||||
//@RestController("act/model")
|
||||
//@RequestMapping("/act/model")
|
||||
//public class ActModelController {
|
||||
// @Autowired
|
||||
// private ActModelService actModelService;
|
||||
//
|
||||
// /**
|
||||
// * 流程设计模型列表
|
||||
// * @param params
|
||||
// * @return
|
||||
// */
|
||||
// @GetMapping("list")
|
||||
// public Result<IPage<Model>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||
// Result<IPage<Model>> result = new Result<IPage<Model>>();
|
||||
// IPage<Model> pageList = new Page<Model>();
|
||||
// List<Model> records = actModelService.page(params);
|
||||
// pageList.setRecords(records);
|
||||
// result.setSuccess(true);
|
||||
// result.setResult(pageList);
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 创建模型
|
||||
// */
|
||||
// @RequestMapping("/create")
|
||||
// public Result<String> create(@RequestBody ModelDTO dto, HttpServletRequest request, HttpServletResponse response) {
|
||||
// Result<String> result = new Result<String>();
|
||||
// try {
|
||||
// String modelId = actModelService.save(dto.getName(), dto.getKey(), dto.getDescription());
|
||||
// result.setResult(modelId);
|
||||
// //response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + modelId);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// log.error("新建流程失败!");
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 流程发布
|
||||
// * @param id
|
||||
// * @return
|
||||
// */
|
||||
// @GetMapping("deploy/{id}")
|
||||
// public Result deploy(@PathVariable("id") String id) {
|
||||
// actModelService.deploy(id);
|
||||
// return Result.ok("流程发布成功");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 流程导出
|
||||
// * @param id
|
||||
// * @param response
|
||||
// * @return
|
||||
// */
|
||||
// @GetMapping("export/{id}")
|
||||
// public Result<Object> export(@PathVariable("id") String id, @Parameter(hidden = true) HttpServletResponse response) {
|
||||
// try {
|
||||
// actModelService.export(id, response);
|
||||
// return Result.ok("导出成功!");
|
||||
// } catch (Exception e) {
|
||||
// return Result.error("导出失败:"+e.toString());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 删除流程设计模型
|
||||
// * @param ids
|
||||
// * @return
|
||||
// */
|
||||
// @DeleteMapping(value = "/delete")
|
||||
// public Result delete(@RequestParam(name = "ids", required = true) String ids) {
|
||||
// if(CommonRandomUtil.isNotEmpty(ids)) {
|
||||
// for (String id : Arrays.asList(ids.split(","))) {
|
||||
// actModelService.delete(id);
|
||||
// }
|
||||
// }
|
||||
// return Result.ok("流程删除成功");
|
||||
// }
|
||||
//}
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
package org.jeecg.modules.bpm.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.TokenUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.service.impl.ActProcessService;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.jeecg.modules.extbpm.util.CommonRandomUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* 流程管理功能
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
@Slf4j
|
||||
@Tag(name="流程实例")
|
||||
@RestController("actProcessController")
|
||||
@RequestMapping("/act/process")
|
||||
public class ActProcessController {
|
||||
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private ActProcessService actProcessService;
|
||||
@Autowired
|
||||
private IExtActProcessService extActProcessService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
@Autowired
|
||||
@Lazy
|
||||
private RedisUtil redisUtil;
|
||||
/**
|
||||
* 查询所有版本的流程
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("list")
|
||||
public Result<IPage<Map<String, Object>>> list(@RequestParam Map<String, Object> params) {
|
||||
Result<IPage<Map<String, Object>>> result = new Result<IPage<Map<String, Object>>>();
|
||||
IPage<Map<String, Object>> pageList = new Page<Map<String, Object>>();
|
||||
List<Map<String, Object>> records = actProcessService.page(params);
|
||||
pageList.setRecords(records);
|
||||
result.setSuccess(true);
|
||||
result.setResult(pageList);
|
||||
return result;
|
||||
}
|
||||
|
||||
@PostMapping("deploy")
|
||||
@Operation(summary = "部署流程文件")
|
||||
public Result deploy(@RequestParam("processFile") MultipartFile file) throws IOException {
|
||||
if (file.isEmpty()) {
|
||||
return Result.error("发布流程失败!");
|
||||
}
|
||||
|
||||
try {
|
||||
actProcessService.deploy(file);
|
||||
return Result.ok("流程上传成功!");
|
||||
} catch (Exception e) {
|
||||
return Result.error("发布流程失败: "+ e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活流程
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("active/{id}")
|
||||
public Result active(@PathVariable("id") String id) {
|
||||
actProcessService.active(id);
|
||||
return new Result();
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起流程
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("suspend/{id}")
|
||||
@Operation(summary="挂起流程")
|
||||
@Parameter(name = "id", description = "流程ID")
|
||||
public Result suspend(@PathVariable("id") String id) {
|
||||
actProcessService.suspend(id);
|
||||
return new Result();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 关闭流程
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("close/{key}")
|
||||
@Operation(summary="关闭流程")
|
||||
@Parameter(name = "key", description = "流程key")
|
||||
public Result close(@PathVariable("key") String key) {
|
||||
actProcessService.closeProcess(key);
|
||||
return new Result();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动流程
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("open/{key}")
|
||||
@Operation(summary="启动流程")
|
||||
@Parameter(name = "key", description = "流程key")
|
||||
public Result open(@PathVariable("key") String key) {
|
||||
actProcessService.openProcess(key);
|
||||
return new Result();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param deploymentIds
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result delete(@RequestParam(name = "ids", required = true) String ids) {
|
||||
if(CommonRandomUtil.isNotEmpty(ids)) {
|
||||
for (String id : Arrays.asList(ids.split(","))) {
|
||||
actProcessService.deleteDeployment(id);
|
||||
}
|
||||
}
|
||||
return new Result();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示静态资源(图片/XML)
|
||||
* @param deploymentId
|
||||
* @param resourceName
|
||||
* @param response
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping(value = "resource")
|
||||
public void resource(@RequestParam(value="deploymentId")String deploymentId, @RequestParam(value="resourceName")String resourceName, @Parameter(hidden = true) HttpServletResponse response) throws Exception {
|
||||
log.debug("-------------deploymentId-----",deploymentId);
|
||||
log.debug("-------------resourceName-----",resourceName);
|
||||
InputStream resourceAsStream = actProcessService.getResourceAsStream(deploymentId, resourceName);
|
||||
IOUtils.copy(resourceAsStream, response.getOutputStream());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取流程进度图
|
||||
* @param processInstanceId
|
||||
* @param response
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping(value = "processPic")
|
||||
public void processPic(@RequestParam(value="processInstanceId")String processInstanceId, HttpServletResponse response) throws Exception {
|
||||
actProcessService.genProcessDiagram(response, processInstanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取资源,通过部署ID
|
||||
*
|
||||
* @param deploymentId 流程部署的ID
|
||||
* @param resourceName 资源名称(foo.xml|foo.png)
|
||||
* @param response
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping(value = "downProcessXml")
|
||||
public void downProcessXmlByDeploy(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
InputStream resourceAsStream = null;
|
||||
try {
|
||||
String deploymentId = oConvertUtils.getString(request.getParameter("deploymentId"));
|
||||
String resourceName = oConvertUtils.getString(request.getParameter("resourceName"));
|
||||
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
//校验 token 登录有效性
|
||||
TokenUtils.verifyToken(request, sysBaseAPI, redisUtil);
|
||||
|
||||
resourceAsStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
|
||||
// 文件下载
|
||||
File file = new File(resourceName);
|
||||
String filename = file.getName();
|
||||
// 设置response的Header
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setHeader("Content-disposition", "attachment;filename="+ new String(filename.getBytes("utf-8"), "ISO8859-1"));
|
||||
IOUtils.copy(resourceAsStream, response.getOutputStream());
|
||||
response.flushBuffer();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (resourceAsStream != null) {
|
||||
resourceAsStream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO 未实现
|
||||
* 通过上传流程文件,发布流程
|
||||
*
|
||||
* @param deploymentId 流程部署的ID
|
||||
* @param resourceName 资源名称(foo.xml|foo.png)
|
||||
* @param response
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping(value = "deployProcess")
|
||||
@ResponseBody
|
||||
public void deployProcess(HttpServletRequest request) {
|
||||
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
|
||||
Map<String, MultipartFile> files = multipartRequest.getFileMap();
|
||||
|
||||
List<String> urls = new ArrayList<>();
|
||||
for (Map.Entry<String, MultipartFile> entry : files.entrySet()) {
|
||||
MultipartFile file = entry.getValue();// 获取上传文件对象
|
||||
String fileName = file.getOriginalFilename();
|
||||
InputStream fileInputStream = null;
|
||||
try {
|
||||
fileInputStream = file.getInputStream();
|
||||
String extension = FilenameUtils.getExtension(fileName);
|
||||
if (extension.equals("zip") || extension.equals("bar")) {
|
||||
ZipInputStream zip = new ZipInputStream(fileInputStream);
|
||||
repositoryService.createDeployment().addZipInputStream(zip).deploy();
|
||||
zip.close();
|
||||
} else if (extension.equals("png")) {
|
||||
repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
|
||||
} else if (extension.indexOf("bpmn20.xml") != -1) {
|
||||
repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
|
||||
} else if (extension.equals("bpmn")) {
|
||||
/*
|
||||
* bpmn扩展名特殊处理,转换为bpmn20.xml
|
||||
*/
|
||||
String baseName = FilenameUtils.getBaseName(fileName);
|
||||
repositoryService.createDeployment().addInputStream(baseName + ".bpmn20.xml", fileInputStream).deploy();
|
||||
} else {
|
||||
throw new FlowableException("错误信息:不支改文件类型" + extension);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("错误信息:在部署过程中,文件输入流异常" + e.toString());
|
||||
} finally {
|
||||
try {
|
||||
if (fileInputStream != null) {
|
||||
fileInputStream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+476
@@ -0,0 +1,476 @@
|
||||
package org.jeecg.modules.bpm.controller;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstanceQuery;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.flowable.task.api.DelegationState;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.dto.BatchSuspendInfo;
|
||||
import org.jeecg.modules.bpm.dto.ProcessInstHisDTO;
|
||||
import org.jeecg.modules.bpm.dto.SuspendInfo;
|
||||
import org.jeecg.modules.bpm.service.ActivitiService;
|
||||
import org.jeecg.modules.bpm.service.impl.SuperTaskService;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActFlowData;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActFlowDataService;
|
||||
import org.jeecg.modules.extbpm.util.CommonRandomUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 流程实例管理功能
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController("actProcessInstanceController")
|
||||
@RequestMapping("/act/processInstance")
|
||||
public class ActProcessInstanceController {
|
||||
private final String START_USER_ID = CommonRandomUtil.trim("startUserId");
|
||||
private final String PROCESS_INSTANCE_ID = CommonRandomUtil.trim("processInstanceId");
|
||||
|
||||
@Autowired
|
||||
protected RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private ActivitiService activitiService;
|
||||
@Autowired
|
||||
private SuperTaskService superTaskService;
|
||||
@Autowired
|
||||
private IExtActFlowDataService extActFlowDataService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
|
||||
/**
|
||||
* 运行中流程实例数据
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
|
||||
@GetMapping(value = "/list")
|
||||
public Result<IPage<ProcessInstHisDTO>> listRunning(HttpServletRequest request) {
|
||||
Result<IPage<ProcessInstHisDTO>> result = new Result<IPage<ProcessInstHisDTO>>();
|
||||
IPage<ProcessInstHisDTO> pageList = new Page<ProcessInstHisDTO>();
|
||||
|
||||
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
|
||||
if (CommonRandomUtil.isNotEmpty(request.getParameter(START_USER_ID))) {
|
||||
historicProcessInstanceQuery = historicProcessInstanceQuery.startedBy(request.getParameter(START_USER_ID));
|
||||
}
|
||||
if (CommonRandomUtil.isNotEmpty(request.getParameter(PROCESS_INSTANCE_ID))) {
|
||||
historicProcessInstanceQuery = historicProcessInstanceQuery.processInstanceId(request.getParameter(PROCESS_INSTANCE_ID));
|
||||
}
|
||||
|
||||
String startTimeBegin = request.getParameter("startTime_begin");// 时间开始
|
||||
String startTimeEnd = request.getParameter("startTime_end");// 时间结束
|
||||
if (CommonRandomUtil.isNotEmpty(startTimeBegin)) {
|
||||
try {
|
||||
historicProcessInstanceQuery.startedAfter(DateUtils.parseDate(startTimeBegin, "yyyy-MM-dd"));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (CommonRandomUtil.isNotEmpty(startTimeEnd)) {
|
||||
try {
|
||||
historicProcessInstanceQuery.startedBefore(DateUtils.parseDate(startTimeEnd, "yyyy-MM-dd"));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
String endtimeBegin = request.getParameter("endTime_begin");// 时间开始
|
||||
String endtimeEnd = request.getParameter("endTime_end");// 时间结束
|
||||
if (CommonRandomUtil.isNotEmpty(endtimeBegin)) {
|
||||
try {
|
||||
historicProcessInstanceQuery.finishedAfter(DateUtils.parseDate(endtimeBegin, "yyyy-MM-dd"));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (CommonRandomUtil.isNotEmpty(endtimeEnd)) {
|
||||
try {
|
||||
historicProcessInstanceQuery.finishedBefore(DateUtils.parseDate(endtimeEnd, "yyyy-MM-dd"));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//改造treegrid
|
||||
// 分页参数
|
||||
Integer pageNo = oConvertUtils.getInt(request.getParameter("pageNo"),1);
|
||||
Integer pageSize = oConvertUtils.getInt(request.getParameter("pageSize"),10);
|
||||
Integer start = (pageNo - 1) * pageSize;
|
||||
//Integer end = page * rows - 1;
|
||||
List<HistoricProcessInstance> list = historicProcessInstanceQuery.unfinished().orderByProcessInstanceStartTime().desc().listPage(start, pageSize);
|
||||
long count = historicProcessInstanceQuery.unfinished().count();
|
||||
List<ProcessInstHisDTO> records = new ArrayList<ProcessInstHisDTO>();
|
||||
ProcessInstHisDTO processInstHisDTO = null;
|
||||
for (HistoricProcessInstance hi : list) {
|
||||
String starttime = DateFormatUtils.format(hi.getStartTime(), "yyyy-MM-dd HH:mm:ss");
|
||||
String endtime = hi.getEndTime() == null ? "" : DateFormatUtils.format(hi.getEndTime(), "yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
long totalTimes = hi.getEndTime() == null ? (Calendar.getInstance().getTimeInMillis() - hi.getStartTime().getTime()) : (hi.getEndTime().getTime() - hi.getStartTime().getTime());
|
||||
|
||||
long dayCount = totalTimes / (1000 * 60 * 60 * 24);// 计算天
|
||||
long restTimes = totalTimes % (1000 * 60 * 60 * 24);// 剩下的时间用于计于小时
|
||||
long hourCount = restTimes / (1000 * 60 * 60);// 小时
|
||||
restTimes = restTimes % (1000 * 60 * 60);
|
||||
long minuteCount = restTimes / (1000 * 60);
|
||||
|
||||
String spendTimes = dayCount + "天" + hourCount + "小时" + minuteCount + "分";
|
||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(hi.getProcessDefinitionId()).singleResult();
|
||||
log.debug("spendTimes:" + spendTimes);
|
||||
|
||||
String isSuspended = "finished";
|
||||
String activityName = "";// 当前任务名称
|
||||
String activityUser = "";// 当前任务签收人
|
||||
String taskId = "";// 任务ID
|
||||
if (hi.getEndTime() == null) {
|
||||
// endtime为空表示流程实例未结束
|
||||
// 增加业务标题
|
||||
String bpmBizTitle = this.activitiService.getHisVarinst(WorkFlowGlobals.BPM_BIZ_TITLE, hi.getId());
|
||||
bpmBizTitle = oConvertUtils.isEmpty(bpmBizTitle)?processDefinition.getName():bpmBizTitle;
|
||||
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(hi.getId()).singleResult();
|
||||
List<Task> tasks = taskService.createTaskQuery().processInstanceId(hi.getId()).list();
|
||||
if (tasks.size() > 1) {
|
||||
// 针对会签或者一个流程多个分支任务(一个流程实例,同时存在多个任务情况),流程实例报错处理--------------------
|
||||
isSuspended = "" + pi.isSuspended();
|
||||
activityName = CommonRandomUtil.trimToEmpty(tasks.get(0).getName());
|
||||
activityUser = CommonRandomUtil.trimToEmpty(tasks.get(0).getAssignee());
|
||||
taskId = oConvertUtils.getString(tasks.get(0).getId());
|
||||
processInstHisDTO = new ProcessInstHisDTO();
|
||||
processInstHisDTO.setId(hi.getId());
|
||||
processInstHisDTO.setBpmBizTitle(bpmBizTitle);
|
||||
processInstHisDTO.setParentId("");
|
||||
processInstHisDTO.setTaskId(taskId);
|
||||
processInstHisDTO.setName(activityName);
|
||||
processInstHisDTO.setAssignee("");
|
||||
processInstHisDTO.setPrcocessDefinitionName(processDefinition.getName());
|
||||
processInstHisDTO.setStartUserId(hi.getStartUserId());
|
||||
if(oConvertUtils.isNotEmpty(processInstHisDTO.getStartUserId())) {
|
||||
LoginUser sysUser = sysBaseAPI.getUserByName(processInstHisDTO.getStartUserId());
|
||||
processInstHisDTO.setStartUserName(sysUser.getRealname());
|
||||
}
|
||||
processInstHisDTO.setStartTime(starttime);
|
||||
processInstHisDTO.setEndTime(endtime);
|
||||
processInstHisDTO.setSpendTimes(spendTimes);
|
||||
processInstHisDTO.setIsSuspended(isSuspended);
|
||||
processInstHisDTO.setProcessDefinitionId(hi.getProcessDefinitionId());
|
||||
processInstHisDTO.setProcessInstanceId(hi.getId());
|
||||
int i = 1;
|
||||
List<ProcessInstHisDTO> childrens = new ArrayList<ProcessInstHisDTO>();
|
||||
ProcessInstHisDTO children = null;
|
||||
for (Task task : tasks) {
|
||||
isSuspended = "" + pi.isSuspended();
|
||||
activityName = CommonRandomUtil.trimToEmpty(task.getName());
|
||||
activityUser = CommonRandomUtil.trimToEmpty(task.getAssignee());
|
||||
taskId = oConvertUtils.getString(task.getId());
|
||||
children = new ProcessInstHisDTO();
|
||||
children.setId(hi.getId() + ":" + (i++));
|
||||
children.setBpmBizTitle(bpmBizTitle);
|
||||
children.setParentId(hi.getId());
|
||||
children.setTaskId(taskId);
|
||||
children.setName(activityName);
|
||||
children.setAssignee(activityUser);
|
||||
if(oConvertUtils.isNotEmpty(children.getAssignee())) {
|
||||
LoginUser sysUser = sysBaseAPI.getUserByName(children.getAssignee());
|
||||
children.setAssigneeName(sysUser!=null?sysUser.getRealname():children.getAssignee());
|
||||
}
|
||||
children.setPrcocessDefinitionName(processDefinition.getName());
|
||||
children.setStartUserId(hi.getStartUserId());
|
||||
if(oConvertUtils.isNotEmpty(children.getStartUserId())) {
|
||||
LoginUser sysUser = sysBaseAPI.getUserByName(children.getStartUserId());
|
||||
children.setStartUserName(sysUser.getRealname());
|
||||
}
|
||||
children.setStartTime(starttime);
|
||||
children.setEndTime(endtime);
|
||||
children.setSpendTimes(spendTimes);
|
||||
children.setIsSuspended(isSuspended);
|
||||
children.setProcessDefinitionId(hi.getProcessDefinitionId());
|
||||
children.setProcessInstanceId(hi.getId());
|
||||
childrens.add(children);
|
||||
}
|
||||
processInstHisDTO.setChildren(childrens);
|
||||
records.add(processInstHisDTO);
|
||||
} else {
|
||||
for (Task task : tasks) {
|
||||
isSuspended = "" + pi.isSuspended();
|
||||
activityName = CommonRandomUtil.trimToEmpty(task.getName());
|
||||
activityUser = CommonRandomUtil.trimToEmpty(task.getAssignee());
|
||||
taskId = oConvertUtils.getString(task.getId());
|
||||
processInstHisDTO = new ProcessInstHisDTO();
|
||||
processInstHisDTO.setId(hi.getId());
|
||||
processInstHisDTO.setBpmBizTitle(bpmBizTitle);
|
||||
processInstHisDTO.setParentId("");
|
||||
processInstHisDTO.setTaskId(taskId);
|
||||
processInstHisDTO.setName(activityName);
|
||||
// NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
processInstHisDTO.setAssignee(activityUser);
|
||||
if(oConvertUtils.isNotEmpty(processInstHisDTO.getAssignee())) {
|
||||
LoginUser sysUser = sysBaseAPI.getUserByName(processInstHisDTO.getAssignee());
|
||||
processInstHisDTO.setAssigneeName(sysUser!=null?sysUser.getRealname():processInstHisDTO.getAssignee());
|
||||
}
|
||||
processInstHisDTO.setPrcocessDefinitionName(processDefinition.getName());
|
||||
processInstHisDTO.setStartUserId(hi.getStartUserId());
|
||||
if(oConvertUtils.isNotEmpty(processInstHisDTO.getStartUserId())) {
|
||||
LoginUser sysUser = sysBaseAPI.getUserByName(processInstHisDTO.getStartUserId());
|
||||
processInstHisDTO.setStartUserName(sysUser!=null?sysUser.getRealname():processInstHisDTO.getStartUserId());
|
||||
}
|
||||
processInstHisDTO.setStartTime(starttime);
|
||||
processInstHisDTO.setEndTime(endtime);
|
||||
processInstHisDTO.setSpendTimes(spendTimes);
|
||||
processInstHisDTO.setIsSuspended(isSuspended);
|
||||
processInstHisDTO.setProcessDefinitionId(hi.getProcessDefinitionId());
|
||||
processInstHisDTO.setProcessInstanceId(hi.getId());
|
||||
records.add(processInstHisDTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pageList.setRecords(records);
|
||||
|
||||
log.debug(" count : " + count);
|
||||
pageList.setTotal(count);
|
||||
result.setSuccess(true);
|
||||
result.setResult(pageList);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 进行委派操作
|
||||
* @param processInstanceId 流程部署ID
|
||||
*/
|
||||
@GetMapping(value = "reassign")
|
||||
public Result reassign(@RequestParam("taskId") String taskId, @RequestParam("userName") String assignUserId,HttpServletRequest request) {
|
||||
Task task = activitiService.getTask(taskId);
|
||||
//去掉最后面的逗号
|
||||
if(oConvertUtils.isNotEmpty(assignUserId) && assignUserId.endsWith(",")) {
|
||||
assignUserId = assignUserId.substring(0, assignUserId.length() -1);
|
||||
}
|
||||
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
|
||||
taskService.setOwner(task.getId(), sysUser.getUsername());
|
||||
//TODO 委派给多个人好使吗?
|
||||
taskService.setAssignee(task.getId(), assignUserId);
|
||||
return Result.ok("委派成功!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 暂停正在运行的流程实例
|
||||
* @param processInstanceId 流程实例ID
|
||||
*/
|
||||
@GetMapping(value = "suspend")
|
||||
public Result suspend(@RequestParam("processInstanceId") String processInstanceId, HttpServletRequest request) {
|
||||
activitiService.suspend(processInstanceId);
|
||||
return Result.ok("挂起成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动暂停的流程实例
|
||||
* @param processInstanceId 流程实例ID
|
||||
*/
|
||||
@GetMapping(value = "restart")
|
||||
public Result restart(@RequestParam("processInstanceId") String processInstanceId, HttpServletRequest request) {
|
||||
activitiService.restart(processInstanceId);
|
||||
return Result.ok("启动成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停正在运行的流程实例(批量处理)
|
||||
*/
|
||||
@PostMapping(value = "batchSuspend")
|
||||
public Result<BatchSuspendInfo> batchSuspend(@RequestBody BatchSuspendInfo batchSuspendInfo, HttpServletRequest request) {
|
||||
Result<BatchSuspendInfo> result = new Result<BatchSuspendInfo>();
|
||||
List<SuspendInfo> data = batchSuspendInfo.getData();
|
||||
if(data==null||data.size()<=0) {
|
||||
result.error500("请选择数据");
|
||||
return result;
|
||||
}
|
||||
int sucessCount = 0;
|
||||
for(SuspendInfo info :data) {
|
||||
try {
|
||||
LambdaQueryWrapper<ExtActFlowData> queryWrapper = new LambdaQueryWrapper<ExtActFlowData>();
|
||||
queryWrapper.eq(ExtActFlowData::getFormDataId, info.getDataId());
|
||||
queryWrapper.eq(ExtActFlowData::getRelationCode, info.getFlowCode());
|
||||
ExtActFlowData extActFlowData = extActFlowDataService.getOne(queryWrapper);
|
||||
if(extActFlowData!=null) {
|
||||
info.setProcInstId(extActFlowData.getProcessInstId());
|
||||
activitiService.suspend(extActFlowData.getProcessInstId());
|
||||
info.setStatus("1");//处理成功
|
||||
sucessCount++;
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
info.setStatus("0");//处理失败
|
||||
}
|
||||
batchSuspendInfo.setData(data);
|
||||
batchSuspendInfo.setSucessCount(sucessCount);
|
||||
result.setResult(batchSuspendInfo);
|
||||
result.success("处理完成!");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动暂停的流程实例(批量处理)
|
||||
*/
|
||||
@PostMapping(value = "batchRestart")
|
||||
public Result<BatchSuspendInfo> batchRestart(@RequestBody BatchSuspendInfo batchSuspendInfo, HttpServletRequest request) {
|
||||
Result<BatchSuspendInfo> result = new Result<BatchSuspendInfo>();
|
||||
List<SuspendInfo> data = batchSuspendInfo.getData();
|
||||
if(data==null||data.size()<=0) {
|
||||
result.error500("请选择数据");
|
||||
return result;
|
||||
}
|
||||
int sucessCount = 0;
|
||||
for(SuspendInfo info :data) {
|
||||
try {
|
||||
LambdaQueryWrapper<ExtActFlowData> queryWrapper = new LambdaQueryWrapper<ExtActFlowData>();
|
||||
queryWrapper.eq(ExtActFlowData::getFormDataId, info.getDataId());
|
||||
queryWrapper.eq(ExtActFlowData::getRelationCode, info.getFlowCode());
|
||||
ExtActFlowData extActFlowData = extActFlowDataService.getOne(queryWrapper);
|
||||
if(extActFlowData!=null) {
|
||||
info.setProcInstId(extActFlowData.getProcessInstId());
|
||||
activitiService.restart(extActFlowData.getProcessInstId());
|
||||
info.setStatus("1");//处理成功
|
||||
sucessCount++;
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
info.setStatus("0");//处理失败
|
||||
}
|
||||
batchSuspendInfo.setData(data);
|
||||
batchSuspendInfo.setSucessCount(sucessCount);
|
||||
result.setResult(batchSuspendInfo);
|
||||
result.success("处理完成!");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 作废运行中的流程实例
|
||||
* @param processInstanceId 流程实例ID
|
||||
*/
|
||||
@GetMapping(value = "close")
|
||||
public Result close(@RequestParam("processInstanceId") String processInstanceId, HttpServletRequest request) {
|
||||
//JTC-853 流程实例中被关闭,提示作废成功,但是我的工单列表显示状态是 完成
|
||||
runtimeService.setVariable(processInstanceId, WorkFlowGlobals.BPM_STATUS, WorkFlowGlobals.PROCESS_INVALIDPROCESS_STATUS);
|
||||
runtimeService.deleteProcessInstance(processInstanceId, "作废流程");
|
||||
return Result.ok("作废成功!");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 跳转到某个节点
|
||||
* @param taskId 当前节点
|
||||
* @param skipNode 跳转到那个节点
|
||||
* @param request
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping(value = "skipNode")
|
||||
public Result skipNode(@RequestParam("taskId") String taskId, @RequestParam("skipTaskNode") String skipNode,HttpServletRequest request) throws Exception {
|
||||
//TODO 流程变量参数
|
||||
//Map<String, Object> map = var.getVariableMap(processHandle.getTpProcesspros());
|
||||
//判断是否是委托任务,被委托人先解决委托
|
||||
Task task=taskService.createTaskQuery().taskId(taskId).active().singleResult();
|
||||
if (org.apache.commons.lang.StringUtil.isNotBlank(task.getOwner())) {
|
||||
DelegationState delegationState = task.getDelegationState();
|
||||
switch (delegationState) {
|
||||
case PENDING:
|
||||
taskService.resolveTask(taskId);
|
||||
break;
|
||||
case RESOLVED:
|
||||
//委托任务已经完成
|
||||
break;
|
||||
|
||||
default:
|
||||
//不是委托任务
|
||||
break;
|
||||
}
|
||||
}
|
||||
if("end".equals(skipNode)){
|
||||
superTaskService.endProcess(taskId);
|
||||
}else{
|
||||
superTaskService.goProcessTaskNode(taskId,skipNode);
|
||||
}
|
||||
return Result.ok("跳转成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过当前taskId获取所有的流程任务节点
|
||||
* @param taskId 当前节点
|
||||
* @param request
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping(value = "getAllTask")
|
||||
public Result getAllTask(@RequestParam("taskId") String taskId,HttpServletRequest request) throws Exception {
|
||||
List<Map> ls = activitiService.getAllTaskNode(taskId);
|
||||
List<Map> list = new ArrayList<Map>();
|
||||
for(Map map :ls) {
|
||||
String taskKey = (String)map.get("taskKey");
|
||||
String name = (String)map.get("name");
|
||||
//author:scott date:20220118 for:JTC-1044【工作流】流程实例 跳转 有空节点
|
||||
if(taskKey==null
|
||||
||name == null
|
||||
||taskKey.startsWith("exclusiveGateway")
|
||||
||taskKey.startsWith("parallelGateway")
|
||||
||taskKey.startsWith("callSubProcess")
|
||||
||taskKey.startsWith("Gateway_")
|
||||
||taskKey.startsWith("Start_")
|
||||
||taskKey.startsWith("End_")
|
||||
||taskKey.startsWith("Start")
|
||||
||taskKey.startsWith("end")
|
||||
||taskKey.startsWith("start1")) {
|
||||
continue;
|
||||
}
|
||||
list.add(map);
|
||||
}
|
||||
return Result.ok(list);
|
||||
}
|
||||
|
||||
}
|
||||
+1633
File diff suppressed because it is too large
Load Diff
+1
@@ -0,0 +1 @@
|
||||
package org.jeecg.modules.bpm.dto;␍␍import java.util.Date;␍import lombok.Data;␍␍␍@Data␍public class ActHiActinstDTO implements java.io.Serializable {␍ private static final long serialVersionUID = 1L;␍ ␍ /**␍ *␍ */␍ private String id;␍ /**␍ *␍ */␍ private String procDefId;␍ /**␍ *␍ */␍ private String procInstId;␍ /**␍ *␍ */␍ private String executionId;␍ /**␍ *␍ */␍ private String actId;␍ /**␍ *␍ */␍ private String taskId;␍ /**␍ *␍ */␍ private String callProcInstId;␍ /**␍ *␍ */␍ private String actName;␍ /**␍ *␍ */␍ private String actType;␍ /**␍ *␍ */␍ private String assignee;␍ /**␍ *␍ */␍ private Date startTime;␍ /**␍ *␍ */␍ private Date endTime;␍ /**␍ *␍ */␍ private Long duration;␍ /**␍ *␍ */␍ private String tenantId;␍ ␍}␍␍
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description: 运行时超时任务
|
||||
* @author: scott
|
||||
* @date: 2020年04月21日 19:59
|
||||
*/
|
||||
@Data
|
||||
public class ActRuTaskDTO {
|
||||
private Date createTime;
|
||||
private String id;
|
||||
private String name;
|
||||
private String assignee;
|
||||
private String owner;
|
||||
private String procInstId;
|
||||
private String executionId;
|
||||
private Integer nodeTimeout;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 抄送任务
|
||||
*/
|
||||
@Data
|
||||
public class ActTaskCcDTO {
|
||||
private String procDefId;
|
||||
private String taskDefKey;
|
||||
private String procInstId;
|
||||
private String executionId;
|
||||
private String taskName;
|
||||
}
|
||||
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 动态加任务节点用(流程图跟踪变)
|
||||
*
|
||||
* @author : scott
|
||||
* @title: : AddSignTaskVo
|
||||
* @projectName : flowable
|
||||
* @description: 加签Vo
|
||||
* @date : 2022-12-02
|
||||
*/
|
||||
public class AddSignTaskVo {
|
||||
/**
|
||||
* 任务id 必填
|
||||
*/
|
||||
private String currentTaskId;
|
||||
/**
|
||||
* 被加签人
|
||||
*/
|
||||
private List<String> signUserIds;
|
||||
/**
|
||||
* 操作人code 必填
|
||||
*/
|
||||
private String userCode;
|
||||
/**
|
||||
* 意见
|
||||
*/
|
||||
private String reason;
|
||||
|
||||
public String getCurrentTaskId() {
|
||||
return currentTaskId;
|
||||
}
|
||||
|
||||
public void setCurrentTaskId(String currentTaskId) {
|
||||
this.currentTaskId = currentTaskId;
|
||||
}
|
||||
|
||||
public List<String> getSignUserIds() {
|
||||
return signUserIds;
|
||||
}
|
||||
|
||||
public void setSignUserIds(List<String> signUserIds) {
|
||||
this.signUserIds = signUserIds;
|
||||
}
|
||||
|
||||
public String getUserCode() {
|
||||
return userCode;
|
||||
}
|
||||
|
||||
public void setUserCode(String userCode) {
|
||||
this.userCode = userCode;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public void setReason(String reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BatchSuspendInfo implements java.io.Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 批量挂起业务参数
|
||||
*/
|
||||
private List<SuspendInfo> data;
|
||||
|
||||
/**
|
||||
* 处理成功的个数
|
||||
*/
|
||||
private int sucessCount;
|
||||
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import org.jeecg.modules.bpm.constant.enums.CommentTypeEnum;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: Bruce.liu
|
||||
* @Since:19:24 2019/11/24
|
||||
* 爱拼才会赢 2019 ~ 2030 版权所有
|
||||
*/
|
||||
public class CommentVo implements Serializable {
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
protected String taskId;
|
||||
/**
|
||||
* 添加人
|
||||
*/
|
||||
protected String userId;
|
||||
/**
|
||||
* 用户的名称
|
||||
*/
|
||||
protected String userName;
|
||||
/**
|
||||
* 用户的头像链接
|
||||
*/
|
||||
protected String userUrl;
|
||||
/**
|
||||
* 流程实例id
|
||||
*/
|
||||
protected String processInstanceId;
|
||||
/**
|
||||
* 意见信息
|
||||
*/
|
||||
protected String message;
|
||||
/**
|
||||
* 时间
|
||||
*/
|
||||
protected Date time;
|
||||
/**
|
||||
* @see org.jeecg.modules.bpm.constant.enums.CommentTypeEnum
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 类型名称
|
||||
*/
|
||||
private String typeName;
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
/**
|
||||
* 评论全信息
|
||||
*/
|
||||
private String fullMsg;
|
||||
public CommentVo(){}
|
||||
public CommentVo(String userId, String processInstanceId, String type, String message) {
|
||||
this.userId = userId;
|
||||
this.processInstanceId = processInstanceId;
|
||||
this.message = message;
|
||||
this.type = type;
|
||||
}
|
||||
public CommentVo(String taskId, String userId, String processInstanceId, String type, String message) {
|
||||
this.taskId = taskId;
|
||||
this.userId = userId;
|
||||
this.processInstanceId = processInstanceId;
|
||||
this.message = message;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public void setTaskId(String taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserUrl() {
|
||||
return userUrl;
|
||||
}
|
||||
|
||||
public void setUserUrl(String userUrl) {
|
||||
this.userUrl = userUrl;
|
||||
}
|
||||
|
||||
public String getProcessInstanceId() {
|
||||
return processInstanceId;
|
||||
}
|
||||
|
||||
public void setProcessInstanceId(String processInstanceId) {
|
||||
this.processInstanceId = processInstanceId;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
this.typeName = CommentTypeEnum.getEnumMsgByType(type);
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public void setTypeName(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public String getFullMsg() {
|
||||
return fullMsg;
|
||||
}
|
||||
|
||||
public void setFullMsg(String fullMsg) {
|
||||
this.fullMsg = fullMsg;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description: 流程节点信息
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-05
|
||||
*/
|
||||
@Data
|
||||
public class FlowNodeDto {
|
||||
/**
|
||||
* 节点id
|
||||
*/
|
||||
private String nodeId;
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
/**
|
||||
* 执行人的id
|
||||
*/
|
||||
private String userId;
|
||||
/**
|
||||
* 执行人姓名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 任务节点结束时间
|
||||
*/
|
||||
private Date endTime;
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 模型
|
||||
*
|
||||
* @author scott
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@Schema(description="模型")
|
||||
public class ModelDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "模型名称")
|
||||
@NotBlank(message="{model.name.require}")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "模型标识")
|
||||
@NotBlank(message="{model.key.require}")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "模型描述")
|
||||
private String description;
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: 多实例加签减签操作请求参数
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-24
|
||||
*/
|
||||
@Data
|
||||
public class MultiInstanceRequestDto {
|
||||
|
||||
/**
|
||||
* 任务节点id
|
||||
*/
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 会签赋值表达式 KEY
|
||||
*
|
||||
* - 简流模式参数值:loopAssigneeCollection —— FlowableConstant.LOOP_ASSIGNEE_COLLECTION
|
||||
* - 低代码模式参数值:assigneeUserIdList —— WorkFlowGlobals.ASSIGNEE_USER_ID_LIST
|
||||
*/
|
||||
private String assigneeListKey;
|
||||
|
||||
/**
|
||||
* 加签/减签 人员
|
||||
*/
|
||||
private List<String> assignees;
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 会签节点信息
|
||||
*
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-25
|
||||
*/
|
||||
@Data
|
||||
public class MultiInstanceResponseDto {
|
||||
/**
|
||||
* 会签类型
|
||||
*/
|
||||
private Object type;
|
||||
|
||||
/**
|
||||
* 是否串行
|
||||
*/
|
||||
private Boolean isSequential;
|
||||
|
||||
/**
|
||||
* 会签人员KEY
|
||||
*/
|
||||
private String assignee;
|
||||
|
||||
/**
|
||||
* 会签人员集合KEY
|
||||
*/
|
||||
private String assigneeList;
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.Data;
|
||||
import org.jeecg.modules.bpm.util.BpmUtil;
|
||||
|
||||
@Data
|
||||
public class ProcessHisDTO implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
/** 名称*/
|
||||
private String name;
|
||||
/** 流程实例ID */
|
||||
private String processInstanceId;
|
||||
/** 流程定义id */
|
||||
private String processDefinitionId;
|
||||
/** 流程定义名称 */
|
||||
private String prcocessDefinitionName;
|
||||
/** 开始时间 */
|
||||
private String startTime;
|
||||
/** 结束时间 */
|
||||
private String endTime;
|
||||
|
||||
/** 正在处理的节点 —— 负责人 */
|
||||
private String owner;
|
||||
private String assignee;
|
||||
/** 正在处理的节点 —— 负责人昵称 */
|
||||
private String assigneeName;
|
||||
/** 正在处理的节点 —— 负责人头像 */
|
||||
private String assigneeAvatar;
|
||||
/** 正在处理的节点 */
|
||||
private String currentTaskKey;
|
||||
private String currentTaskName;
|
||||
|
||||
/** 处理结果 */
|
||||
private String deleteReason;
|
||||
/** 流程发起人 */
|
||||
private String startUserId;
|
||||
private String startUserName;
|
||||
/** 流程发起人 - 头像*/
|
||||
private String startUserAvatar;
|
||||
/** 耗时 */
|
||||
private String spendTimes;
|
||||
/** 标题 */
|
||||
private String bpmBizTitle;
|
||||
/** 流程状态 */
|
||||
private String bpmStatus;
|
||||
//--update--begin------author:scott-----date:20220705-----for:【VUEN-1334】流程高级配置支持通知设置和控制撤回、催办权限-----
|
||||
/**是否允许催办1是0否*/
|
||||
private String urgeStatus;
|
||||
/**是否允许取回流程1是0否*/
|
||||
private String backStatus;
|
||||
/**是否允许查看流程图1是0否*/
|
||||
private String graphicStatus;
|
||||
/**是否启用自动提交流程1是0否*/
|
||||
private String autoSubmitStatus;
|
||||
/**通知类型(多个会以逗号隔开)*/
|
||||
private String notifyWay;
|
||||
//--update--end------author:scott-----date:20220705-----for:【VUEN-1334】流程高级配置支持通知设置和控制撤回、催办权限-----
|
||||
|
||||
//--update--begin------author:scott-----date:20230107-----for:【QQYUN-3618】待办流程列表增加字段【应用名称】【表单名称】---
|
||||
/** 应用名称*/
|
||||
private String lowAppName;
|
||||
/** 应用下表单名称*/
|
||||
private String lowFormName;
|
||||
//--update--end------author:scott-----date:20230107-----for:【QQYUN-3618】待办流程列表增加字段【应用名称】【表单名称】---
|
||||
|
||||
/** 审批意见*/
|
||||
private String remarks;
|
||||
/** 任务耗时*/
|
||||
private Long taskDueTime;
|
||||
|
||||
public String getDurationStr(){
|
||||
try {
|
||||
if(this.taskDueTime == null) {
|
||||
return null;
|
||||
}
|
||||
return BpmUtil.dealTimeFromNum(this.taskDueTime);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ProcessInstHisDTO implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
/** 名称*/
|
||||
private String name;
|
||||
/** 父id*/
|
||||
private String parentId;
|
||||
/** 流程实例ID */
|
||||
private String processInstanceId;
|
||||
/** 流程定义id */
|
||||
private String processDefinitionId;
|
||||
/** 流程定义名称 */
|
||||
private String prcocessDefinitionName;
|
||||
/** 开始时间 */
|
||||
private String startTime;
|
||||
/** 结束时间 */
|
||||
private String endTime;
|
||||
/** 任务id */
|
||||
private String taskId;
|
||||
/** 负责人 */
|
||||
private String assignee;
|
||||
private String assigneeName;
|
||||
/** 处理结果 */
|
||||
private String deleteReason;
|
||||
/** 流程发起人 */
|
||||
private String startUserId;
|
||||
private String startUserName;
|
||||
/** 耗时 */
|
||||
private String spendTimes;
|
||||
/** 标题 */
|
||||
private String bpmBizTitle;
|
||||
/** 状态 */
|
||||
private String isSuspended;
|
||||
/** 子节点 */
|
||||
private List<ProcessInstHisDTO> children;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description: 统计流程的每个类型的数量
|
||||
* @author: scott
|
||||
* @date: 2023年01月09日 12:06
|
||||
*/
|
||||
@Data
|
||||
public class StartTypeStatisticsDto {
|
||||
/**
|
||||
* 流程开始节点,启动类型
|
||||
*/
|
||||
private String startType;
|
||||
/**
|
||||
* 个数
|
||||
*/
|
||||
private Integer count;
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SuspendInfo implements java.io.Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 业务单据id
|
||||
*/
|
||||
private String dataId;
|
||||
/**
|
||||
* 流程关联唯一编码
|
||||
*/
|
||||
private String flowCode;
|
||||
/**
|
||||
* 业务标题
|
||||
*/
|
||||
private String bizTitle;
|
||||
/**
|
||||
* 流程实例id
|
||||
*/
|
||||
private String procInstId;
|
||||
/**
|
||||
* 处理状态
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.jeecg.modules.bpm.util.BpmUtil;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TaskDTO implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String id;
|
||||
/** 任务名*/
|
||||
private String taskName;
|
||||
/** 任务ID*/
|
||||
private String taskId;
|
||||
/** 任务办理人 - 用户名*/
|
||||
private String taskAssigneeName;
|
||||
/** 任务办理人 - 用户ID*/
|
||||
private String taskAssigneeId;
|
||||
/** 任务办理人 - 头像*/
|
||||
private String taskAssigneeAvatar;
|
||||
|
||||
/** 任务开始时间*/
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date taskBeginTime;
|
||||
/** 任务结束时间*/
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date taskEndTime;
|
||||
/** 任务耗时*/
|
||||
private Long taskDueTime;
|
||||
|
||||
/** 流程发起人,用户名*/
|
||||
private String processApplyUserName;
|
||||
/** 流程发起人,头像*/
|
||||
private String processApplyUserAvatar;
|
||||
|
||||
/** 流程发起人,用户ID*/
|
||||
private String processApplyUserId;
|
||||
/** 流程编号*/
|
||||
private String processDefinitionId;
|
||||
/** 流程名称*/
|
||||
private String processDefinitionName;
|
||||
/** 流程实例ID*/
|
||||
private String processInstanceId;
|
||||
/** 流程结束时间*/
|
||||
private Date processEndTime;
|
||||
/** 流程取消原因*/
|
||||
private String processDeleteReason;
|
||||
|
||||
|
||||
/** 业务标题*/
|
||||
private String bpmBizTitle;
|
||||
/** 流程状态 未发起、处理中、处理完成*/
|
||||
private String bpmStatus;
|
||||
/** 超时提醒*/
|
||||
private Boolean taskTimeoutWarn;
|
||||
/** 是否催办*/
|
||||
private Boolean taskUrge;
|
||||
/** 催办说明*/
|
||||
private String taskUrgeRemark;
|
||||
|
||||
/** 意见*/
|
||||
private String remarks;
|
||||
|
||||
//--update--begin------author:scott-----date:20230107-----for:【QQYUN-3618】待办流程列表增加字段【应用名称】【表单名称】---
|
||||
/** 应用名称*/
|
||||
private String lowAppName;
|
||||
/** 应用下表单名称*/
|
||||
private String lowFormName;
|
||||
//--update--end------author:scott-----date:20230107-----for:【QQYUN-3618】待办流程列表增加字段【应用名称】【表单名称】---
|
||||
|
||||
public String getDurationStr(){
|
||||
try {
|
||||
if(this.taskDueTime == null) {
|
||||
return null;
|
||||
}
|
||||
return BpmUtil.dealTimeFromNum(this.taskDueTime);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package org.jeecg.modules.bpm.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
/**
|
||||
* @Description: 用户代理人设置
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2019-04-17
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Data
|
||||
public class UserAgentDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**序号*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private java.lang.String id;
|
||||
/**用户名*/
|
||||
@Excel(name = "用户名", width = 15)
|
||||
private java.lang.String userName;
|
||||
/**代理人用户名*/
|
||||
@Excel(name = "代理人用户名", width = 15)
|
||||
private java.lang.String agentUserName;
|
||||
/**代理开始时间*/
|
||||
@Excel(name = "代理开始时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private java.util.Date startTime;
|
||||
/**代理结束时间*/
|
||||
@Excel(name = "代理结束时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private java.util.Date endTime;
|
||||
/**状态0无效1有效*/
|
||||
@Excel(name = "状态0无效1有效", width = 15)
|
||||
private java.lang.String status;
|
||||
/**创建人名称*/
|
||||
@Excel(name = "创建人名称", width = 15)
|
||||
private java.lang.String createName;
|
||||
/**创建人登录名称*/
|
||||
@Excel(name = "创建人登录名称", width = 15)
|
||||
private java.lang.String createBy;
|
||||
/**创建日期*/
|
||||
@Excel(name = "创建日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private java.util.Date createTime;
|
||||
/**更新人名称*/
|
||||
@Excel(name = "更新人名称", width = 15)
|
||||
private java.lang.String updateName;
|
||||
/**更新人登录名称*/
|
||||
@Excel(name = "更新人登录名称", width = 15)
|
||||
private java.lang.String updateBy;
|
||||
/**更新日期*/
|
||||
@Excel(name = "更新日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private java.util.Date updateTime;
|
||||
/**所属部门*/
|
||||
@Excel(name = "所属部门", width = 15)
|
||||
private java.lang.String sysOrgCode;
|
||||
/**所属公司*/
|
||||
@Excel(name = "所属公司", width = 15)
|
||||
private java.lang.String sysCompanyCode;
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
package org.jeecg.modules.bpm.job;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.delegate.event.impl.FlowableEventBuilder;
|
||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||
import org.flowable.engine.impl.cmd.StartProcessInstanceCmd;
|
||||
import org.flowable.engine.impl.jobexecutor.TimerEventHandler;
|
||||
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||
import org.flowable.engine.impl.util.ProcessInstanceHelper;
|
||||
import org.flowable.job.service.JobHandler;
|
||||
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
||||
import org.flowable.variable.api.delegate.VariableScope;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActFormDataService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 自定义定时作业的个性化处理器
|
||||
*/
|
||||
@Slf4j
|
||||
@Component("customTimeStartJobEventHandler")
|
||||
public class CustomTimeStartJobEventHandler extends TimerEventHandler implements JobHandler {
|
||||
public static final String TYPE = "timer-start-event-custom";
|
||||
private IExtActFormDataService extActFormDataService;
|
||||
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "timer-start-event-custom";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
||||
log.info("============执行自定义 定时启动流程 处理器============");
|
||||
log.info("定时任务详情 = {}", JSON.toJSONString(job));
|
||||
if (extActFormDataService == null) {
|
||||
extActFormDataService = SpringContextUtils.getBean(IExtActFormDataService.class);
|
||||
}
|
||||
|
||||
String jobHandlerConfigStr = job.getJobHandlerConfiguration();
|
||||
//获取自定义的定时启动,流程参数
|
||||
JSONObject jobHandlerConfig = JSONObject.parseObject(jobHandlerConfigStr);
|
||||
|
||||
ProcessDefinitionEntity processDefinitionEntity = ProcessDefinitionUtil.getProcessDefinitionFromDatabase(job.getProcessDefinitionId());
|
||||
if (processDefinitionEntity == null) {
|
||||
throw new FlowableException("Could not find process definition needed for timer start event");
|
||||
} else {
|
||||
try {
|
||||
if (!processDefinitionEntity.isSuspended()) {
|
||||
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
||||
if (eventDispatcher != null && eventDispatcher.isEnabled()) {
|
||||
eventDispatcher.dispatchEvent(FlowableEventBuilder.createEntityEvent(FlowableEngineEventType.TIMER_FIRED, job), processEngineConfiguration.getEngineCfgKey());
|
||||
}
|
||||
|
||||
Process process = ProcessDefinitionUtil.getProcess(job.getProcessDefinitionId());
|
||||
String activityId = TimerEventHandler.getActivityIdFromConfiguration(configuration);
|
||||
if (activityId != null) {
|
||||
FlowElement flowElement = process.getFlowElement(activityId, true);
|
||||
if (flowElement == null) {
|
||||
throw new FlowableException("Could not find matching FlowElement for activityId " + activityId);
|
||||
}
|
||||
ProcessInstanceHelper processInstanceHelper = processEngineConfiguration.getProcessInstanceHelper();
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
//设置流程发起所需要的流程变量
|
||||
String formKey = oConvertUtils.getString(jobHandlerConfig.get(WorkFlowGlobals.BPM_FORM_KEY));
|
||||
String dataId = oConvertUtils.getString(jobHandlerConfig.get(WorkFlowGlobals.BPM_DATA_ID));
|
||||
Map<String, Object> params = extActFormDataService.getJsonDataById(formKey, dataId);
|
||||
log.debug("---日期定时启动器,加载初始化数据:{}", params);
|
||||
|
||||
if (params == null) {
|
||||
params = new HashMap<String, Object>();
|
||||
params.put(WorkFlowGlobals.BPM_DES_DATA_ID, dataId);
|
||||
params.put(WorkFlowGlobals.BPM_DES_FORM_CODE, formKey);
|
||||
}
|
||||
|
||||
params.put(WorkFlowGlobals.BPM_DES_DATA_ID, dataId);
|
||||
params.put(WorkFlowGlobals.BPM_DES_FORM_CODE, formKey);
|
||||
params.put(WorkFlowGlobals.BPM_DATA_ID, dataId);
|
||||
params.put(WorkFlowGlobals.BPM_FORM_TYPE, "2");
|
||||
params.put(WorkFlowGlobals.BPM_FORM_KEY, formKey);
|
||||
String url = "{{DOMAIN_URL}}/desform/detail/" + formKey + "/"+dataId+"?token={{TOKEN}}&taskId={{TASKID}}";
|
||||
String mobileUrl = "{{DOMAIN_URL}}/desform/detail/" + formKey + "/"+dataId+"?token={{TOKEN}}&taskId={{TASKID}}";
|
||||
params.put(WorkFlowGlobals.BPM_FORM_CONTENT_URL, url);
|
||||
params.put(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE, mobileUrl);
|
||||
params.put(WorkFlowGlobals.APPLY_USER_ID, jobHandlerConfig.get(WorkFlowGlobals.APPLY_USER_ID));
|
||||
//----------------------------------------------------------------------------------------------
|
||||
//flowable升级 6.7.2 => 6.8.0
|
||||
//processInstanceHelper.createAndStartProcessInstanceWithInitialFlowElement(processDefinitionEntity, (String) null, (String) null, (String) null, flowElement, process, params, (Map) null , true);
|
||||
processInstanceHelper.createAndStartProcessInstanceWithInitialFlowElement(processDefinitionEntity, (String) null, (String) null, (String) null, flowElement, process, params, (Map) null, null, null, true);
|
||||
} else {
|
||||
(new StartProcessInstanceCmd(processDefinitionEntity.getKey(), (String) null, (String) null, (Map) null, job.getTenantId())).execute(commandContext);
|
||||
}
|
||||
} else {
|
||||
log.debug("ignoring timer of suspended process definition {}", processDefinitionEntity.getName());
|
||||
}
|
||||
|
||||
} catch (RuntimeException var12) {
|
||||
log.error("exception during timer execution", var12);
|
||||
throw var12;
|
||||
} catch (Exception var13) {
|
||||
log.error("exception during timer execution", var13);
|
||||
throw new FlowableException("exception during timer execution: " + var13.getMessage(), var13);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
package org.jeecg.modules.bpm.mapper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.flowable.idm.api.User;
|
||||
import org.jeecg.modules.bpm.dto.*;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
public interface ActivitiMapper extends BaseMapper {
|
||||
|
||||
|
||||
/**
|
||||
* 根据历史执行ID,查询变量内容
|
||||
* @param proid EXECUTION_ID_
|
||||
* @param name NAME_
|
||||
* @return
|
||||
*/
|
||||
@Select("select TEXT_ from act_hi_varinst where NAME_= #{name} and EXECUTION_ID_= #{proid}")
|
||||
String getHisVarinst(@Param("name")String name,@Param("proid") String proid);
|
||||
|
||||
|
||||
// /**
|
||||
// * 通过业务标题,去流程变量里模糊匹配出 流程实例list
|
||||
// * @param text text
|
||||
// * @return
|
||||
// */
|
||||
// List<String> getHisVarinstProids(@Param("text") String text);
|
||||
|
||||
/**
|
||||
* 通过业务标题,去流程变量里模糊匹配出 流程实例list
|
||||
* @param text text
|
||||
* @return
|
||||
*/
|
||||
List<String> getHisVarinstProidsWithIn(@Param("text") String text, @Param("procInstIdList") List<String> getHisVarinstProidsWithIn);
|
||||
|
||||
/**
|
||||
* 获取流程的启动和结束时间
|
||||
* @param name
|
||||
* @param proid
|
||||
* @return
|
||||
*/
|
||||
/*
|
||||
* @Select("select * from act_hi_actinst where EXECUTION_ID_=#{proid} and ACT_TYPE_ in ('startEvent','endEvent')"
|
||||
* )
|
||||
*
|
||||
* @ResultType(Map.class) List<Map<String,Object>> getActHiActinst(String
|
||||
* proid);
|
||||
*/
|
||||
|
||||
/**
|
||||
* 指定下一步操作人
|
||||
* @param proInsId
|
||||
* @param taskDefKey
|
||||
* @param nextUser
|
||||
*/
|
||||
@Select("select ID_ from act_ru_task where PROC_INST_ID_= #{proInsId} and TASK_DEF_KEY_= #{taskDefKey} order by CREATE_TIME_")
|
||||
List<String> getTaskIdByProins(@Param("proInsId")String proInsId,@Param("taskDefKey")String taskDefKey);
|
||||
|
||||
|
||||
List<TaskDTO> getHistoryTasks(Page page,@Param("userName") String userName,
|
||||
@Param("processDefinitionId") String processDefinitionId,
|
||||
@Param("processDefinitionName") String processDefinitionName,
|
||||
@Param("procInstIdList") List<String> procInstIdList,
|
||||
@Param("processKeyList") List<String> processKeyList);
|
||||
|
||||
|
||||
List<TaskDTO> getAllHistoryTasks(Page page,@Param("processDefinitionId") String processDefinitionId,
|
||||
@Param("processDefinitionName") String processDefinitionName);
|
||||
|
||||
|
||||
List<TaskDTO> getAllCcHistoryTasks(Page page,@Param("ccUserName") String ccUserName,
|
||||
@Param("processDefinitionId") String processDefinitionId,
|
||||
@Param("processDefinitionName") String processDefinitionName,
|
||||
@Param("executionIdList") List<String> executionIdList,
|
||||
@Param("processInstanceIds") List<String> processInstanceIds,
|
||||
@Param("processKeyList") List<String> processKeyList);
|
||||
|
||||
/**
|
||||
* 查询流程的历史任务节点
|
||||
* @param proceInsId
|
||||
* @return
|
||||
*/
|
||||
//@Select("select DISTINCT TASK_DEF_KEY_,NAME_ from act_hi_taskinst where PROC_INST_ID_= #{proceInsId} and DELETE_REASON_ ='completed'")
|
||||
@Select("select DISTINCT TASK_DEF_KEY_,NAME_ from act_hi_taskinst where PROC_INST_ID_= #{proceInsId} AND END_TIME_ is not null")
|
||||
List<Map<String,Object>> getHistTaskNodeList(@Param("proceInsId") String proceInsId);
|
||||
|
||||
/**
|
||||
* 获取流程的启动和结束时间
|
||||
* @param proceInsId
|
||||
* @return
|
||||
*/
|
||||
List<ActHiActinstDTO> getActHiActinstStartAndEnd(@Param("proceInsId") String proceInsId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据流程实例ID,获取流程的发起人
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@Select("select START_USER_ID_ from act_hi_procinst where ID_ = #{proceInsId}")
|
||||
String getProcessStartUserId(@Param("proceInsId") String proceInsId);
|
||||
|
||||
/**
|
||||
* 根据流程实例ID,获取结束节点处理人
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@Select("select ASSIGNEE_ from act_hi_taskinst where PROC_INST_ID_ = #{proceInsId} order by END_TIME_ DESC")
|
||||
List<Map<String,Object>> getProcessEndUserId(@Param("proceInsId") String proceInsId);
|
||||
|
||||
List<UserAgentDTO> getUserAgent(@Param("currDate") Date currDate);
|
||||
|
||||
/**
|
||||
* 查询抄送的流程实例ID
|
||||
* @param ccUserName
|
||||
* @return
|
||||
*/
|
||||
List<ActTaskCcDTO> getUserCcHistoryTask(@Param("ccUserName") String ccUserName);
|
||||
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 根据流程ID,获取流程的发起人
|
||||
// * @param ID_ 流程ID
|
||||
// */
|
||||
// @Select("select START_USER_ID_ from act_hi_procinst where id_ = :id")
|
||||
// String getProcessStartUserId(String id);
|
||||
//
|
||||
// /**
|
||||
// * 根据流程ID,流程最后一个处理人
|
||||
// * @param ID_ 流程ID
|
||||
// */
|
||||
// @Select("select ASSIGNEE_ from act_hi_taskinst where proc_inst_id_ = :id order by end_time_ desc")
|
||||
// List<Map<String,Object>> getProcessEndUserId(String id,int page, int rows);
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 获取流程发起节点的表单
|
||||
// * @param processid 流程ID
|
||||
// */
|
||||
// @Select("select modelandview from t_p_processnode where processid = :processid and processnodecode = 'start'")
|
||||
// String getProcessStartNodeView(String processid);
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 获取流程发起节点的表单
|
||||
// * @param processid 流程ID
|
||||
// */
|
||||
// @Select("select modelandview_mobile from t_p_processnode where processid = :processid and processnodecode = 'start'")
|
||||
// String getProcessStartNodeViewMobile(String processid);
|
||||
//
|
||||
// /**
|
||||
// * 获取流程发起节点的表单
|
||||
// * @param processid 流程ID
|
||||
// */
|
||||
// @Select("select id from t_p_process where processkey = :processkey ")
|
||||
// String getProcessidByProcesskey(String processkey);
|
||||
|
||||
/**
|
||||
* 获取超时任务节点
|
||||
* @return
|
||||
*/
|
||||
List<ActRuTaskDTO> getTimeoutTask();
|
||||
|
||||
/**
|
||||
* 查询用户列表
|
||||
*
|
||||
* @param wrapper
|
||||
* @return
|
||||
*/
|
||||
List<User> selectUserList(@Param(Constants.WRAPPER) Wrapper wrapper);
|
||||
|
||||
/**
|
||||
* 删除节点信息
|
||||
* @param ids ids
|
||||
*/
|
||||
public void deleteHisActinstsByIds(List<String> ids) ;
|
||||
|
||||
/**
|
||||
* 删除节点信息
|
||||
* @param ids ids
|
||||
*/
|
||||
public void deleteRunActinstsByIds(List<String> ids) ;
|
||||
|
||||
/**
|
||||
* 查询流程设计的不同类型下的数量
|
||||
* @return
|
||||
*/
|
||||
public List<StartTypeStatisticsDto> countStartTypeNum(String lowAppId);
|
||||
|
||||
/**
|
||||
* 批量删除流程的所有自定义定时器
|
||||
*
|
||||
* @param processKey 流程KEY
|
||||
* @return boolean
|
||||
*/
|
||||
boolean deleteAllTimerJobByProcessKey(@Param("processKey") String processKey);
|
||||
|
||||
/**
|
||||
* QQYUN-4415
|
||||
*
|
||||
* 查询低代码应用名称
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Select("select app_name from low_app where id = #{id}")
|
||||
public String getLowAppName(@Param("id") String id);
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package org.jeecg.modules.bpm.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.jeecg.modules.bpm.dto.CommentVo;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author : scott
|
||||
* @projectName : flowable
|
||||
* @description: 流程备注Dao
|
||||
* @date : 2022-12-06
|
||||
*/
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface FlowableCommentMapper {
|
||||
|
||||
/**
|
||||
* 通过流程实例id获取审批意见列表
|
||||
* @param ProcessInstanceId 流程实例id
|
||||
* @return
|
||||
*/
|
||||
public List<CommentVo> getFlowCommentVosByProcessInstanceId(String ProcessInstanceId);
|
||||
|
||||
}
|
||||
+332
@@ -0,0 +1,332 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.jeecg.modules.bpm.mapper.ActivitiMapper">
|
||||
|
||||
<resultMap id="TaskDTO" type="org.jeecg.modules.bpm.dto.TaskDTO" >
|
||||
<result column="id" property="id" jdbcType="VARCHAR"/>
|
||||
<result column="processDefinitionId" property="processDefinitionId" jdbcType="VARCHAR"/>
|
||||
<result column="processDefinitionName" property="processDefinitionName" jdbcType="VARCHAR"/>
|
||||
<result column="taskName" property="taskName" jdbcType="VARCHAR"/>
|
||||
<result column="processInstanceId" property="processInstanceId" jdbcType="VARCHAR"/>
|
||||
<result column="processApplyUserId" property="processApplyUserId" jdbcType="VARCHAR"/>
|
||||
<result column="taskAssigneeId" property="taskAssigneeId" jdbcType="VARCHAR"/>
|
||||
<result column="taskBeginTime" property="taskBeginTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="taskEndTime" property="taskEndTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="taskDueTime" property="taskDueTime" jdbcType="BIGINT"/>
|
||||
<result column="taskId" property="taskId" jdbcType="VARCHAR"/>
|
||||
<result column="processEndTime" property="processEndTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="processDeleteReason" property="processDeleteReason" jdbcType="VARCHAR"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="ActTaskCcDTO" type="org.jeecg.modules.bpm.dto.ActTaskCcDTO" >
|
||||
<result column="procDefId" property="procDefId" jdbcType="VARCHAR"/>
|
||||
<result column="taskDefKey" property="taskDefKey" jdbcType="VARCHAR"/>
|
||||
<result column="procInstId" property="procInstId" jdbcType="VARCHAR"/>
|
||||
<result column="executionId" property="executionId" jdbcType="VARCHAR"/>
|
||||
<result column="taskName" property="taskName" jdbcType="VARCHAR"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="UserAgentDTO" type="org.jeecg.modules.bpm.dto.UserAgentDTO" >
|
||||
<result column="id" property="id" jdbcType="VARCHAR"/>
|
||||
<result column="userName" property="userName" jdbcType="VARCHAR"/>
|
||||
<result column="agentUserName" property="agentUserName" jdbcType="VARCHAR"/>
|
||||
<result column="startTime" property="startTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="endTime" property="endTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="status" property="status" jdbcType="VARCHAR"/>
|
||||
<result column="createName" property="createName" jdbcType="VARCHAR"/>
|
||||
<result column="createBy" property="createBy" jdbcType="VARCHAR"/>
|
||||
<result column="createTime" property="createTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="updateName" property="updateName" jdbcType="VARCHAR"/>
|
||||
<result column="updateBy" property="updateBy" jdbcType="VARCHAR"/>
|
||||
<result column="updateTime" property="updateTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="sysOrgCode" property="sysOrgCode" jdbcType="VARCHAR"/>
|
||||
<result column="sysCompanyCode" property="sysCompanyCode" jdbcType="VARCHAR"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="ActHiActinstDTO" type="org.jeecg.modules.bpm.dto.ActHiActinstDTO" >
|
||||
<result column="ID_" property="id" jdbcType="VARCHAR"/>
|
||||
<result column="PROC_DEF_ID_" property="procDefId" jdbcType="VARCHAR"/>
|
||||
<result column="PROC_INST_ID_" property="procInstId" jdbcType="VARCHAR"/>
|
||||
<result column="EXECUTION_ID_" property="executionId" jdbcType="VARCHAR"/>
|
||||
<result column="ACT_ID_" property="actId" jdbcType="VARCHAR"/>
|
||||
<result column="TASK_ID_" property="taskId" jdbcType="VARCHAR"/>
|
||||
<result column="CALL_PROC_INST_ID_" property="callProcInstId" jdbcType="VARCHAR"/>
|
||||
<result column="ACT_NAME_" property="actName" jdbcType="VARCHAR"/>
|
||||
<result column="ACT_TYPE_" property="actType" jdbcType="VARCHAR"/>
|
||||
<result column="ASSIGNEE_" property="assignee" jdbcType="VARCHAR"/>
|
||||
<result column="START_TIME_" property="startTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="END_TIME_" property="endTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="DURATION_" property="duration" jdbcType="INTEGER"/>
|
||||
<result column="TENANT_ID_" property="tenantId" jdbcType="VARCHAR"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="ActRuTaskDTO" type="org.jeecg.modules.bpm.dto.ActRuTaskDTO" >
|
||||
<result column="ID_" property="id" jdbcType="VARCHAR"/>
|
||||
<result column="CREATE_TIME_" property="createTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="NAME_" property="name" jdbcType="VARCHAR"/>
|
||||
<result column="ASSIGNEE_" property="assignee" jdbcType="VARCHAR"/>
|
||||
<result column="OWNER_" property="owner" jdbcType="VARCHAR"/>
|
||||
<result column="PROC_INST_ID_" property="procInstId" jdbcType="VARCHAR"/>
|
||||
<result column="EXECUTION_ID_" property="executionId" jdbcType="VARCHAR"/>
|
||||
<result column="NODE_TIMEOUT" property="nodeTimeout" jdbcType="INTEGER"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 查询我的历史参与任务 -->
|
||||
<select id="getHistoryTasks" resultMap="TaskDTO">
|
||||
SELECT
|
||||
aht.ID_ AS id
|
||||
,aht.PROC_DEF_ID_ AS processDefinitionId
|
||||
,arp.NAME_ AS processDefinitionName
|
||||
,aht.NAME_ AS taskName
|
||||
,ahp.PROC_INST_ID_ AS processInstanceId
|
||||
,ahp.START_USER_ID_ AS processApplyUserId
|
||||
,aht.ASSIGNEE_ AS taskAssigneeId
|
||||
,aht.START_TIME_ AS taskBeginTime
|
||||
,aht.END_TIME_ AS taskEndTime
|
||||
,aht.DURATION_ AS taskDueTime
|
||||
,aht.TASK_DEF_KEY_ AS taskId
|
||||
FROM ACT_HI_TASKINST aht,
|
||||
ACT_RE_PROCDEF arp,
|
||||
ACT_HI_PROCINST ahp
|
||||
WHERE aht.PROC_DEF_ID_ = arp.id_
|
||||
and aht.PROC_INST_ID_ = ahp.id_
|
||||
and aht.DURATION_>0
|
||||
and aht.ASSIGNEE_ = #{userName}
|
||||
<if test="processKeyList!= null and processKeyList.size()>0">
|
||||
AND arp.KEY_ IN
|
||||
<foreach item="item" collection="processKeyList" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="procInstIdList!= null and procInstIdList.size()>0">
|
||||
and aht.PROC_INST_ID_ IN
|
||||
<foreach item="item" collection="procInstIdList" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="processDefinitionId != null and processDefinitionId !=''">
|
||||
and aht.PROC_DEF_ID_ like concat(concat('%',#{processDefinitionId}),'%')
|
||||
</if>
|
||||
<if test="processDefinitionName != null and processDefinitionName !=''">
|
||||
and arp.NAME_ like concat(concat('%',#{processDefinitionName}),'%')
|
||||
</if>
|
||||
order by aht.START_TIME_ desc
|
||||
</select>
|
||||
|
||||
<!-- 查询我的抄送任务列表 -->
|
||||
<select id="getAllHistoryTasks" resultMap="TaskDTO">
|
||||
SELECT
|
||||
aht.ID_ AS id
|
||||
,aht.PROC_DEF_ID_ AS processDefinitionId
|
||||
,arp.NAME_ AS processDefinitionName
|
||||
,aht.NAME_ AS taskName
|
||||
,ahp.PROC_INST_ID_ AS processInstanceId
|
||||
,ahp.START_USER_ID_ AS processApplyUserId
|
||||
,aht.ASSIGNEE_ AS taskAssigneeId
|
||||
,aht.START_TIME_ AS taskBeginTime
|
||||
,aht.END_TIME_ AS taskEndTime
|
||||
,aht.DURATION_ AS taskDueTime
|
||||
,aht.TASK_DEF_KEY_ AS taskId
|
||||
FROM ACT_HI_TASKINST aht,
|
||||
ACT_RE_PROCDEF arp,
|
||||
ACT_HI_PROCINST ahp
|
||||
WHERE aht.PROC_DEF_ID_ = arp.id_
|
||||
and aht.PROC_INST_ID_ = ahp.id_
|
||||
and aht.DURATION_>0
|
||||
<if test="processDefinitionId != null and processDefinitionId !=''">
|
||||
and aht.PROC_DEF_ID_ like concat(concat('%',#{processDefinitionId}),'%')
|
||||
</if>
|
||||
<if test="processDefinitionName != null and processDefinitionName !=''">
|
||||
and arp.NAME_ like concat(concat('%',#{processDefinitionName}),'%')
|
||||
</if>
|
||||
order by aht.START_TIME_ desc
|
||||
</select>
|
||||
|
||||
<!-- 查询我的抄送任务列表 -->
|
||||
<select id="getAllCcHistoryTasks" resultMap="TaskDTO">
|
||||
SELECT
|
||||
aht.ID_ AS id
|
||||
,aht.PROC_DEF_ID_ AS processDefinitionId
|
||||
,arp.NAME_ AS processDefinitionName
|
||||
,aht.NAME_ AS taskName
|
||||
,ahp.PROC_INST_ID_ AS processInstanceId
|
||||
,ahp.START_USER_ID_ AS processApplyUserId
|
||||
,ahp.END_TIME_ as processEndTime
|
||||
,ahp.DELETE_REASON_ as processDeleteReason
|
||||
,aht.ASSIGNEE_ AS taskAssigneeId
|
||||
,aht.START_TIME_ AS taskBeginTime
|
||||
,aht.END_TIME_ AS taskEndTime
|
||||
,aht.DURATION_ AS taskDueTime
|
||||
,aht.TASK_DEF_KEY_ AS taskId
|
||||
FROM ACT_HI_TASKINST aht,
|
||||
EXT_ACT_TASK_CC cc,
|
||||
ACT_RE_PROCDEF arp,
|
||||
ACT_HI_PROCINST ahp
|
||||
WHERE aht.ID_ = cc.TASK_ID
|
||||
and aht.PROC_INST_ID_ = cc.proc_inst_id
|
||||
and aht.EXECUTION_ID_ = cc.execution_id
|
||||
and aht.PROC_DEF_ID_ = arp.id_
|
||||
and aht.PROC_INST_ID_ = ahp.id_
|
||||
and aht.DURATION_ >0
|
||||
and cc.CC_USER_NAME = #{ccUserName}
|
||||
<if test="processKeyList!= null and processKeyList.size()>0">
|
||||
AND arp.KEY_ IN
|
||||
<foreach item="item" collection="processKeyList" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="executionIdList!= null and executionIdList.size()>0">
|
||||
and aht.EXECUTION_ID_ IN
|
||||
<foreach item="item" collection="executionIdList" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="processInstanceIds!= null and processInstanceIds.size()>0">
|
||||
and aht.PROC_INST_ID_ IN
|
||||
<foreach item="item" collection="processInstanceIds" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="processDefinitionId != null and processDefinitionId !=''">
|
||||
and aht.PROC_DEF_ID_ like concat(concat('%',#{processDefinitionId}),'%')
|
||||
</if>
|
||||
<if test="processDefinitionName != null and processDefinitionName !=''">
|
||||
and arp.NAME_ like concat(concat('%',#{processDefinitionName}),'%')
|
||||
</if>
|
||||
ORDER BY aht.START_TIME_ DESC
|
||||
</select>
|
||||
|
||||
<!-- 查询我的抄送任务实例ID -->
|
||||
<select id="getUserCcHistoryTask" resultMap="ActTaskCcDTO">
|
||||
SELECT
|
||||
proc_def_id AS procDefId,
|
||||
proc_inst_id AS procInstId
|
||||
FROM EXT_ACT_TASK_CC
|
||||
WHERE CC_USER_NAME = #{ccUserName}
|
||||
</select>
|
||||
|
||||
<select id="getUserAgent" resultMap="UserAgentDTO">
|
||||
SELECT
|
||||
sua.id AS id
|
||||
,sua.user_name AS userName
|
||||
,sua.agent_user_name AS agentUserName
|
||||
,sua.start_time AS startTime
|
||||
,sua.end_time AS endTime
|
||||
,sua.status AS status
|
||||
,sua.create_name AS createName
|
||||
,sua.create_by AS createBy
|
||||
,sua.create_time AS createTime
|
||||
,sua.update_name AS updateName
|
||||
,sua.update_by AS updateBy
|
||||
,sua.update_time AS updateTime
|
||||
,sua.sys_org_code AS sysOrgCode
|
||||
,sua.sys_company_code AS sysCompanyCode
|
||||
FROM sys_user_agent sua
|
||||
WHERE sua.status = '1'
|
||||
<![CDATA[
|
||||
and sua.start_time <= #{currDate}
|
||||
and sua.end_time >= #{currDate}
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<!-- update-begin author:scott date:2022-12-06 for:【升级flowable】流程历史跟踪查不到开始和结束节点【原因: 老版activiti字段 PROC_INST_ID_、EXECUTION_ID_ 值一样的,换成flowable后变的不一样了】-->
|
||||
<select id="getActHiActinstStartAndEnd" resultMap="ActHiActinstDTO">
|
||||
SELECT * FROM ACT_HI_ACTINST WHERE PROC_INST_ID_= #{proceInsId} and ACT_TYPE_ in ('startEvent','endEvent')
|
||||
</select>
|
||||
<!-- update-end-author:scott date:2022-12-06 for:【升级flowable】流程历史跟踪查不到开始和结束节点【原因: 老版activiti字段 PROC_INST_ID_、EXECUTION_ID_ 值一样的,换成flowable后变的不一样了】-->
|
||||
|
||||
<!-- 查询超时任务 TODO 节点key重名有问题 -->
|
||||
<select id="getTimeoutTask" resultMap="ActRuTaskDTO">
|
||||
SELECT
|
||||
RES.CREATE_TIME_,
|
||||
RES.ID_,
|
||||
RES.NAME_,
|
||||
RES.ASSIGNEE_,
|
||||
RES.OWNER_,
|
||||
RES.PROC_INST_ID_,
|
||||
RES.EXECUTION_ID_,
|
||||
t.NODE_TIMEOUT
|
||||
FROM
|
||||
ACT_RU_TASK RES
|
||||
LEFT JOIN EXT_ACT_PROCESS_NODE t ON t.PROCESS_NODE_CODE = RES.TASK_DEF_KEY_
|
||||
WHERE
|
||||
t.NODE_TIMEOUT > 0
|
||||
AND ( RES.ASSIGNEE_ IS NOT NULL OR RES.ASSIGNEE_ != '' )
|
||||
UNION ALL
|
||||
SELECT
|
||||
RES.CREATE_TIME_,
|
||||
RES.ID_,
|
||||
RES.NAME_,
|
||||
I.USER_ID_ as ASSIGNEE_,
|
||||
RES.OWNER_,
|
||||
RES.PROC_INST_ID_,
|
||||
RES.EXECUTION_ID_,
|
||||
t.NODE_TIMEOUT
|
||||
FROM
|
||||
ACT_RU_TASK RES
|
||||
LEFT JOIN EXT_ACT_PROCESS_NODE t ON t.PROCESS_NODE_CODE = RES.TASK_DEF_KEY_
|
||||
LEFT JOIN ACT_RU_IDENTITYLINK I ON I.TASK_ID_ = RES.ID_
|
||||
WHERE
|
||||
t.NODE_TIMEOUT > 0
|
||||
AND RES.ASSIGNEE_ IS NULL
|
||||
AND I.USER_ID_ IS NOT NULL
|
||||
AND I.TYPE_ = 'candidate'
|
||||
</select>
|
||||
|
||||
<!-- <!– 通过业务标题,去流程变量里模糊匹配出 流程实例list –>-->
|
||||
<!-- <select id="getHisVarinstProids" resultType="java.lang.String" parameterType="java.lang.String">-->
|
||||
<!-- <bind name="bindText" value="'%'+text+'%'"/>-->
|
||||
<!-- select PROC_INST_ID_ from act_hi_varinst where NAME_= 'bpm_biz_title' and TEXT_ like #{bindText}-->
|
||||
<!-- </select>-->
|
||||
|
||||
<!-- 通过业务标题,去流程变量里模糊匹配出 流程实例list -->
|
||||
<select id="getHisVarinstProidsWithIn" resultType="java.lang.String" parameterType="java.lang.String">
|
||||
<bind name="bindText" value="'%'+text+'%'"/>
|
||||
select PROC_INST_ID_ from act_hi_varinst where NAME_= 'bpm_biz_title' and TEXT_ like #{bindText}
|
||||
<if test="procInstIdList!= null and procInstIdList.size()>0">
|
||||
AND PROC_INST_ID_ in
|
||||
<foreach item="item" index="index" collection="procInstIdList" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectUserList" resultType="org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl">
|
||||
SELECT username id, realname displayName, email
|
||||
FROM sys_user ${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="countStartTypeNum" resultType="org.jeecg.modules.bpm.dto.StartTypeStatisticsDto">
|
||||
SELECT
|
||||
start_type,
|
||||
count(*) AS count
|
||||
FROM
|
||||
ext_act_process
|
||||
WHERE
|
||||
low_app_id = #{lowAppId}
|
||||
GROUP BY
|
||||
start_type
|
||||
</select>
|
||||
|
||||
|
||||
<delete id="deleteRunActinstsByIds" parameterType="java.util.List">
|
||||
delete from act_ru_actinst where ID_ in
|
||||
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<delete id="deleteHisActinstsByIds" parameterType="java.util.List">
|
||||
delete from act_hi_actinst where ID_ in
|
||||
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<!--批量删除流程的所有自定义定时器-->
|
||||
<delete id="deleteAllTimerJobByProcessKey" parameterType="string">
|
||||
delete from act_ru_timer_job where HANDLER_TYPE_ ='timer-start-event-custom' and PROC_DEF_ID_ like CONCAT(#{processKey}, '%')
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="org.jeecg.modules.bpm.mapper.FlowableCommentMapper">
|
||||
<select id="getFlowCommentVosByProcessInstanceId" parameterType="java.lang.String" resultType="org.jeecg.modules.bpm.dto.CommentVo">
|
||||
SELECT
|
||||
t1.ID_,
|
||||
t1.TYPE_ AS type,
|
||||
t1.TIME_ AS time,
|
||||
t1.USER_ID_ AS userId,
|
||||
t2.FIRST_ AS userName,
|
||||
t1.TASK_ID_ AS taskId,
|
||||
t1.PROC_INST_ID_ AS processInstanceId,
|
||||
t1.MESSAGE_ AS message,
|
||||
CONVERT (FULL_MSG_ USING utf8) AS fullMsg
|
||||
FROM
|
||||
act_hi_comment t1
|
||||
INNER JOIN act_id_user t2 ON t1.USER_ID_ = t2.ID_
|
||||
WHERE
|
||||
t1.PROC_INST_ID_ = #{value} and ACTION_='AddComment'
|
||||
ORDER BY
|
||||
t1.TIME_ ASC
|
||||
</select>
|
||||
</mapper>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package org.jeecg.modules.bpm.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Title: activiti流程图工具类 <br>
|
||||
* @author scott
|
||||
* 日期:2021/11/19
|
||||
*/
|
||||
public interface ActImageService {
|
||||
byte[] getFlowImgByProcInstId(String procInstId) throws Exception;
|
||||
|
||||
/**
|
||||
* 新版前端渲染流程图,进度效果
|
||||
* @param procInstId
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Map getFlowMsgByProcInstId(String procInstId) throws Exception;
|
||||
}
|
||||
+262
@@ -0,0 +1,262 @@
|
||||
package org.jeecg.modules.bpm.service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.modules.bpm.cmd.dto.TaskAddRequest;
|
||||
import org.jeecg.modules.bpm.dto.*;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
|
||||
|
||||
public interface ActivitiService{
|
||||
|
||||
|
||||
/**
|
||||
* 查询待办任务-只查询用户自己的 (统计总数)
|
||||
* @param userName
|
||||
* @param procInstIds
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public Long countPriTodaoTask(String userName,String procInstIds, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 待办任务列表-组任务(统计总数)
|
||||
* @param roles
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public Long countGroupTodoTasks(List<String> roles, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 查询待办任务-只查询用户自己的
|
||||
* @param userId
|
||||
* @param procInstIds 流程实例Ids
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public List<TaskDTO> findPriTodoTasks(String userId,String procInstIds, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 加载我的任务查询条件,返回inProcInstIdsStr
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public String initQueryProcInstIds(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 待办任务列表-组任务
|
||||
* @param roles
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public List<TaskDTO> findGroupTodoTasks(List<String> roles,HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 查询历史任务
|
||||
* @param userName
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public Page<TaskDTO> findHistoryTasks(Page page,String userName, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 查询所有的流程历史
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public Page<TaskDTO> findAllHistoryTasks(Page page,HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 查询抄送给我的历史任务
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public Page<TaskDTO> findAllCcHistoryTasks(Page page,String username,HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 根据任务id查询任务信息
|
||||
* @param taskId
|
||||
* @return
|
||||
*/
|
||||
public Task getTask(String taskId);
|
||||
|
||||
/**
|
||||
* 查询流程的所有节点
|
||||
* @param taskId
|
||||
* @return
|
||||
*/
|
||||
public List<Map> getAllTaskNode(String taskId);
|
||||
|
||||
/**
|
||||
* 根据流程processkey获取该流程下已经发布的流程
|
||||
* @param processkey
|
||||
* @return
|
||||
*/
|
||||
public List<ProcessDefinition> processDefinitionListByProcesskey(String processkey);
|
||||
|
||||
/**
|
||||
* 通过任务节点ID,获取当前节点 分支
|
||||
*/
|
||||
public List getOutTransitions(String taskId) ;
|
||||
|
||||
/**
|
||||
* 查询流程的历史任务节点
|
||||
*/
|
||||
public List<Map<String,Object>> getHistTaskNodeList(String proceInsId);
|
||||
|
||||
/**
|
||||
* 获取流程的启动和结束时间
|
||||
* @param proid
|
||||
* @return
|
||||
*/
|
||||
public List<ActHiActinstDTO> getActHiActinstStartAndEnd(String proceInsId);
|
||||
|
||||
/**
|
||||
* 根据流程实例ID,获取流程的发起人
|
||||
* @param proceInsId
|
||||
* @return
|
||||
*/
|
||||
public String getProcessStartUserId(String proceInsId);
|
||||
|
||||
/**
|
||||
* 根据流程实例ID,获取结束节点处理人
|
||||
* @param proceInsId
|
||||
* @return
|
||||
*/
|
||||
public List<Map<String,Object>> getProcessEndUserId(String proceInsId);
|
||||
|
||||
/**
|
||||
* 走向流程 【带参数】
|
||||
* @param taskId
|
||||
* @param nextTaskId
|
||||
* @param variables
|
||||
* @throws Exception
|
||||
*/
|
||||
public void goProcessTaskNode(String taskId, String nextTaskId, Map<String, Object> variables) throws Exception;
|
||||
|
||||
/**
|
||||
* 指定下一步操作人
|
||||
* @param proInsId
|
||||
* @param taskDefKey
|
||||
*/
|
||||
public String getTaskIdByProins(String proInsId,String taskDefKey);
|
||||
|
||||
/**
|
||||
* 根据历史执行流程实例ID,查询变量内容
|
||||
* @param varName
|
||||
* @param proInsId
|
||||
* @return
|
||||
*/
|
||||
public String getHisVarinst(String varName,String proInsId);
|
||||
|
||||
|
||||
/**
|
||||
* 查询有效期的代理设置
|
||||
* @return
|
||||
*/
|
||||
public List<UserAgentDTO> getUserAgent(Date currDate);
|
||||
|
||||
/**
|
||||
* 更新流程实例关联业务单据的流程状态
|
||||
* @param procInstId 流程实例id
|
||||
* @param bpmStatus 流程状态
|
||||
*/
|
||||
public void updateBpmStatus(String procInstId,String bpmStatus);
|
||||
|
||||
/**
|
||||
* 流程挂起
|
||||
* @param procInstId
|
||||
*/
|
||||
public void suspend(String procInstId);
|
||||
|
||||
/**
|
||||
* 流程解挂启动
|
||||
* @param procInstId
|
||||
*/
|
||||
public void restart(String procInstId);
|
||||
|
||||
/**
|
||||
* 多实例加签
|
||||
* @param multiInstanceRequest
|
||||
* @return
|
||||
*/
|
||||
Result addMultiInstanceExecution(MultiInstanceRequestDto multiInstanceRequest);
|
||||
|
||||
/**
|
||||
* 多实例减签
|
||||
* @param multiInstanceRequest
|
||||
* @return
|
||||
*/
|
||||
Result deleteMultiInstanceExecution(MultiInstanceRequestDto multiInstanceRequest);
|
||||
|
||||
/**
|
||||
* 查询会签人员
|
||||
* @param multiInstanceRequest
|
||||
* @return
|
||||
*/
|
||||
Result selectMultiUserList(MultiInstanceRequestDto multiInstanceRequest);
|
||||
|
||||
|
||||
/**
|
||||
* 动态添加用户节点
|
||||
* @param taskAddRequest
|
||||
* @return
|
||||
*/
|
||||
Result addUserTask(TaskAddRequest taskAddRequest);
|
||||
|
||||
/**
|
||||
* 任务前加签 (如果多次加签只能显示第一次前加签的处理人来处理任务)
|
||||
* 多个加签人处理完毕任务之后又流到自己这里
|
||||
*
|
||||
* @param addSignTaskVo 参数
|
||||
* @return
|
||||
*/
|
||||
public Result<String> beforeAddSignTask(AddSignTaskVo addSignTaskVo);
|
||||
|
||||
/**
|
||||
* 任务后加签(加签人自己自动审批完毕加签多个人处理任务)
|
||||
*
|
||||
* @param addSignTaskVo 参数
|
||||
* @return
|
||||
*/
|
||||
public Result<String> afterAddSignTask(AddSignTaskVo addSignTaskVo);
|
||||
|
||||
/**
|
||||
* 任务加签
|
||||
*
|
||||
* @param addSignTaskVo 参数
|
||||
* @param flag true向后加签 false向前加签
|
||||
* @return
|
||||
*/
|
||||
public Result<String> addSignTask(AddSignTaskVo addSignTaskVo, Boolean flag);
|
||||
|
||||
/**
|
||||
* 创建虚拟子任务
|
||||
*
|
||||
* @param ptask
|
||||
* @param assignee
|
||||
* @return
|
||||
*/
|
||||
public TaskEntity createSubTask(TaskEntity ptask, String assignee);
|
||||
|
||||
/**
|
||||
* 批量删除流程的所有自定义定时器
|
||||
*
|
||||
* @param processKey 流程KEY
|
||||
* @return boolean
|
||||
*/
|
||||
boolean deleteAllTimerJobByProcessKey(@Param("processKey") String processKey);
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package org.jeecg.modules.bpm.service;
|
||||
|
||||
|
||||
import org.jeecg.modules.bpm.dto.CommentVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 网上的参考代码(目前未使用)
|
||||
* 说明: 这个使用的是flowable官方表【act_hi_comment】【act_hi_attachment】
|
||||
* 目前jeecgboot自定义了两个表【ext_act_bpm_log】【ext_act_bpm_file】,未使用官方表
|
||||
*
|
||||
* @author : scott
|
||||
* @projectName : flowable
|
||||
* @description: 审批意见service
|
||||
* @date : 2022-12-06
|
||||
*/
|
||||
public interface IFlowableCommentService {
|
||||
|
||||
/**
|
||||
* 添加备注
|
||||
* @param comment 参数
|
||||
*/
|
||||
public void addComment(CommentVo comment) ;
|
||||
|
||||
/**
|
||||
* 通过流程实例id获取审批意见列表
|
||||
* @param processInstanceId 流程实例id
|
||||
* @return
|
||||
*/
|
||||
public List<CommentVo> getFlowCommentVosByProcessInstanceId(String processInstanceId) ;
|
||||
|
||||
/**
|
||||
* 添加审批意见
|
||||
*
|
||||
* @param taskId
|
||||
* @param userCode
|
||||
* @param processInstanceId
|
||||
* @param type
|
||||
* @param comment
|
||||
*/
|
||||
public void addComment(String taskId, String userCode, String processInstanceId, String type, String comment);
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package org.jeecg.modules.bpm.service;
|
||||
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.task.api.Task;
|
||||
|
||||
/**
|
||||
* @Description: 流程校验接口
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-07
|
||||
*/
|
||||
public interface IPermissionService {
|
||||
|
||||
/**
|
||||
* 校验用户是否是任务的拥有者或者代理人
|
||||
*
|
||||
* @param userName
|
||||
* @param task
|
||||
* @return
|
||||
*/
|
||||
boolean checkUserIsTaskOwnerOrAssignee(String userName, Task task);
|
||||
|
||||
/**
|
||||
* 校验用户是否是发起人是否可以完成任务
|
||||
*
|
||||
* @param userName
|
||||
* @param task
|
||||
* @return
|
||||
*/
|
||||
boolean checkUserIsInitiatorAndCanCompleteTask(String userName, Task task);
|
||||
|
||||
|
||||
/**
|
||||
* 判断是否是协办完成还是正常流转
|
||||
*
|
||||
* @param task
|
||||
* @return
|
||||
*/
|
||||
boolean isTaskPending(Task task);
|
||||
|
||||
/**
|
||||
* 验证任务的执行权限
|
||||
*
|
||||
* @param taskId
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
Task checkPermissionOnTask(String taskId, String userId);
|
||||
|
||||
|
||||
/**
|
||||
* 是否可以转办任务
|
||||
* 1.任务所有人可以转办
|
||||
* 2.任务执行人可以转办,但要求任务非委派状态
|
||||
* 3.被转办人不能是当前任务执行人
|
||||
*
|
||||
* @param taskId
|
||||
* @param userId
|
||||
* @param assignee
|
||||
* @return
|
||||
*/
|
||||
Task checkPermissionOnTask(String taskId, String userId, String assignee);
|
||||
|
||||
|
||||
/**
|
||||
* 校验用户是否有权限读取该流程定义
|
||||
*
|
||||
* @param userId
|
||||
* @param processDefinitionId
|
||||
*/
|
||||
void checkPermissionOnProcessDefinition(String processDefinitionId, String userId);
|
||||
|
||||
/**
|
||||
* 校验用户是否有权限读取该流程实例
|
||||
*
|
||||
* @param userId
|
||||
* @param processInstanceId
|
||||
* @return
|
||||
*/
|
||||
HistoricProcessInstance checkPermissionOnProcessInstance(String processInstanceId, String userId);
|
||||
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package org.jeecg.modules.bpm.service;
|
||||
|
||||
/**
|
||||
* 流程追踪图生成类
|
||||
*
|
||||
* @author liuxz
|
||||
*/
|
||||
public interface ImageService {
|
||||
|
||||
/**
|
||||
* 根据流程实例标识,生成流程跟踪图示(高亮)
|
||||
*
|
||||
* @param procInstId 流程实例标识
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
byte[] generateImageByProcInstId(String procInstId) throws Exception;
|
||||
|
||||
}
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
package org.jeecg.modules.bpm.service.impl;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.FlowNode;
|
||||
import org.flowable.bpmn.model.SequenceFlow;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.history.HistoricActivityInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.image.ProcessDiagramGenerator;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.modules.bpm.service.ActImageService;
|
||||
import org.jeecg.modules.bpm.service.impl.image.CustomProcessDiagramGenerator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Title: activiti流程图工具类 <br>
|
||||
* @author scott
|
||||
* 日期:2021/11/19
|
||||
*/
|
||||
@Service("actImageServiceImpl")
|
||||
public class ActImageServiceImpl implements ActImageService {
|
||||
protected static Logger logger = LoggerFactory.getLogger(ActImageServiceImpl.class);
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
|
||||
/**
|
||||
* Desc: 通过流程实例ID获取历史流程实例
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
* @author liuxz
|
||||
*/
|
||||
public HistoricProcessInstance getHistoricProcInst(String procInstId) {
|
||||
return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Desc: 通过流程实例ID获取流程中已经执行的节点,按照执行先后顺序排序
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
* @author liuxz
|
||||
*/
|
||||
public List<HistoricActivityInstance> getHistoricActivityInstAsc(String procInstId) {
|
||||
return historyService.createHistoricActivityInstanceQuery().processInstanceId(procInstId)
|
||||
.orderByHistoricActivityInstanceId().asc().list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Desc: 通过流程实例ID获取流程中正在执行的节点
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
* @author liuxz
|
||||
*/
|
||||
public List<Execution> getRunningActivityInst(String procInstId) {
|
||||
return runtimeService.createExecutionQuery().processInstanceId(procInstId).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Desc: 通过流程实例ID获取已经完成的历史流程实例
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
* @author liuxz
|
||||
*/
|
||||
public List<HistoricProcessInstance> getHistoricFinishedProcInst(String procInstId) {
|
||||
return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).finished().list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已流经的流程线,需要高亮显示高亮流程已发生流转的线id集合
|
||||
*
|
||||
* @param bpmnModel
|
||||
* @param historicActivityInstanceList
|
||||
* @return
|
||||
*/
|
||||
public List<String> getHighLightedFlows(BpmnModel bpmnModel,
|
||||
List<HistoricActivityInstance> historicActivityInstanceList) {
|
||||
// 已流经的流程线,需要高亮显示
|
||||
List<String> highLightedFlowIdList = new ArrayList<>();
|
||||
// 全部活动节点
|
||||
List<FlowNode> allHistoricActivityNodeList = new ArrayList<>();
|
||||
// 已完成的历史活动节点
|
||||
List<HistoricActivityInstance> finishedActivityInstanceList = new ArrayList<>();
|
||||
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
|
||||
// 获取流程节点
|
||||
// org.flowable.bpmn.model.SequenceFlow cannot be cast to org.flowable.bpmn.model.FlowNode
|
||||
FlowNode flowNode = null;
|
||||
FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId());
|
||||
if(flowElement instanceof FlowNode){
|
||||
flowNode = (FlowNode)flowElement;
|
||||
allHistoricActivityNodeList.add(flowNode);
|
||||
}
|
||||
// 结束时间不为空,当前节点则已经完成
|
||||
if (historicActivityInstance.getEndTime() != null) {
|
||||
finishedActivityInstanceList.add(historicActivityInstance);
|
||||
}
|
||||
}
|
||||
|
||||
FlowNode currentFlowNode = null;
|
||||
FlowNode targetFlowNode = null;
|
||||
HistoricActivityInstance currentActivityInstance;
|
||||
// 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
|
||||
for (int k = 0; k < finishedActivityInstanceList.size(); k++) {
|
||||
currentActivityInstance = finishedActivityInstanceList.get(k);
|
||||
// 获得当前活动对应的节点信息及outgoingFlows信息
|
||||
FlowElement currentFlowElement = bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId());
|
||||
if(currentFlowElement==null || !(currentFlowElement instanceof FlowNode)){
|
||||
continue;
|
||||
}
|
||||
currentFlowNode = (FlowNode)currentFlowElement;
|
||||
// 当前节点的所有流出线
|
||||
List<SequenceFlow> outgoingFlowList = currentFlowNode.getOutgoingFlows();
|
||||
|
||||
/**
|
||||
* 遍历outgoingFlows并找到已流转的 满足如下条件认为已流转
|
||||
* 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
|
||||
* 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转 (第2点有问题,有过驳回的,会只绘制驳回的流程线,通过走向下一级的流程线没有高亮显示)
|
||||
*/
|
||||
if ("parallelGateway".equals(currentActivityInstance.getActivityType()) || "inclusiveGateway".equals(currentActivityInstance.getActivityType())) {
|
||||
// 遍历历史活动节点,找到匹配流程目标节点的
|
||||
for (SequenceFlow outgoingFlow : outgoingFlowList) {
|
||||
// 获取当前节点流程线对应的下级节点
|
||||
targetFlowNode = (FlowNode)bpmnModel.getMainProcess().getFlowElement(outgoingFlow.getTargetRef());
|
||||
// 如果下级节点包含在所有历史节点中,则将当前节点的流出线高亮显示
|
||||
if (allHistoricActivityNodeList.contains(targetFlowNode)) {
|
||||
highLightedFlowIdList.add(outgoingFlow.getId());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* 2、当前节点不是并行网关或兼容网关 【已解决-问题】如果当前节点有驳回功能,驳回到申请节点, 则因为申请节点在历史节点中,导致当前节点驳回到申请节点的流程线被高亮显示,但实际并没有进行驳回操作
|
||||
*/
|
||||
List<Map<String, Object>> tempMapList = new ArrayList<>();
|
||||
// 当前节点ID
|
||||
String currentActivityId = currentActivityInstance.getActivityId();
|
||||
int size = historicActivityInstanceList.size();
|
||||
boolean ifStartFind = false;
|
||||
boolean ifFinded = false;
|
||||
HistoricActivityInstance historicActivityInstance;
|
||||
// 循环当前节点的所有流出线
|
||||
// 循环所有历史节点
|
||||
logger.debug("【开始】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线", currentActivityId);
|
||||
logger.debug("循环历史节点");
|
||||
for (int i = 0; i < historicActivityInstanceList.size(); i++) {
|
||||
// 历史节点
|
||||
historicActivityInstance = historicActivityInstanceList.get(i);
|
||||
logger.debug("第【{}/{}】个历史节点-ActivityId=[{}]", i + 1, size, historicActivityInstance.getActivityId());
|
||||
// 如果循环历史节点中的id等于当前节点id,从当前历史节点继续先后查找是否有当前节点流程线等于的节点
|
||||
// 历史节点的序号需要大于等于已完成历史节点的序号,防止驳回重审一个节点经过两次是只取第一次的流出线高亮显示,第二次的不显示
|
||||
if (i >= k && historicActivityInstance.getActivityId().equals(currentActivityId)) {
|
||||
logger.debug("第[{}]个历史节点和当前节点一致-ActivityId=[{}]", i + 1,historicActivityInstance.getActivityId());
|
||||
ifStartFind = true;
|
||||
// 跳过当前节点继续查找下一个节点
|
||||
continue;
|
||||
}
|
||||
if (ifStartFind) {
|
||||
logger.debug("[开始]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);
|
||||
ifFinded = false;
|
||||
for (SequenceFlow sequenceFlow : outgoingFlowList) {
|
||||
// 如果当前节点流程线对应的下级节点在其后面的历史节点中,则该条流程线进行高亮显示
|
||||
logger.debug("当前流出线的下级节点=[{}]", sequenceFlow.getTargetRef());
|
||||
if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
|
||||
logger.debug("当前节点[{}]需高亮显示的流出线=[{}]", currentActivityId, sequenceFlow.getId());
|
||||
highLightedFlowIdList.add(sequenceFlow.getId());
|
||||
// 暂时默认找到离当前节点最近的下一级节点即退出循环,否则有多条流出线时将全部被高亮显示
|
||||
ifFinded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.debug("[完成]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);
|
||||
}
|
||||
if (ifFinded) {
|
||||
// 暂时默认找到离当前节点最近的下一级节点即退出历史节点循环,否则有多条流出线时将全部被高亮显示
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.debug("【完成】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线", currentActivityId);
|
||||
}
|
||||
|
||||
}
|
||||
return highLightedFlowIdList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程实例Id,获取实时流程图片
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public byte[] getFlowImgByProcInstId(String procInstId) throws Exception {
|
||||
if (org.apache.commons.lang.StringUtil.isEmpty(procInstId)) {
|
||||
logger.error("[错误]-传入的参数procInstId为空!");
|
||||
throw new Exception("[异常]-传入的参数procInstId为空!");
|
||||
}
|
||||
InputStream imageStream = null;
|
||||
try {
|
||||
// 通过流程实例ID获取历史流程实例
|
||||
HistoricProcessInstance historicProcessInstance = getHistoricProcInst(procInstId);
|
||||
|
||||
// 通过流程实例ID获取流程中已经执行的节点,按照执行先后顺序排序
|
||||
List<HistoricActivityInstance> historicActivityInstanceList = getHistoricActivityInstAsc(procInstId);
|
||||
|
||||
// 将已经执行的节点ID放入高亮显示节点集合
|
||||
List<String> highLightedActivitiIdList = new ArrayList<>();
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
|
||||
highLightedActivitiIdList.add(historicActivityInstance.getActivityId());
|
||||
logger.debug("已执行的节点[{}-{}-{}-{}]", historicActivityInstance.getId(),
|
||||
historicActivityInstance.getActivityId(), historicActivityInstance.getActivityName(),
|
||||
historicActivityInstance.getAssignee());
|
||||
}
|
||||
|
||||
// 通过流程实例ID获取流程中正在执行的节点
|
||||
List<Execution> runningActivityInstanceList = getRunningActivityInst(procInstId);
|
||||
List<String> runningActivitiIdList = new ArrayList<String>();
|
||||
for (Execution execution : runningActivityInstanceList) {
|
||||
if (org.apache.commons.lang.StringUtil.isNotEmpty(execution.getActivityId())) {
|
||||
runningActivitiIdList.add(execution.getActivityId());
|
||||
logger.debug("执行中的节点[{}-{}-{}]", execution.getId(), execution.getActivityId(), execution.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// 通过流程实例ID获取已经完成的历史流程实例
|
||||
List<HistoricProcessInstance> historicFinishedProcessInstanceList = getHistoricFinishedProcInst(procInstId);
|
||||
|
||||
// 定义流程画布生成器
|
||||
ProcessDiagramGenerator processDiagramGenerator = null;
|
||||
// 如果还没完成,流程图高亮颜色为绿色,如果已经完成为红色
|
||||
// if (!CollectionUtils.isEmpty(historicFinishedProcessInstanceList)) {
|
||||
// // 如果不为空,说明已经完成
|
||||
// processDiagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
|
||||
// } else {
|
||||
processDiagramGenerator = new CustomProcessDiagramGenerator();
|
||||
// }
|
||||
|
||||
// 获取流程定义Model对象
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
|
||||
|
||||
// 获取已流经的流程线,需要高亮显示高亮流程已发生流转的线id集合
|
||||
List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, historicActivityInstanceList);
|
||||
|
||||
// 使用默认配置获得流程图表生成器,并生成追踪图片字符流
|
||||
imageStream = ((CustomProcessDiagramGenerator)processDiagramGenerator).generateDiagramCustom(bpmnModel,
|
||||
"png", highLightedActivitiIdList, runningActivitiIdList, highLightedFlowIds, "宋体",
|
||||
"微软雅黑", "黑体", null,
|
||||
2.0);
|
||||
|
||||
// 将InputStream数据流转换为byte[]
|
||||
byte[] buffer = new byte[imageStream.available()];
|
||||
imageStream.read(buffer);
|
||||
return buffer;
|
||||
} catch (Exception e) {
|
||||
logger.error("通过流程实例ID[{}]获取流程图时出现异常!", e);
|
||||
throw new Exception("通过流程实例ID" + procInstId + "获取流程图时出现异常!", e);
|
||||
} finally {
|
||||
if (imageStream != null) {
|
||||
imageStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程实例Id,获取实时流程图片 【新版npm.js渲染图片进度使用接口】
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public Map<String, List<String>> getFlowMsgByProcInstId(String procInstId) throws Exception {
|
||||
if (org.apache.commons.lang.StringUtil.isEmpty(procInstId)) {
|
||||
logger.error("[错误]-传入的参数procInstId为空!");
|
||||
throw new Exception("[异常]-传入的参数procInstId为空!");
|
||||
}
|
||||
|
||||
try {
|
||||
Map map = new HashMap();
|
||||
// 通过流程实例ID获取历史流程实例
|
||||
HistoricProcessInstance historicProcessInstance = getHistoricProcInst(procInstId);
|
||||
|
||||
// 通过流程实例ID获取流程中已经执行的节点,按照执行先后顺序排序
|
||||
List<HistoricActivityInstance> historicActivityInstanceList = getHistoricActivityInstAsc(procInstId);
|
||||
|
||||
// 将已经执行的节点ID放入高亮显示节点集合
|
||||
List<String> highLightedActivitiIdList = new ArrayList<>();
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
|
||||
highLightedActivitiIdList.add(historicActivityInstance.getActivityId());
|
||||
logger.debug("已执行的节点[{}-{}-{}-{}]", historicActivityInstance.getId(),
|
||||
historicActivityInstance.getActivityId(), historicActivityInstance.getActivityName(),
|
||||
historicActivityInstance.getAssignee());
|
||||
}
|
||||
//已执行过节点ID
|
||||
map.put("highLightedActivitiIdList", highLightedActivitiIdList);
|
||||
|
||||
// 通过流程实例ID获取流程中正在执行的节点
|
||||
List<Execution> runningActivityInstanceList = getRunningActivityInst(procInstId);
|
||||
List<String> runningActivitiIdList = new ArrayList<String>();
|
||||
for (Execution execution : runningActivityInstanceList) {
|
||||
if (org.apache.commons.lang.StringUtil.isNotEmpty(execution.getActivityId())) {
|
||||
runningActivitiIdList.add(execution.getActivityId());
|
||||
logger.debug("执行中的节点[{}-{}-{}]", execution.getId(), execution.getActivityId(), execution.getName());
|
||||
}
|
||||
}
|
||||
//正在执行的节点ID
|
||||
map.put("runningActivitiIdList", runningActivitiIdList);
|
||||
|
||||
// 通过流程实例ID获取已经完成的历史流程实例
|
||||
List<HistoricProcessInstance> historicFinishedProcessInstanceList = getHistoricFinishedProcInst(procInstId);
|
||||
// 获取流程定义Model对象
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
|
||||
// 获取已流经的流程线,需要高亮显示高亮流程已发生流转的线id集合
|
||||
List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, historicActivityInstanceList);
|
||||
|
||||
//获取已流经的流程线ID
|
||||
map.put("highLightedFlowIds", highLightedFlowIds);
|
||||
return map;
|
||||
} catch (Exception e) {
|
||||
logger.error("通过流程实例ID[{}]获取流程图时出现异常!", e);
|
||||
throw new Exception("通过流程实例ID" + procInstId + "获取流程图时出现异常!", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
//package org.jeecg.modules.bpm.service.impl;
|
||||
//
|
||||
//import java.io.ByteArrayInputStream;
|
||||
//import java.io.UnsupportedEncodingException;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import javax.servlet.http.HttpServletResponse;
|
||||
//import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||
//import org.activiti.bpmn.model.BpmnModel;
|
||||
//import org.activiti.editor.constants.ModelDataJsonConstants;
|
||||
//import org.activiti.editor.language.json.converter.BpmnJsonConverter;
|
||||
//import org.activiti.engine.RepositoryService;
|
||||
//import org.activiti.engine.repository.Deployment;
|
||||
//import org.activiti.engine.repository.Model;
|
||||
//import org.activiti.engine.repository.ModelQuery;
|
||||
//import org.activiti.engine.repository.ProcessDefinition;
|
||||
//import org.apache.commons.io.IOUtils;
|
||||
//import org.apache.commons.lang3.StringUtils;
|
||||
//import org.jeecg.common.exception.JeecgBootException;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//import com.fasterxml.jackson.databind.JsonNode;
|
||||
//import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
//import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
//
|
||||
///**
|
||||
// * 流程设计管理
|
||||
// *
|
||||
// * @author scott
|
||||
// */
|
||||
//@Service("actModelService")
|
||||
//public class ActModelService {
|
||||
// @Autowired
|
||||
// protected RepositoryService repositoryService;
|
||||
// @Autowired
|
||||
// private ObjectMapper objectMapper;
|
||||
//
|
||||
// public List<Model> page(Map<String, Object> params) {
|
||||
// String key = (String)params.get("key");
|
||||
// String name = (String)params.get("name");
|
||||
//
|
||||
// ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByLastUpdateTime().desc();
|
||||
//
|
||||
// if(org.apache.commons.lang.StringUtil.isNotEmpty(key)){
|
||||
// modelQuery.modelKey(key);
|
||||
// }
|
||||
// if(org.apache.commons.lang.StringUtil.isNotEmpty(name)){
|
||||
// modelQuery.modelName(name);
|
||||
// }
|
||||
//
|
||||
// List<Model> list = modelQuery.list();
|
||||
//// List<Model> list = modelQuery.listPage((curPage - 1) * limit, limit);
|
||||
// return list;
|
||||
// }
|
||||
//
|
||||
// public String save(String name, String key, String description) throws UnsupportedEncodingException {
|
||||
// //新建一个空模型
|
||||
// Model model = repositoryService.newModel();
|
||||
//
|
||||
// //metaInfo信息
|
||||
// ObjectNode metaInfo = objectMapper.createObjectNode();
|
||||
// metaInfo.put(ModelDataJsonConstants.MODEL_NAME, name);
|
||||
// metaInfo.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
|
||||
// metaInfo.put(ModelDataJsonConstants.MODEL_REVISION, model.getVersion());
|
||||
//
|
||||
// model.setKey(key);
|
||||
// model.setName(name);
|
||||
// model.setMetaInfo(metaInfo.toString());
|
||||
//
|
||||
// repositoryService.saveModel(model);
|
||||
//
|
||||
// ObjectNode editorNode = objectMapper.createObjectNode();
|
||||
// editorNode.put("id", "canvas");
|
||||
// editorNode.put("resourceId", "canvas");
|
||||
// ObjectNode stencilset = objectMapper.createObjectNode();
|
||||
// stencilset.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
|
||||
// editorNode.set("stencilset", stencilset);
|
||||
// repositoryService.addModelEditorSource(model.getId(), editorNode.toString().getBytes("utf-8"));
|
||||
// return model.getId();
|
||||
// }
|
||||
//
|
||||
// public void deploy(String id) {
|
||||
// try {
|
||||
// Model model = repositoryService.getModel(id);
|
||||
// BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
|
||||
// JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(model.getId()));
|
||||
// BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
|
||||
// BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
|
||||
// byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
|
||||
//
|
||||
// String processName = model.getName();
|
||||
// if (!org.apache.commons.lang.StringUtil.endsWith(processName, ".bpmn20.xml")){
|
||||
// processName += ".bpmn20.xml";
|
||||
// }
|
||||
//
|
||||
// ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
|
||||
// Deployment deployment = repositoryService.createDeployment().name(model.getName()).addInputStream(processName, in).deploy();
|
||||
//
|
||||
// List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
|
||||
// if (list.size() == 0){
|
||||
// throw new JeecgBootException("流程定义为空");
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// throw new JeecgBootException(e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 导出模型
|
||||
// */
|
||||
// public void export(String id, HttpServletResponse response) {
|
||||
// try {
|
||||
// Model model = repositoryService.getModel(id);
|
||||
// BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
|
||||
// JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(model.getId()));
|
||||
// BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
|
||||
// BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
|
||||
// byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
|
||||
//
|
||||
// ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
|
||||
// IOUtils.copy(in, response.getOutputStream());
|
||||
// String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
|
||||
// response.setHeader("Content-Disposition", "attachment; filename=" + filename);
|
||||
// response.flushBuffer();
|
||||
// } catch (Exception e) {
|
||||
// throw new JeecgBootException(e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 删除模型
|
||||
// * @param id 模型ID
|
||||
// */
|
||||
// public void delete(String id) {
|
||||
// repositoryService.deleteModel(id);
|
||||
// }
|
||||
//}
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
package org.jeecg.modules.bpm.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.engine.*;
|
||||
import org.flowable.engine.history.HistoricActivityInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.repository.ProcessDefinitionQuery;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.image.ProcessDiagramGenerator;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.modules.bpm.dto.StartTypeStatisticsDto;
|
||||
import org.jeecg.modules.bpm.mapper.ActivitiMapper;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActProcess;
|
||||
import org.jeecg.modules.extbpm.process.mapper.ExtActProcessMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
|
||||
/**
|
||||
* 流程管理
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("actProcessService")
|
||||
public class ActProcessService {
|
||||
@Autowired
|
||||
protected RepositoryService repositoryService;
|
||||
@Autowired
|
||||
protected HistoryService historyService;
|
||||
@Autowired
|
||||
protected RuntimeService runtimeService;
|
||||
@Autowired
|
||||
protected ProcessEngine processEngine;
|
||||
@Autowired
|
||||
protected ActivitiMapper activitiMapper;
|
||||
@Autowired
|
||||
protected ExtActProcessMapper extActProcessMapper;
|
||||
|
||||
/**
|
||||
* 流程列表
|
||||
*/
|
||||
public List<Map<String, Object>> page(Map<String, Object> params) {
|
||||
String key = (String) params.get("key");
|
||||
String processName = (String) params.get("processName");
|
||||
|
||||
//ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().latestVersion().orderByProcessDefinitionId().desc().orderByProcessDefinitionKey().desc();
|
||||
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionId().desc().orderByProcessDefinitionKey().desc();
|
||||
if (org.apache.commons.lang.StringUtil.isNotEmpty(key)) {
|
||||
processDefinitionQuery.processDefinitionKeyLike(key);
|
||||
}
|
||||
if (org.apache.commons.lang.StringUtil.isNotEmpty(processName)) {
|
||||
processDefinitionQuery.processDefinitionNameLike(processName);
|
||||
}
|
||||
|
||||
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.list();
|
||||
// List<ProcessInstance> processInstanceList = processInstanceQuery.listPage((curPage - 1) * limit, limit);
|
||||
List<Map<String, Object>> objectList = new ArrayList<>();
|
||||
for (ProcessDefinition processDefinition : processDefinitionList) {
|
||||
objectList.add(processDefinitionConvert(processDefinition));
|
||||
}
|
||||
|
||||
return objectList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程定义信息
|
||||
*/
|
||||
private Map<String, Object> processDefinitionConvert(ProcessDefinition processDefinition) {
|
||||
String deploymentId = processDefinition.getDeploymentId();
|
||||
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
|
||||
|
||||
Map<String, Object> map = new HashMap<>(9);
|
||||
map.put("suspended", processDefinition.isSuspended());
|
||||
map.put("id", processDefinition.getId());
|
||||
map.put("deploymentId", processDefinition.getDeploymentId());
|
||||
map.put("name", deployment.getName());
|
||||
map.put("key", processDefinition.getKey());
|
||||
map.put("version", processDefinition.getVersion());
|
||||
map.put("resourceName", processDefinition.getResourceName());
|
||||
map.put("diagramResourceName", processDefinition.getDiagramResourceName());
|
||||
map.put("deploymentTime", deployment.getDeploymentTime());
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 部署
|
||||
*
|
||||
* @param file 文件
|
||||
*/
|
||||
public void deploy(MultipartFile file) throws IOException {
|
||||
String fileName = file.getOriginalFilename();
|
||||
String extension = FilenameUtils.getExtension(fileName);
|
||||
if ("zip".equalsIgnoreCase(extension) || "bar".equalsIgnoreCase(extension)) {
|
||||
ZipInputStream zip = new ZipInputStream(file.getInputStream());
|
||||
repositoryService.createDeployment().addZipInputStream(zip).deploy();
|
||||
} else if (fileName.indexOf("bpmn20.xml") != -1) {
|
||||
repositoryService.createDeployment().addInputStream(fileName, file.getInputStream()).deploy();
|
||||
} else if ("bpmn".equalsIgnoreCase(extension)) {
|
||||
repositoryService.createDeployment().addInputStream(fileName, file.getInputStream()).deploy();
|
||||
} else {
|
||||
throw new JeecgBootException("部署失败!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活流程
|
||||
*
|
||||
* @param id 流程ID
|
||||
*/
|
||||
public void active(String id) {
|
||||
repositoryService.activateProcessDefinitionById(id, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起流程
|
||||
*
|
||||
* @param id 流程ID
|
||||
*/
|
||||
public void suspend(String id) {
|
||||
repositoryService.suspendProcessDefinitionById(id, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭流程(挂起流程最后一个版本)
|
||||
*
|
||||
* @param key 流程key
|
||||
*/
|
||||
public void closeProcess(String key) {
|
||||
//修改流程状态为 “关闭”
|
||||
ExtActProcess extActProcess = new ExtActProcess();
|
||||
extActProcess.setOpenStatus(Integer.parseInt(CommonConstant.STATUS_0));
|
||||
LambdaQueryWrapper<ExtActProcess> queryWrapper = new LambdaQueryWrapper<ExtActProcess>();
|
||||
queryWrapper.eq(ExtActProcess::getProcessKey,key);
|
||||
extActProcessMapper.update(extActProcess, queryWrapper);
|
||||
|
||||
//获取最新发布的流程定义(挂起)
|
||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).latestVersion().singleResult();
|
||||
if (processDefinition != null) {
|
||||
boolean suspended = repositoryService.isProcessDefinitionSuspended(processDefinition.getId());
|
||||
if (!suspended) {
|
||||
repositoryService.suspendProcessDefinitionById(processDefinition.getId(), true, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启流程(激活流程最后一个版本)
|
||||
*
|
||||
* @param key 流程key
|
||||
*/
|
||||
public void openProcess(String key) {
|
||||
//修改流程状态为 “打开”
|
||||
ExtActProcess extActProcess = new ExtActProcess();
|
||||
extActProcess.setOpenStatus(Integer.parseInt(CommonConstant.STATUS_1));
|
||||
LambdaQueryWrapper<ExtActProcess> queryWrapper = new LambdaQueryWrapper<ExtActProcess>();
|
||||
queryWrapper.eq(ExtActProcess::getProcessKey,key);
|
||||
extActProcessMapper.update(extActProcess, queryWrapper);
|
||||
|
||||
//获取最新发布的流程定义(激活)
|
||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).latestVersion().singleResult();
|
||||
if (processDefinition != null) {
|
||||
boolean suspended = repositoryService.isProcessDefinitionSuspended(processDefinition.getId());
|
||||
if (suspended) {
|
||||
repositoryService.activateProcessDefinitionById(processDefinition.getId(), true, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部署
|
||||
*
|
||||
* @param deploymentId 部署ID
|
||||
*/
|
||||
public void deleteDeployment(String deploymentId) {
|
||||
repositoryService.deleteDeployment(deploymentId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源文件
|
||||
*
|
||||
* @param deploymentId 部署ID
|
||||
* @param resourceName 资源名称
|
||||
*/
|
||||
public InputStream getResourceAsStream(String deploymentId, String resourceName) {
|
||||
InputStream resourceAsStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
|
||||
return resourceAsStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO 待测试1
|
||||
*
|
||||
* 获取流程图显示
|
||||
* @param httpServletResponse
|
||||
* @param processId
|
||||
*/
|
||||
public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) {
|
||||
/**
|
||||
* 获得当前活动的节点
|
||||
*/
|
||||
String processDefinitionId = "";
|
||||
if (this.isFinished(processId)) {
|
||||
// 如果流程已经结束,则得到结束节点
|
||||
HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
|
||||
processDefinitionId=pi.getProcessDefinitionId();
|
||||
} else {
|
||||
// 如果流程没有结束,则取当前活动节点
|
||||
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
|
||||
processDefinitionId=pi.getProcessDefinitionId();
|
||||
}
|
||||
List<String> highLightedActivitis = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* 获得活动的节点
|
||||
*/
|
||||
List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();
|
||||
for(HistoricActivityInstance tempActivity : highLightedActivitList){
|
||||
String activityId = tempActivity.getActivityId();
|
||||
highLightedActivitis.add(activityId);
|
||||
}
|
||||
|
||||
List<String> flows = new ArrayList<>();
|
||||
//获取流程图
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
|
||||
ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
|
||||
ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
|
||||
InputStream in = diagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivitis, flows, engconf.getActivityFontName(),engconf.getLabelFontName(),
|
||||
engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, true);
|
||||
|
||||
OutputStream out = null;
|
||||
byte[] buf = new byte[1024];
|
||||
int legth = 0;
|
||||
try {
|
||||
out = httpServletResponse.getOutputStream();
|
||||
while ((legth = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, legth);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("操作异常",e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(out);
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished(String processInstanceId) {
|
||||
return historyService.createHistoricProcessInstanceQuery().finished()
|
||||
.processInstanceId(processInstanceId).count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 中终止流程
|
||||
*
|
||||
* @param processInstanceId
|
||||
*/
|
||||
public void stopProcessInstanceById(String processInstanceId) {
|
||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
if (processInstance != null) {
|
||||
//一、获取終止节点
|
||||
List<EndEvent> endNodes = findEndFlowElement(processInstance.getProcessDefinitionId());
|
||||
String endId = endNodes.get(0).getId();
|
||||
//二、执行終止
|
||||
List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
|
||||
List<String> executionIds = new ArrayList<>();
|
||||
executions.forEach(execution -> executionIds.add(execution.getId()));
|
||||
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState();
|
||||
log.info("終止processInstanceId:{}成功", processInstanceId);
|
||||
} else {
|
||||
log.info("不存在运行的流程实例processInstanceId:{},请确认!", processInstanceId);
|
||||
}
|
||||
}
|
||||
|
||||
public List findEndFlowElement(String processDefId) {
|
||||
Process mainProcess = repositoryService.getBpmnModel(processDefId).getMainProcess();
|
||||
Collection<FlowElement> list = mainProcess.getFlowElements();
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
return list.stream().filter(f -> f instanceof EndEvent).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程设计的不同类型下的数量
|
||||
* @return
|
||||
*/
|
||||
public List<StartTypeStatisticsDto> countStartTypeNum(String lowAppId){
|
||||
return this.activitiMapper.countStartTypeNum(lowAppId);
|
||||
}
|
||||
}
|
||||
+1491
File diff suppressed because it is too large
Load Diff
+49
@@ -0,0 +1,49 @@
|
||||
package org.jeecg.modules.bpm.service.impl;
|
||||
|
||||
import org.flowable.engine.ManagementService;
|
||||
import org.jeecg.modules.bpm.cmd.AddHisCommentCmd;
|
||||
import org.jeecg.modules.bpm.dto.CommentVo;
|
||||
import org.jeecg.modules.bpm.mapper.FlowableCommentMapper;
|
||||
import org.jeecg.modules.bpm.service.IFlowableCommentService;
|
||||
import org.jeecg.modules.bpm.constant.enums.CommentTypeEnum;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 网上的参考代码(目前未使用)
|
||||
* 说明: 这个使用的是flowable官方表【act_hi_comment】【act_hi_attachment】
|
||||
* 目前jeecgboot自定义了两个表【ext_act_bpm_log】【ext_act_bpm_file】,未使用官方表
|
||||
*
|
||||
* @description: 流程日志记录 (待实现未用上)
|
||||
* @author : scott
|
||||
* @date :2022-12-06
|
||||
*/
|
||||
@Service("flowableCommentService")
|
||||
public class FlowableCommentServiceImpl implements IFlowableCommentService {
|
||||
@Autowired
|
||||
ManagementService managementService;
|
||||
@Autowired
|
||||
FlowableCommentMapper flowableCommentMapper;
|
||||
|
||||
@Override
|
||||
public void addComment(CommentVo comment) {
|
||||
managementService.executeCommand(new AddHisCommentCmd(comment.getTaskId(), comment.getUserId(), comment.getProcessInstanceId(),
|
||||
comment.getType(), comment.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommentVo> getFlowCommentVosByProcessInstanceId(String processInstanceId) {
|
||||
List<CommentVo> datas = flowableCommentMapper.getFlowCommentVosByProcessInstanceId(processInstanceId);
|
||||
datas.forEach(commentVo -> {
|
||||
commentVo.setTypeName(CommentTypeEnum.getEnumMsgByType(commentVo.getType()));
|
||||
});
|
||||
return datas;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addComment(String taskId, String userCode, String processInstanceId, String type, String comment) {
|
||||
managementService.executeCommand(new AddHisCommentCmd(taskId, userCode, processInstanceId,
|
||||
type, comment));
|
||||
}
|
||||
}
|
||||
+306
@@ -0,0 +1,306 @@
|
||||
package org.jeecg.modules.bpm.service.impl;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.FlowNode;
|
||||
import org.flowable.bpmn.model.SequenceFlow;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.history.HistoricActivityInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.image.ProcessDiagramGenerator;
|
||||
import org.jeecg.modules.bpm.service.ImageService;
|
||||
import org.jeecg.modules.bpm.service.impl.image.CustomProcessDiagramGenerator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* @TODO 待实现未用上1
|
||||
*
|
||||
* 流程追踪图生成类
|
||||
* @author liuxz
|
||||
*/
|
||||
@Service("imageServiceImpl")
|
||||
public class ImageServiceImpl implements ImageService {
|
||||
protected static Logger logger = LoggerFactory.getLogger(ImageServiceImpl.class);
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
|
||||
/**
|
||||
* 通过流程实例ID获取历史流程实例
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
*/
|
||||
public HistoricProcessInstance getHistoricProcInst(String procInstId) {
|
||||
return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过流程实例ID获取流程中已经执行的节点,按照执行先后顺序排序
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
*/
|
||||
public List<HistoricActivityInstance> getHistoricActivityInstAsc(String procInstId) {
|
||||
return historyService.createHistoricActivityInstanceQuery().processInstanceId(procInstId)
|
||||
.orderByHistoricActivityInstanceId().asc().list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过流程实例ID获取流程中正在执行的节点
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
*/
|
||||
public List<Execution> getRunningActivityInst(String procInstId) {
|
||||
return runtimeService.createExecutionQuery().processInstanceId(procInstId).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过流程实例ID获取已经完成的历史流程实例
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
*/
|
||||
public List<HistoricProcessInstance> getHistoricFinishedProcInst(String procInstId) {
|
||||
return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).finished().list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已流经的流程线,需要高亮显示高亮流程已发生流转的线id集合
|
||||
*
|
||||
* @param bpmnModel
|
||||
* @param historicActivityInstanceList
|
||||
* @return
|
||||
*/
|
||||
public List<String> getHighLightedFlows(BpmnModel bpmnModel,
|
||||
List<HistoricActivityInstance> historicActivityInstanceList) {
|
||||
// 已流经的流程线,需要高亮显示
|
||||
List<String> highLightedFlowIdList = new ArrayList<>();
|
||||
// 全部活动节点
|
||||
List<FlowNode> allHistoricActivityNodeList = new ArrayList<>();
|
||||
// 已完成的历史活动节点
|
||||
List<HistoricActivityInstance> finishedActivityInstanceList = new ArrayList<>();
|
||||
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
|
||||
// 获取流程节点
|
||||
FlowElement fe = bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
|
||||
if(fe instanceof FlowNode){
|
||||
FlowNode flowNode = (FlowNode) fe;
|
||||
allHistoricActivityNodeList.add(flowNode);
|
||||
}
|
||||
|
||||
|
||||
// 结束时间不为空,当前节点则已经完成
|
||||
if (historicActivityInstance.getEndTime() != null) {
|
||||
finishedActivityInstanceList.add(historicActivityInstance);
|
||||
}
|
||||
}
|
||||
|
||||
FlowNode currentFlowNode = null;
|
||||
FlowNode targetFlowNode = null;
|
||||
HistoricActivityInstance currentActivityInstance;
|
||||
// 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
|
||||
for (int k = 0; k < finishedActivityInstanceList.size(); k++) {
|
||||
currentActivityInstance = finishedActivityInstanceList.get(k);
|
||||
// 获得当前活动对应的节点信息及outgoingFlows信息
|
||||
FlowElement fe = bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
|
||||
if(fe instanceof FlowNode){
|
||||
currentFlowNode = (FlowNode)fe;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
|
||||
// 当前节点的所有流出线
|
||||
List<SequenceFlow> outgoingFlowList = currentFlowNode.getOutgoingFlows();
|
||||
/**
|
||||
* 遍历outgoingFlows并找到已流转的 满足如下条件认为已流转:
|
||||
* 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
|
||||
* 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转
|
||||
* (第2点有问题,有过驳回的,会只绘制驳回的流程线,通过走向下一级的流程线没有高亮显示)
|
||||
*/
|
||||
if ("parallelGateway".equals(currentActivityInstance.getActivityType()) || "inclusiveGateway".equals(
|
||||
currentActivityInstance.getActivityType())) {
|
||||
// 遍历历史活动节点,找到匹配流程目标节点的
|
||||
for (SequenceFlow outgoingFlow : outgoingFlowList) {
|
||||
// 获取当前节点流程线对应的下级节点
|
||||
targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(outgoingFlow.getTargetRef(),
|
||||
true);
|
||||
// 如果下级节点包含在所有历史节点中,则将当前节点的流出线高亮显示
|
||||
if (allHistoricActivityNodeList.contains(targetFlowNode)) {
|
||||
highLightedFlowIdList.add(outgoingFlow.getId());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* 2、当前节点不是并行网关或兼容网关
|
||||
* 【已解决-问题】如果当前节点有驳回功能,驳回到申请节点,
|
||||
* 则因为申请节点在历史节点中,导致当前节点驳回到申请节点的流程线被高亮显示,但实际并没有进行驳回操作
|
||||
*/
|
||||
List<Map<String, Object>> tempMapList = new ArrayList<>();
|
||||
// 当前节点ID
|
||||
String currentActivityId = currentActivityInstance.getActivityId();
|
||||
int size = historicActivityInstanceList.size();
|
||||
boolean ifStartFind = false;
|
||||
boolean ifFinded = false;
|
||||
HistoricActivityInstance historicActivityInstance;
|
||||
// 循环当前节点的所有流出线
|
||||
// 循环所有历史节点
|
||||
logger.debug("【开始】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线", currentActivityId);
|
||||
logger.debug("循环历史节点");
|
||||
for (int i = 0; i < historicActivityInstanceList.size(); i++) {
|
||||
// // 如果当前节点流程线对应的下级节点在历史节点中,则该条流程线进行高亮显示(【问题】有驳回流程线时,即使没有进行驳回操作,因为申请节点在历史节点中,也会将驳回流程线高亮显示-_-||)
|
||||
// if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
|
||||
// Map<String, Object> map = new HashMap<>();
|
||||
// map.put("highLightedFlowId", sequenceFlow.getId());
|
||||
// map.put("highLightedFlowStartTime", historicActivityInstance.getStartTime().getTime());
|
||||
// tempMapList.add(map);
|
||||
// // highLightedFlowIdList.add(sequenceFlow.getId());
|
||||
// }
|
||||
// 历史节点
|
||||
historicActivityInstance = historicActivityInstanceList.get(i);
|
||||
logger.debug("第【{}/{}】个历史节点-ActivityId=[{}]", i + 1, size, historicActivityInstance.getActivityId());
|
||||
// 如果循环历史节点中的id等于当前节点id,从当前历史节点继续先后查找是否有当前节点流程线等于的节点
|
||||
// 历史节点的序号需要大于等于已完成历史节点的序号,防止驳回重审一个节点经过两次是只取第一次的流出线高亮显示,第二次的不显示
|
||||
if (i >= k && historicActivityInstance.getActivityId().equals(currentActivityId)) {
|
||||
logger.debug("第[{}]个历史节点和当前节点一致-ActivityId=[{}]", i + 1, historicActivityInstance
|
||||
.getActivityId());
|
||||
ifStartFind = true;
|
||||
// 跳过当前节点继续查找下一个节点
|
||||
continue;
|
||||
}
|
||||
if (ifStartFind) {
|
||||
logger.debug("[开始]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);
|
||||
|
||||
ifFinded = false;
|
||||
for (SequenceFlow sequenceFlow : outgoingFlowList) {
|
||||
// 如果当前节点流程线对应的下级节点在其后面的历史节点中,则该条流程线进行高亮显示
|
||||
// 【问题】
|
||||
logger.debug("当前流出线的下级节点=[{}]", sequenceFlow.getTargetRef());
|
||||
if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
|
||||
logger.debug("当前节点[{}]需高亮显示的流出线=[{}]", currentActivityId, sequenceFlow.getId());
|
||||
highLightedFlowIdList.add(sequenceFlow.getId());
|
||||
// 暂时默认找到离当前节点最近的下一级节点即退出循环,否则有多条流出线时将全部被高亮显示
|
||||
ifFinded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.debug("[完成]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);
|
||||
}
|
||||
if (ifFinded) {
|
||||
// 暂时默认找到离当前节点最近的下一级节点即退出历史节点循环,否则有多条流出线时将全部被高亮显示
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.debug("【完成】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线", currentActivityId);
|
||||
// if (!CollectionUtils.isEmpty(tempMapList)) {
|
||||
// // 遍历匹配的集合,取得开始时间最早的一个
|
||||
// long earliestStamp = 0L;
|
||||
// String highLightedFlowId = null;
|
||||
// for (Map<String, Object> map : tempMapList) {
|
||||
// long highLightedFlowStartTime = Long.valueOf(map.get("highLightedFlowStartTime").toString());
|
||||
// if (earliestStamp == 0 || earliestStamp <= highLightedFlowStartTime) {
|
||||
// highLightedFlowId = map.get("highLightedFlowId").toString();
|
||||
// earliestStamp = highLightedFlowStartTime;
|
||||
// }
|
||||
// }
|
||||
// highLightedFlowIdList.add(highLightedFlowId);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return highLightedFlowIdList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程实例Id,获取实时流程图片
|
||||
*
|
||||
* @param procInstId
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public byte[] generateImageByProcInstId(String procInstId) throws Exception {
|
||||
if (org.apache.commons.lang.StringUtil.isEmpty(procInstId)) {
|
||||
logger.error("[错误]-传入的参数procInstId为空!");
|
||||
throw new Exception("[异常]-传入的参数procInstId为空!");
|
||||
}
|
||||
InputStream imageStream = null;
|
||||
try {
|
||||
// 通过流程实例ID获取历史流程实例
|
||||
HistoricProcessInstance historicProcessInstance = getHistoricProcInst(procInstId);
|
||||
|
||||
// 通过流程实例ID获取流程中已经执行的节点,按照执行先后顺序排序
|
||||
List<HistoricActivityInstance> historicActivityInstanceList = getHistoricActivityInstAsc(procInstId);
|
||||
|
||||
|
||||
// 将已经执行的节点ID放入高亮显示节点集合
|
||||
List<String> highLightedActivitiIdList = new ArrayList<>();
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
|
||||
highLightedActivitiIdList.add(historicActivityInstance.getActivityId());
|
||||
logger.debug("已执行的节点[{}-{}-{}-{}]", historicActivityInstance.getId(), historicActivityInstance
|
||||
.getActivityId(), historicActivityInstance.getActivityName(), historicActivityInstance
|
||||
.getAssignee());
|
||||
}
|
||||
|
||||
// 通过流程实例ID获取流程中正在执行的节点
|
||||
List<Execution> runningActivityInstanceList = getRunningActivityInst(procInstId);
|
||||
List<String> runningActivitiIdList = new ArrayList<String>();
|
||||
for (Execution execution : runningActivityInstanceList) {
|
||||
if (org.apache.commons.lang.StringUtil.isNotEmpty(execution.getActivityId())) {
|
||||
runningActivitiIdList.add(execution.getActivityId());
|
||||
logger.debug("执行中的节点[{}-{}-{}]", execution.getId(), execution.getActivityId(), execution.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 通过流程实例ID获取已经完成的历史流程实例
|
||||
List<HistoricProcessInstance> historicFinishedProcessInstanceList = getHistoricFinishedProcInst(procInstId);
|
||||
|
||||
// 定义流程画布生成器
|
||||
ProcessDiagramGenerator processDiagramGenerator = new CustomProcessDiagramGenerator();
|
||||
|
||||
// 获取流程定义Model对象
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
|
||||
|
||||
|
||||
// 获取已流经的流程线,需要高亮显示高亮流程已发生流转的线id集合
|
||||
List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, historicActivityInstanceList);
|
||||
|
||||
// 使用默认配置获得流程图表生成器,并生成追踪图片字符流
|
||||
imageStream = ((CustomProcessDiagramGenerator) processDiagramGenerator).generateDiagramCustom(bpmnModel, "png",
|
||||
highLightedActivitiIdList, runningActivitiIdList, highLightedFlowIds,
|
||||
"宋体", "微软雅黑", "黑体",
|
||||
null, 2.0);
|
||||
// 将InputStream数据流转换为byte[]
|
||||
byte[] buffer = new byte[imageStream.available()];
|
||||
imageStream.read(buffer);
|
||||
return buffer;
|
||||
} catch (Exception e) {
|
||||
logger.error("通过流程实例ID[{}]获取流程图时出现异常!", e);
|
||||
throw new Exception("通过流程实例ID" + procInstId + "获取流程图时出现异常!", e);
|
||||
} finally {
|
||||
if (imageStream != null) {
|
||||
imageStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
package org.jeecg.modules.bpm.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.ExtensionElement;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
|
||||
import org.flowable.editor.language.json.converter.util.CollectionUtils;
|
||||
import org.flowable.engine.*;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstanceQuery;
|
||||
import org.flowable.identitylink.api.IdentityLink;
|
||||
import org.flowable.idm.api.Group;
|
||||
import org.flowable.task.api.DelegationState;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
|
||||
import org.jeecg.modules.bpm.cmd.util.ApiAssert;
|
||||
import org.jeecg.modules.bpm.service.IPermissionService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: 流程校验Service
|
||||
* @Author: zyf
|
||||
* @Date: 2022-05-10
|
||||
*/
|
||||
@Service("permissionServiceImpl")
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class PermissionServiceImpl implements IPermissionService {
|
||||
/**
|
||||
* 任务处理Service
|
||||
* 1查询分配给某人或一组的任务 2产生独立的任务,不依赖于任何流程实例的任务 3操纵用户分配任务 4完成任务。
|
||||
*/
|
||||
@Autowired
|
||||
protected TaskService taskService;
|
||||
/**
|
||||
* 查询各种历史数据
|
||||
*/
|
||||
@Autowired
|
||||
protected HistoryService historyService;
|
||||
/**
|
||||
* 流程运行时Service
|
||||
* 1:用来获取和保存流程变量 2: 查询流程实例和当前执行位置 3:流程实例需要等待一个外部触发,从而继续进行。
|
||||
*/
|
||||
@Autowired
|
||||
protected RuntimeService runtimeService;
|
||||
/**
|
||||
* 用来执行flowable自定义命令
|
||||
*/
|
||||
@Autowired
|
||||
protected ManagementService managementService;
|
||||
@Autowired
|
||||
protected IdentityService identityService;
|
||||
@Autowired
|
||||
protected FormService formService;
|
||||
/**
|
||||
* 管理控制部署与流程定义
|
||||
*/
|
||||
@Autowired
|
||||
protected RepositoryService repositoryService;
|
||||
|
||||
@Override
|
||||
public boolean checkUserIsTaskOwnerOrAssignee(String userName, Task task) {
|
||||
return userName.equals(task.getOwner()) || userName.equals(task.getAssignee());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkUserIsInitiatorAndCanCompleteTask(String userName, Task task) {
|
||||
boolean result = false;
|
||||
String processInstanceId = task.getProcessInstanceId();
|
||||
if (ObjectUtil.isNotEmpty(processInstanceId)) {
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
|
||||
String startUserId = historicProcessInstance.getStartUserId();
|
||||
if (ObjectUtil.isNotEmpty(historicProcessInstance) && ObjectUtil.isNotEmpty(startUserId)) {
|
||||
if (userName.equals(startUserId) && checkIfInitiatorCanCompleteTask(task)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证发起人是否可以完成任务
|
||||
*
|
||||
* @param task
|
||||
* @return
|
||||
*/
|
||||
private boolean checkIfInitiatorCanCompleteTask(Task task) {
|
||||
boolean result = false;
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
|
||||
FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
|
||||
if (flowElement instanceof UserTask) {
|
||||
UserTask userTask = (UserTask) flowElement;
|
||||
List<ExtensionElement> extensionElements = userTask.getExtensionElements().get("initiator-can-complete");
|
||||
if (CollectionUtils.isNotEmpty(extensionElements)) {
|
||||
String value = extensionElements.get(0).getElementText();
|
||||
if (org.apache.commons.lang.StringUtil.isNotEmpty(value) && Boolean.valueOf(value)) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isTaskPending(Task task) {
|
||||
return DelegationState.PENDING.equals(task.getDelegationState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task checkPermissionOnTask(String taskId, String userId) {
|
||||
ApiAssert.isNotEmpty("taskId不能为空", taskId);
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
ApiAssert.isNotEmpty("任务不存在", task);
|
||||
if (isTaskOwnerOrAssignee(userId, taskId)) {
|
||||
return task;
|
||||
}
|
||||
ApiAssert.failure("用户无权限");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task checkPermissionOnTask(String taskId, String userId, String assignee) {
|
||||
ApiAssert.isNotEmpty("taskId不能为空", taskId);
|
||||
ApiAssert.isNotEmpty("办理人不能为空", assignee);
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
ApiAssert.isNotEmpty("任务不存在", task);
|
||||
if (isTaskOwnerOrAssignee(userId, task)) {
|
||||
String owner = task.getOwner();
|
||||
String oldAssignee = task.getAssignee();
|
||||
if (assignee.equals(oldAssignee)) {
|
||||
ApiAssert.failure("不能委派给当前办理人");
|
||||
}
|
||||
if (assignee.equals(owner)) {
|
||||
ApiAssert.failure("不能委派给任务拥有者");
|
||||
}
|
||||
return task;
|
||||
}
|
||||
return task;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermissionOnProcessDefinition(String processDefinitionId, String userId) {
|
||||
List<IdentityLink> identityLinks = repositoryService.getIdentityLinksForProcessDefinition(processDefinitionId);
|
||||
List<String> startUserIds = getPotentialStarterUserIds(identityLinks);
|
||||
List<String> startGroupIds = getPotentialStarterGroupIds(identityLinks);
|
||||
if (startUserIds.isEmpty() && startGroupIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (startUserIds.contains(userId)) {
|
||||
return;
|
||||
}
|
||||
List<String> groupsIds = getGroupIdsForUser(userId);
|
||||
for (String startGroupId : startGroupIds) {
|
||||
if (groupsIds.contains(startGroupId)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ApiAssert.failure("您没有执行流程的权限,请联系管理员");
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoricProcessInstance checkPermissionOnProcessInstance(String processInstanceId, String userId) {
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
boolean hasPermission = hasReadPermissionOnProcessInstance(userId, historicProcessInstance, processInstanceId);
|
||||
if (!hasPermission) {
|
||||
}
|
||||
return historicProcessInstance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the given user is allowed to read the process instance.
|
||||
*/
|
||||
public boolean hasReadPermissionOnProcessInstance(String userId, HistoricProcessInstance historicProcessInstance,
|
||||
String processInstanceId) {
|
||||
if (historicProcessInstance == null) {
|
||||
throw new FlowableObjectNotFoundException(
|
||||
"ProcessInstance with id: " + processInstanceId + " does not exist");
|
||||
}
|
||||
|
||||
// Start user check
|
||||
if (historicProcessInstance.getStartUserId() != null && historicProcessInstance.getStartUserId().equals(userId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if the user is involved in the task
|
||||
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
|
||||
historicProcessInstanceQuery.processInstanceId(processInstanceId);
|
||||
historicProcessInstanceQuery.involvedUser(userId);
|
||||
if (historicProcessInstanceQuery.count() > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Visibility: check if there are any tasks for the current user
|
||||
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
|
||||
historicTaskInstanceQuery.processInstanceId(processInstanceId);
|
||||
historicTaskInstanceQuery.taskInvolvedUser(userId);
|
||||
if (historicTaskInstanceQuery.count() > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<String> groupIds = getGroupIdsForUser(userId);
|
||||
if (!groupIds.isEmpty()) {
|
||||
historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
|
||||
historicTaskInstanceQuery.processInstanceId(processInstanceId).taskCandidateGroupIn(groupIds);
|
||||
return historicTaskInstanceQuery.count() > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean isTaskOwnerOrAssignee(String currentUser, String taskId) {
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
return isTaskOwnerOrAssignee(currentUser, task);
|
||||
}
|
||||
|
||||
|
||||
private boolean isTaskOwnerOrAssignee(String currentUser, Task task) {
|
||||
return task.getAssignee()==null || currentUser.equals(task.getOwner()) || currentUser.equals(task.getAssignee());
|
||||
}
|
||||
|
||||
public List<String> getPotentialStarterUserIds(List<IdentityLink> identityLinks) {
|
||||
List<String> userIds = new ArrayList<>();
|
||||
for (IdentityLink identityLink : identityLinks) {
|
||||
if (identityLink.getUserId() != null && identityLink.getUserId().length() > 0) {
|
||||
if (!userIds.contains(identityLink.getUserId())) {
|
||||
userIds.add(identityLink.getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public List<String> getPotentialStarterGroupIds(List<IdentityLink> identityLinks) {
|
||||
List<String> groupIds = new ArrayList<>();
|
||||
for (IdentityLink identityLink : identityLinks) {
|
||||
if (identityLink.getGroupId() != null && identityLink.getGroupId().length() > 0) {
|
||||
if (!groupIds.contains(identityLink.getGroupId())) {
|
||||
groupIds.add(identityLink.getGroupId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return groupIds;
|
||||
}
|
||||
|
||||
|
||||
private List<String> getGroupIdsForUser(String userId) {
|
||||
List<String> groupIds = new ArrayList<>();
|
||||
List<Group> userGroups = identityService.createGroupQuery().groupMember(userId).list();
|
||||
for (Group group : userGroups) {
|
||||
groupIds.add(String.valueOf(group.getId()));
|
||||
}
|
||||
return groupIds;
|
||||
}
|
||||
}
|
||||
+262
@@ -0,0 +1,262 @@
|
||||
package org.jeecg.modules.bpm.service.impl;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.flowable.engine.*;
|
||||
import org.flowable.engine.impl.RepositoryServiceImpl;
|
||||
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.mapper.ActivitiMapper;
|
||||
import org.jeecg.modules.bpm.service.IPermissionService;
|
||||
import org.jeecg.modules.bpm.util.XmlActivitiUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 类名:SuperTaskService
|
||||
* 功能: 工作流核心处理类
|
||||
* 详细:
|
||||
* 作者:jeecg
|
||||
* 版本:1.0
|
||||
* 日期:2013-7-25 上午10:19:16
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("superTaskService")
|
||||
public class SuperTaskService {
|
||||
|
||||
@Autowired
|
||||
protected RepositoryService repositoryService; //部署流程服务
|
||||
@Autowired
|
||||
protected RuntimeService runtimeService; //流程执行服务
|
||||
@Autowired
|
||||
protected TaskService taskService; //任务服务
|
||||
@Autowired
|
||||
protected HistoryService historyService; //历史服务
|
||||
@Autowired
|
||||
protected ActivitiMapper activitiMapper;
|
||||
@Autowired
|
||||
protected IPermissionService permissionService;
|
||||
|
||||
|
||||
/**
|
||||
* 走向流程 【带参数】
|
||||
*
|
||||
* @param taskId 当前任务节点 ID
|
||||
* @param nextTaskId 下个任务节点ID
|
||||
* @param variables 流程存储参数
|
||||
* @throws Exception
|
||||
*/
|
||||
public synchronized void goProcessTaskNode(String taskId, String nextTaskId, Map<String, Object> variables) throws Exception {
|
||||
// try {
|
||||
// 查找所有并行任务节点,同时驳回
|
||||
List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
|
||||
for (Task task : taskList) {
|
||||
if (taskId.equals(task.getId())) {
|
||||
commitProcess(task.getId(), variables, nextTaskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 走向流程 【不带参数】
|
||||
*
|
||||
* @param taskId 当前任务节点
|
||||
* @param nextTaskId 下个任务节点
|
||||
* @throws Exception
|
||||
*/
|
||||
public void goProcessTaskNode(String taskId, String nextTaskId) throws Exception {
|
||||
if (org.apache.commons.lang.StringUtil.isEmpty(nextTaskId)) {
|
||||
throw new Exception("目标节点ID为空!");
|
||||
}
|
||||
|
||||
// 查找所有并行任务节点,同时取回
|
||||
List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
|
||||
for (Task task : taskList) {
|
||||
commitProcess(task.getId(), null, nextTaskId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param taskId 当前任务ID
|
||||
* @param variables 流程变量
|
||||
* @param activityId 流程转向执行任务节点ID<br>
|
||||
* 此参数为空,默认为提交操作
|
||||
* @throws Exception
|
||||
*/
|
||||
private void commitProcess(String taskId, Map<String, Object> variables, String activityId) throws Exception {
|
||||
// 跳转节点为空,默认提交操作
|
||||
if (oConvertUtils.isEmpty(activityId)) {
|
||||
taskService.complete(taskId, variables);
|
||||
} else {// 流程转向操作
|
||||
turnTransition(taskId, activityId, variables);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程转向操作
|
||||
*
|
||||
* @param taskId 当前任务ID
|
||||
* @param activityId 目标节点任务ID
|
||||
* @param variables 流程变量
|
||||
* @throws Exception
|
||||
*/
|
||||
private void turnTransition(String taskId, String activityId, Map<String, Object> variables) throws Exception {
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.processInstanceId(task.getProcessInstanceId())
|
||||
.moveActivityIdTo(task.getTaskDefinitionKey(), activityId)
|
||||
.changeState();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 中止流程(特权人直接审批通过等)
|
||||
*
|
||||
* @param taskId
|
||||
*/
|
||||
public void endProcess(String taskId) throws Exception {
|
||||
commitProcess(taskId, null, "end");
|
||||
}
|
||||
|
||||
|
||||
static {
|
||||
StringUtil.lastIndexOf();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据任务ID获取流程定义
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public ProcessDefinitionEntity findProcessDefinitionEntityByTaskId(
|
||||
String taskId) throws Exception {
|
||||
// 取得流程定义
|
||||
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
|
||||
.getDeployedProcessDefinition(findTaskById(taskId)
|
||||
.getProcessDefinitionId());
|
||||
|
||||
if (processDefinition == null) {
|
||||
throw new Exception("流程定义未找到!");
|
||||
}
|
||||
|
||||
return processDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据任务ID获取对应的流程实例
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public ProcessInstance findProcessInstanceByTaskId(String taskId)
|
||||
throws Exception {
|
||||
// 找到流程实例
|
||||
ProcessInstance processInstance = runtimeService
|
||||
.createProcessInstanceQuery().processInstanceId(
|
||||
findTaskById(taskId).getProcessInstanceId())
|
||||
.singleResult();
|
||||
if (processInstance == null) {
|
||||
throw new Exception("流程实例未找到!");
|
||||
}
|
||||
return processInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据任务ID获得任务实例
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private TaskEntity findTaskById(String taskId) throws Exception {
|
||||
TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
if (task == null) {
|
||||
throw new Exception("任务实例未找到!");
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据流程实例ID和任务key值查询所有同级任务集合
|
||||
*
|
||||
* @param processInstanceId
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
private List<Task> findTaskListByKey(String processInstanceId, String key) {
|
||||
return taskService.createTaskQuery().processInstanceId(
|
||||
processInstanceId).taskDefinitionKey(key).list();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 转办流程
|
||||
*
|
||||
* @param taskId 当前任务节点ID
|
||||
* @param userCode 被转办人Code
|
||||
*/
|
||||
public void transferAssignee(String taskId, String userCode) {
|
||||
taskService.setAssignee(taskId, userCode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 指定下一步操作人
|
||||
*
|
||||
* @param proInsId
|
||||
* @param taskDefKey
|
||||
*/
|
||||
public String getTaskIdByProins(String proInsId, String taskDefKey) {
|
||||
List<String> list = activitiMapper.getTaskIdByProins(proInsId, taskDefKey);
|
||||
if (list != null && list.size() > 0) {
|
||||
return list.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过流程定义key和任务,判断任务是否是会签节点
|
||||
* 处理方法:通过解析xml文件
|
||||
*
|
||||
* @param taskId
|
||||
* @return
|
||||
*/
|
||||
//TODO
|
||||
public boolean checkUserTaskIsHuiQian(String taskId, String taskkey) {
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
//String taskkey = task.getTaskDefinitionKey();
|
||||
String processkey = task.getProcessDefinitionId();
|
||||
ProcessDefinition pd = repositoryService.getProcessDefinition(processkey);
|
||||
InputStream resourceAsStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), pd.getResourceName());
|
||||
String xmlString = null;
|
||||
try {
|
||||
xmlString = IOUtils.toString(resourceAsStream);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return XmlActivitiUtil.parseXml(xmlString, taskkey);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+1330
File diff suppressed because it is too large
Load Diff
+1006
File diff suppressed because it is too large
Load Diff
+735
@@ -0,0 +1,735 @@
|
||||
//package org.jeecg.modules.bpm.service.impl.image;
|
||||
//
|
||||
//import com.sun.corba.se.impl.orbutil.graph.Graph;
|
||||
//import com.sun.javafx.geom.Edge;
|
||||
//import org.apache.commons.io.FilenameUtils;
|
||||
//import org.flowable.bpmn.constants.BpmnXMLConstants;
|
||||
//import org.flowable.bpmn.model.*;
|
||||
//import org.flowable.bpmn.model.Process;
|
||||
//import org.flowable.common.engine.impl.Page;
|
||||
//import org.flowable.common.engine.impl.context.Context;
|
||||
//import org.flowable.engine.history.HistoricActivityInstance;
|
||||
//import org.flowable.engine.history.HistoricProcessInstance;
|
||||
//import org.flowable.engine.impl.HistoricActivityInstanceQueryImpl;
|
||||
//import org.flowable.engine.impl.cmd.GetBpmnModelCmd;
|
||||
//import org.flowable.engine.impl.cmd.GetDeploymentProcessDefinitionCmd;
|
||||
//import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
//
|
||||
//import javax.imageio.ImageIO;
|
||||
//import java.awt.*;
|
||||
//import java.awt.geom.AffineTransform;
|
||||
//import java.awt.geom.Ellipse2D.Double;
|
||||
//import java.awt.geom.Line2D;
|
||||
//import java.awt.geom.Path2D;
|
||||
//import java.awt.geom.RoundRectangle2D;
|
||||
//import java.awt.image.BufferedImage;
|
||||
//import java.io.ByteArrayInputStream;
|
||||
//import java.io.ByteArrayOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.List;
|
||||
//
|
||||
///**
|
||||
// * 原来有用的类
|
||||
// *
|
||||
// * 流程图绘制工具
|
||||
// */
|
||||
//public class OriginalCustomProcessDiagramGenerator {
|
||||
// //update-begin 5.22流程图矩形圆角问题
|
||||
// //public static final int OFFSET_SUBPROCESS = 5;
|
||||
// //public static final int OFFSET_TASK = 20;
|
||||
// public static final int OFFSET_SUBPROCESS = 0;
|
||||
// public static final int OFFSET_TASK = 0;
|
||||
// //update-end 5.22流程图矩形圆角问题
|
||||
//
|
||||
// private static List<String> taskType = new ArrayList<String>();
|
||||
// private static List<String> eventType = new ArrayList<String>();
|
||||
// private static List<String> gatewayType = new ArrayList<String>();
|
||||
// private static List<String> subProcessType = new ArrayList<String>();
|
||||
// private static Color RUNNING_COLOR = Color.RED;
|
||||
// private static Color HISTORY_COLOR = Color.GREEN;
|
||||
// private static Color SKIP_COLOR = Color.GRAY;
|
||||
// private static Stroke THICK_BORDER_STROKE = new BasicStroke(3.0f);
|
||||
// private int minX;
|
||||
// private int minY;
|
||||
//
|
||||
// public CustomProcessDiagramGenerator() {
|
||||
// init();
|
||||
// }
|
||||
//
|
||||
// protected static void init() {
|
||||
// taskType.add(BpmnXMLConstants.ELEMENT_TASK_MANUAL);
|
||||
// taskType.add(BpmnXMLConstants.ELEMENT_TASK_RECEIVE);
|
||||
// taskType.add(BpmnXMLConstants.ELEMENT_TASK_SCRIPT);
|
||||
// taskType.add(BpmnXMLConstants.ELEMENT_TASK_SEND);
|
||||
// taskType.add(BpmnXMLConstants.ELEMENT_TASK_SERVICE);
|
||||
// taskType.add(BpmnXMLConstants.ELEMENT_TASK_USER);
|
||||
//
|
||||
// gatewayType.add(BpmnXMLConstants.ELEMENT_GATEWAY_EXCLUSIVE);
|
||||
// gatewayType.add(BpmnXMLConstants.ELEMENT_GATEWAY_INCLUSIVE);
|
||||
// gatewayType.add(BpmnXMLConstants.ELEMENT_GATEWAY_EVENT);
|
||||
// gatewayType.add(BpmnXMLConstants.ELEMENT_GATEWAY_PARALLEL);
|
||||
//
|
||||
// eventType.add("intermediateTimer");
|
||||
// eventType.add("intermediateMessageCatch");
|
||||
// eventType.add("intermediateSignalCatch");
|
||||
// eventType.add("intermediateSignalThrow");
|
||||
// eventType.add("messageStartEvent");
|
||||
// eventType.add("startTimerEvent");
|
||||
// eventType.add(BpmnXMLConstants.ELEMENT_ERROR);
|
||||
// eventType.add(BpmnXMLConstants.ELEMENT_EVENT_START);
|
||||
// eventType.add("errorEndEvent");
|
||||
// eventType.add(BpmnXMLConstants.ELEMENT_EVENT_END);
|
||||
//
|
||||
// subProcessType.add(BpmnXMLConstants.ELEMENT_SUBPROCESS);
|
||||
// subProcessType.add(BpmnXMLConstants.ELEMENT_CALL_ACTIVITY);
|
||||
// }
|
||||
//
|
||||
// public InputStream generateDiagram(String processInstanceId)
|
||||
// throws IOException {
|
||||
// HistoricProcessInstance historicProcessInstance = Context
|
||||
// .getCommandContext().getHistoricProcessInstanceEntityManager()
|
||||
// .findHistoricProcessInstance(processInstanceId);
|
||||
// String processDefinitionId = historicProcessInstance
|
||||
// .getProcessDefinitionId();
|
||||
// GetBpmnModelCmd getBpmnModelCmd = new GetBpmnModelCmd(
|
||||
// processDefinitionId);
|
||||
// BpmnModel bpmnModel = getBpmnModelCmd.execute(Context
|
||||
// .getCommandContext());
|
||||
// Point point = getMinXAndMinY(bpmnModel);
|
||||
// //5.22流程图跟踪错位问题解决start
|
||||
//
|
||||
// //update-begin--Author:scott Date:20220112 for:LOWCOD-2229【新版流程】流程设计时上移流程后,图标注错乱---------
|
||||
// this.minX = point.x;
|
||||
// if (this.minX >= 0) {
|
||||
// this.minX = 0;
|
||||
// this.minX = (this.minX <= 5) ? 5 : this.minX;
|
||||
// this.minX -= 5;
|
||||
// }
|
||||
//
|
||||
// this.minY = point.y;
|
||||
// if (this.minY >= 0) {
|
||||
// this.minY = 0;
|
||||
// this.minY = (this.minY <= 5) ? 5 : this.minY;
|
||||
// this.minY -= 5;
|
||||
// }
|
||||
// //update-end--Author:scott Date:20220112 for:LOWCOD-2229【新版流程】流程设计时上移流程后,图标注错乱---------
|
||||
//
|
||||
// ByteArrayInputStream byteArrayInputStream = null;
|
||||
// InputStream originDiagram =null;
|
||||
// ByteArrayOutputStream out=null;
|
||||
// try {
|
||||
// ProcessDefinitionEntity definition = new GetDeploymentProcessDefinitionCmd(
|
||||
// processDefinitionId).execute(Context.getCommandContext());
|
||||
// String diagramResourceName = definition.getDiagramResourceName();
|
||||
// String deploymentId = definition.getDeploymentId();
|
||||
// byte[] bytes = Context
|
||||
// .getCommandContext()
|
||||
// .getResourceEntityManager()
|
||||
// .findResourceByDeploymentIdAndResourceName(deploymentId,
|
||||
// diagramResourceName).getBytes();
|
||||
// originDiagram = new ByteArrayInputStream(bytes);
|
||||
// BufferedImage image = ImageIO.read(originDiagram);
|
||||
//
|
||||
// HistoricActivityInstanceQueryImpl historicActivityInstanceQueryImpl = new HistoricActivityInstanceQueryImpl();
|
||||
// historicActivityInstanceQueryImpl.processInstanceId(processInstanceId)
|
||||
// .orderByHistoricActivityInstanceStartTime().asc();
|
||||
//
|
||||
// Page page = new Page(0, 100);
|
||||
// List<HistoricActivityInstance> activityInstances = Context
|
||||
// .getCommandContext()
|
||||
// .getHistoricActivityInstanceEntityManager()
|
||||
// .findHistoricActivityInstancesByQueryCriteria(
|
||||
// historicActivityInstanceQueryImpl, page);
|
||||
//
|
||||
// this.drawHistoryFlow(image, processInstanceId);
|
||||
//
|
||||
// for (HistoricActivityInstance historicActivityInstance : activityInstances) {
|
||||
// String historicActivityId = historicActivityInstance
|
||||
// .getActivityId();
|
||||
// ActivityImpl activity = definition.findActivity(historicActivityId);
|
||||
//
|
||||
// if (activity != null) {
|
||||
// if (historicActivityInstance.getEndTime() == null) {
|
||||
// // 节点正在运行中
|
||||
// signRunningNode(image, activity.getX() - this.minX,
|
||||
// activity.getY() - this.minY, activity.getWidth(),
|
||||
// activity.getHeight(),
|
||||
// historicActivityInstance.getActivityType());
|
||||
// } else {
|
||||
// String deleteReason = null;
|
||||
//
|
||||
// if (historicActivityInstance.getTaskId() != null) {
|
||||
// deleteReason = Context
|
||||
// .getCommandContext()
|
||||
// .getHistoricTaskInstanceEntityManager()
|
||||
// .findHistoricTaskInstanceById(
|
||||
// historicActivityInstance.getTaskId())
|
||||
// .getDeleteReason();
|
||||
// }
|
||||
//
|
||||
// // 节点已经结束
|
||||
// if ("跳过".equals(deleteReason)) {
|
||||
// signSkipNode(image, activity.getX() - this.minX,
|
||||
// activity.getY() - this.minY,
|
||||
// activity.getWidth(), activity.getHeight(),
|
||||
// historicActivityInstance.getActivityType());
|
||||
// } else {
|
||||
// signHistoryNode(image, activity.getX() - this.minX,
|
||||
// activity.getY() - this.minY,
|
||||
// activity.getWidth(), activity.getHeight(),
|
||||
// historicActivityInstance.getActivityType());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// out = new ByteArrayOutputStream();
|
||||
// String formatName = getDiagramExtension(diagramResourceName);
|
||||
// ImageIO.write(image, formatName, out);
|
||||
// byteArrayInputStream = new ByteArrayInputStream(out.toByteArray());
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }finally{
|
||||
// try {
|
||||
// if(out!=null){
|
||||
// out.close();
|
||||
// }
|
||||
// if(originDiagram!=null){
|
||||
// originDiagram.close();
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// return byteArrayInputStream;
|
||||
// }
|
||||
//
|
||||
// private static String getDiagramExtension(String diagramResourceName) {
|
||||
// return FilenameUtils.getExtension(diagramResourceName);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 标记运行节点
|
||||
// *
|
||||
// * @param image
|
||||
// * 原始图片
|
||||
// * @param x
|
||||
// * 左上角节点坐在X位置
|
||||
// * @param y
|
||||
// * 左上角节点坐在Y位置
|
||||
// * @param width
|
||||
// * 宽
|
||||
// * @param height
|
||||
// * 高
|
||||
// * @param activityType
|
||||
// * 节点类型
|
||||
// */
|
||||
// private static void signRunningNode(BufferedImage image, int x, int y,
|
||||
// int width, int height, String activityType) {
|
||||
// Color nodeColor = RUNNING_COLOR;
|
||||
// Graphics2D graphics = image.createGraphics();
|
||||
//
|
||||
// try {
|
||||
// drawNodeBorder(x, y, width, height, graphics, nodeColor,
|
||||
// activityType);
|
||||
// } finally {
|
||||
// graphics.dispose();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 标记历史节点
|
||||
// *
|
||||
// * @param image
|
||||
// * 原始图片
|
||||
// * @param x
|
||||
// * 左上角节点坐在X位置
|
||||
// * @param y
|
||||
// * 左上角节点坐在Y位置
|
||||
// * @param width
|
||||
// * 宽
|
||||
// * @param height
|
||||
// * 高
|
||||
// * @param activityType
|
||||
// * 节点类型
|
||||
// */
|
||||
// private static void signHistoryNode(BufferedImage image, int x, int y,
|
||||
// int width, int height, String activityType) {
|
||||
// Color nodeColor = HISTORY_COLOR;
|
||||
// Graphics2D graphics = image.createGraphics();
|
||||
//
|
||||
// try {
|
||||
// drawNodeBorder(x, y, width, height, graphics, nodeColor,
|
||||
// activityType);
|
||||
// } finally {
|
||||
// graphics.dispose();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static void signSkipNode(BufferedImage image, int x, int y,
|
||||
// int width, int height, String activityType) {
|
||||
// Color nodeColor = SKIP_COLOR;
|
||||
// Graphics2D graphics = image.createGraphics();
|
||||
//
|
||||
// try {
|
||||
// drawNodeBorder(x, y, width, height, graphics, nodeColor,
|
||||
// activityType);
|
||||
// } finally {
|
||||
// graphics.dispose();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 绘制节点边框
|
||||
// *
|
||||
// * @param x
|
||||
// * 左上角节点坐在X位置
|
||||
// * @param y
|
||||
// * 左上角节点坐在Y位置
|
||||
// * @param width
|
||||
// * 宽
|
||||
// * @param height
|
||||
// * 高
|
||||
// * @param graphics
|
||||
// * 绘图对象
|
||||
// * @param color
|
||||
// * 节点边框颜色
|
||||
// * @param activityType
|
||||
// * 节点类型
|
||||
// */
|
||||
// protected static void drawNodeBorder(int x, int y, int width, int height,
|
||||
// Graphics2D graphics, Color color, String activityType) {
|
||||
// graphics.setPaint(color);
|
||||
// graphics.setStroke(THICK_BORDER_STROKE);
|
||||
//
|
||||
// if (taskType.contains(activityType)) {
|
||||
// drawTask(x, y, width, height, graphics);
|
||||
// } else if (gatewayType.contains(activityType)) {
|
||||
// drawGateway(x, y, width, height, graphics);
|
||||
// } else if (eventType.contains(activityType)) {
|
||||
// drawEvent(x, y, width, height, graphics);
|
||||
// } else if (subProcessType.contains(activityType)) {
|
||||
// drawSubProcess(x, y, width, height, graphics);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 绘制任务
|
||||
// */
|
||||
// protected static void drawTask(int x, int y, int width, int height,
|
||||
// Graphics2D graphics) {
|
||||
// RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width,
|
||||
// height, OFFSET_TASK, OFFSET_TASK);
|
||||
// graphics.draw(rect);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 绘制网关
|
||||
// */
|
||||
// protected static void drawGateway(int x, int y, int width, int height,
|
||||
// Graphics2D graphics) {
|
||||
// Polygon rhombus = new Polygon();
|
||||
// rhombus.addPoint(x, y + (height / 2));
|
||||
// rhombus.addPoint(x + (width / 2), y + height);
|
||||
// rhombus.addPoint(x + width, y + (height / 2));
|
||||
// rhombus.addPoint(x + (width / 2), y);
|
||||
// graphics.draw(rhombus);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 绘制任务
|
||||
// */
|
||||
// protected static void drawEvent(int x, int y, int width, int height,
|
||||
// Graphics2D graphics) {
|
||||
// Double circle = new Double(x, y, width, height);
|
||||
// graphics.draw(circle);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 绘制子流程
|
||||
// */
|
||||
// protected static void drawSubProcess(int x, int y, int width, int height,
|
||||
// Graphics2D graphics) {
|
||||
// RoundRectangle2D rect = new RoundRectangle2D.Double(x + 1, y + 1,
|
||||
// width - 2, height - 2, OFFSET_SUBPROCESS, OFFSET_SUBPROCESS);
|
||||
// graphics.draw(rect);
|
||||
// }
|
||||
//
|
||||
// protected Point getMinXAndMinY(BpmnModel bpmnModel) {
|
||||
// // We need to calculate maximum values to know how big the image will be in its entirety
|
||||
// double theMinX = java.lang.Double.MAX_VALUE;
|
||||
// double theMaxX = 0;
|
||||
// double theMinY = java.lang.Double.MAX_VALUE;
|
||||
// double theMaxY = 0;
|
||||
//
|
||||
// for (Pool pool : bpmnModel.getPools()) {
|
||||
// GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
|
||||
// theMinX = graphicInfo.getX();
|
||||
// theMaxX = graphicInfo.getX() + graphicInfo.getWidth();
|
||||
// theMinY = graphicInfo.getY();
|
||||
// theMaxY = graphicInfo.getY() + graphicInfo.getHeight();
|
||||
// }
|
||||
//
|
||||
// List<FlowNode> flowNodes = gatherAllFlowNodes(bpmnModel);
|
||||
//
|
||||
// for (FlowNode flowNode : flowNodes) {
|
||||
// GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode
|
||||
// .getId());
|
||||
//
|
||||
// // width
|
||||
// if ((flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth()) > theMaxX) {
|
||||
// theMaxX = flowNodeGraphicInfo.getX()
|
||||
// + flowNodeGraphicInfo.getWidth();
|
||||
// }
|
||||
//
|
||||
// if (flowNodeGraphicInfo.getX() < theMinX) {
|
||||
// theMinX = flowNodeGraphicInfo.getX();
|
||||
// }
|
||||
//
|
||||
// // height
|
||||
// if ((flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight()) > theMaxY) {
|
||||
// theMaxY = flowNodeGraphicInfo.getY()
|
||||
// + flowNodeGraphicInfo.getHeight();
|
||||
// }
|
||||
//
|
||||
// if (flowNodeGraphicInfo.getY() < theMinY) {
|
||||
// theMinY = flowNodeGraphicInfo.getY();
|
||||
// }
|
||||
//
|
||||
// for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
|
||||
// List<GraphicInfo> graphicInfoList = bpmnModel
|
||||
// .getFlowLocationGraphicInfo(sequenceFlow.getId());
|
||||
//
|
||||
// for (GraphicInfo graphicInfo : graphicInfoList) {
|
||||
// // width
|
||||
// if (graphicInfo.getX() > theMaxX) {
|
||||
// theMaxX = graphicInfo.getX();
|
||||
// }
|
||||
//
|
||||
// if (graphicInfo.getX() < theMinX) {
|
||||
// theMinX = graphicInfo.getX();
|
||||
// }
|
||||
//
|
||||
// // height
|
||||
// if (graphicInfo.getY() > theMaxY) {
|
||||
// theMaxY = graphicInfo.getY();
|
||||
// }
|
||||
//
|
||||
// if (graphicInfo.getY() < theMinY) {
|
||||
// theMinY = graphicInfo.getY();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// List<Artifact> artifacts = gatherAllArtifacts(bpmnModel);
|
||||
//
|
||||
// for (Artifact artifact : artifacts) {
|
||||
// GraphicInfo artifactGraphicInfo = bpmnModel.getGraphicInfo(artifact
|
||||
// .getId());
|
||||
//
|
||||
// if (artifactGraphicInfo != null) {
|
||||
// // width
|
||||
// if ((artifactGraphicInfo.getX() + artifactGraphicInfo
|
||||
// .getWidth()) > theMaxX) {
|
||||
// theMaxX = artifactGraphicInfo.getX()
|
||||
// + artifactGraphicInfo.getWidth();
|
||||
// }
|
||||
//
|
||||
// if (artifactGraphicInfo.getX() < theMinX) {
|
||||
// theMinX = artifactGraphicInfo.getX();
|
||||
// }
|
||||
//
|
||||
// // height
|
||||
// if ((artifactGraphicInfo.getY() + artifactGraphicInfo
|
||||
// .getHeight()) > theMaxY) {
|
||||
// theMaxY = artifactGraphicInfo.getY()
|
||||
// + artifactGraphicInfo.getHeight();
|
||||
// }
|
||||
//
|
||||
// if (artifactGraphicInfo.getY() < theMinY) {
|
||||
// theMinY = artifactGraphicInfo.getY();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// List<GraphicInfo> graphicInfoList = bpmnModel
|
||||
// .getFlowLocationGraphicInfo(artifact.getId());
|
||||
//
|
||||
// if (graphicInfoList != null) {
|
||||
// for (GraphicInfo graphicInfo : graphicInfoList) {
|
||||
// // width
|
||||
// if (graphicInfo.getX() > theMaxX) {
|
||||
// theMaxX = graphicInfo.getX();
|
||||
// }
|
||||
//
|
||||
// if (graphicInfo.getX() < theMinX) {
|
||||
// theMinX = graphicInfo.getX();
|
||||
// }
|
||||
//
|
||||
// // height
|
||||
// if (graphicInfo.getY() > theMaxY) {
|
||||
// theMaxY = graphicInfo.getY();
|
||||
// }
|
||||
//
|
||||
// if (graphicInfo.getY() < theMinY) {
|
||||
// theMinY = graphicInfo.getY();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// int nrOfLanes = 0;
|
||||
//
|
||||
// for (Process process : bpmnModel.getProcesses()) {
|
||||
// for (Lane l : process.getLanes()) {
|
||||
// nrOfLanes++;
|
||||
//
|
||||
// GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId());
|
||||
//
|
||||
// // // width
|
||||
// if ((graphicInfo.getX() + graphicInfo.getWidth()) > theMaxX) {
|
||||
// theMaxX = graphicInfo.getX() + graphicInfo.getWidth();
|
||||
// }
|
||||
//
|
||||
// if (graphicInfo.getX() < theMinX) {
|
||||
// theMinX = graphicInfo.getX();
|
||||
// }
|
||||
//
|
||||
// // height
|
||||
// if ((graphicInfo.getY() + graphicInfo.getHeight()) > theMaxY) {
|
||||
// theMaxY = graphicInfo.getY() + graphicInfo.getHeight();
|
||||
// }
|
||||
//
|
||||
// if (graphicInfo.getY() < theMinY) {
|
||||
// theMinY = graphicInfo.getY();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Special case, see http://jira.codehaus.org/browse/ACT-1431
|
||||
// if ((flowNodes.size() == 0) && (bpmnModel.getPools().size() == 0)
|
||||
// && (nrOfLanes == 0)) {
|
||||
// // Nothing to show
|
||||
// theMinX = 0;
|
||||
// theMinY = 0;
|
||||
// }
|
||||
//
|
||||
// return new Point((int) theMinX, (int) theMinY);
|
||||
// }
|
||||
//
|
||||
// protected static List<Artifact> gatherAllArtifacts(BpmnModel bpmnModel) {
|
||||
// List<Artifact> artifacts = new ArrayList<Artifact>();
|
||||
//
|
||||
// for (Process process : bpmnModel.getProcesses()) {
|
||||
// artifacts.addAll(process.getArtifacts());
|
||||
// }
|
||||
//
|
||||
// return artifacts;
|
||||
// }
|
||||
//
|
||||
// protected static List<FlowNode> gatherAllFlowNodes(BpmnModel bpmnModel) {
|
||||
// List<FlowNode> flowNodes = new ArrayList<FlowNode>();
|
||||
//
|
||||
// for (Process process : bpmnModel.getProcesses()) {
|
||||
// flowNodes.addAll(gatherAllFlowNodes(process));
|
||||
// }
|
||||
//
|
||||
// return flowNodes;
|
||||
// }
|
||||
//
|
||||
// protected static List<FlowNode> gatherAllFlowNodes(
|
||||
// FlowElementsContainer flowElementsContainer) {
|
||||
// List<FlowNode> flowNodes = new ArrayList<FlowNode>();
|
||||
//
|
||||
// for (FlowElement flowElement : flowElementsContainer.getFlowElements()) {
|
||||
// if (flowElement instanceof FlowNode) {
|
||||
// flowNodes.add((FlowNode) flowElement);
|
||||
// }
|
||||
//
|
||||
// if (flowElement instanceof FlowElementsContainer) {
|
||||
// flowNodes
|
||||
// .addAll(gatherAllFlowNodes((FlowElementsContainer) flowElement));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return flowNodes;
|
||||
// }
|
||||
//
|
||||
// public void drawHistoryFlow(BufferedImage image, String processInstanceId) {
|
||||
// HistoricProcessInstance historicProcessInstance = Context
|
||||
// .getCommandContext().getHistoricProcessInstanceEntityManager()
|
||||
// .findHistoricProcessInstance(processInstanceId);
|
||||
// String processDefinitionId = historicProcessInstance
|
||||
// .getProcessDefinitionId();
|
||||
// Graph graph = new FlowableHistoryGraphBuilder(processInstanceId)
|
||||
// .build();
|
||||
//
|
||||
// for (Edge edge : graph.getEdges()) {
|
||||
// drawSequenceFlow(image, processDefinitionId, edge.getName());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 画线条
|
||||
// * @param image
|
||||
// * @param processDefinitionId
|
||||
// * @param sequenceFlowId
|
||||
// */
|
||||
// private void drawSequenceFlow(BufferedImage image,String processDefinitionId, String sequenceFlowId) {
|
||||
// GetBpmnModelCmd getBpmnModelCmd = new GetBpmnModelCmd(processDefinitionId);
|
||||
// BpmnModel bpmnModel = getBpmnModelCmd.execute(Context.getCommandContext());
|
||||
//
|
||||
// Graphics2D graphics = image.createGraphics();
|
||||
// graphics.setPaint(HISTORY_COLOR);
|
||||
// graphics.setStroke(new BasicStroke(2f));
|
||||
//
|
||||
// try {
|
||||
// //TODO 【JTC-1177】流程画线有斜度,流转的进度线就对不上。问题出在这里,返回的Y轴是一样高度
|
||||
// List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlowId);
|
||||
//
|
||||
// int[] xPoints = new int[graphicInfoList.size()];
|
||||
// int[] yPoints = new int[graphicInfoList.size()];
|
||||
//
|
||||
// for (int i = 1; i < graphicInfoList.size(); i++) {
|
||||
// GraphicInfo graphicInfo = graphicInfoList.get(i);
|
||||
//
|
||||
// //System.out.println("GraphicInfo x: " + graphicInfo.getX());
|
||||
// //System.out.println("GraphicInfo y: " + graphicInfo.getY());
|
||||
//
|
||||
// GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1);
|
||||
//
|
||||
// if (i == 1) {
|
||||
// xPoints[0] = (int) previousGraphicInfo.getX() - minX;
|
||||
// yPoints[0] = (int) previousGraphicInfo.getY() - minY;
|
||||
// }
|
||||
//
|
||||
// xPoints[i] = (int) graphicInfo.getX() - minX;
|
||||
// yPoints[i] = (int) graphicInfo.getY() - minY;
|
||||
// }
|
||||
//
|
||||
// //5.22流程图路径线圆角问题start
|
||||
// //int radius = 15;
|
||||
// int radius = 0;
|
||||
// //5.22流程图路径线圆角问题end
|
||||
//
|
||||
// //画线
|
||||
// Path2D path = new Path2D.Double();
|
||||
//
|
||||
// for (int i = 0; i < xPoints.length; i++) {
|
||||
// Integer anchorX = xPoints[i];
|
||||
// Integer anchorY = yPoints[i];
|
||||
//
|
||||
// double targetX = anchorX;
|
||||
// double targetY = anchorY;
|
||||
//
|
||||
// double ax = 0;
|
||||
// double ay = 0;
|
||||
// double bx = 0;
|
||||
// double by = 0;
|
||||
// double zx = 0;
|
||||
// double zy = 0;
|
||||
//
|
||||
// if ((i > 0) && (i < (xPoints.length - 1))) {
|
||||
// Integer cx = anchorX;
|
||||
// Integer cy = anchorY;
|
||||
//
|
||||
// // pivot point of prev line
|
||||
// double lineLengthY = yPoints[i] - yPoints[i - 1];
|
||||
//
|
||||
// // pivot point of prev line
|
||||
// double lineLengthX = xPoints[i] - xPoints[i - 1];
|
||||
// double lineLength = Math.sqrt(Math.pow(lineLengthY, 2)
|
||||
// + Math.pow(lineLengthX, 2));
|
||||
// double dx = (lineLengthX * radius) / lineLength;
|
||||
// double dy = (lineLengthY * radius) / lineLength;
|
||||
// targetX = targetX - dx;
|
||||
// targetY = targetY - dy;
|
||||
//
|
||||
// // isDefaultConditionAvailable = isDefault && i == 1 && lineLength > 10;
|
||||
// if ((lineLength < (2 * radius)) && (i > 1)) {
|
||||
// targetX = xPoints[i] - (lineLengthX / 2);
|
||||
// targetY = yPoints[i] - (lineLengthY / 2);
|
||||
// }
|
||||
//
|
||||
// // pivot point of next line
|
||||
// lineLengthY = yPoints[i + 1] - yPoints[i];
|
||||
// lineLengthX = xPoints[i + 1] - xPoints[i];
|
||||
// lineLength = Math.sqrt(Math.pow(lineLengthY, 2)
|
||||
// + Math.pow(lineLengthX, 2));
|
||||
//
|
||||
// if (lineLength < radius) {
|
||||
// lineLength = radius;
|
||||
// }
|
||||
//
|
||||
// dx = (lineLengthX * radius) / lineLength;
|
||||
// dy = (lineLengthY * radius) / lineLength;
|
||||
//
|
||||
// double nextSrcX = xPoints[i] + dx;
|
||||
// double nextSrcY = yPoints[i] + dy;
|
||||
//
|
||||
// if ((lineLength < (2 * radius))
|
||||
// && (i < (xPoints.length - 2))) {
|
||||
// nextSrcX = xPoints[i] + (lineLengthX / 2);
|
||||
// nextSrcY = yPoints[i] + (lineLengthY / 2);
|
||||
// }
|
||||
//
|
||||
// double dx0 = (cx - targetX) / 3;
|
||||
// double dy0 = (cy - targetY) / 3;
|
||||
// ax = cx - dx0;
|
||||
// ay = cy - dy0;
|
||||
//
|
||||
// double dx1 = (cx - nextSrcX) / 3;
|
||||
// double dy1 = (cy - nextSrcY) / 3;
|
||||
// bx = cx - dx1;
|
||||
// by = cy - dy1;
|
||||
//
|
||||
// zx = nextSrcX;
|
||||
// zy = nextSrcY;
|
||||
// }
|
||||
//
|
||||
// if (i == 0) {
|
||||
// path.moveTo(targetX, targetY);
|
||||
// } else {
|
||||
// path.lineTo(targetX, targetY);
|
||||
// }
|
||||
//
|
||||
// if ((i > 0) && (i < (xPoints.length - 1))) {
|
||||
// // add curve 添加曲线
|
||||
// path.curveTo(ax, ay, bx, by, zx, zy);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// graphics.draw(path);
|
||||
//
|
||||
// //画箭头 draw arrow
|
||||
// Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2],
|
||||
// yPoints[xPoints.length - 2], xPoints[xPoints.length - 1],
|
||||
// yPoints[xPoints.length - 1]);
|
||||
//
|
||||
// int ARROW_WIDTH = 5;
|
||||
// int doubleArrowWidth = 2 * ARROW_WIDTH;
|
||||
// Polygon arrowHead = new Polygon();
|
||||
// arrowHead.addPoint(0, 0);
|
||||
// arrowHead.addPoint(-ARROW_WIDTH, -doubleArrowWidth);
|
||||
// arrowHead.addPoint(ARROW_WIDTH, -doubleArrowWidth);
|
||||
//
|
||||
// AffineTransform transformation = new AffineTransform();
|
||||
// transformation.setToIdentity();
|
||||
//
|
||||
// double angle = Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
|
||||
// transformation.translate(line.x2, line.y2);
|
||||
// transformation.rotate((angle - (Math.PI / 2d)));
|
||||
//
|
||||
// AffineTransform originalTransformation = graphics.getTransform();
|
||||
// graphics.setTransform(transformation);
|
||||
// graphics.fill(arrowHead);
|
||||
// graphics.setTransform(originalTransformation);
|
||||
// } finally {
|
||||
// graphics.dispose();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
package org.jeecg.modules.bpm.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.util.CommonUtils;
|
||||
import org.jeecg.common.util.ReflectHelper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.DialectFactory;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.DialectModel;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect;
|
||||
|
||||
@Slf4j
|
||||
public class BpmSqlUtil {
|
||||
// /**
|
||||
// * 分页SQL
|
||||
// */
|
||||
// public static final String MYSQL_SQL = "select * from ( {0}) sel_tab00 limit {1},{2}"; // mysql
|
||||
// public static final String POSTGRE_SQL = "select * from ( {0}) sel_tab00 limit {2} offset {1}";// postgresql
|
||||
// public static final String ORACLE_SQL = "select * from (select row_.*,rownum rownum_ from ({0}) row_ where rownum <= {1}) where rownum_>{2}"; // oracle
|
||||
// public static final String SQLSERVER_SQL = "select * from ( select row_number() over(order by tempColumn) tempRowNumber, * from (select top {1} tempColumn = 0, {0}) t ) tt where tempRowNumber > {2}"; // sqlserver
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 按照数据库类型,封装SQL
|
||||
// *
|
||||
// * @param dbType
|
||||
// * 数据库类型
|
||||
// * @param sql
|
||||
// * @param pageNo
|
||||
// * @param pageSize
|
||||
// * @return
|
||||
// */
|
||||
// public static String createPageSql(String dbType, String sql, int pageNo, int pageSize) {
|
||||
// int beginNum = (pageNo - 1) * pageSize;
|
||||
// String[] sqlParam = new String[3];
|
||||
// sqlParam[0] = sql;
|
||||
// sqlParam[1] = beginNum + "";
|
||||
// sqlParam[2] = pageSize + "";
|
||||
// if (dbType == null || "".equals(dbType)) {
|
||||
// throw new RuntimeException("SqlUtil:(数据库类型:dbType)没有设置,请检查配置文件");
|
||||
// }
|
||||
//
|
||||
// if (DataBaseConstant.DB_TYPE_MYSQL.equalsIgnoreCase(dbType) || DataBaseConstant.DB_TYPE_MARIADB.equalsIgnoreCase(dbType)) {
|
||||
// sql = MessageFormat.format(MYSQL_SQL, sqlParam);
|
||||
// } else if (DataBaseConstant.DB_TYPE_POSTGRESQL.equalsIgnoreCase(dbType)) {
|
||||
// sql = MessageFormat.format(POSTGRE_SQL, sqlParam);
|
||||
// } else {
|
||||
// int beginIndex = (pageNo - 1) * pageSize;
|
||||
// int endIndex = beginIndex + pageSize;
|
||||
// sqlParam[2] = Integer.toString(beginIndex);
|
||||
// sqlParam[1] = Integer.toString(endIndex);
|
||||
// if (DataBaseConstant.DB_TYPE_ORACLE.equalsIgnoreCase(dbType)) {
|
||||
// sql = MessageFormat.format(ORACLE_SQL, sqlParam);
|
||||
// } else if (DataBaseConstant.DB_TYPE_SQLSERVER.equalsIgnoreCase(dbType)) {
|
||||
// sqlParam[0] = sql.substring(getAfterSelectInsertPoint(sql));
|
||||
// sql = MessageFormat.format(SQLSERVER_SQL, sqlParam);
|
||||
// }
|
||||
// }
|
||||
// return sql;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @param sql
|
||||
// * @return
|
||||
// */
|
||||
// private static int getAfterSelectInsertPoint(String sql) {
|
||||
// int selectIndex = sql.toLowerCase().indexOf("select");
|
||||
// int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct");
|
||||
// return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* 按照数据库类型,封装SQL
|
||||
*
|
||||
* @param sql
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @return
|
||||
*/
|
||||
public static String createPageSql(String sql, int pageNo, int pageSize) {
|
||||
DbType dbType = CommonUtils.getDatabaseTypeEnum();
|
||||
log.debug(" 当前环境 DbType:"+dbType.getDb());
|
||||
IDialect dialect = DialectFactory.getDialect(dbType);
|
||||
Page page = new Page<>(pageNo, pageSize);
|
||||
DialectModel model = dialect.buildPaginationSql(sql, page.offset(), page.getSize());
|
||||
String pageSQL = model.getDialectSql();
|
||||
// 设置分页参数
|
||||
if (model.getDialectSql().contains("?")) {
|
||||
long firstParam = (long)ReflectHelper.getFieldVal("firstParam", model);
|
||||
long secondParam = (long)ReflectHelper.getFieldVal("secondParam", model);
|
||||
pageSQL = pageSQL.replaceFirst("\\?", firstParam + "");
|
||||
pageSQL = pageSQL.replace("?", secondParam + "");
|
||||
}
|
||||
|
||||
return pageSQL;
|
||||
}
|
||||
|
||||
}
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
package org.jeecg.modules.bpm.util;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
|
||||
public class BpmUtil {
|
||||
|
||||
public static String getNodeUrl(Map<String, Object> variables,String formUrl,String dataId) {
|
||||
if(oConvertUtils.isEmpty(formUrl)) {
|
||||
return null;
|
||||
}
|
||||
Set<String> varParams = getVarParams(formUrl);
|
||||
if(varParams!=null&&varParams.size()>0) {
|
||||
formUrl = getContent(variables, formUrl);
|
||||
}else {
|
||||
if(formUrl.indexOf("/online/df/")>=0||formUrl.indexOf("/online/dfview/")>=0) {
|
||||
if(formUrl.endsWith("/")) {
|
||||
formUrl +=dataId;
|
||||
}else {
|
||||
formUrl +="/"+dataId;
|
||||
}
|
||||
}
|
||||
}
|
||||
return formUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标题表达式 ,翻译后的值文本
|
||||
*
|
||||
* @param variables
|
||||
* @param exp
|
||||
* @return
|
||||
*/
|
||||
public static String getContent(Map<String, Object> variables, String exp){
|
||||
try {
|
||||
if(oConvertUtils.isEmpty(exp)) {
|
||||
return null;
|
||||
}
|
||||
Set<String> varParams = getVarParams(exp);
|
||||
for(String key: varParams){
|
||||
//update-begin---author:scott ---date:2023-08-29 for:【简流】标题字段是关联记录时 流程标题显示id---
|
||||
//取值表临时变量 key
|
||||
String var = key;
|
||||
//【QQYUN-6347】判断标题字段类型是关联记录
|
||||
if(var.startsWith("link_record_")) {
|
||||
var = var + "_dicttext";
|
||||
}
|
||||
//update-end---author:scott ---date::2023-08-29 for:【简流】标题字段是关联记录时 流程标题显示id-
|
||||
|
||||
Object obj = variables.get(var);
|
||||
//update-begin---author:scott ---date:20231016 for:【QQYUN-6760 QQYUN-6812】标题字段是人员、部门、日期时,任务处理中显示的标题未翻译---
|
||||
//翻译值
|
||||
Object objDictText = variables.get((var + CommonConstant.DICT_TEXT_SUFFIX).toLowerCase());
|
||||
if (oConvertUtils.isNotEmpty(objDictText)) {
|
||||
exp = exp.replace("${"+key+"}", objDictText.toString());
|
||||
return exp;
|
||||
}
|
||||
//update-end---author:scott ---date::20231016 for:【QQYUN-6760 QQYUN-6812】标题字段是人员、部门、日期时,任务处理中显示的标题未翻译---
|
||||
|
||||
if(obj==null){
|
||||
obj = variables.get(var.toUpperCase());
|
||||
if(obj==null) {
|
||||
obj = "";
|
||||
}
|
||||
}else if(obj instanceof Date){
|
||||
obj = DateUtils.formatDate((Date)obj);
|
||||
}else if (obj instanceof JSONArray) {
|
||||
//【QQYUN-4094】标题显示问题,表单设计器中使用用户组件
|
||||
JSONArray array = (JSONArray) obj;
|
||||
if (array.size() > 1) {
|
||||
obj = StringUtils.join(array.toArray(), ",");
|
||||
} else {
|
||||
obj = array.size() == 1 ? array.get(0) : "";
|
||||
}
|
||||
//update-begin---author:scott ---date:2023-11-20 for:【QQYUN-7077】设计器表单,出差申请/请假申请/离职申请/晋级申请 名称为 java.lang.Object----
|
||||
} else if (obj instanceof Object[]) {
|
||||
Object[] vals = (Object[]) obj;
|
||||
if (vals.length == 1) {
|
||||
obj = vals[0];
|
||||
} else {
|
||||
obj = StringUtils.join(vals, ",");
|
||||
}
|
||||
}
|
||||
//update-end---author:scott ---date::2023-11-20 for:【QQYUN-7077】设计器表单,出差申请/请假申请/离职申请/晋级申请 名称为 java.lang.Object--
|
||||
|
||||
exp = exp.replace("${"+key+"}", obj.toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
public static Set<String> getVarParams(String exp) {
|
||||
if(oConvertUtils.isEmpty(exp)){
|
||||
return null;
|
||||
}
|
||||
Set<String> varParams = new HashSet<String>();
|
||||
String regex = "\\$\\{\\w+\\}";
|
||||
|
||||
Pattern p = Pattern.compile(regex);
|
||||
Matcher m = p.matcher(exp);
|
||||
while(m.find()){
|
||||
String var = m.group();
|
||||
varParams.add(var.substring(var.indexOf("{")+1,var.indexOf("}")));
|
||||
}
|
||||
return varParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间的处理
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
public static String dealTimeFromNum(long time) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
long interval = time / 1000;
|
||||
final long day = 24 * 60 * 60;
|
||||
final long hour = 60 * 60;
|
||||
final long minute = 60;
|
||||
int detailDay = 0;
|
||||
int detailHour = 0;
|
||||
int detailMinute = 0;
|
||||
int detailSecond = 0;
|
||||
if (interval >= day) {
|
||||
detailDay = (int) (interval / day);
|
||||
interval = interval - detailDay * day;
|
||||
}
|
||||
if (interval >= hour) {
|
||||
detailHour = (int) (interval / hour);
|
||||
interval = interval - hour * detailHour;
|
||||
}
|
||||
if (interval >= minute) {
|
||||
detailMinute = (int) (interval / minute);
|
||||
interval = interval - detailMinute * minute;
|
||||
}
|
||||
if (interval > 0) {
|
||||
detailSecond = (int) interval;
|
||||
}
|
||||
result.setLength(0);
|
||||
if (detailDay > 0) {
|
||||
result.append(detailDay);
|
||||
result.append("天");
|
||||
}
|
||||
if (detailHour > 0) {
|
||||
result.append(detailHour);
|
||||
result.append("小时");
|
||||
}
|
||||
if (detailMinute > 0) {
|
||||
result.append(detailMinute);
|
||||
result.append("分");
|
||||
}
|
||||
if (detailSecond > 0) {
|
||||
result.append(detailSecond);
|
||||
result.append("秒");
|
||||
}else if (detailSecond == 0) {
|
||||
result.append(detailSecond);
|
||||
result.append("秒");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param str 要处理的字符串
|
||||
* @param substring 要移除的子字符串
|
||||
* @return
|
||||
*/
|
||||
public static String removeSubstring(String str, String substring) {
|
||||
int index = str.indexOf(substring);
|
||||
|
||||
if (index != -1) { // 如果找到了指定的子字符串
|
||||
return str.substring(0, index); // 截取前面部分并返回
|
||||
} else {
|
||||
return str; // 如果没有找到指定的子字符串,则返回原字符串
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
//package org.jeecg.modules.bpm.util;
|
||||
//
|
||||
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
//
|
||||
//public class JoaUtil {
|
||||
//
|
||||
// /**
|
||||
// * 查询待审批的单据
|
||||
// * @param bizTaskType 业务类型1待我审批2我发起的申请
|
||||
// * @param queryWrapper 查询器
|
||||
// * @param userName 用户账号
|
||||
// * @param flowCode 流程唯一编码
|
||||
// */
|
||||
// @SuppressWarnings("rawtypes")
|
||||
// public static void filterRunningTask(String bizTaskType,QueryWrapper queryWrapper,String userName,String flowCode) {
|
||||
// StringBuilder sb = new StringBuilder(" (");
|
||||
// if("1".equals(bizTaskType)) {
|
||||
// sb.append(" ID ").append(" in ").append("(");
|
||||
// sb.append(" select fd.FORM_DATA_ID from EXT_ACT_FLOW_DATA fd ");
|
||||
// sb.append(" RIGHT JOIN (");
|
||||
// sb.append(" select * from (");
|
||||
// sb.append(" (select distinct RES.* from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
|
||||
// sb.append(" WHERE RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' ");
|
||||
// sb.append(" and ( I.USER_ID_ = {0} or I.GROUP_ID_ IN ( select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = {0} ) ) ");
|
||||
// sb.append(" and RES.SUSPENSION_STATE_ = 1 ");
|
||||
// sb.append(" ) union (select distinct RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ = {0} ");
|
||||
// sb.append(" )) v ");
|
||||
// sb.append(" ) art ");
|
||||
// sb.append(" on fd.PROCESS_INST_ID = art.PROC_INST_ID_ ");
|
||||
// sb.append(" where fd.RELATION_CODE = {1} ");
|
||||
// sb.append(" )");
|
||||
// sb.append(" )");
|
||||
// queryWrapper.apply(sb.toString(), userName,flowCode);
|
||||
// }else {
|
||||
// sb.append(" CREATE_BY = {0}");
|
||||
// sb.append(" )");
|
||||
// queryWrapper.apply(sb.toString(), userName);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 查询待审批的单据
|
||||
// * @param bizTaskType 业务类型1待我审批2我发起的申请
|
||||
// * @param queryWrapper 查询器
|
||||
// * @param userName 用户账号
|
||||
// * @param flowCode 流程唯一编码
|
||||
// * @param taskDefKey 任务key
|
||||
// */
|
||||
// @SuppressWarnings("rawtypes")
|
||||
// public static void filterRunningTask(String bizTaskType,QueryWrapper queryWrapper,String userName,String flowCode,String taskDefKey) {
|
||||
// StringBuilder sb = new StringBuilder(" (");
|
||||
// if("1".equals(bizTaskType)) {
|
||||
// sb.append(" ID ").append(" in ").append("(");
|
||||
// sb.append(" select fd.FORM_DATA_ID from EXT_ACT_FLOW_DATA fd ");
|
||||
// sb.append(" RIGHT JOIN (");
|
||||
// sb.append(" select * from (");
|
||||
// sb.append(" (select distinct RES.* from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
|
||||
// sb.append(" WHERE RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' ");
|
||||
// sb.append(" and ( I.USER_ID_ = {0} or I.GROUP_ID_ IN ( select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = {0} ) ) ");
|
||||
// sb.append(" and RES.SUSPENSION_STATE_ = 1 ");
|
||||
// sb.append(" ) union (select distinct RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ = {0} ");
|
||||
// sb.append(" )) v ");
|
||||
// sb.append(" ) art ");
|
||||
// sb.append(" on fd.PROCESS_INST_ID = art.PROC_INST_ID_ ");
|
||||
// sb.append(" where fd.RELATION_CODE = {1} ");
|
||||
// sb.append(" and art.TASK_DEF_KEY_ = {2} ");
|
||||
// sb.append(" )");
|
||||
// sb.append(" )");
|
||||
// queryWrapper.apply(sb.toString(), userName,flowCode,taskDefKey);
|
||||
// }else {
|
||||
// sb.append(" CREATE_BY = {0}");
|
||||
// sb.append(" )");
|
||||
// queryWrapper.apply(sb.toString(), userName);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 查询待审批的单据
|
||||
// * @param userName 用户账号
|
||||
// * @param flowCode 流程唯一编码
|
||||
// * @param taskDefKey 任务key
|
||||
// */
|
||||
// public static String getMyTaskSql(String userName,String flowCode) {
|
||||
// StringBuilder sb = new StringBuilder(" ");
|
||||
// sb.append(" select fd.FORM_DATA_ID from EXT_ACT_FLOW_DATA fd ");
|
||||
// sb.append(" RIGHT JOIN (");
|
||||
// sb.append(" select * from (");
|
||||
// sb.append(" (select distinct RES.* from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
|
||||
// sb.append(" WHERE RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' ");
|
||||
// sb.append(" and ( I.USER_ID_ = '"+userName+"' or I.GROUP_ID_ IN ( select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = '"+userName+"' ) ) ");
|
||||
// sb.append(" and RES.SUSPENSION_STATE_ = 1 ");
|
||||
// sb.append(" ) union (select distinct RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ = '"+userName+"' ");
|
||||
// sb.append(" )) v ");
|
||||
// sb.append(" ) art ");
|
||||
// sb.append(" on fd.PROCESS_INST_ID = art.PROC_INST_ID_ ");
|
||||
// sb.append(" where fd.RELATION_CODE = '"+flowCode+"' ");
|
||||
// return sb.toString();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 查询待审批的单据
|
||||
// * @param userName 用户账号 NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
// * @param flowCode 流程唯一编码
|
||||
// * @param taskDefKey 任务key
|
||||
// */
|
||||
// public static String getMyTaskSql(String userName,String flowCode,String taskDefKey) {
|
||||
// StringBuilder sb = new StringBuilder(" ");
|
||||
// sb.append(" select fd.FORM_DATA_ID from EXT_ACT_FLOW_DATA fd ");
|
||||
// sb.append(" RIGHT JOIN (");
|
||||
// sb.append(" select * from (");
|
||||
// sb.append(" (select distinct RES.* from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
|
||||
// sb.append(" WHERE RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' ");
|
||||
// sb.append(" and ( I.USER_ID_ = '"+userName+"' or I.GROUP_ID_ IN ( select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = '"+userName+"' ) ) ");
|
||||
// sb.append(" and RES.SUSPENSION_STATE_ = 1 ");
|
||||
// sb.append(" ) union (select distinct RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ = '"+userName+"' ");
|
||||
// sb.append(" )) v ");
|
||||
// sb.append(" ) art ");
|
||||
// sb.append(" on fd.PROCESS_INST_ID = art.PROC_INST_ID_ ");
|
||||
// sb.append(" where fd.RELATION_CODE = '"+flowCode+"' ");
|
||||
// sb.append(" and art.TASK_DEF_KEY_ = '"+taskDefKey+"' ");
|
||||
// return sb.toString();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 查询我的审批的单据
|
||||
// * @param userName 用户账号
|
||||
// * @param flowCode 流程唯一编码
|
||||
// * @param taskDefKey 任务key
|
||||
// */
|
||||
// public static String getMyRunningTaskSql(String userName,String flowCode) {
|
||||
// StringBuilder sb = new StringBuilder(" ");
|
||||
// sb.append(" select fd.FORM_DATA_ID from EXT_ACT_FLOW_DATA fd ");
|
||||
// sb.append(" RIGHT JOIN (");
|
||||
// sb.append(" select * from (");
|
||||
// sb.append(" (select distinct RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ = '"+userName+"' ");
|
||||
// sb.append(" )) v ");
|
||||
// sb.append(" ) art ");
|
||||
// sb.append(" on fd.PROCESS_INST_ID = art.PROC_INST_ID_ ");
|
||||
// sb.append(" where fd.RELATION_CODE = '"+flowCode+"' ");
|
||||
// return sb.toString();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 查询待我签收的审批的单据
|
||||
// * @param userName 用户账号
|
||||
// * @param flowCode 流程唯一编码
|
||||
// * @param taskDefKey 任务key
|
||||
// */
|
||||
// public static String getMyClaimTaskSql(String userName,String flowCode) {
|
||||
// StringBuilder sb = new StringBuilder(" ");
|
||||
// sb.append(" select fd.FORM_DATA_ID from EXT_ACT_FLOW_DATA fd ");
|
||||
// sb.append(" RIGHT JOIN (");
|
||||
// sb.append(" select * from (");
|
||||
// sb.append(" (select distinct RES.* from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
|
||||
// sb.append(" WHERE RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' ");
|
||||
// sb.append(" and ( I.USER_ID_ = '"+userName+"' or I.GROUP_ID_ IN ( select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = '"+userName+"' ) ) ");
|
||||
// sb.append(" and RES.SUSPENSION_STATE_ = 1 ");
|
||||
// sb.append(" )");
|
||||
// sb.append(" ) v ");
|
||||
// sb.append(" ) art ");
|
||||
// sb.append(" on fd.PROCESS_INST_ID = art.PROC_INST_ID_ ");
|
||||
// sb.append(" where fd.RELATION_CODE = '"+flowCode+"' ");
|
||||
// return sb.toString();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package org.jeecg.modules.bpm.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.dom4j.Attribute;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
public class XmlActivitiUtil {
|
||||
|
||||
/**
|
||||
* 通过解析xml文件,判断该节点是否是会签节点
|
||||
*
|
||||
* @param resourceAsStream
|
||||
* @param taskkey
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean parseXml(String doc, String taskkey) {
|
||||
Element root = null;
|
||||
try {
|
||||
Document document = null;
|
||||
try {
|
||||
SAXReader reader = new SAXReader();
|
||||
//解决报错:Dom4j中文异常处理:Invalid byte 2 of 2-byte UTF-8 sequence
|
||||
reader.setEncoding("GBK");
|
||||
InputStream inputStream = new ByteArrayInputStream(doc.toString().getBytes());
|
||||
document = reader.read(inputStream);
|
||||
} catch (Exception e) {
|
||||
SAXReader reader = new SAXReader();
|
||||
InputStream inputStream = new ByteArrayInputStream(doc.toString().getBytes());
|
||||
document = reader.read(inputStream);
|
||||
}
|
||||
|
||||
root = document.getRootElement();
|
||||
for (Iterator iter = root.elementIterator(); iter.hasNext(); ) {
|
||||
Element element = (Element) iter.next();
|
||||
for (Iterator iterInner = element.elementIterator(); iterInner.hasNext(); ) {
|
||||
Element elementInner = (Element) iterInner.next();
|
||||
if ("userTask".equals(elementInner.getName())) {
|
||||
//获取节点的id属性的值
|
||||
Attribute leaderAttr = elementInner.attribute("id");
|
||||
if (leaderAttr != null) {
|
||||
if (leaderAttr.getValue().equals(taskkey)) {
|
||||
Element e_adds = elementInner.element("multiInstanceLoopCharacteristics");
|
||||
if (e_adds != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---update-begin-----autor:zhoujf------date:20190916-------for:子流程多实例判断--------
|
||||
if ("callActivity".equals(elementInner.getName())) {
|
||||
//获取节点的id属性的值
|
||||
Attribute leaderAttr = elementInner.attribute("id");
|
||||
if (leaderAttr != null) {
|
||||
if (leaderAttr.getValue().equals(taskkey)) {
|
||||
Element e_adds = elementInner.element("multiInstanceLoopCharacteristics");
|
||||
if (e_adds != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ("subProcess".equals(elementInner.getName())) {
|
||||
//获取节点的id属性的值
|
||||
Attribute leaderAttr = elementInner.attribute("id");
|
||||
if (leaderAttr != null) {
|
||||
if (leaderAttr.getValue().equals(taskkey)) {
|
||||
Element e_adds = elementInner.element("multiInstanceLoopCharacteristics");
|
||||
if (e_adds != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---update-end-----autor:zhoujf------date:20190916-------for:子流程多实例判断--------
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过解析xml文件,判断该节点是否是并行网关
|
||||
*
|
||||
* @param doc 流程设计 XML
|
||||
* @param taskkey 任务id
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean parseParallelGatewayFromXml(String doc, String taskkey) {
|
||||
Element root = null;
|
||||
try {
|
||||
Document document = null;
|
||||
try {
|
||||
SAXReader reader = new SAXReader();
|
||||
//解决报错:Dom4j中文异常处理:Invalid byte 2 of 2-byte UTF-8 sequence NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
reader.setEncoding("GBK");
|
||||
InputStream inputStream = new ByteArrayInputStream(doc.toString().getBytes());
|
||||
document = reader.read(inputStream);
|
||||
} catch (Exception e) {
|
||||
SAXReader reader = new SAXReader();
|
||||
InputStream inputStream = new ByteArrayInputStream(doc.toString().getBytes());
|
||||
document = reader.read(inputStream);
|
||||
}
|
||||
|
||||
root = document.getRootElement();
|
||||
for (Iterator iter = root.elementIterator(); iter.hasNext(); ) {
|
||||
Element element = (Element) iter.next();
|
||||
for (Iterator iterInner = element.elementIterator(); iterInner.hasNext(); ) {
|
||||
Element elementInner = (Element) iterInner.next();
|
||||
if ("parallelGateway".equals(elementInner.getName())) {
|
||||
//update-begin---author:scott ---date:20220118 for:[JTC-20、JTC-1229]【流程】多分支和同步网关同时配置时,选择其中一个分支,所有分支均执行-----
|
||||
//获取节点的id属性的值
|
||||
Attribute leaderAttr = elementInner.attribute("id");
|
||||
if (leaderAttr != null) {
|
||||
if (leaderAttr.getValue().equals(taskkey)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//update-end---author:scott ---date:20220118 for:[JTC-20、JTC-1229]【流程】多分支和同步网关同时配置时,选择其中一个分支,所有分支均执行-----
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
//package org.jeecg.modules.designer.config;
|
||||
//
|
||||
//import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//
|
||||
///**
|
||||
// * 流程设计器JSP配置
|
||||
// * @author scott
|
||||
// *
|
||||
// */
|
||||
//@Configuration("moduleDesigerConfig")
|
||||
//public class ModuleDesigerConfig {
|
||||
//
|
||||
// @Bean
|
||||
// public ServletRegistrationBean eventProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.eventProperties_jsp(), "/designer/eventProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean addCandidateGroup() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.addCandidateGroup_jsp(), "/designer/addCandidateGroup.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean addCandidateUser() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.addCandidateUser_jsp(), "/designer/addCandidateUser.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean boundaryEventProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.boundaryEventProperties_jsp(), "/designer/boundaryEventProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean businessRuleTaskProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.businessRuleTaskProperties_jsp(), "/designer/businessRuleTaskProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean candidateGroupsConfig() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.candidateGroupsConfig_jsp(), "/designer/candidateGroupsConfig.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean candidateUsersConfig() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.candidateUsersConfig_jsp(), "/designer/candidateUsersConfig.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean errorBoundaryEventProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.errorBoundaryEventProperties_jsp(), "/designer/errorBoundaryEventProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean flowListenerConfig() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.flowListenerConfig_jsp(), "/designer/flowListenerConfig.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean flowProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.flowProperties_jsp(), "/designer/flowProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean gatewayProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.gatewayProperties_jsp(), "/designer/gatewayProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean index() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.index_jsp(), "/designer/index.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean listenerList() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.listenerList_jsp(), "/designer/listenerList.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean mailTaskProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.mailTaskProperties_jsp(), "/designer/mailTaskProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean processListenerConfig() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.processListenerConfig_jsp(), "/designer/processListenerConfig.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean processpro() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.processpro_jsp(), "/designer/processpro.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean processProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.processProperties_jsp(), "/designer/processProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean receiveTaskProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.receiveTaskProperties_jsp(), "/designer/receiveTaskProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean scriptTaskProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.scriptTaskProperties_jsp(), "/designer/scriptTaskProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean selectExpressionList() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.selectExpressionList_jsp(), "/designer/selectExpressionList.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean selectProcessListenerList() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.selectProcessListenerList_jsp(), "/designer/selectProcessListenerList.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean serviceTaskProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.serviceTaskProperties_jsp(), "/designer/serviceTaskProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean serviceTaskssdkes() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.taskMyProperties_jsp(), "/designer/taskMyProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean subProcessProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.subProcessProperties_jsp(), "/designer/subProcessProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean taskFormConfig() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.taskFormConfig_jsp(), "/designer/taskFormConfig.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean taskListenerConfig() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.taskListenerConfig_jsp(), "/designer/taskListenerConfig.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean taskProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.taskProperties_jsp(), "/designer/taskProperties.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean taskVariableConfig() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.taskVariableConfig_jsp(), "/designer/taskVariableConfig.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean subParameterList_jsp() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.subParameterList_jsp(), "/designer/subParameterList.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean searchSelectUserList_jsp() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.searchSelectUserList_jsp(), "/designer/searchSelectUserList.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean mytags() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.context.mytags_jsp(), "/context/mytags.jsp");
|
||||
// }
|
||||
// @Bean
|
||||
// public ServletRegistrationBean flowMyProperties() {
|
||||
// return new ServletRegistrationBean(new org.apache.jsp.designer.flowMyProperties_jsp(), "/designer/flowMyProperties.jsp");
|
||||
// }
|
||||
//
|
||||
//}
|
||||
+466
@@ -0,0 +1,466 @@
|
||||
package org.jeecg.modules.designer.controller;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstanceQuery;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StreamUtils;
|
||||
import org.apache.commons.lang.StringUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.config.TenantContext;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.TokenUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.bpm.service.impl.ActProcessService;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.extbpm.process.entity.*;
|
||||
import org.jeecg.modules.extbpm.process.mapper.ExtActProcessMapper;
|
||||
import org.jeecg.modules.extbpm.process.pojo.ListenerInfo;
|
||||
import org.jeecg.modules.extbpm.process.pojo.RoleInfo;
|
||||
import org.jeecg.modules.extbpm.process.pojo.UserInfo;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActExpressionService;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActListenerService;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessNodeService;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.jeecgframework.designer.util.DesUtils;
|
||||
import org.jeecgframework.designer.vo.AjaxJson;
|
||||
import org.jeecgframework.designer.vo.ProcessTypeVo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
|
||||
/**
|
||||
* @ClassName: MockAPIController
|
||||
* @Description: 流程设计器(设计器首页所需数据API接口、接受设计器请求数据)
|
||||
* NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
* @author scott
|
||||
* @date 2010-03-12
|
||||
*
|
||||
*/
|
||||
@RestController("designerApiController")
|
||||
@RequestMapping("/act/designer/api")
|
||||
@Slf4j
|
||||
//@RequestMapping("/designer/mock")
|
||||
public class DesignerApiController {
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private IExtActProcessService extActProcessService;
|
||||
@Autowired
|
||||
private IExtActProcessNodeService extActProcessNodeService;
|
||||
@Autowired
|
||||
private IExtActListenerService extActListenerService;
|
||||
@Autowired
|
||||
private IExtActExpressionService extActExpressionService;
|
||||
@Autowired
|
||||
private ExtActProcessMapper extActProcessMapper;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
@Autowired
|
||||
@Lazy
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
/**
|
||||
* 流程编辑
|
||||
*
|
||||
* @param processId 流程ID
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/getProcessXml")
|
||||
@ResponseBody
|
||||
public void getProcessXml(HttpServletRequest request, HttpServletResponse response) {
|
||||
response.setContentType("text/xml;charset=UTF-8");
|
||||
String processId = oConvertUtils.getString(request.getParameter("processId"));
|
||||
//String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
//log.info(" getProcessXml 登录令牌token: "+token);
|
||||
//校验 token 登录有效性
|
||||
TokenUtils.verifyToken(request, sysBaseAPI, redisUtil);
|
||||
|
||||
ExtActProcess process = extActProcessService.getById(processId);
|
||||
String retstr = null;
|
||||
try {
|
||||
retstr = StreamUtils.InputStreamTOString(StreamUtils.byteTOInputStream(process.getProcessXml()));
|
||||
response.getWriter().write(retstr);
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【新版流程预览】
|
||||
* 通过流程实例ID获取流程设计xml(用于流程预览)
|
||||
*
|
||||
* @param processInstanceId 流程ID
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/getProcessXmlByInstanceId")
|
||||
@ResponseBody
|
||||
public void getProcessXmlByInstanceId(HttpServletRequest request, HttpServletResponse response) {
|
||||
response.setContentType("text/xml;charset=UTF-8");
|
||||
String processInstanceId = oConvertUtils.getString(request.getParameter("processInstanceId"));
|
||||
//String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
//log.info(" getProcessXml 登录令牌token: "+token);
|
||||
//校验 token 登录有效性
|
||||
TokenUtils.verifyToken(request, sysBaseAPI, redisUtil);
|
||||
|
||||
|
||||
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
//ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
|
||||
|
||||
//获取BpmnModel对象
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
|
||||
//创建转换对象
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
//把bpmnModel对象转换成字符
|
||||
byte[] bytes = converter.convertToXML(bpmnModel);
|
||||
String xmlContenxt = new String(bytes, StandardCharsets.UTF_8);
|
||||
|
||||
// LambdaQueryWrapper<ExtActProcess> queryWrapper = new LambdaQueryWrapper<ExtActProcess>();
|
||||
// queryWrapper.eq(ExtActProcess::getProcessKey, processDefinition.getKey());
|
||||
// ExtActProcess process = extActProcessService.getOne(queryWrapper);
|
||||
// String retstr = null;
|
||||
try {
|
||||
//retstr = StreamUtils.InputStreamTOString(StreamUtils.byteTOInputStream(process.getProcessXml()));
|
||||
response.getWriter().write(xmlContenxt);
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程表达式列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getExpressions", method = { RequestMethod.POST, RequestMethod.GET })
|
||||
public String getExpressions(HttpServletRequest request) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
//表达式业务类型
|
||||
String bizType = oConvertUtils.getString(request.getParameter("bizType"));
|
||||
log.debug(" getExpressions 登录令牌token: "+token);
|
||||
// String jsonpath = "classpath:org/jeecgframework/designer/mock/getExpressions.json";
|
||||
// return StringUtil.readJson(jsonpath);
|
||||
|
||||
//update-begin---author:scott ---date:2023-11-20 for:【QQYUN-7066】根据类型“指定人公式” ”候选人公式“,返回单人表达式或者多人表达式,以便于区分
|
||||
LambdaQueryWrapper<ExtActExpression> queryWrapper = new LambdaQueryWrapper<ExtActExpression>();
|
||||
if(oConvertUtils.isNotEmpty(bizType)){
|
||||
queryWrapper.eq(ExtActExpression::getBizType, bizType);
|
||||
}
|
||||
List<ExtActExpression> list = extActExpressionService.list(queryWrapper);
|
||||
//update-end---author:scott ---date:2023-11-20 for:【QQYUN-7066】根据类型“指定人公式” ”候选人公式“,返回单人表达式或者多人表达式,以便于区分
|
||||
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
map.put("total", list.size());
|
||||
map.put("rows", list);
|
||||
JSONObject json = new JSONObject(map);
|
||||
log.debug(json.toJSONString());
|
||||
return json.toJSONString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认流程监听
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getDefaultListener", method = { RequestMethod.POST, RequestMethod.GET })
|
||||
public String getDefaultListener(HttpServletRequest request) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
log.debug(" getDefaultListener 登录令牌token: "+token);
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
Map<String,Object> listenerObj = new HashMap<String,Object>();
|
||||
ExtActListener extActListener = extActListenerService.getById("402880e54803a496014805e5d9190012");
|
||||
if(extActListener!=null) {
|
||||
map.put("success", true);
|
||||
map.put("msg", "成功获取默认监听器!");
|
||||
listenerObj.put("id",extActListener.getId());
|
||||
listenerObj.put("listenername",extActListener.getListenerName());
|
||||
listenerObj.put("listenereven", extActListener.getListenerEvent());
|
||||
listenerObj.put("listenertype", extActListener.getListenerValueType());
|
||||
listenerObj.put("listenervalue", extActListener.getListenerValue());
|
||||
}else {
|
||||
map.put("success", false);
|
||||
map.put("msg", "获取默认监听器失败");
|
||||
}
|
||||
map.put("obj", listenerObj);
|
||||
JSONObject json = new JSONObject(map);
|
||||
log.debug(json.toJSONString());
|
||||
return json.toJSONString();
|
||||
// String jsonpath = "classpath:org/jeecgframework/designer/mock/getDefaultListener.json";
|
||||
// return StringUtil.readJson(jsonpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程角色组列表(也叫用户组列表)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getGroups", method = { RequestMethod.POST, RequestMethod.GET })
|
||||
public String getGroups(HttpServletRequest request) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
log.debug(" getGroups 登录令牌token: "+token);
|
||||
//TODO 有token风险
|
||||
//------------------------------------------------------------------------------------------------
|
||||
Integer tenantId = null;
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
|
||||
tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
List<RoleInfo> list = extActProcessService.getBpmRoles(tenantId);
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
map.put("total", list.size());
|
||||
map.put("rows", list);
|
||||
JSONObject json = new JSONObject(map);
|
||||
log.debug(json.toJSONString());
|
||||
return json.toJSONString();
|
||||
|
||||
// String jsonpath = "classpath:org/jeecgframework/designer/mock/getGroups.json";
|
||||
// return StringUtil.readJson(jsonpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程用户列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getUsers", method = { RequestMethod.POST, RequestMethod.GET })
|
||||
public String getUsers(HttpServletRequest request) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
log.debug(" getUsers 登录令牌token: "+token);
|
||||
//------------------------------------------------------------------------------------------------
|
||||
Integer tenantId = null;
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
|
||||
tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
//--update--begin------author:scott-----date:20210423-----for:【流程】用户数据多了以后就出现界面卡顿 LOWCOD-1488---------
|
||||
//List<UserInfo> list = extActProcessService.getBpmUsers();
|
||||
Page<UserInfo> page = new Page<UserInfo>(oConvertUtils.getInt(1), oConvertUtils.getInt(30));
|
||||
Page<UserInfo> list = extActProcessService.getPageBpmUsers(null,null,page,tenantId);
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
map.put("total", list.getTotal());
|
||||
map.put("rows", list.getRecords());
|
||||
//--update--end------author:scott-----date:20210423-----for:【流程】用户数据多了以后就出现界面卡顿 LOWCOD-1488-----------
|
||||
JSONObject json = new JSONObject(map);
|
||||
log.debug(json.toJSONString());
|
||||
return json.toJSONString();
|
||||
|
||||
//String jsonpath = "classpath:org/jeecgframework/designer/mock/getUsers.json";
|
||||
//return StringUtil.readJson(jsonpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取流程用户列表(popup分页列表)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getPageUsers", method = { RequestMethod.POST, RequestMethod.GET })
|
||||
public String getPageUsers(HttpServletRequest request) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
log.debug(" getPageUsers 登录令牌token: "+token);
|
||||
//TODO 有token风险
|
||||
Object pageNumber = request.getParameter("page"); //获取当前页码,easyui默认传到后台
|
||||
Object pageSize = request.getParameter("rows"); //获取每页显示多少行,easyui默认传到后台
|
||||
String account = request.getParameter("account"); //用户账号
|
||||
String name = request.getParameter("name"); //用户昵称
|
||||
//------------------------------------------------------------------------------------------------
|
||||
Integer tenantId = null;
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
|
||||
tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
log.debug("pageNumber: "+ oConvertUtils.getInt(pageNumber,1));
|
||||
log.debug("pageSize: "+ oConvertUtils.getInt(pageSize,10));
|
||||
log.debug("account: "+ account);
|
||||
log.debug("name: "+ name);
|
||||
Page<UserInfo> page = new Page<UserInfo>(oConvertUtils.getInt(pageNumber,1), oConvertUtils.getInt(pageSize,10));
|
||||
Page<UserInfo> list = extActProcessService.getPageBpmUsers(account,name,page,tenantId);
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
map.put("total", list.getTotal());
|
||||
map.put("rows", list.getRecords());
|
||||
JSONObject json = new JSONObject(map);
|
||||
log.debug(json.toJSONString());
|
||||
return json.toJSONString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 目前流程监听数据,不能通过解析xml直接获取数据,所以需要同步维护xml和表关系 1. 目前可以通过流程解析,获取到流程监听的 ids 2.
|
||||
* 然后通过ids ,再获取到流程监听数据列表
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/getListenersByIds")
|
||||
public String getRealListenerGrid(HttpServletRequest request, HttpServletResponse response) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
log.debug(" getRealListenerGrid 登录令牌token: "+token);
|
||||
//TODO 有token风险
|
||||
// 获取流程监听IDS
|
||||
String ids = oConvertUtils.getString(request.getParameter("ids"));
|
||||
String[] idsArr = ids.split(",");
|
||||
List<ListenerInfo> list = extActListenerService.getListenerInfoByIds(idsArr);
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
map.put("total", list.size());
|
||||
map.put("rows", list);
|
||||
JSONObject json = new JSONObject(map);
|
||||
log.debug(json.toJSONString());
|
||||
return json.toJSONString();
|
||||
|
||||
// return DesUtils.getMockDataRealListeners(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程监听类型返回不同监听列表
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/getListenersByType")
|
||||
public String getListenersByType(HttpServletRequest request, HttpServletResponse response) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
log.debug(" getListenersByType 登录令牌token: "+token);
|
||||
//TODO 有token风险
|
||||
// 获取流程监听IDS
|
||||
String typeid = oConvertUtils.getString(request.getParameter("typeid"));
|
||||
log.debug(" 流程监听类型 typeid: " + typeid);
|
||||
List<ListenerInfo> list = extActListenerService.getListenerInfoByType(typeid);
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
map.put("total", list.size());
|
||||
map.put("rows", list);
|
||||
JSONObject json = new JSONObject(map);
|
||||
log.debug(json.toJSONString());
|
||||
return json.toJSONString();
|
||||
// TODO
|
||||
// String jsonpath = "classpath:org/jeecgframework/designer/mock/listenersByType.json";
|
||||
// return StringUtil.readJson(jsonpath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取流程类型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getTypes", method = { RequestMethod.POST, RequestMethod.GET })
|
||||
public String getTypes(HttpServletRequest request) {
|
||||
List<ProcessTypeVo> ls = extActProcessMapper.getDictItems("bpm_process_type");
|
||||
List<Map> mapResult = ls.stream().map(p -> {
|
||||
Map mp = new HashMap();
|
||||
mp.put("value",p.getId());
|
||||
mp.put("label",p.getTypename());
|
||||
return mp;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
map.put("total", mapResult.size());
|
||||
map.put("rows", mapResult);
|
||||
|
||||
JSONObject json = new JSONObject(map);
|
||||
log.debug(json.toJSONString());
|
||||
return json.toJSONString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 导出流程
|
||||
*/
|
||||
@RequestMapping("/exportProcessDef")
|
||||
@ResponseBody
|
||||
public AjaxJson exportProcessDef(HttpServletRequest request, HttpServletResponse response) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
log.debug(" exportProcessDef 登录令牌token: "+token);
|
||||
//TODO 有token风险
|
||||
AjaxJson j = new AjaxJson();
|
||||
String procdefId = oConvertUtils.getString(request.getParameter("procdefId"));
|
||||
String processName = oConvertUtils.getString(request.getParameter("processName"));
|
||||
LambdaQueryWrapper<ExtActProcess> queryWrapper = new LambdaQueryWrapper<ExtActProcess>();
|
||||
queryWrapper.eq(ExtActProcess::getProcessKey, procdefId);
|
||||
ExtActProcess tProcess = extActProcessService.getOne(queryWrapper);
|
||||
// String token = oConvertUtils.getString(request.getParameter("token"),"NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=");
|
||||
// //校验 token 登录有效性
|
||||
// TokenUtils.verifyToken(request, sysBaseAPI, redisUtil);
|
||||
|
||||
try {
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(tProcess.getProcessXml());
|
||||
String filename = procdefId + ".bpmn20.xml";
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + filename);
|
||||
IOUtils.copy(in, response.getOutputStream());
|
||||
response.flushBuffer();
|
||||
j.setMsg("导出成功!");
|
||||
in.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 保存流程
|
||||
*/
|
||||
@RequiresPermissions("act:des:process:save")
|
||||
@RequestMapping("/saveProcess")
|
||||
@ResponseBody
|
||||
public AjaxJson saveProcess(HttpServletRequest request) {
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
log.debug(" exportProcessDef 登录令牌token: "+token);
|
||||
//TODO 有token风险
|
||||
AjaxJson j = new AjaxJson();
|
||||
try {
|
||||
j = extActProcessService.saveProcess(request);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
j.setMsg(e.getMessage());
|
||||
j.setSuccess(false);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
package org.jeecg.modules.designer.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.TokenUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActProcess;
|
||||
import org.jeecg.modules.extbpm.process.mapper.ExtActProcessMapper;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
*
|
||||
* @ClassName: DesignerController
|
||||
* @Description: 流程设计器(负责页面跳转)
|
||||
* @author scott
|
||||
* @date 2010-03-12
|
||||
*
|
||||
*/
|
||||
@Controller("designerController")
|
||||
@RequestMapping("/act/designer")
|
||||
public class DesignerController {
|
||||
private static final Log logger = LogFactory.getLog(DesignerController.class);
|
||||
@Autowired
|
||||
private IExtActProcessService extActProcessService;
|
||||
@Autowired
|
||||
private ExtActProcessMapper extActProcessMapper;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
@Autowired
|
||||
@Lazy
|
||||
private RedisUtil redisUtil;
|
||||
/**
|
||||
* 流程设计主页
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping
|
||||
public void index(HttpServletRequest request,HttpServletResponse response) {
|
||||
String processid = oConvertUtils.getString(request.getParameter("id"), "0");
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
logger.info(" index 登录令牌token: "+token);
|
||||
//校验 token 登录有效性
|
||||
TokenUtils.verifyToken(request, sysBaseAPI, redisUtil);
|
||||
|
||||
request.setAttribute("processid", processid);// 流程ID
|
||||
request.setAttribute("token", token);// 登录人token令牌 NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
try {
|
||||
request.getRequestDispatcher("/designer/index.jsp").forward(request,response);
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程设计属性页面跳转
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@RequestMapping("processProperties")
|
||||
public void processProperties(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
|
||||
String turn = oConvertUtils.getString(request.getParameter("turn"));
|
||||
String id = oConvertUtils.getString(request.getParameter("id"));// 流程当前节点Id
|
||||
String checkbox = oConvertUtils.getString(request.getParameter("checkbox"));// 设置单选多选
|
||||
String processId = oConvertUtils.getString(request.getParameter("processId"));// 流程ID
|
||||
//TODO 查看流程属性是请求中流程id传参传给该属性了 后期需要优化
|
||||
String processDefinitionId = oConvertUtils.getString(request.getParameter("processDefinitionId"));// 流程ID
|
||||
logger.info(" 流程设计属性页面 turn: " + turn + ",节点ID: " + id + ",checkbox: " + checkbox + ",processId: " + processId);
|
||||
|
||||
//设置流程类型
|
||||
ExtActProcess process = extActProcessService.getById(processId);
|
||||
if(process!=null) {
|
||||
request.setAttribute("typeId", process.getProcessType());// 流程ID
|
||||
}else {
|
||||
process = extActProcessService.getById(processDefinitionId);
|
||||
if(process!=null) {
|
||||
request.setAttribute("typeId", process.getProcessType());// 流程ID
|
||||
}else{
|
||||
//默认测试流程
|
||||
request.setAttribute("typeId", "test");
|
||||
}
|
||||
}
|
||||
request.setAttribute("checkbox", checkbox);
|
||||
request.setAttribute("id", id);
|
||||
//流程设计器流程类型设置
|
||||
request.setAttribute("proTypeList", extActProcessMapper.getDictItems("bpm_process_type"));
|
||||
request.setAttribute("processId", processId);
|
||||
request.getRequestDispatcher("/designer/" + turn+".jsp").forward(request,response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择表达式页面
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@RequestMapping("goExpression")
|
||||
public void goExpression(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
|
||||
String id = oConvertUtils.getString(request.getParameter("id"));// 流程当前节点Id
|
||||
String checkbox = oConvertUtils.getString(request.getParameter("checkbox"));// 设置单选多选
|
||||
String processId = oConvertUtils.getString(request.getParameter("processId"));// 流程ID
|
||||
request.setAttribute("checkbox", checkbox);
|
||||
request.setAttribute("id", id);
|
||||
request.setAttribute("processId", processId);
|
||||
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
logger.debug(" index 登录令牌token: "+token);
|
||||
request.setAttribute("token", token);// 登录人token令牌
|
||||
request.getRequestDispatcher("/designer/selectExpressionList.jsp").forward(request,response);
|
||||
}
|
||||
|
||||
/**
|
||||
* popup选择用户列表页面
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("goSearchSelectUser")
|
||||
public void goSearchSelectUser(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
|
||||
String id = oConvertUtils.getString(request.getParameter("id"));// 流程当前节点Id
|
||||
String checkbox = oConvertUtils.getString(request.getParameter("checkbox"));// 设置单选多选
|
||||
String processId = oConvertUtils.getString(request.getParameter("processId"));// 流程ID
|
||||
request.setAttribute("checkbox", checkbox);
|
||||
request.setAttribute("id", id);
|
||||
request.setAttribute("processId", processId);
|
||||
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
logger.debug(" index 登录令牌token: "+token);
|
||||
request.setAttribute("token", token);// 登录人token令牌
|
||||
request.getRequestDispatcher("/designer/searchSelectUserList.jsp").forward(request,response);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 跳转到子流程参数配置页面
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("goSubParameterList")
|
||||
public void subParameterList(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
|
||||
String id = oConvertUtils.getString(request.getParameter("id"));// 流程当前节点Id
|
||||
String checkbox = oConvertUtils.getString(request.getParameter("checkbox"));// 设置单选多选
|
||||
String processId = oConvertUtils.getString(request.getParameter("processId"));// 流程ID
|
||||
request.setAttribute("checkbox", checkbox);
|
||||
request.setAttribute("id", id);
|
||||
request.setAttribute("processId", processId);
|
||||
request.getRequestDispatcher("/designer/subParameterList.jsp").forward(request,response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到监听列表页面
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@RequestMapping("goListeners")
|
||||
public void goListeners(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
|
||||
// 获取流程监听IDS
|
||||
String typeid = oConvertUtils.getString(request.getParameter("typeid"));
|
||||
logger.info(" 流程监听类型 typeid: " + typeid);
|
||||
request.setAttribute("typeid", typeid);
|
||||
|
||||
String token = oConvertUtils.getString(request.getParameter("token"));
|
||||
logger.debug(" index 登录令牌token: "+token);
|
||||
request.setAttribute("token", token);// 登录人token令牌
|
||||
request.getRequestDispatcher("/designer/selectProcessListenerList.jsp").forward(request,response);
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package org.jeecg.modules.designer.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jeecg.common.constant.TenantConstant;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.TokenUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActProcess;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.jeecg.modules.extbpm.util.ViewFreemarker;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程设计器 NEW
|
||||
* @Author jeecg
|
||||
* @since 2021-10-27
|
||||
*/
|
||||
@Controller("designerNewController")
|
||||
@RequestMapping("/act/designer")
|
||||
@Slf4j
|
||||
public class DesignerNewController {
|
||||
private static final Log logger = LogFactory.getLog(DesignerNewController.class);
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
@Autowired
|
||||
@Lazy
|
||||
private RedisUtil redisUtil;
|
||||
@Autowired
|
||||
private IExtActProcessService extActProcessService;
|
||||
|
||||
/**
|
||||
* 打开流程设计界面
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param id
|
||||
* @param token
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping("/index")
|
||||
public void designer(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestParam(name="id",required = false,defaultValue = "") String id,
|
||||
@RequestParam(name="token",required = false,defaultValue = "") String token) throws Exception{
|
||||
Map content = new HashMap<String,Object>(5);
|
||||
content.put("id",id);
|
||||
content.put("token",token);
|
||||
|
||||
//支持应用ID的设置 20220908
|
||||
String lowAppId = request.getParameter(TenantConstant.FIELD_LOW_APP_ID);
|
||||
if(oConvertUtils.isNotEmpty(lowAppId)){
|
||||
content.put(TenantConstant.FIELD_LOW_APP_ID,lowAppId);
|
||||
}
|
||||
|
||||
//支持租户ID的设置 20221229
|
||||
String tenantId = TokenUtils.getTenantIdByRequest(request);
|
||||
content.put(TenantConstant.TENANT_ID, tenantId);
|
||||
|
||||
//base url
|
||||
String domianURL= this.getBaseUrl(request);
|
||||
content.put("domianURL",domianURL);
|
||||
if(oConvertUtils.isNotEmpty(id)){
|
||||
//流程类型
|
||||
ExtActProcess process = extActProcessService.getById(id);
|
||||
content.put("typeid", oConvertUtils.getString(process.getProcessType(),"test"));
|
||||
}else{
|
||||
content.put("typeid","test");
|
||||
}
|
||||
logger.info(" index 登录令牌token: "+token);
|
||||
//校验 token 登录有效性
|
||||
TokenUtils.verifyToken(request, sysBaseAPI, redisUtil);
|
||||
//跳转 ftl页面
|
||||
ViewFreemarker.view(request, response, "templates/desflow/designer.ftl", content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务器地址
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private String getBaseUrl(HttpServletRequest request) {
|
||||
//1.【微服务环境下】用户、部门等接口无法获取数据问题--------
|
||||
String x_gateway_base_path = request.getHeader("X_GATEWAY_BASE_PATH");
|
||||
if(oConvertUtils.isNotEmpty(x_gateway_base_path)){
|
||||
log.info("x_gateway_base_path = "+ x_gateway_base_path);
|
||||
return x_gateway_base_path;
|
||||
}
|
||||
|
||||
//2. SSL认证之后,request.getScheme()获取不到https的问题记录
|
||||
// https://blog.csdn.net/weixin_34376986/article/details/NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
String scheme = request.getHeader("X-Forwarded-Scheme");
|
||||
if(oConvertUtils.isEmpty(scheme)){
|
||||
scheme = request.getScheme();
|
||||
}
|
||||
|
||||
//3.常规操作
|
||||
String serverName = request.getServerName();
|
||||
int serverPort = request.getServerPort();
|
||||
String contextPath = request.getContextPath();
|
||||
|
||||
|
||||
//返回 host domain
|
||||
String baseDomainPath = null;
|
||||
if(80 == serverPort){
|
||||
baseDomainPath = scheme + "://" + serverName + contextPath ;
|
||||
}else{
|
||||
baseDomainPath = scheme + "://" + serverName + ":" + serverPort + contextPath ;
|
||||
}
|
||||
log.info("================getBaseUrl==============: " + baseDomainPath);
|
||||
return baseDomainPath;
|
||||
}
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package org.jeecg.modules.extbpm.enums;
|
||||
|
||||
/**
|
||||
* 流程节点消息类型
|
||||
* @author: jeecg-boot
|
||||
*/
|
||||
public enum TaskTipTypeEnum {
|
||||
|
||||
XT("system", "bpm_system"),
|
||||
YJ("email", "bpm_email"),
|
||||
DD("dingtalk", "bpm_dingtalk"),
|
||||
QYWX("wechat_enterprise", "bpm_wechat_enterprise");
|
||||
|
||||
TaskTipTypeEnum(String type, String code){
|
||||
this.type = type;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
String type;
|
||||
|
||||
/**
|
||||
* 模板编码
|
||||
*/
|
||||
String code;
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static String getCodeByType(String type) {
|
||||
for (TaskTipTypeEnum e : TaskTipTypeEnum.values()) {
|
||||
if (type.startsWith(e.getType())) {
|
||||
return e.getCode();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
package org.jeecg.modules.extbpm.job;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.jeecg.common.api.dto.message.BusTemplateMessageDTO;
|
||||
import org.jeecg.common.constant.CommonSendStatus;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.constant.enums.SysAnnmentTypeEnum;
|
||||
import org.jeecg.modules.bpm.dto.ActRuTaskDTO;
|
||||
import org.jeecg.modules.bpm.mapper.ActivitiMapper;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecgframework.core.util.ApplicationContextUtil;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @Author scott
|
||||
* @Date 2019/11/7 18:30
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
public class TimeOutTask implements Job {
|
||||
|
||||
private static TaskService taskService;
|
||||
private static ISysBaseAPI sysBaseAPI;
|
||||
private static ActivitiMapper activitiMapper;
|
||||
static {
|
||||
taskService = ApplicationContextUtil.getContext().getBean(TaskService.class);
|
||||
sysBaseAPI = ApplicationContextUtil.getContext().getBean(ISysBaseAPI.class);
|
||||
activitiMapper = ApplicationContextUtil.getContext().getBean(ActivitiMapper.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext arg0) throws JobExecutionException {
|
||||
try {
|
||||
log.info("----------【定时任务】--任务超时提醒开始--------------");
|
||||
List<ActRuTaskDTO> list = activitiMapper.getTimeoutTask();
|
||||
if (list != null && list.size() > 0) {
|
||||
taskDeal(list);
|
||||
}
|
||||
log.info("-----------【定时任务】--任务超时提醒结束---------------");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void taskDeal(List<ActRuTaskDTO> list) {
|
||||
try {
|
||||
for (ActRuTaskDTO actRuTaskDTO : list) {
|
||||
//超时时间
|
||||
int nodeTimeout = actRuTaskDTO.getNodeTimeout();
|
||||
//流程发起时间
|
||||
Date startTime = actRuTaskDTO.getCreateTime();
|
||||
if (checkTimeOut(startTime, nodeTimeout)) {
|
||||
log.info("-------------任务超时提醒-----startTime=" + startTime.toString()+",nodeTimeout="+nodeTimeout);
|
||||
String taskId = actRuTaskDTO.getId();
|
||||
String bpmBizTitle = (String) taskService.getVariable(taskId, WorkFlowGlobals.BPM_BIZ_TITLE);
|
||||
Map<String, String> mp = new HashMap<>();
|
||||
mp.put("title",bpmBizTitle);
|
||||
mp.put("task",actRuTaskDTO.getName());
|
||||
mp.put("user",actRuTaskDTO.getAssignee());
|
||||
mp.put("time",DateUtils.formatDateTime());
|
||||
//系统通知
|
||||
BusTemplateMessageDTO msg = new BusTemplateMessageDTO("流程通知", actRuTaskDTO.getAssignee(),"任务超时提醒",mp,CommonSendStatus.TZMB_BPM_CHAOSHI_TIP, SysAnnmentTypeEnum.BPM.getType(),taskId);
|
||||
sysBaseAPI.sendBusTemplateAnnouncement(msg);
|
||||
//sysBaseAPI.sendSysAnnouncement("系统", (String) map.get("ASSIGNEE_"), "任务超时提醒", sb.toString());
|
||||
//短信通知接口
|
||||
//邮件通知接口
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较时间大小
|
||||
* @param startTime
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
private boolean checkTimeOut(Date startTime, Integer timeout) {
|
||||
boolean flag = false;
|
||||
try {
|
||||
if (timeout == null || startTime == null) {
|
||||
return flag;
|
||||
}
|
||||
Calendar calSrc = Calendar.getInstance();
|
||||
Calendar calDes = Calendar.getInstance();
|
||||
calDes.setTime(startTime);
|
||||
int diff = DateUtils.dateDiff('h', calSrc, calDes);
|
||||
if (diff >= timeout) {
|
||||
flag = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
package org.jeecg.modules.extbpm.job;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.api.NativeTaskQuery;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.modules.bpm.dto.UserAgentDTO;
|
||||
import org.jeecg.modules.bpm.service.ActivitiService;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActBpmLog;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActBpmLogService;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户代理任务
|
||||
*
|
||||
* @author zhoujf
|
||||
*/
|
||||
@Slf4j
|
||||
public class UserAgentJob implements Job {
|
||||
|
||||
private static TaskService taskService;
|
||||
private static ActivitiService activitiService;
|
||||
private static IExtActBpmLogService extActBpmLogService;
|
||||
protected static RuntimeService runtimeService;
|
||||
static {
|
||||
taskService = SpringContextUtils.getBean(TaskService.class);
|
||||
activitiService = SpringContextUtils.getBean(ActivitiService.class);
|
||||
extActBpmLogService = SpringContextUtils.getBean(IExtActBpmLogService.class);
|
||||
runtimeService = SpringContextUtils.getBean(RuntimeService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
log.info(String.format(" Jeecg-Boot 用户代理任务 UserAgentJob ! 时间:" + DateUtils.getTimestamp()));
|
||||
try {
|
||||
//查询有代理设置的用户
|
||||
String currDateStr = DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
|
||||
Date currDate = DateUtils.parseDate(currDateStr, "yyyy-MM-dd HH:mm:ss");
|
||||
List<UserAgentDTO> userAgentList = activitiService.getUserAgent(currDate);
|
||||
for(UserAgentDTO agent:userAgentList) {
|
||||
//log.info("--------任务处理人:"+agent.getUserName()+",代办人:"+agent.getAgentUserName());
|
||||
taskDeal(agent);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Jeecg-Boot 用户代理任务 UserAgentJob 异常"+e.getMessage(),e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void taskDeal(UserAgentDTO agent){
|
||||
//1、查用户的待处理的任务
|
||||
StringBuilder sb = new StringBuilder("");
|
||||
sb.append("select * ").append("from (");
|
||||
//---update-begin-----autor:zhoujf------date:20190916-------for:未签收的任务不进行委派--------
|
||||
//sb.append("(select distinct RES.* ");
|
||||
//sb.append(" from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
|
||||
//sb.append("WHERE RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' ");
|
||||
//sb.append(" and ( I.USER_ID_ = #{userid} or I.GROUP_ID_ IN ( select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = #{userid} ) ");
|
||||
//sb.append(" ) ").append(" and RES.SUSPENSION_STATE_ = 1 ");
|
||||
//sb.append(") union ");
|
||||
//---update-end-----autor:zhoujf------date:20190916-------for:未签收的任务不进行委派--------
|
||||
sb.append("(select distinct RES.* ");
|
||||
sb.append(" from ACT_RU_TASK RES ");
|
||||
sb.append("WHERE RES.ASSIGNEE_ = #{userid} ");
|
||||
sb.append(" )) v ");
|
||||
// sb.append(" order by v.CREATE_TIME_ desc, v.PRIORITY_ desc ");
|
||||
|
||||
NativeTaskQuery query = taskService.createNativeTaskQuery()
|
||||
.sql(sb.toString())
|
||||
.parameter("userid", agent.getUserName());
|
||||
List<Task> pretasks = query.list();
|
||||
//2、任务委派给代理人
|
||||
for(Task task:pretasks){
|
||||
log.info("-------------任务id:"+task.getId()+",taskName:"+task.getName());
|
||||
try{
|
||||
//---update-begin-----autor:zhoujf------date:20190916-------for:未签收的任务不进行委派--------
|
||||
//判断任务是否签收没有签收需要进行签收
|
||||
//if(oConvertUtils.isEmpty(task.getAssignee())) {
|
||||
// taskService.claim(task.getId(), agent.getAgentUserName());
|
||||
//}
|
||||
//---update-end-----autor:zhoujf------date:20190916-------for:未签收的任务不进行委派--------
|
||||
this.trunTask(task.getId(), agent.getAgentUserName());
|
||||
String description = ""+task.getAssignee()==null?"系统":task.getAssignee()+" 转办任务【"+task.getName()+"】给 "+agent.getAgentUserName()+" 办理";
|
||||
String processInstanceId = task.getProcessInstanceId();
|
||||
|
||||
//保存审批意见
|
||||
this.saveBpmLog(processInstanceId, description, task, agent);
|
||||
|
||||
}catch(Exception e){
|
||||
log.error("Jeecg-Boot 用户代理任务 UserAgentJob 异常"+e.getMessage(),e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转办
|
||||
*
|
||||
* @param taskId
|
||||
* @param assignee
|
||||
* @return
|
||||
*/
|
||||
public boolean trunTask(String taskId, String assignee) {
|
||||
taskService.setAssignee(taskId, assignee);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存审批日志
|
||||
*
|
||||
* @param processInstanceId
|
||||
* @param description
|
||||
* @param task
|
||||
* @param agent
|
||||
*/
|
||||
private void saveBpmLog(String processInstanceId,String description,Task task,UserAgentDTO agent){
|
||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
ExtActBpmLog bpmlog = new ExtActBpmLog();
|
||||
if(processInstance!=null) {
|
||||
bpmlog.setBusinessKey(processInstance.getBusinessKey());
|
||||
bpmlog.setProcName(processInstance.getName());
|
||||
}
|
||||
bpmlog.setOpTime(new Date());
|
||||
bpmlog.setOpUserId(WorkFlowGlobals.SYS_AGENT_JOB_OPUSER_ID);
|
||||
bpmlog.setOpUserName("系统任务");
|
||||
bpmlog.setProcInstId(processInstanceId);
|
||||
bpmlog.setRemarks(description);
|
||||
bpmlog.setTaskDefKey(task.getTaskDefinitionKey());
|
||||
bpmlog.setTaskId(task.getId());
|
||||
bpmlog.setTaskName(task.getName());
|
||||
extActBpmLogService.save(bpmlog);
|
||||
String msg = "用户"+task.getName()+"[任务,id:"+task.getId()+",taskName:"+task.getName()+"]委派给"+ agent.getAgentUserName();
|
||||
log.info(msg);
|
||||
}
|
||||
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @Project: jeecg
|
||||
* @Title: ProcessEndListener.java
|
||||
* @Package com.oa.manager.workFlow.listener.execution
|
||||
* NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
* @date 2013-8-16 下午2:04:12
|
||||
* @Copyright: 2013
|
||||
*/
|
||||
package org.jeecg.modules.extbpm.listener.execution;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActFlowData;
|
||||
import org.jeecg.modules.extbpm.process.mapper.ExtActFlowDataMapper;
|
||||
import org.jeecg.modules.extbpm.process.mapper.ExtActProcessMapper;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActFormDataService;
|
||||
|
||||
|
||||
/**
|
||||
* 类名:ProcessEndListener
|
||||
* 功能:流程实例结束监听器
|
||||
* @author zhoujf
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
public class ProcessEndListener implements ExecutionListener{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void notify(DelegateExecution execution) {
|
||||
//修改流程状态
|
||||
doUpdateStatus(execution);
|
||||
|
||||
// //清空流程实例所有历史流程变量,任务变量
|
||||
// HistoryService historyService = SpringContextUtils.getBean(HistoryService.class);
|
||||
// List<HistoricVariableInstance> hvis = historyService.createHistoricVariableInstanceQuery().processInstanceId(execution.getProcessInstanceId()).list();
|
||||
//
|
||||
// for(HistoricVariableInstance h:hvis){
|
||||
// //log.info(h.getVariableName());
|
||||
// //流程对应的表单业务标题,不清空
|
||||
// if(WorkFlowGlobals.BPM_DATA_ID.equals(h.getVariableName())){
|
||||
// continue;
|
||||
// }
|
||||
// if(WorkFlowGlobals.BPM_FORM_KEY.equals(h.getVariableName())){
|
||||
// continue;
|
||||
// }
|
||||
// if(WorkFlowGlobals.BPM_BIZ_TITLE.equals(h.getVariableName())){
|
||||
// continue;
|
||||
// }
|
||||
// //流程办理风格,不清空
|
||||
// if(WorkFlowGlobals.BPM_PROC_DEAL_STYLE.equals(h.getVariableName())){
|
||||
// continue;
|
||||
// }
|
||||
// //流程对应的表单页面,不清空
|
||||
// if(!WorkFlowGlobals.BPM_FORM_CONTENT_URL.equals(h.getVariableName()) && !WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE.equals(h.getVariableName())){
|
||||
// //TODO 待测试
|
||||
// ((HistoricVariableInstanceEntity)h).setDeleted(true);
|
||||
// }
|
||||
// }
|
||||
log.info(" -- 流程结束监听执行完成 -- ");
|
||||
}
|
||||
|
||||
|
||||
private void doUpdateStatus(DelegateExecution execution){
|
||||
String businessKey = execution.getProcessInstanceBusinessKey();
|
||||
log.info("流程结束监听,处理businessKey = {}",businessKey );
|
||||
|
||||
if(oConvertUtils.isEmpty(businessKey)) {
|
||||
return;
|
||||
}
|
||||
ExtActProcessMapper extActProcessMapper= SpringContextUtils.getBean(ExtActProcessMapper.class);
|
||||
ExtActFlowDataMapper extActFlowDataMapper= SpringContextUtils.getBean(ExtActFlowDataMapper.class);
|
||||
IExtActFormDataService extActFormDataService= SpringContextUtils.getBean(IExtActFormDataService.class);
|
||||
String desFormCode = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.BPM_DES_FORM_CODE));
|
||||
String bpmDesDataId = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.BPM_DES_DATA_ID));
|
||||
|
||||
String bpmStatus=(String)execution.getVariable(WorkFlowGlobals.BPM_STATUS);//获取流程状态
|
||||
// String bpm_form_key = (String)execution.getVariable(WorkFlowGlobals.BPM_FORM_KEY);//获取流程对应的表单
|
||||
// String id = (String)execution.getVariable(WorkFlowGlobals.BPM_DATA_ID);//获取表单数据id
|
||||
// String formType = (String)execution.getVariable(WorkFlowGlobals.BPM_FORM_TYPE);//获取表单类型
|
||||
if(WorkFlowGlobals.PROCESS_CALLBACKPROCESS_STATUS.equals(bpmStatus)){
|
||||
//流程追回逻辑
|
||||
LambdaQueryWrapper<ExtActFlowData> queryWrapper = new LambdaQueryWrapper<ExtActFlowData>();
|
||||
queryWrapper.eq(ExtActFlowData::getFormDataId, businessKey);
|
||||
queryWrapper.eq(ExtActFlowData::getProcessInstId, execution.getProcessInstanceId());
|
||||
ExtActFlowData extActFlowData = extActFlowDataMapper.selectOne(queryWrapper);
|
||||
//更新表单状态
|
||||
if(extActFlowData!=null) {
|
||||
String tableName = extActFlowData.getFormTableName().toUpperCase();
|
||||
if(oConvertUtils.isEmpty(desFormCode) || WorkFlowGlobals.DESIGN_FORM_DRAFT_TABLE.equals(tableName)){
|
||||
//变更物理表 流程状态
|
||||
String col = extActFlowData.getBpmStatusField();
|
||||
if(oConvertUtils.isEmpty(col)) {
|
||||
col = "BPM_STATUS";
|
||||
}
|
||||
extActProcessMapper.updateBpmStatusById(tableName, businessKey, col.toUpperCase(), WorkFlowGlobals.BPM_BUS_STATUS_1);
|
||||
}
|
||||
if(oConvertUtils.isNotEmpty(desFormCode)){
|
||||
//变更设计器表单和映射的,online表单的流程状态
|
||||
extActFormDataService.updateDesformAndOnlineDataStatus(desFormCode,bpmDesDataId,extActFlowData.getBpmStatusField(), WorkFlowGlobals.BPM_BUS_STATUS_1);
|
||||
}
|
||||
extActFlowDataMapper.deleteById(extActFlowData.getId());
|
||||
}
|
||||
|
||||
}else if(WorkFlowGlobals.PROCESS_INVALIDPROCESS_STATUS.equals(bpmStatus)){
|
||||
LambdaQueryWrapper<ExtActFlowData> queryWrapper = new LambdaQueryWrapper<ExtActFlowData>();
|
||||
queryWrapper.eq(ExtActFlowData::getFormDataId, businessKey);
|
||||
queryWrapper.eq(ExtActFlowData::getProcessInstId, execution.getProcessInstanceId());
|
||||
ExtActFlowData extActFlowData = extActFlowDataMapper.selectOne(queryWrapper);
|
||||
//更新表单状态
|
||||
if(extActFlowData!=null) {
|
||||
String tableName = extActFlowData.getFormTableName().toUpperCase();
|
||||
log.debug("-------tableName--------"+ tableName);
|
||||
if(oConvertUtils.isEmpty(desFormCode) || WorkFlowGlobals.DESIGN_FORM_DRAFT_TABLE.equals(tableName)){
|
||||
//变更物理表 流程状态
|
||||
String col = extActFlowData.getBpmStatusField().toUpperCase();
|
||||
if(oConvertUtils.isEmpty(col)) {
|
||||
col = "BPM_STATUS";
|
||||
}
|
||||
extActProcessMapper.updateBpmStatusById(tableName, businessKey, col, WorkFlowGlobals.BPM_BUS_STATUS_4);
|
||||
}
|
||||
if(oConvertUtils.isNotEmpty(desFormCode)){
|
||||
//变更设计器表单和映射的,online表单的流程状态
|
||||
extActFormDataService.updateDesformAndOnlineDataStatus(desFormCode,bpmDesDataId,extActFlowData.getBpmStatusField(), WorkFlowGlobals.BPM_BUS_STATUS_4);
|
||||
}
|
||||
extActFlowData.setBpmStatus(WorkFlowGlobals.BPM_BUS_STATUS_4);
|
||||
extActFlowDataMapper.updateById(extActFlowData);
|
||||
}
|
||||
}else {
|
||||
LambdaQueryWrapper<ExtActFlowData> queryWrapper = new LambdaQueryWrapper<ExtActFlowData>();
|
||||
queryWrapper.eq(ExtActFlowData::getFormDataId, businessKey);
|
||||
queryWrapper.eq(ExtActFlowData::getProcessInstId, execution.getProcessInstanceId());
|
||||
ExtActFlowData extActFlowData = extActFlowDataMapper.selectOne(queryWrapper);
|
||||
//1.更新表单状态
|
||||
if(extActFlowData!=null) {
|
||||
String tableName = extActFlowData.getFormTableName().toUpperCase();
|
||||
if(oConvertUtils.isEmpty(desFormCode) || WorkFlowGlobals.DESIGN_FORM_DRAFT_TABLE.equals(tableName)){
|
||||
//变更物理表 流程状态
|
||||
String col = extActFlowData.getBpmStatusField().toUpperCase();
|
||||
if(oConvertUtils.isEmpty(col)) {
|
||||
col = "BPM_STATUS";
|
||||
}
|
||||
extActProcessMapper.updateBpmStatusById(tableName, businessKey, col, WorkFlowGlobals.BPM_BUS_STATUS_3);
|
||||
}
|
||||
if(oConvertUtils.isNotEmpty(desFormCode)){
|
||||
//变更设计器表单和映射的,online表单的流程状态
|
||||
extActFormDataService.updateDesformAndOnlineDataStatus(desFormCode,bpmDesDataId,extActFlowData.getBpmStatusField(),WorkFlowGlobals.BPM_BUS_STATUS_3);
|
||||
}
|
||||
extActFlowData.setBpmStatus(WorkFlowGlobals.BPM_BUS_STATUS_3);
|
||||
extActFlowDataMapper.updateById(extActFlowData);
|
||||
}
|
||||
//2.修改流程中的流程变量为已完成
|
||||
execution.setVariable(WorkFlowGlobals.BPM_STATUS,WorkFlowGlobals.BPM_BUS_STATUS_3);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* @Project: jeecg
|
||||
* @Title: ProcessEndListener.java
|
||||
* @Package com.oa.manager.workFlow.listener.execution
|
||||
* @date 2013-8-16 下午2:04:12
|
||||
* @Copyright: 2013
|
||||
*/
|
||||
package org.jeecg.modules.extbpm.listener.execution;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import liquibase.pro.packaged.U;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.engine.runtime.ProcessInstanceQuery;
|
||||
import org.jeecg.common.constant.DataBaseConstant;
|
||||
import org.jeecg.common.desform.api.IDesformBaseApi;
|
||||
import org.jeecg.common.desform.vo.DesignFormDataVo;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.bpm.service.ActivitiService;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActProcess;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActProcessForm;
|
||||
import org.jeecg.modules.extbpm.process.mapper.ExtActProcessFormMapper;
|
||||
import org.jeecg.modules.extbpm.process.mapper.ExtActProcessMapper;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 【简流】
|
||||
* 类名:SignalProcessStartListener
|
||||
* 功能:信号启动流程监听
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
@Slf4j
|
||||
public class SignalProcessStartListener implements ExecutionListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static ExtActProcessMapper extActProcessMapper;
|
||||
private static ExtActProcessFormMapper extActProcessFormMapper;
|
||||
private static IDesformBaseApi desformBaseApi;
|
||||
private static IExtActProcessService extActProcessService;
|
||||
private static RuntimeService runtimeService;
|
||||
static {
|
||||
extActProcessMapper = SpringContextUtils.getBean(ExtActProcessMapper.class);
|
||||
extActProcessFormMapper = SpringContextUtils.getBean(ExtActProcessFormMapper.class);
|
||||
desformBaseApi = SpringContextUtils.getBean(IDesformBaseApi.class);
|
||||
extActProcessService = SpringContextUtils.getBean(IExtActProcessService.class);
|
||||
runtimeService = SpringContextUtils.getBean(RuntimeService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 这里可以加逻辑,定义给子流程传递变量
|
||||
*
|
||||
* @param execution
|
||||
*/
|
||||
@Override
|
||||
public void notify(DelegateExecution execution) {
|
||||
|
||||
//接口参数
|
||||
String id = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.BPM_DATA_ID));
|
||||
String tableName = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.BPM_FORM_KEY));
|
||||
//表单类型 —— 1:Online表单,2:设计器表单,3:自定义开发
|
||||
String bpmFormType = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.BPM_FORM_TYPE));
|
||||
String formUrl = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.BPM_FORM_CONTENT_URL));
|
||||
String formUrlMobile = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE));
|
||||
String username = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.APPLY_USER_ID));
|
||||
|
||||
String processInstanceId = execution.getProcessInstanceId();
|
||||
|
||||
//更新业务data id
|
||||
runtimeService.updateBusinessKey(processInstanceId,id);
|
||||
String processDefinitionKey = null;
|
||||
String processDefinitionName = null;
|
||||
|
||||
log.info("data id = {}", id);
|
||||
log.info("tableName = {}", tableName);
|
||||
log.info("bpmFormType = {}", bpmFormType);
|
||||
log.info("processInstanceId = {}", processInstanceId);
|
||||
try {
|
||||
ProcessInstance processInstance = (ProcessInstance)execution;
|
||||
processDefinitionKey = processInstance.getProcessDefinitionKey();
|
||||
processDefinitionName = processInstance.getProcessDefinitionName();
|
||||
log.info("getProcessDefinitionKey = {}", processDefinitionKey);
|
||||
log.info("getProcessDefinitionName = {}", processDefinitionName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//获取流程设计配置
|
||||
LambdaQueryWrapper<ExtActProcess> queryWrapper = new LambdaQueryWrapper<ExtActProcess>();
|
||||
queryWrapper.eq(ExtActProcess::getProcessKey, processDefinitionKey);
|
||||
ExtActProcess extActProcess = extActProcessMapper.selectOne(queryWrapper);
|
||||
log.info("process Des Id = {}", extActProcess.getId());
|
||||
|
||||
//查询流程业务关联配置
|
||||
ExtActProcessForm extActProcessForm = null;
|
||||
LambdaQueryWrapper<ExtActProcessForm> extActProcessFormQueryWrapper = new LambdaQueryWrapper<ExtActProcessForm>();
|
||||
extActProcessFormQueryWrapper.eq(ExtActProcessForm::getFormTableName, tableName);
|
||||
extActProcessFormQueryWrapper.eq(ExtActProcessForm::getProcessId, extActProcess.getId());
|
||||
extActProcessForm = extActProcessFormMapper.selectOne(extActProcessFormQueryWrapper);
|
||||
|
||||
|
||||
Map<String, Object> dataForm = null;
|
||||
if (WorkFlowGlobals.BPM_FORM_TYPE_2.equals(bpmFormType)) {
|
||||
dataForm = this.getJsonDataById(tableName, id, execution);
|
||||
dataForm.put(WorkFlowGlobals.BPM_DES_DATA_ID, id);
|
||||
dataForm.put(WorkFlowGlobals.BPM_DES_FORM_CODE, tableName);
|
||||
} else {
|
||||
dataForm = this.getDataById(tableName, id);
|
||||
}
|
||||
if (dataForm == null) {
|
||||
dataForm = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
|
||||
//获取数据创建人
|
||||
if(oConvertUtils.isEmpty(username)){
|
||||
username = oConvertUtils.getString(dataForm != null ? dataForm.get(DataBaseConstant.CREATE_BY_TABLE) : null);
|
||||
}
|
||||
log.info("获取登录人: {}" , username);
|
||||
|
||||
dataForm.put(WorkFlowGlobals.BPM_DATA_ID, id);
|
||||
dataForm.put(WorkFlowGlobals.BPM_FORM_CONTENT_URL, formUrl);
|
||||
if (oConvertUtils.isNotEmpty(formUrlMobile)) {
|
||||
dataForm.put(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE, formUrlMobile);
|
||||
} else {
|
||||
//没有传移动端表单,默认用PC端
|
||||
dataForm.put(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE, formUrl);
|
||||
}
|
||||
dataForm.put(WorkFlowGlobals.BPM_FORM_KEY, tableName);
|
||||
extActProcessService.startSignalMutilProcess(username, id, dataForm, extActProcessForm, execution);
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Object> getJsonDataById(String desFormCode, String id, DelegateExecution execution) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
//TODO 设计器表单改成 mongdb后,查询不到数据报错临时方案
|
||||
//Map<String, Object> desformData = extActProcessMapper.getJsonDataById(id);
|
||||
DesignFormDataVo designFormDataVo = desformBaseApi.getTranslateDataById(desFormCode, id);
|
||||
|
||||
// 如果是删除数据走流程,从mongo查不到数据,再从流程变量中查询一下
|
||||
if (designFormDataVo == null || designFormDataVo.getDesformData() == null) {
|
||||
JSONObject bpmDeleteData = execution.getVariable(WorkFlowGlobals.BPM_DELETE_DATA, JSONObject.class);
|
||||
if (oConvertUtils.isNotEmpty(bpmDeleteData)) {
|
||||
designFormDataVo = JSONObject.toJavaObject(bpmDeleteData , DesignFormDataVo.class);
|
||||
}
|
||||
}
|
||||
|
||||
if (designFormDataVo != null && designFormDataVo.getDesformData()!=null) {
|
||||
for (Map.Entry<String, Object> entry : designFormDataVo.getDesformData().entrySet()) {
|
||||
//update-begin--- author:scott---date:20201227------for:JT-250【流程】特殊字段 发起流程失败------
|
||||
//大字段处理
|
||||
if (entry.getValue() != null && (entry.getValue() instanceof Clob || entry.getValue() instanceof Blob)) {
|
||||
continue;
|
||||
}
|
||||
//update-end--- author:scott---date:20201227------for:JT-250【流程】特殊字段 发起流程失败------
|
||||
result.put(entry.getKey().toLowerCase(), entry.getValue());
|
||||
}
|
||||
}else{
|
||||
//删除走流程此实体会为空
|
||||
result.put("id", id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Object> getDataById(String tableName, String id) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
Map<String, Object> data = extActProcessMapper.getDataById(tableName, id);
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
//update-begin--- author:scott---date:20201227------for:JT-250【流程】特殊字段 发起流程失败------
|
||||
//大字段处理
|
||||
if (entry.getValue() != null && (entry.getValue() instanceof Clob || entry.getValue() instanceof Blob)) {
|
||||
continue;
|
||||
}
|
||||
//update-end--- author:scott---date:20201227------for:JT-250【流程】特殊字段 发起流程失败------
|
||||
result.put(entry.getKey().toLowerCase(), entry.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @Project: jeecg
|
||||
* @Title: ProcessEndListener.java
|
||||
* @Package com.oa.manager.workFlow.listener.execution
|
||||
* @date 2013-8-16 下午2:04:12
|
||||
* @Copyright: 2013
|
||||
*/
|
||||
package org.jeecg.modules.extbpm.listener.execution;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 类名:SubProcessStartListener
|
||||
* 功能:会签子流程开始监听器
|
||||
* @author zhoujf
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
public class SubProcessHqStartListener implements ExecutionListener{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void notify(DelegateExecution execution) {
|
||||
|
||||
RuntimeService runtimeService = SpringContextUtils.getBean(RuntimeService.class);
|
||||
String mainProcessId = (String)execution.getVariable(WorkFlowGlobals.JG_SUB_MAIN_PROCESS_ID);
|
||||
String url = (String)execution.getVariable(WorkFlowGlobals.BPM_FORM_CONTENT_URL);
|
||||
String bizTitle = (String)runtimeService.getVariable(mainProcessId,WorkFlowGlobals.BPM_BIZ_TITLE);
|
||||
if(org.apache.commons.lang.StringUtil.isEmpty(url)) {
|
||||
url = (String)runtimeService.getVariable(mainProcessId,WorkFlowGlobals.BPM_FORM_CONTENT_URL);
|
||||
String mobileUrl = (String)runtimeService.getVariable(mainProcessId,WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE);
|
||||
execution.setVariable(WorkFlowGlobals.BPM_FORM_CONTENT_URL, url);
|
||||
execution.setVariable(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE, mobileUrl);
|
||||
}
|
||||
execution.setVariable(WorkFlowGlobals.BPM_BIZ_TITLE, bizTitle);
|
||||
//获取主表数据id
|
||||
String businessKey = (String)runtimeService.getVariable(mainProcessId, WorkFlowGlobals.BPM_DATA_ID);
|
||||
//获取主表的设计表单数据ID
|
||||
String BPM_DES_DATA_ID = oConvertUtils.getString(runtimeService.getVariable(mainProcessId, WorkFlowGlobals.BPM_DES_DATA_ID));
|
||||
|
||||
//获取主表表名
|
||||
String tableName = (String)runtimeService.getVariable(mainProcessId,WorkFlowGlobals.BPM_FORM_KEY);
|
||||
execution.setVariable(WorkFlowGlobals.BPM_FORM_KEY, tableName);
|
||||
|
||||
//--update--begin------author:scott-----date:20210512-----for:出差借款子流程,加载表单数据为空问题---------
|
||||
log.info("----------传入子流程的数据ID--------------: "+execution.getVariable(WorkFlowGlobals.DATA_ID));
|
||||
if(oConvertUtils.isNotEmpty(execution.getVariable(WorkFlowGlobals.DATA_ID))){
|
||||
execution.setVariable(WorkFlowGlobals.BPM_DATA_ID, execution.getVariable(WorkFlowGlobals.DATA_ID));
|
||||
//如果是设计器表单,则还需要设置设计表单数据ID
|
||||
if(oConvertUtils.isNotEmpty(BPM_DES_DATA_ID)){
|
||||
execution.setVariable(WorkFlowGlobals.BPM_DES_DATA_ID, execution.getVariable(WorkFlowGlobals.DATA_ID));
|
||||
}
|
||||
}else{
|
||||
//未传入id值,则获取主表数据id给子流程【online表单需要】
|
||||
execution.setVariable(WorkFlowGlobals.BPM_DATA_ID, businessKey);
|
||||
//如果是设计器表单,则还需要设置设计表单数据ID
|
||||
if(oConvertUtils.isNotEmpty(BPM_DES_DATA_ID)){
|
||||
execution.setVariable(WorkFlowGlobals.BPM_DES_DATA_ID, BPM_DES_DATA_ID);
|
||||
}
|
||||
}
|
||||
//--update--end------author:scott-----date:20210512-----for:出差借款子流程,加载表单数据为空问题---------
|
||||
|
||||
//子流程实例set业务号和主流程保持一致
|
||||
runtimeService.updateBusinessKey(execution.getProcessInstanceId(), businessKey);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @Project: jeecg
|
||||
* @Title: ProcessEndListener.java
|
||||
* @Package com.oa.manager.workFlow.listener.execution
|
||||
* @date 2013-8-16 下午2:04:12
|
||||
* @Copyright: 2013
|
||||
*/
|
||||
package org.jeecg.modules.extbpm.listener.execution;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 类名:SubProcessStartListener
|
||||
* 功能:子流程启动监听
|
||||
* @author zhoujf
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
public class SubProcessStartListener implements ExecutionListener{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 这里可以加逻辑,定义给子流程传递变量
|
||||
* @param execution
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void notify(DelegateExecution execution) {
|
||||
|
||||
RuntimeService runtimeService = SpringContextUtils.getBean(RuntimeService.class);
|
||||
String mainProcessId = oConvertUtils.getString(execution.getVariable(WorkFlowGlobals.JG_SUB_MAIN_PROCESS_ID));
|
||||
log.info("------------主流程的ID--------------["+mainProcessId+"]");
|
||||
if(oConvertUtils.isNotEmpty(mainProcessId)){
|
||||
String bizTitle = oConvertUtils.getString(runtimeService.getVariable(mainProcessId,WorkFlowGlobals.BPM_BIZ_TITLE));
|
||||
String businessKey = oConvertUtils.getString(runtimeService.getVariable(mainProcessId, WorkFlowGlobals.BPM_DATA_ID));
|
||||
//设计表单数据ID
|
||||
String BPM_DES_DATA_ID = oConvertUtils.getString(runtimeService.getVariable(mainProcessId, WorkFlowGlobals.BPM_DES_DATA_ID));
|
||||
execution.setVariable(WorkFlowGlobals.BPM_BIZ_TITLE, bizTitle);
|
||||
|
||||
//获取主表表名【online表单需要】
|
||||
String tableName = oConvertUtils.getString(runtimeService.getVariable(mainProcessId,WorkFlowGlobals.BPM_FORM_KEY));
|
||||
execution.setVariable(WorkFlowGlobals.BPM_FORM_KEY, tableName);
|
||||
|
||||
//--update--begin------author:scott-----date:20210512-----for:出差借款子流程,加载表单数据为空问题---------
|
||||
if(execution.hasVariable(WorkFlowGlobals.DATA_ID)){
|
||||
log.info("----------传入子流程的,数据ID--------------[ " + execution.getVariable(WorkFlowGlobals.DATA_ID) +"]");
|
||||
execution.setVariable(WorkFlowGlobals.BPM_DATA_ID, execution.getVariable(WorkFlowGlobals.DATA_ID));
|
||||
//如果是设计器表单,则还需要设置设计表单数据ID
|
||||
if(oConvertUtils.isNotEmpty(BPM_DES_DATA_ID)){
|
||||
execution.setVariable(WorkFlowGlobals.BPM_DES_DATA_ID, execution.getVariable(WorkFlowGlobals.DATA_ID));
|
||||
}
|
||||
}else{
|
||||
//未传入id值,则获取主表数据id给子流程【online表单需要】
|
||||
execution.setVariable(WorkFlowGlobals.BPM_DATA_ID, businessKey);
|
||||
//如果是设计器表单,则还需要设置设计表单数据ID
|
||||
if(oConvertUtils.isNotEmpty(BPM_DES_DATA_ID)){
|
||||
execution.setVariable(WorkFlowGlobals.BPM_DES_DATA_ID, BPM_DES_DATA_ID);
|
||||
}
|
||||
}
|
||||
//--update--end------author:scott-----date:20210512-----for:出差借款子流程,加载表单数据为空问题---------
|
||||
|
||||
//子流程实例set业务号和主流程保持一致
|
||||
runtimeService.updateBusinessKey(execution.getProcessInstanceId(), businessKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package org.jeecg.modules.extbpm.listener.global;
|
||||
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
|
||||
|
||||
/**
|
||||
* Activiti的事件处理器
|
||||
* @author zhoujf
|
||||
*
|
||||
*/
|
||||
public interface FlowEventHandler {
|
||||
/**
|
||||
* 事件处理器
|
||||
* @param event
|
||||
*/
|
||||
public void handle(FlowableEvent event);
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package org.jeecg.modules.extbpm.listener.global;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.flowable.common.engine.api.delegate.event.AbstractFlowableEventListener;
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Activiti的全局事件监听器,即所有事件均需要在这里统一分发处理
|
||||
* @author zhoujf
|
||||
*
|
||||
*/
|
||||
public class GlobalEventListener extends AbstractFlowableEventListener {
|
||||
|
||||
/**
|
||||
* 日志处理器
|
||||
*/
|
||||
public final static Logger logger = LoggerFactory.getLogger(GlobalEventListener.class);
|
||||
|
||||
//事件及事件的处理器
|
||||
//private Map<String,EventHandler> handlers=new HashMap<String, EventHandler>();
|
||||
//更换为以下模式,可以防止Spring容器启动时,ProcessEngine尚未创建,而业务类中又使用了这个引用
|
||||
private Map<String,String> handlers=new HashMap<String, String>();
|
||||
|
||||
@Override
|
||||
public void onEvent(FlowableEvent event) {
|
||||
String eventType=event.getType().name();
|
||||
logger.debug("envent type is ========>" + eventType);
|
||||
//根据事件的类型ID,找到对应的事件处理器
|
||||
String eventHandlerBeanId=handlers.get(eventType);
|
||||
if(eventHandlerBeanId!=null){
|
||||
FlowEventHandler handler=(FlowEventHandler)SpringContextUtils.getBean(eventHandlerBeanId);
|
||||
handler.handle(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFailOnException() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<String, String> getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public void setHandlers(Map<String, String> handlers) {
|
||||
this.handlers = handlers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package org.jeecg.modules.extbpm.listener.global;
|
||||
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.StartEvent;
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
|
||||
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
|
||||
import org.flowable.engine.impl.context.Context;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.modules.bpm.service.ActivitiService;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActBpmLog;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActBpmLogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @TODO 待测试1 【这个监听类好像没人用】
|
||||
*
|
||||
* 全局自动完成首个任务监听器
|
||||
* Created by Vim 2018/11/21 9:46
|
||||
*
|
||||
* @author Vim
|
||||
*/
|
||||
@Component("taskCreatedEventListener")
|
||||
public class TaskCreatedEventListener implements FlowableEventListener {
|
||||
@Autowired
|
||||
private IExtActBpmLogService extActBpmLogService;
|
||||
@Autowired
|
||||
protected RuntimeService runtimeService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
|
||||
@Override
|
||||
public void onEvent(FlowableEvent event) {
|
||||
if (!(event instanceof FlowableEntityEventImpl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FlowableEntityEventImpl entityEvent = (FlowableEntityEventImpl) event;
|
||||
|
||||
Object entity = entityEvent.getEntity();
|
||||
|
||||
//是否是任务实体类
|
||||
if (!(entity instanceof TaskEntity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TaskEntity taskEntity = (TaskEntity) entity;
|
||||
|
||||
//是否是在任务节点创建时
|
||||
if (FlowableEngineEventType.TASK_CREATED.equals(event.getType())) {
|
||||
//找到流程第一个userTask节点
|
||||
FlowElement firstElement = this.findFirstFlowElement(taskEntity);
|
||||
|
||||
//对比节点是否相同,因为有可能有子流程的节点进来
|
||||
if (firstElement != null && taskEntity.getTaskDefinitionKey().equals(firstElement.getId())) {
|
||||
Context.getProcessEngineConfiguration().getTaskService().complete(taskEntity.getId());
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
//记录审批日志
|
||||
String username = JwtUtil.getUserNameByToken(SpringContextUtils.getHttpServletRequest());
|
||||
LoginUser user = sysBaseAPI.getUserByName(username);
|
||||
String processInstanceId = taskEntity.getProcessInstanceId();
|
||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
ExtActBpmLog bpmlog = new ExtActBpmLog();
|
||||
if(processInstance!=null) {
|
||||
bpmlog.setBusinessKey(processInstance.getBusinessKey());
|
||||
bpmlog.setProcName(processInstance.getName());
|
||||
}
|
||||
bpmlog.setOpTime(new Date());
|
||||
bpmlog.setOpUserId(username);
|
||||
if(user!=null){
|
||||
bpmlog.setOpUserName(user.getRealname());
|
||||
}
|
||||
bpmlog.setProcInstId(processInstanceId);
|
||||
bpmlog.setRemarks("发起流程");
|
||||
bpmlog.setTaskDefKey(taskEntity.getTaskDefinitionKey());
|
||||
bpmlog.setTaskId(taskEntity.getId());
|
||||
bpmlog.setTaskName(taskEntity.getName());
|
||||
extActBpmLogService.save(bpmlog);
|
||||
//---------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找流程第一个userTask
|
||||
*/
|
||||
private FlowElement findFirstFlowElement(TaskEntity taskEntity) {
|
||||
RepositoryService repositoryService = SpringContextUtils.getBean(RepositoryService.class);
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(taskEntity.getProcessDefinitionId());
|
||||
for (FlowElement flowElement : bpmnModel.getProcesses().get(0).getFlowElements()) {
|
||||
if (flowElement instanceof StartEvent) {
|
||||
return bpmnModel.getFlowElement(((StartEvent) flowElement).getOutgoingFlows().get(0).getTargetRef());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFailOnException() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFireOnTransactionLifecycleEvent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOnTransaction() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.jeecg.modules.extbpm.listener.service;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.JavaDelegate;
|
||||
|
||||
/**
|
||||
* @Description: 流程服务节点
|
||||
* 参考: https://blog.csdn.net/shirdrn/article/details/NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
* https://www.iteye.com/blog/topmanopensource-1315238
|
||||
* @author: scott
|
||||
* @date: 2020/3/30 19:58
|
||||
*/
|
||||
@Slf4j
|
||||
public class ServiceTask implements JavaDelegate {
|
||||
|
||||
//重写委托的提交方法
|
||||
@Override
|
||||
public void execute(DelegateExecution execution) {
|
||||
|
||||
log.info("serviceTask已经执行已经执行!");
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.info("variavles=" + execution.getVariables());
|
||||
execution.setVariable("task1", "I am task 1");
|
||||
log.info("I am task 1.");
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.jeecg.modules.extbpm.listener.task;
|
||||
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 子流程开始监听
|
||||
*/
|
||||
@Service("subProcessListener")
|
||||
public class SubProcessListener implements TaskListener{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
//获取主流程实例
|
||||
String mainProcessId = (String)delegateTask.getVariable(WorkFlowGlobals.JG_SUB_MAIN_PROCESS_ID);
|
||||
String bizTitle = (String)runtimeService.getVariable(mainProcessId,WorkFlowGlobals.BPM_BIZ_TITLE);
|
||||
String businessKey = (String)runtimeService.getVariable(mainProcessId, WorkFlowGlobals.BPM_DATA_ID);
|
||||
delegateTask.setVariable(WorkFlowGlobals.BPM_BIZ_TITLE, bizTitle);
|
||||
//子流程实例set业务号和主流程保持一致
|
||||
runtimeService.updateBusinessKey(delegateTask.getProcessInstanceId(), businessKey);
|
||||
}
|
||||
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package org.jeecg.modules.extbpm.listener.task;
|
||||
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.StartEvent;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.modules.bpm.service.ActivitiService;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActBpmLog;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActBpmLogService;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 首节点任务被创建时自动执行通过
|
||||
*
|
||||
* @author zhoujf
|
||||
* A task has been created. This is thrown when task is fully initialized (before TaskListener.EVENTNAME_CREATE)
|
||||
*/
|
||||
public class TaskCreatedAutoSubmitListener implements TaskListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static ISysBaseAPI sysBaseAPI;
|
||||
private static IExtActBpmLogService extActBpmLogService;
|
||||
protected static RuntimeService runtimeService;
|
||||
private static ActivitiService activitiService;
|
||||
private static TaskService taskService;
|
||||
|
||||
static {
|
||||
sysBaseAPI = SpringContextUtils.getBean(ISysBaseAPI.class);
|
||||
extActBpmLogService = SpringContextUtils.getBean(IExtActBpmLogService.class);
|
||||
runtimeService = SpringContextUtils.getBean(RuntimeService.class);
|
||||
activitiService = SpringContextUtils.getBean(ActivitiService.class);
|
||||
taskService = SpringContextUtils.getBean(TaskService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
try {
|
||||
//如果是流程的第一步,则自动提交
|
||||
this.onCreate(delegateTask);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void onCreate(DelegateTask delegateTask) throws Exception {
|
||||
//找到流程第一个userTask节点
|
||||
FlowElement firstElement = this.findFirstFlowElement(delegateTask);
|
||||
//判断如果当前节点不是首节点,则不做任何处理
|
||||
if (!firstElement.getId().equals(delegateTask.getTaskDefinitionKey())) {
|
||||
return;
|
||||
}
|
||||
|
||||
//判断是否存在历史节点,存在说明第一个节点已经自动审批过
|
||||
List<Map<String,Object>> histListNode = activitiService.getHistTaskNodeList(delegateTask.getProcessInstanceId());
|
||||
if(histListNode!=null&&histListNode.size()>0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String applyUserId = (String)delegateTask.getVariable("applyUserId");
|
||||
//设置任务处理人为发起人
|
||||
taskService.setAssignee(delegateTask.getId(), applyUserId);
|
||||
//自动完成
|
||||
taskService.complete(delegateTask.getId(),delegateTask.getVariables());
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//记录审批日志
|
||||
String username = JwtUtil.getUserNameByToken(SpringContextUtils.getHttpServletRequest());
|
||||
LoginUser user = sysBaseAPI.getUserByName(username);
|
||||
String processInstanceId = delegateTask.getProcessInstanceId();
|
||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
ExtActBpmLog bpmlog = new ExtActBpmLog();
|
||||
if(processInstance!=null) {
|
||||
bpmlog.setBusinessKey(processInstance.getBusinessKey());
|
||||
bpmlog.setProcName(processInstance.getName());
|
||||
}
|
||||
bpmlog.setOpTime(new Date());
|
||||
bpmlog.setOpUserId(username);
|
||||
if(user!=null){
|
||||
bpmlog.setOpUserName(user.getRealname());
|
||||
}
|
||||
bpmlog.setProcInstId(processInstanceId);
|
||||
bpmlog.setRemarks("系统自动完成");
|
||||
bpmlog.setTaskDefKey(delegateTask.getTaskDefinitionKey());
|
||||
bpmlog.setTaskId(delegateTask.getId());
|
||||
bpmlog.setTaskName(delegateTask.getName());
|
||||
extActBpmLogService.save(bpmlog);
|
||||
//----------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public RepositoryService getRepositoryService(){
|
||||
return SpringContextUtils.getBean(RepositoryService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @TODO 待测试1
|
||||
*
|
||||
* 查找流程第一个userTask
|
||||
*/
|
||||
private FlowElement findFirstFlowElement(DelegateTask taskEntity) {
|
||||
RepositoryService repositoryService = SpringContextUtils.getBean(RepositoryService.class);
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(taskEntity.getProcessDefinitionId());
|
||||
for (FlowElement flowElement : bpmnModel.getProcesses().get(0).getFlowElements()) {
|
||||
if (flowElement instanceof StartEvent) {
|
||||
return bpmnModel.getFlowElement(((StartEvent) flowElement).getOutgoingFlows().get(0).getTargetRef());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
package org.jeecg.modules.extbpm.listener.task;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.jeecg.common.desform.api.IDesformBaseApi;
|
||||
import org.jeecg.common.desform.vo.DesignFormDataVo;
|
||||
import org.jeecg.common.miniflow.ISignalProcessStartApi;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActDesignFlowData;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActProcess;
|
||||
import org.jeecg.modules.extbpm.process.mapper.ExtActDesignFlowDataMapper;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActProcessService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author scott
|
||||
* 通过节点监听更新业务数据在流程里面的变量数据
|
||||
*/
|
||||
@Slf4j
|
||||
public class TaskUpdateFormDataListener implements TaskListener {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static IExtActProcessService extActProcessService;
|
||||
private static ExtActDesignFlowDataMapper extActDesignFlowDataMapper;
|
||||
private static IDesformBaseApi desformBaseApi;
|
||||
private static ISignalProcessStartApi signalProcessStartApi;
|
||||
|
||||
static {
|
||||
extActProcessService = SpringContextUtils.getBean(IExtActProcessService.class);
|
||||
extActDesignFlowDataMapper = SpringContextUtils.getBean(ExtActDesignFlowDataMapper.class);
|
||||
desformBaseApi = SpringContextUtils.getBean(IDesformBaseApi.class);
|
||||
try {
|
||||
signalProcessStartApi = SpringContextUtils.getBean(ISignalProcessStartApi.class);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
//获取主流程实例
|
||||
String processInstanceId = delegateTask.getProcessInstanceId();
|
||||
String bpmDataId = (String) delegateTask.getVariable(WorkFlowGlobals.BPM_DATA_ID);
|
||||
String businessKey = (String) delegateTask.getVariable(WorkFlowGlobals.BPM_FORM_KEY);
|
||||
String bpmDesFormCode = (String) delegateTask.getVariable(WorkFlowGlobals.BPM_DES_FORM_CODE);
|
||||
|
||||
Map<String, Object> dataForm = new HashMap<String, Object>();
|
||||
//表单老数据(流程变量中的字段值)
|
||||
DesignFormDataVo oldFormDataVo = new DesignFormDataVo();
|
||||
if(WorkFlowGlobals.DESIGN_FORM_DRAFT_TABLE.equals(businessKey)){
|
||||
//如果是表单设计器的数据(需要关联通过中间表取数据)
|
||||
ExtActDesignFlowData extActDesignFlowData = extActDesignFlowDataMapper.selectById(bpmDataId);
|
||||
//DesignFormDataDTO designFormDataDTO = extActDesignFlowDataMapper.getDesignFormDataById(extActDesignFlowData.getDesformDataId());
|
||||
//dataForm = JSONHelper.json2MapNoObj(designFormDataDTO.getDesformDataJson());
|
||||
DesignFormDataVo designFormDataVo = desformBaseApi.getDataById(extActDesignFlowData.getDesformCode(),extActDesignFlowData.getDesformDataId());
|
||||
dataForm = designFormDataVo.getDesformData();
|
||||
// 复制数据
|
||||
BeanUtils.copyProperties(designFormDataVo, oldFormDataVo);
|
||||
}else if(!WorkFlowGlobals.DESIGN_FORM_DRAFT_TABLE.equals(businessKey) && oConvertUtils.isNotEmpty(bpmDesFormCode)){
|
||||
DesignFormDataVo designFormDataVo = desformBaseApi.getTranslateDataById(bpmDesFormCode, bpmDataId);
|
||||
dataForm = designFormDataVo.getDesformData();
|
||||
// 复制数据
|
||||
BeanUtils.copyProperties(designFormDataVo, oldFormDataVo);
|
||||
}else{
|
||||
//update-begin---author:scott ---date:2023-11-19 for:【QQYUN-6845】简流填写节点配置了 加签 使用加签时 报错----------
|
||||
//获取对应的物理表的业务数据
|
||||
if(oConvertUtils.isNotEmpty(businessKey) && oConvertUtils.isNotEmpty(bpmDataId)){
|
||||
dataForm = extActProcessService.getDataById(businessKey, bpmDataId);
|
||||
}
|
||||
//update-end---author:scott ---date::2023-11-19 for:【QQYUN-6845】简流填写节点配置了 加签 使用加签时 报错----------
|
||||
}
|
||||
|
||||
if (dataForm != null && !dataForm.isEmpty()) {
|
||||
for (Map.Entry<String, Object> entry : dataForm.entrySet()) {
|
||||
String mapKey = entry.getKey();
|
||||
Object mapValue = entry.getValue();
|
||||
//TODO 存在大小写问题
|
||||
|
||||
// 1.先备份流程变量中的表单值,用于触发简流事件
|
||||
if(oldFormDataVo!=null && oldFormDataVo.getDesformData()!=null){
|
||||
oldFormDataVo.getDesformData().put(mapKey, delegateTask.getVariable(mapKey));
|
||||
}
|
||||
// 2.更新流程变量中的表单数据为新值
|
||||
log.info(" 同步更变流程变量 execution.setVariable => "+ mapKey + ":" + mapValue);
|
||||
delegateTask.setVariable(mapKey, mapValue);
|
||||
}
|
||||
|
||||
//update-begin---author:scott ---date:2023-12-06 for:填报节点提交流程后,抛出的设计器表单的简流触发事件---
|
||||
// 流程填报节点提交流程后,抛出简流的表单事件
|
||||
try {
|
||||
if(oConvertUtils.isNotEmpty(bpmDesFormCode)){
|
||||
String definitionId = delegateTask.getProcessDefinitionId();
|
||||
String processKey = definitionId.contains(":") ? definitionId.substring(0, definitionId.indexOf(":")) : definitionId;
|
||||
ExtActProcess extActProcess = extActProcessService.getExtActProcessByKey(processKey);
|
||||
if(extActProcess!=null && "1".equals(extActProcess.getTriggerOtherProcess())) {
|
||||
String action = "update";
|
||||
signalProcessStartApi.signalStartProcess(action, bpmDataId, oldFormDataVo, bpmDesFormCode, null);
|
||||
}
|
||||
}
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
log.warn("低代码模式无简流模块,不支持触发流程信号!");
|
||||
}
|
||||
//update-end---author:scott ---date::2023-12-06 for:填报节点提交流程后,抛出的设计器表单的简流触发事件---
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package org.jeecg.modules.extbpm.process.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CodeUtil {
|
||||
|
||||
|
||||
public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f",
|
||||
"g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
|
||||
"t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
|
||||
"6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
|
||||
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
|
||||
"W", "X", "Y", "Z" };
|
||||
/** 随机数总长度 */
|
||||
private static final int maxLength = 10;
|
||||
/** 随机编码 */
|
||||
private static final int[] r = new int[]{7, 9, 6, 2, 8 , 1, 3, 0, 5, 4};
|
||||
|
||||
|
||||
/**
|
||||
* 生成8位无重复随机码
|
||||
* @return
|
||||
*/
|
||||
public static String generateShortUuid() {
|
||||
StringBuffer shortBuffer = new StringBuffer();
|
||||
String uuid = UUID.randomUUID().toString().replace("-", "");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
String str = uuid.substring(i * 4, i * 4 + 4);
|
||||
int x = Integer.parseInt(str, 16);
|
||||
shortBuffer.append(chars[x % 0x3E]);
|
||||
}
|
||||
return shortBuffer.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成数字类型的UUID
|
||||
* @return
|
||||
*/
|
||||
public static String getUUIDNum() {
|
||||
int machineId = 1;//最大支持1-9个集群机器部署
|
||||
int hashCodeV = UUID.randomUUID().toString().hashCode();
|
||||
if(hashCodeV < 0) {//有可能是负数
|
||||
hashCodeV = - hashCodeV;
|
||||
}
|
||||
// 0 代表前面补充0
|
||||
// 4 代表长度为4
|
||||
// d 代表参数为正数型
|
||||
return machineId + String.format("%015d", hashCodeV);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成固定长度随机码
|
||||
* @param n 长度
|
||||
*/
|
||||
private static long getRandom(long n) {
|
||||
long min = 1, max = 9;
|
||||
for (int i = 1; i < n; i++) {
|
||||
min *= 10;
|
||||
max *= 10;
|
||||
}
|
||||
long rangeLong = (((long) (new Random().nextDouble() * (max - min)))) + min;
|
||||
return rangeLong;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更具id进行加密+加随机数组成固定长度编码
|
||||
*/
|
||||
public static String generateCode(Long id) {
|
||||
String idStr = id.toString();
|
||||
StringBuilder idsbs = new StringBuilder();
|
||||
for (int i = idStr.length() - 1 ; i >= 0; i--) {
|
||||
idsbs.append(r[idStr.charAt(i)-'0']);
|
||||
}
|
||||
return idsbs.append(getRandom(maxLength - idStr.length())).toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 更具id进行加密+加随机数组成固定长度编码
|
||||
*/
|
||||
public static String generateCode(String pre) {
|
||||
StringBuilder idsbs = new StringBuilder();
|
||||
idsbs.append(pre);
|
||||
return idsbs.append(getRandom(maxLength - pre.length())).toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
Set<String> codes = new HashSet<String>();
|
||||
String code = "";
|
||||
for(int i=0;i<1000;i++) {
|
||||
// code= generateShortUuid();
|
||||
// code = generateCode("PPP");
|
||||
code = getUUIDNum();
|
||||
codes.add(code);
|
||||
System.out.println(code);
|
||||
}
|
||||
System.out.println("---------size-------"+codes.size());
|
||||
}
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package org.jeecg.modules.extbpm.process.common;
|
||||
|
||||
/**
|
||||
* 流程办理风格枚举
|
||||
* @author junfeng.zhou
|
||||
* @version $ v1.0 $
|
||||
*/
|
||||
public enum ProcDealStyleEnum {
|
||||
DEFAULT("default", "默认",""),
|
||||
office("office", "流程与表单自定义","office/"),
|
||||
SINGLE("single", "单页面","single/"),
|
||||
SINGLE_SUBMIT("singlesubmit", "单页面并提交表单","singlesubmit/");
|
||||
private String code;//风格编码
|
||||
private String name;//风格名称
|
||||
private String viewName;//风格页面路径
|
||||
|
||||
private ProcDealStyleEnum(String code, String name,String viewName) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.viewName = viewName;
|
||||
}
|
||||
public static ProcDealStyleEnum toEnum(String code) {
|
||||
for (ProcDealStyleEnum type : ProcDealStyleEnum.values()) {
|
||||
if (type.code.equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return ProcDealStyleEnum.DEFAULT;
|
||||
// throw new IllegalArgumentException("the style argument of " + code
|
||||
// + " has no correspond ProcDealStyleEnum enums.");
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getViewName() {
|
||||
return viewName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
package org.jeecg.modules.extbpm.process.common;
|
||||
|
||||
/**
|
||||
* 项目名称:jeecg
|
||||
* 类名称:Globals
|
||||
* 类描述: 全局变量定义
|
||||
* 创建人:zhoujf
|
||||
* @version
|
||||
*
|
||||
*/
|
||||
public final class WorkFlowGlobals {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 流程发布状态
|
||||
*/
|
||||
public static Integer Process_Deploy_NO=0;//未发布
|
||||
public static Integer Process_Deploy_YES=1;//已发布
|
||||
|
||||
/**
|
||||
* BPM_BUS_STATUS[流程业务单据状态位]
|
||||
* 待提交:1/处理中:2/处理完毕:3
|
||||
*/
|
||||
public static String BPM_BUS_STATUS_1 = "1";//待提交
|
||||
public static String BPM_BUS_STATUS_2 = "2";//处理中
|
||||
public static String BPM_BUS_STATUS_3 = "3";//处理完毕
|
||||
public static String BPM_BUS_STATUS_4 = "4";//流程作废
|
||||
public static String BPM_BUS_STATUS_5 = "5";//流程挂起
|
||||
|
||||
|
||||
/**
|
||||
* BPM 流程对应的表单KEY
|
||||
*/
|
||||
public static String BPM_FORM_KEY = "BPM_FORM_KEY";
|
||||
/**
|
||||
* BPM 流程流程开始节点名字
|
||||
*/
|
||||
public static String BPM_NODE_START = "start";
|
||||
/**
|
||||
* BPM 流程流程开始节点名字
|
||||
*/
|
||||
public static String BPM_NODE_END = "end";
|
||||
|
||||
/**
|
||||
* BPM 流程对应的流程实例ID KEY[当前流程]
|
||||
*/
|
||||
public static String JG_LOCAL_PROCESS_ID = "JG_LOCAL_PROCESS_ID";
|
||||
/**
|
||||
* BPM 流程对应的流程实例ID KEY[主流程]
|
||||
*/
|
||||
public static String JG_SUB_MAIN_PROCESS_ID = "JG_SUB_MAIN_PROCESS_ID";
|
||||
/**
|
||||
* 业务数据对应ID
|
||||
*/
|
||||
public static String BPM_DATA_ID = "BPM_DATA_ID";
|
||||
public static String DATA_ID = "id";
|
||||
/**
|
||||
* 日期字段触发流程的字段名
|
||||
*/
|
||||
public static String TIME_TRIGGER_FIELD = "TIME_TRIGGER_FIELD";
|
||||
|
||||
/**
|
||||
* 删除数据对象(删除数据走流程)
|
||||
*/
|
||||
public static final String BPM_DELETE_DATA = "BPM_DELETE_DATA";
|
||||
|
||||
/**
|
||||
* 流程发起人
|
||||
*/
|
||||
public static String APPLY_USER_ID = "applyUserId";
|
||||
/**
|
||||
* 设计器表单编码
|
||||
*/
|
||||
public static String BPM_DES_FORM_CODE = "BPM_DES_FORM_CODE";
|
||||
/**
|
||||
* 设计器表单数据ID
|
||||
*/
|
||||
public static String BPM_DES_DATA_ID = "BPM_DES_DATA_ID";
|
||||
/**
|
||||
* 设计器表单关联编码——固定前缀
|
||||
*/
|
||||
public static String BPM_DES_FORM_RELATION_CODE_PREFIX = "desform_";
|
||||
|
||||
/**
|
||||
* BPM 节点对应的表单URL(全局)
|
||||
*/
|
||||
public static String BPM_FORM_CONTENT_URL = "BPM_FORM_CONTENT_URL";
|
||||
/**
|
||||
* BPM 节点对应的表单URL(全局) - 移动端
|
||||
*/
|
||||
public static String BPM_FORM_CONTENT_URL_MOBILE = "BPM_FORM_CONTENT_URL_MOBILE";
|
||||
|
||||
/**
|
||||
* BPM 流程状态
|
||||
*/
|
||||
public static String BPM_STATUS = "bpm_status";
|
||||
/**
|
||||
* BPM 业务标题表达式(全局)
|
||||
*/
|
||||
public static String BPM_BIZ_TITLE = "bpm_biz_title";
|
||||
/**
|
||||
* BPM 流程办理风格(全局)
|
||||
*/
|
||||
public static String BPM_PROC_DEAL_STYLE = "bpm_proc_deal_style";
|
||||
/**
|
||||
* BPM 业务表单类型流程变量
|
||||
*/
|
||||
public static String BPM_FORM_TYPE = "BPM_FORM_TYPE";
|
||||
/**
|
||||
* BPM 业务表单类型 表单类型:1:Online表单,2:设计器表单,3:自定义开发
|
||||
*/
|
||||
public static String BPM_FORM_TYPE_1 = "1";
|
||||
public static String BPM_FORM_TYPE_2 = "2";
|
||||
public static String BPM_FORM_TYPE_3 = "3";
|
||||
|
||||
/**
|
||||
* BPM 流程对应的流程业务KEY
|
||||
*/
|
||||
public static String BPM_FORM_BUSINESSKEY = "BPM_FORM_BUSINESSKEY";
|
||||
/**
|
||||
* 会签【用户组常量】
|
||||
*/
|
||||
public static String ASSIGNEE_USER_ID_LIST = "assigneeUserIdList";
|
||||
/**
|
||||
* 流程追回状态
|
||||
*/
|
||||
public static String PROCESS_CALLBACKPROCESS_STATUS = "callBackProcess";
|
||||
/**
|
||||
* 流程作废状态
|
||||
*/
|
||||
public static String PROCESS_INVALIDPROCESS_STATUS = "invalidProcess";
|
||||
/**
|
||||
* 流程驳回状态
|
||||
*/
|
||||
public static String PROCESS_REJECTPROCESS_STATUS = "rejectProcess";
|
||||
|
||||
/**
|
||||
* BPM 节点对应的表单URL类型--pc电脑端 mobile移动端
|
||||
*/
|
||||
public static String SUFFIX_BPM_FORM_URL = "pc";
|
||||
public static String SUFFIX_BPM_FORM_URL_MOBILE = "mobile";
|
||||
|
||||
|
||||
/**
|
||||
* BPM_OP_TYPE[流程日志操作类型]
|
||||
* 普通任务:1/会签任务:2/驳回:3/作废:4/取回:5
|
||||
*/
|
||||
public static String BPM_OP_TYPE_1 = "1";//普通任务
|
||||
public static String BPM_OP_TYPE_2 = "2";//会签任务
|
||||
public static String BPM_OP_TYPE_3 = "3";//驳回
|
||||
public static String BPM_OP_TYPE_4 = "4";//作废
|
||||
public static String BPM_OP_TYPE_5 = "5";//取回
|
||||
|
||||
|
||||
/**
|
||||
* 定时任务,自动委派用户ID
|
||||
*/
|
||||
public static final String SYS_AGENT_JOB_OPUSER_ID = "System Job";
|
||||
|
||||
/**
|
||||
* 表单设计器,流程中间草稿表
|
||||
*/
|
||||
public static final String DESIGN_FORM_DRAFT_TABLE = "EXT_ACT_DESIGN_FLOW_DATA";
|
||||
|
||||
/**
|
||||
* 流程用户组类型
|
||||
* role 角色
|
||||
* depart 部门
|
||||
* position 职务
|
||||
*/
|
||||
public static final String ACTIVITI_GROUP_TYPE_DEP = "depart";
|
||||
public static final String ACTIVITI_GROUP_TYPE_ROLE = "role";
|
||||
public static final String ACTIVITI_GROUP_TYPE_POSITION = "position";
|
||||
|
||||
/**
|
||||
* 动态key
|
||||
*/
|
||||
public static final String DESIGN_FORM_DRAFT_TABLE_KEY = "NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=";
|
||||
|
||||
/**
|
||||
* 当前驳回节点key
|
||||
*/
|
||||
public static final String CURRENT_REJECT_NODE_KEY = "CURRENT_REJECT_NODE_KEY";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 并发运行方式(默认并行)
|
||||
* 并行0、串行 1
|
||||
*/
|
||||
public static String RUN_CONCURRENT_MODE_PARALLEL = "0";
|
||||
public static String RUN_CONCURRENT_MODE_SERIAL = "1";
|
||||
|
||||
/**
|
||||
* 子流程中的节点 需要添加一个标识
|
||||
*/
|
||||
public static String SUB_EVENT = "subEvent_";
|
||||
|
||||
/**
|
||||
* 流程信号启动类型:按钮触发
|
||||
*/
|
||||
public static String START_BUTTON_EVENT = "buttonEvent";
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user