From 9f6d07b4eb72dfce7fb52ad35dffdf18096ca135 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期三, 23 九月 2026 13:38:05 +0800
Subject: [PATCH] 增加新功能

---
 sql/20260922_fleet.sql                                                                      |    2 
 ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/FleetQueryDTO.java          |   18 +++
 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TFleetService.java          |   20 ++++
 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TFleetServiceImpl.java |  126 +++++++++++++++++++++++++
 ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/FleetExcelDTO.java          |   22 ++++
 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TFleetController.java    |   63 ++++++++++++
 6 files changed, 251 insertions(+), 0 deletions(-)

diff --git a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/FleetExcelDTO.java b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/FleetExcelDTO.java
new file mode 100644
index 0000000..232703d
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/FleetExcelDTO.java
@@ -0,0 +1,22 @@
+package com.ruoyi.other.api.dto;
+
+import com.ruoyi.common.core.annotation.Excel;
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ * 车队导入导出 Excel DTO(模板下载、导入解析、导出共用)
+ *
+ * @author mxcd
+ * @since 2026-09-23
+ */
+@Data
+public class FleetExcelDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @Excel(name = "车队名称", width = 24, prompt = "必填,最多128个字符") private String fleetName;
+    @Excel(name = "所属公司", width = 24, prompt = "必填,公司名称") private String companyName;
+    @Excel(name = "联系人", width = 16) private String contactName;
+    @Excel(name = "联系人电话", width = 16) private String contactPhone;
+    @Excel(name = "启用状态", width = 14, readConverterExp = "1=启用,0=停用", combo = {"启用", "停用"}) private String status;
+    @Excel(name = "备注", width = 30) private String remark;
+}
diff --git a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/FleetQueryDTO.java b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/FleetQueryDTO.java
new file mode 100644
index 0000000..ac1e625
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/FleetQueryDTO.java
@@ -0,0 +1,18 @@
+package com.ruoyi.other.api.dto;
+
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ * 车队导出查询条件 DTO
+ *
+ * @author mxcd
+ * @since 2026-09-23
+ */
+@Data
+public class FleetQueryDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private String fleetName;
+    private Integer companyId;
+    private Integer status;
+}
diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TFleetController.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TFleetController.java
index b5e1505..0f9411c 100644
--- a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TFleetController.java
+++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TFleetController.java
@@ -1,5 +1,6 @@
 package com.ruoyi.other.controller;
 
+import com.ruoyi.common.core.utils.poi.ExcelUtil;
 import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.ruoyi.common.core.web.page.PageInfo;
 import com.ruoyi.common.log.annotation.Log;
@@ -8,6 +9,8 @@
 import com.ruoyi.common.security.annotation.RequiresPermissions;
 import com.ruoyi.other.api.domain.TFleet;
 import com.ruoyi.other.api.domain.TGroupCompany;
+import com.ruoyi.other.api.dto.FleetExcelDTO;
+import com.ruoyi.other.api.dto.FleetQueryDTO;
 import com.ruoyi.other.service.TFleetService;
 import com.ruoyi.other.service.TGroupCompanyService;
 import io.swagger.annotations.ApiOperation;
