Files
APP/pages/common/addDevice/addBle.vue

1498 lines
32 KiB
Vue
Raw Normal View History

<template>
<view class="content">
2026-04-01 08:46:32 +08:00
<uni-nav-bar :border="false" @clickLeft="prevPage" fixed="true" statusBar="true" background-color="#121212"
color="#FFFFFF" :title="Status.navbar.title">
<template v-slot:left>
<view>
<uni-icons type="left" size="24" color="#FFFFFF"></uni-icons>
</view>
</template>
<block slot="right">
<view class="navbarRight center">
<image @click.stop="handleRightClick(index,item)" v-for="item,index in Status.navbar.icons"
class="img" :src="item.src" mode="aspectFit"></image>
</view>
</block>
</uni-nav-bar>
<view class="topStatric">
<view class="lblTitle">
<view class="red">搜不到设备时,请尝试重启蓝牙,或重启App后重试</view>
</view>
<view class="lblTitle">
<view>添加:{{type.typeName}} 设备数量:{{devicesCnt}}</view>
2026-04-01 08:46:32 +08:00
<view class="btn" style="color: #FFFFFF;" @click="ReSearch()">刷新</view>
</view>
<view class="lblTitle">
<uni-easyinput :styles="{color:'#ffffff'}" :clearable="true" class="uni-mt-5" :trim="'both'"
prefixIcon="search" v-model="search" placeholder="名称筛选"></uni-easyinput>
</view>
<view class="th">
<text>
蓝牙设备列表
</text>
<text class="margintLeft10">
{{SearchEquips.length}}
</text>
</view>
</view>
<view class="mainContent">
<view class="p100">
<view class="list searchList">
<view class="item" v-on:click="Link(item,index)" v-for="item, index in SearchEquips"
v-show="!item['linkStatu']"
:class="{'displayNone':item.name.toLowerCase().indexOf(search.toLowerCase())===-1}">
<view class="leftImg ">
<image src="/static/images/common/bluetooth.png" class="titleIco" mode="heightFix">
</image>
</view>
<view class="centertxt ">
<view class="name">
<text class="fleft">蓝牙名:{{item.name?item.name:'Unnamed'}}</text>
<text class="fright" :class="item.link?'green':'red'">{{item.link?'已连接':'未连接'}}</text>
<view class="clear"></view>
</view>
<view class="name lbl">Mac:
<text class="green" v-if="item.macAddress">{{item.macAddress}}</text>
<view class="red" v-if="!item.macAddress && item.link">
<view class="rotateAnimation">
<uni-icons type="spinner-cycle" color="#FFFFFF"></uni-icons>
</view>
</view>
</view>
<view class="name lbl">IMEI:
<text class="green" v-if="item.imei">{{item.imei}}</text>
<view class="red" v-if="!item.imei && item.link">
<view class="rotateAnimation">
<uni-icons type="spinner-cycle" color="#FFFFFF"></uni-icons>
</view>
</view>
</view>
<view class="name lbl">信号:{{item.RSSI}}dBm</view>
<view class="name lbl">
状态:
<text :class="item.isUpload?'green':'red'">{{item.remark}}</text>
</view>
<view class="name lbl">
设备名:
2026-04-01 08:46:32 +08:00
<text class="green">{{item.device_name}}</text>
</view>
</view>
<view class="rightIco " :class="item.isUpload?'bggreen':'bgred'">
</view>
</view>
</view>
</view>
</view>
<global-loading ref="loading" />
2026-04-01 08:46:32 +08:00
<MsgBox ref="msgPop" />
</view>
</template>
<script>
import bleTool from '@/utils/BleHelper.js';
import request from '@/utils/request.js';
import {
showLoading,
hideLoading,
updateLoading
} from '@/utils/loading.js'
2026-04-01 08:46:32 +08:00
import common from '@/utils/Common.js'
const pagePath = "pages/common/addBLE/addEquip";
2026-04-01 08:46:32 +08:00
import {
MsgSuccess,
MsgError,
MsgClose,
MsgWarning,
showPop,
2026-04-02 08:45:36 +08:00
MsgClear,
MsgInfo
2026-04-01 08:46:32 +08:00
} from '@/utils/MsgPops.js';
import MQTT from '@/utils/MqHelper.js';
var ble = null;
var these = null;
var eventChannel = null;
var time = null;
var time1 = null;
2026-04-01 08:46:32 +08:00
var mq = null;
export default {
data() {
return {
Status: {
intval: null,
2026-04-01 08:46:32 +08:00
pcAuthori: false,
navbar: {
icons: [
{
src: '/static/images/common/scane.png'
}
],
title: '添加设备',
showBack: true,
height: 90
}
},
search: '',
groupid: '',
type: '',
deviceTypes: [], //设备类型
PairEquip: [], //已配对设备
EquipMents: [], //搜索出来的设备
devices: [],
devicesCnt: 0,
2026-04-01 08:46:32 +08:00
privateNetUrl: '',
scanKey: ''
}
},
computed: {
SearchEquips: function() {
let f = this.EquipMents.filter(v => {
return v.name.toLowerCase().indexOf(this.search.toLowerCase()) > -1
});
return f;
}
},
onHide: function() {
ble.StopSearch();
},
onUnload() {
2026-04-01 08:46:32 +08:00
if (ble) {
ble.StopSearch().then(res => {
console.log("停止搜索成功")
}).catch(ex => {
console.error("停止搜索成功", ex);
});
ble.removeAllCallback(pagePath);
ble.disconnectDevice();
}
if (mq) {
mq.disconnect();
}
},
onLoad() {
2026-04-01 08:46:32 +08:00
these = this;
mq = MQTT.getMqTool();
mq.init();
this.groupid = common.DateFormat(new Date(), 'yyyy-MM-dd HH:mm:ss');
2026-04-01 08:46:32 +08:00
ble = bleTool.getBleTool();
// serv = serTool.serverInit();
//已连接过但删除了设备
// #ifdef H5
this.EquipMents = [{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
}, {
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
}, {
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
}, {
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
}, {
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
}, {
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
}, {
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
}, {
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "F281938F-27FC-4739-4ACA-58B8D3BC44A6",
"name": "JQZM-HBY670-1C7493",
"linkStatu": false,
link: true
},
{
"RSSI": -62,
"advertisData": "",
"advertisServiceUUIDs": [
"0000FFE0-0000-1000-8000-00805F9B34FB"
],
"deviceId": "469FB381-B47E-1E40-8073-EF50B5704AAB",
"name": "JQZM-EF4651",
"linkStatu": false
}
]
// #endif
// #ifdef APP
this.EquipMents = [];
// these.EquipMents=[];
ble.addDeviceFound((arr) => {
// console.log("发现新设备,",arr);
arr = arr.devices;
let promis = [];
for (var i = 0; i < arr.length; i++) {
arr[i].linkStatu = false;
if (!arr[i].name) {
continue;
}
2026-04-01 08:46:32 +08:00
2026-04-02 08:45:36 +08:00
arr[i].name = arr[i].name.replace(/\r\n/g, '').replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,'');
2026-04-01 08:46:32 +08:00
let f = these.EquipMents.find(function(v, index) {
if (v.deviceId == arr[i].deviceId) {
these.$set(these.EquipMents[index], "RSSI", arr[i].RSSI);
return true;
}
return false;
});
if (!f) {
arr[i].remark = '正在校验...';
these.EquipMents.push(arr[i]);
these.getDevice(arr[i]);
// console.log("EquipMents=", these.EquipMents);
}
}
2026-04-01 08:46:32 +08:00
these.sendEquipToMq();
// console.log("equip=", these.EquipMents)
}, pagePath);
// console.log("addEquip")
ble.addReceiveCallback((receivData, f, path, arr) => {
console.log("收到消息", receivData)
console.log("f=", f)
let item = null;
if (f.macAddress) {
item = this.EquipMents.find((v, index) => {
if (v.deviceId == f.deviceId) {
v.macAddress = f.macAddress;
this.$set(this.EquipMents[index], "macAddress", f.macAddress);
console.log("22222");
return true;
}
return false;
});
console.log("111111");
}
if (f.imei) {
2026-04-01 08:46:32 +08:00
f.imei = f.imei.replace(/\u0000/g, '');
item = this.EquipMents.find((v, index) => {
if (v.deviceId == f.deviceId) {
v.imei = f.imei;
this.$set(this.EquipMents[index], "imei", f.imei);
return true;
}
return false;
});
}
if (this.type.communicationMode == 2) {
if (f.macAddress || f.imei) {
this.uploadItem(item);
}
} else { //==1
if (f.macAddress) {
this.uploadItem(item);
}
}
}, pagePath);
ble.addStateBreakCallback(() => {
uni.showModal({
title: '提示',
content: '蓝牙不可用'
});
these.EquipMents.filter((v, i) => {
these.$set(these.EquipMents[i], 'link', false);
});
}, pagePath);
ble.addStateRecoveryCallback(() => {
uni.showModal({
title: '提示',
content: '蓝牙恢复可用'
});
},
pagePath);
ble.addDisposeCallback((res) => {
these.EquipMents.find((v, i) => {
if (res.deviceId == v.deviceId) {
these.$set(these.EquipMents[i], 'link', false);
return true;
}
return false;
});
}, pagePath);
ble.addRecoveryCallback((res) => {
these.EquipMents.find((v, i) => {
if (res.deviceId == v.deviceId) {
these.$set(these.EquipMents[i], 'link', true);
return true;
}
return false;
});
}, pagePath);
// #endif
eventChannel = this.getOpenerEventChannel();
eventChannel.on('addType', function(rec) {
console.log("接收到父页面的参数:", rec);
these.type = rec.data;
let callback = () => {
these.getTypeDeviceCnt().then(res => {
2026-04-01 08:46:32 +08:00
console.error("设备数量:", res);
these.devicesCnt = res;
if (res > 0 && res <= 10000) {
these.getAlltypeDevices().then(devs => {
these.devices = devs;
these.ReSearch();
});
return;
}
these.ReSearch();
}).catch(ex => {
these.devicesCnt = 0;
these.ReSearch();
});
}
2026-04-01 08:46:32 +08:00
callback();
2026-04-01 08:46:32 +08:00
});
2026-04-01 08:46:32 +08:00
setTimeout(()=>{
2026-04-02 08:45:36 +08:00
MsgInfo("如需要在PC上查看此数据,请复制链接后通过微信发送到PC,在PC端打开然后点右上角扫码授权","复制链接",these,true,()=>{
console.log("执行复制");
2026-04-01 08:46:32 +08:00
uni.setClipboardData({
data:'https://static-mp-5b7c35fc-f6fe-4100-a2e1-3669e4d4bfc9.next.bspapp.com/AppTools/views/index.html',
success(){
uni.showToast({
title:'已复制链接'
});
2026-04-02 08:45:36 +08:00
plus.runtime.openURL('weixin://', (err) => {
MsgError("打开微信失败,请手动打开微信粘贴");
});
},
fail(ex){
console.error("无法复制",ex)
2026-04-01 08:46:32 +08:00
}
});
});
},500);
},
onShow: function() {
if (these.type) {
this.ReSearch();
}
},
methods: {
2026-04-01 08:46:32 +08:00
prevPage() {
uni.navigateBack({
});
},
handleRightClick: function(s, e) {
this.scan();
},
initWatch() {
this.$watch("devicesCnt", (newVal, oldVal) => {
const phone = uni.getStorageSync('phone');
mq.sendData('pc/' + phone, JSON.stringify({
devicesCnt: this.devicesCnt
}), false);
});
},
//获取某个类型下的所有设备
getAlltypeDevices() {
return new Promise((succ, err) => {
2026-04-01 08:46:32 +08:00
let json = {
"tenant_id": this.type.tenantId,
"deviceType": this.type.deviceTypeId
};
request({
url: "/app/xinghan/device/getEquipAllByType",
method: 'POST',
data: json,
}).then(res => {
if (res && res.code == 200) {
succ(res.data);
return;
}
err(res);
}).catch(ex => {
console.error("ex=", ex);
err(ex);
});
});
},
//获取类型下的设备数量
getTypeDeviceCnt() {
return new Promise((resolve, reject) => {
2026-04-01 08:46:32 +08:00
let json = {
"tenant_id": this.type.tenantId,
"deviceType": this.type.deviceTypeId
};
console.error("json=", json);
request({
url: "/app/xinghan/device/getEquipCountByType",
method: 'POST',
data: json,
}).then(res => {
console.error("getEquipCountByType res.data=", res.data)
if (res && res.code == 200) {
resolve(res.data);
return;
}
reject(res);
}).catch(ex => {
console.error("ex=", ex);
reject(ex);
});
});
},
getDevice(item) {
//从后台通过类型和名称查询设备
return new Promise((resolve, reject) => {
let f = null;
let fIndex = -1;
these.EquipMents.find(function(v, index) {
if (v.deviceId == item.deviceId) {
f = v;
fIndex = index;
return true;
}
return false;
});
if (this.devicesCnt > 0) {
if (this.devices && this.devices.length > 0) {
let eqp = this.devices.find(v => {
2026-04-01 08:46:32 +08:00
let flag = v.bluetooth_name.replace(/\r\n/g, '').replace(
/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '') == item.name;
return flag;
2026-04-01 08:46:32 +08:00
});
if (eqp) {
2026-04-01 08:46:32 +08:00
these.$set(these.EquipMents[fIndex], "isUpload",
true);
these.$set(these.EquipMents[fIndex], "remark",
"校验完成,设备已入库");
these.$set(these.EquipMents[fIndex], "macAddress",
eqp.device_mac);
2026-04-01 08:46:32 +08:00
these.$set(these.EquipMents[fIndex], "device_name", eqp.device_name);
console.log("从缓存中找到了设备", eqp);
resolve(eqp);
return;
}
}
2026-04-01 08:46:32 +08:00
// console.error("缓存中找不到此设备22222222", this.devices);
these.$set(these.EquipMents[fIndex], "remark",
"校验完成,设备未入库");
reject(null);
2026-04-01 08:46:32 +08:00
these.sendEquipToMq();
return;
}
2026-04-01 08:46:32 +08:00
let succCallback = (data) => {
if (data) {
these.$set(these.EquipMents[fIndex], "isUpload",
true);
these.$set(these.EquipMents[fIndex], "remark",
"校验完成,设备已入库");
these.$set(these.EquipMents[fIndex], "macAddress",
data.device_mac);
these.$set(these.EquipMents[fIndex], "imei", data
.device_imei);
2026-04-01 08:46:32 +08:00
these.$set(these.EquipMents[fIndex], "device_name", data.device_name);
} else {
console.error("设备未入库111111", data)
these.$set(these.EquipMents[fIndex], "remark",
"校验完成,设备未入库");
}
2026-04-01 08:46:32 +08:00
these.sendEquipToMq();
}
2026-04-01 08:46:32 +08:00
let errCallback = () => {
these.$set(these.EquipMents[fIndex], "remark",
"校验出现异常");
2026-04-01 08:46:32 +08:00
these.sendEquipToMq();
}
2026-04-01 08:46:32 +08:00
let p2 = new Promise((resolve, reject) => {
let json = {
"tenant_id": this.type.tenantId,
"deviceType": this.type.deviceTypeId,
"deviceName": item.name
};
2026-04-01 08:46:32 +08:00
request({
2026-04-01 08:46:32 +08:00
url: '/app/xinghan/device/GetDeviceByName',
data: json,
method: 'POST'
2026-04-01 08:46:32 +08:00
}).then(res => {
if (res && res.code == 200) {
resolve(res.data);
return;
}
2026-04-01 08:46:32 +08:00
reject(res);
2026-04-01 08:46:32 +08:00
}).catch(ex => {
reject(ex);
});
})
2026-04-01 08:46:32 +08:00
Promise.any([p2]).then(res => {
succCallback(res);
2026-04-01 08:46:32 +08:00
}).catch(ex => {
errCallback(ex);
2026-04-01 08:46:32 +08:00
}).finally(() => {
});
});
},
2026-04-01 08:46:32 +08:00
scan() {
uni.scanCode({
success: (res) => {
console.log('条码内容:' + res.result);
let getUrlParams = (url) => {
var p = {},
s = (url.indexOf('?') > -1 ? url.split('?')[1] : '').split('&');
for (var i = 0; i < s.length; i++) {
if (!s[i]) continue;
var kv = s[i].split('=');
p[decodeURIComponent(kv[0])] = kv[1] ? decodeURIComponent(kv[1].replace(
/\+/g, ' ')) : '';
}
return p;
}
let json = getUrlParams(res.result);
if (!json.key) {
uni.showModal({
title: '错误',
content: "无效的二维码"
})
return;
}
this.scanKey = json.key;
let msg = {
scanResult: '已扫码',
scanCode: 200
};
mq.sendData('pc/' + json.key, JSON.stringify(msg), false);
uni.showModal({
title: '授权申请',
content: 'pc端授权登陆',
confirmText: '同意',
cancelText: '拒绝',
showCancel: true,
success(res) {
if (res.confirm) {
these.pcAuthori(json);
return;
}
if (res.cancel) {
msg.scanResult = "用户拒绝授权";
msg.scanCode = 500;
mq.sendData('pc/' + json.key, JSON.stringify(msg), false);
}
},
})
},
fail: (err) => {
console.log('扫码失败', err);
uni.showToast({
title: '扫码失败',
icon: 'none'
});
}
});
},
pcAuthori() { //同意授权
const token = 'Bearer ' + uni.getStorageSync('token');
const clientid = uni.getStorageSync('clientID');
const phone = uni.getStorageSync('phone');
let msg = {
scanResult: '用户同意授权',
scanUsr: phone,
scanCode: 0,
Authorization: token,
clientid: clientid,
};
console.log("同意授权", msg);
this.Status.pcAuthori = true;
mq.sendData('pc/' + this.scanKey, JSON.stringify(msg), false);
these.sendEquipToMq();
},
sendEquipToMq() {
if (mq && this.scanKey) {
const phone = uni.getStorageSync('phone');
setTimeout(() => {
mq.sendData('pc/' + phone, JSON.stringify({
EquipMents: this.EquipMents
}), false);
}, 500);
}
},
ReSearch() {
if (!ble) {
return;
}
2026-04-01 08:46:32 +08:00
ble.disconnectDevice().finally(dis => {
2026-04-01 08:46:32 +08:00
ble.StopSearch().finally(res => {
2026-04-01 08:46:32 +08:00
this.EquipMents = [];
this.PairEquip = [];
ble.StartSearch().then(result => {
2026-04-01 08:46:32 +08:00
}).catch(err => {
console.error("err=", err);
2026-04-01 08:46:32 +08:00
MsgError("出现错误:" + err.msg, '', these);
});
}).catch(ex => {
console.error("ex=", ex);
2026-04-01 08:46:32 +08:00
MsgError("出现错误:" + ex.msg, '', these);
});
});
},
uploadItem(item) {
clearTimeout(time);
ble.disconnectDevice(item.deviceId).catch(ex => {});
let exec = () => {
let json = {
// "assignId": 0,
"deviceType": this.type.id,
// "customerId": 0,
"deviceName": item.name, //typeName
"deviceMac": item.macAddress,
"bluetoothName": item.name,
"deviceImei": item.imei,
// "deviceSn": "",
// "file": "",
"remark": this.groupid
}
request({
url: '/app/xinghan/device/add',
method: 'post',
data: json
}).then(res => {
if (res && res.code == 200) {
console.log("res=", res);
this.EquipMents.find((v, index) => {
if (v.deviceId == item.deviceId) {
this.$set(this.EquipMents[index], "isUpload", true);
this.$set(this.EquipMents[index], "remark", "上传成功");
this.devices.push({
bluetooth_name: item.name,
device_mac: item.macAddress,
2026-04-01 08:46:32 +08:00
device_name: item.name
});
this.devicesCnt = this.devices.length;
return true;
}
return false;
});
} else {
console.error("出现错误,", item);
console.error("出现错误,", this.devices);
this.EquipMents.find((v, index) => {
if (v.deviceId == item.deviceId) {
this.$set(this.EquipMents[index], "isUpload", false);
this.$set(this.EquipMents[index], "remark", res.msg);
2026-04-01 08:46:32 +08:00
this.devices.find((d, i) => {
if (d.device_mac == item.macAddress) {
this.$set(this.EquipMents[index], "device_name", d
.device_name);
return true;
}
});
2026-04-01 08:46:32 +08:00
return true;
}
return false;
});
2026-04-01 08:46:32 +08:00
}
2026-04-01 08:46:32 +08:00
}).catch(ex => {}).finally(() => {
these.sendEquipToMq();
});
}
time = setTimeout(exec, 100)
},
Link: function(item) {
let exec = () => {
showLoading(this, {
text: "正在连接:第1次"
});
let index = 1;
let total = 5;
let linkCallback = (res) => {
let c = these.PairEquip.find(function(v) {
return v.deviceId == item.deviceId;
});
if (!c) {
these.PairEquip.push(item);
}
console.log("连接成功", these.device);
hideLoading(these);
}
let execLink = () => {
return new Promise((resolve, reject) => {
if (index > total) {
reject({
msg: "连接超时"
});
return;
}
ble.LinkBlue(item.deviceId).then((res) => {
console.log("连接成功");
these.EquipMents.find((v, index) => {
if (v.deviceId == item.deviceId) {
this.$set(this.EquipMents[index], "link",
true);
return true;
}
return false;
});
ble.StopSearch();
resolve(res);
}).catch((ex) => {
if (index == total) {
console.log("连接了N次都没连上");
reject(ex);
return;
}
index++;
updateLoading(this, {
text: ex.msg + ",正在重试第" + index + "次"
})
execLink().then(resolve).catch(reject);
})
});
}
execLink().then((res) => {
linkCallback(res);
2026-04-01 08:46:32 +08:00
these.sendEquipToMq();
}).catch(ex => {
console.log("ex=", ex)
uni.showModal({
content: "连接失败:" + ex.msg
});
hideLoading(these);
});
}
if (this.PairEquip && this.PairEquip.length) {
ble && ble.disconnectDevice();
this.PairEquip = [];
exec();
} else {
exec();
}
}
}
}
</script>
<style>
.noLink {
text-align: center;
width: 100%;
font-size: 28rpx;
}
.content {
background-color: #121212;
color: #ffffffde;
box-sizing: border-box;
overflow: hidden;
width: 100%;
min-height: 100vh;
height: auto;
}
.p100 {
width: 100%;
height: 100%;
}
.fleft {
float: left;
}
.fright {
float: right;
}
.clear {
clear: both;
}
.center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: center;
align-items: center;
}
.topAnimate {
position: absolute;
left: 0rpx;
width: 100%;
height: 400rpx;
top: 20px;
/* 距离视口顶部 20px 时固定 */
z-index: 100;
/* 确保元素显示在最上层 */
}
.animate {
width: 100%;
height: 400rpx;
position: relative;
}
.animate .animateContent {
position: relative;
z-index: 0;
}
.animate .imgContent {
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
}
.animate .imgContent .img {
height: 100rpx;
width: 100rpx;
background: #bbe600;
border-radius: 50%;
}
.animate .titleIco {
width: 36rpx;
height: 36rpx;
}
.circle {
position: absolute;
border-radius: 50%;
background-color: #bbe60033;
animation: expand 4s infinite ease-out;
display: inline-block;
transform: translate(-50%, -50%);
}
.circle:nth-child(2) {
animation-delay: 1s;
}
.circle:nth-child(3) {
animation-delay: 2s;
}
@keyframes expand {
0% {
width: 0;
height: 0;
opacity: 0.8;
}
100% {
width: 18.75rem;
height: 18.75rem;
opacity: 0.2;
}
}
.mainContent {
padding: 30rpx;
box-sizing: border-box;
width: 100%;
overflow-y: scroll;
}
.mainContent .p100 {}
.lblTitle {
color: #26df1cde;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 700;
text-align: left;
width: 100%;
height: 60rpx;
line-height: 60rpx;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: space-between;
}
.list {
min-height: 120rpx;
}
.searchList {
width: 100%;
height: calc(100% - 186rpx);
overflow-y: scroll;
2026-04-01 08:46:32 +08:00
margin-top: 120rpx;
}
.list .item {
width: 100%;
min-height: 120rpx;
height: auto;
box-sizing: border-box;
padding: 10rpx;
border-radius: 8px;
background: #1a1a1a;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: center;
margin-top: 20rpx;
position: relative;
}
.list .item .leftImg {
width: 60rpx;
height: 60rpx;
}
.list .item .centertxt {
width: calc(100% - 60rpx);
height: 100%;
padding-left: 10rpx;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-evenly;
align-items: flex-start;
align-content: flex-start;
}
.list .item .rightIco {
position: absolute;
bottom: 0px;
right: 0px;
width: 0;
height: 0;
border-style: solid;
border-width: 0 0 30rpx 30rpx;
}
.list .item .leftImg .titleIco {
width: 100%;
height: 100%;
}
.list .item .name {
color: #ffffffde;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 400;
line-height: 36rpx;
text-align: left;
width: 100%;
}
.list .item .name.lbl {
font-size: 26rpx !important;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: flex-start;
}
.list .item .name .green {
color: limegreen;
}
.list .item .name .red {
color: #FF0000;
}
.list .item .id {
color: #ffffff99;
font-family: "PingFang SC";
font-size: 24rpx;
font-weight: 400;
line-height: 36rpx;
text-align: left;
}
.list .item .rightIco .img {
width: 45rpx;
height: 45rpx;
}
.openBlue {
padding: 30rpx;
width: 100%;
box-sizing: border-box;
height: auto;
}
.openBlue .txt {
color: rgba(255, 255, 255, 0.87);
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 400;
letter-spacing: 0.14rpx;
text-align: center;
}
.openBlue .btns {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: space-evenly;
margin-top: 50rpx;
width: 100%;
height: auto;
}
.openBlue .btn {
border-radius: 91rpx;
box-sizing: border-box;
width: 25%;
height: 60rpx;
text-align: center;
font-family: "PingFang SC";
font-size: 28rpx;
letter-spacing: 12rpx;
display: flex !important;
align-items: center;
letter-spacing: 0.375rem;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: center;
}
.openBlue .cancel {
border: 1px solid rgba(255, 255, 255, 1);
color: rgba(255, 255, 255, 1);
}
.openBlue .ok {
background-color: #BBE600;
color: #232323;
}
.margintLeft10 {
margin-left: 20rpx;
color: #BBE600;
font-size: 36rpx;
}
.bleIco {
width: 60rpx;
}
.th {
display: flex;
height: 70rpx;
line-height: 70rpx;
}
.bgred {
border-color: transparent transparent #FF0000 transparent;
}
.bggreen {
border-color: transparent transparent #4CAF50 transparent;
}
@keyframes rotateClockwise {
from {
transform: rotate(0deg);
/* 起始角度0度 */
}
to {
transform: rotate(360deg);
/* 结束角度360度顺时针一圈 */
}
}
/* 应用动画到元素 */
.rotateAnimation {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: center;
align-items: center;
width: 32rpx;
height: 32rpx;
animation: rotateClockwise 3s linear infinite;
}
2026-04-01 08:46:32 +08:00
.topStatric {
width: 100%;
box-sizing: border-box;
padding: 30rpx;
position: fixed;
top: 0rpx;
z-index: 99;
background-color: #121212;
}
/* #ifdef H5 */
.topStatric {
top: 44px;
}
.mainContent {
margin-top: 160rpx;
}
/* #endif */
/* #ifdef APP */
.mainContent {
margin-top: 240rpx;
}
.topStatric {
2026-04-01 08:46:32 +08:00
top: 90rpx
}
2026-04-01 08:46:32 +08:00
/* #endif */
.uni-mt-5 {
background-color: #000000;
}
.uni-easyinput__content {
background-color: #121212 !important;
}
2026-04-01 08:46:32 +08:00
.navbarRight .img {
width: 35rpx;
height: 35rpx;
margin-right: 20rpx;
}
.uni-navbar--fixed {
top: 0rpx;
}
/deep/ .uni-navbar--fixed {
top: 0px;
}
/deep/ .uni-navbar__placeholder {
display: none !important;
}
</style>