heshaofeng
2025-11-26 1331e9edaf52ec0820dd1c7efc605127aa3a2c36
提交
已修改8个文件
2716 ■■■■ 文件已修改
项目代码/WIDESEA_WMSClient/src/extension/inbound/extend/Pallet.vue 1985 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/extend/SelectedStock.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/SelectedStock.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js 695 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/outbound/outboundOrder.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/stock/stockInfo.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/Pallet.vue
@@ -1,37 +1,16 @@
<template>
   <vol-box
    v-model="groupPalletVisible"
    :title="'组盘操作 - å•据号:' + currentDocNo"
    :height="1000"
    :width="1100"
    :padding="20"
    :modal="true"
     @open="handleDialogOpen"
    @close="handleDialogClose"
  >
  <div class="barcode-scanner-container">
  <vol-box v-model="groupPalletVisible" :title="'组盘操作 - å•据号:' + currentDocNo" :height="1000" :width="1100" :padding="20"
    :modal="true" @open="handleDialogOpen" @close="handleDialogClose">
    <div class="barcode-scanner-container">
      <!-- ä»“库选择 - ç´§å‡‘布局 -->
      <div class="location-section compact">
        <el-form :model="form" :rules="rules" ref="locationForm" class="compact-form">
          <el-form-item label="仓库" prop="warehouseType" class="location-select compact-item">
            <el-select
              v-model="form.warehouseType"
              placeholder="请选择仓库"
              clearable
              filterable
              @change="handleWarehouseChange"
              style="width: 100%"
              :loading="warehouseLoading"
              size="medium"
            >
              <el-option
                v-for="item in warehouseTypes"
                :key="item.warehouseType"
                :label="item.warehouseTypeDesc"
                :value="item.warehouseType"
              />
            <el-select v-model="form.warehouseType" placeholder="请选择仓库" clearable filterable
              @change="handleWarehouseChange" style="width: 100%" :loading="warehouseLoading" size="medium">
              <el-option v-for="item in warehouseTypes" :key="item.warehouseType" :label="item.warehouseTypeDesc"
                :value="item.warehouseType" />
            </el-select>
          </el-form-item>
        </el-form>
@@ -41,38 +20,26 @@
      <div class="location-section compact">
        <el-form :model="form" :rules="rules" ref="locationForm" class="compact-form">
          <el-form-item label="仓库区域" prop="locationType" class="location-select compact-item">
            <el-select
              v-model="form.locationType"
              placeholder="请先选择仓库"
              clearable
              filterable
              @change="handleLocationChange"
              style="width: 100%"
              :loading="locationLoading"
              size="medium"
            >
              <el-option
                v-for="item in locationTypes"
                :key="item.locationType"
                :label="item.locationTypeDesc"
                :value="item.locationType"
              />
            <el-select v-model="form.locationType" placeholder="请先选择仓库" clearable filterable
              @change="handleLocationChange" style="width: 100%" :loading="locationLoading" size="medium">
              <el-option v-for="item in locationTypes" :key="item.locationType" :label="item.locationTypeDesc"
                :value="item.locationType" />
            </el-select>
          </el-form-item>
        </el-form>
      </div>
      <!-- æ‰˜ç›˜ä¿¡æ¯æ˜¾ç¤º - ç´§å‡‘布局 -->
      <div class="tray-info compact" v-if="trayBarcode">
        <i class="el-icon-s-management"></i> å½“前料箱: {{ trayBarcode }}
        <span class="location-info" v-if="form.warehouseType">
          | ä»“库: {{ currentWarehouseName  }}
          | ä»“库: {{ currentWarehouseName }}
        </span>
        <span class="location-info" v-if="form.locationType">
          | ä»“库区域: {{ currentLocationDesc }}
        </span>
      </div>
      <!-- æ‰«ç åŒºåŸŸ - ç´§å‡‘布局 -->
      <div class="input-section compact">
        <el-card shadow="hover" class="compact-card">
@@ -83,73 +50,45 @@
              {{ form.locationType && form.warehouseType ? '扫码就绪' : '请先选择仓库和仓库区域' }}
            </span>
          </div>
          <!-- æ‰˜ç›˜æ¡ç è¾“å…¥ -->
          <div class="input-wrapper custom-input-group compact-input">
            <div class="input-label">料箱码</div>
            <el-input
              ref="trayInput"
              v-model="trayBarcode"
              placeholder="请扫描或输入料箱码后按回车键"
              clearable
              :disabled="!form.locationType || !form.warehouseType"
              @keyup.enter.native="handleTraySubmit"
              @clear="handleTrayClear"
              @input="handleTrayInput"
              class="custom-input"
              size="medium"
            >
            <el-input ref="trayInput" v-model="trayBarcode" placeholder="请扫描或输入料箱码后按回车键" clearable
              :disabled="!form.locationType || !form.warehouseType" @keyup.enter.native="handleTraySubmit"
              @clear="handleTrayClear" @input="handleTrayInput" class="custom-input" size="medium">
              <template slot="append">
                <el-button
                  @click="handleTraySubmit"
                  type="primary"
                  icon="el-icon-position"
                  :disabled="!form.locationType || !trayBarcode || !form.warehouseType"
                  size="medium"
                >
                <el-button @click="handleTraySubmit" type="primary" icon="el-icon-position"
                  :disabled="!form.locationType || !trayBarcode || !form.warehouseType" size="medium">
                  ç¡®è®¤
                </el-button>
              </template>
            </el-input>
          </div>
          <!-- ç‰©æ–™æ¡ç è¾“å…¥ -->
          <div class="input-wrapper custom-input-group compact-input">
            <div class="input-label">物料条码</div>
            <el-input
              ref="barcodeInput"
              v-model="barcode"
              placeholder="请扫描或输入物料条码后按回车键"
              clearable
            <el-input ref="barcodeInput" v-model="barcode" placeholder="请扫描或输入物料条码后按回车键" clearable
              :disabled="!form.locationType || !trayBarcode || !form.warehouseType"
              @keyup.enter.native="handleBarcodeSubmit"
              @clear="handleClear"
              @input="handleBarcodeInput"
              class="custom-input"
              size="medium"
            >
              @keyup.enter.native="handleBarcodeSubmit" @clear="handleClear" @input="handleBarcodeInput"
              class="custom-input" size="medium">
              <template slot="append">
                <el-button
                  :loading="loading"
                  @click="handleBarcodeSubmit"
                  type="primary"
                  icon="el-icon-search"
                  :disabled="!form.locationType || !trayBarcode || !barcode || !from.warehouseType"
                  size="medium"
                >
                <el-button :loading="loading" @click="handleBarcodeSubmit" type="primary" icon="el-icon-search"
                  :disabled="!form.locationType || !trayBarcode || !barcode || !from.warehouseType" size="medium">
                  {{ loading ? '查询中...' : '查询' }}
                </el-button>
              </template>
            </el-input>
          </div>
          <div class="input-tips compact-tips">
            <p>提示:请先选择仓库 â†’ é€‰æ‹©ä»“库区域 â†’ è¾“入料箱码 â†’ è¾“入物料条码</p>
            <p v-if="!form.warehouseType" class="warning-text">⚠️ è¯·å…ˆé€‰æ‹©ä»“库</p>
            <p v-if="!form.locationType && !form.warehouseType" class="warning-text">⚠️ è¯·å…ˆé€‰æ‹©ä»“库区域</p>
            <p v-if="form.warehouseType && form.locationType && !trayBarcode" class="warning-text">⚠️ è¯·å…ˆè¾“入料箱码</p>
          </div>
        </el-card>
      </div>
@@ -161,13 +100,7 @@
      <!-- é”™è¯¯æç¤º -->
      <div v-if="error" class="error-message compact">
        <el-alert
          :title="error"
          type="error"
          show-icon
          closable
          @close="error = ''"
        />
        <el-alert :title="error" type="error" show-icon closable @close="error = ''" />
      </div>
      <!-- ç‰©æ–™åˆ—表 - å›ºå®šé«˜åº¦å¸¦æ»šåŠ¨æ¡ -->
@@ -184,7 +117,7 @@
              <el-tag v-if="form.locationType" type="info" size="small">区域: {{ currentLocationDesc }}</el-tag>
            </span>
          </div>
          <div v-if="materials.length === 0" class="empty-state compact">
            <i class="el-icon-document"></i>
            <p v-if="!form.warehouseType">请先选择仓库</p>
@@ -192,15 +125,9 @@
            <p v-else-if="!trayBarcode">请先输入料箱条码</p>
            <p v-else>暂无物料数据,请扫描或输入物料条码</p>
          </div>
          <div class="table-container" v-else>
            <el-table
              :data="materials"
              stripe
              style="width: 100%"
              height="100%"
              size="small"
            >
            <el-table :data="materials" stripe style="width: 100%" height="100%" size="small">
              <el-table-column type="index" label="序号" width="60" align="center"></el-table-column>
              <el-table-column prop="barcode" label="条码" min-width="140" show-overflow-tooltip></el-table-column>
              <el-table-column prop="materielCode" label="物料编码" min-width="150" show-overflow-tooltip></el-table-column>
@@ -214,19 +141,19 @@
        </el-card>
      </div>
    </div>
   <!--      <div slot="footer" class="dialog-footer">
    <!--      <div slot="footer" class="dialog-footer">
      <el-button @click="handleCancel">取消</el-button>
      <el-button type="primary" @click="handleConfirm">确认</el-button>
    </div> -->
    </vol-box>
  </vol-box>
