소스 검색

整炉补录钢坯

qiangxuan 2 주 전
부모
커밋
804747e0b6

+ 15 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/actualControl/billetActual/billetActual/controller/BilletBasicInfoController.java

@@ -14,6 +14,7 @@ import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfoAdd;
 import org.jeecg.modules.actualControl.billetActual.billetActual.service.IBilletBasicInfoService;
 import org.jeecg.modules.billet.billetHotsendConfig.entity.BilletHotsendTypeConfig;
 import org.jeecg.modules.billet.billetHotsendConfig.service.IBilletHotsendTypeConfigService;
@@ -99,6 +100,20 @@ public class BilletBasicInfoController extends JeecgController<BilletBasicInfo,
 		return Result.OK("添加成功!");
 	}
 
+	/**
+	 *   添加
+	 *
+	 * @param billetBasicInfoAdd
+	 * @return
+	 */
+	@AutoLog(value = "钢坯浇筑页面-补录钢坯")
+	@ApiOperation(value="钢坯浇筑页面-补录钢坯", notes="钢坯浇筑页面-补录钢坯")
+	@PostMapping(value = "/addBilletBasic")
+	public Result<?> addBilletBasic(@RequestBody BilletBasicInfoAdd billetBasicInfoAdd){
+		String result = billetBasicInfoService.addBilletBasicHandle(billetBasicInfoAdd);
+		return Result.OK(result);
+	}
+
 	/**
 	 *  编辑
 	 *

+ 55 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/actualControl/billetActual/billetActual/entity/BilletBasicInfoAdd.java

@@ -0,0 +1,55 @@
+package org.jeecg.modules.actualControl.billetActual.billetActual.entity;
+
+import lombok.Data;
+import org.jeecg.modules.billet.rollClubOne.entity.RollClubOne;
+
+import java.util.List;
+
+@Data
+public class BilletBasicInfoAdd {
+    private String ccmNo;
+    private String heatNo;
+    private String shiftGroup;
+    private String shift;
+
+    private Integer oneStrandNo;
+    private Integer oneStrandNoSum;
+    private Integer oneLength;
+
+    private Integer twoStrandNo;
+    private Integer twoStrandNoSum;
+    private Integer twoLength;
+
+    private Integer threeStrandNo;
+    private Integer threeStrandNoSum;
+    private Integer threeLength;
+
+    private Integer fourStrandNo;
+    private Integer fourStrandNoSum;
+    private Integer fourLength;
+
+    private Integer fiveStrandNo;
+    private Integer fiveStrandNoSum;
+    private Integer fiveLength;
+
+    private Integer sixStrandNo;
+    private Integer sixStrandNoSum;
+    private Integer sixLength;
+
+    private Integer sevenStrandNo;
+    private Integer sevenStrandNoSum;
+    private Integer sevenLength;
+
+    private Integer eightStrandNo;
+    private Integer eightStrandNoSum;
+    private Integer eightLength;
+
+    // 1 整炉 生成棒一流号、数量
+    private List<RollClubOneInfo> rollClubOneList;
+
+    // 1 整炉 2 列表补坯
+    private Integer addType;
+
+    // 整炉 添加总支数
+    private Integer addCount;
+}

+ 10 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/actualControl/billetActual/billetActual/entity/RollClubOneInfo.java

@@ -0,0 +1,10 @@
+package org.jeecg.modules.actualControl.billetActual.billetActual.entity;
+
+import lombok.Data;
+
+@Data
+public class RollClubOneInfo {
+    private Integer strandNo;//流号
+    private Integer length;//定尺
+    private Integer addSum;//新增数量
+}

+ 3 - 1
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/actualControl/billetActual/billetActual/mapper/BilletBasicInfoMapper.java

@@ -3,6 +3,8 @@ package org.jeecg.modules.actualControl.billetActual.billetActual.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
 
+import java.util.List;
+
 /**
  * @Description: 钢坯基础信息
  * @Author: jeecg-boot
@@ -10,5 +12,5 @@ import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBa
  * @Version: V1.0
  */
 public interface BilletBasicInfoMapper extends BaseMapper<BilletBasicInfo> {
-
+    int insertBatch(List<BilletBasicInfo> list);
 }

+ 75 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/actualControl/billetActual/billetActual/mapper/xml/BilletBasicInfoMapper.xml

@@ -1,5 +1,80 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.jeecg.modules.actualControl.billetActual.billetActual.mapper.BilletBasicInfoMapper">
+    <!-- 批量插入方法 -->
+    <insert id="insertBatch" parameterType="java.util.List">
+        INSERT INTO billet_basic_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            id,
+            create_by,
+            create_time,
+            update_by,
+            update_time,
+            sys_org_code,
+            heat_no,
+            ccm_no,
+            casting_speed,
+            ladle_no,
+            strand_no,
+            heatno_index,
+            grade,
+            length,
+            actual_length,
+            width,
+            thickness,
+            spec,
+            weight,
+            billet_no,
+            strandno_index,
+            cut_start_time,
+            cut_stop_time,
+            ratings_result,
+            belong_table,
+            stack_or_car_id,
+            bhtc_id,
+            shift_group,
+            shift,
+            billet_weight,
+            assembly_number,
+            brand_num
+        </trim>
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (
+            #{item.id,jdbcType=VARCHAR},
+            #{item.createBy,jdbcType=VARCHAR},
+            #{item.createTime,jdbcType=TIMESTAMP},
+            #{item.updateBy,jdbcType=VARCHAR},
+            #{item.updateTime,jdbcType=TIMESTAMP},
+            #{item.sysOrgCode,jdbcType=VARCHAR},
+            #{item.heatNo,jdbcType=VARCHAR},
+            #{item.ccmNo,jdbcType=INTEGER},
+            #{item.castingSpeed,jdbcType=DOUBLE},
+            #{item.ladleNo,jdbcType=VARCHAR},
+            #{item.strandNo,jdbcType=INTEGER},
+            #{item.heatnoIndex,jdbcType=INTEGER},
+            #{item.grade,jdbcType=VARCHAR},
+            #{item.length,jdbcType=INTEGER},
+            #{item.actualLength,jdbcType=INTEGER},
+            #{item.width,jdbcType=INTEGER},
+            #{item.thickness,jdbcType=INTEGER},
+            #{item.spec,jdbcType=VARCHAR},
+            #{item.weight,jdbcType=DOUBLE},
+            #{item.billetNo,jdbcType=VARCHAR},
+            #{item.strandnoIndex,jdbcType=INTEGER},
+            #{item.cutStartTime,jdbcType=TIMESTAMP},
+            #{item.cutStopTime,jdbcType=TIMESTAMP},
+            #{item.ratingsResult,jdbcType=VARCHAR},
+            #{item.belongTable,jdbcType=VARCHAR},
+            #{item.stackOrCarId,jdbcType=VARCHAR},
+            #{item.bhtcId,jdbcType=VARCHAR},
+            #{item.shiftGroup,jdbcType=VARCHAR},
+            #{item.shift,jdbcType=VARCHAR},
+            #{item.billetWeight,jdbcType=DOUBLE},
+            #{item.assemblyNumber,jdbcType=VARCHAR},
+            #{item.brandNum,jdbcType=VARCHAR}
+            )
+        </foreach>
+    </insert>
 
 </mapper>

