device-detail.vue 6.18 KB
<template>
	<view class="device-detail-page">
		<!-- 公共组件-每个页面必须引入 -->
		<public-module></public-module>
		<u-sticky :bgColor="bgColor">
			<u-tabs :list="list" :current="currentTab" @click="handleTabClick" :activeStyle="activeColor"
				:inactiveStyle="inActiveColor" :scrollable="isScrollable" />
		</u-sticky>
		<view class="mt-3">
			<basic-info v-show="currentTab == 0" :deviceDetail="deviceDetail" />
			<realtime-data v-show="currentTab === 1" :recordList="recordList" />
			<history-data v-if="currentTab === 2" :keys="keys" :yesterday="yesterday" :today="today"
				:timeDiff="timeDiff" :historyData="historyData" :entityId="entityId" :start="startTs" :end="endTs"
				@update="handleUpdate" />
			<alarm-history v-show="currentTab === 3" :deviceId="deviceId" />
			<commond-record v-if="currentTab === 4" :tbDeviceId="entityId" />
		</view>
	</view>
</template>

<script>
	import fTabbar from "@/components/module/f-tabbar/f-tabbar";
	import basicInfo from "./components/basic-info.vue";
	import realtimeData from "./components/realtime-data.vue";
	import alarmHistory from "./components/alarm-history.vue";
	import historyData from "./components/history-data.vue";
	import commondRecord from "./components/command-record.vue";
	import { getDeviceKeys,getHistoryData } from "./api/index.js";
	import {formatToDate} from "@/plugins/utils.js";
	import MescrollCompMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js";
	import moment from "moment";
	import base from "@/config/baseUrl.js";
	import { list } from './config/data.js'
	import api from '@/api'

	export default {
		mixins: [MescrollCompMixin],
		components: {
			fTabbar,
			basicInfo,
			realtimeData,
			alarmHistory,
			historyData,
			commondRecord,
		},
		data() {
			return {
				bgColor: '#fff',
				activeColor: {
					fontWeight: 'bold',
					color: '#333',
				},
				inActiveColor: {
					color: '#999',
				},
				list,
				currentTab: 0,
				deviceId: "",
				deviceDetail: {},
				keys: [],
				yesterday: "",
				today: "",
				timeDiff: "",
				historyData: [],
				entityId: "",
				startTs: "",
				endTs: "",
				recordList: [], //实时数据
				isScrollable: false,
				attrList: [],
				getAttrList:[]
			};
		},
		onUnload() {
			// 页面关闭时,销毁webSocket连接,否则第二次会存在连接不到的情况
			uni.closeSocket();
		},
		async onLoad(options) {
			const {id,alarmStatus,lastOnlineTime,tbDeviceId,deviceProfileId} = options;
			this.deviceId = id;
			const res = await api.deviceApi.getDeviceDetail(this.deviceId)
			if(!res) return
			this.deviceDetail = {
				...res,
				alarmStatus,
				lastOnlineTime,
			};
			// 设备类型不是网关子设备的添加一个命令记录的选项卡
			if (this.deviceDetail.deviceType !== "SENSOR") {
				this.list.push({
					name: "命令记录",
				});
				const res = new Map()
				this.list = this.list.filter((item) => !res.has(item.name) && res.set(item.name, 1))
			} else {
				this.list = this.list.filter(item => item.name !=='命令记录')
			}
			this.isScrollable = this.list.length > 4;
			if (res.deviceProfileId) {
				this.getAttrList = await api.deviceApi.getAttribute(res.deviceProfileId)
				if (Array.isArray(this.getAttrList)) {
					this.attrList = this.getAttrList.map(m => {
						return m.identifier
					})
				}
			}
			// 连接webSockte
			const socketTask = uni.connectSocket({
				url: `${base.socketPrefix}://${base.baseWebSocketUrl}/api/ws/plugins/telemetry?token=` + uni.getStorageSync("userInfo").isToken, //仅为示例,并非真实接口地址。
				complete: () => {},
			});
			uni.onSocketOpen((header) => {
				socketTask.send({
					data: JSON.stringify({
						attrSubCmds: [],
						tsSubCmds: [{
							entityType: "DEVICE",
							entityId: tbDeviceId,
							scope: "LATEST_TELEMETRY",
							cmdId: 1,
							keys: this.attrList.join(','),
						}, ],
						historyCmds: [],
						entityDataCmds: [],
						entityDataUnsubscribeCmds: [],
						alarmDataCmds: [],
						alarmDataUnsubscribeCmds: [],
						entityCountCmds: [],
						entityCountUnsubscribeCmds: [],
					}),
					success() {},
				});
			});
			socketTask.onMessage((msg) => {
				const { data } = JSON.parse(msg.data);
				const newArray = [];
				for (const key in data) {
					const [time, value] = data[key].flat(1);
					let obj = { key,time,value, };
					if (this.recordList.length === 0) {
						this.recordList.unshift(obj);
					} else {
						newArray.push(obj);
					}
				}
				newArray.forEach((item) => {
					let flag = false;
					this.recordList.forEach((item1) => {
						if (item1.key === item.key) {
							item1.value = item.value;
							item1.time = item.time;
							flag = true;
						}
					});
					if (!flag) {
						this.recordList.unshift(item);
					}
				});
				this.recordList = this.recordList.map((item) => {
					return {
						...item,
						time: formatToDate(item.time, "YYYY-MM-DD HH:mm:ss"),
					};
				});
			});
			const keys = await getDeviceKeys(tbDeviceId);
			this.keys = [this.getAttrList.map(item=>item.identifier)];
			// 昨天
			this.yesterday = moment().subtract(1, "days").format("YYYY-MM-DD");
			// 今天
			this.today = moment().format("YYYY-MM-DD");
			// 开始时间
			this.startTs = moment().subtract(1, "days").format("x");
			// 结束时间
			this.endTs = moment().format("x");
			this.entityId = tbDeviceId;
			const data = await getHistoryData({
				entityId: tbDeviceId,
				startTs: this.startTs,
				endTs: this.endTs,
				keys: keys[0],
				// interval: 1800000,
				limit: 7,
				agg: 'NONE'
			});
			this.timeDiff = "30分钟";
			if (!Object.keys(data).length) return;
			this.historyData = data[keys[0]].map((item) => {
				return {
					value: item.value,
					ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"),
				};
			});
		},
		methods: {
			handleTabClick({
				index
			}) {
				this.currentTab = index;
			},
			handleUpdate(data, e) {
				if (!Array.isArray(data)) {
					this.historyData = [];
					return;
				}
				this.historyData = data.map((item) => {
					return {
						value: item.value,
						ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"),
					};
				});
			},
		},
	};
</script>

<style lang="scss" scoped>
	.device-detail-page {
		height: 100vh;
		background-color: #f8f9fa;
	}
</style>