#
zhou zhou
2 天以前 153d2d110c7b43c4f8407ff3d851c7a4434b5c21
pages/sockroom/sockroom.vue
@@ -1,18 +1,20 @@
<template>
   <view class="sockpage">
      <view class="column">
         <!-- 托盘编码栏(对应后端barcode) -->
         <view class="form-card">
            <view class="form-row">
               <view class="label">
                  <text class="required">*</text>托盘编码:
               </view>
               <view class="picker-wrap" @click="scan" hover-class="picker-hover">
               <view class="picker-wrap" hover-class="picker-hover">
                  <view class="input-box">
                     <text class="input-placeholder" v-if="!barcode">点击扫码录入</text>
                     <text class="input-value" v-else>{{barcode}}</text>
                     <input
                     id="pdacode"
                     type="text"
                     v-model="barcode"
                     placeholder="请扫码"
                     />
                  </view>
                  <view class="scan-icon">📷</view>
               </view>
            </view>
         </view>
@@ -34,6 +36,25 @@
            </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"
                        type="text"
                        v-model="thingCode"
                        placeholder="请扫码"
                        @input="handleBarcodeInput"
                        />
                     </view>
                  </view>
               </view>
            </view>
         <!-- 物料信息输入栏(对应后端MatList) -->
         <view class="form-card material-card">
            <view class="card-title">物料信息</view>
@@ -44,8 +65,9 @@
                     class="material-input" 
                     type="text" 
                     v-model="matList.model"
                     placeholder="请输入卷号"
                     placeholder="请扫码或输入卷号"
                     placeholder-class="input-placeholder"
                     ref="modelInput"
                  />
               </view>
               <view class="material-item">
@@ -54,8 +76,9 @@
                     class="material-input" 
                     type="text" 
                     v-model="matList.batch"
                     placeholder="请输入箱号"
                     placeholder="请扫码或输入箱号"
                     placeholder-class="input-placeholder"
                     ref="batchInput"
                  />
               </view>
               <view class="material-item">
@@ -74,7 +97,7 @@
                     class="material-input" 
                     type="number" 
                     v-model="matList.rollExtent"
                     placeholder="请输入长度(m)"
                     placeholder="请输入长度"
                     placeholder-class="input-placeholder"
                  />
               </view>
@@ -84,7 +107,7 @@
                     class="material-input" 
                     type="number" 
                     v-model="matList.weight"
                     placeholder="请输入净重(kg)"
                     placeholder="请输入净重"
                     placeholder-class="input-placeholder"
                  />
               </view>
@@ -94,7 +117,7 @@
                     class="material-input" 
                     type="number" 
                     v-model="matList.roughWeight"
                     placeholder="请输入毛重(kg)"
                     placeholder="请输入毛重"
                     placeholder-class="input-placeholder"
                  />
               </view>
@@ -110,233 +133,370 @@
               </view>
            </view>
         </view>
         <!-- 操作按钮组 -->
         <view class="btn-group">
            <button class="operate-btn scan-btn" @click="scantwo">扫货物码</button>
            <button class="operate-btn submit-btn" @click="submit">成品入库</button>
         </view>
      </view>
   </view>
