فهرست منبع

Merge remote-tracking branch 'origin/master' into master

肖路 3 روز پیش
والد
کامیت
6b9884dbd6

+ 13 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderMainController.java

@@ -25,6 +25,7 @@ import org.dromara.order.domain.dto.ChangeReturnedStatusRequestDto;
 import org.dromara.order.domain.vo.OrderMainVo;
 import org.dromara.order.domain.vo.OrderProductVo;
 import org.dromara.order.domain.vo.OrderStatusStats;
+import org.dromara.order.domain.vo.OrderTreeVo;
 import org.dromara.order.service.IOrderMainService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -243,4 +244,16 @@ public class OrderMainController extends BaseController {
         // 调用服务层方法
         return toAjax(orderMainService.changeReturnedStatusByIds(List.of(ids), returnedStatus));
     }
+
+    /**
+     * 查询订单及其所有子订单和商品(树形结构)
+     * 支持1级、2级、3级订单层级
+     *
+     * @param id 订单ID
+     */
+    @GetMapping("/tree/{id}")
+    public R<OrderTreeVo> getOrderTree(@NotNull(message = "主键不能为空")
+                                       @PathVariable("id") Long id) {
+        return R.ok(orderMainService.queryOrderWithChildren(id));
+    }
 }

+ 95 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderProductSimpleVo.java

@@ -0,0 +1,95 @@
+package org.dromara.order.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 订单商品简化视图对象
+ *
+ * @author LionLi
+ * @date 2026-05-26
+ */
+@Data
+public class OrderProductSimpleVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单商品明细ID
+     */
+    private Long id;
+
+    /**
+     * 订单ID
+     */
+    private Long orderId;
+
+    /**
+     * 产品ID
+     */
+    private Long productId;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 产品名称
+     */
+    private String productName;
+
+    /**
+     * 产品单位
+     */
+    private String productUnit;
+
+    /**
+     * 产品图片URL
+     */
+    private String productImage;
+
+    /**
+     * 订单单价
+     */
+    private BigDecimal orderPrice;
+
+    /**
+     * 订购数量
+     */
+    private Long orderQuantity;
+
+    /**
+     * 行小计金额
+     */
+    private BigDecimal subtotal;
+
+    /**
+     * 已发货数量
+     */
+    private Long quantitySent;
+
+    /**
+     * 未发货数量
+     */
+    private Long unsentQuantity;
+
+    /**
+     * 当前层级
+     */
+    private Integer currentLevel;
+
+    /**
+     * 分配状态
+     */
+    private String assignmentStatus;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 142 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderTreeVo.java

@@ -0,0 +1,142 @@
+package org.dromara.order.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 订单树形结构视图对象(包含订单及其所有子订单和商品)
+ *
+ * @author LionLi
+ * @date 2026-05-26
+ */
+@Data
+public class OrderTreeVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单ID
+     */
+    private Long id;
+
+    /**
+     * 订单编号
+     */
+    private String orderNo;
+
+    /**
+     * 父订单ID
+     */
+    private Long parentOrderId;
+
+    /**
+     * 父订单编号
+     */
+    private String parentOrderNo;
+
+    /**
+     * 当前层级(1-一级订单,2-二级订单,3-三级订单)
+     */
+    private Integer currentLevel;
+
+    /**
+     * 订单状态
+     */
+    private String orderStatus;
+
+    /**
+     * 支付状态
+     */
+    private String paymentStatus;
+
+    /**
+     * 审核状态
+     */
+    private String checkStatus;
+
+    /**
+     * 分配对象类型
+     */
+    private String assigneeType;
+
+    /**
+     * 分配对象ID
+     */
+    private Long assigneeId;
+
+    /**
+     * 分配对象名称
+     */
+    private String assigneeName;
+
+    /**
+     * 客户ID
+     */
+    private Long customerId;
+
+    /**
+     * 客户名称
+     */
+    private String customerName;
+
+    /**
+     * 订单总金额
+     */
+    private BigDecimal totalAmount;
+
+    /**
+     * 应付金额
+     */
+    private BigDecimal payableAmount;
+
+    /**
+     * 运费
+     */
+    private BigDecimal shippingFee;
+
+    /**
+     * 下单时间
+     */
+    private Date orderTime;
+
+    /**
+     * 确认时间
+     */
+    private Date confirmTime;
+
+    /**
+     * 发货时间
+     */
+    private Date shippingTime;
+
+    /**
+     * 收货时间
+     */
+    private Date receivingTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
+    /**
+     * 该订单的商品列表
+     */
+    private List<OrderProductSimpleVo> productList;
+
+    /**
+     * 子订单列表(递归结构)
+     */
+    private List<OrderTreeVo> childOrders;
+}

