From 01175f85df1e8402ada5a30aacfeb18fa621e95e Mon Sep 17 00:00:00 2001
From: chen.lin <1442464845@qq.com>
Date: 星期三, 28 一月 2026 16:15:11 +0800
Subject: [PATCH] 委外加工出库单同步+PDA出库功能

---
 src/main/java/materialReceive.sql                                    |   10 
 src/main/java/com/zy/asrs/service/MaterialWwOutService.java          |    8 
 src/main/webapp/views/materialReceive/materialReceive.html           |   33 
 src/main/java/materialWwOut_alter_decimal.sql                        |   25 
 src/main/webapp/views/pda/materialWwOut.html                         |  511 ++++++++++++++++++
 src/main/java/com/zy/asrs/service/impl/MaterialWwOutServiceImpl.java |   12 
 src/main/java/materialWwOut.sql                                      |   42 +
 src/main/webapp/views/materialWwOut/materialWwOut.html               |  380 +++++++++++++
 src/main/java/com/zy/asrs/controller/MaterialWwOutController.java    |  409 ++++++++++++++
 src/main/java/com/zy/asrs/entity/MaterialWwOut.java                  |  218 +++++++
 src/main/java/com/zy/asrs/mapper/MaterialWwOutMapper.java            |   12 
 11 files changed, 1,639 insertions(+), 21 deletions(-)

