Преглед изворни кода

Merge branch 'master' of http://123.57.213.14:3001/zgzt/dosb-java

guoqiang пре 1 месец
родитељ
комит
322f5534f0

+ 646 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetOriginalProductRecord/controller/BilletOriginalProductRecordController.java

@@ -0,0 +1,646 @@
+package org.jeecg.modules.billet.billetOriginalProductRecord.controller;
+import java.util.*;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import org.apache.commons.collections.CollectionUtils;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.system.query.QueryGenerator;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
+import org.jeecg.modules.actualControl.billetActual.billetActual.service.IBilletBasicInfoService;
+import org.jeecg.modules.actualControl.heatsActuals.service.IHeatsActualsService;
+import org.jeecg.modules.billet.billetHotsend.entity.BilletHotsend;
+import org.jeecg.modules.billet.billetHotsend.service.IBilletHotsendBaseService;
+import org.jeecg.modules.billet.billetHotsendChangeShift.entity.BilletHotsendChangeShift;
+import org.jeecg.modules.billet.billetHotsendChangeShift.service.IBilletHotsendChangeShiftService;
+import org.jeecg.modules.billet.billetOriginalProductRecord.entity.BilletOriginalProductRecord;
+import org.jeecg.modules.billet.billetOriginalProductRecord.service.IBilletOriginalProductRecordService;
+import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.modules.billet.storageBill.entity.HeatsActualsInfo;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.ModelAndView;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+
+ /**
+ * @Description: 钢坯生成原始记录
+ * @Author: jeecg-boot
+ * @Date:   2025-06-23
+ * @Version: V1.0
+ */
+@Api(tags="钢坯生成原始记录")
+@RestController
+@RequestMapping("/billet/billetOriginalProductRecord")
+@Slf4j
+public class BilletOriginalProductRecordController extends JeecgController<BilletOriginalProductRecord, IBilletOriginalProductRecordService> {
+
+	@Autowired
+	private IBilletOriginalProductRecordService billetOriginalProductRecordService;
+
+	@Autowired
+	public RedisTemplate redisTemplate;
+
+	@Autowired
+	private IBilletHotsendChangeShiftService billetHotsendChangeShiftService;
+
+	 @Autowired
+	 private IBilletHotsendBaseService billetHotsendBaseService;
+
+	 @Autowired
+	 private IHeatsActualsService heatsActualsService;
+
+	 @Autowired
+	 private IBilletBasicInfoService billetBasicInfoService;
+
+	 /**
+	 * 分页列表查询
+	 *
+	 * @param billetOriginalProductRecord
+	 * @param pageNo
+	 * @param pageSize
+	 * @param req
+	 * @return
+	 */
+	//@AutoLog(value = "钢坯生成原始记录-分页列表查询")
+	@ApiOperation(value="钢坯生成原始记录-分页列表查询", notes="钢坯生成原始记录-分页列表查询")
+	@GetMapping(value = "/list")
+	public Result<IPage<BilletOriginalProductRecord>> queryPageList(BilletOriginalProductRecord billetOriginalProductRecord,
+								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
+								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
+								   HttpServletRequest req) {
+		QueryWrapper<BilletOriginalProductRecord> queryWrapper = QueryGenerator.initQueryWrapper(billetOriginalProductRecord, req.getParameterMap());
+		Page<BilletOriginalProductRecord> page = new Page<BilletOriginalProductRecord>(pageNo, pageSize);
+		IPage<BilletOriginalProductRecord> pageList = billetOriginalProductRecordService.page(page, queryWrapper);
+		return Result.OK(pageList);
+	}
+	
+	/**
+	 *   添加
+	 *
+	 * @param billetOriginalProductRecord
+	 * @return
+	 */
+	@AutoLog(value = "钢坯生成原始记录-添加")
+	@ApiOperation(value="钢坯生成原始记录-添加", notes="钢坯生成原始记录-添加")
+	@RequiresPermissions("billetOriginalProductRecord:billet_original_product_record:add")
+	@PostMapping(value = "/add")
+	public Result<String> add(@RequestBody BilletOriginalProductRecord billetOriginalProductRecord) {
+		billetOriginalProductRecordService.save(billetOriginalProductRecord);
+		return Result.OK("添加成功!");
+	}
+	
+	/**
+	 *  编辑
+	 *
+	 * @param billetOriginalProductRecord
+	 * @return
+	 */
+	@AutoLog(value = "钢坯生成原始记录-编辑")
+	@ApiOperation(value="钢坯生成原始记录-编辑", notes="钢坯生成原始记录-编辑")
+//	@RequiresPermissions("billetOriginalProductRecord:billet_original_product_record:edit")
+	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
+	public Result<String> edit(@RequestBody BilletOriginalProductRecord billetOriginalProductRecord) {
+		BilletOriginalProductRecord bopr = billetOriginalProductRecordService.getById(billetOriginalProductRecord.getId());
+		if(bopr == null) {
+			return Result.error("未找到对应数据,编辑失败!");
+		}
+		if (bopr.getAmount() != null && !bopr.getAmount().equals(billetOriginalProductRecord.getAmount())) {
+			Integer newTotal = billetOriginalProductRecord.getAmount();
+			// 确保新合计数非负
+			if (newTotal < 0) {
+				return Result.error("合计数量不能为负数,编辑失败!");
+			}
+			// 执行随机分配
+			Map<String, Integer> strandAllocation = allocateRandomly(newTotal, 8);
+			// 将分配结果设置到对象中
+			bopr.setOneStrandSum(strandAllocation.get("oneStrandSum"));
+			bopr.setTwoStrandSum(strandAllocation.get("twoStrandSum"));
+			bopr.setThreeStrandSum(strandAllocation.get("threeStrandSum"));
+			bopr.setFourStrandSum(strandAllocation.get("fourStrandSum"));
+			bopr.setFiveStrandSum(strandAllocation.get("fiveStrandSum"));
+			bopr.setSixStrandSum(strandAllocation.get("sixStrandSum"));
+			bopr.setSevenStrandSum(strandAllocation.get("sevenStrandSum"));
+			bopr.setEightStrandSum(strandAllocation.get("eightStrandSum"));
+			// 更新合计字段
+			bopr.setAmount(newTotal);
+			// 复制其他非空字段(忽略流支数和ID)
+			BeanUtils.copyProperties(billetOriginalProductRecord, bopr,
+					"id", "oneStrandSum", "twoStrandSum", "threeStrandSum",
+					"fourStrandSum", "fiveStrandSum", "sixStrandSum",
+					"sevenStrandSum", "eightStrandSum", "amount");
+			// 保存修改
+			billetOriginalProductRecordService.updateById(bopr);
+		}else {
+			billetOriginalProductRecordService.updateById(billetOriginalProductRecord);
+		}
+		return Result.OK("编辑成功!");
+	}
+	
+	/**
+	 *   通过id删除
+	 *
+	 * @param id
+	 * @return
+	 */
+	@AutoLog(value = "钢坯生成原始记录-通过id删除")
+	@ApiOperation(value="钢坯生成原始记录-通过id删除", notes="钢坯生成原始记录-通过id删除")
+	@RequiresPermissions("billetOriginalProductRecord:billet_original_product_record:delete")
+	@DeleteMapping(value = "/delete")
+	public Result<String> delete(@RequestParam(name="id",required=true) String id) {
+		billetOriginalProductRecordService.removeById(id);
+		return Result.OK("删除成功!");
+	}
+	
+	/**
+	 *  批量删除
+	 *
+	 * @param ids
+	 * @return
+	 */
+	@AutoLog(value = "钢坯生成原始记录-批量删除")
+	@ApiOperation(value="钢坯生成原始记录-批量删除", notes="钢坯生成原始记录-批量删除")
+	@RequiresPermissions("billetOriginalProductRecord:billet_original_product_record:deleteBatch")
+	@DeleteMapping(value = "/deleteBatch")
+	public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
+		this.billetOriginalProductRecordService.removeByIds(Arrays.asList(ids.split(",")));
+		return Result.OK("批量删除成功!");
+	}
+	
+	/**
+	 * 通过id查询
+	 *
+	 * @param id
+	 * @return
+	 */
+	//@AutoLog(value = "钢坯生成原始记录-通过id查询")
+	@ApiOperation(value="钢坯生成原始记录-通过id查询", notes="钢坯生成原始记录-通过id查询")
+	@GetMapping(value = "/queryById")
+	public Result<BilletOriginalProductRecord> queryById(@RequestParam(name="id",required=true) String id) {
+		BilletOriginalProductRecord billetOriginalProductRecord = billetOriginalProductRecordService.getById(id);
+		if(billetOriginalProductRecord==null) {
+			return Result.error("未找到对应数据");
+		}
+		return Result.OK(billetOriginalProductRecord);
+	}
+
+    /**
+    * 导出excel
+    *
+    * @param request
+    * @param billetOriginalProductRecord
+    */
+    @RequiresPermissions("billetOriginalProductRecord:billet_original_product_record:exportXls")
+    @RequestMapping(value = "/exportXls")
+    public ModelAndView exportXls(HttpServletRequest request, BilletOriginalProductRecord billetOriginalProductRecord) {
+        return super.exportXls(request, billetOriginalProductRecord, BilletOriginalProductRecord.class, "钢坯生成原始记录");
+    }
+
+    /**
+      * 通过excel导入数据
+    *
+    * @param request
+    * @param response
+    * @return
+    */
+    @RequiresPermissions("billetOriginalProductRecord:billet_original_product_record:importExcel")
+    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
+    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
+        return super.importExcel(request, response, BilletOriginalProductRecord.class);
+    }
+
+
+	 @ApiOperation(value="钢坯原始生产记录查询", notes="钢坯原始生产记录查询")
+	 @GetMapping(value = "/queryBilletRecordByCcmNo")
+	 public Result<List<BilletOriginalProductRecord>> queryHeatsActualsByCcmNo(@RequestParam(name="ccmNo", required = false) String ccmNo) {
+
+		 String classShiftGroup = String.format("class:shift:group:%s", ccmNo); // 班组
+		 String classShift = String.format("class:shift:%s",ccmNo); // 班别
+		 String shift = !oConvertUtils.getString(redisTemplate.opsForValue().get(classShift)).isEmpty() ? oConvertUtils.getString(redisTemplate.opsForValue().get(classShift)) : "";
+		 String shiftGroup = !oConvertUtils.getString(redisTemplate.opsForValue().get(classShiftGroup)).isEmpty() ? oConvertUtils.getString(redisTemplate.opsForValue().get(classShiftGroup)) : "";
+
+		 if (oConvertUtils.isEmpty(shiftGroup) || oConvertUtils.isEmpty(shift)){
+			 return Result.error("班组班别获取为空,钢坯原始生产记录查询失败!");
+		 }
+		 // 根据ccmNo、shift、shiftGroup查询最新的交班记录
+		 LambdaQueryWrapper<BilletHotsendChangeShift> queryWrapper = new LambdaQueryWrapper<>();
+		 queryWrapper.eq(BilletHotsendChangeShift::getCcmNo, ccmNo)
+				 .eq(BilletHotsendChangeShift::getShift, shift)
+				 .eq(BilletHotsendChangeShift::getShiftGroup, shiftGroup)
+				 .isNull(BilletHotsendChangeShift::getChangeShiftTime)
+				 .orderByDesc(BilletHotsendChangeShift::getCreateTime)
+				 .last("limit 1");
+		 BilletHotsendChangeShift billetHotsendChangeShift = billetHotsendChangeShiftService.getOne(queryWrapper);
+		 if (billetHotsendChangeShift == null){
+			 log.info("{}{}", "钢坯原始生产记录,交班记录为空!", ccmNo + "失败时间:" + new Date());
+			 return Result.error("交班信息为空,钢坯原始生产记录查询失败!");
+		 }
+		 //1、 获取当班浇筑炉次详细信息
+		 List<BilletOriginalProductRecord> billetOriginalProductRecords = new ArrayList<>();
+		 List<HeatsActualsInfo> heatsActualsInfoList = queryCurrentHeatsActualsInfo(ccmNo, shift, shiftGroup, billetHotsendChangeShift.getCreateTime());
+		 log.info("原始生产记录,当班浇筑炉次数据信息: " + JSON.toJSON(heatsActualsInfoList));
+		 if (oConvertUtils.listIsNotEmpty(heatsActualsInfoList)){
+			 //2、把获取到的当班浇筑炉次信息heatsActualsInfoList保存到原始生产记录表
+			 heatsActualsInfoList.forEach(x -> {
+				 BilletOriginalProductRecord billetOriginalProductRecord = new BilletOriginalProductRecord();
+				 billetOriginalProductRecord.setId(String.valueOf(IdWorker.getId()));
+				 billetOriginalProductRecord.setCcmNo(ccmNo);
+				 billetOriginalProductRecord.setHeatNo(x.getHeatNo());
+				 billetOriginalProductRecord.setShift(x.getShift());
+				 billetOriginalProductRecord.setShiftGroup(x.getShiftGroup());
+				 billetOriginalProductRecord.setGrade(x.getBrandNum());
+				 billetOriginalProductRecord.setOneStrandSum(x.getOneSum());
+				 billetOriginalProductRecord.setTwoStrandSum(x.getTwoSum());
+				 billetOriginalProductRecord.setThreeStrandSum(x.getThreeSum());
+				 billetOriginalProductRecord.setFourStrandSum(x.getFourSum());
+				 billetOriginalProductRecord.setFiveStrandSum(x.getFiveSum());
+				 billetOriginalProductRecord.setSixStrandSum(x.getSixSum());
+				 billetOriginalProductRecord.setSevenStrandSum(x.getSevenSum());
+				 billetOriginalProductRecord.setEightStrandSum(x.getEightSum());
+				 String totalInfoJson = x.getTotalInfo();
+				 if (oConvertUtils.isEmpty(totalInfoJson)){
+					 billetOriginalProductRecord.setAmount(0);// 合计
+				 }
+				 JSONObject json = JSON.parseObject(totalInfoJson);
+				 Integer totalCount = json.getInteger("totalCount");
+				 billetOriginalProductRecord.setAmount(totalCount);// 合计
+				 billetOriginalProductRecord.setRollClubOneDetails(x.getDirectRolling());// 直轧热送棒一
+				 billetOriginalProductRecord.setHotChargeLength(x.getHotCharge());
+				 billetOriginalProductRecord.setStackLength(x.getStacking());
+				 billetOriginalProductRecord.setLengthDetails(x.getLength());
+				 billetOriginalProductRecord.setCreateTime(DateUtils.str2Date(x.getCreateTime(), DateUtils.datetimeFormat.get()));
+				 billetOriginalProductRecords.add(billetOriginalProductRecord);
+			 });
+			 log.info("钢坯原始生产记录信息: " + JSON.toJSON(billetOriginalProductRecords));
+			 billetOriginalProductRecordService.saveBatch(billetOriginalProductRecords);
+		 }
+		 // 通过铸机号、班组、班别、交班开始时间 查询钢坯生产原始记录
+		 List<BilletOriginalProductRecord> billetOriginalProductRecordList = billetOriginalProductRecordService.list(new QueryWrapper<BilletOriginalProductRecord>()
+				 .eq("ccm_no", ccmNo)
+				 .eq("shift", shift)
+				 .eq("shift_group", shiftGroup)
+				 .between("create_time", billetHotsendChangeShift.getCreateTime(), new Date()));
+		 return Result.OK(billetOriginalProductRecordList);
+	 }
+
+	 /**
+	  * 获取当前班次下所有炉次浇筑数据
+	  * @param ccmNo
+	  * @param shift
+	  * @param shiftGroup
+	  * @return
+	  */
+	 private List<HeatsActualsInfo> queryCurrentHeatsActualsInfo(String ccmNo, String shift, String shiftGroup, Date createTime) {
+		 List<HeatsActualsInfo> heatsActualsInfoList = new ArrayList<>();
+		 //根据ccmNo、shift、shiftGroup、大于billetHotsendChangeShift的创建时间 查询所有炉次传递单BilletHotsend
+		 LambdaQueryWrapper<BilletHotsend> queryWrapper1 = new LambdaQueryWrapper<>();
+		 queryWrapper1.eq(BilletHotsend::getCcmNo, ccmNo)
+				 .eq(BilletHotsend::getShift, shift)
+				 .eq(BilletHotsend::getShiftGroup, shiftGroup)
+				 .between(BilletHotsend::getCreateTime, createTime, new Date())
+				 .orderByDesc(BilletHotsend::getCreateTime);
+		 List<BilletHotsend> billetHotsendList = billetHotsendBaseService.list(queryWrapper1);
+		 if (oConvertUtils.listIsEmpty(billetHotsendList)){
+			 log.info("{}{}", "钢坯原始生产记录,炉次传递单为空!", ccmNo + "失败时间:" + new Date());
+			 return heatsActualsInfoList;
+		 }
+		 List<String> distinctHeatNoList = billetHotsendList.stream()
+				 .map(BilletHotsend::getHeatNo)      // 提取炉号
+				 .filter(Objects::nonNull)           // 过滤可能的 null 值
+				 .distinct()                         // 去重
+				 .collect(Collectors.toList());      // 转为列表
+		 List<BilletHotsend> filteredBilletHotsendList = new ArrayList<>();
+		 // 根据铸机号、班别、班别、炉号查询钢坯原始生产记录
+		 QueryWrapper<BilletOriginalProductRecord> queryWrapper8 = new QueryWrapper<>();
+		 queryWrapper8.eq("ccm_no", ccmNo)
+				      .eq("shift", shift)
+		 			  .eq("shift_group", shiftGroup)
+		 			  .in("heat_no", distinctHeatNoList)
+				      .orderByDesc("create_time");
+		 List<BilletOriginalProductRecord> billetOriginalProductRecordList = billetOriginalProductRecordService.list(queryWrapper8);
+		 if (oConvertUtils.listIsNotEmpty(billetOriginalProductRecordList)){
+			 List<String> distinctOriginalProductRecordHeatNoList = billetOriginalProductRecordList.stream()
+					 .map(BilletOriginalProductRecord::getHeatNo)      // 提取炉号
+					 .filter(Objects::nonNull)           // 过滤可能的 null 值
+					 .distinct()                         // 去重
+					 .collect(Collectors.toList());      // 转为列表
+			 // 2. 将炉号列表转换为 Set 以提高查询效率
+			 Set<String> excludeHeatNos = new HashSet<>(distinctOriginalProductRecordHeatNoList);
+			 // 3. 过滤 billetHotsendList,保留炉号不在 excludeHeatNos 中的记录
+			 filteredBilletHotsendList = billetHotsendList.stream()
+					 .filter(item -> {
+						 String heatNo = item.getHeatNo();
+						 // 保留 heatNo 为空或不在 excludeHeatNos 中的记录
+						 return heatNo == null || !excludeHeatNos.contains(heatNo);
+					 }).collect(Collectors.toList());
+		 }else {
+			 filteredBilletHotsendList = billetHotsendList;
+		 }
+		 // 查询当班炉次浇筑时,增量查询
+		 filteredBilletHotsendList.forEach(x -> {
+			 HeatsActualsInfo heatsActualsInfo = new HeatsActualsInfo();
+			 heatsActualsInfo.setCreateTime(DateUtils.date2Str(x.getCreateTime(), DateUtils.datetimeFormat.get()));
+			 heatsActualsInfo.setShiftGroup(x.getShiftGroup());
+			 heatsActualsInfo.setShift(x.getShift());
+			 heatsActualsInfo.setHeatNo(x.getHeatNo());
+
+			 String brandNum = String.format("billet:basic:info:brand:num:%s", ccmNo); // 牌号
+			 String brandNumStr = !oConvertUtils.getString(redisTemplate.opsForValue().get(brandNum)).isEmpty() ? oConvertUtils.getString(redisTemplate.opsForValue().get(brandNum)) : "";
+
+			 heatsActualsInfo.setBrandNum(brandNumStr);
+			 // 根据铸机号、炉号查询钢坯实绩信息BilletBasicInfo
+			 LambdaQueryWrapper<BilletBasicInfo> queryWrapper2 = new LambdaQueryWrapper<>();
+			 queryWrapper2.eq(BilletBasicInfo::getCcmNo, x.getCcmNo())
+					 .eq(BilletBasicInfo::getHeatNo, x.getHeatNo())
+					 .eq(BilletBasicInfo::getShift, x.getShift())
+					 .eq(BilletBasicInfo::getShiftGroup, x.getShiftGroup());
+			 List<BilletBasicInfo> billetBasicInfoList = billetBasicInfoService.list(queryWrapper2);
+			 if (oConvertUtils.listIsEmpty(billetBasicInfoList)){
+				 log.info("{}{}", "钢坯原始生产记录,该炉对应的钢坯实绩不存在:", x.getHeatNo());
+				 return;
+			 }
+			 // 统计各流号的数量
+			 Map<Integer, Long> strandCountMap = billetBasicInfoList.stream()
+					 .filter(info -> info.getStrandNo() != null && info.getStrandNo() >= 1 && info.getStrandNo() <= 8)
+					 .collect(Collectors.groupingBy(BilletBasicInfo::getStrandNo, Collectors.counting()));
+
+			 // 获取StrandNo等于1的所有定尺length,并去重后用逗号连接
+			 heatsActualsInfo.setOneStrandNo(Math.toIntExact(strandCountMap.getOrDefault(1, 0L)));
+			 List<BilletBasicInfo> strandOneData = filterByStrandNo(billetBasicInfoList,1);
+			 heatsActualsInfo.setOneLength(JSON.toJSONString(groupByLength(strandOneData)));
+			 heatsActualsInfo.setOneSum(strandOneData.size());
+
+			 heatsActualsInfo.setTwoStrandNo(Math.toIntExact(strandCountMap.getOrDefault(2, 0L)));
+			 List<BilletBasicInfo> strandTwoData = filterByStrandNo(billetBasicInfoList,2);
+			 heatsActualsInfo.setTwoLength(JSON.toJSONString(groupByLength(strandTwoData)));
+			 heatsActualsInfo.setTwoSum(strandTwoData.size());
+
+			 heatsActualsInfo.setThreeStrandNo(Math.toIntExact(strandCountMap.getOrDefault(3, 0L)));
+			 List<BilletBasicInfo> strandThreeData = filterByStrandNo(billetBasicInfoList,3);
+			 heatsActualsInfo.setThreeLength(JSON.toJSONString(groupByLength(strandThreeData)));
+			 heatsActualsInfo.setThreeSum(strandThreeData.size());
+
+			 heatsActualsInfo.setFourStrandNo(Math.toIntExact(strandCountMap.getOrDefault(4, 0L)));
+			 List<BilletBasicInfo> strandFourData = filterByStrandNo(billetBasicInfoList,4);
+			 heatsActualsInfo.setFourLength(JSON.toJSONString(groupByLength(strandFourData)));
+			 heatsActualsInfo.setFourSum(strandFourData.size());
+
+			 heatsActualsInfo.setFiveStrandNo(Math.toIntExact(strandCountMap.getOrDefault(5, 0L)));
+			 List<BilletBasicInfo> strandFiveData = filterByStrandNo(billetBasicInfoList,5);
+			 heatsActualsInfo.setFiveLength(JSON.toJSONString(groupByLength(strandFiveData)));
+			 heatsActualsInfo.setFiveSum(strandFiveData.size());
+
+			 heatsActualsInfo.setSixStrandNo(Math.toIntExact(strandCountMap.getOrDefault(6, 0L)));
+			 List<BilletBasicInfo> strandSixData = filterByStrandNo(billetBasicInfoList,6);
+			 heatsActualsInfo.setSixLength(JSON.toJSONString(groupByLength(strandSixData)));
+			 heatsActualsInfo.setSixSum(strandSixData.size());
+
+			 heatsActualsInfo.setSevenStrandNo(Math.toIntExact(strandCountMap.getOrDefault(7, 0L)));
+			 List<BilletBasicInfo> strandSevenData = filterByStrandNo(billetBasicInfoList,7);
+			 heatsActualsInfo.setSevenLength(JSON.toJSONString(groupByLength(strandSevenData)));
+			 heatsActualsInfo.setSevenSum(strandSevenData.size());
+
+			 heatsActualsInfo.setEightStrandNo(Math.toIntExact(strandCountMap.getOrDefault(8, 0L)));
+			 List<BilletBasicInfo> strandEightData = filterByStrandNo(billetBasicInfoList,8);
+			 heatsActualsInfo.setEightLength(JSON.toJSONString(groupByLength(strandEightData)));
+			 heatsActualsInfo.setEightSum(strandEightData.size());
+
+			 // 直轧过滤并计算
+			 List<BilletBasicInfo> filterDirectRollingList = billetBasicInfoList.stream()
+					 .filter(info -> "roll_club_one".equals(info.getBelongTable()))
+					 .collect(Collectors.toList());
+			 if (oConvertUtils.listIsNotEmpty(filterDirectRollingList)){
+				 // 计算总重(保留4位小数)
+				 double totalWeight = filterDirectRollingList.stream()
+						 .mapToDouble(BilletBasicInfo::getBilletWeight)
+						 .sum();
+				 totalWeight = Math.round(totalWeight * 10000) / 10000.0;
+
+				 // 统计总数
+				 int totalCount = filterDirectRollingList.size();
+
+				 // 按定尺 length 分组统计每组数量(Long 类型)
+				 Map<Integer, Long> lengthCountMapRaw = filterDirectRollingList.stream()
+						 .filter(info -> info.getLength() != null)
+						 .collect(Collectors.groupingBy(BilletBasicInfo::getLength, Collectors.counting()));
+
+				 // 转换为 Map<String, Long>,确保 JSON key 是字符串
+				 Map<String, Long> lengthCountMap = lengthCountMapRaw.entrySet().stream()
+						 .collect(Collectors.toMap(
+								 e -> String.valueOf(e.getKey()), // key 转字符串
+								 Map.Entry::getValue
+						 ));
+
+				 // 转为JSON字符串
+				 Map<String, Object> directRollingMap = new HashMap<>();
+				 directRollingMap.put("directRollingTotalWeight", totalWeight);
+				 directRollingMap.put("directRollingTotalCount", totalCount);
+				 directRollingMap.put("lengthGroupCount", lengthCountMap); // 定尺统计结果
+				 String jsonResult = JSON.toJSONString(directRollingMap); // 使用FastJSON转换.
+				 heatsActualsInfo.setDirectRolling(jsonResult);
+			 }
+
+			 // 堆垛过滤并计算
+			 List<BilletBasicInfo> filterStackList = billetBasicInfoList.stream()
+					 .filter(info -> "stacking_and_loading_vehicles".equals(info.getBelongTable()))
+					 .collect(Collectors.toList());
+			 if (oConvertUtils.listIsNotEmpty(filterStackList)){
+				 // 计算总重(保留4位小数)
+				 double totalWeight = filterStackList.stream()
+						 .mapToDouble(BilletBasicInfo::getBilletWeight)
+						 .sum();
+				 totalWeight = Math.round(totalWeight * 10000) / 10000.0;
+
+				 // 统计总数
+				 int totalCount = filterStackList.size();
+
+				 // 转为JSON字符串
+				 Map<String, Object> stackingMap = new HashMap<>();
+				 stackingMap.put("stackingTotalWeight", totalWeight);
+				 stackingMap.put("stackingTotalCount", totalCount);
+				 String jsonResult = JSON.toJSONString(stackingMap); // 使用FastJSON转换.
+				 heatsActualsInfo.setStacking(jsonResult);
+			 }
+
+			 // 定义需要筛选的belongTable列表
+			 List<String> targetTables = Arrays.asList("roll_club_two", "roll_club_three");
+
+			 // 热装过滤并计算
+			 List<BilletBasicInfo> filterHotChargeList = billetBasicInfoList.stream()
+					 .filter(info -> targetTables.contains(info.getBelongTable()))
+					 .collect(Collectors.toList());
+			 if (oConvertUtils.listIsNotEmpty(filterHotChargeList)){
+				 // 计算总重(保留4位小数)
+				 double totalWeight = filterHotChargeList.stream()
+						 .mapToDouble(BilletBasicInfo::getBilletWeight)
+						 .sum();
+				 totalWeight = Math.round(totalWeight * 10000) / 10000.0;
+
+				 // 统计总数
+				 int totalCount = filterHotChargeList.size();
+
+				 // 转为JSON字符串
+				 Map<String, Object> hotChargeMap = new HashMap<>();
+				 hotChargeMap.put("hotChargeTotalWeight", totalWeight);
+				 hotChargeMap.put("hotChargeTotalCount", totalCount);
+				 String jsonResult = JSON.toJSONString(hotChargeMap); // 使用FastJSON转换
+				 heatsActualsInfo.setHotCharge(jsonResult);
+			 }
+
+			 // 按length字段分组,并统计每组的总数和总重
+			 Map<Integer, Map<String, Object>> lengthResultMap = billetBasicInfoList.stream()
+					 .filter(info -> info.getLength() != null) // 过滤掉length为null的记录
+					 .collect(Collectors.groupingBy(
+							 BilletBasicInfo::getLength, // 按length分组
+							 Collectors.collectingAndThen(
+									 Collectors.toList(),
+									 list -> {
+										 // 计算每组的总重(保留4位小数)
+										 double totalWeight = list.stream()
+												 .mapToDouble(BilletBasicInfo::getBilletWeight)
+												 .sum();
+										 totalWeight = Math.round(totalWeight * 10000) / 10000.0;
+										 // 统计每组的总数
+										 int totalCount = list.size();
+										 // 创建每组的结果Map
+										 Map<String, Object> groupResult = new HashMap<>();
+										 groupResult.put("lengthTotalWeight", totalWeight);
+										 groupResult.put("lengthTotalCount", totalCount);
+										 //棒一统计
+										 long rollClubOneCount = list.stream()
+												 .filter(billet -> "roll_club_one".equals(billet.getBelongTable()))
+												 .count();
+										 groupResult.put("rollClubOneCount", (int) rollClubOneCount);
+										 // 棒二统计
+										 long rollClubTwoCount = list.stream()
+												 .filter(billet -> "roll_club_two".equals(billet.getBelongTable()))
+												 .count();
+										 groupResult.put("rollClubTwoCount", (int) rollClubTwoCount);
+										 // 棒三统计
+										 long rollClubThreeCount = list.stream()
+												 .filter(billet -> "roll_club_three".equals(billet.getBelongTable()))
+												 .count();
+										 groupResult.put("rollClubThreeCount", (int) rollClubThreeCount);
+										 // 堆垛统计
+										 long stackingAndLoadingVehiclesCount = list.stream()
+												 .filter(billet -> "stacking_and_loading_vehicles".equals(billet.getBelongTable()))
+												 .count();
+										 groupResult.put("stackingAndLoadingVehiclesCount", (int) stackingAndLoadingVehiclesCount);
+										 return groupResult;
+									 }
+							 )
+					 ));
+			 // 将Integer键转换为String键
+			 Map<String, Map<String, Object>> stringKeyMap = lengthResultMap.entrySet().stream()
+					 .collect(Collectors.toMap(
+							 e -> String.valueOf(e.getKey()),
+							 Map.Entry::getValue
+					 ));
+
+			 // 转换为JSON字符串
+			 String jsonResult = JSON.toJSONString(stringKeyMap);
+			 heatsActualsInfo.setLength(jsonResult);
+
+			 // 统计总数
+			 long totalCount = billetBasicInfoList.size();
+
+			 // 计算总重(保留4位小数)
+			 double totalWeight = billetBasicInfoList.stream()
+					 .mapToDouble(BilletBasicInfo::getBilletWeight)
+					 .sum();
+			 totalWeight = Math.round(totalWeight * 10000) / 10000.0;
+
+			 // 转为JSON字符串
+			 Map<String, Object> resultMap = new HashMap<>();
+			 resultMap.put("totalCount", totalCount);
+			 resultMap.put("totalWeight", totalWeight);
+			 String sumJsonResult = JSON.toJSONString(resultMap); // 使用FastJSON转换
+			 heatsActualsInfo.setTotalInfo(sumJsonResult);
+
+			 heatsActualsInfoList.add(heatsActualsInfo);
+		 });
+		 return heatsActualsInfoList;
+	 }
+
+	 /**
+	  * 筛选指定流号的数据
+	  * @param billetList 钢坯信息列表
+	  * @param strandNo 流号
+	  * @return 指定流号的钢坯信息列表
+	  */
+	 private List<BilletBasicInfo> filterByStrandNo(List<BilletBasicInfo> billetList, Integer strandNo) {
+		 if (CollectionUtils.isEmpty(billetList) || strandNo == null) {
+			 return Collections.emptyList();
+		 }
+
+		 return billetList.stream()
+				 .filter(info -> info.getStrandNo() != null && info.getStrandNo().equals(strandNo))
+				 .collect(Collectors.toList());
+	 }
+
+	 /**
+	  * 按定尺长度分组并统计数量
+	  * @param billetList 钢坯信息列表
+	  * @return 定尺长度到数量的映射
+	  */
+	 private Map<String, Long> groupByLength(List<BilletBasicInfo> billetList) {
+		 if (CollectionUtils.isEmpty(billetList)) {
+			 return Collections.emptyMap();
+		 }
+
+		 return billetList.stream()
+				 .filter(info -> info.getLength() != null)
+				 .collect(Collectors.groupingBy(
+						 info -> String.valueOf(info.getLength()),
+						 Collectors.counting()
+				 ));
+	 }
+
+
+	 /**
+	  * 将总数随机分配到指定数量的流中,允许流的数量为0
+	  * @param total 总数
+	  * @param numStrands 流的数量
+	  * @return 分配结果映射(键为流的名称,值为分配的数量)
+	  */
+	 private Map<String, Integer> allocateRandomly(int total, int numStrands) {
+		 // 初始化每个流分配0个
+		 List<Integer> allocation = new ArrayList<>(Collections.nCopies(numStrands, 0));
+
+		 // 随机分配所有数量
+		 Random random = ThreadLocalRandom.current();
+		 for (int i = 0; i < total; i++) {
+			 // 随机选择一个流增加数量
+			 int index = random.nextInt(numStrands);
+			 allocation.set(index, allocation.get(index) + 1);
+		 }
+
+		 // 构建结果映射
+		 Map<String, Integer> result = new HashMap<>();
+		 result.put("oneStrandSum", allocation.get(0));
+		 result.put("twoStrandSum", allocation.get(1));
+		 result.put("threeStrandSum", allocation.get(2));
+		 result.put("fourStrandSum", allocation.get(3));
+		 result.put("fiveStrandSum", allocation.get(4));
+		 result.put("sixStrandSum", allocation.get(5));
+		 result.put("sevenStrandSum", allocation.get(6));
+		 result.put("eightStrandSum", allocation.get(7));
+
+		 return result;
+	 }
+ }

