Browse Source

新增高线工作台以及高线工作台导出

lingpeng.li 2 weeks ago
parent
commit
2f90b12b23

+ 182 - 126
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollHeight/controller/RollHeightController.java

@@ -1,5 +1,6 @@
 package org.jeecg.modules.billet.rollHeight.controller;
 
+import com.alibaba.excel.EasyExcel;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -10,148 +11,203 @@ import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.aspect.annotation.AutoLog;
 import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.modules.billet.operateLog.service.IOperateLogService;
+import org.jeecg.modules.billet.rollHeight.dto.RollHeightQueryDTO;
 import org.jeecg.modules.billet.rollHeight.entity.DestinationStatistics;
 import org.jeecg.modules.billet.rollHeight.entity.RollHeight;
 import org.jeecg.modules.billet.rollHeight.service.IRollHeightService;
+import org.jeecg.modules.billet.rollHeight.vo.RollHeightVO;
+import org.jeecg.modules.billet.storageBill.vo.StorageCenterExportRow;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
 
- /**
+/**
  * @Description: 轧钢高线
  * @Author: jeecg-boot
- * @Date:   2024-05-06
+ * @Date: 2024-05-06
  * @Version: V1.0
  */
-@Api(tags="轧钢高线")
+@Api(tags = "轧钢高线")
 @RestController
 @RequestMapping("/rollHeight")
 @Slf4j
 public class RollHeightController {
 
-	@Autowired
-	private IRollHeightService rollHeightService;
-	 @Autowired
-	 private IOperateLogService operateLogService;
-	
-	/**
-	 * 分页列表查询
-	 *
-	 * @param rollHeight
-	 * @param pageNo
-	 * @param pageSize
-	 * @param req
-	 * @return
-	 */
-	@AutoLog(value = "轧钢高线-分页列表查询")
-	@ApiOperation(value="轧钢高线-分页列表查询", notes="轧钢高线-分页列表查询")
-	@GetMapping(value = "/list")
-	public Result<?> queryPageList(RollHeight rollHeight,
-								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
-								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
-								   HttpServletRequest req) {
-		QueryWrapper<RollHeight> queryWrapper = QueryGenerator.initQueryWrapper(rollHeight, req.getParameterMap());
-		Page<RollHeight> page = new Page<RollHeight>(pageNo, pageSize);
-		IPage<RollHeight> pageList = rollHeightService.page(page, queryWrapper);
-		return Result.OK(pageList);
-	}
-	
-	/**
-	 *   添加
-	 *
-	 * @param rollHeightPage
-	 * @return
-	 */
-	@AutoLog(value = "轧钢高线-添加")
-	@ApiOperation(value="轧钢高线-添加", notes="轧钢高线-添加")
-	@PostMapping(value = "/add")
-	public Result<?> add(@RequestBody RollHeight rollHeightPage) {
-		RollHeight rollHeight = new RollHeight();
-		rollHeightService.save(rollHeight);
-		operateLogService.add(rollHeight,null,RollHeight.class);
-		return Result.OK("添加成功!");
-	}
-
-	 /**
-	  *  编辑
-	  *
-	  * @return
-	  */
-	 @AutoLog(value = "轧钢高线详情-编辑")
-	 @ApiOperation(value="轧钢高线详情-编辑", notes="轧钢高线详情-编辑")
-	 @PutMapping(value = "/editDesc")
-	 public Result<?> editDesc(@RequestBody RollHeight rollHeight) {
-		 operateLogService.add(rollHeightService.getById(rollHeight.getId()),rollHeight, RollHeight.class);
-		 rollHeightService.updateById(rollHeight);
-		 return Result.OK("编辑成功!");
-	 }
-	
-	/**
-	 *   通过id删除
-	 *
-	 * @param id
-	 * @return
-	 */
-	@AutoLog(value = "轧钢高线-通过id删除")
-	@ApiOperation(value="轧钢高线-通过id删除", notes="轧钢高线-通过id删除")
-	@DeleteMapping(value = "/delete")
-	public Result<?> delete(@RequestParam(name="id",required=true) String id) {
-		rollHeightService.removeById(id);
-		return Result.OK("删除成功!");
-	}
-	
-	/**
-	 *  批量删除
-	 *
-	 * @param ids
-	 * @return
-	 */
-	@AutoLog(value = "轧钢高线-批量删除")
-	@ApiOperation(value="轧钢高线-批量删除", notes="轧钢高线-批量删除")
-	@DeleteMapping(value = "/deleteBatch")
-	public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
-		this.rollHeightService.removeBatchByIds(Arrays.asList(ids.split(",")));
-		return Result.OK("批量删除成功!");
-	}
-	
-	/**
-	 * 通过id查询
-	 *
-	 * @param id
-	 * @return
-	 */
-	@AutoLog(value = "轧钢高线-通过id查询")
-	@ApiOperation(value="轧钢高线-通过id查询", notes="轧钢高线-通过id查询")
-	@GetMapping(value = "/queryById")
-	public Result<?> queryById(@RequestParam(name="id",required=true) String id) {
-		RollHeight rollHeight = rollHeightService.getById(id);
-		if(rollHeight==null) {
-			return Result.error("未找到对应数据");
-		}
-		return Result.OK(rollHeight);
-
-	}
-
-	 @ApiOperation(value="高线统计-通过铸机号查询", notes="高线统计-通过铸机号查询")
-	 @GetMapping(value = "/queryRollHeightByCcmNo")
-	 public Result<DestinationStatistics> queryByCcmNo(@RequestParam(name="ccmNo", required = false) String ccmNo) {
-		 DestinationStatistics destinationStatistics = rollHeightService.queryByCcmNoHandle(ccmNo);
-		 if(destinationStatistics == null) {
-			 return Result.ok("未找到对应数据");
-		 }
-		 return Result.OK(destinationStatistics);
-	 }
-
-	 @ApiOperation(value="当班高线统计-通过铸机号班组班别查询", notes="当班高线统计-通过铸机号班组班别查询")
-	 @GetMapping(value = "/queryOnDutyRollHeightByCcmNo")
-	 public Result<DestinationStatistics> queryOnDutyRollHeightByCcmNo(@RequestParam(name="ccmNo") String ccmNo,
-																	   @RequestParam(name="changeShiftId", required = false) String changeShiftId) {
-		 DestinationStatistics destinationStatistics = rollHeightService.queryOnDutyRollHeightByCcmNo(ccmNo, changeShiftId);
-		 if(destinationStatistics == null) {
-			 return Result.ok("未找到当班对应数据");
-		 }
-		 return Result.OK(destinationStatistics);
-	 }
+    @Autowired
+    private IRollHeightService rollHeightService;
+    @Autowired
+    private IOperateLogService operateLogService;
+
+    /**
+     * 分页列表查询
+     *
+     * @param rollHeight
+     * @param pageNo
+     * @param pageSize
+     * @param req
+     * @return
+     */
+    @AutoLog(value = "轧钢高线-分页列表查询")
+    @ApiOperation(value = "轧钢高线-分页列表查询", notes = "轧钢高线-分页列表查询")
+    @GetMapping(value = "/list")
+    public Result<?> queryPageList(RollHeight rollHeight,
+                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
+                                   HttpServletRequest req) {
+        QueryWrapper<RollHeight> queryWrapper = QueryGenerator.initQueryWrapper(rollHeight, req.getParameterMap());
+        Page<RollHeight> page = new Page<RollHeight>(pageNo, pageSize);
+        IPage<RollHeight> pageList = rollHeightService.page(page, queryWrapper);
+        return Result.OK(pageList);
+    }
+
+    /**
+     * 添加
+     *
+     * @param rollHeightPage
+     * @return
+     */
+    @AutoLog(value = "轧钢高线-添加")
+    @ApiOperation(value = "轧钢高线-添加", notes = "轧钢高线-添加")
+    @PostMapping(value = "/add")
+    public Result<?> add(@RequestBody RollHeight rollHeightPage) {
+        RollHeight rollHeight = new RollHeight();
+        rollHeightService.save(rollHeight);
+        operateLogService.add(rollHeight, null, RollHeight.class);
+        return Result.OK("添加成功!");
+    }
+
+    /**
+     * 编辑
+     *
+     * @return
+     */
+    @AutoLog(value = "轧钢高线详情-编辑")
+    @ApiOperation(value = "轧钢高线详情-编辑", notes = "轧钢高线详情-编辑")
+    @PutMapping(value = "/editDesc")
+    public Result<?> editDesc(@RequestBody RollHeight rollHeight) {
+        operateLogService.add(rollHeightService.getById(rollHeight.getId()), rollHeight, RollHeight.class);
+        rollHeightService.updateById(rollHeight);
+        return Result.OK("编辑成功!");
+    }
+
+    /**
+     * 通过id删除
+     *
+     * @param id
+     * @return
+     */
+    @AutoLog(value = "轧钢高线-通过id删除")
+    @ApiOperation(value = "轧钢高线-通过id删除", notes = "轧钢高线-通过id删除")
+    @DeleteMapping(value = "/delete")
+    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
+        rollHeightService.removeById(id);
+        return Result.OK("删除成功!");
+    }
+
+    /**
+     * 批量删除
+     *
+     * @param ids
+     * @return
+     */
+    @AutoLog(value = "轧钢高线-批量删除")
+    @ApiOperation(value = "轧钢高线-批量删除", notes = "轧钢高线-批量删除")
+    @DeleteMapping(value = "/deleteBatch")
+    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
+        this.rollHeightService.removeBatchByIds(Arrays.asList(ids.split(",")));
+        return Result.OK("批量删除成功!");
+    }
+
+    /**
+     * 通过id查询
+     *
+     * @param id
+     * @return
+     */
+    @AutoLog(value = "轧钢高线-通过id查询")
+    @ApiOperation(value = "轧钢高线-通过id查询", notes = "轧钢高线-通过id查询")
+    @GetMapping(value = "/queryById")
+    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
+        RollHeight rollHeight = rollHeightService.getById(id);
+        if (rollHeight == null) {
+            return Result.error("未找到对应数据");
+        }
+        return Result.OK(rollHeight);
+
+    }
+
+    @ApiOperation(value = "高线统计-通过铸机号查询", notes = "高线统计-通过铸机号查询")
+    @GetMapping(value = "/queryRollHeightByCcmNo")
+    public Result<DestinationStatistics> queryByCcmNo(@RequestParam(name = "ccmNo", required = false) String ccmNo) {
+        DestinationStatistics destinationStatistics = rollHeightService.queryByCcmNoHandle(ccmNo);
+        if (destinationStatistics == null) {
+            return Result.ok("未找到对应数据");
+        }
+        return Result.OK(destinationStatistics);
+    }
+
+    @ApiOperation(value = "当班高线统计-通过铸机号班组班别查询", notes = "当班高线统计-通过铸机号班组班别查询")
+    @GetMapping(value = "/queryOnDutyRollHeightByCcmNo")
+    public Result<DestinationStatistics> queryOnDutyRollHeightByCcmNo(@RequestParam(name = "ccmNo") String ccmNo,
+                                                                      @RequestParam(name = "changeShiftId", required = false) String changeShiftId) {
+        DestinationStatistics destinationStatistics = rollHeightService.queryOnDutyRollHeightByCcmNo(ccmNo, changeShiftId);
+        if (destinationStatistics == null) {
+            return Result.ok("未找到当班对应数据");
+        }
+        return Result.OK(destinationStatistics);
+    }
+
+    @ApiOperation(value = "高线工作台数据展示", notes = "高线工作台数据展示")
+    @GetMapping(value = "/rollHeightList")
+    public Result<IPage<RollHeightVO>> rollHeightList(RollHeightQueryDTO queryDTO) {
+
+        List<RollHeightVO> rollHeightVOS = rollHeightService.rollHeightList(queryDTO);
+
+        // 手动分页
+        int pageNo = queryDTO.getPageNo() != null ? queryDTO.getPageNo() : 1;
+        int pageSize = queryDTO.getPageSize() != null ? queryDTO.getPageSize() : 20;
+        int total = rollHeightVOS.size();
+        int fromIndex = (pageNo - 1) * pageSize;
+        int toIndex = Math.min(fromIndex + pageSize, total);
+
+        List<RollHeightVO> pageList = fromIndex >= total ? Collections.emptyList() : rollHeightVOS.subList(fromIndex, toIndex);
+
+        IPage<RollHeightVO> page = new Page<>(pageNo, pageSize, total);
+        page.setRecords(pageList);
+
+        return Result.OK(page);
+    }
+
+    @ApiOperation(value = "高线工作台导出", notes = "高线工作台导出")
+    @GetMapping("/exportHeightXls")
+    public void exportHeightXls(HttpServletResponse response, RollHeightQueryDTO queryDTO) throws IOException {
+
+        List<RollHeightVO> rollHeightVOS = rollHeightService.rollHeightList(queryDTO);
+
+        // 数据处理
+        List<StorageCenterExportRow> exportList = rollHeightService.buildExportData(rollHeightVOS);
+
+        // 按出厂日期倒序排序
+        exportList.sort(Comparator.comparing(StorageCenterExportRow::getFactoryDate, Comparator.nullsLast(Comparator.reverseOrder())));
+
+        // 设置响应
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        String fileName = URLEncoder.encode("高线工作台装运打印信息", String.valueOf(StandardCharsets.UTF_8)).replaceAll("\\+", "%20");
+        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
+
+        // 导出
+        EasyExcel.write(response.getOutputStream(), StorageCenterExportRow.class)
+                .sheet("装运打印信息")
+                .doWrite(exportList);
+    }
 }

