Merge branch 'main' of http://yykjgit.sdyyst.com/r/school-ai
| | |
| | | <artifactId>ruoyi-chat</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>sc-services</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>sc-page-designer</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-knowledge-api</artifactId> |
| | |
| | | |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>sc-services</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>sc-page-designer</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-generator</artifactId> |
| | | </dependency> |
| | | |
| | |
| | | # è
¾è®¯äº sms.tencentcloudapi.com |
| | | endpoint: "dysmsapi.aliyuncs.com" |
| | | accessKeyId: xxxxxxx |
| | | accessKeySecret: xxxxxx |
| | | accessKeySecret: xxxxxxq |
| | | signName: æµè¯ |
| | | # è
¾è®¯ä¸ç¨ |
| | | sdkAppId: |
| | | # =============================== |
| | | # Flowable é
ç½®ï¼éæ Flowable æ¶å¯ç¨ï¼ |
| | | # =============================== |
| | | flowable: |
| | | database-schema-update: true # 馿¬¡è¿è¡å»ºè®®ä¸º trueï¼åæè®¾ä¸º false |
| | | async-executor-activate: false |
| | | id-generator: simple |
| | | |
| | | |
| | |
| | | url: http://127.0.0.1:8081 |
| | | stdio: |
| | | servers-configuration: classpath:mcp-server.json |
| | | request-timeout: 300s |
| | | |
| | | request-timeout: 300s |
| | |
| | | package org.ruoyi.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("chat_session") |
| | | @TableName("CHAT_SESSION") |
| | | public class ChatSession extends BaseEntity { |
| | | |
| | | @Serial |
| | |
| | | /** |
| | | * ä¸»é® |
| | | */ |
| | | @TableId(value = "id") |
| | | @TableId(value = "ID") |
| | | private Long id; |
| | | |
| | | /** |
| | | * ç¨æ·id |
| | | * ç¨æ·ID |
| | | */ |
| | | @TableField("USER_ID") |
| | | private Long userId; |
| | | |
| | | /** |
| | | * ä¼è¯æ é¢ |
| | | */ |
| | | @TableField("SESSION_TITLE") |
| | | private String sessionTitle; |
| | | |
| | | /** |
| | | * ä¼è¯å
容 |
| | | */ |
| | | @TableField("SESSION_CONTENT") |
| | | private String sessionContent; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | @TableField("REMARK") |
| | | private String remark; |
| | | |
| | | |
| | | } |
| | |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("knowledge_info") |
| | | @TableName("KNOWLEDGE_INFO") |
| | | public class KnowledgeInfo extends BaseEntity { |
| | | |
| | | @Serial |
| | |
| | | * 主é®ID |
| | | */ |
| | | @TableId(value = "ID") |
| | | @TableField("ID") |
| | | private Long id; |
| | | |
| | | /** |
| | |
| | | * |
| | | */ |
| | | void updateXcxUser(SysUserBo user); |
| | | |
| | | List<SysUser> selectUserByRoleIds(List<Long> groups); |
| | | |
| | | List<SysUser> selectUserByDeptIds(List<Long> groups); |
| | | } |
| | |
| | | package org.ruoyi.system.service; |
| | | |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.system.domain.SysUser; |
| | |
| | | */ |
| | | int deleteUserByIds(Long[] userIds); |
| | | |
| | | R<List<SysUser>> selectUserByRoleIds(List<Long> groups); |
| | | |
| | | R<List<SysUser>> selectUserByDeptIds(List<Long> groups); |
| | | } |
| | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.ruoyi.common.core.constant.CacheNames; |
| | | import org.ruoyi.common.core.constant.UserConstants; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.exception.ServiceException; |
| | | import org.ruoyi.common.core.service.UserService; |
| | | import org.ruoyi.common.core.utils.MapstructUtils; |
| | |
| | | .eq(SysUser::getUserName, userName)); |
| | | return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserBalance().toString(); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®è§è²ç»æ¥è¯¢ç¨æ· |
| | | */ |
| | | @Override |
| | | public R<List<SysUser>> selectUserByRoleIds(List<Long> groups) { |
| | | List<SysUser> list = baseMapper.selectUserByRoleIds(groups); |
| | | return R.ok(list); |
| | | } |
| | | |
| | | @Override |
| | | public R<List<SysUser>> selectUserByDeptIds(List<Long> groups) { |
| | | List<SysUser> list = baseMapper.selectUserByDeptIds(groups); |
| | | return R.ok(list); |
| | | } |
| | | } |
| | |
| | | <include refid="selectUserVo"/> |
| | | where u.del_flag = '0' and u.user_id = #{userId} |
| | | </select> |
| | | <select id="selectUserByRoleIds" resultMap="SysUserResult"> |
| | | <include refid="selectUserVo"/> |
| | | where u.del_flag = '0' and r.role_id in <foreach item="item" collection="list" separator="," open="(" close=")" index=""> |
| | | #{item} |
| | | </foreach> |
| | | </select> |
| | | <select id="selectUserByDeptIds" resultMap="SysUserResult"> |
| | | <include refid="selectUserVo"/> |
| | | where u.del_flag = '0' and u.dept_id in <foreach item="item" collection="list" separator="," open="(" close=")" index=""> |
| | | #{item} |
| | | </foreach> |
| | | </select> |
| | | |
| | | |
| | | </mapper> |
| | |
| | | <module>ruoyi-chat</module> |
| | | <module>ruoyi-system</module> |
| | | <module>ruoyi-generator</module> |
| | | <module>ruoyi-flowable</module> |
| | | <module>sc-services</module> |
| | | <module>sc-page-designer</module> |
| | | </modules> |
| | | |
| | | <properties> |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void removeKnowledge(String id) { |
| | | Map<String,Object> map = new HashMap<>(); |
| | | KnowledgeInfo knowledgeInfo = baseMapper.selectById(id); |
| | | KnowledgeInfo knowledgeInfo = baseMapper.selectOne(new LambdaQueryWrapper<KnowledgeInfo>() |
| | | .eq(KnowledgeInfo::getKid, id)); |
| | | check(knowledgeInfo); |
| | | map.put("kid",knowledgeInfo.getKid()); |
| | | // å é¤åéæ°æ® |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-modules</artifactId> |
| | | <version>${revision}</version> |
| | | <relativePath>../pom.xml</relativePath> |
| | | </parent> |
| | | |
| | | <artifactId>ruoyi-flowable</artifactId> |
| | | |
| | | <properties> |
| | | <maven.compiler.source>17</maven.compiler.source> |
| | | <maven.compiler.target>17</maven.compiler.target> |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <flowable.version>6.8.0</flowable.version> |
| | | </properties> |
| | | |
| | | <dependencies> |
| | | <!-- Flowable 工使µ --> |
| | | <dependency> |
| | | <groupId>org.flowable</groupId> |
| | | <artifactId>flowable-spring-boot-starter-process</artifactId> |
| | | <version>${flowable.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- Spring Boot Web --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-web</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- Lombok --> |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.googlecode.aviator</groupId> |
| | | <artifactId>aviator</artifactId> |
| | | <version>5.3.1</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-system-api</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.nimbusds</groupId> |
| | | <artifactId>oauth2-oidc-sdk</artifactId> |
| | | <version>11.10.1</version> |
| | | <scope>compile</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.common.constant; |
| | | |
| | | /** |
| | | * æµç¨å¸¸éä¿¡æ¯ |
| | | * |
| | | * @author Xuan xuan |
| | | * @date 2021/4/17 22:46 |
| | | */ |
| | | public class ProcessConstants { |
| | | |
| | | public static final String SUFFIX = ".bpmn"; |
| | | |
| | | /** |
| | | * å¨ææ°æ® |
| | | */ |
| | | public static final String DATA_TYPE = "dynamic"; |
| | | |
| | | /** |
| | | * å个审æ¹äºº |
| | | */ |
| | | public static final String USER_TYPE_ASSIGNEE = "assignee"; |
| | | |
| | | |
| | | /** |
| | | * åé人 |
| | | */ |
| | | public static final String USER_TYPE_USERS = "candidateUsers"; |
| | | |
| | | |
| | | /** |
| | | * 审æ¹ç» |
| | | */ |
| | | public static final String USER_TYPE_ROUPS = "candidateGroups"; |
| | | |
| | | /** |
| | | * å个审æ¹äºº |
| | | */ |
| | | public static final String PROCESS_APPROVAL = "approval"; |
| | | |
| | | /** |
| | | * ä¼ç¾äººå |
| | | */ |
| | | public static final String PROCESS_MULTI_INSTANCE_USER = "userList"; |
| | | |
| | | /** |
| | | * nameapace |
| | | */ |
| | | public static final String NAMASPASE = "http://flowable.org/bpmn"; |
| | | |
| | | /** |
| | | * ä¼ç¾èç¹ |
| | | */ |
| | | public static final String PROCESS_MULTI_INSTANCE = "multiInstance"; |
| | | |
| | | /** |
| | | * èªå®ä¹å±æ§ dataType |
| | | */ |
| | | public static final String PROCESS_CUSTOM_DATA_TYPE = "dataType"; |
| | | |
| | | /** |
| | | * èªå®ä¹å±æ§ userType |
| | | */ |
| | | public static final String PROCESS_CUSTOM_USER_TYPE = "userType"; |
| | | |
| | | /** |
| | | * èªå®ä¹å±æ§ localScope |
| | | */ |
| | | public static final String PROCESS_FORM_LOCAL_SCOPE = "localScope"; |
| | | |
| | | /** |
| | | * èªå®ä¹å±æ§ æµç¨ç¶æ |
| | | */ |
| | | public static final String PROCESS_STATUS_KEY = "processStatus"; |
| | | |
| | | |
| | | /** |
| | | * æµç¨è·³è¿ |
| | | */ |
| | | public static final String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED"; |
| | | |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.common.constant; |
| | | |
| | | /** |
| | | * @author konbai |
| | | * @createTime 2022/4/24 13:24 |
| | | */ |
| | | public class TaskConstants { |
| | | |
| | | /** |
| | | * æµç¨å起人 |
| | | */ |
| | | public static final String PROCESS_INITIATOR = "initiator"; |
| | | |
| | | /** |
| | | * è§è²åéç»åç¼ |
| | | */ |
| | | public static final String ROLE_GROUP_PREFIX = "ROLE"; |
| | | |
| | | /** |
| | | * é¨é¨åéç»åç¼ |
| | | */ |
| | | public static final String DEPT_GROUP_PREFIX = "DEPT"; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.common.enums; |
| | | |
| | | /** |
| | | * æµç¨æè§ç±»å |
| | | * |
| | | * @author Xuan xuan |
| | | * @date 2021/4/19 |
| | | */ |
| | | public enum FlowComment { |
| | | |
| | | /** |
| | | * 说æ |
| | | */ |
| | | NORMAL("1", "æ£å¸¸"), |
| | | REBACK("2", "éå"), |
| | | REJECT("3", "驳å"), |
| | | DELEGATE("4", "å§æ´¾"), |
| | | TRANSFER("5", "转å"), |
| | | STOP("6", "ç»æ¢"), |
| | | REVOKE("7", "æ¤å"); |
| | | |
| | | /** |
| | | * ç±»å |
| | | */ |
| | | private final String type; |
| | | |
| | | /** |
| | | * 说æ |
| | | */ |
| | | private final String remark; |
| | | |
| | | FlowComment(String type, String remark) { |
| | | this.type = type; |
| | | this.remark = remark; |
| | | } |
| | | |
| | | public String getType() { |
| | | return type; |
| | | } |
| | | |
| | | public String getRemark() { |
| | | return remark; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.common.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/6/28 9:51 |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum FormType { |
| | | |
| | | /** |
| | | * æµç¨è¡¨å |
| | | */ |
| | | PROCESS(0), |
| | | |
| | | /** |
| | | * å¤ç½®è¡¨å |
| | | */ |
| | | EXTERNAL(1), |
| | | |
| | | /** |
| | | * èç¹ç¬ç«è¡¨å |
| | | */ |
| | | INDEPENDENT(2); |
| | | |
| | | /** |
| | | * 表åç±»å |
| | | */ |
| | | private final Integer type; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.common.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | |
| | | /** |
| | | * @author konbai |
| | | * @since 2023/3/9 00:45 |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum ProcessStatus { |
| | | |
| | | /** |
| | | * è¿è¡ä¸ï¼å®¡æ¹ä¸ï¼ |
| | | */ |
| | | RUNNING("running"), |
| | | /** |
| | | * å·²ç»æ¢ |
| | | */ |
| | | TERMINATED("terminated"), |
| | | /** |
| | | * 已宿 |
| | | */ |
| | | COMPLETED("completed"), |
| | | /** |
| | | * 已忶 |
| | | */ |
| | | CANCELED("canceled"); |
| | | |
| | | private final String status; |
| | | |
| | | public static ProcessStatus getProcessStatus(String str) { |
| | | if (StringUtils.isNotBlank(str)) { |
| | | for (ProcessStatus value : values()) { |
| | | if (StringUtils.equalsIgnoreCase(str, value.getStatus())) { |
| | | return value; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.config; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType; |
| | | import org.flowable.engine.RuntimeService; |
| | | import org.ruoyi.flowable.listener.GlobalEventListener; |
| | | import org.springframework.context.ApplicationListener; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.context.event.ContextRefreshedEvent; |
| | | |
| | | /** |
| | | * flowableå
¨å±çå¬é
ç½® |
| | | * |
| | | * @author ssc |
| | | */ |
| | | @Configuration |
| | | @AllArgsConstructor |
| | | public class GlobalEventListenerConfig implements ApplicationListener<ContextRefreshedEvent> { |
| | | |
| | | private final GlobalEventListener globalEventListener; |
| | | private final RuntimeService runtimeService; |
| | | |
| | | @Override |
| | | public void onApplicationEvent(ContextRefreshedEvent event) { |
| | | // æµç¨æ£å¸¸ç»æ |
| | | runtimeService.addEventListener(globalEventListener, FlowableEngineEventType.PROCESS_COMPLETED); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.config; |
| | | |
| | | import org.flowable.bpmn.model.AssociationDirection; |
| | | import org.flowable.image.impl.DefaultProcessDiagramCanvas; |
| | | |
| | | import java.awt.*; |
| | | import java.awt.geom.Line2D; |
| | | import java.awt.geom.RoundRectangle2D; |
| | | |
| | | /** |
| | | * @author XuanXuan |
| | | * @date 2021-04-03 |
| | | */ |
| | | public class MyDefaultProcessDiagramCanvas extends DefaultProcessDiagramCanvas { |
| | | //设置é«äº®çº¿çé¢è² è¿éæè®¾ç½®æç»¿è² |
| | | protected static Color HIGHLIGHT_SEQUENCEFLOW_COLOR = Color.GREEN; |
| | | |
| | | public MyDefaultProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { |
| | | super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); |
| | | } |
| | | |
| | | public MyDefaultProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType) { |
| | | super(width, height, minX, minY, imageType); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * ç»çº¿é¢è²è®¾ç½® |
| | | */ |
| | | @Override |
| | | public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType, |
| | | AssociationDirection associationDirection, boolean highLighted, double scaleFactor) { |
| | | |
| | | Paint originalPaint = g.getPaint(); |
| | | Stroke originalStroke = g.getStroke(); |
| | | |
| | | g.setPaint(CONNECTION_COLOR); |
| | | if (connectionType.equals("association")) { |
| | | g.setStroke(ASSOCIATION_STROKE); |
| | | } else if (highLighted) { |
| | | //设置线çé¢è² |
| | | g.setPaint(originalPaint); |
| | | g.setStroke(HIGHLIGHT_FLOW_STROKE); |
| | | } |
| | | |
| | | for (int i = 1; i < xPoints.length; i++) { |
| | | Integer sourceX = xPoints[i - 1]; |
| | | Integer sourceY = yPoints[i - 1]; |
| | | Integer targetX = xPoints[i]; |
| | | Integer targetY = yPoints[i]; |
| | | Line2D.Double line = new Line2D.Double(sourceX, sourceY, targetX, targetY); |
| | | g.draw(line); |
| | | } |
| | | |
| | | if (isDefault) { |
| | | Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]); |
| | | drawDefaultSequenceFlowIndicator(line, scaleFactor); |
| | | } |
| | | |
| | | if (conditional) { |
| | | Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]); |
| | | drawConditionalSequenceFlowIndicator(line, scaleFactor); |
| | | } |
| | | |
| | | if (associationDirection == AssociationDirection.ONE || associationDirection == AssociationDirection.BOTH) { |
| | | Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2], yPoints[xPoints.length - 2], xPoints[xPoints.length - 1], yPoints[xPoints.length - 1]); |
| | | drawArrowHead(line, scaleFactor); |
| | | } |
| | | if (associationDirection == AssociationDirection.BOTH) { |
| | | Line2D.Double line = new Line2D.Double(xPoints[1], yPoints[1], xPoints[0], yPoints[0]); |
| | | drawArrowHead(line, scaleFactor); |
| | | } |
| | | g.setPaint(originalPaint); |
| | | g.setStroke(originalStroke); |
| | | } |
| | | |
| | | /** |
| | | * é«äº®èç¹è®¾ç½® |
| | | */ |
| | | @Override |
| | | public void drawHighLight(int x, int y, int width, int height) { |
| | | Paint originalPaint = g.getPaint(); |
| | | Stroke originalStroke = g.getStroke(); |
| | | //设置é«äº®èç¹çé¢è² |
| | | g.setPaint(HIGHLIGHT_COLOR); |
| | | g.setStroke(THICK_TASK_BORDER_STROKE); |
| | | |
| | | RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); |
| | | g.draw(rect); |
| | | |
| | | g.setPaint(originalPaint); |
| | | g.setStroke(originalStroke); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.config; |
| | | |
| | | import cn.hutool.core.net.NetUtil; |
| | | import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator; |
| | | import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; |
| | | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
| | | import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; |
| | | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.transaction.annotation.EnableTransactionManagement; |
| | | |
| | | /** |
| | | * mybatis-plusé
置类(䏿¹æ³¨éææä»¶ä»ç») |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @EnableTransactionManagement(proxyTargetClass = true) |
| | | @Configuration |
| | | public class MybatisPlusConfig { |
| | | |
| | | @Bean |
| | | public MybatisPlusInterceptor mybatisPlusInterceptor() { |
| | | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); |
| | | // å页æä»¶ |
| | | interceptor.addInnerInterceptor(paginationInnerInterceptor()); |
| | | // ä¹è§éæä»¶ |
| | | interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor()); |
| | | return interceptor; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å页æä»¶ï¼èªå¨è¯å«æ°æ®åºç±»å |
| | | */ |
| | | public PaginationInnerInterceptor paginationInnerInterceptor() { |
| | | PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); |
| | | // 设置æå¤§å页éå¶æ°éï¼é»è®¤ 500 æ¡ï¼-1 ä¸åéå¶ |
| | | paginationInnerInterceptor.setMaxLimit(-1L); |
| | | // å页åçå |
| | | paginationInnerInterceptor.setOverflow(true); |
| | | return paginationInnerInterceptor; |
| | | } |
| | | |
| | | /** |
| | | * ä¹è§éæä»¶ |
| | | */ |
| | | public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() { |
| | | return new OptimisticLockerInnerInterceptor(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 使ç¨ç½å¡ä¿¡æ¯ç»å®éªè±çæå¨ |
| | | * 鲿¢é群éªè±IDéå¤ |
| | | */ |
| | | @Bean |
| | | public IdentifierGenerator idGenerator() { |
| | | return new DefaultIdentifierGenerator(NetUtil.getLocalhost()); |
| | | } |
| | | |
| | | /** |
| | | * PaginationInnerInterceptor å页æä»¶ï¼èªå¨è¯å«æ°æ®åºç±»å |
| | | * https://baomidou.com/pages/97710a/ |
| | | * OptimisticLockerInnerInterceptor ä¹è§éæä»¶ |
| | | * https://baomidou.com/pages/0d93c0/ |
| | | * MetaObjectHandler å
å¯¹è±¡åæ®µå¡«å
æ§å¶å¨ |
| | | * https://baomidou.com/pages/4c6bcf/ |
| | | * ISqlInjector sql注å
¥å¨ |
| | | * https://baomidou.com/pages/42ea4a/ |
| | | * BlockAttackInnerInterceptor 妿æ¯å¯¹å
¨è¡¨çå é¤ææ´æ°æä½ï¼å°±ä¼ç»æ¢è¯¥æä½ |
| | | * https://baomidou.com/pages/f9a237/ |
| | | * IllegalSQLInnerInterceptor sqlæ§è½è§èæä»¶(åå¾SQLæ¦æª) |
| | | * IdentifierGenerator èªå®ä¹ä¸»é®çç¥ |
| | | * https://baomidou.com/pages/568eb2/ |
| | | * TenantLineInnerInterceptor å¤ç§æ·æä»¶ |
| | | * https://baomidou.com/pages/aef2f2/ |
| | | * DynamicTableNameInnerInterceptor å¨æè¡¨åæä»¶ |
| | | * https://baomidou.com/pages/2a45ff/ |
| | | */ |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.core; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 表å屿§ç±» |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/8/6 18:54 |
| | | */ |
| | | @Data |
| | | public class FormConf { |
| | | |
| | | /** |
| | | * æ é¢ |
| | | */ |
| | | private String title; |
| | | /** |
| | | * 表åå |
| | | */ |
| | | private String formRef; |
| | | /** |
| | | * è¡¨åæ¨¡å |
| | | */ |
| | | private Map<String, Object> formModel; |
| | | /** |
| | | * 表å尺寸 |
| | | */ |
| | | private String size; |
| | | /** |
| | | * æ ç¾å¯¹é½ |
| | | */ |
| | | private String labelPosition; |
| | | /** |
| | | * æ ç¾å®½åº¦ |
| | | */ |
| | | private Integer labelWidth; |
| | | /** |
| | | * æ ¡éªæ¨¡å |
| | | */ |
| | | private String formRules; |
| | | /** |
| | | * æ
æ ¼é´é |
| | | */ |
| | | private Integer gutter; |
| | | /** |
| | | * ç¦ç¨è¡¨å |
| | | */ |
| | | private Boolean disabled = false; |
| | | /** |
| | | * æ
æ ¼å æ®çåæ° |
| | | */ |
| | | private Integer span; |
| | | /** |
| | | * 表åæé® |
| | | */ |
| | | private Boolean formBtns = true; |
| | | /** |
| | | * 表å项 |
| | | */ |
| | | private List<Map<String, Object>> fields; |
| | | /** |
| | | * è¡¨åæ°æ® |
| | | */ |
| | | private Map<String, Object> formData; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.core.domain; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æµç¨æ¥è¯¢å®ä½å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/6/11 01:15 |
| | | */ |
| | | @Data |
| | | public class ProcessQuery { |
| | | |
| | | /** |
| | | * æµç¨æ è¯ |
| | | */ |
| | | private String processKey; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | private String processName; |
| | | |
| | | /** |
| | | * æµç¨åç±» |
| | | */ |
| | | private String category; |
| | | |
| | | /** |
| | | * ç¶æ |
| | | */ |
| | | private String state; |
| | | |
| | | /** |
| | | * 请æ±åæ° |
| | | */ |
| | | private Map<String, Object> params = new HashMap<>(); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.core.domain.model; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.metadata.OrderItem; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import lombok.Data; |
| | | import org.ruoyi.common.core.exception.ServiceException; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.common.core.utils.sql.SqlUtil; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å页æ¥è¯¢å®ä½ç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | public class PageQuery implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * åé¡µå¤§å° |
| | | */ |
| | | private Integer pageSize; |
| | | |
| | | /** |
| | | * å½åé¡µæ° |
| | | */ |
| | | private Integer pageNum; |
| | | |
| | | /** |
| | | * æåºå |
| | | */ |
| | | private String orderByColumn; |
| | | |
| | | /** |
| | | * æåºçæ¹ådescæè
asc |
| | | */ |
| | | private String isAsc; |
| | | |
| | | /** |
| | | * å½åè®°å½èµ·å§ç´¢å¼ é»è®¤å¼ |
| | | */ |
| | | public static final int DEFAULT_PAGE_NUM = 1; |
| | | |
| | | /** |
| | | * æ¯é¡µæ¾ç¤ºè®°å½æ° é»è®¤å¼ é»è®¤æ¥å
¨é¨ |
| | | */ |
| | | public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE; |
| | | |
| | | public <T> Page<T> build() { |
| | | Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM); |
| | | Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE); |
| | | if (pageNum <= 0) { |
| | | pageNum = DEFAULT_PAGE_NUM; |
| | | } |
| | | Page<T> page = new Page<>(pageNum, pageSize); |
| | | List<OrderItem> orderItems = buildOrderItem(); |
| | | if (CollUtil.isNotEmpty(orderItems)) { |
| | | page.addOrder(orderItems); |
| | | } |
| | | return page; |
| | | } |
| | | |
| | | /** |
| | | * æå»ºæåº |
| | | * |
| | | * æ¯æçç¨æ³å¦ä¸: |
| | | * {isAsc:"asc",orderByColumn:"id"} order by id asc |
| | | * {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc |
| | | * {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc |
| | | * {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc |
| | | */ |
| | | private List<OrderItem> buildOrderItem() { |
| | | if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) { |
| | | return null; |
| | | } |
| | | String orderBy = SqlUtil.escapeOrderBySql(orderByColumn); |
| | | orderBy = StringUtils.toUnderScoreCase(orderBy); |
| | | |
| | | // å
¼å®¹å端æåºç±»å |
| | | isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"}); |
| | | |
| | | String[] orderByArr = orderBy.split(","); |
| | | String[] isAscArr = isAsc.split(","); |
| | | if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) { |
| | | throw new ServiceException("æåºåæ°æè¯¯"); |
| | | } |
| | | |
| | | List<OrderItem> list = new ArrayList<>(); |
| | | // æ¯ä¸ªå段åèªæåº |
| | | for (int i = 0; i < orderByArr.length; i++) { |
| | | String orderByStr = orderByArr[i]; |
| | | String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i]; |
| | | if ("asc".equals(isAscStr)) { |
| | | list.add(OrderItem.asc(orderByStr)); |
| | | } else if ("desc".equals(isAscStr)) { |
| | | list.add(OrderItem.desc(orderByStr)); |
| | | } else { |
| | | throw new ServiceException("æåºåæ°æè¯¯"); |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.core.mapper; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.toolkit.Db; |
| | | import org.apache.ibatis.logging.Log; |
| | | import org.apache.ibatis.logging.LogFactory; |
| | | import org.ruoyi.flowable.utils.BeanCopyUtils; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * èªå®ä¹ Mapper æ¥å£, å®ç° èªå®ä¹æ©å± |
| | | * |
| | | * @param <M> mapper æ³å |
| | | * @param <T> table æ³å |
| | | * @param <V> vo æ³å |
| | | * @author Lion Li |
| | | * @since 2021-05-13 |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> { |
| | | |
| | | Log log = LogFactory.getLog(BaseMapperPlus.class); |
| | | |
| | | default Class<V> currentVoClass() { |
| | | return (Class<V>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2); |
| | | } |
| | | |
| | | default Class<T> currentModelClass() { |
| | | return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 1); |
| | | } |
| | | |
| | | default Class<M> currentMapperClass() { |
| | | return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 0); |
| | | } |
| | | |
| | | default List<T> selectList() { |
| | | return this.selectList(new QueryWrapper<>()); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæå
¥ |
| | | */ |
| | | default boolean insertBatch(Collection<T> entityList) { |
| | | return Db.saveBatch(entityList); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæ´æ° |
| | | */ |
| | | default boolean updateBatchById(Collection<T> entityList) { |
| | | return Db.updateBatchById(entityList); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæå
¥ææ´æ° |
| | | */ |
| | | default boolean insertOrUpdateBatch(Collection<T> entityList) { |
| | | return Db.saveOrUpdateBatch(entityList); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæå
¥(å
å«éå¶æ¡æ°) |
| | | */ |
| | | default boolean insertBatch(Collection<T> entityList, int batchSize) { |
| | | return Db.saveBatch(entityList, batchSize); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæ´æ°(å
å«éå¶æ¡æ°) |
| | | */ |
| | | default boolean updateBatchById(Collection<T> entityList, int batchSize) { |
| | | return Db.updateBatchById(entityList, batchSize); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæå
¥ææ´æ°(å
å«éå¶æ¡æ°) |
| | | */ |
| | | default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) { |
| | | return Db.saveOrUpdateBatch(entityList, batchSize); |
| | | } |
| | | |
| | | /** |
| | | * æå
¥ææ´æ°(å
å«éå¶æ¡æ°) |
| | | */ |
| | | default boolean insertOrUpdate(T entity) { |
| | | return Db.saveOrUpdate(entity); |
| | | } |
| | | |
| | | default V selectVoById(Serializable id) { |
| | | return selectVoById(id, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ® ID æ¥è¯¢ |
| | | */ |
| | | default <C> C selectVoById(Serializable id, Class<C> voClass) { |
| | | T obj = this.selectById(id); |
| | | if (ObjectUtil.isNull(obj)) { |
| | | return null; |
| | | } |
| | | return BeanCopyUtils.copy(obj, voClass); |
| | | } |
| | | |
| | | default List<V> selectVoBatchIds(Collection<? extends Serializable> idList) { |
| | | return selectVoBatchIds(idList, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢ï¼æ ¹æ®ID æ¹éæ¥è¯¢ï¼ |
| | | */ |
| | | default <C> List<C> selectVoBatchIds(Collection<? extends Serializable> idList, Class<C> voClass) { |
| | | List<T> list = this.selectBatchIds(idList); |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return BeanCopyUtils.copyList(list, voClass); |
| | | } |
| | | |
| | | default List<V> selectVoByMap(Map<String, Object> map) { |
| | | return selectVoByMap(map, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢ï¼æ ¹æ® columnMap æ¡ä»¶ï¼ |
| | | */ |
| | | default <C> List<C> selectVoByMap(Map<String, Object> map, Class<C> voClass) { |
| | | List<T> list = this.selectByMap(map); |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return BeanCopyUtils.copyList(list, voClass); |
| | | } |
| | | |
| | | default V selectVoOne(Wrapper<T> wrapper) { |
| | | return selectVoOne(wrapper, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ® entity æ¡ä»¶ï¼æ¥è¯¢ä¸æ¡è®°å½ |
| | | */ |
| | | default <C> C selectVoOne(Wrapper<T> wrapper, Class<C> voClass) { |
| | | T obj = this.selectOne(wrapper); |
| | | if (ObjectUtil.isNull(obj)) { |
| | | return null; |
| | | } |
| | | return BeanCopyUtils.copy(obj, voClass); |
| | | } |
| | | |
| | | default List<V> selectVoList(Wrapper<T> wrapper) { |
| | | return selectVoList(wrapper, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ® entity æ¡ä»¶ï¼æ¥è¯¢å
¨é¨è®°å½ |
| | | */ |
| | | default <C> List<C> selectVoList(Wrapper<T> wrapper, Class<C> voClass) { |
| | | List<T> list = this.selectList(wrapper); |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return BeanCopyUtils.copyList(list, voClass); |
| | | } |
| | | |
| | | default <P extends IPage<V>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper) { |
| | | return selectVoPage(page, wrapper, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * å页æ¥è¯¢VO |
| | | */ |
| | | default <C, P extends IPage<C>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper, Class<C> voClass) { |
| | | IPage<T> pageData = this.selectPage(page, wrapper); |
| | | IPage<C> voPage = new Page<>(pageData.getCurrent(), pageData.getSize(), pageData.getTotal()); |
| | | if (CollUtil.isEmpty(pageData.getRecords())) { |
| | | return (P) voPage; |
| | | } |
| | | voPage.setRecords(BeanCopyUtils.copyList(pageData.getRecords(), voClass)); |
| | | return (P) voPage; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.core.page; |
| | | |
| | | import cn.hutool.http.HttpStatus; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * è¡¨æ ¼åé¡µæ°æ®å¯¹è±¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class TableDataInfo<T> implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æ»è®°å½æ° |
| | | */ |
| | | private long total; |
| | | |
| | | /** |
| | | * åè¡¨æ°æ® |
| | | */ |
| | | private List<T> rows; |
| | | |
| | | /** |
| | | * æ¶æ¯ç¶æç |
| | | */ |
| | | private int code; |
| | | |
| | | /** |
| | | * æ¶æ¯å
容 |
| | | */ |
| | | private String msg; |
| | | |
| | | /** |
| | | * å页 |
| | | * |
| | | * @param list åè¡¨æ°æ® |
| | | * @param total æ»è®°å½æ° |
| | | */ |
| | | public TableDataInfo(List<T> list, long total) { |
| | | this.rows = list; |
| | | this.total = total; |
| | | } |
| | | |
| | | public static <T> TableDataInfo<T> build(IPage<T> page) { |
| | | TableDataInfo<T> rspData = new TableDataInfo<>(); |
| | | rspData.setCode(HttpStatus.HTTP_OK); |
| | | rspData.setMsg("æ¥è¯¢æå"); |
| | | rspData.setRows(page.getRecords()); |
| | | rspData.setTotal(page.getTotal()); |
| | | return rspData; |
| | | } |
| | | |
| | | public static <T> TableDataInfo<T> build(List<T> list) { |
| | | TableDataInfo<T> rspData = new TableDataInfo<>(); |
| | | rspData.setCode(HttpStatus.HTTP_OK); |
| | | rspData.setMsg("æ¥è¯¢æå"); |
| | | rspData.setRows(list); |
| | | rspData.setTotal(list.size()); |
| | | return rspData; |
| | | } |
| | | |
| | | public static <T> TableDataInfo<T> build() { |
| | | TableDataInfo<T> rspData = new TableDataInfo<>(); |
| | | rspData.setCode(HttpStatus.HTTP_OK); |
| | | rspData.setMsg("æ¥è¯¢æå"); |
| | | return rspData; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.factory; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import lombok.Getter; |
| | | import org.flowable.engine.*; |
| | | import org.springframework.beans.factory.annotation.Qualifier; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | /** |
| | | * flowable å¼ææ³¨å
¥å°è£
|
| | | * @author XuanXuan |
| | | * @date 2021-04-03 |
| | | */ |
| | | @Component |
| | | @Getter |
| | | public class FlowServiceFactory { |
| | | |
| | | @Resource |
| | | protected RepositoryService repositoryService; |
| | | |
| | | @Resource |
| | | protected RuntimeService runtimeService; |
| | | |
| | | @Resource |
| | | protected IdentityService identityService; |
| | | |
| | | @Resource |
| | | protected TaskService taskService; |
| | | |
| | | @Resource |
| | | protected FormService formService; |
| | | |
| | | @Resource |
| | | protected HistoryService historyService; |
| | | |
| | | @Resource |
| | | protected ManagementService managementService; |
| | | |
| | | @Qualifier("processEngine") |
| | | @Resource |
| | | protected ProcessEngine processEngine; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.flow; |
| | | |
| | | import org.flowable.bpmn.model.AssociationDirection; |
| | | import org.flowable.bpmn.model.GraphicInfo; |
| | | import org.flowable.image.impl.DefaultProcessDiagramCanvas; |
| | | import org.flowable.image.util.ReflectUtil; |
| | | |
| | | import javax.imageio.ImageIO; |
| | | import java.awt.*; |
| | | import java.awt.font.FontRenderContext; |
| | | import java.awt.font.LineBreakMeasurer; |
| | | import java.awt.font.TextAttribute; |
| | | import java.awt.font.TextLayout; |
| | | import java.awt.geom.Ellipse2D; |
| | | import java.awt.geom.Rectangle2D; |
| | | import java.awt.geom.RoundRectangle2D; |
| | | import java.awt.image.BufferedImage; |
| | | import java.io.IOException; |
| | | import java.text.AttributedCharacterIterator; |
| | | import java.text.AttributedString; |
| | | |
| | | /** |
| | | * @author XuanXuan |
| | | * @date 2021/4/4 23:58 |
| | | */ |
| | | public class CustomProcessDiagramCanvas extends DefaultProcessDiagramCanvas { |
| | | //å®ä¹èµ°è¿æµç¨è¿çº¿é¢è²ä¸ºç»¿è² |
| | | protected static Color HIGHLIGHT_SequenceFlow_COLOR = Color.GREEN; |
| | | //设置æªèµ°è¿æµç¨çè¿æ¥çº¿é¢è² |
| | | protected static Color CONNECTION_COLOR = Color.BLACK; |
| | | //设置flowsè¿æ¥çº¿åä½é¢è²red |
| | | protected static Color LABEL_COLOR = new Color(0, 0, 0); |
| | | //é«äº®æ¾ç¤ºtaskæ¡é¢è² |
| | | protected static Color HIGHLIGHT_COLOR = Color.GREEN; |
| | | protected static Color HIGHLIGHT_COLOR1 = Color.RED; |
| | | |
| | | public CustomProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { |
| | | super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); |
| | | this.initialize(imageType); |
| | | } |
| | | |
| | | /** |
| | | * éåç»å¶è¿çº¿çæ¹å¼,设置ç»å¶é¢è² |
| | | * @param xPoints |
| | | * @param yPoints |
| | | * @param conditional |
| | | * @param isDefault |
| | | * @param connectionType |
| | | * @param associationDirection |
| | | * @param highLighted |
| | | * @param scaleFactor |
| | | */ |
| | | @Override |
| | | public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType, AssociationDirection associationDirection, boolean highLighted, double scaleFactor) { |
| | | Paint originalPaint = this.g.getPaint(); |
| | | Stroke originalStroke = this.g.getStroke(); |
| | | this.g.setPaint(CONNECTION_COLOR); |
| | | if (connectionType.equals("association")) { |
| | | this.g.setStroke(ASSOCIATION_STROKE); |
| | | } else if (highLighted) { |
| | | this.g.setPaint(HIGHLIGHT_SequenceFlow_COLOR); |
| | | this.g.setStroke(HIGHLIGHT_FLOW_STROKE); |
| | | } |
| | | |
| | | for (int i = 1; i < xPoints.length; ++i) { |
| | | int sourceX = xPoints[i - 1]; |
| | | int sourceY = yPoints[i - 1]; |
| | | int targetX = xPoints[i]; |
| | | int targetY = yPoints[i]; |
| | | java.awt.geom.Line2D.Double line = new java.awt.geom.Line2D.Double((double) sourceX, (double) sourceY, (double) targetX, (double) targetY); |
| | | this.g.draw(line); |
| | | } |
| | | |
| | | java.awt.geom.Line2D.Double line; |
| | | if (isDefault) { |
| | | line = new java.awt.geom.Line2D.Double((double) xPoints[0], (double) yPoints[0], (double) xPoints[1], (double) yPoints[1]); |
| | | this.drawDefaultSequenceFlowIndicator(line, scaleFactor); |
| | | } |
| | | |
| | | if (conditional) { |
| | | line = new java.awt.geom.Line2D.Double((double) xPoints[0], (double) yPoints[0], (double) xPoints[1], (double) yPoints[1]); |
| | | this.drawConditionalSequenceFlowIndicator(line, scaleFactor); |
| | | } |
| | | |
| | | if (associationDirection.equals(AssociationDirection.ONE) || associationDirection.equals(AssociationDirection.BOTH)) { |
| | | line = new java.awt.geom.Line2D.Double((double) xPoints[xPoints.length - 2], (double) yPoints[xPoints.length - 2], (double) xPoints[xPoints.length - 1], (double) yPoints[xPoints.length - 1]); |
| | | this.drawArrowHead(line, scaleFactor); |
| | | } |
| | | |
| | | if (associationDirection.equals(AssociationDirection.BOTH)) { |
| | | line = new java.awt.geom.Line2D.Double((double) xPoints[1], (double) yPoints[1], (double) xPoints[0], (double) yPoints[0]); |
| | | this.drawArrowHead(line, scaleFactor); |
| | | } |
| | | |
| | | this.g.setPaint(originalPaint); |
| | | this.g.setStroke(originalStroke); |
| | | } |
| | | |
| | | /** |
| | | * 设置åä½å¤§å°å¾æ é¢è² |
| | | * @param imageType |
| | | */ |
| | | @Override |
| | | public void initialize(String imageType) { |
| | | if ("png".equalsIgnoreCase(imageType)) { |
| | | this.processDiagram = new BufferedImage(this.canvasWidth, this.canvasHeight, 2); |
| | | } else { |
| | | this.processDiagram = new BufferedImage(this.canvasWidth, this.canvasHeight, 1); |
| | | } |
| | | |
| | | this.g = this.processDiagram.createGraphics(); |
| | | if (!"png".equalsIgnoreCase(imageType)) { |
| | | this.g.setBackground(new Color(255, 255, 255, 0)); |
| | | this.g.clearRect(0, 0, this.canvasWidth, this.canvasHeight); |
| | | } |
| | | |
| | | this.g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
| | | //ä¿®æ¹å¾æ é¢è²ï¼ä¿®æ¹å¾æ åä½å¤§å° |
| | | this.g.setPaint(Color.black); |
| | | Font font = new Font(this.activityFontName, 10, 14); |
| | | this.g.setFont(font); |
| | | this.fontMetrics = this.g.getFontMetrics(); |
| | | //ä¿®æ¹è¿æ¥çº¿åä½å¤§å° |
| | | LABEL_FONT = new Font(this.labelFontName, 10, 15); |
| | | ANNOTATION_FONT = new Font(this.annotationFontName, 0, 11); |
| | | |
| | | try { |
| | | USERTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/userTask.png", this.customClassLoader)); |
| | | SCRIPTTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/scriptTask.png", this.customClassLoader)); |
| | | SERVICETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/serviceTask.png", this.customClassLoader)); |
| | | RECEIVETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/receiveTask.png", this.customClassLoader)); |
| | | SENDTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/sendTask.png", this.customClassLoader)); |
| | | MANUALTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/manualTask.png", this.customClassLoader)); |
| | | BUSINESS_RULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/businessRuleTask.png", this.customClassLoader)); |
| | | SHELL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/shellTask.png", this.customClassLoader)); |
| | | DMN_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/dmnTask.png", this.customClassLoader)); |
| | | CAMEL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/camelTask.png", this.customClassLoader)); |
| | | MULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/muleTask.png", this.customClassLoader)); |
| | | HTTP_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/httpTask.png", this.customClassLoader)); |
| | | TIMER_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/timer.png", this.customClassLoader)); |
| | | COMPENSATE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/compensate-throw.png", this.customClassLoader)); |
| | | COMPENSATE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/compensate.png", this.customClassLoader)); |
| | | ERROR_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/error-throw.png", this.customClassLoader)); |
| | | ERROR_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/error.png", this.customClassLoader)); |
| | | MESSAGE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/message-throw.png", this.customClassLoader)); |
| | | MESSAGE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/message.png", this.customClassLoader)); |
| | | SIGNAL_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/signal-throw.png", this.customClassLoader)); |
| | | SIGNAL_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/signal.png", this.customClassLoader)); |
| | | } catch (IOException var4) { |
| | | LOGGER.warn("Could not load image for process diagram creation: {}", var4.getMessage()); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * è®¾ç½®è¿æ¥çº¿åä½ |
| | | * @param text |
| | | * @param graphicInfo |
| | | * @param centered |
| | | */ |
| | | @Override |
| | | public void drawLabel(String text, GraphicInfo graphicInfo, boolean centered) { |
| | | float interline = 1.0f; |
| | | |
| | | // text |
| | | if (text != null && text.length() > 0) { |
| | | Paint originalPaint = g.getPaint(); |
| | | Font originalFont = g.getFont(); |
| | | |
| | | g.setPaint(LABEL_COLOR); |
| | | g.setFont(LABEL_FONT); |
| | | |
| | | int wrapWidth = 100; |
| | | int textY = (int) graphicInfo.getY(); |
| | | |
| | | // TODO: use drawMultilineText() |
| | | AttributedString as = new AttributedString(text); |
| | | as.addAttribute(TextAttribute.FOREGROUND, g.getPaint()); |
| | | as.addAttribute(TextAttribute.FONT, g.getFont()); |
| | | AttributedCharacterIterator aci = as.getIterator(); |
| | | FontRenderContext frc = new FontRenderContext(null, true, false); |
| | | LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc); |
| | | |
| | | while (lbm.getPosition() < text.length()) { |
| | | TextLayout tl = lbm.nextLayout(wrapWidth); |
| | | textY += tl.getAscent(); |
| | | |
| | | Rectangle2D bb = tl.getBounds(); |
| | | double tX = graphicInfo.getX(); |
| | | |
| | | if (centered) { |
| | | tX += (int) (graphicInfo.getWidth() / 2 - bb.getWidth() / 2); |
| | | } |
| | | tl.draw(g, (float) tX, textY); |
| | | textY += tl.getDescent() + tl.getLeading() + (interline - 1.0f) * tl.getAscent(); |
| | | } |
| | | |
| | | // restore originals |
| | | g.setFont(originalFont); |
| | | g.setPaint(originalPaint); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * é«äº®æ¾ç¤ºtaskæ¡å®æç |
| | | * @param x |
| | | * @param y |
| | | * @param width |
| | | * @param height |
| | | */ |
| | | @Override |
| | | public void drawHighLight(int x, int y, int width, int height) { |
| | | Paint originalPaint = g.getPaint(); |
| | | Stroke originalStroke = g.getStroke(); |
| | | |
| | | g.setPaint(HIGHLIGHT_COLOR); |
| | | g.setStroke(THICK_TASK_BORDER_STROKE); |
| | | |
| | | RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); |
| | | g.draw(rect); |
| | | |
| | | g.setPaint(originalPaint); |
| | | g.setStroke(originalStroke); |
| | | } |
| | | |
| | | /** |
| | | * èªå®ä¹taskæ¡å½åçä½ç½® |
| | | * @param x |
| | | * @param y |
| | | * @param width |
| | | * @param height |
| | | */ |
| | | public void drawHighLightNow(int x, int y, int width, int height) { |
| | | Paint originalPaint = g.getPaint(); |
| | | Stroke originalStroke = g.getStroke(); |
| | | |
| | | g.setPaint(HIGHLIGHT_COLOR1); |
| | | g.setStroke(THICK_TASK_BORDER_STROKE); |
| | | |
| | | RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); |
| | | g.draw(rect); |
| | | |
| | | g.setPaint(originalPaint); |
| | | g.setStroke(originalStroke); |
| | | } |
| | | |
| | | /** |
| | | * èªå®ä¹ç»æèç¹ |
| | | * @param x |
| | | * @param y |
| | | * @param width |
| | | * @param height |
| | | */ |
| | | public void drawHighLightEnd(int x, int y, int width, int height) { |
| | | Paint originalPaint = g.getPaint(); |
| | | Stroke originalStroke = g.getStroke(); |
| | | |
| | | g.setPaint(HIGHLIGHT_COLOR); |
| | | g.setStroke(THICK_TASK_BORDER_STROKE); |
| | | |
| | | RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); |
| | | g.draw(rect); |
| | | |
| | | g.setPaint(originalPaint); |
| | | g.setStroke(originalStroke); |
| | | } |
| | | |
| | | /** |
| | | * taskæ¡èªå®ä¹æå |
| | | * @param name |
| | | * @param graphicInfo |
| | | * @param thickBorder |
| | | * @param scaleFactor |
| | | */ |
| | | @Override |
| | | protected void drawTask(String name, GraphicInfo graphicInfo, boolean thickBorder, double scaleFactor) { |
| | | |
| | | Paint originalPaint = g.getPaint(); |
| | | int x = (int) graphicInfo.getX(); |
| | | int y = (int) graphicInfo.getY(); |
| | | int width = (int) graphicInfo.getWidth(); |
| | | int height = (int) graphicInfo.getHeight(); |
| | | |
| | | // Create a new gradient paint for every task box, gradient depends on x and y and is not relative |
| | | g.setPaint(TASK_BOX_COLOR); |
| | | |
| | | int arcR = 6; |
| | | if (thickBorder) { |
| | | arcR = 3; |
| | | } |
| | | |
| | | // shape |
| | | RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, arcR, arcR); |
| | | g.fill(rect); |
| | | g.setPaint(TASK_BORDER_COLOR); |
| | | |
| | | if (thickBorder) { |
| | | Stroke originalStroke = g.getStroke(); |
| | | g.setStroke(THICK_TASK_BORDER_STROKE); |
| | | g.draw(rect); |
| | | g.setStroke(originalStroke); |
| | | } else { |
| | | g.draw(rect); |
| | | } |
| | | |
| | | g.setPaint(originalPaint); |
| | | // text |
| | | if (scaleFactor == 1.0 && name != null && name.length() > 0) { |
| | | int boxWidth = width - (2 * TEXT_PADDING); |
| | | int boxHeight = height - 16 - ICON_PADDING - ICON_PADDING - MARKER_WIDTH - 2 - 2; |
| | | int boxX = x + width / 2 - boxWidth / 2; |
| | | int boxY = y + height / 2 - boxHeight / 2 + ICON_PADDING + ICON_PADDING - 2 - 2; |
| | | |
| | | drawMultilineCentredText(name, boxX, boxY, boxWidth, boxHeight); |
| | | } |
| | | } |
| | | |
| | | protected static Color EVENT_COLOR = new Color(255, 255, 255); |
| | | |
| | | /** |
| | | * éåå¼å§äºä»¶ |
| | | * @param graphicInfo |
| | | * @param image |
| | | * @param scaleFactor |
| | | */ |
| | | @Override |
| | | public void drawStartEvent(GraphicInfo graphicInfo, BufferedImage image, double scaleFactor) { |
| | | Paint originalPaint = g.getPaint(); |
| | | g.setPaint(EVENT_COLOR); |
| | | Ellipse2D circle = new Ellipse2D.Double(graphicInfo.getX(), graphicInfo.getY(), |
| | | graphicInfo.getWidth(), graphicInfo.getHeight()); |
| | | g.fill(circle); |
| | | g.setPaint(EVENT_BORDER_COLOR); |
| | | g.draw(circle); |
| | | g.setPaint(originalPaint); |
| | | if (image != null) { |
| | | // calculate coordinates to center image |
| | | int imageX = (int) Math.round(graphicInfo.getX() + (graphicInfo.getWidth() / 2) - (image.getWidth() / (2 * scaleFactor))); |
| | | int imageY = (int) Math.round(graphicInfo.getY() + (graphicInfo.getHeight() / 2) - (image.getHeight() / (2 * scaleFactor))); |
| | | g.drawImage(image, imageX, imageY, |
| | | (int) (image.getWidth() / scaleFactor), (int) (image.getHeight() / scaleFactor), null); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * éåç»æäºä»¶ |
| | | * @param graphicInfo |
| | | * @param scaleFactor |
| | | */ |
| | | @Override |
| | | public void drawNoneEndEvent(GraphicInfo graphicInfo, double scaleFactor) { |
| | | Paint originalPaint = g.getPaint(); |
| | | Stroke originalStroke = g.getStroke(); |
| | | g.setPaint(EVENT_COLOR); |
| | | Ellipse2D circle = new Ellipse2D.Double(graphicInfo.getX(), graphicInfo.getY(), |
| | | graphicInfo.getWidth(), graphicInfo.getHeight()); |
| | | g.fill(circle); |
| | | g.setPaint(EVENT_BORDER_COLOR); |
| | | // g.setPaint(HIGHLIGHT_COLOR); |
| | | if (scaleFactor == 1.0) { |
| | | g.setStroke(END_EVENT_STROKE); |
| | | } else { |
| | | g.setStroke(new BasicStroke(2.0f)); |
| | | } |
| | | g.draw(circle); |
| | | g.setStroke(originalStroke); |
| | | g.setPaint(originalPaint); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.flow; |
| | | |
| | | |
| | | import org.flowable.bpmn.model.Process; |
| | | import org.flowable.bpmn.model.*; |
| | | import org.flowable.image.impl.DefaultProcessDiagramCanvas; |
| | | import org.flowable.image.impl.DefaultProcessDiagramGenerator; |
| | | |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author XuanXuan |
| | | * @date 2021/4/5 0:31 |
| | | */ |
| | | public class CustomProcessDiagramGenerator extends DefaultProcessDiagramGenerator { |
| | | @Override |
| | | protected DefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities, List<String> highLightedFlows, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { |
| | | this.prepareBpmnModel(bpmnModel); |
| | | DefaultProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); |
| | | Iterator var13 = bpmnModel.getPools().iterator(); |
| | | |
| | | while (var13.hasNext()) { |
| | | Pool process = (Pool) var13.next(); |
| | | GraphicInfo subProcesses = bpmnModel.getGraphicInfo(process.getId()); |
| | | processDiagramCanvas.drawPoolOrLane(process.getName(), subProcesses, scaleFactor); |
| | | } |
| | | |
| | | var13 = bpmnModel.getProcesses().iterator(); |
| | | |
| | | Process process1; |
| | | Iterator subProcesses1; |
| | | while (var13.hasNext()) { |
| | | process1 = (Process) var13.next(); |
| | | subProcesses1 = process1.getLanes().iterator(); |
| | | |
| | | while (subProcesses1.hasNext()) { |
| | | Lane artifact = (Lane) subProcesses1.next(); |
| | | GraphicInfo subProcess = bpmnModel.getGraphicInfo(artifact.getId()); |
| | | processDiagramCanvas.drawPoolOrLane(artifact.getName(), subProcess, scaleFactor); |
| | | } |
| | | } |
| | | |
| | | var13 = bpmnModel.getProcesses().iterator(); |
| | | |
| | | while (var13.hasNext()) { |
| | | process1 = (Process) var13.next(); |
| | | subProcesses1 = process1.findFlowElementsOfType(FlowNode.class).iterator(); |
| | | |
| | | while (subProcesses1.hasNext()) { |
| | | FlowNode artifact1 = (FlowNode) subProcesses1.next(); |
| | | if (!this.isPartOfCollapsedSubProcess(artifact1, bpmnModel)) { |
| | | this.drawActivity(processDiagramCanvas, bpmnModel, artifact1, highLightedActivities, highLightedFlows, scaleFactor, Boolean.valueOf(drawSequenceFlowNameWithNoLabelDI)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | var13 = bpmnModel.getProcesses().iterator(); |
| | | |
| | | label75: |
| | | while (true) { |
| | | List subProcesses2; |
| | | do { |
| | | if (!var13.hasNext()) { |
| | | return processDiagramCanvas; |
| | | } |
| | | |
| | | process1 = (Process) var13.next(); |
| | | subProcesses1 = process1.getArtifacts().iterator(); |
| | | |
| | | while (subProcesses1.hasNext()) { |
| | | Artifact artifact2 = (Artifact) subProcesses1.next(); |
| | | this.drawArtifact(processDiagramCanvas, bpmnModel, artifact2); |
| | | } |
| | | |
| | | subProcesses2 = process1.findFlowElementsOfType(SubProcess.class, true); |
| | | } while (subProcesses2 == null); |
| | | |
| | | Iterator artifact3 = subProcesses2.iterator(); |
| | | |
| | | while (true) { |
| | | GraphicInfo graphicInfo; |
| | | SubProcess subProcess1; |
| | | do { |
| | | do { |
| | | if (!artifact3.hasNext()) { |
| | | continue label75; |
| | | } |
| | | |
| | | subProcess1 = (SubProcess) artifact3.next(); |
| | | graphicInfo = bpmnModel.getGraphicInfo(subProcess1.getId()); |
| | | } while (graphicInfo != null && graphicInfo.getExpanded() != null && !graphicInfo.getExpanded().booleanValue()); |
| | | } while (this.isPartOfCollapsedSubProcess(subProcess1, bpmnModel)); |
| | | |
| | | Iterator var19 = subProcess1.getArtifacts().iterator(); |
| | | |
| | | while (var19.hasNext()) { |
| | | Artifact subProcessArtifact = (Artifact) var19.next(); |
| | | this.drawArtifact(processDiagramCanvas, bpmnModel, subProcessArtifact); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected static DefaultProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { |
| | | double minX = 1.7976931348623157E308D; |
| | | double maxX = 0.0D; |
| | | double minY = 1.7976931348623157E308D; |
| | | double maxY = 0.0D; |
| | | |
| | | GraphicInfo nrOfLanes; |
| | | for (Iterator flowNodes = bpmnModel.getPools().iterator(); flowNodes.hasNext(); maxY = nrOfLanes.getY() + nrOfLanes.getHeight()) { |
| | | Pool artifacts = (Pool) flowNodes.next(); |
| | | nrOfLanes = bpmnModel.getGraphicInfo(artifacts.getId()); |
| | | minX = nrOfLanes.getX(); |
| | | maxX = nrOfLanes.getX() + nrOfLanes.getWidth(); |
| | | minY = nrOfLanes.getY(); |
| | | } |
| | | |
| | | List var23 = gatherAllFlowNodes(bpmnModel); |
| | | Iterator var24 = var23.iterator(); |
| | | |
| | | label155: |
| | | while (var24.hasNext()) { |
| | | FlowNode var26 = (FlowNode) var24.next(); |
| | | GraphicInfo artifact = bpmnModel.getGraphicInfo(var26.getId()); |
| | | if (artifact.getX() + artifact.getWidth() > maxX) { |
| | | maxX = artifact.getX() + artifact.getWidth(); |
| | | } |
| | | |
| | | if (artifact.getX() < minX) { |
| | | minX = artifact.getX(); |
| | | } |
| | | |
| | | if (artifact.getY() + artifact.getHeight() > maxY) { |
| | | maxY = artifact.getY() + artifact.getHeight(); |
| | | } |
| | | |
| | | if (artifact.getY() < minY) { |
| | | minY = artifact.getY(); |
| | | } |
| | | |
| | | Iterator process = var26.getOutgoingFlows().iterator(); |
| | | |
| | | while (true) { |
| | | List l; |
| | | do { |
| | | if (!process.hasNext()) { |
| | | continue label155; |
| | | } |
| | | |
| | | SequenceFlow graphicInfoList = (SequenceFlow) process.next(); |
| | | l = bpmnModel.getFlowLocationGraphicInfo(graphicInfoList.getId()); |
| | | } while (l == null); |
| | | |
| | | Iterator graphicInfo = l.iterator(); |
| | | |
| | | while (graphicInfo.hasNext()) { |
| | | GraphicInfo graphicInfo1 = (GraphicInfo) graphicInfo.next(); |
| | | if (graphicInfo1.getX() > maxX) { |
| | | maxX = graphicInfo1.getX(); |
| | | } |
| | | |
| | | if (graphicInfo1.getX() < minX) { |
| | | minX = graphicInfo1.getX(); |
| | | } |
| | | |
| | | if (graphicInfo1.getY() > maxY) { |
| | | maxY = graphicInfo1.getY(); |
| | | } |
| | | |
| | | if (graphicInfo1.getY() < minY) { |
| | | minY = graphicInfo1.getY(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | List var25 = gatherAllArtifacts(bpmnModel); |
| | | Iterator var27 = var25.iterator(); |
| | | |
| | | GraphicInfo var37; |
| | | while (var27.hasNext()) { |
| | | Artifact var29 = (Artifact) var27.next(); |
| | | GraphicInfo var31 = bpmnModel.getGraphicInfo(var29.getId()); |
| | | if (var31 != null) { |
| | | if (var31.getX() + var31.getWidth() > maxX) { |
| | | maxX = var31.getX() + var31.getWidth(); |
| | | } |
| | | |
| | | if (var31.getX() < minX) { |
| | | minX = var31.getX(); |
| | | } |
| | | |
| | | if (var31.getY() + var31.getHeight() > maxY) { |
| | | maxY = var31.getY() + var31.getHeight(); |
| | | } |
| | | |
| | | if (var31.getY() < minY) { |
| | | minY = var31.getY(); |
| | | } |
| | | } |
| | | |
| | | List var33 = bpmnModel.getFlowLocationGraphicInfo(var29.getId()); |
| | | if (var33 != null) { |
| | | Iterator var35 = var33.iterator(); |
| | | |
| | | while (var35.hasNext()) { |
| | | var37 = (GraphicInfo) var35.next(); |
| | | if (var37.getX() > maxX) { |
| | | maxX = var37.getX(); |
| | | } |
| | | |
| | | if (var37.getX() < minX) { |
| | | minX = var37.getX(); |
| | | } |
| | | |
| | | if (var37.getY() > maxY) { |
| | | maxY = var37.getY(); |
| | | } |
| | | |
| | | if (var37.getY() < minY) { |
| | | minY = var37.getY(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | int var28 = 0; |
| | | Iterator var30 = bpmnModel.getProcesses().iterator(); |
| | | |
| | | while (var30.hasNext()) { |
| | | Process var32 = (Process) var30.next(); |
| | | Iterator var34 = var32.getLanes().iterator(); |
| | | |
| | | while (var34.hasNext()) { |
| | | Lane var36 = (Lane) var34.next(); |
| | | ++var28; |
| | | var37 = bpmnModel.getGraphicInfo(var36.getId()); |
| | | if (var37.getX() + var37.getWidth() > maxX) { |
| | | maxX = var37.getX() + var37.getWidth(); |
| | | } |
| | | |
| | | if (var37.getX() < minX) { |
| | | minX = var37.getX(); |
| | | } |
| | | |
| | | if (var37.getY() + var37.getHeight() > maxY) { |
| | | maxY = var37.getY() + var37.getHeight(); |
| | | } |
| | | |
| | | if (var37.getY() < minY) { |
| | | minY = var37.getY(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (var23.isEmpty() && bpmnModel.getPools().isEmpty() && var28 == 0) { |
| | | minX = 0.0D; |
| | | minY = 0.0D; |
| | | } |
| | | |
| | | return new CustomProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); |
| | | } |
| | | |
| | | |
| | | private static void drawHighLight(DefaultProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { |
| | | processDiagramCanvas.drawHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); |
| | | |
| | | } |
| | | |
| | | private static void drawHighLightNow(CustomProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { |
| | | processDiagramCanvas.drawHighLightNow((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); |
| | | |
| | | } |
| | | |
| | | private static void drawHighLightEnd(CustomProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { |
| | | processDiagramCanvas.drawHighLightEnd((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); |
| | | |
| | | } |
| | | |
| | | @Override |
| | | protected void drawActivity(DefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, |
| | | FlowNode flowNode, List<String> highLightedActivities, List<String> highLightedFlows, double scaleFactor, Boolean drawSequenceFlowNameWithNoLabelDI) { |
| | | |
| | | ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass()); |
| | | if (drawInstruction != null) { |
| | | |
| | | drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode); |
| | | |
| | | // Gather info on the multi instance marker |
| | | boolean multiInstanceSequential = false; |
| | | boolean multiInstanceParallel = false; |
| | | boolean collapsed = false; |
| | | if (flowNode instanceof Activity) { |
| | | Activity activity = (Activity) flowNode; |
| | | MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics(); |
| | | if (multiInstanceLoopCharacteristics != null) { |
| | | multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential(); |
| | | multiInstanceParallel = !multiInstanceSequential; |
| | | } |
| | | } |
| | | |
| | | // Gather info on the collapsed marker |
| | | GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); |
| | | if (flowNode instanceof SubProcess) { |
| | | collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded(); |
| | | } else if (flowNode instanceof CallActivity) { |
| | | collapsed = true; |
| | | } |
| | | |
| | | if (scaleFactor == 1.0) { |
| | | // Actually draw the markers |
| | | processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), |
| | | multiInstanceSequential, multiInstanceParallel, collapsed); |
| | | } |
| | | |
| | | // Draw highlighted activities |
| | | if (highLightedActivities.contains(flowNode.getId())) { |
| | | |
| | | if (highLightedActivities.get(highLightedActivities.size() - 1).equals(flowNode.getId()) |
| | | && !"endenv".equals(flowNode.getId())) { |
| | | if ((flowNode.getId().contains("Event_"))) { |
| | | drawHighLightEnd((CustomProcessDiagramCanvas) processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); |
| | | } else { |
| | | drawHighLightNow((CustomProcessDiagramCanvas) processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); |
| | | } |
| | | } else { |
| | | drawHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | // Outgoing transitions of activity |
| | | for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) { |
| | | boolean highLighted = (highLightedFlows.contains(sequenceFlow.getId())); |
| | | String defaultFlow = null; |
| | | if (flowNode instanceof Activity) { |
| | | defaultFlow = ((Activity) flowNode).getDefaultFlow(); |
| | | } else if (flowNode instanceof Gateway) { |
| | | defaultFlow = ((Gateway) flowNode).getDefaultFlow(); |
| | | } |
| | | |
| | | boolean isDefault = false; |
| | | if (defaultFlow != null && defaultFlow.equalsIgnoreCase(sequenceFlow.getId())) { |
| | | isDefault = true; |
| | | } |
| | | boolean drawConditionalIndicator = sequenceFlow.getConditionExpression() != null && !(flowNode instanceof Gateway); |
| | | |
| | | String sourceRef = sequenceFlow.getSourceRef(); |
| | | String targetRef = sequenceFlow.getTargetRef(); |
| | | FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef); |
| | | FlowElement targetElement = bpmnModel.getFlowElement(targetRef); |
| | | List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId()); |
| | | if (graphicInfoList != null && graphicInfoList.size() > 0) { |
| | | graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList); |
| | | 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); |
| | | GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); |
| | | |
| | | if (i == 1) { |
| | | xPoints[0] = (int) previousGraphicInfo.getX(); |
| | | yPoints[0] = (int) previousGraphicInfo.getY(); |
| | | } |
| | | xPoints[i] = (int) graphicInfo.getX(); |
| | | yPoints[i] = (int) graphicInfo.getY(); |
| | | |
| | | } |
| | | |
| | | processDiagramCanvas.drawSequenceflow(xPoints, yPoints, drawConditionalIndicator, isDefault, highLighted, scaleFactor); |
| | | |
| | | |
| | | // Draw sequenceflow label |
| | | GraphicInfo labelGraphicInfo = bpmnModel.getLabelGraphicInfo(sequenceFlow.getId()); |
| | | if (labelGraphicInfo != null) { |
| | | processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false); |
| | | } else { |
| | | if (drawSequenceFlowNameWithNoLabelDI) { |
| | | GraphicInfo lineCenter = getLineCenter(graphicInfoList); |
| | | processDiagramCanvas.drawLabel(sequenceFlow.getName(), lineCenter, false); |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Nested elements |
| | | if (flowNode instanceof FlowElementsContainer) { |
| | | for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) { |
| | | if (nestedFlowElement instanceof FlowNode && !isPartOfCollapsedSubProcess(nestedFlowElement, bpmnModel)) { |
| | | drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement, |
| | | highLightedActivities, highLightedFlows, scaleFactor, drawSequenceFlowNameWithNoLabelDI); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.flow; |
| | | |
| | | import com.googlecode.aviator.AviatorEvaluator; |
| | | import com.googlecode.aviator.Expression; |
| | | import org.flowable.bpmn.model.Process; |
| | | import org.flowable.bpmn.model.*; |
| | | import org.flowable.engine.RepositoryService; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author Xuan xuan |
| | | * @date 2021/4/19 20:51 |
| | | */ |
| | | public class FindNextNodeUtil { |
| | | |
| | | /** |
| | | * è·åä¸ä¸æ¥éª¤çç¨æ·ä»»å¡ |
| | | * |
| | | * @param repositoryService |
| | | * @param map |
| | | * @return |
| | | */ |
| | | public static List<UserTask> getNextUserTasks(RepositoryService repositoryService, org.flowable.task.api.Task task, Map<String, Object> map) { |
| | | List<UserTask> data = new ArrayList<>(); |
| | | ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); |
| | | Process mainProcess = bpmnModel.getMainProcess(); |
| | | Collection<FlowElement> flowElements = mainProcess.getFlowElements(); |
| | | String key = task.getTaskDefinitionKey(); |
| | | FlowElement flowElement = bpmnModel.getFlowElement(key); |
| | | next(flowElements, flowElement, map, data); |
| | | return data; |
| | | } |
| | | |
| | | public static void next(Collection<FlowElement> flowElements, FlowElement flowElement, Map<String, Object> map, List<UserTask> nextUser) { |
| | | //妿æ¯ç»æèç¹ |
| | | if (flowElement instanceof EndEvent) { |
| | | //妿æ¯åä»»å¡çç»æèç¹ |
| | | if (getSubProcess(flowElements, flowElement) != null) { |
| | | flowElement = getSubProcess(flowElements, flowElement); |
| | | } |
| | | } |
| | | //è·åTaskçåºçº¿ä¿¡æ¯--å¯ä»¥æ¥æå¤ä¸ª |
| | | List<SequenceFlow> outGoingFlows = null; |
| | | if (flowElement instanceof Task) { |
| | | outGoingFlows = ((Task) flowElement).getOutgoingFlows(); |
| | | } else if (flowElement instanceof Gateway) { |
| | | outGoingFlows = ((Gateway) flowElement).getOutgoingFlows(); |
| | | } else if (flowElement instanceof StartEvent) { |
| | | outGoingFlows = ((StartEvent) flowElement).getOutgoingFlows(); |
| | | } else if (flowElement instanceof SubProcess) { |
| | | outGoingFlows = ((SubProcess) flowElement).getOutgoingFlows(); |
| | | } else if (flowElement instanceof CallActivity) { |
| | | outGoingFlows = ((CallActivity) flowElement).getOutgoingFlows(); |
| | | } |
| | | if (outGoingFlows != null && outGoingFlows.size() > 0) { |
| | | //éåææçåºçº¿--æ¾å°å¯ä»¥æ£ç¡®æ§è¡çé£ä¸æ¡ |
| | | for (SequenceFlow sequenceFlow : outGoingFlows) { |
| | | //1.æè¡¨è¾¾å¼ï¼ä¸ä¸ºtrue |
| | | //2.æ è¡¨è¾¾å¼ |
| | | String expression = sequenceFlow.getConditionExpression(); |
| | | if (expression == null || expressionResult(map, expression.substring(expression.lastIndexOf("{") + 1, expression.lastIndexOf("}")))) { |
| | | //åºçº¿çä¸ä¸èç¹ |
| | | String nextFlowElementID = sequenceFlow.getTargetRef(); |
| | | if (checkSubProcess(nextFlowElementID, flowElements, nextUser)) { |
| | | continue; |
| | | } |
| | | |
| | | //æ¥è¯¢ä¸ä¸èç¹çä¿¡æ¯ |
| | | FlowElement nextFlowElement = getFlowElementById(nextFlowElementID, flowElements); |
| | | //è°ç¨æµç¨ |
| | | if (nextFlowElement instanceof CallActivity) { |
| | | CallActivity ca = (CallActivity) nextFlowElement; |
| | | if (ca.getLoopCharacteristics() != null) { |
| | | UserTask userTask = new UserTask(); |
| | | userTask.setId(ca.getId()); |
| | | |
| | | userTask.setId(ca.getId()); |
| | | userTask.setLoopCharacteristics(ca.getLoopCharacteristics()); |
| | | userTask.setName(ca.getName()); |
| | | nextUser.add(userTask); |
| | | } |
| | | next(flowElements, nextFlowElement, map, nextUser); |
| | | } |
| | | //ç¨æ·ä»»å¡ |
| | | if (nextFlowElement instanceof UserTask) { |
| | | nextUser.add((UserTask) nextFlowElement); |
| | | } |
| | | //æä»ç½å
³ |
| | | else if (nextFlowElement instanceof ExclusiveGateway) { |
| | | next(flowElements, nextFlowElement, map, nextUser); |
| | | } |
| | | //å¹¶è¡ç½å
³ |
| | | else if (nextFlowElement instanceof ParallelGateway) { |
| | | next(flowElements, nextFlowElement, map, nextUser); |
| | | } |
| | | //æ¥æ¶ä»»å¡ |
| | | else if (nextFlowElement instanceof ReceiveTask) { |
| | | next(flowElements, nextFlowElement, map, nextUser); |
| | | } |
| | | //æå¡ä»»å¡ |
| | | else if (nextFlowElement instanceof ServiceTask) { |
| | | next(flowElements, nextFlowElement, map, nextUser); |
| | | } |
| | | //åä»»å¡çèµ·ç¹ |
| | | else if (nextFlowElement instanceof StartEvent) { |
| | | next(flowElements, nextFlowElement, map, nextUser); |
| | | } |
| | | //ç»æèç¹ |
| | | else if (nextFlowElement instanceof EndEvent) { |
| | | next(flowElements, nextFlowElement, map, nextUser); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦æ¯å¤å®ä¾åæµç¨å¹¶ä¸éè¦è®¾ç½®éåç±»ååé |
| | | */ |
| | | public static boolean checkSubProcess(String Id, Collection<FlowElement> flowElements, List<UserTask> nextUser) { |
| | | for (FlowElement flowElement1 : flowElements) { |
| | | if (flowElement1 instanceof SubProcess && flowElement1.getId().equals(Id)) { |
| | | |
| | | SubProcess sp = (SubProcess) flowElement1; |
| | | if (sp.getLoopCharacteristics() != null) { |
| | | String inputDataItem = sp.getLoopCharacteristics().getInputDataItem(); |
| | | UserTask userTask = new UserTask(); |
| | | userTask.setId(sp.getId()); |
| | | userTask.setLoopCharacteristics(sp.getLoopCharacteristics()); |
| | | userTask.setName(sp.getName()); |
| | | nextUser.add(userTask); |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢ä¸ä¸ªèç¹çæ¯å¦åä»»å¡ä¸çèç¹ï¼å¦ææ¯ï¼è¿ååä»»å¡ |
| | | * |
| | | * @param flowElements å
¨æµç¨çèç¹éå |
| | | * @param flowElement å½åèç¹ |
| | | * @return |
| | | */ |
| | | public static FlowElement getSubProcess(Collection<FlowElement> flowElements, FlowElement flowElement) { |
| | | for (FlowElement flowElement1 : flowElements) { |
| | | if (flowElement1 instanceof SubProcess) { |
| | | for (FlowElement flowElement2 : ((SubProcess) flowElement1).getFlowElements()) { |
| | | if (flowElement.equals(flowElement2)) { |
| | | return flowElement1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * æ ¹æ®IDæ¥è¯¢æµç¨èç¹å¯¹è±¡, 妿æ¯åä»»å¡ï¼åè¿ååä»»å¡çå¼å§èç¹ |
| | | * |
| | | * @param Id èç¹ID |
| | | * @param flowElements æµç¨èç¹éå |
| | | * @return |
| | | */ |
| | | public static FlowElement getFlowElementById(String Id, Collection<FlowElement> flowElements) { |
| | | for (FlowElement flowElement : flowElements) { |
| | | if (flowElement.getId().equals(Id)) { |
| | | //妿æ¯åä»»å¡ï¼åæ¥è¯¢åºåä»»å¡çå¼å§èç¹ |
| | | if (flowElement instanceof SubProcess) { |
| | | return getStartFlowElement(((SubProcess) flowElement).getFlowElements()); |
| | | } |
| | | return flowElement; |
| | | } |
| | | if (flowElement instanceof SubProcess) { |
| | | FlowElement flowElement1 = getFlowElementById(Id, ((SubProcess) flowElement).getFlowElements()); |
| | | if (flowElement1 != null) { |
| | | return flowElement1; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * è¿åæµç¨çå¼å§èç¹ |
| | | * |
| | | * @param flowElements èç¹éå |
| | | * @description: |
| | | */ |
| | | public static FlowElement getStartFlowElement(Collection<FlowElement> flowElements) { |
| | | for (FlowElement flowElement : flowElements) { |
| | | if (flowElement instanceof StartEvent) { |
| | | return flowElement; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªelè¡¨è¾¾å¼ |
| | | * |
| | | * @param map |
| | | * @param expression |
| | | * @return |
| | | */ |
| | | public static boolean expressionResult(Map<String, Object> map, String expression) { |
| | | Expression exp = AviatorEvaluator.compile(expression); |
| | | final Object execute = exp.execute(map); |
| | | return Boolean.parseBoolean(String.valueOf(execute)); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.flow; |
| | | |
| | | import org.flowable.spring.SpringProcessEngineConfiguration; |
| | | import org.flowable.spring.boot.EngineConfigurationConfigurer; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | |
| | | /** |
| | | * @author XuanXuan |
| | | * @date 2021/4/5 01:32 |
| | | */ |
| | | @Configuration |
| | | public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> { |
| | | |
| | | @Override |
| | | public void configure(SpringProcessEngineConfiguration engineConfiguration) { |
| | | engineConfiguration.setActivityFontName("å®ä½"); |
| | | engineConfiguration.setLabelFontName("å®ä½"); |
| | | engineConfiguration.setAnnotationFontName("å®ä½"); |
| | | |
| | | } |
| | | } |
| | | |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.flow; |
| | | |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import org.ruoyi.common.core.exception.ServiceException; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.flowable.bpmn.model.*; |
| | | import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; |
| | | import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; |
| | | import org.flowable.task.api.history.HistoricTaskInstance; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * @author XuanXuan |
| | | * @date 2021-04-03 23:57 |
| | | */ |
| | | @Slf4j |
| | | public class FlowableUtils { |
| | | |
| | | /** |
| | | * æ ¹æ®èç¹ï¼è·åå
¥å£è¿çº¿ |
| | | * @param source |
| | | * @return |
| | | */ |
| | | public static List<SequenceFlow> getElementIncomingFlows(FlowElement source) { |
| | | List<SequenceFlow> sequenceFlows = null; |
| | | if (source instanceof FlowNode) { |
| | | sequenceFlows = ((FlowNode) source).getIncomingFlows(); |
| | | } else if (source instanceof Gateway) { |
| | | sequenceFlows = ((Gateway) source).getIncomingFlows(); |
| | | } else if (source instanceof SubProcess) { |
| | | sequenceFlows = ((SubProcess) source).getIncomingFlows(); |
| | | } else if (source instanceof StartEvent) { |
| | | sequenceFlows = ((StartEvent) source).getIncomingFlows(); |
| | | } else if (source instanceof EndEvent) { |
| | | sequenceFlows = ((EndEvent) source).getIncomingFlows(); |
| | | } |
| | | return sequenceFlows; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®èç¹ï¼è·ååºå£è¿çº¿ |
| | | * @param source |
| | | * @return |
| | | */ |
| | | public static List<SequenceFlow> getElementOutgoingFlows(FlowElement source) { |
| | | List<SequenceFlow> sequenceFlows = null; |
| | | if (source instanceof FlowNode) { |
| | | sequenceFlows = ((FlowNode) source).getOutgoingFlows(); |
| | | } else if (source instanceof Gateway) { |
| | | sequenceFlows = ((Gateway) source).getOutgoingFlows(); |
| | | } else if (source instanceof SubProcess) { |
| | | sequenceFlows = ((SubProcess) source).getOutgoingFlows(); |
| | | } else if (source instanceof StartEvent) { |
| | | sequenceFlows = ((StartEvent) source).getOutgoingFlows(); |
| | | } else if (source instanceof EndEvent) { |
| | | sequenceFlows = ((EndEvent) source).getOutgoingFlows(); |
| | | } |
| | | return sequenceFlows; |
| | | } |
| | | |
| | | /** |
| | | * è·åå
¨é¨èç¹å表ï¼å
å«åæµç¨èç¹ |
| | | * @param flowElements |
| | | * @param allElements |
| | | * @return |
| | | */ |
| | | public static Collection<FlowElement> getAllElements(Collection<FlowElement> flowElements, Collection<FlowElement> allElements) { |
| | | allElements = allElements == null ? new ArrayList<>() : allElements; |
| | | |
| | | for (FlowElement flowElement : flowElements) { |
| | | allElements.add(flowElement); |
| | | if (flowElement instanceof SubProcess) { |
| | | // ç»§ç»æ·±å
¥åæµç¨ï¼è¿ä¸æ¥è·ååæµç¨ |
| | | allElements = FlowableUtils.getAllElements(((SubProcess) flowElement).getFlowElements(), allElements); |
| | | } |
| | | } |
| | | return allElements; |
| | | } |
| | | |
| | | /** |
| | | * è¿ä»£è·åç¶çº§ä»»å¡èç¹å表ï¼ååæ¾ |
| | | * @param source èµ·å§èç¹ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param userTaskList å·²æ¾å°çç¨æ·ä»»å¡èç¹ |
| | | * @return |
| | | */ |
| | | public static List<UserTask> iteratorFindParentUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) { |
| | | userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; |
| | | hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
| | | |
| | | // å¦æè¯¥èç¹ä¸ºå¼å§èç¹ï¼ä¸åå¨ä¸çº§åèç¹ï¼å顺çä¸çº§åèç¹ç»§ç»è¿ä»£ |
| | | if (source instanceof StartEvent && source.getSubProcess() != null) { |
| | | userTaskList = iteratorFindParentUserTasks(source.getSubProcess(), hasSequenceFlow, userTaskList); |
| | | } |
| | | |
| | | // æ ¹æ®ç±»åï¼è·åå
¥å£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source); |
| | | |
| | | if (sequenceFlows != null) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | // ç±»åä¸ºç¨æ·èç¹ï¼åæ°å¢ç¶çº§èç¹ |
| | | if (sequenceFlow.getSourceFlowElement() instanceof UserTask) { |
| | | userTaskList.add((UserTask) sequenceFlow.getSourceFlowElement()); |
| | | continue; |
| | | } |
| | | // ç±»åä¸ºåæµç¨ï¼åæ·»å åæµç¨å¼å§èç¹åºå£å¤ç¸è¿çèç¹ |
| | | if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) { |
| | | // è·ååæµç¨ç¨æ·ä»»å¡èç¹ |
| | | List<UserTask> childUserTaskList = findChildProcessUserTasks((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, null); |
| | | // 妿æ¾å°èç¹ï¼å说æè¯¥çº¿è·¯æ¾å°èç¹ï¼ä¸ç»§ç»å䏿¾ï¼åä¹ç»§ç» |
| | | if (childUserTaskList != null && childUserTaskList.size() > 0) { |
| | | userTaskList.addAll(childUserTaskList); |
| | | continue; |
| | | } |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | userTaskList = iteratorFindParentUserTasks(sequenceFlow.getSourceFlowElement(), hasSequenceFlow, userTaskList); |
| | | } |
| | | } |
| | | return userTaskList; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ£å¨è¿è¡çä»»å¡èç¹ï¼è¿ä»£è·åå级任å¡èç¹å表ï¼ååæ¾ |
| | | * @param source èµ·å§èç¹ |
| | | * @param runTaskKeyList æ£å¨è¿è¡çä»»å¡ Keyï¼ç¨äºæ ¡éªä»»å¡èç¹æ¯å¦æ¯æ£å¨è¿è¡çèç¹ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param userTaskList éè¦æ¤åçç¨æ·ä»»å¡å表 |
| | | * @return |
| | | */ |
| | | public static List<UserTask> iteratorFindChildUserTasks(FlowElement source, List<String> runTaskKeyList, Set<String> hasSequenceFlow, List<UserTask> userTaskList) { |
| | | hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
| | | userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; |
| | | |
| | | // å¦æè¯¥èç¹ä¸ºå¼å§èç¹ï¼ä¸åå¨ä¸çº§åèç¹ï¼å顺çä¸çº§åèç¹ç»§ç»è¿ä»£ |
| | | if (source instanceof StartEvent && source.getSubProcess() != null) { |
| | | userTaskList = iteratorFindChildUserTasks(source.getSubProcess(), runTaskKeyList, hasSequenceFlow, userTaskList); |
| | | } |
| | | |
| | | // æ ¹æ®ç±»åï¼è·ååºå£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source); |
| | | |
| | | if (sequenceFlows != null) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | // å¦æä¸ºç¨æ·ä»»å¡ç±»åï¼ä¸ä»»å¡èç¹ç Key æ£å¨è¿è¡çä»»å¡ä¸åå¨ï¼æ·»å |
| | | if (sequenceFlow.getTargetFlowElement() instanceof UserTask && runTaskKeyList.contains((sequenceFlow.getTargetFlowElement()).getId())) { |
| | | userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement()); |
| | | continue; |
| | | } |
| | | // 妿èç¹ä¸ºåæµç¨èç¹æ
åµï¼åä»èç¹ä¸ç第ä¸ä¸ªèç¹å¼å§è·å |
| | | if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) { |
| | | List<UserTask> childUserTaskList = iteratorFindChildUserTasks((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), runTaskKeyList, hasSequenceFlow, null); |
| | | // 妿æ¾å°èç¹ï¼å说æè¯¥çº¿è·¯æ¾å°èç¹ï¼ä¸ç»§ç»å䏿¾ï¼åä¹ç»§ç» |
| | | if (childUserTaskList != null && childUserTaskList.size() > 0) { |
| | | userTaskList.addAll(childUserTaskList); |
| | | continue; |
| | | } |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | userTaskList = iteratorFindChildUserTasks(sequenceFlow.getTargetFlowElement(), runTaskKeyList, hasSequenceFlow, userTaskList); |
| | | } |
| | | } |
| | | return userTaskList; |
| | | } |
| | | |
| | | /** |
| | | * è¿ä»£è·ååæµç¨ç¨æ·ä»»å¡èç¹ |
| | | * @param source èµ·å§èç¹ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param userTaskList éè¦æ¤åçç¨æ·ä»»å¡å表 |
| | | * @return |
| | | */ |
| | | public static List<UserTask> findChildProcessUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) { |
| | | hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
| | | userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; |
| | | |
| | | // æ ¹æ®ç±»åï¼è·ååºå£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source); |
| | | |
| | | if (sequenceFlows != null) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | // å¦æä¸ºç¨æ·ä»»å¡ç±»åï¼ä¸ä»»å¡èç¹ç Key æ£å¨è¿è¡çä»»å¡ä¸åå¨ï¼æ·»å |
| | | if (sequenceFlow.getTargetFlowElement() instanceof UserTask) { |
| | | userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement()); |
| | | continue; |
| | | } |
| | | // 妿èç¹ä¸ºåæµç¨èç¹æ
åµï¼åä»èç¹ä¸ç第ä¸ä¸ªèç¹å¼å§è·å |
| | | if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) { |
| | | List<UserTask> childUserTaskList = findChildProcessUserTasks((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, null); |
| | | // 妿æ¾å°èç¹ï¼å说æè¯¥çº¿è·¯æ¾å°èç¹ï¼ä¸ç»§ç»å䏿¾ï¼åä¹ç»§ç» |
| | | if (childUserTaskList != null && childUserTaskList.size() > 0) { |
| | | userTaskList.addAll(childUserTaskList); |
| | | continue; |
| | | } |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | userTaskList = findChildProcessUserTasks(sequenceFlow.getTargetFlowElement(), hasSequenceFlow, userTaskList); |
| | | } |
| | | } |
| | | return userTaskList; |
| | | } |
| | | |
| | | /** |
| | | * ä»ååå寻路ï¼è·åææè线路ä¸çç¹ |
| | | * @param source èµ·å§èç¹ |
| | | * @param passRoads å·²ç»ç»è¿çç¹éå |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param targets ç®æ è线路ç»ç¹ |
| | | * @param dirtyRoads ç¡®å®ä¸ºèæ°æ®çç¹ï¼å 为ä¸éè¦éå¤ï¼å æ¤ä½¿ç¨ set åå¨ |
| | | * @return |
| | | */ |
| | | public static Set<String> iteratorFindDirtyRoads(FlowElement source, List<String> passRoads, Set<String> hasSequenceFlow, List<String> targets, Set<String> dirtyRoads) { |
| | | passRoads = passRoads == null ? new ArrayList<>() : passRoads; |
| | | dirtyRoads = dirtyRoads == null ? new HashSet<>() : dirtyRoads; |
| | | hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
| | | |
| | | // å¦æè¯¥èç¹ä¸ºå¼å§èç¹ï¼ä¸åå¨ä¸çº§åèç¹ï¼å顺çä¸çº§åèç¹ç»§ç»è¿ä»£ |
| | | if (source instanceof StartEvent && source.getSubProcess() != null) { |
| | | dirtyRoads = iteratorFindDirtyRoads(source.getSubProcess(), passRoads, hasSequenceFlow, targets, dirtyRoads); |
| | | } |
| | | |
| | | // æ ¹æ®ç±»åï¼è·åå
¥å£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source); |
| | | |
| | | if (sequenceFlows != null) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | // æ°å¢ç»è¿ç路线 |
| | | passRoads.add(sequenceFlow.getSourceFlowElement().getId()); |
| | | // 妿æ¤ç¹ä¸ºç®æ ç¹ï¼ç¡®å®ç»è¿ç路线为èçº¿è·¯ï¼æ·»å ç¹å°è线路ä¸ï¼ç¶åæ¾ä¸ä¸ªè¿çº¿ |
| | | if (targets.contains(sequenceFlow.getSourceFlowElement().getId())) { |
| | | dirtyRoads.addAll(passRoads); |
| | | continue; |
| | | } |
| | | // å¦æè¯¥èç¹ä¸ºå¼å§èç¹ï¼ä¸åå¨ä¸çº§åèç¹ï¼å顺çä¸çº§åèç¹ç»§ç»è¿ä»£ |
| | | if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) { |
| | | dirtyRoads = findChildProcessAllDirtyRoad((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, dirtyRoads); |
| | | // æ¯å¦åå¨åæµç¨ä¸ï¼true æ¯ï¼false å¦ |
| | | Boolean isInChildProcess = dirtyTargetInChildProcess((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, targets, null); |
| | | if (isInChildProcess) { |
| | | // å·²å¨åæµç¨ä¸æ¾å°ï¼è¯¥è·¯çº¿ç»æ |
| | | continue; |
| | | } |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | dirtyRoads = iteratorFindDirtyRoads(sequenceFlow.getSourceFlowElement(), passRoads, hasSequenceFlow, targets, dirtyRoads); |
| | | } |
| | | } |
| | | return dirtyRoads; |
| | | } |
| | | |
| | | /** |
| | | * è¿ä»£è·ååæµç¨è路线 |
| | | * 说æï¼åå¦åéçç¹å°±æ¯åæµç¨ï¼é£ä¹ä¹è¯å®ä¼åéå°åæµç¨æåçç¨æ·ä»»å¡èç¹ï¼å æ¤åæµç¨ä¸çèç¹å
¨æ¯è路线 |
| | | * @param source èµ·å§èç¹ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param dirtyRoads ç¡®å®ä¸ºèæ°æ®çç¹ï¼å 为ä¸éè¦éå¤ï¼å æ¤ä½¿ç¨ set åå¨ |
| | | * @return |
| | | */ |
| | | public static Set<String> findChildProcessAllDirtyRoad(FlowElement source, Set<String> hasSequenceFlow, Set<String> dirtyRoads) { |
| | | hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
| | | dirtyRoads = dirtyRoads == null ? new HashSet<>() : dirtyRoads; |
| | | |
| | | // æ ¹æ®ç±»åï¼è·ååºå£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source); |
| | | |
| | | if (sequenceFlows != null) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | // æ·»å è路线 |
| | | dirtyRoads.add(sequenceFlow.getTargetFlowElement().getId()); |
| | | // 妿èç¹ä¸ºåæµç¨èç¹æ
åµï¼åä»èç¹ä¸ç第ä¸ä¸ªèç¹å¼å§è·å |
| | | if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) { |
| | | dirtyRoads = findChildProcessAllDirtyRoad((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, dirtyRoads); |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | dirtyRoads = findChildProcessAllDirtyRoad(sequenceFlow.getTargetFlowElement(), hasSequenceFlow, dirtyRoads); |
| | | } |
| | | } |
| | | return dirtyRoads; |
| | | } |
| | | |
| | | /** |
| | | * 夿èè·¯çº¿ç»æèç¹æ¯å¦å¨åæµç¨ä¸ |
| | | * @param source èµ·å§èç¹ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param targets 夿è路线èç¹æ¯å¦åå¨åæµç¨ä¸ï¼åªè¦åå¨ä¸ä¸ªï¼è¯´æè路线åªå°åæµç¨ä¸ºæ¢ |
| | | * @param inChildProcess æ¯å¦åå¨åæµç¨ä¸ï¼true æ¯ï¼false å¦ |
| | | * @return |
| | | */ |
| | | public static Boolean dirtyTargetInChildProcess(FlowElement source, Set<String> hasSequenceFlow, List<String> targets, Boolean inChildProcess) { |
| | | hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
| | | inChildProcess = inChildProcess == null ? false : inChildProcess; |
| | | |
| | | // æ ¹æ®ç±»åï¼è·ååºå£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source); |
| | | |
| | | if (sequenceFlows != null && !inChildProcess) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | // 妿åç°ç®æ ç¹å¨åæµç¨ä¸åå¨ï¼è¯´æåªå°åæµç¨ä¸ºæ¢ |
| | | if (targets.contains(sequenceFlow.getTargetFlowElement().getId())) { |
| | | inChildProcess = true; |
| | | break; |
| | | } |
| | | // 妿èç¹ä¸ºåæµç¨èç¹æ
åµï¼åä»èç¹ä¸ç第ä¸ä¸ªèç¹å¼å§è·å |
| | | if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) { |
| | | inChildProcess = dirtyTargetInChildProcess((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, targets, inChildProcess); |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | inChildProcess = dirtyTargetInChildProcess(sequenceFlow.getTargetFlowElement(), hasSequenceFlow, targets, inChildProcess); |
| | | } |
| | | } |
| | | return inChildProcess; |
| | | } |
| | | |
| | | /** |
| | | * è¿ä»£ä»åååæ«æï¼å¤æç®æ èç¹ç¸å¯¹äºå½åèç¹æ¯å¦æ¯ä¸²è¡ |
| | | * ä¸åå¨ç´æ¥åéå°åæµç¨ä¸çæ
åµï¼ä½åå¨ä»åæµç¨åºå»å°ç¶æµç¨æ
åµ |
| | | * @param source èµ·å§èç¹ |
| | | * @param isSequential æ¯å¦ä¸²è¡ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param targetKsy ç®æ èç¹ |
| | | * @return |
| | | */ |
| | | public static Boolean iteratorCheckSequentialReferTarget(FlowElement source, String targetKsy, Set<String> hasSequenceFlow, Boolean isSequential) { |
| | | isSequential = isSequential == null ? true : isSequential; |
| | | hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
| | | |
| | | // å¦æè¯¥èç¹ä¸ºå¼å§èç¹ï¼ä¸åå¨ä¸çº§åèç¹ï¼å顺çä¸çº§åèç¹ç»§ç»è¿ä»£ |
| | | if (source instanceof StartEvent && source.getSubProcess() != null) { |
| | | isSequential = iteratorCheckSequentialReferTarget(source.getSubProcess(), targetKsy, hasSequenceFlow, isSequential); |
| | | } |
| | | |
| | | // æ ¹æ®ç±»åï¼è·åå
¥å£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source); |
| | | |
| | | if (sequenceFlows != null) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | // å¦æç®æ èç¹å·²è¢«å¤æä¸ºå¹¶è¡ï¼åé¢é½ä¸éè¦æ§è¡ï¼ç´æ¥è¿å |
| | | if (isSequential == false) { |
| | | break; |
| | | } |
| | | // è¿æ¡çº¿è·¯åå¨ç®æ èç¹ï¼è¿æ¡çº¿è·¯å®æï¼è¿å
¥ä¸ä¸ªçº¿è·¯ |
| | | if (targetKsy.equals(sequenceFlow.getSourceFlowElement().getId())) { |
| | | continue; |
| | | } |
| | | if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) { |
| | | isSequential = false; |
| | | break; |
| | | } |
| | | // å¦å就继ç»è¿ä»£ |
| | | isSequential = iteratorCheckSequentialReferTarget(sequenceFlow.getSourceFlowElement(), targetKsy, hasSequenceFlow, isSequential); |
| | | } |
| | | } |
| | | return isSequential; |
| | | } |
| | | |
| | | /** |
| | | * ä»ååå寻路ï¼è·åå°è¾¾èç¹çææè·¯çº¿ |
| | | * ä¸åå¨ç´æ¥åéå°åæµç¨ï¼ä½æ¯åå¨åéå°ç¶çº§æµç¨çæ
åµ |
| | | * @param source èµ·å§èç¹ |
| | | * @param passRoads å·²ç»ç»è¿çç¹éå |
| | | * @param roads 路线 |
| | | * @return |
| | | */ |
| | | public static List<List<UserTask>> findRoad(FlowElement source, List<UserTask> passRoads, Set<String> hasSequenceFlow, List<List<UserTask>> roads) { |
| | | passRoads = passRoads == null ? new ArrayList<>() : passRoads; |
| | | roads = roads == null ? new ArrayList<>() : roads; |
| | | hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; |
| | | |
| | | // å¦æè¯¥èç¹ä¸ºå¼å§èç¹ï¼ä¸åå¨ä¸çº§åèç¹ï¼å顺çä¸çº§åèç¹ç»§ç»è¿ä»£ |
| | | if (source instanceof StartEvent && source.getSubProcess() != null) { |
| | | roads = findRoad(source.getSubProcess(), passRoads, hasSequenceFlow, roads); |
| | | } |
| | | |
| | | // æ ¹æ®ç±»åï¼è·åå
¥å£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source); |
| | | |
| | | if (sequenceFlows != null && sequenceFlows.size() != 0) { |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | // æ·»å ç»è¿è·¯çº¿ |
| | | if (sequenceFlow.getSourceFlowElement() instanceof UserTask) { |
| | | passRoads.add((UserTask) sequenceFlow.getSourceFlowElement()); |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | roads = findRoad(sequenceFlow.getSourceFlowElement(), passRoads, hasSequenceFlow, roads); |
| | | } |
| | | } else { |
| | | // æ·»å 路线 |
| | | roads.add(passRoads); |
| | | } |
| | | return roads; |
| | | } |
| | | |
| | | /** |
| | | * åå²èç¹æ°æ®æ¸
æ´ï¼æ¸
æ´æå忻坼è´çèæ°æ® |
| | | * @param allElements å
¨é¨èç¹ä¿¡æ¯ |
| | | * @param historicTaskInstanceList åå²ä»»å¡å®ä¾ä¿¡æ¯ï¼æ°æ®éç¨å¼å§æ¶é´ååº |
| | | * @return |
| | | */ |
| | | public static List<String> historicTaskInstanceClean(Collection<FlowElement> allElements, List<HistoricTaskInstance> historicTaskInstanceList) { |
| | | // ä¼ç¾èç¹æ¶é |
| | | List<String> multiTask = new ArrayList<>(); |
| | | allElements.forEach(flowElement -> { |
| | | if (flowElement instanceof UserTask) { |
| | | // å¦æè¯¥èç¹çè¡ä¸ºä¸ºä¼ç¾è¡ä¸ºï¼è¯´æè¯¥èç¹ä¸ºä¼ç¾èç¹ |
| | | if (((UserTask) flowElement).getBehavior() instanceof ParallelMultiInstanceBehavior || ((UserTask) flowElement).getBehavior() instanceof SequentialMultiInstanceBehavior) { |
| | | multiTask.add(flowElement.getId()); |
| | | } |
| | | } |
| | | }); |
| | | // å¾ªç¯æ¾å
¥æ ï¼æ LIFOï¼åè¿å
åº |
| | | Stack<HistoricTaskInstance> stack = new Stack<>(); |
| | | historicTaskInstanceList.forEach(item -> stack.push(item)); |
| | | // æ¸
æ´åçåå²ä»»å¡å®ä¾ |
| | | List<String> lastHistoricTaskInstanceList = new ArrayList<>(); |
| | | // ç½å
³åå¨å¯è½åªèµ°äºé¨å忝æ
åµï¼ä¸è¿åå¨è·³è½¬åºå¼æ°æ®ä»¥åå
¶ä»åæ¯æ°æ®çå¹²æ°ï¼å æ¤éè¦å¯¹åå²èç¹æ°æ®è¿è¡æ¸
æ´ |
| | | // 临æ¶ç¨æ·ä»»å¡ key |
| | | StringBuilder userTaskKey = null; |
| | | // 临æ¶è¢«å æçä»»å¡ keyï¼åå¨å¹¶è¡æ
åµ |
| | | List<String> deleteKeyList = new ArrayList<>(); |
| | | // 临æ¶èæ°æ®çº¿è·¯ |
| | | List<Set<String>> dirtyDataLineList = new ArrayList<>(); |
| | | // ç±æä¸ªç¹è·³å°ä¼ç¾ç¹,æ¤æ¶åºç°å¤ä¸ªä¼ç¾å®ä¾å¯¹åº 1 个跳转æ
åµï¼éè¦æè¿äºè¿ç»èæ°æ®é½æ¾å° |
| | | // ä¼ç¾ç¹æ®å¤ç䏿 |
| | | int multiIndex = -1; |
| | | // ä¼ç¾ç¹æ®å¤ç key |
| | | StringBuilder multiKey = null; |
| | | // ä¼ç¾ç¹æ®å¤çæä½æ è¯ |
| | | boolean multiOpera = false; |
| | | while (!stack.empty()) { |
| | | // ä»è¿éå¼å§ userTaskKey é½è¿æ¯ä¸ä¸ªæ ç key |
| | | // æ¯å¦æ¯èæ°æ®çº¿è·¯ä¸çç¹ |
| | | final boolean[] isDirtyData = {false}; |
| | | for (Set<String> oldDirtyDataLine : dirtyDataLineList) { |
| | | if (oldDirtyDataLine.contains(stack.peek().getTaskDefinitionKey())) { |
| | | isDirtyData[0] = true; |
| | | } |
| | | } |
| | | // å é¤åå ä¸ä¸ºç©ºï¼è¯´æä»è¿æ¡æ°æ®å¼å§åè·³æè
åéç |
| | | // MI_ENDï¼ä¼ç¾å®æåï¼å
¶ä»æªç¾å°èç¹çå é¤åå ï¼ä¸å¨å¤çèå´å
|
| | | if (stack.peek().getDeleteReason() != null && !stack.peek().getDeleteReason().equals("MI_END")) { |
| | | // å¯ä»¥ç解为èçº¿è·¯èµ·ç¹ |
| | | String dirtyPoint = ""; |
| | | if (stack.peek().getDeleteReason().indexOf("Change activity to ") >= 0) { |
| | | dirtyPoint = stack.peek().getDeleteReason().replace("Change activity to ", ""); |
| | | } |
| | | // ä¼ç¾åéå é¤åå æç¹ä¸å |
| | | if (stack.peek().getDeleteReason().indexOf("Change parent activity to ") >= 0) { |
| | | dirtyPoint = stack.peek().getDeleteReason().replace("Change parent activity to ", ""); |
| | | } |
| | | FlowElement dirtyTask = null; |
| | | // è·ååæ´èç¹ç对åºçå
¥å£å¤è¿çº¿ |
| | | // 妿æ¯ç½å
³å¹¶è¡åéæ
åµï¼ä¼åæä¸¤æ¡èæ°æ®è·¯çº¿ï¼ææä¸æ · |
| | | for (FlowElement flowElement : allElements) { |
| | | if (flowElement.getId().equals(stack.peek().getTaskDefinitionKey())) { |
| | | dirtyTask = flowElement; |
| | | } |
| | | } |
| | | // è·åèæ°æ®çº¿è·¯ |
| | | Set<String> dirtyDataLine = FlowableUtils.iteratorFindDirtyRoads(dirtyTask, null, null, Arrays.asList(dirtyPoint.split(",")), null); |
| | | // èªå·±æ¬èº«ä¹æ¯è线路ä¸çç¹ï¼å è¿å» |
| | | dirtyDataLine.add(stack.peek().getTaskDefinitionKey()); |
| | | log.info(stack.peek().getTaskDefinitionKey() + "ç¹è路线éåï¼" + dirtyDataLine); |
| | | // æ¯å
¨æ°çéè¦æ·»å çè线路 |
| | | boolean isNewDirtyData = true; |
| | | for (int i = 0; i < dirtyDataLineList.size(); i++) { |
| | | // 妿åç°ä»çä¸ä¸ªèç¹å¨è线路å
ï¼è¯´æè¿ä¸ªç¹å¯è½æ¯å¹¶è¡çèç¹ï¼æè
è¿ç»é©³å |
| | | // è¿æ¶ï¼é½ä»¥ä¹åçè线路èç¹ä¸ºæ åï¼åªéåå¹¶è线路å³å¯ï¼ä¹å°±æ¯è·¯çº¿è¡¥å
¨ |
| | | if (dirtyDataLineList.get(i).contains(userTaskKey.toString())) { |
| | | isNewDirtyData = false; |
| | | dirtyDataLineList.get(i).addAll(dirtyDataLine); |
| | | } |
| | | } |
| | | // å·²ç¡®å®æ¶å
¨æ°çè线路 |
| | | if (isNewDirtyData) { |
| | | // deleteKey åä¸è·¯çº¿é©³åå°å¹¶è¡ï¼è¿ç§åæ¶çæå¤ä¸ªæ°å®ä¾è®°å½æ
åµï¼è¿æ¶ deleteKey å
¶å®æ¯ç±å¤ä¸ªå¼ç»æ |
| | | // æç
§é»è¾ï¼åéåç«å»çæçå®ä¾è®°å½å°±æ¯åéçè®°å½ |
| | | // è³äºé©³åæçæç Keyï¼ç´æ¥ä»å é¤åå ä¸è·åï¼å 为åå¨é©³åå°å¹¶è¡çæ
åµ |
| | | deleteKeyList.add(dirtyPoint + ","); |
| | | dirtyDataLineList.add(dirtyDataLine); |
| | | } |
| | | // æ·»å åï¼ç°å¨è¿ä¸ªç¹åæè线路ä¸çç¹äº |
| | | isDirtyData[0] = true; |
| | | } |
| | | // 妿䏿¯è线路ä¸çç¹ï¼è¯´ææ¯æææ°æ®ï¼æ·»å åå²å®ä¾ Key |
| | | if (!isDirtyData[0]) { |
| | | lastHistoricTaskInstanceList.add(stack.peek().getTaskDefinitionKey()); |
| | | } |
| | | // æ ¡éªè线路æ¯å¦ç»æ |
| | | for (int i = 0; i < deleteKeyList.size(); i ++) { |
| | | // 妿åç°èæ°æ®å±äºä¼ç¾ï¼è®°å½ä¸ä¸æ ä¸å¯¹åº Keyï¼ä»¥å¤åç»æ¯å¯¹ï¼ä¼ç¾èæ°æ®èç´å¼å§ |
| | | if (multiKey == null && multiTask.contains(stack.peek().getTaskDefinitionKey()) |
| | | && deleteKeyList.get(i).contains(stack.peek().getTaskDefinitionKey())) { |
| | | multiIndex = i; |
| | | multiKey = new StringBuilder(stack.peek().getTaskDefinitionKey()); |
| | | } |
| | | // ä¼ç¾èæ°æ®å¤çï¼èç¹éåä¼ç¾æ¸
空 |
| | | // 妿å¨ä¼ç¾èæ°æ®èç´ä¸åç° Keyæ¹åï¼è¯´æä¼ç¾èæ°æ®å¨ä¸ä¸ªèç¹å°±ç»æäºï¼å¯ä»¥æä¼ç¾èæ°æ®å æ |
| | | if (multiKey != null && !multiKey.toString().equals(stack.peek().getTaskDefinitionKey())) { |
| | | deleteKeyList.set(multiIndex , deleteKeyList.get(multiIndex).replace(stack.peek().getTaskDefinitionKey() + ",", "")); |
| | | multiKey = null; |
| | | // ç»æè¿è¡ä¸æ ¡éªå é¤ |
| | | multiOpera = true; |
| | | } |
| | | // å
¶ä»èæ°æ®å¤ç |
| | | // åç°è¯¥è·¯çº¿æå䏿¡èæ°æ®ï¼è¯´æè¿æ¡èæ°æ®çº¿è·¯å¤çå®äºï¼å é¤èæ°æ®ä¿¡æ¯ |
| | | // èæ°æ®äº§ççæ°å®ä¾ä¸æ¯å¦å
å«è¿æ¡æ°æ® |
| | | if (multiKey == null && deleteKeyList.get(i).contains(stack.peek().getTaskDefinitionKey())) { |
| | | // å é¤å¹é
å°çé¨å |
| | | deleteKeyList.set(i , deleteKeyList.get(i).replace(stack.peek().getTaskDefinitionKey() + ",", "")); |
| | | } |
| | | // 妿æ¯ç»ä¸çå
ç´ é½ä»¥å¹é
è¿ï¼è¯´æèæ°æ®ç»æ |
| | | if ("".equals(deleteKeyList.get(i))) { |
| | | // åæ¶å é¤èæ°æ® |
| | | deleteKeyList.remove(i); |
| | | dirtyDataLineList.remove(i); |
| | | break; |
| | | } |
| | | } |
| | | // ä¼ç¾æ°æ®å¤çéè¦å¨å¾ªç¯å¤å¤çï¼å¦åå¯è½å¯¼è´æº¢åº |
| | | // ä¼ç¾çæ°æ®è¯å®æ¯ä¹åæ¾è¿å»çæä»¥ç论ä¸ä¸ä¼æº¢åºï¼ä½è¿æ¯æ ¡éªä¸ |
| | | if (multiOpera && deleteKeyList.size() > multiIndex && "".equals(deleteKeyList.get(multiIndex))) { |
| | | // åæ¶å é¤èæ°æ® |
| | | deleteKeyList.remove(multiIndex); |
| | | dirtyDataLineList.remove(multiIndex); |
| | | multiIndex = -1; |
| | | multiOpera = false; |
| | | } |
| | | // pop() æ¹æ³ä¸ peek() æ¹æ³ä¸åï¼å¨è¿åå¼çåæ¶ï¼ä¼æå¼ä»æ ä¸ç§»é¤ |
| | | // ä¿åæ°ç userTaskKey å¨ä¸ä¸ªå¾ªç¯ä¸ä½¿ç¨ |
| | | userTaskKey = new StringBuilder(stack.pop().getTaskDefinitionKey()); |
| | | } |
| | | log.info("æ¸
æ´åçåå²èç¹æ°æ®ï¼" + lastHistoricTaskInstanceList); |
| | | return lastHistoricTaskInstanceList; |
| | | } |
| | | |
| | | /** |
| | | * æ·±æéå½è·åæµç¨æªéè¿çèç¹ |
| | | * @param bpmnModel æµç¨æ¨¡å |
| | | * @param unfinishedTaskSet æªç»æçä»»å¡èç¹ |
| | | * @param finishedSequenceFlowSet å·²ç»å®æçè¿çº¿ |
| | | * @param finishedTaskSet 已宿çä»»å¡èç¹ |
| | | * @return |
| | | */ |
| | | public static Set<String> dfsFindRejects(BpmnModel bpmnModel, Set<String> unfinishedTaskSet, Set<String> finishedSequenceFlowSet, Set<String> finishedTaskSet) { |
| | | if (ObjectUtil.isNull(bpmnModel)) { |
| | | throw new ServiceException("æµç¨æ¨¡åä¸åå¨"); |
| | | } |
| | | Collection<FlowElement> allElements = getAllElements(bpmnModel.getMainProcess().getFlowElements(), null); |
| | | Set<String> rejectedSet = new HashSet<>(); |
| | | for (FlowElement flowElement : allElements) { |
| | | // ç¨æ·èç¹ä¸æªç»æå
ç´ |
| | | if (flowElement instanceof UserTask && unfinishedTaskSet.contains(flowElement.getId())) { |
| | | List<String> hasSequenceFlow = iteratorFindFinishes(flowElement, null); |
| | | List<String> rejects = iteratorFindRejects(flowElement, finishedSequenceFlowSet, finishedTaskSet, hasSequenceFlow, null); |
| | | rejectedSet.addAll(rejects); |
| | | } |
| | | } |
| | | return rejectedSet; |
| | | } |
| | | |
| | | /** |
| | | * è¿ä»£è·åç¶çº§èç¹å表ï¼ååæ¾ |
| | | * @param source èµ·å§èç¹ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿çIDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @return |
| | | */ |
| | | public static List<String> iteratorFindFinishes(FlowElement source, List<String> hasSequenceFlow) { |
| | | hasSequenceFlow = hasSequenceFlow == null ? new ArrayList<>() : hasSequenceFlow; |
| | | |
| | | // æ ¹æ®ç±»åï¼è·åå
¥å£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source); |
| | | |
| | | if (sequenceFlows != null) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | FlowElement finishedElement = sequenceFlow.getSourceFlowElement(); |
| | | // ç±»åä¸ºåæµç¨ï¼åæ·»å åæµç¨å¼å§èç¹åºå£å¤ç¸è¿çèç¹ |
| | | if (finishedElement instanceof SubProcess) { |
| | | FlowElement firstElement = (StartEvent) ((SubProcess) finishedElement).getFlowElements().toArray()[0]; |
| | | // è·ååæµç¨çè¿çº¿ |
| | | hasSequenceFlow.addAll(iteratorFindFinishes(firstElement, null)); |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | hasSequenceFlow = iteratorFindFinishes(finishedElement, hasSequenceFlow); |
| | | } |
| | | } |
| | | return hasSequenceFlow; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ£å¨è¿è¡çä»»å¡èç¹ï¼è¿ä»£è·åå级任å¡èç¹å表ï¼ååæ¾ |
| | | * @param source èµ·å§èç¹ |
| | | * @param finishedSequenceFlowSet å·²ç»å®æçè¿çº¿ |
| | | * @param finishedTaskSet å·²ç»å®æçä»»å¡èç¹ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param rejectedList æªéè¿çå
ç´ |
| | | * @return |
| | | */ |
| | | public static List<String> iteratorFindRejects(FlowElement source, Set<String> finishedSequenceFlowSet, Set<String> finishedTaskSet |
| | | , List<String> hasSequenceFlow, List<String> rejectedList) { |
| | | hasSequenceFlow = hasSequenceFlow == null ? new ArrayList<>() : hasSequenceFlow; |
| | | rejectedList = rejectedList == null ? new ArrayList<>() : rejectedList; |
| | | |
| | | // æ ¹æ®ç±»åï¼è·ååºå£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source); |
| | | |
| | | if (sequenceFlows != null) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | FlowElement targetElement = sequenceFlow.getTargetFlowElement(); |
| | | // æ·»å æªå®æçèç¹ |
| | | if (finishedTaskSet.contains(targetElement.getId())) { |
| | | rejectedList.add(targetElement.getId()); |
| | | } |
| | | // æ·»å æªå®æçè¿çº¿ |
| | | if (finishedSequenceFlowSet.contains(sequenceFlow.getId())) { |
| | | rejectedList.add(sequenceFlow.getId()); |
| | | } |
| | | // 妿èç¹ä¸ºåæµç¨èç¹æ
åµï¼åä»èç¹ä¸ç第ä¸ä¸ªèç¹å¼å§è·å |
| | | if (targetElement instanceof SubProcess) { |
| | | FlowElement firstElement = (FlowElement) (((SubProcess) targetElement).getFlowElements().toArray()[0]); |
| | | List<String> childList = iteratorFindRejects(firstElement, finishedSequenceFlowSet, finishedTaskSet, hasSequenceFlow, null); |
| | | // 妿æ¾å°èç¹ï¼å说æè¯¥çº¿è·¯æ¾å°èç¹ï¼ä¸ç»§ç»å䏿¾ï¼åä¹ç»§ç» |
| | | if (childList != null && childList.size() > 0) { |
| | | rejectedList.addAll(childList); |
| | | continue; |
| | | } |
| | | } |
| | | // ç»§ç»è¿ä»£ |
| | | rejectedList = iteratorFindRejects(targetElement, finishedSequenceFlowSet, finishedTaskSet, hasSequenceFlow, rejectedList); |
| | | } |
| | | } |
| | | return rejectedList; |
| | | } |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.listener; |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import org.ruoyi.flowable.common.constant.ProcessConstants; |
| | | |
| | | import org.ruoyi.flowable.common.enums.ProcessStatus; |
| | | import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent; |
| | | import org.flowable.engine.RuntimeService; |
| | | import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | /** |
| | | * Flowable å
¨å±çå¬å¨ |
| | | * |
| | | * @author konbai |
| | | * @since 2023/3/8 22:45 |
| | | */ |
| | | @Component |
| | | public class GlobalEventListener extends AbstractFlowableEngineEventListener { |
| | | |
| | | @Autowired |
| | | private RuntimeService runtimeService; |
| | | |
| | | /** |
| | | * æµç¨ç»æçå¬å¨ |
| | | */ |
| | | @Override |
| | | protected void processCompleted(FlowableEngineEntityEvent event) { |
| | | String processInstanceId = event.getProcessInstanceId(); |
| | | Object variable = runtimeService.getVariable(processInstanceId, ProcessConstants.PROCESS_STATUS_KEY); |
| | | ProcessStatus status = ProcessStatus.getProcessStatus(Convert.toStr(variable)); |
| | | if (ObjectUtil.isNotNull(status) && ProcessStatus.RUNNING == status) { |
| | | runtimeService.setVariable(processInstanceId, ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.COMPLETED.getStatus()); |
| | | } |
| | | super.processCompleted(event); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.listener; |
| | | |
| | | import org.flowable.engine.delegate.TaskListener; |
| | | import org.flowable.task.service.delegate.DelegateTask; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | /** |
| | | * ç¨æ·ä»»å¡çå¬å¨ |
| | | * |
| | | * @author KonBAI |
| | | * @since 2023/5/13 |
| | | */ |
| | | @Component(value = "userTaskListener") |
| | | public class UserTaskListener implements TaskListener { |
| | | |
| | | /** |
| | | * 注å
¥å段ï¼åç§°ä¸æµç¨è®¾è®¡æ¶å段åç§°ä¸è´ï¼ |
| | | */ |
| | | // private FixedValue field; |
| | | |
| | | @Override |
| | | public void notify(DelegateTask delegateTask) { |
| | | //TODO å®ç°ä½ çä»»å¡çå¬å¨é»è¾ |
| | | System.out.println("æ§è¡ä»»å¡çå¬å¨..."); |
| | | } |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.utils; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.lang.SimpleCache; |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.ruoyi.common.core.utils.StreamUtils; |
| | | import org.springframework.cglib.beans.BeanCopier; |
| | | import org.springframework.cglib.beans.BeanMap; |
| | | import org.springframework.cglib.core.Converter; |
| | | |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * beanæ·±æ·è´å·¥å
·(åºäº cglib æ§è½ä¼å¼) |
| | | * <p> |
| | | * éç¹ cglib 䏿¯æ æ·è´å°é¾å¼å¯¹è±¡ |
| | | * ä¾å¦: æºå¯¹è±¡ æ·è´å° ç®æ (é¾å¼å¯¹è±¡) |
| | | * 请åºå好`æµ
æ·è´`å`æ·±æ·è´`ååä½¿ç¨ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class BeanCopyUtils { |
| | | |
| | | /** |
| | | * å对象åºäºclasså建æ·è´ |
| | | * |
| | | * @param source æ°æ®æ¥æºå®ä½ |
| | | * @param desc æè¿°å¯¹è±¡ 转æ¢åç对象 |
| | | * @return desc |
| | | */ |
| | | public static <T, V> V copy(T source, Class<V> desc) { |
| | | if (ObjectUtil.isNull(source)) { |
| | | return null; |
| | | } |
| | | if (ObjectUtil.isNull(desc)) { |
| | | return null; |
| | | } |
| | | final V target = ReflectUtil.newInstanceIfPossible(desc); |
| | | return copy(source, target); |
| | | } |
| | | |
| | | /** |
| | | * å对象åºäºå¯¹è±¡å建æ·è´ |
| | | * |
| | | * @param source æ°æ®æ¥æºå®ä½ |
| | | * @param desc 转æ¢åç对象 |
| | | * @return desc |
| | | */ |
| | | public static <T, V> V copy(T source, V desc) { |
| | | if (ObjectUtil.isNull(source)) { |
| | | return null; |
| | | } |
| | | if (ObjectUtil.isNull(desc)) { |
| | | return null; |
| | | } |
| | | BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null); |
| | | beanCopier.copy(source, desc, null); |
| | | return desc; |
| | | } |
| | | |
| | | /** |
| | | * å表对象åºäºclasså建æ·è´ |
| | | * |
| | | * @param sourceList æ°æ®æ¥æºå®ä½å表 |
| | | * @param desc æè¿°å¯¹è±¡ 转æ¢åç对象 |
| | | * @return desc |
| | | */ |
| | | public static <T, V> List<V> copyList(List<T> sourceList, Class<V> desc) { |
| | | if (ObjectUtil.isNull(sourceList)) { |
| | | return null; |
| | | } |
| | | if (CollUtil.isEmpty(sourceList)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return StreamUtils.toList(sourceList, source -> { |
| | | V target = ReflectUtil.newInstanceIfPossible(desc); |
| | | copy(source, target); |
| | | return target; |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * beanæ·è´å°map |
| | | * |
| | | * @param bean æ°æ®æ¥æºå®ä½ |
| | | * @return map对象 |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <T> Map<String, Object> copyToMap(T bean) { |
| | | if (ObjectUtil.isNull(bean)) { |
| | | return null; |
| | | } |
| | | return BeanMap.create(bean); |
| | | } |
| | | |
| | | /** |
| | | * mapæ·è´å°bean |
| | | * |
| | | * @param map æ°æ®æ¥æº |
| | | * @param beanClass beanç±» |
| | | * @return bean对象 |
| | | */ |
| | | public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) { |
| | | if (MapUtil.isEmpty(map)) { |
| | | return null; |
| | | } |
| | | if (ObjectUtil.isNull(beanClass)) { |
| | | return null; |
| | | } |
| | | T bean = ReflectUtil.newInstanceIfPossible(beanClass); |
| | | return mapToBean(map, bean); |
| | | } |
| | | |
| | | /** |
| | | * mapæ·è´å°bean |
| | | * |
| | | * @param map æ°æ®æ¥æº |
| | | * @param bean bean对象 |
| | | * @return bean对象 |
| | | */ |
| | | public static <T> T mapToBean(Map<String, Object> map, T bean) { |
| | | if (MapUtil.isEmpty(map)) { |
| | | return null; |
| | | } |
| | | if (ObjectUtil.isNull(bean)) { |
| | | return null; |
| | | } |
| | | BeanMap.create(bean).putAll(map); |
| | | return bean; |
| | | } |
| | | |
| | | /** |
| | | * mapæ·è´å°map |
| | | * |
| | | * @param map æ°æ®æ¥æº |
| | | * @param clazz è¿åç对象类å |
| | | * @return map对象 |
| | | */ |
| | | public static <T, V> Map<String, V> mapToMap(Map<String, T> map, Class<V> clazz) { |
| | | if (MapUtil.isEmpty(map)) { |
| | | return null; |
| | | } |
| | | if (ObjectUtil.isNull(clazz)) { |
| | | return null; |
| | | } |
| | | Map<String, V> copyMap = new LinkedHashMap<>(map.size()); |
| | | map.forEach((k, v) -> copyMap.put(k, copy(v, clazz))); |
| | | return copyMap; |
| | | } |
| | | |
| | | /** |
| | | * BeanCopier屿§ç¼å<br> |
| | | * ç¼åç¨äºé²æ¢å¤æ¬¡åå°é æçæ§è½é®é¢ |
| | | * |
| | | * @author Looly |
| | | * @since 5.4.1 |
| | | */ |
| | | public enum BeanCopierCache { |
| | | /** |
| | | * BeanCopier屿§ç¼ååä¾ |
| | | */ |
| | | INSTANCE; |
| | | |
| | | private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>(); |
| | | |
| | | /** |
| | | * è·å¾ç±»ä¸è½¬æ¢å¨çæçkeyå¨{@link BeanCopier}çMapä¸å¯¹åºçå
ç´ |
| | | * |
| | | * @param srcClass æºBeançç±» |
| | | * @param targetClass ç®æ Beançç±» |
| | | * @param converter 转æ¢å¨ |
| | | * @return Mapä¸å¯¹åºçBeanCopier |
| | | */ |
| | | public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Converter converter) { |
| | | final String key = genKey(srcClass, targetClass, converter); |
| | | return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null)); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç±»ä¸è½¬æ¢å¨çæçkey |
| | | * |
| | | * @param srcClass æºBeançç±» |
| | | * @param targetClass ç®æ Beançç±» |
| | | * @param converter 转æ¢å¨ |
| | | * @return 屿§ååMapæ å°çkey |
| | | */ |
| | | private String genKey(Class<?> srcClass, Class<?> targetClass, Converter converter) { |
| | | final StringBuilder key = StrUtil.builder() |
| | | .append(srcClass.getName()).append('#').append(targetClass.getName()); |
| | | if (null != converter) { |
| | | key.append('#').append(converter.getClass().getName()); |
| | | } |
| | | return key.toString(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.utils; |
| | | |
| | | |
| | | import cn.hutool.core.lang.Dict; |
| | | import cn.hutool.core.util.ArrayUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.fasterxml.jackson.databind.exc.MismatchedInputException; |
| | | import org.ruoyi.common.core.utils.SpringUtils; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * JSON å·¥å
·ç±» |
| | | * |
| | | * @author èéæºç |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class JsonUtils { |
| | | |
| | | private static final ObjectMapper OBJECT_MAPPER = SpringUtils.getBean(ObjectMapper.class); |
| | | |
| | | public static ObjectMapper getObjectMapper() { |
| | | return OBJECT_MAPPER; |
| | | } |
| | | |
| | | public static String toJsonString(Object object) { |
| | | if (ObjectUtil.isNull(object)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.writeValueAsString(object); |
| | | } catch (JsonProcessingException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | public static <T> T parseObject(String text, Class<T> clazz) { |
| | | if (StringUtils.isEmpty(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, clazz); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | public static <T> T parseObject(byte[] bytes, Class<T> clazz) { |
| | | if (ArrayUtil.isEmpty(bytes)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(bytes, clazz); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | public static <T> T parseObject(String text, TypeReference<T> typeReference) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, typeReference); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | public static Dict parseMap(String text) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType(Dict.class)); |
| | | } catch (MismatchedInputException e) { |
| | | // ç±»åä¸å¹é
说æä¸æ¯json |
| | | return null; |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | public static List<Dict> parseArrayMap(String text) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, Dict.class)); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | public static <T> List<T> parseArray(String text, Class<T> clazz) { |
| | | if (StringUtils.isEmpty(text)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz)); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.utils; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import org.flowable.bpmn.converter.BpmnXMLConverter; |
| | | import org.flowable.bpmn.model.Process; |
| | | import org.flowable.bpmn.model.*; |
| | | import org.flowable.common.engine.impl.util.io.StringStreamSource; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/3/26 19:04 |
| | | */ |
| | | public class ModelUtils { |
| | | |
| | | private static final BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter(); |
| | | |
| | | /** |
| | | * xml转bpmnModel对象 |
| | | * |
| | | * @param xml xml |
| | | * @return bpmnModel对象 |
| | | */ |
| | | public static BpmnModel getBpmnModel(String xml) { |
| | | return bpmnXMLConverter.convertToBpmnModel(new StringStreamSource(xml), false, false); |
| | | } |
| | | |
| | | /** |
| | | * bpmnModel转xmlå符串 |
| | | * |
| | | * @deprecated åå¨ä¼ä¸¢å¤± bpmn è¿çº¿é®é¢ |
| | | * @param bpmnModel bpmnModel对象 |
| | | * @return xmlå符串 |
| | | */ |
| | | @Deprecated |
| | | public static String getBpmnXmlStr(BpmnModel bpmnModel) { |
| | | return StrUtil.utf8Str(getBpmnXml(bpmnModel)); |
| | | } |
| | | |
| | | /** |
| | | * bpmnModel转xml对象 |
| | | * |
| | | * @deprecated åå¨ä¸¢å¤± bpmn è¿çº¿é®é¢ |
| | | * @param bpmnModel bpmnModel对象 |
| | | * @return xml |
| | | */ |
| | | @Deprecated |
| | | public static byte[] getBpmnXml(BpmnModel bpmnModel) { |
| | | return bpmnXMLConverter.convertToXML(bpmnModel); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®èç¹ï¼è·åå
¥å£è¿çº¿ |
| | | * |
| | | * @param source èµ·å§èç¹ |
| | | * @return å
¥å£è¿çº¿å表 |
| | | */ |
| | | public static List<SequenceFlow> getElementIncomingFlows(FlowElement source) { |
| | | List<SequenceFlow> sequenceFlows = new ArrayList<>(); |
| | | if (source instanceof FlowNode) { |
| | | sequenceFlows = ((FlowNode) source).getIncomingFlows(); |
| | | } |
| | | return sequenceFlows; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * æ ¹æ®èç¹ï¼è·ååºå£è¿çº¿ |
| | | * |
| | | * @param source èµ·å§èç¹ |
| | | * @return åºå£è¿çº¿å表 |
| | | */ |
| | | public static List<SequenceFlow> getElementOutgoingFlows(FlowElement source) { |
| | | List<SequenceFlow> sequenceFlows = new ArrayList<>(); |
| | | if (source instanceof FlowNode) { |
| | | sequenceFlows = ((FlowNode) source).getOutgoingFlows(); |
| | | } |
| | | return sequenceFlows; |
| | | } |
| | | |
| | | /** |
| | | * è·åå¼å§èç¹ |
| | | * |
| | | * @param model bpmnModel对象 |
| | | * @return å¼å§èç¹ï¼æªæ¾å°å¼å§èç¹ï¼è¿ånullï¼ |
| | | */ |
| | | public static StartEvent getStartEvent(BpmnModel model) { |
| | | Process process = model.getMainProcess(); |
| | | FlowElement startElement = process.getInitialFlowElement(); |
| | | if (startElement instanceof StartEvent) { |
| | | return (StartEvent) startElement; |
| | | } |
| | | return getStartEvent(process.getFlowElements()); |
| | | } |
| | | |
| | | /** |
| | | * è·åå¼å§èç¹ |
| | | * |
| | | * @param flowElements æµç¨å
ç´ éå |
| | | * @return å¼å§èç¹ï¼æªæ¾å°å¼å§èç¹ï¼è¿ånullï¼ |
| | | */ |
| | | public static StartEvent getStartEvent(Collection<FlowElement> flowElements) { |
| | | for (FlowElement flowElement : flowElements) { |
| | | if (flowElement instanceof StartEvent) { |
| | | return (StartEvent) flowElement; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * è·åç»æèç¹ |
| | | * |
| | | * @param model bpmnModel对象 |
| | | * @return ç»æèç¹ï¼æªæ¾å°å¼å§èç¹ï¼è¿ånullï¼ |
| | | */ |
| | | public static EndEvent getEndEvent(BpmnModel model) { |
| | | Process process = model.getMainProcess(); |
| | | return getEndEvent(process.getFlowElements()); |
| | | } |
| | | |
| | | /** |
| | | * è·åç»æèç¹ |
| | | * |
| | | * @param flowElements æµç¨å
ç´ éå |
| | | * @return ç»æèç¹ï¼æªæ¾å°å¼å§èç¹ï¼è¿ånullï¼ |
| | | */ |
| | | public static EndEvent getEndEvent(Collection<FlowElement> flowElements) { |
| | | for (FlowElement flowElement : flowElements) { |
| | | if (flowElement instanceof EndEvent) { |
| | | return (EndEvent) flowElement; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static UserTask getUserTaskByKey(BpmnModel model, String taskKey) { |
| | | Process process = model.getMainProcess(); |
| | | FlowElement flowElement = process.getFlowElement(taskKey); |
| | | if (flowElement instanceof UserTask) { |
| | | return (UserTask) flowElement; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨å
ç´ ä¿¡æ¯ |
| | | * |
| | | * @param model bpmnModel对象 |
| | | * @param flowElementId å
ç´ ID |
| | | * @return å
ç´ ä¿¡æ¯ |
| | | */ |
| | | public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) { |
| | | Process process = model.getMainProcess(); |
| | | return process.getFlowElement(flowElementId); |
| | | } |
| | | |
| | | /** |
| | | * è·åå
ç´ è¡¨åKeyï¼éå¼å§èç¹åç¨æ·èç¹å¯ç¨ï¼ |
| | | * |
| | | * @param flowElement å
ç´ |
| | | * @return 表åKey |
| | | */ |
| | | public static String getFormKey(FlowElement flowElement) { |
| | | if (flowElement != null) { |
| | | if (flowElement instanceof StartEvent) { |
| | | return ((StartEvent) flowElement).getFormKey(); |
| | | } else if (flowElement instanceof UserTask) { |
| | | return ((UserTask) flowElement).getFormKey(); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * è·åå¼å§èç¹å±æ§å¼ |
| | | * @param model bpmnModel对象 |
| | | * @param name 屿§å |
| | | * @return 屿§å¼ |
| | | */ |
| | | public static String getStartEventAttributeValue(BpmnModel model, String name) { |
| | | StartEvent startEvent = getStartEvent(model); |
| | | return getElementAttributeValue(startEvent, name); |
| | | } |
| | | |
| | | /** |
| | | * è·åç»æèç¹å±æ§å¼ |
| | | * @param model bpmnModel对象 |
| | | * @param name 屿§å |
| | | * @return 屿§å¼ |
| | | */ |
| | | public static String getEndEventAttributeValue(BpmnModel model, String name) { |
| | | EndEvent endEvent = getEndEvent(model); |
| | | return getElementAttributeValue(endEvent, name); |
| | | } |
| | | |
| | | /** |
| | | * è·åç¨æ·ä»»å¡èç¹å±æ§å¼ |
| | | * @param model bpmnModel对象 |
| | | * @param taskKey ä»»å¡Key |
| | | * @param name 屿§å |
| | | * @return 屿§å¼ |
| | | */ |
| | | public static String getUserTaskAttributeValue(BpmnModel model, String taskKey, String name) { |
| | | UserTask userTask = getUserTaskByKey(model, taskKey); |
| | | return getElementAttributeValue(userTask, name); |
| | | } |
| | | |
| | | /** |
| | | * è·åå
ç´ å±æ§å¼ |
| | | * @param baseElement æµç¨å
ç´ |
| | | * @param name 屿§å |
| | | * @return 屿§å¼ |
| | | */ |
| | | public static String getElementAttributeValue(BaseElement baseElement, String name) { |
| | | if (baseElement != null) { |
| | | List<ExtensionAttribute> attributes = baseElement.getAttributes().get(name); |
| | | if (attributes != null && !attributes.isEmpty()) { |
| | | attributes.iterator().next().getValue(); |
| | | Iterator<ExtensionAttribute> attrIterator = attributes.iterator(); |
| | | if(attrIterator.hasNext()) { |
| | | ExtensionAttribute attribute = attrIterator.next(); |
| | | return attribute.getValue(); |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static boolean isMultiInstance(BpmnModel model, String taskKey) { |
| | | UserTask userTask = getUserTaskByKey(model, taskKey); |
| | | if (ObjectUtil.isNotNull(userTask)) { |
| | | return userTask.hasMultiInstanceLoopCharacteristics(); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * è·åææç¨æ·ä»»å¡èç¹ |
| | | * |
| | | * @param model bpmnModel对象 |
| | | * @return ç¨æ·ä»»å¡èç¹å表 |
| | | */ |
| | | public static Collection<UserTask> getAllUserTaskEvent(BpmnModel model) { |
| | | Process process = model.getMainProcess(); |
| | | Collection<FlowElement> flowElements = process.getFlowElements(); |
| | | return getAllUserTaskEvent(flowElements, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åææç¨æ·ä»»å¡èç¹ |
| | | * @param flowElements æµç¨å
ç´ éå |
| | | * @param allElements æææµç¨å
ç´ éå |
| | | * @return ç¨æ·ä»»å¡èç¹å表 |
| | | */ |
| | | public static Collection<UserTask> getAllUserTaskEvent(Collection<FlowElement> flowElements, Collection<UserTask> allElements) { |
| | | allElements = allElements == null ? new ArrayList<>() : allElements; |
| | | for (FlowElement flowElement : flowElements) { |
| | | if (flowElement instanceof UserTask) { |
| | | allElements.add((UserTask) flowElement); |
| | | } |
| | | if (flowElement instanceof SubProcess) { |
| | | // ç»§ç»æ·±å
¥åæµç¨ï¼è¿ä¸æ¥è·ååæµç¨ |
| | | allElements = getAllUserTaskEvent(((SubProcess) flowElement).getFlowElements(), allElements); |
| | | } |
| | | } |
| | | return allElements; |
| | | } |
| | | |
| | | /** |
| | | * æ¥æ¾èµ·å§èç¹ä¸ä¸ä¸ªç¨æ·ä»»å¡å表å表 |
| | | * @param source èµ·å§èç¹ |
| | | * @return ç»æ |
| | | */ |
| | | public static List<UserTask> findNextUserTasks(FlowElement source) { |
| | | return findNextUserTasks(source, null, null); |
| | | } |
| | | |
| | | /** |
| | | * æ¥æ¾èµ·å§èç¹ä¸ä¸ä¸ªç¨æ·ä»»å¡å表å表 |
| | | * @param source èµ·å§èç¹ |
| | | * @param hasSequenceFlow å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @param userTaskList ç¨æ·ä»»å¡å表 |
| | | * @return ç»æ |
| | | */ |
| | | public static List<UserTask> findNextUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) { |
| | | hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>()); |
| | | userTaskList = Optional.ofNullable(userTaskList).orElse(new ArrayList<>()); |
| | | // è·ååºå£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source); |
| | | if (!sequenceFlows.isEmpty()) { |
| | | for (SequenceFlow sequenceFlow : sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (hasSequenceFlow.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | hasSequenceFlow.add(sequenceFlow.getId()); |
| | | FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement(); |
| | | if (targetFlowElement instanceof UserTask) { |
| | | // è¥èç¹ä¸ºç¨æ·ä»»å¡ï¼å å
¥å°ç»æåè¡¨ä¸ |
| | | userTaskList.add((UserTask) targetFlowElement); |
| | | } else { |
| | | // è¥èç¹éç¨æ·ä»»å¡ï¼ç»§ç»é彿¥æ¾ä¸ä¸ä¸ªèç¹ |
| | | findNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList); |
| | | } |
| | | } |
| | | } |
| | | return userTaskList; |
| | | } |
| | | |
| | | /** |
| | | * è¿ä»£ä»åååæ«æï¼å¤æç®æ èç¹ç¸å¯¹äºå½åèç¹æ¯å¦æ¯ä¸²è¡ |
| | | * ä¸åå¨ç´æ¥åéå°åæµç¨ä¸çæ
åµï¼ä½åå¨ä»åæµç¨åºå»å°ç¶æµç¨æ
åµ |
| | | * @param source èµ·å§èç¹ |
| | | * @param target ç®æ èç¹ |
| | | * @param visitedElements å·²ç»ç»è¿çè¿çº¿ç IDï¼ç¨äºå¤æçº¿è·¯æ¯å¦éå¤ |
| | | * @return ç»æ |
| | | */ |
| | | public static boolean isSequentialReachable(FlowElement source, FlowElement target, Set<String> visitedElements) { |
| | | visitedElements = visitedElements == null ? new HashSet<>() : visitedElements; |
| | | if (source instanceof StartEvent && isInEventSubprocess(source)) { |
| | | return false; |
| | | } |
| | | |
| | | // æ ¹æ®ç±»åï¼è·åå
¥å£è¿çº¿ |
| | | List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source); |
| | | if (sequenceFlows != null && sequenceFlows.size() > 0) { |
| | | // å¾ªç¯æ¾å°ç®æ å
ç´ |
| | | for (SequenceFlow sequenceFlow: sequenceFlows) { |
| | | // 妿åç°è¿çº¿éå¤ï¼è¯´æå¾ªç¯äºï¼è·³è¿è¿ä¸ªå¾ªç¯ |
| | | if (visitedElements.contains(sequenceFlow.getId())) { |
| | | continue; |
| | | } |
| | | // æ·»å å·²ç»èµ°è¿çè¿çº¿ |
| | | visitedElements.add(sequenceFlow.getId()); |
| | | FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement(); |
| | | // è¿æ¡çº¿è·¯åå¨ç®æ èç¹ï¼è¿æ¡çº¿è·¯å®æï¼è¿å
¥ä¸ä¸ªçº¿è·¯ |
| | | if (target.getId().equals(sourceFlowElement.getId())) { |
| | | continue; |
| | | } |
| | | // å¦æç®æ èç¹ä¸ºå¹¶è¡ç½å
³ï¼åä¸ç»§ç» |
| | | if (sourceFlowElement instanceof ParallelGateway) { |
| | | return false; |
| | | } |
| | | // å¦å就继ç»è¿ä»£ |
| | | boolean isSequential = isSequentialReachable(sourceFlowElement, target, visitedElements); |
| | | if (!isSequential) { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | protected static boolean isInEventSubprocess(FlowElement flowElement) { |
| | | FlowElementsContainer flowElementsContainer = flowElement.getParentContainer(); |
| | | while (flowElementsContainer != null) { |
| | | if (flowElementsContainer instanceof EventSubProcess) { |
| | | return true; |
| | | } |
| | | |
| | | if (flowElementsContainer instanceof FlowElement) { |
| | | flowElementsContainer = ((FlowElement) flowElementsContainer).getParentContainer(); |
| | | } else { |
| | | flowElementsContainer = null; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.utils; |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import org.ruoyi.flowable.core.FormConf; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æµç¨è¡¨åå·¥å
·ç±» |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/8/7 17:09 |
| | | */ |
| | | public class ProcessFormUtils { |
| | | |
| | | private static final String CONFIG = "__config__"; |
| | | private static final String MODEL = "__vModel__"; |
| | | |
| | | /** |
| | | * å¡«å
表å项å
容 |
| | | * |
| | | * @param formConf 表åé
ç½®ä¿¡æ¯ |
| | | * @param data 表åå
容 |
| | | */ |
| | | public static void fillFormData(FormConf formConf, Map<String, Object> data) { |
| | | for (Map<String, Object> field : formConf.getFields()) { |
| | | recursiveFillField(field, data); |
| | | } |
| | | } |
| | | |
| | | @SuppressWarnings("unchecked") |
| | | private static void recursiveFillField(final Map<String, Object> field, final Map<String, Object> data) { |
| | | if (!field.containsKey(CONFIG)) { |
| | | return; |
| | | } |
| | | Map<String, Object> configMap = (Map<String, Object>) field.get(CONFIG); |
| | | if (configMap.containsKey("children")) { |
| | | List<Map<String, Object>> childrens = (List<Map<String, Object>>) configMap.get("children"); |
| | | for (Map<String, Object> children : childrens) { |
| | | recursiveFillField(children, data); |
| | | } |
| | | } |
| | | String modelKey = Convert.toStr(field.get(MODEL)); |
| | | Object value = data.get(modelKey); |
| | | if (value != null) { |
| | | configMap.put("defaultValue", value); |
| | | } |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.utils; |
| | | |
| | | import org.ruoyi.common.core.utils.DateUtils; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.flowable.core.domain.ProcessQuery; |
| | | import org.flowable.common.engine.api.query.Query; |
| | | import org.flowable.common.engine.impl.db.SuspensionState; |
| | | import org.flowable.engine.history.HistoricProcessInstanceQuery; |
| | | import org.flowable.engine.repository.ProcessDefinitionQuery; |
| | | import org.flowable.task.api.TaskQuery; |
| | | import org.flowable.task.api.history.HistoricTaskInstanceQuery; |
| | | |
| | | import java.util.Collections; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æµç¨å·¥å
·ç±» |
| | | * |
| | | * @author konbai |
| | | * @since 2022/12/11 03:35 |
| | | */ |
| | | public class ProcessUtils { |
| | | |
| | | public static void buildProcessSearch(Query<?, ?> query, ProcessQuery process) { |
| | | if (query instanceof ProcessDefinitionQuery) { |
| | | buildProcessDefinitionSearch((ProcessDefinitionQuery) query, process); |
| | | } else if (query instanceof TaskQuery) { |
| | | buildTaskSearch((TaskQuery) query, process); |
| | | } else if (query instanceof HistoricTaskInstanceQuery) { |
| | | buildHistoricTaskInstanceSearch((HistoricTaskInstanceQuery) query, process); |
| | | } else if (query instanceof HistoricProcessInstanceQuery) { |
| | | buildHistoricProcessInstanceSearch((HistoricProcessInstanceQuery) query, process); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æå»ºæµç¨å®ä¹æç´¢ |
| | | */ |
| | | public static void buildProcessDefinitionSearch(ProcessDefinitionQuery query, ProcessQuery process) { |
| | | // æµç¨æ è¯ |
| | | if (StringUtils.isNotBlank(process.getProcessKey())) { |
| | | query.processDefinitionKeyLike("%" + process.getProcessKey() + "%"); |
| | | } |
| | | // æµç¨åç§° |
| | | if (StringUtils.isNotBlank(process.getProcessName())) { |
| | | query.processDefinitionNameLike("%" + process.getProcessName() + "%"); |
| | | } |
| | | // æµç¨åç±» |
| | | if (StringUtils.isNotBlank(process.getCategory())) { |
| | | query.processDefinitionCategory(process.getCategory()); |
| | | } |
| | | // æµç¨ç¶æ |
| | | if (StringUtils.isNotBlank(process.getState())) { |
| | | if (SuspensionState.ACTIVE.toString().equals(process.getState())) { |
| | | query.active(); |
| | | } else if (SuspensionState.SUSPENDED.toString().equals(process.getState())) { |
| | | query.suspended(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æå»ºä»»å¡æç´¢ |
| | | */ |
| | | public static void buildTaskSearch(TaskQuery query, ProcessQuery process) { |
| | | Map<String, Object> params = process.getParams(); |
| | | if (StringUtils.isNotBlank(process.getProcessKey())) { |
| | | query.processDefinitionKeyLike("%" + process.getProcessKey() + "%"); |
| | | } |
| | | if (StringUtils.isNotBlank(process.getProcessName())) { |
| | | query.processDefinitionNameLike("%" + process.getProcessName() + "%"); |
| | | } |
| | | if (params.get("beginTime") != null && params.get("endTime") != null) { |
| | | query.taskCreatedAfter(DateUtils.parseDate(params.get("beginTime"))); |
| | | query.taskCreatedBefore(DateUtils.parseDate(params.get("endTime"))); |
| | | } |
| | | // æµç¨åç±» |
| | | if (StringUtils.isNotBlank(process.getCategory())) { |
| | | query.processCategoryIn(Collections.singleton(process.getCategory())); |
| | | } |
| | | } |
| | | |
| | | private static void buildHistoricTaskInstanceSearch(HistoricTaskInstanceQuery query, ProcessQuery process) { |
| | | Map<String, Object> params = process.getParams(); |
| | | if (StringUtils.isNotBlank(process.getProcessKey())) { |
| | | query.processDefinitionKeyLike("%" + process.getProcessKey() + "%"); |
| | | } |
| | | if (StringUtils.isNotBlank(process.getProcessName())) { |
| | | query.processDefinitionNameLike("%" + process.getProcessName() + "%"); |
| | | } |
| | | if (params.get("beginTime") != null && params.get("endTime") != null) { |
| | | query.taskCompletedAfter(DateUtils.parseDate(params.get("beginTime"))); |
| | | query.taskCompletedBefore(DateUtils.parseDate(params.get("endTime"))); |
| | | } |
| | | // æµç¨åç±» |
| | | if (StringUtils.isNotBlank(process.getCategory())) { |
| | | query.processCategoryIn(Collections.singleton(process.getCategory())); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æå»ºå岿µç¨å®ä¾æç´¢ |
| | | */ |
| | | public static void buildHistoricProcessInstanceSearch(HistoricProcessInstanceQuery query, ProcessQuery process) { |
| | | Map<String, Object> params = process.getParams(); |
| | | // æµç¨æ è¯ |
| | | if (StringUtils.isNotBlank(process.getProcessKey())) { |
| | | query.processDefinitionKey(process.getProcessKey()); |
| | | } |
| | | // æµç¨åç§° |
| | | if (StringUtils.isNotBlank(process.getProcessName())) { |
| | | query.processDefinitionName(process.getProcessName()); |
| | | } |
| | | // æµç¨åç§° |
| | | if (StringUtils.isNotBlank(process.getCategory())) { |
| | | query.processDefinitionCategory(process.getCategory()); |
| | | } |
| | | if (params.get("beginTime") != null && params.get("endTime") != null) { |
| | | query.startedAfter(DateUtils.parseDate(params.get("beginTime"))); |
| | | query.startedBefore(DateUtils.parseDate(params.get("endTime"))); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.utils; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.map.MapUtil; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.*; |
| | | import java.util.function.BiFunction; |
| | | import java.util.function.Function; |
| | | import java.util.function.Predicate; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * stream æµå·¥å
·ç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class StreamUtils { |
| | | |
| | | /** |
| | | * å°collectionè¿æ»¤ |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function è¿æ»¤æ¹æ³ |
| | | * @return è¿æ»¤åçlist |
| | | */ |
| | | public static <E> List<E> filter(Collection<E> collection, Predicate<E> function) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return collection.stream().filter(function).collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæ¼æ¥ |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function æ¼æ¥æ¹æ³ |
| | | * @return æ¼æ¥åçlist |
| | | */ |
| | | public static <E> String join(Collection<E> collection, Function<E, String> function) { |
| | | return join(collection, function, ","); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæ¼æ¥ |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function æ¼æ¥æ¹æ³ |
| | | * @param delimiter æ¼æ¥ç¬¦ |
| | | * @return æ¼æ¥åçlist |
| | | */ |
| | | public static <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return StringUtils.EMPTY; |
| | | } |
| | | return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter)); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæåº |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param comparing æåºæ¹æ³ |
| | | * @return æåºåçlist |
| | | */ |
| | | public static <E> List<E> sorted(Collection<E> collection, Comparator<E> comparing) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return collection.stream().sorted(comparing).collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * å°collection转å为类åä¸åçmap<br> |
| | | * <B>{@code Collection<V> ----> Map<K,V>}</B> |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param key Vç±»å转å为Kç±»åçlambdaæ¹æ³ |
| | | * @param <V> collectionä¸çæ³å |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @return 转ååçmap |
| | | */ |
| | | public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l)); |
| | | } |
| | | |
| | | /** |
| | | * å°Collection转å为map(valueç±»åä¸collectionçæ³åä¸å)<br> |
| | | * <B>{@code Collection<E> -----> Map<K,V> }</B> |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param key Eç±»å转å为Kç±»åçlambdaæ¹æ³ |
| | | * @param value Eç±»å转å为Vç±»åçlambdaæ¹æ³ |
| | | * @param <E> collectionä¸çæ³å |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @param <V> mapä¸çvalueç±»å |
| | | * @return 转ååçmap |
| | | */ |
| | | public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l)); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæç
§è§å(æ¯å¦æç¸åçç级id)åç±»æmap<br> |
| | | * <B>{@code Collection<E> -------> Map<K,List<E>> } </B> |
| | | * |
| | | * @param collection éè¦åç±»çéå |
| | | * @param key åç±»çè§å |
| | | * @param <E> collectionä¸çæ³å |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @return åç±»åçmap |
| | | */ |
| | | public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection |
| | | .stream() |
| | | .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList())); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæç
§ä¸¤ä¸ªè§å(æ¯å¦æç¸åç年级id,ç级id)åç±»æåå±map<br> |
| | | * <B>{@code Collection<E> ---> Map<T,Map<U,List<E>>> } </B> |
| | | * |
| | | * @param collection éè¦åç±»çéå |
| | | * @param key1 第ä¸ä¸ªåç±»çè§å |
| | | * @param key2 第äºä¸ªåç±»çè§å |
| | | * @param <E> éåå
ç´ ç±»å |
| | | * @param <K> 第ä¸ä¸ªmapä¸çkeyç±»å |
| | | * @param <U> 第äºä¸ªmapä¸çkeyç±»å |
| | | * @return åç±»åçmap |
| | | */ |
| | | public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1, Function<E, U> key2) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection |
| | | .stream() |
| | | .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList()))); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæç
§ä¸¤ä¸ªè§å(æ¯å¦æç¸åç年级id,ç级id)åç±»æåå±map<br> |
| | | * <B>{@code Collection<E> ---> Map<T,Map<U,E>> } </B> |
| | | * |
| | | * @param collection éè¦åç±»çéå |
| | | * @param key1 第ä¸ä¸ªåç±»çè§å |
| | | * @param key2 第äºä¸ªåç±»çè§å |
| | | * @param <T> 第ä¸ä¸ªmapä¸çkeyç±»å |
| | | * @param <U> 第äºä¸ªmapä¸çkeyç±»å |
| | | * @param <E> collectionä¸çæ³å |
| | | * @return åç±»åçmap |
| | | */ |
| | | public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection, Function<E, T> key1, Function<E, U> key2) { |
| | | if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection |
| | | .stream() |
| | | .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l))); |
| | | } |
| | | |
| | | /** |
| | | * å°collection转å为Listéåï¼ä½æ¯ä¸¤è
çæ³åä¸å<br> |
| | | * <B>{@code Collection<E> ------> List<T> } </B> |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function collectionä¸çæ³å转å为listæ³åçlambdaè¡¨è¾¾å¼ |
| | | * @param <E> collectionä¸çæ³å |
| | | * @param <T> Listä¸çæ³å |
| | | * @return 转ååçlist |
| | | */ |
| | | public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return collection |
| | | .stream() |
| | | .map(function) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * å°collection转å为Setéåï¼ä½æ¯ä¸¤è
çæ³åä¸å<br> |
| | | * <B>{@code Collection<E> ------> Set<T> } </B> |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function collectionä¸çæ³å转å为setæ³åçlambdaè¡¨è¾¾å¼ |
| | | * @param <E> collectionä¸çæ³å |
| | | * @param <T> Setä¸çæ³å |
| | | * @return 转ååçSet |
| | | */ |
| | | public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) { |
| | | if (CollUtil.isEmpty(collection) || function == null) { |
| | | return CollUtil.newHashSet(); |
| | | } |
| | | return collection |
| | | .stream() |
| | | .map(function) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å并两个ç¸åkeyç±»åçmap |
| | | * |
| | | * @param map1 第ä¸ä¸ªéè¦åå¹¶ç map |
| | | * @param map2 第äºä¸ªéè¦åå¹¶ç map |
| | | * @param merge åå¹¶çlambdaï¼å°key value1 value2åå¹¶ææç»çç±»å,注ævalueå¯è½ä¸ºç©ºçæ
åµ |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @param <X> 第ä¸ä¸ª mapçvalueç±»å |
| | | * @param <Y> 第äºä¸ª mapçvalueç±»å |
| | | * @param <V> æç»mapçvalueç±»å |
| | | * @return åå¹¶åçmap |
| | | */ |
| | | public static <K, X, Y, V> Map<K, V> merge(Map<K, X> map1, Map<K, Y> map2, BiFunction<X, Y, V> merge) { |
| | | if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) { |
| | | return MapUtil.newHashMap(); |
| | | } else if (MapUtil.isEmpty(map1)) { |
| | | map1 = MapUtil.newHashMap(); |
| | | } else if (MapUtil.isEmpty(map2)) { |
| | | map2 = MapUtil.newHashMap(); |
| | | } |
| | | Set<K> key = new HashSet<>(); |
| | | key.addAll(map1.keySet()); |
| | | key.addAll(map2.keySet()); |
| | | Map<K, V> map = new HashMap<>(); |
| | | for (K t : key) { |
| | | X x = map1.get(t); |
| | | Y y = map2.get(t); |
| | | V z = merge.apply(x, y); |
| | | if (z != null) { |
| | | map.put(t, z); |
| | | } |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.utils; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.common.satoken.utils.LoginHelper; |
| | | import org.ruoyi.flowable.common.constant.TaskConstants; |
| | | |
| | | import java.security.Security; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 工使µä»»å¡å·¥å
·ç±» |
| | | * |
| | | * @author konbai |
| | | * @createTime 2022/4/24 12:42 |
| | | */ |
| | | public class TaskUtils { |
| | | public static String getUserId() { |
| | | |
| | | LoginUser user = LoginHelper.getLoginUser(); |
| | | if (ObjectUtil.isNotNull(user)) { |
| | | return String.valueOf(user.getUserId()); |
| | | } |
| | | |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * è·åç¨æ·ç»ä¿¡æ¯ |
| | | * |
| | | * @return candidateGroup |
| | | */ |
| | | public static List<String> getCandidateGroup() { |
| | | List<String> list = new ArrayList<>(); |
| | | LoginUser user = LoginHelper.getLoginUser(); |
| | | if (ObjectUtil.isNotNull(user)) { |
| | | if (ObjectUtil.isNotEmpty(user.getRoles())) { |
| | | user.getRoles().forEach(role -> list.add(TaskConstants.ROLE_GROUP_PREFIX + role.getRoleId() )); |
| | | } |
| | | if (ObjectUtil.isNotNull(user.getDeptId())) { |
| | | list.add(TaskConstants.DEPT_GROUP_PREFIX + user.getDeptId()); |
| | | } |
| | | } |
| | | |
| | | return list; |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.controller; |
| | | |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.utils.MapstructUtils; |
| | | import org.ruoyi.common.web.core.BaseController; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.WfCategory; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfCategoryVo; |
| | | import org.ruoyi.flowable.workflow.service.IWfCategoryService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import org.ruoyi.common.excel.utils.ExcelUtil; |
| | | |
| | | /** |
| | | * æµç¨åç±»Controller |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @Validated |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/category") |
| | | public class WfCategoryController extends BaseController { |
| | | |
| | | private final IWfCategoryService categoryService; |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨åç±»å表 |
| | | */ |
| | | @GetMapping("/list") |
| | | public TableDataInfo<WfCategoryVo> list(WfCategory category) { |
| | | List<WfCategoryVo> list = categoryService.queryList(category); |
| | | return TableDataInfo.build(list); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢å
¨é¨çæµç¨åç±»å表 |
| | | */ |
| | | @GetMapping("/listAll") |
| | | public R<List<WfCategoryVo>> listAll(WfCategory category) { |
| | | return R.ok(categoryService.queryList(category)); |
| | | } |
| | | |
| | | /** |
| | | * å¯¼åºæµç¨åç±»å表 |
| | | */ |
| | | @PostMapping("/export") |
| | | public void export(@Validated WfCategory category, HttpServletResponse response) { |
| | | List<WfCategoryVo> list = categoryService.queryList(category); |
| | | List<WfCategoryVo> util = MapstructUtils.convert(list,WfCategoryVo.class); |
| | | ExcelUtil.exportExcel(util, "æµç¨åç±»", WfCategoryVo.class, response); |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨å类详ç»ä¿¡æ¯ |
| | | * @param categoryId åç±»ä¸»é® |
| | | */ |
| | | @GetMapping("/{categoryId}") |
| | | public R<WfCategoryVo> getInfo(@NotNull(message = "主é®ä¸è½ä¸ºç©º") @PathVariable("categoryId") Long categoryId) { |
| | | return R.ok(categoryService.queryById(categoryId)); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢æµç¨åç±» |
| | | */ |
| | | @PostMapping |
| | | public R add(@Validated @RequestBody WfCategory category) { |
| | | if (!categoryService.checkCategoryCodeUnique(category)) { |
| | | return R.fail("æ°å¢æµç¨åç±»'" + category.getCategoryName() + "'å¤±è´¥ï¼æµç¨ç¼ç å·²åå¨"); |
| | | } |
| | | return R.ok(categoryService.insertCategory(category)); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹æµç¨åç±» |
| | | */ |
| | | @PutMapping() |
| | | public R edit(@Validated @RequestBody WfCategory category) { |
| | | if (!categoryService.checkCategoryCodeUnique(category)) { |
| | | return R.fail("ä¿®æ¹æµç¨åç±»'" + category.getCategoryName() + "'å¤±è´¥ï¼æµç¨ç¼ç å·²åå¨"); |
| | | } |
| | | return toAjax(categoryService.updateCategory(category)); |
| | | } |
| | | |
| | | /** |
| | | * å 餿µç¨åç±» |
| | | * @param categoryIds å类主é®ä¸² |
| | | */ |
| | | @DeleteMapping("/{categoryIds}") |
| | | public R remove(@NotEmpty(message = "主é®ä¸è½ä¸ºç©º") @PathVariable Long[] categoryIds) { |
| | | return toAjax(categoryService.deleteWithValidByIds(Arrays.asList(categoryIds), true)); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.controller; |
| | | |
| | | |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.web.core.BaseController; |
| | | import org.ruoyi.flowable.core.domain.ProcessQuery; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.utils.JsonUtils; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfDeployVo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | import org.ruoyi.flowable.workflow.service.IWfDeployFormService; |
| | | import org.ruoyi.flowable.workflow.service.IWfDeployService; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import java.util.Arrays; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * æµç¨é¨ç½² |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/24 20:57 |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/deploy") |
| | | public class WfDeployController extends BaseController { |
| | | |
| | | private final IWfDeployService deployService; |
| | | private final IWfDeployFormService deployFormService; |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨é¨ç½²å表 |
| | | */ |
| | | @GetMapping("/list") |
| | | public TableDataInfo<WfDeployVo> list(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | return deployService.queryPageList(processQuery, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨é¨ç½²çæ¬å表 |
| | | */ |
| | | @GetMapping("/publishList") |
| | | public TableDataInfo<WfDeployVo> publishList(@RequestParam String processKey, PageQuery pageQuery) { |
| | | return deployService.queryPublishList(processKey, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * æ¿æ´»ææèµ·æµç¨ |
| | | * |
| | | * @param state ç¶æï¼active:æ¿æ´» suspended:æèµ·ï¼ |
| | | * @param definitionId æµç¨å®ä¹ID |
| | | */ |
| | | @PutMapping(value = "/changeState") |
| | | public R<Void> changeState(@RequestParam String state, @RequestParam String definitionId) { |
| | | deployService.updateState(definitionId, state); |
| | | return R.ok("æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * 读åxmlæä»¶ |
| | | * @param definitionId æµç¨å®ä¹ID |
| | | * @return |
| | | */ |
| | | @GetMapping("/bpmnXml/{definitionId}") |
| | | public R<String> getBpmnXml(@PathVariable(value = "definitionId") String definitionId) { |
| | | return R.ok( deployService.queryBpmnXmlById(definitionId),null); |
| | | } |
| | | |
| | | /** |
| | | * å 餿µç¨æ¨¡å |
| | | * @param deployIds æµç¨é¨ç½²ids |
| | | */ |
| | | @DeleteMapping("/{deployIds}") |
| | | public R<String> remove(@NotEmpty(message = "主é®ä¸è½ä¸ºç©º") @PathVariable String[] deployIds) { |
| | | deployService.deleteByIds(Arrays.asList(deployIds)); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨é¨ç½²å
³è表åä¿¡æ¯ |
| | | * |
| | | * @param deployId æµç¨é¨ç½²id |
| | | */ |
| | | @GetMapping("/form/{deployId}") |
| | | public R<?> start(@PathVariable(value = "deployId") String deployId) { |
| | | WfFormVo formVo = deployFormService.selectDeployFormByDeployId(deployId); |
| | | if (Objects.isNull(formVo)) { |
| | | return R.fail("请å
é
ç½®æµç¨è¡¨å"); |
| | | } |
| | | return R.ok(JsonUtils.parseObject(formVo.getContent(), Map.class)); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.controller; |
| | | |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.utils.MapstructUtils; |
| | | import org.ruoyi.common.core.validate.QueryGroup; |
| | | import org.ruoyi.common.excel.utils.ExcelUtil; |
| | | import org.ruoyi.common.web.core.BaseController; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.WfDeployForm; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfFormBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | import org.ruoyi.flowable.workflow.service.IWfDeployFormService; |
| | | import org.ruoyi.flowable.workflow.service.IWfFormService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æµç¨è¡¨åController |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/form") |
| | | public class WfFormController extends BaseController { |
| | | |
| | | private final IWfFormService formService; |
| | | |
| | | private final IWfDeployFormService deployFormService; |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¡¨åå表 |
| | | */ |
| | | @GetMapping("/list") |
| | | public TableDataInfo<WfFormVo> list(@Validated(QueryGroup.class) WfFormBo bo, PageQuery pageQuery) { |
| | | return formService.queryPageList(bo, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * å¯¼åºæµç¨è¡¨åå表 |
| | | */ |
| | | @PostMapping("/export") |
| | | public void export(@Validated WfFormBo bo, HttpServletResponse response) { |
| | | List<WfFormVo> list = formService.queryList(bo); |
| | | List<WfFormVo> convert = MapstructUtils.convert(list, WfFormVo.class); |
| | | ExcelUtil.exportExcel( convert, "æµç¨è¡¨å", WfFormVo.class, response); |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨è¡¨å详ç»ä¿¡æ¯ |
| | | * @param formId ä¸»é® |
| | | */ |
| | | @GetMapping(value = "/{formId}") |
| | | public R getInfo(@NotNull(message = "主é®ä¸è½ä¸ºç©º") @PathVariable("formId") Long formId) { |
| | | return R.ok(formService.queryById(formId)); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢æµç¨è¡¨å |
| | | */ |
| | | @PostMapping |
| | | public R add(@RequestBody WfFormBo bo) { |
| | | return toAjax(formService.insertForm(bo)); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹æµç¨è¡¨å |
| | | */ |
| | | @PutMapping |
| | | public R edit(@RequestBody WfFormBo bo) { |
| | | return toAjax(formService.updateForm(bo)); |
| | | } |
| | | |
| | | /** |
| | | * å 餿µç¨è¡¨å |
| | | * @param formIds 主é®ä¸² |
| | | */ |
| | | @DeleteMapping("/{formIds}") |
| | | public R remove(@NotEmpty(message = "主é®ä¸è½ä¸ºç©º") @PathVariable Long[] formIds) { |
| | | return toAjax(formService.deleteWithValidByIds(Arrays.asList(formIds)) ? 1 : 0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * æè½½æµç¨è¡¨å |
| | | */ |
| | | @PostMapping("/addDeployForm") |
| | | public R addDeployForm(@RequestBody WfDeployForm deployForm) { |
| | | return toAjax(deployFormService.insertWfDeployForm(deployForm)); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.controller; |
| | | |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfTaskBo; |
| | | import org.ruoyi.flowable.workflow.service.IWfInstanceService; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | /** |
| | | * 工使µæµç¨å®ä¾ç®¡ç |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/instance") |
| | | public class WfInstanceController { |
| | | |
| | | private final IWfInstanceService instanceService; |
| | | |
| | | /** |
| | | * æ¿æ´»ææèµ·æµç¨å®ä¾ |
| | | * |
| | | * @param state 1:æ¿æ´»,2:æèµ· |
| | | * @param instanceId æµç¨å®ä¾ID |
| | | */ |
| | | @PostMapping(value = "/updateState") |
| | | public R updateState(@RequestParam Integer state, @RequestParam String instanceId) { |
| | | instanceService.updateState(state, instanceId); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * ç»ææµç¨å®ä¾ |
| | | * |
| | | * @param bo æµç¨ä»»å¡ä¸å¡å¯¹è±¡ |
| | | */ |
| | | @PostMapping(value = "/stopProcessInstance") |
| | | public R stopProcessInstance(@RequestBody WfTaskBo bo) { |
| | | instanceService.stopProcessInstance(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * å 餿µç¨å®ä¾ |
| | | * |
| | | * @param instanceId æµç¨å®ä¾ID |
| | | * @param deleteReason å é¤åå |
| | | */ |
| | | @Deprecated |
| | | @DeleteMapping(value = "/delete") |
| | | public R delete(@RequestParam String instanceId, String deleteReason) { |
| | | instanceService.delete(instanceId, deleteReason); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨å®ä¾è¯¦æ
ä¿¡æ¯ |
| | | * |
| | | * @param procInsId æµç¨å®ä¾ID |
| | | * @param deployId æµç¨é¨ç½²ID |
| | | */ |
| | | @GetMapping("/detail") |
| | | public R detail(String procInsId, String deployId) { |
| | | return R.ok(instanceService.queryDetailProcess(procInsId, deployId)); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.controller; |
| | | |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.utils.MapstructUtils; |
| | | import org.ruoyi.common.core.validate.AddGroup; |
| | | import org.ruoyi.common.core.validate.EditGroup; |
| | | import org.ruoyi.common.excel.utils.ExcelUtil; |
| | | import org.ruoyi.common.web.core.BaseController; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.WfCategory; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfModelBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfCategoryVo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfModelExportVo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfModelVo; |
| | | import org.ruoyi.flowable.workflow.service.IWfCategoryService; |
| | | import org.ruoyi.flowable.workflow.service.IWfModelService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 工使µæµç¨æ¨¡å管ç |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/6/21 9:09 |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/model") |
| | | public class WfModelController extends BaseController { |
| | | |
| | | private final IWfModelService modelService; |
| | | private final IWfCategoryService categoryService; |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æ¨¡åå表 |
| | | * |
| | | * @param modelBo æµç¨æ¨¡å对象 |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | @GetMapping("/list") |
| | | public TableDataInfo<WfModelVo> list(WfModelBo modelBo, PageQuery pageQuery) { |
| | | return modelService.list(modelBo, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æ¨¡åå表 |
| | | * |
| | | * @param modelBo æµç¨æ¨¡å对象 |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | @GetMapping("/historyList") |
| | | public TableDataInfo<WfModelVo> historyList(WfModelBo modelBo, PageQuery pageQuery) { |
| | | return modelService.historyList(modelBo, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨æ¨¡å详ç»ä¿¡æ¯ |
| | | * |
| | | * @param modelId 模åä¸»é® |
| | | */ |
| | | @GetMapping(value = "/{modelId}") |
| | | public R<WfModelVo> getInfo(@NotNull(message = "主é®ä¸è½ä¸ºç©º") @PathVariable("modelId") String modelId) { |
| | | return R.ok(modelService.getModel(modelId)); |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨è¡¨å详ç»ä¿¡æ¯ |
| | | * |
| | | * @param modelId 模åä¸»é® |
| | | */ |
| | | @GetMapping(value = "/bpmnXml/{modelId}") |
| | | public R<String> getBpmnXml(@NotNull(message = "主é®ä¸è½ä¸ºç©º") @PathVariable("modelId") String modelId) { |
| | | return R.ok(modelService.queryBpmnXmlById(modelId),"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢æµç¨æ¨¡å |
| | | */ |
| | | @PostMapping |
| | | public R<Void> add(@Validated(AddGroup.class) @RequestBody WfModelBo modelBo) { |
| | | modelService.insertModel(modelBo); |
| | | return R.ok("æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹æµç¨æ¨¡å |
| | | */ |
| | | @PutMapping |
| | | public R<Void> edit(@Validated(EditGroup.class) @RequestBody WfModelBo modelBo) { |
| | | modelService.updateModel(modelBo); |
| | | return R.ok("æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * ä¿åæµç¨æ¨¡å |
| | | */ |
| | | @PostMapping("/save") |
| | | public R<String> save(@RequestBody WfModelBo modelBo) { |
| | | modelService.saveModel(modelBo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * è®¾ä¸ºææ°æµç¨æ¨¡å |
| | | * @param modelId |
| | | * @return |
| | | */ |
| | | @PostMapping("/latest") |
| | | public R<?> latest(@RequestParam String modelId) { |
| | | modelService.latestModel(modelId); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * å 餿µç¨æ¨¡å |
| | | * |
| | | * @param modelIds æµç¨æ¨¡å主é®ä¸² |
| | | */ |
| | | @DeleteMapping("/{modelIds}") |
| | | public R<String> remove(@NotEmpty(message = "主é®ä¸è½ä¸ºç©º") @PathVariable String[] modelIds) { |
| | | modelService.deleteByIds(Arrays.asList(modelIds)); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * é¨ç½²æµç¨æ¨¡å |
| | | * |
| | | * @param modelId æµç¨æ¨¡åä¸»é® |
| | | */ |
| | | @PostMapping("/deploy") |
| | | public R deployModel(@RequestParam String modelId) { |
| | | return toAjax(modelService.deployModel(modelId)); |
| | | } |
| | | |
| | | /** |
| | | * å¯¼åºæµç¨æ¨¡åæ°æ® |
| | | */ |
| | | @PostMapping("/export") |
| | | public void export(WfModelBo modelBo, HttpServletResponse response) { |
| | | List<WfModelVo> list = modelService.list(modelBo); |
| | | List<WfModelExportVo> listVo = BeanUtil.copyToList(list, WfModelExportVo.class); |
| | | List<WfCategoryVo> categoryVos = categoryService.queryList(new WfCategory()); |
| | | Map<String, String> categoryMap = categoryVos.stream() |
| | | .collect(Collectors.toMap(WfCategoryVo::getCode, WfCategoryVo::getCategoryName)); |
| | | for (WfModelExportVo exportVo : listVo) { |
| | | exportVo.setCategoryName(categoryMap.get(exportVo.getCategory())); |
| | | } |
| | | List<WfModelExportVo> convert = MapstructUtils.convert(listVo, WfModelExportVo.class); |
| | | ExcelUtil.exportExcel(convert, "æµç¨æ¨¡åæ°æ®", WfModelExportVo.class, response); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.controller; |
| | | |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.utils.MapstructUtils; |
| | | import org.ruoyi.common.excel.utils.ExcelUtil; |
| | | import org.ruoyi.common.satoken.utils.LoginHelper; |
| | | import org.ruoyi.common.web.core.BaseController; |
| | | import org.ruoyi.flowable.core.domain.ProcessQuery; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfCopyBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.*; |
| | | import org.ruoyi.flowable.workflow.service.IWfCopyService; |
| | | import org.ruoyi.flowable.workflow.service.IWfProcessService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 工使µæµç¨ç®¡ç |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/24 18:54 |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/process") |
| | | public class WfProcessController extends BaseController { |
| | | |
| | | private final IWfProcessService processService; |
| | | private final IWfCopyService copyService; |
| | | |
| | | /** |
| | | * æ¥è¯¢å¯åèµ·æµç¨å表 |
| | | * |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | @GetMapping(value = "/list") |
| | | public TableDataInfo<WfDefinitionVo> startProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | return processService.selectPageStartProcessList(processQuery, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * ææ¥æçæµç¨ |
| | | */ |
| | | @GetMapping(value = "/ownList") |
| | | public TableDataInfo<WfTaskVo> ownProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | return processService.selectPageOwnProcessList(processQuery, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * è·åå¾
åå表 |
| | | */ |
| | | @GetMapping(value = "/todoList") |
| | | public TableDataInfo<WfTaskVo> todoProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | return processService.selectPageTodoProcessList(processQuery, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * è·åå¾
ç¾å表 |
| | | * |
| | | * @param processQuery æµç¨ä¸å¡å¯¹è±¡ |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | @GetMapping(value = "/claimList") |
| | | public TableDataInfo<WfTaskVo> claimProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | return processService.selectPageClaimProcessList(processQuery, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * è·åå·²åå表 |
| | | * |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | @GetMapping(value = "/finishedList") |
| | | public TableDataInfo<WfTaskVo> finishedProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | return processService.selectPageFinishedProcessList(processQuery, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * è·åæéå表 |
| | | * |
| | | * @param copyBo æµç¨æé对象 |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | @GetMapping(value = "/copyList") |
| | | public TableDataInfo<WfCopyVo> copyProcessList(WfCopyBo copyBo, PageQuery pageQuery) { |
| | | // è·åå½åçç¨æ· |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | if (ObjectUtil.isNotNull(loginUser)) |
| | | { |
| | | copyBo.setUserId(loginUser.getUserId()); |
| | | } |
| | | return copyService.selectPageList(copyBo, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * 导åºå¯åèµ·æµç¨å表 |
| | | */ |
| | | @PostMapping("/startExport") |
| | | public void startExport(@Validated ProcessQuery processQuery, HttpServletResponse response) { |
| | | List<WfDefinitionVo> list = processService.selectStartProcessList(processQuery); |
| | | |
| | | List<WfDefinitionVo> convert = MapstructUtils.convert(list, WfDefinitionVo.class); |
| | | ExcelUtil.exportExcel(convert, "å¯åèµ·æµç¨", WfDefinitionVo.class, response); |
| | | } |
| | | |
| | | /** |
| | | * å¯¼åºææ¥ææµç¨å表 |
| | | */ |
| | | @PostMapping("/ownExport") |
| | | public void ownExport(@Validated ProcessQuery processQuery, HttpServletResponse response) { |
| | | List<WfTaskVo> list = processService.selectOwnProcessList(processQuery); |
| | | List<WfOwnTaskExportVo> listVo = BeanUtil.copyToList(list, WfOwnTaskExportVo.class); |
| | | for (WfOwnTaskExportVo exportVo : listVo) { |
| | | exportVo.setStatus(ObjectUtil.isNull(exportVo.getFinishTime()) ? "è¿è¡ä¸" : "已宿"); |
| | | } |
| | | List<WfOwnTaskExportVo> convert = MapstructUtils.convert(listVo, WfOwnTaskExportVo.class); |
| | | ExcelUtil.exportExcel(convert, "ææ¥æçæµç¨", WfOwnTaskExportVo.class, response); |
| | | } |
| | | |
| | | /** |
| | | * 导åºå¾
åæµç¨å表 |
| | | */ |
| | | @PostMapping("/todoExport") |
| | | public void todoExport(@Validated ProcessQuery processQuery, HttpServletResponse response) { |
| | | List<WfTaskVo> list = processService.selectTodoProcessList(processQuery); |
| | | List<WfTodoTaskExportVo> listVo = BeanUtil.copyToList(list, WfTodoTaskExportVo.class); |
| | | List<WfTodoTaskExportVo> convert = MapstructUtils.convert(listVo, WfTodoTaskExportVo.class); |
| | | ExcelUtil.exportExcel(convert, "å¾
åæµç¨", WfTodoTaskExportVo.class, response); |
| | | } |
| | | |
| | | /** |
| | | * 导åºå¾
ç¾æµç¨å表 |
| | | */ |
| | | @PostMapping("/claimExport") |
| | | public void claimExport(@Validated ProcessQuery processQuery, HttpServletResponse response) { |
| | | List<WfTaskVo> list = processService.selectClaimProcessList(processQuery); |
| | | List<WfClaimTaskExportVo> listVo = BeanUtil.copyToList(list, WfClaimTaskExportVo.class); |
| | | |
| | | List<WfClaimTaskExportVo> convert = MapstructUtils.convert(listVo, WfClaimTaskExportVo.class); |
| | | ExcelUtil.exportExcel(convert, "å¾
ç¾æµç¨", WfClaimTaskExportVo.class, response); |
| | | } |
| | | |
| | | /** |
| | | * 导åºå·²åæµç¨å表 |
| | | */ |
| | | @PostMapping("/finishedExport") |
| | | public void finishedExport(@Validated ProcessQuery processQuery, HttpServletResponse response) { |
| | | List<WfTaskVo> list = processService.selectFinishedProcessList(processQuery); |
| | | List<WfFinishedTaskExportVo> listVo = BeanUtil.copyToList(list, WfFinishedTaskExportVo.class); |
| | | List<WfFinishedTaskExportVo> convert = MapstructUtils.convert(listVo, WfFinishedTaskExportVo.class); |
| | | ExcelUtil.exportExcel(convert, "已念ç¨", WfFinishedTaskExportVo.class, response); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * å¯¼åºæéæµç¨å表 |
| | | */ |
| | | @PostMapping("/copyExport") |
| | | public void copyExport(WfCopyBo copyBo, HttpServletResponse response) { |
| | | // è·åå½åçç¨æ· |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | if (ObjectUtil.isNotNull(loginUser)) |
| | | { |
| | | copyBo.setUserId(loginUser.getUserId()); |
| | | } |
| | | List<WfCopyVo> list = copyService.selectList(copyBo); |
| | | List<WfCopyVo> convert = MapstructUtils.convert(list, WfCopyVo.class); |
| | | ExcelUtil.exportExcel(convert, "æéæµç¨", WfCopyVo.class, response); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨é¨ç½²å
³è表åä¿¡æ¯ |
| | | * |
| | | * @param definitionId æµç¨å®ä¹id |
| | | * @param deployId æµç¨é¨ç½²id |
| | | */ |
| | | @GetMapping("/getProcessForm") |
| | | public R<?> getForm(@RequestParam(value = "definitionId") String definitionId, |
| | | @RequestParam(value = "deployId") String deployId, |
| | | @RequestParam(value = "procInsId", required = false) String procInsId) { |
| | | return R.ok(processService.selectFormContent(definitionId, deployId, procInsId)); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æµç¨å®ä¹idå¯å¨æµç¨å®ä¾ |
| | | * |
| | | * @param processDefId æµç¨å®ä¹id |
| | | * @param variables åééå,json对象 |
| | | */ |
| | | @PostMapping("/start/{processDefId}") |
| | | public R start(@PathVariable(value = "processDefId") String processDefId, @RequestBody Map<String, Object> variables) { |
| | | processService.startProcessByDefId(processDefId, variables); |
| | | return R.ok("æµç¨å¯å¨æå"); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * å 餿µç¨å®ä¾ |
| | | * |
| | | * @param instanceIds æµç¨å®ä¾ID串 |
| | | */ |
| | | @DeleteMapping("/instance/{instanceIds}") |
| | | public R<Void> delete(@PathVariable String[] instanceIds) { |
| | | processService.deleteProcessByIds(instanceIds); |
| | | return R.ok("æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * 读åxmlæä»¶ |
| | | * @param processDefId æµç¨å®ä¹ID |
| | | */ |
| | | @GetMapping("/bpmnXml/{processDefId}") |
| | | public R<String> getBpmnXml(@PathVariable(value = "processDefId") String processDefId) { |
| | | return R.ok(processService.queryBpmnXmlById(processDefId),null ); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¯¦æ
ä¿¡æ¯ |
| | | * |
| | | * @param procInsId æµç¨å®ä¾ID |
| | | * @param taskId ä»»å¡ID |
| | | */ |
| | | @GetMapping("/detail") |
| | | public R detail(String procInsId, String taskId) { |
| | | return R.ok(processService.queryProcessDetail(procInsId, taskId)); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.controller; |
| | | |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfTaskBo; |
| | | import org.ruoyi.flowable.workflow.service.IWfTaskService; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.imageio.ImageIO; |
| | | import java.awt.image.BufferedImage; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | |
| | | /** |
| | | * 工使µä»»å¡ç®¡ç |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/task") |
| | | public class WfTaskController { |
| | | |
| | | private final IWfTaskService flowTaskService; |
| | | |
| | | /** |
| | | * åæ¶æµç¨ |
| | | */ |
| | | @PostMapping(value = "/stopProcess") |
| | | public R stopProcess(@RequestBody WfTaskBo bo) { |
| | | flowTaskService.stopProcess(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * æ¤åæµç¨ |
| | | */ |
| | | @PostMapping(value = "/revokeProcess") |
| | | public R revokeProcess(@RequestBody WfTaskBo bo) { |
| | | flowTaskService.revokeProcess(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨åé |
| | | * @param taskId æµç¨ä»»å¡Id |
| | | */ |
| | | @GetMapping(value = "/processVariables/{taskId}") |
| | | public R processVariables(@PathVariable(value = "taskId") String taskId) { |
| | | return R.ok(flowTaskService.getProcessVariables(taskId)); |
| | | } |
| | | |
| | | /** |
| | | * 审æ¹ä»»å¡ |
| | | */ |
| | | @PostMapping(value = "/complete") |
| | | public R complete(@RequestBody WfTaskBo bo) { |
| | | flowTaskService.complete(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * æç»ä»»å¡ |
| | | */ |
| | | @PostMapping(value = "/reject") |
| | | public R taskReject(@RequestBody WfTaskBo taskBo) { |
| | | flowTaskService.taskReject(taskBo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * éåä»»å¡ |
| | | */ |
| | | @PostMapping(value = "/return") |
| | | public R taskReturn(@RequestBody WfTaskBo bo) { |
| | | flowTaskService.taskReturn(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * è·åææå¯åéçèç¹ |
| | | */ |
| | | @PostMapping(value = "/returnList") |
| | | public R findReturnTaskList(@RequestBody WfTaskBo bo) { |
| | | return R.ok(flowTaskService.findReturnTaskList(bo)); |
| | | } |
| | | |
| | | /** |
| | | * å é¤ä»»å¡ |
| | | */ |
| | | @DeleteMapping(value = "/delete") |
| | | public R delete(@RequestBody WfTaskBo bo) { |
| | | flowTaskService.deleteTask(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * 认é¢/ç¾æ¶ä»»å¡ |
| | | */ |
| | | @PostMapping(value = "/claim") |
| | | public R claim(@RequestBody WfTaskBo bo) { |
| | | flowTaskService.claim(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * åæ¶è®¤é¢/ç¾æ¶ä»»å¡ |
| | | */ |
| | | @PostMapping(value = "/unClaim") |
| | | public R unClaim(@RequestBody WfTaskBo bo) { |
| | | flowTaskService.unClaim(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * å§æ´¾ä»»å¡ |
| | | */ |
| | | @PostMapping(value = "/delegate") |
| | | public R delegate(@RequestBody WfTaskBo bo) { |
| | | if (ObjectUtil.hasNull(bo.getTaskId(), bo.getUserId())) { |
| | | return R.fail("åæ°é误ï¼"); |
| | | } |
| | | flowTaskService.delegateTask(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * 转åä»»å¡ |
| | | */ |
| | | @PostMapping(value = "/transfer") |
| | | public R transfer(@RequestBody WfTaskBo bo) { |
| | | if (ObjectUtil.hasNull(bo.getTaskId(), bo.getUserId())) { |
| | | return R.fail("åæ°é误ï¼"); |
| | | } |
| | | flowTaskService.transferTask(bo); |
| | | return R.ok(null,"æä½æå"); |
| | | } |
| | | |
| | | /** |
| | | * çææµç¨å¾ |
| | | * |
| | | * @param processId ä»»å¡ID |
| | | */ |
| | | @RequestMapping("/diagram/{processId}") |
| | | public void genProcessDiagram(HttpServletResponse response, |
| | | @PathVariable("processId") String processId) { |
| | | InputStream inputStream = flowTaskService.diagram(processId); |
| | | OutputStream os = null; |
| | | BufferedImage image = null; |
| | | try { |
| | | image = ImageIO.read(inputStream); |
| | | response.setContentType("image/png"); |
| | | os = response.getOutputStream(); |
| | | if (image != null) { |
| | | ImageIO.write(image, "png", os); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | if (os != null) { |
| | | os.flush(); |
| | | os.close(); |
| | | } |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain; |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * æµç¨å类对象 wf_category |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-01-15 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("wf_category") |
| | | public class WfCategory extends BaseEntity { |
| | | |
| | | private static final long serialVersionUID=1L; |
| | | |
| | | /** |
| | | * åç±»ID |
| | | */ |
| | | @TableId(value = "category_id", type = IdType.AUTO) |
| | | private Long categoryId; |
| | | /** |
| | | * åç±»åç§° |
| | | */ |
| | | @NotBlank(message = "åç±»åç§°ä¸è½ä¸ºç©º") |
| | | private String categoryName; |
| | | /** |
| | | * åç±»ç¼ç |
| | | */ |
| | | @NotBlank(message = "åç±»ç¼ç ä¸è½ä¸ºç©º") |
| | | private String code; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | /** |
| | | * å 餿 å¿ï¼0代表åå¨ 2代表å é¤ï¼ |
| | | */ |
| | | @TableLogic |
| | | private String delFlag; |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain; |
| | | |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * æµç¨æé对象 wf_copy |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-05-19 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("wf_copy") |
| | | public class WfCopy extends BaseEntity { |
| | | |
| | | private static final long serialVersionUID=1L; |
| | | |
| | | /** |
| | | * æéä¸»é® |
| | | */ |
| | | @TableId(value = "copy_id", type = IdType.AUTO) |
| | | private Long copyId; |
| | | /** |
| | | * æéæ é¢ |
| | | */ |
| | | private String title; |
| | | /** |
| | | * æµç¨ä¸»é® |
| | | */ |
| | | private String processId; |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | private String processName; |
| | | /** |
| | | * æµç¨åç±»ä¸»é® |
| | | */ |
| | | private String categoryId; |
| | | /** |
| | | * é¨ç½²ä¸»é® |
| | | */ |
| | | private String deploymentId; |
| | | /** |
| | | * æµç¨å®ä¾ä¸»é® |
| | | */ |
| | | private String instanceId; |
| | | /** |
| | | * ä»»å¡ä¸»é® |
| | | */ |
| | | private String taskId; |
| | | /** |
| | | * ç¨æ·ä¸»é® |
| | | */ |
| | | private Long userId; |
| | | /** |
| | | * å起人Id |
| | | */ |
| | | private Long originatorId; |
| | | /** |
| | | * å起人åç§° |
| | | */ |
| | | private String originatorName; |
| | | /** |
| | | * å 餿 å¿ï¼0代表åå¨ 2代表å é¤ï¼ |
| | | */ |
| | | @TableLogic |
| | | private String delFlag; |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain; |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾å
³è表å对象 sys_instance_form |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @Data |
| | | @TableName("wf_deploy_form") |
| | | public class WfDeployForm { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æµç¨é¨ç½²ä¸»é® |
| | | */ |
| | | private String deployId; |
| | | |
| | | /** |
| | | * 表åKey |
| | | */ |
| | | private String formKey; |
| | | |
| | | /** |
| | | * èç¹Key |
| | | */ |
| | | private String nodeKey; |
| | | |
| | | /** |
| | | * 表ååç§° |
| | | */ |
| | | private String formName; |
| | | |
| | | /** |
| | | * èç¹åç§° |
| | | */ |
| | | private String nodeName; |
| | | |
| | | /** |
| | | * 表åå
容 |
| | | */ |
| | | private String content; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain; |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * æµç¨è¡¨å对象 wf_form |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("wf_form") |
| | | public class WfForm extends BaseEntity { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 表åä¸»é® |
| | | */ |
| | | @TableId(value = "form_id", type = IdType.AUTO) |
| | | private Long formId; |
| | | |
| | | /** |
| | | * 表ååç§° |
| | | */ |
| | | private String formName; |
| | | |
| | | /** |
| | | * 表åå
容 |
| | | */ |
| | | private String content; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.base; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.fasterxml.jackson.annotation.JsonIgnore; |
| | | import com.fasterxml.jackson.annotation.JsonInclude; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * Entityåºç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class BaseEntity implements Serializable |
| | | { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** æç´¢å¼ */ |
| | | @JsonIgnore |
| | | @TableField(exist = false) |
| | | private String searchValue; |
| | | |
| | | /** å建è
*/ |
| | | private String createBy; |
| | | |
| | | /** å建æ¶é´ */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date createTime; |
| | | |
| | | /** æ´æ°è
*/ |
| | | private String updateBy; |
| | | |
| | | /** æ´æ°æ¶é´ */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date updateTime; |
| | | |
| | | /** 夿³¨ */ |
| | | private String remark; |
| | | |
| | | /** 请æ±åæ° */ |
| | | @JsonInclude(JsonInclude.Include.NON_EMPTY) |
| | | @TableField(exist = false) |
| | | private Map<String, Object> params; |
| | | |
| | | public String getSearchValue() |
| | | { |
| | | return searchValue; |
| | | } |
| | | |
| | | public void setSearchValue(String searchValue) |
| | | { |
| | | this.searchValue = searchValue; |
| | | } |
| | | |
| | | public String getCreateBy() |
| | | { |
| | | return createBy; |
| | | } |
| | | |
| | | public void setCreateBy(String createBy) |
| | | { |
| | | this.createBy = createBy; |
| | | } |
| | | |
| | | public Date getCreateTime() |
| | | { |
| | | return createTime; |
| | | } |
| | | |
| | | public void setCreateTime(Date createTime) |
| | | { |
| | | this.createTime = createTime; |
| | | } |
| | | |
| | | public String getUpdateBy() |
| | | { |
| | | return updateBy; |
| | | } |
| | | |
| | | public void setUpdateBy(String updateBy) |
| | | { |
| | | this.updateBy = updateBy; |
| | | } |
| | | |
| | | public Date getUpdateTime() |
| | | { |
| | | return updateTime; |
| | | } |
| | | |
| | | public void setUpdateTime(Date updateTime) |
| | | { |
| | | this.updateTime = updateTime; |
| | | } |
| | | |
| | | public String getRemark() |
| | | { |
| | | return remark; |
| | | } |
| | | |
| | | public void setRemark(String remark) |
| | | { |
| | | this.remark = remark; |
| | | } |
| | | |
| | | public Map<String, Object> getParams() |
| | | { |
| | | if (params == null) |
| | | { |
| | | params = new HashMap<>(); |
| | | } |
| | | return params; |
| | | } |
| | | |
| | | public void setParams(Map<String, Object> params) |
| | | { |
| | | this.params = params; |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.bo; |
| | | |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.ruoyi.common.core.validate.AddGroup; |
| | | import org.ruoyi.common.core.validate.EditGroup; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * æµç¨æéä¸å¡å¯¹è±¡ wf_copy |
| | | * |
| | | * @author ruoyi |
| | | * @date 2022-05-19 |
| | | */ |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class WfCopyBo extends BaseEntity { |
| | | |
| | | /** |
| | | * æéä¸»é® |
| | | */ |
| | | @NotNull(message = "æé主é®ä¸è½ä¸ºç©º", groups = { EditGroup.class }) |
| | | private Long copyId; |
| | | |
| | | /** |
| | | * æéæ é¢ |
| | | */ |
| | | @NotNull(message = "æéæ é¢ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String title; |
| | | |
| | | /** |
| | | * æµç¨ä¸»é® |
| | | */ |
| | | @NotBlank(message = "æµç¨ä¸»é®ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String processId; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @NotBlank(message = "æµç¨åç§°ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String processName; |
| | | |
| | | /** |
| | | * æµç¨åç±»ä¸»é® |
| | | */ |
| | | @NotBlank(message = "æµç¨å类主é®ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String categoryId; |
| | | |
| | | /** |
| | | * ä»»å¡ä¸»é® |
| | | */ |
| | | @NotBlank(message = "ä»»å¡ä¸»é®ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String taskId; |
| | | |
| | | /** |
| | | * ç¨æ·ä¸»é® |
| | | */ |
| | | @NotNull(message = "ç¨æ·ä¸»é®ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private Long userId; |
| | | |
| | | /** |
| | | * å起人Id |
| | | */ |
| | | @NotNull(message = "å起人主é®ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private Long originatorId; |
| | | /** |
| | | * å起人åç§° |
| | | */ |
| | | @NotNull(message = "å起人åç§°ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String originatorName; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.bo; |
| | | |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | import org.ruoyi.common.core.validate.AddGroup; |
| | | import org.ruoyi.common.core.validate.EditGroup; |
| | | |
| | | |
| | | /** |
| | | * æµç¨è®¾è®¡ä¸å¡å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @Data |
| | | public class WfDesignerBo { |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @NotNull(message = "æµç¨åç§°", groups = { AddGroup.class, EditGroup.class }) |
| | | private String name; |
| | | |
| | | /** |
| | | * æµç¨åç±» |
| | | */ |
| | | @NotBlank(message = "æµç¨åç±»", groups = { AddGroup.class, EditGroup.class }) |
| | | private String category; |
| | | |
| | | /** |
| | | * XMLå符串 |
| | | */ |
| | | @NotBlank(message = "XMLå符串", groups = { AddGroup.class, EditGroup.class }) |
| | | private String xml; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.bo; |
| | | |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.ruoyi.common.core.validate.AddGroup; |
| | | import org.ruoyi.common.core.validate.EditGroup; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * æµç¨è¡¨åä¸å¡å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class WfFormBo extends BaseEntity { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 表åä¸»é® |
| | | */ |
| | | @NotNull(message = "表åIDä¸è½ä¸ºç©º", groups = { EditGroup.class }) |
| | | private Long formId; |
| | | |
| | | /** |
| | | * 表ååç§° |
| | | */ |
| | | @NotBlank(message = "表ååç§°ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String formName; |
| | | |
| | | /** |
| | | * 表åå
容 |
| | | */ |
| | | @NotBlank(message = "表åå
容ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String content; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.bo; |
| | | |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | import org.ruoyi.common.core.validate.AddGroup; |
| | | import org.ruoyi.common.core.validate.EditGroup; |
| | | |
| | | /** |
| | | * æµç¨æ¨¡å对象 |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/6/21 9:16 |
| | | */ |
| | | @Data |
| | | public class WfModelBo { |
| | | /** |
| | | * 模åä¸»é® |
| | | */ |
| | | @NotNull(message = "模å主é®ä¸è½ä¸ºç©º", groups = { EditGroup.class }) |
| | | private String modelId; |
| | | /** |
| | | * 模ååç§° |
| | | */ |
| | | @NotNull(message = "模ååç§°ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String modelName; |
| | | /** |
| | | * 模åKey |
| | | */ |
| | | @NotNull(message = "模åKeyä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String modelKey; |
| | | /** |
| | | * æµç¨åç±» |
| | | */ |
| | | @NotBlank(message = "æµç¨åç±»ä¸è½ä¸ºç©º", groups = { AddGroup.class, EditGroup.class }) |
| | | private String category; |
| | | /** |
| | | * æè¿° |
| | | */ |
| | | private String description; |
| | | /** |
| | | * 表åç±»å |
| | | */ |
| | | private Integer formType; |
| | | /** |
| | | * 表åä¸»é® |
| | | */ |
| | | private Long formId; |
| | | /** |
| | | * æµç¨xml |
| | | */ |
| | | private String bpmnXml; |
| | | /** |
| | | * æ¯å¦ä¿å为æ°çæ¬ |
| | | */ |
| | | private Boolean newVersion; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.bo; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æµç¨ä»»å¡ä¸å¡å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @Data |
| | | public class WfTaskBo { |
| | | /** |
| | | * ä»»å¡Id |
| | | */ |
| | | private String taskId; |
| | | /** |
| | | * ä»»å¡åç§° |
| | | */ |
| | | private String taskName; |
| | | /** |
| | | * ç¨æ·Id |
| | | */ |
| | | private String userId; |
| | | /** |
| | | * ä»»å¡æè§ |
| | | */ |
| | | private String comment; |
| | | /** |
| | | * æµç¨å®ä¾Id |
| | | */ |
| | | private String procInsId; |
| | | /** |
| | | * èç¹ |
| | | */ |
| | | private String targetKey; |
| | | /** |
| | | * æµç¨åéä¿¡æ¯ |
| | | */ |
| | | private Map<String, Object> variables; |
| | | /** |
| | | * 审æ¹äºº |
| | | */ |
| | | private String assignee; |
| | | /** |
| | | * åé人 |
| | | */ |
| | | private List<String> candidateUsers; |
| | | /** |
| | | * 审æ¹ç» |
| | | */ |
| | | private List<String> candidateGroups; |
| | | /** |
| | | * æéç¨æ·Id |
| | | */ |
| | | private String copyUserIds; |
| | | /** |
| | | * ä¸ä¸èç¹å®¡æ¹äºº |
| | | */ |
| | | private String nextUserIds; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.dto; |
| | | |
| | | |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | public class WfCommentDto implements Serializable { |
| | | |
| | | /** |
| | | * æè§ç±»å« 0 æ£å¸¸æè§ 1 éåæè§ 2 驳åæè§ |
| | | */ |
| | | private String type; |
| | | |
| | | /** |
| | | * æè§å
容 |
| | | */ |
| | | private String comment; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.dto; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/6/21 9:16 |
| | | */ |
| | | @Data |
| | | public class WfMetaInfoDto { |
| | | |
| | | /** |
| | | * å建è
ï¼usernameï¼ |
| | | */ |
| | | private String createUser; |
| | | |
| | | /** |
| | | * æµç¨æè¿° |
| | | */ |
| | | private String description; |
| | | /** |
| | | * 表åç±»å |
| | | */ |
| | | private Integer formType; |
| | | /** |
| | | * 表åç¼å· |
| | | */ |
| | | private Long formId; |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.dto; |
| | | |
| | | |
| | | import lombok.Data; |
| | | import org.ruoyi.system.domain.SysRole; |
| | | import org.ruoyi.system.domain.SysUser; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å¨æäººåãç» |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @Data |
| | | public class WfNextDto implements Serializable { |
| | | |
| | | private String type; |
| | | |
| | | private String vars; |
| | | |
| | | private List<SysUser> userList; |
| | | |
| | | private List<SysRole> roleList; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import lombok.Data; |
| | | |
| | | |
| | | |
| | | /** |
| | | * æµç¨åç±»è§å¾å¯¹è±¡ flow_category |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-01-15 |
| | | */ |
| | | @Data |
| | | @ExcelIgnoreUnannotated |
| | | public class WfCategoryVo { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * åç±»ID |
| | | */ |
| | | @ExcelProperty(value = "åç±»ID") |
| | | private Long categoryId; |
| | | |
| | | /** |
| | | * åç±»åç§° |
| | | */ |
| | | @ExcelProperty(value = "åç±»åç§°") |
| | | private String categoryName; |
| | | |
| | | /** |
| | | * åç±»ç¼ç |
| | | */ |
| | | @ExcelProperty(value = "åç±»ç¼ç ") |
| | | private String code; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | @ExcelProperty(value = "夿³¨") |
| | | private String remark; |
| | | |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * å¾
ç¾æµç¨å¯¹è±¡å¯¼åºVO |
| | | * |
| | | * @author konbai |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class WfClaimTaskExportVo implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ä»»å¡ç¼å· |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡ç¼å·") |
| | | private String taskId; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨åç§°") |
| | | private String procDefName; |
| | | |
| | | /** |
| | | * ä»»å¡èç¹ |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡èç¹") |
| | | private String taskName; |
| | | |
| | | /** |
| | | * æµç¨çæ¬ |
| | | */ |
| | | @ExcelProperty(value = "æµç¨çæ¬") |
| | | private int procDefVersion; |
| | | |
| | | /** |
| | | * æµç¨å起人åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨å起人") |
| | | private String startUserName; |
| | | |
| | | /** |
| | | * æ¥æ¶æ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelProperty(value = "æ¥æ¶æ¶é´") |
| | | private Date createTime; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * æµç¨æ¹å¤è§å¾å¯¹è±¡ |
| | | * |
| | | * @author konbai |
| | | * @createTime 2022/4/4 02:03 |
| | | */ |
| | | @Data |
| | | public class WfCommentVo { |
| | | |
| | | /** |
| | | * 审æ¹ç±»å« |
| | | */ |
| | | private String type; |
| | | |
| | | /** |
| | | * æ¹å¤å
容 |
| | | */ |
| | | private String message; |
| | | |
| | | /** |
| | | * æ¹å¤æ¶é´ |
| | | */ |
| | | private Date time; |
| | | |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | |
| | | /** |
| | | * æµç¨æéè§å¾å¯¹è±¡ wf_copy |
| | | * |
| | | * @author ruoyi |
| | | * @date 2022-05-19 |
| | | */ |
| | | @Data |
| | | @ExcelIgnoreUnannotated |
| | | public class WfCopyVo { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æéä¸»é® |
| | | */ |
| | | @ExcelProperty(value = "æé主é®") |
| | | private Long copyId; |
| | | |
| | | /** |
| | | * æéæ é¢ |
| | | */ |
| | | @ExcelProperty(value = "æéæ é¢") |
| | | private String title; |
| | | |
| | | /** |
| | | * æµç¨ä¸»é® |
| | | */ |
| | | @ExcelProperty(value = "æµç¨ä¸»é®") |
| | | private String processId; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨åç§°") |
| | | private String processName; |
| | | |
| | | /** |
| | | * æµç¨åç±»ä¸»é® |
| | | */ |
| | | @ExcelProperty(value = "æµç¨å类主é®") |
| | | private String categoryId; |
| | | |
| | | /** |
| | | * é¨ç½²ä¸»é® |
| | | */ |
| | | @ExcelProperty(value = "é¨ç½²ä¸»é®") |
| | | private String deploymentId; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾ä¸»é® |
| | | */ |
| | | @ExcelProperty(value = "æµç¨å®ä¾ä¸»é®") |
| | | private String instanceId; |
| | | |
| | | /** |
| | | * ä»»å¡ä¸»é® |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡ä¸»é®") |
| | | private String taskId; |
| | | |
| | | /** |
| | | * ç¨æ·ä¸»é® |
| | | */ |
| | | @ExcelProperty(value = "ç¨æ·ä¸»é®") |
| | | private Long userId; |
| | | |
| | | /** |
| | | * å起人Id |
| | | */ |
| | | @ExcelProperty(value = "å起人主é®") |
| | | private Long originatorId; |
| | | |
| | | /** |
| | | * å起人åç§° |
| | | */ |
| | | @ExcelProperty(value = "å起人åç§°") |
| | | private String originatorName; |
| | | |
| | | /** |
| | | * æéæ¶é´ï¼å建æ¶é´ï¼ |
| | | */ |
| | | @ExcelProperty(value = "æéæ¶é´") |
| | | private Date createTime; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | |
| | | |
| | | /** |
| | | * æµç¨å®ä¹è§å¾å¯¹è±¡ workflow_definition |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-01-17 |
| | | */ |
| | | @Data |
| | | @ExcelIgnoreUnannotated |
| | | public class WfDefinitionVo { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æµç¨å®ä¹ID |
| | | */ |
| | | @ExcelProperty(value = "æµç¨å®ä¹ID") |
| | | private String definitionId; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨åç§°") |
| | | private String processName; |
| | | |
| | | /** |
| | | * æµç¨Key |
| | | */ |
| | | @ExcelProperty(value = "æµç¨Key") |
| | | private String processKey; |
| | | |
| | | /** |
| | | * åç±»ç¼ç |
| | | */ |
| | | @ExcelProperty(value = "åç±»ç¼ç ") |
| | | private String category; |
| | | |
| | | /** |
| | | * çæ¬ |
| | | */ |
| | | @ExcelProperty(value = "çæ¬") |
| | | private Integer version; |
| | | |
| | | /** |
| | | * 表åID |
| | | */ |
| | | @ExcelProperty(value = "表åID") |
| | | private Long formId; |
| | | |
| | | /** |
| | | * 表ååç§° |
| | | */ |
| | | @ExcelProperty(value = "表ååç§°") |
| | | private String formName; |
| | | |
| | | /** |
| | | * é¨ç½²ID |
| | | */ |
| | | @ExcelProperty(value = "é¨ç½²ID") |
| | | private String deploymentId; |
| | | |
| | | /** |
| | | * æµç¨æ¯å¦æåï¼true:æèµ· false:æ¿æ´» ï¼ |
| | | */ |
| | | @ExcelProperty(value = "æµç¨æ¯å¦æèµ·") |
| | | private Boolean suspended; |
| | | |
| | | /** |
| | | * é¨ç½²æ¶é´ |
| | | */ |
| | | @ExcelProperty(value = "é¨ç½²æ¶é´") |
| | | private Date deploymentTime; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * é¨ç½²å®ä¾å表åå
³èè§å¾å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/7/17 18:29 |
| | | */ |
| | | @Data |
| | | public class WfDeployFormVo { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æµç¨é¨ç½²ä¸»é® |
| | | */ |
| | | private String deployId; |
| | | |
| | | /** |
| | | * 表åKey |
| | | */ |
| | | private String formKey; |
| | | |
| | | /** |
| | | * èç¹Key |
| | | */ |
| | | private String nodeKey; |
| | | |
| | | /** |
| | | * 表ååç§° |
| | | */ |
| | | private String formName; |
| | | |
| | | /** |
| | | * èç¹åç§° |
| | | */ |
| | | private String nodeName; |
| | | |
| | | /** |
| | | * 表åå
容 |
| | | */ |
| | | private String content; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | |
| | | /** |
| | | * æµç¨é¨ç½²è§å¾å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-06-30 |
| | | */ |
| | | @Data |
| | | @ExcelIgnoreUnannotated |
| | | public class WfDeployVo { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æµç¨å®ä¹ID |
| | | */ |
| | | @ExcelProperty(value = "æµç¨å®ä¹ID") |
| | | private String definitionId; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨åç§°") |
| | | private String processName; |
| | | |
| | | /** |
| | | * æµç¨Key |
| | | */ |
| | | @ExcelProperty(value = "æµç¨Key") |
| | | private String processKey; |
| | | |
| | | /** |
| | | * åç±»ç¼ç |
| | | */ |
| | | @ExcelProperty(value = "åç±»ç¼ç ") |
| | | private String category; |
| | | |
| | | /** |
| | | * çæ¬ |
| | | */ |
| | | private Integer version; |
| | | |
| | | /** |
| | | * 表åID |
| | | */ |
| | | @ExcelProperty(value = "表åID") |
| | | private Long formId; |
| | | |
| | | /** |
| | | * 表ååç§° |
| | | */ |
| | | @ExcelProperty(value = "表ååç§°") |
| | | private String formName; |
| | | |
| | | /** |
| | | * é¨ç½²ID |
| | | */ |
| | | @ExcelProperty(value = "é¨ç½²ID") |
| | | private String deploymentId; |
| | | |
| | | /** |
| | | * æµç¨å®ä¹ç¶æ: 1:æ¿æ´» , 2:䏿¢ |
| | | */ |
| | | @ExcelProperty(value = "æµç¨å®ä¹ç¶æ: 1:æ¿æ´» , 2:䏿¢") |
| | | private Boolean suspended; |
| | | |
| | | /** |
| | | * é¨ç½²æ¶é´ |
| | | */ |
| | | @ExcelProperty(value = "é¨ç½²æ¶é´") |
| | | private Date deploymentTime; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.Data; |
| | | import org.ruoyi.flowable.core.FormConf; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æµç¨è¯¦æ
è§å¾å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/8/7 15:01 |
| | | */ |
| | | @Data |
| | | public class WfDetailVo { |
| | | |
| | | /** |
| | | * ä»»å¡è¡¨åä¿¡æ¯ |
| | | */ |
| | | private FormConf taskFormData; |
| | | |
| | | /** |
| | | * å岿µç¨èç¹ä¿¡æ¯ |
| | | */ |
| | | private List<WfProcNodeVo> historyProcNodeList; |
| | | |
| | | /** |
| | | * æµç¨è¡¨åå表 |
| | | */ |
| | | private List<FormConf> processFormList; |
| | | |
| | | /** |
| | | * æµç¨XML |
| | | */ |
| | | private String bpmnXml; |
| | | |
| | | private WfViewerVo flowViewer; |
| | | |
| | | /** |
| | | * æ¯å¦åå¨ä»»å¡è¡¨åä¿¡æ¯ |
| | | * @return true:åå¨ï¼false:ä¸åå¨ |
| | | */ |
| | | public Boolean isExistTaskForm() { |
| | | return ObjectUtil.isNotEmpty(this.taskFormData); |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 已念ç¨å¯¹è±¡å¯¼åºVO |
| | | * |
| | | * @author konbai |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class WfFinishedTaskExportVo implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ä»»å¡ç¼å· |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡ç¼å·") |
| | | private String taskId; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨åç§°") |
| | | private String procDefName; |
| | | |
| | | /** |
| | | * ä»»å¡èç¹ |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡èç¹") |
| | | private String taskName; |
| | | |
| | | /** |
| | | * æµç¨çæ¬ |
| | | */ |
| | | @ExcelProperty(value = "æµç¨çæ¬") |
| | | private int procDefVersion; |
| | | |
| | | /** |
| | | * æµç¨å起人åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨å起人") |
| | | private String startUserName; |
| | | |
| | | /** |
| | | * æ¥æ¶æ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelProperty(value = "æ¥æ¶æ¶é´") |
| | | private Date createTime; |
| | | |
| | | /** |
| | | * å®¡æ¹æ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelProperty(value = "å®¡æ¹æ¶é´") |
| | | private Date finishTime; |
| | | |
| | | /** |
| | | * ä»»å¡èæ¶ |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡èæ¶") |
| | | private String duration; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * æµç¨åç±»è§å¾å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @Data |
| | | @ExcelIgnoreUnannotated |
| | | public class WfFormVo { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 表åä¸»é® |
| | | */ |
| | | @ExcelProperty(value = "表åID") |
| | | private Long formId; |
| | | |
| | | /** |
| | | * 表ååç§° |
| | | */ |
| | | @ExcelProperty(value = "表ååç§°") |
| | | private String formName; |
| | | |
| | | /** |
| | | * 表åå
容 |
| | | */ |
| | | @ExcelProperty(value = "表åå
容") |
| | | private String content; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | @ExcelProperty(value = "夿³¨") |
| | | private String remark; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * æµç¨æ¨¡å对象导åºVO |
| | | * |
| | | * @author konbai |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class WfModelExportVo implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | /** |
| | | * 模åID |
| | | */ |
| | | @ExcelProperty(value = "模åID") |
| | | private String modelId; |
| | | /** |
| | | * 模åKey |
| | | */ |
| | | @ExcelProperty(value = "模åKey") |
| | | private String modelKey; |
| | | /** |
| | | * 模ååç§° |
| | | */ |
| | | @ExcelProperty(value = "模ååç§°") |
| | | private String modelName; |
| | | /** |
| | | * åç±»ç¼ç |
| | | */ |
| | | @ExcelProperty(value = "åç±»ç¼ç ") |
| | | private String category; |
| | | /** |
| | | * æµç¨åç±» |
| | | */ |
| | | @ExcelProperty(value = "æµç¨åç±»") |
| | | private String categoryName; |
| | | /** |
| | | * 模åçæ¬ |
| | | */ |
| | | @ExcelProperty(value = "模åçæ¬") |
| | | private Integer version; |
| | | /** |
| | | * 模åæè¿° |
| | | */ |
| | | @ExcelProperty(value = "模åæè¿°") |
| | | private String description; |
| | | /** |
| | | * å建æ¶é´ |
| | | */ |
| | | @ExcelProperty(value = "å建æ¶é´") |
| | | private Date createTime; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * æµç¨æ¨¡åè§å¾å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/6/21 9:16 |
| | | */ |
| | | @Data |
| | | public class WfModelVo { |
| | | /** |
| | | * 模åID |
| | | */ |
| | | private String modelId; |
| | | /** |
| | | * 模ååç§° |
| | | */ |
| | | private String modelName; |
| | | /** |
| | | * 模åKey |
| | | */ |
| | | private String modelKey; |
| | | /** |
| | | * åç±»ç¼ç |
| | | */ |
| | | private String category; |
| | | /** |
| | | * çæ¬ |
| | | */ |
| | | private Integer version; |
| | | /** |
| | | * 表åç±»å |
| | | */ |
| | | private Integer formType; |
| | | /** |
| | | * 表åID |
| | | */ |
| | | private Long formId; |
| | | /** |
| | | * 模åæè¿° |
| | | */ |
| | | private String description; |
| | | /** |
| | | * å建æ¶é´ |
| | | */ |
| | | private Date createTime; |
| | | /** |
| | | * æµç¨xml |
| | | */ |
| | | private String bpmnXml; |
| | | /** |
| | | * 表åå
容 |
| | | */ |
| | | private String content; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * ææ¥ææµç¨å¯¹è±¡å¯¼åºVO |
| | | * |
| | | * @author konbai |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class WfOwnTaskExportVo implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾ID |
| | | */ |
| | | @ExcelProperty(value = "æµç¨ç¼å·") |
| | | private String procInsId; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨åç§°") |
| | | private String procDefName; |
| | | |
| | | /** |
| | | * æµç¨ç±»å« |
| | | */ |
| | | @ExcelProperty(value = "æµç¨ç±»å«") |
| | | private String category; |
| | | |
| | | /** |
| | | * æµç¨çæ¬ |
| | | */ |
| | | @ExcelProperty(value = "æµç¨çæ¬") |
| | | private int procDefVersion; |
| | | |
| | | /** |
| | | * æäº¤æ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelProperty(value = "æäº¤æ¶é´") |
| | | private Date createTime; |
| | | |
| | | /** |
| | | * æµç¨ç¶æ |
| | | */ |
| | | @ExcelProperty(value = "æµç¨ç¶æ") |
| | | private String status; |
| | | |
| | | /** |
| | | * ä»»å¡èæ¶ |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡èæ¶") |
| | | private String duration; |
| | | |
| | | /** |
| | | * å½åèç¹ |
| | | */ |
| | | @ExcelProperty(value = "å½åèç¹") |
| | | private String taskName; |
| | | |
| | | /** |
| | | * ä»»å¡å®ææ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date finishTime; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import org.flowable.engine.task.Comment; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 工使µèç¹å
ç´ è§å¾å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/9/11 22:04 |
| | | */ |
| | | @Data |
| | | @ExcelIgnoreUnannotated |
| | | public class WfProcNodeVo implements Serializable { |
| | | /** |
| | | * æµç¨ID |
| | | */ |
| | | private String procDefId; |
| | | /** |
| | | * æ´»å¨ID |
| | | */ |
| | | private String activityId; |
| | | /** |
| | | * æ´»å¨åç§° |
| | | */ |
| | | private String activityName; |
| | | /** |
| | | * æ´»å¨ç±»å |
| | | */ |
| | | private String activityType; |
| | | /** |
| | | * æ´»å¨èæ¶ |
| | | */ |
| | | private String duration; |
| | | /** |
| | | * æ§è¡äººId |
| | | */ |
| | | private Long assigneeId; |
| | | /** |
| | | * æ§è¡äººåç§° |
| | | */ |
| | | private String assigneeName; |
| | | /** |
| | | * åéæ§è¡äºº |
| | | */ |
| | | private String candidate; |
| | | /** |
| | | * ä»»å¡æè§ |
| | | */ |
| | | private List<Comment> commentList; |
| | | /** |
| | | * å建æ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date createTime; |
| | | /** |
| | | * ç»ææ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date endTime; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import org.flowable.engine.task.Comment; |
| | | import org.ruoyi.flowable.workflow.domain.dto.WfCommentDto; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 工使µä»»å¡è§å¾å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @Data |
| | | @ExcelIgnoreUnannotated |
| | | public class WfTaskVo implements Serializable { |
| | | /** |
| | | * ä»»å¡ç¼å· |
| | | */ |
| | | private String taskId; |
| | | /** |
| | | * ä»»å¡åç§° |
| | | */ |
| | | private String taskName; |
| | | /** |
| | | * ä»»å¡Key |
| | | */ |
| | | private String taskDefKey; |
| | | /** |
| | | * 任塿§è¡äººId |
| | | */ |
| | | private Long assigneeId; |
| | | /** |
| | | * é¨é¨åç§° |
| | | */ |
| | | @Deprecated |
| | | private String deptName; |
| | | /** |
| | | * æµç¨å起人é¨é¨åç§° |
| | | */ |
| | | @Deprecated |
| | | private String startDeptName; |
| | | /** |
| | | * 任塿§è¡äººåç§° |
| | | */ |
| | | private String assigneeName; |
| | | /** |
| | | * æµç¨å起人Id |
| | | */ |
| | | private Long startUserId; |
| | | /** |
| | | * æµç¨å起人åç§° |
| | | */ |
| | | private String startUserName; |
| | | /** |
| | | * æµç¨ç±»å |
| | | */ |
| | | private String category; |
| | | /** |
| | | * æµç¨åéä¿¡æ¯ |
| | | */ |
| | | private Object procVars; |
| | | /** |
| | | * å±é¨åéä¿¡æ¯ |
| | | */ |
| | | private Object taskLocalVars; |
| | | /** |
| | | * æµç¨é¨ç½²ç¼å· |
| | | */ |
| | | private String deployId; |
| | | /** |
| | | * æµç¨ID |
| | | */ |
| | | private String procDefId; |
| | | /** |
| | | * æµç¨key |
| | | */ |
| | | private String procDefKey; |
| | | /** |
| | | * æµç¨å®ä¹åç§° |
| | | */ |
| | | private String procDefName; |
| | | /** |
| | | * æµç¨å®ä¹å
置使ç¨çæ¬ |
| | | */ |
| | | private int procDefVersion; |
| | | /** |
| | | * æµç¨å®ä¾ID |
| | | */ |
| | | private String procInsId; |
| | | /** |
| | | * å岿µç¨å®ä¾ID |
| | | */ |
| | | private String hisProcInsId; |
| | | /** |
| | | * ä»»å¡èæ¶ |
| | | */ |
| | | private String duration; |
| | | /** |
| | | * ä»»å¡æè§ |
| | | */ |
| | | private WfCommentDto comment; |
| | | /** |
| | | * ä»»å¡æè§ |
| | | */ |
| | | private List<Comment> commentList; |
| | | /** |
| | | * åéæ§è¡äºº |
| | | */ |
| | | private String candidate; |
| | | /** |
| | | * ä»»å¡å建æ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date createTime; |
| | | /** |
| | | * ä»»å¡å®ææ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date finishTime; |
| | | |
| | | /** |
| | | * æµç¨ç¶æ |
| | | */ |
| | | private String processStatus; |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * å¾
åæµç¨å¯¹è±¡å¯¼åºVO |
| | | * |
| | | * @author konbai |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class WfTodoTaskExportVo implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ä»»å¡ç¼å· |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡ç¼å·") |
| | | private String taskId; |
| | | |
| | | /** |
| | | * æµç¨åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨åç§°") |
| | | private String procDefName; |
| | | |
| | | /** |
| | | * ä»»å¡èç¹ |
| | | */ |
| | | @ExcelProperty(value = "ä»»å¡èç¹") |
| | | private String taskName; |
| | | |
| | | /** |
| | | * æµç¨çæ¬ |
| | | */ |
| | | @ExcelProperty(value = "æµç¨çæ¬") |
| | | private int procDefVersion; |
| | | |
| | | /** |
| | | * æµç¨å起人åç§° |
| | | */ |
| | | @ExcelProperty(value = "æµç¨å起人") |
| | | private String startUserName; |
| | | |
| | | /** |
| | | * æ¥æ¶æ¶é´ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelProperty(value = "æ¥æ¶æ¶é´") |
| | | private Date createTime; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.domain.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * ä»»å¡è¿½è¸ªè§å¾å¯¹è±¡ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/1/8 19:42 |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | @ExcelIgnoreUnannotated |
| | | public class WfViewerVo { |
| | | |
| | | /** |
| | | * è·åæµç¨å®ä¾çåå²èç¹ï¼å»éï¼ |
| | | */ |
| | | private Set<String> finishedTaskSet; |
| | | |
| | | /** |
| | | * 已宿 |
| | | */ |
| | | private Set<String> finishedSequenceFlowSet; |
| | | |
| | | /** |
| | | * è·åæµç¨å®ä¾å½åæ£å¨å¾
åçèç¹ï¼å»éï¼ |
| | | */ |
| | | private Set<String> unfinishedTaskSet; |
| | | |
| | | /** |
| | | * å·²æç» |
| | | */ |
| | | private Set<String> rejectedTaskSet; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.handler; |
| | | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.AllArgsConstructor; |
| | | import org.flowable.bpmn.model.FlowElement; |
| | | import org.flowable.bpmn.model.UserTask; |
| | | import org.flowable.engine.delegate.DelegateExecution; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.flowable.common.constant.ProcessConstants; |
| | | import org.ruoyi.system.domain.SysUser; |
| | | import org.ruoyi.system.domain.bo.SysUserBo; |
| | | import org.ruoyi.system.service.ISysUserService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * å¤å®ä¾å¤çç±» |
| | | * |
| | | * @author KonBAI |
| | | */ |
| | | @AllArgsConstructor |
| | | @Component("multiInstanceHandler") |
| | | public class MultiInstanceHandler { |
| | | @Autowired |
| | | private ISysUserService remoteUserService; |
| | | public Set<String> getUserIds(DelegateExecution execution) { |
| | | Set<String> candidateUserIds = new LinkedHashSet<>(); |
| | | FlowElement flowElement = execution.getCurrentFlowElement(); |
| | | if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask) { |
| | | UserTask userTask = (UserTask) flowElement; |
| | | String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); |
| | | if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) { |
| | | // æ·»å åéç¨æ·id |
| | | candidateUserIds.addAll(userTask.getCandidateUsers()); |
| | | } else if (CollUtil.isNotEmpty(userTask.getCandidateGroups())) { |
| | | // è·åç»çIDï¼è§è²IDéåæé¨é¨IDéå |
| | | List<Long> groups = userTask.getCandidateGroups().stream() |
| | | .map(item -> Long.parseLong(item.substring(4))) |
| | | .collect(Collectors.toList()); |
| | | List<Long> userIds = new ArrayList<>(); |
| | | if ("ROLES".equals(dataType)) { |
| | | //todo éè¿è§è²idï¼è·åææç¨æ·idéå |
| | | R<List<SysUser>> userList = remoteUserService.selectUserByRoleIds(groups); |
| | | if(!ObjectUtil.isNull(userList) && !ObjectUtil.isNull(userList.getData())) { |
| | | List<SysUser> userListData = userList.getData(); |
| | | for(SysUser user : userListData) { |
| | | userIds.add(user.getUserId()); |
| | | } |
| | | } |
| | | } else if ("DEPTS".equals(dataType)) { |
| | | //todo éè¿é¨é¨idï¼è·åææç¨æ·idéå |
| | | R<List<SysUser>> userList = remoteUserService.selectUserByDeptIds(groups); |
| | | if(!ObjectUtil.isNull(userList) && ! ObjectUtil.isNull(userList.getData())) { |
| | | List<SysUser> userListData = userList.getData(); |
| | | for(SysUser user : userListData) { |
| | | userIds.add(user.getUserId()); |
| | | } |
| | | } |
| | | } |
| | | // æ·»å åéç¨æ·id |
| | | userIds.forEach(id -> candidateUserIds.add(String.valueOf(id))); |
| | | } |
| | | } |
| | | return candidateUserIds; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.mapper; |
| | | |
| | | |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.ruoyi.flowable.core.mapper.BaseMapperPlus; |
| | | import org.ruoyi.flowable.workflow.domain.WfCategory; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfCategoryVo; |
| | | |
| | | /** |
| | | * æµç¨åç±»Mapperæ¥å£ |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-01-15 |
| | | */ |
| | | @Mapper |
| | | public interface WfCategoryMapper extends BaseMapperPlus<WfCategoryMapper, WfCategory, WfCategoryVo> { |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.mapper; |
| | | |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.ruoyi.flowable.core.mapper.BaseMapperPlus; |
| | | import org.ruoyi.flowable.workflow.domain.WfCopy; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfCopyVo; |
| | | |
| | | /** |
| | | * æµç¨æéMapperæ¥å£ |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-05-19 |
| | | */ |
| | | @Mapper |
| | | public interface WfCopyMapper extends BaseMapperPlus<WfCopyMapper, WfCopy, WfCopyVo> { |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.mapper; |
| | | |
| | | |
| | | import org.ruoyi.flowable.core.mapper.BaseMapperPlus; |
| | | import org.ruoyi.flowable.workflow.domain.WfDeployForm; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfDeployFormVo; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾å
³è表åMapperæ¥å£ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @Mapper |
| | | public interface WfDeployFormMapper extends BaseMapperPlus<WfDeployFormMapper, WfDeployForm, WfDeployFormVo> { |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Constants; |
| | | import org.ruoyi.flowable.core.mapper.BaseMapperPlus; |
| | | import org.ruoyi.flowable.workflow.domain.WfForm; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æµç¨è¡¨åMapperæ¥å£ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @Mapper |
| | | public interface WfFormMapper extends BaseMapperPlus<WfFormMapper, WfForm, WfFormVo> { |
| | | |
| | | List<WfFormVo> selectFormVoList(@Param(Constants.WRAPPER) Wrapper<WfForm> queryWrapper); |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | import org.ruoyi.flowable.workflow.domain.WfCategory; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfCategoryVo; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æµç¨åç±»Serviceæ¥å£ |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-01-15 |
| | | */ |
| | | public interface IWfCategoryService { |
| | | /** |
| | | * æ¥è¯¢å个 |
| | | * @return |
| | | */ |
| | | WfCategoryVo queryById(Long categoryId); |
| | | |
| | | |
| | | /** |
| | | * æ¥è¯¢å表 |
| | | */ |
| | | List<WfCategoryVo> queryList(WfCategory category); |
| | | |
| | | /** |
| | | * æ°å¢æµç¨åç±» |
| | | * |
| | | * @param category æµç¨åç±»ä¿¡æ¯ |
| | | * @return ç»æ |
| | | */ |
| | | int insertCategory(WfCategory category); |
| | | |
| | | /** |
| | | * ç¼è¾æµç¨åç±» |
| | | * @param category æµç¨åç±»ä¿¡æ¯ |
| | | * @return ç»æ |
| | | */ |
| | | int updateCategory(WfCategory category); |
| | | |
| | | /** |
| | | * æ ¡éªå¹¶å 餿°æ® |
| | | * @param ids 主é®éå |
| | | * @param isValid æ¯å¦æ ¡éª,true-å é¤åæ ¡éª,false-䏿 ¡éª |
| | | * @return ç»æ |
| | | */ |
| | | int deleteWithValidByIds(Collection<Long> ids, Boolean isValid); |
| | | |
| | | /** |
| | | * æ ¡éªåç±»ç¼ç æ¯å¦å¯ä¸ |
| | | * |
| | | * @param category æµç¨åç±» |
| | | * @return ç»æ |
| | | */ |
| | | boolean checkCategoryCodeUnique(WfCategory category); |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfCopyBo; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfTaskBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfCopyVo; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æµç¨æéServiceæ¥å£ |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-05-19 |
| | | */ |
| | | public interface IWfCopyService { |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æé |
| | | * |
| | | * @param copyId æµç¨æéä¸»é® |
| | | * @return æµç¨æé |
| | | */ |
| | | WfCopyVo queryById(Long copyId); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æéå表 |
| | | * |
| | | * @param wfCopy æµç¨æé |
| | | * @return æµç¨æééå |
| | | */ |
| | | TableDataInfo<WfCopyVo> selectPageList(WfCopyBo wfCopy, PageQuery pageQuery); |
| | | /** |
| | | * æ¥è¯¢æµç¨æéå表 |
| | | * |
| | | * @param wfCopy æµç¨æé |
| | | * @return æµç¨æééå |
| | | */ |
| | | List<WfCopyVo> selectList(WfCopyBo wfCopy); |
| | | |
| | | /** |
| | | * æé |
| | | * @param taskBo |
| | | * @return |
| | | */ |
| | | Boolean makeCopy(WfTaskBo taskBo); |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | import org.ruoyi.flowable.workflow.domain.WfDeployForm; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | import org.flowable.bpmn.model.BpmnModel; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾å
³è表åServiceæ¥å£ |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | public interface IWfDeployFormService { |
| | | |
| | | /** |
| | | * æ°å¢æµç¨å®ä¾å
³è表å |
| | | * |
| | | * @param wfDeployForm æµç¨å®ä¾å
³è表å |
| | | * @return ç»æ |
| | | */ |
| | | int insertWfDeployForm(WfDeployForm wfDeployForm); |
| | | |
| | | /** |
| | | * ä¿åæµç¨å®ä¾å
³è表å |
| | | * @param deployId é¨ç½²ID |
| | | * @param bpmnModel bpmnModel对象 |
| | | * @return |
| | | */ |
| | | boolean saveInternalDeployForm(String deployId, BpmnModel bpmnModel); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æçç表å |
| | | * |
| | | * @param deployId |
| | | * @return |
| | | */ |
| | | @Deprecated |
| | | WfFormVo selectDeployFormByDeployId(String deployId); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | |
| | | import org.ruoyi.flowable.core.domain.ProcessQuery; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfDeployVo; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/6/30 9:03 |
| | | */ |
| | | public interface IWfDeployService { |
| | | |
| | | TableDataInfo<WfDeployVo> queryPageList(ProcessQuery processQuery, PageQuery pageQuery); |
| | | |
| | | TableDataInfo<WfDeployVo> queryPublishList(String processKey, PageQuery pageQuery); |
| | | |
| | | void updateState(String definitionId, String stateCode); |
| | | |
| | | String queryBpmnXmlById(String definitionId); |
| | | |
| | | void deleteByIds(List<String> deployIds); |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfFormBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 表å |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | public interface IWfFormService { |
| | | /** |
| | | * æ¥è¯¢æµç¨è¡¨å |
| | | * |
| | | * @param formId æµç¨è¡¨åID |
| | | * @return æµç¨è¡¨å |
| | | */ |
| | | WfFormVo queryById(Long formId); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¡¨åå表 |
| | | * |
| | | * @param bo æµç¨è¡¨å |
| | | * @return æµç¨è¡¨åéå |
| | | */ |
| | | TableDataInfo<WfFormVo> queryPageList(WfFormBo bo, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¡¨åå表 |
| | | * |
| | | * @param bo æµç¨è¡¨å |
| | | * @return æµç¨è¡¨åéå |
| | | */ |
| | | List<WfFormVo> queryList(WfFormBo bo); |
| | | |
| | | /** |
| | | * æ°å¢æµç¨è¡¨å |
| | | * |
| | | * @param bo æµç¨è¡¨å |
| | | * @return ç»æ |
| | | */ |
| | | int insertForm(WfFormBo bo); |
| | | |
| | | /** |
| | | * ä¿®æ¹æµç¨è¡¨å |
| | | * |
| | | * @param bo æµç¨è¡¨å |
| | | * @return ç»æ |
| | | */ |
| | | int updateForm(WfFormBo bo); |
| | | |
| | | /** |
| | | * æ¹éå 餿µç¨è¡¨å |
| | | * |
| | | * @param formIds éè¦å é¤çæµç¨è¡¨åID |
| | | * @return ç»æ |
| | | */ |
| | | Boolean deleteWithValidByIds(Collection<Long> formIds); |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfTaskBo; |
| | | import org.flowable.engine.history.HistoricProcessInstance; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | public interface IWfInstanceService { |
| | | |
| | | /** |
| | | * ç»ææµç¨å®ä¾ |
| | | * |
| | | * @param vo |
| | | */ |
| | | void stopProcessInstance(WfTaskBo vo); |
| | | |
| | | /** |
| | | * æ¿æ´»ææèµ·æµç¨å®ä¾ |
| | | * |
| | | * @param state ç¶æ |
| | | * @param instanceId æµç¨å®ä¾ID |
| | | */ |
| | | void updateState(Integer state, String instanceId); |
| | | |
| | | /** |
| | | * å 餿µç¨å®ä¾ID |
| | | * |
| | | * @param instanceId æµç¨å®ä¾ID |
| | | * @param deleteReason å é¤åå |
| | | */ |
| | | void delete(String instanceId, String deleteReason); |
| | | |
| | | /** |
| | | * æ ¹æ®å®ä¾IDæ¥è¯¢åå²å®ä¾æ°æ® |
| | | * |
| | | * @param processInstanceId |
| | | * @return |
| | | */ |
| | | HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId); |
| | | |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¯¦æ
ä¿¡æ¯ |
| | | * @param procInsId æµç¨å®ä¾ID |
| | | * @param deployId æµç¨é¨ç½²ID |
| | | */ |
| | | Map<String, Object> queryDetailProcess(String procInsId, String deployId); |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfModelBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfModelVo; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/6/21 9:11 |
| | | */ |
| | | public interface IWfModelService { |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æ¨¡åå表 |
| | | */ |
| | | TableDataInfo<WfModelVo> list(WfModelBo modelBo, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æ¨¡åå表 |
| | | */ |
| | | List<WfModelVo> list(WfModelBo modelBo); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æ¨¡åå表 |
| | | */ |
| | | TableDataInfo<WfModelVo> historyList(WfModelBo modelBo, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æ¨¡å详æ
ä¿¡æ¯ |
| | | */ |
| | | WfModelVo getModel(String modelId); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¡¨å详ç»ä¿¡æ¯ |
| | | */ |
| | | String queryBpmnXmlById(String modelId); |
| | | |
| | | /** |
| | | * æ°å¢æ¨¡åä¿¡æ¯ |
| | | */ |
| | | void insertModel(WfModelBo modelBo); |
| | | |
| | | /** |
| | | * ä¿®æ¹æ¨¡åä¿¡æ¯ |
| | | */ |
| | | void updateModel(WfModelBo modelBo); |
| | | |
| | | /** |
| | | * ä¿åæµç¨æ¨¡åä¿¡æ¯ |
| | | */ |
| | | void saveModel(WfModelBo modelBo); |
| | | |
| | | /** |
| | | * è®¾ä¸ºææ°æµç¨æ¨¡å |
| | | */ |
| | | void latestModel(String modelId); |
| | | |
| | | /** |
| | | * å 餿µç¨æ¨¡å |
| | | */ |
| | | void deleteByIds(Collection<String> ids); |
| | | |
| | | /** |
| | | * é¨ç½²æµç¨æ¨¡å |
| | | */ |
| | | boolean deployModel(String modelId); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | |
| | | import org.ruoyi.flowable.core.FormConf; |
| | | import org.ruoyi.flowable.core.domain.ProcessQuery; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfDefinitionVo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfDetailVo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfTaskVo; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/3/24 18:57 |
| | | */ |
| | | public interface IWfProcessService { |
| | | |
| | | /** |
| | | * æ¥è¯¢å¯åèµ·æµç¨å表 |
| | | * @param pageQuery å页忰 |
| | | * @return |
| | | */ |
| | | TableDataInfo<WfDefinitionVo> selectPageStartProcessList(ProcessQuery processQuery, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢å¯åèµ·æµç¨å表 |
| | | */ |
| | | List<WfDefinitionVo> selectStartProcessList(ProcessQuery processQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢æçæµç¨å表 |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | TableDataInfo<WfTaskVo> selectPageOwnProcessList(ProcessQuery processQuery, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢æçæµç¨å表 |
| | | */ |
| | | List<WfTaskVo> selectOwnProcessList(ProcessQuery processQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢ä»£åä»»å¡å表 |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | TableDataInfo<WfTaskVo> selectPageTodoProcessList(ProcessQuery processQuery, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢ä»£åä»»å¡å表 |
| | | */ |
| | | List<WfTaskVo> selectTodoProcessList(ProcessQuery processQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢å¾
ç¾ä»»å¡å表 |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | TableDataInfo<WfTaskVo> selectPageClaimProcessList(ProcessQuery processQuery, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢å¾
ç¾ä»»å¡å表 |
| | | */ |
| | | List<WfTaskVo> selectClaimProcessList(ProcessQuery processQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢å·²åä»»å¡å表 |
| | | * @param pageQuery å页忰 |
| | | */ |
| | | TableDataInfo<WfTaskVo> selectPageFinishedProcessList(ProcessQuery processQuery, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢å·²åä»»å¡å表 |
| | | */ |
| | | List<WfTaskVo> selectFinishedProcessList(ProcessQuery processQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨é¨ç½²å
³è表åä¿¡æ¯ |
| | | * @param definitionId æµç¨å®ä¹ID |
| | | * @param deployId é¨ç½²ID |
| | | */ |
| | | FormConf selectFormContent(String definitionId, String deployId, String procInsId); |
| | | |
| | | /** |
| | | * å¯å¨æµç¨å®ä¾ |
| | | * @param procDefId æµç¨å®ä¹ID |
| | | * @param variables æ©å±åæ° |
| | | */ |
| | | void startProcessByDefId(String procDefId, Map<String, Object> variables); |
| | | |
| | | /** |
| | | * éè¿DefinitionKeyå¯å¨æµç¨ |
| | | * @param procDefKey æµç¨å®ä¹Key |
| | | * @param variables æ©å±åæ° |
| | | */ |
| | | void startProcessByDefKey(String procDefKey, Map<String, Object> variables); |
| | | |
| | | /** |
| | | * å 餿µç¨å®ä¾ |
| | | */ |
| | | void deleteProcessByIds(String[] instanceIds); |
| | | |
| | | |
| | | /** |
| | | * 读åxmlæä»¶ |
| | | * @param processDefId æµç¨å®ä¹ID |
| | | */ |
| | | String queryBpmnXmlById(String processDefId); |
| | | |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨ä»»å¡è¯¦æ
ä¿¡æ¯ |
| | | * @param procInsId æµç¨å®ä¾ID |
| | | * @param taskId ä»»å¡ID |
| | | */ |
| | | WfDetailVo queryProcessDetail(String procInsId, String taskId); |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service; |
| | | |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfTaskBo; |
| | | import org.flowable.bpmn.model.FlowElement; |
| | | import org.flowable.engine.runtime.ProcessInstance; |
| | | |
| | | import java.io.InputStream; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | public interface IWfTaskService { |
| | | |
| | | /** |
| | | * 审æ¹ä»»å¡ |
| | | * |
| | | * @param task 请æ±å®ä½åæ° |
| | | */ |
| | | void complete(WfTaskBo task); |
| | | |
| | | /** |
| | | * æç»ä»»å¡ |
| | | * |
| | | * @param taskBo |
| | | */ |
| | | void taskReject(WfTaskBo taskBo); |
| | | |
| | | |
| | | /** |
| | | * éåä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | void taskReturn(WfTaskBo bo); |
| | | |
| | | /** |
| | | * è·åææå¯åéçèç¹ |
| | | * |
| | | * @param bo |
| | | * @return |
| | | */ |
| | | List<FlowElement> findReturnTaskList(WfTaskBo bo); |
| | | |
| | | /** |
| | | * å é¤ä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | void deleteTask(WfTaskBo bo); |
| | | |
| | | /** |
| | | * 认é¢/ç¾æ¶ä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | void claim(WfTaskBo bo); |
| | | |
| | | /** |
| | | * åæ¶è®¤é¢/ç¾æ¶ä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | void unClaim(WfTaskBo bo); |
| | | |
| | | /** |
| | | * å§æ´¾ä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | void delegateTask(WfTaskBo bo); |
| | | |
| | | |
| | | /** |
| | | * 转åä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | void transferTask(WfTaskBo bo); |
| | | |
| | | /** |
| | | * åæ¶ç³è¯· |
| | | * @param bo |
| | | * @return |
| | | */ |
| | | void stopProcess(WfTaskBo bo); |
| | | |
| | | /** |
| | | * æ¤åæµç¨ |
| | | * @param bo |
| | | * @return |
| | | */ |
| | | void revokeProcess(WfTaskBo bo); |
| | | |
| | | /** |
| | | * è·åæµç¨è¿ç¨å¾ |
| | | * @param processId |
| | | * @return |
| | | */ |
| | | InputStream diagram(String processId); |
| | | |
| | | /** |
| | | * è·åæµç¨åé |
| | | * @param taskId ä»»å¡ID |
| | | * @return æµç¨åé |
| | | */ |
| | | Map<String, Object> getProcessVariables(String taskId); |
| | | |
| | | /** |
| | | * å¯å¨ç¬¬ä¸ä¸ªä»»å¡ |
| | | * @param processInstance æµç¨å®ä¾ |
| | | * @param variables æµç¨åæ° |
| | | */ |
| | | void startFirstTask(ProcessInstance processInstance, Map<String, Object> variables); |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.flowable.workflow.domain.WfCategory; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfCategoryVo; |
| | | import org.ruoyi.flowable.workflow.mapper.WfCategoryMapper; |
| | | import org.ruoyi.flowable.workflow.service.IWfCategoryService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æµç¨åç±»Serviceä¸å¡å±å¤ç |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-01-15 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class WfCategoryServiceImpl implements IWfCategoryService { |
| | | |
| | | private final WfCategoryMapper baseMapper; |
| | | |
| | | @Override |
| | | public WfCategoryVo queryById(Long categoryId){ |
| | | return baseMapper.selectVoById(categoryId); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public List<WfCategoryVo> queryList(WfCategory category) { |
| | | LambdaQueryWrapper<WfCategory> lqw = buildQueryWrapper(category); |
| | | return baseMapper.selectVoList(lqw); |
| | | } |
| | | |
| | | private LambdaQueryWrapper<WfCategory> buildQueryWrapper(WfCategory category) { |
| | | Map<String, Object> params = category.getParams(); |
| | | LambdaQueryWrapper<WfCategory> lqw = Wrappers.lambdaQuery(); |
| | | lqw.like(StringUtils.isNotBlank(category.getCategoryName()), WfCategory::getCategoryName, category.getCategoryName()); |
| | | lqw.eq(StringUtils.isNotBlank(category.getCode()), WfCategory::getCode, category.getCode()); |
| | | return lqw; |
| | | } |
| | | |
| | | @Override |
| | | public int insertCategory(WfCategory categoryBo) { |
| | | WfCategory add = BeanUtil.toBean(categoryBo, WfCategory.class); |
| | | return baseMapper.insert(add); |
| | | } |
| | | |
| | | @Override |
| | | public int updateCategory(WfCategory categoryBo) { |
| | | WfCategory update = BeanUtil.toBean(categoryBo, WfCategory.class); |
| | | return baseMapper.updateById(update); |
| | | } |
| | | |
| | | @Override |
| | | public int deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { |
| | | if(isValid){ |
| | | //TODO åä¸äºä¸å¡ä¸çæ ¡éª,夿æ¯å¦éè¦æ ¡éª |
| | | } |
| | | return baseMapper.deleteBatchIds(ids); |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªåç±»ç¼ç æ¯å¦å¯ä¸ |
| | | * |
| | | * @param category æµç¨åç±» |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public boolean checkCategoryCodeUnique(WfCategory category) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<WfCategory>() |
| | | .eq(WfCategory::getCode, category.getCode()) |
| | | .ne(ObjectUtil.isNotNull(category.getCategoryId()), WfCategory::getCategoryId, category.getCategoryId())); |
| | | return !exist; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import jakarta.annotation.Resource; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.utils.ObjectUtils; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.common.satoken.utils.LoginHelper; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.WfCopy; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfCopyBo; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfTaskBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfCopyVo; |
| | | import org.ruoyi.flowable.workflow.mapper.WfCopyMapper; |
| | | import org.ruoyi.flowable.workflow.service.IWfCopyService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.flowable.engine.HistoryService; |
| | | import org.flowable.engine.RepositoryService; |
| | | import org.flowable.engine.history.HistoricProcessInstance; |
| | | import org.flowable.engine.repository.Deployment; |
| | | import org.springframework.stereotype.Service; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æµç¨æéServiceä¸å¡å±å¤ç |
| | | * |
| | | * @author KonBAI |
| | | * @date 2022-05-19 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class WfCopyServiceImpl implements IWfCopyService { |
| | | |
| | | private final WfCopyMapper baseMapper; |
| | | |
| | | private final HistoryService historyService; |
| | | @Resource |
| | | protected RepositoryService repositoryService; |
| | | /** |
| | | * æ¥è¯¢æµç¨æé |
| | | * |
| | | * @param copyId æµç¨æéä¸»é® |
| | | * @return æµç¨æé |
| | | */ |
| | | @Override |
| | | public WfCopyVo queryById(Long copyId){ |
| | | return baseMapper.selectVoById(copyId); |
| | | } |
| | | /** |
| | | * æ¥è¯¢æµç¨æéå表 |
| | | * |
| | | * @param bo æµç¨æé |
| | | * @return æµç¨æé |
| | | */ |
| | | @Override |
| | | public TableDataInfo<WfCopyVo> selectPageList(WfCopyBo bo, PageQuery pageQuery) { |
| | | LambdaQueryWrapper<WfCopy> lqw = buildQueryWrapper(bo); |
| | | lqw.orderByDesc(WfCopy::getCreateTime); |
| | | Page<WfCopyVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); |
| | | return TableDataInfo.build(result); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æéå表 |
| | | * |
| | | * @param bo æµç¨æé |
| | | * @return æµç¨æé |
| | | */ |
| | | @Override |
| | | public List<WfCopyVo> selectList(WfCopyBo bo) { |
| | | LambdaQueryWrapper<WfCopy> lqw = buildQueryWrapper(bo); |
| | | return baseMapper.selectVoList(lqw); |
| | | } |
| | | |
| | | private LambdaQueryWrapper<WfCopy> buildQueryWrapper(WfCopyBo bo) { |
| | | Map<String, Object> params = bo.getParams(); |
| | | LambdaQueryWrapper<WfCopy> lqw = Wrappers.lambdaQuery(); |
| | | lqw.eq(bo.getUserId() != null, WfCopy::getUserId, bo.getUserId()); |
| | | lqw.like(StringUtils.isNotBlank(bo.getProcessName()), WfCopy::getProcessName, bo.getProcessName()); |
| | | lqw.like(StringUtils.isNotBlank(bo.getOriginatorName()), WfCopy::getOriginatorName, bo.getOriginatorName()); |
| | | return lqw; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean makeCopy(WfTaskBo taskBo) { |
| | | if (StringUtils.isBlank(taskBo.getCopyUserIds())) { |
| | | // è¥æéç¨æ·ä¸ºç©ºï¼åä¸éè¦å¤çï¼è¿åæå |
| | | return true; |
| | | } |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(taskBo.getProcInsId()).singleResult(); |
| | | String[] ids = taskBo.getCopyUserIds().split(","); |
| | | List<WfCopy> copyList = new ArrayList<>(ids.length); |
| | | // è·åå½åçç¨æ· |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | Long originatorId = null; |
| | | String originatorName = null; |
| | | if (ObjectUtils.isNotEmpty(loginUser)) |
| | | { |
| | | originatorId = loginUser.getUserId(); |
| | | originatorName = loginUser.getNickName(); |
| | | } |
| | | // æµç¨é¨ç½²å®ä¾ä¿¡æ¯ |
| | | Deployment deployment = repositoryService.createDeploymentQuery() |
| | | .deploymentId(historicProcessInstance.getDeploymentId()).singleResult(); |
| | | String title = historicProcessInstance.getProcessDefinitionName() + "-" + taskBo.getTaskName(); |
| | | for (String id : ids) { |
| | | Long userId = Long.valueOf(id); |
| | | WfCopy copy = new WfCopy(); |
| | | copy.setTitle(title); |
| | | copy.setProcessId(historicProcessInstance.getProcessDefinitionId()); |
| | | copy.setProcessName(historicProcessInstance.getProcessDefinitionName()); |
| | | copy.setDeploymentId(historicProcessInstance.getDeploymentId()); |
| | | copy.setInstanceId(taskBo.getProcInsId()); |
| | | copy.setTaskId(taskBo.getTaskId()); |
| | | copy.setUserId(userId); |
| | | copy.setOriginatorId(originatorId); |
| | | copy.setOriginatorName(originatorName); |
| | | copy.setCreateTime(new Date()); |
| | | copy.setCategoryId(deployment.getCategory()); |
| | | copyList.add(copy); |
| | | } |
| | | return baseMapper.insertBatch(copyList); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import org.ruoyi.common.core.exception.ServiceException; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.flowable.utils.ModelUtils; |
| | | import org.ruoyi.flowable.workflow.domain.WfDeployForm; |
| | | import org.ruoyi.flowable.workflow.domain.WfForm; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | import org.ruoyi.flowable.workflow.mapper.WfDeployFormMapper; |
| | | import org.ruoyi.flowable.workflow.mapper.WfFormMapper; |
| | | import org.ruoyi.flowable.workflow.service.IWfDeployFormService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.flowable.bpmn.model.BpmnModel; |
| | | import org.flowable.bpmn.model.FlowNode; |
| | | import org.flowable.bpmn.model.StartEvent; |
| | | import org.flowable.bpmn.model.UserTask; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾å
³è表åServiceä¸å¡å±å¤ç |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class WfDeployFormServiceImpl implements IWfDeployFormService { |
| | | |
| | | private final WfDeployFormMapper baseMapper; |
| | | |
| | | private final WfFormMapper formMapper; |
| | | |
| | | /** |
| | | * æ°å¢æµç¨å®ä¾å
³è表å |
| | | * |
| | | * @param deployForm æµç¨å®ä¾å
³è表å |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int insertWfDeployForm(WfDeployForm deployForm) { |
| | | // å é¤é¨ç½²æµç¨å表åçå
³èå
³ç³» |
| | | baseMapper.delete(new LambdaQueryWrapper<WfDeployForm>().eq(WfDeployForm::getDeployId, deployForm.getDeployId())); |
| | | // æ°å¢é¨ç½²æµç¨å表åå
³ç³» |
| | | return baseMapper.insert(deployForm); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean saveInternalDeployForm(String deployId, BpmnModel bpmnModel) { |
| | | List<WfDeployForm> deployFormList = new ArrayList<>(); |
| | | // è·åå¼å§èç¹ |
| | | StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel); |
| | | if (ObjectUtil.isNull(startEvent)) { |
| | | throw new RuntimeException("å¼å§èç¹ä¸åå¨ï¼è¯·æ£æ¥æµç¨è®¾è®¡æ¯å¦æè¯¯ï¼"); |
| | | } |
| | | // ä¿åå¼å§èç¹è¡¨åä¿¡æ¯ |
| | | WfDeployForm startDeployForm = buildDeployForm(deployId, startEvent); |
| | | if (ObjectUtil.isNotNull(startDeployForm)) { |
| | | deployFormList.add(startDeployForm); |
| | | } |
| | | // ä¿åç¨æ·èç¹è¡¨åä¿¡æ¯ |
| | | Collection<UserTask> userTasks = ModelUtils.getAllUserTaskEvent(bpmnModel); |
| | | if (CollUtil.isNotEmpty(userTasks)) { |
| | | for (UserTask userTask : userTasks) { |
| | | WfDeployForm userTaskDeployForm = buildDeployForm(deployId, userTask); |
| | | if (ObjectUtil.isNotNull(userTaskDeployForm)) { |
| | | deployFormList.add(userTaskDeployForm); |
| | | } |
| | | } |
| | | } |
| | | // æ¹éæ°å¢é¨ç½²æµç¨å表åå
³èä¿¡æ¯ |
| | | return baseMapper.insertBatch(deployFormList); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨æçç表å |
| | | * |
| | | * @param deployId |
| | | * @return |
| | | */ |
| | | @Override |
| | | public WfFormVo selectDeployFormByDeployId(String deployId) { |
| | | QueryWrapper<WfForm> wrapper = Wrappers.query(); |
| | | wrapper.eq("t2.deploy_id", deployId); |
| | | List<WfFormVo> list = formMapper.selectFormVoList(wrapper); |
| | | if (ObjectUtil.isNotEmpty(list)) { |
| | | if (list.size() != 1) { |
| | | throw new ServiceException("表åä¿¡æ¯æ¥è¯¢é误"); |
| | | } else { |
| | | return list.get(0); |
| | | } |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æå»ºé¨ç½²è¡¨åå
³èä¿¡æ¯å¯¹è±¡ |
| | | * @param deployId é¨ç½²ID |
| | | * @param node èç¹ä¿¡æ¯ |
| | | * @return é¨ç½²è¡¨åå
³è对象ãè¥æ 表åä¿¡æ¯ï¼formKeyï¼ï¼åè¿ånull |
| | | */ |
| | | private WfDeployForm buildDeployForm(String deployId, FlowNode node) { |
| | | String formKey = ModelUtils.getFormKey(node); |
| | | if (StringUtils.isEmpty(formKey)) { |
| | | return null; |
| | | } |
| | | Long formId = Convert.toLong(StringUtils.substringAfter(formKey, "key_")); |
| | | WfForm wfForm = formMapper.selectById(formId); |
| | | if (ObjectUtil.isNull(wfForm)) { |
| | | throw new ServiceException("表åä¿¡æ¯æ¥è¯¢é误"); |
| | | } |
| | | WfDeployForm deployForm = new WfDeployForm(); |
| | | deployForm.setDeployId(deployId); |
| | | deployForm.setFormKey(formKey); |
| | | deployForm.setNodeKey(node.getId()); |
| | | deployForm.setFormName(wfForm.getFormName()); |
| | | deployForm.setNodeName(node.getName()); |
| | | deployForm.setContent(wfForm.getContent()); |
| | | return deployForm; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | import cn.hutool.core.io.IORuntimeException; |
| | | import cn.hutool.core.io.IoUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.ruoyi.flowable.core.domain.ProcessQuery; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.utils.ProcessUtils; |
| | | import org.ruoyi.flowable.workflow.domain.WfDeployForm; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfDeployVo; |
| | | import org.ruoyi.flowable.workflow.mapper.WfDeployFormMapper; |
| | | import org.ruoyi.flowable.workflow.service.IWfDeployService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.flowable.common.engine.impl.db.SuspensionState; |
| | | import org.flowable.engine.RepositoryService; |
| | | import org.flowable.engine.repository.Deployment; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | import org.flowable.engine.repository.ProcessDefinitionQuery; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.io.InputStream; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/6/30 9:04 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class WfDeployServiceImpl implements IWfDeployService { |
| | | |
| | | private final RepositoryService repositoryService; |
| | | private final WfDeployFormMapper deployFormMapper; |
| | | |
| | | @Override |
| | | public TableDataInfo<WfDeployVo> queryPageList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | // æµç¨å®ä¹åè¡¨æ°æ®æ¥è¯¢ |
| | | ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery() |
| | | .latestVersion() |
| | | .orderByProcessDefinitionKey() |
| | | .asc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(processDefinitionQuery, processQuery); |
| | | long pageTotal = processDefinitionQuery.count(); |
| | | if (pageTotal <= 0) { |
| | | return TableDataInfo.build(); |
| | | } |
| | | int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<ProcessDefinition> definitionList = processDefinitionQuery.listPage(offset, pageQuery.getPageSize()); |
| | | |
| | | List<WfDeployVo> deployVoList = new ArrayList<>(definitionList.size()); |
| | | for (ProcessDefinition processDefinition : definitionList) { |
| | | String deploymentId = processDefinition.getDeploymentId(); |
| | | Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); |
| | | WfDeployVo vo = new WfDeployVo(); |
| | | vo.setDefinitionId(processDefinition.getId()); |
| | | vo.setProcessKey(processDefinition.getKey()); |
| | | vo.setProcessName(processDefinition.getName()); |
| | | vo.setVersion(processDefinition.getVersion()); |
| | | vo.setCategory(processDefinition.getCategory()); |
| | | vo.setDeploymentId(processDefinition.getDeploymentId()); |
| | | vo.setSuspended(processDefinition.isSuspended()); |
| | | // æµç¨é¨ç½²ä¿¡æ¯ |
| | | vo.setCategory(deployment.getCategory()); |
| | | vo.setDeploymentTime(deployment.getDeploymentTime()); |
| | | deployVoList.add(vo); |
| | | } |
| | | Page<WfDeployVo> page = new Page<>(); |
| | | page.setRecords(deployVoList); |
| | | page.setTotal(pageTotal); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<WfDeployVo> queryPublishList(String processKey, PageQuery pageQuery) { |
| | | // å建æ¥è¯¢æ¡ä»¶ |
| | | ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionKey(processKey) |
| | | .orderByProcessDefinitionVersion() |
| | | .desc(); |
| | | long pageTotal = processDefinitionQuery.count(); |
| | | if (pageTotal <= 0) { |
| | | return TableDataInfo.build(); |
| | | } |
| | | // æ ¹æ®æ¥è¯¢æ¡ä»¶ï¼æ¥è¯¢ææçæ¬ |
| | | int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<ProcessDefinition> processDefinitionList = processDefinitionQuery |
| | | .listPage(offset, pageQuery.getPageSize()); |
| | | List<WfDeployVo> deployVoList = processDefinitionList.stream().map(item -> { |
| | | WfDeployVo vo = new WfDeployVo(); |
| | | vo.setDefinitionId(item.getId()); |
| | | vo.setProcessKey(item.getKey()); |
| | | vo.setProcessName(item.getName()); |
| | | vo.setVersion(item.getVersion()); |
| | | vo.setCategory(item.getCategory()); |
| | | vo.setDeploymentId(item.getDeploymentId()); |
| | | vo.setSuspended(item.isSuspended()); |
| | | return vo; |
| | | }).collect(Collectors.toList()); |
| | | Page<WfDeployVo> page = new Page<>(); |
| | | page.setRecords(deployVoList); |
| | | page.setTotal(pageTotal); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | /** |
| | | * æ¿æ´»ææèµ·æµç¨ |
| | | * |
| | | * @param state ç¶æ |
| | | * @param definitionId æµç¨å®ä¹ID |
| | | */ |
| | | @Override |
| | | public void updateState(String definitionId, String state) { |
| | | if (SuspensionState.ACTIVE.toString().equals(state)) { |
| | | // æ¿æ´» |
| | | repositoryService.activateProcessDefinitionById(definitionId, true, null); |
| | | } else if (SuspensionState.SUSPENDED.toString().equals(state)) { |
| | | // æèµ· |
| | | repositoryService.suspendProcessDefinitionById(definitionId, true, null); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public String queryBpmnXmlById(String definitionId) { |
| | | InputStream inputStream = repositoryService.getProcessModel(definitionId); |
| | | try { |
| | | return IoUtil.readUtf8(inputStream); |
| | | } catch (IORuntimeException exception) { |
| | | throw new RuntimeException("å è½½xmlæä»¶å¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteByIds(List<String> deployIds) { |
| | | for (String deployId : deployIds) { |
| | | repositoryService.deleteDeployment(deployId, true); |
| | | deployFormMapper.delete(new LambdaQueryWrapper<WfDeployForm>().eq(WfDeployForm::getDeployId, deployId)); |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.workflow.domain.WfForm; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfFormBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | import org.ruoyi.flowable.workflow.mapper.WfFormMapper; |
| | | import org.ruoyi.flowable.workflow.service.IWfFormService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æµç¨è¡¨åServiceä¸å¡å±å¤ç |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/7 22:07 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class WfFormServiceImpl implements IWfFormService { |
| | | |
| | | private final WfFormMapper baseMapper; |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¡¨å |
| | | * |
| | | * @param formId æµç¨è¡¨åID |
| | | * @return æµç¨è¡¨å |
| | | */ |
| | | @Override |
| | | public WfFormVo queryById(Long formId) { |
| | | return baseMapper.selectVoById(formId); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¡¨åå表 |
| | | * |
| | | * @param bo æµç¨è¡¨å |
| | | * @return æµç¨è¡¨å |
| | | */ |
| | | @Override |
| | | public TableDataInfo<WfFormVo> queryPageList(WfFormBo bo, PageQuery pageQuery) { |
| | | LambdaQueryWrapper<WfForm> lqw = buildQueryWrapper(bo); |
| | | Page<WfFormVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); |
| | | return TableDataInfo.build(result); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨è¡¨åå表 |
| | | * |
| | | * @param bo æµç¨è¡¨å |
| | | * @return æµç¨è¡¨å |
| | | */ |
| | | @Override |
| | | public List<WfFormVo> queryList(WfFormBo bo) { |
| | | LambdaQueryWrapper<WfForm> lqw = buildQueryWrapper(bo); |
| | | return baseMapper.selectVoList(lqw); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢æµç¨è¡¨å |
| | | * |
| | | * @param bo æµç¨è¡¨å |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public int insertForm(WfFormBo bo) { |
| | | WfForm wfForm = new WfForm(); |
| | | wfForm.setFormName(bo.getFormName()); |
| | | wfForm.setContent(bo.getContent()); |
| | | wfForm.setRemark(bo.getRemark()); |
| | | return baseMapper.insert(wfForm); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹æµç¨è¡¨å |
| | | * |
| | | * @param bo æµç¨è¡¨å |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public int updateForm(WfFormBo bo) { |
| | | return baseMapper.update(new WfForm(), new LambdaUpdateWrapper<WfForm>() |
| | | .set(StrUtil.isNotBlank(bo.getFormName()), WfForm::getFormName, bo.getFormName()) |
| | | .set(StrUtil.isNotBlank(bo.getContent()), WfForm::getContent, bo.getContent()) |
| | | .set(StrUtil.isNotBlank(bo.getRemark()), WfForm::getRemark, bo.getRemark()) |
| | | .eq(WfForm::getFormId, bo.getFormId())); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éå 餿µç¨è¡¨å |
| | | * |
| | | * @param ids éè¦å é¤çæµç¨è¡¨åID |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public Boolean deleteWithValidByIds(Collection<Long> ids) { |
| | | return baseMapper.deleteBatchIds(ids) > 0; |
| | | } |
| | | |
| | | private LambdaQueryWrapper<WfForm> buildQueryWrapper(WfFormBo bo) { |
| | | Map<String, Object> params = bo.getParams(); |
| | | LambdaQueryWrapper<WfForm> lqw = Wrappers.lambdaQuery(); |
| | | lqw.like(StringUtils.isNotBlank(bo.getFormName()), WfForm::getFormName, bo.getFormName()); |
| | | return lqw; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.date.BetweenFormatter; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.exception.ServiceException; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.flowable.common.constant.TaskConstants; |
| | | import org.ruoyi.flowable.factory.FlowServiceFactory; |
| | | import org.ruoyi.flowable.utils.JsonUtils; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfTaskBo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfTaskVo; |
| | | import org.ruoyi.flowable.workflow.service.IWfDeployFormService; |
| | | import org.ruoyi.flowable.workflow.service.IWfInstanceService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.flowable.common.engine.api.FlowableObjectNotFoundException; |
| | | import org.flowable.engine.history.HistoricProcessInstance; |
| | | import org.flowable.engine.task.Comment; |
| | | import org.flowable.identitylink.api.history.HistoricIdentityLink; |
| | | import org.flowable.task.api.history.HistoricTaskInstance; |
| | | import org.ruoyi.system.domain.SysDept; |
| | | import org.ruoyi.system.domain.SysRole; |
| | | import org.ruoyi.system.domain.SysUser; |
| | | import org.ruoyi.system.domain.vo.SysDeptVo; |
| | | import org.ruoyi.system.domain.vo.SysRoleVo; |
| | | import org.ruoyi.system.domain.vo.SysUserVo; |
| | | import org.ruoyi.system.service.ISysDeptService; |
| | | import org.ruoyi.system.service.ISysRoleService; |
| | | import org.ruoyi.system.service.ISysUserService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * 工使µæµç¨å®ä¾ç®¡ç |
| | | * |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | @Slf4j |
| | | public class WfInstanceServiceImpl extends FlowServiceFactory implements IWfInstanceService { |
| | | |
| | | private final IWfDeployFormService deployFormService; |
| | | private final ISysUserService userService; |
| | | private final ISysRoleService roleService; |
| | | private final ISysDeptService deptService; |
| | | @Autowired |
| | | private ISysUserService remoteUserService; |
| | | |
| | | /** |
| | | * ç»ææµç¨å®ä¾ |
| | | * |
| | | * @param vo |
| | | */ |
| | | @Override |
| | | public void stopProcessInstance(WfTaskBo vo) { |
| | | String taskId = vo.getTaskId(); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * æ¿æ´»ææèµ·æµç¨å®ä¾ |
| | | * |
| | | * @param state ç¶æ |
| | | * @param instanceId æµç¨å®ä¾ID |
| | | */ |
| | | @Override |
| | | public void updateState(Integer state, String instanceId) { |
| | | |
| | | // æ¿æ´» |
| | | if (state == 1) { |
| | | runtimeService.activateProcessInstanceById(instanceId); |
| | | } |
| | | // æèµ· |
| | | if (state == 2) { |
| | | runtimeService.suspendProcessInstanceById(instanceId); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å 餿µç¨å®ä¾ID |
| | | * |
| | | * @param instanceId æµç¨å®ä¾ID |
| | | * @param deleteReason å é¤åå |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void delete(String instanceId, String deleteReason) { |
| | | |
| | | // æ¥è¯¢å岿°æ® |
| | | HistoricProcessInstance historicProcessInstance = getHistoricProcessInstanceById(instanceId); |
| | | if (historicProcessInstance.getEndTime() != null) { |
| | | historyService.deleteHistoricProcessInstance(historicProcessInstance.getId()); |
| | | return; |
| | | } |
| | | // å 餿µç¨å®ä¾ |
| | | runtimeService.deleteProcessInstance(instanceId, deleteReason); |
| | | // å é¤å岿µç¨å®ä¾ |
| | | historyService.deleteHistoricProcessInstance(instanceId); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®å®ä¾IDæ¥è¯¢åå²å®ä¾æ°æ® |
| | | * |
| | | * @param processInstanceId |
| | | * @return |
| | | */ |
| | | @Override |
| | | public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) { |
| | | HistoricProcessInstance historicProcessInstance = |
| | | historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); |
| | | if (Objects.isNull(historicProcessInstance)) { |
| | | throw new FlowableObjectNotFoundException("æµç¨å®ä¾ä¸åå¨: " + processInstanceId); |
| | | } |
| | | return historicProcessInstance; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * æµç¨å岿µè½¬è®°å½ |
| | | * |
| | | * @param procInsId æµç¨å®ä¾Id |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Map<String, Object> queryDetailProcess(String procInsId, String deployId) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | if (StringUtils.isNotBlank(procInsId)) { |
| | | List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery() |
| | | .processInstanceId(procInsId) |
| | | .orderByHistoricTaskInstanceStartTime().desc() |
| | | .list(); |
| | | List<Comment> commentList = taskService.getProcessInstanceComments(procInsId); |
| | | List<WfTaskVo> taskVoList = new ArrayList<>(taskInstanceList.size()); |
| | | taskInstanceList.forEach(taskInstance -> { |
| | | WfTaskVo taskVo = new WfTaskVo(); |
| | | taskVo.setProcDefId(taskInstance.getProcessDefinitionId()); |
| | | taskVo.setTaskId(taskInstance.getId()); |
| | | taskVo.setTaskDefKey(taskInstance.getTaskDefinitionKey()); |
| | | taskVo.setTaskName(taskInstance.getName()); |
| | | taskVo.setCreateTime(taskInstance.getStartTime()); |
| | | taskVo.setFinishTime(taskInstance.getEndTime()); |
| | | if (StringUtils.isNotBlank(taskInstance.getAssignee())) { |
| | | Long userId = Long.parseLong(taskInstance.getAssignee()); |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | taskVo.setAssigneeId(userId); |
| | | taskVo.setAssigneeName(user.getNickName()); |
| | | } |
| | | } |
| | | // å±ç¤ºå®¡æ¹äººå |
| | | List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(taskInstance.getId()); |
| | | StringBuilder stringBuilder = new StringBuilder(); |
| | | for (HistoricIdentityLink identityLink : linksForTask) { |
| | | if ("candidate".equals(identityLink.getType())) { |
| | | if (StringUtils.isNotBlank(identityLink.getUserId())) { |
| | | Long userId = Long.parseLong(identityLink.getUserId()); |
| | | String nickName =""; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | stringBuilder.append(nickName).append(","); |
| | | } |
| | | if (StringUtils.isNotBlank(identityLink.getGroupId())) { |
| | | if (identityLink.getGroupId().startsWith(TaskConstants.ROLE_GROUP_PREFIX)) { |
| | | Long roleId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.ROLE_GROUP_PREFIX)); |
| | | //finish do æ¥è¯¢è§è²åç§° |
| | | SysRoleVo roleR=roleService.selectRoleById(roleId); |
| | | if (!ObjectUtil.isNull(roleR)) { |
| | | stringBuilder.append(roleR.getRoleName()).append(","); |
| | | } |
| | | } else if (identityLink.getGroupId().startsWith(TaskConstants.DEPT_GROUP_PREFIX)) { |
| | | Long deptId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.DEPT_GROUP_PREFIX)); |
| | | //finish do æ¥è¯¢é¨é¨åç§° |
| | | SysDeptVo deptR=deptService.selectDeptById(deptId); |
| | | if (!ObjectUtil.isNull(deptR)) { |
| | | stringBuilder.append(deptR.getDeptName()).append(","); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | if (StringUtils.isNotBlank(stringBuilder)) { |
| | | taskVo.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); |
| | | } |
| | | if (ObjectUtil.isNotNull(taskInstance.getDurationInMillis())) { |
| | | taskVo.setDuration(DateUtil.formatBetween(taskInstance.getDurationInMillis(), BetweenFormatter.Level.SECOND)); |
| | | } |
| | | // è·åæè§è¯è®ºå
容 |
| | | if (CollUtil.isNotEmpty(commentList)) { |
| | | List<Comment> comments = new ArrayList<>(); |
| | | // commentList.stream().filter(comment -> taskInstance.getId().equals(comment.getTaskId())).collect(Collectors.toList()); |
| | | for (Comment comment : commentList) { |
| | | if (comment.getTaskId().equals(taskInstance.getId())) { |
| | | comments.add(comment); |
| | | // taskVo.setComment(WfCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build()); |
| | | } |
| | | } |
| | | taskVo.setCommentList(comments); |
| | | } |
| | | taskVoList.add(taskVo); |
| | | }); |
| | | map.put("flowList", taskVoList); |
| | | // // æ¥è¯¢å½å任塿¯å¦å®æ |
| | | // List<Task> taskList = taskService.createTaskQuery().processInstanceId(procInsId).list(); |
| | | // if (CollectionUtils.isNotEmpty(taskList)) { |
| | | // map.put("finished", true); |
| | | // } else { |
| | | // map.put("finished", false); |
| | | // } |
| | | } |
| | | // ç¬¬ä¸æ¬¡ç³è¯·è·ååå§å表å |
| | | if (StringUtils.isNotBlank(deployId)) { |
| | | WfFormVo formVo = deployFormService.selectDeployFormByDeployId(deployId); |
| | | if (Objects.isNull(formVo)) { |
| | | throw new ServiceException("请å
é
ç½®æµç¨è¡¨å"); |
| | | } |
| | | map.put("formData", JsonUtils.parseObject(formVo.getContent(), Map.class)); |
| | | } |
| | | return map; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | import cn.hutool.core.util.ArrayUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.common.satoken.utils.LoginHelper; |
| | | import org.ruoyi.flowable.common.constant.ProcessConstants; |
| | | import org.ruoyi.flowable.common.enums.FormType; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.factory.FlowServiceFactory; |
| | | import org.ruoyi.flowable.utils.JsonUtils; |
| | | import org.ruoyi.flowable.utils.ModelUtils; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfModelBo; |
| | | import org.ruoyi.flowable.workflow.domain.dto.WfMetaInfoDto; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfFormVo; |
| | | import org.ruoyi.flowable.workflow.domain.vo.WfModelVo; |
| | | import org.ruoyi.flowable.workflow.service.IWfDeployFormService; |
| | | import org.ruoyi.flowable.workflow.service.IWfFormService; |
| | | import org.ruoyi.flowable.workflow.service.IWfModelService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.flowable.bpmn.model.BpmnModel; |
| | | import org.flowable.bpmn.model.StartEvent; |
| | | import org.flowable.engine.repository.Deployment; |
| | | import org.flowable.engine.repository.Model; |
| | | import org.flowable.engine.repository.ModelQuery; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/6/21 9:11 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | @Slf4j |
| | | public class WfModelServiceImpl extends FlowServiceFactory implements IWfModelService { |
| | | |
| | | private final IWfFormService formService; |
| | | private final IWfDeployFormService deployFormService; |
| | | |
| | | @Override |
| | | public TableDataInfo<WfModelVo> list(WfModelBo modelBo, PageQuery pageQuery) { |
| | | ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByCreateTime().desc(); |
| | | // æå»ºæ¥è¯¢æ¡ä»¶ |
| | | if (StringUtils.isNotBlank(modelBo.getModelKey())) { |
| | | modelQuery.modelKey(modelBo.getModelKey()); |
| | | } |
| | | if (StringUtils.isNotBlank(modelBo.getModelName())) { |
| | | modelQuery.modelNameLike("%" + modelBo.getModelName() + "%"); |
| | | } |
| | | if (StringUtils.isNotBlank(modelBo.getCategory())) { |
| | | modelQuery.modelCategory(modelBo.getCategory()); |
| | | } |
| | | // æ§è¡æ¥è¯¢ |
| | | long pageTotal = modelQuery.count(); |
| | | if (pageTotal <= 0) { |
| | | return TableDataInfo.build(); |
| | | } |
| | | int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<Model> modelList = modelQuery.listPage(offset, pageQuery.getPageSize()); |
| | | List<WfModelVo> modelVoList = new ArrayList<>(modelList.size()); |
| | | modelList.forEach(model -> { |
| | | WfModelVo modelVo = new WfModelVo(); |
| | | modelVo.setModelId(model.getId()); |
| | | modelVo.setModelName(model.getName()); |
| | | modelVo.setModelKey(model.getKey()); |
| | | modelVo.setCategory(model.getCategory()); |
| | | modelVo.setCreateTime(model.getCreateTime()); |
| | | modelVo.setVersion(model.getVersion()); |
| | | WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class); |
| | | if (metaInfo != null) { |
| | | modelVo.setDescription(metaInfo.getDescription()); |
| | | modelVo.setFormType(metaInfo.getFormType()); |
| | | modelVo.setFormId(metaInfo.getFormId()); |
| | | } |
| | | modelVoList.add(modelVo); |
| | | }); |
| | | Page<WfModelVo> page = new Page<>(); |
| | | page.setRecords(modelVoList); |
| | | page.setTotal(pageTotal); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | @Override |
| | | public List<WfModelVo> list(WfModelBo modelBo) { |
| | | ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByCreateTime().desc(); |
| | | // æå»ºæ¥è¯¢æ¡ä»¶ |
| | | if (StringUtils.isNotBlank(modelBo.getModelKey())) { |
| | | modelQuery.modelKey(modelBo.getModelKey()); |
| | | } |
| | | if (StringUtils.isNotBlank(modelBo.getModelName())) { |
| | | modelQuery.modelNameLike("%" + modelBo.getModelName() + "%"); |
| | | } |
| | | if (StringUtils.isNotBlank(modelBo.getCategory())) { |
| | | modelQuery.modelCategory(modelBo.getCategory()); |
| | | } |
| | | List<Model> modelList = modelQuery.list(); |
| | | List<WfModelVo> modelVoList = new ArrayList<>(modelList.size()); |
| | | modelList.forEach(model -> { |
| | | WfModelVo modelVo = new WfModelVo(); |
| | | modelVo.setModelId(model.getId()); |
| | | modelVo.setModelName(model.getName()); |
| | | modelVo.setModelKey(model.getKey()); |
| | | modelVo.setCategory(model.getCategory()); |
| | | modelVo.setCreateTime(model.getCreateTime()); |
| | | modelVo.setVersion(model.getVersion()); |
| | | WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class); |
| | | if (metaInfo != null) { |
| | | modelVo.setDescription(metaInfo.getDescription()); |
| | | modelVo.setFormType(metaInfo.getFormType()); |
| | | modelVo.setFormId(metaInfo.getFormId()); |
| | | } |
| | | modelVoList.add(modelVo); |
| | | }); |
| | | return modelVoList; |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<WfModelVo> historyList(WfModelBo modelBo, PageQuery pageQuery) { |
| | | ModelQuery modelQuery = repositoryService.createModelQuery() |
| | | .modelKey(modelBo.getModelKey()) |
| | | .orderByModelVersion() |
| | | .desc(); |
| | | // æ§è¡æ¥è¯¢ï¼ä¸æ¾ç¤ºææ°çï¼-1ï¼ |
| | | long pageTotal = modelQuery.count() - 1; |
| | | if (pageTotal <= 0) { |
| | | return TableDataInfo.build(); |
| | | } |
| | | // offset+1ï¼å»æææ°ç |
| | | int offset = 1 + pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<Model> modelList = modelQuery.listPage(offset, pageQuery.getPageSize()); |
| | | List<WfModelVo> modelVoList = new ArrayList<>(modelList.size()); |
| | | modelList.forEach(model -> { |
| | | WfModelVo modelVo = new WfModelVo(); |
| | | modelVo.setModelId(model.getId()); |
| | | modelVo.setModelName(model.getName()); |
| | | modelVo.setModelKey(model.getKey()); |
| | | modelVo.setCategory(model.getCategory()); |
| | | modelVo.setCreateTime(model.getCreateTime()); |
| | | modelVo.setVersion(model.getVersion()); |
| | | WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class); |
| | | if (metaInfo != null) { |
| | | modelVo.setDescription(metaInfo.getDescription()); |
| | | modelVo.setFormType(metaInfo.getFormType()); |
| | | modelVo.setFormId(metaInfo.getFormId()); |
| | | } |
| | | modelVoList.add(modelVo); |
| | | }); |
| | | Page<WfModelVo> page = new Page<>(); |
| | | page.setRecords(modelVoList); |
| | | page.setTotal(pageTotal); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | @Override |
| | | public WfModelVo getModel(String modelId) { |
| | | // è·åæµç¨æ¨¡å |
| | | Model model = repositoryService.getModel(modelId); |
| | | if (ObjectUtil.isNull(model)) { |
| | | throw new RuntimeException("æµç¨æ¨¡åä¸åå¨ï¼"); |
| | | } |
| | | // è·åæµç¨å¾ |
| | | String bpmnXml = queryBpmnXmlById(modelId); |
| | | WfModelVo modelVo = new WfModelVo(); |
| | | modelVo.setModelId(model.getId()); |
| | | modelVo.setModelName(model.getName()); |
| | | modelVo.setModelKey(model.getKey()); |
| | | modelVo.setCategory(model.getCategory()); |
| | | modelVo.setCreateTime(model.getCreateTime()); |
| | | modelVo.setVersion(model.getVersion()); |
| | | modelVo.setBpmnXml(bpmnXml); |
| | | WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class); |
| | | if (metaInfo != null) { |
| | | modelVo.setDescription(metaInfo.getDescription()); |
| | | modelVo.setFormType(metaInfo.getFormType()); |
| | | modelVo.setFormId(metaInfo.getFormId()); |
| | | if (FormType.PROCESS.getType().equals(metaInfo.getFormType())) { |
| | | WfFormVo wfFormVo = formService.queryById(metaInfo.getFormId()); |
| | | modelVo.setContent(wfFormVo.getContent()); |
| | | } |
| | | } |
| | | return modelVo; |
| | | } |
| | | |
| | | @Override |
| | | public String queryBpmnXmlById(String modelId) { |
| | | byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId); |
| | | return StrUtil.utf8Str(bpmnBytes); |
| | | } |
| | | |
| | | @Override |
| | | public void insertModel(WfModelBo modelBo) { |
| | | Model model = repositoryService.newModel(); |
| | | model.setName(modelBo.getModelName()); |
| | | model.setKey(modelBo.getModelKey()); |
| | | model.setCategory(modelBo.getCategory()); |
| | | String metaInfo = buildMetaInfo(new WfMetaInfoDto(), modelBo.getDescription()); |
| | | model.setMetaInfo(metaInfo); |
| | | // ä¿åæµç¨æ¨¡å |
| | | repositoryService.saveModel(model); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateModel(WfModelBo modelBo) { |
| | | // æ ¹æ®æ¨¡åKeyæ¥è¯¢æ¨¡åä¿¡æ¯ |
| | | Model model = repositoryService.getModel(modelBo.getModelId()); |
| | | if (ObjectUtil.isNull(model)) { |
| | | throw new RuntimeException("æµç¨æ¨¡åä¸åå¨ï¼"); |
| | | } |
| | | model.setCategory(modelBo.getCategory()); |
| | | WfMetaInfoDto metaInfoDto = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class); |
| | | String metaInfo = buildMetaInfo(metaInfoDto, modelBo.getDescription()); |
| | | model.setMetaInfo(metaInfo); |
| | | // ä¿åæµç¨æ¨¡å |
| | | repositoryService.saveModel(model); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void saveModel(WfModelBo modelBo) { |
| | | // æ¥è¯¢æ¨¡åä¿¡æ¯ |
| | | Model model = repositoryService.getModel(modelBo.getModelId()); |
| | | if (ObjectUtil.isNull(model)) { |
| | | throw new RuntimeException("æµç¨æ¨¡åä¸åå¨ï¼"); |
| | | } |
| | | BpmnModel bpmnModel = ModelUtils.getBpmnModel(modelBo.getBpmnXml()); |
| | | if (ObjectUtil.isEmpty(bpmnModel)) { |
| | | throw new RuntimeException("è·å模å设计失败ï¼"); |
| | | } |
| | | String processName = bpmnModel.getMainProcess().getName(); |
| | | // è·åå¼å§èç¹ |
| | | StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel); |
| | | if (ObjectUtil.isNull(startEvent)) { |
| | | throw new RuntimeException("å¼å§èç¹ä¸åå¨ï¼è¯·æ£æ¥æµç¨è®¾è®¡æ¯å¦æè¯¯ï¼"); |
| | | } |
| | | // è·åå¼å§èç¹é
ç½®ç表åKey |
| | | if (StrUtil.isBlank(startEvent.getFormKey())) { |
| | | throw new RuntimeException("请é
ç½®æµç¨è¡¨å"); |
| | | } |
| | | Model newModel; |
| | | if (Boolean.TRUE.equals(modelBo.getNewVersion())) { |
| | | newModel = repositoryService.newModel(); |
| | | newModel.setName(processName); |
| | | newModel.setKey(model.getKey()); |
| | | newModel.setCategory(model.getCategory()); |
| | | newModel.setMetaInfo(model.getMetaInfo()); |
| | | newModel.setVersion(model.getVersion() + 1); |
| | | } else { |
| | | newModel = model; |
| | | // 设置æµç¨åç§° |
| | | newModel.setName(processName); |
| | | } |
| | | // ä¿åæµç¨æ¨¡å |
| | | repositoryService.saveModel(newModel); |
| | | // ä¿å BPMN XML |
| | | byte[] bpmnXmlBytes = StringUtils.getBytes(modelBo.getBpmnXml(), StandardCharsets.UTF_8); |
| | | repositoryService.addModelEditorSource(newModel.getId(), bpmnXmlBytes); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void latestModel(String modelId) { |
| | | // è·åæµç¨æ¨¡å |
| | | Model model = repositoryService.getModel(modelId); |
| | | if (ObjectUtil.isNull(model)) { |
| | | throw new RuntimeException("æµç¨æ¨¡åä¸åå¨ï¼"); |
| | | } |
| | | Integer latestVersion = repositoryService.createModelQuery() |
| | | .modelKey(model.getKey()) |
| | | .latestVersion() |
| | | .singleResult() |
| | | .getVersion(); |
| | | if (model.getVersion().equals(latestVersion)) { |
| | | throw new RuntimeException("å½åçæ¬å·²æ¯ææ°çï¼"); |
| | | } |
| | | // è·å BPMN XML |
| | | byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId); |
| | | Model newModel = repositoryService.newModel(); |
| | | newModel.setName(model.getName()); |
| | | newModel.setKey(model.getKey()); |
| | | newModel.setCategory(model.getCategory()); |
| | | newModel.setMetaInfo(model.getMetaInfo()); |
| | | newModel.setVersion(latestVersion + 1); |
| | | // ä¿åæµç¨æ¨¡å |
| | | repositoryService.saveModel(newModel); |
| | | // ä¿å BPMN XML |
| | | repositoryService.addModelEditorSource(newModel.getId(), bpmnBytes); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteByIds(Collection<String> ids) { |
| | | ids.forEach(id -> { |
| | | Model model = repositoryService.getModel(id); |
| | | if (ObjectUtil.isNull(model)) { |
| | | throw new RuntimeException("æµç¨æ¨¡åä¸åå¨ï¼"); |
| | | } |
| | | repositoryService.deleteModel(id); |
| | | }); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean deployModel(String modelId) { |
| | | // è·åæµç¨æ¨¡å |
| | | Model model = repositoryService.getModel(modelId); |
| | | if (ObjectUtil.isNull(model)) { |
| | | throw new RuntimeException("æµç¨æ¨¡åä¸åå¨ï¼"); |
| | | } |
| | | // è·åæµç¨å¾ |
| | | byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId); |
| | | if (ArrayUtil.isEmpty(bpmnBytes)) { |
| | | throw new RuntimeException("请å
设计æµç¨å¾ï¼"); |
| | | } |
| | | String bpmnXml = StringUtils.toEncodedString(bpmnBytes, StandardCharsets.UTF_8); |
| | | BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnXml); |
| | | String processName = model.getName() + ProcessConstants.SUFFIX; |
| | | // é¨ç½²æµç¨ |
| | | Deployment deployment = repositoryService.createDeployment() |
| | | .name(model.getName()) |
| | | .key(model.getKey()) |
| | | .category(model.getCategory()) |
| | | .addBytes(processName, bpmnBytes) |
| | | .deploy(); |
| | | ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery() |
| | | .deploymentId(deployment.getId()) |
| | | .singleResult(); |
| | | // ä¿®æ¹æµç¨å®ä¹çåç±»ï¼ä¾¿äºæç´¢æµç¨ |
| | | repositoryService.setProcessDefinitionCategory(procDef.getId(), model.getCategory()); |
| | | // ä¿åé¨ç½²è¡¨å |
| | | return deployFormService.saveInternalDeployForm(deployment.getId(), bpmnModel); |
| | | } |
| | | |
| | | /** |
| | | * æå»ºæ¨¡åæ©å±ä¿¡æ¯ |
| | | * @return |
| | | */ |
| | | private String buildMetaInfo(WfMetaInfoDto metaInfo, String description) { |
| | | // åªæéç©ºï¼æè¿è¡è®¾ç½®ï¼é¿å
æ´æ°æ¶çè¦ç |
| | | if (StringUtils.isNotEmpty(description)) { |
| | | metaInfo.setDescription(description); |
| | | } |
| | | if (StringUtils.isNotEmpty(metaInfo.getCreateUser())) { |
| | | // è·åå½åçç¨æ· |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | if (ObjectUtil.isNotNull(loginUser)){ |
| | | metaInfo.setCreateUser(loginUser.getUsername()); |
| | | } |
| | | } |
| | | return JsonUtils.toJsonString(metaInfo); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.date.BetweenFormatter; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.hutool.core.io.IORuntimeException; |
| | | import cn.hutool.core.io.IoUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.exception.ServiceException; |
| | | import org.ruoyi.common.core.utils.DateUtils; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.flowable.common.constant.ProcessConstants; |
| | | import org.ruoyi.flowable.common.constant.TaskConstants; |
| | | import org.ruoyi.flowable.common.enums.ProcessStatus; |
| | | import org.ruoyi.flowable.core.FormConf; |
| | | import org.ruoyi.flowable.core.domain.ProcessQuery; |
| | | import org.ruoyi.flowable.core.domain.model.PageQuery; |
| | | import org.ruoyi.flowable.core.page.TableDataInfo; |
| | | import org.ruoyi.flowable.factory.FlowServiceFactory; |
| | | import org.ruoyi.flowable.flow.FlowableUtils; |
| | | import org.ruoyi.flowable.utils.*; |
| | | import org.ruoyi.flowable.workflow.domain.WfDeployForm; |
| | | import org.ruoyi.flowable.workflow.domain.vo.*; |
| | | import org.ruoyi.flowable.workflow.mapper.WfDeployFormMapper; |
| | | import org.ruoyi.flowable.workflow.service.IWfProcessService; |
| | | import org.ruoyi.flowable.workflow.service.IWfTaskService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.flowable.bpmn.constants.BpmnXMLConstants; |
| | | import org.flowable.bpmn.model.Process; |
| | | import org.flowable.bpmn.model.*; |
| | | import org.flowable.engine.history.HistoricActivityInstance; |
| | | import org.flowable.engine.history.HistoricActivityInstanceQuery; |
| | | import org.flowable.engine.history.HistoricProcessInstance; |
| | | import org.flowable.engine.history.HistoricProcessInstanceQuery; |
| | | import org.flowable.engine.repository.Deployment; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | import org.flowable.engine.repository.ProcessDefinitionQuery; |
| | | import org.flowable.engine.runtime.ProcessInstance; |
| | | import org.flowable.engine.task.Comment; |
| | | import org.flowable.identitylink.api.history.HistoricIdentityLink; |
| | | import org.flowable.task.api.Task; |
| | | import org.flowable.task.api.TaskQuery; |
| | | import org.flowable.task.api.history.HistoricTaskInstance; |
| | | import org.flowable.task.api.history.HistoricTaskInstanceQuery; |
| | | import org.flowable.variable.api.history.HistoricVariableInstance; |
| | | import org.ruoyi.system.domain.SysDept; |
| | | import org.ruoyi.system.domain.SysRole; |
| | | import org.ruoyi.system.domain.SysUser; |
| | | import org.ruoyi.system.domain.vo.SysDeptVo; |
| | | import org.ruoyi.system.domain.vo.SysRoleVo; |
| | | import org.ruoyi.system.domain.vo.SysUserVo; |
| | | import org.ruoyi.system.service.ISysDeptService; |
| | | import org.ruoyi.system.service.ISysRoleService; |
| | | import org.ruoyi.system.service.ISysUserService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.io.InputStream; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/3/24 18:57 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProcessService { |
| | | |
| | | private final IWfTaskService wfTaskService; |
| | | private final ISysUserService userService; |
| | | private final WfDeployFormMapper deployFormMapper; |
| | | private final ISysDeptService deptService; |
| | | private final ISysRoleService roleService; |
| | | @Autowired |
| | | private ISysUserService remoteUserService; |
| | | @Autowired |
| | | private ISysDeptService remoteDeptService; |
| | | /** |
| | | * æµç¨å®ä¹å表 |
| | | * |
| | | * @param pageQuery å页忰 |
| | | * @return æµç¨å®ä¹å页åè¡¨æ°æ® |
| | | */ |
| | | @Override |
| | | public TableDataInfo<WfDefinitionVo> selectPageStartProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | Page<WfDefinitionVo> page = new Page<>(); |
| | | // æµç¨å®ä¹åè¡¨æ°æ®æ¥è¯¢ |
| | | ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery() |
| | | .latestVersion() |
| | | .active() |
| | | .orderByProcessDefinitionKey() |
| | | .asc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(processDefinitionQuery, processQuery); |
| | | long pageTotal = processDefinitionQuery.count(); |
| | | if (pageTotal <= 0) { |
| | | return TableDataInfo.build(); |
| | | } |
| | | int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<ProcessDefinition> definitionList = processDefinitionQuery.listPage(offset, pageQuery.getPageSize()); |
| | | |
| | | List<WfDefinitionVo> definitionVoList = new ArrayList<>(); |
| | | for (ProcessDefinition processDefinition : definitionList) { |
| | | String deploymentId = processDefinition.getDeploymentId(); |
| | | Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); |
| | | WfDefinitionVo vo = new WfDefinitionVo(); |
| | | vo.setDefinitionId(processDefinition.getId()); |
| | | vo.setProcessKey(processDefinition.getKey()); |
| | | vo.setProcessName(processDefinition.getName()); |
| | | vo.setVersion(processDefinition.getVersion()); |
| | | vo.setDeploymentId(processDefinition.getDeploymentId()); |
| | | vo.setSuspended(processDefinition.isSuspended()); |
| | | // æµç¨å®ä¹æ¶é´ |
| | | vo.setCategory(deployment.getCategory()); |
| | | vo.setDeploymentTime(deployment.getDeploymentTime()); |
| | | definitionVoList.add(vo); |
| | | } |
| | | page.setRecords(definitionVoList); |
| | | page.setTotal(pageTotal); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | @Override |
| | | public List<WfDefinitionVo> selectStartProcessList(ProcessQuery processQuery) { |
| | | // æµç¨å®ä¹åè¡¨æ°æ®æ¥è¯¢ |
| | | ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery() |
| | | .latestVersion() |
| | | .active() |
| | | .orderByProcessDefinitionKey() |
| | | .asc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(processDefinitionQuery, processQuery); |
| | | |
| | | List<ProcessDefinition> definitionList = processDefinitionQuery.list(); |
| | | |
| | | List<WfDefinitionVo> definitionVoList = new ArrayList<>(); |
| | | for (ProcessDefinition processDefinition : definitionList) { |
| | | String deploymentId = processDefinition.getDeploymentId(); |
| | | Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); |
| | | WfDefinitionVo vo = new WfDefinitionVo(); |
| | | vo.setDefinitionId(processDefinition.getId()); |
| | | vo.setProcessKey(processDefinition.getKey()); |
| | | vo.setProcessName(processDefinition.getName()); |
| | | vo.setVersion(processDefinition.getVersion()); |
| | | vo.setDeploymentId(processDefinition.getDeploymentId()); |
| | | vo.setSuspended(processDefinition.isSuspended()); |
| | | // æµç¨å®ä¹æ¶é´ |
| | | vo.setCategory(deployment.getCategory()); |
| | | vo.setDeploymentTime(deployment.getDeploymentTime()); |
| | | definitionVoList.add(vo); |
| | | } |
| | | return definitionVoList; |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<WfTaskVo> selectPageOwnProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | Page<WfTaskVo> page = new Page<>(); |
| | | HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery() |
| | | .startedBy(TaskUtils.getUserId()) |
| | | .orderByProcessInstanceStartTime() |
| | | .desc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(historicProcessInstanceQuery, processQuery); |
| | | int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery |
| | | .listPage(offset, pageQuery.getPageSize()); |
| | | page.setTotal(historicProcessInstanceQuery.count()); |
| | | List<WfTaskVo> taskVoList = new ArrayList<>(); |
| | | for (HistoricProcessInstance hisIns : historicProcessInstances) { |
| | | WfTaskVo taskVo = new WfTaskVo(); |
| | | // è·åæµç¨ç¶æ |
| | | HistoricVariableInstance processStatusVariable = historyService.createHistoricVariableInstanceQuery() |
| | | .processInstanceId(hisIns.getId()) |
| | | .variableName(ProcessConstants.PROCESS_STATUS_KEY) |
| | | .singleResult(); |
| | | String processStatus = null; |
| | | if (ObjectUtil.isNotNull(processStatusVariable)) { |
| | | processStatus = Convert.toStr(processStatusVariable.getValue()); |
| | | } |
| | | // å
¼å®¹æ§æµç¨ |
| | | if (processStatus == null) { |
| | | processStatus = ObjectUtil.isNull(hisIns.getEndTime()) ? ProcessStatus.RUNNING.getStatus() : ProcessStatus.COMPLETED.getStatus(); |
| | | } |
| | | taskVo.setProcessStatus(processStatus); |
| | | taskVo.setCreateTime(hisIns.getStartTime()); |
| | | taskVo.setFinishTime(hisIns.getEndTime()); |
| | | taskVo.setProcInsId(hisIns.getId()); |
| | | |
| | | // 计ç®èæ¶ |
| | | if (Objects.nonNull(hisIns.getEndTime())) { |
| | | taskVo.setDuration(DateUtils.getDatePoor(hisIns.getEndTime(), hisIns.getStartTime())); |
| | | } else { |
| | | taskVo.setDuration(DateUtils.getDatePoor(DateUtils.getNowDate(), hisIns.getStartTime())); |
| | | } |
| | | // æµç¨é¨ç½²å®ä¾ä¿¡æ¯ |
| | | Deployment deployment = repositoryService.createDeploymentQuery() |
| | | .deploymentId(hisIns.getDeploymentId()).singleResult(); |
| | | taskVo.setDeployId(hisIns.getDeploymentId()); |
| | | taskVo.setProcDefId(hisIns.getProcessDefinitionId()); |
| | | taskVo.setProcDefName(hisIns.getProcessDefinitionName()); |
| | | taskVo.setProcDefVersion(hisIns.getProcessDefinitionVersion()); |
| | | taskVo.setCategory(deployment.getCategory()); |
| | | // å½åæå¤æµç¨ |
| | | List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).includeIdentityLinks().list(); |
| | | if (CollUtil.isNotEmpty(taskList)) { |
| | | taskVo.setTaskName(taskList.stream().map(Task::getName).filter(StringUtils::isNotEmpty).collect(Collectors.joining(","))); |
| | | } |
| | | taskVoList.add(taskVo); |
| | | } |
| | | page.setRecords(taskVoList); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | @Override |
| | | public List<WfTaskVo> selectOwnProcessList(ProcessQuery processQuery) { |
| | | HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery() |
| | | .startedBy(TaskUtils.getUserId()) |
| | | .orderByProcessInstanceStartTime() |
| | | .desc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(historicProcessInstanceQuery, processQuery); |
| | | List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.list(); |
| | | List<WfTaskVo> taskVoList = new ArrayList<>(); |
| | | for (HistoricProcessInstance hisIns : historicProcessInstances) { |
| | | WfTaskVo taskVo = new WfTaskVo(); |
| | | taskVo.setCreateTime(hisIns.getStartTime()); |
| | | taskVo.setFinishTime(hisIns.getEndTime()); |
| | | taskVo.setProcInsId(hisIns.getId()); |
| | | |
| | | // 计ç®èæ¶ |
| | | if (Objects.nonNull(hisIns.getEndTime())) { |
| | | taskVo.setDuration(DateUtils.getDatePoor(hisIns.getEndTime(), hisIns.getStartTime())); |
| | | } else { |
| | | taskVo.setDuration(DateUtils.getDatePoor(DateUtils.getNowDate(), hisIns.getStartTime())); |
| | | } |
| | | // æµç¨é¨ç½²å®ä¾ä¿¡æ¯ |
| | | Deployment deployment = repositoryService.createDeploymentQuery() |
| | | .deploymentId(hisIns.getDeploymentId()).singleResult(); |
| | | taskVo.setDeployId(hisIns.getDeploymentId()); |
| | | taskVo.setProcDefId(hisIns.getProcessDefinitionId()); |
| | | taskVo.setProcDefName(hisIns.getProcessDefinitionName()); |
| | | taskVo.setProcDefVersion(hisIns.getProcessDefinitionVersion()); |
| | | taskVo.setCategory(deployment.getCategory()); |
| | | // å½åæå¤æµç¨ |
| | | List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).includeIdentityLinks().list(); |
| | | if (CollUtil.isNotEmpty(taskList)) { |
| | | taskVo.setTaskName(taskList.stream().map(Task::getName).filter(StringUtils::isNotEmpty).collect(Collectors.joining(","))); |
| | | } |
| | | taskVoList.add(taskVo); |
| | | } |
| | | return taskVoList; |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<WfTaskVo> selectPageTodoProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | Page<WfTaskVo> page = new Page<>(); |
| | | TaskQuery taskQuery = taskService.createTaskQuery() |
| | | .active() |
| | | .includeProcessVariables() |
| | | .taskCandidateOrAssigned(TaskUtils.getUserId()) |
| | | .taskCandidateGroupIn(TaskUtils.getCandidateGroup()) |
| | | .orderByTaskCreateTime().desc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(taskQuery, processQuery); |
| | | page.setTotal(taskQuery.count()); |
| | | int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<Task> taskList = taskQuery.listPage(offset, pageQuery.getPageSize()); |
| | | List<WfTaskVo> flowList = new ArrayList<>(); |
| | | for (Task task : taskList) { |
| | | WfTaskVo flowTask = new WfTaskVo(); |
| | | // å½åæµç¨ä¿¡æ¯ |
| | | flowTask.setTaskId(task.getId()); |
| | | flowTask.setTaskDefKey(task.getTaskDefinitionKey()); |
| | | flowTask.setCreateTime(task.getCreateTime()); |
| | | flowTask.setProcDefId(task.getProcessDefinitionId()); |
| | | flowTask.setTaskName(task.getName()); |
| | | // æµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionId(task.getProcessDefinitionId()) |
| | | .singleResult(); |
| | | flowTask.setDeployId(pd.getDeploymentId()); |
| | | flowTask.setProcDefName(pd.getName()); |
| | | flowTask.setProcDefVersion(pd.getVersion()); |
| | | flowTask.setProcInsId(task.getProcessInstanceId()); |
| | | flowTask.setCategory(pd.getCategory()); |
| | | // æµç¨åèµ·äººä¿¡æ¯ |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(task.getProcessInstanceId()) |
| | | .singleResult(); |
| | | Long userId = Long.parseLong(historicProcessInstance.getStartUserId()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | flowTask.setStartUserId(userId); |
| | | flowTask.setStartUserName(nickName); |
| | | |
| | | // æµç¨åé |
| | | flowTask.setProcVars(task.getProcessVariables()); |
| | | |
| | | flowList.add(flowTask); |
| | | } |
| | | page.setRecords(flowList); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | @Override |
| | | public List<WfTaskVo> selectTodoProcessList(ProcessQuery processQuery) { |
| | | TaskQuery taskQuery = taskService.createTaskQuery() |
| | | .active() |
| | | .includeProcessVariables() |
| | | .taskCandidateOrAssigned(TaskUtils.getUserId()) |
| | | .taskCandidateGroupIn(TaskUtils.getCandidateGroup()) |
| | | .orderByTaskCreateTime().desc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(taskQuery, processQuery); |
| | | List<Task> taskList = taskQuery.list(); |
| | | List<WfTaskVo> taskVoList = new ArrayList<>(); |
| | | for (Task task : taskList) { |
| | | WfTaskVo taskVo = new WfTaskVo(); |
| | | // å½åæµç¨ä¿¡æ¯ |
| | | taskVo.setTaskId(task.getId()); |
| | | taskVo.setTaskDefKey(task.getTaskDefinitionKey()); |
| | | taskVo.setCreateTime(task.getCreateTime()); |
| | | taskVo.setProcDefId(task.getProcessDefinitionId()); |
| | | taskVo.setTaskName(task.getName()); |
| | | // æµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionId(task.getProcessDefinitionId()) |
| | | .singleResult(); |
| | | taskVo.setDeployId(pd.getDeploymentId()); |
| | | taskVo.setProcDefName(pd.getName()); |
| | | taskVo.setProcDefVersion(pd.getVersion()); |
| | | taskVo.setProcInsId(task.getProcessInstanceId()); |
| | | |
| | | // æµç¨åèµ·äººä¿¡æ¯ |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(task.getProcessInstanceId()) |
| | | .singleResult(); |
| | | Long userId = Long.parseLong(historicProcessInstance.getStartUserId()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | taskVo.setStartUserId(userId); |
| | | taskVo.setStartUserName(nickName); |
| | | |
| | | taskVoList.add(taskVo); |
| | | } |
| | | return taskVoList; |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<WfTaskVo> selectPageClaimProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | Page<WfTaskVo> page = new Page<>(); |
| | | TaskQuery taskQuery = taskService.createTaskQuery() |
| | | .active() |
| | | .includeProcessVariables() |
| | | .taskCandidateUser(TaskUtils.getUserId()) |
| | | .taskCandidateGroupIn(TaskUtils.getCandidateGroup()) |
| | | .orderByTaskCreateTime().desc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(taskQuery, processQuery); |
| | | page.setTotal(taskQuery.count()); |
| | | int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<Task> taskList = taskQuery.listPage(offset, pageQuery.getPageSize()); |
| | | List<WfTaskVo> flowList = new ArrayList<>(); |
| | | for (Task task : taskList) { |
| | | WfTaskVo flowTask = new WfTaskVo(); |
| | | // å½åæµç¨ä¿¡æ¯ |
| | | flowTask.setTaskId(task.getId()); |
| | | flowTask.setTaskDefKey(task.getTaskDefinitionKey()); |
| | | flowTask.setCreateTime(task.getCreateTime()); |
| | | flowTask.setProcDefId(task.getProcessDefinitionId()); |
| | | flowTask.setTaskName(task.getName()); |
| | | // æµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionId(task.getProcessDefinitionId()) |
| | | .singleResult(); |
| | | flowTask.setDeployId(pd.getDeploymentId()); |
| | | flowTask.setProcDefName(pd.getName()); |
| | | flowTask.setProcDefVersion(pd.getVersion()); |
| | | flowTask.setProcInsId(task.getProcessInstanceId()); |
| | | |
| | | // æµç¨åèµ·äººä¿¡æ¯ |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(task.getProcessInstanceId()) |
| | | .singleResult(); |
| | | Long userId = Long.parseLong(historicProcessInstance.getStartUserId()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | flowTask.setStartUserId(userId); |
| | | flowTask.setStartUserName(nickName); |
| | | |
| | | flowList.add(flowTask); |
| | | } |
| | | page.setRecords(flowList); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | @Override |
| | | public List<WfTaskVo> selectClaimProcessList(ProcessQuery processQuery) { |
| | | TaskQuery taskQuery = taskService.createTaskQuery() |
| | | .active() |
| | | .includeProcessVariables() |
| | | .taskCandidateUser(TaskUtils.getUserId()) |
| | | .taskCandidateGroupIn(TaskUtils.getCandidateGroup()) |
| | | .orderByTaskCreateTime().desc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(taskQuery, processQuery); |
| | | List<Task> taskList = taskQuery.list(); |
| | | List<WfTaskVo> flowList = new ArrayList<>(); |
| | | for (Task task : taskList) { |
| | | WfTaskVo flowTask = new WfTaskVo(); |
| | | // å½åæµç¨ä¿¡æ¯ |
| | | flowTask.setTaskId(task.getId()); |
| | | flowTask.setTaskDefKey(task.getTaskDefinitionKey()); |
| | | flowTask.setCreateTime(task.getCreateTime()); |
| | | flowTask.setProcDefId(task.getProcessDefinitionId()); |
| | | flowTask.setTaskName(task.getName()); |
| | | // æµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionId(task.getProcessDefinitionId()) |
| | | .singleResult(); |
| | | flowTask.setDeployId(pd.getDeploymentId()); |
| | | flowTask.setProcDefName(pd.getName()); |
| | | flowTask.setProcDefVersion(pd.getVersion()); |
| | | flowTask.setProcInsId(task.getProcessInstanceId()); |
| | | |
| | | // æµç¨åèµ·äººä¿¡æ¯ |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(task.getProcessInstanceId()) |
| | | .singleResult(); |
| | | Long userId = Long.parseLong(historicProcessInstance.getStartUserId()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | flowTask.setStartUserId(userId); |
| | | flowTask.setStartUserName(nickName); |
| | | |
| | | flowList.add(flowTask); |
| | | } |
| | | return flowList; |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<WfTaskVo> selectPageFinishedProcessList(ProcessQuery processQuery, PageQuery pageQuery) { |
| | | Page<WfTaskVo> page = new Page<>(); |
| | | HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() |
| | | .includeProcessVariables() |
| | | .finished() |
| | | .taskAssignee(TaskUtils.getUserId()) |
| | | .orderByHistoricTaskInstanceEndTime() |
| | | .desc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(taskInstanceQuery, processQuery); |
| | | int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); |
| | | List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(offset, pageQuery.getPageSize()); |
| | | List<WfTaskVo> hisTaskList = new ArrayList<>(); |
| | | for (HistoricTaskInstance histTask : historicTaskInstanceList) { |
| | | WfTaskVo flowTask = new WfTaskVo(); |
| | | // å½åæµç¨ä¿¡æ¯ |
| | | flowTask.setTaskId(histTask.getId()); |
| | | // 审æ¹äººåä¿¡æ¯ |
| | | flowTask.setCreateTime(histTask.getCreateTime()); |
| | | flowTask.setFinishTime(histTask.getEndTime()); |
| | | flowTask.setDuration(DateUtil.formatBetween(histTask.getDurationInMillis(), BetweenFormatter.Level.SECOND)); |
| | | flowTask.setProcDefId(histTask.getProcessDefinitionId()); |
| | | flowTask.setTaskDefKey(histTask.getTaskDefinitionKey()); |
| | | flowTask.setTaskName(histTask.getName()); |
| | | |
| | | // æµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionId(histTask.getProcessDefinitionId()) |
| | | .singleResult(); |
| | | flowTask.setDeployId(pd.getDeploymentId()); |
| | | flowTask.setProcDefName(pd.getName()); |
| | | flowTask.setProcDefVersion(pd.getVersion()); |
| | | flowTask.setProcInsId(histTask.getProcessInstanceId()); |
| | | flowTask.setHisProcInsId(histTask.getProcessInstanceId()); |
| | | flowTask.setCategory(pd.getCategory()); |
| | | // æµç¨åèµ·äººä¿¡æ¯ |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(histTask.getProcessInstanceId()) |
| | | .singleResult(); |
| | | Long userId = Long.parseLong(historicProcessInstance.getStartUserId()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | flowTask.setStartUserId(userId); |
| | | flowTask.setStartUserName(nickName); |
| | | |
| | | // æµç¨åé |
| | | flowTask.setProcVars(histTask.getProcessVariables()); |
| | | |
| | | hisTaskList.add(flowTask); |
| | | } |
| | | page.setTotal(taskInstanceQuery.count()); |
| | | page.setRecords(hisTaskList); |
| | | // Map<String, Object> result = new HashMap<>(); |
| | | // result.put("result",page); |
| | | // result.put("finished",true); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | @Override |
| | | public List<WfTaskVo> selectFinishedProcessList(ProcessQuery processQuery) { |
| | | HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() |
| | | .includeProcessVariables() |
| | | .finished() |
| | | .taskAssignee(TaskUtils.getUserId()) |
| | | .orderByHistoricTaskInstanceEndTime() |
| | | .desc(); |
| | | // æå»ºæç´¢æ¡ä»¶ |
| | | ProcessUtils.buildProcessSearch(taskInstanceQuery, processQuery); |
| | | List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.list(); |
| | | List<WfTaskVo> hisTaskList = new ArrayList<>(); |
| | | for (HistoricTaskInstance histTask : historicTaskInstanceList) { |
| | | WfTaskVo flowTask = new WfTaskVo(); |
| | | // å½åæµç¨ä¿¡æ¯ |
| | | flowTask.setTaskId(histTask.getId()); |
| | | // 审æ¹äººåä¿¡æ¯ |
| | | flowTask.setCreateTime(histTask.getCreateTime()); |
| | | flowTask.setFinishTime(histTask.getEndTime()); |
| | | flowTask.setDuration(DateUtil.formatBetween(histTask.getDurationInMillis(), BetweenFormatter.Level.SECOND)); |
| | | flowTask.setProcDefId(histTask.getProcessDefinitionId()); |
| | | flowTask.setTaskDefKey(histTask.getTaskDefinitionKey()); |
| | | flowTask.setTaskName(histTask.getName()); |
| | | |
| | | // æµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionId(histTask.getProcessDefinitionId()) |
| | | .singleResult(); |
| | | flowTask.setDeployId(pd.getDeploymentId()); |
| | | flowTask.setProcDefName(pd.getName()); |
| | | flowTask.setProcDefVersion(pd.getVersion()); |
| | | flowTask.setProcInsId(histTask.getProcessInstanceId()); |
| | | flowTask.setHisProcInsId(histTask.getProcessInstanceId()); |
| | | |
| | | // æµç¨åèµ·äººä¿¡æ¯ |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(histTask.getProcessInstanceId()) |
| | | .singleResult(); |
| | | Long userId = Long.parseLong(historicProcessInstance.getStartUserId()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | flowTask.setStartUserId(userId); |
| | | flowTask.setStartUserName(nickName); |
| | | |
| | | // æµç¨åé |
| | | flowTask.setProcVars(histTask.getProcessVariables()); |
| | | |
| | | hisTaskList.add(flowTask); |
| | | } |
| | | return hisTaskList; |
| | | } |
| | | |
| | | @Override |
| | | public FormConf selectFormContent(String definitionId, String deployId, String procInsId) { |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(definitionId); |
| | | if (ObjectUtil.isNull(bpmnModel)) { |
| | | throw new RuntimeException("è·åæµç¨è®¾è®¡å¤±è´¥ï¼"); |
| | | } |
| | | StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel); |
| | | WfDeployForm deployForm = deployFormMapper.selectOne(new LambdaQueryWrapper<WfDeployForm>() |
| | | .eq(WfDeployForm::getDeployId, deployId) |
| | | .eq(WfDeployForm::getFormKey, startEvent.getFormKey()) |
| | | .eq(WfDeployForm::getNodeKey, startEvent.getId())); |
| | | Map<String, Object> formModel = JsonUtils.parseObject(deployForm.getContent(), Map.class); |
| | | if (null == formModel || formModel.isEmpty()) { |
| | | throw new RuntimeException("è·åæµç¨è¡¨å失败ï¼"); |
| | | } |
| | | |
| | | |
| | | FormConf formConf = new FormConf(); |
| | | formConf.setFormBtns(false); |
| | | formConf.setFormModel(formModel); |
| | | if (ObjectUtil.isNotEmpty(procInsId)) { |
| | | // è·åæµç¨å®ä¾ |
| | | HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(procInsId) |
| | | .includeProcessVariables() |
| | | .singleResult(); |
| | | formConf.setFormData(historicProcIns.getProcessVariables()); |
| | | } |
| | | return formConf; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æµç¨å®ä¹IDå¯å¨æµç¨å®ä¾ |
| | | * |
| | | * @param procDefId æµç¨å®ä¹Id |
| | | * @param variables æµç¨åé |
| | | * @return |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void startProcessByDefId(String procDefId, Map<String, Object> variables) { |
| | | try { |
| | | ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionId(procDefId).singleResult(); |
| | | startProcess(processDefinition, variables); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | throw new ServiceException("æµç¨å¯å¨é误"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * éè¿DefinitionKeyå¯å¨æµç¨ |
| | | * @param procDefKey æµç¨å®ä¹Key |
| | | * @param variables æ©å±åæ° |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void startProcessByDefKey(String procDefKey, Map<String, Object> variables) { |
| | | try { |
| | | ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionKey(procDefKey).latestVersion().singleResult(); |
| | | startProcess(processDefinition, variables); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | throw new ServiceException("æµç¨å¯å¨é误"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteProcessByIds(String[] instanceIds) { |
| | | List<String> ids = Arrays.asList(instanceIds); |
| | | // æ ¡éªæµç¨æ¯å¦ç»æ |
| | | long activeInsCount = runtimeService.createProcessInstanceQuery() |
| | | .processInstanceIds(new HashSet<>(ids)).active().count(); |
| | | if (activeInsCount > 0) { |
| | | throw new ServiceException("ä¸å
许å é¤è¿è¡ä¸çæµç¨å®ä¾"); |
| | | } |
| | | // å é¤å岿µç¨å®ä¾ |
| | | historyService.bulkDeleteHistoricProcessInstances(ids); |
| | | } |
| | | |
| | | /** |
| | | * 读åxmlæä»¶ |
| | | * @param processDefId æµç¨å®ä¹ID |
| | | */ |
| | | @Override |
| | | public String queryBpmnXmlById(String processDefId) { |
| | | InputStream inputStream = repositoryService.getProcessModel(processDefId); |
| | | try { |
| | | return IoUtil.readUtf8(inputStream); |
| | | } catch (IORuntimeException exception) { |
| | | throw new RuntimeException("å è½½xmlæä»¶å¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æµç¨è¯¦æ
ä¿¡æ¯ |
| | | * |
| | | * @param procInsId æµç¨å®ä¾ID |
| | | * @param taskId ä»»å¡ID |
| | | * @return |
| | | */ |
| | | @Override |
| | | public WfDetailVo queryProcessDetail(String procInsId, String taskId) { |
| | | WfDetailVo detailVo = new WfDetailVo(); |
| | | // è·åæµç¨å®ä¾ |
| | | HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery() |
| | | .processInstanceId(procInsId) |
| | | .includeProcessVariables() |
| | | .singleResult(); |
| | | if (StringUtils.isNotBlank(taskId)) { |
| | | HistoricTaskInstance taskIns = historyService.createHistoricTaskInstanceQuery() |
| | | .taskId(taskId) |
| | | .includeIdentityLinks() |
| | | .includeProcessVariables() |
| | | .includeTaskLocalVariables() |
| | | .singleResult(); |
| | | if (taskIns == null) { |
| | | throw new ServiceException("没æå¯åççä»»å¡ï¼"); |
| | | } |
| | | detailVo.setTaskFormData(currTaskFormData(historicProcIns.getDeploymentId(), taskIns)); |
| | | } |
| | | // è·åBpmn模åä¿¡æ¯ |
| | | InputStream inputStream = repositoryService.getProcessModel(historicProcIns.getProcessDefinitionId()); |
| | | String bpmnXmlStr = StrUtil.utf8Str(IoUtil.readBytes(inputStream, false)); |
| | | BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnXmlStr); |
| | | detailVo.setBpmnXml(bpmnXmlStr); |
| | | detailVo.setHistoryProcNodeList(historyProcNodeList(historicProcIns)); |
| | | detailVo.setProcessFormList(processFormList(bpmnModel, historicProcIns)); |
| | | detailVo.setFlowViewer(getFlowViewer(bpmnModel, procInsId)); |
| | | return detailVo; |
| | | } |
| | | |
| | | /** |
| | | * å¯å¨æµç¨å®ä¾ |
| | | */ |
| | | private void startProcess(ProcessDefinition procDef, Map<String, Object> variables) { |
| | | if (ObjectUtil.isNotNull(procDef) && procDef.isSuspended()) { |
| | | throw new ServiceException("æµç¨å·²è¢«æèµ·ï¼è¯·å
æ¿æ´»æµç¨"); |
| | | } |
| | | // 设置æµç¨å起人Idå°æµç¨ä¸ |
| | | String userIdStr = TaskUtils.getUserId(); |
| | | identityService.setAuthenticatedUserId(userIdStr); |
| | | variables.put(BpmnXMLConstants.ATTRIBUTE_EVENT_START_INITIATOR, userIdStr); |
| | | // 设置æµç¨ç¶æä¸ºè¿è¡ä¸ |
| | | variables.put(ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.RUNNING.getStatus()); |
| | | // åèµ·æµç¨å®ä¾ |
| | | ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDef.getId(), variables); |
| | | // 第ä¸ä¸ªç¨æ·ä»»å¡ä¸ºå起人ï¼åèªå¨å®æä»»å¡ |
| | | wfTaskService.startFirstTask(processInstance, variables); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * è·åæµç¨åé |
| | | * |
| | | * @param taskId ä»»å¡ID |
| | | * @return æµç¨åé |
| | | */ |
| | | private Map<String, Object> getProcessVariables(String taskId) { |
| | | HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() |
| | | .includeProcessVariables() |
| | | .finished() |
| | | .taskId(taskId) |
| | | .singleResult(); |
| | | if (Objects.nonNull(historicTaskInstance)) { |
| | | return historicTaskInstance.getProcessVariables(); |
| | | } |
| | | return taskService.getVariables(taskId); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½å任塿µç¨è¡¨åä¿¡æ¯ |
| | | */ |
| | | private FormConf currTaskFormData(String deployId, HistoricTaskInstance taskIns) { |
| | | WfDeployFormVo deployFormVo = deployFormMapper.selectVoOne(new LambdaQueryWrapper<WfDeployForm>() |
| | | .eq(WfDeployForm::getDeployId, deployId) |
| | | .eq(WfDeployForm::getFormKey, taskIns.getFormKey()) |
| | | .eq(WfDeployForm::getNodeKey, taskIns.getTaskDefinitionKey())); |
| | | if (ObjectUtil.isNotEmpty(deployFormVo)) { |
| | | FormConf currTaskFormData = JsonUtils.parseObject(deployFormVo.getContent(), FormConf.class); |
| | | if (null != currTaskFormData) { |
| | | currTaskFormData.setFormBtns(false); |
| | | ProcessFormUtils.fillFormData(currTaskFormData, taskIns.getTaskLocalVariables()); |
| | | return currTaskFormData; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * è·åå岿µç¨è¡¨åä¿¡æ¯ |
| | | */ |
| | | private List<FormConf> processFormList(BpmnModel bpmnModel, HistoricProcessInstance historicProcIns) { |
| | | List<FormConf> procFormList = new ArrayList<>(); |
| | | |
| | | List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery() |
| | | .processInstanceId(historicProcIns.getId()).finished() |
| | | .activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_TASK_USER)) |
| | | .orderByHistoricActivityInstanceStartTime().asc() |
| | | .list(); |
| | | List<String> processFormKeys = new ArrayList<>(); |
| | | for (HistoricActivityInstance activityInstance : activityInstanceList) { |
| | | // è·åå½åèç¹æµç¨å
ç´ ä¿¡æ¯ |
| | | FlowElement flowElement = ModelUtils.getFlowElementById(bpmnModel, activityInstance.getActivityId()); |
| | | // è·åå½åèç¹è¡¨åKey |
| | | String formKey = ModelUtils.getFormKey(flowElement); |
| | | if (formKey == null) { |
| | | continue; |
| | | } |
| | | boolean localScope = Convert.toBool(ModelUtils.getElementAttributeValue(flowElement, ProcessConstants.PROCESS_FORM_LOCAL_SCOPE), false); |
| | | Map<String, Object> variables; |
| | | if (localScope) { |
| | | // æ¥è¯¢ä»»å¡èç¹åæ°ï¼å¹¶è½¬æ¢æMap |
| | | variables = historyService.createHistoricVariableInstanceQuery() |
| | | .processInstanceId(historicProcIns.getId()) |
| | | .taskId(activityInstance.getTaskId()) |
| | | .list() |
| | | .stream() |
| | | .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)); |
| | | } else { |
| | | if (processFormKeys.contains(formKey)) { |
| | | continue; |
| | | } |
| | | variables = historicProcIns.getProcessVariables(); |
| | | processFormKeys.add(formKey); |
| | | } |
| | | // éèç¹è¡¨åæ¤å¤æ¥è¯¢ç»æå¯è½æå¤æ¡ï¼åªè·åç¬¬ä¸æ¡ä¿¡æ¯ |
| | | List<WfDeployFormVo> formInfoList = deployFormMapper.selectVoList(new LambdaQueryWrapper<WfDeployForm>() |
| | | .eq(WfDeployForm::getDeployId, historicProcIns.getDeploymentId()) |
| | | .eq(WfDeployForm::getFormKey, formKey) |
| | | .eq(localScope, WfDeployForm::getNodeKey, flowElement.getId())); |
| | | |
| | | //@update by Brathï¼é¿å
空éå导è´çNULL空æé |
| | | WfDeployFormVo formInfo = formInfoList.stream().findFirst().orElse(null); |
| | | |
| | | if (ObjectUtil.isNotNull(formInfo)) { |
| | | // æ§æ°æ® formInfo.getFormName() 为 null |
| | | String formName = Optional.ofNullable(formInfo.getFormName()).orElse(StringUtils.EMPTY); |
| | | String title = localScope ? formName.concat("(" + flowElement.getName() + ")") : formName; |
| | | FormConf formConf = new FormConf(); |
| | | Map<String, Object> formModel = JsonUtils.parseObject(formInfo.getContent(), Map.class); |
| | | if (null != formModel && !formModel.isEmpty()) { |
| | | formConf.setTitle(title); |
| | | formConf.setDisabled(true); |
| | | formConf.setFormBtns(false); |
| | | formConf.setFormModel(formModel); |
| | | formConf.setFormData(variables); |
| | | procFormList.add(formConf); |
| | | } |
| | | } |
| | | } |
| | | return procFormList; |
| | | } |
| | | |
| | | @Deprecated |
| | | private void buildStartFormData(HistoricProcessInstance historicProcIns, Process process, String deployId, List<FormConf> procFormList) { |
| | | procFormList = procFormList == null ? new ArrayList<>() : procFormList; |
| | | HistoricActivityInstance startInstance = historyService.createHistoricActivityInstanceQuery() |
| | | .processInstanceId(historicProcIns.getId()) |
| | | .activityId(historicProcIns.getStartActivityId()) |
| | | .singleResult(); |
| | | StartEvent startEvent = (StartEvent) process.getFlowElement(startInstance.getActivityId()); |
| | | WfDeployFormVo startFormInfo = deployFormMapper.selectVoOne(new LambdaQueryWrapper<WfDeployForm>() |
| | | .eq(WfDeployForm::getDeployId, deployId) |
| | | .eq(WfDeployForm::getFormKey, startEvent.getFormKey()) |
| | | .eq(WfDeployForm::getNodeKey, startEvent.getId())); |
| | | if (ObjectUtil.isNotNull(startFormInfo)) { |
| | | FormConf formConf = JsonUtils.parseObject(startFormInfo.getContent(), FormConf.class); |
| | | if (null != formConf) { |
| | | formConf.setTitle(startEvent.getName()); |
| | | formConf.setDisabled(true); |
| | | formConf.setFormBtns(false); |
| | | ProcessFormUtils.fillFormData(formConf, historicProcIns.getProcessVariables()); |
| | | procFormList.add(formConf); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Deprecated |
| | | private void buildUserTaskFormData(String procInsId, String deployId, Process process, List<FormConf> procFormList) { |
| | | procFormList = procFormList == null ? new ArrayList<>() : procFormList; |
| | | List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery() |
| | | .processInstanceId(procInsId).finished() |
| | | .activityType(BpmnXMLConstants.ELEMENT_TASK_USER) |
| | | .orderByHistoricActivityInstanceStartTime().asc() |
| | | .list(); |
| | | for (HistoricActivityInstance instanceItem : activityInstanceList) { |
| | | UserTask userTask = (UserTask) process.getFlowElement(instanceItem.getActivityId(), true); |
| | | String formKey = userTask.getFormKey(); |
| | | if (formKey == null) { |
| | | continue; |
| | | } |
| | | // æ¥è¯¢ä»»å¡èç¹åæ°ï¼å¹¶è½¬æ¢æMap |
| | | Map<String, Object> variables = historyService.createHistoricVariableInstanceQuery() |
| | | .processInstanceId(procInsId) |
| | | .taskId(instanceItem.getTaskId()) |
| | | .list() |
| | | .stream() |
| | | .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)); |
| | | WfDeployFormVo deployFormVo = deployFormMapper.selectVoOne(new LambdaQueryWrapper<WfDeployForm>() |
| | | .eq(WfDeployForm::getDeployId, deployId) |
| | | .eq(WfDeployForm::getFormKey, formKey) |
| | | .eq(WfDeployForm::getNodeKey, userTask.getId())); |
| | | if (ObjectUtil.isNotNull(deployFormVo)) { |
| | | FormConf formConf = JsonUtils.parseObject(deployFormVo.getContent(), FormConf.class); |
| | | if (null != formConf) { |
| | | formConf.setTitle(userTask.getName()); |
| | | formConf.setDisabled(true); |
| | | formConf.setFormBtns(false); |
| | | ProcessFormUtils.fillFormData(formConf, variables); |
| | | procFormList.add(formConf); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·ååå²ä»»å¡ä¿¡æ¯å表 |
| | | */ |
| | | private List<WfProcNodeVo> historyProcNodeList(HistoricProcessInstance historicProcIns) { |
| | | String procInsId = historicProcIns.getId(); |
| | | List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery() |
| | | .processInstanceId(procInsId) |
| | | .activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_EVENT_END, BpmnXMLConstants.ELEMENT_TASK_USER)) |
| | | .orderByHistoricActivityInstanceStartTime().desc() |
| | | .orderByHistoricActivityInstanceEndTime().desc() |
| | | .list(); |
| | | |
| | | List<Comment> commentList = taskService.getProcessInstanceComments(procInsId); |
| | | |
| | | List<WfProcNodeVo> elementVoList = new ArrayList<>(); |
| | | for (HistoricActivityInstance activityInstance : historicActivityInstanceList) { |
| | | WfProcNodeVo elementVo = new WfProcNodeVo(); |
| | | elementVo.setProcDefId(activityInstance.getProcessDefinitionId()); |
| | | elementVo.setActivityId(activityInstance.getActivityId()); |
| | | elementVo.setActivityName(activityInstance.getActivityName()); |
| | | elementVo.setActivityType(activityInstance.getActivityType()); |
| | | elementVo.setCreateTime(activityInstance.getStartTime()); |
| | | elementVo.setEndTime(activityInstance.getEndTime()); |
| | | if (ObjectUtil.isNotNull(activityInstance.getDurationInMillis())) { |
| | | elementVo.setDuration(DateUtil.formatBetween(activityInstance.getDurationInMillis(), BetweenFormatter.Level.SECOND)); |
| | | } |
| | | |
| | | if (BpmnXMLConstants.ELEMENT_EVENT_START.equals(activityInstance.getActivityType())) { |
| | | if (ObjectUtil.isNotNull(historicProcIns)) { |
| | | Long userId = Long.parseLong(historicProcIns.getStartUserId()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | if (nickName != null) { |
| | | elementVo.setAssigneeId(userId); |
| | | elementVo.setAssigneeName(nickName); |
| | | } |
| | | } |
| | | } else if (BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType())) { |
| | | if (StringUtils.isNotBlank(activityInstance.getAssignee())) { |
| | | Long userId = Long.parseLong(activityInstance.getAssignee()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | elementVo.setAssigneeId(userId); |
| | | elementVo.setAssigneeName(nickName); |
| | | } |
| | | // å±ç¤ºå®¡æ¹äººå |
| | | List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(activityInstance.getTaskId()); |
| | | StringBuilder stringBuilder = new StringBuilder(); |
| | | for (HistoricIdentityLink identityLink : linksForTask) { |
| | | if ("candidate".equals(identityLink.getType())) { |
| | | if (StringUtils.isNotBlank(identityLink.getUserId())) { |
| | | Long userId = Long.parseLong(identityLink.getUserId()); |
| | | String nickName = null; |
| | | SysUserVo user = userService.selectUserById(userId); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | stringBuilder.append(nickName).append(","); |
| | | } |
| | | if (StringUtils.isNotBlank(identityLink.getGroupId())) { |
| | | if (identityLink.getGroupId().startsWith(TaskConstants.ROLE_GROUP_PREFIX)) { |
| | | Long roleId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.ROLE_GROUP_PREFIX)); |
| | | //finish do æ¥è¯¢è§è²åç§° |
| | | SysRoleVo role=roleService.selectRoleById(roleId); |
| | | if (!ObjectUtil.isNull(role)) { |
| | | stringBuilder.append(role.getRoleName()).append(","); |
| | | } |
| | | } else if (identityLink.getGroupId().startsWith(TaskConstants.DEPT_GROUP_PREFIX)) { |
| | | Long deptId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.DEPT_GROUP_PREFIX)); |
| | | //finish do æ¥è¯¢é¨é¨åç§° |
| | | SysDeptVo deptR=deptService.selectDeptById(deptId); |
| | | if (!ObjectUtil.isNull(deptR) ) { |
| | | stringBuilder.append(deptR.getDeptName()).append(","); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | if (StringUtils.isNotBlank(stringBuilder)) { |
| | | elementVo.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); |
| | | } |
| | | // è·åæè§è¯è®ºå
容 |
| | | if (CollUtil.isNotEmpty(commentList)) { |
| | | List<Comment> comments = new ArrayList<>(); |
| | | for (Comment comment : commentList) { |
| | | |
| | | if (comment.getTaskId().equals(activityInstance.getTaskId())) { |
| | | comments.add(comment); |
| | | } |
| | | } |
| | | elementVo.setCommentList(comments); |
| | | } |
| | | } |
| | | elementVoList.add(elementVo); |
| | | } |
| | | return elementVoList; |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨æ§è¡è¿ç¨ |
| | | * |
| | | * @param procInsId |
| | | * @return |
| | | */ |
| | | private WfViewerVo getFlowViewer(BpmnModel bpmnModel, String procInsId) { |
| | | // æå»ºæ¥è¯¢æ¡ä»¶ |
| | | HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery() |
| | | .processInstanceId(procInsId); |
| | | List<HistoricActivityInstance> allActivityInstanceList = query.list(); |
| | | if (CollUtil.isEmpty(allActivityInstanceList)) { |
| | | return new WfViewerVo(); |
| | | } |
| | | // æ¥è¯¢ææå·²å®æçå
ç´ |
| | | List<HistoricActivityInstance> finishedElementList = allActivityInstanceList.stream() |
| | | .filter(item -> ObjectUtil.isNotNull(item.getEndTime())).collect(Collectors.toList()); |
| | | // ææå·²å®æçè¿çº¿ |
| | | Set<String> finishedSequenceFlowSet = new HashSet<>(); |
| | | // ææå·²å®æçä»»å¡èç¹ |
| | | Set<String> finishedTaskSet = new HashSet<>(); |
| | | finishedElementList.forEach(item -> { |
| | | if (BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW.equals(item.getActivityType())) { |
| | | finishedSequenceFlowSet.add(item.getActivityId()); |
| | | } else { |
| | | finishedTaskSet.add(item.getActivityId()); |
| | | } |
| | | }); |
| | | // æ¥è¯¢æææªç»æçèç¹ |
| | | Set<String> unfinishedTaskSet = allActivityInstanceList.stream() |
| | | .filter(item -> ObjectUtil.isNull(item.getEndTime())) |
| | | .map(HistoricActivityInstance::getActivityId) |
| | | .collect(Collectors.toSet()); |
| | | // DFS æ¥è¯¢æªéè¿çå
ç´ éå |
| | | Set<String> rejectedSet = FlowableUtils.dfsFindRejects(bpmnModel, unfinishedTaskSet, finishedSequenceFlowSet, finishedTaskSet); |
| | | return new WfViewerVo(finishedTaskSet, finishedSequenceFlowSet, unfinishedTaskSet, rejectedSet); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.flowable.workflow.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.exception.ServiceException; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.common.satoken.utils.LoginHelper; |
| | | import org.ruoyi.flowable.common.constant.ProcessConstants; |
| | | import org.ruoyi.flowable.common.constant.TaskConstants; |
| | | import org.ruoyi.flowable.common.enums.FlowComment; |
| | | import org.ruoyi.flowable.common.enums.ProcessStatus; |
| | | import org.ruoyi.flowable.factory.FlowServiceFactory; |
| | | import org.ruoyi.flowable.flow.CustomProcessDiagramGenerator; |
| | | import org.ruoyi.flowable.flow.FlowableUtils; |
| | | import org.ruoyi.flowable.utils.ModelUtils; |
| | | import org.ruoyi.flowable.utils.TaskUtils; |
| | | import org.ruoyi.flowable.workflow.domain.bo.WfTaskBo; |
| | | import org.ruoyi.flowable.workflow.service.IWfCopyService; |
| | | import org.ruoyi.flowable.workflow.service.IWfTaskService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.flowable.bpmn.constants.BpmnXMLConstants; |
| | | import org.flowable.bpmn.model.Process; |
| | | import org.flowable.bpmn.model.*; |
| | | import org.flowable.common.engine.api.FlowableException; |
| | | import org.flowable.common.engine.api.FlowableObjectNotFoundException; |
| | | import org.flowable.common.engine.impl.identity.Authentication; |
| | | import org.flowable.engine.ProcessEngineConfiguration; |
| | | import org.flowable.engine.history.HistoricActivityInstance; |
| | | import org.flowable.engine.history.HistoricProcessInstance; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | import org.flowable.engine.runtime.Execution; |
| | | import org.flowable.engine.runtime.ProcessInstance; |
| | | import org.flowable.image.ProcessDiagramGenerator; |
| | | import org.flowable.task.api.DelegationState; |
| | | import org.flowable.task.api.Task; |
| | | import org.flowable.task.api.history.HistoricTaskInstance; |
| | | import org.ruoyi.system.domain.SysUser; |
| | | import org.ruoyi.system.domain.vo.SysUserVo; |
| | | import org.ruoyi.system.service.ISysUserService; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.io.InputStream; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @author KonBAI |
| | | * @createTime 2022/3/10 00:12 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | @Slf4j |
| | | public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskService { |
| | | |
| | | private final ISysUserService sysUserService; |
| | | |
| | | private final IWfCopyService copyService; |
| | | |
| | | /** |
| | | * å®æä»»å¡ |
| | | * |
| | | * @param taskBo 请æ±å®ä½åæ° |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void complete(WfTaskBo taskBo) { |
| | | Task task = taskService.createTaskQuery().taskId(taskBo.getTaskId()).singleResult(); |
| | | if (Objects.isNull(task)) { |
| | | throw new ServiceException("ä»»å¡ä¸åå¨"); |
| | | } |
| | | // è·å bpmn 模å |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId()); |
| | | identityService.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | if (DelegationState.PENDING.equals(task.getDelegationState())) { |
| | | taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.DELEGATE.getType(), taskBo.getComment()); |
| | | taskService.resolveTask(taskBo.getTaskId()); |
| | | } else { |
| | | taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.NORMAL.getType(), taskBo.getComment()); |
| | | taskService.setAssignee(taskBo.getTaskId(), TaskUtils.getUserId()); |
| | | if (ObjectUtil.isNotEmpty(taskBo.getVariables())) { |
| | | // è·å模åä¿¡æ¯ |
| | | String localScopeValue = ModelUtils.getUserTaskAttributeValue(bpmnModel, task.getTaskDefinitionKey(), ProcessConstants.PROCESS_FORM_LOCAL_SCOPE); |
| | | boolean localScope = Convert.toBool(localScopeValue, false); |
| | | taskService.complete(taskBo.getTaskId(), taskBo.getVariables(), localScope); |
| | | } else { |
| | | taskService.complete(taskBo.getTaskId()); |
| | | } |
| | | } |
| | | // 设置任å¡èç¹åç§° |
| | | taskBo.setTaskName(task.getName()); |
| | | // å¤çä¸ä¸çº§å®¡æ¹äºº |
| | | if (StringUtils.isNotBlank(taskBo.getNextUserIds())) { |
| | | this.assignNextUsers(bpmnModel, taskBo.getProcInsId(), taskBo.getNextUserIds()); |
| | | } |
| | | // å¤çæéç¨æ· |
| | | if (!copyService.makeCopy(taskBo)) { |
| | | throw new RuntimeException("æéä»»å¡å¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æç»ä»»å¡ |
| | | * |
| | | * @param taskBo |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void taskReject(WfTaskBo taskBo) { |
| | | // å½åä»»å¡ task |
| | | Task task = taskService.createTaskQuery().taskId(taskBo.getTaskId()).singleResult(); |
| | | if (ObjectUtil.isNull(task)) { |
| | | throw new RuntimeException("è·åä»»å¡ä¿¡æ¯å¼å¸¸ï¼"); |
| | | } |
| | | if (task.isSuspended()) { |
| | | throw new RuntimeException("ä»»å¡å¤äºæèµ·ç¶æ"); |
| | | } |
| | | // è·åæµç¨å®ä¾ |
| | | ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() |
| | | .processInstanceId(taskBo.getProcInsId()) |
| | | .singleResult(); |
| | | if (processInstance == null) { |
| | | throw new RuntimeException("æµç¨å®ä¾ä¸åå¨ï¼è¯·ç¡®è®¤ï¼"); |
| | | } |
| | | // è·åæµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() |
| | | .processDefinitionId(task.getProcessDefinitionId()) |
| | | .singleResult(); |
| | | |
| | | identityService.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | // æ·»å å®¡æ¹æè§ |
| | | taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.REJECT.getType(), taskBo.getComment()); |
| | | // 设置æµç¨ç¶æä¸ºå·²ç»ç» |
| | | runtimeService.setVariable(processInstance.getId(), ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.TERMINATED.getStatus()); |
| | | // è·åææèç¹ä¿¡æ¯ |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); |
| | | EndEvent endEvent = ModelUtils.getEndEvent(bpmnModel); |
| | | // ç»æ¢æµç¨ |
| | | List<Execution> executions = runtimeService.createExecutionQuery().parentId(task.getProcessInstanceId()).list(); |
| | | List<String> executionIds = executions.stream().map(Execution::getId).collect(Collectors.toList()); |
| | | runtimeService.createChangeActivityStateBuilder() |
| | | .processInstanceId(task.getProcessInstanceId()) |
| | | .moveExecutionsToSingleActivityId(executionIds, endEvent.getId()) |
| | | .changeState(); |
| | | // å¤çæéç¨æ· |
| | | if (!copyService.makeCopy(taskBo)) { |
| | | throw new RuntimeException("æéä»»å¡å¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * éåä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void taskReturn(WfTaskBo bo) { |
| | | // å½åä»»å¡ task |
| | | Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult(); |
| | | if (ObjectUtil.isNull(task)) { |
| | | throw new RuntimeException("è·åä»»å¡ä¿¡æ¯å¼å¸¸ï¼"); |
| | | } |
| | | if (task.isSuspended()) { |
| | | throw new RuntimeException("ä»»å¡å¤äºæèµ·ç¶æ"); |
| | | } |
| | | // è·åæµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); |
| | | // è·åæµç¨æ¨¡åä¿¡æ¯ |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); |
| | | // è·åå½åä»»å¡èç¹å
ç´ |
| | | FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); |
| | | // è·å跳转çèç¹å
ç´ |
| | | FlowElement target = ModelUtils.getFlowElementById(bpmnModel, bo.getTargetKey()); |
| | | // ä»å½åèç¹ååæ«æï¼å¤æå½åèç¹ä¸ç®æ èç¹æ¯å¦å±äºä¸²è¡ï¼è¥ç®æ èç¹æ¯å¨å¹¶è¡ç½å
³ä¸æéåä¸è·¯çº¿ä¸ï¼ä¸å¯è·³è½¬ |
| | | boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>()); |
| | | if (!isSequential) { |
| | | throw new RuntimeException("å½åèç¹ç¸å¯¹äºç®æ èç¹ï¼ä¸å±äºä¸²è¡å
³ç³»ï¼æ æ³åé"); |
| | | } |
| | | |
| | | // è·åæææ£å¸¸è¿è¡çä»»å¡èç¹ Keyï¼è¿äºä»»å¡ä¸è½ç´æ¥ä½¿ç¨ï¼éè¦æ¾åºå
¶ä¸éè¦æ¤åçä»»å¡ |
| | | List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); |
| | | List<String> runTaskKeyList = new ArrayList<>(); |
| | | runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); |
| | | // ééåä»»å¡å表 |
| | | List<String> currentIds = new ArrayList<>(); |
| | | // éè¿ç¶çº§ç½å
³çåºå£è¿çº¿ï¼ç»å runTaskList æ¯å¯¹ï¼è·åéè¦æ¤åçä»»å¡ |
| | | List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null); |
| | | currentUserTaskList.forEach(item -> currentIds.add(item.getId())); |
| | | |
| | | // 循ç¯è·åé£äºéè¦è¢«æ¤åçèç¹çIDï¼ç¨æ¥è®¾ç½®é©³ååå |
| | | List<String> currentTaskIds = new ArrayList<>(); |
| | | currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { |
| | | if (currentId.equals(runTask.getTaskDefinitionKey())) { |
| | | currentTaskIds.add(runTask.getId()); |
| | | } |
| | | })); |
| | | identityService.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | // 设置åéæè§ |
| | | for (String currentTaskId : currentTaskIds) { |
| | | taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), bo.getComment()); |
| | | } |
| | | |
| | | try { |
| | | // 1 对 1 æ å¤ å¯¹ 1 æ
åµï¼currentIds å½åè¦è·³è½¬çèç¹å表(1æå¤)ï¼targetKey 跳转å°çèç¹(1) |
| | | runtimeService.createChangeActivityStateBuilder() |
| | | .processInstanceId(task.getProcessInstanceId()) |
| | | .moveActivityIdsToSingleActivityId(currentIds, bo.getTargetKey()).changeState(); |
| | | } catch (FlowableObjectNotFoundException e) { |
| | | throw new RuntimeException("æªæ¾å°æµç¨å®ä¾ï¼æµç¨å¯è½å·²åçåå"); |
| | | } catch (FlowableException e) { |
| | | throw new RuntimeException("æ æ³åæ¶æå¼å§æ´»å¨"); |
| | | } |
| | | // 设置任å¡èç¹åç§° |
| | | bo.setTaskName(task.getName()); |
| | | // å¤çæéç¨æ· |
| | | if (!copyService.makeCopy(bo)) { |
| | | throw new RuntimeException("æéä»»å¡å¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * è·åææå¯åéçèç¹ |
| | | * |
| | | * @param bo |
| | | * @return |
| | | */ |
| | | @Override |
| | | public List<FlowElement> findReturnTaskList(WfTaskBo bo) { |
| | | // å½åä»»å¡ task |
| | | Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult(); |
| | | // è·åæµç¨å®ä¹ä¿¡æ¯ |
| | | ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); |
| | | // è·åæµç¨æ¨¡åä¿¡æ¯ |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); |
| | | // æ¥è¯¢åå²èç¹å®ä¾ |
| | | List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery() |
| | | .processInstanceId(task.getProcessInstanceId()) |
| | | .activityType(BpmnXMLConstants.ELEMENT_TASK_USER) |
| | | .finished() |
| | | .orderByHistoricActivityInstanceEndTime().asc() |
| | | .list(); |
| | | List<String> activityIdList = activityInstanceList.stream() |
| | | .map(HistoricActivityInstance::getActivityId) |
| | | .filter(activityId -> !StringUtils.equals(activityId, task.getTaskDefinitionKey())) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | // è·åå½åä»»å¡èç¹å
ç´ |
| | | FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); |
| | | List<FlowElement> elementList = new ArrayList<>(); |
| | | for (String activityId : activityIdList) { |
| | | FlowElement target = ModelUtils.getFlowElementById(bpmnModel, activityId); |
| | | boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>()); |
| | | if (isSequential) { |
| | | elementList.add(target); |
| | | } |
| | | } |
| | | return elementList; |
| | | } |
| | | |
| | | /** |
| | | * å é¤ä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | @Override |
| | | public void deleteTask(WfTaskBo bo) { |
| | | // todo å¾
确认å é¤ä»»å¡æ¯ç©çå é¤ä»»å¡ è¿æ¯é»è¾å é¤ï¼è®©è¿ä¸ªä»»å¡ç´æ¥éè¿ï¼ |
| | | identityService.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | taskService.deleteTask(bo.getTaskId(), bo.getComment()); |
| | | } |
| | | |
| | | /** |
| | | * 认é¢/ç¾æ¶ä»»å¡ |
| | | * |
| | | * @param taskBo 请æ±å®ä½åæ° |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void claim(WfTaskBo taskBo) { |
| | | Task task = taskService.createTaskQuery().taskId(taskBo.getTaskId()).singleResult(); |
| | | if (Objects.isNull(task)) { |
| | | throw new ServiceException("ä»»å¡ä¸åå¨"); |
| | | } |
| | | taskService.claim(taskBo.getTaskId(), TaskUtils.getUserId()); |
| | | } |
| | | |
| | | /** |
| | | * åæ¶è®¤é¢/ç¾æ¶ä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void unClaim(WfTaskBo bo) { |
| | | taskService.unclaim(bo.getTaskId()); |
| | | } |
| | | |
| | | /** |
| | | * å§æ´¾ä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void delegateTask(WfTaskBo bo) { |
| | | // å½åä»»å¡ task |
| | | Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult(); |
| | | if (ObjectUtil.isEmpty(task)) { |
| | | throw new ServiceException("è·åä»»å¡å¤±è´¥ï¼"); |
| | | } |
| | | // è·åå½åçç¨æ· |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | String currentNickname = null; |
| | | if (ObjectUtil.isNotNull(loginUser)){ |
| | | currentNickname=loginUser.getNickName(); |
| | | } |
| | | StringBuilder commentBuilder = new StringBuilder(currentNickname) |
| | | .append("->"); |
| | | |
| | | String nickName = null; |
| | | SysUserVo user = sysUserService.selectUserById(Long.parseLong(bo.getUserId())); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | if (StringUtils.isNotBlank(nickName)) { |
| | | commentBuilder.append(nickName); |
| | | } else { |
| | | commentBuilder.append(bo.getUserId()); |
| | | } |
| | | if (StringUtils.isNotBlank(bo.getComment())) { |
| | | commentBuilder.append(": ").append(bo.getComment()); |
| | | } |
| | | identityService.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | // æ·»å å®¡æ¹æè§ |
| | | taskService.addComment(bo.getTaskId(), task.getProcessInstanceId(), FlowComment.DELEGATE.getType(), commentBuilder.toString()); |
| | | // 设置åç人为å½åç»å½äºº |
| | | taskService.setOwner(bo.getTaskId(), TaskUtils.getUserId()); |
| | | // æ§è¡å§æ´¾ |
| | | taskService.delegateTask(bo.getTaskId(), bo.getUserId()); |
| | | // 设置任å¡èç¹åç§° |
| | | bo.setTaskName(task.getName()); |
| | | // å¤çæéç¨æ· |
| | | if (!copyService.makeCopy(bo)) { |
| | | throw new RuntimeException("æéä»»å¡å¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 转åä»»å¡ |
| | | * |
| | | * @param bo 请æ±å®ä½åæ° |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void transferTask(WfTaskBo bo) { |
| | | // å½åä»»å¡ task |
| | | Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult(); |
| | | if (ObjectUtil.isEmpty(task)) { |
| | | throw new ServiceException("è·åä»»å¡å¤±è´¥ï¼"); |
| | | } |
| | | // è·åå½åçç¨æ· |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | String currentNickname = null; |
| | | if (ObjectUtil.isNotNull(loginUser)){ |
| | | currentNickname=loginUser.getNickName(); |
| | | } |
| | | StringBuilder commentBuilder = new StringBuilder(currentNickname) |
| | | .append("->"); |
| | | |
| | | String nickName = null; |
| | | SysUserVo user = sysUserService.selectUserById(Long.parseLong(bo.getUserId())); |
| | | if(!ObjectUtil.isNull(user)) { |
| | | nickName=user.getNickName(); |
| | | } |
| | | if (StringUtils.isNotBlank(nickName)) { |
| | | commentBuilder.append(nickName); |
| | | } else { |
| | | commentBuilder.append(bo.getUserId()); |
| | | } |
| | | if (StringUtils.isNotBlank(bo.getComment())) { |
| | | commentBuilder.append(": ").append(bo.getComment()); |
| | | } |
| | | identityService.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | // æ·»å å®¡æ¹æè§ |
| | | taskService.addComment(bo.getTaskId(), task.getProcessInstanceId(), FlowComment.TRANSFER.getType(), commentBuilder.toString()); |
| | | // è®¾ç½®æ¥æè
为å½åç»å½äºº |
| | | taskService.setOwner(bo.getTaskId(), TaskUtils.getUserId()); |
| | | // 转åä»»å¡ |
| | | taskService.setAssignee(bo.getTaskId(), bo.getUserId()); |
| | | // 设置任å¡èç¹åç§° |
| | | bo.setTaskName(task.getName()); |
| | | // å¤çæéç¨æ· |
| | | if (!copyService.makeCopy(bo)) { |
| | | throw new RuntimeException("æéä»»å¡å¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åæ¶ç³è¯· |
| | | * |
| | | * @param bo |
| | | * @return |
| | | */ |
| | | @Override |
| | | public void stopProcess(WfTaskBo bo) { |
| | | List<Task> taskList = taskService.createTaskQuery().processInstanceId(bo.getProcInsId()).list(); |
| | | if (CollectionUtils.isEmpty(taskList)) { |
| | | throw new RuntimeException("æµç¨æªå¯å¨æå·²æ§è¡å®æï¼åæ¶ç³è¯·å¤±è´¥"); |
| | | } |
| | | |
| | | ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() |
| | | .processInstanceId(bo.getProcInsId()).singleResult(); |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); |
| | | if (Objects.nonNull(bpmnModel)) { |
| | | Process process = bpmnModel.getMainProcess(); |
| | | List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false); |
| | | if (CollectionUtils.isNotEmpty(endNodes)) { |
| | | Authentication.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | runtimeService.setVariable(processInstance.getId(), ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.CANCELED.getStatus()); |
| | | for (Task task : taskList) { |
| | | taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.STOP.getType(), "åæ¶æµç¨"); |
| | | } |
| | | // è·åå½åæµç¨æåä¸ä¸ªèç¹ |
| | | String endId = endNodes.get(0).getId(); |
| | | List<Execution> executions = runtimeService.createExecutionQuery() |
| | | .parentId(processInstance.getProcessInstanceId()).list(); |
| | | List<String> executionIds = new ArrayList<>(); |
| | | executions.forEach(execution -> executionIds.add(execution.getId())); |
| | | // åæ´æµç¨ä¸ºå·²ç»æç¶æ |
| | | runtimeService.createChangeActivityStateBuilder() |
| | | .moveExecutionsToSingleActivityId(executionIds, endId).changeState(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¤åæµç¨ |
| | | * |
| | | * @param taskBo 请æ±å®ä½åæ° |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void revokeProcess(WfTaskBo taskBo) { |
| | | String procInsId = taskBo.getProcInsId(); |
| | | String taskId = taskBo.getTaskId(); |
| | | // æ ¡éªæµç¨æ¯å¦ç»æ |
| | | ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() |
| | | .processInstanceId(procInsId) |
| | | .active() |
| | | .singleResult(); |
| | | if(ObjectUtil.isNull(processInstance)) { |
| | | throw new RuntimeException("æµç¨å·²ç»ææå·²æèµ·ï¼æ æ³æ§è¡æ¤åæä½"); |
| | | } |
| | | // è·åå¾
æ¤åä»»å¡å®ä¾ |
| | | HistoricTaskInstance currTaskIns = historyService.createHistoricTaskInstanceQuery() |
| | | .taskId(taskId) |
| | | .taskAssignee(TaskUtils.getUserId()) |
| | | .singleResult(); |
| | | if (ObjectUtil.isNull(currTaskIns)) { |
| | | throw new RuntimeException("å½åä»»å¡ä¸åå¨ï¼æ æ³æ§è¡æ¤åæä½"); |
| | | } |
| | | // è·å bpmn 模å |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(currTaskIns.getProcessDefinitionId()); |
| | | UserTask currUserTask = ModelUtils.getUserTaskByKey(bpmnModel, currTaskIns.getTaskDefinitionKey()); |
| | | // æ¥æ¾ä¸ä¸çº§ç¨æ·ä»»å¡å表 |
| | | List<UserTask> nextUserTaskList = ModelUtils.findNextUserTasks(currUserTask); |
| | | List<String> nextUserTaskKeys = nextUserTaskList.stream().map(UserTask::getId).collect(Collectors.toList()); |
| | | |
| | | // è·åå½åèç¹ä¹åå·²å®æçæµç¨åå²èç¹ |
| | | List<HistoricTaskInstance> finishedTaskInsList = historyService.createHistoricTaskInstanceQuery() |
| | | .processInstanceId(procInsId) |
| | | .taskCreatedAfter(currTaskIns.getEndTime()) |
| | | .finished() |
| | | .list(); |
| | | for (HistoricTaskInstance finishedTaskInstance : finishedTaskInsList) { |
| | | // æ£æ¥å·²å®ææµç¨åå²èç¹æ¯å¦åå¨ä¸ä¸çº§ä¸ |
| | | if (CollUtil.contains(nextUserTaskKeys, finishedTaskInstance.getTaskDefinitionKey())) { |
| | | throw new RuntimeException("ä¸ä¸æµç¨å·²å¤çï¼æ æ³æ§è¡æ¤åæä½"); |
| | | } |
| | | } |
| | | // è·åæææ¿æ´»çä»»å¡èç¹ï¼æ¾å°éè¦æ¤åçä»»å¡ |
| | | List<Task> activateTaskList = taskService.createTaskQuery().processInstanceId(procInsId).list(); |
| | | List<String> revokeExecutionIds = new ArrayList<>(); |
| | | identityService.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | for (Task task : activateTaskList) { |
| | | // æ£æ¥æ¿æ´»çä»»å¡èç¹æ¯å¦åå¨ä¸ä¸çº§ä¸ï¼å¦æåå¨ï¼åå å
¥å°éè¦æ¤åçèç¹ |
| | | if (CollUtil.contains(nextUserTaskKeys, task.getTaskDefinitionKey())) { |
| | | // æ·»å æ¤å审æ¹ä¿¡æ¯ |
| | | taskService.setAssignee(task.getId(), TaskUtils.getUserId()); |
| | | |
| | | // è·åå½åçç¨æ· |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | String currentNickname = null; |
| | | if (ObjectUtil.isNotNull(loginUser)){ |
| | | currentNickname=loginUser.getNickName(); |
| | | } |
| | | taskService.addComment(task.getId(), task.getProcessInstanceId(), FlowComment.REVOKE.getType(), currentNickname + "æ¤åæµç¨å®¡æ¹"); |
| | | revokeExecutionIds.add(task.getExecutionId()); |
| | | } |
| | | } |
| | | try { |
| | | runtimeService.createChangeActivityStateBuilder() |
| | | .processInstanceId(procInsId) |
| | | .moveExecutionsToSingleActivityId(revokeExecutionIds, currTaskIns.getTaskDefinitionKey()).changeState(); |
| | | } catch (FlowableObjectNotFoundException e) { |
| | | throw new RuntimeException("æªæ¾å°æµç¨å®ä¾ï¼æµç¨å¯è½å·²åçåå"); |
| | | } catch (FlowableException e) { |
| | | throw new RuntimeException("æ§è¡æ¤åæä½å¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨è¿ç¨å¾ |
| | | * |
| | | * @param processId |
| | | * @return |
| | | */ |
| | | @Override |
| | | public InputStream diagram(String processId) { |
| | | String processDefinitionId; |
| | | // è·åå½åçæµç¨å®ä¾ |
| | | ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult(); |
| | | // 妿æµç¨å·²ç»ç»æï¼åå¾å°ç»æèç¹ |
| | | if (Objects.isNull(processInstance)) { |
| | | HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult(); |
| | | |
| | | processDefinitionId = pi.getProcessDefinitionId(); |
| | | } else {// 妿æµç¨æ²¡æç»æï¼ååå½åæ´»å¨èç¹ |
| | | // æ ¹æ®æµç¨å®ä¾IDè·å¾å½åå¤äºæ´»å¨ç¶æçActivityIdåé |
| | | ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult(); |
| | | processDefinitionId = pi.getProcessDefinitionId(); |
| | | } |
| | | |
| | | // è·å¾æ´»å¨çèç¹ |
| | | List<HistoricActivityInstance> highLightedFlowList = historyService.createHistoricActivityInstanceQuery() |
| | | .processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list(); |
| | | |
| | | List<String> highLightedFlows = new ArrayList<>(); |
| | | List<String> highLightedNodes = new ArrayList<>(); |
| | | //é«äº®çº¿ |
| | | for (HistoricActivityInstance tempActivity : highLightedFlowList) { |
| | | if ("sequenceFlow".equals(tempActivity.getActivityType())) { |
| | | //é«äº®çº¿ |
| | | highLightedFlows.add(tempActivity.getActivityId()); |
| | | } else { |
| | | //é«äº®èç¹ |
| | | highLightedNodes.add(tempActivity.getActivityId()); |
| | | } |
| | | } |
| | | |
| | | //è·åæµç¨å¾ |
| | | BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); |
| | | ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration(); |
| | | //è·åèªå®ä¹å¾ççæå¨ |
| | | ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator(); |
| | | return diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(), |
| | | configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨åé |
| | | * |
| | | * @param taskId ä»»å¡ID |
| | | * @return æµç¨åé |
| | | */ |
| | | @Override |
| | | public Map<String, Object> getProcessVariables(String taskId) { |
| | | HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() |
| | | .includeProcessVariables() |
| | | .finished() |
| | | .taskId(taskId) |
| | | .singleResult(); |
| | | if (Objects.nonNull(historicTaskInstance)) { |
| | | return historicTaskInstance.getProcessVariables(); |
| | | } |
| | | return taskService.getVariables(taskId); |
| | | } |
| | | |
| | | /** |
| | | * å¯å¨ç¬¬ä¸ä¸ªä»»å¡ |
| | | * @param processInstance æµç¨å®ä¾ |
| | | * @param variables æµç¨åæ° |
| | | */ |
| | | @Override |
| | | public void startFirstTask(ProcessInstance processInstance, Map<String, Object> variables) { |
| | | // è¥ç¬¬ä¸ä¸ªç¨æ·ä»»å¡ä¸ºå起人ï¼åèªå¨å®æä»»å¡ |
| | | List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).list(); |
| | | if (CollUtil.isNotEmpty(tasks)) { |
| | | String userIdStr = (String) variables.get(TaskConstants.PROCESS_INITIATOR); |
| | | identityService.setAuthenticatedUserId(TaskUtils.getUserId()); |
| | | // è·åå½åçç¨æ· |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | String currentNickname = null; |
| | | if (ObjectUtil.isNotNull(loginUser)){ |
| | | currentNickname=loginUser.getNickName(); |
| | | } |
| | | for (Task task : tasks) { |
| | | if (StrUtil.equals(task.getAssignee(), userIdStr)) { |
| | | taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), currentNickname+ "åèµ·æµç¨ç³è¯·"); |
| | | taskService.complete(task.getId(), variables); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * ææ´¾ä¸ä¸ä»»å¡å®¡æ¹äºº |
| | | * @param bpmnModel bpmn模å |
| | | * @param processInsId æµç¨å®ä¾id |
| | | * @param userIds ç¨æ·ids |
| | | */ |
| | | private void assignNextUsers(BpmnModel bpmnModel, String processInsId, String userIds) { |
| | | // è·åææèç¹ä¿¡æ¯ |
| | | List<Task> list = taskService.createTaskQuery() |
| | | .processInstanceId(processInsId) |
| | | .list(); |
| | | if (list.size() == 0) { |
| | | return; |
| | | } |
| | | Queue<String> assignIds = CollUtil.newLinkedList(userIds.split(",")); |
| | | if (list.size() == assignIds.size()) { |
| | | for (Task task : list) { |
| | | taskService.setAssignee(task.getId(), assignIds.poll()); |
| | | } |
| | | return; |
| | | } |
| | | // ä¼å
å¤çéå¤å®ä¾ä»»å¡ |
| | | Iterator<Task> iterator = list.iterator(); |
| | | while (iterator.hasNext()) { |
| | | Task task = iterator.next(); |
| | | if (!ModelUtils.isMultiInstance(bpmnModel, task.getTaskDefinitionKey())) { |
| | | if (!assignIds.isEmpty()) { |
| | | taskService.setAssignee(task.getId(), assignIds.poll()); |
| | | } |
| | | iterator.remove(); |
| | | } |
| | | } |
| | | // è¥åå¨å¤å®ä¾ä»»å¡ï¼åè¿è¡å¨æå åç¾ |
| | | if (CollUtil.isNotEmpty(list)) { |
| | | if (assignIds.isEmpty()) { |
| | | // 卿åç¾ |
| | | for (Task task : list) { |
| | | runtimeService.deleteMultiInstanceExecution(task.getExecutionId(), true); |
| | | } |
| | | } else { |
| | | // 卿å ç¾ |
| | | for (String assignId : assignIds) { |
| | | Map<String, Object> assignVariables = Collections.singletonMap(BpmnXMLConstants.ATTRIBUTE_TASK_USER_ASSIGNEE, assignId); |
| | | runtimeService.addMultiInstanceExecution(list.get(0).getTaskDefinitionKey(), list.get(0).getProcessInstanceId(), assignVariables); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | Spring Boot Version: ${spring-boot.version} |
| | | Spring Application Name: ${spring.application.name} |
| | | ââ ââââ ââ ââ ââ |
| | | ââ ââââ ââââ âââ âââ âââ |
| | | ââââââ ââ ââ ââââââ ââââ ââ ââ ââââââ âââ ââââââ âââ ââ ââââââ âââ âââ âââââ |
| | | ââââââââââ âââ ââââââââ âââââ âââ âââââââââââ âââ ââââââââââââ â âââ ââââââââ âââââââ âââ âââââââ |
| | | âââ â âââ ââââââ âââ âââ ââââââââ âââ ââââââ âââ âââ ââââââ âââââââ ââââââââ âââââââââââ |
| | | âââ âââ ââââââ âââ ââ âââ âââ ââââââ âââ ââââââââââ ââââââââ âââ âââ ââââââââââ |
| | | ââââ ââââââââââââââââ ââ âââ âââ âââââââââââ ââââ ââââââââââââââââââââââ âââââââââââ |
| | | âââ ââââââ ââââââ ââ ââ ââ âââ ââââââ âââ âââ ââââââââ âââââ âââ ââââââ |
| | | |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | # Tomcat |
| | | server: |
| | | port: 9308 |
| | | |
| | | # Spring |
| | | spring: |
| | | main: |
| | | lazy-initialization: true #é»è®¤false å
³é |
| | | application: |
| | | # åºç¨åç§° |
| | | name: ruoyi-flowable |
| | | profiles: |
| | | # ç¯å¢é
ç½® |
| | | active: dev |
| | | cloud: |
| | | nacos: |
| | | discovery: |
| | | # æå¡æ³¨åå°å |
| | | server-addr: 127.0.0.1:8848 |
| | | config: |
| | | # é
ç½®ä¸å¿å°å |
| | | server-addr: 127.0.0.1:8848 |
| | | # é
ç½®æä»¶æ ¼å¼ |
| | | file-extension: yml |
| | | # å
±äº«é
ç½® |
| | | shared-configs: |
| | | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <configuration scan="true" scanPeriod="60 seconds" debug="false"> |
| | | <!-- æ¥å¿åæ¾è·¯å¾ --> |
| | | <property name="log.path" value="logs/ruoyi-flowable" /> |
| | | <!-- æ¥å¿è¾åºæ ¼å¼ --> |
| | | <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> |
| | | |
| | | <!-- æ§å¶å°è¾åº --> |
| | | <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> |
| | | <encoder> |
| | | <pattern>${log.pattern}</pattern> |
| | | </encoder> |
| | | </appender> |
| | | |
| | | <!-- ç³»ç»æ¥å¿è¾åº --> |
| | | <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
| | | <file>${log.path}/info.log</file> |
| | | <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ --> |
| | | <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
| | | <!-- æ¥å¿æä»¶åæ ¼å¼ --> |
| | | <fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern> |
| | | <!-- æ¥å¿æå¤§çåå² 60天 --> |
| | | <maxHistory>60</maxHistory> |
| | | </rollingPolicy> |
| | | <encoder> |
| | | <pattern>${log.pattern}</pattern> |
| | | </encoder> |
| | | <filter class="ch.qos.logback.classic.filter.LevelFilter"> |
| | | <!-- è¿æ»¤ççº§å« --> |
| | | <level>INFO</level> |
| | | <!-- å¹é
æ¶çæä½ï¼æ¥æ¶ï¼è®°å½ï¼ --> |
| | | <onMatch>ACCEPT</onMatch> |
| | | <!-- ä¸å¹é
æ¶çæä½ï¼æç»ï¼ä¸è®°å½ï¼ --> |
| | | <onMismatch>DENY</onMismatch> |
| | | </filter> |
| | | </appender> |
| | | |
| | | <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
| | | <file>${log.path}/error.log</file> |
| | | <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ --> |
| | | <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
| | | <!-- æ¥å¿æä»¶åæ ¼å¼ --> |
| | | <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern> |
| | | <!-- æ¥å¿æå¤§çåå² 60天 --> |
| | | <maxHistory>60</maxHistory> |
| | | </rollingPolicy> |
| | | <encoder> |
| | | <pattern>${log.pattern}</pattern> |
| | | </encoder> |
| | | <filter class="ch.qos.logback.classic.filter.LevelFilter"> |
| | | <!-- è¿æ»¤ççº§å« --> |
| | | <level>ERROR</level> |
| | | <!-- å¹é
æ¶çæä½ï¼æ¥æ¶ï¼è®°å½ï¼ --> |
| | | <onMatch>ACCEPT</onMatch> |
| | | <!-- ä¸å¹é
æ¶çæä½ï¼æç»ï¼ä¸è®°å½ï¼ --> |
| | | <onMismatch>DENY</onMismatch> |
| | | </filter> |
| | | </appender> |
| | | |
| | | <!-- Console Appender --> |
| | | <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> |
| | | <encoder> |
| | | <pattern>%d{yyyy-MM-dd HH:mm:ss} - %msg%n</pattern> |
| | | </encoder> |
| | | </appender> |
| | | |
| | | <!-- MyBatis-Plus Logger Configuration --> |
| | | <logger name="com.baomidou.mybatisplus" level="DEBUG"/> |
| | | |
| | | <!-- ç³»ç»æ¨¡åæ¥å¿çº§å«æ§å¶ --> |
| | | <logger name="com.ruoyi" level="info" /> |
| | | <!-- Springæ¥å¿çº§å«æ§å¶ --> |
| | | <logger name="org.springframework" level="warn" /> |
| | | |
| | | <root level="info"> |
| | | <appender-ref ref="console" /> |
| | | </root> |
| | | |
| | | <!--ç³»ç»æä½æ¥å¿--> |
| | | <root level="info"> |
| | | <appender-ref ref="file_info" /> |
| | | <appender-ref ref="file_error" /> |
| | | </root> |
| | | </configuration> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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.ruoyi.flowable.workflow.mapper.WfCategoryMapper"> |
| | | |
| | | <resultMap type="org.ruoyi.flowable.workflow.domain.WfCategory" id="FlowCategoryResult"> |
| | | <result property="categoryId" column="category_id"/> |
| | | <result property="categoryName" column="category_name"/> |
| | | <result property="code" column="code"/> |
| | | <result property="createBy" column="create_by"/> |
| | | <result property="createTime" column="create_time"/> |
| | | <result property="updateBy" column="update_by"/> |
| | | <result property="updateTime" column="update_time"/> |
| | | <result property="remark" column="remark"/> |
| | | <result property="delFlag" column="del_flag"/> |
| | | </resultMap> |
| | | |
| | | </mapper> |
| | |
| | | return R.ok(trees); |
| | | } |
| | | |
| | | /** |
| | | * è·åé¨é¨ä¸çææç¨æ·ä¿¡æ¯ |
| | | */ |
| | | @SaCheckPermission("system:user:list") |
| | | @GetMapping("/list/dept/{deptId}") |
| | | public R<List<SysUserVo>> listByDeptId(@PathVariable Long deptId) { |
| | | List<SysUserVo> sysUserVos = userService.selectUserList(new SysUserBo()); |
| | | return R.ok(sysUserVos.stream() |
| | | .filter(user -> deptId.equals(user.getDeptId())) |
| | | .collect(Collectors.toList())); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-modules</artifactId> |
| | | <version>${revision}</version> |
| | | <relativePath>../pom.xml</relativePath> |
| | | </parent> |
| | | <artifactId>sc-page-designer</artifactId> |
| | | <description> |
| | | school-ai页é¢è®¾è®¡å¨æ¨¡å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <!-- éç¨å·¥å
·--> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-system-api</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.controller; |
| | | |
| | | import jakarta.validation.Valid; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.web.core.BaseController; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.pageDesigner.domain.PageDesigner; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerDTO; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerVo; |
| | | import org.ruoyi.pageDesigner.service.PageDesignerService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 14:41:24 |
| | | */ |
| | | @Validated |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/page-designer") |
| | | public class PageDesignerController extends BaseController { |
| | | |
| | | private final PageDesignerService pageDesignerService; |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡å表 |
| | | */ |
| | | @GetMapping("/list") |
| | | public TableDataInfo<PageDesignerVo> list(PageDesignerDTO pageDesignerDTO, PageQuery pageQuery) { |
| | | return pageDesignerService.selectPagelistAll(pageDesignerDTO, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡è¯¦æ
|
| | | */ |
| | | @GetMapping("/{id}") |
| | | public R<PageDesigner> getInfo(@PathVariable Long id) { |
| | | return R.ok(pageDesignerService.getDetail(id)); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢é¡µé¢è®¾è®¡ |
| | | */ |
| | | @PostMapping |
| | | public R<Void> add(@Valid @RequestBody PageDesignerDTO dto) { |
| | | pageDesignerService.add(dto); |
| | | return R.ok("æ°å¢æå"); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹é¡µé¢è®¾è®¡ |
| | | */ |
| | | @PutMapping |
| | | public R<Void> update(@Valid @RequestBody PageDesignerDTO dto) { |
| | | pageDesignerService.updatePage(dto); |
| | | return R.ok("ä¿®æ¹æå"); |
| | | } |
| | | |
| | | /** |
| | | * å é¤é¡µé¢è®¾è®¡ |
| | | */ |
| | | @DeleteMapping |
| | | public R<Void> remove(@RequestBody List<Long> ids) { |
| | | pageDesignerService.deleteByIds(ids); |
| | | return R.ok("å 餿å"); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.controller; |
| | | |
| | | import jakarta.validation.Valid; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.domain.R; |
| | | import org.ruoyi.common.web.core.BaseController; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.pageDesigner.domain.*; |
| | | import org.ruoyi.pageDesigner.service.PageDesignerTemplateService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 14:41:24 |
| | | */ |
| | | @Validated |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/page-designer-template") |
| | | public class PageDesignerTemplateController extends BaseController { |
| | | |
| | | private final PageDesignerTemplateService service; |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡å表 |
| | | */ |
| | | @GetMapping("/list") |
| | | public TableDataInfo<PageDesignerTemplateVo> list(PageDesignerTemplateDTO dto, PageQuery pageQuery) { |
| | | return service.selectPagelistAll(dto, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡è¯¦æ
|
| | | */ |
| | | @GetMapping("/{id}") |
| | | public R<PageDesignerTemplate> getInfo(@PathVariable Long id) { |
| | | return R.ok(service.getDetail(id)); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢é¡µé¢è®¾è®¡ |
| | | */ |
| | | @PostMapping |
| | | public R<Void> add(@Valid @RequestBody PageDesignerTemplateDTO dto) { |
| | | service.add(dto); |
| | | return R.ok("æ°å¢æå"); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹é¡µé¢è®¾è®¡ |
| | | */ |
| | | @PutMapping |
| | | public R<Void> update(@Valid @RequestBody PageDesignerTemplateDTO dto) { |
| | | service.updatePage(dto); |
| | | return R.ok("ä¿®æ¹æå"); |
| | | } |
| | | |
| | | /** |
| | | * å é¤é¡µé¢è®¾è®¡ |
| | | */ |
| | | @DeleteMapping |
| | | public R<Void> remove(@RequestBody List<Long> ids) { |
| | | service.deleteByIds(ids); |
| | | return R.ok("å 餿å"); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:24:05 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("PAGE_DESIGNER") |
| | | public class PageDesigner extends BaseEntity { |
| | | @TableId(value = "ID") |
| | | private Long id; |
| | | @TableField("NAME") |
| | | private String name; |
| | | @TableField("MENU_ID") |
| | | private String menuId; // å
³èçèåID |
| | | @TableField("MENU_PARENT_ID") |
| | | private String menuParentId; // å
³èçèåç¶ID |
| | | @TableField("STATUS") |
| | | private String status; |
| | | @TableField(value = "DEL_FLAG") |
| | | @TableLogic |
| | | private String delFlag; |
| | | @TableField("REMARK") |
| | | private String remark; |
| | | @TableField("FORM_JSON") |
| | | private String formJson; |
| | | @TableField("SHOW_COLUMN") |
| | | private String showColumn; // å¯ä»¥å° selectedFields åå¨ä¸º JSON å符串 |
| | | @TableField("ACTIONS_FUNC") |
| | | private String actionsFunc; // å¯ä»¥å° enableActions åå¨ä¸º JSON å符串 |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.domain; |
| | | |
| | | import io.github.linpeilie.annotations.AutoMapper; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.NoArgsConstructor; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:23:35 |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @AutoMapper(target = PageDesigner.class, reverseConvertGenerate = false) |
| | | public class PageDesignerDTO extends BaseEntity { |
| | | private Long id; // ä¿®æ¹æ¶ä¼ å
¥ |
| | | private String name; // 页é¢åç§° |
| | | private String menuId; // å
³èèå ID |
| | | private String status; // å¯ç¨ç¶æ |
| | | private String remark; // 夿³¨ |
| | | private String formJson; // 表å设计 JSON å符串 |
| | | private String showColumn; // åæ®µæ¾ç¤ºé
ç½® |
| | | private String actionsFunc; // å¯ç¨çæä½é¡¹ï¼å¢å æ¹æ¥ï¼ |
| | | private String menuParentId; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:24:05 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("PAGE_DESIGNER_TEMPLATE") |
| | | public class PageDesignerTemplate extends BaseEntity { |
| | | @TableId(value = "ID") |
| | | private Long id; |
| | | @TableField(value = "PAGE_ID") |
| | | private Long pageId; |
| | | @TableField("FORM_DATA") |
| | | private String formData; |
| | | @TableField(value = "DEL_FLAG") |
| | | @TableLogic |
| | | private String delFlag; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.domain; |
| | | |
| | | import io.github.linpeilie.annotations.AutoMapper; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.NoArgsConstructor; |
| | | import org.ruoyi.core.domain.BaseEntity; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:23:35 |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @AutoMapper(target = PageDesignerTemplate.class, reverseConvertGenerate = false) |
| | | public class PageDesignerTemplateDTO extends BaseEntity { |
| | | private Long id; |
| | | private Long pageId; |
| | | private String formData; |
| | | private String delFlag; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.domain; |
| | | |
| | | import io.github.linpeilie.annotations.AutoMapper; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:23:35 |
| | | */ |
| | | @Data |
| | | @AutoMapper(target = PageDesignerTemplate.class) |
| | | public class PageDesignerTemplateVo implements Serializable { |
| | | private Long id; |
| | | private Long pageId; |
| | | private String formData; |
| | | private String delFlag; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.domain; |
| | | |
| | | import io.github.linpeilie.annotations.AutoMapper; |
| | | import lombok.Data; |
| | | import org.ruoyi.system.domain.vo.SysMenuVo; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:23:35 |
| | | */ |
| | | @Data |
| | | @AutoMapper(target = PageDesigner.class) |
| | | public class PageDesignerVo implements Serializable { |
| | | private Long id; // ä¿®æ¹æ¶ä¼ å
¥ |
| | | private String name; // 页é¢åç§° |
| | | private String status; // å¯ç¨ç¶æ |
| | | private String remark; // 夿³¨ |
| | | private String menuParentId; // èåç¶ID |
| | | private Date createTime; // å建æ¶é´ |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Constants; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.ruoyi.pageDesigner.domain.PageDesigner; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerVo; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:34:48 |
| | | */ |
| | | @Mapper |
| | | public interface PageDesignerMapper extends BaseMapper<PageDesigner> { |
| | | Page<PageDesignerVo> selectPagelistAll(@Param("page") Page<PageDesigner> page, @Param(Constants.WRAPPER) Wrapper<PageDesigner> queryWrapper); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Constants; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerTemplate; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerTemplateVo; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:34:48 |
| | | */ |
| | | @Mapper |
| | | public interface PageDesignerTemplateMapper extends BaseMapper<PageDesignerTemplate> { |
| | | Page<PageDesignerTemplateVo> selectPagelistAll(@Param("page") Page<PageDesignerTemplate> page, @Param(Constants.WRAPPER) Wrapper<PageDesignerTemplate> queryWrapper); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.pageDesigner.domain.PageDesigner; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerDTO; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerVo; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:35:56 |
| | | */ |
| | | public interface PageDesignerService extends IService<PageDesigner> { |
| | | |
| | | void add(PageDesignerDTO dto); |
| | | |
| | | void updatePage(PageDesignerDTO dto); |
| | | |
| | | List<PageDesigner> listAll(String keyword); |
| | | |
| | | PageDesigner getDetail(Long id); |
| | | |
| | | void deleteByIds(List<Long> ids); |
| | | |
| | | TableDataInfo<PageDesignerVo> selectPagelistAll(PageDesignerDTO pageDesignerDTO, PageQuery pageQuery); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.pageDesigner.domain.*; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:35:56 |
| | | */ |
| | | public interface PageDesignerTemplateService extends IService<PageDesignerTemplate> { |
| | | |
| | | void add(PageDesignerTemplateDTO dto); |
| | | |
| | | void updatePage(PageDesignerTemplateDTO dto); |
| | | |
| | | List<PageDesignerTemplate> listAll(String keyword); |
| | | |
| | | PageDesignerTemplate getDetail(Long id); |
| | | |
| | | void deleteByIds(List<Long> ids); |
| | | |
| | | TableDataInfo<PageDesignerTemplateVo> selectPagelistAll(PageDesignerTemplateDTO dto, PageQuery pageQuery); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.service.impl; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.amazonaws.util.json.Jackson; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.constant.UserConstants; |
| | | import org.ruoyi.common.core.utils.StreamUtils; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.helper.DataBaseHelper; |
| | | import org.ruoyi.pageDesigner.domain.PageDesigner; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerDTO; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerVo; |
| | | import org.ruoyi.pageDesigner.mapper.PageDesignerMapper; |
| | | import org.ruoyi.pageDesigner.service.PageDesignerService; |
| | | import org.ruoyi.system.domain.SysMenu; |
| | | import org.ruoyi.system.mapper.SysMenuMapper; |
| | | import org.ruoyi.system.mapper.SysUserMapper; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:36:29 |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class PageDesignerServiceImpl extends ServiceImpl<PageDesignerMapper, PageDesigner> |
| | | implements PageDesignerService { |
| | | |
| | | private final SysMenuMapper menuMapper; |
| | | |
| | | @Override |
| | | public void add(PageDesignerDTO dto) { |
| | | SysMenu menu = new SysMenu(); |
| | | menu.setMenuName(dto.getName()); |
| | | menu.setParentId(Long.valueOf(dto.getMenuParentId())); |
| | | menu.setOrderNum(999); |
| | | menu.setComponent("tool/template/index"); |
| | | menu.setIsFrame("1"); |
| | | menu.setIsCache("0"); |
| | | menu.setMenuType("C"); // C:ç®å½, M:èå, F:æé® |
| | | menu.setVisible("0"); |
| | | menu.setStatus(dto.getStatus()); |
| | | menuMapper.insert(menu); |
| | | PageDesigner entity = convertToEntity(dto); |
| | | entity.setMenuId(menu.getMenuId().toString()); |
| | | this.save(entity); |
| | | menu.setPath(String.valueOf(entity.getId())); |
| | | menuMapper.updateById(menu); |
| | | } |
| | | |
| | | @Override |
| | | public void updatePage(PageDesignerDTO dto) { |
| | | PageDesigner entity = convertToEntity(dto); |
| | | this.updateById(entity); |
| | | PageDesigner byId = this.getById(entity.getId()); |
| | | SysMenu menu = new SysMenu(); |
| | | menu.setMenuId(Long.valueOf(byId.getMenuId())); |
| | | menu.setStatus(entity.getStatus()); |
| | | menu.setParentId(Long.valueOf(entity.getMenuParentId())); |
| | | menuMapper.updateById(menu); |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<PageDesignerVo> selectPagelistAll(PageDesignerDTO pageDesignerDTO, PageQuery pageQuery) { |
| | | Page<PageDesignerVo> page = baseMapper.selectPagelistAll(pageQuery.build(), this.buildQueryWrapper(pageDesignerDTO)); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | private Wrapper<PageDesigner> buildQueryWrapper(PageDesignerDTO pageDesignerDTO) { |
| | | Map<String, Object> params = pageDesignerDTO.getParams(); |
| | | QueryWrapper<PageDesigner> wrapper = Wrappers.query(); |
| | | wrapper.eq("del_flag", UserConstants.USER_NORMAL) |
| | | .eq(ObjectUtil.isNotNull(pageDesignerDTO.getId()), "id", pageDesignerDTO.getId()) |
| | | .like(StringUtils.isNotBlank(pageDesignerDTO.getName()), "name", pageDesignerDTO.getName()) |
| | | .eq(StringUtils.isNotBlank(pageDesignerDTO.getStatus()), "status", pageDesignerDTO.getStatus()) |
| | | .between(params.get("beginTime") != null && params.get("endTime") != null, |
| | | "create_time", params.get("beginTime"), params.get("endTime")) |
| | | ; |
| | | return wrapper; |
| | | } |
| | | @Override |
| | | public List<PageDesigner> listAll(String keyword) { |
| | | LambdaQueryWrapper<PageDesigner> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.like(keyword != null, PageDesigner::getName, keyword); |
| | | return this.list(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public PageDesigner getDetail(Long id) { |
| | | return this.getById(id); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteByIds(List<Long> ids) { |
| | | List<PageDesigner> designers = this.listByIds(ids); |
| | | for (PageDesigner designer : designers) { |
| | | Long id = designer.getId(); |
| | | this.removeById(id); |
| | | |
| | | Long menuId = Long.valueOf(designer.getMenuId()); |
| | | if (menuId != null) { |
| | | menuMapper.deleteById(menuId); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | private PageDesigner convertToEntity(PageDesignerDTO dto) { |
| | | PageDesigner entity = new PageDesigner(); |
| | | entity.setId(dto.getId()); |
| | | entity.setName(dto.getName()); |
| | | entity.setMenuId(dto.getMenuId()); |
| | | entity.setStatus(dto.getStatus()); |
| | | entity.setRemark(dto.getRemark()); |
| | | entity.setFormJson(dto.getFormJson()); |
| | | entity.setShowColumn(dto.getShowColumn()); |
| | | entity.setActionsFunc(dto.getActionsFunc()); |
| | | entity.setMenuParentId(dto.getMenuParentId()); |
| | | return entity; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.service.impl; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.constant.UserConstants; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.pageDesigner.domain.*; |
| | | import org.ruoyi.pageDesigner.mapper.PageDesignerMapper; |
| | | import org.ruoyi.pageDesigner.mapper.PageDesignerTemplateMapper; |
| | | import org.ruoyi.pageDesigner.service.PageDesignerService; |
| | | import org.ruoyi.pageDesigner.service.PageDesignerTemplateService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:36:29 |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class PageDesignerTemplateServiceImpl extends ServiceImpl<PageDesignerTemplateMapper, PageDesignerTemplate> |
| | | implements PageDesignerTemplateService { |
| | | |
| | | private final ObjectMapper objectMapper; |
| | | |
| | | @Override |
| | | public void add(PageDesignerTemplateDTO dto) { |
| | | PageDesignerTemplate entity = convertToEntity(dto); |
| | | this.save(entity); |
| | | } |
| | | |
| | | @Override |
| | | public void updatePage(PageDesignerTemplateDTO dto) { |
| | | PageDesignerTemplate entity = convertToEntity(dto); |
| | | this.updateById(entity); |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<PageDesignerTemplateVo> selectPagelistAll(PageDesignerTemplateDTO dto, PageQuery pageQuery) { |
| | | Page<PageDesignerTemplateVo> page = baseMapper.selectPagelistAll(pageQuery.build(), this.buildQueryWrapper(dto)); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | private Wrapper<PageDesignerTemplate> buildQueryWrapper(PageDesignerTemplateDTO dto) { |
| | | //Map<String, Object> params = pageDesignerDTO.getParams(); |
| | | QueryWrapper<PageDesignerTemplate> wrapper = Wrappers.query(); |
| | | wrapper.eq("del_flag", UserConstants.USER_NORMAL) |
| | | .eq(ObjectUtil.isNotNull(dto.getPageId()), "page_id", dto.getPageId()) |
| | | // .like(StringUtils.isNotBlank(pageDesignerDTO.getName()), "name", pageDesignerDTO.getName()) |
| | | // .eq(StringUtils.isNotBlank(pageDesignerDTO.getStatus()), "status", pageDesignerDTO.getStatus()) |
| | | // .between(params.get("beginTime") != null && params.get("endTime") != null, |
| | | // "create_time", params.get("beginTime"), params.get("endTime")) |
| | | ; |
| | | return wrapper; |
| | | } |
| | | @Override |
| | | public List<PageDesignerTemplate> listAll(String keyword) { |
| | | LambdaQueryWrapper<PageDesignerTemplate> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.like(keyword != null, PageDesignerTemplate::getPageId, keyword); |
| | | return this.list(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public PageDesignerTemplate getDetail(Long id) { |
| | | return this.getById(id); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteByIds(List<Long> ids) { |
| | | this.removeByIds(ids); |
| | | } |
| | | |
| | | private PageDesignerTemplate convertToEntity(PageDesignerTemplateDTO dto) { |
| | | PageDesignerTemplate entity = new PageDesignerTemplate(); |
| | | entity.setId(dto.getId()); |
| | | entity.setFormData(dto.getFormData()); |
| | | entity.setDelFlag(dto.getDelFlag()); |
| | | entity.setPageId(dto.getPageId()); |
| | | return entity; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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.ruoyi.pageDesigner.mapper.PageDesignerMapper"> |
| | | |
| | | <!-- å¤ç»æåµå¥èªå¨æ å°é另䏿¯ä¸ªå®ä½ç主é®id å¦åæ å°ä¼å¤±è´¥ --> |
| | | <resultMap type="org.ruoyi.pageDesigner.domain.PageDesignerVo" id="PageDesignerResult"> |
| | | <id property="id" column="id"/> |
| | | <result property="name" column="name"/> |
| | | <result property="status" column="status"/> |
| | | <result property="createTime" column="create_time"/> |
| | | <result property="menuParentId" column="menu_parent_id"/> |
| | | <result property="remark" column="remark"/> |
| | | </resultMap> |
| | | |
| | | |
| | | <select id="selectPagelistAll" resultMap="PageDesignerResult"> |
| | | select |
| | | id, |
| | | name, |
| | | status, |
| | | create_time, |
| | | menu_parent_id, |
| | | remark |
| | | from page_designer |
| | | ${ew.getCustomSqlSegment} |
| | | </select> |
| | | |
| | | |
| | | |
| | | |
| | | </mapper> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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.ruoyi.pageDesigner.mapper.PageDesignerTemplateMapper"> |
| | | |
| | | <!-- ç»ææ å° --> |
| | | <resultMap type="org.ruoyi.pageDesigner.domain.PageDesignerTemplateVo" id="PageDesignerTemplateResult"> |
| | | <id property="id" column="id"/> |
| | | <result property="pageId" column="page_id"/> |
| | | <result property="formData" column="form_data"/> |
| | | <result property="delFlag" column="del_flag"/> |
| | | </resultMap> |
| | | |
| | | <select id="selectPagelistAll" resultMap="PageDesignerTemplateResult"> |
| | | SELECT |
| | | id, |
| | | page_id, |
| | | form_data, |
| | | del_flag |
| | | FROM page_designer_template |
| | | <where> |
| | | ${ew.sqlSegment} |
| | | </where> |
| | | </select> |
| | | |
| | | </mapper> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-modules</artifactId> |
| | | <version>${revision}</version> |
| | | <relativePath>../pom.xml</relativePath> |
| | | </parent> |
| | | <artifactId>sc-services</artifactId> |
| | | <description> |
| | | school-aiä¸å¡æ¨¡å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <!-- éç¨å·¥å
·--> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| | |
| | | "@vben/utils": "workspace:*", |
| | | "@vueuse/core": "catalog:", |
| | | "ant-design-vue": "catalog:", |
| | | "axios": "^1.10.0", |
| | | "bpmn-js": "^18.6.2", |
| | | "cropperjs": "^1.6.2", |
| | | "crypto-js": "^4.2.0", |
| | | "dayjs": "catalog:", |
| | | "diagram-js": "^15.3.0", |
| | | "echarts": "^5.5.1", |
| | | "element-plus": "^2.10.2", |
| | | "jsencrypt": "^3.3.2", |
| | | "lodash-es": "^4.17.21", |
| | | "pinia": "catalog:", |
| | | "qs": "^6.13.1", |
| | | "tinymce": "^7.3.0", |
| | | "unplugin-vue-components": "^0.27.3", |
| | | "vue": "catalog:", |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { |
| | | PageDesigner |
| | | } from './model'; |
| | | |
| | | enum Api { |
| | | pageAdd = '/page-designer', |
| | | pageUpdate = '/page-designer', |
| | | pageList = '/page-designer/list', |
| | | pageInfo = '/page-designer', |
| | | pageRemove = '/page-designer', |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function pageAdd(data: any) { |
| | | return requestClient.post(Api.pageAdd, data); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function pageUpdate(data: any) { |
| | | return requestClient.put(Api.pageUpdate, data); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡å表 |
| | | */ |
| | | export function pageList(params?: any) { |
| | | return requestClient.get<{ |
| | | total: number; |
| | | rows: PageDesigner[]; |
| | | code: number; |
| | | msg: string; |
| | | }>(Api.pageList, { params }); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡è¯¦æ
|
| | | */ |
| | | export function pageInfo(id: string | number) { |
| | | return requestClient.get<PageDesigner>(`${Api.pageInfo}/${id}`); |
| | | } |
| | | |
| | | /** |
| | | * å é¤é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function pageRemove(ids: string[] | number[]) { |
| | | return requestClient.delete(Api.pageRemove, { data: ids }); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | export interface PageDesigner { |
| | | id?: string | number; // 主é®ï¼ç¼è¾æ¶ç¨ |
| | | name: string; // 页é¢åç§° |
| | | menuId: string | number | null; // ä¸çº§ç®å½ï¼èåIDï¼ |
| | | parentId: string | number | null; // ç¶çº§ID |
| | | status: string; // ç¶æ |
| | | remark?: string | null; // 夿³¨ |
| | | formJson?: string | null; // 表å设计JSON |
| | | showColumn?: string | null; // æ¾ç¤ºå段(JSONå符串) |
| | | actionsFunc?: string | null; // å¯ç¨åè½(JSONå符串) |
| | | createTime?: string; // å建æ¶é´ |
| | | updateTime?: string; // æ´æ°æ¶é´ |
| | | menu?: { // å
³èçèåä¿¡æ¯ |
| | | menuId: number; |
| | | menuName: string; |
| | | } | null; |
| | | parent?: { // å
³èçç¶çº§ä¿¡æ¯ |
| | | id: string | number; |
| | | name: string; |
| | | } | null; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { Template } from './model'; |
| | | |
| | | enum Api { |
| | | templateAdd = '/page-designer-template', |
| | | templateUpdate = '/page-designer-template', |
| | | templateList = '/page-designer-template/list', |
| | | templateInfo = '/page-designer-template', |
| | | templateRemove = '/page-designer-template', |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function templateAdd(data: any) { |
| | | return requestClient.post(Api.templateAdd, data); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function templateUpdate(data: any) { |
| | | return requestClient.put(Api.templateUpdate, data); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡å表 |
| | | */ |
| | | export function templateList(params?: any) { |
| | | return requestClient.get(Api.templateList, { params }); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡è¯¦æ
|
| | | */ |
| | | export function templateInfo(id: string | number) { |
| | | return requestClient.get(`${Api.templateInfo}/${id}`); |
| | | } |
| | | |
| | | /** |
| | | * å é¤é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function templateRemove(ids: string[] | number[]) { |
| | | return requestClient.delete(Api.templateRemove, { data: ids }); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | export interface Template { |
| | | id?: string | number; // ä¸»é® |
| | | formData: string; // 模çåç§° |
| | | pageDesignId: string | number; // å
³èç页é¢è®¾è®¡ID |
| | | createTime?: string; // å建æ¶é´ |
| | | updateTime?: string; // æ´æ°æ¶é´ |
| | | pageDesign?: { // å
³èç页é¢è®¾è®¡ä¿¡æ¯ |
| | | id: string | number; |
| | | name: string; |
| | | formJson?: string; |
| | | showColumn?: string; |
| | | actionsFunc?: string; |
| | | } | null; |
| | | } |
| | |
| | | import { router } from './router'; |
| | | import formCreate from '@form-create/element-ui'; |
| | | import FcDesigner from '@form-create/designer'; |
| | | import Antd from 'ant-design-vue'; |
| | | import 'ant-design-vue/dist/reset.css'; |
| | | async function bootstrap(namespace: string) { |
| | | |
| | | // åå§åç»ä»¶éé
å¨ |
| | | await initComponentAdapter(); |
| | | |
| | |
| | | app.use(ElementPlus); |
| | | app.use(formCreate); |
| | | app.use(FcDesigner); |
| | | app.use(Antd); |
| | | // å¨ææ´æ°æ é¢ |
| | | watchEffect(() => { |
| | | if (preferences.app.dynamicTitle) { |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { VxeGridProps } from 'src/adapter/vxe-table'; |
| | | import type { FormSchemaGetter } from "src/adapter/form"; |
| | | |
| | | |
| | | export const querySchema: FormSchemaGetter = () => [ |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'roleName', |
| | | label: 'åç§°', |
| | | }, |
| | | |
| | | { |
| | | component: 'Select', |
| | | fieldName: 'roleSort', |
| | | label: 'å建人', |
| | | }, |
| | | { |
| | | component: 'RangePicker', |
| | | fieldName: 'createTime', |
| | | label: 'å建æ¶é´', |
| | | }, |
| | | ]; |
| | | export const columns: VxeGridProps['columns'] = [ |
| | | { type: 'checkbox', width: 60 }, |
| | | { |
| | | title: 'åç§°', |
| | | field: 'roleName', |
| | | }, |
| | | { |
| | | title: 'å建人', |
| | | field: 'roleSort', |
| | | }, |
| | | { |
| | | title: 'å建æ¶é´', |
| | | field: 'createTime', |
| | | }, |
| | | { |
| | | field: 'action', |
| | | fixed: 'right', |
| | | slots: { default: 'action' }, |
| | | title: 'æä½', |
| | | width: 180, |
| | | }, |
| | | ]; |
| | |
| | | <template> |
| | | <div>å·¥ä½èæ ¸ææ </div> |
| | | <Page :auto-content-height="true"> |
| | | <BasicTable table-title="å·¥ä½èæ ¸ææ å表"> |
| | | <template #toolbar-tools> |
| | | <Space> |
| | | <a-button |
| | | v-access:code="['system:role:export']" |
| | | @click="handleDownloadExcel" |
| | | style="margin-right: 10px" |
| | | > |
| | | {{ $t('pages.common.export') }} |
| | | </a-button> |
| | | <a-button |
| | | type="primary" |
| | | v-access:code="['system:role:add']" |
| | | @click="handleAdd" |
| | | > |
| | | {{ $t('pages.common.add') }} |
| | | </a-button> |
| | | </Space> |
| | | </template> |
| | | </BasicTable> |
| | | </Page> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "index" |
| | | <script setup lang="ts"> |
| | | import type { VxeGridProps } from "#/adapter/vxe-table"; |
| | | import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table'; |
| | | import type { VbenFormProps } from '@vben/common-ui'; |
| | | import type { roleList} from "#/api/system/role"; |
| | | import { columns, querySchema } from './data'; |
| | | import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui'; |
| | | const formOptions: VbenFormProps = { |
| | | commonConfig: { |
| | | labelWidth: 80, |
| | | componentProps: { |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | schema: querySchema(), |
| | | wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', |
| | | // æ¥æéæ©æ ¼å¼å |
| | | fieldMappingTime: [ |
| | | [ |
| | | 'createTime', |
| | | ['params[beginTime]', 'params[endTime]'], |
| | | ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'], |
| | | ], |
| | | ], |
| | | }; |
| | | const gridOptions: VxeGridProps = { |
| | | checkboxConfig: { |
| | | // é«äº® |
| | | highlight: true, |
| | | // 翻页æ¶ä¿çéä¸ç¶æ |
| | | reserve: true, |
| | | // ç¹å»è¡éä¸ |
| | | // trigger: 'row', |
| | | checkMethod: ({ row }) => row.roleId !== 1, |
| | | }, |
| | | columns, |
| | | height: 'auto', |
| | | keepSource: true, |
| | | pagerConfig: {}, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues = {}) => { |
| | | return await roleList({ |
| | | pageNum: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'roleId', |
| | | }, |
| | | id: 'system-role-index', |
| | | }; |
| | | const [BasicTable,tableApi] = useVbenVxeGrid({ |
| | | formOptions, |
| | | gridOptions, |
| | | }); |
| | | const handleAdd = () => { |
| | | console.log('æ°å¢') |
| | | } |
| | | const handleDownloadExcel = () => { |
| | | console.log('导åº') |
| | | } |
| | | </script> |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | |
| | | <script> |
| | | import {modelInfo} from "#/api/system/model/index.js"; |
| | | import {pick} from "lodash-es"; |
| | | import {useVbenModal} from "@vben/common-ui"; |
| | | import {ref, computed} from "vue"; |
| | | import { $t } from '@vben/locales'; |
| | | const defaultValues = { |
| | | id: undefined, |
| | | name: undefined, |
| | | } |
| | | |
| | | const isUpdate = ref(false); |
| | | const title = computed(() => { |
| | | return isUpdate.value ? $t('ç¼è¾') : $t('æ°å¢'); |
| | | }); |
| | | const { validate, validateInfos, resetFields } = Form.useForm( |
| | | formData, |
| | | formRules, |
| | | ); |
| | | const [BasicModal, modalApi] = useVbenModal({ |
| | | class: 'w-[550px]', |
| | | fullscreenButton: false, |
| | | closeOnClickModal: false, |
| | | onClosed: handleCancel, |
| | | onConfirm: handleConfirm, |
| | | onOpenChange: async (isOpen) => { |
| | | if (!isOpen) { |
| | | return null; |
| | | } |
| | | modalApi.modalLoading(true); |
| | | |
| | | const { id } = modalApi.getData() as { id?: number | string }; |
| | | isUpdate.value = !!id; |
| | | |
| | | if (isUpdate.value && id) { |
| | | const record = await modelInfo(id); |
| | | // åªèµå¼åå¨çåæ®µ |
| | | const filterRecord = pick(record, Object.keys(defaultValues)); |
| | | formData.value = filterRecord; |
| | | } |
| | | |
| | | modalApi.modalLoading(false); |
| | | }, |
| | | }); |
| | | |
| | | |
| | | </script> |
| | | <template> |
| | | <BasicModal :title="title"> |
| | | <Form :label-col="{ span: 4 }"> |
| | | <FormItem label="åç§°" v-bind="validateInfos.name"> |
| | | <Input |
| | | v-model:value="formData.name" |
| | | :placeholder="$t('ui.formRules.required')" |
| | | /> |
| | | </FormItem> |
| | | </Form> |
| | | </BasicModal> |
| | | </template> |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="process-definition-container"> |
| | | <a-card title="æµç¨å®ä¹å表" :bordered="false"> |
| | | <div class="table-actions"> |
| | | <a-button type="primary" @click="showCreateModal">æ°å¢æµç¨å¾</a-button> |
| | | </div> |
| | | <a-table |
| | | :columns="columns" |
| | | :data-source="definitions" |
| | | :row-key="record => record.id" |
| | | :pagination="pagination" |
| | | :loading="loading" |
| | | @change="handleTableChange" |
| | | > |
| | | <template #bodyCell="{ column, record }"> |
| | | <template v-if="column.key === 'action'"> |
| | | <a-space> |
| | | <a-button type="link" @click="showDiagram(record)">æ¥ç</a-button> |
| | | <a-button type="link" @click="editDiagram(record)">ä¿®æ¹</a-button> |
| | | <a-button type="link" danger @click="deleteDefinition(record)">å é¤</a-button> |
| | | </a-space> |
| | | </template> |
| | | </template> |
| | | </a-table> |
| | | </a-card> |
| | | |
| | | <!-- æµç¨å¾æ¥çæ¨¡ææ¡ --> |
| | | <a-modal |
| | | v-model:visible="diagramVisible" |
| | | title="æµç¨å¾æ¥ç" |
| | | width="80%" |
| | | :footer="null" |
| | | @cancel="handleDiagramCancel" |
| | | > |
| | | <div style="text-align: center"> |
| | | <img |
| | | v-if="currentDiagramUrl" |
| | | :src="currentDiagramUrl" |
| | | alt="æµç¨å¾" |
| | | style="max-width: 100%" |
| | | /> |
| | | <a-skeleton v-else active /> |
| | | </div> |
| | | </a-modal> |
| | | |
| | | <!-- æµç¨å¾ç¼è¾æ¨¡ææ¡ --> |
| | | <a-modal |
| | | v-model:visible="editorVisible" |
| | | :title="editorTitle" |
| | | width="90%" |
| | | :maskClosable="false" |
| | | :okText="'ä¿å'" |
| | | :cancelText="'åæ¶'" |
| | | :confirmLoading="editorSaving" |
| | | @ok="handleEditorOk" |
| | | @cancel="handleEditorCancel" |
| | | :destroyOnClose="true" |
| | | :afterClose="handleEditorAfterClose" |
| | | :style="{ top: '20px' }" |
| | | :bodyStyle="{ |
| | | padding: '0', |
| | | height: 'calc(100vh - 100px)', |
| | | overflow: 'hidden', |
| | | display: 'flex', |
| | | flexDirection: 'column' |
| | | }" |
| | | > |
| | | <div class="editor-container"> |
| | | <div v-if="isCreateMode" class="create-form"> |
| | | <a-form layout="vertical"> |
| | | <a-form-item label="æµç¨åç§°" required> |
| | | <a-input v-model:value="newProcess.name" placeholder="请è¾å
¥æµç¨åç§°" /> |
| | | </a-form-item> |
| | | <a-form-item label="æµç¨Key" required> |
| | | <a-input v-model:value="newProcess.key" placeholder="请è¾å
¥æµç¨Key" /> |
| | | </a-form-item> |
| | | <a-form-item label="æµç¨æè¿°"> |
| | | <a-textarea v-model:value="newProcess.description" placeholder="请è¾å
¥æµç¨æè¿°" /> |
| | | </a-form-item> |
| | | </a-form> |
| | | </div> |
| | | <div class="bpmn-editor" ref="bpmnEditor"></div> |
| | | </div> |
| | | </a-modal> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, nextTick } from 'vue' |
| | | import { message, Modal } from 'ant-design-vue' |
| | | import BpmnModeler from 'bpmn-js/lib/Modeler' |
| | | import 'bpmn-js/dist/assets/diagram-js.css' |
| | | import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css' |
| | | import 'bpmn-js/dist/assets/bpmn-js.css' |
| | | |
| | | // è¡¨æ ¼åå®ä¹ |
| | | const columns = [ |
| | | { |
| | | title: 'ID', |
| | | dataIndex: 'id', |
| | | key: 'id', |
| | | ellipsis: true |
| | | }, |
| | | { |
| | | title: 'åç§°', |
| | | dataIndex: 'name', |
| | | key: 'name' |
| | | }, |
| | | { |
| | | title: 'Key', |
| | | dataIndex: 'key', |
| | | key: 'key' |
| | | }, |
| | | { |
| | | title: 'æä½', |
| | | key: 'action', |
| | | } |
| | | ] |
| | | |
| | | // æ°æ®ç¶æ |
| | | const definitions = ref([]) |
| | | const loading = ref(false) |
| | | const pagination = ref({ |
| | | current: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | showSizeChanger: true, |
| | | pageSizeOptions: ['10', '20', '50'] |
| | | }) |
| | | |
| | | // æµç¨å¾æ¥çç¸å
³ç¶æ |
| | | const diagramVisible = ref(false) |
| | | const currentDiagramUrl = ref('') |
| | | const currentProcessDefinition = ref(null) |
| | | |
| | | // æµç¨å¾ç¼è¾ç¸å
³ç¶æ |
| | | const editorVisible = ref(false) |
| | | const editorSaving = ref(false) |
| | | const editorTitle = ref('æµç¨å¾ç¼è¾') |
| | | const bpmnModeler = ref(null) |
| | | const bpmnEditor = ref(null) |
| | | const isCreateMode = ref(false) |
| | | const newProcess = ref({ |
| | | name: '', |
| | | key: '', |
| | | description: '' |
| | | }) |
| | | |
| | | // è·åæµç¨å®ä¹å表 |
| | | const fetchProcessDefinitions = async (params = {}) => { |
| | | loading.value = true |
| | | try { |
| | | // æ¨¡ææ°æ® |
| | | const mockData = [ |
| | | { id: '1', name: 'è¯·åæµç¨', key: 'leaveProcess'}, |
| | | { id: '2', name: 'æ¥éæµç¨', key: 'expenseProcess'}, |
| | | { id: '3', name: 'éè´æµç¨', key: 'purchaseProcess' } |
| | | ] |
| | | // 模æå页 |
| | | const start = (params.page - 1) * params.size |
| | | const end = start + params.size |
| | | definitions.value = mockData.slice(start, end) |
| | | pagination.value.total = mockData.length |
| | | } catch (error) { |
| | | message.error('å è½½æµç¨å®ä¹å¤±è´¥:'+ error.message) |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // è¡¨æ ¼å页/æåºååå¤ç |
| | | const handleTableChange = (pag, filters, sorter) => { |
| | | const params = { |
| | | page: pag.current, |
| | | size: pag.pageSize |
| | | } |
| | | |
| | | if (sorter.field) { |
| | | params.sort = sorter.field |
| | | params.order = sorter.order === 'ascend' ? 'asc' : 'desc' |
| | | } |
| | | |
| | | fetchProcessDefinitions(params) |
| | | } |
| | | |
| | | // æ¾ç¤ºæµç¨å¾ |
| | | const showDiagram = (record) => { |
| | | currentProcessDefinition.value = record |
| | | currentDiagramUrl.value = `https://via.placeholder.com/800x600?text=æµç¨å¾+${record.id}` |
| | | diagramVisible.value = true |
| | | } |
| | | |
| | | // 鿝BPMNç¼è¾å¨ |
| | | const destroyBpmnEditor = () => { |
| | | if (bpmnModeler.value) { |
| | | bpmnModeler.value.destroy() |
| | | bpmnModeler.value = null |
| | | } |
| | | } |
| | | |
| | | // åå§åBPMNç¼è¾å¨ |
| | | const initBpmnEditor = async (xml) => { |
| | | await nextTick() |
| | | |
| | | // å
鿝æ§çç¼è¾å¨ |
| | | destroyBpmnEditor() |
| | | |
| | | try { |
| | | // å建æ°çç¼è¾å¨å®ä¾ |
| | | bpmnModeler.value = new BpmnModeler({ |
| | | container: bpmnEditor.value, |
| | | }) |
| | | |
| | | // å è½½XMLæé»è®¤æµç¨å¾ |
| | | const diagram = xml || ` |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <bpmn:definitions |
| | | xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" |
| | | xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" |
| | | xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" |
| | | xmlns:di="http://www.omg.org/spec/DD/20100524/DI" |
| | | id="Definitions_1" |
| | | targetNamespace="http://bpmn.io/schema/bpmn"> |
| | | <bpmn:process id="Process_1" isExecutable="false"> |
| | | <bpmn:startEvent id="StartEvent_1" /> |
| | | </bpmn:process> |
| | | <bpmndi:BPMNDiagram id="BPMNDiagram_1"> |
| | | <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1"> |
| | | <bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1"> |
| | | <dc:Bounds x="173" y="102" width="36" height="36" /> |
| | | </bpmndi:BPMNShape> |
| | | </bpmndi:BPMNPlane> |
| | | </bpmndi:BPMNDiagram> |
| | | </bpmn:definitions> |
| | | ` |
| | | |
| | | await bpmnModeler.value.importXML(diagram) |
| | | } catch (err) { |
| | | console.error('Error rendering diagram', err) |
| | | message.error('åå§åæµç¨å¾ç¼è¾å¨å¤±è´¥: ' + err.message) |
| | | } |
| | | } |
| | | |
| | | // æ¾ç¤ºåå»ºæ°æµç¨æ¨¡ææ¡ |
| | | const showCreateModal = () => { |
| | | isCreateMode.value = true |
| | | editorTitle.value = 'åå»ºæ°æµç¨å¾' |
| | | editorVisible.value = true |
| | | |
| | | // é置表å |
| | | newProcess.value = { |
| | | name: '', |
| | | key: '', |
| | | description: '' |
| | | } |
| | | |
| | | // åå§åç¼è¾å¨ |
| | | initBpmnEditor() |
| | | } |
| | | |
| | | // ç¼è¾æµç¨å¾ |
| | | const editDiagram = async (record) => { |
| | | isCreateMode.value = false |
| | | currentProcessDefinition.value = record |
| | | editorTitle.value = `ç¼è¾æµç¨ - ${record.name}` |
| | | editorVisible.value = true |
| | | |
| | | // 模æå è½½æµç¨å®ä¹XML |
| | | const mockXml = ` |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <bpmn:definitions |
| | | xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" |
| | | xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" |
| | | xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" |
| | | xmlns:di="http://www.omg.org/spec/DD/20100524/DI" |
| | | id="Definitions_1" |
| | | targetNamespace="http://bpmn.io/schema/bpmn"> |
| | | <bpmn:process id="${record.id}" name="${record.name}" isExecutable="true"> |
| | | <bpmn:startEvent id="StartEvent_1" name="å¼å§" /> |
| | | <bpmn:userTask id="UserTask_1" name="æäº¤ç³è¯·" /> |
| | | <bpmn:sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="UserTask_1" /> |
| | | <bpmn:endEvent id="EndEvent_1" name="ç»æ" /> |
| | | <bpmn:sequenceFlow id="Flow_2" sourceRef="UserTask_1" targetRef="EndEvent_1" /> |
| | | </bpmn:process> |
| | | <bpmndi:BPMNDiagram id="BPMNDiagram_1"> |
| | | <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="${record.id}"> |
| | | <bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1"> |
| | | <dc:Bounds x="173" y="102" width="36" height="36" /> |
| | | </bpmndi:BPMNShape> |
| | | <bpmndi:BPMNShape id="UserTask_1_di" bpmnElement="UserTask_1"> |
| | | <dc:Bounds x="280" y="80" width="100" height="80" /> |
| | | </bpmndi:BPMNShape> |
| | | <bpmndi:BPMNShape id="EndEvent_1_di" bpmnElement="EndEvent_1"> |
| | | <dc:Bounds x="450" y="102" width="36" height="36" /> |
| | | </bpmndi:BPMNShape> |
| | | <bpmndi:BPMNEdge id="Flow_1_di" bpmnElement="Flow_1"> |
| | | <di:waypoint x="209" y="120" /> |
| | | <di:waypoint x="280" y="120" /> |
| | | </bpmndi:BPMNEdge> |
| | | <bpmndi:BPMNEdge id="Flow_2_di" bpmnElement="Flow_2"> |
| | | <di:waypoint x="380" y="120" /> |
| | | <di:waypoint x="450" y="120" /> |
| | | </bpmndi:BPMNEdge> |
| | | </bpmndi:BPMNPlane> |
| | | </bpmndi:BPMNDiagram> |
| | | </bpmn:definitions> |
| | | ` |
| | | |
| | | // åå§åç¼è¾å¨å¹¶å è½½XML |
| | | initBpmnEditor(mockXml) |
| | | } |
| | | |
| | | // ä¿åæµç¨å¾ä¿®æ¹ |
| | | const handleEditorOk = async () => { |
| | | editorSaving.value = true |
| | | |
| | | try { |
| | | if (isCreateMode.value) { |
| | | // éªè¯è¡¨å |
| | | if (!newProcess.value.name || !newProcess.value.key) { |
| | | message.error('è¯·å¡«åæµç¨åç§°åKey') |
| | | return |
| | | } |
| | | |
| | | // è·åXML |
| | | const { xml } = await bpmnModeler.value.saveXML({ format: true }) |
| | | console.log('æ°æµç¨XML:', xml) |
| | | |
| | | // 模æåå»ºæ°æµç¨ |
| | | await new Promise(resolve => setTimeout(resolve, 1000)) |
| | | |
| | | // æ·»å å°å表 |
| | | const newId = Math.max(...definitions.value.map(d => parseInt(d.id))) + 1 |
| | | definitions.value.unshift({ |
| | | id: newId.toString(), |
| | | name: newProcess.value.name, |
| | | key: newProcess.value.key, |
| | | version: 1 |
| | | }) |
| | | |
| | | message.success('æ°æµç¨å建æå') |
| | | } else { |
| | | // è·åä¿®æ¹åçXML |
| | | const { xml } = await bpmnModeler.value.saveXML({ format: true }) |
| | | console.log('ä¿®æ¹åçXML:', xml) |
| | | |
| | | // 模æä¿å |
| | | await new Promise(resolve => setTimeout(resolve, 1000)) |
| | | |
| | | message.success('æµç¨å¾ä¿åæå') |
| | | } |
| | | |
| | | editorVisible.value = false |
| | | } catch (error) { |
| | | console.error('Error saving BPMN diagram', error) |
| | | message.error('æä½å¤±è´¥: ' + error.message) |
| | | } finally { |
| | | editorSaving.value = false |
| | | } |
| | | } |
| | | |
| | | // å 餿µç¨å®ä¹ |
| | | const deleteDefinition = (record) => { |
| | | Modal.confirm({ |
| | | title: '确认å 餿µç¨?', |
| | | content: `ç¡®å®è¦å 餿µç¨ "${record.name}" åï¼æ¤æä½ä¸å¯æ¢å¤ã`, |
| | | okText: '确认', |
| | | okType: 'danger', |
| | | cancelText: 'åæ¶', |
| | | onOk() { |
| | | // 模æå é¤ |
| | | definitions.value = definitions.value.filter(item => item.id !== record.id) |
| | | message.success('æµç¨å 餿å') |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // æ¨¡ææ¡å
³é忏
ç |
| | | const handleEditorAfterClose = () => { |
| | | destroyBpmnEditor() |
| | | } |
| | | |
| | | const handleEditorCancel = () => { |
| | | editorVisible.value = false |
| | | } |
| | | |
| | | const handleDiagramCancel = () => { |
| | | diagramVisible.value = false |
| | | } |
| | | |
| | | // åå§åå è½½æ°æ® |
| | | onMounted(() => { |
| | | const params = { |
| | | page: 1, |
| | | size: 10 |
| | | } |
| | | fetchProcessDefinitions(params) |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .process-definition-container { |
| | | padding: 20px; |
| | | background: #fff; |
| | | } |
| | | |
| | | .table-actions { |
| | | margin-bottom: 16px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .editor-container { |
| | | height: 600px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .bpmn-editor { |
| | | flex: 1; |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 2px; |
| | | margin-top: 16px; |
| | | min-height: 500px; /* ç¡®ä¿ç¼è¾å¨æè¶³å¤é«åº¦ */ |
| | | } |
| | | |
| | | .create-form { |
| | | padding: 16px; |
| | | background: #fafafa; |
| | | border-radius: 2px; |
| | | border: 1px solid #d9d9d9; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | /* éèBPMNæ°´å° */ |
| | | .bpmn-editor :deep(.bjs-powered-by) { |
| | | display: none !important; |
| | | } |
| | | .editor-container { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .bpmn-editor { |
| | | flex: 1; |
| | | min-height: 0; /* éè¦ï¼å
许flex容卿¶ç¼© */ |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 2px; |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .create-form { |
| | | padding: 16px; |
| | | background: #fafafa; |
| | | border-radius: 2px; |
| | | border: 1px solid #d9d9d9; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | /* éèBPMNæ°´å° */ |
| | | .bpmn-editor :deep(.bjs-powered-by) { |
| | | display: none !important; |
| | | } |
| | | |
| | | /* ç¡®ä¿BPMNå·¥å
·æ å¯è§ */ |
| | | .bpmn-editor :deep(.djs-palette) { |
| | | top: 20px; |
| | | left: 20px; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { FormSchemaGetter } from '#/adapter/form'; |
| | | import type { VxeGridProps } from '#/adapter/vxe-table'; |
| | | import { h } from 'vue'; |
| | | import { FolderIcon, VbenIcon } from '@vben/icons'; |
| | | |
| | | export const querySchema: FormSchemaGetter = () => [ |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'name', |
| | | label: '页é¢åç§°', |
| | | }, |
| | | { |
| | | component: 'Select', |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'æ£å¸¸', value: '0' }, |
| | | { label: 'åç¨', value: '1' }, |
| | | ], |
| | | }, |
| | | fieldName: 'status', |
| | | label: '页é¢ç¶æ', |
| | | }, |
| | | ]; |
| | | |
| | | export const columns: VxeGridProps['columns'] = [ |
| | | { |
| | | title: '页é¢åç§°', |
| | | field: 'name', |
| | | }, |
| | | { |
| | | title: 'ä¸çº§ç®å½', |
| | | field: 'menuParentName', |
| | | |
| | | }, |
| | | { |
| | | title: 'ç¶æ', |
| | | field: 'status', |
| | | slots: { |
| | | default: ({ row }) => { |
| | | return row.status === '0' ? 'æ£å¸¸' : 'åç¨'; |
| | | }, |
| | | }, |
| | | }, |
| | | { |
| | | title: 'å建æ¶é´', |
| | | field: 'createTime', |
| | | }, |
| | | { |
| | | field: 'action', |
| | | fixed: 'right', |
| | | slots: { default: 'action' }, |
| | | title: 'æä½', |
| | | }, |
| | | ]; |
| | | |
| | | export const drawerSchema = () => [ |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'name', |
| | | label: '页é¢åç§°', |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | component: 'TreeSelect', |
| | | fieldName: 'menuParentId', |
| | | label: 'ä¸çº§ç®å½', |
| | | componentProps: { |
| | | allowClear: true, |
| | | showSearch: true, |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | component: 'Select', |
| | | fieldName: 'status', |
| | | label: 'ç¶æ', |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'æ£å¸¸', value: '0' }, |
| | | { label: 'åç¨', value: '1' }, |
| | | ], |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | component: 'CheckboxGroup', |
| | | fieldName: 'actionsFunc', |
| | | label: 'å¯ç¨åè½', |
| | | defaultValue: ['add', 'edit', 'delete', 'query'], |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'æ°å¢', value: 'add' }, |
| | | { label: 'ç¼è¾', value: 'edit' }, |
| | | { label: 'å é¤', value: 'delete' }, |
| | | { label: 'æ¥è¯¢', value: 'query' }, |
| | | ], |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | | componentProps: { |
| | | type: 'textarea', |
| | | rows: 2, |
| | | }, |
| | | }, |
| | | ]; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <Page v-if="isAdmin" :auto-content-height="true"> |
| | | <BasicTable table-title="页é¢è®¾è®¡å¨" > |
| | | <template #toolbar-tools> |
| | | <Space> |
| | | <a-button type="primary" @click="handleAdd">æ°å¢</a-button> |
| | | </Space> |
| | | </template> |
| | | <template #action="{ row }"> |
| | | <Space> |
| | | <ghost-button @click="handleEdit(row)">ç¼è¾</ghost-button> |
| | | <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认å é¤ï¼" @confirm="handleDelete(row)"> |
| | | <ghost-button danger @click.stop="">å é¤</ghost-button> |
| | | </Popconfirm> |
| | | </Space> |
| | | </template> |
| | | </BasicTable> |
| | | <PageDrawer ref="pageModalRef" @reload="tableApi.query()" :menu-array="menuArray" /> |
| | | </Page> |
| | | <Fallback v-else description="æ¨æ²¡æé¡µé¢çæå¨çè®¿é®æé" status="403" /> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import type { VbenFormProps } from '@vben/common-ui'; |
| | | import type { VxeGridProps } from '#/adapter/vxe-table'; |
| | | import { computed, ref, onMounted } from 'vue'; |
| | | import { useAccess } from '@vben/access'; |
| | | import { Fallback, Page, useVbenDrawer } from '@vben/common-ui'; |
| | | import { eachTree, getVxePopupContainer } from '@vben/utils'; |
| | | import { Popconfirm, Space } from 'ant-design-vue'; |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { columns, querySchema } from './data'; |
| | | import PageDrawer from './page-drawer.vue'; |
| | | import FcDesigner from '@form-create/designer'; |
| | | import { pageList, pageRemove } from '#/api/tool/page-designer'; |
| | | import { menuList } from '../../../api/system/menu'; |
| | | import { listToTree} from '@vben/utils'; |
| | | // ç§»é¤mockæ°æ® |
| | | // const pageList = async (params: any) => { ... }; |
| | | // const pageRemove = async (ids: number[]) => {}; |
| | | const menuArray = ref([]); |
| | | const processedMenuTree = ref([]); |
| | | onMounted(async () => { |
| | | try { |
| | | // è·ååå§èåæ°æ® |
| | | const rawMenuData = await menuList(); |
| | | menuArray.value = rawMenuData; |
| | | |
| | | // å¤çèåæ°æ® |
| | | processMenuData(); |
| | | } catch (error) { |
| | | console.error('è·åèåæ°æ®å¤±è´¥:', error); |
| | | } |
| | | }); |
| | | // å¤çèåæ°æ®ç彿° |
| | | const processMenuData = () => { |
| | | if (!menuArray.value || menuArray.value.length === 0) return; |
| | | |
| | | // 1. è¿æ»¤ææé®ç±»å(F)åèåç±»å(C) |
| | | const filteredList = menuArray.value.filter(item => |
| | | item.menuType !== 'F' && item.menuType !== 'C' |
| | | ); |
| | | |
| | | // 2. 转æ¢ä¸ºæ å½¢ç»æ |
| | | const treeData = listToTree(filteredList, { |
| | | id: 'menuId', |
| | | pid: 'parentId' |
| | | }); |
| | | |
| | | // 3. æ·»å æ ¹èç¹ |
| | | processedMenuTree.value = [ |
| | | { |
| | | menuId: 0, |
| | | parentId: 0, |
| | | menuName: 'æ ¹ç®å½', |
| | | children: treeData |
| | | } |
| | | ]; |
| | | }; |
| | | const formOptions: VbenFormProps = { |
| | | commonConfig: { |
| | | labelWidth: 80, |
| | | componentProps: { |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | schema: querySchema(), |
| | | wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', |
| | | }; |
| | | const getFullMenuPath = (id: number) => { |
| | | if (!processedMenuTree.value || processedMenuTree.value.length === 0) return ''; |
| | | |
| | | // é彿¥æ¾èåè·¯å¾ |
| | | const findPath = (tree, currentId, path = []): string[] | null => { |
| | | for (const item of tree) { |
| | | if (item.menuId === currentId) { |
| | | return [...path, item.menuName]; |
| | | } |
| | | if (item.children && item.children.length > 0) { |
| | | const found = findPath(item.children, currentId, [...path, item.menuName]); |
| | | if (found) return found; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const path = findPath(processedMenuTree.value, id); |
| | | return path ? path.join(' / ') : 'æ ¹ç®å½'; |
| | | }; |
| | | const gridOptions: VxeGridProps = { |
| | | columns, |
| | | height: 'auto', |
| | | keepSource: true, |
| | | pagerConfig: { |
| | | enabled: true, |
| | | }, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues = {}) => { |
| | | const resp = await pageList({ |
| | | pageNum: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }); |
| | | |
| | | // å¤çè¿åæ°æ®ï¼æ·»å menuParentName |
| | | const processedRows = resp.rows.map(row => { |
| | | return { |
| | | ...row, |
| | | menuParentName: getFullMenuPath(row.menuParentId) || 'æ ¹ç®å½' |
| | | }; |
| | | }); |
| | | return { |
| | | rows: processedRows, // 使ç¨å¤çåçæ°æ® |
| | | total: resp.total, |
| | | }; |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | }, |
| | | id: 'tool-page-designer-index', |
| | | columnConfig: { resizable: true }, |
| | | }; |
| | | |
| | | const [BasicTable, tableApi] = useVbenVxeGrid({ |
| | | formOptions, |
| | | gridOptions, |
| | | }); |
| | | |
| | | const designer = ref(); |
| | | const pageModalRef = ref(); |
| | | |
| | | function getFormJson() { |
| | | // è·åè®¾è®¡ç»æ |
| | | const json = designer.value.getRule(); |
| | | // ä½ å¯ä»¥å° json åå°å端 |
| | | } |
| | | |
| | | function setFormJson(json) { |
| | | // å 载已æè®¾è®¡ |
| | | designer.value.setRule(json); |
| | | } |
| | | |
| | | function handleAdd() { |
| | | pageModalRef.value.open({ update: false }); |
| | | } |
| | | |
| | | function handleEdit(record) { |
| | | pageModalRef.value.open({ id: record.id, update: true }); |
| | | } |
| | | |
| | | async function handleDelete(row: any) { |
| | | await pageRemove([row.id]); |
| | | await tableApi.query(); |
| | | } |
| | | |
| | | function handleSubAdd(row) { |
| | | pageModalRef.value.open({ id: row.id, update: false }); |
| | | } |
| | | |
| | | const { hasAccessByRoles } = useAccess(); |
| | | const isAdmin = computed(() => { |
| | | return hasAccessByRoles(['admin', 'superadmin']); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .designer-page { |
| | | background: #f5f6fa; |
| | | padding: 16px; |
| | | min-height: 100vh; |
| | | } |
| | | .designer-query-form { |
| | | background: #fff; |
| | | padding: 16px 16px 0 16px; |
| | | border-radius: 6px; |
| | | margin-bottom: 12px; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | } |
| | | .designer-toolbar { |
| | | background: #fff; |
| | | padding: 12px 16px; |
| | | border-radius: 6px; |
| | | margin-bottom: 12px; |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | .designer-table { |
| | | background: #fff; |
| | | border-radius: 6px; |
| | | padding: 0 0 16px 0; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <script setup lang="ts"> |
| | | import { computed, ref, watch, nextTick, onMounted } from 'vue'; |
| | | import { Modal, message, FormItem } from 'ant-design-vue'; |
| | | import { $t } from '@vben/locales'; |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { drawerSchema } from './data'; |
| | | import FcDesigner from '@form-create/designer'; |
| | | |
| | | import { listToTree, addFullName, getPopupContainer } from '@vben/utils'; |
| | | import { pageAdd, pageUpdate, pageInfo } from '#/api/tool/page-designer'; |
| | | |
| | | interface ModalProps { |
| | | id?: number | string; |
| | | update: boolean; |
| | | } |
| | | |
| | | |
| | | const emit = defineEmits<{ reload: [] }>(); |
| | | |
| | | const isUpdate = ref(false); |
| | | const title = computed(() => { |
| | | return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add'); |
| | | }); |
| | | |
| | | const [BasicForm, formApi] = useVbenForm({ |
| | | commonConfig: { |
| | | componentProps: { |
| | | class: 'w-full', |
| | | }, |
| | | formItemClass: 'col-span-1', |
| | | labelWidth: 90, |
| | | }, |
| | | schema: drawerSchema(), |
| | | showDefaultActions: false, |
| | | wrapperClass: 'grid-cols-5', |
| | | }); |
| | | |
| | | const designer = ref(); |
| | | const selectedFields = ref([]); // å¤éæ¡éä¸çåæ®µkey |
| | | const fieldOptions = ref([]); // è®¾è®¡åºææå段 |
| | | const modalVisible = ref(false); |
| | | const modalLoading = ref(false); |
| | | const currentEditId = ref<string | number>(''); // å½åç¼è¾çID |
| | | const fullMenuTree = ref([]); |
| | | const props=defineProps({ |
| | | menuArray: { |
| | | type: Array, |
| | | required: true, |
| | | default: () => [] |
| | | } |
| | | }); |
| | | // æå¼å¼¹çª |
| | | const open = async (params: ModalProps = { update: false }) => { |
| | | try { |
| | | |
| | | modalVisible.value = true; |
| | | modalLoading.value = true; |
| | | isUpdate.value = params.update; |
| | | currentEditId.value = params.id || ''; // ä¿åå½åç¼è¾çID |
| | | await setupPageSelect(); |
| | | |
| | | if (params.id) { |
| | | await formApi.setFieldValue('menuParentId', params.id); |
| | | if (params.update) { |
| | | // è·å详æ
æ°æ® |
| | | const record = await pageInfo(params.id); |
| | | |
| | | // 设置åºç¡è¡¨åæ°æ® |
| | | const menuParentId = String(record.menuParentId || record.parentId || ''); |
| | | await formApi.setValues({ |
| | | name: record.name, |
| | | menuParentId: menuParentId, // ç¨ menuParentId åæ®µ |
| | | status: record.status, |
| | | remark: record.remark, |
| | | actionsFunc: record.actionsFunc ? JSON.parse(record.actionsFunc) : ['add', 'edit', 'delete', 'query'] |
| | | }); |
| | | |
| | | // å 载表åè®¾è®¡æ°æ® |
| | | if (record.formJson) { |
| | | try { |
| | | const formRule = JSON.parse(record.formJson); |
| | | console.log('设计å¨è§å:', formRule); |
| | | designer.value.setRule(formRule); |
| | | |
| | | // æ´æ°å段é项 |
| | | await nextTick(); |
| | | updateFieldOptions(); |
| | | |
| | | // æ¢å¤éä¸çåæ®µ |
| | | if (record.showColumn) { |
| | | selectedFields.value = JSON.parse(record.showColumn); |
| | | } |
| | | } catch (e) { |
| | | console.error('å 载表åè®¾è®¡æ°æ®å¤±è´¥:', e); |
| | | message.error('å 载表åè®¾è®¡æ°æ®å¤±è´¥'); |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | // æ°å¢æ¶éç½®æ°æ® |
| | | designer.value?.setRule([]); |
| | | selectedFields.value = []; |
| | | await formApi.resetForm(); |
| | | } |
| | | } catch (error) { |
| | | console.error('æå¼å¼¹çªå¤±è´¥:', error); |
| | | message.error('å è½½æ°æ®å¤±è´¥'); |
| | | } finally { |
| | | modalLoading.value = false; |
| | | } |
| | | }; |
| | | const close = () => { |
| | | modalVisible.value = false; |
| | | }; |
| | | |
| | | defineExpose({ open, close }); |
| | | |
| | | async function setupPageSelect() { |
| | | // è·åèåæ°æ® |
| | | if (!props.menuArray || props.menuArray.length === 0) { |
| | | await nextTick(); // çå¾
å¯è½ç弿¥å è½½ |
| | | if (!props.menuArray || props.menuArray.length === 0) { |
| | | console.warn('menuArray is empty'); |
| | | return; |
| | | } |
| | | } |
| | | // è¿æ»¤ææé®ç±»å |
| | | const filteredList = props.menuArray.filter(item => item.menuType !== 'F' && item.menuType !== 'C'); |
| | | // æ¯æi18n |
| | | filteredList.forEach(item => { item.menuName = $t(item.menuName); }); |
| | | // 转为æ ç»æ |
| | | const menuTree = listToTree(filteredList, { id: 'menuId', pid: 'parentId' }); |
| | | // é彿 å° menuId -> menuParentId |
| | | function mapMenuIdToParentId(list) { |
| | | return list.map(item => { |
| | | const newItem = { ...item, menuParentId: item.menuId }; |
| | | if (item.children) { |
| | | newItem.children = mapMenuIdToParentId(item.children); |
| | | } |
| | | return newItem; |
| | | }); |
| | | } |
| | | fullMenuTree.value = [ |
| | | { |
| | | menuId: 0, |
| | | menuParentId: 0, |
| | | menuName: $t('menu.root'), |
| | | children: mapMenuIdToParentId(menuTree), |
| | | }, |
| | | ]; |
| | | // çæå
¨è·¯å¾å |
| | | addFullName(fullMenuTree.value, 'menuName', ' / '); |
| | | |
| | | formApi.updateSchema([ |
| | | { |
| | | componentProps: { |
| | | fieldNames: { |
| | | label: 'menuName', |
| | | value: 'menuId', // ç¨ menuId |
| | | children: 'children' |
| | | }, |
| | | getPopupContainer, |
| | | listHeight: 300, |
| | | showSearch: true, |
| | | treeData: fullMenuTree.value, |
| | | treeDefaultExpandAll: false, |
| | | treeDefaultExpandedKeys: [0], |
| | | treeLine: { showLeafIcon: false }, |
| | | treeNodeFilterProp: 'menuName', |
| | | treeNodeLabelProp: 'fullName', |
| | | }, |
| | | fieldName: 'menuParentId', // ç¨ menuParentId |
| | | }, |
| | | ]); |
| | | } |
| | | |
| | | |
| | | // 忥ææå段å°éä¸ç¶æ |
| | | const syncAllFields = () => { |
| | | // è·å表åç»ä»¶çè§åæè¿° |
| | | const formDesc = designer.value?.getFormDescription?.(); |
| | | |
| | | if (!formDesc || !Array.isArray(formDesc)) { |
| | | message.warning('ææ è®¾è®¡æ°æ®'); |
| | | return; |
| | | } |
| | | |
| | | // æååæ®µä¿¡æ¯ |
| | | const allFields = formDesc |
| | | .filter(item => item && item.field && item.title) |
| | | .map(item => ({ |
| | | title: item.title, |
| | | field: item.field |
| | | })); |
| | | |
| | | |
| | | if (allFields.length === 0) { |
| | | message.warning('æªæ¾å°å¯ç¨å段'); |
| | | return; |
| | | } |
| | | |
| | | // æ´æ°å段é项 |
| | | fieldOptions.value = allFields.map(item => ({ |
| | | label: item.title, |
| | | value: item.field |
| | | })); |
| | | |
| | | // é䏿æå段 |
| | | selectedFields.value = allFields.map(item => item.field); |
| | | message.success(`已忥 ${allFields.length} ä¸ªåæ®µ`); |
| | | }; |
| | | |
| | | // å¤ç设计å¨åå |
| | | const handleDesignerChange = () => { |
| | | nextTick(() => { |
| | | updateFieldOptions(); |
| | | }); |
| | | }; |
| | | |
| | | // å½è®¾è®¡å¨å
容ååæ¶æ´æ°å段é项 |
| | | const updateFieldOptions = () => { |
| | | // è·å表åç»ä»¶çè§åæè¿° |
| | | const formDesc = designer.value?.getFormDescription?.(); |
| | | if (!formDesc || !Array.isArray(formDesc)) return; |
| | | |
| | | const fields = formDesc |
| | | .filter(item => item && item.field && item.title) |
| | | .map(item => ({ |
| | | title: item.title, |
| | | field: item.field |
| | | })); |
| | | |
| | | fieldOptions.value = fields.map(item => ({ |
| | | label: item.title, |
| | | value: item.field |
| | | })); |
| | | }; |
| | | |
| | | // çå¬è®¾è®¡å¨å
容åå |
| | | watch(() => modalVisible.value, (val) => { |
| | | if (val) { |
| | | nextTick(() => updateFieldOptions()); |
| | | } |
| | | }); |
| | | |
| | | async function handleOk() { |
| | | try { |
| | | modalLoading.value = true; |
| | | const { valid } = await formApi.validate(); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | const data = await formApi.getValues(); |
| | | |
| | | // 妿æ¯ç¼è¾æ¨¡å¼ï¼æ·»å idåæ®µ |
| | | if (isUpdate.value) { |
| | | data.id = currentEditId.value; |
| | | } |
| | | |
| | | // è·å表å设计 JSON |
| | | data.formJson = designer.value.getJson(); |
| | | // æ·»å éä¸çåæ®µ |
| | | data.showColumn = JSON.stringify(selectedFields.value); |
| | | // 转æ¢å¯ç¨åè½ä¸ºJSONå符串 |
| | | data.actionsFunc = JSON.stringify(data.actionsFunc); |
| | | |
| | | // 忥䏿¬¡å段å¤é |
| | | updateFieldOptions(); |
| | | await (isUpdate.value ? pageUpdate(data) : pageAdd(data)); |
| | | emit('reload'); |
| | | close(); |
| | | message.success('ä¿åæå'); |
| | | } catch (error) { |
| | | console.error(error); |
| | | } finally { |
| | | modalLoading.value = false; |
| | | } |
| | | } |
| | | |
| | | function handleCancel() { |
| | | close(); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <a-modal |
| | | v-model:open="modalVisible" |
| | | :title="title" |
| | | :width="'80vw'" |
| | | :confirm-loading="modalLoading" |
| | | @ok="handleOk" |
| | | @cancel="handleCancel" |
| | | :bodyStyle="{ padding: '24px', minHeight: '60vh' }" |
| | | destroyOnClose |
| | | wrapClassName="page-designer-modal" |
| | | > |
| | | <template #closeIcon> |
| | | <span></span> |
| | | </template> |
| | | <BasicForm /> |
| | | <div style="margin-top: 16px;"> |
| | | <FcDesigner |
| | | ref="designer" |
| | | @update="handleDesignerChange" |
| | | @change="handleDesignerChange" |
| | | @add-rule="handleDesignerChange" |
| | | @remove-rule="handleDesignerChange" |
| | | |
| | | /> |
| | | <div style="margin-top: 8px; display: flex; justify-content: flex-end;"> |
| | | <a-button type="primary" ghost @click="syncAllFields"> |
| | | åæ¥è®¾è®¡åæ®µå°è¡¨æ ¼ |
| | | </a-button> |
| | | </div> |
| | | </div> |
| | | <FormItem label="è¡¨æ ¼åæ®µ" style="margin-top: 24px;"> |
| | | <a-checkbox-group |
| | | v-model:value="selectedFields" |
| | | :options="fieldOptions" |
| | | style="width:100%;display:flex;flex-wrap:wrap;gap:8px" |
| | | /> |
| | | </FormItem> |
| | | <template #empty> |
| | | <div style="padding: 32px 0; color: #999; text-align: center;"> |
| | | ææ æ°æ® |
| | | </div> |
| | | </template> |
| | | </a-modal> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | .page-designer-modal .ant-modal { |
| | | max-width: 1200px; |
| | | } |
| | | |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { FormSchemaGetter } from '#/adapter/form'; |
| | | import type { VxeGridProps } from '#/adapter/vxe-table'; |
| | | |
| | | export const querySchema: FormSchemaGetter = () => [ |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'name', |
| | | label: '模çåç§°', |
| | | }, |
| | | { |
| | | component: 'Select', |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'æ£å¸¸', value: '1' }, |
| | | { label: 'åç¨', value: '0' }, |
| | | ], |
| | | }, |
| | | fieldName: 'status', |
| | | label: '模çç¶æ', |
| | | }, |
| | | ]; |
| | | |
| | | export const columns = [ |
| | | { |
| | | title: 'å§å', |
| | | dataIndex: 'name', |
| | | auth: 'test', // æ ¹æ®æéæ§å¶æ¯å¦æ¾ç¤º: æ æéï¼ä¸æ¾ç¤º |
| | | } |
| | | ]; |
| | | |
| | | export const drawerSchema = () => [ |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'name', |
| | | label: '模çåç§°', |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | component: 'Select', |
| | | fieldName: 'pageDesignId', |
| | | label: '页é¢è®¾è®¡', |
| | | componentProps: { |
| | | allowClear: true, |
| | | showSearch: true, |
| | | filterOption: (input: string, option: any) => { |
| | | return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0; |
| | | }, |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | component: 'Select', |
| | | fieldName: 'templateType', |
| | | label: '模çç±»å', |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'å表页', value: 'list' }, |
| | | { label: '表å页', value: 'form' }, |
| | | { label: '详æ
页', value: 'detail' }, |
| | | { label: '仪表æ¿', value: 'dashboard' }, |
| | | ], |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | component: 'Select', |
| | | fieldName: 'status', |
| | | label: 'ç¶æ', |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'æ£å¸¸', value: '1' }, |
| | | { label: 'åç¨', value: '0' }, |
| | | ], |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | | componentProps: { |
| | | type: 'textarea', |
| | | rows: 2, |
| | | }, |
| | | }, |
| | | ]; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <Page v-if="isAdmin && pageId" :auto-content-height="true"> |
| | | <BasicTable |
| | | :key="tableKey" |
| | | :table-title="pageDesignDetail?.name || '模æ¿å表'" |
| | | :grid-options="gridOptions" |
| | | > |
| | | <template #toolbar-tools> |
| | | <Space> |
| | | <a-button v-if="showAction('add')" type="primary" @click="handleAdd">æ°å¢</a-button> |
| | | </Space> |
| | | </template> |
| | | <template #action="{ row }"> |
| | | <Space> |
| | | <ghost-button v-if="showAction('query')" @click="handleQuery(row)">详æ
</ghost-button> |
| | | <ghost-button v-if="showAction('edit')" @click="handleEdit(row)">ç¼è¾</ghost-button> |
| | | <Popconfirm v-if="showAction('delete')" :get-popup-container="getVxePopupContainer" placement="left" title="确认å é¤ï¼" @confirm="handleDelete(row)"> |
| | | <ghost-button danger @click.stop="">å é¤</ghost-button> |
| | | </Popconfirm> |
| | | </Space> |
| | | </template> |
| | | </BasicTable> |
| | | <TemplateDrawer ref="templateModalRef" @reload="tableApi.query()" /> |
| | | <a-modal v-model:open="detailModalVisible" title="详æ
" :footer="null" width="600px"> |
| | | <a-descriptions bordered column="1"> |
| | | <a-descriptions-item v-for="item in formDataFields" :key="item.key" :label="formFieldTitleMap[item.key] || item.key"> |
| | | <span>{{ item.value }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="å建æ¶é´"> |
| | | <span>{{ createTime }}</span> |
| | | </a-descriptions-item> |
| | | </a-descriptions> |
| | | </a-modal> |
| | | </Page> |
| | | <Fallback v-else description="æªæå® pageIdï¼æ æ³è®¿é®æ¤é¡µé¢" status="403" /> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import type { VbenFormProps } from '@vben/common-ui'; |
| | | import type { VxeGridProps } from '#/adapter/vxe-table'; |
| | | import { computed, ref, onMounted, watch } from 'vue'; |
| | | import { useRoute, useRouter } from 'vue-router'; |
| | | import { useAccess } from '@vben/access'; |
| | | import { Fallback, Page } from '@vben/common-ui'; |
| | | import { getVxePopupContainer } from '@vben/utils'; |
| | | import { Popconfirm, Space, Spin as ASpin } from 'ant-design-vue'; |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { columns as baseColumns, querySchema } from './data'; |
| | | import TemplateDrawer from './template-drawer.vue'; |
| | | import { templateList, templateRemove, templateInfo } from '#/api/tool/template'; |
| | | import { pageInfo } from '#/api/tool/page-designer'; |
| | | |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | const pageId = ref<string | number>(''); |
| | | const pageDesignDetail = ref<any>(null); // 页é¢è®¾è®¡è¯¦æ
|
| | | const loading = ref(true); // å è½½ä¸ |
| | | const detailModalVisible = ref(false); |
| | | const detailRecord = ref({}); |
| | | const formDataFields = ref([]); |
| | | const createTime = ref(''); |
| | | |
| | | // 卿columns |
| | | const dynamicColumns = ref([ |
| | | { field: 'id', title: 'ID', width: 100 }, |
| | | { field: 'formData', title: 'è¡¨åæ°æ®', minWidth: 160 }, |
| | | { field: 'action', title: 'æä½', width: 160, slots: { default: 'action' } } |
| | | ]); |
| | | |
| | | // ç¨äºè¡¨æ ¼éæ°æ¸²æç key |
| | | const tableKey = ref(0); |
| | | |
| | | // æ´æ°å¨æåç彿° |
| | | function updateDynamicColumns() { |
| | | if (!pageDesignDetail.value || !pageDesignDetail.value.showColumn || !pageDesignDetail.value.formJson) { |
| | | console.log('使ç¨é»è®¤å'); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | const showFields = JSON.parse(pageDesignDetail.value.showColumn); |
| | | const formFields = JSON.parse(pageDesignDetail.value.formJson); |
| | | const cols = showFields.map(field => { |
| | | const fieldDef = formFields.find(f => f.field === field); |
| | | return { |
| | | field: field, |
| | | title: fieldDef ? fieldDef.title : field, |
| | | minWidth: 120, |
| | | align: 'center', |
| | | }; |
| | | }); |
| | | |
| | | cols.push({ |
| | | field: 'action', |
| | | title: 'æä½', |
| | | width: 160, |
| | | slots: { default: 'action' }, |
| | | }); |
| | | |
| | | dynamicColumns.value = cols; |
| | | gridOptions.value = { ...gridOptions.value, columns: cols }; |
| | | tableKey.value++; |
| | | } catch (error) { |
| | | const fallbackCols = [ |
| | | { field: 'id', title: 'ID', width: 100 }, |
| | | { field: 'formData', title: 'è¡¨åæ°æ®', minWidth: 160 }, |
| | | { field: 'action', title: 'æä½', width: 160, slots: { default: 'action' } } |
| | | ]; |
| | | dynamicColumns.value = fallbackCols; |
| | | gridOptions.value = { ...gridOptions.value, columns: fallbackCols }; |
| | | tableKey.value++; |
| | | } |
| | | } |
| | | |
| | | |
| | | // 卿æé® |
| | | function showAction(action: string) { |
| | | if (!pageDesignDetail.value || !pageDesignDetail.value.actionsFunc) { |
| | | return true; |
| | | } |
| | | |
| | | try { |
| | | const actions = JSON.parse(pageDesignDetail.value.actionsFunc); |
| | | if (!Array.isArray(actions)) { |
| | | console.warn('actionsFunc 䏿¯æ°ç»æ ¼å¼:', pageDesignDetail.value.actionsFunc); |
| | | return true; |
| | | } |
| | | |
| | | return actions.includes(action); |
| | | } catch (error) { |
| | | console.error('è§£æ actionsFunc 失败:', error); |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | // è·å pageIdï¼åªç¨ params |
| | | function getPageId() { |
| | | const segments = window.location.pathname.split('/'); |
| | | return segments[segments.length - 1] || ''; |
| | | } |
| | | |
| | | onMounted(() => { |
| | | const initialPageId = getPageId(); |
| | | console.log('è·åå°ç pageId:', initialPageId); |
| | | |
| | | if (initialPageId) { |
| | | pageId.value = initialPageId; |
| | | handlePageIdChange(); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | }); |
| | | |
| | | // çå¬è·¯ç±ååï¼èªå¨æ´æ° pageId |
| | | watch( |
| | | () => [route.meta.pageId, route.params.pageId, route.query.pageId], |
| | | (newValues, oldValues) => { |
| | | // åªæå½å¼çæ£ååæ¶æå¤ç |
| | | if (JSON.stringify(newValues) !== JSON.stringify(oldValues)) { |
| | | const newPageId = getPageId(); |
| | | console.log('è·¯ç±ååå pageId:', newPageId); |
| | | |
| | | // åªæå½ pageId çæ£ååæ¶ææ´æ° |
| | | if (newPageId !== pageId.value) { |
| | | pageId.value = newPageId; |
| | | handlePageIdChange(); |
| | | tableApi.query(); |
| | | } |
| | | } |
| | | }, |
| | | { deep: true } |
| | | ); |
| | | |
| | | // pageIdååæ¶èªå¨è·å页é¢è®¾è®¡è¯¦æ
|
| | | async function handlePageIdChange() { |
| | | loading.value = true; |
| | | console.log(`[handlePageIdChange] å¼å§å¤ç pageId: ${pageId.value}`); |
| | | try { |
| | | if (pageId.value) { |
| | | const detail = await pageInfo(pageId.value); |
| | | console.log('[handlePageIdChange] è·åå°ç页é¢è®¾è®¡è¯¦æ
(detail):', JSON.parse(JSON.stringify(detail))); |
| | | |
| | | // å¤çæ°æ®ï¼é¿å
循ç¯å¼ç¨ |
| | | const safeDetail = { |
| | | id: detail.id, |
| | | name: detail.name, |
| | | menuParentId: detail.menuId, |
| | | status: detail.status, |
| | | remark: detail.remark, |
| | | formJson: detail.formJson, |
| | | showColumn: detail.showColumn, |
| | | actionsFunc: detail.actionsFunc, |
| | | createTime: detail.createTime, |
| | | updateTime: detail.updateTime, |
| | | createBy: detail.createBy, |
| | | updateBy: detail.updateBy, |
| | | createDept: detail.createDept |
| | | }; |
| | | |
| | | pageDesignDetail.value = safeDetail; |
| | | console.log('[handlePageIdChange] 设置ç pageDesignDetail.value:', JSON.parse(JSON.stringify(pageDesignDetail.value))); |
| | | updateDynamicColumns(); |
| | | } else { |
| | | pageDesignDetail.value = null; |
| | | updateDynamicColumns(); |
| | | } |
| | | } catch (error) { |
| | | console.error('[handlePageIdChange] è·å页é¢è®¾è®¡è¯¦æ
失败:', error); |
| | | pageDesignDetail.value = null; |
| | | updateDynamicColumns(); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | |
| | | // const formOptions: VbenFormProps = { |
| | | // commonConfig: { |
| | | // labelWidth: 80, |
| | | // componentProps: { |
| | | // allowClear: true, |
| | | // }, |
| | | // }, |
| | | // schema: querySchema(), |
| | | // wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', |
| | | // }; |
| | | |
| | | const gridOptions = ref<VxeGridProps>({ |
| | | columns: dynamicColumns.value, |
| | | height: 'auto', |
| | | keepSource: true, |
| | | pagerConfig: { |
| | | enabled: true, |
| | | }, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues = {}) => { |
| | | try { |
| | | console.log('æ¥è¯¢åæ°:', { page, formValues }); |
| | | const queryParams = { |
| | | pageNum: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }; |
| | | if (pageId.value) { |
| | | queryParams.pageId = pageId.value; |
| | | } |
| | | const resp = await templateList(queryParams); |
| | | // å¤çæ¯æ¡ row ç formData |
| | | const rows = (resp.rows || []).map(row => { |
| | | let formData = {}; |
| | | try { |
| | | if (row.formData) { |
| | | formData = JSON.parse(row.formData); |
| | | console.log('è§£æåç formData:', formData); |
| | | // å é¤åå§ç formData åæ®µï¼å 为æä»¬å·²ç»å±å¼å®çå
容 |
| | | const { formData: _, ...restRow } = row; |
| | | // è¿åå±å¼åçæ°æ® |
| | | return { |
| | | ...restRow, |
| | | ...formData |
| | | }; |
| | | } |
| | | } catch (e) { |
| | | console.error('è§£æ formData 失败:', e); |
| | | } |
| | | return row; |
| | | }); |
| | | console.log('å¤çåç rows:', rows); |
| | | return { |
| | | rows, |
| | | total: resp.total || 0, |
| | | }; |
| | | } catch (error) { |
| | | console.error('æ¥è¯¢æ¨¡æ¿å表失败:', error); |
| | | return { |
| | | rows: [], |
| | | total: 0, |
| | | }; |
| | | } |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | }, |
| | | id: 'tool-template-index', |
| | | columnConfig: { resizable: true }, |
| | | }); |
| | | |
| | | const [BasicTable, tableApi] = useVbenVxeGrid({ |
| | | // formOptions, |
| | | gridOptions: computed(() => ({ |
| | | ...gridOptions.value, |
| | | columns: dynamicColumns.value |
| | | })), |
| | | }); |
| | | |
| | | const templateModalRef = ref(); |
| | | const generateModalRef = ref(); |
| | | |
| | | function handleAdd() { |
| | | // 妿æ pageIdï¼ä¼ éç»æ°å¢ |
| | | const params: any = { update: false }; |
| | | if (pageId.value) { |
| | | params.pageId = pageId.value; |
| | | } |
| | | // å¨æä¼ éformJsonï¼å
JSON.parseï¼ä¿è¯æ¯çº¯å¯¹è±¡ |
| | | if (pageDesignDetail.value && pageDesignDetail.value.formJson) { |
| | | try { |
| | | const formJson = JSON.parse(pageDesignDetail.value.formJson); |
| | | params.formJson = formJson; |
| | | console.log('ä¼ éå¨æè¡¨ååæ®µ:', formJson); |
| | | } catch (error) { |
| | | console.error('è§£æ formJson 失败:', error); |
| | | params.formJson = undefined; |
| | | } |
| | | } |
| | | templateModalRef.value.open(params); |
| | | } |
| | | |
| | | function handleEdit(record) { |
| | | // ç¼è¾æ¶ä¹ä¼ éformJsonï¼å
JSON.parseï¼ä¿è¯æ¯çº¯å¯¹è±¡ |
| | | const params: any = { |
| | | id: record.id, |
| | | update: true, |
| | | pageId: pageId.value, // ä¼ é页é¢è®¾è®¡ID |
| | | record: record // ä¼ é宿´çè®°å½æ°æ® |
| | | }; |
| | | |
| | | if (pageDesignDetail.value && pageDesignDetail.value.formJson) { |
| | | try { |
| | | const formJson = JSON.parse(pageDesignDetail.value.formJson); |
| | | params.formJson = formJson; |
| | | console.log('ç¼è¾æ¶ä¼ éæ°æ®:', { record, formJson, pageId: pageId.value }); |
| | | } catch (error) { |
| | | console.error('è§£æ formJson 失败:', error); |
| | | params.formJson = undefined; |
| | | } |
| | | } |
| | | templateModalRef.value.open(params); |
| | | } |
| | | |
| | | async function handleDelete(row: any) { |
| | | try { |
| | | await templateRemove([row.id]); |
| | | await tableApi.query(); |
| | | } catch (error) { |
| | | console.error('å 餿¨¡æ¿å¤±è´¥:', error); |
| | | } |
| | | } |
| | | |
| | | async function handleQuery(row) { |
| | | try { |
| | | const detail = await templateInfo(row.id); |
| | | detailRecord.value = detail || {}; |
| | | createTime.value = detail.createTime || ''; |
| | | // è§£æ formData |
| | | let fields = []; |
| | | if (detail.formData) { |
| | | try { |
| | | const data = JSON.parse(detail.formData); |
| | | fields = Object.entries(data).map(([key, value]) => ({ key, value })); |
| | | } catch (e) { |
| | | fields = []; |
| | | } |
| | | } |
| | | formDataFields.value = fields; |
| | | detailModalVisible.value = true; |
| | | } catch (e) { |
| | | detailRecord.value = {}; |
| | | formDataFields.value = []; |
| | | createTime.value = ''; |
| | | detailModalVisible.value = true; |
| | | } |
| | | } |
| | | |
| | | const { hasAccessByRoles } = useAccess(); |
| | | const isAdmin = computed(() => { |
| | | try { |
| | | return hasAccessByRoles(['admin', 'superadmin']); |
| | | } catch (error) { |
| | | console.error('æ£æ¥æé失败:', error); |
| | | return false; |
| | | } |
| | | }); |
| | | |
| | | const isReady = computed(() => { |
| | | try { |
| | | // ç®å夿é»è¾ï¼åå°ä¸å¿
è¦çè®¡ç® |
| | | return !!(pageDesignDetail.value && !loading.value); |
| | | } catch (error) { |
| | | console.error('æ£æ¥é¡µé¢åå¤ç¶æå¤±è´¥:', error); |
| | | return false; |
| | | } |
| | | }); |
| | | |
| | | const formFieldTitleMap = computed(() => { |
| | | try { |
| | | if (pageDesignDetail.value && pageDesignDetail.value.formJson) { |
| | | const arr = JSON.parse(pageDesignDetail.value.formJson); |
| | | return arr.reduce((map, item) => { |
| | | map[item.field] = item.title || item.field; |
| | | return map; |
| | | }, {}); |
| | | } |
| | | } catch (e) {} |
| | | return {}; |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .template-page { |
| | | background: #f5f6fa; |
| | | padding: 16px; |
| | | min-height: 100vh; |
| | | height: 100vh; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | /* ç¡®ä¿è¡¨æ ¼å®¹å¨é«åº¦ç¨³å® */ |
| | | :deep(.vxe-table--main-wrapper) { |
| | | height: 690px !important; |
| | | } |
| | | |
| | | /* ç¡®ä¿å页å¨ä½ç½®åºå® */ |
| | | :deep(.vxe-pager) { |
| | | position: sticky; |
| | | bottom: 0; |
| | | background: white; |
| | | z-index: 10; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <script setup lang="ts"> |
| | | import { computed, ref, watch, nextTick } from 'vue'; |
| | | import { Modal, message, FormItem } from 'ant-design-vue'; |
| | | import { $t } from '@vben/locales'; |
| | | import { templateAdd, templateUpdate, templateInfo } from '#/api/tool/template'; |
| | | import { pageList } from '#/api/tool/page-designer'; |
| | | import formCreate from '@form-create/element-ui'; |
| | | |
| | | interface ModalProps { |
| | | id?: number | string; |
| | | update: boolean; |
| | | pageId?: string | number; |
| | | formJson?: any; |
| | | } |
| | | |
| | | const emit = defineEmits<{ reload: [] }>(); |
| | | |
| | | const isUpdate = ref(false); |
| | | const title = computed(() => { |
| | | return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add'); |
| | | }); |
| | | |
| | | const modalVisible = ref(false); |
| | | const modalLoading = ref(false); |
| | | const currentEditId = ref<string | number>(''); |
| | | const dynamicFormRef = ref(); |
| | | const dynamicFormRule = ref([]); |
| | | const dynamicFormOption = ref({ |
| | | submitBtn: false, |
| | | resetBtn: false |
| | | }); |
| | | const showOkBtn = ref(true); |
| | | const currentPageId = ref(''); |
| | | const formApi = ref(); |
| | | |
| | | // 夿æ¯å¦ææäº¤æé® |
| | | type RuleItem = { type?: string }; |
| | | const hasSubmitBtn = (rules: any[] = []) => { |
| | | return rules.some((item: RuleItem) => item.type === 'submit'); |
| | | }; |
| | | // æ´å½»åºçéå½ç§»é¤ææ submit æé®ï¼æ¯æ childrenãbodyãcolumnsãlistãoptionsãtabs çå®¹å¨ |
| | | function removeSubmitBtn(rules = []) { |
| | | return rules |
| | | .filter(item => item.type !== 'submit') |
| | | .map(item => { |
| | | if (item.children) item.children = removeSubmitBtn(item.children); |
| | | if (item.body) item.body = removeSubmitBtn(item.body); |
| | | if (item.columns) item.columns = item.columns.map(col => ({ |
| | | ...col, |
| | | list: removeSubmitBtn(col.list || []) |
| | | })); |
| | | if (item.list) item.list = removeSubmitBtn(item.list); |
| | | if (item.options && Array.isArray(item.options)) item.options = removeSubmitBtn(item.options); |
| | | if (item.tabs) item.tabs = item.tabs.map(tab => ({ |
| | | ...tab, |
| | | list: removeSubmitBtn(tab.list || []) |
| | | })); |
| | | return item; |
| | | }); |
| | | } |
| | | |
| | | // æå¼å¼¹çª |
| | | const open = async (params: ModalProps = { update: false }) => { |
| | | try { |
| | | console.log('æå¼å¼¹çªï¼åæ°:', params); |
| | | modalVisible.value = true; |
| | | modalLoading.value = true; |
| | | isUpdate.value = params.update; |
| | | currentEditId.value = params.id || ''; |
| | | currentPageId.value = params.pageId || ''; |
| | | |
| | | // è®¾ç½®å¨æè¡¨ååæ®µï¼å§ç»ç§»é¤ææsubmitæé® |
| | | if (params.formJson) { |
| | | console.log('è®¾ç½®å¨æè¡¨åè§å:', params.formJson); |
| | | dynamicFormRule.value = removeSubmitBtn(params.formJson); |
| | | showOkBtn.value = true; // å§ç»æ¾ç¤ºç¡®å®æé® |
| | | } else { |
| | | dynamicFormRule.value = []; |
| | | showOkBtn.value = true; |
| | | } |
| | | |
| | | // ç¼è¾æ¨¡å¼ |
| | | if (params.id && params.update) { |
| | | console.log('ç¼è¾æ¨¡å¼ï¼è·å详æ
æ°æ®'); |
| | | try { |
| | | // è·å详æ
æ°æ® |
| | | const record = await templateInfo(params.id); |
| | | console.log('è·åå°çè®°å½æ°æ®:', record); |
| | | |
| | | // è®¾ç½®å¨æè¡¨åæ°æ® |
| | | if (record.formData) { |
| | | try { |
| | | const dynamicData = JSON.parse(record.formData); |
| | | console.log('è§£æåçè¡¨åæ°æ®:', dynamicData); |
| | | |
| | | await nextTick(); |
| | | if (formApi.value) { |
| | | console.log('åå¤è®¾ç½®è¡¨åæ°æ®å°ç»ä»¶'); |
| | | // ä½¿ç¨ form-create ç API è®¾ç½®å¼ |
| | | Object.keys(dynamicData).forEach(key => { |
| | | formApi.value.setValue(key, dynamicData[key]); |
| | | }); |
| | | console.log('è¡¨åæ°æ®è®¾ç½®å®æ'); |
| | | } else { |
| | | console.warn('表åAPIæªå°±ç»ª'); |
| | | message.error('è¡¨åæªå°±ç»ªï¼è¯·éè¯'); |
| | | } |
| | | } catch (error) { |
| | | console.error('è§£æå¨æåæ®µæ°æ®å¤±è´¥:', error); |
| | | message.error('å è½½è¡¨åæ°æ®å¤±è´¥'); |
| | | } |
| | | } else { |
| | | console.log('è®°å½ä¸æ²¡æ formData æ°æ®'); |
| | | } |
| | | } catch (error) { |
| | | console.error('å¤çè¡¨åæ°æ®å¤±è´¥:', error); |
| | | message.error('å è½½è¡¨åæ°æ®å¤±è´¥ï¼è¯·éè¯'); |
| | | } |
| | | } else { |
| | | // æ°å¢æ¶éç½®æ°æ® |
| | | console.log('æ°å¢æ¨¡å¼ï¼é置表å'); |
| | | await nextTick(); |
| | | if (formApi.value) { |
| | | formApi.value.resetFields && formApi.value.resetFields(); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('æå¼å¼¹çªå¤±è´¥:', error); |
| | | message.error('å è½½æ°æ®å¤±è´¥'); |
| | | } finally { |
| | | modalLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const close = () => { |
| | | modalVisible.value = false; |
| | | }; |
| | | |
| | | defineExpose({ open, close }); |
| | | |
| | | function onFormMounted(api) { |
| | | formApi.value = api; |
| | | } |
| | | |
| | | // handleOk åªè´è´£è§¦å表å submit |
| | | async function handleOk() { |
| | | await nextTick(); |
| | | console.log('handleOk formApi:', formApi.value); |
| | | if (!dynamicFormRule.value || dynamicFormRule.value.length === 0) { |
| | | message.error('表åè§åæªå è½½ï¼æ æ³æäº¤'); |
| | | return; |
| | | } |
| | | if (!formApi.value) { |
| | | message.error('è¡¨åæªæ¸²æå®æï¼è¯·ç¨åéè¯'); |
| | | return; |
| | | } |
| | | try { |
| | | modalLoading.value = true; |
| | | const valid = await formApi.value.validate(); |
| | | if (!valid) { |
| | | modalLoading.value = false; |
| | | return; |
| | | } |
| | | const formData = formApi.value.formData(); |
| | | await onFormSubmit(formData); |
| | | } catch (error) { |
| | | console.error('ä¿å失败:', error); |
| | | message.error('ä¿å失败'); |
| | | modalLoading.value = false; |
| | | } |
| | | } |
| | | |
| | | // form-create ç submit äºä»¶å¤ç |
| | | async function onFormSubmit(dynamicData: any) { |
| | | try { |
| | | modalLoading.value = true; |
| | | // æå»ºä¿åæ°æ® |
| | | const finalData = { |
| | | pageId: currentPageId.value, |
| | | formData: Object.keys(dynamicData).length > 0 ? JSON.stringify(dynamicData) : undefined |
| | | }; |
| | | if (isUpdate.value) { |
| | | finalData.id = currentEditId.value; |
| | | } |
| | | console.log(finalData) |
| | | await (isUpdate.value ? templateUpdate(finalData) : templateAdd(finalData)); |
| | | emit('reload'); |
| | | close(); |
| | | message.success('ä¿åæå'); |
| | | } catch (error) { |
| | | console.error('ä¿å失败:', error); |
| | | message.error('ä¿å失败'); |
| | | } finally { |
| | | modalLoading.value = false; |
| | | } |
| | | } |
| | | |
| | | function handleCancel() { |
| | | close(); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <a-modal |
| | | v-model:open="modalVisible" |
| | | :title="title" |
| | | :width="'80vw'" |
| | | :confirm-loading="modalLoading" |
| | | @ok="handleOk" |
| | | @cancel="handleCancel" |
| | | :bodyStyle="{ padding: '24px', minHeight: '60vh' }" |
| | | destroyOnClose |
| | | :ok-button-props="{ style: showOkBtn ? {} : { display: 'none' } }" |
| | | > |
| | | <!-- å¨æè¡¨ååºå --> |
| | | <form-create |
| | | ref="dynamicFormRef" |
| | | :rule="dynamicFormRule" |
| | | :option="dynamicFormOption" |
| | | @submit="onFormSubmit" |
| | | @mounted="onFormMounted" |
| | | /> |
| | | </a-modal> |
| | | </template> |