From 6f0ffcf4a6e75ac3a76c6cfd75e02de3a17d46e3 Mon Sep 17 00:00:00 2001
From: 647556386 <647556386@qq.com>
Date: 星期二, 31 三月 2026 10:05:32 +0800
Subject: [PATCH] 同库区移库

---
 项目代码/WIDESEA_WMSClient/src/extension/stock/stockView.js                                 |  311 ++++++++++++++-------------
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs          |  134 ++++++++++++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs               |   14 -
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs              |    1 
 项目代码/WIDESEA_WMSClient/config/buttons.js                                                |    8 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskInfo/TaskController.cs |   12 +
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs                 |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs                   |  128 +++++++++++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskTypeEnum.cs                  |   10 
 9 files changed, 455 insertions(+), 165 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 ca34800..8ce07b4 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"
@@ -355,6 +355,14 @@
     type: 'warning',
     onClick: function () {
     }
+},{
+    name: "搴撳瓨鍚屽尯鍩熺Щ搴�",
+    icon: '',
+    class: '',
+    value: 'SelectStockAreaOut',
+    type: 'danger',
+    onClick: function () {
+    }
 }
 ]
 
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
index f786268..56cdda1 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
@@ -159,169 +159,182 @@
       })
 
       let SelectTake = this.buttons.find(x => x.value == 'SelectStockTake');