+ 10 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderMainService.java

@@ -164,4 +164,14 @@ public interface IOrderMainService extends IService<OrderMain> {
 
     void apiConfirmOrder(Long orderId, String orderNo);
 
+    /**
+     * 查询订单及其所有子订单和商品(树形结构)
+     * 支持1级、2级、3级订单层级
+     *
+     * @param orderId 订单ID
+     * @return 订单树形结构
+     */
+
+    OrderTreeVo queryOrderWithChildren(Long orderId);
+
 }

+ 183 - 3
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java

@@ -458,8 +458,8 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
         lqw.eq(StringUtils.isNotBlank(bo.getIsNeedCheck()), OrderMain::getIsNeedCheck, bo.getIsNeedCheck());
         lqw.eq(StringUtils.isNotBlank(bo.getReturnedStatus()), OrderMain::getReturnedStatus, bo.getReturnedStatus());
         lqw.eq(StringUtils.isNotBlank(bo.getOrderType()), OrderMain::getOrderType, bo.getOrderType());
-        if (ObjectUtils.isNotEmpty(bo.getDataSource())){
-            if ("1".equals(bo.getDataSource())){
+        if (ObjectUtils.isNotEmpty(bo.getDataSource())) {
+            if ("1".equals(bo.getDataSource())) {
                 // dataSource="1" 时,查询 dataSource 为空或 null 的数据
                 lqw.and(wrapper -> wrapper.isNull(OrderMain::getDataSource).or().eq(OrderMain::getDataSource, ""));
             } else {
@@ -561,7 +561,7 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
                     bo.setProductQuantity(productQuantity);
                     bo.setTotalAmount(totalAmount);
                     bo.setPayableAmount(payableAmount);
-
+                    bo.setPaymentStatus("1");//后台下单默认已支付
                     // --- 步骤 B: 处理下单时间 ---
                     Date orderTimeToUse;
                     if (bo.getOrderTime() != null) {
@@ -1849,4 +1849,184 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
             log.warn("API订单确认失败,订单可能不存在,订单ID: {},订单号: {}", orderId, orderNo);
         }
     }
+
+    /**
+     * 查询订单及其所有子订单和商品(树形结构)
+     * 支持1级、2级、3级订单层级
+     *
+     * @param orderId 订单ID
+     * @return 订单树形结构
+     */
+    @Override
+    public OrderTreeVo queryOrderWithChildren(Long orderId) {
+        if (orderId == null) {
+            throw new IllegalArgumentException("订单ID不能为空");
+        }
+
+        // 1. 查询当前订单
+        OrderMainVo currentOrder = baseMapper.selectVoById(orderId);
+        if (currentOrder == null) {
+            log.warn("订单ID {} 不存在", orderId);
+            return null;
+        }
+
+        // 2. 构建当前订单的树形节点
+        OrderTreeVo treeVo = buildOrderTree(currentOrder);
+
+        // 3. 递归查询所有子订单
+        List<OrderTreeVo> childOrders = queryChildOrdersRecursive(orderId);
+        treeVo.setChildOrders(childOrders);
+
+        log.info("成功查询订单树形结构,订单ID: {},子订单数量: {}", orderId, childOrders != null ? childOrders.size() : 0);
+        return treeVo;
+    }
+
+    /**
+     * 递归查询子订单
+     *
+     * @param parentOrderId 父订单ID
+     * @return 子订单树形列表
+     */
+    private List<OrderTreeVo> queryChildOrdersRecursive(Long parentOrderId) {
+        // 查询直接子订单
+        List<OrderMainVo> directChildren = baseMapper.selectVoList(
+            new LambdaQueryWrapper<OrderMain>()
+                .eq(OrderMain::getParentOrderId, parentOrderId)
+                .orderByAsc(OrderMain::getId)
+        );
+
+        if (CollUtil.isEmpty(directChildren)) {
+            return Collections.emptyList();
+        }
+
+        List<OrderTreeVo> childTreeList = new ArrayList<>();
+
+        for (OrderMainVo childOrder : directChildren) {
+            // 构建子订单节点
+            OrderTreeVo childTreeVo = buildOrderTree(childOrder);
+
+            // 递归查询子订单的子订单
+            List<OrderTreeVo> grandChildren = queryChildOrdersRecursive(childOrder.getId());
+            if (CollUtil.isNotEmpty(grandChildren)) {
+                childTreeVo.setChildOrders(grandChildren);
+            }
+
+            childTreeList.add(childTreeVo);
+        }
+
+        return childTreeList;
+    }
+
+    /**
+     * 构建订单树形节点(包含商品信息)
+     *
+     * @param orderMainVo 订单信息
+     * @return 订单树形节点
+     */
+    private OrderTreeVo buildOrderTree(OrderMainVo orderMainVo) {
+        OrderTreeVo treeVo = new OrderTreeVo();
+
+        // 复制基本字段
+        treeVo.setId(orderMainVo.getId());
+        treeVo.setOrderNo(orderMainVo.getOrderNo());
+        treeVo.setParentOrderId(orderMainVo.getParentOrderId());
+        treeVo.setParentOrderNo(orderMainVo.getParentOrderNo());
+        treeVo.setCurrentLevel(orderMainVo.getCurrentLevel());
+        treeVo.setOrderStatus(orderMainVo.getOrderStatus());
+        treeVo.setPaymentStatus(orderMainVo.getPaymentStatus());
+        treeVo.setCheckStatus(orderMainVo.getCheckStatus());
+        treeVo.setAssigneeType(orderMainVo.getAssigneeType());
+        treeVo.setAssigneeId(orderMainVo.getAssigneeId());
+        treeVo.setCustomerId(orderMainVo.getCustomerId());
+        treeVo.setCustomerName(orderMainVo.getCustomerName());
+        treeVo.setTotalAmount(orderMainVo.getTotalAmount());
+        treeVo.setPayableAmount(orderMainVo.getPayableAmount());
+        treeVo.setShippingFee(orderMainVo.getShippingFee());
+        treeVo.setOrderTime(orderMainVo.getOrderTime());
+        treeVo.setConfirmTime(orderMainVo.getConfirmTime());
+        treeVo.setShippingTime(orderMainVo.getShippingTime());
+        treeVo.setReceivingTime(orderMainVo.getReceivingTime());
+        treeVo.setRemark(orderMainVo.getRemark());
+        treeVo.setDataSource(orderMainVo.getDataSource());
+
+        // 查询并设置分配对象名称
+        if (orderMainVo.getAssigneeId() != null && StringUtils.isNotBlank(orderMainVo.getAssigneeType())) {
+            String assigneeName = getAssigneeName(orderMainVo.getAssigneeId(), orderMainVo.getAssigneeType());
+            treeVo.setAssigneeName(assigneeName);
+        }
+
+        // 查询该订单的商品列表
+        List<OrderProductSimpleVo> productList = queryOrderProductsSimple(orderMainVo.getId());
+        treeVo.setProductList(productList);
+
+        return treeVo;
+    }
+
+    /**
+     * 查询订单商品(简化版)
+     *
+     * @param orderId 订单ID
+     * @return 商品列表
+     */
+    private List<OrderProductSimpleVo> queryOrderProductsSimple(Long orderId) {
+        List<OrderProductVo> productVos = orderProductMapper.selectVoList(
+            new LambdaQueryWrapper<OrderProduct>()
+                .eq(OrderProduct::getOrderId, orderId)
+                .orderByAsc(OrderProduct::getId)
+        );
+
+        if (CollUtil.isEmpty(productVos)) {
+            return Collections.emptyList();
+        }
+
+        return productVos.stream().map(vo -> {
+            OrderProductSimpleVo simpleVo = new OrderProductSimpleVo();
+            simpleVo.setId(vo.getId());
+            simpleVo.setOrderId(vo.getOrderId());
+            simpleVo.setProductId(vo.getProductId());
+            simpleVo.setProductNo(vo.getProductNo());
+            simpleVo.setProductName(vo.getProductName());
+            simpleVo.setProductUnit(vo.getProductUnit());
+            simpleVo.setProductImage(vo.getProductImage());
+            simpleVo.setOrderPrice(vo.getOrderPrice());
+            simpleVo.setOrderQuantity(vo.getOrderQuantity());
+            simpleVo.setSubtotal(vo.getSubtotal());
+            simpleVo.setQuantitySent(vo.getQuantitySent());
+            simpleVo.setUnsentQuantity(vo.getUnsentQuantity());
+            simpleVo.setCurrentLevel(vo.getCurrentLevel());
+            simpleVo.setAssignmentStatus(vo.getAssignmentStatus());
+            simpleVo.setRemark(vo.getRemark());
+            return simpleVo;
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * 获取分配对象名称
+     *
+     * @param assigneeId   分配对象ID
+     * @param assigneeType 分配对象类型
+     * @return 分配对象名称
+     */
+    private String getAssigneeName(Long assigneeId, String assigneeType) {
+        if (assigneeId == null || StringUtils.isBlank(assigneeType)) {
+            return null;
+        }
+
+        try {
+            if (AssigneeTypeConstants.CUSTOMER.getCode().equals(assigneeType)) {
+                Map<Long, String> customerMap = remoteCustomerService.selectCustomerNameByIds(Collections.singleton(assigneeId));
+                return customerMap.get(assigneeId);
+            } else if (AssigneeTypeConstants.SUPPLIER.getCode().equals(assigneeType)) {
+                Map<Long, String> supplierMap = remoteSupplierInfoService.selectSupplierNameByIds(Collections.singleton(assigneeId));
+                return supplierMap.get(assigneeId);
+            } else if (AssigneeTypeConstants.PARTNER.getCode().equals(assigneeType)) {
+                Map<Long, String> partnerMap = remotePartnerInfoService.selectPartnerNameByIds(Collections.singleton(assigneeId));
+                return partnerMap.get(assigneeId);
+            }
+        } catch (Exception e) {
+            log.error("获取分配对象名称失败,assigneeId: {}, assigneeType: {}", assigneeId, assigneeType, e);
+        }
+
+        return null;
+    }
 }

+ 0 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/dubbo/RemoteCategoryServiceImpl.java

@@ -206,7 +206,6 @@ public class RemoteCategoryServiceImpl implements RemoteCategoryService {
                 .or()
                 .eq(ProductCategory::getParentId, categoryId)
                 .orderByAsc(ProductCategory::getSort)
-                .orderByAsc(ProductCategory::getId)
         );
 
         // 去重:使用 Set 来避免重复

+ 6 - 6
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/AddressAreaController.java

@@ -40,7 +40,7 @@ public class AddressAreaController extends BaseController {
     /**
      * 查询地区列表列表
      */
-    @SaCheckPermission("system:addressarea:list")
+//    @SaCheckPermission("system:addressarea:list")
     @GetMapping("/list")
     public TableDataInfo<AddressAreaVo> list(AddressAreaBo bo, PageQuery pageQuery) {
         return addressAreaService.queryPageList(bo, pageQuery);
@@ -61,7 +61,7 @@ public class AddressAreaController extends BaseController {
     /**
      * 导出地区列表列表
      */
-    @SaCheckPermission("system:addressarea:export")
+//    @SaCheckPermission("system:addressarea:export")
     @Log(title = "地区列表", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(AddressAreaBo bo, HttpServletResponse response) {
@@ -74,7 +74,7 @@ public class AddressAreaController extends BaseController {
      *
      * @param id 主键
      */
-    @SaCheckPermission("system:addressarea:query")
+//    @SaCheckPermission("system:addressarea:query")
     @GetMapping("/{id}")
     public R<AddressAreaVo> getInfo(@NotNull(message = "主键不能为空")
                                      @PathVariable("id") Long id) {
@@ -84,7 +84,7 @@ public class AddressAreaController extends BaseController {
     /**
      * 新增地区列表
      */
-    @SaCheckPermission("system:addressarea:add")
+//    @SaCheckPermission("system:addressarea:add")
     @Log(title = "地区列表", businessType = BusinessType.INSERT)
     @RepeatSubmit()
     @PostMapping()
@@ -95,7 +95,7 @@ public class AddressAreaController extends BaseController {
     /**
      * 修改地区列表
      */
-    @SaCheckPermission("system:addressarea:edit")
+//    @SaCheckPermission("system:addressarea:edit")
     @Log(title = "地区列表", businessType = BusinessType.UPDATE)
     @RepeatSubmit()
     @PutMapping()
@@ -108,7 +108,7 @@ public class AddressAreaController extends BaseController {
      *
      * @param ids 主键串
      */
-    @SaCheckPermission("system:addressarea:remove")
+//    @SaCheckPermission("system:addressarea:remove")
     @Log(title = "地区列表", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     public R<Void> remove(@NotEmpty(message = "主键不能为空")

+ 25 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/ComStaffServiceImpl.java

@@ -237,6 +237,8 @@ public class ComStaffServiceImpl extends ServiceImpl<ComStaffMapper, ComStaff> i
         }
         ComStaff add = MapstructUtils.convert(bo, ComStaff.class);
         add.setUserId(userId);
+        // 设置人员编码为数据库最大编号加1
+        add.setStaffCode(generateStaffCode());
         validEntityBeforeSave(add);
         boolean flag = baseMapper.insert(add) > 0;
         if (flag) {
@@ -245,6 +247,29 @@ public class ComStaffServiceImpl extends ServiceImpl<ComStaffMapper, ComStaff> i
         return flag;
     }
 
+    /**
+     * 生成人员编码(格式:00001, 00002, ...)
+     */
+    private String generateStaffCode() {
+        // 查询当前最大编号
+        LambdaQueryWrapper<ComStaff> lqw = Wrappers.lambdaQuery();
+        lqw.select(ComStaff::getStaffCode);
+        lqw.orderByDesc(ComStaff::getStaffCode);
+        lqw.last("LIMIT 1");
+        ComStaff maxRecord = baseMapper.selectOne(lqw);
+
+        int nextNum = 1;
+        if (maxRecord != null && StringUtils.isNotBlank(maxRecord.getStaffCode())) {
+            try {
+                nextNum = Integer.parseInt(maxRecord.getStaffCode()) + 1;
+            } catch (NumberFormatException e) {
+                log.warn("解析人员编码失败: {}", maxRecord.getStaffCode());
+            }
+        }
+        // 格式化为5位数字,如 00001, 00002
+        return String.format("%05d", nextNum);
+    }
+
     /**
      * 修改人员信息
      *