فهرست منبع

refactor(订单): 删除旧用户端外卖与闪送列表接口,统一走统一订单列表

- 删 GET /system/userOrder/orderList 及 applyTabFilter/enrichOrderData;tab 语义已由 UnifiedOrderTab 承接且有独立测试覆盖
- 删 GET /system/flashDelivery/orders 及 userOrders/userOrderListView/mapPage/FlashDeliveryUserOrderListView
- 收件人卡片 deliveryAddress 换成本人站点的隐私逻辑移植进统一列表 flashItem,多站单不再向收件人暴露他人收货地址
- 修复 FlashDeliveryRiderOrderListViewTest 骑手字段集缺 stops(前两次提交遗漏更新该契约测试)
- 文档同步:app-api 7.4 标注删除并指向统一列表,v2 handoff 更新用户列表入口
qmj 4 روز پیش
والد
کامیت
30c31c06be
15فایلهای تغییر یافته به همراه37 افزوده شده و 484 حذف شده
  1. 2 18
      docs/flash-delivery-app-api.md
  2. 1 1
      docs/flash-delivery-v2-frontend-handoff.md
  3. 0 17
      ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryUserController.java
  4. 0 72
      ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryUserOrderListView.java
  5. 0 83
      ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationService.java
  6. 0 84
      ruoyi-admin/src/main/java/com/ruoyi/app/order/UserOrderController.java
  7. 11 2
      ruoyi-admin/src/main/java/com/ruoyi/app/unifiedorder/UnifiedOrderQueryService.java
  8. 1 1
      ruoyi-admin/src/main/java/com/ruoyi/app/unifiedorder/dto/UnifiedOrderListItem.java
  9. 4 7
      ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryControllerContractTest.java
  10. 1 13
      ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderListViewTest.java
  11. 0 43
      ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationServiceTest.java
  12. 0 52
      ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryV2Test.java
  13. 0 37
      ruoyi-admin/src/test/java/com/ruoyi/app/order/OrderListPaymentFilterTest.java
  14. 0 54
      ruoyi-admin/src/test/java/com/ruoyi/app/order/UserOrderTabFilterTest.java
  15. 17 0
      ruoyi-admin/src/test/java/com/ruoyi/app/unifiedorder/UnifiedOrderQueryServiceTest.java

+ 2 - 18
docs/flash-delivery-app-api.md

@@ -673,25 +673,9 @@ POST /system/flashDelivery/orders
 
 创建时,后端会移除收件手机号中的空白、`+`、`-`、`(`、`)` 后,匹配有效且未删除的普通用户账号。仅在恰好匹配一个账号时把该账号固化为收件人;无匹配或重复匹配均不绑定。此绑定只执行一次,历史订单不会因收件人之后注册或修改手机号而自动认领。
 
-### 7.4 查询用户订单列表
+### 7.4 查询用户订单列表(已删除,改用统一订单列表)
 
-```http
-GET /system/flashDelivery/orders?page=1&size=10&role=sender
-```
-
-查询参数:
-
-| 参数 | 必填 | 说明 |
-|---|---:|---|
-| `page` | 否 | 默认 `1`,小于 `1` 时按 `1` 处理 |
-| `size` | 否 | 默认 `10`,范围为 `1` 至 `100` |
-| `role` | 否 | `sender` 查询“我发的”,`receiver` 查询“我收的”;默认 `sender` |
-
-仅查询当前用户作为指定角色的订单,按创建时间倒序返回全部状态的订单摘要。接口不接受 `status`、`scene` 或 `serviceType`;响应 `data.records` 中每项为用户列表摘要对象。
-
-`role` 只接受 `sender` 或 `receiver`,不区分大小写;传空值按 `sender` 处理,传其他值返回业务错误。“我收的”依据订单当前绑定的收件账号;创建时匹配,确认修改取送信息时重新匹配收件电话,查询时不会重新按手机号匹配。
-
-设计原型中的“待接单、配送中、已完成、已取消”筛选页签当前没有对应查询参数。第一版建议只展示“全部”列表;如需页签,只能基于当前页数据本地过滤,且不应依赖它得到准确的分页总数。
+`GET /system/flashDelivery/orders` 已于 2026-10-15 删除,用户端订单列表统一走 `GET /system/unifiedOrder/list`(外卖与闪送合并,游标分页)。原 `role=sender|receiver` 语义由统一列表的 `role` 字段承接:寄件人条目 `role=sender`,收件人条目 `role=receiver`;收件人条目的 `deliveryAddress` 为本人站点地址,多站点单附 `stops` 逐站列表与双进度计数。
 
 ### 7.5 查询用户订单详情
 

+ 1 - 1
docs/flash-delivery-v2-frontend-handoff.md

@@ -66,7 +66,7 @@
 
 ## 订单详情、收件人和进度
 
