<template>
	<view class="device-detail-box">
		<view class="menu-list">
			<view class="menu-item" @click="goDeviceAbility">
				<view class="iconfont icon-appstore"></view>
				<view class="menu-txt">
					设备功能
				</view>
			</view>
			<view class="menu-item" @click="goDeviceAlarm">
				<view class="iconfont icon-bell"></view>
				<view class="menu-txt">
					设备报警
				</view>
			</view>
		</view>
		<view class="device-title-box">
			<view class="title-box-left">
				<view class="title-txt"  @click="openDeviceModel">
					<text>{{deviceName}}</text>
					<text class="title-name-detail">详情</text>
				</view>
				<view class="time-txt">
					{{deviceTime?deviceTime:''}}
				</view>
			</view>
			<view v-if="wsStatus" class="title-right color-blue" @click="refreshSocket">
				<view class="iconfont icon-reload"></view>点击刷新
			</view>
			<view v-else class="title-right color-red" @click="refreshSocket">
				<view class="iconfont icon-disconnect"></view>点击重连
			</view>
			<!-- <view class="title-right" @click="refreshSocket">
				<view class="iconfont icon-reload"></view>{{wsStatus?'刷新':'已断连'}}
			</view> -->
		</view>
		<view class="group-list">
			<view class="group-list-label">
				属性分组:
			</view>
			<uni-data-select
				style="min-width: 200rpx;max-width: 500rpx;"
				v-model="selectGroup"
				:localdata="groupList"
				:clear="false"
				@change="changeGroup"
			></uni-data-select>
		</view>
		<view class="attr-list">
			<view class="attr-list-item" v-for="(item,index) in dataList" :key="index">
				<!-- 选择器 -->
				<iots-select 
				 v-if="item.viewType == 'select'"
				 :disabled="true"
				 :name="item.name"
				 v-model="item.value"
				 :selectList="item.ioObj.enums"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-select>
				<!-- 时间选择器 -->
				<iots-select-time
				 v-else-if="item.viewType == 'text' && item.formType == 'time_picker'"
				 :disabled="true"
				 :name="item.name"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-select-time>
				<!-- 颜色选择 -->
				<iots-color-select
				 v-else-if="item.viewType == 'color-select'"
				 :name="item.name"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-color-select>
				<!-- 开关 -->
				<iots-switch
				 v-else-if="item.viewType == 'switch'"
				 :name="item.name"
				 :disabled="true"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-switch>
				<!-- 开关按钮 -->
				<iots-switch-btn
				 v-else-if="item.viewType == 'switch-btn'"
				 :name="item.name"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-switch-btn>
				<!-- 滑块 -->
				<iots-slider 
				 v-else-if="item.viewType == 'slider'"
				 :disabled="true"
				 :name="item.name"
				 :min="parseFloat(item.ioObj.IoDeployForm.min || 0)"
				 :max="parseFloat(item.ioObj.IoDeployForm.max || 100)"
				 :step="parseFloat(item.ioObj.IoDeployForm.step || 1)"
				 :unit="item.ioObj.unit"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-slider>
				<!-- 文字展示 -->
				<!-- <iots-text
				 v-else-if="item.viewType == 'text'"
				 :name="item.name"
				 :value="getParseText(item.value)"
				 @clickLog="clickLog(index)"
				></iots-text> -->
				<!-- 柱状图 -->
				<iots-bar
				 v-else-if="item.viewType == 'bar'"
				 :name="item.name"
				 :dataList="item.dataList"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-bar>
				<!-- 折线图 -->
				<iots-line
				 v-else-if="item.viewType == 'charts_line'"
				 :name="item.name"
				 :time="item.time"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-line>
				<!-- 饼图 -->
				<!-- <iots-pie
				 v-else-if="item.viewType == 'charts_pie'"
				 :name="item.name"
				 :dataList="item.dataList"
				 :value="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-pie> -->
				<!-- 仪表盘 -->
				<iots-gauge
				 v-else-if="item.viewType == 'charts_dashboard'"
				 :name="item.name"
				 :dataList="getChartData('charts_dashboard',item)"
				 v-model="item.value"
				 :min="parseFloat(item.ioObj.IoDeployForm.min || 0)"
				 :max="parseFloat(item.ioObj.IoDeployForm.max || 100)"
				 :unit="item.ioObj.unit"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-gauge>
				<!-- 步进器 -->
				<iots-number-box 
				 v-else-if="item.viewType == 'text' && item.formType == 'number'"
				 :disabled="true"
				 :name="item.name"
				 :min="parseFloat(item.ioObj.IoDeployForm.min || 0)"
				 :max="parseFloat(item.ioObj.IoDeployForm.max || 100)"
				 :step="parseFloat(item.ioObj.IoDeployForm.step || 1)"
				 :unit="item.ioObj.unit"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-number-box>
				<!-- 输入框 -->
				<iots-input
				 v-else-if="item.viewType == 'text'"
				 :disabled="true"
				 :name="item.name"
				 v-model="item.value"
				 :unit="item.ioObj?item.ioObj.unit?item.ioObj.unit:'':''"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-input>
				<iots-img
				 v-else-if="item.viewType == 'image'"
				 :disabled="true"
				 :name="item.name"
				 v-model="item.value"
				 @change="downData($event,index)"
				 @clickLog="clickLog(index)"
				></iots-img>
				
				<view v-else class="attr-item">
					<view class="attr-item-left">
						<view class="iconfont" :class="item.icon?item.icon:'icon-file-unknown2'"></view>
						<view class="attr-name">{{item.name}}</view>
						<view class="iconfont icon-unordered-list" @click="clickLog(index)"></view>
					</view>
					<view class="attr-item-right">
						<view class="">
							<!-- 未适配属性 -->
						</view>	
						<!-- <view v-if="item.viewType == 'img'" class="attr-value item-border item-img-box"  >
							<u-upload ref="uPloadimgRef" width="120" height="120"  :action="imgUploadUrl" :file-list="imgList" max-count="1" @on-change="changeUploadImg"></u-upload>
							<view class="iconfont icon-xiangyou1"></view>
						</view> -->
					</view>
				</view>
			</view>
			<view v-if="dataList.length == 0" class="attr-empty">
				<u-empty text="设备属性为空,请添加属性" src="setting"></u-empty>
			</view>
			<!-- 数据日志 -->
			<!-- <view class="iconfont icon-shuaxin" @click="resetLog"></view> -->
			<!-- <view class="attr-value item-border item-log">
				<view class="item-log-header">
					<text class="item-log-header-label">数据日志</text>
					<view class="item-log-header-right">
						<view class="iconfont icon-shanchu" @click="clearLog"></view>
					</view>
				</view>
				<scroll-view scroll-y="true" :scroll-top="scrollTop" class="item-log-box" :scroll-with-animation="true">
					<view id="scroll-view-content">
						<view  class="log-item" v-for="(logItem,index) in logList" :key="index">
							<view v-if="logItem.type == 'up'" class="iconfont icon-arrow-up color-red"></view>
							<view v-else class="iconfont icon-arrow-down color-green"></view>
							<view class="log-item-content">
								<text class="log-item-time">
									{{logItem.time}} 
								</text>
								<text class="log-item-txt">
									{{logItem.txt}}
								</text>
							</view>
						</view>
						<view v-if="logList.length==0" class="log-item">
							数据日志监听中···
						</view>
					</view>	
				</scroll-view>
			</view> -->
			<view class="btn-box" @click="goDeviceControl">
				<button>设备控制</button>
			</view>
		</view>
		
		<!-- <u-select mode="single-column" :default-value="selectDefaultValue" v-model="selectShow" :list="selectList" @confirm="confirm"></u-select>
		<u-popup v-model="colorShow" closeable="true" mode="bottom" border-radius="10" safe-area-inset-bottom="true">
			<view class="">
				<view class="" style="display: flex;justify-content: center;align-items: center;height: 40rpx;margin: 24rpx 0;font-weight: bold;font-size: 34rpx;">
					选择颜色
				</view>
				<zebra-color-picker v-model="colors" @input="inputColor"></zebra-color-picker>
			</view>
		</u-popup> -->
		<u-modal v-model="detailShow" title="设备详情" :mask-close-able="true">
			<view class="detail-model">
				<view class="content-item">
					<view class="item-label">
						设备ID：
					</view>
					<view class="item-value">
						{{deviceInfo.devId}}
					</view>
				</view>
				<view class="content-item">
					<view class="item-label">
						设备名称：
					</view>
					<view class="item-value">
						{{deviceInfo.devName}}
					</view>
				</view>
				<view class="content-item">
					<view class="item-label">
						产品名称：
					</view>
					<view class="item-value">
						{{deviceInfo.product.prodName}}
					</view>
				</view>
				<view class="content-item">
					<view class="item-label">
						设备类型：
					</view>
					<view class="item-value">
						{{getDeviceTypeName('deviceType',deviceInfo.product.prodType)}}
					</view>
				</view>
				<view class="content-item">
					<view class="item-label">
						在线状态：
					</view>
					<view class="item-value" :style="{color:deviceInfo.devState==1?'#10CC70':deviceInfo.devState==2?'#FF2B38':'#999999'}">
						{{getDeviceTypeName('deviceStatus',deviceInfo.devState)}}
					</view>
				</view>
				<view class="content-item">
					<view class="item-label">
						创建时间：
					</view>
					<view class="item-value">
						{{deviceInfo.createdAt}}
					</view>
				</view>
				<view class="content-item">
					<view class="item-label">
						激活时间：
					</view>
					<view class="item-value">
						{{deviceInfo.activateTime}}
					</view>
				</view>
				<view class="content-item">
					<view class="item-label">
						最后上线时间：
					</view>
					<view class="item-value">
						{{deviceInfo.lastOnlineTime}}
					</view>
				</view>
			</view>
		</u-modal>
	</view>
