lyh
2025-06-25 e756af0f5bfd1addbd5d5c145441fb34aad91a28
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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
package org.jeecg.modules.dnc.service.impl;
 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import liquibase.pro.packaged.S;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.dnc.dto.ComponentHierarchy;
import org.jeecg.modules.dnc.dto.TransferPackage;
import org.jeecg.modules.dnc.entity.*;
import org.jeecg.modules.dnc.exception.ExceptionCast;
import org.jeecg.modules.dnc.mapper.DocRelativeMapper;
import org.jeecg.modules.dnc.response.ActivitiCode;
import org.jeecg.modules.dnc.response.DocumentCode;
import org.jeecg.modules.dnc.service.IDocClassificationService;
import org.jeecg.modules.dnc.service.IDocFileService;
import org.jeecg.modules.dnc.service.IDocInfoService;
import org.jeecg.modules.dnc.service.IDocRelativeService;
import org.jeecg.modules.dnc.utils.CompressionUtils;
import org.jeecg.modules.dnc.utils.JsonUtils;
import org.jeecg.modules.dnc.utils.file.FileUtilS;
import org.jeecg.modules.dncFlow.service.IAssignFileStreamService;
import org.jeecg.modules.mdc.entity.MdcEquipment;
import org.jeecg.modules.mdc.mapper.MdcEquipmentMapper;
import org.jeecg.modules.system.service.IMdcProductionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
 
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
 
@Service
public class FileFerryService {
 
    private static final Logger logger = LoggerFactory.getLogger(FileFerryService.class);
 
    @Value("${deploy.secretFolder}")
    private String ferryPath;
 
    @Value("${fileHomePath}")
    private String fileHomePath;
 
    @Autowired
    private MdcEquipmentMapper mdcEquipmentMapper;
 
    @Autowired
    private IMdcProductionService mdcProductionService;
 
    @Autowired
    private IDocInfoService docInfoService;
 
    @Autowired
    private IDocClassificationService classificationService;
 
    @Autowired
    private IDocRelativeService docRelativeService;
    @Autowired
    private DataPackageService dataPackageService;
 
    public String exportData(TransferPackage.DataType type, String id,String fileName) {
        // 1. 获取封装数据
        TransferPackage transferPackage = dataPackageService.packageData(type, id);
 
        // 2. 压缩层级结构
        compressHierarchy(transferPackage);
 
        // 3. JSON序列化
        String json = JsonUtils.toJson(transferPackage);
 
//        // 4. 压缩加密
//        byte[] compressed = CompressionUtils.gzipCompress(json.getBytes(StandardCharsets.UTF_8));
//        byte[] encrypted = securityService.encrypt(compressed);
        //暂时不加密
        byte[] compressed = json.getBytes(StandardCharsets.UTF_8);
 
        // 5. 生成文件
        Path filePath = Paths.get(ferryPath,fileName);
        try {
            Files.createDirectories(filePath.getParent());
            Files.write(filePath, compressed);
            return filePath.toString();
        } catch (IOException e) {
            throw new RuntimeException("文件写入失败", e);
        }
    }
 
 
 
