package com.trafficaudit.dataimport.controller; import com.trafficaudit.common.Result; import com.trafficaudit.dataimport.dto.ImportResult; import com.trafficaudit.dataimport.entity.ImportBatch; import com.trafficaudit.dataimport.mapper.ImportBatchMapper; import com.trafficaudit.dataimport.service.DataImportService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @Slf4j @RestController @RequestMapping("/api/import") public class DataImportController { @Resource private DataImportService importService; @Resource private ImportBatchMapper importBatchMapper; /** H203-2表 道路货物运输月度生产情况 */ @PostMapping("/h2032") public Result importH2032(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { ImportResult result = importService.importH2032(file, period); return Result.ok(buildH2032Message(result)); } catch (Exception e) { log.error("H2032 import error", e); return Result.error("导入失败: " + e.getMessage()); } } private String buildH2032Message(ImportResult r) { if (r.getFail() == 0) { return "H2032月报导入成功,共 " + r.getSuccess() + " 条记录"; } StringBuilder sb = new StringBuilder("H2032月报导入完成:成功 " + r.getSuccess() + " 条,失败 " + r.getFail() + " 条。失败明细:"); java.util.List details = r.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { sb.append("\n").append(details.get(i)); } if (details.size() > shown) { sb.append("\n……共 ").append(details.size()).append(" 行失败"); } return sb.toString(); } /** H204 道路货运车辆能源消耗情况(季度能耗明细 + 运政车辆信息) */ @PostMapping("/energyMonthly") public Result importEnergyMonthly(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { ImportResult result = importService.importEnergyMonthly(file, period); String msg = "H204能耗季报导入完成:成功 " + result.getSuccess() + " 条,失败 " + result.getFail() + " 条(含同报表期运政车辆信息)"; if (result.getFail() > 0) { java.util.List details = result.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { msg += "\n" + details.get(i); } if (details.size() > shown) { msg += "\n……共 " + details.size() + " 行失败"; } } return Result.ok(msg); } catch (Exception e) { log.error("energyMonthly import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 能耗车辆运政信息(独立模板,也可随 H204 季报第二个 sheet 一并导入) */ @PostMapping("/energyAuth") public Result importEnergyAuth(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { ImportResult result = importService.importEnergyAuth(file, period); String msg = "能耗车辆运政信息导入完成:成功 " + result.getSuccess() + " 条,失败 " + result.getFail() + " 条"; if (result.getFail() > 0) { java.util.List details = result.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { msg += "\n" + details.get(i); } if (details.size() > shown) { msg += "\n……共 " + details.size() + " 行失败"; } } return Result.ok(msg); } catch (Exception e) { log.error("energyAuth import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** H203-1表 公路旅客运输月度生产情况(含运政车辆数sheet) */ @PostMapping("/passengerMonthly") public Result importPassengerMonthly(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { ImportResult result = importService.importPassengerMonthly(file, period); String msg = "H2031旅客月报导入完成:成功 " + result.getSuccess() + " 条,失败 " + result.getFail() + " 条(含同报表期运政车辆数据)"; if (result.getFail() > 0) { java.util.List details = result.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { msg += "\n" + details.get(i); } if (details.size() > shown) { msg += "\n……共 " + details.size() + " 行失败"; } } return Result.ok(msg); } catch (Exception e) { log.error("passengerMonthly import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 公路旅客个体客运量/周转量(企业线下汇报,导入后供分市州表个体行填充) */ @PostMapping("/passengerIndividual") public Result importPassengerIndividual(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { ImportResult result = importService.importPassengerIndividual(file, period); String msg = "个体客运量导入完成:成功 " + result.getSuccess() + " 条,失败 " + result.getFail() + " 条"; if (result.getFail() > 0) { java.util.List details = result.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { msg += "\n" + details.get(i); } if (details.size() > shown) { msg += "\n……共 " + details.size() + " 行失败"; } } return Result.ok(msg); } catch (Exception e) { log.error("passengerIndividual import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 公路旅客运政车辆数(独立模板,也可随 H203-1 月报第二个 sheet 一并导入) */ @PostMapping("/passengerAuth") public Result importPassengerAuth(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { ImportResult result = importService.importPassengerAuth(file, period); String msg = "旅客运政车辆数导入完成:成功 " + result.getSuccess() + " 条,失败 " + result.getFail() + " 条"; if (result.getFail() > 0) { java.util.List details = result.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { msg += "\n" + details.get(i); } if (details.size() > shown) { msg += "\n……共 " + details.size() + " 行失败"; } } return Result.ok(msg); } catch (Exception e) { log.error("passengerAuth import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 城市公交月报(城市公共交通月度运营情况,企业级明细) */ @PostMapping("/cityBus") public Result importCityBus(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { ImportResult result = importService.importCityBus(file, period); String msg = "城市公交月报导入完成:成功 " + result.getSuccess() + " 条,失败 " + result.getFail() + " 条"; if (result.getFail() > 0) { java.util.List details = result.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { msg += "\n" + details.get(i); } if (details.size() > shown) { msg += "\n……共 " + details.size() + " 行失败"; } } return Result.ok(msg); } catch (Exception e) { log.error("cityBus import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 巡游出租汽车运营服务情况月报(市州级) */ @PostMapping("/cityTaxi") public Result importCityTaxi(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { ImportResult result = importService.importCityTaxi(file, period); String msg = "巡游出租月报导入完成:成功 " + result.getSuccess() + " 条,失败 " + result.getFail() + " 条"; if (result.getFail() > 0) { java.util.List details = result.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { msg += "\n" + details.get(i); } if (details.size() > shown) { msg += "\n……共 " + details.size() + " 行失败"; } } return Result.ok(msg); } catch (Exception e) { log.error("cityTaxi import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 出租车运政车辆信息(车辆级明细,用于运营车数对比) */ @PostMapping("/cityTaxiAuth") public Result importCityTaxiAuth(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { int count = importService.importCityTaxiAuth(file, period); return Result.ok("出租车运政车辆导入成功, 共 " + count + " 条记录"); } catch (Exception e) { log.error("cityTaxiAuth import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 投资月报(全省汇总大表):category=客运站场/物流园区 */ @PostMapping("/investment") public Result importInvestment(@RequestParam("file") MultipartFile file, @RequestParam("period") String period, @RequestParam(value = "category", defaultValue = "客运站场") String category) { try { ImportResult result = importService.importInvestment(file, period, category); String msg = "投资月报导入完成(" + category + "):成功 " + result.getSuccess() + " 条,失败 " + result.getFail() + " 条"; if (result.getFail() > 0) { java.util.List details = result.getFailDetails(); int shown = Math.min(details.size(), 100); for (int i = 0; i < shown; i++) { msg += "\n" + details.get(i); } if (details.size() > shown) { msg += "\n……共 " + details.size() + " 行失败"; } } return Result.ok(msg); } catch (Exception e) { log.error("investment import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 多文件批量导入:前端一次选择多个 Excel 上传(type 为数据类型,投资类型按市州单表解析) */ @PostMapping("/batch") public Result importBatch(@RequestParam("type") String type, @RequestParam("period") String period, @RequestParam("files") List files) { try { Map result = importService.importBatchFiles(type, period, files); return Result.ok(result); } catch (Exception e) { log.error("batch import error", e); return Result.error("批量导入失败: " + e.getMessage()); } } /** 投资市州单表批量导入(M2):扫描 docs/投资/输入/{类别}/{X月} 目录全部市州报表,category=客运站场/物流园区 */ @PostMapping("/investCityBatch") public Result importInvestCityBatch(@RequestParam("period") String period, @RequestParam(value = "category", defaultValue = "客运站场") String category) { try { Map result = importService.importInvestCityDir(period, category); return Result.ok(result); } catch (Exception e) { log.error("investCityBatch import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 投资系统导出(审核比对基准) */ @PostMapping("/investmentSystem") public Result importInvestmentSystem(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { int count = importService.importInvestmentSystem(file, period); return Result.ok("投资系统导出导入成功, 共 " + count + " 条记录"); } catch (Exception e) { log.error("investmentSystem import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 运政车辆 */ @PostMapping("/transportAuth") public Result importTransportAuth(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { int count = importService.importTransportAuth(file, period); return Result.ok("运政车辆导入成功, 共 " + count + " 条记录"); } catch (Exception e) { log.error("transportAuth import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 轨迹里程 */ @PostMapping("/trackMileage") public Result importTrackMileage(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { int count = importService.importTrackMileage(file, period); return Result.ok("轨迹里程导入成功, 共 " + count + " 条记录"); } catch (Exception e) { log.error("trackMileage import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 模板_货运量周转量.xlsx(每月导入:左半今年1-N月,右半去年1-12月) */ @PostMapping("/freightTurnover") public Result importFreightTurnover(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { int count = importService.importFreightTurnover(file, period); return Result.ok("货运量周转量导入成功, 共 " + count + " 条记录"); } catch (Exception e) { log.error("freightTurnover import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 规上规下拆分运输量 */ @PostMapping("/scaleSplit") public Result importScaleSplit(@RequestParam("file") MultipartFile file, @RequestParam("period") String period) { try { int count = importService.importScaleSplit(file, period); return Result.ok("规上规下拆分导入成功, 共 " + count + " 条记录"); } catch (Exception e) { log.error("scaleSplit import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 目录浏览器:path 为空返回项目 docs 数据目录,返回子目录与当前目录 Excel 文件 */ @GetMapping("/dirs") public Result> dirs(@RequestParam(value = "path", required = false) String path) { try { Map result = importService.listDirs(path); return Result.ok(result); } catch (Exception e) { log.error("list dirs error", e); return Result.error("目录浏览失败: " + e.getMessage()); } } /** 按路径导入单个 Excel 文件(前端逐文件导入显示进度);报表期优先从文件名识别 */ @PostMapping("/fromDirFile") public Result> importFromDirFile(@RequestParam("type") String type, @RequestParam(value = "period", required = false) String period, @RequestParam(value = "skipImported", defaultValue = "true") boolean skipImported, @RequestParam("path") String path) { try { Map result = importService.importDirFileByPath(type, period, skipImported, path); return Result.ok(result); } catch (Exception e) { log.error("fromDirFile import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 从服务端文件夹批量导入:扫描 dir 下全部 .xlsx/.xls,按 type 逐个导入;报表期优先从文件名识别 */ @PostMapping("/fromDir") public Result importFromDir(@RequestParam("type") String type, @RequestParam(value = "period", required = false) String period, @RequestParam(value = "skipImported", defaultValue = "true") boolean skipImported, @RequestParam("dir") String dir) { try { Map result = importService.importFromDir(type, period, skipImported, dir); return Result.ok(result); } catch (Exception e) { log.error("fromDir import error", e); return Result.error("导入失败: " + e.getMessage()); } } /** 导入批次历史(数据导入页展示最近导入结果) */ @GetMapping("/batches") public Result> batches(@RequestParam(value = "type", required = false) String type, @RequestParam(value = "period", required = false) String period, @RequestParam(value = "limit", defaultValue = "20") int limit) { int safeLimit = Math.min(Math.max(limit, 1), 200); LambdaQueryWrapper w = new LambdaQueryWrapper() .eq(type != null && !type.trim().isEmpty(), ImportBatch::getImportType, type) .eq(period != null && !period.trim().isEmpty(), ImportBatch::getReportPeriod, period) .orderByDesc(ImportBatch::getId) .last("limit " + safeLimit); List list = importBatchMapper.selectList(w); Map result = new LinkedHashMap<>(); result.put("records", list); return Result.ok(result); } }