puzhibing
2026-09-28 fcfe33b85f85c1a35d9f8aed161ff34390b63e6d
更新功能和修改bug
1个文件已添加
8个文件已修改
205 ■■■■■ 已修改文件
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/dto/VinManagementQueryDTO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/VinManagementFallbackFactory.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/VinManagementClient.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TVinManagementController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TVinManagementMapper.xml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TFleetController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TFleetService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TFleetServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/test/java/com/ruoyi/other/service/impl/TFleetServiceImplTest.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/dto/VinManagementQueryDTO.java
@@ -13,4 +13,6 @@
    private Integer status;
    /** 所属公司ID(额度分配弹窗按公司筛选使用) */
    private Integer companyId;
    /** 所属车队ID(车队管理-查看车队抽屉按车队筛选VIN码车辆使用) */
    private Integer fleetId;
}
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/VinManagementFallbackFactory.java
@@ -1,5 +1,7 @@
package com.ruoyi.account.api.factory;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.account.api.dto.VinManagementQueryDTO;
import com.ruoyi.account.api.feignClient.VinManagementClient;
import com.ruoyi.account.api.model.TVinManagement;
import com.ruoyi.common.core.domain.R;
@@ -35,6 +37,11 @@
            public R<List<TVinManagement>> getVinByIds(List<Long> ids) {
                return R.fail("根据ID批量查询VIN记录失败:" + throwable.getMessage());
            }
            @Override
            public R<Page<TVinManagement>> getVinPageByFleet(VinManagementQueryDTO query) {
                return R.fail("按车队分页查询VIN记录失败:" + throwable.getMessage());
            }
        };
    }
}
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/VinManagementClient.java
@@ -1,5 +1,7 @@
package com.ruoyi.account.api.feignClient;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.account.api.dto.VinManagementQueryDTO;
import com.ruoyi.account.api.factory.VinManagementFallbackFactory;
import com.ruoyi.account.api.model.TVinManagement;
import com.ruoyi.common.core.constant.ServiceNameConstants;
@@ -33,4 +35,10 @@
     */
    @PostMapping("/t-vin-management/inner/list-by-ids")
    R<List<TVinManagement>> getVinByIds(@RequestBody List<Long> ids);
    /**
     * 按车队分页查询VIN码车辆(车队管理-查看车队抽屉使用,query.fleetId 必须传入)
     */
    @PostMapping("/t-vin-management/inner/page-by-fleet")
    R<Page<TVinManagement>> getVinPageByFleet(@RequestBody VinManagementQueryDTO query);
}
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TVinManagementController.java
@@ -104,4 +104,12 @@
        List<Long> distinctIds = ids.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
        return R.ok(distinctIds.isEmpty() ? new ArrayList<>() : service.listByIds(distinctIds));
    }
    /**
     * 内部接口:按车队分页查询VIN码车辆(车队管理-查看车队抽屉使用,含车队名称回填)
     */
    @PostMapping("/inner/page-by-fleet")
    public R<IPage<TVinManagement>> pageByFleet(@RequestBody VinManagementQueryDTO query) {
        return R.ok(service.selectPageList(query));
    }
}
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TVinManagementMapper.xml
@@ -9,6 +9,7 @@
        <if test="query != null and query.phone != null and query.phone != ''">AND phone LIKE CONCAT('%', #{query.phone}, '%')</if>
        <if test="query != null and query.status != null">AND status = #{query.status}</if>
        <if test="query != null and query.companyId != null">AND company_id = #{query.companyId}</if>
        <if test="query != null and query.fleetId != null">AND fleet_id = #{query.fleetId}</if>
        ORDER BY create_time DESC, id DESC
    </select>
    <select id="selectExportList" resultType="com.ruoyi.account.api.dto.VinManagementExcelDTO">
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TFleetController.java
@@ -1,5 +1,7 @@
package com.ruoyi.other.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.account.api.model.TVinManagement;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.domain.AjaxResult;
@@ -213,6 +215,18 @@
    }
    /**
     * 分页查询车队下的VIN码车辆(查看车队抽屉使用)
     */
    @RequiresPermissions(value = {"/fleet/list"}, logical = Logical.OR)
    @GetMapping("/vin-page")
    @ApiOperation(value = "分页查询车队下VIN码车辆", tags = {"管理后台-车队管理"})
    public AjaxResult<Page<TVinManagement>> vinPage(@RequestParam("id") Integer id,
                                                    @RequestParam(value = "current", defaultValue = "1") Integer current,
                                                    @RequestParam(value = "size", defaultValue = "10") Integer size) {
        return AjaxResult.success(fleetService.selectVinPage(id, current, size));
    }
    /**
     * 按公司ID批量回填公司名称
     */
    private void fillCompanyName(List<TFleet> records) {
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TFleetService.java
@@ -1,6 +1,8 @@
package com.ruoyi.other.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.account.api.model.TVinManagement;
import com.ruoyi.other.api.domain.TFleet;
import com.ruoyi.other.api.dto.FleetExportDTO;
import com.ruoyi.other.api.dto.FleetImportDTO;
@@ -34,4 +36,14 @@
     */
    List<FleetExportDTO> selectExportList(FleetQueryDTO query);
    /**
     * 分页查询车队下的VIN码车辆(远程调用VIN管理服务,含VIN码、车牌号、手机号、初始分配额度、启用状态)
     *
     * @param fleetId 车队ID
     * @param current 当前页码
     * @param size    每页数量
     * @return VIN码车辆分页数据
     */
    Page<TVinManagement> selectVinPage(Integer fleetId, Integer current, Integer size);
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TFleetServiceImpl.java
@@ -1,6 +1,11 @@
package com.ruoyi.other.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.api.dto.VinManagementQueryDTO;
import com.ruoyi.account.api.feignClient.VinManagementClient;
import com.ruoyi.account.api.model.TVinManagement;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.other.api.domain.TFleet;
import com.ruoyi.other.api.domain.TGroupCompany;
@@ -42,6 +47,28 @@
    @Resource
    private TGroupCompanyService groupCompanyService;
    @Resource
    private VinManagementClient vinManagementClient;
    @Override
    public Page<TVinManagement> selectVinPage(Integer fleetId, Integer current, Integer size) {
        if (fleetId == null) {
            throw new ServiceException("车队ID不能为空");
        }
        if (getById(fleetId) == null) {
            throw new ServiceException("车队不存在或已删除");
        }
        VinManagementQueryDTO query = new VinManagementQueryDTO();
        query.setFleetId(fleetId);
        query.setPageCurr(current == null || current < 1 ? 1 : current);
        query.setPageSize(size == null || size < 1 ? 10 : size);
        R<Page<TVinManagement>> response = vinManagementClient.getVinPageByFleet(query);
        if (response == null || !R.isSuccess(response) || response.getData() == null) {
            throw new ServiceException("VIN码车辆查询失败:" + (response == null ? "服务无响应" : response.getMsg()));
        }
        return response.getData();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importFleets(List<FleetImportDTO> items) {
ruoyi-service/ruoyi-other/src/test/java/com/ruoyi/other/service/impl/TFleetServiceImplTest.java
New file
@@ -0,0 +1,126 @@
package com.ruoyi.other.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.account.api.dto.VinManagementQueryDTO;
import com.ruoyi.account.api.feignClient.VinManagementClient;
import com.ruoyi.account.api.model.TVinManagement;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.other.api.domain.TFleet;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.test.util.ReflectionTestUtils;
import java.math.BigDecimal;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
 * 车队下VIN码车辆分页查询逻辑单测(VIN管理远程服务以 Mock 替代,不依赖 Spring 容器与数据库)。
 */
class TFleetServiceImplTest {
    @Test
    void passesFleetIdAndPagingToVinService() {
        VinManagementClient client = Mockito.mock(VinManagementClient.class);
        Page<TVinManagement> expected = new Page<>(1, 10);
        expected.setTotal(1);
        expected.setRecords(Collections.singletonList(vehicle()));
        Mockito.when(client.getVinPageByFleet(Mockito.any())).thenReturn(R.ok(expected));
        Page<TVinManagement> actual = buildService(fleet(4), client).selectVinPage(4, 1, 10);
        assertSame(expected, actual);
        ArgumentCaptor<VinManagementQueryDTO> captor = ArgumentCaptor.forClass(VinManagementQueryDTO.class);
        Mockito.verify(client).getVinPageByFleet(captor.capture());
        assertEquals(4, captor.getValue().getFleetId());
        assertEquals(1, captor.getValue().getPageCurr());
        assertEquals(10, captor.getValue().getPageSize());
    }
    @Test
    void fallsBackToDefaultPagingWhenParamsInvalid() {
        VinManagementClient client = Mockito.mock(VinManagementClient.class);
        Mockito.when(client.getVinPageByFleet(Mockito.any())).thenReturn(R.ok(new Page<>(1, 10)));
        buildService(fleet(5), client).selectVinPage(5, null, 0);
        ArgumentCaptor<VinManagementQueryDTO> captor = ArgumentCaptor.forClass(VinManagementQueryDTO.class);
        Mockito.verify(client).getVinPageByFleet(captor.capture());
        assertEquals(1, captor.getValue().getPageCurr());
        assertEquals(10, captor.getValue().getPageSize());
    }
    @Test
    void rejectsMissingFleetId() {
        VinManagementClient client = Mockito.mock(VinManagementClient.class);
        TFleetServiceImpl service = buildService(null, client);
        ServiceException ex = assertThrows(ServiceException.class, () -> service.selectVinPage(null, 1, 10));
        assertTrue(ex.getMessage().contains("车队ID不能为空"), ex.getMessage());
        Mockito.verifyNoInteractions(client);
    }
    @Test
    void rejectsUnknownFleet() {
        VinManagementClient client = Mockito.mock(VinManagementClient.class);
        TFleetServiceImpl service = buildService(null, client);
        ServiceException ex = assertThrows(ServiceException.class, () -> service.selectVinPage(9, 1, 10));
        assertTrue(ex.getMessage().contains("车队不存在"), ex.getMessage());
        Mockito.verifyNoInteractions(client);
    }
    @Test
    void failsWhenRemoteReturnsError() {
        VinManagementClient client = Mockito.mock(VinManagementClient.class);
        Mockito.when(client.getVinPageByFleet(Mockito.any())).thenReturn(R.fail("VIN 管理服务调用失败"));
        ServiceException ex = assertThrows(ServiceException.class,
                () -> buildService(fleet(4), client).selectVinPage(4, 1, 10));
        assertTrue(ex.getMessage().contains("VIN码车辆查询失败"), ex.getMessage());
    }
    @Test
    void failsWhenRemoteReturnsNullData() {
        VinManagementClient client = Mockito.mock(VinManagementClient.class);
        Mockito.when(client.getVinPageByFleet(Mockito.any())).thenReturn(null);
        ServiceException ex = assertThrows(ServiceException.class,
                () -> buildService(fleet(4), client).selectVinPage(4, 1, 10));
        assertTrue(ex.getMessage().contains("服务无响应"), ex.getMessage());
    }
    private TFleetServiceImpl buildService(TFleet fleet, VinManagementClient client) {
        TFleetServiceImpl service = Mockito.spy(new TFleetServiceImpl());
        Mockito.doReturn(fleet).when(service).getById(Mockito.any());
        ReflectionTestUtils.setField(service, "vinManagementClient", client);
        return service;
    }
    private TFleet fleet(Integer id) {
        TFleet fleet = new TFleet();
        fleet.setId(id);
        return fleet;
    }
    private TVinManagement vehicle() {
        TVinManagement item = new TVinManagement();
        item.setId(1L);
        item.setVin("12345678900000000");
        item.setPlateNumber("川A123456");
        item.setFleetId(4);
        item.setInitQuota(new BigDecimal("30.00"));
        item.setStatus(1);
        return item;
    }
}