feat: 城市客运导入新增网约车总数/网约车订单及全省总量两母版导入 + 09-04 测试报告
3个文件已修改
1 文件已重命名
7个文件已添加
375 ■■■■■ 已修改文件
docs/sql_wyc.sql 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/功能测试报告/功能测试报告_城市客运网约车导入下拉_2026-09-04.md 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/城市客运/模板_网约车总数.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
docs/城市客运/模板_网约车订单及全省总量.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/entity/WycOrderMonthly.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/entity/WycTotalMonthly.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/mapper/WycOrderMonthlyMapper.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/mapper/WycTotalMonthlyMapper.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-web/src/views/DataImport.vue 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/sql_wyc.sql
New file
@@ -0,0 +1,45 @@
-- åŸŽå¸‚客运网约车月度输入建表(2026-09-04)
-- æ•°æ®æº1:模板_网约车总数.xlsx(月度全省 pin:客运量/其中城市内/周转量/其中城市内周转量)
-- æ•°æ®æº2:模板_网约车订单及全省总量.xlsx(月度输入页:B-E å…¨çœ pin + F è®¢å•合计 + G-W 17市州订单)
CREATE TABLE IF NOT EXISTS wyc_total_monthly (
  id BIGINT NOT NULL AUTO_INCREMENT,
  report_period VARCHAR(20) NOT NULL COMMENT '报表期 yyyy-MM',
  pin_k DOUBLE DEFAULT NULL COMMENT '全省网约车客运量(万人次)',
  pin_ck DOUBLE DEFAULT NULL COMMENT '其中城市内客运量',
  pin_z DOUBLE DEFAULT NULL COMMENT '全省客运周转量(万人公里)',
  pin_cz DOUBLE DEFAULT NULL COMMENT '其中城市内周转量',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uk_wyc_total_period (report_period)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='网约车月度全省 pin è¾“å…¥';
CREATE TABLE IF NOT EXISTS wyc_order_monthly (
  id BIGINT NOT NULL AUTO_INCREMENT,
  report_period VARCHAR(20) NOT NULL COMMENT '报表期 yyyy-MM',
  pin_k DOUBLE DEFAULT NULL,
  pin_ck DOUBLE DEFAULT NULL,
  pin_z DOUBLE DEFAULT NULL,
  pin_cz DOUBLE DEFAULT NULL,
  order_sum DOUBLE DEFAULT NULL COMMENT '订单合计(单)',
  order_wuhan DOUBLE DEFAULT NULL,
  order_huangshi DOUBLE DEFAULT NULL,
  order_shiyan DOUBLE DEFAULT NULL,
  order_yichang DOUBLE DEFAULT NULL,
  order_xiangyang DOUBLE DEFAULT NULL,
  order_ezhou DOUBLE DEFAULT NULL,
  order_jingmen DOUBLE DEFAULT NULL,
  order_xiaogan DOUBLE DEFAULT NULL,
  order_jingzhou DOUBLE DEFAULT NULL,
  order_huanggang DOUBLE DEFAULT NULL,
  order_xianning DOUBLE DEFAULT NULL,
  order_suizhou DOUBLE DEFAULT NULL,
  order_enshi DOUBLE DEFAULT NULL,
  order_xiantao DOUBLE DEFAULT NULL,
  order_qianjiang DOUBLE DEFAULT NULL,
  order_tianmen DOUBLE DEFAULT NULL,
  order_shennong DOUBLE DEFAULT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uk_wyc_order_period (report_period)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='网约车订单及全省总量月度输入';
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_³ÇÊпÍÔËÍøÔ¼³µµ¼ÈëÏÂÀ­_2026-09-04.md
New file
@@ -0,0 +1,35 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Šï¼šåŸŽå¸‚å®¢è¿å¯¼å…¥ä¸‹æ‹‰æ–°å¢žç½‘çº¦è½¦å¯¼å…¥ï¼ˆ2026-09-04)
## åŠŸèƒ½è¯´æ˜Ž
2026-09-04 ç”¨æˆ·æ‹æ¿ï¼šæ•°æ®å¯¼å…¥â€”—城市客运模块下拉增加《网约车总数》与《网约车订单及全省总量》两项,母版放于 docs/城市客运/。本次实现:
- åŽç«¯æ–°å¢žå¯¼å…¥æŽ¥å£ï¼šPOST /api/import/wycTotal、POST /api/import/wycOrder;
- æ–°å¢žè¡¨ wyc_total_monthly(全省 pin)与 wyc_order_monthly(pin + è®¢å•合计 + 17市州订单),按报表期先删后插、幂等 upsert,同时记录批次(WYC_TOTAL / WYC_ORDER)供导入进度与历史显示;
- å‰ç«¯ DataImport.vue:城市客运下拉新增两项、TYPE_LABELS / BATCH_TYPE_MAP、模板名/下载 URL(对应母版)、endpoint æ˜ å°„全部补齐。
代码改动(待推送):
- traffic-audit-server/src/main/java/com/trafficaudit/dataimport/entity/WycTotalMonthly.java、WycOrderMonthly.java(新增,@TableField å›ºå®š pin_ck/pin_cz åˆ—名)
- traffic-audit-server/src/main/java/com/trafficaudit/dataimport/mapper/WycTotalMonthlyMapper.java、WycOrderMonthlyMapper.java(新增)
- traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java(新增 importWycTotal/importWycOrder/upsertWyc/upsertWycTotal/periodOfCell/dbl/dblN åŠåˆ†å‘ case)
- traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java(新增两个端点)
- traffic-audit-web/src/views/DataImport.vue(下拉/标签/模板/端点)
- docs/sql_wyc.sql(建表 DDL æ²‰æ·€ï¼‰
## æµ‹è¯•环境
- åŽç«¯ 8090(重启后就绪);前端 dev server 8080(DataImport.vue æ”¹åŠ¨åŽçƒ­ç¼–è¯‘ Compiled successfully);MySQL 127.0.0.1:3308 traffic_audit;母版为 docs/城市客运/模板_网约车总数.xlsx、模板_网约车订单及全省总量.xlsx(实际编辑版,含 2026-01~07)。
- æ–¹æ³•:HTTP å®žé™…导入,与源文件逐项对齐、幂等重导、模板下载 URL、空数据负向用例。
## ç”¨ä¾‹ä¸Žç»“æžœ
1. ç½‘约车总数导入(正向):上传模板_网约车总数.xlsx,接口返回“导入成功,共 7 æœŸâ€ï¼›DB ä¸­ 2026-01~07 å…¨çœ pin B-E ä¸Žæ¯ç‰ˆé€æœŸä¸€è‡´ï¼ˆå¦‚ 2026-07 = 4852.3/4430.84/28348.02/22705.61)。结论 PASS。
2. ç½‘约车订单导入(正向):上传模板_网约车订单及全省总量.xlsx,共 7 æœŸï¼›2026-07 F=订单合计 29730791、G-W 17市州与母版一致(武汉 11183267…神农架 3534);2026-01~06 è®¢å•列为 NULL(母版无数据,正确)。结论 PASS。
3. å¹‚等重复导入(正向):同文件重复上传,两表数据仍各 7 è¡Œä¸”值不变(先删后插);批次表每次导入均记录。结论 PASS。
4. æ¨¡æ¿ä¸‹è½½ï¼ˆæ­£å‘):GET /api/templates/城市客运/模板_网约车总数.xlsx ä¸Ž è®¢å•版均 200。结论 PASS。
5. ç©ºæ•°æ®æ–‡ä»¶ï¼ˆè´Ÿå‘):上传只含表头的 xlsx,返回 code 500、提示“未识别到有效月份行:A åˆ—应为日期(如 2026-07)…”,错误文案清晰。结论 PASS(预期失败)。
6. ç¼–译与启动:后端 mvn compile EXIT=0;前端脚本 node --check é€šè¿‡ä¸” dev server çƒ­ç¼–译成功。结论 PASS。
## å‘现的问题与处置
1. æ–°å¢ž Mapper æŽ¥å£å°¾éƒ¨æ®‹ç•™â€œ{{}}”(抽象方法体)导致编译失败:已修为“{}”。
2. DataImportService.periodOfCell æ­£åˆ™ \d æœªè½¬ä¹‰ä¸º \\d(Java å­—符串“非法转义”编译失败):已修复。
3. é¦–次导入返回“共 0 æœŸâ€ï¼šåŽŸå› ä¸ºå®žä½“å­—æ®µ pinCK/pinCZ ä¸‹åˆ’线策略映射为 pin_c_k/pin_c_z,与表列 pin_ck/pin_cz ä¸åŒ¹é…ï¼Œinsert æŠ¥ Unknown column;处理:实体增加 @TableField("pin_ck")/@TableField("pin_cz"),复测后 7 æœŸå…¨éƒ¨å…¥åº“。
## ç»“论
城市客运导入下拉新增两项网约车导入功能已实现并通过测试:正向(实际母版 1-7 æœˆï¼‰ã€å¹‚等重导、模板下载、空数据负向均符合预期;入库数据与源文件逐项一致。前端下拉项还需用户在页面点击人工过一眼。
docs/³ÇÊпÍÔË/Ä£°å_ÍøÔ¼³µ×ÜÊý.xlsx
Binary files differ
docs/³ÇÊпÍÔË/Ä£°å_ÍøÔ¼³µ¶©µ¥¼°È«Ê¡×ÜÁ¿.xlsx
Binary files differ
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java
@@ -242,6 +242,33 @@
        }
    }
    /** ç½‘约车总数(月度全省 pin:模板_网约车总数.xlsx) */
    @PostMapping("/wycTotal")
    public Result<String> importWycTotal(@RequestParam("file") MultipartFile file,
                                         @RequestParam("period") String period) {
        try {
            int count = importService.importWycTotal(file, period);
            return Result.ok("网约车总数导入成功, å…± " + count + " æœŸ");
        } catch (Exception e) {
            log.error("wycTotal import error", e);
            return Result.error("导入失败: " + e.getMessage());
        }
    }
    /** ç½‘约车订单及全省总量(模板_网约车订单及全省总量.xlsx) */
    @PostMapping("/wycOrder")
    public Result<String> importWycOrder(@RequestParam("file") MultipartFile file,
                                         @RequestParam("period") String period) {
        try {
            int count = importService.importWycOrder(file, period);
            return Result.ok("网约车订单及全省总量导入成功, å…± " + count + " æœŸ");
        } catch (Exception e) {
            log.error("wycOrder import error", e);
            return Result.error("导入失败: " + e.getMessage());
        }
    }
    /** æŠ•资月报(全省汇总大表):category=客运站场/物流园区 */
    @PostMapping("/investment")
    public Result<String> importInvestment(@RequestParam("file") MultipartFile file,
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/entity/WycOrderMonthly.java
New file
@@ -0,0 +1,47 @@
package com.trafficaudit.dataimport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/** ç½‘约车订单及全省总量月度输入(源:模板_网约车订单及全省总量.xlsx æœˆåº¦è¾“入页) */
@Data
@TableName("wyc_order_monthly")
public class WycOrderMonthly {
    @TableId(type = IdType.AUTO)
    private Long id;
    /** æŠ¥è¡¨æœŸ yyyy-MM */
    private String reportPeriod;
    /** B-E å…¨çœ pin */
    private Double pinK;
    @TableField("pin_ck")
    private Double pinCK;
    private Double pinZ;
    @TableField("pin_cz")
    private Double pinCZ;
    /** F è®¢å•合计(单) */
    private Double orderSum;
    /** G-W 17 å¸‚州订单,按 RegionUtil.cityList é¡ºåº */
    private Double orderWuhan;
    private Double orderHuangshi;
    private Double orderShiyan;
    private Double orderYichang;
    private Double orderXiangyang;
    private Double orderEzhou;
    private Double orderJingmen;
    private Double orderXiaogan;
    private Double orderJingzhou;
    private Double orderHuanggang;
    private Double orderXianning;
    private Double orderSuizhou;
    private Double orderEnshi;
    private Double orderXiantao;
    private Double orderQianjiang;
    private Double orderTianmen;
    private Double orderShennong;
    private LocalDateTime createdAt;
}
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/entity/WycTotalMonthly.java
New file
@@ -0,0 +1,30 @@
package com.trafficaudit.dataimport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/** ç½‘约车总数月度输入(源:模板_网约车总数.xlsx,B-E ä¸ºå…¨çœ pin) */
@Data
@TableName("wyc_total_monthly")
public class WycTotalMonthly {
    @TableId(type = IdType.AUTO)
    private Long id;
    /** æŠ¥è¡¨æœŸ yyyy-MM */
    private String reportPeriod;
    /** å…¨çœç½‘约车客运量(万人次) */
    private Double pinK;
    /** å…¶ä¸­åŸŽå¸‚内客运量(万人次) */
    @TableField("pin_ck")
    private Double pinCK;
    /** å…¨çœç½‘约车周转量(万人公里) */
    private Double pinZ;
    /** å…¶ä¸­åŸŽå¸‚内周转量(万人公里) */
    @TableField("pin_cz")
    private Double pinCZ;
    private LocalDateTime createdAt;
}
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/mapper/WycOrderMonthlyMapper.java
New file
@@ -0,0 +1,6 @@
package com.trafficaudit.dataimport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.trafficaudit.dataimport.entity.WycOrderMonthly;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface WycOrderMonthlyMapper extends BaseMapper<WycOrderMonthly> {}
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/mapper/WycTotalMonthlyMapper.java
New file
@@ -0,0 +1,6 @@
package com.trafficaudit.dataimport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.trafficaudit.dataimport.entity.WycTotalMonthly;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface WycTotalMonthlyMapper extends BaseMapper<WycTotalMonthly> {}
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -18,6 +18,8 @@
import com.trafficaudit.dataimport.entity.CityBusMonthly;
import com.trafficaudit.dataimport.entity.CityTaxiMonthly;
import com.trafficaudit.dataimport.entity.CityTaxiAuth;
import com.trafficaudit.dataimport.entity.WycOrderMonthly;
import com.trafficaudit.dataimport.entity.WycTotalMonthly;
import com.trafficaudit.dataimport.entity.ScaleSplitTransport;
import com.trafficaudit.dataimport.entity.TransportAuthVehicle;
import com.trafficaudit.dataimport.entity.VehicleTrackMileage;
@@ -36,6 +38,8 @@
import com.trafficaudit.dataimport.mapper.CityBusMonthlyMapper;
import com.trafficaudit.dataimport.mapper.CityTaxiMonthlyMapper;
import com.trafficaudit.dataimport.mapper.CityTaxiAuthMapper;
import com.trafficaudit.dataimport.mapper.WycOrderMonthlyMapper;
import com.trafficaudit.dataimport.mapper.WycTotalMonthlyMapper;
import com.trafficaudit.dataimport.mapper.ScaleSplitTransportMapper;
import com.trafficaudit.dataimport.mapper.TransportAuthVehicleMapper;
import com.trafficaudit.dataimport.mapper.VehicleTrackMileageMapper;
@@ -162,6 +166,10 @@
    private CityTaxiMonthlyMapper cityTaxiMapper;
    @Resource
    private CityTaxiAuthMapper cityTaxiAuthMapper;
    @Resource
    private WycTotalMonthlyMapper wycTotalMapper;
    @Resource
    private WycOrderMonthlyMapper wycOrderMapper;
    @Resource
    private SqlSessionFactory sqlSessionFactory;
@@ -2704,6 +2712,155 @@
        return success;
    }
    // ========== ç½‘约车月度输入导入(全省 pin / è®¢å•) ==========
    /** ç½‘约车总数月度输入:模板_网约车总数.xlsx(sheet1;A åˆ—=月份日期;B=全省客运量 C=其中城市内 D=周转量 E=其中城市内周转量)。整表按报表期覆盖。 */
    public synchronized int importWycTotal(MultipartFile file, String period) throws Exception {
        Map<String, WycTotalMonthly> rows = new LinkedHashMap<>();
        try (Workbook wb = WorkbookFactory.create(file.getInputStream())) {
            Sheet sheet = wb.getSheetAt(0);
            for (int r = 2; r <= sheet.getLastRowNum(); r++) {
                Row row = sheet.getRow(r);
                if (row == null) continue;
                String rp = periodOfCell(row.getCell(0));
                if (rp == null) continue;
                double pk = dbl(row, 1), pck = dbl(row, 2), pz = dbl(row, 3), pcz = dbl(row, 4);
                if (pk <= 0 && pck <= 0 && pz <= 0 && pcz <= 0) continue;
                WycTotalMonthly item = new WycTotalMonthly();
                item.setReportPeriod(rp);
                item.setPinK(pk > 0 ? pk : null);
                item.setPinCK(pck > 0 ? pck : null);
                item.setPinZ(pz > 0 ? pz : null);
                item.setPinCZ(pcz > 0 ? pcz : null);
                rows.put(rp, item);
            }
        }
        if (rows.isEmpty()) throw new RuntimeException("未识别到有效月份行:A åˆ—应为日期(如 2026-07),B-E ä¸ºå…¨çœå®¢è¿é‡/城市内/周转量/城市内周转量");
        int ok = upsertWycTotal(rows);
        log.info("WycTotal imported: {} periods ok={}", rows.size(), ok);
        return ok;
    }
    /** ç½‘约车订单及全省总量:模板_网约车订单及全省总量.xlsx é¦–个数据 sheet(A=月份;B-E=全省 pin;F=订单合计;G-W=17 å¸‚州订单) */
    public synchronized int importWycOrder(MultipartFile file, String period) throws Exception {
        Map<String, WycOrderMonthly> rows = new LinkedHashMap<>();
        try (Workbook wb = WorkbookFactory.create(file.getInputStream())) {
            Sheet sheet = wb.getSheetAt(0);
            int head = -1;
            for (int r = 0; r <= Math.min(sheet.getLastRowNum(), 4); r++) {
                Row row = sheet.getRow(r);
                if (row == null) continue;
                String a = getString(row, 0);
                if (a != null && a.contains("月份")) { head = r; break; }
            }
            if (head < 0) throw new RuntimeException("未找到表头:A åˆ—需含“月份”");
            for (int r = head + 1; r <= sheet.getLastRowNum(); r++) {
                Row row = sheet.getRow(r);
                if (row == null) continue;
                String rp = periodOfCell(row.getCell(0));
                if (rp == null) continue;
                double pk = dbl(row, 1), pck = dbl(row, 2), pz = dbl(row, 3), pcz = dbl(row, 4), sum = dbl(row, 5);
                double citySum = 0;
                for (int k = 0; k < 17; k++) citySum += dbl(row, 6 + k);
                if (pk <= 0 && pck <= 0 && pz <= 0 && pcz <= 0 && sum <= 0 && citySum <= 0) continue;
                WycOrderMonthly it = new WycOrderMonthly();
                it.setReportPeriod(rp);
                it.setPinK(pk > 0 ? pk : null);
                it.setPinCK(pck > 0 ? pck : null);
                it.setPinZ(pz > 0 ? pz : null);
                it.setPinCZ(pcz > 0 ? pcz : null);
                if (sum <= 0 && citySum > 0) sum = citySum;
                it.setOrderSum(sum > 0 ? sum : null);
                it.setOrderWuhan(dblN(row, 6));
                it.setOrderHuangshi(dblN(row, 7));
                it.setOrderShiyan(dblN(row, 8));
                it.setOrderYichang(dblN(row, 9));
                it.setOrderXiangyang(dblN(row, 10));
                it.setOrderEzhou(dblN(row, 11));
                it.setOrderJingmen(dblN(row, 12));
                it.setOrderXiaogan(dblN(row, 13));
                it.setOrderJingzhou(dblN(row, 14));
                it.setOrderHuanggang(dblN(row, 15));
                it.setOrderXianning(dblN(row, 16));
                it.setOrderSuizhou(dblN(row, 17));
                it.setOrderEnshi(dblN(row, 18));
                it.setOrderXiantao(dblN(row, 19));
                it.setOrderQianjiang(dblN(row, 20));
                it.setOrderTianmen(dblN(row, 21));
                it.setOrderShennong(dblN(row, 22));
                rows.put(rp, it);
            }
        }
        if (rows.isEmpty()) throw new RuntimeException("未识别到有效月份行:A åˆ—应为 yyyy-MM,B-E å…¨çœ pin / F åˆè®¡ / G-W 17 å¸‚州订单");
        int ok = upsertWyc(rows);
        log.info("WycOrder imported: {} periods ok={}", rows.size(), ok);
        return ok;
    }
    private int upsertWyc(Map<String, WycOrderMonthly> rows) {
        int ok = 0, fail = 0;
        for (WycOrderMonthly item : rows.values()) {
            try {
                wycOrderMapper.delete(new LambdaQueryWrapper<WycOrderMonthly>().eq(WycOrderMonthly::getReportPeriod, item.getReportPeriod()));
                wycOrderMapper.insert(item);
                recordBatch("网约车订单及全省总量", "WYC_ORDER", item.getReportPeriod(), 1, 1, 0, null);
                ok++;
            } catch (Exception e) {
                fail++;
                log.error("WycOrder insert error period={}", item.getReportPeriod(), e);
            }
        }
        return ok;
    }
    private int upsertWycTotal(Map<String, WycTotalMonthly> rows) {
        int ok = 0, fail = 0;
        for (WycTotalMonthly item : rows.values()) {
            try {
                wycTotalMapper.delete(new LambdaQueryWrapper<WycTotalMonthly>().eq(WycTotalMonthly::getReportPeriod, item.getReportPeriod()));
                wycTotalMapper.insert(item);
                recordBatch("网约车总数", "WYC_TOTAL", item.getReportPeriod(), 1, 1, 0, null);
                ok++;
            } catch (Exception e) {
                fail++;
                log.error("WycTotal insert error period={}", item.getReportPeriod(), e);
            }
        }
        return ok;
    }
    private String periodOfCell(Cell c) {
        if (c == null) return null;
        if (c.getCellType() == CellType.NUMERIC) {
            try {
                double v = c.getNumericCellValue();
                if (v >= 40000 && v <= 60000) {
                    java.util.Date d = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(v);
                    java.text.SimpleDateFormat f = new java.text.SimpleDateFormat("yyyy-MM");
                    return f.format(d);
                }
            } catch (Exception ignore) { }
        }
        String s = null;
        try { s = c.getStringCellValue(); } catch (Exception ignore) { }
        if (s != null) {
            java.util.regex.Matcher m = java.util.regex.Pattern.compile("(\\d{4})[-/.å¹´](\\d{1,2})").matcher(s.trim());
            if (m.find()) return String.format("%04d-%02d", Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)));
        }
        return null;
    }
    private double dbl(Row row, int idx) {
        Double v = getDecimal(row, idx);
        return v == null ? 0.0 : v;
    }
    private Double dblN(Row row, int idx) {
        Double v = getDecimal(row, idx);
        return (v == null || v <= 0) ? null : v;
    }
    /** è¿æ”¿å‡ºç§Ÿè½¦å¸‚州提取:道路运输证字号→档案号→经营权号→业户地址,取 6 ä½åŒºåˆ’代码 */
    private static final java.util.regex.Pattern TAXI_REGION_PAT =
        java.util.regex.Pattern.compile("(4290\\d{2}|42(?:0[1-9]|1[0-3]|28)\\d{2})");
