From 88580dae55106dcf4a8f80693b90638e07af02fa Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期三, 14 十月 2026 09:20:23 +0800
Subject: [PATCH] 修改bug

---
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java                |    7 
 ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml                              |    2 
 ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java                  |    7 +
 ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java     |   78 +++++++++++
 ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml                             |    2 
 ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java     |  165 +++++++++++++++++++++++
 ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml                     |    5 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java                                   |    2 
 sql/20261013_order_evaluate_vin_type.sql                                                                           |    6 
 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java                              |    2 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java                |   41 +++++
 ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java         |   20 ++
 ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java                   |    4 
 ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java |   40 +++++
 sql/charging_pile_order.sql                                                                                        |    2 
 ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java                       |    3 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java                   |    2 
 17 files changed, 378 insertions(+), 10 deletions(-)

diff --git a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java
index 3b4a479..fd40572 100644
--- a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java
+++ b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java
@@ -64,6 +64,9 @@
     @ApiModelProperty(value = "是否命中白名单")
     private Boolean whitelistMatched = false;
 
+    @ApiModelProperty(value = "白名单账户可用余额(企业账户充电显示,共享模式=公司可用余额,分配模式=白名单用户余额)")
+    private BigDecimal whitelistBalance;
+
     @ApiModelProperty(value = "白名单权益:1=全部免费,2=免电费,3=免服务费")
     private Integer whitelistBenefitType;
 
diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java
index 4ebe265..f6fa736 100644
--- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java
+++ b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java
@@ -31,7 +31,7 @@
     @TableId(value = "id", type = IdType.NONE)
     private Long id;
 
-    @ApiModelProperty(value = "订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单)")
+    @ApiModelProperty(value = "订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单,5=VIN码充电订单)")
     @TableField("order_type")
     private Integer orderType;
 
diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java
index bd3b4eb..177c3df 100644
--- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java
+++ b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java
@@ -179,6 +179,10 @@
             }
             AppUserWhitelistMatchVO whitelist = whitelistService.matchWhitelist(tokenService.getLoginUserApplet().getUserId(), chargingGun.getSiteId());
             data.setWhitelistMatched(Boolean.TRUE.equals(whitelist.getMatched()));
+            if (Boolean.TRUE.equals(whitelist.getMatched())) {
+                // 充电页余额显示:按白名单所属公司账户模式下发账户可用余额(共享=公司余额,分配=白名单余额)
+                data.setWhitelistBalance(whitelistService.resolveWhitelistAccountBalance(whitelist));
+            }
             // 白名单权益已下线(充电完全按企业优惠结算),不再下发权益类型与名称,仅保留命中标识
             data.setWhitelistBenefitType(null);
             data.setWhitelistBenefitName(null);
diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java
index 1b6b29a..44e0d03 100644
--- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java
+++ b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java
@@ -50,6 +50,13 @@
     AppUserWhitelistMatchVO matchWhitelist(Long appUserId, Integer siteId);
 
     /**
+     * 解析白名单账户可用余额(小程序充电页余额显示):按所属公司账户模式,
+     * 共享模式=公司可用余额,分配模式=白名单用户余额,账户模式未知按共享处理;
+     * 公司信息查询失败时降级返回 null(由调用方保持原余额显示)
+     */
+    BigDecimal resolveWhitelistAccountBalance(AppUserWhitelistMatchVO match);
+
+    /**
      * 按公司查询未删除的白名单用户列表(公司详情-充电用户信息聚合使用)
      */
     List<TAppUserWhitelist> listByCompany(Integer companyId);
diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java
index 5a88272..c9d1af4 100644
--- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java
+++ b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java
@@ -457,6 +457,26 @@
     }
 
     @Override
