lsh
13 小时以前 218e046d9339ddf3a729930f6bb7b0b77bbed858
pages/sockroom/sockroom.vue
@@ -1,31 +1,32 @@
<template>
   <view class="sockpage">
      <view class="column">
         <!-- 托盘编码 -->
         <view class="form-card">
            <view class="form-row">
               <view class="label">
                  <text class="required">*</text>托盘编码:
               </view>
               <view class="picker-wrap" hover-class="picker-hover">
               <view class="picker-wrap">
                  <view class="input-box">
                     <input 
                     id="pdacode"
                     type="text"
                     v-model="barcode"
                     placeholder="请扫码"
                        type="text"
                        v-model="barcode"
                        placeholder="请扫码"
                        placeholder-class="input-placeholder"
                     />
                  </view>
               </view>
            </view>
         </view>
         
         <!-- 箱型栏(对应后端boxType) -->
         <!-- 箱型选择 -->
         <view class="form-card">
            <view class="form-row">
               <view class="label">
                  <text class="required">*</text>箱    型:
                  <text class="required">*</text>箱型:
               </view>
               <view class="picker-wrap" hover-class="picker-hover">
               <view class="picker-wrap">
                  <picker @change="modePickerChange" :value="index_mode" :range="mode">
                     <view class="input-box">
                        <text class="input-placeholder" v-if="!mode.length || !mode[index_mode]">请选择箱型</text>
