111
啊鑫
9 天以前 2b0e70bb88ced210dbc693a4d2ded2d658b1da02
pages/QC/OQC/ScanCode.vue
@@ -1,745 +1,928 @@
<template>
   <view class="container">
      <!-- 表单区域 -->
      <view class="form-container card">
         <form :modelValue="formData">
            <view class="form-grid">
               <view class="form-group col-2">
                  <label class="form-label">物料条码:</label>
                  <view class="input-with-scan">
                     <input class="form-input scan-input" type="text" v-model="formData.ItemBarcode"
                        @confirm="addItemBarCode"
                        placeholder="输入后离开或按回车" />
                     <view class="scan-button" @tap="startScan">
                        <uni-icons type="scan" size="24" color="#007bff"></uni-icons>
                        <text class="scan-text">扫码</text>
                     </view>
                  </view>
               </view>
               <view class="form-group col-2">
                  <label class="form-label">产品名称:</label>
                  <input class="form-input" disabled="true" type="text" v-model="formData.itemName" />
               </view>
               <view class="form-group col-2">
                  <label class="form-label">产品编码:</label>
                  <input class="form-input" disabled="true" type="text" v-model="formData.itemNo" />
               </view>
               <view class="form-group col-2">
                  <label class="form-label">订单编号:</label>
                  <input class="form-input" disabled="true" type="text" v-model="formData.taskNo" />
               </view>
               <view class="form-group col-2">
                  <label class="form-label">已扫数量:</label>
                  <input class="form-input" disabled="true" type="text" v-model="quantity" />
               </view>
            </view>
         </form>
      </view>
  <view class="container">
    <!-- 表单区域 -->
    <view class="form-container card">
      <form :modelValue="formData">
        <view class="form-grid">
          <view class="form-group col-2">
            <label class="form-label">物料条码:</label>
            <view class="input-with-scan">
              <input v-model="formData.ItemBarcode" class="form-input scan-input" placeholder="输入后离开或按回车"
                     type="text"
                     @confirm="addItemBarCode"/>
              <view class="scan-button" @tap="startScan">
                <uni-icons color="#007bff" size="24" type="scan"></uni-icons>
                <text class="scan-text">扫码</text>
              </view>
            </view>
          </view>
          <view class="form-group col-2">
            <label class="form-label">产品名称:</label>
            <input v-model="formData.itemName" class="form-input" disabled="true" type="text"/>
          </view>
          <view class="form-group col-2">
            <label class="form-label">产品编码:</label>
            <input v-model="formData.itemNo" class="form-input" disabled="true" type="text"/>
          </view>
          <view class="form-group col-2">
            <label class="form-label">订单编号:</label>
            <input v-model="formData.taskNo" class="form-input" disabled="true" type="text"/>
          </view>
          <view class="form-group col-2">
            <label class="form-label">已扫数量:</label>
            <input v-model="quantity" class="form-input" disabled="true" type="text"/>
          </view>
        </view>
      </form>
    </view>
      <!-- 待检条码表格区域 -->
      <view class="table-container card">
         <view class="table-header">
            <text class="section-title">待检条码列表</text>
            <view class="table-tip">
               <text class="tip-text">👈 左右滑动查看更多信息</text>
            </view>
         </view>
         <view class="table-wrapper">
            <scroll-view class="table-scroll" scroll-x="true" show-scrollbar="true">
               <uni-table ref="table" border emptyText="暂无更多数据" class="custom-table">
                  <uni-tr class="table-header-row">
                     <uni-th align="center" class="th" width="80">序号</uni-th>
                     <uni-th align="center" class="th" width="160">物料条码</uni-th>
                     <uni-th align="center" class="th" width="140">订单编号</uni-th>
                     <uni-th align="center" class="th" width="140">产品编码</uni-th>
                     <uni-th align="center" class="th" width="160">产品名称</uni-th>
                     <uni-th align="center" class="th" width="100">条码数量</uni-th>
                     <uni-th align="center" class="th" width="80"> </uni-th>
                  </uni-tr>
                  <uni-tr v-for="(item, index) in tableData" :key="index" class="table-row">
                     <uni-td align="center" width="80">
                        <view class="description-text">{{ index + 1 }}</view>
                     </uni-td>
                     <uni-td align="center" width="160">
                        <view class="cell-content">{{ item.itemBarcode }}</view>
                     </uni-td>
                     <uni-td align="center" width="140">
                        <view class="cell-content">{{ item.taskNo || '-' }}</view>
                     </uni-td>
                     <uni-td align="center" width="140">
                        <view class="cell-content">{{ item.itemNo }}</view>
                     </uni-td>
                     <uni-td align="center" width="160">
                        <view class="cell-content" :title="item.itemName">{{ item.itemName }}</view>
                     </uni-td>
                     <uni-td align="center" width="100">
                        <view class="cell-content quantity">{{ item.quantity }}</view>
                     </uni-td>
                     <uni-td align="center" width="80">
                        <view class="cell-content"> </view>
                     </uni-td>
                  </uni-tr>
               </uni-table>
            </scroll-view>
            <!-- 右固定悬浮删除按钮列 -->
            <view class="fixed-delete-column">
               <view class="fixed-header">
                  <text class="fixed-header-text">操作</text>
               </view>
               <view class="fixed-content">
                  <view v-for="(item, index) in tableData" :key="index" class="fixed-delete-item"
                     :class="{ 'even': index % 2 === 1 }">
                     <view @click="deleteItem(index)" class="delete-icon">
                        <uni-icons type="trash" size="24"></uni-icons>
                     </view>
                  </view>
               </view>
            </view>
         </view>
      </view>
    <!-- 待检条码表格区域 -->
    <view class="table-container card">
      <view class="table-header">
        <text class="section-title">待检条码列表</text>
        <view class="table-tip">
          <text class="tip-text">👈 左右滑动查看更多信息</text>
        </view>
      </view>
      <view class="table-wrapper">
        <scroll-view class="table-scroll" scroll-x="true" show-scrollbar="true">
          <uni-table ref="table" border class="custom-table" emptyText="暂无更多数据">
            <uni-tr class="table-header-row">
              <uni-th align="center" class="th" width="80">序号</uni-th>
              <uni-th align="center" class="th" width="160">物料条码</uni-th>
              <uni-th align="center" class="th" width="140">订单编号</uni-th>
              <uni-th align="center" class="th" width="140">产品编码</uni-th>
              <uni-th align="center" class="th" width="160">产品名称</uni-th>
              <uni-th align="center" class="th" width="100">条码数量</uni-th>
              <uni-th align="center" class="th" width="80">删除</uni-th>
            </uni-tr>
            <uni-tr v-for="(item, index) in tableData" :key="index" class="table-row">
              <uni-td align="center" width="80">
                <view class="description-text">{{ index + 1 }}</view>
              </uni-td>
              <uni-td align="center" width="160">
                <view class="cell-content">{{ item.itemBarcode }}</view>
              </uni-td>
              <uni-td align="center" width="140">
                <view class="cell-content">{{ item.taskNo || '-' }}</view>
              </uni-td>
              <uni-td align="center" width="140">
                <view class="cell-content">{{ item.itemNo }}</view>
              </uni-td>
              <uni-td align="center" width="160">
                <view :title="item.itemName" class="cell-content">{{ item.itemName }}</view>
              </uni-td>
              <uni-td align="center" width="100">
                <view class="cell-content quantity">{{ item.quantity }}</view>
              </uni-td>
              <uni-td align="center" width="80">
                <view class="delete-icon" @click="deleteItem(index)">
                  <uni-icons size="24" type="trash"></uni-icons>
                </view>
              </uni-td>
            </uni-tr>
          </uni-table>
        </scroll-view>
      </view>
    </view>
      <!-- 操作按钮区域 -->
      <view class="action-buttons-container button-group">
         <view class="plus-button" :class="{ 'submitting': isSubmitting }" @tap="handleSubmit">
            <text>{{ isSubmitting ? '提交中...' : '生成OQC检验单' }}</text>
         </view>
      </view>
   </view>
    <!-- 操作按钮区域 -->
    <view class="action-buttons-container button-group">
      <view :class="{ 'submitting': isSubmitting }" class="plus-button" @tap="handleSubmit">
        <text>{{ isSubmitting ? '提交中...' : '生成OQC检验单' }}</text>
      </view>
    </view>
  </view>