-if (SelectTake) {
-  // 鏀逛负绠ご鍑芥暟纭繚this鎸囧悜Vue缁勪欢瀹炰緥
-  SelectTake.onClick = async () => {
-    // 鑾峰彇閫変腑鏁版嵁锛堜笌鍘熼�昏緫涓�鑷达紝纭繚鏄暟缁勬牸寮忥級
-    let stockViews = this.$refs.table.getSelected();
-    
-    // 鏁版嵁鏍¢獙锛氳嚦灏戦�夋嫨涓�鏉℃暟鎹�
-    if (stockViews.length === 0) return ElMessage.error("璇烽�夋嫨闇�瑕佹搷浣滅殑鏁版嵁!");
-    
-    // 绔欏彴閫夐」锛堝彲鏍规嵁瀹為檯涓氬姟璋冩暣閫夐」鍊硷級
-    const stationOptions = [
-      { label: "绔欏彴2", value: "2-1" },
-      { label: "绔欏彴3", value: "3-1" },
-      { label: "绔欏彴4", value: "4-1" },
-    ];
-    
-    // 鍒涘缓寮圭獥鎸傝浇鑺傜偣
-    const mountNode = document.createElement("div");
-    document.body.appendChild(mountNode);
-    
-    // 琛ㄥ崟鏁版嵁锛堢粦瀹氶�変腑鐨勭珯鍙帮級
-    const formData = reactive({
-      outStation: stationOptions[0].value, // 榛樿閫変腑绗竴涓珯鍙�
-    });
-    
-    // 鍒涘缓寮圭獥VNode
-    const vnode = createVNode(
-      ElDialog,
-      {
-        title: "搴撳瓨鎿嶄綔 - 閫夋嫨鍑哄簱绔欏彴",
-        width: "500px",
-        modelValue: true,
-        appendToBody: true,
-        "onUpdate:modelValue": (isVisible) => {
-          if (!isVisible) {
-            render(null, mountNode);
-            document.body.removeChild(mountNode);
-          }
-        },
-        style: {
-          padding: "20px 0",
-          borderRadius: "8px",
-        },
-      },
-      {
-        default: () =>
-          h(
-            ElForm,
+      if (SelectTake) {
+        // 鏀逛负绠ご鍑芥暟纭繚this鎸囧悜Vue缁勪欢瀹炰緥
+        SelectTake.onClick = async () => {
+          // 鑾峰彇閫変腑鏁版嵁锛堜笌鍘熼�昏緫涓�鑷达紝纭繚鏄暟缁勬牸寮忥級
+          let stockViews = this.$refs.table.getSelected();
+          
+          // 鏁版嵁鏍¢獙锛氳嚦灏戦�夋嫨涓�鏉℃暟鎹�
+          if (stockViews.length === 0) return ElMessage.error("璇烽�夋嫨闇�瑕佹搷浣滅殑鏁版嵁!");
+          
+          // 绔欏彴閫夐」锛堝彲鏍规嵁瀹為檯涓氬姟璋冩暣閫夐」鍊硷級
+          const stationOptions = [
+            { label: "绔欏彴2", value: "2-1" },
+            { label: "绔欏彴3", value: "3-1" },
+            { label: "绔欏彴4", value: "4-1" },
+          ];
+          
+          // 鍒涘缓寮圭獥鎸傝浇鑺傜偣
+          const mountNode = document.createElement("div");
+          document.body.appendChild(mountNode);
+          
+          // 琛ㄥ崟鏁版嵁锛堢粦瀹氶�変腑鐨勭珯鍙帮級
+          const formData = reactive({
+            outStation: stationOptions[0].value, // 榛樿閫変腑绗竴涓珯鍙�
+          });
+          
+          // 鍒涘缓寮圭獥VNode
+          const vnode = createVNode(
+            ElDialog,
             {
-              model: formData,
-              rules: {
-                outStation: [
-                  { required: true, message: "璇烽�夋嫨鍑哄簱绔欏彴", trigger: "change" },
-                ],
+              title: "搴撳瓨鎿嶄綔 - 閫夋嫨鍑哄簱绔欏彴",
+              width: "500px",
+              modelValue: true,
+              appendToBody: true,
+              "onUpdate:modelValue": (isVisible) => {
+                if (!isVisible) {
+                  render(null, mountNode);
+                  document.body.removeChild(mountNode);
+                }
               },
-              ref: "stockTakeForm", // 琛ㄥ崟ref鏍囪瘑
-              labelWidth: "100px",
               style: {
-                padding: "0 30px",
+                padding: "20px 0",
+                borderRadius: "8px",
               },
             },
-            [
-              // 绔欏彴閫夋嫨涓嬫媺妗�
-              h(ElFormItem, {
-                label: "鍑哄簱绔欏彴",
-                prop: "outStation",
-                style: { marginBottom: "24px" },
-              }, [
-                h(ElSelect, {
-                  placeholder: "璇烽�夋嫨鍑哄簱绔欏彴",
-                  modelValue: formData.outStation,
-                  "onUpdate:modelValue": (val) => {
-                    formData.outStation = val;
+            {
+              default: () =>
+                h(
+                  ElForm,
+                  {
+                    model: formData,
+                    rules: {
+                      outStation: [
+                        { required: true, message: "璇烽�夋嫨鍑哄簱绔欏彴", trigger: "change" },
+                      ],
+                    },
+                    ref: "stockTakeForm", // 琛ㄥ崟ref鏍囪瘑
+                    labelWidth: "100px",
+                    style: {
+                      padding: "0 30px",
+                    },
                   },
-                  style: {
-                    width: "100%",
-                    height: "40px",
-                    borderRadius: "4px",
-                    borderColor: "#dcdfe6",
-                  },
-                }, stationOptions.map((station) =>
-                  h(ElOption, { label: station.label, value: station.value })
-                )),
-              ]),
-              // 搴曢儴鎸夐挳鍖哄煙
-              h("div", {
-                style: {
-                  textAlign: "right",
-                  marginTop: "8px",
-                  paddingRight: "4px",
-                },
-              }, [
-                // 鍙栨秷鎸夐挳
-                h(ElButton, {
-                  type: "text",
-                  onClick: () => {
-                    render(null, mountNode);
-                    document.body.removeChild(mountNode);
-                    ElMessage.info("鍙栨秷搴撳瓨鎿嶄綔");
-                  },
-                  style: { marginRight: "8px", color: "#606266" },
-                }, "鍙栨秷"),
-                // 纭畾鎸夐挳
-                h(ElButton, {
-                  type: "primary",
-                  onClick: async () => {
-                    // 纭繚琛ㄥ崟ref宸叉寕杞�
-                    await this.$nextTick();
-                    const formRef = vnode.component.refs.stockTakeForm;
+                  [
+                    // 绔欏彴閫夋嫨涓嬫媺妗�
+                    h(ElFormItem, {
+                      label: "鍑哄簱绔欏彴",
+                      prop: "outStation",
+                      style: { marginBottom: "24px" },
+                    }, [
+                      h(ElSelect, {
+                        placeholder: "璇烽�夋嫨鍑哄簱绔欏彴",
+                        modelValue: formData.outStation,
+                        "onUpdate:modelValue": (val) => {
+                          formData.outStation = val;
+                        },
+                        style: {
+                          width: "100%",
+                          height: "40px",
+                          borderRadius: "4px",
+                          borderColor: "#dcdfe6",
+                        },
+                      }, stationOptions.map((station) =>
+                        h(ElOption, { label: station.label, value: station.value })
+                      )),
+                    ]),
+                    // 搴曢儴鎸夐挳鍖哄煙
+                    h("div", {
+                      style: {
+                        textAlign: "right",
+                        marginTop: "8px",
+                        paddingRight: "4px",
+                      },
+                    }, [
+                      // 鍙栨秷鎸夐挳
+                      h(ElButton, {
+                        type: "text",
+                        onClick: () => {
+                          render(null, mountNode);
+                          document.body.removeChild(mountNode);
+                          ElMessage.info("鍙栨秷搴撳瓨鎿嶄綔");
+                        },
+                        style: { marginRight: "8px", color: "#606266" },
+                      }, "鍙栨秷"),
+                      // 纭畾鎸夐挳
+                      h(ElButton, {
+                        type: "primary",
+                        onClick: async () => {
+                          // 纭繚琛ㄥ崟ref宸叉寕杞�
+                          await this.$nextTick();
+                          const formRef = vnode.component.refs.stockTakeForm;
 
-                    if (!formRef) {
-                      ElMessage.error("琛ㄥ崟鍒濆鍖栧け璐ワ紝璇烽噸璇�");
-                      return;
-                    }
+                          if (!formRef) {
+                            ElMessage.error("琛ㄥ崟鍒濆鍖栧け璐ワ紝璇烽噸璇�");
+                            return;
+                          }
 
-                    // 琛ㄥ崟楠岃瘉
-                    try {
-                      await formRef.validate();
-                    } catch (err) {
-                      return;
-                    }
+                          // 琛ㄥ崟楠岃瘉
+                          try {
+                            await formRef.validate();
+                          } catch (err) {
+                            return;
+                          }
 
-                    const requestBody = stockViews;
-                    const outStation = formData.outStation;
+                          const requestBody = stockViews;
+                          const outStation = formData.outStation;
 
-                    try {
+                          try {
 
-                      const url = `api/Task/TakeOutbound?outStation=${encodeURIComponent(outStation)}`;
-                      
-                      const x = await this.http.post(
-                        url, // 甯︽煡璇㈠弬鏁扮殑URL
-                        requestBody, // 璇锋眰浣擄細stockViews鏁扮粍
-                        "鏁版嵁澶勭悊涓�"
-                      );
+                            const url = `api/Task/TakeOutbound?outStation=${encodeURIComponent(outStation)}`;
+                            
+                            const x = await this.http.post(
+                              url, // 甯︽煡璇㈠弬鏁扮殑URL
+                              requestBody, // 璇锋眰浣擄細stockViews鏁扮粍
+                              "鏁版嵁澶勭悊涓�"
+                            );
 
-                      if (!x.status) {
-                        ElMessage.error(x.message || "搴撳瓨鎿嶄綔澶辫触");
-                        return;
-                      }
+                            if (!x.status) {
+                              ElMessage.error(x.message || "搴撳瓨鎿嶄綔澶辫触");
+                              return;
+                            }
 
-                      ElMessage.success("鎿嶄綔鎴愬姛");
-                      this.refresh(); // 鍘熷埛鏂伴�昏緫淇濈暀
-                    } catch (error) {
-                      console.error("搴撳瓨鎺ュ彛璇锋眰澶辫触锛�", error);
-                      ElMessage.error("璇锋眰澶辫触锛岃绋嶅悗閲嶈瘯");
-                    } finally {
-                      // 鏃犺鎴愬姛澶辫触锛屽叧闂脊绐�
-                      render(null, mountNode);
-                      document.body.removeChild(mountNode);
-                    }
-                  },
-                  style: { borderRadius: "4px", padding: "8px 20px" },
-                }, "纭畾鎿嶄綔"),
-              ]),
-            ]),
+                            ElMessage.success("鎿嶄綔鎴愬姛");
+                            this.refresh(); // 鍘熷埛鏂伴�昏緫淇濈暀
+                          } catch (error) {
+                            console.error("搴撳瓨鎺ュ彛璇锋眰澶辫触锛�", error);
+                            ElMessage.error("璇锋眰澶辫触锛岃绋嶅悗閲嶈瘯");
+                          } finally {
+                            // 鏃犺鎴愬姛澶辫触锛屽叧闂脊绐�
+                            render(null, mountNode);
+                            document.body.removeChild(mountNode);
+                          }
+                        },
+                        style: { borderRadius: "4px", padding: "8px 20px" },
+                      }, "纭畾鎿嶄綔"),
+                    ]),
+                  ]),
+            }
+          );
+
+          // 缁戝畾app涓婁笅鏂囷紙纭繚寮圭獥鍐呯粍浠舵甯稿伐浣滐級
+          vnode.appContext = this.$.appContext;
+          render(vnode, mountNode);
+        };
       }
-    );
-
-    // 缁戝畾app涓婁笅鏂囷紙纭繚寮圭獥鍐呯粍浠舵甯稿伐浣滐級
-    vnode.appContext = this.$.appContext;
-    render(vnode, mountNode);
-  };
-}
+      let SelectTakeArea = this.buttons.find(x => x.value == 'SelectStockAreaOut');
+      if (SelectTakeArea) {
+        SelectTakeArea.onClick = function () {
+          let stockViews = this.$refs.table.getSelected();
+          this.http
+            .post("api/Task/AreaOutbound",stockViews, "鏁版嵁澶勭悊涓�")
+            .then((x) => {
+              if (!x.status) return this.$message.error(x.message);
+              this.$message.success("鎿嶄綔鎴愬姛");
+              this.refresh();
+            });
+        }
+      }
     },
     onInited() {
       //妗嗘灦鍒濆鍖栭厤缃悗
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_BasicService/LocationInfoService.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_BasicService/LocationInfoService.cs"
index c93a8eb..e01b90c 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_BasicService/LocationInfoService.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_BasicService/LocationInfoService.cs"
@@ -156,7 +156,6 @@
                     { nameof(Dt_LocationInfo.Row),OrderByType.Asc },
                     { nameof(Dt_LocationInfo.Column),OrderByType.Asc },
                     { nameof(Dt_LocationInfo.Depth),OrderByType.Desc },
-
                 };
 
 
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_Common/TaskEnum/TaskTypeEnum.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_Common/TaskEnum/TaskTypeEnum.cs"
index d407243..21f0392 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_Common/TaskEnum/TaskTypeEnum.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_Common/TaskEnum/TaskTypeEnum.cs"
@@ -147,8 +147,14 @@
         /// 宸烽亾鍐呯Щ搴�
         /// </summary>
         [Description("宸烽亾鍐呯Щ搴�")]
-        Relocation = 900
-        
+        Relocation = 900,
+
+        /// <summary>
+        /// 鍚屽尯鍩熺Щ搴�
+        /// </summary>
+        [Description("鍚屽尯鍩熺Щ搴�")]
+        AreaRelocation = 910
+
     }
 
     public enum TaskTypeGroup
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_ITaskInfoService/ITaskService.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_ITaskInfoService/ITaskService.cs"
index 830fba1..056278e 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_ITaskInfoService/ITaskService.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_ITaskInfoService/ITaskService.cs"
@@ -79,5 +79,7 @@
         Task<WebResponseContent> HandCompleteTask(string TaskNum);
 
         Task<WebResponseContent> TaskCancel(List<int> taskCodes);
+
+        Task<WebResponseContent> AreaOutbound(List<StockViewDTO> stockViews);
     }
 }
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_OutboundService/OutboundService.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_OutboundService/OutboundService.cs"
index 894adab..a003631 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_OutboundService/OutboundService.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_OutboundService/OutboundService.cs"
@@ -1376,13 +1376,8 @@
 
                         Func<Dt_OutStockLockInfo, bool> wareWhere = x => string.IsNullOrEmpty(outboundOrderDetails.First().WarehouseCode) ? true : x.WarehouseCode == outboundOrderDetails.First().WarehouseCode;
 
