7 天以前 5bce6fa4728a9fb62b95e94828fddf8f3134a409
feat(bpm): 添加业务附件配置功能

- 新增BpmBusinessAttachService接口及其实现类
- 新增BpmBusinessAttachDO数据对象和BpmBusinessAttachMapper
- 新增BpmBusinessAttachController提供CRUD接口
- 添加业务附件配置相关的请求和响应VO类
- 在流程实例控制器中注入业务附件服务
- 实现审批详情和打印数据中填充业务表单信息的功能
- 添加业务附件配置的错误码常量
已修改3个文件
已添加12个文件
489 ■■■■■ 文件已修改
approval-detail-before-full.png 补丁 | 查看 | 原始文档 | blame | 历史
approval-detail-before.png 补丁 | 查看 | 原始文档 | blame | 历史
approval-detail-v2.jpeg 补丁 | 查看 | 原始文档 | blame | 历史
contract-approve-detail.png 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/attach/BpmBusinessAttachController.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/attach/vo/attach/BpmBusinessAttachPageReqVO.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/attach/vo/attach/BpmBusinessAttachRespVO.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/attach/vo/attach/BpmBusinessAttachSaveReqVO.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmBusinessAttachDO.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/attach/BpmBusinessAttachMapper.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/attach/BpmBusinessAttachService.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/attach/BpmBusinessAttachServiceImpl.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
approval-detail-before-full.png
approval-detail-before.png
approval-detail-v2.jpeg
contract-approve-detail.png
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/attach/BpmBusinessAttachController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,72 @@
package cn.iocoder.yudao.module.bpm.controller.admin.attach;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach.BpmBusinessAttachPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach.BpmBusinessAttachRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach.BpmBusinessAttachSaveReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmBusinessAttachDO;
import cn.iocoder.yudao.module.bpm.service.attach.BpmBusinessAttachService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - BPM ä¸šåŠ¡é™„ä»¶é…ç½®")
@RestController
@RequestMapping("/bpm/business-attach")
@Validated
public class BpmBusinessAttachController {
    @Resource
    private BpmBusinessAttachService businessAttachService;
    @PostMapping("/create")
    @Operation(summary = "创建业务附件配置")
    @PreAuthorize("@ss.hasPermission('bpm:business-attach:create')")
    public CommonResult<Long> createBusinessAttach(@Valid @RequestBody BpmBusinessAttachSaveReqVO createReqVO) {
        return success(businessAttachService.createBusinessAttach(createReqVO));
    }
    @PutMapping("/update")
    @Operation(summary = "更新业务附件配置")
    @PreAuthorize("@ss.hasPermission('bpm:business-attach:update')")
    public CommonResult<Boolean> updateBusinessAttach(@Valid @RequestBody BpmBusinessAttachSaveReqVO updateReqVO) {
        businessAttachService.updateBusinessAttach(updateReqVO);
        return success(true);
    }
    @DeleteMapping("/delete")
    @Operation(summary = "删除业务附件配置")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('bpm:business-attach:delete')")
    public CommonResult<Boolean> deleteBusinessAttach(@RequestParam("id") Long id) {
        businessAttachService.deleteBusinessAttach(id);
        return success(true);
    }
    @GetMapping("/get")
    @Operation(summary = "获得业务附件配置")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('bpm:business-attach:query')")
    public CommonResult<BpmBusinessAttachRespVO> getBusinessAttach(@RequestParam("id") Long id) {
        BpmBusinessAttachDO attach = businessAttachService.getBusinessAttach(id);
        return success(BeanUtils.toBean(attach, BpmBusinessAttachRespVO.class));
    }
    @GetMapping("/page")
    @Operation(summary = "获得业务附件配置分页")
    @PreAuthorize("@ss.hasPermission('bpm:business-attach:query')")
    public CommonResult<PageResult<BpmBusinessAttachRespVO>> getBusinessAttachPage(@Valid BpmBusinessAttachPageReqVO pageReqVO) {
        PageResult<BpmBusinessAttachDO> pageResult = businessAttachService.getBusinessAttachPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, BpmBusinessAttachRespVO.class));
    }
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/attach/vo/attach/BpmBusinessAttachPageReqVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - BPM ä¸šåŠ¡é™„ä»¶é…ç½®åˆ†é¡µ Request VO")
@Data
public class BpmBusinessAttachPageReqVO extends PageParam {
    @Schema(description = "流程定义的 Key", example = "purchase_approve")
    private String processDefinitionKey;
    @Schema(description = "业务类型,例如 erp_purchase_order", example = "erp_purchase_order")
    private String businessType;
    @Schema(description = "业务详情组件路径,例如 /erp/purchase/order/detail/index.vue")
    private String componentPath;
    @Schema(description = "状态,参见 CommonStatusEnum æžšä¸¾", example = "1")
    @InEnum(CommonStatusEnum.class)
    private Integer status;
    @Schema(description = "创建时间")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
    private LocalDateTime[] createTime;
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/attach/vo/attach/BpmBusinessAttachRespVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - BPM ä¸šåŠ¡é™„ä»¶é…ç½® Response VO")
@Data
public class BpmBusinessAttachRespVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    private Long id;
    @Schema(description = "流程定义的 Key", requiredMode = Schema.RequiredMode.REQUIRED, example = "purchase_approve")
    private String processDefinitionKey;
    @Schema(description = "业务类型,例如 erp_purchase_order", example = "erp_purchase_order")
    private String businessType;
    @Schema(description = "业务详情组件路径,例如 /erp/purchase/order/detail/index.vue", requiredMode = Schema.RequiredMode.REQUIRED)
    private String componentPath;
    @Schema(description = "状态,参见 CommonStatusEnum æžšä¸¾", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Integer status;
    @Schema(description = "备注", example = "采购订单审批展示采购订单详情")
    private String remark;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    private LocalDateTime createTime;
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/attach/vo/attach/BpmBusinessAttachSaveReqVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - BPM ä¸šåŠ¡é™„ä»¶é…ç½®æ–°å¢ž/修改 Request VO")
@Data
public class BpmBusinessAttachSaveReqVO {
    @Schema(description = "编号", example = "1024")
    private Long id;
    @Schema(description = "流程定义的 Key", requiredMode = Schema.RequiredMode.REQUIRED, example = "purchase_approve")
    @NotEmpty(message = "流程定义的 Key ä¸èƒ½ä¸ºç©º")
    private String processDefinitionKey;
    @Schema(description = "业务类型,例如 erp_purchase_order", example = "erp_purchase_order")
    private String businessType;
    @Schema(description = "业务详情组件路径,例如 /erp/purchase/order/detail/index.vue", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotEmpty(message = "业务详情组件路径不能为空")
    private String componentPath;
    @Schema(description = "状态,参见 CommonStatusEnum æžšä¸¾", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    @NotNull(message = "状态不能为空")
    @InEnum(CommonStatusEnum.class)
    private Integer status;
    @Schema(description = "备注", example = "采购订单审批展示采购订单详情")
    private String remark;
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
@@ -11,6 +11,7 @@
import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
import cn.iocoder.yudao.module.bpm.service.attach.BpmBusinessAttachService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
@@ -56,6 +57,8 @@
    private BpmProcessDefinitionService processDefinitionService;
    @Resource
    private BpmCategoryService categoryService;
    @Resource
    private BpmBusinessAttachService businessAttachService;
    @Resource
    private AdminUserApi adminUserApi;
@@ -217,10 +220,16 @@
        List<HistoricTaskInstance> tasks = taskService.getFinishedTaskListByProcessInstanceIdWithoutCancel(processInstanceId);
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
                convertSet(tasks, item -> Long.valueOf(item.getAssignee())));
        return success(BpmProcessInstanceConvert.INSTANCE.buildProcessInstancePrintData(historicProcessInstance,
        BpmProcessPrintDataRespVO printData = BpmProcessInstanceConvert.INSTANCE.buildProcessInstancePrintData(
                historicProcessInstance,
                processDefinitionService.getProcessDefinitionInfo(historicProcessInstance.getProcessDefinitionId()),
                tasks, userMap,
                new UserSimpleBaseVO().setNickname(startUser.getNickname()).setDeptName(dept.getName())));
                new UserSimpleBaseVO().setNickname(startUser.getNickname()).setDeptName(dept.getName()));
        // å¡«å……业务附件配置,实现打印自动展示外部业务信息
        businessAttachService.fillBusinessForm(printData.getProcessInstance().getProcessDefinition(),
                processDefinitionService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId()).getKey(),
                historicProcessInstance.getBusinessKey());
        return success(printData);
    }
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmBusinessAttachDO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * BPM ä¸šåŠ¡é™„ä»¶é…ç½® DO
 *
 * ç”¨äºŽå»ºç«‹ã€Œæµç¨‹å®šä¹‰ Key -> ä¸šåŠ¡è¯¦æƒ…ç»„ä»¶ã€çš„æ˜ å°„ï¼Œå®žçŽ°å®¡æ‰¹è¯¦æƒ…è‡ªåŠ¨å±•ç¤ºå¤–éƒ¨ä¸šåŠ¡ä¿¡æ¯
 *
 * @author è¶…级管理员
 */
@TableName("bpm_business_attach")
@KeySequence("bpm_business_attach_seq") // ç”¨äºŽ Oracle、PostgreSQL、Kingbase、DB2、H2 æ•°æ®åº“的主键自增。如果是 MySQL ç­‰æ•°æ®åº“,可不写。
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BpmBusinessAttachDO extends BaseDO {
    /**
     * ç¼–号
     */
    @TableId
    private Long id;
    /**
     * æµç¨‹å®šä¹‰çš„ Key
     */
    private String processDefinitionKey;
    /**
     * ä¸šåŠ¡ç±»åž‹ï¼Œä¾‹å¦‚ erp_purchase_order
     */
    private String businessType;
    /**
     * ä¸šåŠ¡è¯¦æƒ…ç»„ä»¶è·¯å¾„ï¼Œä¾‹å¦‚ /erp/purchase/order/detail/index.vue
     */
    private String componentPath;
    /**
     * çŠ¶æ€
     *
     * æžšä¸¾ {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
     */
    private Integer status;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/attach/BpmBusinessAttachMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.attach;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach.BpmBusinessAttachPageReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmBusinessAttachDO;
import org.apache.ibatis.annotations.Mapper;
/**
 * BPM ä¸šåŠ¡é™„ä»¶é…ç½® Mapper
 *
 * @author è¶…级管理员
 */
@Mapper
public interface BpmBusinessAttachMapper extends BaseMapperX<BpmBusinessAttachDO> {
    default PageResult<BpmBusinessAttachDO> selectPage(BpmBusinessAttachPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<BpmBusinessAttachDO>()
                .likeIfPresent(BpmBusinessAttachDO::getProcessDefinitionKey, reqVO.getProcessDefinitionKey())
                .likeIfPresent(BpmBusinessAttachDO::getBusinessType, reqVO.getBusinessType())
                .likeIfPresent(BpmBusinessAttachDO::getComponentPath, reqVO.getComponentPath())
                .eqIfPresent(BpmBusinessAttachDO::getStatus, reqVO.getStatus())
                .betweenIfPresent(BpmBusinessAttachDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(BpmBusinessAttachDO::getId));
    }
    default BpmBusinessAttachDO selectByProcessDefinitionKey(String processDefinitionKey) {
        return selectOne(BpmBusinessAttachDO::getProcessDefinitionKey, processDefinitionKey);
    }
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
@@ -89,4 +89,8 @@
    // ========== BPM æµç¨‹è¡¨è¾¾å¼ 1-009-014-000 ==========
    ErrorCode PROCESS_EXPRESSION_NOT_EXISTS = new ErrorCode(1_009_014_000, "流程表达式不存在");
    // ========== BPM ä¸šåŠ¡é™„ä»¶é…ç½® 1-009-015-000 ==========
    ErrorCode BUSINESS_ATTACH_NOT_EXISTS = new ErrorCode(1_009_015_000, "业务附件配置不存在");
    ErrorCode BUSINESS_ATTACH_PROCESS_DEFINITION_KEY_DUPLICATE = new ErrorCode(1_009_015_001, "流程定义的 Key({})已存在");
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/attach/BpmBusinessAttachService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
package cn.iocoder.yudao.module.bpm.service.attach;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach.BpmBusinessAttachPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach.BpmBusinessAttachSaveReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmBusinessAttachDO;
import jakarta.validation.Valid;
/**
 * BPM ä¸šåŠ¡é™„ä»¶é…ç½® Service æŽ¥å£
 *
 * @author è¶…级管理员
 */
public interface BpmBusinessAttachService {
    /**
     * åˆ›å»ºä¸šåŠ¡é™„ä»¶é…ç½®
     *
     * @param createReqVO åˆ›å»ºä¿¡æ¯
     * @return ç¼–号
     */
    Long createBusinessAttach(@Valid BpmBusinessAttachSaveReqVO createReqVO);
    /**
     * æ›´æ–°ä¸šåŠ¡é™„ä»¶é…ç½®
     *
     * @param updateReqVO æ›´æ–°ä¿¡æ¯
     */
    void updateBusinessAttach(@Valid BpmBusinessAttachSaveReqVO updateReqVO);
    /**
     * åˆ é™¤ä¸šåŠ¡é™„ä»¶é…ç½®
     *
     * @param id ç¼–号
     */
    void deleteBusinessAttach(Long id);
    /**
     * èŽ·å¾—ä¸šåŠ¡é™„ä»¶é…ç½®
     *
     * @param id ç¼–号
     * @return ä¸šåŠ¡é™„ä»¶é…ç½®
     */
    BpmBusinessAttachDO getBusinessAttach(Long id);
    /**
     * èŽ·å¾—ä¸šåŠ¡é™„ä»¶é…ç½®åˆ†é¡µ
     *
     * @param pageReqVO åˆ†é¡µæŸ¥è¯¢
     * @return ä¸šåŠ¡é™„ä»¶é…ç½®åˆ†é¡µ
     */
    PageResult<BpmBusinessAttachDO> getBusinessAttachPage(BpmBusinessAttachPageReqVO pageReqVO);
    /**
     * èŽ·å¾—ä¸šåŠ¡é™„ä»¶é…ç½®ï¼ŒåŸºäºŽæµç¨‹å®šä¹‰ Key
     *
     * @param processDefinitionKey æµç¨‹å®šä¹‰ Key
     * @return ä¸šåŠ¡é™„ä»¶é…ç½®
     */
    BpmBusinessAttachDO getBusinessAttachByProcessDefinitionKey(String processDefinitionKey);
    /**
     * å¡«å……业务表单信息到流程定义 Response
     *
     * è‹¥è¯¥æµç¨‹å®šä¹‰é…ç½®äº†ä¸šåŠ¡é™„ä»¶ï¼ˆä¸”å·²å¯ç”¨ã€å½“å‰æ˜¯ NORMAL æµç¨‹è¡¨å•、存在业务主键),
     * åˆ™å°† formType è¦†ç›–为 CUSTOM å¹¶æ³¨å…¥ä¸šåŠ¡è¯¦æƒ…ç»„ä»¶è·¯å¾„ï¼Œå®žçŽ°å®¡æ‰¹è¯¦æƒ…è‡ªåŠ¨å±•ç¤ºä¸šåŠ¡ä¿¡æ¯
     *
     * @param definitionResp        æµç¨‹å®šä¹‰ Response
     * @param processDefinitionKey  æµç¨‹å®šä¹‰ Key
     * @param businessKey           ä¸šåŠ¡çš„å”¯ä¸€æ ‡è¯†ï¼ˆæœªå‘èµ·æ—¶ä¸º null)
     */
    void fillBusinessForm(BpmProcessDefinitionRespVO definitionResp, String processDefinitionKey, String businessKey);
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/attach/BpmBusinessAttachServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,119 @@
package cn.iocoder.yudao.module.bpm.service.attach;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach.BpmBusinessAttachPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.attach.vo.attach.BpmBusinessAttachSaveReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmBusinessAttachDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.attach.BpmBusinessAttachMapper;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.BUSINESS_ATTACH_NOT_EXISTS;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.BUSINESS_ATTACH_PROCESS_DEFINITION_KEY_DUPLICATE;
/**
 * BPM ä¸šåŠ¡é™„ä»¶é…ç½® Service å®žçŽ°ç±»
 *
 * @author è¶…级管理员
 */
@Service
@Validated
public class BpmBusinessAttachServiceImpl implements BpmBusinessAttachService {
    @Resource
    private BpmBusinessAttachMapper businessAttachMapper;
    @Override
    public Long createBusinessAttach(BpmBusinessAttachSaveReqVO createReqVO) {
        // æ ¡éªŒæµç¨‹å®šä¹‰ Key å”¯ä¸€
        validateProcessDefinitionKeyUnique(createReqVO);
        // æ’å…¥
        BpmBusinessAttachDO attach = BeanUtils.toBean(createReqVO, BpmBusinessAttachDO.class);
        businessAttachMapper.insert(attach);
        return attach.getId();
    }
    @Override
    public void updateBusinessAttach(BpmBusinessAttachSaveReqVO updateReqVO) {
        // æ ¡éªŒå­˜åœ¨
        validateBusinessAttachExists(updateReqVO.getId());
        // æ ¡éªŒæµç¨‹å®šä¹‰ Key å”¯ä¸€
        validateProcessDefinitionKeyUnique(updateReqVO);
        // æ›´æ–°
        BpmBusinessAttachDO updateObj = BeanUtils.toBean(updateReqVO, BpmBusinessAttachDO.class);
        businessAttachMapper.updateById(updateObj);
    }
    private void validateProcessDefinitionKeyUnique(BpmBusinessAttachSaveReqVO reqVO) {
        BpmBusinessAttachDO attach = businessAttachMapper.selectByProcessDefinitionKey(reqVO.getProcessDefinitionKey());
        if (attach == null || ObjUtil.equal(attach.getId(), reqVO.getId())) {
            return;
        }
        throw exception(BUSINESS_ATTACH_PROCESS_DEFINITION_KEY_DUPLICATE, reqVO.getProcessDefinitionKey());
    }
    @Override
    public void deleteBusinessAttach(Long id) {
        // æ ¡éªŒå­˜åœ¨
        validateBusinessAttachExists(id);
        // åˆ é™¤
        businessAttachMapper.deleteById(id);
    }
    private BpmBusinessAttachDO validateBusinessAttachExists(Long id) {
        BpmBusinessAttachDO attach = businessAttachMapper.selectById(id);
        if (attach == null) {
            throw exception(BUSINESS_ATTACH_NOT_EXISTS);
        }
        return attach;
    }
    @Override
    public BpmBusinessAttachDO getBusinessAttach(Long id) {
        return businessAttachMapper.selectById(id);
    }
    @Override
    public PageResult<BpmBusinessAttachDO> getBusinessAttachPage(BpmBusinessAttachPageReqVO pageReqVO) {
        return businessAttachMapper.selectPage(pageReqVO);
    }
    @Override
    public BpmBusinessAttachDO getBusinessAttachByProcessDefinitionKey(String processDefinitionKey) {
        return businessAttachMapper.selectByProcessDefinitionKey(processDefinitionKey);
    }
    @Override
    public void fillBusinessForm(BpmProcessDefinitionRespVO definitionResp, String processDefinitionKey, String businessKey) {
        // æœªå‘èµ· / æ— ä¸šåŠ¡ä¸»é”®ï¼šä¸æ³¨å…¥
        if (definitionResp == null || StrUtil.isBlank(businessKey)) {
            return;
        }
        // éž NORMAL æµç¨‹è¡¨å•(已手动配置 CUSTOM):不覆盖
        if (!Objects.equals(definitionResp.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
            return;
        }
        // æœªå‘½ä¸­é…ç½® / é…ç½®è¢«ç¦ç”¨ï¼šä¿æŒåŽŸæ ·
        BpmBusinessAttachDO attach = getBusinessAttachByProcessDefinitionKey(processDefinitionKey);
        if (attach == null || !Objects.equals(attach.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
            return;
        }
        // è¦†ç›–为 CUSTOM,注入业务详情组件路径
        definitionResp.setFormType(BpmModelFormTypeEnum.CUSTOM.getType());
        definitionResp.setFormCustomViewPath(attach.getComponentPath());
        // æ¸…空普通表单字段:详情页 CUSTOM åˆ†æ”¯ä¸è¯»ï¼›æ‰“印页按 formFields.length == 0 åˆ¤æ–­æ¸²æŸ“业务组件
        definitionResp.setFormFields(null);
        definitionResp.setFormConf(null);
    }
}
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -37,6 +37,7 @@
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
import cn.iocoder.yudao.module.bpm.service.attach.BpmBusinessAttachService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@@ -123,6 +124,9 @@
    @Resource
    private BpmProcessIdRedisDAO processIdRedisDAO;
    @Resource
    private BpmBusinessAttachService businessAttachService;
    // ========== Query æŸ¥è¯¢ç›¸å…³æ–¹æ³• ==========
@@ -389,9 +393,14 @@
        Map<String, String> formFieldsPermission = getFormFieldsPermission(bpmnModel, reqVO.getActivityId(), taskId);
        // 3. æ‹¼æŽ¥æ•°æ®
        return BpmProcessInstanceConvert.INSTANCE.buildApprovalDetail(bpmnModel, processDefinition,
                processDefinitionInfo, processInstance,
        BpmApprovalDetailRespVO detailRespVO = BpmProcessInstanceConvert.INSTANCE.buildApprovalDetail(bpmnModel,
                processDefinition, processDefinitionInfo, processInstance,
                processInstanceStatus, approveNodes, todoTask, formFieldsPermission, userMap, deptMap);
        // 4. å¡«å……业务附件配置,实现审批详情自动展示外部业务信息
        businessAttachService.fillBusinessForm(detailRespVO.getProcessDefinition(), processDefinition.getKey(),
                processInstance != null ? processInstance.getBusinessKey() : null);
        return detailRespVO;
    }
    /**