diff --git a/yami-shop-admin/src/main/java/com/yami/shop/admin/controller/OrderController.java b/yami-shop-admin/src/main/java/com/yami/shop/admin/controller/OrderController.java index b150acb..1af9260 100644 --- a/yami-shop-admin/src/main/java/com/yami/shop/admin/controller/OrderController.java +++ b/yami-shop-admin/src/main/java/com/yami/shop/admin/controller/OrderController.java @@ -44,6 +44,7 @@ import java.util.Date; import java.util.List; /** + * 订单相关操作的控制器类,用于处理后台对订单的各种请求,例如分页查询、获取订单详情、订单发货、导出订单相关的Excel表格等操作。 * @author lgh on 2018/09/15. */ @Slf4j @@ -51,104 +52,143 @@ import java.util.List; @RequestMapping("/order/order") public class OrderController { + // 自动注入订单服务层接口,通过该接口调用具体的业务逻辑方法,处理订单相关业务 @Autowired private OrderService orderService; - + // 自动注入订单项服务层接口,用于处理与订单中具体商品项相关的业务逻辑 @Autowired private OrderItemService orderItemService; - + // 自动注入用户地址订单服务层接口,用于获取订单相关的用户地址信息等业务逻辑 @Autowired private UserAddrOrderService userAddrOrderService; - + // 自动注入商品服务层接口,可能用于商品相关的业务操作,比如缓存清理等 @Autowired private ProductService productService; - + // 自动注入库存单元(SKU)服务层接口,同样可能涉及到缓存清理等与库存单元相关的业务操作 @Autowired private SkuService skuService; /** - * 分页获取 + * 分页获取订单信息的方法 + * 此方法根据传入的订单查询参数(OrderParam)以及分页参数(PageParam),查询并返回符合条件的订单信息分页结果。 + * 只有拥有 'order:order:page' 权限的用户才能访问此方法。 */ @GetMapping("/page") @PreAuthorize("@pms.hasPermission('order:order:page')") - public ServerResponseEntity> page(OrderParam orderParam,PageParam page) { + public ServerResponseEntity> page(OrderParam orderParam, PageParam page) { + // 获取当前登录用户所属店铺的 ID,用于后续筛选该店铺下的订单数据 Long shopId = SecurityUtils.getSysUser().getShopId(); + // 将店铺 ID 设置到订单查询参数中,确保查询的是当前店铺的订单 orderParam.setShopId(shopId); + // 调用订单服务层的方法,按照订单参数和分页参数获取详细的订单分页信息 IPage orderPage = orderService.pageOrdersDetailByOrderParam(page, orderParam); return ServerResponseEntity.success(orderPage); - - } /** - * 获取信息 + * 根据订单编号获取订单详细信息的方法 + * 此方法接收一个订单编号,从数据库中获取对应的订单详细信息,包括订单项、用户地址等信息,并进行权限校验, + * 只有拥有 'order:order:info' 权限且属于对应店铺的用户才能获取该订单信息。 */ @GetMapping("/orderInfo/{orderNumber}") @PreAuthorize("@pms.hasPermission('order:order:info')") public ServerResponseEntity info(@PathVariable("orderNumber") String orderNumber) { + // 获取当前登录用户所属店铺的 ID,用于权限校验 Long shopId = SecurityUtils.getSysUser().getShopId(); + // 通过订单服务层的方法,根据订单编号获取订单基本信息 Order order = orderService.getOrderByOrderNumber(orderNumber); + // 校验当前用户所属店铺 ID 是否与订单所属店铺 ID 一致,不一致则抛出无权限异常 if (!Objects.equal(shopId, order.getShopId())) { throw new YamiShopBindException("您没有权限获取该订单信息"); } + // 通过订单项服务层的方法,根据订单编号获取该订单下的所有订单项信息 List orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber); + // 将订单项信息设置到订单对象中,完善订单的详细信息 order.setOrderItems(orderItems); + // 通过用户地址订单服务层的方法,根据订单关联的地址 ID 获取用户地址信息 UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId()); + // 将用户地址信息设置到订单对象中 order.setUserAddrOrder(userAddrOrder); return ServerResponseEntity.success(order); } /** - * 发货 + * 处理订单发货的方法 + * 此方法接收发货相关的参数(DeliveryOrderParam),先进行权限校验,确保当前用户有权限修改对应订单信息, + * 然后更新订单的发货相关信息,并在发货后清除对应商品和库存单元(SKU)的缓存,只有拥有 'order:order:delivery' 权限的用户才能执行此操作。 */ @PutMapping("/delivery") @PreAuthorize("@pms.hasPermission('order:order:delivery')") public ServerResponseEntity delivery(@RequestBody DeliveryOrderParam deliveryOrderParam) { + // 获取当前登录用户所属店铺的 ID,用于权限校验 Long shopId = SecurityUtils.getSysUser().getShopId(); + // 通过订单服务层的方法,根据订单编号获取订单基本信息 Order order = orderService.getOrderByOrderNumber(deliveryOrderParam.getOrderNumber()); + // 校验当前用户所属店铺 ID 是否与订单所属店铺 ID 一致,不一致则抛出无权限异常 if (!Objects.equal(shopId, order.getShopId())) { throw new YamiShopBindException("您没有权限修改该订单信息"); } + // 创建一个新的 Order 对象,用于设置要更新的订单信息 Order orderParam = new Order(); + // 设置订单 ID,确保更新的是正确的订单记录 orderParam.setOrderId(order.getOrderId()); + // 设置快递 ID,来自发货参数 orderParam.setDvyId(deliveryOrderParam.getDvyId()); + // 设置快递单号,来自发货参数 orderParam.setDvyFlowId(deliveryOrderParam.getDvyFlowId()); + // 设置发货时间为当前时间 orderParam.setDvyTime(new Date()); + // 设置订单状态为已发货(通过 OrderStatus 枚举获取对应状态值) orderParam.setStatus(OrderStatus.CONSIGNMENT.value()); + // 设置用户 ID,与原订单一致 orderParam.setUserId(order.getUserId()); + // 调用订单服务层的方法,更新订单的发货相关信息 orderService.delivery(orderParam); + // 通过订单项服务层的方法,根据订单编号获取该订单下的所有订单项信息 List orderItems = orderItemService.getOrderItemsByOrderNumber(deliveryOrderParam.getOrderNumber()); + // 遍历订单项,清除对应商品和库存单元(SKU)的缓存 for (OrderItem orderItem : orderItems) { productService.removeProductCacheByProdId(orderItem.getProdId()); - skuService.removeSkuCacheBySkuId(orderItem.getSkuId(),orderItem.getProdId()); + skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId()); } return ServerResponseEntity.success(); } /** - * 打印待发货的订单表 + * 生成待发货订单的 Excel 表格并提供下载的方法 + * 此方法根据传入的订单筛选条件(包括时间范围、订单状态等)查询待发货的订单数据, + * 然后使用 Hutool 的 Excel 工具类将数据整理并写入 Excel 表格,最后将表格输出到响应流中供客户端下载, + * 只有拥有 'order:order:waitingConsignmentExcel' 权限的用户才能访问此方法。 * - * @param order - * @param consignmentName 发件人姓名 - * @param consignmentMobile 发货人手机号 - * @param consignmentAddr 发货地址 + * @param order 订单筛选条件对象,包含店铺 ID、订单状态等用于筛选订单的信息 + * @param startTime 订单创建时间范围的起始时间,格式需符合指定的 @DateTimeFormat 注解要求 + * @param endTime 订单创建时间范围的结束时间,格式需符合指定的 @DateTimeFormat 注解要求 + * @param consignmentName 发件人姓名,用于填充 Excel 表格中的发件人相关信息 + * @param consignmentMobile 发件人手机号,用于填充 Excel 表格中的发件人相关信息 + * @param consignmentAddr 发货地址,用于填充 Excel 表格中的发件人相关信息 + * @param response HttpServletResponse 对象,用于向客户端返回 Excel 文件流,实现下载功能 */ @GetMapping("/waitingConsignmentExcel") @PreAuthorize("@pms.hasPermission('order:order:waitingConsignmentExcel')") public void waitingConsignmentExcel(Order order, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, String consignmentName, String consignmentMobile, String consignmentAddr, HttpServletResponse response) { + // 获取当前登录用户所属店铺的 ID,设置到订单筛选条件对象中,确保查询的是当前店铺的待发货订单 Long shopId = SecurityUtils.getSysUser().getShopId(); order.setShopId(shopId); + // 设置订单状态为已支付(待发货状态对应的前置状态,这里假设已支付的订单待发货),用于筛选待发货订单 order.setStatus(OrderStatus.PADYED.value()); + // 调用订单服务层的方法,根据订单筛选条件(包括时间范围、订单状态等)查询符合条件的待发货订单列表 List orders = orderService.listOrdersDetailByOrder(order, startTime, endTime); - //通过工具类创建writer + // 通过 Hutool 的 ExcelUtil 工具类创建一个 ExcelWriter 对象,用于后续写入 Excel 数据 ExcelWriter writer = ExcelUtil.getBigWriter(); + // 获取 Excel 表格的 Sheet 对象,用于设置列宽等表格样式相关操作 Sheet sheet = writer.getSheet(); + // 设置各列的宽度,单位是字符宽度的 1/256,这里根据实际需求设置了不同列的宽度 sheet.setColumnWidth(0, 20 * 256); sheet.setColumnWidth(1, 20 * 256); sheet.setColumnWidth(2, 20 * 256); @@ -157,19 +197,27 @@ public class OrderController { sheet.setColumnWidth(7, 60 * 256); sheet.setColumnWidth(8, 60 * 256); sheet.setColumnWidth(9, 60 * 256); - // 待发货 + + // 设置 Excel 表格的表头信息,定义了要展示的各列字段名称 String[] hearder = {"订单编号", "收件人", "手机", "收货地址", "商品名称", "数量", "发件人姓名", "发件人手机号", "发货地址", "备注"}; + // 合并表头单元格,用于展示标题等整体说明信息,这里合并了除第一列外的所有表头列 writer.merge(hearder.length - 1, "发货信息整理"); + // 将表头行数据写入 Excel 表格 writer.writeRow(Arrays.asList(hearder)); int row = 1; + // 遍历查询到的每个订单 for (Order dbOrder : orders) { + // 获取订单对应的用户地址信息 UserAddrOrder addr = dbOrder.getUserAddrOrder(); + // 拼接完整的收货地址信息 String addrInfo = addr.getProvince() + addr.getCity() + addr.getArea() + addr.getAddr(); + // 获取该订单下的所有订单项信息 List orderItems = dbOrder.getOrderItems(); row++; + // 遍历每个订单项,将订单和订单项相关信息逐行写入 Excel 表格 for (OrderItem orderItem : orderItems) { - // 第0列开始 + // 从第 0 列开始写入数据,列索引递增 int col = 0; writer.writeCellValue(col++, row, dbOrder.getOrderNumber()); writer.writeCellValue(col++, row, addr.getReceiver()); @@ -183,105 +231,51 @@ public class OrderController { writer.writeCellValue(col++, row, dbOrder.getRemarks()); } } + // 将整理好的 Excel 数据通过响应流输出给客户端,实现下载功能 writeExcel(response, writer); } /** - * 已销售订单 + * 生成已销售订单的 Excel 表格并提供下载的方法 + * 此方法根据传入的订单筛选条件(包括时间范围、是否已支付等)查询已销售的订单数据, + * 然后使用 Hutool 的 Excel 工具类将数据整理并写入 Excel 表格,最后将表格输出到响应流中供客户端下载, + * 只有拥有 'order:order:soldExcel' 权限的用户才能访问此方法。 * - * @param order + * @param order 订单筛选条件对象,包含店铺 ID、是否已支付等用于筛选订单的信息 + * @param startTime 订单创建时间范围的起始时间,格式需符合指定的 @DateTimeFormat 注解要求 + * @param endTime 订单创建时间范围的结束时间,格式需符合指定的 @DateTimeFormat 注解要求 + * @param response HttpServletResponse 对象,用于向客户端返回 Excel 文件流,实现下载功能 */ @GetMapping("/soldExcel") @PreAuthorize("@pms.hasPermission('order:order:soldExcel')") public void soldExcel(Order order, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, HttpServletResponse response) { + // 获取当前登录用户所属店铺的 ID,设置到订单筛选条件对象中,确保查询的是当前店铺的已销售订单 Long shopId = SecurityUtils.getSysUser().getShopId(); order.setShopId(shopId); + // 设置订单为已支付状态,用于筛选已销售的订单(这里简单以是否已支付作为已销售的判断条件之一) order.setIsPayed(1); + // 调用订单服务层的方法,根据订单筛选条件(包括时间范围、是否已支付等)查询符合条件的已销售订单列表 List orders = orderService.listOrdersDetailByOrder(order, startTime, endTime); - //通过工具类创建writer + // 通过 Hutool 的 ExcelUtil 工具类创建一个 ExcelWriter 对象,用于后续写入 Excel 数据 ExcelWriter writer = ExcelUtil.getBigWriter(); - // 待发货 - String[] hearder = {"订单编号", "下单时间", "收件人", "手机", "收货地址", "商品名称", "数量", "订单应付", "订单运费", "订单实付"}; + // 获取 Excel 表格的 Sheet 对象,用于设置列宽等表格样式相关操作 Sheet sheet = writer.getSheet(); + // 设置各列的宽度,单位是字符宽度的 1/256,这里根据实际需求设置了不同列的宽度 sheet.setColumnWidth(0, 20 * 256); sheet.setColumnWidth(1, 20 * 256); sheet.setColumnWidth(3, 20 * 256); sheet.setColumnWidth(4, 60 * 256); sheet.setColumnWidth(5, 60 * 256); + // 设置 Excel 表格的表头信息,定义了要展示的各列字段名称 + String[] hearder = {"订单编号", "下单时间", "收件人", "手机", "收货地址", "商品名称", "数量", "订单应付", "订单运费", "订单实付"}; + // 合并表头单元格,用于展示标题等整体说明信息,这里合并了除第一列外的所有表头列 writer.merge(hearder.length - 1, "销售信息整理"); + // 将表头行数据写入 Excel 表格 writer.writeRow(Arrays.asList(hearder)); int row = 1; - for (Order dbOrder : orders) { - UserAddrOrder addr = dbOrder.getUserAddrOrder(); - String addrInfo = addr.getProvince() + addr.getCity() + addr.getArea() + addr.getAddr(); - List orderItems = dbOrder.getOrderItems(); - int firstRow = row + 1; - int lastRow = row + orderItems.size(); - int col = -1; - // 订单编号 - mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getOrderNumber()); - // 下单时间 - mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getCreateTime()); - // 收件人 - mergeIfNeed(writer, firstRow, lastRow, ++col, col, addr.getReceiver()); - // "手机" - mergeIfNeed(writer, firstRow, lastRow, ++col, col, addr.getMobile()); - // "收货地址" - mergeIfNeed(writer, firstRow, lastRow, ++col, col, addrInfo); - int prodNameCol = ++col; - int prodCountCol = ++col; - for (OrderItem orderItem : orderItems) { - row++; - // 商品名称 - writer.writeCellValue(prodNameCol, row, orderItem.getProdName()); - // 数量 - writer.writeCellValue(prodCountCol, row, orderItem.getProdCount()); - } - // 订单应付 - mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getTotal()); - // 订单运费 - mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getFreightAmount()); - // 订单实付 - mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getActualTotal()); - - } - writeExcel(response, writer); - } - - /** - * 如果需要合并的话,就合并 - */ - private void mergeIfNeed(ExcelWriter writer, int firstRow, int lastRow, int firstColumn, int lastColumn, Object content) { - if (content instanceof Date) { - content = DateUtil.format((Date) content, DatePattern.NORM_DATETIME_PATTERN); - } - if (lastRow - firstRow > 0 || lastColumn - firstColumn > 0) { - writer.merge(firstRow, lastRow, firstColumn, lastColumn, content, false); - } else { - writer.writeCellValue(firstColumn, firstRow, content); - } - - } - - private void writeExcel(HttpServletResponse response, ExcelWriter writer) { - //response为HttpServletResponse对象 - response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 - response.setHeader("Content-Disposition", "attachment;filename=1.xls"); - - ServletOutputStream servletOutputStream = null; - try { - servletOutputStream = response.getOutputStream(); - writer.flush(servletOutputStream); - servletOutputStream.flush(); - } catch (IORuntimeException | IOException e) { - log.error("写出Excel错误:", e); - } finally { - IoUtil.close(writer); - } - } -} + // 遍历查询到的每个订单 + for (Order db \ No newline at end of file