From cefe93f0197d675b19fe68d6758aabb010c3fbb0 Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期五, 06 二月 2026 17:30:03 +0800
Subject: [PATCH] 添加计算库存总和功能

---
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IStockService/IStockDetailByMaterielService.cs                 |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockDetailByMaterielController.cs |    9 +
 项目代码/WIDESEA_WMSClient/src/extension/stock/extend/CalculateStock.vue                                  |  250 +++++++++++++++++++++++++++++++++++++++++
 项目代码/WIDESEA_WMSClient/src/views/outbound/outPicking.vue                                              |    4 
 项目代码/WIDESEA_WMSClient/config/buttons.js                                                              |    8 +
 项目代码/WIDESEA_WMSClient/src/extension/stock/stockInfoDetailByMaterielSum.js                            |   13 +
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_StockService/StockDetailByMaterielService.cs                   |   26 +++
 7 files changed, 303 insertions(+), 9 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/config/buttons.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/config/buttons.js"
index 53cdeef..ca34800 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/config/buttons.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/config/buttons.js"
@@ -347,6 +347,14 @@
     type: 'warning',
     onClick: function () {
     }
+},{
+    name: "璁$畻搴撳瓨鎬诲拰",
+    icon: '',
+    class: '',
+    value: 'CalculateStock',
+    type: 'warning',
+    onClick: function () {
+    }
 }
 ]
 
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/extend/CalculateStock.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/extend/CalculateStock.vue"
new file mode 100644
index 0000000..cb6382b
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/extend/CalculateStock.vue"
@@ -0,0 +1,250 @@
+<template>
+    <vol-box v-model="show" title="鐗╂枡搴撳瓨鏌ヨ" :width="800" :height="600">
+        <template #content>
+            <el-form ref="form" :model="form" :rules="rules" label-width="90px">
+                <!-- 浠撳簱鍙疯緭鍏ユ -->
+                <el-form-item label="浠撳簱鍙�:" prop="warehouseCode">
+                    <el-input 
+                        v-model="form.warehouseCode" 
+                        placeholder="璇疯緭鍏ヤ粨搴撳彿锛堝锛�5053锛�" 
+                        clearable
+                        @input="handleWarehouseInput"
+                        @keyup.enter="focusMaterielInput"
+                        ref="warehouseCodeInput"
+                        :disabled="loading"
+                    />
+                </el-form-item>
+
+                <!-- 鐗╂枡鏉$爜杈撳叆妗� -->
+                <el-form-item label="鐗╂枡鏉$爜:" prop="materielBarcode">
+                    <el-input 
+                        v-model="form.materielBarcode" 
+                        placeholder="璇锋壂鎻�/杈撳叆鐗╂枡鏉$爜锛堝锛�100401-01211锛�" 
+                        @keyup.enter="getStockTotal" 
+                        clearable
+                        @paste="handlePaste" 
+                        @input="handleInput" 
+                        ref="materielCodeInput"
+                        :disabled="loading"
+                    />
+                    <!-- 搴撳瓨鏌ヨ鍔犺浇鐘舵�� -->
+                    <el-icon class="ml-2" v-if="loading"><loading /></el-icon>
+                </el-form-item>
+
+                <!-- 搴撳瓨鎬诲拰鏄剧ず鍖哄煙 -->
+                <el-form-item label="搴撳瓨鎬诲拰:" prop="totalStockQuantity">
+                    <el-input 
+                        v-model="form.totalStockQuantity" 
+                        placeholder="璇疯緭鍏ヤ粨搴撳彿鍜岀墿鏂欐潯鐮佹煡璇�" 
+                        disabled
+                        prefix-icon="el-icon-s-data"
+                    />
+                    <!-- 鏃犳暟鎹彁绀� -->
+                    <span v-if="form.totalStockQuantity === 0 && !loading && form.materielBarcode && form.warehouseCode" class="text-gray-500 ml-2">
+                        璇ョ墿鏂欏湪褰撳墠浠撳簱鏆傛棤搴撳瓨
+                    </span>
+                </el-form-item>
+            </el-form>
+        </template>
+
+        <template #footer>
+            <div class="dialog-footer">
+                <el-button @click="resetForm">閲嶇疆</el-button>
+                <el-button @click="show = false">鍏抽棴</el-button>
+            </div>
+        </template>
+    </vol-box>
+</template>
+  
+<script>
+import VolBox from '@/components/basic/VolBox.vue'
+import { Loading } from '@element-plus/icons-vue' 
+
+export default {
+    components: { VolBox, Loading },
+    props: {
+        value: { type: Boolean, default: false }
+    },
+    data() {
+        // 浠撳簱鍙烽獙璇佽鍒�
+        const validateWarehouseCode = (rule, value, callback) => {
+            if (!value) {
+                return callback(new Error('璇疯緭鍏ヤ粨搴撳彿'));
+            }
+            callback();
+        };
+
+        // 鐗╂枡鏉$爜楠岃瘉瑙勫垯
+        const validateMaterielBarcode = (rule, value, callback) => {
+            if (!value) {
+                return callback(new Error('璇疯緭鍏ョ墿鏂欐潯鐮�'));
+            }
+            callback();
+        };
+
+        return {
+            show: false,
+            loading: false, // 搴撳瓨鏌ヨ鍔犺浇鐘舵��
+            form: {
+                warehouseCode: '', // 浠撳簱鍙�
+                materielBarcode: '', // 鐗╂枡鏉$爜
+                totalStockQuantity: 0 // 搴撳瓨鎬诲拰
+            },
+            // 琛ㄥ崟楠岃瘉瑙勫垯
+            rules: {
+                warehouseCode: [
+                    { validator: validateWarehouseCode, trigger: ['blur', 'change'] }
+                ],
+                materielBarcode: [
+                    { validator: validateMaterielBarcode, trigger: ['blur', 'change'] }
+                ]
+            }
+        }
+    },
+    methods: {
+        // 鎵撳紑寮圭獥鍒濆鍖�
+        open() {
+            this.show = true
+            this.$nextTick(() => {
+                this.focusWarehouseInput()
+            })
+        },
+        async getStockTotal() {
+            // 琛ㄥ崟楠岃瘉
+            try {
+                await this.$refs.form.validate();
+            } catch (error) {
+                if (!this.form.warehouseCode) {
+                    this.focusWarehouseInput();
+                } else {
+                    this.focusAndSelectInput();
+                }
+                return;
+            }
+
+            this.loading = true;
+            try {
+                const res = await this.http.post('/api/StockDetailByMateriel/CalculateStock?warehouseCode=' + this.form.warehouseCode.trim() + '&materielCode=' + this.form.materielBarcode.trim());
+                if (res.status && res.code === 0) {
+                    this.form.totalStockQuantity = Number(res.data) || 0;
+                    this.$message.success('搴撳瓨鏌ヨ鎴愬姛');
+                } else {
+                    this.form.totalStockQuantity = 0;
+                    this.$message.error(res.message || '搴撳瓨鏌ヨ澶辫触锛氭帴鍙h繑鍥炲紓甯�');
+                }
+            } catch (error) {
+                this.form.totalStockQuantity = 0;
+                const errorMsg = error.response 
+                    ? `鎺ュ彛閿欒锛�${error.response.status} - ${error.response.data?.message || '鏈煡閿欒'}`
+                    : `缃戠粶寮傚父锛�${error.message}`;
+                this.$message.error(`搴撳瓨鏌ヨ澶辫触锛�${errorMsg}`);
+            } finally {
+                this.loading = false;
+            }
+        },
+
+        // 浠撳簱鍙疯緭鍏ヨ繃婊�
+        handleWarehouseInput(value) {
+            this.form.warehouseCode = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase();
+            this.$nextTick(() => {
+                this.$refs.form.validateField('warehouseCode');
+            });
+        },
+
+        // 鐗╂枡鏉$爜杈撳叆杩囨护
+        handleInput(value) {
+            this.form.materielBarcode = value.replace(/[^-a-zA-Z0-9]/g, '');
+            this.$nextTick(() => {
+                this.$refs.form.validateField('materielBarcode');
+            });
+        },
+
+        // 绮樿创鐗╂枡鏉$爜鑷姩鏌ヨ
+        handlePaste(e) {
+            const clipboardData = e.clipboardData || window.clipboardData;
+            const pastedText = clipboardData.getData('text');
+            const cleanedText = pastedText.replace(/[^-a-zA-Z0-9]/g, '');
+            if (cleanedText) {
+                this.form.materielBarcode = cleanedText;
+                setTimeout(() => {
+                    this.getStockTotal();
+                }, 50);
+            }
+            e.preventDefault();
+        },
+
+        // 浠撳簱鍙峰洖杞﹁仛鐒︾墿鏂欐潯鐮�
+        focusMaterielInput() {
+            this.$nextTick(() => {
+                const inputRef = this.$refs.materielCodeInput;
+                if (inputRef) {
+                    const inputEl = inputRef.$el ? inputRef.$el.querySelector('input') : inputRef;
+                    inputEl?.focus();
+                }
+            });
+        },
+
+        // 鑱氱劍浠撳簱鍙疯緭鍏ユ
+        focusWarehouseInput() {
+            this.$nextTick(() => {
+                const inputRef = this.$refs.warehouseCodeInput;
+                if (inputRef) {
+                    const inputEl = inputRef.$el ? inputRef.$el.querySelector('input') : inputRef;
+                    inputEl?.focus();
+                }
+            });
+        },
+
+        // 鑱氱劍骞堕�変腑鐗╂枡鏉$爜杈撳叆妗�
+        focusAndSelectInput() {
+            this.$nextTick(() => {
+                setTimeout(() => {
+                    const inputRef = this.$refs.materielCodeInput;
+                    if (inputRef) {
+                        const inputEl = inputRef.$el ? inputRef.$el.querySelector('input') : inputRef;
+                        if (inputEl) {
+                            inputEl.focus();
+                            inputEl.select();
+                        }
+                    }
+                }, 100);
+            });
+        },
+
+        // 閲嶇疆琛ㄥ崟
+        resetForm() {
+            this.form = {
+                warehouseCode: '',
+                materielBarcode: '',
+                totalStockQuantity: 0
+            };
+            this.$refs.form.clearValidate();
+            this.focusWarehouseInput();
+        }
+    },
+    watch: {
+        show(val) {
+            if (val) {
+                this.$nextTick(() => {
+                    this.focusWarehouseInput()
+                })
+            } else {
+                this.resetForm();
+            }
+        }
+    }
+}
+</script>
+  
+<style scoped>
+.dialog-footer {
+    text-align: right;
+}
+.text-gray-500 {
+    color: #909399;
+    font-size: 12px;
+}
+.ml-2 {
+    margin-left: 8px;
+}
+</style>
\ No newline at end of file
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockInfoDetailByMaterielSum.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockInfoDetailByMaterielSum.js"
index 2d89d3f..b5d5ead 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockInfoDetailByMaterielSum.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockInfoDetailByMaterielSum.js"
@@ -1,10 +1,10 @@
 
 //姝s鏂囦欢鏄敤鏉ヨ嚜瀹氫箟鎵╁睍涓氬姟浠g爜锛屽彲浠ユ墿灞曚竴浜涜嚜瀹氫箟椤甸潰鎴栬�呴噸鏂伴厤缃敓鎴愮殑浠g爜
