From 4476740c214edb7ab667c48fcab00488fbdd9879 Mon Sep 17 00:00:00 2001
From: pan <antony1029@163.com>
Date: 星期六, 15 十一月 2025 09:03:54 +0800
Subject: [PATCH] 提交

---
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs                   |   35 +
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutboundPickingController.cs  |   46 +
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutStockLockInfoController.cs |   11 
 项目代码/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js                                      |    4 
 项目代码/WIDESEA_WMSClient/src/router/viewGird.js                                                       |    2 
 项目代码/WIDESEA_WMSClient/src/views/outbound/PickingConfirm.vue                                        |  777 +++++++++-------------
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs                    |  235 ++++++
 项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue                             |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_DTO/Outbound/OutboundOrderGetDTO.cs                          |   34 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundPickingService.cs                  |   12 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IOutboundService/ISplitPackageService.cs                     |    7 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundOrderDetail.cs              |    3 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_DTO/Basic/SupplierDTO.cs                                     |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs                 |    3 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/SplitPackageService.cs                       |  114 ++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs                 |    3 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_PickingRecord.cs                    |   20 
 项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/PickingConfirm.vue                             |  294 ++++++++
 项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/Picking.vue                                    |  190 +++++
 项目代码/WIDESEA_WMSClient/vue.config.js                                                                |    1 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs                               |    7 
 项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/SplitPackage.vue                               |  176 +++++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/WarehouseService.cs                             |   25 
 23 files changed, 1,475 insertions(+), 528 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/Picking.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/Picking.vue"
