diff --git a/core/src/main/java/com/dite/znpt/constant/Message.java b/core/src/main/java/com/dite/znpt/constant/Message.java index d694614..974043f 100644 --- a/core/src/main/java/com/dite/znpt/constant/Message.java +++ b/core/src/main/java/com/dite/znpt/constant/Message.java @@ -20,7 +20,9 @@ public class Message implements Serializable { public static final String IMAGE_SOURCE_IS_NOT_EXIST = "图像类型不存在"; public static final String DEFECT_ID_IS_NOT_EXIST = "缺陷id不存在"; public static final String PROJECT_ID_IS_NOT_EXIST = "项目id不存在"; + public static final String PROJECT_STATUS_IS_NOT_COMPLETED = "项目[{}]的状态不是已完工"; public static final String TURBINE_ID_IS_NOT_EXIST = "机组id不存在"; + public static final String TURBINE_STATUS_IS_NOT_COMPLETED = "机组[{}]的状态不是已完工"; public static final String PART_ID_IS_NOT_EXIST = "部件id不存在"; public static final String USER_ID_NOT_EXIST = "用户id不存在"; public static final String USER_ID_NOT_EXIST_OR_ILLEGAL = "用户id不存在或者不合法"; @@ -67,4 +69,5 @@ public class Message implements Serializable { public static final String SUGGESTION_ID_IS_NOT_EXIST = "维修建议id不存在"; public static final String SUGGESTION_LEVEL_TYPE_FORBID_REPEAT = "存在缺陷级别为[{}]缺陷类型为[{}]的维修建议"; public static final String CHECK_SCHEME_ID_IS_NOT_EXIST = "检查方案id不存在"; + public static final String INSPECTION_REPORT_ID_IS_NOT_EXIST = "检查报告id不存在"; } diff --git a/core/src/main/java/com/dite/znpt/converts/Converts.java b/core/src/main/java/com/dite/znpt/converts/Converts.java index a8f7ba6..9c20029 100644 --- a/core/src/main/java/com/dite/znpt/converts/Converts.java +++ b/core/src/main/java/com/dite/znpt/converts/Converts.java @@ -108,5 +108,17 @@ public interface Converts { CheckSchemeResp toCheckSchemeResp(CheckSchemeEntity entity); CheckSchemeEntity toCheckSchemeEntity(CheckSchemeReq req); + + InspectionReportEntity toInspectionReportEntity(InspectionReportReq req); + + InspectionReportCheckInfo toInspectionReportCheckInfo(InspectionReportEntity entity); + + InspectionReportReportInfo toInspectionReportReportInfo(InspectionReportEntity entity); + + List toInspectionReportSchemeInfo(List list); + + AttendanceRecordEntity toAttendanceRecordEntity(AttendanceRecordReq req); + + List toAttendanceRecordResp(List list); } diff --git a/core/src/main/java/com/dite/znpt/domain/dto/FlowProcDefDto.java b/core/src/main/java/com/dite/znpt/domain/dto/FlowProcDefDto.java new file mode 100644 index 0000000..b4922ea --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/dto/FlowProcDefDto.java @@ -0,0 +1,57 @@ +package com.dite.znpt.domain.dto; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + *

流程定义

+ * + * @author Tony + * @date 2021-04-03 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel("流程定义") +public class FlowProcDefDto implements Serializable { + + @ApiModelProperty("流程id") + private String id; + + @ApiModelProperty("流程名称") + private String name; + + @ApiModelProperty("流程key") + private String flowKey; + + @ApiModelProperty("流程分类") + private String category; + + @ApiModelProperty("配置表单名称") + private String formName; + + @ApiModelProperty("配置表单id") + private Long formId; + + @ApiModelProperty("版本") + private int version; + + @ApiModelProperty("部署ID") + private String deploymentId; + + @ApiModelProperty("流程定义状态: 1:激活 , 2:中止") + private int suspensionState; + + @ApiModelProperty("部署时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date deploymentTime; + + +} diff --git a/core/src/main/java/com/dite/znpt/domain/entity/AttendanceRecordEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/AttendanceRecordEntity.java new file mode 100644 index 0000000..d6413ee --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/entity/AttendanceRecordEntity.java @@ -0,0 +1,54 @@ +package com.dite.znpt.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.dite.znpt.domain.AuditableEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * @Author: gaoxiong + * @Date: 2025/7/21 20:51 + * @Description: + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("attendance_record") +@ApiModel(value="AttendanceRecordEntity对象", description="打卡记录表") +public class AttendanceRecordEntity extends AuditableEntity implements Serializable { + @Serial + private static final long serialVersionUID = 6186237408298557453L; + + @ApiModelProperty("考勤记录id") + @TableId(value = "record_id", type = IdType.ASSIGN_UUID) + private String recordId; + + @ApiModelProperty("考勤人员") + private String userId; + + @ApiModelProperty("记录类型,0-上班,1-下班,2-无效") + private String recordType; + + @ApiModelProperty("考勤日期") + private LocalDate attendanceDate; + + @ApiModelProperty("打卡时间") + private LocalDateTime recordTime; + + @ApiModelProperty("照片") + private String recordImage; + + @ApiModelProperty("打卡地点,经纬度") + private String recordPosition; + + @ApiModelProperty("打卡地点,中文描述") + private String recordPositionLabel; +} diff --git a/core/src/main/java/com/dite/znpt/domain/entity/CheckSchemeEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/CheckSchemeEntity.java index d007394..ae4d742 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/CheckSchemeEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/CheckSchemeEntity.java @@ -52,6 +52,6 @@ public class CheckSchemeEntity extends AuditableEntity implements Serializable { private String remark; @ApiModelProperty("删除标志(0代表存在 1代表删除)") - @TableField("delFlag") + @TableField("del_flag") private String delFlag; } diff --git a/core/src/main/java/com/dite/znpt/domain/entity/ContractEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/ContractEntity.java new file mode 100644 index 0000000..3f1627d --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/entity/ContractEntity.java @@ -0,0 +1,110 @@ +package com.dite.znpt.domain.entity; + +import java.math.BigDecimal; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.dite.znpt.domain.AuditableEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.alibaba.excel.annotation.ExcelProperty; + +/** + * @author huise23 + * @date 2025/07/21 21:13 + * @Description: 合同表实体类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("contract") +@ApiModel(value="ContractEntity对象", description="合同表") +public class ContractEntity extends AuditableEntity implements Serializable { + + @Serial + private static final long serialVersionUID = 782007452634989148L; + + @ExcelProperty("合同id") + @ApiModelProperty("合同id") + @TableId(value = "contract_id", type = IdType.ASSIGN_ID) + private String contractId; + + @ExcelProperty("客户名称") + @ApiModelProperty("客户名称") + @TableField("customer") + private String customer; + + @ExcelProperty("合同编号") + @ApiModelProperty("合同编号") + @TableField("code") + private String code; + + @ExcelProperty("项目id") + @ApiModelProperty("项目id") + @TableField("project_id") + private String projectId; + + @ExcelProperty("业务员id") + @ApiModelProperty("业务员id") + @TableField("salesperson_id") + private String salespersonId; + + @ExcelProperty("部门id") + @ApiModelProperty("部门id") + @TableField("department_id") + private String departmentId; + + @ExcelProperty("签订日期") + @ApiModelProperty("签订日期") + @TableField("sign_date") + private Date signDate; + + @ExcelProperty("期限") + @ApiModelProperty("期限") + @TableField("duration") + private String duration; + + @ExcelProperty("类型") + @ApiModelProperty("类型") + @TableField("type") + private String type; + + @ExcelProperty("产品或服务") + @ApiModelProperty("产品或服务") + @TableField("product_service") + private String productService; + + @ExcelProperty("付款日期/交付日期") + @ApiModelProperty("付款日期/交付日期") + @TableField("payment_date") + private Date paymentDate; + + @ExcelProperty("付款地址/交付地址") + @ApiModelProperty("付款地址/交付地址") + @TableField("payment_address") + private String paymentAddress; + + @ExcelProperty("金额") + @ApiModelProperty("金额") + @TableField("amount") + private BigDecimal amount; + + @ExcelProperty("收款账号") + @ApiModelProperty("收款账号") + @TableField("account_number") + private String accountNumber; + + @ExcelProperty("备注") + @ApiModelProperty("备注") + @TableField("notes") + private String notes; + + @ExcelProperty("合同状态") + @ApiModelProperty("合同状态") + @TableField("contract_status") + private String contractStatus; +} + diff --git a/core/src/main/java/com/dite/znpt/domain/entity/ContractSettlementEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/ContractSettlementEntity.java new file mode 100644 index 0000000..bd93291 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/entity/ContractSettlementEntity.java @@ -0,0 +1,105 @@ +package com.dite.znpt.domain.entity; + +import java.math.BigDecimal; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.dite.znpt.domain.AuditableEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.alibaba.excel.annotation.ExcelProperty; + +/** + * @author huise23 + * @date 2025/07/21 21:13 + * @Description: 合同结算表实体类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("contract_settlement") +@ApiModel(value="ContractSettlementEntity对象", description="合同结算表") +public class ContractSettlementEntity extends AuditableEntity implements Serializable { + + @Serial + private static final long serialVersionUID = -59751771276704650L; + + @ExcelProperty("合同结算id") + @ApiModelProperty("合同结算id") + @TableId(value = "settlement_id", type = IdType.ASSIGN_ID) + private String settlementId; + + @ExcelProperty("合同id") + @ApiModelProperty("合同id") + @TableField("contract_id") + private String contractId; + + @ExcelProperty("客户/供应商名称") + @ApiModelProperty("客户/供应商名称") + @TableField("customer") + private String customer; + + @ExcelProperty("合同结算编号") + @ApiModelProperty("合同结算编号") + @TableField("code") + private String code; + + @ExcelProperty("项目id") + @ApiModelProperty("项目id") + @TableField("project_id") + private String projectId; + + @ExcelProperty("业务员id") + @ApiModelProperty("业务员id") + @TableField("salesperson_id") + private String salespersonId; + + @ExcelProperty("部门id") + @ApiModelProperty("部门id") + @TableField("department_id") + private String departmentId; + + @ExcelProperty("账期") + @ApiModelProperty("账期") + @TableField("payment_period") + private Date paymentPeriod; + + @ExcelProperty("日期") + @ApiModelProperty("日期") + @TableField("payment_date") + private Date paymentDate; + + @ExcelProperty("期限") + @ApiModelProperty("期限") + @TableField("duration") + private String duration; + + @ExcelProperty("产品或服务") + @ApiModelProperty("产品或服务") + @TableField("product_service") + private String productService; + + @ExcelProperty("金额") + @ApiModelProperty("金额") + @TableField("amount") + private BigDecimal amount; + + @ExcelProperty("收款账号") + @ApiModelProperty("收款账号") + @TableField("account_number") + private String accountNumber; + + @ExcelProperty("备注") + @ApiModelProperty("备注") + @TableField("notes") + private String notes; + + @ExcelProperty("合同结算状态") + @ApiModelProperty("合同结算状态") + @TableField("settlement_status") + private String settlementStatus; +} + diff --git a/core/src/main/java/com/dite/znpt/domain/entity/DefectEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/DefectEntity.java index a4d352a..1921e16 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/DefectEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/DefectEntity.java @@ -1,5 +1,6 @@ package com.dite.znpt.domain.entity; +import java.io.Serial; import java.math.BigDecimal; import java.io.Serializable; import java.time.LocalDateTime; @@ -23,6 +24,7 @@ import com.alibaba.excel.annotation.ExcelProperty; @ApiModel(value="DefectEntity对象", description="缺陷记录表") public class DefectEntity extends AuditableEntity implements Serializable { + @Serial private static final long serialVersionUID = 721961595098309935L; @ExcelProperty("缺陷id") diff --git a/core/src/main/java/com/dite/znpt/domain/entity/InspectionReportEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/InspectionReportEntity.java index be836b3..0e47de4 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/InspectionReportEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/InspectionReportEntity.java @@ -56,10 +56,6 @@ public class InspectionReportEntity extends AuditableEntity implements Serializa @TableField("check_date") private LocalDate checkDate; - @ApiModelProperty("检查位置") - @TableField("check_position") - private String checkPosition; - @ApiModelProperty("检查内容") @TableField("check_content") private String checkContent; diff --git a/core/src/main/java/com/dite/znpt/domain/entity/ProjectBudgetInfoEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/ProjectBudgetInfoEntity.java new file mode 100644 index 0000000..7b5e4bb --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/entity/ProjectBudgetInfoEntity.java @@ -0,0 +1,61 @@ +package com.dite.znpt.domain.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.dite.znpt.domain.AuditableEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息表实体类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("project_budget_info") +@ApiModel(value="ProjectBudgetInfoEntity对象", description="项目预算信息表") +public class ProjectBudgetInfoEntity extends AuditableEntity implements Serializable { + + @Serial + private static final long serialVersionUID = 514469235298737990L; + + @ExcelProperty("主键") + @ApiModelProperty("主键") + @TableId(value = "budget_id", type = IdType.ASSIGN_ID) + private String budgetId; + + @ExcelProperty("项目id") + @ApiModelProperty("项目id") + @TableField("project_id") + private String projectId; + + @ExcelProperty("预算名称") + @ApiModelProperty("预算名称") + @TableField("budget_name") + private String budgetName; + + @ExcelProperty("预算类型") + @ApiModelProperty("预算类型") + @TableField("budget_type") + private String budgetType; + + @ExcelProperty("预算金额(万元)") + @ApiModelProperty("预算金额(万元)") + @TableField("budget_amount") + private Double budgetAmount; + + @ExcelProperty("预算说明") + @ApiModelProperty("预算说明") + @TableField("budget_desc") + private String budgetDesc; +} + diff --git a/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskEntity.java index 3c3560d..e2a25e8 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskEntity.java @@ -81,5 +81,9 @@ public class ProjectTaskEntity extends AuditableEntity implements Serializable { @ApiModelProperty("备注") @TableField("remark") private String remark; + + @ApiModelProperty("项目id") + @TableField("project_id") + private String projectId; } diff --git a/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskGroupEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskGroupEntity.java index 15f38a0..e46c2c7 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskGroupEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskGroupEntity.java @@ -33,5 +33,9 @@ public class ProjectTaskGroupEntity extends AuditableEntity implements Serializa @ApiModelProperty("项目任务组名") @TableField("group_name") private String groupName; + + @ApiModelProperty("项目id") + @TableField("project_id") + private String projectId; } diff --git a/core/src/main/java/com/dite/znpt/domain/entity/RoleMenuEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/RoleMenuEntity.java index 057f9bc..914fcdd 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/RoleMenuEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/RoleMenuEntity.java @@ -11,6 +11,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; +import java.io.Serial; import java.io.Serializable; /** @@ -24,6 +25,9 @@ import java.io.Serializable; @ApiModel(value="RoleMenuEntity对象", description="角色和菜单关联表") public class RoleMenuEntity extends AuditableEntity implements Serializable { + @Serial + private static final long serialVersionUID = -795955361477553526L; + @ApiModelProperty("角色id") @TableField("role_id") private String roleId; diff --git a/core/src/main/java/com/dite/znpt/domain/vo/AttendanceRecordReq.java b/core/src/main/java/com/dite/znpt/domain/vo/AttendanceRecordReq.java new file mode 100644 index 0000000..e9692f0 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/AttendanceRecordReq.java @@ -0,0 +1,34 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.io.Serial; +import java.io.Serializable; + +/** + * @Author: gaoxiong + * @Date: 2025/7/21 21:10 + * @Description: + */ +@Data +@ApiModel("考勤记录请求对象") +public class AttendanceRecordReq implements Serializable { + @Serial + private static final long serialVersionUID = 3567864990724491657L; + + @NotBlank(message = "打卡照片不能为空") + @ApiModelProperty("打卡照片") + private String recordImage; + + @NotBlank(message = "打卡地点不能为空") + @ApiModelProperty("打卡地点,经纬度") + private String recordPosition; + + @ApiModelProperty("打卡地点,中文描述") + private String recordPositionLabel; + + +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/AttendanceRecordResp.java b/core/src/main/java/com/dite/znpt/domain/vo/AttendanceRecordResp.java new file mode 100644 index 0000000..22d250a --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/AttendanceRecordResp.java @@ -0,0 +1,54 @@ +package com.dite.znpt.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * @Author: gaoxiong + * @Date: 2025/7/21 21:11 + * @Description: + */ +@Data +@ApiModel("考勤记录响应对象") +public class AttendanceRecordResp implements Serializable { + @Serial + private static final long serialVersionUID = -4158464225924809958L; + + + @ApiModelProperty("考勤记录id") + private String recordId; + + @ApiModelProperty("考勤人员id") + private String userId; + + @ApiModelProperty("考勤人员") + private String name; + + @ApiModelProperty("记录类型, 0-上班,1-下班,2-无效") + private String recordType; + + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("考勤日期") + private LocalDate attendanceDate; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("打卡时间") + private LocalDateTime recordTime; + + @ApiModelProperty("打卡照片") + private String recordImage; + + @ApiModelProperty("打卡地点,经纬度") + private String recordPosition; + + @ApiModelProperty("打卡地点,中文描述") + private String recordPositionLabel; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/CheckSchemeListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/CheckSchemeListReq.java new file mode 100644 index 0000000..514f615 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/CheckSchemeListReq.java @@ -0,0 +1,27 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * @Author: gaoxiong + * @Date: 2025/7/9 23:35 + * @Description: + */ +@Data +@ApiModel("检查方案列表查询请求实体") +public class CheckSchemeListReq implements Serializable { + + @Serial + private static final long serialVersionUID = 1345082408495150993L; + + @ApiModelProperty("检查方式,枚举CheckMethodEnum") + private List checkMethod; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/CheckSchemeReq.java b/core/src/main/java/com/dite/znpt/domain/vo/CheckSchemeReq.java index 6935dbe..02c0ab2 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/CheckSchemeReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/CheckSchemeReq.java @@ -44,7 +44,6 @@ public class CheckSchemeReq implements Serializable { @ApiModelProperty("检查方式,枚举CheckMethodEnum") private String checkMethod; - @NotBlank(message = "备注不能为空") @Size(max = 500, message = "备注不能超过500个字") @ApiModelProperty("备注") private String remark; diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ContractImportReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ContractImportReq.java new file mode 100644 index 0000000..e24ee4f --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ContractImportReq.java @@ -0,0 +1,77 @@ +package com.dite.znpt.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.alibaba.excel.annotation.ExcelProperty; + +import com.dite.znpt.util.ValidationGroup; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +/** + * @author huise23 + * @date 2025/07/21 21:13 + * @Description: 合同表导入请求类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="Contract导入请求对象", description="合同表") +public class ContractImportReq implements Serializable { + + @Serial + private static final long serialVersionUID = 416194686656143643L; + + + @ExcelProperty(value = "客户名称") + private String customer; + + @ExcelProperty(value = "合同编号") + private String code; + + @ExcelProperty(value = "项目名称") + private String projectName; + + @ExcelProperty(value = "业务员名称") + private String salespersonName; + + @ExcelProperty(value = "部门名称") + private String departmentName; + + @ExcelProperty(value = "签订日期") + private Date signDate; + + @ExcelProperty(value = "期限") + private String duration; + + @ExcelProperty(value = "类型") + private String type; + + @ExcelProperty(value = "产品或服务") + private String productService; + + @ExcelProperty(value = "付款日期/交付日期") + private Date paymentDate; + + @ExcelProperty(value = "付款地址/交付地址") + private String paymentAddress; + + @ExcelProperty(value = "金额") + private BigDecimal amount; + + @ExcelProperty(value = "收款账号") + private String accountNumber; + + @ExcelProperty(value = "备注") + private String notes; + + @ExcelProperty(value = "合同状态") + private String contractStatus; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ContractListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ContractListReq.java new file mode 100644 index 0000000..9eb3e7a --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ContractListReq.java @@ -0,0 +1,76 @@ +package com.dite.znpt.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author huise23 + * @date 2025/07/21 21:13 + * @Description: 合同请求实体 + */ +@Data +@ApiModel("合同列表请求实体") +public class ContractListReq implements Serializable { + + @Serial + private static final long serialVersionUID = 188906332887614727L; + + @ApiModelProperty("查询关键字") + private String keyword; + + @ApiModelProperty("合同Id") + private String contractId; + + @ApiModelProperty("客户名称") + private String customer; + + @ApiModelProperty("合同编号") + private String code; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty("业务员id") + private String salespersonId; + + @ApiModelProperty("部门id") + private String departmentId; + + @ApiModelProperty("签订日期") + private Date signDate; + + @ApiModelProperty("期限") + private String duration; + + @ApiModelProperty("类型") + private String type; + + @ApiModelProperty("产品或服务") + private String productService; + + @ApiModelProperty("付款日期/交付日期") + private Date paymentDate; + + @ApiModelProperty("付款地址/交付地址") + private String paymentAddress; + + @ApiModelProperty("金额") + private BigDecimal amount; + + @ApiModelProperty("收款账号") + private String accountNumber; + + @ApiModelProperty("备注") + private String notes; + + @ApiModelProperty("合同状态") + private String contractStatus; + +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ContractReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ContractReq.java new file mode 100644 index 0000000..ace5f90 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ContractReq.java @@ -0,0 +1,80 @@ +package com.dite.znpt.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.alibaba.excel.annotation.ExcelProperty; + +import com.dite.znpt.util.ValidationGroup; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +/** + * @author huise23 + * @date 2025/07/21 21:13 + * @Description: 合同表请求类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="Contract请求对象", description="合同表") +public class ContractReq implements Serializable { + + @Serial + private static final long serialVersionUID = -42338861509205617L; + + @ApiModelProperty("合同id") + private String contractId; + + @ApiModelProperty("客户名称") + private String customer; + + @ApiModelProperty("合同编号") + private String code; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty("业务员id") + private String salespersonId; + + @ApiModelProperty("部门id") + private String departmentId; + + @ApiModelProperty("签订日期") + private Date signDate; + + @ApiModelProperty("期限") + private String duration; + + @ApiModelProperty("类型") + private String type; + + @ApiModelProperty("产品或服务") + private String productService; + + @ApiModelProperty("付款日期/交付日期") + private Date paymentDate; + + @ApiModelProperty("付款地址/交付地址") + private String paymentAddress; + + @ApiModelProperty("金额") + private BigDecimal amount; + + @ApiModelProperty("收款账号") + private String accountNumber; + + @ApiModelProperty("备注") + private String notes; + + @ApiModelProperty("合同状态") + private String contractStatus; +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ContractResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ContractResp.java new file mode 100644 index 0000000..f21e2ca --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ContractResp.java @@ -0,0 +1,39 @@ +package com.dite.znpt.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.dite.znpt.domain.entity.ContractEntity; + +/** + * @author huise23 + * @date 2025/07/21 20:29 + * @Description: 合同响应实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel("合同响应实体") +public class ContractResp extends ContractEntity { + + @ApiModelProperty("项目名称") + private String projectName; + + @ApiModelProperty("业务员姓名") + private String salespersonName; + + @ApiModelProperty("部门名称") + private String salespersonDeptName; + + @ApiModelProperty("已结算金额") + private BigDecimal settlementAmount; + + @ApiModelProperty("已收款金额") + private BigDecimal receivedAmount; +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementImportReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementImportReq.java new file mode 100644 index 0000000..6c51ead --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementImportReq.java @@ -0,0 +1,74 @@ +package com.dite.znpt.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.alibaba.excel.annotation.ExcelProperty; + +import com.dite.znpt.util.ValidationGroup; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +/** + * @author huise23 + * @date 2025/07/21 21:13 + * @Description: 合同结算表导入请求类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="ContractSettlement导入请求对象", description="合同结算表") +public class ContractSettlementImportReq implements Serializable { + + @Serial + private static final long serialVersionUID = 148613402074177824L; + + + @ExcelProperty(value = "合同名称(不能为空,长度32以内)") + private String contractName; + + @ExcelProperty(value = "客户/供应商名称") + private String customer; + + @ExcelProperty(value = "合同结算编号") + private String code; + + @ExcelProperty(value = "项目名称") + private String projectName; + + @ExcelProperty(value = "业务员名称") + private String salespersonName; + + @ExcelProperty(value = "部门名称") + private String departmentName; + + @ExcelProperty(value = "账期") + private Date paymentPeriod; + + @ExcelProperty(value = "日期") + private Date paymentDate; + + @ExcelProperty(value = "期限") + private String duration; + + @ExcelProperty(value = "产品或服务") + private String productService; + + @ExcelProperty(value = "金额") + private BigDecimal amount; + + @ExcelProperty(value = "收款账号") + private String accountNumber; + + @ExcelProperty(value = "备注") + private String notes; + + @ExcelProperty(value = "合同结算状态") + private String settlementStatus; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementListReq.java new file mode 100644 index 0000000..063b96d --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementListReq.java @@ -0,0 +1,73 @@ +package com.dite.znpt.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author huise23 + * @date 2025/07/21 21:13 + * @Description: 合同结算请求实体 + */ +@Data +@ApiModel("合同结算列表请求实体") +public class ContractSettlementListReq implements Serializable { + + @Serial + private static final long serialVersionUID = -36243842073737072L; + + @ApiModelProperty("查询关键字") + private String keyword; + + @ApiModelProperty("合同结算Id") + private String settlementId; + + @ApiModelProperty("合同id") + private String contractId; + + @ApiModelProperty("客户/供应商名称") + private String customer; + + @ApiModelProperty("合同结算编号") + private String code; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty("业务员id") + private String salespersonId; + + @ApiModelProperty("部门id") + private String departmentId; + + @ApiModelProperty("账期") + private Date paymentPeriod; + + @ApiModelProperty("日期") + private Date paymentDate; + + @ApiModelProperty("期限") + private String duration; + + @ApiModelProperty("产品或服务") + private String productService; + + @ApiModelProperty("金额") + private BigDecimal amount; + + @ApiModelProperty("收款账号") + private String accountNumber; + + @ApiModelProperty("备注") + private String notes; + + @ApiModelProperty("合同结算状态") + private String settlementStatus; + +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementReq.java new file mode 100644 index 0000000..440482a --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementReq.java @@ -0,0 +1,79 @@ +package com.dite.znpt.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.alibaba.excel.annotation.ExcelProperty; + +import com.dite.znpt.util.ValidationGroup; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +/** + * @author huise23 + * @date 2025/07/21 21:13 + * @Description: 合同结算表请求类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="ContractSettlement请求对象", description="合同结算表") +public class ContractSettlementReq implements Serializable { + + @Serial + private static final long serialVersionUID = -44768849127704946L; + + @ApiModelProperty("合同结算id") + private String settlementId; + + @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "合同id不能为空") + @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 32, message = "合同id长度不能超过32字符") + @ApiModelProperty("合同id") + private String contractId; + + @ApiModelProperty("客户/供应商名称") + private String customer; + + @ApiModelProperty("合同结算编号") + private String code; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty("业务员id") + private String salespersonId; + + @ApiModelProperty("部门id") + private String departmentId; + + @ApiModelProperty("账期") + private Date paymentPeriod; + + @ApiModelProperty("日期") + private Date paymentDate; + + @ApiModelProperty("期限") + private String duration; + + @ApiModelProperty("产品或服务") + private String productService; + + @ApiModelProperty("金额") + private BigDecimal amount; + + @ApiModelProperty("收款账号") + private String accountNumber; + + @ApiModelProperty("备注") + private String notes; + + @ApiModelProperty("合同结算状态") + private String settlementStatus; +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementResp.java new file mode 100644 index 0000000..fbd1f36 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ContractSettlementResp.java @@ -0,0 +1,20 @@ +package com.dite.znpt.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.dite.znpt.domain.entity.ContractSettlementEntity; + +/** + * @author huise23 + * @date 2025/07/21 21:10 + * @Description: 合同结算响应实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel("合同结算响应实体") +public class ContractSettlementResp extends ContractSettlementEntity { +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/DefectListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/DefectListReq.java index 87ef106..14299d6 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/DefectListReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/DefectListReq.java @@ -3,6 +3,7 @@ package com.dite.znpt.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.experimental.Accessors; import java.io.Serializable; @@ -12,6 +13,7 @@ import java.io.Serializable; * @Description: 缺陷记录请求实体 */ @Data +@Accessors(chain = true) @ApiModel("缺陷记录列表请求实体") public class DefectListReq implements Serializable { diff --git a/core/src/main/java/com/dite/znpt/domain/vo/DefectListResp.java b/core/src/main/java/com/dite/znpt/domain/vo/DefectListResp.java index 3dc0e60..f002788 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/DefectListResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/DefectListResp.java @@ -28,12 +28,27 @@ public class DefectListResp implements Serializable { @ApiModelProperty("部件名称") private String partName; - @ApiModelProperty("缺陷未知") + @ApiModelProperty("缺陷类型描述") + private String defectTypeLabel; + + @ApiModelProperty("缺陷类型,枚举DefectTypeEnum") + private String defectType; + + @ApiModelProperty("危重等级描述") + private String defectLevelLabel; + + @ApiModelProperty("危重等级,枚举DefectLevelEnum") + private String defectLevel; + + @ApiModelProperty("缺陷位置") private String defectPosition; @ApiModelProperty("说明") private String description; + @ApiModelProperty("维修建议") + private String repairIdea; + @ApiModelProperty("标注信息") private String labelInfo; diff --git a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportCheckInfo.java b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportCheckInfo.java index 57a255c..9c825b3 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportCheckInfo.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportCheckInfo.java @@ -24,15 +24,18 @@ public class InspectionReportCheckInfo implements Serializable { @ApiModelProperty("检查日期") private LocalDate checkDate; - @ApiModelProperty("检查位置") - private String checkPosition; - @ApiModelProperty("检查内容") private String checkContent; @ApiModelProperty("检查方式") private String checkMethod; + @ApiModelProperty("检查方式描述") + private String checkMethodLabel; + @ApiModelProperty("检查人员id,多个人员英文逗号分隔") private String checkUserId; + + @ApiModelProperty("检查人员") + private String checkUserName; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportListReq.java new file mode 100644 index 0000000..9daa4d3 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportListReq.java @@ -0,0 +1,40 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author Bear.G + * @date 2025/7/14/周一 15:32 + * @description + */ +@Data +@ApiModel("检查报告列表请求实体") +public class InspectionReportListReq implements Serializable { + @Serial + private static final long serialVersionUID = -8122588121700840604L; + + @ApiModelProperty("主标题") + private String title; + + @ApiModelProperty("副标题") + private String subTile; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty("机组id") + private String turbineId; + + @ApiModelProperty("风场名字") + private String farmName; + + @ApiModelProperty("委托单位") + private String client; + + +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportListResp.java b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportListResp.java new file mode 100644 index 0000000..a5c6e04 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportListResp.java @@ -0,0 +1,62 @@ +package com.dite.znpt.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author Bear.G + * @date 2025/7/14/周一 15:32 + * @description + */ +@Data +@ApiModel("检查报告列表响应实体") +public class InspectionReportListResp implements Serializable { + @Serial + private static final long serialVersionUID = -7652873535955803183L; + + @ApiModelProperty("报告id") + private String reportId; + + @ApiModelProperty("主标题") + private String title; + + @ApiModelProperty("副标题") + private String subTitle; + + @ApiModelProperty("报告编制人员id") + private String reportWriter; + + @ApiModelProperty("报告编制人员") + private String reportWriterName; + + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("报告编制时间") + private LocalDateTime reportWriteTime; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty("项目名称") + private String projectName; + + @ApiModelProperty("风场名字") + private String farmName; + + @ApiModelProperty("委托单位") + private String client; + + @ApiModelProperty("机组id") + private String turbineId; + + @ApiModelProperty("机组名称") + private String turbineName; + + @ApiModelProperty("机组编码") + private String turbineCode; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportCoverInfo.java b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportReportInfo.java similarity index 83% rename from core/src/main/java/com/dite/znpt/domain/vo/InspectionReportCoverInfo.java rename to core/src/main/java/com/dite/znpt/domain/vo/InspectionReportReportInfo.java index 19d51ec..fd12a76 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportCoverInfo.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportReportInfo.java @@ -1,6 +1,6 @@ package com.dite.znpt.domain.vo; -import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -15,8 +15,8 @@ import java.time.LocalDateTime; * @Description: */ @Data -@ApiModel("检查报告封面信息") -public class InspectionReportCoverInfo implements Serializable { +@ApiModel("检查报告信息") +public class InspectionReportReportInfo implements Serializable { @Serial private static final long serialVersionUID = 2416173276374292199L; @@ -38,6 +38,7 @@ public class InspectionReportCoverInfo implements Serializable { @ApiModelProperty("报告编制人员") private String reportWriterName; + @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("报告编制时间") private LocalDateTime reportWriteTime; @@ -47,6 +48,7 @@ public class InspectionReportCoverInfo implements Serializable { @ApiModelProperty("报告复核人员") private String reportReviewerName; + @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("报告复核时间") private LocalDateTime reportReviewTime; @@ -56,6 +58,8 @@ public class InspectionReportCoverInfo implements Serializable { @ApiModelProperty("报告审核人员") private String reportAuditName; + @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("报告审核时间") private LocalDateTime reportAuditTime; + } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportReq.java b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportReq.java index c679385..dd5ebe4 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportReq.java @@ -1,17 +1,16 @@ package com.dite.znpt.domain.vo; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import java.io.Serial; import java.io.Serializable; import java.time.LocalDate; -import java.time.LocalDateTime; /** * @Author: gaoxiong @@ -24,55 +23,68 @@ public class InspectionReportReq implements Serializable { @Serial private static final long serialVersionUID = 4937399975205847660L; - @ApiModelProperty("报告id") - private String reportId; - + @NotBlank(message = "主标题不能为空") + @Size(max = 50, message = "主标题长度不能超过50") @ApiModelProperty("主标题") private String title; + @NotBlank(message = "副标题不能为空") + @Size(max = 50, message = "副标题长度不能超过50") @ApiModelProperty("副标题") private String subTitle; @ApiModelProperty("封面") private String coverImage; + @NotBlank(message = "项目id不能为空") @ApiModelProperty("项目id") private String projectId; + @NotBlank(message = "机组id不能为空") @ApiModelProperty("机组id") private String turbineId; + @NotNull(message = "检查日期不能为空") @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("检查日期") private LocalDate checkDate; - @ApiModelProperty("检查位置") - private String checkPosition; - + @NotBlank(message = "检查内容不能为空") @ApiModelProperty("检查内容") private String checkContent; - @ApiModelProperty("检查方式,多个方式英文逗号分隔") + @NotBlank(message = "检查内容不能为空") + @ApiModelProperty("检查方式,多个方式英文逗号分隔,枚举:CheckMethodEnum") private String checkMethod; + @NotBlank(message = "检查人员不能为空") @ApiModelProperty("检查人员id,多个人员英文逗号分隔") private String checkUserId; + @NotBlank(message = "报告编制人员不能为空") @ApiModelProperty("报告编制人员id") private String reportWriter; + @JsonFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "报告编制时间不能为空") @ApiModelProperty("报告编制时间") - private LocalDateTime reportWriteTime; + private LocalDate reportWriteTime; + @NotBlank(message = "报告复核人员不能为空") @ApiModelProperty("报告复核人员id") private String reportReviewer; + @JsonFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "报告复核时间不能为空") @ApiModelProperty("报告复核时间") - private LocalDateTime reportReviewTime; + private LocalDate reportReviewTime; + @NotBlank(message = "报告审核人员不能为空") @ApiModelProperty("报告审核人员id") private String reportAuditor; + @JsonFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "报告审核时间不能为空") @ApiModelProperty("报告审核时间") - private LocalDateTime reportAuditTime; + private LocalDate reportAuditTime; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportResp.java b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportResp.java index 8d15c94..d307245 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/InspectionReportResp.java @@ -3,6 +3,7 @@ package com.dite.znpt.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.experimental.Accessors; import java.io.Serial; import java.io.Serializable; @@ -14,13 +15,14 @@ import java.util.List; * @Description: */ @Data +@Accessors(chain = true) @ApiModel("检查报告响应实体") public class InspectionReportResp implements Serializable { @Serial private static final long serialVersionUID = -2229157312487991799L; @ApiModelProperty("封面信息") - private InspectionReportCoverInfo coverInfo; + private InspectionReportReportInfo reportInfo; @ApiModelProperty("项目信息") private ProjectResp projectInfo; @@ -35,5 +37,5 @@ public class InspectionReportResp implements Serializable { private List schemeInfoList; @ApiModelProperty("缺陷信息") - private List defectInfoList; + private List defectInfoList; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/PartListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/PartListReq.java index fb5ccb0..e5b40ad 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/PartListReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/PartListReq.java @@ -5,6 +5,7 @@ import java.io.Serializable; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.experimental.Accessors; /** * @author huise23 @@ -12,6 +13,7 @@ import lombok.Data; * @Description: 请求实体 */ @Data +@Accessors(chain = true) @ApiModel("部件列表请求实体") public class PartListReq implements Serializable { diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoImportReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoImportReq.java new file mode 100644 index 0000000..18d93a7 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoImportReq.java @@ -0,0 +1,38 @@ +package com.dite.znpt.domain.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; +import java.io.Serializable; +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息表导入请求类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="ProjectBudgetInfo导入请求对象", description="项目预算信息表") +public class ProjectBudgetInfoImportReq implements Serializable { + + @Serial + private static final long serialVersionUID = 580212651388155611L; + + + @ExcelProperty(value = "项目名称") + private String projectName; + + @ExcelProperty(value = "预算名称") + private String budgetName; + + @ExcelProperty(value = "预算类型") + private String budgetType; + + @ExcelProperty(value = "预算金额(万元)") + private Double budgetAmount; + + @ExcelProperty(value = "预算说明") + private String budgetDesc; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoListReq.java new file mode 100644 index 0000000..047b5e9 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoListReq.java @@ -0,0 +1,44 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息请求实体 + */ +@Data +@ApiModel("项目预算信息列表请求实体") +public class ProjectBudgetInfoListReq implements Serializable { + + @Serial + private static final long serialVersionUID = 539751666379021505L; + + @ApiModelProperty("查询关键字") + private String keyword; + + @ApiModelProperty("项目预算信息Id") + private String budgetId; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty("预算名称") + private String budgetName; + + @ApiModelProperty("预算类型") + private String budgetType; + + @ApiModelProperty("预算金额(万元)") + private Double budgetAmount; + + @ApiModelProperty("预算说明") + private String budgetDesc; + +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoListResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoListResp.java new file mode 100644 index 0000000..af0e31b --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoListResp.java @@ -0,0 +1,19 @@ +package com.dite.znpt.domain.vo; + +import com.dite.znpt.domain.entity.ProjectBudgetInfoEntity; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息列表响应实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel("项目预算信息列表响应实体") +public class ProjectBudgetInfoListResp extends ProjectBudgetInfoEntity { + +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoReq.java new file mode 100644 index 0000000..60caa06 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoReq.java @@ -0,0 +1,41 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; +import java.io.Serializable; +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息表请求类 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="ProjectBudgetInfo请求对象", description="项目预算信息表") +public class ProjectBudgetInfoReq implements Serializable { + + @Serial + private static final long serialVersionUID = 778519049897573879L; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty("预算名称") + private String budgetName; + + @ApiModelProperty("预算类型") + private String budgetType; + + @ApiModelProperty("预算金额(万元)") + private Double budgetAmount; + + @ApiModelProperty("预算说明") + private String budgetDesc; + + @ApiModelProperty("附件id") + private String attachId; +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoResp.java new file mode 100644 index 0000000..70b2d3f --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoResp.java @@ -0,0 +1,22 @@ +package com.dite.znpt.domain.vo; + +import com.dite.znpt.domain.entity.ProjectBudgetInfoEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息响应实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel("项目预算信息响应实体") +public class ProjectBudgetInfoResp extends ProjectBudgetInfoEntity { + + @ApiModelProperty("预算类型描述") + private String budgetTypeDesc; +} + diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectListReq.java index 42f55e5..a285e33 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectListReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectListReq.java @@ -41,5 +41,8 @@ public class ProjectListReq implements Serializable { @ApiModelProperty("项目结束日期") private LocalDate endDate; + @ApiModelProperty(value = "用户id", hidden = true) + private String userId; + } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectListResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectListResp.java index 8947fcc..f0578ef 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectListResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectListResp.java @@ -90,4 +90,16 @@ public class ProjectListResp implements Serializable { @ApiModelProperty(value = "结束时间") private LocalDate endDate; + + @ApiModelProperty(value = "未开始任务数") + private Integer taskPendingCount; + + @ApiModelProperty(value = "进行中任务数") + private Integer taskProgressCount; + + @ApiModelProperty(value = "已完成任务数") + private Integer taskCompleteCount; + + @ApiModelProperty(value = "总任务数") + private Integer taskCount; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupListReq.java index 26d9076..c203b19 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupListReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupListReq.java @@ -29,5 +29,8 @@ public class ProjectTaskGroupListReq implements Serializable { @ApiModelProperty("任务名称/负责人") private String keyword; + @ApiModelProperty("项目id") + private String projectId; + } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupReq.java index 6d91415..c069967 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupReq.java @@ -11,6 +11,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; /** @@ -34,5 +35,9 @@ public class ProjectTaskGroupReq implements Serializable { @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 100, message = "项目任务组名长度不能超过100字符") @ApiModelProperty("项目任务组名") private String groupName; + + @NotNull(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目id不能为空") + @ApiModelProperty("项目id") + private String projectId; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupResp.java index 14027da..3c1242a 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskGroupResp.java @@ -21,5 +21,7 @@ public class ProjectTaskGroupResp extends ProjectTaskGroupEntity { @ApiModelProperty("任务列表") private List taskList; + @ApiModelProperty("项目名称") + private String projectName; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskImportReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskImportReq.java index bc56499..f647f34 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskImportReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskImportReq.java @@ -2,6 +2,7 @@ package com.dite.znpt.domain.vo; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -60,4 +61,7 @@ public class ProjectTaskImportReq implements Serializable { @ExcelProperty(value = "备注") private String remark; + + @ApiModelProperty("项目id") + private String projectId; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskListReq.java index ecca3b6..8e9ac9b 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskListReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskListReq.java @@ -65,5 +65,11 @@ public class ProjectTaskListReq implements Serializable { @ApiModelProperty(value = "导出?", hidden = true) private Boolean isExport; + + @ApiModelProperty("项目id") + private String projectId; + + @ApiModelProperty(value = "用户id", hidden = true) + private String userId; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskReq.java index 14d6b97..cf66cad 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskReq.java @@ -80,5 +80,9 @@ public class ProjectTaskReq implements Serializable { @ApiModelProperty("备注") private String remark; + + @NotNull(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目id不能为空") + @ApiModelProperty("项目id") + private String projectId; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskResp.java index 605b3c6..df9696a 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTaskResp.java @@ -23,5 +23,7 @@ public class ProjectTaskResp extends ProjectTaskEntity { @ApiModelProperty("附件列表") private List attachList; + @ApiModelProperty("项目名称") + private String projectName; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/TurbineResp.java b/core/src/main/java/com/dite/znpt/domain/vo/TurbineResp.java index beb18d9..7e60769 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/TurbineResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/TurbineResp.java @@ -18,7 +18,7 @@ public class TurbineResp implements Serializable { @Serial private static final long serialVersionUID = -1403719853347580858L; - @ApiModelProperty("机组号") + @ApiModelProperty("机组id") private String turbineId; @ApiModelProperty("项目id") diff --git a/core/src/main/java/com/dite/znpt/domain/vo/WorkbenchInfoResp.java b/core/src/main/java/com/dite/znpt/domain/vo/WorkbenchInfoResp.java new file mode 100644 index 0000000..197e778 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/WorkbenchInfoResp.java @@ -0,0 +1,28 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author huise23 + * @date 2025/04/11 23:17 + * @Description: 工作台信息响应实体 + */ +@Data +@ApiModel("工作台信息响应实体") +public class WorkbenchInfoResp { + + @ApiModelProperty("项目数量") + private long projectCount; + + @ApiModelProperty("进行中任务") + private long progressTaskCount; + + @ApiModelProperty("待审核报告数") + private long approvalReportCount; + + @ApiModelProperty("发现缺陷数") + private long findDefectCount; +} + diff --git a/core/src/main/java/com/dite/znpt/enums/AttachBusinessTypeEnum.java b/core/src/main/java/com/dite/znpt/enums/AttachBusinessTypeEnum.java index 096af63..4e008b3 100644 --- a/core/src/main/java/com/dite/znpt/enums/AttachBusinessTypeEnum.java +++ b/core/src/main/java/com/dite/znpt/enums/AttachBusinessTypeEnum.java @@ -17,6 +17,8 @@ public enum AttachBusinessTypeEnum { INSURANCE_FILE("insurance", "保险文件"), MODEL_FILE("model", "模型文件"), DEFECT_MARK_PIC("defect_mark_pic", "缺陷标注图片"), + REPORT("report", "报告"), + PROJECT_BUDGE("project_budge", "预算文件"), ; private final String code; private final String desc; diff --git a/core/src/main/java/com/dite/znpt/enums/BudgeTypeEnum.java b/core/src/main/java/com/dite/znpt/enums/BudgeTypeEnum.java new file mode 100644 index 0000000..8eeff96 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/enums/BudgeTypeEnum.java @@ -0,0 +1,52 @@ +package com.dite.znpt.enums; + +import cn.hutool.json.JSONObject; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author: gaoxiong + * @Date: 2025/5/7 21:22 + * @Description: + */ +@Getter +public enum BudgeTypeEnum { + PROCUREMENT("procurement", "采购"), + ARTIFICIAL("artificial", "人工"), + MANAGEMENT_FEE("managementFee", "管理费"), + ; + + private final String code; + private final String desc; + + BudgeTypeEnum(String code, String desc){ + this.code = code; + this.desc = desc; + } + + public static BudgeTypeEnum getByCode(String code){ + for (BudgeTypeEnum e : BudgeTypeEnum.values() ) { + if(e.code.equals(code)){ + return e; + } + } + return null; + } + + public static String getDescByCode(String code){ + BudgeTypeEnum e = getByCode(code); + return null == e ? null : e.desc; + } + + public static List listAll(){ + List list = new ArrayList<>(BudgeTypeEnum.values().length); + for (BudgeTypeEnum e : BudgeTypeEnum.values() ) { + JSONObject jsonObject = new JSONObject(); + jsonObject.set(e.code, e.desc); + list.add(jsonObject); + } + return list; + } +} diff --git a/core/src/main/java/com/dite/znpt/mapper/AttendanceRecordMapper.java b/core/src/main/java/com/dite/znpt/mapper/AttendanceRecordMapper.java new file mode 100644 index 0000000..30a0de8 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/mapper/AttendanceRecordMapper.java @@ -0,0 +1,12 @@ +package com.dite.znpt.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dite.znpt.domain.entity.AttendanceRecordEntity; + +/** + * @Author: gaoxiong + * @Date: 2025/7/21 21:19 + * @Description: + */ +public interface AttendanceRecordMapper extends BaseMapper { +} diff --git a/core/src/main/java/com/dite/znpt/mapper/ContractMapper.java b/core/src/main/java/com/dite/znpt/mapper/ContractMapper.java new file mode 100644 index 0000000..dd7e123 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/mapper/ContractMapper.java @@ -0,0 +1,19 @@ +package com.dite.znpt.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dite.znpt.domain.entity.ContractEntity; +import com.dite.znpt.domain.vo.ContractListReq; +import com.dite.znpt.domain.vo.ContractResp; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/21 20:29 + * @Description: 合同表数据库访问层 + */ +public interface ContractMapper extends BaseMapper { + List queryBySelective(ContractListReq contractReq); +} + diff --git a/core/src/main/java/com/dite/znpt/mapper/ContractSettlementMapper.java b/core/src/main/java/com/dite/znpt/mapper/ContractSettlementMapper.java new file mode 100644 index 0000000..d114d52 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/mapper/ContractSettlementMapper.java @@ -0,0 +1,19 @@ +package com.dite.znpt.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dite.znpt.domain.entity.ContractSettlementEntity; +import com.dite.znpt.domain.vo.ContractSettlementListReq; +import com.dite.znpt.domain.vo.ContractSettlementResp; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/21 21:10 + * @Description: 合同结算表数据库访问层 + */ +public interface ContractSettlementMapper extends BaseMapper { + List queryBySelective(ContractSettlementListReq contractSettlementReq); +} + diff --git a/core/src/main/java/com/dite/znpt/mapper/FlowDeployMapper.java b/core/src/main/java/com/dite/znpt/mapper/FlowDeployMapper.java new file mode 100644 index 0000000..02976ca --- /dev/null +++ b/core/src/main/java/com/dite/znpt/mapper/FlowDeployMapper.java @@ -0,0 +1,23 @@ +package com.dite.znpt.mapper; + + +import com.dite.znpt.domain.dto.FlowProcDefDto; + +import java.util.List; + +/** + * 流程定义查询 + * + * @author Tony + * @email + * @date 2022/1/29 5:44 下午 + **/ +public interface FlowDeployMapper { + + /** + * 流程定义列表 + * @param name + * @return + */ + List selectDeployList(String name); +} diff --git a/core/src/main/java/com/dite/znpt/mapper/InspectionReportMapper.java b/core/src/main/java/com/dite/znpt/mapper/InspectionReportMapper.java index f9a62ab..8a42c64 100644 --- a/core/src/main/java/com/dite/znpt/mapper/InspectionReportMapper.java +++ b/core/src/main/java/com/dite/znpt/mapper/InspectionReportMapper.java @@ -2,6 +2,12 @@ package com.dite.znpt.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dite.znpt.domain.entity.InspectionReportEntity; +import com.dite.znpt.domain.vo.InspectionReportListReq; +import com.dite.znpt.domain.vo.InspectionReportListResp; +import com.dite.znpt.domain.vo.InspectionReportResp; +import org.apache.ibatis.annotations.Param; + +import java.util.List; /** * @author Bear.G @@ -9,4 +15,7 @@ import com.dite.znpt.domain.entity.InspectionReportEntity; * @description */ public interface InspectionReportMapper extends BaseMapper { + + List listInspectionReportListResp(@Param("req") InspectionReportListReq req); + InspectionReportResp getInspectionReportResp(@Param("reportId") String reportId); } diff --git a/core/src/main/java/com/dite/znpt/mapper/ProjectBudgetInfoMapper.java b/core/src/main/java/com/dite/znpt/mapper/ProjectBudgetInfoMapper.java new file mode 100644 index 0000000..2dcb73d --- /dev/null +++ b/core/src/main/java/com/dite/znpt/mapper/ProjectBudgetInfoMapper.java @@ -0,0 +1,20 @@ +package com.dite.znpt.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dite.znpt.domain.entity.ProjectBudgetInfoEntity; +import com.dite.znpt.domain.vo.ProjectBudgetInfoListReq; +import com.dite.znpt.domain.vo.ProjectBudgetInfoListResp; +import com.dite.znpt.domain.vo.ProjectBudgetInfoResp; + +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息表数据库访问层 + */ +public interface ProjectBudgetInfoMapper extends BaseMapper { + List queryBySelective(ProjectBudgetInfoListReq projectBudgetInfoReq); + List detailByProjectId(String projectId); +} + diff --git a/core/src/main/java/com/dite/znpt/service/AttendanceRecordService.java b/core/src/main/java/com/dite/znpt/service/AttendanceRecordService.java new file mode 100644 index 0000000..99bb6eb --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/AttendanceRecordService.java @@ -0,0 +1,23 @@ +package com.dite.znpt.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.dite.znpt.domain.entity.AttendanceRecordEntity; +import com.dite.znpt.domain.vo.AttendanceRecordReq; +import com.dite.znpt.domain.vo.AttendanceRecordResp; +import io.swagger.models.auth.In; + +import java.util.List; + +/** + * @Author: gaoxiong + * @Date: 2025/7/21 21:20 + * @Description: + */ +public interface AttendanceRecordService extends IService { + + void save(AttendanceRecordReq req); + + List listToday(String userId); + + List listMonth(String userId, Integer year, Integer month); +} diff --git a/core/src/main/java/com/dite/znpt/service/CheckSchemeService.java b/core/src/main/java/com/dite/znpt/service/CheckSchemeService.java index 78e7e6f..06274c0 100644 --- a/core/src/main/java/com/dite/znpt/service/CheckSchemeService.java +++ b/core/src/main/java/com/dite/znpt/service/CheckSchemeService.java @@ -13,8 +13,8 @@ import java.util.List; * @Description: */ public interface CheckSchemeService extends IService { - List page(String checkMethod); - List list(String checkMethod); + List page(List checkMethods); + List list(List checkMethods); CheckSchemeResp detail(String checkSchemeId); void save(CheckSchemeReq req); void update(String checkSchemeId, CheckSchemeReq req); diff --git a/core/src/main/java/com/dite/znpt/service/ContractService.java b/core/src/main/java/com/dite/znpt/service/ContractService.java new file mode 100644 index 0000000..25c5464 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/ContractService.java @@ -0,0 +1,65 @@ +package com.dite.znpt.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.dite.znpt.domain.entity.ContractEntity; +import com.dite.znpt.domain.vo.ContractListReq; +import com.dite.znpt.domain.vo.ContractResp; +import com.dite.znpt.domain.vo.ContractReq; + +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/21 20:29 + * @Description: 合同表服务接口 + */ +public interface ContractService extends IService { + + /** + * 功能描述:查询合同列表 + * + * @param contractReq 合同 + * @return {@link List }<{@link ContractResp }> + * @author huise23 + * @date 2025/07/21 20:29 + **/ + List selectList(ContractListReq contractReq); + + /** + * 功能描述:查询单条合同 + * + * @param contractId 合同Id + * @return {@link ContractResp } + * @author huise23 + * @date 2025/07/21 20:29 + **/ + ContractResp selectById(String contractId); + + /** + * 功能描述:新增合同 + * + * @param contractReq 合同 + * @author huise23 + * @date 2025/07/21 20:29 + **/ + void saveData(ContractReq contractReq); + + /** + * 功能描述:更新合同 + * + * @param contractReq 合同 + * @author huise23 + * @date 2025/07/21 20:29 + **/ + void updateData(ContractReq contractReq); + + /** + * 功能描述:删除合同 + * + * @param contractId 合同Id + * @author huise23 + * @date 2025/07/21 20:29 + **/ + void deleteById(String contractId); +} + diff --git a/core/src/main/java/com/dite/znpt/service/ContractSettlementService.java b/core/src/main/java/com/dite/znpt/service/ContractSettlementService.java new file mode 100644 index 0000000..80fd55c --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/ContractSettlementService.java @@ -0,0 +1,47 @@ +package com.dite.znpt.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.dite.znpt.domain.entity.ContractSettlementEntity; +import com.dite.znpt.domain.vo.ContractSettlementListReq; +import com.dite.znpt.domain.vo.ContractSettlementResp; +import com.dite.znpt.domain.vo.ContractSettlementReq; + +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/21 21:10 + * @Description: 合同结算表服务接口 + */ +public interface ContractSettlementService extends IService { + + /** + * 功能描述:查询合同结算列表 + * + * @param contractSettlementReq 合同结算 + * @return {@link List }<{@link ContractSettlementResp }> + * @author huise23 + * @date 2025/07/21 21:10 + **/ + List selectList(ContractSettlementListReq contractSettlementReq); + + /** + * 功能描述:查询单条合同结算 + * + * @param settlementId 合同结算Id + * @return {@link ContractSettlementResp } + * @author huise23 + * @date 2025/07/21 21:10 + **/ + ContractSettlementResp selectById(String settlementId); + + /** + * 功能描述:新增合同结算 + * + * @param contractSettlementReq 合同结算 + * @author huise23 + * @date 2025/07/21 21:10 + **/ + void saveData(ContractSettlementReq contractSettlementReq); +} + diff --git a/core/src/main/java/com/dite/znpt/service/InspectionReportService.java b/core/src/main/java/com/dite/znpt/service/InspectionReportService.java index 6723e3a..df8db79 100644 --- a/core/src/main/java/com/dite/znpt/service/InspectionReportService.java +++ b/core/src/main/java/com/dite/znpt/service/InspectionReportService.java @@ -2,6 +2,12 @@ package com.dite.znpt.service; import com.baomidou.mybatisplus.extension.service.IService; import com.dite.znpt.domain.entity.InspectionReportEntity; +import com.dite.znpt.domain.vo.InspectionReportListReq; +import com.dite.znpt.domain.vo.InspectionReportListResp; +import com.dite.znpt.domain.vo.InspectionReportReq; +import com.dite.znpt.domain.vo.InspectionReportResp; + +import java.util.List; /** * @author Bear.G @@ -9,4 +15,9 @@ import com.dite.znpt.domain.entity.InspectionReportEntity; * @description */ public interface InspectionReportService extends IService { + List page(InspectionReportListReq req); + List list(InspectionReportListReq req); + InspectionReportResp detail(String reportId); + void save(InspectionReportReq req); + void update(String reportId, InspectionReportReq req); } diff --git a/core/src/main/java/com/dite/znpt/service/ProjectBudgetInfoService.java b/core/src/main/java/com/dite/znpt/service/ProjectBudgetInfoService.java new file mode 100644 index 0000000..72aa0f0 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/ProjectBudgetInfoService.java @@ -0,0 +1,48 @@ +package com.dite.znpt.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.dite.znpt.domain.entity.ProjectBudgetInfoEntity; +import com.dite.znpt.domain.vo.ProjectBudgetInfoListReq; +import com.dite.znpt.domain.vo.ProjectBudgetInfoListResp; +import com.dite.znpt.domain.vo.ProjectBudgetInfoReq; +import com.dite.znpt.domain.vo.ProjectBudgetInfoResp; + +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息表服务接口 + */ +public interface ProjectBudgetInfoService extends IService { + + /** + * 功能描述:查询项目预算信息列表 + * + * @param projectBudgetInfoReq 项目预算信息 + * @return {@link List }<{@link ProjectBudgetInfoListResp }> + * @author huise23 + * @date 2025/07/17 21:58 + **/ + List selectList(ProjectBudgetInfoListReq projectBudgetInfoReq); + + /** + * 功能描述:根据项目id获取项目预算信息列表 + * + * @param projectId 项目id + * @return {@link List }<{@link ProjectBudgetInfoListResp }> + * @author huise23 + * @date 2025/07/17 21:58 + **/ + List detailByProjectId(String projectId); + + /** + * 功能描述:新增项目预算信息 + * + * @param projectBudgetInfoReq 项目预算信息 + * @author huise23 + * @date 2025/07/17 21:58 + **/ + void saveData(List projectBudgetInfoReq); +} + diff --git a/core/src/main/java/com/dite/znpt/service/WorkbenchService.java b/core/src/main/java/com/dite/znpt/service/WorkbenchService.java new file mode 100644 index 0000000..8426f83 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/WorkbenchService.java @@ -0,0 +1,15 @@ +package com.dite.znpt.service; + +import com.dite.znpt.domain.vo.WorkbenchInfoResp; + +public interface WorkbenchService { + + /** + * 功能描述:获取工作台信息 + * + * @return {@link WorkbenchInfoResp } + * @author cuizhibin + * @date 2025/07/21 21:27 + **/ + WorkbenchInfoResp getInfo(); +} diff --git a/core/src/main/java/com/dite/znpt/service/impl/AttendanceRecordServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/AttendanceRecordServiceImpl.java new file mode 100644 index 0000000..9d9cc8f --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/impl/AttendanceRecordServiceImpl.java @@ -0,0 +1,93 @@ +package com.dite.znpt.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.dite.znpt.constant.Constants; +import com.dite.znpt.constant.Message; +import com.dite.znpt.converts.Converts; +import com.dite.znpt.domain.entity.AttendanceRecordEntity; +import com.dite.znpt.domain.entity.UserEntity; +import com.dite.znpt.domain.vo.AttendanceRecordReq; +import com.dite.znpt.domain.vo.AttendanceRecordResp; +import com.dite.znpt.exception.ServiceException; +import com.dite.znpt.mapper.AttendanceRecordMapper; +import com.dite.znpt.service.AttendanceRecordService; +import com.dite.znpt.service.UserService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @Author: gaoxiong + * @Date: 2025/7/21 21:20 + * @Description: + */ +@Service +public class AttendanceRecordServiceImpl extends ServiceImpl implements AttendanceRecordService { + + @Resource + private UserService userService; + @Transactional(rollbackFor = Exception.class) + @Override + public void save(AttendanceRecordReq req) { + AttendanceRecordEntity entity = Converts.INSTANCE.toAttendanceRecordEntity(req); + entity.setUserId(StpUtil.getLoginId().toString()); + List list = this.list(Wrappers.lambdaQuery() + .eq(AttendanceRecordEntity::getUserId, entity.getUserId()) + .eq(AttendanceRecordEntity::getAttendanceDate, LocalDate.now()) + .orderByAsc(AttendanceRecordEntity::getCreateTime) + ); + if(list.isEmpty()){ + entity.setRecordType("0"); + }else { + entity.setRecordType("1"); + List invalidRecordList = list.stream().filter(record -> "1".equals(record.getRecordType())).collect(Collectors.toList()); + invalidRecordList.forEach(record -> { + record.setRecordType("2"); + }); + this.updateBatchById(invalidRecordList); + } + this.save(entity); + } + + @Override + public List listToday(String userId) { + List list = Converts.INSTANCE.toAttendanceRecordResp( + this.list(Wrappers.lambdaQuery() + .eq(AttendanceRecordEntity::getUserId, userId) + .eq(AttendanceRecordEntity::getAttendanceDate, LocalDate.now()) + .orderByAsc(AttendanceRecordEntity::getCreateTime) + ) + ); + UserEntity user = userService.getById(userId); + list.forEach(resp -> { + resp.setName(user.getName()); + }); + return list; + } + + @Override + public List listMonth(String userId, Integer year, Integer month) { + LocalDate beginDate = LocalDate.of(year, month, 1); + LocalDate endDate = beginDate.plusMonths(1L); + List list = Converts.INSTANCE.toAttendanceRecordResp( + this.list(Wrappers.lambdaQuery() + .eq(AttendanceRecordEntity::getUserId, userId) + .ge(AttendanceRecordEntity::getAttendanceDate, beginDate) + .lt(AttendanceRecordEntity::getAttendanceDate, endDate) + .orderByAsc(AttendanceRecordEntity::getCreateTime) + ) + ); + UserEntity user = userService.getById(userId); + list.forEach(resp -> { + resp.setName(user.getName()); + }); + return list; + } +} diff --git a/core/src/main/java/com/dite/znpt/service/impl/CheckSchemeServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/CheckSchemeServiceImpl.java index 7c0535b..6d5829c 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/CheckSchemeServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/CheckSchemeServiceImpl.java @@ -28,14 +28,16 @@ import java.util.List; public class CheckSchemeServiceImpl extends ServiceImpl implements CheckSchemeService { @Override - public List page(String checkMethod) { + public List page(List checkMethods) { PageUtil.startPage(); - return this.list(checkMethod); + return this.list(checkMethods); } @Override - public List list(String checkMethod) { - List result = Converts.INSTANCE.toCheckSchemeResp(this.list(Wrappers.lambdaQuery(CheckSchemeEntity.class).eq(StrUtil.isNotBlank(checkMethod), CheckSchemeEntity::getCheckMethod, checkMethod))); + public List list(List checkMethods) { + List result = Converts.INSTANCE.toCheckSchemeResp( + this.list(Wrappers.lambdaQuery(CheckSchemeEntity.class).in(null != checkMethods && !checkMethods.isEmpty(), CheckSchemeEntity::getCheckMethod, checkMethods)) + ); result.forEach(resp -> { resp.setCheckMethodLabel(CheckMethodEnum.getDescByCode(resp.getCheckMethod())); }); diff --git a/core/src/main/java/com/dite/znpt/service/impl/ContractServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ContractServiceImpl.java new file mode 100644 index 0000000..2f830c9 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/impl/ContractServiceImpl.java @@ -0,0 +1,103 @@ +package com.dite.znpt.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.dite.znpt.domain.entity.ContractEntity; +import com.dite.znpt.domain.vo.ContractListReq; +import com.dite.znpt.domain.vo.ContractResp; +import com.dite.znpt.domain.vo.ContractReq; +import com.dite.znpt.service.ContractService; +import com.dite.znpt.mapper.ContractMapper; +import org.springframework.stereotype.Service; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import com.dite.znpt.util.PageUtil; + +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/21 20:29 + * @Description: 合同表服务实现类 + */ +@Service +@RequiredArgsConstructor +public class ContractServiceImpl extends ServiceImpl implements ContractService { + + /** + * 功能描述:查询合同列表 + * + * @param contractReq 合同信息 + * @return {@link List }<{@link ContractResp }> + * @author huise23 + * @date 2025/07/21 20:29 + **/ + @Override + public List selectList(ContractListReq contractReq) { + PageUtil.startPage(); + List contractList= this.baseMapper.queryBySelective(contractReq); + contractList.forEach(resp -> { + + }); + return contractList; + } + + /** + * 功能描述:查询单条合同 + * + * @param contractId 合同Id + * @return {@link ContractResp } + * @author huise23 + * @date 2025/07/21 20:29 + **/ + @Override + public ContractResp selectById(String contractId) { + ContractListReq contractReq = new ContractListReq(); + contractReq.setContractId(contractId); + + List list = selectList(contractReq); + return CollUtil.isNotEmpty(list) ? CollUtil.getFirst(list) : new ContractResp(); + } + + /** + * 功能描述:新增合同 + * + * @param contractReq 合同 + * @author huise23 + * @date 2025/07/21 20:29 + **/ + @Override + public void saveData(ContractReq contractReq) { +// todo 校验 + ContractEntity entity = BeanUtil.copyProperties(contractReq, ContractEntity.class); + save(entity); + } + + /** + * 功能描述:更新合同 + * + * @param contractReq 合同 + * @author huise23 + * @date 2025/07/21 20:29 + **/ + @Override + public void updateData(ContractReq contractReq) { +// todo 校验 + ContractEntity entity = BeanUtil.copyProperties(contractReq, ContractEntity.class); + updateById(entity); + } + + /** + * 功能描述:删除合同 + * + * @param contractId 合同Id + * @author huise23 + * @date 2025/07/21 20:29 + **/ + @Override + public void deleteById(String contractId) { +// todo 校验 + removeById(contractId); + } + +} diff --git a/core/src/main/java/com/dite/znpt/service/impl/ContractSettlementServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ContractSettlementServiceImpl.java new file mode 100644 index 0000000..6d44287 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/impl/ContractSettlementServiceImpl.java @@ -0,0 +1,76 @@ +package com.dite.znpt.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.dite.znpt.domain.entity.ContractSettlementEntity; +import com.dite.znpt.domain.vo.ContractSettlementListReq; +import com.dite.znpt.domain.vo.ContractSettlementResp; +import com.dite.znpt.domain.vo.ContractSettlementReq; +import com.dite.znpt.service.ContractSettlementService; +import com.dite.znpt.mapper.ContractSettlementMapper; +import org.springframework.stereotype.Service; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import com.dite.znpt.util.PageUtil; + +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/21 21:10 + * @Description: 合同结算表服务实现类 + */ +@Service +@RequiredArgsConstructor +public class ContractSettlementServiceImpl extends ServiceImpl implements ContractSettlementService { + + /** + * 功能描述:查询合同结算列表 + * + * @param contractSettlementReq 合同结算信息 + * @return {@link List }<{@link ContractSettlementResp }> + * @author huise23 + * @date 2025/07/21 21:10 + **/ + @Override + public List selectList(ContractSettlementListReq contractSettlementReq) { + PageUtil.startPage(); + List contractSettlementList= this.baseMapper.queryBySelective(contractSettlementReq); + contractSettlementList.forEach(resp -> { + + }); + return contractSettlementList; + } + + /** + * 功能描述:查询单条合同结算 + * + * @param settlementId 合同结算Id + * @return {@link ContractSettlementResp } + * @author huise23 + * @date 2025/07/21 21:10 + **/ + @Override + public ContractSettlementResp selectById(String settlementId) { + ContractSettlementListReq contractSettlementReq = new ContractSettlementListReq(); + contractSettlementReq.setSettlementId(settlementId); + + List list = selectList(contractSettlementReq); + return CollUtil.isNotEmpty(list) ? CollUtil.getFirst(list) : new ContractSettlementResp(); + } + + /** + * 功能描述:新增合同结算 + * + * @param contractSettlementReq 合同结算 + * @author huise23 + * @date 2025/07/21 21:10 + **/ + @Override + public void saveData(ContractSettlementReq contractSettlementReq) { +// todo 校验 + ContractSettlementEntity entity = BeanUtil.copyProperties(contractSettlementReq, ContractSettlementEntity.class); + save(entity); + } + +} diff --git a/core/src/main/java/com/dite/znpt/service/impl/DefectServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/DefectServiceImpl.java index a68dbd6..91dfc47 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/DefectServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/DefectServiceImpl.java @@ -71,6 +71,8 @@ public class DefectServiceImpl extends ServiceImpl i public List list(DefectListReq req) { List defectList= this.baseMapper.queryBySelective(req); defectList.forEach(defect -> { + defect.setDefectTypeLabel(DefectTypeEnum.getDescByCode(defect.getDefectType())); + defect.setDefectLevelLabel(DefectLevelEnum.getDescByCode(defect.getDefectLevel())); defect.setMarkInfo(JSONUtil.toBean(defect.getLabelInfo(), Detection.class)); }); return defectList; diff --git a/core/src/main/java/com/dite/znpt/service/impl/ImageServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ImageServiceImpl.java index ccb6c56..72fe852 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/ImageServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/ImageServiceImpl.java @@ -161,6 +161,7 @@ public class ImageServiceImpl extends ServiceImpl impl String path = temPathPrefix + file.getOriginalFilename(); FileUtil.writeBytes(file.getBytes(),path); ImageReq imageReq = imageRespBuilder(path); + imageReq.setImageId(IdUtil.simpleUUID()); BeanUtil.copyProperties(imageReq, imageEntity); list.add(imageReq); imageEntity.setImagePath(FilePathEnum.IMAGE_TEMP.getFileDownPath(path)); diff --git a/core/src/main/java/com/dite/znpt/service/impl/InspectionReportServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/InspectionReportServiceImpl.java index b2d352a..4586040 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/InspectionReportServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/InspectionReportServiceImpl.java @@ -1,12 +1,25 @@ package com.dite.znpt.service.impl; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.dite.znpt.domain.entity.InspectionReportEntity; +import com.dite.znpt.constant.Message; +import com.dite.znpt.converts.Converts; +import com.dite.znpt.domain.entity.*; +import com.dite.znpt.domain.vo.*; +import com.dite.znpt.enums.CheckMethodEnum; +import com.dite.znpt.enums.ProjectStatusEnum; +import com.dite.znpt.exception.ServiceException; import com.dite.znpt.mapper.InspectionReportMapper; +import com.dite.znpt.service.*; +import com.dite.znpt.util.PageUtil; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -import java.io.Serial; -import java.io.Serializable; +import javax.annotation.Resource; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; /** * @author Bear.G @@ -14,7 +27,112 @@ import java.io.Serializable; * @description */ @Service -public class InspectionReportServiceImpl extends ServiceImpl implements Serializable { - @Serial - private static final long serialVersionUID = 1460849450000057636L; +public class InspectionReportServiceImpl extends ServiceImpl implements InspectionReportService { + + @Resource + private ProjectService projectService; + + @Resource + private TurbineService turbineService; + + @Resource + private DefectService defectService; + + @Resource + private CheckSchemeService checkSchemeService; + + + @Resource + private UserService userService; + + @Override + public List page(InspectionReportListReq req) { + PageUtil.startPage(); + return this.list(req); + } + + @Override + public List list(InspectionReportListReq req) { + return this.baseMapper.listInspectionReportListResp(req); + } + + @Override + public InspectionReportResp detail(String reportId) { + InspectionReportEntity inspectionReport = this.getById(reportId); + if(null == inspectionReport){ + throw new ServiceException(Message.INSPECTION_REPORT_ID_IS_NOT_EXIST); + } + InspectionReportResp result = new InspectionReportResp(); + List userIds = new ArrayList<>(); + InspectionReportReportInfo reportInfo = Converts.INSTANCE.toInspectionReportReportInfo(inspectionReport); + userIds.add(reportInfo.getReportAuditor()); + userIds.add(reportInfo.getReportWriter()); + userIds.add(reportInfo.getReportReviewer()); + ProjectResp projectInfo = projectService.detail(inspectionReport.getProjectId()); + result.setProjectInfo(projectInfo); + TurbineInfoResp turbineInfo = turbineService.info(inspectionReport.getTurbineId()); + result.setTurbineInfo(turbineInfo); + List schemeInfoList = checkSchemeService.list(List.of(inspectionReport.getCheckMethod().split(StrUtil.COMMA))); + result.setSchemeInfoList(schemeInfoList); + InspectionReportCheckInfo checkInfo = Converts.INSTANCE.toInspectionReportCheckInfo(inspectionReport); + userIds.addAll(List.of(checkInfo.getCheckUserId().split(StrUtil.COMMA))); + Map userIdMap = userService.listByIds(userIds).stream().collect(Collectors.toMap(UserEntity::getUserId, Function.identity())); + if(userIdMap.containsKey(reportInfo.getReportAuditor())){ + reportInfo.setReportAuditName(userIdMap.get(reportInfo.getReportAuditor()).getName()); + } + if(userIdMap.containsKey(reportInfo.getReportWriter())){ + reportInfo.setReportWriterName(userIdMap.get(reportInfo.getReportWriter()).getName()); + } + if(userIdMap.containsKey(reportInfo.getReportReviewer())){ + reportInfo.setReportReviewerName(userIdMap.get(reportInfo.getReportReviewer()).getName()); + } + result.setReportInfo(reportInfo); + StringBuilder checkUserName = new StringBuilder(); + Arrays.stream(checkInfo.getCheckUserId().split(StrUtil.COMMA)).forEach(userId ->{ + if(userIdMap.containsKey(userId)){ + checkUserName.append(userIdMap.get(userId).getUserId()).append(StrUtil.COMMA); + } + }); + checkInfo.setCheckUserName(checkUserName.toString()); + checkInfo.setCheckMethodLabel(CheckMethodEnum.getDescByCode(checkInfo.getCheckMethod())); + result.setCheckInfo(checkInfo); + List defectInfoList = defectService.list(new DefectListReq().setTurbineId(inspectionReport.getTurbineId())); + result.setDefectInfoList(defectInfoList); + return result; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void save(InspectionReportReq req) { + this.save(validation(req)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(String reportId, InspectionReportReq req) { + if(this.getById(reportId) == null){ + throw new ServiceException(Message.INSPECTION_REPORT_ID_IS_NOT_EXIST); + } + InspectionReportEntity entity = validation(req); + entity.setReportId(reportId); + this.updateById(entity); + } + + private InspectionReportEntity validation(InspectionReportReq req){ + ProjectEntity project = projectService.getById(req.getProjectId()); + if(null == project){ + throw new ServiceException(Message.PROJECT_ID_IS_NOT_EXIST); + } + if(ProjectStatusEnum.COMPLETED.getCode() != project.getStatus()){ + throw new ServiceException(StrUtil.format(Message.PROJECT_STATUS_IS_NOT_COMPLETED, project.getProjectName())); + } + TurbineEntity turbine = turbineService.getById(req.getTurbineId()); + if(null == turbine){ + throw new ServiceException(Message.TURBINE_ID_IS_NOT_EXIST); + } + if(ProjectStatusEnum.COMPLETED.getCode() != turbine.getStatus()){ + throw new ServiceException(StrUtil.format(Message.TURBINE_STATUS_IS_NOT_COMPLETED, turbine.getTurbineName())); + } + return Converts.INSTANCE.toInspectionReportEntity(req); + } } diff --git a/core/src/main/java/com/dite/znpt/service/impl/ProjectBudgetInfoServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ProjectBudgetInfoServiceImpl.java new file mode 100644 index 0000000..5380782 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/impl/ProjectBudgetInfoServiceImpl.java @@ -0,0 +1,92 @@ +package com.dite.znpt.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.IdUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.dite.znpt.domain.entity.ProjectBudgetInfoEntity; +import com.dite.znpt.domain.vo.ProjectBudgetInfoListReq; +import com.dite.znpt.domain.vo.ProjectBudgetInfoListResp; +import com.dite.znpt.domain.vo.ProjectBudgetInfoReq; +import com.dite.znpt.domain.vo.ProjectBudgetInfoResp; +import com.dite.znpt.enums.AttachBusinessTypeEnum; +import com.dite.znpt.enums.BudgeTypeEnum; +import com.dite.znpt.mapper.ProjectBudgetInfoMapper; +import com.dite.znpt.service.AttachInfoService; +import com.dite.znpt.service.ProjectBudgetInfoService; +import com.dite.znpt.util.PageUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/17 21:58 + * @Description: 项目预算信息表服务实现类 + */ +@Service +@RequiredArgsConstructor +public class ProjectBudgetInfoServiceImpl extends ServiceImpl implements ProjectBudgetInfoService { + + private final AttachInfoService attachInfoService; + + /** + * 功能描述:查询项目预算信息列表 + * + * @param projectBudgetInfoReq 项目预算信息信息 + * @return {@link List }<{@link ProjectBudgetInfoResp }> + * @author huise23 + * @date 2025/07/17 21:58 + **/ + @Override + public List selectList(ProjectBudgetInfoListReq projectBudgetInfoReq) { + PageUtil.startPage(); + List projectBudgetInfoList= this.baseMapper.queryBySelective(projectBudgetInfoReq); + projectBudgetInfoList.forEach(resp -> { + + }); + return projectBudgetInfoList; + } + + /** + * 功能描述:根据项目id获取项目预算信息列表 + * + * @param projectId 项目id + * @return {@link List }<{@link ProjectBudgetInfoListResp }> + * @author huise23 + * @date 2025/07/17 21:58 + **/ + @Override + public List detailByProjectId(String projectId) { + List projectBudgetInfoList= this.baseMapper.detailByProjectId(projectId); + projectBudgetInfoList.forEach(resp -> { + resp.setBudgetTypeDesc(BudgeTypeEnum.getDescByCode(resp.getBudgetType())); + }); + return projectBudgetInfoList; + } + + /** + * 功能描述:新增项目预算信息 + * + * @param projectBudgetInfoReq 项目预算信息 + * @author huise23 + * @date 2025/07/17 21:58 + **/ + @Override + @Transactional(rollbackFor = Exception.class) + public void saveData(List projectBudgetInfoReq) { + List list = new ArrayList<>(); + for (ProjectBudgetInfoReq req : projectBudgetInfoReq) { + ProjectBudgetInfoEntity info = BeanUtil.copyProperties(req, ProjectBudgetInfoEntity.class); + info.setBudgetId(IdUtil.simpleUUID()); + attachInfoService.updateBusinessIdByAttachIds(info.getBudgetId(), ListUtil.of(req.getAttachId()), AttachBusinessTypeEnum.PROJECT_BUDGE); + list.add(info); + } + lambdaUpdate().eq(ProjectBudgetInfoEntity::getProjectId, list.get(0).getProjectId()).remove(); + baseMapper.insert(list); + } + +} diff --git a/core/src/main/java/com/dite/znpt/service/impl/ProjectServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ProjectServiceImpl.java index 3748b14..faf5a4a 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/ProjectServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/ProjectServiceImpl.java @@ -23,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -97,10 +98,18 @@ public class ProjectServiceImpl extends ServiceImpl userIdMap = userService.listByIds(userIds).stream().collect(Collectors.toMap(k->k.getUserId(), Function.identity())); if(CollUtil.isNotEmpty(userIdMap)){ + StringBuilder constructorName = new StringBuilder(); resp.setAuditorName(userIdMap.containsKey(resp.getAuditorId()) ? userIdMap.get(resp.getAuditorId()).getName() : null); resp.setProjectManagerName(userIdMap.containsKey(resp.getProjectManagerId()) ? userIdMap.get(resp.getProjectManagerId()).getName() : null); resp.setConstructionTeamLeaderName(userIdMap.containsKey(resp.getConstructionTeamLeaderId()) ? userIdMap.get(resp.getConstructionTeamLeaderId()).getName() : null); resp.setQualityOfficerName(userIdMap.containsKey(resp.getQualityOfficerId()) ? userIdMap.get(resp.getQualityOfficerId()).getName() : null); + Arrays.stream(resp.getConstructorIds().split(StrUtil.COMMA)).forEach(id -> { + if(userIdMap.containsKey(id)){ + constructorName.append(userIdMap.get(id).getName()).append(StrUtil.COMMA); + } + }); + constructorName.deleteCharAt(constructorName.lastIndexOf(StrUtil.COMMA)); + resp.setConstructorName(constructorName.toString()); } } return resp; diff --git a/core/src/main/java/com/dite/znpt/service/impl/ProjectTaskServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ProjectTaskServiceImpl.java index 8c26691..16939d8 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/ProjectTaskServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/ProjectTaskServiceImpl.java @@ -52,7 +52,6 @@ public class ProjectTaskServiceImpl extends ServiceImpl selectList(ProjectTaskListReq projectTaskReq) { - PageUtil.startPage(); List projectTaskList = this.baseMapper.queryBySelective(projectTaskReq); Map> attachMap; if (!BooleanUtil.isTrue(projectTaskReq.getIsExport())) { diff --git a/core/src/main/java/com/dite/znpt/service/impl/TurbineServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/TurbineServiceImpl.java index d5647af..4daf34f 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/TurbineServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/TurbineServiceImpl.java @@ -11,6 +11,7 @@ import com.dite.znpt.domain.entity.TurbineEntity; import com.dite.znpt.domain.vo.*; import com.dite.znpt.domain.vo.job.resp.TurbineStatusResp; import com.dite.znpt.enums.Enums; +import com.dite.znpt.enums.PartTypeEnum; import com.dite.znpt.enums.ProjectStatusEnum; import com.dite.znpt.exception.ServiceException; import com.dite.znpt.mapper.TurbineMapper; @@ -119,7 +120,11 @@ public class TurbineServiceImpl extends ServiceImpl { + part.setPartTypeLabel(PartTypeEnum.getDescByCode(part.getPartType())); + }); + return result; } /** diff --git a/core/src/main/java/com/dite/znpt/service/impl/WorkbenchServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/WorkbenchServiceImpl.java new file mode 100644 index 0000000..75d6821 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/impl/WorkbenchServiceImpl.java @@ -0,0 +1,53 @@ +package com.dite.znpt.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import com.dite.znpt.domain.entity.DefectEntity; +import com.dite.znpt.domain.entity.InspectionReportEntity; +import com.dite.znpt.domain.entity.ProjectEntity; +import com.dite.znpt.domain.entity.ProjectTaskEntity; +import com.dite.znpt.domain.vo.WorkbenchInfoResp; +import com.dite.znpt.service.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class WorkbenchServiceImpl implements WorkbenchService { + private final ProjectService projectService; + private final ProjectTaskService projectTaskService; + private final InspectionReportService inspectionReportService; + private final DefectService defectService; + + @Override + public WorkbenchInfoResp getInfo() { + WorkbenchInfoResp resp = new WorkbenchInfoResp(); + String userId = StpUtil.getLoginIdAsString(); +// 项目数量 + Long projectCount = projectService.lambdaQuery() + .eq(ProjectEntity::getProjectManagerId, userId).or() + .eq(ProjectEntity::getAuditorId, userId).or() + .like(ProjectEntity::getConstructorIds, userId).or() + .eq(ProjectEntity::getQualityOfficerId, userId).or() + .eq(ProjectEntity::getConstructTeamLeaderId, userId) + .count(); + resp.setProjectCount(projectCount); + +// 进行中任务 + Long progressTaskCount = projectTaskService.lambdaQuery() + .eq(ProjectTaskEntity::getMainUserId, userId).or() + .like(ProjectTaskEntity::getUserIds, userId).count(); + resp.setProgressTaskCount(progressTaskCount); + +// 待审核报告数 + Long approvalReportCount = inspectionReportService.lambdaQuery().eq(InspectionReportEntity::getReportAuditor, userId).count(); + resp.setApprovalReportCount(approvalReportCount); + +// 发现缺陷数 + Long findDefectCount = defectService.lambdaQuery() + .eq(DefectEntity::getCreateBy, userId).count(); + resp.setFindDefectCount(findDefectCount); + return resp; + } +} diff --git a/core/src/main/resources/mapper/ContractMapper.xml b/core/src/main/resources/mapper/ContractMapper.xml new file mode 100644 index 0000000..182e078 --- /dev/null +++ b/core/src/main/resources/mapper/ContractMapper.xml @@ -0,0 +1,74 @@ + + + + + + a.contract_id, a.customer, a.code, a.project_id, + a.salesperson_id, a.department_id, a.sign_date, a.duration, + a.type, a.product_service, a.payment_date, a.payment_address, + a.amount, a.account_number, a.notes, a.contract_status, + a.create_time, a.create_by, a.update_time, a.update_by + + + + + diff --git a/core/src/main/resources/mapper/ContractSettlementMapper.xml b/core/src/main/resources/mapper/ContractSettlementMapper.xml new file mode 100644 index 0000000..36761c6 --- /dev/null +++ b/core/src/main/resources/mapper/ContractSettlementMapper.xml @@ -0,0 +1,69 @@ + + + + + + a.settlement_id, a.contract_id, a.customer, a.code, + a.project_id, a.salesperson_id, a.department_id, a.payment_period, + a.payment_date, a.duration, a.product_service, a.amount, + a.account_number, a.notes, a.settlement_status, a.create_time, + a.create_by, a.update_time, a.update_by + + + + + diff --git a/core/src/main/resources/mapper/DefectMapper.xml b/core/src/main/resources/mapper/DefectMapper.xml index 36ca53a..48f0fdf 100644 --- a/core/src/main/resources/mapper/DefectMapper.xml +++ b/core/src/main/resources/mapper/DefectMapper.xml @@ -5,7 +5,7 @@ + SELECT ir.report_id, ir.title, ir.sub_title, ir.report_writer, u.name AS reportWriterName, ir.report_write_time, + ir.project_id, p.project_name, p.farm_name, p.`client`, + ir.turbine_id, t.turbine_name, t.turbine_code + FROM inspection_report ir + LEFT JOIN user u ON ir.report_writer = u.user_id + LEFT JOIN project p ON ir.project_id = p.project_id + LEFT JOIN turbine t ON ir.turbine_id = t.turbine_id + + + AND ir.title LIKE concat('%', #{req.title}, '%') + + + AND ir.sub_title LIKE concat('%', #{req.subTile}, '%') + + + AND ir.project_id = #{req.projectId} + + + AND ir.turbine_id = #{req.turbineId} + + + AND p.farm_name LIKE concat('%', #{req.farmName}, '%') + + + AND p.client LIKE concat('%', #{req.client}, '%') + + + + \ No newline at end of file diff --git a/core/src/main/resources/mapper/ProjectBudgetInfoMapper.xml b/core/src/main/resources/mapper/ProjectBudgetInfoMapper.xml new file mode 100644 index 0000000..5425a2b --- /dev/null +++ b/core/src/main/resources/mapper/ProjectBudgetInfoMapper.xml @@ -0,0 +1,49 @@ + + + + + + a.budget_id, a.project_id, a.budget_name, a.budget_type, + a.budget_amount, a.budget_desc, a.update_by, a.create_time, + a.create_by, a.update_time + + + + + + + diff --git a/core/src/main/resources/mapper/ProjectMapper.xml b/core/src/main/resources/mapper/ProjectMapper.xml index 181fd5a..25aabf1 100644 --- a/core/src/main/resources/mapper/ProjectMapper.xml +++ b/core/src/main/resources/mapper/ProjectMapper.xml @@ -2,13 +2,24 @@ diff --git a/core/src/main/resources/mapper/ProjectTaskGroupMapper.xml b/core/src/main/resources/mapper/ProjectTaskGroupMapper.xml index e47a1b9..76c368b 100644 --- a/core/src/main/resources/mapper/ProjectTaskGroupMapper.xml +++ b/core/src/main/resources/mapper/ProjectTaskGroupMapper.xml @@ -9,15 +9,19 @@ diff --git a/core/src/main/resources/mapper/ProjectTaskMapper.xml b/core/src/main/resources/mapper/ProjectTaskMapper.xml index a53848b..7b07675 100644 --- a/core/src/main/resources/mapper/ProjectTaskMapper.xml +++ b/core/src/main/resources/mapper/ProjectTaskMapper.xml @@ -11,9 +11,10 @@ diff --git a/flowable/.mvn/wrapper/maven-wrapper.properties b/flowable/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..2f94e61 --- /dev/null +++ b/flowable/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.10/apache-maven-3.9.10-bin.zip diff --git a/flowable/pom.xml b/flowable/pom.xml new file mode 100644 index 0000000..edd8467 --- /dev/null +++ b/flowable/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.dite.znpt + parent + 1.0.0-SNAPSHOT + + + flowable + 1.0.0-SNAPSHOT + + + + com.dite.znpt + core + 1.0.0-SNAPSHOT + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.alibaba.fastjson2 + fastjson2 + 2.0.53 + + + org.flowable + flowable-spring-boot-starter + 6.8.0 + + + + org.flowable + flowable-spring-security + + + + + + + com.googlecode.aviator + aviator + 5.3.3 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 17 + 17 + + + + + + diff --git a/flowable/src/main/java/com/dite/znpt/flowable/common/constant/ProcessConstants.java b/flowable/src/main/java/com/dite/znpt/flowable/common/constant/ProcessConstants.java new file mode 100644 index 0000000..987da6a --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/common/constant/ProcessConstants.java @@ -0,0 +1,80 @@ +package com.dite.znpt.flowable.common.constant; + +/** + * 流程常量信息 + * + * @author Tony + * @date 2021/4/17 22:46 + */ +public class ProcessConstants { + + /** + * 动态数据 + */ + public static final String DYNAMIC = "dynamic"; + + /** + * 固定任务接收 + */ + public static final String FIXED = "fixed"; + + /** + * 单个审批人 + */ + public static final String ASSIGNEE = "assignee"; + + + /** + * 候选人 + */ + public static final String CANDIDATE_USERS = "candidateUsers"; + + + /** + * 审批组 + */ + public static final String CANDIDATE_GROUPS = "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"; + + /** + * 初始化人员 + */ + public static final String PROCESS_INITIATOR = "INITIATOR"; + + + /** + * 流程跳过 + */ + public static final String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED"; + + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/common/enums/FlowComment.java b/flowable/src/main/java/com/dite/znpt/flowable/common/enums/FlowComment.java new file mode 100644 index 0000000..225b865 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/common/enums/FlowComment.java @@ -0,0 +1,43 @@ +package com.dite.znpt.flowable.common.enums; + +/** + * 流程意见类型 + * + * @author Tony + * @date 2021/4/19 + */ +public enum FlowComment { + + /** + * 说明 + */ + NORMAL("1", "正常意见"), + REBACK("2", "退回意见"), + REJECT("3", "驳回意见"), + DELEGATE("4", "委派意见"), + ASSIGN("5", "转办意见"), + STOP("6", "终止流程"); + + /** + * 类型 + */ + 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; + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/common/expand/el/BaseEl.java b/flowable/src/main/java/com/dite/znpt/flowable/common/expand/el/BaseEl.java new file mode 100644 index 0000000..df934f2 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/common/expand/el/BaseEl.java @@ -0,0 +1,12 @@ +package com.dite.znpt.flowable.common.expand.el; + +/** + * 扩展表达式 + * + * @author Tony + * @date 2023-03-04 09:10 + */ +public interface BaseEl { + +} + diff --git a/flowable/src/main/java/com/dite/znpt/flowable/common/expand/el/FlowEl.java b/flowable/src/main/java/com/dite/znpt/flowable/common/expand/el/FlowEl.java new file mode 100644 index 0000000..a4f8e46 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/common/expand/el/FlowEl.java @@ -0,0 +1,26 @@ +package com.dite.znpt.flowable.common.expand.el; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 扩展表达式 + * + * @author Tony + * @date 2023-03-04 12:10 + */ +@Component +@Slf4j +public class FlowEl implements BaseEl { + + public String findDeptLeader(String name){ + log.info("开始查询表达式变量值,getName"); + return name; + } + + public String getName(String name){ + log.info("开始查询表达式变量值,getName"); + return name; + } +} + diff --git a/flowable/src/main/java/com/dite/znpt/flowable/config/FlowableConfig.java b/flowable/src/main/java/com/dite/znpt/flowable/config/FlowableConfig.java new file mode 100644 index 0000000..a8988fc --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/config/FlowableConfig.java @@ -0,0 +1,23 @@ +package com.dite.znpt.flowable.config; + +import org.flowable.engine.impl.db.DbIdGenerator; +import org.flowable.spring.SpringProcessEngineConfiguration; +import org.flowable.spring.boot.EngineConfigurationConfigurer; +import org.springframework.context.annotation.Configuration; + +/** + * 扩展流程配置 + * @author Tony + * @date 2022-12-26 10:24 + */ +@Configuration +public class FlowableConfig implements EngineConfigurationConfigurer { + @Override + public void configure(SpringProcessEngineConfiguration engineConfiguration) { + engineConfiguration.setActivityFontName("宋体"); + engineConfiguration.setLabelFontName("宋体"); + engineConfiguration.setAnnotationFontName("宋体"); + engineConfiguration.setIdGenerator(new DbIdGenerator()); + } + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/config/MyDefaultProcessDiagramCanvas.java b/flowable/src/main/java/com/dite/znpt/flowable/config/MyDefaultProcessDiagramCanvas.java new file mode 100644 index 0000000..19496f4 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/config/MyDefaultProcessDiagramCanvas.java @@ -0,0 +1,95 @@ +package com.dite.znpt.flowable.config;//package com.ruoyi.flowable.config; +// +//import com.sun.prism.paint.Color; +//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 Tony +// * @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); +// } +//} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowDefinitionController.java b/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowDefinitionController.java new file mode 100644 index 0000000..9235ad6 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowDefinitionController.java @@ -0,0 +1,200 @@ +package com.dite.znpt.flowable.controller; + + +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.dto.FlowProcDefDto; +import com.dite.znpt.flowable.domain.entity.SysExpression; +import com.dite.znpt.domain.vo.RoleResp; +import com.dite.znpt.domain.vo.UserListReq; +import com.dite.znpt.domain.vo.UserListResp; +import com.dite.znpt.flowable.domain.dto.FlowSaveXmlVo; +import com.dite.znpt.flowable.service.IFlowDefinitionService; +import com.dite.znpt.flowable.service.ISysExpressionService; +import com.dite.znpt.service.RoleService; +import com.dite.znpt.service.UserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; + +/** + *

+ * 工作流程定义 + *

+ * + * @author Tony + * @date 2021-04-03 + */ +@Slf4j +@Api(tags = "流程定义") +@RestController +@RequestMapping("/flowable/definition") +public class FlowDefinitionController { + + @Resource + private IFlowDefinitionService flowDefinitionService; + @Resource + private UserService userService; + @Resource + private RoleService roleService; + + @Resource + private ISysExpressionService sysExpressionService; + + @GetMapping(value = "/list") + @ApiOperation(value = "流程定义列表", response = FlowProcDefDto.class) + public Result list(@ApiParam(value = "当前页码", required = true) @RequestParam Integer pageNum, + @ApiParam(value = "每页条数", required = true) @RequestParam Integer pageSize, + @ApiParam(value = "流程名称", required = false) @RequestParam(required = false) String name) { + return Result.ok(flowDefinitionService.list(name, pageNum, pageSize)); + } + + + @ApiOperation(value = "导入流程文件", notes = "上传bpmn20的xml文件") + @PostMapping("/import") + public Result importFile(@RequestParam(required = false) String name, + @RequestParam(required = false) String category, + MultipartFile file) { + InputStream in = null; + try { + in = file.getInputStream(); + flowDefinitionService.importFile(name, category, in); + } catch (Exception e) { + log.error("导入失败:", e); + return Result.ok(e.getMessage()); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + log.error("关闭输入流出错", e); + } + } + + return Result.ok("导入成功"); + } + + + @ApiOperation(value = "读取xml文件") + @GetMapping("/readXml/{deployId}") + public Result readXml(@ApiParam(value = "流程定义id") @PathVariable(value = "deployId") String deployId) { + try { + return flowDefinitionService.readXml(deployId); + } catch (Exception e) { + return Result.error("加载xml文件异常"); + } + + } + + @ApiOperation(value = "读取图片文件") + @GetMapping("/readImage/{deployId}") + public void readImage(@ApiParam(value = "流程定义id") @PathVariable(value = "deployId") String deployId, HttpServletResponse response) { + OutputStream os = null; + BufferedImage image = null; + try { + image = ImageIO.read(flowDefinitionService.readImage(deployId)); + 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(); + } + } + + } + + + @ApiOperation(value = "保存流程设计器内的xml文件") + @PostMapping("/save") + public Result save(@RequestBody FlowSaveXmlVo vo) { + InputStream in = null; + try { + in = new ByteArrayInputStream(vo.getXml().getBytes(StandardCharsets.UTF_8)); + flowDefinitionService.importFile(vo.getName(), vo.getCategory(), in); + } catch (Exception e) { + log.error("导入失败:", e); + return Result.error(e.getMessage()); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + log.error("关闭输入流出错", e); + } + } + + return Result.ok("导入成功"); + } + + @ApiOperation(value = "发起流程") + @PostMapping("/start/{procDefId}") + public Result start(@ApiParam(value = "流程定义id") @PathVariable(value = "procDefId") String procDefId, + @ApiParam(value = "变量集合,json对象") @RequestBody Map variables) { + return flowDefinitionService.startProcessInstanceById(procDefId, variables); + } + + @ApiOperation(value = "激活或挂起流程定义") + @PutMapping(value = "/updateState") + public Result updateState(@ApiParam(value = "1:激活,2:挂起", required = true) @RequestParam Integer state, + @ApiParam(value = "流程部署ID", required = true) @RequestParam String deployId) { + flowDefinitionService.updateState(state, deployId); + return Result.ok(); + } + + @ApiOperation(value = "删除流程") + @DeleteMapping(value = "/{deployIds}") + public Result delete(@PathVariable String[] deployIds) { + for (String deployId : deployIds) { + flowDefinitionService.delete(deployId); + } + return Result.ok(); + } + + @ApiOperation(value = "指定流程办理人员列表") + @GetMapping("/userList") + public Result userList(UserListReq req) { + List list = userService.list(req); + return Result.ok(list); + } + + @ApiOperation(value = "指定流程办理组列表") + @GetMapping("/roleList") + public Result roleList(String roleName) { + List list = roleService.list(roleName); + return Result.ok(list); + } + + @ApiOperation(value = "指定流程达式列表") + @GetMapping("/expList") + public Result expList(SysExpression sysExpression) { + List list = sysExpressionService.selectSysExpressionList(sysExpression); + return Result.ok(list); + } + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowInstanceController.java b/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowInstanceController.java new file mode 100644 index 0000000..19411b6 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowInstanceController.java @@ -0,0 +1,62 @@ +package com.dite.znpt.flowable.controller; + +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.vo.FlowTaskVo; +import com.dite.znpt.flowable.service.IFlowInstanceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + *

工作流流程实例管理

+ * + * @author Tony + * @date 2021-04-03 + */ +@Slf4j +@Api(tags = "工作流流程实例管理") +@RestController +@RequestMapping("/flowable/instance") +public class FlowInstanceController { + + @Autowired + private IFlowInstanceService flowInstanceService; + + @ApiOperation(value = "根据流程定义id启动流程实例") + @PostMapping("/startBy/{procDefId}") + public Result startById(@ApiParam(value = "流程定义id") @PathVariable(value = "procDefId") String procDefId, + @ApiParam(value = "变量集合,json对象") @RequestBody Map variables) { + return flowInstanceService.startProcessInstanceById(procDefId, variables); + + } + + @ApiOperation(value = "激活或挂起流程实例") + @PostMapping(value = "/updateState") + public Result updateState(@ApiParam(value = "1:激活,2:挂起", required = true) @RequestParam Integer state, + @ApiParam(value = "流程实例ID", required = true) @RequestParam String instanceId) { + flowInstanceService.updateState(state,instanceId); + return Result.ok(); + } + + @ApiOperation("结束流程实例") + @PostMapping(value = "/stopProcessInstance") + public Result stopProcessInstance(@RequestBody FlowTaskVo flowTaskVo) { + flowInstanceService.stopProcessInstance(flowTaskVo); + return Result.ok(); + } + + @ApiOperation(value = "删除流程实例") + @DeleteMapping(value = "/delete/{instanceIds}") + public Result delete(@ApiParam(value = "流程实例ID", required = true) @PathVariable String[] instanceIds, + @ApiParam(value = "删除原因") @RequestParam(required = false) String deleteReason) { + for (String instanceId : instanceIds) { + flowInstanceService.delete(instanceId,deleteReason); + } + return Result.ok(); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowTaskController.java b/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowTaskController.java new file mode 100644 index 0000000..f313b43 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/controller/FlowTaskController.java @@ -0,0 +1,267 @@ +package com.dite.znpt.flowable.controller; + +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.dto.FlowTaskDto; +import com.dite.znpt.flowable.domain.vo.FlowQueryVo; +import com.dite.znpt.flowable.domain.vo.FlowTaskVo; +import com.dite.znpt.flowable.service.IFlowTaskService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + *

工作流任务管理

+ * + * @author Tony + * @date 2021-04-03 + */ +@Slf4j +@Api(tags = "工作流流程任务管理") +@RestController +@RequestMapping("/flowable/task") +public class FlowTaskController { + + @Autowired + private IFlowTaskService flowTaskService; + + @ApiOperation(value = "我发起的流程", response = FlowTaskDto.class) + @GetMapping(value = "/myProcess") + public Result myProcess(FlowQueryVo queryVo) { + return flowTaskService.myProcess(queryVo); + } + + @ApiOperation(value = "取消申请", response = FlowTaskDto.class) + @PostMapping(value = "/stopProcess") + public Result stopProcess(@RequestBody FlowTaskVo flowTaskVo) { + return flowTaskService.stopProcess(flowTaskVo); + } + + @ApiOperation(value = "撤回流程", response = FlowTaskDto.class) + @PostMapping(value = "/revokeProcess") + public Result revokeProcess(@RequestBody FlowTaskVo flowTaskVo) { + return flowTaskService.revokeProcess(flowTaskVo); + } + + @ApiOperation(value = "获取待办列表", response = FlowTaskDto.class) + @GetMapping(value = "/todoList") + public Result todoList(FlowQueryVo queryVo) { + return flowTaskService.todoList(queryVo); + } + + @ApiOperation(value = "获取已办任务", response = FlowTaskDto.class) + @GetMapping(value = "/finishedList") + public Result finishedList(FlowQueryVo queryVo) { + return flowTaskService.finishedList(queryVo); + } + + + @ApiOperation(value = "流程历史流转记录", response = FlowTaskDto.class) + @GetMapping(value = "/flowRecord") + public Result flowRecord(String procInsId, String deployId) { + return flowTaskService.flowRecord(procInsId, deployId); + } + + @ApiOperation(value = "根据任务ID查询挂载的表单信息") + @GetMapping(value = "/getTaskForm") + public Result getTaskForm(String taskId) { + return flowTaskService.getTaskForm(taskId); + } + + + @ApiOperation(value = "流程初始化表单", response = FlowTaskDto.class) + @GetMapping(value = "/flowFormData") + public Result flowFormData(String deployId) { + return flowTaskService.flowFormData(deployId); + } + + @ApiOperation(value = "获取流程变量", response = FlowTaskDto.class) + @GetMapping(value = "/processVariables/{taskId}") + public Result processVariables(@ApiParam(value = "流程任务Id") @PathVariable(value = "taskId") String taskId) { + return flowTaskService.processVariables(taskId); + } + + @ApiOperation(value = "审批任务") + @PostMapping(value = "/complete") + public Result complete(@RequestBody FlowTaskVo flowTaskVo) { + return flowTaskService.complete(flowTaskVo); + } + + @PostMapping(value = "/reject") + public Result taskReject(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.taskReject(flowTaskVo); + return Result.ok(); + } + + @ApiOperation(value = "退回任务") + @PostMapping(value = "/return") + public Result taskReturn(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.taskReturn(flowTaskVo); + return Result.ok(); + } + + @ApiOperation(value = "获取所有可回退的节点") + @PostMapping(value = "/returnList") + public Result findReturnTaskList(@RequestBody FlowTaskVo flowTaskVo) { + return flowTaskService.findReturnTaskList(flowTaskVo); + } + + @ApiOperation(value = "删除任务") + @DeleteMapping(value = "/delete") + public Result delete(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.deleteTask(flowTaskVo); + return Result.ok(); + } + + @ApiOperation(value = "认领/签收任务") + @PostMapping(value = "/claim") + public Result claim(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.claim(flowTaskVo); + return Result.ok(); + } + + @ApiOperation(value = "取消认领/签收任务") + @PostMapping(value = "/unClaim") + public Result unClaim(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.unClaim(flowTaskVo); + return Result.ok(); + } + + @ApiOperation(value = "委派任务") + @PostMapping(value = "/delegateTask") + public Result delegate(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.delegateTask(flowTaskVo); + return Result.ok(); + } + + @ApiOperation(value = "任务归还") + @PostMapping(value = "/resolveTask") + public Result resolveTask(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.resolveTask(flowTaskVo); + return Result.ok(); + } + + @ApiOperation(value = "转办任务") + @PostMapping(value = "/assignTask") + public Result assign(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.assignTask(flowTaskVo); + return Result.ok(); + } + + @PostMapping(value = "/addMultiInstanceExecution") + @ApiOperation(value = "多实例加签") + public Result addMultiInstanceExecution(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.addMultiInstanceExecution(flowTaskVo); + return Result.ok("加签成功"); + } + + @PostMapping(value = "/deleteMultiInstanceExecution") + @ApiOperation(value = "多实例减签") + public Result deleteMultiInstanceExecution(@RequestBody FlowTaskVo flowTaskVo) { + flowTaskService.deleteMultiInstanceExecution(flowTaskVo); + return Result.ok("减签成功"); + } + + @ApiOperation(value = "获取下一节点") + @PostMapping(value = "/nextFlowNode") + public Result getNextFlowNode(@RequestBody FlowTaskVo flowTaskVo) { + return flowTaskService.getNextFlowNode(flowTaskVo); + } + + @ApiOperation(value = "流程发起时获取下一节点") + @PostMapping(value = "/nextFlowNodeByStart") + public Result getNextFlowNodeByStart(@RequestBody FlowTaskVo flowTaskVo) { + return flowTaskService.getNextFlowNodeByStart(flowTaskVo); + } + + /** + * 生成流程图 + * + * @param processId 任务ID + */ + @GetMapping("/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(); + } + } + } + + /** + * 获取流程执行节点 + * + * @param procInsId 流程实例编号 + * @param procInsId 任务执行编号 + */ + @GetMapping("/flowViewer/{procInsId}/{executionId}") + public Result getFlowViewer(@PathVariable("procInsId") String procInsId, + @PathVariable("executionId") String executionId) { + return flowTaskService.getFlowViewer(procInsId, executionId); + } + + /** + * 流程节点信息 + * + * @param procInsId 流程实例id + * @return + */ + @GetMapping("/flowXmlAndNode") + public Result flowXmlAndNode(@RequestParam(value = "procInsId", required = false) String procInsId, + @RequestParam(value = "deployId", required = false) String deployId) { + return flowTaskService.flowXmlAndNode(procInsId, deployId); + } + + /** + * 流程节点表单 + * + * @param taskId 流程任务编号 + * @return + */ + @GetMapping("/flowTaskForm") + public Result flowTaskForm(@RequestParam(value = "taskId", required = false) String taskId) throws Exception { + return flowTaskService.flowTaskForm(taskId); + } + + + /** + * 流程节点信息 + * + * @param procInsId 流程实例编号 + * @param elementId 流程节点编号 + * @return + */ + @GetMapping("/flowTaskInfo") + public Result flowTaskInfo(@RequestParam(value = "procInsId") String procInsId, + @RequestParam(value = "elementId") String elementId){ + return flowTaskService.flowTaskInfo(procInsId,elementId); + } + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/controller/SysExpressionController.java b/flowable/src/main/java/com/dite/znpt/flowable/controller/SysExpressionController.java new file mode 100644 index 0000000..05b9b38 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/controller/SysExpressionController.java @@ -0,0 +1,91 @@ +package com.dite.znpt.flowable.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +import com.dite.znpt.domain.PageResult; +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.entity.SysExpression; +import com.dite.znpt.flowable.service.ISysExpressionService; +import com.dite.znpt.util.PageUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 流程达式Controller + * + * @author ruoyi + * @date 2022-12-12 + */ +@RestController +@RequestMapping("/system/expression") +public class SysExpressionController +{ + @Autowired + private ISysExpressionService sysExpressionService; + + /** + * 查询流程达式列表 + */ + @GetMapping("/list") + public PageResult list(SysExpression sysExpression) + { + PageUtil.startPage(); + List list = sysExpressionService.selectSysExpressionList(sysExpression); + return PageResult.ok(list); + } + + /** + * 导出流程达式列表 + */ + @PostMapping("/export") + public void export(HttpServletResponse response, SysExpression sysExpression){ + //TODO +// List list = sysExpressionService.selectSysExpressionList(sysExpression); +// ExcelUtil util = new ExcelUtil(SysExpression.class); +// util.exportExcel(response, list, "流程达式数据"); + } + + /** + * 获取流程达式详细信息 + */ + @GetMapping(value = "/{id}") + public Result getInfo(@PathVariable("id") Long id) + { + return Result.ok(sysExpressionService.selectSysExpressionById(id)); + } + + /** + * 新增流程达式 + */ + @PostMapping + public Result add(@RequestBody SysExpression sysExpression) + { + return Result.ok(sysExpressionService.insertSysExpression(sysExpression)); + } + + /** + * 修改流程达式 + */ + @PutMapping + public Result edit(@RequestBody SysExpression sysExpression) + { + return Result.ok(sysExpressionService.updateSysExpression(sysExpression)); + } + + /** + * 删除流程达式 + */ + @DeleteMapping("/{ids}") + public Result remove(@PathVariable Long[] ids) + { + return Result.ok(sysExpressionService.deleteSysExpressionByIds(ids)); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/controller/SysFormController.java b/flowable/src/main/java/com/dite/znpt/flowable/controller/SysFormController.java new file mode 100644 index 0000000..9a52ee4 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/controller/SysFormController.java @@ -0,0 +1,104 @@ +package com.dite.znpt.flowable.controller; + +import java.util.List; + + +import com.dite.znpt.domain.PageResult; +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.entity.SysDeployForm; +import com.dite.znpt.flowable.domain.entity.SysForm; +import com.dite.znpt.flowable.service.ISysDeployFormService; +import com.dite.znpt.flowable.service.ISysFormService; +import com.dite.znpt.util.PageUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 流程表单Controller + * + * @author Tony + * @date 2021-04-03 + */ +@RestController +@RequestMapping("/flowable/form") +public class SysFormController { + @Autowired + private ISysFormService SysFormService; + + @Autowired + private ISysDeployFormService sysDeployFormService; + + /** + * 查询流程表单列表 + */ + @GetMapping("/list") + public PageResult list(SysForm sysForm) { + PageUtil.startPage(); + List list = SysFormService.selectSysFormList(sysForm); + return PageResult.ok(list); + } + + @GetMapping("/formList") + public Result formList(SysForm sysForm) { + List list = SysFormService.selectSysFormList(sysForm); + return Result.ok(list); + } + /** + * 导出流程表单列表 + */ + @GetMapping("/export") + public void export(SysForm sysForm) { + // TODO +// List list = SysFormService.selectSysFormList(sysForm); +// ExcelUtil util = new ExcelUtil(SysForm.class); +// util.exportExcel(list, "form"); + } + + /** + * 获取流程表单详细信息 + */ + @GetMapping(value = "/{formId}") + public Result getInfo(@PathVariable("formId") Long formId) { + return Result.ok(SysFormService.selectSysFormById(formId)); + } + + /** + * 新增流程表单 + */ + @PostMapping + public Result add(@RequestBody SysForm sysForm) { + return Result.ok(SysFormService.insertSysForm(sysForm)); + } + + /** + * 修改流程表单 + */ + @PutMapping + public Result edit(@RequestBody SysForm sysForm) { + return Result.ok(SysFormService.updateSysForm(sysForm)); + } + + /** + * 删除流程表单 + */ + @DeleteMapping("/{formIds}") + public Result remove(@PathVariable Long[] formIds) { + return Result.ok(SysFormService.deleteSysFormByIds(formIds)); + } + + + /** + * 挂载流程表单 + */ + @PostMapping("/addDeployForm") + public Result addDeployForm(@RequestBody SysDeployForm sysDeployForm) { + return Result.ok(sysDeployFormService.insertSysDeployForm(sysDeployForm)); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/controller/SysListenerController.java b/flowable/src/main/java/com/dite/znpt/flowable/controller/SysListenerController.java new file mode 100644 index 0000000..35464be --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/controller/SysListenerController.java @@ -0,0 +1,92 @@ +package com.dite.znpt.flowable.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +import com.dite.znpt.domain.PageResult; +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.entity.SysListener; +import com.dite.znpt.flowable.service.ISysListenerService; +import com.dite.znpt.util.PageUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 流程监听Controller + * + * @author Tony + * @date 2022-12-25 + */ +@RestController +@RequestMapping("/system/listener") +public class SysListenerController +{ + @Autowired + private ISysListenerService sysListenerService; + + /** + * 查询流程监听列表 + */ + @GetMapping("/list") + public PageResult list(SysListener sysListener) + { + PageUtil.startPage(); + List list = sysListenerService.selectSysListenerList(sysListener); + return PageResult.ok(list); + } + + /** + * 导出流程监听列表 + */ + @PostMapping("/export") + public void export(HttpServletResponse response, SysListener sysListener) + { + //TODO +// List list = sysListenerService.selectSysListenerList(sysListener); +// ExcelUtil util = new ExcelUtil(SysListener.class); +// util.exportExcel(response, list, "流程监听数据"); + } + + /** + * 获取流程监听详细信息 + */ + @GetMapping(value = "/{id}") + public Result getInfo(@PathVariable("id") Long id) + { + return Result.ok(sysListenerService.selectSysListenerById(id)); + } + + /** + * 新增流程监听 + */ + @PostMapping + public Result add(@RequestBody SysListener sysListener) + { + return Result.ok(sysListenerService.insertSysListener(sysListener)); + } + + /** + * 修改流程监听 + */ + @PutMapping + public Result edit(@RequestBody SysListener sysListener) + { + return Result.ok(sysListenerService.updateSysListener(sysListener)); + } + + /** + * 删除流程监听 + */ + @DeleteMapping("/{ids}") + public Result remove(@PathVariable Long[] ids) + { + return Result.ok(sysListenerService.deleteSysListenerByIds(ids)); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowCommentDto.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowCommentDto.java new file mode 100644 index 0000000..e138e49 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowCommentDto.java @@ -0,0 +1,25 @@ +package com.dite.znpt.flowable.domain.dto; + +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Tony + * @date 2021/3/28 15:50 + */ +@Data +@Builder +public class FlowCommentDto implements Serializable { + + /** + * 意见类别 0 正常意见 1 退回意见 2 驳回意见 + */ + private String type; + + /** + * 意见内容 + */ + private String comment; +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowFromFieldDTO.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowFromFieldDTO.java new file mode 100644 index 0000000..cc0ba8c --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowFromFieldDTO.java @@ -0,0 +1,15 @@ +package com.dite.znpt.flowable.domain.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Tony + * @date 2021/3/31 23:20 + */ +@Data +public class FlowFromFieldDTO implements Serializable { + + private Object fields; +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowNextDto.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowNextDto.java new file mode 100644 index 0000000..6f184cc --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowNextDto.java @@ -0,0 +1,30 @@ +package com.dite.znpt.flowable.domain.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 动态人员、组 + * @author Tony + * @date 2021/4/17 22:59 + */ +@Data +public class FlowNextDto implements Serializable { + + /** + * 审批人类型 + */ + private String type; + + /** + * 是否需要动态指定任务审批人 + */ + private String dataType; + + /** + * 流程变量 + */ + private String vars; + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowSaveXmlVo.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowSaveXmlVo.java new file mode 100644 index 0000000..a5dfff2 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowSaveXmlVo.java @@ -0,0 +1,28 @@ +package com.dite.znpt.flowable.domain.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Tony + * @date 2021/3/28 19:48 + */ +@Data +public class FlowSaveXmlVo implements Serializable { + + /** + * 流程名称 + */ + private String name; + + /** + * 流程分类 + */ + private String category; + + /** + * xml 文件 + */ + private String xml; +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowTaskDto.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowTaskDto.java new file mode 100644 index 0000000..da21000 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowTaskDto.java @@ -0,0 +1,102 @@ +package com.dite.znpt.flowable.domain.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; + +/** + *

工作流任务

+ * + * @author Tony + * @date 2021-04-03 + */ +@Getter +@Setter +@ApiModel("工作流任务相关-返回参数") +public class FlowTaskDto implements Serializable { + + @ApiModelProperty("任务编号") + private String taskId; + + @ApiModelProperty("任务执行编号") + private String executionId; + + @ApiModelProperty("任务名称") + private String taskName; + + @ApiModelProperty("任务Key") + private String taskDefKey; + + @ApiModelProperty("任务执行人Id") + private String assigneeId; + + @ApiModelProperty("部门名称") + private String deptName; + + @ApiModelProperty("流程发起人部门名称") + private String startDeptName; + + @ApiModelProperty("任务执行人名称") + private String assigneeName; + @ApiModelProperty("任务执行人部门") + private String assigneeDeptName;; + + @ApiModelProperty("流程发起人Id") + private String startUserId; + + @ApiModelProperty("流程发起人名称") + private String startUserName; + + @ApiModelProperty("流程类型") + private String category; + + @ApiModelProperty("流程变量信息") + private Object variables; + + @ApiModelProperty("局部变量信息") + private Object taskLocalVars; + + @ApiModelProperty("流程部署编号") + private String deployId; + + @ApiModelProperty("流程ID") + private String procDefId; + + @ApiModelProperty("流程key") + private String procDefKey; + + @ApiModelProperty("流程定义名称") + private String procDefName; + + @ApiModelProperty("流程定义内置使用版本") + private int procDefVersion; + + @ApiModelProperty("流程实例ID") + private String procInsId; + + @ApiModelProperty("历史流程实例ID") + private String hisProcInsId; + + @ApiModelProperty("任务耗时") + private String duration; + + @ApiModelProperty("任务意见") + private FlowCommentDto comment; + + @ApiModelProperty("候选执行人") + private String candidate; + + @ApiModelProperty("任务创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @ApiModelProperty("任务完成时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date finishTime; + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowViewerDto.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowViewerDto.java new file mode 100644 index 0000000..9568799 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/dto/FlowViewerDto.java @@ -0,0 +1,23 @@ +package com.dite.znpt.flowable.domain.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Tony + * @date 2021/4/21 20:55 + */ +@Data +public class FlowViewerDto implements Serializable { + + /** + * 流程key + */ + private String key; + + /** + * 是否完成(已经审批) + */ + private boolean completed; +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysDeployForm.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysDeployForm.java new file mode 100644 index 0000000..666ad64 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysDeployForm.java @@ -0,0 +1,51 @@ +package com.dite.znpt.flowable.domain.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 流程实例关联表单对象 sys_instance_form + * + * @author Tony + * @date 2021-03-30 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_deploy_form") +@ApiModel(value="SysDeployForm对象", description="流程实例关联表单") +public class SysDeployForm implements Serializable { + + @Serial + private static final long serialVersionUID = 1229567797120051612L; + + @ApiModelProperty("主键") + @TableId(value = "id") + private Long id; + + @ApiModelProperty("表单主键") + @TableField("form_id") + private Long formId; + + @ApiModelProperty("流程定义主键") + @TableField("deploy_id") + private String deployId; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("formId", getFormId()) + .append("deployId", getDeployId()) + .toString(); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysExpression.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysExpression.java new file mode 100644 index 0000000..6747f42 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysExpression.java @@ -0,0 +1,73 @@ +package com.dite.znpt.flowable.domain.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.dite.znpt.domain.AuditableEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 流程达式对象 sys_expression + * + * @author ruoyi + * @date 2022-12-12 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_expression") +@ApiModel(value="SysExpression对象", description="流程表达式") +public class SysExpression extends AuditableEntity implements Serializable { + + @Serial + private static final long serialVersionUID = -6620158503098718552L; + /** 表单主键 */ + @TableId(value = "id") + private Long id; + + /** 表达式名称 */ + @ApiModelProperty(name = "表达式名称") + @TableField("name") + private String name; + + /** 表达式内容 */ + @ApiModelProperty(name = "表达式内容") + @TableField("expression") + private String expression; + /** 表达式类型 */ + @ApiModelProperty(name = "表达式类型") + @TableField("data_type") + private String dataType; + + /** 状态 */ + @ApiModelProperty(name = "状态") + @TableField("status") + private Integer status; + + @ApiModelProperty(name = "备注") + @TableField("remark") + private String remark; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("expression", getExpression()) + .append("dataType", getDataType()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .append("createBy", getCreateBy()) + .append("updateBy", getUpdateBy()) + .append("status", getStatus()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysForm.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysForm.java new file mode 100644 index 0000000..404cb1e --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysForm.java @@ -0,0 +1,63 @@ +package com.dite.znpt.flowable.domain.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.dite.znpt.domain.AuditableEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 流程表单对象 sys_task_form + * + * @author Tony + * @date 2021-03-30 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_form") +@ApiModel(value="SysForm对象", description="流程表单") +public class SysForm extends AuditableEntity implements Serializable { + @Serial + private static final long serialVersionUID = 4305516082701611447L; + + /** 表单主键 */ + @TableId(value = "form_id") + @ApiModelProperty(name = "表单主键") + private Long formId; + + /** 表单名称 */ + @ApiModelProperty(name = "表单名称") + @TableField("form_name") + private String formName; + + /** 表单内容 */ + @ApiModelProperty(name = "表单内容") + @TableField("form_content") + private String formContent; + + @ApiModelProperty(name = "备注") + @TableField("remark") + private String remark; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("formId", getFormId()) + .append("formName", getFormName()) + .append("formContent", getFormContent()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .append("createBy", getCreateBy()) + .append("updateBy", getUpdateBy()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysListener.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysListener.java new file mode 100644 index 0000000..7ca2c52 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/entity/SysListener.java @@ -0,0 +1,87 @@ +package com.dite.znpt.flowable.domain.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.dite.znpt.domain.AuditableEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 流程监听对象 sys_listener + * + * @author Tony + * @date 2022-12-25 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_listener") +@ApiModel(value="SysListener对象", description="流程监听") +public class SysListener extends AuditableEntity implements Serializable { + + @Serial + private static final long serialVersionUID = 3933601576294703106L; + + /** 表单主键 */ + @ApiModelProperty(name = "表单主键") + @TableId(value = "id") + private Long id; + + /** 名称 */ + @ApiModelProperty(name = "名称") + @TableField("name") + private String name; + + /** 监听类型 */ + @TableField("type") + @ApiModelProperty(name = "监听类型") + private String type; + + /** 事件类型 */ + @ApiModelProperty(name = "事件类型") + @TableField("event_type") + private String eventType; + + /** 值类型 */ + @ApiModelProperty(name = "值类型") + @TableField("value_type") + private String valueType; + + /** 执行内容 */ + @ApiModelProperty(name = "执行内容") + @TableField("value") + private String value; + + /** 状态 */ + @ApiModelProperty(name = "状态") + @TableField("status") + private Integer status; + + @ApiModelProperty(name = "备注") + @TableField("remark") + private String remark; + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("type", getType()) + .append("eventType", getEventType()) + .append("valueType", getValueType()) + .append("value", getValue()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .append("createBy", getCreateBy()) + .append("updateBy", getUpdateBy()) + .append("status", getStatus()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/FlowQueryVo.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/FlowQueryVo.java new file mode 100644 index 0000000..a0e8384 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/FlowQueryVo.java @@ -0,0 +1,36 @@ +package com.dite.znpt.flowable.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + *

流程任务

+ * + * @author Tony + * @date 2021-04-03 + */ +@Data +@ApiModel("工作流任务相关--请求参数") +public class FlowQueryVo { + + @ApiModelProperty("流程名称") + private String name; + + @ApiModelProperty("开始时间") + private String startTime; + + @ApiModelProperty("结束时间") + private String endTime; + + @ApiModelProperty("当前页码") + private Integer pageNum; + + @ApiModelProperty("每页条数") + private Integer pageSize; + + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/FlowTaskVo.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/FlowTaskVo.java new file mode 100644 index 0000000..4579e8c --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/FlowTaskVo.java @@ -0,0 +1,56 @@ +package com.dite.znpt.flowable.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + *

流程任务

+ * + * @author Tony + * @date 2021-04-03 + */ +@Data +@ApiModel("工作流任务相关--请求参数") +public class FlowTaskVo { + + @ApiModelProperty("任务Id") + private String taskId; + + @ApiModelProperty("用户Id") + private String userId; + + @ApiModelProperty("任务意见") + private String comment; + + @ApiModelProperty("流程实例Id") + private String instanceId; + + @ApiModelProperty("节点") + private String targetKey; + + private String deploymentId; + @ApiModelProperty("流程环节定义ID") + private String defId; + + @ApiModelProperty("子执行流ID") + private String currentChildExecutionId; + + @ApiModelProperty("子执行流是否已执行") + private Boolean flag; + + @ApiModelProperty("流程变量信息") + private Map variables; + + @ApiModelProperty("审批人") + private String assignee; + + @ApiModelProperty("候选人") + private List candidateUsers; + + @ApiModelProperty("审批组") + private List candidateGroups; +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/ReturnTaskNodeVo.java b/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/ReturnTaskNodeVo.java new file mode 100644 index 0000000..645648e --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/domain/vo/ReturnTaskNodeVo.java @@ -0,0 +1,26 @@ +package com.dite.znpt.flowable.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + *

可退回节点

+ * + * @author tony + * @date 2022-04-23 11:01:52 + */ +@Data +@ApiModel("可退回节点") +public class ReturnTaskNodeVo { + + @ApiModelProperty("任务Id") + private String id; + + @ApiModelProperty("用户Id") + private String name; + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/factory/FlowServiceFactory.java b/flowable/src/main/java/com/dite/znpt/flowable/factory/FlowServiceFactory.java new file mode 100644 index 0000000..9ba5683 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/factory/FlowServiceFactory.java @@ -0,0 +1,41 @@ +package com.dite.znpt.flowable.factory; + +import lombok.Getter; +import org.flowable.engine.*; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * flowable 引擎注入封装 + * @author Tony + * @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 HistoryService historyService; + + @Resource + protected ManagementService managementService; + + @Qualifier("processEngine") + @Resource + protected ProcessEngine processEngine; + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/flow/CustomProcessDiagramCanvas.java b/flowable/src/main/java/com/dite/znpt/flowable/flow/CustomProcessDiagramCanvas.java new file mode 100644 index 0000000..8321d9f --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/flow/CustomProcessDiagramCanvas.java @@ -0,0 +1,370 @@ +package com.dite.znpt.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 Tony + * @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) { + Integer sourceX = xPoints[i - 1]; + Integer sourceY = yPoints[i - 1]; + Integer targetX = xPoints[i]; + Integer 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); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/flow/CustomProcessDiagramGenerator.java b/flowable/src/main/java/com/dite/znpt/flowable/flow/CustomProcessDiagramGenerator.java new file mode 100644 index 0000000..8844341 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/flow/CustomProcessDiagramGenerator.java @@ -0,0 +1,404 @@ +package com.dite.znpt.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 Tony + * @date 2021/4/5 0:31 + */ +public class CustomProcessDiagramGenerator extends DefaultProcessDiagramGenerator { + @Override + protected DefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, List 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 highLightedActivities, List 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 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); + } + } + } + } +} + diff --git a/flowable/src/main/java/com/dite/znpt/flowable/flow/FindNextNodeUtil.java b/flowable/src/main/java/com/dite/znpt/flowable/flow/FindNextNodeUtil.java new file mode 100644 index 0000000..d31362f --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/flow/FindNextNodeUtil.java @@ -0,0 +1,266 @@ +package com.dite.znpt.flowable.flow; + +import com.googlecode.aviator.AviatorEvaluator; +import com.googlecode.aviator.Expression; +//import com.greenpineyu.fel.FelEngine; +//import com.greenpineyu.fel.FelEngineImpl; +//import com.greenpineyu.fel.context.FelContext; +//import org.apache.commons.jexl2.JexlContext; +//import org.apache.commons.jexl2.JexlEngine; +//import org.apache.commons.jexl2.MapContext; +//import org.apache.commons.lang3.StringUtils; +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.*; + +/** + * @author Tony + * @date 2021/4/19 20:51 + */ +public class FindNextNodeUtil { + + /** + * 获取下一步骤的用户任务 + * + * @param repositoryService + * @param map + * @return + */ + public static List getNextUserTasks(RepositoryService repositoryService, org.flowable.task.api.Task task, Map map) { + List data = new ArrayList<>(); + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); + Process mainProcess = bpmnModel.getMainProcess(); + Collection flowElements = mainProcess.getFlowElements(); + String key = task.getTaskDefinitionKey(); + FlowElement flowElement = bpmnModel.getFlowElement(key); + next(flowElements, flowElement, map, data); + return data; + } + + /** + * 启动流程时获取下一步骤的用户任务 + * + * @param repositoryService + * @param map + * @return + */ + public static List getNextUserTasksByStart(RepositoryService repositoryService, ProcessDefinition processDefinition, Map map) { + List data = new ArrayList<>(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); + Process mainProcess = bpmnModel.getMainProcess(); + Collection flowElements = mainProcess.getFlowElements(); + String key = null; + // 找到开始节点 并获取唯一key + for (FlowElement flowElement : flowElements) { + if (flowElement instanceof StartEvent) { + key = flowElement.getId(); + break; + } + } + FlowElement flowElement = bpmnModel.getFlowElement(key); + List sequenceFlows = ((StartEvent)flowElement).getOutgoingFlows(); + // 获取出口连线, 此时从开始节点往后,只能是一个出口 + if (!sequenceFlows.isEmpty()) { + SequenceFlow sequenceFlow = sequenceFlows.get(0); + FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement(); + next(flowElements, targetFlowElement, map, data); + } + return data; + } + + + /** + * 查找下一节点 + * + * @param flowElements + * @param flowElement + * @param map + * @param nextUser + */ + public static void next(Collection flowElements, FlowElement flowElement, Map map, List nextUser) { + //如果是结束节点 + if (flowElement instanceof EndEvent) { + //如果是子任务的结束节点 + if (getSubProcess(flowElements, flowElement) != null) { + flowElement = getSubProcess(flowElements, flowElement); + } + } + //获取Task的出线信息--可以拥有多个 + List 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 flowElements, List 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 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 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 flowElements) { + for (FlowElement flowElement : flowElements) { + if (flowElement instanceof StartEvent) { + return flowElement; + } + } + return null; + } + + /** + * 校验el表达式 + * + * @param map + * @param expression + * @return + */ + public static boolean expressionResult(Map map, String expression) { + Expression exp = AviatorEvaluator.compile(expression); + return (Boolean) exp.execute(map); +// return true; + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/flow/FlowableUtils.java b/flowable/src/main/java/com/dite/znpt/flowable/flow/FlowableUtils.java new file mode 100644 index 0000000..742e011 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/flow/FlowableUtils.java @@ -0,0 +1,702 @@ +package com.dite.znpt.flowable.flow; + +import lombok.extern.slf4j.Slf4j; +import org.flowable.bpmn.model.*; +import org.flowable.engine.RepositoryService; +import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; +import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.task.api.history.HistoricTaskInstance; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Tony + * @date 2021-04-03 23:57 + */ +@Slf4j +public class FlowableUtils { + + /** + * 根据节点,获取入口连线 + * + * @param source + * @return + */ + public static List getElementIncomingFlows(FlowElement source) { + List 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 getElementOutgoingFlows(FlowElement source) { + List 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 getAllElements(Collection flowElements, Collection 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 iteratorFindParentUserTasks(FlowElement source, Set hasSequenceFlow, List 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 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 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 iteratorFindChildUserTasks(FlowElement source, List runTaskKeyList, Set hasSequenceFlow, List userTaskList) { + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; + + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代 + if (source instanceof EndEvent && source.getSubProcess() != null) { + userTaskList = iteratorFindChildUserTasks(source.getSubProcess(), runTaskKeyList, hasSequenceFlow, userTaskList); + } + + // 根据类型,获取出口连线 + List 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 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 findChildProcessUserTasks(FlowElement source, Set hasSequenceFlow, List userTaskList) { + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList; + + // 根据类型,获取出口连线 + List 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 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 iteratorFindDirtyRoads(FlowElement source, List passRoads, Set hasSequenceFlow, List targets, Set 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 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 findChildProcessAllDirtyRoad(FlowElement source, Set hasSequenceFlow, Set dirtyRoads) { + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + dirtyRoads = dirtyRoads == null ? new HashSet<>() : dirtyRoads; + + // 根据类型,获取出口连线 + List 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 hasSequenceFlow, List targets, Boolean inChildProcess) { + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + inChildProcess = inChildProcess != null && inChildProcess; + + // 根据类型,获取出口连线 + List 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 hasSequenceFlow, Boolean isSequential) { + isSequential = isSequential == null || isSequential; + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow; + + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代 + if (source instanceof StartEvent && source.getSubProcess() != null) { + isSequential = iteratorCheckSequentialReferTarget(source.getSubProcess(), targetKsy, hasSequenceFlow, isSequential); + } + + // 根据类型,获取入口连线 + List sequenceFlows = getElementIncomingFlows(source); + + if (sequenceFlows != null) { + // 循环找到目标元素 + for (SequenceFlow sequenceFlow : sequenceFlows) { + // 如果发现连线重复,说明循环了,跳过这个循环 + if (hasSequenceFlow.contains(sequenceFlow.getId())) { + continue; + } + // 添加已经走过的连线 + hasSequenceFlow.add(sequenceFlow.getId()); + // 如果目标节点已被判断为并行,后面都不需要执行,直接返回 + if (!isSequential) { + 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> findRoad(FlowElement source, List passRoads, Set hasSequenceFlow, List> 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 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 historicTaskInstanceClean(Collection allElements, List historicTaskInstanceList) { + // 会签节点收集 + List 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 stack = new Stack<>(); + historicTaskInstanceList.forEach(stack::push); + // 清洗后的历史任务实例 + List lastHistoricTaskInstanceList = new ArrayList<>(); + // 网关存在可能只走了部分分支情况,且还存在跳转废弃数据以及其他分支数据的干扰,因此需要对历史节点数据进行清洗 + // 临时用户任务 key + StringBuilder userTaskKey = null; + // 临时被删掉的任务 key,存在并行情况 + List deleteKeyList = new ArrayList<>(); + // 临时脏数据线路 + List> 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 oldDirtyDataLine : dirtyDataLineList) { + if (oldDirtyDataLine.contains(stack.peek().getTaskDefinitionKey())) { + isDirtyData[0] = true; + } + } + // 删除原因不为空,说明从这条数据开始回跳或者回退的 + // MI_END:会签完成后,其他未签到节点的删除原因,不在处理范围内 + if (stack.peek().getDeleteReason() != null && !"MI_END".equals(stack.peek().getDeleteReason())) { + // 可以理解为脏线路起点 + String dirtyPoint = ""; + if (stack.peek().getDeleteReason().contains("Change activity to ")) { + dirtyPoint = stack.peek().getDeleteReason().replace("Change activity to ", ""); + } + // 会签回退删除原因有点不同 + if (stack.peek().getDeleteReason().contains("Change parent activity to ")) { + 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 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; + } + + /** + * 从 flowElement 获取 指定名称的 拓展元素 + * + * @param flowElement 元素 + * @param extensionElementName 拓展元素名称 + */ + public static ExtensionElement getExtensionElementFromFlowElementByName(FlowElement flowElement, String extensionElementName) { + + if (flowElement == null) { + return null; + } + Map> extensionElements = flowElement.getExtensionElements(); + for (Map.Entry> stringEntry : extensionElements.entrySet()) { + if (stringEntry.getKey().equals(extensionElementName)) { + for (ExtensionElement extensionElement : stringEntry.getValue()) { + if (extensionElement.getName().equals(extensionElementName)) { + return extensionElement; + } + } + } + } + + return null; + } + + /** + * 获取当前任务节点扩展属性信息 + * + * @param repositoryService + * @param task 当前任务 + * @return 自定义属性列表 + */ + public static List getPropertyElement(RepositoryService repositoryService, org.flowable.task.api.Task task) { + FlowElement flowElement = getCurrentElement(repositoryService, task); + ExtensionElement extensionElement = FlowableUtils.getExtensionElementFromFlowElementByName(flowElement, "properties"); + if (extensionElement == null) { + return Collections.emptyList(); + } + return getPropertyExtensionElementByName(extensionElement, "property"); + } + + /** + * 获取当前任务节点 + * + * @param repositoryService + * @param task + * @return + */ + public static FlowElement getCurrentElement(RepositoryService repositoryService, org.flowable.task.api.Task task) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); + return bpmnModel.getFlowElement(task.getTaskDefinitionKey()); + } + + /** + * 根据属性名获取扩展元素中的扩展属性列表 + * + * @param extensionElement 扩展元素 + * @param attributesName 属性名 + * @return 扩展属性列表 + */ + public static List getPropertyExtensionElementByName(ExtensionElement extensionElement, String attributesName) { + try { + // 获取名称为attributesName的子元素 + return Optional.ofNullable(extensionElement.getChildElements().get(attributesName)) + .orElse(Collections.emptyList()) // 如果子元素不存在则返回空集合,避免null引用 + .stream() + .map(element -> { + // 获取子元素的属性 + Map> attributes = element.getAttributes(); + Object propertyDto = new Object(); + // 获取FlowPropertyDto的所有属性 + Arrays.stream(propertyDto.getClass().getDeclaredFields()) + .forEach(field -> { + field.setAccessible(true); + // 获取属性名称和值 + attributes.getOrDefault(field.getName(), Collections.emptyList()) + .stream() + .findFirst() + .ifPresent(attribute -> { + try { + // 反射设置属性值 + field.set(propertyDto, attribute.getValue()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + // 如果反射设置失败则忽略该属性 + } + }); + }); + return propertyDto; + }).collect(Collectors.toList()); + } catch (Exception e) { + e.printStackTrace(); + return Collections.emptyList(); // 如果发生异常则返回空列表 + } + } + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/listener/FlowExecutionListener.java b/flowable/src/main/java/com/dite/znpt/flowable/listener/FlowExecutionListener.java new file mode 100644 index 0000000..514833b --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/listener/FlowExecutionListener.java @@ -0,0 +1,36 @@ +package com.dite.znpt.flowable.listener; + +import lombok.extern.slf4j.Slf4j; +import org.flowable.common.engine.api.delegate.Expression; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.ExecutionListener; +import org.springframework.stereotype.Component; + +/** + * 执行监听器 + * + * 执行监听器允许在执行过程中执行Java代码。 + * 执行监听器可以捕获事件的类型: + * 流程实例启动,结束 + * 输出流捕获 + * 获取启动,结束 + * 路由开始,结束 + * 中间事件开始,结束 + * 触发开始事件,触发结束事件 + * + * @author Tony + * @date 2022/12/16 + */ +@Slf4j +@Component +public class FlowExecutionListener implements ExecutionListener { + /** + * 流程设计器添加的参数 + */ + private Expression param; + + @Override + public void notify(DelegateExecution execution) { + log.info("执行监听器:{}", execution); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/listener/FlowTaskListener.java b/flowable/src/main/java/com/dite/znpt/flowable/listener/FlowTaskListener.java new file mode 100644 index 0000000..ec8b89f --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/listener/FlowTaskListener.java @@ -0,0 +1,32 @@ +package com.dite.znpt.flowable.listener; + +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.TaskListener; +import org.flowable.task.service.delegate.DelegateTask; +import org.springframework.stereotype.Component; + +/** + * 任务监听器 + * + * create(创建):在任务被创建且所有的任务属性设置完成后才触发 + * assignment(指派):在任务被分配给某个办理人之后触发 + * complete(完成):在配置了监听器的上一个任务完成时触发 + * delete(删除):在任务即将被删除前触发。请注意任务由completeTask正常完成时也会触发 + * + * @author Tony + * @date 2021/4/20 + */ +@Slf4j +@Component +public class FlowTaskListener implements TaskListener{ + + @Override + public void notify(DelegateTask delegateTask) { + + log.info("任务监听器:{}", delegateTask); + // TODO 获取事件类型 delegateTask.getEventName(),可以通过监听器给任务执行人发送相应的通知消息 + + + } + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysDeployFormMapper.java b/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysDeployFormMapper.java new file mode 100644 index 0000000..b5cc146 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysDeployFormMapper.java @@ -0,0 +1,73 @@ +package com.dite.znpt.flowable.mapper; + + +import com.dite.znpt.flowable.domain.entity.SysDeployForm; +import com.dite.znpt.flowable.domain.entity.SysForm; + +import java.util.List; + +/** + * 流程实例关联表单Mapper接口 + * + * @author Tony + * @date 2021-03-30 + */ +public interface SysDeployFormMapper +{ + /** + * 查询流程实例关联表单 + * + * @param id 流程实例关联表单ID + * @return 流程实例关联表单 + */ + public SysDeployForm selectSysDeployFormById(Long id); + + /** + * 查询流程实例关联表单列表 + * + * @param SysDeployForm 流程实例关联表单 + * @return 流程实例关联表单集合 + */ + public List selectSysDeployFormList(SysDeployForm SysDeployForm); + + /** + * 新增流程实例关联表单 + * + * @param SysDeployForm 流程实例关联表单 + * @return 结果 + */ + public int insertSysDeployForm(SysDeployForm SysDeployForm); + + /** + * 修改流程实例关联表单 + * + * @param SysDeployForm 流程实例关联表单 + * @return 结果 + */ + public int updateSysDeployForm(SysDeployForm SysDeployForm); + + /** + * 删除流程实例关联表单 + * + * @param id 流程实例关联表单ID + * @return 结果 + */ + public int deleteSysDeployFormById(Long id); + + /** + * 批量删除流程实例关联表单 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteSysDeployFormByIds(Long[] ids); + + + + /** + * 查询流程挂着的表单 + * @param deployId + * @return + */ + SysForm selectSysDeployFormByDeployId(String deployId); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysExpressionMapper.java b/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysExpressionMapper.java new file mode 100644 index 0000000..8156df3 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysExpressionMapper.java @@ -0,0 +1,63 @@ +package com.dite.znpt.flowable.mapper; + + +import com.dite.znpt.flowable.domain.entity.SysExpression; + +import java.util.List; + +/** + * 流程达式Mapper接口 + * + * @author ruoyi + * @date 2022-12-12 + */ +public interface SysExpressionMapper +{ + /** + * 查询流程达式 + * + * @param id 流程达式主键 + * @return 流程达式 + */ + public SysExpression selectSysExpressionById(Long id); + + /** + * 查询流程达式列表 + * + * @param sysExpression 流程达式 + * @return 流程达式集合 + */ + public List selectSysExpressionList(SysExpression sysExpression); + + /** + * 新增流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + public int insertSysExpression(SysExpression sysExpression); + + /** + * 修改流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + public int updateSysExpression(SysExpression sysExpression); + + /** + * 删除流程达式 + * + * @param id 流程达式主键 + * @return 结果 + */ + public int deleteSysExpressionById(Long id); + + /** + * 批量删除流程达式 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSysExpressionByIds(Long[] ids); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysFormMapper.java b/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysFormMapper.java new file mode 100644 index 0000000..9ee72ba --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysFormMapper.java @@ -0,0 +1,63 @@ +package com.dite.znpt.flowable.mapper; + + +import com.dite.znpt.flowable.domain.entity.SysForm; + +import java.util.List; + +/** + * 流程表单Mapper接口 + * + * @author Tony + * @date 2021-03-30 + */ +public interface SysFormMapper +{ + /** + * 查询流程表单 + * + * @param formId 流程表单ID + * @return 流程表单 + */ + public SysForm selectSysFormById(Long formId); + + /** + * 查询流程表单列表 + * + * @param sysForm 流程表单 + * @return 流程表单集合 + */ + public List selectSysFormList(SysForm sysForm); + + /** + * 新增流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + public int insertSysForm(SysForm sysForm); + + /** + * 修改流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + public int updateSysForm(SysForm sysForm); + + /** + * 删除流程表单 + * + * @param formId 流程表单ID + * @return 结果 + */ + public int deleteSysFormById(Long formId); + + /** + * 批量删除流程表单 + * + * @param formIds 需要删除的数据ID + * @return 结果 + */ + public int deleteSysFormByIds(Long[] formIds); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysListenerMapper.java b/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysListenerMapper.java new file mode 100644 index 0000000..10ffe5a --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/mapper/SysListenerMapper.java @@ -0,0 +1,62 @@ +package com.dite.znpt.flowable.mapper; + +import com.dite.znpt.flowable.domain.entity.SysListener; + +import java.util.List; + +/** + * 流程监听Mapper接口 + * + * @author Tony + * @date 2022-12-25 + */ +public interface SysListenerMapper +{ + /** + * 查询流程监听 + * + * @param id 流程监听主键 + * @return 流程监听 + */ + public SysListener selectSysListenerById(Long id); + + /** + * 查询流程监听列表 + * + * @param sysListener 流程监听 + * @return 流程监听集合 + */ + public List selectSysListenerList(SysListener sysListener); + + /** + * 新增流程监听 + * + * @param sysListener 流程监听 + * @return 结果 + */ + public int insertSysListener(SysListener sysListener); + + /** + * 修改流程监听 + * + * @param sysListener 流程监听 + * @return 结果 + */ + public int updateSysListener(SysListener sysListener); + + /** + * 删除流程监听 + * + * @param id 流程监听主键 + * @return 结果 + */ + public int deleteSysListenerById(Long id); + + /** + * 批量删除流程监听 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSysListenerByIds(Long[] ids); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowDefinitionService.java b/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowDefinitionService.java new file mode 100644 index 0000000..94d22d6 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowDefinitionService.java @@ -0,0 +1,80 @@ +package com.dite.znpt.flowable.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.dto.FlowProcDefDto; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +/** + * @author Tony + * @date 2021-04-03 14:41 + */ +public interface IFlowDefinitionService { + + boolean exist(String processDefinitionKey); + + + /** + * 流程定义列表 + * + * @param pageNum 当前页码 + * @param pageSize 每页条数 + * @return 流程定义分页列表数据 + */ + Page list(String name, Integer pageNum, Integer pageSize); + + /** + * 导入流程文件 + * 当每个key的流程第一次部署时,指定版本为1。对其后所有使用相同key的流程定义, + * 部署时版本会在该key当前已部署的最高版本号基础上加1。key参数用于区分流程定义 + * @param name + * @param category + * @param in + */ + void importFile(String name, String category, InputStream in); + + /** + * 读取xml + * @param deployId + * @return + */ + Result readXml(String deployId) throws IOException; + + /** + * 根据流程定义ID启动流程实例 + * + * @param procDefId + * @param variables + * @return + */ + + Result startProcessInstanceById(String procDefId, Map variables); + + + /** + * 激活或挂起流程定义 + * + * @param state 状态 + * @param deployId 流程部署ID + */ + void updateState(Integer state, String deployId); + + + /** + * 删除流程定义 + * + * @param deployId 流程部署ID act_ge_bytearray 表中 deployment_id值 + */ + void delete(String deployId); + + + /** + * 读取图片文件 + * @param deployId + * @return + */ + InputStream readImage(String deployId); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowInstanceService.java b/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowInstanceService.java new file mode 100644 index 0000000..7bc4b5d --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowInstanceService.java @@ -0,0 +1,53 @@ +package com.dite.znpt.flowable.service; + +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.vo.FlowTaskVo; +import org.flowable.engine.history.HistoricProcessInstance; +import java.util.Map; + +/** + * @author Tony + * @date 2021-04-03 14:40 + */ +public interface IFlowInstanceService { + + /** + * 结束流程实例 + * + * @param vo + */ + void stopProcessInstance(FlowTaskVo 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); + + /** + * 根据流程定义ID启动流程实例 + * + * @param procDefId 流程定义Id + * @param variables 流程变量 + * @return + */ + Result startProcessInstanceById(String procDefId, Map variables); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowTaskService.java b/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowTaskService.java new file mode 100644 index 0000000..226845b --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/IFlowTaskService.java @@ -0,0 +1,218 @@ +package com.dite.znpt.flowable.service; + +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.vo.FlowQueryVo; +import com.dite.znpt.flowable.domain.vo.FlowTaskVo; +import org.flowable.task.api.Task; + +import java.io.InputStream; +import java.util.List; + +/** + * @author Tony + * @date 2021-04-03 14:42 + */ +public interface IFlowTaskService { + + /** + * 审批任务 + * + * @param task 请求实体参数 + */ + Result complete(FlowTaskVo task); + + /** + * 驳回任务 + * + * @param flowTaskVo + */ + void taskReject(FlowTaskVo flowTaskVo); + + + /** + * 退回任务 + * + * @param flowTaskVo 请求实体参数 + */ + void taskReturn(FlowTaskVo flowTaskVo); + + /** + * 获取所有可回退的节点 + * + * @param flowTaskVo + * @return + */ + Result findReturnTaskList(FlowTaskVo flowTaskVo); + + /** + * 删除任务 + * + * @param flowTaskVo 请求实体参数 + */ + void deleteTask(FlowTaskVo flowTaskVo); + + /** + * 认领/签收任务 + * + * @param flowTaskVo 请求实体参数 + */ + void claim(FlowTaskVo flowTaskVo); + + /** + * 取消认领/签收任务 + * + * @param flowTaskVo 请求实体参数 + */ + void unClaim(FlowTaskVo flowTaskVo); + + /** + * 委派任务 + * + * @param flowTaskVo 请求实体参数 + */ + void delegateTask(FlowTaskVo flowTaskVo); + + /** + * 任务归还 + * + * @param flowTaskVo 请求实体参数 + */ + void resolveTask(FlowTaskVo flowTaskVo); + + + /** + * 转办任务 + * + * @param flowTaskVo 请求实体参数 + */ + void assignTask(FlowTaskVo flowTaskVo); + + + /** + * 多实例加签 + * @param flowTaskVo + */ + void addMultiInstanceExecution(FlowTaskVo flowTaskVo); + + /** + * 多实例减签 + * @param flowTaskVo + */ + void deleteMultiInstanceExecution(FlowTaskVo flowTaskVo); + + /** + * 我发起的流程 + * @param queryVo 请求参数 + * @return + */ + Result myProcess(FlowQueryVo queryVo); + + /** + * 取消申请 + * 目前实现方式: 直接将当前流程变更为已完成 + * @param flowTaskVo + * @return + */ + Result stopProcess(FlowTaskVo flowTaskVo); + + /** + * 撤回流程 + * @param flowTaskVo + * @return + */ + Result revokeProcess(FlowTaskVo flowTaskVo); + + + /** + * 代办任务列表 + * + * @param queryVo 请求参数 + * @return + */ + Result todoList(FlowQueryVo queryVo); + + + /** + * 已办任务列表 + * + * @param queryVo 请求参数 + * @return + */ + Result finishedList(FlowQueryVo queryVo); + + /** + * 流程历史流转记录 + * + * @param procInsId 流程实例Id + * @return + */ + Result flowRecord(String procInsId,String deployId); + + /** + * 根据任务ID查询挂载的表单信息 + * + * @param taskId 任务Id + * @return + */ + Result getTaskForm(String taskId); + + /** + * 获取流程过程图 + * @param processId + * @return + */ + InputStream diagram(String processId); + + /** + * 获取流程执行节点 + * @param procInsId + * @return + */ + Result getFlowViewer(String procInsId,String executionId); + + /** + * 获取流程变量 + * @param taskId + * @return + */ + Result processVariables(String taskId); + + /** + * 获取下一节点 + * @param flowTaskVo 任务 + * @return + */ + Result getNextFlowNode(FlowTaskVo flowTaskVo); + + Result getNextFlowNodeByStart(FlowTaskVo flowTaskVo); + + /** + * 流程初始化表单 + * @param deployId + * @return + */ + Result flowFormData(String deployId); + + /** + * 流程节点信息 + * @param procInsId + * @return + */ + Result flowXmlAndNode(String procInsId,String deployId); + + /** + * 流程节点表单 + * @param taskId 流程任务编号 + * @return + */ + Result flowTaskForm(String taskId) throws Exception; + + + /** + * 流程节点信息 + * @param procInsId + * @param elementId + * @return + */ + Result flowTaskInfo(String procInsId, String elementId); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/ISysDeployFormService.java b/flowable/src/main/java/com/dite/znpt/flowable/service/ISysDeployFormService.java new file mode 100644 index 0000000..d10ffee --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/ISysDeployFormService.java @@ -0,0 +1,70 @@ +package com.dite.znpt.flowable.service; + +import com.dite.znpt.flowable.domain.entity.SysDeployForm; +import com.dite.znpt.flowable.domain.entity.SysForm; + +import java.util.List; + +/** + * 流程实例关联表单Service接口 + * + * @author Tony + * @date 2021-04-03 + */ +public interface ISysDeployFormService +{ + /** + * 查询流程实例关联表单 + * + * @param id 流程实例关联表单ID + * @return 流程实例关联表单 + */ + public SysDeployForm selectSysDeployFormById(Long id); + + /** + * 查询流程实例关联表单列表 + * + * @param sysDeployForm 流程实例关联表单 + * @return 流程实例关联表单集合 + */ + public List selectSysDeployFormList(SysDeployForm sysDeployForm); + + /** + * 新增流程实例关联表单 + * + * @param sysDeployForm 流程实例关联表单 + * @return 结果 + */ + public int insertSysDeployForm(SysDeployForm sysDeployForm); + + /** + * 修改流程实例关联表单 + * + * @param sysDeployForm 流程实例关联表单 + * @return 结果 + */ + public int updateSysDeployForm(SysDeployForm sysDeployForm); + + /** + * 批量删除流程实例关联表单 + * + * @param ids 需要删除的流程实例关联表单ID + * @return 结果 + */ + public int deleteSysDeployFormByIds(Long[] ids); + + /** + * 删除流程实例关联表单信息 + * + * @param id 流程实例关联表单ID + * @return 结果 + */ + public int deleteSysDeployFormById(Long id); + + /** + * 查询流程挂着的表单 + * @param deployId + * @return + */ + SysForm selectSysDeployFormByDeployId(String deployId); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/ISysExpressionService.java b/flowable/src/main/java/com/dite/znpt/flowable/service/ISysExpressionService.java new file mode 100644 index 0000000..f41fcab --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/ISysExpressionService.java @@ -0,0 +1,63 @@ +package com.dite.znpt.flowable.service; + + +import com.dite.znpt.flowable.domain.entity.SysExpression; + +import java.util.List; + +/** + * 流程达式Service接口 + * + * @author ruoyi + * @date 2022-12-12 + */ +public interface ISysExpressionService +{ + /** + * 查询流程达式 + * + * @param id 流程达式主键 + * @return 流程达式 + */ + public SysExpression selectSysExpressionById(Long id); + + /** + * 查询流程达式列表 + * + * @param sysExpression 流程达式 + * @return 流程达式集合 + */ + public List selectSysExpressionList(SysExpression sysExpression); + + /** + * 新增流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + public int insertSysExpression(SysExpression sysExpression); + + /** + * 修改流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + public int updateSysExpression(SysExpression sysExpression); + + /** + * 批量删除流程达式 + * + * @param ids 需要删除的流程达式主键集合 + * @return 结果 + */ + public int deleteSysExpressionByIds(Long[] ids); + + /** + * 删除流程达式信息 + * + * @param id 流程达式主键 + * @return 结果 + */ + public int deleteSysExpressionById(Long id); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/ISysFormService.java b/flowable/src/main/java/com/dite/znpt/flowable/service/ISysFormService.java new file mode 100644 index 0000000..8e4ed68 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/ISysFormService.java @@ -0,0 +1,61 @@ +package com.dite.znpt.flowable.service; + +import com.dite.znpt.flowable.domain.entity.SysForm; + +import java.util.List; + +/** + * 表单 + * @author Tony + * @date 2021-04-03 + */ +public interface ISysFormService +{ + /** + * 查询流程表单 + * + * @param formId 流程表单ID + * @return 流程表单 + */ + public SysForm selectSysFormById(Long formId); + + /** + * 查询流程表单列表 + * + * @param sysForm 流程表单 + * @return 流程表单集合 + */ + public List selectSysFormList(SysForm sysForm); + + /** + * 新增流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + public int insertSysForm(SysForm sysForm); + + /** + * 修改流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + public int updateSysForm(SysForm sysForm); + + /** + * 批量删除流程表单 + * + * @param formIds 需要删除的流程表单ID + * @return 结果 + */ + public int deleteSysFormByIds(Long[] formIds); + + /** + * 删除流程表单信息 + * + * @param formId 流程表单ID + * @return 结果 + */ + public int deleteSysFormById(Long formId); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/ISysListenerService.java b/flowable/src/main/java/com/dite/znpt/flowable/service/ISysListenerService.java new file mode 100644 index 0000000..006d41f --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/ISysListenerService.java @@ -0,0 +1,63 @@ +package com.dite.znpt.flowable.service; + + +import com.dite.znpt.flowable.domain.entity.SysListener; + +import java.util.List; + +/** + * 流程监听Service接口 + * + * @author Tony + * @date 2022-12-25 + */ +public interface ISysListenerService +{ + /** + * 查询流程监听 + * + * @param id 流程监听主键 + * @return 流程监听 + */ + public SysListener selectSysListenerById(Long id); + + /** + * 查询流程监听列表 + * + * @param sysListener 流程监听 + * @return 流程监听集合 + */ + public List selectSysListenerList(SysListener sysListener); + + /** + * 新增流程监听 + * + * @param sysListener 流程监听 + * @return 结果 + */ + public int insertSysListener(SysListener sysListener); + + /** + * 修改流程监听 + * + * @param sysListener 流程监听 + * @return 结果 + */ + public int updateSysListener(SysListener sysListener); + + /** + * 批量删除流程监听 + * + * @param ids 需要删除的流程监听主键集合 + * @return 结果 + */ + public int deleteSysListenerByIds(Long[] ids); + + /** + * 删除流程监听信息 + * + * @param id 流程监听主键 + * @return 结果 + */ + public int deleteSysListenerById(Long id); +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowDefinitionServiceImpl.java b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowDefinitionServiceImpl.java new file mode 100644 index 0000000..b64e696 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowDefinitionServiceImpl.java @@ -0,0 +1,241 @@ +package com.dite.znpt.flowable.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.dto.FlowProcDefDto; +import com.dite.znpt.flowable.domain.entity.SysForm; +import com.dite.znpt.domain.vo.UserInfo; +import com.dite.znpt.flowable.common.constant.ProcessConstants; +import com.dite.znpt.flowable.common.enums.FlowComment; +import com.dite.znpt.flowable.factory.FlowServiceFactory; +import com.dite.znpt.flowable.service.IFlowDefinitionService; +import com.dite.znpt.flowable.service.ISysDeployFormService; +import com.dite.znpt.mapper.FlowDeployMapper; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.flowable.bpmn.model.BpmnModel; +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.image.impl.DefaultProcessDiagramGenerator; +import org.flowable.task.api.Task; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 流程定义 + * + * @author Tony + * @date 2021-04-03 + */ +@Service +@Slf4j +public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFlowDefinitionService { + + @Resource + private ISysDeployFormService sysDeployFormService; + + @Resource + private FlowDeployMapper flowDeployMapper; + + private static final String BPMN_FILE_SUFFIX = ".bpmn"; + + @Override + public boolean exist(String processDefinitionKey) { + ProcessDefinitionQuery processDefinitionQuery + = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey); + long count = processDefinitionQuery.count(); + return count > 0 ? true : false; + } + + + /** + * 流程定义列表 + * + * @param pageNum 当前页码 + * @param pageSize 每页条数 + * @return 流程定义分页列表数据 + */ + @Override + public Page list(String name, Integer pageNum, Integer pageSize) { + Page page = new Page<>(); +// // 流程定义列表数据查询 +// final ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); +// if (StringUtils.isNotEmpty(name)) { +// processDefinitionQuery.processDefinitionNameLike(name); +// } +//// processDefinitionQuery.orderByProcessDefinitionKey().asc(); +// page.setTotal(processDefinitionQuery.count()); +// List processDefinitionList = processDefinitionQuery.listPage(pageSize * (pageNum - 1), pageSize); +// +// List dataList = new ArrayList<>(); +// for (ProcessDefinition processDefinition : processDefinitionList) { +// String deploymentId = processDefinition.getDeploymentId(); +// Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); +// FlowProcDefDto reProcDef = new FlowProcDefDto(); +// BeanUtils.copyProperties(processDefinition, reProcDef); +// SysForm sysForm = sysDeployFormService.selectSysDeployFormByDeployId(deploymentId); +// if (Objects.nonNull(sysForm)) { +// reProcDef.setFormName(sysForm.getFormName()); +// reProcDef.setFormId(sysForm.getFormId()); +// } +// // 流程定义时间 +// reProcDef.setDeploymentTime(deployment.getDeploymentTime()); +// dataList.add(reProcDef); +// } + PageHelper.startPage(pageNum, pageSize); + final List dataList = flowDeployMapper.selectDeployList(name); + // 加载挂表单 + for (FlowProcDefDto procDef : dataList) { + SysForm sysForm = sysDeployFormService.selectSysDeployFormByDeployId(procDef.getDeploymentId()); + if (Objects.nonNull(sysForm)) { + procDef.setFormName(sysForm.getFormName()); + procDef.setFormId(sysForm.getFormId()); + } + } + page.setTotal(new PageInfo(dataList).getTotal()); + page.setRecords(dataList); + return page; + } + + + /** + * 导入流程文件 + * + * 当每个key的流程第一次部署时,指定版本为1。对其后所有使用相同key的流程定义, + * 部署时版本会在该key当前已部署的最高版本号基础上加1。key参数用于区分流程定义 + * @param name + * @param category + * @param in + */ + @Override + public void importFile(String name, String category, InputStream in) { + Deployment deploy = repositoryService.createDeployment().addInputStream(name + BPMN_FILE_SUFFIX, in).name(name).category(category).deploy(); + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult(); + repositoryService.setProcessDefinitionCategory(definition.getId(), category); + + } + + /** + * 读取xml + * + * @param deployId + * @return + */ + @Override + public Result readXml(String deployId) throws IOException { + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName()); + String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name()); + return Result.okM(result,""); + } + + /** + * 读取xml + * + * @param deployId + * @return + */ + @Override + public InputStream readImage(String deployId) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + //获得图片流 + DefaultProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); + //输出为图片 + return diagramGenerator.generateDiagram( + bpmnModel, + "png", + Collections.emptyList(), + Collections.emptyList(), + "宋体", + "宋体", + "宋体", + null, + 1.0, + false); + + } + + /** + * 根据流程定义ID启动流程实例 + * + * @param procDefId 流程模板ID + * @param variables 流程变量 + * @return + */ + @Override + public Result startProcessInstanceById(String procDefId, Map variables) { + try { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId) + .latestVersion().singleResult(); + if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) { + return Result.error("流程已被挂起,请先激活流程"); + } + // 设置流程发起人Id到流程中 + UserInfo userInfo = (UserInfo)StpUtil.getSession().get("userInfo"); + identityService.setAuthenticatedUserId(userInfo.getUser().getUserId()); + variables.put(ProcessConstants.PROCESS_INITIATOR, userInfo.getUser().getUserId()); + + // 流程发起时 跳过发起人节点 + ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables); + // 给第一步申请人节点设置任务执行人和意见 + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult(); + if (Objects.nonNull(task)) { + taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), userInfo.getUser().getName() + "发起流程申请"); + taskService.complete(task.getId(), variables); + } + return Result.okM("流程启动成功"); + } catch (Exception e) { + e.printStackTrace(); + return Result.error("流程启动错误"); + } + } + + + /** + * 激活或挂起流程定义 + * + * @param state 状态 + * @param deployId 流程部署ID + */ + @Override + public void updateState(Integer state, String deployId) { + ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + // 激活 + if (state == 1) { + repositoryService.activateProcessDefinitionById(procDef.getId(), true, null); + } + // 挂起 + if (state == 2) { + repositoryService.suspendProcessDefinitionById(procDef.getId(), true, null); + } + } + + + /** + * 删除流程定义 + * + * @param deployId 流程部署ID act_ge_bytearray 表中 deployment_id值 + */ + @Override + public void delete(String deployId) { + // true 允许级联删除 ,不设置会导致数据库外键关联异常 + repositoryService.deleteDeployment(deployId, true); + } + + +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowInstanceServiceImpl.java b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowInstanceServiceImpl.java new file mode 100644 index 0000000..c44b24e --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowInstanceServiceImpl.java @@ -0,0 +1,119 @@ +package com.dite.znpt.flowable.service.impl; + + +import cn.dev33.satoken.stp.StpUtil; +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.vo.FlowTaskVo; +import com.dite.znpt.flowable.factory.FlowServiceFactory; +import com.dite.znpt.flowable.service.IFlowInstanceService; +import lombok.extern.slf4j.Slf4j; +import org.flowable.common.engine.api.FlowableObjectNotFoundException; +import org.flowable.engine.history.HistoricProcessInstance; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Map; +import java.util.Objects; + +/** + *

工作流流程实例管理

+ * + * @author Tony + * @date 2021-04-03 + */ +@Service +@Slf4j +public class FlowInstanceServiceImpl extends FlowServiceFactory implements IFlowInstanceService { + + /** + * 结束流程实例 + * + * @param vo + */ + @Override + public void stopProcessInstance(FlowTaskVo 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; + } + + /** + * 根据流程定义ID启动流程实例 + * + * @param procDefId 流程定义Id + * @param variables 流程变量 + * @return + */ + @Override + public Result startProcessInstanceById(String procDefId, Map variables) { + + try { + // 设置流程发起人Id到流程中 + Long userId = Long.valueOf(StpUtil.getLoginId().toString()); +// identityService.setAuthenticatedUserId(userId.toString()); + variables.put("initiator",userId); + variables.put("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true); + runtimeService.startProcessInstanceById(procDefId, variables); + return Result.ok("流程启动成功"); + } catch (Exception e) { + e.printStackTrace(); + return Result.error("流程启动错误"); + } + } +} \ No newline at end of file diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowTaskServiceImpl.java b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowTaskServiceImpl.java new file mode 100644 index 0000000..042d53a --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/FlowTaskServiceImpl.java @@ -0,0 +1,1266 @@ +package com.dite.znpt.flowable.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.TypeReference; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.dite.znpt.domain.Result; +import com.dite.znpt.flowable.domain.entity.SysForm; +import com.dite.znpt.domain.vo.RoleResp; +import com.dite.znpt.domain.vo.UserInfo; +import com.dite.znpt.domain.vo.UserResp; +import com.dite.znpt.exception.ServiceException; +import com.dite.znpt.flowable.common.constant.ProcessConstants; +import com.dite.znpt.flowable.common.enums.FlowComment; +import com.dite.znpt.flowable.domain.dto.FlowCommentDto; +import com.dite.znpt.flowable.domain.dto.FlowNextDto; +import com.dite.znpt.flowable.domain.dto.FlowTaskDto; +import com.dite.znpt.flowable.domain.dto.FlowViewerDto; +import com.dite.znpt.flowable.domain.vo.FlowQueryVo; +import com.dite.znpt.flowable.domain.vo.FlowTaskVo; +import com.dite.znpt.flowable.factory.FlowServiceFactory; +import com.dite.znpt.flowable.flow.CustomProcessDiagramGenerator; +import com.dite.znpt.flowable.flow.FindNextNodeUtil; +import com.dite.znpt.flowable.flow.FlowableUtils; +import com.dite.znpt.flowable.service.IFlowTaskService; +import com.dite.znpt.flowable.service.ISysDeployFormService; +import com.dite.znpt.flowable.service.ISysFormService; +import com.dite.znpt.service.RoleService; +import com.dite.znpt.service.UserService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +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.engine.ProcessEngineConfiguration; +import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.history.HistoricProcessInstanceQuery; +import org.flowable.engine.impl.cmd.AddMultiInstanceExecutionCmd; +import org.flowable.engine.impl.cmd.DeleteMultiInstanceExecutionCmd; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.engine.runtime.Execution; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.engine.task.Comment; +import org.flowable.identitylink.api.history.HistoricIdentityLink; +import org.flowable.image.ProcessDiagramGenerator; +import org.flowable.task.api.DelegationState; +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.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * @author Tony + * @date 2021-04-03 + **/ +@Service +@Slf4j +public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTaskService { + @Resource + private ISysDeployFormService sysInstanceFormService; + @Resource + private ISysFormService sysFormService; + @Resource + private UserService userService; + + @Resource + private RoleService roleService; + + /** + * 完成任务 + * + * @param taskVo 请求实体参数 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public Result complete(FlowTaskVo taskVo) { + Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult(); + if (Objects.isNull(task)) { + return Result.error("任务不存在"); + } + if (DelegationState.PENDING.equals(task.getDelegationState())) { + taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment()); + taskService.resolveTask(taskVo.getTaskId(), taskVo.getVariables()); + } else { + taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment()); + UserInfo userInfo = (UserInfo) StpUtil.getSession().get("userInfo"); + taskService.setAssignee(taskVo.getTaskId(), userInfo.getUser().getUserId()); + taskService.complete(taskVo.getTaskId(), taskVo.getVariables()); + } + return Result.ok(); + } + + /** + * 驳回任务 + * + * @param flowTaskVo + */ + @Override + public void taskReject(FlowTaskVo flowTaskVo) { + if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { + throw new ServiceException("任务处于挂起状态!"); + } + // 当前任务 task + Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + // 获取流程定义信息 + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); + // 获取所有节点信息 + Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); + // 获取全部节点列表,包含子节点 + Collection allElements = FlowableUtils.getAllElements(process.getFlowElements(), null); + // 获取当前任务节点元素 + FlowElement source = null; + if (allElements != null) { + for (FlowElement flowElement : allElements) { + // 类型为用户节点 + if (flowElement.getId().equals(task.getTaskDefinitionKey())) { + // 获取节点信息 + source = flowElement; + } + } + } + + // 目的获取所有跳转到的节点 targetIds + // 获取当前节点的所有父级用户任务节点 + // 深度优先算法思想:延边迭代深入 + List parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null); + if (parentUserTaskList == null || parentUserTaskList.size() == 0) { + throw new ServiceException("当前节点为初始任务节点,不能驳回"); + } + // 获取活动 ID 即节点 Key + List parentUserTaskKeyList = new ArrayList<>(); + parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId())); + // 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序 + List historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list(); + // 数据清洗,将回滚导致的脏数据清洗掉 + List lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList); + // 此时历史任务实例为倒序,获取最后走的节点 + List targetIds = new ArrayList<>(); + // 循环结束标识,遇到当前目标节点的次数 + int number = 0; + StringBuilder parentHistoricTaskKey = new StringBuilder(); + for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) { + // 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过 + if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) { + continue; + } + parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey); + if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) { + number++; + } + // 在数据清洗后,历史节点就是唯一一条从起始到当前节点的历史记录,理论上每个点只会出现一次 + // 在流程中如果出现循环,那么每次循环中间的点也只会出现一次,再出现就是下次循环 + // number == 1,第一次遇到当前节点 + // number == 2,第二次遇到,代表最后一次的循环范围 + if (number == 2) { + break; + } + // 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点 + if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) { + targetIds.add(historicTaskInstanceKey); + } + } + + + // 目的获取所有需要被跳转的节点 currentIds + // 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路 + UserTask oneUserTask = parentUserTaskList.get(0); + // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务 + List runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); + List runTaskKeyList = new ArrayList<>(); + runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); + // 需驳回任务列表 + List currentIds = new ArrayList<>(); + // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务 + List currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null); + currentUserTaskList.forEach(item -> currentIds.add(item.getId())); + + + // 规定:并行网关之前节点必须需存在唯一用户任务节点,如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况 + if (targetIds.size() > 1 && currentIds.size() > 1) { + throw new ServiceException("任务出现多对多情况,无法撤回"); + } + + // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因 + List currentTaskIds = new ArrayList<>(); + currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { + if (currentId.equals(runTask.getTaskDefinitionKey())) { + currentTaskIds.add(runTask.getId()); + } + })); + // 设置驳回意见 + currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment())); + + try { + // 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况 + if (targetIds.size() > 1) { + // 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多) + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(task.getProcessInstanceId()). + moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState(); + } + // 如果父级任务只有一个,因此当前任务可能为网关中的任务 + if (targetIds.size() == 1) { + // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1) + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(task.getProcessInstanceId()) + .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState(); + } + } catch (FlowableObjectNotFoundException e) { + throw new ServiceException("未找到流程实例,流程可能已发生变化"); + } catch (FlowableException e) { + throw new ServiceException("无法取消或开始活动"); + } + + } + + /** + * 退回任务 + * + * @param flowTaskVo 请求实体参数 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public void taskReturn(FlowTaskVo flowTaskVo) { + if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { + throw new ServiceException("任务处于挂起状态"); + } + // 当前任务 task + Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + // 获取流程定义信息 + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); + // 获取所有节点信息 + Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); + // 获取全部节点列表,包含子节点 + Collection allElements = FlowableUtils.getAllElements(process.getFlowElements(), null); + // 获取当前任务节点元素 + FlowElement source = null; + // 获取跳转的节点元素 + FlowElement target = null; + if (allElements != null) { + for (FlowElement flowElement : allElements) { + // 当前任务节点元素 + if (flowElement.getId().equals(task.getTaskDefinitionKey())) { + source = flowElement; + } + // 跳转的节点元素 + if (flowElement.getId().equals(flowTaskVo.getTargetKey())) { + target = flowElement; + } + } + } + + // 从当前节点向前扫描 + // 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转 + // 否则目标节点相对于当前节点,属于串行 + Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null); + if (!isSequential) { + throw new ServiceException("当前节点相对于目标节点,不属于串行关系,无法回退"); + } + + + // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务 + List runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); + List runTaskKeyList = new ArrayList<>(); + runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); + // 需退回任务列表 + List currentIds = new ArrayList<>(); + // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务 + List currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null); + currentUserTaskList.forEach(item -> currentIds.add(item.getId())); + + // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因 + List currentTaskIds = new ArrayList<>(); + currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { + if (currentId.equals(runTask.getTaskDefinitionKey())) { + currentTaskIds.add(runTask.getId()); + } + })); + // 设置回退意见 + currentTaskIds.forEach(currentTaskId -> taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment())); + + try { + // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetKey 跳转到的节点(1) + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(task.getProcessInstanceId()) + .moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState(); + } catch (FlowableObjectNotFoundException e) { + throw new ServiceException("未找到流程实例,流程可能已发生变化"); + } catch (FlowableException e) { + throw new ServiceException("无法取消或开始活动"); + } + } + + + /** + * 获取所有可回退的节点 + * + * @param flowTaskVo + * @return + */ + @Override + public Result findReturnTaskList(FlowTaskVo flowTaskVo) { + // 当前任务 task + Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + // 获取流程定义信息 + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); + // 获取所有节点信息,暂不考虑子流程情况 + Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); + Collection flowElements = process.getFlowElements(); + // 获取当前任务节点元素 + UserTask source = null; + if (flowElements != null) { + for (FlowElement flowElement : flowElements) { + // 类型为用户节点 + if (flowElement.getId().equals(task.getTaskDefinitionKey())) { + source = (UserTask) flowElement; + } + } + } + // 获取节点的所有路线 + List> roads = FlowableUtils.findRoad(source, null, null, null); + // 可回退的节点列表 + List userTaskList = new ArrayList<>(); + for (List road : roads) { + if (userTaskList.size() == 0) { + // 还没有可回退节点直接添加 + userTaskList = road; + } else { + // 如果已有回退节点,则比对取交集部分 + userTaskList.retainAll(road); + } + } + return Result.ok(userTaskList); + } + + /** + * 删除任务 + * + * @param flowTaskVo 请求实体参数 + */ + @Override + public void deleteTask(FlowTaskVo flowTaskVo) { + // todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过? + taskService.deleteTask(flowTaskVo.getTaskId(), flowTaskVo.getComment()); + } + + /** + * 认领/签收任务 + * 认领以后,这个用户就会成为任务的执行人,任务会从其他成员的任务列表中消失 + * + * @param flowTaskVo 请求实体参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void claim(FlowTaskVo flowTaskVo) { + taskService.claim(flowTaskVo.getTaskId(), flowTaskVo.getUserId()); + } + + /** + * 取消认领/签收任务 + * + * @param flowTaskVo 请求实体参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void unClaim(FlowTaskVo flowTaskVo) { + taskService.unclaim(flowTaskVo.getTaskId()); + } + + /** + * 委派任务 + * 任务委派只是委派人将当前的任务交给被委派人进行审批,处理任务后又重新回到委派人身上。 + * + * @param flowTaskVo 请求实体参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void delegateTask(FlowTaskVo flowTaskVo) { + taskService.delegateTask(flowTaskVo.getTaskId(), flowTaskVo.getAssignee()); + } + + /** + * 任务归还 + * 被委派人完成任务之后,将任务归还委派人 + * + * @param flowTaskVo 请求实体参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void resolveTask(FlowTaskVo flowTaskVo) { + taskService.resolveTask(flowTaskVo.getTaskId()); + } + + + /** + * 转办任务 + * 直接将办理人换成别人,这时任务的拥有者不再是转办人 + * + * @param flowTaskVo 请求实体参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void assignTask(FlowTaskVo flowTaskVo) { + // 直接转派就可以覆盖掉之前的 + taskService.setAssignee(flowTaskVo.getTaskId(), flowTaskVo.getAssignee()); +// // 删除指派人重新指派 +// taskService.deleteCandidateUser(flowTaskVo.getTaskId(),flowTaskVo.getAssignee()); +// taskService.addCandidateUser(flowTaskVo.getTaskId(),flowTaskVo.getAssignee()); +// // 如果要查询转给他人处理的任务,可以同时将OWNER进行设置: +// taskService.setOwner(flowTaskVo.getTaskId(), flowTaskVo.getAssignee()); + + } + + /** + * 多实例加签 + * act_ru_task、act_ru_identitylink各生成一条记录 + * + * @param flowTaskVo + */ + @Override + public void addMultiInstanceExecution(FlowTaskVo flowTaskVo) { + managementService.executeCommand(new AddMultiInstanceExecutionCmd(flowTaskVo.getDefId(), flowTaskVo.getInstanceId(), flowTaskVo.getVariables())); + } + + /** + * 多实例减签 + * act_ru_task减1、act_ru_identitylink不变 + * + * @param flowTaskVo + */ + @Override + public void deleteMultiInstanceExecution(FlowTaskVo flowTaskVo) { + managementService.executeCommand(new DeleteMultiInstanceExecutionCmd(flowTaskVo.getCurrentChildExecutionId(), flowTaskVo.getFlag())); + } + + /** + * 我发起的流程 + * + * @param queryVo 请求参数 + * @return + */ + @Override + public Result myProcess(FlowQueryVo queryVo) { + Page page = new Page<>(); + UserInfo userInfo = (UserInfo)StpUtil.getSession().get("userInfo"); + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery() + .startedBy(userInfo.getUser().getUserId()) + .orderByProcessInstanceStartTime() + .desc(); + List historicProcessInstances = historicProcessInstanceQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize()); + page.setTotal(historicProcessInstanceQuery.count()); + List flowList = new ArrayList<>(); + for (HistoricProcessInstance hisIns : historicProcessInstances) { + FlowTaskDto flowTask = new FlowTaskDto(); + flowTask.setCreateTime(hisIns.getStartTime()); + flowTask.setFinishTime(hisIns.getEndTime()); + flowTask.setProcInsId(hisIns.getId()); + + // 计算耗时 + if (Objects.nonNull(hisIns.getEndTime())) { + long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime(); + flowTask.setDuration(getDate(time)); + } else { + long time = System.currentTimeMillis() - hisIns.getStartTime().getTime(); + flowTask.setDuration(getDate(time)); + } + // 流程定义信息 + ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(hisIns.getProcessDefinitionId()) + .singleResult(); + flowTask.setDeployId(pd.getDeploymentId()); + flowTask.setProcDefName(pd.getName()); + flowTask.setProcDefVersion(pd.getVersion()); + flowTask.setCategory(pd.getCategory()); + flowTask.setProcDefVersion(pd.getVersion()); + // 当前所处流程 + List taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list(); + if (CollectionUtils.isNotEmpty(taskList)) { + flowTask.setTaskId(taskList.get(0).getId()); + flowTask.setTaskName(taskList.get(0).getName()); + if (StringUtils.isNotBlank(taskList.get(0).getAssignee())) { + // 当前任务节点办理人信息 + UserResp user = userService.detail(taskList.get(0).getAssignee()); + if (Objects.nonNull(user)) { + flowTask.setAssigneeId(user.getUserId()); + flowTask.setAssigneeName(user.getName()); + flowTask.setAssigneeDeptName(StrUtil.isNotBlank(user.getDeptName()) ? user.getDeptName() : ""); + } + } + } else { + List historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list(); + flowTask.setTaskId(historicTaskInstance.get(0).getId()); + flowTask.setTaskName(historicTaskInstance.get(0).getName()); + if (StringUtils.isNotBlank(historicTaskInstance.get(0).getAssignee())) { + // 当前任务节点办理人信息 + UserResp user = userService.detail(historicTaskInstance.get(0).getAssignee()); + if (Objects.nonNull(user)) { + flowTask.setAssigneeId(user.getUserId()); + flowTask.setAssigneeName(user.getName()); + flowTask.setAssigneeDeptName(StrUtil.isNotBlank(user.getDeptName()) ? user.getDeptName() : ""); + } + } + } + flowList.add(flowTask); + } + page.setRecords(flowList); + return Result.ok(page); + } + + /** + * 取消申请 + * 目前实现方式: 直接将当前流程变更为已完成 + * + * @param flowTaskVo + * @return + */ + @Override + public Result stopProcess(FlowTaskVo flowTaskVo) { + List task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).list(); + if (CollectionUtils.isEmpty(task)) { + throw new ServiceException("流程未启动或已执行完成,取消申请失败"); + } + // 获取当前流程实例 + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() + .processInstanceId(flowTaskVo.getInstanceId()) + .singleResult(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); + if (Objects.nonNull(bpmnModel)) { + Process process = bpmnModel.getMainProcess(); + List endNodes = process.findFlowElementsOfType(EndEvent.class, false); + if (CollectionUtils.isNotEmpty(endNodes)) { + // TODO 取消流程为什么要设置流程发起人? +// SysUser loginUser = SecurityUtils.getLoginUser().getUser(); +// Authentication.setAuthenticatedUserId(loginUser.getUserId().toString()); + +// taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.STOP.getType(), +// StringUtils.isBlank(flowTaskVo.getComment()) ? "取消申请" : flowTaskVo.getComment()); + // 获取当前流程最后一个节点 + String endId = endNodes.get(0).getId(); + List executions = runtimeService.createExecutionQuery() + .parentId(processInstance.getProcessInstanceId()).list(); + List executionIds = new ArrayList<>(); + executions.forEach(execution -> executionIds.add(execution.getId())); + // 变更流程为已结束状态 + runtimeService.createChangeActivityStateBuilder() + .moveExecutionsToSingleActivityId(executionIds, endId).changeState(); + } + } + + return Result.ok(); + } + + /** + * 撤回流程 目前存在错误 + * + * @param flowTaskVo + * @return + */ + @Override + public Result revokeProcess(FlowTaskVo flowTaskVo) { + Task task = taskService.createTaskQuery() + .processInstanceId(flowTaskVo.getInstanceId()) + .singleResult(); + if (task == null) { + throw new ServiceException("流程未启动或已执行完成,无法撤回"); + } + + UserInfo userInfo = (UserInfo)StpUtil.getSession().get("userInfo"); + List htiList = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(task.getProcessInstanceId()) + .orderByTaskCreateTime() + .asc() + .list(); + String myTaskId = null; + for (HistoricTaskInstance hti : htiList) { + if (userInfo.getUser().getUserId().toString().equals(hti.getAssignee())) { + myTaskId = hti.getId(); + break; + } + } + if (null == myTaskId) { + throw new ServiceException("该任务非当前用户提交,无法撤回"); + } + List historicTaskInstanceList = historyService + .createHistoricTaskInstanceQuery() + .processInstanceId(task.getProcessInstanceId()) + .orderByHistoricTaskInstanceStartTime() + .asc() + .list(); + Iterator it = historicTaskInstanceList.iterator(); + //循环节点,获取当前节点的上一节点的key + String tarKey = ""; + while (it.hasNext()) { + HistoricTaskInstance his = it.next(); + if (!task.getTaskDefinitionKey().equals(his.getTaskDefinitionKey())) { + tarKey = his.getTaskDefinitionKey(); + } + } + // 跳转节点 + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(flowTaskVo.getInstanceId()) + .moveActivityIdTo(task.getTaskDefinitionKey(), tarKey) + .changeState(); + + return Result.ok(); + } + + /** + * 代办任务列表 + * + * @param queryVo 请求参数 + * @return + */ + @Override + public Result todoList(FlowQueryVo queryVo) { + Page page = new Page<>(); + // 只查看自己的数据 + UserInfo userInfo = (UserInfo)StpUtil.getSession().get("userInfo"); + TaskQuery taskQuery = taskService.createTaskQuery() + .active() + .includeProcessVariables() + .taskCandidateGroupIn(userInfo.getRoles().stream().map(role -> role.getRoleId().toString()).collect(Collectors.toList())) + .taskCandidateOrAssigned(userInfo.getUser().getUserId().toString()) + .orderByTaskCreateTime().desc(); + +// TODO 传入名称查询不到数据? + if (StringUtils.isNotBlank(queryVo.getName())) { + taskQuery.processDefinitionNameLike(queryVo.getName()); + } + page.setTotal(taskQuery.count()); + List taskList = taskQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize()); + List flowList = new ArrayList<>(); + for (Task task : taskList) { + FlowTaskDto flowTask = new FlowTaskDto(); + // 当前流程信息 + flowTask.setTaskId(task.getId()); + flowTask.setTaskDefKey(task.getTaskDefinitionKey()); + flowTask.setCreateTime(task.getCreateTime()); + flowTask.setProcDefId(task.getProcessDefinitionId()); + flowTask.setExecutionId(task.getExecutionId()); + 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(); + UserResp startUser = userService.detail(historicProcessInstance.getStartUserId()); + flowTask.setStartUserId(startUser.getUserId().toString()); + flowTask.setStartUserName(startUser.getName()); + flowTask.setStartDeptName(StrUtil.isNotBlank(startUser.getDeptName()) ? startUser.getDeptName() : ""); + flowList.add(flowTask); + } + + page.setRecords(flowList); + return Result.ok(page); + } + + + /** + * 已办任务列表 + * + * @param queryVo 请求参数 + * @return + */ + @Override + public Result finishedList(FlowQueryVo queryVo) { + Page page = new Page<>(); + UserInfo userInfo = (UserInfo)StpUtil.getSession().get("userInfo"); + HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() + .includeProcessVariables() + .finished() + .taskAssignee(userInfo.getUser().getUserId().toString()) + .orderByHistoricTaskInstanceEndTime() + .desc(); + List historicTaskInstanceList = taskInstanceQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize()); + List hisTaskList = new ArrayList<>(); + for (HistoricTaskInstance histTask : historicTaskInstanceList) { + FlowTaskDto flowTask = new FlowTaskDto(); + // 当前流程信息 + flowTask.setTaskId(histTask.getId()); + // 审批人员信息 + flowTask.setCreateTime(histTask.getCreateTime()); + flowTask.setFinishTime(histTask.getEndTime()); + flowTask.setDuration(getDate(histTask.getDurationInMillis())); + 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(); + UserResp startUser = userService.detail(historicProcessInstance.getStartUserId()); + flowTask.setStartUserId(startUser.getUserId()); + flowTask.setStartUserName(startUser.getName()); + flowTask.setStartDeptName(StrUtil.isNotBlank(startUser.getDeptName()) ? startUser.getDeptName() : ""); + hisTaskList.add(flowTask); + } + page.setTotal(taskInstanceQuery.count()); + page.setRecords(hisTaskList); + return Result.ok(page); + } + + private static Predicate distinctByKey(Function keyExtractor) { + Set seen = ConcurrentHashMap.newKeySet(); + return t -> seen.add(keyExtractor.apply(t)); + } + + /** + * 流程历史流转记录 + * + * @param procInsId 流程实例Id + * @return + */ + @Override + public Result flowRecord(String procInsId, String deployId) { + Map map = new HashMap(); + if (StringUtils.isNotBlank(procInsId)) { + List list = historyService + .createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .orderByHistoricActivityInstanceStartTime() + .desc().list(); + List hisFlowList = new ArrayList<>(); + for (HistoricActivityInstance histIns : list) { + // 展示开始节点 +// if ("startEvent".equals(histIns.getActivityType())) { +// FlowTaskDto flowTask = new FlowTaskDto(); +// // 流程发起人信息 +// HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() +// .processInstanceId(histIns.getProcessInstanceId()) +// .singleResult(); +// SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId())); +// flowTask.setTaskName(startUser.getNickName() + "(" + startUser.getDept().getDeptName() + ")发起申请"); +// flowTask.setFinishTime(histIns.getEndTime()); +// hisFlowList.add(flowTask); +// } else if ("endEvent".equals(histIns.getActivityType())) { +// FlowTaskDto flowTask = new FlowTaskDto(); +// flowTask.setTaskName(StringUtils.isNotBlank(histIns.getActivityName()) ? histIns.getActivityName() : "结束"); +// flowTask.setFinishTime(histIns.getEndTime()); +// hisFlowList.add(flowTask); +// } else + if (StringUtils.isNotBlank(histIns.getTaskId())) { + FlowTaskDto flowTask = new FlowTaskDto(); + flowTask.setTaskId(histIns.getTaskId()); + flowTask.setTaskName(histIns.getActivityName()); + flowTask.setCreateTime(histIns.getStartTime()); + flowTask.setFinishTime(histIns.getEndTime()); + if (StringUtils.isNotBlank(histIns.getAssignee())) { + UserResp sysUser = userService.detail(histIns.getAssignee()); + flowTask.setAssigneeId(sysUser.getUserId()); + flowTask.setAssigneeName(sysUser.getName()); + flowTask.setDeptName(StrUtil.isNotBlank(sysUser.getDeptName()) ? sysUser.getDeptName() : ""); + } + // 展示审批人员 + List linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); + StringBuilder stringBuilder = new StringBuilder(); + for (HistoricIdentityLink identityLink : linksForTask) { + // 获选人,候选组/角色(多个) + if ("candidate".equals(identityLink.getType())) { + if (StringUtils.isNotBlank(identityLink.getUserId())) { + UserResp sysUser = userService.detail(identityLink.getUserId()); + stringBuilder.append(sysUser.getName()).append(","); + } + if (StringUtils.isNotBlank(identityLink.getGroupId())) { + RoleResp sysRole = roleService.detail(identityLink.getGroupId()); + stringBuilder.append(sysRole.getRoleName()).append(","); + } + } + } + if (StringUtils.isNotBlank(stringBuilder)) { + flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); + } + + flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis())); + // 获取意见评论内容 + List commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId()); + commentList.forEach(comment -> { + if (histIns.getTaskId().equals(comment.getTaskId())) { + flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build()); + } + }); + hisFlowList.add(flowTask); + } + } + map.put("flowList", hisFlowList); + } + // 第一次申请获取初始化表单 + if (StringUtils.isNotBlank(deployId)) { + SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId); + if (Objects.isNull(sysForm)) { + return Result.error("请先配置流程表单"); + } + map.put("formData", JSONObject.parseObject(sysForm.getFormContent())); + } + return Result.ok(map); + } + + /** + * 根据任务ID查询挂载的表单信息 + * + * @param taskId 任务Id + * @return + */ + @Override + public Result getTaskForm(String taskId) { + Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); + SysForm sysForm = sysFormService.selectSysFormById(Long.parseLong(task.getFormKey())); + return Result.ok(sysForm.getFormContent()); + } + + /** + * 获取流程过程图 + * + * @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 highLightedFlowList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list(); + + List highLightedFlows = new ArrayList<>(); + List 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(); + InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(), + configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true); + return in; + + } + + /** + * 获取流程执行节点 + * + * @param procInsId 流程实例id + * @return + */ + @Override + public Result getFlowViewer(String procInsId, String executionId) { + List flowViewerList = new ArrayList<>(); + FlowViewerDto flowViewerDto; + // 获取任务开始节点(临时处理方式) + List startNodeList = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .orderByHistoricActivityInstanceStartTime() + .asc().listPage(0, 3); + for (HistoricActivityInstance startInstance : startNodeList) { + if (!"sequenceFlow".equals(startInstance.getActivityType())) { + flowViewerDto = new FlowViewerDto(); + if (!"sequenceFlow".equals(startInstance.getActivityType())) { + flowViewerDto.setKey(startInstance.getActivityId()); + // 根据流程节点处理时间校验改节点是否已完成 + flowViewerDto.setCompleted(!Objects.isNull(startInstance.getEndTime())); + flowViewerList.add(flowViewerDto); + } + } + } + // 历史节点 + List hisActIns = historyService.createHistoricActivityInstanceQuery() + .executionId(executionId) + .orderByHistoricActivityInstanceStartTime() + .asc().list(); + for (HistoricActivityInstance activityInstance : hisActIns) { + if (!"sequenceFlow".equals(activityInstance.getActivityType())) { + flowViewerDto = new FlowViewerDto(); + flowViewerDto.setKey(activityInstance.getActivityId()); + // 根据流程节点处理时间校验改节点是否已完成 + flowViewerDto.setCompleted(!Objects.isNull(activityInstance.getEndTime())); + flowViewerList.add(flowViewerDto); + } + } + return Result.ok(flowViewerList); + } + + /** + * 获取流程变量 + * + * @param taskId + * @return + */ + @Override + public Result processVariables(String taskId) { + // 流程变量 + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult(); + if (Objects.nonNull(historicTaskInstance)) { + return Result.ok(historicTaskInstance.getProcessVariables()); + } else { + Map variables = taskService.getVariables(taskId); + return Result.ok(variables); + } + } + + /** + * 审批任务获取下一节点 + * + * @param flowTaskVo 任务 + * @return + */ + @Override + public Result getNextFlowNode(FlowTaskVo flowTaskVo) { + // Step 1. 获取当前节点并找到下一步节点 + Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); + if (Objects.isNull(task)) { + return Result.error("任务不存在或已被审批!"); + } + // Step 2. 获取当前流程所有流程变量(网关节点时需要校验表达式) + Map variables = taskService.getVariables(task.getId()); + List nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, variables); + if (CollectionUtils.isEmpty(nextUserTask)) { + return Result.ok("流程已完结!"); + } + return getFlowAttribute(nextUserTask); + } + + /** + * 发起流程获取下一节点 + * + * @param flowTaskVo 任务 + * @return + */ + @Override + public Result getNextFlowNodeByStart(FlowTaskVo flowTaskVo) { + // Step 1. 查找流程定义信息 + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(flowTaskVo.getDeploymentId()).singleResult(); + if (Objects.isNull(processDefinition)) { + return Result.error("流程信息不存在!"); + } + // Step 2. 获取下一任务节点(网关节点时需要校验表达式) + List nextUserTask = FindNextNodeUtil.getNextUserTasksByStart(repositoryService, processDefinition, flowTaskVo.getVariables()); + if (CollectionUtils.isEmpty(nextUserTask)) { + return Result.error("暂未查找到下一任务,请检查流程设计是否正确!"); + } + return getFlowAttribute(nextUserTask); + } + + + /** + * 获取任务节点属性,包含自定义属性等 + * + * @param nextUserTask + */ + private Result getFlowAttribute(List nextUserTask) { + FlowNextDto flowNextDto = new FlowNextDto(); + for (UserTask userTask : nextUserTask) { + MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics(); + // 会签节点 + if (Objects.nonNull(multiInstance)) { + flowNextDto.setVars(multiInstance.getInputDataItem()); + flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE); + flowNextDto.setDataType(ProcessConstants.DYNAMIC); + } else { + // 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组 + String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); + String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE); + flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL); + flowNextDto.setType(userType); + flowNextDto.setDataType(dataType); + } + } + return Result.ok(flowNextDto); + } + + /** + * 流程初始化表单 + * + * @param deployId + * @return + */ + @Override + public Result flowFormData(String deployId) { + // 第一次申请获取初始化表单 + if (StringUtils.isNotBlank(deployId)) { + SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId); + if (Objects.isNull(sysForm)) { + return Result.error("请先配置流程表单!"); + } + return Result.ok(JSONObject.parseObject(sysForm.getFormContent())); + } else { + return Result.error("参数错误!"); + } + } + + /** + * 流程节点信息 + * + * @param procInsId + * @return + */ + @Override + public Result flowXmlAndNode(String procInsId, String deployId) { + try { + List flowViewerList = new ArrayList<>(); + // 获取已经完成的节点 + List listFinished = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .finished() + .list(); + + // 保存已经完成的流程节点编号 + listFinished.forEach(s -> { + FlowViewerDto flowViewerDto = new FlowViewerDto(); + flowViewerDto.setKey(s.getActivityId()); + flowViewerDto.setCompleted(true); + // 退回节点不进行展示 + if (StringUtils.isBlank(s.getDeleteReason())) { + flowViewerList.add(flowViewerDto); + } + }); + + // 获取代办节点 + List listUnFinished = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .unfinished() + .list(); + + // 保存需要代办的节点编号 + listUnFinished.forEach(s -> { + // 删除已退回节点 + flowViewerList.removeIf(task -> task.getKey().equals(s.getActivityId())); + FlowViewerDto flowViewerDto = new FlowViewerDto(); + flowViewerDto.setKey(s.getActivityId()); + flowViewerDto.setCompleted(false); + flowViewerList.add(flowViewerDto); + }); + Map result = new HashMap(); + // xmlData 数据 + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName()); + String xmlData = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + result.put("nodeData", flowViewerList); + result.put("xmlData", xmlData); + return Result.ok(result); + } catch (Exception e) { + return Result.error("高亮历史任务失败"); + } + } + + /** + * 流程节点表单 + * + * @param taskId 流程任务编号 + * @return + */ + @Override + public Result flowTaskForm(String taskId) throws Exception { + Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); + // 流程变量 + Map parameters = new HashMap<>(); + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult(); + if (Objects.nonNull(historicTaskInstance)) { + parameters = historicTaskInstance.getProcessVariables(); + } else { + parameters = taskService.getVariables(taskId); + } + JSONObject oldVariables = JSONObject.parseObject(JSON.toJSONString(parameters.get("formJson"))); + List oldFields = JSON.parseObject(JSON.toJSONString(oldVariables.get("widgetList")), new TypeReference>() { + }); + // 设置已填写的表单为禁用状态 + for (JSONObject oldField : oldFields) { + JSONObject options = oldField.getJSONObject("options"); + options.put("disabled", true); + } + // TODO 暂时只处理用户任务上的表单 + if (StringUtils.isNotBlank(task.getFormKey())) { + SysForm sysForm = sysFormService.selectSysFormById(Long.parseLong(task.getFormKey())); + JSONObject data = JSONObject.parseObject(sysForm.getFormContent()); + List newFields = JSON.parseObject(JSON.toJSONString(data.get("widgetList")), new TypeReference>() { + }); + // 表单回显时 加入子表单信息到流程变量中 + for (JSONObject newField : newFields) { + String key = newField.getString("id"); + // 处理图片上传组件回显问题 + if ("picture-upload".equals(newField.getString("type"))) { + parameters.put(key, new ArrayList<>()); + } else { + parameters.put(key, null); + } + } + oldFields.addAll(newFields); + } + oldVariables.put("widgetList", oldFields); + parameters.put("formJson", oldVariables); + return Result.ok(parameters); + } + + /** + * 流程节点信息 + * + * @param procInsId + * @param elementId + * @return + */ + @Override + public Result flowTaskInfo(String procInsId, String elementId) { + List list = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(procInsId) + .activityId(elementId) + .list(); + // 退回任务后有多条数据 只取待办任务进行展示 + list.removeIf(task -> StringUtils.isNotBlank(task.getDeleteReason())); + if (CollectionUtils.isEmpty(list)) { + return Result.ok(); + } + if (list.size() > 1) { + list.removeIf(task -> Objects.nonNull(task.getEndTime())); + } + HistoricActivityInstance histIns = list.get(0); + FlowTaskDto flowTask = new FlowTaskDto(); + flowTask.setTaskId(histIns.getTaskId()); + flowTask.setTaskName(histIns.getActivityName()); + flowTask.setCreateTime(histIns.getStartTime()); + flowTask.setFinishTime(histIns.getEndTime()); + if (StringUtils.isNotBlank(histIns.getAssignee())) { + UserResp sysUser = userService.detail(histIns.getAssignee()); + flowTask.setAssigneeId(sysUser.getUserId()); + flowTask.setAssigneeName(sysUser.getName()); + flowTask.setDeptName(StrUtil.isNotBlank(sysUser.getDeptName()) ? sysUser.getDeptName() : ""); + + } + // 流程变量信息 +// HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() +// .includeProcessVariables().finished().taskId(histIns.getTaskId()).singleResult(); +// flowTask.setVariables(historicTaskInstance.getProcessVariables()); + + // 展示审批人员 + List linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); + StringBuilder stringBuilder = new StringBuilder(); + for (HistoricIdentityLink identityLink : linksForTask) { + // 获选人,候选组/角色(多个) + if ("candidate".equals(identityLink.getType())) { + if (StringUtils.isNotBlank(identityLink.getUserId())) { + UserResp sysUser = userService.detail(identityLink.getUserId()); + stringBuilder.append(sysUser.getName()).append(","); + } + if (StringUtils.isNotBlank(identityLink.getGroupId())) { + RoleResp sysRole = roleService.detail(identityLink.getGroupId()); + stringBuilder.append(sysRole.getRoleName()).append(","); + } + } + } + if (StringUtils.isNotBlank(stringBuilder)) { + flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); + } + + flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis())); + // 获取意见评论内容 + List commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId()); + commentList.forEach(comment -> { + if (histIns.getTaskId().equals(comment.getTaskId())) { + flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build()); + } + }); + return Result.ok(flowTask); + } + + /** + * 将Object类型的数据转化成Map + * + * @param obj + * @return + * @throws Exception + */ + public Map obj2Map(Object obj) throws Exception { + Map map = new HashMap(); + Field[] fields = obj.getClass().getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + map.put(field.getName(), field.get(obj)); + } + return map; + } + + /** + * 流程完成时间处理 + * + * @param ms + * @return + */ + private String getDate(long ms) { + + long day = ms / (24 * 60 * 60 * 1000); + long hour = (ms / (60 * 60 * 1000) - day * 24); + long minute = ((ms / (60 * 1000)) - day * 24 * 60 - hour * 60); + long second = (ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60); + + if (day > 0) { + return day + "天" + hour + "小时" + minute + "分钟"; + } + if (hour > 0) { + return hour + "小时" + minute + "分钟"; + } + if (minute > 0) { + return minute + "分钟"; + } + if (second > 0) { + return second + "秒"; + } else { + return 0 + "秒"; + } + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysDeployFormServiceImpl.java b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysDeployFormServiceImpl.java new file mode 100644 index 0000000..31a2a0a --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysDeployFormServiceImpl.java @@ -0,0 +1,112 @@ +package com.dite.znpt.flowable.service.impl; + +import java.util.List; +import java.util.Objects; + +import com.dite.znpt.flowable.domain.entity.SysDeployForm; +import com.dite.znpt.flowable.domain.entity.SysForm; +import com.dite.znpt.flowable.service.ISysDeployFormService; +import com.dite.znpt.flowable.mapper.SysDeployFormMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 流程实例关联表单Service业务层处理 + * + * @author Tony + * @date 2021-04-03 + */ +@Service +public class SysDeployFormServiceImpl implements ISysDeployFormService { + + @Autowired + private SysDeployFormMapper sysDeployFormMapper; + + /** + * 查询流程实例关联表单 + * + * @param id 流程实例关联表单ID + * @return 流程实例关联表单 + */ + @Override + public SysDeployForm selectSysDeployFormById(Long id) + { + return sysDeployFormMapper.selectSysDeployFormById(id); + } + + /** + * 查询流程实例关联表单列表 + * + * @param sysDeployForm 流程实例关联表单 + * @return 流程实例关联表单 + */ + @Override + public List selectSysDeployFormList(SysDeployForm sysDeployForm) + { + return sysDeployFormMapper.selectSysDeployFormList(sysDeployForm); + } + + /** + * 新增流程实例关联表单 + * + * @param sysDeployForm 流程实例关联表单 + * @return 结果 + */ + @Override + public int insertSysDeployForm(SysDeployForm sysDeployForm) + { + SysForm sysForm = sysDeployFormMapper.selectSysDeployFormByDeployId(sysDeployForm.getDeployId()); + if (Objects.isNull(sysForm)) { + return sysDeployFormMapper.insertSysDeployForm(sysDeployForm); + }else { + return 1; + } + } + + /** + * 修改流程实例关联表单 + * + * @param sysDeployForm 流程实例关联表单 + * @return 结果 + */ + @Override + public int updateSysDeployForm(SysDeployForm sysDeployForm) + { + return sysDeployFormMapper.updateSysDeployForm(sysDeployForm); + } + + /** + * 批量删除流程实例关联表单 + * + * @param ids 需要删除的流程实例关联表单ID + * @return 结果 + */ + @Override + public int deleteSysDeployFormByIds(Long[] ids) + { + return sysDeployFormMapper.deleteSysDeployFormByIds(ids); + } + + /** + * 删除流程实例关联表单信息 + * + * @param id 流程实例关联表单ID + * @return 结果 + */ + @Override + public int deleteSysDeployFormById(Long id) + { + return sysDeployFormMapper.deleteSysDeployFormById(id); + } + + /** + * 查询流程挂着的表单 + * + * @param deployId + * @return + */ + @Override + public SysForm selectSysDeployFormByDeployId(String deployId) { + return sysDeployFormMapper.selectSysDeployFormByDeployId(deployId); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysExpressionServiceImpl.java b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysExpressionServiceImpl.java new file mode 100644 index 0000000..546081c --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysExpressionServiceImpl.java @@ -0,0 +1,97 @@ +package com.dite.znpt.flowable.service.impl; + +import com.dite.znpt.flowable.domain.entity.SysExpression; +import com.dite.znpt.flowable.mapper.SysExpressionMapper; +import com.dite.znpt.flowable.service.ISysExpressionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 流程达式Service业务层处理 + * + * @author ruoyi + * @date 2022-12-12 + */ +@Service +public class SysExpressionServiceImpl implements ISysExpressionService +{ + @Autowired + private SysExpressionMapper sysExpressionMapper; + + /** + * 查询流程达式 + * + * @param id 流程达式主键 + * @return 流程达式 + */ + @Override + public SysExpression selectSysExpressionById(Long id) + { + return sysExpressionMapper.selectSysExpressionById(id); + } + + /** + * 查询流程达式列表 + * + * @param sysExpression 流程达式 + * @return 流程达式 + */ + @Override + public List selectSysExpressionList(SysExpression sysExpression) + { + return sysExpressionMapper.selectSysExpressionList(sysExpression); + } + + /** + * 新增流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + @Override + public int insertSysExpression(SysExpression sysExpression) + { + sysExpression.setCreateTime(LocalDateTime.now()); + return sysExpressionMapper.insertSysExpression(sysExpression); + } + + /** + * 修改流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + @Override + public int updateSysExpression(SysExpression sysExpression) + { + sysExpression.setUpdateTime(LocalDateTime.now()); + return sysExpressionMapper.updateSysExpression(sysExpression); + } + + /** + * 批量删除流程达式 + * + * @param ids 需要删除的流程达式主键 + * @return 结果 + */ + @Override + public int deleteSysExpressionByIds(Long[] ids) + { + return sysExpressionMapper.deleteSysExpressionByIds(ids); + } + + /** + * 删除流程达式信息 + * + * @param id 流程达式主键 + * @return 结果 + */ + @Override + public int deleteSysExpressionById(Long id) + { + return sysExpressionMapper.deleteSysExpressionById(id); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysFormServiceImpl.java b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysFormServiceImpl.java new file mode 100644 index 0000000..7a3f6ce --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysFormServiceImpl.java @@ -0,0 +1,97 @@ +package com.dite.znpt.flowable.service.impl; + +import java.time.LocalDateTime; +import java.util.List; + +import com.dite.znpt.flowable.domain.entity.SysForm; +import com.dite.znpt.flowable.service.ISysFormService; +import com.dite.znpt.flowable.mapper.SysFormMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 流程表单Service业务层处理 + * + * @author Tony + * @date 2021-04-03 + */ +@Service +public class SysFormServiceImpl implements ISysFormService +{ + @Autowired + private SysFormMapper sysFormMapper; + + /** + * 查询流程表单 + * + * @param formId 流程表单ID + * @return 流程表单 + */ + @Override + public SysForm selectSysFormById(Long formId) + { + return sysFormMapper.selectSysFormById(formId); + } + + /** + * 查询流程表单列表 + * + * @param sysForm 流程表单 + * @return 流程表单 + */ + @Override + public List selectSysFormList(SysForm sysForm) + { + return sysFormMapper.selectSysFormList(sysForm); + } + + /** + * 新增流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + @Override + public int insertSysForm(SysForm sysForm) + { + sysForm.setCreateTime(LocalDateTime.now()); + return sysFormMapper.insertSysForm(sysForm); + } + + /** + * 修改流程表单 + * + * @param sysForm 流程表单 + * @return 结果 + */ + @Override + public int updateSysForm(SysForm sysForm) + { + sysForm.setUpdateTime(LocalDateTime.now()); + return sysFormMapper.updateSysForm(sysForm); + } + + /** + * 批量删除流程表单 + * + * @param formIds 需要删除的流程表单ID + * @return 结果 + */ + @Override + public int deleteSysFormByIds(Long[] formIds) + { + return sysFormMapper.deleteSysFormByIds(formIds); + } + + /** + * 删除流程表单信息 + * + * @param formId 流程表单ID + * @return 结果 + */ + @Override + public int deleteSysFormById(Long formId) + { + return sysFormMapper.deleteSysFormById(formId); + } +} diff --git a/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysListenerServiceImpl.java b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysListenerServiceImpl.java new file mode 100644 index 0000000..d8de902 --- /dev/null +++ b/flowable/src/main/java/com/dite/znpt/flowable/service/impl/SysListenerServiceImpl.java @@ -0,0 +1,97 @@ +package com.dite.znpt.flowable.service.impl; + +import com.dite.znpt.flowable.domain.entity.SysListener; +import com.dite.znpt.flowable.mapper.SysListenerMapper; +import com.dite.znpt.flowable.service.ISysListenerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 流程监听Service业务层处理 + * + * @author Tony + * @date 2022-12-25 + */ +@Service +public class SysListenerServiceImpl implements ISysListenerService +{ + @Autowired + private SysListenerMapper sysListenerMapper; + + /** + * 查询流程监听 + * + * @param id 流程监听主键 + * @return 流程监听 + */ + @Override + public SysListener selectSysListenerById(Long id) + { + return sysListenerMapper.selectSysListenerById(id); + } + + /** + * 查询流程监听列表 + * + * @param sysListener 流程监听 + * @return 流程监听 + */ + @Override + public List selectSysListenerList(SysListener sysListener) + { + return sysListenerMapper.selectSysListenerList(sysListener); + } + + /** + * 新增流程监听 + * + * @param sysListener 流程监听 + * @return 结果 + */ + @Override + public int insertSysListener(SysListener sysListener) + { + sysListener.setCreateTime(LocalDateTime.now()); + return sysListenerMapper.insertSysListener(sysListener); + } + + /** + * 修改流程监听 + * + * @param sysListener 流程监听 + * @return 结果 + */ + @Override + public int updateSysListener(SysListener sysListener) + { + sysListener.setUpdateTime(LocalDateTime.now()); + return sysListenerMapper.updateSysListener(sysListener); + } + + /** + * 批量删除流程监听 + * + * @param ids 需要删除的流程监听主键 + * @return 结果 + */ + @Override + public int deleteSysListenerByIds(Long[] ids) + { + return sysListenerMapper.deleteSysListenerByIds(ids); + } + + /** + * 删除流程监听信息 + * + * @param id 流程监听主键 + * @return 结果 + */ + @Override + public int deleteSysListenerById(Long id) + { + return sysListenerMapper.deleteSysListenerById(id); + } +} diff --git a/flowable/src/main/resources/mapper/FlowDeployMapper.xml b/flowable/src/main/resources/mapper/FlowDeployMapper.xml new file mode 100644 index 0000000..e42c58e --- /dev/null +++ b/flowable/src/main/resources/mapper/FlowDeployMapper.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/flowable/src/main/resources/mapper/SysDeployFormMapper.xml b/flowable/src/main/resources/mapper/SysDeployFormMapper.xml new file mode 100644 index 0000000..9464e6f --- /dev/null +++ b/flowable/src/main/resources/mapper/SysDeployFormMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + select id, form_id, deploy_id from sys_deploy_form + + + + + + + + + + insert into sys_deploy_form + + form_id, + deploy_id, + + + #{formId}, + #{deployId}, + + + + + update sys_deploy_form + + form_id = #{formId}, + deploy_id = #{deployId}, + + where id = #{id} + + + + delete from sys_deploy_form where id = #{id} + + + + delete from sys_deploy_form where id in + + #{id} + + + \ No newline at end of file diff --git a/flowable/src/main/resources/mapper/SysExpressionMapper.xml b/flowable/src/main/resources/mapper/SysExpressionMapper.xml new file mode 100644 index 0000000..dc64db1 --- /dev/null +++ b/flowable/src/main/resources/mapper/SysExpressionMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + select id, name, expression, data_type,create_time, update_time, create_by, update_by, status, remark from sys_expression + + + + + + + + insert into sys_expression + + name, + expression, + data_type, + create_time, + update_time, + create_by, + update_by, + status, + remark, + + + #{name}, + #{expression}, + #{dataType}, + #{createTime}, + #{updateTime}, + #{createBy}, + #{updateBy}, + #{status}, + #{remark}, + + + + + update sys_expression + + name = #{name}, + expression = #{expression}, + data_type = #{dataType}, + create_time = #{createTime}, + update_time = #{updateTime}, + create_by = #{createBy}, + update_by = #{updateBy}, + status = #{status}, + remark = #{remark}, + + where id = #{id} + + + + delete from sys_expression where id = #{id} + + + + delete from sys_expression where id in + + #{id} + + + diff --git a/flowable/src/main/resources/mapper/SysFormMapper.xml b/flowable/src/main/resources/mapper/SysFormMapper.xml new file mode 100644 index 0000000..48d5024 --- /dev/null +++ b/flowable/src/main/resources/mapper/SysFormMapper.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + select form_id, form_name, form_content, create_time, update_time, create_by, update_by, remark from sys_form + + + + + + + + insert into sys_form + + form_name, + form_content, + create_time, + update_time, + create_by, + update_by, + remark, + + + #{formName}, + #{formContent}, + #{createTime}, + #{updateTime}, + #{createBy}, + #{updateBy}, + #{remark}, + + + + + update sys_form + + form_name = #{formName}, + form_content = #{formContent}, + create_time = #{createTime}, + update_time = #{updateTime}, + create_by = #{createBy}, + update_by = #{updateBy}, + remark = #{remark}, + + where form_id = #{formId} + + + + delete from sys_form where form_id = #{formId} + + + + delete from sys_form where form_id in + + #{formId} + + + \ No newline at end of file diff --git a/flowable/src/main/resources/mapper/SysListenerMapper.xml b/flowable/src/main/resources/mapper/SysListenerMapper.xml new file mode 100644 index 0000000..f3c906a --- /dev/null +++ b/flowable/src/main/resources/mapper/SysListenerMapper.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + select id, + name, + type, + event_type, + value_type, + value, + create_time, + update_time, + create_by, + update_by, + status, + remark + from sys_listener + + + + + + + + insert into sys_listener + + name, + type, + event_type, + value_type, + value, + create_time, + update_time, + create_by, + update_by, + status, + remark, + + + #{name}, + #{type}, + #{eventType}, + #{valueType}, + #{value}, + #{createTime}, + #{updateTime}, + #{createBy}, + #{updateBy}, + #{status}, + #{remark}, + + + + + update sys_listener + + name = #{name}, + type = #{type}, + event_type = #{eventType}, + value_type = #{valueType}, + value = #{value}, + create_time = #{createTime}, + update_time = #{updateTime}, + create_by = #{createBy}, + update_by = #{updateBy}, + status = #{status}, + remark = #{remark}, + + where id = #{id} + + + + delete + from sys_listener + where id = #{id} + + + + delete from sys_listener where id in + + #{id} + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index fc41a56..fcdc462 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,7 @@ core sip web + flowable pom diff --git a/web/pom.xml b/web/pom.xml index 011cbcf..c6d6423 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -32,6 +32,11 @@ + + + + + diff --git a/web/src/main/java/com/dite/znpt/web/build/DeployController.java b/web/src/main/java/com/dite/znpt/web/build/DeployController.java index 193e3bb..fc20ca5 100644 --- a/web/src/main/java/com/dite/znpt/web/build/DeployController.java +++ b/web/src/main/java/com/dite/znpt/web/build/DeployController.java @@ -7,10 +7,13 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -51,6 +54,41 @@ public class DeployController { return ResponseEntity.ok("部署流程已启动"); } + @ApiOperation(value = "gitea自动部署", httpMethod = "POST") + @PostMapping("/gitea-webhook") + public ResponseEntity handleWebhook(@RequestHeader("X-Gitea-Signature") String signature, + @RequestBody(required = false) byte[] body) { + + // 1. 签名校验 + if (!validSignature(body, signature)) { + throw new RuntimeException("签名错误"); + } + + // 2. 启动部署流程 + startDeployment(); + + return ResponseEntity.ok("部署流程已启动"); + } + + private boolean validSignature(byte[] body, String sigHeader) { + if (sigHeader == null) return false; + try { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(webhookSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); + byte[] hash = mac.doFinal(body); + String computed = "sha256=" + bytesToHex(hash); + return computed.equalsIgnoreCase(sigHeader); + } catch (Exception e) { + return false; + } + } + + private String bytesToHex(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) sb.append(String.format("%02x", b)); + return sb.toString(); + } + @ApiOperation(value = "查询自动部署状态", httpMethod = "GET") @GetMapping("/deployment-status") public ResponseEntity getDeploymentStatus() { diff --git a/web/src/main/java/com/dite/znpt/web/controller/AttendanceRecordController.java b/web/src/main/java/com/dite/znpt/web/controller/AttendanceRecordController.java new file mode 100644 index 0000000..844c3bb --- /dev/null +++ b/web/src/main/java/com/dite/znpt/web/controller/AttendanceRecordController.java @@ -0,0 +1,49 @@ +package com.dite.znpt.web.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.vo.AttendanceRecordReq; +import com.dite.znpt.domain.vo.AttendanceRecordResp; +import com.dite.znpt.service.AttendanceRecordService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Author: gaoxiong + * @Date: 2025/7/21 21:21 + * @Description: + */ +@Api(tags = "考勤记录") +@RestController +@RequestMapping("/attendance-record") +public class AttendanceRecordController { + @Resource + private AttendanceRecordService attendanceRecordService; + + + @ApiOperation(value = "新增考勤记录", httpMethod = "POST") + @PostMapping + public Result add(@Validated @RequestBody AttendanceRecordReq req){ + attendanceRecordService.save(req); + return Result.ok(); + } + + @ApiOperation(value = "查询当天考勤记录", httpMethod = "GET") + @GetMapping("/list-today") + public Result> listToday(){ + String userId = StpUtil.getLoginId().toString(); + return Result.ok(attendanceRecordService.listToday(userId)); + } + + @ApiOperation(value = "按月份查询指定人员考勤记录", httpMethod = "GET") + @GetMapping("/list-month/{year}/{month}") + public Result> listMonth(@PathVariable Integer year, @PathVariable Integer month){ + String userId = StpUtil.getLoginId().toString(); + return Result.ok(attendanceRecordService.listMonth(userId, year, month)); + } +} diff --git a/web/src/main/java/com/dite/znpt/web/controller/CheckSchemeController.java b/web/src/main/java/com/dite/znpt/web/controller/CheckSchemeController.java index c8e30dc..0dd4abb 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/CheckSchemeController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/CheckSchemeController.java @@ -27,14 +27,14 @@ public class CheckSchemeController { @ApiOperation(value = "分页查询检查方案信息", httpMethod = "GET") @GetMapping("/page") - public PageResult page(@RequestParam(required = false) String checkMethod){ - return PageResult.ok(checkSchemeService.page(checkMethod)); + public PageResult page(@RequestParam(required = false) List checkMethods){ + return PageResult.ok(checkSchemeService.page(checkMethods)); } @ApiOperation(value = "查询检查方案信息列表", httpMethod = "GET") @GetMapping("/list") - public Result> list(@RequestParam(required = false) String checkMethod){ - return Result.ok(checkSchemeService.list(checkMethod)); + public Result> list(@RequestParam(required = false) List checkMethods){ + return Result.ok(checkSchemeService.list(checkMethods)); } @ApiOperation(value = "查询检查方案详情", httpMethod = "GET") diff --git a/web/src/main/java/com/dite/znpt/web/controller/CommonController.java b/web/src/main/java/com/dite/znpt/web/controller/CommonController.java index 1edc6e8..75f14fe 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/CommonController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/CommonController.java @@ -105,7 +105,7 @@ public class CommonController { return Result.ok(GenderEnum.listAll()); } - @ApiOperation(value = "上传图片", httpMethod = "POST") + @ApiOperation(value = "上传图片-遥控器app使用,已废弃", httpMethod = "POST") @PostMapping("/upload-image/{imageSource}") public Result uploadImage(@PathVariable String imageSource, ImageWorkReq workReq, MultipartFile file) throws IOException { if(null == file){ @@ -114,7 +114,7 @@ public class CommonController { return Result.ok(imageService.batchUploadCommonImage(imageSource, workReq, new MultipartFile[]{file}).get(0)); } - @ApiOperation(value = "批量上传图片", httpMethod = "POST") + @ApiOperation(value = "批量上传图片-遥控器app使用,已废弃", httpMethod = "POST") @PostMapping("/batch-upload-image/{imageSource}") public Result batchUploadImage(@PathVariable String imageSource, ImageWorkReq workReq, @RequestParam("file") MultipartFile[] files) throws IOException { diff --git a/web/src/main/java/com/dite/znpt/web/controller/ContractController.java b/web/src/main/java/com/dite/znpt/web/controller/ContractController.java new file mode 100644 index 0000000..d62a82a --- /dev/null +++ b/web/src/main/java/com/dite/znpt/web/controller/ContractController.java @@ -0,0 +1,85 @@ +package com.dite.znpt.web.controller; + + +import com.dite.znpt.constant.Constants; +import com.dite.znpt.domain.PageResult; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.entity.ContractEntity; +import com.dite.znpt.domain.vo.ContractListReq; +import com.dite.znpt.domain.vo.ContractReq; +import com.dite.znpt.domain.vo.ContractResp; +import com.dite.znpt.service.ContractService; +import com.pig4cloud.plugin.excel.annotation.RequestExcel; +import com.pig4cloud.plugin.excel.annotation.ResponseExcel; +import com.pig4cloud.plugin.excel.vo.ErrorMessage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/21 20:29 + */ +@Api(tags = "合同") +@RestController +@RequestMapping("/contract") +public class ContractController { + @Resource + private ContractService contractService; + + @ApiOperation(value = "获取合同列表", httpMethod = "GET") + @GetMapping("/list") + public PageResult list(ContractListReq contractReq) { + return PageResult.ok(contractService.selectList(contractReq)); + } + + @ApiOperation(value = "根据合同Id获取详细信息", httpMethod = "GET") + @GetMapping("/{contractId}") + public Result getInfo(@PathVariable String contractId) { + return Result.ok(contractService.selectById(contractId)); + } + + @ApiOperation(value = "新增合同", httpMethod = "POST") + @PostMapping + public Result add(@RequestBody ContractReq contractReq) { + contractService.saveData(contractReq); + return Result.ok(); + } + + @ApiOperation(value = "修改合同", httpMethod = "PUT") + @PutMapping + public Result edit(@RequestBody ContractReq contractReq) { + contractService.updateData(contractReq); + return Result.ok(); + } + + @ApiOperation(value = "删除合同", httpMethod = "DELETE") + @DeleteMapping("/{contractId}") + public Result remove(@PathVariable String contractId) { + contractService.deleteById(contractId); + return Result.ok(); + } + + @ApiOperation(value = "导出合同", httpMethod = "GET") + @GetMapping("/export") + @ResponseExcel(name = "合同") + public List export(ContractListReq contractReq) { + return contractService.selectList(contractReq); + } + + @ApiOperation(value = "导入合同", httpMethod = "POST") + @PostMapping("/import") + public Result importData(@RequestExcel List dataList, BindingResult bindingResult) { + // JSR 303 校验通用校验获取失败的数据 + List errorMessageList = (List) bindingResult.getTarget(); + if (errorMessageList != null && !errorMessageList.isEmpty()) { + return Result.error(Constants.SERVICE_EXCEPTION, "导入失败"); + } + return Result.okM("导入"+dataList.size()+"条数据"); + } +} + diff --git a/web/src/main/java/com/dite/znpt/web/controller/ContractSettlementController.java b/web/src/main/java/com/dite/znpt/web/controller/ContractSettlementController.java new file mode 100644 index 0000000..854895f --- /dev/null +++ b/web/src/main/java/com/dite/znpt/web/controller/ContractSettlementController.java @@ -0,0 +1,42 @@ +package com.dite.znpt.web.controller; + + +import com.dite.znpt.constant.Constants; +import com.dite.znpt.domain.PageResult; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.entity.ContractSettlementEntity; +import com.dite.znpt.domain.vo.ContractSettlementListReq; +import com.dite.znpt.domain.vo.ContractSettlementReq; +import com.dite.znpt.domain.vo.ContractSettlementResp; +import com.dite.znpt.service.ContractSettlementService; +import com.pig4cloud.plugin.excel.annotation.RequestExcel; +import com.pig4cloud.plugin.excel.annotation.ResponseExcel; +import com.pig4cloud.plugin.excel.vo.ErrorMessage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/21 21:11 + */ +@Api(tags = "合同结算") +@RestController +@RequestMapping("/contract-settlement") +public class ContractSettlementController { + @Resource + private ContractSettlementService contractSettlementService; + + @ApiOperation(value = "新增合同结算", httpMethod = "POST") + @PostMapping + public Result add(@RequestBody ContractSettlementReq contractSettlementReq) { + contractSettlementService.saveData(contractSettlementReq); + return Result.ok(); + } + +} + diff --git a/web/src/main/java/com/dite/znpt/web/controller/ImageController.java b/web/src/main/java/com/dite/znpt/web/controller/ImageController.java index 9ee105b..002a073 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/ImageController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/ImageController.java @@ -57,9 +57,9 @@ public class ImageController { @ApiOperation(value = "上传图像", httpMethod = "POST") @PostMapping("/{imageSource}/upload/{partId}") - public Result uploadOutWork(@PathVariable String imageSource, @PathVariable String partId, ImageCollectReq collectReq, @RequestParam("file") MultipartFile file) { + public Result uploadOutWork(@PathVariable String imageSource, @PathVariable String partId, ImageCollectReq collectReq, @RequestParam("file") MultipartFile file) { MultipartFile[] files = {file}; - return Result.ok(imageService.batchUploadDefectImage(partId, imageSource, collectReq, files).get(0).getImagePath()); + return Result.ok(imageService.batchUploadDefectImage(partId, imageSource, collectReq, files).get(0)); } @ApiOperation(value = "设置信息", httpMethod = "POST") @@ -76,13 +76,13 @@ public class ImageController { return Result.ok(); } - @ApiOperation(value = "获取APP上传的图片列表", httpMethod = "GET") + @ApiOperation(value = "获取APP上传的图片列表-废弃", httpMethod = "GET") @GetMapping("/list/app-upload-images") public Result> listAppUploadImages() throws IOException { return Result.ok(imageService.listAppUploadImages()); } - @ApiOperation(value = "关联APP上传图片到机组", httpMethod = "POST") + @ApiOperation(value = "关联APP上传图片到机组-废弃", httpMethod = "POST") @PostMapping("/linkAppImagesToPart") public Result linkAppImagesToPart(@RequestBody AppImageToPartReq partReq) { imageService.linkAppImagesToPart(partReq); diff --git a/web/src/main/java/com/dite/znpt/web/controller/InspectionReportController.java b/web/src/main/java/com/dite/znpt/web/controller/InspectionReportController.java index 090f103..d43883c 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/InspectionReportController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/InspectionReportController.java @@ -1,8 +1,19 @@ package com.dite.znpt.web.controller; +import com.dite.znpt.domain.PageResult; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.vo.InspectionReportListReq; +import com.dite.znpt.domain.vo.InspectionReportListResp; +import com.dite.znpt.domain.vo.InspectionReportReq; +import com.dite.znpt.domain.vo.InspectionReportResp; +import com.dite.znpt.service.InspectionReportService; import io.swagger.annotations.Api; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; /** * @author Bear.G @@ -13,4 +24,47 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/inspection-report") public class InspectionReportController { + + @Resource + private InspectionReportService inspectionReportService; + + + @ApiOperation(value = "分页查询检查报告列表", httpMethod = "GET") + @GetMapping("/page") + public PageResult page(InspectionReportListReq req) { + return PageResult.ok(inspectionReportService.page(req)); + } + + @ApiOperation(value = "查询检查报告列表", httpMethod = "GET") + @GetMapping("/list") + public Result> list(InspectionReportListReq req) { + return Result.ok(inspectionReportService.list(req)); + } + + @ApiOperation(value = "查询检查报告详情", httpMethod = "GET") + @GetMapping("/detail/{reportId}") + public Result detail(@PathVariable String reportId) { + return Result.ok(inspectionReportService.detail(reportId)); + } + + @ApiOperation(value = "新增检查报告", httpMethod = "POST") + @PostMapping + public Result add(@Validated @RequestBody InspectionReportReq req) { + inspectionReportService.save(req); + return Result.ok(); + } + + @ApiOperation(value = "修改检查报告", httpMethod = "PUT") + @PostMapping("/{reportId}") + public Result edit(@PathVariable String reportId, @Validated @RequestBody InspectionReportReq req) { + inspectionReportService.update(reportId, req); + return Result.ok(); + } + + @ApiOperation(value = "删除检查报告", httpMethod = "DELETE") + @DeleteMapping("/{reportId}") + public Result delete(@PathVariable String reportId) { + inspectionReportService.removeById(reportId); + return Result.ok(); + } } diff --git a/web/src/main/java/com/dite/znpt/web/controller/ProjectBudgetInfoController.java b/web/src/main/java/com/dite/znpt/web/controller/ProjectBudgetInfoController.java new file mode 100644 index 0000000..3771898 --- /dev/null +++ b/web/src/main/java/com/dite/znpt/web/controller/ProjectBudgetInfoController.java @@ -0,0 +1,48 @@ +package com.dite.znpt.web.controller; + + +import com.dite.znpt.domain.PageResult; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.vo.ProjectBudgetInfoListReq; +import com.dite.znpt.domain.vo.ProjectBudgetInfoListResp; +import com.dite.znpt.domain.vo.ProjectBudgetInfoReq; +import com.dite.znpt.domain.vo.ProjectBudgetInfoResp; +import com.dite.znpt.service.ProjectBudgetInfoService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author huise23 + * @date 2025/07/17 21:55 + */ +@Api(tags = "项目预算信息") +@RestController +@RequestMapping("/project-budget-info") +public class ProjectBudgetInfoController { + @Resource + private ProjectBudgetInfoService projectBudgetInfoService; + + @ApiOperation(value = "获取项目预算信息列表", httpMethod = "GET") + @GetMapping("/list") + public PageResult list(ProjectBudgetInfoListReq projectBudgetInfoReq) { + return PageResult.ok(projectBudgetInfoService.selectList(projectBudgetInfoReq)); + } + + @ApiOperation(value = "根据项目id获取项目预算信息列表", httpMethod = "GET") + @GetMapping("/detail/{projectId}") + public PageResult detailByProjectId(@PathVariable String projectId) { + return PageResult.ok(projectBudgetInfoService.detailByProjectId(projectId)); + } + + @ApiOperation(value = "保存项目预算信息", httpMethod = "POST") + @PostMapping + public Result add(@RequestBody List projectBudgetInfoReq) { + projectBudgetInfoService.saveData(projectBudgetInfoReq); + return Result.ok(); + } +} + diff --git a/web/src/main/java/com/dite/znpt/web/controller/ProjectController.java b/web/src/main/java/com/dite/znpt/web/controller/ProjectController.java index b9068cc..88f58b4 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/ProjectController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/ProjectController.java @@ -1,6 +1,7 @@ package com.dite.znpt.web.controller; +import cn.dev33.satoken.stp.StpUtil; import com.dite.znpt.constant.Constants; import com.dite.znpt.domain.vo.ProjectListReq; import com.dite.znpt.domain.vo.ProjectListResp; @@ -90,5 +91,14 @@ public class ProjectController { } return Result.okM("导入"+dataList.size()+"条数据"); } + + @ApiOperation(value = "查询我的项目", httpMethod = "GET") + @GetMapping("/my") + public Result> my() { + ProjectListReq req = new ProjectListReq(); + req.setUserId(StpUtil.getLoginIdAsString()); + return Result.ok(projectService.list(req)); + } + } diff --git a/web/src/main/java/com/dite/znpt/web/controller/ProjectTaskController.java b/web/src/main/java/com/dite/znpt/web/controller/ProjectTaskController.java index cbf1788..b2cd6b3 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/ProjectTaskController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/ProjectTaskController.java @@ -1,12 +1,14 @@ package com.dite.znpt.web.controller; +import cn.dev33.satoken.stp.StpUtil; import com.dite.znpt.constant.Constants; import com.dite.znpt.domain.PageResult; import com.dite.znpt.domain.Result; import com.dite.znpt.domain.entity.ProjectTaskEntity; import com.dite.znpt.domain.vo.*; import com.dite.znpt.service.ProjectTaskService; +import com.dite.znpt.util.PageUtil; import com.dite.znpt.util.ValidationGroup; import com.pig4cloud.plugin.excel.annotation.RequestExcel; import com.pig4cloud.plugin.excel.annotation.ResponseExcel; @@ -34,6 +36,7 @@ public class ProjectTaskController { @ApiOperation(value = "获取项目任务信息列表", httpMethod = "GET") @GetMapping("/list") public PageResult list(ProjectTaskListReq projectTaskReq) { + PageUtil.startPage(); return PageResult.ok(projectTaskService.selectList(projectTaskReq)); } @@ -97,5 +100,12 @@ public class ProjectTaskController { return Result.ok(); } + @ApiOperation(value = "查询我的任务", httpMethod = "GET") + @GetMapping("/my") + public Result> my() { + ProjectTaskListReq req = new ProjectTaskListReq(); + req.setUserId(StpUtil.getLoginIdAsString()); + return Result.ok(projectTaskService.selectList(req)); + } } diff --git a/web/src/main/java/com/dite/znpt/web/controller/WorkbenchController.java b/web/src/main/java/com/dite/znpt/web/controller/WorkbenchController.java new file mode 100644 index 0000000..046cff6 --- /dev/null +++ b/web/src/main/java/com/dite/znpt/web/controller/WorkbenchController.java @@ -0,0 +1,34 @@ +package com.dite.znpt.web.controller; + +import com.dite.znpt.domain.PageResult; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.vo.WeatherTypeListReq; +import com.dite.znpt.domain.vo.WeatherTypeResp; +import com.dite.znpt.domain.vo.WorkbenchInfoResp; +import com.dite.znpt.service.WorkbenchService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author huise23 + * @date 2025/04/11 23:17 + */ +@Api(tags = "工作台") +@RestController +@RequestMapping("/workbench") +@RequiredArgsConstructor +public class WorkbenchController { + + private final WorkbenchService workbenchService; + + @ApiOperation(value = "获取工作台信息", httpMethod = "GET") + @GetMapping("/info") + public Result info() { + return Result.ok(workbenchService.getInfo()); + } + +} diff --git a/web/src/main/resources/application.yml b/web/src/main/resources/application.yml index 83993b1..694c057 100644 --- a/web/src/main/resources/application.yml +++ b/web/src/main/resources/application.yml @@ -20,4 +20,11 @@ spring: matching-strategy: ant_path_matcher main: allow-circular-references: true - allow-bean-definition-overriding: true \ No newline at end of file + allow-bean-definition-overriding: true + +# flowable相关表 +flowable: + # true 会对数据库中所有表进行更新操作。如果表不存在,则自动创建(建议开发时使用) + database-schema-update: false + # 关闭定时任务JOB + async-executor-activate: false \ No newline at end of file