@@ -36,115 +37,236 @@
            </view>
         </view>
         
            <view class="form-card">
               <view class="form-row">
                  <view class="label">
                     <text class="required">*</text>物料码:
                  </view>
                  <view class="picker-wrap" hover-class="picker-hover">
                     <view class="textareainput">
                        <textarea
                        style="max-height: 15px;overflow: hidden;"
                        id="pdacode"
         <!-- 物料码扫码(隐藏但可用) -->
         <!-- <view class="form-card" style="height: 0; overflow: hidden; padding: 0; margin: 0;"> -->
         <view class="form-card" style=" overflow: hidden; padding: 0; margin: 0;">
            <view class="form-row">
               <view class="label">
                  <text class="required">*</text>物料码:
               </view>
               <view class="picker-wrap">
                  <view class="input-box">
                     <input
                        type="text"
                        v-model="thingCode"
                        v-model="scanBuffer"
                        placeholder="请扫码"
                        @input="handleBarcodeInput"
                        @input="handleMaterialScan"
                        ref="scanInput"
                     />
                  </view>
               </view>
            </view>
         </view>
         <!-- 物料信息 -->
         <view class="form-card material-card">
            <view class="card-title">物料信息</view>
            <!-- 多物料列表 -->
            <view class="material-list" v-if="matList.length > 0">
               <view class="material-item" v-for="(mat, index) in matList" :key="mat.id">
                  <view class="material-header">
                     <text class="material-title">物料 {{ index + 1 }}</text>
                     <view class="material-actions">
                        <view class="action-btn" @click="removeMaterial(index)">删除</view>
                     </view>
                  </view>
                  <view class="material-grid">
                     <view class="material-item">
                        <text class="material-label"><text class="required">*</text>位置:</text>
                        <input
                           class="material-input"
                           type="text"
                           v-model="mat.position"
                           placeholder="请选择位置"
                           placeholder-class="input-placeholder"
                        />
                     </view>
                     <view class="material-item">
                        <text class="material-label"><text class="required">*</text>箱号:</text>
                        <input
                           class="material-input"
                           type="text"
                           v-model="mat.batch"
                           placeholder="请扫码或输入箱号"
                           placeholder-class="input-placeholder"
                        />
                     </view>
                     <view class="material-item">
                        <text class="material-label"><text class="required">*</text>卷号:</text>
                        <input
                           class="material-input"
                           type="text"
                           v-model="mat.model"
                           placeholder="请扫码或输入卷号"
                           placeholder-class="input-placeholder"
                        />
                     </view>
                     <view class="material-item">
                        <text class="material-label">规格:</text>
                        <input
                           class="material-input"
                           type="text"
                           v-model="mat.matnr"
                           placeholder="请输入规格"
                           placeholder-class="input-placeholder"
                        />
                     </view>
                     <view class="material-item">
                        <text class="material-label">长度:</text>
                        <input
                           class="material-input"
                           type="number"
                           v-model="mat.rollExtent"
                           placeholder="请输入长度"
                           placeholder-class="input-placeholder"
                        />
                     </view>
                     <view class="material-item">
                        <text class="material-label">净重:</text>
                        <input
                           class="material-input"
                           type="number"
                           v-model="mat.weight"
                           placeholder="请输入净重"
                           placeholder-class="input-placeholder"
                        />
                     </view>
                     <view class="material-item">
                        <text class="material-label">毛重:</text>
                        <input
                           class="material-input"
                           type="number"
                           v-model="mat.roughWeight"
                           placeholder="请输入毛重"
                           placeholder-class="input-placeholder"
                        />
                     </view>
                     <view class="material-item">
                        <text class="material-label">接头:</text>
                        <input
                           class="material-input"
                           type="number"
                           v-model="mat.joint"
                           placeholder="请输入接头数"
                           placeholder-class="input-placeholder"
                        />
                     </view>
                  </view>
               </view>
            </view>
         <!-- 物料信息输入栏(对应后端MatList) -->
         <view class="form-card material-card">
            <view class="card-title">物料信息</view>
            <view class="material-grid">
               <view class="material-item">
                  <text class="material-label"><text class="required">*</text>卷号:</text>
                  <input
                     class="material-input"
                     type="text"
                     v-model="matList.model"
                     placeholder="请扫码或输入卷号"
                     placeholder-class="input-placeholder"
                     ref="modelInput"
                  />
               </view>
               <view class="material-item">
                  <text class="material-label"><text class="required">*</text>箱号:</text>
                  <input
                     class="material-input"
                     type="text"
                     v-model="matList.batch"
                     placeholder="请扫码或输入箱号"
                     placeholder-class="input-placeholder"
                     ref="batchInput"
                  />
               </view>
               <view class="material-item">
                  <text class="material-label">规格:</text>
                  <input
                     class="material-input"
                     type="text"
                     v-model="matList.matnr"
                     placeholder="请输入规格"
                     placeholder-class="input-placeholder"
                  />
               </view>
               <view class="material-item">
                  <text class="material-label">长度:</text>
                  <input
                     class="material-input"
                     type="number"
                     v-model="matList.rollExtent"
                     placeholder="请输入长度"
                     placeholder-class="input-placeholder"
                  />
               </view>
               <view class="material-item">
                  <text class="material-label">净重:</text>
                  <input
                     class="material-input"
                     type="number"
                     v-model="matList.weight"
                     placeholder="请输入净重"
                     placeholder-class="input-placeholder"
                  />
               </view>
               <view class="material-item">
                  <text class="material-label">毛重:</text>
                  <input
                     class="material-input"
                     type="number"
                     v-model="matList.roughWeight"
                     placeholder="请输入毛重"
                     placeholder-class="input-placeholder"
                  />
               </view>
               <view class="material-item">
                  <text class="material-label">接头:</text>
                  <input
                     class="material-input"
                     type="number"
                     v-model="matList.joint"
                     placeholder="请输入接头数"
                     placeholder-class="input-placeholder"
                  />
               </view>
            <!-- 空状态提示 -->
            <view class="empty-state" v-else>
               <view class="empty-icon">📦</view>
               <text class="empty-text">暂无物料信息</text>
               <text class="empty-tip">请扫描物料码添加物料</text>
            </view>
            <!-- 扫码按钮 -->
            <view class="scan-btn" @click="focusScanInput">
               <text class="scan-icon">+</text>
               <text class="scan-text">扫码添加物料</text>
            </view>
         </view>
         <!-- 操作按钮组 -->
         <view class="btn-group">
            <button class="operate-btn submit-btn" @click="submit">成品入库</button>
            <button class="operate-btn submit-btn" @click="submit">组托</button>
         </view>
      </view>
      <!-- 扫码确认弹窗 -->
      <view class="modal-mask" v-if="showScanModal" @click="closeModal">
         <view class="modal-content" @click.stop>
            <view class="modal-header">
               <text class="modal-title">扫码确认</text>
            </view>
            <view class="modal-body">
               <view class="scan-preview">
                  <text class="scan-label">扫描到物料:</text>
                  <text class="scan-code">{{ tempMaterial.model || '未知物料' }}</text>
               </view>
               <view class="preview-grid">
                  <view class="preview-item">
                     <text class="preview-label">箱号:</text>
                     <text class="preview-value">{{ tempMaterial.batch || '未识别' }}</text>
                  </view>
                  <view class="preview-item">
                     <text class="preview-label">卷号:</text>
                     <text class="preview-value">{{ tempMaterial.model || '未识别' }}</text>
                  </view>
                  <view class="preview-item">
                     <text class="preview-label">规格:</text>
                     <text class="preview-value">{{ tempMaterial.matnr || '未识别' }}</text>
                  </view>
                  <view class="preview-item">
                     <text class="preview-label">长度:</text>
                     <text class="preview-value">{{ tempMaterial.rollExtent || '未识别' }}</text>
                  </view>
                  <view class="preview-item">
                     <text class="preview-label">净重:</text>
                     <text class="preview-value">{{ tempMaterial.weight || '未识别' }}</text>
                  </view>
                  <view class="preview-item">
                     <text class="preview-label">毛重:</text>
                     <text class="preview-value">{{ tempMaterial.roughWeight || '未识别' }}</text>
                  </view>
                  <view class="preview-item">
                     <text class="preview-label">接头:</text>
                     <text class="preview-value">{{ tempMaterial.joint || '未识别' }}</text>
                  </view>
                  <view class="preview-item full-width">
                     <text class="preview-label">物料位置:</text>
                     <view class="position-selector" @click.stop="togglePositionPicker">
                        <view class="position-display">
                           <text v-if="positionIndex >= 0">{{ positionOptions[positionIndex].label }}</text>
                           <text v-else class="placeholder">请选择位置</text>
                           <text class="position-arrow">▼</text>
                        </view>
                     </view>
                  </view>
                  <!-- 新增:自定义选择器弹出层 -->
                  <view v-if="showPositionPicker" class="custom-picker-overlay" @click.stop="closePositionPicker">
                     <view class="custom-picker-content" @click.stop>
                        <view class="custom-picker-header">
                           <text class="custom-picker-title">选择物料位置</text>
                           <view class="custom-picker-close" @click="closePositionPicker">×</view>
                        </view>
                        <view class="custom-picker-list">
                           <view
                              v-for="(item, index) in positionOptions"
                              :key="index"
                              class="custom-picker-item"
                              :class="{'selected': positionIndex === index}"
                              @click="selectPosition(index)"
                           >
                              <text class="custom-picker-text">{{ item.label }}</text>
                              <text v-if="positionIndex === index" class="custom-picker-check">✓</text>
                           </view>
                        </view>
                     </view>
                  </view>
               </view>
            </view>
            <view class="modal-footer">
               <button class="modal-btn cancel" @click="cancelAddMaterial">取消</button>
               <button class="modal-btn confirm" @click="confirmAddMaterial">确定添加</button>
            </view>
         </view>
      </view>
   </view>