new file mode 100644
index 0000000..7236d00
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/Picking.vue"
@@ -0,0 +1,190 @@
+<template>
+  <div class="picking-operation">
+    <div class="operation-toolbar">
+      <el-button type="primary" @click="showPickingConfirm">
+        鍒嗘嫞纭
+      </el-button>
+      <el-button 
+        type="warning" 
+        @click="showSplitDialog"
+        :disabled="selectedRows.length !== 1"
+      >
+        鎷嗗寘
+      </el-button>
+      <el-button type="success" @click="batchDirectOutbound">
+        鐩存帴鍑哄簱
+      </el-button>
+      <el-button type="info" @click="batchReturnToWarehouse">
+        鍥炲簱
+      </el-button>
+    </div>
+
+    <!-- 鍑哄簱璇︽儏鍒楄〃 -->
+    <div class="lock-info-table">
+      <base-table
+        ref="lockInfoTable"
+        :table-config="tableConfig"
+        :height="300"
+        selection
+        @selection-change="handleSelectionChange"
+      />
+    </div>
+
+    <!-- 鍒嗘嫞纭寮圭獥 -->
+    <el-dialog
+      v-model="pickingConfirmVisible"
+      title="鍒嗘嫞纭"
+      width="90%"
+      top="5vh"
+      destroy-on-close
+    >
+      <picking-confirm
+        v-if="pickingConfirmVisible"
+        :order-no="orderDetail.OrderNo"
+        @confirm="handlePickingConfirm"
+        @close="pickingConfirmVisible = false"
+      />
+    </el-dialog>
+
+    <!-- 鎷嗗寘寮圭獥 -->
+    <el-dialog
+      v-model="splitVisible"
+      title="鎷嗗寘鎿嶄綔"
+      width="600px"
+      destroy-on-close
+    >
+      <split-package
+        v-if="splitVisible && selectedLockInfo"
+        :lock-info="selectedLockInfo"
+        @confirm="handleSplitConfirm"
+        @close="splitVisible = false"
+      />
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import BaseTable from '@/components/base/BaseTable.vue'
+import PickingConfirm from './PickingConfirm.vue'
+import SplitPackage from './SplitPackage.vue'
+
+const props = defineProps({
+  orderDetail: {
+    type: Object,
+    required: true
+  }
+})
+
+const emit = defineEmits(['close'])
+
+const lockInfoTable = ref()
+const pickingConfirmVisible = ref(false)
+const splitVisible = ref(false)
+const selectedRows = ref([])
+const selectedLockInfo = ref(null)
+
+const tableConfig = reactive({
+  url: '/api/outbound/getOutStockLockInfo',
+  query: { orderDetailId: props.orderDetail.Id },
+  columns: [
+    { type: 'selection', width: 55 },
+    { prop: 'BatchNo', label: '鎵规鍙�', width: 120 },
+    { prop: 'MaterielCode', label: '鐗╂枡鏉$爜', width: 150 },
+    { prop: 'AssignQuantity', label: '鍒嗛厤鏁伴噺', width: 100 },
+    { prop: 'PickedQty', label: '宸叉嫞鏁伴噺', width: 100 },
+    { prop: 'LocationCode', label: '搴撲綅缂栧彿', width: 120 },
+    { prop: 'PalletCode', label: '鎵樼洏缂栧彿', width: 120 },
+    { prop: 'Status', label: '鐘舵��', width: 100 }
+  ]
+})
+
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection
+}
+
+const showPickingConfirm = () => {
+  pickingConfirmVisible.value = true
+}
+
+const showSplitDialog = async () => {
+  if (selectedRows.value.length !== 1) {
+    ElMessage.warning('璇烽�夋嫨涓�鏉¤鎷嗗寘鐨勮褰�')
+    return
+  }
+
+  try {
+    // 鑾峰彇閫変腑璁板綍鐨勮缁嗕俊鎭�
+    const result = await $http.get('/api/outbound/getLockInfoDetail', {
+      params: { lockInfoId: selectedRows.value[0].Id }
+    })
+
+    if (result.success) {
+      selectedLockInfo.value = result.data
+      splitVisible.value = true
+    } else {
+      ElMessage.error('鑾峰彇鎷嗗寘璁板綍璇︽儏澶辫触')
+    }
+  } catch (error) {
+    ElMessage.error('鑾峰彇鎷嗗寘璁板綍璇︽儏澶辫触')
+  }
+}
+
+const batchDirectOutbound = async () => {
+  try {
+    await ElMessageBox.confirm('纭畾瑕佸鏁翠釜璁㈠崟鎵ц鐩存帴鍑哄簱鍚楋紵', '鎻愮ず', {
+      type: 'warning'
+    })
+
+    const result = await $http.post('/api/outbound/batchDirectOutbound', {
+      orderNo: props.orderDetail.OrderNo
+    })
+
+    if (result.success) {
+      ElMessage.success('鎵归噺鐩存帴鍑哄簱鎴愬姛')
+      lockInfoTable.value.refresh()
+    } else {
+      ElMessage.error(result.message)
+    }
+  } catch (error) {
+    if (error !== 'cancel') {
+      ElMessage.error('鎵归噺鐩存帴鍑哄簱澶辫触')
+    }
+  }
+}
+
+const batchReturnToWarehouse = async () => {
+  try {
+    await ElMessageBox.confirm('纭畾瑕佸鏈嫞閫夎揣鐗╂墽琛屽洖搴撳悧锛�', '鎻愮ず', {
+      type: 'warning'
+    })
+
+    const result = await $http.post('/api/outbound/batchReturnToWarehouse', {
+      orderNo: props.orderDetail.OrderNo
+    })
+
+    if (result.success) {
+      ElMessage.success('鎵归噺鍥炲簱鎴愬姛')
+      lockInfoTable.value.refresh()
+    } else {
+      ElMessage.error(result.message)
+    }
+  } catch (error) {
+    if (error !== 'cancel') {
+      ElMessage.error('鎵归噺鍥炲簱澶辫触')
+    }
+  }
+}
+
+const handlePickingConfirm = () => {
+  pickingConfirmVisible.value = false
+  lockInfoTable.value.refresh()
+}
+
+const handleSplitConfirm = () => {
+  splitVisible.value = false
+  selectedLockInfo.value = null
+  lockInfoTable.value.refresh()
+}
+</script>
\ 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/outbound/extend/PickingConfirm.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/PickingConfirm.vue"
new file mode 100644
index 0000000..58b70eb
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/PickingConfirm.vue"
@@ -0,0 +1,294 @@
+<template>
+  <div class="picking-confirm">
+    <div class="scan-section">
+      <el-alert
+        title="璇蜂娇鐢ㄦ壂鐮佹灙鎵弿鎵樼洏鐮佸拰鐗╂枡鏉$爜锛屾壂鐮佹灙甯﹀洖杞﹀姛鑳斤紝鎵畬鐗╂枡鏉$爜鑷姩纭"
+        type="info"
+        :closable="false"
+        class="scan-alert"
+      />
+
+      <el-form :model="scanForm" label-width="100px" class="scan-form">
+        <el-form-item label="鎵樼洏鐮�" required>
+          <el-input
+            ref="palletInput"
+            v-model="scanForm.palletCode"
+            placeholder="璇锋壂鎻忔墭鐩樼爜"
+            @keyup.enter="handlePalletScan"
+            @blur="loadPalletSummary"
+            clearable
+          />
+        </el-form-item>
+
+        <el-form-item label="鐗╂枡鏉$爜" required>
+          <el-input
+            ref="materialInput"
+            v-model="scanForm.materialBarcode"
+            placeholder="璇锋壂鎻忕墿鏂欐潯鐮�"
+            :disabled="!scanForm.palletCode"
+            @keyup.enter="handleMaterialScan"
+            clearable
+          />
+        </el-form-item>
+      </el-form>
+
+      <!-- 鎵樼洏鎷h揣缁熻 -->
+      <div v-if="palletSummary" class="pallet-summary">
+        <el-card header="鎵樼洏鎷h揣缁熻">
+          <el-descriptions :column="3" border>
+            <el-descriptions-item label="鎵樼洏鍙�">
+              {{ scanForm.palletCode }}
+            </el-descriptions-item>
+            <el-descriptions-item label="鏈嫞璐ф潯鏁�">
+              <el-text type="warning">{{ palletSummary.unpickedCount }}</el-text>
+            </el-descriptions-item>
+            <el-descriptions-item label="鏈嫞璐ф�绘暟">
+              <el-text type="danger">{{ palletSummary.unpickedTotal }}</el-text>
+            </el-descriptions-item>
+          </el-descriptions>
+        </el-card>
+      </div>
+
+      <div class="action-buttons">
+        <el-button type="primary" @click="handleConfirm" :loading="confirmLoading">
+          鎵嬪姩纭
+        </el-button>
+        <el-button @click="handleReset">閲嶇疆</el-button>
+        <el-button @click="$emit('close')">鍙栨秷</el-button>
+      </div>
+    </div>
+
+    <!-- 宸插垎鎷h褰曞垪琛� -->
+    <div class="picked-records">
+      <el-card header="宸插垎鎷h褰�">
+        <base-table
+          ref="pickedTable"
+          :table-config="pickedTableConfig"
+          :height="300"
+        />
+      </el-card>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, nextTick } from 'vue'
+import { ElMessage } from 'element-plus'
+import BaseTable from '@/components/base/BaseTable.vue'
+
+const props = defineProps({
+  orderNo: {
+    type: String,
+    required: true
+  }
+})
+
+const emit = defineEmits(['confirm', 'close'])
+
+const palletInput = ref()
+const materialInput = ref()
+const pickedTable = ref()
+
+const scanForm = reactive({
+  palletCode: '',
+  materialBarcode: ''
+})
+
+const palletSummary = ref(null)
+const confirmLoading = ref(false)
+
+const pickedTableConfig = reactive({
+  url: '/api/outbound/getPickingRecords',
+  query: { orderNo: props.orderNo },
+  columns: [
+    { prop: 'TaskNo', label: '浠诲姟鍙�', width: 150 },
+    { prop: 'Barcode', label: '鐗╂枡鏉$爜', width: 150 },
+    { prop: 'MaterielName', label: '鐗╂枡鍚嶇О', width: 150 },
+    { prop: 'PickQuantity', label: '鎷h揣鏁伴噺', width: 100 },
+    { prop: 'LocationCode', label: '璐т綅', width: 120 },
+    { prop: 'CreateTime', label: '鎷h揣鏃堕棿', width: 180 }
+  ]
+})
+
+onMounted(() => {
+  nextTick(() => {
+    if (palletInput.value) {
+      palletInput.value.focus()
+    }
+  })
+})
+const loadOrderInfo = async () => {
+  const orderId = route.query.orderId
+  if (!orderId) return
+  
+  try {
+    const response = await http.get(`/api/OutboundOrder/GetById?id=${orderId}`)
+    if (response.status) {
+      orderInfo.value = response.data
+    }
+  } catch (error) {
+    ElMessage.error('鍔犺浇鍑哄簱鍗曚俊鎭け璐�')
+  }
+}
+const handlePalletScan = async () => {
+  if (scanForm.palletCode) {
+    ElMessage.success(`宸叉壂鎻忔墭鐩�: ${scanForm.palletCode}`)
+    await loadPalletSummary()
+    
+    nextTick(() => {
+      if (materialInput.value) {
+        materialInput.value.focus()
+      }
+    })
+  }
+}
+
+const handleMaterialScan = async () => {
+  if (!scanForm.palletCode) {
+    ElMessage.warning('璇峰厛鎵弿鎵樼洏鐮�')
+    palletInput.value.focus()
+    return
+  }
+
+  if (!scanForm.materialBarcode) {
+    ElMessage.warning('璇锋壂鎻忕墿鏂欐潯鐮�')
+    return
+  }
+
+  await executePickingConfirm()
+}
+
+const loadPalletSummary = async () => {
+  if (!scanForm.palletCode) {
+    palletSummary.value = null
+    return
+  }
+
+  try {
+    const result = await $http.get('/api/outbound/getPalletPickingSummary', {
+      params: {
+        orderNo: props.orderNo,
+        palletCode: scanForm.palletCode
+      }
+    })
+
+    if (result.success) {
+      // 澶勭悊缁熻淇℃伅
+      const summary = result.data
+      const assigned = summary.find(x => x.Status === '宸插垎閰�') || { TotalAssignQty: 0, TotalPickedQty: 0 }
+      const picked = summary.find(x => x.Status === '宸叉嫞閫�') || { TotalPickedQty: 0 }
+      
+      palletSummary.value = {
+        unpickedCount: assigned.TotalAssignQty > 0 ? 1 : 0, // 绠�鍖栬绠�
+        unpickedTotal: assigned.TotalAssignQty - assigned.TotalPickedQty
+      }
+    }
+  } catch (error) {
+    console.error('鍔犺浇鎵樼洏缁熻澶辫触:', error)
+  }
+}
+
+const handleConfirm = async () => {
+  if (!scanForm.palletCode || !scanForm.materialBarcode) {
+    ElMessage.warning('璇峰~鍐欏畬鏁寸殑鎵爜淇℃伅')
+    return
+  }
+
+  await executePickingConfirm()
+}
+
+const executePickingConfirm = async () => {
+  confirmLoading.value = true
+  
+  try {
+    // 鍏堟壘鍒板搴旂殑鍑哄簱閿佸畾淇℃伅
+    const lockInfoResult = await $http.get('/api/outbound/getOutStockLockInfo', {
+      params: { 
+        orderNo: props.orderNo,
+        palletCode: scanForm.palletCode,
+        materialBarcode: scanForm.materialBarcode
+      }
+    })
+
+    if (!lockInfoResult.success || !lockInfoResult.data || lockInfoResult.data.length === 0) {
+      ElMessage.error('鏈壘鍒板搴旂殑鍑哄簱閿佸畾淇℃伅')
+      return
+    }
+
+    const lockInfo = lockInfoResult.data[0]
+
+    const request = {
+      outStockLockId: lockInfo.Id,
+      taskNo: `TASK_${Date.now()}`,
+      palletCode: scanForm.palletCode,
+      materialBarcode: scanForm.materialBarcode,
+      locationCode: lockInfo.LocationCode
+    }
+
+    const result = await $http.post('/api/outbound/pickingConfirm', request)
+    
+    if (result.success) {
+      ElMessage.success('鍒嗘嫞纭鎴愬姛')
+      handleReset()
+      emit('confirm')
+      
+      // 鍒锋柊宸插垎鎷h褰�
+      if (pickedTable.value) {
+        pickedTable.value.refresh()
+      }
+      
+      // 閲嶆柊鍔犺浇鎵樼洏缁熻
+      await loadPalletSummary()
+    } else {
+      ElMessage.error(result.message)
+    }
+  } catch (error) {
+    ElMessage.error('鍒嗘嫞纭澶辫触')
+  } finally {
+    confirmLoading.value = false
+  }
+}
+
+const handleReset = () => {
+  scanForm.materialBarcode = ''
+  nextTick(() => {
+    if (materialInput.value) {
+      materialInput.value.focus()
+    }
+  })
+}
+</script>
+
+<style scoped>
+.picking-confirm {
+  display: flex;
+  flex-direction: column;
+  height: 70vh;
+}
+
+.scan-section {
+  flex-shrink: 0;
+  margin-bottom: 16px;
+}
+
+.scan-alert {
+  margin-bottom: 16px;
+}
+
+.scan-form {
+  max-width: 500px;
+}
+
+.pallet-summary {
+  margin: 16px 0;
+}
+
+.action-buttons {
+  margin-top: 16px;
+}
+
+.picked-records {
+  flex: 1;
+  min-height: 300px;
+}
+</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/outbound/extend/SplitPackage.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/SplitPackage.vue"
new file mode 100644
index 0000000..8507c3e
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/SplitPackage.vue"
@@ -0,0 +1,176 @@
+<template>
+  <div class="split-package">
+    <el-alert
+      title="鎷嗗寘鎿嶄綔灏嗘妸閫変腑鐨勭墿鏂欏寘鍒嗘垚涓や釜鍖咃紝绯荤粺浼氳嚜鍔ㄧ敓鎴愭柊鏉$爜"
+      type="info"
+      :closable="false"
+      class="split-alert"
+    />
+
+    <!-- 鍘熺墿鏂欎俊鎭睍绀� -->
+    <el-card header="鍘熺墿鏂欎俊鎭�" class="original-info">
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="鏃ф潯鐮�">
+          <el-text type="primary">{{ lockInfo.MaterielCode }}</el-text>
+        </el-descriptions-item>
+        <el-descriptions-item label="鐗╂枡鍚嶇О">
+          {{ lockInfo.MaterielName }}
+        </el-descriptions-item>
+        <el-descriptions-item label="鎵规鍙�">
+          {{ lockInfo.BatchNo }}
+        </el-descriptions-item>
+        <el-descriptions-item label="鎵樼洏缂栧彿">
+          {{ lockInfo.PalletCode }}
+        </el-descriptions-item>
+        <el-descriptions-item label="搴撲綅缂栧彿">
+          {{ lockInfo.LocationCode }}
+        </el-descriptions-item>
+        <el-descriptions-item label="浠诲姟鍙�">
+          {{ taskNo }}
+        </el-descriptions-item>
+        <el-descriptions-item label="鍒嗛厤鏁伴噺">
+          <el-text type="info">{{ lockInfo.AssignQuantity }}</el-text>
+        </el-descriptions-item>
+        <el-descriptions-item label="宸叉嫞鏁伴噺">
+          <el-text type="warning">{{ lockInfo.PickedQty }}</el-text>
+        </el-descriptions-item>
+        <el-descriptions-item label="鍙媶鍖呮暟閲�">
+          <el-text type="success">{{ availableQuantity }}</el-text>
+        </el-descriptions-item>
+      </el-descriptions>
+    </el-card>
+
+    <!-- 鎷嗗寘淇℃伅杈撳叆 -->
+    <el-card header="鎷嗗寘淇℃伅" class="split-info">
+      <el-form :model="splitForm" label-width="120px">
+        <el-form-item label="鎷嗗寘鏁伴噺" required>
+          <el-input-number
+            v-model="splitForm.splitQuantity"
+            :min="1"
+            :max="availableQuantity"
+            :precision="2"
+            placeholder="璇疯緭鍏ユ媶鍖呮暟閲�"
+            style="width: 200px"
+          />
+          <div class="form-tips">
+            鍙媶鍖呮暟閲�: {{ availableQuantity }} {{ lockInfo.Unit }}
+          </div>
+        </el-form-item>
+        
+        <el-form-item label="鏂版潯鐮�" v-if="newBarcode">
+          <el-text type="success">{{ newBarcode }}</el-text>
+          <div class="form-tips">绯荤粺鑷姩鐢熸垚鐨勬柊鏉$爜</div>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <div class="action-buttons">
+      <el-button 
+        type="primary" 
+        @click="handleConfirm" 
+        :loading="confirmLoading"
+        :disabled="!splitForm.splitQuantity"
+      >
+        纭鎷嗗寘
+      </el-button>
+      <el-button @click="$emit('close')">鍙栨秷</el-button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from 'vue'
+import { ElMessage } from 'element-plus'
+
+const props = defineProps({
+  lockInfo: {
+    type: Object,
+    required: true
+  }
+})
+
+const emit = defineEmits(['confirm', 'close'])
+
+const splitForm = reactive({
+  splitQuantity: 1
+})
+
+const confirmLoading = ref(false)
+const newBarcode = ref('')
+const taskNo = ref(`SPLIT_${Date.now()}`)
+
+// 璁$畻鍙媶鍖呮暟閲�
+const availableQuantity = computed(() => {
+  return props.lockInfo.AssignQuantity - props.lockInfo.PickedQty
+})
+
+const handleConfirm = async () => {
+  if (!splitForm.splitQuantity || splitForm.splitQuantity <= 0) {
+    ElMessage.warning('璇疯緭鍏ユ湁鏁堢殑鎷嗗寘鏁伴噺')
+    return
+  }
+
+  if (splitForm.splitQuantity >= availableQuantity.value) {
+    ElMessage.warning('鎷嗗寘鏁伴噺蹇呴』灏忎簬鍙媶鍖呮暟閲�')
+    return
+  }
+
+  confirmLoading.value = true
+  
+  try {
+    const request = {
+      lockInfoId: props.lockInfo.Id,
+      taskNo: taskNo.value,
+      splitQuantity: splitForm.splitQuantity
+    }
+
+    const result = await $http.post('/api/outbound/splitPackage', request)
+    
+    if (result.success) {
+      newBarcode.value = result.data?.newBarcode || '鐢熸垚鎴愬姛'
+      ElMessage.success(`鎷嗗寘鎿嶄綔鎴愬姛锛佹柊鏉$爜: ${newBarcode.value}`)
+      
+      // 寤惰繜鍏抽棴锛岃鐢ㄦ埛鐪嬪埌鏂版潯鐮�
+      setTimeout(() => {
+        emit('confirm')
+      }, 2000)
+    } else {
+      ElMessage.error(result.message)
+    }
+  } catch (error) {
+    ElMessage.error('鎷嗗寘鎿嶄綔澶辫触')
+  } finally {
+    confirmLoading.value = false
+  }
+}
+</script>
+
+<style scoped>
+.split-package {
+  max-height: 70vh;
+  overflow-y: auto;
+}
+
+.split-alert {
+  margin-bottom: 16px;
+}
+
+.original-info {
+  margin-bottom: 16px;
+}
+
+.split-info {
+  margin-bottom: 16px;
+}
+
+.form-tips {
+  font-size: 12px;
+  color: #909399;
+  margin-top: 4px;
+}
+
+.action-buttons {
+  text-align: center;
+  margin-top: 20px;
+}
+</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/outbound/extend/outOrderDetail.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue"
index af6508f..890b066 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue"
@@ -329,7 +329,7 @@
    handleOpenPicking() {
       this.$router.push({
         path: '/outbound/picking',
-        query: { orderId: this.row.id }
+        query: { orderId: this.row.id ,orderNo:this.row.orderNo}
       })
     },
     outbound() {
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js"
index fb04c10..5eb8232 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js"
@@ -18,7 +18,7 @@
     },
     tableAction: '', //鎸囧畾鏌愬紶琛ㄧ殑鏉冮檺(杩欓噷濉啓琛ㄥ悕,榛樿涓嶇敤濉啓)
     buttons: { view: [
-       {
+       /* {
         name: '鍑哄簱',
         type: 'primary',
         value: '鍑哄簱',
@@ -42,7 +42,7 @@
             createDate: selectedRows[0].createDate || new Date().toLocaleDateString()  // 鍑哄簱鏃ユ湡
           });
         }
-      },
+      }, */
       {
   name: '绌烘墭鐩樺嚭搴�',
   type: 'primary',
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/router/viewGird.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/router/viewGird.js"
index a78b685..854c4d1 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/router/viewGird.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/router/viewGird.js"
@@ -76,7 +76,7 @@
   }, 
   {
   path: '/outbound/picking',
-  name: 'PickingConfirm',
+  name: 'PickingConfirm', 
   component: () => import('@/views/outbound/PickingConfirm.vue'),
   meta: { title: '鎷i�夌‘璁�', keepAlive: false }
 },{
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/PickingConfirm.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/PickingConfirm.vue"
index ef26541..d9f3d25 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/PickingConfirm.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/PickingConfirm.vue"
@@ -3,516 +3,375 @@
     <div class="page-header">
       <el-page-header @back="goBack">
         <template #content>
-          <span class="title">鍑哄簱鎷i�夌‘璁� - {{ orderInfo.orderNo }}</span>
+          <span class="title">鍑哄簱鎷i�夌‘璁� - {{ this.$route.query.orderNo }}</span>
         </template>
       </el-page-header>
     </div>
-
-    <el-row :gutter="20" class="main-content">
-      <el-col :span="8">
+    
+    <div class="content-layout">
+      <!-- 宸︿晶锛氭壂鐮佸尯鍩� -->
+      <div class="left-section">
         <div class="scan-section">
-          <el-card header="鎵爜鍖哄煙">
-            <el-form label-width="100px" size="small">
-              <el-form-item label="鎵樼洏鏉$爜">
-                <el-input 
-                  v-model="scanForm.palletCode" 
-                  placeholder="鎵弿鎴栬緭鍏ユ墭鐩樻潯鐮�"
-                  @keyup.enter="handlePalletScan"
-                  clearable
-                >
-                  <template #append>
-                    <el-button @click="handlePalletScan">纭</el-button>
-                  </template>
-                </el-input>
-              </el-form-item>
+          <el-alert
+            title="璇蜂娇鐢ㄦ壂鐮佹灙鎵弿鎵樼洏鐮佸拰鐗╂枡鏉$爜锛屾壂鐮佹灙甯﹀洖杞﹀姛鑳斤紝鎵畬鐗╂枡鏉$爜鑷姩纭"
+            type="info"
+            :closable="false"
+            class="scan-alert"
+          />
 
-              <el-form-item label="鐗╂枡鏉$爜">
-                <el-input 
-                  v-model="scanForm.barcode" 
-                  placeholder="鎵弿鎴栬緭鍏ョ墿鏂欐潯鐮�"
-                  @keyup.enter="handleBarcodeScan"
-                  :disabled="!currentPallet"
-                  clearable
-                >
-                  <template #append>
-                    <el-button @click="handleBarcodeScan" :disabled="!currentPallet">纭</el-button>
-                  </template>
-                </el-input>
-              </el-form-item>
+          <el-form :model="scanForm" label-width="100px" class="scan-form">
+            <el-form-item label="鎵樼洏鐮�" required>
+              <el-input
+                ref="palletInput"
+                v-model="scanForm.palletCode"
+                placeholder="璇锋壂鎻忔墭鐩樼爜"
+                @keyup.enter="handlePalletScan"
+                @blur="loadPalletSummary"
+                clearable
+              />
+            </el-form-item>
 
-              <el-form-item label="鎷i�夋暟閲�">
-                <el-input-number 
-                  v-model="scanForm.quantity" 
-                  :min="1" 
-                  :max="maxPickQuantity"
-                  :disabled="!currentLockInfo"
-                />
-              </el-form-item>
+            <el-form-item label="鐗╂枡鏉$爜" required>
+              <el-input
+                ref="materialInput"
+                v-model="scanForm.materialBarcode"
+                placeholder="璇锋壂鎻忕墿鏂欐潯鐮�"
+                :disabled="!scanForm.palletCode"
+                @keyup.enter="handleMaterialScan"
+                clearable
+              />
+            </el-form-item>
+          </el-form>
 
-              <!-- 鐗╂枡淇℃伅鏄剧ず -->
-              <el-form-item label="鐗╂枡缂栫爜" v-if="currentMaterialInfo">
-                <el-input v-model="currentMaterialInfo.materielCode" readonly />
-              </el-form-item>
-              <el-form-item label="鐗╂枡鍚嶇О" v-if="currentMaterialInfo">
-                <el-input v-model="currentMaterialInfo.materielName" readonly />
-              </el-form-item>
-            </el-form>
-
-            <div class="current-info" v-if="currentPallet">
-              <p>褰撳墠鎵樼洏: {{ currentPallet.palletCode }}</p>
-              <p>璐т綅: {{ currentPallet.locationCode }}</p>
-              <p>鐘舵��: {{ currentPallet.statusText }}</p>
-            </div>
-          </el-card>
+          <!-- 鎵樼洏鎷h揣缁熻 -->
+          <div v-if="palletSummary" class="pallet-summary">
+            <el-card header="鎵樼洏鎷h揣缁熻">
+              <el-descriptions :column="3" border>
+                <el-descriptions-item label="鎵樼洏鍙�">
+                  {{ scanForm.palletCode }}
+                </el-descriptions-item>
+                <el-descriptions-item label="鏈嫞璐ф潯鏁�">
+                  <el-text type="warning">{{ palletSummary.unpickedCount }}</el-text>
+                </el-descriptions-item>
+                <el-descriptions-item label="鏈嫞璐ф�绘暟">
+                  <el-text type="danger">{{ palletSummary.unpickedTotal }}</el-text>
+                </el-descriptions-item>
+              </el-descriptions>
+            </el-card>
+          </div>
 
           <div class="action-buttons">
-            <el-button 
-              type="warning" 
-              @click="handleBackToStock" 
-              :disabled="!currentPallet"
-              style="margin-bottom: 10px;"
-            >
-              鍥炲簱
+            <el-button type="primary" @click="handleConfirm" :loading="confirmLoading">
+              鎵嬪姩纭
             </el-button>
-            <el-button 
-              type="success" 
-              @click="handleDirectOutbound" 
-              :disabled="!currentPallet"
-              style="margin-bottom: 10px;"
-            >
-              鐩存帴鍑哄簱
-            </el-button>
-            <el-button 
-              type="primary" 
-              @click="handleOpenSplit" 
-              :disabled="!currentLockInfo"
-            >
-              鎷嗗寘
-            </el-button>
+            <el-button @click="handleReset">閲嶇疆</el-button>
+            <el-button @click="$emit('close')">鍙栨秷</el-button>
           </div>
         </div>
-      </el-col>
+      </div>
 
-      <el-col :span="16">
-        <el-card header="鎷i�夌粨鏋�">
-          <div class="summary-info">
-            <el-alert
-              :title="`鏈嫞璐�: ${unpickedCount} 鏉�, ${unpickedQuantity} 涓猔"
-              type="warning"
-              :closable="false"
-            />
-          </div>
-
+      <!-- 鍙充晶锛氬嚭搴撹鎯呭垪琛� -->
+      <div class="right-section">
+        <el-card class="outbound-details-card" header="鍑哄簱璇︽儏">
           <vol-table
-            :data="pickedList"
-            :columns="pickedColumns"
-            :pagination="false"
-            :height="400"
-          >
-            <template #action="{ row }">
-              <el-button type="text" @click="handleCancelPick(row)">鎾ら攢</el-button>
-            </template>
-          </vol-table>
+            ref="outboundTable"
+            :table-config="outboundTableConfig"
+            :height="300"
+          />
         </el-card>
-      </el-col>
-    </el-row>
+      </div>
+    </div>
 
-    <!-- 鎷嗗寘寮圭獥 -->
-    <vol-box
-      v-model="splitVisible"
-      title="鎷嗗寘鎿嶄綔"
-      :width="600"
-      :height="500"
-    >
-      <SplitPackageModal
-        v-if="splitVisible"
-        :lockInfo="currentLockInfo"
-        @success="handleSplitSuccess"
-        @close="splitVisible = false"
-      />
-    </vol-box>
+    <!-- 宸插垎鎷h褰曞垪琛� -->
+    <div class="picked-records">
+      <el-card header="宸插垎鎷h褰�">
+        <vol-table
+          ref="pickedTable"
+          :table-config="pickedTableConfig"
+          :height="300"
+        />
+      </el-card>
+    </div>
   </div>
 </template>
 
 <script>
-import SplitPackageModal from './SplitPackageModal.vue'
+import http from '@/api/http.js'
+import { ref, defineComponent } from "vue";
+import { ElMessage } from "element-plus";
+import { useRoute } from 'vue-router' 
 
-export default {
-  components: { SplitPackageModal },
+export default defineComponent({
+  name: 'PickingConfirm',
+  components: {
+  
+  },
+  props: {
+    orderNo: {
+      type: String,
+      required: true
+    }
+  },
+  emits: ['confirm', 'close'],
   data() {
     return {
-      orderInfo: {},
       scanForm: {
         palletCode: '',
-        barcode: '',
-        quantity: 1
+        materialBarcode: ''
       },
-      currentPallet: null,
-      currentLockInfo: null,
-      currentMaterialInfo: null, // 鏂板锛氬綋鍓嶇墿鏂欎俊鎭�
-      pickedList: [],
-      pickedColumns: [
-        { field: 'barcode', title: '鐗╂枡鏉$爜', width: 150 },
-        { field: 'materielCode', title: '鐗╂枡缂栫爜', width: 120 },
-        { field: 'materielName', title: '鐗╂枡鍚嶇О', width: 150 },
-        { field: 'pickQuantity', title: '鎷i�夋暟閲�', width: 100 },
-        { field: 'palletCode', title: '鎵樼洏缂栧彿', width: 120 },
-        { field: 'pickTime', title: '鎷i�夋椂闂�', width: 160 },
-        { field: 'operator', title: '鎿嶄綔浜�', width: 100 },
-        { field: 'action', title: '鎿嶄綔', width: 80, slot: true }
-      ],
-      splitVisible: false,
-      maxPickQuantity: 0,
-      allLockInfos: [] // 鏂板锛氫繚瀛樻墍鏈夐攣瀹氫俊鎭紝鐢ㄤ簬鏉$爜鍖归厤
-    }
-  },
-  computed: {
-    unpickedCount() {
-      return this.orderInfo.unpickedCount || 0
-    },
-    unpickedQuantity() {
-      return this.orderInfo.unpickedQuantity || 0
-    }
-  },
-  methods: {
-    goBack() {
-      this.$router.back()
-    },
-
-    async loadOrderInfo() {
-      const orderId = this.$route.query.orderId
-      if (!orderId) return
-
-      try {
-        const result = await this.http.get(`api/OutboundOrder/GetById?id=${orderId}`)
-        if (result.status) {
-          this.orderInfo = result.data
-        }
-      } catch (error) {
-        this.$message.error('鍔犺浇鍑哄簱鍗曚俊鎭け璐�')
-      }
-    },
-
-    async handlePalletScan() {
-      if (!this.scanForm.palletCode) {
-        this.$message.warning('璇疯緭鍏ユ墭鐩樻潯鐮�')
-        return
-      }
-
-      try {
-        const result = await this.http.get(
-          `api/OutboundPicking/GetPalletOutboundStatus?palletCode=${this.scanForm.palletCode}`
-        )
-        if (result.status) {
-          this.currentPallet = result.data
-          await this.loadPalletLockInfo()
-          this.$message.success(`鎵樼洏 ${this.scanForm.palletCode} 璇嗗埆鎴愬姛`)
-        } else {
-          this.$message.error(result.message)
-        }
-      } catch (error) {
-        this.$message.error('鎵樼洏璇嗗埆澶辫触')
-      }
-    },
-
-    async loadPalletLockInfo() {
-      if (!this.currentPallet) return
-
-      try {
-        const result = await this.http.get(
-          `api/OutboundPicking/GetPalletLockInfos?palletCode=${this.currentPallet.palletCode}`
-        )
-        if (result.status) {
-          this.allLockInfos = result.data
-          // 榛樿閫夋嫨绗竴涓攣瀹氫俊鎭�
-          if (this.allLockInfos.length > 0) {
-            this.currentLockInfo = this.allLockInfos[0]
-            this.currentMaterialInfo = {
-              materielCode: this.currentLockInfo.materielCode,
-              materielName: this.currentLockInfo.materielName
-            }
-            this.maxPickQuantity = this.currentLockInfo.assignQuantity - this.currentLockInfo.pickedQty
-          }
-        }
-      } catch (error) {
-        console.error('鍔犺浇閿佸畾淇℃伅澶辫触:', error)
-      }
-    },
-
-    // 鏍规嵁鏉$爜鏌ユ壘瀵瑰簲鐨勯攣瀹氫俊鎭拰鐗╂枡淇℃伅
-    findLockInfoByBarcode(barcode) {
-      if (!this.allLockInfos || this.allLockInfos.length === 0) {
-        return null
-      }
-      
-      // 棣栧厛绮剧‘鍖归厤褰撳墠鏉$爜
-      let lockInfo = this.allLockInfos.find(x => x.currentBarcode === barcode)
-      if (lockInfo) {
-        return lockInfo
-      }
-      
-      // 濡傛灉娌℃湁绮剧‘鍖归厤锛屾煡鎵捐鏉$爜瀵瑰簲鐨勭墿鏂欐槸鍚﹀湪閿佸畾淇℃伅涓�
-      // 杩欓噷闇�瑕佽皟鐢ㄥ悗绔帴鍙i獙璇佹潯鐮佸搴旂殑鐗╂枡
-      return null
-    },
-
-    async handleBarcodeScan() {
-      if (!this.scanForm.barcode) {
-        this.$message.warning('璇疯緭鍏ョ墿鏂欐潯鐮�')
-        return
-      }
-
-      if (!this.currentPallet) {
-        this.$message.warning('璇峰厛鎵弿鎵樼洏鏉$爜')
-        return
-      }
-
-      if (this.scanForm.quantity <= 0) {
-        this.$message.warning('璇疯緭鍏ユ湁鏁堢殑鎷i�夋暟閲�')
-        return
-      }
-
-      try {
-        // 楠岃瘉鏉$爜骞惰幏鍙栫墿鏂欎俊鎭�
-        const materialInfo = await this.validateBarcode(this.scanForm.barcode)
-        if (!materialInfo) {
-          this.$message.error('鏃犳晥鐨勭墿鏂欐潯鐮�')
-          return
-        }
-
-        // 鏌ユ壘瀵瑰簲鐨勯攣瀹氫俊鎭�
-        const targetLockInfo = this.findLockInfoByBarcodeAndMaterial(this.scanForm.barcode, materialInfo.materielCode)
-        if (!targetLockInfo) {
-          this.$message.error('璇ョ墿鏂欐潯鐮佷笉鍦ㄥ綋鍓嶆墭鐩樼殑閿佸畾淇℃伅涓�')
-          return
-        }
-
-        // 妫�鏌ユ嫞閫夋暟閲�
-        const availableQuantity = targetLockInfo.assignQuantity - targetLockInfo.pickedQty
-        if (this.scanForm.quantity > availableQuantity) {
-          this.$message.error(`鎷i�夋暟閲忚秴杩囧彲鐢ㄦ暟閲忥紝鍓╀綑鍙嫞閫夛細${availableQuantity}`)
-          return
-        }
-
-        // 鍑嗗璇锋眰鏁版嵁
-        const request = {
-          orderDetailId: targetLockInfo.orderDetailId,
-          barcode: this.scanForm.barcode,
-          materielCode: materialInfo.materielCode, // 浼犻�掔墿鏂欑紪鐮�
-          pickQuantity: this.scanForm.quantity,
-          locationCode: this.currentPallet.locationCode,
-          palletCode: this.currentPallet.palletCode,
-          stockId: targetLockInfo.stockId,
-          outStockLockInfoId: targetLockInfo.id // 浼犻�掗攣瀹氫俊鎭疘D
-        }
-
-        const result = await this.http.post('api/OutboundPicking/ConfirmPicking', request)
-        if (result.status) {
-          this.$message.success('鎷i�夌‘璁ゆ垚鍔�')
-          
-          // 閲嶇疆琛ㄥ崟
-          this.scanForm.barcode = ''
-          this.scanForm.quantity = 1
-          this.currentMaterialInfo = null
-          
-          // 鍒锋柊鏁版嵁
-          this.loadOrderInfo()
-          this.loadPickedHistory()
-          this.loadPalletLockInfo()
-        } else {
-          this.$message.error(result.message)
-        }
-      } catch (error) {
-        this.$message.error('鎷i�夌‘璁ゅけ璐�: ' + (error.message || '鏈煡閿欒'))
-      }
-    },
-
-    // 鏍规嵁鏉$爜鍜岀墿鏂欑紪鐮佹煡鎵鹃攣瀹氫俊鎭�
-    findLockInfoByBarcodeAndMaterial(barcode, materielCode) {
-      if (!this.allLockInfos || this.allLockInfos.length === 0) {
-        return null
-      }
-      
-      // 棣栧厛灏濊瘯绮剧‘鍖归厤鏉$爜
-      let lockInfo = this.allLockInfos.find(x => 
-        x.currentBarcode === barcode && x.materielCode === materielCode
-      )
-      
-      if (lockInfo) {
-        return lockInfo
-      }
-      
-      // 濡傛灉绮剧‘鍖归厤澶辫触锛屽彧鍖归厤鐗╂枡缂栫爜锛堝厑璁镐粠鍚屼竴鐗╂枡鐨勪笉鍚屾潯鐮佹嫞閫夛級
-      lockInfo = this.allLockInfos.find(x => 
-        x.materielCode === materielCode && 
-        (x.assignQuantity - x.pickedQty) > 0
-      )
-      
-      return lockInfo
-    },
-
-    // 楠岃瘉鏉$爜骞惰幏鍙栫墿鏂欎俊鎭�
-    async validateBarcode(barcode) {
-      try {
-        const result = await this.http.get(`api/OutboundPicking/ValidateBarcode?barcode=${barcode}`)
-        if (result.status) {
-          return result.data
-        } else {
-          this.$message.error(result.message)
-          return null
-        }
-      } catch (error) {
-        this.$message.error('鏉$爜楠岃瘉澶辫触')
-        return null
-      }
-    },
-
-    async handleBackToStock() {
-      if (!this.currentPallet) return
-
-      try {
-        await this.$confirm(`纭畾灏嗘墭鐩� ${this.currentPallet.palletCode} 鍥炲簱鍚楋紵`, '鎻愮ず', {
-          type: 'warning'
-        })
-
-        const result = await this.http.post('api/BackToStock/GenerateBackToStockTask', {
-          palletCode: this.currentPallet.palletCode,
-          currentLocation: '鎷i�変綅',
-          operator: '褰撳墠鐢ㄦ埛'
-        })
-
-        if (result.status) {
-          this.$message.success('鍥炲簱浠诲姟宸茬敓鎴�')
-          this.resetCurrentPallet()
-        }
-      } catch (error) {
-        // 鐢ㄦ埛鍙栨秷
-      }
-    },
-
-    async handleDirectOutbound() {
-      if (!this.currentPallet) return
-
-      try {
-        await this.$confirm(`纭畾灏嗘墭鐩� ${this.currentPallet.palletCode} 鐩存帴鍑哄簱鍚楋紵`, '鎻愮ず', {
-          type: 'warning'
-        })
-
-        const result = await this.http.post('api/OutboundPicking/DirectOutbound', {
-          palletCode: this.currentPallet.palletCode
-        })
-
-        if (result.status) {
-          this.$message.success('鐩存帴鍑哄簱鎴愬姛')
-          this.resetCurrentPallet()
-          this.loadOrderInfo()
-        }
-      } catch (error) {
-        // 鐢ㄦ埛鍙栨秷
-      }
-    },
-
-    handleOpenSplit() {
-      if (!this.currentLockInfo) {
-        this.$message.warning('璇峰厛閫夋嫨閿佸畾淇℃伅')
-        return
-      }
-      this.splitVisible = true
-    },
-
-    handleSplitSuccess() {
-      this.$message.success('鎷嗗寘鎴愬姛')
-      this.loadPalletLockInfo()
-    },
-
-    resetCurrentPallet() {
-      this.currentPallet = null
-      this.currentLockInfo = null
-      this.currentMaterialInfo = null
-      this.allLockInfos = []
-      this.scanForm.palletCode = ''
-    },
-
-    async loadPickedHistory() {
-      const orderId = this.$route.query.orderId
-      if (!orderId) return
-
-      try {
-        const result = await this.http.get(`api/OutboundPicking/GetPickingHistory?orderId=${orderId}`)
-        if (result.status) {
-          this.pickedList = result.data
-        }
-      } catch (error) {
-        console.error('鍔犺浇鎷i�夊巻鍙插け璐�:', error)
-      }
-    },
-
-    async handleCancelPick(row) {
-      try {
-        await this.$confirm('纭畾鎾ら攢杩欐潯鎷i�夎褰曞悧锛�', '鎻愮ず', { type: 'warning' })
-        
-        const result = await this.http.post('api/OutboundPicking/CancelPicking', {
-          pickingHistoryId: row.id
-        })
-
-        if (result.status) {
-          this.$message.success('鎾ら攢鎴愬姛')
-          this.loadPickedHistory()
-          this.loadOrderInfo()
-        }
-      } catch (error) {
-        // 鐢ㄦ埛鍙栨秷
-      }
+      palletSummary: null,
+      confirmLoading: false,
+      pickedTableConfig: {
+        url: '/api/outbound/getPickingRecords',
+        query: { orderNo: this.orderNo },
+        columns: [
+          { prop: 'TaskNo', label: '浠诲姟鍙�', width: 150 },
+          { prop: 'Barcode', label: '鐗╂枡鏉$爜', width: 150 },
+          { prop: 'MaterielName', label: '鐗╂枡鍚嶇О', width: 150 },
+          { prop: 'PickQuantity', label: '鎷h揣鏁伴噺', width: 100 },
+          { prop: 'LocationCode', label: '璐т綅', width: 120 },
+          { prop: 'CreateTime', label: '鎷h揣鏃堕棿', width: 180 }
+        ]
+      },
+      // 鍑哄簱璇︽儏琛ㄦ牸閰嶇疆
+      outboundTableConfig: {
+        url: '/api/outbound/getOutboundDetails',
+        query: { orderNo: this.orderNo },
+        columns: [
+          { prop: 'OrderNo', label: '鍑哄簱鍗曞彿', width: 150 },
+          { prop: 'MaterialCode', label: '鐗╂枡缂栧彿', width: 120 },
+          { prop: 'MaterialBarcode', label: '鐗╂枡鏉$爜', width: 150 },
+          { prop: 'BatchNo', label: '鎵规鍙�', width: 120 },
+          { prop: 'AssignQuantity', label: '鍒嗛厤鍑哄簱閲�', width: 100 },
+          { prop: 'PalletCode', label: '鎵樼洏缂栧彿', width: 120 },
+          { prop: 'Unit', label: '鍗曚綅', width: 80 }
+        ]
+      },
+      orderInfo: {orderNo:''}
     }
   },
   mounted() {
-    this.loadOrderInfo()
-    this.loadPickedHistory()
+    this.loadOrderInfo();
+    this.$nextTick(() => {
+      if (this.$refs.palletInput) {
+        this.$refs.palletInput.focus()
+      }
+    })
+  },
+  methods: {
+    loadOrderInfo() {
+      const orderId = this.$route.query.orderId
+      if (!orderId) return
+
+      try {
+        this.http.get(`/api/OutboundOrder/GetById?id=${orderId}`).then(response => {debugger;
+          if (response.status) {
+            this.orderInfo = response.data
+              
+          }
+        })
+      } catch (error) {
+        ElMessage.error('鍔犺浇鍑哄簱鍗曚俊鎭け璐�')
+      }
+    },
+     goBack() {
+      this.$router.back()
+    },
+    async handlePalletScan() {
+      if (this.scanForm.palletCode) {
+        ElMessage.success(`宸叉壂鎻忔墭鐩�: ${this.scanForm.palletCode}`)
+        await this.loadPalletSummary()
+
+        this.$nextTick(() => {
+          if (this.$refs.materialInput) {
+            this.$refs.materialInput.focus()
+          }
+        })
+      }
+    },
+    async handleMaterialScan() {
+      if (!this.scanForm.palletCode) {
+        ElMessage.warning('璇峰厛鎵弿鎵樼洏鐮�')
+        this.$refs.palletInput.focus()
+        return
+      }
+
+      if (!this.scanForm.materialBarcode) {
+        ElMessage.warning('璇锋壂鎻忕墿鏂欐潯鐮�')
+        return
+      }
+
+      await this.executePickingConfirm()
+    },
+    async loadPalletSummary() {
+      if (!this.scanForm.palletCode) {
+        this.palletSummary = null
+        return
+      }
+
+      try {
+        const result = await http.get('/api/outbound/getPalletPickingSummary', {
+          params: {
+            orderNo: this.orderNo,
+            palletCode: this.scanForm.palletCode
+          }
+        })
+
+        if (result.success) {
+          // 澶勭悊缁熻淇℃伅
+          const summary = result.data
+          const assigned = summary.find(x => x.Status === '宸插垎閰�') || { TotalAssignQty: 0, TotalPickedQty: 0 }
+          const picked = summary.find(x => x.Status === '宸叉嫞閫�') || { TotalPickedQty: 0 }
+
+          this.palletSummary = {
+            unpickedCount: assigned.TotalAssignQty > 0 ? 1 : 0, // 绠�鍖栬绠�
+            unpickedTotal: assigned.TotalAssignQty - assigned.TotalPickedQty
+          }
+        }
+      } catch (error) {
+        console.error('鍔犺浇鎵樼洏缁熻澶辫触:', error)
+      }
+    },
+    async handleConfirm() {
+      if (!this.scanForm.palletCode || !this.scanForm.materialBarcode) {
+        ElMessage.warning('璇峰~鍐欏畬鏁寸殑鎵爜淇℃伅')
+        return
+      }
+
+      await this.executePickingConfirm()
+    },
+    async executePickingConfirm() {
+      this.confirmLoading = true
+
+      try {
+        // 鍏堟壘鍒板搴旂殑鍑哄簱閿佸畾淇℃伅
+        const lockInfoResult = await this.http.get('/api/outbound/getOutStockLockInfo', {
+          params: {
+            orderNo: this.orderNo,
+            palletCode: this.scanForm.palletCode,
+            materialBarcode: this.scanForm.materialBarcode
+          }
+        })
+
+        if (!lockInfoResult.success || !lockInfoResult.data || lockInfoResult.data.length === 0) {
+          ElMessage.error('鏈壘鍒板搴旂殑鍑哄簱閿佸畾淇℃伅')
+          return
+        }
+
+        const lockInfo = lockInfoResult.data[0]
+
+        const request = {
+          outStockLockId: lockInfo.Id,
+          taskNo: `TASK_${Date.now()}`,
+          palletCode: this.scanForm.palletCode,
+          materialBarcode: this.scanForm.materialBarcode,
+          locationCode: lockInfo.LocationCode
+        }
+
+        const result = await this.http.post('/api/outbound/pickingConfirm', request)
+
+        if (result.success) {
+          ElMessage.success('鍒嗘嫞纭鎴愬姛')
+          this.handleReset()
+          this.$emit('confirm')
+
+          // 鍒锋柊琛ㄦ牸
+          if (this.$refs.pickedTable) {
+            this.$refs.pickedTable.refresh()
+          }
+          
+          // 鍒锋柊鍑哄簱璇︽儏琛ㄦ牸
+          if (this.$refs.outboundTable) {
+            this.$refs.outboundTable.refresh()
+          }
+
+          // 閲嶆柊鍔犺浇鎵樼洏缁熻
+          await this.loadPalletSummary()
+        } else {
+          ElMessage.error(result.ElMessage)
+        }
+      } catch (error) {
+        ElMessage.error('鍒嗘嫞纭澶辫触')
+      } finally {
+        this.confirmLoading = false
+      }
+    },
+    handleReset() {
+      this.scanForm.materialBarcode = ''
+      this.$nextTick(() => {
+        if (this.$refs.materialInput) {
+          this.$refs.materialInput.focus()
+        }
+      })
+    }
   }
-}
+})
 </script>
 
 <style scoped>
 .picking-confirm {
-  padding: 20px;
+  display: flex;
+  flex-direction: column;
+  height: 70vh;
 }
 
-.page-header {
-  margin-bottom: 20px;
+.content-layout {
+  display: flex;
+  gap: 16px;
+  margin-bottom: 16px;
+  flex: 1;
+  min-height: 0; /* 閲嶈锛氶槻姝lex瀛愬厓绱犳孩鍑� */
 }
 
-.title {
-  font-size: 18px;
-  font-weight: bold;
+.left-section {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+
+.right-section {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
 }
 
 .scan-section {
-  margin-bottom: 20px;
+  flex-shrink: 0;
+}
+
+.scan-alert {
+  margin-bottom: 16px;
+}
+
+.scan-form {
+  max-width: 500px;
+}
+
+.pallet-summary {
+  margin: 16px 0;
 }
 
 .action-buttons {
+  margin-top: 16px;
+}
+
+.outbound-details-card {
+  height: 100%;
   display: flex;
   flex-direction: column;
-  gap: 10px;
 }
 
-.action-buttons .el-button {
-  width: 100%;
+.outbound-details-card :deep(.el-card__body) {
+  flex: 1;
+  padding: 0;
 }
 
-.current-info {
-  margin-top: 15px;
-  padding: 10px;
-  background-color: #f5f7fa;
-  border-radius: 4px;
+.picked-records {
+  flex-shrink: 0;
+  height: 300px;
 }
 
-.current-info p {
-  margin: 5px 0;
-  font-size: 14px;
-}
-
-.summary-info {
-  margin-bottom: 15px;
+.picked-records :deep(.el-card__body) {
+  padding: 0;
 }
 </style>
\ No newline at end of file
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/vue.config.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/vue.config.js"
index 2d3d8d5..0bdf11a 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/vue.config.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/vue.config.js"
@@ -1,4 +1,3 @@
-// const webpack = require("webpack");
 
 module.exports = {
   productionSourceMap: false,
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/WarehouseService.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/WarehouseService.cs"
index 5ca706b..82c58f0 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/WarehouseService.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/WarehouseService.cs"
@@ -89,17 +89,28 @@
             var lists = _warehouseArearepository.Db.Queryable<Dt_WarehouseArea>().ToList();
             foreach (var item in models)
             {
-                var dbfirst = lists.FirstOrDefault(x => x.Code == item.Code);
-                if (dbfirst != null)
+                if (item.IsDelete == 1)
                 {
-                    dbfirst.Code = item.Code;
-                    dbfirst.Name = item.Name;
-                    dbfirst.FactoryArea = item.FactoryArea;
-                    _warehouseArearepository.UpdateData(dbfirst);
+                  var first=  _warehouseArearepository.Db.Queryable<Dt_WarehouseArea>().First(x => x.Code == item.Code);
+                    if(first != null)
+                    {
+                        _warehouseArearepository.DeleteData(first);
+                    }
                 }
                 else
                 {
-                    _warehouseArearepository.AddData(new Dt_WarehouseArea { Code=item.Code,Name=item.Name,FactoryArea=item.FactoryArea});
+                    var dbfirst = lists.FirstOrDefault(x => x.Code == item.Code);
+                    if (dbfirst != null)
+                    {
+                        dbfirst.Code = item.Code;
+                        dbfirst.Name = item.Name;
+                        dbfirst.FactoryArea = item.FactoryArea;
+                        _warehouseArearepository.UpdateData(dbfirst);
+                    }
+                    else
+                    {
+                        _warehouseArearepository.AddData(new Dt_WarehouseArea { Code = item.Code, Name = item.Name, FactoryArea = item.FactoryArea });
+                    }
                 }
             }
             return WebResponseContent.Instance.OK();
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_DTO/Basic/SupplierDTO.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_DTO/Basic/SupplierDTO.cs"
index b051017..ab2a822 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_DTO/Basic/SupplierDTO.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_DTO/Basic/SupplierDTO.cs"
@@ -70,7 +70,7 @@
         /// 搴撳瓨缁勭粐
         /// </summary>
         [PropertyValidate("搴撳瓨缁勭粐", NotNullAndEmpty = true)]
-        public string InvOrgId { get; set; } = "娣畨鐗瑰垱浜屽巶";
+        public string InvOrgId { get; set; } = "";
 
         /// <summary>
         /// 鎿嶄綔绫诲瀷
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_DTO/Outbound/OutboundOrderGetDTO.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_DTO/Outbound/OutboundOrderGetDTO.cs"
index 88aa0f7..72d582e 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_DTO/Outbound/OutboundOrderGetDTO.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_DTO/Outbound/OutboundOrderGetDTO.cs"
@@ -4,6 +4,7 @@
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using WIDESEA_Model.Models;
 
 namespace WIDESEA_DTO.Outbound
 {
@@ -22,7 +23,12 @@
         public decimal SplitQuantity { get; set; }
         public string Operator { get; set; }
     }
-
+    public class ConfirmPickingDto
+    {
+        public string OrderNo { get; set; }
+        public string PalletCode { get; set; }
+        public string Barcode { get; set; }
+    }
 
     public class PickingConfirmRequest
     {
@@ -115,7 +121,11 @@
         public string CurrentBarcode { get; set; } = string.Empty;
         public decimal AssignQuantity { get; set; }
     }
-
+    public class LockInfoDetailDto : Dt_OutStockLockInfo
+    {
+        public string MaterielName { get; set; }
+        public string Unit { get; set; }
+    }
     public class MaterielBarcodeValidateOutput : OutputDto
     {
         public bool IsValid { get; set; }
@@ -213,4 +223,24 @@
         public decimal pickQuantity { get; set; }
         public string pickTime { get; set; } = string.Empty;
     }
+
+    public class CancelPickingDto
+    {
+        public string OrderNo { get; set; }
+        public string PalletCode { get; set; }
+        public string Barcode { get; set; }
+    }
+
+    public class SplitPackageDto
+    {
+        public string OrderNo { get; set; }
+        public string PalletCode { get; set; }
+        public string OriginalBarcode { get; set; }
+        public decimal SplitQuantity { get; set; }
+    }
+
+    public class RevertSplitDto
+    {
+        public string OriginalBarcode { get; set; }
+    }
 }
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_IOutboundService/IOutStockLockInfoService.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_IOutboundService/IOutStockLockInfoService.cs"
index 6d4dd63..154ef55 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_IOutboundService/IOutStockLockInfoService.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_IOutboundService/IOutStockLockInfoService.cs"
@@ -8,6 +8,7 @@
 using WIDESEA_Core.BaseRepository;
 using WIDESEA_Core.BaseServices;
 using WIDESEA_Core.Enums;
+using WIDESEA_DTO.Outbound;
 using WIDESEA_Model.Models;
 
 namespace WIDESEA_IOutboundService
@@ -21,8 +22,8 @@
  
         Task<List<Dt_OutStockLockInfo>> GetByOrderDetailId(int orderDetailId);
         Task<List<Dt_OutStockLockInfo>> GetByPalletCode(string palletCode, int? status = null);
- 
 
+        Task<LockInfoDetailDto> GetLockInfoDetail(int lockInfoId);
         Dt_OutStockLockInfo GetOutStockLockInfo(Dt_OutboundOrder outboundOrder,Dt_OutboundOrderDetail outboundOrderDetail,Dt_StockInfo outStock, decimal assignQuantity, string barcode = null);
         Task<List<Dt_OutStockLockInfo>> GetPalletLockInfos(string palletCode);
         Task<WebResponseContent> UpdateLockInfoBarcode(int lockInfoId, string newBarcode);
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_IOutboundService/IOutboundPickingService.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_IOutboundService/IOutboundPickingService.cs"
index bc178b0..ceac439 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_IOutboundService/IOutboundPickingService.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_IOutboundService/IOutboundPickingService.cs"
@@ -16,9 +16,17 @@
         IRepository<Dt_PickingRecord> Repository { get; }
 
         Task<WebResponseContent> CancelPicking(CancelPickingRequest request);
+        Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode);
         Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request);
-        Task<List<Dt_PickingRecord>> GetPickingHistory(int orderId);
-         Task<WebResponseContent> ValidateBarcode(string barcode);
+        Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode);
+        Task<WebResponseContent> DirectOutbound(DirectOutboundRequest request);
+        Task<List<OutStockLockListResp>> GetOutStockLockListAsync(string orderNo);
         Task<WebResponseContent> GetPalletOutboundStatus(string palletCode);
+        Task GetPalletPickingSummary(string orderNo, string palletCode);
+        Task<List<Dt_OutStockLockInfo>> GetPickedList(string orderNo, string palletCode);
+        Task<List<Dt_PickingRecord>> GetPickingHistory(int orderId);
+        Task<object> GetPickingSummary(string orderNo);
+        Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode);
+        Task<WebResponseContent> ValidateBarcode(string barcode);
     }
 }
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_IOutboundService/ISplitPackageService.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_IOutboundService/ISplitPackageService.cs"
index aeeb77d..c19e7a8 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_IOutboundService/ISplitPackageService.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_IOutboundService/ISplitPackageService.cs"
@@ -15,6 +15,11 @@
     {
         IRepository<Dt_SplitPackageRecord> Repository { get; }
 
-        Task<WebResponseContent> SplitPackage(SplitPackageRequest request);
+        Task<WebResponseContent> SplitPackage(SplitPackageDto request);
+
+          Task<WebResponseContent> RevertSplitPackage(string originalBarcode);
+        Task<WebResponseContent> GetSplitPackageInfo(string orderNo, string palletCode, string barcode);
+
+        Task<WebResponseContent> GetSplitableLockInfos(int orderDetailId);
     }
 }
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_Model/Models/Outbound/Dt_OutboundLockInfo.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_Model/Models/Outbound/Dt_OutboundLockInfo.cs"
index 53fcc79..03bc89c 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_Model/Models/Outbound/Dt_OutboundLockInfo.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_Model/Models/Outbound/Dt_OutboundLockInfo.cs"
@@ -127,5 +127,8 @@
         [Navigate(NavigateType.OneToOne, nameof(StockInfo))]//涓�瀵逛竴 SchoolId鏄疭tudentA绫婚噷闈㈢殑
         public Dt_StockInfo StockInfo { get; set; } //涓嶈兘璧嬪�煎彧鑳芥槸null
 
+        [SugarColumn(IsIgnore = true)]
+        public decimal RemainQuantity => AssignQuantity - PickedQty;
+
     }
 }
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_Model/Models/Outbound/Dt_OutboundOrderDetail.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_Model/Models/Outbound/Dt_OutboundOrderDetail.cs"
index 056d47f..0a17802 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_Model/Models/Outbound/Dt_OutboundOrderDetail.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_Model/Models/Outbound/Dt_OutboundOrderDetail.cs"
@@ -111,5 +111,8 @@
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDescription = "澶囨敞")]
         public string Remark { get; set; }