+ 4 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/actualControl/billetActual/billetActual/service/IBilletBasicInfoService.java

@@ -2,7 +2,9 @@ package org.jeecg.modules.actualControl.billetActual.billetActual.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.common.api.vo.Result;
 import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfoAdd;
 import org.jeecg.modules.billet.billetHotsend.entity.RulerDefaultConfig;
 import org.jeecg.modules.billet.billetHotsendConfig.entity.BilletHotsendTypeConfig;
 
@@ -27,4 +29,6 @@ public interface IBilletBasicInfoService extends IService<BilletBasicInfo> {
     boolean exists(QueryWrapper<BilletBasicInfo> eq);
 
     void addB(BilletBasicInfo billetBasicInfo, Integer num);
+
+    String addBilletBasicHandle(BilletBasicInfoAdd billetBasicInfoAdd);
 }

+ 773 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/actualControl/billetActual/billetActual/service/impl/BilletBasicInfoServiceImpl.java

@@ -4,10 +4,16 @@ import cn.hutool.core.date.DateTime;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfoAdd;
 import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletRulerConfig;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.RollClubOneInfo;
 import org.jeecg.modules.actualControl.billetActual.billetActual.mapper.BilletBasicInfoMapper;
 import org.jeecg.modules.actualControl.billetActual.billetActual.mapper.BilletRulerConfigMapper;
 import org.jeecg.modules.actualControl.billetActual.billetActual.service.IBilletBasicInfoService;
@@ -15,11 +21,22 @@ import org.jeecg.modules.actualControl.billetActual.billetActual.utils.MqttClien
 import org.jeecg.modules.actualControl.billetActual.billetAssemblyNumber.entity.BilletAssemblyNumber;
 import org.jeecg.modules.actualControl.billetActual.billetAssemblyNumber.mapper.BilletAssemblyNumberMapper;
 import org.jeecg.modules.actualControl.heatsActuals.entity.HeatsActuals;
+import org.jeecg.modules.actualControl.heatsActuals.mapper.HeatsActualsMapper;
+import org.jeecg.modules.actualControl.heatsActuals.service.IHeatsActualsService;
+import org.jeecg.modules.billet.billetHotsend.entity.BilletHotsend;
 import org.jeecg.modules.billet.billetHotsend.entity.RulerDefaultConfig;
+import org.jeecg.modules.billet.billetHotsend.mapper.BilletHotsendBaseMapper;
+import org.jeecg.modules.billet.billetHotsend.service.IBilletHotsendBaseService;
+import org.jeecg.modules.billet.billetHotsendChangeShift.entity.BilletHotsendChangeShift;
+import org.jeecg.modules.billet.billetHotsendChangeShift.mapper.BilletHotsendChangeShiftMapper;
 import org.jeecg.modules.billet.billetHotsendConfig.entity.BilletHotsendTypeConfig;
 import org.jeecg.modules.billet.billetHotsendConfig.service.IBilletHotsendTypeConfigService;
+import org.jeecg.modules.billet.rollClubOne.service.IRollClubOneDetailsService;
 import org.jeecg.modules.connConfig.mapper.ConfigMqttMapper;
+import org.simpleframework.xml.core.Complete;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -33,6 +50,7 @@ import java.util.stream.Collectors;
  * @Version: V1.0
  */
 @Service
