From 46b422214d5d422be5dfa0df57560cda678058c9 Mon Sep 17 00:00:00 2001
From: chen.llin <1442464845@qq.comm>
Date: 星期三, 24 十二月 2025 08:30:38 +0800
Subject: [PATCH] 月结功能-主体

---
 src/main/java/com/zy/asrs/mapper/MonthlySettleDetailMapper.java         |   20 
 src/main/resources/mapper/MonthlySettleDetailMapper.xml                 |   62 +
 src/main/java/com/zy/asrs/entity/MonthlySettleDetail.java               |  157 ++++
 src/main/java/com/zy/asrs/entity/param/DateRangeParam.java              |   29 
 src/main/webapp/static/js/monthlySettle/monthlySettle.js                |  630 +++++++++++++++++
 src/main/java/com/zy/asrs/entity/result/MonthlySettleResultVO.java      |   44 +
 src/main/java/com/zy/asrs/service/impl/MonthlySettleServiceImpl.java    |  385 ++++++++++
 src/main/webapp/views/monthlySettle/monthlySettle.html                  |  122 +++
 src/main/java/com/zy/asrs/mapper/MonthlySettleMapper.java               |   64 +
 src/main/java/com/zy/asrs/service/MonthlySettleService.java             |   54 +
 src/main/java/com/zy/asrs/controller/MonthlySettleController.java       |  135 +++
 src/main/java/com/zy/asrs/entity/result/MaterialInOutStatDTO.java       |   43 +
 src/main/java/com/zy/asrs/entity/result/PreviousSettleEndingQtyDTO.java |   33 
 src/main/resources/mapper/MonthlySettleMapper.xml                       |  159 ++++
 src/main/java/com/zy/asrs/entity/result/MonthlySettleStatisticsVO.java  |   28 
 src/main/java/com/zy/asrs/entity/MonthlySettle.java                     |  188 +++++
 src/main/java/com/zy/asrs/entity/param/MonthlySettleQueryParam.java     |   48 +
 17 files changed, 2,201 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/zy/asrs/controller/MonthlySettleController.java b/src/main/java/com/zy/asrs/controller/MonthlySettleController.java
