From ba69a4fb6db917d5e4d0fb14c37add8ee859b0e1 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期五, 13 三月 2026 17:57:51 +0800
Subject: [PATCH] 1.耗材迁移 2.仓储物流新增字段(毛重,皮重,净重) 3.设备保养多选(多条定时任务)

---
 src/main/java/com/ruoyi/stock/pojo/StockInventory.java                                  |    3 
 src/main/java/com/ruoyi/consumables/controller/ConsumablesInRecordController.java       |   51 +
 src/main/java/com/ruoyi/consumables/mapper/ConsumablesInRecordMapper.java               |   17 
 src/main/java/com/ruoyi/consumables/pojo/ConsumablesInventory.java                      |   69 +
 src/main/java/com/ruoyi/consumables/controller/ConsumablesUnInventoryController.java    |   76 +
 src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java                                  |   12 
 src/main/java/com/ruoyi/consumables/controller/ConsumablesInventoryController.java      |  108 ++
 src/main/java/com/ruoyi/consumables/dto/ConsumablesOutRecordDto.java                    |   28 
 src/main/java/com/ruoyi/consumables/pojo/ConsumablesOutRecord.java                      |   97 +
 src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java                |    2 
 src/main/java/com/ruoyi/consumables/service/ConsumablesUnInventoryService.java          |   33 
 src/main/java/com/ruoyi/consumables/service/ConsumablesInRecordService.java             |   22 
 src/main/java/com/ruoyi/consumables/dto/ConsumablesUnInventoryDto.java                  |   22 
 src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java                      |    2 
 src/main/resources/mapper/consumables/ConsumablesUninventoryMapper.xml                  |   81 +
 src/main/java/com/ruoyi/consumables/execl/ConsumablesUnInventoryExportData.java         |   36 
 src/main/java/com/ruoyi/stock/word/WeighbridgeDocGenerator.java                         |  268 +++++
 src/main/java/com/ruoyi/consumables/mapper/ConsumablesInventoryMapper.java              |   52 +
 src/main/java/com/ruoyi/consumables/service/impl/ConsumablesInRecordServiceImpl.java    |  113 ++
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java                     |  117 +
 src/main/java/com/ruoyi/consumables/pojo/ConsumablesUnInventory.java                    |   62 +
 src/main/java/com/ruoyi/consumables/service/impl/ConsumablesInventoryServiceImpl.java   |  227 ++++
 src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java               |   53 
 src/main/resources/mapper/consumables/ConsumablesInventoryMapper.xml                    |  307 ++++++
 src/main/java/com/ruoyi/consumables/service/ConsumablesInventoryService.java            |   41 
 src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java                                |   12 
 src/main/java/com/ruoyi/stock/pojo/StockInRecord.java                                   |   29 
 src/main/resources/mapper/consumables/ConsumablesInRecordMapper.xml                     |   59 +
 src/main/resources/mapper/stock/StockInventoryMapper.xml                                |    4 
 src/main/java/com/ruoyi/consumables/service/impl/ConsumablesOutRecordServiceImpl.java   |  116 ++
 src/main/java/com/ruoyi/consumables/mapper/ConsumablesOutRecordMapper.java              |   28 
 src/main/java/com/ruoyi/device/dto/MaintenanceTaskDto.java                              |   17 
 src/main/java/com/ruoyi/consumables/pojo/ConsumablesInRecord.java                       |  103 ++
 src/main/java/com/ruoyi/consumables/mapper/ConsumablesUnInventoryMapper.java            |   32 
 src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java                                |   10 
 src/main/java/com/ruoyi/consumables/controller/ConsumablesOutRecordController.java      |   69 +
 src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java                |    2 
 src/main/java/com/ruoyi/consumables/service/ConsumablesOutRecordService.java            |   30 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java             |   80 +
 src/main/java/com/ruoyi/consumables/execl/ConsumablesInRecordExportData.java            |   32 
 src/main/java/com/ruoyi/consumables/dto/ConsumablesInventoryDto.java                    |   71 +
 src/main/java/com/ruoyi/consumables/service/impl/ConsumablesUnInventoryServiceImpl.java |  125 ++
 src/main/java/com/ruoyi/consumables/execl/ConsumablesOutRecordExportData.java           |   31 
 src/main/java/com/ruoyi/consumables/dto/ConsumablesInRecordDto.java                     |   38 
 src/main/java/com/ruoyi/consumables/execl/ConsumablesInventoryExportData.java           |   39 
 src/main/java/com/ruoyi/stock/word/ChineseNumberUtil.java                               |  101 +
 src/main/resources/mapper/consumables/ConsumablesOutRecordMapper.xml                    |   76 +
 47 files changed, 2,942 insertions(+), 61 deletions(-)