-
+import gridHeader from "./extend/CalculateStock.vue";
 let extension = {
     components: {
       //鏌ヨ鐣岄潰鎵╁睍缁勪欢
-      gridHeader: '',
+      gridHeader: gridHeader,
       gridBody: '',
       gridFooter: '',
       //鏂板缓銆佺紪杈戝脊鍑烘鎵╁睍缁勪欢
@@ -17,7 +17,14 @@
     methods: {
        //涓嬮潰杩欎簺鏂规硶鍙互淇濈暀涔熷彲浠ュ垹闄�
       onInit() {  
-        console.log(this)
+        var EmptyTrayInboundBtn = this.buttons.find(
+        (x) => x.value == "CalculateStock"
+      );
+      if (EmptyTrayInboundBtn != null) {
+        EmptyTrayInboundBtn.onClick = () => {
+          this.$refs.gridHeader.open();
+        };
+      }
       },
       onInited() {
         //妗嗘灦鍒濆鍖栭厤缃悗
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
index 14cef75..5a5d03a 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
@@ -9,6 +9,8 @@
                     <i class="el-icon-document"></i>
                     <span class="order-label">璁㈠崟鍙凤細</span>
                     <span class="order-value">{{ orderNo }}</span>
+                    <span class="order-label" style="margin-left: 20px;">浜х嚎鍚嶇О锛�</span>
+                    <span class="order-value">{{ orderInfo?.departmentName || '' }}</span>
                 </div>
                 <div class="order-status">
                     <el-tag v-if="orderInfo" :type="getStatusType(orderInfo.orderStatus)" size="medium"
@@ -656,7 +658,6 @@
             this.pickedTotal = this.pickedCount
         },
 
-        // ============== 寰皟锛氭柊澧炶幏鍙栬鍗曞彿閫昏緫锛屽叾浣欎笉鍙� ==============
         handlePalletScan(flag = true) {
             const palletCode = this.scanForm.palletCode.trim();
             if (!palletCode) {
@@ -673,7 +674,6 @@
                 this.loadPalletData(flag);
             });
         },
-        // ============== 寰皟缁撴潫 ==============
 
         handleMaterialScan() {
             if (!this.scanForm.palletCode) {
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IStockService/IStockDetailByMaterielService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IStockService/IStockDetailByMaterielService.cs"
index d7838cc..40e9574 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IStockService/IStockDetailByMaterielService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IStockService/IStockDetailByMaterielService.cs"
@@ -14,5 +14,7 @@
     public interface IStockDetailByMaterielService : IDependency
     {
         PageGridData<StockDetailByMateriel> GetPageGridData(PageDataOptions options);
+
+        WebResponseContent CalculateStock(string warehouseCode, string materielCode);
     }
 }
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_StockService/StockDetailByMaterielService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_StockService/StockDetailByMaterielService.cs"
index 7ca9282..385eed4 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_StockService/StockDetailByMaterielService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_StockService/StockDetailByMaterielService.cs"
@@ -18,11 +18,13 @@
     {
         private readonly IUnitOfWorkManage _unitOfWorkManage;
         private readonly SqlSugarClient _dbBase;
+        private readonly IRepository<Dt_StockInfoDetail> _stockInfoDetailRepository;
 
-        public StockDetailByMaterielService(IUnitOfWorkManage unitOfWorkManage)
+        public StockDetailByMaterielService(IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository)
         {
             _unitOfWorkManage = unitOfWorkManage;
             _dbBase = unitOfWorkManage.GetDbClient();
+            _stockInfoDetailRepository = stockInfoDetailRepository;
         }
 
 
@@ -146,7 +148,12 @@
                     }
                 }
 
-                
+                decimal totalStockQuantity = 0;
+                if (groupedData.Count > 0)
+                {
+                    totalStockQuantity = groupedData.Values.Sum(x => x.StockQuantity);
+                }
+
                 materielnfoStatistics = groupedData.Values.ToList();
                 int startIndex = (options.Page - 1) * options.Rows;
                 int endIndex = Math.Min(startIndex + options.Rows, materielnfoStatistics.Count);
@@ -160,12 +167,25 @@
                 }
 
                 int count = groupedData.Count;
-                return new PageGridData<StockDetailByMateriel>(count, materielnfoStatistics);
+                return new PageGridData<StockDetailByMateriel>(count, materielnfoStatistics)
+                {
+                    TotalStockQuantity = totalStockQuantity 
+                };
             }
             catch (Exception ex)
             {
                 return new PageGridData<StockDetailByMateriel>();
             }
         }