</template>
<script>
   export default {
      data() {
         return {
            formData: {},
            tableData: [],
            quantity: 0,
            isSubmitting: false, // 防止重复提交
            isProcessing: false, // 防止重复处理条码
         }
      },
      methods: {
         // 启动扫码功能
         startScan() {
            // 检查是否正在处理条码,防止重复扫码
            if (this.isProcessing) {
               this.$showMessage("正在处理条码,请稍候");
               return;
            }
export default {
  data() {
    return {
      formData: {},
      tableData: [],
      quantity: 0,
      isSubmitting: false, // 防止重复提交
      isProcessing: false, // 防止重复处理条码
    }
  },
  methods: {
    // 启动扫码功能
    startScan() {
      // 检查是否正在处理条码,防止重复扫码
      if (this.isProcessing) {
        this.$showMessage("正在处理条码,请稍候");
        return;
      }
            uni.scanCode({
               scanType: ['barCode', 'qrCode'], // 支持条码和二维码
               success: (res) => {
                  console.log('扫码成功:', res);
                  // 将扫码结果设置到输入框
                  this.formData.ItemBarcode = res.result;
                  // 自动处理扫码结果
                  this.addItemBarCode();
               },
               fail: (err) => {
                  console.log('扫码失败:', err);
                  if (err.errMsg && err.errMsg.indexOf('cancel') === -1) {
                     this.$showMessage("扫码失败,请重试");
                  }
               }
            });
         },
      uni.scanCode({
        scanType: ['barCode', 'qrCode'], // 支持条码和二维码
        success: (res) => {
          console.log('扫码成功:', res);
          // 将扫码结果设置到输入框
          this.formData.ItemBarcode = res.result;
          // 自动处理扫码结果
          this.addItemBarCode();
        },
        fail: (err) => {
          console.log('扫码失败:', err);
          if (err.errMsg && err.errMsg.indexOf('cancel') === -1) {
            this.$showMessage("扫码失败,请重试");
          }
        }
      });
    },
         addItemBarCode() {
            // 防止重复处理
            if (this.isProcessing) {
               return;
            }
    addItemBarCode() {
      // 防止重复处理
      if (this.isProcessing) {
        return;
      }
            // 校验物料条码是否为空
            if (!this.formData.ItemBarcode || this.formData.ItemBarcode.trim() === '') {
               this.$showMessage("请输入物料条码");
               return;
            }
      // 校验物料条码是否为空
      if (!this.formData.ItemBarcode || this.formData.ItemBarcode.trim() === '') {
        this.$showMessage("请输入物料条码");
        return;
      }
            // 检查物料条码是否已存在于 tableData 中
            const isDuplicate = this.tableData.some(item => item.itemBarcode === this.formData.ItemBarcode);
            if (isDuplicate) {
               this.$showMessage("该物料条码已存在,请检查!");
               return;
            }
      // 检查物料条码是否已存在于 tableData 中
      const isDuplicate = this.tableData.some(item => item.itemBarcode === this.formData.ItemBarcode);
      if (isDuplicate) {
        this.$showMessage("该物料条码已存在,请检查!");
        return;
      }
            // 设置处理状态
            this.isProcessing = true;
      // 设置处理状态
      this.isProcessing = true;
            // 如果通过了上述校验,发送请求并更新数据
            this.$post({
               url: "/MesOqcItemsDetect02/GetItemBarCode",
               data: {
                  ItemCode: this.formData.ItemBarcode
               }
            }).then(res => {
               let fr = res.data.tbBillList;
      // 如果通过了上述校验,发送请求并更新数据
      this.$post({
        url: "/MesOqcItemsDetect02/GetItemBarCode",
        data: {
          ItemCode: this.formData.ItemBarcode
        }
      }).then(res => {
        let fr = res.data.tbBillList;
               // 数据完整性校验
               if (!fr) {
                  this.$showMessage("获取条码信息失败,请重试");
                  return;
               }
        // 数据完整性校验
        if (!fr) {
          this.$showMessage("获取条码信息失败,请重试");
          return;
        }
               if (!fr.itemId || !fr.itemName || !fr.itemNo) {
                  this.$showMessage("条码信息不完整,请检查条码");
                  return;
               }
        if (!fr.itemId || !fr.itemName || !fr.itemNo) {
          this.$showMessage("条码信息不完整,请检查条码");
          return;
        }
               if (fr.quantity <= 0) {
                  this.$showMessage("条码数量为0,请确认");
                  return;
               }
        if (fr.quantity <= 0) {
          this.$showMessage("条码数量为0,请确认");
          return;
        }
               //需要验证
               //扫的码的itemId必须是和tableData中的itemId相同  必须的条件
               //扫的码的TaskNo也必须是和tableData中的TaskNo相同
               //TaskNo为空的只能和TaskNo为空的一起扫
               // 如果tableData中已有数据,需要验证itemId和TaskNo的一致性
               if (this.tableData.length > 0) {
                  const firstItem = this.tableData[0];
                  // 验证itemId是否相同(必须条件)
                  if (fr.itemId !== firstItem.itemId) {
                     this.$showMessage("物料编码不一致,请扫描相同物料的条码");
                     return;
                  }
                  // 验证TaskNo是否相同
                  if (fr.taskNo !== firstItem.taskNo) {
                     this.$showMessage("订单编号不一致,请扫描相同订单的条码");
                     return;
                  }
                  // 验证空TaskNo的情况:TaskNo为空的只能和TaskNo为空的一起扫
                  if ((fr.taskNo === '' || fr.taskNo === null || fr.taskNo === undefined) &&
                     (firstItem.taskNo !== '' && firstItem.taskNo !== null && firstItem.taskNo !== undefined)) {
                     this.$showMessage("订单编号不匹配,空订单编号只能与空订单编号一起扫描");
                     return;
                  }
                  if ((fr.taskNo !== '' && fr.taskNo !== null && fr.taskNo !== undefined) &&
                     (firstItem.taskNo === '' || firstItem.taskNo === null || firstItem.taskNo === undefined)) {
                     this.$showMessage("订单编号不匹配,有订单编号的条码只能与有订单编号的条码一起扫描");
                     return;
                  }
               }
        //需要验证
        //扫的码的itemId必须是和tableData中的itemId相同  必须的条件
        //扫的码的TaskNo也必须是和tableData中的TaskNo相同
        //TaskNo为空的只能和TaskNo为空的一起扫
               this.formData = fr;
               this.tableData.push(fr); // 将新数据添加到表格
               this.quantity = this.tableData.reduce(function(accumulator, current) {
                  return accumulator + current["quantity"];
               }, 0);
               // 清空输入框
               this.formData.ItemBarcode = '';
            }).catch(error => {
               this.$showMessage("获取条码信息失败,请重试");
            }).finally(() => {
               // 重置处理状态
               this.isProcessing = false;
            });
         },
        // 如果tableData中已有数据,需要验证itemId和TaskNo的一致性
        if (this.tableData.length > 0) {
          const firstItem = this.tableData[0];
         // 删除操作:删除 tableData 中指定索引的数据
         deleteItem(index) {
            this.tableData.splice(index, 1); // 删除该行数据
            this.quantity = this.tableData.reduce(function(accumulator, current) {
               return accumulator + current["quantity"];
            }, 0); // 更新条码数量
          // 验证itemId是否相同(必须条件)
          if (fr.itemId !== firstItem.itemId) {
            this.$showMessage("物料编码不一致,请扫描相同物料的条码");
            return;
          }
            if (this.tableData.length <= 0) {
               this.formData = {};
            }
         },
          // 验证TaskNo是否相同
          if (fr.taskNo !== firstItem.taskNo) {
            this.$showMessage("订单编号不一致,请扫描相同订单的条码");
            return;
          }
         handleSubmit() {
            console.log("handleSubmit方法被调用,isSubmitting:", this.isSubmitting);
            console.log("tableData长度:", this.tableData.length);
            console.log("quantity:", this.quantity);
            this.submit();
         },
          // 验证空TaskNo的情况:TaskNo为空的只能和TaskNo为空的一起扫
          if ((fr.taskNo === '' || fr.taskNo === null || fr.taskNo === undefined) &&
              (firstItem.taskNo !== '' && firstItem.taskNo !== null && firstItem.taskNo !== undefined)) {
            this.$showMessage("订单编号不匹配,空订单编号只能与空订单编号一起扫描");
            return;
          }
         submit() {
            console.log("submit方法被调用");
            // 防止重复提交
            if (this.isSubmitting) {
               this.$showMessage("正在提交中,请勿重复操作");
               return;
            }
          if ((fr.taskNo !== '' && fr.taskNo !== null && fr.taskNo !== undefined) &&
              (firstItem.taskNo === '' || firstItem.taskNo === null || firstItem.taskNo === undefined)) {
            this.$showMessage("订单编号不匹配,有订单编号的条码只能与有订单编号的条码一起扫描");
            return;
          }
        }
            // 校验用户登录状态
            if (!this.$loginInfo.account) {
               this.$showMessage("用户未登录,请重新登录");
               return;
            }
        this.formData = fr;
        this.tableData.push(fr); // 将新数据添加到表格
        this.quantity = this.tableData.reduce(function (accumulator, current) {
          return accumulator + current["quantity"];
        }, 0);
            // 校验条码数量是否有效
            if (this.quantity <= 0) {
               this.$showMessage("条码数量必须大于0");
               return;
            }
        // 清空输入框
        this.formData.ItemBarcode = '';
      }).catch(error => {
        this.$showMessage("获取条码信息失败,请重试");
      }).finally(() => {
        // 重置处理状态
        this.isProcessing = false;
      });
    },
            // 校验是否有数据
            if (this.tableData.length === 0) {
               this.$showMessage("请扫描条码");
               return;
            }
    // 删除操作:删除 tableData 中指定索引的数据
    deleteItem(index) {
      this.tableData.splice(index, 1); // 删除该行数据
      this.quantity = this.tableData.reduce(function (accumulator, current) {
        return accumulator + current["quantity"];
      }, 0); // 更新条码数量
            let userName = this.$loginInfo.account;
            this.isSubmitting = true; // 设置提交状态
      if (this.tableData.length <= 0) {
        this.formData = {};
      }
    },
            // 发送请求
            this.$post({
               url: "/MesOqcItemsDetect02/ItemBarCodeSubmit",
               data: {
                  itemBarCodeData: this.tableData,
                  CreateUser: userName
               }
            }).then(response => {
               if(response.status == 0){
                  // 请求成功后显示选择框
                  uni.showModal({
                     title: "操作成功",
                     content: "已经成功生成检验单",
                     showCancel: true,
                     cancelText: "继续扫码",
                     confirmText: "跳转到检验单",
                     success: (res) => {
                        if (res.confirm) {
                           // 用户点击了"跳转到检验单"
                           uni.navigateTo({
                              url: '/pages/QC/OQC/Add?id=' + response.data
                           });
                        } else if (res.cancel) {
                           // 用户点击了"继续扫码"
                           this.clearData();
                        }
                     }
                  });
               }else{
                  this.$showMessage(response.message);
               }
            }).catch(error => {
               // 请求失败时的处理
               this.$showMessage("请求失败,请稍后重试");
            }).finally(() => {
               // 无论成功还是失败都重置提交状态
               this.isSubmitting = false;
            });
         },
    handleSubmit() {
      console.log("handleSubmit方法被调用,isSubmitting:", this.isSubmitting);
      console.log("tableData长度:", this.tableData.length);
      console.log("quantity:", this.quantity);
      this.submit();
    },
         // 清空表格和表单数据
         clearData() {
            this.tableData = [];
            this.formData = {};
            this.quantity = 0;
            this.isSubmitting = false;
            this.isProcessing = false;
         }
    submit() {
      console.log("submit方法被调用");
      }
   }
      // 防止重复提交
      if (this.isSubmitting) {
        this.$showMessage("正在提交中,请勿重复操作");
        return;
      }
      // 校验用户登录状态
      if (!this.$loginInfo.account) {
        this.$showMessage("用户未登录,请重新登录");
        return;
      }
      // 校验条码数量是否有效
      if (this.quantity <= 0) {
        this.$showMessage("条码数量必须大于0");
        return;
      }
      // 校验是否有数据
      if (this.tableData.length === 0) {
        this.$showMessage("请扫描条码");
        return;
      }
      let userName = this.$loginInfo.account;
      this.isSubmitting = true; // 设置提交状态
      // 发送请求
      this.$post({
        url: "/MesOqcItemsDetect02/ItemBarCodeSubmit",
        data: {
          itemBarCodeData: this.tableData,
          CreateUser: userName
        }
      }).then(response => {
        if (response.status == 0) {
          // 请求成功后显示选择框
          uni.showModal({
            title: "操作成功",
            content: "已经成功生成检验单",
            showCancel: true,
            cancelText: "继续扫码",
            confirmText: "跳转到检验单",
            success: (res) => {
              if (res.confirm) {
                // 用户点击了"跳转到检验单"
                uni.navigateTo({
                  url: '/pages/QC/OQC/Add?id=' + response.data
                });
              } else if (res.cancel) {
                // 用户点击了"继续扫码"
                this.clearData();
              }
            }
          });
        } else {
          this.$showMessage(response.message);
        }
      }).catch(error => {
        // 请求失败时的处理
        this.$showMessage("请求失败,请稍后重试");
      }).finally(() => {
        // 无论成功还是失败都重置提交状态
        this.isSubmitting = false;
      });
    },
    // 清空表格和表单数据
    clearData() {
      this.tableData = [];
      this.formData = {};
      this.quantity = 0;
      this.isSubmitting = false;
      this.isProcessing = false;
    }
  }
}
</script>
<style>
   .container {
     padding: 24rpx;
     background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
     min-height: 100vh;
     display: flex;
     flex-direction: column;
   }
   /* 卡片通用样式 */
   .card {
     background: #ffffff;
     border-radius: 12rpx;
     box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
     margin-bottom: 24rpx;
     padding: 32rpx;
     border: 1rpx solid #e9ecef;
   }
   /* 表单区域 */
   .form-container {
     .form-grid {
       display: grid;
       grid-template-columns: repeat(2, 1fr);
       gap: 24rpx 16rpx;
     }
     .form-group {
       display: flex;
       flex-direction: column;
       gap: 16rpx;
       .form-label {
         font-size: 28rpx;
         color: #495057;
         font-weight: 600;
         padding-left: 4rpx;
         position: relative;
         &::after {
           content: "";
           position: absolute;
           left: 0;
           bottom: -4rpx;
           width: 24rpx;
           height: 3rpx;
           background: #007bff;
           border-radius: 2rpx;
         }
       }
       .form-input {
         height: 92rpx;
         padding: 0 24rpx;
         border: 2rpx solid #dee2e6;
         border-radius: 8rpx;
         font-size: 28rpx;
         color: #212529;
         background: #ffffff;
         transition: all 0.3s ease;
         &[disabled] {
           background: #f8f9fa;
           color: #6c757d;
           border-color: #e9ecef;
         }
         &:focus {
           border-color: #007bff;
           box-shadow: 0 0 0 4rpx rgba(0, 123, 255, 0.1);
           outline: none;
         }
         &::placeholder {
           color: #adb5bd;
         }
       }
     }
   }
   /* 表格优化 */
   .table-container {
     .table-header {
       margin-bottom: 24rpx;
       padding-bottom: 16rpx;
       border-bottom: 2rpx solid #e9ecef;
       display: flex;
       justify-content: space-between;
       align-items: center;
       .section-title {
         font-size: 32rpx;
         color: #212529;
         font-weight: 700;
         position: relative;
         padding-left: 24rpx;
         &::before {
           content: "";
           position: absolute;
           left: 0;
           top: 50%;
           transform: translateY(-50%);
           width: 4rpx;
           height: 28rpx;
           background: linear-gradient(135deg, #007bff, #0056b3);
           border-radius: 2rpx;
         }
       }
       .table-tip {
         .tip-text {
           font-size: 22rpx;
           color: #6c757d;
           background: #f8f9fa;
           padding: 8rpx 16rpx;
           border-radius: 16rpx;
           border: 1rpx solid #e9ecef;
         }
       }
     }
     .table-wrapper {
       position: relative;
       border-radius: 8rpx;
       overflow: hidden;
       border: 1rpx solid #dee2e6;
     }
     .table-scroll {
       width: calc(100% - 80rpx); /* 减去固定列宽度 */
       white-space: nowrap;
     }
     .custom-table {
       border: none;
       min-width: 780rpx;
       .table-header-row {
         background: linear-gradient(135deg, #f8f9fa, #e9ecef);
         .th {
           font-size: 26rpx;
           color: #495057;
           font-weight: 600;
           padding: 20rpx 12rpx;
           background: transparent !important;
           border-right: 1rpx solid #dee2e6;
           white-space: nowrap;
           min-width: 80rpx;
           &:last-child {
             border-right: none;
           }
         }
       }
       .table-row {
         transition: background-color 0.2s ease;
         &:nth-child(even) {
           background: #f8f9fa;
         }
         &:hover {
           background: #e3f2fd;
         }
         .uni-td {
           padding: 16rpx 12rpx;
           border-color: #dee2e6 !important;
           border-right: 1rpx solid #dee2e6;
           white-space: nowrap;
           min-width: 80rpx;
           &:last-child {
             border-right: none;
           }
           .cell-content {
             font-size: 24rpx;
             color: #495057;
             line-height: 1.4;
             max-width: 100%;
             overflow: hidden;
             text-overflow: ellipsis;
             &.quantity {
               font-weight: 600;
               color: #007bff;
               background: linear-gradient(135deg, #e3f2fd, #bbdefb);
               padding: 8rpx 16rpx;
               border-radius: 12rpx;
               display: inline-block;
               min-width: 60rpx;
               text-align: center;
             }
           }
           .description-text {
             font-size: 24rpx;
             color: #6c757d;
             font-weight: 500;
           }
         }
       }
     }
     /* 右固定悬浮删除列 */
     .fixed-delete-column {
       position: absolute;
       top: 0;
       right: 0;
       width: 80rpx;
       background: #ffffff;
       border-left: 1rpx solid #dee2e6;
       box-shadow: -4rpx 0 8rpx rgba(0, 0, 0, 0.05);
       z-index: 10;
       .fixed-header {
         height: 60rpx;
         background: linear-gradient(135deg, #f8f9fa, #e9ecef);
         display: flex;
         align-items: center;
         justify-content: center;
         border-bottom: 1rpx solid #dee2e6;
         .fixed-header-text {
           font-size: 26rpx;
           color: #495057;
           font-weight: 600;
         }
       }
       .fixed-content {
         .fixed-delete-item {
           height: 48rpx;
           display: flex;
           align-items: center;
           justify-content: center;
           border-bottom: 1rpx solid #dee2e6;
           transition: background-color 0.2s ease;
           &.even {
             background: #f8f9fa;
           }
           &:hover {
             background: #e3f2fd;
           }
           &:last-child {
             border-bottom: none;
           }
         }
       }
     }
   }
   /* 删除图标优化 */
   .delete-icon {
     cursor: pointer;
     color: #dc3545;
     transition: all 0.3s ease;
     padding: 12rpx;
     border-radius: 50%;
     display: flex;
     align-items: center;
     justify-content: center;
     min-width: 48rpx;
     min-height: 48rpx;
     &:hover {
       color: #c82333;
       background: rgba(220, 53, 69, 0.1);
       transform: scale(1.1);
     }
     &:active {
       transform: scale(0.95);
       background: rgba(220, 53, 69, 0.2);
     }
   }
   /* 按钮优化 */
   .action-buttons-container {
     display: flex;
     justify-content: center;
     margin-top: 48rpx;
     padding: 0 24rpx;
     .plus-button {
       width: 100%;
       max-width: 600rpx;
       height: 96rpx;
       background: linear-gradient(135deg, #007bff, #0056b3);
       border-radius: 48rpx;
       display: flex;
       justify-content: center;
       align-items: center;
       color: #ffffff;
       font-size: 32rpx;
       font-weight: 600;
       box-shadow: 0 8rpx 24rpx rgba(0, 123, 255, 0.3);
       transition: all 0.3s ease;
       border: none;
       position: relative;
       overflow: hidden;
       &::before {
         content: "";
         position: absolute;
         top: 0;
         left: -100%;
         width: 100%;
         height: 100%;
         background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
         transition: left 0.5s ease;
       }
       &:active {
         transform: scale(0.98);
         box-shadow: 0 4rpx 12rpx rgba(0, 123, 255, 0.4);
         &::before {
           left: 100%;
         }
       }
       &.submitting {
         background: linear-gradient(135deg, #6c757d, #5a6268);
         cursor: not-allowed;
         &::before {
           display: none;
         }
       }
     }
   }
   /* 数量显示优化 */
   .form-group {
     &:nth-child(5) .form-input {
       font-weight: 600;
       color: #007bff;
       background: linear-gradient(135deg, #e3f2fd, #bbdefb);
       border: 2rpx solid #007bff;
       text-align: center;
     }
   }
.container {
  padding: 24rpx;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
   /* 扫码输入框样式 */
   .input-with-scan {
     display: flex;
     align-items: center;
     gap: 16rpx;
     .scan-input {
       flex: 1;
     }
     .scan-button {
       display: flex;
       flex-direction: column;
       align-items: center;
       justify-content: center;
       padding: 16rpx 20rpx;
       background: linear-gradient(135deg, #e3f2fd, #bbdefb);
       border: 2rpx solid #007bff;
       border-radius: 8rpx;
       min-width: 120rpx;
       height: 92rpx;
       cursor: pointer;
       transition: all 0.3s ease;
       &:hover {
         background: linear-gradient(135deg, #bbdefb, #90caf9);
         transform: translateY(-2rpx);
         box-shadow: 0 4rpx 12rpx rgba(0, 123, 255, 0.2);
       }
       &:active {
         transform: translateY(0);
         box-shadow: 0 2rpx 6rpx rgba(0, 123, 255, 0.3);
       }
       .scan-text {
         font-size: 22rpx;
         color: #007bff;
         font-weight: 600;
         margin-top: 4rpx;
       }
     }
   }
/* 卡片通用样式 */
.card {
  background: #ffffff;
  border-radius: 12rpx;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  margin-bottom: 24rpx;
  padding: 32rpx;
  border: 1rpx solid #e9ecef;
}
/* 表单区域 */
.form-container {
  .form-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 24rpx;
  }
  .form-group {
    display: flex;
    flex-direction: column;
    gap: 16rpx;
    .form-label {
      font-size: 28rpx;
      color: #495057;
      font-weight: 600;
      padding-left: 4rpx;
      position: relative;
      &::after {
        content: "";
        position: absolute;
        left: 0;
        bottom: -4rpx;
        width: 24rpx;
        height: 3rpx;
        background: #007bff;
        border-radius: 2rpx;
      }
    }
    .form-input {
      height: 92rpx;
      padding: 0 24rpx;
      border: 2rpx solid #dee2e6;
      border-radius: 8rpx;
      font-size: 28rpx;
      color: #212529;
      background: #ffffff;
      transition: all 0.3s ease;
      &[disabled] {
        background: #f8f9fa;
        color: #6c757d;
        border-color: #e9ecef;
      }
      &:focus {
        border-color: #007bff;
        box-shadow: 0 0 0 4rpx rgba(0, 123, 255, 0.1);
        outline: none;
      }
      &::placeholder {
        color: #adb5bd;
      }
    }
  }
}
/* 表格优化 */
.table-container {
  .table-header {
    margin-bottom: 24rpx;
    padding-bottom: 16rpx;
    border-bottom: 2rpx solid #e9ecef;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .section-title {
      font-size: 32rpx;
      color: #212529;
      font-weight: 700;
      position: relative;
      padding-left: 24rpx;
      &::before {
        content: "";
        position: absolute;
        left: 0;
        top: 50%;
        transform: translateY(-50%);
        width: 4rpx;
        height: 28rpx;
        background: linear-gradient(135deg, #007bff, #0056b3);
        border-radius: 2rpx;
      }
    }
    .table-tip {
      .tip-text {
        font-size: 22rpx;
        color: #6c757d;
        background: #f8f9fa;
        padding: 8rpx 16rpx;
        border-radius: 16rpx;
        border: 1rpx solid #e9ecef;
      }
    }
  }
  .table-wrapper {
    position: relative;
    border-radius: 8rpx;
    overflow: hidden;
    border: 1rpx solid #dee2e6;
    display: flex;
  }
  .table-scroll {
    flex: 1;
    overflow-x: auto;
    white-space: nowrap;
  }
  .custom-table {
    border: none;
    min-width: 780rpx;
    .table-header-row {
      background: linear-gradient(135deg, #f8f9fa, #e9ecef);
      .th {
        font-size: 26rpx;
        color: #495057;
        font-weight: 600;
        padding: 0 8rpx;
        height: 68rpx;
        line-height: 68rpx;
        background: transparent !important;
        border-right: 1rpx solid #dee2e6;
        white-space: nowrap;
        min-width: 80rpx;
        &:last-child {
          border-right: none;
        }
      }
    }
    .table-row {
      transition: background-color 0.2s ease;
      &:nth-child(even) {
        background: #f8f9fa;
      }
      &:hover {
        background: #e3f2fd;
      }
      .uni-td {
        padding: 0 8rpx;
        height: 68rpx;
        border-color: #dee2e6 !important;
        border-right: 1rpx solid #dee2e6;
        white-space: nowrap;
        min-width: 80rpx;
        vertical-align: middle;
        &:last-child {
          border-right: none;
        }
        .cell-content {
          font-size: 24rpx;
          color: #495057;
          line-height: 68rpx;
          max-width: 100%;
          overflow: hidden;
          text-overflow: ellipsis;
          display: flex;
          align-items: center;
          height: 68rpx;
          &.quantity {
            font-weight: 600;
            color: #007bff;
            background: linear-gradient(135deg, #e3f2fd, #bbdefb);
            padding: 8rpx 16rpx;
            border-radius: 12rpx;
            display: inline-block;
            min-width: 60rpx;
            text-align: center;
          }
        }
        .description-text {
          font-size: 24rpx;
          color: #6c757d;
          font-weight: 500;
          line-height: 68rpx;
          display: flex;
          align-items: center;
          height: 68rpx;
        }
      }
    }
  }
  /* 右固定悬浮删除列 */
  .fixed-delete-column {
    flex-shrink: 0;
    width: 100rpx;
    background: #ffffff;
    border-left: 1rpx solid #dee2e6;
    box-shadow: -4rpx 0 8rpx rgba(0, 0, 0, 0.05);
    .fixed-header {
      height: 68rpx;
      background: linear-gradient(135deg, #f8f9fa, #e9ecef);
      display: flex;
      align-items: center;
      justify-content: center;
      border-bottom: 1rpx solid #dee2e6;
      .fixed-header-text {
        font-size: 26rpx;
        color: #495057;
        font-weight: 600;
      }
    }
    .fixed-content {
      .fixed-delete-item {
        height: 68rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        border-bottom: 1rpx solid #dee2e6;
        transition: background-color 0.2s ease;
        &.even {
          background: #f8f9fa;
        }
        &:hover {
          background: #e3f2fd;
        }
        &:last-child {
          border-bottom: none;
        }
      }
    }
  }
}
/* 删除图标优化 */
.delete-icon {
  cursor: pointer;
  color: #dc3545;
  transition: all 0.3s ease;
  padding: 12rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 48rpx;
  min-height: 48rpx;
  &:hover {
    color: #c82333;
    background: rgba(220, 53, 69, 0.1);
    transform: scale(1.1);
  }
  &:active {
    transform: scale(0.95);
    background: rgba(220, 53, 69, 0.2);
  }
}
/* 按钮优化 */
.action-buttons-container {
  display: flex;
  justify-content: center;
  margin-top: 48rpx;
  padding: 0 24rpx;
  .plus-button {
    width: 100%;
    max-width: 600rpx;
    height: 96rpx;
    background: linear-gradient(135deg, #007bff, #0056b3);
    border-radius: 12rpx;
    border: 2rpx solid #007bff;
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #ffffff;
    font-size: 32rpx;
    font-weight: 600;
    box-shadow: 0 8rpx 24rpx rgba(0, 123, 255, 0.3);
    transition: all 0.3s ease;
    position: relative;
    overflow: hidden;
    text-align: center;
    /* 确保按钮可点击 */
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
    user-select: none;
    text {
      color: #ffffff;
      font-size: 32rpx;
      font-weight: 600;
      line-height: 1;
    }
    &::before {
      content: "";
      position: absolute;
      top: 0;
      left: -100%;
      width: 100%;
      height: 100%;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
      transition: left 0.5s ease;
    }
    &:active {
      transform: scale(0.98);
      box-shadow: 0 4rpx 12rpx rgba(0, 123, 255, 0.4);
      &::before {
        left: 100%;
      }
    }
    &.submitting {
      background: linear-gradient(135deg, #6c757d, #5a6268);
      cursor: not-allowed;
      &::before {
        display: none;
      }
    }
    /* 悬停效果 */
    &:hover:not(.submitting) {
      background: linear-gradient(135deg, #0056b3, #004085);
      border-color: #0056b3;
      box-shadow: 0 12rpx 32rpx rgba(0, 123, 255, 0.4);
      transform: translateY(-2rpx);
    }
  }
}
/* 数量显示优化 */
.form-group {
  &:nth-child(5) .form-input {
    font-weight: 600;
    color: #007bff;
    background: linear-gradient(135deg, #e3f2fd, #bbdefb);
    border: 2rpx solid #007bff;
    text-align: center;
  }
}
/* 扫码输入框样式 */
.input-with-scan {
  display: flex;
  align-items: center;
  gap: 16rpx;
  .scan-input {
    flex: 1;
  }
  .scan-button {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 16rpx 20rpx;
    background: linear-gradient(135deg, #e3f2fd, #bbdefb);
    border: 2rpx solid #007bff;
    border-radius: 8rpx;
    min-width: 120rpx;
    height: 92rpx;
    cursor: pointer;
    transition: all 0.3s ease;
    &:hover {
      background: linear-gradient(135deg, #bbdefb, #90caf9);
      transform: translateY(-2rpx);
      box-shadow: 0 4rpx 12rpx rgba(0, 123, 255, 0.2);
    }
    &:active {
      transform: translateY(0);
      box-shadow: 0 2rpx 6rpx rgba(0, 123, 255, 0.3);
    }
    .scan-text {
      font-size: 22rpx;
      color: #007bff;
      font-weight: 600;
      margin-top: 4rpx;
    }
  }
}
/* 手机端响应式优化 */
@media (max-width: 768px) {
  .container {
    padding: 16rpx;
  }
  .card {
    padding: 24rpx;
    margin-bottom: 16rpx;
  }
  .form-container .form-grid {
    grid-template-columns: 1fr;
    gap: 20rpx;
  }
  .form-group .form-label {
    font-size: 26rpx;
  }
  .form-group .form-input {
    height: 84rpx;
    font-size: 26rpx;
    padding: 0 20rpx;
  }
  .scan-button {
    min-width: 100rpx !important;
    height: 84rpx !important;
    padding: 12rpx 16rpx !important;
    .scan-text {
      font-size: 20rpx !important;
    }
  }
  .table-scroll {
    flex: 1;
  }
  .fixed-delete-column {
    width: 80rpx;
    flex-shrink: 0;
    .fixed-header {
      height: 60rpx;
      .fixed-header-text {
        font-size: 22rpx;
      }
    }
    .fixed-content .fixed-delete-item {
      height: 60rpx;
    }
  }
  .custom-table {
    .th {
      font-size: 22rpx;
      padding: 0 6rpx;
      height: 60rpx;
      line-height: 60rpx;
    }
    .uni-td {
      padding: 0 6rpx;
      height: 60rpx;
      .cell-content {
        font-size: 22rpx;
        line-height: 60rpx;
        height: 60rpx;
      }
      .description-text {
        line-height: 60rpx;
        height: 60rpx;
      }
    }
  }
  .delete-icon {
    padding: 8rpx;
    min-width: 40rpx;
    min-height: 40rpx;
  }
  .plus-button {
    height: 88rpx;
    font-size: 30rpx;
    border-radius: 8rpx;
    text {
      font-size: 30rpx;
      color: #ffffff;
    }
    &.submitting text {
      color: #ffffff;
    }
  }
}
/* 强制按钮样式 - 解决手机端显示问题 */
.plus-button {
  background: #007bff !important;
  background: linear-gradient(135deg, #007bff, #0056b3) !important;
  border: 2rpx solid #007bff !important;
  border-radius: 12rpx !important;
  color: #ffffff !important;
  font-size: 32rpx !important;
  font-weight: 600 !important;
  box-shadow: 0 8rpx 24rpx rgba(0, 123, 255, 0.3) !important;
  width: 100% !important;
  max-width: 600rpx !important;
  height: 96rpx !important;
  display: flex !important;
  justify-content: center !important;
  align-items: center !important;
  text-align: center !important;
}
.plus-button text {
  color: #ffffff !important;
  font-size: 32rpx !important;
  font-weight: 600 !important;
}
.plus-button.submitting {
  background: #6c757d !important;
  background: linear-gradient(135deg, #6c757d, #5a6268) !important;
  border-color: #6c757d !important;
}
.plus-button.submitting text {
  color: #ffffff !important;
}
/* 手机端按钮强制样式 */
@media (max-width: 768px) {
  .plus-button {
    background: #007bff !important;
    background: linear-gradient(135deg, #007bff, #0056b3) !important;
    border: 2rpx solid #007bff !important;
    border-radius: 8rpx !important;
    height: 88rpx !important;
    font-size: 30rpx !important;
  }
  .plus-button text {
    color: #ffffff !important;
    font-size: 30rpx !important;
    font-weight: 600 !important;
  }
  .plus-button.submitting text {
    color: #ffffff !important;
    font-size: 30rpx !important;
  }
}
</style>