From 2b8a06fad6cc62d8d46307626489b68c4f8f065d Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期五, 27 三月 2026 16:15:49 +0800
Subject: [PATCH] #
---
src/main/webapp/static/js/wrkAnalysis/wrkAnalysis.js | 11 +++++
src/main/webapp/views/wrkAnalysis/wrkAnalysis.html | 5 ++
src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java | 16 ++++++++
src/test/java/com/zy/asrs/service/impl/WrkAnalysisServiceImplTest.java | 73 ++++++++++++++++++++++++++++++++++++
4 files changed, 105 insertions(+), 0 deletions(-)
diff --git a/src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java
index c000928..f647010 100644
--- a/src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/WrkAnalysisServiceImpl.java
@@ -16,6 +16,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@@ -467,6 +469,7 @@
summary.put("avgTaskBeatDurationMs", list.isEmpty() || taskStartTime == null || taskEndTime == null
? null
: durationMs(taskStartTime, taskEndTime) / list.size());
+ summary.put("avgTaskPerHour", calculateAvgTaskPerHour(list.size(), summary.get("taskDurationMs")));
summary.put("avgTotalDurationMs", average(list, item -> item.getTotalDurationMs() != null, WrkAnalysis::getTotalDurationMs));
summary.put("avgStationDurationMs", average(list, item -> !METRIC_PARTIAL.equals(item.getMetricCompleteness()) && item.getStationDurationMs() != null, WrkAnalysis::getStationDurationMs));
summary.put("avgCraneDurationMs", average(list, item -> !METRIC_PARTIAL.equals(item.getMetricCompleteness()) && item.getCraneDurationMs() != null, WrkAnalysis::getCraneDurationMs));
@@ -842,6 +845,19 @@
return count == 0 ? null : total / count;
}
+ private Double calculateAvgTaskPerHour(int taskCount, Object taskDurationMsValue) {
+ if (taskCount <= 0 || !(taskDurationMsValue instanceof Number)) {
+ return null;
+ }
+ long taskDurationMs = ((Number) taskDurationMsValue).longValue();
+ if (taskDurationMs <= 0L) {
+ return null;
+ }
+ return BigDecimal.valueOf(taskCount * 3600000D / taskDurationMs)
+ .setScale(2, RoundingMode.HALF_UP)
+ .doubleValue();
+ }
+
private void applyRange(QueryWrapper<WrkMastLog> wrapper, String column, String rawValue) {
if (Cools.isEmpty(rawValue) || !rawValue.contains("~")) {
return;
diff --git a/src/main/webapp/static/js/wrkAnalysis/wrkAnalysis.js b/src/main/webapp/static/js/wrkAnalysis/wrkAnalysis.js
index 4ea91bf..1844fe8 100644
--- a/src/main/webapp/static/js/wrkAnalysis/wrkAnalysis.js
+++ b/src/main/webapp/static/js/wrkAnalysis/wrkAnalysis.js
@@ -35,6 +35,7 @@
taskEndTime$: "",
taskDurationMs: null,
avgTaskBeatDurationMs: null,
+ avgTaskPerHour: null,
avgTotalDurationMs: null,
avgStationDurationMs: null,
avgCraneDurationMs: null,
@@ -819,6 +820,16 @@
}
return this.formatDurationBySeconds(ms / 1000);
},
+ formatTaskPerHour: function (value) {
+ if (value === null || value === undefined || value === "") {
+ return "--";
+ }
+ var num = Number(value);
+ if (!isFinite(num)) {
+ return "--";
+ }
+ return this.trimTrailingZeros(num.toFixed(2)) + " 浠诲姟/灏忔椂";
+ },
formatDurationBySeconds: function (seconds) {
var totalSeconds = Number(seconds || 0);
if (!isFinite(totalSeconds)) {
diff --git a/src/main/webapp/views/wrkAnalysis/wrkAnalysis.html b/src/main/webapp/views/wrkAnalysis/wrkAnalysis.html
index d18b9fe..1cda19f 100644
--- a/src/main/webapp/views/wrkAnalysis/wrkAnalysis.html
+++ b/src/main/webapp/views/wrkAnalysis/wrkAnalysis.html
@@ -414,6 +414,11 @@
<div class="summary-sub">鎬讳换鍔℃�昏�楁椂 / 浠诲姟鏁�</div>
</div>
<div class="summary-card">
+ <div class="summary-label">骞冲潎姣忓皬鏃惰妭鎷�</div>
+ <div class="summary-value">{{ formatTaskPerHour(analysis.summary.avgTaskPerHour) }}</div>
+ <div class="summary-sub">浠诲姟鏁� / 鎬讳换鍔℃�昏�楁椂锛堝皬鏃讹級</div>
+ </div>
+ <div class="summary-card">
<div class="summary-label">骞冲潎鎬昏�楁椂</div>
<div class="summary-value">{{ formatDuration(analysis.summary.avgTotalDurationMs) }}</div>
<div class="summary-sub">鍒涘缓鍒板畬鎴愮殑骞冲潎鑰楁椂</div>
diff --git a/src/test/java/com/zy/asrs/service/impl/WrkAnalysisServiceImplTest.java b/src/test/java/com/zy/asrs/service/impl/WrkAnalysisServiceImplTest.java
new file mode 100644
index 0000000..1460a51
--- /dev/null
+++ b/src/test/java/com/zy/asrs/service/impl/WrkAnalysisServiceImplTest.java
@@ -0,0 +1,73 @@
+package com.zy.asrs.service.impl;
+
+import com.zy.asrs.entity.WrkAnalysis;
+import com.zy.asrs.service.BasCrnpErrLogService;
+import com.zy.asrs.service.BasDualCrnpErrLogService;
+import com.zy.asrs.service.BasRgvErrLogService;
+import com.zy.asrs.service.BasStationService;
+import com.zy.asrs.service.BasWrkStatusService;
+import com.zy.asrs.service.WrkMastLogService;
+import com.zy.asrs.service.WrkMastService;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class WrkAnalysisServiceImplTest {
+
+ @Test
+ @SuppressWarnings("unchecked")
+ void buildAnalysisResult_calculatesAverageTaskPerHour() {
+ BasWrkStatusService basWrkStatusService = mock(BasWrkStatusService.class);
+ when(basWrkStatusService.getById(org.mockito.ArgumentMatchers.any())).thenReturn(null);
+ WrkAnalysisServiceImpl service = new WrkAnalysisServiceImpl(
+ mock(WrkMastLogService.class),
+ mock(BasCrnpErrLogService.class),
+ mock(BasDualCrnpErrLogService.class),
+ mock(BasRgvErrLogService.class),
+ mock(BasStationService.class),
+ basWrkStatusService,
+ mock(WrkMastService.class)
+ );
+
+ Map<String, Object> result = ReflectionTestUtils.invokeMethod(
+ service,
+ "buildAnalysisResult",
+ Arrays.asList(
+ analysis(1001, date("2026-03-27 13:00:00"), date("2026-03-27 13:10:00"), 600_000L),
+ analysis(1002, date("2026-03-27 13:15:00"), date("2026-03-27 13:30:00"), 900_000L)
+ ),
+ "finish_time"
+ );
+
+ Map<String, Object> summary = (Map<String, Object>) result.get("summary");
+ assertEquals(4.0d, ((Number) summary.get("avgTaskPerHour")).doubleValue(), 0.0001d);
+ }
+
+ private WrkAnalysis analysis(int wrkNo, Date appeTime, Date finishTime, long totalDurationMs) {
+ WrkAnalysis item = new WrkAnalysis();
+ item.setWrkNo(wrkNo);
+ item.setAppeTime(appeTime);
+ item.setFinishTime(finishTime);
+ item.setTotalDurationMs(totalDurationMs);
+ item.setFinalWrkSts(80L);
+ item.setMetricCompleteness("COMPLETE");
+ return item;
+ }
+
+ private Date date(String value) {
+ try {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value);
+ } catch (ParseException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+}
--
Gitblit v1.9.1