device.vue 9.91 KB
<template>
	<view class="device-page">
		<!-- 公共组件-每个页面必须引入 -->
		<public-module></public-module>
		<u-sticky>
			<view class="device-top">
				<view class="search">
					<view>
						<view class="search-left"><u--input prefixIcon="search" placeholder="输入设备SN或名称搜索" shape="circle" @change="inputChanged"></u--input></view>
					</view>
					<view @click="openSearchDialog" class="search-right">
						<text>筛选</text>
						<image src="../../static/shaixuan.png" />
					</view>
				</view>
				<u-line />
				<view class="org">
					<u-cell @click="openOrg" isLink title="组织关系" :border="false">
						<view slot="label" class="label" style="display: flex; align-items: center;margin-top: 20rpx;">
							<image src="../../static/org.png" style="width: 24rpx;height: 28rpx;"></image>
							<view style="margin-left: 10rpx; color: #666;">
								设备数:
								<text style="margin-left: 20rpx;">{{ total }}</text>
							</view>
						</view>
					</u-cell>
				</view>
			</view>
		</u-sticky>
		<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback">
			<view class="device-list">
				<view @click="openDeviceDetail(item.id, item.alarmStatus, item.lastOnlineTime, item.tbDeviceId)" class="list-item" v-for="item in list" :key="item.id">
					<view
						class="u-flex item"
						style="
              justify-content: flex-start;
              flex-direction: column;
              align-items: center;
            "
					>
						<view style="width: 450rpx; text-align: left">
							<text style="color: #333; font-size: 30rpx;font-weight: bold;">{{ item.name }}</text>
						</view>
						<view style="width: 450rpx; text-align: left; margin-top: 10rpx">
							<view style="color: #666; font-size: 14px;display: flex;">
								设备编号:
								<view style="margin-left:16rpx">{{ item.sn }}</view>
							</view>
						</view>
						<view style="width: 450rpx; text-align: left; margin-top: 10rpx">
							<view style="color: #666; font-size: 14px;display: flex;">
								所属组织:
								<view style="margin-left:16rpx">{{ item.organizationDTO.name }}</view>
							</view>
						</view>
					</view>
					<view class="item">
						<view class="u-flex" style="margin-top: -6rpx">
							<image
								style="
                  width: 30rpx;
                  height: 30rpx;
                  margin-top: 5rpx;
                  margin-right: 5rpx;
                "
								:src="item.deviceState === 'ONLINE' ? '../../static/online.png' : item.deviceState === 'INACTIVE' ? '../../static/unonline.png' : '../../static/baojing.png'"
							/>

							<view>
								<text
									style="
                    color: #377dff;
                    font-size: 13px;
                    margin-left: 5rpx;
                    margin-top: 20rpx;
                  "
									:style="{ color: item.deviceState === 'ONLINE' ? '#377DFF' : item.deviceState === 'INACTIVE' ? '#666666' : '#DE4437' }"
								>
									{{ item.deviceState === 'ONLINE' ? '在线' : item.deviceState === 'INACTIVE' ? '待激活' : '离线' }}
								</text>
							</view>
						</view>
					</view>
				</view>
			</view>
		</mescroll-body>
		<!-- 设备筛选 -->
		<u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20">
			<view class="filter">
				<view class="filter-title"><text>筛选条件</text></view>
				<FilterItem :filterList="deviceStatus" title="设备状态" @clickTag="currentIndex => handleClickTag(currentIndex, deviceStatus)"></FilterItem>
				<FilterItem :filterList="alarmStatus" title="告警状态" @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem>
				<FilterItem :filterList="typeStatus" title="设备类型" @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem>
				<view class="button-group">
					<view><u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置" @click="resetFilter"></u-button></view>
					<view><u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button></view>
				</view>
			</view>
		</u-popup>
		<f-tabbar></f-tabbar>
	</view>
</template>

<script>
import fTabbar from '@/components/module/f-tabbar/f-tabbar';
import fNavbar from '@/components/module/f-navbar/f-navbar';
import FilterItem from './FilterItem.vue';
import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';

