package com.ruoyi.device.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.device.dto.DeviceAreaDto;
|
import com.ruoyi.device.mapper.DeviceAreaMapper;
|
import com.ruoyi.device.mapper.DeviceLedgerMapper;
|
import com.ruoyi.device.pojo.DeviceArea;
|
import com.ruoyi.device.pojo.DeviceLedger;
|
import com.ruoyi.device.service.IDeviceAreaService;
|
import com.ruoyi.device.vo.DeviceAreaTreeDto;
|
import com.ruoyi.framework.web.domain.AjaxResult;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.stream.Collectors;
|
|
/**
|
* 设备区域 Service 实现
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class DeviceAreaServiceImpl extends ServiceImpl<DeviceAreaMapper, DeviceArea> implements IDeviceAreaService {
|
|
private final DeviceAreaMapper deviceAreaMapper;
|
private final DeviceLedgerMapper deviceLedgerMapper;
|
|
@Override
|
public List<DeviceAreaTreeDto> selectAreaTree() {
|
List<DeviceArea> all = this.list(new LambdaQueryWrapper<DeviceArea>().orderByAsc(DeviceArea::getSort));
|
if (all == null || all.isEmpty()) {
|
return new ArrayList<>();
|
}
|
|
// 统计每个区域直接挂载的设备数量
|
Map<Long, Long> directCountMap = deviceLedgerMapper.selectList(
|
new LambdaQueryWrapper<DeviceLedger>()
|
.select(DeviceLedger::getAreaId)
|
.isNotNull(DeviceLedger::getAreaId))
|
.stream()
|
.filter(d -> d.getAreaId() != null)
|
.collect(Collectors.groupingBy(DeviceLedger::getAreaId, Collectors.counting()));
|
|
Map<Long, DeviceArea> areaMap = all.stream()
|
.collect(Collectors.toMap(DeviceArea::getId, a -> a));
|
|
// 递归汇总每个节点的设备数量(含所有子级)
|
Map<Long, Long> countMap = directCountMap.entrySet().stream()
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
for (DeviceArea area : all) {
|
accumulate(area.getId(), directCountMap.getOrDefault(area.getId(), 0L), countMap, areaMap);
|
}
|
|
List<Long> rootIds = all.stream()
|
.filter(a -> a.getParentId() == null || !areaMap.containsKey(a.getParentId()))
|
.map(DeviceArea::getId)
|
.collect(Collectors.toList());
|
|
List<DeviceAreaTreeDto> tree = new ArrayList<>();
|
for (Long rootId : rootIds) {
|
DeviceArea root = areaMap.get(rootId);
|
tree.add(buildNode(root, all, countMap));
|
}
|
return tree;
|
}
|
|
// 将当前节点数量累加到所有祖级节点
|
private void accumulate(Long areaId, Long count, Map<Long, Long> countMap, Map<Long, DeviceArea> areaMap) {
|
DeviceArea area = areaMap.get(areaId);
|
if (area == null) {
|
return;
|
}
|
countMap.merge(areaId, count, Long::sum);
|
// 沿祖先链继续累加(避免祖先链循环依赖)
|
if (area.getParentId() != null && areaMap.containsKey(area.getParentId())) {
|
accumulate(area.getParentId(), count, countMap, areaMap);
|
}
|
}
|
|
private DeviceAreaTreeDto buildNode(DeviceArea area, List<DeviceArea> all, Map<Long, Long> countMap) {
|
DeviceAreaTreeDto node = new DeviceAreaTreeDto();
|
node.setId(area.getId());
|
node.setParentId(area.getParentId());
|
node.setLabel(area.getName());
|
node.setDeviceCount(countMap.getOrDefault(area.getId(), 0L));
|
for (DeviceArea child : all) {
|
if (area.getId().equals(child.getParentId())) {
|
node.getChildren().add(buildNode(child, all, countMap));
|
}
|
}
|
return node;
|
}
|
|
@Override
|
public AjaxResult addArea(DeviceAreaDto dto) {
|
if (StringUtils.isEmpty(dto.getName())) {
|
return AjaxResult.error("区域名称不能为空");
|
}
|
DeviceArea area = new DeviceArea();
|
area.setName(dto.getName());
|
area.setParentId(dto.getParentId());
|
area.setSort(dto.getSort());
|
area.setDeptId(dto.getDeptId());
|
area.setTenantId(SecurityUtils.getLoginUser().getTenantId());
|
|
if (dto.getParentId() != null) {
|
DeviceArea parent = this.getById(dto.getParentId());
|
if (parent == null) {
|
return AjaxResult.error("父级区域不存在");
|
}
|
area.setAncestors(StringUtils.isEmpty(parent.getAncestors())
|
? String.valueOf(parent.getId())
|
: parent.getAncestors() + "," + parent.getId());
|
}
|
this.save(area);
|
return AjaxResult.success();
|
}
|
|
@Override
|
public AjaxResult updateArea(DeviceAreaDto dto) {
|
if (dto.getId() == null) {
|
return AjaxResult.error("区域ID不能为空");
|
}
|
DeviceArea area = this.getById(dto.getId());
|
if (area == null) {
|
return AjaxResult.error("区域不存在");
|
}
|
// 不允许把区域挂到自己的子级下,避免循环
|
if (dto.getParentId() != null && dto.getParentId().equals(dto.getId())) {
|
return AjaxResult.error("不能将区域挂载到自身");
|
}
|
if (dto.getParentId() != null && isDescendant(dto.getId(), dto.getParentId())) {
|
return AjaxResult.error("不能将区域挂载到自己的子级下");
|
}
|
area.setName(dto.getName());
|
area.setSort(dto.getSort());
|
area.setDeptId(dto.getDeptId());
|
if (!java.util.Objects.equals(dto.getParentId(), area.getParentId())) {
|
area.setParentId(dto.getParentId());
|
if (dto.getParentId() == null) {
|
area.setAncestors(null);
|
} else {
|
DeviceArea parent = this.getById(dto.getParentId());
|
if (parent == null) {
|
return AjaxResult.error("父级区域不存在");
|
}
|
area.setAncestors(StringUtils.isEmpty(parent.getAncestors())
|
? String.valueOf(parent.getId())
|
: parent.getAncestors() + "," + parent.getId());
|
}
|
}
|
this.updateById(area);
|
return AjaxResult.success();
|
}
|
|
private boolean isDescendant(Long targetId, Long candidateParentId) {
|
DeviceArea cur = this.getById(candidateParentId);
|
while (cur != null && cur.getParentId() != null) {
|
if (cur.getParentId().equals(targetId)) {
|
return true;
|
}
|
cur = this.getById(cur.getParentId());
|
}
|
return false;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public AjaxResult deleteArea(List<Long> ids) {
|
for (Long id : ids) {
|
DeviceArea area = this.getById(id);
|
if (area == null) {
|
return AjaxResult.error("区域不存在");
|
}
|
long childCount = this.count(new LambdaQueryWrapper<DeviceArea>().eq(DeviceArea::getParentId, id));
|
if (childCount > 0) {
|
return AjaxResult.error("该区域存在子级区域,请先删除子级");
|
}
|
long deviceCount = deviceLedgerMapper.selectCount(
|
new LambdaQueryWrapper<DeviceLedger>().eq(DeviceLedger::getAreaId, id));
|
if (deviceCount > 0) {
|
return AjaxResult.error("该区域下存在设备,请先移除设备关联");
|
}
|
}
|
this.removeByIds(ids);
|
return AjaxResult.success();
|
}
|
}
|