src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java
@@ -13,15 +13,22 @@
import com.ruoyi.approve.bean.vo.ApprovalTemplateVo;
import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
import com.ruoyi.approve.mapper.ApprovalTemplateNodeApproverMapper;
import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
import com.ruoyi.approve.pojo.ApprovalInstance;
import com.ruoyi.approve.pojo.ApprovalTemplate;
import com.ruoyi.approve.pojo.ApprovalTemplateNode;
import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
import com.ruoyi.approve.service.ApprovalTemplateNodeService;
import com.ruoyi.approve.service.ApprovalTemplateService;
import com.ruoyi.basic.dto.StorageBlobDTO;
import com.ruoyi.basic.enums.ApplicationTypeEnum;
import com.ruoyi.basic.enums.RecordTypeEnum;
import com.ruoyi.basic.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.Comparator;
@@ -43,6 +50,8 @@
    private final ApprovalTemplateMapper approvalTemplateMapper;
    private final ApprovalTemplateNodeService approvalTemplateNodeService;
    private final ApprovalTemplateNodeApproverMapper approvalTemplateNodeApproverMapper;
    private final ApprovalInstanceMapper approvalInstanceMapper;
    private final FileUtil fileUtil;
    @Override
    public IPage<ApprovalTemplateVo> listPage(Page<ApprovalTemplateVo> page, ApprovalTemplateDto approvalTemplateDto) {
@@ -63,6 +72,11 @@
                new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
                        .eq(ApprovalTemplateNodeApprover::getTemplateId, approvalTemplateDto.getId())
        );
        // 保存附件
        List<StorageBlobDTO> storageBlobDTOs = approvalTemplateDto.getStorageBlobDTOs();
        if (!CollectionUtils.isEmpty(storageBlobDTOs)) {
            fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_TEMPLATE, approvalTemplateDto.getId(), storageBlobDTOs);
        }
        return approvalTemplateNodeService.saveApprovalTemplateNode(
                approvalTemplateDto.getId(),
                approvalTemplateDto.getNodes()
@@ -71,6 +85,10 @@
    @Override
    public Boolean updateApprovalTemplateDto(ApprovalTemplateDto approvalTemplateDto) {
        // 检查模板是否被审批实例引用
        if (isTemplateReferenced(approvalTemplateDto.getId())) {
            throw new RuntimeException("该审批模板已被审批流程引用,无法编辑");
        }
        approvalTemplateMapper.updateById(approvalTemplateDto);
        approvalTemplateNodeService.remove(
                new LambdaQueryWrapper<ApprovalTemplateNode>()
@@ -80,6 +98,16 @@
                new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
                        .eq(ApprovalTemplateNodeApprover::getTemplateId, approvalTemplateDto.getId())
        );
        // 保存附件(会先删除旧附件)
        List<StorageBlobDTO> storageBlobDTOs = approvalTemplateDto.getStorageBlobDTOs();
        if (!CollectionUtils.isEmpty(storageBlobDTOs)) {
            fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_TEMPLATE, approvalTemplateDto.getId(), storageBlobDTOs);
        } else {
            // 如果前端传空数组,删除旧附件
            fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordId(
                    ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_TEMPLATE, approvalTemplateDto.getId()
            );
        }
        return approvalTemplateNodeService.saveApprovalTemplateNode(
                approvalTemplateDto.getId(),
                approvalTemplateDto.getNodes()
@@ -90,6 +118,12 @@
    public Boolean delete(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return false;
        }
        // 检查模板是否被审批实例引用
        for (Long id : ids) {
            if (isTemplateReferenced(id)) {
                throw new RuntimeException("审批模板(ID: " + id + ")已被审批流程引用,无法删除");
            }
        }
        ApprovalTemplate updateEntity = new ApprovalTemplate();
        updateEntity.setDeleted(1);
@@ -107,7 +141,7 @@
                new LambdaQueryWrapper<ApprovalTemplate>()
                        .eq(ApprovalTemplate::getDeleted, 0)
                        .eq(ApprovalTemplate::getEnabled, 1)
                        .eq(type != null, ApprovalTemplate::getTemplateType, type)
                        .notIn(ApprovalTemplate::getBusinessType, List.of(5L, 6L, 7L))
                        .orderByDesc(ApprovalTemplate::getTemplateType)
                        .orderByDesc(ApprovalTemplate::getId)
        );
@@ -221,6 +255,12 @@
                .collect(Collectors.toList());
        templateVo.setNodes(nodeVos);
        // 查询附件
        templateVo.setStorageBlobDTOs(
                fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(
                        ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_TEMPLATE, template.getId()
                )
        );
        return templateVo;
    }
@@ -248,4 +288,21 @@
        BeanUtils.copyProperties(approver, approverVo);
        return approverVo;
    }
    /**
     * 检查审批模板是否被审批实例引用
     * @param templateId 模板ID
     * @return true 表示被引用,false 表示未被引用
     */
    private boolean isTemplateReferenced(Long templateId) {
        if (templateId == null) {
            return false;
        }
        Long count = approvalInstanceMapper.selectCount(
                new LambdaQueryWrapper<ApprovalInstance>()
                        .eq(ApprovalInstance::getTemplateId, templateId)
                        .eq(ApprovalInstance::getDeleted, 0)
        );
        return count != null && count > 0;
    }
}