+ 148 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetOriginalProductRecord/entity/BilletOriginalProductRecord.java

@@ -0,0 +1,148 @@
+package org.jeecg.modules.billet.billetOriginalProductRecord.entity;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import lombok.Data;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.jeecg.common.aspect.annotation.Dict;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * @Description: 钢坯生成原始记录
+ * @Author: jeecg-boot
+ * @Date:   2025-06-23
+ * @Version: V1.0
+ */
+@Data
+@TableName("billet_original_product_record")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="billet_original_product_record对象", description="钢坯生成原始记录")
+public class BilletOriginalProductRecord implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	/**ID*/
+	@TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "ID")
+    private String id;
+	/**创建人*/
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+	/**创建时间*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+	/**更新人*/
+    @ApiModelProperty(value = "更新人")
+    private String updateBy;
+	/**更新时间*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "更新时间")
+    private Date updateTime;
+	/**所属部门*/
+    @ApiModelProperty(value = "所属部门")
+    private String sysOrgCode;
+	/**铸机号*/
+	@Excel(name = "铸机号", width = 15)
+    @ApiModelProperty(value = "铸机号")
+    private String ccmNo;
+	/**炉号*/
+	@Excel(name = "炉号", width = 15)
+    @ApiModelProperty(value = "炉号")
+    private String heatNo;
+	/**班别*/
+	@Excel(name = "班别", width = 15)
+    @Dict(dicCode = "lg_bb")
+    @ApiModelProperty(value = "班别")
+    private String shift;
+	/**班组*/
+	@Excel(name = "班组", width = 15)
+    @Dict(dicCode = "lg_bz")
+    @ApiModelProperty(value = "班组")
+    private String shiftGroup;
+	/**钢种*/
+	@Excel(name = "钢种", width = 15)
+    @ApiModelProperty(value = "钢种")
+    private String grade;
+	/**定尺*/
+	@Excel(name = "定尺", width = 15)
+    @ApiModelProperty(value = "定尺")
+    private Integer length;
+    /**定尺*/
+    @Excel(name = "合计", width = 15)
+    @ApiModelProperty(value = "合计")
+    private Integer amount;
+	/**棒一定尺明细*/
+	@Excel(name = "棒一定尺明细", width = 15)
+    @ApiModelProperty(value = "棒一定尺明细")
+    private String rollClubOneDetails;
+	/**棒二定尺明细*/
+	@Excel(name = "棒二定尺明细", width = 15)
+    @ApiModelProperty(value = "棒二定尺明细")
+    private String rollClubTwoDetails;
+	/**棒三定尺明细*/
+	@Excel(name = "棒三定尺明细", width = 15)
+    @ApiModelProperty(value = "棒三定尺明细")
+    private String rollClubThreeDetails;
+    /**所有定尺明细*/
+    @Excel(name = "所有定尺明细", width = 15)
+    @ApiModelProperty(value = "所有定尺明细")
+    private String lengthDetails;
+	/**1流支数*/
+	@Excel(name = "1流支数", width = 15)
+    @ApiModelProperty(value = "1流支数")
+    private Integer oneStrandSum;
+	/**2流支数*/
+	@Excel(name = "2流支数", width = 15)
+    @ApiModelProperty(value = "2流支数")
+    private Integer twoStrandSum;
+	/**3流支数*/
+	@Excel(name = "3流支数", width = 15)
+    @ApiModelProperty(value = "3流支数")
+    private Integer threeStrandSum;
+	/**4流支数*/
+	@Excel(name = "4流支数", width = 15)
+    @ApiModelProperty(value = "4流支数")
+    private Integer fourStrandSum;
+	/**5流支数*/
+	@Excel(name = "5流支数", width = 15)
+    @ApiModelProperty(value = "5流支数")
+    private Integer fiveStrandSum;
+	/**6流支数*/
+	@Excel(name = "6流支数", width = 15)
+    @ApiModelProperty(value = "6流支数")
+    private Integer sixStrandSum;
+	/**7流支数*/
+	@Excel(name = "7流支数", width = 15)
+    @ApiModelProperty(value = "7流支数")
+    private Integer sevenStrandSum;
+	/**8流支数*/
+	@Excel(name = "8流支数", width = 15)
+    @ApiModelProperty(value = "8流支数")
+    private Integer eightStrandSum;
+	/**热送定尺*/
+	@Excel(name = "热装定尺", width = 15)
+    @ApiModelProperty(value = "热装定尺")
+    private String hotChargeLength;
+	/**堆垛定尺*/
+	@Excel(name = "堆垛定尺", width = 15)
+    @ApiModelProperty(value = "堆垛定尺")
+    private String stackLength;
+	/**备注*/
+	@Excel(name = "备注", width = 15)
+    @ApiModelProperty(value = "备注")
+    private String remark;
+}