-- 用户列表:`GET /system/flashDelivery/orders?role=sender|receiver&page=1&size=10`;`receiver` 包括每一个已匹配到系统普通用户的收货站。收件人列表卡片展示自己的收货地址。
+- 用户列表:统一订单列表 `GET /system/unifiedOrder/list`(2026-10-15 起旧闪送专属列表 `GET /system/flashDelivery/orders` 已删除);`receiver` 角色条目包括每一个已匹配到系统普通用户的收货站。收件人列表卡片展示自己的收货地址:`deliveryAddress` 已换成本人站点,`stops` 里其余站只留类型/序号/状态。
 - 用户详情:`GET /system/flashDelivery/orders/{id}`;按订单号打开消息:`GET /system/flashDelivery/orders/byOrderNo?orderNo=...`。
 - 骑手列表与详情:`GET /system/flashDelivery/rider/orders`、`GET /system/flashDelivery/rider/orders/{id}`,沿用原有 `tab`、分页和可选坐标参数。
 

+ 0 - 17
ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryUserController.java

@@ -69,23 +69,6 @@ public class FlashDeliveryUserController extends BaseController {
         }
     }
 
-    /**
-     * 分页查询当前用户参与的闪送订单。
-     *
-     * @param token 登录令牌,用于解析当前用户 ID
-     * @param page 页码,从 1 开始,默认 1
-     * @param size 每页数量,默认 10,服务端限制为 1 至 100
-     * @param role 订单角色;sender 表示我发的,receiver 表示我收的,不传按 sender 处理
-     */
-    @GetMapping("/orders")
-    @Auth
-    public AjaxResult orders(@RequestHeader String token,
-                             @RequestParam(defaultValue = "1") int page,
-                             @RequestParam(defaultValue = "10") int size,
-                             @RequestParam(required = false) String role) {
-        return success(service.userOrders(userId(token), page, size, role));
-    }
-
     /** 查询本人订单详情,直接返回订单字段和按类型分组的履约图片。 */
     @GetMapping("/orders/{id}")
     @Auth

+ 0 - 72
ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryUserOrderListView.java

@@ -1,72 +0,0 @@
-package com.ruoyi.app.flashdelivery.dto;
-
-import lombok.Data;
-
-import java.util.Date;
-
-/** 用户端闪送订单卡片,仅包含列表页面所需字段。 */
-@Data
-public class FlashDeliveryUserOrderListView {
-    /** 订单 ID。 */
-    private Long id;
-    /** 订单号。 */
-    private String orderNo;
-    /** 业务场景:HELP_SEND=帮送、HELP_PICKUP=帮取。 */
-    private String serviceType;
-    /** 配送等级:NORMAL=普通、URGENT=加急。 */
-    private String deliveryType;
-    /** 配送车型:1=机车、2=轿车。 */
-    private Integer vehicleType;
-    /** 订单状态,取值见 FlashDeliveryStatus。 */
-    private String status;
-    /** 用户编辑待接单订单使用的乐观锁版本。 */
-    private Integer orderVersion;
-    /** 物品类别。 */
-    private String packageType;
-    /** 物品数量。 */
-    private Integer quantity;
-    /** 重量范围。 */
-    private String weightRange;
-    /** 取件方式:NOW=立即、SCHEDULED=预约。 */
-    private String deliveryMode;
-    /** 预约取件时间窗开始时间,立即单为空。 */
-    private Date scheduledPickupStartAt;
-    /** 预约取件时间窗结束时间,立即单为空。 */
-    private Date scheduledPickupEndAt;
-    /** 取件主地址。 */
-    private String pickupAddress;
-    /** 取件详细地址。 */
-    private String pickupDetailAddress;
-    /** 收件主地址。 */
-    private String deliveryAddress;
-    /** 收件详细地址。 */
-    private String deliveryDetailAddress;
-    /** 预计配送时长(秒)。 */
-    private Integer estimatedDurationSeconds;
-    /** 基础配送费(TWD),仅表示起步价,不含距离附加费。 */
-    private Long baseDeliveryFee;
-    /** 加急费(TWD),普通配送为 0。 */
-    private Long urgentFee;
-    /** 小费(TWD)。 */
-    private Long tipAmount;
-    /** 订单总金额(TWD)。 */
-    private Long amount;
-    /** 币种。 */
-    private String currency;
-    /** 收款状态:0=未收款,1=骑手已确认收款。 */
-    private Integer paymentStatus;
-    /** 送达时间。 */
-    private Date deliveredAt;
-    /** 创建时间。 */
-    private Date createTime;
-    /** 取货站总数及已实际确认的取货站数。 */
-    private Integer pickupStopCount;
-    private Integer pickedUpStopCount;
-    /** 收货站总数与已送达数;历史单按单收货站兼容。 */
-    private Integer deliveryStopCount;
-    private Integer deliveredStopCount;
-    /** 任一站已取货即禁止用户自助取消,不能仅按订单主状态判断。 */
-    private Boolean canUserCancel;
-    /** v2 多站点单的逐站列表(用户顺序);寄件人全站文字地址,收件人仅本站,其余站只留类型/序号/状态。 */
-    private java.util.List<FlashDeliveryStopView> stops;
-}

+ 0 - 83
ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationService.java

@@ -38,7 +38,6 @@ import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Function;
 
 import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.*;
 