+ 68 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollHeight/dto/RollHeightQueryDTO.java

@@ -0,0 +1,68 @@
+package org.jeecg.modules.billet.rollHeight.dto;
+
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+@Data
+public class RollHeightQueryDTO {
+
+    /**
+     * 铸机号
+     */
+    private String ccmNo;
+
+    private String heatsCode;
+
+    private String heatNo;
+
+    /**
+     * 当前日期
+     */
+    private String currentDate;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date storageTimeBegin;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date storageTimeEnd;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date startTime;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date endTime;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date queryDate;
+
+    /**
+     * 班组
+     */
+    private String shiftGroup;
+
+    /**
+     * 定尺
+     */
+    private String size;
+    /**
+     * 牌号
+     */
+    private String brandNum;
+
+    /**
+     * 班别
+     */
+    private String shift;
+
+    /**
+     * 交班记录id
+     */
+    private String changeShiftId;
+
+    private Integer pageNo;
+
+    private Integer pageSize;
+
+}

+ 10 - 1
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollHeight/service/IRollHeightService.java

@@ -1,13 +1,18 @@
 package org.jeecg.modules.billet.rollHeight.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.billet.rollHeight.dto.RollHeightQueryDTO;
 import org.jeecg.modules.billet.rollHeight.entity.DestinationStatistics;
 import org.jeecg.modules.billet.rollHeight.entity.RollHeight;