+
+        public WebResponseContent CalculateStock(string warehouseCode,string materielCode)
+        {
+           var calculateStock =_stockInfoDetailRepository.QueryData(x => x.WarehouseCode == warehouseCode && x.MaterielCode == materielCode).Sum(x => x.StockQuantity);
+           if(calculateStock == 0)
+            {
+                return WebResponseContent.Instance.Error("鏈壘鍒板簱瀛�");
+            }
+            return WebResponseContent.Instance.OK(data: calculateStock);
+        }
     }
 }
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockDetailByMaterielController.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockDetailByMaterielController.cs"
index 27e5858..fd3c85f 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockDetailByMaterielController.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockDetailByMaterielController.cs"
@@ -1,4 +1,5 @@
-锘縰sing Microsoft.AspNetCore.Authorization;
+锘縰sing Autofac.Core;
+using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using WIDESEA_Core;
 using WIDESEA_DTO.Stock;
@@ -22,5 +23,11 @@
         {
             return _stockDetailByMaterielService.GetPageGridData(options);
         }
+
+        [HttpPost, Route("CalculateStock"), AllowAnonymous]
+        public WebResponseContent CalculateStock(string warehouseCode,string materielCode)
+        {
+            return _stockDetailByMaterielService.CalculateStock(warehouseCode,materielCode);
+        }
     }
 }

--
Gitblit v1.9.3