快乐的昕的电脑
2025-10-15 6e332109c3d179a29514d929dbe9f45d69db32d6
components/WorkOrderPrint.vue
@@ -1,20 +1,42 @@
<template>
   <view class="page">
      <!-- 顶部显示当前系统采集生产数,打码报工数和不良数 -->
   <view class="page wide-layout" :class="{'has-overlay': (isShowUserSelect || isShow || barcodeIsShow)}">
      <view class="status-section">
         <!-- 整体标题和刷新按钮 -->
         <view class="header-container">
            <view class="header-title">
               <text>生产数据统计</text>
            </view>
            <view class="header-right">
               <view class="version-info-top">
                  <text>v1.0.6</text>
               </view>
               <button class="refresh-btn" @click="refresh">刷新</button>
               <!-- 紧急重置按钮(仅在生成状态卡住时显示) -->
               <button v-if="isGeneratingBarcode" class="reset-btn" @click="resetGenerateState">重置</button>
            </view>
         <view class="report-table-wrapper">
            <view class="report-title">报工记录表</view>
            <div class="table-scroll">
               <table class="report-table">
                  <thead>
                     <tr>
                        <th>时间</th>
                        <th>报工人</th>
                        <th>工单号</th>
                        <th>产品名称</th>
                        <th>计划生产数</th>
                        <th>机台号</th>
                        <th>初始采集数</th>
                        <th>报工时采集数</th>
                        <th>报工数(计算)</th>
                        <th>不良数</th>
                        <th>良品数(计算)</th>
                     </tr>
                  </thead>
                  <tbody>
                     <tr>
                        <td>{{ nowTime }}</td>
                        <td>{{ staffDisplay || '-' }}</td>
                        <td>{{ orderNo || '-' }}</td>
                        <td>{{ order.daa003 || '-' }}</td>
                        <td>{{ planQtyDisplay }}</td>
                        <td>{{ machineNo || '-' }}</td>
                        <td>{{ initialValue }}</td>
                        <td>{{ productionCount }}</td>
                        <td>{{ calculatedTotalProduction }}</td>
                        <td>{{ calculatedDefectiveCount }}</td>
                        <td>{{ sQuantity }}</td>
                     </tr>
                  </tbody>
               </table>
            </div>
         </view>
         <view class="status-row">
@@ -26,10 +48,6 @@
               <text>当前采集数:</text>
               <input v-model="calculatedCurrentCount" class="highlight" disabled />
            </view>
            <!-- <view class="status-box">
                        <text>开工时工单已报工数:</text>
                        <input v-model="kgQty" class="highlight" disabled />
                     </view> -->
            <view class="operator-box">-</view>
            <view class="status-box standalone-box">
               <text>已打印条码数:</text>