+    public BigDecimal resolveWhitelistAccountBalance(AppUserWhitelistMatchVO match) {
+        if (match == null || !Boolean.TRUE.equals(match.getMatched()) || match.getCompanyId() == null) {
+            return null;
+        }
+        try {
+            TGroupCompany company = loadCompany(match.getCompanyId());
+            Integer accountMode = company == null ? null : company.getAccountMode();
+            if (accountMode == null) {
+                // 历史数据账户模式为空,按共享模式处理
+                accountMode = ACCOUNT_MODE_SHARED;
+            }
+            return resolveAvailableBalance(accountMode, match.getBalance(),
+                    company == null ? null : company.getAvailableBalance());
+        } catch (Exception ex) {
+            log.warn("解析白名单账户可用余额失败,companyId={}", match.getCompanyId(), ex);
+            return null;
+        }
+    }
+
+    @Override
     public List<TAppUserWhitelist> listByCompany(Integer companyId) {
         if (companyId == null) {
             return Collections.emptyList();
diff --git a/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml b/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml
index 9c72703..a56d9cd 100644
--- a/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml
+++ b/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml
@@ -4,6 +4,9 @@
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.account.mapper.TCompanyAllocateRecordMapper">
 
+    <!-- 分配记录弹窗只统计「给子账号(VIN码/刷卡/白名单)分配余额」的流水:
+         change_type = 1 仅取分配类(1=分配;排除 2=充电结算消费流水,其 after_balance 可为负数);
+         user_type != 4 排除账户模式切换时企业账户自身的回退留痕(不属于子账号分配) -->
     <select id="selectRecordPage" resultType="com.ruoyi.account.api.model.TCompanyAllocateRecord">
         SELECT id,
                company_id,
@@ -21,6 +24,8 @@
                create_time
         FROM t_company_allocate_record
         WHERE company_id = #{query.companyId}
+          AND change_type = 1
+          AND user_type != 4
         ORDER BY operate_time DESC, id DESC
     </select>
 </mapper>
diff --git a/ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java b/ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java
index 6621aa1..e763e60 100644
--- a/ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java
+++ b/ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java
@@ -50,6 +50,7 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -259,6 +260,83 @@
         assertEquals(null, result.getFleetId());
     }
 
+    // ---------------- 白名单账户可用余额解析(充电页余额显示) ----------------
+
+    @Test
+    void resolveWhitelistAccountBalanceReturnsCompanyBalanceForSharedMode() {
+        TGroupCompany company = new TGroupCompany();
+        company.setAccountMode(1);
+        company.setAvailableBalance(new BigDecimal("500.50"));
+        when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company));
+
+        AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
+        match.setMatched(true);
+        match.setCompanyId(12);
+        match.setBalance(new BigDecimal("100.00"));
+
+        BigDecimal result = service.resolveWhitelistAccountBalance(match);
+
+        assertEquals(new BigDecimal("500.50"), result);
+    }
+
+    @Test
+    void resolveWhitelistAccountBalanceReturnsWhitelistBalanceForAllocationMode() {
+        TGroupCompany company = new TGroupCompany();
+        company.setAccountMode(2);
+        company.setAvailableBalance(new BigDecimal("500.50"));
+        when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company));
+
+        AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
+        match.setMatched(true);
+        match.setCompanyId(12);
+        match.setBalance(new BigDecimal("100.00"));
+
+        BigDecimal result = service.resolveWhitelistAccountBalance(match);
+
+        assertEquals(new BigDecimal("100.00"), result);
+    }
+
+    @Test
+    void resolveWhitelistAccountBalanceTreatsNullAccountModeAsShared() {
+        TGroupCompany company = new TGroupCompany();
+        company.setAccountMode(null);
+        company.setAvailableBalance(new BigDecimal("500.50"));
+        when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company));
+
+        AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
+        match.setMatched(true);
+        match.setCompanyId(12);
+        match.setBalance(new BigDecimal("100.00"));
+
+        BigDecimal result = service.resolveWhitelistAccountBalance(match);
+
+        assertEquals(new BigDecimal("500.50"), result);
+    }
+
+    @Test
+    void resolveWhitelistAccountBalanceReturnsNullWhenCompanyQueryFails() {
+        when(groupCompanyClient.getCompanyById(12)).thenReturn(R.fail("公司信息查询失败"));
+
+        AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
+        match.setMatched(true);
+        match.setCompanyId(12);
+        match.setBalance(new BigDecimal("100.00"));
+
+        BigDecimal result = service.resolveWhitelistAccountBalance(match);
+
+        assertNull(result);
+    }
+
+    @Test
+    void resolveWhitelistAccountBalanceReturnsNullWhenNotMatched() {
+        AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
+        match.setMatched(false);
+
+        BigDecimal result = service.resolveWhitelistAccountBalance(match);
+
+        assertNull(result);
+    }
+
     // ---------------- 额度分配 ----------------
 
     @Test
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java
index 27c1c87..315f7b5 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java
@@ -183,7 +183,7 @@
     @ApiOperation(value = "获取订单评价详情", tags = {"小程序-充电记录"})
     @ApiImplicitParams({
             @ApiImplicitParam(value = "订单id", name = "orderId", required = true),
-            @ApiImplicitParam(value = "订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单)", name = "orderType", required = true),
+            @ApiImplicitParam(value = "订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单,5=VIN码充电订单)", name = "orderType", required = true),
     })
     public AjaxResult<OrderEvaluateVo> getOrderEvaluate(String orderId, Integer orderType){
         OrderEvaluateVo orderEvaluate = orderEvaluateService.getOrderEvaluate(orderId, orderType);
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java
index 5b248cc..a8f136d 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java
@@ -36,7 +36,7 @@
 	private BigDecimal chargedDegrees;
 	@ApiModelProperty("已充电时间")
 	private String chargedTime;
-	@ApiModelProperty("充电费用")
+	@ApiModelProperty("已使用费用(设备上报已充金额,缺失时回退订单已使用金额)")
 	private BigDecimal chargingCost;
 	@ApiModelProperty("充电状态(0=未知,1=等待中,2=启动中,3=充电中,4=停止中,5=已结束)")
 	private Integer status;
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
index 8d08113..d9d4d96 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -2796,7 +2796,8 @@
         boolean reservationPending = ReservationOrderSupport.isPending(
                 one.getStatus(), one.getReservationTime(), LocalDateTime.now());
         chargingDetails.setStatus(reservationPending ? 1 : one.getStatus());
-        chargingDetails.setChargingCost(one.getResidualAmount());
+        // 已使用费用:默认取订单已使用金额,存在实时监测数据时以设备上报已充金额(电费+服务费)为准
+        chargingDetails.setChargingCost(money(one.getResidualAmount()));
         UploadRealTimeMonitoringData data = uploadRealTimeMonitoringDataService.getLastDataById(one.getCode());
         if (null != data) {
             chargingDetails.setChargeCurrent(data.getOutput_current());
@@ -2809,6 +2810,10 @@
             Integer h = Integer.valueOf(data.getCumulative_charging_time() / 60);
             Integer m = Integer.valueOf(data.getCumulative_charging_time() % 60);
             chargingDetails.setChargedTime(String.format("%02d", h) + ":" + String.format("%02d", m));
+            // 设备上报已充金额非空时覆盖,上报缺失则沿用订单已使用金额
+            if (null != data.getPaid_amount()) {
+                chargingDetails.setChargingCost(money(data.getPaid_amount()));
+            }
             if (null != one.getAppUserCarId()) {
                 TAppUserCar appUserCar = appUserCarClient.getCarById(one.getAppUserCarId().toString()).getData();
                 //   续航 = 续航里程 * soc
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java
index ab0bcc4..4ab6514 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java
@@ -24,6 +24,7 @@
 import com.ruoyi.order.api.model.TEvaluationAutoReply;
 import com.ruoyi.order.api.model.TOrderEvaluate;
 import com.ruoyi.order.api.model.TOrderEvaluateTag;
+import com.ruoyi.order.api.model.TVinChargingOrder;
 import com.ruoyi.order.api.query.TOrderEvaluateQuery;
 import com.ruoyi.order.api.vo.SiteDetailEvaluateVO;
 import com.ruoyi.order.api.vo.TOrderEvaluateVO;
@@ -36,6 +37,7 @@
 import com.ruoyi.order.service.TChargingOrderService;
 import com.ruoyi.order.service.TEvaluationAutoReplyService;
 import com.ruoyi.order.service.TOrderEvaluateService;
+import com.ruoyi.order.service.TVinChargingOrderService;
 import com.ruoyi.order.service.WxSubscribeMessageService;
 import com.ruoyi.other.api.domain.TEvaluationTag;
 import com.ruoyi.other.api.domain.TIntegralRule;
@@ -90,6 +92,9 @@
     
     @Resource
     private TChargingOrderService chargingOrderService;
+    
+    @Resource
+    private TVinChargingOrderService vinChargingOrderService;
     
     @Resource
     private IntegralRuleClient integralRuleClient;
@@ -345,9 +350,25 @@
         BeanUtils.copyProperties(query, orderEvaluate);
         Long userid = tokenService.getLoginUserApplet().getUserId();
         orderEvaluate.setAppUserId(userid);
-        if(query.getOrderType() == 1){
+        Integer orderType = query.getOrderType();
+        if(null == orderType){
+            return AjaxResult.error("订单类型不能为空");
+        }
+        if(orderType == 1){
             TChargingOrder chargingOrder = chargingOrderService.getById(query.getOrderId());
+            if(null == chargingOrder){
+                return AjaxResult.error("订单不存在");
+            }
             orderEvaluate.setAppUserCarId(chargingOrder.getAppUserCarId());
+        }else if(orderType == 5){
+            //VIN码充电订单,仅允许评价本人订单
+            TVinChargingOrder vinChargingOrder = vinChargingOrderService.getById(query.getOrderId());
+            if(null == vinChargingOrder || !userid.equals(vinChargingOrder.getAppUserId())){
+                return AjaxResult.error("订单不存在");
+            }
+            orderEvaluate.setAppUserCarId(vinChargingOrder.getAppUserCarId());
+        }else{
+            return AjaxResult.error("订单类型不支持评价");
         }
         TAppUser appUser = appUserClient.getUserById(userid).getData();
     
@@ -392,7 +413,6 @@
                 appUser.setPoints(appUser.getPoints() + num1);
                 appUserClient.updateAppUser(appUser);
     
-                TChargingOrder chargingOrder = chargingOrderService.getById(orderEvaluate.getOrderId());
                 //积分变动明细
                 TAppUserIntegralChange appUserIntegralChange = new TAppUserIntegralChange();
                 appUserIntegralChange.setAppUserId(appUser.getId());
@@ -400,7 +420,7 @@
                 appUserIntegralChange.setHistoricalIntegral(points);
                 appUserIntegralChange.setCurrentIntegral(points + num1);
                 appUserIntegralChange.setCreateTime(LocalDateTime.now());
-                appUserIntegralChange.setOrderCode(chargingOrder.getCode());
+                appUserIntegralChange.setOrderCode(getOrderCode(orderEvaluate.getOrderType(), orderEvaluate.getOrderId()));
                 appUserIntegralChange.setExtension(orderEvaluate.getOrderId().toString());
                 appUserIntegralChangeClient.addAppUserIntegralChange(appUserIntegralChange);
             }
@@ -408,6 +428,21 @@
         return AjaxResult.success();
     }
     
+    /**
+     * 根据评价的订单类型获取对应的订单编号
+     * @param orderType 订单类型(1=充电订单,5=VIN码充电订单)
+     * @param orderId 订单id
+     * @return 订单编号
+     */
+    private String getOrderCode(Integer orderType, Long orderId) {
+        if(Integer.valueOf(5).equals(orderType)){
+            TVinChargingOrder vinChargingOrder = vinChargingOrderService.getById(orderId);
+            return null == vinChargingOrder ? null : vinChargingOrder.getCode();
+        }
+        TChargingOrder chargingOrder = chargingOrderService.getById(orderId);
+        return null == chargingOrder ? null : chargingOrder.getCode();
+    }
+    
     private void applyAutoReply(TOrderEvaluate orderEvaluate) {
         TEvaluationAutoReply rule = evaluationAutoReplyService.matchRule(orderEvaluate.getContent(), orderEvaluate.getMark());
         if (rule == null || StringUtils.isEmpty(rule.getReplyContent())) {
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml
index 8df7f35..1f743b8 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml
+++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml
@@ -36,7 +36,7 @@
                 AND o.charging_gun_id = #{query.gunId}
             </if>
             <if test="startTime1 != null and startTime1 != '' and startTime2 != null and startTime2 != ''">
-                AND o.pay_time BETWEEN #{startTime1} AND #{startTime2}
+                AND o.start_time BETWEEN #{startTime1} AND #{startTime2}
             </if>
             <if test="endTime1 != null and endTime1 != '' and endTime2 != null and endTime2 != ''">
                 AND o.end_time BETWEEN #{endTime1} AND #{endTime2}
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml
index 93ffe57..3813b89 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml
+++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml
@@ -60,7 +60,7 @@
                o.status,
                CASE WHEN EXISTS (
                    SELECT 1 FROM t_order_evaluate e
-                   WHERE e.order_id = o.id AND e.order_type = 1 AND e.del_flag = 0
+                   WHERE e.order_id = o.id AND e.order_type = 5 AND e.del_flag = 0
                ) THEN 2 ELSE 1 END AS evaluate
         FROM t_vin_charging_order o
         WHERE o.del_flag = 0
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java
index dda4567..090cb4a 100644
--- a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java
@@ -134,6 +134,46 @@
     }
 
     @Test
+    void getChargingDetailsUsesPaidAmountAsUsedCostWhenRealTimeDataPresent() {
+        LoginUserApplet loginUser = new LoginUserApplet();
+        loginUser.setUserId(88L);
+        when(tokenService.getLoginUserApplet()).thenReturn(loginUser);
+        when(mapper.selectOne(any())).thenReturn(null);
+        TVinChargingOrder vinOrder = new TVinChargingOrder();
+        vinOrder.setId(1001L);
+        vinOrder.setAppUserId(88L);
+        vinOrder.setChargingGunId(5);
+        vinOrder.setStatus(3);
+        vinOrder.setCode("VD20261013001");
+        vinOrder.setResidualAmount(new BigDecimal("66.60"));
+        when(vinChargingOrderMapper.selectOne(any())).thenReturn(vinOrder);
+        TChargingGun gun = new TChargingGun();
+        gun.setChargingPileId(7);
+        when(chargingGunClient.getChargingGunById(5)).thenReturn(R.ok(gun));
+        TChargingPile pile = new TChargingPile();
+        pile.setName("1号桩");
+        pile.setSiteId(9);
+        when(chargingPileClient.getChargingPileById(7)).thenReturn(R.ok(pile));
+        Site site = new Site();
+        site.setName("城东站");
+        when(siteClient.getSiteByIds(Arrays.asList(9))).thenReturn(R.ok(Collections.singletonList(site)));
+        UploadRealTimeMonitoringData data = new UploadRealTimeMonitoringData();
+        data.setOutput_current(new BigDecimal("10"));
+        data.setOutput_voltage(new BigDecimal("220"));
+        data.setSoc(50);
+        data.setTime_remaining(30);
+        data.setCharging_degree(new BigDecimal("5.5"));
+        data.setCumulative_charging_time(75);
+        // 设备上报已充金额为 4 位小数,展示口径统一保留 2 位
+        data.setPaid_amount(new BigDecimal("12.3456"));
+        when(uploadRealTimeMonitoringDataService.getLastDataById("VD20261013001")).thenReturn(data);
+
+        ChargingDetails details = service.getChargingDetails(5);
+
+        assertEquals(0, new BigDecimal("12.35").compareTo(details.getChargingCost()));
+    }
+
+    @Test
     void getChargingDetailsReturnsNullWhenNeitherNormalNorVinOrderExists() {
         LoginUserApplet loginUser = new LoginUserApplet();
         loginUser.setUserId(88L);
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java
new file mode 100644
index 0000000..8d29ef8
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java
@@ -0,0 +1,165 @@
+package com.ruoyi.order.service.impl;
+
+import com.ruoyi.account.api.feignClient.AppUserClient;
+import com.ruoyi.account.api.model.TAppUser;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.common.security.service.TokenService;
+import com.ruoyi.order.api.model.TChargingOrder;
+import com.ruoyi.order.api.model.TOrderEvaluate;
+import com.ruoyi.order.api.model.TVinChargingOrder;
+import com.ruoyi.order.dto.OrderEvaluateVo;
+import com.ruoyi.order.mapper.TOrderEvaluateMapper;
+import com.ruoyi.order.service.TChargingOrderService;
+import com.ruoyi.order.service.TEvaluationAutoReplyService;
+import com.ruoyi.order.service.TVinChargingOrderService;
+import com.ruoyi.system.api.model.LoginUserApplet;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * VIN 码充电订单评价(orderType=5)分支测试
+ * 覆盖:本人 VIN 订单可评价、他人订单/不存在订单被拒、普通充电订单不存在的兜底校验
+ */
+@ExtendWith(MockitoExtension.class)
+class TOrderEvaluateServiceImplVinTypeTest {
+
+    @InjectMocks
+    private TOrderEvaluateServiceImpl service;
+    @Mock
+    private TOrderEvaluateMapper orderEvaluateMapper;
+    @Mock
+    private TokenService tokenService;
+    @Mock
+    private TChargingOrderService chargingOrderService;
+    @Mock
+    private TVinChargingOrderService vinChargingOrderService;
+    @Mock
+    private AppUserClient appUserClient;
+    @Mock
+    private TEvaluationAutoReplyService evaluationAutoReplyService;
+
+    @BeforeEach
+    void setUp() {
+        ReflectionTestUtils.setField(service, "baseMapper", orderEvaluateMapper);
+        ReflectionTestUtils.setField(service, "orderEvaluateMapper", orderEvaluateMapper);
+        LoginUserApplet loginUser = new LoginUserApplet();
+        loginUser.setUserId(88L);
+        when(tokenService.getLoginUserApplet()).thenReturn(loginUser);
+    }
+
+    private OrderEvaluateVo buildQuery(Long orderId, Integer orderType) {
+        OrderEvaluateVo query = new OrderEvaluateVo();
+        query.setOrderId(orderId);
+        query.setOrderType(orderType);
+        query.setMark(5);
+        return query;
+    }
+
+    @Test
+    void addOrderEvaluateForOwnVinOrderStoresTypeFiveAndOwnerCar() {
+        TVinChargingOrder vinOrder = new TVinChargingOrder();
+        vinOrder.setId(1001L);
+        vinOrder.setAppUserId(88L);
+        vinOrder.setAppUserCarId(66L);
+        vinOrder.setCode("VD_1001");
+        when(vinChargingOrderService.getById(1001L)).thenReturn(vinOrder);
+        TAppUser appUser = new TAppUser();
+        appUser.setId(88L);
+        appUser.setWxOpenid("openid_88");
+        when(appUserClient.getUserById(88L)).thenReturn(R.ok(appUser));
+        when(orderEvaluateMapper.insert(any(TOrderEvaluate.class))).thenReturn(1);
+
+        AjaxResult result = service.addOrderEvaluate(buildQuery(1001L, 5));
+
+        assertTrue(result.isSuccess());
+        ArgumentCaptor<TOrderEvaluate> captor = ArgumentCaptor.forClass(TOrderEvaluate.class);
+        verify(orderEvaluateMapper).insert(captor.capture());
+        TOrderEvaluate saved = captor.getValue();
+        assertEquals(Integer.valueOf(5), saved.getOrderType());
+        assertEquals(Long.valueOf(88L), saved.getAppUserId());
+        assertEquals(Long.valueOf(66L), saved.getAppUserCarId());
+        // VIN 订单评价不应再走普通充电订单表
+        verify(chargingOrderService, never()).getById(anyLong());
+    }
+
+    @Test
+    void addOrderEvaluateRejectsVinOrderBelongingToOtherUser() {
+        TVinChargingOrder vinOrder = new TVinChargingOrder();
+        vinOrder.setId(1001L);
+        vinOrder.setAppUserId(99L);
+        when(vinChargingOrderService.getById(1001L)).thenReturn(vinOrder);
+
+        AjaxResult result = service.addOrderEvaluate(buildQuery(1001L, 5));
+
+        assertFalse(result.isSuccess());
+        assertEquals("订单不存在", result.get(AjaxResult.MSG_TAG));
+        verify(orderEvaluateMapper, never()).insert(any(TOrderEvaluate.class));
+    }
+
+    @Test
+    void addOrderEvaluateRejectsMissingVinOrder() {
+        AjaxResult result = service.addOrderEvaluate(buildQuery(1001L, 5));
+
+        assertFalse(result.isSuccess());
+        assertEquals("订单不存在", result.get(AjaxResult.MSG_TAG));
+        verify(orderEvaluateMapper, never()).insert(any(TOrderEvaluate.class));
+    }
+
+    @Test
+    void addOrderEvaluateRejectsMissingChargingOrder() {
+        AjaxResult result = service.addOrderEvaluate(buildQuery(2002L, 1));
+
+        assertFalse(result.isSuccess());
+        assertEquals("订单不存在", result.get(AjaxResult.MSG_TAG));
+        verify(orderEvaluateMapper, never()).insert(any(TOrderEvaluate.class));
+    }
+
+    @Test
+    void addOrderEvaluateRejectsUnsupportedOrderType() {
+        AjaxResult result = service.addOrderEvaluate(buildQuery(3003L, 2));
+
+        assertFalse(result.isSuccess());
+        assertEquals("订单类型不支持评价", result.get(AjaxResult.MSG_TAG));
+        verify(orderEvaluateMapper, never()).insert(any(TOrderEvaluate.class));
+    }
+
+    @Test
+    void addOrderEvaluateStillWorksForNormalChargingOrder() {
+        TChargingOrder chargingOrder = new TChargingOrder();
+        chargingOrder.setId(2002L);
+        chargingOrder.setAppUserCarId(55L);
+        chargingOrder.setCode("CD_2002");
+        when(chargingOrderService.getById(2002L)).thenReturn(chargingOrder);
+        TAppUser appUser = new TAppUser();
+        appUser.setId(88L);
+        appUser.setWxOpenid("openid_88");
+        when(appUserClient.getUserById(88L)).thenReturn(R.ok(appUser));
+        when(orderEvaluateMapper.insert(any(TOrderEvaluate.class))).thenReturn(1);
+
+        AjaxResult result = service.addOrderEvaluate(buildQuery(2002L, 1));
+
+        assertTrue(result.isSuccess());
+        ArgumentCaptor<TOrderEvaluate> captor = ArgumentCaptor.forClass(TOrderEvaluate.class);
+        verify(orderEvaluateMapper).insert(captor.capture());
+        TOrderEvaluate saved = captor.getValue();
+        assertEquals(Integer.valueOf(1), saved.getOrderType());
+        assertEquals(Long.valueOf(55L), saved.getAppUserCarId());
+        verify(vinChargingOrderService, never()).getById(anyLong());
+    }
+}
diff --git a/sql/20261013_order_evaluate_vin_type.sql b/sql/20261013_order_evaluate_vin_type.sql
new file mode 100644
index 0000000..a312407
--- /dev/null
+++ b/sql/20261013_order_evaluate_vin_type.sql
@@ -0,0 +1,6 @@
+-- VIN码充电订单评价:t_order_evaluate.order_type 新增取值 5=VIN码充电订单
+-- 背景:小程序 VIN 码充电订单列表"评价/查看评价"原先按 order_type=1 提交,后端按普通充电订单表查询导致空指针;
+--       现改为独立类型 5,与普通充电订单(1)区分,本脚本仅更新字段注释,无表结构调整。
+-- 执行环境:测试库已执行,其他环境发版前同步执行
+ALTER TABLE `t_order_evaluate`
+    MODIFY COLUMN `order_type` int NULL DEFAULT NULL COMMENT '订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单,5=VIN码充电订单)';
diff --git a/sql/charging_pile_order.sql b/sql/charging_pile_order.sql
index 92a2216..4e37e5d 100644
--- a/sql/charging_pile_order.sql
+++ b/sql/charging_pile_order.sql
@@ -4287,7 +4287,7 @@
 DROP TABLE IF EXISTS `t_order_evaluate`;
 CREATE TABLE `t_order_evaluate`  (
   `id` bigint NOT NULL COMMENT '主键',
-  `order_type` int NULL DEFAULT NULL COMMENT '订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单)',
+  `order_type` int NULL DEFAULT NULL COMMENT '订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单,5=VIN码充电订单)',
   `order_id` bigint NULL DEFAULT NULL COMMENT '订单id',
   `app_user_id` bigint NULL DEFAULT NULL COMMENT '用户id',
   `mark` int NULL DEFAULT NULL COMMENT '评分',

--
Gitblit v1.7.1