Bladeren bron

feat(backend): 新增商品管理 + 订单管理 API

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Sisyphus 2 maanden geleden
bovenliggende
commit
fd726b7716

+ 48 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminProductController.java

@@ -32,6 +32,7 @@ public class AdminProductController {
     public Result<Map<String, Object>> list(@RequestBody Map<String, Object> params) {
         String status = (String) params.get("status");
         String productType = (String) params.get("productType");
+        String keyword = (String) params.get("keyword");
         Integer page = params.get("page") != null ? ((Number) params.get("page")).intValue() : 1;
         Integer size = params.get("size") != null ? ((Number) params.get("size")).intValue() : 20;
 
@@ -45,6 +46,9 @@ public class AdminProductController {
         if (productType != null && !productType.isEmpty()) {
             wrapper.eq(Product::getProductType, productType);
         }
+        if (keyword != null && !keyword.isEmpty()) {
+            wrapper.like(Product::getName, keyword);
+        }
 
         Page<Product> result = productService.adminProductList(pageParam, wrapper);
         List<ProductDTO> records = result.getRecords().stream()
@@ -97,4 +101,48 @@ public class AdminProductController {
 
         return productService.adminShelve(productId, shelve);
     }
+
+    @Operation(summary = "商品详情")
+    @PostMapping("/detail")
+    public Result<ProductDTO> detail(@RequestBody Map<String, Object> params) {
+        Long productId = params.get("productId") != null
+                ? Long.valueOf(params.get("productId").toString())
+                : null;
+        if (productId == null) {
+            return Result.error("productId不能为空");
+        }
+        return productService.adminDetail(productId);
+    }
+
+    @Operation(summary = "创建商品")
+    @PostMapping("/create")
+    public Result<ProductDTO> create(@RequestBody Product product,
+                                     @RequestAttribute("userId") Long adminId) {
+        if (product.getName() == null || product.getName().isEmpty()) {
+            return Result.error("商品名称不能为空");
+        }
+        return productService.adminCreate(product);
+    }
+
+    @Operation(summary = "更新商品")
+    @PostMapping("/update")
+    public Result<ProductDTO> update(@RequestBody Product product,
+                                     @RequestAttribute("userId") Long adminId) {
+        if (product.getId() == null) {
+            return Result.error("商品ID不能为空");
+        }
+        return productService.adminUpdate(product);
+    }
+
+    @Operation(summary = "删除商品")
+    @PostMapping("/delete")
+    public Result<String> delete(@RequestBody Map<String, Object> params) {
+        Long productId = params.get("productId") != null
+                ? Long.valueOf(params.get("productId").toString())
+                : null;
+        if (productId == null) {
+            return Result.error("productId不能为空");
+        }
+        return productService.adminDelete(productId);
+    }
 }

+ 46 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminProductOrderController.java

@@ -1,7 +1,10 @@
 package com.etotem.cfc.controller.admin;
 
 import com.etotem.cfc.common.Result;
+import com.etotem.cfc.dto.ProductOrderDTO;
 import com.etotem.cfc.service.ProductOrderService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestAttribute;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -13,11 +16,53 @@ import java.util.Map;
 
 @RestController
 @RequestMapping("/api/admin/product/order")
+@Tag(name = "管理端-订单管理")
 public class AdminProductOrderController {
 
     @Resource
     private ProductOrderService orderService;
 
+    @Operation(summary = "订单列表")
+    @PostMapping("/list")
+    public Result<Map<String, Object>> list(@RequestBody Map<String, Object> params) {
+        String status = (String) params.get("status");
+        Integer page = params.get("page") != null ? ((Number) params.get("page")).intValue() : 1;
+        Integer size = params.get("size") != null ? ((Number) params.get("size")).intValue() : 20;
+        return orderService.adminOrderPage(page, size, status);
+    }
+
+    @Operation(summary = "订单详情")
+    @PostMapping("/detail")
+    public Result<ProductOrderDTO> detail(@RequestBody Map<String, Object> params) {
+        String orderNo = (String) params.get("orderNo");
+        if (orderNo == null || orderNo.isEmpty()) {
+            return Result.error("orderNo不能为空");
+        }
+        return orderService.adminOrderDetail(orderNo);
+    }
+
+    @Operation(summary = "订单发货")
+    @PostMapping("/ship")
+    public Result<String> ship(@RequestBody Map<String, Object> params,
+                               @RequestAttribute("userId") Long adminId) {
+        String orderNo = (String) params.get("orderNo");
+        String trackingNumber = (String) params.get("trackingNumber");
+        String expressCompany = (String) params.get("expressCompany");
+        return orderService.ship(orderNo, trackingNumber, expressCompany);
+    }
+
+    @Operation(summary = "关闭订单")
+    @PostMapping("/close")
+    public Result<String> close(@RequestBody Map<String, Object> params,
+                                  @RequestAttribute("userId") Long adminId) {
+        String orderNo = (String) params.get("orderNo");
+        if (orderNo == null || orderNo.isEmpty()) {
+            return Result.error("orderNo不能为空");
+        }
+        return orderService.adminClose(orderNo, adminId);
+    }
+
+    @Operation(summary = "退款审核通过")
     @PostMapping("/refund/approve")
     public Result<String> approveRefund(@RequestBody Map<String, Object> params,
                                         @RequestAttribute("userId") Long adminId) {
@@ -25,6 +70,7 @@ public class AdminProductOrderController {
         return orderService.approveRefund(orderNo, adminId);
     }
 
+    @Operation(summary = "退款审核拒绝")
     @PostMapping("/refund/reject")
     public Result<String> rejectRefund(@RequestBody Map<String, Object> params,
                                        @RequestAttribute("userId") Long adminId) {

+ 49 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java

@@ -1,6 +1,7 @@
 package com.etotem.cfc.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.etotem.cfc.common.Result;
 import com.etotem.cfc.dto.CreateProductOrderDTO;
 import com.etotem.cfc.dto.OrderItemVO;
@@ -412,6 +413,54 @@ public class ProductOrderService {
         return Result.success(list.stream().map(ProductOrderDTO::from).collect(Collectors.toList()));
     }
 
+    public Result<Map<String, Object>> adminOrderPage(int page, int size, String status) {
+        Page<ProductOrder> pageParam = new Page<>(page, size);
+        LambdaQueryWrapper<ProductOrder> wrapper = new LambdaQueryWrapper<ProductOrder>()
+            .orderByDesc(ProductOrder::getCreatedAt);
+        if (status != null && !status.isEmpty()) {
+            wrapper.eq(ProductOrder::getStatus, status);
+        }
+        Page<ProductOrder> result = orderMapper.selectPage(pageParam, wrapper);
+        List<ProductOrderDTO> records = result.getRecords().stream()
+            .map(ProductOrderDTO::from)
+            .collect(Collectors.toList());
+        Map<String, Object> data = new HashMap<>();
+        data.put("records", records);
+        data.put("total", result.getTotal());
+        data.put("page", result.getCurrent());
+        data.put("size", result.getSize());
+        return Result.success(data);
+    }
+
+    public Result<ProductOrderDTO> adminOrderDetail(String orderNo) {
+        ProductOrder order = orderMapper.selectOne(
+            new LambdaQueryWrapper<ProductOrder>().eq(ProductOrder::getOrderNo, orderNo));
+        if (order == null) {
+            return Result.error("订单不存在");
+        }
+        return Result.success(ProductOrderDTO.from(order));
+    }
+
+    public Result<String> adminClose(String orderNo, Long adminId) {
+        ProductOrder order = orderMapper.selectOne(
+            new LambdaQueryWrapper<ProductOrder>().eq(ProductOrder::getOrderNo, orderNo));
+        if (order == null) {
+            return Result.error("订单不存在");
+        }
+        String currentStatus = order.getStatus();
+        if ("completed".equals(currentStatus) || "cancelled".equals(currentStatus) || "refunded".equals(currentStatus)) {
+            return Result.error("该订单无法关闭");
+        }
+        if ("paid".equals(currentStatus) || "pending_receipt".equals(currentStatus)) {
+            productService.increaseStock(order.getProductId(), order.getQuantity());
+        }
+        order.setStatus("closed");
+        order.setUpdatedAt(new Date());
+        orderMapper.updateById(order);
+        log.info("管理员关闭订单: orderNo={}, adminId={}", orderNo, adminId);
+        return Result.success("订单已关闭");
+    }
+
     public Result<String> confirm(String orderNo, Long vendorId) {
         ProductOrder order = orderMapper.selectOne(
             new LambdaQueryWrapper<ProductOrder>().eq(ProductOrder::getOrderNo, orderNo));

+ 49 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ProductService.java

@@ -248,4 +248,53 @@ public class ProductService {
         productMapper.updateById(product);
         return Result.success("更新成功");
     }
+
+    /**
+     * 管理员商品详情
+     */
+    public Result<ProductDTO> adminDetail(Long productId) {
+        Product product = productMapper.selectById(productId);
+        if (product == null) {
+            return Result.error("商品不存在");
+        }
+        return Result.success(ProductDTO.from(product));
+    }
+
+    /**
+     * 管理员创建商品(直接上架)
+     */
+    public Result<ProductDTO> adminCreate(Product product) {
+        product.setStatus("on_shelf");
+        product.setCreatedAt(new Date());
+        product.setUpdatedAt(new Date());
+        productMapper.insert(product);
+        return Result.success(ProductDTO.from(product));
+    }
+
+    /**
+     * 管理员更新商品
+     */
+    public Result<ProductDTO> adminUpdate(Product product) {
+        Product existing = productMapper.selectById(product.getId());
+        if (existing == null) {
+            return Result.error("商品不存在");
+        }
+        product.setUpdatedAt(new Date());
+        // 保留原状态不变,避免被覆盖
+        product.setStatus(existing.getStatus());
+        productMapper.updateById(product);
+        return Result.success(ProductDTO.from(productMapper.selectById(product.getId())));
+    }
+
+    /**
+     * 管理员删除商品
+     */
+    public Result<String> adminDelete(Long productId) {
+        Product product = productMapper.selectById(productId);
+        if (product == null) {
+            return Result.error("商品不存在");
+        }
+        productMapper.deleteById(productId);
+        return Result.success("删除成功");
+    }
 }