@@ -3040,6 +3197,8 @@
            case "trackMileage": return new ImportResult(importTrackMileage(file, period), 0, new ArrayList<>());
            case "freightTurnover": return new ImportResult(importFreightTurnover(file, period), 0, new ArrayList<>());
            case "scaleSplit": return new ImportResult(importScaleSplit(file, period), 0, new ArrayList<>());
            case "wycTotal": return new ImportResult(importWycTotal(file, period), 0, new ArrayList<>());
            case "wycOrder": return new ImportResult(importWycOrder(file, period), 0, new ArrayList<>());
            default: throw new RuntimeException("不支持的导入类型:" + type);
        }
    }
traffic-audit-web/src/views/DataImport.vue
@@ -1,4 +1,4 @@
<template>
SKIP/CHECK (0): TYPE_LABELS upper <template>
  <el-container direction="vertical">
    <app-header title="交通统计报表审核系统 - æ•°æ®å¯¼å…¥"></app-header>
    <el-container>
@@ -134,10 +134,11 @@
  investCityPassenger: '市州单表(客运站场)', investCityLogistics: '市州单表(物流园区)',
  'INVEST_客运站场_CITY': '市州单表(客运站场)', 'INVEST_物流园区_CITY': '市州单表(物流园区)',
  cityBus: '城市公交月报', cityTaxi: '巡游出租月报', cityTaxiAuth: '出租车运政车辆',
  wycTotal: '网约车总数', wycOrder: '网约车订单及全省总量',
  H2032: 'H203-2月报', H2031: 'H203-1旅客月报', H204: 'H204能耗季报', PASSENGER_AUTH: '旅客运政车辆数',
  PASSENGER_INDIVIDUAL: '个体客运量/周转量', ENERGY_AUTH: '能耗车辆运政信息', TRANSPORT_AUTH: '运政车辆',
  TRACK_MILEAGE: '轨迹里程', SCALE_SPLIT: '规上规下拆分', FREIGHT_TURNOVER: '货运量周转量',
  INVEST_SYSTEM: '投资系统导出', CITY_BUS: '城市公交月报', CITY_TAXI: '巡游出租月报', CITY_TAXI_AUTH: '出租车运政车辆'
  INVEST_SYSTEM: '投资系统导出', CITY_BUS: '城市公交月报', CITY_TAXI: '巡游出租月报', CITY_TAXI_AUTH: '出租车运政车辆', WYC_TOTAL: '网约车总数', WYC_ORDER: '网约车订单及全省总量'
}
const BATCH_TYPE_MAP = {
  H2032: 'h2032', TRANSPORT_AUTH: 'transportAuth', TRACK_MILEAGE: 'trackMileage',
@@ -145,6 +146,7 @@
  H2031: 'passengerMonthly', PASSENGER_AUTH: 'passengerAuth', PASSENGER_INDIVIDUAL: 'passengerIndividual',
  H204: 'energyMonthly', ENERGY_AUTH: 'energyAuth',
  CITY_BUS: 'cityBus', CITY_TAXI: 'cityTaxi', CITY_TAXI_AUTH: 'cityTaxiAuth',
  WYC_TOTAL: 'wycTotal', WYC_ORDER: 'wycOrder',
  INVEST_SYSTEM: 'investmentSystem'
}
export default {
@@ -187,7 +189,9 @@
          key: 'city', name: '城市客运', types: [
            { value: 'cityBus', label: '城市公共交通月度运营情况' },
            { value: 'cityTaxi', label: '巡游出租汽车运营服务情况月报' },
            { value: 'cityTaxiAuth', label: '出租车运政车辆' }
            { value: 'cityTaxiAuth', label: '出租车运政车辆' },
            { value: 'wycTotal', label: '网约车总数' },
            { value: 'wycOrder', label: '网约车订单及全省总量' }
          ]
        },
        {
@@ -258,7 +262,9 @@
        investCityLogistics: '—(批量扫描目录,无需模板)',
        cityBus: '导入_城市公共交通月度运营情况(YYYYå¹´M月).xls/.xlsx(企业级明细,取公共汽电车字段)',
        cityTaxi: '导入_巡游出租汽车运营服务情况月报(YYYYå¹´M月).xls(市州级17行)',
        cityTaxiAuth: '导入模板_出租车信息(运政车辆信息).xlsx(车辆级明细,用于运营车数对比)'
        cityTaxiAuth: '导入模板_出租车信息(运政车辆信息).xlsx(车辆级明细,用于运营车数对比)',
        wycTotal: '模板_网约车总数.xlsx(A列=月份,B-E=全省客运量/城市内/周转量/城市内周转量)',
        wycOrder: '模板_网约车订单及全省总量.xlsx(A列=月份,B-E=全省pin,F=订单合计,G-W=17市州订单)'
      }
      return map[this.importType] || ''
    },
@@ -277,6 +283,8 @@
        cityBus: '城市客运/生成_城市公交客运量分市州明细.xlsx',
        cityTaxi: '城市客运/生成_巡游出租客运量分市州明细.xlsx',
        cityTaxiAuth: '城市客运/导入模板_出租车信息(运政车辆信息).xlsx',
        wycTotal: '城市客运/模板_网约车总数.xlsx',
        wycOrder: '城市客运/模板_网约车订单及全省总量.xlsx',
        investment: '投资/输入/客运(客运站)/更新_7月客运站投资明细表(市州汇总大表,给领导).xlsx',
        investmentLogistics: '投资/输入/物流(物流园区)/更新_7月物流站场投资明细.xls',
        investmentSystem: '投资/模板_查询结果(投资系统-客运+物流 2026.7).xls'
@@ -314,7 +322,9 @@
        investmentSystem: '/import/investmentSystem',
        cityBus: '/import/cityBus',
        cityTaxi: '/import/cityTaxi',
        cityTaxiAuth: '/import/cityTaxiAuth'
        cityTaxiAuth: '/import/cityTaxiAuth',
        wycTotal: '/import/wycTotal',
        wycOrder: '/import/wycOrder'
      }
      return map[t] || ''
    },