|
@@ -0,0 +1,350 @@
|
|
|
|
|
+package com.jeesite.modules.mes.web;
|
|
|
|
|
+
|
|
|
|
|
+import com.jeesite.common.entity.Page;
|
|
|
|
|
+import com.jeesite.common.lang.StringUtils;
|
|
|
|
|
+import com.jeesite.common.web.BaseController;
|
|
|
|
|
+import com.jeesite.modules.mes.entity.MesProductHf;
|
|
|
|
|
+import com.jeesite.modules.mes.entity.MesProductQm;
|
|
|
|
|
+import com.jeesite.modules.mes.entity.MesProductLeakagePointStat;
|
|
|
|
|
+import com.jeesite.modules.mes.req.MesSearchDateReq;
|
|
|
|
|
+import com.jeesite.modules.mes.service.MesProductHfService;
|
|
|
|
|
+import com.jeesite.modules.mes.service.MesProductQmService;
|
|
|
|
|
+import com.jeesite.modules.mes.util.CommonUitl;
|
|
|
|
|
+import org.apache.shiro.authz.annotation.RequiresPermissions;
|
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.stereotype.Controller;
|
|
|
|
|
+import org.springframework.ui.Model;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.ResponseBody;
|
|
|
|
|
+
|
|
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
+import javax.servlet.ServletOutputStream;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.Comparator;
|
|
|
|
|
+import java.util.Date;
|
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
|
+import java.util.Calendar;
|
|
|
|
|
+import java.net.URLEncoder;
|
|
|
|
|
+
|
|
|
|
|
+import org.apache.poi.ss.usermodel.BorderStyle;
|
|
|
|
|
+import org.apache.poi.ss.usermodel.Cell;
|
|
|
|
|
+import org.apache.poi.ss.usermodel.CellStyle;
|
|
|
|
|
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
|
|
|
|
+import org.apache.poi.ss.usermodel.Row;
|
|
|
|
|
+import org.apache.poi.ss.usermodel.Sheet;
|
|
|
|
|
+import org.apache.poi.ss.usermodel.Workbook;
|
|
|
|
|
+import org.apache.poi.ss.util.CellRangeAddress;
|
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.LinkedHashMap;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+
|
|
|
|
|
+/** 气密泄露点位统计 Controller。 */
|
|
|
|
|
+@Controller
|
|
|
|
|
+@RequestMapping(value = "${adminPath}/mes/mesProductLeakagePointStat")
|
|
|
|
|
+public class MesProductLeakagePointStatController extends BaseController {
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private MesProductHfService mesProductHfService;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private MesProductQmService mesProductQmService;
|
|
|
|
|
+
|
|
|
|
|
+ @RequiresPermissions("mes:mesProductQm:view")
|
|
|
|
|
+ @RequestMapping(value = {"list", ""})
|
|
|
|
|
+ public String list(Model model) {
|
|
|
|
|
+ return "redirect:" + adminPath + "/mes/mesProductLeakagePointStat/chart";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @RequiresPermissions("mes:mesProductQm:view")
|
|
|
|
|
+ @RequestMapping(value = "listData")
|
|
|
|
|
+ @ResponseBody
|
|
|
|
|
+ public Page<MesProductLeakagePointStat> listData(String leakagePoint, String sn, Date startDate,
|
|
|
|
|
+ Date endDate, HttpServletRequest request, HttpServletResponse response) {
|
|
|
|
|
+ List<MesProductLeakagePointStat> rows = buildStatistics(leakagePoint, sn, startDate, endDate);
|
|
|
|
|
+ Page<MesProductLeakagePointStat> page = new Page<>(request, response);
|
|
|
|
|
+ page.setCount(rows.size());
|
|
|
|
|
+ int from = Math.max(0, (page.getPageNo() - 1) * page.getPageSize());
|
|
|
|
|
+ int to = Math.min(rows.size(), from + page.getPageSize());
|
|
|
|
|
+ page.setList(from < to ? rows.subList(from, to) : new ArrayList<MesProductLeakagePointStat>());
|
|
|
|
|
+ return page;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @RequiresPermissions("mes:mesProductQm:view")
|
|
|
|
|
+ @RequestMapping(value = "chart")
|
|
|
|
|
+ public String chart(Model model) {
|
|
|
|
|
+ MesSearchDateReq dateRange = CommonUitl.getSearchDate();
|
|
|
|
|
+ model.addAttribute("startDate", dateRange.getStartDate());
|
|
|
|
|
+ model.addAttribute("endDate", dateRange.getEndtDate());
|
|
|
|
|
+ return "modules/mes/mesProductLeakagePointStatChart";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @RequiresPermissions("mes:mesProductQm:view")
|
|
|
|
|
+ @RequestMapping(value = "chartData")
|
|
|
|
|
+ @ResponseBody
|
|
|
|
|
+ public Map<String, Object> chartData(String leakagePoint, String sn, Date startDate, Date endDate) {
|
|
|
|
|
+ List<MesProductHf> records = findRecords(sn, startDate, endDate);
|
|
|
|
|
+ Map<String, Integer> pointCounts = new HashMap<>();
|
|
|
|
|
+ for (MesProductHf record : records) {
|
|
|
|
|
+ if (StringUtils.isBlank(record.getHfFlag())) continue;
|
|
|
|
|
+ for (String item : record.getHfFlag().split(",")) {
|
|
|
|
|
+ String point = normalizeLeakPoint(item);
|
|
|
|
|
+ if (StringUtils.isNotBlank(point)) pointCounts.put(point, pointCounts.getOrDefault(point, 0) + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<Map<String, Object>> points = new ArrayList<>();
|
|
|
|
|
+ for (Map.Entry<String, Integer> entry : pointCounts.entrySet()) {
|
|
|
|
|
+ Map<String, Object> row = new LinkedHashMap<>();
|
|
|
|
|
+ row.put("point", entry.getKey());
|
|
|
|
|
+ row.put("count", entry.getValue());
|
|
|
|
|
+ points.add(row);
|
|
|
|
|
+ }
|
|
|
|
|
+ points.sort((a, b) -> Integer.compare((Integer) b.get("count"), (Integer) a.get("count")));
|
|
|
|
|
+ String selectedPoint = StringUtils.isNotBlank(leakagePoint) ? leakagePoint.trim()
|
|
|
|
|
+ : (points.isEmpty() ? "" : (String) points.get(0).get("point"));
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, MesProductLeakagePointStat> detailsBySn = new LinkedHashMap<>();
|
|
|
|
|
+ Map<String, Integer> dailyCounts = new LinkedHashMap<>();
|
|
|
|
|
+ SimpleDateFormat dayFormat = new SimpleDateFormat("MM-dd");
|
|
|
|
|
+ for (MesProductHf record : records) {
|
|
|
|
|
+ if (StringUtils.isBlank(record.getSn()) || StringUtils.isBlank(record.getHfFlag())) continue;
|
|
|
|
|
+ boolean containsSelectedPoint = false;
|
|
|
|
|
+ for (String item : record.getHfFlag().split(",")) {
|
|
|
|
|
+ if (selectedPoint.equals(normalizeLeakPoint(item))) {
|
|
|
|
|
+ containsSelectedPoint = true;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!containsSelectedPoint) continue;
|
|
|
|
|
+ MesProductLeakagePointStat detail = detailsBySn.get(record.getSn());
|
|
|
|
|
+ if (detail == null) {
|
|
|
|
|
+ detail = new MesProductLeakagePointStat();
|
|
|
|
|
+ detail.setLeakagePoint(selectedPoint);
|
|
|
|
|
+ detail.setSn(record.getSn());
|
|
|
|
|
+ detail.setFirstOccurrenceTime(record.getCreateDate());
|
|
|
|
|
+ detailsBySn.put(record.getSn(), detail);
|
|
|
|
|
+ }
|
|
|
|
|
+ detail.setOccurrenceCount(detail.getOccurrenceCount() + 1);
|
|
|
|
|
+ if (record.getCreateDate() != null && (detail.getFirstOccurrenceTime() == null || record.getCreateDate().before(detail.getFirstOccurrenceTime()))) {
|
|
|
|
|
+ detail.setFirstOccurrenceTime(record.getCreateDate());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (record.getCreateDate() != null && (detail.getLastOccurrenceTime() == null || record.getCreateDate().after(detail.getLastOccurrenceTime()))) {
|
|
|
|
|
+ detail.setLastOccurrenceTime(record.getCreateDate());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (record.getCreateDate() != null) {
|
|
|
|
|
+ String day = dayFormat.format(record.getCreateDate());
|
|
|
|
|
+ dailyCounts.put(day, dailyCounts.getOrDefault(day, 0) + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<MesProductLeakagePointStat> details = new ArrayList<>(detailsBySn.values());
|
|
|
|
|
+ details.sort(Comparator.comparing(MesProductLeakagePointStat::getOccurrenceCount, Comparator.reverseOrder())
|
|
|
|
|
+ .thenComparing(MesProductLeakagePointStat::getLastOccurrenceTime, Comparator.nullsLast(Comparator.reverseOrder())));
|
|
|
|
|
+ List<Map<String, Object>> trend = new ArrayList<>();
|
|
|
|
|
+ for (Map.Entry<String, Integer> entry : dailyCounts.entrySet()) {
|
|
|
|
|
+ Map<String, Object> row = new LinkedHashMap<>();
|
|
|
|
|
+ row.put("day", entry.getKey());
|
|
|
|
|
+ row.put("count", entry.getValue());
|
|
|
|
|
+ trend.add(row);
|
|
|
|
|
+ }
|
|
|
|
|
+ trend.sort(Comparator.comparing(row -> (String) row.get("day")));
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> result = new LinkedHashMap<>();
|
|
|
|
|
+ result.put("points", points);
|
|
|
|
|
+ result.put("selectedPoint", selectedPoint);
|
|
|
|
|
+ result.put("details", details);
|
|
|
|
|
+ result.put("trend", trend);
|
|
|
|
|
+ result.put("totalCount", pointCounts.getOrDefault(selectedPoint, 0));
|
|
|
|
|
+ result.put("workpieceCount", details.size());
|
|
|
|
|
+ result.put("rawRecordCount", records.size());
|
|
|
|
|
+ result.putAll(buildQualityData(records, startDate, endDate));
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Map<String, Object> buildQualityData(List<MesProductHf> hfRecords, Date startDate, Date endDate) {
|
|
|
|
|
+ MesProductQm query = new MesProductQm();
|
|
|
|
|
+ if (startDate != null) query.setTestTime_gte(startDate);
|
|
|
|
|
+ if (endDate != null) query.setTestTime_lte(endOfDay(endDate));
|
|
|
|
|
+ int qualified = 0;
|
|
|
|
|
+ int defective = 0;
|
|
|
|
|
+ int noPoint = 0;
|
|
|
|
|
+ Map<String, Integer> pointCounts = new LinkedHashMap<>();
|
|
|
|
|
+ for (MesProductQm record : mesProductQmService.findList(query)) {
|
|
|
|
|
+ if ("OK".equalsIgnoreCase(record.getTestResult())) qualified++;
|
|
|
|
|
+ else { defective++; noPoint++; }
|
|
|
|
|
+ }
|
|
|
|
|
+ for (MesProductHf record : hfRecords) {
|
|
|
|
|
+ if ("OK".equalsIgnoreCase(record.getResult())) { qualified++; continue; }
|
|
|
|
|
+ defective++;
|
|
|
|
|
+ boolean found = false;
|
|
|
|
|
+ for (String item : (record.getHfFlag() == null ? "" : record.getHfFlag()).split(",")) {
|
|
|
|
|
+ String point = normalizeLeakPoint(item);
|
|
|
|
|
+ if (StringUtils.isNotBlank(point)) {
|
|
|
|
|
+ found = true;
|
|
|
|
|
+ pointCounts.put(point, pointCounts.getOrDefault(point, 0) + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!found) noPoint++;
|
|
|
|
|
+ }
|
|
|
|
|
+ List<Map<String, Object>> quality = new ArrayList<>();
|
|
|
|
|
+ Map<String, Object> ok = new LinkedHashMap<>(); ok.put("label", "合格数量"); ok.put("count", qualified); ok.put("color", "#2b8c70"); quality.add(ok);
|
|
|
|
|
+ Map<String, Object> ng = new LinkedHashMap<>(); ng.put("label", "不良数量"); ng.put("count", defective); ng.put("color", "#d65b43"); quality.add(ng);
|
|
|
|
|
+ List<Map<String, Object>> defects = new ArrayList<>();
|
|
|
|
|
+ String[] colors = {"#c94f3b", "#df8a43", "#3b94a1", "#6f8d4e", "#7d6aa3", "#5682b8"};
|
|
|
|
|
+ int colorIndex = 0;
|
|
|
|
|
+ for (Map.Entry<String, Integer> entry : pointCounts.entrySet()) {
|
|
|
|
|
+ Map<String, Object> item = new LinkedHashMap<>(); item.put("label", entry.getKey()); item.put("count", entry.getValue());
|
|
|
|
|
+ item.put("color", colors[colorIndex++ % colors.length]); defects.add(item);
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> missing = new LinkedHashMap<>(); missing.put("label", "找不到漏点"); missing.put("count", noPoint); missing.put("color", "#8998a3"); defects.add(missing);
|
|
|
|
|
+ defects.sort((a, b) -> Integer.compare((Integer) b.get("count"), (Integer) a.get("count")));
|
|
|
|
|
+ Map<String, Object> result = new LinkedHashMap<>();
|
|
|
|
|
+ result.put("qualifiedCount", qualified); result.put("defectiveCount", defective); result.put("noPointCount", noPoint);
|
|
|
|
|
+ result.put("qualityCategories", quality); result.put("defectCategories", defects); result.put("qualityTotal", qualified + defective);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @RequiresPermissions("mes:mesProductQm:view")
|
|
|
|
|
+ @RequestMapping(value = "chartExport")
|
|
|
|
|
+ public void chartExport(String sn, Date startDate, Date endDate, HttpServletResponse response) throws Exception {
|
|
|
|
|
+ List<MesProductLeakagePointStat> rows = buildStatistics("", sn, startDate, endDate);
|
|
|
|
|
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
|
|
+ String start = startDate == null ? "全部" : dateFormat.format(startDate);
|
|
|
|
|
+ String end = endDate == null ? "全部" : dateFormat.format(endDate);
|
|
|
|
|
+ String fileName = "气密泄露点位汇总_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".xlsx";
|
|
|
|
|
+
|
|
|
|
|
+ response.reset();
|
|
|
|
|
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
|
|
|
|
+ response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''"
|
|
|
|
|
+ + URLEncoder.encode(fileName, "UTF-8").replace("+", "%20"));
|
|
|
|
|
+ try (Workbook workbook = new XSSFWorkbook(); ServletOutputStream output = response.getOutputStream()) {
|
|
|
|
|
+ Sheet sheet = workbook.createSheet("泄露点位汇总");
|
|
|
|
|
+ int[] widths = {14, 34, 12, 22, 22};
|
|
|
|
|
+ for (int i = 0; i < widths.length; i++) sheet.setColumnWidth(i, widths[i] * 256);
|
|
|
|
|
+
|
|
|
|
|
+ CellStyle titleStyle = workbook.createCellStyle();
|
|
|
|
|
+ titleStyle.setAlignment(HorizontalAlignment.CENTER);
|
|
|
|
|
+ CellStyle headerStyle = workbook.createCellStyle();
|
|
|
|
|
+ headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
|
|
|
|
+ headerStyle.setBorderBottom(BorderStyle.THIN);
|
|
|
|
|
+ headerStyle.setBorderTop(BorderStyle.THIN);
|
|
|
|
|
+ headerStyle.setBorderLeft(BorderStyle.THIN);
|
|
|
|
|
+ headerStyle.setBorderRight(BorderStyle.THIN);
|
|
|
|
|
+ CellStyle dataStyle = workbook.createCellStyle();
|
|
|
|
|
+ dataStyle.setBorderBottom(BorderStyle.THIN);
|
|
|
|
|
+ dataStyle.setBorderTop(BorderStyle.THIN);
|
|
|
|
|
+ dataStyle.setBorderLeft(BorderStyle.THIN);
|
|
|
|
|
+ dataStyle.setBorderRight(BorderStyle.THIN);
|
|
|
|
|
+
|
|
|
|
|
+ Row titleRow = sheet.createRow(0);
|
|
|
|
|
+ titleRow.setHeightInPoints(24);
|
|
|
|
|
+ Cell titleCell = titleRow.createCell(0);
|
|
|
|
|
+ titleCell.setCellValue("气密泄露点位汇总(统计范围:" + start + " 至 " + end + ")");
|
|
|
|
|
+ titleCell.setCellStyle(titleStyle);
|
|
|
|
|
+ sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, widths.length - 1));
|
|
|
|
|
+
|
|
|
|
|
+ String[] headers = {"泄露点位", "工件号", "出现次数", "首次上报时间", "最近上报时间"};
|
|
|
|
|
+ Row headerRow = sheet.createRow(2);
|
|
|
|
|
+ headerRow.setHeightInPoints(21);
|
|
|
|
|
+ for (int i = 0; i < headers.length; i++) {
|
|
|
|
|
+ Cell cell = headerRow.createCell(i);
|
|
|
|
|
+ cell.setCellValue(headers[i]);
|
|
|
|
|
+ cell.setCellStyle(headerStyle);
|
|
|
|
|
+ }
|
|
|
|
|
+ SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
+ int rowIndex = 3;
|
|
|
|
|
+ for (MesProductLeakagePointStat stat : rows) {
|
|
|
|
|
+ Row row = sheet.createRow(rowIndex++);
|
|
|
|
|
+ String[] values = {stat.getLeakagePoint(), stat.getSn(), String.valueOf(stat.getOccurrenceCount()),
|
|
|
|
|
+ formatDateTime(stat.getFirstOccurrenceTime(), dateTimeFormat), formatDateTime(stat.getLastOccurrenceTime(), dateTimeFormat)};
|
|
|
|
|
+ for (int i = 0; i < values.length; i++) {
|
|
|
|
|
+ Cell cell = row.createCell(i);
|
|
|
|
|
+ cell.setCellValue(values[i]);
|
|
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ sheet.createFreezePane(0, 3);
|
|
|
|
|
+ workbook.write(output);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ throw new RuntimeException("导出气密泄露点位失败", e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String formatDateTime(Date date, SimpleDateFormat format) {
|
|
|
|
|
+ return date == null ? "" : format.format(date);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<MesProductLeakagePointStat> buildStatistics(String leakagePoint, String sn, Date startDate, Date endDate) {
|
|
|
|
|
+ Map<String, MesProductLeakagePointStat> statistics = new LinkedHashMap<>();
|
|
|
|
|
+ for (MesProductHf record : findRecords(sn, startDate, endDate)) {
|
|
|
|
|
+ if (StringUtils.isBlank(record.getSn()) || StringUtils.isBlank(record.getHfFlag())) continue;
|
|
|
|
|
+ for (String item : record.getHfFlag().split(",")) {
|
|
|
|
|
+ String point = normalizeLeakPoint(item);
|
|
|
|
|
+ if (StringUtils.isBlank(point)
|
|
|
|
|
+ || (StringUtils.isNotBlank(leakagePoint) && !point.contains(leakagePoint.trim()))) continue;
|
|
|
|
|
+ String key = point + "\u0000" + record.getSn();
|
|
|
|
|
+ MesProductLeakagePointStat stat = statistics.get(key);
|
|
|
|
|
+ if (stat == null) {
|
|
|
|
|
+ stat = new MesProductLeakagePointStat();
|
|
|
|
|
+ stat.setLeakagePoint(point);
|
|
|
|
|
+ stat.setSn(record.getSn());
|
|
|
|
|
+ stat.setFirstOccurrenceTime(record.getCreateDate());
|
|
|
|
|
+ statistics.put(key, stat);
|
|
|
|
|
+ }
|
|
|
|
|
+ stat.setOccurrenceCount(stat.getOccurrenceCount() + 1);
|
|
|
|
|
+ if (record.getCreateDate() != null && (stat.getFirstOccurrenceTime() == null
|
|
|
|
|
+ || record.getCreateDate().before(stat.getFirstOccurrenceTime()))) {
|
|
|
|
|
+ stat.setFirstOccurrenceTime(record.getCreateDate());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (record.getCreateDate() != null && (stat.getLastOccurrenceTime() == null
|
|
|
|
|
+ || record.getCreateDate().after(stat.getLastOccurrenceTime()))) {
|
|
|
|
|
+ stat.setLastOccurrenceTime(record.getCreateDate());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<MesProductLeakagePointStat> rows = new ArrayList<>(statistics.values());
|
|
|
|
|
+ rows.sort(Comparator.comparing(MesProductLeakagePointStat::getLeakagePoint)
|
|
|
|
|
+ .thenComparing(MesProductLeakagePointStat::getOccurrenceCount, Comparator.reverseOrder())
|
|
|
|
|
+ .thenComparing(MesProductLeakagePointStat::getSn));
|
|
|
|
|
+ return rows;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<MesProductHf> findRecords(String sn, Date startDate, Date endDate) {
|
|
|
|
|
+ MesProductHf query = new MesProductHf();
|
|
|
|
|
+ query.setSn(sn);
|
|
|
|
|
+ if (startDate != null) query.setCreateDate_gte(startDate);
|
|
|
|
|
+ if (endDate != null) query.setCreateDate_lte(endOfDay(endDate));
|
|
|
|
|
+ return mesProductHfService.findList(query);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** Date-only filters are inclusive of the selected end date, matching the detection-record page. */
|
|
|
|
|
+ private Date endOfDay(Date date) {
|
|
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
|
|
+ calendar.setTime(date);
|
|
|
|
|
+ calendar.set(Calendar.HOUR_OF_DAY, 23);
|
|
|
|
|
+ calendar.set(Calendar.MINUTE, 59);
|
|
|
|
|
+ calendar.set(Calendar.SECOND, 59);
|
|
|
|
|
+ calendar.set(Calendar.MILLISECOND, 999);
|
|
|
|
|
+ return calendar.getTime();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String normalizeLeakPoint(String value) {
|
|
|
|
|
+ String point = value == null ? "" : value.trim();
|
|
|
|
|
+ if (!point.matches("\\d+")) return point;
|
|
|
|
|
+ int index;
|
|
|
|
|
+ try {
|
|
|
|
|
+ index = Integer.parseInt(point);
|
|
|
|
|
+ } catch (NumberFormatException ignored) {
|
|
|
|
|
+ return point;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (index < 1 || index > 39) return point;
|
|
|
|
|
+ if (index <= 9) return "A" + index;
|
|
|
|
|
+ if (index <= 25) return "B" + (index - 9);
|
|
|
|
|
+ if (index <= 27) return "C" + (index - 25);
|
|
|
|
|
+ return "D" + (index - 27);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|