+ 17 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetOriginalProductRecord/mapper/BilletOriginalProductRecordMapper.java

@@ -0,0 +1,17 @@
+package org.jeecg.modules.billet.billetOriginalProductRecord.mapper;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Param;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.billet.billetOriginalProductRecord.entity.BilletOriginalProductRecord;
+
+/**
+ * @Description: 钢坯生成原始记录
+ * @Author: jeecg-boot
+ * @Date:   2025-06-23
+ * @Version: V1.0
+ */
+public interface BilletOriginalProductRecordMapper extends BaseMapper<BilletOriginalProductRecord> {
+
+}

+ 5 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetOriginalProductRecord/mapper/xml/BilletOriginalProductRecordMapper.xml

@@ -0,0 +1,5 @@
+<?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.billet.billetOriginalProductRecord.mapper.BilletOriginalProductRecordMapper">
+
+</mapper>

+ 15 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetOriginalProductRecord/service/IBilletOriginalProductRecordService.java

@@ -0,0 +1,15 @@
+package org.jeecg.modules.billet.billetOriginalProductRecord.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.billet.billetOriginalProductRecord.entity.BilletOriginalProductRecord;
+
+/**
+ * @Description: 钢坯生成原始记录
+ * @Author: jeecg-boot
+ * @Date:   2025-06-23
+ * @Version: V1.0
+ */
+public interface IBilletOriginalProductRecordService extends IService<BilletOriginalProductRecord> {
+
+}

