Sprinkler-app/page_user/lanya.vue
2025-05-19 16:32:27 +08:00

589 lines
13 KiB
Vue
Raw Permalink 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>
<u-navbar :is-back="true" title='添加设备' title-color="#000" :border-bottom="false" :background="bgc" id="navbar">
</u-navbar>
<view class="page">
<!-- 有搜索到设备 -->
<view class="you" v-if="flags">
<view class="topone">
<image src="https://api.ccttiot.com/smartmeter/img/static/ubrPcpGQEXTadkBa1gKh" mode=""></image>
扫描到以下设备点击添加
</view>
<view class="toptwo">
如未找到想添加的设备点击重新搜索
</view>
<view class="list">
<view class="list_item" v-for="(item,index) in jiaohuaqi" :key="index" :class="{ show: item.show }">
<image :src="item.modelPicture" mode=""></image>
<view class="cen">
<view class="name" style="color: #ccc;" v-if="item.userId && item.userId != userid">
{{item.modelName == undefined ? '' : item.modelName}}
</view>
<view class="name" v-else>
{{item.modelName == undefined ? '' : item.modelName}}
</view>
<view class="devmac">
MAC{{item.mac == undefined ? item.name.slice(-12) : item.mac}}
</view>
<view class="devmac">
信号:{{item.ssid == undefined ? '--' : item.ssid}}
</view>
</view>
<view class="add" style="color: #ccc;border: 1px solid #ccc;" v-if="item.userId">
已添加
</view>
<view class="add" @click="btnadd(item)" v-else>
添加
</view>
</view>
</view>
</view>
<!-- 未搜索到设备 -->
<view class="wei" v-else>
<image src="https://api.ccttiot.com/smartmeter/img/static/uQ4g6A27FGtF34ebOtea" mode=""></image>
<view class="sbname">
搜索附近的设备失败
</view>
<view class="sbwz">
搜索失败点击重新搜索注意打开蓝牙
</view>
</view>
<!-- 点击搜索 -->
<view class="btnss" @click="handleSearch" :class="{ 'searching': !flag }">
重新搜索
</view>
</view>
<!-- 自定义名称弹框 -->
<u-popup v-model="showNameDialog" mode="center" border-radius="14" width="600rpx">
<view class="custom-name-dialog">
<view class="dialog-title">设备名称</view>
<u-input v-model="customDeviceName" placeholder="请输入设备名称" />
<view class="dialog-btns">
<view class="btn cancel" @click="showNameDialog = false">取消</view>
<view class="btn confirm" @click="confirmAddDevice">确定</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
var xBlufi = require("@/components/blufi/xBlufi.js");
export default {
data() {
return {
bgc: {
backgroundColor: "#fff",
},
active: 1,
flag: true,
devicesList: [],
deviceId: '',
name: '',
mac: '',
flags: true,
userid: '',
arr: '',
jiaohuaqi: [],
getpre: [],
showNameDialog: false,
customDeviceName: '',
currentDevice: null,
searchTimer: null,
checkTimer: null,
isSearching: false,
searchTimeout: null,
throttleTimer: null,
lastSearchTime: 0,
searchInterval: 2000, // 搜索间隔2秒
displayQueue: [], // 显示队列
processingQueue: false, // 是否正在处理队列
}
},
// 分享到好友(会话)
onShareAppMessage: function() {
return {
title: '绿小能',
path: '/pages/index/index'
}
},
// 分享到朋友圈
onShareTimeline: function() {
return {
title: '绿小能',
query: '',
path: '/pages/index/index'
}
},
onLoad() {
this.getmodel()
this.getinfo()
},
onShow() {
this.startSearch()
},
onHide() {
this.stopSearch()
},
onUnload() {
this.stopSearch()
},
methods: {
// 获取用户信息
getinfo() {
this.$u.get(`/appVerify/profile`).then((res) => {
if (res.code == 200) {
this.userid = res.data.userId
} else if (res.code == 401) {
uni.showModal({
title: '提示',
content: '您还未登录,是否前去登录?',
success: function(res) {
if (res.confirm) {
uni.navigateTo({
url: '/pages/login/login'
})
} else if (res.cancel) {
}
}
})
}
})
},
// 点击添加按钮
btnadd(e) {
this.currentDevice = e;
this.customDeviceName = e.modelName || '未知设备'; // 默认使用型号名称
this.showNameDialog = true;
},
// 确认添加设备
confirmAddDevice() {
if (!this.customDeviceName.trim()) {
uni.showToast({
title: '请输入设备名称',
icon: 'none'
});
return;
}
let mac = this.currentDevice.name.slice(-12);
let data = {
mac: mac,
userId: this.userid,
pre: this.currentDevice.pre,
deviceName: this.customDeviceName
}
console.log(data,'参数');
this.$u.post(`/app/bandDevice`, data).then((res) => {
if (res.code == 200) {
uni.showToast({
title: '添加成功',
icon: 'success',
duration: 3000
})
this.showNameDialog = false;
setTimeout(() => {
uni.navigateBack()
}, 2000)
} else {
console.log(res,'报错');
uni.showToast({
title: res.msg,
icon: 'none',
duration: 3000
})
}
})
},
getmodel() {
this.$u.get(`/app/getAllModelList`).then(res => {
if (res.code == 200) {
this.getpre = res.data
}
})
},
getpipei(pre) {
// 添加默认返回值防止undefined
return this.getpre.find(item => item.pre == pre) || {
modelName: '未知型号',
picture: ''
};
},
// 开始搜索
startSearch() {
if (this.isSearching) return
this.isSearching = true
this.jiaohuaqi = []
this.displayQueue = []
this.processingQueue = false
this.flag = false
// 开始蓝牙搜索
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
xBlufi.notifyStartDiscoverBle({ 'isStart': true })
// 30秒后自动停止搜索
this.searchTimeout = setTimeout(() => {
this.stopSearch()
}, 30000)
},
// 停止搜索
stopSearch() {
this.isSearching = false
if (this.checkTimer) {
clearInterval(this.checkTimer)
this.checkTimer = null
}
if (this.searchTimeout) {
clearTimeout(this.searchTimeout)
this.searchTimeout = null
}
if (this.throttleTimer) {
clearTimeout(this.throttleTimer)
this.throttleTimer = null
}
xBlufi.notifyStartDiscoverBle({ 'isStart': false })
this.flag = true
},
// 处理显示队列
processDisplayQueue() {
if (this.processingQueue || this.displayQueue.length === 0) return
this.processingQueue = true
const device = this.displayQueue.shift()
// 检查设备是否已存在
if (!this.jiaohuaqi.some(item => item.name === device.name)) {
this.jiaohuaqi.push(device)
}
// 延迟处理下一个设备
setTimeout(() => {
this.processingQueue = false
this.processDisplayQueue()
}, 500) // 每个设备显示间隔500ms
},
// 添加设备到显示队列
addToDisplayQueue(device) {
this.displayQueue.push(device)
if (!this.processingQueue) {
this.processDisplayQueue()
}
},
// 更新设备列表
updateDeviceList(existList) {
const newDevices = this.devicesList.filter(item => {
const mac = item.name.slice(-12)
return !this.jiaohuaqi.some(device => device.name === mac) &&
!this.displayQueue.some(device => device.name === mac)
})
newDevices.forEach(item => {
const mac = item.name.slice(-12)
const pre = item.name.slice(0, 5)
const ssid = item.RSSI
const matched = this.getpipei(pre)
const existDevice = existList.find(val => val.mac === mac)
const newDevice = {
name: mac,
modelName: matched.modelName,
modelPicture: matched.picture,
pre: pre,
userId: existDevice ? existDevice.userId : null,
ssid: ssid
}
this.addToDisplayQueue(newDevice)
})
},
// 获取附近蓝牙设备列表
funListenDeviceMsgEvent: function(options) {
switch (options.type) {
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS:
if (options.result) {
const now = Date.now()
if (now - this.lastSearchTime < this.searchInterval) {
return
}
this.lastSearchTime = now
let devicesarr = []
this.devicesList = options.data
options.data.forEach(item => {
devicesarr.push(item.name.slice(-12))
})
this.arr = devicesarr.join(',')
// 使用节流处理设备检查
if (this.throttleTimer) {
clearTimeout(this.throttleTimer)
}
this.throttleTimer = setTimeout(() => {
if (this.devicesList.length > 0) {
const data = { mac: this.arr }
this.$u.post(`/app/getExistListByMacs`, data)
.then(res => {
if (res.code === 200) {
this.updateDeviceList(res.data)
}
})
.catch(error => {
console.error('请求失败:', error)
})
}
}, 500) // 500ms的节流时间
}
break
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START:
if (!options.result) {
uni.showToast({
title: '蓝牙未开启',
icon: 'none',
duration: 3000
})
this.flags = false
return
}
break
}
},
btnss() {
this.stopSearch()
this.jiaohuaqi = []
this.displayQueue = []
this.processingQueue = false
this.startSearch()
},
// 处理搜索按钮点击
handleSearch() {
if (!this.flag) {
uni.showToast({
title: '请等待蓝牙搜索完成后再操作',
icon: 'none',
duration: 2000
})
return
}
this.btnss()
},
}
}
</script>
<style lang="less">
/deep/ .u-input__input{
border: 1px solid #ccc;
border-radius: 10rpx;
padding-left: 10rpx;
box-sizing: border-box;
}
/deep/ .u-title {
margin-bottom: 22rpx;
}
/deep/ .uicon-nav-back {
margin-bottom: 22rpx;
}
.page {
padding-bottom: 300rpx;
box-sizing: border-box;
}
.wei {
text-align: center;
image {
width: 380rpx;
height: 394rpx;
}
.sbname {
font-size: 40rpx;
color: #3D3D3D;
margin-top: 80rpx;
width: 100%;
text-align: center;
}
.sbwz {
font-size: 28rpx;
color: #737B80;
margin-top: 24rpx;
width: 100%;
text-align: center;
}
}
.btnss {
width: 512rpx;
height: 92rpx;
background: #48893B;
border-radius: 46rpx 46rpx 46rpx 46rpx;
border-radius: 50rpx;
text-align: center;
line-height: 92rpx;
font-weight: 600;
font-size: 40rpx;
color: #FFFFFF;
position: fixed;
left: 50%;
transform: translateX(-50%);
bottom: 106rpx;
transition: all 0.3s ease;
&.searching {
background: #E5E5E5;
color: #666666;
}
}
.list {
width: 100%;
border-radius: 20rpx;
margin: auto;
margin-top: 72rpx;
will-change: transform; // 优化动画性能
.list_item {
margin-top: 18rpx;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 152rpx;
background: #FFFFFF;
border-radius: 20rpx;
box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08);
padding: 18rpx 30rpx;
box-sizing: border-box;
animation: slideIn 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
opacity: 0;
transform: translateX(-100%);
will-change: transform, opacity; // 优化动画性能
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(-100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
image {
width: 94rpx;
height: 94rpx;
}
.cen {
.name {
font-size: 32rpx;
color: #50565A;
}
.devmac {
font-size: 24rpx;
color: #BDBCBC;
margin-top: 6rpx;
}
}
.add {
width: 108rpx;
height: 60rpx;
background: #FFFFFF;
border: 3rpx solid #48893B;
filter: blur(0px);
border-radius: 20rpx;
text-align: center;
line-height: 60rpx;
font-size: 28rpx;
color: #48893B;
}
}
}
page {
width: 100%;
padding: 20rpx 64rpx;
box-sizing: border-box;
background-color: #fff;
}
.topone {
font-size: 36rpx;
color: #3D3D3D;
display: flex;
image {
width: 48rpx;
height: 48rpx;
}
}
.toptwo {
font-size: 28rpx;
color: #737B7F;
margin-top: 14rpx;
width: 100%;
padding-left: 48rpx;
box-sizing: border-box;
}
.custom-name-dialog {
background: #fff;
padding: 40rpx;
.dialog-title {
font-size: 32rpx;
color: #333;
text-align: center;
margin-bottom: 30rpx;
}
.dialog-btns {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
.btn {
width: 240rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border-radius: 40rpx;
font-size: 28rpx;
&.cancel {
background: #f5f5f5;
color: #666;
}
&.confirm {
background: #48893B;
color: #fff;
}
}
}
}
</style>