#
whycq
2024-04-15 4ca50950b4d6371261d95f4bb60532abae4d02d5
pages/print/print.vue
@@ -1,416 +1,174 @@
<template>
   <!-- 蓝牙打印页面 -->
   <view class="page">
      <button @click="openBluetoothAdapter">重新查询</button>
      <view class="title">
         可连接的蓝牙设备列表:
         <text style="color: red;font-size:22rpx;">(部分机型需要打开GPS定位服务)</text>
      </view>
      <view class="list">
         <view class="item" v-for="(item, i) in devices" :key="i">
            <!-- 设备名称 -->
            <text>{{ item.name }}</text>
            <!-- 连接状态 -->
            <view class="right">
               <view class="font-color-3" @click="createBLEConnection(item)" v-show="!item.isShowConnect">连接设备</view>
               <view class="font-color-3" v-show="item.isShowConnect">已连接</view>
            </view>
   <view>
      <view class="print-model" :style="style">
         <view class="display" :style="">
            <table>
               <tr>
                  <td>料号</td>
                  <td>{{mat.matnr}}</td>
                  <td colspan="1" rowspan="2" style="width: 150px;">
                     <!-- 二维码 -->
                     <view class="qr-box">
                        <canvas canvas-id="qrcode" v-show="qrShow" style="width: 300rpx;margin: 0 auto;" />
                     </view>
                  </td>
               </tr>
               <tr>
                  <td>商品</td>
                  <td colspan="1">{{mat.maktx}}</td>
               </tr>
               <tr>
                  <td>日期</td>
                  <td colspan="2">{{time}}</td>
               </tr>
            </table>
         </view>
         <!-- v-if="devices.length" -->
         <button @click="writeBLECharacteristicValue">开始打印</button>
         <!-- <button :class="isDisabled || isConnected ? 'submit disabled' : 'submit'" @click="writeBLECharacteristicValue" :disabled="isDisabled || isConnected">开始打印</button> -->
         <view class="no-devices" v-if="!devices.length">未搜索到蓝牙设备</view>
      </view>
      <view>
         <button @click="toPrint">打印</button>
      </view>
   </view>