new file mode 100644
index 0000000..a3c847a
--- /dev/null
+++ b/src/main/java/com/zy/asrs/controller/MonthlySettleController.java
@@ -0,0 +1,135 @@
+package com.zy.asrs.controller;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.core.annotations.ManagerAuth;
+import com.core.common.R;
+import com.zy.asrs.entity.MonthlySettle;
+import com.zy.asrs.entity.param.DateRangeParam;
+import com.zy.asrs.entity.param.MonthlySettleQueryParam;
+import com.zy.asrs.service.MonthlySettleService;
+import com.zy.common.web.BaseController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@RestController
+public class MonthlySettleController extends BaseController {
+
+    @Autowired
+    private MonthlySettleService monthlySettleService;
+
+    /**
+     * 鑾峰彇鏈堢粨淇℃伅
+     */
+    @RequestMapping(value = "/monthlySettle/{id}/auth")
+    @ManagerAuth
+    public R get(@PathVariable("id") Long id) {
+        return R.ok(monthlySettleService.selectById(id));
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨ鏈堢粨鍒楄〃
+     */
+    @RequestMapping(value = "/monthlySettle/list/auth")
+    @ManagerAuth
+    public R list(MonthlySettleQueryParam param) {
+        Page<MonthlySettle> page = new Page<>(param.getCurr(), param.getLimit());
+        java.util.Map<String, Object> condition = new java.util.HashMap<>();
+        if (param.getSettleNo() != null && !param.getSettleNo().trim().isEmpty()) {
+            condition.put("settleNo", param.getSettleNo());
+        }
+        if (param.getStatus() != null) {
+            condition.put("status", param.getStatus());
+        }
+        if (param.getStartDate() != null && !param.getStartDate().trim().isEmpty() 
+                && param.getEndDate() != null && !param.getEndDate().trim().isEmpty()) {
+            condition.put("startDate", param.getStartDate());
+            condition.put("endDate", param.getEndDate());
+        }
+        page.setCondition(condition);
+        return R.ok(monthlySettleService.getPage(page));
+    }
+
+    /**
+     * 鑾峰彇鏈�杩戠殑鏈堢粨璁板綍
+     */
+    @RequestMapping(value = "/monthlySettle/latest/auth")
+    @ManagerAuth
+    public R getLatest() {
+        MonthlySettle latest = monthlySettleService.getLatestSettle();
+        return R.ok(latest);
+    }
+
+    /**
+     * 鑾峰彇涓嬩竴涓湀缁撶殑璧峰鏃ユ湡
+     */
+    @RequestMapping(value = "/monthlySettle/nextStartDate/auth")
+    @ManagerAuth
+    public R getNextStartDate() {
+        Date nextStartDate = monthlySettleService.getNextStartDate();
+        if (nextStartDate != null) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+            return R.ok(sdf.format(nextStartDate));
+        }
+        return R.ok(null);
+    }
+
+    /**
+     * 鑾峰彇鏈�鏅氭湀缁撹褰曠殑缁撴潫鏃ユ湡
+     */
+    @RequestMapping(value = "/monthlySettle/latestEndDate/auth")
+    @ManagerAuth
+    public R getLatestEndDate() {
+        Date latestEndDate = monthlySettleService.getLatestEndDate();
+        if (latestEndDate != null) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+            return R.ok(sdf.format(latestEndDate));
+        }
+        return R.ok(null);
+    }
+
+    /**
+     * 妫�鏌ユ湀缁撴椂闂磋寖鍥村唴鏄惁鏈夋湭瀹屾垚鐨勮鍗�
+     */
+    @RequestMapping(value = "/monthlySettle/checkUnfinished/auth")
+    @ManagerAuth
+    public R checkUnfinished(DateRangeParam param) {
+        boolean hasUnfinished = monthlySettleService.hasUnfinishedOrders(param.getStartDate(), param.getEndDate());
+        if (hasUnfinished) {
+            return R.error("鏈堢粨鏃堕棿鑼冨洿鍐呭瓨鍦ㄦ湭瀹屾垚鐨勮鍗曪紝鏃犳硶杩涜鏈堢粨");
+        }
+        return R.ok();
+    }
+
+    /**
+     * 鍙戣捣鏈堢粨
+     */
+    @RequestMapping(value = "/monthlySettle/start/auth")
+    @ManagerAuth
+    public R startSettle(DateRangeParam param) {
+        return R.ok(monthlySettleService.startSettle(param.getStartDate(), param.getEndDate(), getUserId()));
+    }
+
+    /**
+     * 鑾峰彇鏈堢粨缁熻淇℃伅
+     */
+    @RequestMapping(value = "/monthlySettle/statistics/{id}/auth")
+    @ManagerAuth
+    public R getStatistics(@PathVariable("id") Long id) {
+        return R.ok(monthlySettleService.getSettleStatistics(id));
+    }
+
+    /**
+     * 鍒犻櫎鏈堢粨璁板綍
+     */
+    @RequestMapping(value = "/monthlySettle/{id}/auth", method = RequestMethod.DELETE)
+    @ManagerAuth
+    public R delete(@PathVariable("id") Long id) {
+        monthlySettleService.deleteSettle(id);
+        return R.ok("鍒犻櫎鎴愬姛");
+    }
+
+}
+
diff --git a/src/main/java/com/zy/asrs/entity/MonthlySettle.java b/src/main/java/com/zy/asrs/entity/MonthlySettle.java
new file mode 100644
index 0000000..73df7e9
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/MonthlySettle.java
@@ -0,0 +1,188 @@
+package com.zy.asrs.entity;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.baomidou.mybatisplus.enums.IdType;
+import com.core.common.Cools;
+import com.core.common.SpringUtils;
+import com.zy.system.entity.User;
+import com.zy.system.service.UserService;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Data
+@TableName("man_monthly_settle")
+public class MonthlySettle implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ApiModelProperty(value = "ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鏈堢粨缂栧彿
+     */
+    @ApiModelProperty(value = "鏈堢粨缂栧彿")
+    @TableField("settle_no")
+    private String settleNo;
+
+    /**
+     * 璧峰鏃ユ湡
+     */
+    @ApiModelProperty(value = "璧峰鏃ユ湡")
+    @TableField("start_date")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date startDate;
+
+    /**
+     * 缁撴潫鏃ユ湡
+     */
+    @ApiModelProperty(value = "缁撴潫鏃ユ湡")
+    @TableField("end_date")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date endDate;
+
+    /**
+     * 鐘舵�� 0:寰呮湀缁� 1:宸叉湀缁�
+     */
+    @ApiModelProperty(value = "鐘舵�� 0:寰呮湀缁� 1:宸叉湀缁�")
+    private Integer status;
+
+    /**
+     * 鎬诲叆搴撴暟閲�
+     */
+    @ApiModelProperty(value = "鎬诲叆搴撴暟閲�")
+    @TableField("total_in_qty")
+    private BigDecimal totalInQty;
+
+    /**
+     * 鎬诲嚭搴撴暟閲�
+     */
+    @ApiModelProperty(value = "鎬诲嚭搴撴暟閲�")
+    @TableField("total_out_qty")
+    private BigDecimal totalOutQty;
+
+    /**
+     * 鐗╂枡绉嶇被鏁�
+     */
+    @ApiModelProperty(value = "鐗╂枡绉嶇被鏁�")
+    @TableField("total_materials")
+    private Integer totalMaterials;
+
+    /**
+     * 澶囨敞
+     */
+    @ApiModelProperty(value = "澶囨敞")
+    private String memo;
+
+    /**
+     * 鍒涘缓浜哄憳
+     */
+    @ApiModelProperty(value = "鍒涘缓浜哄憳")
+    @TableField("create_by")
+    private Long createBy;
+
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @TableField("create_time")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 淇敼浜哄憳
+     */
+    @ApiModelProperty(value = "淇敼浜哄憳")
+    @TableField("update_by")
+    private Long updateBy;
+
+    /**
+     * 淇敼鏃堕棿
+     */
+    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @TableField("update_time")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /**
+     * 鍒犻櫎鏍囪 0:鏈垹闄� 1:宸插垹闄�
+     */
+    @ApiModelProperty(value = "鍒犻櫎鏍囪 0:鏈垹闄� 1:宸插垹闄�")
+    @TableField("is_deleted")
+    private Integer isDeleted;
+
+    public String getStatus$() {
+        if (null == this.status) {
+            return null;
+        }
+        switch (this.status) {
+            case 0:
+                return "寰呮湀缁�";
+            case 1:
+                return "宸叉湀缁�";
+            default:
+                return String.valueOf(this.status);
+        }
+    }
+
+
+    public String getStartDate$() {
+        if (Cools.isEmpty(this.startDate)) {
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd").format(this.startDate);
+    }
+
+    public String getEndDate$() {
+        if (Cools.isEmpty(this.endDate)) {
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd").format(this.endDate);
+    }
+
+    public String getCreateBy$() {
+        UserService service = SpringUtils.getBean(UserService.class);
+        User user = service.selectById(this.createBy);
+        if (!Cools.isEmpty(user)) {
+            return String.valueOf(user.getUsername());
+        }
+        return null;
+    }
+
+    public String getCreateTime$() {
+        if (Cools.isEmpty(this.createTime)) {
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
+    }
+
+    public String getUpdateBy$() {
+        UserService service = SpringUtils.getBean(UserService.class);
+        User user = service.selectById(this.updateBy);
+        if (!Cools.isEmpty(user)) {
+            return String.valueOf(user.getUsername());
+        }
+        return null;
+    }
+
+    public String getUpdateTime$() {
+        if (Cools.isEmpty(this.updateTime)) {
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
+    }
+}
+
+
diff --git a/src/main/java/com/zy/asrs/entity/MonthlySettleDetail.java b/src/main/java/com/zy/asrs/entity/MonthlySettleDetail.java
new file mode 100644
index 0000000..01db1d5
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/MonthlySettleDetail.java
@@ -0,0 +1,157 @@
+package com.zy.asrs.entity;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.baomidou.mybatisplus.enums.IdType;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@TableName("man_monthly_settle_detail")
+public class MonthlySettleDetail implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ApiModelProperty(value = "ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鏈堢粨涓昏〃ID
+     */
+    @ApiModelProperty(value = "鏈堢粨涓昏〃ID")
+    @TableField("settle_id")
+    private Long settleId;
+
+    /**
+     * 鏈堢粨缂栧彿
+     */
+    @ApiModelProperty(value = "鏈堢粨缂栧彿")
+    @TableField("settle_no")
+    private String settleNo;
+
+    // ========== 鍩烘湰淇℃伅 ==========
+    /**
+     * 鐗╂枡缂栫爜
+     */
+    @ApiModelProperty(value = "鐗╂枡缂栫爜")
+    private String matnr;
+
+    /**
+     * 鎵规锛堣鍗曟槑缁嗘壒娆★級
+     */
+    @ApiModelProperty(value = "鎵规")
+    private String batch;
+
+    /**
+     * 鐗╂枡鍚嶇О锛堟湀缁撴椂浠庤鍗曟槑缁嗚〃鑾峰彇锛�
+     */
+    @ApiModelProperty(value = "鐗╂枡鍚嶇О")
+    private String maktx;
+
+    /**
+     * 鍝佺墝锛堟湀缁撴椂浠庤鍗曟槑缁嗚〃鑾峰彇锛�
+     */
+    @ApiModelProperty(value = "鍝佺墝")
+    private String brand;
+
+    // ========== 鏁伴噺淇℃伅 ==========
+    /**
+     * 鏈熷垵搴撳瓨锛堜笂鏈熺粨浣欙級
+     */
+    @ApiModelProperty(value = "鏈熷垵搴撳瓨锛堜笂鏈熺粨浣欙級")
+    @TableField("beginning_qty")
+    private BigDecimal beginningQty;
+
+    /**
+     * 鏈湡鍏ュ簱鏁伴噺
+     */
+    @ApiModelProperty(value = "鏈湡鍏ュ簱鏁伴噺")
+    @TableField("in_qty")
+    private BigDecimal inQty;
+
+    /**
+     * 鏈湡鍑哄簱鏁伴噺
+     */
+    @ApiModelProperty(value = "鏈湡鍑哄簱鏁伴噺")
+    @TableField("out_qty")
+    private BigDecimal outQty;
+
+    /**
+     * 鏈熸湯搴撳瓨锛堟湡鍒�+鍏ュ簱-鍑哄簱锛�
+     */
+    @ApiModelProperty(value = "鏈熸湯搴撳瓨锛堟湡鍒�+鍏ュ簱-鍑哄簱锛�")
+    @TableField("ending_qty")
+    private BigDecimal endingQty;
+
+    /**
+     * 褰撳墠瀹為檯搴撳瓨鏁伴噺
+     */
+    @ApiModelProperty(value = "褰撳墠瀹為檯搴撳瓨鏁伴噺")
+    @TableField("stock_qty")
+    private BigDecimal stockQty;
+
+    /**
+     * 宸紓鏁伴噺锛堝疄闄呭簱瀛�-鏈熸湯搴撳瓨锛�
+     */
+    @ApiModelProperty(value = "宸紓鏁伴噺锛堝疄闄呭簱瀛�-鏈熸湯搴撳瓨锛�")
+    @TableField("diff_qty")
+    private BigDecimal diffQty;
+
+    // ========== 鍏宠仈瀛楁锛堥�氳繃鍏宠仈鏌ヨ鑾峰彇锛屼笉瀛樺偍鍦ㄦ槑缁嗚〃涓級==========
+
+    /**
+     * 瑙勬牸锛堜紭鍏堜粠鍑哄叆搴撹鍗曟槑缁嗚〃鑾峰彇锛屽鏋滀负绌哄垯浠庣墿鏂欒〃鑾峰彇锛�
+     */
+    @ApiModelProperty(value = "瑙勬牸")
+    @TableField(exist = false)
+    private String specs;
+
+    /**
+     * 鍨嬪彿锛堜紭鍏堜粠鍑哄叆搴撹鍗曟槑缁嗚〃鑾峰彇锛屽鏋滀负绌哄垯浠庣墿鏂欒〃鑾峰彇锛�
+     */
+    @ApiModelProperty(value = "鍨嬪彿")
+    @TableField(exist = false)
+    private String model;
+
+    /**
+     * 棰滆壊锛堜紭鍏堜粠鍑哄叆搴撹鍗曟槑缁嗚〃鑾峰彇锛屽鏋滀负绌哄垯浠庣墿鏂欒〃鑾峰彇锛�
+     */
+    @ApiModelProperty(value = "棰滆壊")
+    @TableField(exist = false)
+    private String color;
+
+    /**
+     * 鍗曚綅锛堜粠鐗╂枡琛ㄨ幏鍙栵級
+     */
+    @ApiModelProperty(value = "鍗曚綅")
+    @TableField(exist = false)
+    private String unit;
+
+    // ========== 鏃堕棿淇℃伅 ==========
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @TableField("create_time")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 鍒犻櫎鏍囪 0:鏈垹闄� 1:宸插垹闄�
+     */
+    @ApiModelProperty(value = "鍒犻櫎鏍囪 0:鏈垹闄� 1:宸插垹闄�")
+    @TableField("is_deleted")
+    private Integer isDeleted;
+}
+
+
diff --git a/src/main/java/com/zy/asrs/entity/param/DateRangeParam.java b/src/main/java/com/zy/asrs/entity/param/DateRangeParam.java
new file mode 100644
index 0000000..cb59c60
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/param/DateRangeParam.java
@@ -0,0 +1,29 @@
+package com.zy.asrs.entity.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * 鏃ユ湡鑼冨洿鍙傛暟
+ */
+@Data
+public class DateRangeParam {
+    
+    /**
+     * 璧峰鏃ユ湡
+     */
+    @ApiModelProperty(value = "璧峰鏃ユ湡", required = true)
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date startDate;
+    
+    /**
+     * 缁撴潫鏃ユ湡锛堝彲浠ユ帴鍙� yyyy-MM-dd 鎴� yyyy-MM-dd HH:mm:ss 鏍煎紡锛�
+     */
+    @ApiModelProperty(value = "缁撴潫鏃ユ湡", required = true)
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date endDate;
+}
+
diff --git a/src/main/java/com/zy/asrs/entity/param/MonthlySettleQueryParam.java b/src/main/java/com/zy/asrs/entity/param/MonthlySettleQueryParam.java
new file mode 100644
index 0000000..e6b0a20
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/param/MonthlySettleQueryParam.java
@@ -0,0 +1,48 @@
+package com.zy.asrs.entity.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 鏈堢粨鏌ヨ鍙傛暟
+ */
+@Data
+public class MonthlySettleQueryParam {
+    
+    /**
+     * 褰撳墠椤�
+     */
+    @ApiModelProperty(value = "褰撳墠椤�")
+    private Integer curr = 1;
+    
+    /**
+     * 姣忛〉鏁伴噺
+     */
+    @ApiModelProperty(value = "姣忛〉鏁伴噺")
+    private Integer limit = 10;
+    
+    /**
+     * 鏈堢粨缂栧彿
+     */
+    @ApiModelProperty(value = "鏈堢粨缂栧彿")
+    private String settleNo;
+    
+    /**
+     * 鐘舵��
+     */
+    @ApiModelProperty(value = "鐘舵��")
+    private Integer status;
+    
+    /**
+     * 璧峰鏃ユ湡
+     */
+    @ApiModelProperty(value = "璧峰鏃ユ湡")
+    private String startDate;
+    
+    /**
+     * 缁撴潫鏃ユ湡
+     */
+    @ApiModelProperty(value = "缁撴潫鏃ユ湡")
+    private String endDate;
+}
+
diff --git a/src/main/java/com/zy/asrs/entity/result/MaterialInOutStatDTO.java b/src/main/java/com/zy/asrs/entity/result/MaterialInOutStatDTO.java
new file mode 100644
index 0000000..ddb57a0
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/result/MaterialInOutStatDTO.java
@@ -0,0 +1,43 @@
+package com.zy.asrs.entity.result;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鐗╂枡鍑哄叆搴撶粺璁�
+ */
+@Data
+public class MaterialInOutStatDTO {
+    
+    /**
+     * 鐗╂枡缂栫爜
+     */
+    private String matnr;
+    
+    /**
+     * 鐗╂枡鍚嶇О
+     */
+    private String maktx;
+    
+    /**
+     * 鎵规
+     */
+    private String batch;
+    
+    /**
+     * 鍝佺墝
+     */
+    private String brand;
+    
+    /**
+     * 鍏ュ簱鏁伴噺
+     */
+    private BigDecimal inQty;
+    
+    /**
+     * 鍑哄簱鏁伴噺
+     */
+    private BigDecimal outQty;
+}
+
diff --git a/src/main/java/com/zy/asrs/entity/result/MonthlySettleResultVO.java b/src/main/java/com/zy/asrs/entity/result/MonthlySettleResultVO.java
new file mode 100644
index 0000000..77ec981
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/result/MonthlySettleResultVO.java
@@ -0,0 +1,44 @@
+package com.zy.asrs.entity.result;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鏈堢粨缁撴灉
+ */
+@Data
+public class MonthlySettleResultVO {
+    
+    /**
+     * 鏈堢粨ID
+     */
+    @ApiModelProperty(value = "鏈堢粨ID")
+    private Long settleId;
+    
+    /**
+     * 鏈堢粨缂栧彿
+     */
+    @ApiModelProperty(value = "鏈堢粨缂栧彿")
+    private String settleNo;
+    
+    /**
+     * 鎬诲叆搴撴暟閲�
+     */
+    @ApiModelProperty(value = "鎬诲叆搴撴暟閲�")
+    private BigDecimal totalInQty;
+    
+    /**
+     * 鎬诲嚭搴撴暟閲�
+     */
+    @ApiModelProperty(value = "鎬诲嚭搴撴暟閲�")
+    private BigDecimal totalOutQty;
+    
+    /**
+     * 鐗╂枡绉嶇被鏁�
+     */
+    @ApiModelProperty(value = "鐗╂枡绉嶇被鏁�")
+    private Integer totalMaterials;
+}
+
diff --git a/src/main/java/com/zy/asrs/entity/result/MonthlySettleStatisticsVO.java b/src/main/java/com/zy/asrs/entity/result/MonthlySettleStatisticsVO.java
new file mode 100644
index 0000000..c4b7a6a
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/result/MonthlySettleStatisticsVO.java
@@ -0,0 +1,28 @@
+package com.zy.asrs.entity.result;
+
+import com.zy.asrs.entity.MonthlySettle;
+import com.zy.asrs.entity.MonthlySettleDetail;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 鏈堢粨缁熻淇℃伅
+ */
+@Data
+public class MonthlySettleStatisticsVO {
+    
+    /**
+     * 鏈堢粨涓昏褰�
+     */
+    @ApiModelProperty(value = "鏈堢粨涓昏褰�")
+    private MonthlySettle settle;
+    
+    /**
+     * 鏈堢粨鏄庣粏鍒楄〃
+     */
+    @ApiModelProperty(value = "鏈堢粨鏄庣粏鍒楄〃")
+    private List<MonthlySettleDetail> details;
+}
+
diff --git a/src/main/java/com/zy/asrs/entity/result/PreviousSettleEndingQtyDTO.java b/src/main/java/com/zy/asrs/entity/result/PreviousSettleEndingQtyDTO.java
new file mode 100644
index 0000000..5b9a727
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/result/PreviousSettleEndingQtyDTO.java
@@ -0,0 +1,33 @@
+package com.zy.asrs.entity.result;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 涓婃湡鏈堢粨鏈熸湯搴撳瓨
+ */
+@Data
+public class PreviousSettleEndingQtyDTO {
+    
+    /**
+     * 鐗╂枡缂栫爜
+     */
+    private String matnr;
+    
+    /**
+     * 鎵规
+     */
+    private String batch;
+    
+    /**
+     * 鍝佺墝
+     */
+    private String brand;
+    
+    /**
+     * 鏈熸湯搴撳瓨
+     */
+    private BigDecimal endingQty;
+}
+
diff --git a/src/main/java/com/zy/asrs/mapper/MonthlySettleDetailMapper.java b/src/main/java/com/zy/asrs/mapper/MonthlySettleDetailMapper.java
new file mode 100644
index 0000000..9af3484
--- /dev/null
+++ b/src/main/java/com/zy/asrs/mapper/MonthlySettleDetailMapper.java
@@ -0,0 +1,20 @@
+package com.zy.asrs.mapper;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.zy.asrs.entity.MonthlySettleDetail;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Mapper
+@Repository
+public interface MonthlySettleDetailMapper extends BaseMapper<MonthlySettleDetail> {
+    
+    /**
+     * 鏌ヨ鏈堢粨鏄庣粏锛堝叧鑱旂墿鏂欒〃锛�
+     */
+    List<MonthlySettleDetail> selectDetailWithMat(@Param("settleId") Long settleId);
+}
+
diff --git a/src/main/java/com/zy/asrs/mapper/MonthlySettleMapper.java b/src/main/java/com/zy/asrs/mapper/MonthlySettleMapper.java
new file mode 100644
index 0000000..1710a27
--- /dev/null
+++ b/src/main/java/com/zy/asrs/mapper/MonthlySettleMapper.java
@@ -0,0 +1,64 @@
+package com.zy.asrs.mapper;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.zy.asrs.entity.MonthlySettle;
+import com.zy.asrs.entity.result.MaterialInOutStatDTO;
+import com.zy.asrs.entity.result.PreviousSettleEndingQtyDTO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Mapper
+@Repository
+public interface MonthlySettleMapper extends BaseMapper<MonthlySettle> {
+
+    /**
+     * 鑾峰彇鏈�杩戠殑鏈堢粨璁板綍
+     */
+    MonthlySettle selectLatestSettle();
+
+    /**
+     * 缁熻鏈堢粨鏃堕棿鑼冨洿鍐呯殑璁㈠崟鏁伴噺
+     */
+    int countOrdersInRange(@Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    /**
+     * 缁熻鏈堢粨鏃堕棿鑼冨洿鍐呮湭瀹屾垚鐨勮鍗曟暟閲忥紙鍏ュ簱鍜屽嚭搴擄級
+     */
+    int countUnfinishedOrdersInRange(@Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    /**
+     * 缁熻鏈堢粨鏃堕棿鑼冨洿鍐呯殑鐗╂枡鍑哄叆搴撴暟閲忥紙鍚堝苟鍏ュ簱鍜屽嚭搴擄級
+     */
+    List<MaterialInOutStatDTO> statisticsMaterialInOut(@Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    /**
+     * 鑾峰彇涓婁竴涓湀缁撶殑鐗╂枡鏈熸湯搴撳瓨
+     */
+    List<PreviousSettleEndingQtyDTO> getPreviousSettleEndingQty(@Param("previousSettleId") Long previousSettleId);
+
+    /**
+     * 鏇存柊鍏ュ簱璁㈠崟鐨勬湀缁撲俊鎭�
+     */
+    int updateOrderSettleInfo(@Param("settleId") Long settleId, @Param("settleNo") String settleNo, 
+                              @Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    /**
+     * 鏇存柊鍑哄簱璁㈠崟鐨勬湀缁撲俊鎭�
+     */
+    int updateOrderSettleInfoPakout(@Param("settleId") Long settleId, @Param("settleNo") String settleNo, 
+                                    @Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    /**
+     * 娓呴櫎鍏ュ簱璁㈠崟鐨勬湀缁撲俊鎭�
+     */
+    int clearOrderSettleInfo(@Param("settleId") Long settleId);
+
+    /**
+     * 娓呴櫎鍑哄簱璁㈠崟鐨勬湀缁撲俊鎭�
+     */
+    int clearOrderSettleInfoPakout(@Param("settleId") Long settleId);
+}
+
diff --git a/src/main/java/com/zy/asrs/service/MonthlySettleService.java b/src/main/java/com/zy/asrs/service/MonthlySettleService.java
new file mode 100644
index 0000000..599215d
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/MonthlySettleService.java
@@ -0,0 +1,54 @@
+package com.zy.asrs.service;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.service.IService;
+import com.zy.asrs.entity.MonthlySettle;
+import com.zy.asrs.entity.result.MonthlySettleResultVO;
+import com.zy.asrs.entity.result.MonthlySettleStatisticsVO;
+
+import java.util.Date;
+
+public interface MonthlySettleService extends IService<MonthlySettle> {
+
+    /**
+     * 鑾峰彇鏈�杩戠殑鏈堢粨璁板綍
+     */
+    MonthlySettle getLatestSettle();
+
+    /**
+     * 鑾峰彇涓嬩竴涓湀缁撶殑璧峰鏃ユ湡
+     */
+    Date getNextStartDate();
+
+    /**
+     * 鑾峰彇鏈�鏅氭湀缁撹褰曠殑缁撴潫鏃ユ湡
+     */
+    Date getLatestEndDate();
+
+    /**
+     * 妫�鏌ユ湀缁撴椂闂磋寖鍥村唴鏄惁鏈夋湭瀹屾垚鐨勮鍗�
+     */
+    boolean hasUnfinishedOrders(Date startDate, Date endDate);
+
+    /**
+     * 鍙戣捣鏈堢粨
+     */
+    MonthlySettleResultVO startSettle(Date startDate, Date endDate, Long userId);
+
+    /**
+     * 鑾峰彇鏈堢粨缁熻淇℃伅
+     */
+    MonthlySettleStatisticsVO getSettleStatistics(Long settleId);
+
+    /**
+     * 鍒嗛〉鏌ヨ鏈堢粨鍒楄〃
+     */
+    Page<MonthlySettle> getPage(Page<MonthlySettle> page);
+
+    /**
+     * 鍒犻櫎鏈堢粨璁板綍
+     */
+    void deleteSettle(Long settleId);
+}
+
+
diff --git a/src/main/java/com/zy/asrs/service/impl/MonthlySettleServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/MonthlySettleServiceImpl.java
new file mode 100644
index 0000000..4dd63c1
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/impl/MonthlySettleServiceImpl.java
@@ -0,0 +1,385 @@
+package com.zy.asrs.service.impl;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.core.common.SnowflakeIdWorker;
+import com.core.exception.CoolException;
+import com.zy.asrs.entity.MonthlySettle;
+import com.zy.asrs.entity.MonthlySettleDetail;
+import com.zy.asrs.entity.result.MaterialInOutStatDTO;
+import com.zy.asrs.entity.result.MonthlySettleResultVO;
+import com.zy.asrs.entity.result.MonthlySettleStatisticsVO;
+import com.zy.asrs.entity.result.PreviousSettleEndingQtyDTO;
+import com.zy.asrs.mapper.MonthlySettleDetailMapper;
+import com.zy.asrs.mapper.MonthlySettleMapper;
+import com.zy.asrs.service.ManLocDetlService;
+import com.zy.asrs.service.MonthlySettleService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Service("monthlySettleService")
+public class MonthlySettleServiceImpl extends ServiceImpl<MonthlySettleMapper, MonthlySettle> implements MonthlySettleService {
+
+    @Autowired
+    private MonthlySettleDetailMapper monthlySettleDetailMapper;
+    @Autowired
+    private ManLocDetlService manLocDetlService;
+    @Autowired
+    private SnowflakeIdWorker snowflakeIdWorker;
+
+    @Override
+    public MonthlySettle getLatestSettle() {
+        return this.baseMapper.selectLatestSettle();
+    }
+
+    @Override
+    public Date getNextStartDate() {
+        MonthlySettle latestSettle = getLatestSettle();
+        if (latestSettle == null) {
+            // 濡傛灉娌℃湁鏈堢粨璁板綍锛岃繑鍥瀗ull锛岀敱鍓嶇閫夋嫨璧峰鏃ユ湡
+            return null;
+        }
+        // 杩斿洖鏈�鏅氭湀缁撹褰曠粨鏉熸棩鏈熺殑涓嬩竴澶╋紙璧峰鏃ユ湡搴旇鏄粨鏉熸棩鏈�+1澶╃殑00:00:00锛�
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(latestSettle.getEndDate());
+        // 鍏堣缃负褰撳ぉ鐨�00:00:00锛岀劧鍚庡姞1澶╋紝纭繚杩斿洖鐨勬槸涓嬩竴澶╃殑00:00:00
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        cal.add(Calendar.DAY_OF_MONTH, 1);
+        return cal.getTime();
+    }
+
+    @Override
+    public Date getLatestEndDate() {
+        MonthlySettle latestSettle = getLatestSettle();
+        if (latestSettle == null) {
+            return null;
+        }
+        // 杩斿洖鏈�鏅氭湀缁撹褰曠殑缁撴潫鏃ユ湡锛堟牸寮忓寲涓哄綋澶╃殑00:00:00锛岀敤浜庢樉绀猴級
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(latestSettle.getEndDate());
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    @Override
+    public boolean hasUnfinishedOrders(Date startDate, Date endDate) {
+        // 缁撴潫鏃ユ湡+23:59:59
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(endDate);
+        cal.set(Calendar.HOUR_OF_DAY, 23);
+        cal.set(Calendar.MINUTE, 59);
+        cal.set(Calendar.SECOND, 59);
+        cal.set(Calendar.MILLISECOND, 999);
+        endDate = cal.getTime();
+        
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String startDateStr = dateFormat.format(startDate);
+        String endDateStr = dateTimeFormat.format(endDate);
+        int count = this.baseMapper.countUnfinishedOrdersInRange(startDateStr, endDateStr);
+        return count > 0;
+    }
+
+    @Override
+    @Transactional
+    public MonthlySettleResultVO startSettle(Date startDate, Date endDate, Long userId) {
+        // 缁撴潫鏃ユ湡+23:59:59
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(endDate);
+        cal.set(Calendar.HOUR_OF_DAY, 23);
+        cal.set(Calendar.MINUTE, 59);
+        cal.set(Calendar.SECOND, 59);
+        cal.set(Calendar.MILLISECOND, 999);
+        endDate = cal.getTime();
+        
+        // 妫�鏌ヨ捣濮嬫棩鏈熷繀椤诲ぇ浜庢渶鏅氭湀缁撹褰曠殑缁撴潫鏃ユ湡
+        MonthlySettle latestSettle = getLatestSettle();
+        if (latestSettle != null) {
+            Calendar startCal = Calendar.getInstance();
+            startCal.setTime(startDate);
+            startCal.set(Calendar.HOUR_OF_DAY, 0);
+            startCal.set(Calendar.MINUTE, 0);
+            startCal.set(Calendar.SECOND, 0);
+            startCal.set(Calendar.MILLISECOND, 0);
+            
+            Calendar latestEndCal = Calendar.getInstance();
+            latestEndCal.setTime(latestSettle.getEndDate());
+            latestEndCal.set(Calendar.HOUR_OF_DAY, 0);
+            latestEndCal.set(Calendar.MINUTE, 0);
+            latestEndCal.set(Calendar.SECOND, 0);
+            latestEndCal.set(Calendar.MILLISECOND, 0);
+            
+            // 璧峰鏃ユ湡蹇呴』澶т簬鏈�鏅氱粨鏉熸棩鏈燂紝涓嶈兘绛変簬鎴栧皬浜�
+            if (!startCal.getTime().after(latestEndCal.getTime())) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                throw new CoolException("璧峰鏃ユ湡蹇呴』澶т簬鏈�鏅氭湀缁撹褰曠殑缁撴潫鏃ユ湡锛�" + sdf.format(latestSettle.getEndDate()));
+            }
+        }
+        
+        // 妫�鏌ユ槸鍚︽湁鏈畬鎴愮殑璁㈠崟
+        if (hasUnfinishedOrders(startDate, endDate)) {
+            throw new CoolException("鏈堢粨鏃堕棿鑼冨洿鍐呭瓨鍦ㄦ湭瀹屾垚鐨勮鍗曪紝鏃犳硶杩涜鏈堢粨");
+        }
+
+        // 缁熻鐗╂枡鍑哄叆搴撴暟閲忥紙鍚堝苟鍏ュ簱鍜屽嚭搴擄級
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String startDateStr = dateFormat.format(startDate);
+        String endDateStr = dateTimeFormat.format(endDate);
+        List<MaterialInOutStatDTO> materialStats = this.baseMapper.statisticsMaterialInOut(startDateStr, endDateStr);
+        
+        // 妫�鏌ユ槸鍚︽湁鍑哄叆搴撳巻鍙茶鍗�
+        if (materialStats == null || materialStats.isEmpty()) {
+            throw new CoolException("鏈堢粨鏃堕棿鑼冨洿鍐呮病鏈夊嚭鍏ュ簱鍘嗗彶璁㈠崟锛屾棤娉曡繘琛屾湀缁�");
+        }
+
+        // 鑾峰彇涓婁竴涓湀缁撹褰曪紙鐢ㄤ簬璁$畻鏈熷垵搴撳瓨锛�
+        MonthlySettle previousSettle = getLatestSettle();
+        Map<String, BigDecimal> previousEndingQtyMap = new HashMap<>();
+        if (previousSettle != null) {
+            List<PreviousSettleEndingQtyDTO> previousDetails = this.baseMapper.getPreviousSettleEndingQty(previousSettle.getId());
+            for (PreviousSettleEndingQtyDTO detail : previousDetails) {
+                String key = detail.getMatnr() + "_" + 
+                            (detail.getBatch() != null ? detail.getBatch() : "") + "_" + 
+                            (detail.getBrand() != null ? detail.getBrand() : "");
+                BigDecimal endingQty = detail.getEndingQty() != null ? detail.getEndingQty() : BigDecimal.ZERO;
+                previousEndingQtyMap.put(key, endingQty);
+            }
+        }
+
+        // 鐢熸垚鏈堢粨缂栧彿
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+        String settleNo = "MS" + sdf.format(new Date()) + String.format("%04d", snowflakeIdWorker.nextId() % 10000);
+
+        // 鍒涘缓鏈堢粨涓昏褰�
+        MonthlySettle monthlySettle = new MonthlySettle();
+        monthlySettle.setSettleNo(settleNo);
+        monthlySettle.setStartDate(startDate);
+        monthlySettle.setEndDate(endDate);
+        monthlySettle.setStatus(1); // 宸叉湀缁�
+        monthlySettle.setIsDeleted(0); // 鏈垹闄�
+        monthlySettle.setCreateBy(userId);
+        monthlySettle.setCreateTime(new Date());
+        this.insert(monthlySettle);
+
+        BigDecimal totalInQty = BigDecimal.ZERO;
+        BigDecimal totalOutQty = BigDecimal.ZERO;
+        int materialCount = 0;
+
+        // 鍒涘缓鏈堢粨鏄庣粏
+        for (MaterialInOutStatDTO stat : materialStats) {
+            // 1. 鎻愬彇鍩虹淇℃伅
+            String matnr = stat.getMatnr();
+            String batch = stat.getBatch() != null ? stat.getBatch() : "";
+            String brand = stat.getBrand() != null ? stat.getBrand() : "";
+            String maktx = stat.getMaktx();
+            
+            // 2. 鎻愬彇鏁伴噺淇℃伅
+            BigDecimal inQty = stat.getInQty() != null ? stat.getInQty() : BigDecimal.ZERO;
+            BigDecimal outQty = stat.getOutQty() != null ? stat.getOutQty() : BigDecimal.ZERO;
+            
+            // 3. 璁$畻搴撳瓨鐩稿叧鏁伴噺
+            BigDecimal beginningQty = getBeginningQty(matnr, batch, brand, previousEndingQtyMap);
+            BigDecimal endingQty = calculateEndingQty(beginningQty, inQty, outQty);
+            BigDecimal stockQtyDecimal = getCurrentStockQty(matnr, batch);
+            BigDecimal diffQty = calculateDiffQty(stockQtyDecimal, endingQty);
+            
+            // 4. 鍒涘缓骞朵繚瀛樻槑缁嗚褰�
+            MonthlySettleDetail detail = buildMonthlySettleDetail(
+                monthlySettle.getId(), settleNo, matnr, batch, maktx, brand,
+                beginningQty, inQty, outQty, endingQty, stockQtyDecimal, diffQty
+            );
+            detail.setIsDeleted(0); // 鏈垹闄�
+            monthlySettleDetailMapper.insert(detail);
+
+            // 5. 绱缁熻
+            totalInQty = totalInQty.add(inQty);
+            totalOutQty = totalOutQty.add(outQty);
+            materialCount++;
+        }
+
+        // 鏇存柊鏈堢粨涓昏褰�
+        monthlySettle.setTotalInQty(totalInQty);
+        monthlySettle.setTotalOutQty(totalOutQty);
+        monthlySettle.setTotalMaterials(materialCount);
+        monthlySettle.setStatus(1); // 宸叉湀缁�
+        monthlySettle.setUpdateBy(userId);
+        monthlySettle.setUpdateTime(new Date());
+        this.updateById(monthlySettle);
+
+        // 鏇存柊璁㈠崟鐨勬湀缁撲俊鎭紙鍏ュ簱鍜屽嚭搴撻兘瑕佹洿鏂帮級
+        this.baseMapper.updateOrderSettleInfo(monthlySettle.getId(), settleNo, startDateStr, endDateStr);
+        this.baseMapper.updateOrderSettleInfoPakout(monthlySettle.getId(), settleNo, startDateStr, endDateStr);
+
+        MonthlySettleResultVO result = new MonthlySettleResultVO();
+        result.setSettleId(monthlySettle.getId());
+        result.setSettleNo(settleNo);
+        result.setTotalInQty(totalInQty);
+        result.setTotalOutQty(totalOutQty);
+        result.setTotalMaterials(materialCount);
+        return result;
+    }
+
+    @Override
+    public MonthlySettleStatisticsVO getSettleStatistics(Long settleId) {
+        MonthlySettle settle = this.selectById(settleId);
+        if (settle == null || (settle.getIsDeleted() != null && settle.getIsDeleted() == 1)) {
+            throw new CoolException("鏈堢粨璁板綍涓嶅瓨鍦�");
+        }
+
+        // 鍏宠仈鐗╂枡琛ㄦ煡璇㈡槑缁�
+        List<MonthlySettleDetail> details = monthlySettleDetailMapper.selectDetailWithMat(settleId);
+
+        MonthlySettleStatisticsVO result = new MonthlySettleStatisticsVO();
+        result.setSettle(settle);
+        result.setDetails(details);
+        return result;
+    }
+
+    @Override
+    public Page<MonthlySettle> getPage(Page<MonthlySettle> page) {
+        Map<String, Object> condition = page.getCondition();
+        EntityWrapper<MonthlySettle> wrapper = new EntityWrapper<>();
+        wrapper.eq("is_deleted", 0);
+        
+        if (condition != null) {
+            if (condition.get("settleNo") != null) {
+                wrapper.like("settle_no", condition.get("settleNo").toString());
+            }
+            if (condition.get("status") != null) {
+                wrapper.eq("status", condition.get("status"));
+            }
+            if (condition.get("startDate") != null && condition.get("endDate") != null) {
+                wrapper.ge("start_date", condition.get("startDate"));
+                wrapper.le("end_date", condition.get("endDate"));
+            }
+        }
+        
+        wrapper.orderBy("create_time", false);
+        List<MonthlySettle> list = this.selectList(wrapper);
+        
+        EntityWrapper<MonthlySettle> countWrapper = new EntityWrapper<>();
+        countWrapper.eq("is_deleted", 0);
+        if (condition != null) {
+            if (condition.get("settleNo") != null) {
+                countWrapper.like("settle_no", condition.get("settleNo").toString());
+            }
+            if (condition.get("status") != null) {
+                countWrapper.eq("status", condition.get("status"));
+            }
+            if (condition.get("startDate") != null && condition.get("endDate") != null) {
+                countWrapper.ge("start_date", condition.get("startDate"));
+                countWrapper.le("end_date", condition.get("endDate"));
+            }
+        }
+        page.setRecords(list);
+        page.setTotal(this.selectCount(countWrapper));
+        return page;
+    }
+
+    /**
+     * 鑾峰彇鏈熷垵搴撳瓨锛堜笂鏈熺粨浣欙級
+     */
+    private BigDecimal getBeginningQty(String matnr, String batch, String brand, Map<String, BigDecimal> previousEndingQtyMap) {
+        String key = matnr + "_" + batch + "_" + brand;
+        return previousEndingQtyMap.getOrDefault(key, BigDecimal.ZERO);
+    }
+
+    /**
+     * 璁$畻鏈熸湯搴撳瓨锛堟湡鍒�+鍏ュ簱-鍑哄簱锛�
+     */
+    private BigDecimal calculateEndingQty(BigDecimal beginningQty, BigDecimal inQty, BigDecimal outQty) {
+        return beginningQty.add(inQty).subtract(outQty);
+    }
+
+    /**
+     * 鑾峰彇褰撳墠瀹為檯搴撳瓨鏁伴噺
+     */
+    private BigDecimal getCurrentStockQty(String matnr, String batch) {
+        Double stockQty = manLocDetlService.queryStockAnfme(matnr, batch);
+        return stockQty != null ? BigDecimal.valueOf(stockQty) : BigDecimal.ZERO;
+    }
+
+    /**
+     * 璁$畻宸紓鏁伴噺锛堝疄闄呭簱瀛�-鏈熸湯搴撳瓨锛�
+     */
+    private BigDecimal calculateDiffQty(BigDecimal stockQty, BigDecimal endingQty) {
+        return stockQty.subtract(endingQty);
+    }
+
+    /**
+     * 鏋勫缓鏈堢粨鏄庣粏瀵硅薄
+     */
+    private MonthlySettleDetail buildMonthlySettleDetail(
+            Long settleId, String settleNo, String matnr, String batch, String maktx, String brand,
+            BigDecimal beginningQty, BigDecimal inQty, BigDecimal outQty, BigDecimal endingQty,
+            BigDecimal stockQty, BigDecimal diffQty) {
+        MonthlySettleDetail detail = new MonthlySettleDetail();
+        // 鍩烘湰淇℃伅
+        detail.setSettleId(settleId);
+        detail.setSettleNo(settleNo);
+        detail.setMatnr(matnr);
+        detail.setBatch(batch);
+        detail.setMaktx(maktx);
+        detail.setBrand(brand);
+        // 鏁伴噺淇℃伅
+        detail.setBeginningQty(beginningQty);
+        detail.setInQty(inQty);
+        detail.setOutQty(outQty);
+        detail.setEndingQty(endingQty);
+        detail.setStockQty(stockQty);
+        detail.setDiffQty(diffQty);
+        // 鏃堕棿淇℃伅
+        detail.setCreateTime(new Date());
+        return detail;
+    }
+
+    @Override
+    @Transactional
+    public void deleteSettle(Long settleId) {
+        MonthlySettle settle = this.selectById(settleId);
+        if (settle == null || (settle.getIsDeleted() != null && settle.getIsDeleted() == 1)) {
+            throw new CoolException("鏈堢粨璁板綍涓嶅瓨鍦�");
+        }
+
+        // 娓呴櫎鍑哄叆搴撹鍗曠殑鏈堢粨淇℃伅
+        this.baseMapper.clearOrderSettleInfo(settleId);
+        this.baseMapper.clearOrderSettleInfoPakout(settleId);
+
+        // 閫昏緫鍒犻櫎鏈堢粨鏄庣粏
+        EntityWrapper<MonthlySettleDetail> detailWrapper = new EntityWrapper<>();
+        detailWrapper.eq("settle_id", settleId);
+        detailWrapper.eq("is_deleted", 0);
+        List<MonthlySettleDetail> details = monthlySettleDetailMapper.selectList(detailWrapper);
+        if (details != null && !details.isEmpty()) {
+            for (MonthlySettleDetail detail : details) {
+                detail.setIsDeleted(1);
+                monthlySettleDetailMapper.updateById(detail);
+            }
+        }
+
+        // 閫昏緫鍒犻櫎鏈堢粨涓昏褰�
+        settle.setIsDeleted(1);
+        settle.setUpdateTime(new Date());
+        this.updateById(settle);
+    }
+}
+
diff --git a/src/main/resources/mapper/MonthlySettleDetailMapper.xml b/src/main/resources/mapper/MonthlySettleDetailMapper.xml
new file mode 100644
index 0000000..21cb23a
--- /dev/null
+++ b/src/main/resources/mapper/MonthlySettleDetailMapper.xml
@@ -0,0 +1,62 @@
+<?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.zy.asrs.mapper.MonthlySettleDetailMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.MonthlySettleDetail">
+        <id column="id" property="id" />
+        <result column="settle_id" property="settleId" />
+        <result column="settle_no" property="settleNo" />
+        <result column="matnr" property="matnr" />
+        <result column="batch" property="batch" />
+        <result column="maktx" property="maktx" />
+        <result column="brand" property="brand" />
+        <result column="beginning_qty" property="beginningQty" />
+        <result column="in_qty" property="inQty" />
+        <result column="out_qty" property="outQty" />
+        <result column="ending_qty" property="endingQty" />
+        <result column="stock_qty" property="stockQty" />
+        <result column="diff_qty" property="diffQty" />
+        <result column="create_time" property="createTime" />
+        <result column="is_deleted" property="isDeleted" />
+    </resultMap>
+
+    <!-- 鍏宠仈鐗╂枡琛ㄧ殑鏌ヨ鏄犲皠缁撴灉锛堣幏鍙栧叾浠栫墿鏂欎俊鎭級 -->
+    <resultMap id="DetailWithMatResultMap" type="com.zy.asrs.entity.MonthlySettleDetail" extends="BaseResultMap">
+        <result column="specs" property="specs" />
+        <result column="model" property="model" />
+        <result column="color" property="color" />
+        <result column="unit" property="unit" />
+    </resultMap>
+
+    <!-- 鏌ヨ鏈堢粨鏄庣粏锛堜粠鏄庣粏琛ㄦ煡璇紝鍏宠仈鐗╂枡琛ㄨ幏鍙栬ˉ鍏呬俊鎭級 -->
+    <select id="selectDetailWithMat" resultMap="DetailWithMatResultMap">
+        SELECT 
+            d.id,
+            d.settle_id,
+            d.settle_no,
+            d.matnr,
+            d.batch,
+            d.maktx,
+            d.brand,
+            d.beginning_qty,
+            d.in_qty,
+            d.out_qty,
+            d.ending_qty,
+            d.stock_qty,
+            d.diff_qty,
+            d.create_time,
+            m.specs,
+            m.model,
+            m.color,
+            m.unit
+        FROM man_monthly_settle_detail d
+        LEFT JOIN man_mat m ON d.matnr = m.matnr
+        WHERE d.settle_id = #{settleId}
+        AND d.is_deleted = 0
+        ORDER BY d.matnr, d.batch
+    </select>
+
+</mapper>
+
+
diff --git a/src/main/resources/mapper/MonthlySettleMapper.xml b/src/main/resources/mapper/MonthlySettleMapper.xml
new file mode 100644
index 0000000..78cc204
--- /dev/null
+++ b/src/main/resources/mapper/MonthlySettleMapper.xml
@@ -0,0 +1,159 @@
+<?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.zy.asrs.mapper.MonthlySettleMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.MonthlySettle">
+        <id column="id" property="id" />
+    <result column="settle_no" property="settleNo" />
+    <result column="start_date" property="startDate" />
+        <result column="end_date" property="endDate" />
+        <result column="status" property="status" />
+        <result column="total_in_qty" property="totalInQty" />
+        <result column="total_out_qty" property="totalOutQty" />
+        <result column="total_materials" property="totalMaterials" />
+        <result column="memo" property="memo" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="is_deleted" property="isDeleted" />
+    </resultMap>
+
+    <!-- 鑾峰彇鏈�杩戠殑鏈堢粨璁板綍 -->
+    <select id="selectLatestSettle" resultMap="BaseResultMap">
+        SELECT TOP 1 * FROM man_monthly_settle
+        WHERE is_deleted = 0
+        ORDER BY end_date DESC
+    </select>
+
+    <!-- 缁熻鏈堢粨鏃堕棿鑼冨洿鍐呯殑璁㈠崟鏁伴噺 -->
+    <select id="countOrdersInRange" resultType="int">
+        SELECT COUNT(*) FROM man_order
+        WHERE status = 1
+        AND order_time >= #{startDate}
+        AND order_time &lt;= #{endDate}
+    </select>
+
+    <!-- 缁熻鏈堢粨鏃堕棿鑼冨洿鍐呮湭瀹屾垚鐨勮鍗曟暟閲忥紙鍏ュ簱鍜屽嚭搴擄級 -->
+    <select id="countUnfinishedOrdersInRange" resultType="int">
+        SELECT COUNT(*) FROM (
+            SELECT DISTINCT o.id FROM man_order_log_pakin o
+            INNER JOIN man_order_detl_log_pakin od ON o.id = od.order_id
+            WHERE o.status = 1
+            AND CONVERT(date, o.order_time) >= #{startDate}
+            AND o.order_time &lt;= #{endDate}
+            AND o.move_status != 2
+            AND (od.anfme > od.qty OR od.qty IS NULL)
+            AND (o.monthly_settle_id IS NULL OR o.monthly_settle_id = 0)
+            UNION
+            SELECT DISTINCT o.id FROM man_order_log_pakout o
+            INNER JOIN man_order_detl_log_pakout od ON o.id = od.order_id
+            WHERE o.status = 1
+            AND CONVERT(date, o.order_time) >= #{startDate}
+            AND o.order_time &lt;= #{endDate}
+            AND o.move_status != 2
+            AND (od.anfme > od.qty OR od.qty IS NULL)
+            AND (o.monthly_settle_id IS NULL OR o.monthly_settle_id = 0)
+        ) t
+    </select>
+
+    <!-- 缁熻鏈堢粨鏃堕棿鑼冨洿鍐呯殑鐗╂枡鍑哄叆搴撴暟閲忥紙鍚堝苟鍏ュ簱鍑哄簱锛� -->
+    <select id="statisticsMaterialInOut" resultType="com.zy.asrs.entity.result.MaterialInOutStatDTO">
+        SELECT 
+            matnr,
+            MAX(maktx) as maktx,
+            batch,
+            brand,
+            SUM(in_qty) as inQty,
+            SUM(out_qty) as outQty
+        FROM (
+            SELECT 
+                od.matnr,
+                MAX(od.maktx) as maktx,
+                ISNULL(od.batch, '') as batch,
+                ISNULL(od.brand, '') as brand,
+                SUM(od.qty) as in_qty,
+                0 as out_qty
+            FROM man_order_log_pakin o
+            INNER JOIN man_order_detl_log_pakin od ON o.id = od.order_id
+            WHERE o.status = 1
+            AND CONVERT(date, o.order_time) >= #{startDate}
+            AND o.order_time &lt;= #{endDate}
+            AND o.move_status = 2
+            AND (o.monthly_settle_id IS NULL OR o.monthly_settle_id = 0)
+            GROUP BY od.matnr, od.batch, od.brand
+            UNION ALL
+            SELECT 
+                od.matnr,
+                MAX(od.maktx) as maktx,
+                ISNULL(od.batch, '') as batch,
+                ISNULL(od.brand, '') as brand,
+                0 as in_qty,
+                SUM(od.qty) as out_qty
+            FROM man_order_log_pakout o
+            INNER JOIN man_order_detl_log_pakout od ON o.id = od.order_id
+            WHERE o.status = 1
+            AND CONVERT(date, o.order_time) >= #{startDate}
+            AND o.order_time &lt;= #{endDate}
+            AND o.move_status = 2
+            AND (o.monthly_settle_id IS NULL OR o.monthly_settle_id = 0)
+            GROUP BY od.matnr, od.batch, od.brand
+        ) t
+        GROUP BY matnr, batch, brand
+    </select>
+
+    <!-- 鑾峰彇涓婁竴涓湀缁撶殑鐗╂枡鏈熸湯搴撳瓨 -->
+    <select id="getPreviousSettleEndingQty" resultType="com.zy.asrs.entity.result.PreviousSettleEndingQtyDTO">
+        SELECT 
+            matnr,
+            batch,
+            brand,
+            ending_qty as endingQty
+        FROM man_monthly_settle_detail
+        WHERE settle_id = #{previousSettleId}
+    </select>
+
+    <!-- 鏇存柊鍏ュ簱璁㈠崟鐨勬湀缁撲俊鎭� -->
+    <update id="updateOrderSettleInfo">
+        UPDATE man_order_log_pakin
+        SET monthly_settle_id = #{settleId},
+            monthly_settle_no = #{settleNo}
+        WHERE status = 1
+        AND CONVERT(date, order_time) >= #{startDate}
+        AND order_time &lt;= #{endDate}
+        AND move_status = 2
+        AND (monthly_settle_id IS NULL OR monthly_settle_id = 0)
+    </update>
+
+    <!-- 鏇存柊鍑哄簱璁㈠崟鐨勬湀缁撲俊鎭� -->
+    <update id="updateOrderSettleInfoPakout">
+        UPDATE man_order_log_pakout
+        SET monthly_settle_id = #{settleId},
+            monthly_settle_no = #{settleNo}
+        WHERE status = 1
+        AND CONVERT(date, order_time) >= #{startDate}
+        AND order_time &lt;= #{endDate}
+        AND move_status = 2
+        AND (monthly_settle_id IS NULL OR monthly_settle_id = 0)
+    </update>
+
+    <!-- 娓呴櫎鍏ュ簱璁㈠崟鐨勬湀缁撲俊鎭� -->
+    <update id="clearOrderSettleInfo">
+        UPDATE man_order_log_pakin
+        SET monthly_settle_id = NULL,
+            monthly_settle_no = NULL
+        WHERE monthly_settle_id = #{settleId}
+    </update>
+
+    <!-- 娓呴櫎鍑哄簱璁㈠崟鐨勬湀缁撲俊鎭� -->
+    <update id="clearOrderSettleInfoPakout">
+        UPDATE man_order_log_pakout
+        SET monthly_settle_id = NULL,
+            monthly_settle_no = NULL
+        WHERE monthly_settle_id = #{settleId}
+    </update>
+
+</mapper>
+
+
diff --git a/src/main/webapp/static/js/monthlySettle/monthlySettle.js b/src/main/webapp/static/js/monthlySettle/monthlySettle.js
new file mode 100644
index 0000000..dc9df4f
--- /dev/null
+++ b/src/main/webapp/static/js/monthlySettle/monthlySettle.js
@@ -0,0 +1,630 @@
+var pageCurr;
+layui.config({
+    base: baseUrl + "/static/layui/lay/modules/"
+}).use(['layer', 'form', 'table', 'util', 'admin', 'laydate', 'laytpl'], function () {
+    var $ = layui.jquery;
+    var layer = layui.layer;
+    var form = layui.form;
+    var table = layui.table;
+    var util = layui.util;
+    var admin = layui.admin;
+    var layDate = layui.laydate;
+    var laytpl = layui.laytpl;
+
+    // 娓叉煋琛ㄦ牸
+    tableIns = table.render({
+        elem: '#monthlySettle',
+        url: baseUrl + '/monthlySettle/list/auth',
+        headers: {token: localStorage.getItem('token')},
+        method: 'POST',
+        page: true,
+        cellMinWidth: 100,
+        where: {},
+        cols: [[
+            {type: 'numbers'},
+            {field: 'settleNo', title: '鏈堢粨缂栧彿', width: 180},
+            {field: 'startDate$', align: 'center', title: '璧峰鏃ユ湡', width: 120},
+            {field: 'endDate$', align: 'center', title: '缁撴潫鏃ユ湡', width: 120},
+            {field: 'totalInQty', align: 'center', title: '鎬诲叆搴撴暟閲�', width: 120},
+            {field: 'totalOutQty', align: 'center', title: '鎬诲嚭搴撴暟閲�', width: 120},
+            {field: 'totalMaterials', align: 'center', title: '鐗╂枡绉嶇被鏁�', width: 120},
+            {field: 'createTime$', title: '鍒涘缓鏃堕棿', minWidth: 180, width: 180},
+            {align: 'center', title: '鎿嶄綔', toolbar: '#operate', width: 180}
+        ]],
+        request: {
+            pageName: 'curr',
+            pageSize: 'limit'
+        },
+        parseData: function (res) {
+            return {
+                'code': res.code,
+                'msg': res.msg,
+                'count': res.data.total,
+                'data': res.data.records
+            }
+        },
+        response: {
+            statusCode: 200
+        },
+        done: function (res, curr, count) {
+            if (res.code === 403) {
+                top.location.href = baseUrl + "/";
+            }
+            pageCurr = curr;
+        }
+    });
+
+    // 鎼滅储
+    form.on('submit(search)', function (data) {
+        pageCurr = 1;
+        tableReload(false);
+    });
+
+    // 閲嶇疆
+    form.on('submit(reset)', function (data) {
+        pageCurr = 1;
+        clearFormVal($('#search-box'));
+        // 鎵嬪姩娓呯┖鏃ユ湡鑼冨洿閫夋嫨鍣�
+        $('input[name="date_range"]').val('');
+        // 鏄惧紡娓呯┖琛ㄦ牸閰嶇疆涓殑 where 鍙傛暟
+        if (tableIns && tableIns.config) {
+            tableIns.config.where = {};
+        }
+        // 浣跨敤 setTimeout 纭繚琛ㄥ崟鍊艰瀹屽叏娓呯┖鍚庡啀閲嶆柊鍔犺浇琛ㄦ牸
+        setTimeout(function() {
+            tableReload(false);
+        }, 0);
+    });
+
+    // 鏃ユ湡鑼冨洿閫夋嫨鍣�
+    layDate.render({
+        elem: '.layui-laydate-range',
+        type: 'date',
+        range: true
+    });
+
+    // 鍙戣捣鏈堢粨
+    $('#startSettleBtn').click(function () {
+        showStartSettleDialog();
+    });
+
+    // 鏄剧ず鍙戣捣鏈堢粨寮圭獥
+    function showStartSettleDialog() {
+        admin.open({
+            type: 1,
+            title: '鍙戣捣鏈堢粨',
+            content: $('#startSettleDialog').html(),
+            area: '500px',
+            success: function (layero, dIndex) {
+                var startDateIns = null;
+                var endDateIns = null;
+                
+                // 鍒濆鍖栫粨鏉熸棩鏈熼�夋嫨鍣紙鍏堝垵濮嬪寲锛屽悗缁啀璁剧疆min锛�
+                // 浣跨敤 setTimeout 纭繚 DOM 宸插畬鍏ㄦ覆鏌�
+                setTimeout(function() {
+                    var $endDate = layero.find('#endDate');
+                    if ($endDate.length > 0) {
+                        endDateIns = layDate.render({
+                            elem: $endDate[0],
+                            type: 'date',
+                            done: function(value, date, endDate){
+                                var startDate = layero.find('#startDate').val();
+                                if (startDate && value < startDate) {
+                                    layer.msg('缁撴潫鏃ユ湡涓嶈兘鏃╀簬璧峰鏃ユ湡', {icon: 2});
+                                    layero.find('#endDate').val('');
+                                    checkUnfinishedOrders(startDate, '');
+                                    return;
+                                }
+                                checkUnfinishedOrders(startDate, value);
+                            }
+                        });
+                    }
+                }, 50);
+                
+                // 鑾峰彇涓嬩竴涓湀缁撶殑璧峰鏃ユ湡锛堟渶鏅氭湀缁撹褰曠粨鏉熸棩鏈熺殑涓嬩竴澶╋級
+                $.ajax({
+                    url: baseUrl + '/monthlySettle/nextStartDate/auth',
+                    headers: {'token': localStorage.getItem('token')},
+                    method: 'POST',
+                    success: function (res) {
+                        if (res.code === 200) {
+                            // 鏁版嵁鍦� msg 瀛楁涓�
+                            var nextStartDate = res.msg;
+                            // 纭繚 nextStartDate 鏄瓧绗︿覆鏍煎紡
+                            if (nextStartDate != null && nextStartDate !== '') {
+                                // 杞崲涓哄瓧绗︿覆锛屽鐞嗗彲鑳界殑鏁板瓧鎴栧叾浠栫被鍨�
+                                nextStartDate = String(nextStartDate).trim();
+                                if (nextStartDate !== '' && nextStartDate !== 'null') {
+                                    // 浣跨敤 setTimeout 纭繚 DOM 宸插畬鍏ㄦ覆鏌�
+                                    setTimeout(function() {
+                                        // 浣跨敤 layero.find 鏌ユ壘寮圭獥鍐呯殑鍏冪礌
+                                        var $startDate = layero.find('#startDate');
+                                        if ($startDate.length > 0) {
+                                            $startDate.val(nextStartDate);
+                                            $startDate.attr('readonly', true);
+                                            $startDate.css('background-color', '#f5f5f5');
+                                            $startDate.css('cursor', 'not-allowed');
+                                            console.log('宸茶缃捣濮嬫棩鏈�:', $startDate.val());
+                                        } else {
+                                            console.error('鏈壘鍒� #startDate 鍏冪礌');
+                                        }
+                                    }, 50);
+                                
+                                    // 鑾峰彇鏈�鏅氱粨鏉熸棩鏈熺敤浜庢彁绀�
+                                    $.ajax({
+                                        url: baseUrl + '/monthlySettle/latestEndDate/auth',
+                                        headers: {'token': localStorage.getItem('token')},
+                                        method: 'POST',
+                                        success: function (latestRes) {
+                                            var latestEndDate = (latestRes.code === 200 && latestRes.msg) ? String(latestRes.msg) : '';
+                                            var tipMsg = latestEndDate 
+                                                ? '鎻愮ず锛氭渶鏅氭湀缁撹褰曠粨鏉熸棩鏈熶负 ' + latestEndDate + '锛屾湰娆℃湀缁撹捣濮嬫棩鏈熷凡鑷姩璁剧疆涓� ' + nextStartDate + '锛屼笉鍙慨鏀�'
+                                                : '鎻愮ず锛氭湰娆℃湀缁撹捣濮嬫棩鏈熷凡鑷姩璁剧疆涓� ' + nextStartDate + '锛屼笉鍙慨鏀�';
+                                            layero.find('#settleTip').html(tipMsg);
+                                        },
+                                        error: function() {
+                                            layero.find('#settleTip').html('鎻愮ず锛氭湰娆℃湀缁撹捣濮嬫棩鏈熷凡鑷姩璁剧疆涓� ' + nextStartDate + '锛屼笉鍙慨鏀�');
+                                        }
+                                    });
+                                    
+                                    // 閲嶆柊娓叉煋缁撴潫鏃ユ湡閫夋嫨鍣紝璁剧疆鏈�灏忔棩鏈熶负璧峰鏃ユ湡
+                                    setTimeout(function() {
+                                        endDateIns = layDate.render({
+                                            elem: layero.find('#endDate')[0],
+                                            type: 'date',
+                                            min: nextStartDate,
+                                            done: function(value, date, endDate){
+                                                var startDate = layero.find('#startDate').val();
+                                                if (startDate && value < startDate) {
+                                                    layer.msg('缁撴潫鏃ユ湡涓嶈兘鏃╀簬璧峰鏃ユ湡', {icon: 2});
+                                                    layero.find('#endDate').val('');
+                                                    checkUnfinishedOrders(startDate, '');
+                                                    return;
+                                                }
+                                                checkUnfinishedOrders(startDate, value);
+                                            }
+                                        });
+                                    }, 100);
+                                }
+                            } else {
+                                // 娌℃湁鏈堢粨璁板綍锛屽厑璁歌嚜鐢遍�夋嫨璧峰鏃ユ湡
+                                setTimeout(function() {
+                                    var $startDate = layero.find('#startDate');
+                                    if ($startDate.length > 0) {
+                                        startDateIns = layDate.render({
+                                            elem: $startDate[0],
+                                            type: 'date',
+                                            done: function(value, date, endDate){
+                                                // 褰撹捣濮嬫棩鏈熸敼鍙樻椂锛岄噸鏂版覆鏌撶粨鏉熸棩鏈熼�夋嫨鍣紝璁剧疆鏈�灏忔棩鏈�
+                                                var currentEndDate = layero.find('#endDate').val();
+                                                if (currentEndDate && currentEndDate < value) {
+                                                    layero.find('#endDate').val('');
+                                                    layero.find('#settleTip').html('<span style="color: #ff5722;">璀﹀憡锛氱粨鏉熸棩鏈熶笉鑳芥棭浜庤捣濮嬫棩鏈燂紝璇烽噸鏂伴�夋嫨缁撴潫鏃ユ湡</span>');
+                                                }
+                                                
+                                                // 閲嶆柊娓叉煋缁撴潫鏃ユ湡閫夋嫨鍣�
+                                                endDateIns = layDate.render({
+                                                    elem: layero.find('#endDate')[0],
+                                                    type: 'date',
+                                                    min: value,
+                                                    done: function(endValue, endDate, endEndDate){
+                                                        if (value && endValue < value) {
+                                                            layer.msg('缁撴潫鏃ユ湡涓嶈兘鏃╀簬璧峰鏃ユ湡', {icon: 2});
+                                                            layero.find('#endDate').val('');
+                                                            checkUnfinishedOrders(value, '');
+                                                            return;
+                                                        }
+                                                        checkUnfinishedOrders(value, endValue);
+                                                    }
+                                                });
+                                                
+                                                checkUnfinishedOrders(value, layero.find('#endDate').val());
+                                            }
+                                        });
+                                        layero.find('#settleTip').html('鎻愮ず锛氶娆℃湀缁擄紝璇烽�夋嫨璧峰鏃ユ湡');
+                                    }
+                                }, 50);
+                            }
+                        } else if (res.code === 403) {
+                            top.location.href = baseUrl + "/";
+                        }
+                    },
+                    error: function() {
+                        // 濡傛灉鑾峰彇澶辫触锛屽厑璁歌嚜鐢遍�夋嫨璧峰鏃ユ湡
+                        setTimeout(function() {
+                            var $startDate = layero.find('#startDate');
+                            if ($startDate.length > 0) {
+                                startDateIns = layDate.render({
+                                    elem: $startDate[0],
+                                    type: 'date',
+                                    done: function(value, date, endDate){
+                                        var currentEndDate = layero.find('#endDate').val();
+                                        if (currentEndDate && currentEndDate < value) {
+                                            layero.find('#endDate').val('');
+                                            layero.find('#settleTip').html('<span style="color: #ff5722;">璀﹀憡锛氱粨鏉熸棩鏈熶笉鑳芥棭浜庤捣濮嬫棩鏈燂紝璇烽噸鏂伴�夋嫨缁撴潫鏃ユ湡</span>');
+                                        }
+                                        
+                                        endDateIns = layDate.render({
+                                            elem: layero.find('#endDate')[0],
+                                            type: 'date',
+                                            min: value,
+                                            done: function(endValue, endDate, endEndDate){
+                                                if (value && endValue < value) {
+                                                    layer.msg('缁撴潫鏃ユ湡涓嶈兘鏃╀簬璧峰鏃ユ湡', {icon: 2});
+                                                    layero.find('#endDate').val('');
+                                                    checkUnfinishedOrders(value, '');
+                                                    return;
+                                                }
+                                                checkUnfinishedOrders(value, endValue);
+                                            }
+                                        });
+                                        
+                                        checkUnfinishedOrders(value, layero.find('#endDate').val());
+                                    }
+                                });
+                                layero.find('#settleTip').html('鎻愮ず锛氳閫夋嫨璧峰鏃ユ湡');
+                            }
+                        }, 50);
+                    }
+                });
+
+                // 琛ㄥ崟鎻愪氦浜嬩欢
+                form.on('submit(startSettleSubmit)', function (data) {
+                    var startDate = layero.find('#startDate').val();
+                    var endDate = layero.find('#endDate').val();
+                    
+                    if (!startDate || !endDate) {
+                        layer.msg('璇烽�夋嫨璧峰鏃ユ湡鍜岀粨鏉熸棩鏈�', {icon: 2});
+                        return false;
+                    }
+                    
+                    if (startDate > endDate) {
+                        layer.msg('缁撴潫鏃ユ湡涓嶈兘鏃╀簬璧峰鏃ユ湡锛岃閲嶆柊閫夋嫨', {icon: 2});
+                        return false;
+                    }
+
+                    // 灏嗙粨鏉熸棩鏈熻缃负褰撳ぉ鐨� 23:59:59
+                    var endDateTime = endDate + ' 23:59:59';
+
+                    layer.load(2);
+                    $.ajax({
+                        url: baseUrl + '/monthlySettle/start/auth',
+                        headers: {'token': localStorage.getItem('token')},
+                        data: {
+                            startDate: startDate,
+                            endDate: endDateTime
+                        },
+                        method: 'POST',
+                        success: function (res) {
+                            layer.closeAll('loading');
+                            if (res.code === 200) {
+                                layer.close(dIndex);
+                                tableIns.reload({page: {curr: 1}});
+                                layer.msg(res.msg || '鏈堢粨鎴愬姛', {icon: 1});
+                            } else if (res.code === 403) {
+                                top.location.href = baseUrl + "/";
+                            } else {
+                                layer.msg(res.msg || '鏈堢粨澶辫触', {icon: 2});
+                            }
+                        },
+                        error: function() {
+                            layer.closeAll('loading');
+                            layer.msg('鏈堢粨璇锋眰澶辫触', {icon: 2});
+                        }
+                    });
+                    return false;
+                });
+            }
+        });
+    }
+
+    // 妫�鏌ユ湭瀹屾垚鐨勮鍗�
+    function checkUnfinishedOrders(startDate, endDate) {
+        if (!startDate && !endDate) {
+            $('#settleTip').html('<span style="color: #999;">璇烽�夋嫨璧峰鏃ユ湡鍜岀粨鏉熸棩鏈�</span>');
+            return;
+        }
+        
+        if (!startDate) {
+            $('#settleTip').html('<span style="color: #999;">璇烽�夋嫨璧峰鏃ユ湡</span>');
+            return;
+        }
+        
+        if (!endDate) {
+            $('#settleTip').html('<span style="color: #999;">璇烽�夋嫨缁撴潫鏃ユ湡</span>');
+            return;
+        }
+        
+        // 楠岃瘉鏃ユ湡鑼冨洿
+        if (startDate > endDate) {
+            $('#settleTip').html('<span style="color: #ff5722;">璀﹀憡锛氱粨鏉熸棩鏈熶笉鑳芥棭浜庤捣濮嬫棩鏈燂紝璇烽噸鏂伴�夋嫨</span>');
+            return;
+        }
+        
+        $.ajax({
+            url: baseUrl + '/monthlySettle/checkUnfinished/auth',
+            headers: {'token': localStorage.getItem('token')},
+            data: {
+                startDate: startDate,
+                endDate: endDate
+            },
+            method: 'POST',
+            success: function (res) {
+                if (res.code === 200) {
+                    $('#settleTip').html('<span style="color: #5FB878;">鉁� 鏃ユ湡鑼冨洿鏈夋晥锛屽彲浠ユ甯歌繘琛屾湀缁�</span>');
+                } else {
+                    $('#settleTip').html('<span style="color: #ff5722;">璀﹀憡锛�' + (res.msg || '鏈堢粨鏃堕棿鑼冨洿鍐呭瓨鍦ㄦ湭瀹屾垚鐨勮鍗曪紝鏃犳硶杩涜鏈堢粨') + '</span>');
+                }
+            },
+            error: function() {
+                $('#settleTip').html('<span style="color: #ff5722;">妫�鏌ュけ璐ワ紝璇烽噸璇�</span>');
+            }
+        });
+    }
+
+    // 宸ュ叿鏉$偣鍑讳簨浠�
+    table.on('tool(monthlySettle)', function (obj) {
+        var data = obj.data;
+        var layEvent = obj.event;
+        if (layEvent === 'detail') {
+            showDetailDialog(data);
+        } else if (layEvent === 'delete') {
+            deleteSettle(data);
+        }
+    });
+
+    // 鏄剧ず鏄庣粏寮圭獥
+    function showDetailDialog(data) {
+        layer.load(2);
+        $.ajax({
+            url: baseUrl + '/monthlySettle/statistics/' + data.id + '/auth',
+            headers: {'token': localStorage.getItem('token')},
+            method: 'POST',
+            success: function (res) {
+                layer.closeAll('loading');
+                if (res.code === 200) {
+                    var settle = res.data.settle;
+                    var details = res.data.details;
+                    
+                    // 鍏堟覆鏌撴ā鏉�
+                    var template = $('#detailDialog').html();
+                    var html = laytpl(template).render(settle);
+                    
+                    admin.open({
+                        type: 1,
+                        title: '鏈堢粨鏄庣粏 - ' + settle.settleNo,
+                        content: html,
+                        area: ['90%', '80%'],
+                        success: function (layero, dIndex) {
+                            // 娓叉煋鏄庣粏琛ㄦ牸锛堝璐﹀崟鏍煎紡锛�
+                            table.render({
+                                elem: '#detailTable',
+                                data: details,
+                                page: true,
+                                cellMinWidth: 100,
+                                cols: [[
+                                    {type: 'numbers', title: '搴忓彿', width: 60, align: 'center'},
+                                    {field: 'matnr', title: '鐗╂枡缂栫爜', width: 150},
+                                    {field: 'maktx', title: '鐗╂枡鍚嶇О', width: 200},
+                                    {field: 'batch', title: '鎵规', width: 120},
+                                    {field: 'brand', title: '鍝佺墝', width: 120},
+                                    {
+                                        field: 'beginningQty',
+                                        align: 'right',
+                                        title: '鏈熷垵搴撳瓨',
+                                        width: 120,
+                                        templet: function (d) {
+                                            var qty = parseFloat(d.beginningQty || 0);
+                                            return qty.toFixed(2);
+                                        }
+                                    },
+                                    {
+                                        field: 'inQty',
+                                        align: 'right',
+                                        title: '鏈湡鍏ュ簱',
+                                        width: 120,
+                                        templet: function (d) {
+                                            var qty = parseFloat(d.inQty || 0);
+                                            return qty.toFixed(2);
+                                        }
+                                    },
+                                    {
+                                        field: 'outQty',
+                                        align: 'right',
+                                        title: '鏈湡鍑哄簱',
+                                        width: 120,
+                                        templet: function (d) {
+                                            var qty = parseFloat(d.outQty || 0);
+                                            return qty.toFixed(2);
+                                        }
+                                    },
+                                    {
+                                        field: 'endingQty',
+                                        align: 'right',
+                                        title: '鏈熸湯搴撳瓨',
+                                        width: 120,
+                                        templet: function (d) {
+                                            var qty = parseFloat(d.endingQty || 0);
+                                            return qty.toFixed(2);
+                                        }
+                                    },
+                                    {
+                                        field: 'stockQty',
+                                        align: 'right',
+                                        title: '瀹為檯搴撳瓨',
+                                        width: 120,
+                                        templet: function (d) {
+                                            var qty = parseFloat(d.stockQty || 0);
+                                            return qty.toFixed(2);
+                                        }
+                                    },
+                                    {
+                                        field: 'diffQty',
+                                        align: 'right',
+                                        title: '宸紓鏁伴噺',
+                                        width: 120,
+                                        templet: function (d) {
+                                            var diff = parseFloat(d.diffQty || 0);
+                                            if (diff > 0) {
+                                                return '<span style="color: #5FB878;">+' + diff.toFixed(2) + '</span>';
+                                            } else if (diff < 0) {
+                                                return '<span style="color: #ff5722;">' + diff.toFixed(2) + '</span>';
+                                            } else {
+                                                return diff.toFixed(2);
+                                            }
+                                        }
+                                    }
+                                ]]
+                            });
+                        }
+                    });
+                } else if (res.code === 403) {
+                    top.location.href = baseUrl + "/";
+                } else {
+                    layer.msg(res.msg || '鑾峰彇鏄庣粏澶辫触', {icon: 2});
+                }
+            }
+        });
+    }
+
+    // 鍒犻櫎鏈堢粨璁板綍
+    function deleteSettle(data) {
+        layer.confirm('纭瑕佸垹闄ゆ湀缁撹褰� "' + data.settleNo + '" 鍚楋紵鍒犻櫎鍚庡皢娓呴櫎鍏宠仈鐨勫嚭鍏ュ簱璁㈠崟鏈堢粨淇℃伅锛屽彲浠ラ噸鏂拌繘琛屾湀缁撱��', {
+            shade: .1,
+            skin: 'layui-layer-admin'
+        }, function (i) {
+            layer.close(i);
+            layer.load(2);
+            $.ajax({
+                url: baseUrl + '/monthlySettle/' + data.id + '/auth',
+                headers: {'token': localStorage.getItem('token')},
+                method: 'DELETE',
+                success: function (res) {
+                    layer.closeAll('loading');
+                    if (res.code === 200) {
+                        tableIns.reload({page: {curr: 1}});
+                        layer.msg(res.msg || '鍒犻櫎鎴愬姛', {icon: 1});
+                    } else if (res.code === 403) {
+                        top.location.href = baseUrl + "/";
+                    } else {
+                        layer.msg(res.msg || '鍒犻櫎澶辫触', {icon: 2});
+                    }
+                },
+                error: function() {
+                    layer.closeAll('loading');
+                    layer.msg('鍒犻櫎澶辫触', {icon: 2});
+                }
+            });
+        });
+    }
+});
+
+function tableReload(child) {
+    var searchData = {};
+    $.each($('#search-box [name]').serializeArray(), function() {
+        var value = this.value;
+        // 澶勭悊鏃ユ湡鑼冨洿瀛楁
+        if (this.name === 'date_range') {
+            // 鍙鐞嗛潪绌哄��
+            if (value && value.trim() !== '') {
+                var dates = value.split(' - ');
+                if (dates.length === 2) {
+                    var startDate = dates[0].trim();
+                    var endDate = dates[1].trim();
+                    if (startDate !== '' && endDate !== '') {
+                        searchData.startDate = startDate;
+                        searchData.endDate = endDate;
+                    }
+                }
+            }
+        } else if (this.name === 'settle_no') {
+            // 鍙鐞嗛潪绌哄��
+            var trimmedValue = value ? value.trim() : '';
+            if (trimmedValue !== '') {
+                searchData.settleNo = trimmedValue;
+            }
+        }
+    });
+    debugger; // 璋冭瘯鐢細妫�鏌� searchData 鐨勫��
+    
+    // 鑾峰彇 table 瀹炰緥
+    var tableInstance = child ? parent.tableIns : tableIns;
+    
+    // 濡傛灉 searchData 涓虹┖瀵硅薄锛岄渶瑕佹樉寮忎紶鍏ヨ鐩栨墍鏈夊彲鑳藉弬鏁扮殑瀵硅薄
+    // 鍥犱负 layui table 鍙兘浼氬悎骞舵棫鐨勫弬鏁帮紝鍗充娇浼犲叆绌哄璞′篃鍙兘淇濈暀鏃у��
+    if (Object.keys(searchData).length === 0) {
+        if (tableInstance && tableInstance.config) {
+            // 鍏堜繚瀛樻棫鐨� where 涓彲鑳藉瓨鍦ㄧ殑鎵�鏈夐敭
+            var oldWhereKeys = [];
+            if (tableInstance.config.where) {
+                for (var key in tableInstance.config.where) {
+                    if (tableInstance.config.where.hasOwnProperty(key)) {
+                        oldWhereKeys.push(key);
+                    }
+                }
+            }
+            
+            // 瀹屽叏鏇挎崲 where 瀵硅薄
+            tableInstance.config.where = {};
+            
+            // 濡傛灉涔嬪墠鏈夊弬鏁帮紝鍒涘缓涓�涓槑纭鐩栫殑瀵硅薄锛屽皢鎵�鏈夋棫鍙傛暟璁剧疆涓虹┖瀛楃涓�
+            // 浣跨敤绌哄瓧绗︿覆鑰屼笉鏄� null锛屽洜涓� layui 鍙兘浼氳繃婊� null 鍊�
+            if (oldWhereKeys.length > 0) {
+                var overrideWhere = {};
+                oldWhereKeys.forEach(function(key) {
+                    overrideWhere[key] = ''; // 璁剧疆涓虹┖瀛楃涓叉潵瑕嗙洊鏃у��
+                });
+                searchData = overrideWhere;
+                console.log('鍒涘缓瑕嗙洊瀵硅薄锛屾棫鍙傛暟閿�:', oldWhereKeys, '瑕嗙洊瀵硅薄:', JSON.stringify(overrideWhere));
+            } else {
+                // 鍗充娇娌℃湁鏃у弬鏁帮紝涔熷垱寤轰竴涓寘鍚墍鏈夊彲鑳藉弬鏁扮殑绌哄璞�
+                // 杩欐牱鍙互纭繚瑕嗙洊浠讳綍鍙兘鐨勬棫鍙傛暟
+                searchData = {
+                    settleNo: '',
+                    startDate: '',
+                    endDate: ''
+                };
+                console.log('鍒涘缓榛樿瑕嗙洊瀵硅薄:', JSON.stringify(searchData));
+            }
+        }
+    }
+    
+    // 鏋勫缓 reload 鍙傛暟
+    var reloadOptions = {
+        where: searchData,
+        page: {
+            curr: pageCurr
+        },
+        done: function (res, curr, count) {
+            if (res.code === 403) {
+                top.location.href = baseUrl+"/";
+            }
+            pageCurr=curr;
+            if (res.data.length === 0 && count !== 0) {
+                var reloadTableInstance = child ? parent.tableIns : tableIns;
+                // 濡傛灉 searchData 涓虹┖锛屼篃瀹屽叏鏇挎崲 where 瀵硅薄
+                if (Object.keys(searchData).length === 0 && reloadTableInstance && reloadTableInstance.config) {
+                    reloadTableInstance.config.where = {};
+                }
+                reloadTableInstance.reload({
+                    where: searchData,
+                    page: {
+                        curr: pageCurr-1
+                    }
+                });
+                pageCurr -= 1;
+            }
+        }
+    };
+    
+    // 璋冭瘯锛氭墦鍗� reload 鍓嶇殑閰嶇疆
+    console.log('reload 鍓嶇殑 config.where:', JSON.stringify(tableInstance.config ? tableInstance.config.where : 'no config'));
+    console.log('reload 鏃剁殑 where 鍙傛暟:', JSON.stringify(reloadOptions.where));
+    
+    tableInstance.reload(reloadOptions);
+    
+    // 璋冭瘯锛氭墦鍗� reload 鍚庣殑閰嶇疆
+    setTimeout(function() {
+        console.log('reload 鍚庣殑 config.where:', JSON.stringify(tableInstance.config ? tableInstance.config.where : 'no config'));
+    }, 100);
+}
diff --git a/src/main/webapp/views/monthlySettle/monthlySettle.html b/src/main/webapp/views/monthlySettle/monthlySettle.html
new file mode 100644
index 0000000..c0ba70c
--- /dev/null
+++ b/src/main/webapp/views/monthlySettle/monthlySettle.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>鏈堢粨绠$悊</title>
+    <meta name="renderer" content="webkit">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
+    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
+    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
+</head>
+<body>
+
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body">
+            <div class="layui-form toolbar"  id="search-box">
+                <div class="layui-form-item">
+                    <div class="layui-inline">
+                        <div class="layui-input-inline mr0">
+                            <input name="settle_no" class="layui-input" type="text" placeholder="杈撳叆鏈堢粨缂栧彿"/>
+                        </div>
+                    </div>
+                    <div class="layui-inline" style="width: 300px">
+                        <div class="layui-input-inline">
+                            <input class="layui-input layui-laydate-range" name="date_range" type="text" placeholder="璧峰鏃ユ湡 - 缁撴潫鏃ユ湡" autocomplete="off" style="width: 300px">
+                        </div>
+                    </div>
+                    <div class="layui-inline">
+                        <button class="layui-btn icon-btn" lay-filter="search" lay-submit>
+                            <i class="layui-icon">&#xe615;</i>鎼滅储
+                        </button>
+                        <button id="startSettleBtn" class="layui-btn icon-btn layui-btn-normal">
+                            <i class="layui-icon">&#xe608;</i>鍙戣捣鏈堢粨
+                        </button>
+                        <button type="button" class="layui-btn icon-btn layui-btn-primary" lay-filter="reset" lay-submit>
+                            <i class="layui-icon">&#xe669;</i>閲嶇疆
+                        </button>
+                    </div>
+                </div>
+            </div>
+            <table class="layui-hide" id="monthlySettle" lay-filter="monthlySettle" ></table>
+        </div>
+    </div>
+</div>
+
+<!-- 琛ㄦ牸鎿嶄綔鍒� -->
+<script type="text/html" id="operate">
+    <a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="detail">鏌ョ湅鏄庣粏</a>
+    <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete">鍒犻櫎</a>
+</script>
+
+<!-- 鍙戣捣鏈堢粨寮圭獥 -->
+<script type="text/html" id="startSettleDialog">
+    <form id="startSettleForm" lay-filter="startSettleForm" class="layui-form model-form">
+        <div class="layui-form-item">
+            <label class="layui-form-label">璧峰鏃ユ湡锛�</label>
+            <div class="layui-input-block">
+                <input id="startDate" name="startDate" placeholder="閫夋嫨璧峰鏃ユ湡" type="text" class="layui-input" autocomplete="off" lay-verType="tips" lay-verify="required">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">缁撴潫鏃ユ湡锛�</label>
+            <div class="layui-input-block">
+                <input id="endDate" name="endDate" placeholder="閫夋嫨缁撴潫鏃ユ湡" type="text" class="layui-input" autocomplete="off" lay-verType="tips" lay-verify="required">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">鎻愮ず锛�</label>
+            <div class="layui-input-block">
+                <div id="settleTip" style="color: #ff5722;"></div>
+            </div>
+        </div>
+        <div class="layui-form-item text-right">
+            <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">鍙栨秷</button>
+            <button class="layui-btn" lay-filter="startSettleSubmit" lay-submit>纭鏈堢粨</button>
+        </div>
+    </form>
+</script>
+
+<!-- 鏈堢粨鏄庣粏寮圭獥 -->
+<script type="text/html" id="detailDialog">
+    <div style="padding: 20px;">
+        <div class="layui-row">
+            <div class="layui-col-md6">
+                {{# if(d.settleNo) { }}
+                <p><strong>鏈堢粨缂栧彿锛�</strong>{{ d.settleNo }}</p>
+                {{# } }}
+                {{# if(d.startDate$) { }}
+                <p><strong>璧峰鏃ユ湡锛�</strong>{{ d.startDate$ }}</p>
+                {{# } }}
+                {{# if(d.endDate$) { }}
+                <p><strong>缁撴潫鏃ユ湡锛�</strong>{{ d.endDate$ }}</p>
+                {{# } }}
+            </div>
+            <div class="layui-col-md6">
+                {{# if(d.totalInQty !== null && d.totalInQty !== undefined) { }}
+                <p><strong>鎬诲叆搴撴暟閲忥細</strong>{{ d.totalInQty }}</p>
+                {{# } }}
+                {{# if(d.totalOutQty !== null && d.totalOutQty !== undefined) { }}
+                <p><strong>鎬诲嚭搴撴暟閲忥細</strong>{{ d.totalOutQty }}</p>
+                {{# } }}
+                {{# if(d.totalMaterials !== null && d.totalMaterials !== undefined) { }}
+                <p><strong>鐗╂枡绉嶇被鏁帮細</strong>{{ d.totalMaterials }}</p>
+                {{# } }}
+            </div>
+        </div>
+        <hr class="layui-bg-gray">
+        <table id="detailTable" lay-filter="detailTable"></table>
+    </div>
+</script>
+
+<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
+<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/monthlySettle/monthlySettle.js" charset="utf-8"></script>
+</body>
+</html>
+
+

--
Gitblit v1.9.1