+import org.jeecg.modules.billet.rollHeight.vo.RollHeightVO;
+import org.jeecg.modules.billet.storageBill.vo.StorageCenterExportRow;
+
+import java.util.List;
 
 /**
  * @Description: 轧钢高线
  * @Author: jeecg-boot
- * @Date:   2024-05-06
+ * @Date: 2024-05-06
  * @Version: V1.0
  */
 public interface IRollHeightService extends IService<RollHeight> {
@@ -15,4 +20,8 @@ public interface IRollHeightService extends IService<RollHeight> {
     DestinationStatistics queryByCcmNoHandle(String ccmNo);
 
     DestinationStatistics queryOnDutyRollHeightByCcmNo(String ccmNo, String changeShiftId);
+
+    List<RollHeightVO> rollHeightList(RollHeightQueryDTO queryDTO);
+
+    List<StorageCenterExportRow> buildExportData(List<RollHeightVO> records);
 }

+ 415 - 5
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollHeight/service/impl/RollHeightServiceImpl.java

@@ -2,10 +2,24 @@ package org.jeecg.modules.billet.rollHeight.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.jeecg.common.util.DateUtils;
 import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletRulerConfig;
+import org.jeecg.modules.actualControl.billetActual.billetActual.mapper.BilletRulerConfigMapper;
+import org.jeecg.modules.billet.billetHotsend.entity.BilletHotsend;
+import org.jeecg.modules.billet.billetHotsend.mapper.BilletHotsendBaseMapper;
 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.modules.billet.rollClubOne.vo.RollClubOneHeatVO;
+import org.jeecg.modules.billet.rollClubOne.vo.RollClubOneVO;
+import org.jeecg.modules.billet.rollHeight.dto.RollHeightQueryDTO;
 import org.jeecg.modules.billet.rollHeight.entity.DestinationStatistics;
 import org.jeecg.modules.billet.rollHeight.entity.DestinationStatisticsDetails;
 import org.jeecg.modules.billet.rollHeight.entity.RollHeight;
@@ -13,20 +27,23 @@ import org.jeecg.modules.billet.rollHeight.entity.RollHeightDetails;
 import org.jeecg.modules.billet.rollHeight.mapper.RollHeightMapper;
 import org.jeecg.modules.billet.rollHeight.service.IRollHeightDetailsService;
 import org.jeecg.modules.billet.rollHeight.service.IRollHeightService;
+import org.jeecg.modules.billet.rollHeight.vo.RollHeightHeatVO;
+import org.jeecg.modules.billet.rollHeight.vo.RollHeightVO;
+import org.jeecg.modules.billet.storageBill.vo.StorageCenterExportRow;
+import org.jeecg.modules.carUnit.service.ISysDictService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.text.SimpleDateFormat;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
- * @Description: 轧钢棒一
+ * @Description: 轧钢高线
  * @Author: jeecg-boot
  * @Date:   2024-05-06
  * @Version: V1.0
@@ -44,6 +61,18 @@ public class RollHeightServiceImpl extends ServiceImpl<RollHeightMapper, RollHei
     @Autowired
     private IBilletHotsendChangeShiftService billetHotsendChangeShiftService;
 
+    @Autowired
+    private IBilletOriginalProductRecordService billetOriginalProductRecordService;
+
+    @Autowired
+    private BilletHotsendBaseMapper billetHotsendBaseMapper;
+
+    @Autowired
+    private ISysDictService sysDictService;
+
+    @Autowired
+    private BilletRulerConfigMapper billetRulerConfigMapper;
+
     @Override
     public DestinationStatistics queryByCcmNoHandle(String ccmNo) {
         DestinationStatistics destinationStatistics = new DestinationStatistics();
@@ -220,6 +249,382 @@ public class RollHeightServiceImpl extends ServiceImpl<RollHeightMapper, RollHei
         return destinationStatistics;
     }
 
+    @Override
+    public List<RollHeightVO> rollHeightList(RollHeightQueryDTO queryDTO) {
+        // 2. 遍历所有炉号,构建最终返回列表
+        List<RollHeightVO> resultList = new ArrayList<>();
+        LambdaQueryWrapper<BilletOriginalProductRecord> oneQueryWrapper = new LambdaQueryWrapper<>();
+        oneQueryWrapper.eq(BilletOriginalProductRecord::getCcmNo, queryDTO.getCcmNo());
+        Boolean search = true; // 定义未传任何条件
+        if(oConvertUtils.isNotEmpty(queryDTO.getChangeShiftId())) { // 班组取班组时间
+            // 根据铸机号、交班记录ID,获取交班记录中的班别、班次、创建时间
+            LambdaQueryWrapper<BilletHotsendChangeShift> changeQueryWrapper = new LambdaQueryWrapper<>();
+            changeQueryWrapper.eq(BilletHotsendChangeShift::getId, queryDTO.getChangeShiftId()).eq(BilletHotsendChangeShift::getCcmNo, queryDTO.getCcmNo());
+            BilletHotsendChangeShift billetHotsendChangeShift = billetHotsendChangeShiftService.getOne(changeQueryWrapper);
+            if (billetHotsendChangeShift == null){
+                return resultList;
+            }
+            Date startChangeTime = billetHotsendChangeShift.getCreateTime();
+            oneQueryWrapper.eq(BilletOriginalProductRecord::getShift, billetHotsendChangeShift.getShift());
+            oneQueryWrapper.eq(BilletOriginalProductRecord::getShiftGroup, billetHotsendChangeShift.getShiftGroup());
+            Date endChangeTime = oConvertUtils.isNotEmpty(billetHotsendChangeShift.getChangeShiftTime()) ? billetHotsendChangeShift.getChangeShiftTime() : new Date();
+            oneQueryWrapper.between(BilletOriginalProductRecord::getCreateTime, startChangeTime, endChangeTime);
+            search = false;
+        }else if(oConvertUtils.isNotEmpty(queryDTO.getStartTime()) && oConvertUtils.isNotEmpty(queryDTO.getEndTime())){ // 时间范围
+            oneQueryWrapper.between(BilletOriginalProductRecord::getCreateTime,queryDTO.getStartTime(), queryDTO.getEndTime());
+            search = false;
+        }
+
+        if(oConvertUtils.isNotEmpty(queryDTO.getQueryDate())  || search == true){ // 具体时间
+            // 如果时间给了空
+            if(oConvertUtils.isEmpty(queryDTO.getQueryDate())){ // 查询最后一个班次
+                String nowDate = DateUtils.getDate("yyyy-MM-dd");
+                Date startOneTime = DateUtils.getStartOfDayByDate(DateUtils.getStartOfDay(nowDate));
+                // 查询最后一次交班记录时间
+                LambdaQueryWrapper<BilletHotsendChangeShift> changeQueryWrapper = new LambdaQueryWrapper<>();
+                changeQueryWrapper.eq(BilletHotsendChangeShift::getCcmNo, queryDTO.getCcmNo()).orderByDesc(BilletHotsendChangeShift::getCreateTime).last("limit 1");
+                BilletHotsendChangeShift billetHotsendChangeShift = billetHotsendChangeShiftService.getOne(changeQueryWrapper);
+                // 查询确认时间为 null 或者  班次记录
+                oneQueryWrapper.ge(BilletOriginalProductRecord::getCreateTime, oConvertUtils.isNotEmpty(billetHotsendChangeShift.getCreateTime()) ? billetHotsendChangeShift.getCreateTime() : startOneTime);
+            } else {
+                // 获取当前年月日
+                Date queryDate = oConvertUtils.isNotEmpty(queryDTO.getQueryDate()) ? queryDTO.getQueryDate() : DateUtils.getDate() ;
+                Date startTime = DateUtils.getStartOfDayByDate(DateUtils.getStartOfDay(queryDate));
+                // 结束时间
+                Date endTime = DateUtils.getEndOfDayByDate(startTime);
+                oneQueryWrapper.between(BilletOriginalProductRecord::getCreateTime, startTime, endTime);
+            }
+        }
+        // 炉号查询
+        if (oConvertUtils.isNotEmpty(queryDTO.getHeatNo())) {
+            oneQueryWrapper.eq(BilletOriginalProductRecord::getHeatNo, queryDTO.getHeatNo());
+        }
+
+        // 定尺查询
+        if (oConvertUtils.isNotEmpty(queryDTO.getSize())) {
+            oneQueryWrapper.like(BilletOriginalProductRecord::getRollClubOneDetails, queryDTO.getSize());
+        }
+
+        // 牌号
+        if (oConvertUtils.isNotEmpty(queryDTO.getBrandNum())) {
+            oneQueryWrapper.eq(BilletOriginalProductRecord::getGrade, queryDTO.getBrandNum());
+        }
+        oneQueryWrapper.orderByAsc(BilletOriginalProductRecord::getCreateTime);
+
+        List<BilletOriginalProductRecord> list = billetOriginalProductRecordService.list(oneQueryWrapper);
+
+
+        //构造数据
+        Map<String, RollHeightHeatVO.RollHeightHeatNo> rollHeightMap = buildRollHeightHeatNoMap(list); // 根据高线明细构建
+
+        // 1. 按炉号聚合高线数据到 StorageCenterHeatNoInvoicingVO
+        Map<String, RollHeightHeatVO> heatNoVOMap = new HashMap<>();
+        for (String heatNo : rollHeightMap.keySet()) {
+            RollHeightHeatVO vo = heatNoVOMap.computeIfAbsent(heatNo, k -> new RollHeightHeatVO());
+            RollHeightHeatVO.RollHeightHeatNo rollHeight = rollHeightMap.get(heatNo);
+            vo.setRollHeightDetails(rollHeight);
+
+        }
+
+
+        Set<String> allHeatNos = new HashSet<>();
+        allHeatNos.addAll(rollHeightMap.keySet());
+
+        Map<String, RollHeightVO.HeatNoDetail> heatNoDetailMap = new HashMap<>();
+
+
+        if (CollectionUtils.isNotEmpty(allHeatNos)) {
+            LambdaQueryWrapper<BilletHotsend> hotsendWrapper = new LambdaQueryWrapper<>();
+            hotsendWrapper.in(BilletHotsend::getHeatNo, allHeatNos); // 只查用到的炉号
+            List<BilletHotsend> hotsendList = billetHotsendBaseMapper.selectList(hotsendWrapper);
+
+            if (CollectionUtils.isNotEmpty(hotsendList)) {
+                Map<String, List<BilletHotsend>> hotsendGroupMap = hotsendList.stream()
+                        .collect(Collectors.groupingBy(BilletHotsend::getHeatNo));
+
+                for (Map.Entry<String, List<BilletHotsend>> entry : hotsendGroupMap.entrySet()) {
+                    String heatNo = entry.getKey();
+                    List<BilletHotsend> hotsends = entry.getValue();
+                    if (CollectionUtils.isEmpty(hotsends)) {
+                        continue;
+                    }
+                    // 先定义 rollOne,初始值为 null
+                    RollHeightHeatVO.RollHeightHeatNo rollHeight = null;
+                    RollHeightHeatVO vo = heatNoVOMap.get(heatNo);
+                    if (vo != null) {
+                        rollHeight = vo.getRollHeightDetails();
+                    }
+                    // 初始化累计值
+                    int totalAmount = 0;
+                    BigDecimal totalWeight = BigDecimal.ZERO;
+
+                    if (rollHeight != null && rollHeight.getTotalAmount() != null) {
+                        totalAmount += rollHeight.getTotalAmount();
+                    }
+                    if (rollHeight != null && rollHeight.getTotalWeight() != null) {
+                        totalWeight = totalWeight.add(rollHeight.getTotalWeight());
+                    }
+                    RollHeightVO.HeatNoDetail detail = new RollHeightVO.HeatNoDetail();
+                    detail.setHeatNo(heatNo);
+                    // 按 createTime 降序,选最新记录
+                    hotsends.sort(Comparator.comparing(BilletHotsend::getCreateTime, Comparator.nullsLast(Date::compareTo)).reversed());
+                    BilletHotsend latest = hotsends.get(0);
+
+                    // 这里用优先级取 createTime
+                    Date finalCreateTime = null;
+                    if (rollHeight != null
+                            && rollHeight.getRollSendDetails() != null
+                            && !rollHeight.getRollSendDetails().isEmpty()
+                            && rollHeight.getRollSendDetails().get(0).getCreateTime() != null) {
+
+                        finalCreateTime = rollHeight.getRollSendDetails().get(0).getCreateTime();
+                    } else {
+                        finalCreateTime = latest.getCreateTime();
+                    }
+
+                    detail.setCreateTime(finalCreateTime);
+                    detail.setHeatNoAmount(totalAmount);
+                    detail.setHeatNoWeight(totalWeight);
+
+                    // ccmNo 可能为空或非数字,需要校验
+                    try {
+                        if (StringUtils.isNotBlank(latest.getCcmNo())) {
+                            detail.setCcmNo(Integer.valueOf(latest.getCcmNo()));
+                        }
+                    } catch (NumberFormatException e) {
+                        log.warn("炉号 {} 的 ccmNo 非法值:{}", heatNo, latest.getCcmNo(), e);
+                    }
+
+                    detail.setShift(latest.getShift());
+                    detail.setShiftGroup(latest.getShiftGroup());
+                    heatNoDetailMap.put(heatNo, detail);
+                }
+            } else {
+                log.warn("未查询到 billet_hotsend 记录,heatNo 列表为:{}", allHeatNos);
+            }
+        } else {
+            log.warn("heatNo 集合为空,跳过 billet_hotsend 查询");
+        }
+
+        if (CollectionUtils.isNotEmpty(allHeatNos)) {
+            for (String heatNo : allHeatNos) {
+                RollHeightVO invoicingVO = new RollHeightVO();
+
+                // 设置基础详情
+                RollHeightVO.HeatNoDetail detail = heatNoDetailMap.get(heatNo);
+                invoicingVO.setHeatNoDetails(detail == null ? Collections.emptyList() : Collections.singletonList(detail));
+
+                // 设置聚合的高线数据
+                RollHeightHeatVO heatNoInvoicing = heatNoVOMap.get(heatNo);
+                invoicingVO.setStorageCenterHeatNoInvoicing(heatNoInvoicing);
+
+                resultList.add(invoicingVO);
+            }
+        } else {
+            log.warn("allHeatNos 为空,未生成高线信息结果");
+        }
+
+        resultList.sort(Comparator.comparing(
+                vo -> vo.getHeatNoDetails() == null || vo.getHeatNoDetails().isEmpty()
+                        ? null
+                        : vo.getHeatNoDetails().stream()
+                        .map(RollHeightVO.HeatNoDetail::getCreateTime)
+                        .filter(Objects::nonNull)
+                        .max(Comparator.naturalOrder())
+                        .orElse(null),
+                Comparator.nullsLast(Comparator.reverseOrder())
+        ));
+
+        return resultList;
+    }
+
+    @Override
+    public List<StorageCenterExportRow> buildExportData(List<RollHeightVO> records) {
+        List<StorageCenterExportRow> rows = new ArrayList<>();
+
+        for (RollHeightVO vo : records) {
+            Integer ccmNo = Optional.ofNullable(vo.getHeatNoDetails())
+                    .flatMap(list -> list.stream().findFirst())
+                    .map(RollHeightVO.HeatNoDetail::getCcmNo)
+                    .orElse(null);
+
+            RollHeightHeatVO invoicing = vo.getStorageCenterHeatNoInvoicing();
+            if (invoicing == null) continue;
+
+            // 高线 rollHeightDetails
+            if (invoicing.getRollHeightDetails() != null && invoicing.getRollHeightDetails() != null) {
+                for (RollHeightHeatVO.RollSendDetail detail : invoicing.getRollHeightDetails().getRollSendDetails()) {
+                    StorageCenterExportRow row = otherConvert(detail, ccmNo, "高线");
+                    row.setBrand(vo.getStorageCenterHeatNoInvoicing().getRollHeightDetails().getBrandNum());
+
+                    String heatNo = Optional.ofNullable(vo.getHeatNoDetails())
+                            .filter(list -> !list.isEmpty())
+                            .map(list -> list.get(0).getHeatNo())
+                            .orElse("");
+
+                    row.setHeatNo(heatNo);
+                    rows.add(row);
+                }
+            }
+        }
+
+        return rows;
+    }
+
+
+    private static StorageCenterExportRow otherConvert(RollHeightHeatVO.RollSendDetail detail, Integer ccmNo, String endPoint) {
+        StorageCenterExportRow row = new StorageCenterExportRow();
+
+        row.setEndPoint(endPoint);
+        row.setLicensePlate("辊道");
+        row.setAmount(detail.getAmount());
+        row.setTotalWeight(detail.getWeight());
+        row.setCcmNo(ccmNo);
+        row.setWeightPerPiece(calcWeightPerPiece(detail.getWeight(), detail.getAmount()));
+        BigDecimal result = BigDecimal.valueOf(detail.getSize()).divide(BigDecimal.valueOf(1000));
+        if (result != null) {
+            row.setSize("170*170*" + result.toPlainString());
+        }
+        row.setSpec(detail.getSpec());
+        if (detail != null && detail.getCreateTime() != null) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            row.setFactoryDate(sdf.format(detail.getCreateTime()));
+        } else {
+            row.setFactoryDate("");
+        }
+
+        return row;
+    }
+
+
+    public Map<String, RollHeightHeatVO.RollHeightHeatNo> buildRollHeightHeatNoMap(List<BilletOriginalProductRecord> heightList) {
+        Map<String, RollHeightHeatVO.RollHeightHeatNo> resultMap = new HashMap<>();
+        Map<String, BigDecimal> lengthWeightCache = new HashMap<>();
+        Map<String, String> lengthSpecCache = new HashMap<>();
+        Map<String, Integer> lengthCumulativeCountMap = new HashMap<>(); // 新增:记录每种定尺的累计终止根数
+
+        ObjectMapper objectMapper = new ObjectMapper();
+
+        for (BilletOriginalProductRecord record : heightList) {
+            Map<String, Integer> lengthCountMap = new HashMap<>();
+            RollHeightHeatVO.RollHeightHeatNo rollHeightHeatNo = new RollHeightHeatVO.RollHeightHeatNo();
+            List<RollHeightHeatVO.SizeDetail> sizeDetailsList = new ArrayList<>();
+            List<RollHeightHeatVO.RollSendDetail> rollSendDetailList = new ArrayList<>();
+            String brandNum = "";
+
+            if (record.getGrade() != null) {
+                brandNum = Optional.ofNullable(record.getGrade())
+                        .map(bn -> sysDictService.queryDictTextByKey("billet_spec", bn))
+                        .orElseGet(() -> sysDictService.queryDictTextByKey("billet_spec", "5"));
+            }
+
+            rollHeightHeatNo.setBrandNum(brandNum);
+
+            rollHeightHeatNo.setId(record.getId());
+            rollHeightHeatNo.setConfirmTime(record.getConfirmTime());
+
+            String detailJson = record.getRollClubOneDetails();
+
+            if (StringUtils.isNotBlank(detailJson)) {
+                try {
+                    JsonNode rootNode = objectMapper.readTree(detailJson);
+
+                    rollHeightHeatNo.setTotalAmount(getIntValue(rootNode, "directRollingTotalCount"));
+                    rollHeightHeatNo.setTotalWeight(getBigDecimalValue(rootNode, "directRollingTotalWeight"));
+
+                    JsonNode lengthGroupNode = rootNode.get("lengthGroupCount");
+                    if (lengthGroupNode != null && lengthGroupNode.isObject()) {
+                        Iterator<Map.Entry<String, JsonNode>> fields = lengthGroupNode.fields();
+                        while (fields.hasNext()) {
+                            Map.Entry<String, JsonNode> entry = fields.next();
+                            String length = entry.getKey();
+                            int count = entry.getValue().asInt();
+                            lengthCountMap.merge(length, count, Integer::sum);
+                        }
+                    }
+
+                    for (Map.Entry<String, Integer> entry : lengthCountMap.entrySet()) {
+                        String length = entry.getKey();
+                        int count = entry.getValue();
+
+                        BigDecimal unitWeight = BigDecimal.ZERO;
+                        String spec = "";
+
+
+                        if (lengthWeightCache.containsKey(length)) {
+                            unitWeight = lengthWeightCache.get(length);
+                            spec = lengthSpecCache.getOrDefault(length, "");
+
+                        } else {
+                            LambdaQueryWrapper<BilletRulerConfig> wrapper = new LambdaQueryWrapper<BilletRulerConfig>()
+                                    .eq(BilletRulerConfig::getLength, length);
+                            BilletRulerConfig config = billetRulerConfigMapper.selectOne(wrapper);
+                            if (config != null) {
+                                if (config.getWeight() != null) {
+                                    unitWeight = BigDecimal.valueOf(config.getWeight());
+                                    lengthWeightCache.put(length, unitWeight);
+                                }
+                                if (config.getSpec() != null) {
+                                    spec = config.getSpec();
+                                    lengthSpecCache.put(length, spec);
+                                }
+
+                            }
+                        }
+
+                        BigDecimal totalWeight = unitWeight.multiply(BigDecimal.valueOf(count));
+
+                        // 计算起始根数与终止根数
+                        int lastEndAmount = lengthCumulativeCountMap.getOrDefault(length, 0);
+                        int startAmount = lastEndAmount + 1;
+                        int endAmount = lastEndAmount + count;
+                        lengthCumulativeCountMap.put(length, endAmount); // 更新累计值
+
+                        // sizeDetail
+                        RollHeightHeatVO.SizeDetail sizeDetail = new RollHeightHeatVO.SizeDetail();
+                        sizeDetail.setSize(Integer.valueOf(length));
+                        sizeDetail.setSizeAmount(count);
+                        sizeDetail.setSizeWeight(totalWeight);
+                        sizeDetail.setStartAmount(startAmount);
+                        sizeDetail.setEndAmount(endAmount);
+                        sizeDetailsList.add(sizeDetail);
+
+                        // rollSendDetail
+                        RollHeightHeatVO.RollSendDetail rollSendDetail = new RollHeightHeatVO.RollSendDetail();
+                        rollSendDetail.setSize(Integer.valueOf(length));
+                        rollSendDetail.setAmount(count);
+                        rollSendDetail.setWeight(totalWeight);
+                        rollSendDetail.setSpec(spec);
+                        rollSendDetail.setCreateTime(record.getCreateTime());
+                        rollSendDetailList.add(rollSendDetail);
+                    }
+
+                    rollHeightHeatNo.setSizeDetails(sizeDetailsList);
+                    rollHeightHeatNo.setRollSendDetails(rollSendDetailList);
+                    resultMap.put(record.getHeatNo(), rollHeightHeatNo);
+
+                } catch (Exception e) {
+                    log.info("JSON 解析失败,数据:{}", detailJson, e);
+                }
+            }
+        }
+
+        return resultMap;
+    }
+
+
+    // 工具方法:解析 int
+    private Integer getIntValue(JsonNode node, String fieldName) {
+        JsonNode valueNode = node.get(fieldName);
+        return (valueNode != null && valueNode.isInt()) ? valueNode.asInt() : 0;
+    }
+
+    // 工具方法:解析 BigDecimal(使用字符串,避免精度丢失)
+    private BigDecimal getBigDecimalValue(JsonNode node, String fieldName) {
+        JsonNode valueNode = node.get(fieldName);
+        return (valueNode != null && valueNode.isNumber()) ? new BigDecimal(valueNode.asText()) : BigDecimal.ZERO;
+    }
+
 
     /**
      * 从Redis中获取班组班别
@@ -231,4 +636,9 @@ public class RollHeightServiceImpl extends ServiceImpl<RollHeightMapper, RollHei
         String key = String.format(keyFormat, ccmNo);
         return oConvertUtils.getString(redisTemplate.opsForValue().get(key));
     }
+
+    private static BigDecimal calcWeightPerPiece(BigDecimal total, Integer amount) {
+        if (total == null || amount == null || amount == 0) return BigDecimal.ZERO;
+        return total.divide(BigDecimal.valueOf(amount), 4, RoundingMode.HALF_UP);
+    }
 }

+ 84 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollHeight/vo/RollHeightHeatVO.java

@@ -0,0 +1,84 @@
+package org.jeecg.modules.billet.rollHeight.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class RollHeightHeatVO {
+
+    private RollHeightHeatNo rollHeightDetails;
+
+    @Data
+    public static class RollHeightHeatNo {
+
+        private String id;
+
+        @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+        @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+        private Date confirmTime;
+
+        @ApiModelProperty(value = "牌号")
+        private String brandNum;
+
+        @ApiModelProperty(value = "当前定尺总支数")
+        private Integer totalAmount;
+
+        @ApiModelProperty(value = "当前定尺总重量")
+        private BigDecimal totalWeight;
+
+
+        private List<SizeDetail> sizeDetails;
+
+        private List<RollSendDetail> rollSendDetails;
+
+    }
+
+    @Data
+    public static class RollSendDetail {
+
+        @ApiModelProperty(value = "定尺")
+        private Integer size;
+
+        @ApiModelProperty(value = "规格")
+        private String spec;
+
+        @ApiModelProperty(value = "支数")
+        private Integer amount;
+
+        @ApiModelProperty(value = "重量")
+        private BigDecimal weight;
+
+        @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+        @DateTimeFormat(pattern = "yyyy-MM-dd")
+        @ApiModelProperty(value = "创建日期")
+        private Date createTime;
+
+
+    }
+
+    @Data
+    public static class SizeDetail {
+
+        @ApiModelProperty(value = "当前定尺")
+        public Integer size;
+
+        @ApiModelProperty(value = "当前定尺总支数")
+        private Integer sizeAmount;
+
+        @ApiModelProperty(value = "当前定尺总重量")
+        private BigDecimal sizeWeight;
+
+        @ApiModelProperty(value = "当前定尺起始根")
+        private Integer startAmount;
+
+        @ApiModelProperty(value = "当前定尺结束根")
+        private Integer endAmount;
+
+    }
+}

+ 52 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollHeight/vo/RollHeightVO.java

@@ -0,0 +1,52 @@
+package org.jeecg.modules.billet.rollHeight.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class RollHeightVO {
+
+    private List<HeatNoDetail> heatNoDetails;
+
+    private RollHeightHeatVO storageCenterHeatNoInvoicing;
+
+
+    @Data
+    public static class HeatNoDetail {
+
+        @ApiModelProperty(value = "铸机号")
+        private Integer ccmNo;
+
+        @ApiModelProperty(value = "当前炉号")
+        public String heatNo;
+
+        @ApiModelProperty(value = "当前炉号总支数")
+        private Integer heatNoAmount;
+
+        @ApiModelProperty(value = "当前炉号总重量")
+        private BigDecimal heatNoWeight;
+
+        @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "创建时间")
+        private Date createTime;
+
+        @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 shiftGroup;
+
+        @ApiModelProperty(value = "班别")
+        private String shift;
+
+    }
+}

+ 1 - 1
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/storageBill/service/impl/StorageBillServiceImpl.java

@@ -1415,8 +1415,8 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
             BigDecimal currentShiftProduct = new BigDecimal(currentTotalWeight).setScale(4, RoundingMode.HALF_UP);
             billetHotsendChangeShift.setShiftProduct(currentShiftProduct.doubleValue());
             billetHotsendChangeShift.setShiftSum(billetBasicInfoListSum.size());
-            onDutyInfo.setBilletHotsendChangeShift(billetHotsendChangeShift);
         }
+        onDutyInfo.setBilletHotsendChangeShift(billetHotsendChangeShift);
         return onDutyInfo;
     }