Browse Source

feat: eqpbookChannel表新增useMode字段的汇聚

feature/agg
yinhuaiwei 6 days ago
parent
commit
aa593aecbb
6 changed files with 56 additions and 41 deletions
  1. +2
    -0
      inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbookChannel.java
  2. +29
    -35
      inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/AggStatisticService.java
  3. +1
    -0
      inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/ChannelSyncService.java
  4. +18
    -2
      inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/EqpbookTreeService.java
  5. +2
    -1
      inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/web/AggTreeController.java
  6. +4
    -3
      inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookChannelMapper.xml

+ 2
- 0
inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbookChannel.java View File

@ -38,6 +38,8 @@ public class AggBasedataEqpbookChannel {
private String deviceSource;
/** 通道能力(JSON 字符串,树接口返回时解析为对象) */
private String capabilities;
/** 使用类型(源表 basedata_eqpbook_channel.use_mode) */
private String useMode;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime updateTime;
private LocalDateTime syncedAt;


+ 29
- 35
inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/AggStatisticService.java View File

@ -13,7 +13,6 @@ import java.util.Map;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.inspect.agg.config.AggProperties;
import com.inspect.agg.entity.AggAnalysisDefectMonth;
import com.inspect.agg.entity.AggStation;
import com.inspect.agg.enums.AlgCategory;
@ -31,39 +30,49 @@ public class AggStatisticService {
private static final String MONTH = "month";
private static final String QUARTER = "quarter";
private static final String YEAR = "year";
/** 统计窗口下限:最早只能查 2026-10(季度下限即 2026-Q4 的首月)。 */
private static final YearMonth MIN_STAT_MONTH = YearMonth.of(2026, 10);
private static final YearMonth MIN_STAT_QUARTER_START = YearMonth.of(2026, 10);
private final AggAnalysisDefectMonthMapper defectMonthMapper;
private final AggPatrolTaskStatusMapper taskStatusMapper;
private final AggStationMapper stationMapper;
private final AggProperties props;
public List<Map<String, Object>> defectStatistic(String stationCode, String algCategory,
String dateType) {
List<AlgCategory> categories = parseCategories(algCategory);
String normalizedType = normalizeDateType(dateType);
YearMonth current = YearMonth.now();
LocalDate begin;
LocalDate endExclusive;
if (QUARTER.equals(normalizedType)) {
YearMonth currentQuarter = quarterStart(current);
begin = currentQuarter.minusMonths(9).atDay(1);
endExclusive = currentQuarter.plusMonths(3).atDay(1);
} else if (YEAR.equals(normalizedType)) {
begin = LocalDate.of(current.getYear() - 2, 1, 1);
endExclusive = LocalDate.of(current.getYear() + 1, 1, 1);
// 固定长度窗口:月 12 个、季 4 个、年 3 个;右端对齐当前周期,
// 若左端早于统计下限(2026-10),整体右移,窗口长度不变。
YearMonth windowStart;
int windowMonths;
if (YEAR.equals(normalizedType)) {
int startYear = Math.max(current.getYear() - 2, MIN_STAT_MONTH.getYear());
windowStart = YearMonth.of(startYear, 1);
windowMonths = 36;
} else if (QUARTER.equals(normalizedType)) {
YearMonth start = quarterStart(current).minusMonths(9);
windowStart = start.isBefore(MIN_STAT_QUARTER_START) ? MIN_STAT_QUARTER_START : start;
windowMonths = 12;
} else {
begin = current.minusMonths(11).atDay(1);
endExclusive = current.plusMonths(1).atDay(1);
YearMonth start = current.minusMonths(11);
windowStart = start.isBefore(MIN_STAT_MONTH) ? MIN_STAT_MONTH : start;
windowMonths = 12;
}
LocalDate begin = windowStart.atDay(1);
LocalDate endExclusive = windowStart.plusMonths(windowMonths).atDay(1);
List<AggAnalysisDefectMonth> rows = defectMonthMapper.selectRange(stationCode, begin, endExclusive);
Map<YearMonth, Counts> monthlyMap = toMonthlyMap(rows, categories);
String stationName = stationDisplayName(stationCode);
List<Map<String, Object>> result = new ArrayList<>();
if (YEAR.equals(normalizedType)) {
int currentYear = current.getYear();
for (int year = currentYear - 2; year <= currentYear; year++) {
int startYear = windowStart.getYear();
for (int i = 0; i < 3; i++) {
int year = startYear + i;
Counts counts = new Counts();
for (int monthOffset = 0; monthOffset < 12; monthOffset++) {
counts.add(monthlyMap.get(YearMonth.of(year, 1).plusMonths(monthOffset)));
@ -75,9 +84,8 @@ public class AggStatisticService {
}
if (QUARTER.equals(normalizedType)) {
YearMonth firstQuarter = quarterStart(current).minusMonths(9);
for (int i = 0; i < 4; i++) {
YearMonth quarter = firstQuarter.plusMonths(i * 3L);
YearMonth quarter = windowStart.plusMonths(i * 3L);
Counts counts = new Counts();
for (int monthOffset = 0; monthOffset < 3; monthOffset++) {
counts.add(monthlyMap.get(quarter.plusMonths(monthOffset)));
@ -89,9 +97,8 @@ public class AggStatisticService {
return result;
}
YearMonth first = current.minusMonths(11);
for (int i = 0; i < 12; i++) {
YearMonth month = first.plusMonths(i);
YearMonth month = windowStart.plusMonths(i);
Counts counts = monthlyMap.getOrDefault(month, new Counts());
result.add(toPeriodResult(counts, month.format(MONTH_FORMAT), normalizedType, algCategory,
stationCode, stationName));
@ -161,7 +168,6 @@ public class AggStatisticService {
item.put("stationCode", stationCode);
item.put("stationName", stationName != null ? stationName : stationCode);
}
item.put("minorCount", minorCount(counts));
item.put("generalCount", counts.general);
item.put("seriousCount", counts.serious);
item.put("urgentCount", counts.urgent);
@ -182,21 +188,16 @@ public class AggStatisticService {
result.put("inspectedTaskCount", number(taskStats, "inspected_task_count"));
result.put("completedTaskCount", number(taskStats, "completed_task_count"));
result.put("defectCount", defectCount(defectStats));
result.put("minorCount", minorCount(defectStats));
result.put("generalCount", defectStats.general);
result.put("seriousCount", defectStats.serious);
result.put("urgentCount", defectStats.urgent);
return result;
}
private int minorCount(Counts counts) {
return props.getStatistic().isMinorDefectEnabled() ? counts.minor : 0;
}
/**
* 缺陷总数只统计一般及以上缺陷,轻微缺陷不计入。
*/
private long defectCount(Counts counts) {
if (props.getStatistic().isMinorDefectEnabled()) {
return counts.defectCount();
}
return (long) counts.general + counts.serious + counts.urgent;
}
@ -262,7 +263,6 @@ public class AggStatisticService {
}
private static class Counts {
private int minor;
private int general;
private int serious;
private int urgent;
@ -272,7 +272,6 @@ public class AggStatisticService {
if (row == null) {
return;
}
minor += nz(row.getMinorCount());
general += nz(row.getGeneralCount());
serious += nz(row.getSeriousCount());
urgent += nz(row.getUrgentCount());
@ -283,17 +282,12 @@ public class AggStatisticService {
if (other == null) {
return;
}
minor += other.minor;
general += other.general;
serious += other.serious;
urgent += other.urgent;
normal += other.normal;
}
private long defectCount() {
return minor + general + serious + urgent;
}
private static int nz(Integer value) {
return value == null ? 0 : value;
}


+ 1
- 0
inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/ChannelSyncService.java View File

@ -93,6 +93,7 @@ public class ChannelSyncService {
c.setUpSystemDeviceCode(Rows.text(r, "upSystemDeviceCode"));
c.setDeviceSource(Rows.text(r, "deviceSource"));
c.setCapabilities(Rows.jsonText(r, "capabilities"));
c.setUseMode(Rows.text(r, "useMode", "use_mode"));
c.setUpdateTime(Rows.date(r, "updateTime"));
c.setSyncedAt(LocalDateTime.now());
c.setIsDeleted(0);


+ 18
- 2
inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/EqpbookTreeService.java View File

@ -41,7 +41,8 @@ public class EqpbookTreeService {
String patrolDeviceName,
String onlineStatus,
String patrolDeviceTypeFlag,
String deviceSource) {
String deviceSource,
String useMode) {
List<AggBasedataArea> areas = areaMapper.listForTree(stationCode);
List<AggBasedataEqpbook> eqpbooks = eqpbookMapper.list(stationCode, 0);
List<AggBasedataEqpbookChannel> channels = channelMapper.list(stationCode, 0);
@ -53,7 +54,7 @@ public class EqpbookTreeService {
Map<String, List<AggBasedataEqpbookChannel>> channelIndex = new HashMap<>();
for (AggBasedataEqpbookChannel channel : channels) {
if (!matchesDeviceSource(channel, deviceSource)) {
if (!matchesDeviceSource(channel, deviceSource) || !matchesUseMode(channel, useMode)) {
continue;
}
channelIndex.computeIfAbsent(eqpbookKey(channel.getStationCode(), channel.getEqpbookId()),
@ -159,6 +160,7 @@ public class EqpbookTreeService {
channelNode.put("channelType", channel.getChannelType());
channelNode.put("deviceSource", channel.getDeviceSource());
channelNode.put("capabilities", parseCapabilities(channel.getCapabilities()));
channelNode.put("useMode", channel.getUseMode());
channelNode.put("host", channel.getHost());
channelNode.put("port", channel.getPort());
channelNode.put("stationCode", channel.getStationCode());
@ -243,6 +245,20 @@ public class EqpbookTreeService {
return expected.equals(actual);
}
private static boolean matchesUseMode(AggBasedataEqpbookChannel channel, String useMode) {
if (!StringUtils.hasText(useMode)) {
return true;
}
String actual = channel.getUseMode() == null ? "" : channel.getUseMode().trim();
for (String expected : useMode.split(",")) {
String value = expected.trim();
if (!value.isEmpty() && value.equals(actual)) {
return true;
}
}
return false;
}
private static boolean matchesType(AggBasedataEqpbook eqpbook, String flag) {
if (!StringUtils.hasText(flag)) return true;
String type = eqpbook.getDeviceType();


+ 2
- 1
inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/web/AggTreeController.java View File

@ -35,9 +35,10 @@ public class AggTreeController {
@RequestParam(value = "onlineStatus", required = false) String onlineStatus,
@RequestParam(value = "patroldeviceTypeFlag", required = false) String patrolDeviceTypeFlag,
@RequestParam(value = "deviceSource", required = false) String deviceSource,
@RequestParam(required = false) String useMode,
@RequestParam(required = false) String stationCode) {
List<Map<String, Object>> tree = eqpbookTreeService.buildFilterTree(
stationCode, patrolDeviceName, onlineStatus, patrolDeviceTypeFlag, deviceSource);
stationCode, patrolDeviceName, onlineStatus, patrolDeviceTypeFlag, deviceSource, useMode);
return AjaxResult.success(tree);
}


+ 4
- 3
inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookChannelMapper.xml View File

@ -21,16 +21,16 @@
<result column="up_system_device_code" property="upSystemDeviceCode"/>
<result column="device_source" property="deviceSource"/>
<result column="capabilities" property="capabilities"/>
<result column="use_mode" property="useMode"/>
<result column="update_time" property="updateTime"/>
<result column="synced_at" property="syncedAt"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
<!-- 骞傜瓑 upsert锛氭寜 (station_code, channel_id) -->
<insert id="upsert" parameterType="com.inspect.agg.entity.AggBasedataEqpbookChannel">
INSERT INTO agg_basedata_eqpbook_channel (station_code, channel_id, channel_code, channel_name, channel_type, online_state, channel_content, host, port, area_id, area_name, eqpbook_id, patrol_device_code, up_system_device_code, device_source, capabilities, update_time, synced_at, is_deleted)
VALUES (#{stationCode}, #{channelId}, #{channelCode}, #{channelName}, #{channelType}, #{onlineState}, #{channelContent}, #{host}, #{port}, #{areaId}, #{areaName}, #{eqpbookId}, #{patrolDeviceCode}, #{upSystemDeviceCode}, #{deviceSource}, #{capabilities}, #{updateTime}, #{syncedAt}, #{isDeleted})
INSERT INTO agg_basedata_eqpbook_channel (station_code, channel_id, channel_code, channel_name, channel_type, online_state, channel_content, host, port, area_id, area_name, eqpbook_id, patrol_device_code, up_system_device_code, device_source, capabilities, use_mode, update_time, synced_at, is_deleted)
VALUES (#{stationCode}, #{channelId}, #{channelCode}, #{channelName}, #{channelType}, #{onlineState}, #{channelContent}, #{host}, #{port}, #{areaId}, #{areaName}, #{eqpbookId}, #{patrolDeviceCode}, #{upSystemDeviceCode}, #{deviceSource}, #{capabilities}, #{useMode}, #{updateTime}, #{syncedAt}, #{isDeleted})
ON DUPLICATE KEY UPDATE
channel_code = VALUES(channel_code),
channel_name = VALUES(channel_name),
@ -46,6 +46,7 @@
up_system_device_code = VALUES(up_system_device_code),
device_source = VALUES(device_source),
capabilities = VALUES(capabilities),
use_mode = VALUES(use_mode),
update_time = VALUES(update_time),
synced_at = VALUES(synced_at),
is_deleted = VALUES(is_deleted),


Loading…
Cancel
Save