+
+        [SugarColumn(IsIgnore = true)]
+        public decimal NeedOutQuantity => OrderQuantity - MoveQty;
     }
 }
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_Model/Models/Outbound/Dt_PickingRecord.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_Model/Models/Outbound/Dt_PickingRecord.cs"
index 8700510..f291fa0 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_Model/Models/Outbound/Dt_PickingRecord.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_Model/Models/Outbound/Dt_PickingRecord.cs"
@@ -19,8 +19,13 @@
     {
         [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
         public int Id { get; set; }
-
+        public string OrderNo { get; set; }
         public int OrderDetailId { get; set; }
+
+        public string PalletCode { get; set; }
+
+        public int OutStockLockId { get; set; }
+        public string MaterielCode { get; set; }
 
         [SugarColumn(Length = 100)]
         public string Barcode { get; set; }
@@ -37,8 +42,8 @@
 
         public int StockId { get; set; }
     }
- 
 
+ 
     /// <summary>
     /// 鍥炲簱璁板綍琛�
     /// </summary>
@@ -73,7 +78,10 @@
     {
         [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
         public int Id { get; set; }
-
+        public string OrderNo { get; set; }
+        public string PalletCode { get; set; }
+        public string StockId { get; set; }
+        public bool IsReverted { get; set; } = false;
         public int OutStockLockInfoId { get; set; } // 鍏宠仈鐨勫嚭搴撻攣瀹氫俊鎭�
         public string OriginalBarcode { get; set; } // 鍘熸潯鐮�
         public string NewBarcode { get; set; } // 鏂版潯鐮�
@@ -82,14 +90,14 @@
         /// 鎷嗗垎鏁伴噺锛堟柊鏉$爜鏁伴噺锛�
         /// </summary>
         public decimal SplitQty { get; set; }
- 
 
- 
+        public decimal RemainQuantity { get; set; }
+
         public string MaterielCode { get; set; } // 鐗╂枡缂栫爜
         public DateTime SplitTime { get; set; } = DateTime.Now;
         public string Operator { get; set; } // 鎿嶄綔浜�
         public int Status { get; set; } // 鐘舵�侊細1-宸叉媶鍖� 2-宸叉嫞閫� 3-宸插洖搴�
     }
+ 
 
-    
 }
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/OutStockLockInfoService.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/OutStockLockInfoService.cs"
index d407809..e93585a 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/OutStockLockInfoService.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/OutStockLockInfoService.cs"
@@ -1,4 +1,5 @@
-锘縰sing System;
+锘縰sing Microsoft.AspNetCore.Http;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -10,6 +11,7 @@
 using WIDESEA_Core.BaseServices;
 using WIDESEA_Core.Enums;
 using WIDESEA_Core.Helper;
+using WIDESEA_DTO.Outbound;
 using WIDESEA_IRecordService;
 using WIDESEA_IStockService;
 using WIDESEA_Model.Models;
@@ -117,6 +119,37 @@
                 .ToListAsync();
         }
 
