basic-info.vue 9.97 KB
<template>
	<view class="basic-page">
		<!-- 公共组件-每个页面必须引入 -->
		<public-module></public-module>
		<!-- 基础信息头部 -->
		<view class="basic-header">
			<view class="u-flex">
				<view class="pl-3">
					<u-icon v-if="deviceDetail.deviceInfo.longitude !== ''" @click="handleClick"
						name="map-fill"></u-icon>
				</view>
				<view class="basic-text text-clip ml-2">
					{{ deviceDetail.alias ? deviceDetail.alias : deviceDetail.name }}
				</view>
				<view class="basic-text-status ml-2" :style="{ color: formatTextStatus(deviceDetail.deviceState) }">
					{{ deviceStatus }}
				</view>
			</view>
			<!-- 命令下发 设备在线并且不是网关子设备 -->
			<view class="mr-2"
				v-if="deviceDetail.deviceState === 'ONLINE' && deviceDetail.transportType !== deviceTypeNum.GBT">
				<view class="cu-item" @tap="handleAppShowModal" data-target="Modal">
					<text>{{ $t('device.commandIssuance') }}</text>
				</view>
			</view>
		</view>
		<!-- 设备详情 -->
		<view class="detail">
			<view class="detail-item">
				<view class="detail-label">{{ $t('device.deviceNumber') }}</view>
				<view class="detail-value">{{ deviceDetail.sn }}</view>
			</view>
			<u-line length="90%" margin="0 auto"></u-line>
			<view class="detail-item">
				<view class="detail-label">{{ $t('device.deviceType') }}</view>
				<view class="detail-value">{{ deviceType }}</view>
			</view>
			<u-line length="90%" margin="0 auto"></u-line>
			<view class="detail-item">
				<view class="detail-label">{{ $t('common.belongingOrganization') }}</view>
				<view class="detail-value">{{ deviceDetail.organizationDTO.name }}</view>
			</view>
			<u-line length="90%" margin="0 auto"></u-line>
			<view class="detail-item">
				<view class="detail-label">{{ $t('device.lastConnectionTime') }}</view>
				<view class="detail-value">{{ formatLastOnlineTime }}</view>
			</view>
			<u-line length="90%" margin="0 auto"></u-line>
			<view class="detail-item">
				<view class="detail-label">{{ $t('device.isAlarm') }}</view>
				<view class="detail-value">{{ alarmStatus }}</view>
			</view>
			<u-line length="90%" margin="0 auto"></u-line>
			<view class="detail-item">
				<view class="detail-label">{{ $t('device.deviceRemark') }}</view>
				<view class="detail-value">{{ deviceDetail.description }}</view>
			</view>
		</view>
		<!-- 命令下发 -->
		<!-- 引入三方库,进行mp端和app端同步弹窗 -->
		<tn-popup v-model="showNativeModal">
			<commandIssuanceVue ref="mpCommandIssuanceRef" :isShowTCP="isShowTCP"
				:deviceDetail="deviceDetail" @hideModal="hideMpModal" @cancelCommand="cancelCommand"
				@confirmCommand="confirmCommand" />
		</tn-popup>
	</view>
</template>

