622 lines
16 KiB
Vue
622 lines
16 KiB
Vue
<template>
|
||
<view class="pages">
|
||
<u-navbar title="设备录入" :border-bottom="false" :background="bgc" title-size='32' title-color='#333'
|
||
:custom-back="btns" back-icon-color="#333" height='44'></u-navbar>
|
||
<!-- 顶部操作栏 -->
|
||
<view class="header-action">
|
||
<view class="header-title">
|
||
<text class="main-title">设备列表</text>
|
||
<text class="sub-title">附近的蓝牙设备</text>
|
||
</view>
|
||
<view class="console-btn" @click="btnkzt">
|
||
<u-icon name="grid-fill" size="28" color="#fff" style="margin-right: 6rpx;"></u-icon>
|
||
<text>控制台</text>
|
||
</view>
|
||
</view>
|
||
<!-- 设备列表 -->
|
||
<view class="device-list-container">
|
||
<view class="device-card" v-for="(item, index) in devicesLists" :key="index" v-if="item.name.slice(0, 5) == 'CTWG:'">
|
||
<view class="card-left" @click="createBLEConnections(item)">
|
||
<view class="row-header">
|
||
<text class="info-text sn-text">SN: {{item.sn == undefined ? '--' : item.sn}}</text>
|
||
<u-tag :text="item.flags ? '已录入' : '未录入'"
|
||
:type="item.flags ? 'success' : 'info'"
|
||
mode="light" shape="circle" size="mini"
|
||
class="status-tag"/>
|
||
</view>
|
||
<view class="row-info">
|
||
<text class="device-mac">MAC: {{item.name.substring(5)}}</text>
|
||
</view>
|
||
</view>
|
||
<view class="card-right">
|
||
<view class="button-group">
|
||
<u-button size="mini" shape="circle" :plain="true" type="primary" :ripple="true"
|
||
@click.stop="createBLEConnections(item)" class="action-btn" :custom-style="{padding: '0 20rpx', height: '50rpx'}">
|
||
蓝牙
|
||
</u-button>
|
||
<u-button size="mini" shape="circle" :plain="true" type="" :ripple="true"
|
||
v-if="item.sn" @click.stop="btnwl(item)" class="action-btn" :custom-style="{padding: '0 20rpx', height: '50rpx', marginLeft: '10rpx'}">
|
||
控制
|
||
</u-button>
|
||
</view>
|
||
<text class="info-text rssi-text" :style="{color: getRssiColor(item.RSSI)}">信号: {{item.RSSI}}</text>
|
||
</view>
|
||
</view>
|
||
<!-- 空状态 -->
|
||
<view v-if="devicesLists.length === 0 && !searching" class="empty-state">
|
||
<u-empty text="暂无发现设备" mode="search"></u-empty>
|
||
</view>
|
||
|
||
<!-- 底部占位,防止被按钮遮挡 -->
|
||
<view style="height: 180rpx;"></view>
|
||
</view>
|
||
<!-- 底部悬浮扫描按钮 -->
|
||
<view class="footer-fixed">
|
||
<u-button type="warning" shape="circle" :ripple="true" :loading="searching"
|
||
class="scan-btn" @click="Search"
|
||
:custom-style="{height: '90rpx', fontSize: '32rpx', boxShadow: '0 8rpx 20rpx rgba(206, 158, 16, 0.3)'}">
|
||
{{ searching ? '正在扫描...' : '重新扫描' }}
|
||
</u-button>
|
||
</view>
|
||
<!-- 提示弹窗 -->
|
||
<u-popup v-model="titleflag" mode="center" border-radius="24" width="600">
|
||
<view class="popup-content">
|
||
<view class="popup-title">温馨提示</view>
|
||
<view class="popup-body">
|
||
<view class="tips-text">未扫描到附近未绑定设备:</view>
|
||
<view class="tips-item">1. 确保待连接设备在附近且蓝牙处于打开状态。</view>
|
||
<view class="tips-item">2. 确保设备未与其他设备进行蓝牙连接。</view>
|
||
<view class="tips-item">3. 确保设备未被添加过。</view>
|
||
</view>
|
||
<view class="popup-btn">
|
||
<u-button type="warning" shape="circle" @click="btnyc">我知道了</u-button>
|
||
</view>
|
||
</view>
|
||
</u-popup>
|
||
<!-- 遮罩层 (保留逻辑) -->
|
||
<view v-if="mengcflag" class="global-mask"></view>
|
||
<!-- 选择蓝牙型号 -->
|
||
<u-select v-model="shows" :list="arr" @confirm="confirm"></u-select>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
const app = getApp();
|
||
var xBlufi = require("@/components/blufi/xBlufi.js");
|
||
export default {
|
||
data() {
|
||
return {
|
||
mengcflag: false,
|
||
titleflag: false, //提示隐藏
|
||
devicesList: [],
|
||
devicesLists: [],
|
||
searching: false,
|
||
texts: '正在扫描设备...',
|
||
btnflag: true,
|
||
tishiflag: false,
|
||
option: '',
|
||
bluthlist: [], //蓝牙数组
|
||
status: 'loading',
|
||
statusflag: false,
|
||
Bluetoothmac: '',
|
||
gps: {},
|
||
mac: '',
|
||
status: false,
|
||
storeId: '',
|
||
bgc: {
|
||
backgroundColor: "#f5f6f7",
|
||
},
|
||
lurulist: [],
|
||
arr: [],
|
||
shows: false,
|
||
arrname: '',
|
||
valuexh: '',
|
||
deviceId: '',
|
||
arrs: '',
|
||
sn: '输入SN',
|
||
snname: '',
|
||
qrResult:'',
|
||
name:'',
|
||
ver_data:null
|
||
}
|
||
},
|
||
onLoad(option) {
|
||
this.getluru()
|
||
// this.getxingh()
|
||
this.storeId = option.sn
|
||
},
|
||
onUnload: function() {
|
||
console.log("unload ");
|
||
xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent);
|
||
wx.closeBLEConnection({
|
||
deviceId: this.deviceId,
|
||
})
|
||
},
|
||
methods: {
|
||
getRssiColor(rssi) {
|
||
if (!rssi) return '#909399';
|
||
if (rssi > -60) return '#19be6b'; // 优
|
||
if (rssi > -80) return '#ff9900'; // 中
|
||
return '#fa3534'; // 差
|
||
},
|
||
btnwl(item){
|
||
uni.reLaunch({
|
||
url:'/page_newyemian/wgkongzhi?sn=' + item.sn
|
||
})
|
||
},
|
||
btns(){
|
||
uni.reLaunch({
|
||
url:'/pages/my'
|
||
})
|
||
},
|
||
// 点击跳转到控制台
|
||
btnkzt(){
|
||
uni.reLaunch({
|
||
url:'/page_newyemian/wgkongzhi'
|
||
})
|
||
},
|
||
// 获取型号列表
|
||
getxingh() {
|
||
this.$u.get(`/app/model/admin/all`).then(res => {
|
||
if (res.code == 200) {
|
||
this.arr = res.data
|
||
this.arr.forEach(item => {
|
||
if (item.hasOwnProperty('modelId')) {
|
||
item.value = item.modelId;
|
||
}
|
||
if (item.hasOwnProperty('name')) {
|
||
item.label = item.name;
|
||
}
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 选择型号
|
||
confirm(e) {
|
||
this.devicesLists.forEach(item => {
|
||
if (item.name == this.arrname) {
|
||
item.xuanz = e[0].label
|
||
this.valuexh = e[0].value
|
||
}
|
||
})
|
||
},
|
||
// 点击隐藏没有搜索到设备的提示
|
||
btnyc() {
|
||
this.titleflag = false
|
||
},
|
||
// 获取连接蓝牙收取到的信息
|
||
funListenDeviceMsgEvent: function(options) {
|
||
switch (options.type) {
|
||
case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_MY_DATA:
|
||
let loadPercent = options.data;
|
||
let loadText = '文件读取中'
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA:
|
||
// this.ver_data = this.parseCustomData(options.data)
|
||
console.log("1收到设备发来的自定义数据结果:", options.data)
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS:
|
||
if (options.result) {
|
||
// 将获取的蓝牙列表进行匹配,找到需要;连接的那个
|
||
this.devicesList = options.data
|
||
this.devicesList.forEach(device => {
|
||
const mac = device.name.substring(5)
|
||
if (device.name == this.qrResult) {
|
||
this.deviceId = device.deviceId
|
||
this.name = device.name
|
||
this.mac = device.name.slice(5, 17)
|
||
}
|
||
})
|
||
}
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_CONNECTED:
|
||
// console.log("连接回调:" + JSON.stringify(options))
|
||
if (options.result) {
|
||
setTimeout(()=>{
|
||
this.bluetoothflag = false
|
||
},3000)
|
||
{
|
||
console.log("连接回调options.data.deviceId:" + options.data.deviceId,
|
||
"连接回调options.data.name:" + options.data.name)
|
||
}
|
||
} else {
|
||
this.shibaiflag = true
|
||
this.bluetoothflag = false
|
||
}
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START:
|
||
if (!options.result) {
|
||
this.mengcflag = false
|
||
uni.hideLoading()
|
||
console.log("蓝牙未开启", options);
|
||
uni.showToast({
|
||
title: '蓝牙未开启,请打开手机蓝牙',
|
||
icon: 'none',
|
||
duration: 3000
|
||
})
|
||
} else {
|
||
this.searching = true
|
||
}
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP:
|
||
if (options.result) {
|
||
// 获取所有蓝牙列表之后将每个蓝牙信息中都添加一个选择型号的字段
|
||
let uniqueDevicesList = Array.from(new Set(this.devicesList));
|
||
this.devicesLists = uniqueDevicesList.map(device => {
|
||
const deviceId = device.name.substring(5);
|
||
const newDevice = {
|
||
...device,
|
||
xuanz: "请选择",
|
||
}; // 直接在复制时添加 xuanz 字段
|
||
return newDevice;
|
||
})
|
||
let devicesarr = options.data
|
||
this.devicesList.forEach(device => {
|
||
if (device.name.substring(0, 4) == "CTWG") {
|
||
this.devicesList.push(device);
|
||
let uniqueDevicesList = Array.from(new Set(this.devicesList));
|
||
this.devicesLists = uniqueDevicesList.filter(device => {
|
||
const deviceId = device.name.substring(5);
|
||
return deviceId
|
||
})
|
||
}
|
||
})
|
||
// console.log('蓝牙停止搜索ok')
|
||
this.mengcflag = false
|
||
if (this.devicesLists.length == 0) {
|
||
this.titleflag = true
|
||
} else {
|
||
let arr = []
|
||
// console.log(this.devicesLists,'101010');
|
||
this.devicesLists.forEach(item => {
|
||
arr.push(item.name.slice(5))
|
||
})
|
||
// let data = {
|
||
// macList:arr
|
||
// }
|
||
this.$u.get(`/app/device/list?macList=${arr}`).then(res => {
|
||
if (res.code == 200 && Array.isArray(res.data)) {
|
||
const existingDevices = new Map(res.data.map(item => [item.mac, true])); // 使用Map来存储已找到的MAC
|
||
this.devicesLists = this.devicesLists.map(device => {
|
||
const trimmedName = device.name.slice(5); // 假设name中包含MAC地址的一部分
|
||
const mac = trimmedName; // 如果trimmedName直接就是MAC,则不需要再处理
|
||
device.found = existingDevices.has(mac); // 添加一个found属性来标记是否找到
|
||
if (device.found) {
|
||
const sn = res.data.find(val => val.mac === mac)?.sn; // 从res.data中找到匹配的sn
|
||
if (sn) {
|
||
device.sn = sn; // 设置sn
|
||
}
|
||
device.flags = true; // 设置flags为true,因为找到了匹配的MAC
|
||
} else {
|
||
device.flags = false; // 可选:如果你想要明确表示未找到
|
||
}
|
||
return device; // 但map函数仍然需要return来保持结构
|
||
});
|
||
this.devicesLists.sort((a, b) => {
|
||
if (a.found && !b.found) return 1; // b排在a前面(即a在后面)
|
||
if (!a.found && b.found) return -1; // a排在b前面
|
||
return 0;
|
||
});
|
||
}
|
||
})
|
||
setTimeout(()=>{
|
||
uni.hideLoading()
|
||
},2000)
|
||
}
|
||
} else {
|
||
//蓝牙停止搜索失败
|
||
this.mengcflag = false
|
||
setTimeout(()=>{
|
||
uni.hideLoading()
|
||
},2000)
|
||
console.log('蓝牙停止搜索失败');
|
||
}
|
||
this.searching = false
|
||
break
|
||
}
|
||
},
|
||
|
||
// 发送开关
|
||
createBLEConnections(e) {
|
||
console.log(e);
|
||
let Bluetoothmac = e.name.substring(5)
|
||
if(e.sn){
|
||
uni.reLaunch({
|
||
url:'/page_newyemian/wgluru-add?mac=' + Bluetoothmac + '&sn=' + e.sn
|
||
})
|
||
}else{
|
||
uni.reLaunch({
|
||
url:'/page_newyemian/wgluru-add?mac=' + Bluetoothmac
|
||
})
|
||
}
|
||
},
|
||
// 请求已经录入设备的mac
|
||
getluru() {
|
||
xBlufi.initXBlufi(1);
|
||
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent);
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': true
|
||
})
|
||
// 两秒后停止蓝牙搜索
|
||
setTimeout(() => {
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': false
|
||
});
|
||
this.status = true
|
||
}, 1000)
|
||
},
|
||
//4、建立连接
|
||
createBLEConnection(e) {
|
||
this.mengcflag = true
|
||
uni.showLoading({
|
||
title: '录入中...'
|
||
})
|
||
this.mac = e.name.substring(5)
|
||
// 录入设备
|
||
let data = {
|
||
sn: this.storeId,
|
||
mac: this.mac,
|
||
modelId: this.valuexh
|
||
}
|
||
this.$u.post('/app/device', data).then((res) => {
|
||
if (res.code == 200) {
|
||
uni.showToast({
|
||
title: '设备:' + this.mac + '已录入成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
this.mengcflag = false
|
||
uni.hideLoading()
|
||
this.Search()
|
||
uni.removeStorageSync('mac');
|
||
} else {
|
||
this.mengcflag = false
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
}
|
||
})
|
||
},
|
||
// 点击重新搜索
|
||
Search() {
|
||
this.mengcflag = true
|
||
uni.showLoading({
|
||
title: '扫描中...'
|
||
})
|
||
xBlufi.initXBlufi(1);
|
||
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent);
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': true
|
||
})
|
||
// 重新搜索清空蓝牙数组
|
||
this.bluthlist = []
|
||
this.devicesList = []
|
||
this.devicesLists = []
|
||
this.arrs = []
|
||
this.statusflag = true
|
||
this.texts = '正在扫描蓝牙设备...'
|
||
setTimeout(() => {
|
||
this.statusflag = false
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': false
|
||
});
|
||
uni.hideLoading()
|
||
// 判断是否存在设备
|
||
if (this.devicesList.length == 0) {
|
||
this.tishiflag = true
|
||
this.texts = '扫描完毕,暂无发现设备'
|
||
} else {
|
||
this.texts = '扫描到以下设备,请点击录入!'
|
||
}
|
||
}, 2000)
|
||
},
|
||
// 点击隐藏没有设备提示
|
||
btnhd() {
|
||
this.tishiflag = false
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
page {
|
||
background-color: #f5f6f7 !important;
|
||
min-height: 100vh;
|
||
}
|
||
::v-deep .u-btn--warning{
|
||
background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%)
|
||
}
|
||
.pages {
|
||
padding: 0 30rpx;
|
||
padding-bottom: 40rpx;
|
||
}
|
||
|
||
.header-action {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 30rpx 0;
|
||
margin-bottom: 20rpx;
|
||
|
||
.header-title {
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.main-title {
|
||
font-size: 40rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.sub-title {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
.console-btn {
|
||
background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
|
||
color: #fff;
|
||
padding: 12rpx 30rpx;
|
||
border-radius: 50rpx;
|
||
font-size: 26rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
box-shadow: 0 4rpx 12rpx rgba(82, 196, 26, 0.3);
|
||
transition: all 0.3s;
|
||
|
||
&:active {
|
||
transform: scale(0.96);
|
||
opacity: 0.9;
|
||
}
|
||
}
|
||
}
|
||
|
||
.device-list-container {
|
||
width: 100%;
|
||
}
|
||
|
||
.device-card {
|
||
background: #ffffff;
|
||
border-radius: 20rpx;
|
||
margin-bottom: 20rpx;
|
||
padding: 24rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
&:active {
|
||
background-color: #f9f9f9;
|
||
}
|
||
|
||
.card-left {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
.row-header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 12rpx;
|
||
flex-wrap: wrap;
|
||
.info-text {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
&.sn-text {
|
||
margin-right: 16rpx;
|
||
}
|
||
}
|
||
.status-tag {
|
||
flex-shrink: 0;
|
||
margin-right: 16rpx;
|
||
margin-bottom: 6rpx;
|
||
}
|
||
}
|
||
.row-info {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.device-mac {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
}
|
||
}
|
||
|
||
.card-right {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
justify-content: space-between;
|
||
margin-left: 20rpx;
|
||
flex-shrink: 0;
|
||
|
||
.button-group {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.action-btn {
|
||
margin: 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.rssi-text {
|
||
font-size: 26rpx;
|
||
text-align: right;
|
||
}
|
||
}
|
||
}
|
||
|
||
.footer-fixed {
|
||
position: fixed;
|
||
bottom: 60rpx;
|
||
left: 0;
|
||
right: 0;
|
||
padding: 0 60rpx;
|
||
z-index: 100;
|
||
}
|
||
|
||
.empty-state {
|
||
margin-top: 100rpx;
|
||
}
|
||
|
||
.popup-content {
|
||
padding: 40rpx;
|
||
background: #fff;
|
||
|
||
.popup-title {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
text-align: center;
|
||
margin-bottom: 30rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.popup-body {
|
||
margin-bottom: 40rpx;
|
||
|
||
.tips-text {
|
||
font-size: 30rpx;
|
||
font-weight: bold;
|
||
margin-bottom: 16rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.tips-item {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
line-height: 1.6;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
}
|
||
|
||
.popup-btn {
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
}
|
||
|
||
.global-mask {
|
||
width: 100%;
|
||
height: 100vh;
|
||
background-color: #000;
|
||
opacity: 0.5;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
z-index: 999;
|
||
}
|
||
</style> |