+        public async Task<LockInfoDetailDto> GetLockInfoDetail(int lockInfoId)
+        {
+            var lockInfo = await Db.Queryable<Dt_OutStockLockInfo>()
+                .LeftJoin<Dt_OutboundOrderDetail>((lockInfo, detail) => lockInfo.OrderDetailId == detail.Id)
+                .Where((lockInfo, detail) => lockInfo.Id == lockInfoId)
+                .Select((lockInfo, detail) => new LockInfoDetailDto
+                {
+                    Id = lockInfo.Id,
+                    OrderNo = lockInfo.OrderNo,
+                    OrderDetailId = lockInfo.OrderDetailId,
+                    BatchNo = lockInfo.BatchNo,
+                    MaterielCode = lockInfo.MaterielCode,
+                    StockId = lockInfo.StockId,
+                    OrderQuantity = lockInfo.OrderQuantity,
+                    OriginalQuantity = lockInfo.OriginalQuantity,
+                    AssignQuantity = lockInfo.AssignQuantity,
+                    PickedQty = lockInfo.PickedQty,
+                    LocationCode = lockInfo.LocationCode,
+                    PalletCode = lockInfo.PalletCode,
+                    Status = lockInfo.Status,
+                    IsSplitted = lockInfo.IsSplitted,
+                    ParentLockId = lockInfo.ParentLockId,
+                    
+                    MaterielName = detail.MaterielName,
+                    Unit = detail.Unit
+                })
+                .FirstAsync();
+
+            return lockInfo;
+        }
+
         /// <summary>
         /// 鏍规嵁鎵樼洏缂栧彿鑾峰彇鍑哄簱閿佸畾淇℃伅
         /// </summary>
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/OutboundPickingService.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/OutboundPickingService.cs"
index 82df3f5..fafc2a8 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/OutboundPickingService.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/OutboundPickingService.cs"
@@ -1,4 +1,6 @@
-锘縰sing System;
+锘縰sing Microsoft.AspNetCore.Http;
+using SqlSugar;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -9,6 +11,7 @@
 using WIDESEA_Core;
 using WIDESEA_Core.BaseRepository;
 using WIDESEA_Core.BaseServices;