<script>
	import {
		formatToDate
	} from '@/plugins/utils.js';
	import api from '@/api/index.js';
	import mpCommandIssuance from './mp-command-issuance.vue';
	import {
		commandTypeList
	} from '../config/data.js'
	import {
		useShowModal
	} from '@/plugins/utils.js'
	import {
		deviceTypeNum
	} from '../config/data'
	import deviceDetail from '../device-detail.vue';
	import commandIssuanceVue from './command-issuance.vue';

	export default {
		components: {
			mpCommandIssuance,
			commandIssuanceVue
		},
		props: {
			deviceDetail: {
				type: Object,
				default: () => ({})
			}
		},
		data() {
			return {
				showNativeModal: false,
				current: 0,
				commandTypeList,
				deviceTypeNum: deviceTypeNum,
				commandTypeStr: 'OneWay',
				inputCommandContent: '',
				mpShowModal: false,
				commandValue: {},
				isShowTCP: false, //用于下发命令时判断是否是TCP/UDP
				modalName: null,
				copyTextValue: {
					"method": "methodThingskit",
					"params": {
						"pin": 7,
						"value": 1
					}
				}
			};
		},
		computed: {
			deviceStatus() {
				return this.deviceDetail.deviceState === 'INACTIVE' ? this.$t('common.toBeActivated') : this.deviceDetail.deviceState === 'ONLINE' ?
					this.$t('common.onLine') : this.$t('common.offLine');
			},
			deviceType() {
				return this.deviceDetail.deviceType === 'DIRECT_CONNECTION' ?
					this.$t('common.directlyDevice') :
					this.deviceDetail.deviceType === 'GATEWAY' ?
					this.$t('common.gatewayDevice') :
					this.deviceDetail.deviceType === 'SENSOR' ?
					this.$t('common.sensorDevice') :
					'';
			},
			alarmStatus() {
				return this.deviceDetail.alarmStatus === '0' ? this.$t('common.noText') : this.$t('common.yesText');
			},
			formatLastOnlineTime() {
				return this.deviceDetail?.lastOnlineTime && Number(this.deviceDetail?.lastOnlineTime)?formatToDate(Number(this.deviceDetail.lastOnlineTime), 'YYYY-MM-DD HH:mm:ss'):' ';
			}
		},
		beforeCreate() {
			this.modalName = null
		},
		onLoad() {
			// 隐藏原生的tabbar
			uni.hideTabBar();
			this.modalName = null
		},
		methods: {
			handleCopy(value) {
				useShowModal(JSON.stringify(value), this.$t('device.commandIssuance'), this.$t('common.copyContent')).then(res => {
					uni.setClipboardData({
						data: JSON.stringify(value),
						success: () => {
							uni.showToast({
								title: this.$t('common.copyOk')
							})
						}
					});
				})
			},
			radioChange: function(evt) {
				for (let i = 0; i < this.commandTypeList.length; i++) {
					if (this.items[i].value === evt.detail.value) {
						this.current = i;
						break;
					}
				}
				this.commandTypeStr = evt.detail.value
			},
			formatTextStatus(deviceState) {
				return deviceState === 'INACTIVE' ? '#666' : deviceState === 'ONLINE' ? '#377DFF' : '#DE4437';
			},
			handleClick() {
				const data = {
					longitude: this.deviceDetail.deviceInfo.longitude || 0,
					latitude: this.deviceDetail.deviceInfo.latitude || 0
				};
				uni.navigateTo({
					url: '/device-subpackage/device-detail/device-position?data=' + JSON.stringify(data)
				});
			},
			disabledScroll() {
				return;
			},
			handleAppShowModal(e) {
				this.modalName = e.currentTarget.dataset.target;
				this.showNativeModal = true
			},
			handleMpShowModal() {
				const {
					transportType
				} = this.deviceDetail.deviceProfile;
				this.isShowTCP = transportType == 'TCP' ? true : false;
				this.mpShowModal = true;
			},
			hideMpModal() {
				this.mpShowModal = false;
			},
			hideAppModal() {
				this.modalName = null;
				this.showNativeModal = false
			},
			confirmCommand(commandType, callType, values) {
				this.handleCommand(commandType, callType, values)
			},
			cancelCommand() {
				this.hideMpModal();
				this.hideAppModal();
				this.commandTypeStr = 'OneWay'
				this.inputCommandContent = ''
				this.$nextTick(() => {
					this.$refs.mpCommandIssuanceRef.reset()
				})
			},
			handleAppCommand() {
				this.handleCommand(this.commandTypeStr, this.commandTypeStr, this.inputCommandContent)
			},
			async handleCommand(commandType, callType, values) {
				if (!values) return uni.$u.toast(this.$t('device.pleaseEnterCommandContent'));
				if (callType == 'TwoWay') {
					const result = await api.deviceApi.getDeviceActiveTime(this.deviceDetail.tbDeviceId)
					const [firsetItem] = result || []
					if (!firsetItem.value) {
						return uni.$u.toast(this.$t('device.currentDeviceNotOnLine'))
					}
				}

				this.commandValue.persistent = true;
				this.commandValue.additionalInfo = {
					cmdType: commandType == 0 ? 0 : 1
				};
				this.commandValue.method = 'methodThingskit';
				this.commandValue.params = values;
				if (commandType == 0) { //下发类型是自定义时
					if (this.isShowTCP) {
						//TCP的格式只能是字符串
						const zg = /^[0-9a-zA-Z]*$/;
						if (!zg.test(values)) {
							uni.$u.toast(this.$t('device.pleaseCommandRule'));
							return;
						}
						this.commandValue.params = values;
					} else {
						this.commandValue.params = JSON.parse(values);
					}
				}

				await api.deviceApi.issueCommand(callType, this.deviceDetail.tbDeviceId, this.commandValue);
				this.cancelCommand();
				uni.$u.toast(this.$t('device.issuedSuccess'));
			},

		}
	};