+ 19 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetOriginalProductRecord/service/impl/BilletOriginalProductRecordServiceImpl.java

@@ -0,0 +1,19 @@
+package org.jeecg.modules.billet.billetOriginalProductRecord.service.impl;
+
+import org.jeecg.modules.billet.billetOriginalProductRecord.entity.BilletOriginalProductRecord;
+import org.jeecg.modules.billet.billetOriginalProductRecord.mapper.BilletOriginalProductRecordMapper;
+import org.jeecg.modules.billet.billetOriginalProductRecord.service.IBilletOriginalProductRecordService;
+import org.springframework.stereotype.Service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+/**
+ * @Description: 钢坯生成原始记录
+ * @Author: jeecg-boot
+ * @Date:   2025-06-23
+ * @Version: V1.0
+ */
+@Service
+public class BilletOriginalProductRecordServiceImpl extends ServiceImpl<BilletOriginalProductRecordMapper, BilletOriginalProductRecord> implements IBilletOriginalProductRecordService {
+
+}

+ 8 - 3
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/storageBill/entity/HeatsActualsInfo.java

@@ -1,8 +1,5 @@
 package org.jeecg.modules.billet.storageBill.entity;
-import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import org.jeecg.common.aspect.annotation.Dict;
-import org.jeecgframework.poi.excel.annotation.Excel;
 
 @Data
 public class HeatsActualsInfo {
@@ -12,20 +9,28 @@ public class HeatsActualsInfo {
 
     private Integer oneStrandNo;
     private String oneLength;
+    private Integer oneSum;
     private Integer twoStrandNo;
     private String twoLength;
+    private Integer twoSum;
     private Integer threeStrandNo;
     private String threeLength;
+    private Integer threeSum;
     private Integer fourStrandNo;
     private String fourLength;
+    private Integer fourSum;
     private Integer fiveStrandNo;
     private String fiveLength;
+    private Integer fiveSum;
     private Integer sixStrandNo;
     private String sixLength;
+    private Integer sixSum;
     private Integer sevenStrandNo;
     private String sevenLength;
+    private Integer sevenSum;
     private Integer eightStrandNo;
     private String eightLength;
+    private Integer eightSum;
 
     private String directRolling;