device.vue 8.68 KB
<template>
	<view class="device-page">
		<f-navbar>
			<view class="u-flex" slot="left" style="justify-content: space-between;">
				<view style="width: 580rpx;"><u--input prefixIcon="search" placeholder="输入设备SN或名称搜索" border="surround" shape="circle" @change="inputChanged"></u--input></view>
				<view style="margin-left: 7rpx;">
					<view><text style="color:#333;font-size: 14px;">筛选</text></view>
				</view>
				<view style="margin-left: 7rpx;"><image @click="openSearchDialog" style="width: 40rpx;height: 40rpx;" src="../../static/shaixuan.png" /></view>
			</view>
		</f-navbar>
		<!-- 公共组件-每个页面必须引入 -->
		<public-module></public-module>
		<view class="org-sty">
			<view class="org-item">
				<view class="u-flex" style="margin-top: 26rpx;margin-left: 15rpx;"><text style="color:#333;font-size: 15px;margin-left: 14rpx;">组织关系</text></view>
				<view style="margin-top: 20rpx;margin-left: 15rpx;" class="u-flex" v-if="total">
					<image style="margin-left: 14rpx;width: 30rpx;height: 30rpx;" src="../../static/org.png" />
					<text style="margin-left: 10rpx;color:#666;font-size: 12px;">设备数 : {{ total }}</text>
				</view>
			</view>
			<view class="org-item">
				<image @click="openOrg" style="width: 6px;height: 10px;float: right; margin-right: 34rpx; margin-top: 58rpx;" src="../../static/right-arrow.png" />
			</view>
		</view>
		<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback">
			<view class="device-list">
				<view @click="openDeviceDetail(item.id)" 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;">{{ item.name ? `设备名称:${item.name}` : '' }}</text>
						</view>
						<view style="width: 450rpx;text-align: left; margin-top: 10rpx;">
							<text style="color:#666;font-size: 15px;">{{ item.sn ? `设备编号:${item.sn}` : '' }}</text>
						</view>
						<view style="width: 450rpx;text-align: left; margin-top: 10rpx;">
							<text style="color:#666;font-size: 15px;">{{ item.organizationDTO.name ? `所属组织:${item.organizationDTO.name}` : '' }}</text>
						</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/secondary.png' : '../../static/baojing.png'"
							/>

							<view>
								<text style="color: #377DFF;font-size: 13px;margin-left: 5rpx;margin-top: 20rpx;">
									{{ 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>
				<view style="text-align: center;margin-top: 28rpx;"><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="u-flex" style="margin-top:40rpx;margin-left: 55rpx;">
					<view style="width: 300rpx"><u-button type="info" shape="circle" text="重置" @click="resetFilter"></u-button></view>
					<view style="width: 300rpx;margin-left:46rpx;"><u-button type="primary" 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
			},
			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: [],
		};
	},
	onLoad() {
		// 隐藏原生的tabbar
		uni.hideTabBar();
	},
	methods: {
		/*下拉刷新的回调 */
		downCallback() {
			//联网加载数据
			this.loadData(1);
		},
		/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
		upCallback(page) {
			//联网加载数据
			console.log(page);
			this.loadData(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.total, Math.ceil(res.total / 10)); //必传参数(当前页的数据个数, 总页数)
					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) {
			uni.navigateTo({
				url: `deviceDetail?id=${id}`
			});
		},
		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;
}

.org-sty {
	width: 750rpx;
	height: 150rpx;
	margin-top: 1rpx;
	background-color: #fff;
	display: flex;
	justify-content: space-between;

	.org-item {
		width: 350rpx;
		height: 200rpx;
	}
}

.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;
		}
	}
}
</style>