device.vue 10.7 KB
<template>
	<view class="device-page">
		<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" :up="upOption" :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: 15px;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" @touchmove.stop.prevent="disabledScroll">
			<view class="filter" @touchmove.stop.prevent="disabledScroll">
				<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 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,
		FilterItem
	},
	data() {
		return {
			downOption: {
				auto: false //是否在初始化后,自动执行downCallback; 默认true
			},
			upOption: {
				isBounce: false,
				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
			},
			deviceState: '',
			deviceName: ''
		};
	},
	async onLoad(options) {
		// 隐藏原生的tabbar
		uni.hideTabBar();
		this.page.num = 1;
		const { deviceState } = options;
		this.deviceState = deviceState;
		if (deviceState) {
			this.deviceStatus.forEach(item => {
				item.type === deviceState ? (item.checked = true) : (item.checked = false);
			});
			await this.loadData(1, {
				deviceState
			});
		} else {
			await this.loadData(1);
		}
		if (!this.list.length) {
			this.mescroll.showEmpty();
		}
	},
	onShow() {
		if (this.orgId) {
			this.loadData(1, {
				organizationId: this.orgId
			});
		}
	},
	methods: {
		disabledScroll() {
			return;
		},
		/*下拉刷新的回调 */
		downCallback() {
			this.deviceName = '';
			//联网加载数据
			this.list = [];
			this.page.num = 1;
			//联网加载数据
			this.resetFilter();
			this.loadData(this.page.num);
		},

		/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
		upCallback() {
			//联网加载数据
			this.page.num += 1;
			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(this.page.num, {
				deviceState: deviceState.type ? deviceState.type : undefined,
				deviceType: deviceType.type ? deviceType.type : undefined,
				alarmStatus: alarmStatus.type === '0' || alarmStatus.type === '1' ? alarmStatus.type : undefined,
				name: this.deviceName == null ? null : this.deviceName
			});
		},

		//获取设备
		async loadData(pageNo, params = {}) {
			try {
				let httpData = {
					page: pageNo,
					pageSize: 10,
					...params
				};
				const { total, items } = await uni.$u.http.get('/yt/device', {
					params: httpData,
					custom: {
						load: false
					}
				});
				this.total = total;
				uni.stopPullDownRefresh();
				this.mescroll.endByPage(items.length, total); //必传参数(当前页的数据个数, 总页数)
				if (pageNo == 1) {
					this.list = items;
				} else {
					this.list = this.list.concat(items);
				}
			} catch {
				this.mescroll.endErr();
			}
		},
		openOrg() {
			uni.navigateTo({
				url: './org/org'
			});
		},
		close() {
			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(e) {
			this.page.num = 1;
			this.deviceName = e;
			this.loadData(1, {
				name: this.deviceName
			});
		}
	}
};
</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: 16px;
		font-weight: 700;
	}
	.button-group {
		display: flex;
		margin-top: 40rpx;
		justify-content: space-between;
		view {
			width: 330rpx;
		}
	}
}
</style>