+using WIDESEA_Core.Helper;
 using WIDESEA_DTO.Outbound;
 using WIDESEA_IBasicService;
 using WIDESEA_IOutboundService;
@@ -31,10 +34,11 @@
         private readonly IStockInfoDetailService _stockInfoDetailService;
         private readonly ILocationInfoService _locationInfoService;
         private readonly IOutboundOrderDetailService _outboundOrderDetailService;
+        private readonly IOutboundOrderService _outboundOrderService;
         private readonly ISplitPackageService _splitPackageService;
- 
 
-        public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService) : base(BaseDal)
+
+        public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService) : base(BaseDal)
         {
             _unitOfWorkManage = unitOfWorkManage;
             _stockInfoService = stockInfoService;
@@ -44,9 +48,10 @@
             _locationInfoService = locationInfoService;
             _outboundOrderDetailService = outboundOrderDetailService;
             _splitPackageService = splitPackageService;
+            _outboundOrderService = outboundOrderService;
         }
 
-   
+
         #region 鏌ヨ鍑哄簱璇︽儏鍒楄〃
         public async Task<List<OutStockLockListResp>> GetOutStockLockListAsync(string orderNo)
         {
@@ -57,13 +62,13 @@
             return locks.Select(t => new OutStockLockListResp
             {
                 Id = t.Id,
-               // TaskNum = t.TaskNum,
+                // TaskNum = t.TaskNum,
                 PalletCode = t.PalletCode,
                 CurrentBarcode = t.CurrentBarcode,
                 AssignQuantity = t.AssignQuantity,
                 PickedQty = t.PickedQty,
                 Status = t.Status,
-              //  IsSplitted = t.IsSplitted
+                //  IsSplitted = t.IsSplitted
             }).ToList();
         }
         #endregion