</script>

<style lang="scss" scoped>
	@import url('../static/modal.css');

	.app-command-content {
		.app-command-text {
			display: flex;
			justify-content: center;
			align-items: center;

			text {
				font-weight: 700;
			}
		}

		.app-command-type {
			display: flex;
			margin-top: 20rpx;
			margin-left: 20rpx;

			text {
				font-weight: 700;
			}
		}

		.app-command-body {
			display: flex;
			align-items: center;
			justify-content: space-between;
			margin-top: 20rpx;
			margin-left: 20rpx;

			.app-command-textarea {
				width: 625rpx;
				height: 400rpx;
				background: #FFFFFF;
				box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.03);
				border-radius: 10px;
			}
		}

		.app-command-buttons {
			display: flex;
			align-items: center;
			justify-content: space-evenly;
			height: 85rpx;
			margin-top: 20rpx;
			margin-bottom: 20rpx;

			.cancel-button {
				width: 300rpx;
				background: #e3e3e5;
				height: 85rpx;
				border-radius: 38rpx;
				line-height: 85rpx;

				.cancel-text {
					color: #333333
				}
			}

			.confrim-button {
				width: 300rpx;
				background: #3388ff;
				border-radius: 38rpx;
				height: 85rpx;
				line-height: 85rpx;

				.confrim-text {
					color: white
				}
			}
		}
	}

	.basic-page {
		padding: 0 30rpx;

		.basic-header {
			display: flex;
			justify-content: space-between;
			align-items: center;
			height: 140rpx;
			background-color: #fff;
			border-radius: 20rpx;

			.basic-text {
				width: 370rpx;
			}

			.cu-item {
				background: #3388ff;
				border-radius: 12px;
				width: 120rpx;
				height: 48rpx;
				text-align: center;
				line-height: 40rpx;

				text {
					font-size: 12px;
					font-family: PingFangSC-Regular, PingFang SC;
					font-weight: 400;
					color: #ffffff;
				}
			}

			.basic-text-status {
				font-size: 14px;
			}
		}

		.detail {
			background-color: #fff;
			margin-top: 30rpx;
			border-radius: 20rpx;
			width: 690rpx;

			.detail-item {
				padding: 30rpx;
				display: flex;
				align-items: center;

				.detail-label {
					color: #333;
					font-size: 15px;
				}

				.detail-value {
					color: #666;
					font-size: 14px;
					margin-left: 30rpx;
				}
			}
		}
	}

	::v-deep .u-modal__content {
		padding: 30rpx 0 !important;
	}
</style>