</template>
<script>
const LAST_CONNECTED_DEVICE = 'last_connected_device';
import PrinterJobs from '../../static/js/printerjobs';
import printerUtil from '../../static/js/printerutil';
function inArray(arr, key, val) {
   for (let i = 0; i < arr.length; i++) {
      if (arr[i][key] === val) {
         return i;
      }
   }
   return -1;
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
   const hexArr = Array.prototype.map.call(new Uint8Array(buffer), function(bit) {
      return ('00' + bit.toString(16)).slice(-2);
   });
   return hexArr.join(',');
}
function str2ab(str) {
   // Convert str to ArrayBuff and write to printer
   let buffer = new ArrayBuffer(str.length);
   let dataView = new DataView(buffer);
   for (let i = 0; i < str.length; i++) {
      dataView.setUint8(i, str.charAt(i).charCodeAt(0));
   }
   return buffer;
}
export default {
   name: 'print',
   components: {},
   props: {},
   data() {
      return {
         devices: [],
         connected: false,
         isConnected: true,
         name: '',
         deviceId: null
      };
   },
   onLoad() {},
   onShow() {},
   created() {},
   mounted() {
      this.openBluetoothAdapter();
   },
   methods: {
      // 初始化蓝牙
      openBluetoothAdapter() {
         console.log('初始化蓝牙模块 openBluetoothAdapter');
         if (!uni.openBluetoothAdapter) {
            console.log('微信版本过低');
            uni.showModal({
               title: '提示',
               content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
            });
            return;
   import uQRCode from '@/static/js/uqrcode.js' //引入uqrcode.js
   export default {
      data() {
         return {
            style: {
               height: '3px'
            },
            mat: {
               matnr: '1200128-10055',
               maktx: 'X5S-4-M03/333'
            },
            qrShow: false,
            time: ''
         }
         uni.showLoading({
            title: '开始搜索蓝牙设备'
         });
         // uni.hideLoading();
         uni.openBluetoothAdapter({
            success: res => {
               console.log('初始化成功openBluetoothAdapter success', res);
               uni.hideLoading();
               // 搜寻附近的蓝牙
               this.startBluetoothDevicesDiscovery();
            },
            fail: res => {
               console.log('初始化失败openBluetoothAdapter fail', res);
               // uni.showModal({
               //    content: res.errMsg,
               //    showCancel: false
               // });
               uni.hideLoading();
               if (res.errCode === 10001) {
                  // 当前蓝牙适配器不可用
                  uni.showModal({
                     title: '错误',
                     content: '未找到蓝牙设备, 请打开蓝牙后重试。',
                     showCancel: false
                  });
                  // 监听蓝牙适配器状态变化事件
                  uni.onBluetoothAdapterStateChange(res => {
                     console.log('监听蓝牙适配器状态 onBluetoothAdapterStateChange', res);
                     // available:蓝牙适配器是否可用
                     if (res.available) {
                        // 取消监听,否则stopBluetoothDevicesDiscovery后仍会继续触发onBluetoothAdapterStateChange,
                        // 导致再次调用startBluetoothDevicesDiscovery
                        // uni.onBluetoothAdapterStateChange(() => {});
                        // 开始搜寻附近的蓝牙外围设备
                        this.startBluetoothDevicesDiscovery();
                     }
                  });
               }
            }
         });
      },
      // 开始搜寻附近的蓝牙外围设备
      startBluetoothDevicesDiscovery() {
         console.log('开始搜寻附近的蓝牙设备');
         uni.startBluetoothDevicesDiscovery({
            allowDuplicatesKey: false,
            interval: 0,
            success: res => {
               console.log('搜寻附近的蓝牙外围设备 startBluetoothDevicesDiscovery success111', res);
               // 监听寻找到新设备的事件
               this.onBluetoothDeviceFound();
            },
            fail: res => {
               console.log('搜寻附近的蓝牙外围设备 startBluetoothDevicesDiscovery fail', res);
               uni.hideLoading();
            }
         });
      onShow() {
         let getWindowInfo = uni.getWindowInfo()
         // console.log(getWindowInfo.screenHeight); //屏幕高度
         // console.log(getWindowInfo.screenWidth); //屏幕宽度
         // console.log(getWindowInfo.windowHeight); //可操作页面高度
         // console.log(getWindowInfo.windowWidth); //可操作页面宽度
         // console.log(getWindowInfo);
         // console.log('获取窗口信息');
         let height = (getWindowInfo.screenWidth + 10) * 48 / 74
         // console.log(height);
         this.style.height = height + 'px'
         this.getDate()
      },
      // 监听寻找到新设备的事件
      onBluetoothDeviceFound() {
         console.log('进入查询设备');
         uni.onBluetoothDeviceFound(res => {
            console.log('寻找设备', res.devices);
            res.devices.forEach(device => {
               if (!device.name && !device.localName) {
                  return;
               }
               const foundDevices = this.devices;
               // 在数组中查找指定值,并返回它的索引值(如果没有找到,则返回-1)
               const idx = inArray(foundDevices, 'deviceId', device.deviceId);
               const data = {};
               if (idx === -1) {
                  this.$set(this.devices, `${foundDevices.length}`, device);
               } else {
                  this.$set(this.devices, `${idx}`, device);
               }
               console.log('搜索结果', this.devices);
               uni.hideLoading();
            });
         });
      onLoad(opt) {
         let that = this
         const eventChannel = this.getOpenerEventChannel();
         eventChannel.on('data', function(data) {
            that.mat = data.data
            that.qrFun(that.mat.matnr)
         })
      },
      // this.devices是蓝牙设备列表,渲染到页面显示点击执行蓝牙连接
      // 点击链接蓝牙
      createBLEConnection(e) {
         console.log('点击连接蓝牙', e);
         const deviceId = e.deviceId;
         const name = e.name;
         this._createBLEConnection(deviceId, name);
      },
      _createBLEConnection(deviceId, name) {
         // this.$myToast('连接设备中', 'loading');
         // 连接低功耗蓝牙设备
         uni.createBLEConnection({
            deviceId, // 用于区分设备的 id
            success: () => {
               console.log('连接蓝牙接口调用成功 createBLEConnection success', this.devices);
               this.devices.forEach((item, index) => {
                  this.$set(this.devices[index], 'isShowConnect', false);
                  if (item.deviceId === deviceId) {
                     this.$set(this.devices[index], 'isShowConnect', true);
                  }
               });
               this.$myToast('设备连接成功', 'success');
               this.connected = true;
               this.isConnected = false;
               this.name = name;
               this.deviceId = deviceId;
               // 获取蓝牙设备所有服务(service)
               this.getBLEDeviceServices(deviceId);
               // 最后连接设备
               uni.setStorage({
                  key: LAST_CONNECTED_DEVICE,
                  data: name + ':' + deviceId
               });
            },
            complete() {
               uni.hideLoading();
            },
            fail: res => {
               // 连接蓝牙接口调用失败
               console.log('连接蓝牙接口调用失败 createBLEConnection fail', res);
               uni.showModal({
                  title: this.$t('wechat.w227'),
                  content: '蓝牙连接失败',
                  showCancel: false
               });
            }
         });
         // 已经找到需要的蓝牙设备,停止搜寻附近的蓝牙外围设备
         this.stopBluetoothDevicesDiscovery();
      },
      // 获取蓝牙设备所有服务(service)
      getBLEDeviceServices(deviceId) {
         uni.getBLEDeviceServices({
            deviceId,
            success: res => {
               console.log('获取蓝牙设备所有服务 getBLEDeviceServices', res);
               for (let i = 0; i < res.services.length; i++) {
                  if (res.services[i].isPrimary) {
                     this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);
                     return;
                  }
               }
            }
         });
      },
      stopBluetoothDevicesDiscovery() {
         uni.stopBluetoothDevicesDiscovery({
            complete: () => {
               // console.log('stopBluetoothDevicesDiscovery')
               this._discoveryStarted = false;
            }
         });
      },
      /*
                        获取蓝牙设备某个服务中所有特征值(characteristic)
                        characteristic:
                           uuid:蓝牙设备特征值的 uuid
                           properties:该特征值支持的操作类型
                     */
      getBLEDeviceCharacteristics(deviceId, serviceId) {
         uni.getBLEDeviceCharacteristics({
            // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
            deviceId,
            // 这里的 serviceId(蓝牙服务 uuid) 需要在 getBLEDeviceServices 接口中获取
            serviceId,
            success: res => {
               console.log('特征值变化 getBLEDeviceCharacteristics success', res.characteristics);
               // 这里会存在特征值是支持write,写入成功但是没有任何反应的情况
               // 只能一个个去试
               // characteristics:设备服务列表
               for (let i = 0; i < res.characteristics.length; i++) {
                  const item = res.characteristics[i];
                  // if (item.properties.read) {
                  //    uni.readBLECharacteristicValue({
                  //       deviceId,
                  //       serviceId,
                  //       characteristicId: item.uuid
                  //    })
                  // }
                  if (item.properties.write) {
                     this.canWrite = true;
                     this._deviceId = deviceId;
                     this._serviceId = serviceId;
                     this._characteristicId = item.uuid;
                  }
                  if (item.properties.notify || item.properties.indicate) {
                     uni.notifyBLECharacteristicValueChange({
                        deviceId,
                        serviceId,
                        characteristicId: item.uuid,
                        state: true
                     });
                  }
                  if (item.properties.write) {
                     this.canWrite = true;
                     this._deviceId = deviceId;
                     this._serviceId = serviceId;
                     this._characteristicId = item.uuid;
                  }
                  if (item.properties.notify || item.properties.indicate) {
                     uni.notifyBLECharacteristicValueChange({
                        deviceId,
                        serviceId,
                        characteristicId: item.uuid,
                        state: true
                     });
                  }
               }
            },
            fail(res) {
               console.error('特征值变化 getBLEDeviceCharacteristics', res);
            }
         });
      },
      // 蓝牙连接成功后点击打印,打印数据
      // 点击打印:写入数据(根据项目需要打印内容来实现)
      writeBLECharacteristicValue() {
         console.log('写数据');
         let printerJobs = new PrinterJobs();
         // 要打印的信息
         printerJobs
            .setAlign('ct')
            .setSize(2, 2)
            .print('记录报告')
            .setSize(0, 0)
            .print()
            .setAlign('lt');
      methods: {
         // 打印
         printerJobs.print(printerUtil.fillLine());
         // 结尾
         printerJobs
            .println()
            .print('签名')
            .println()
            .println();
         let buffer = printerJobs.buffer();
         // console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer));
         // 1.并行调用多次会存在写失败的可能性
         // 2.建议每次写入不超过20字节
         // 分包处理,延时调用
         const maxChunk = 20;
         const delay = 40;
         console.log(111111);
         for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
            let subPackage = buffer.slice(i, i + maxChunk <= length ? i + maxChunk : length);
            // subPackage:参数
            setTimeout(this._writeBLECharacteristicValue, j * delay, subPackage);
         }
         console.log(22222);
      },
      // 向低功耗蓝牙设备特征值中写入二进制数据。注意:必须设备的特征值支持 write 才可以成功调用。
      _writeBLECharacteristicValue(buffer) {
         console.log('写入数据');
         uni.writeBLECharacteristicValue({
            deviceId: this._deviceId, // 蓝牙设备 id
            serviceId: this._serviceId, // 蓝牙特征值对应服务的 uuid
            characteristicId: this._characteristicId, // 蓝牙特征值的 uuid
            value: buffer, // 蓝牙设备特征值对应的二进制值
            success(res) {
               console.log('writeBLECharacteristicValue success', res);
            },
            fail(res) {
               console.log('writeBLECharacteristicValue fail', res);
         toPrint() {
            let that = this
            uni.navigateTo({
               url: "../print/printUNI",
               success: function(res) {
                  // 通过eventChannel向被打开页面传送数据   向另外一个页面传递值的
                  res.eventChannel.emit('data1', {
                     data: that.mat,
                     time: that.time
                  })
               },
               events: {
                  // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据  另外一个页面传过来的
                  acceptDataFromOpenedPage: function(data) {
                     that.matnr = data.data
                  },
               },
            });
         },
         //**生成二维码**//
         qrFun(text) {
            this.qrShow = true
            uQRCode.make({
               canvasId: 'qrcode',
               componentInstance: this,
               text: text,
               size: 150,
               margin: 0,
               backgroundColor: '#ffffff',
               foregroundColor: '#000000',
               fileType: 'jpg',
               errorCorrectLevel: uQRCode.errorCorrectLevel.H,
               success: res => {}
            })
         },
         // 日历
         getDate() {
            var dt = new Date();
            var year,month,day,hours,minutes,seconds,weeks
            year = dt.getFullYear();
            month = (dt.getMonth()+1) < 10 ? '0'+ (dt.getMonth()+1) : (dt.getMonth()+1);
            day = dt.getDate() < 10 ? '0'+dt.getDate() : dt.getDate();
            hours = dt.getHours() < 10 ? '0' + dt.getHours() : dt.getHours();
            minutes = dt.getMinutes() < 10 ? '0' + dt.getMinutes() : dt.getMinutes();
            seconds = dt.getSeconds() < 10 ? '0' + dt.getSeconds() : dt.getSeconds();
            weeks = dt.getDay();
            switch (weeks) {
               case 0: weeks = "星期日"; break;
               case 1: weeks = "星期一"; break;
               case 2: weeks = "星期二"; break;
               case 3: weeks = "星期三"; break;
               case 4: weeks = "星期四"; break;
               case 5: weeks = "星期五"; break;
               default : weeks = "星期六";
            }
         });
            this.time = year + "年" + month + "月" + day + "日 " + hours + ":" + minutes + ":" + seconds + " "
         },
      }
   }
};
</script>
<style scoped lang="scss">
.page {
   margin: 20rpx;
   color: #323232;
   background-color: #f5f9ff;
   height: 100vh;
}
.title {
   font-weight: 600;
   margin: 20rpx 0rpx;
}
.list {
   .item {
<style>
   .print-model {
      width: 100%;
      /* background-color: #555555; */
      display: flex;
      justify-content: space-between;
      padding: 10rpx 20rpx;
      height: 60rpx;
      line-height: 60rpx;
      background-color: #ffffff;
      margin-bottom: 4rpx;
      align-items: center;
      justify-content: center;
   }
   .right {
   .display {
      width: 96%;
      height: 96%;
      border-radius: 5px;
      background-color: #FFF;
      box-shadow: #bdbdbd;
      display: flex;
      align-items: center;
      justify-content: center;
   }
   .no-devices {
      height: 400rpx;
      font-size: 32rpx;
      line-height: 400rpx;
   .display-pak {
      margin: 2%;
      height: 92%;
      border: 1px solid #8a8a8a;
   }
   table {
      width: 92%;
      height: 92%;
      border: 0;
      border-collapse: collapse;
   }
   td {
      border: 1px solid #8a8a8a;
      text-align: center;
      color: #969696;
   }
}
.font-color-3 {
   color: #1a8cff;
}
.submit {
   background-color: #4d88ff !important;
   color: #f5f9ff !important;
}
.disabled {
   background-color: #66b1ff !important;
}
</style>