0602
This commit is contained in:
@@ -0,0 +1,570 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 状态栏 -->
|
||||
<view class="status-section">
|
||||
<view class="status-item">
|
||||
<text class="status-label">蓝牙适配器</text>
|
||||
<text class="status-value" :class="adapterState.available ? 'available' : ''">
|
||||
{{ adapterState.available ? '就绪' : '未就绪' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="status-item">
|
||||
<text class="status-label">打印机</text>
|
||||
<text class="status-value" :class="{ connected: connected }">
|
||||
{{ connected ? '已连接' : '未连接' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="status-item">
|
||||
<text class="status-label">连接方式</text>
|
||||
<text class="status-value auto">自动</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 连接信息 -->
|
||||
<view class="section" v-if="savedConfig">
|
||||
<view class="section-header">
|
||||
<text class="section-title">已保存的配置</text>
|
||||
</view>
|
||||
<view class="config-info">
|
||||
<view class="config-row">
|
||||
<text class="config-label">设备名称</text>
|
||||
<text class="config-value">{{ savedConfig.deviceName }}</text>
|
||||
</view>
|
||||
<view class="config-row">
|
||||
<text class="config-label">服务UUID</text>
|
||||
<text class="config-value uuid">{{ savedConfig.serviceId }}</text>
|
||||
</view>
|
||||
<view class="config-row">
|
||||
<text class="config-label">特征值UUID</text>
|
||||
<text class="config-value uuid">{{ savedConfig.writeCharId }}</text>
|
||||
</view>
|
||||
<view class="config-row" v-if="savedConfig.lastUpdated">
|
||||
<text class="config-label">保存时间</text>
|
||||
<text class="config-value">{{ formatDate(savedConfig.lastUpdated) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="config-actions">
|
||||
<button type="warn" size="mini" @click="clearConfig">清除配置</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 无配置提示 -->
|
||||
<view class="section empty-section" v-else>
|
||||
<text class="empty-text">暂无保存的配置</text>
|
||||
<text class="empty-hint">请先在蓝牙打印页面连接打印机并保存配置</text>
|
||||
<button type="primary" size="mini" @click="goToBlePrint">前往配置</button>
|
||||
</view>
|
||||
|
||||
<!-- 打印控制区 -->
|
||||
<view class="section print-section" v-if="connected">
|
||||
<view class="section-header">
|
||||
<text class="section-title">打印控制</text>
|
||||
<text class="printer-name">{{ connectedDeviceName }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 指令类型选择 -->
|
||||
<view class="command-type">
|
||||
<view class="type-label">指令类型:</view>
|
||||
<view class="type-switch">
|
||||
<view
|
||||
class="type-btn"
|
||||
:class="{ active: commandType === 'CPCL' }"
|
||||
@click="commandType = 'CPCL'">
|
||||
CPCL
|
||||
</view>
|
||||
<view
|
||||
class="type-btn"
|
||||
:class="{ active: commandType === 'TSPL' }"
|
||||
@click="commandType = 'TSPL'">
|
||||
TSPL
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 打印内容 -->
|
||||
<view class="print-content">
|
||||
<view class="content-header">
|
||||
<text class="content-title">打印内容</text>
|
||||
<view class="content-actions">
|
||||
<button size="mini" @click="clearContent">清空</button>
|
||||
<button size="mini" type="primary" @click="doPrint">打印</button>
|
||||
</view>
|
||||
</view>
|
||||
<textarea
|
||||
class="content-textarea"
|
||||
v-model="printContent"
|
||||
:placeholder="contentPlaceholder">
|
||||
</textarea>
|
||||
</view>
|
||||
|
||||
<!-- 快捷模板 -->
|
||||
<view class="template-section">
|
||||
<text class="template-title">快捷模板</text>
|
||||
<scroll-view class="template-list" scroll-x>
|
||||
<view class="template-tags">
|
||||
<view class="template-tag" @click="useTemplate('qrcode')">二维码</view>
|
||||
<view class="template-tag" @click="useTemplate('barcode')">条码</view>
|
||||
<view class="template-tag" @click="useTemplate('label')">标签</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 连接中状态 -->
|
||||
<view class="section connecting-section" v-else-if="savedConfig && isConnecting">
|
||||
<view class="connecting-content">
|
||||
<view class="loading-icon"></view>
|
||||
<text class="connecting-text">正在自动连接...</text>
|
||||
<text class="connecting-hint">{{ savedConfig.deviceName }}</text>
|
||||
</view>
|
||||
<button type="default" size="mini" @click="cancelConnect">取消</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as iconv from 'iconv-lite';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
adapterState: {
|
||||
available: false,
|
||||
discovering: false
|
||||
},
|
||||
isConnecting: false,
|
||||
savedConfig: null,
|
||||
connectedDeviceId: '',
|
||||
connectedDeviceName: '',
|
||||
connected: false,
|
||||
writeServiceId: '',
|
||||
writeCharacteristicId: '',
|
||||
|
||||
commandType: 'CPCL',
|
||||
printContent: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
contentPlaceholder() {
|
||||
const placeholders = {
|
||||
'TSPL': '输入TSPL指令,如:\nSIZE 50 mm 30 mm\nGAP 2 mm\nCLS\nTEXT 50 50 "4" 0 1 1 "Hello"\nPRINT',
|
||||
'CPCL': '输入CPCL指令,如:\n! 0 200 200 240 1\nSIZE 50mm 30mm\nGAP 2mm\nTEXT 4 0 10 10 EN Hello\nPRINT'
|
||||
}
|
||||
return placeholders[this.commandType]
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.loadConfig()
|
||||
},
|
||||
onUnload() {
|
||||
this.cleanup()
|
||||
},
|
||||
methods: {
|
||||
formatDate(dateStr) {
|
||||
const date = new Date(dateStr)
|
||||
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
|
||||
},
|
||||
loadConfig() {
|
||||
const config = uni.getStorageSync('blePrintAutoConfig')
|
||||
if (config) {
|
||||
this.savedConfig = config
|
||||
setTimeout(() => {
|
||||
this.autoConnect()
|
||||
}, 500)
|
||||
}
|
||||
},
|
||||
clearConfig() {
|
||||
uni.removeStorageSync('blePrintAutoConfig')
|
||||
this.savedConfig = null
|
||||
uni.showToast({ title: '配置已清除', icon: 'success' })
|
||||
},
|
||||
goToBlePrint() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/testpages/bleprint'
|
||||
})
|
||||
},
|
||||
async autoConnect() {
|
||||
if (!this.savedConfig) return
|
||||
|
||||
this.isConnecting = true
|
||||
|
||||
try {
|
||||
await this.initBluetooth()
|
||||
await this.createConnection()
|
||||
|
||||
this.connected = true
|
||||
this.connectedDeviceId = this.savedConfig.deviceId
|
||||
this.connectedDeviceName = this.savedConfig.deviceName
|
||||
this.writeServiceId = this.savedConfig.serviceId
|
||||
this.writeCharacteristicId = this.savedConfig.writeCharId
|
||||
this.isConnecting = false
|
||||
uni.showToast({ title: '连接成功', icon: 'success' })
|
||||
|
||||
} catch (err) {
|
||||
this.isConnecting = false
|
||||
uni.showToast({ title: '连接失败', icon: 'none' })
|
||||
}
|
||||
},
|
||||
initBluetooth() {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.openBluetoothAdapter({
|
||||
success: () => {
|
||||
this.adapterState.available = true
|
||||
uni.onBLEConnectionStateChange((res) => {
|
||||
if (!res.connected && this.connectedDeviceId === res.deviceId) {
|
||||
this.connected = false
|
||||
this.connectedDeviceId = ''
|
||||
this.connectedDeviceName = ''
|
||||
}
|
||||
})
|
||||
resolve()
|
||||
},
|
||||
fail: (err) => {
|
||||
this.adapterState.available = false
|
||||
// 检测蓝牙是否未打开
|
||||
if (err.errMsg && (err.errMsg.includes('not available') || err.errMsg.includes('available'))) {
|
||||
uni.showModal({
|
||||
title: '蓝牙未开启',
|
||||
content: '请先开启手机蓝牙,然后重试',
|
||||
confirmText: '重试',
|
||||
cancelText: '取消',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 延迟重试
|
||||
setTimeout(() => {
|
||||
this.autoConnect()
|
||||
}, 300)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
createConnection() {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.createBLEConnection({
|
||||
deviceId: this.savedConfig.deviceId,
|
||||
timeout: 15000,
|
||||
success: () => {
|
||||
resolve()
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
cancelConnect() {
|
||||
this.isConnecting = false
|
||||
},
|
||||
disconnectPrinter() {
|
||||
if (!this.connectedDeviceId) return
|
||||
uni.closeBLEConnection({
|
||||
deviceId: this.connectedDeviceId,
|
||||
success: () => {
|
||||
this.connected = false
|
||||
this.connectedDeviceId = ''
|
||||
this.connectedDeviceName = ''
|
||||
}
|
||||
})
|
||||
},
|
||||
clearContent() {
|
||||
this.printContent = ''
|
||||
},
|
||||
useTemplate(type) {
|
||||
const templates = {
|
||||
qrcode: {
|
||||
CPCL: '! 0 200 200 240 1\nSIZE 50mm 30mm\nGAP 2mm\nCENTER\nQR 300 10 M 2 A 0\nMA,https://www.example.com\nENDQR\nPRINT',
|
||||
TSPL: 'SIZE 50 mm 30 mm\nGAP 2 mm\nCLS\nQRCODE 50 50 L 5 0 A 0 "https://www.example.com"\nPRINT'
|
||||
},
|
||||
barcode: {
|
||||
CPCL: '! 0 200 200 240 1\nSIZE 50mm 30mm\nGAP 2mm\nCENTER\nBARCODE 128 1 1 60 1 0 10 40 1234567890\nPRINT',
|
||||
TSPL: 'SIZE 50 mm 30 mm\nGAP 2 mm\nCLS\nBARCODE 50 50 "128" 50 1 0 2 2 "1234567890"\nPRINT'
|
||||
},
|
||||
label: {
|
||||
CPCL: '! 0 200 200 400 1\nSIZE 50mm 80mm\nGAP 2mm\nCENTER\nTEXT 4 0 10 20 EN Product Name\nTEXT 4 0 10 60 EN Price: $99.00\nQR 300 120 M 2 A 0\nMA,https://example.com\nENDQR\nBARCODE 128 1 1 60 1 0 10 200 12345678\nPRINT',
|
||||
TSPL: 'SIZE 50 mm 80 mm\nGAP 2 mm\nCLS\nTEXT 20 20 "4" 0 1 1 "Product Name"\nTEXT 20 60 "4" 0 1 1 "Price: $99.00"\nQRCODE 50 100 L 5 0 A 0 "https://example.com"\nBARCODE 20 160 "128" 50 1 0 2 2 "12345678"\nPRINT'
|
||||
}
|
||||
}
|
||||
this.printContent = templates[type][this.commandType]
|
||||
},
|
||||
stringToBuffer(str) {
|
||||
try {
|
||||
const uint8Array = iconv.encode(str, 'gbk');
|
||||
return uint8Array.buffer;
|
||||
} catch (e) {
|
||||
console.warn('编码失败,使用回退方案', e)
|
||||
const buffer = new ArrayBuffer(str.length)
|
||||
const dataView = new DataView(buffer)
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
dataView.setUint8(i, str.charCodeAt(i) & 0xFF)
|
||||
}
|
||||
return buffer
|
||||
}
|
||||
},
|
||||
doPrint() {
|
||||
if (!this.connected) {
|
||||
uni.showToast({ title: '请先连接打印机', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!this.printContent.trim()) {
|
||||
uni.showToast({ title: '请输入打印内容', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!this.writeCharacteristicId) {
|
||||
uni.showToast({ title: '未配置特征值', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const buffer = this.stringToBuffer(this.printContent)
|
||||
uni.writeBLECharacteristicValue({
|
||||
deviceId: this.connectedDeviceId,
|
||||
serviceId: this.writeServiceId,
|
||||
characteristicId: this.writeCharacteristicId,
|
||||
value: buffer,
|
||||
writeType: 'writeNoResponse',
|
||||
success: () => {
|
||||
uni.showToast({ title: '打印成功', icon: 'success' })
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.showToast({ title: '发送失败', icon: 'none' })
|
||||
}
|
||||
})
|
||||
},
|
||||
cleanup() {
|
||||
if (this.connectedDeviceId) {
|
||||
uni.closeBLEConnection({
|
||||
deviceId: this.connectedDeviceId
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
background: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.status-section {
|
||||
display: flex;
|
||||
background: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.status-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.status-label {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
.status-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
}
|
||||
.status-value.available {
|
||||
color: #007aff;
|
||||
}
|
||||
.status-value.connected {
|
||||
color: #34c759;
|
||||
}
|
||||
.status-value.auto {
|
||||
color: #ff9500;
|
||||
}
|
||||
.section {
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.printer-name {
|
||||
font-size: 24rpx;
|
||||
color: #34c759;
|
||||
}
|
||||
.config-info {
|
||||
background: #f8f8f8;
|
||||
border-radius: 8rpx;
|
||||
padding: 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.config-row {
|
||||
display: flex;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.config-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.config-label {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
min-width: 140rpx;
|
||||
}
|
||||
.config-value {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
.config-value.uuid {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 22rpx;
|
||||
word-break: break-all;
|
||||
}
|
||||
.config-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.empty-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 60rpx 20rpx;
|
||||
}
|
||||
.empty-text {
|
||||
font-size: 30rpx;
|
||||
color: #666;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.empty-hint {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-bottom: 32rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.print-section {
|
||||
min-height: 400rpx;
|
||||
}
|
||||
.command-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.type-label {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
.type-switch {
|
||||
display: flex;
|
||||
border: 1rpx solid #007aff;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.type-btn {
|
||||
padding: 12rpx 24rpx;
|
||||
font-size: 24rpx;
|
||||
color: #007aff;
|
||||
background: #fff;
|
||||
}
|
||||
.type-btn.active {
|
||||
background: #007aff;
|
||||
color: #fff;
|
||||
}
|
||||
.print-content {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.content-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.content-title {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
.content-actions {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.content-textarea {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
border: 1rpx solid #ddd;
|
||||
border-radius: 8rpx;
|
||||
padding: 16rpx;
|
||||
font-size: 26rpx;
|
||||
font-family: 'Courier New', monospace;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.template-section {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.template-title {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 12rpx;
|
||||
display: block;
|
||||
}
|
||||
.template-list {
|
||||
width: 100%;
|
||||
}
|
||||
.template-tags {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
padding: 4rpx;
|
||||
}
|
||||
.template-tag {
|
||||
padding: 12rpx 24rpx;
|
||||
background: #f0f0f0;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
.template-tag:active {
|
||||
background: #e0e0e0;
|
||||
}
|
||||
.connecting-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 60rpx 20rpx;
|
||||
}
|
||||
.connecting-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
.loading-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border: 4rpx solid #007aff;
|
||||
border-top-color: transparent;
|
||||
border-radius: 50%;
|
||||
animation: rotate 1s linear infinite;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
@keyframes rotate {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.connecting-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
.connecting-hint {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 步骤1:扫描设备 -->
|
||||
<button @click="startScan">1. 扫描蓝牙设备</button>
|
||||
<view v-if="devices.length">
|
||||
<view v-for="device in devices" :key="device.deviceId" class="device-item" @click="selectDevice(device)">
|
||||
<text>{{ device.name || '未知设备' }}</text>
|
||||
<text class="mac">{{ device.deviceId }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 步骤2:连接后展示服务 -->
|
||||
<view v-if="services.length">
|
||||
<text>请选择服务:</text>
|
||||
<view v-for="svc in services" :key="svc.uuid" class="service-item" @click="selectService(svc)">
|
||||
<text>{{ svc.uuid }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 步骤3:选择特征值 -->
|
||||
<view v-if="characteristics.length">
|
||||
<text>请选择写入特征值:</text>
|
||||
<view v-for="char in characteristics" :key="char.uuid" class="char-item" @click="selectWriteChar(char)">
|
||||
<text>{{ char.uuid }} ({{ char.properties.write ? '可写' : '' }})</text>
|
||||
</view>
|
||||
<text>请选择通知特征值(可选):</text>
|
||||
<view v-for="char in characteristics" :key="char.uuid" class="char-item" @click="selectNotifyChar(char)">
|
||||
<text>{{ char.uuid }} ({{ char.properties.notify ? '可通知' : '' }})</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 步骤4:保存配置 -->
|
||||
<button v-if="selectedWriteChar" @click="saveConfiguration">4. 保存配置并测试连接</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import bluetoothManager from '@/utils/BluetoothManager.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
devices: [], // 扫描到的设备列表
|
||||
selectedDeviceId: null,
|
||||
services: [], // 选中设备的服务列表
|
||||
characteristics: [], // 选中服务的特征值列表
|
||||
selectedServiceId: null,
|
||||
selectedWriteChar: null,
|
||||
selectedNotifyChar: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async startScan() {
|
||||
await bluetoothManager.init();
|
||||
this.devices = [];
|
||||
bluetoothManager.setDeviceFoundCallback((device) => {
|
||||
// 避免重复添加
|
||||
if (!this.devices.find(d => d.deviceId === device.deviceId)) {
|
||||
this.devices.push(device);
|
||||
}
|
||||
});
|
||||
await bluetoothManager.startScan();
|
||||
uni.showToast({ title: '扫描中...', icon: 'none' });
|
||||
// 30秒后停止
|
||||
setTimeout(() => bluetoothManager.stopScan(), 30000);
|
||||
},
|
||||
|
||||
async selectDevice(device) {
|
||||
bluetoothManager.stopScan();
|
||||
uni.showLoading({ title: '连接设备中...' });
|
||||
try {
|
||||
const { services, deviceId } = await bluetoothManager.connectForDiscovery(device.deviceId);
|
||||
this.selectedDeviceId = deviceId;
|
||||
this.services = services;
|
||||
this.characteristics = [];
|
||||
this.selectedServiceId = null;
|
||||
this.selectedWriteChar = null;
|
||||
this.selectedNotifyChar = null;
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: '连接成功,请选择服务', icon: 'success' });
|
||||
} catch (err) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: '连接失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
async selectService(service) {
|
||||
this.selectedServiceId = service.uuid;
|
||||
uni.showLoading({ title: '获取特征值...' });
|
||||
try {
|
||||
const chars = await this._getCharacteristics(this.selectedDeviceId, service.uuid);
|
||||
this.characteristics = chars;
|
||||
uni.hideLoading();
|
||||
} catch (err) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: '获取特征值失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
async _getCharacteristics(deviceId, serviceId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getBLEDeviceCharacteristics({
|
||||
deviceId,
|
||||
serviceId,
|
||||
success: (res) => resolve(res.characteristics),
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
selectWriteChar(char) {
|
||||
if (!char.properties.write && !char.properties.writeNoResponse) {
|
||||
uni.showToast({ title: '该特征值不支持写入', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.selectedWriteChar = char.uuid;
|
||||
},
|
||||
|
||||
selectNotifyChar(char) {
|
||||
if (!char.properties.notify && !char.properties.indicate) {
|
||||
uni.showToast({ title: '该特征值不支持通知', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.selectedNotifyChar = char.uuid;
|
||||
},
|
||||
|
||||
async saveConfiguration() {
|
||||
if (!this.selectedWriteChar) {
|
||||
uni.showToast({ title: '请先选择写入特征值', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await bluetoothManager.saveAndConnect(
|
||||
this.selectedDeviceId,
|
||||
this.selectedServiceId,
|
||||
this.selectedWriteChar,
|
||||
this.selectedNotifyChar
|
||||
);
|
||||
// 保存配置到本地
|
||||
const config = {
|
||||
deviceId: this.selectedDeviceId,
|
||||
serviceId: this.selectedServiceId,
|
||||
writeCharId: this.selectedWriteChar,
|
||||
notifyCharId: this.selectedNotifyChar,
|
||||
deviceName: this.devices.find(d => d.deviceId === this.selectedDeviceId)?.name || '',
|
||||
};
|
||||
uni.setStorageSync('bleDeviceConfig', config);
|
||||
uni.showToast({ title: '配置已保存,可返回使用', icon: 'success' });
|
||||
// 可选:跳转到主页面
|
||||
setTimeout(() => uni.navigateBack(), 1500);
|
||||
} catch (err) {
|
||||
console.error('保存失败', err);
|
||||
uni.showToast({ title: '保存失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.device-item, .service-item, .char-item {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.mac {
|
||||
font-size: 12px;
|
||||
color: gray;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,339 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="status-bar">
|
||||
<text>打印机: {{ printerConnected ? '已连接' : '未连接' }}</text>
|
||||
<text v-if="lastPrinterMac && !printerConnected">上次设备: {{ lastPrinterMac }}</text>
|
||||
</view>
|
||||
<view class="status-bar">
|
||||
<text>电子秤: {{ scaleConnected ? '已连接' : '未连接' }}</text>
|
||||
<text>重量: {{ weightValue }} g</text>
|
||||
</view>
|
||||
|
||||
<button type="primary" @click="initAndAutoConnect">启动蓝牙并自动连接</button>
|
||||
<button @click="manualScanPrinter">手动扫描打印机</button>
|
||||
<button @click="manualScanScale">手动扫描电子秤</button>
|
||||
<button @click="printTest">打印测试</button>
|
||||
<button @click="disconnectAll">断开所有连接</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import bluetoothManager from '@/utils/BluetoothManager.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 打印机相关
|
||||
printerDeviceId: null,
|
||||
printerConnected: false,
|
||||
lastPrinterMac: '',
|
||||
// 电子秤相关
|
||||
scaleDeviceId: null,
|
||||
scaleConnected: false,
|
||||
weightValue: '--',
|
||||
// UUID 配置(请替换为实际值)
|
||||
printerServiceUUID: '0000EEE2-0000-1000-8000-00805F9B34FB',
|
||||
printerWriteUUID: '0000EEE3-0000-1000-8000-00805F9B34FB',
|
||||
scaleServiceUUID: 'FFF0',
|
||||
scaleNotifyUUID: 'FFF1',
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
const config = uni.getStorageSync('bleDeviceConfig');
|
||||
if (config && config.deviceId) {
|
||||
this.printerServiceUUID = config.serviceId;
|
||||
this.printerWriteUUID = config.writeCharId;
|
||||
this.lastPrinterMac = config.deviceId;
|
||||
// 如果配置了 notify UUID,也可用于电子秤等
|
||||
this.initAndAutoConnect();
|
||||
} else {
|
||||
// 没有配置,引导用户去配置页面
|
||||
uni.showModal({
|
||||
title: '未配置设备',
|
||||
content: '请先配置蓝牙设备',
|
||||
success: () => {
|
||||
uni.navigateTo({ url: '/pages/testpages/bleconfig' });
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
onUnload() {
|
||||
// 页面卸载时释放所有连接(可选,也可保持连接)
|
||||
bluetoothManager.closeAll();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 初始化蓝牙并自动连接上次的打印机
|
||||
*/
|
||||
async initAndAutoConnect() {
|
||||
try {
|
||||
await bluetoothManager.init();
|
||||
console.log('蓝牙初始化成功');
|
||||
|
||||
// 设置全局回调
|
||||
bluetoothManager.setConnectionChangeCallback(this.onConnectionChange);
|
||||
bluetoothManager.setDataReceivedCallback(this.onDataReceived);
|
||||
|
||||
if (this.lastPrinterMac) {
|
||||
uni.showLoading({ title: '正在连接上次打印机...' });
|
||||
try {
|
||||
const info = await bluetoothManager.connectKnownDevice(
|
||||
this.lastPrinterMac,
|
||||
this.printerServiceUUID,
|
||||
this.printerWriteUUID
|
||||
);
|
||||
this.printerDeviceId = this.lastPrinterMac;
|
||||
this.printerConnected = true;
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: '打印机已自动连接', icon: 'success' });
|
||||
} catch (err) {
|
||||
uni.hideLoading();
|
||||
console.error('自动连接失败', err);
|
||||
uni.showModal({
|
||||
title: '连接失败',
|
||||
content: `上次使用的打印机 (${this.lastPrinterMac}) 未找到,是否重新扫描?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) this.manualScanPrinter();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('蓝牙初始化失败', err);
|
||||
uni.showToast({ title: '请打开蓝牙并授权', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 手动扫描打印机(用于首次或自动连接失败后的补救)
|
||||
*/
|
||||
async manualScanPrinter() {
|
||||
try {
|
||||
await bluetoothManager.init();
|
||||
bluetoothManager.setDeviceFoundCallback(this.onPrinterFound);
|
||||
await bluetoothManager.stopScan();
|
||||
await bluetoothManager.startScan([this.printerServiceUUID]);
|
||||
uni.showToast({ title: '扫描打印机中...', icon: 'none' });
|
||||
// 20秒后自动停止扫描
|
||||
setTimeout(() => {
|
||||
bluetoothManager.stopScan();
|
||||
}, 20000);
|
||||
} catch (err) {
|
||||
console.error('扫描启动失败', err);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 手动扫描电子秤
|
||||
*/
|
||||
async manualScanScale() {
|
||||
try {
|
||||
await bluetoothManager.init();
|
||||
bluetoothManager.setDeviceFoundCallback(this.onScaleFound);
|
||||
await bluetoothManager.stopScan();
|
||||
await bluetoothManager.startScan([this.scaleServiceUUID]);
|
||||
uni.showToast({ title: '扫描电子秤中...', icon: 'none' });
|
||||
setTimeout(() => {
|
||||
bluetoothManager.stopScan();
|
||||
}, 20000);
|
||||
} catch (err) {
|
||||
console.error('扫描电子秤失败', err);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 打印机发现回调
|
||||
*/
|
||||
onPrinterFound(device) {
|
||||
const name = device.name || '';
|
||||
// 根据名称过滤器(可修改为你的打印机名称关键字)
|
||||
if (name.includes('QR380A-15E0_Ble')) {
|
||||
bluetoothManager.stopScan(); // 发现后停止扫描
|
||||
uni.showModal({
|
||||
title: '发现打印机',
|
||||
content: `设备: ${name}\nMAC: ${device.deviceId}\n是否连接?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.connectAndSavePrinter(device.deviceId, name);
|
||||
} else {
|
||||
// 用户取消,可以继续扫描(可选)
|
||||
this.manualScanPrinter();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 电子秤发现回调
|
||||
*/
|
||||
onScaleFound(device) {
|
||||
const name = device.name || '';
|
||||
if (name.includes('Scale') || name.includes('Weight')) {
|
||||
bluetoothManager.stopScan();
|
||||
uni.showModal({
|
||||
title: '发现电子秤',
|
||||
content: `设备: ${name}\nMAC: ${device.deviceId}\n是否连接?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.connectScale(device.deviceId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 连接打印机并保存 MAC
|
||||
*/
|
||||
async connectAndSavePrinter(deviceId, deviceName) {
|
||||
try {
|
||||
uni.showLoading({ title: '连接打印机中...' });
|
||||
const info = await bluetoothManager.connectKnownDevice(
|
||||
deviceId,
|
||||
this.printerServiceUUID,
|
||||
this.printerWriteUUID
|
||||
);
|
||||
this.printerDeviceId = deviceId;
|
||||
this.printerConnected = true;
|
||||
// 保存 MAC
|
||||
uni.setStorageSync('savedPrinterMac', deviceId);
|
||||
this.lastPrinterMac = deviceId;
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: `打印机 ${deviceName} 已连接`, icon: 'success' });
|
||||
} catch (err) {
|
||||
uni.hideLoading();
|
||||
console.error('连接打印机失败', err);
|
||||
uni.showToast({ title: '连接失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 连接电子秤(不需要保存,按需连接)
|
||||
*/
|
||||
async connectScale(deviceId) {
|
||||
try {
|
||||
uni.showLoading({ title: '连接电子秤...' });
|
||||
const info = await bluetoothManager.connectKnownDevice(
|
||||
deviceId,
|
||||
this.scaleServiceUUID,
|
||||
null, // 写入特征值可选
|
||||
this.scaleNotifyUUID
|
||||
);
|
||||
this.scaleDeviceId = deviceId;
|
||||
this.scaleConnected = true;
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: '电子秤已连接', icon: 'success' });
|
||||
} catch (err) {
|
||||
uni.hideLoading();
|
||||
console.error('连接电子秤失败', err);
|
||||
uni.showToast({ title: '连接失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 全局连接状态变化回调
|
||||
*/
|
||||
onConnectionChange(deviceId, connected) {
|
||||
if (deviceId === this.printerDeviceId) {
|
||||
this.printerConnected = connected;
|
||||
if (!connected) {
|
||||
uni.showToast({ title: '打印机断开', icon: 'none' });
|
||||
// 可选:自动重连(这里不做,避免频繁请求)
|
||||
}
|
||||
}
|
||||
if (deviceId === this.scaleDeviceId) {
|
||||
this.scaleConnected = connected;
|
||||
if (!connected) {
|
||||
uni.showToast({ title: '电子秤断开', icon: 'none' });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 全局数据接收回调(接收电子秤重量数据)
|
||||
*/
|
||||
onDataReceived(deviceId, value) {
|
||||
if (deviceId === this.scaleDeviceId) {
|
||||
// 将 ArrayBuffer 转为字符串(根据电子秤协议解析)
|
||||
const data = this.ab2str(value);
|
||||
console.log('电子秤原始数据:', data);
|
||||
// 示例:假设秤返回 "1234g" 或 "12.34kg"
|
||||
const weight = this.parseWeight(data);
|
||||
if (weight !== null) {
|
||||
this.weightValue = weight;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 打印测试
|
||||
*/
|
||||
async printTest() {
|
||||
if (!this.printerConnected) {
|
||||
uni.showToast({ title: '打印机未连接', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 示例:发送纯文本(实际需组装打印机指令,如 ESC/POS 或 CPCL)
|
||||
const text = '测试打印\n自动连接成功\n时间: ' + new Date().toLocaleString() + '\n\n';
|
||||
const buffer = this.str2ab(text);
|
||||
await bluetoothManager.writeData(this.printerDeviceId, buffer);
|
||||
uni.showToast({ title: '打印指令已发送', icon: 'success' });
|
||||
} catch (err) {
|
||||
console.error('打印失败', err);
|
||||
uni.showToast({ title: '打印失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 断开所有连接
|
||||
*/
|
||||
async disconnectAll() {
|
||||
await bluetoothManager.closeAll();
|
||||
this.printerDeviceId = null;
|
||||
this.printerConnected = false;
|
||||
this.scaleDeviceId = null;
|
||||
this.scaleConnected = false;
|
||||
this.weightValue = '--';
|
||||
uni.showToast({ title: '已断开所有连接', icon: 'success' });
|
||||
},
|
||||
|
||||
// ---------- 辅助函数 ----------
|
||||
str2ab(str) {
|
||||
const buf = new ArrayBuffer(str.length);
|
||||
const view = new Uint8Array(buf);
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
view[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
},
|
||||
ab2str(buffer) {
|
||||
return String.fromCharCode.apply(null, new Uint8Array(buffer));
|
||||
},
|
||||
parseWeight(dataStr) {
|
||||
// 修改为你的电子秤实际解析规则
|
||||
const match = dataStr.match(/(\d+(?:\.\d+)?)/);
|
||||
return match ? match[1] : null;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
.status-bar {
|
||||
background: #f5f5f5;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
button {
|
||||
margin: 5px 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<div>
|
||||
<button type="primary" @click="initScanFunc()">初始化扫描</button>
|
||||
<br/>
|
||||
<button type="primary" @click="closeScanFunc()">结束扫描</button>
|
||||
<br/>
|
||||
<button type="primary" @click="scanStartFunc()">开启扫描</button>
|
||||
<br/>
|
||||
<button type="primary" @click="scanStopFunc()">停止扫描</button>
|
||||
<br/>
|
||||
<p>设置连续扫描时间间隔</p><input type="number" v-model="invTime" placeholder="时间间隔(单位ms)">
|
||||
<button type="primary" @click="continueScanFunc(true)">连续扫描开启</button>
|
||||
<br/>
|
||||
<button type="primary" @click="continueScanFunc(false)">连续扫描关闭</button>
|
||||
<br/>
|
||||
<button type="primary" @click="setCenterModeFunc(0)">区域解码</button>
|
||||
<br/>
|
||||
<button type="primary" @click="setCenterModeFunc(1)">中心解码</button>
|
||||
<br/>
|
||||
<p>设置扫描输出模式</p>
|
||||
<button type="primary" @click="setOutputModeFunc(0)">焦点</button>
|
||||
<button type="primary" @click="setOutputModeFunc(1)">广播</button>
|
||||
<button type="primary" @click="setOutputModeFunc(2)">模拟按键</button>
|
||||
<p>部分旧版扫描软件不支持以下模式,设置后会导致软件异常</p>
|
||||
<button type="primary" @click="setOutputModeFunc(3)">复制</button>
|
||||
<button type="primary" @click="setOutputModeFunc(4)">焦点&广播</button>
|
||||
<br/>
|
||||
<button type="primary" @click="setLockScanKeyFunc()">启用扫码功能</button>
|
||||
<br/>
|
||||
<button type="primary" @click="setUnLockScanKeyFunc()">禁用扫码功能</button>
|
||||
<br/>
|
||||
<button type="primary" @click="setMultiBarcodeEnableFunc()">启用多条码识别功能</button>
|
||||
<br/>
|
||||
<button type="primary" @click="setMultiBarcodeDisableFunc()">禁用多条码识别功能</button>
|
||||
<br/>
|
||||
<p>设置多条码识别数量</p><input type="number" v-model="mulNumber" placeholder="个数">
|
||||
<button type="primary" @click="setMultiBarcodePreciseStatusEnableFunc()">启用多条码精准识别功能</button>
|
||||
<br/>
|
||||
<button type="primary" @click="setMultiBarcodePreciseStatusDisableFunc()">禁用多条码精准识别功能</button>
|
||||
<br/>
|
||||
|
||||
<button type="primary" @click="goTestFunc()">打开新页面</button>
|
||||
|
||||
<text id="testcontent" class="intro">\n测试步骤:\n1.点击初始化扫描\n2.按设备黄色扫描按键扫描到条码后弹窗提示条码数据\n3.页面关闭前点击结束扫描或调用closeScan()\n4.如需使用连续扫描功能,请点击连续扫描开启或关闭按钮,建议设置连续扫描时间间隔</text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
//获取module
|
||||
var barcodeModel = uni.requireNativePlugin("iData-BarcodePlugin-BarcodeModule")
|
||||
const modal = uni.requireNativePlugin('modal');
|
||||
var globalEvent = uni.requireNativePlugin('globalEvent');
|
||||
|
||||
export default {
|
||||
onLoad() {
|
||||
|
||||
globalEvent.addEventListener('iDataBarcodeEvent', function(e) {
|
||||
console.log("收到条码:" + JSON.stringify(e));
|
||||
modal.toast({
|
||||
message: "收到条码:" + JSON.stringify(e),
|
||||
duration: 1.5
|
||||
});
|
||||
//连续扫描如果间隔时间比较短,会出现toast不提示的情况,数据可以正常接收到,建议查看控制台输出
|
||||
console.log(JSON.stringify(e));
|
||||
});
|
||||
barcodeModel.initScan((ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
onUnload() {
|
||||
barcodeModel.closeScan((ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
globalEvent.removeEventListener('iDataBarcodeEvent');
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
invTime:"500",
|
||||
mulNumber:"3"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goTestFunc(){
|
||||
uni.navigateTo({
|
||||
url: './scantest2'
|
||||
});
|
||||
},
|
||||
initScanFunc() {
|
||||
barcodeModel.initScan((ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
scanStartFunc() {
|
||||
barcodeModel.scanStart((ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
scanStopFunc() {
|
||||
barcodeModel.scanStop((ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
setCenterModeFunc(mode) {
|
||||
// 区域/中心扫码设置
|
||||
barcodeModel.setCenterMode(mode,
|
||||
(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
setOutputModeFunc(mode) {
|
||||
// 扫描输出模式设置
|
||||
barcodeModel.setOutputMode(mode,
|
||||
(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
continueScanFunc(enable) {
|
||||
// 连续扫描设置:先设置扫描间隔时间,然后开启扫描开关
|
||||
if(enable){
|
||||
//设置连续扫描间隔时间
|
||||
barcodeModel.intervalSet(this.invTime,
|
||||
(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//设置连续扫描
|
||||
barcodeModel.continueScan(enable,
|
||||
(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
closeScanFunc() {
|
||||
barcodeModel.closeScan((ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
globalEvent.removeEventListener('iDataBarcodeEvent');
|
||||
},
|
||||
setLockScanKeyFunc() {
|
||||
//启用扫码按键扫码功能,启用后按扫描键会自动触发扫码功能
|
||||
barcodeModel.setScanKeyEnable(true,(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
setUnLockScanKeyFunc() {
|
||||
//禁用扫码按键扫码功能,禁用后按扫描键不会自动触发扫码功能,支持自行监听按键触发功能
|
||||
barcodeModel.setScanKeyEnable(false,(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
setMultiBarcodeEnableFunc() {
|
||||
//启用多条码识别功能,启用后按扫描键会一次性识别多个条码并返回对应的条码数据,每个数据一行,分隔符为'\n'
|
||||
barcodeModel.setMultiBarcodeEnable(true,(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
setMultiBarcodeDisableFunc() {
|
||||
//禁用多条码识别功能,禁用后按扫描键不会识别多个条码,仅识别一个条码
|
||||
barcodeModel.setMultiBarcodeEnable(false,(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
setMultiBarcodePreciseStatusEnableFunc() {
|
||||
//启用多条码精准模式,配合多条码数据接口,识别到配置的多条码数量的条码后才会返回条码数据
|
||||
barcodeModel.setMultiBarcodePreciseStatus(true,(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
barcodeModel.setMultiBarcodeNumber(this.mulNumber,(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
},
|
||||
setMultiBarcodePreciseStatusDisableFunc() {
|
||||
//禁用多条码精准模式
|
||||
barcodeModel.setMultiBarcodePreciseStatus(false,(ret) => {
|
||||
modal.toast({
|
||||
message: ret,
|
||||
duration: 1.5
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="uni-section">
|
||||
<text>扫描测试(统一扫码模块)</text>
|
||||
</view>
|
||||
<view class="uni-form-item uni-column">
|
||||
<button class="btn btn-primary" @click="startScan">开始扫描</button>
|
||||
<button class="btn" @click="stopScan">停止扫描</button>
|
||||
</view>
|
||||
<view v-if="scanResult">
|
||||
<text>最近扫描结果: {{ scanResult }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import scan from '@/utils/scan.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
scanResult: ''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 初始化(默认自动检测模式,也可手动指定)
|
||||
// scan.setMode('idata') // 强制 iData 模式
|
||||
scan.setMode('android') // 强制 Android 系统模式
|
||||
scan.init()
|
||||
|
||||
// 注册扫码结果回调
|
||||
scan.register(this.onScanResult)
|
||||
},
|
||||
onUnload() {
|
||||
scan.unregister()
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 扫码结果回调
|
||||
* @param {string} codeStr - 解码后的扫描字符串
|
||||
*/
|
||||
onScanResult(codeStr) {
|
||||
console.log('codeStr:', codeStr)
|
||||
this.scanResult = codeStr
|
||||
uni.showToast({
|
||||
title: codeStr,
|
||||
duration: 2000
|
||||
})
|
||||
},
|
||||
|
||||
startScan() {
|
||||
scan.startScan()
|
||||
},
|
||||
|
||||
stopScan() {
|
||||
scan.stopScan()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user