Houjie
3 天以前 51c7896fd8e45085dd5cdfff11e79a00ee0a7379
pages/spare/spare.vue
@@ -1,134 +1,324 @@
<template>
   <view>
      <cu-custom :bgColor="NavBarColor" :isBack="true" backRouterName="index">
         <block slot="backText">返回</block>
         <block slot="content">扫一扫</block>
      </cu-custom>
      <view class="scanCode">
         <mumu-get-qrcode :continue="true" @success='qrcodeSucess' @error="qrcodeError"
            :definition="true"></mumu-get-qrcode>
      </view>
   </view>
  <view class="container">
    <cu-custom :bgColor="NavBarColor" :isBack="true" backRouterName="index">
      <block slot="backText">返回</block>
      <block slot="content">移库单打印</block>
    </cu-custom>
    <view class="print-area">
      <button @click="previewTransferOrder" class="btn test" :loading="isLoading">
        {{ isLoading ? '生成中...' : '预览移库单' }}
      </button>
    </view>
    <view class="status">
      预览状态: {{ isPreview ? '已生成预览' : '未生成' }}
    </view>
    <view class="log" v-if="logList.length > 0">
      <text class="log-title">操作日志:</text>
      <view v-for="(log, index) in logList" :key="index" class="log-item">
        {{ log }}
      </view>
    </view>
  </view>
</template>
<script>
   import mumuGetQrcode from '@/uni_modules/mumu-getQrcode/components/mumu-getQrcode/mumu-getQrcode.vue';
