iot-ui-app/pages/tabbar/device.vue

405 lines
9.9 KiB
Vue

<template>
<view class="device-list-box">
<!-- 菜单 -->
<view class="device-search">
<u-dropdown class="sl-filter" border-bottom>
<u-dropdown-item v-model="productId" title="所属产品" height="750" :options="productList" @change="searchChange"></u-dropdown-item>
<u-dropdown-item v-model="deviceType" title="设备类型" :options="deviceTypeList" @change="searchChange"></u-dropdown-item>
</u-dropdown>
<u-search placeholder="请输入设备名称/编号搜索" class="uni-search-bar" v-model="searchVal" @custom="searchChange" @clear="searchChange" @search="searchChange"></u-search>
<u-tabs :list="tabsList" bar-width="187" :is-scroll="false" :current="tabIndex" @change="tabChange"></u-tabs>
</view>
<mescroll-body ref="mescrollRef" top="260" @init="mescrollInit" @down="downCallback" :up="upOption" @up="upCallback">
<view class="device-box">
<view class="device-info">
<view class="name">设备总数: <text style="font-size: 24rpx;">{{total}}</text></view>
</view>
<!-- 设备列表 -->
<view class="device-list">
<view class="device-item" v-for="(item, index) in dataList" :key="index" @click="goDetail(item)">
<!-- 设备名称和类型区域 -->
<view class="device-header">
<view class="device-title">{{ item.productName }}</view>
</view>
<!-- 设备图片和信息区域 -->
<view class="device-content">
<!-- 设备图片 -->
<view class="device-img-box">
<image v-if="item.photoUrl" :src="item.photoUrl" mode="aspectFit"></image>
<!-- #ifdef MP-WEIXIN -->
<image v-else src="http://static.drgyen.com/app/iot-ui-app/image/device/device-card.png" mode="aspectFit"></image>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<image v-else src="/static/app-plus/image/device/device-card.png" mode="aspectFit"></image>
<!-- #endif -->
</view>
<!-- 设备信息和状态 -->
<view class="device-info-box">
<!-- 设备状态 -->
<view class="device-status-dot" :class="item.state.value">
<text>{{ item.state.text }}</text>
</view>
<!-- 设备类型 -->
<view class="device-type">{{ item.deviceType.text }}</view>
</view>
</view>
<!-- 设备名称 -->
<view class="device-name-box">
<text class="device-name">{{ item.name }}</text>
</view>
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js"
export default {
mixins: [MescrollMixin],
components: {
},
data() {
return {
upOption:{
noMoreSize: 4,
textNoMore: '---- 已经到底啦 ----',
empty:{
tip: '~ 搜索无数据 ~' // 提示
}
},
tabbarIndex:1,
productId:null,
deviceType:null,
searchVal: '',
tabIndex: 0, // tab下标
productList:[],
deviceTypeList:[
{
label: '全部设备',
value: null,
},
{
label: '直连设备',
value: 'device',
},
{
label: '网关子设备',
value: 'childrenDevice',
},
{
label: '网关设备',
value: 'gateway',
}
],
tabsList:[{
name: '全部',
value: null
}, {
name: '禁用',
value: 'notActive'
}, {
name: '在线',
value: 'online'
}, {
name: '离线',
value: 'offline'
}],
dataList: [],
total: 0,
imgPath:'',
}
},
onLoad() {
this.getConfigPath();
this.getProductList();
this.getUserInfo();
},
methods: {
getUserInfo(){
this.$api.getUserInfo({}).then(res => {
console.log("获取用户信息",res)
if(res.status == 200){
uni.setStorageSync('userInfo',res.result)
}
}, error => {
})
},
goDetail(obj){
// console.log("跳转设备详情",obj)
uni.navigateTo({
url:'./device-detail?id=' + obj.id + '&devName=' + obj.devName
})
},
getConfigPath(){
let configList = uni.getStorageSync('configList');
let configIndex = uni.getStorageSync('configIndex');
this.imgPath = configList[configIndex].protocol + configList[configIndex].address;
},
getDeviceTypeLabel(type) {
const typeMap = {
'device': '直连设备',
'childrenDevice': '网关子设备',
'gateway': '网关设备'
};
return typeMap[type] || '网关设备';
},
// 切换菜单
tabChange(e) {
this.tabIndex = e;
this.mescroll.resetUpScroll() // 再刷新列表数据
},
searchChange(e) {
// this.searchVal = res.value
this.dataList = []// 先置空列表,显示加载进度
this.mescroll.resetUpScroll() // 再刷新列表数据
},
getProductList(){
this.$api.iotsApi.getProductList({paging:false}).then(res => {
if(res.status == 200 && res.result.length>0){
let productList = res.result.map((item)=>{
return {
label:item.name,
value:item.id
}
})
this.productList = [{
label: '全部产品',
value: null,
},...productList];
}else{
this.productList = [{
label: '全部产品',
value: null,
}];
}
}, error => {
})
},
upCallback(page) {
let pageNum = page.num-1;
let params = {
"pageIndex": pageNum,
"pageSize": page.size,
"sorts": [
{
"name": "createTime",
"order": "desc"
},
{
"name": "name",
"order": "desc"
}
],
"terms": [{
"terms": [
{ "type": "and", "column": "productId", "termType": "eq", "value": this.productId },
{ "type": "and", "column": "state", "termType": "eq", "value": this.tabsList[this.tabIndex].value },
{ "type": "and", "column": "deviceType", "termType": "eq", "value": this.deviceType }
]
},
// 新增的 id/name 模糊查询
{
"terms": [
{ "type": "or", "column": "id", "termType": "like", "value": "%"+this.searchVal+"%" },
{ "type": "or", "column": "name", "termType": "like", "value": "%"+this.searchVal+"%" }
]
}],
}
this.$api.iotsApi.getDeviceList(params).then(res => {
if(res.status === 200){
let curPageData = res.result && res.result.data;
let curPageLen = curPageData && curPageData.length || 0;
let totalSize = res.result.total;
this.$nextTick(()=>{
// 隐藏下拉刷新和上拉加载的状态;
this.mescroll.endBySize(curPageLen, totalSize);
})
//设置列表数据
if(page.num == 1) this.dataList = []; //如果是第一页需手动制空列表
this.dataList = curPageLen > 0 && this.dataList.concat(curPageData); //追加新数据
this.total = totalSize;
}else{
this.$u.toast(res.msg);
this.mescroll.endErr();
}
}, error => {
console.error("API Error:", error);
uni.showToast({
title: '请求失败,请稍后重试',
icon: 'none'
});
this.mescroll.endErr();
})
}
}
}
</script>
<style>
page{
background-color: #f5f5f5;
}
</style>
<style lang="scss" scoped>
/deep/.u-search{
padding: 19rpx 20rpx;
border-bottom: 1px solid #f4f6f8;
}
.device-list-box{
width: 100%;
height: 100%;
background-color: #f5f5f5;
.device-search{
position: fixed;
top: 0;
left: 0;
box-sizing: border-box;
height: 260rpx;
background-color: #fff;
width: 100%;
z-index: 999;
}
.device-box{
.device-info{
text-align: right;
padding: 20rpx;
padding-bottom: 0;
.name{
font-size: 28rpx;
font-weight: bold;
color: #333333;
}
}
.device-list {
display: flex;
flex-wrap: wrap;
padding: 20rpx;
.device-item {
width: 345rpx;
background: #fff;
border-radius: 20rpx;
margin-bottom: 20rpx;
padding: 20rpx;
box-sizing: border-box;
&:nth-child(2n-1) {
margin-right: 20rpx;
}
// 设备头部:产品名称
.device-header {
margin-bottom: 15rpx;
.device-title {
font-size: 24rpx;
color: #666;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
// 设备内容:图片和设备信息
.device-content {
display: flex;
align-items: center;
margin-bottom: 15rpx;
.device-img-box {
width: 120rpx;
height: 120rpx;
display: flex;
justify-content: center;
align-items: center;
image {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.device-info-box {
flex: 1;
padding-left: 36rpx;
display: flex;
flex-direction: column;
justify-content: center;
// 设备状态
.device-status-dot {
display: flex;
align-items: center;
font-size: 24rpx;
margin-bottom: 10rpx;
&::before {
content: '';
display: inline-block;
width: 12rpx;
height: 12rpx;
border-radius: 50%;
margin-right: 6rpx;
}
&.online {
color: #10CC70;
&::before {
background-color: #10CC70;
}
}
&.offline {
color: #E50012;
&::before {
background-color: #E50012;
}
}
&.notActive {
color: #FF9000;
&::before {
background-color: #FF9000;
}
}
}
// 设备类型
.device-type {
font-size: 24rpx;
color: #666;
}
}
}
// 设备名称
.device-name-box {
.device-name {
font-size: 28rpx;
font-weight: bold;
color: #333;
display: block;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
}
}
</style>