@@ -299,43 +298,6 @@ public class FlashDeliveryApplicationService {
         return message != null && message.contains("uk_flash_order_no");
     }
 
-    /** 分页查询当前用户参与的订单卡片;role=sender 按寄件人、receiver 按收件人过滤。 */
-    public IPage<FlashDeliveryUserOrderListView> userOrders(Long userId, int pageNum, int pageSize, String role) {
-        String selectedRole = hasText(role) ? role.trim().toLowerCase(Locale.ROOT) : "sender";
-        if (!"sender".equals(selectedRole) && !"receiver".equals(selectedRole)) {
-            throw fail("flash.delivery.tab.invalid");
-        }
-        QueryWrapper<FlashDeliveryOrder> query = new QueryWrapper<>();
-        if ("receiver".equals(selectedRole)) {
-            query.and(participant -> participant.eq("receiver_user_id", userId)
-                    .or().apply("exists (select 1 from flash_delivery_order_stop s where s.order_id = flash_delivery_order.id "
-                            + "and s.stop_type = 'DELIVERY' and s.receiver_user_id = {0})", userId));
-        } else {
-            query.eq("user_id", userId);
-        }
-        query.orderByDesc("create_time");
-        IPage<FlashDeliveryOrder> orders = orderMapper.selectPage(page(pageNum, pageSize), query);
-        Map<Long, List<FlashDeliveryOrderStop>> stopRows = stopRowsFor(orders.getRecords());
-        return mapPage(orders, order -> {
-            FlashDeliveryUserOrderListView view = userOrderListView(order);
-            List<FlashDeliveryOrderStop> rows = stopRows.get(order.getId());
-            if ("receiver".equals(selectedRole) && order.getDeliveryStopCount() != null
-                    && !Objects.equals(userId, order.getUserId()) && rows != null) {
-                rows.stream().filter(s -> "DELIVERY".equals(s.getStopType())
-                        && Objects.equals(userId, s.getReceiverUserId())).findFirst().ifPresent(own -> {
-                    view.setDeliveryAddress(own.getAddress());
-                    view.setDeliveryDetailAddress(own.getAddressDetail());
-                });
-            }
-            // v2 多站点卡片逐站展示;寄件人全站文字地址,收件人仅本站,其余站只留类型/序号/状态。
-            if (order.getDeliveryStopCount() != null && rows != null && !rows.isEmpty()) {
-                view.setStops(FlashDeliveryUserCardStops.of(rows, userId, Objects.equals(userId, order.getUserId())));
-            }
-            view.setCanUserCancel(Objects.equals(userId, order.getUserId()) && canUserCancel(order));
-            return view;
-        });
-    }
-
     /** 查询本人订单详情,仅寄件人和匹配到的收件人可见。 */
     public FlashDeliveryOrderDetailView userDetail(Long userId, Long orderId) {
         return userDetail(userId, requireOrder(orderId));
@@ -1569,43 +1531,6 @@ public class FlashDeliveryApplicationService {
         return view;
     }
 
-    /** 订单实体转用户端订单卡片。 */
-    private FlashDeliveryUserOrderListView userOrderListView(FlashDeliveryOrder order) {
-        FlashDeliveryUserOrderListView view = new FlashDeliveryUserOrderListView();
-        view.setId(order.getId());
-        view.setOrderNo(order.getOrderNo());
-        view.setServiceType(order.getServiceType());
-        view.setDeliveryType(order.getDeliveryType());
-        view.setVehicleType(vehicleTypeOf(order));
-        view.setStatus(order.getStatus());
-        view.setPickupStopCount(order.getPickupStopCount());
-        view.setPickedUpStopCount(order.getPickedUpStopCount());
-        view.setDeliveryStopCount(expectedDeliveryStopCount(order));
-        view.setDeliveredStopCount(deliveredStopCount(order));
-        view.setCanUserCancel(canUserCancel(order));
-        view.setOrderVersion(order.getVersion());
-        view.setPackageType(order.getPackageType());
-        view.setQuantity(order.getQuantity());
-        view.setWeightRange(order.getWeightRange());
-        view.setDeliveryMode(order.getDeliveryMode());
-        view.setScheduledPickupStartAt(order.getScheduledPickupStartAt());
-        view.setScheduledPickupEndAt(order.getScheduledPickupEndAt());
-        view.setPickupAddress(order.getPickupAddress());
-        view.setPickupDetailAddress(order.getPickupAddressDetail());
-        view.setDeliveryAddress(order.getDeliveryAddress());
-        view.setDeliveryDetailAddress(order.getDeliveryAddressDetail());
-        view.setEstimatedDurationSeconds(order.getEstimatedDurationSeconds());
-        view.setBaseDeliveryFee(order.getBaseDeliveryFee());
-        view.setUrgentFee(order.getUrgentFee());
-        view.setTipAmount(order.getTipAmount());
-        view.setAmount(order.getAmount());
-        view.setCurrency(order.getCurrency());
-        view.setPaymentStatus(order.getPaymentStatus());
-        view.setDeliveredAt(order.getDeliveredAt());
-        view.setCreateTime(order.getCreateTime());
-        return view;
-    }
-
     /** 订单实体转骑手端任务卡片,可附带骑手到取件点的直线距离。 */
     /** 列表页一次 IN 批量取回 v2 多站点单的站点,避免逐单 N+1;单点单卡片不需要逐站展示。 */
     private Map<Long, List<FlashDeliveryOrderStop>> stopRowsFor(List<FlashDeliveryOrder> records) {
@@ -1935,14 +1860,6 @@ public class FlashDeliveryApplicationService {
         return new Page<>(Math.max(1, pageNum), Math.min(Math.max(1, pageSize), 100));
     }
 
-    /** 分页结果实体转换,保留分页元数据。 */
-    private <T> IPage<T> mapPage(IPage<FlashDeliveryOrder> source,
-                                 Function<FlashDeliveryOrder, T> mapper) {
-        Page<T> result = new Page<>(source.getCurrent(), source.getSize(), source.getTotal());
-        result.setRecords(source.getRecords().stream().map(mapper).toList());
-        return result;
-    }
-
     /** 按页签构建骑手任务查询:newTask 限定可抢状态与时间窗,可选距离过滤和就近排序。 */
     private QueryWrapper<FlashDeliveryOrder> riderOrdersQuery(Long riderId, Integer riderVehicleType, String tab,
                                                                 BigDecimal longitude, BigDecimal latitude,

+ 0 - 84
ruoyi-admin/src/main/java/com/ruoyi/app/order/UserOrderController.java

@@ -566,90 +566,6 @@ public class UserOrderController extends BaseController {
         return success(distance);
     }
 
-    /**
-     * 用户端订单列表(Tab分页)
-     */
-    @GetMapping("/orderList")
-    @Auth
-    @Anonymous
-    public AjaxResult orderList(@RequestHeader String token,
-                                @RequestParam(defaultValue = "1") int page,
-                                @RequestParam(defaultValue = "10") int size,
-                                @RequestParam(required = false) String tab,
-                                @RequestParam(required = false) String type) {
-        JwtUtil jwtUtil = new JwtUtil();
-        String userId = jwtUtil.getusid(token);
-
-        LambdaQueryWrapper<PosOrder> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(PosOrder::getUserId, Long.valueOf(userId));
-
-        // 类型筛选
-        if (type != null && !type.isEmpty()) {
-            wrapper.eq(PosOrder::getType, Long.valueOf(type));
-        }
-
-        applyTabFilter(wrapper, tab);
-        wrapper.orderByDesc(PosOrder::getCretim);
-
-        // 分页
-        com.baomidou.mybatisplus.extension.plugins.pagination.Page<PosOrder> pageParam =
-                new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(page, size);
-        com.baomidou.mybatisplus.extension.plugins.pagination.Page<PosOrder> result = posOrderService.page(pageParam, wrapper);
-
-        // 附加关联数据
-        for (PosOrder order : result.getRecords()) {
-            enrichOrderData(order);
-        }
-
-        java.util.Map<String, Object> data = new java.util.LinkedHashMap<>();
-        data.put("records", result.getRecords());
-        data.put("total", result.getTotal());
-        data.put("page", page);
-        data.put("size", size);
-        return success(result);
-    }
-
-    /** 订单列表页签过滤条件(031 US7 抽取便于单测):unpaid 仅在线支付;active 放行到付与现金自取/堂食。 */
-    static void applyTabFilter(LambdaQueryWrapper<PosOrder> wrapper, String tab) {
-        switch (tab) {
-            case "unpaid":
-                // 在线支付订单不区分配送类型;自取/堂食未付款也必须先留在待付款。
-                wrapper.eq(PosOrder::getPayStatus, 0L)
-                       .in(PosOrder::getPayType, "2", "3")
-                       .ne(PosOrder::getState, 4L)
-                       .eq(PosOrder::getAfterSaleStatus, 0L);
-                break;
-            case "active":
-                wrapper.in(PosOrder::getState, 0L, 1L, 2L)
-                       .eq(PosOrder::getAfterSaleStatus, 0L)
-                       // 到付/现金自取堂食可以线下收款;OMG、LINE Pay 等在线订单必须已付款才能履约。
-                       .and(w -> w.eq(PosOrder::getPayStatus, 1L)
-                               .or(cod -> cod.in(PosOrder::getPayType, "1", "4")
-                                       .in(PosOrder::getType, 1L, 2L)));
-                break;
-            case "completed":
-                wrapper.eq(PosOrder::getState, 3L).eq(PosOrder::getAfterSaleStatus, 0L);
-                break;
-            case "cancelled":
-                wrapper.eq(PosOrder::getState, 4L).eq(PosOrder::getAfterSaleStatus, 0L);
-                break;
-            case "refund":
-                wrapper.gt(PosOrder::getAfterSaleStatus, 0L);
-                break;
-            default:
-               break;
-        }
-    }
-
-    private void enrichOrderData(PosOrder order) {
-        try {
-            if (order.getShId() != null) {
-                InfoUser shanghu = infoUserService.getById(order.getShId());
-                order.setPriceAll(shanghu != null ? String.valueOf(shanghu.getNickName()) : null);
-            }
-        } catch (Exception ignored) {}
-    }
-
     /**
      * 确认取餐(自取类型订单,state=2 → state=3)
      */

+ 11 - 2
ruoyi-admin/src/main/java/com/ruoyi/app/unifiedorder/UnifiedOrderQueryService.java

@@ -250,14 +250,23 @@ public class UnifiedOrderQueryService {
         item.setPackageType(order.getPackageType());
         item.setQuantity(order.getQuantity());
         item.setTipAmount(order.getTipAmount());
-        // v2 多站点单补双进度计数与逐站列表;卡片脱敏口径与闪送专属列表一致。
+        // v2 多站点单补双进度计数与逐站列表;卡片脱敏口径与原闪送专属列表一致。
         if (order.getDeliveryStopCount() != null) {
             item.setPickupStopCount(order.getPickupStopCount());
             item.setPickedUpStopCount(order.getPickedUpStopCount());
             item.setDeliveryStopCount(order.getDeliveryStopCount());
             item.setDeliveredStopCount(order.getDeliveredStopCount());
             if (stopRows != null && !stopRows.isEmpty()) {
-                item.setStops(FlashDeliveryUserCardStops.of(stopRows, userId, Objects.equals(userId, order.getUserId())));
+                boolean sender = Objects.equals(userId, order.getUserId());
+                item.setStops(FlashDeliveryUserCardStops.of(stopRows, userId, sender));
+                // 收件人看他人多站单:deliveryAddress 换成本人站点,避免暴露他人收货地址。
+                if (!sender) {
+                    stopRows.stream().filter(s -> "DELIVERY".equals(s.getStopType())
+                            && Objects.equals(userId, s.getReceiverUserId())).findFirst().ifPresent(own -> {
+                        item.setDeliveryAddress(own.getAddress());
+                        item.setDeliveryDetailAddress(own.getAddressDetail());
+                    });
+                }
             }
         }
         return item;

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/app/unifiedorder/dto/UnifiedOrderListItem.java

@@ -61,7 +61,7 @@ public class UnifiedOrderListItem {
 
     /** 闪送状态:WAITING_ACCEPTANCE/ACCEPTED/PICKED_UP/DELIVERED/COMPLETED/CANCELLED。 */
     private String status;
-    /** 闪送乐观锁版本(用户编辑待接单订单须回传,同 FlashDeliveryUserOrderListView.orderVersion)。 */
+    /** 闪送乐观锁版本(用户编辑待接单订单须回传,与订单详情的 orderVersion 同源)。 */
     private Integer orderVersion;
     /** 业务场景:HELP_SEND=帮送、HELP_PICKUP=帮取。 */
     private String serviceType;

+ 4 - 7
ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryControllerContractTest.java

@@ -176,13 +176,10 @@ class FlashDeliveryControllerContractTest {
 
     @Test
     void appOrderListsUseSimplePageAndRiderFoodOrderParameters() throws Exception {
-        Method userOrders = FlashDeliveryUserController.class.getMethod("orders",
-                String.class, int.class, int.class, String.class);
-        assertNotNull(userOrders.getParameters()[0].getAnnotation(RequestHeader.class));
-        assertNotNull(userOrders.getParameters()[1].getAnnotation(RequestParam.class));
-        assertNotNull(userOrders.getParameters()[2].getAnnotation(RequestParam.class));
-        assertNotNull(userOrders.getParameters()[3].getAnnotation(RequestParam.class));
-        assertTrue(!userOrders.getParameters()[3].getAnnotation(RequestParam.class).required());
+        // 用户端闪送专属列表已删除(改用统一订单列表);骑手列表契约保持原样。
+        assertThrows(NoSuchMethodException.class,
+                () -> FlashDeliveryUserController.class.getMethod("orders",
+                        String.class, int.class, int.class, String.class));
 
         Method riderOrders = FlashDeliveryRiderController.class.getMethod("orders",
                 String.class, int.class, int.class, String.class, BigDecimal.class, BigDecimal.class);

+ 1 - 13
ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderListViewTest.java

@@ -7,18 +7,6 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 class FlashDeliveryRiderOrderListViewTest {
-    @Test
-    void userListContainsOnlyFieldsRequiredByOrderCards() {
-        Set<String> fields = Stream.of(FlashDeliveryUserOrderListView.class.getDeclaredFields())
-                .map(java.lang.reflect.Field::getName).collect(Collectors.toSet());
-        Set<String> expected = Set.of("id", "orderNo", "serviceType", "deliveryType", "vehicleType", "status", "packageType",
-                "quantity", "weightRange", "baseDeliveryFee", "urgentFee", "tipAmount",
-                "deliveryMode", "scheduledPickupStartAt", "scheduledPickupEndAt", "pickupAddress",
-                "pickupDetailAddress", "deliveryAddress", "deliveryDetailAddress",
-                "estimatedDurationSeconds", "amount", "currency", "paymentStatus", "deliveredAt", "createTime", "orderVersion", "pickupStopCount", "pickedUpStopCount", "deliveryStopCount", "deliveredStopCount", "canUserCancel");
-        org.junit.jupiter.api.Assertions.assertEquals(expected, fields);
-    }
-
     @Test
     void riderListContainsOnlyFieldsRequiredByOrderCards() {
         Set<String> fields = Stream.of(FlashDeliveryRiderOrderListView.class.getDeclaredFields())
@@ -29,7 +17,7 @@ class FlashDeliveryRiderOrderListViewTest {
                 "pinRequired", "pickupAddress", "pickupDetailAddress", "deliveryAddress",
                 "deliveryDetailAddress", "pickupDistanceMeters", "distanceMeters",
                 "estimatedDurationSeconds", "baseDeliveryFee", "distanceFee", "urgentFee",
-                "tipAmount", "amount", "currency", "paymentStatus", "createTime", "payType", "pickupStopCount", "pickedUpStopCount", "deliveryStopCount", "deliveredStopCount", "canUserCancel", "userNote");
+                "tipAmount", "amount", "currency", "paymentStatus", "createTime", "payType", "pickupStopCount", "pickedUpStopCount", "deliveryStopCount", "deliveredStopCount", "canUserCancel", "userNote", "stops");
         org.junit.jupiter.api.Assertions.assertEquals(expected, fields);
     }
 

+ 0 - 43
ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationServiceTest.java

@@ -266,33 +266,6 @@ class FlashDeliveryApplicationServiceTest {
         verify(fixture.logMapper, never()).insert(any(com.ruoyi.system.domain.flash.FlashDeliveryOrderLog.class));
     }
 
-    @Test
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    void userListOnlyFiltersByOwnerAndReturnsCardFields() {
-        Fixture fixture = new Fixture();
-        FlashDeliveryOrder order = order(10L, "COMPLETED");
-        order.setWeightRange("OVER_5_TO_10_KG");
-        Page<FlashDeliveryOrder> source = new Page<>(1, 10, 1);
-        source.setRecords(List.of(order));
-        when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
-                any(Wrapper.class))).thenReturn(source);
-
-        var result = fixture.service.userOrders(7L, 1, 10, null);
-
-        ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.QueryWrapper> query =
-                ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
-        verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class), query.capture());
-        String sql = query.getValue().getSqlSegment().toLowerCase();
-        var parameters = query.getValue().getParamNameValuePairs().values();
-        assertTrue(sql.contains("user_id"));
-        assertFalse(sql.contains("status"));
-        assertFalse(sql.contains("service_type"));
-        assertTrue(parameters.contains(7L));
-        assertEquals("pickup road", result.getRecords().get(0).getPickupAddress());
-        assertEquals("OVER_5_TO_10_KG", result.getRecords().get(0).getWeightRange());
-        assertEquals(112L, result.getRecords().get(0).getAmount());
-    }
-
     @Test
     void createDoesNotBindReceiverWhenNormalizedPhoneMatchesMultipleUsers() {
         Fixture fixture = new Fixture();
@@ -335,22 +308,6 @@ class FlashDeliveryApplicationServiceTest {
         assertNull(saved.getValue().getReceiverUserId());
     }
 
-    @Test
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    void receiverListFiltersByCreationTimeReceiverBinding() {
-        Fixture fixture = new Fixture();
-        when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
-                any(Wrapper.class))).thenReturn(new Page<FlashDeliveryOrder>());
-
-        fixture.service.userOrders(88L, 1, 10, "receiver");
-
-        ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.QueryWrapper> query =
-                ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
-        verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class), query.capture());
-        assertTrue(query.getValue().getSqlSegment().toLowerCase().contains("receiver_user_id"));
-        assertTrue(query.getValue().getParamNameValuePairs().values().contains(88L));
-    }
-
     @Test
     @SuppressWarnings({"rawtypes", "unchecked"})
     void riderNewTaskUsesFoodOrderParametersAndReturnsPrototypeCardSummary() {

+ 0 - 52
ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryV2Test.java

@@ -364,58 +364,6 @@ class FlashDeliveryV2Test {
         assertThrows(ServiceException.class, () -> f.service.userDetail(99L, 10L));
     }
 
-    @Test void receiverOrderQueryIncludesEveryBoundDeliveryStopWithBoundParameters() {
-        Fixture f = ready(); receivers(f);
-        when(f.orders.selectPage(any(), any())).thenReturn(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<FlashDeliveryOrder>());
-        f.service.userOrders(32L, 1, 10, "receiver");
-        var query = org.mockito.ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
-        verify(f.orders).selectPage(any(), query.capture());
-        String sql = query.getValue().getSqlSegment();
-        assertTrue(sql.contains("flash_delivery_order_stop"));
-        assertTrue(sql.contains("receiver_user_id"));
-        assertTrue(query.getValue().getParamNameValuePairs().containsValue(32L));
-    }
-
-    @Test void secondReceiverOrderCardShowsOwnDeliveryAddress() {
-        Fixture f = ready(); receivers(f);
-        f.order.setDeliveryAddress("first receiver address");
-        f.order.setDeliveryAddressDetail("first receiver floor");
-        f.rows.get(3).setAddressDetail("second receiver floor");
-        var page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<FlashDeliveryOrder>(1, 10);
-        page.setRecords(List.of(f.order));
-        when(f.orders.selectPage(any(), any())).thenReturn(page);
-        FlashDeliveryUserOrderListView card = f.service.userOrders(32L, 1, 10, "receiver").getRecords().get(0);
-        assertEquals("address 3", card.getDeliveryAddress());
-        assertEquals("second receiver floor", card.getDeliveryDetailAddress());
-    }
-
-    @Test void userListCardsCarryStopsForSenderAndMaskOtherStopsForReceiver() {
-        Fixture f = ready(); receivers(f);
-        f.rows.get(0).setRemark("取月餅"); f.rows.get(3).setRemark("送前台");
-        var page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<FlashDeliveryOrder>(1, 10);
-        page.setRecords(List.of(f.order));
-        when(f.orders.selectPage(any(), any())).thenReturn(page);
-        // 寄件人卡片:全站文字地址与备注可见,联系人、电话、坐标仍不落卡片。
-        var senderCard = f.service.userOrders(7L, 1, 10, null).getRecords().get(0);
-        assertEquals(List.of("address 0", "address 1", "address 2", "address 3"),
-                senderCard.getStops().stream().map(FlashDeliveryStopView::getAddress).toList());
-        assertEquals(java.util.Arrays.asList("取月餅", null, null, "送前台"),
-                senderCard.getStops().stream().map(FlashDeliveryStopView::getRemark).toList());
-        assertEquals(List.of("PICKED_UP", "PICKED_UP", "PENDING", "PENDING"),
-                senderCard.getStops().stream().map(FlashDeliveryStopView::getStatus).toList());
-        assertNull(senderCard.getStops().get(0).getName());
-        assertNull(senderCard.getStops().get(0).getPhone());
-        assertNull(senderCard.getStops().get(0).getLongitude());
-        // 收件人卡片(32 号用户绑定第 4 站):仅本站保留地址与备注,其余站只留类型/序号/状态。
-        var receiverCard = f.service.userOrders(32L, 1, 10, "receiver").getRecords().get(0);
-        assertEquals(java.util.Arrays.asList(null, null, null, "address 3"),
-                receiverCard.getStops().stream().map(FlashDeliveryStopView::getAddress).toList());
-        assertEquals(java.util.Arrays.asList(null, null, null, "送前台"),
-                receiverCard.getStops().stream().map(FlashDeliveryStopView::getRemark).toList());
-        assertEquals(List.of("PICKUP", "PICKUP", "DELIVERY", "DELIVERY"),
-                receiverCard.getStops().stream().map(FlashDeliveryStopView::getStopType).toList());
-    }
-
     @Test void legacyDeliveryRejectsV2OrdersIncludingSingleDropoffBeforeAnyWrite() {
         for (int count : List.of(1, 2)) {
             Fixture f = ready(); if (count == 1) f.rows.remove(3); f.order.setDeliveryStopCount(count);

+ 0 - 37
ruoyi-admin/src/test/java/com/ruoyi/app/order/OrderListPaymentFilterTest.java

@@ -50,43 +50,6 @@ class OrderListPaymentFilterTest {
                 new MapperBuilderAssistant(new MybatisConfiguration(), ""), PosOrder.class);
     }
 
-    @Test
-    void userUnpaidTabIncludesOnlinePickupAndDineInOrders() {
-        IPosOrderService orders = mock(IPosOrderService.class);
-        UserOrderController controller = new UserOrderController();
-        ReflectionTestUtils.setField(controller, "posOrderService", orders);
-        when(orders.page(any(Page.class), any(Wrapper.class))).thenReturn(new Page<>());
-
-        controller.orderList(tokenFor(909L), 1, 10, "unpaid", null);
-
-        LambdaQueryWrapper<PosOrder> query = capturedQuery(orders);
-        String sql = query.getSqlSegment();
-        Collection<Object> parameters = new ArrayList<>(query.getParamNameValuePairs().values());
-        assertTrue(sql.contains("pay_type IN"));
-        assertFalse(sql.contains("AND type ="));
-        assertEquals(1, Collections.frequency(parameters, "2"));
-        assertEquals(1, Collections.frequency(parameters, "3"));
-    }
-
-    @Test
-    void userActiveTabAllowsUnpaidPickupAndDineInOnlyForCashPayment() {
-        IPosOrderService orders = mock(IPosOrderService.class);
-        UserOrderController controller = new UserOrderController();
-        ReflectionTestUtils.setField(controller, "posOrderService", orders);
-        when(orders.page(any(Page.class), any(Wrapper.class))).thenReturn(new Page<>());
-
-        controller.orderList(tokenFor(909L), 1, 10, "active", null);
-
-        LambdaQueryWrapper<PosOrder> query = capturedQuery(orders);
-        String sql = query.getSqlSegment();
-        Collection<Object> parameters = new ArrayList<>(query.getParamNameValuePairs().values());
-        assertTrue(sql.contains("(pay_status ="));
-        assertTrue(sql.contains("OR (pay_type IN"));
-        assertTrue(sql.contains("AND type IN"));
-        assertEquals(1, Collections.frequency(parameters, "1"));
-        assertEquals(1, Collections.frequency(parameters, "4"));
-    }
-
     @Test
     void merchantPendingTabDoesNotExposeUnpaidOnlinePickupOrDineInOrders() {
         IPosOrderService orders = mock(IPosOrderService.class);

+ 0 - 54
ruoyi-admin/src/test/java/com/ruoyi/app/order/UserOrderTabFilterTest.java

@@ -1,54 +0,0 @@
-package com.ruoyi.app.order;
-
-import com.baomidou.mybatisplus.core.MybatisConfiguration;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
-import com.ruoyi.system.domain.PosOrder;
-import org.apache.ibatis.builder.MapperBuilderAssistant;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-import java.util.Collection;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-/** 订单列表页签过滤单测(031 US7 T027):现金自取/堂食进 active、不进 unpaid。 */
-class UserOrderTabFilterTest {
-
-    @BeforeAll
-    static void initTableInfo() {
-        // Lambda 方法引用依赖 PosOrder 的 TableInfo 缓存
-        TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), PosOrder.class);
-    }
-
-    private static LambdaQueryWrapper<PosOrder> wrapperOf(String tab) {
-        LambdaQueryWrapper<PosOrder> wrapper = new LambdaQueryWrapper<>();
-        UserOrderController.applyTabFilter(wrapper, tab);
-        return wrapper;
-    }
-
-    @Test
-    void activeTabIncludesCashSelfPickupAndDineIn() {
-        LambdaQueryWrapper<PosOrder> wrapper = wrapperOf("active");
-        String sql = wrapper.getSqlSegment().toLowerCase();
-        Collection<Object> params = wrapper.getParamNameValuePairs().values();
-        assertTrue(sql.contains("pay_type in"));
-        assertTrue(params.contains("1"));
-        assertTrue(params.contains("4"));
-        assertTrue(sql.contains("type in"));
-        assertTrue(params.contains(1L));
-        assertTrue(params.contains(2L));
-    }
-
-    @Test
-    void unpaidTabExcludesCashOrders() {
-        LambdaQueryWrapper<PosOrder> wrapper = wrapperOf("unpaid");
-        String sql = wrapper.getSqlSegment().toLowerCase();
-        Collection<Object> params = wrapper.getParamNameValuePairs().values();
-        assertTrue(sql.contains("pay_type in"));
-        assertTrue(params.contains("2"));
-        assertTrue(params.contains("3"));
-        assertFalse(params.contains("4"), "待付款页签不得出现现金订单");
-    }
-}

+ 17 - 0
ruoyi-admin/src/test/java/com/ruoyi/app/unifiedorder/UnifiedOrderQueryServiceTest.java

@@ -62,6 +62,8 @@ class UnifiedOrderQueryServiceTest {
     void flashMultiStopOrderCarriesCountsAndReceiverMaskedStops() {
         FlashDeliveryOrder order = flash(31L, 3000L);
         order.setUserId(7L);
+        order.setDeliveryAddress("first receiver address");
+        order.setDeliveryAddressDetail("first receiver floor");
         order.setPickupStopCount(2); order.setPickedUpStopCount(1);
         order.setDeliveryStopCount(2); order.setDeliveredStopCount(0);
         doReturn(pageOf(List.of(order))).when(flashOrderMapper).selectPage(any(), any());
@@ -82,6 +84,21 @@ class UnifiedOrderQueryServiceTest {
                 item.getStops().stream().map(FlashDeliveryStopView::getAddress).toList());
         assertEquals(List.of("PICKUP", "PICKUP", "DELIVERY", "DELIVERY"),
                 item.getStops().stream().map(FlashDeliveryStopView::getStopType).toList());
+        // 卡片级收货地址同步换成本人站点,不暴露他人收货地址。
+        assertEquals("address 3", item.getDeliveryAddress());
+
+        // 寄件人视角:全站文字地址可见,联系人、电话、坐标仍不落卡片。
+        FlashDeliveryOrder ownOrder = flash(31L, 3000L);
+        ownOrder.setPickupStopCount(2); ownOrder.setPickedUpStopCount(1);
+        ownOrder.setDeliveryStopCount(2); ownOrder.setDeliveredStopCount(0);
+        doReturn(pageOf(List.of(ownOrder))).when(flashOrderMapper).selectPage(any(), any());
+        UnifiedOrderListItem senderItem = service.query(USER_ID, UnifiedOrderTab.ALL, null, null, 10).getList().get(0);
+        assertEquals("sender", senderItem.getRole());
+        assertEquals(List.of("address 0", "address 1", "address 2", "address 3"),
+                senderItem.getStops().stream().map(FlashDeliveryStopView::getAddress).toList());
+        assertNull(senderItem.getStops().get(0).getName());
+        assertNull(senderItem.getStops().get(0).getPhone());
+        assertNull(senderItem.getStops().get(0).getLongitude());
     }
 
     @Test