Sprinkler-app/page_newyemian/wgluru.vue
2026-01-17 17:37:00 +08:00

622 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>