@@ -44,245 +62,110 @@
               <text>已生产数:</text>
               <input v-model="calculatedTotalProduction" class="highlight" disabled />
            </view>
         </view>
         <view class="status-row">
            <view class="status-box">
               <text>手报不良数:</text>
               <input v-model="defectiveCount" class="highlight" disabled />
            </view>
            <view class="status-box">
               <text>未打印条码数:</text>
               <input v-model="bqty" class="highlight" disabled />
            <view class="btn-group">
               <button class="refresh-btn-inline" @click="refresh">刷新</button>
               <button v-if="isGeneratingBarcode" class="reset-btn-inline" @click="resetGenerateState">重置</button>
            </view>
         </view>
         <!-- 第一行 -->
         <!-- <view class="status-row">
            <view class="status-box result-box">
               <text>当前采集数:</text>
               <input v-model="calculatedCurrentCount" class="highlight" disabled />
            </view>
            <view class="operator-box">=</view>
            <view class="status-box">
               <text>机台面板数:</text>
               <input v-model="productionCount" class="highlight" disabled />
            </view>
            <view class="operator-box">-</view>
            <view class="status-box">
               <text>初始值:</text>
               <input v-model="initialValue" class="highlight" disabled />
            </view>
         </view> -->
         <!-- 第二行 -->
         <!-- <view class="status-row">
            <view class="status-box result-box">
               <text>已生产数:</text>
               <input v-model="calculatedTotalProduction" class="highlight" disabled />
            </view>
            <view class="operator-box">=</view>
            <view class="status-box">
               <text>开工时工单已报工数:</text>
               <input v-model="kgQty" class="highlight" disabled />
            </view>
            <view class="operator-box">+</view>
            <view class="status-box">
               <text>当前采集数:</text>
               <input v-model="calculatedCurrentCount" class="highlight" disabled />
            </view>
         </view> -->
         <!-- 第三行 -->
         <!-- <view class="status-row">
            <view class="status-box result-box">
               <text>不良数:</text>
               <input v-model="calculatedDefectiveCount" class="highlight" disabled />
            </view>
            <view class="operator-box">=</view>
            <view class="status-box">
               <text>已生产数:</text>
               <input v-model="calculatedTotalProduction" class="highlight" disabled />
            </view>
            <view class="operator-box">-</view>
            <view class="status-box">
               <text>良品数:</text>
               <input v-model="sQuantity" class="highlight" disabled />
            </view>
            <view class="status-box standalone-box">
               <text>已打印条码数:</text>
               <input v-model="sQuantity" class="highlight" disabled />
            </view>
         </view>   -->
         <view>
            <view style="display: flex; flex-direction: column; flex-wrap: nowrap; align-content: flex-start;">
               <view class="form-row">
                  <view class="form-item">
                     <label>产品编码:</label>
                     <input class="inp" type="text" v-model="order.daa002" disabled="true" />
         <view class="flex-row gap-lg">
            <view class="print-section flex-grow">
               <view class="barcode-info">
                  <view class="user-select">
                     <text>不良数量:</text>
                     <input v-model="customAmount" class="inp bad-input" placeholder="请输入数量" />
                  </view>
                  <view class="form-item">
                     <label>产品名称:</label>
                     <!-- <input class="inp" type="text" v-model="order.daa003" disabled="true" /> -->
                     <superwei-combox :candidates="DAA003List" v-model="order.daa003" @select="onDaa003Change"
                        class="inp"></superwei-combox>
                  </view>
                  <view class="form-item">
                     <label>产品规格:</label>
                     <input class="inp" type="text" v-model="order.daa004" disabled="true" />
                  <view class="user-select">
                     <button class="details-btn" @click="confirmCustomAmount">确认提交</button>
                  </view>
               </view>
               <view class="form-row">
                  <view class="form-item">
                     <label>图&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;号:</label>
                     <input class="inp" type="text" v-model="order.engineeringNo" disabled="true" />
            </view>
            <view class="current-user-section fill-width">
               <text>当前报工人:</text>
               <text class="current-user-name">{{ staffDisplay || '未选择' }}</text>
               <button class="select-user-btn" @click="isShowUserSelect = true">选人</button>
            </view>
         </view>
         <!-- 选人弹窗 -->
         <view v-if="isShowUserSelect" class="overlay">
            <view class="popup user-select-popup">
               <!-- 搜索栏 -->
               <view class="user-search-bar">
                  <input v-model.trim="userSearch"
                        type="text"
                        class="user-search-input"
                        placeholder="输入工号或姓名搜索"
                        @keydown.enter.prevent />
                  <button v-if="userSearch" class="user-search-clear" @click="userSearch=''">清空</button>
                  <view class="user-search-info">
                     匹配:{{ filteredUsers.length }} / {{ users.length }}
                  </view>
                  <view class="form-item">
                     <label>材&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;质:</label>
                     <input class="inp" type="text" v-model="order.material" disabled="true" />
               </view>
               <view class="user-list-scroll">
                  <template v-if="filteredUsers.length">
                     <view class="user-list-grid">
                        <button v-for="(u, index) in filteredUsers"
                              :key="index"
                              :class="['user-list-btn', {'selected': u===staffNo}]"
                              @click="selectUser(u)">
                           <span class="user-code">{{ u.split(':')[0] }}</span>
                           <span class="user-name">{{ u.split(':')[1] }}</span>
                        </button>
                     </view>
                  </template>
                  <view v-else class="no-user-result">
                     未找到匹配人员
                  </view>
                  <view class="form-item">
                     <label>颜&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;色:</label>
                     <input class="inp" type="text" v-model="order.colorName" disabled="true" />
                  </view>
               </view>
               <view class="user-popup-footer">
                  <button class="clean-btn wide-btn" @click="isShowUserSelect = false">关闭</button>
               </view>
            </view>
         </view>
         <!-- 条码打印部分 - 中部元素在一条线上 -->
         <view class="print-section">
            <view class="barcode-info">
               <view class="user-select">
                  <text style="display: inline-block;float:left;margin-left: -11px;">打印条码张数:</text>
                  <input v-model="icount" class="inp"
                     style="width: 20%; height: 70px; border: 3px solid #808080; font-size: 40px; text-align: center; margin-top: 5px;" />
               </view>
               <text style="margin-left:-280px;">每张条码数量:</text>
               <input class="inp"
                  style="width: 19%; height: 70px; border: 3px solid #808080; font-size: 40px; text-align: center; margin-top: 5px; margin-left: -38px;"
                  v-model="barcodeAmount" placeholder="条码数量(装箱数)" />
               <view class="user-select">
                  <button class="print-btn" @click="showPrint" :disabled="isGeneratingBarcode || printLoading"
                     :style="(isGeneratingBarcode || printLoading) ? 'background-color: #ccc; cursor: not-allowed;' : ''">
                     {{ isGeneratingBarcode ? '生成中...' : (printLoading ? '打印中...' : '打印条码') }}
                  </button>
                  <button class="details-btn" @click="showBarcode">条码明细</button>
               </view>
            </view>
         </view>
         <!-- 自定义数量输入行 -->
         <view class="print-section" style="margin-top: 20px;">
            <view class="barcode-info">
               <view class="user-select">
                  <text style="display: inline-block;float:left;margin-left: -11px;">不良数量:</text>
                  <input v-model="customAmount" class="inp"
                     style="width: 55%; height: 70px; border: 3px solid #808080; font-size: 40px; text-align: center; margin-top: 5px;"
                     placeholder="请输入数量" />
               </view>
               <view class="user-select" style="margin-left: 30px;">
                  <button class="details-btn" @click="confirmCustomAmount">确认提交</button>
               </view>
            </view>
         </view>
         <!-- 不良原因选择 -->
         <view>
            <view class="reason-section" style="margin-bottom: -16px">
               <text>点选不良备注(绑定到工单):</text>
               <view class="reason-buttons" style="font-size: 23px;">
                  <button v-for="(reason, index) in badReasons" :key="index"
                     :class="{'reason-btn': true, 'selected': selectedReasons.includes(reason)}"
                     @click="toggleReason(reason)" v-text="reason"></button>
               </view>
            </view>
         </view>
         <!-- 底部保存和取消按钮 -->
         <view class="bottom-section">
            <button class="save-btn" @click="save">保存并生效</button>
            <button class="cancel-btn" @click="cancel">取消</button>
         </view>
         <!-- 保留旧弹窗 -->
         <view v-if="isShow" class="overlay">
            <view class="popup">
               <view class="barcode-info">
                  <!-- <view class="user-select">
                     <text>已打印条码数:</text>
                     <input v-model="sQuantity" class="highlight" disabled />
                  </view>
                  <view class="user-select">
                     <text>未打印条码数:</text>
                     <input v-model="bqty" class="highlight" disabled />
                  </view> -->
                  <view class="user-select1">
                     <text style="float: left; display: inline-block;">打印条码张数:</text>
                     <input v-model="icount" class="inp5" disabled="true" />
                  </view>
                  <view class="user-select2">
                     <text style="float: left;">每张条码数量:</text>
                     <input class="inp6" disabled="true" v-model="barcodeAmount" placeholder="条码数量(装箱数)" />
                  </view>
                  <view class="form-row">
                     <!--<kk-printer defaultText="打印条码" class="print-btn" ref="kkprinter" :user="staffNo"
                        :bufferData="bufferData" @onPrint="onPrint" @onPrintSuccess="onPrintSuccess"
                        @onPrintFail="onPrintFail">
                     </kk-printer>-->
                  </view>
               </view>
               <view class="bottom-section1">
                  <!-- <button class="clean-btn" type="primary" @click="cleanUser">关闭</button> -->
                  <button class="clean-btn" type="warn" @click="deleteBarcode">取消打印</button>
                  <button class="print-btn"
                     style="width: 48%; padding: 1.5vh; color: white; font-size: 1.5vw; border: none; text-align: center; cursor: pointer; border-radius: 0.5vw;"
                     @click="printTest" :loading="printLoading" :disabled="printLoading || isGeneratingBarcode"
                     :style="(printLoading || isGeneratingBarcode) ? 'background-color: #ccc; cursor: not-allowed;' : ''">
                     {{ isGeneratingBarcode ? '生成中...' : (printLoading ? '打印中...' : '打印条码') }}
                  </button>
                  <button class="clean-btn" type="warn" @click="deleteBarcode">关闭</button>
               </view>
               <view class="reason-section">
                  <text>报工人:</text>
                  <view class="reason-buttons">
                     <button v-for="(reason, index) in users" :key="index"
                        :class="{'reason-btn': true, 'selected': user === reason}" @click="toggleUser(reason)"
                        v-text="reason"></button>
                     <button v-for="(u,index) in users" :key="index"
                           :class="{'reason-btn':true,'selected': user===u}"
                           @click="toggleUser(u)">
                        {{ formatUser(u) }}
                     </button>
                  </view>
               </view>
            </view>
         </view>
         <!-- 展示条码明细 -->
         <view v-if="barcodeIsShow" class="overlay">
            <view class="popup">
               <!-- <view class="barcode-info"> -->
               <uni-table ref="table" border stripe emptyText="暂无更多数据" class="table1">
                  <uni-tr>
                     <uni-th align="center" style="font-size: 40px;">生成时间</uni-th>
                     <uni-th align="center" style="width:39%;font-size: 40px;">条码</uni-th>
                     <uni-th align="center" style="font-size: 40px;">报工人</uni-th>
                     <uni-th align="center" style="font-size: 40px;">报工数量</uni-th>
                     <uni-th align="center" style="font-size:40px;">生成时间</uni-th>
                     <uni-th align="center" style="width:39%;font-size:40px;">条码</uni-th>
                     <uni-th align="center" style="font-size:40px;">报工人</uni-th>
                     <uni-th align="center" style="font-size:40px;">报工数量</uni-th>
                  </uni-tr>
                  <uni-tr v-for="(item, index) in reportingList" :key="index">
                     <uni-td align="center">
                        <input type="text" v-model="item.bgDate" style="width: 26vh;" />
                     </uni-td>
                     <uni-td align="center">
                        <input v-model="item.itemNoCade" style="width: 40vh;" />
                     </uni-td>
                     <uni-td align="center">
                        <input v-model="item.staffName" />
                     </uni-td>
                     <uni-td align="center">
                        <input v-model="item.okQty" />
                     </uni-td>
                  <uni-tr v-for="(item,index) in reportingList" :key="index">
                     <uni-td align="center"><input type="text" v-model="item.bgDate" style="width:26vh;" /></uni-td>
                     <uni-td align="center"><input v-model="item.itemNoCade" style="width:40vh;" /></uni-td>
                     <uni-td align="center"><input v-model="item.staffName" /></uni-td>
                     <uni-td align="center"><input v-model="item.okQty" /></uni-td>
                  </uni-tr>
               </uni-table>
               <!-- </view> -->
               <view>
                  <button class="clean-btn" type="warn" @click="barcodeIsShow = false">关闭</button>
               </view>
               <view><button class="clean-btn" type="warn" @click="barcodeIsShow=false">关闭</button></view>
            </view>
         </view>
      </view>
