<template>
	<view class="page">
		<u-navbar :is-back="false" :border-bottom="false" :background="bgc" title-color='#2E4975' title-size='36'
			height='8'></u-navbar>
		<view class="title" style="display: flex;padding: 0;align-items: center;font-size: 48rpx;font-weight: 600;color: #48893B;">		
		    <image style="width: 60rpx;margin-right: 10rpx;height: 50rpx;" src="https://api.ccttiot.com/smartmeter/img/static/u6wBJM2Dah2jLVGeSrKL" mode="aspectFit"></image> {{ $t('app.name') }}
		</view>
		<!-- 加载状态遮罩层 -->
		<view class="loading-mask" v-if="isLoading">
			<view class="loading-content">
				<u-loading mode="circle" size="60" color="#7FAD76"></u-loading>
				<text class="loading-text">{{ $t('index.loading') }}</text>
			</view>
		</view>
		<!-- 背景图 -->
		<!-- 没设备时展示 -->
		<image class="bjimg" v-if="bjflag" src="https://api.ccttiot.com/smartmeter/img/static/uz8MR6BuZW2qRANnYgLu"
			mode=""></image>
		<!-- 有设备时展示 -->
		<image class="bjimg" v-else src="https://api.ccttiot.com/smartmeter/img/static/uXBpJuaUs0XUNb8HTahh" mode="">
		</image>
		<view class="wusb" v-if="bjflag">
			<text>{{ $t('index.noDevice') }}</text>
			<view class="bang" @click="btnaddsb">
				{{ $t('index.bind') }}
			</view>
		</view>
		<view class="" v-else>
			<view class="selectbox">
				<view class="shebeiname" >
					<view class="" @click="btnksxz">
						{{user.deviceName == undefined ? '--' : user.deviceName}}
						<image style="width: 32rpx;height: 26rpx;margin-left: 14rpx;" v-if="!xuanzeflag" src="https://api.ccttiot.com/smartmeter/img/static/uwHOBxvbJjkhx1uDiQHI" mode=""></image>
						<image style="width: 32rpx;height: 26rpx;margin-left: 14rpx;" v-else class="rotated-image" src="https://api.ccttiot.com/smartmeter/img/static/uwHOBxvbJjkhx1uDiQHI" mode=""></image>
					</view>
					<view style="margin-left: 10rpx;" class="lj" @click="btnlj" v-if="vardataflag == 1">
						{{ $t('index.bleDirect') }}
					</view>
					<view class="lj" v-if="vardataflag == 2">
						{{ $t('index.connecting') }}
					</view>
					<view class="lj" style="color: #7FAD76;border: 1px solid #7FAD76;" v-if="vardataflag == 3" @click="btnduankai">
						{{ $t('index.connected') }}
					</view>
				</view>
				<view class="selectshezhi" style="display: flex;">
					<view class="gateway-item" @click="goToGatewayList" style="position: relative;padding: 0 20rpx;">
						<image class="gateway-icon-circle" src="https://api.ccttiot.com/ad93702b02429b8adf394569460b8b2a-1758263546164.png" mode="aspectFill"></image>
					    <view class="gateway-content" style="display: flex;align-items: center;">
					    </view>
					</view>
					<image style="margin-left: 10rpx;" @click="btnsz" src="https://api.ccttiot.com/smartmeter/img/static/uvCJ8ro0MpfGZd53vypJ" mode=""></image>
				</view>
			</view>
			<view v-if=" ver != '' && ver.slice(3) != version" @click="btnsz" class="" style="width: 100%;height: 76rpx;margin-top: 20rpx;">
				<image style="width: 100%;height: 76rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uFqC94yHg1YXw1GoqTsL" mode=""></image>
			</view>
			<!-- 设备信息 -->
			<view class="devicebox"> 
				<view class="devicetop">
					<view class="devicelt" @click="btnsz">
						<image :src="imgpic" mode="aspectFit"></image>
						<view class="xinghao">
							<view class="one" style="display: flex;align-items: center;">
								{{ $t('common.model') }}：{{user.model == undefined ? '--' : user.model}}
								<view class="" style="display: flex;align-items: center;margin-left: 20rpx;" v-if="vardataflag != 3">
									<view class="signal-bars" style="display: flex;align-items: flex-end;">
										<view class="signal-bar" :class="{'active': signalStrength >= 1}" style="width: 6rpx;height: 10rpx;background-color: #E0E0E0;margin-right: 3rpx;border-radius: 1rpx;"></view>
										<view class="signal-bar" :class="{'active': signalStrength >= 2}" style="width: 6rpx;height: 14rpx;background-color: #E0E0E0;margin-right: 3rpx;border-radius: 1rpx;"></view>
										<view class="signal-bar" :class="{'active': signalStrength >= 3}" style="width: 6rpx;height: 18rpx;background-color: #E0E0E0;margin-right: 3rpx;border-radius: 1rpx;"></view>
										<view class="signal-bar" :class="{'active': signalStrength >= 4}" style="width: 6rpx;height: 22rpx;background-color: #E0E0E0;border-radius: 1rpx;"></view>
									</view>
								</view>
								<view class="battery-wrap" style="font-weight: 400;font-size: 26rpx;margin-left: 20rpx;display: flex;align-items: center;">
									<view class="battery-box">
										<view class="battery-fill" :style="{ width: (batteryPercent != null ? (Number(batteryPercent) < 100 ? Number(batteryPercent) + 10 : 100) : 0) + '%',   backgroundColor: batteryColor }"></view>
										<!-- <view class="battery-text">{{ batteryPercent != null ? batteryPercent + '%' : '--' }}</view> -->
									</view>
									<view class="battery-nub"></view>
								</view>
							</view>
							<view class="">{{ $t('common.mac') }}：{{user.mac == undefined ? '--' : user.mac}}</view>
						</view>
					</view>
					<view v-if="vardataflag != 3" class="refresh-btn" :class="{ 'is-refreshing': isRefreshing }" @click="onRefreshClick">
						<text class="refresh-icon">{{ isRefreshing ? '⋯' : '↻' }}</text>
						<text class="refresh-text">{{ isRefreshing ? $t('index.refreshing') : $t('index.refresh') }}</text>
					</view>
				</view>
				<!-- SATER：双通道定时（A/B）斜跨样式（梯形tab） -->
				<view class="channel-switch" v-if="pre === 'SATER'">
					<view class="channel-bg channel-bg-a" :class="{ active: stareChannel === 'A' }"></view>
					<view class="channel-bg channel-bg-b" :class="{ active: stareChannel === 'B' }"></view>
					<view class="channel-text channel-text-a" :class="{ active: stareChannel === 'A' }" @click.stop="setStareChannel('A')">
						<text>A</text>
						<view class="channel-indicator" v-if="stareChannel === 'A'"></view>
					</view>
					<view class="channel-text channel-text-b" :class="{ active: stareChannel === 'B' }" @click.stop="setStareChannel('B')">
						<text>B</text>
						<view class="channel-indicator" v-if="stareChannel === 'B'"></view>
					</view>
				</view>
				<view class="deviceweek" v-if="['WATER', 'DATER', 'TATER', 'SATER'].includes(pre)" @click="btntime">
					<view class="weeklist">
						<view class="" v-if="!ver_data.p_set1 || ver_data.p_set1[3] == 0">
							<view class="kg" style="color: rgba(0, 0, 0, .3);" v-if="!ver_data.p_set1 || ver_data.p_set1[3] == 0">
								OFF
							</view>
							<view class="weekday" style="color: rgba(0,0,0,.3);">
								P1
							</view>
							<view class="time" style="color: rgba(0,0,0,.3);">
								{{ver_data.p_set1 && ver_data.p_set1[0] !== undefined ? ver_data.p_set1[0].toString().padStart(2, '0') + ':' + ver_data.p_set1[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" style="color: rgba(0,0,0,.3);" v-if="ver_data.p_set1 && ver_data.p_set1[4] > 1">
								 {{ $t('index.everyNdays', { n: ver_data.p_set1[4] }) }}
							</view>
							<view style="color: rgba(0,0,0,.3);" class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="" v-else>
							<view class="kg" style="color: #7FAD76;">
								ON
							</view>
							<view class="weekday">
								P1
							</view>
							<view class="time">
								{{ver_data.p_set1 && ver_data.p_set1[0] !== undefined ? ver_data.p_set1[0].toString().padStart(2, '0') + ':' + ver_data.p_set1[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" v-if="ver_data.p_set1 && ver_data.p_set1[4] > 1">
								 {{ $t('index.everyNdays', { n: ver_data.p_set1[4] }) }}
							</view>
							<view class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="img">
							<image v-if="shouldShowIcon(1)"
							    src="https://api.ccttiot.com/smartmeter/img/static/u9iZpd6bW6bUsUay4uvH" mode="">
							</image>
						</view>
					</view>
					<view class="weeklist">
						<view class="" v-if="!ver_data.p_set2 || ver_data.p_set2[3] == 0">
							<view class="kg" style="color: rgba(0, 0, 0, .3);" v-if="!ver_data.p_set2 || ver_data.p_set2[3] == 0">
								OFF
							</view>
							<view class="weekday" style="color: rgba(0,0,0,.3);">
								P2
							</view>
							<view class="time" style="color: rgba(0,0,0,.3);">
								{{ver_data.p_set2 && ver_data.p_set2[0] !== undefined ? ver_data.p_set2[0].toString().padStart(2, '0') + ':' + ver_data.p_set2[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" style="color: rgba(0,0,0,.3);" v-if="ver_data.p_set2 && ver_data.p_set2[4] > 1">
								{{ $t('index.everyNdays', { n: ver_data.p_set2[4] }) }}
							</view>
							<view style="color: rgba(0,0,0,.3);" class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="" v-else>
							<view class="kg" style="color: #7FAD76;">
								ON
							</view>
							<view class="weekday">
								P2
							</view>
							<view class="time">
								{{ver_data.p_set2 && ver_data.p_set2[0] !== undefined ? ver_data.p_set2[0].toString().padStart(2, '0') + ':' + ver_data.p_set2[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" v-if="ver_data.p_set2 && ver_data.p_set2[4] > 1">
								{{ $t('index.everyNdays', { n: ver_data.p_set2[4] }) }}
							</view>
							<view class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="img">
							<image v-if="shouldShowIcon(2)"
								src="https://api.ccttiot.com/smartmeter/img/static/u9iZpd6bW6bUsUay4uvH" mode="">
							</image>
						</view>
					</view>
					<view class="weeklist">
						<view class="" v-if="!ver_data.p_set3 || ver_data.p_set3[3] == 0">
							<view class="kg" style="color: rgba(0, 0, 0, .3);" v-if="!ver_data.p_set3 || ver_data.p_set3[3] == 0">
								OFF
							</view>
							<view class="weekday" style="color: rgba(0,0,0,.3);">
								P3
							</view>
							<view class="time" style="color: rgba(0,0,0,.3);">
								{{ver_data.p_set3 && ver_data.p_set3[0] !== undefined ? ver_data.p_set3[0].toString().padStart(2, '0') + ':' + ver_data.p_set3[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" style="color: rgba(0,0,0,.3);" v-if="ver_data.p_set3 && ver_data.p_set3[4] > 1">
								 {{ $t('index.everyNdays', { n: ver_data.p_set3[4] }) }}
							</view>
							<view style="color: rgba(0,0,0,.3);" class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="" v-else>
							<view class="kg" style="color: #7FAD76;">
								ON
							</view>
							<view class="weekday">
								P3
							</view>
							<view class="time">
								{{ver_data.p_set3 && ver_data.p_set3[0] !== undefined ? ver_data.p_set3[0].toString().padStart(2, '0') + ':' + ver_data.p_set3[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" v-if="ver_data.p_set3 && ver_data.p_set3[4] > 1">
								 {{ $t('index.everyNdays', { n: ver_data.p_set3[4] }) }}
							</view>
							<view class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="img">
							<image v-if="shouldShowIcon(3)"
								src="https://api.ccttiot.com/smartmeter/img/static/u9iZpd6bW6bUsUay4uvH" mode="">
							</image>
						</view>
					</view>
					<view class="weeklist">
						<view class="" v-if="!ver_data.p_set4 || ver_data.p_set4[3] == 0">
							<view class="kg" style="color: rgba(0, 0, 0, .3);" v-if="!ver_data.p_set4 || ver_data.p_set4[3] == 0">
								OFF
							</view>
							<view class="weekday" style="color: rgba(0,0,0,.3);">
								P4
							</view>
							<view class="time" style="color: rgba(0,0,0,.3);">
								{{ver_data.p_set4 && ver_data.p_set4[0] !== undefined ? ver_data.p_set4[0].toString().padStart(2, '0') + ':' + ver_data.p_set4[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" style="color: rgba(0,0,0,.3);" v-if="ver_data.p_set4 && ver_data.p_set4[4] > 1">
								{{ $t('index.everyNdays', { n: ver_data.p_set4[4] }) }}
							</view>
							<view style="color: rgba(0,0,0,.3);" class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="" v-else>
							<view class="kg" style="color: #7FAD76;">
								ON
							</view>
							<view class="weekday">
								P4
							</view>
							<view class="time">
								{{ver_data.p_set4 && ver_data.p_set4[0] !== undefined ? ver_data.p_set4[0].toString().padStart(2, '0') + ':' + ver_data.p_set4[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" v-if="ver_data.p_set4 && ver_data.p_set4[4] > 1">
								{{ $t('index.everyNdays', { n: ver_data.p_set4[4] }) }}
							</view>
							<view class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="img">
							<image v-if="shouldShowIcon(4)"
								src="https://api.ccttiot.com/smartmeter/img/static/u9iZpd6bW6bUsUay4uvH" mode="">
							</image>
						</view>
					</view>
					<view class="weeklist">
						<view class="" v-if="!ver_data.p_set5 || ver_data.p_set5[3] == 0">
							<view class="kg" style="color: rgba(0, 0, 0, .3);" v-if="!ver_data.p_set5 || ver_data.p_set5[3] == 0">
								OFF
							</view>
							<view class="weekday" style="color: rgba(0,0,0,.3);">
								P5
							</view>
							<view class="time" style="color: rgba(0,0,0,.3);">
								{{ver_data.p_set5 && ver_data.p_set5[0] !== undefined ? ver_data.p_set5[0].toString().padStart(2, '0') + ':' + ver_data.p_set5[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" style="color: rgba(0,0,0,.3);" v-if="ver_data.p_set5 && ver_data.p_set5[4] > 1">
								{{ $t('index.everyNdays', { n: ver_data.p_set5[4] }) }}
							</view>
							<view style="color: rgba(0,0,0,.3);" class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="" v-else>
							<view class="kg" style="color: #7FAD76;">
								ON
							</view>
							<view class="weekday">
								P5
							</view>
							<view class="time">
								{{ver_data.p_set5 && ver_data.p_set5[0] !== undefined ? ver_data.p_set5[0].toString().padStart(2, '0') + ':' + ver_data.p_set5[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" v-if="ver_data.p_set5 && ver_data.p_set5[4] > 1">
								{{ $t('index.everyNdays', { n: ver_data.p_set5[4] }) }}
							</view>
							<view class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="img">
							<image v-if="shouldShowIcon(5)"
								src="https://api.ccttiot.com/smartmeter/img/static/u9iZpd6bW6bUsUay4uvH" mode="">
							</image>
						</view>
					</view>
					<view class="weeklist">
						<view class="" v-if="!ver_data.p_set6 || ver_data.p_set6[3] == 0">
							<view class="kg" style="color: rgba(0, 0, 0, .3);" v-if="!ver_data.p_set6 || ver_data.p_set6[3] == 0">
								OFF
							</view>
							<view class="weekday" style="color: rgba(0,0,0,.3);">
								P6
							</view>
							<view class="time" style="color: rgba(0,0,0,.3);">
								{{ver_data.p_set6 && ver_data.p_set6[0] !== undefined ? ver_data.p_set6[0].toString().padStart(2, '0') + ':' + ver_data.p_set6[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" style="color: rgba(0,0,0,.3);" v-if="ver_data.p_set6 && ver_data.p_set6[4] > 1">
								{{ $t('index.everyNdays', { n: ver_data.p_set6[4] }) }}
							</view>
							<view style="color: rgba(0,0,0,.3);" class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="" v-else>
							<view class="kg" style="color: #7FAD76;">
								ON
							</view>
							<view class="weekday">
								P6
							</view>
							<view class="time">
								{{ver_data.p_set6 && ver_data.p_set6[0] !== undefined ? ver_data.p_set6[0].toString().padStart(2, '0') + ':' + ver_data.p_set6[1].toString().padStart(2, '0') : '--:--'}}
							</view>
							<view class="interval" v-if="ver_data.p_set6 && ver_data.p_set6[4] > 1">
								{{ $t('index.everyNdays', { n: ver_data.p_set6[4] }) }}
							</view>
							<view class="interval" v-else>
								{{ $t('index.daily') }}
							</view>
						</view>
						<view class="img">
							<image v-if="shouldShowIcon(6)"
								src="https://api.ccttiot.com/smartmeter/img/static/u9iZpd6bW6bUsUay4uvH" mode="">
							</image>
						</view>
					</view>
				</view>
				<view class="" style="margin-top: 18rpx;display: flex;justify-content: space-between;" v-else>
					<view class="" style="font-size: 24rpx;color: #50565A;text-align: center;margin-top: 10rpx;">
						<view class="" style="display: flex;align-items: center;">
							<image style="width:32rpx;height:32rpx;margin-right: 8rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uhyYG0TLfWi9XUhTQz7D" mode=""></image>
							{{ $t('index.startTime') }}
						</view>
						<view class="" style="margin-top:10rpx;font-size: 36rpx;font-weight: 600;" v-if="csbobj.hour">
							{{csbobj.hour == undefined ? '--' : csbobj.hour + ':'}}{{csbobj.minute == undefined ? '' : csbobj.minute}}
						</view>
						<view class="" style="margin-top:10rpx;font-size: 36rpx;font-weight: 600;" v-else>
							{{formatOnlineStartTime(zaixianobj)}}
						</view>
					</view>
					<view class="" style="font-size: 24rpx;color: #50565A;margin-top: 10rpx;text-align: center;">
						<view class="" style="display: flex;align-items: center;">
							<image style="width:32rpx;height:32rpx;margin-right: 8rpx;font-size: 36rpx;font-weight: 600;" src="https://api.ccttiot.com/smartmeter/img/static/uuQaK98cmdQQnPWus27Z" mode=""></image>
							{{ $t('index.workDuration') }}
						</view>
						<view class="" style="margin-top:10rpx;font-size: 36rpx;font-weight: 600;" v-if="csbobj.second">
							{{csbobj.second == undefined ? '--' : csbobj.second + $t('common.sec')}}
						</view>
						<view class="" style="margin-top:10rpx;font-size: 36rpx;font-weight: 600;" v-else>
							{{zaixianobj.t.value == undefined ? '--' : zaixianobj.t.value + $t('common.sec')}}
						</view>
					</view>
					<view class="" style="font-size: 24rpx;color: #50565A;margin-top: 10rpx;text-align: center;">
						<view class="" style="display: flex;align-items: center;">
							<image style="width:32rpx;height:32rpx;margin-right: 8rpx;font-size: 36rpx;font-weight: 600;" src="https://api.ccttiot.com/smartmeter/img/static/uM6Yz4xVqFwzW6xlTRph" mode=""></image>
							{{ $t('index.intervalDays') }}
						</view>
						<view class="" style="margin-top:10rpx;font-size: 36rpx;font-weight: 600;" v-if="csbobj.day">
							{{csbobj.day == undefined ? '--' : csbobj.day + $t('common.day')}}
						</view>
						<view class="" style="margin-top:10rpx;font-size: 36rpx;font-weight: 600;" v-else>
							{{zaixianobj.d.value == undefined ? '--' : zaixianobj.d.value + $t('common.day')}}
						</view>
					</view>
				</view>
			</view>
			<!-- 开关选择 -->
			<view class="dangqian">
				<view class="" style="display: flex;">
					<image src="https://lxnapi.ccttiot.com/smartmeter/img/static/ufHmxq7KI9PJhv8ey4ds" mode=""></image>
					<view class="cen" @click="btntb">
						<view class="shen">
							{{ $t('index.currentTime') }} <text>{{ $t('index.sync') }}</text>
						</view>
						<view class="">
							{{ $t('index.tapSyncHint') }}
						</view>
					</view>
				</view>
				<view class="rt" style="display: flex;align-items: center;" @click="btnsztime">
					{{devicetime == '' ? '--' : devicetime.slice(0,5)}} <u-icon name="arrow-right" color="#7FAD76" size="32"></u-icon>
				</view>
			</view>
			<view class="switchbox">
				<view class="switch_he" v-if="['WATER', 'DATER', 'TATER', 'SATER'].includes(pre)">
					<image src="https://api.ccttiot.com/smartmeter/img/static/u7NwkNOoQYYsvHVMkDlu" mode=""></image>
					<view class="yushui">
						{{ $t('index.rainSensor') }}
						<u-switch v-if="yschecked" v-model="one" @change="btnyushui" :disabled="isRainSensorLocked" inactive-color="#eee"
							active-color="#eee" size="40"></u-switch>
						<u-switch v-else v-model="ones" @change="btnyushuis" :disabled="isRainSensorLocked" active-color="#7FAD76"
							inactive-color="#7FAD76" size="40"></u-switch>
					</view>
				</view>
				<view class="switch_he" v-if="['WATER', 'DATER', 'TATER', 'SATER'].includes(pre)">
					<image src="https://api.ccttiot.com/smartmeter/img/static/u7kd92ocUgDN052nhp4R" mode=""></image>
					<view class="yushui">
						{{ $t('index.childLock') }} <u-switch v-if="etchecked" v-model="two" @change="btnertong" inactive-color="#eee"
							active-color="#eee" size="40"></u-switch>
						<u-switch v-else v-model="twos" @change="btnertongs" active-color="#7FAD76"
							inactive-color="#7FAD76" size="40"></u-switch>
					</view>
				</view>
			</view>
			<view class="" style="display: flex;justify-content: space-between;">
				<!-- 定时 -->
				<view class="dingshi_he" @click="btntime">
					<view class="naoz">
						<image src="https://api.ccttiot.com/smartmeter/img/static/uJPgzMejk9gaogWnCO9M" mode=""></image> <text v-if="['WATER', 'DATER', 'TATER', 'SATER'].includes(pre)">{{ $t('index.groups6') }}</text>
					</view>
					<view class="dstime">
						{{ $t('index.timerMgmt') }} <image src="https://api.ccttiot.com/smartmeter/img/static/uagx3wGa7RYvqKqoSymy" mode="">
						</image>
					</view>
				</view>
				<!-- 手动浇水 -->
				<view class="dingshi_he">
					<view class="naoz" style="font-weight: 400;font-size: 26rpx;align-items: center;">
						<image style="width: 170rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uVYXvo4F6U6fJ5fP27BT" mode="aspectFill"></image>
						<text v-if="(sdminutes || sdseconds) && pre === 'SATER'">{{stareChannel}}</text>
						{{ sdminutes ? sdminutes + ':' : '' }}{{ sdseconds ? sdseconds : '' }}
						<text v-if="showWateringCountdown && wateringCountdownSeconds" style="margin-left: 10rpx;color: #7FAD76;font-size: 24rpx;">
						{{ wateringCountdownMinutes ? wateringCountdownMinutes + ':' : '' }}{{ wateringCountdownSeconds }}
						</text>
					</view>
					<view class="dstime">
						{{ $t('index.manualWater') }} <u-switch v-if="kgflag" v-model="jskeds" @change="btngb"  inactive-color="#eee" active-color="#eee" size="40"></u-switch>
							<u-switch v-else v-model="jsked" @change="btnkq" active-color="#7FAD76" inactive-color="#7FAD76" size="40"></u-switch>
					</view>
				</view>
			</view>
			<!-- 浇水日志 -->
			<view class="wateringlogbox" v-if="['WATER', 'DATER', 'TATER', 'SATER'].includes(pre)" @click="btnjs">
				<view class="wateringlogtop">
					<image src="https://api.ccttiot.com/smartmeter/img/static/uGh3pRM7mMRSHdmvtzv3" mode=""></image>
					{{ $t('index.wateringLog') }}
				</view>
				<view class="wateringlogbd">
					<view class="lt" >
						<view class="">{{ $t('index.lastSprayDur') }}{{jsobj.sprayingTime == undefined ? '--' : jsobj.sprayingTime + 's'}}</view>
						<view class="">{{ $t('index.lastWater') }}{{jsobj.lastWaterTime == undefined ? '--' : jsobj.lastWaterTime + 's'}}</view>
					</view>
					<view class="rt">
						<image src="https://api.ccttiot.com/smartmeter/img/static/uagx3wGa7RYvqKqoSymy" mode=""></image>
					</view>
				</view>
			</view>
			<view class="" @click="btnbc" v-if="['WATER', 'DATER', 'TATER', 'SATER'].includes(pre)" style="width: 100%;height: 80rpx;background-color: #7FAD76;color: #fff;text-align: center;font-size: 32rpx;line-height: 80rpx;margin-top: 30rpx;border-radius: 20rpx;">
				{{ $t('index.saveTimer') }}
			</view>
		</view>
		<!-- 切换设备 -->
		<view class="tabsb" v-if="xuanzeflag">
			<view class="selectbox">
				<view class="selectname" @click="btnksxz">
					{{ $t('index.switchDevice') }} <image v-if="!xuanzeflag" src="https://api.ccttiot.com/smartmeter/img/static/uwHOBxvbJjkhx1uDiQHI" mode=""></image>
					        <image v-else class="rotated-image" src="https://api.ccttiot.com/smartmeter/img/static/uwHOBxvbJjkhx1uDiQHI" mode=""></image>
				</view>
			</view>
			<view class="sblist">
				<view class="sbist_val" v-for="(item,index) in devicelist" :key="index" @click="btnactive(item.deviceId,index)">
					<view class="lt">
						<view class="">{{item.deviceName}}</view>
						<view class="" style="font-weight: 400;font-size: 26rpx;color: #989090;margin-top: 10rpx;">
							{{item.mac}}
						</view>
					</view>
					<view class="rt">
						<image :src="item.modelPicture" mode="aspectFit"></image>
					</view>
				</view>
			</view>
			<view class="qdan" @click="btnaddsb">
				{{ $t('index.addDevice') }}
			</view>
		</view>
		<view class="mask" v-if="xuanzeflag" @click="btntc"></view>
		<!-- 手动浇水 -->
		<view class="manualjs" v-if="sdjsflag">
			<view class="toptit">
				{{ $t('index.pickDuration') }}
			</view>
			<view class="container" @click="btnshowjs">
				<view class="">{{minute}}{{ $t('common.min') }}</view>
				<text>:</text>
				<view class="">{{second}}{{ $t('common.sec') }}</view>
			</view>
			<view class="anniu">
				<view class="qx" @click="btnqx">
					{{ $t('common.cancel') }}
				</view>
				<view class="qd" @click="btnqd">
					{{ $t('common.confirm') }}
				</view>
			</view>
		</view>
		<view class="manualmask" v-if="sdjsflag"></view>
		<!-- 选择浇水时间-->
		<u-picker v-model="showjs" mode="time" :default-time="0" :params="params" @confirm="confirm"></u-picker>
        <!-- 设置当前时间 -->
		<u-picker v-model="timeflag" mode="time" :params="paramss" @confirm="confirmtime"></u-picker>
		<tab-bar :indexs='0'></tab-bar>
		<language-float />
		
		<!-- 自定义错误弹窗 -->
		<view class="error-modal-mask" v-if="showErrorModal" @click="closeErrorModal">
			<view class="error-modal-container" @click.stop>
				<view class="error-modal-header">
					<view class="error-icon">⚠️</view>
					<text class="error-modal-title">{{errorModalData.title}}</text>
				</view>
				<view class="error-modal-content">
					<view class="error-message">{{errorModalData.message}}</view>
					<view class="error-action" v-if="errorModalData.userAction">
						<text class="action-label">{{ $t('index.suggestion') }}</text>
						<text class="action-text">{{errorModalData.userAction}}</text>
					</view>
				</view>
				<view class="error-modal-footer">
					<view class="error-btn error-btn-cancel" v-if="errorModalData.showCancel" @click="closeErrorModal">
						{{errorModalData.cancelText || $t('common.cancel')}}
					</view>
					<view class="error-btn error-btn-confirm" @click="handleErrorConfirm">
						{{errorModalData.confirmText || $t('common.confirm')}}
					</view>
				</view>
			</view>
		</view>

	</view>
</template>

<script>
	import LanguageFloat from '@/components/language-float/language-float.vue'
	var xBlufi = require("@/components/blufi/xBlufi.js")
	export default {
		components: {
			LanguageFloat
		},
		data() {
			return {
				timeflag:false,
				// 手动浇水“确定”按钮请求锁：请求未返回前禁止重复提交
				isManualWaterRequesting: false,
				// 点击确定后立即锁死雨水感应（不等请求返回），请求失败或浇水结束才解锁
				rainSensorLockedByWatering: false,
				// 手动浇水开关（开启/关闭）防频繁点击：接口模式等请求结束，蓝牙模式至少冷却3秒
				isManualWaterSwitchRequesting: false,
				manualWaterBtCooldownUntil: 0,
				// 浇水倒计时到0后的延迟清理定时器（避免和新倒计时串台）
				wateringCountdownResetTimer: null,
				// 刷新按钮“刷新中”状态，约 1.5 秒
				isRefreshing: false,
				// 最近一次成功上传的时间戳（毫秒）
				lastUploadTs: 0,
				// 最近一次获取电量的时间戳（毫秒）
				lastPowerTs: 0,
				one: false,
				ones: true,
				two: false,
				twos: true,
				jsked:true,
				jskeds:false,
				yschecked: false,
				etchecked: false,
				kgflag: true,
				activeshu: 0,
				xuanzeflag: false,
				selectedMinute: '1',
				selectedSecond: '1',
				sdjsflag: false,
				showjs: false,
				params: {
					year: false,
					month: false,
					day: false,
					hour: false,
					minute: true,
					second: true
				},
				paramss: {
					year: false,
					month: false,
					day: false,
					hour: true,
					minute: true,
					second: false
				},
				minute: '00',
				second: '10',
				hasShownVersionAlert: false,
				deviceId: '',
				name: '',
				mac: '',
				jstime: '10',
				ver_data: {},
				vardataflag:1,
				showobj: {},
				jstimeobj:{},
				xctime: '--',
				sctimejs: '--',
				xctimesc: '--',
				xctimesj: '',
				sdminutes: '',
				sdseconds: '',
				wateringCountdownMinutes: '', // 浇水倒计时分钟（从showArray[4]获取）
				wateringCountdownSeconds: '', // 浇水倒计时秒数（从showArray[4]获取）
				showWateringCountdown: false, // 是否显示浇水倒计时（第三位和第四位都为1时才显示）
				datalist: '',
				devicelist:[],
				shebid:'',
				user:{},
				lastChar:'',
				timer:'',
				wateringCountdownTimer: null, // 浇水倒计时定时器
				bjflag: '', 
				userobj:{},
				devicesarr:[],
				intervalId: null,
				imgflag:true,
				ver:'',
				pre:'',
				csbobj:{},
				disconnectTimer: null,
				devicetime:'',
				imgpic:'',
				xinp:'',
				version:'',
				jiance:false,
				shibainum:0,
				searchStartTime: 0,      // 记录开始搜索的时间戳
				searchTimeout: 10000,    // 10秒超时（单位：毫秒）
				searchTimer: null,       // 搜索定时器
				isSearching: false,      // 是否正在搜索中
				dataTimeoutTimer: null   ,// 5秒数据看门狗定时器
				connectionStartTime: 0,  // 记录连接开始时间
				connectionTimeout: null, // 连接超时定时器
				connectTimeout: null,    // 配对超时定时器
				errorModalShown: false,  // 错误弹窗是否已显示（防止重复弹出）
				currentErrorType: null,   // 当前检测到的错误类型
				showErrorModal: false,     // 是否显示自定义错误弹窗
				errorModalData: {},        // 错误弹窗数据
				dianya:0,
				sydl:'--',
				signalStrength: 0, // 信号强度格数（1-4）
				zaixianobj:{},
				modelId:'',
				jsobj:{},
				isLoading: false ,// 设备请求加载状态
				vatatxt:'',
				sn:'',
				onlineTime:'',
				onlineStatus:'',
				qiehuan:'',
				// SATER 双通道（A/B）
				stareChannel: 'A',
				// SATER 按类型缓存：pA/pB/ver 三组数据不定序到达，存各自最新值
				saterDataByType: { pA: '', pB: '', ver: '' },
				// SATER 最近一次完整原始数据（包含 A/B），用于通道切换后重算
				saterRawPayload: '',
				// SATER 从 getDetail 接口解析的 A/B 组别（非蓝牙模式展示用）
				saterListA: {},
				saterListB: {}
			}
		},
		computed: {
			// 是否正在浇水（手动定时器或设备倒计时在跑），用于：浇水开关不可关闭、雨水感应不可点击
			isWateringInProgress() {
				const manualRunning = !!(this.sdminutes || this.sdseconds)
				const deviceCountdownRunning = !!(this.showWateringCountdown && (this.wateringCountdownMinutes || this.wateringCountdownSeconds))
				return manualRunning || deviceCountdownRunning
			},
			// 雨水感应是否锁死（点击确定那一刻即锁，请求失败或浇水结束才解锁）
			isRainSensorLocked() {
				return this.isWateringInProgress || this.rainSensorLockedByWatering
			},
			// 电量百分比 0-100，无效时为 null（显示 --）
			batteryPercent() {
				if (this.sydl == null || this.sydl === '' || isNaN(Number(this.sydl))) return null
				return Math.min(100, Math.max(0, Math.floor(Number(this.sydl))))
			},
			// 电量条背景色：低红、中黄、高绿
			batteryColor() {
				if (this.batteryPercent == null) return '#E0E0E0'
				if (this.batteryPercent <= 20) return '#F44336'
				if (this.batteryPercent <= 49) return '#FFC107'
				return '#7FAD76'
			}
		},
		// 分享到好友（会话）
		onShareAppMessage: function() {
			return {
				title: this.$t('app.name'),
				path: '/pages/index/index'
			}
		},

		// 分享到朋友圈  
		onShareTimeline: function() {
			return {
				title: this.$t('app.name'),
				query: '',
				path: '/pages/index/index'
			}
		},
		onLoad(e) {	
			console.log(e,'000000000000000000000000000000000000');
			if(e.q){
				function getQueryParam(url, paramName) {
					let regex = new RegExp(`[?&]${paramName}=([^&]*)`)
					let results = regex.exec(url)
					return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null
				}
				let sceneValue = e.q
				let decodedValue = decodeURIComponent(sceneValue)
				this.sn = getQueryParam(decodedValue, 's')
				let data = {
					sn:this.sn
				}
				this.$u.post(`/app/device/bindDevice`,data).then((res) => {
					if (res.code == 200) {
					   uni.showModal({
					     title: this.$t('common.tip'),
					     content: this.$t('common.bindSuccess'),
					     showCancel: false,
					     confirmText: this.$t('common.gotIt')
					   })
					}else if(res.code == 401){
						this.jmlogin()
					} else{
					  uni.showModal({
					    title: this.$t('common.tip'),
					    content: res.msg,
					    showCancel: false,
					    confirmText: this.$t('common.gotIt')
					  })
					}
				})
			}
			xBlufi.initXBlufi(1)
		},
		onShow() {
			// 从定时页返回时：若当前是蓝牙已连接状态，先同步定时页可能写入的 BLE 数据并在首页解析
			if (this.$store && this.$store.state.bleWaterData && this.$store.state.bleWaterData.raw && this.vardataflag === 3 && (this.pre === 'WATER' || this.pre === 'SATER')) {
				const raw = this.$store.state.bleWaterData.raw
				this.datalist = (raw.slice(-1) === ';' ? raw : raw.slice(0, -1) + ';')
				if (this.pre === 'SATER') {
					this.saterRawPayload = this.datalist
					this.grisfjx()
				} else {
					this.getchuli()
				}
				this.$store.commit('clearBleWaterData')
			}
			// 蓝牙已连接时确保注册监听，以便返回首页后能继续收到设备推送
			if (this.vardataflag === 3) {
				xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
			}
			// 请求个人信息
			this.getinfo() 
			this.getshuju() // 页面加载时启动定时器
		},
		mounted() {
		   
		},
		onHide() {
		    // 页面隐藏时清除定时器
		   this.clearTimer()
		   this.clearDisconnectTimer()
		   this.clearDataTimeoutTimer()
		   this.clearConnectionTimeout()
		   this.clearWateringCountdownTimer()
		},
		onUnload() {
		    // 页面卸载时清除定时器
		   this.clearTimer()
		   this.clearDisconnectTimer()
		   this.clearDataTimeoutTimer()
		   this.clearConnectionTimeout()
		   this.clearWateringCountdownTimer()
		},
		methods: {
			pad2(v){
				if (v == null || v === '' || v === undefined) return '-'
				const s = String(v)
				return s.length < 2 ? ('0' + s) : s
			},
			formatOnlineStartTime(obj){
				const h = obj && obj.h ? obj.h.value : undefined
				const m = obj && obj.m ? obj.m.value : undefined
				if (h === undefined || m === undefined) return '--:--'
				return `${this.pad2(h)}:${this.pad2(m)}`
			},
			// 点击弹窗进行隐藏
			btntc(){
				this.xuanzeflag = !this.xuanzeflag
			},
			
			// 将时间格式（HH:mm）转换为总秒数
			timeToSeconds(timeStr) {
				if (!timeStr || timeStr === '--' || !timeStr.includes(':')) {
					return 0;
				}
				const [hours, minutes] = timeStr.split(':').map(Number);
				return (hours || 0) * 3600 + (minutes || 0) * 60;
			},
			// 将总秒数转换为时间格式（HH:mm）
			secondsToTime(seconds) {
				if (!seconds && seconds !== 0) {
					return '--';
				}
				const totalSeconds = parseInt(seconds) || 0;
				const hours = Math.floor(totalSeconds / 3600);
				const minutes = Math.floor((totalSeconds % 3600) / 60);
				return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
			},
			// 点击断开连接
			btnduankai(){
				wx.closeBLEConnection({
					deviceId: this.deviceId,
				})
				this.fullPageRefresh()
			},
			// 跳转到网关列表
			goToGatewayList() {
				uni.navigateTo({
					url: '/pages/gateway/list'
				})
			},
			// 请求浇花器数据
			getsj(){
				this.$u.get(`/app/device/getDetail?deviceId=${this.shebid}`).then(res => {
					if (res.code == 200) {
						this.zaixianobj = res.data.iotData
						this.modelId = res.data.modelId
						console.log(this.vardataflag,this.zaixianobj);
						// 非蓝牙模式时，用后台数据组装渲染结构
						if((this.pre === 'WATER' || this.pre === 'SATER') && this.vardataflag != 3 || this.pre === 'DATER' && this.vardataflag != 3 || this.pre === 'TATER' && this.vardataflag != 3){
							this.ver_data = this.buildVerDataFromBackend(this.zaixianobj)
							this.calculateNextWateringTime()
						}
						if(this.pre === 'SMSJ:' && this.vardataflag != 3){
							this.ver_data = this.buildVerDataFromBackend(this.zaixianobj)
							// this.ver_data = this.zaixianobj
							console.log(this.ver_data,'55555555555prprprprprprprpr');
						}
						if (res.data && res.data.iotData && res.data.iotData.xinp !== undefined) {
						  this.xinp = res.data.iotData.xinp.value == undefined ? '--' : res.data.iotData.xinp.value
						}
						if (res.data && res.data.iotData && res.data.iotData.yudi !== undefined) {
						  if (!this.isRainSensorLocked) {
						  	this.yschecked = res.data.iotData.yudi.value == 0 ? true : false
						  }
						}
						if (res.data && res.data.iotData && res.data.iotData.lock !== undefined) {
						  this.etchecked = res.data.iotData.lock.value == 0 ? true : false
						}
						// 优先从 nt.value 获取总秒数，如果没有则从 time.value 获取
						let ntValue = res?.data?.iotData?.nt?.value;
						if (ntValue !== undefined && ntValue !== null && ntValue !== '') {
							// 从总秒数转换为时间格式
							this.devicetime = this.secondsToTime(ntValue);
						} else {
							// 兼容旧数据，从 time.value 获取
							let originalValue = (res?.data?.iotData?.time?.value ?? "").toString().trim();
							// 去掉首尾可能多出来的英文双引号 "
							originalValue = originalValue.replace(/^"|"$/g, '');
							this.devicetime = originalValue || "--";
						}
						console.log('devicetime:', this.devicetime);
						// 获取信号强度
						if (res.data && res.data.iotData && res.data.iotData.RSSI !== undefined && res.data.iotData.RSSI.value !== undefined) {
							this.signalStrength = this.calculateSignalStrength(res.data.iotData.RSSI.value)
						} else {
							this.signalStrength = 0
						}
						// 取值
						this.onlineTime = res.data.onlineTime
						this.onlineStatus = res.data.onlineStatus
						if(res.data.iotData && res.data.iotData.bat !== undefined && res.data.iotData.bat.value !== undefined){
							this.dianya = res.data.iotData.bat.value
							this.getdianliang()
						}
 					}
				})
			},
			// 点击保存设置
			btnbc(){
				this.handleUserAction()
				if(this.vardataflag != 3){
					let parameters = {
						time:this.xinp
					}
					let data = {
						deviceId:this.shebid,
						instructionKey:'sleep',
						parameters:parameters
					}
					this.$u.post(`/app/sendCommandByGateway`,data).then(res => {
						if (res.code == 200) {
							uni.showToast({
								title: this.$t('common.saveOk'),
								icon: 'success',
								duration:2000
							})
						}else{
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}else{
					this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=sleep`).then(res =>{
						if(res.code == 200){
							uni.showToast({
								title: this.$t('common.saveOk'),
								icon: 'success',
								duration:2000
							})
							xBlufi.notifySendCustomData({
								customData: '11' + this.format(res.data, {time: this.xinp })
							})
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}
			},
			getbanbens(){
				this.$u.get(`/app/model/${this.user.modelId}`).then(res => {
					if (res.code == 200) {
						this.version = res.data.version.slice(1)
						console.log(this.version,'this.versionthis.versionthis.version');
					}
				})
			},
			// 点击进行设备录入
			btnluru(){
				this.datalist = ''
				this.mac = ''
				this.ver_data = {}
				uni.reLaunch({
					url:'/pages/myorder/index'
				})
			},
			// 点击选择时间
			btnshowjs() {
				this.showjs = true
			}, 
            // 补零函数
			formattedTime(minutes, seconds) {
				// 将数字转换为字符串并补零  
				const formattedMinutes = String(minutes).padStart(2, '0')
				const formattedSeconds = String(seconds).padStart(2, '0')
				// 返回格式化后的时间字符串  
				console.log(`${formattedMinutes}:${formattedSeconds}`,'111111111')
				return `${formattedMinutes}:${formattedSeconds}`
			},
			// 静默登录
			jmlogin() {
				let taht = this
				wx.login({
					success(res) {
						if (res.code) {
							let data = {
								loginCode: res.code,
							}
							taht.$u.post(`/wxLogin`, data).then(res => {
								if (res.code == 200) {
									taht.getinfo()
									uni.setStorageSync('token', res.token)
								}else if(res.code == 10001){
									that.bjflag = true
									uni.showModal({
									    title: taht.$t('common.tip'),  
									    content: taht.$t('common.promptLogin'),  
									    success: function (res) {  
									        if (res.confirm) { 
											   uni.reLaunch({
											   	 url:'/pages/login/login'
											   })
									        } else if (res.cancel) {  
									           
									        }  
									    }  
									})
								}
							})
						}
					}
				})
			},
			// 获取用户信息
			getinfo() {
				this.isLoading = true // 开始加载
				this.$u.get(`/system/user/profile`).then((res) => {
					if (res.code == 200) {
						this.userobj = res.data
						uni.setStorageSync('user',res.data)
						uni.setStorageSync('userId',res.data.userId)
						// 根据用户id获取当前用户
						this.getlist()
					}else if(res.code == 401){
						this.isLoading = false // 请求失败时隐藏加载状态
						this.bjflag = true
						this.jmlogin()
					}
				}).catch(() => {
					this.isLoading = false // 请求异常时隐藏加载状态
				})
			},
			// 获取设备列表
			getlist(){
				this.$u.get(`/app/device/list?userId=${this.userobj.userId}&classifyCodeList=1`).then((res) => {
					if (res.code == 200) {
						if(res.data.length > 0 || res.data != ''){
							this.bjflag = false
							this.devicelist = res.data
							this.imgpic = res.data[0].modelPicture
							this.mac = res.data[0].mac
							this.pre = res.data[0].pre
							console.log(this.pre,'454545454545454');
							this.user = res.data[0]
							this.shebid = res.data[0].deviceId			
							this.getbanbens()
							this.getscjsjl()
							setTimeout(()=>{
								this.getsj()
							},1000)
						}else{
							this.bjflag = true
						}
						this.isLoading = false // 请求完成后隐藏加载状态
					}else{
						this.isLoading = false
					}
				}).catch(() => {
					this.isLoading = false // 请求异常时隐藏加载状态
				})
			},
			// 点击连接蓝牙函数
			btnlj() {
				// 如果正在连接中，不重复连接
				if (this.vardataflag === 2) {
					return
				}
				// 如果已连接，提示用户
				if (this.vardataflag === 3) {
					uni.showToast({
						title: this.$t('index.deviceConnected'),
						icon: 'none',
						duration: 2000
					})
					return
				}
				
				// 重置错误状态（允许重新检查错误）
				this.errorModalShown = false
				this.currentErrorType = null
				this.shibainum = 0
				this.connectionStartTime = Date.now() // 记录连接开始时间
				this.connectionTimeout = null // 连接超时定时器
				
				// 先检查蓝牙状态并尝试自动修复
				this.checkAndFixBluetooth().then(() => {
					// 蓝牙正常，开始连接流程
					xBlufi.initXBlufi(1)
					xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
					xBlufi.notifyStartDiscoverBle({
						'isStart': true
					})
					this.vardataflag = 2
					
					// 设置连接超时（30秒）
					this.connectionTimeout = setTimeout(() => {
						if (this.vardataflag === 2) {
							this.handleConnectionTimeout()
						}
					}, 30000)
					
					this.findDevice()
				}).catch((error) => {
					// 蓝牙检查失败，显示错误提示（只显示一次）
					if (!this.errorModalShown) {
						this.handleConnectionError(error)
					}
				})
			},
			// ios递归函数匹配
			findDevice() {
			    let that = this;
			    const findDevices = () => {
					console.log(that.shibainum,'失败次数');
			        // 如果已经尝试了10次及以上，直接返回不执行
			        if (that.shibainum > 10) {
						that.vardataflag = 1
						that.clearConnectionTimeout()
						xBlufi.notifyStartDiscoverBle({
						    'isStart': false
						});
						// 诊断连接失败原因
						that.diagnoseConnectionFailure();
			            return;
			        }
			        that.vatatxt = that.$t('index.searching');
			        const matchedDevice = that.devicesarr.find(device => {
			            if (device.name) {
			                return device.name.slice(-12) === that.mac.slice(-12);
			            }
			        });
			        if (matchedDevice) {
			            // 找到设备的处理逻辑...
			            that.vatatxt = that.$t('index.pairing');
			            that.clearConnectionTimeout() // 清除超时定时器
			            xBlufi.notifyStartDiscoverBle({
			                'isStart': false
			            });
			            console.log(matchedDevice, '找到匹配设备');
			            xBlufi.notifyConnectBle({
			                isStart: true,
			                deviceId: matchedDevice.deviceId,
			                name: matchedDevice.name
			            });
			            that.deviceId = matchedDevice.deviceId;
			            // 设置连接超时（8秒）
			            that.connectTimeout = setTimeout(() => {
			                if (that.vardataflag !== 3 && !that.errorModalShown) {
			                    that.vardataflag = 1
			                    that.shibainum = 0;
			                    that.handleConnectionError({
			                        type: 'CONNECT_TIMEOUT',
			                        message: that.$t('index.ble.pairTimeout'),
			                        userAction: that.$t('index.ble.pairTimeoutHint'),
			                        canAutoFix: false
			                    })
			                }
			            }, 8000);
			        } else {
			            // 未找到设备，递增计数器并继续尝试
			            that.shibainum++;
			            // 只有在还没到10次时才设置定时器继续查找
			            if (that.shibainum < 10) {
			                that.findDeviceTimer = setTimeout(findDevices, 1000);
			            } else {
							that.vardataflag = 1
							that.clearConnectionTimeout()
			                that.shibainum = 0;
							// 诊断连接失败原因
							that.diagnoseConnectionFailure();
			            }
			        }
			    };
			    // 重置计数器后开始查找
			    findDevices();
			},
			// 获取附近蓝牙设备列表
			funListenDeviceMsgEvent: function(options) {
				switch (options.type) {
					case xBlufi.XBLUFI_TYPE.TYPE_STATUS_CONNECTED:
						if (!options.result) {
							this.vardataflag = 1
							this.clearDisconnectTimer()
							this.clearConnectionTimeout()
							console.log('设备连接断开', options);
							// 如果是在连接过程中断开，且还没显示过错误，才显示提示
							if (this.connectionStartTime && (Date.now() - this.connectionStartTime) < 5000 && !this.errorModalShown) {
								this.handleConnectionError({
									type: 'CONNECTION_DISCONNECTED',
									message: this.$t('index.ble.disconnected'),
									userAction: this.$t('index.ble.disconnectedHint'),
									canAutoFix: false
								})
							}
						}
						break;
					case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS:
						if (options.result) {
							this.devicesarr = options.data
							// console.log('搜索的附近设备列表',this.devicesarr);
						}
						break;
					case xBlufi.XBLUFI_TYPE.TYPE_CONNECTED:
						console.log("连接回调：" + JSON.stringify(options))
						this.clearConnectionTimeout() // 清除连接超时定时器
						xBlufi.notifyInitBleEsp32({
							deviceId: this.deviceId
						})
						if (options.result == true){
							console.log('服务发现成功:', options);
							// 一连上立刻请求数据推送
							this.vardataflag = 3
							this.initDisconnectTimer()
							this.datalist = ''
							// this.startDataTimeoutTimer()
							xBlufi.notifySendCustomData({
								customData: "11get"
							})
							// 连接成功提示
							uni.showToast({
								title: this.$t('index.connectOk'),
								icon: 'success',
								duration: 2000
							})
						}else{
							// 服务发现失败
							this.vardataflag = 1
							this.clearDisconnectTimer() 
							this.clearConnectionTimeout()
							this.jiance = true
							
							// 如果还没显示过错误，才显示
							if (!this.errorModalShown) {
								this.handleConnectionError({
									type: 'SERVICE_DISCOVERY_FAILED',
									message: this.$t('index.ble.serviceFail'),
									userAction: this.$t('index.ble.serviceFailHint'),
									canAutoFix: false
								})
							}
						}
						break
					case xBlufi.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT:
			
						break
					case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA:
						console.log("收到设备数据：", options.data)
						if(this.pre == 'SATER'){
							// SATER 设备分 3 种类型不定序推送：pA(pA1:...)、pB(pB1:...)、ver(ver...@show:...)
							// 按类型存最新值，集齐后解析并展示
							let chunk = String(options.data || '')
							if (chunk) {
								chunk = chunk.slice(0, -1)
							}
							if (!chunk) return
							if (!chunk.endsWith(';')) {
								chunk += ';'
							}
							// 识别类型并更新该类型的最新数据
							if (chunk.includes('pA1:')) {
								this.saterDataByType.pA = chunk
							} else if (chunk.includes('pB1:')) {
								this.saterDataByType.pB = chunk
							} else if (chunk.startsWith('ver')) {
								this.saterDataByType.ver = chunk
							} else {
								return
							}
							const { pA, pB, ver } = this.saterDataByType
							if (!pA || !pB || !ver) {
								return
							}
							this.saterRawPayload = [ver, pA, pB].join('')
							this.datalist = this.saterRawPayload
							this.clearDataTimeoutTimer()
							this.vardataflag = 3
							this.grisfjx()
							return
						}
						this.saterDataByType = { pA: '', pB: '', ver: '' }
						this.saterRawPayload = ''
						if (options.data.indexOf("prom:") !== -1) {
							// console.log('固件升级中')
							var indexOld = options.data.substring(options.data.indexOf('prom:'))
							// console.log("indexOld", indexOld);
							var load_num = indexOld.substring(
								indexOld.indexOf("prom:") + 5,
								indexOld.indexOf("@")
							)
							this.progress = Number(load_num);
							// console.log("load_num", load_num);
							console.log("升级进度：", this.progress)
							if (this.progress === 6000) {
								// console.log('固件成功')
								this.progress = 100
								uni.showToast({
									title: this.$t('index.fwOk'),
									icon: 'success',
									duration: 2000
								})
								setTimeout(()=>{
									this.shengjiflag = false
									uni.reLaunch({
										url:'/pages/index/index'
									})
								},2000)
							}
							if (this.progress === 9000) {
								// console.log('固件升级失败')
								this.progress = 99
								uni.showToast({
									title: this.$t('index.fwFail'),
									icon: 'none',
									duration: 2000
								})
								setTimeout(()=>{
									this.shengjiflag = false
									uni.reLaunch({
										url:'/pages/index/index'
									})
								},1000)
							}
						} else {
							this.datalist = options.data.slice(0, -1) + ";"
							this.clearDataTimeoutTimer()
							this.vardataflag = 3
							if(this.pre == 'WATER' || this.pre == 'DATER' || this.pre == 'TATER'){
								this.getchuli()
							}else if(this.pre == 'SATER'){
								this.grisfjx()
							}else{
								this.getcsbshuju()
							}
						}
						break
					case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START:
						if (!options.result) {
							this.vardataflag = 1
							this.jiance = true
							this.clearConnectionTimeout()
							console.log('蓝牙搜索启动失败', options)
							// 如果还没显示过错误，才显示
							if (!this.errorModalShown) {
								this.handleConnectionError({
									type: 'SEARCH_START_FAILED',
									message: this.$t('index.ble.searchStartFail'),
									userAction: this.$t('index.ble.searchStartFailHint'),
									canAutoFix: false
								})
							}
							return
						}
						break
				}
			},
			
			
			// 雨水感应开启
			btnyushui() {
				this.handleUserAction()
				if (this.isRainSensorLocked) {
					this.one = true
					this.ones = false
					uni.showToast({
						title: this.$t('index.rainWait'),
						icon: 'none',
						duration: 2000
					})
					return
				}
				this.one = false
				this.ones = true
				if(this.vardataflag != 3){
					uni.showLoading({
						title: this.$t('index.opening')
					})

					this.$u.post(`/app/device/yudi/${this.shebid}`).then(res => {
						if (res.code == 200) {
							uni.hideLoading()
							this.yschecked = false
							uni.showToast({
								title: this.$t('index.openOk'),
								icon: 'success',
								duration:2000
							})
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					}).catch(error => {
                            uni.hideLoading() // 务必隐藏加载提示，避免一直显示
                            const errorMsg = error.message || '';
                            const isNetworkError = errorMsg.includes('Network Error') || 
                                                  errorMsg.includes('网络') || 
                                                  errorMsg.includes('超时') || 
                                                  errorMsg.includes('fail') || // 小程序请求失败的核心关键词
                                                  errorMsg.includes('request:fail');
                            uni.showToast({
                              title: isNetworkError ? this.$t('common.networkErrorAlt') : this.$t('common.requestFail'),
                              icon: 'none',
                              duration: 5000
                            })
                            // 可选：打印错误日志，方便调试
                            console.error('请求异常：', error)
                          })
				}else{
					this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=yudi`).then(res =>{
						if(res.code == 200){
							uni.showLoading({
								title: this.$t('index.opening')
							})
							this.yschecked = false
							xBlufi.notifySendCustomData({
								customData: '11' + res.data
							})
							uni.hideLoading()
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}
			},
			// 点击同步时间
			btntb(){
				this.handleUserAction()
				if(this.vardataflag != 3){
					uni.showLoading({
						title: this.$t('index.setting')
					})
					this.devicetime = this.getCurrentTime();
					console.log(this.devicetime);
					let data = {
						deviceId:this.shebid,
						time:this.devicetime,
					}
					this.$u.post(`/app/device/syncTime`,data).then(res => {
						if (res.code == 200) {
							uni.hideLoading()
							uni.showToast({
								title: this.$t('index.syncOk'),
								icon: 'success',
								duration:2000
							})
						}else{
							uni.hideLoading()
							this.devicetime = '--'
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}else{
					this.devicetime = this.getCurrentTime();
					console.log(this.devicetime);
					xBlufi.notifySendCustomData({
						customData: '11date' + this.devicetime + ':' + '00' + ';'
					})
					// if(this.pre == 'WATER'){ //单阀
					// this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=syncTime`).then(res =>{
					// 	if(res.code == 200){
					// 		uni.showLoading({
					// 			title: this.$t('index.setting')
					// 		})
					// 		xBlufi.notifySendCustomData({
					// 			customData: '11' + this.format(res.data, {date: this.devicetime + ':' + '00' + ';'})
					// 		})
					// 		uni.hideLoading()
					// 	}else{
					// 		uni.hideLoading()
					// 		uni.showToast({
					// 			title: res.msg,
					// 			icon: 'none',
					// 			duration:2000
					// 		})
					// 	}
					// })
				} 
			},
			// 点击显示设置时间
			btnsztime(){
				this.handleUserAction()
				this.timeflag = true
			},
			getCurrentTime() {
			  const now = new Date();
			  const padZero = num => num.toString().padStart(2, '0');
			  const hours = padZero(now.getHours());   // 时 (00-23)
			  const minutes = padZero(now.getMinutes()); // 分 (00-59)
			  const seconds = padZero(now.getSeconds()); // 秒 (00-59)
			  return `${hours}:${minutes}`;
			},
			// 点击设置当前时间
			confirmtime(e){
				this.devicetime = e.hour + ':' + e.minute
				console.log(this.devicetime);
				if(this.vardataflag == 3){
					xBlufi.notifySendCustomData({
						customData: '11date' + this.devicetime + ':' + '00' + ';'
					})
					// this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=syncTime`).then(res =>{
					// 	if(res.code == 200){
					// 		uni.showLoading({
					// 			title: this.$t('index.setting')
					// 		})
					// 		xBlufi.notifySendCustomData({
					// 			customData: '11' + this.format(res.data, {date: this.devicetime + ':' + '00' + ';'})
					// 		})
					// 		uni.hideLoading()
					// 	}else{
					// 		uni.hideLoading()
					// 		uni.showToast({
					// 			title: res.msg,
					// 			icon: 'none',
					// 			duration:2000
					// 		})
					// 	}
					// })
				}else{
					uni.showLoading({
						title: this.$t('index.setting')
					})
					this.devicetime = e.hour + ':' + e.minute

					let data = {
						deviceId:this.shebid,
						time:this.devicetime,
	
					}
					this.$u.post(`/app/device/syncTime`,data).then(res => {
						if (res.code == 200) {
							uni.hideLoading()
							uni.showToast({
								title: this.$t('index.setOk'),
								icon: 'success',
								duration:2000
							})
						}else{
							this.devicetime = '--'
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}
			},
			// 雨水感应关闭
			btnyushuis() {
				this.handleUserAction()
				if (this.isRainSensorLocked) {
					this.one = false
					this.ones = false
					uni.showToast({
						title: this.$t('index.rainWait'),
						icon: 'none',
						duration: 2000
					})
					return
				}
				this.one = false
				this.ones = true
				if(this.vardataflag != 3){
					uni.showLoading({
						title: this.$t('index.closing')
					})
					let data = {
						deviceId:this.shebid,
						instructionKey:'unyudi',
					}
					this.$u.post(`/app/device/unyudi/${this.shebid}`).then(res => {
						if (res.code == 200) {
							uni.hideLoading()
							this.yschecked = true
							uni.showToast({
								title: this.$t('index.closeOk'),
								icon: 'success',
								duration:2000
							})
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}else{
					this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=unyudi`).then(res =>{
						if(res.code == 200){
							uni.showLoading({
								title: this.$t('index.closing')
							})
							this.yschecked = true
							xBlufi.notifySendCustomData({
								customData: '11' + res.data
							})
							uni.hideLoading()
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}
			},
			// 点击儿童锁开启
			btnertong() {
				this.handleUserAction()
				this.two = false
				this.twos = true
				if(this.vardataflag != 3){
					uni.showLoading({
						title: this.$t('index.opening')
					})
					// let data = {
					// 	deviceId:this.shebid,
					// 	instructionKey:'lock',
					// }
					this.$u.post(`/app/device/lock/${this.shebid}`).then(res => {
						if (res.code == 200) {
							uni.hideLoading()
							this.etchecked = false
							uni.showToast({
								title: this.$t('index.openOk'),
								icon: 'success',
								duration:2000
							})
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}else{
					this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=lock`).then(res =>{
						if(res.code == 200){
							uni.showLoading({
								title: this.$t('index.opening')
							})
							this.etchecked = false
							xBlufi.notifySendCustomData({
								customData: '11' + res.data
							})
							uni.hideLoading()
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}
			},
			// 点击儿童锁关闭
			btnertongs() {
				this.handleUserAction()
				this.two = false
				this.twos = true
				if(this.vardataflag != 3){
					uni.showLoading({
						title: this.$t('index.closing')
					})
					// let data = {
					// 	deviceId:this.shebid,
					// 	instructionKey:'unlock',
					// }
					this.$u.post(`/app/device/unlock/${this.shebid}`).then(res => {
						if (res.code == 200) {
							uni.hideLoading()
							this.etchecked = true
							uni.showToast({
								title: this.$t('index.closeOk'),
								icon: 'success',
								duration:2000
							})
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
			    }else{
					this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=unlock`).then(res =>{
						if(res.code == 200){
							uni.showLoading({
								title: this.$t('index.closing')
							})
							this.etchecked = true
							xBlufi.notifySendCustomData({
								customData: '11' + res.data
							})
							uni.hideLoading()
						}else{
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					})
				}
			},

			// 点击添加设备 
			btnaddsb() {
				this.$u.get(`/system/user/profile`).then((res) => {
					if (res.code == 200) {
						uni.setStorageSync('user',res.data)
						uni.setStorageSync('userId',res.data.userId)
						this.vardataflag = 1
						this.ver_data = {}
						this.datalist = ''
						uni.navigateTo({
							url: '/page_user/lanya'
						})
					}else if(res.code == 401){
						// this.jmlogin()
						uni.showModal({
						    title: this.$t('common.tip'),  
						    content: this.$t('common.promptLogin'),  
						    success: function (res) {  
						        if (res.confirm) { 
								   uni.navigateTo({
								   	url:'/pages/login/login'
								   })
						        } else if (res.cancel) {  
						           
						        }  
						    }  
						})
					}
				})
			},

			// 点击选择浇水时间
			confirm(e) {
				this.handleUserAction()
				this.minute = e.minute
				this.second = e.second
				this.jstime = Number(e.second) + Number(e.minute * 60)
			},

			// 点击跳转到定时页面
			btntime() {
				this.handleUserAction()
				if(this.vardataflag != 3){
					let url = '/page_user/dingshi?pre=' + this.pre + '&shebid=' + this.shebid
					if (this.pre === 'SATER') {
						url += '&channel=' + this.stareChannel
					}
					uni.navigateTo({ url })
				}else{
					if (this.pre === 'SATER') {
						const saterRaw = this.saterRawPayload || this.datalist || ''
						const list = encodeURIComponent(JSON.stringify(this.ver_data || {}))
						const raw = encodeURIComponent(saterRaw)
						uni.navigateTo({
							url: '/page_user/dingshi?list=' + list + '&raw=' + raw + '&pre=' + this.pre + '&channel=' + this.stareChannel
						})
						return
					}
					uni.navigateTo({
						url: '/page_user/dingshi?list=' + JSON.stringify(this.ver_data) + '&pre=' + this.pre
					})
				}
			},
			setStareChannel(ch) {
				this.stareChannel = ch === 'B' ? 'B' : 'A'
				if (this.pre === 'SATER') {
					if (this.saterRawPayload) {
						this.grisfjx()
					} else if (this.vardataflag != 3 && (Object.keys(this.saterListA || {}).length || Object.keys(this.saterListB || {}).length)) {
						const target = this.stareChannel === 'B' ? this.saterListB : this.saterListA
						this.ver_data = this.normalizeVerDataSwitch(target) || {}
						this.calculateNextWateringTime()
					}
				}
			},
			
			// 点击取消手动浇水
			btnqx() {
				this.handleUserAction()
				this.sdjsflag = false
				this.sdminutes = ''
				this.sdseconds = ''
				this.kgflag = true
				this.jsked = true
				this.jskeds = false
				this.rainSensorLockedByWatering = false
			},
			// 替换
			format(template, params) {
			  return template.replace(/\{(\w+)\}/g, (_, k) => params[k] ?? '');
			},
			// 手动浇水记录
			getjl(){
				let that = this
				let data = {
					deviceId:that.shebid,
					sprayingTime:that.jstime
				}
				that.$u.post(`/app/wateringRecord`,data).then(res =>{})
			},
			// 请求上次浇水记录
			getscjsjl(){
				this.$u.get(`/app/wateringRecord/last/${this.shebid}`).then(res =>{
					if(res.code == 200){
						if(res.data){
							this.jsobj = res.data
						}else{
							this.jsobj = {}
						}
					}
				})
			},
			// 确定选择时间
			btnqd() {
				this.handleUserAction()
				if (this.isManualWaterRequesting) {
					uni.showToast({
						title: this.$t('index.waitReq'),
						icon: 'none',
						duration: 2000
					})
					return
				}
				if (this.minute == '--' || this.second == '--') {
					uni.showToast({
						title: this.$t('index.pickWaterDur'),
						icon: 'none',
						duration: 3000
					})
					return
				}
				// 点击确定那一刻立即锁死雨水感应，不等请求返回
				this.rainSensorLockedByWatering = true
				this.isManualWaterRequesting = true
				
				if(this.vardataflag == 3){
					this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=time`).then(res =>{
						if(res.code == 200){
							uni.showLoading({
								title: this.$t('index.opening')
							})
							let cmd = this.format(res.data, {time: this.jstime})
							// SATER：命令后追加 A/B，例如 timeA10
							if (this.pre === 'SATER') {
								cmd = String(cmd).replace(/^time/, 'time' + this.stareChannel)
							}
							xBlufi.notifySendCustomData({
								customData: '11' + cmd + '@'
							})
							this.getjl()
							uni.hideLoading()
							this.startTimer(this.jstime)
							this.sdjsflag = false
						}else{
							this.rainSensorLockedByWatering = false
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					}).catch(() => {
						this.rainSensorLockedByWatering = false
						uni.hideLoading()
						uni.showToast({
							title: this.$t('common.networkError'),
							icon: 'none',
							duration: 2000
						})
					}).finally(() => {
						this.isManualWaterRequesting = false
					})
				}else{

					let data = {
						deviceId:this.shebid,
						second:this.jstime,
					
					}
					this.$u.post(`/app/device/time`,data).then(res => {
						if (res.code == 200) {
							uni.showToast({
								title: this.$t('index.openOk'),
								icon: 'success',
								duration:2000
							})
							this.getjl()
							uni.hideLoading()
							this.startTimer(this.jstime)
							this.sdjsflag = false
						}else{
							this.rainSensorLockedByWatering = false
							this.kgflag = true
							this.jsked = false
							this.jskeds = false
							uni.hideLoading()
							this.sdjsflag = false
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					}).catch(() => {
						this.rainSensorLockedByWatering = false
						uni.hideLoading()
						uni.showToast({
							title: this.$t('common.networkError'),
							icon: 'none',
							duration: 2000
						})
					}).finally(() => {
						this.isManualWaterRequesting = false
					})
				}
			},

			// 手动浇水定时器
			startTimer(totalSeconds) {  
			    let remainingSeconds = totalSeconds
			    const sdminutes = ''
			    const sdseconds = ''
			    this.timer = setInterval(() => {  
			        // 计算分钟和秒  
			        const minutes = Math.floor(remainingSeconds / 60).toString()
			        const secs = (remainingSeconds % 60).toString()
			        // 格式化秒和分钟，确保是两位数  
			        this.sdseconds = secs.padStart(2, '0')
			        this.sdminutes = (minutes > 0 ? minutes : '').padStart(2, '0') // 如果分钟为0，则不显示分钟  
			        // 更新剩余秒数  
			        remainingSeconds--
			        // 如果剩余秒数为0，则停止定时器  
			        if (remainingSeconds <= 0) {  
			            clearInterval(this.timer)
			            // 定时结束：清空计时、自动关闭浇水开关、解锁雨水感应
			            setTimeout(()=>{
							this.sdminutes = ''
							this.sdseconds = ''
							this.kgflag = true
							this.jsked = true
							this.jskeds = false
							this.rainSensorLockedByWatering = false
						},1000)
			        }  
			    }, 1000)
			},
			
			// 启动浇水倒计时定时器
			startWateringCountdownTimer(totalSeconds) {
				// 启动新倒计时前，先清理旧的 interval 和延迟清理 timeout，避免出现负数/串台
				this.clearWateringCountdownTimer()

			    let remainingSeconds = Math.max(0, Math.floor(Number(totalSeconds) || 0))
				if (remainingSeconds <= 0) {
					this.wateringCountdownMinutes = ''
					this.wateringCountdownSeconds = ''
					this.showWateringCountdown = false
					return
				}

				const updateDisplay = (secsLeft) => {
					const safe = Math.max(0, Math.floor(Number(secsLeft) || 0))
					const minutes = Math.floor(safe / 60).toString()
					const secs = (safe % 60).toString()
					this.wateringCountdownSeconds = secs.padStart(2, '0')
					this.wateringCountdownMinutes = (minutes > 0 ? minutes : '').padStart(2, '0')
				}

			    // 先设置初始值
			    updateDisplay(remainingSeconds)
			    
			    this.wateringCountdownTimer = setInterval(() => {
					// 先减少再渲染，避免“多显示1秒”，并确保永不小于0
			        remainingSeconds = Math.max(0, remainingSeconds - 1)
			        updateDisplay(remainingSeconds)

			        // 到0立刻停止，且用受控的 timeout 延迟清理展示（避免负数和旧 timeout 影响新倒计时）
			        if (remainingSeconds === 0) {
			            clearInterval(this.wateringCountdownTimer)
			            this.wateringCountdownTimer = null
			            this.wateringCountdownResetTimer = setTimeout(() => {
			                this.wateringCountdownMinutes = ''
			                this.wateringCountdownSeconds = ''
			                this.showWateringCountdown = false
			                this.rainSensorLockedByWatering = false
							this.wateringCountdownResetTimer = null
			            }, 1000)
			        }
			    }, 1000)
			},
			
			// 清除浇水倒计时定时器
			clearWateringCountdownTimer() {
				if (this.wateringCountdownResetTimer) {
					clearTimeout(this.wateringCountdownResetTimer)
					this.wateringCountdownResetTimer = null
				}
			    if (this.wateringCountdownTimer) {
			        clearInterval(this.wateringCountdownTimer)
			        this.wateringCountdownTimer = null
			    }
			},
			
			// 计算信号强度格数（根据RSSI值）
			calculateSignalStrength(rssi) {
				if (rssi === undefined || rssi === null) {
					return 0
				}
				// 转换为数字
				const rssiValue = Number(rssi)
				// 0 到 -50：4格（最强）
				if (rssiValue >= -50) {
					return 4
				}
				// -50 到 -70：3格
				if (rssiValue >= -70) {
					return 3
				}
				// -70 到 -90：2格
				if (rssiValue >= -90) {
					return 2
				}
				// -90 以下：1格
				return 1
			},
			
			// 关闭手动浇水
			btnkq() {
				this.handleUserAction()
				// 防频繁点击（包含“确定”请求进行中、开关请求进行中）
				// if (this.isManualWaterRequesting || this.isManualWaterSwitchRequesting) {
				// 	// 回滚开关状态（当前是“关闭”动作，阻止时保持开启）
				// 	this.jsked = true
				// 	uni.showToast({
				// 		title: this.$t('index.noTap'),
				// 		icon: 'none',
				// 		duration: 2000
				// 	})
				// 	return
				// }
				console.log('关闭')
				// 蓝牙模式：每次点击后至少冷却3秒
				if (this.vardataflag == 3) {
					const now = Date.now()
					if (now < this.manualWaterBtCooldownUntil) {
						this.jsked = true
						uni.showToast({
							title: this.$t('index.noTap'),
							icon: 'none',
							duration: 2000
						})
						return
					}
					this.manualWaterBtCooldownUntil = now + 3000
					this.isManualWaterSwitchRequesting = true
					const unlockAt = this.manualWaterBtCooldownUntil

					this.$u.get(`/app/getModelCommand/${this.modelId}?instructionKey=close`).then(res =>{
						if(res.code == 200){
							uni.showLoading({
								title: this.$t('index.closing')
							})
							xBlufi.notifySendCustomData({
								customData: "11" + res.data
							})
							clearInterval(this.timer)
							this.sdminutes = ''
							this.sdseconds = ''
							this.kgflag = true
							this.jsked = true
							this.jskeds = false
							this.rainSensorLockedByWatering = false
							uni.hideLoading()
						}else{
							// 回滚开关（关闭失败则保持开启）
							this.jsked = true
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					}).catch(() => {
						// 回滚开关（关闭失败则保持开启）
						this.jsked = true
						uni.hideLoading()
						uni.showToast({
							title: this.$t('common.networkError'),
							icon: 'none',
							duration: 2000
						})
					}).finally(() => {
						const delay = Math.max(0, unlockAt - Date.now())
						setTimeout(() => {
							this.isManualWaterSwitchRequesting = false
						}, delay)
					})
					return
				}

				// 接口模式：等待请求结束后才能再次点击
				this.isManualWaterSwitchRequesting = true
				if(this.vardataflag != 3){
					uni.showLoading({
						title: this.$t('index.closing')
					})
					// let data = {
					// 	deviceId:this.shebid,
					// 	instructionKey:'close',
					// }
					this.$u.post(`/app/device/close/${this.shebid}`).then(res => {
						if (res.code == 200) {
							uni.showToast({
								title: this.$t('index.closeOk'),
								icon: 'success',
								duration:2000
							})
							clearInterval(this.timer)
							uni.hideLoading()
							this.sdminutes = ''
							this.sdseconds = ''
							this.kgflag = true
							this.jsked = true
							this.jskeds = false
							this.rainSensorLockedByWatering = false
						}else{
							// 回滚开关（关闭失败则保持开启）
							this.jsked = true
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none',
								duration:2000
							})
						}
					}).catch(() => {
						// 回滚开关（关闭失败则保持开启）
						this.jsked = true
						uni.hideLoading()
						uni.showToast({
							title: this.$t('common.networkError'),
							icon: 'none',
							duration: 2000
						})
					}).finally(() => {
						this.isManualWaterSwitchRequesting = false
					})
				}
			},
			// 开启手动浇水
			btngb() {
				this.handleUserAction()
				// 防频繁点击（包含“确定”请求进行中、开关请求进行中）
				if (this.isManualWaterRequesting || this.isManualWaterSwitchRequesting) {
					// 回滚开关状态（当前是“开启”动作，阻止时保持关闭）
					this.jskeds = false
					uni.showToast({
						title: this.$t('index.noTap'),
						icon: 'none',
						duration: 2000
					})
					return
				}
				// 蓝牙模式：每次点击后至少冷却3秒
				if (this.vardataflag == 3) {
					const now = Date.now()
					if (now < this.manualWaterBtCooldownUntil) {
						this.jskeds = false
						uni.showToast({
							title: this.$t('index.noTap'),
							icon: 'none',
							duration: 2000
						})
						return
					}
					this.manualWaterBtCooldownUntil = now + 3000
					this.isManualWaterSwitchRequesting = true
					const unlockAt = this.manualWaterBtCooldownUntil
					setTimeout(() => {
						// 到时间自动解锁
						if (Date.now() >= unlockAt) this.isManualWaterSwitchRequesting = false
					}, 3000)
				}
				console.log('开启')
				this.sdjsflag = true
				this.kgflag = false
			},

			// 跳转到设置
			btnsz() {
				xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent)
				if(this.csbobj.day){
					this.xctime = '111'
				}
				uni.navigateTo({
					url: '/page_user/upload?deviceid=' + this.shebid + '&ver=' + this.ver + '&xctime=' + this.xctime + '&xipin=' + this.xinp + '&img=' + this.imgpic + '&varflag=' + this.vardataflag
				})
			},
			// 选择设备
			btnactive(deviceId,index) {
				// wx.closeBLEConnection({
				// 	deviceId: this.mac,
				// })
				// xBlufi.notifyConnectBle({
				//     isStart: false,
				//     deviceId: this.deviceId,
				//     name: this.name
				// })
				this.isLoading = true
				this.shebid = deviceId
				this.zaixianobj = {}
				this.ver = ''
				this.jsobj = {}
                this.btnxuanze()
			},
			// 选择确定设备  shebid
			btnxuanze() {
				this.$u.put(`/app/toggleDevice?userId=${this.userobj.userId}&deviceId=${this.shebid}`).then(res => {
					if(res.code == 200){
						
						this.csbobj = {}
						this.datalist = ''
						this.mac = ''
						this.ver_data = {}
						this.name = ''
						this.deviceId = ''
						this.xuanzeflag = false
						this.vardataflag = 1
						this.sdseconds = ''
						this.sdminutes = ''
						this.kgflag = true
						this.jsked = true
						this.jskeds = false
						this.getshebxq()
					}else{
						this.isLoading = false
						uni.showToast({
							title: res.msg,
							icon: 'none',
							duration: 2000
						})
					}
				})
			},
			// 刷新按钮点击（避免编译成 e0 等匿名方法导致小程序报错）
			onRefreshClick() {
				if (this.isRefreshing) return
				this.qiehuan = 1
				this.getshebxq()
			},
			// 获取设备信息
			getshebxq(){
				if (this.isRefreshing) return
				this.isRefreshing = true
				const done = () => {
					setTimeout(() => {
						this.isLoading = false
						this.isRefreshing = false
						if(this.qiehuan == 1){
							uni.showToast({
								title: this.$t('index.refreshOk'),
								icon: 'success',
								duration:5000
							})
						}else{
							uni.showToast({
								title: this.$t('index.switchOk'),
								icon: 'success',
								duration: 5000
							})
							this.fullPageRefresh()
						}
						this.qiehuan = ''
					}, 500)
				}
				this.$u.get(`/app/device/getDetail?deviceId=${this.shebid}`).then(res => {
					if (res.code == 200) {
						this.zaixianobj = res.data.iotData
						this.modelId = res.data.modelId
						console.log(this.vardataflag,this.zaixianobj);
						// 非蓝牙模式时，用后台数据组装渲染结构
						if((this.pre === 'WATER' || this.pre === 'SATER') && this.vardataflag != 3 || this.pre === 'TATER' && this.vardataflag != 3 || this.pre === 'DATER' && this.vardataflag != 3){
							this.ver_data = this.buildVerDataFromBackend(this.zaixianobj)
							this.calculateNextWateringTime()
						}
						if(this.pre === 'SMSJ:' && this.vardataflag != 3){
							this.ver_data = this.buildVerDataFromBackend(this.zaixianobj)
							// this.ver_data = this.zaixianobj
							console.log(this.ver_data,'55555555555prprprprprprprpr');
						}
						if (res.data && res.data.iotData && res.data.iotData.xinp !== undefined) {
						  this.xinp = res.data.iotData.xinp.value == undefined ? '--' : res.data.iotData.xinp.value
						}
						if (res.data && res.data.iotData && res.data.iotData.yudi !== undefined) {
						  if (!this.isRainSensorLocked) {
						  	this.yschecked = res.data.iotData.yudi.value == 0 ? true : false
						  }
						}
						if (res.data && res.data.iotData && res.data.iotData.lock !== undefined) {
						  this.etchecked = res.data.iotData.lock.value == 0 ? true : false
						}
						// 优先从 nt.value 获取总秒数，如果没有则从 time.value 获取
						let ntValue = res?.data?.iotData?.nt?.value;
						if (ntValue !== undefined && ntValue !== null && ntValue !== '') {
							// 从总秒数转换为时间格式
							this.devicetime = this.secondsToTime(ntValue);
						} else {
							// 兼容旧数据，从 time.value 获取
							let originalValue = (res?.data?.iotData?.time?.value ?? "").toString().trim();
							// 去掉首尾可能多出来的英文双引号 "
							originalValue = originalValue.replace(/^"|"$/g, '');
							this.devicetime = originalValue || "--";
						}
						console.log('devicetime:', this.devicetime);
						// 获取信号强度
						if (res.data && res.data.iotData && res.data.iotData.RSSI !== undefined && res.data.iotData.RSSI.value !== undefined) {
							this.signalStrength = this.calculateSignalStrength(res.data.iotData.RSSI.value)
						} else {
							this.signalStrength = 0
						}
						// 取值
						this.onlineTime = res.data.onlineTime
						this.onlineStatus = res.data.onlineStatus
						if(res.data.iotData && res.data.iotData.bat !== undefined && res.data.iotData.bat.value !== undefined){
							this.dianya = res.data.iotData.bat.value
							this.getdianliang()
						}
					}
					done()
				}).catch(() => {
					this.isLoading = false
					done()
				})
			},
			
			// 点击切换设备
			btnksxz() {
				if (this.xuanzeflag == true) {
					this.xuanzeflag = false
				} else {
					this.xuanzeflag = true
				}
			},
			//跳转到浇水日志页
			btnjs() {
				uni.showToast({
					title: this.$t('index.featureSoon'),
					icon: 'none',
					duration:2000
				})
				// uni.navigateTo({
				// 	url: '/page_user/jiaoshui'
				// })
			},
			// 每隔一时间发送一次获取数据
			getshuju() {
				const that = this
				that.intervalId = setInterval(() => {
					if (that.vardataflag == 3) {
						that.datalist = ''
						xBlufi.notifySendCustomData({
							customData: "11get"
						})
					}
				}, 5000) 
			},
			// 清除定时器
		     clearTimer() {
		         if (this.intervalId) {
		             clearInterval(this.intervalId);
		             this.intervalId = null; // 重置定时器 ID
		             console.log("定时器已清除");
		         }
		     },
			// 无闪屏整页刷新：重置状态并重新拉数，替代 uni.reLaunch 避免白屏闪一下
			fullPageRefresh() {
				// 1. 清除所有定时器
				this.clearTimer()
				this.clearConnectionTimeout()
				this.clearDataTimeoutTimer()
				if (this.disconnectTimer) {
					clearTimeout(this.disconnectTimer)
					this.disconnectTimer = null
				}
				if (this.searchTimer) {
					clearTimeout(this.searchTimer)
					this.searchTimer = null
				}
				if (this.wateringCountdownTimer) {
					clearInterval(this.wateringCountdownTimer)
					this.wateringCountdownTimer = null
				}
				if (this.wateringCountdownResetTimer) {
					clearTimeout(this.wateringCountdownResetTimer)
					this.wateringCountdownResetTimer = null
				}
				if (this.timer) {
					clearInterval(this.timer)
					this.timer = null
				}
				// 2. 关闭可能打开的弹窗
				this.showErrorModal = false
				this.xuanzeflag = false
				// 3. 重置 data 到初始状态（不销毁页面，避免闪屏）
				const initial = this.$options.data ? this.$options.data.call(this) : {}
				Object.keys(initial).forEach(key => {
					this[key] = initial[key]
				})
				// 4. 重新初始化并拉取数据（相当于重新进入页面）
				xBlufi.initXBlufi(1)
				this.getinfo()
				this.getshuju()
			},
            // 处理抽水泵接收数据
			getcsbshuju() {
			    // 1. 获取原始数据
			    const inputString = this.datalist;
			    // 2. 先处理分号（替换为逗号）
			    const normalizedString = inputString.replace(/;/g, ',');
			    // 3. 分割版本信息和数据部分
			    const parts = normalizedString.split(':');
			    console.log('分割结果:', parts); // 应该输出 ["ver3@p_set0", "11,5,603,99,19,9,0,"]
			    // 4. 处理数据部分（移除末尾可能的多余逗号）
			    let dataPart = parts[1];
			    if (dataPart.endsWith(',')) {
			        dataPart = dataPart.slice(0, -1);
			    }
			    // 5. 重新组合为期望的格式
			    const result = [parts[0], dataPart];
			    console.log('最终结果:', result); // ["ver3@p_set0", "11,5,603,99,19,9,0"]
				const versionNumber = result[0].match(/ver(\d+)/)?.[1];
				const ver = versionNumber ? parseInt(versionNumber) : 0;
				this.ver = 'ver' + ver
				
				console.log(this.ver,'ververver');
			    // 6. 继续您原来的处理逻辑
			    const timeParts = dataPart.split(',');
				console.log(timeParts,'timePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimePartstimeParts');
			    this.dianya = timeParts[timeParts.length - 1]
				this.getdianliang()
			    this.csbobj = {
			        hour: String(timeParts[0]).padStart(2, '0'),
			        minute: String(timeParts[1]).padStart(2, '0'),
			        second: timeParts[2],
			        day: timeParts[3]
			    };
			    console.log(this.csbobj,'4564654654584654564654654654654654621654652165');
			    const hours = parseInt(timeParts[4]) || 0;
			    const minutes = parseInt(timeParts[5]) || 0;
			    this.devicetime = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
		        this.ver_data = {...this.csbobj};
			    // 生成当前时间字符串 yyyy-MM-dd HH:mm:ss
			    const now = new Date();
			    const yyyy = now.getFullYear();
			    const MM = String(now.getMonth() + 1).padStart(2, '0');
			    const dd = String(now.getDate()).padStart(2, '0');
			    const HH = String(now.getHours()).padStart(2, '0');
			    const mm = String(now.getMinutes()).padStart(2, '0');
			    const ss = String(now.getSeconds()).padStart(2, '0');
			    const at = `${yyyy}-${MM}-${dd} ${HH}:${mm}:${ss}`;
			    // 仅在已连接（vardataflag==3）且距离上次上传≥60秒时推送
			    console.log(this.ver_data);
			    if(this.vardataflag == 3){
			    	const nowTs = Date.now();
			    	if(!this.lastUploadTs || (nowTs - this.lastUploadTs) >= 2000){
			    		let data = {
			    			mac: this.mac,
			    			params: {
			    				h: {
			    					value: String(this.ver_data.hour),
			    					at
			    				},
			    				m: {
			    					value: String(this.ver_data.minute),
			    					at
			    				},
			    				t: {
			    					value: String(this.ver_data.second),
			    					at
			    				},
			    				d: {
			    					value: String(this.ver_data.day),
			    					at
			    				},
			    				time: {
			    					value: String(this.devicetime),
			    					at
			    				},
								nt:{
									value: String(this.timeToSeconds(this.devicetime)),
									at
								}
			    			}
			    		}
			    		data.params.xinp = { value: String(this.xinp), at }
			    		this.$u.put(`/app/updateDeviceParam`, data).then(res => {}) //上传数据
			    		this.lastUploadTs = nowTs;
			    	}
			    }
			    console.log('设备时间:', this.devicetime);
			},
			// 获取电量
			getdianliang(){
				const nowTs = Date.now();
				if(this.lastPowerTs && (nowTs - this.lastPowerTs) < 20000){
					return
				}
				this.$u.get(`/app/device/remainingPower/${this.shebid}?voltage=${this.dianya / 1000}`).then(res => {
					if (res.code == 200) {
						this.sydl = res.data
						this.lastPowerTs = nowTs
					}
				})
			},
			// 处理双阀的浇花器设备
			grisfjx(){
				const raw = String(this.saterRawPayload || this.datalist || '')
				if (!raw) return
				let source = raw.replace(/@/g, ';')
				if (!source.endsWith(';')) source += ';'
				const channel = this.stareChannel === 'B' ? 'B' : 'A'
				const channelMap = {}
				const pRegex = /p([AB])(\d+):([^;]+)/g
				let pMatch
				while ((pMatch = pRegex.exec(source)) !== null) {
					const ch = pMatch[1]
					const idx = Number(pMatch[2])
					const val = pMatch[3]
					if (ch === channel && idx >= 1 && idx <= 6) {
						channelMap[idx] = val
					}
				}
				const showMatch = source.match(/show:([^;]+)/)
				const showPair = showMatch ? `show:${showMatch[1]}` : ''
				const mergedPairs = []
				if (showPair) {
					mergedPairs.push(showPair)
				}
				for (let i = 1; i <= 6; i++) {
					const pickedValue = channelMap[i] || '0,0,0,0,0'
					mergedPairs.push(`p_set${i}:${pickedValue}`)
				}
				const rebuilt = `${mergedPairs.join(';')};`
				this.datalist = rebuilt
				// 复用已有解析流程（开关/倒计时/电量/上传等）
				this.getchuli()
			},
			
			// 处理从设备接收数据
			getchuli() {
			    const inputString = this.datalist;
			    // console.log('接收到的数据:', inputString);
		    // 检查是否有 @ 分隔符
		    const hasAtSymbol = inputString.includes('@')
		    let processedString
		    let currentDay = 0
		    if (hasAtSymbol) {
		        // 只分割第一个 @，保留后面的所有内容
		        const firstAtIndex = inputString.indexOf('@')
		        this.ver = inputString.substring(0, firstAtIndex) || ''
		        processedString = inputString.substring(firstAtIndex + 1) || ''
		        // 解析当前天数
		        const showMatch = processedString.match(/show:([^;]+)/)
		        if (showMatch) {
		            const showValues = showMatch[1].split(',');
		            currentDay = parseInt(showValues[showValues.length - 2]) || 0
		        }
		    } else {
		        processedString = inputString;
		        this.ver = '';
		    }
			if(this.ver.length > 6){
				this.ver = this.ver.slice(0,6)
			}
			console.log(this.ver,'ververver');
		    const version = this.ver;
		    // 使用正则表达式提取数字部分
		    const versionNumber = version.match(/\d+/); // 匹配连续的数字
		    
		    // 检查并删除 @low:0 或 low:0
		    if (processedString.includes('@low:0') || processedString.includes('low:0')) {
		        // 删除 @low:0（可能在开头或中间）
		        processedString = processedString.replace(/@low:0@?/g, '');
		        // 删除 low:0@（在开头，后面跟着@）
		        processedString = processedString.replace(/^low:0@/g, '');
		        // 删除 low:0（处理各种位置的情况）
		        processedString = processedString.replace(/^low:0;?/g, ''); // 开头
		        processedString = processedString.replace(/;low:0;?/g, ';'); // 中间
		        processedString = processedString.replace(/;low:0$/g, ''); // 结尾
		        processedString = processedString.replace(/^low:0$/g, ''); // 只有 low:0
		        // 清理可能出现的连续分号或开头结尾的分号
		        processedString = processedString.replace(/;;+/g, ';').replace(/^;+|;+$/g, '');
		    }
		    
		    const pairs = processedString.split(';').filter(Boolean)
			    console.log('分割后的数据对:', pairs)
			    const showObject = {}
			    const pSetObjects = {}
			    // 初始化所有p_set为默认值
			    for (let i = 1; i <= 6; i++) {
			        pSetObjects[`p_set${i}`] = [0, 0, 0, 0, 0]
			    }
			    // 解析字符串
			    pairs.forEach(pair => {
			        const [key, value] = pair.split(':')
					console.log(key,'555555555555555555555555')
			        if (key === 'show') {
			            showObject.showArray = value.split(',').map(Number)
			        } else if (key.startsWith('p_set')) {
			            const values = value.split(',').map(Number)
			            // 确保数组长度为5
			            while (values.length < 5) {
			                values.push(0)
			            }
			            pSetObjects[key] = values
			        }
			    })
			    this.ver_data = pSetObjects
			    this.jstimeobj = pSetObjects
			    this.showobj = showObject
				
			const showArray = (this.showobj && Array.isArray(this.showobj.showArray)) ? this.showobj.showArray : []
			console.log(showArray,'this.showobj.showArraythis.showobj.showArraythis.showobj.showArray')
		    // 设置开关状态（浇水进行中或已点确定未结束时，不更新雨水感应状态）
			if(showArray.length >= 2){
				if (!this.isRainSensorLocked) {
					this.yschecked = showArray[1] == 0 ? true : false
				}
				this.etchecked = showArray[0] == 0 ? true : false
			}
			// 获取浇水倒计时（第五位，索引为4），前提是第三位（索引2）和第四位（索引3）都必须是1
			if(showArray.length > 4){
				// 检查第三位（索引2）和第四位（索引3）是否都为1
				const thirdValue = showArray[2]
				const fourthValue = showArray[3]
				if(thirdValue === 1 && fourthValue === 1){
					// 第三位和第四位都是1，才取第五位的值
					const countdown = showArray[4]
					if(countdown && countdown > 0){
						// 清除之前的倒计时定时器
						this.clearWateringCountdownTimer()
						// 仅更新设备倒计时显示，不改变浇水开关状态（仅用户点击才改变）
						this.showWateringCountdown = true
						// 启动倒计时
						this.startWateringCountdownTimer(countdown)
					} else {
						// 倒计时为0，清除定时器与显示，不改变浇水开关状态
						this.clearWateringCountdownTimer()
						this.wateringCountdownMinutes = ''
						this.wateringCountdownSeconds = ''
						this.showWateringCountdown = false
					}
				} else {
					// 第三位或第四位不是1，清除定时器与显示，不改变浇水开关状态
					this.clearWateringCountdownTimer()
					this.wateringCountdownMinutes = ''
					this.wateringCountdownSeconds = ''
					this.showWateringCountdown = false
				}
			} else {
				// 数组长度不够，清除定时器与显示，不改变浇水开关状态
				this.clearWateringCountdownTimer()
				this.wateringCountdownMinutes = ''
				this.wateringCountdownSeconds = ''
				this.showWateringCountdown = false
			}
				this.dianya = showArray.length ? showArray[showArray.length - 1] : 0
				console.log('this.yscheckedthis.yschecked',this.yschecked,this.etchecked)
				this.getdianliang()
			    this.calculateNextWateringTime(currentDay)
			    console.log('解析后的数据:', {
			        ver_data: this.ver_data,
			        showobj: this.showobj,
			        nextTime: this.xctimesj,
			        nextTimeDiff: this.xctime,
			        prevTime: this.sctimejs
			    });
				if(showArray.length > 9){
					this.xinp = showArray[showArray.length - 2]
					this.dianya = showArray[showArray.length - 1]
				}else{
					this.xinp = showArray.length ? showArray[showArray.length - 1] : 0
					this.dianya = 0
				}
				console.log('息屏',this.xinp,'电压',this.dianya);
				this.getdianliang()
				
				// 非 WATER 情况也按 { value, at } 结构上传（大量字段统一包装）
				if(this.vardataflag == 3){
					const now = new Date();
					const yyyy = now.getFullYear();
					const MM = String(now.getMonth() + 1).padStart(2, '0');
					const dd = String(now.getDate()).padStart(2, '0');
					const HH = String(now.getHours()).padStart(2, '0');
					const mm = String(now.getMinutes()).padStart(2, '0');
					const ss = String(now.getSeconds()).padStart(2, '0');
					const at = `${yyyy}-${MM}-${dd} ${HH}:${mm}:${ss}`;
					const nowTs = Date.now();
					if(!this.lastUploadTs || (nowTs - this.lastUploadTs) >= 2000){
					const wrapParams = (obj) => {
							const out = {};
							if(!obj || typeof obj !== 'object') return out;
							Object.keys(obj).forEach((key) => {
								const raw = obj[key];
								const value = (raw && typeof raw === 'object' && 'value' in raw) ? raw.value : raw;
								out[key] = { value: String(value == null ? '' : value), at };
							});
							return out;
						}
					// 当后台参数对象为空时，从 BLE 解析的 ver_data 构造 h1/m1/s1/o1/d1 ...
					const buildParamsFromState = () => {
						const params = {}
						if(this.ver_data && typeof this.ver_data === 'object'){
							for(let i = 1; i <= 6; i++){
								const arr = this.ver_data[`p_set${i}`]
								if(Array.isArray(arr) && arr.length >= 5){
									params[`h${i}`] = arr[0]
									params[`m${i}`] = arr[1]
									params[`s${i}`] = arr[2]
									params[`o${i}`] = arr[3]
									params[`d${i}`] = arr[4]
								}
							}
						}
						return params
					}
					// SATER：从 saterDataByType 构造 pA、pB 上传参数
					const buildSaterParamsFromState = () => {
						const params = {}
						const { pA, pB } = this.saterDataByType || {}
						if (pA) params.pA = pA.replace(/;+$/, '')
						if (pB) params.pB = pB.replace(/;+$/, '')
						return params
					}
					// 在 BLE 已连接场景，优先使用当前解析的 ver_data（p_set1..p_set6）
					const hasVerData = (() => {
						if(!this.ver_data || typeof this.ver_data !== 'object') return false;
						for(let i = 1; i <= 6; i++){
							const arr = this.ver_data[`p_set${i}`]
							if(Array.isArray(arr) && arr.length >= 2 && (arr[0] > 0 || arr[1] > 0 || arr[2] > 0 || arr[3] > 0)){
								return true
							}
						}
						return false
					})()
					const hasSaterData = this.pre === 'SATER' && this.saterDataByType && (this.saterDataByType.pA || this.saterDataByType.pB)
					const yiStr = String(showArray[6] == null ? 0 : showArray[6])
					const erStr = String(showArray[7] == null ? 0 : showArray[7])
					// console.log('22222222222222222222222222222222222222222222222222222',yiStr,erStr);
					// 判断字符串长度是否为1（而不是<10）
					let yi = yiStr.length === 1 ? '0' + yiStr : yiStr
					let er = erStr.length === 1 ? '0' + erStr : erStr
					// console.log('33333333333333333333333333333333333333333333333333',yi,er);
					this.devicetime = yi + ':' + er
					const hasBackend = this.zaixianobj && Object.keys(this.zaixianobj).length > 0
					const chosenParams = hasSaterData ? buildSaterParamsFromState() : (hasVerData ? buildParamsFromState() : (hasBackend ? this.zaixianobj : {}))
					// 合并额外状态字段：仅保留 yudi（雨水感应）、lock（儿童锁），
					// 按你的要求直接使用布尔：开启=false，关闭=true
					const mergedParams = { ...chosenParams }
					mergedParams.yudi = this.yschecked ? 0 : 1
					mergedParams.lock = this.etchecked ? 0 : 1
					mergedParams.time = this.devicetime
					mergedParams.bat = this.dianya
					mergedParams.nt = { value: String(this.timeToSeconds(this.devicetime)),at }
					let data = {
						mac: this.mac,
						params: wrapParams(mergedParams)
					}
						data.params.xinp = { value: String(this.xinp), at }
						this.$u.put(`/app/updateDeviceParam`, data).then(res => {})
						this.lastUploadTs = nowTs;
					}
				}
			},
			// 初始化断开蓝牙定时器
			initDisconnectTimer() {
				this.clearDisconnectTimer()
				this.disconnectTimer = setTimeout(() => {

				}, 600000)
			},
			// 重置断开蓝牙定时器
			resetDisconnectTimer() {
				this.initDisconnectTimer()
			},
			// 清除断开蓝牙定时器
			clearDisconnectTimer() {
				if(this.disconnectTimer) {
					clearTimeout(this.disconnectTimer)
					this.disconnectTimer = null
				}
			},
			// 断开蓝牙连接
			disconnectBluetooth() {
				if(this.deviceId) {
					wx.closeBLEConnection({
						deviceId: this.deviceId,
						success: () => {
							console.log('蓝牙连接已断开')
							this.vardataflag = 1
							this.datalist = ''
							this.saterDataByType = { pA: '', pB: '', ver: '' }
							this.saterRawPayload = ''
							this.clearDataTimeoutTimer()
							uni.showToast({
								title: this.$t('index.bleDisconnected'),
								icon: 'none',
								duration: 2000
							})
						}
					})
					xBlufi.notifyConnectBle({
						isStart: false,
						deviceId: this.deviceId,
						name: this.name
					})
				}
			},
			// 清理5秒数据看门狗
			clearDataTimeoutTimer() {
				if (this.dataTimeoutTimer) {
					clearTimeout(this.dataTimeoutTimer)
					this.dataTimeoutTimer = null
				}
			},
			// 监听用户操作的方法
			handleUserAction() {
				if(this.vardataflag == 3) {
					this.resetDisconnectTimer()
				}
			},
			// 获取时间显示
			getTimeDisplay(setKey) {
				const set = this.ver_data[setKey];
				if (set && set[0] !== undefined) {
					return `${set[0].toString().padStart(2, '0')}:${set[1].toString().padStart(2, '0')}`;
				}
				return '--:--';
			},
			// 判断是否是当前时间
			isCurrentTime(setKey) {
				const set = this.ver_data[setKey];
				return set && set[0] == this.xctimesj.slice(0,2) && set[1] == this.xctimesj.slice(-2);
			},
			// 计算时间差值（分钟）
			getTimeDifference(hour, minute) {
				if (!this.devicetime) return Infinity;
				const [currentHour, currentMinute] = this.devicetime.split(':').map(Number);
				const currentTotalMinutes = currentHour * 60 + currentMinute;
				const targetTotalMinutes = hour * 60 + minute;
				
				// 计算时间差
				let diff = targetTotalMinutes - currentTotalMinutes;
				// 如果时间已过，加上24小时
				if (diff <= 0) {
					diff += 1440;
				}
				return diff;
			},
			
			// 判断定时是否开启（兼容 1 和 true）
			isPsetEnabled(arr) {
				return arr && (arr[3] === 1 || arr[3] === true);
			},
			// 计算下一次浇水时间（用于 xctime、xctimesj、小三角图标等）
			calculateNextWateringTime(currentDay) {
				if (!this.ver_data || typeof this.ver_data !== 'object') return
				const day = (currentDay != null && currentDay >= 0) ? currentDay : Math.floor(Date.now() / 86400000)
				const calculateTimeDifference = (date1, date2) => {
					const diffMs = Math.abs(date1 - date2)
					const diffMinutes = Math.floor(diffMs / (1000 * 60))
					const diffHours = Math.floor(diffMinutes / 60)
					const remainingMinutes = diffMinutes % 60
					return { hours: diffHours, minutes: remainingMinutes }
				}
				const formatTime = (seconds) => {
					const minutes = Math.floor(seconds / 60)
					const remainingSeconds = seconds % 60
					return this.$t('index.durationMinSec', { m: minutes, s: remainingSeconds })
				}
				const getTimeFromArray = (timeArray) => {
					if (!timeArray || timeArray.length < 2) return null
					const [hour, minute] = timeArray
					const date = new Date()
					date.setHours(hour, minute, 0, 0)
					return date
				}
				let nextTime = null
				let nextTimeDiff = null
				let nextWaterDuration = null
				let prevTime = null
				for (const key in this.ver_data) {
					if (this.ver_data.hasOwnProperty(key) && this.isPsetEnabled(this.ver_data[key])) {
						const timeArray = this.ver_data[key]
						const timeDate = getTimeFromArray(timeArray)
						if (!timeDate) continue
						const diff = calculateTimeDifference(timeDate, new Date())
						const interval = timeArray[4] || 0
						const shouldWaterToday = interval === 0 || (day % Math.max(1, interval) === 0)
						if (timeDate > new Date() && shouldWaterToday) {
							if (!nextTime || (diff.hours * 60 + diff.minutes < (nextTimeDiff?.hours || 0) * 60 + (nextTimeDiff?.minutes || 0))) {
								nextTimeDiff = diff
								nextTime = timeDate
								nextWaterDuration = formatTime(timeArray[2])
							}
						} else if (!prevTime || timeDate > prevTime) {
							prevTime = timeDate
						}
					}
				}
				this.xctime = nextTime ? this.$t('index.timeUntil', { h: nextTimeDiff.hours, m: nextTimeDiff.minutes }) : this.$t('index.noNextGap')
				this.xctimesc = nextWaterDuration || this.$t('index.unknownDuration')
				this.sctimejs = prevTime ? prevTime.toTimeString().slice(0, 5) : this.$t('index.noLastWater')
				this.xctimesj = nextTime ? nextTime.toTimeString().slice(0, 5) : this.$t('index.noNextWater')
			},
			// 判断是否显示图标（下一次浇水小三角）
			shouldShowIcon(pSetIndex) {
				const pSet = this.ver_data[`p_set${pSetIndex}`];
				if (!pSet || !this.isPsetEnabled(pSet)) return false;
				
				const currentDiff = this.getTimeDifference(pSet[0], pSet[1]);
				
				for (let i = 1; i <= 6; i++) {
					const checkSet = this.ver_data[`p_set${i}`];
					if (checkSet && this.isPsetEnabled(checkSet)) {
						const checkDiff = this.getTimeDifference(checkSet[0], checkSet[1]);
						if (checkDiff < currentDiff || (checkDiff === currentDiff && i < pSetIndex)) {
							return false;
						}
					}
				}
				return true;
			},
			// 将后台返回的 h1/m1/o1/s1... 整合为 ver_data 结构
			// SATER：从 pA、pB 解析六组定时；其他型号从 h1/m1/s1/o1/d1 解析
			buildVerDataFromBackend(params){
				if (this.pre === 'SATER' && (params?.pA || params?.pB)) {
					const parsed = this.parseSaterFromApiParams(params)
					this.saterListA = parsed.A
					this.saterListB = parsed.B
					const target = this.stareChannel === 'B' ? parsed.B : parsed.A
					return this.normalizeVerDataSwitch(target)
				}
				const result = {}
				for(let i = 1; i <= 6; i++){
					const h = Number(params?.[`h${i}`]?.value)
					const m = Number(params?.[`m${i}`]?.value)
					const s = Number(params?.[`s${i}`]?.value)
					const o = Number(params?.[`o${i}`]?.value)
					const d = Number(params?.[`d${i}`]?.value)
					const hour = isNaN(h) ? 0 : h
					const minute = isNaN(m) ? 0 : m
					const second = isNaN(s) ? 0 : s
					const onoff = isNaN(o) ? 0 : o
					const interval = isNaN(d) || d <= 0 ? 1 : d
					result[`p_set${i}`] = [hour, minute, second, onoff, interval]
				}
				return result
			},
			// SATER：从 getDetail 的 pA、pB 解析为六组定时 { A: {p_set1..p_set6}, B: {...} }
			parseSaterFromApiParams(params){
				const getVal = (obj) => {
					if (!obj) return ''
					const v = (obj && typeof obj === 'object' && 'value' in obj) ? obj.value : obj
					return String(v == null ? '' : v).replace(/^["\s]+|["\s]+$/g, '')
				}
				const pAStr = getVal(params.pA)
				const pBStr = getVal(params.pB)
				const raw = (pAStr ? pAStr + ';' : '') + (pBStr || '')
				return this.parseSaterRawToAB(raw)
			},
			parseSaterRawToAB(rawInput){
				const raw = String(rawInput || '')
				const src = raw.replace(/@/g, ';')
				const resultA = {}
				const resultB = {}
				for (let i = 1; i <= 6; i++) {
					resultA[`p_set${i}`] = [0, 0, 0, 0, 0]
					resultB[`p_set${i}`] = [0, 0, 0, 0, 0]
				}
				const reg = /p([AB])(\d+):([^;]+)/g
				let m
				while ((m = reg.exec(src)) !== null) {
					const ch = m[1]
					const idx = Number(m[2])
					if (!idx || idx < 1 || idx > 6) continue
					const nums = m[3].split(',').map(v => {
						const n = parseInt(v, 10)
						return isNaN(n) ? 0 : n
					})
					while (nums.length < 5) nums.push(0)
					nums[3] = nums[3] === 1
					const key = `p_set${idx}`
					if (ch === 'A') resultA[key] = nums
					if (ch === 'B') resultB[key] = nums
				}
				return { A: resultA, B: resultB }
			},
			normalizeVerDataSwitch(obj){
				const out = {}
				if (!obj || typeof obj !== 'object') return out
				Object.keys(obj).forEach((k) => {
					const arr = Array.isArray(obj[k]) ? [...obj[k]] : [0, 0, 0, 0, 0]
					while (arr.length < 5) arr.push(0)
					arr[3] = arr[3] === 1 || arr[3] === true
					out[k] = arr
				})
				return out
			},
			// 检查并修复蓝牙状态
			checkAndFixBluetooth() {
				return new Promise((resolve, reject) => {
					uni.getBluetoothAdapterState({
						success: (res) => {
							if (res.available) {
								// 蓝牙可用，直接继续
								resolve()
							} else {
								// 蓝牙不可用，尝试重新打开
								this.fixBluetoothAdapter().then(resolve).catch(reject)
							}
						},
						fail: (err) => {
							// 获取状态失败，尝试重新初始化
							this.fixBluetoothAdapter().then(resolve).catch(reject)
						}
					})
				})
			},
			// 修复蓝牙适配器
			fixBluetoothAdapter() {
				return new Promise((resolve, reject) => {
					uni.openBluetoothAdapter({
						success: () => {
							console.log('蓝牙适配器重新初始化成功')
							resolve()
						},
						fail: (err) => {
							const errMsg = err.errMsg || ''
							let errorType = 'UNKNOWN'
							let errorMessage = this.$t('index.ble.initFail')
							let canAutoFix = false
							let userAction = ''
							
							if (errMsg.includes('auth deny') || errMsg.includes('authorize')) {
								errorType = 'PERMISSION_DENIED'
								errorMessage = this.$t('index.ble.permDenied')
								userAction = this.$t('index.ble.permDeniedHint')
							} else if (errMsg.includes('not available') || errMsg.includes('unavailable')) {
								errorType = 'BLUETOOTH_UNAVAILABLE'
								errorMessage = this.$t('index.ble.btUnavailable')
								userAction = this.$t('index.ble.btUnavailableHint')
							} else if (errMsg.includes('open fail')) {
								errorType = 'OPEN_FAILED'
								errorMessage = this.$t('index.ble.openFail')
								userAction = this.$t('index.ble.openFailHint')
							} else if (errMsg.includes('system permission denied')) {
								errorType = 'SYSTEM_PERMISSION_DENIED'
								errorMessage = this.$t('index.ble.sysPerm')
								userAction = this.$t('index.ble.sysPermHint')
							} else if (errMsg.includes('bluetooth service unavailable')) {
								errorType = 'SERVICE_UNAVAILABLE'
								errorMessage = this.$t('index.ble.svcUnavailable')
								userAction = this.$t('index.ble.svcUnavailableHint')
								canAutoFix = true
							} else if (errMsg.includes('already opened')) {
								// 已经打开，可以继续
								resolve()
								return
							}
							reject({
								type: errorType,
								message: errorMessage,
								errMsg: errMsg,
								canAutoFix: canAutoFix,
								userAction: userAction
							})
						}
					})
				})
			},
			// 诊断连接失败原因（按优先级逐个检查，找到第一个错误就停止）
			diagnoseConnectionFailure() {
				// 如果已经显示过错误弹窗，不再重复诊断
				if (this.errorModalShown) {
					return
				}
				
				// 按优先级检查错误，找到第一个就停止
				// 1. 首先检查蓝牙适配器状态
				uni.getBluetoothAdapterState({
					success: (res) => {
						// 2. 检查蓝牙是否可用
						if (!res.available) {
							// 找到第一个错误：蓝牙不可用
							this.handleConnectionError({
								type: 'BLUETOOTH_UNAVAILABLE',
								message: this.$t('index.ble.btUnavailable'),
								userAction: this.$t('index.ble.btUnavailableHint'),
								canAutoFix: true
							})
							return // 找到错误，停止检查
						}
						
						// 3. 蓝牙可用，检查是否找到设备
						const deviceCount = this.devicesarr ? this.devicesarr.length : 0
						
						if (deviceCount === 0) {
							// 找到第二个错误：未搜索到任何设备
							this.handleConnectionError({
								type: 'NO_DEVICES_FOUND',
								message: this.$t('index.ble.noDevices'),
								userAction: this.$t('index.ble.noDevicesHint'),
								canAutoFix: false
							})
							return // 找到错误，停止检查
						}
						
						// 4. 有设备但找不到目标设备
						const matchedDevice = this.devicesarr.find(device => {
							if (device.name) {
								return device.name.slice(-12) === this.mac.slice(-12)
							}
							return false
						})
						
						if (!matchedDevice) {
							// 找到第三个错误：未找到目标设备
							this.handleConnectionError({
								type: 'TARGET_DEVICE_NOT_FOUND',
								message: this.$t('index.ble.targetNotFound', { n: deviceCount }),
								userAction: this.$t('index.ble.targetNotFoundHint'),
								canAutoFix: false
							})
							return // 找到错误，停止检查
						}
						
						// 如果所有检查都通过但没有连接成功，可能是其他原因
						// 这种情况不应该发生，但为了安全起见还是处理一下
						if (!this.errorModalShown) {
							this.handleConnectionError({
								type: 'UNKNOWN_ERROR',
								message: this.$t('index.ble.unknown'),
								userAction: this.$t('index.ble.unknownHint'),
								canAutoFix: false
							})
						}
					},
					fail: (err) => {
						// 获取状态失败，尝试重新初始化
						this.fixBluetoothAdapter().then(() => {
							// 修复成功，提示用户重试
							if (!this.errorModalShown) {
								this.handleConnectionError({
									type: 'ADAPTER_ERROR',
									message: this.$t('index.ble.adapterFixed'),
									userAction: this.$t('index.ble.adapterFixedHint'),
									canAutoFix: true,
									autoFixed: true
								})
							}
						}).catch((error) => {
							// 修复失败，显示错误
							if (!this.errorModalShown) {
								this.handleConnectionError(error)
							}
						})
					}
				})
			},
			// 处理连接错误（只显示一次）
			handleConnectionError(error) {
				// 如果已经显示过错误弹窗，不再重复显示
				if (this.errorModalShown) {
					return
				}
				
				const errorInfo = error || {}
				const type = errorInfo.type || 'UNKNOWN'
				
				// 如果错误类型相同，不再重复显示
				if (this.currentErrorType === type) {
					return
				}
				
				// 标记错误弹窗已显示
				this.errorModalShown = true
				this.currentErrorType = type
				
				const message = errorInfo.message || this.$t('index.ble.connectFailDefault')
				const userAction = errorInfo.userAction || this.$t('index.ble.retryHint')
				const canAutoFix = errorInfo.canAutoFix || false
				const autoFixed = errorInfo.autoFixed || false
				
				// 清除连接状态
				this.vardataflag = 1
				this.clearConnectionTimeout()
				xBlufi.notifyStartDiscoverBle({
					'isStart': false
				})
				
				// 如果已自动修复，显示成功提示
				if (autoFixed) {
					this.showCustomErrorModal({
						title: this.$t('index.fixed'),
						message: message,
						userAction: userAction,
						showCancel: false,
						confirmText: this.$t('common.gotIt'),
						onConfirm: () => {
							// 重置错误状态，允许下次检查
							this.errorModalShown = false
							this.currentErrorType = null
							// 可以自动重试
							if (canAutoFix) {
								setTimeout(() => {
									this.btnlj()
								}, 1000)
							}
						}
					})
					return
				}
				
				// 根据错误类型决定是否可以自动修复
				if (canAutoFix && type === 'BLUETOOTH_UNAVAILABLE') {
					this.showCustomErrorModal({
						title: this.$t('index.connectFail'),
						message: message,
						userAction: userAction,
						showCancel: true,
						cancelText: this.$t('common.cancel'),
						confirmText: this.$t('common.autoRepair'),
						onConfirm: () => {
							// 重置错误状态
							this.errorModalShown = false
							this.currentErrorType = null
							// 尝试自动修复
							this.fixBluetoothAdapter().then(() => {
								uni.showToast({
									title: this.$t('index.fixOkRetry'),
									icon: 'success',
									duration: 2000
								})
								// 修复成功后，允许重新检查错误
								setTimeout(() => {
									this.errorModalShown = false
									this.currentErrorType = null
								}, 2000)
							}).catch((err) => {
								// 修复失败，重新显示错误（重置状态后）
								this.errorModalShown = false
								this.currentErrorType = null
								this.handleConnectionError(err)
							})
						}
					})
				} else {
					// 需要用户手动处理
					this.showCustomErrorModal({
						title: this.$t('index.connectFail'),
						message: message,
						userAction: userAction,
						showCancel: true,
						cancelText: this.$t('common.cancel'),
						confirmText: this.$t('common.retry'),
						onConfirm: () => {
							// 重置错误状态，允许下次检查
							this.errorModalShown = false
							this.currentErrorType = null
							// 用户点击重试
							setTimeout(() => {
								this.btnlj()
							}, 500)
						}
					})
				}
			},
			// 显示自定义错误弹窗
			showCustomErrorModal(data) {
				this.errorModalData = {
					title: data.title || this.$t('common.tip'),
					message: data.message || '',
					userAction: data.userAction || '',
					showCancel: data.showCancel !== undefined ? data.showCancel : true,
					cancelText: data.cancelText || this.$t('common.cancel'),
					confirmText: data.confirmText || this.$t('common.confirm'),
					onConfirm: data.onConfirm || (() => {})
				}
				this.showErrorModal = true
			},
			// 关闭错误弹窗
			closeErrorModal() {
				this.showErrorModal = false
				// 重置错误状态
				this.errorModalShown = false
				this.currentErrorType = null
			},
			// 处理错误弹窗确认
			handleErrorConfirm() {
				if (this.errorModalData.onConfirm) {
					this.errorModalData.onConfirm()
				}
				this.showErrorModal = false
				// xBlufi.initXBlufi(1)
				// xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
				// xBlufi.notifyStartDiscoverBle({
				// 	'isStart': true
				// })
			},
			// 处理连接超时
			handleConnectionTimeout() {
				// 如果已经显示过错误弹窗，不再重复显示
				if (this.errorModalShown) {
					return
				}
				
				this.vardataflag = 1
				this.clearConnectionTimeout()
				xBlufi.notifyStartDiscoverBle({
					'isStart': false
				})
				
				const elapsedTime = Date.now() - (this.connectionStartTime || Date.now())
				this.handleConnectionError({
					type: 'CONNECTION_TIMEOUT',
					message: this.$t('index.ble.timeout', { s: Math.floor(elapsedTime / 1000) }),
					userAction: this.$t('index.ble.timeoutHint'),
					canAutoFix: false
				})
			},
			// 清除连接超时定时器
			clearConnectionTimeout() {
				if (this.connectionTimeout) {
					clearTimeout(this.connectionTimeout)
					this.connectionTimeout = null
				}
				if (this.connectTimeout) {
					clearTimeout(this.connectTimeout)
					this.connectTimeout = null
				}
			},
		}
	}
</script>

<style lang="scss">
	
	.dangqian{
		width: 100%;
		height: 160rpx;
		background: #FFFFFF;
		box-shadow: 0rpx 0rpx 38rpx 0rpx rgba(128,128,128,0.3);
		filter: blur(0px);
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 0 26rpx;
		box-sizing: border-box;
		margin-top: 24rpx;
		border-radius: 20rpx;
		image{
			width: 78rpx;
			height: 78rpx;
		}
		.cen{
			margin-left: 30rpx;
			.shen{
				font-weight: 600;
				font-size: 28rpx;
				color: #3D3D3D;
				margin-bottom: 8rpx;
				display: flex;
				text{
					width: 80rpx;
					height: 40rpx;
					background-color: #7FAD76;
					color: #fff;
					text-align: center;
					line-height: 40rpx;
					border-radius: 10rpx;
					margin-left: 20rpx;
				}
			}
			view{
				font-size: 24rpx;
				color: #808080;
			}
		}
		.rt{
			font-weight: 600;
			font-size: 48rpx;
			color: #50565A;
		}
	}
	.rotated-image {
	    transform: rotate(180deg); /* 旋转 180 度 */
	    transition: transform 1s ease;
	}
	.container {
		display: flex;
		align-items: center;
		justify-content: center;
		margin-top: 22rpx;
		view {
			width: 242rpx;
			height: 208rpx;
			background: #F0F0F0;
			border-radius: 24rpx 24rpx 24rpx 24rpx;
			text-align: center;
			line-height: 208rpx;
			font-weight: 600;
			font-size: 44rpx;
			color: #3D3D3D;
		}
		text {
			font-size: 80rpx;
			margin-left: 46rpx;
			margin-right: 46rpx;
		}
	}
	.anniu {
		display: flex;
		justify-content: space-between;
		margin-top: 58rpx;
		.qx {
			width: 278rpx;
			height: 80rpx;
			border-radius: 10rpx 10rpx 10rpx 10rpx;
			border: 2rpx solid #7FAD76;
			font-size: 36rpx;
			color: #7FAD76;
			font-weight: 600;
			line-height: 80rpx;
			text-align: center;
		}
		.qd {
			width: 278rpx;
			height: 80rpx;
			background: #7FAD76;
			border-radius: 10rpx 10rpx 10rpx 10rpx;
			font-size: 36rpx;
			color: #fff;
			font-weight: 600;
			line-height: 80rpx;
			text-align: center;
		}
	}
	.selected-time {
		margin-top: 20px;
		font-size: 20px;
	}
	#activebor {
		border: 1px solid #7FAD76;
	}
	@keyframes fadeInDown {
		from {
			opacity: 0;
			transform: translateY(-20px);
			/* 初始位置稍微在上方 */
		}
		to {
			opacity: 1;
			transform: translateY(0);
			/* 最终位置 */
		}
	}
	.mask{
		width: 100%;
		height: 100vh;
		background: #3D3D3D;
		opacity: 0.2;
		position: fixed;
		top: 0;
		left: 0;
		z-index: 1;
	}
	.manualmask {
		width: 100%;
		height: 100vh;
		background: #3D3D3D;
		opacity: 0.2;
		position: fixed;
		top: 0;
		left: 0;
		z-index: 99;
	}
	.manualjs {
		width: 678rpx;
		max-height: 610rpx;
		background: #fff;
		border-radius: 24rpx 24rpx 24rpx 24rpx;
		position: fixed;
		top: 538rpx;
		left: 50%;
		transform: translateX(-50%);
		z-index: 100;
		padding: 42rpx 44rpx;
		box-sizing: border-box;
		.toptit {
			font-size: 36rpx;
			color: #3D3D3D;
			font-weight: 600;
			display: flex;
			justify-content: space-between;
			align-items: center;
		}
	}
	.page {
		padding: 0 20rpx;
		padding-bottom: 300rpx;
		box-sizing: border-box;
		.tabsb {
			width: 750rpx;
			max-height: 95vh;
			background: #FFFFFF;
			position: fixed;
			top: 0;
			left: 0;
			padding: 0 40rpx;
			padding-bottom: 60rpx !important;
			box-sizing: border-box;
			border-radius: 0rpx 0rpx 50rpx 50rpx;
			z-index: 2;
			padding-top: 110rpx;
			box-sizing: border-box;
			animation: fadeInDown .5s ease-out forwards;
			.qdan {
				width: 100%;
				height: 102rpx;
				font-size: 48rpx;
				color: #FFFFFF;
				font-weight: 500;
				line-height: 102rpx;
				text-align: center;
				background-color: #7FAD76;
				border-radius: 20rpx;
				margin-top: 40rpx;
			}
			.sblist {
				width: 100%;
				max-height: 68vh;
				overflow: scroll;
				margin-top: 50rpx;
				.sbist_val {
					display: flex;
					justify-content: space-between;
					align-items: center;
					padding: 20rpx 30rpx;
					margin-bottom: 28rpx;
					box-sizing: border-box;
					background: #F7F7F7;
					border-radius: 20rpx 20rpx 20rpx 20rpx;
					border: 1px solid transparent;
					.lt {
						font-size: 36rpx;
						color: #3D3D3D;
						font-weight: 600;
					}
					.rt {
						image {
							width: 124rpx;
							height: 124rpx;
						}
					}
				}
			}
		}
		.sbmask {
			width: 100%;
			height: 100vh;
			background-color: rgb(238, 238, 238);
			position: fixed;
			top: 400rpx;
			left: 0;
			opacity: .5;
		}
		.wusb {
			margin-top: 514rpx;
			text-align: center;
			text {
				font-size: 28rpx;
				color: #737B80;
			}
			view {
				width: 212rpx;
				height: 76rpx;
				background: #7FAD76;
				border-radius: 38rpx 38rpx 38rpx 38rpx;
				border-radius: 50rpx;
				font-size: 28rpx;
				color: #FFFFFF;
				text-align: center;
				line-height: 76rpx;
				margin: auto;
				margin-top: 50rpx;
			}
		}
		.wateringlogbox {
			width: 100%;
			height: 200rpx;
			background: #FFFFFF;
			box-shadow: 0rpx 0rpx 38rpx 0rpx rgba(128, 128, 128, 0.3);
			filter: blur(0px);
			border-radius: 20rpx;
			margin-top: 20rpx;
			padding: 30rpx;
			box-sizing: border-box;
			.wateringlogbd {
				display: flex;
				justify-content: space-between;
				.lt {
					view {
						font-size: 28rpx;
						color: #50565A;
						margin-top: 10rpx;
					}
				}
				.rt {
					image {
						width: 114rpx;
						height: 114rpx;
					}
				}
			}
			.wateringlogtop {
				display: flex;
				align-items: center;
				font-size: 32rpx;
				color: #3D3D3D;
				font-weight: 600;
				image {
					width: 40rpx;
					height: 40rpx;
					margin-right: 14rpx;
				}
			}
		}
		.dingshi_he {
			margin-top: 24rpx;
			width: 350rpx;
			height: 194rpx;
			background: #FFFFFF;
			box-shadow: 0rpx 0rpx 38rpx 0rpx rgba(128, 128, 128, 0.3);
			filter: blur(0px);
			border-radius: 20rpx;
			padding: 26rpx;
			box-sizing: border-box;
			.naoz {
				font-size: 40rpx;
				color: #3D3D3D;
				font-weight: 600;
				display: flex;
				justify-content: space-between;
				image {
					width: 78rpx;
					height: 78rpx;
				}
			}
			.dstime {
				margin-top: 14rpx;
				display: flex;
				align-items: center;
				width: 100%;
				justify-content: space-between;
				image {
					width: 52rpx;
					height: 52rpx;
				}
			}
		}
		.switchbox {
			margin-top: 24rpx;
			display: flex;
			justify-content: space-between;
			.switch_he {
				width: 350rpx;
				height: 194rpx;
				background: #FFFFFF;
				box-shadow: 0rpx 0rpx 38rpx 0rpx rgba(128, 128, 128, 0.3);
				filter: blur(0px);
				border-radius: 20rpx;
				padding: 26rpx;
				box-sizing: border-box;
				.yushui {
					width: 100%;
					font-size: 28rpx;
					color: #3D3D3D;
					display: flex;
					align-items: center;
					justify-content: space-between;
					margin-top: 20rpx;
				}
				image {
					width: 78rpx;
					height: 78rpx;
				}
			}
		}
		.devicebox {
			width: 100%;
			max-height: 800rpx;
			background: #FFFFFF;
			box-shadow: 0rpx 0rpx 38rpx 0rpx rgba(128, 128, 128, 0.3);
			filter: blur(0px);
			margin-top: 22rpx;
			border-radius: 20rpx;
			padding: 30rpx;
			box-sizing: border-box;
			.deviceweek {
				display: flex;
				justify-content: space-between;
				margin-top: 20rpx;
				.weeklist {
					text-align: center;
					.kg {
						font-size: 24rpx;
						color: #999999;
						font-weight: 600;
					}
					.weekday {
						font-size: 36rpx;
						color: #3D3D3D;
						font-weight: 600;
						margin-top: 4rpx;
					}
					.time {
						font-size: 28rpx;
						color: #3D3D3D;
						margin-top: 4rpx;
					}
					.interval {
						font-size: 24rpx;
						color: #3D3D3D;
						font-weight: 600;
						margin-top: 4rpx;
					}
					.img {
						text-align: center;
						image {
							width: 12rpx;
							height: 12rpx;
						}
					}
				}
			}
			.devicetop {
				display: flex;
				justify-content: space-between;
				align-items: center;
				.devicert {
					text-align: right;
					.shoudong {
						display: flex;
						image {
							width: 64rpx;
							height: 32rpx;
							margin-right: 8rpx;
						}
						font-size: 24rpx;
						color: #3D3D3D;
					}
					.shengyu {
						font-size: 24rpx;
						color: #3D3D3D;
						margin-top: 6rpx;
					}
				}
				.devicelt {
					display: flex;
					.xinghao {
						font-size: 24rpx;
						color: #3D3D3D;
						.one {
							font-size: 28rpx !important;
							color: #3D3D3D;
							font-weight: 600 !important;
							margin-top: 6rpx;
						}
					}
					image {
						width: 74rpx;
						height: 80rpx;
						margin-right: 32rpx;
					}
				}
				.signal-bars {
					.signal-bar {
						transition: background-color 0.3s;
						&.active {
							background-color: #7FAD76 !important;
						}
					}
				}
			}
		}
		/* 电池电量样式：边框包裹，背景按百分比填充，红黄绿 */
		.battery-wrap {
			display: flex;
			align-items: center;
			.battery-box {
				position: relative;
				width: 46rpx;
				height: 24rpx;
				line-height: 24rpx;
				border: 2rpx solid #b1b1b1;
				border-radius: 8rpx;
				overflow: hidden;
				background: #f5f5f5;
				.battery-fill {
					position: absolute;
					left: 0;
					top: 0;
					bottom: 0;
					min-width: 0;
					border-radius: 8rpx;
					transition: width 0.3s ease, background-color 0.3s ease;
					/* width: 20rpx ; */
					/* height: 24rpx ; */
					border: 1px solid #fff;
				}
				.battery-text {
					position: relative;
					z-index: 1;
					height: 100%;
					display: flex;
					align-items: center;
					justify-content: center;
					font-size: 16rpx;
					color: #333;
					font-weight: 500;
				}
			}
			.battery-nub {
				width: 4rpx;
				height: 14rpx;
				background: #b1b1b1;
				border-radius: 0 4rpx 4rpx 0;
				margin-left: 2rpx;
			}
		}
		/* 刷新按钮 */
		.refresh-btn {
			display: flex;
			align-items: center;
			justify-content: center;
			gap: 8rpx;
			padding: 12rpx 24rpx;
			border: 1rpx solid #7FAD76;
			border-radius: 32rpx;
			background: rgba(127, 173, 118, 0.08);
			font-size: 26rpx;
			color: #7FAD76;
			&:active {
				background: rgba(127, 173, 118, 0.2);
			}
			&.is-refreshing {
				opacity: 0.85;
				pointer-events: none;
			}
			.refresh-icon {
				font-size: 28rpx;
				line-height: 1;
			}
			.refresh-text {
				font-weight: 500;
			}
		}
		.selectbox {
			width: 100%;
			margin-top: 22rpx;
			display: flex;
			justify-content: space-between;
			align-items: center;
			.shebeiname {
				font-size: 36rpx;
				color: #333;
				font-weight: 600;
				display: flex;
				align-items: center;
				.lj{
					color: #e21616;
					margin-left: 10rpx;
					font-weight: 400;
					font-size: 28rpx;
					border: 1px solid #e21616;
					padding: 4rpx;
					box-sizing: border-box;
					border-radius: 10rpx;
				}
				text {
					display: inline-block;
					width: 14rpx;
					height: 14rpx;
					background: #7FAD76;
					border-radius: 50%;
					box-shadow: 0rpx 0rpx 10rpx 0rpx rgba(0, 255, 102, 0.9), 0rpx 0rpx 30rpx 0rpx rgba(69, 255, 143, 0.9);
					margin-left: 22rpx;
				}
			}
			.shebeiadd {
				image {
					width: 214rpx;
					height: 64rpx;
				}
			}
			.selectname {
				font-size: 48rpx;
				color: #3D3D3D;
				font-weight: 600;
				z-index: 2;
				image {
					width: 32rpx;
					height: 26rpx;
					margin-left: 14rpx;
				}
			}
			.selectnames {
				font-size: 28rpx;
				color: #3D3D3D;
                border: 1px solid;
				padding:0 20rpx;
				box-sizing: border-box;
				border-radius: 10rpx;
				background-color: #7FAD76;
				color: #fff;
				height: 60rpx;
				line-height: 60rpx;
				image {
					width: 32rpx;
					height: 26rpx;
					margin-left: 14rpx;
				}
			}
			.selectshezhi {
				image {
					width: 60rpx;
					height: 60rpx;
				}
			}
		}
		.bjimg {
			width: 100%;
			height: 100vh;
			position: fixed;
			top: 0;
			left: 0;
			z-index: -1;
		}
		.title {
			box-sizing: border-box;
			padding: 0 20rpx;
			image {
				width: 260rpx;
				height: 60rpx;
			}
		}
		.gateway-item {
			display: flex;
			align-items: end;
			// padding: 20rpx;
			padding-left: 20rpx;
			box-sizing: border-box;
			background: #FFFFFF;
			
			.gateway-icon-circle {
				width: 60rpx;
				height: 60rpx;
				background: #E5E5E5;
				border-radius: 50%;
				// margin-right: 10rpx;
				flex-shrink: 0;
			}
			
			.gateway-content {
				display: flex;
				align-items: center;
				.gateway-title {
					font-size: 20rpx;
					color: #333333;
					font-weight: 500;
					margin-bottom: 2rpx;
				}
				
				.gateway-desc {
					font-size: 24rpx;
					color: #7FAD76;
				}
			}
		}
	}

	.channel-switch{
		position: relative;
		width: 100%;
		margin-top: 20rpx;
		height: 72rpx;
		border-radius: 12rpx;
		overflow: hidden;
		border: 2rpx solid #48893B;
		box-sizing: border-box;
	}
	/* 背景层：梯形斜切（未选中白色，选中绿色） */
	.channel-bg{
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background: #fff;
	}
	/* A：左梯形，右边缘斜（上窄下宽） */
	.channel-bg.channel-bg-a{
		clip-path: polygon(0 0, 48% 0, 52% 100%, 0 100%);
		z-index: 1;
	}
	.channel-bg.channel-bg-a.active{
		background: #48893B;
		z-index: 2;
	}
	/* B：右梯形，左边缘斜 */
	.channel-bg.channel-bg-b{
		clip-path: polygon(48% 0, 100% 0, 100% 100%, 52% 100%);
		z-index: 1;
	}
	.channel-bg.channel-bg-b.active{
		background: #48893B;
		z-index: 2;
	}
	/* 文字层：独立定位，不被裁剪 */
	.channel-text{
		position: absolute;
		top: 0;
		bottom: 0;
		width: 50%;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		z-index: 3;
		font-size: 28rpx;
		font-weight: 600;
		color: #48893B;
	}
	.channel-text.channel-text-a{
		left: 0;
	}
	.channel-text.channel-text-b{
		right: 0;
		left: auto;
	}
	.channel-text.active{
		color: #fff;
	}
	/* 激活态底部指示条（绿色背景上显白色） */
	.channel-indicator{
		position: absolute;
		bottom: 12rpx;
		left: 50%;
		transform: translateX(-50%);
		width: 36rpx;
		height: 6rpx;
		border-radius: 3rpx;
		background: #fff;
	}
	
	/* 加载遮罩层样式 */
	.loading-mask {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100vh;
		background-color: rgba(255, 255, 255, 0.8);
		display: flex;
		align-items: center;
		justify-content: center;
		z-index: 9999;
	}
	
	.loading-content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		padding: 40rpx;
		background-color: #fff;
		border-radius: 20rpx;
		box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
	}
	
	.loading-text {
		margin-top: 20rpx;
		font-size: 28rpx;
		color: #666;
		text-align: center;
	}
	
	/* 自定义错误弹窗样式 */
	.error-modal-mask {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100vh;
		background-color: rgba(0, 0, 0, 0.5);
		display: flex;
		align-items: center;
		justify-content: center;
		z-index: 10000;
		animation: fadeIn 0.3s ease;
	}
	
	@keyframes fadeIn {
		from {
			opacity: 0;
		}
		to {
			opacity: 1;
		}
	}
	
	.error-modal-container {
		width: 640rpx;
		background: #FFFFFF;
		border-radius: 24rpx;
		overflow: hidden;
		animation: slideUp 0.3s ease;
		box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
	}
	
	@keyframes slideUp {
		from {
			transform: translateY(100rpx);
			opacity: 0;
		}
		to {
			transform: translateY(0);
			opacity: 1;
		}
	}
	
	.error-modal-header {
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 40rpx 40rpx 30rpx;
		border-bottom: 1rpx solid #F0F0F0;
	}
	
	.error-icon {
		font-size: 48rpx;
		margin-right: 16rpx;
	}
	
	.error-modal-title {
		font-size: 36rpx;
		font-weight: 600;
		color: #333333;
	}
	
	.error-modal-content {
		padding: 40rpx;
		max-height: 60vh;
		overflow-y: auto;
	}
	
	.error-message {
		font-size: 32rpx;
		color: #FF6B6B;
		font-weight: 500;
		line-height: 1.6;
		margin-bottom: 30rpx;
		word-break: break-all;
	}
	
	.error-action {
		background: #F8F9FA;
		border-radius: 12rpx;
		padding: 24rpx;
		border-left: 4rpx solid #7FAD76;
	}
	
	.action-label {
		font-size: 28rpx;
		color: #7FAD76;
		font-weight: 600;
		display: block;
		margin-bottom: 16rpx;
	}
	
	.action-text {
		font-size: 28rpx;
		color: #666666;
		line-height: 1.8;
		white-space: pre-line;
		word-break: break-all;
	}
	
	.error-modal-footer {
		display: flex;
		border-top: 1rpx solid #F0F0F0;
	}
	
	.error-btn {
		flex: 1;
		height: 100rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 32rpx;
		font-weight: 500;
		cursor: pointer;
		transition: all 0.3s;
	}
	
	.error-btn-cancel {
		color: #999999;
		border-right: 1rpx solid #F0F0F0;
		background: #FAFAFA;
	}
	
	.error-btn-cancel:active {
		background: #F0F0F0;
	}
	
	.error-btn-confirm {
		color: #FFFFFF;
		background: linear-gradient(135deg, #7FAD76 0%, #6A9A65 100%);
		font-weight: 600;
	}
	
	.error-btn-confirm:active {
		background: linear-gradient(135deg, #6A9A65 0%, #5A8A55 100%);
		opacity: 0.9;
	}
</style>