@@ -87,13 +92,13 @@
                     return WebResponseContent.Instance.Error("鏉$爜涓嶅瓨鍦�");
                 }
 
-                
+
 
                 var result = new
                 {
                     Barcode = barcode,
                     MaterielCode = stockDetail.MaterielCode,
-                 
+
                     BatchNo = stockDetail.BatchNo,
                     AvailableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity,
                     LocationCode = stockDetail.StockInfo?.LocationCode,
@@ -203,6 +208,162 @@
             }
         }
 
+        public async Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode)
+        {
+            try
+            {
+                _unitOfWorkManage.BeginTran();
+                // 1. 楠岃瘉鏉$爜鏈夋晥鎬�
+                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                        .Where(x => x.Barcode == barcode)
+                        .FirstAsync();
+
+                if (stockDetail == null)
+                    return WebResponseContent.Instance.Error("鏃犳晥鐨勬潯鐮佹垨鐗╂枡缂栫爜");
+
+                // 2. 妫�鏌ュ簱瀛樺彲鐢ㄦ暟閲�
+                var availableQty = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
+                if (availableQty <= 0)
+                    return WebResponseContent.Instance.Error("搴撳瓨鏁伴噺涓嶈冻");
+
+                // 3. 鏌ユ壘鐩稿叧鐨勫嚭搴撹鎯呬俊鎭�
+                var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                    .Where(x => x.OrderNo == orderNo &&
+                               x.PalletCode == palletCode &&
+                               x.CurrentBarcode == barcode &&
+                               x.Status == 0 &&
+                               x.RemainQuantity > 0)
+                    .FirstAsync();
+
+                if (outStockInfo == null)
+                    return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑鎷i�変俊鎭垨宸叉嫞閫夊畬鎴�");
+
+                // 4. 妫�鏌ュ嚭搴撹鎯呴攣瀹氭暟閲�
+                if (outStockInfo.RemainQuantity <= 0)
+                    return WebResponseContent.Instance.Error("璇ユ潯鐮佸凡鏃犲墿浣欏彲鎷i�夋暟閲�");
+
+                // 5. 鏇存柊鍑哄簱璇︽儏鐨勫凡鎷i�夋暟閲�
+                outStockInfo.PickedQty = outStockInfo.AssignQuantity;
+                outStockInfo.Status = 1;
+                await _outStockLockInfoService.Db.Updateable(outStockInfo).ExecuteCommandAsync();
+
+                // 6. 鏇存柊搴撳瓨鍑哄簱鏁伴噺
+                await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>()
+                    .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity + outStockInfo.AssignQuantity)
+                    .Where(x => x.Id == stockDetail.Id)
+                    .ExecuteCommandAsync();
+
+                // 7. 鏇存柊鍑哄簱鍗曟槑缁�
+                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                    .Where(x => x.Id == outStockInfo.OrderDetailId)
+                    .FirstAsync();
+
+                orderDetail.OverOutQuantity += outStockInfo.AssignQuantity;
+                await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
+
+                // 8. 妫�鏌ユ槸鍚﹀畬鎴愬嚭搴�
+                await CheckAndUpdateOrderStatus(orderNo);
+
+                // 9. 璁板綍鎷i�夊巻鍙�
+                var pickingHistory = new Dt_PickingRecord
+                {
+
+                    OrderNo = orderNo,
+                    PalletCode = palletCode,
+                    Barcode = barcode,
+                    MaterielCode = outStockInfo.MaterielCode,
+                    PickQuantity = outStockInfo.AssignQuantity,
+                    PickTime = DateTime.Now,
+                    OutStockLockId = outStockInfo.Id
+                };
+                await Db.Insertable(pickingHistory).ExecuteCommandAsync();
+
+                _unitOfWorkManage.CommitTran();
+                return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔�");
+
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error($"鎷i�夌‘璁ゅけ璐ワ細{ex.Message}");
+            }
+        }
+        // 妫�鏌ュ苟鏇存柊璁㈠崟鐘舵��
+        private async Task CheckAndUpdateOrderStatus(string orderNo)
+        {
+
+
+            var orderDetails = await _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                .Where(x => x.OrderId == orderNo.ObjToInt())
+                .ToListAsync();
+
+            bool allCompleted = true;
+            foreach (var detail in orderDetails)
+            {
+                if (detail.OverOutQuantity < detail.NeedOutQuantity)
+                {
+                    allCompleted = false;
+                    break;
+                }
+            }
+
+            if (allCompleted)
+            {
+                await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+                    .SetColumns(x => x.OrderStatus == 2) // 宸插畬鎴�
+                    .Where(x => x.OrderNo == orderNo)
+                    .ExecuteCommandAsync();
+            }
+        }
+        // 鍙栨秷鎷i�夊姛鑳�
+        public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode)
+        {
+            try
+            {
+                _unitOfWorkManage.BeginTran();
+                // 鏌ユ壘鎷i�夎褰�
+                var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                        .Where(x => x.OrderNo == orderNo &&
+                                   x.PalletCode == palletCode &&
+                                   x.CurrentBarcode == barcode &&
+                                   x.Status == 1)
+                        .FirstAsync();
+
+                if (outStockInfo == null)
+                    return WebResponseContent.Instance.Error("鏈壘鍒板凡鎷i�夎褰�");
+
+                // 杩樺師鍑哄簱璇︽儏鐘舵��
+                outStockInfo.PickedQty = 0;
+                outStockInfo.Status = 0;
+                await _outStockLockInfoService.Db.Updateable(outStockInfo).ExecuteCommandAsync();
+
+                // 杩樺師搴撳瓨鍑哄簱鏁伴噺
+                await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>()
+                        .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity - outStockInfo.AssignQuantity)
+                        .Where(x => x.Barcode == barcode)
+                        .ExecuteCommandAsync();
+
+                // 杩樺師鍑哄簱鍗曟槑缁�
+                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                    .Where(x => x.Id == outStockInfo.OrderDetailId)
+                    .FirstAsync();
+
+                orderDetail.OverOutQuantity -= outStockInfo.AssignQuantity;
+                await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
+
+                // 鍒犻櫎鎷i�夊巻鍙�
+                await Db.Deleteable<Dt_PickingRecord>()
+                    .Where(x => x.OutStockLockId == outStockInfo.Id)
+                    .ExecuteCommandAsync();
+
+                _unitOfWorkManage.CommitTran();
+                return WebResponseContent.Instance.OK("鍙栨秷鎷i�夋垚鍔�");
+
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error($"鍙栨秷鎷i�夊け璐ワ細{ex.Message}");
+            }
+        }
         /// <summary>
         /// 鏍规嵁鏉$爜鏌ユ壘閿佸畾淇℃伅
         /// </summary>