@@ -290,1162 +173,280 @@
</template>
<script>
   import {
      printTemplate3
   } from "../utils/printTemplate";
   import { printTemplate3 } from "../utils/printTemplate";
   export default {
      props: {
         orderNo: String,
         orderId: Number,
         machineNo: String
      },
      props: { orderNo: String, orderId: Number, machineNo: String },
      data() {
         return {
            currentUser: '', // 默认当前用户
            barcodeAmount: '', // 输入的条码数量
            users: [], // 用户列表
            userForm: [],
            staff: [],
            user: {},
            badReasons: [], // 不良原因
            itemsNgname: [],
            selectedReasons: [], // 存储选中的不良原因
            productionCount: 0, // 当前系统采集生产数
            printedCount: 0, // 当前已打码报工数
            defectiveCount: 0, // 不良数
            order: {},
            icount: 1, // 默认为1,避免为0或null
            bqty: 0,
            sQuantity: 0,
            kgQty: 0,
            initialValue: 0,
            qqty: 0,
            ngStaid: 0,
            bufferData: '',
            dataToPrint: [],
            isLoading: false, // 新的加载状态
            but: false,
            DAA003List: [],
            lineList: [],
            isShow: false, // 控制打印条码按钮的显示
            barcodeIsShow: false,
            barcodeList: [],
            staffNo: '',
            printStr: '',
            printMac: '',
            bluetoothSocket: {}, // 蓝牙连接
            device: '',
            uuid: '',
            printNum: 1,
            reportingList: [],
            printLoading: false,
            customAmount: '',
            // 新增防重复请求相关变量
            isGeneratingBarcode: false, // 是否正在生成条码
            lastGenerateTime: 0, // 上次生成条码的时间戳
            generateRequestId: null // 当前生成请求的唯一ID
         };
      },
      computed: {
         // 计算当前采集数,确保不会出现NaN或undefined
         calculatedCurrentCount() {
            const production = this.productionCount || 0;
            const initial = this.initialValue || 0;
            return production - initial;
         },
         // 计算已生产总数
         calculatedTotalProduction() {
            const kgQty = this.kgQty || 0;
            const currentCount = this.calculatedCurrentCount;
            // 当开工时工单已报工数为0时,直接使用当前采集数的值
            //return kgQty === 0 ? currentCount : kgQty + currentCount;
            return kgQty + currentCount
         },
         // 计算不良数
         calculatedDefectiveCount() {
            const totalProduction = this.calculatedTotalProduction;
            // const totalProduction = this.productionCount;
            const goodCount = this.sQuantity || 0;
            return totalProduction - goodCount;
            isShowUserSelect: false,
            currentUser: '',
            barcodeAmount: '',
            users: [], userForm: [], staff: [], user: {},
            productionCount: 0, printedCount: 0, defectiveCount: 0, order: {},
            icount: 1, bqty: 0, sQuantity: 0, kgQty: 0, initialValue: 0, qqty: 0,
            ngStaid: 0, bufferData: '', dataToPrint: [], isLoading: false, but: false,
            DAA003List: [], lineList: [], isShow: false, barcodeIsShow: false, barcodeList: [],
            staffNo: '', printStr: '', printMac: '', bluetoothSocket: {}, device: '', uuid: '',
            printNum: 1, reportingList: [], printLoading: false, customAmount: '',
            isGeneratingBarcode: false, lastGenerateTime: 0, generateRequestId: null,
            nowTimeTimer: null, nowTime: '',
            // 新增:搜索关键字
            userSearch: ''
         }
      },
      components: {},
      mounted() {
         // this.fetchData(false); // Initial fetch
         // this.timer = setInterval(this.fetchData, 180000); // Call fetchData every 5 minutes
      computed: {
         calculatedCurrentCount() { return (this.productionCount || 0) - (this.initialValue || 0); },
         calculatedTotalProduction() { return (this.kgQty || 0) + this.calculatedCurrentCount; },
         calculatedDefectiveCount() { return this.calculatedTotalProduction - (this.sQuantity || 0); },
         planQtyDisplay() { return this.order.planQty || this.order.planQuantity || this.order.daa007 || this.order.daa010 || 0; },
         staffDisplay() {
            if (!this.staffNo) return '';
            const segs = this.staffNo.split(':');
            return segs.length > 1 ? `${segs[0]} ${segs[1]}` : this.staffNo;
         },
         // 新增:过滤后的用户列表
         filteredUsers() {
            if (!this.userSearch) return this.users;
            const kw = this.userSearch.trim().toLowerCase();
            return this.users.filter(u => u.toLowerCase().includes(kw));
         }
      },
      created() {
         // 初始化数据,确保所有数值型变量有默认值
         this.initializeData();
         this.fetchData(true);
         this.init();
         this.getXS0101();
         this.updateNowTime();
         this.nowTimeTimer = setInterval(this.updateNowTime, 60000);
      },
      beforeDestroy() { if (this.nowTimeTimer) clearInterval(this.nowTimeTimer); },
      methods: {
         // 初始化所有数值型变量,避免null或undefined
         initializeData() {
            this.productionCount = 0;
            this.printedCount = 0;
            this.defectiveCount = 0;
            this.icount = 1;
            this.bqty = 0;
            this.sQuantity = 0;
            this.kgQty = 0;
            this.initialValue = 0;
            this.qqty = 0;
            // 初始化防重复状态
            this.isGeneratingBarcode = false;
            this.lastGenerateTime = 0;
            this.generateRequestId = null;
         formatUser(u) {
            if (!u) return '';
            const segs = u.split(':');
            return segs.length > 1 ? `${segs[0]} ${segs[1]}` : u;
         },
         // 手动重置防重复状态(紧急情况下使用)
         selectUser(u) { this.staffNo = u; this.isShowUserSelect = false; this.userSearch = ''; },
         updateNowTime() {
            const d = new Date(), p = n => n.toString().padStart(2, '0');
            this.nowTime = `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
         },
         initializeData() {
            this.productionCount = this.printedCount = this.defectiveCount = 0;
            this.icount = 1; this.bqty = 0; this.sQuantity = 0; this.kgQty = 0;
            this.initialValue = 0; this.qqty = 0;
            this.isGeneratingBarcode = false; this.lastGenerateTime = 0; this.generateRequestId = null;
         },
         resetGenerateState() {
            this.isGeneratingBarcode = false;
            this.generateRequestId = null;
            this.lastGenerateTime = 0;
            console.log("已手动重置条码生成状态");
            this.isGeneratingBarcode = false; this.generateRequestId = null; this.lastGenerateTime = 0;
            this.$showMessage("已重置条码生成状态");
         },
         refresh() {
            this.$sendPostRequest({
               url: "http://192.168.0.94:9095/Numerical/RefreshDev",
               data: {
                  machineNo: this.order.machineNo
               },
               data: { machineNo: this.order.machineNo },
               contentType: "application/json"
            }).then(res1 => {
               if (res1.code == 200) {
                  this.fetchData(true); // 重新请求数据
               } else {
                  this.$showMessage("同步失败");
               }
            });
            }).then(r => { r.code == 200 ? this.fetchData(true) : this.$showMessage("同步失败"); });
         },
         printTest() {
            if (!this.staffNo) {
               this.$showMessage("请选择报工人");
               return;
            }
            try {
               // 在调用onPrint前清空数据
               // 这样可以确保每次打印都是从零开始
               this.dataToPrint = [];
               this.bufferData = '';
               this.onPrint();
               this.$showMessage('正在打印,请稍等!');
               this.printLoading = true;
               this.printNum = 1;
               setTimeout(() => {
                  this.doPrint();
                  this.printLoading = false;
                  console.log("调用打印");
               }, 2000);
            } catch (e) {
               this.onPrintFail();
               console.log(e);
            }
         },
         doPrint() { //printNum:打印次数
            var mac_address = uni.getStorageSync('printMac');
            console.log("打印机地址" + mac_address);
            console.log('打印开始');
            console.log("打印参数" + this.bufferData);
            if (!mac_address) {
               this.$showMessage('请选择蓝牙打印机');
               this.printLoading = false;
               return false;
            }
            // 检查Android版本并使用对应的打印方法
            // const androidVersion = this.getAndroidVersion();
            // console.log('Android版本:', androidVersion);
            // if (androidVersion >= 12) {
            //    return this.doPrintForAndroid12Plus(mac_address);
            // } else {
               return this.doPrintForAndroidLegacy(mac_address);
            // }
         },
         // Android 12+ 版本的蓝牙打印方法
         doPrintForAndroid12Plus(mac_address) {
            try {
               console.log('使用Android 12+兼容的蓝牙打印方法');
               // 检查蓝牙权限
               if (!this.checkBluetoothPermissions()) {
                  this.$showMessage('蓝牙权限不足,请检查应用权限设置');
                  this.printLoading = false;
                  return false;
               }
               var main = plus.android.runtimeMainActivity();
               var BluetoothManager = plus.android.importClass("android.bluetooth.BluetoothManager");
               var Context = plus.android.importClass("android.content.Context");
               // 获取BluetoothManager
               var bluetoothManager = main.getSystemService(Context.BLUETOOTH_SERVICE);
               var bluetoothAdapter = bluetoothManager.getAdapter();
               if (!bluetoothAdapter) {
                  this.$showMessage('设备不支持蓝牙');
                  this.printLoading = false;
                  return false;
               }
               if (!bluetoothAdapter.isEnabled()) {
                  this.$showMessage('请先开启蓝牙');
                  this.printLoading = false;
                  return false;
               }
               // 获取配对设备
               var pairedDevices = bluetoothAdapter.getBondedDevices();
               var targetDevice = null;
               // 查找目标设备
               var iterator = pairedDevices.iterator();
               while (iterator.hasNext()) {
                  var device = iterator.next();
                  if (device.getAddress().equals(mac_address)) {
                     targetDevice = device;
                     break;
                  }
               }
               if (!targetDevice) {
                  this.$showMessage('未找到配对的打印机设备');
                  this.printLoading = false;
                  return false;
               }
               // 创建蓝牙连接
               var UUID = plus.android.importClass("java.util.UUID");
               var uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
               var bluetoothSocket = targetDevice.createRfcommSocketToServiceRecord(uuid);
               // 连接设备
               try {
                  bluetoothSocket.connect();
                  console.log('蓝牙连接成功');
                  // 发送打印数据
                  var outputStream = bluetoothSocket.getOutputStream();
                  var bytes = plus.android.invoke(this.bufferData, 'getBytes', 'gbk');
                  outputStream.write(bytes);
                  outputStream.flush();
                  // 关闭连接
                  outputStream.close();
                  bluetoothSocket.close();
                  console.log("打印成功");
                  this.cleanUser();
                  this.onPrintSuccess();
                  return true;
               } catch (connectError) {
                  console.error('蓝牙连接失败:', connectError);
                  // 尝试fallback方法
                  try {
                     bluetoothSocket.close();
                     // 使用反射获取hidden方法
                     var createRfcommSocket = targetDevice.getClass().getMethod("createRfcommSocket",
                        plus.android.importClass("java.lang.Integer").TYPE);
                     bluetoothSocket = createRfcommSocket.invoke(targetDevice, 1);
                     bluetoothSocket.connect();
                     console.log('使用fallback方法连接成功');
                     var outputStream = bluetoothSocket.getOutputStream();
                     var bytes = plus.android.invoke(this.bufferData, 'getBytes', 'gbk');
                     outputStream.write(bytes);
                     outputStream.flush();
                     outputStream.close();
                     bluetoothSocket.close();
                     this.cleanUser();
                     this.onPrintSuccess();
                     return true;
                  } catch (fallbackError) {
                     console.error('Fallback方法也失败:', fallbackError);
                     this.$showMessage('蓝牙连接失败,请检查打印机状态');
                     this.printLoading = false;
                     return false;
                  }
               }
            } catch (error) {
               console.error('Android 12+ 蓝牙打印错误:', error);
               this.$showMessage('打印失败: ' + error.message);
               this.printLoading = false;
               return false;
            }
         },
         // Android 11及以下版本的蓝牙打印方法(保持原有逻辑)
         doPrintForAndroidLegacy(mac_address) {
            try {
               console.log('使用传统蓝牙打印方法');
               var device = null,
                  BAdapter = null,
                  BluetoothAdapter = null,
                  uuid = null,
                  main = null,
                  bluetoothSocket = null;
               main = plus.android.runtimeMainActivity();
               BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
               let UUID = plus.android.importClass("java.util.UUID");
               uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
               BAdapter = BluetoothAdapter.getDefaultAdapter();
               if (!BAdapter) {
                  this.$showMessage('设备不支持蓝牙');
                  this.printLoading = false;
                  return false;
               }
               device = BAdapter.getRemoteDevice(mac_address);
               plus.android.importClass(device);
               bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid);
               plus.android.importClass(bluetoothSocket);
               if (!bluetoothSocket.isConnected()) {
                  console.log('检测到设备未连接,尝试连接....');
                  bluetoothSocket.connect();
               }
               console.log('设备已连接');
               if (bluetoothSocket.isConnected()) {
                  var outputStream = bluetoothSocket.getOutputStream();
                  plus.android.importClass(outputStream);
                  var bytes = plus.android.invoke(this.bufferData, 'getBytes', 'gbk');
                  outputStream.write(bytes);
                  outputStream.flush();
                  device = null //这里关键
                  bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误
                  console.log("打印机连接状态:111");
                  this.cleanUser();
                  this.onPrintSuccess();
                  return true;
               } else {
                  console.log("打印机连接状态:222");
                  this.printLoading = false;
                  return false;
               }
            } catch (error) {
               console.error('传统蓝牙打印错误:', error);
               this.$showMessage('打印失败: ' + error.message);
               this.printLoading = false;
               return false;
            }
         },
         // 获取Android版本号
         getAndroidVersion() {
            try {
               var Build = plus.android.importClass("android.os.Build");
               return Build.VERSION.SDK_INT;
            } catch (error) {
               console.error('获取Android版本失败:', error);
               return 30; // 默认返回Android 11的API Level
            }
         },
         // 检查蓝牙权限(Android 12+需要)
         checkBluetoothPermissions() {
            try {
               const androidVersion = this.getAndroidVersion();
               // Android 12以下版本不需要新权限
               if (androidVersion < 31) { // Android 12 = API 31
                  return true;
               }
               var main = plus.android.runtimeMainActivity();
               var PackageManager = plus.android.importClass("android.content.pm.PackageManager");
               var ContextCompat = plus.android.importClass("androidx.core.content.ContextCompat");
               // Android 12+ 需要的权限
               var permissions = [
                  "android.permission.BLUETOOTH_CONNECT",
                  "android.permission.BLUETOOTH_SCAN"
               ];
               var missingPermissions = [];
               for (var i = 0; i < permissions.length; i++) {
                  var permission = permissions[i];
                  var granted = ContextCompat.checkSelfPermission(main, permission);
                  if (granted !== PackageManager.PERMISSION_GRANTED) {
                     console.log('权限未授予:', permission);
                     missingPermissions.push(permission);
                  }
               }
               if (missingPermissions.length > 0) {
                  // 尝试请求权限
                  this.requestBluetoothPermissions(missingPermissions);
                  return false;
               }
               return true;
            } catch (error) {
               console.error('权限检查失败:', error);
               // 如果检查失败,假设权限已授予(可能是老版本Android)
               return true;
            }
         },
         // 请求蓝牙权限
         requestBluetoothPermissions(permissions) {
            try {
               var main = plus.android.runtimeMainActivity();
               var ActivityCompat = plus.android.importClass("androidx.core.app.ActivityCompat");
               console.log('请求蓝牙权限:', permissions);
               // 将JavaScript数组转换为Java数组
               var javaPermissions = plus.android.newObject("java.lang.String", permissions.length);
               for (var i = 0; i < permissions.length; i++) {
                  javaPermissions[i] = permissions[i];
               }
               // 请求权限
               ActivityCompat.requestPermissions(main, javaPermissions, 1001);
               // 显示提示信息
               this.$showMessage('正在请求蓝牙权限,请在系统弹窗中允许权限后重试');
            } catch (error) {
               console.error('请求权限失败:', error);
               this.$showMessage('无法请求蓝牙权限,请手动在设置中开启应用的蓝牙权限');
            }
         },
         init() {
            console.log("设置蓝牙");
            try {
               // 检查Android版本并使用对应的初始化方法
               const androidVersion = this.getAndroidVersion();
               if (androidVersion >= 12) {
                  this.initForAndroid12Plus();
               } else {
                  this.initForAndroidLegacy();
               }
            } catch (err) {
               console.error("蓝牙初始化异常!", err);
            }
         },
         // Android 12+ 版本的蓝牙初始化
         initForAndroid12Plus() {
            try {
               console.log("使用Android 12+兼容的蓝牙初始化");
               var main = plus.android.runtimeMainActivity();
               var BluetoothManager = plus.android.importClass("android.bluetooth.BluetoothManager");
               var Context = plus.android.importClass("android.content.Context");
               var UUID = plus.android.importClass("java.util.UUID");
               this.uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
               // 获取BluetoothManager和Adapter
               var bluetoothManager = main.getSystemService(Context.BLUETOOTH_SERVICE);
               var bluetoothAdapter = bluetoothManager.getAdapter();
               if (bluetoothAdapter && bluetoothAdapter.isDiscovering()) {
                  bluetoothAdapter.cancelDiscovery(); // 停止扫描
               }
               let printMac1 = uni.getStorageSync('printMac');
               this.printMac = printMac1;
               console.log("打印机地址" + this.printMac);
               var address_mac = this.printMac ? this.printMac : "DC:1D:30:91:06:52";
               console.log("status:" + address_mac);
               if (bluetoothAdapter) {
                  this.device = bluetoothAdapter.getRemoteDevice(address_mac);
                  plus.android.importClass(this.device);
                  console.log("Android 12+ 蓝牙初始化成功");
               }
            } catch (err) {
               console.error("Android 12+ 蓝牙初始化失败:", err);
               // 如果失败,尝试使用传统方法
               this.initForAndroidLegacy();
            }
         },
         // Android 11及以下版本的蓝牙初始化(保持原有逻辑)
         initForAndroidLegacy() {
            try {
               console.log("使用传统蓝牙初始化方法");
               var main = plus.android.runtimeMainActivity();
               var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
               var UUID = plus.android.importClass("java.util.UUID");
               this.uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
               var BAdapter = BluetoothAdapter.getDefaultAdapter();
               if (BAdapter) {
                  BAdapter.cancelDiscovery(); // 停止扫描
               }
               let printMac1 = uni.getStorageSync('printMac');
               this.printMac = printMac1;
               console.log("打印机地址" + this.printMac);
               var address_mac = this.printMac ? this.printMac : "DC:1D:30:91:06:52";
               console.log("status:" + address_mac);
               if (BAdapter) {
                  this.device = BAdapter.getRemoteDevice(address_mac);
                  plus.android.importClass(this.device);
                  this.bluetoothSocket = this.device.createInsecureRfcommSocketToServiceRecord(this.uuid);
                  plus.android.importClass(this.bluetoothSocket);
                  console.log("传统蓝牙初始化成功");
               }
            } catch (err) {
               console.error("传统蓝牙初始化失败:", err);
            }
         },
         onDaa003Change(event) {
            let orde = this.lineList[this.DAA003List.indexOf(event)];
            this.orderId = orde.id;
            this.orderNo = orde.daa001;
            //切换为新的id
         onDaa003Change(v) {
            let o = this.lineList[this.DAA003List.indexOf(v)];
            this.orderId = o.id; this.orderNo = o.daa001;
            uni.setStorageSync('machine', this.machineNo);
            uni.setStorageSync('orderId', this.orderId);
            uni.setStorageSync('orderNo', this.orderNo);
            uni.setStorageSync('engineeringNo', this.order.engineeringNo);
            this.fetchData(false);
         },
         fetchData(flag) {
            // let machine = uni.getStorageSync('machine');
            // let orderId = uni.getStorageSync('orderId');
            // let orderNo = uni.getStorageSync('orderNo');
            // if (orderId) {
            //    this.orderId = orderId;
            // } else {
            //    if (!this.orderId) {
            //       this.orderId = uni.getStorageSync('id');
            //    }
            // }
            // if (orderNo) {
            //    this.orderNo = orderNo;
            // } else {
            //    if (!this.orderNo) {
            //       this.orderNo = uni.getStorageSync('daa001');
            //    }
            // }
            // if (machine) {
            //    this.machineNo = machine;
            // } else {
            //    if (!this.machineNo) {
            //       this.machineNo = uni.getStorageSync('machineNo');
            //    }
            // }
            if (!this.orderId && !this.orderNo) {
               return;
            }
            if (!this.orderId && !this.orderNo) return;
            this.getOrderById();
            this.getMesItemsNgname();
            this.getWomdaaPrintById();
            this.findByOrderId();
            if (flag) {
               this.$post({
                  url: "/Womdaa/GetWomdaasByShow",
                  data: {
                     machineNo: this.machineNo
                  }
               }).then(res => {
                  this.lineList = res.data.tbBillList;
                  this.DAA003List = res.data.tbBillList.map(item => item.daa003);
               })
            }
         },
         formatDate(date) {
            if (!date) return '';
            try {
               let year = date.getFullYear(); // 获取年份
               let month = String(date.getMonth() + 1).padStart(2, '0'); // 获取月份并补零
               let day = String(date.getDate()).padStart(2, '0'); // 获取日期并补零
               return `${year}-${month}-${day}`; // 返回格式化后的字符串
            } catch (error) {
               console.error("日期格式化错误:", error);
               return '';
            }
         },
         // 切换选中的不良原因
         toggleReason(reason) {
            if (!reason) return;
            if (this.selectedReasons.includes(reason)) {
               this.selectedReasons = this.selectedReasons.filter(r => r !== reason);
            } else {
               this.selectedReasons.push(reason);
            }
         },
         toggleUser(user) {
            if (!user) return;
            this.user = this.user === user ? null : user;
            this.staffNo = user;
         },
         showPrint() {
            // 防重复点击检查 - 生成中或打印中都不允许
            if (this.isGeneratingBarcode) {
               this.$showMessage('正在生成条码,请稍等...');
               return;
            }
            if (this.printLoading) {
               this.$showMessage('正在打印条码,请稍等...');
               return;
            }
            // 防抖检查:2秒内不允许重复操作
            const currentTime = Date.now();
            if (currentTime - this.lastGenerateTime < 2000) {
               this.$showMessage('操作过于频繁,请稍等再试');
               return;
            }
            if (this.icount > 6) {
               this.$showMessage('条码数量不能超过6张');
               return;
            }
            this.isShow = true;
            //this.printBarcode();
            this.getXS0101();
            this.user = "";
            this.staffNo = null;
         },
         showBarcode() {
            this.$post({
               url: "/MesStaff/GetMesReportingList",
               data: {
                  orderNo: this.orderNo,
               }
            }).then(res => {
               this.reportingList = res.data.tbBillList;
               this.barcodeIsShow = true;
            });
         },
         // 打印条码报工
         printBarcode() {
            // 防重复请求检查
            if (this.isGeneratingBarcode) {
               this.$showMessage('正在生成条码,请稍等...');
               return;
            }
            if (!this.barcodeAmount) {
               this.isShow = false;
               this.$showMessage('请输入条码数量');
               return;
            }
            if (this.bqty == 0) {
               this.isShow = false;
               this.$showMessage('可打印数量为0');
               return;
            }
            if (this.bqty < this.barcodeAmount) {
               this.isShow = false;
               this.$showMessage('打印数量不能大于可打印数量');
               return;
            }
            if (this.icount * this.barcodeAmount > this.bqty) {
               this.isShow = false;
               this.$showMessage('打印总数超过可打印总数');
               return;
            }
            // 设置生成状态锁定
            this.isGeneratingBarcode = true;
            this.lastGenerateTime = Date.now();
            // 生成唯一请求ID,用于防重
            this.generateRequestId = `${this.orderNo}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
            console.log('开始生成条码,请求ID:', this.generateRequestId);
            // 添加超时机制:15秒后自动释放锁定
            const timeoutId = setTimeout(() => {
               if (this.isGeneratingBarcode) {
                  console.log('条码生成超时,释放锁定');
                  this.isGeneratingBarcode = false;
                  this.$showMessage('生成条码超时,请重试');
               }
            }, 15000);
            this.$post({
               url: "/MesInvItemBarcodes/AddItemToBarcodes",
               data: {
                  printQty: this.barcodeAmount,
                  orderNo: this.orderNo,
                  orderId: this.orderId,
                  user: this.user,
                  count: this.icount,
                  requestId: this.generateRequestId // 传递请求ID到后端用于防重
               },
               showLoading: true,
               showLoadingTitle: "正在生成条码..."
            }).then(res => {
               // 清除超时定时器
               clearTimeout(timeoutId);
               // 注意:这里不立即释放 isGeneratingBarcode,要等到打印完成才释放
               // this.isGeneratingBarcode = false; // 移除这行,在 cleanUser() 中重置
               if (res.status == 1) {
                  this.$showMessage(res.message);
                  this.isShow = false;
                  // 如果生成失败,重置状态
                  this.isGeneratingBarcode = false;
                  this.generateRequestId = null;
                  return;
               }
               this.dataToPrint = res.data.tbBillList;
               // this.getXS0101();
               let printCommands = [];
               console.log("接口返回的条数" + this.dataToPrint.length);
               let user = this.staffNo;
               for (let i = 0; i < this.dataToPrint.length; i++) {
                  let _printData = {
                     strp1: this.dataToPrint[i].out12,
                     strp2: this.dataToPrint[i].out2,
                     strp3: this.dataToPrint[i].out6,
                     strp4: this.dataToPrint[i].out1,
                     strp5: this.dataToPrint[i].out11,
                     strp6: this.dataToPrint[i].out8,
                     strp7: this.dataToPrint[i].out9,
                     strp8: this.dataToPrint[i].out12,
                     strp9: this.dataToPrint[i].out7,
                     strp10: user,
                  }
                  let printCmd = printTemplate3(_printData);
                  printCommands.push(printCmd);
               }
               this.bufferData = printCommands.join('\n');
               console.log('条码生成成功,请求ID:', this.generateRequestId);
            }).catch(error => {
               // 网络错误时也要释放锁定
               clearTimeout(timeoutId);
               this.isGeneratingBarcode = false;
               this.generateRequestId = null;
               console.error('条码生成失败:', error);
               this.$showMessage('网络异常,条码生成失败,请重试');
            });
         },
         onPrint() {
            this.printBarcode();
         },
         onPrintSuccess() {
            this.getOrderById();
            this.findByOrderId();
            // this.updateBarcodeAmount();
            this.getWomdaaPrintById();
            // 清空打印数据
            this.bufferData = '';
            this.dataToPrint = [];
            // 清空报工人数据
            this.staffNo = null;
            this.user = '';
            // 重置防重复状态(打印成功后完全重置)
            this.isGeneratingBarcode = false;
            this.generateRequestId = null;
            console.log("打印成功,已重置防重复状态");
         },
         onPrintFail() {
            console.log("重连失败");
            this.printLoading = false;
            // 重置防重复状态(打印失败后也要重置)
            this.isGeneratingBarcode = false;
            this.generateRequestId = null;
            console.log("打印失败,已重置防重复状态");
         },
         updateBarcodeAmount() {
            if (this.dataToPrint.length == 0) {
               return;
            }
            let barcodes = this.dataToPrint.map(s => s.out12);
            this.$post({
               url: "/MesInvItemBarcodes/UpdateBarcodeAmount",
               data: {
                  barcodes: barcodes,
                  user: this.staffNo
               }
            }).then(res => {
               console.log("更新条码数量成功");
            })
         },
         deleteBarcode() {
            // 关闭弹窗
            this.isShow = false;
            // 取消打印时完全重置防重复状态
            this.isGeneratingBarcode = false;
            this.generateRequestId = null;
            // 清空打印数据
            this.bufferData = '';
            this.dataToPrint = [];
            // 清空报工人相关数据
            this.staffNo = null;
            this.user = '';
            // 重置打印条码数据
            this.barcodeAmount = '';
            this.icount = 1;
            // 清空staff数据
            this.staff = null;
            console.log("已清空报工人和打印数据,重置防重复状态");
            if (this.dataToPrint.length == 0) {
               return;
            }
            // let barcodes = this.dataToPrint.map(s => s.out12);
            // this.$post({
            //    url: "/MesInvItemBarcodes/DeleteBarcode",
            //    data: {
            //       barcodes: barcodes,
            //    }
            // }).then(res => {
            //    console.log("删除条码成功");
            // })
         },
         cleanUser() {
            this.isShow = false;
            this.printLoading = false;
            // 打印结束后重置生成状态,允许下次生成
            this.isGeneratingBarcode = false;
            this.generateRequestId = null;
            console.log("打印结束,已重置生成状态");
         },
         // 保存操作
         save() {
            console.log('保存成功');
            let ids = [];
            this.selectedReasons.forEach(s => {
               let id = this.itemsNgname[this.badReasons.indexOf(s)].id;
               ids.push(id);
            });
            if (ids.length <= 0) {
               return
            }
            let ngids = ids.join(",");
            //MesOrderSta
            this.$post({
               url: "/MesOrderSta/UpdateNg",
               data: {
                  ngId: ngids,
                  staId: this.ngStaid
               }
            }).then(res => {
               if (res.data.tbBillList) {
                  uni.showToast({
                     title: '保存成功',
                     icon: 'success',
               this.$post({ url: "/Womdaa/GetWomdaasByShow", data: { machineNo: this.machineNo } })
                  .then(res => {
                     this.lineList = res.data.tbBillList;
                     this.DAA003List = res.data.tbBillList.map(i => i.daa003);
                  });
                  this.getOrderById();
                  this.getWomdaaPrintById();
                  this.findByOrderId();
               }
            });
         },
         // 取消操作
         cancel() {
            console.log('取消操作');
            uni.showToast({
               title: '取消操作',
               icon: 'none',
            });
         },
         getOrderById() {
            this.$post({
               url: "/Womdaa/GetWomdaaById",
               data: {
                  orderId: this.orderId,
                  orderNo: this.orderNo
               }
            }).then(res => {
               this.order = res.data.tbBillList;
               this.printedCount = res.data.tbBillList.bgqty;
               this.defectiveCount = res.data.tbBillList.blQty;
               this.productionCount = this.order.todayOutput;
               if (!this.order.todayOutput) {
                  this.productionCount = 0;
               }
               if (!this.defectiveCount) {
                  this.defectiveCount = 0;
               }
               if (!this.printedCount) {
                  this.printedCount = 0;
               }
               //this.defectiveCount = this.productionCount - this.sQuantity;
            })
         },
         getMesItemsNgname() {
            this.$post({
               url: "/MesItemsNgname/GetMesItemsNgname",
            }).then(res => {
               this.itemsNgname = res.data.tbBillList;
               this.badReasons = this.itemsNgname.map(s => s.ngName);
            });
         },
         getXS0101() {
            this.$post({
               url: "/MesStaff/GetAllXS0101",
            }).then(res => {
               this.staff = res.data.tbBillList;
               this.users = this.staff.map(s => s.staffNo + ":" + s.staffName);
            });
         },
         getWomdaaPrintById() {
            // 添加错误处理和数据校验
            try {
               this.$post({
                  url: "/Womdaa/GetWomdaaPrintById",
                  data: {
                     orderId: this.orderId
                  }
               }).then(res => {
                  // 检查响应数据是否存在且格式正确
                  if (!res || !res.data || !res.data.tbBillList) {
                     console.error('获取打印数据失败: 响应数据格式错误');
                     return;
                  }
                  const data = res.data.tbBillList;
                  // 直接赋值bqty,不使用默认值
                  this.bqty = data.bqty;
                  this.icount = 1; // 固定为1
                  this.sQuantity = data.sQuantity || 0;
                  this.initialValue = data.initialValue || 0;
                  this.kgQty = data.kgQty || 0;
                  this.barcodeAmount = data.qqty || 0;
                  // 只有当bqty不为null且不为undefined且等于0时才执行Completed
                  if (this.bqty !== null && this.bqty !== undefined && this.bqty === 0) {
                     console.log('数量为0,执行完成操作');
                     this.Completed();
                  }
               }).catch(err => {
                  console.error('获取打印数据失败:', err);
               });
            } catch (error) {
               console.error('执行getWomdaaPrintById时发生错误:', error);
            }
         },
         Completed() {
            this.$post({
               url: "/MesOrderSta/Completed",
               data: {
                  orderId: this.orderId,
                  orderNo: this.orderNo
               }
            }).then(res1 => {
            })
         },
         findByOrderId() {
            this.$post({
               url: "/MesOrderSta/FindByOrderNo",
               data: {
                  orderId: this.orderId,
                  orderNo: this.orderNo
               }
            }).then(res => {
               // 从接口获取的已选择原因
               let str = res.data.tbBillList.ngId;
               this.ngStaid = res.data.tbBillList.id;
               if (!str) {
                  return;
               }
               let ids = str.split(",");
               // 使用 map 和 filter 提取对应的 ngName
               let preSelectedReasons = ids.map(id => {
                  // 查找对应的对象
                  let matchedItem = this.itemsNgname.find(item => item.id == id);
                  return matchedItem ? matchedItem.ngName : null; // 如果找到,返回 ngName;否则返回 null
               }).filter(ngName => ngName !== null); // 过滤掉 null 值
               // 设置已选中的不良原因
               this.selectedReasons = this.badReasons.filter(reason => preSelectedReasons.includes(reason));
            });
         toggleUser(u) {
            if (!u) return;
            this.user = this.user === u ? null : u;
            this.staffNo = this.user;
         },
         confirmCustomAmount() {
            // 检查输入是否为有效数字
            if (!this.customAmount || isNaN(Number(this.customAmount))) {
               this.$showMessage('请输入有效的数量');
               return;
            }
            // 将自定义数量应用到系统中
            let amount = Number(this.customAmount);
            console.log('应用自定义数量:', amount);
            // 这里可以根据需要调用API或更新相关数据
            if (!this.customAmount || isNaN(Number(this.customAmount))) { this.$showMessage('请输入有效的数量'); return; }
            const amount = Number(this.customAmount);
            this.$post({
               url: "/MesInvItemBarcodes/AddBFToBarcodes",
               data: {
                  orderNo: this.orderNo,
                  orderId: this.orderId,
                  bf: amount
               }
               data: { orderNo: this.orderNo, orderId: this.orderId, bf: amount }
            }).then(res => {
               if (res.status == 1) {
                  this.$showMessage(res.message);
                  return;
               }
               if (res.status == 1) { this.$showMessage(res.message); return; }
               this.$showMessage('报废数量填写成功');
               // 重新获取数据以更新显示
               this.fetchData(true);
               // 清空输入框
               this.customAmount = '';
            }).catch(err => {
               console.error('报废数量填写失败:', err);
               this.$showMessage('报废数量填写失败,请重试');
            });
            }).catch(() => this.$showMessage('报废数量填写失败,请重试'));
         },
         save() {
            if (!this.staffNo) { this.$showMessage('请选择报工人'); return; }
            uni.showToast({ title: '保存成功', icon: 'success' });
         },
         cancel() { uni.showToast({ title: '取消操作', icon: 'none' }); },
         getOrderById() {
            this.$post({ url: "/Womdaa/GetWomdaaById", data: { orderId: this.orderId, orderNo: this.orderNo } })
               .then(res => {
                  this.order = res.data.tbBillList;
                  this.printedCount = res.data.tbBillList.bgqty || 0;
                  this.defectiveCount = res.data.tbBillList.blQty || 0;
                  this.productionCount = this.order.todayOutput || 0;
               });
         },
         getXS0101() {
            this.$post({ url: "/MesStaff/GetAllXS0101" })
               .then(res => {
                  this.staff = res.data.tbBillList;
                  this.users = this.staff.map(s => s.staffNo + ":" + s.staffName);
               });
         },
         getWomdaaPrintById() {
            this.$post({ url: "/Womdaa/GetWomdaaPrintById", data: { orderId: this.orderId } })
               .then(res => {
                  if (!res?.data?.tbBillList) return;
                  const d = res.data.tbBillList;
                  this.bqty = d.bqty;
                  this.icount = 1;
                  this.sQuantity = d.sQuantity || 0;
                  this.initialValue = d.initialValue || 0;
                  this.kgQty = d.kgQty || 0;
                  this.barcodeAmount = d.qqty || 0;
                  if (this.bqty === 0) this.Completed();
               }).catch(() => { });
         },
         Completed() {
            this.$post({ url: "/MesOrderSta/Completed", data: { orderId: this.orderId, orderNo: this.orderNo } });
         },
         init() {
            try {
               const v = this.getAndroidVersion();
               v >= 12 ? this.initForAndroid12Plus() : this.initForAndroidLegacy();
            } catch (e) { console.error(e); }
         },
         getAndroidVersion() {
            try { var Build = plus.android.importClass("android.os.Build"); return Build.VERSION.SDK_INT; }
            catch { return 30; }
         },
         initForAndroid12Plus() {
            try {
               var main = plus.android.runtimeMainActivity();
               var BluetoothManager = plus.android.importClass("android.bluetooth.BluetoothManager");
               var Context = plus.android.importClass("android.content.Context");
               var UUID = plus.android.importClass("java.util.UUID");
               this.uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
               var mgr = main.getSystemService(Context.BLUETOOTH_SERVICE);
               var adp = mgr.getAdapter();
               if (adp && adp.isDiscovering()) adp.cancelDiscovery();
               this.printMac = uni.getStorageSync('printMac');
               var mac = this.printMac || "DC:1D:30:91:06:52";
               if (adp) {
                  this.device = adp.getRemoteDevice(mac);
                  plus.android.importClass(this.device);
               }
            } catch (e) { this.initForAndroidLegacy(); }
         },
         initForAndroidLegacy() {
            try {
               var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
               var UUID = plus.android.importClass("java.util.UUID");
               this.uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
               var BAdapter = BluetoothAdapter.getDefaultAdapter();
               if (BAdapter) BAdapter.cancelDiscovery();
               this.printMac = uni.getStorageSync('printMac');
               var mac = this.printMac || "DC:1D:30:91:06:52";
               if (BAdapter) {
                  this.device = BAdapter.getRemoteDevice(mac);
                  plus.android.importClass(this.device);
                  this.bluetoothSocket = this.device.createInsecureRfcommSocketToServiceRecord(this.uuid);
                  plus.android.importClass(this.bluetoothSocket);
               }
            } catch (e) { }
         },
         deleteBarcode() {
            this.isShow = false;
            this.isGeneratingBarcode = false;
            this.generateRequestId = null;
            this.bufferData = ''; this.dataToPrint = [];
            this.staffNo = null; this.user = ''; this.barcodeAmount = ''; this.icount = 1; this.staff = null;
         }
      }
   };
   }
</script>
<style scoped>
   /* 页面样式 */
   .page {
      padding: 2vh;
      padding: 1.2vh 2vw;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      box-sizing: border-box;
   }
   .top-right {
      position: absolute;
      top: -25px;
      right: 50px;
      z-index: 1000;
   .wide-layout {
      max-width: 1600px;
      margin: 0 auto;
   }
   .refresh-btn {
      /* padding: 10px; */
      float: right;
      background-color: #00A2E9;
      color: white;
      border: none;
      font-size: 32px;
      border-radius: 15px;
      margin-top: -23px;
      padding-left: 25px;
      padding-right: 25px;
      margin-top: -32px;
      margin-bottom: 49px;
   .page.has-overlay .status-section > :not(.overlay) {
      pointer-events: none;
   }
   /* 状态行样式 */
   .page.has-overlay .status-section > .overlay {
      pointer-events: auto;
   }
   .report-table-wrapper {
      margin-bottom: 12px;
   }
   .table-scroll {
      overflow-x: auto;
   }
   .report-title {
      font-size: 24px;
      font-weight: 600;
      text-align: center;
      margin: 0 0 8px;
   }
   .report-table {
      min-width: 1080px;
      width: 100%;
      border-collapse: collapse;
      font-size: 14px;
      background: #fff;
   }
      .report-table th, .report-table td {
         border: 1px solid #555;
         padding: 6px 8px;
         text-align: center;
         white-space: nowrap;
      }
   .status-section {
      display: flex;
      flex-direction: column;
      margin-bottom: 3vh;
      padding-top: 14px;
      gap: 10px;
   }
   .status-row {
      display: flex;
      justify-content: space-around;
      margin-bottom: 20px;
      flex-wrap: wrap;
      align-items: center;
      gap: 10px;
      background: #f9f9f9;
      padding: 10px 14px;
      border-radius: 8px;
      box-shadow: 0 1px 4px rgba(0,0,0,.06);
   }
   .status-box {
@@ -1453,192 +454,163 @@
      align-items: center;
   }
   .refresh-container {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
   .result-box {
      background: #f0f8ff;
      padding: 4px 12px;
      border-radius: 6px;
      border-left: 5px solid #007aff;
   }
   input.highlight {
      width: 10vw;
      font-weight: 700;
      width: 9vw;
      min-width: 110px;
      font-weight: 600;
      border: none;
      background-color: #FFD700;
      background: #fff;
      text-align: center;
      font-size: 1.5vw;
      font-size: 18px;
      padding: 6px 0;
      border-radius: 6px;
      box-shadow: inset 0 1px 3px rgba(0,0,0,.12);
   }
   .form-row {
   .operator-box {
      display: flex;
      justify-content: space-between;
      margin-bottom: 3vh;
      flex-wrap: nowrap;
      justify-content: center;
      align-items: center;
      font-size: 28px;
      font-weight: bold;
      color: #007aff;
      margin: 0 6px;
   }
   .form-item {
      width: 30%;
   .btn-group {
      margin-left: auto;
      display: flex;
      align-items: center;
      gap: 12px;
   }
   .refresh-btn-inline, .reset-btn-inline {
      transition: .15s;
   }
   .refresh-btn-inline {
      background: #00A2E9;
      color: #fff;
      border: none;
      font-size: 18px;
      border-radius: 10px;
      padding: 8px 30px;
   }
      .refresh-btn-inline:hover {
         background: #0086c0;
      }
   .reset-btn-inline {
      background: #ff6b6b;
      color: #fff;
      border: none;
      font-size: 16px;
      border-radius: 10px;
      padding: 8px 18px;
   }
      .reset-btn-inline:hover {
         background: #e94d4d;
      }
   .flex-row {
      display: flex;
      flex-wrap: wrap;
      gap: 20px;
      align-items: flex-start;
   }
   .flex-grow {
      flex: 1 1 540px;
   }
   .gap-lg {
      gap: 30px;
   }
   .print-section {
      padding: 1vh;
      border-radius: 1vw;
      margin-bottom: 2vh;
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      flex-direction: row;
      align-content: stretch;
      justify-content: flex-start;
      padding: 6px 0 14px;
      margin-bottom: 0;
      flex: 1;
   }
   .barcode-info {
      display: flex;
      flex-wrap: wrap;
      align-items: flex-start;
      gap: 2vw;
      flex-direction: row;
      flex-wrap: nowrap;
      align-content: flex-start;
      justify-content: flex-start;
      gap: 30px;
   }
   .inp {
      width: 65%;
      padding: 1vh;
      margin-top: -13px;
      font-size: 1.3vw;
      padding: 8px;
      font-size: 16px;
      border: 1px solid #808080;
      border-radius: 0.5vw;
      border-radius: 8px;
      box-sizing: border-box;
   }
   .barcode-info text {
      font-size: 2.5vw
   }
   input {
      padding: 1vh;
      font-size: 1.5vw;
      width: 10vw;
      border-radius: 0.5vw;
      height: 2.4em;
   }
   .print-btn {
      display: inline-block;
      padding: 1.5vh;
      background-color: #e93c00eb;
      color: white;
      font-size: 1.5vw;
      border: none;
      cursor: pointer;
      border-radius: 1vw;
      margin-left: 30px;
   .bad-input {
      width: 320px;
      max-width: 100%;
      height: 66px;
      border: 3px solid #808080;
      font-size: 34px;
      text-align: center;
   }
   .details-btn {
      display: inline-block;
      padding: 1.5vh;
      background-color: #00a2e9;
      color: white;
      font-size: 1.5vw;
      padding: 12px 34px;
      background: #00a2e9;
      color: #fff;
      font-size: 20px;
      border: none;
      cursor: pointer;
      border-radius: 1vw;
      margin-left: 50px;
      border-radius: 12px;
   }
   /* 不良原因选择 */
   .reason-section {
      margin-bottom: 3vh;
   }
      .details-btn:hover {
         background: #008ac2;
      }
   .reason-buttons {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      gap: 1vw;
   }
   .reason-btn {
      padding: 0.5vh;
      background-color: #808080;
      color: white;
      font-size: 1.3vw;
      border: none;
      border-radius: 0.5vw;
      cursor: pointer;
   }
   .reason-btn.selected {
      background-color: #FFD700;
      color: black;
   }
   /* 底部保存和取消按钮 */
   .bottom-section {
   .current-user-section {
      display: flex;
      justify-content: space-between;
      margin-top: 2vh;
      align-items: center;
      font-size: 18px;
      border: 1.5px solid #f00;
      border-radius: 10px;
      padding: 14px 22px;
      background: #fff;
      gap: 14px;
   }
   .bottom-section1 {
      display: flex;
      justify-content: space-around;
      margin-bottom: 2vh;
      padding: 2vh 1vw;
   .fill-width {
      flex: 0 1 380px;
   }
   .save-btn,
   .cancel-btn {
      width: 48%;
      padding: 1.5vh;
      background-color: #00A2E9;
      color: white;
      font-size: 1.5vw;
      border: none;
      text-align: center;
      cursor: pointer;
      border-radius: 0.5vw;
   .current-user-name {
      font-weight: bold;
      font-size: 22px;
   }
   .clean-btn {
      width: 48%;
      padding: 1.5vh;
      color: white;
      font-size: 1.5vw;
      border: none;
      text-align: center;
      cursor: pointer;
      border-radius: 0.5vw;
      background-color: #007aff;
   .select-user-btn {
      padding: 6px 22px;
      background: #eee;
      border: 1px solid #aaa;
      border-radius: 8px;
      font-size: 16px;
   }
   .user-select1 {
      float: left;
      display: inline-block;
      margin-top: 17px;
   }
   .user-select2 {
      margin-top: 17px;
      margin-left: -10px;
   }
   .user-select {
      /* margin-right: 2vw; */
      font-size: 1.5vw;
   }
   .form-item label {
      float: left;
      margin-top: -5px;
      font-size: 1.5vw;
      /* Larger font for labels */
      display: inline-block;
      margin-bottom: 0.5vh;
      color: #333;
   }
      .select-user-btn:hover {
         background: #ddd;
      }
   .overlay {
      position: fixed;
@@ -1646,277 +618,226 @@
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      background: rgba(0,0,0,.45);
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 1000;
   }
   .popup {
      background-color: #fff;
      background: #fff;
      padding: 2vh;
      border: 1px solid #ccc;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
      width: 70vw;
      box-shadow: 0 0 14px rgba(0,0,0,.12);
      width: 72vw;
      max-width: 1400px;
      height: 70vh;
      font-size: 1.6vw;
      /* 设置弹框的最大高度 */
      font-size: 1.4vw;
      max-height: 80vh;
      /* 启用纵向滚动条 */
      overflow-y: auto;
      /* 设置弹框的外观 */
      border-radius: 12px;
      z-index: 1001;
   }
   .user-select-popup {
      width: 860px;
      max-width: 80vw;
      height: auto;
      min-height: 480px;
      padding: 0;
      display: flex;
      flex-direction: column;
   }
   /* 搜索条样式 */
   .user-search-bar {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 18px 32px 0 32px;
      background: #fff;
      flex-wrap: wrap;
   }
   .user-search-input {
      flex: 1 1 260px;
      padding: 10px 14px;
      font-size: 16px;
      border: 1px solid #bbb;
      border-radius: 8px;
      /* Increased font size within popups */
      outline: none;
   }
   .inp5 {
      float: left;
      margin-top: 0px;
      width: 20%;
      text-align: center;
      font-size: 45px;
      border: 0px;
      border-radius: 1.5vw;
      background-color: #e5d3a0;
      .user-search-input:focus {
         border-color: #007aff;
         box-shadow: 0 0 0 2px rgba(0,122,255,.15);
      }
   .user-search-clear {
      padding: 10px 18px;
      background: #ff9f43;
      color: #fff;
      border: none;
      border-radius: 8px;
      font-size: 14px;
      cursor: pointer;
   }
   .inp6 {
      float: left;
      width: 22%;
      text-align: center;
      font-size: 45px;
      border: 0px;
      border-radius: 1.5vw;
      background-color: #e5d3a0;
      display: inline-block;
      .user-search-clear:hover {
         background: #ff8920;
      }
   .user-search-info {
      font-size: 14px;
      color: #555;
   }
   .user-list-scroll {
      flex: 1 1 auto;
      overflow-y: auto;
      padding: 24px 32px 0 32px;
   }
   .user-list-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill,minmax(150px,1fr));
      gap: 24px 24px;
   }
   .user-list-btn {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      gap: 6px;
      padding: 16px 10px;
      height: 120px;
      font-size: 18px;
      background: #00a2e9;
      color: #fff;
      border: none;
      border-radius: 10px;
      cursor: pointer;
      box-sizing: border-box;
      word-break: break-word;
   }
      .user-list-btn .user-code {
         font-weight: 600;
         font-size: 18px;
      }
      .user-list-btn .user-name {
         font-size: 16px;
      }
      .user-list-btn.selected {
         background: #0072c9;
         box-shadow: 0 0 0 3px rgba(255,255,255,.6) inset;
      }
      .user-list-btn:hover {
         background: #008ed0;
      }
   .no-user-result {
      padding: 40px 0;
      text-align: center;
      font-size: 18px;
      color: #666;
   }
   .user-popup-footer {
      flex-shrink: 0;
      padding: 22px 32px 32px 32px;
      background: #fff;
      text-align: center;
   }
   .clean-btn {
      width: 48%;
      padding: 1.6vh;
      color: #fff;
      font-size: 1.4vw;
      border: none;
      text-align: center;
      cursor: pointer;
      border-radius: .6vw;
      background: #007aff;
   }
      .clean-btn.wide-btn {
         width: 60%;
         font-size: 20px;
      }
      .clean-btn:hover {
         background: #0062c9;
      }
   .reason-section {
      margin: 14px 0 18px;
   }
   .reason-buttons {
      display: grid;
      grid-template-columns: repeat(5,1fr);
      gap: 12px;
   }
   .reason-btn {
      padding: 10px 6px;
      background: #808080;
      color: #fff;
      font-size: 14px;
      border: none;
      border-radius: 8px;
      cursor: pointer;
   }
      .reason-btn.selected {
         background: #FFD700;
         color: #000;
      }
   .bottom-section {
      display: flex;
      justify-content: space-between;
      margin-top: 16px;
      gap: 16px;
   }
   .save-btn, .cancel-btn {
      flex: 1;
      padding: 16px 0;
      background: #00A2E9;
      color: #fff;
      font-size: 20px;
      border: none;
      border-radius: 10px;
   }
      .save-btn:hover, .cancel-btn:hover {
         background: #0086c0;
      }
   .table1 {
      width: 100%;
      border-spacing: 3px;
   }
   .table2 {
      background-color: bisque;
   @media (max-width:1400px) {
      input.highlight {
         font-size: 16px;
      }
   }
      .user-list-btn {
         height: 110px;
         font-size: 16px;
      }
   .top-refresh-container {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      margin-bottom: 15px;
   }
   .version-info-top {
      text-align: right;
      font-size: 13px;
      color: #000;
      margin-right: 10px;
   }
   .operator-box {
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 36px;
      font-weight: bold;
      margin: 0 10px;
      color: #333;
   }
   .header-container {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;
      padding: 10px 15px;
      background-color: #f2f2f2;
      border-radius: 10px;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
   }
   .header-title {
      font-size: 24px;
      font-weight: bold;
      color: #333;
   }
   .header-right {
      display: flex;
      align-items: center;
   }
   .top-refresh-container {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      margin-bottom: 15px;
   }
   .version-info-top {
      text-align: right;
      font-size: 13px;
      color: #666;
      margin-right: 10px;
   }
   .status-row {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      margin-bottom: 20px;
      background-color: #f9f9f9;
      padding: 15px;
      border-radius: 8px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
   }
   .status-box {
      display: flex;
      align-items: center;
      padding: 0 10px;
   }
   .result-box {
      background-color: #f0f8ff;
      padding: 5px 15px;
      border-radius: 6px;
      border-left: 4px solid #007aff;
   }
   input.highlight {
      width: 10vw;
      font-weight: 700;
      border: none;
      background-color: #fff;
      text-align: center;
      font-size: 1.5vw;
      padding: 8px;
      border-radius: 4px;
      box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
   }
   .operator-box {
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 36px;
      font-weight: bold;
      margin: 0 15px;
      color: #007aff;
      width: 40px;
      height: 40px;
      line-height: 40px;
      text-align: center;
   }
   .refresh-btn {
      background-color: #007aff;
      color: white;
      border: none;
      font-size: 18px;
      border-radius: 6px;
      padding: 8px 20px;
      transition: background-color 0.3s;
   }
   .refresh-btn:active {
      background-color: #0062cc;
   }
   .reset-btn {
      background-color: #ff6b6b;
      color: white;
      border: none;
      font-size: 18px;
      border-radius: 6px;
      padding: 8px 15px;
      margin-left: 10px;
      transition: background-color 0.3s;
   }
   .reset-btn:active {
      background-color: #e55555;
   }
   .non-calc-row {
      border-top: 1px dashed #ccc;
      margin-top: 30px;
      padding-top: 20px;
      position: relative;
   }
   .divider-label {
      position: absolute;
      top: -12px;
      left: 30px;
      background-color: #fff;
      padding: 0 15px;
      font-size: 16px;
      color: #777;
   }
   .standalone-box {
      background-color: #f5f5f5;
      padding: 8px 15px;
      border-radius: 6px;
      margin-right: 20px;
   }
   .confirm-row {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-top: 10px;
   }
   .input-group {
      display: flex;
      align-items: center;
   }
   .custom-input {
      width: 60%;
      padding: 1vh;
      font-size: 1.5vw;
      border: 1px solid #808080;
      border-radius: 0.5vw;
   }
   .confirm-btn {
      padding: 1.5vh;
      background-color: #00A2E9;
      color: white;
      font-size: 1.5vw;
      border: none;
      cursor: pointer;
      border-radius: 0.5vw;
   }
   .custom-amount-section {
      margin-top: 20px;
   }
   .custom-amount-container {
      display: flex;
      align-items: center;
   }
   .custom-amount-label {
      margin-right: 10px;
      font-size: 1.5vw;
   }
   .custom-amount-input {
      width: 60%;
      padding: 1vh;
      font-size: 1.5vw;
      border: 1px solid #808080;
      border-radius: 0.5vw;
   }
   .custom-amount-row {
      margin-top: 20px;
      .reason-btn {
         font-size: 12px;
      }
   }
</style>