diff --git a/src/main/java/com/zy/asrs/controller/MaterialWwOutController.java b/src/main/java/com/zy/asrs/controller/MaterialWwOutController.java
new file mode 100644
index 0000000..5c46504
--- /dev/null
+++ b/src/main/java/com/zy/asrs/controller/MaterialWwOutController.java
@@ -0,0 +1,409 @@
+package com.zy.asrs.controller;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.core.common.Cools;
+import com.core.common.R;
+import com.core.annotations.ManagerAuth;
+import com.zy.asrs.entity.MaterialWwOut;
+import com.zy.asrs.service.MaterialWwOutService;
+import com.zy.common.web.BaseController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.core.common.DateUtils;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+public class MaterialWwOutController extends BaseController {
+
+    @Autowired
+    private MaterialWwOutService materialWwOutService;
+
+    @RequestMapping(value = "/materialWwOut/{id}/auth")
+    @ManagerAuth
+    public R get(@PathVariable("id") String id) {
+        return R.ok(materialWwOutService.selectById(String.valueOf(id)));
+    }
+
+    @RequestMapping(value = "/materialWwOut/list/auth")
+    @ManagerAuth
+    public R list(@RequestParam(defaultValue = "1") Integer curr,
+                  @RequestParam(defaultValue = "1000") Integer limit,
+                  @RequestParam(required = false) String orderByField,
+                  @RequestParam(required = false) String orderByType,
+                  @RequestParam(required = false) String condition,
+                  @RequestParam(required = false) Boolean pdaQuery,
+                  @RequestParam Map<String, Object> param) {
+        EntityWrapper<MaterialWwOut> wrapper = new EntityWrapper<>();
+        excludeTrash(param);
+        // 绉婚櫎pdaQuery鍙傛暟锛屽洜涓哄畠涓嶆槸鏁版嵁搴撳瓧娈碉紝鍙槸鎺у埗鍙傛暟
+        param.remove("pdaQuery");
+        convert(param, wrapper);
+        allLike(MaterialWwOut.class, param.keySet(), wrapper, condition);
+        
+        // 鍙傝�冨叾浠栧嚭搴撴ā鍧楋紝PDA鍑哄簱鏌ヨ鏃惰繃婊ゆ帀宸插叏閮ㄥ嚭搴撶殑鐗╂枡锛堝彧鏄剧ず杩樻湁鍓╀綑鏁伴噺鐨勶級
+        // 閫氳繃 pdaQuery 鍙傛暟鍒ゆ柇鏄惁鏄疨DA鍑哄簱鏌ヨ
+        if (pdaQuery != null && pdaQuery) {
+            // PDA鍑哄簱鏌ヨ锛氬彧鏄剧ず鍓╀綑鏁伴噺澶т簬0鐨勮褰�
+            wrapper.gt("remain_qty", 0);
+        }
+        
+        if (!Cools.isEmpty(orderByField)) {
+            wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType));
+        }
+        return R.ok(materialWwOutService.selectPage(new Page<>(curr, limit), wrapper));
+    }
+
+    @RequestMapping(value = "/materialWwOut/batchSave/auth", method = RequestMethod.POST)
+    @ManagerAuth
+    public R batchSave(@RequestBody List<Map<String, Object>> dataList) {
+        if (Cools.isEmpty(dataList)) {
+            return R.error("鏁版嵁涓嶈兘涓虹┖");
+        }
+        int successCount = 0;
+        int updateCount = 0;
+        for (Map<String, Object> data : dataList) {
+            try {
+                // 妫�鏌ユ槸鍚﹀凡瀛樺湪锛堟牴鎹畆ecordId鍜宨nvCode鍞竴鏍囪瘑锛屽鏋渞ecordId涓虹┖鍒欎娇鐢╥d锛�
+                String recordId = data.get("recordId") != null ? String.valueOf(data.get("recordId")) : null;
+                // 濡傛灉recordId涓虹┖锛屽皾璇曚娇鐢╥d瀛楁
+                if (recordId == null || recordId.isEmpty() || "null".equals(recordId)) {
+                    if (data.get("id") != null) {
+                        recordId = String.valueOf(data.get("id"));
+                    }
+                }
+                String invCode = data.get("invCode") != null ? String.valueOf(data.get("invCode")) : null;
+
+                MaterialWwOut existRecord = null;
+                if (recordId != null && !recordId.isEmpty() && !"null".equals(recordId) && invCode != null) {
+                    existRecord = materialWwOutService.selectOne(new EntityWrapper<MaterialWwOut>()
+                            .eq("record_id", recordId)
+                            .eq("inv_code", invCode));
+                }
+
+                MaterialWwOut materialWwOut;
+                if (existRecord != null) {
+                    // 宸插瓨鍦紝鏇存柊鏁版嵁锛堜笉瑕嗙洊鍑哄簱鐩稿叧瀛楁锛�
+                    materialWwOut = existRecord;
+                    updateCount++;
+                } else {
+                    // 涓嶅瓨鍦紝鍒涘缓鏂拌褰�
+                    materialWwOut = new MaterialWwOut();
+                    materialWwOut.setCreateTime(new Date());
+                    // 鍒濆鍖栧嚭搴撶浉鍏冲瓧娈�
+                    materialWwOut.setOutQty(BigDecimal.ZERO);
+                    materialWwOut.setRemainQty(data.get("fqty") != null ? 
+                        new BigDecimal(String.valueOf(data.get("fqty"))) : 
+                        (data.get("qty") != null ? new BigDecimal(String.valueOf(data.get("qty"))) : BigDecimal.ZERO));
+                    materialWwOut.setIsAllOut(0);
+                    successCount++;
+                }
+
+                // 鏇存柊/璁剧疆瀛楁 - 纭繚recordId鏈夊��
+                if (recordId == null || recordId.isEmpty() || "null".equals(recordId)) {
+                    // 濡傛灉recordId涓虹┖锛屽皾璇曚娇鐢╥d瀛楁
+                    if (data.get("id") != null) {
+                        recordId = String.valueOf(data.get("id"));
+                    }
+                }
+                materialWwOut.setRecordId(recordId);
+                if (data.get("dateStart") != null && !Cools.isEmpty(String.valueOf(data.get("dateStart")))) {
+                    try {
+                        String dateStr = String.valueOf(data.get("dateStart"));
+                        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
+                        materialWwOut.setDateStart(sdf.parse(dateStr));
+                    } catch (Exception ex) {
+                        // 蹇界暐鏃ユ湡瑙f瀽閿欒
+                    }
+                }
+                if (data.get("dateEnd") != null && !Cools.isEmpty(String.valueOf(data.get("dateEnd")))) {
+                    try {
+                        String dateStr = String.valueOf(data.get("dateEnd"));
+                        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
+                        materialWwOut.setDateEnd(sdf.parse(dateStr));
+                    } catch (Exception ex) {
+                        // 蹇界暐鏃ユ湡瑙f瀽閿欒
+                    }
+                }
+                if (data.get("venId") != null) {
+                    try {
+                        materialWwOut.setVenId(Integer.valueOf(String.valueOf(data.get("venId"))));
+                    } catch (Exception e) {
+                        // 蹇界暐杞崲閿欒
+                    }
+                }
+                materialWwOut.setVenName(data.get("venName") != null ? String.valueOf(data.get("venName")) : null);
+                materialWwOut.setInvCode(invCode);
+                materialWwOut.setInvName(data.get("invName") != null ? String.valueOf(data.get("invName")) : null);
+                materialWwOut.setInvStd(data.get("invStd") != null ? String.valueOf(data.get("invStd")) : null);
+                materialWwOut.setUnit(data.get("unit") != null ? String.valueOf(data.get("unit")) : null);
+                
+                // 鏁伴噺瀛楁澶勭悊锛堜紭鍏堜娇鐢╢qty锛屽鏋滄病鏈夊垯浣跨敤qty锛�
+                BigDecimal qty = null;
+                if (data.get("fqty") != null) {
+                    qty = new BigDecimal(String.valueOf(data.get("fqty")));
+                    materialWwOut.setFqty(qty);
+                } else if (data.get("qty") != null) {
+                    qty = new BigDecimal(String.valueOf(data.get("qty")));
+                    materialWwOut.setQty(qty);
+                }
+                
+                if (data.get("qqty") != null) {
+                    materialWwOut.setQqty(new BigDecimal(String.valueOf(data.get("qqty"))));
+                }
+                if (data.get("yqty") != null) {
+                    materialWwOut.setYqty(new BigDecimal(String.valueOf(data.get("yqty"))));
+                }
+                if (data.get("wqty") != null) {
+                    materialWwOut.setWqty(new BigDecimal(String.valueOf(data.get("wqty"))));
+                }
+                
+                // 濡傛灉宸插瓨鍦紝鏇存柊鍓╀綑鏁伴噺锛堝熀浜庡師濮嬫暟閲忥級
+                if (existRecord == null && qty != null) {
+                    materialWwOut.setRemainQty(qty);
+                } else if (existRecord != null && qty != null) {
+                    // 宸插瓨鍦ㄦ椂锛屽鏋滄暟閲忔湁鍙樺寲锛岄噸鏂拌绠楀墿浣欐暟閲�
+                    BigDecimal originalQty = existRecord.getFqty() != null ? existRecord.getFqty() : 
+                                           (existRecord.getQty() != null ? existRecord.getQty() : BigDecimal.ZERO);
+                    BigDecimal outQty = existRecord.getOutQty() != null ? existRecord.getOutQty() : BigDecimal.ZERO;
+                    // 濡傛灉鏂版暟閲忎笌鍘熷鏁伴噺涓嶅悓锛岃鏄庢暟閲忔洿鏂颁簡锛岄渶瑕侀噸鏂拌绠楀墿浣欐暟閲�
+                    if (qty.compareTo(originalQty) != 0) {
+                        // 鏁伴噺鍙樺寲锛屽墿浣欐暟閲� = 鏂版暟閲� - 宸插嚭搴撴暟閲�
+                        materialWwOut.setRemainQty(qty.subtract(outQty));
+                    } else {
+                        // 鏁伴噺娌″彉鍖栵紝淇濇寔鍘熸湁鍓╀綑鏁伴噺
+                        materialWwOut.setRemainQty(existRecord.getRemainQty());
+                    }
+                }
+                
+                if (data.get("funitid") != null) {
+                    try {
+                        materialWwOut.setFunitid(Integer.valueOf(String.valueOf(data.get("funitid"))));
+                    } catch (Exception e) {
+                        // 蹇界暐杞崲閿欒
+                    }
+                }
+                if (data.get("fitemid") != null) {
+                    try {
+                        materialWwOut.setFitemid(Integer.valueOf(String.valueOf(data.get("fitemid"))));
+                    } catch (Exception e) {
+                        // 蹇界暐杞崲閿欒
+                    }
+                }
+                if (data.get("whId") != null) {
+                    try {
+                        materialWwOut.setWhId(Integer.valueOf(String.valueOf(data.get("whId"))));
+                    } catch (Exception e) {
+                        // 蹇界暐杞崲閿欒
+                    }
+                }
+                materialWwOut.setWhName(data.get("whName") != null ? String.valueOf(data.get("whName")) : null);
+                
+                if (data.get("izSync") != null) {
+                    materialWwOut.setIzSync(String.valueOf(data.get("izSync")));
+                }
+                if (data.get("izPrint") != null) {
+                    materialWwOut.setIzPrint(String.valueOf(data.get("izPrint")));
+                }
+                
+                // 灏嗗叾浠栧瓧娈靛瓨鍌ㄥ埌ext_data锛圝SON鏍煎紡锛�
+                Map<String, Object> extDataMap = new HashMap<>();
+                // 宸叉槧灏勫埌鏁版嵁搴撹〃瀛楁鐨勫瓧娈靛垪琛紙杩欎簺瀛楁涓嶉渶瑕佸瓨鍌ㄥ湪ext_data涓級
+                java.util.Set<String> mappedFields = new java.util.HashSet<>();
+                mappedFields.add("recordId");
+                mappedFields.add("dateStart");
+                mappedFields.add("dateEnd");
+                mappedFields.add("venId");
+                mappedFields.add("venName");
+                mappedFields.add("invCode");
+                mappedFields.add("invName");
+                mappedFields.add("invStd");
+                mappedFields.add("unit");
+                mappedFields.add("funitid");
+                mappedFields.add("fitemid");
+                mappedFields.add("whId");
+                mappedFields.add("whName");
+                mappedFields.add("qty");
+                mappedFields.add("fqty");
+                mappedFields.add("qqty");
+                mappedFields.add("yqty");
+                mappedFields.add("wqty");
+                mappedFields.add("izSync");
+                mappedFields.add("izPrint");
+                
+                // 灏嗘墍鏈夋湭鏄犲皠鐨勫瓧娈靛瓨鍌ㄥ埌ext_data涓�
+                for (Map.Entry<String, Object> entry : data.entrySet()) {
+                    String key = entry.getKey();
+                    if (!mappedFields.contains(key) && entry.getValue() != null) {
+                        extDataMap.put(key, entry.getValue());
+                    }
+                }
+                
+                // 濮嬬粓鏇存柊ext_data锛屽嵆浣夸负绌轰篃瑕佸瓨鍌紙鐢ㄤ簬鍚庣画鎵╁睍锛�
+                materialWwOut.setExtData(com.alibaba.fastjson.JSON.toJSONString(extDataMap));
+                
+                materialWwOut.setSyncTime(new Date());
+                materialWwOut.setUpdateTime(new Date());
+
+                // 淇濆瓨鎴栨洿鏂�
+                if (existRecord != null) {
+                    materialWwOutService.updateById(materialWwOut);
+                } else {
+                    materialWwOutService.insert(materialWwOut);
+                }
+            } catch (Exception e) {
+                // 璁板綍澶辫触鐨勮褰曪紝缁х画澶勭悊涓嬩竴鏉�
+                e.printStackTrace();
+            }
+        }
+        return R.ok("鎴愬姛淇濆瓨 " + successCount + " 鏉℃柊鏁版嵁锛屾洿鏂� " + updateCount + " 鏉″凡瀛樺湪鏁版嵁");
+    }
+
+    @RequestMapping(value = "/materialWwOut/update/auth")
+    @ManagerAuth
+    public R update(MaterialWwOut materialWwOut) {
+        if (Cools.isEmpty(materialWwOut) || null == materialWwOut.getId()) {
+            return R.error();
+        }
+        materialWwOut.setUpdateTime(new Date());
+        materialWwOutService.updateById(materialWwOut);
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/materialWwOut/updateOutQty/auth", method = RequestMethod.POST)
+    @ManagerAuth
+    public R updateOutQty(@RequestBody Map<String, Object> param) {
+        Long id = Long.valueOf(String.valueOf(param.get("id")));
+        BigDecimal addOutQty = new BigDecimal(String.valueOf(param.get("outQty"))); // 鏈鍑哄簱鏁伴噺
+        
+        MaterialWwOut materialWwOut = materialWwOutService.selectById(id);
+        if (materialWwOut == null) {
+            return R.error("璁板綍涓嶅瓨鍦�");
+        }
+        
+        // 绱姞鍑哄簱鏁伴噺
+        BigDecimal currentOutQty = materialWwOut.getOutQty() != null ? materialWwOut.getOutQty() : BigDecimal.ZERO;
+        BigDecimal newOutQty = currentOutQty.add(addOutQty);
+        materialWwOut.setOutQty(newOutQty);
+        
+        // 璁$畻鍓╀綑鏁伴噺锛堜紭鍏堜娇鐢╢qty锛屽鏋滄病鏈夊垯浣跨敤qty锛�
+        BigDecimal qty = materialWwOut.getFqty() != null ? materialWwOut.getFqty() : 
+                         (materialWwOut.getQty() != null ? materialWwOut.getQty() : BigDecimal.ZERO);
+        BigDecimal remainQty = qty.subtract(newOutQty);
+        materialWwOut.setRemainQty(remainQty.compareTo(BigDecimal.ZERO) > 0 ? remainQty : BigDecimal.ZERO);
+        
+        // 鍒ゆ柇鏄惁鍏ㄩ儴鍑哄簱瀹屾垚
+        materialWwOut.setIsAllOut(remainQty.compareTo(BigDecimal.ZERO) <= 0 ? 1 : 0);
+        materialWwOut.setUpdateTime(new Date());
+        
+        materialWwOutService.updateById(materialWwOut);
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/materialWwOut/checkSyncStatus/auth")
+    @ManagerAuth
+    public R checkSyncStatus(@RequestParam String recordId, @RequestParam(required = false) String invCode) {
+        EntityWrapper<MaterialWwOut> wrapper = new EntityWrapper<>();
+        wrapper.eq("record_id", recordId);
+        if (!Cools.isEmpty(invCode)) {
+            wrapper.eq("inv_code", invCode);
+        }
+        List<MaterialWwOut> list = materialWwOutService.selectList(wrapper);
+        
+        Map<String, Object> result = new HashMap<>();
+        if (Cools.isEmpty(list)) {
+            result.put("synced", false);
+            result.put("allOut", false);
+            result.put("message", "璇ヨ褰旾D鏈悓姝ュ埌WMS");
+            return R.ok(result);
+        }
+        
+        // 妫�鏌ユ槸鍚﹀叏閮ㄥ嚭搴撳畬鎴�
+        boolean allOut = true;
+        List<Map<String, Object>> notOutList = new ArrayList<>();
+        for (MaterialWwOut mwo : list) {
+            if (mwo.getIsAllOut() == null || mwo.getIsAllOut() != 1) {
+                allOut = false;
+                Map<String, Object> notOutItem = new HashMap<>();
+                notOutItem.put("invCode", mwo.getInvCode());
+                notOutItem.put("invName", mwo.getInvName());
+                notOutItem.put("remainQty", mwo.getRemainQty());
+                notOutList.add(notOutItem);
+            }
+        }
+        
+        result.put("synced", true);
+        result.put("allOut", allOut);
+        result.put("records", list);
+        if (!allOut && !notOutList.isEmpty()) {
+            result.put("notOutList", notOutList);
+            result.put("message", "閮ㄥ垎鐗╂枡鏈叏閮ㄥ嚭搴撳畬鎴�");
+        } else if (allOut) {
+            result.put("message", "鍏ㄩ儴鐗╂枡宸插嚭搴撳畬鎴�");
+        }
+        return R.ok(result);
+    }
+    
+    private void convert(Map<String, Object> map, EntityWrapper<MaterialWwOut> wrapper) {
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+            String fieldName = entry.getKey();
+            String columnName = getColumnName(MaterialWwOut.class, fieldName);
+            String val = String.valueOf(entry.getValue());
+            if (val.contains(RANGE_TIME_LINK)) {
+                String[] dates = val.split(RANGE_TIME_LINK);
+                wrapper.ge(columnName, DateUtils.convert(dates[0]));
+                wrapper.le(columnName, DateUtils.convert(dates[1]));
+            } else {
+                wrapper.like(columnName, val);
+            }
+        }
+    }
+    
+    /**
+     * 鏍规嵁瀹炰綋绫诲瓧娈靛悕鑾峰彇鏁版嵁搴撳垪鍚�
+     * @param cls 瀹炰綋绫�
+     * @param fieldName Java瀛楁鍚嶏紙椹煎嘲鍛藉悕锛�
+     * @return 鏁版嵁搴撳垪鍚嶏紙涓嬪垝绾垮懡鍚嶏級
+     */
+    private String getColumnName(Class<?> cls, String fieldName) {
+        for (Field field : Cools.getAllFields(cls)) {
+            if (field.getName().equals(fieldName)) {
+                if (field.isAnnotationPresent(TableField.class)) {
+                    TableField annotation = field.getAnnotation(TableField.class);
+                    if (!annotation.exist()) {
+                        continue;
+                    }
+                    String column = annotation.value();
+                    if (!Cools.isEmpty(column)) {
+                        return column;
+                    }
+                }
+                // 濡傛灉娌℃湁@TableField娉ㄨВ锛屼娇鐢╤umpToLine杞崲
+                return humpToLine(fieldName);
+            }
+        }
+        // 濡傛灉鎵句笉鍒板瓧娈碉紝浣跨敤humpToLine杞崲
+        return humpToLine(fieldName);
+    }
+
+    @RequestMapping(value = "/materialWwOut/delete/auth")
+    @ManagerAuth
+    public R delete(@RequestParam String param) {
+        com.alibaba.fastjson.JSONArray jsonArray = com.alibaba.fastjson.JSONArray.parseArray(param);
+        List<MaterialWwOut> list = jsonArray.toJavaList(MaterialWwOut.class);
+        if (Cools.isEmpty(list)) {
+            return R.error("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
+        }
+        for (MaterialWwOut entity : list) {
+            materialWwOutService.deleteById(entity.getId());
+        }
+        return R.ok();
+    }
+}
diff --git a/src/main/java/com/zy/asrs/entity/MaterialWwOut.java b/src/main/java/com/zy/asrs/entity/MaterialWwOut.java
new file mode 100644
index 0000000..ae3cdbf
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/MaterialWwOut.java
@@ -0,0 +1,218 @@
+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 java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 濮斿鍔犲伐鍑哄簱鍗曞疄浣撶被
+ */
+@TableName("erp_material_ww_out")
+@Data
+public class MaterialWwOut implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ApiModelProperty(value = "ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 璁板綍ID锛圗RP涓殑璁板綍ID锛�
+     */
+    @ApiModelProperty(value = "璁板綍ID")
+    @TableField("record_id")
+    private String recordId;
+
+    /**
+     * 寮�宸ユ棩鏈�
+     */
+    @ApiModelProperty(value = "寮�宸ユ棩鏈�")
+    @TableField("date_start")
+    private Date dateStart;
+
+    /**
+     * 瀹屾垚鏃ユ湡
+     */
+    @ApiModelProperty(value = "瀹屾垚鏃ユ湡")
+    @TableField("date_end")
+    private Date dateEnd;
+
+    /**
+     * 渚涘簲鍟咺D
+     */
+    @ApiModelProperty(value = "渚涘簲鍟咺D")
+    @TableField("ven_id")
+    private Integer venId;
+
+    /**
+     * 渚涘簲鍟嗗悕绉�
+     */
+    @ApiModelProperty(value = "渚涘簲鍟嗗悕绉�")
+    @TableField("ven_name")
+    private String venName;
+
+    /**
+     * 鐗╂枡缂栫爜
+     */
+    @ApiModelProperty(value = "鐗╂枡缂栫爜")
+    @TableField("inv_code")
+    private String invCode;
+
+    /**
+     * 鐗╂枡鍚嶇О
+     */
+    @ApiModelProperty(value = "鐗╂枡鍚嶇О")
+    @TableField("inv_name")
+    private String invName;
+
+    /**
+     * 瑙勬牸鍨嬪彿
+     */
+    @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
+    @TableField("inv_std")
+    private String invStd;
+
+    /**
+     * 鍗曚綅
+     */
+    @ApiModelProperty(value = "鍗曚綅")
+    @TableField("unit")
+    private String unit;
+
+    /**
+     * 鍗曚綅ID
+     */
+    @ApiModelProperty(value = "鍗曚綅ID")
+    @TableField("funitid")
+    private Integer funitid;
+
+    /**
+     * 鐗╂枡ID
+     */
+    @ApiModelProperty(value = "鐗╂枡ID")
+    @TableField("fitemid")
+    private Integer fitemid;
+
+    /**
+     * 浠撳簱ID
+     */
+    @ApiModelProperty(value = "浠撳簱ID")
+    @TableField("wh_id")
+    private Integer whId;
+
+    /**
+     * 浠撳簱鍚嶇О
+     */
+    @ApiModelProperty(value = "浠撳簱鍚嶇О")
+    @TableField("wh_name")
+    private String whName;
+
+    /**
+     * 鏁伴噺
+     */
+    @ApiModelProperty(value = "鏁伴噺")
+    @TableField("qty")
+    private BigDecimal qty;
+
+    /**
+     * 搴斿彂鏁伴噺
+     */
+    @ApiModelProperty(value = "搴斿彂鏁伴噺")
+    @TableField("fqty")
+    private BigDecimal fqty;
+
+    /**
+     * 鏈熷垵鏁伴噺
+     */
+    @ApiModelProperty(value = "鏈熷垵鏁伴噺")
+    @TableField("qqty")
+    private BigDecimal qqty;
+
+    /**
+     * 宸插彂鏁伴噺
+     */
+    @ApiModelProperty(value = "宸插彂鏁伴噺")
+    @TableField("yqty")
+    private BigDecimal yqty;
+
+    /**
+     * 鏈彂鏁伴噺
+     */
+    @ApiModelProperty(value = "鏈彂鏁伴噺")
+    @TableField("wqty")
+    private BigDecimal wqty;
+
+    /**
+     * 鍑哄簱鏁伴噺
+     */
+    @ApiModelProperty(value = "鍑哄簱鏁伴噺")
+    @TableField("out_qty")
+    private BigDecimal outQty;
+
+    /**
+     * 鍓╀綑鏁伴噺
+     */
+    @ApiModelProperty(value = "鍓╀綑鏁伴噺")
+    @TableField("remain_qty")
+    private BigDecimal remainQty;
+
+    /**
+     * 鏄惁鍏ㄩ儴鍑哄簱锛�0锛氬惁锛�1锛氭槸锛�
+     */
+    @ApiModelProperty(value = "鏄惁鍏ㄩ儴鍑哄簱")
+    @TableField("is_all_out")
+    private Integer isAllOut;
+
+    /**
+     * 鏄惁鍚屾
+     */
+    @ApiModelProperty(value = "鏄惁鍚屾")
+    @TableField("iz_sync")
+    private String izSync;
+
+    /**
+     * 鏄惁鎵撳嵃
+     */
+    @ApiModelProperty(value = "鏄惁鎵撳嵃")
+    @TableField("iz_print")
+    private String izPrint;
+
+    /**
+     * 鍚屾鏃堕棿
+     */
+    @ApiModelProperty(value = "鍚屾鏃堕棿")
+    @TableField("sync_time")
+    private Date syncTime;
+
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 鏇存柊鏃堕棿
+     */
+    @ApiModelProperty(value = "鏇存柊鏃堕棿")
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 鎵╁睍鏁版嵁锛圝SON鏍煎紡锛�
+     */
+    @ApiModelProperty(value = "鎵╁睍鏁版嵁")
+    @TableField("ext_data")
+    private String extData;
+}
diff --git a/src/main/java/com/zy/asrs/mapper/MaterialWwOutMapper.java b/src/main/java/com/zy/asrs/mapper/MaterialWwOutMapper.java
new file mode 100644
index 0000000..94413f0
--- /dev/null
+++ b/src/main/java/com/zy/asrs/mapper/MaterialWwOutMapper.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.mapper;
+
+import com.zy.asrs.entity.MaterialWwOut;
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface MaterialWwOutMapper extends BaseMapper<MaterialWwOut> {
+
+}
diff --git a/src/main/java/com/zy/asrs/service/MaterialWwOutService.java b/src/main/java/com/zy/asrs/service/MaterialWwOutService.java
new file mode 100644
index 0000000..08207c0
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/MaterialWwOutService.java
@@ -0,0 +1,8 @@
+package com.zy.asrs.service;
+
+import com.zy.asrs.entity.MaterialWwOut;
+import com.baomidou.mybatisplus.service.IService;
+
+public interface MaterialWwOutService extends IService<MaterialWwOut> {
+
+}
diff --git a/src/main/java/com/zy/asrs/service/impl/MaterialWwOutServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/MaterialWwOutServiceImpl.java
new file mode 100644
index 0000000..8eab67c
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/impl/MaterialWwOutServiceImpl.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.service.impl;
+
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.zy.asrs.entity.MaterialWwOut;
+import com.zy.asrs.mapper.MaterialWwOutMapper;
+import com.zy.asrs.service.MaterialWwOutService;
+import org.springframework.stereotype.Service;
+
+@Service("materialWwOutService")
+public class MaterialWwOutServiceImpl extends ServiceImpl<MaterialWwOutMapper, MaterialWwOut> implements MaterialWwOutService {
+
+}
diff --git a/src/main/java/materialReceive.sql b/src/main/java/materialReceive.sql
index 61e5125..359041d 100644
--- a/src/main/java/materialReceive.sql
+++ b/src/main/java/materialReceive.sql
@@ -7,9 +7,9 @@
     [inv_code] [nvarchar](100) NULL,
     [inv_name] [nvarchar](200) NULL,
     [inv_std] [nvarchar](200) NULL,
-    [qty] [decimal](18, 2) NULL,
-    [fqty] [decimal](18, 2) NULL,
-    [fauxqty] [decimal](18, 2) NULL,
+    [qty] [decimal](18, 4) NULL,
+    [fqty] [decimal](18, 4) NULL,
+    [fauxqty] [decimal](18, 4) NULL,
     [unit] [nvarchar](50) NULL,
     [funitid] [int] NULL,
     [dep_name] [nvarchar](100) NULL,
@@ -23,8 +23,8 @@
     [finterid] [int] NULL,
     [fitemid] [int] NULL,
     -- 鍑哄簱鐩稿叧瀛楁
-    [out_qty] [decimal](18, 2) NULL DEFAULT 0,
-    [remain_qty] [decimal](18, 2) NULL DEFAULT 0,
+    [out_qty] [decimal](18, 4) NULL DEFAULT 0,
+    [remain_qty] [decimal](18, 4) NULL DEFAULT 0,
     [is_all_out] [int] NULL DEFAULT 0,
     -- 鍚屾鐩稿叧瀛楁
     [sync_time] [datetime] NULL,
diff --git a/src/main/java/materialWwOut.sql b/src/main/java/materialWwOut.sql
new file mode 100644
index 0000000..552f43d
--- /dev/null
+++ b/src/main/java/materialWwOut.sql
@@ -0,0 +1,42 @@
+-- 濮斿鍔犲伐鍑哄簱鍗曡〃锛堟墿灞曞瓧娈典互鏀寔瀹屾暣鏁版嵁锛�
+CREATE TABLE [dbo].[erp_material_ww_out](
+    [id] [bigint] IDENTITY(1,1) NOT NULL,
+    -- 鍩虹瀛楁
+    [record_id] [nvarchar](100) NULL,
+    [date_start] [datetime] NULL,
+    [date_end] [datetime] NULL,
+    [ven_id] [int] NULL,
+    [ven_name] [nvarchar](200) NULL,
+    [inv_code] [nvarchar](100) NULL,
+    [inv_name] [nvarchar](200) NULL,
+    [inv_std] [nvarchar](200) NULL,
+    [unit] [nvarchar](50) NULL,
+    [funitid] [int] NULL,
+    [fitemid] [int] NULL,
+    [wh_id] [int] NULL,
+    [wh_name] [nvarchar](100) NULL,
+    [qty] [decimal](18, 4) NULL,
+    [fqty] [decimal](18, 4) NULL,
+    [qqty] [decimal](18, 4) NULL,
+    [yqty] [decimal](18, 4) NULL,
+    [wqty] [decimal](18, 4) NULL,
+    -- 鍑哄簱鐩稿叧瀛楁
+    [out_qty] [decimal](18, 4) NULL DEFAULT 0,
+    [remain_qty] [decimal](18, 4) NULL DEFAULT 0,
+    [is_all_out] [int] NULL DEFAULT 0,
+    -- 鍚屾鐩稿叧瀛楁
+    [iz_sync] [nvarchar](10) NULL,
+    [iz_print] [nvarchar](10) NULL,
+    [sync_time] [datetime] NULL,
+    [create_time] [datetime] NULL DEFAULT GETDATE(),
+    [update_time] [datetime] NULL DEFAULT GETDATE(),
+    -- 鎵╁睍瀛楁锛堢敤浜庡瓨鍌ㄦ洿澶欵RP瀛楁锛孞SON鏍煎紡锛�
+    [ext_data] [nvarchar](max) NULL,
+    CONSTRAINT [PK_erp_material_ww_out] PRIMARY KEY CLUSTERED ([id] ASC)
+)
+
+-- 鍒涘缓绱㈠紩
+CREATE INDEX [IX_erp_material_ww_out_record_id] ON [dbo].[erp_material_ww_out] ([record_id])
+CREATE INDEX [IX_erp_material_ww_out_inv_code] ON [dbo].[erp_material_ww_out] ([inv_code])
+CREATE INDEX [IX_erp_material_ww_out_ven_id] ON [dbo].[erp_material_ww_out] ([ven_id])
+CREATE INDEX [IX_erp_material_ww_out_sync] ON [dbo].[erp_material_ww_out] ([record_id], [inv_code])
diff --git a/src/main/java/materialWwOut_alter_decimal.sql b/src/main/java/materialWwOut_alter_decimal.sql
new file mode 100644
index 0000000..a50341e
--- /dev/null
+++ b/src/main/java/materialWwOut_alter_decimal.sql
@@ -0,0 +1,25 @@
+-- 淇敼濮斿鍔犲伐鍑哄簱鍗曡〃鐨勬暟閲忓瓧娈电簿搴︼紝鏀寔4浣嶅皬鏁�
+-- 濡傛灉琛ㄥ凡瀛樺湪锛屾墽琛屾鑴氭湰淇敼瀛楁绮惧害
+
+-- 淇敼鏁伴噺瀛楁绮惧害涓�4浣嶅皬鏁�
+ALTER TABLE [dbo].[erp_material_ww_out]
+    ALTER COLUMN [qty] [decimal](18, 4) NULL;
+
+ALTER TABLE [dbo].[erp_material_ww_out]
+    ALTER COLUMN [fqty] [decimal](18, 4) NULL;
+
+ALTER TABLE [dbo].[erp_material_ww_out]
+    ALTER COLUMN [qqty] [decimal](18, 4) NULL;
+
+ALTER TABLE [dbo].[erp_material_ww_out]
+    ALTER COLUMN [yqty] [decimal](18, 4) NULL;
+
+ALTER TABLE [dbo].[erp_material_ww_out]
+    ALTER COLUMN [wqty] [decimal](18, 4) NULL;
+
+-- 淇敼鍑哄簱鐩稿叧瀛楁绮惧害涓�4浣嶅皬鏁�
+ALTER TABLE [dbo].[erp_material_ww_out]
+    ALTER COLUMN [out_qty] [decimal](18, 4) NULL;
+
+ALTER TABLE [dbo].[erp_material_ww_out]
+    ALTER COLUMN [remain_qty] [decimal](18, 4) NULL;
diff --git a/src/main/webapp/views/materialReceive/materialReceive.html b/src/main/webapp/views/materialReceive/materialReceive.html
index ff430f7..8c60cc9 100644
--- a/src/main/webapp/views/materialReceive/materialReceive.html
+++ b/src/main/webapp/views/materialReceive/materialReceive.html
@@ -59,30 +59,17 @@
                 <el-table-column type="index" width="50"></el-table-column>
                 <el-table-column prop="soCode" label="鐢熶骇鍗曞彿" width="120"
                     :show-overflow-tooltip="true"></el-table-column>
+                <el-table-column prop="fbillno" label="浠诲姟鍗曞彿" width="120"
+                    :show-overflow-tooltip="true"></el-table-column>
                 <el-table-column prop="invCode" label="鐗╂枡缂栫爜" width="120"
                     :show-overflow-tooltip="true"></el-table-column>
                 <el-table-column prop="invName" label="鐗╂枡鍚嶇О" width="200"
                     :show-overflow-tooltip="true"></el-table-column>
                 <el-table-column prop="invStd" label="瑙勬牸鍨嬪彿" width="150"
                     :show-overflow-tooltip="true"></el-table-column>
-                <el-table-column prop="fbillno" label="浠诲姟鍗曞彿" width="120"
-                    :show-overflow-tooltip="true"></el-table-column>
-                <el-table-column prop="qty" label="鎬绘暟閲�" width="100">
+                <el-table-column prop="qty" label="閫氱煡鍑哄簱閲�" width="100">
                     <template #default="scope">
                         {{ scope.row.fqty || scope.row.qty || 0 }}
-                    </template>
-                </el-table-column>
-                <el-table-column prop="unit" label="鍗曚綅" width="80"></el-table-column>
-                <el-table-column prop="depName" label="閮ㄩ棬鍚嶇О" width="120"></el-table-column>
-                <el-table-column prop="depCode" label="閮ㄩ棬缂栫爜" width="120"></el-table-column>
-                <el-table-column prop="whName" label="浠撳簱鍚嶇О" width="120"></el-table-column>
-                <el-table-column prop="fplancommitdate$" label="璁″垝寮�宸ユ棩鏈�" width="120"></el-table-column>
-                <el-table-column prop="fplanfinishdate$" label="璁″垝瀹屽伐鏃ユ湡" width="120"></el-table-column>
-                <el-table-column prop="outQty" label="宸插嚭搴撴暟閲�" width="110">
-                    <template #default="scope">
-                        <span :style="{ color: scope.row.outQty > 0 ? 'green' : 'gray' }">
-                            {{ scope.row.outQty || 0 }}
-                        </span>
                     </template>
                 </el-table-column>
                 <el-table-column prop="remainQty" label="鍓╀綑鏁伴噺" width="110">
@@ -92,6 +79,20 @@
                         </span>
                     </template>
                 </el-table-column>
+                <el-table-column prop="outQty" label="宸插嚭搴撴暟閲�" width="110">
+                    <template #default="scope">
+                        <span :style="{ color: scope.row.outQty > 0 ? 'green' : 'gray' }">
+                            {{ scope.row.outQty || 0 }}
+                        </span>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="unit" label="鍗曚綅" width="80"></el-table-column>
+                <el-table-column prop="depName" label="閮ㄩ棬鍚嶇О" width="120"></el-table-column>
+                <el-table-column prop="depCode" label="閮ㄩ棬缂栫爜" width="120"></el-table-column>
+                <el-table-column prop="whName" label="浠撳簱鍚嶇О" width="120"></el-table-column>
+                <el-table-column prop="fplancommitdate$" label="璁″垝寮�宸ユ棩鏈�" width="120"></el-table-column>
+                <el-table-column prop="fplanfinishdate$" label="璁″垝瀹屽伐鏃ユ湡" width="120"></el-table-column>
+
                 <el-table-column prop="isAllOut" label="鍑哄簱鐘舵��" width="100">
                     <template #default="scope">
                         <el-tag v-if="scope.row.isAllOut == 1" type="success">宸插畬鎴�</el-tag>
diff --git a/src/main/webapp/views/materialWwOut/materialWwOut.html b/src/main/webapp/views/materialWwOut/materialWwOut.html
new file mode 100644
index 0000000..a933d47
--- /dev/null
+++ b/src/main/webapp/views/materialWwOut/materialWwOut.html
@@ -0,0 +1,380 @@
+<!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/evn/index.css">
+</head>
+
+<body>
+    <div id="app">
+        <el-card>
+            <!-- 鎼滅储琛ㄥ崟 -->
+            <el-form :inline="true">
+                <el-form-item label="渚涘簲鍟�">
+                    <el-input v-model="tableSearchParam.venName" placeholder="璇疯緭鍏ヤ緵搴斿晢鍚嶇О"></el-input>
+                </el-form-item>
+                <el-form-item label="鐗╂枡缂栫爜">
+                    <el-input v-model="tableSearchParam.invCode" placeholder="璇疯緭鍏ョ墿鏂欑紪鐮�"></el-input>
+                </el-form-item>
+                <el-form-item label="鐗╂枡鍚嶇О">
+                    <el-input v-model="tableSearchParam.invName" placeholder="璇疯緭鍏ョ墿鏂欏悕绉�"></el-input>
+                </el-form-item>
+                <el-form-item label="">
+                    <el-button type="primary" @click="search" circle>
+                        <el-icon>
+                            <Search />
+                        </el-icon>
+                    </el-button>
+                    <el-button @click="reset" circle style="margin-left: 10px">
+                        <el-icon>
+                            <Refresh />
+                        </el-icon>
+                    </el-button>
+                </el-form-item>
+            </el-form>
+
+            <!-- 宸ュ叿鏍� -->
+            <el-form :inline="true" style="display: none;">
+                <el-form-item label="">
+                    <el-button type="danger" @click="selectDelete">鍒犻櫎</el-button>
+                    <el-button type="success" @click="exportData">瀵煎嚭</el-button>
+                </el-form-item>
+            </el-form>
+
+            <!-- 鏁版嵁琛ㄦ牸 -->
+            <el-table :data="tableData" border style="width: 100%" @selection-change="handleSelectionChange"
+                max-height="550">
+                <el-table-column type="selection"></el-table-column>
+                <el-table-column type="index" width="50"></el-table-column>
+                <el-table-column prop="venName" label="渚涘簲鍟�" width="150"
+                    :show-overflow-tooltip="true"></el-table-column>
+                <el-table-column prop="invCode" label="鐗╂枡缂栫爜" width="120"
+                    :show-overflow-tooltip="true"></el-table-column>
+                <el-table-column prop="invName" label="鐗╂枡鍚嶇О" width="200"
+                    :show-overflow-tooltip="true"></el-table-column>
+                <el-table-column prop="invStd" label="瑙勬牸鍨嬪彿" width="150"
+                    :show-overflow-tooltip="true"></el-table-column>
+                <el-table-column prop="unit" label="鍗曚綅" width="80"></el-table-column>
+                <el-table-column prop="whName" label="浠撳簱鍚嶇О" width="120"></el-table-column>
+                <el-table-column prop="dateStart$" label="寮�宸ユ棩鏈�" width="120"></el-table-column>
+                <el-table-column prop="dateEnd$" label="瀹屾垚鏃ユ湡" width="120"></el-table-column>
+                <el-table-column prop="fqty" label="搴斿彂鏁伴噺" width="100">
+                    <template #default="scope">
+                        {{ scope.row.fqty || scope.row.qty || 0 }}
+                    </template>
+                </el-table-column>
+                <el-table-column prop="qqty" label="鏈熷垵鏁伴噺" width="100">
+                    <template #default="scope">
+                        {{ scope.row.qqty || 0 }}
+                    </template>
+                </el-table-column>
+                <el-table-column prop="yqty" label="宸插彂鏁伴噺" width="100">
+                    <template #default="scope">
+                        {{ scope.row.yqty || 0 }}
+                    </template>
+                </el-table-column>
+                <el-table-column prop="wqty" label="鏈彂鏁伴噺" width="100">
+                    <template #default="scope">
+                        {{ scope.row.wqty || 0 }}
+                    </template>
+                </el-table-column>
+                <el-table-column prop="outQty" label="宸插嚭搴撴暟閲�" width="110">
+                    <template #default="scope">
+                        <span :style="{ color: scope.row.outQty > 0 ? 'green' : 'gray' }">
+                            {{ scope.row.outQty || 0 }}
+                        </span>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="remainQty" label="鍓╀綑鏁伴噺" width="110">
+                    <template #default="scope">
+                        <span :style="{ color: scope.row.remainQty > 0 ? 'orange' : 'green' }">
+                            {{ scope.row.remainQty || 0 }}
+                        </span>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="isAllOut" label="鍑哄簱鐘舵��" width="100">
+                    <template #default="scope">
+                        <el-tag v-if="scope.row.isAllOut == 1" type="success">宸插畬鎴�</el-tag>
+                        <el-tag v-else type="warning">鏈畬鎴�</el-tag>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="izSync" label="鏄惁鍚屾" width="100">
+                    <template #default="scope">
+                        <el-tag v-if="scope.row.izSync == '鏄�'" type="success">宸插悓姝�</el-tag>
+                        <el-tag v-else type="info">鏈悓姝�</el-tag>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="izPrint" label="鏄惁鎵撳嵃" width="100">
+                    <template #default="scope">
+                        <el-tag v-if="scope.row.izPrint == '鏄�'" type="success">宸叉墦鍗�</el-tag>
+                        <el-tag v-else type="info">鏈墦鍗�</el-tag>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="syncTime$" label="鍚屾鏃堕棿" width="160"></el-table-column>
+                <el-table-column prop="createTime$" label="鍒涘缓鏃堕棿" width="160"></el-table-column>
+                <el-table-column prop="updateTime$" label="鏇存柊鏃堕棿" width="160"></el-table-column>
+            </el-table>
+
+            <!-- 鍒嗛〉 -->
+            <div style="margin-top: 10px">
+                <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
+                    :current-page="currentPage" :page-sizes="pageSizes" :page-size="pageSize"
+                    layout="total, sizes, prev, pager, next, jumper" :total="pageTotal">
+                </el-pagination>
+            </div>
+        </el-card>
+    </div>
+
+    <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
+    <script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
+    <script src="../../static/evn/vue.global.js"></script>
+    <script src="../../static/evn/element-plus.js"></script>
+    <script src="../../static/evn/icons-vue.js"></script>
+    <script type="module">
+        // 瀵煎叆涓枃璇█鍖�
+        import zhCn from '../../static/evn/zh-cn.js';
+
+        const { createApp, ref } = Vue;
+
+        const app = createApp({
+            setup() {
+                const currentPage = ref(1)
+                const pageSizes = ref([15, 20, 30, 50, 100, 200])
+                const pageSize = ref(15)
+                const pageTotal = ref(0)
+                const tableSearchParam = ref({
+                    venName: null,
+                    invCode: null,
+                    invName: null
+                })
+                const tableData = ref([])
+                const selectList = ref([])
+
+                function handleSelectionChange(selection) {
+                    selectList.value = selection
+                }
+
+                function handleSizeChange(val) {
+                    pageSize.value = val
+                    search()
+                }
+
+                function handleCurrentChange(val) {
+                    currentPage.value = val
+                    search()
+                }
+
+                function search() {
+                    const loading = ElementPlus.ElLoading.service({
+                        lock: true,
+                        text: 'Loading',
+                        background: 'rgba(0, 0, 0, 0.7)',
+                    })
+                    let data = JSON.parse(JSON.stringify(tableSearchParam.value))
+                    data.curr = currentPage.value
+                    data.limit = pageSize.value
+                    // 绉婚櫎绌哄��
+                    Object.keys(data).forEach(key => {
+                        if (data[key] === null || data[key] === '' || data[key] === undefined) {
+                            delete data[key]
+                        }
+                    })
+                    $.ajax({
+                        url: baseUrl + "/materialWwOut/list/auth",
+                        headers: { 'token': localStorage.getItem('token') },
+                        data: data,
+                        dataType: 'json',
+                        method: 'GET',
+                        success: function (res) {
+                            if (res.code == 200) {
+                                tableData.value = res.data.records || []
+                                pageTotal.value = res.data.total || 0
+                            } else if (res.code === 403) {
+                                top.location.href = baseUrl + "/";
+                            } else {
+                                ElementPlus.ElMessage({ message: res.msg, type: 'error' });
+                            }
+                        },
+                        complete: function () {
+                            loading.close()
+                        }
+                    });
+                }
+
+                function selectDelete() {
+                    if (selectList.value.length === 0) {
+                        ElementPlus.ElMessage({
+                            message: "璇峰厛閫夋嫨瑕佸垹闄ょ殑鏁版嵁",
+                            type: 'warning'
+                        });
+                        return;
+                    }
+                    ElementPlus.ElMessageBox.confirm('纭畾瑕佸垹闄ら�変腑鐨勬暟鎹悧?', '鎻愮ず', {
+                        confirmButtonText: '纭畾',
+                        cancelButtonText: '鍙栨秷',
+                        type: 'warning'
+                    }).then(() => {
+                        const loading = ElementPlus.ElLoading.service({
+                            lock: true,
+                            text: '鍒犻櫎涓�...',
+                            background: 'rgba(0, 0, 0, 0.7)',
+                        })
+                        $.ajax({
+                            url: baseUrl + "/materialWwOut/delete/auth",
+                            headers: { 'token': localStorage.getItem('token') },
+                            data: {
+                                param: JSON.stringify(selectList.value)
+                            },
+                            dataType: 'json',
+                            method: 'POST',
+                            success: function (res) {
+                                if (res.code == 200) {
+                                    ElementPlus.ElMessage({
+                                        message: "鍒犻櫎鎴愬姛",
+                                        type: 'success'
+                                    });
+                                    search()
+                                } else if (res.code === 403) {
+                                    top.location.href = baseUrl + "/";
+                                } else {
+                                    ElementPlus.ElMessage({ message: res.msg, type: 'error' });
+                                }
+                            },
+                            complete: function () {
+                                loading.close()
+                            }
+                        });
+                    }).catch(() => {
+                        // 鍙栨秷
+                    });
+                }
+
+                function reset() {
+                    tableSearchParam.value = {
+                        venName: null,
+                        invCode: null,
+                        invName: null
+                    }
+                    currentPage.value = 1
+                    search()
+                }
+
+                function exportData() {
+                    if (selectList.value.length === 0) {
+                        ElementPlus.ElMessage({
+                            message: "璇峰厛閫夋嫨瑕佸鍑虹殑鏁版嵁",
+                            type: 'warning'
+                        });
+                        return;
+                    }
+                    // 鏋勫缓瀵煎嚭鏁版嵁
+                    const exportData = selectList.value.map(item => ({
+                        venName: item.venName || '',
+                        invCode: item.invCode || '',
+                        invName: item.invName || '',
+                        invStd: item.invStd || '',
+                        unit: item.unit || '',
+                        whName: item.whName || '',
+                        dateStart: item.dateStart$ || '',
+                        dateEnd: item.dateEnd$ || '',
+                        fqty: item.fqty || item.qty || 0,
+                        qqty: item.qqty || 0,
+                        yqty: item.yqty || 0,
+                        wqty: item.wqty || 0,
+                        outQty: item.outQty || 0,
+                        remainQty: item.remainQty || 0,
+                        isAllOut: item.isAllOut == 1 ? '宸插畬鎴�' : '鏈畬鎴�',
+                        izSync: item.izSync || '鍚�',
+                        izPrint: item.izPrint || '鍚�',
+                        syncTime: item.syncTime$ || '',
+                        createTime: item.createTime$ || '',
+                        updateTime: item.updateTime$ || ''
+                    }));
+
+                    // 杞崲涓篊SV鏍煎紡
+                    const headers = ['渚涘簲鍟�', '鐗╂枡缂栫爜', '鐗╂枡鍚嶇О', '瑙勬牸鍨嬪彿', '鍗曚綅', '浠撳簱鍚嶇О', '寮�宸ユ棩鏈�', '瀹屾垚鏃ユ湡', '搴斿彂鏁伴噺', '鏈熷垵鏁伴噺', '宸插彂鏁伴噺', '鏈彂鏁伴噺', '宸插嚭搴撴暟閲�', '鍓╀綑鏁伴噺', '鍑哄簱鐘舵��', '鏄惁鍚屾', '鏄惁鎵撳嵃', '鍚屾鏃堕棿', '鍒涘缓鏃堕棿', '鏇存柊鏃堕棿'];
+                    const csvContent = [
+                        headers.join(','),
+                        ...exportData.map(row => [
+                            row.venName,
+                            row.invCode,
+                            row.invName,
+                            row.invStd,
+                            row.unit,
+                            row.whName,
+                            row.dateStart,
+                            row.dateEnd,
+                            row.fqty,
+                            row.qqty,
+                            row.yqty,
+                            row.wqty,
+                            row.outQty,
+                            row.remainQty,
+                            row.isAllOut,
+                            row.izSync,
+                            row.izPrint,
+                            row.syncTime,
+                            row.createTime,
+                            row.updateTime
+                        ].map(cell => `"${cell}"`).join(','))
+                    ].join('\n');
+
+                    // 涓嬭浇鏂囦欢
+                    const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8;' });
+                    const link = document.createElement('a');
+                    const url = URL.createObjectURL(blob);
+                    link.setAttribute('href', url);
+                    link.setAttribute('download', '濮斿鍔犲伐鍑哄簱鍗曟暟鎹甠' + new Date().getTime() + '.csv');
+                    link.style.visibility = 'hidden';
+                    document.body.appendChild(link);
+                    link.click();
+                    document.body.removeChild(link);
+
+                    ElementPlus.ElMessage({
+                        message: "瀵煎嚭鎴愬姛",
+                        type: 'success'
+                    });
+                }
+
+                // 鍒濆鍖栧姞杞�
+                search()
+
+                return {
+                    currentPage,
+                    pageSizes,
+                    pageSize,
+                    pageTotal,
+                    tableSearchParam,
+                    tableData,
+                    selectList,
+                    handleSelectionChange,
+                    handleSizeChange,
+                    handleCurrentChange,
+                    search,
+                    reset,
+                    selectDelete,
+                    exportData
+                }
+            }
+        })
+
+        // 閰嶇疆Element Plus涓枃璇█鍖�
+        app.use(ElementPlus, {
+            locale: zhCn
+        })
+        
+        // 娉ㄥ唽鎵�鏈夊浘鏍囩粍浠�
+        for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+            app.component(key, component)
+        }
+
+        app.mount('#app')
+    </script>
+</body>
+
+</html>
diff --git a/src/main/webapp/views/pda/materialWwOut.html b/src/main/webapp/views/pda/materialWwOut.html
new file mode 100644
index 0000000..75453ef
--- /dev/null
+++ b/src/main/webapp/views/pda/materialWwOut.html
@@ -0,0 +1,511 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>濮斿鍔犲伐鍑哄簱</title>
+    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
+    <link rel="stylesheet" href="../../static/css/pda.css" media="all">
+    <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>
+</head>
+<style>
+    .form-box span {
+        font-size: 16px;
+        display: inline-block;
+        text-align: right;
+    }
+    .form-box input {
+        width: 165px;
+        padding-left: 5px;
+        height: 30px;
+        border: 1px solid #777777;
+        overflow:hidden;
+        white-space:nowrap;
+        text-overflow:ellipsis;
+    }
+    .number-tool {
+        margin-left: 10px;
+        padding: 1px 0 1px 5px;
+        display: inline-block;
+        width: 120px;
+    }
+
+    .number-tool:after {
+        clear: both;
+        content: "";
+        display: table;
+    }
+
+    .number-tool button {
+        background-color: #fff;
+        margin-top: 3px;
+        font-size: 16px;
+        height: 25px;
+        float: left;
+        width: 25px;
+        border: 1px solid #777777;
+    }
+
+    .number-tool input {
+        text-align: center;
+        height: 30px;
+        float: left;
+        margin: 0 5px;
+        min-width: 50px;
+        width: auto;
+        padding: 0 5px;
+        box-sizing: border-box;
+    }
+</style>
+<body>
+
+<header class="layui-form">
+    <div class="layui-input-inline">
+        <label class="layui-form-label">渚涘簲鍟�</label>
+        <input class="layui-input" id="venName" onkeyup="findCode(this, 'venName')" placeholder="鎵爜 / 杈撳叆"
+               style="width: 175px"
+               autocomplete="off">
+    </div>
+    <div class="layui-input-inline">
+        <label class="layui-form-label">鐗╂枡缂栫爜</label>
+        <input class="layui-input" id="invCode" onkeyup="findCode(this, 'invCode')" placeholder="鎵爜 / 杈撳叆"
+               style="width: 175px"
+               autocomplete="off">
+    </div>
+</header>
+
+<main>
+    <table class="layui-table" id="materialWwOut" lay-filter="materialWwOut"></table>
+</main>
+
+<footer>
+    <div class="layui-btn-container">
+        <button type="button" id="reset-btn" class="layui-btn layui-btn-primary" onclick="reset()">閲嶇疆</button>
+        <button type="button" id="out-btn" class="layui-btn layui-btn-normal " onclick="materialWwOut()"
+                style="margin-left: 20px">鍑哄簱
+        </button>
+        <button type="button" id="retrun-btn" class="layui-btn layui-btn-primary " onclick="back()"
+                style="margin-left: 20px">杩斿洖
+        </button>
+        <span id="tips"></span>
+    </div>
+</footer>
+
+<!-- 淇敼鏁伴噺寮圭獥 -->
+<div id="modify" style="display: none; padding-top: 10px; text-align: center;">
+    <div class="form-box">
+        <div class="form-item">
+            <table style="display: inline">
+                <tr>
+                    <td>
+                        <span style="width: 35px; margin-right: 5px">缂栫爜</span>
+                    </td>
+                    <td style="text-align: left">
+                        <input id="invCode2" type="text" disabled="disabled">
+                    </td>
+                </tr>
+            </table>
+        </div>
+        <div class="form-item">
+            <table style="display: inline">
+                <tr>
+                    <td style="vertical-align: top">
+                        <span style="width: 35px; margin-right: 5px">鍚嶇О</span>
+                    </td>
+                    <td style="text-align: left">
+                    <textarea rows="3" style="resize: none; width: 165px" id="invName2" type="text" disabled="disabled"
+                              readonly="readonly"></textarea>
+                    </td>
+                </tr>
+            </table>
+        </div>
+    </div>
+    <input id="index" type="text" disabled="disabled" style="display: none;">
+    <div class="form-item" style="margin-top: 5px; margin-bottom: 8px;">
+        <span style="vertical-align: middle">鏁伴噺</span>
+        <div class="number-tool" style="vertical-align: middle">
+            <button onclick="reduce()">-</button>
+            <input id="outQtyInput" type="number" onchange="fix(this)">
+            <button onclick="add()">+</button>
+        </div>
+    </div>
+    <button id="remove" onclick="remove()">绉婚櫎</button>
+    <button id="confirm" onclick="confirm()">淇濆瓨</button>
+</div>
+
+</body>
+<script>
+    var countLayer;
+    // 褰撳墠鐐瑰嚮鐗╂枡鐨勬渶澶у墿浣欐暟閲�
+    var maxRemainQty;
+    // 琛ㄦ牸鏁版嵁
+    var materialWwOutList = [];
+    window.onload = function () {
+        document.getElementById("venName").focus();
+    }
+
+    /**
+     * 鎻愮ず淇℃伅
+     * @param msg 鎻愮ず鍐呭
+     * @param warn true锛氱孩鑹插瓧浣�
+     */
+    function tips(msg, warn) {
+        layer.msg(msg, {icon: warn ? 2 : 1})
+    }
+
+    function back() {
+        parent.backIndex();
+    }
+
+    var tableIns;
+    layui.use(['table', 'form'], function () {
+        var table = layui.table;
+        var $ = layui.jquery;
+        var layer = layui.layer;
+        var form = layui.form;
+
+        tableIns = table.render({
+            id: 'materialWwOut',
+            elem: '#materialWwOut',
+            data: [],
+            limit: 500,
+            cellMinWidth: 50,
+            cols: [[
+                {field: 'invCode', align: 'center', title: '缂栫爜', event: 'detail', width: 80},
+                {field: 'venName', align: 'center', title: '渚涘簲鍟�', event: 'detail', width: 100},
+                {field: 'invName', align: 'center', title: '鍚嶇О', event: 'detail'},
+                {field: 'whName', align: 'center', title: '搴撳尯', event: 'detail', width: 50},
+                {
+                    field: 'remainQty',
+                    align: 'center',
+                    title: '鏁伴噺',
+                    event: 'modify',
+                    style: 'cursor: pointer;color: blue',
+                    width: 80,
+                    templet: function(d) {
+                        // 鏄剧ず鍑哄簱鏁伴噺锛堝鏋滃凡淇敼锛夋垨鍓╀綑鏁伴噺
+                        // 浼樺厛鏄剧ず淇敼鍚庣殑鍑哄簱鏁伴噺锛屽鏋滄病鏈変慨鏀瑰垯鏄剧ず鍓╀綑鏁伴噺
+                        var qty = (d.outQtyOut !== undefined && d.outQtyOut !== null) ? d.outQtyOut : (d.remainQty || 0);
+                        // 鏍煎紡鍖栨暟瀛楁樉绀猴紝淇濈暀閫傚綋鐨勫皬鏁颁綅鏁�
+                        if (typeof qty === 'number' || (typeof qty === 'string' && qty.indexOf('.') !== -1)) {
+                            return parseFloat(qty).toString();
+                        }
+                        return qty;
+                    }
+                },
+                {type: 'checkbox', fixed: 'right', width: 30},
+            ]],
+            done: function (res, curr, count) {
+            }
+        });
+
+        // 鐩戝惉琛屽伐鍏蜂簨浠�
+        table.on('tool(materialWwOut)', function (obj) {
+            var data = obj.data;
+            switch (obj.event) {
+                case 'modify':
+                    countLayer = layer.open({
+                        type: 1,
+                        offset: '20px',
+                        title: '淇敼鏁伴噺',
+                        shadeClose: true,
+                        area: ['80%', '240px'],
+                        content: $("#modify"),
+                        success: function (layero, index) {
+                            $('#invCode2').val(data.invCode);
+                            $('#invName2').val(data.invName);
+                            $('#index').val(data.id);
+                            // 鏄剧ず褰撳墠鍑哄簱鏁伴噺锛堝鏋滃凡淇敼锛夋垨鍓╀綑鏁伴噺
+                            var currentOutQty = (data.outQtyOut !== undefined && data.outQtyOut !== null) ? data.outQtyOut : (data.remainQty || 0);
+                            $('#outQtyInput').val(currentOutQty);
+                            maxRemainQty = parseFloat(data.remainQty) || 0;
+                            // 鏍规嵁鏁板瓧闀垮害璋冩暣杈撳叆妗嗗搴�
+                            adjustInputWidth($('#outQtyInput'));
+                            // 鐩戝惉杈撳叆鍙樺寲锛屽姩鎬佽皟鏁村搴�
+                            $('#outQtyInput').off('input').on('input', function() {
+                                adjustInputWidth($(this));
+                            });
+                        }
+                    });
+                    break;
+            }
+        });
+    });
+
+    var venNameBar;
+    var invCodeBar;
+
+    /* 鎵爜銆佽緭鍏ヤ緵搴斿晢鍜岀墿鏂欑紪鐮� */
+    function findCode(el, type) {
+        venNameBar = $("#venName").val();
+        invCodeBar = $("#invCode").val();
+        
+        // 鍘婚櫎绌烘牸
+        if (venNameBar) {
+            venNameBar = venNameBar.trim();
+        }
+        if (invCodeBar) {
+            invCodeBar = invCodeBar.trim();
+        }
+        
+        switch (type) {
+            case 'venName':
+                break;
+            case 'invCode':
+                break;
+            default:
+                break;
+        }
+
+        // 鏋勫缓鏌ヨ鍙傛暟
+        var params = {};
+        if (venNameBar) {
+            params.venName = venNameBar;
+        }
+        if (invCodeBar) {
+            params.invCode = invCodeBar;
+        }
+
+        // 濡傛灉鎵�鏈夋煡璇㈡潯浠堕兘涓虹┖锛屼笉鎵ц鏌ヨ
+        if (!venNameBar && !invCodeBar) {
+            // 娓呯┖琛ㄦ牸鏁版嵁
+            tableIns.reload({
+                data: [],
+            });
+            materialWwOutList = [];
+            return;
+        }
+
+        // PDA鍑哄簱鏌ヨ锛屾坊鍔爌daQuery鍙傛暟锛屽悗绔細杩囨护鎺夊凡鍏ㄩ儴鍑哄簱鐨勭墿鏂�
+        params.pdaQuery = true;
+        
+        $.ajax({
+            url: baseUrl + "/materialWwOut/list/auth",
+            headers: {'token': localStorage.getItem('token')},
+            data: params,
+            method: 'GET',
+            async: false,
+            success: function (res) {
+                if (res && res.code === 200) {
+                    var records = [];
+                    if (res.data && res.data.records && res.data.records.length > 0) {
+                        records = res.data.records;
+                    } else if (res.data && Array.isArray(res.data)) {
+                        records = res.data;
+                    }
+                    // 鍒濆鍖栧嚭搴撴暟閲忓瓧娈碉紙鍒濆绛変簬鍓╀綑鏁伴噺锛岀敤鎴峰彲浠ヤ慨鏀癸級
+                    records.map(function (item) {
+                        // 濡傛灉杩樻病鏈夎缃嚭搴撴暟閲忥紝鍒欏垵濮嬪寲涓哄墿浣欐暟閲�
+                        if (item.outQtyOut === undefined || item.outQtyOut === null) {
+                            item.outQtyOut = item.remainQty || 0;
+                        }
+                    });
+                    tableIns.reload({
+                        data: records,
+                    });
+                    materialWwOutList = records;
+                } else if (res && res.code === 403) {
+                    top.location.href = baseUrl + "/pda";
+                } else if (res && res.msg) {
+                    tips(res.msg, true)
+                } else {
+                    tips("鏌ヨ澶辫触锛岃绋嶅悗閲嶈瘯", true);
+                }
+            },
+            error: function(xhr, status, error) {
+                console.error("鏌ヨ澶辫触:", status, error);
+                tips("鏌ヨ澶辫触锛岃绋嶅悗閲嶈瘯", true);
+            }
+        });
+    }
+
+    /* 淇敼鏁伴噺 */
+    var countDom = $('#outQtyInput');
+
+    function add() {
+        if (Number(countDom.val()) >= maxRemainQty) {
+            return;
+        }
+        countDom.val(Number(countDom.val()) + 1);
+        // 璋冩暣杈撳叆妗嗗搴�
+        adjustInputWidth(countDom);
+    }
+
+    function reduce() {
+        if (Number(countDom.val()) <= 0) {
+            return;
+        }
+        countDom.val(Number(countDom.val()) - 1);
+        // 璋冩暣杈撳叆妗嗗搴�
+        adjustInputWidth(countDom);
+    }
+
+    function fix(e) {
+        var val = Number(e.value) || 0;
+        if (val > maxRemainQty) {
+            countDom.val(maxRemainQty);
+        }
+        // 璋冩暣杈撳叆妗嗗搴�
+        adjustInputWidth($(e));
+    }
+    
+    /**
+     * 鏍规嵁鏁板瓧闀垮害鍔ㄦ�佽皟鏁磋緭鍏ユ瀹藉害
+     * @param $input jQuery瀵硅薄锛岃緭鍏ユ鍏冪礌
+     */
+    function adjustInputWidth($input) {
+        if (!$input || $input.length === 0) {
+            return;
+        }
+        var value = $input.val() || '';
+        var valueStr = value.toString();
+        
+        // 璁$畻鏂囨湰瀹藉害锛堟瘡涓瓧绗︾害8-10px锛屽皬鏁扮偣鍜屽皬鏁颁綅闇�瑕侀澶栫┖闂达級
+        // 鏈�灏忓搴�50px锛屾渶澶у搴�150px
+        var minWidth = 50;
+        var maxWidth = 150;
+        var charWidth = 10; // 姣忎釜瀛楃澶х害10px
+        var padding = 10; // 宸﹀彸鍐呰竟璺�
+        
+        // 璁$畻闇�瑕佺殑瀹藉害锛氬瓧绗︽暟 * 瀛楃瀹藉害 + 鍐呰竟璺�
+        var calculatedWidth = valueStr.length * charWidth + padding;
+        
+        // 纭繚瀹藉害鍦ㄦ渶灏忓拰鏈�澶ц寖鍥村唴
+        var finalWidth = Math.max(minWidth, Math.min(maxWidth, calculatedWidth));
+        
+        $input.css('width', finalWidth + 'px');
+    }
+
+    function remove() {
+        var invCode = $('#invCode2').val();
+        var id = $('#index').val();
+        for (var j = 0; j < materialWwOutList.length; j++) {
+            if (invCode === materialWwOutList[j].invCode && id == materialWwOutList[j].id) {
+                materialWwOutList.splice(j, 1);
+            }
+        }
+        tableIns.reload({data: materialWwOutList});
+        layer.close(countLayer);
+        tips("绉婚櫎鎴愬姛");
+    }
+
+    // 淇敼鏁伴噺
+    function confirm() {
+        var invCode = $('#invCode2').val();
+        var outQty = parseFloat($('#outQtyInput').val()) || 0;
+        var id = $('#index').val();
+        
+        if (outQty < 0) {
+            tips("鏁伴噺涓嶈兘灏忎簬0", true);
+            return;
+        }
+        
+        if (outQty > maxRemainQty) {
+            tips("鏁伴噺涓嶈兘瓒呰繃鍓╀綑鏁伴噺", true);
+            return;
+        }
+        
+        // 鏇存柊琛ㄦ牸涓殑鍑哄簱鏁伴噺
+        for (var j = 0; j < materialWwOutList.length; j++) {
+            if (invCode === materialWwOutList[j].invCode && id == materialWwOutList[j].id) {
+                materialWwOutList[j].outQtyOut = outQty;
+            }
+        }
+        tableIns.reload({data: materialWwOutList});
+        layer.close(countLayer);
+        tips("淇敼鎴愬姛");
+    }
+
+    /* 濮斿鍔犲伐鍑哄簱 */
+    function materialWwOut() {
+        var table = layui.table;
+        var checkStatus = table.checkStatus('materialWwOut');
+        var data = checkStatus.data;
+        if (data.length == 0) {
+            layer.msg("璇烽�夋嫨鐗╂枡!");
+            return;
+        }
+        
+        // 鎵归噺鍑哄簱
+        var outQtyList = [];
+        for (var i = 0; i < data.length; i++) {
+            var item = data[i];
+            // 浣跨敤淇敼鍚庣殑鍑哄簱鏁伴噺锛坥utQtyOut锛夛紝濡傛灉娌℃湁淇敼鍒欎娇鐢ㄥ墿浣欐暟閲�
+            var outQty = 0;
+            if (item.outQtyOut !== undefined && item.outQtyOut !== null) {
+                outQty = parseFloat(item.outQtyOut) || 0;
+            } else {
+                outQty = parseFloat(item.remainQty) || 0;
+            }
+            
+            if (outQty <= 0) {
+                tips("鐗╂枡 " + item.invCode + " 鍑哄簱鏁伴噺蹇呴』澶т簬0", true);
+                return;
+            }
+            var remainQty = parseFloat(item.remainQty) || 0;
+            if (outQty > remainQty) {
+                tips("鐗╂枡 " + item.invCode + " 鍑哄簱鏁伴噺涓嶈兘瓒呰繃鍓╀綑鏁伴噺", true);
+                return;
+            }
+            outQtyList.push({
+                id: item.id,
+                outQty: outQty
+            });
+        }
+        
+        // 纭鍑哄簱
+        layer.confirm('纭畾瑕佸嚭搴撻�変腑鐨勭墿鏂欏悧锛�', {icon: 3, title: '鎻愮ず'}, function(index){
+            // 鎵归噺鏇存柊鍑哄簱鏁伴噺
+            var successCount = 0;
+            var failCount = 0;
+            for (var i = 0; i < outQtyList.length; i++) {
+                $.ajax({
+                    url: baseUrl + "/materialWwOut/updateOutQty/auth",
+                    headers: {'token': localStorage.getItem('token')},
+                    data: JSON.stringify(outQtyList[i]),
+                    contentType: 'application/json;charset=UTF-8',
+                    method: 'POST',
+                    async: false,
+                    success: function (res) {
+                        if (res && res.code === 200) {
+                            successCount++;
+                        } else {
+                            failCount++;
+                        }
+                    },
+                    error: function(xhr, status, error) {
+                        console.error("鍑哄簱澶辫触:", status, error);
+                        failCount++;
+                    }
+                });
+            }
+            
+            if (successCount > 0) {
+                tips("鎴愬姛鍑哄簱 " + successCount + " 鏉¤褰�");
+                // 娓呯┖杈撳叆妗嗗苟鍒锋柊鍒楄〃
+                $("#venName").val("");
+                $("#invCode").val("");
+                materialWwOutList = [];
+                tableIns.reload({data: materialWwOutList});
+                document.getElementById("venName").focus();
+            }
+            if (failCount > 0) {
+                tips("鍑哄簱澶辫触 " + failCount + " 鏉¤褰�", true);
+            }
+            
+            layer.close(index);
+        });
+    }
+
+    function reset() {
+        $("#venName").val(null);
+        $("#invCode").val(null);
+        materialWwOutList = [];
+        tableIns.reload({data: materialWwOutList});
+        layer.closeAll();
+        document.getElementById("venName").focus();
+    }
+</script>
+</html>

--
Gitblit v1.9.1