lyh
2025-06-16 24e0bdd24a10449c98013cdb5bcc5e37735f5a91
对接刀具系统,涉密网封装结构树与文件
已重命名1个文件
已添加14个文件
已修改28个文件
1813 ■■■■■ 文件已修改
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/constant/DncPassLogPassType.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/dto/ComponentHierarchy.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/dto/ProcessTraceChain.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/dto/TransferPackage.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/entity/ProductMix.java 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/ext/NcTxtFilePathInfo.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ComponentInfoMapper.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/PartsInfoMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ProcessSpecVersionMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ProcessStreamMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ProductInfoMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ProductMixMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/WorkStepMapper.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/xml/ComponentInfoMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/xml/PermissionStreamNewMapper.xml 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/DataPackageStrategy.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/IProductInfoService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/IProductMixService.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ComponentInfoSeServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DataImportService.java 455 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DataPackageService.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DevicePermissionServiceImpl.java 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DocInfoServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/FileFerryService.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/FullHierarchyTraceService.java 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/PartsInfoServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessPackageStrategy.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessSpecVersionServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessStreamServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessionDepartmentServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProductInfoServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProductMixServiceImpl.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProductPermissionServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/SecurityService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/WorkStepPackageStrategy.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/WorkStepServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/utils/CompressionUtils.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/utils/JsonUtils.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/utils/TreeBuilder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/service/IAssignFileStreamService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/service/impl/AssignFileStreamServiceImpl.java 139 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/service/IMdcProductionService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/service/impl/MdcProductionServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/constant/DncPassLogPassType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package org.jeecg.modules.dnc.constant;
public enum DncPassLogPassType {
    //NC文件
    DOCUMENT("01", "nc文件"),
    //nc文件
    NCFILE("02", "NC文件"),
    //产品结构树
    PRODUCTSTRUCTURE("03", "产品结构树"),
    //程序加工确认表
    PROGRAMPROCESSING("04", "程序加工确认表");
    private String code;
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    DncPassLogPassType() {
    }
    DncPassLogPassType(String code, String name) {
        this.code = code;
        this.name = name;
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/dto/ComponentHierarchy.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package org.jeecg.modules.dnc.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import org.jeecg.modules.dnc.entity.ComponentInfo;
import org.jeecg.modules.dnc.entity.ProductInfo;
import java.util.ArrayList;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class ComponentHierarchy {
    private ProductInfo rootProduct;
    private final List<ComponentInfo> components = new ArrayList<>(); // ä»Žæ ¹éƒ¨ä»¶åˆ°åº•层部件的顺序
    public void addComponentToTop(ComponentInfo component) {
        components.add(0, component);
    }
    public List<ComponentInfo> getComponentsFromTop() {
        return new ArrayList<>(components);
    }
    public ComponentInfo getLeafComponent() {
        return components.isEmpty() ? null : components.get(components.size() - 1);
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/dto/ProcessTraceChain.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
package org.jeecg.modules.dnc.dto;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Data;
import org.jeecg.modules.dnc.entity.*;
import java.util.List;
/**
 * @Description: æ¶‰å¯†ç½‘同步工控网需要的数据
 * @Author: lyh
 * @Date:   2025-06-13
 * @Version: V1.0
 * @remark: åŽç»­éœ€è¦å¢žåŠ ï¼Œæ·»åŠ å¯¹åº”å‚æ•°ä¸Žç»“æž„æ•°æ®ï¼Œé‡‡ç”¨JSON序列化与反序列化进行传输,方便传输(加密操作,避免数据污染)
 */
@Data
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class ProcessTraceChain {
    /**程序加工确认表*/
    private GuideCardBatch guideCardBatch;
    /**刀具列表*/
    private List<Cutter> cutterList;
    /**文件*/
    private DocFile docFile;
    /**设备文档对应关系*/
    private DocRelative docRelative;
    /**文档*/
    private DocInfo docInfo;
    /**设备类*/
    private DeviceType deviceType;
    /**设备类对应关系*/
    private DeviceManagement deviceManagement;
    /**工步*/
    private WorkStep workStep;
    /**工序*/
    private ProcessStream process;
    /**工艺规程版本*/
    private ProcessSpecVersion processSpec;
    /**零件*/
    private PartsInfo parts;
    /**部件*/
    private ComponentHierarchy componentHierarchy;
    /**产品*/
    private ProductInfo product;
    /**产品树路径*/
    private List<ProductMix> treePath;
    /**权限表*/
    private List<PermissionStreamNew> permissionStreamNewList;
    @JsonCreator
    public ProcessTraceChain(
            @JsonProperty("guideCardBatch") GuideCardBatch guideCardBatch,
            @JsonProperty("cutterList") List<Cutter> cutterList,
            @JsonProperty("docFile") DocFile docFile,
            @JsonProperty("docRelative") DocRelative docRelative,
            @JsonProperty("docInfo") DocInfo docInfo,
            @JsonProperty("deviceType") DeviceType deviceType,
            @JsonProperty("deviceManagement") DeviceManagement deviceManagement,
            @JsonProperty("workStep") WorkStep workStep,
            @JsonProperty("process") ProcessStream process,
            @JsonProperty("processSpec") ProcessSpecVersion processSpec,
            @JsonProperty("parts") PartsInfo parts,
            @JsonProperty("componentHierarchy") ComponentHierarchy componentHierarchy,
            @JsonProperty("product") ProductInfo product,
            @JsonProperty("treePath") List<ProductMix> treePath,
            @JsonProperty("permissionStreamNewList") List<PermissionStreamNew> permissionStreamNewList
    ) {
        this.guideCardBatch = guideCardBatch;
        this.cutterList = cutterList;
        this.docFile = docFile;
        this.docRelative = docRelative;
        this.docInfo = docInfo;
        this.deviceType = deviceType;
        this.deviceManagement = deviceManagement;
        this.workStep = workStep;
        this.process = process;
        this.processSpec = processSpec;
        this.parts = parts;
        this.componentHierarchy = componentHierarchy;
        this.product = product;
        this.treePath = treePath;
        this.permissionStreamNewList = permissionStreamNewList;
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/dto/TransferPackage.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package org.jeecg.modules.dnc.dto;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Data;
import org.jeecg.modules.dnc.entity.DocRelative;
@Data
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class TransferPackage {
    public enum DataType { PROCESS, WORKSTEP }
    private final DataType dataType;
    private final DocRelative docRelative;
    private final ProcessTraceChain traceChain;
    @JsonCreator
    public TransferPackage(
            @JsonProperty("dataType") DataType dataType,
            @JsonProperty("docRelative")  DocRelative docRelative,
            @JsonProperty("traceChain") ProcessTraceChain traceChain
    ) {
        this.dataType = dataType;
        this.docRelative = docRelative;
        this.traceChain = traceChain;
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/entity/ProductMix.java
@@ -6,7 +6,6 @@
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@@ -14,7 +13,6 @@
import java.util.Date;
import java.util.List;
@Getter
@Data
@NoArgsConstructor
@TableName(value = "nc_product_mix")
@@ -29,13 +27,13 @@
    private Long parentId;
    // åç§°
    @TableField(value = "tree_name")
    private String name;
    private String treeName;
    // code
    @TableField(value = "tree_code")
    private String code;
    private String treeCode;
    // ç±»åž‹
    @TableField(value = "tree_type")
    private Integer type;
    private Integer treeType;
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    @TableField(value = "create_time")
    private Date createTime;
@@ -43,17 +41,20 @@
    //展示名称
    private transient String label;
    //类型方便前端展示
    private transient Integer type;
    private transient List<ProductMix> children = new ArrayList<>();
    public ProductMix(Long id, Long parentId, String name, String code, Integer type, Date createTime) {
    public ProductMix(Long id, Long parentId, String treeName, String treeCode, Integer type, Date createTime) {
        this.id = id;
        this.parentId = parentId;
        this.name = name;
        this.code = code;
        this.treeName = treeName;
        this.treeCode = treeCode;
        this.type = type;
        this.children = new ArrayList<>();
        this.label="["+code+"]"+name;
        this.label="["+treeCode+"]"+treeName;
        this.createTime = createTime;
    }
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/ext/NcTxtFilePathInfo.java
@@ -24,6 +24,18 @@
    private Integer fileAddOrDelete;
    /*文件大小*/
    private String fileSize;
    /*产品添加执行语句*/
    private String productAddSql;
    /*部件添加执行语句*/
    private String componentAddSql;
    /*零件添加执行语句*/
    private String partAddSql;
    /*工艺规程版本添加执行语句*/
    private String processVersionAddSql;
    /*工序版本添加执行语句*/
    private String processAddSql;
    /*工步版本添加执行语句*/
    private String processStepAddSql;
    @Override
    public String toString() {
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ComponentInfoMapper.java
@@ -1,9 +1,9 @@
package org.jeecg.modules.dnc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.dnc.dto.ComponentExt;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.dnc.dto.ComponentExt;
import org.jeecg.modules.dnc.entity.ComponentInfo;
import java.util.List;
@@ -38,4 +38,10 @@
     */
    List<ComponentExt> getByParentIdAndUserPerms(@Param("parentId") String parentId, @Param("userId") String userId);
    @Select("SELECT * FROM nc_component_info WHERE component_id = #{componentId}")
    ComponentInfo selectById(@Param("componentId") String componentId);
    // é€’归查询部件层级结构
    List<ComponentInfo> findComponentHierarchy(@Param("componentId") String componentId);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/PartsInfoMapper.java
@@ -1,8 +1,9 @@
package org.jeecg.modules.dnc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.dnc.entity.PartsInfo;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.dnc.entity.PartsInfo;
import java.util.List;
@@ -14,4 +15,7 @@
     * @return
     */
    List<PartsInfo> getByUserPerms(@Param("userId") String userId);
    @Select("SELECT * FROM nc_parts_info WHERE parts_id = #{partsId}")
    PartsInfo selectById(@Param("partsId") String partsId);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ProcessSpecVersionMapper.java
@@ -1,8 +1,9 @@
package org.jeecg.modules.dnc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.lettuce.core.dynamic.annotation.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.dnc.entity.ProcessSpecVersion;
import org.jeecg.modules.dnc.entity.WorkStep;
import java.util.List;
@@ -14,4 +15,7 @@
     * @return
     */
    List<ProcessSpecVersion> getByUserPerms(String userId);
    @Select("SELECT * FROM nc_process_spec_version WHERE id = #{id}")
    ProcessSpecVersion selectById(@Param("id") String id);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ProcessStreamMapper.java
@@ -1,6 +1,8 @@
package org.jeecg.modules.dnc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.lettuce.core.dynamic.annotation.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.dnc.entity.ProcessStream;
import java.util.List;
@@ -22,4 +24,6 @@
     */
    List<ProcessStream> findByPartsAndComponents(String productId, List<String> componentIds, List<String> partsIds);
    @Select("SELECT * FROM nc_process_stream WHERE process_id = #{processId}")
    ProcessStream selectById(@Param("processId") String processId);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ProductInfoMapper.java
@@ -1,8 +1,9 @@
package org.jeecg.modules.dnc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.dnc.entity.ProductInfo;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.dnc.entity.ProductInfo;
import java.util.List;
@@ -13,4 +14,7 @@
     * @return
     */
    List<ProductInfo> getByUserPerms(@Param("userId") String userId);
    @Select("SELECT * FROM nc_product_info WHERE product_id = #{productId}")
    ProductInfo selectById(@Param("productId") String productId);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/ProductMixMapper.java
@@ -1,7 +1,29 @@
package org.jeecg.modules.dnc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.lettuce.core.dynamic.annotation.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.dnc.entity.ProductMix;
public interface ProductMixMapper extends BaseMapper<ProductMix> {
    @Select("SELECT * FROM nc_product_mix WHERE id = #{productId} AND tree_type = 1")
    ProductMix findByProductId(@Param("productId") String productId);
    @Select("SELECT * FROM nc_product_mix WHERE id = #{componentId} AND tree_type = 2")
    ProductMix findByComponentId(@Param("componentId") String componentId);
    @Select("SELECT * FROM nc_product_mix WHERE id = #{partsId} AND tree_type = 3")
    ProductMix findByPartsId(@Param("partsId") String partsId);
    @Select("SELECT * FROM nc_product_mix WHERE id = #{operationId} AND tree_type = 4")
    ProductMix findByOperationId(@Param("operationId") String operationId);
    @Select("SELECT * FROM nc_product_mix WHERE id = #{processId} AND tree_type = 5")
    ProductMix findByProcessId(@Param("operationId") String processId);
    @Select("SELECT * FROM nc_product_mix WHERE id = #{worksiteId} AND tree_type = 6")
    ProductMix findByWorksiteId(@Param("operationId") String worksiteId);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/WorkStepMapper.java
@@ -1,7 +1,8 @@
package org.jeecg.modules.dnc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.dnc.entity.SynchronizedFlag;
import io.lettuce.core.dynamic.annotation.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.dnc.entity.WorkStep;
import java.util.List;
@@ -13,4 +14,10 @@
     * @return
     */
    List<WorkStep> getByUserPerms(String userId);
    @Select("SELECT * FROM nc_work_step WHERE id = #{workStepId}")
    WorkStep selectById(@Param("workStepId") String workStepId);
    @Select("SELECT * FROM nc_work_step WHERE process_id = #{processId}")
    List<WorkStep> selectByProcessId(@Param("processId") String processId);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/xml/ComponentInfoMapper.xml
@@ -158,4 +158,26 @@
        on comp.component_id=s.component_id
        where delete_flag = 0 and parent_id=#{parentId}
    </select>
    <select id="findComponentHierarchy" resultType="org.jeecg.modules.dnc.entity.ComponentInfo">
        WITH component_tree AS (
            SELECT
                *,
                0 AS LEVEL
            FROM
                nc_component_info
            WHERE
                component_id = #{componentId} UNION ALL
            SELECT
                c.*,
                ct.level + 1
            FROM
                nc_component_info c
                    INNER JOIN component_tree ct ON c.component_id = ct.parent_id
        ) SELECT
            *
        FROM
            component_tree
        ORDER BY
            LEVEL ASC
    </select>
</mapper>
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/mapper/xml/PermissionStreamNewMapper.xml
@@ -4,8 +4,8 @@
    <select id="loadProductMix" resultType="org.jeecg.modules.dnc.entity.ProductMix">
        SELECT DISTINCT
            mix.id,
            mix.tree_code 'code',
                mix.tree_name 'name',
            mix.tree_code,
            mix.tree_name,
            mix.parent_id,
            mix.tree_type AS 'type',
                mix.extend,
@@ -31,8 +31,8 @@
    </select>
    <select id="loadProductMixAll" resultType="org.jeecg.modules.dnc.entity.ProductMix">
        SELECT DISTINCT mix.id,
                        mix.tree_code    'code',
                        mix.tree_name    'name',
                        mix.tree_code,
                        mix.tree_name   ,
                        mix.parent_id,
                        mix.tree_type AS 'type',
                        mix.extend,
@@ -92,8 +92,8 @@
        )
        SELECT DISTINCT
            mix.id,
            mix.tree_code 'code',
            mix.tree_name 'name',
            mix.tree_code,
            mix.tree_name,
            mix.parent_id,
            mix.tree_type AS 'type',
            mix.extend,
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/DataPackageStrategy.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
package org.jeecg.modules.dnc.service;
import org.jeecg.modules.dnc.dto.TransferPackage;
// æ•°æ®å°è£…策略接口
public interface DataPackageStrategy {
    /**
     * å°è£…业务数据为传输包
     * @param id ä¸šåŠ¡å®žä½“ID(工序ID或工步ID)
     * @return å°è£…好的传输包
     */
    TransferPackage packageData(String id);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/IProductInfoService.java
@@ -221,7 +221,7 @@
    /**
     * èŽ·å–å…·ä½“å±‚çº§å®žä½“
     * @param id,type
     * @param id,treeType
     * @return
     */
    Result<?> getTreeById(String id, Integer type);
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/IProductMixService.java
@@ -1,8 +1,6 @@
package org.jeecg.modules.dnc.service;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.dnc.entity.ProductMix;
import java.util.List;
@@ -10,8 +8,20 @@
public interface IProductMixService extends IService<ProductMix> {
    //获取封装产品结构树
    public List<ProductMix> getTree();
    List<ProductMix> getTree();
    //模拟生成产品结构树
    /**
     * æŸ¥è¯¢å¯¹åº”id的所有父级(权限分配使用)
     * @param id
     * @return
     */
    List<ProductMix> getParentList(String id);
    /**
     * æŸ¥è¯¢å¯¹åº”id的所有子节点(权限分配使用)
     * @param id
     * @return
     */
    List<ProductMix> getChildrenList(String id);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ComponentInfoSeServiceImpl.java
@@ -189,8 +189,8 @@
        boolean b = super.updateById(componentInfo);
        //同步修改结构树
        ProductMix productMix = productMixService.getById(Long.parseLong(id));
        productMix.setName(componentInfo.getComponentName());
        productMix.setCode(componentInfo.getComponentCode());
        productMix.setTreeName(componentInfo.getComponentName());
        productMix.setTreeCode(componentInfo.getComponentCode());
        productMixService.updateById(productMix);
        if(!b)
            return false;
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DataImportService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,455 @@
package org.jeecg.modules.dnc.service.impl;
import cn.hutool.core.util.StrUtil;
import com.jeecg.weibo.exception.BusinessException;
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.mapper.*;
import org.jeecg.modules.dnc.service.*;
import org.jeecg.modules.system.service.IMdcProductionService;
import org.jeecg.modules.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class DataImportService {
    private static final Logger logger = LoggerFactory.getLogger(DataImportService.class);
    @Autowired
    private ProductInfoMapper productMapper;
    @Autowired
    private ComponentInfoMapper componentMapper;
    @Autowired
    private PartsInfoMapper partsMapper;
    @Autowired
    private ProcessSpecVersionMapper psvMapper;
    @Autowired
    private ProcessStreamMapper processMapper;
    @Autowired
    private WorkStepMapper workStepMapper;
    @Autowired
    private ProductMixMapper productMixMapper;
    @Autowired
    private PermissionStreamNewMapper permissionStreamNewMapper;
    @Autowired
    private DeviceManagementMapper deviceManagementMapper;
    @Autowired
    private DeviceTypeMapper deviceTypeMapper;
    @Autowired
    private DocInfoMapper docInfoMapper;
    @Autowired
    private DocFileMapper docFileMapper;
    @Autowired
    private DocRelativeMapper docRelativeMapper;
    @Autowired
    private CutterMapper cutterMapper;
    @Autowired
    private GuideCardBatchMapper guideCardBatchMapper;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IMdcProductionService mdcProductionService;
    @Autowired
    private IProductPermissionService productPermissionService;
    @Autowired
    private IProductDepartmentService productDepartmentService;
    @Autowired
    private IComponentPermissionService componentPermissionService;
    @Autowired
    private IComponentDepartmentService componentDepartmentService;
    @Autowired
    private IPartsPermissionService partsPermissionService;
    @Autowired
    private IPartsDepartmentService partsDepartmentService;
    @Autowired
    private IProcessSpecVersionPermissionService processSpecVersionPermissionService;
    @Autowired
    private IProcessSpecVersionDepartmentService processSpecVersionDepartmentService;
    @Autowired
    private IProcessStreamPermissionService processStreamPermissionService;
    @Autowired
    private IProcessionDepartmentService processionDepartmentService;
    @Autowired
    private IWorkStepPermissionService workStepPermissionService;
    @Autowired
    private IWorkStepDepartmentService workStepDepartmentService;
    @Transactional(rollbackFor = Exception.class)
    public void importTransferPackage(TransferPackage transferPackage) {
        try {
            logger.info("开始导入传输包数据, ç±»åž‹: {}", transferPackage.getDataType());
            // ä¿å­˜äº§å“
            if (transferPackage.getTraceChain() != null &&
                    transferPackage.getTraceChain().getProduct() != null) {
                saveProduct(transferPackage.getTraceChain().getProduct());
            }
            // ä¿å­˜éƒ¨ä»¶å±‚级
            if (transferPackage.getTraceChain() != null &&
                    transferPackage.getTraceChain().getComponentHierarchy() != null) {
                saveComponentHierarchy(transferPackage.getTraceChain().getComponentHierarchy());
            }
            // ä¿å­˜é›¶ä»¶
            if (transferPackage.getTraceChain() != null &&
                    transferPackage.getTraceChain().getParts() != null) {
                saveParts(transferPackage.getTraceChain().getParts());
            }
            // ä¿å­˜å·¥è‰ºè§„程
            if (transferPackage.getTraceChain() != null &&
                    transferPackage.getTraceChain().getProcessSpec() != null) {
                saveProcessSpec(transferPackage.getTraceChain().getProcessSpec());
            }
            // ä¿å­˜å·¥åº
            if (transferPackage.getTraceChain() != null&&
                    transferPackage.getTraceChain().getProcess() != null) {
                saveProcess(transferPackage.getTraceChain().getProcess());
            }
            // ä¿å­˜å·¥æ­¥
            if (transferPackage.getTraceChain() != null&&
                    transferPackage.getTraceChain().getWorkStep() != null) {
                saveWorkSteps(transferPackage.getTraceChain().getWorkStep());
            }
            // ä¿å­˜ç»“构树
            if (transferPackage.getTraceChain() != null&&
                    transferPackage.getTraceChain().getTreePath() != null) {
                saveTreePath(transferPackage.getTraceChain().getTreePath());
            }
            //保存权限
            if (transferPackage.getTraceChain() != null&&
                    transferPackage.getTraceChain().getPermissionStreamNewList() != null) {
                savePermissionStreamNewList(transferPackage.getTraceChain().getPermissionStreamNewList());
            }
            // ä¿å­˜è®¾å¤‡ç±»
            if (transferPackage.getTraceChain() != null&&
                    transferPackage.getTraceChain().getDeviceManagement() != null) {
                saveDeviceManagement(transferPackage.getTraceChain().getDeviceManagement());
            }
            // ä¿å­˜è®¾å¤‡ç±»å¯¹åº”信息
            if (transferPackage.getTraceChain() != null&&
                    transferPackage.getTraceChain().getDeviceType() != null) {
                saveDeviceType(transferPackage.getTraceChain().getDeviceType());
            }
            // ä¿å­˜æ–‡æ¡£
            if (transferPackage.getTraceChain() != null&&
                    transferPackage.getTraceChain().getDocInfo() != null) {
                saveDocInfo(transferPackage.getTraceChain().getDocInfo());
            }
            // ä¿å­˜æ–‡ä»¶
            if (transferPackage.getTraceChain() !=null&&
                    transferPackage.getTraceChain().getDocFile() != null) {
                saveDocFile(transferPackage.getTraceChain().getDocFile());
            }
            // ä¿å­˜æ–‡æ¡£æ–‡ä»¶å¯¹åº”关系
            if (transferPackage.getDocRelative() !=null){
                saveDocRelative(transferPackage.getDocRelative());
            }
            // ä¿å­˜åˆ€å…·ç³»ç»Ÿ
            if (transferPackage.getTraceChain() !=null&&
                    transferPackage.getTraceChain().getCutterList() != null) {
                saveCutterList(transferPackage.getTraceChain().getCutterList());
            }
            //保存数控程序加工确认表
            if (transferPackage.getTraceChain() !=null&&
                    transferPackage.getTraceChain().getGuideCardBatch() != null) {
                saveGuideCardBatch(transferPackage.getTraceChain().getGuideCardBatch());
            }
            logger.info("数据导入成功");
        } catch (DuplicateKeyException e) {
            logger.warn("主键冲突: {}", e.getMessage());
            throw new BusinessException("数据已存在,无法重复导入");
        } catch (DataIntegrityViolationException e) {
            logger.error("数据完整性违反: {}", e.getMessage());
            throw new BusinessException("数据不完整,请检查必填字段");
        } catch (Exception e) {
            logger.error("数据导入失败: {}", e.getMessage(), e);
            throw new BusinessException("数据导入失败: " + e.getMessage());
        }
    }
    private void saveProduct(ProductInfo product) {
        if (productMapper.selectById(product.getProductId()) == null) {
            productMapper.insert(product);
            logger.debug("产品已保存: {}", product.getProductId());
        } else {
            logger.debug("产品已存在: {}", product.getProductId());
        }
    }
    private void saveComponentHierarchy(ComponentHierarchy hierarchy) {
        for (ComponentInfo component : hierarchy.getComponents()) {
            if (componentMapper.selectById(component.getComponentId()) == null) {
                componentMapper.insert(component);
                logger.debug("部件已保存: {}", component.getComponentId());
            } else {
                logger.debug("部件已存在: {}", component.getComponentId());
            }
        }
    }
    private void saveParts(PartsInfo parts) {
        if (partsMapper.selectById(parts.getPartsId()) == null) {
            partsMapper.insert(parts);
            logger.debug("零件已保存: {}", parts.getPartsId());
        } else {
            logger.debug("零件已存在: {}", parts.getPartsId());
        }
    }
    private void saveProcessSpec(ProcessSpecVersion processSpec) {
        if (psvMapper.selectById(processSpec.getId()) == null) {
            psvMapper.insert(processSpec);
            logger.debug("工艺规程已保存: {}", processSpec.getId());
        } else {
            logger.debug("工艺规程已存在: {}", processSpec.getId());
        }
    }
    private void saveProcess(ProcessStream process) {
        if (processMapper.selectById(process.getProcessId()) == null) {
            processMapper.insert(process);
            logger.debug("工序已保存: {}", process.getProcessId());
        } else {
            logger.debug("工序已存在: {}", process.getProcessId());
        }
    }
    private void saveWorkSteps(WorkStep workStep) {
        if (workStepMapper.selectById(workStep.getId()) == null) {
            workStepMapper.insert(workStep);
            logger.debug("工步已保存: {}", workStep.getId());
        } else {
            logger.debug("工步已存在: {}", workStep.getId());
        }
    }
    private void saveTreePath(List<ProductMix> productMixList){
        for (ProductMix productMix : productMixList) {
            if (productMixMapper.selectById(productMix.getId()) == null) {
                productMixMapper.insert(productMix);
                logger.debug("产品组合已保存: {}", productMix.getId());
            } else {
                logger.debug("产品组合已存在: {}", productMix.getId());
            }
        }
    }
    private void savePermissionStreamNewList(List<PermissionStreamNew> permissionStreamNewList) {
        for (PermissionStreamNew permissionStreamNew : permissionStreamNewList) {
            if (permissionStreamNew.getUserId() != null) {
                String id=sysUserService.getUserByName(permissionStreamNew.getUserId()).getId();
                if (id!=null){
                    permissionStreamNew.setUserId(id);
                }
            }
            if (permissionStreamNew.getDepartId() != null) {
                String id=mdcProductionService.findByOrgCode(permissionStreamNew.getDepartId()).getId();
                if (id!=null){
                permissionStreamNew.setDepartId(id);
                }
            }
            permissionStreamNewMapper.insert(permissionStreamNew);
            logger.debug("权限已保存: {}", permissionStreamNew.getId());
        }
        //分批添加产品、部件、零件、工艺规程、工序、工步权限
        permissionStreamNewList.forEach(item -> {
            switch (item.getBusinessType()){
                case "1":
                    if (StrUtil.isNotEmpty(item.getUserId())){
                        ProductPermission productPermission = new ProductPermission();
                        productPermission.setProductId(item.getBusinessId());
                        productPermission.setUserId(item.getUserId());
                        productPermissionService.save(productPermission);
                    }else {
                        ProductDepartment productDepartment = new ProductDepartment();
                        productDepartment.setProductId(item.getBusinessId());
                        productDepartment.setDepartId(item.getDepartId());
                        productDepartmentService.save(productDepartment);
                    }
                    break;
                case "2":
                    if (StrUtil.isNotEmpty(item.getUserId())){
                        ComponentPermission componentPermission = new ComponentPermission();
                        componentPermission.setComponentId(item.getBusinessId());
                        componentPermission.setUserId(item.getUserId());
                        componentPermissionService.save(componentPermission);
                    }else {
                        ComponentDepartment componentDepartment = new ComponentDepartment();
                        componentDepartment.setComponentId(item.getBusinessId());
                        componentDepartment.setDepartId(item.getDepartId());
                        componentDepartmentService.save(componentDepartment);
                    }
                    break;
                case "3":
                    if (StrUtil.isNotEmpty(item.getUserId())){
                        PartsPermission partsPermission = new PartsPermission();
                        partsPermission.setPartsId(item.getBusinessId());
                        partsPermission.setUserId(item.getUserId());
                        partsPermissionService.save(partsPermission);
                    }else {
                        PartsDepartment partsDepartment = new PartsDepartment();
                        partsDepartment.setPartsId(item.getBusinessId());
                        partsDepartment.setDepartId(item.getDepartId());
                        partsDepartmentService.save(partsDepartment);
                    }
                    break;
                case "4":
                    if (StrUtil.isNotEmpty(item.getUserId())){
                        ProcessSpecVersionPermission processSpecVersionPermission = new ProcessSpecVersionPermission();
                        processSpecVersionPermission.setPsvId(item.getBusinessId());
                        processSpecVersionPermission.setUserId(item.getUserId());
                        processSpecVersionPermissionService.save(processSpecVersionPermission);
                    }else {
                        ProcessSpecVersionDepartment processSpecVersionDepartment = new ProcessSpecVersionDepartment();
                        processSpecVersionDepartment.setPsvId(item.getBusinessId());
                        processSpecVersionDepartment.setDepartId(item.getDepartId());
                        processSpecVersionDepartmentService.save(processSpecVersionDepartment);
                    }
                    break;
                case "5":
                    if (StrUtil.isNotEmpty(item.getUserId())){
                        ProcessionPermission processionPermission = new ProcessionPermission();
                        processionPermission.setProcessId(item.getBusinessId());
                        processionPermission.setUserId(item.getUserId());
                        processStreamPermissionService.save(processionPermission);
                    }else {
                        ProcessionDepartment processionDepartment = new ProcessionDepartment();
                        processionDepartment.setProcessId(item.getBusinessId());
                        processionDepartment.setDepartId(item.getDepartId());
                        processionDepartmentService.save(processionDepartment);
                    }
                    break;
                case  "6":
                    if (StrUtil.isNotEmpty(item.getUserId())){
                        WorkStepPermission workStepPermission = new WorkStepPermission();
                        workStepPermission.setStepId(item.getBusinessId());
                        workStepPermission.setUserId(item.getUserId());
                        workStepPermissionService.save(workStepPermission);
                    }else {
                        WorkStepDepartment workStepDepartment = new WorkStepDepartment();
                        workStepDepartment.setStepId(item.getBusinessId());
                        workStepDepartment.setDepartId(item.getDepartId());
                        workStepDepartmentService.save(workStepDepartment);
                    }
                    break;
                    default:
            }
        });
    }
    private void saveDeviceManagement(DeviceManagement deviceManagement) {
        if (deviceManagementMapper.selectById(deviceManagement.getId()) == null) {
            deviceManagementMapper.insert(deviceManagement);
            logger.debug("设备类信息已保存: {}", deviceManagement.getId());
        } else {
            logger.debug("设备类信息已存在: {}", deviceManagement.getId());
        }
    }
    private void saveDeviceType(DeviceType deviceType) {
        if (deviceTypeMapper.selectById(deviceType.getId()) == null) {
            deviceTypeMapper.insert(deviceType);
            logger.debug("设备类已保存: {}", deviceType.getId());
        } else {
            logger.debug("设备类已存在: {}", deviceType.getId());
        }
    }
    private void saveDocInfo(DocInfo docInfo) {
        if (docInfoMapper.selectById(docInfo.getDocId()) == null) {
            docInfoMapper.insert(docInfo);
            logger.debug("文档已保存: {}", docInfo.getDocId());
        } else {
            logger.debug("文档已存在: {}", docInfo.getDocId());
        }
    }
    private void saveDocFile(DocFile docFile) {
        if (docFileMapper.selectById(docFile.getFileId()) == null) {
            docFileMapper.insert(docFile);
            logger.debug("文档文件已保存: {}", docFile.getFileId());
        } else {
            logger.debug("文档文件已存在: {}", docFile.getFileId());
        }
    }
    private void saveDocRelative(DocRelative docRelative) {
        if (docRelativeMapper.selectById(docRelative.getId()) == null) {
            docRelativeMapper.insert(docRelative);
            logger.debug("文档对应关系已保存: {}", docRelative.getId());
        } else {
            logger.debug("文档对应关系已存在: {}", docRelative.getId());
        }
    }
    private void saveCutterList(List<Cutter> cutterList) {
        for (Cutter cutter : cutterList) {
            if (cutterMapper.selectById(cutter.getId()) == null) {
                cutterMapper.insert(cutter);
                logger.debug("刀具已保存: {}", cutter.getId());
            } else {
                cutterMapper.updateById(cutter);
            }
        }
    }
    private void saveGuideCardBatch(GuideCardBatch guideCardBatch) {
        if (guideCardBatchMapper.selectById(guideCardBatch.getId()) == null) {
            guideCardBatchMapper.insert(guideCardBatch);
            logger.debug("刀片批次已保存: {}", guideCardBatch.getId());
        } else {
            logger.debug("刀片批次已存在: {}", guideCardBatch.getId());
        }
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DataPackageService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
package org.jeecg.modules.dnc.service.impl;
import org.jeecg.modules.dnc.dto.TransferPackage;
import org.jeecg.modules.dnc.service.DataPackageStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
@Service
public class DataPackageService {
    private final Map<TransferPackage.DataType, DataPackageStrategy> strategies;
    @Autowired
    public DataPackageService(List<DataPackageStrategy> strategyList) {
        strategies = new EnumMap<>(TransferPackage.DataType.class);
        strategyList.forEach(strategy -> {
            if (strategy instanceof ProcessPackageStrategy) {
                strategies.put(TransferPackage.DataType.PROCESS, strategy);
            } else if (strategy instanceof WorkStepPackageStrategy) {
                strategies.put(TransferPackage.DataType.WORKSTEP, strategy);
            }
        });
    }
    public TransferPackage packageData(TransferPackage.DataType type, String id) {
        DataPackageStrategy strategy = strategies.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的数据类型: " + type);
        }
        return strategy.packageData(id);
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DevicePermissionServiceImpl.java
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DocInfoServiceImpl.java
@@ -342,10 +342,20 @@
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean addDocInfoAnalysisSmwNcService(String pathFile,File fileRec){
        //todo ç¨‹åºå›žä¼ 
        //确认解析目录
        return true;
    }
    /**
     * æ–‡æ¡£è§£æž
     * todo ä¿®æ”¹åˆ›å»ºæ–‡ä»¶å…³è”关系,改成固定docId,去除创建DocInfo
     * @param equipmentId
     * @param fileRec
     * @param fileNameSuffix
     * @param fileNameNew
     * @param filePath
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean addDocInfoRecService(String equipmentId,File fileRec,String fileNameSuffix,String fileNameNew,String filePath ) {
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/FileFerryService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,254 @@
package org.jeecg.modules.dnc.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.response.ActivitiCode;
import org.jeecg.modules.dnc.response.DocumentCode;
import org.jeecg.modules.dnc.service.IDocClassificationService;
import org.jeecg.modules.dnc.service.IDocInfoService;
import org.jeecg.modules.dnc.service.IDocRelativeService;
import org.jeecg.modules.dnc.utils.JsonUtils;
import org.jeecg.modules.dnc.utils.file.FileUtilS;
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 final DataPackageService dataPackageService;
    private final SecurityService securityService;
    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 IDocClassificationService classificationService;
    @Autowired
    private IDocRelativeService docRelativeService;
    @Autowired
    private IDocInfoService docInfoService;
    @Autowired
    public FileFerryService(DataPackageService dataPackageService, SecurityService securityService) {
        this.dataPackageService = dataPackageService;
        this.securityService = securityService;
    }
    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());
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/FullHierarchyTraceService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,236 @@
package org.jeecg.modules.dnc.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.jeecg.modules.dnc.constant.DocAttributionTypeEnum;
import org.jeecg.modules.dnc.dto.ComponentHierarchy;
import org.jeecg.modules.dnc.dto.ProcessTraceChain;
import org.jeecg.modules.dnc.entity.*;
import org.jeecg.modules.dnc.mapper.*;
import org.jeecg.modules.dnc.service.IPermissionStreamNewService;
import org.jeecg.modules.system.service.IMdcProductionService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class FullHierarchyTraceService {
    @Autowired
    private ProductMixMapper productMixMapper;
    @Autowired
    private ProductInfoMapper productMapper;
    @Autowired
    private ComponentInfoMapper componentMapper;
    @Autowired
    private PartsInfoMapper partsMapper;
    @Autowired
    private ProcessSpecVersionMapper psvMapper;
    @Autowired
    private ProcessStreamMapper processMapper;
    @Autowired
    private WorkStepMapper workStepMapper;
    @Autowired
    private DeviceTypeMapper deviceTypeMapper;
    @Autowired
    private DeviceManagementMapper deviceManagementMapper;
    @Autowired
    private DocInfoMapper docInfoMapper;
    @Autowired
    private DocFileMapper docFileMapper;
    @Autowired
    private CutterMapper cutterMapper;
    @Autowired
    private GuideCardBatchMapper guideCardBatchMapper;
    @Autowired
    private IPermissionStreamNewService permissionStreamNewService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IMdcProductionService mdcProductionService;
    public ProcessTraceChain traceFromProcess(DocRelative docRelative) {
        ProcessTraceChain chain = initChainWithDocInfo(docRelative);
        DeviceType deviceType = deviceTypeMapper.selectById(docRelative.getAttributionId());
        chain.setDeviceType(deviceType);
        if (isProcessType(deviceType)) {
            chain.setDeviceManagement(deviceManagementMapper.selectById(deviceType.getDeviceManagementId()));
            traceProcessChain(chain, deviceType.getAttributionId());
        }
        completeChainWithProductInfo(chain);
        List<ProductMix> productMixList=buildFullTreePath(chain);
        chain.setTreePath(productMixList);
        chain.setPermissionStreamNewList(buildFullTreePathPermission(productMixList));
        return chain;
    }
    public ProcessTraceChain traceFromWorkStep(DocRelative docRelative) {
        ProcessTraceChain chain = initChainWithDocInfo(docRelative);
        DeviceType deviceType = deviceTypeMapper.selectById(docRelative.getAttributionId());
        chain.setDeviceType(deviceType);
        if (isWorkSiteType(deviceType)) {
            chain.setDeviceManagement(deviceManagementMapper.selectById(deviceType.getDeviceManagementId()));
            traceWorkStepChain(chain, deviceType.getAttributionId());
        }
        completeChainWithProductInfo(chain);
        List<ProductMix> productMixList=buildFullTreePath(chain);
        chain.setTreePath(productMixList);
        chain.setPermissionStreamNewList(buildFullTreePathPermission(productMixList));
        return chain;
    }
    private ProcessTraceChain initChainWithDocInfo(DocRelative docRelative) {
        ProcessTraceChain chain = ProcessTraceChain.builder().docRelative(docRelative).build();
        Optional.ofNullable(docInfoMapper.selectById(docRelative.getDocId()))
                .ifPresent(doc -> {
                    chain.setDocInfo(doc);
                    chain.setDocFile(docFileMapper.selectById(doc.getPublishFileId()));
                    chain.setCutterList(getCuttersByDocId(doc.getDocId()));
                    getLatestGuideCardBatch(doc.getDocId()).ifPresent(chain::setGuideCardBatch);
                });
        return chain;
    }
    private List<Cutter> getCuttersByDocId(String docId) {
        return cutterMapper.selectList(new QueryWrapper<Cutter>().eq("doc_id", docId));
    }
    private Optional<GuideCardBatch> getLatestGuideCardBatch(String docId) {
        List<GuideCardBatch> batches = guideCardBatchMapper.selectList(
                new QueryWrapper<GuideCardBatch>()
                        .eq("doc_id", docId)
                        .orderByDesc("SUBSTRING(serial_number, LEN(serial_number)-3, 4)"));
        return CollectionUtils.isEmpty(batches) ? Optional.empty() : Optional.of(batches.get(0));
    }
    private boolean isProcessType(DeviceType deviceType) {
        return deviceType != null &&
                Objects.equals(deviceType.getAttributionType(), DocAttributionTypeEnum.PROCESS.getCode());
    }
    private boolean isWorkSiteType(DeviceType deviceType) {
        return deviceType != null &&
                Objects.equals(deviceType.getAttributionType(), DocAttributionTypeEnum.WORKSITE.getCode());
    }
    private void traceProcessChain(ProcessTraceChain chain, String processId) {
        ProcessStream process = processMapper.selectById(processId);
        if (process == null) return;
        chain.setProcess(process);
        if (process.getPsvId() != null) {
            ProcessSpecVersion psv = psvMapper.selectById(process.getPsvId());
            chain.setProcessSpec(psv);
            if (psv != null && psv.getPartsId() != null) {
                PartsInfo parts = partsMapper.selectById(psv.getPartsId());
                chain.setParts(parts);
                if (parts != null && parts.getComponentId() != null) {
                    chain.setComponentHierarchy(traceComponentHierarchy(parts.getComponentId()));
                }
            }
        } else if (process.getComponentId() != null) {
            chain.setComponentHierarchy(traceComponentHierarchy(process.getComponentId()));
        }
    }
    private void traceWorkStepChain(ProcessTraceChain chain, String workStepId) {
        WorkStep workStep = workStepMapper.selectById(workStepId);
        if (workStep == null) return;
        chain.setWorkStep(workStep);
        traceProcessChain(chain, workStep.getProcessId());
    }
    private ComponentHierarchy traceComponentHierarchy(String componentId) {
        ComponentHierarchy hierarchy = new ComponentHierarchy();
        ComponentInfo current = componentMapper.selectById(componentId);
        while (current != null) {
            hierarchy.addComponentToTop(current);
            if (current.getParentId() == null || current.getParentId().isEmpty()) {
                Optional.ofNullable(current.getProductId())
                        .map(productMapper::selectById)
                        .ifPresent(hierarchy::setRootProduct);
                break;
            }
            current = componentMapper.selectById(current.getParentId());
        }
        return hierarchy;
    }
    private void completeChainWithProductInfo(ProcessTraceChain chain) {
        Optional.ofNullable(chain.getComponentHierarchy())
                .map(ComponentHierarchy::getComponents)
                .filter(components -> !components.isEmpty())
                .map(components -> components.get(0))
                .map(ComponentInfo::getProductId)
                .map(productMapper::selectById)
                .ifPresent(chain::setProduct);
    }
    private List<ProductMix> buildFullTreePath(ProcessTraceChain chain) {
        List<ProductMix> path = new ArrayList<>();
        Optional.ofNullable(chain.getProduct())
                .map(ProductInfo::getProductId)
                .map(productMixMapper::findByProductId)
                .ifPresent(path::add);
        Optional.ofNullable(chain.getComponentHierarchy())
                .map(ComponentHierarchy::getComponentsFromTop)
                .ifPresent(components -> components.stream()
                        .map(ComponentInfo::getComponentId)
                        .map(productMixMapper::findByComponentId)
                        .filter(Objects::nonNull)
                        .forEach(path::add));
        Optional.ofNullable(chain.getParts())
                .map(PartsInfo::getPartsId)
                .map(productMixMapper::findByPartsId)
                .ifPresent(path::add);
        Optional.ofNullable(chain.getProcessSpec())
                .map(ProcessSpecVersion::getId)
                .map(productMixMapper::findByOperationId)
                .ifPresent(path::add);
        Optional.ofNullable(chain.getProcess())
                .map(ProcessStream::getProcessId)
                .map(productMixMapper::findByProcessId)
                .ifPresent(path::add);
        Optional.ofNullable(chain.getWorkStep())
                .map(WorkStep::getId)
                .map(productMixMapper::findByWorksiteId)
                .ifPresent(path::add);
        return path;
    }
    private List<PermissionStreamNew> buildFullTreePathPermission(List<ProductMix> productMixList) {
        List<Long> ids=productMixList.stream().map(ProductMix::getId).collect(Collectors.toList());
        List<PermissionStreamNew> path = permissionStreamNewService
                .list(new QueryWrapper<PermissionStreamNew>().in("business_id",ids)
                        .eq("delete_flag",0));
        path.forEach(item->{
            if (item.getDepartId()!=null){
                item.setDepartId(mdcProductionService.getById(item.getDepartId()).getOrgCode());
            }
            if (item.getUserId()!=null){
                item.setUserId(sysUserService.getById(item.getUserId()).getUsername());
            }
        });
        return path;
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/PartsInfoServiceImpl.java
@@ -151,8 +151,8 @@
        boolean b = super.updateById(partsInfo);
        //同步修改结构树
        ProductMix productMix = productMixService.getById(Long.parseLong(id));
        productMix.setName(partsInfo.getPartsName());
        productMix.setCode(partsInfo.getPartsCode());
        productMix.setTreeName(partsInfo.getPartsName());
        productMix.setTreeCode(partsInfo.getPartsCode());
        productMixService.updateById(productMix);
        if(!b)
            return false;
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessPackageStrategy.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package org.jeecg.modules.dnc.service.impl;
import org.jeecg.modules.dnc.constant.DocAttributionTypeEnum;
import org.jeecg.modules.dnc.dto.TransferPackage;
import org.jeecg.modules.dnc.entity.DeviceType;
import org.jeecg.modules.dnc.entity.DocRelative;
import org.jeecg.modules.dnc.entity.ProcessStream;
import org.jeecg.modules.dnc.mapper.DeviceTypeMapper;
import org.jeecg.modules.dnc.mapper.DocRelativeMapper;
import org.jeecg.modules.dnc.mapper.ProcessStreamMapper;
import org.jeecg.modules.dnc.service.DataPackageStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProcessPackageStrategy implements DataPackageStrategy {
    @Autowired
    private ProcessStreamMapper processMapper;
    @Autowired
    private DeviceTypeMapper deviceTypeMapper;
    @Autowired
    private FullHierarchyTraceService traceService;
    @Autowired
    private DocRelativeMapper docRelativeMapper;
    @Override
    public TransferPackage packageData(String relativeId) {
        DocRelative docRelative=docRelativeMapper.selectById(relativeId);
        DeviceType deviceType=deviceTypeMapper.selectById(docRelative.getAttributionId());
        if (deviceType!=null&&deviceType.getAttributionType().equals(DocAttributionTypeEnum.PROCESS.getCode())) {
            ProcessStream process = processMapper.selectById(deviceType.getAttributionId());
            if (process == null) {
                throw new IllegalArgumentException("设备类对应的工序不存在: " + deviceType.getDeviceManagementId());
            }
        }
        return TransferPackage.builder()
                .dataType(TransferPackage.DataType.PROCESS)
                .docRelative(docRelative)
                .traceChain(traceService.traceFromProcess(docRelative))
                .build();
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessSpecVersionServiceImpl.java
@@ -205,8 +205,8 @@
        boolean b = super.updateById(processSpecVersion);
        //同步修改结构树
        ProductMix productMix = productMixService.getById(Long.parseLong(id));
        productMix.setName(processSpecVersion.getProcessSpecVersionName());
        productMix.setCode(processSpecVersion.getProcessSpecVersionCode());
        productMix.setTreeName(processSpecVersion.getProcessSpecVersionName());
        productMix.setTreeCode(processSpecVersion.getProcessSpecVersionCode());
        productMixService.updateById(productMix);
        if(!b)
            return false;
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessStreamServiceImpl.java
@@ -61,7 +61,6 @@
    private IDocInfoService docInfoService;
    @Autowired
    private IDeviceTypeService deviceTypeService;
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean addProcessStream(ProcessStream stream) {
@@ -177,8 +176,8 @@
        boolean b = super.updateById(stream);
        //同步修改结构树
        ProductMix productMix = productMixService.getById(Long.parseLong(id));
        productMix.setName(stream.getProcessName());
        productMix.setCode(stream.getProcessCode());
        productMix.setTreeName(stream.getProcessName());
        productMix.setTreeCode(stream.getProcessCode());
        productMixService.updateById(productMix);
        if(!b)
            ExceptionCast.cast(CommonCode.FAIL);
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessionDepartmentServiceImpl.java
ÎļþÃû´Ó lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProcessionDepartmentService.java ÐÞ¸Ä
@@ -10,10 +10,11 @@
import org.jeecg.modules.system.entity.MdcProduction;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
@Service
public class ProcessionDepartmentService extends ServiceImpl<ProcessionDepartmentMapper, ProcessionDepartment> implements IProcessionDepartmentService {
public class ProcessionDepartmentServiceImpl extends ServiceImpl<ProcessionDepartmentMapper, ProcessionDepartment> implements IProcessionDepartmentService {
    @Override
    public boolean deleteByProcessId(String processId) {
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProductInfoServiceImpl.java
@@ -164,8 +164,8 @@
        boolean b = super.updateById(productInfo);
        //同步修改结构树
        ProductMix productMix = productMixService.getById(Long.parseLong(id));
        productMix.setName(productInfo.getProductName());
        productMix.setCode(productInfo.getProductNo());
        productMix.setTreeName(productInfo.getProductName());
        productMix.setTreeCode(productInfo.getProductNo());
        productMixService.updateById(productMix);
        if (!b)
            return false;
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProductMixServiceImpl.java
@@ -48,4 +48,67 @@
        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;
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProductPermissionServiceImpl.java
@@ -143,7 +143,7 @@
                break;
            default:
                // å¤„理未知类型
                throw new IllegalArgumentException("Unknown permission type: " + type);
                throw new IllegalArgumentException("Unknown permission treeType: " + type);
        }
    }
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/SecurityService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
package org.jeecg.modules.dnc.service.impl;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
@Service
public class SecurityService {
    private static final String ALGORITHM = "SM4/ECB/PKCS5Padding";
    private final String secretKey;
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    @Autowired
    public SecurityService(@Value("${security.encryption-key}") String secretKey) {
        this.secretKey = secretKey;
    }
    public byte[] encrypt(byte[] data) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "SM4");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);
            return cipher.doFinal(data);
        } catch (Exception e) {
            throw new RuntimeException("加密失败", e);
        }
    }
    public byte[] decrypt(byte[] encryptedData) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "SM4");
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            return cipher.doFinal(encryptedData);
        } catch (Exception e) {
            throw new RuntimeException("解密失败", e);
        }
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/WorkStepPackageStrategy.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
package org.jeecg.modules.dnc.service.impl;
import org.jeecg.modules.dnc.constant.DocAttributionTypeEnum;
import org.jeecg.modules.dnc.dto.TransferPackage;
import org.jeecg.modules.dnc.entity.DeviceType;
import org.jeecg.modules.dnc.entity.DocRelative;
import org.jeecg.modules.dnc.entity.WorkStep;
import org.jeecg.modules.dnc.mapper.DeviceTypeMapper;
import org.jeecg.modules.dnc.mapper.DocRelativeMapper;
import org.jeecg.modules.dnc.mapper.WorkStepMapper;
import org.jeecg.modules.dnc.service.DataPackageStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class WorkStepPackageStrategy implements DataPackageStrategy {
    @Autowired
    private WorkStepMapper workStepMapper;
    @Autowired
    private FullHierarchyTraceService traceService;
    @Autowired
    private DeviceTypeMapper deviceTypeMapper;
    @Autowired
    private DocRelativeMapper docRelativeMapper;
    @Override
    public TransferPackage packageData(String relativeId) {
        DocRelative docRelative=docRelativeMapper.selectById(relativeId);
        DeviceType deviceType=deviceTypeMapper.selectById(docRelative.getAttributionId());
        if (deviceType!=null&&deviceType.getAttributionType().equals(DocAttributionTypeEnum.WORKSITE.getCode())) {
            WorkStep workStep = workStepMapper.selectById(deviceType.getAttributionId());
            if (workStep == null) {
                throw new IllegalArgumentException("设备类对应的工步不存在: " + deviceType.getDeviceManagementId());
            }
        }
        return TransferPackage.builder()
                .dataType(TransferPackage.DataType.WORKSTEP)
                .docRelative(docRelative)
                .traceChain(traceService.traceFromWorkStep(docRelative))
                .build();
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/WorkStepServiceImpl.java
@@ -175,8 +175,8 @@
            ExceptionCast.cast(ProcessInfoCode.WORKSTEP_NOT_EXIST);
        //同步修改结构树
        ProductMix productMix = productMixService.getById(Long.parseLong(id));
        productMix.setName(workStep.getStepName());
        productMix.setCode(workStep.getStepCode());
        productMix.setTreeName(workStep.getStepName());
        productMix.setTreeCode(workStep.getStepCode());
        productMixService.updateById(productMix);
        return super.updateById(workStep);
    }
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/utils/CompressionUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
package org.jeecg.modules.dnc.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class CompressionUtils {
    public static byte[] gzipCompress(byte[] data) {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
             GZIPOutputStream gzip = new GZIPOutputStream(bos)) {
            gzip.write(data);
            gzip.finish();
            return bos.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException("GZIP压缩失败", e);
        }
    }
    public static byte[] gzipDecompress(byte[] compressed) {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(compressed);
             GZIPInputStream gzip = new GZIPInputStream(bis);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = gzip.read(buffer)) > 0) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException("GZIP解压失败", e);
        }
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/utils/JsonUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
package org.jeecg.modules.dnc.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.text.SimpleDateFormat;
public class JsonUtils {
    private static final ObjectMapper objectMapper = createObjectMapper();
    private static ObjectMapper createObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        // é…ç½®æ—¥æœŸæ ¼å¼
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // é…ç½®åºåˆ—化选项
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // é…ç½®ååºåˆ—化选项
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
        mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
        return mapper;
    }
    public static String toJson(Object object) {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (Exception e) {
            throw new RuntimeException("JSON序列化失败: " + e.getMessage(), e);
        }
    }
    public static <T> T fromJson(String json, Class<T> valueType) {
        try {
            return objectMapper.readValue(json, valueType);
        } catch (Exception e) {
            throw new RuntimeException("JSON反序列化失败: " + e.getMessage() + "\nJSON内容: " + json, e);
        }
    }
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/utils/TreeBuilder.java
@@ -108,8 +108,8 @@
            ProductMix newNode = new ProductMix(
                    node.getId(),
                    node.getParentId(),
                    node.getName(),
                    node.getCode(),
                    node.getTreeName(),
                    node.getTreeCode(),
                    node.getType(),
                    node.getCreateTime()
            );
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/service/IAssignFileStreamService.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.dnc.entity.DocFile;
import org.jeecg.modules.dnc.response.QueryPageResponseResult;
import org.jeecg.modules.dncFlow.entity.AssignFileStream;
import org.jeecg.modules.dncFlow.ext.AssignFileStreamExt;
@@ -9,6 +10,7 @@
import org.jeecg.modules.dncFlow.request.AssignFileRequest;
import org.jeecg.modules.dncFlow.request.AssignFileStreamQueryRequest;
import org.jeecg.modules.dncFlow.vo.AssignFlowTaskVo;
import org.jeecg.modules.mdc.entity.MdcEquipment;
public interface IAssignFileStreamService extends IService<AssignFileStream> {
    /**
@@ -41,9 +43,7 @@
    /**
     * å®¡æ‰¹æœåŠ¡
     * @param taskId
     * @param streamId
     * @param stream
     * @param assignFlowTaskVo
     * @return
     */
    boolean approveAssignFile(AssignFlowTaskVo assignFlowTaskVo);
@@ -84,4 +84,6 @@
     * @return
     */
    Boolean getFlowableEnable();
    void handleFileTransfer(MdcEquipment mdcEquipment, DocFile docFile);
}
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/service/impl/AssignFileStreamServiceImpl.java
@@ -16,11 +16,14 @@
import org.flowable.task.api.Task;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.dnc.constant.DncPassLogPassType;
import org.jeecg.modules.dnc.constant.DocAttributionTypeEnum;
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.ext.NcTxtFilePathInfo;
import org.jeecg.modules.dnc.response.*;
import org.jeecg.modules.dnc.service.*;
import org.jeecg.modules.dnc.service.impl.FileFerryService;
import org.jeecg.modules.dnc.utils.ValidateUtil;
import org.jeecg.modules.dnc.utils.date.DateUtil;
import org.jeecg.modules.dnc.utils.file.FileUtilS;
@@ -42,7 +45,6 @@
import org.jeecg.modules.flowable.service.IFlowTaskService;
import org.jeecg.modules.mdc.entity.MdcEquipment;
import org.jeecg.modules.mdc.service.IMdcEquipmentService;
import org.jeecg.modules.message.enums.DeployEnum;
import org.jeecg.modules.system.service.IMdcProductionService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -51,23 +53,17 @@
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Service("IAssignFileStreamService")
public class AssignFileStreamServiceImpl extends ServiceImpl<AssignFileStreamMapper, AssignFileStream> implements IAssignFileStreamService , FlowCallBackServiceI {
    private static final String PROCESS_KEY = "assign_nc_to_device";
    private static final String APPLY_VARIABLE = "apply_user";
    private static final String APPROVE_VARIABLE = "approve_users";
    private static final String SEND_CODE = "SEND";
    @Value("${flowable.enable}")
    private Boolean flowableEnable;
    @Value("${fileHomePath}")
    private String fileHomePath;
    @Autowired
    private IDocInfoService docInfoService;
    @Autowired
@@ -98,11 +94,10 @@
    private PermissionService permissionService;
    @Autowired
    private IDncPassLogService dncPassLogService;
    @Value("${deploy.deployType}")
    private String deployType;    //工控网/涉密网部署 0为工控网 1为涉密网
    @Value("${deploy.secretFolder}")
    private String secretFolder;    //涉密网传输nc文件夹
    @Autowired
    private FileFerryService ferryService;
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Result applyAssignFile(AssignFileStream stream) {
@@ -253,11 +248,19 @@
            }
        }
        handleFileTransfer(mdcEquipment, docFile);
        //注意----区分工控网与涉密网!!!  æ¶‰å¯†ç½‘进行NC文件的拷贝,工控网负责进行解析NC文件
        if (deployType.equals(DeployEnum.SMW.getCode())) {
            handleFileProcessing(docFile, mdcEquipment, secretFolder);
        List<DocRelative> docRelativeList=docRelativeService.
                list(new QueryWrapper<DocRelative>()
                        .eq("attribution_type",stream.getAttributionType())
                        .eq("attribution_id",stream.getAttributionId())
                        .eq("doc_id",stream.getDocId()));
        if (docRelativeList.isEmpty()){
            ExceptionCast.cast(ActivitiCode.ACT_APPROVE_ERROR);
        }
        handleFileTransfer(mdcEquipment, docFile);
        //NC文件的拷贝
        handleFileProcessing(docFile, mdcEquipment, secretFolder);
        //对应产品结构树拷贝
        handleProductTree(docInfo,docRelativeList.get(0),mdcEquipment.getEquipmentId());
        synchronizedFlagService.updateFlag(2);
        return Result.OK("操作成功");
    }
@@ -383,10 +386,20 @@
                    }
                }
            }
            //注意----区分工控网与涉密网!!!  æ¶‰å¯†ç½‘进行NC文件的拷贝,工控网负责进行解析NC文件
            if (deployType.equals(DeployEnum.SMW.getCode())) {
                handleFileProcessing(docFile, mdcEquipment, secretFolder);
            List<DocRelative> docRelativeList=docRelativeService.
                    list(new QueryWrapper<DocRelative>()
                            .eq("attribution_type",en.getAttributionType())
                            .eq("attribution_id",en.getAttributionId())
                            .eq("doc_id",en.getDocId()));
            if (docRelativeList.isEmpty()){
                ExceptionCast.cast(ActivitiCode.ACT_APPROVE_ERROR);
            }
            //涉密网进行NC文件的拷贝
            handleFileTransfer(mdcEquipment, docFile);
            //NC文件的拷贝
            handleFileProcessing(docFile, mdcEquipment, secretFolder);
            //对应产品结构树拷贝
            handleProductTree(docInfo,docRelativeList.get(0),mdcEquipment.getEquipmentId());
            return synchronizedFlagService.updateFlag(1);
        }else if(up.getStatus() == 3) {
            //拒绝操作 ä»€ä¹ˆä¹Ÿä¸åš
@@ -579,7 +592,8 @@
    }
    //插入文件传输任务表
    private void handleFileTransfer(MdcEquipment mdcEquipment, DocFile docFile) {
    @Override
    public void handleFileTransfer(MdcEquipment mdcEquipment, DocFile docFile) {
        List<String> strings = iMdcProductionService.findListParentTreeAll(mdcEquipment.getId());
        if (strings != null && !strings.isEmpty()) {
            String path = StringUtils.join(strings.toArray(), "/");
@@ -600,7 +614,6 @@
    //封装处理文件
    private void handleFileProcessing(DocFile docFile, MdcEquipment mdcEquipment, String secretFolder) {
        if (!docFile.getFileSuffix().equals("zip") && !docFile.getFileSuffix().equals("rar")) {
            String size = FileUtilS.fileSizeNC(docFile.getFilePath(), docFile.getFileEncodeName());
            List<String> strings = iMdcProductionService.findListParentTreeAll(mdcEquipment.getId());
            if (strings != null && !strings.isEmpty()) {
                DncPassLog passInfoTxt = new DncPassLog();
@@ -611,23 +624,14 @@
                /*查询最后一条记录*/
                //休眠 500毫秒
                DncPassLog dncPassLog  = dncPassLogService.findDayTime(DateUtil.format(dateFirst,DateUtil.STR_YEARMONTHDAY));
                int fileTxt = 0, fileNc =0;
                int fileNc =0;
                if (dncPassLog !=null) {
                    fileTxt = dncPassLog.getSequenceNumber() + 1;
                    fileNc = dncPassLog.getSequenceNumber() + 1;
                } else {
                    fileTxt =  1;
                    fileNc =  1;
                }
                fileNc = fileTxt + 1;
                //处理文件名称  æ–‡ä»¶è·¯å¾„
                String sequence = String.format("%06d",fileTxt);
                String sequenceNc = String.format("%06d",fileNc);
                passInfoTxt.setSequenceNumber(fileTxt);
                passInfoTxt.setSequenceOrder(sequence);
                passInfoTxt.setCreateTime(dateFirst);
                System.out.println(DateUtil.format(dateFirst,DateUtil.STR_DATE_TIME));
                passInfoTxt.setPassType("02");
                dncPassLogService.save(passInfoTxt);
                DncPassLog passInfoNc = new DncPassLog();
                passInfoNc.setSequenceNumber(fileNc);
                passInfoNc.setSequenceOrder(sequenceNc);
@@ -642,41 +646,50 @@
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                dncPassLogService.save(passInfoNc);
                NcTxtFilePathInfo ncTxt = new NcTxtFilePathInfo();
                ncTxt.setEquipmentId(mdcEquipment.getEquipmentId());
                ncTxt.setFileNcName("10A"+DateUtil.format(dateFirst,DateUtil.STR_YEARMONTHDAY)+sequenceNc);
                ncTxt.setFileTxtName("10A"+DateUtil.format(dateFirst,DateUtil.STR_YEARMONTHDAY)+sequence);
                ncTxt.setFilePath(path + "/" + mdcEquipment.getEquipmentId() + "/");
                ncTxt.setOrigFileName(docFile.getFileName());
                ncTxt.setOrigFileSuffix(docFile.getFileSuffix());
                ncTxt.setFileAddOrDelete(1);
                String loFilePath = secretFolder +"/"+ ncTxt.getFileTxtName() + ".nc";
                try {
                    String allList = ncTxt.getFileTxtName() + "\n"
                            + ncTxt.getFileNcName() + "\n"
                            + ncTxt.getOrigFileName() + "\n"
                            + ncTxt.getOrigFileSuffix() + "\n"
                            + ncTxt.getFilePath() + "\n"
                            + ncTxt.getEquipmentId() + "\n"
                            + ncTxt.getFileAddOrDelete().toString() + "\n"
                            + size + "\n";
                    FileUtilS.fileWriterSql(loFilePath, allList);
                    boolean copyFileNc = FileUtilS.copyFileUpName(path + "/" + mdcEquipment.getEquipmentId() + "/send/" +
                FileUtilS.copyFileUpName(path + "/" + mdcEquipment.getEquipmentId() + "/send/" +
                                    docFile.getFileName(),
                            secretFolder +"/"+ncTxt.getFileNcName(),
                        secretFolder +"/"+"10A"+DateUtil.format(dateFirst,DateUtil.STR_YEARMONTHDAY)+sequenceNc+"_"+mdcEquipment.getEquipmentId(),
                            docFile.getFileSuffix(), "NC");
                    if (!copyFileNc) {
                        FileUtilS.deleteNcFile(loFilePath);
                    }
                } catch (IOException e) {
                    throw new RuntimeException("文件处理失败", e);
                }
            }
        }
    }
    /**
     * å¤„理对应产品结构树、nc文件、刀具列表、程序加工确认表封装
     * @param docInfo
     */
    private void handleProductTree(DocInfo docInfo,DocRelative docRelative,String equipmentId) {
        /*查询最后一条记录*/
        //休眠 500毫秒
        DncPassLog passInfoTxt = new DncPassLog();
        Date dateFirst = DateUtil.getNow();
        passInfoTxt.setDayTime(DateUtil.format(dateFirst,DateUtil.STR_YEARMONTHDAY));
        DncPassLog dncPassLog  = dncPassLogService.findDayTime(DateUtil.format(dateFirst,DateUtil.STR_YEARMONTHDAY));
        int fileTxt = 0, fileNc =0;
        if (dncPassLog !=null) {
            fileTxt = dncPassLog.getSequenceNumber() + 1;
        } else {
            fileTxt =  1;
        }
        String sequence = String.format("%06d",fileTxt);
        passInfoTxt.setSequenceNumber(fileTxt);
        passInfoTxt.setCreateTime(dateFirst);
        passInfoTxt.setSequenceOrder(sequence);
        System.out.println(DateUtil.format(dateFirst,DateUtil.STR_DATE_TIME));
        passInfoTxt.setPassType(DncPassLogPassType.PRODUCTSTRUCTURE.getCode());
        dncPassLogService.save(passInfoTxt);
        String fileName="10A"+DateUtil.format(dateFirst,DateUtil.STR_YEARMONTHDAY);
        if (Objects.equals(docInfo.getAttributionType(), DocAttributionTypeEnum.PROCESS.getCode())){
            //工序对应设备类
            String filePath = ferryService.exportData(TransferPackage.DataType.PROCESS, docRelative.getId(),fileName+sequence+"_"+equipmentId+".ferry");
            System.out.println("工序数据已导出: " + filePath);
        }else {
            //工步对应设备类
            String filePath = ferryService.exportData(TransferPackage.DataType.WORKSTEP, docRelative.getId(),fileName+sequence+"_"+equipmentId+".ferry");
            System.out.println("工步数据已导出: " + filePath);
        }
    }
    @Override
    public void afterFlowHandle(FlowMyBusiness business) {
        business.getTaskNameId();//接下来审批的节点
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/service/IMdcProductionService.java
@@ -185,4 +185,11 @@
    String findProName(String equipmentId);
    /**
     * æ ¹æ®äº§çº¿orgCode查询产线
     * @param orgCode
     * @return
     */
    MdcProduction findByOrgCode(String orgCode);
}
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/service/impl/MdcProductionServiceImpl.java
@@ -637,4 +637,9 @@
    public String findProName(String equipmentId) {
        return this.baseMapper.findProName(equipmentId);
    }
    @Override
    public MdcProduction findByOrgCode(String orgCode){
        return this.baseMapper.selectOne(new LambdaQueryWrapper<MdcProduction>().eq(MdcProduction::getOrgCode, orgCode));
    }
}