fix: 整车吨位按平均吨位口径审核、提示数字去科学计数;拆分导入按目标期取月页签(重导04-06验证);数据查看全屏可翻页 + 测试报告
4个文件已修改
1个文件已添加
118 ■■■■■ 已修改文件
docs/功能测试报告/功能测试报告_审核平均吨位口径与拆分目标月导入及全屏翻页_2026-09-04.md 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/生成汇总大表/数据导入现状与缺口清单_2026-09-04.md 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-web/src/views/DataView.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_ÉóºËƽ¾ù¶Öλ¿Ú¾¶Óë²ð·ÖÄ¿±êÔµ¼Èë¼°È«ÆÁ·­Ò³_2026-09-04.md
New file
@@ -0,0 +1,22 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Šï¼šå®¡æ ¸å…¬å¼ä¿®æ­£ + æ‹†åˆ†ç›®æ ‡æœˆå¯¼å…¥ + å…¨å±ç¿»é¡µï¼ˆ2026-09-04)
## ä¸€ã€è´§è¿å®¡æ ¸ RULE_006:整车吨位改为“平均吨位”口径
- æ”¹åŠ¨ï¼š`AuditEngineService.checkOutRange` å¯¹ `tonsWhole` å­—段按“整车平均吨位 = æ•´è½¦å¨ä½(tonsWhole) / æ•´è½¦è½¦è¾†æ•°(vehicleWhole)”计算后与 4~40 æ¯”较;无整车数时退回原值判断。`h2032FieldLabel` ä¸å˜ï¼Œæç¤ºæ–‡æœ¬æ˜¾å¼æ ‡â€œæ•´è½¦å¹³å‡å¨ä½(整车吨位/整车数)”。
- åŽŸå› ï¼šåŽŸé€»è¾‘ç›´æŽ¥æ‹¿æ•´è½¦å¨ä½æ€»é‡ï¼ˆå¦‚é»„å†ˆå¯ç¨‹ç‰©æµ 357 å¨ï¼Œ23 è¾†æ•´è½¦ï¼‰æ¯” 4~40,把总量当单均误报。
- éªŒè¯ï¼šé‡æ–°æ‰§è¡Œ 2026-07 H2032 å®¡æ ¸ï¼ˆPOST /api/audit/execute),RULE_006 å‘½ä¸­ 8 æ¡ä¸”全部为“整车平均吨位=0.92~3.93,范围 4~40”(黄冈启程 357/23≈15.52 ä¸å†å‘½ä¸­ï¼‰ï¼›å…¶ä½™è§„则正常(RULE_001 59、RULE_002 106、RULE_004 6、RULE_005 21、RULE_003 0)。结论 PASS。
## äºŒã€å®¡æ ¸æç¤ºæ•°å­—不再用科学计数法
- æ”¹åŠ¨ï¼š`fmt`/`fmt4` ç”¨ BigDecimal.toPlainString è¾“出,大数如 1.04e7 æ˜¾ç¤ºä¸º 10435762.52 è€Œä¸æ˜¯ 1.043576252E7。
- éªŒè¯ï¼šé‡å¯¼åŽ 2026-07 å®¡æ ¸æ–‡æœ¬å‡ä¸ºæ™®é€šåè¿›åˆ¶æ˜¾ç¤ºï¼›ç¼–译通过。结论 PASS。
## ä¸‰ã€è§„上规下拆分导入:按目标报表期只取对应月页签
- æ”¹åŠ¨ï¼š`DataImportService.importScaleSplit` å¢žåŠ ç›®æ ‡æœˆï¼ˆperiod çš„æœˆä»½ï¼‰è¿‡æ»¤ï¼šé¡µç­¾å½¢å¦‚“{M}月累计/M月份”只在该 M=目标月时导入(M月累计→CUMULATIVE、M月份→MONTH);页签为“当月/累计”(模板样式)不限定月。
- åŽŸå› ï¼š1-N æœˆæ•´åŒ…文件被整导会把多个月页签塞进同一报表期造成重复行(此前 04-07 åˆ†åˆ« 72/90/108/126 è¡Œå³ä¸ºæ­¤ç±»è„æ•°æ®ï¼‰ã€‚
- éªŒè¯ï¼ˆç«¯åˆ°ç«¯ï¼‰ï¼šç”¨ã€Š2026å¹´1-6月公路货运量(分市州).xlsx》重导 2026-04/05/06,每期返回“36 æ¡è®°å½•”=当月 18 + ç´¯è®¡ 18;库内每期按 region å”¯ä¸€ï¼›æ­¦æ±‰ 2026-06 å½“月合计周转量 687103.88 ä¸Žæºæ–‡ä»¶é€å€¼ä¸€è‡´ï¼›2026-07 æ—§ 126 è¡Œç´¯è®¡æ•°æ®å¾…用 1-7 æœˆæ–‡ä»¶é‡å¯¼ä¸€æ¬¡å³æ”¶æ•›ä¸º 36 è¡Œã€‚结论 PASS。
## å››ã€æ•°æ®æŸ¥çœ‹å…¨å±æ¨¡å¼å¯ç¿»é¡µï¼ˆå‰ç«¯ï¼‰
- æ”¹åŠ¨ï¼š`DataView.vue` æŠŠè¡¨æ ¼ä¸Žå…¶ä¸‹åˆ†é¡µå™¨åŒ…进同一 `.table-wrap`,全屏目标从 `.table-area` æ”¹ä¸º `.table-wrap`,并加全屏 flex å¸ƒå±€æ ·å¼ï¼Œå…¨å±æ—¶ä¿ç•™åˆ†é¡µæ¡ã€‚
- éªŒè¯ï¼šæ¨¡æ¿ç»“æž„/逻辑调整编译由 vue-cli-service çƒ­æ›´æ–°ï¼›æµè§ˆå™¨ç«¯éœ€ç”¨æˆ·å…¨å±æŸ¥çœ‹ç¡®è®¤ï¼ˆè¡¨æ ¼+分页可见、可翻页)。结论:代码就绪,待人工视觉确认。
## çŽ¯å¢ƒ
- åŽç«¯ 8090(多次重启至最新代码,最后一次 16:51 å°±ç»ªï¼‰ï¼›å‰ç«¯ 8080 è¿è¡Œä¸­ï¼›MySQL 127.0.0.1:3308。
docs/Éú³É»ã×Ü´ó±í/Êý¾Ýµ¼ÈëÏÖ×´Óëȱ¿ÚÇåµ¥_2026-09-04.md
@@ -65,3 +65,12 @@
3. æ¯ç‰ˆæŒ‰â€œæ•°æ®å’Œå…¬å¼æ”¹å¯¹åŽä½œä¸ºæ¯ç‰ˆâ€å¤„理(拍板第 5 æ¡ï¼Œå³ä½“检清单方案 A ä¿®æ­£ï¼‰ã€‚
4. ç‹¬ç«‹å°è¡¨ä¿ç•™ä¸åˆ ï¼ˆæ‹æ¿ç¬¬ 1 æ¡ï¼‰ï¼Œå¾…大表验证通过后再议下线。
5. å…è®¸é‡å¤å¯¼å…¥å·²ç”Ÿæ•ˆï¼ˆæŒ‰æŠ¥è¡¨æœŸå…ˆåˆ åŽæ’,拍板第 3 æ¡ï¼‰ã€‚
---
## æ›´æ–°è®°å½•(2026-09-04 ä¸‹åˆ ç”¨æˆ·ç­”复后)
- å…¬äº¤/出租/个体客运/H203-1 å·²è¡¥å¯¼ï¼š2026-01~07(H203-1 è‡³ 08)现已全齐;投资模块暂不纳入本次范围(用户答复)。
- è´§è¿é‡å‘¨è½¬é‡ï¼š2026-02 å·²æœ‰å¯¼å…¥è¡Œï¼›ç”¨æˆ·ç­”复“7月表格已含 1-7 æœˆæ¯æœˆæ•°æ®â€ä¸”已重新导入(2026-04~07 åœ¨åº“,01、03 æ— ç‹¬ç«‹è¡Œä½† 07 è¡Œå†…嵌各月列值,取数时按 m01~m07 ä½¿ç”¨ï¼‰ã€‚
- è§„上规下拆分导入已升级为“按目标报表期取页签”(只导入 {目标月}月份/{目标月}累计,不再把 1-N æœˆå…¨éƒ¨é¡µç­¾å¡žè¿›åŒä¸€æœŸï¼‰ï¼Œå¹¶å·²ç”¨ã€Š2026å¹´1-6月公路货运量(分市州).xlsx》重导 2026-04/05/06 éªŒè¯ï¼šæ¯æœŸ = å½“月 18 è¡Œ + ç´¯è®¡ 18 è¡Œï¼Œæ­¦æ±‰ 6 æœˆå½“月合计周转量 687103.88 ä¸Žæºæ–‡ä»¶ä¸€è‡´ã€‚2026-07 ç›®å‰ä»ä¸ºæ—§æ•°æ®ï¼ˆ126 è¡Œç´¯è®¡ï¼‰ï¼Œå¾…用《2026å¹´1-7月公路货运量(分市州).xlsx》重导一次即可变干净(36 è¡Œï¼‰ã€‚
- è§„上规下拆分 2026-01~03 ä»ç©ºï¼šå¯å¤ç”¨ã€Š2026å¹´1-6月公路货运量(分市州)》等文件,导入页选报表期 01/02/03 å³å¯ï¼ˆç¨‹åºåªå–对应月页签),或用各月自己的定稿文件。
- åŽŸâ€œä¸ªä½“å®¢è¿ 2026-05 æ–‡ä»¶åä¸º (2026.3)”疑点已澄清:文件名写错、内容为 6 æœˆæ•°æ®ï¼Œå·²ä¿®æ”¹åŽå¯¼å…¥ï¼ˆ06 çŽ°æœ‰ 7 è¡Œï¼‰ã€‚
traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
@@ -1679,15 +1679,29 @@
        return null;
    }
    /** æ•°å€¼èŒƒå›´æ£€æŸ¥ï¼ˆå¦‚ æ•´è½¦å¨ä½ 4≤且≤40) */
    /** æ•°å€¼èŒƒå›´æ£€æŸ¥ï¼›æ•´è½¦å¨ä½æŒ‰â€œå¹³å‡å¨ä½=整车吨位/整车数”口径判定 4~40 */
    private AuditResult checkOutRange(AuditRule rule, H2032EnterpriseMonthly report) {
        String[] bounds = rule.getThreshold().split(",");
        if (bounds.length < 2) return null;
        double value = getH2032FieldValue(report, rule.getCheckField());
        String field = rule.getCheckField();
        String label = h2032FieldLabel(field);
        double value;
        if ("tonsWhole".equals(field)) {
            double vehicles = report.getVehicleWhole() == null ? 0.0 : report.getVehicleWhole().doubleValue();
            double tons = nvl(report.getTonsWhole());
            if (vehicles > 0) {
                value = tons / vehicles;
                label = "整车平均吨位(整车吨位/整车数)";
            } else {
                value = tons; // æ— æ•´è½¦æ•°ä½†æœ‰å¨ä½æ—¶ä»æŒ‰åŽŸå¨ä½åˆ¤å®š
            }
        } else {
            value = getH2032FieldValue(report, field);
        }
        double low = Double.parseDouble(bounds[0].trim());
        double high = Double.parseDouble(bounds[1].trim());
        if (value > 0 && (value < low || value > high)) {
            return buildResult(rule, report, h2032FieldLabel(rule.getCheckField()) + "=" + fmt(value),
            return buildResult(rule, report, label + "=" + fmt(value),
                "范围 " + fmt(low) + "~" + fmt(high), "超出范围");
        }
        return null;
@@ -1805,18 +1819,20 @@
    }
    private String fmt(double v) {
        if (v == Math.floor(v) && !Double.isInfinite(v)) {
        if (v == Math.floor(v) && !Double.isInfinite(v) && Math.abs(v) < 1e15) {
            return String.valueOf((long) v);
        }
        return String.valueOf(Math.round(v * 100.0) / 100.0);
        return java.math.BigDecimal.valueOf(v).setScale(2, java.math.RoundingMode.HALF_UP)
            .stripTrailingZeros().toPlainString();
    }
    /** å æ¯”/小数值:保留 4 ä½å°æ•° */
    private String fmt4(double v) {
        if (v == Math.floor(v) && !Double.isInfinite(v)) {
        if (v == Math.floor(v) && !Double.isInfinite(v) && Math.abs(v) < 1e15) {
            return String.valueOf((long) v);
        }
        return String.valueOf(Math.round(v * 10000.0) / 10000.0);
        return java.math.BigDecimal.valueOf(v).setScale(4, java.math.RoundingMode.HALF_UP)
            .stripTrailingZeros().toPlainString();
    }
    // ========== H2031 æ—…客审核 ==========
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -924,6 +924,7 @@
        List<ScaleSplitTransport> list = new ArrayList<>();
        int failRows = 0;
        try (Workbook wb = WorkbookFactory.create(file.getInputStream())) {
            int targetMonth = Integer.parseInt(period.split("-")[1]); // ä»…导入目标期所在月的页签(1-N月文件按目标期取当月/累计)
            boolean hasPeriodSheet = false;
            for (int i = 0; i < wb.getNumberOfSheets(); i++) {
                String sn = wb.getSheetAt(i).getSheetName();
@@ -936,8 +937,16 @@
                Sheet sheet = wb.getSheetAt(i);
                String sheetName = sheet.getSheetName();
                String periodType = null;
                if (sheetName.contains("当月") || sheetName.contains("月份")) periodType = "MONTH";
                else if (sheetName.contains("累计")) periodType = "CUMULATIVE";
                java.util.regex.Matcher mSheetMonth = java.util.regex.Pattern.compile("(\\d{1,2})\\u6708(\\u4efd|\\u7d2f\\u8ba1)").matcher(sheetName);
                if (mSheetMonth.find()) {
                    int sheetMonth = Integer.parseInt(mSheetMonth.group(1));
                    if (sheetMonth == targetMonth) {
                        periodType = "份".equals(mSheetMonth.group(2)) ? "MONTH" : "CUMULATIVE";
                    }
                } else {
                    if (sheetName.contains("当月")) periodType = "MONTH";
                    else if (sheetName.contains("累计")) periodType = "CUMULATIVE";
                }
                if (periodType == null) continue;
                // æ ¡éªŒ sheet å¸ƒå±€ï¼šç¬¬2行应含「市州/规上企业运输量」,第3行子表头应含「周转量」或「货运量」(扩展布局)
traffic-audit-web/src/views/DataView.vue
@@ -45,20 +45,22 @@
        <div style="color:#909399;font-size:12px;margin-bottom:6px">
          å…± {{ total }} æ¡è®°å½•,当前第 {{ page }} é¡µ
        </div>
        <div class="table-area" ref="tableArea">
        <el-table :data="records" border v-loading="loading" size="small" style="width:100%" height="100%">
          <el-table-column v-for="c in columns" :key="c.prop" :prop="c.prop" :label="c.label" :min-width="c.width" show-overflow-tooltip>
            <template slot-scope="scope">
              <span>{{ formatCell(scope.row[c.prop]) }}</span>
            </template>
          </el-table-column>
        </el-table>
        <div class="table-wrap" ref="tableWrap">
          <div class="table-area">
            <el-table :data="records" border v-loading="loading" size="small" style="width:100%" height="100%">
              <el-table-column v-for="c in columns" :key="c.prop" :prop="c.prop" :label="c.label" :min-width="c.width" show-overflow-tooltip>
                <template slot-scope="scope">
                  <span>{{ formatCell(scope.row[c.prop]) }}</span>
                </template>
              </el-table-column>
            </el-table>
          </div>
          <el-pagination style="margin-top:15px;text-align:right"
            background layout="total, prev, pager, next, sizes"
            :total="total" :current-page.sync="page" :page-size.sync="size"
            :page-sizes="[20, 50, 100]" @current-change="loadData" @size-change="loadData">
          </el-pagination>
        </div>
        <el-pagination style="margin-top:15px;text-align:right"
          background layout="total, prev, pager, next, sizes"
          :total="total" :current-page.sync="page" :page-size.sync="size"
          :page-sizes="[20, 50, 100]" @current-change="loadData" @size-change="loadData">
        </el-pagination>
      </el-main>
    </el-container>
  </el-container>
@@ -110,7 +112,7 @@
      })
    },
    toggleFullscreen() {
      const el = this.$refs.tableArea
      const el = this.$refs.tableWrap
      if (!document.fullscreenElement) {
        if (el && el.requestFullscreen) el.requestFullscreen()
        else this.$message.warning("浏览器不支持全屏")
@@ -139,4 +141,18 @@
  background: #fff;
  overflow: auto;
}
#app .table-wrap:fullscreen {
  padding: 20px;
  background: #fff;
  overflow: auto;
  display: flex;
  flex-direction: column;
}
#app .table-wrap:fullscreen .table-area {
  flex: 1 1 auto;
  min-height: 0;
}
#app .table-wrap:fullscreen .el-pagination {
  flex: none;
}
</style>