import { debounce } from '@/plugins/throttle.js';
export default {
	mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
	components: {
		fTabbar,
		fNavbar,
		FilterItem
	},
	data() {
		return {
			downOption: {
				auto: false //是否在初始化后,自动执行downCallback; 默认true
			},
			upOption: {
				auto: false // 不自动加载
			},
			show: false,
			deviceStatus: [
				{
					checked: true,
					name: '全部',
					type: ''
				},
				{
					checked: false,
					name: '在线',
					type: 'ONLINE'
				},
				{
					checked: false,
					name: '离线',
					type: 'OFFLINE'
				},
				{
					checked: false,
					name: '待激活',
					type: 'INACTIVE'
				}
			],
			alarmStatus: [
				{
					checked: true,
					name: '全部',
					type: ''
				},
				{
					checked: false,
					name: '告警',
					type: '1'
				},
				{
					checked: false,
					name: '正常',
					type: '0'
				}
			],
			typeStatus: [
				{
					checked: true,
					name: '全部',
					type: ''
				},

				{
					checked: false,
					name: '直连设备',
					type: 'DIRECT_CONNECTION'
				},
				{
					checked: false,
					name: '网关设备',
					type: 'GATEWAY'
				},
				{
					checked: false,
					name: '网关子设备',
					type: 'SENSOR'
				}
			],
			total: 0,
			list: [],
			page: {
				num: 0,
				size: 10
			}
		};
	},
	onLoad(e) {
		// 隐藏原生的tabbar
		uni.hideTabBar();
		if (e.type !== undefined) {
			const statusT = JSON.parse(e.type);
			this.loadData(1, {
				deviceState: statusT
			});
		}
	},
	onShow() {
		if (this.orgId) {
			this.loadData(1, {
				organizationId: this.orgId
			});
		}
	},
	methods: {
		/*下拉刷新的回调 */
		downCallback() {
			//联网加载数据
			this.list = [];
			this.page.num = 1;
			//联网加载数据
			this.loadData(this.page.num);
		},

		/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
		upCallback() {
			//联网加载数据
			this.page.num += 1;
			this.loadData(this.page.num);
		},

		//获取设备
		loadData(pageNo, params = {}) {
			let httpData = {
				page: pageNo,
				pageSize: 10,
				...params
			};
			uni.$u.http
				.get('/yt/device', {
					params: httpData,
					custom: {
						load: false
					}
				})
				.then(res => {
					this.total = res.total;
					uni.stopPullDownRefresh();
					console.log('获取后端数据', res);
					//方法一(推荐): 后台接口有返回列表的总页数 totalPage
					this.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数)
					if (pageNo == 1) {
						this.list = res.items;
					} else {
						this.list = this.list.concat(res.items);
					}
				})
				.catch(() => {
					//联网失败, 结束加载
					this.mescroll.endErr();
				});
		},
		openOrg() {
			uni.navigateTo({
				url: './org/org'
			});
		},
		close() {
			this.resetFilter();
			this.show = false;
		},
		openSearchDialog() {
			this.show = true;
		},
		openDeviceDetail(id, alarmStatus, lastOnlineTime, tbDeviceId) {
			uni.navigateTo({
				url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}`
			});
		},
		handleClickTag(currentIndex, list) {
			list.map((item, index) => {
				item.checked = index === currentIndex;
			});
		},
		resetFilter() {
			const { deviceStatus, alarmStatus, typeStatus } = this;
			[deviceStatus, alarmStatus, typeStatus].forEach(item => item.map((item, index) => (item.checked = index === 0)));
		},
		confirmFilter() {
			const deviceState = this.deviceStatus.find(item => item.checked);
			const alarmStatus = this.alarmStatus.find(item => item.checked);
			const deviceType = this.typeStatus.find(item => item.checked);
			this.loadData(1, {
				deviceState: deviceState.type ? deviceState.type : undefined,
				deviceType: deviceType.type ? deviceType.type : undefined,
				alarmStatus: alarmStatus.type === '0' || alarmStatus.type === '1' ? alarmStatus.type : undefined
			});
			this.show = false;
		},
		inputChanged: debounce(function(name) {
			this.loadData(1, {
				name
			});
		}, 500)
	}
};
</script>

<style lang="scss" scoped>
.device-page {
	min-height: 100vh;
	background-color: #f8f9fa;
}
.device-top {
	padding: 10rpx 30rpx;
	background-color: #fff;
	.search {
		display: flex;
		justify-content: space-between;
		padding-bottom: 10rpx;
		.search-left {
			width: 580rpx;
			background-color: #f8f9fa;
			border-radius: 200rpx;
		}
		.search-right {
			display: flex;
			align-items: center;
			text {
				color: #333;
				font-size: 14px;
			}
			image {
				width: 40rpx;
				height: 40rpx;
			}
		}
	}
}

.device-list {
	display: flex;
	flex-direction: column;
	padding-left: 20rpx;
	.list-item {
		width: 713rpx;
		height: 200rpx;
		background-color: #fff;
		margin-top: 24rpx;
		display: flex;
		border-radius: 10px;
		justify-content: space-between;
		.item {
			margin: 30rpx;
		}
	}
}

.filter {
	padding: 0 30rpx;
	.filter-title {
		text-align: center;
		margin-top: 14px;
		font-size: 32rpx;
		font-weight: 700;
	}
	.button-group {
		display: flex;
		margin-top: 40rpx;
		justify-content: space-between;
		view {
			width: 330rpx;
		}
	}
}
</style>