-                        var idStr = outboundOrderDetails.First().Id.ToString();
-
                         var stockLockInfos = _outboundLockInfoRepository.QueryData(x =>
-                            (x.OrderDetailIds == idStr ||
-                             x.OrderDetailIds.StartsWith(idStr + ",") ||
-                             x.OrderDetailIds.EndsWith("," + idStr) ||
-                             x.OrderDetailIds.Contains("," + idStr + ",")) &&
+                            x.OrderDetailIds == lockInfo.OrderDetailIds &&
                             x.OrderNo == request.OrderNo &&
                             x.MaterielCode == stockInfoDetail.MaterielCode)
                             .Where(supWhere)
@@ -1813,13 +1808,8 @@
 
                         Func<Dt_OutStockLockInfo, bool> wareWhere = x => string.IsNullOrEmpty(outboundOrderDetails.First().WarehouseCode) ? true : x.WarehouseCode == outboundOrderDetails.First().WarehouseCode;
 
-                        var idStr = outboundOrderDetails.First().Id.ToString();
-
                         var stockLockInfos = _outboundLockInfoRepository.QueryData(x =>
-                            (x.OrderDetailIds == idStr ||
-                             x.OrderDetailIds.StartsWith(idStr + ",") ||
-                             x.OrderDetailIds.EndsWith("," + idStr) ||
-                             x.OrderDetailIds.Contains("," + idStr + ",")) &&
+                            x.OrderDetailIds == lockInfo.OrderDetailIds &&
                             x.OrderNo == request.OrderNo &&
                             x.MaterielCode == stockDetail.MaterielCode)
                             .Where(supWhere)
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_TaskInfoService/TaskService.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_TaskInfoService/TaskService.cs"
index 572a087..9b7fa57 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_TaskInfoService/TaskService.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_TaskInfoService/TaskService.cs"
@@ -2583,6 +2583,134 @@
                 return WebResponseContent.Instance.Error($"浠诲姟鍙栨秷澶辫触锛歿ex.Message}");
             }
         }
