Selaa lähdekoodia

库存管理模块重构

skyline 1 kuukausi sitten
vanhempi
säilyke
f4db20dda7
24 muutettua tiedostoa jossa 517 lisäystä ja 276 poistoa
  1. 1 1
      haha-admin-mp/src/App.vue
  2. 1 1
      haha-admin-web/src/api/inventory.ts
  3. 5 3
      haha-admin-web/src/views/inventory/logs/utils/hook.tsx
  4. 1 1
      haha-admin-web/src/views/inventory/records/utils/hook.tsx
  5. 2 2
      haha-admin-web/src/views/inventory/utils/hook.tsx
  6. 83 180
      haha-admin/src/main/java/com/haha/admin/controller/InventoryController.java
  7. 34 0
      haha-common/src/main/java/com/haha/common/vo/InventoryStatisticsVO.java
  8. 15 0
      haha-entity/src/main/java/com/haha/entity/DeviceInventory.java
  9. 5 0
      haha-entity/src/main/java/com/haha/entity/InventoryLog.java
  10. 4 0
      haha-entity/src/main/java/com/haha/entity/StockRecord.java
  11. 42 0
      haha-entity/src/main/java/com/haha/entity/dto/InventoryLogQueryDTO.java
  12. 49 0
      haha-entity/src/main/java/com/haha/entity/dto/InventoryQueryDTO.java
  13. 35 0
      haha-entity/src/main/java/com/haha/entity/dto/StockAdjustDTO.java
  14. 55 0
      haha-entity/src/main/java/com/haha/entity/dto/StockIncreaseDTO.java
  15. 25 0
      haha-entity/src/main/java/com/haha/entity/dto/StockRecordCompleteDTO.java
  16. 32 0
      haha-entity/src/main/java/com/haha/entity/dto/StockRecordCreateDTO.java
  17. 42 0
      haha-entity/src/main/java/com/haha/entity/dto/StockRecordQueryDTO.java
  18. 6 0
      haha-mapper/src/main/java/com/haha/mapper/DeviceInventoryMapper.java
  19. 5 4
      haha-service/src/main/java/com/haha/service/DeviceInventoryService.java
  20. 3 2
      haha-service/src/main/java/com/haha/service/InventoryLogService.java
  21. 3 2
      haha-service/src/main/java/com/haha/service/StockRecordService.java
  22. 38 39
      haha-service/src/main/java/com/haha/service/impl/DeviceInventoryServiceImpl.java
  23. 17 22
      haha-service/src/main/java/com/haha/service/impl/InventoryLogServiceImpl.java
  24. 14 19
      haha-service/src/main/java/com/haha/service/impl/StockRecordServiceImpl.java

+ 1 - 1
haha-admin-mp/src/App.vue

