赞
踩
更多文章请访问 深的个人博客
最近开发的一个小程序里需要对接热敏打印机打印小票,在此记录一下对接的过程
项目开发注意点:
1、因为项目中有多个页面的数据是需要进行打印的,为了保持蓝牙的连接状态和数据,所以连接蓝牙的操作和数据会在vuex里面进行统一管理。
2、打印模板会统一进行管理
3、打印数据前需要对上一次打印的数据进行清理 使用 printerJobs 对象里的 clear() 方法实现清理数据
4、在原有的sdk上增加三列打印的方法
uni-app
只展示主要项目结构
/** * 连接蓝牙 */ function inArray(arr, key, val) { for (let i = 0; i < arr.length; i++) { if (arr[i][key] === val) { return i } } return -1 } export default { namespaced: true, // 开启命名空间 state: { devices: [], // 搜索到的蓝牙设备 connected: false, // 是否连接 discoveryStarted: false, // 是否开始搜索蓝牙 name: "", // 连接到的蓝牙设备名称 deviceId: "", // 连接到的蓝牙设备的deviceId canWrite: false, _deviceId: "", // 连接到的蓝牙设备的deviceId _serviceId: "", // 连接到的蓝牙设备的seviceId _characteristicId: "", // 连接到的蓝牙设备的characteristicId }, getters: { getDevices: state => state.devices, getName: state => state.name, getConnected: state => state.connected, getDiscoveryStarted: state => state.discoveryStarted, getConnectDeviceId: state => state._deviceId, getServiceId: state => state._serviceId, getCharacteristicId: state => state._characteristicId }, mutations: { // 初始化连接 initConnect(state) { state.devices = [] if (!uni.openBluetoothAdapter) { uni.showModal({ title: '提示', content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。' }) return } uni.openBluetoothAdapter({ success: (res) => { console.log('openBluetoothAdapter success', res) this.commit('connect/startBluetoothDevicesDiscovery') }, fail: (res) => { console.log('openBluetoothAdapter fail', res) if (res.errCode === 10001) { uni.showModal({ title: '错误', content: '未找到蓝牙设备, 请打开蓝牙后重试。', showCancel: false }) uni.onBluetoothAdapterStateChange((res) => { console.log('onBluetoothAdapterStateChange', res) if (res.available) { // 取消监听,否则stopBluetoothDevicesDiscovery后仍会继续触发onBluetoothAdapterStateChange, // 导致再次调用startBluetoothDevicesDiscovery uni.onBluetoothAdapterStateChange(() => {}); this.commit('connect/startBluetoothDevicesDiscovery') } }) } } }) uni.onBLEConnectionStateChange((res) => { // 该方法回调中可以用于处理连接意外断开等异常情况 console.log('onBLEConnectionStateChange', `device ${res.deviceId} state has changed, connected: ${res.connected}`) // this.setData({ // connected: res.connected // }) state.connected = res.connected if (!res.connected) { uni.showModal({ title: '错误', content: '蓝牙连接已断开', showCancel: false }) } }); }, getBluetoothAdapterState(state) { uni.getBluetoothAdapterState({ success: (res) => { console.log('getBluetoothAdapterState', res) if (res.discovering) { this.commit('connect/onBluetoothDeviceFound') } else if (res.available) { this.commit('connect/startBluetoothDevicesDiscovery') } } }) }, // 开启蓝牙搜索 startBluetoothDevicesDiscovery(state) { if (state.discoveryStarted) { return } state.discoveryStarted = true uni.startBluetoothDevicesDiscovery({ success: (res) => { this.commit('connect/onBluetoothDeviceFound') }, fail: (res) => { console.log('startBluetoothDevicesDiscovery fail', res) } }) }, // 停止搜索蓝牙 stopBluetoothDevicesDiscovery(state) { uni.stopBluetoothDevicesDiscovery({ complete: () => { console.log('complete,stopBluetoothDevicesDiscovery') state.discoveryStarted = false console.log(this.discoveryStarted) } }) }, // 搜索蓝牙 onBluetoothDeviceFound(state) { uni.onBluetoothDeviceFound((res) => { console.log("搜索到的蓝牙", res.devices) res.devices.forEach(device => { if (!device.name && !device.localName) { return } const idx = inArray(state.devices, 'deviceId', device.deviceId) if (idx === -1) { state.devices.push(device) } }) }) }, // 连接蓝牙 1 createBLEConnection(state, item) { console.log("连接的设备", item) this.commit("connect/next_createBLEConnection", { deviceId: item.deviceId, name: item.name }) }, // 连接蓝牙 2 next_createBLEConnection(state, equipment) { let { deviceId, name } = equipment uni.showLoading() uni.createBLEConnection({ deviceId, success: () => { console.log('createBLEConnection success'); state.name = name state.connected = true state.deviceId = deviceId console.log("连接的设备", state.name) this.commit("connect/getBLEDeviceServices", deviceId) uni.setStorageSync('LAST_CONNECTED_DEVICE', name + ":" + deviceId) }, complete() { uni.hideLoading() }, fail: (res) => { console.log('createBLEConnection fail', res) } }) this.commit("connect/stopBluetoothDevicesDiscovery") }, // 断开蓝牙连接 closeBLEConnection(state) { uni.closeBLEConnection({ deviceId: state.deviceId }) state.connected = false state.canWrite = false state.deviceId = "" state._deviceId= "" state._serviceId= "" state._characteristicId= "" }, // 获取蓝牙服务 getBLEDeviceServices(state, 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) this.commit("connect/getBLEDeviceCharacteristics", { deviceId, serviceId: res.services[i].uuid }) return } } } }) }, getBLEDeviceCharacteristics(state, idObject) { let { deviceId, serviceId } = idObject uni.getBLEDeviceCharacteristics({ deviceId, serviceId, success: (res) => { console.log('getBLEDeviceCharacteristics success', res.characteristics) // 这里会存在特征值是支持write,写入成功但是没有任何反应的情况 // 只能一个个去试 for (let i = 0; i < res.characteristics.length; i++) { const item = res.characteristics[i] if (item.properties.write) { // this.setData({ // canWrite: true // }) state.canWrite = true state._deviceId = deviceId state._serviceId = serviceId state._characteristicId = item.uuid break; } } }, fail(res) { console.error('getBLEDeviceCharacteristics', res) } }) }, closeBluetoothAdapter(state) { uni.closeBluetoothAdapter() state.discoveryStarted = false console.log("关闭蓝牙") }, }, actions: { } }
打印数据:页面传递过来的要打印的数据是一个对象,为了避免数据没有及时更新的问题,所以存储这个对象用的是一个数组(printData),这个打印数据会传递到打印模板 (template.js) 中
打印类型 :每个页面都对应一个打印的模板,这个模板存储在 print/printTheTemplat/template.js 文件中,打印的时候会根据传递的打印类型打印相应的模板
/** * 打印的相关数据 */ export default { namespaced: true, state: { printType: "", // 打印类型 printData: [], // 打印的数据 }, getters: { // 获取打印类型 getPrintType: state => state.printType, // 获取打印数据 getPrintData: state => state.printData }, mutations: { // 更新打印数据和打印类型 updatePrintData(state, printObj) { let { printData, printType } = printObj console.log("接收到的数据", printObj) state.printType = printType state.printData = [] state.printData.push(printData) } }, actions: { } }
// 打印的常量
export const REGISTRATION = "registration" // 退款单/收款单
export const CARSALES = "carSales" // 车销单
export const INVENTORY = "inventory" // 盘点详情
export const DAILY = "daily" // 销售日报
export const CUSTOMER = "customer" //客户汇总
export const COMMODITY = "commodity" // 商品汇总
export const STOCK = "stock" // 库存汇总
// 模板 // printerJobs // .print('2018年12月5日17:34') // .print(printerUtil.fillLine()) // .setAlign('ct') // .setSize(2, 2) // .print('#20饿了么外卖') // .setSize(1, 1) // .print('切尔西Chelsea') // .setSize(2, 2) // .print('在线支付(已支付)') // .setSize(1, 1) // .print('订单号:5415221202244734') // .print('下单时间:2017-07-07 18:08:08') // .setAlign('lt') // .print(printerUtil.fillAround('一号口袋')) // .print(printerUtil.inline('意大利茄汁一面 * 1', '15.00')) // .print(printerUtil.fillAround('其他')) // .print('餐盒费:1') // .print('[赠送康师傅冰红茶] * 1') // .print(printerUtil.fillLine()) // .setAlign('rt') // .print('原价:¥16.00') // .print('总价:¥16.00') // .setAlign('lt') // .print(printerUtil.fillLine()) // .print('备注') // .print("无") // .print(printerUtil.fillLine()) // .println(); import { REGISTRATION, CARSALES, INVENTORY, DAILY, CUSTOMER, COMMODITY, STOCK } from "../../utils/pritConstant.js" const PrinterJobs = require('../sdk/printer/printerjobs.js') const printerUtil = require('../sdk/printer/printerutil') let printerJobs = new PrinterJobs(); export default { // 收款单 [REGISTRATION]: (array) => { console.log("打印接收的数据", array) let data = array[0] let prefix = "" data.order_type == 1 ? prefix = "收款" : prefix = "退款" printerJobs .setAlign('ct') .setSize(2, 2) .print(`${prefix}单`) .lineFeed() .setSize(1, 1) .setAlign('lt') .print(printerUtil.inline(`${prefix}单号`, data.pay_sn)) .print(printerUtil.inline('客户名称', data.client_name)) .print(printerUtil.fillLine()) if (data.order_type == 1) { printerJobs.print(printerUtil.inline(`${prefix}类型`, data.pay_type)) } printerJobs.print(printerUtil.inline(`${prefix}金额`, data.pay_money)) .print(printerUtil.inline('优惠金额', data.dicount_money)) .print(printerUtil.inline(`${prefix}方式`, data.pay_method)) .print(printerUtil.inline(`${prefix}时间`, data.pay_time)) .print(printerUtil.fillLine()) .print(printerUtil.inline('经办人', data.operator)) .print(printerUtil.inline('提交人', data.userName)) .print(printerUtil.inline('提交日期', data.created_at)) .print(printerUtil.fillLine()) .print('审批历程') data.log_list.forEach(item => { printerJobs.print(item.username + '' + item.contents) }) printerJobs.print(printerUtil.doubleFillLine()) .print('业代签字') .lineFeed(2) .println(); return { buffer: printerJobs.buffer(), printerJobs }; }, // 车销单 [CARSALES]: (array) => { let data = array[0] printerJobs .setAlign('ct') .setSize(2, 2) .print('车销单') .lineFeed() .setSize(1, 1) .setAlign('lt') .print(printerUtil.inline('客户名称', data.shopClient.username)) .setBold(false) .print(printerUtil.inline('状态', data.status_name)) .print(printerUtil.inline('销售单编号', data.order_sn)) .print(printerUtil.inline('提交日期', data.created_at)) .print(printerUtil.inline('客户经理', data.member.username)) .print(printerUtil.doubleFillLine()) .print(printerUtil.inline('销售清单', `共${data.products_list.length}种`)) data.products_list.forEach(item => { printerJobs.print(item.product_name) .print(printerUtil.inline(` 数量:${item.num}`, `单价:${item.price}`)) .print(` 金额:${(item.price * 1 * item.num)}`) }) printerJobs.print(printerUtil.fillLine()) .print(printerUtil.inline('销售金额', `${data.pay_money}`)) .print(printerUtil.inline('退货金额', `${ data.refuned_money}`)) .print(printerUtil.inline('本单应收', `${data.remain_money}`)) .print(printerUtil.fillLine()) .print('收款记录') .print(printerUtil.inline('记录数量', `${data.log_list.length}`)) // .print(printerUtil.inline('收款核销', '230.00')) // .print(printerUtil.inline('欠款', '230.00')) .print(printerUtil.doubleFillLine()) .print('业代签字') .lineFeed(2) .println(); return { buffer: printerJobs.buffer(), printerJobs }; }, // 盘点详情 [INVENTORY]: (array) => { let data = array[0] let { products_list, log_list } = data let status = "" data.status == 0 ? status = "待审批" : data.status == 1 ? status = "已通过" : status = "作废" let range = data.order_type && data.order_type == 2 ? "部分盘点" : "全部盘点" printerJobs .setAlign('ct') .setSize(2, 2) .print('盘点详情') .lineFeed() .setSize(1, 1) .setAlign('lt') .print(printerUtil.inline('盘点单号', `${data.order_sn}`)) .print(printerUtil.inline('盘点人员', `${data.member.username}`)) .print(printerUtil.inline('状态', `${status}`)) .print(printerUtil.inline('盘点范围', `${range}`)) .print(printerUtil.inline('提交日期', `${data.created}`)) .print(printerUtil.fillLine()) .print("商品清单") products_list.forEach(item => { printerJobs.print(`${item.product_name}`) .print(printerUtil.inline(` 账面:${item.num}`, `实盘:${item.diff_num}`)) }) if (log_list.length > 0) { printerJobs.print(printerUtil.fillLine()).print('审批历程') log_list.forEach(item => { printerJobs.print(`${item.username} ${item.created_at} [${item.contents}]`) }) } else { printerJobs.print(printerUtil.fillLine()).print('审批历程(暂无)') } printerJobs.print(printerUtil.doubleFillLine()) .print('业代签字') .lineFeed(2) .println(); return { buffer: printerJobs.buffer(), printerJobs }; }, // 日报汇总 [DAILY]: (array) => { let data = array[0] printerJobs .setAlign('ct') .setSize(2, 2) .print('销售日报') .lineFeed() .setSize(1, 1) .setAlign('lt') .setUnderline(true) .print(`日期:${data.date}`) .print(printerUtil.doubleFillLine()) .setUnderline(false) .print(printerUtil.inline('销售金额', `${data.incomeTotal}`)) .print(printerUtil.inline('其中:销售金额', `${data.salesTotal}`)) .print(printerUtil.inline(' 退货金额', `${data.returndTotal}`)) .print(printerUtil.fillLine()) .print(printerUtil.inline('应收金额', `${data.remainTotal}`)) .print(printerUtil.fillLine()) .print(printerUtil.inline('收款金额', `${data.payTotal}`)) .print(printerUtil.inline('收款优惠', `${data.dicountTotal}`)) .print(printerUtil.inline('支出费用', `${data.debtTotal}`)) .print(printerUtil.fillLine()) .print(`打印时间:${format(new Date(),"full")}`) .print(printerUtil.doubleFillLine()) .print('业代签字') .lineFeed() .println(); return { buffer: printerJobs.buffer(), printerJobs }; }, // 库存汇总 [STOCK]: array => { printerJobs .setAlign('ct') .setSize(2, 2) .print('库存汇总') .lineFeed() .setSize(1, 1) .setAlign('lt') .setUnderline(true) .print('日期:2021-07-19 仓库:一号仓库') .print(printerUtil.doubleFillLine()) .print(printerUtil.inline('正常品清单', '共0家')) .print(printerUtil.fillLine()) .print(printerUtil.centerInline('白酒商品名称', '库存量', '金额')) .print(printerUtil.centerInline('白酒', '2000', '0.35')) .print(printerUtil.centerInline('白酒', '2000', '5000')) .print(printerUtil.centerInline('燕京330吉祥红佳节订单', '1000', '7000')) .print(printerUtil.fillLine()) .print(printerUtil.inline('合计', '0.35')) .print('打印时间:2021-07-19 17:34') .print('业务员:张三') .print(printerUtil.doubleFillLine()) .print('业代签字') .lineFeed() .lineFeed() .println(); return { buffer: printerJobs.buffer(), printerJobs }; } } // 时间处理 function format(shijianchuo, type) { //shijianchuo是整数,否则要parseInt转换 var time = new Date(shijianchuo); var y = time.getFullYear(); var m = time.getMonth() + 1; var d = time.getDate(); var h = time.getHours(); var mm = time.getMinutes(); var s = time.getSeconds(); if (type == "full") { return y + '-' + add0(m) + '-' + add0(d) + ' ' + add0(h) + ':' + add0(mm) + ':' + add0(s); } else { return y + '-' + add0(m) + '-' + add0(d); } } function add0(m) { return m < 10 ? '0' + m : m }
具体sdk可以下载 github上的代码,这里只展示在printerutil.js文件中添加的几个方法
/** * 一排三列 * 同一行输出str1, str2,str3,str1居左, str2居中偏右,str3居右 * @param {string} str1 内容1 固定宽度 占可打印宽度的3/5 * @param {string} str2 内容2 * @param {string} str3 内容3 * @param {number} fontWidth 字符宽度 1/2 * @param {string} fillWith str1 str2之间的填充字符 * */ function centerInline(str1, str2, str3, fillWith = ' ', fontWidth = 1) { const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth; let newStr1 = setString(str1, 14) console.log("截取的字符", newStr1) console.log("newStr1的字符长度", getStringWidth(newStr1)) // 需要填充的字符数量 let fillCount = lineWidth - (getStringWidth(newStr1) + getStringWidth(str2) + getStringWidth(str3)) % lineWidth; let leftWidth = Math.round(lineWidth / 5 * 3); console.log("fillcount", fillCount) console.log("左侧的字符长度", getStringWidth(str1)) let leftCount = leftWidth - getStringWidth(newStr1) % lineWidth let rightCount = fillCount - leftCount let lefFillStr = new Array(leftCount).fill(fillWith.charAt(0)).join(''); let rightFillStr = new Array(rightCount).fill(fillWith.charAt(0)).join(''); return newStr1 + lefFillStr + str2 + rightFillStr + str3; } // 截取字符串,多余的部分用...代替 function setString(str, len) { var strlen = 0; var s = ""; for (var i = 0; i < str.length; i++) { if (str.charCodeAt(i) > 128) { strlen += 2; } else { strlen++; } s += str.charAt(i); if (strlen >= len) { return s + '...' } } return s; } /** * 用 = 字符填充一整行 * @param {string} fillWith 填充字符 * @param {number} fontWidth 字符宽度 1/2 */ function doubleFillLine(fillWith = '=', fontWidth = 1) { const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth; return new Array(lineWidth).fill(fillWith.charAt(0)).join(''); }
print.vue
注意点:在调用打印或者是退出页面的时候要清理掉上一次打印的数据,这个可以通过 printerJobs 对象里的 clear() 方法实现清理数据, printerJobs 对象会在调用打印模板的时候返回,这个时候我们需要将printerJobs 对象保存在data中
<template> <view class="container"> <view class="page-section"> <view class="devices-summary my-2 flex items-center"> <view>已发现 {{getDevices.length}} 个设备</view> <view class="ml-2" v-if="getDiscoveryStarted"> <u-loading mode="flower"></u-loading> </view> </view> <scroll-view class="device-list" scroll-y scroll-with-animation> <view class="scroll_box mx-3 p-2 px-4" v-if="getDevices.length>0"> <view v-for="(item,index) in getDevices" :key="item.deviceId" @click="connect(item)" class="device-item"> <view class="item_left" style="font-size: 15px; color: #333;">{{item.name}}</view> <view class="item_right" style="font-size: 15px;" v-if="getConnectDeviceId == item.deviceId">已连接 </view> </view> </view> <view class="scroll_box mx-3 p-2 px-4 null_box" v-else> 暂无可连接设备 </view> </scroll-view> <view class="py-4 px-3 w-full"> <view class="info_box p-2 bg-white" v-if="getConnected"> 已连接设备: {{getName}} </view> <view class="info_box p-2 bg-white" v-else> 暂未连接设备 </view> </view> <view class="btn-area"> <view class="btn_box px-4"> <view class="btn_view" type="primary" @click="refreshDiscovery">重新扫描</view> </view> <view class="btn_box px-4"> <view class="btn_view" @click="stopDiscovery" style="margin-top: 10px;">停止扫描</view> </view> </view> </view> <view class="page-section connected-area" v-if="getConnected"> <view class="btn-area"> <view class="btn_box px-4" style="margin-bottom: 10px;margin-top: 10px;"> <view class="btn_view" type="primary" @click="writeBLECharacteristicValue"> 打印 </view> </view> <view class="btn_box px-4"> <view class="btn_view" @click="closeBLEConnection">断开连接</view> </view> </view> </view> </view> </template> <script> const LAST_CONNECTED_DEVICE = 'last_connected_device' const PrinterJobs = require('./sdk/printer/printerjobs') const printerUtil = require('./sdk/printer/printerutil') import printObject from "./printTheTemplate/template.js" import { mapGetters } from "vuex" 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 { data() { return { devices: [], connected: false, discoveryStarted: false, chs: [], name: "", deviceId: "", canWrite: false, lastDevice: "", printerJobs: null } }, computed: { ...mapGetters("print", ['getPrintType', 'getPrintData']), ...mapGetters("connect", ['getDevices', 'getDiscoveryStarted', 'getName', 'getConnected', 'getConnectDeviceId', 'getServiceId', 'getCharacteristicId' ]) }, onShow() { console.log(this.getDiscoveryStarted, this.getConnected) if (!this.getDiscoveryStarted && !this.getConnected) { this.$store.commit("connect/initConnect") } // const lastDevice = uni.getStorageSync(LAST_CONNECTED_DEVICE); // this.lastDevice = lastDevice // if (this.lastDevice) { // this.createBLEConnectionWithDeviceId() // } else { // this.openBluetoothAdapter() // } }, onUnload() { // 清理上一次打印的数据 this.printerJobs && this.printerJobs.clear() }, methods: { connect(item) { // createBLEConnection(item) this.$store.commit("connect/createBLEConnection", item) }, refreshDiscovery() { this.$store.commit("connect/startBluetoothDevicesDiscovery") }, stopDiscovery() { this.$store.commit("connect/stopBluetoothDevicesDiscovery") }, closeBLEConnection(){ this.$store.commit("connect/closeBLEConnection") }, writeBLECharacteristicValue() { if (this.printerJobs) { // 清理上一次打印的数据 this.printerJobs.clear() } let { buffer, printerJobs } = printObject[this.getPrintType](this.getPrintData) this.printerJobs = printerJobs // console.log("buffer", buffer) // console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer)); // 1.并行调用多次会存在写失败的可能性 // 2.建议每次写入不超过20字节 // 分包处理,延时调用 const maxChunk = 20; const delay = 20; 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); setTimeout(this._writeBLECharacteristicValue, j * delay, subPackage); } }, _writeBLECharacteristicValue(buffer) { uni.writeBLECharacteristicValue({ deviceId: this.getConnectDeviceId, serviceId: this.getServiceId, characteristicId: this.getCharacteristicId, value: buffer, success(res) { console.log('writeBLECharacteristicValue success', res) }, fail(res) { console.log('writeBLECharacteristicValue fail', res) } }) }, closeBluetoothAdapter() { uni.closeBluetoothAdapter() this.discoveryStarted = false }, createBLEConnectionWithDeviceId(e) { // 小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备 const device = this.lastDevice if (!device) { return } const index = device.indexOf(':'); const name = device.substring(0, index); const deviceId = device.substring(index + 1, device.length); console.log('createBLEConnectionWithDeviceId', name + ':' + deviceId) uni.openBluetoothAdapter({ success: (res) => { console.log('openBluetoothAdapter success', res) this._createBLEConnection(deviceId, name) }, fail: (res) => { console.log('openBluetoothAdapter fail', res) if (res.errCode === 10001) { uni.showModal({ title: '错误', content: '未找到蓝牙设备, 请打开蓝牙后重试。', showCancel: false }) uni.onBluetoothAdapterStateChange((res) => { console.log('onBluetoothAdapterStateChange', res) if (res.available) { // 取消监听 uni.onBluetoothAdapterStateChange(() => {}); this._createBLEConnection(deviceId, name) } }) } } }) } } } </script> <style lang="scss" scoped> .page-section { display: flex; flex-direction: column; align-items: center; width: 100%; box-sizing: border-box; border-bottom: 2rpx solid #EEE; // padding: 30rpx 0; } .devices-summary { padding: 10rpx; font-size: 30rpx; } .device-list { height: 400rpx; .scroll_box { background: #FAFAFA; height: 400rpx; .device-item { // border-bottom: 1rpx solid #EEE; padding: 20rpx; color: #666; background-color: white; margin: 10upx 0upx; display: flex; justify-content: space-between; align-items: center; .item_left { width: 80%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-right: 20upx; } .item_right { color: #CCCCCC; } } } .null_box { display: flex; justify-content: center; align-items: center; font-size: 28upx; color: #CCCCCC; } } .device-item-hover { background-color: rgba(0, 0, 0, .1); } .btn-area { box-sizing: border-box; width: 100%; // padding: 0 30rpx; } .connected-area { font-size: 22rpx; } .connected-info {} .input-area { background: #fff; margin-top: 10rpx; width: 100%; } .input { font-size: 28rpx; height: 2.58823529em; min-height: 2.58823529em; line-height: 2.58823529em; padding: 10rpx; } .btn_box { width: 100%; display: flex; justify-content: center; align-items: center; .btn_view { width: 100%; height: 80upx; background-color: $colorred; color: white; display: flex; justify-content: center; align-items: center; border-radius: 10upx; font-size: 30upx; } } .info_box { width: 100%; text-align: center; font-size: 28upx; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。