@@ -217,6 +378,45 @@
                 .FirstAsync();
         }
 
+        // 鑾峰彇鏈嫞閫夊垪琛�
+        public async Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode)
+        {
+            var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(x => x.OrderNo == orderNo &&
+                           x.PalletCode == palletCode &&
+                           x.Status == 0 &&
+                       x.RemainQuantity > 0)
+                .ToListAsync();
+            return list;
+        }
+
+        // 鑾峰彇宸叉嫞閫夊垪琛�
+        public async Task<List<Dt_OutStockLockInfo>> GetPickedList(string orderNo, string palletCode)
+        {
+            var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(x => x.OrderNo == orderNo &&
+                           x.PalletCode == palletCode &&
+                           x.Status == 1)
+                .ToListAsync();
+            return list;
+        }
+        // 鑾峰彇鎷i�夋眹鎬�
+        public async Task<object> GetPickingSummary(string orderNo)
+        {
+            var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(x => x.OrderNo == orderNo && x.Status == 0)
+                .GroupBy(x => new { x.PalletCode, x.MaterielCode })
+                .Select(x => new
+                {
+                    PalletCode = x.PalletCode,
+                    MaterielCode = x.MaterielCode,
+                    UnpickedCount = SqlFunc.AggregateCount(x.Id),
+                    UnpickedQuantity = SqlFunc.AggregateSum(x.RemainQuantity)
+                })
+                .ToListAsync();
+
+            return  summary;
+        }
         /// <summary>
         /// 鑾峰彇鎷i�夊巻鍙�
         /// </summary>
@@ -235,6 +435,25 @@
                 .ToListAsync();
         }
 
+        public async Task GetPalletPickingSummary(string orderNo, string palletCode)
+        {
+            var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
+                .GroupBy(x => new { x.PalletCode, x.Status })
+                .Select(x => new
+                {
+                    PalletCode = x.PalletCode,
+                    Status = x.Status,
+                    TotalAssignQty = SqlFunc.AggregateSum(x.AssignQuantity),
+                    TotalPickedQty = SqlFunc.AggregateSum(x.PickedQty)
+                })
+                .ToListAsync();
+
+            //   return summary;
+        }
+
+
+
         /// <summary>
         /// 鎾ら攢鎷i��
         /// </summary>
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/SplitPackageService.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/SplitPackageService.cs"
index ddc6e54..33f0cd7 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/SplitPackageService.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/SplitPackageService.cs"
@@ -1,4 +1,5 @@
-锘縰sing System;
+锘縰sing Microsoft.AspNetCore.Http;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -34,40 +35,31 @@
         /// <summary>
         /// 鎷嗗寘鎷嗙鎿嶄綔
         /// </summary>