@@ -15,12 +18,16 @@
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -146,6 +153,62 @@
     }
 
     /**
+     * 导入车队(Excel)
+     */
+    @RequiresPermissions(value = {"/fleet/import"}, logical = Logical.OR)
+    @PostMapping("/import")
+    @ApiOperation(value = "导入车队", tags = {"管理后台-车队管理"})
+    @Log(title = "【车队管理】导入车队", businessType = BusinessType.IMPORT)
+    public AjaxResult<String> importData(@RequestPart("file") MultipartFile file) throws Exception {
+        List<FleetExcelDTO> items = new ExcelUtil<>(FleetExcelDTO.class).importExcel(file.getInputStream());
+        return AjaxResult.success(fleetService.importFleets(items));
+    }
+
+    /**
+     * 下载车队导入模板
+     */
+    @RequiresPermissions(value = {"/fleet/import"}, logical = Logical.OR)
+    @GetMapping("/import-template")
+    @ApiOperation(value = "下载车队导入模板", tags = {"管理后台-车队管理"})
+    public void template(HttpServletResponse response) {
+        new ExcelUtil<>(FleetExcelDTO.class).importTemplateExcel(response, "车队导入模板");
+    }
+
+    /**
+     * 导出车队(Excel,按筛选条件)
+     */
+    @RequiresPermissions(value = {"/fleet/export"}, logical = Logical.OR)
+    @PutMapping("/export")
+    @ApiOperation(value = "导出车队", tags = {"管理后台-车队管理"})
+    @Log(title = "【车队管理】导出车队", businessType = BusinessType.EXPORT)
+    public void export(HttpServletResponse response, @RequestBody(required = false) FleetQueryDTO query) {
+        new ExcelUtil<>(FleetExcelDTO.class).exportExcel(response, fleetService.selectExportList(query), "车队数据");
+    }
+
+    /**
+     * 查询车队详情(查看按钮使用)
+     */
+    @RequiresPermissions(value = {"/fleet/list"}, logical = Logical.OR)
+    @GetMapping("/detail")
+    @ApiOperation(value = "查询车队详情", tags = {"管理后台-车队管理"})
+    public AjaxResult<TFleet> detail(@RequestParam("id") Integer id) {
+        if (id == null) {
+            return AjaxResult.error("车队ID不能为空");
+        }
+        TFleet fleet = fleetService.getById(id);
+        if (fleet == null) {
+            return AjaxResult.error("车队不存在或已删除");
+        }
+        if (fleet.getCompanyId() != null) {
+            TGroupCompany company = groupCompanyService.getById(fleet.getCompanyId());
+            if (company != null) {
+                fleet.setCompanyName(company.getName());
+            }
+        }
+        return AjaxResult.success(fleet);
+    }
+
+    /**
      * 按公司ID批量回填公司名称
      */
     private void fillCompanyName(List<TFleet> records) {
diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TFleetService.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TFleetService.java
index a19765a..92d6d55 100644
--- a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TFleetService.java
+++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TFleetService.java
@@ -2,6 +2,10 @@
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.other.api.domain.TFleet;
+import com.ruoyi.other.api.dto.FleetExcelDTO;
+import com.ruoyi.other.api.dto.FleetQueryDTO;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +17,20 @@
  */
 public interface TFleetService extends IService<TFleet> {
 
+    /**
+     * 批量导入车队(Excel 解析结果),校验并入库
+     *
+     * @param items Excel 解析出的车队数据
+     * @return 导入结果提示
+     */
+    String importFleets(List<FleetExcelDTO> items);
+
+    /**
+     * 按条件查询车队导出列表(含公司名称回填)
+     *
+     * @param query 导出查询条件
+     * @return 导出数据
+     */
+    List<FleetExcelDTO> selectExportList(FleetQueryDTO query);
+
 }
diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TFleetServiceImpl.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TFleetServiceImpl.java
index cd79643..2f11a67 100644
--- a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TFleetServiceImpl.java
+++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TFleetServiceImpl.java
@@ -1,10 +1,28 @@
 package com.ruoyi.other.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.exception.ServiceException;
 import com.ruoyi.other.api.domain.TFleet;
+import com.ruoyi.other.api.domain.TGroupCompany;
+import com.ruoyi.other.api.dto.FleetExcelDTO;
+import com.ruoyi.other.api.dto.FleetQueryDTO;
 import com.ruoyi.other.mapper.TFleetMapper;
 import com.ruoyi.other.service.TFleetService;
+import com.ruoyi.other.service.TGroupCompanyService;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -17,4 +35,112 @@
 @Service
 public class TFleetServiceImpl extends ServiceImpl<TFleetMapper, TFleet> implements TFleetService {
 
+    private static final int ENABLED = 1;
+    private static final int DISABLED = 0;
+
+    @Resource
+    private TGroupCompanyService groupCompanyService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String importFleets(List<FleetExcelDTO> items) {
+        if (items == null || items.isEmpty()) {
+            throw new ServiceException("导入数据不能为空");
+        }
+        Set<String> fleetNames = new HashSet<>();
+        Set<String> companyNames = new HashSet<>();
+        int row = 1;
+        for (FleetExcelDTO item : items) {
+            row++;
+            if (item == null || !StringUtils.hasText(item.getFleetName())) {
+                throw new ServiceException("第" + row + "行车队名称不能为空");
+            }
+            String fleetName = item.getFleetName().trim();
+            if (fleetName.length() > 128) {
+                throw new ServiceException("第" + row + "行车队名称不能超过128个字符");
+            }
+            if (!StringUtils.hasText(item.getCompanyName())) {
+                throw new ServiceException("第" + row + "行所属公司不能为空");
+            }
+            parseStatus(item.getStatus(), row);
+            if (!fleetNames.add(fleetName) || lambdaQuery().eq(TFleet::getFleetName, fleetName).count() > 0) {
+                throw new ServiceException("第" + row + "行车队名称已存在或重复");
+            }
+            companyNames.add(item.getCompanyName().trim());
+        }
+        // 批量查询公司名称 -> ID
+        Map<String, Integer> companyMap = groupCompanyService.lambdaQuery()
+                .in(TGroupCompany::getName, companyNames)
+                .list()
+                .stream()
+                .collect(Collectors.toMap(TGroupCompany::getName, TGroupCompany::getId, (a, b) -> a));
+        row = 1;
+        for (FleetExcelDTO item : items) {
+            row++;
+            String companyName = item.getCompanyName().trim();
+            if (!companyMap.containsKey(companyName)) {
+                throw new ServiceException("第" + row + "行所属公司不存在:" + companyName);
+            }
+        }
+        LocalDateTime now = LocalDateTime.now();
+        for (FleetExcelDTO item : items) {
+            TFleet fleet = new TFleet();
+            fleet.setCompanyId(companyMap.get(item.getCompanyName().trim()));
+            fleet.setFleetName(item.getFleetName().trim());
+            fleet.setContactName(trim(item.getContactName()));
+            fleet.setContactPhone(trim(item.getContactPhone()));
+            fleet.setRemark(trim(item.getRemark()));
+            fleet.setStatus(parseStatus(item.getStatus(), 0));
+            fleet.setDelFlag(false);
+            fleet.setCreateTime(now);
+            save(fleet);
+        }
+        return "成功导入" + items.size() + "条车队数据";
+    }
+
+    @Override
+    public List<FleetExcelDTO> selectExportList(FleetQueryDTO query) {
+        FleetQueryDTO safe = query == null ? new FleetQueryDTO() : query;
+        List<TFleet> fleets = lambdaQuery()
+                .like(StringUtils.hasText(safe.getFleetName()), TFleet::getFleetName, safe.getFleetName())
+                .eq(safe.getCompanyId() != null, TFleet::getCompanyId, safe.getCompanyId())
+                .eq(safe.getStatus() != null, TFleet::getStatus, safe.getStatus())
+                .orderByDesc(TFleet::getId)
+                .list();
+        if (fleets == null || fleets.isEmpty()) {
+            return new ArrayList<>();
+        }
+        Set<Integer> companyIds = fleets.stream()
+                .map(TFleet::getCompanyId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        Map<Integer, String> nameMap = companyIds.isEmpty() ? Collections.emptyMap()
+                : groupCompanyService.listByIds(companyIds).stream()
+                        .collect(Collectors.toMap(TGroupCompany::getId, TGroupCompany::getName, (a, b) -> a));
+        return fleets.stream().map(item -> {
+            FleetExcelDTO dto = new FleetExcelDTO();
+            dto.setFleetName(item.getFleetName());
+            dto.setCompanyName(nameMap.get(item.getCompanyId()));
+            dto.setContactName(item.getContactName());
+            dto.setContactPhone(item.getContactPhone());
+            dto.setStatus(item.getStatus() == null ? null : String.valueOf(item.getStatus()));
+            dto.setRemark(item.getRemark());
+            return dto;
+        }).collect(Collectors.toList());
+    }
+
+    private String trim(String value) {
+        return value == null ? null : value.trim();
+    }
+
+    private Integer parseStatus(String value, int row) {
+        if (!StringUtils.hasText(value) || "1".equals(value.trim()) || "启用".equals(value.trim())) {
+            return ENABLED;
+        }
+        if ("0".equals(value.trim()) || "停用".equals(value.trim())) {
+            return DISABLED;
+        }
+        throw new ServiceException((row > 0 ? "第" + row + "行" : "") + "启用状态错误");
+    }
+
 }
diff --git a/sql/20260922_fleet.sql b/sql/20260922_fleet.sql
index 5694c7b..3d0f95f 100644
--- a/sql/20260922_fleet.sql
+++ b/sql/20260922_fleet.sql
@@ -2,6 +2,8 @@
 -- 车队管理表
 -- 创建日期: 2026-09-22
 -- 库: charging_pile_other
+-- 执行途径: 必须经 DRDS 中间件 192.168.110.111:8066 执行
+--          (直连 74 建表中间件无元数据,后端插入报 can not route)
 -- ----------------------------
 CREATE TABLE `t_fleet` (
   `id`            int          NOT NULL AUTO_INCREMENT COMMENT '主键',

--
Gitblit v1.7.1