baodeng_xcx/page_shanghu/device/index.vue
2025-05-14 15:14:12 +08:00

563 lines
14 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="device-management">
<!-- 顶部导航栏 -->
<u-navbar title="设备管理" :border-bottom="false" :background="{ background: '#1a1a1a' }" back-icon-color="#fff"
title-color='#fff' title-size='36' height='36' id="navbar">
</u-navbar>
<!-- 搜索和筛选区域 -->
<view class="search-filter">
<view class="search-box">
<u-icon name="search" color="#666" size="32"></u-icon>
<input type="text" placeholder="搜索设备编号" placeholder-style="color: #666;" v-model="searchText"
@input="handleSearch" />
<u-icon name="scan" color="#666" @click="saoma" size="32"></u-icon>
</view>
<view class="filters">
<view class="filter-item" @tap="showStorePopup">
<text>门店:{{storesname}}</text>
<u-icon name="arrow-down" color="#666" size="28"></u-icon>
</view>
<view class="filter-item" @tap="showStatusPopup">
<text>状态:{{statusname}}</text>
<u-icon name="arrow-down" color="#666" size="28"></u-icon>
</view>
</view>
</view>
<!-- 设备列表 -->
<scroll-view scroll-y class="device-list" @scrolltolower="handqixing" refresher-enabled @refresherrefresh="onRefresh" :refresher-triggered="isRefreshing" refresher-default-style="white">
<view v-for="(device,index) in deviceList" :key="index" class="device-item">
<view class="device-header" @click="btnxq(device.deviceId)">
<text class="sn">{{device.deviceName == null ? '--' : device.deviceName}}</text>
<text :class="['status', device.onlineStatus == 1 ? 'online' : 'offline']">
<view class="status-dot"></view>
{{device.onlineStatus == 1 ? '在线' : '离线'}}
</text>
</view>
<view class="device-content" @click="btnxq(device.deviceId)">
<image src="https://api.ccttiot.com/smartmeter/img/static/uyKu3YhTED9tkOUSs919" mode="aspectFit"
class="device-image" />
<view class="device-info">
<view class="info-row">
<text class="label">SN</text>
<text class="value">{{device.deviceNo == null ? '--' : device.deviceNo}}</text>
</view>
<view class="info-row">
<text class="label">门店名称:</text>
<text class="value">{{device.storeName == null ? '--' : device.storeName}}</text>
</view>
<view class="info-row">
<text class="label">设备状态:</text>
<text class="value" v-if="device.status == 1">正常</text>
<text class="value" v-if="device.status == 2">使用中</text>
<text class="value" v-if="device.status == 3">维修中</text>
</view>
<view class="info-row">
<text class="label">亮灯时长:</text>
<text class="value">{{device.duration == null ? 0 : device.duration}}s</text>
</view>
</view>
</view>
<view class="device-footer">
<view class=""></view>
<view class="" style="display: flex;align-items: center;">
<u-switch v-model="device.powerStatus == 1"
@change="(e) => handleSwitch(e, device.deviceId,index)" style="transform:scale(0.8);"
active-color="#FF4D7D"></u-switch>
<button class="code-btn" @tap="showDeviceCode(device.deviceNo)">设备码</button>
</view>
</view>
</view>
<view class="" style="font-size: 28rpx;color: #808080;margin-top: 30rpx;text-align: center;width: 100%;">
没有更多设备了...</view>
</scroll-view>
<!-- 弹出层 -->
<u-popup v-model="showStorePicker" mode="bottom">
<view class="popup-content">
<view class="popup-header">
<text>选择门店</text>
<u-icon name="close" @tap="showStorePicker = false"></u-icon>
</view>
<view class="popup-list">
<view v-for="(store, index) in stores" :key="index" class="popup-item"
:class="{ active: selectedStore === index }" @tap="selectStore(index)">
{{store.name}}
</view>
</view>
</view>
</u-popup>
<u-popup v-model="showStatusPicker" mode="bottom">
<view class="popup-content">
<view class="popup-header">
<text>选择状态</text>
<u-icon name="close" @tap="showStatusPicker = false"></u-icon>
</view>
<view class="popup-list">
<view v-for="(status, index) in statusOptions" :key="index" class="popup-item"
:class="{ active: selectedStatus === index }" @tap="selectStatus(index)">
{{status}}
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
var xBlufi = require("@/components/blufi/xBlufi.js")
export default {
data() {
return {
searchText: '',
stores: [{
name: '全部',
id: ''
}],
storesname: '全部',
statusname: '全部',
statusOptions: ['全部', '在线', '离线'],
selectedStore: 0,
selectedStatus: 0,
deviceList: [],
showStorePicker: false,
showStatusPicker: false,
bgc: {
background: '#1a1a1a'
},
storeId: '',
devicestatus: '',
bdsn: '',
user: {},
pagesum:'',
total:'',
isRefreshing:false
}
},
onLoad(option) {
// xBlufi.initXBlufi(1)
if(option.storeId){
this.storeId = option.storeId
this.storesname = option.tit
}
},
onShow() {
this.pagesum = 1
this.getinfo()
this.getlist()
this.getshop()
this.
xBlufi.notifyStartDiscoverBle({
'isStart': true
})
},
methods: {
// 下拉刷新
onRefresh() {
this.isRefreshing = true
this.pageNum = 1
this.getlist()
setTimeout(() => {
this.isRefreshing = false
}, 1000)
},
// 点击扫码绑定设备
saoma() {
uni.scanCode({
onlyFromCamera: true,
scanType: ['qrCode'],
success: res => {
console.log(res);
function getQueryParam(url, paramName) {
let regex = new RegExp(`[?&]${paramName}=([^&]*)`)
let results = regex.exec(url)
return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null
}
let sceneValue = res.result
let decodedValue = decodeURIComponent(sceneValue)
this.bdsn = getQueryParam(decodedValue, 's')
console.log(this.bdsn, 'snsnsnsnsn');
let data = {
deviceNo: this.bdsn
}
this.$u.put(`/bst/device/bindMch?mchId=${this.user.userId}`, data).then(res => {
if (res.code == 200) {
uni.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
})
this.pagesum = 1
this.getlist()
} else if (res.msg == null) {
uni.showToast({
title: '未知错误',
icon: 'none',
duration: 2000
})
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
},
fail: err => {
console.error('扫描失败:', err)
uni.showToast({
title: '扫描失败',
icon: 'none'
})
}
})
},
// 获取用户信息
getinfo() {
this.$u.get(`/getInfo`).then(res => {
if (res.code == 200) {
this.user = res.user
}
})
},
// 查询设备列表
getlist() {
this.$u.get(`/bst/device/list?pageNum=${this.pagesum}&pageSize=20&storeId=${this.storeId}&onlineStatus=${this.devicestatus}&deviceNo=${this.searchText}`).then(res => {
if (res.code == 200) {
this.total = res.total
if(this.pagesum == 1){
this.deviceList = res.rows
this.pagesum++
}else{
this.deviceList = this.deviceList.concat(res.rows)
this.pagesum++
}
} else if (res.msg == null) {
uni.showToast({
title: '未知错误',
icon: 'none',
duration: 2000
})
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
},
// 获取所有店铺
getshop() {
this.$u.get(`/bst/store/list?pageNum=1&pageSize=999`).then(res => {
if (res.code == 200) {
res.rows.forEach((item) => {
this.stores.push({
name: item.storeName,
id: item.storeId
})
})
}
})
},
// 点击跳转到详情
btnxq(deviceId) {
// uni.navigateTo({
// url: '/page_shanghu/device/devicexq?deviceId=' + deviceId
// })
uni.navigateTo({
url: '/page_user/devicekzxq?deviceId=' + deviceId
})
// console.log('跳转到详情');
},
// 滚动骑行订单到底部分页请求
handqixing() {
if(this.total > this.deviceList.length){
this.getlist()
}else{
console.log(11);
}
},
// 进行搜索
handleSearch(e) {
this.pagesum = 1
this.searchText = e.detail.value
this.getlist()
},
// 选择店铺
showStorePopup() {
this.showStorePicker = true
},
//选择状态
showStatusPopup() {
this.showStatusPicker = true
},
//筛选门店条件
selectStore(index) {
this.storesname = this.stores[index].name
this.storeId = this.stores[index].id
console.log(this.storesname, this.storeId, '0000')
this.selectedStore = index
this.showStorePicker = false
this.pagesum = 1
this.getlist()
},
// 筛选在线离线条件
selectStatus(index) {
this.statusname = this.statusOptions[index]
this.selectedStatus = index
if (index == 0) {
this.devicestatus = ''
} else if (index == 1) {
this.devicestatus = 1
} else if (index == 2) {
this.devicestatus = 0
}
this.showStatusPicker = false
this.pagesum = 1
this.getlist()
},
// 点击开关
handleSwitch(e, deviceId, index) {
console.log(e, deviceId, index)
if (this.deviceList[index].powerStatus == 0) {
this.$u.put(`/bst/device/iot/${deviceId}/switch?open=true`).then(res => {
if (res.code == 200) {
this.deviceList[index].powerStatus = 1
uni.showToast({
title: res.msg,
icon: 'success',
duration: 2000
})
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
} else {
this.$u.put(`/bst/device/iot/${deviceId}/switch?open=false`).then(res => {
if (res.code == 200) {
this.deviceList[index].powerStatus = 0
uni.showToast({
title: res.msg,
icon: 'success',
duration: 2000
})
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
}
},
// 点击设备码
showDeviceCode(sn) {
uni.navigateTo({
url: '/page_shanghu/ewm?sn=' + sn
})
},
}
}
</script>
<style lang="scss" scoped>
/deep/ .u-iconfont {
color: #fff !important;
}
.device-management {
min-height: 100vh;
background-color: #1a1a1a;
.search-filter {
padding: 20rpx;
background-color: #1a1a1a;
.search-box {
display: flex;
align-items: center;
background-color: #2c2c2c;
padding: 15rpx 30rpx;
border-radius: 40rpx;
margin-bottom: 30rpx;
input {
flex: 1;
font-size: 28rpx;
color: #fff;
margin: 0 20rpx;
}
}
.filters {
display: flex;
justify-content: space-between;
.filter-item {
flex: 1;
margin: 0 10rpx;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #2c2c2c;
padding: 15rpx 30rpx;
border-radius: 40rpx;
text {
font-size: 28rpx;
color: #fff;
}
}
}
}
.device-list {
width: 680rpx;
margin: auto;
height: 76vh;
overflow: scroll;
.device-item {
background-color: #2c2c2c;
margin-bottom: 20rpx;
padding: 30rpx;
border-radius: 20rpx;
.device-header {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
.sn {
font-size: 32rpx;
color: #fff;
font-weight: 600;
}
.status {
font-size: 24rpx;
display: flex;
align-items: center;
.status-dot {
width: 12rpx;
height: 12rpx;
border-radius: 50%;
margin-right: 10rpx;
}
&.online {
color: #67C23A;
.status-dot {
background-color: #67C23A;
}
}
&.offline {
color: #909399;
.status-dot {
background-color: #909399;
}
}
}
}
.device-content {
display: flex;
margin-bottom: 20rpx;
.device-image {
width: 170rpx;
height: 170rpx;
margin-right: 30rpx;
background-color: #1a1a1a;
border-radius: 10rpx;
}
.device-info {
flex: 1;
.info-row {
margin-bottom: 15rpx;
display: flex;
align-items: center;
.label {
color: #909399;
font-size: 26rpx;
width: 140rpx;
}
.value {
color: #fff;
font-size: 26rpx;
}
}
}
}
.device-footer {
display: flex;
justify-content: space-between;
align-items: center;
.code-btn {
width: 152rpx;
// height: 64rpx;
background-color: #2c2c2c;
border-radius: 14rpx 14rpx 14rpx 14rpx;
border: 2rpx solid #FF8998;
font-size: 32rpx;
color: #FF8998;
text-align: center;
margin-left: 30rpx;
}
}
}
}
}
.popup-content {
background-color: #2c2c2c;
border-radius: 20rpx 20rpx 0 0;
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 2rpx solid #3a3a3a;
text {
color: #fff;
font-size: 32rpx;
}
}
.popup-list {
padding: 20rpx 0;
.popup-item {
padding: 30rpx;
color: #fff;
font-size: 28rpx;
&.active {
color: #FF4D7D;
}
}
}
}
</style>