baodeng_xcx/page_shanghu/device/index.vue

563 lines
14 KiB
Vue
Raw Normal View History

2025-05-14 15:14:12 +08:00
<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()
2025-06-06 11:14:06 +08:00
// this.
2025-05-14 15:14:12 +08:00
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>