364 lines
8.6 KiB
Vue
Raw Normal View History

2025-07-07 09:21:15 +08:00
<template>
<view class="ble-connect">
<u-navbar :title="$tt('navBar.bleAddDevice')" bgColor="#F1F3F9"
:titleStyle="{fontWeight: 700, fontSize: '16px'}" @leftClick="handleGoback">
</u-navbar>
<view class="device-search">
<view class="img-wrap">
<image class="img" :class="{'rotating': isSearch }" src="/static/common/searching.png" />
</view>
<view class="title" v-if="isSearch">{{$tt('bleConnect.scanning')}}</view>
<view class="title" v-else>{{$tt('bleConnect.ifNoDev')}}</view>
<view class="describe" v-if="!isSearch">{{errmgs}}</view>
<view class="describe" v-if="isSearch">{{$tt('bleConnect.scanningDev')}}</view>
<view class="again" v-else @click="handleAgainSearch">{{$tt('bleConnect.rescan')}}</view>
</view>
<view class="device-title">{{$tt('bleConnect.usableDev')}}</view>
<view class="device-list" v-if="deviceList.length !== 0">
<view class="item-wrap" v-for="item in deviceList" :key="item.deviceId">
<view class="icon">
<u--image src="/static/common/device.png" width="28px" height="28px"></u--image>
</view>
<view class="name">{{item.name}}</view>
<view class="btn" @click="handleConnect(item.deviceId)">{{$tt('bleConnect.connect')}}</view>
</view>
</view>
<u-empty v-else mode="data" :iconSize="80" :text="$tt('bleConnect.connect')" marginTop="65px">
</u-empty>
<view class="tools-wrap">
<view class="btn" @click="handleManualAdd">{{$tt('bleConnect.manuallyAdd')}}</view>
<view class="btn" @click="handleScan">{{$tt('bleConnect.scan')}}</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
nDelayTimer: -1, // 定时器
isFind: false, // 是否发现设备
deviceList: [], // 设备列表
isSearch: false,
errmgs: ''
};
},
mounted() {
this.searchBlueToothDevice();
},
methods: {
searchBlueToothDevice() {
this.initBlueTooth();
},
stopBlueToothDevice() {
clearInterval(this.nDelayTimer);
this.isSearch = false;
this.isFind = false;
this.deviceList = [];
this.errmgs = '';
this.nDelayTimer = -1;
},
// 重新扫描
handleAgainSearch() {
this.stopBlueToothDevice();
this.searchBlueToothDevice();
},
// 连接
handleConnect(deviceId) {
uni.navigateTo({
url: `/pagesB/home/device/add/bleConnect/setWifi?deviceId=${deviceId}`
});
},
// 初始化蓝牙适配器
initBlueTooth() {
let _this = this;
uni.closeBluetoothAdapter({
success: (res) => {
uni.openBluetoothAdapter({
success: (res) => {
this.findBlueTooth();
},
fail: (err) => {
console.log('openBluetoothAdapter', err.errMsg);
uni.showModal({
content: this.$tt('bleConnect.turnOnBle'),
showCancel: false,
});
}
})
},
})
},
// 搜索蓝牙设备
findBlueTooth() {
let _this = this;
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
interval: 0,
success: (res) => {
_this.isSearch = true;
_this.nDelayTimer = setInterval(() => _this.discoveryBlueTooth(), 1000);
setTimeout(() => {
_this.isSearch = false;
if (_this.isFind) {
uni.stopBluetoothDevicesDiscovery({
success: (result) => {
console.log(result);
},
});
clearInterval(_this.nDelayTimer);
_this.nDelayTimer = -1;
return;
} else {
uni.stopBluetoothDevicesDiscovery({
success: (result) => {
console.log(result);
},
});
clearInterval(_this.nDelayTimer);
_this.nDelayTimer = -1;
_this.errmgs = this.$tt('bleConnect.checkBleAndTurnOnGPSForAndroid');
}
}, 15000);
},
fail: (res) => {
_this.errmgs = this.$tt('bleConnect.bleDiscoverydev') + `${res.errMsg}`;
}
})
},
// 搜索设备回调
discoveryBlueTooth() {
const _this = this;
uni.getBluetoothDevices({
success: (res) => {
if (res?.devices && res?.devices?.length != 0) {
const list = res.devices;
const devices = [];
list.forEach((item) => {
let bname = '';
if (item.name && item.name.length > 0) {
bname = item.name;
}
if (item.localName && item.localName.length > 0) {
bname = item.localName;
}
if (bname !== "" && bname !== "未知设备") {
devices.push(item);
}
});
_this.deviceList = devices;
_this.isFind = true;
clearInterval(_this.nDelayTimer);
_this.nDelayTimer = -1;
}
},
fail: (res) => {
console.log('getBluetoothDevices', res);
_this.errmgs = this.$tt('bleConnect.failedToSearchBle');
},
});
},
// 返回
handleGoback() {
uni.switchTab({
url: '/pages/tabBar/home/index'
});
},
// 扫码添加
async handleScan() {
// #ifndef MP-WEIXIN || APP-PLUS
uni.showToast({
icon: 'none',
title: this.$tt('user.scanning')
});
return;
// #endif
// 权限问题app 需要做权限说明
let onlyFromCamera = false;
// #ifdef APP-PLUS
onlyFromCamera = true;
let result = await this.$store.dispatch("permission/requestPermissions", 'CAMERA');
if (result !== 1) return;
// #endif
this.startScanCode(onlyFromCamera);
},
// 开始扫码
startScanCode(onlyFromCamera) {
uni.scanCode({
onlyFromCamera, // 是否允许从相册扫码
success: res => {
// 解析JSON
try {
const scanJson = JSON.parse(res.result);
// type=1 代表扫码关联设备
if (scanJson.deviceId) {
uni.showModal({
content: '【' + this.$tt('bleConnect.deviceName') +
':' + scanJson.name + ',' + this.$tt('bleConnect.deviceNum') +
':' + scanJson.deviceId + '】' + this.$tt(
'bleConnect.isConfirmed'),
cancelText: this.$tt('common.cancel'),
confirmText: this.$tt('common.confirm'),
confirmColor: '#486ff2',
cancelColor: '#606266',
success: result => {
if (result.confirm) {
this.handleConnect(scanJson.deviceId);
}
}
});
return;
}
uni.showToast({
icon: 'none',
title: $tt('bleConnect.qsNosupport')
});
} catch (error) {
uni.showToast({
icon: 'none',
title: this.$tt('user.errorParseQRcode')
});
}
}
});
},
// 手动添加
handleManualAdd() {
uni.navigateTo({
url: `/pagesB/home/device/add/bleConnect/manualAdd`
});
}
}
};
</script>
<style lang="scss">
page {
height: 100%;
background: $uni-bg-color-grey;
}
</style>
<style lang="scss" scoped>
.ble-connect {
height: 100vh;
overflow-y: hidden;
display: flex;
flex-direction: column;
.device-search {
margin-top: calc(44px + var(--status-bar-height));
display: flex;
flex-direction: column;
align-items: center;
height: 700rpx;
.img-wrap {
padding: 20rpx 0;
margin-top: 20rpx;
.img {
width: 500rpx;
height: 500rpx;
}
.rotating {
animation: rotation 4s infinite linear;
}
@keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
}
.title {
font-size: 32rpx;
font-weight: 500;
line-height: 64rpx;
}
.describe {
font-size: 24rpx;
line-height: 48rpx;
color: #7e7e7e;
}
.again {
font-size: 28rpx;
font-weight: 500;
line-height: 64rpx;
color: #486ff2;
}
}
.device-title {
font-size: 32rpx;
font-weight: 500;
line-height: 64rpx;
padding: 40rpx 40rpx 10rpx 40rpx;
}
.device-list {
padding: 20rpx 40rpx;
flex-direction: column;
overflow-y: auto;
margin-bottom: 160rpx;
.item-wrap {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 26rpx;
.name {
font-size: 28rpx;
font-weight: 500;
line-height: 64rpx;
margin-left: 12px;
flex: 1
}
.btn {
font-size: 28rpx;
font-weight: 500;
line-height: 50rpx;
background: #7e7e7e21;
width: 120rpx;
text-align: center;
color: #486ff2;
border-radius: 40rpx;
padding: 0 10rpx;
}
}
}
.tools-wrap {
position: fixed;
bottom: 60rpx;
left: 0;
right: 0;
display: flex;
flex-direction: row;
justify-content: center;
gap: 40rpx;
.btn {
font-size: 32rpx;
font-weight: 500;
line-height: 62rpx;
background: #7e7e7e21;
width: 260rpx;
text-align: center;
color: #486ff2;
border-radius: 40rpx;
padding: 5rpx 10rpx;
}
}
}
</style>