</template>

<script>
	import IotsSelect from '@/components/iot-components/select/iots-select.vue'
	import IotsNumberBox from "@/components/iot-components/number-box/iots-number-box.vue"
	import IotsColorSelect from "@/components/iot-components/color/iots-color-select.vue"
	import IotsSwitch from '@/components/iot-components/switch/iots-switch.vue'
	import IotsSlider from '@/components/iot-components/slider/iots-slider.vue'
	import IotsSwitchBtn from '@/components/iot-components/switch-btn/iots-switch-btn.vue'
	import IotsText from '@/components/iot-components/text/iots-text.vue'
	import IotsBar from '@/components/iot-components/chart/bar/iots-bar.vue'
	import IotsLine from '@/components/iot-components/chart/line/iots-line.vue'
	import IotsPie from '@/components/iot-components/chart/pie/iots-pie.vue'
	import IotsGauge from '@/components/iot-components/chart/gauge/iots-gauge.vue'
	import IotsInput from '@/components/iot-components/input/iots-input.vue'
	import IotsSelectTime from '@/components/iot-components/select-time/iots-select-time.vue'
	import IotsImg from '@/components/iot-components/img/iots-img.vue'
	import uniDataSelect from "@/components/iot-components/uni-data-select/uni-data-select.vue"
	
	export default{
		data(){
			return{
				wsUrl:null,
				socketTask: null,
				wsStatus:false,
				deviceId:null,
				deviceName:null,
				deviceTime:null,
				deviceInfo:{
					devId:'',
					devName:'',
					devState:'',
					createdAt:'',
					activateTime:'',
					lastOnlineTime:'',
					token:'',
					tokenTs:'',
					pk:'',
					product:{
						prodName:'',
						prodType:'',
					},
					
				},
				scrollTop:0,
				selectGroup:0,
				// 属性分组
				groupList:[{
					value:0,
					label:'全部',
					groupKey:'all',
					groupName:'全部',
					groupRel:[]
				}],
				// 全部设备属性用于属性分组（不变）
				dataAllData:[],
				// 设备属性用于属性分组后数据（会变）
				dataList:[],
				dataIndex: 0,
				// 设备功能
				abilityList:[],
				
				selectShow: false,
				selectList: [{
						value: '0',
						label: '正常'
					},
					{
						value: '1',
						label: '异常'
					}
				],
				selectDefaultValue:[0],
				selectIndex: 0,
				selectItemIndex: 0,
				imgUploadUrl: 'http://www.example.com/upload',
				imgList: [],
				logList:[],
				colors:{
					hex: '#7ED321'
				},
				colorShow:false,
				detailShow:false,
				deviceTypeList:[
					{
						label: '直连设备',
						value: 'dev',
					},
					{
						label: '网关子设备',
						value: 'childrenDevice',
					},
					{
						label: '网关设备',
						value: 'gateway',
					}
				],
				deviceStatusList:[
					{
						label: '未激活',
						value: 0
					},
					{
						label: '在线',
						value: 1,
					},
					{
						label: '离线',
						value: 2,
					}
				],
			}
		},
		components: {
			IotsSelect,
			IotsSelectTime,
			IotsNumberBox,
			IotsColorSelect,
			IotsSwitch,
			IotsSlider,
			IotsSwitchBtn,
			IotsText,
			IotsBar,
			IotsLine,
			IotsPie,
			IotsGauge,
			IotsInput,
			IotsImg,
			uniDataSelect
		},
		onLoad(option) {
			console.log("option",option)
			this.deviceId = option.id;
			this.deviceName = option.devName;
			if(option.devName){
				// 修改页面标题
				uni.setNavigationBarTitle({
					title: option.devName
				});
			}
			this.getDeviceInfo(option.id);
			// this.logList = logList;
			let configList = uni.getStorageSync('configList');
			let configIndex = uni.getStorageSync('configIndex');
			this.wsUrl = (configList[configIndex].protocol == 'http://' ?'ws://':'wss://' ) + configList[configIndex].address
		},
		// 关闭websocket【必须在实例销毁之前关闭,否则会是underfined错误】
		beforeDestroy() {
			this.closeSocket();
		},
		watch:{
			logList(){
				this.scrollToBottom();
			}
		},
		methods:{
			goDeviceControl(){
				console.log("设备值",this.dataList);
				let dataList = encodeURIComponent(JSON.stringify(this.dataList).replace(/%/g, '%25'))
				uni.navigateTo({
					url:'./device-control?dataList=' + dataList + '&devId=' + this.deviceInfo.devId + '&pk=' + this.deviceInfo.pk + '&devName=' + this.deviceInfo.devName
				})
			},
			// 选择分组
			changeGroup(e){
				if(e != 0){
					const identifierMap = new Map();
					this.dataAllData.forEach(val => {
							identifierMap.set(val.identifier, val);
					});
					const attrArr = this.groupList[e].groupRel.map(item => identifierMap.get(item.ioRelKey));
					this.dataList = attrArr;
				}else{
					this.dataList = this.dataAllData;
				}
			},
			getChartData(type,data){
				if(type == 'charts_dashboard'){
					let min = 0;
					let max = 100;
					if(data.ioObj.IoDeployForm.min != undefined){
						min = parseFloat(data.ioObj.IoDeployForm.min);
					}
					if(data.ioObj.IoDeployForm.max != undefined){
						max = parseFloat(data.ioObj.IoDeployForm.max);
					}
					let percentage = (data.value/(max - min)).toFixed(2);
					return {series: [{name: data.name,data: percentage}]}
					
				}
			},
			getDeviceTypeName(type,key){
				// console.log("getDeviceTypeName",type,key)
				let label = '';
				if(type == 'deviceType'){
					this.deviceTypeList.forEach(item=>{
						if(key === item.value){
							label = item.label;
						}
					})
				}else if(type == 'deviceStatus'){
					this.deviceStatusList.forEach(item=>{
						if(key == item.value){
							label = item.label;
						}
					})
				}
				return label;
			},
			getDeviceInfo(deviceId){
				this.$api.iotsApi.getDeviceInfo({id:deviceId}).then(res => {
					console.log("获取设备详情",res)
					if(res.code == 0 && res.data){
						this.deviceInfo = res.data;
						
						if(res.data.product.thingModel){
							let thingModel = JSON.parse(res.data.product.thingModel);
							if(thingModel.contents.prop.length){
								this.dataList = thingModel.contents.prop.map(item=>{
									if(item.dataType=='int'){
										
										if(item.ioObj.IoDeployForm.min!=undefined){
											item.value = parseFloat(item.ioObj.IoDeployForm.min);
										}else{
											item.ioObj.IoDeployForm.min = 0;
											item.value = 0;
										}
									}else if(item.viewType == 'slider' || item.viewType == 'charts_dashboard' || (item.viewType == 'text' && item.formType == 'number')){
											console.log("item.ioObj.IoDeployForm.min",item.ioObj);
											if(item.ioObj && item.ioObj.IoDeployForm && item.ioObj.IoDeployForm.min!=undefined && item.ioObj.IoDeployForm.min!= null){
												item.value = parseFloat(item.ioObj.IoDeployForm.min);
											}else{
												// 确保ioObj对象存在于item内
												if (!item.ioObj) {
												    item.ioObj = {};
												}
												// 确保IoDeployForm对象存在于item.ioObj内
												if (!item.ioObj.IoDeployForm) {
												    item.ioObj.IoDeployForm = {};
												}
												// 现在可以安全地给min赋值
												item.ioObj.IoDeployForm.min = 0;
												if(item.ioObj.IoDeployForm.max == undefined){
													item.ioObj.IoDeployForm.max = 100;
												}
												item.value = 0;
											}
									}else{
										item.value = '';
									}
									item.time = 0;
									return item;
								})
								this.dataAllData = this.dataList;
							}else{
								this.dataList = [];
								this.dataAllData = [];
							}
							if(thingModel.contents.groups.length){
								let groupList = [{
									value:0,
									label:'全部',
									groupKey:'all',
									groupName:'全部',
									ioRelKey:[]
								}];
								thingModel.contents.groups.forEach((item,index)=>{
									groupList.push({
										value:index+1,
										label:item.groupName,
										...item
									})
								})
								this.groupList = groupList;
								// this.$nextTick(()=>{
								// 	this.$set(this,'groupList',groupList)
								// })
							}else{
								this.groupList = [{
									value:0,
									label:'全部',
									groupKey:'all',
									groupName:'全部',
									ioRelKey:[]
								}];
							}
							if(thingModel.contents.server.length){
								this.abilityList = thingModel.contents.server;
							}else{
								this.abilityList = [];
							}
							if(thingModel.contents.server.length){
								this.abilityList = thingModel.contents.server;
							}else{
								this.abilityList = [];
							}
							console.log("属性列表",this.dataList)
							this.connectSocketInit()
						}else{
							this.$u.toast('获取设备属性失败');
						}
						
					}else{
						this.$u.toast(res.message);
					}
				}, error => {
				})
			},
			openDeviceModel(){
				this.detailShow = true;
			},
			goDeviceAbility(){
				let abilityList = encodeURIComponent(JSON.stringify(this.abilityList))
				uni.navigateTo({
					url:'./device-ability-list?abilityList=' + abilityList + '&deviceName=' + this.deviceName + '&devId=' + this.deviceInfo.devId + '&pk=' + this.deviceInfo.pk
				})
			},
			goDeviceAlarm(){
				// this.$u.toast('功能未完成')
				uni.navigateTo({
					url:'/pages/iots/notice/list?devId=' + this.deviceInfo.devId + '&devName=' + this.deviceName
				})
			},
			clickLog(index){
				console.log("当前点击日志",this.dataList[index]);
				let obj = this.dataList[index];
				let devState = this.getDeviceTypeName('deviceStatus',this.deviceInfo.devState);
				uni.navigateTo({
					url:'./device-data?devId=' + this.deviceInfo.devId + '&devName=' + this.deviceInfo.devName + '&devState=' + devState + '&fields=' + obj.identifier
				})
				// h5 页不刷新
				// #ifdef H5
				location.reload()
				// #endif
			},
			downData(e,index){
				let params = {
					ac:'write',
					d:this.deviceInfo.devId,
					pk:this.deviceInfo.pk,
					p:{
						[this.dataList[index].identifier]:e
					}
				}
				console.log("下发数据JSON",params)
				// this.addLog('down',params);
				this.$api.iotsApi.downDeviceProp(params).then(res => {
					console.log("下发数据成功",res)
					if(res.code !=0){
						this.$u.toast(res.message)
					}
				}, error => {
				})
			},
			// 解析显示字段
			getParseText(e){
				// let textList = [];
				// try {
				//   if(e){
				// 		textList = JSON.parse(e)
				// 		return textList;
				// 	}else{
				// 		return textList;
				// 	}
				// } catch (error) {
				//   // 捕获异常并处理
				// 	console.log("文字列表解析失败" + error.message);
				// 	return textList;
				// }
				return [{"name":"今日用电","value":e,"unit":""}];
			},
			// 格式化select数据
			formatSelect(value, index){
				// 先格式化数据
				let reg = /\\/g;
				let str = value.funObj.replace(reg, '');
				let obj = JSON.parse(str)
				let selectList = [];
				for (let i in obj) {
					var obj1 = {
						value: i,
						label: obj[i]
					}
					selectList.push(obj1)
				}
				return selectList;
			},
			// 颜色选择变化
			inputColor(color){
				console.log("当前选择颜色为",color)
			},
			// 样式转换
			getVlaue(value) {
				let reg = /\\/g;
				let str = value.funObj.replace(reg, '');
				let obj = JSON.parse(str)
				if (value.funDataType == 'TEXT') {
					return value.lastValue;
				}else {
					return obj[value.lastValue];
				}
			},
			// 点击选择框
			changeSelect(value, index) {
				this.selectIndex = index;
				// 先格式化数据
				let reg = /\\/g;
				let str = value.funObj.replace(reg, '');;
				let obj = JSON.parse(str)
				this.selectList = [];
				for (let i in obj) {
					var obj1 = {
						value: i,
						label: obj[i]
					}
					this.selectList.push(obj1)
				}
				this.selectShow = true;
				// console.log("格式化之后的数据",this.selectList)
			},
			// 选择完成
			confirm(e) {
				if(this.dataList[this.selectIndex].funDataType=="TEXT"){
					this.$nextTick(() => {
						this.dataList[this.selectIndex].lastValue = e[0].label;
						this.selectDefaultValue = [this.selectList.findIndex(item => item.value === e[0].value)] || [0];
					})
				}else{
					this.$nextTick(() => {
						this.dataList[this.selectIndex].lastValue = e[0].value;
						this.selectDefaultValue = [this.selectList.findIndex(item => item.value === e[0].value)] || [0];
					})
				}
			},
			// 点击步进器
			changeNumber(e, index) {
				this.dataList[index].lastValue = e;
			},
			// 上传图片完成
			changeUploadImg(e){
				console.log("上传图片",e);
			},
			upLoadImg(){
				this.$refs.uPloadimgRef.upload();
			},
			scrollToBottom(){
				this.$nextTick(()=>{
					uni.createSelectorQuery().in(this).select('#scroll-view-content').boundingClientRect((res)=>{
						if(res){
							let top = res.height-195;
							if(top>0){
								this.scrollTop=top;
							}
						}
					}).exec()
				})
			},
			// 添加日志
			addLog(type,txt){
				this.logList.push({
					id:this.$u.guid(20),
					time:this.$u.timeFormat(new Date(), 'hh:MM:ss'),
					type,
					txt:JSON.stringify(txt),
				})
			},
			// 刷新数据日志
			resetLog(){
				this.logList = logList;
			},
			// 清理日志
			clearLog(){
				this.logList=[]
			},
			refresh(){
				console.log("点击刷新")
			},
			// 进入这个页面的时候创建websocket连接【整个页面随时使用】
			connectSocketInit() {
				// let ip = uni.getStorageSync('ipAddress');
				// 创建一个this.socketTask对象【发送、接收、关闭socket都由这个对象操作】
				this.socketTask = uni.connectSocket({
					// 【非常重要】必须确保你的服务器是成功的,如果是手机测试千万别使用ws://127.0.0.1:9099【特别容易犯的错误】
					url: this.wsUrl + '/iot/device/ws/prop/' + this.deviceInfo.devId + '/' + this
						.deviceInfo.token + '?ts=' + this.deviceInfo.tokenTs,
					success(data) {
						console.log("websocket连接成功", data);
			
					},
				});
			
				// 消息的发送和接收必须在正常连接打开中,才能发送或接收【否则会失败】
				this.socketTask.onOpen((res) => {
					console.log("WebSocket连接正常打开中...！");
					this.wsStatus = true;
					// 注：只有连接正常打开中 ，才能正常成功发送消息
					// this.socketTask.send({
					// 	data: "uni-app发送一条消息",
					// 	async success() {
					// 		console.log("消息发送成功");
					// 	},
					// });
					// 注：只有连接正常打开中 ，才能正常收到消息
					this.socketTask.onMessage((res) => {
						console.log("收到服务器内容：" + res.data);
						let obj = JSON.parse(res.data)
						// this.addLog('up',obj);
						this.deviceTime = this.$u.timeFormat(obj.fg_device_ts, 'yyyy-mm-dd hh:MM:ss');
						if (obj) {
							let dataList = JSON.parse(JSON.stringify(this.dataList));
							// 这是连接的第一次获取，虽然进页面已经获取一次最新数据，但是可能存在断开之后的请求，所以需要遍历覆盖
							for (let i = 0; i < dataList.length; i++) {
								for (let key in obj) {
									if (key == dataList[i].identifier) {
										if(dataList[i].viewType == 'slider' || (dataList[i].viewType == 'text' && dataList[i].formType == 'number')){
											dataList[i].value = parseFloat(obj[key]);
										}else{
											dataList[i].value = obj[key];
										}
										dataList[i].time = obj.fg_device_ts;
										break;
									}
								}
							}
							this.$nextTick(()=>{
								this.$set(this,'dataList',dataList)
								this.$forceUpdate()
							})
						}
					});
				})
				// 这里仅是事件监听【如果socket关闭了会执行】
				this.socketTask.onClose(() => {
					this.wsStatus = false;
					console.log("已经被关闭了")
				})
			},
			// 关闭websocket【离开这个页面的时候执行关闭】
			closeSocket() {
				let that = this;
				if(this.wsStatus){
					this.socketTask.close({
						success(res) {
							that.wsStatus = false;
							console.log("关闭成功", res)
						},
						fail(err) {
							console.log("关闭失败", err)
						}
					})
				}
			},
			refreshSocket(){
				if(this.wsStatus){
					this.closeSocket();
					setTimeout(()=>{
						this.connectSocketInit();
					},500)
				}else if(this.dataList.length == 0){
					this.$u.toast('设备属性为空，无法刷新')
				}else{
					this.connectSocketInit();
				}
			}
		}
	}