export default {
  name: 'TransferOrderPrinter',
  data() {
    return {
      NavBarColor: '#007AFF',
      isPreview: false,
      logList: [],
      isLoading: false,
      // 移库单数据(实际项目中可从接口获取)
      orderData: {
        productionOrderNo: '112379',
        productModel: 'G-639',
        customerName: '东方日产',
        materialNo: '120047854',
        customerModel: '4200-51354',
        productionBatch: '25159847',
        factory: '双林新火炬工厂',
        quantity: '73',
        docCode: 'XHJ.QM.QMS009E',
        qrCodeText: 'C2506080024'
      }
    };
  },
  methods: {
    // 添加操作日志
    addLog(message) {
      const time = new Date().toLocaleTimeString();
      this.logList.unshift(`[${time}] ${message}`);
      if (this.logList.length > 20) this.logList.pop();
    },
   export default {
      components: {
         mumuGetQrcode // 注册
      },
      name: 'spare',
      data() {
         return {
            NavBarColor: this.NavBarColor,
            hasNavigated: false // 标记是否已经跳转
         };
      },
    // 使用在线API生成二维码(无Canvas依赖)
    async generateQrCode(content) {
      try {
        this.addLog('开始生成二维码...');
        // 方案1: 使用Base64编码内容直接生成二维码(推荐)
        const base64Content = encodeURIComponent(content);
        // 该链接会根据内容生成二维码,无需后端支持
        return `https://api.qrserver.com/v1/create-qr-code/?data=${base64Content}&size=120x120`;
        // 方案2: 备用API(若方案1不可用)
        // return `https://chart.googleapis.com/chart?chs=120x120&cht=qr&chl=${base64Content}`;
      } catch (error) {
        this.addLog(`二维码生成失败: ${error.message}`);
        throw error;
      }
    },
      methods: {
         navigateToDeviceDetails(equipmentId) {
            this.hasNavigated = true; // 标记已经跳转
            uni.redirectTo({
               url: `/pages/device/deviceWebDeils/deviceWebDeils?equipmentId=${encodeURIComponent(equipmentId)}`,
               success: () => {
                  console.log('Navigated to device details');
               },
               fail: (err) => {
                  console.error('Navigation failed:', err);
               }
            });
         },
         qrcodeSucess(data) { // 扫码成功
            setTimeout(() => {
               let equipmentId;
               try {
                  // 兼容性处理:优先使用URL和URLSearchParams,如果不可用则使用字符串解析
                  if ('URL' in window && 'URLSearchParams' in window) {
                     const url = new URL(data);
                     const params = new URLSearchParams(url.hash.slice(1).split('?')[1]);
                     equipmentId = params.get('equipmentId');
                  } else {
                     // 字符串解析方式
                     const hashIndex = data.indexOf('#');
                     if (hashIndex !== -1) {
                        const hashPart = data.substring(hashIndex + 1);
                        const paramIndex = hashPart.indexOf('?');
                        if (paramIndex !== -1) {
                           const paramStr = hashPart.substring(paramIndex + 1);
                           const pairs = paramStr.split('&');
                           for (let pair of pairs) {
                              const [key, value] = pair.split('=');
                              if (key === 'equipmentId') {
                                 equipmentId = value;
                                 break;
                              }
                           }
                        }
                     }
                  }
    // 生成移库单HTML并预览
    async generateTransferHTML() {
      try {
        this.isLoading = true;
        this.addLog('开始生成移库单...');
                  if (equipmentId) {
                     // 登录成功且获取到equipmentId,跳转到设备详情页面
                     this.navigateToDeviceDetails(equipmentId);
                  } else {
                     uni.showModal({
                        title: '提示',
                        content: "二维码中未找到有效的equipmentId",
                        showCancel: false
                     });
                  }
               } catch (error) {
                  uni.showModal({
                     title: '错误',
                     content: "解析URL出错,请检查二维码内容",
                     showCancel: false
                  });
               }
            }, 200); // 增加100毫秒的延迟
         },
         qrcodeError(err) { // 扫码失败
            uni.showModal({
               title: '摄像头授权失败',
               content: '摄像头授权失败,请检测当前浏览器是否有摄像头权限。',
               success: () => {
                  uni.navigateBack({}); // 返回到上一页
               }
            });
         }
      }
   };
        // 生成二维码内容
        const qrContent = `生产订单号:${this.orderData.productionOrderNo},产品型号:${this.orderData.productModel},客户名称:${this.orderData.customerName},物料号:${this.orderData.materialNo},客户型号:${this.orderData.customerModel},生产批号:${this.orderData.productionBatch},生产分厂:${this.orderData.factory},数量:${this.orderData.quantity}`;
        // 调用在线API生成二维码
        const qrDataUrl = await this.generateQrCode(qrContent);
        this.addLog('二维码生成成功');
        // 处理logo图片(使用本地资源)
        const logoUrl = '/static/index_logo.png';
        // 生成移库单HTML内容
        const htmlContent = `
          <!DOCTYPE html>
          <html lang="zh-CN">
          <head>
            <meta charset="UTF-8">
            <title>移库单</title>
            <style>
              @media print {
                @page {
                  size: A4 landscape;
                  margin: 15mm;
                }
                body {
                  -webkit-print-color-adjust: exact;
                }
              }
              body {
                margin: 0;
                padding: 0;
                font-family: "Microsoft YaHei", "SimHei", sans-serif;
              }
              .transfer-order {
                width: 800px;
                height: 550px;
                border: 2px solid #000;
                box-sizing: border-box;
                margin: 20px auto;
                padding: 15px;
              }
              .header {
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding: 10px 0;
                border-bottom: 2px solid #000;
                margin-bottom: 15px;
              }
              .logo img {
                width: 180px;
                height: auto;
              }
              .doc-info {
                text-align: right;
              }
              .doc-code {
                font-size: 18px;
                font-weight: bold;
                margin-bottom: 5px;
              }
              .doc-name {
                font-size: 28px;
                font-weight: bold;
                text-align: center;
                margin: 15px 0;
              }
              .divider {
                border-top: 2px solid #000;
                width: 200px;
                margin: 0 auto 15px;
              }
              table {
                width: 100%;
                border-collapse: collapse;
                table-layout: fixed;
              }
              table, th, td {
                border: 1px solid #000;
                padding: 10px;
                font-size: 15px;
                word-wrap: break-word;
              }
              .label-container {
                display: flex;
                gap: 15px;
                flex-wrap: wrap;
                padding: 5px 0;
              }
              .status-label {
                display: inline-block;
                padding: 8px 15px;
                background-color: #f0f0f0;
                border: 1px solid #ccc;
                border-radius: 4px;
                font-size: 14px;
              }
              table tr td:first-child {
                width: 120px;
              }
              table tr td[colspan="4"] {
                width: calc(100% - 120px);
              }
              .qrcode-area {
                text-align: center;
                vertical-align: middle;
              }
              .qrcode-area img {
                width: 150px;
                height: 150px;
                display: block;
                margin: 0 auto;
              }
              .qrcode-text {
                margin-top: 10px;
                text-align: center;
                font-size: 14px;
              }
            </style>
          </head>
          <body>
            <div class="transfer-order">
              <div class="header">
                <div class="logo">
                  <img src="${logoUrl}" alt="企业logo">
                </div>
                <div class="doc-info">
                  <div class="doc-code">${this.orderData.docCode}</div>
                </div>
              </div>
              <div class="doc-name">移库单</div>
              <div class="divider"></div>
              <table>
                <tr>
                  <td>生产订单号</td>
                  <td>${this.orderData.productionOrderNo}</td>
                  <td>产品型号</td>
                  <td>${this.orderData.productModel}</td>
                  <td rowspan="4" class="qrcode-area">
                    <img src="${qrDataUrl}" alt="二维码">
                    <div class="qrcode-text">${this.orderData.qrCodeText}</div>
                  </td>
                </tr>
                <tr>
                  <td>客户名称</td>
                  <td>${this.orderData.customerName}</td>
                  <td>物料号</td>
                  <td>${this.orderData.materialNo}</td>
                </tr>
                <tr>
                  <td>客户型号</td>
                  <td>${this.orderData.customerModel}</td>
                  <td>生产批号</td>
                  <td>${this.orderData.productionBatch}</td>
                </tr>
                <tr>
                  <td>生产分厂</td>
                  <td>${this.orderData.factory}</td>
                  <td>数量</td>
                  <td>${this.orderData.quantity}</td>
                </tr>
                <tr>
                  <td>检验状态</td>
                  <td colspan="4">
                    <div class="label-container">
                      <span class="status-label">合格</span>
                      <span class="status-label">已检验</span>
                    </div>
                  </td>
                </tr>
              </table>
            </div>
          </body>
          </html>
        `;
        // 生成Blob链接并跳转预览
        const blob = new Blob([htmlContent], { type: 'text/html' });
        const previewUrl = URL.createObjectURL(blob);
        uni.navigateTo({
          url: `/pages/print-preview/print-preview?previewUrl=${encodeURIComponent(previewUrl)}`,
          success: () => {
            this.isPreview = true;
            this.addLog('移库单预览生成成功');
          },
          fail: (err) => {
            this.addLog(`跳转预览失败: ${err.errMsg}`);
          }
        });
      } catch (error) {
        this.addLog(`生成失败: ${error.message}`);
        uni.showToast({ title: '生成失败', icon: 'none' });
      } finally {
        this.isLoading = false;
      }
    },
    // 触发预览
    previewTransferOrder() {
      if (this.isLoading) return;
      this.generateTransferHTML();
    }
  }
};
</script>
<style>
   .scanCode {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 99;
      height: 100%;
      width: 100%;
      background-color: rgba(0, 0, 0, 0.7);
   }
   .reader-box {
      position: fixed;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      background-color: rgba(0, 0, 0, 0.5);
   }
   .reader {
      width: 540rpx;
      height: 540rpx;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
   }
<style scoped>
.print-area {
  padding: 20rpx;
}
.btn {
  width: 100%;
  padding: 20rpx;
  margin-bottom: 15rpx;
  border-radius: 8rpx;
  color: #fff;
  font-size: 28rpx;
  background-color: #FF9500;
}
.status {
  padding: 20rpx;
  font-size: 28rpx;
  color: #666;
}
.log {
  margin: 10rpx;
  padding: 20rpx;
  background-color: #f5f5f5;
  border-radius: 10rpx;
}
.log-title {
  font-weight: bold;
  display: block;
  margin-bottom: 10rpx;
  color: #333;
}
.log-item {
  font-size: 26rpx;
  color: #666;
  margin-bottom: 5rpx;
  word-break: break-all;
}
</style>