1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package com.ruoyi.technology.service.impl;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto;
import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo;
import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
import com.ruoyi.technology.pojo.TechnologyBomStructure;
import com.ruoyi.technology.service.TechnologyBomStructureService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.util.*;
 
@Service
@RequiredArgsConstructor
public class TechnologyBomStructureServiceImpl extends ServiceImpl<TechnologyBomStructureMapper, TechnologyBomStructure> implements TechnologyBomStructureService {
 
    private final TechnologyBomStructureMapper technologyBomStructureMapper;
 
    /**
     * 保存BOM结构树,处理新增、更新和删除节点。
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addTechnologyBomStructure(TechnologyBomStructureDto dto) {
        Long bomId = dto.getBomId();
        List<TechnologyBomStructureDto> flatDtoList = new ArrayList<>();
        flattenTree(dto.getChildren(), flatDtoList);
 
        List<TechnologyBomStructure> dbList = this.list(new LambdaQueryWrapper<TechnologyBomStructure>()
                .eq(TechnologyBomStructure::getBomId, bomId));
 
        Set<Long> frontendIds = new HashSet<>();
        for (TechnologyBomStructureDto item : flatDtoList) {
            if (item.getId() != null) {
                frontendIds.add(item.getId());
            }
        }
 
        Set<Long> deleteIds = new HashSet<>();
        for (TechnologyBomStructure dbItem : dbList) {
            if (!frontendIds.contains(dbItem.getId())) {
                deleteIds.add(dbItem.getId());
            }
        }
        if (!deleteIds.isEmpty()) {
            this.removeByIds(deleteIds);
        }
 
        List<TechnologyBomStructure> insertList = new ArrayList<>();
        List<TechnologyBomStructure> updateList = new ArrayList<>();
        Map<String, TechnologyBomStructure> tempEntityMap = new HashMap<>();
 
        for (TechnologyBomStructureDto item : flatDtoList) {
            TechnologyBomStructure entity = new TechnologyBomStructure();
            BeanUtils.copyProperties(item, entity);
            entity.setBomId(bomId);
            if (item.getId() == null) {
                entity.setParentId(null);
                insertList.add(entity);
                tempEntityMap.put(item.getTempId(), entity);
            } else {
                updateList.add(entity);
            }
        }
 
        if (!insertList.isEmpty()) {
            this.saveBatch(insertList);
        }
 
        List<TechnologyBomStructure> parentFixList = new ArrayList<>();
        for (TechnologyBomStructureDto item : flatDtoList) {
            if (item.getId() == null && item.getParentTempId() != null) {
                TechnologyBomStructure child = tempEntityMap.get(item.getTempId());
                if (child == null) {
                    continue;
                }
                TechnologyBomStructure parent = tempEntityMap.get(item.getParentTempId());
                Long realParentId = parent != null ? parent.getId() : Long.valueOf(item.getParentTempId());
                child.setParentId(realParentId);
                parentFixList.add(child);
            }
        }
 
        if (!parentFixList.isEmpty()) {
            this.updateBatchById(parentFixList);
        }
        if (!updateList.isEmpty()) {
            this.updateBatchById(updateList);
        }
        return true;
    }
 
    /**
     * 根据BOM查询并组装结构树。
     */
    @Override
    public List<TechnologyBomStructureVo> listByBomId(Long bomId) {
        List<TechnologyBomStructureVo> list = technologyBomStructureMapper.listByBomId(bomId);
        Map<Long, TechnologyBomStructureVo> map = new HashMap<>();
        for (TechnologyBomStructureVo node : list) {
            node.setChildren(new ArrayList<>());
            map.put(node.getId(), node);
        }
 
        List<TechnologyBomStructureVo> tree = new ArrayList<>();
        for (TechnologyBomStructureVo node : list) {
            Long parentId = node.getParentId();
            if (parentId == null || parentId == 0L) {
                tree.add(node);
                continue;
            }
            TechnologyBomStructureVo parent = map.get(parentId);
            if (parent != null) {
                parent.getChildren().add(node);
            }
        }
        return tree;
    }
 
    /**
     * 将树形结构拍平成列表,便于统一保存。
     */
    private void flattenTree(List<TechnologyBomStructureDto> source, List<TechnologyBomStructureDto> result) {
        if (source == null) {
            return;
        }
        for (TechnologyBomStructureDto node : source) {
            result.add(node);
            flattenTree(node.getChildren(), result);
        }
    }
}