</template>
<script>
export default {
   onLoad(options){
   onLoad(options) {
      this.checkLoginStatus();
      this.POSTinfo();
      this.POSTinfo();
   },
   onShow() {
@@ -158,41 +280,292 @@
      }
   },
   onReady() {
      // 在页面准备就绪后初始化扫码监听
      setTimeout(() => {
         this.initScanListener();
      }, 500);
   },
   data() {
      return {
         thingCode:'',
         focusState: false,
         baseUrl: '',
         token: '',
         barcode: '',
         palletizingNo: '1',
         boxType: '',
         matList: {
            matnr: '',
            maktx: '',
            batch: '',
            model: '',
            position: '1',
            weight: '',
            roughWeight: '',
            anfme: 1.0,
            rollExtent: '',
            joint: 0,
            cutting: 2,
            qualified: 0,
            modelFront: '',
            batchFront: ''
         },
         mode: [],
         mode: [],
         index_mode: 0,
         submitData: {},
         // 扫码相关
         scanBuffer: '',
         scanTimeout: null,
         lastScanTime: 0,
         isProcessingScan: false
         // 物料列表
         matList: [],
         materialId: 1,
         // 弹窗相关
         showScanModal: false,
         tempMaterial: {
            model: '',
            batch: '',
            matnr: '',
            rollExtent: '',
            weight: '',
            roughWeight: '',
            joint: 0,
            position: '1' // 新增:物料位置,默认值为"1"(左)
         },
         // 新增:物料位置下拉框相关数据
         positionIndex: 0, // 默认选中第一个(左)
         // 新增:控制自定义选择器显示
         showPositionPicker: false,
         positionOptions: [
            { label: '1', value: '1' },
            { label: '2', value: '2' }
         ]
      }
   },
   methods: {
      // 新增:切换位置选择器显示
      togglePositionPicker() {
         this.showPositionPicker = !this.showPositionPicker;
      },
      // 新增:关闭位置选择器
      closePositionPicker() {
         this.showPositionPicker = false;
      },
      // 新增:选择位置
      selectPosition(index) {
         this.positionIndex = index;
         this.tempMaterial.position = this.positionOptions[index].value;
         this.closePositionPicker();
      },
      // 初始化扫码监听
      initScanListener() {
         // 在uni-app中,可以通过ref获取DOM节点,但要注意平台差异
         // 这里我们通过一个安全的方法来聚焦输入框
         this.$nextTick(() => {
            const input = this.$refs.scanInput;
            if (input && typeof input.focus === 'function') {
               input.focus();
            }
         });
      },
      // 聚焦扫码输入框
      focusScanInput() {
         // 使用uni-app的安全方法
         this.$nextTick(() => {
            const input = this.$refs.scanInput;
            if (input) {
               // 在uni-app中,input可能是一个组件实例
               // 我们需要获取其DOM节点或使用平台特定的方法
               // 这里我们尝试调用focus,如果不可用则跳过
               try {
                  if (typeof input.focus === 'function') {
                     input.focus();
                  } else if (input.$el && typeof input.$el.focus === 'function') {
                     // 如果是Vue组件实例
                     input.$el.focus();
                  }
               } catch (error) {
                  console.log('聚焦失败,但不影响功能:', error);
               }
            }
         });
      },
      // 处理扫码输入
      handleMaterialScan(e) {
         const value = e.detail ? e.detail.value : e.target.value;
         // 防抖处理
         if (this.scanTimeout) {
            clearTimeout(this.scanTimeout);
         }
         this.scanTimeout = setTimeout(() => {
            if (value && value.trim()) {
               this.parseBarcodeContent(value.trim());
               this.showScanModal = true;
               this.scanBuffer = ''; // 清空缓冲区
               // 每次打开弹窗时重置位置选择为默认值
               this.positionIndex = 0;
               this.tempMaterial.position = '1';
            }
         }, 300);
      },
      // 解析条码内容
      parseBarcodeContent(content) {
          // const lines = content.split(/\\n/).filter(line => line.trim() !== '');
         const lines = content.split(' ').filter(line => line.trim().length > 0);
          // 清空临时数据
          this.tempMaterial = {
              model: '',
              batch: '',
              matnr: '',
              rollExtent: '',
              weight: '',
              roughWeight: '',
              joint: 0,
            position: '1' // 重置位置为默认值
          };
          // 使用正则表达式提取键值对[6,7](@ref)
          const extractKeyValue = (line) => {
              const match = line.match(/([^:]+):(.+)/);
              if (match && match.length === 3) {
                  return {
                      key: match[1].trim(),
                      value: match[2].trim()
                  };
              }
              return null;
          };
          // 提取数字(包括小数)[6,7](@ref)
          const extractNumber = (str) => {
              const match = str.match(/[\d.]+/);
              return match ? match[0] : '';
          };
          // 遍历每一行,解析键值对
          lines.forEach(line => {
              const keyValue = extractKeyValue(line);
              if (keyValue) {
                  const { key, value } = keyValue;
                  switch (key) {
                      case '卷号':
                          this.tempMaterial.model = value;
                          break;
                      case '箱号':
                          this.tempMaterial.batch = value;
                          break;
                      case '规格':
                          this.tempMaterial.matnr = value;
                          break;
                      case '长度':
                          this.tempMaterial.rollExtent = extractNumber(value);
                          break;
                      case '净重':
                          this.tempMaterial.weight = extractNumber(value);
                          break;
                      case '毛重':
                          this.tempMaterial.roughWeight = extractNumber(value);
                          break;
                      case '接头':
                          this.tempMaterial.joint = extractNumber(value) || 0;
                          break;
                      default:
                          // 可以处理未知键或忽略
                          break;
                  }
              }
          });
      },
      // 确认添加物料
      confirmAddMaterial() {
         this.closePositionPicker();
         if (!this.tempMaterial.model) {
            uni.showToast({
               title: '卷号不能为空',
               icon: 'none'
            });
            return;
         }
         // 检查是否已存在相同物料
         const exists = this.matList.some(item =>
            item.model === this.tempMaterial.model &&
            item.batch === this.tempMaterial.batch
         );
         if (exists) {
            uni.showToast({
               title: '该物料已存在',
               icon: 'none'
            });
            this.closeModal();
            return;
         };
         // 添加到物料列表
         const newMaterial = {
            id: this.materialId++,
            ...this.tempMaterial,
            position: (this.matList.length + 1).toString(),
            cutting: 2,
            qualified: 0
         };
         this.matList.push(newMaterial);
         uni.showToast({
            title: '物料添加成功',
            icon: 'success'
         });
         this.closeModal();
      },
      // 取消添加
      cancelAddMaterial() {
         this.closeModal();
      },
      // 关闭弹窗
      closeModal() {
         this.showPositionPicker = false;
         this.showScanModal = false;
         this.tempMaterial = {
            model: '',
            batch: '',
            matnr: '',
            rollExtent: '',
            weight: '',
            roughWeight: '',
            joint: 0,
            position: '1' // 重置位置
         };
         // 重置位置选择
         this.positionIndex = 0;
         // 重新聚焦到扫码输入框
         setTimeout(() => {
            this.focusScanInput();
         }, 100);
      },
      // 删除物料
      removeMaterial(index) {
         uni.showModal({
            title: '确认删除',
            content: '确定要删除这个物料吗?',
            success: (res) => {
               if (res.confirm) {
                  this.matList.splice(index, 1);
                  uni.showToast({
                     title: '删除成功',
                     icon: 'success'
                  });
               }
            }
         });
      },
      // 检查登录状态
      checkLoginStatus() {
         this.token = uni.getStorageSync('token');
@@ -217,7 +590,7 @@
      },
      
      // 获取箱型数据
      POSTinfo(){
      POSTinfo() {
         if (!this.checkLoginStatus()) return;
         
         uni.showLoading({
@@ -233,27 +606,14 @@
            },
            success: (res) => {
               uni.hideLoading();
               console.log('箱型接口返回:', res.data);
               
               if (res.data && res.data.code === 200) {
                  if (Array.isArray(res.data.data)) {
                     // 尝试多种可能的字段名
                     this.mode = res.data.data
                        .map(item => item.boxSpecs || item.boxType || item.typeName || item.name || '')
                        .filter(item => item && item.trim() !== '');
                     console.log('提取的箱型列表:', this.mode);
                     if (this.mode.length === 0) {
                        uni.showToast({
                           title: '无可用箱型',
                           icon: 'none'
                        });
                     }
                  } else {
                     console.warn('返回数据格式不符,不是数组:', res.data.data);
               if (res.data && res.data.code === 200 && Array.isArray(res.data.data)) {
                  this.mode = res.data.data
                     .map(item => item.boxSpecs || item.boxType || item.typeName || item.name || '')
                     .filter(item => item && item.trim() !== '');
                  if (this.mode.length === 0) {
                     uni.showToast({
                        title: '数据格式错误',
                        title: '无可用箱型',
                        icon: 'none'
                     });
                  }
@@ -274,185 +634,63 @@
            }
         });
      },
      modePickerChange(e) {
         this.index_mode = e.detail.value;
         this.boxType = this.mode[this.index_mode];
         console.log('选择的箱型:', this.boxType);
      },
      handleBarcodeInput(e) {
            // 在uni-app中,textarea的input事件可能是e.detail.value
            const value = e.detail ? e.detail.value : e.target.value;
            this.thingCode = value;
            this.parseBarcodeContent(value);
         },
         parseBarcodeContent(content) {
            if (!content) return;
            // 按行分割内容
            const lines = content.split('\n').filter(line => line.trim() !== '');
            console.log('解析的行数据:', lines);
            // 根据你提供的样例格式解析
            // 格式为:
            // 2511080305A22B6  (卷号)
            // Y251113764        (箱号)
            // 5μm×1050mm       (规格)
            // 8700 m           (长度)
            // 418.0 kg         (净重)
            // 441.0 kg         (毛重)
            // 0 个             (接头)
            if (lines.length >= 7) {
               // 卷号 (第一行)
               this.matList.model = lines[0].trim();
               // 箱号 (第二行)
               this.matList.batch = lines[1].trim();
               // 规格 (第三行)
               this.matList.matnr = lines[2].trim();
               // 长度 (第四行) - 提取数字部分
               const lengthMatch = lines[3].match(/([\d.]+)/);
               if (lengthMatch) {
                  this.matList.rollExtent = lengthMatch[1];
               }
               // 净重 (第五行) - 提取数字部分
               const weightMatch = lines[4].match(/([\d.]+)/);
               if (weightMatch) {
                  this.matList.weight = weightMatch[1];
               }
               // 毛重 (第六行) - 提取数字部分
               const roughWeightMatch = lines[5].match(/([\d.]+)/);
               if (roughWeightMatch) {
                  this.matList.roughWeight = roughWeightMatch[1];
               }
               // 接头 (第七行) - 提取数字部分
               const jointMatch = lines[6].match(/([\d.]+)/);
               if (jointMatch) {
                  this.matList.joint = jointMatch[1];
               }
               console.log('解析后的数据:', this.matList);
            } else if (lines.length > 0) {
               // 如果行数不够,也可以尝试智能匹配
               this.autoMatchFields(lines);
            }
         },
         // 智能匹配方法,用于处理可能的不规则数据
         autoMatchFields(lines) {
            lines.forEach((line, index) => {
               line = line.trim();
               // 根据内容特征匹配
               if (index === 0 && !this.matList.model) {
                  // 假设第一行总是卷号
                  this.matList.model = line;
               } else if (index === 1 && !this.matList.batch) {
                  // 假设第二行总是箱号
                  this.matList.batch = line;
               } else if (line.includes('μm') || line.includes('mm') || line.includes('×')) {
                  // 包含规格特征的
                  this.matList.matnr = line;
               } else if (line.includes('m') && line.match(/[\d.]+ m/)) {
                  // 长度特征
                  const match = line.match(/([\d.]+)/);
                  if (match) this.matList.rollExtent = match[1];
               } else if (line.includes('kg') && line.match(/[\d.]+ kg/)) {
                  // 重量特征,需要区分净重和毛重
                  const match = line.match(/([\d.]+)/);
                  if (match) {
                     const weightValue = match[1];
                     if (!this.matList.weight) {
                        this.matList.weight = weightValue;
                     } else if (!this.matList.roughWeight) {
                        this.matList.roughWeight = weightValue;
                     }
                  }
               } else if (line.includes('个') && line.match(/[\d.]+ 个/)) {
                  // 接头特征
                  const match = line.match(/([\d.]+)/);
                  if (match) this.matList.joint = match[1];
               }
            });
         },
      // 重置表单
      resetForm() {
         this.barcode = '';
         this.boxType = '';
         this.index_mode = 0;
         this.matList = {
            matnr: '',
            maktx: '',
            batch: '',
            model: '',
            position: '1',
            weight: '',
            roughWeight: '',
            anfme: 1.0,
            rollExtent: '',
            joint: 0,
            cutting: 2,
            qualified: 0,
            modelFront: '',
            batchFront: ''
         };
         this.scanBuffer = '';
         this.focusState = false;
      },
      
      // 提交数据
      submit() {
         // 1. 验证登录
         if (!this.checkLoginStatus()) return;
         
         // 2. 验证必填项
         // 验证必填项
         if (!this.barcode) {
            uni.showToast({title: '请扫描托盘编码', icon: 'none'});
            return;
         }
         this.boxType = 999;
         if (!this.boxType) {
            uni.showToast({title: '请选择箱型', icon: 'none'});
            return;
         }
         
         if (!this.matList.model) {
            uni.showToast({title: '请填写卷号', icon: 'none'});
         if (this.matList.length === 0) {
            uni.showToast({title: '请至少添加一个物料', icon: 'none'});
            return;
         }
         
         if (!this.matList.batch) {
            uni.showToast({title: '请填写箱号', icon: 'none'});
            return;
         // 验证每个物料的必填字段
         for (let i = 0; i < this.matList.length; i++) {
            const mat = this.matList[i];
            if (!mat.model) {
               uni.showToast({title: `物料${i+1}卷号不能为空`, icon: 'none'});
               return;
            }
            if (!mat.batch) {
               uni.showToast({title: `物料${i+1}箱号不能为空`, icon: 'none'});
               return;
            }
         }
         
         // 3. 准备数据
         const matItem = {
            ...this.matList,
            weight: this.matList.weight ? Number(this.matList.weight) : null,
            roughWeight: this.matList.roughWeight ? Number(this.matList.roughWeight) : null,
            rollExtent: this.matList.rollExtent ? Number(this.matList.rollExtent) : null,
            joint: this.matList.joint ? Number(this.matList.joint) : 0
         };
         // 准备提交数据
         const submitData = {
            barcode: this.barcode,
            palletizingNo: this.palletizingNo,
            boxType: this.boxType,
            matList: [matItem]
            matList: this.matList.map(mat => ({
               ...mat,
               weight: mat.weight ? Number(mat.weight) : null,
               roughWeight: mat.roughWeight ? Number(mat.roughWeight) : null,
               rollExtent: mat.rollExtent ? Number(mat.rollExtent) : null,
               joint: mat.joint ? Number(mat.joint) : 0,
               position: mat.position // 包含位置信息
            }))
         };
         
         console.log('提交数据:', submitData);
         
         // 4. 发送请求
         // 发送请求
         uni.showLoading({
            title: '提交中...',
            mask: true
@@ -468,7 +706,6 @@
            data: submitData,
            success: (res) => {
               uni.hideLoading();
               console.log('提交返回:', res.data);
               
               if (res.data.code === 200) {
                  uni.showToast({
@@ -477,12 +714,13 @@
                     duration: 2000
                  });
                  
                  // 清空表单
                  setTimeout(() => {
                     this.resetForm();
                  }, 1500);
               } else {
                  uni.showToast({
                     title: res.data.message || '提交失败',
                     title: res.data.msg || '提交失败',
                     icon: 'none'
                  });
               }
@@ -497,212 +735,510 @@
            }
         });
      },
      // 重置表单
      resetForm() {
         this.barcode = '';
         this.boxType = '';
         this.index_mode = 0;
         this.matList = [];
         this.materialId = 1;
      }
   }
}
</script>
<style scoped>
/* 全局样式 */
/* 物料位置选择器样式 */
.full-width {
   grid-column: 1 / -1; /* 占满整行 */
   margin-top: 8rpx;
   position: relative;
   z-index: 100; /* 确保在弹窗内部层级正常 */
}
.position-selector {
   width: 200rpx;
   display: flex;
   justify-content: flex-end;
}
.position-picker {
   width: 200rpx;
}
.position-display {
   display: flex;
   align-items: center;
   justify-content: space-between;
   padding: 8rpx 16rpx;
   border: 1rpx solid #e5e7eb;
   border-radius: 6rpx;
   background-color: #ffffff;
   color: #333;
   font-size: 28rpx;
   min-height: 40rpx;
   width: 100%;
   box-sizing: border-box;
}
.placeholder {
   color: #999;
}
.position-arrow {
   font-size: 20rpx;
   color: #666;
   margin-left: 8rpx;
}
/* 全局样式 - 保持原有风格 */
.sockpage {
   background-color: #f5f7fa;
   padding: 24rpx;
   padding: 20rpx;
   min-height: 100vh;
}
/* 表单列容器 */
.column {
   display: flex;
   flex-direction: column;
   gap: 24rpx;
   gap: 20rpx;
}
/* 表单卡片 */
.form-card {
   background: #ffffff;
   border-radius: 12rpx;
   box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
   padding: 24rpx;
   transition: all 0.2s ease;
}
.textareainput{
   width: 60%;
   height: 15px;
   font-size: 28rpx;
   padding: 16rpx 12rpx;
   border: 1rpx solid #e5e7eb;
   border-radius: 8rpx;
   transition: border-color 0.2s ease;
}
/* 物料信息卡片特殊样式 */
.material-card {
   padding: 0;
}
.card-title {
   font-size: 30rpx;
   font-weight: 500;
   color: #1f2937;
   padding: 24rpx 24rpx 16rpx;
   border-bottom: 1rpx solid #f0f0f0;
   padding: 20rpx;
   box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
}
/* 表单行 */
.form-row {
   display: flex;
   flex-direction: row;
   align-items: center;
   gap: 16rpx;
   gap: 20rpx;
}
/* 标签样式 */
.label {
   font-size: 28rpx;
   color: #374151;
   color: #333;
   font-weight: 500;
   min-width: 140rpx;
}
/* 必填项标红 */
.required {
   color: #ef4444;
   color: #e64340;
   margin-right: 4rpx;
}
/* 选择器容器 */
.picker-wrap {
   flex: 1;
   display: flex;
   align-items: center;
   justify-content: space-between;
}
/* 选择器hover态 */
.picker-hover {
   background-color: #f9fafb;
   border-radius: 8rpx;
}
/* 输入框容器 */
.input-box {
   flex: 1;
   font-size: 28rpx;
   padding: 16rpx 12rpx;
   border: 1rpx solid #e5e7eb;
   border-radius: 8rpx;
   transition: border-color 0.2s ease;
   border-radius: 6rpx;
   padding: 16rpx 20rpx;
   background: #fff;
}
.input-box:focus-within {
   border-color: #f97316;
.input-placeholder {
   color: #999;
   font-size: 28rpx;
}
/* 输入值样式 */
.input-value {
   color: #1f2937;
   color: #333;
   font-size: 28rpx;
}
/* 扫码图标 */
.scan-icon {
/* 物料信息卡片 */
.material-card {
   padding: 0;
}
.card-title {
   font-size: 30rpx;
   font-weight: 500;
   color: #333;
   padding: 20rpx 20rpx 16rpx;
   border-bottom: 1rpx solid #f0f0f0;
}
/* 物料列表 */
.material-list {
   padding: 0 20rpx;
}
.material-item {
   margin-bottom: 20rpx;
}
.material-header {
   display: flex;
   justify-content: space-between;
   align-items: center;
   margin-bottom: 16rpx;
   padding-bottom: 12rpx;
   border-bottom: 1rpx solid #f0f0f0;
}
.material-title {
   font-size: 28rpx;
   font-weight: 500;
   color: #333;
}
.material-actions {
   display: flex;
   gap: 20rpx;
}
.action-btn {
   font-size: 24rpx;
   margin-left: 8rpx;
   color: #6b7280;
   color: #e64340;
   padding: 6rpx 12rpx;
   border-radius: 4rpx;
   background: #fff0f0;
}
/* 物料信息网格布局 */
/* 物料网格 */
.material-grid {
   display: grid;
   grid-template-columns: repeat(2, 1fr);
   gap: 20rpx;
   padding: 24rpx;
   gap: 16rpx;
}
/* 物料信息项 */
.material-item {
   display: flex;
   flex-direction: column;
   gap: 8rpx;
}
/* 物料标签 */
.material-label {
   font-size: 26rpx;
   color: #4b5563;
   color: #666;
}
/* 物料输入框 */
.material-input {
   width: 45%;
   font-size: 28rpx;
   color: #1f2937;
   padding: 16rpx 12rpx;
   color: #333;
   padding: 12rpx;
   border: 1rpx solid #e5e7eb;
   border-radius: 8rpx;
   border-radius: 6rpx;
   background-color: #ffffff;
   transition: border-color 0.2s ease;
}
.material-input:focus {
   border-color: #f97316;
   outline: none;
/* 空状态 */
.empty-state {
   text-align: center;
   padding: 40rpx 20rpx;
}
/* 按钮组 */
.btn-group {
   display: flex;
   gap: 20rpx;
   justify-content: center;
   margin-top: 16rpx;
   padding: 8rpx 0;
.empty-icon {
   font-size: 60rpx;
   display: block;
   margin-bottom: 20rpx;
   opacity: 0.5;
}
/* 操作按钮通用样式 */
.operate-btn {
   flex: 1;
   max-width: 200rpx;
   height: 80rpx;
   line-height: 80rpx;
.empty-text {
   display: block;
   font-size: 28rpx;
   font-weight: 500;
   border-radius: 12rpx;
   border: none;
   transition: all 0.2s ease;
   display: flex;
   align-items: center;
   justify-content: center;
   color: #999;
   margin-bottom: 10rpx;
}
.empty-tip {
   display: block;
   font-size: 24rpx;
   color: #ccc;
}
/* 扫码按钮 */
.scan-btn {
   background-color: #3b82f6;
   color: #ffffff;
   display: flex;
   align-items: center;
   justify-content: center;
   gap: 10rpx;
   padding: 20rpx;
   margin: 20rpx 20rpx 20rpx;
   background: #f0f7ff;
   border: 1rpx dashed #1989fa;
   border-radius: 8rpx;
   color: #1989fa;
   font-size: 28rpx;
}
.scan-btn:active {
   background-color: #2563eb;
   transform: scale(0.98);
.scan-icon {
   font-size: 36rpx;
   font-weight: bold;
}
/* 提交按钮 */
.submit-btn {
   background-color: #f97316;
   color: #ffffff;
/* 按钮组 */
.btn-group {
   margin-top: 20rpx;
   padding: 8rpx 0;
   text-align: center;
}
.submit-btn:active {
   background-color: #ea580c;
   transform: scale(0.98);
.operate-btn {
   width: 200rpx;
   height: 80rpx;
   line-height: 80rpx;
   font-size: 30rpx;
   font-weight: 500;
   border-radius: 8rpx;
   border: none;
   background: #333;
   color: #fff;
}
/* 适配小屏幕 */
@media (max-width: 375px) {
/* 弹窗样式 */
.modal-mask {
   position: fixed;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   background: rgba(0, 0, 0, 0.5);
   display: flex;
   align-items: center;
   justify-content: center;
   z-index: 1000;
}
.modal-content {
   background: #fff;
   border-radius: 12rpx;
   width: 600rpx;
   max-width: 90%;
   overflow: hidden;
}
.modal-header {
   padding: 30rpx 30rpx 20rpx;
   border-bottom: 1rpx solid #f0f0f0;
}
.modal-title {
   font-size: 32rpx;
   font-weight: 500;
   color: #333;
}
.modal-body {
   padding: 30rpx;
}
.scan-preview {
   margin-bottom: 20rpx;
   padding-bottom: 20rpx;
   border-bottom: 1rpx solid #f0f0f0;
}
.scan-label {
   font-size: 28rpx;
   color: #666;
   display: block;
   margin-bottom: 10rpx;
}
.scan-code {
   font-size: 32rpx;
   color: #333;
   font-weight: bold;
   word-break: break-all;
}
.preview-grid {
   display: grid;
   grid-template-columns: repeat(2, 1fr);
   gap: 15rpx;
}
.preview-item {
   display: flex;
   justify-content: space-between;
   align-items: center;
}
.preview-label {
   font-size: 28rpx;
   color: #666;
}
.preview-value {
   font-size: 28rpx;
   color: #333;
   font-weight: 500;
}
.modal-footer {
   display: flex;
   border-top: 1rpx solid #f0f0f0;
}
.modal-btn {
   flex: 1;
   height: 90rpx;
   line-height: 90rpx;
   font-size: 30rpx;
   border: none;
   background: transparent;
   border-radius: 0;
}
.modal-btn.cancel {
   color: #999;
   border-right: 1rpx solid #f0f0f0;
}
.modal-btn.confirm {
   color: #1989fa;
   font-weight: 500;
}
/* 自定义选择器样式 */
.custom-picker-overlay {
   position: fixed;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   background-color: rgba(0, 0, 0, 0.5);
   display: flex;
   align-items: center;
   justify-content: center;
   z-index: 9999; /* 确保在最上层 */
}
.custom-picker-content {
   background-color: #ffffff;
   border-radius: 12rpx;
   width: 600rpx;
   max-width: 80%;
   max-height: 70vh;
   overflow: hidden;
   box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
   animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
   from {
      opacity: 0;
      transform: translateY(20rpx);
   }
   to {
      opacity: 1;
      transform: translateY(0);
   }
}
.custom-picker-header {
   display: flex;
   justify-content: space-between;
   align-items: center;
   padding: 30rpx;
   border-bottom: 1rpx solid #f0f0f0;
}
.custom-picker-title {
   font-size: 32rpx;
   font-weight: 500;
   color: #333;
}
.custom-picker-close {
   font-size: 40rpx;
   color: #999;
   line-height: 1;
   padding: 0 10rpx;
   cursor: pointer;
}
.custom-picker-list {
   max-height: 50vh;
   overflow-y: auto;
   padding: 0;
}
.custom-picker-item {
   display: flex;
   justify-content: space-between;
   align-items: center;
   padding: 25rpx 30rpx;
   border-bottom: 1rpx solid #f5f5f5;
   cursor: pointer;
   transition: background-color 0.2s;
}
.custom-picker-item:last-child {
   border-bottom: none;
}
.custom-picker-item:hover {
   background-color: #f8f9fa;
}
.custom-picker-item.selected {
   background-color: #f0f7ff;
   color: #1989fa;
}
.custom-picker-text {
   font-size: 30rpx;
}
.custom-picker-check {
   font-size: 28rpx;
   color: #1989fa;
   font-weight: bold;
}
/* 弹窗样式调整,确保层级关系 */
.modal-mask {
   position: fixed;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   background: rgba(0, 0, 0, 0.5);
   display: flex;
   align-items: center;
   justify-content: center;
   z-index: 1000; /* 弹窗基础层级 */
}
.modal-content {
   position: relative; /* 确保子元素相对定位 */
   z-index: 1001; /* 比蒙版高一级 */
   background: #fff;
   border-radius: 12rpx;
   width: 600rpx;
   max-width: 90%;
   overflow: visible; /* 改为 visible 允许选择器弹出 */
}
/* 响应式适配 */
@media (max-width: 750rpx) {
   .material-grid {
      grid-template-columns: 1fr;
   }
   
   .operate-btn {
      max-width: 160rpx;
      height: 72rpx;
      line-height: 72rpx;
      font-size: 26rpx;
   .preview-grid {
      grid-template-columns: 1fr;
   }
   .modal-content {
      width: 90%;
   }
   .custom-picker-content {
      width: 90%;
      max-width: 90%;
   }
   .custom-picker-item {
      padding: 20rpx 25rpx;
   }
}
</style>