</script>

<style>
	page{
		background: #f5f5f5;
	}
</style>

<style lang="scss" scoped>
	.device-detail-box{
		padding-bottom: 160rpx;
	}
	.menu-list{
		display: flex;
		.menu-item{
			flex: 1;
			margin: 20rpx;
			background-color: #fff;
			border-radius: 20rpx;
			height: 130rpx;
			display: flex;
			align-items: center;
			justify-content: space-around;
			padding: 0 30rpx;
			box-shadow: 0px 0px 15rpx 0px rgba(201,201,201,0.4);
			.iconfont{
				font-size: 60rpx;
				background-image: -webkit-linear-gradient(90deg, #3BBCFF, #006CFF);
				-webkit-background-clip: text;
				-webkit-text-fill-color: transparent;
			}
			.menu-txt{
				font-size: 46rpx;
				font-family: Georgia, 'Times New Roman', Times, serif;
				font-weight: bold;
			}
		}
	}
	
	.attr-empty{
		margin: 20rpx 0;
		background-color: #fff;
		border-radius: 20rpx;
		padding: 250rpx 0;
	}
	
	.device-title-box{
		display: flex;
		justify-content: space-between;
		align-items: center;
		margin: 0 20rpx;
		padding: 20rpx;
		background-color: #fff;
		border-radius: 20rpx;
		
		.title-box-left{
			.title-txt{
				font-size: 30rpx;
				font-weight: bold;
				margin-bottom: 10rpx;
				display: flex;
				align-items: center;
				.title-name-detail{
					padding: 4rpx 12rpx;
					color: #006CFF;
					border: 1px solid #006CFF;
					border-radius: 10rpx;
					font-size: 26rpx;
					margin-left: 10rpx;
				}
			}
			.time-txt{
				font-size: 24rpx;
				color: #999;
			}
		}
		.title-right{
			display: flex;
			align-items: center;
			font-size: 30rpx;
			.iconfont{
				margin-right: 10rpx;
			}
		}
	}
	.group-list{
		display: flex;
		// justify-content: space-between;
		align-items: center;
		margin: 0 20rpx;
		margin-top: 20rpx;
		padding: 20rpx;
		background-color: #fff;
		border-radius: 20rpx;
		.group-list-label{
			margin-right: 10rpx;
			font-weight: bold;
		}
	}
	// 设备详情弹窗
	.detail-model{
		padding: 30rpx;
		.content-item{
			display: flex;
			align-items: center;
			margin-top: 10rpx;
			font-size: 28rpx;
			.item-label{
				margin-right: 10rpx;
			}
		}
	}
	
	.attr-list{
		padding: 0 20rpx 30rpx 20rpx;
		.attr-item{
			padding: 20rpx 20rpx;
			background: #fff;
			display: flex;
			align-items: center;
			justify-content: space-between;
			margin-top: 20rpx;
			border-radius: 10rpx;
			.attr-item-left{
				display: flex;
				align-items: center;
				font-size: 28rpx;
				color: #000;
				.iconfont{
					margin-right: 20rpx;
					font-size: 40rpx;
				}
				.icon-unordered-list{
					margin-left: 16rpx;
					margin-right: 0rpx;
					font-size: 36rpx;
					color: #0b7bff;
				}
			}
			.attr-item-right{
				flex: 1;
				// height: 70rpx;
				display: flex;
				flex-wrap: wrap;
				align-items: center;
				justify-content: flex-end;
				.attr-value{
					display: flex;
					align-items: center;
					justify-content: flex-end;
					height: 70rpx;
					flex: 1;
					&.item-select {
						padding: 0 20rpx;
						display: flex;
						align-items: center;
						justify-content: flex-end;
						color: #ccc;
						.iconfont{
							margin-left: 10rpx;
						}
					}
					&.item-input{
						// width: 250rpx;
						// border: 1px solid #dcdfe6;
						// border-radius: 8rpx;
						// background: #fafafa;
						input{
							flex: 1;
							height: 70rpx;
						}
					}
					&.item-img-box{
						height: 120rpx;
						color: #ccc;
					}
					&.item-number{
						flex: 0 1 auto;
						width: 250rpx;
						display: flex;
						align-items: center;
						justify-content: flex-end;
						color: #ccc;
						border: 1px solid #dcdfe6;
						border-radius: 8rpx;
						/deep/.number-box {
							.minus {
								border: none;
								border-right: 1px solid #dcdfe6;
							}
						
							.plus {
								border: none;
								border-left: 1px solid #dcdfe6;
							}
						}
					}
				}
			}
			
		}
		// 数据日志
		.item-log{
			background: #fff;
			margin-top: 20rpx;
			border-radius: 10rpx;
			overflow: hidden;
			.item-log-header{
				display: flex;
				justify-content: space-between;
				align-items: center;
				padding: 0 20rpx;
				line-height: 50rpx;
				background: $mainColor;
				color: #fff;
				.item-log-header-right{
					display: flex;
					align-items: center;
					.iconfont{
						padding: 10rpx 15rpx;
						// margin-left: 30rpx;
						font-size: 30rpx;
					}
				}
			}
			.item-log-box{
				height: 200px;
				padding: 10rpx;
				box-sizing: border-box;
				.log-item{
					position: relative;
					margin-bottom: 10rpx;
					// display: flex;
					.iconfont{
						position: absolute;
						top:2rpx;
						left:0;
						font-weight: bold;
					}
					.log-item-content{
						// display: inline-block;
						padding-right: 10rpx;
						word-wrap: break-word;
						white-space: pre-line;
						.log-item-time{
							color: $mainColor;
							margin: 0 10rpx 0 36rpx;
						}
						.log-item-txt{
							
						}
					}
					
				}
			}
		}
		
	}
	/deep/ .u-add-btn{
		display: none;
	}
	/deep/ .u-add-tips{
		margin-top: 0 !important;
	}
	// 设置颜色选择器宽为100%
	/deep/ .zebra-chrome{
		width: 100%;
	}
	.color-red{
		color: red;
	}
	.color-green{
		color: green;
	}
	.color-blue{
		color: #006CFF;
	}
	.btn-box{
		display: flex;
		align-items: center;
		justify-content: center;
		background: #fff;
		height: 140rpx;
		padding-bottom: 10rpx;
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		z-index: 99;
		button{
			width: 690rpx;
			height: 90rpx;
			background: #3683FD;
			border-radius: 43rpx;
			font-size: 32rpx;
			color: #FFFFFF;
			display: flex;
			justify-content: center;
			align-items: center;
		}
	}
</style>