From 3e069207503d4685a20ab5c695b1a17993f115ea Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期三, 09 九月 2026 15:56:45 +0800
Subject: [PATCH] fix: 09-09下午第三轮——审核结果默认按企业合并与问题范围语义收敛/导出企业合并问题列按用户4条例文话术、数据查看工具栏整理、报表整本预览分组表格化 + 测试报告与工作日结
---
traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java | 431 ++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 327 insertions(+), 104 deletions(-)
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java b/traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
index 799c2fc..63dfe69 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
@@ -1259,19 +1259,17 @@
public List<AuditResult> queryResults(String reportPeriod, String reportType) {
String type = reportType == null || reportType.trim().isEmpty() ? "H2032" : reportType.trim();
+ List<AuditRule> rules = ruleMapper.selectList(new LambdaQueryWrapper<AuditRule>()
+ .eq(AuditRule::getReportType, type));
+ if (rules.isEmpty()) return new java.util.ArrayList<>();
+ List<Long> ruleIds = new ArrayList<>();
+ for (AuditRule rule : rules) ruleIds.add(rule.getId());
List<AuditResult> results = resultMapper.selectList(new LambdaQueryWrapper<AuditResult>()
.eq(AuditResult::getReportPeriod, reportPeriod)
+ .in(AuditResult::getRuleId, ruleIds)
.orderByAsc(AuditResult::getId));
- List<Long> ruleIds = new ArrayList<>();
- for (AuditRule rule : ruleMapper.selectList(null)) {
- if (type.equals(rule.getReportType())) ruleIds.add(rule.getId());
- }
- List<AuditResult> filtered = new ArrayList<>();
- for (AuditResult result : results) {
- if (ruleIds.contains(result.getRuleId())) filtered.add(result);
- }
- attachInfo(filtered);
- return filtered;
+ attachInfo(results, type, reportPeriod);
+ return results;
}
public void reviewResult(Long id, String status, String comment) {
@@ -1283,46 +1281,56 @@
resultMapper.updateById(result);
}
- private void attachInfo(List<AuditResult> results) {
+ private void attachInfo(List<AuditResult> results, String type, String period) {
if (results.isEmpty()) return;
Map<Long, AuditRule> ruleMap = new HashMap<>();
- for (AuditRule rule : ruleMapper.selectList(null)) ruleMap.put(rule.getId(), rule);
- Map<Long, String> h2032Name = new HashMap<>();
- Map<Long, String> h2032Explain = new HashMap<>();
- Map<Long, String> passengerName = new HashMap<>();
- Map<Long, String> passengerExplain = new HashMap<>();
- Map<Long, String> energyName = new HashMap<>();
- Map<Long, String> investName = new HashMap<>();
- Map<Long, String> busName = new HashMap<>();
- Map<Long, String> busExplain = new HashMap<>();
- Map<Long, String> taxiName = new HashMap<>();
- Map<Long, String> taxiExplain = new HashMap<>();
- for (H2032EnterpriseMonthly r : h2032Mapper.selectList(null)) {
- h2032Name.putIfAbsent(r.getId(), r.getEnterpriseName());
- h2032Explain.putIfAbsent(r.getId(), r.getVerifyExplanation());
+ for (AuditRule rule : ruleMapper.selectList(new LambdaQueryWrapper<AuditRule>()
+ .eq(AuditRule::getReportType, type))) {
+ ruleMap.put(rule.getId(), rule);
}
- for (PassengerEnterpriseMonthly r : passengerMapper.selectList(null)) {
- passengerName.putIfAbsent(r.getId(), r.getEnterpriseName());
- passengerExplain.putIfAbsent(r.getId(), r.getVerifyExplanation());
- }
- for (EnergyVehicleQuarterly r : energyMapper.selectList(null)) {
- energyName.putIfAbsent(r.getId(), r.getEnterpriseName());
- }
- for (CityBusMonthly r : cityBusMapper.selectList(null)) {
- busName.putIfAbsent(r.getId(), r.getEnterpriseName());
- busExplain.putIfAbsent(r.getId(), r.getVerifyExplanation());
- }
- for (CityTaxiMonthly r : cityTaxiMapper.selectList(null)) {
- taxiName.putIfAbsent(r.getId(), r.getCity());
- taxiExplain.putIfAbsent(r.getId(), r.getVerifyExplanation());
- }
- Map<Long, Long> investProjectId = new HashMap<>();
- for (InvestmentMonthly r : investMonthlyMapper.selectList(null)) {
- investProjectId.putIfAbsent(r.getId(), r.getProjectId());
- }
- for (InvestmentProject p : investProjectMapper.selectList(null)) {
- for (Map.Entry<Long, Long> e : investProjectId.entrySet()) {
- if (e.getValue().equals(p.getId())) investName.putIfAbsent(e.getKey(), p.getProjectName());
+ Map<Long, String> nameMap = new HashMap<>();
+ Map<Long, String> explainMap = new HashMap<>();
+ if ("INVEST".equals(type)) {
+ Map<Long, Long> monthlyProject = new HashMap<>();
+ for (InvestmentMonthly m : investMonthlyMapper.selectList(new LambdaQueryWrapper<InvestmentMonthly>()
+ .eq(InvestmentMonthly::getReportPeriod, period))) {
+ monthlyProject.put(m.getId(), m.getProjectId());
+ }
+ for (InvestmentProject p : investProjectMapper.selectList(null)) {
+ for (Map.Entry<Long, Long> e : monthlyProject.entrySet()) {
+ if (e.getValue() != null && e.getValue().equals(p.getId())) {
+ nameMap.putIfAbsent(e.getKey(), p.getProjectName());
+ }
+ }
+ }
+ } else if ("H204".equals(type)) {
+ for (EnergyVehicleQuarterly m : energyMapper.selectList(new LambdaQueryWrapper<EnergyVehicleQuarterly>()
+ .eq(EnergyVehicleQuarterly::getReportPeriod, period))) {
+ nameMap.putIfAbsent(m.getId(), m.getEnterpriseName());
+ }
+ } else if ("H2031".equals(type)) {
+ for (PassengerEnterpriseMonthly m : passengerMapper.selectList(new LambdaQueryWrapper<PassengerEnterpriseMonthly>()
+ .eq(PassengerEnterpriseMonthly::getReportPeriod, period))) {
+ nameMap.putIfAbsent(m.getId(), m.getEnterpriseName());
+ explainMap.putIfAbsent(m.getId(), m.getVerifyExplanation());
+ }
+ } else if ("CITY_BUS".equals(type)) {
+ for (CityBusMonthly m : cityBusMapper.selectList(new LambdaQueryWrapper<CityBusMonthly>()
+ .eq(CityBusMonthly::getReportPeriod, period))) {
+ nameMap.putIfAbsent(m.getId(), m.getEnterpriseName());
+ explainMap.putIfAbsent(m.getId(), m.getVerifyExplanation());
+ }
+ } else if ("CITY_TAXI".equals(type)) {
+ for (CityTaxiMonthly m : cityTaxiMapper.selectList(new LambdaQueryWrapper<CityTaxiMonthly>()
+ .eq(CityTaxiMonthly::getReportPeriod, period))) {
+ nameMap.putIfAbsent(m.getId(), m.getCity());
+ explainMap.putIfAbsent(m.getId(), m.getVerifyExplanation());
+ }
+ } else {
+ for (H2032EnterpriseMonthly m : h2032Mapper.selectList(new LambdaQueryWrapper<H2032EnterpriseMonthly>()
+ .eq(H2032EnterpriseMonthly::getReportPeriod, period))) {
+ nameMap.putIfAbsent(m.getId(), m.getEnterpriseName());
+ explainMap.putIfAbsent(m.getId(), m.getVerifyExplanation());
}
}
for (AuditResult result : results) {
@@ -1332,69 +1340,49 @@
result.setRuleCode(rule.getRuleCode());
result.setAlertLevel(rule.getAlertLevel());
}
- // 鍚勬姤琛ㄨ〃 id 鍚勮嚜鐙珛鑷锛岄渶鎸夎鍒欐墍灞炴姤琛ㄧ被鍨嬪垎琛ㄥ洖濉紒涓氬悕绉�
- String type = rule == null ? null : rule.getReportType();
- Map<Long, String> nameMap = "INVEST".equals(type) ? investName
- : "H204".equals(type) ? energyName
- : "H2031".equals(type) ? passengerName
- : "CITY_BUS".equals(type) ? busName
- : "CITY_TAXI".equals(type) ? taxiName : h2032Name;
- Map<Long, String> explainMap = "H2031".equals(type) ? passengerExplain
- : "CITY_BUS".equals(type) ? busExplain
- : "CITY_TAXI".equals(type) ? taxiExplain : h2032Explain;
String enterpriseName = nameMap.get(result.getReportId());
if (enterpriseName == null) {
- // 涓婃姤鏁版嵁琚噸鏂板鍏ュ悗鏃у鏍哥粨鏋滃凡澶辨晥锛岀粰鍑烘彁绀鸿�岄潪绌虹櫧
- enterpriseName = "\uFF08\u539F\u6570\u636E\u5DF2\u91CD\u65B0\u5BFC\u5165\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C\u5BA1\u6838\uFF09";
+ enterpriseName = "锛堝師鏁版嵁宸查噸鏂板鍏ワ紝璇烽噸鏂版墽琛屽鏍革級";
}
result.setEnterpriseName(enterpriseName);
result.setVerifyExplanation(explainMap.get(result.getReportId()));
}
}
-
/** 鏈�杩戞湁鏁版嵁鐨勬姤琛ㄦ湡锛堢敤浜庡墠绔粯璁ら�変腑锛� */
public String latestPeriod(String reportType) {
String type = reportType == null || reportType.trim().isEmpty() ? "H2032" : reportType.trim();
- String max = null;
switch (type) {
case "H2031":
- for (PassengerEnterpriseMonthly m : passengerMapper.selectList(
- new LambdaQueryWrapper<PassengerEnterpriseMonthly>().select(PassengerEnterpriseMonthly::getReportPeriod))) {
- max = maxPeriod(max, m.getReportPeriod());
- }
- break;
+ return firstOf(passengerMapper.selectObjs(new LambdaQueryWrapper<PassengerEnterpriseMonthly>()
+ .select(PassengerEnterpriseMonthly::getReportPeriod)
+ .orderByDesc(PassengerEnterpriseMonthly::getReportPeriod).last("LIMIT 1")));
case "H204":
- for (EnergyVehicleQuarterly m : energyMapper.selectList(
- new LambdaQueryWrapper<EnergyVehicleQuarterly>().select(EnergyVehicleQuarterly::getReportPeriod))) {
- max = maxPeriod(max, m.getReportPeriod());
- }
- break;
+ return firstOf(energyMapper.selectObjs(new LambdaQueryWrapper<EnergyVehicleQuarterly>()
+ .select(EnergyVehicleQuarterly::getReportPeriod)
+ .orderByDesc(EnergyVehicleQuarterly::getReportPeriod).last("LIMIT 1")));
case "INVEST":
- for (InvestmentMonthly m : investMonthlyMapper.selectList(
- new LambdaQueryWrapper<InvestmentMonthly>().select(InvestmentMonthly::getReportPeriod))) {
- max = maxPeriod(max, m.getReportPeriod());
- }
- break;
+ return firstOf(investMonthlyMapper.selectObjs(new LambdaQueryWrapper<InvestmentMonthly>()
+ .select(InvestmentMonthly::getReportPeriod)
+ .orderByDesc(InvestmentMonthly::getReportPeriod).last("LIMIT 1")));
case "CITY_BUS":
- for (CityBusMonthly m : cityBusMapper.selectList(
- new LambdaQueryWrapper<CityBusMonthly>().select(CityBusMonthly::getReportPeriod))) {
- max = maxPeriod(max, m.getReportPeriod());
- }
- break;
+ return firstOf(cityBusMapper.selectObjs(new LambdaQueryWrapper<CityBusMonthly>()
+ .select(CityBusMonthly::getReportPeriod)
+ .orderByDesc(CityBusMonthly::getReportPeriod).last("LIMIT 1")));
case "CITY_TAXI":
- for (CityTaxiMonthly m : cityTaxiMapper.selectList(
- new LambdaQueryWrapper<CityTaxiMonthly>().select(CityTaxiMonthly::getReportPeriod))) {
- max = maxPeriod(max, m.getReportPeriod());
- }
- break;
+ return firstOf(cityTaxiMapper.selectObjs(new LambdaQueryWrapper<CityTaxiMonthly>()
+ .select(CityTaxiMonthly::getReportPeriod)
+ .orderByDesc(CityTaxiMonthly::getReportPeriod).last("LIMIT 1")));
default:
- for (H2032EnterpriseMonthly m : h2032Mapper.selectList(
- new LambdaQueryWrapper<H2032EnterpriseMonthly>().select(H2032EnterpriseMonthly::getReportPeriod))) {
- max = maxPeriod(max, m.getReportPeriod());
- }
- break;
+ return firstOf(h2032Mapper.selectObjs(new LambdaQueryWrapper<H2032EnterpriseMonthly>()
+ .select(H2032EnterpriseMonthly::getReportPeriod)
+ .orderByDesc(H2032EnterpriseMonthly::getReportPeriod).last("LIMIT 1")));
}
- return max;
+ }
+
+ private String firstOf(List<Object> objs) {
+ if (objs == null || objs.isEmpty() || objs.get(0) == null) return null;
+ String v = String.valueOf(objs.get(0));
+ return v.trim().isEmpty() ? null : v.trim();
}
private String maxPeriod(String a, String b) {
@@ -1403,24 +1391,29 @@
return a;
}
- /** 瀹℃牳缁撴灉瀵煎嚭 Excel锛堝惈浼佷笟鍚�/瑙勫垯鍚�/鐘舵��/瀹℃牳鎰忚锛� */
+ /** 瀹℃牳缁撴灉瀵煎嚭 Excel锛堜袱 Sheet锛屾寜涓氬姟妯℃澘锛夛細Sheet1 瀹℃牳缁撴灉锛堥�愭潯鏄庣粏锛夛紱Sheet2 浼佷笟鍚堝苟锛堟寜浼佷笟姹囨�� + 闂鍒楋級 */
public byte[] exportResults(String reportPeriod, String reportType) throws Exception {
+ return exportResults(reportPeriod, reportType, true, "all");
+ }
+
+ /** onlyVerify=true 鏃跺墧闄も�滄彁閱掑瀷鈥濊鍒欙紙濡� RULE_004 鐜瘮鎻愰啋锛夛紝鍙繚鐣欐牳瀹炲瀷闂锛泂tatus=all/pending/handled 涓庣晫闈⑩�滅姸鎬佲�濈瓫閫変竴鑷� */
+ public byte[] exportResults(String reportPeriod, String reportType, boolean onlyVerify, String status) throws Exception {
List<AuditResult> results = queryResults(reportPeriod, reportType);
+ java.util.List<AuditResult> filtered = new java.util.ArrayList<>();
+ String st = status == null ? "all" : status.trim();
+ for (AuditResult res : results) {
+ if (onlyVerify && isReminderRule(res.getRuleCode())) continue;
+ if ("pending".equals(st) && !"PENDING".equals(res.getStatus())) continue;
+ if ("handled".equals(st) && (res.getStatus() == null || "PENDING".equals(res.getStatus()))) continue;
+ filtered.add(res);
+ }
try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ // ---------- Sheet1 瀹℃牳缁撴灉锛堥�愭潯锛屽垪涓庝笟鍔℃ā鏉夸竴鑷达級 ----------
Sheet sheet = wb.createSheet("瀹℃牳缁撴灉");
String[] headers = {"鎶ヨ〃鏈�", "浼佷笟/甯傚窞", "瑙勫垯缂栫爜", "瀹℃牳瑙勫垯", "绛夌骇", "瀹為檯鍊�", "闃堝��/鍩哄噯", "鍋忓樊璇存槑", "鐘舵��", "瀹℃牳鎰忚"};
- Row head = sheet.createRow(0);
- for (int i = 0; i < headers.length; i++) {
- Cell cell = head.createCell(i);
- cell.setCellValue(headers[i]);
- org.apache.poi.ss.usermodel.CellStyle style = wb.createCellStyle();
- org.apache.poi.ss.usermodel.Font font = wb.createFont();
- font.setBold(true);
- style.setFont(font);
- cell.setCellStyle(style);
- }
+ writeAuditHeader(sheet, headers);
int r = 1;
- for (AuditResult res : results) {
+ for (AuditResult res : filtered) {
Row row = sheet.createRow(r++);
row.createCell(0).setCellValue(valueOf(res.getReportPeriod()));
row.createCell(1).setCellValue(valueOf(res.getEnterpriseName()));
@@ -1437,10 +1430,154 @@
for (int i = 0; i < widths.length; i++) {
sheet.setColumnWidth(i, widths[i] * 256);
}
+
+ // ---------- Sheet2 浼佷笟鍚堝苟锛堝悓涓�浼佷笟澶氭潯瑙勫垯骞舵帓鍒楀嚭 + 闂姹囨�诲垪锛� ----------
+ Sheet ms = wb.createSheet("浼佷笟鍚堝苟");
+ String[] h2 = {"鎶ヨ〃鏈�", "浼佷笟/甯傚窞", "瀹℃牳瑙勫垯", "瀹為檯鍊�", "闃堝��/鍩哄噯", "鍋忓樊璇存槑", "闂"};
+ writeAuditHeader(ms, h2);
+ java.util.LinkedHashMap<String, java.util.List<AuditResult>> groups = new java.util.LinkedHashMap<>();
+ for (AuditResult res : filtered) {
+ String key = valueOf(res.getEnterpriseName());
+ if (key.isEmpty()) key = valueOf(res.getReportPeriod()) + "#" + valueOf(res.getActualValue());
+ groups.computeIfAbsent(key, k -> new java.util.ArrayList<>()).add(res);
+ }
+ int rowCursor = 1;
+ for (java.util.Map.Entry<String, java.util.List<AuditResult>> e : groups.entrySet()) {
+ java.util.List<AuditResult> items = e.getValue();
+ int groupStart = rowCursor;
+ StringBuilder problems = new StringBuilder();
+ int seq = 0;
+ for (AuditResult it : items) {
+ Row row = ms.createRow(rowCursor++);
+ if (seq == 0) {
+ row.createCell(0).setCellValue(valueOf(it.getReportPeriod()));
+ row.createCell(1).setCellValue(valueOf(it.getEnterpriseName()).isEmpty() ? e.getKey() : valueOf(it.getEnterpriseName()));
+ }
+ row.createCell(2).setCellValue(valueOf(it.getRuleName()));
+ row.createCell(3).setCellValue(valueOf(it.getActualValue()));
+ row.createCell(4).setCellValue(valueOf(it.getThresholdValue()));
+ row.createCell(5).setCellValue(valueOf(it.getDeviation()));
+ seq++;
+ if (problems.length() > 0) problems.append("\n");
+ problems.append(seq).append("銆�").append(issueSentence(it));
+ }
+ if (rowCursor - groupStart > 1) {
+ ms.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(groupStart, rowCursor - 1, 1, 1));
+ ms.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(groupStart, rowCursor - 1, 6, 6));
+ }
+ Row first = ms.getRow(groupStart);
+ if (first.getCell(6) == null) first.createCell(6);
+ first.getCell(6).setCellValue(problems.toString());
+ }
+ int[] widths2 = {12, 30, 22, 34, 22, 34, 60};
+ for (int i = 0; i < widths2.length; i++) {
+ ms.setColumnWidth(i, widths2[i] * 256);
+ }
ByteArrayOutputStream out = new ByteArrayOutputStream();
wb.write(out);
return out.toByteArray();
}
+ }
+
+ private void writeAuditHeader(Sheet sheet, String[] headers) {
+ Row head = sheet.createRow(0);
+ for (int i = 0; i < headers.length; i++) {
+ Cell cell = head.createCell(i);
+ cell.setCellValue(headers[i]);
+ org.apache.poi.ss.usermodel.CellStyle style = sheet.getWorkbook().createCellStyle();
+ org.apache.poi.ss.usermodel.Font font = sheet.getWorkbook().createFont();
+ font.setBold(true);
+ style.setFont(font);
+ cell.setCellStyle(style);
+ }
+ }
+
+ /** 鎻愰啋鍨嬭鍒欙細浠呮彁绀哄彉鍖栥�佷笉闇�浜哄伐鏍稿疄锛堝 RULE_004 璐ц繍绫诲瀷鐜瘮鎻愰啋锛� */
+ private boolean isReminderRule(String ruleCode) {
+ return "RULE_004".equals(ruleCode);
+ }
+
+ /** 浼佷笟鍚堝苟鈥滈棶棰樷�濆垪璇濇湳锛氭寜瑙勫垯绫诲瀷鐢熸垚鍙鐨勬牳瀹炴剰瑙� */
+ private String issueSentence(AuditResult res) {
+ String code = res.getRuleCode();
+ String name = valueOf(res.getRuleName());
+ String act = valueOf(res.getActualValue());
+ if ("RULE_001".equals(code) || "RULE_002".equals(code)) {
+ return "浼佷笟涓婃姤杞﹁締/鍚ㄤ綅涓庤繍鏀挎暟鎹姣斿瓨鍦ㄥ樊寮傦紙" + act + "锛夛紝璇锋牳瀹�";
+ }
+ if ("RULE_003".equals(code)) {
+ return "涓婃姤鍛ㄨ浆閲忎笌杞ㄨ抗娴嬬畻鍛ㄨ浆閲忓樊寮傛槑鏄撅紙" + act + "锛夛紝璇峰弬鑰冭建杩规牳瀹炰紒涓氬懆杞噺";
+ }
+ if ("RULE_004".equals(code)) {
+ return "璐ц繍绫诲瀷鐜瘮鍙戠敓鍙樺寲" + (act.isEmpty() ? "" : "锛�" + act + "锛�") + "锛岃鍏虫敞鏄惁濉姤姝e父";
+ }
+ if ("RULE_005".equals(code)) {
+ return "鏃犻泦瑁呯杞︿絾瀛樺湪闆嗚绠辫揣杩愰噺锛�" + act + "锛夛紝璇锋牳瀹炶溅杈嗙被鍨嬩笌璐ц繍閲忓~鎶�";
+ }
+ if ("RULE_006".equals(code)) {
+ return "鏁磋溅骞冲潎鍚ㄤ綅瓒呭嚭鍚堢悊鑼冨洿锛�" + act + "锛夛紝璇锋牳瀹炲钩鍧囧惃浣嶅~鎶�";
+ }
+ if (code != null && code.startsWith("RULE_P")) {
+ String special = passengerIssueSentence(res);
+ if (special != null) return special;
+ }
+ return name + "寮傚父锛�" + act + "锛夛紝璇锋牳瀹�";
+ }
+
+ /** 瀹㈣繍锛圚2031锛夎鍒欓棶棰樿瘽鏈細璐村悎妯℃澘绀轰緥鈥滄牳瀹炲紓甯革紙涓婃湡鎸囨爣=锛屾湰鏈熸寚鏍�=锛夎鏍稿疄鈥� */
+ private String passengerIssueSentence(AuditResult res) {
+ String code = res.getRuleCode();
+ String act = valueOf(res.getActualValue());
+ if ("RULE_P003".equals(code) || "RULE_P004".equals(code)) {
+ boolean turnover = "RULE_P004".equals(code);
+ String inner = act;
+ if (inner.startsWith("鏈湀涓庝笂鏈堢浉鍚�: ")) {
+ inner = inner.substring("鏈湀涓庝笂鏈堢浉鍚�: ".length());
+ }
+ java.util.List<String> clauses = new java.util.ArrayList<>();
+ for (String item : inner.split("銆�")) {
+ int eq = item.indexOf('=');
+ if (eq <= 0) { clauses.add(item); continue; }
+ String label = item.substring(0, eq).trim();
+ String v = item.substring(eq + 1).trim();
+ clauses.add("涓婃湀" + (turnover ? "鍛ㄨ浆閲�" : "瀹㈣繍閲�") + "=" + v + "锛屾湰鏈�" + label + "=" + v);
+ }
+ return valueOf(res.getRuleName()) + "寮傚父锛�" + String.join("锛�", clauses) + "锛夎鏍稿疄";
+ }
+ if ("RULE_P005".equals(code)) {
+ String pct = extractPct(valueOf(res.getThresholdValue()));
+ String prefix = pct.isEmpty() ? "鐝嚎骞冲潎杩愯窛鐜瘮瓒呴檺" : "鐝嚎骞冲潎杩愯窛鐜瘮瓒吢�" + pct + "%";
+ return prefix + "锛屾甯哥彮绾胯繍璺濆湪绾胯矾鏈彂鐢熼噸澶у彉鍖栧墠杈冧负绋冲畾锛�" + act + "锛夛紝璇锋牳瀹�";
+ }
+ if ("RULE_P006".equals(code)) {
+ String inner = act;
+ if (inner.startsWith("绛変簬涓婃湀: ")) {
+ inner = inner.substring("绛変簬涓婃湀: ".length());
+ }
+ java.util.List<String> clauses = new java.util.ArrayList<>();
+ for (String item : inner.split("銆�")) {
+ int eq = item.indexOf('=');
+ if (eq <= 0) { clauses.add(item); continue; }
+ String v = item.substring(eq + 1).trim();
+ clauses.add("涓婃湀杩愯窛=" + v + "锛屾湰鏈堣繍璺�=" + v);
+ }
+ return "鍖呰溅骞冲潎杩愯窛绛変簬涓婃湀锛�" + String.join("锛�", clauses)
+ + "锛夎鏍稿疄浼佷笟鏄惁鏄浐瀹氱嚎璺梾娓告垨鑰呴�氬嫟涓氬姟";
+ }
+ return null;
+ }
+
+ private String extractPct(String thresholdText) {
+ if (thresholdText == null || thresholdText.isEmpty()) return "";
+ int idx = thresholdText.indexOf('\u00b1');
+ if (idx < 0) return "";
+ StringBuilder num = new StringBuilder();
+ for (int i = idx + 1; i < thresholdText.length(); i++) {
+ char c = thresholdText.charAt(i);
+ if (Character.isDigit(c) || c == '.') num.append(c);
+ else if (!Character.isWhitespace(c)) break;
+ }
+ return num.toString();
}
private String auditStatusCn(String status) {
@@ -1569,6 +1706,8 @@
switch (rule.getCompareType()) {
case "DIFF":
return checkDiff(rule, report, authMap);
+ case "DIFF_FIELDS":
+ return checkDiffFields(rule, report, authMap);
case "RATIO":
return checkRatio(rule, report, authMap, trackMap);
case "MOM":
@@ -1609,6 +1748,86 @@
"宸窛鈮�" + fmt(threshold), "宸窛=" + fmt(diff));
}
return null;
+ }
+
+ /** RULE_001 鍒嗛」杩愭斂瀵规瘮锛氱壍寮曡溅/鎸傝溅/鏁磋溅杞﹁締鏁颁笌鎸傝溅鍚ㄤ綅/鏁磋溅鍚ㄤ綅/鎬诲惃浣嶅垎鍒笌杩愭斂瀵规瘮锛屼换涓�鍒嗛」瓒呴檺鍗虫彁閱� */
+ private AuditResult checkDiffFields(AuditRule rule, H2032EnterpriseMonthly report,
+ Map<String, TransportAuthVehicle> authMap) {
+ TransportAuthVehicle auth = findAuth(authMap, report.getEnterpriseName());
+ if (auth == null) return null;
+ String[] fields = rule.getCheckField() == null ? new String[0] : rule.getCheckField().split(",");
+ String[] limits = rule.getThreshold() == null ? new String[0] : rule.getThreshold().split("[,;|]");
+ if (fields.length == 0 || limits.length != fields.length) return null;
+ java.util.List<String> hits = new java.util.ArrayList<>();
+ double maxAbs = 0;
+ for (int i = 0; i < fields.length; i++) {
+ String field = fields[i].trim();
+ double limit;
+ try {
+ limit = Double.parseDouble(limits[i].trim());
+ } catch (Exception e) {
+ return null;
+ }
+ double actual;
+ double reference;
+ String unit;
+ switch (field) {
+ case "vehicleTractor":
+ actual = num(report.getVehicleTractor());
+ reference = num(auth.getTractorCount());
+ unit = "鍙�";
+ break;
+ case "vehicleTrailer":
+ actual = num(report.getVehicleTrailer());
+ reference = num(auth.getTrailerCount());
+ unit = "鍙�";
+ break;
+ case "tonsTrailer":
+ actual = nvl(report.getTonsTrailer());
+ reference = nvl(auth.getTrailerTons());
+ unit = "鍚�";
+ break;
+ case "vehicleWhole":
+ actual = num(report.getVehicleWhole());
+ reference = num(auth.getOtherCount());
+ unit = "鍙�";
+ break;
+ case "tonsWhole":
+ actual = nvl(report.getTonsWhole());
+ reference = nvl(auth.getOtherTons());
+ unit = "鍚�";
+ break;
+ case "tonsTotal":
+ actual = nvl(report.getTonsTotal());
+ reference = nvl(auth.getTrailerTons()) + nvl(auth.getOtherTons());
+ unit = "鍚�";
+ break;
+ default:
+ return null;
+ }
+ double diff = Math.abs(actual - reference);
+ maxAbs = Math.max(maxAbs, diff);
+ if (diff > limit) {
+ hits.add(h2032FieldLabel(field) + "锛氫笂鎶�=" + fmt(actual) + " " + unit + "锛岃繍鏀�=" + fmt(reference) + " " + unit
+ + "锛屽樊" + fmt(diff) + " " + unit + "锛堥檺" + fmt(limit) + " " + unit + "锛�");
+ }
+ }
+ if (hits.isEmpty()) return null;
+ StringBuilder detail = new StringBuilder();
+ for (int i = 0; i < hits.size(); i++) {
+ String one = hits.get(i);
+ if (detail.length() == 0) {
+ detail.append(one);
+ } else if (detail.length() + one.length() + 1 <= 180) {
+ detail.append("锛�").append(one);
+ } else {
+ detail.append("锛涚瓑").append(hits.size() - i).append("椤硅秴闄�");
+ break;
+ }
+ }
+ return buildResult(rule, report, detail.toString(),
+ "鐗靛紩杞�/鎸傝溅/鏁磋溅杞﹁締宸墹5鍙帮紱鎸傝溅鍚ㄤ綅/鏁磋溅鍚ㄤ綅宸墹50鍚紱鎬诲惃浣嶅樊鈮�50鍚�",
+ "瓒呭嚭椤规暟=" + hits.size() + "锛屾渶澶у樊=" + fmt(maxAbs));
}
/** 涓婃姤鍛ㄨ浆閲忎笌杞ㄨ抗娴嬬畻鍛ㄨ浆閲忓姣旓紝楂樺嚭闃堝�兼瘮渚嬫牳瀹� */
@@ -1804,6 +2023,10 @@
labels.put("tonsWhole", "鏁磋溅鍚ㄤ綅");
labels.put("turnoverTotal", "鍛ㄨ浆閲�");
labels.put("vehicleWhole", "鏁磋溅杞﹁締鏁�");
+ labels.put("vehicleTractor", "鐗靛紩杞︽暟");
+ labels.put("vehicleTrailer", "鎸傝溅鏁�");
+ labels.put("tonsTrailer", "鎸傝溅鍚ㄤ綅");
+ labels.put("tonsWhole", "鏁磋溅鍚ㄤ綅");
String v = labels.get(field);
return v == null ? field : v;
}
--
Gitblit v1.9.1