</template>
<script>
import http from '@/api/http.js';
import VolBox from '@/components/basic/VolBox.vue';
import VolForm from '@/components/basic/VolForm.vue';
import VolTable from '@/components/basic/VolTable.vue';
import { ElLoading, ElMessage,ElMessageBox  } from 'element-plus';
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus';
import { ref, onMounted, onUnmounted } from 'vue'
import InboundOrder from '../../../views/inbound/inboundOrder.vue';
import { th } from 'element-plus/es/locales.mjs';
@@ -241,50 +168,50 @@
  data() {
    return {
        palletVisible: this.visible,
         trayBarcode: '',
          barcode: '',
          materials: [],
          loading: false,
          error: '',
          debugMode: false,
          currentFocus: 'warehouse',
          // æ‰«ç æžªç›¸å…³å˜é‡
          scanCode: '',
          lastKeyTime: null,
          isManualInput: false,
          isScanning: false,
          scanTimer: null,
          manualInputTimer: null,
          scanTarget: 'tray', // å½“前扫码目标: tray æˆ– material
      palletVisible: this.visible,
      trayBarcode: '',
      barcode: '',
      materials: [],
      loading: false,
      error: '',
      debugMode: false,
      currentFocus: 'warehouse',
          // åº“存统计相关变量
          totalStockSum: 0,
          totalStockCount: 0,
          uniqueUnit: '',
          sumLoading: false,
          sumError: '',
        // ä»“库相关变量
          warehouseTypes: [],
          warehouseLoading: false,
        // ä»“库区域相关变量
        locationTypes: [],
        locationLoading: false,
        form: {
            warehouseType: null,
            locationType: null
        },
    rules: {
      locationType: [
        {
          validator: this.validateLocationType,
          trigger: 'change'
        }
      ],
      warehouseType: [
          {
            massage:'请选择仓库',
      // æ‰«ç æžªç›¸å…³å˜é‡
      scanCode: '',
      lastKeyTime: null,
      isManualInput: false,
      isScanning: false,
      scanTimer: null,
      manualInputTimer: null,
      scanTarget: 'tray', // å½“前扫码目标: tray æˆ– material
      // åº“存统计相关变量
      totalStockSum: 0,
      totalStockCount: 0,
      uniqueUnit: '',
      sumLoading: false,
      sumError: '',
      // ä»“库相关变量
      warehouseTypes: [],
      warehouseLoading: false,
      // ä»“库区域相关变量
      locationTypes: [],
      locationLoading: false,
      form: {
        warehouseType: null,
        locationType: null
      },
      rules: {
        locationType: [
          {
            validator: this.validateLocationType,
            trigger: 'change'
          }
        ],
        warehouseType: [
          {
            massage: '请选择仓库',
            trigger: 'change'
          }
        ]
@@ -297,44 +224,44 @@
      set(newVal) { this.$emit('update:visible', newVal); }
    },
    currentDocNo() { return this.docNo; },
        // å½“前选择的仓库名称
    // å½“前选择的仓库名称
    currentWarehouseName() {
      const warehouse = this.warehouseTypes.find(item => item.warehouseType === this.form.warehouseType);
      return warehouse ? warehouse.warehouseTypeDesc : '';
    },
        // å½“前选择的仓库区域描述
    // å½“前选择的仓库区域描述
    currentLocationDesc() {
        const location = this.locationTypes.find(item => item.locationType === this.form.locationType)
        return location ? location.locationTypeDesc : ''
      const location = this.locationTypes.find(item => item.locationType === this.form.locationType)
      return location ? location.locationTypeDesc : ''
    }
  },
  watch: {
    visible(newVal, oldVal) {
    this.palletVisible = newVal;
    // å½“从 false å˜ä¸º true æ—¶ï¼Œè¡¨ç¤ºå¼¹æ¡†æ‰“å¼€
    if (newVal === true && oldVal === false) {
      console.log('弹框打开,重置数据');
      this.resetData();
      this.$nextTick(() => {
        setTimeout(() => {
         // this.focusTrayInput();
          this.initwarehouseTypes(); // åˆå§‹åŒ–仓库
          this.initLocationTypes(); // åˆå§‹åŒ–仓库区域
          this.fetchStockStatistics(); // åŠ è½½ç»Ÿè®¡æ•°æ®
        }, 300);
      });
    }
    // å½“从 true å˜ä¸º false æ—¶ï¼Œè¡¨ç¤ºå¼¹æ¡†å…³é—­
    if (newVal === false && oldVal === true) {
      console.log('弹框关闭,重置数据');
      this.resetData();
    }
  },
  palletVisible(newVal) {
    this.$emit('update:visible', newVal);
  },
      this.palletVisible = newVal;
      // å½“从 false å˜ä¸º true æ—¶ï¼Œè¡¨ç¤ºå¼¹æ¡†æ‰“å¼€
      if (newVal === true && oldVal === false) {
        console.log('弹框打开,重置数据');
        this.resetData();
        this.$nextTick(() => {
          setTimeout(() => {
            // this.focusTrayInput();
            this.initwarehouseTypes(); // åˆå§‹åŒ–仓库
            this.initLocationTypes(); // åˆå§‹åŒ–仓库区域
            this.fetchStockStatistics(); // åŠ è½½ç»Ÿè®¡æ•°æ®
          }, 300);
        });
      }
      // å½“从 true å˜ä¸º false æ—¶ï¼Œè¡¨ç¤ºå¼¹æ¡†å…³é—­
      if (newVal === false && oldVal === true) {
        console.log('弹框关闭,重置数据');
        this.resetData();
      }
    },
    palletVisible(newVal) {
      this.$emit('update:visible', newVal);
    },
    docNo(newVal) {
      if (newVal) {
        this.palletForm = { palletCode: '', barcode: '' };
@@ -345,160 +272,160 @@
    }
  },
  'form.warehouseType'(newVal) {
      if (newVal) {
        this.form.locationType = null;
    if (newVal) {
      this.form.locationType = null;
    } else {
      this.locationTypes = [];
    }
  },
  mounted() {
    // æ·»åŠ å…¨å±€é”®ç›˜ç›‘å¬
    document.addEventListener('keypress', this.handleKeyPress);
    // ä½¿ç”¨setTimeout确保DOM完全渲染后再聚焦
    setTimeout(() => {
      // this.focusTrayInput();
      this.focusLocationSelect();
    }, 300);
  },
  beforeDestroy() {
    // æ¸…理事件监听
    document.removeEventListener('keypress', this.handleKeyPress);
    this.clearAllTimers();
  },
  methods: {
    /**
* è‡ªå®šä¹‰ä»“库区域验证
* å…è®¸å€¼ä¸º0,因为0是合法的locationType
*/
    validateLocationType(rule, value, callback) {
      // æ£€æŸ¥å€¼æ˜¯å¦ä¸ºnull、undefined或空字符串,但允许数字0
      if (!this.form.warehouseType) {
        callback(new Error('请先选择仓库'));
      } else if (value === null || value === undefined || value === '') {
        callback(new Error('请选择仓库区域'));
      } else {
        this.locationTypes = [];
        callback();
      }
    },
    /**
    * åˆå§‹åŒ–仓库区域数据
    */
    async initLocationTypes() {
      this.locationLoading = true;
      this.error = '';
      try {
        const response = await http.post('/api/LocationInfo/GetLocationTypes');
        if (response.status && Array.isArray(response.data)) {
          this.locationTypes = response.data;
          if (this.locationTypes.length === 0) {
            this.error = '未获取到仓库区域数据';
          } else {
            // å¦‚果有默认区域,可以在这里设置
            // this.form.locationType = this.locationTypes[0].locationType;
          }
        } else {
          this.error = '获取仓库区域数据失败';
        }
      } catch (error) {
        console.error('获取仓库区域失败:', error);
        this.error = `获取仓库区域失败: ${error.message || '网络错误'}`;
      } finally {
        this.locationLoading = false;
      }
    },
 mounted() {
        // æ·»åŠ å…¨å±€é”®ç›˜ç›‘å¬
        document.addEventListener('keypress', this.handleKeyPress);
        // ä½¿ç”¨setTimeout确保DOM完全渲染后再聚焦
        setTimeout(() => {
         // this.focusTrayInput();
                  this.focusLocationSelect();
        }, 300);
      },
      beforeDestroy() {
        // æ¸…理事件监听
        document.removeEventListener('keypress', this.handleKeyPress);
         this.clearAllTimers();
      },
      methods: {
         /**
   * è‡ªå®šä¹‰ä»“库区域验证
   * å…è®¸å€¼ä¸º0,因为0是合法的locationType
   */
  validateLocationType(rule, value, callback) {
    // æ£€æŸ¥å€¼æ˜¯å¦ä¸ºnull、undefined或空字符串,但允许数字0
    if (!this.form.warehouseType) {
      callback(new Error('请先选择仓库'));
    } else if (value === null || value === undefined || value === '') {
      callback(new Error('请选择仓库区域'));
    } else {
      callback();
    }
  },
         /**
         * åˆå§‹åŒ–仓库区域数据
         */
        async initLocationTypes() {
            this.locationLoading = true;
            this.error = '';
            try {
                const response = await http.post('/api/LocationInfo/GetLocationTypes');
                if (response.status && Array.isArray(response.data)) {
                    this.locationTypes = response.data;
                    if (this.locationTypes.length === 0) {
                        this.error = '未获取到仓库区域数据';
                    } else {
                        // å¦‚果有默认区域,可以在这里设置
                        // this.form.locationType = this.locationTypes[0].locationType;
                    }
                } else {
                    this.error = '获取仓库区域数据失败';
                }
            } catch (error) {
                console.error('获取仓库区域失败:', error);
                this.error = `获取仓库区域失败: ${error.message || '网络错误'}`;
            } finally {
                this.locationLoading = false;
            }
        },
    /**
     * åˆå§‹åŒ–仓库数据
     */
    async initwarehouseTypes() {
      this.warehouseLoading = true;
      this.error = '';
        /**
         * åˆå§‹åŒ–仓库数据
         */
        async initwarehouseTypes() {
            this.warehouseLoading = true;
            this.error = '';
            try {
                const response = await http.post('/api/Warehouse/GetwarehouseTypes');
                if (response.status && Array.isArray(response.data)) {
                    this.warehouseTypes = response.data;
                    if (this.warehouseTypes.length === 0) {
                        this.error = '未获取到仓库数据';
                    } else {
                        // å¦‚果有默认区域,可以在这里设置
                        // this.form.locationType = this.locationTypes[0].locationType;
                    }
                } else {
                    this.error = '获取仓库数据失败';
                }
            } catch (error) {
                console.error('获取仓库失败:', error);
                this.error = `获取仓库失败: ${error.message || '网络错误'}`;
            } finally {
                this.warehouseLoading = false;
            }
        },
      try {
        const response = await http.post('/api/Warehouse/GetwarehouseTypes');
        if (response.status && Array.isArray(response.data)) {
          this.warehouseTypes = response.data;
          if (this.warehouseTypes.length === 0) {
            this.error = '未获取到仓库数据';
          } else {
            // å¦‚果有默认区域,可以在这里设置
            // this.form.locationType = this.locationTypes[0].locationType;
          }
        } else {
          this.error = '获取仓库数据失败';
        }
      } catch (error) {
        console.error('获取仓库失败:', error);
        this.error = `获取仓库失败: ${error.message || '网络错误'}`;
      } finally {
        this.warehouseLoading = false;
      }
    },
 /**
 * ä»“库区域变更处理
 */
handleLocationChange(value) {
 console.log('选择仓库区域:', value, '类型:', typeof value, this.currentLocationDesc);
    // ç«‹å³æ¸…除错误信息
    this.error = '';
    // æ‰‹åŠ¨è§¦å‘è¡¨å•éªŒè¯æ›´æ–°
    this.$nextTick(() => {
      if (this.$refs.locationForm) {
        // æ¸…除该字段的验证状态,然后重新验证
        this.$refs.locationForm.clearValidate('locationType');
        // çŸ­æš‚延迟后重新验证,确保DOM已更新
        setTimeout(() => {
          this.$refs.locationForm.validateField('locationType', (errorMsg) => {
            if (!errorMsg && (value === 0 || value)) {
              console.log('仓库区域验证通过:', value);
              // åŒºåŸŸé€‰æ‹©åŽï¼Œè‡ªåŠ¨èšç„¦åˆ°æ‰˜ç›˜è¾“å…¥æ¡†
              this.focusLocationSelect();
            }
          });
        }, 100);
    }
  });
},
    /**
    * ä»“库区域变更处理
    */
    handleLocationChange(value) {
      console.log('选择仓库区域:', value, '类型:', typeof value, this.currentLocationDesc);
/**
 * ä»“库变更处理
 */
handleWarehouseChange(value) {
 console.log('选择仓库:', value, '类型:', typeof value, this.currentWarehouseName);
    // ç«‹å³æ¸…除错误信息
    this.error = '';
    // æ‰‹åŠ¨è§¦å‘è¡¨å•éªŒè¯æ›´æ–°
    this.$nextTick(() => {
      if (this.$refs.locationForm) {
        // æ¸…除该字段的验证状态,然后重新验证
        this.$refs.locationForm.clearValidate('warehouseType');
        // çŸ­æš‚延迟后重新验证,确保DOM已更新
        setTimeout(() => {
          this.$refs.locationForm.validateField('warehouseType', (errorMsg) => {
            if (!errorMsg && (value === 0 || value)) {
              console.log('仓库验证通过:', value);
              this.focusLocationSelect();
            }
          });
        }, 100);
    }
  });
},
      // ç«‹å³æ¸…除错误信息
      this.error = '';
      // æ‰‹åŠ¨è§¦å‘è¡¨å•éªŒè¯æ›´æ–°
      this.$nextTick(() => {
        if (this.$refs.locationForm) {
          // æ¸…除该字段的验证状态,然后重新验证
          this.$refs.locationForm.clearValidate('locationType');
          // çŸ­æš‚延迟后重新验证,确保DOM已更新
          setTimeout(() => {
            this.$refs.locationForm.validateField('locationType', (errorMsg) => {
              if (!errorMsg && (value === 0 || value)) {
                console.log('仓库区域验证通过:', value);
                // åŒºåŸŸé€‰æ‹©åŽï¼Œè‡ªåŠ¨èšç„¦åˆ°æ‰˜ç›˜è¾“å…¥æ¡†
                this.focusLocationSelect();
              }
            });
          }, 100);
        }
      });
    },
    /**
     * ä»“库变更处理
     */
    handleWarehouseChange(value) {
      console.log('选择仓库:', value, '类型:', typeof value, this.currentWarehouseName);
      // ç«‹å³æ¸…除错误信息
      this.error = '';
      // æ‰‹åŠ¨è§¦å‘è¡¨å•éªŒè¯æ›´æ–°
      this.$nextTick(() => {
        if (this.$refs.locationForm) {
          // æ¸…除该字段的验证状态,然后重新验证
          this.$refs.locationForm.clearValidate('warehouseType');
          // çŸ­æš‚延迟后重新验证,确保DOM已更新
          setTimeout(() => {
            this.$refs.locationForm.validateField('warehouseType', (errorMsg) => {
              if (!errorMsg && (value === 0 || value)) {
                console.log('仓库验证通过:', value);
                this.focusLocationSelect();
              }
            });
          }, 100);
        }
      });
    },
    async fetchStockStatistics() {
      // å•据号为空时不查询
      if (!this.docNo) {
@@ -510,8 +437,8 @@
      this.sumError = '';
      try {
        // è°ƒç”¨åŽç«¯ç»Ÿè®¡æŽ¥å£ï¼ˆæ›¿æ¢ä¸ºä½ çš„实际接口路径)
        const response = await http.post('/api/InboundOrder/UnPalletQuantity?orderNo='+this.docNo, {
        const response = await http.post('/api/InboundOrder/UnPalletQuantity?orderNo=' + this.docNo, {
        });
        // ç»‘定数据(匹配 PalletSumQuantityDTO ç»“构)
@@ -529,82 +456,91 @@
        this.sumLoading = false;
      }
    },
/**
 * è¡¨å•验证
 */
async validateForm() {
  return new Promise((resolve) => {
    if (!this.$refs.locationForm) {
      this.error = '表单未初始化';
      this.$message.warning('请先选择仓库区域');
      resolve(false);
      return;
    }
    /**
     * è¡¨å•验证
     */
    async validateForm() {
      return new Promise((resolve) => {
        if (!this.$refs.locationForm) {
          this.error = '表单未初始化';
          this.$message.warning('请先选择仓库区域');
          resolve(false);
          return;
        }
    this.$refs.locationForm.validate((valid) => {
      if (valid) {
        this.error = '';
        resolve(true);
      } else {
        // æ‰‹åŠ¨æ£€æŸ¥locationType,正确处理值为0的情况
        if(!this.from.warehouseType){
          this.error='请先选择仓库';
        this.$refs.locationForm.validate((valid) => {
          if (valid) {
            this.error = '';
            resolve(true);
          } else {
            // æ‰‹åŠ¨æ£€æŸ¥locationType,正确处理值为0的情况
            if (!this.from.warehouseType) {
              this.error = '请先选择仓库';
            }
            else if (this.form.locationType === null || this.form.locationType === undefined || this.form.locationType === '') {
              this.error = '请先选择仓库区域';
              //this.$message.warning('请先选择仓库区域');
            } else {
              // å¦‚果值存在(包括0),但验证不通过,可能是其他验证错误
              this.error = '请检查表单填写是否正确';
            }
            resolve(false);
          }
        });
      });
    },
    focusWarehouseSelect() {
      if (this.$refs.locationForm) {
        const selectEl = this.$el.querySelector('.location-select:first-child .el-input__inner');
        if (selectEl) {
          selectEl.focus();
          this.currentFocus = 'warehouse';
        }
        else if(this.form.locationType === null || this.form.locationType === undefined || this.form.locationType === '') {
          this.error = '请先选择仓库区域';
          //this.$message.warning('请先选择仓库区域');
        } else {
          // å¦‚果值存在(包括0),但验证不通过,可能是其他验证错误
          this.error = '请检查表单填写是否正确';
        }
        resolve(false);
      }
    });
  });
},
       focusWarehouseSelect() {
            if (this.$refs.locationForm) {
                const selectEl = this.$el.querySelector('.location-select:first-child .el-input__inner');
                if (selectEl) {
                    selectEl.focus();
                    this.currentFocus = 'warehouse';
                }
            }
        },
        // èšç„¦åˆ°ä»“库区域选择
        focusLocationSelect() {
            if (this.$refs.locationForm) {
                const selectEl = this.$el.querySelector('.location-select:nth-child(2) .el-input__inner');
                if (selectEl) {
                    selectEl.focus();
                    this.currentFocus = 'location';
                }
            }
        },
        // èšç„¦åˆ°æ‰˜ç›˜è¾“入框
        focusTrayInput() {
            if (this.$refs.trayInput && this.$refs.trayInput.$el) {
                const inputEl = this.$refs.trayInput.$el.querySelector('input');
                if (inputEl) {
                    inputEl.focus();
                    this.currentFocus = 'tray';
                    this.scanTarget = 'tray';
                }
            }
        },
        // èšç„¦åˆ°ç‰©æ–™è¾“入框
        focusBarcodeInput() {
            if (this.$refs.barcodeInput && this.$refs.barcodeInput.$el) {
                const inputEl = this.$refs.barcodeInput.$el.querySelector('input');
                if (inputEl) {
                    inputEl.focus();
                    this.currentFocus = 'material';
                    this.scanTarget = 'material';
                }
            }
        },
         // é‡ç½®æ‰€æœ‰æ•°æ®
    },
    // èšç„¦åˆ°ä»“库区域选择
    focusLocationSelect() {
      if (this.$refs.locationForm) {
        const selectEl = this.$el.querySelector('.location-select:nth-child(2) .el-input__inner');
        if (selectEl) {
          selectEl.focus();
          this.currentFocus = 'location';
        }
      }
    },
    // èšç„¦åˆ°æ‰˜ç›˜è¾“入框
    focusTrayInput() {
      if (this.$refs.trayInput && this.$refs.trayInput.$el) {
        const inputEl = this.$refs.trayInput.$el.querySelector('input');
        if (inputEl) {
          inputEl.focus();
          this.currentFocus = 'tray';
          this.scanTarget = 'tray';
        }
      }
    },
    // èšç„¦åˆ°ç‰©æ–™è¾“入框
    focusBarcodeInput() {
      if (this.$refs.barcodeInput && this.$refs.barcodeInput.$el) {
        const inputEl = this.$refs.barcodeInput.$el.querySelector('input');
        if (inputEl) {
          inputEl.focus();
          this.currentFocus = 'material';
          this.scanTarget = 'material';
            inputEl.select();
            console.log('物料输入框内容已选中');
        }
      }
    },
    // é‡ç½®æ‰€æœ‰æ•°æ®
    resetData() {
      console.log('重置弹框数据');
      this.trayBarcode = '';
@@ -623,20 +559,20 @@
      this.totalStockCount = 0;
      this.sumLoading = false;
      this.sumError = '';
        this.form={
          warehouseType:null,
          locationType:null
      this.form = {
        warehouseType: null,
        locationType: null
      }
      this.warehouseTypes = [];
      this.locationTypes = [];
      // æ¸…除表单验证状态
      this.$nextTick(() => {
        if (this.$refs.locationForm) {
          this.$refs.locationForm.clearValidate();
        }
      this.warehouseTypes=[];
      this.locationTypes=[];
          // æ¸…除表单验证状态
  this.$nextTick(() => {
    if (this.$refs.locationForm) {
      this.$refs.locationForm.clearValidate();
    }
  });
      });
    },
    // æ¸…除所有计时器
    clearAllTimers() {
      if (this.manualInputTimer) {
@@ -648,7 +584,7 @@
        this.scanTimer = null;
      }
    },
    // å¼¹æ¡†æ‰“开时重置数据
    handleDialogOpen() {
      console.log('弹框打开,重置数据');
@@ -656,676 +592,691 @@
      // ä½¿ç”¨setTimeout确保DOM完全渲染后再聚焦
      this.$nextTick(() => {
        setTimeout(() => {
            this.initwarehouseTypes();
            this.initLocationTypes(); // åˆå§‹åŒ–仓库区域
             // ç¡®ä¿è¡¨å•引用存在后再聚焦
      if (this.$refs.locationForm) {
        this.focusWarehouseSelect();
      } else {
        // å¦‚果表单引用还不存在,稍后重试
        setTimeout(() => {
          this.focusWarehouseSelect();
        }, 500);
      }
          this.initwarehouseTypes();
          this.initLocationTypes(); // åˆå§‹åŒ–仓库区域
          // ç¡®ä¿è¡¨å•引用存在后再聚焦
          if (this.$refs.locationForm) {
            this.focusWarehouseSelect();
          } else {
            // å¦‚果表单引用还不存在,稍后重试
            setTimeout(() => {
              this.focusWarehouseSelect();
            }, 500);
          }
        }, 300);
      });
    },
    // å¼¹æ¡†å…³é—­æ—¶é‡ç½®æ•°æ®
    handleDialogClose() {
      console.log('弹框关闭,重置数据');
      this.resetData();
    },
    // å–消按钮
    handleCancel() {
      this.palletVisible = false;
    },
    // ç¡®è®¤æŒ‰é’®
   async  handleConfirm() {
           if (!await this.validateForm()) return;
    async handleConfirm() {
      if (!await this.validateForm()) return;
      if (this.materials.length === 0) {
        this.$message.warning('请至少添加一个物料');
        return;
      }
      if (!this.trayBarcode) {
        this.$message.warning('请输入托盘条码');
        return;
      }
      const result = {
        warehouseType:this.form.warehouseType,
        warehouseName:this.currentWarehouseName,
        warehouseType: this.form.warehouseType,
        warehouseName: this.currentWarehouseName,
        locationType: this.form.locationType,
        locationDesc: this.currentLocationDesc,
        trayBarcode: this.trayBarcode,
        materials: this.materials,
        docNo: this.docNo
      };
      // è§¦å‘父组件的 back-success äº‹ä»¶
      this.$emit('back-success', result);
      this.palletVisible = false;
    },
    // å¤„理托盘输入
        handleTrayInput() {
            // æ ‡è®°ä¸ºæ‰‹åŠ¨è¾“å…¥æ¨¡å¼
            this.isManualInput = true;
            this.isScanning = false;
            // æ¸…除之前的计时器
            if (this.manualInputTimer) {
                clearTimeout(this.manualInputTimer);
            }
            // è®¾ç½®è®¡æ—¶å™¨ï¼Œå¦‚果一段时间内没有输入,则重置为扫码模式
            this.manualInputTimer = setTimeout(() => {
                this.isManualInput = false;
            }, 1000);
        },
        // å¤„理物料输入
        handleBarcodeInput() {
            // æ ‡è®°ä¸ºæ‰‹åŠ¨è¾“å…¥æ¨¡å¼
            this.isManualInput = true;
            this.isScanning = false;
            // æ¸…除之前的计时器
            if (this.manualInputTimer) {
                clearTimeout(this.manualInputTimer);
            }
            // è®¾ç½®è®¡æ—¶å™¨ï¼Œå¦‚果一段时间内没有输入,则重置为扫码模式
            this.manualInputTimer = setTimeout(() => {
                this.isManualInput = false;
            }, 1000);
        },
       // å¤„理托盘条码提交
async handleTraySubmit() {
  // å…ˆç›´æŽ¥æ£€æŸ¥locationType,避免表单验证的异步问题
  if (!this.form.warehouseType) {
    this.error = '请先选择仓库';
    return;
  }
  if (!this.form.locationType) {
    this.error = '请先选择仓库区域';
    //this.$message.warning('请先选择仓库区域');
    return;
  }
  // ç„¶åŽå†è¿›è¡Œå®Œæ•´çš„表单验证
  if (!await this.validateForm()) return;
  const currentTrayBarcode = this.trayBarcode.trim();
  if (!currentTrayBarcode) {
    this.error = '请输入或扫描托盘条码';
    return;
  }
    handleTrayInput() {
      // æ ‡è®°ä¸ºæ‰‹åŠ¨è¾“å…¥æ¨¡å¼
      this.isManualInput = true;
      this.isScanning = false;
  this.error = '';
  // è®¾ç½®æ‰˜ç›˜æ¡ç åŽï¼Œè‡ªåŠ¨èšç„¦åˆ°ç‰©æ–™è¾“å…¥æ¡†
  this.focusBarcodeInput();
  this.$message({
    message: `托盘条码已设置: ${currentTrayBarcode}`,
    type: 'success',
    duration: 2000
  });
},
        // æ¸…除托盘
        clearTray() {
          this.trayBarcode = '';
          this.materials = [];
          this.focusTrayInput();
      // æ¸…除之前的计时器
      if (this.manualInputTimer) {
        clearTimeout(this.manualInputTimer);
      }
      // è®¾ç½®è®¡æ—¶å™¨ï¼Œå¦‚果一段时间内没有输入,则重置为扫码模式
      this.manualInputTimer = setTimeout(() => {
        this.isManualInput = false;
      }, 1000);
    },
    // å¤„理物料输入
    handleBarcodeInput() {
      // æ ‡è®°ä¸ºæ‰‹åŠ¨è¾“å…¥æ¨¡å¼
      this.isManualInput = true;
      this.isScanning = false;
      // æ¸…除之前的计时器
      if (this.manualInputTimer) {
        clearTimeout(this.manualInputTimer);
      }
      // è®¾ç½®è®¡æ—¶å™¨ï¼Œå¦‚果一段时间内没有输入,则重置为扫码模式
      this.manualInputTimer = setTimeout(() => {
        this.isManualInput = false;
      }, 1000);
    },
    // å¤„理托盘条码提交
    async handleTraySubmit() {
      // å…ˆç›´æŽ¥æ£€æŸ¥locationType,避免表单验证的异步问题
      if (!this.form.warehouseType) {
        this.error = '请先选择仓库';
        return;
      }
      if (!this.form.locationType) {
        this.error = '请先选择仓库区域';
        //this.$message.warning('请先选择仓库区域');
        return;
      }
      // ç„¶åŽå†è¿›è¡Œå®Œæ•´çš„表单验证
      if (!await this.validateForm()) return;
      const currentTrayBarcode = this.trayBarcode.trim();
      if (!currentTrayBarcode) {
        this.error = '请输入或扫描托盘条码';
        return;
      }
      this.error = '';
      // è®¾ç½®æ‰˜ç›˜æ¡ç åŽï¼Œè‡ªåŠ¨èšç„¦åˆ°ç‰©æ–™è¾“å…¥æ¡†
      this.focusBarcodeInput();
      this.$message({
        message: `托盘条码已设置: ${currentTrayBarcode}`,
        type: 'success',
        duration: 2000
      });
    },
    // æ¸…除托盘
    clearTray() {
      this.trayBarcode = '';
      this.materials = [];
      this.focusTrayInput();
      this.$message({
        message: '托盘条码已清除',
        type: 'info',
        duration: 2000
      });
    },
    // æ¸…空托盘输入
    handleTrayClear() {
      this.error = '';
    },
    // æ¸…空输入
    handleClear() {
      this.error = '';
      this.scanCode = '';
      this.isManualInput = false;
      this.isScanning = false;
    },
    // å¤„理物料条码提交
    async handleBarcodeSubmit() {
      if (!await this.validateForm()) return;
      const currentBarcode = this.barcode.trim();
      if (!this.trayBarcode) {
        this.error = '请先输入托盘条码';
        this.focusTrayInput();
        return;
      }
      if (!currentBarcode) {
        this.error = '请输入或扫描物料条码';
        return;
      }
      this.focusBarcodeInput();
      this.error = '';
      this.loading = true;
      try {
        // è°ƒç”¨API查询物料信息
        const materialData = await this.fetchMaterialData(currentBarcode);
        if (!materialData || materialData.length === 0) {
          return;
        }
        // æ£€æŸ¥æ˜¯å¦å·²å­˜åœ¨ç›¸åŒç‰©æ–™ç¼–码的记录
        const exists = this.materials.some(item =>
          item.barcode === this.trayBarcode
        );
        console.log('API:', materialData)
        if (exists) {
          this.$message({
            message: '托盘条码已清除',
            type: 'info',
            message: '该条码已存在当前托盘的列表中',
            type: 'warning',
            duration: 2000
          });
        },
        // æ¸…空托盘输入
        handleTrayClear() {
          this.error = '';
        },
        // æ¸…空输入
        handleClear() {
          this.error = '';
          this.scanCode = '';
          this.isManualInput = false;
          this.isScanning = false;
        },
        // å¤„理物料条码提交
        async handleBarcodeSubmit() {
                    if (!await this.validateForm()) return;
          const currentBarcode = this.barcode.trim();
          
          if (!this.trayBarcode) {
            this.error = '请先输入托盘条码';
            this.focusTrayInput();
            return;
          }
          if (!currentBarcode) {
            this.error = '请输入或扫描物料条码';
            return;
          }
        } else {
          this.error = '';
          this.loading = true;
          materialData.forEach(item => {
          try {
            // è°ƒç”¨API查询物料信息
            const materialData = await this.fetchMaterialData(currentBarcode);
                  if (!materialData  || materialData.length === 0) {
          return;
         }
            // æ£€æŸ¥æ˜¯å¦å·²å­˜åœ¨ç›¸åŒç‰©æ–™ç¼–码的记录
            const exists = this.materials.some(item =>
                 item.barcode === this.trayBarcode
            );
            console.log('API:',materialData)
            if (exists) {
              this.$message({
                message: '该条码已存在当前托盘的列表中',
                type: 'warning',
                duration: 2000
              });
            } else {
                materialData.forEach(item => {
          // å¦‚果不存在,添加新物料
          this.materials.push({
            ...item,
             trayCode: this.trayBarcode,
               locationType: this.form.locationType,
                            locationDesc: this.currentLocationDesc,
               scanTime: this.formatTime(new Date())
            // å¦‚果不存在,添加新物料
            this.materials.push({
              ...item,
              trayCode: this.trayBarcode,
              locationType: this.form.locationType,
              locationDesc: this.currentLocationDesc,
              scanTime: this.formatTime(new Date())
            });
          });
        });
              this.$message({
                message: `成功添加条码: ${currentBarcode}`,
                type: 'success',
                duration: 2000
              });
            this.fetchStockStatistics();
            // æ¸…空物料输入框并保持聚焦
            this.barcode = '';
            this.scanCode = ''; // æ¸…空扫码缓存
            this.isScanning = false;
            setTimeout(() => {
              this.focusBarcodeInput();
            }, 100);
          }
          } catch (err) {
            this.error = err.message || '查询条码信息失败,请重试';
          } finally {
            this.loading = false;
          }
        },
        // API请求 - æ›¿æ¢ä¸ºå®žé™…çš„API调用
      async  fetchMaterialData(barcode) {
         try {
        const response = await http.post('/api/InboundOrder/BarcodeMaterielGroup',
           {
          this.$message({
            message: `成功添加条码: ${currentBarcode}`,
            type: 'success',
            duration: 2000
          });
          this.fetchStockStatistics();
          // æ¸…空物料输入框并保持聚焦
          this.barcode = '';
          this.scanCode = ''; // æ¸…空扫码缓存
          this.isScanning = false;
          setTimeout(() => {
            this.focusBarcodeInput();
          }, 100);
        }
      } catch (err) {
        this.error = err.message || '查询条码信息失败,请重试';
        this.focusBarcodeInput();
        setTimeout(() => {
      // é€‰ä¸­è¾“入框内的错误内容(确保focus完成后执行)
      const inputEl = this.$refs.barcodeInput?.$el?.querySelector('input');
      if (inputEl) inputEl.select();
    }, 100);
      } finally {
        this.loading = false;
      }
    },
    // API请求 - æ›¿æ¢ä¸ºå®žé™…çš„API调用
    async fetchMaterialData(barcode) {
      try {
        const response = await http.post('/api/InboundOrder/BarcodeMaterielGroup',
          {
            palletCode: this.trayBarcode,
            orderNo: this.docNo,
            barcodes: barcode,
            locationTypeDesc:  this.currentLocationDesc,
            locationTypeDesc: this.currentLocationDesc,
            locationType: this.form.locationType, // æ·»åŠ ä»“åº“åŒºåŸŸä¿¡æ¯
            warehouseType:this.form.warehouseType
          }
            warehouseType: this.form.warehouseType
          }
        );
        let materialData;
        if (typeof response.data === 'string') {
          try {
            materialData = JSON.parse(response.data);
          } catch (e) {
          }
        } else {
          // å¦‚果返回的是JSON对象,直接使用
          materialData = response.data;
        }
 if(!response.status){
   this.error = response.message || '查询条码信息失败,请重试';
 }
        if (!response.status) {
          this.error = response.message || '查询条码信息失败,请重试';
        }
        return  materialData;
        return materialData;
      } catch (error) {
        console.error('API调用失败:', error);
      }
        },
        // å¤„理扫码枪输入
        handleKeyPress(event) {
          // å¦‚果是手动输入模式,不处理扫码枪逻辑
          if (this.isManualInput) {
            return;
          }
          const key = event.key;
          const currentTime = new Date().getTime();
          // å¿½ç•¥ç›´æŽ¥æŒ‰ä¸‹çš„回车键(由handleBarcodeSubmit处理)
          if (key === 'Enter') {
            if (this.scanCode.length > 0) {
              // é˜»æ­¢é»˜è®¤å›žè½¦è¡Œä¸ºï¼Œé¿å…è¡¨å•提交
              event.preventDefault();
              // æ‰«ç å®Œæˆï¼Œè‡ªåŠ¨è§¦å‘æŸ¥è¯¢
              this.isScanning = false;
              // æ ¹æ®å½“前扫码目标设置相应的输入框值
              if (this.scanTarget === 'tray') {
                this.trayBarcode = this.scanCode;
                this.handleTraySubmit();
              } else if (this.scanTarget === 'material') {
                this.barcode = this.scanCode;
                this.handleBarcodeSubmit();
              }
            }
            this.scanCode = '';
            this.lastKeyTime = null;
            return;
          }
          // æž„建扫码内容(快速连续输入视为扫码)
          if (this.lastKeyTime && currentTime - this.lastKeyTime < 50) {
            this.scanCode += key;
            this.isScanning = true;
          } else {
            this.scanCode = key;
            this.isScanning = true;
          }
          // è®¾ç½®è®¡æ—¶å™¨ï¼Œå¦‚果一段时间内没有输入,则重置扫描状态
          if (this.scanTimer) {
            clearTimeout(this.scanTimer);
          }
          this.scanTimer = setTimeout(() => {
            this.isScanning = false;
          }, 100);
          this.lastKeyTime = currentTime;
        },
        // åˆ é™¤ç‰©æ–™
        removeMaterial(index) {
          this.$confirm('确定要删除这条物料记录吗?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            this.materials.splice(index, 1);
            this.$message({
              type: 'success',
              message: '删除成功!'
            });
            this.fetchStockStatistics();
          }).catch(() => {
            // å–消删除
          });
        },
        // æ¸…空所有物料
        clearAllMaterials() {
          if (this.materials.length === 0) return;
          this.$confirm('确定要清空所有物料记录吗?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            this.materials = [];
            this.$message({
              type: 'success',
              message: '已清空所有记录!'
            });
          }).catch(() => {
            // å–消清空
          });
        },
        // æ ¼å¼åŒ–æ—¶é—´
        formatTime(date) {
          const year = date.getFullYear();
          const month = String(date.getMonth() + 1).padStart(2, '0');
          const day = String(date.getDate()).padStart(2, '0');
          const hours = String(date.getHours()).padStart(2, '0');
          const minutes = String(date.getMinutes()).padStart(2, '0');
          const seconds = String(date.getSeconds()).padStart(2, '0');
          return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
        }
      }
    },
    // å¤„理扫码枪输入
    handleKeyPress(event) {
      // å¦‚果是手动输入模式,不处理扫码枪逻辑
      if (this.isManualInput) {
        return;
      }
      const key = event.key;
      const currentTime = new Date().getTime();
      // å¿½ç•¥ç›´æŽ¥æŒ‰ä¸‹çš„回车键(由handleBarcodeSubmit处理)
      if (key === 'Enter') {
        if (this.scanCode.length > 0) {
          // é˜»æ­¢é»˜è®¤å›žè½¦è¡Œä¸ºï¼Œé¿å…è¡¨å•提交
          event.preventDefault();
          // æ‰«ç å®Œæˆï¼Œè‡ªåŠ¨è§¦å‘æŸ¥è¯¢
          this.isScanning = false;
          // æ ¹æ®å½“前扫码目标设置相应的输入框值
          if (this.scanTarget === 'tray') {
            this.trayBarcode = this.scanCode;
            this.handleTraySubmit();
          } else if (this.scanTarget === 'material') {
            this.barcode = this.scanCode;
            this.handleBarcodeSubmit();
          }
        }
        this.scanCode = '';
        this.lastKeyTime = null;
        return;
      }
      // æž„建扫码内容(快速连续输入视为扫码)
      if (this.lastKeyTime && currentTime - this.lastKeyTime < 50) {
        this.scanCode += key;
        this.isScanning = true;
      } else {
        this.scanCode = key;
        this.isScanning = true;
      }
      // è®¾ç½®è®¡æ—¶å™¨ï¼Œå¦‚果一段时间内没有输入,则重置扫描状态
      if (this.scanTimer) {
        clearTimeout(this.scanTimer);
      }
      this.scanTimer = setTimeout(() => {
        this.isScanning = false;
      }, 100);
      this.lastKeyTime = currentTime;
    },
    // åˆ é™¤ç‰©æ–™
    removeMaterial(index) {
      this.$confirm('确定要删除这条物料记录吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.materials.splice(index, 1);
        this.$message({
          type: 'success',
          message: '删除成功!'
        });
        this.fetchStockStatistics();
      }).catch(() => {
        // å–消删除
      });
    },
    // æ¸…空所有物料
    clearAllMaterials() {
      if (this.materials.length === 0) return;
      this.$confirm('确定要清空所有物料记录吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.materials = [];
        this.$message({
          type: 'success',
          message: '已清空所有记录!'
        });
      }).catch(() => {
        // å–消清空
      });
    },
    // æ ¼å¼åŒ–æ—¶é—´
    formatTime(date) {
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const day = String(date.getDate()).padStart(2, '0');
      const hours = String(date.getHours()).padStart(2, '0');
      const minutes = String(date.getMinutes()).padStart(2, '0');
      const seconds = String(date.getSeconds()).padStart(2, '0');
      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    }
  }
}
</script>
<style scoped>
    .barcode-scanner-container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 10px;
      display: flex;
      flex-direction: column;
      height: 100%;
      gap: 8px;
    }
    /* ç´§å‡‘布局样式 */
    .compact {
      margin-bottom: 0;
    }
    .compact-form {
      margin-bottom: 0;
    }
    .compact-item {
      margin-bottom: 0;
    }
    .compact-card {
      margin-bottom: 0;
    }
    .compact-card >>> .el-card__body {
      padding: 12px;
    }
    .compact-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 !important;
    }
    .compact-header >>> .el-card__header {
      padding: 8px 12px;
    }
    .compact-input {
      margin: 8px 0;
    }
    .compact-tips {
      margin-top: 8px;
      font-size: 11px;
    }
    /* ä»“库区域选择 - ç´§å‡‘ */
    .location-section.compact {
      margin-bottom: 8px;
    }
    .location-section.compact >>> .el-form-item {
      margin-bottom: 0;
    }
    /* æ‰˜ç›˜ä¿¡æ¯ - ç´§å‡‘ */
    .tray-info.compact {
      padding: 6px 10px;
      margin-bottom: 8px;
      font-size: 13px;
    }
    /* æ‰«ç åŒºåŸŸ - ç´§å‡‘ */
    .input-section.compact {
      margin-bottom: 8px;
      flex-shrink: 0;
    }
    /* ç‰©æ–™åˆ—表 - å›ºå®šé«˜åº¦å¸¦æ»šåЍ */
    .material-list.compact {
      flex: 1;
      min-height: 0; /* é‡è¦ï¼šå…è®¸flex子项收缩 */
      display: flex;
      flex-direction: column;
    }
    .material-list.compact >>> .el-card {
      display: flex;
      flex-direction: column;
      height: 100%;
    }
    .material-list.compact >>> .el-card__body {
      flex: 1;
      display: flex;
      flex-direction: column;
      padding: 0;
      min-height: 0;
    }
    .table-container {
      flex: 1;
      min-height: 0;
      overflow: hidden;
    }
    .material-list.compact >>> .el-table {
      flex: 1;
    }
    .material-list.compact >>> .el-table__body-wrapper {
      overflow-y: auto;
    }
    /* ç´§å‡‘的空状态 */
    .empty-state.compact {
      padding: 20px 0;
      flex: 1;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }
    .empty-state.compact i {
      font-size: 36px;
      margin-bottom: 8px;
    }
    .empty-state.compact p {
      font-size: 13px;
    }
    /* å…¶ä»–原有样式调整 */
    .page-title {
      text-align: center;
      margin-bottom: 15px;
    }
    .scan-status {
      font-size: 12px;
      color: #67C23A;
    }
    .scan-indicator {
      display: inline-block;
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background-color: #67C23A;
      margin-right: 5px;
      animation: pulse 1.5s infinite;
    }
    @keyframes pulse {
      0% { opacity: 1; }
      50% { opacity: 0.4; }
      100% { opacity: 1; }
    }
    .input-wrapper {
      position: relative;
    }
    .input-tips {
      margin-top: 6px;
      color: #909399;
    }
    .warning-text {
        color: #E6A23C;
        font-weight: bold;
    }
    .loading.compact {
      text-align: center;
      margin: 10px 0;
      padding: 5px;
    }
    .loading.compact p {
      margin-top: 5px;
      color: #409EFF;
      font-size: 12px;
    }
    .error-message.compact {
      margin: 5px 0;
    }
    .error-message.compact >>> .el-alert {
      padding: 6px 12px;
    }
    .list-actions {
      display: flex;
      align-items: center;
      gap: 4px;
    }
    .list-actions >>> .el-tag {
      height: 24px;
      line-height: 22px;
      padding: 0 6px;
    }
    .clear-all-btn {
      margin-left: 8px;
    }
    .material-code {
      font-family: 'Courier New', monospace;
      font-weight: bold;
      color: #409EFF;
    }
    .location-info {
        color: #606266;
        font-weight: normal;
    }
    .debug-info {
      background: #f5f7fa;
      padding: 8px;
      border-radius: 4px;
      margin-top: 8px;
      font-size: 11px;
      color: #909399;
    }
    .small-button {
      padding: 6px 8px;
      font-size: 11px;
    }
.barcode-scanner-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 8px;
}
    /* è¾“入框组样式调整 */
    .custom-input-group {
      display: flex;
      align-items: center;
      width: 100%;
      margin: 8px 0;
      border: 1px solid #DCDFE6;
      border-radius: 4px;
      overflow: hidden;
      background: #fff;
    }
/* ç´§å‡‘布局样式 */
.compact {
  margin-bottom: 0;
}
    .input-label {
      padding: 0 12px;
      background: #F5F7FA;
      border-right: 1px solid #DCDFE6;
      color: #606266;
      font-size: 13px;
      white-space: nowrap;
      height: 36px;
      line-height: 36px;
      flex-shrink: 0;
      min-width: 70px;
      text-align: center;
    }
.compact-form {
  margin-bottom: 0;
}
    .input-container {
      display: flex;
      flex: 1;
      align-items: center;
    }
.compact-item {
  margin-bottom: 0;
}
    .custom-input {
      flex: 1;
    }
.compact-card {
  margin-bottom: 0;
}
    .custom-input >>> .el-input__inner {
      border: none;
      border-radius: 0;
      height: 36px;
      line-height: 36px;
      font-size: 13px;
    }
    /* å“åº”式调整 */
    @media (max-width: 768px) {
      .barcode-scanner-container {
        padding: 5px;
      }
      .custom-input-group {
        flex-direction: column;
        border: none;
      }
      .input-label {
        width: 100%;
        border-right: none;
        border-bottom: 1px solid #DCDFE6;
        margin-bottom: 5px;
      }
      .input-container {
        width: 100%;
        border: 1px solid #DCDFE6;
        border-radius: 4px;
      }
    }
.compact-card>>>.el-card__body {
  padding: 12px;
}
.compact-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 !important;
}
.compact-header>>>.el-card__header {
  padding: 8px 12px;
}
.compact-input {
  margin: 8px 0;
}
.compact-tips {
  margin-top: 8px;
  font-size: 11px;
}
/* ä»“库区域选择 - ç´§å‡‘ */
.location-section.compact {
  margin-bottom: 8px;
}
.location-section.compact>>>.el-form-item {
  margin-bottom: 0;
}
/* æ‰˜ç›˜ä¿¡æ¯ - ç´§å‡‘ */
.tray-info.compact {
  padding: 6px 10px;
  margin-bottom: 8px;
  font-size: 13px;
}
/* æ‰«ç åŒºåŸŸ - ç´§å‡‘ */
.input-section.compact {
  margin-bottom: 8px;
  flex-shrink: 0;
}
/* ç‰©æ–™åˆ—表 - å›ºå®šé«˜åº¦å¸¦æ»šåЍ */
.material-list.compact {
  flex: 1;
  min-height: 0;
  /* é‡è¦ï¼šå…è®¸flex子项收缩 */
  display: flex;
  flex-direction: column;
}
.material-list.compact>>>.el-card {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.material-list.compact>>>.el-card__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 0;
  min-height: 0;
}
.table-container {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.material-list.compact>>>.el-table {
  flex: 1;
}
.material-list.compact>>>.el-table__body-wrapper {
  overflow-y: auto;
}
/* ç´§å‡‘的空状态 */
.empty-state.compact {
  padding: 20px 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.empty-state.compact i {
  font-size: 36px;
  margin-bottom: 8px;
}
.empty-state.compact p {
  font-size: 13px;
}
/* å…¶ä»–原有样式调整 */
.page-title {
  text-align: center;
  margin-bottom: 15px;
}
.scan-status {
  font-size: 12px;
  color: #67C23A;
}
.scan-indicator {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #67C23A;
  margin-right: 5px;
  animation: pulse 1.5s infinite;
}
@keyframes pulse {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.4;
  }
  100% {
    opacity: 1;
  }
}
.input-wrapper {
  position: relative;
}
.input-tips {
  margin-top: 6px;
  color: #909399;
}
.warning-text {
  color: #E6A23C;
  font-weight: bold;
}
.loading.compact {
  text-align: center;
  margin: 10px 0;
  padding: 5px;
}
.loading.compact p {
  margin-top: 5px;
  color: #409EFF;
  font-size: 12px;
}
.error-message.compact {
  margin: 5px 0;
}
.error-message.compact>>>.el-alert {
  padding: 6px 12px;
}
.list-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}
.list-actions>>>.el-tag {
  height: 24px;
  line-height: 22px;
  padding: 0 6px;
}
.clear-all-btn {
  margin-left: 8px;
}
.material-code {
  font-family: 'Courier New', monospace;
  font-weight: bold;
  color: #409EFF;
}
.location-info {
  color: #606266;
  font-weight: normal;
}
.debug-info {
  background: #f5f7fa;
  padding: 8px;
  border-radius: 4px;
  margin-top: 8px;
  font-size: 11px;
  color: #909399;
}
.small-button {
  padding: 6px 8px;
  font-size: 11px;
}
/* è¾“入框组样式调整 */
.custom-input-group {
  display: flex;
  align-items: center;
  width: 100%;
  margin: 8px 0;
  border: 1px solid #DCDFE6;
  border-radius: 4px;
  overflow: hidden;
  background: #fff;
}
.input-label {
  padding: 0 12px;
  background: #F5F7FA;
  border-right: 1px solid #DCDFE6;
  color: #606266;
  font-size: 13px;
  white-space: nowrap;
  height: 36px;
  line-height: 36px;
  flex-shrink: 0;
  min-width: 70px;
  text-align: center;
}
.input-container {
  display: flex;
  flex: 1;
  align-items: center;
}
.custom-input {
  flex: 1;
}
.custom-input>>>.el-input__inner {
  border: none;
  border-radius: 0;
  height: 36px;
  line-height: 36px;
  font-size: 13px;
}
/* å“åº”式调整 */
@media (max-width: 768px) {
  .barcode-scanner-container {
    padding: 5px;
  }
  .custom-input-group {
    flex-direction: column;
    border: none;
  }
  .input-label {
    width: 100%;
    border-right: none;
    border-bottom: 1px solid #DCDFE6;
    margin-bottom: 5px;
  }
  .input-container {
    width: 100%;
    border: 1px solid #DCDFE6;
    border-radius: 4px;
  }
}
</style>
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/SelectedStock.vue
@@ -182,14 +182,19 @@
          "查询中"
        )
        .then((x) => {
          var label=[
              { label: '已分配', value: 0 },
              { label: '出库中', value: 1 },
              { label: '出库完成', value: 2 },
              { label: '拣选完成', value: 3 },
              { label: '部分拣选', value: 2 },
              { label: '已拣选', value: 3 },
              { label: '已出库', value: 4 },
              { label: '出库完成', value: 5 },
              { label: '拣选完成', value: 6 },
              { label: '回库中', value: 7 },
              { label: '已回库', value: 8 },
              { label: '撤销', value: 99 }
          ]
          this.tableData=x.map((i) => ({
            ...i,
            status:label.find((j) => j.value === i.status).label
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/SelectedStock.vue
@@ -190,12 +190,17 @@
        .then((x) => {
          
          var label=[
              { label: '已分配', value: 0 },
             { label: '已分配', value: 0 },
              { label: '出库中', value: 1 },
              { label: '出库完成', value: 2 },
              { label: '拣选完成', value: 3 },
              { label: '部分拣选', value: 2 },
              { label: '已拣选', value: 3 },
              { label: '已出库', value: 4 },
              { label: '出库完成', value: 5 },
              { label: '拣选完成', value: 6 },
              { label: '回库中', value: 7 },
              { label: '已回库', value: 8 },
              { label: '撤销', value: 99 }
          ]
          ];
          this.tableData=x.map((i) => ({
            ...i,
            status:label.find((j) => j.value === i.status).label
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js
@@ -1,365 +1,366 @@
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
import http from '@/api/http.js'
import { h,createVNode, render,reactive ,ref } from 'vue';
import { ElDialog , ElForm, ElFormItem, ElInput, ElButton, ElMessage ,ElSelect, ElOption} from 'element-plus';
import { h, createVNode, render, reactive, ref } from 'vue';
import { ElDialog, ElForm, ElFormItem, ElInput, ElButton, ElMessage, ElSelect, ElOption } from 'element-plus';
import gridBody from './extend/outOrderDetail.vue'
let extension = {
    components: {
      //查询界面扩展组件
      gridHeader: '',
      gridBody: gridBody,
      gridFooter: '',
      //新建、编辑弹出框扩展组件
      modelHeader: '',
      modelBody: '',
      modelFooter: ''
    },
    tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
    buttons: { view: [
       /* {
        name: '出库',
        type: 'primary',
        value: '出库',
        onClick: function () { // ä¿®å¤ï¼šç”¨ElMessage替代this.$message
          const selectedRows = this.$refs.table.getSelected();
          if (selectedRows.length === 0) {
            ElMessage.warning('请先选择要生成任务的行');
            return;
          }
          if (selectedRows.length > 1) {
            ElMessage.warning('只能选择一行');
            return;
          }
          // æ‰€æœ‰æ ¡éªŒé€šè¿‡ï¼Œè§¦å‘主组件打开出库弹窗
          console.log('所有校验通过,触发openOutboundDialog事件,单据数据:', selectedRows[0]);
          this.$emit('openOutboundDialog', {
            transNo: selectedRows[0].transNo,       // å‡ºåº“单编号
            createDate: selectedRows[0].createDate || new Date().toLocaleDateString()  // å‡ºåº“日期
          });
        }
      }, */
      {
  name: '空托盘出库',
  type: 'primary',
  value: '空托盘出库',
  onClick: function () {
  components: {
    //查询界面扩展组件
    gridHeader: '',
    gridBody: gridBody,
    gridFooter: '',
    //新建、编辑弹出框扩展组件
    modelHeader: '',
    modelBody: '',
    modelFooter: ''
  },
  tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
  buttons: {
    view: [
      /* {
       name: '出库',
       type: 'primary',
       value: '出库',
       onClick: function () { // ä¿®å¤ï¼šç”¨ElMessage替代this.$message
         const selectedRows = this.$refs.table.getSelected();
         if (selectedRows.length === 0) {
           ElMessage.warning('请先选择要生成任务的行');
           return;
         }
         if (selectedRows.length > 1) {
           ElMessage.warning('只能选择一行');
           return;
         }
   
    const platformOptions = Array.from({ length: 1 }, (_, i) => {
      const num = 1;
      return { label: `站台${num}`, value: `1-2` };
    });
    const quantityOptions = Array.from({ length: 6 }, (_, i) => ({
      label: (i + 1).toString(),
      value: i + 1
    }));
    const warehouseOptions = ref([]);
    const isLoadingWarehouses = ref(false);
    const getWarehouseList = async () => {
      isLoadingWarehouses.value = true;
      try {
        const { data, status } = await http.post('/api/LocationInfo/GetLocationTypes');
        if (status && Array.isArray(data)) {
          // æ ¼å¼åŒ–仓库选项:适配ElSelect的label-value格式
          warehouseOptions.value = data.map(item => ({
            label: item.locationTypeDesc,
            value: item.locationType
          }));
        } else {
          ElMessage.error('获取区域列表失败');
          warehouseOptions.value = [];
        }
      } catch (err) {
        ElMessage.error('区域数据请求异常,请稍后重试');
        warehouseOptions.value = [];
      } finally {
        isLoadingWarehouses.value = false;
      }
    };
    const mountNode = document.createElement('div');
    document.body.appendChild(mountNode);
    const formData = reactive({
      warehouseCode:'',
      palletCode: '',
      selectedPlatform: platformOptions[0].value,
      quantity:1
    });
    const vnode = createVNode(ElDialog, {
      title: '空托盘出库',
      width: '500px',
      modelValue: true,
      appendToBody: true,
      onOpened: async () => {
        await getWarehouseList();
        const inputRef = vnode.component.refs.boxCodeInput;
        inputRef?.focus();
      },
      'onUpdate:modelValue': (isVisible) => {
        if (!isVisible) {
          render(null, mountNode);
          document.body.removeChild(mountNode);
        }
      },
      style: {
        padding: '20px 0',
        borderRadius: '8px'
      }
    }, {
      default: () => h(ElForm, {
        model: formData,
        rules: {
          warehouseCode:[
            { required: true, message: '请选择区域', trigger: ['change', 'blur'] }
          ],
          palletCode: [
            { type: 'string', message: '料箱号必须为字符串', trigger: 'blur' }
          ],
          selectedPlatform: [
            { required: true, message: '请选择出库站台', trigger: 'change' }
          ],
          quantity:[
            { required: true, message: '请选择空箱数量', trigger: 'change'}
          ]
        },
        ref: 'batchOutForm',
        labelWidth: '100px',
        style: {
          padding: '0 30px',
        }
       },
       [
      //   h(ElFormItem, {
      //     label: '仓库区域',
      //     prop: 'warehouseCode',
      //     style: {
      //       marginBottom: '24px'
      //     }
      //   }, [
      //     h(ElSelect, {
      //       placeholder: '请选择仓库区域',
      //       modelValue: formData.warehouseCode,
      //       'onUpdate:modelValue': (val) => {
      //         formData.warehouseCode = val;
      //       },
      //       style: {
      //         width: '100%',
      //         height: '40px',
      //         borderRadius: '4px',
      //         borderColor: '#dcdfe6'
      //       }
      //     }, warehouseOptions.value.map(platform =>
      //       h(ElOption, { label: platform.label, value: platform.value })
      //     ))
      //   ]),
        h(ElFormItem, {
          label: '出库站台',
          prop: 'selectedPlatform',
          style: {
            marginBottom: '24px'
          }
        }, [
          h(ElSelect, {
            placeholder: '请选择出库站台',
            modelValue: formData.selectedPlatform,
            'onUpdate:modelValue': (val) => {
              formData.selectedPlatform = val;
            },
            style: {
              width: '100%',
              height: '40px',
              borderRadius: '4px',
              borderColor: '#dcdfe6'
            }
          }, platformOptions.map(platform =>
            h(ElOption, { label: platform.label, value: platform.value })
          ))
        ]),
      //   h(ElFormItem,{
      //     label:'出库数量',
      //     prop:'quantity',
      //     style:{
      //       marginBottom:'24px'
      //     }
      //   },[h(ElSelect,{
      //     placeholder:'请选择空箱数量',
      //     modelValue:formData.quantity,
      //     'onUpdate:modelValue':(val)=>{
      //       formData.quantity=val;
      //     },
      //     style:{
      //       width:'100%',
      //       height:'40px',
      //       borderRadius:'4px',
      //       borderColor:'#dcdfe6'
      //     },
      //     filterable:false
      //   },
      //   quantityOptions.map(option=>
      //     h(ElOption,{
      //       label:option.label,
      //       value:option.value
      //     })
      //   )
      // )]),
        h(ElFormItem, {
          label: '料箱号',
          prop: 'palletCode',
          style: {
            marginBottom: '16px'
          }
        }, [
          h(ElInput, {
            type: 'text',
            placeholder: '可选输入料箱号,不填则自动分配空料箱',
            modelValue: formData.palletCode,
            'onUpdate:modelValue': (val) => {
              formData.palletCode = val;
            },
            style: {
              width: '100%',
              height: '40px',
              borderRadius: '4px',
              borderColor: '#dcdfe6'
            },
            attrs: {
              placeholderStyle: 'color: #909399;'
            }
          })
        ]),
         // æ‰€æœ‰æ ¡éªŒé€šè¿‡ï¼Œè§¦å‘主组件打开出库弹窗
         console.log('所有校验通过,触发openOutboundDialog事件,单据数据:', selectedRows[0]);
        
        h('div', {
          style: {
            textAlign: 'right',
            marginTop: '8px',
            paddingRight: '4px'
          }
        }, [
          h(ElButton, {
            type: 'text',
            onClick: () => {
              render(null, mountNode);
              document.body.removeChild(mountNode);
              ElMessage.info('取消出库操作');
            },
            style: {
              marginRight: '8px',
              color: '#606266'
            }
          }, '取消'),
          h(ElButton, {
            type: 'primary',
            onClick: async () => {
              const formRef = vnode.component.refs.batchOutForm;
              try {
                await formRef.validate();
              } catch (err) {
                return;
         this.$emit('openOutboundDialog', {
           transNo: selectedRows[0].transNo,       // å‡ºåº“单编号
           createDate: selectedRows[0].createDate || new Date().toLocaleDateString()  // å‡ºåº“日期
         });
       }
     }, */
      {
        name: '空托盘出库',
        type: 'primary',
        value: '空托盘出库',
        onClick: function () {
          const platformOptions = Array.from({ length: 1 }, (_, i) => {
            const num = 1;
            return { label: `站台${num}`, value: `1-2` };
          });
          const quantityOptions = Array.from({ length: 6 }, (_, i) => ({
            label: (i + 1).toString(),
            value: i + 1
          }));
          const warehouseOptions = ref([]);
          const isLoadingWarehouses = ref(false);
          const getWarehouseList = async () => {
            isLoadingWarehouses.value = true;
            try {
              const { data, status } = await http.post('/api/LocationInfo/GetLocationTypes');
              if (status && Array.isArray(data)) {
                // æ ¼å¼åŒ–仓库选项:适配ElSelect的label-value格式
                warehouseOptions.value = data.map(item => ({
                  label: item.locationTypeDesc,
                  value: item.locationType
                }));
              } else {
                ElMessage.error('获取区域列表失败');
                warehouseOptions.value = [];
              }
            } catch (err) {
              ElMessage.error('区域数据请求异常,请稍后重试');
              warehouseOptions.value = [];
            } finally {
              isLoadingWarehouses.value = false;
            }
          };
              http.post('/api/Task/PalletOutboundTask?palletCode='+formData.palletCode+'&endStation='+formData.selectedPlatform, {
              }).then(({ data, status, message }) => {
                if (status) {
          const mountNode = document.createElement('div');
          document.body.appendChild(mountNode);
                  ElMessage.success(`出库成功`);
                  this.refresh();
                  render(null, mountNode);
                  document.body.removeChild(mountNode);
                } else {
                  ElMessage.error(message || data?.message || '出库失败');
                }
              }).catch(() => {
                ElMessage.error('请求失败,请稍后重试');
              });
          const formData = reactive({
            warehouseCode: '',
            palletCode: '',
            selectedPlatform: platformOptions[0].value,
            quantity: 1
          });
          const vnode = createVNode(ElDialog, {
            title: '空托盘出库',
            width: '500px',
            modelValue: true,
            appendToBody: true,
            onOpened: async () => {
              await getWarehouseList();
              const inputRef = vnode.component.refs.boxCodeInput;
              inputRef?.focus();
            },
            'onUpdate:modelValue': (isVisible) => {
              if (!isVisible) {
                render(null, mountNode);
                document.body.removeChild(mountNode);
              }
            },
            style: {
              borderRadius: '4px',
              padding: '8px 20px'
              padding: '20px 0',
              borderRadius: '8px'
            }
          }, '确定')
        ])
      ])
    });
          }, {
            default: () => h(ElForm, {
              model: formData,
              rules: {
                warehouseCode: [
                  { required: true, message: '请选择区域', trigger: ['change', 'blur'] }
                ],
                palletCode: [
                  { type: 'string', message: '料箱号必须为字符串', trigger: 'blur' }
                ],
                selectedPlatform: [
                  { required: true, message: '请选择出库站台', trigger: 'change' }
                ],
                quantity: [
                  { required: true, message: '请选择空箱数量', trigger: 'change' }
                ]
              },
              ref: 'batchOutForm',
              labelWidth: '100px',
              style: {
                padding: '0 30px',
              }
            },
              [
                //   h(ElFormItem, {
                //     label: '仓库区域',
                //     prop: 'warehouseCode',
                //     style: {
                //       marginBottom: '24px'
                //     }
                //   }, [
                //     h(ElSelect, {
                //       placeholder: '请选择仓库区域',
                //       modelValue: formData.warehouseCode,
                //       'onUpdate:modelValue': (val) => {
                //         formData.warehouseCode = val;
                //       },
                //       style: {
                //         width: '100%',
                //         height: '40px',
                //         borderRadius: '4px',
                //         borderColor: '#dcdfe6'
                //       }
                //     }, warehouseOptions.value.map(platform =>
                //       h(ElOption, { label: platform.label, value: platform.value })
                //     ))
                //   ]),
                h(ElFormItem, {
                  label: '出库站台',
                  prop: 'selectedPlatform',
                  style: {
                    marginBottom: '24px'
                  }
                }, [
                  h(ElSelect, {
                    placeholder: '请选择出库站台',
                    modelValue: formData.selectedPlatform,
                    'onUpdate:modelValue': (val) => {
                      formData.selectedPlatform = val;
                    },
                    style: {
                      width: '100%',
                      height: '40px',
                      borderRadius: '4px',
                      borderColor: '#dcdfe6'
                    }
                  }, platformOptions.map(platform =>
                    h(ElOption, { label: platform.label, value: platform.value })
                  ))
                ]),
                //   h(ElFormItem,{
                //     label:'出库数量',
                //     prop:'quantity',
                //     style:{
                //       marginBottom:'24px'
                //     }
                //   },[h(ElSelect,{
                //     placeholder:'请选择空箱数量',
                //     modelValue:formData.quantity,
                //     'onUpdate:modelValue':(val)=>{
                //       formData.quantity=val;
                //     },
                //     style:{
                //       width:'100%',
                //       height:'40px',
                //       borderRadius:'4px',
                //       borderColor:'#dcdfe6'
                //     },
                //     filterable:false
                //   },
                //   quantityOptions.map(option=>
                //     h(ElOption,{
                //       label:option.label,
                //       value:option.value
                //     })
                //   )
                // )]),
                h(ElFormItem, {
                  label: '料箱号',
                  prop: 'palletCode',
                  style: {
                    marginBottom: '16px'
                  }
                }, [
                  h(ElInput, {
                    type: 'text',
                    placeholder: '可选输入料箱号,不填则自动分配空料箱',
                    modelValue: formData.palletCode,
                    'onUpdate:modelValue': (val) => {
                      formData.palletCode = val;
                    },
                    style: {
                      width: '100%',
                      height: '40px',
                      borderRadius: '4px',
                      borderColor: '#dcdfe6'
                    },
                    attrs: {
                      placeholderStyle: 'color: #909399;'
                    }
                  })
                ]),
    vnode.appContext = this.$.appContext;
    render(vnode, mountNode);
  }
}
    ], box: [], detail: [] }, //扩展的按钮
    methods: {
       //下面这些方法可以保留也可以删除
      onInit() {
        //扩展页面初始化操作
        this.columns.push({
          field: '操作',
          title: '操作',
          width: 90,
          fixed: 'right',
          align: 'center',
          formatter: (row) => {
              return (
                  '<i style="cursor: pointer;color: #2d8cf0;"class="el-icon-view">查看明细</i>'
              );
          },
          click: (row) => {
            const table = this.$refs.table.$refs.table;
            if(table){
              table.clearSelection();
              table.toggleRowSelection(row,true);
            }
              const rowId =row.id;
              console.log(rowId);
              this.$refs.gridBody.open(row);
          }
      });
      },
      onInited() {
        //框架初始化配置后
        //如果要配置明细表,在此方法操作
        //this.detailOptions.columns.forEach(column=>{ });
      },
      searchBefore(param) {
        //界面查询前,可以给param.wheres添加查询参数
        //返回false,则不会执行查询
        return true;
      },
      searchAfter(result) {
        //查询后,result返回的查询数据,可以在显示到表格前处理表格的值
        return true;
      },
      addBefore(formData) {
        //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值
        return true;
      },
      updateBefore(formData) {
        //编辑保存前formData为对象,包括明细表、删除行的Id
        return true;
      },
      rowClick({ row, column, event }) {
        //查询界面点击行事件
        this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行;
      },
      modelOpenAfter(row) {
        //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据
        //(1)判断是编辑还是新建操作: this.currentAction=='Add';
        //(2)给弹出框设置默认值
        //(3)this.editFormFields.字段='xxx';
        //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值
        //看不懂就把输出看:console.log(this.editFormOptions)
                h('div', {
                  style: {
                    textAlign: 'right',
                    marginTop: '8px',
                    paddingRight: '4px'
                  }
                }, [
                  h(ElButton, {
                    type: 'text',
                    onClick: () => {
                      render(null, mountNode);
                      document.body.removeChild(mountNode);
                      ElMessage.info('取消出库操作');
                    },
                    style: {
                      marginRight: '8px',
                      color: '#606266'
                    }
                  }, '取消'),
                  h(ElButton, {
                    type: 'primary',
                    onClick: async () => {
                      const formRef = vnode.component.refs.batchOutForm;
                      try {
                        await formRef.validate();
                      } catch (err) {
                        return;
                      }
                      http.post('/api/Task/PalletOutboundTask?palletCode=' + formData.palletCode + '&endStation=' + formData.selectedPlatform, {
                      }).then(({ data, status, message }) => {
                        if (status) {
                          ElMessage.success(`出库成功`);
                          this.refresh();
                          render(null, mountNode);
                          document.body.removeChild(mountNode);
                        } else {
                          ElMessage.error(message || data?.message || '出库失败');
                        }
                      }).catch(() => {
                        ElMessage.error('请求失败,请稍后重试');
                      });
                    },
                    style: {
                      borderRadius: '4px',
                      padding: '8px 20px'
                    }
                  }, '确定')
                ])
              ])
          });
          vnode.appContext = this.$.appContext;
          render(vnode, mountNode);
        }
      }
    ], box: [], detail: []
  }, //扩展的按钮
  methods: {
    //下面这些方法可以保留也可以删除
    onInit() {
      //扩展页面初始化操作
      this.columns.push({
        field: '操作',
        title: '操作',
        width: 90,
        fixed: 'right',
        align: 'center',
        formatter: (row) => {
          return (
            '<i style="cursor: pointer;color: #2d8cf0;"class="el-icon-view">查看明细</i>'
          );
        },
        click: (row) => {
          const table = this.$refs.table.$refs.table;
          if (table) {
            table.clearSelection();
            table.toggleRowSelection(row, true);
          }
          const rowId = row.id;
          console.log(rowId);
          this.$refs.gridBody.open(row);
        }
      });
    },
    onInited() {
      //框架初始化配置后
      //如果要配置明细表,在此方法操作
      //this.detailOptions.columns.forEach(column=>{ });
    },
    searchBefore(param) {
      //界面查询前,可以给param.wheres添加查询参数
      //返回false,则不会执行查询
      return true;
    },
    searchAfter(result) {
      //查询后,result返回的查询数据,可以在显示到表格前处理表格的值
      return true;
    },
    addBefore(formData) {
      //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值
      return true;
    },
    updateBefore(formData) {
      //编辑保存前formData为对象,包括明细表、删除行的Id
      return true;
    },
    rowClick({ row, column, event }) {
      //查询界面点击行事件
      this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行;
    },
    modelOpenAfter(row) {
      //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据
      //(1)判断是编辑还是新建操作: this.currentAction=='Add';
      //(2)给弹出框设置默认值
      //(3)this.editFormFields.字段='xxx';
      //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值
      //看不懂就把输出看:console.log(this.editFormOptions)
    }
  };
  export default extension;
  }
};
export default extension;
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue
@@ -57,6 +57,7 @@
          type: "select",
          dataKey: "inOrderType",
          data: [],
          hidden:true
        },
        {
          field: "inboundOrderNo",
@@ -94,6 +95,7 @@
          type: "select",
          dataKey: "inOrderType",
          data: [0],
          hidden:true
        },
        {
          title: "单据状态",
@@ -148,6 +150,7 @@
        width: 150,
        align: "left",
        bind: { key: "inOrderType", data: [] },
        hidden:true
      },
      {
        field: "businessType",
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/outbound/outboundOrder.vue
@@ -114,6 +114,7 @@
          type: "select",
          dataKey: "outOrderType",
          data: [],
          hidden:true
        },
        {
          title: "单据状态",
@@ -168,6 +169,7 @@
        width: 150,
        align: "left",
        bind: { key: "outOrderType", data: [] },
        hidden:true
      },
      {
        field: "businessType",
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
@@ -92,6 +92,7 @@
          width: 100,
          align: "left",
          bind: { key: "warehouses", data: [] },
          hidden:true
        },
        {
          field: "creater",
@@ -113,7 +114,7 @@
          type: "string",
          width: 100,
          align: "left",
          hidden:true
          // hidden:true
        },
        {
          field: "modifyDate",
@@ -121,7 +122,7 @@
          type: "datetime",
          width: 160,
          align: "left",
          hidden:true
          // hidden:true
        },
        {
          field: "remark",
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs
@@ -647,7 +647,7 @@
            {
                return WebResponseContent.Instance.Error("托盘号不能为空");
            }
           var stock= _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(o=>o.Details).First(x => x.PalletCode == palletCode );
           var stock= _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(o=>o.Details).First(x => x.PalletCode == palletCode &&  x.StockStatus ==(int)StockStatusEmun.组盘暂存);
            if (stock == null)
            {
                return WebResponseContent.Instance.Error($"未找到托盘号{palletCode}对应的库存记录");