package com.ruoyi.approve.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.approve.bean.dto.ApprovalTemplateDto;
import com.ruoyi.approve.bean.vo.ApprovalTemplateNodeApproverVo;
import com.ruoyi.approve.bean.vo.ApprovalTemplateNodeVo;
import com.ruoyi.approve.bean.vo.ApprovalTemplateVo;
import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
import com.ruoyi.approve.mapper.ApprovalTemplateNodeApproverMapper;
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 lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
* 审批模板服务实现类
*
*
* @since 2026-05-18 11:20:08
*/
@Service
@RequiredArgsConstructor
public class ApprovalTemplateServiceImpl extends ServiceImpl implements ApprovalTemplateService {
private final ApprovalTemplateMapper approvalTemplateMapper;
private final ApprovalTemplateNodeService approvalTemplateNodeService;
private final ApprovalTemplateNodeApproverMapper approvalTemplateNodeApproverMapper;
@Override
public IPage listPage(Page page, ApprovalTemplateDto approvalTemplateDto) {
IPage approvalTemplateVoIPage = approvalTemplateMapper.listPage(page, approvalTemplateDto);
fillTemplateVoNodes(approvalTemplateVoIPage.getRecords());
return approvalTemplateVoIPage;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean saveApprovalTemplateDto(ApprovalTemplateDto approvalTemplateDto) {
approvalTemplateMapper.insert(approvalTemplateDto);
approvalTemplateNodeService.remove(
new LambdaQueryWrapper()
.eq(ApprovalTemplateNode::getTemplateId, approvalTemplateDto.getId())
);
approvalTemplateNodeApproverMapper.delete(
new LambdaQueryWrapper()
.eq(ApprovalTemplateNodeApprover::getTemplateId, approvalTemplateDto.getId())
);
return approvalTemplateNodeService.saveApprovalTemplateNode(
approvalTemplateDto.getId(),
approvalTemplateDto.getNodes()
);
}
@Override
public Boolean updateApprovalTemplateDto(ApprovalTemplateDto approvalTemplateDto) {
approvalTemplateMapper.updateById(approvalTemplateDto);
approvalTemplateNodeService.remove(
new LambdaQueryWrapper()
.eq(ApprovalTemplateNode::getTemplateId, approvalTemplateDto.getId())
);
approvalTemplateNodeApproverMapper.delete(
new LambdaQueryWrapper()
.eq(ApprovalTemplateNodeApprover::getTemplateId, approvalTemplateDto.getId())
);
return approvalTemplateNodeService.saveApprovalTemplateNode(
approvalTemplateDto.getId(),
approvalTemplateDto.getNodes()
);
}
@Transactional(rollbackFor = Exception.class)
public Boolean delete(List ids) {
if (ids == null || ids.isEmpty()) {
return false;
}
ApprovalTemplate updateEntity = new ApprovalTemplate();
updateEntity.setDeleted(1);
LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate();
updateWrapper.in(ApprovalTemplate::getId, ids)
.eq(ApprovalTemplate::getDeleted, 0);
int rows = approvalTemplateMapper.update(updateEntity, updateWrapper);
return rows == ids.size();
}
@Override
public List listApprovalTemplateVo(Integer type) {
List templateList = this.list(
new LambdaQueryWrapper()
.eq(ApprovalTemplate::getDeleted, 0)
.eq(ApprovalTemplate::getEnabled, 1)
.eq(type != null, ApprovalTemplate::getTemplateType, type)
.orderByDesc(ApprovalTemplate::getTemplateType)
.orderByDesc(ApprovalTemplate::getId)
);
if (CollUtil.isEmpty(templateList)) {
return Collections.emptyList();
}
List templateVos = templateList.stream()
.map(template -> {
ApprovalTemplateVo templateVo = new ApprovalTemplateVo();
BeanUtils.copyProperties(template, templateVo);
return templateVo;
})
.collect(Collectors.toList());
fillTemplateVoNodes(templateVos);
return templateVos;
}
@Override
public ApprovalTemplateVo getApprovalTemplateVoById(Long id) {
if (id == null) {
throw new IllegalArgumentException("参数 id 不能为空");
}
ApprovalTemplate template = this.getOne(
new LambdaQueryWrapper()
.eq(ApprovalTemplate::getId, id)
.eq(ApprovalTemplate::getDeleted, 0)
);
if (template == null) {
throw new IllegalArgumentException("模板不存在");
}
List nodeList = approvalTemplateNodeService.list(
new LambdaQueryWrapper()
.eq(ApprovalTemplateNode::getTemplateId, id)
.orderByAsc(ApprovalTemplateNode::getLevelNo)
);
List approverList = approvalTemplateNodeApproverMapper.selectList(
new LambdaQueryWrapper()
.eq(ApprovalTemplateNodeApprover::getTemplateId, id)
.eq(ApprovalTemplateNodeApprover::getDeleted, 0L)
);
Map> nodeMap = nodeList.stream()
.collect(Collectors.groupingBy(ApprovalTemplateNode::getTemplateId));
Map> approverMap = approverList.stream()
.collect(Collectors.groupingBy(ApprovalTemplateNodeApprover::getNodeId));
return buildTemplateVo(template, nodeMap, approverMap);
}
/**
* 批量填充模板节点及节点审批人,避免循环查库。
*/
private void fillTemplateVoNodes(List templateVos) {
if (CollUtil.isEmpty(templateVos)) {
return;
}
List templateIds = templateVos.stream()
.map(ApprovalTemplateVo::getId)
.collect(Collectors.toList());
List nodeList = approvalTemplateNodeService.list(
new LambdaQueryWrapper()
.in(ApprovalTemplateNode::getTemplateId, templateIds)
.orderByAsc(ApprovalTemplateNode::getLevelNo)
);
List approverList = approvalTemplateNodeApproverMapper.selectList(
new LambdaQueryWrapper()
.in(ApprovalTemplateNodeApprover::getTemplateId, templateIds)
.eq(ApprovalTemplateNodeApprover::getDeleted, 0L)
);
Map> nodeMap = nodeList.stream()
.collect(Collectors.groupingBy(ApprovalTemplateNode::getTemplateId));
Map> approverMap = approverList.stream()
.collect(Collectors.groupingBy(ApprovalTemplateNodeApprover::getNodeId));
templateVos.forEach(templateVo -> templateVo.setNodes(
nodeMap.getOrDefault(templateVo.getId(), Collections.emptyList())
.stream()
.sorted(Comparator.comparing(
ApprovalTemplateNode::getLevelNo,
Comparator.nullsLast(Integer::compareTo)
))
.map(node -> buildNodeVo(node, approverMap))
.collect(Collectors.toList())
));
}
private ApprovalTemplateVo buildTemplateVo(ApprovalTemplate template,
Map> nodeMap,
Map> approverMap) {
ApprovalTemplateVo templateVo = new ApprovalTemplateVo();
BeanUtils.copyProperties(template, templateVo);
List nodeVos = nodeMap
.getOrDefault(template.getId(), Collections.emptyList())
.stream()
.sorted(Comparator.comparing(
ApprovalTemplateNode::getLevelNo,
Comparator.nullsLast(Integer::compareTo)
))
.map(node -> buildNodeVo(node, approverMap))
.collect(Collectors.toList());
templateVo.setNodes(nodeVos);
return templateVo;
}
private ApprovalTemplateNodeVo buildNodeVo(ApprovalTemplateNode node,
Map> approverMap) {
ApprovalTemplateNodeVo nodeVo = new ApprovalTemplateNodeVo();
BeanUtils.copyProperties(node, nodeVo);
List approverVos = approverMap
.getOrDefault(node.getId(), Collections.emptyList())
.stream()
.sorted(Comparator.comparing(
ApprovalTemplateNodeApprover::getSortNo,
Comparator.nullsLast(Integer::compareTo)
))
.map(this::buildApproverVo)
.collect(Collectors.toList());
nodeVo.setApprovers(approverVos);
return nodeVo;
}
private ApprovalTemplateNodeApproverVo buildApproverVo(ApprovalTemplateNodeApprover approver) {
ApprovalTemplateNodeApproverVo approverVo = new ApprovalTemplateNodeApproverVo();
BeanUtils.copyProperties(approver, approverVo);
return approverVo;
}
}