    public TransferPackage importData(String filePath) {
        try {
            // 1. 读取文件
            Path path = Paths.get(filePath);
            String fileName = path.getFileName().toString();
            byte[] encrypted = Files.readAllBytes(path);
            logger.debug("读取文件完成, 大小: {} 字节", encrypted.length);
 
            // 2. 解密 (当前已注释)
            // byte[] compressed = securityService.decrypt(encrypted);
 
            // 3. 解压缩
//            byte[] jsonBytes = CompressionUtils.gzipDecompress(encrypted);
            String json = new String(encrypted, StandardCharsets.UTF_8);
            logger.debug("解压缩完成, JSON长度: {} 字符", json.length());
 
            // 记录JSON内容用于调试
            logger.trace("原始JSON内容:\n{}", json);
 
            // 4. JSON反序列化
            logger.debug("开始反序列化...");
            TransferPackage pkg = JsonUtils.fromJson(json, TransferPackage.class);
 
            // 5. 处理文件名 - 示例: 10A20250614000026_3102038
            String[] split = fileName.split("_");
            if (split.length < 2) {
                throw new IllegalArgumentException("无效的文件名格式: " + fileName);
            }
 
            String id = split[0];
            String equipmentId = split[1].split("\\.")[0];
 
            // 提取前缀和数字部分
            int aIndex = id.indexOf("A");
            if (aIndex == -1 || aIndex == id.length() - 1) {
                throw new IllegalArgumentException("无效的ID格式: " + id);
            }
 
            String prefix = id.substring(0, aIndex + 1);
            String numericPart = id.substring(aIndex + 1);
 
            // 计算前一个文件名
            long number = Long.parseLong(numericPart);
            number--;  // 获取前一个序列号
 
            // 保持相同位数格式
            String newNumeric = String.format("%0" + numericPart.length() + "d", number);
            String ncFileName = prefix + newNumeric + "_" + equipmentId+".NC";
            String ncFilePath = path.getParent().resolve(ncFileName).toString();
 
            // 6. 获取文件复制目标路径
            DocFile docFile = pkg.getTraceChain().getDocFile();
            DocInfo docInfo = pkg.getTraceChain().getDocInfo();
            if (docFile == null) {
                throw new IllegalStateException("传输包中缺少文档文件信息");
            }
 
            // 构建目标路径
            String targetDirectory = fileHomePath + docFile.getFilePath();
            String targetPath = Paths.get(targetDirectory, docFile.getFileEncodeName()).toString();
 
            // 确保目标目录存在
            File targetDir = new File(targetDirectory);
            if (!targetDir.exists() && !targetDir.mkdirs()) {
                throw new IOException("无法创建目标目录: " + targetDirectory);
            }
 
            // 7. 复制文件并重命名
            logger.info("复制文件: {} → {}", ncFilePath, targetPath);
            Path source = Paths.get(ncFilePath);
            Files.copy(source, Paths.get(targetPath), StandardCopyOption.REPLACE_EXISTING);
 
            // 8. 查询设备id
            MdcEquipment mdcEquipment=mdcEquipmentMapper.selectOne(new QueryWrapper<MdcEquipment>().eq("equipment_id",equipmentId));
            if (mdcEquipment == null) {
                throw new IllegalArgumentException("无效的设备ID: " + equipmentId);
            }
 
            // 9.传输文件到设备下
            List<String> strings = mdcProductionService.findListParentTreeAll(mdcEquipment.getId());
            if (strings != null && !strings.isEmpty()) {
                DocInfo deviceDoc = docInfoService.getByDocAttrAndDocId(docInfo.getDocId(), 7, mdcEquipment.getId());
                if (deviceDoc == null) {
                    DocClassification classification = classificationService.getByCode("send");
                    if(classification == null)
                        ExceptionCast.cast(DocumentCode.DOC_CLASS_ERROR);
                    DocRelative docRelative = new DocRelative();
                    docRelative.setDocId(docInfo.getDocId());
                    docRelative.setClassificationId(classification.getClassificationId());
                    docRelative.setAttributionType(7);
                    docRelative.setAttributionId(mdcEquipment.getId());
                    docRelativeService.save(docRelative);
                }
                String sendPath = StringUtils.join(strings.toArray(), "/");
                boolean copyFileNc = FileUtilS.copyFileNc(docFile.getFilePath(), sendPath + "/" + mdcEquipment.getEquipmentId(),
                        docFile.getFileEncodeName(),
                        docFile.getFileName(), docFile.getFileSuffix());
                if (!copyFileNc) {
                    ExceptionCast.cast(ActivitiCode.ACT_FILE_ERROR);
                } else {
                    FileUtilS.deleteZipFromToSend(sendPath + "/" + mdcEquipment.getEquipmentId(),
                            docFile.getFileName(), docFile.getFileSuffix());
                }
            } else {
                throw new RuntimeException("文件传输路径获取失败");
            }
 
            // 10.删除临时NC文件与json文件
            logger.info("删除临时文件: {}", ncFilePath);
            Files.delete(source);
            Files.delete(path);
 
            return JsonUtils.fromJson(json, TransferPackage.class);
 
        } catch (NumberFormatException e) {
            throw new RuntimeException("文件名中的数字格式无效: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new RuntimeException("文件操作失败: " + e.getMessage(), e);
        } catch (Exception e) {
            logger.error("文件导入失败 [路径: {}]", filePath, e);
            throw new RuntimeException("文件导入失败: " + e.getMessage(), e);
        }
    }
 
    private void compressHierarchy(TransferPackage pkg) {
        if (pkg.getTraceChain() == null ||
                pkg.getTraceChain().getComponentHierarchy() == null ||
                pkg.getTraceChain().getComponentHierarchy().getComponents().size() < 4) {
            return;
        }
 
        ComponentHierarchy hierarchy = pkg.getTraceChain().getComponentHierarchy();
        List<ComponentInfo> compressed = new ArrayList<>();
 
        // 保留根部件
        compressed.add(hierarchy.getComponents().get(0));
 
        // 保留关键中间节点
        int step = Math.max(1, hierarchy.getComponents().size() / 3);
        for (int i = step; i < hierarchy.getComponents().size() - 1; i += step) {
            compressed.add(hierarchy.getComponents().get(i));
        }
 
        // 保留叶子部件
        compressed.add(hierarchy.getLeafComponent());
 
        // 更新层级
        hierarchy.getComponents().clear();
        hierarchy.getComponents().addAll(compressed);
    }
 
    private String generateFilename(TransferPackage.DataType type, String id) {
        return String.format("%s_%s_%d.ferry",
                type.name().toLowerCase(),
                id,
                System.currentTimeMillis());
    }
}