diff --git a/src/main/java/com/ruoyi/consumables/controller/ConsumablesInRecordController.java b/src/main/java/com/ruoyi/consumables/controller/ConsumablesInRecordController.java
new file mode 100644
index 0000000..a7d9921
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/controller/ConsumablesInRecordController.java
@@ -0,0 +1,51 @@
+package com.ruoyi.consumables.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.consumables.dto.ConsumablesInRecordDto;
+import com.ruoyi.consumables.service.ConsumablesInRecordService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+@RestController
+@Api(tags = "鑰楁潗鍏ュ簱")
+@RequestMapping("/consumablesInRecord")
+public class ConsumablesInRecordController {
+    @Autowired
+    private ConsumablesInRecordService consumablesInRecordService;
+
+    @GetMapping("/listPage")
+    @Log(title = "鐢熶骇鍏ュ簱-鍏ュ簱绠$悊-鍒楄〃", businessType = BusinessType.OTHER)
+    @ApiOperation(value = "鍏ュ簱绠$悊鍒楄〃")
+    public AjaxResult listPage(Page page, ConsumablesInRecordDto ConsumablesInRecordDto) {
+        IPage<ConsumablesInRecordDto> result = consumablesInRecordService.listPage(page, ConsumablesInRecordDto);
+        return AjaxResult.success(result);
+    }
+
+
+
+    @DeleteMapping("")
+    @Log(title = "鍏ュ簱绠$悊-鍒犻櫎鍏ュ簱", businessType = BusinessType.DELETE)
+    public AjaxResult delete(@RequestBody List<Long> ids) {
+        if(CollectionUtils.isEmpty(ids)){
+            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        return AjaxResult.success(consumablesInRecordService.batchDelete(ids));
+    }
+
+    @PostMapping("/exportConsumablesInRecord")
+    @ApiOperation("瀵煎嚭鍏ュ簱璁板綍")
+    public void exportConsumablesInRecord(HttpServletResponse response, ConsumablesInRecordDto ConsumablesInRecordDto) {
+        consumablesInRecordService.exportConsumablesInRecord(response,ConsumablesInRecordDto);
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/consumables/controller/ConsumablesInventoryController.java b/src/main/java/com/ruoyi/consumables/controller/ConsumablesInventoryController.java
new file mode 100644
index 0000000..8687fa2
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/controller/ConsumablesInventoryController.java
@@ -0,0 +1,108 @@
+package com.ruoyi.consumables.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.execl.ConsumablesInventoryExportData;
+import com.ruoyi.consumables.service.ConsumablesInventoryService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ * 鑰楁潗搴撳瓨琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 04:16:36
+ */
+@RestController
+@RequestMapping("/consumablesInventory")
+@Api(tags = "鑰楁潗搴撳瓨琛�")
+public class ConsumablesInventoryController {
+
+    @Autowired
+    private ConsumablesInventoryService ConsumablesInventoryService;
+
+    @GetMapping("/pageConsumablesInventory")
+    @ApiOperation("鍒嗛〉鏌ヨ搴撳瓨")
+    public R pageConsumablesInventory(Page page, ConsumablesInventoryDto ConsumablesInventoryDto) {
+        IPage<ConsumablesInventoryDto> ConsumablesInventoryDtoIPage = ConsumablesInventoryService.pageConsumablesInventory(page, ConsumablesInventoryDto);
+        return R.ok(ConsumablesInventoryDtoIPage);
+    }
+
+    @PostMapping("/addConsumablesInventory")
+    @ApiOperation("鏂板搴撳瓨")
+    public R addConsumablesInventory(@RequestBody ConsumablesInventoryDto ConsumablesInventoryDto) {
+        ConsumablesInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode()));
+        ConsumablesInventoryDto.setRecordId(0L);
+        return R.ok(ConsumablesInventoryService.addConsumablesInventory(ConsumablesInventoryDto));
+    }
+
+
+    @PostMapping("/subtractConsumablesInventory")
+    @ApiOperation("鎵e噺搴撳瓨")
+    public R subtractConsumablesInventory(@RequestBody ConsumablesInventoryDto ConsumablesInventoryDto) {
+        ConsumablesInventoryDto.setRecordType(String.valueOf(StockOutQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_OUT.getCode()));
+        ConsumablesInventoryDto.setRecordId(0L);
+        return R.ok(ConsumablesInventoryService.subtractConsumablesInventory(ConsumablesInventoryDto));
+    }
+
+
+    @PostMapping("importConsumablesInventory")
+    @ApiOperation("瀵煎叆搴撳瓨")
+    public R importConsumablesInventory(MultipartFile file) {
+        return ConsumablesInventoryService.importConsumablesInventory(file);
+    }
+
+    @Log(title = "涓嬭浇搴撳瓨瀵煎叆妯℃澘", businessType = BusinessType.EXPORT)
+    @PostMapping("/downloadConsumablesInventory")
+    public void downloadConsumablesInventory(HttpServletResponse response) {
+        List<ConsumablesInventoryExportData> list = new ArrayList<>();
+        ExcelUtil<ConsumablesInventoryExportData> util = new ExcelUtil<>(ConsumablesInventoryExportData.class);
+        util.exportExcel(response, list, "搴撳瓨妯℃澘");
+    }
+
+    @PostMapping("/exportConsumablesInventory")
+    @ApiOperation("瀵煎嚭搴撳瓨")
+    public void exportConsumablesInventory(HttpServletResponse response, ConsumablesInventoryDto ConsumablesInventoryDto) {
+        ConsumablesInventoryService.exportConsumablesInventory(response, ConsumablesInventoryDto);
+    }
+
+    @GetMapping("ConsumablesInventoryPage")
+    @ApiOperation("搴撳瓨鎶ヨ〃鏌ヨ")
+    public R ConsumablesInventoryPage(Page page, ConsumablesInventoryDto consumablesInventoryDto) {
+        return R.ok(ConsumablesInventoryService.consumablesInventoryPage(consumablesInventoryDto,page));
+    }
+
+    @GetMapping("ConsumablesInAndOutRecord")
+    @ApiOperation("缁熻鍚勪釜浜у搧鐨勫叆搴撳拰鍑哄簱璁板綍")
+    public R ConsumablesInAndOutRecord(ConsumablesInventoryDto consumablesInventoryDto, Page page) {
+        return R.ok(ConsumablesInventoryService.consumablesInAndOutRecord(consumablesInventoryDto,page));
+    }
+
+    @PostMapping("/frozenConsumables")
+    @ApiOperation("鍐荤粨搴撳瓨")
+    public R frozenConsumables(@RequestBody ConsumablesInventoryDto ConsumablesInventoryDto) {
+        return R.ok(ConsumablesInventoryService.frozenConsumables(ConsumablesInventoryDto));
+    }
+
+    @PostMapping("/thawConsumables")
+    @ApiOperation("瑙e喕搴撳瓨")
+    public R thawConsumables(@RequestBody ConsumablesInventoryDto ConsumablesInventoryDto) {
+        return R.ok(ConsumablesInventoryService.thawConsumables(ConsumablesInventoryDto));
+    }
+}
diff --git a/src/main/java/com/ruoyi/consumables/controller/ConsumablesOutRecordController.java b/src/main/java/com/ruoyi/consumables/controller/ConsumablesOutRecordController.java
new file mode 100644
index 0000000..efc98b7
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/controller/ConsumablesOutRecordController.java
@@ -0,0 +1,69 @@
+package com.ruoyi.consumables.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.consumables.dto.ConsumablesOutRecordDto;
+import com.ruoyi.consumables.service.ConsumablesOutRecordService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * <p>
+ * 鑰楁潗鍑哄簱璁板綍琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 05:27:04
+ */
+@Api(tags = "鑰楁潗鍑哄簱")
+@RestController
+@RequestMapping("/consumablesOutRecord")
+public class ConsumablesOutRecordController {
+    @Autowired
+    private ConsumablesOutRecordService consumablesUnInventoryDto;
+
+    @GetMapping("/listPage")
+    @Log(title = "鐢熶骇鍑哄簱-鍑哄簱绠$悊-鍒楄〃", businessType = BusinessType.OTHER)
+    @ApiOperation(value = "鍑哄簱绠$悊鍒楄〃")
+    public AjaxResult listPage(Page page, ConsumablesOutRecordDto ConsumablesOutRecordDto) {
+        IPage<ConsumablesOutRecordDto> result = consumablesUnInventoryDto.listPage(page, ConsumablesOutRecordDto);
+        return AjaxResult.success(result);
+    }
+
+    @PostMapping("")
+    @Log(title = "鍑哄簱绠$悊-鏂板鍑哄簱", businessType = BusinessType.INSERT)
+    public AjaxResult add(@RequestBody ConsumablesOutRecordDto ConsumablesOutRecordDto) {
+        return AjaxResult.success(consumablesUnInventoryDto.add(ConsumablesOutRecordDto));
+    }
+
+    @PutMapping("/{id}")
+    @Log(title = "鍑哄簱绠$悊-鏇存柊鍑哄簱", businessType = BusinessType.UPDATE)
+    public AjaxResult update(@PathVariable("id") Long id, @RequestBody ConsumablesOutRecordDto ConsumablesOutRecordDto) {
+        return AjaxResult.success(consumablesUnInventoryDto.update(id, ConsumablesOutRecordDto));
+    }
+
+    @DeleteMapping("")
+    @Log(title = "鍑哄簱绠$悊-鍒犻櫎鍑哄簱", businessType = BusinessType.DELETE)
+    public AjaxResult delete(@RequestBody List<Long> ids) {
+        if(CollectionUtils.isEmpty(ids)){
+            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        return AjaxResult.success(consumablesUnInventoryDto.batchDelete(ids));
+    }
+
+    @PostMapping("/exportConsumablesOutRecord")
+    @ApiOperation("瀵煎嚭鍑哄簱璁板綍")
+    public void exportConsumablesOutRecord(HttpServletResponse response, ConsumablesOutRecordDto ConsumablesOutRecordDto) {
+        consumablesUnInventoryDto.exportConsumablesOutRecord(response,ConsumablesOutRecordDto);
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/consumables/controller/ConsumablesUnInventoryController.java b/src/main/java/com/ruoyi/consumables/controller/ConsumablesUnInventoryController.java
new file mode 100644
index 0000000..3beb689
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/controller/ConsumablesUnInventoryController.java
@@ -0,0 +1,76 @@
+package com.ruoyi.consumables.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutUnQualifiedRecordTypeEnum;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.dto.ConsumablesUnInventoryDto;
+import com.ruoyi.consumables.service.ConsumablesUnInventoryService;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>
+ * 鑰楁潗涓嶅悎鏍煎簱瀛樿〃 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-22 10:17:45
+ */
+@Api(tags = "鑰楁潗涓嶅悎鏍�")
+@RestController
+@RequestMapping("/consumablesUnInventory")
+public class ConsumablesUnInventoryController {
+    @Autowired
+    private ConsumablesUnInventoryService consumablesUnInventoryService;
+
+    @GetMapping("/pageConsumablesUnInventory")
+    @ApiOperation("鍒嗛〉鏌ヨ搴撳瓨")
+    public R pageConsumablesUnInventory(Page page, ConsumablesUnInventoryDto consumablesUnInventoryDto) {
+        IPage<ConsumablesUnInventoryDto> ConsumablesUnInventoryDtoIPage = consumablesUnInventoryService.pageConsumablesUnInventory(page, consumablesUnInventoryDto);
+        return R.ok(ConsumablesUnInventoryDtoIPage);
+    }
+
+    @PostMapping("/addConsumablesUnInventory")
+    @ApiOperation("鏂板搴撳瓨")
+    public R addConsumablesUnInventory(@RequestBody ConsumablesUnInventoryDto consumablesUnInventoryDto) {
+        consumablesUnInventoryDto.setRecordType(String.valueOf(StockInUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_IN.getCode()));
+        consumablesUnInventoryDto.setRecordId(0L);
+        return R.ok(consumablesUnInventoryService.addConsumablesUnInventory(consumablesUnInventoryDto));
+    }
+
+
+    @PostMapping("/subtractConsumablesUnInventory")
+    @ApiOperation("鎵e噺搴撳瓨")
+    public R subtractConsumablesUnInventory(@RequestBody ConsumablesUnInventoryDto consumablesUnInventoryDto) {
+        consumablesUnInventoryDto.setRecordType(String.valueOf(StockOutUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode()));
+        consumablesUnInventoryDto.setRecordId(0L);
+        return R.ok(consumablesUnInventoryService.subtractConsumablesUnInventory(consumablesUnInventoryDto));
+    }
+
+    @PostMapping("/exportConsumablesUnInventory")
+    @ApiOperation("瀵煎嚭搴撳瓨")
+    public void exportConsumablesUnInventory(HttpServletResponse response, ConsumablesUnInventoryDto consumablesUnInventoryDto) {
+        consumablesUnInventoryService.exportConsumablesUnInventory(response,consumablesUnInventoryDto);
+    }
+
+
+    @PostMapping("/frozenConsumables")
+    @ApiOperation("鍐荤粨搴撳瓨")
+    public R frozenConsumables(@RequestBody ConsumablesInventoryDto consumablesUnInventoryDto) {
+        return R.ok(consumablesUnInventoryService.frozenConsumables(consumablesUnInventoryDto));
+    }
+
+    @PostMapping("/thawConsumables")
+    @ApiOperation("瑙e喕搴撳瓨")
+    public R thawConsumables(@RequestBody ConsumablesInventoryDto consumablesUnInventoryDto) {
+        return R.ok(consumablesUnInventoryService.thawConsumables(consumablesUnInventoryDto));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/consumables/dto/ConsumablesInRecordDto.java b/src/main/java/com/ruoyi/consumables/dto/ConsumablesInRecordDto.java
new file mode 100644
index 0000000..06b146e
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/dto/ConsumablesInRecordDto.java
@@ -0,0 +1,38 @@
+package com.ruoyi.consumables.dto;
+
+import com.ruoyi.consumables.pojo.ConsumablesInRecord;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ConsumablesInRecordDto extends ConsumablesInRecord {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 浜у搧鍚嶇О
+     */
+    private String productName;
+    /**
+     * 浜у搧瑙勬牸
+     */
+    private String model;
+    /**
+     * 浜у搧鍗曚綅
+     */
+    private String unit;
+
+    private String timeStr;
+
+    private String createBy;
+
+    //鐜板瓨閲�
+    private String currentconsumables;
+
+    //鐜板噣閲�
+    private BigDecimal currentWeight;
+}
diff --git a/src/main/java/com/ruoyi/consumables/dto/ConsumablesInventoryDto.java b/src/main/java/com/ruoyi/consumables/dto/ConsumablesInventoryDto.java
new file mode 100644
index 0000000..9625664
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/dto/ConsumablesInventoryDto.java
@@ -0,0 +1,71 @@
+package com.ruoyi.consumables.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.consumables.pojo.ConsumablesInventory;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+public class ConsumablesInventoryDto extends ConsumablesInventory {
+
+    private String productName;
+    private String model;
+    private String unit;
+
+
+    //鍏ュ簱绫诲瀷
+    private String recordType;
+
+    //鍏ュ簱绫诲瀷瀵瑰簲鐨刬d
+    private Long recordId;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate reportDate;
+
+    //搴撳瓨鏈堟姤鏌ヨ瀛楁
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate startMonth;
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate endMonth;
+
+    private BigDecimal totalconsumablesIn;
+    private BigDecimal totalconsumablesOut;
+    private BigDecimal currentconsumables;
+
+    private BigDecimal  unLockedQuantity;
+
+    private Long parentId;
+
+    @ApiModelProperty("杩囩鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime weighingDate;
+
+    private String  parentName;
+
+    @ApiModelProperty("鍑�閲�(鎬绘暟)")
+    private BigDecimal netWeight;
+
+    @ApiModelProperty("杞︾墝鍙�")
+    private String licensePlateNo;
+
+    @ApiModelProperty("姣涢噸")
+    private BigDecimal grossWeight;
+
+    @ApiModelProperty("鐨噸")
+    private BigDecimal tareWeight;
+
+    @ApiModelProperty("杩囩鍛�")
+    private String weighingOperator;
+
+    @ApiModelProperty("纾呭崟鏂囦欢璺緞")
+    private String weighbridgeDocPath;
+}
diff --git a/src/main/java/com/ruoyi/consumables/dto/ConsumablesOutRecordDto.java b/src/main/java/com/ruoyi/consumables/dto/ConsumablesOutRecordDto.java
new file mode 100644
index 0000000..13781ea
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/dto/ConsumablesOutRecordDto.java
@@ -0,0 +1,28 @@
+package com.ruoyi.consumables.dto;
+
+import com.ruoyi.consumables.pojo.ConsumablesOutRecord;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ConsumablesOutRecordDto extends ConsumablesOutRecord {
+    /**
+     * 浜у搧鍚嶇О
+     */
+    private String productName;
+    /**
+     * 浜у搧瑙勬牸
+     */
+    private String model;
+    /**
+     * 浜у搧鍗曚綅
+     */
+    private String unit;
+
+    private String timeStr;
+
+    private String createBy;
+}
diff --git a/src/main/java/com/ruoyi/consumables/dto/ConsumablesUnInventoryDto.java b/src/main/java/com/ruoyi/consumables/dto/ConsumablesUnInventoryDto.java
new file mode 100644
index 0000000..a25368a
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/dto/ConsumablesUnInventoryDto.java
@@ -0,0 +1,22 @@
+package com.ruoyi.consumables.dto;
+
+import com.ruoyi.consumables.pojo.ConsumablesUnInventory;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class ConsumablesUnInventoryDto  extends ConsumablesUnInventory {
+    private String productName;
+    private String model;
+    private String unit;
+
+
+    //鍏ュ簱绫诲瀷
+    private String recordType;
+
+    //鍏ュ簱绫诲瀷瀵瑰簲鐨刬d
+    private Long recordId;
+
+    private BigDecimal unLockedQuantity;
+}
diff --git a/src/main/java/com/ruoyi/consumables/execl/ConsumablesInRecordExportData.java b/src/main/java/com/ruoyi/consumables/execl/ConsumablesInRecordExportData.java
new file mode 100644
index 0000000..12681e6
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/execl/ConsumablesInRecordExportData.java
@@ -0,0 +1,32 @@
+package com.ruoyi.consumables.execl;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+@Data
+public class ConsumablesInRecordExportData {
+
+    @Excel(name = "鍏ュ簱鎵规")
+    private String inboundBatches;
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+    @Excel(name = "瑙勬牸鍨嬪彿")
+    private String model;
+    @Excel(name = "鍗曚綅")
+    private String unit;
+    @Excel(name = "鍏ュ簱鏉ユ簮")
+    private String recordType;
+    @Excel(name = "鍏ュ簱鏁伴噺")
+    private String ConsumablesInNum;
+    @Excel(name = "鍏ュ簱鏃堕棿")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @Excel(isExport = false)
+    private String type;
+}
diff --git a/src/main/java/com/ruoyi/consumables/execl/ConsumablesInventoryExportData.java b/src/main/java/com/ruoyi/consumables/execl/ConsumablesInventoryExportData.java
new file mode 100644
index 0000000..01e4e6f
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/execl/ConsumablesInventoryExportData.java
@@ -0,0 +1,39 @@
+package com.ruoyi.consumables.execl;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class ConsumablesInventoryExportData {
+
+
+
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Excel(name = "瑙勬牸")
+    private String model;
+
+    @Excel(name = "鍗曚綅")
+    private String unit;
+
+    @Excel(name = "搴撳瓨鏁伴噺")
+    private BigDecimal qualitity;
+
+    @Excel(name = "棰勮鏁伴噺")
+    private BigDecimal warnNum;
+
+    @Excel(name = "鍐荤粨鏁伴噺")
+    private BigDecimal lockedQuantity;
+
+    @Excel(name = "澶囨敞")
+    private String remark;
+//
+//    @Excel(name = "鏈�鏂版洿鏂版椂闂�")
+//    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+//    private LocalDateTime updateTime;
+
+}
diff --git a/src/main/java/com/ruoyi/consumables/execl/ConsumablesOutRecordExportData.java b/src/main/java/com/ruoyi/consumables/execl/ConsumablesOutRecordExportData.java
new file mode 100644
index 0000000..3e8f65f
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/execl/ConsumablesOutRecordExportData.java
@@ -0,0 +1,31 @@
+package com.ruoyi.consumables.execl;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+@Data
+public class ConsumablesOutRecordExportData {
+    @Excel(name = "鍑哄簱鎵规")
+    private String outboundBatches;
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+    @Excel(name = "瑙勬牸鍨嬪彿")
+    private String model;
+    @Excel(name = "鍗曚綅")
+    private String unit;
+    @Excel(name = "鍑哄簱鏉ユ簮")
+    private String recordType;
+    @Excel(name = "鍑哄簱鏁伴噺")
+    private String ConsumablesInNum;
+    @Excel(name = "鍑哄簱鏃堕棿")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @Excel(isExport = false)
+    private String type;
+}
diff --git a/src/main/java/com/ruoyi/consumables/execl/ConsumablesUnInventoryExportData.java b/src/main/java/com/ruoyi/consumables/execl/ConsumablesUnInventoryExportData.java
new file mode 100644
index 0000000..ac500f6
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/execl/ConsumablesUnInventoryExportData.java
@@ -0,0 +1,36 @@
+package com.ruoyi.consumables.execl;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class ConsumablesUnInventoryExportData {
+
+
+
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Excel(name = "瑙勬牸")
+    private String model;
+
+    @Excel(name = "鍗曚綅")
+    private String unit;
+
+    @Excel(name = "搴撳瓨鏁伴噺")
+    private BigDecimal qualitity;
+
+    @Excel(name = "鍐荤粨鏁伴噺")
+    private BigDecimal lockedQuantity;
+
+    @Excel(name = "澶囨敞")
+    private String remark;
+//
+//    @Excel(name = "鏈�鏂版洿鏂版椂闂�")
+//    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+//    private LocalDateTime updateTime;
+
+}
diff --git a/src/main/java/com/ruoyi/consumables/mapper/ConsumablesInRecordMapper.java b/src/main/java/com/ruoyi/consumables/mapper/ConsumablesInRecordMapper.java
new file mode 100644
index 0000000..e70efd2
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/mapper/ConsumablesInRecordMapper.java
@@ -0,0 +1,17 @@
+package com.ruoyi.consumables.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.consumables.dto.ConsumablesInRecordDto;
+import com.ruoyi.consumables.execl.ConsumablesInRecordExportData;
+import com.ruoyi.consumables.pojo.ConsumablesInRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface ConsumablesInRecordMapper extends BaseMapper<ConsumablesInRecord> {
+    IPage<ConsumablesInRecordDto> listPage(Page page, @Param("params") ConsumablesInRecordDto ConsumablesInRecordDto);
+
+    List<ConsumablesInRecordExportData> listConsumablesInRecordExportData(@Param("params") ConsumablesInRecordDto ConsumablesInRecordDto);
+}
diff --git a/src/main/java/com/ruoyi/consumables/mapper/ConsumablesInventoryMapper.java b/src/main/java/com/ruoyi/consumables/mapper/ConsumablesInventoryMapper.java
new file mode 100644
index 0000000..880af3a
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/mapper/ConsumablesInventoryMapper.java
@@ -0,0 +1,52 @@
+package com.ruoyi.consumables.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.consumables.dto.ConsumablesInRecordDto;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.execl.ConsumablesInventoryExportData;
+import com.ruoyi.consumables.pojo.ConsumablesInventory;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 搴撳瓨琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 04:16:36
+ */
+@Mapper
+public interface ConsumablesInventoryMapper extends BaseMapper<ConsumablesInventory> {
+
+    IPage<ConsumablesInventoryDto> pageConsumablesInventory(Page page, @Param("ew") ConsumablesInventoryDto ConsumablesInventoryDto);
+
+
+    int updateAddConsumablesInventory(@Param("ew") ConsumablesInventoryDto ConsumablesInventoryDto);
+
+    int updateSubtractConsumablesInventory(@Param("ew") ConsumablesInventoryDto ConsumablesInventoryDto);
+
+    List<ConsumablesInventoryExportData> listConsumablesInventoryExportData(@Param("ew") ConsumablesInventoryDto ConsumablesInventoryDto);
+
+    IPage<ConsumablesInRecordDto> ConsumablesInventoryPage(@Param("ew") ConsumablesInventoryDto ConsumablesInventoryDto, Page page);
+
+    IPage<ConsumablesInventoryDto> ConsumablesInAndOutRecord(@Param("ew") ConsumablesInventoryDto ConsumablesInventoryDto, Page page);
+
+    BigDecimal selectTotal();
+
+    int selectStorageProductCountByDate(@Param("startDate") LocalDateTime startDate, @Param("endDate") LocalDateTime endDate);
+
+    List<Map<String, Object>> selectDailyConsumablesInCounts(@Param("rootCategoryId") Long rootCategoryId, @Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    List<Map<String, Object>> selectDailyConsumablesOutCounts(@Param("rootCategoryId") Long rootCategoryId, @Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    BigDecimal selectTotalByDate(@Param("now") LocalDate now);
+}
diff --git a/src/main/java/com/ruoyi/consumables/mapper/ConsumablesOutRecordMapper.java b/src/main/java/com/ruoyi/consumables/mapper/ConsumablesOutRecordMapper.java
new file mode 100644
index 0000000..7f4b3bc
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/mapper/ConsumablesOutRecordMapper.java
@@ -0,0 +1,28 @@
+package com.ruoyi.consumables.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.consumables.dto.ConsumablesOutRecordDto;
+import com.ruoyi.consumables.execl.ConsumablesOutRecordExportData;
+import com.ruoyi.consumables.pojo.ConsumablesOutRecord;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鍑哄簱璁板綍琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 05:27:04
+ */
+@Mapper
+public interface ConsumablesOutRecordMapper extends BaseMapper<ConsumablesOutRecord> {
+    IPage<ConsumablesOutRecordDto> listPage(Page page, @Param("params") ConsumablesOutRecordDto ConsumablesOutRecordDto);
+
+    List<ConsumablesOutRecordExportData> listConsumablesOutRecordExportData(@Param("params") ConsumablesOutRecordDto ConsumablesOutRecordDto);
+
+}
diff --git a/src/main/java/com/ruoyi/consumables/mapper/ConsumablesUnInventoryMapper.java b/src/main/java/com/ruoyi/consumables/mapper/ConsumablesUnInventoryMapper.java
new file mode 100644
index 0000000..96dc9a7
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/mapper/ConsumablesUnInventoryMapper.java
@@ -0,0 +1,32 @@
+package com.ruoyi.consumables.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.consumables.dto.ConsumablesUnInventoryDto;
+import com.ruoyi.consumables.execl.ConsumablesUnInventoryExportData;
+import com.ruoyi.consumables.pojo.ConsumablesUnInventory;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 涓嶅悎鏍煎簱瀛樿〃 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-22 10:17:45
+ */
+@Mapper
+public interface ConsumablesUnInventoryMapper extends BaseMapper<ConsumablesUnInventory> {
+
+    IPage<ConsumablesUnInventoryDto> pageConsumablesUnInventory(Page page, @Param("ew") ConsumablesUnInventoryDto ConsumablesUnInventoryDto);
+
+    int updateSubtractConsumablesUnInventory(@Param("ew") ConsumablesUnInventoryDto ConsumablesUnInventoryDto);
+
+    int updateAddConsumablesUnInventory(@Param("ew") ConsumablesUnInventoryDto ConsumablesUnInventoryDto);
+
+    List<ConsumablesUnInventoryExportData> listConsumablesInventoryExportData(@Param("ew") ConsumablesUnInventoryDto ConsumablesUnInventoryDto);
+}
diff --git a/src/main/java/com/ruoyi/consumables/pojo/ConsumablesInRecord.java b/src/main/java/com/ruoyi/consumables/pojo/ConsumablesInRecord.java
new file mode 100644
index 0000000..352c3f3
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/pojo/ConsumablesInRecord.java
@@ -0,0 +1,103 @@
+package com.ruoyi.consumables.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("consumables_in_record")
+@ApiModel("鍏ュ簱绠$悊")
+public class ConsumablesInRecord implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+    /**
+     * 搴忓彿
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "鍏ュ簱鎵规")
+    private String inboundBatches;
+
+    @ApiModelProperty(value = "鍏ュ簱鏁伴噺")
+    private BigDecimal consumablesInNum;
+
+    @ApiModelProperty(value = "璁板綍绫诲瀷  鏋氫妇")
+    private String recordType;
+
+    @ApiModelProperty(value = "璁板綍ID  ")
+    private Long recordId;
+
+    @ApiModelProperty(value = "浜у搧瑙勬牸ID")
+    private Long productModelId;
+
+    @ApiModelProperty(value = "澶囨敞")
+    private String remark;
+
+    @ApiModelProperty(value = "绫诲瀷  0鍚堟牸鍏ュ簱 1涓嶅悎鏍煎叆搴�")
+    private String type;
+
+    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @ApiModelProperty("杩囩鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime weighingDate;
+
+    @ApiModelProperty("鍑�閲�")
+    private BigDecimal netWeight;
+    /**
+     * 姣涢噸锛堝崟浣嶏細鍚級
+     */
+    @ApiModelProperty("姣涢噸")
+    private BigDecimal grossWeight;
+
+    /**
+     * 鐨噸锛堝崟浣嶏細鍚級
+     */
+    @ApiModelProperty("鐨噸")
+    private BigDecimal tareWeight;
+
+    /**
+     * 杞︾墝鍙�
+     */
+    @ApiModelProperty("杞︾墝鍙�")
+    private String licensePlateNo;
+
+    /**
+     * 杩囩鍛�
+     */
+    @ApiModelProperty("杩囩鍛�")
+    private String weighingOperator;
+
+    @ApiModelProperty("纾呭崟鏂囦欢璺緞")
+    private String weighbridgeDocPath;
+
+    @ApiModelProperty("浜у搧id")
+    private Long productId;
+}
diff --git a/src/main/java/com/ruoyi/consumables/pojo/ConsumablesInventory.java b/src/main/java/com/ruoyi/consumables/pojo/ConsumablesInventory.java
new file mode 100644
index 0000000..de3255c
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/pojo/ConsumablesInventory.java
@@ -0,0 +1,69 @@
+package com.ruoyi.consumables.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 搴撳瓨琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 04:16:36
+ */
+@Getter
+@Setter
+@TableName("consumables_inventory")
+@ApiModel(value = "consumablesInventory瀵硅薄", description = "搴撳瓨琛�")
+public class ConsumablesInventory implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("涓婚敭id")
+    private Long id;
+
+    @ApiModelProperty("瑙勬牸id")
+    @NotBlank(message = "涓嶈兘涓虹┖")
+    private Long productModelId;
+
+    @ApiModelProperty("鏁伴噺")
+    private BigDecimal qualitity;
+
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("鐗堟湰鍙�")
+    private Integer version;
+
+    @ApiModelProperty("琚鍗曢攣瀹氭暟閲�")
+    private BigDecimal lockedQuantity;
+
+    @ApiModelProperty("棰勮鏁伴噺")
+    private BigDecimal warnNum;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @ApiModelProperty("浜у搧id")
+    private Long productId;
+}
diff --git a/src/main/java/com/ruoyi/consumables/pojo/ConsumablesOutRecord.java b/src/main/java/com/ruoyi/consumables/pojo/ConsumablesOutRecord.java
new file mode 100644
index 0000000..c34e169
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/pojo/ConsumablesOutRecord.java
@@ -0,0 +1,97 @@
+package com.ruoyi.consumables.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鍑哄簱璁板綍琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 05:27:04
+ */
+@Getter
+@Setter
+@TableName("consumables_out_record")
+@ApiModel(value = "consumablesOutRecord瀵硅薄", description = "鍑哄簱璁板綍琛�")
+public class ConsumablesOutRecord implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("鍏ュ簱鎵规")
+    private String outboundBatches;
+
+    @ApiModelProperty("鍏ュ簱鏁伴噺")
+    private BigDecimal consumablesOutNum;
+
+    @ApiModelProperty("鍏ュ簱鏉ユ簮id")
+    private Long recordId;
+
+    @ApiModelProperty("鍏ュ簱绫诲瀷")
+    private String recordType;
+
+    @ApiModelProperty("浜у搧瑙勬牸id")
+    private Long productModelId;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("鍒涘缓浜�")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @ApiModelProperty("鏇存柊浜�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @ApiModelProperty(value = "绫诲瀷  0鍚堟牸鍏ュ簱 1涓嶅悎鏍煎叆搴�")
+    private String type;
+
+    @ApiModelProperty("杩囩鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime weighingDate;
+
+    @ApiModelProperty("鍑�閲�")
+    private BigDecimal netWeight;
+
+    @ApiModelProperty("杞︾墝鍙�")
+    private String licensePlateNo;
+
+    @ApiModelProperty("姣涢噸")
+    private BigDecimal grossWeight;
+
+    @ApiModelProperty("鐨噸")
+    private BigDecimal tareWeight;
+
+    @ApiModelProperty("杩囩鍛�")
+    private String weighingOperator;
+
+    @ApiModelProperty("浜у搧id")
+    private Long productId;
+}
diff --git a/src/main/java/com/ruoyi/consumables/pojo/ConsumablesUnInventory.java b/src/main/java/com/ruoyi/consumables/pojo/ConsumablesUnInventory.java
new file mode 100644
index 0000000..20b7138
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/pojo/ConsumablesUnInventory.java
@@ -0,0 +1,62 @@
+package com.ruoyi.consumables.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 涓嶅悎鏍煎簱瀛樿〃
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-22 10:17:45
+ */
+@Getter
+@Setter
+@TableName("consumables_UnInventory")
+@ApiModel(value = "consumablesUnInventory瀵硅薄", description = "涓嶅悎鏍煎簱瀛樿〃")
+public class ConsumablesUnInventory implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("涓婚敭id")
+    private Long id;
+
+    @ApiModelProperty("瑙勬牸id")
+    private Long productModelId;
+
+    @ApiModelProperty("鏁伴噺")
+    private BigDecimal qualitity;
+
+    @TableField(fill = FieldFill.INSERT)
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("鐗堟湰鍙�")
+    private Integer version;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @ApiModelProperty("琚鍗曢攣瀹氭暟閲�")
+    private BigDecimal lockedQuantity;
+
+}
diff --git a/src/main/java/com/ruoyi/consumables/service/ConsumablesInRecordService.java b/src/main/java/com/ruoyi/consumables/service/ConsumablesInRecordService.java
new file mode 100644
index 0000000..55c4c9c
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/service/ConsumablesInRecordService.java
@@ -0,0 +1,22 @@
+package com.ruoyi.consumables.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.consumables.dto.ConsumablesInRecordDto;
+import com.ruoyi.consumables.pojo.ConsumablesInRecord;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+public interface ConsumablesInRecordService extends IService<ConsumablesInRecord> {
+    IPage<ConsumablesInRecordDto> listPage(Page page, ConsumablesInRecordDto consumablesInRecordDto);
+
+    int add(ConsumablesInRecordDto consumablesInRecordDto);
+
+    int update(Long id, ConsumablesInRecordDto consumablesInRecordDto);
+
+    int batchDelete(List<Long> ids);
+
+    void exportConsumablesInRecord(HttpServletResponse response, ConsumablesInRecordDto consumablesInRecordDto);
+}
diff --git a/src/main/java/com/ruoyi/consumables/service/ConsumablesInventoryService.java b/src/main/java/com/ruoyi/consumables/service/ConsumablesInventoryService.java
new file mode 100644
index 0000000..ae11c7e
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/service/ConsumablesInventoryService.java
@@ -0,0 +1,41 @@
+package com.ruoyi.consumables.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.consumables.dto.ConsumablesInRecordDto;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.pojo.ConsumablesInventory;
+import com.ruoyi.framework.web.domain.R;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>
+ * 搴撳瓨琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 04:16:36
+ */
+public interface ConsumablesInventoryService extends IService<ConsumablesInventory> {
+
+    IPage<ConsumablesInventoryDto> pageConsumablesInventory(Page page, ConsumablesInventoryDto consumablesInventoryDto);
+
+    Boolean addConsumablesInventory(ConsumablesInventoryDto consumablesInventoryDto);
+
+    Boolean subtractConsumablesInventory(ConsumablesInventoryDto consumablesInventoryDto);
+
+    R importConsumablesInventory(MultipartFile file);
+
+    void exportConsumablesInventory(HttpServletResponse response, ConsumablesInventoryDto consumablesInventoryDto);
+
+    IPage<ConsumablesInRecordDto> consumablesInventoryPage(ConsumablesInventoryDto consumablesInventoryDto, Page page);
+
+    IPage<ConsumablesInventoryDto> consumablesInAndOutRecord(ConsumablesInventoryDto consumablesInventoryDto, Page page);
+
+    Boolean frozenConsumables(ConsumablesInventoryDto consumablesInventoryDto);
+
+    Boolean thawConsumables(ConsumablesInventoryDto consumablesInventoryDto);
+}
diff --git a/src/main/java/com/ruoyi/consumables/service/ConsumablesOutRecordService.java b/src/main/java/com/ruoyi/consumables/service/ConsumablesOutRecordService.java
new file mode 100644
index 0000000..0b5412c
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/service/ConsumablesOutRecordService.java
@@ -0,0 +1,30 @@
+package com.ruoyi.consumables.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.consumables.dto.ConsumablesOutRecordDto;
+import com.ruoyi.consumables.pojo.ConsumablesOutRecord;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * <p>
+ * 鍑哄簱璁板綍琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 05:27:04
+ */
+public interface ConsumablesOutRecordService extends IService<ConsumablesOutRecord> {
+    IPage<ConsumablesOutRecordDto> listPage(Page page, ConsumablesOutRecordDto ConsumablesOutRecordDto);
+
+    int add(ConsumablesOutRecordDto ConsumablesOutRecordDto);
+
+    int update(Long id, ConsumablesOutRecordDto ConsumablesOutRecordDto);
+
+    int batchDelete(List<Long> ids);
+
+    void exportConsumablesOutRecord(HttpServletResponse response, ConsumablesOutRecordDto ConsumablesOutRecordDto);
+}
diff --git a/src/main/java/com/ruoyi/consumables/service/ConsumablesUnInventoryService.java b/src/main/java/com/ruoyi/consumables/service/ConsumablesUnInventoryService.java
new file mode 100644
index 0000000..645236b
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/service/ConsumablesUnInventoryService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.consumables.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.dto.ConsumablesUnInventoryDto;
+import com.ruoyi.consumables.pojo.ConsumablesUnInventory;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>
+ * 涓嶅悎鏍煎簱瀛樿〃 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-22 10:17:45
+ */
+public interface ConsumablesUnInventoryService extends IService<ConsumablesUnInventory> {
+
+    IPage<ConsumablesUnInventoryDto> pageConsumablesUnInventory(Page page, ConsumablesUnInventoryDto ConsumablesUnInventoryDto);
+
+    Integer addConsumablesUnInventory(ConsumablesUnInventoryDto ConsumablesUnInventoryDto);
+
+    Integer subtractConsumablesUnInventory(ConsumablesUnInventoryDto ConsumablesUnInventoryDto);
+
+    void exportConsumablesUnInventory(HttpServletResponse response, ConsumablesUnInventoryDto ConsumablesUnInventoryDto);
+
+    Boolean frozenConsumables(ConsumablesInventoryDto ConsumablesInventoryDto);
+
+    Boolean thawConsumables(ConsumablesInventoryDto ConsumablesInventoryDto);
+}
diff --git a/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesInRecordServiceImpl.java b/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesInRecordServiceImpl.java
new file mode 100644
index 0000000..a5f3d21
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesInRecordServiceImpl.java
@@ -0,0 +1,113 @@
+package com.ruoyi.consumables.service.impl;
+
+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.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.EnumUtil;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.consumables.dto.ConsumablesInRecordDto;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.dto.ConsumablesUnInventoryDto;
+import com.ruoyi.consumables.execl.ConsumablesInRecordExportData;
+import com.ruoyi.consumables.mapper.ConsumablesInRecordMapper;
+import com.ruoyi.consumables.mapper.ConsumablesInventoryMapper;
+import com.ruoyi.consumables.mapper.ConsumablesUnInventoryMapper;
+import com.ruoyi.consumables.pojo.ConsumablesInRecord;
+import com.ruoyi.consumables.pojo.ConsumablesInventory;
+import com.ruoyi.consumables.pojo.ConsumablesUnInventory;
+import com.ruoyi.consumables.service.ConsumablesInRecordService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+public class ConsumablesInRecordServiceImpl extends ServiceImpl<ConsumablesInRecordMapper, ConsumablesInRecord> implements ConsumablesInRecordService {
+
+    private ConsumablesInRecordMapper consumablesInRecordMapper;
+    private ConsumablesInventoryMapper consumablesInventoryMapper;
+    private ConsumablesUnInventoryMapper consumablesUnInventoryMapper;
+
+    @Override
+    public IPage<ConsumablesInRecordDto> listPage(Page page, ConsumablesInRecordDto consumablesInRecordDto) {
+        return consumablesInRecordMapper.listPage(page, consumablesInRecordDto);
+    }
+
+    // 鏂板鍏ュ簱
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int add(ConsumablesInRecordDto consumablesInRecordDto) {
+        String no = OrderUtils.countTodayByCreateTime(consumablesInRecordMapper, "RK");
+        consumablesInRecordDto.setInboundBatches(no);
+        ConsumablesInRecord consumablesInRecord = new ConsumablesInRecord();
+        BeanUtils.copyProperties(consumablesInRecordDto, consumablesInRecord);
+        return consumablesInRecordMapper.insert(consumablesInRecord);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int update(Long id, ConsumablesInRecordDto consumablesInRecordDto) {
+        // 鍒ゆ柇瀵硅薄鏄惁瀛樺湪
+        ConsumablesInRecord consumablesInRecord = consumablesInRecordMapper.selectById(id);
+        if (consumablesInRecord == null){
+            throw new BaseException("璇ュ叆搴撹褰曚笉瀛樺湪,鏃犳硶鏇存柊!!!");
+        }
+
+        String[] ignoreProperties = {"id", "inbound_batches"};//鎺掗櫎id灞炴��
+        BeanUtils.copyProperties(consumablesInRecordDto, consumablesInRecord, ignoreProperties);
+        return consumablesInRecordMapper.updateById(consumablesInRecord);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int batchDelete(List<Long> ids) {
+        for (Long id : ids) {
+            ConsumablesInRecord consumablesInRecord = consumablesInRecordMapper.selectById(id);
+            if (consumablesInRecord.getType().equals("0")) {
+                ConsumablesInventory consumablesInventory = consumablesInventoryMapper.selectOne(new LambdaQueryWrapper<ConsumablesInventory>().eq(ConsumablesInventory::getProductModelId, consumablesInRecord.getProductModelId()));
+                if (consumablesInventory == null) {
+                    throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
+                }else {
+                    ConsumablesInventoryDto consumablesInRecordDto = new ConsumablesInventoryDto();
+                    consumablesInRecordDto.setProductModelId(consumablesInventory.getProductModelId());
+                    consumablesInRecordDto.setQualitity(consumablesInRecord.getConsumablesInNum());
+                    consumablesInventoryMapper.updateSubtractConsumablesInventory(consumablesInRecordDto);
+                }
+            }else if (consumablesInRecord.getType().equals("1")) {
+                ConsumablesUnInventory consumablesUnInventory = consumablesUnInventoryMapper.selectOne(new LambdaQueryWrapper<ConsumablesUnInventory>().eq(ConsumablesUnInventory::getProductModelId, consumablesInRecord.getProductModelId()));
+                if (consumablesUnInventory == null) {
+                    throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
+                }else {
+                    ConsumablesUnInventoryDto consumablesUnInventoryDto = new ConsumablesUnInventoryDto();
+                    consumablesUnInventoryDto.setProductModelId(consumablesUnInventory.getProductModelId());
+                    consumablesUnInventoryDto.setQualitity(consumablesInRecord.getConsumablesInNum());
+                    consumablesUnInventoryMapper.updateSubtractConsumablesUnInventory(consumablesUnInventoryDto);
+                }
+            }
+        }
+        return consumablesInRecordMapper.deleteBatchIds(ids);
+    }
+
+    @Override
+    public void exportConsumablesInRecord(HttpServletResponse response, ConsumablesInRecordDto consumablesInRecordDto) {
+        List<ConsumablesInRecordExportData> list = consumablesInRecordMapper.listConsumablesInRecordExportData(consumablesInRecordDto);
+        for (ConsumablesInRecordExportData consumablesInRecordExportData : list) {
+            if (consumablesInRecordExportData.getType().equals("0")) {
+                consumablesInRecordExportData.setRecordType(EnumUtil.fromCode(StockOutQualifiedRecordTypeEnum.class, Integer.parseInt(consumablesInRecordExportData.getRecordType())).getValue());
+            }else {
+                consumablesInRecordExportData.setRecordType(EnumUtil.fromCode(StockInUnQualifiedRecordTypeEnum.class, Integer.parseInt(consumablesInRecordExportData.getRecordType())).getValue());
+            }
+        }
+        ExcelUtil<ConsumablesInRecordExportData> util = new ExcelUtil<>(ConsumablesInRecordExportData.class);
+        util.exportExcel(response,list, "鍏ュ簱璁板綍淇℃伅");
+    }
+}
diff --git a/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesInventoryServiceImpl.java b/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesInventoryServiceImpl.java
new file mode 100644
index 0000000..6f30282
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesInventoryServiceImpl.java
@@ -0,0 +1,227 @@
+package com.ruoyi.consumables.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.consumables.dto.ConsumablesInRecordDto;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.dto.ConsumablesOutRecordDto;
+import com.ruoyi.consumables.execl.ConsumablesInventoryExportData;
+import com.ruoyi.consumables.mapper.ConsumablesInventoryMapper;
+import com.ruoyi.consumables.pojo.ConsumablesInventory;
+import com.ruoyi.consumables.service.ConsumablesInRecordService;
+import com.ruoyi.consumables.service.ConsumablesInventoryService;
+import com.ruoyi.consumables.service.ConsumablesOutRecordService;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.stock.word.WeighbridgeDocGenerator;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ * 搴撳瓨琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 04:16:36
+ */
+@Service
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class ConsumablesInventoryServiceImpl extends ServiceImpl<ConsumablesInventoryMapper, ConsumablesInventory> implements ConsumablesInventoryService {
+
+    private final ConsumablesInventoryMapper ConsumablesInventoryMapper;
+    private final ConsumablesInRecordService ConsumablesInRecordService;
+    private final ConsumablesOutRecordService ConsumablesOutRecordService;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+
+    @Override
+    public IPage<ConsumablesInventoryDto> pageConsumablesInventory(Page page, ConsumablesInventoryDto ConsumablesInventoryDto) {
+        return ConsumablesInventoryMapper.pageConsumablesInventory(page, ConsumablesInventoryDto);
+    }
+
+    //鍏ュ簱璋冪敤
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addConsumablesInventory(ConsumablesInventoryDto consumablesInventoryDto) {
+        //鏂板鍏ュ簱璁板綍鍐嶆坊鍔犲簱瀛�
+        ConsumablesInRecordDto consumablesInRecordDto = new ConsumablesInRecordDto();
+        consumablesInRecordDto.setRecordId(consumablesInventoryDto.getRecordId());
+        consumablesInRecordDto.setRecordType(consumablesInventoryDto.getRecordType());
+        consumablesInRecordDto.setConsumablesInNum(consumablesInventoryDto.getNetWeight());
+        consumablesInRecordDto.setWeighingDate(consumablesInventoryDto.getWeighingDate());
+        consumablesInRecordDto.setNetWeight(consumablesInventoryDto.getNetWeight());
+        consumablesInRecordDto.setGrossWeight(consumablesInventoryDto.getGrossWeight());
+        consumablesInRecordDto.setTareWeight(consumablesInventoryDto.getTareWeight());
+        consumablesInRecordDto.setLicensePlateNo(consumablesInventoryDto.getLicensePlateNo());
+        consumablesInRecordDto.setWeighingOperator(consumablesInventoryDto.getWeighingOperator());
+        consumablesInRecordDto.setProductModelId(consumablesInventoryDto.getProductModelId());
+        consumablesInRecordDto.setProductId(consumablesInventoryDto.getProductId());
+        consumablesInRecordDto.setType("0");
+        ConsumablesInRecordService.add(consumablesInRecordDto);
+        //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
+        //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
+        ConsumablesInventory oldConsumablesInventory = ConsumablesInventoryMapper.selectOne(new QueryWrapper<ConsumablesInventory>().lambda().eq(ConsumablesInventory::getProductModelId, consumablesInventoryDto.getProductModelId()));
+        if (ObjectUtils.isEmpty(oldConsumablesInventory)) {
+            ConsumablesInventory newConsumablesInventory = new ConsumablesInventory();
+            newConsumablesInventory.setProductModelId(consumablesInventoryDto.getProductModelId());
+            newConsumablesInventory.setQualitity(consumablesInventoryDto.getNetWeight());
+            newConsumablesInventory.setVersion(1);
+            newConsumablesInventory.setRemark(consumablesInventoryDto.getRemark());
+            newConsumablesInventory.setLockedQuantity(consumablesInventoryDto.getLockedQuantity());
+            newConsumablesInventory.setWarnNum(consumablesInventoryDto.getWarnNum());
+            ConsumablesInventoryMapper.insert(newConsumablesInventory);
+        } else {
+            consumablesInventoryDto.setQualitity(consumablesInventoryDto.getNetWeight());
+            ConsumablesInventoryMapper.updateAddConsumablesInventory(consumablesInventoryDto);
+        }
+        return true;
+    }
+
+    //鍑哄簱璋冪敤
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean subtractConsumablesInventory(ConsumablesInventoryDto consumablesInventoryDto) {
+        //  鏂板鍑哄簱璁板綍
+        ConsumablesOutRecordDto consumablesOutRecordDto = new ConsumablesOutRecordDto();
+        consumablesOutRecordDto.setRecordId(consumablesInventoryDto.getRecordId());
+        consumablesOutRecordDto.setRecordType(consumablesInventoryDto.getRecordType());
+        consumablesOutRecordDto.setWeighingDate(consumablesInventoryDto.getWeighingDate());
+        consumablesOutRecordDto.setConsumablesOutNum(consumablesInventoryDto.getNetWeight());
+        consumablesOutRecordDto.setNetWeight(consumablesInventoryDto.getNetWeight());
+        consumablesOutRecordDto.setGrossWeight(consumablesInventoryDto.getGrossWeight());
+        consumablesOutRecordDto.setTareWeight(consumablesInventoryDto.getTareWeight());
+        consumablesOutRecordDto.setWeighingOperator(consumablesInventoryDto.getWeighingOperator());
+        consumablesOutRecordDto.setProductModelId(consumablesInventoryDto.getProductModelId());
+        consumablesOutRecordDto.setLicensePlateNo(consumablesInventoryDto.getLicensePlateNo());
+        consumablesOutRecordDto.setProductId(consumablesInventoryDto.getProductId());
+        consumablesOutRecordDto.setType("0");
+        ConsumablesOutRecordService.add(consumablesOutRecordDto);
+        ConsumablesInventory oldConsumablesInventory = ConsumablesInventoryMapper.selectOne(new QueryWrapper<ConsumablesInventory>().lambda().eq(ConsumablesInventory::getProductModelId, consumablesInventoryDto.getProductModelId()));
+        if (ObjectUtils.isEmpty(oldConsumablesInventory)) {
+            throw new RuntimeException("浜у搧搴撳瓨涓嶅瓨鍦�");
+        }
+        BigDecimal lockedQty = oldConsumablesInventory.getLockedQuantity();
+        if (lockedQty == null) {
+            lockedQty = BigDecimal.ZERO;
+        }
+        if (consumablesInventoryDto.getQualitity().compareTo(oldConsumablesInventory.getQualitity().subtract(lockedQty)) > 0) {
+            throw new RuntimeException("搴撳瓨涓嶈冻鏃犳硶鍑哄簱");
+        }
+
+        ConsumablesInventoryMapper.updateSubtractConsumablesInventory(consumablesInventoryDto);
+        return true;
+    }
+
+    @Override
+    public R importConsumablesInventory(MultipartFile file) {
+        try {
+            // 鏌ヨ鎵�鏈夌殑浜у搧
+            List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectProduct();
+
+            ExcelUtil<ConsumablesInventoryExportData> util = new ExcelUtil<ConsumablesInventoryExportData>(ConsumablesInventoryExportData.class);
+            List<ConsumablesInventoryExportData> list = util.importExcel(file.getInputStream());
+
+            // 璁板綍鏈壘鍒板尮閰嶉」鐨勬暟鎹�
+            List<String> unmatchedRecords = new ArrayList<>();
+
+            list.forEach(dto -> {
+                boolean matched = false;
+                for (SalesLedgerProduct item : salesLedgerProducts) {
+                    if (item.getProductCategory().equals(dto.getProductName()) &&
+                            item.getSpecificationModel().equals(dto.getModel())) {
+                        ConsumablesInventoryDto ConsumablesInventoryDto = new ConsumablesInventoryDto();
+                        ConsumablesInventoryDto.setRecordId(0L);
+                        ConsumablesInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode());
+                        ConsumablesInventoryDto.setQualitity(dto.getQualitity());
+                        ConsumablesInventoryDto.setRemark(dto.getRemark());
+                        ConsumablesInventoryDto.setWarnNum(dto.getWarnNum());
+                        if (ObjectUtils.isNotEmpty(dto.getLockedQuantity()) && dto.getLockedQuantity().compareTo(dto.getQualitity()) > 0) {
+                            throw new RuntimeException("鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫簱瀛樻暟閲�");
+                        }
+                        ConsumablesInventoryDto.setLockedQuantity(dto.getLockedQuantity());
+                        ConsumablesInventoryDto.setProductModelId(item.getProductModelId());
+                        this.addConsumablesInventory(ConsumablesInventoryDto);
+                        matched = true;
+                        break; // 鎵惧埌鍖归厤椤瑰悗璺冲嚭寰幆
+                    }
+                }
+                if (!matched) {
+                    // 璁板綍鏈尮閰嶇殑鏁版嵁
+                    String unmatchedInfo = String.format("浜у搧鍚嶇О锛�%s锛岃鏍煎瀷鍙凤細%s",
+                            dto.getProductName(), dto.getModel());
+                    unmatchedRecords.add(unmatchedInfo);
+                }
+            });
+            // 鏋勫缓杩斿洖淇℃伅
+            StringBuilder message = new StringBuilder();
+            if (!unmatchedRecords.isEmpty()) {
+                message.append("浠ヤ笅浜у搧鏈壘鍒板尮閰嶉」锛歕n");
+                for (String record : unmatchedRecords) {
+                    message.append(record).append("\n");
+                }
+                throw new RuntimeException(message.toString());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.fail("瀵煎叆澶辫触锛�" + e.getMessage());
+        }
+        return R.ok("瀵煎叆鎴愬姛");
+    }
+
+
+    @Override
+    public void exportConsumablesInventory(HttpServletResponse response, ConsumablesInventoryDto ConsumablesInventoryDto) {
+
+        List<ConsumablesInventoryExportData> list = ConsumablesInventoryMapper.listConsumablesInventoryExportData(ConsumablesInventoryDto);
+        ExcelUtil<ConsumablesInventoryExportData> util = new ExcelUtil<>(ConsumablesInventoryExportData.class);
+        util.exportExcel(response, list, "搴撳瓨淇℃伅");
+    }
+
+    @Override
+    public IPage<ConsumablesInRecordDto> consumablesInventoryPage(ConsumablesInventoryDto consumablesInventoryDto, Page page) {
+        return ConsumablesInventoryMapper.ConsumablesInventoryPage(consumablesInventoryDto, page);
+    }
+
+    @Override
+    public IPage<ConsumablesInventoryDto> consumablesInAndOutRecord(ConsumablesInventoryDto consumablesInventoryDto, Page page) {
+        return ConsumablesInventoryMapper.ConsumablesInAndOutRecord(consumablesInventoryDto, page);
+    }
+
+    @Override
+    public Boolean frozenConsumables(ConsumablesInventoryDto ConsumablesInventoryDto) {
+        ConsumablesInventory ConsumablesInventory = ConsumablesInventoryMapper.selectById(ConsumablesInventoryDto.getId());
+        if (ConsumablesInventory.getQualitity().compareTo(ConsumablesInventoryDto.getLockedQuantity()) < 0) {
+            throw new RuntimeException("鍐荤粨鏁伴噺涓嶈兘瓒呰繃搴撳瓨鏁伴噺");
+        }
+        if (ObjectUtils.isEmpty(ConsumablesInventory.getLockedQuantity())) {
+            ConsumablesInventory.setLockedQuantity(ConsumablesInventoryDto.getLockedQuantity());
+        } else {
+            ConsumablesInventory.setLockedQuantity(ConsumablesInventory.getLockedQuantity().add(ConsumablesInventoryDto.getLockedQuantity()));
+        }
+        return this.updateById(ConsumablesInventory);
+    }
+
+    @Override
+    public Boolean thawConsumables(ConsumablesInventoryDto ConsumablesInventoryDto) {
+        ConsumablesInventory ConsumablesInventory = ConsumablesInventoryMapper.selectById(ConsumablesInventoryDto.getId());
+        if (ConsumablesInventory.getLockedQuantity().compareTo(ConsumablesInventoryDto.getLockedQuantity()) < 0) {
+            throw new RuntimeException("瑙e喕鏁伴噺涓嶈兘瓒呰繃鍐荤粨鏁伴噺");
+        }
+        ConsumablesInventory.setLockedQuantity(ConsumablesInventory.getLockedQuantity().subtract(ConsumablesInventoryDto.getLockedQuantity()));
+        return this.updateById(ConsumablesInventory);
+    }
+}
diff --git a/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesOutRecordServiceImpl.java b/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesOutRecordServiceImpl.java
new file mode 100644
index 0000000..e4c9238
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesOutRecordServiceImpl.java
@@ -0,0 +1,116 @@
+package com.ruoyi.consumables.service.impl;
+
+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.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.EnumUtil;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.dto.ConsumablesOutRecordDto;
+import com.ruoyi.consumables.dto.ConsumablesUnInventoryDto;
+import com.ruoyi.consumables.execl.ConsumablesOutRecordExportData;
+import com.ruoyi.consumables.mapper.ConsumablesInventoryMapper;
+import com.ruoyi.consumables.mapper.ConsumablesOutRecordMapper;
+import com.ruoyi.consumables.mapper.ConsumablesUnInventoryMapper;
+import com.ruoyi.consumables.pojo.ConsumablesInRecord;
+import com.ruoyi.consumables.pojo.ConsumablesInventory;
+import com.ruoyi.consumables.pojo.ConsumablesOutRecord;
+import com.ruoyi.consumables.pojo.ConsumablesUnInventory;
+import com.ruoyi.consumables.service.ConsumablesOutRecordService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * <p>
+ * 鍑哄簱璁板綍琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-21 05:27:04
+ */
+@Service
+@AllArgsConstructor
+public class ConsumablesOutRecordServiceImpl extends ServiceImpl<ConsumablesOutRecordMapper, ConsumablesOutRecord> implements ConsumablesOutRecordService {
+    private ConsumablesOutRecordMapper consumablesOutRecordMapper;
+    private ConsumablesInventoryMapper consumablesInventoryMapper;
+    private ConsumablesUnInventoryMapper consumablesUnInventoryMapper;
+
+    @Override
+    public IPage<ConsumablesOutRecordDto> listPage(Page page, ConsumablesOutRecordDto ConsumablesOutRecordDto) {
+        return consumablesOutRecordMapper.listPage(page, ConsumablesOutRecordDto);
+    }
+
+    @Override
+    public int add(ConsumablesOutRecordDto ConsumablesOutRecordDto) {
+        String no = OrderUtils.countTodayByCreateTime(consumablesOutRecordMapper, "CK");
+        ConsumablesOutRecordDto.setOutboundBatches(no);
+        ConsumablesInRecord ConsumablesInRecord = new ConsumablesInRecord();
+        BeanUtils.copyProperties(ConsumablesOutRecordDto, ConsumablesInRecord);
+        return consumablesOutRecordMapper.insert(ConsumablesOutRecordDto);
+    }
+
+    @Override
+    public int update(Long id, ConsumablesOutRecordDto ConsumablesOutRecordDto) {
+        // 鍒ゆ柇瀵硅薄鏄惁瀛樺湪
+        ConsumablesOutRecord ConsumablesOutRecord = consumablesOutRecordMapper.selectById(id);
+        if (ConsumablesOutRecord == null){
+            throw new BaseException("璇ュ嚭搴撹褰曚笉瀛樺湪,鏃犳硶鏇存柊!!!");
+        }
+
+        String[] ignoreProperties = {"id", "outbound_batches"};//鎺掗櫎id灞炴��
+        BeanUtils.copyProperties(ConsumablesOutRecordDto, ConsumablesOutRecord, ignoreProperties);
+        return consumablesOutRecordMapper.updateById(ConsumablesOutRecord);
+    }
+
+    @Override
+    public int batchDelete(List<Long> ids) {
+        for (Long id : ids) {
+            ConsumablesOutRecord consumablesOutRecord = consumablesOutRecordMapper.selectById(id);
+            if (consumablesOutRecord.getType().equals("0")) {
+                ConsumablesInventory consumablesInventory = consumablesInventoryMapper.selectOne(new LambdaQueryWrapper<ConsumablesInventory>().eq(ConsumablesInventory::getProductModelId, consumablesOutRecord.getProductModelId()));
+                if (consumablesInventory == null) {
+                    throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
+                }else {
+                    ConsumablesInventoryDto consumablesInRecordDto = new ConsumablesInventoryDto();
+                    consumablesInRecordDto.setProductModelId(consumablesInventory.getProductModelId());
+                    consumablesInRecordDto.setQualitity(consumablesOutRecord.getConsumablesOutNum());
+                    consumablesInventoryMapper.updateAddConsumablesInventory(consumablesInRecordDto);
+                }
+            }else if (consumablesOutRecord.getType().equals("1")) {
+                ConsumablesUnInventory consumablesUnInventory = consumablesUnInventoryMapper.selectOne(new LambdaQueryWrapper<ConsumablesUnInventory>().eq(ConsumablesUnInventory::getProductModelId, consumablesOutRecord.getProductModelId()));
+                if (consumablesUnInventory == null) {
+                    throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
+                }else {
+                    ConsumablesUnInventoryDto consumablesUnInventoryDto = new ConsumablesUnInventoryDto();
+                    consumablesUnInventoryDto.setProductModelId(consumablesUnInventory.getProductModelId());
+                    consumablesUnInventoryDto.setQualitity(consumablesOutRecord.getConsumablesOutNum());
+                    consumablesUnInventoryMapper.updateAddConsumablesUnInventory(consumablesUnInventoryDto);
+                }
+            }
+        }
+        return consumablesOutRecordMapper.deleteBatchIds(ids);
+    }
+
+    @Override
+    public void exportConsumablesOutRecord(HttpServletResponse response, ConsumablesOutRecordDto ConsumablesOutRecordDto) {
+        List<ConsumablesOutRecordExportData> list = consumablesOutRecordMapper.listConsumablesOutRecordExportData(ConsumablesOutRecordDto);
+        for (ConsumablesOutRecordExportData consumablesInRecordExportData : list) {
+            if (consumablesInRecordExportData.getType().equals("0")) {
+                consumablesInRecordExportData.setRecordType(EnumUtil.fromCode(StockOutQualifiedRecordTypeEnum.class, Integer.parseInt(consumablesInRecordExportData.getRecordType())).getValue());
+            }else {
+                consumablesInRecordExportData.setRecordType(EnumUtil.fromCode(StockInUnQualifiedRecordTypeEnum.class, Integer.parseInt(consumablesInRecordExportData.getRecordType())).getValue());
+            }
+        }
+        ExcelUtil<ConsumablesOutRecordExportData> util = new ExcelUtil<>(ConsumablesOutRecordExportData.class);
+        util.exportExcel(response,list, "鍑哄簱璁板綍淇℃伅");
+    }
+}
diff --git a/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesUnInventoryServiceImpl.java b/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesUnInventoryServiceImpl.java
new file mode 100644
index 0000000..a504657
--- /dev/null
+++ b/src/main/java/com/ruoyi/consumables/service/impl/ConsumablesUnInventoryServiceImpl.java
@@ -0,0 +1,125 @@
+package com.ruoyi.consumables.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.consumables.dto.ConsumablesInRecordDto;
+import com.ruoyi.consumables.dto.ConsumablesInventoryDto;
+import com.ruoyi.consumables.dto.ConsumablesOutRecordDto;
+import com.ruoyi.consumables.dto.ConsumablesUnInventoryDto;
+import com.ruoyi.consumables.execl.ConsumablesUnInventoryExportData;
+import com.ruoyi.consumables.mapper.ConsumablesUnInventoryMapper;
+import com.ruoyi.consumables.pojo.ConsumablesUnInventory;
+import com.ruoyi.consumables.service.ConsumablesInRecordService;
+import com.ruoyi.consumables.service.ConsumablesOutRecordService;
+import com.ruoyi.consumables.service.ConsumablesUnInventoryService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * <p>
+ * 涓嶅悎鏍煎簱瀛樿〃 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-22 10:17:45
+ */
+@Service
+@AllArgsConstructor
+public class ConsumablesUnInventoryServiceImpl extends ServiceImpl<ConsumablesUnInventoryMapper, ConsumablesUnInventory> implements ConsumablesUnInventoryService {
+
+    private ConsumablesUnInventoryMapper ConsumablesUnInventoryMapper;
+    private ConsumablesOutRecordService ConsumablesOutRecordService;
+    private ConsumablesInRecordService ConsumablesInRecordService;
+
+    @Override
+    public IPage<ConsumablesUnInventoryDto> pageConsumablesUnInventory(Page page, ConsumablesUnInventoryDto ConsumablesUnInventoryDto) {
+        return ConsumablesUnInventoryMapper.pageConsumablesUnInventory(page, ConsumablesUnInventoryDto);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Integer addConsumablesUnInventory(ConsumablesUnInventoryDto ConsumablesUnInventoryDto) {
+        //鏂板鍏ュ簱璁板綍鍐嶆坊鍔犲簱瀛�
+        ConsumablesInRecordDto ConsumablesInRecordDto = new ConsumablesInRecordDto();
+        ConsumablesInRecordDto.setRecordId(ConsumablesUnInventoryDto.getRecordId());
+        ConsumablesInRecordDto.setRecordType(ConsumablesUnInventoryDto.getRecordType());
+        ConsumablesInRecordDto.setConsumablesInNum(ConsumablesUnInventoryDto.getQualitity());
+        ConsumablesInRecordDto.setProductModelId(ConsumablesUnInventoryDto.getProductModelId());
+        ConsumablesInRecordDto.setType("1");
+        ConsumablesInRecordService.add(ConsumablesInRecordDto);
+        //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
+        //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
+        ConsumablesUnInventory oldConsumablesUnInventory = ConsumablesUnInventoryMapper.selectOne(new QueryWrapper<ConsumablesUnInventory>().lambda().eq(ConsumablesUnInventory::getProductModelId, ConsumablesUnInventoryDto.getProductModelId()));
+        if (ObjectUtils.isEmpty(oldConsumablesUnInventory)) {
+            ConsumablesUnInventory newConsumablesUnInventory = new ConsumablesUnInventory();
+            newConsumablesUnInventory.setProductModelId(ConsumablesUnInventoryDto.getProductModelId());
+            newConsumablesUnInventory.setQualitity(ConsumablesUnInventoryDto.getQualitity());
+            newConsumablesUnInventory.setVersion(1);
+            newConsumablesUnInventory.setRemark(ConsumablesUnInventoryDto.getRemark());
+            ConsumablesUnInventoryMapper.insert(newConsumablesUnInventory);
+        }else {
+            ConsumablesUnInventoryMapper.updateAddConsumablesUnInventory(ConsumablesUnInventoryDto);
+        }
+        return 1;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Integer subtractConsumablesUnInventory(ConsumablesUnInventoryDto ConsumablesUnInventoryDto) {
+
+        //  鏂板鍑哄簱璁板綍
+        ConsumablesOutRecordDto ConsumablesOutRecordDto = new ConsumablesOutRecordDto();
+        ConsumablesOutRecordDto.setRecordId(ConsumablesUnInventoryDto.getRecordId());
+        ConsumablesOutRecordDto.setRecordType(ConsumablesUnInventoryDto.getRecordType());
+        ConsumablesOutRecordDto.setConsumablesOutNum(ConsumablesUnInventoryDto.getQualitity());
+        ConsumablesOutRecordDto.setProductModelId(ConsumablesUnInventoryDto.getProductModelId());
+        ConsumablesOutRecordDto.setType("1");
+        ConsumablesOutRecordService.add(ConsumablesOutRecordDto);
+        ConsumablesUnInventory oldConsumablesInventory = ConsumablesUnInventoryMapper.selectOne(new QueryWrapper<ConsumablesUnInventory>().lambda().eq(ConsumablesUnInventory::getProductModelId, ConsumablesUnInventoryDto.getProductModelId()));
+        if (ObjectUtils.isEmpty(oldConsumablesInventory)) {
+            throw new RuntimeException("浜у搧搴撳瓨涓嶅瓨鍦�");
+        }else {
+            ConsumablesUnInventoryMapper.updateSubtractConsumablesUnInventory(ConsumablesUnInventoryDto);
+        }
+        return 1;
+    }
+
+    @Override
+    public void exportConsumablesUnInventory(HttpServletResponse response, ConsumablesUnInventoryDto ConsumablesUnInventoryDto) {
+        List<ConsumablesUnInventoryExportData> list = ConsumablesUnInventoryMapper.listConsumablesInventoryExportData(ConsumablesUnInventoryDto);
+        ExcelUtil<ConsumablesUnInventoryExportData> util = new ExcelUtil<>(ConsumablesUnInventoryExportData.class);
+        util.exportExcel(response,list, "涓嶅悎鏍煎簱瀛樹俊鎭�");
+    }
+
+    @Override
+    public Boolean frozenConsumables(ConsumablesInventoryDto ConsumablesInventoryDto) {
+        ConsumablesUnInventory ConsumablesUnInventory = ConsumablesUnInventoryMapper.selectById(ConsumablesInventoryDto.getId());
+        if (ConsumablesUnInventory.getQualitity().compareTo(ConsumablesInventoryDto.getLockedQuantity())<0) {
+            throw new RuntimeException("鍐荤粨鏁伴噺涓嶈兘瓒呰繃搴撳瓨鏁伴噺");
+        }
+        if (ObjectUtils.isEmpty(ConsumablesUnInventory.getLockedQuantity())) {
+            ConsumablesUnInventory.setLockedQuantity(ConsumablesInventoryDto.getLockedQuantity());
+        }else {
+            ConsumablesUnInventory.setLockedQuantity(ConsumablesUnInventory.getLockedQuantity().add(ConsumablesInventoryDto.getLockedQuantity()));
+        }
+        return this.updateById(ConsumablesUnInventory);
+    }
+
+    @Override
+    public Boolean thawConsumables(ConsumablesInventoryDto ConsumablesInventoryDto) {
+        ConsumablesUnInventory ConsumablesUnInventory = ConsumablesUnInventoryMapper.selectById(ConsumablesInventoryDto.getId());
+        if (ConsumablesUnInventory.getLockedQuantity().compareTo(ConsumablesInventoryDto.getLockedQuantity())<0) {
+            throw new RuntimeException("瑙e喕鏁伴噺涓嶈兘瓒呰繃鍐荤粨鏁伴噺");
+        }
+        ConsumablesUnInventory.setLockedQuantity(ConsumablesUnInventory.getLockedQuantity().subtract(ConsumablesInventoryDto.getLockedQuantity()));
+        return this.updateById(ConsumablesUnInventory);
+    }
+}
diff --git a/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java b/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
index fd8398c..fcbef30 100644
--- a/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
+++ b/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
@@ -30,7 +30,7 @@
 
     @GetMapping("/listPage")
     @ApiOperation(value = "璁惧淇濆吇瀹氭椂浠诲姟鍒楄〃")
-    public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) {
+    public AjaxResult listPage(Page<MaintenanceTask> page, MaintenanceTask maintenanceTask) {
         return maintenanceTaskService.listPage(page,maintenanceTask);
     }
 
diff --git a/src/main/java/com/ruoyi/device/dto/MaintenanceTaskDto.java b/src/main/java/com/ruoyi/device/dto/MaintenanceTaskDto.java
new file mode 100644
index 0000000..53b7d87
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/dto/MaintenanceTaskDto.java
@@ -0,0 +1,17 @@
+package com.ruoyi.device.dto;
+
+import com.ruoyi.device.pojo.MaintenanceTask;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class MaintenanceTaskDto extends MaintenanceTask {
+
+    private static final long serialVersionUID = 1L;
+
+    private List<Long> taskIds;
+
+}
diff --git a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
index a6f4432..67ec0d9 100644
--- a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
+++ b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
@@ -11,6 +11,7 @@
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
+import java.io.Serializable;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 
@@ -21,7 +22,7 @@
 @Data
 @ApiModel
 @TableName("maintenance_task")
-public class MaintenanceTask {
+public class MaintenanceTask implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
@@ -34,12 +35,15 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "璁惧鍚嶇О")
+    @ApiModelProperty(value = "浠诲姟鍚嶇О")
     @Excel(name = "淇濆吇浠诲姟鍚嶇О")
     private String taskName;
 
     @ApiModelProperty(value = "璁惧id")
     private Long taskId;
+
+    @ApiModelProperty(value = "澶氫釜璁惧id")
+    private String deviceIds;
 
     @ApiModelProperty(value = "棰戞")
     @Excel(name = "棰戞")
@@ -106,4 +110,6 @@
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
     private Long tenantId;
 
+    @TableField(exist = false)
+    private String deviceName;
 }
diff --git a/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java b/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
index 19cb6ed..80ff64b 100644
--- a/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
+++ b/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
@@ -12,7 +12,7 @@
  * @date : 2025/12/22 14:56
  */
 public interface MaintenanceTaskService extends IService<MaintenanceTask> {
-    AjaxResult listPage(Page page, MaintenanceTask maintenanceTask);
+    AjaxResult listPage(Page<MaintenanceTask> page, MaintenanceTask maintenanceTask);
 
     AjaxResult add(MaintenanceTask maintenanceTask);
 
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
index 0e2d317..96a511b 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
@@ -15,7 +15,6 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
-import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -28,7 +27,6 @@
 import java.util.List;
 
 @Service
-@AllArgsConstructor
 @Slf4j
 public class DeviceLedgerServiceImpl  extends ServiceImpl<DeviceLedgerMapper, DeviceLedger> implements IDeviceLedgerService {
 
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
index fca829a..bc3f320 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
@@ -1,5 +1,10 @@
 package com.ruoyi.device.service.impl;
 
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.device.pojo.DeviceMaintenance;
 import com.ruoyi.device.pojo.MaintenanceTask;
 import org.quartz.*;
@@ -13,9 +18,9 @@
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.YearMonth;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 @Component
 @DisallowConcurrentExecution // 绂佹骞跺彂鎵ц鍚屼竴涓狫ob
@@ -27,6 +32,9 @@
 
     @Autowired
     private JdbcTemplate jdbcTemplate;
+
+    @Autowired
+    private DeviceLedgerMapper deviceLedgerMapper;
 
     @Override
     public void execute(JobExecutionContext context) throws JobExecutionException {
@@ -48,9 +56,8 @@
                 throw new JobExecutionException("MaintenanceTaskJob鎵句笉鍒板畾鏃朵换鍔�: " + taskId);
             }
 
-            // 2. 鍒涘缓骞朵繚瀛樺贰妫�浠诲姟璁板綍 - 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸簲璇ユ斁鐨勪綅缃�
-            DeviceMaintenance deviceMaintenance = createInspectionTask(timingTask);
-            deviceMaintenanceService.save(deviceMaintenance);
+            // 2. 鍒涘缓骞朵繚瀛樺贰妫�浠诲姟璁板綍
+            createInspectionTask(timingTask);
 
             // 3. 鏇存柊瀹氭椂浠诲姟鐨勬墽琛屾椂闂�
             if (!tasks.isEmpty()) {
@@ -83,25 +90,87 @@
         }
     }
 
-    // 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸皝瑁呮垚鐨勬柟娉�
-    private DeviceMaintenance createInspectionTask(MaintenanceTask timingTask) {
-        DeviceMaintenance inspectionTask = new DeviceMaintenance();
+    // 瀹炰綋绫诲皝瑁�
+    private void createInspectionTask(MaintenanceTask timingTask) {
+        // 1. 鍙傛暟鏍¢獙
+        if (timingTask == null || StringUtils.isEmpty(timingTask.getDeviceIds())) {
+            return;
+        }
 
-        // 澶嶅埗鍩烘湰灞炴��
-        inspectionTask.setDeviceName(timingTask.getTaskName());
-        inspectionTask.setMaintenanceTaskId(timingTask.getId());
-        inspectionTask.setDeviceLedgerId(timingTask.getTaskId());
-        inspectionTask.setMaintenancePlanTime(LocalDateTime.now());
-        inspectionTask.setFrequencyType(timingTask.getFrequencyType());
-        inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail());
-        inspectionTask.setTenantId(timingTask.getTenantId());
-        inspectionTask.setStatus(0);
-        inspectionTask.setDeviceModel(timingTask.getDeviceModel());
-        inspectionTask.setCreateUser(Integer.parseInt(timingTask.getRegistrantId().toString()));
-        inspectionTask.setUpdateTime(LocalDateTime.now());
-        inspectionTask.setCreateTime(LocalDateTime.now());
-        inspectionTask.setUpdateUser(Integer.parseInt(timingTask.getRegistrantId().toString()));
-        return inspectionTask;
+        // 2. 瑙f瀽璁惧ID鍒楄〃
+        List<Long> deviceIds;
+        try {
+            deviceIds = JSON.parseArray(timingTask.getDeviceIds(), Long.class);
+        } catch (Exception e) {
+            throw new RuntimeException("璁惧ID鏍煎紡閿欒");
+        }
+
+        if (CollectionUtils.isEmpty(deviceIds)) {
+            return;
+        }
+
+        // 3. 鎵归噺鏌ヨ璁惧淇℃伅
+        List<DeviceLedger> deviceLedgers = deviceLedgerMapper.selectBatchIds(deviceIds);
+        if (CollectionUtils.isEmpty(deviceLedgers)) {
+            return;
+        }
+
+        // 4. 杞崲涓篗ap
+        Map<Long, DeviceLedger> deviceLedgerMap = deviceLedgers.stream()
+                .collect(Collectors.toMap(DeviceLedger::getId, Function.identity()));
+
+        // 5. 鎵归噺鏋勫缓宸℃浠诲姟
+        List<DeviceMaintenance> inspectionTaskList = new ArrayList<>();
+        LocalDateTime now = LocalDateTime.now();
+
+        Integer createUser = null;
+        if (timingTask.getRegistrantId() != null) {
+            try {
+                createUser = Math.toIntExact(timingTask.getRegistrantId());
+            } catch (ArithmeticException e) {
+                throw new RuntimeException("鐢ㄦ埛ID瓒呭嚭鏈夋晥鑼冨洿");
+            }
+        }
+
+        for (Long deviceId : deviceIds) {
+            DeviceLedger deviceLedger = deviceLedgerMap.get(deviceId);
+            if (deviceLedger == null) {
+                continue;
+            }
+
+            DeviceMaintenance inspectionTask = new DeviceMaintenance();
+
+            // 璁剧疆璁惧鐩稿叧淇℃伅
+            inspectionTask.setDeviceLedgerId(deviceId);
+            inspectionTask.setDeviceName(deviceLedger.getDeviceName());
+            inspectionTask.setDeviceModel(deviceLedger.getDeviceModel());
+
+            // 璁剧疆浠诲姟鐩稿叧淇℃伅
+            inspectionTask.setMaintenanceTaskId(timingTask.getId());
+            inspectionTask.setMaintenancePlanTime(now);
+            inspectionTask.setFrequencyType(timingTask.getFrequencyType());
+            inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail());
+
+            // 璁剧疆鐘舵�佸拰鏃堕棿
+            inspectionTask.setStatus(0);
+            inspectionTask.setCreateTime(now);
+            inspectionTask.setUpdateTime(now);
+
+            // 璁剧疆鐢ㄦ埛淇℃伅
+            inspectionTask.setTenantId(timingTask.getTenantId());
+            inspectionTask.setCreateUser(createUser);
+            inspectionTask.setUpdateUser(createUser);
+
+            inspectionTaskList.add(inspectionTask);
+        }
+
+        if (!inspectionTaskList.isEmpty()) {
+            try {
+                deviceMaintenanceService.saveBatch(inspectionTaskList);
+            } catch (Exception e) {
+                throw new RuntimeException("鍒涘缓宸℃浠诲姟澶辫触");
+            }
+        }
     }
 
 
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
index 0c00da7..c590ca0 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
@@ -1,9 +1,15 @@
 package com.ruoyi.device.service.impl;
 
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
 import com.ruoyi.device.mapper.MaintenanceTaskMapper;
+import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.device.pojo.MaintenanceTask;
 import com.ruoyi.device.service.MaintenanceTaskService;
 import com.ruoyi.framework.web.domain.AjaxResult;
@@ -17,6 +23,7 @@
 
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author :yys
@@ -38,36 +45,87 @@
     @Autowired
     private MaintenanceTaskScheduler maintenanceTaskScheduler;
 
+    @Autowired
+    private DeviceLedgerMapper deviceLedgerMapper;
+
     @Override
-    public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) {
-        Page<MaintenanceTask> taskPage = maintenanceTaskMapper.selectPage(page, null);
-        // 2. 濡傛灉娌℃湁鏁版嵁锛岀洿鎺ヨ繑鍥炵┖鍒嗛〉
+    public AjaxResult listPage(Page<MaintenanceTask> page, MaintenanceTask maintenanceTask) {
+        // 鏌ヨ
+        LambdaQueryWrapper<MaintenanceTask> queryWrapper = new LambdaQueryWrapper<>();
+        if (maintenanceTask.getTaskName() != null) {
+            queryWrapper.like(MaintenanceTask::getTaskName, maintenanceTask.getTaskName());
+        }
+
+        Page<MaintenanceTask> taskPage = maintenanceTaskMapper.selectPage(page, queryWrapper);
+
         if (taskPage.getRecords().isEmpty()) {
             return AjaxResult.success(taskPage);
         }
 
-        // 3. 鏀堕泦鎵�鏈夐渶瑕佹煡璇㈢殑鐢ㄦ埛ID
+        //鏀堕泦鎵�鏈夐渶瑕佹煡璇㈢殑ID
         Set<Long> userIds = new HashSet<>();
+        Set<Long> allDeviceIds = new HashSet<>();
+        //璁惧ID鍒楄〃
+        Map<Long, List<Long>> taskDeviceIdMap = new HashMap<>();
 
-        // 鏀堕泦鐧昏浜篒D
-        taskPage.getRecords().forEach(task -> {
+        // 閬嶅巻浠诲姟锛屾敹闆嗙櫥璁颁汉ID鍜岃澶嘔D
+        for (MaintenanceTask task : taskPage.getRecords()) {
+            // 鏀堕泦鐧昏浜篒D
             if (task.getRegistrantId() != null) {
                 userIds.add(task.getRegistrantId());
             }
-        });
+
+            // 鏀堕泦璁惧ID骞惰В鏋�
+            if (StringUtils.isNotEmpty(task.getDeviceIds())) {
+                try {
+                    List<Long> deviceIds = JSON.parseArray(task.getDeviceIds(), Long.class);
+                    if (CollectionUtils.isNotEmpty(deviceIds)) {
+                        allDeviceIds.addAll(deviceIds);
+                        taskDeviceIdMap.put(task.getId(), deviceIds);
+                    }
+                } catch (Exception e) {
+                    log.error("瑙f瀽璁惧ID鍒楄〃澶辫触: taskId={}, deviceIds={}", task.getId(), task.getDeviceIds(), e);
+                }
+            }
+        }
 
         // 4. 鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
         Map<Long, String> userNickNameMap = new HashMap<>();
         if (!userIds.isEmpty()) {
-            List<SysUser> users = sysUserMapper.selectUserByIds((new ArrayList<>(userIds)));
-            users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
+            List<SysUser> users = sysUserMapper.selectUserByIds(new ArrayList<>(userIds));
+            if (CollectionUtils.isNotEmpty(users)) {
+                users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
+            }
         }
-        taskPage.getRecords().forEach(task -> {
+
+        // 5. 鎵归噺鏌ヨ璁惧淇℃伅
+        Map<Long, String> deviceNameMap = new HashMap<>();
+        if (!allDeviceIds.isEmpty()) {
+            List<DeviceLedger> devices = deviceLedgerMapper.selectBatchIds(new ArrayList<>(allDeviceIds));
+            if (CollectionUtils.isNotEmpty(devices)) {
+                devices.forEach(device -> deviceNameMap.put(device.getId(), device.getDeviceName()));
+            }
+        }
+
+        // 6. 璁剧疆杩斿洖缁撴灉
+        for (MaintenanceTask task : taskPage.getRecords()) {
             // 璁剧疆鐧昏浜烘樀绉�
             if (task.getRegistrantId() != null) {
                 task.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "鏈煡鐢ㄦ埛"));
             }
-        });
+
+            // 璁剧疆璁惧鍚嶇О
+            List<Long> deviceIds = taskDeviceIdMap.get(task.getId());
+            if (CollectionUtils.isNotEmpty(deviceIds)) {
+                List<String> deviceNames = deviceIds.stream()
+                        .map(id -> deviceNameMap.getOrDefault(id, "鏈煡璁惧"))
+                        .collect(Collectors.toList());
+                task.setDeviceName(String.join(", ", deviceNames));
+            } else {
+                task.setDeviceName("鏃犺澶�");
+            }
+        }
+
         return AjaxResult.success(taskPage);
     }
 
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
index 78464d4..9c3f5de 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
@@ -56,4 +56,16 @@
 
     @ApiModelProperty("杞︾墝鍙�")
     private String licensePlateNo;
+
+    @ApiModelProperty("姣涢噸")
+    private BigDecimal grossWeight;
+
+    @ApiModelProperty("鐨噸")
+    private BigDecimal tareWeight;
+
+    @ApiModelProperty("杩囩鍛�")
+    private String weighingOperator;
+
+    @ApiModelProperty("纾呭崟鏂囦欢璺緞")
+    private String weighbridgeDocPath;
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java b/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
index cad02df..2b70d8b 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
@@ -70,4 +70,33 @@
 
     @ApiModelProperty("鍑�閲�")
     private BigDecimal netWeight;
+    /**
+     * 姣涢噸锛堝崟浣嶏細鍚級
+     */
+    @ApiModelProperty("姣涢噸")
+    private BigDecimal grossWeight;
+
+    /**
+     * 鐨噸锛堝崟浣嶏細鍚級
+     */
+    @ApiModelProperty("鐨噸")
+    private BigDecimal tareWeight;
+
+    /**
+     * 杞︾墝鍙�
+     */
+    @ApiModelProperty("杞︾墝鍙�")
+    private String licensePlateNo;
+
+    /**
+     * 杩囩鍛�
+     */
+    @ApiModelProperty("杩囩鍛�")
+    private String weighingOperator;
+
+    @ApiModelProperty("纾呭崟鏂囦欢璺緞")
+    private String weighbridgeDocPath;
+
+    @ApiModelProperty("浜у搧id")
+    private Long productId;
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockInventory.java b/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
index 36e7cf0..59983e2 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
@@ -63,4 +63,7 @@
 
     @ApiModelProperty("澶囨敞")
     private String remark;
+
+    @ApiModelProperty("浜у搧id")
+    private Long productId;
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java b/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
index a38ab4d..12cbf81 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
@@ -82,4 +82,16 @@
 
     @ApiModelProperty("杞︾墝鍙�")
     private String licensePlateNo;
+
+    @ApiModelProperty("姣涢噸")
+    private BigDecimal grossWeight;
+
+    @ApiModelProperty("鐨噸")
+    private BigDecimal tareWeight;
+
+    @ApiModelProperty("杩囩鍛�")
+    private String weighingOperator;
+
+    @ApiModelProperty("浜у搧id")
+    private Long productId;
 }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
index fae5de3..bc2eb2e 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -19,7 +19,9 @@
 import com.ruoyi.stock.service.StockInRecordService;
 import com.ruoyi.stock.service.StockInventoryService;
 import com.ruoyi.stock.service.StockOutRecordService;
-import lombok.AllArgsConstructor;
+import com.ruoyi.stock.word.WeighbridgeDocGenerator;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
@@ -38,13 +40,15 @@
  * @since 2026-01-21 04:16:36
  */
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class StockInventoryServiceImpl extends ServiceImpl<StockInventoryMapper, StockInventory> implements StockInventoryService {
 
-    private  StockInventoryMapper stockInventoryMapper;
-    private StockInRecordService stockInRecordService;
-    private StockOutRecordService stockOutRecordService;
-    private SalesLedgerProductMapper salesLedgerProductMapper;
+    private final StockInventoryMapper stockInventoryMapper;
+    private final StockInRecordService stockInRecordService;
+    private final StockOutRecordService stockOutRecordService;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final WeighbridgeDocGenerator weighbridgeDocGenerator;
+
     @Override
     public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
         return stockInventoryMapper.pagestockInventory(page, stockInventoryDto);
@@ -58,11 +62,19 @@
         StockInRecordDto stockInRecordDto = new StockInRecordDto();
         stockInRecordDto.setRecordId(stockInventoryDto.getRecordId());
         stockInRecordDto.setRecordType(stockInventoryDto.getRecordType());
-        stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
+        stockInRecordDto.setStockInNum(stockInventoryDto.getNetWeight());
         stockInRecordDto.setWeighingDate(stockInventoryDto.getWeighingDate());
         stockInRecordDto.setNetWeight(stockInventoryDto.getNetWeight());
+        stockInRecordDto.setGrossWeight(stockInventoryDto.getGrossWeight());
+        stockInRecordDto.setTareWeight(stockInventoryDto.getTareWeight());
+        stockInRecordDto.setLicensePlateNo(stockInventoryDto.getLicensePlateNo());
+        stockInRecordDto.setWeighingOperator(stockInventoryDto.getWeighingOperator());
         stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
+        stockInRecordDto.setProductId(stockInventoryDto.getProductId());
         stockInRecordDto.setType("0");
+        //鐢熸垚纾呭崟
+        String absoluteDocPath = weighbridgeDocGenerator.generateWeighbridgeDoc(stockInRecordDto);
+        stockInRecordDto.setWeighbridgeDocPath(absoluteDocPath);
         stockInRecordService.add(stockInRecordDto);
         //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
         //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
@@ -70,14 +82,15 @@
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             StockInventory newStockInventory = new StockInventory();
             newStockInventory.setProductModelId(stockInventoryDto.getProductModelId());
-            newStockInventory.setQualitity(stockInventoryDto.getQualitity());
+            newStockInventory.setQualitity(stockInventoryDto.getNetWeight());
             newStockInventory.setVersion(1);
             newStockInventory.setRemark(stockInventoryDto.getRemark());
             newStockInventory.setLockedQuantity(stockInventoryDto.getLockedQuantity());
             newStockInventory.setWarnNum(stockInventoryDto.getWarnNum());
             stockInventoryMapper.insert(newStockInventory);
-        }else {
-             stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
+        } else {
+            stockInventoryDto.setQualitity(stockInventoryDto.getNetWeight());
+            stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
         }
         return true;
     }
@@ -91,10 +104,14 @@
         stockOutRecordDto.setRecordId(stockInventoryDto.getRecordId());
         stockOutRecordDto.setRecordType(stockInventoryDto.getRecordType());
         stockInventoryDto.setWeighingDate(stockInventoryDto.getWeighingDate());
-        stockOutRecordDto.setStockOutNum(stockInventoryDto.getQualitity());
+        stockOutRecordDto.setStockOutNum(stockInventoryDto.getNetWeight());
         stockOutRecordDto.setNetWeight(stockInventoryDto.getNetWeight());
+        stockOutRecordDto.setGrossWeight(stockInventoryDto.getGrossWeight());
+        stockOutRecordDto.setTareWeight(stockInventoryDto.getTareWeight());
+        stockOutRecordDto.setWeighingOperator(stockInventoryDto.getWeighingOperator());
         stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
         stockOutRecordDto.setLicensePlateNo(stockInventoryDto.getLicensePlateNo());
+        stockOutRecordDto.setProductId(stockInventoryDto.getProductId());
         stockOutRecordDto.setType("0");
         stockOutRecordService.add(stockOutRecordDto);
         StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
@@ -136,7 +153,7 @@
                         stockInventoryDto.setQualitity(dto.getQualitity());
                         stockInventoryDto.setRemark(dto.getRemark());
                         stockInventoryDto.setWarnNum(dto.getWarnNum());
-                        if (ObjectUtils.isNotEmpty(dto.getLockedQuantity())&&dto.getLockedQuantity().compareTo(dto.getQualitity())>0) {
+                        if (ObjectUtils.isNotEmpty(dto.getLockedQuantity()) && dto.getLockedQuantity().compareTo(dto.getQualitity()) > 0) {
                             throw new RuntimeException("鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫簱瀛樻暟閲�");
                         }
                         stockInventoryDto.setLockedQuantity(dto.getLockedQuantity());
@@ -175,28 +192,28 @@
 
         List<StockInventoryExportData> list = stockInventoryMapper.listStockInventoryExportData(stockInventoryDto);
         ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class);
-        util.exportExcel(response,list, "搴撳瓨淇℃伅");
+        util.exportExcel(response, list, "搴撳瓨淇℃伅");
     }
 
     @Override
     public IPage<StockInRecordDto> stockInventoryPage(StockInventoryDto stockInventoryDto, Page page) {
-        return stockInventoryMapper.stockInventoryPage(stockInventoryDto,page);
+        return stockInventoryMapper.stockInventoryPage(stockInventoryDto, page);
     }
 
     @Override
     public IPage<StockInventoryDto> stockInAndOutRecord(StockInventoryDto stockInventoryDto, Page page) {
-        return stockInventoryMapper.stockInAndOutRecord(stockInventoryDto,page);
+        return stockInventoryMapper.stockInAndOutRecord(stockInventoryDto, page);
     }
 
     @Override
     public Boolean frozenStock(StockInventoryDto stockInventoryDto) {
         StockInventory stockInventory = stockInventoryMapper.selectById(stockInventoryDto.getId());
-        if (stockInventory.getQualitity().compareTo(stockInventoryDto.getLockedQuantity())<0) {
+        if (stockInventory.getQualitity().compareTo(stockInventoryDto.getLockedQuantity()) < 0) {
             throw new RuntimeException("鍐荤粨鏁伴噺涓嶈兘瓒呰繃搴撳瓨鏁伴噺");
         }
         if (ObjectUtils.isEmpty(stockInventory.getLockedQuantity())) {
             stockInventory.setLockedQuantity(stockInventoryDto.getLockedQuantity());
-        }else {
+        } else {
             stockInventory.setLockedQuantity(stockInventory.getLockedQuantity().add(stockInventoryDto.getLockedQuantity()));
         }
         return this.updateById(stockInventory);
@@ -205,7 +222,7 @@
     @Override
     public Boolean thawStock(StockInventoryDto stockInventoryDto) {
         StockInventory stockInventory = stockInventoryMapper.selectById(stockInventoryDto.getId());
-        if (stockInventory.getLockedQuantity().compareTo(stockInventoryDto.getLockedQuantity())<0) {
+        if (stockInventory.getLockedQuantity().compareTo(stockInventoryDto.getLockedQuantity()) < 0) {
             throw new RuntimeException("瑙e喕鏁伴噺涓嶈兘瓒呰繃鍐荤粨鏁伴噺");
         }
         stockInventory.setLockedQuantity(stockInventory.getLockedQuantity().subtract(stockInventoryDto.getLockedQuantity()));
diff --git a/src/main/java/com/ruoyi/stock/word/ChineseNumberUtil.java b/src/main/java/com/ruoyi/stock/word/ChineseNumberUtil.java
new file mode 100644
index 0000000..b72e35b
--- /dev/null
+++ b/src/main/java/com/ruoyi/stock/word/ChineseNumberUtil.java
@@ -0,0 +1,101 @@
+package com.ruoyi.stock.word;
+
+import java.math.BigDecimal;
+
+/**
+ * 閲戦鏁板瓧杞ぇ鍐欏伐鍏风被
+ */
+public class ChineseNumberUtil {
+
+    private static final String[] CN_UPPER_NUMBER = {"闆�", "澹�", "璐�", "鍙�", "鑲�", "浼�", "闄�", "鏌�", "鎹�", "鐜�"};
+    private static final String[] CN_UPPER_UNIT = {"", "鎷�", "浣�", "浠�", "涓�", "鎷�", "浣�", "浠�", "浜�", "鎷�", "浣�", "浠�"};
+    private static final String CN_DOLLAR = "";
+    private static final String CN_TEN_CENT = "鐐�";
+    private static final String CN_CENT = "";
+    private static final String CN_INTEGER = "鏁�";
+
+    /**
+     * 灏嗘暟瀛楄浆鎹负澶у啓閲戦
+     * @param number 鏁板瓧锛堝崟浣嶏細鍚級
+     * @return 澶у啓閲戦瀛楃涓�
+     */
+    public static String numberToChinese(BigDecimal number) {
+        if (number == null) {
+            return "闆�";
+        }
+
+        // 澶勭悊璐熸暟
+        boolean isNegative = false;
+        if (number.compareTo(BigDecimal.ZERO) < 0) {
+            isNegative = true;
+            number = number.abs();
+        }
+
+        StringBuilder result = new StringBuilder();
+
+        // 鍒嗙鏁存暟鍜屽皬鏁伴儴鍒�
+        String[] parts = number.toString().split("\\.");
+        String integerPart = parts[0];
+        String decimalPart = parts.length > 1 ? parts[1] : "";
+
+        // 杞崲鏁存暟閮ㄥ垎
+        if (!"0".equals(integerPart)) {
+            result.append(convertIntegerPart(integerPart));
+        } else {
+            result.append("闆�");
+        }
+
+        // 杞崲灏忔暟閮ㄥ垎
+        if (decimalPart.length() > 0 && !"00".equals(decimalPart) && !"0".equals(decimalPart)) {
+            result.append(CN_TEN_CENT);
+            char[] decimals = decimalPart.toCharArray();
+            for (int i = 0; i < decimals.length; i++) {
+                if (decimals[i] != '0') {
+                    result.append(CN_UPPER_NUMBER[Integer.parseInt(String.valueOf(decimals[i]))]);
+                } else {
+                    if (i < decimals.length - 1 && decimals[i + 1] != '0') {
+                        result.append(CN_UPPER_NUMBER[0]);
+                    }
+                }
+            }
+        }
+
+        return isNegative ? "璐�" + result.toString() : result.toString();
+    }
+
+    /**
+     * 杞崲鏁存暟閮ㄥ垎
+     */
+    private static String convertIntegerPart(String integerPart) {
+        StringBuilder result = new StringBuilder();
+        int length = integerPart.length();
+
+        for (int i = 0; i < length; i++) {
+            int digit = Integer.parseInt(String.valueOf(integerPart.charAt(i)));
+            int unitIndex = length - i - 1;
+
+            if (digit != 0) {
+                result.append(CN_UPPER_NUMBER[digit]).append(CN_UPPER_UNIT[unitIndex]);
+            } else {
+                // 澶勭悊杩炵画鐨勯浂
+                if (i > 0 && integerPart.charAt(i - 1) != '0') {
+                    result.append(CN_UPPER_NUMBER[0]);
+                }
+                // 澶勭悊涓囦綅鍜屼嚎浣�
+                if (unitIndex == 4 || unitIndex == 8) {
+                    if (result.length() > 0 && !result.toString().endsWith(CN_UPPER_NUMBER[0])) {
+                        result.append(CN_UPPER_UNIT[unitIndex]);
+                    }
+                }
+            }
+        }
+
+        String resultStr = result.toString();
+        // 鍘婚櫎鏈熬鐨勯浂
+        while (resultStr.endsWith(CN_UPPER_NUMBER[0])) {
+            resultStr = resultStr.substring(0, resultStr.length() - 1);
+        }
+
+        return resultStr;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/stock/word/WeighbridgeDocGenerator.java b/src/main/java/com/ruoyi/stock/word/WeighbridgeDocGenerator.java
new file mode 100644
index 0000000..feafdd0
--- /dev/null
+++ b/src/main/java/com/ruoyi/stock/word/WeighbridgeDocGenerator.java
@@ -0,0 +1,268 @@
+package com.ruoyi.stock.word;
+
+import com.ruoyi.basic.pojo.Product;
+import com.ruoyi.basic.service.IProductService;
+import com.ruoyi.stock.dto.StockInRecordDto;
+import org.apache.poi.xwpf.usermodel.*;
+import org.apache.poi.xwpf.usermodel.XWPFTable.XWPFBorderType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 纾呭崟Word鏂囨。鐢熸垚鍣�
+ */
+@Component
+public class WeighbridgeDocGenerator {
+
+    @Value("${file.upload-dir}")
+    private String uploadDir;
+
+    @Autowired
+    private IProductService productService;
+
+    /**
+     * 鐢熸垚纾呭崟Word鏂囨。
+     * @param dto 鍏ュ簱璁板綍DTO
+     * @return 鏂囦欢淇濆瓨鐨勭粷瀵硅矾寰勶紝鐢熸垚澶辫触杩斿洖null
+     */
+    public String generateWeighbridgeDoc(StockInRecordDto dto) {
+        // 鍙傛暟鏍¢獙
+        if (dto == null) {
+            return null;
+        }
+
+        FileOutputStream out = null;
+        XWPFDocument document = null;
+
+        try {
+            // 鍒涘缓鏂版枃妗�
+            document = new XWPFDocument();
+
+            // 鏋勫缓鏂囨。鍐呭
+            buildDocumentContent(document, dto);
+
+            // 鏋勫缓鏂囦欢淇濆瓨璺緞锛堢粷瀵硅矾寰勶級
+            String absolutePath = buildAbsoluteFilePath(dto);
+            File file = new File(absolutePath);
+
+            // 纭繚鐩綍瀛樺湪
+            file.getParentFile().mkdirs();
+
+            // 鍐欏叆鏂囦欢
+            out = new FileOutputStream(file);
+            document.write(out);
+            out.flush();
+
+            // 杩斿洖缁濆璺緞锛堢敤浜庢暟鎹簱瀛樺偍锛�
+            return absolutePath;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            // 鍏抽棴璧勬簮
+            try {
+                if (out != null) {
+                    out.close();
+                }
+                if (document != null) {
+                    document.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 鏋勫缓鏂囨。鍐呭
+     */
+    private void buildDocumentContent(XWPFDocument document, StockInRecordDto dto) {
+        // 1. 娣诲姞鏍囬 "纾呯爜鍗�" - 浣跨敤榛戜綋
+        XWPFParagraph titlePara = document.createParagraph();
+        titlePara.setAlignment(ParagraphAlignment.CENTER);
+        titlePara.setSpacingAfter(200);
+
+        XWPFRun titleRun = titlePara.createRun();
+        titleRun.setText("纾呯爜鍗�");
+        titleRun.setBold(true);
+        titleRun.setFontSize(28);
+        titleRun.setFontFamily("榛戜綋");
+
+        // 2. 绌轰竴琛�
+        document.createParagraph();
+
+        // 3. 澶撮儴淇℃伅锛堝勾鏈堟棩鍜岃閲忓崟浣嶅悎骞跺湪涓�琛岋級- 浣跨敤瀹嬩綋
+        XWPFParagraph headerPara = document.createParagraph();
+        headerPara.setSpacingAfter(200);
+        XWPFRun headerRun = headerPara.createRun();
+
+        // 鏍煎紡鍖栨棩鏈熶负 yyyy-MM-dd
+        String weighDate = "";
+        if (dto.getWeighingDate() != null) {
+            try {
+                // 鍋囪 weighingDate 鏄� LocalDateTime 绫诲瀷
+                weighDate = dto.getWeighingDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+            } catch (Exception e) {
+                // 濡傛灉鏄瓧绗︿覆绫诲瀷锛屽皾璇曡浆鎹�
+                weighDate = dto.getWeighingDate().toString();
+                if (weighDate.length() > 10) {
+                    weighDate = weighDate.substring(0, 10);
+                }
+            }
+        }
+
+        headerRun.setText("骞存湀鏃ワ細" + weighDate + "    璁¢噺鍗曚綅锛氾紙鍚級");
+        headerRun.setFontSize(12);
+        headerRun.setFontFamily("瀹嬩綋");
+
+        // 4. 鍒涘缓涓昏〃鏍� - 4琛�6鍒楋紙琛ㄥご1琛�+鏁版嵁1琛�+鍚堣1琛�+绌鸿1琛岋級
+        XWPFTable table = document.createTable(4, 6);
+
+        // 璁剧疆琛ㄦ牸瀹藉害
+        table.setWidth("100%");
+
+        // 璁剧疆琛ㄦ牸杈规鍔犵矖锛堣竟妗嗗搴﹁涓�2锛�
+        table.setInsideHBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
+        table.setInsideVBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
+        table.setTopBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
+        table.setBottomBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
+        table.setLeftBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
+        table.setRightBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
+
+        // 璁剧疆琛岄珮
+        table.getRow(0).setHeight(400);
+        table.getRow(1).setHeight(400);
+        table.getRow(2).setHeight(400);
+        table.getRow(3).setHeight(400);
+
+        // 璁剧疆琛ㄥご - 浣跨敤榛戜綋鍔犵矖
+        String[] headers = {"杞﹀彿", "鍝佸悕", "姣涢噸", "鐨噸", "鍑�閲�", "澶囨敞"};
+        XWPFTableRow headerRow = table.getRow(0);
+        for (int i = 0; i < headers.length; i++) {
+            XWPFTableCell cell = headerRow.getCell(i);
+            cell.setText(headers[i]);
+            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
+
+            XWPFParagraph cellPara = cell.getParagraphs().get(0);
+            cellPara.setAlignment(ParagraphAlignment.CENTER);
+            XWPFRun cellRun = cellPara.getRuns().get(0);
+            cellRun.setBold(true);
+            cellRun.setFontSize(12);
+            cellRun.setFontFamily("榛戜綋");
+        }
+
+        // 璁剧疆鏁版嵁琛� - 浣跨敤瀹嬩綋
+        XWPFTableRow dataRow = table.getRow(1);
+        String netWeight = dto.getNetWeight() != null ? dto.getNetWeight().toString() : "";
+        String grossWeight = dto.getGrossWeight() != null ? dto.getGrossWeight().toString() : "";
+        String tareWeight = dto.getTareWeight() != null ? dto.getTareWeight().toString() : "";
+
+        String[] data = {
+                dto.getLicensePlateNo() != null ? dto.getLicensePlateNo() : "",
+                getProductModelName(dto.getProductId()),
+                grossWeight + "t",
+                tareWeight + "t",
+                netWeight + "t",
+                dto.getRemark() != null ? dto.getRemark() : ""
+        };
+
+        for (int i = 0; i < data.length; i++) {
+            XWPFTableCell cell = dataRow.getCell(i);
+            cell.setText(data[i]);
+            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
+
+            XWPFParagraph cellPara = cell.getParagraphs().get(0);
+            cellPara.setAlignment(ParagraphAlignment.CENTER);
+            XWPFRun cellRun = cellPara.getRuns().get(0);
+            cellRun.setFontSize(12);
+            cellRun.setFontFamily("瀹嬩綋");
+        }
+
+        // 鍚堣琛� - 绗�3琛�
+        XWPFTableRow totalRow = table.getRow(2);
+
+        // 绗�1鍒楁樉绀�"鍚堣锛堝ぇ鍐欙級"
+        XWPFTableCell totalLabelCell = totalRow.getCell(0);
+        totalLabelCell.setText("鍚堣锛堝ぇ鍐欙級");
+        totalLabelCell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
+        XWPFParagraph totalLabelPara = totalLabelCell.getParagraphs().get(0);
+        totalLabelPara.setAlignment(ParagraphAlignment.CENTER);
+        XWPFRun totalLabelRun = totalLabelPara.getRuns().get(0);
+        totalLabelRun.setBold(true);
+        totalLabelRun.setFontSize(12);
+        totalLabelRun.setFontFamily("瀹嬩綋");
+
+
+        XWPFTableCell contentCell = totalRow.getCell(1);
+        String netWeightChinese = ChineseNumberUtil.numberToChinese(
+                dto.getNetWeight() != null ? dto.getNetWeight() : BigDecimal.ZERO
+        );
+        contentCell.setText(netWeightChinese + "鍚�");
+        contentCell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
+        XWPFParagraph contentPara = contentCell.getParagraphs().get(0);
+        contentPara.setAlignment(ParagraphAlignment.LEFT);
+        XWPFRun contentRun = contentPara.getRuns().get(0);
+        contentRun.setFontSize(12);
+        contentRun.setFontFamily("瀹嬩綋");
+
+        // 鍚堝苟绗�3-6鍒楀埌绗�2鍒�
+        for (int i = 2; i < 6; i++) {
+            XWPFTableCell cell = totalRow.getCell(i);
+            // 璁剧疆杩欎簺鍗曞厓鏍间负鍚堝苟鐘舵�侊紙缁ф壙鑷2鍒楋級
+            cell.getCTTc().addNewTcPr().addNewHMerge().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge.CONTINUE);
+        }
+
+        // 6. 鍒涘缓杩囩鍛樿锛堝崟鐙竴琛岋紝宸﹀榻愶級
+        XWPFParagraph operatorPara = document.createParagraph();
+        operatorPara.setSpacingAfter(100);
+        operatorPara.setAlignment(ParagraphAlignment.LEFT);
+        XWPFRun operatorRun = operatorPara.createRun();
+        String operator = dto.getWeighingOperator() != null ? dto.getWeighingOperator() : "";
+        operatorRun.setText("杩囩鍛橈細" + operator);
+        operatorRun.setFontSize(8);
+        operatorRun.setFontFamily("瀹嬩綋");
+
+    }
+
+    /**
+     * 鏋勫缓鏂囦欢淇濆瓨鐨勭粷瀵硅矾寰�
+     */
+    private String buildAbsoluteFilePath(StockInRecordDto dto) {
+        LocalDateTime now = LocalDateTime.now();
+        String year = String.valueOf(now.getYear());
+        String month = String.format("%02d", now.getMonthValue());
+        String day = String.format("%02d", now.getDayOfMonth());
+
+        // 鏂囦欢鍚嶆牸寮忥細纾呭崟_杞︾墝鍙穇骞存湀鏃ユ椂鍒嗙.docx
+        String fileName = String.format("纾呭崟_%s_%s.docx",
+                dto.getLicensePlateNo() != null ? dto.getLicensePlateNo() : "鏈煡杞︾墝",
+                now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
+
+        return uploadDir + File.separator + year + File.separator + month + File.separator + day + File.separator + fileName;
+    }
+
+    /**
+     * 鑾峰彇浜у搧鍨嬪彿鍚嶇О
+     */
+    private String getProductModelName(Long productModelId) {
+        if (productModelId == null) {
+            return "鏈煡浜у搧";
+        }
+        try {
+            Product product = productService.getById(productModelId);
+            return product != null ? product.getProductName() : "鏈煡浜у搧";
+        } catch (Exception e) {
+            e.printStackTrace();
+            return "鏈煡浜у搧";
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/mapper/consumables/ConsumablesInRecordMapper.xml b/src/main/resources/mapper/consumables/ConsumablesInRecordMapper.xml
new file mode 100644
index 0000000..695e611
--- /dev/null
+++ b/src/main/resources/mapper/consumables/ConsumablesInRecordMapper.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.consumables.mapper.ConsumablesInRecordMapper">
+
+    <select id="listPage" resultType="com.ruoyi.consumables.dto.ConsumablesInRecordDto">
+        SELECT
+        sir.*,
+        p.product_name as product_name,
+        pm.model,
+        pm.unit,
+        u.nick_name as createBy
+        FROM consumables_in_record as sir
+        LEFT JOIN product_model as pm on sir.product_model_id = pm.id
+        LEFT JOIN product as p on pm.product_id = p.id
+        LEFT JOIN sys_user as u on sir.create_user = u.user_id
+        <where>
+            <if test="params.timeStr != null and params.timeStr != ''">
+                and sir.create_time like concat('%',#{params.timeStr},'%')
+            </if>
+            <if test="params.productName != null and params.productName != ''">
+                and p.product_name like concat('%',#{params.productName},'%')
+            </if>
+            <if test="params.type != null and params.type != ''">
+                and sir.type = #{params.type}
+            </if>
+            <if test="params.recordType != null and params.recordType != ''">
+                and sir.record_type = #{params.recordType}
+            </if>
+        </where>
+        order by sir.id desc
+    </select>
+    <select id="listConsumablesInRecordExportData" resultType="com.ruoyi.consumables.execl.ConsumablesInRecordExportData">
+        SELECT
+        sir.*,
+        p.product_name as product_name,
+        pm.model,
+        pm.unit,
+        u.nick_name as createBy
+        FROM consumables_in_record as sir
+        LEFT JOIN product_model as pm on sir.product_model_id = pm.id
+        LEFT JOIN product as p on pm.product_id = p.id
+        LEFT JOIN sys_user as u on sir.create_user = u.user_id
+        <where>
+            <if test="params.timeStr != null and params.timeStr != ''">
+                and sir.create_time like concat('%',#{params.timeStr},'%')
+            </if>
+            <if test="params.productName != null and params.productName != ''">
+                and p.product_name like concat('%',#{params.productName},'%')
+            </if>
+            <if test="params.type != null and params.type != ''">
+                and sir.type = #{params.type}
+            </if>
+            <if test="params.recordType != null and params.recordType != ''">
+                and sir.record_type = #{params.recordType}
+            </if>
+        </where>
+        order by sir.id desc
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/consumables/ConsumablesInventoryMapper.xml b/src/main/resources/mapper/consumables/ConsumablesInventoryMapper.xml
new file mode 100644
index 0000000..2940d56
--- /dev/null
+++ b/src/main/resources/mapper/consumables/ConsumablesInventoryMapper.xml
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.consumables.mapper.ConsumablesInventoryMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.consumables.pojo.ConsumablesInventory">
+        <result column="id" property="id"/>
+        <result column="product_model_id" property="productModelId"/>
+        <result column="qualitity" property="qualitity"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="version" property="version"/>
+        <result column="locked_quantity" property="lockedQuantity"/>
+        <result column="warn_num" property="warnNum"/>
+    </resultMap>
+    <update id="updateAddConsumablesInventory">
+        update Consumables_inventory
+        <set>
+            <if test="ew.qualitity != null">
+                qualitity = qualitity + #{ew.qualitity},
+            </if>
+            <if test="ew.version != null">
+                version = version + 1,
+            </if>
+
+            <if test="ew.remark != null and ew.remark !=''">
+                remark = #{ew.remark},
+            </if>
+            <if test="ew.warnNum != null and ew.warnNum !=''">
+                warn_num = #{ew.warnNum},
+            </if>
+            <if test="ew.lockedQuantity != null and ew.lockedQuantity !=''">
+                locked_quantity = locked_quantity + #{ew.lockedQuantity},
+            </if>
+            update_time = now()
+        </set>
+        where product_model_id = #{ew.productModelId}
+    </update>
+    <update id="updateSubtractConsumablesInventory">
+        update Consumables_inventory
+        <set>
+            <if test="ew.netWeight != null">
+                qualitity = qualitity - #{ew.netWeight},
+            </if>
+            <if test="ew.version != null">
+                version = version + 1,
+            </if>
+            <if test="ew.remark != null and ew.remark !=''">
+                remark = #{ew.remark},
+            </if>
+            update_time = now()
+        </set>
+        where product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
+    </update>
+
+    <select id="pageConsumablesInventory" resultType="com.ruoyi.consumables.dto.ConsumablesInventoryDto">
+        select
+        si.id,
+        -- 褰撳墠鍑�閲� = 鍏ュ簱鍑�閲� - 鍑哄簱鍑�閲�
+        (COALESCE(sir.total_net_weight,0) - COALESCE(sor.total_net_weight,0)) as net_weight,
+        si.qualitity,
+        COALESCE(si.locked_quantity, 0) as locked_quantity,
+        si.product_model_id,
+        si.create_time,
+        si.update_time,
+        COALESCE(si.warn_num, 0) as warn_num,
+        si.version,
+        (si.qualitity - COALESCE(si.locked_quantity, 0)) as un_locked_quantity,
+        pm.model,
+        si.remark,
+        pm.unit,
+        p.product_name,
+        p1.product_name as parent_name,
+        p1.id as parent_id
+
+        from Consumables_inventory si
+        left join product_model pm on si.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        left join product p1 on p.parent_id = p1.id
+        -- 鍏ュ簱鍑�閲�
+        left join (
+        select
+        product_model_id,
+        sum(net_weight) as total_net_weight
+        from Consumables_in_record
+        group by product_model_id
+        ) sir on si.product_model_id = sir.product_model_id
+        -- 鍑哄簱鍑�閲�
+        left join (
+        select
+        product_model_id,
+        sum(net_weight) as total_net_weight
+        from Consumables_out_record
+        group by product_model_id
+        ) sor on si.product_model_id = sor.product_model_id
+
+        <where>
+            1=1
+            <if test="ew.parentId != null and ew.parentId !=''">
+                and p.parent_id = #{ew.parentId}
+            </if>
+            <if test="ew.productName != null and ew.productName !=''">
+                and p.product_name like concat('%',#{ew.productName},'%')
+            </if>
+        </where>
+    </select>
+
+    <select id="listConsumablesInventoryExportData" resultType="com.ruoyi.consumables.execl.ConsumablesInventoryExportData">
+        select si.qualitity,
+        pm.model,
+        pm.unit,
+        p.product_name,
+        coalesce(si.warn_num, 0) as warn_num,
+        coalesce(si.locked_quantity, 0) as locked_quantity,
+        si.remark,
+        si.update_time
+        from Consumables_inventory si
+        left join product_model pm on si.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        where 1 = 1
+        <if test="ew.productName != null and ew.productName !=''">
+            and p.product_name like concat('%',#{ew.productName},'%')
+        </if>
+    </select>
+
+    <select id="ConsumablesInventoryPage" resultType="com.ruoyi.consumables.dto.ConsumablesInRecordDto">
+        select
+        sir.*,
+        si.qualitity as current_Consumables,
+        pm.model,
+        pm.unit,
+        p.product_name,
+        su.nick_name as create_by,
+
+        -- 褰撳墠鍑�閲� = 鍏ュ簱鍑�閲� - 鍑哄簱鍑�閲�
+        IFNULL(inWeight.total_in_weight,0) - IFNULL(outWeight.total_out_weight,0) as current_weight
+
+        from Consumables_in_record sir
+
+        left join Consumables_inventory si
+        on sir.product_model_id = si.product_model_id
+
+        left join product_model pm
+        on sir.product_model_id = pm.id
+
+        left join product p
+        on pm.product_id = p.id
+
+        left join sys_user su
+        on sir.create_user = su.user_id
+
+        -- 鍏ュ簱鍑�閲嶇粺璁�
+        left join (
+        select
+        product_model_id,
+        sum(net_weight) as total_in_weight
+        from Consumables_in_record
+        group by product_model_id
+        ) inWeight
+        on sir.product_model_id = inWeight.product_model_id
+
+        -- 鍑哄簱鍑�閲嶇粺璁�
+        left join (
+        select
+        product_model_id,
+        sum(net_weight) as total_out_weight
+        from Consumables_out_record
+        group by product_model_id
+        ) outWeight
+        on sir.product_model_id = outWeight.product_model_id
+
+        <where>
+            <if test="ew.reportDate != null">
+                and sir.create_time >= #{ew.reportDate}
+                and sir.create_time &lt; DATE_ADD(#{ew.reportDate}, INTERVAL 1 DAY)
+            </if>
+            <if test="ew.startMonth != null">
+                and sir.create_time &gt;= #{ew.startMonth}
+            </if>
+            <if test="ew.endMonth != null">
+                and sir.create_time &lt;= #{ew.endMonth}
+            </if>
+        </where>
+    </select>
+
+    <select id="ConsumablesInAndOutRecord" resultType="com.ruoyi.consumables.dto.ConsumablesInventoryDto">
+        SELECT
+        pm.model,
+        pm.unit,
+        p.product_name,
+        MAX(current_inventory) as current_Consumables,
+        SUM(CASE WHEN record_type = 'in' THEN amount ELSE 0 END) as total_Consumables_in,
+        SUM(CASE WHEN record_type = 'out' THEN amount ELSE 0 END) as total_Consumables_out
+        FROM (
+        SELECT
+        product_model_id,
+        SUM(qualitity) as current_inventory,
+        0 as amount,
+        '' as record_type
+        FROM Consumables_inventory
+        GROUP BY product_model_id
+
+        UNION ALL
+
+        SELECT
+        product_model_id,
+        0 as current_inventory,
+        SUM(Consumables_in_num) as amount,
+        'in' as record_type
+        FROM Consumables_in_record
+        <where>
+            type = 0
+            <if test="ew.startMonth != null">
+                and Consumables_in_record.create_time &gt;= #{ew.startMonth}
+            </if>
+            <if test="ew.endMonth != null">
+                and Consumables_in_record.create_time &lt;= #{ew.endMonth}
+            </if>
+        </where>
+        GROUP BY product_model_id
+
+        UNION ALL
+
+        SELECT
+        product_model_id,
+        0 as current_inventory,
+        SUM(Consumables_out_num) as amount,
+        'out' as record_type
+        FROM Consumables_out_record
+        <where>
+            type = 0
+            <if test="ew.startMonth != null">
+                and Consumables_out_record.create_time &gt;= #{ew.startMonth}
+            </if>
+            <if test="ew.endMonth != null">
+                and Consumables_out_record.create_time &lt;= #{ew.endMonth}
+            </if>
+        </where>
+        GROUP BY product_model_id
+        ) combined_data
+        LEFT JOIN product_model pm ON pm.id = combined_data.product_model_id
+        LEFT JOIN product p ON p.id = pm.product_id
+        <where>
+            <if test="ew.productName != null and ew.productName !=''">
+                and p.product_name like concat('%',#{ew.productName},'%')
+            </if>
+            <if test="ew.model != null and ew.model !=''">
+                and pm.model like concat('%',#{ew.model},'%')
+            </if>
+        </where>
+        GROUP BY
+        pm.model,
+        pm.unit,
+        p.product_name
+    </select>
+    <select id="selectTotal" resultType="java.math.BigDecimal">
+        select ifnull(sum(qualitity), 0)
+        from consumables_inventory
+    </select>
+
+    <select id="selectTotalByDate" resultType="java.math.BigDecimal">
+        select IFNULL(sum(qualitity), 0)
+        from consumables_inventory
+        where create_time &gt;= #{now}
+          and create_time &lt; DATE_ADD(#{now}, INTERVAL 1 DAY)
+    </select>
+
+    <select id="selectStorageProductCountByDate" resultType="int">
+        SELECT SUM(total_count)
+        FROM (SELECT COUNT(*) as total_count
+              FROM consumables_inventory
+              WHERE create_time &gt;= #{startDate}
+                AND create_time &lt;= #{endDate}
+              UNION ALL
+              SELECT COUNT(*) as total_count
+              FROM consumables_uninventory
+              WHERE create_time &gt;= #{startDate}
+                AND create_time &lt;= #{endDate}) AS combined_counts
+    </select>
+
+    <select id="selectDailyConsumablesInCounts" resultType="java.util.Map">
+        SELECT DATE(sir.create_time) AS date,
+               SUM(sir.Consumables_in_num) AS count
+        FROM consumables_in_record sir
+                 JOIN product_model pm ON sir.product_model_id = pm.id
+                 JOIN product p ON pm.product_id = p.id
+        WHERE (p.parent_id = #{rootCategoryId} OR p.id = #{rootCategoryId})
+          AND sir.create_time &gt;= #{startDate}
+          AND sir.create_time &lt;= #{endDate}
+        GROUP BY DATE(sir.create_time)
+        ORDER BY DATE(sir.create_time) ASC
+    </select>
+
+    <select id="selectDailyConsumablesOutCounts" resultType="java.util.Map">
+        SELECT DATE(sor.create_time)  AS date,
+               SUM(sor.Consumables_out_num) AS count
+        FROM consumables_out_record sor
+                 JOIN product_model pm ON sor.product_model_id = pm.id
+                 JOIN product p ON pm.product_id = p.id
+        WHERE (p.parent_id = #{rootCategoryId} OR p.id = #{rootCategoryId})
+          AND sor.create_time &gt;= #{startDate}
+          AND sor.create_time &lt;= #{endDate}
+        GROUP BY DATE(sor.create_time)
+        ORDER BY DATE(sor.create_time) ASC
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/consumables/ConsumablesOutRecordMapper.xml b/src/main/resources/mapper/consumables/ConsumablesOutRecordMapper.xml
new file mode 100644
index 0000000..cb70944
--- /dev/null
+++ b/src/main/resources/mapper/consumables/ConsumablesOutRecordMapper.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.consumables.mapper.ConsumablesOutRecordMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.consumables.pojo.ConsumablesOutRecord">
+        <id column="id" property="id" />
+        <result column="outbound_batches" property="outboundBatches" />
+        <result column="Consumables_out_num" property="consumablesOutNum" />
+        <result column="record_id" property="recordId" />
+        <result column="record_type" property="recordType" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="remark" property="remark" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_user" property="updateUser" />
+        <result column="license_plate_no" property="licensePlateNo" />
+    </resultMap>
+
+    <select id="listPage" resultType="com.ruoyi.consumables.dto.ConsumablesOutRecordDto">
+        SELECT
+        sor.*,
+        p.product_name as productName,
+        pm.model,
+        pm.unit,
+        u.nick_name as createBy
+        FROM Consumables_out_record as sor
+        LEFT JOIN product_model as pm on sor.product_model_id = pm.id
+        LEFT JOIN product as p on pm.product_id = p.id
+        LEFT JOIN sys_user as u on sor.create_user = u.user_id
+        <where>
+            <if test="params.timeStr != null and params.timeStr != ''">
+                and sor.create_time like concat('%',#{params.timeStr},'%')
+            </if>
+            <if test="params.productName != null and params.productName != ''">
+                and p.product_name like concat('%',#{params.productName},'%')
+            </if>
+            <if test="params.type != null and params.type != ''">
+                and sor.type = #{params.type}
+            </if>
+            <if test="params.recordType != null and params.recordType != ''">
+                and sor.record_type = #{params.recordType}
+            </if>
+        </where>
+        order by sor.id desc
+    </select>
+    <select id="listConsumablesOutRecordExportData" resultType="com.ruoyi.consumables.execl.ConsumablesOutRecordExportData">
+        SELECT
+        sor.*,
+        p.product_name as productName,
+        pm.model,
+        pm.unit,
+        u.nick_name as createBy
+        FROM Consumables_out_record as sor
+        LEFT JOIN product_model as pm on sor.product_model_id = pm.id
+        LEFT JOIN product as p on pm.product_id = p.id
+        LEFT JOIN sys_user as u on sor.create_user = u.user_id
+        <where>
+            <if test="params.timeStr != null and params.timeStr != ''">
+                and sor.create_time like concat('%',#{params.timeStr},'%')
+            </if>
+            <if test="params.productName != null and params.productName != ''">
+                and p.product_name like concat('%',#{params.productName},'%')
+            </if>
+            <if test="params.type != null and params.type != ''">
+                and sor.type = #{params.type}
+            </if>
+            <if test="params.recordType != null and params.recordType != ''">
+                and sor.record_type = #{params.recordType}
+            </if>
+        </where>
+        order by sor.id desc
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/consumables/ConsumablesUninventoryMapper.xml b/src/main/resources/mapper/consumables/ConsumablesUninventoryMapper.xml
new file mode 100644
index 0000000..727c7da
--- /dev/null
+++ b/src/main/resources/mapper/consumables/ConsumablesUninventoryMapper.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.consumables.mapper.ConsumablesUnInventoryMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.consumables.pojo.ConsumablesUnInventory">
+        <result column="id" property="id" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="qualitity" property="qualitity" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="version" property="version" />
+    </resultMap>
+    <update id="updateSubtractConsumablesUnInventory">
+        update consumables_uninventory
+        <set>
+            <if test="ew.qualitity != null">
+                qualitity = qualitity - #{ew.qualitity},
+            </if>
+            <if test="ew.version != null">
+                version = version + 1,
+            </if>
+            <if test="ew.remark != null and ew.remark !=''">
+                remark = #{ew.remark},
+            </if>
+            update_time = now()
+        </set>
+        where product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
+    </update>
+    <update id="updateAddConsumablesUnInventory">
+        update consumables_uninventory
+        <set>
+            <if test="ew.qualitity != null">
+                qualitity = qualitity + #{ew.qualitity},
+            </if>
+            <if test="ew.version != null">
+                version = version + 1,
+            </if>
+            <if test="ew.remark != null and ew.remark !=''">
+                remark = #{ew.remark},
+            </if>
+            update_time = now()
+        </set>
+        where product_model_id = #{ew.productModelId}
+    </update>
+    <select id="pageConsumablesUninventory" resultType="com.ruoyi.consumables.dto.ConsumablesUnInventoryDto">
+        select su.id,
+        su.qualitity,
+        COALESCE(su.locked_quantity, 0) as locked_quantity,
+        su.product_model_id,
+        su.create_time,
+        su.update_time,
+        su.version,
+        su.update_time,
+        (su.qualitity - COALESCE(su.locked_quantity, 0)) as un_locked_quantity,
+        pm.model,
+        pm.unit,
+        p.product_name
+        from consumables_uninventory su
+        left join product_model pm on su.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        where 1 = 1
+        <if test="ew.productName != null and ew.productName !=''">
+            and p.product_name like concat('%',#{ew.productName},'%')
+        </if>
+    </select>
+    <select id="listConsumablesInventoryExportData" resultType="com.ruoyi.consumables.execl.ConsumablesUnInventoryExportData">
+        select su.*,
+        pm.model,
+        pm.unit,
+        p.product_name
+        from consumables_uninventory su
+        left join product_model pm on su.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        where 1 = 1
+        <if test="ew.productName != null and ew.productName !=''">
+            and p.product_name like concat('%',#{ew.productName},'%')
+        </if>
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index 7cdef56..0cde0e3c 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -39,8 +39,8 @@
     <update id="updateSubtractStockInventory">
         update stock_inventory
         <set>
-            <if test="ew.qualitity != null">
-                qualitity = qualitity - #{ew.qualitity},
+            <if test="ew.netWeight != null">
+                qualitity = qualitity - #{ew.netWeight},
             </if>
             <if test="ew.version != null">
                 version = version + 1,

--
Gitblit v1.9.3