+
+        public async Task<WebResponseContent> AreaRelocationTaskCompleted(Dt_Task task)
+        {
+            WebResponseContent content = new WebResponseContent();
+            try
+            {
+                if (task == null || string.IsNullOrEmpty(task.PalletCode) || string.IsNullOrEmpty(task.TargetAddress))
+                {
+                    return WebResponseContent.Instance.Error("绉诲簱浠诲姟淇℃伅涓嶅畬鏁达紙鎵樼洏鍙�/鐩爣璐т綅涓虹┖锛�");
+                }
+
+                // 2. 鏌ヨ鎵樼洏搴撳瓨淇℃伅
+                Dt_StockInfo stockInfo = await _stockRepository.Db.Queryable<Dt_StockInfo>()
+                    .Includes(x => x.Details)
+                    .Where(x => x.PalletCode == task.PalletCode)
+                    .FirstAsync();
+
+                if (stockInfo == null)
+                {
+                    return WebResponseContent.Instance.Error($"鏈壘鍒版墭鐩榌{task.PalletCode}]瀵瑰簲鐨勭粍鐩樹俊鎭�");
+                }
+
+                // 闈炵┖鎵樼洏蹇呴』鏈夋槑缁�
+                if (stockInfo.Details.Count == 0 && stockInfo.PalletType != PalletTypeEnum.Empty.ObjToInt())
+                {
+                    _logger.LogInformation($"TaskService RelocationTaskCompleted: 鏈壘鍒拌鎵樼洏搴撳瓨鏄庣粏淇℃伅.{task.TaskNum}");
+                    return WebResponseContent.Instance.Error($"鏈壘鍒拌鎵樼洏[{task.PalletCode}]搴撳瓨鏄庣粏淇℃伅");
+                }
+
+                // 3. 鏌ヨ鐩爣璐т綅+鍘熻揣浣嶄俊鎭�
+                Dt_LocationInfo targetLocationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress);
+                if (targetLocationInfo == null)
+                {
+                    return content.Error($"鏈壘鍒板搴旂殑缁堢偣璐т綅[{task.TargetAddress}]淇℃伅");
+                }
+
+                // 鍘熻揣浣嶄俊鎭�
+                Dt_LocationInfo oldLocationInfo = null;
+                if (!string.IsNullOrEmpty(stockInfo.LocationCode))
+                {
+                    oldLocationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == stockInfo.LocationCode);
+                    if (oldLocationInfo == null)
+                    {
+                        return content.Error($"鏈壘鍒板師璐т綅[{stockInfo.LocationCode}]淇℃伅");
+                    }
+                }
+
+                // 4. 璐т綅鐘舵�佹牎楠�
+                if (targetLocationInfo.LocationStatus == LocationStatusEnum.InStock.ObjToInt())
+                {
+                    return WebResponseContent.Instance.Error($"鐩爣璐т綅[{task.TargetAddress}]鐘舵�佷笉姝g‘锛堝綋鍓嶄负宸插崰鐢級");
+                }
+
+                // 5. 寮�鍚簨鍔″鐞嗘牳蹇冮�昏緫
+                _unitOfWorkManage.BeginTran();
+
+                // 5.1 璁板綍鐩爣璐т綅鍘熺姸鎬侊紝鏇存柊涓哄崰鐢�
+                var beforeTargetLocationStatus = targetLocationInfo.LocationStatus;
+                targetLocationInfo.LocationStatus = stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt()
+                        ? LocationStatusEnum.Pallet.ObjToInt()
+                        : LocationStatusEnum.InStock.ObjToInt();
+                _locationInfoService.Repository.UpdateData(targetLocationInfo);
+
+                // 5.2 閲婃斁鍘熻揣浣�
+                int beforeOldLocationStatus = 0;
+                if (oldLocationInfo != null)
+                {
+                    beforeOldLocationStatus = oldLocationInfo.LocationStatus;
+                    // 鍘熻揣浣嶆仮澶嶄负绌洪棽
+                    oldLocationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
+                    _locationInfoService.Repository.UpdateData(oldLocationInfo);
+                }
+                // 5.4 鏇存柊搴撳瓨涓讳俊鎭紙缁戝畾鏂拌揣浣嶏級
+                string oldLocationCode = stockInfo.LocationCode; // 璁板綍鍘熻揣浣�
+                stockInfo.LocationCode = targetLocationInfo.LocationCode; // 缁戝畾鐩爣璐т綅
+                stockInfo.PalletCode = task.PalletCode;
+                stockInfo.StockStatus = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
+
+                _stockRepository.UpdateData(stockInfo);
+
+                // 5.5 鏇存柊浠诲姟鐘舵�佷负瀹屾垚
+                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
+                var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.鑷姩瀹屾垚);
+
+                // 鎻愪氦浜嬪姟
+                _unitOfWorkManage.CommitTran();
+
+                // 浠诲姟褰掓。澶辫触鍒欑洿鎺ュ垹闄�
+                if (!result)
+                {
+                    await Db.Deleteable(task).ExecuteCommandAsync();
+                }
+                try
+                {
+                    // 璁板綍鐩爣璐т綅鐘舵�佸彉鏇�
+                    _locationStatusChangeRecordService.AddLocationStatusChangeRecord(
+                        targetLocationInfo,
+                        beforeTargetLocationStatus,
+                        StockChangeType.Inbound.ObjToInt(),
+                        $"绉诲簱鍏ュ簱锛堝師璐т綅锛歿oldLocationCode}锛�",
+                        task.TaskNum);
+
+                    // 璁板綍鍘熻揣浣嶇姸鎬佸彉鏇达紙鑻ユ湁锛�
+                    if (oldLocationInfo != null)
+                    {
+                        _locationStatusChangeRecordService.AddLocationStatusChangeRecord(
+                            oldLocationInfo,
+                            beforeOldLocationStatus,
+                            StockChangeType.Outbound.ObjToInt(),
+                            $"绉诲簱鍑哄簱锛堢洰鏍囪揣浣嶏細{targetLocationInfo.LocationCode}锛�",
+                            task.TaskNum);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogInformation($"RelocationTaskCompleted AddLocationStatusChangeRecord : {ex.Message} ");
+                }
+
+                return content.OK();
+            }
+            catch (Exception ex)
+            {
+                // 浜嬪姟鍥炴粴
+                _unitOfWorkManage.RollbackTran();
+                _logger.LogError($"RelocationTaskCompleted 澶勭悊澶辫触锛歿ex.Message}", ex);
+                return await Task.FromResult(WebResponseContent.Instance.Error($"绉诲簱浠诲姟澶勭悊澶辫触锛歿ex.Message}"));
+            }
+        }
     }
 }
 
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_TaskInfoService/TaskService_Outbound.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_TaskInfoService/TaskService_Outbound.cs"
index 32ae529..37dcbc7 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_TaskInfoService/TaskService_Outbound.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_TaskInfoService/TaskService_Outbound.cs"
@@ -10,6 +10,7 @@
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using System.Transactions;
 using WIDESEA_BasicService;
 using WIDESEA_Common.CommonEnum;
 using WIDESEA_Common.LocationEnum;