-        public async Task<WebResponseContent> SplitPackage(SplitPackageRequest request)
+        public async Task<WebResponseContent> SplitPackage(SplitPackageDto request)
         {
             try
             {
                 _unitOfWorkManage.BeginTran();
 
                 // 1. 楠岃瘉鍑哄簱閿佸畾淇℃伅
-                var lockInfo = await Db.Queryable<Dt_OutStockLockInfo>()
-                    .Where(x => x.Id == request.OutStockLockInfoId &&
-                               x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+                var lockInfo = await _stockInfoDetailService.Db.Queryable<Dt_OutStockLockInfo>()
+                          .Where(x => x.OrderNo == request.OrderNo &&
+                           x.PalletCode == request.PalletCode &&
+                           x.CurrentBarcode == request.OriginalBarcode &&
+                           x.Status == 0)
                     .FirstAsync();
 
                 if (lockInfo == null)
                     return WebResponseContent.Instance.Error("鏈壘鍒版湁鏁堢殑鍑哄簱閿佸畾淇℃伅");
-
-                //// 2. 楠岃瘉褰撳墠鏉$爜鐨勫彲鐢ㄦ暟閲�
-                //var currentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                //    .Where(x => x.Barcode == lockInfo.CurrentBarcode &&
-                //               x.MaterielCode == request.MaterielCode &&
-                //               x.StockId == lockInfo.StockId)
-                //    .FirstAsync();
-
-                //if (currentStockDetail == null)
-                //    return WebResponseContent.Instance.Error("褰撳墠鏉$爜鍦ㄥ簱瀛樹腑涓嶅瓨鍦�");
-
-                //// 3. 妫�鏌ュ彲鐢ㄦ暟閲�
-                //decimal availableQuantity = currentStockDetail.StockQuantity - currentStockDetail.OutboundQuantity;
-                //if (request.SplitQuantity > availableQuantity)
-                //    return WebResponseContent.Instance.Error($"鎷嗗寘鏁伴噺涓嶈兘澶т簬鍙敤鏁伴噺锛屽彲鐢ㄦ暟閲忥細{availableQuantity}");
-
+ 
                 // 2. 妫�鏌ュ墿浣欓攣瀹氭暟閲�
                 decimal remainingLockQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty;
                 if (request.SplitQuantity > remainingLockQuantity)
                     return WebResponseContent.Instance.Error($"鎷嗗寘鏁伴噺涓嶈兘澶т簬鍓╀綑閿佸畾鏁伴噺锛屽墿浣欙細{remainingLockQuantity}");
+
+                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+               .Where(x => x.Barcode == request.OriginalBarcode)
+               .FirstAsync();
 
                 // 3. 鐢熸垚鏂版潯鐮�
                 string newBarcode = "";
@@ -109,9 +101,11 @@
                     OriginalBarcode = lockInfo.CurrentBarcode,
                     NewBarcode = newBarcode,
                     SplitQty = request.SplitQuantity,
-                    MaterielCode = request.MaterielCode,
+                    RemainQuantity = lockInfo.RemainQuantity - request.SplitQuantity,
+                    MaterielCode = lockInfo.MaterielCode,
                     SplitTime = DateTime.Now,
-                    Operator = request.Operator,
+                    OrderNo = request.OrderNo,
+                    PalletCode = request.PalletCode,
                     Status = (int)SplitPackageStatusEnum.宸叉媶鍖�
                 };
                 await Db.Insertable(splitHistory).ExecuteCommandAsync();
@@ -134,6 +128,80 @@
             }
         }
 
+        // 鎾ら攢鎷嗗寘
+        public async Task<WebResponseContent> RevertSplitPackage(string originalBarcode)
+        {
+            try
+            {
+                _unitOfWorkManage.BeginTran();
+                // 鏌ユ壘鏈�杩戠殑鏈挙閿�鎷嗗寘璁板綍
+                var splitPackage = await Db.Queryable<Dt_SplitPackageRecord>()
+                        .Where(x => x.OriginalBarcode == originalBarcode && !x.IsReverted)
+                        .OrderByDescending(x => x.CreateDate)
+                        .FirstAsync();
+
+                    if (splitPackage == null)
+                        return  WebResponseContent.Instance.Error("鏈壘鍒版媶鍖呰褰�");
+
+                    // 妫�鏌ユ柊鏉$爜鏄惁宸叉嫞閫�
+                    var newOutStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                        .Where(x => x.CurrentBarcode == splitPackage.NewBarcode)
+                        .FirstAsync();
+
+                    if (newOutStockInfo.Status == 1)
+                        return  WebResponseContent.Instance.Error("鏂版潯鐮佸凡鎷i�夛紝鏃犳硶鎾ら攢鎷嗗寘");
+
+                    // 杩樺師鍘熷嚭搴撹鎯呮暟閲�
+                    var originalOutStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                        .Where(x => x.CurrentBarcode == originalBarcode)
+                        .FirstAsync();
+
+                    originalOutStockInfo.AssignQuantity += splitPackage.SplitQty;
+                    await _outStockLockInfoService.Db.Updateable(originalOutStockInfo).ExecuteCommandAsync();
+
+                    // 鍒犻櫎鏂板嚭搴撹鎯呰褰�
+                    await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
+                        .Where(x => x.CurrentBarcode == splitPackage.NewBarcode)
+                        .ExecuteCommandAsync();
+
+                    // 鏍囪鎷嗗寘璁板綍涓哄凡鎾ら攢
+                    splitPackage.IsReverted = true;
+                    await Db.Updateable(splitPackage).ExecuteCommandAsync();
+
+                _unitOfWorkManage.CommitTran();
+                    return  WebResponseContent.Instance.OK("鎾ら攢鎷嗗寘鎴愬姛");
+                
+            }
+            catch (Exception ex)
+            {
+                return  WebResponseContent.Instance.Error($"鎾ら攢鎷嗗寘澶辫触锛歿ex.Message}");
+            }
+        }
+
+        // 鑾峰彇鎷嗗寘淇℃伅
+        public async Task< WebResponseContent > GetSplitPackageInfo(string orderNo, string palletCode, string barcode)
+        {
+            var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(x => x.OrderNo == orderNo &&
+                           x.PalletCode == palletCode &&
+                           x.CurrentBarcode == barcode &&
+                           x.Status == 0)
+                .FirstAsync();
+
+            if (outStockInfo == null)
+                return  WebResponseContent.Instance .Error("鏈壘鍒板搴旂殑鍑哄簱淇℃伅");
+
+            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                .Where(x => x.Barcode == barcode)
+                .FirstAsync();
+
+            return  WebResponseContent.Instance .OK("",new
+            {
+                MaterielCode = outStockInfo.MaterielCode,
+                RemainQuantity = outStockInfo.RemainQuantity,
+                Unit = "涓�" // 鏍规嵁瀹為檯鎯呭喌鑾峰彇鍗曚綅
+            });
+        }
         /// <summary>
         /// 鑾峰彇鍙媶鍖呯殑鍑哄簱閿佸畾淇℃伅
         /// </summary>
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 f772492..8113068 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"
@@ -362,8 +362,7 @@
                     return content.Error($"鏈壘鍒板搴旂殑缁堢偣璐т綅淇℃伅");
                 }
 
-                _stockRepository.Db.Deleteable(stockInfo).ExecuteCommand();
-
+               
                 int beforeStatus = locationInfo.LocationStatus;
 
                 locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
@@ -374,6 +373,7 @@
                 task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                 BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.鑷姩瀹屾垚 : OperateTypeEnum.浜哄伐瀹屾垚);
                 _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.鑷姩瀹屾垚 : OperateTypeEnum.浜哄伐瀹屾垚);
+                _stockRepository.Db.Deleteable(stockInfo).ExecuteCommand();
 
                 _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum);
 
@@ -390,8 +390,7 @@
 
       
         /// <summary>
-        /// 鍥炲簱瀹屾垚鍥炶皟 - AGV灏嗘墭鐩樻斁鍥炶揣浣嶅悗璋冪敤
-        /// </summary>
+        /// 鍥炲簱瀹屾垚鍥炶皟 
         public async Task<WebResponseContent> BackToStockComplete(Dt_Task task)
         {
             try
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/Outbound/OutStockLockInfoController.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/Outbound/OutStockLockInfoController.cs"
index 7eba6eb..7fedc9b 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/Outbound/OutStockLockInfoController.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/Outbound/OutStockLockInfoController.cs"
@@ -1,8 +1,10 @@
 锘縰sing Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
+using Org.BouncyCastle.Utilities.Collections;
 using WIDESEA_Core;
 using WIDESEA_Core.BaseController;
+using WIDESEA_Core.Helper;
 using WIDESEA_IOutboundService;
 using WIDESEA_Model.Models;
 
@@ -19,5 +21,14 @@
         {
         }
 
+        
+            [HttpGet("getOutStockLockInfo")]
+    public async Task<WebResponseContent> GetOutStockLockInfo(string orderDetailId)
+        {
+            var list = await Service.GetByOrderDetailId(orderDetailId.ObjToInt());
+
+            return WebResponseContent.Instance.OK(null, list);
+        }
+
     }
 }
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/Outbound/OutboundPickingController.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/Outbound/OutboundPickingController.cs"
index 3935b6d..e92783d 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/Outbound/OutboundPickingController.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/Outbound/OutboundPickingController.cs"
@@ -1,4 +1,5 @@
-锘縰sing Microsoft.AspNetCore.Mvc;
+锘縰sing Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
 using WIDESEA_Core;
 using WIDESEA_Core.BaseController;
 using WIDESEA_DTO.Outbound;
@@ -38,14 +39,43 @@
             return WebResponseContent.Instance.OK(null, lockInfos);
         }
 
-        /// <summary>
-        /// 鎷i�夌‘璁�
-        /// </summary>
-        [HttpPost("ConfirmPicking")]
-        public async Task<WebResponseContent> ConfirmPicking([FromBody] PickingConfirmRequest request)
+ 
+
+        [HttpGet("unpicked-list")]
+        public async Task<WebResponseContent> GetUnpickedList(string orderNo, string palletCode)
         {
-            return await Service.ConfirmPicking(request);
+            var lists= await Service.GetUnpickedList(orderNo, palletCode);
+            return WebResponseContent.Instance.OK("", lists);
         }
+
+        [HttpGet("picked-list")]
+        public async Task<WebResponseContent> GetPickedList(string orderNo, string palletCode)
+        {
+            var lists = await Service.GetPickedList(orderNo, palletCode);
+            return WebResponseContent.Instance.OK("", lists);
+        }
+
+        [HttpPost("confirm-picking")]
+        public async Task<WebResponseContent> ConfirmPicking([FromBody] ConfirmPickingDto dto)
+        {
+            return await Service.ConfirmPicking(dto.OrderNo, dto.PalletCode, dto.Barcode);
+        }
+
+        [HttpGet("picking-summary")]
+        public async Task<WebResponseContent> GetPickingSummary(string orderNo)
+        {
+            var data = await Service.GetPickingSummary(orderNo);
+            return WebResponseContent.Instance.OK("", data);
+        }
+
+        ///// <summary>
+        ///// 鎷i�夌‘璁�
+        ///// </summary>
+        //[HttpPost("ConfirmPicking")]
+        //public async Task<WebResponseContent> ConfirmPicking([FromBody] PickingConfirmRequest request)
+        //{
+        //    return await Service.ConfirmPicking(request);
+        //}
         /// <summary>
         /// 楠岃瘉鏉$爜骞惰幏鍙栫墿鏂欎俊鎭�
         /// </summary>
@@ -58,7 +88,7 @@
         /// 鎷嗗寘鎿嶄綔
         /// </summary>
         [HttpPost("SplitPackage")]
-        public async Task<WebResponseContent> SplitPackage([FromBody] SplitPackageRequest request)
+        public async Task<WebResponseContent> SplitPackage([FromBody] SplitPackageDto request)
         {
             return await _splitPackageService.SplitPackage(request);
         }

--
Gitblit v1.9.3