</template>
<script>
import { onLoad } from '../../uni_modules/uview-ui/libs/mixin/mixin'
export default {
   onLoad(){
      // 先读取缓存,再执行请求
      this.baseUrl = uni.getStorageSync('baseUrl');
      this.token = uni.getStorageSync('token');
      // 页面加载时 mode 为空,调用接口后才填充数据
   onLoad(options){
      this.checkLoginStatus();
      this.POSTinfo(); 
   },
   onShow() {
      this.checkLoginStatus();
   },
   onHide() {
      if (this.scanTimeout) {
         clearTimeout(this.scanTimeout);
         this.scanTimeout = null;
      }
   },
   data() {
      return {
         thingCode:'',
         focusState: false,
         baseUrl: '',
         barcodeNum:'',
         barcode: '', // 托盘码
         palletizingNo: '1', // 码垛位编号
         boxType: '', // 木箱类型
         token: '',
         barcode: '',
         palletizingNo: '1',
         boxType: '',
         matList: {
            matnr: '', // 规格
            maktx: '', // 物料名称
            batch: '', // 木箱编号
            model: '', // 卷编号
            position: '1', // 木箱码垛位置
            weight: '', // 净重
            roughWeight: '', // 毛重
            anfme: 1.0, // 默认值1.0
            rollExtent: '', // 卷长度
            joint: 0, // 接头
            cutting: 2, // 默认“否”
            qualified: 0, // 默认“否”
            modelFront: '', // 分切前箱编号
            batchFront: '' ,// 分切前卷号
            matnr: '',
            maktx: '',
            batch: '',
            model: '',
            position: '1',
            weight: '',
            roughWeight: '',
            anfme: 1.0,
            rollExtent: '',
            joint: 0,
            cutting: 2,
            qualified: 0,
            modelFront: '',
            batchFront: ''
         },
         // 关键1:初始化 mode 为空数组 → 页面加载时箱型无数据
         mode: [], 
         index_mode: 0,
         index_num: 0,
         submitData: {} // 最终提交给后端的数据
         submitData: {},
         scanBuffer: '',
         scanTimeout: null,
         lastScanTime: 0,
         isProcessingScan: false
      }
   },
   methods: {
      // 检查登录状态
      checkLoginStatus() {
         this.token = uni.getStorageSync('token');
         this.baseUrl = uni.getStorageSync('baseUrl');
         if (!this.token || !this.baseUrl) {
            uni.showModal({
               title: '提示',
               content: '请先登录',
               showCancel: false,
               success: (res) => {
                  if (res.confirm) {
                     uni.navigateTo({
                        url: '/pages/login/login'
                     });
                  }
               }
            });
            return false;
         }
         return true;
      },
      // 获取箱型数据
      POSTinfo(){
         if (!this.checkLoginStatus()) return;
         uni.showLoading({
            title: '加载中...'
         });
         uni.request({
            url: this.baseUrl + '/mobile/box/type/complete/auth/v2',
            method:'POST',
            method: 'POST',
            header: {
               'Content-Type': 'application/json'
               'Content-Type': 'application/json',
               'Authorization': 'Bearer ' + this.token
            },
            success:(res)=>{
               // 接口返回后才填充箱型数据
               this.mode = res.data.data.map(item => item.boxSpecs || '').filter(item => item);
               console.log('提取的箱型数据:', this.mode);
            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);
                     uni.showToast({
                        title: '数据格式错误',
                        icon: 'none'
                     });
                  }
               } else {
                  uni.showToast({
                     title: res.data?.message || '获取箱型失败',
                     icon: 'none'
                  });
               }
            },
            fail:(err)=>{
               console.error('获取箱型失败:', err)
            fail: (err) => {
               uni.hideLoading();
               console.error('获取箱型失败:', err);
               uni.showToast({
                  title: '网络错误',
                  icon: 'none'
               });
            }
         })
         });
      },
      modePickerChange(e) {
         this.index_mode = e.detail.value;
         this.boxType = this.mode[this.index_mode]; // 同步到boxType
         this.boxType = this.mode[this.index_mode];
         console.log('选择的箱型:', this.boxType);
      },
      numPickerChange(e) {
         this.index_num = e.detail.value
      },
      // 关键2:修改重置方法 → 清空 mode 及相关状态
      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.barcodeNum = '';
         this.barcode = '';
         this.boxType = '';
         this.index_mode = 0;
         this.index_num = 0;
         this.submitData = {};
         // 清空 mode 数组 → 箱型选择器恢复无数据状态
         this.mode = [];
         // 重置物料信息(保留默认值)
         this.barcode = '';
         this.boxType = '';
         this.index_mode = 0;
         this.matList = {
            matnr: '',
            maktx: '',
            batch: '',
            model: '',
            position: '1',
            position: '1',
            weight: '',
            roughWeight: '',
            anfme: 1.0,
            anfme: 1.0,
            rollExtent: '',
            joint: 0,
            cutting: 2,
            qualified: 0,
            joint: 0,
            cutting: 2,
            qualified: 0,
            modelFront: '',
            batchFront: ''
         };
         // 可选:重置后重新请求箱型数据(根据需求选择)
         // this.POSTinfo();
         this.scanBuffer = '';
         this.focusState = false;
      },
      submit(){
          // 校验必填项
          if(!this.barcode) return uni.showToast({title: '请扫描托盘编码', icon: 'none'})
          if(!this.boxType) return uni.showToast({title: '请选择箱型', icon: 'none'})
          if(!this.matList.model || !this.matList.batch) return uni.showToast({title: '请填写卷号/箱号', icon: 'none'})
          // 数据类型转换
          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,
              anfme: 1.0,
              cutting: 2,
              qualified: 0
          }
          // 组装提交数据
          this.submitData = {
              barcode: this.barcode,
              palletizingNo: this.palletizingNo,
              boxType: this.boxType,
              matList: [matItem]
          }
          console.log('修正类型后的提交数据:', this.submitData)
          // 提交请求
          uni.request({
              url: this.baseUrl + '/mobile/truss/comd/auth/v2',
              method: 'POST',
              header: {'Content-Type': 'application/json'},
              data: this.submitData,
              success: (res) => {
                  console.log('后端返回:', res)
                  uni.showToast({title:'提交成功',icon: 'success'})
                  // 提交成功后重置所有数据
                  this.resetForm();
                  // 可选:重置后重新拉取箱型数据,方便下次操作
                  // setTimeout(() => {
                  //     this.POSTinfo();
                  // }, 300);
              },
              fail: (err) => {
                  console.error('请求失败详情:', err)
                  uni.showToast({title:'提交失败',icon: 'none'})
              },
              complete: (res) => {
                  console.log('请求完成状态:', res)
              }
          })
      },
      scan(){
         uni.scanCode({
            autoDecodeCharSet: true,
            scanType: ['barCode'],
            onlyFromCamera: true,
            continuousScan: false,
            camera: 'back',
            timeout: 5000,
      // 提交数据
      submit() {
         // 1. 验证登录
         if (!this.checkLoginStatus()) return;
         // 2. 验证必填项
         if (!this.barcode) {
            uni.showToast({title: '请扫描托盘编码', icon: 'none'});
            return;
         }
         if (!this.boxType) {
            uni.showToast({title: '请选择箱型', icon: 'none'});
            return;
         }
         if (!this.matList.model) {
            uni.showToast({title: '请填写卷号', icon: 'none'});
            return;
         }
         if (!this.matList.batch) {
            uni.showToast({title: '请填写箱号', 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]
         };
         console.log('提交数据:', submitData);
         // 4. 发送请求
         uni.showLoading({
            title: '提交中...',
            mask: true
         });
         uni.request({
            url: this.baseUrl + '/mobile/truss/comd/auth/v2',
            method: 'POST',
            header: {
               'Content-Type': 'application/json',
               'Authorization': 'Bearer ' + this.token
            },
            data: submitData,
            success: (res) => {
               this.barcodeNum = res.result
               this.barcode = res.result
               uni.showToast({title: `托盘编码扫码成功`,icon: 'success'})
               uni.hideLoading();
               console.log('提交返回:', res.data);
               if (res.data.code === 200) {
                  uni.showToast({
                     title: '提交成功',
                     icon: 'success',
                     duration: 2000
                  });
                  setTimeout(() => {
                     this.resetForm();
                  }, 1500);
               } else {
                  uni.showToast({
                     title: res.data.message || '提交失败',
                     icon: 'none'
                  });
               }
            },
            fail: (err) => {
               uni.showToast({title: '扫码失败或取消',icon: 'none'})
            }
         })
      },
      parseQrCodeText(text) {
         const result = {};
         const regMap = {
            model: /卷号:(.+)/,
            batch: /箱号:(.+)/,
            matnr: /规格:(.+)/,
            rollExtent: /长度:(.+?)\s*m/,
            weight: /净重:(.+?)\s*kg/,
            roughWeight: /毛重:(.+?)\s*kg/,
            joint: /接头:(.+?)\s*个/
         };
         Object.keys(regMap).forEach(key => {
            const match = text.match(regMap[key]);
            if (match && match[1]) {
               result[key] = match[1].trim();
               uni.hideLoading();
               console.error('提交失败:', err);
               uni.showToast({
                  title: '网络错误',
                  icon: 'none'
               });
            }
         });
         return result;
      },
      scantwo(){
         uni.scanCode({
            autoDecodeCharSet:true,
            scanType: ['qrCode'],
            success: (res) => {
               const qrResult = res.result.trim();
               this.barcodeNum = qrResult;
               let parseResult = {};
               try {
                  parseResult = JSON.parse(qrResult);
                  parseResult = {
                     model: parseResult.卷号 || '',
                     batch: parseResult.箱号 || '',
                     matnr: parseResult.规格 || '',
                     rollExtent: (parseResult.长度 || '').replace(/\s*m/g, '') || '',
                     weight: (parseResult.净重 || '').replace(/\s*kg/g, '') || '',
                     roughWeight: (parseResult.毛重 || '').replace(/\s*kg/g, '') || '',
                     joint: (parseResult.接头 || '').replace(/\s*个/g, '') || ''
                  };
               } catch (e) {
                  parseResult = this.parseQrCodeText(qrResult);
               }
               this.matList = { ...this.matList, ...parseResult };
               uni.showToast({title: `物料信息扫码成功`,icon: 'success'});
            },
            fail: (err) => {
               uni.showToast({title: '扫码失败或取消',icon: 'none'})
            }
         })
      }
   }
}
</script>
@@ -364,12 +524,19 @@
   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;
@@ -428,11 +595,6 @@
   border-color: #f97316;
}
/* 占位符样式 */
.input-placeholder {
   color: #9ca3af;
}
/* 输入值样式 */
.input-value {
   color: #1f2937;
@@ -468,6 +630,7 @@
/* 物料输入框 */
.material-input {
   width: 45%;
   font-size: 28rpx;
   color: #1f2937;
   padding: 16rpx 12rpx;