@@ -1243,7 +1244,7 @@
             catch (Exception ex)
             {
                 _unitOfWorkManage.RollbackTran();
-                content.Error(ex.Message);
+                return await Task.FromResult(WebResponseContent.Instance.Error(ex.Message));
             }
             return content;
         }
@@ -1309,6 +1310,137 @@
                 return code;
             }
         }
+
+        /// <summary>
+        /// 閫夊畾搴撳瓨鍚屽尯鍩熺Щ搴�
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        public async Task<WebResponseContent> AreaOutbound(List<StockViewDTO> stockViews)
+        {
+            WebResponseContent content = new WebResponseContent();
+            try
+            {
+                List<int> ids = stockViews.Select(x => x.StockId).ToList();
+                //鑾峰彇搴撳瓨
+                List<Dt_StockInfo> stockInfos = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => ids.Contains(x.Id)).Includes(x => x.Details).ToList();
+                if (stockInfos.Count != stockViews.Count)
+                {
+                    StockViewDTO? stockViewDTO = stockViews.FirstOrDefault(x => !stockInfos.Select(x => x.PalletCode).ToList().Contains(x.PalletCode));
+                    return content.Error($"鏈壘鍒皗stockViewDTO?.PalletCode}搴撳瓨");
+                }
+                //鑾峰彇璐т綅
+                List<string> locStrs = stockInfos.Select(x => x.LocationCode).ToList();
+                List<Dt_LocationInfo> locationInfos = _locationInfoService.Db.Queryable<Dt_LocationInfo>().Where(x => locStrs.Contains(x.LocationCode)).ToList();
+                if (stockInfos.Count != locationInfos.Count)
+                {
+                    string? locStr = locStrs.FirstOrDefault(x => !locationInfos.Select(x => x.LocationCode).ToList().Contains(x));
+                    return content.Error($"鏈壘鍒皗locStr}璐т綅鏁版嵁");
+                }
+               
+                foreach (var item in stockInfos)
+                {
+                    Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x => x.LocationCode == item.LocationCode);
+                    if (locationInfo == null || (locationInfo.EnableStatus == EnableStatusEnum.Disable.ObjToInt() || locationInfo.EnableStatus != EnableStatusEnum.Normal.ObjToInt()) || item.StockStatus != StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt())
+                    {
+                        return content.Error($"{item.PalletCode}璐т綅鎴栧簱瀛樼姸鎬佷笉婊¤冻鍑哄簱鏉′欢");
+                    }
+                }
+                List<Dt_Task> tasks = AreaGetTasks(stockInfos, TaskTypeEnum.AreaRelocation);
+                if (tasks == null || tasks.Count <= 0)
+                {
+                    return content.Error($"鐢熸垚浠诲姟澶辫触");
+                }
+                stockInfos.ForEach(x =>
+                {
+                    x.StockStatus = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
+                });
+                tasks.ForEach(x =>
+                {
+                    x.OrderNo = "鏃犲崟鎹Щ搴�";
+                });
+                locationInfos.ForEach(x =>
+                {
+                    x.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
+                });
+                _unitOfWorkManage.BeginTran();
+                //鏇存柊搴撳瓨鐘舵��
+                _stockRepository.UpdateData(stockInfos);
+                //鏂板缓浠诲姟
+                BaseDal.AddData(tasks);
+                _locationInfoService.UpdateData(locationInfos);
+                _unitOfWorkManage.CommitTran();
+                content.OK();
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                return await Task.FromResult(WebResponseContent.Instance.Error(ex.Message));
+            }
+            return content;
+        }
+
+        public List<Dt_Task> AreaGetTasks(List<Dt_StockInfo> stockInfos, TaskTypeEnum taskType)
+        {
+            // 浣跨敤 TransactionScope 鍖呰9鏁翠釜鎿嶄綔锛岀‘淇濇墍鏈夋暟鎹簱鎿嶄綔鍦ㄥ悓涓�浜嬪姟涓�
+            using (var scope = new TransactionScope(TransactionScopeOption.Required,
+                new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
+            {
+                try
+                {
+                    List<Dt_Task> tasks = new List<Dt_Task>();
+                    List<Dt_LocationInfo> locationInfos = _locationInfoService.Repository.QueryData(
+                        x => stockInfos.Select(x => x.LocationCode).Contains(x.LocationCode));
+
+                    for (int i = 0; i < stockInfos.Count; i++)
+                    {
+                        Dt_StockInfo stockInfo = stockInfos[i];
+
+                        if (stockInfo != null)
+                        {
+                            Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x => x.LocationCode == stockInfo.LocationCode);
+                            var newLocation = _locationInfoService.AssignLocation(stockInfo.LocationType);
+
+                            if (newLocation == null)
+                            {
+                                throw new Exception($"鍦▄stockInfo.PalletCode}鏃舵病鏈夌┖闂插簱浣嶅彲杩涜鍚屽尯鍩熺Щ搴擄紝璇锋鏌ユ垨鍑忓皯绉诲簱鏂欑");
+                            }
+
+                            if (!tasks.Exists(x => x.PalletCode == stockInfo.PalletCode))
+                            {
+                                Dt_Task task = new()
+                                {
+                                    CurrentAddress = stockInfo.LocationCode,
+                                    Grade = 0,
+                                    PalletCode = stockInfo.PalletCode,
+                                    NextAddress = "",
+                                    Roadway = locationInfo.RoadwayNo,
+                                    SourceAddress = stockInfo.LocationCode,
+                                    TargetAddress = newLocation.LocationCode,
+                                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
+                                    TaskType = taskType.ObjToInt(),
+                                    PalletType = stockInfo.PalletType,
+                                    WarehouseId = stockInfo.WarehouseId,
+                                };
+                                tasks.Add(task);
+                            }
+
+                            newLocation.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
+                            _locationInfoService.UpdateData(newLocation);
+                        }
+                    }
+
+                    // 鎻愪氦浜嬪姟
+                    scope.Complete();
+                    return tasks;
+                }
+                catch (Exception ex)
+                {
+                    // TransactionScope 浼氳嚜鍔ㄥ洖婊氫簨鍔★紝鏃犻渶鎵嬪姩 Rollback
+                    throw new Exception(ex.Message);
+                }
+            }
+        }
     }
 
 }
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/TaskInfo/TaskController.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/TaskInfo/TaskController.cs"
index 8d06ecc..22cc2ac 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/TaskInfo/TaskController.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/TaskInfo/TaskController.cs"
@@ -132,5 +132,17 @@
         {
             return await Service.TaskCancel(taskCancel);
         }
+
+        /// <summary>
+        /// 鐩樼偣搴撳瓨鍑哄簱
+        /// </summary>
+        /// <param name="stockViews"></param>
+        /// <param name="outStation"></param>
+        /// <returns></returns>
+        [HttpPost, HttpGet, Route("AreaOutbound"), AllowAnonymous]
+        public async Task<WebResponseContent> AreaOutbound([FromBody] List<StockViewDTO> stockViews)
+        {
+            return await Service.AreaOutbound(stockViews);
+        }
     }
 }

--
Gitblit v1.9.3