@@ -52,7 +52,7 @@ const checkInviteCode = (options: any) => {
  * 绑定邀请关系(注册成功后调用)
  * @param onSuccess 绑定成功回调
  */
-export const bindPendingInviteRelation = async (onSuccess?: () => void) => {
+const bindPendingInviteRelation = async (onSuccess?: () => void) => {
   const inviteCode = uni.getStorageSync('pendingInviteCode');
 
   if (!inviteCode) {

+ 1 - 1
haha-admin-web/src/api/inventory.ts

@@ -77,7 +77,7 @@ export const getInventoryLogs = (params: {
   pageSize?: number;
   deviceId?: string;
   productId?: number;
-  changeType?: string;
+  changeType?: number;
 }) => {
   return http.request<ResultTable>("get", "/inventory/logs", { params });
 };

+ 5 - 3
haha-admin-web/src/views/inventory/logs/utils/hook.tsx

@@ -46,9 +46,11 @@ export function useInventoryLogs() {
       minWidth: 100,
       cellRenderer: ({ row }) => {
         const typeMap = {
-          increase: { text: "增加", type: "success" },
-          decrease: { text: "减少", type: "danger" },
-          adjust: { text: "调整", type: "warning" }
+          1: { text: "上货增加", type: "success" },
+          2: { text: "销售减少", type: "danger" },
+          3: { text: "调整增加", type: "warning" },
+          4: { text: "调整减少", type: "warning" },
+          5: { text: "盘点调整", type: "info" }
         };
         const item = typeMap[row.changeType] || { text: row.changeType, type: "info" };
         return <el-tag type={item.type}>{item.text}</el-tag>;

+ 1 - 1
haha-admin-web/src/views/inventory/records/utils/hook.tsx

@@ -136,7 +136,7 @@ export function useStockRecords() {
 
   async function handleCancel(row) {
     const { code } = await cancelStockRecord(row.id);
-    if (code === 0) {
+    if (code === 200) {
       message("取消成功", { type: "success" });
       onSearch();
     }

+ 2 - 2
haha-admin-web/src/views/inventory/utils/hook.tsx

@@ -194,7 +194,7 @@ export function useInventory(tableRef: Ref) {
 
         try {
           const res = await increaseStock(toRaw(stockInForm));
-          if (res.code === 0) {
+          if (res.code === 200) {
             message("上货成功", { type: "success" });
             done();
             onSearch();
@@ -245,7 +245,7 @@ export function useInventory(tableRef: Ref) {
 
         try {
           const res = await adjustStock(toRaw(adjustForm));
-          if (res.code === 0) {
+          if (res.code === 200) {
             message("库存调整成功", { type: "success" });
             done();
             onSearch();

+ 83 - 180
haha-admin/src/main/java/com/haha/admin/controller/InventoryController.java

@@ -5,18 +5,22 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.haha.admin.annotation.RequirePermission;
 import com.haha.common.annotation.Log;
 import com.haha.common.enums.OperationType;
+import com.haha.common.vo.InventoryStatisticsVO;
+import com.haha.common.vo.PageResult;
 import com.haha.common.vo.Result;
 import com.haha.entity.DeviceInventory;
 import com.haha.entity.InventoryLog;
 import com.haha.entity.StockRecord;
+import com.haha.entity.dto.*;
+import com.haha.service.AdminService;
 import com.haha.service.DeviceInventoryService;
 import com.haha.service.InventoryLogService;
 import com.haha.service.StockRecordService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -24,6 +28,7 @@ import java.util.Map;
  * 库存管理控制器
  */
 @Slf4j
+@Validated
 @RequiredArgsConstructor
 @RestController
 @RequestMapping("/inventory")
@@ -35,6 +40,8 @@ public class InventoryController {
 
     private final StockRecordService stockRecordService;
 
+    private final AdminService adminService;
+
     // ==================== 库存查询 ====================
 
     /**
@@ -43,28 +50,11 @@ public class InventoryController {
      */
     @RequirePermission("inventory:read")
     @GetMapping("/device-stats")
-    public Result<Map<String, Object>> deviceStats(@RequestParam Map<String, Object> params) {
-        int page = 1;
-        int pageSize = 10;
-
-        Object pageObj = params.get("page");
-        if (pageObj != null && !pageObj.toString().isEmpty()) {
-            page = Integer.parseInt(pageObj.toString());
-        }
-        Object pageSizeObj = params.get("pageSize");
-        if (pageSizeObj != null && !pageSizeObj.toString().isEmpty()) {
-            pageSize = Integer.parseInt(pageSizeObj.toString());
-        }
-
-        IPage<Map<String, Object>> pageResult = deviceInventoryService.getDeviceInventoryStats(page, pageSize, params);
-
-        Map<String, Object> result = new HashMap<>();
-        result.put("list", pageResult.getRecords());
-        result.put("total", pageResult.getTotal());
-        result.put("page", page);
-        result.put("pageSize", pageSize);
-
-        return Result.success(result);
+    public Result<PageResult<Map<String, Object>>> deviceStats(InventoryQueryDTO queryDTO) {
+        queryDTO.validate();
+        IPage<Map<String, Object>> pageResult = deviceInventoryService.getDeviceInventoryStats(
+                queryDTO.getPage(), queryDTO.getPageSize(), queryDTO);
+        return Result.success(PageResult.of(pageResult));
     }
 
     /**
@@ -72,33 +62,11 @@ public class InventoryController {
      */
     @RequirePermission("inventory:read")
     @GetMapping("/list")
-    public Result<Map<String, Object>> list(@RequestParam Map<String, Object> params) {
-        int page = 1;
-        int pageSize = 10;
-
-        Object pageObj = params.get("page");
-        if (pageObj != null && !pageObj.toString().isEmpty()) {
-            page = Integer.parseInt(pageObj.toString());
-        }
-        Object pageSizeObj = params.get("pageSize");
-        if (pageSizeObj != null && !pageSizeObj.toString().isEmpty()) {
-            pageSize = Integer.parseInt(pageSizeObj.toString());
-        }
-
-        // 处理低库存筛选参数
-        if ("true".equals(params.get("lowStock"))) {
-            params.put("lowStock", true);
-        }
-
-        IPage<DeviceInventory> pageResult = deviceInventoryService.getPage(page, pageSize, params);
-
-        Map<String, Object> result = new HashMap<>();
-        result.put("list", pageResult.getRecords());
-        result.put("total", pageResult.getTotal());
-        result.put("page", page);
-        result.put("pageSize", pageSize);
-
-        return Result.success(result);
+    public Result<PageResult<DeviceInventory>> list(InventoryQueryDTO queryDTO) {
+        queryDTO.validate();
+        IPage<DeviceInventory> pageResult = deviceInventoryService.getPage(
+                queryDTO.getPage(), queryDTO.getPageSize(), queryDTO);
+        return Result.success(PageResult.of(pageResult));
     }
 
     /**
@@ -106,11 +74,9 @@ public class InventoryController {
      */
     @RequirePermission("inventory:read")
     @GetMapping("/device/{deviceId}")
-    public Result<Map<String, Object>> getDeviceInventory(@PathVariable String deviceId) {
+    public Result<List<Map<String, Object>>> getDeviceInventory(@PathVariable String deviceId) {
         List<Map<String, Object>> inventory = deviceInventoryService.getInventoryWithProduct(deviceId);
-        Map<String, Object> result = new HashMap<>();
-        result.put("list", inventory);
-        return Result.success(result);
+        return Result.success(inventory);
     }
 
     /**
@@ -128,9 +94,14 @@ public class InventoryController {
      */
     @RequirePermission("inventory:read")
     @GetMapping("/statistics")
-    public Result<Map<String, Object>> getStatistics() {
+    public Result<InventoryStatisticsVO> getStatistics() {
         Map<String, Object> stats = deviceInventoryService.getStatistics();
-        return Result.success(stats);
+        InventoryStatisticsVO vo = new InventoryStatisticsVO();
+        vo.setTotalRecords((Long) stats.get("totalRecords"));
+        vo.setTotalStock((Integer) stats.get("totalStock"));
+        vo.setLowStockCount((Long) stats.get("lowStockCount"));
+        vo.setZeroStockCount((Long) stats.get("zeroStockCount"));
+        return Result.success(vo);
     }
 
     // ==================== 库存操作 ====================
@@ -141,31 +112,16 @@ public class InventoryController {
     @RequirePermission("inventory:update")
     @Log(module = "库存管理", operation = OperationType.INSERT, summary = "上货增加库存")
     @PostMapping("/increase")
-    public Result<DeviceInventory> increaseStock(@RequestBody Map<String, Object> params) {
-        try {
-            Long userId = StpUtil.getLoginIdAsLong();
-            String userName = StpUtil.getLoginIdAsString();
-
-            String deviceId = (String) params.get("deviceId");
-            Long productId = Long.parseLong(params.get("productId").toString());
-            String productCode = (String) params.get("productCode");
-            String productName = (String) params.get("productName");
-            Integer quantity = Integer.parseInt(params.get("quantity").toString());
-            Integer shelfNum = params.get("shelfNum") != null ? 
-                    Integer.parseInt(params.get("shelfNum").toString()) : null;
-            String position = (String) params.get("position");
-            String activityId = (String) params.get("activityId");
-
-            DeviceInventory inventory = deviceInventoryService.increaseStock(
-                    deviceId, productId, productCode, productName,
-                    quantity, shelfNum, position,
-                    userId, userName, activityId);
-
-            return Result.success("库存增加成功", inventory);
-        } catch (Exception e) {
-            log.error("增加库存失败", e);
-            return Result.error(e.getMessage());
-        }
+    public Result<DeviceInventory> increaseStock(@RequestBody @Validated StockIncreaseDTO dto) {
+        Long userId = StpUtil.getLoginIdAsLong();
+        String userName = getCurrentOperatorName();
+
+        DeviceInventory inventory = deviceInventoryService.increaseStock(
+                dto.getDeviceId(), dto.getProductId(), dto.getProductCode(), dto.getProductName(),
+                dto.getQuantity(), dto.getShelfNum(), dto.getPosition(),
+                userId, userName, dto.getActivityId());
+
+        return Result.success("库存增加成功", inventory);
     }
 
     /**
@@ -174,24 +130,15 @@ public class InventoryController {
     @RequirePermission("inventory:update")
     @Log(module = "库存管理", operation = OperationType.UPDATE, summary = "调整库存")
     @PostMapping("/adjust")
-    public Result<DeviceInventory> adjustStock(@RequestBody Map<String, Object> params) {
-        try {
-            Long userId = StpUtil.getLoginIdAsLong();
-            String userName = StpUtil.getLoginIdAsString();
-
-            String deviceId = (String) params.get("deviceId");
-            Long productId = Long.parseLong(params.get("productId").toString());
-            Integer newStock = Integer.parseInt(params.get("newStock").toString());
-            String remark = (String) params.get("remark");
+    public Result<DeviceInventory> adjustStock(@RequestBody @Validated StockAdjustDTO dto) {
+        Long userId = StpUtil.getLoginIdAsLong();
+        String userName = getCurrentOperatorName();
 
-            DeviceInventory inventory = deviceInventoryService.adjustStock(
-                    deviceId, productId, newStock, remark, userId, userName);
+        DeviceInventory inventory = deviceInventoryService.adjustStock(
+                dto.getDeviceId(), dto.getProductId(), dto.getNewStock(),
+                dto.getRemark(), userId, userName);
 
-            return Result.success("库存调整成功", inventory);
-        } catch (Exception e) {
-            log.error("调整库存失败", e);
-            return Result.error(e.getMessage());
-        }
+        return Result.success("库存调整成功", inventory);
     }
 
     // ==================== 库存变动日志 ====================
@@ -201,28 +148,11 @@ public class InventoryController {
      */
     @RequirePermission("inventory:read")
     @GetMapping("/logs")
-    public Result<Map<String, Object>> getLogList(@RequestParam Map<String, Object> params) {
-        int page = 1;
-        int pageSize = 10;
-
-        Object pageObj = params.get("page");
-        if (pageObj != null && !pageObj.toString().isEmpty()) {
-            page = Integer.parseInt(pageObj.toString());
-        }
-        Object pageSizeObj = params.get("pageSize");
-        if (pageSizeObj != null && !pageSizeObj.toString().isEmpty()) {
-            pageSize = Integer.parseInt(pageSizeObj.toString());
-        }
-
-        IPage<InventoryLog> pageResult = inventoryLogService.getPage(page, pageSize, params);
-
-        Map<String, Object> result = new HashMap<>();
-        result.put("list", pageResult.getRecords());
-        result.put("total", pageResult.getTotal());
-        result.put("page", page);
-        result.put("pageSize", pageSize);
-
-        return Result.success(result);
+    public Result<PageResult<InventoryLog>> getLogList(InventoryLogQueryDTO queryDTO) {
+        queryDTO.validate();
+        IPage<InventoryLog> pageResult = inventoryLogService.getPage(
+                queryDTO.getPage(), queryDTO.getPageSize(), queryDTO);
+        return Result.success(PageResult.of(pageResult));
     }
 
     /**
@@ -245,28 +175,11 @@ public class InventoryController {
      */
     @RequirePermission("inventory:read")
     @GetMapping("/records")
-    public Result<Map<String, Object>> getRecordList(@RequestParam Map<String, Object> params) {
-        int page = 1;
-        int pageSize = 10;
-
-        Object pageObj = params.get("page");
-        if (pageObj != null && !pageObj.toString().isEmpty()) {
-            page = Integer.parseInt(pageObj.toString());
-        }
-        Object pageSizeObj = params.get("pageSize");
-        if (pageSizeObj != null && !pageSizeObj.toString().isEmpty()) {
-            pageSize = Integer.parseInt(pageSizeObj.toString());
-        }
-
-        IPage<StockRecord> pageResult = stockRecordService.getPage(page, pageSize, params);
-
-        Map<String, Object> result = new HashMap<>();
-        result.put("list", pageResult.getRecords());
-        result.put("total", pageResult.getTotal());
-        result.put("page", page);
-        result.put("pageSize", pageSize);
-
-        return Result.success(result);
+    public Result<PageResult<StockRecord>> getRecordList(StockRecordQueryDTO queryDTO) {
+        queryDTO.validate();
+        IPage<StockRecord> pageResult = stockRecordService.getPage(
+                queryDTO.getPage(), queryDTO.getPageSize(), queryDTO);
+        return Result.success(PageResult.of(pageResult));
     }
 
     /**
@@ -284,26 +197,15 @@ public class InventoryController {
      */
     @RequirePermission("inventory:create")
     @PostMapping("/records")
-    public Result<StockRecord> createRecord(@RequestBody Map<String, Object> params) {
-        try {
-            String deviceId = (String) params.get("deviceId");
-            Integer stockType = params.get("stockType") != null ?
-                    Integer.parseInt(params.get("stockType").toString()) : 1;
-            String remark = (String) params.get("remark");
+    public Result<StockRecord> createRecord(@RequestBody @Validated StockRecordCreateDTO dto) {
+        Long stockerId = StpUtil.getLoginIdAsLong();
+        String stockerName = getCurrentOperatorName();
 
-            // 获取当前用户作为上货员
-            Long stockerId = StpUtil.getLoginIdAsLong();
-            String stockerName = StpUtil.getLoginIdAsString();
-            String stockerPhone = (String) params.get("stockerPhone");
+        StockRecord record = stockRecordService.createRecord(
+                dto.getDeviceId(), dto.getStockType(), stockerId, stockerName,
+                dto.getStockerPhone(), dto.getRemark());
 
-            StockRecord record = stockRecordService.createRecord(
-                    deviceId, stockType, stockerId, stockerName, stockerPhone, remark);
-
-            return Result.success("上货记录创建成功", record);
-        } catch (Exception e) {
-            log.error("创建上货记录失败", e);
-            return Result.error(e.getMessage());
-        }
+        return Result.success("上货记录创建成功", record);
     }
 
     /**
@@ -313,20 +215,9 @@ public class InventoryController {
     @PutMapping("/records/{id}/complete")
     public Result<String> completeRecord(
             @PathVariable Long id,
-            @RequestBody Map<String, Object> params) {
-        try {
-            Integer totalItems = params.get("totalItems") != null ?
-                    Integer.parseInt(params.get("totalItems").toString()) : 0;
-            Integer totalQuantity = params.get("totalQuantity") != null ?
-                    Integer.parseInt(params.get("totalQuantity").toString()) : 0;
-            String activityId = (String) params.get("activityId");
-
-            stockRecordService.completeActivity(id, totalItems, totalQuantity, activityId);
-            return Result.success("上货记录已完成");
-        } catch (Exception e) {
-            log.error("完成上货记录失败", e);
-            return Result.error(e.getMessage());
-        }
+            @RequestBody StockRecordCompleteDTO dto) {
+        stockRecordService.completeActivity(id, dto.getTotalItems(), dto.getTotalQuantity(), dto.getActivityId());
+        return Result.success("上货记录已完成");
     }
 
     /**
@@ -335,13 +226,8 @@ public class InventoryController {
     @RequirePermission("inventory:update")
     @PutMapping("/records/{id}/cancel")
     public Result<String> cancelRecord(@PathVariable Long id) {
-        try {
-            stockRecordService.cancelActivity(id);
-            return Result.success("上货记录已取消");
-        } catch (Exception e) {
-            log.error("取消上货记录失败", e);
-            return Result.error(e.getMessage());
-        }
+        stockRecordService.cancelActivity(id);
+        return Result.success("上货记录已取消");
     }
 
     /**
@@ -356,4 +242,21 @@ public class InventoryController {
         Map<String, Object> stats = stockRecordService.getStockerStatistics(stockerId, startTime, endTime);
         return Result.success(stats);
     }
+
+    /**
+     * 获取当前操作人名称
+     * 优先从Session获取昵称,fallback到loginId字符串
+     */
+    private String getCurrentOperatorName() {
+        String operatorName = StpUtil.getLoginIdAsString();
+        try {
+            Object nickname = StpUtil.getSession().get("nickname");
+            if (nickname != null) {
+                operatorName = nickname.toString();
+            }
+        } catch (Exception e) {
+            log.debug("获取用户昵称失败,使用默认值");
+        }
+        return operatorName;
+    }
 }

+ 34 - 0
haha-common/src/main/java/com/haha/common/vo/InventoryStatisticsVO.java

@@ -0,0 +1,34 @@
+package com.haha.common.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 库存统计VO
+ */
+@Data
+public class InventoryStatisticsVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 总库存记录数
+     */
+    private Long totalRecords;
+
+    /**
+     * 总库存数量
+     */
+    private Integer totalStock;
+
+    /**
+     * 低库存数量
+     */
+    private Long lowStockCount;
+
+    /**
+     * 零库存数量
+     */
+    private Long zeroStockCount;
+}

+ 15 - 0
haha-entity/src/main/java/com/haha/entity/DeviceInventory.java

@@ -3,6 +3,10 @@ package com.haha.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.Version;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import lombok.Data;
 import java.io.Serializable;
 import java.time.LocalDateTime;
@@ -16,6 +20,7 @@ public class DeviceInventory implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @TableId(type = IdType.ASSIGN_ID)
+    @JsonSerialize(using = ToStringSerializer.class)
     private Long id;
 
     /**
@@ -26,6 +31,7 @@ public class DeviceInventory implements Serializable {
     /**
      * 商品ID(本地)
      */
+    @JsonSerialize(using = ToStringSerializer.class)
     private Long productId;
 
     /**
@@ -61,15 +67,24 @@ public class DeviceInventory implements Serializable {
     /**
      * 最后补货时间
      */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
     private LocalDateTime lastRestockTime;
 
     /**
      * 创建时间
      */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
     private LocalDateTime createTime;
 
     /**
      * 更新时间
      */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
     private LocalDateTime updateTime;
+
+    /**
+     * 乐观锁版本号
+     */
+    @Version
+    private Integer version;
 }

+ 5 - 0
haha-entity/src/main/java/com/haha/entity/InventoryLog.java

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import lombok.Data;
 import java.io.Serializable;
 import java.time.LocalDateTime;
@@ -26,6 +28,7 @@ public class InventoryLog implements Serializable {
     public static final int TYPE_INVENTORY = 5;
 
     @TableId(type = IdType.ASSIGN_ID)
+    @JsonSerialize(using = ToStringSerializer.class)
     private Long id;
 
     /**
@@ -36,6 +39,7 @@ public class InventoryLog implements Serializable {
     /**
      * 商品ID
      */
+    @JsonSerialize(using = ToStringSerializer.class)
     private Long productId;
 
     /**
@@ -81,6 +85,7 @@ public class InventoryLog implements Serializable {
     /**
      * 操作人ID
      */
+    @JsonSerialize(using = ToStringSerializer.class)
     private Long operatorId;
 
     /**

+ 4 - 0
haha-entity/src/main/java/com/haha/entity/StockRecord.java

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import lombok.Data;
 import java.io.Serializable;
 import java.time.LocalDateTime;
@@ -17,6 +19,7 @@ public class StockRecord implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @TableId(type = IdType.ASSIGN_ID)
+    @JsonSerialize(using = ToStringSerializer.class)
     private Long id;
 
     /**
@@ -37,6 +40,7 @@ public class StockRecord implements Serializable {
     /**
      * 上货员ID
      */
+    @JsonSerialize(using = ToStringSerializer.class)
     private Long stockerId;
 
     /**

+ 42 - 0
haha-entity/src/main/java/com/haha/entity/dto/InventoryLogQueryDTO.java

@@ -0,0 +1,42 @@
+package com.haha.entity.dto;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 库存变动日志查询DTO
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class InventoryLogQueryDTO extends PageQueryDTO {
+
+    /**
+     * 设备ID
+     */
+    private String deviceId;
+
+    /**
+     * 商品编码
+     */
+    private String productCode;
+
+    /**
+     * 变动类型:1上货增加,2销售减少,3调整增加,4调整减少,5盘点调整
+     */
+    private Integer changeType;
+
+    /**
+     * 订单号
+     */
+    private String orderId;
+
+    /**
+     * 开始时间(yyyy-MM-dd)
+     */
+    private String startTime;
+
+    /**
+     * 结束时间(yyyy-MM-dd)
+     */
+    private String endTime;
+}

+ 49 - 0
haha-entity/src/main/java/com/haha/entity/dto/InventoryQueryDTO.java

@@ -0,0 +1,49 @@
+package com.haha.entity.dto;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 库存列表查询DTO
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class InventoryQueryDTO extends PageQueryDTO {
+
+    /**
+     * 设备ID
+     */
+    private String deviceId;
+
+    /**
+     * 商品名称(模糊搜索)
+     */
+    private String productName;
+
+    /**
+     * 仅显示低库存
+     */
+    private Boolean lowStock;
+
+    // ==================== 设备库存统计专用参数 ====================
+
+    /**
+     * 门店名称(模糊搜索)
+     */
+    private String shopName;
+
+    /**
+     * 设备名称(模糊搜索)
+     */
+    private String deviceName;
+
+    /**
+     * 是否包含未知商品
+     */
+    private Boolean hasUnknownProduct;
+
+    /**
+     * 库存状态筛选
+     */
+    private Integer stockStatus;
+}

+ 35 - 0
haha-entity/src/main/java/com/haha/entity/dto/StockAdjustDTO.java

@@ -0,0 +1,35 @@
+package com.haha.entity.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * 库存调整DTO
+ */
+@Data
+public class StockAdjustDTO {
+
+    /**
+     * 设备ID
+     */
+    @NotBlank(message = "设备ID不能为空")
+    private String deviceId;
+
+    /**
+     * 商品ID
+     */
+    @NotNull(message = "商品ID不能为空")
+    private Long productId;
+
+    /**
+     * 新库存数量
+     */
+    @NotNull(message = "新库存数量不能为空")
+    private Integer newStock;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 55 - 0
haha-entity/src/main/java/com/haha/entity/dto/StockIncreaseDTO.java

@@ -0,0 +1,55 @@
+package com.haha.entity.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * 上货增加库存DTO
+ */
+@Data
+public class StockIncreaseDTO {
+
+    /**
+     * 设备ID
+     */
+    @NotBlank(message = "设备ID不能为空")
+    private String deviceId;
+
+    /**
+     * 商品ID
+     */
+    @NotNull(message = "商品ID不能为空")
+    private Long productId;
+
+    /**
+     * 商品编码
+     */
+    private String productCode;
+
+    /**
+     * 商品名称
+     */
+    private String productName;
+
+    /**
+     * 增加数量
+     */
+    @NotNull(message = "上货数量不能为空")
+    private Integer quantity;
+
+    /**
+     * 货架层号
+     */
+    private Integer shelfNum;
+
+    /**
+     * 货道位置(left/right)
+     */
+    private String position;
+
+    /**
+     * 活动号
+     */
+    private String activityId;
+}

+ 25 - 0
haha-entity/src/main/java/com/haha/entity/dto/StockRecordCompleteDTO.java

@@ -0,0 +1,25 @@
+package com.haha.entity.dto;
+
+import lombok.Data;
+
+/**
+ * 完成上货记录DTO
+ */
+@Data
+public class StockRecordCompleteDTO {
+
+    /**
+     * 商品种类数
+     */
+    private Integer totalItems;
+
+    /**
+     * 总数量
+     */
+    private Integer totalQuantity;
+
+    /**
+     * 哈哈平台活动号
+     */
+    private String activityId;
+}

+ 32 - 0
haha-entity/src/main/java/com/haha/entity/dto/StockRecordCreateDTO.java

@@ -0,0 +1,32 @@
+package com.haha.entity.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * 创建上货记录DTO
+ */
+@Data
+public class StockRecordCreateDTO {
+
+    /**
+     * 设备ID
+     */
+    @NotBlank(message = "设备ID不能为空")
+    private String deviceId;
+
+    /**
+     * 类型:1上货,2补货
+     */
+    private Integer stockType;
+
+    /**
+     * 上货员电话
+     */
+    private String stockerPhone;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 42 - 0
haha-entity/src/main/java/com/haha/entity/dto/StockRecordQueryDTO.java

@@ -0,0 +1,42 @@
+package com.haha.entity.dto;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 上货记录查询DTO
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class StockRecordQueryDTO extends PageQueryDTO {
+
+    /**
+     * 设备ID
+     */
+    private String deviceId;
+
+    /**
+     * 上货员ID
+     */
+    private Long stockerId;
+
+    /**
+     * 类型:1上货,2补货
+     */
+    private Integer stockType;
+
+    /**
+     * 状态:1进行中,2已完成,3已取消
+     */
+    private Integer status;
+
+    /**
+     * 开始时间(yyyy-MM-dd)
+     */
+    private String startTime;
+
+    /**
+     * 结束时间(yyyy-MM-dd)
+     */
+    private String endTime;
+}

+ 6 - 0
haha-mapper/src/main/java/com/haha/mapper/DeviceInventoryMapper.java

@@ -99,4 +99,10 @@ public interface DeviceInventoryMapper extends BaseMapper<DeviceInventory> {
             "AND change_type = 1 " +
             "AND create_time = (SELECT MAX(create_time) FROM t_inventory_log WHERE device_id = #{deviceId} AND change_type = 1)")
     Integer selectLastRestockTotalStock(@Param("deviceId") String deviceId);
+
+    /**
+     * 查询所有库存总数量(SQL聚合)
+     */
+    @Select("SELECT COALESCE(SUM(stock), 0) FROM t_device_inventory")
+    Integer selectSumStock();
 }

+ 5 - 4
haha-service/src/main/java/com/haha/service/DeviceInventoryService.java

@@ -3,6 +3,7 @@ package com.haha.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.haha.entity.DeviceInventory;
+import com.haha.entity.dto.InventoryQueryDTO;
 
 import java.util.List;
 import java.util.Map;
@@ -17,10 +18,10 @@ public interface DeviceInventoryService extends IService<DeviceInventory> {
      *
      * @param page     页码
      * @param pageSize 每页条数
-     * @param params   查询参数(deviceId, productName, lowStock等)
+     * @param queryDTO 查询参数
      * @return 分页结果
      */
-    IPage<DeviceInventory> getPage(int page, int pageSize, Map<String, Object> params);
+    IPage<DeviceInventory> getPage(int page, int pageSize, InventoryQueryDTO queryDTO);
 
     /**
      * 查询设备的库存列表(带商品详情)
@@ -105,8 +106,8 @@ public interface DeviceInventoryService extends IService<DeviceInventory> {
      *
      * @param page     页码
      * @param pageSize 每页条数
-     * @param params   查询参数(shopName, deviceName, deviceId, hasUnknownProduct, stockStatus)
+     * @param queryDTO 查询参数
      * @return 分页结果
      */
-    IPage<Map<String, Object>> getDeviceInventoryStats(int page, int pageSize, Map<String, Object> params);
+    IPage<Map<String, Object>> getDeviceInventoryStats(int page, int pageSize, InventoryQueryDTO queryDTO);
 }

+ 3 - 2
haha-service/src/main/java/com/haha/service/InventoryLogService.java

@@ -3,6 +3,7 @@ package com.haha.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.haha.entity.InventoryLog;
+import com.haha.entity.dto.InventoryLogQueryDTO;
 
 import java.util.List;
 import java.util.Map;
@@ -17,10 +18,10 @@ public interface InventoryLogService extends IService<InventoryLog> {
      *
      * @param page     页码
      * @param pageSize 每页条数
-     * @param params   查询参数
+     * @param queryDTO 查询参数
      * @return 分页结果
      */
-    IPage<InventoryLog> getPage(int page, int pageSize, Map<String, Object> params);
+    IPage<InventoryLog> getPage(int page, int pageSize, InventoryLogQueryDTO queryDTO);
 
     /**
      * 记录库存变动

+ 3 - 2
haha-service/src/main/java/com/haha/service/StockRecordService.java

@@ -3,6 +3,7 @@ package com.haha.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.haha.entity.StockRecord;
+import com.haha.entity.dto.StockRecordQueryDTO;
 
 import java.util.Map;
 
@@ -16,10 +17,10 @@ public interface StockRecordService extends IService<StockRecord> {
      *
      * @param page     页码
      * @param pageSize 每页条数
-     * @param params   查询参数
+     * @param queryDTO 查询参数
      * @return 分页结果
      */
-    IPage<StockRecord> getPage(int page, int pageSize, Map<String, Object> params);
+    IPage<StockRecord> getPage(int page, int pageSize, StockRecordQueryDTO queryDTO);
 
     /**
      * 创建上货记录

+ 38 - 39
haha-service/src/main/java/com/haha/service/impl/DeviceInventoryServiceImpl.java

@@ -4,13 +4,15 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.haha.common.exception.BusinessException;
 import com.haha.entity.DeviceInventory;
 import com.haha.entity.InventoryLog;
+import com.haha.entity.dto.InventoryQueryDTO;
 import com.haha.mapper.DeviceInventoryMapper;
 import com.haha.service.DeviceInventoryService;
 import com.haha.service.InventoryLogService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
@@ -25,34 +27,30 @@ import java.util.Map;
  */
 @Slf4j
 @Service
+@RequiredArgsConstructor
 public class DeviceInventoryServiceImpl extends ServiceImpl<DeviceInventoryMapper, DeviceInventory>
         implements DeviceInventoryService {
 
-    @Autowired
-    private DeviceInventoryMapper deviceInventoryMapper;
+    private final DeviceInventoryMapper deviceInventoryMapper;
 
-    @Autowired
-    private InventoryLogService inventoryLogService;
+    private final InventoryLogService inventoryLogService;
 
     @Override
-    public IPage<DeviceInventory> getPage(int page, int pageSize, Map<String, Object> params) {
+    public IPage<DeviceInventory> getPage(int page, int pageSize, InventoryQueryDTO queryDTO) {
         LambdaQueryWrapper<DeviceInventory> wrapper = new LambdaQueryWrapper<>();
 
         // 设备ID筛选
-        String deviceId = (String) params.get("deviceId");
-        if (StringUtils.hasText(deviceId)) {
-            wrapper.eq(DeviceInventory::getDeviceId, deviceId);
+        if (StringUtils.hasText(queryDTO.getDeviceId())) {
+            wrapper.eq(DeviceInventory::getDeviceId, queryDTO.getDeviceId());
         }
 
         // 商品名称模糊搜索
-        String productName = (String) params.get("productName");
-        if (StringUtils.hasText(productName)) {
-            wrapper.like(DeviceInventory::getProductName, productName);
+        if (StringUtils.hasText(queryDTO.getProductName())) {
+            wrapper.like(DeviceInventory::getProductName, queryDTO.getProductName());
         }
 
         // 低库存筛选
-        Object lowStock = params.get("lowStock");
-        if (lowStock != null && Boolean.TRUE.equals(lowStock)) {
+        if (Boolean.TRUE.equals(queryDTO.getLowStock())) {
             wrapper.apply("stock <= warning_threshold");
         }
 
@@ -124,14 +122,22 @@ public class DeviceInventoryServiceImpl extends ServiceImpl<DeviceInventoryMappe
 
         if (inventory == null) {
             log.warn("库存记录不存在: deviceId={}, productId={}", deviceId, productId);
-            return null;
+            throw new BusinessException(404, "库存记录不存在");
         }
 
         int beforeStock = inventory.getStock();
-        int newStock = Math.max(0, beforeStock - quantity);
+        if (beforeStock < quantity) {
+            throw new BusinessException(400, "库存不足,当前库存: " + beforeStock + ",需扣减: " + quantity);
+        }
+
+        int newStock = beforeStock - quantity;
         inventory.setStock(newStock);
         inventory.setUpdateTime(LocalDateTime.now());
-        updateById(inventory);
+
+        boolean updated = updateById(inventory);
+        if (!updated) {
+            throw new BusinessException(409, "库存数据并发冲突,请重试");
+        }
 
         // 记录日志
         inventoryLogService.logChange(deviceId, productId, inventory.getProductCode(), inventory.getProductName(),
@@ -149,7 +155,7 @@ public class DeviceInventoryServiceImpl extends ServiceImpl<DeviceInventoryMappe
 
         if (inventory == null) {
             log.warn("库存记录不存在: deviceId={}, productId={}", deviceId, productId);
-            return null;
+            throw new BusinessException(404, "库存记录不存在");
         }
 
         int beforeStock = inventory.getStock();
@@ -158,7 +164,11 @@ public class DeviceInventoryServiceImpl extends ServiceImpl<DeviceInventoryMappe
 
         inventory.setStock(newStock);
         inventory.setUpdateTime(LocalDateTime.now());
-        updateById(inventory);
+
+        boolean updated = updateById(inventory);
+        if (!updated) {
+            throw new BusinessException(409, "库存数据并发冲突,请重试");
+        }
 
         // 记录日志
         inventoryLogService.logChange(deviceId, productId, inventory.getProductCode(), inventory.getProductName(),
@@ -175,12 +185,9 @@ public class DeviceInventoryServiceImpl extends ServiceImpl<DeviceInventoryMappe
         // 总库存记录数
         stats.put("totalRecords", count());
 
-        // 总库存数量
-        LambdaQueryWrapper<DeviceInventory> wrapper = new LambdaQueryWrapper<>();
-        wrapper.select(DeviceInventory::getStock);
-        List<DeviceInventory> allInventory = list(wrapper);
-        int totalStock = allInventory.stream().mapToInt(i -> i.getStock() != null ? i.getStock() : 0).sum();
-        stats.put("totalStock", totalStock);
+        // 总库存数量(使用SQL聚合,避免大数据量内存求和)
+        Integer totalStock = deviceInventoryMapper.selectSumStock();
+        stats.put("totalStock", totalStock != null ? totalStock : 0);
 
         // 低库存数量
         long lowStockCount = count(new LambdaQueryWrapper<DeviceInventory>()
@@ -201,22 +208,14 @@ public class DeviceInventoryServiceImpl extends ServiceImpl<DeviceInventoryMappe
     }
 
     @Override
-    public IPage<Map<String, Object>> getDeviceInventoryStats(int page, int pageSize, Map<String, Object> params) {
+    public IPage<Map<String, Object>> getDeviceInventoryStats(int page, int pageSize, InventoryQueryDTO queryDTO) {
         Page<Map<String, Object>> pageParam = new Page<>(page, pageSize);
 
-        String shopName = (String) params.get("shopName");
-        String deviceName = (String) params.get("deviceName");
-        String deviceId = (String) params.get("deviceId");
-        Boolean hasUnknownProduct = null;
-        Object hasUnknownObj = params.get("hasUnknownProduct");
-        if (hasUnknownObj != null) {
-            hasUnknownProduct = Boolean.valueOf(hasUnknownObj.toString());
-        }
-        Integer stockStatus = null;
-        Object stockStatusObj = params.get("stockStatus");
-        if (stockStatusObj != null && !stockStatusObj.toString().isEmpty()) {
-            stockStatus = Integer.valueOf(stockStatusObj.toString());
-        }
+        String shopName = queryDTO.getShopName();
+        String deviceName = queryDTO.getDeviceName();
+        String deviceId = queryDTO.getDeviceId();
+        Boolean hasUnknownProduct = queryDTO.getHasUnknownProduct();
+        Integer stockStatus = queryDTO.getStockStatus();
 
         IPage<Map<String, Object>> result = deviceInventoryMapper.selectDeviceInventoryStats(
                 pageParam, shopName, deviceName, deviceId, hasUnknownProduct, stockStatus);

+ 17 - 22
haha-service/src/main/java/com/haha/service/impl/InventoryLogServiceImpl.java

@@ -5,10 +5,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.haha.entity.InventoryLog;
+import com.haha.entity.dto.InventoryLogQueryDTO;
 import com.haha.mapper.InventoryLogMapper;
 import com.haha.service.InventoryLogService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
@@ -21,48 +22,42 @@ import java.util.Map;
  */
 @Slf4j
 @Service
+@RequiredArgsConstructor
 public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, InventoryLog>
         implements InventoryLogService {
 
-    @Autowired
-    private InventoryLogMapper inventoryLogMapper;
+    private final InventoryLogMapper inventoryLogMapper;
 
     @Override
-    public IPage<InventoryLog> getPage(int page, int pageSize, Map<String, Object> params) {
+    public IPage<InventoryLog> getPage(int page, int pageSize, InventoryLogQueryDTO queryDTO) {
         LambdaQueryWrapper<InventoryLog> wrapper = new LambdaQueryWrapper<>();
 
         // 设备ID筛选
-        String deviceId = (String) params.get("deviceId");
-        if (StringUtils.hasText(deviceId)) {
-            wrapper.eq(InventoryLog::getDeviceId, deviceId);
+        if (StringUtils.hasText(queryDTO.getDeviceId())) {
+            wrapper.eq(InventoryLog::getDeviceId, queryDTO.getDeviceId());
         }
 
         // 商品编码筛选
-        String productCode = (String) params.get("productCode");
-        if (StringUtils.hasText(productCode)) {
-            wrapper.eq(InventoryLog::getProductCode, productCode);
+        if (StringUtils.hasText(queryDTO.getProductCode())) {
+            wrapper.eq(InventoryLog::getProductCode, queryDTO.getProductCode());
         }
 
         // 变动类型筛选
-        Object changeType = params.get("changeType");
-        if (changeType != null) {
-            wrapper.eq(InventoryLog::getChangeType, changeType);
+        if (queryDTO.getChangeType() != null) {
+            wrapper.eq(InventoryLog::getChangeType, queryDTO.getChangeType());
         }
 
         // 订单号筛选
-        String orderId = (String) params.get("orderId");
-        if (StringUtils.hasText(orderId)) {
-            wrapper.eq(InventoryLog::getOrderId, orderId);
+        if (StringUtils.hasText(queryDTO.getOrderId())) {
+            wrapper.eq(InventoryLog::getOrderId, queryDTO.getOrderId());
         }
 
         // 时间范围
-        String startTime = (String) params.get("startTime");
-        String endTime = (String) params.get("endTime");
-        if (StringUtils.hasText(startTime)) {
-            wrapper.ge(InventoryLog::getCreateTime, LocalDateTime.parse(startTime + "T00:00:00"));
+        if (StringUtils.hasText(queryDTO.getStartTime())) {
+            wrapper.ge(InventoryLog::getCreateTime, LocalDateTime.parse(queryDTO.getStartTime() + "T00:00:00"));
         }
-        if (StringUtils.hasText(endTime)) {
-            wrapper.le(InventoryLog::getCreateTime, LocalDateTime.parse(endTime + "T23:59:59"));
+        if (StringUtils.hasText(queryDTO.getEndTime())) {
+            wrapper.le(InventoryLog::getCreateTime, LocalDateTime.parse(queryDTO.getEndTime() + "T23:59:59"));
         }
 
         // 按创建时间倒序

+ 14 - 19
haha-service/src/main/java/com/haha/service/impl/StockRecordServiceImpl.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.haha.common.exception.BusinessException;
 import com.haha.entity.StockRecord;
+import com.haha.entity.dto.StockRecordQueryDTO;
 import com.haha.mapper.StockRecordMapper;
 import com.haha.service.StockRecordService;
 import lombok.RequiredArgsConstructor;
@@ -30,41 +31,35 @@ public class StockRecordServiceImpl extends ServiceImpl<StockRecordMapper, Stock
     private final StockRecordMapper stockRecordMapper;
 
     @Override
-    public IPage<StockRecord> getPage(int page, int pageSize, Map<String, Object> params) {
+    public IPage<StockRecord> getPage(int page, int pageSize, StockRecordQueryDTO queryDTO) {
         LambdaQueryWrapper<StockRecord> wrapper = new LambdaQueryWrapper<>();
 
         // 设备ID筛选
-        String deviceId = (String) params.get("deviceId");
-        if (StringUtils.hasText(deviceId)) {
-            wrapper.eq(StockRecord::getDeviceId, deviceId);
+        if (StringUtils.hasText(queryDTO.getDeviceId())) {
+            wrapper.eq(StockRecord::getDeviceId, queryDTO.getDeviceId());
         }
 
         // 上货员筛选
-        Object stockerId = params.get("stockerId");
-        if (stockerId != null) {
-            wrapper.eq(StockRecord::getStockerId, stockerId);
+        if (queryDTO.getStockerId() != null) {
+            wrapper.eq(StockRecord::getStockerId, queryDTO.getStockerId());
         }
 
         // 类型筛选
-        Object stockType = params.get("stockType");
-        if (stockType != null) {
-            wrapper.eq(StockRecord::getStockType, stockType);
+        if (queryDTO.getStockType() != null) {
+            wrapper.eq(StockRecord::getStockType, queryDTO.getStockType());
         }
 
         // 状态筛选
-        Object status = params.get("status");
-        if (status != null) {
-            wrapper.eq(StockRecord::getStatus, status);
+        if (queryDTO.getStatus() != null) {
+            wrapper.eq(StockRecord::getStatus, queryDTO.getStatus());
         }
 
         // 时间范围
-        String startTime = (String) params.get("startTime");
-        String endTime = (String) params.get("endTime");
-        if (StringUtils.hasText(startTime)) {
-            wrapper.ge(StockRecord::getCreateTime, LocalDateTime.parse(startTime + "T00:00:00"));
+        if (StringUtils.hasText(queryDTO.getStartTime())) {
+            wrapper.ge(StockRecord::getCreateTime, LocalDateTime.parse(queryDTO.getStartTime() + "T00:00:00"));
         }
-        if (StringUtils.hasText(endTime)) {
-            wrapper.le(StockRecord::getCreateTime, LocalDateTime.parse(endTime + "T23:59:59"));
+        if (StringUtils.hasText(queryDTO.getEndTime())) {
+            wrapper.le(StockRecord::getCreateTime, LocalDateTime.parse(queryDTO.getEndTime() + "T23:59:59"));
         }
 
         // 按创建时间倒序