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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package org.jeecg.modules.dnc.service.impl;
 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.dnc.entity.*;
import org.jeecg.modules.dnc.mapper.ProductMixMapper;
import org.jeecg.modules.dnc.service.*;
import org.jeecg.modules.dnc.utils.TreeBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
 
import java.util.*;
import java.util.stream.Collectors;
 
@Service
public class ProductMixServiceImpl extends ServiceImpl<ProductMixMapper, ProductMix> implements IProductMixService {
 
    @Autowired
    private IPermissionStreamNewService permissionStreamNewService;
 
    @Autowired
    @Lazy
    private IDeviceTypeService deviceTypeService;
 
    @Autowired
    @Lazy
    private IDeviceManagementService deviceManagementService;
 
    @Autowired
    @Lazy
    private IDocInfoService docInfoService;
 
    @Autowired
    @Lazy
    private IDocRelativeService docRelativeService;
    /**
     * 默认结构树查询
     * @return
     */
    @Override
    public List<ProductMix> getTree() {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<ProductMix> rawData = new ArrayList<>();
        if (loginUser.getUsername().equals("admin")) {
            //不需要权限过滤
            rawData=permissionStreamNewService.loadProductMixAll(loginUser.getId());
        }else{
            //需要权限过滤
            String productIds = loginUser.getProductionIds();
            if (productIds != null && !productIds.isEmpty()) {
                List<String> productIdList = Arrays.asList(productIds.split(","));
                rawData = permissionStreamNewService.loadProductMix(loginUser.getId(),productIdList);
            }
        }
        TreeBuilder builder = new TreeBuilder();
        TreeBuilder.CleanResult cleanResult = builder.preprocessData(rawData);
        List<ProductMix> sorted = builder.topologicalSort(
                cleanResult.getValidNodes(),
                cleanResult.getNodeMap()
        );
        List<ProductMix> result =builder.assembleTree(sorted, cleanResult.getNodeMap());
        result.sort(Comparator.comparing(ProductMix::getCreateTime, Comparator.nullsLast(Date::compareTo)));
        return result;
    }
 
    @Override
    public List<ProductMix> getParentList(String id) {
        List<ProductMix> parentList = new ArrayList<>();
        // 1. 根据ID查询当前节点
        ProductMix current = this.getById(id);
        if (current == null) {
            return parentList; // 节点不存在时返回空列表
        }
        // 2. 从当前节点开始向上查找父节点
        Long parentId = current.getParentId();
        while ( parentId != 0L) {
            ProductMix parent = this.getById(parentId.toString());
            if (parent == null) {
                break;
            }
            parentList.add(parent);
            parentId = parent.getParentId();
        }
 
        return parentList;
    }
 
    @Override
    public List<ProductMix> getChildrenList(String id) {
        List<ProductMix> childrenList = new ArrayList<>();
        ProductMix current = this.getById(id);
        if (current == null) {
            return childrenList;
        }
 
        // 使用队列进行BFS
        Queue<ProductMix> queue = new LinkedList<>();
        queue.add(current); // 加入当前节点作为起点
 
        // 记录已访问节点的ID,避免循环引用
        Set<String> visited = new HashSet<>();
        visited.add(id); // 起始节点已访问
 
        while (!queue.isEmpty()) {
            ProductMix node = queue.poll();
            // 跳过起始节点(即传入的节点),不加入结果列表
            if (!node.getId().toString().equals(id)) {
                childrenList.add(node);
            }
 
            // 查询当前节点的直接子节点
            List<ProductMix> directChildren = this.lambdaQuery().eq(ProductMix::getParentId, node.getId()).list();
            if (directChildren != null && !directChildren.isEmpty()) {
                for (ProductMix child : directChildren) {
                    String childId = child.getId().toString();
                    // 如果该子节点还未访问过
                    if (!visited.contains(childId)) {
                        visited.add(childId);
                        queue.add(child);
                    }
                    // 否则忽略,避免循环引用导致的死循环
                }
            }
        }
        return childrenList;
    }
 
    /**
     * 查询产品结构树(包括设备类与nc文件)
     * @return
     */
    @Override
    public List<ProductMix> getProductMixTree() {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<ProductMix> rawData = new ArrayList<>();
        if (loginUser.getUsername().equals("admin")) {
            //不需要权限过滤
            rawData = permissionStreamNewService.loadProductMixAll(loginUser.getId());
        } else {
            //需要权限过滤
            String productIds = loginUser.getProductionIds();
            if (productIds != null && !productIds.isEmpty()) {
                List<String> productIdList = Arrays.asList(productIds.split(","));
                rawData = permissionStreamNewService.loadProductMix(loginUser.getId(), productIdList);
            }
        }
        List<Long> ids = rawData.stream()
                .filter(p -> p.getType() != null)
                .filter(productMix -> productMix.getType() == 5 || productMix.getType() == 6)
                .map(ProductMix::getId)
                .collect(Collectors.toList());
        if (ids.isEmpty()) {
            return rawData;
        }
        //过滤设备类关联信息
        List<DeviceType> deviceTypeList = deviceTypeService.list(new QueryWrapper<DeviceType>()
                .in("attribution_id", ids));
        List<ProductMix> productMixList = new ArrayList<>();
        deviceTypeList.forEach(item->{
            ProductMix productMix = new ProductMix();
            productMix.setId(Long.parseLong(item.getId()));
            productMix.setParentId(Long.parseLong(item.getAttributionId()));
            DeviceManagement deviceManagement=deviceManagementService.getById(item.getDeviceManagementId());
            productMix.setTreeCode(deviceManagement.getDeviceManagementCode());
            productMix.setTreeName(deviceManagement.getDeviceManagementName());
            productMix.setType(7);
            productMixList.add(productMix);
        });
        rawData.addAll(productMixList);
        //过滤文档关联信息
        List<String> deviceTypeIds = deviceTypeList.stream().map(DeviceType::getId).collect(Collectors.toList());
        List<DocRelative> relativeList = docRelativeService.list(new QueryWrapper<DocRelative>()
                .in("attribution_id", deviceTypeIds));
        List<ProductMix> docList = new ArrayList<>();
        relativeList.forEach(item->{
            ProductMix productMix = new ProductMix();
            productMix.setId(Long.parseLong(item.getId()));
            productMix.setParentId(Long.parseLong(item.getAttributionId()));
            DocInfo docInfo = docInfoService.getById(item.getDocId());
            productMix.setTreeCode(docInfo.getDocSuffix());
            productMix.setTreeName(docInfo.getDocName());
            productMix.setType(99);
            docList.add(productMix);
        });
        rawData.addAll(docList);
        TreeBuilder builder = new TreeBuilder();
        TreeBuilder.CleanResult cleanResult = builder.preprocessData(rawData);
        List<ProductMix> sorted = builder.topologicalSort(
                cleanResult.getValidNodes(),
                cleanResult.getNodeMap()
        );
        List<ProductMix> result =builder.assembleTree(sorted, cleanResult.getNodeMap());
        result.sort(Comparator.comparing(ProductMix::getCreateTime, Comparator.nullsLast(Date::compareTo)));
        return result;
    }
}