+@Slf4j
 public class BilletBasicInfoServiceImpl extends ServiceImpl<BilletBasicInfoMapper, BilletBasicInfo> implements IBilletBasicInfoService {
 
     @Autowired
@@ -50,6 +68,15 @@ public class BilletBasicInfoServiceImpl extends ServiceImpl<BilletBasicInfoMappe
     @Autowired
     BilletAssemblyNumberMapper billetAssemblyNumberMapper;
 
+    @Autowired
+    HeatsActualsMapper heatsActualsMapper;
+
+    @Autowired
+    BilletHotsendBaseMapper billetHotsendBaseMapper;
+
+    @Autowired
+    RedisTemplate redisTemplate;
+
     @Override
     public void insertBatch(String sid, RulerDefaultConfig rulerDefaultConfig) {
         for (int i = 0; i < 4; i++) {
@@ -194,6 +221,752 @@ public class BilletBasicInfoServiceImpl extends ServiceImpl<BilletBasicInfoMappe
         }
     }
 
+    @Override
+    public String addBilletBasicHandle(BilletBasicInfoAdd billetBasicInfoAdd) {
+
+        String brandNum = String.format("billet:basic:info:brand:num:%s", billetBasicInfoAdd.getCcmNo()); // 牌号
+        String brandNumStr = !oConvertUtils.getString(redisTemplate.opsForValue().get(brandNum)).isEmpty() ? oConvertUtils.getString(redisTemplate.opsForValue().get(brandNum)) : "";
+
+        // 查询炉次传递单
+        LambdaQueryWrapper<BilletHotsend> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(BilletHotsend::getCcmNo, billetBasicInfoAdd.getCcmNo())
+                .eq(BilletHotsend::getHeatNo, billetBasicInfoAdd.getHeatNo())
+                .eq(BilletHotsend::getShift, billetBasicInfoAdd.getShift())
+                .eq(BilletHotsend::getShiftGroup, billetBasicInfoAdd.getShiftGroup())
+                .orderByDesc(BilletHotsend::getCreateTime).last("limit 1");
+        BilletHotsend billetHotsend = billetHotsendBaseMapper.selectOne(queryWrapper);
+        if (billetHotsend == null && billetBasicInfoAdd.getAddType() == 1){
+            // 处理整炉补录钢坯逻辑
+            completeHeatsHandle(billetBasicInfoAdd, brandNumStr);
+            return "整炉补录成功!";
+        }else if(billetHotsend == null && billetBasicInfoAdd.getAddType() == 2){
+            return "炉次传递单为空,补录失败!";
+        }
+
+        LambdaQueryWrapper<HeatsActuals> queryWrapperHeatsActuals = new LambdaQueryWrapper<HeatsActuals>()
+                .eq(HeatsActuals::getHeatsCode, billetBasicInfoAdd.getHeatNo())
+                .eq(HeatsActuals::getCasterCode, billetBasicInfoAdd.getCcmNo())
+                .eq(HeatsActuals::getShift, billetBasicInfoAdd.getShift())
+                .eq(HeatsActuals::getShiftGroup, billetBasicInfoAdd.getShiftGroup())
+                .orderByDesc(HeatsActuals::getCreateTime).last("limit 1");
+        HeatsActuals heatsActuals = heatsActualsMapper.selectOne(queryWrapperHeatsActuals);
+        if (heatsActuals == null){
+            return "炉次实绩为空,补录失败!";
+        }
+
+        //通过ccmNo和heatNo、shift、shiftGroup 查询出最新一条钢坯实绩信息
+        List<BilletBasicInfo> billetBasicInfoList = billetBasicInfoMapper.selectList(new QueryWrapper<BilletBasicInfo>()
+                .eq("ccm_no", billetBasicInfoAdd.getCcmNo())
+                .eq("heat_no", billetBasicInfoAdd.getHeatNo())
+                .eq("shift", billetBasicInfoAdd.getShift())
+                .eq("shift_group", billetBasicInfoAdd.getShiftGroup())
+                .orderByDesc("create_time"));
+        if (oConvertUtils.listIsEmpty(billetBasicInfoList)){
+            return "该炉钢坯实绩不存在,补录失败!";
+        }
+        BilletBasicInfo heatnoIndexNewBilletBasicInfo = billetBasicInfoList.stream().findFirst().orElse(null);
+        // 1流补录钢坯
+        if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getOneStrandNo()) && billetBasicInfoAdd.getOneStrandNoSum() > 0){
+            // 根据strand_no过滤出最新一条
+            BilletBasicInfo latestStrandBillet = billetBasicInfoList.stream()
+                    .filter(billetBasicInfo -> billetBasicInfo.getStrandNo().equals(billetBasicInfoAdd.getOneStrandNo()))
+                    .findFirst().orElse(null);
+            // 1流内顺序号
+            int strandnoIndex;
+            if (latestStrandBillet != null){
+                strandnoIndex = latestStrandBillet.getStrandnoIndex();
+            }else {
+                strandnoIndex = 0;
+            }
+            // 补坯总数
+            int number = billetBasicInfoAdd.getOneStrandNoSum();
+            // 流号
+            int strandNo = billetBasicInfoAdd.getOneStrandNo();
+            // 定尺
+            int length = billetBasicInfoAdd.getOneLength();
+            allBilletBasicInfo(strandnoIndex, heatnoIndexNewBilletBasicInfo, billetBasicInfoAdd, number, brandNumStr, billetHotsend, heatsActuals, strandNo, length);
+        }
+
+        // 2流补录钢坯
+        if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getTwoStrandNo()) && billetBasicInfoAdd.getTwoStrandNoSum() > 0){
+            // 根据strand_no过滤出最新一条
+            BilletBasicInfo latestStrandBillet = billetBasicInfoList.stream()
+                    .filter(billetBasicInfo -> billetBasicInfo.getStrandNo().equals(billetBasicInfoAdd.getTwoStrandNo()))
+                    .findFirst().orElse(null);
+            // 2流内顺序号
+            int strandnoIndex;
+            if (latestStrandBillet != null){
+                strandnoIndex = latestStrandBillet.getStrandnoIndex();
+            }else {
+                strandnoIndex = 0;
+            }
+            // 补坯总数
+            int number = billetBasicInfoAdd.getTwoStrandNoSum();
+            // 流号
+            int strandNo = billetBasicInfoAdd.getTwoStrandNo();
+            // 定尺
+            int length = billetBasicInfoAdd.getTwoLength();
+            allBilletBasicInfo(strandnoIndex, heatnoIndexNewBilletBasicInfo, billetBasicInfoAdd, number, brandNumStr, billetHotsend, heatsActuals, strandNo, length);
+        }
+
+        // 3流补录钢坯
+        if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getThreeStrandNo()) && billetBasicInfoAdd.getThreeStrandNoSum() > 0){
+            // 根据strand_no过滤出最新一条
+            BilletBasicInfo latestStrandBillet = billetBasicInfoList.stream()
+                    .filter(billetBasicInfo -> billetBasicInfo.getStrandNo().equals(billetBasicInfoAdd.getThreeStrandNo()))
+                    .findFirst().orElse(null);
+            // 3流内顺序号
+            int strandnoIndex;
+            if (latestStrandBillet != null){
+                strandnoIndex = latestStrandBillet.getStrandnoIndex();
+            }else {
+                strandnoIndex = 0;
+            }
+            // 补坯总数
+            int number = billetBasicInfoAdd.getThreeStrandNoSum();
+            // 流号
+            int strandNo = billetBasicInfoAdd.getThreeStrandNo();
+            // 定尺
+            int length = billetBasicInfoAdd.getThreeLength();
+            allBilletBasicInfo(strandnoIndex, heatnoIndexNewBilletBasicInfo, billetBasicInfoAdd, number, brandNumStr, billetHotsend, heatsActuals, strandNo, length);
+        }
+
+        // 4流补录钢坯
+        if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getFourStrandNo()) && billetBasicInfoAdd.getFourStrandNoSum() > 0){
+            // 根据strand_no过滤出最新一条
+            BilletBasicInfo latestStrandBillet = billetBasicInfoList.stream()
+                    .filter(billetBasicInfo -> billetBasicInfo.getStrandNo().equals(billetBasicInfoAdd.getFourStrandNo()))
+                    .findFirst().orElse(null);
+            // 4流内顺序号
+            int strandnoIndex;
+            if (latestStrandBillet != null){
+                strandnoIndex = latestStrandBillet.getStrandnoIndex();
+            }else {
+                strandnoIndex = 0;
+            }
+            // 补坯总数
+            int number = billetBasicInfoAdd.getFourStrandNoSum();
+            // 流号
+            int strandNo = billetBasicInfoAdd.getFourStrandNo();
+            // 定尺
+            int length = billetBasicInfoAdd.getFourLength();
+            allBilletBasicInfo(strandnoIndex, heatnoIndexNewBilletBasicInfo, billetBasicInfoAdd, number, brandNumStr, billetHotsend, heatsActuals, strandNo, length);
+        }
+
+        // 5流补录钢坯
+        if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getFiveStrandNo()) && billetBasicInfoAdd.getFiveStrandNoSum() > 0){
+            // 根据strand_no过滤出最新一条
+            BilletBasicInfo latestStrandBillet = billetBasicInfoList.stream()
+                    .filter(billetBasicInfo -> billetBasicInfo.getStrandNo().equals(billetBasicInfoAdd.getFiveStrandNo()))
+                    .findFirst().orElse(null);
+            // 5流内顺序号
+            int strandnoIndex;
+            if (latestStrandBillet != null){
+                strandnoIndex = latestStrandBillet.getStrandnoIndex();
+            }else {
+                strandnoIndex = 0;
+            }
+            // 补坯总数
+            int number = billetBasicInfoAdd.getFiveStrandNoSum();
+            // 流号
+            int strandNo = billetBasicInfoAdd.getFiveStrandNo();
+            // 定尺
+            int length = billetBasicInfoAdd.getFiveLength();
+            allBilletBasicInfo(strandnoIndex, heatnoIndexNewBilletBasicInfo, billetBasicInfoAdd, number, brandNumStr, billetHotsend, heatsActuals, strandNo, length);
+        }
+
+        // 6流补录钢坯
+        if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getSixStrandNo()) && billetBasicInfoAdd.getSixStrandNoSum() > 0){
+            // 根据strand_no过滤出最新一条
+            BilletBasicInfo latestStrandBillet = billetBasicInfoList.stream()
+                    .filter(billetBasicInfo -> billetBasicInfo.getStrandNo().equals(billetBasicInfoAdd.getSixStrandNo()))
+                    .findFirst().orElse(null);
+            // 6流内顺序号
+            int strandnoIndex;
+            if (latestStrandBillet != null){
+                strandnoIndex = latestStrandBillet.getStrandnoIndex();
+            }else {
+                strandnoIndex = 0;
+            }
+            // 补坯总数
+            int number = billetBasicInfoAdd.getSixStrandNoSum();
+            // 流号
+            int strandNo = billetBasicInfoAdd.getSixStrandNo();
+            // 定尺
+            int length = billetBasicInfoAdd.getSixLength();
+            allBilletBasicInfo(strandnoIndex, heatnoIndexNewBilletBasicInfo, billetBasicInfoAdd, number, brandNumStr, billetHotsend, heatsActuals, strandNo, length);
+        }
+
+        // 7流补录钢坯
+        if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getSevenStrandNo()) && billetBasicInfoAdd.getSevenStrandNoSum() > 0){
+            // 根据strand_no过滤出最新一条
+            BilletBasicInfo latestStrandBillet = billetBasicInfoList.stream()
+                    .filter(billetBasicInfo -> billetBasicInfo.getStrandNo().equals(billetBasicInfoAdd.getSevenStrandNo()))
+                    .findFirst().orElse(null);
+            // 7流内顺序号
+            int strandnoIndex;
+            if (latestStrandBillet != null){
+                strandnoIndex = latestStrandBillet.getStrandnoIndex();
+            }else {
+                strandnoIndex = 0;
+            }
+            // 补坯总数
+            int number = billetBasicInfoAdd.getSevenStrandNoSum();
+            // 流号
+            int strandNo = billetBasicInfoAdd.getSevenStrandNo();
+            // 定尺
+            int length = billetBasicInfoAdd.getSevenLength();
+            allBilletBasicInfo(strandnoIndex, heatnoIndexNewBilletBasicInfo, billetBasicInfoAdd, number, brandNumStr, billetHotsend, heatsActuals, strandNo, length);
+        }
+
+        // 8流补录钢坯
+        if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getEightStrandNo()) && billetBasicInfoAdd.getEightStrandNoSum() > 0){
+            // 根据strand_no过滤出最新一条
+            BilletBasicInfo latestStrandBillet = billetBasicInfoList.stream()
+                    .filter(billetBasicInfo -> billetBasicInfo.getStrandNo().equals(billetBasicInfoAdd.getEightStrandNo()))
+                    .findFirst().orElse(null);
+            // 8流内顺序号
+            int strandnoIndex;
+            if (latestStrandBillet != null){
+                strandnoIndex = latestStrandBillet.getStrandnoIndex();
+            }else {
+                strandnoIndex = 0;
+            }
+            // 补坯总数
+            int number = billetBasicInfoAdd.getEightStrandNoSum();
+            // 流号
+            int strandNo = billetBasicInfoAdd.getEightStrandNo();
+            // 定尺
+            int length = billetBasicInfoAdd.getEightLength();
+            allBilletBasicInfo(strandnoIndex, heatnoIndexNewBilletBasicInfo, billetBasicInfoAdd, number, brandNumStr, billetHotsend, heatsActuals, strandNo, length);
+        }
+        return "补录成功!";
+    }
+
+    /**
+     * 整炉添加逻辑处理
+     * @param billetBasicInfoAdd
+     */
+    private String completeHeatsHandle(BilletBasicInfoAdd billetBasicInfoAdd, String brandNumStr) {
+
+        LambdaQueryWrapper<HeatsActuals> queryWrapper1 = new LambdaQueryWrapper<HeatsActuals>()
+                .eq(HeatsActuals::getHeatsCode, billetBasicInfoAdd.getHeatNo())
+                .orderByDesc(HeatsActuals::getCreateTime).last("limit 1");
+        HeatsActuals actualsCheck = heatsActualsMapper.selectOne(queryWrapper1);
+        if (actualsCheck != null){
+            return "炉号重复,补录失败!";
+        }
+
+        // 查询基础信息
+        LambdaQueryWrapper<HeatsActuals> queryWrapper = new LambdaQueryWrapper<HeatsActuals>()
+                .eq(HeatsActuals::getCasterCode, billetBasicInfoAdd.getCcmNo())
+                .orderByDesc(HeatsActuals::getCreateTime).last("limit 1");
+        HeatsActuals actuals = heatsActualsMapper.selectOne(queryWrapper);
+
+        HeatsActuals heatsActuals = new HeatsActuals();
+        BeanUtils.copyProperties(actuals, heatsActuals);
+
+        try {
+            heatsActuals.setId(String.valueOf(IdWorker.getId()));
+            heatsActuals.setHeatsCode(billetBasicInfoAdd.getHeatNo());
+            heatsActuals.setShift(billetBasicInfoAdd.getShift());
+            heatsActuals.setShiftGroup(billetBasicInfoAdd.getShiftGroup());
+            //根据最新一炉的炉次信息计算 空包重量核算
+            if(heatsActuals.getMoltenSteelWeight() > 0 && heatsActuals.getFullLadleWeight() > 0){ // 如果钢水重量存在核算
+                heatsActuals.setEmptyLadleWeight(heatsActuals.getFullLadleWeight() - heatsActuals.getMoltenSteelWeight());
+            }
+            // 整理添加总支数
+            heatsActuals.setBilletSum(0);
+            heatsActuals.setBlankOutput(0.0d);
+            heatsActuals.setCreateTime(new Date());
+            heatsActuals.setUpdateTime(new Date());
+            heatsActualsMapper.insert(heatsActuals);
+        } catch (Exception e) {
+            log.error("整炉补坯保存炉次实绩数据出现异常", e);
+            throw new RuntimeException("整炉补坯保存炉次实绩数据出现失败!", e);
+        }
+
+        //新增炉次传递单
+        BilletHotsend billetHotsend = new BilletHotsend();
+        billetHotsend.setId(String.valueOf(IdWorker.getId()));
+        billetHotsend.setCcmNo(billetBasicInfoAdd.getCcmNo()); // 铸机号
+        billetHotsend.setHeatNo(billetBasicInfoAdd.getHeatNo()); // 炉号
+        billetHotsend.setShiftGroup(billetBasicInfoAdd.getShiftGroup()); // 班组
+        billetHotsend.setShift(billetBasicInfoAdd.getShift()); // 班别
+        billetHotsend.setSteel(heatsActuals.getGrade()); // 钢种
+        billetHotsend.setSpec(heatsActuals.getSpec()); // 规格
+
+        billetHotsend.setBrandNum(brandNumStr);
+        billetHotsend.setAmountTotal(heatsActuals.getBilletSum()); // 支数
+        billetHotsend.setBlankOutput(0.0d); // 出批量
+        billetHotsend.setDecideWeight(0.0d); // 定重
+        billetHotsend.setWasteBlankOutput(0.0);
+        billetHotsend.setCreateTime(new Date());
+        billetHotsend.setUpdateTime(new Date());
+        billetHotsendBaseMapper.insert(billetHotsend);
+
+        LambdaQueryWrapper<BilletBasicInfo> queryWrapperB = new LambdaQueryWrapper<BilletBasicInfo>()
+                .eq(BilletBasicInfo::getCcmNo, billetBasicInfoAdd.getCcmNo())
+                .orderByDesc(BilletBasicInfo::getCreateTime).last("limit 1");
+        BilletBasicInfo billetInfo = baseMapper.selectOne(queryWrapperB);
+
+        BilletBasicInfo billetBasicInfo = new BilletBasicInfo();
+        BeanUtils.copyProperties(billetInfo, billetBasicInfo);
+        // 去棒一数据补录
+        if (oConvertUtils.listIsEmpty(billetBasicInfoAdd.getRollClubOneList())){
+            // 整炉全部去组批
+            // 1流补录钢坯
+            if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getOneStrandNo()) && billetBasicInfoAdd.getOneStrandNoSum() > 0){
+                int addSum = billetBasicInfoAdd.getOneStrandNoSum();
+                int strandNo = billetBasicInfoAdd.getOneStrandNo();
+                int length = billetBasicInfoAdd.getOneLength();
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, addSum, strandNo, length);
+            }
+            // 2流补录钢坯
+            if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getTwoStrandNo()) && billetBasicInfoAdd.getTwoStrandNoSum() > 0){
+                int addSum = billetBasicInfoAdd.getTwoStrandNoSum();
+                int strandNo = billetBasicInfoAdd.getTwoStrandNo();
+                int length = billetBasicInfoAdd.getTwoLength();
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, addSum, strandNo, length);
+            }
+            // 3流补录钢坯
+            if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getThreeStrandNo()) && billetBasicInfoAdd.getThreeStrandNoSum() > 0){
+                int addSum = billetBasicInfoAdd.getOneStrandNoSum();
+                int strandNo = billetBasicInfoAdd.getOneStrandNo();
+                int length = billetBasicInfoAdd.getOneLength();
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, addSum, strandNo, length);
+            }
+
+            // 4流补录钢坯
+            if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getFourStrandNo()) && billetBasicInfoAdd.getFourStrandNoSum() > 0){
+                int addSum = billetBasicInfoAdd.getFourStrandNoSum();
+                int strandNo = billetBasicInfoAdd.getFourStrandNo();
+                int length = billetBasicInfoAdd.getFourLength();
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, addSum, strandNo, length);
+            }
+
+            // 5流补录钢坯
+            if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getFiveStrandNo()) && billetBasicInfoAdd.getFiveStrandNoSum() > 0){
+                int addSum = billetBasicInfoAdd.getFiveStrandNoSum();
+                int strandNo = billetBasicInfoAdd.getFiveStrandNo();
+                int length = billetBasicInfoAdd.getFiveLength();
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, addSum, strandNo, length);
+            }
+
+            // 6流补录钢坯
+            if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getSixStrandNo()) && billetBasicInfoAdd.getSixStrandNoSum() > 0){
+                int addSum = billetBasicInfoAdd.getSixStrandNoSum();
+                int strandNo = billetBasicInfoAdd.getSixStrandNo();
+                int length = billetBasicInfoAdd.getSixLength();
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, addSum, strandNo, length);
+            }
+
+            // 7流补录钢坯
+            if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getSevenStrandNo()) && billetBasicInfoAdd.getSevenStrandNoSum() > 0){
+                int addSum = billetBasicInfoAdd.getSevenStrandNoSum();
+                int strandNo = billetBasicInfoAdd.getSevenStrandNo();
+                int length = billetBasicInfoAdd.getSevenLength();
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, addSum, strandNo, length);
+            }
+
+            // 8流补录钢坯
+            if (oConvertUtils.isNotEmpty(billetBasicInfoAdd.getEightStrandNo()) && billetBasicInfoAdd.getEightStrandNoSum() > 0){
+                int addSum = billetBasicInfoAdd.getEightStrandNoSum();
+                int strandNo = billetBasicInfoAdd.getEightStrandNo();
+                int length = billetBasicInfoAdd.getEightLength();
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, addSum, strandNo, length);
+            }
+            // 查询整个炉钢坯基础信息
+            List<BilletBasicInfo> resultList = baseMapper.selectList(new LambdaQueryWrapper<BilletBasicInfo>()
+                    .eq(BilletBasicInfo::getCcmNo, billetBasicInfoAdd.getCcmNo())
+                    .eq(BilletBasicInfo::getHeatNo, billetBasicInfoAdd.getHeatNo())
+                    .eq(BilletBasicInfo::getShift, billetBasicInfoAdd.getShift())
+                    .eq(BilletBasicInfo::getShiftGroup, billetBasicInfoAdd.getShiftGroup()));
+            if (oConvertUtils.listIsNotEmpty(resultList)){
+                // 处理流内顺序号、和炉内顺序号
+                updateBilletBasicInfoAndSave(resultList);
+            }
+            if (oConvertUtils.listIsNotEmpty(resultList) && resultList.size() >= 4) {
+                int size = resultList.size();
+                int maxProcessed = (size / 4) * 4; // 计算可处理的最大4的倍数
+                for (int i = 0; i < maxProcessed; i += 4) {
+                    int start = i;
+                    int end = Math.min(i + 4, maxProcessed);
+                    //组批成功的,对钢坯实绩进行组批号更新
+                    updateBilletBasicInfoAsendAssemblyHandle(resultList.subList(start, end), billetBasicInfoAdd);
+                }
+            }
+
+            // 更新炉次传递单中的总数和坯重
+            double totalBilletWeight = resultList.stream()
+                    .mapToDouble(BilletBasicInfo::getBilletWeight)
+                    .sum();
+            billetHotsend.setAmountTotal(resultList.size());
+            billetHotsend.setBlankOutput(totalBilletWeight);
+            billetHotsendBaseMapper.updateById(billetHotsend);
+
+            // 更新炉次实绩中的总数和坯重
+            heatsActuals.setBlankOutput(totalBilletWeight);
+            heatsActuals.setBilletSum(resultList.size());
+            heatsActualsMapper.updateById(heatsActuals);
+        }else {
+            int oneStrandRemainSum = 0;
+            int twoStrandRemainSum = 0;
+            int threeStrandRemainSum = 0;
+            int fourStrandRemainSum = 0;
+            int fiveStrandRemainSum = 0;
+            int sixStrandRemainSum = 0;
+
+            // 有去组批的,有去棒一的(混合情况) 1、先处理去棒一的数据 2、在减掉棒一的数量,剩余的进行组批
+            List<BilletBasicInfo> resultList = new ArrayList<>();
+            // 添加棒一明细
+            List<RollClubOneInfo> rollClubOneList = billetBasicInfoAdd.getRollClubOneList();
+            // 遍历 RollClubOneInfo 列表
+            for (RollClubOneInfo item : rollClubOneList) {
+                Integer strandNo = item.getStrandNo();
+                Integer length = item.getLength();
+                Integer addSum = item.getAddSum();
+                if (strandNo == 1){
+                    oneStrandRemainSum = billetBasicInfoAdd.getOneStrandNoSum() - addSum;
+                }else if (strandNo == 2){
+                    twoStrandRemainSum = billetBasicInfoAdd.getTwoStrandNoSum() - addSum;
+                }else if (strandNo == 3){
+                    threeStrandRemainSum = billetBasicInfoAdd.getThreeStrandNoSum() - addSum;
+                }else if (strandNo == 4){
+                    fourStrandRemainSum = billetBasicInfoAdd.getFourStrandNoSum() - addSum;
+                }else if (strandNo == 5){
+                    fiveStrandRemainSum = billetBasicInfoAdd.getFiveStrandNoSum() - addSum;
+                }else if (strandNo == 6){
+                    sixStrandRemainSum = billetBasicInfoAdd.getSixStrandNoSum() - addSum;
+                }
+                // 根据 addSum 生成对应数量的 BilletBasicInfo 对象
+                for (int i = 0; i < addSum; i++) {
+                    BilletBasicInfo billet = new BilletBasicInfo();
+                    BeanUtils.copyProperties(billetBasicInfo, billet);
+                    billet.setStrandNo(strandNo);
+                    billet.setLength(length);
+                    // 设置其他必要属性
+                    billet.setId(String.valueOf(IdWorker.getId()));
+                    billet.setHeatNo(billetBasicInfoAdd.getHeatNo());
+                    String billetNo = generateUniqueBilletNo(Integer.valueOf(billetBasicInfoAdd.getCcmNo()), billetBasicInfoAdd.getHeatNo());
+                    billet.setBilletNo(billetNo);
+                    billet.setCreateTime(new Date());
+                    billet.setUpdateTime(new Date());
+                    billet.setAssemblyNumber(null);
+                    billet.setBelongTable("roll_club_one");
+                    billet.setBhtcId("1");
+                    // 查询定尺规则
+                    LambdaQueryWrapper<BilletRulerConfig> queryWrapperbilletRulerConfig = new LambdaQueryWrapper<BilletRulerConfig>().eq(BilletRulerConfig::getLength, billetBasicInfo.getLength());
+                    BilletRulerConfig billetRulerConfig = billetRulerConfigMapper.selectOne(queryWrapperbilletRulerConfig);
+                    Double weight = 0.0;
+                    if (oConvertUtils.isEmpty(billetRulerConfig)) {
+                        weight = billetBasicInfo.getWeight();
+                    } else {
+                        weight = billetRulerConfig.getWeight();
+                    }
+                    billet.setWeight(weight);
+                    billet.setBilletWeight(weight);
+                    resultList.add(billet);
+                }
+            }
+            if (oConvertUtils.listIsNotEmpty(resultList)){
+                // 对 resultList 中的元素按 Strandno 分组后重新赋值 StrandnoIndex
+                Map<Integer, List<BilletBasicInfo>> strandNoGroups = resultList.stream()
+                        .collect(Collectors.groupingBy(BilletBasicInfo::getStrandNo));
+
+                // 对每个分组内的元素按顺序赋值 StrandnoIndex
+                strandNoGroups.forEach((strandNo, groupList) -> {
+                    for (int i = 0; i < groupList.size(); i++) {
+                        groupList.get(i).setStrandnoIndex(i + 1); // 每组内从1开始
+                    }
+                });
+
+                // 对 resultList 中的元素按整体顺序赋值 HeatnoIndex(保持原有逻辑)
+                for (int i = 0; i < resultList.size(); i++) {
+                    resultList.get(i).setHeatnoIndex(i + 1); // 整体从1开始
+                }
+
+                log.info("整炉去棒一的钢坯总数:{}", resultList.size());
+                baseMapper.insertBatch(resultList);
+
+                
+
+            }
+
+
+            if (oneStrandRemainSum > 0){
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, oneStrandRemainSum, 1, billetBasicInfoAdd.getOneLength());
+            }
+            if (twoStrandRemainSum > 0){
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, twoStrandRemainSum, 2, billetBasicInfoAdd.getTwoLength());
+            }
+            if (threeStrandRemainSum > 0){
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, threeStrandRemainSum, 3, billetBasicInfoAdd.getThreeLength());
+            }
+            if (fourStrandRemainSum > 0){
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, fourStrandRemainSum, 4, billetBasicInfoAdd.getFourLength());
+            }
+            if (fiveStrandRemainSum > 0){
+               saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, fourStrandRemainSum, 5, billetBasicInfoAdd.getFiveLength());
+            }
+            if (sixStrandRemainSum > 0){
+                saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, sixStrandRemainSum, 6, billetBasicInfoAdd.getSixLength());
+            }
+
+            // 查询去除棒一,整炉钢坯基础信息
+            List<BilletBasicInfo> result = baseMapper.selectList(new LambdaQueryWrapper<BilletBasicInfo>()
+                    .eq(BilletBasicInfo::getCcmNo, billetBasicInfoAdd.getCcmNo())
+                    .eq(BilletBasicInfo::getHeatNo, billetBasicInfoAdd.getHeatNo())
+                    .eq(BilletBasicInfo::getShift, billetBasicInfoAdd.getShift())
+                    .eq(BilletBasicInfo::getShiftGroup, billetBasicInfoAdd.getShiftGroup())
+                    .isNull(BilletBasicInfo::getBelongTable));
+            log.info("整炉去除棒一需要组批的钢坯总数:{}", result.size());
+            if (oConvertUtils.listIsNotEmpty(result)){
+                // 处理流内顺序号、和炉内顺序号
+                updateBilletBasicInfoAndSave(result);
+            }
+
+            if (oConvertUtils.listIsNotEmpty(result) && result.size() >= 4) {
+                int size = result.size();
+                int maxProcessed = (size / 4) * 4; // 计算可处理的最大4的倍数
+                for (int i = 0; i < maxProcessed; i += 4) {
+                    int start = i;
+                    int end = Math.min(i + 4, maxProcessed);
+                    //组批成功的,对钢坯实绩进行组批号更新
+                    updateBilletBasicInfoAsendAssemblyHandle(result.subList(start, end), billetBasicInfoAdd);
+                }
+            }
+
+            result.addAll(resultList);
+
+            // 更新炉次传递单中的总数和坯重
+            double totalBilletWeight = result.stream()
+                    .mapToDouble(BilletBasicInfo::getBilletWeight)
+                    .sum();
+            billetHotsend.setAmountTotal(result.size());
+            billetHotsend.setBlankOutput(totalBilletWeight);
+            billetHotsendBaseMapper.updateById(billetHotsend);
+
+            // 更新炉次实绩中的总数和坯重
+            heatsActuals.setBlankOutput(totalBilletWeight);
+            heatsActuals.setBilletSum(result.size());
+            heatsActualsMapper.updateById(heatsActuals);
+        }
+        return "整炉补录成功!";
+    }
+
+
+    /**
+     * 处理流内顺序号、和炉内顺序号
+     * @param resultList
+     */
+    public void updateBilletBasicInfoAndSave(List<BilletBasicInfo> resultList) {
+        if (oConvertUtils.listIsEmpty(resultList)) {
+            return;
+        }
+        Map<Integer, List<BilletBasicInfo>> strandNoGroupMap = resultList.stream()
+                .collect(Collectors.groupingBy(BilletBasicInfo::getStrandNo));
+        strandNoGroupMap.forEach((strandNo, groupList) -> {
+            for (int i = 0; i < groupList.size(); i++) {
+                BilletBasicInfo item = groupList.get(i);
+                item.setStrandnoIndex(i + 1); // 组内序号从1开始
+            }
+        });
+        for (int i = 0; i < resultList.size(); i++) {
+            resultList.get(i).setHeatnoIndex(i + 1); // 全局序号从1开始
+        }
+        resultList.forEach(item -> {
+            baseMapper.updateById(item);
+        });
+
+    }
+
+    /**
+     * 整炉处理
+     * @param billetBasicInfo
+     * @param billetBasicInfoAdd
+     * @param addSum
+     * @param strandNo
+     * @param length
+     */
+    private void saveBilletBasicInfoList(BilletBasicInfo billetBasicInfo, BilletBasicInfoAdd billetBasicInfoAdd, int addSum, int strandNo, int length) {
+        List<BilletBasicInfo> resultList = new ArrayList<>();
+        // 根据 addSum 生成对应数量的 BilletBasicInfo 对象
+        for (int i = 0; i < addSum; i++) {
+            BilletBasicInfo billet = new BilletBasicInfo();
+            BeanUtils.copyProperties(billetBasicInfo, billet);
+            billet.setStrandNo(strandNo);
+            billet.setLength(length);
+            // 设置其他必要属性
+            billet.setId(String.valueOf(IdWorker.getId()));
+            billet.setHeatNo(billetBasicInfoAdd.getHeatNo());
+            String billetNo = generateUniqueBilletNo(Integer.valueOf(billetBasicInfoAdd.getCcmNo()), billetBasicInfoAdd.getHeatNo());
+            billet.setBilletNo(billetNo);
+            billet.setCreateTime(new Date());
+            billet.setUpdateTime(new Date());
+            billet.setAssemblyNumber(null);
+            billet.setBelongTable(null);
+            billet.setBhtcId(null);
+            // 查询定尺规则
+            LambdaQueryWrapper<BilletRulerConfig> queryWrapperbilletRulerConfig = new LambdaQueryWrapper<BilletRulerConfig>().eq(BilletRulerConfig::getLength, billetBasicInfo.getLength());
+            BilletRulerConfig billetRulerConfig = billetRulerConfigMapper.selectOne(queryWrapperbilletRulerConfig);
+            Double weight = 0.0;
+            if (oConvertUtils.isEmpty(billetRulerConfig)) {
+                weight = billetBasicInfo.getWeight();
+            } else {
+                weight = billetRulerConfig.getWeight();
+            }
+            billet.setWeight(weight);
+            billet.setBilletWeight(weight);
+            resultList.add(billet);
+        }
+        baseMapper.insertBatch(resultList);
+    }
+
+
+    /**
+     * 批量生成
+     * @param strandnoIndex
+     * @param billetBasicInfoLast
+     * @param billetBasicInfoAdd
+     * @param number
+     * @param brandNumStr
+     * @param billetHotsend
+     * @param heatsActuals
+     */
+    private void allBilletBasicInfo(int strandnoIndex, BilletBasicInfo billetBasicInfoLast, BilletBasicInfoAdd billetBasicInfoAdd,
+                                    int number, String brandNumStr, BilletHotsend billetHotsend, HeatsActuals heatsActuals, int strandNo, int length) {
+        List<BilletBasicInfo> billetBasicInfoList = new ArrayList<>();
+
+        // 初始化计数器,从billetBasicInfoLast的值开始
+        int currentHeatnoIndex = billetBasicInfoLast.getHeatnoIndex();
+        int currentStrandnoIndex = strandnoIndex;
+
+        /**
+         *  对number 循环生成新的钢坯实绩、并维护炉次实绩、炉次传递单、交班信息
+         */
+        for (int i = 0; i < number; i++) {
+            BilletBasicInfo billetBasicInfo = new BilletBasicInfo();
+            BeanUtils.copyProperties(billetBasicInfoLast, billetBasicInfo);
+            billetBasicInfo.setId(String.valueOf(IdWorker.getId()));
+            billetBasicInfo.setCreateTime(new Date());
+            billetBasicInfo.setUpdateBy(null);
+            billetBasicInfo.setUpdateTime(null);
+            billetBasicInfo.setCreateBy(null);
+            billetBasicInfo.setCutStartTime(null);
+            billetBasicInfo.setCutStopTime(null);
+            billetBasicInfo.setBelongTable(null);
+            billetBasicInfo.setBhtcId(null);
+            billetBasicInfo.setAssemblyNumber(null);
+
+            billetBasicInfo.setCcmNo(Integer.valueOf(billetBasicInfoAdd.getCcmNo()));
+            billetBasicInfo.setHeatNo(billetBasicInfoAdd.getHeatNo());
+            // 随机生成坯号
+            String billetNo = generateUniqueBilletNo(Integer.valueOf(billetBasicInfoAdd.getCcmNo()), billetBasicInfoAdd.getHeatNo());
+            billetBasicInfo.setBilletNo(billetNo);
+
+            billetBasicInfo.setShift(billetBasicInfoAdd.getShift());
+            billetBasicInfo.setShiftGroup(billetBasicInfoAdd.getShiftGroup());
+            billetBasicInfo.setStrandNo(strandNo);//流号
+            billetBasicInfo.setLength(length);
+
+            // 查询定尺规则
+            LambdaQueryWrapper<BilletRulerConfig> queryWrapperbilletRulerConfig = new LambdaQueryWrapper<BilletRulerConfig>()
+                    .eq(BilletRulerConfig::getLength, billetBasicInfo.getLength());
+            BilletRulerConfig billetRulerConfig = billetRulerConfigMapper.selectOne(queryWrapperbilletRulerConfig);
+            Double weight = 0.0;
+            if(oConvertUtils.isNotEmpty(billetRulerConfig)) {
+                weight = billetRulerConfig.getWeight();
+            }
+            billetBasicInfo.setBilletWeight(weight);
+            billetBasicInfo.setWeight(weight);
+
+            // 使用计数器并递增
+            currentHeatnoIndex++;
+            currentStrandnoIndex++;
+
+            billetBasicInfo.setHeatnoIndex(currentHeatnoIndex);  // 炉内顺序号
+            billetBasicInfo.setStrandnoIndex(currentStrandnoIndex);  // 流内顺序号
+            billetBasicInfo.setBrandNum(brandNumStr);
+            billetBasicInfoMapper.insert(billetBasicInfo);
+            billetBasicInfoList.add(billetBasicInfo);
+
+            UpdateWrapper<BilletBasicInfo> wrapper = new UpdateWrapper<>();
+            wrapper.set("assembly_number", null)
+                    .eq("id", billetBasicInfo.getId());
+            billetBasicInfoMapper.update(null, wrapper);
+
+            // 炉次实绩出坯量维护
+            if (oConvertUtils.isNotEmpty(heatsActuals)) {
+                heatsActuals.setId(heatsActuals.getId());
+                heatsActuals.setBlankOutput(heatsActuals.getBlankOutput() + weight);
+                heatsActualsMapper.updateById(heatsActuals);
+            }
+
+            // 钢坯热送单炉支数传递单信息维护
+            if (oConvertUtils.isNotEmpty(billetHotsend) && oConvertUtils.isNotEmpty(billetHotsend.getId())) { // 编辑钢坯热送单炉支数传递单
+                billetHotsend.setAmountTotal(billetHotsend.getAmountTotal() + 1);
+                billetHotsend.setBlankOutput(billetHotsend.getBlankOutput() + weight); // 出坯量
+                billetHotsend.setDecideWeight(billetHotsend.getDecideWeight() + billetBasicInfo.getWeight()); // 定重
+                billetHotsendBaseMapper.updateById(billetHotsend);
+            }
+        }
+
+        //
+        //组批逻辑处理 查询钢坯实绩,组批号不为空,belongtable为空
+        List<BilletBasicInfo> availableBilletBasicInfoList = billetBasicInfoMapper.selectList(
+                new QueryWrapper<BilletBasicInfo>()
+                        .eq("ccm_no", billetBasicInfoAdd.getCcmNo())
+                        .eq("heat_no", billetBasicInfoAdd.getHeatNo())
+                        .eq("shift", billetBasicInfoAdd.getShift())
+                        .eq("shift_group", billetBasicInfoAdd.getShiftGroup())
+                        .isNull("belong_table")           // 使用 isNull 代替 eq(null)
+                        .isNotNull("assembly_number")     // 使用 isNotNull 代替 ne(null)
+                        .orderByDesc("create_time"));
+        if (oConvertUtils.listIsNotEmpty(availableBilletBasicInfoList)){
+            // 按assembly_number分组并过滤出数量不等于4的组
+            Map<String, List<BilletBasicInfo>> filteredGroups = availableBilletBasicInfoList.stream()
+                    .collect(Collectors.groupingBy(BilletBasicInfo::getAssemblyNumber))
+                    .entrySet().stream()
+                    .filter(entry -> entry.getValue().size() != 4)
+                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+            // 将过滤后的结果,转换为单个列表并设置 assemblyNumber 为 null
+            List<BilletBasicInfo> resultList = filteredGroups.values().stream()
+                    .flatMap(Collection::stream)
+                    .peek(billet -> billet.setAssemblyNumber(null))
+                    .collect(Collectors.toList());
+
+            resultList.addAll(billetBasicInfoList);
+
+            if (oConvertUtils.listIsNotEmpty(resultList) && resultList.size() >= 4) {
+                int size = resultList.size();
+                int maxProcessed = (size / 4) * 4; // 计算可处理的最大4的倍数
+                for (int i = 0; i < maxProcessed; i += 4) {
+                    int start = i;
+                    int end = Math.min(i + 4, maxProcessed);
+
+                    // 处理当前分组数据
+                    updateBilletBasicInfoAsendAssemblyHandle(resultList.subList(start, end), billetBasicInfoAdd);
+                }
+            }
+        }
+    }
+
+    /**
+     * 组批处理
+     * @param billetBasicInfoList
+     * @param billetBasicInfoAdd
+     */
+    private void updateBilletBasicInfoAsendAssemblyHandle(List<BilletBasicInfo> billetBasicInfoList, BilletBasicInfoAdd billetBasicInfoAdd){
+
+        String assemblyNumber = generateUniqueAssemblyNumber(Integer.valueOf(billetBasicInfoAdd.getCcmNo()), billetBasicInfoAdd.getHeatNo());
+        // 遍历列表,为每个元素设置装配编号并更新到数据库
+        billetBasicInfoList.forEach(x -> {
+            x.setAssemblyNumber(assemblyNumber);
+            billetBasicInfoMapper.updateById(x);
+        });
+    }
     /**
      * 生成高线逻辑
      * @param billetBasicInfo