Browse Source

fix:各设备滑块,场景,样式

anxiaoxia 1 week ago
parent
commit
b8cc601dd1

+ 18 - 22
src/components/slider/Slider.vue

@@ -13,31 +13,28 @@
       <span
         v-if="isFollow && showValue && suffixNormal"
         class="slider-internal-text"
-        :style="{ left: isFollow && progressWidth < 86 ? `calc(${progressWidth}% + 10px)` : 'auto', color: followColor }"
-        >{{ showValue ? internalValue : max }}{{ suffix }} 
-        </span
-      >
+        :style="{
+          left: isFollow && progressWidth < 86 ? `calc(${progressWidth}% + 10px)` : 'auto',
+          color: followColor
+        }"
+        >{{ showValue ? internalValue : max }}{{ suffix }}
+      </span>
       <!-- <span
         v-if="isFollow && showValue && !suffixNormal"
         class="slider-internal-text"
         :style="{ left: isFollow && progressWidth < 86 ? `calc(${progressWidth}% + 10px)` : 'auto', color: followColor }"
-        >{{ showValue ? internalValue : max }}<sup class="slider-internal-text-suffix">{{ suffix }}</sup> 
+        >{{ showValue ? internalValue : max }}<sup class="slider-internal-text-suffix">{{ suffix }}</sup>
         </span
       > -->
-      <span
-        v-else
-        class="slider-max-text"
-        :style="{color: maxColor }"
-        >{{ max }}</span
-      >
+      <span v-else class="slider-max-text" :style="{ color: maxColor }">{{ max }}</span>
     </div>
   </div>
 </template>
 
 <script setup>
-import { computed, defineModel, defineProps, onMounted, ref, useTemplateRef, watch } from 'vue';
+import { computed, defineModel, defineProps, onMounted, ref, useTemplateRef, watch } from "vue"
 
-const emit = defineEmits(['onEnd', 'onStart'])
+const emit = defineEmits(["onEnd", "onStart"])
 const props = defineProps({
   min: {
     type: Number,
@@ -57,13 +54,12 @@ const props = defineProps({
   },
   suffix: {
     type: String,
-    default: ''
+    default: ""
   },
   showValue: {
     type: Boolean,
     default: false
   }
-
 })
 
 const model = defineModel()
@@ -78,7 +74,7 @@ watch(
 const internalValue = ref(model.value || props.min)
 const isDragging = ref(false)
 let animationFrameId = null
-const sliderContainer = useTemplateRef('slider-container')
+const sliderContainer = useTemplateRef("slider-container")
 const progressWidth = computed(() => {
   const percentage = ((internalValue.value - props.min) / (props.max - props.min)) * 100
   return `${Math.max(percentage, 10)}`
@@ -91,16 +87,16 @@ const progressWidth = computed(() => {
 
 const followColor = computed(() => {
   const percentage = ((internalValue.value - props.min) / (props.max - props.min)) * 100
-  return percentage >= 95 ? 'rgba(255, 255, 255, 0.6)' : 'var(--Blue, #001428)'
+  return percentage >= 95 ? "rgba(255, 255, 255, 0.6)" : "var(--Blue, #001428)"
 })
 const maxColor = computed(() => {
   const percentage = ((internalValue.value - props.min) / (props.max - props.min)) * 100
-  return percentage >= 95 ? 'rgba(255, 255, 255, 0.6)' : 'rgb(116, 128, 141)'
+  return percentage >= 95 ? "rgba(255, 255, 255, 0.6)" : "rgb(116, 128, 141)"
 })
 
 const startDrag = event => {
   isDragging.value = true
-  emit('onStart', internalValue.value)
+  emit("onStart", internalValue.value)
 }
 
 const onDrag = event => {
@@ -110,7 +106,7 @@ const onDrag = event => {
 
   const sliderRect = sliderContainer.value.getBoundingClientRect()
 
-  const offsetX = touch.clientX - sliderRect.left
+  const offsetX = touch.clientX - sliderRect.left + 16
   //   console.log(touch, sliderRect, offsetX)
   // 计算百分比并确保在 0 到 1 之间
   const percentage = Math.min(Math.max(offsetX / sliderRect.width, 0), 1)
@@ -130,7 +126,7 @@ const endDrag = () => {
   if (animationFrameId) {
     cancelAnimationFrame(animationFrameId)
   }
-  emit('onEnd')
+  emit("onEnd")
 }
 
 onMounted(() => {
@@ -212,7 +208,7 @@ onMounted(() => {
     color: rgb(116, 128, 141);
     font-family: Jost;
   }
-  &-internal-text{
+  &-internal-text {
     @include text-middle(auto, 10px);
     color: #001428;
     font-family: Jost;

+ 17 - 20
src/components/slider/air-slider.vue

@@ -14,24 +14,21 @@
       <span
         v-if="isFollow && showValue"
         class="slider-internal-text"
-        :style="{ left: isFollow && progressWidth < 86 ? `calc(${progressWidth}% + 10px)` : 'auto', color: followColor }"
+        :style="{
+          left: isFollow && progressWidth < 86 ? `calc(${progressWidth}% + 10px)` : 'auto',
+          color: followColor
+        }"
         >{{ showValue ? internalValue : max }}<sup v-if="suffix" class="slider-internal-text-suffix">{{ suffix }}</sup>
-        </span
-      >
-      <span
-        v-if="progressWidth < 80"
-        class="slider-max-text"
-        :style="{color: maxColor }"
-        >{{ max }}</span
-      >
+      </span>
+      <span v-if="progressWidth < 75" class="slider-max-text" :style="{ color: maxColor }">{{ max }}</span>
     </div>
   </div>
 </template>
 
 <script setup>
-import { computed, defineModel, defineProps, onMounted, ref, useTemplateRef, watch } from 'vue'
+import { computed, defineModel, defineProps, onMounted, ref, useTemplateRef, watch } from "vue"
 
-const emit = defineEmits(['onEnd', 'onStart'])
+const emit = defineEmits(["onEnd", "onMoving", "onStart"])
 const props = defineProps({
   min: {
     type: Number,
@@ -48,13 +45,12 @@ const props = defineProps({
 
   suffix: {
     type: String,
-    default: ''
+    default: ""
   },
   showValue: {
     type: Boolean,
     default: false
   }
-
 })
 
 const model = defineModel()
@@ -69,7 +65,7 @@ watch(
 const internalValue = ref(model.value || props.min)
 const isDragging = ref(false)
 let animationFrameId = null
-const sliderContainer = useTemplateRef('slider-container')
+const sliderContainer = useTemplateRef("slider-container")
 const progressWidth = computed(() => {
   const percentage = ((internalValue.value - props.min) / (props.max - props.min)) * 100
   return `${Math.max(percentage, 10)}`
@@ -82,16 +78,16 @@ const progressWidth = computed(() => {
 
 const followColor = computed(() => {
   const percentage = ((internalValue.value - props.min) / (props.max - props.min)) * 100
-  return percentage >= 95 ? 'rgba(255, 255, 255, 0.6)' : 'var(--Blue, #001428)'
+  return percentage >= 95 ? "rgba(255, 255, 255, 0.6)" : "var(--Blue, #001428)"
 })
 const maxColor = computed(() => {
   const percentage = ((internalValue.value - props.min) / (props.max - props.min)) * 100
-  return percentage >= 95 ? 'rgba(255, 255, 255, 0.6)' : 'rgb(116, 128, 141)'
+  return percentage >= 95 ? "rgba(255, 255, 255, 0.6)" : "rgb(116, 128, 141)"
 })
 
 const startDrag = event => {
   isDragging.value = true
-  emit('onStart', internalValue.value)
+  emit("onStart", internalValue.value)
 }
 
 const onDrag = event => {
@@ -101,7 +97,7 @@ const onDrag = event => {
 
   const sliderRect = sliderContainer.value.getBoundingClientRect()
 
-  const offsetX = touch.clientX - sliderRect.left
+  const offsetX = touch.clientX - sliderRect.left + 16
   //   console.log(touch, sliderRect, offsetX)
   // 计算百分比并确保在 0 到 1 之间
   const percentage = Math.min(Math.max(offsetX / sliderRect.width, 0), 1)
@@ -114,6 +110,7 @@ const onDrag = event => {
   animationFrameId = requestAnimationFrame(() => {
     model.value = internalValue.value = newValue
     // emit('update:modelValue', internalValue.value) // 确保使用正确的事件名称
+    emit("onMoving", internalValue.value)
   })
 }
 const endDrag = () => {
@@ -121,7 +118,7 @@ const endDrag = () => {
   if (animationFrameId) {
     cancelAnimationFrame(animationFrameId)
   }
-  emit('onEnd')
+  emit("onEnd")
 }
 
 onMounted(() => {
@@ -207,7 +204,7 @@ onMounted(() => {
     font-weight: 400;
     font-size: 14px;
   }
-  &-internal-text{
+  &-internal-text {
     @include text-middle(auto, 10px);
     color: #001428;
     font-family: Jost;

+ 54 - 42
src/hooks/useDeviceControl.js

@@ -1,4 +1,4 @@
-import { httpSetEnv } from '@/apis/taiguv1'
+import { httpSetEnv } from "@/apis/taiguv1"
 const COMMAND_MAPPINGS = {
   air: {
     isOpen: item => ({ code: item.switchCode, value: val => (val ? 1 : 0) }),
@@ -8,12 +8,12 @@ const COMMAND_MAPPINGS = {
   },
   lamp: {
     // isOpen: () => ({ code: 'EquipSwitchSet', value: val => (val ? 1 : 0) }),
-    isOpen: () => ({ code: 'brightSet', value: val => (val ? 80 : 0) }),
-    brightValue: () => ({ code: 'brightSet', value: val => val }),
-    colorTempValue: () => ({ code: 'colorTempSet', value: val => val })
+    isOpen: () => ({ code: "brightSet", value: val => (val ? 80 : 0) }),
+    brightValue: () => ({ code: "brightSet", value: val => val }),
+    colorTempValue: () => ({ code: "colorTempSet", value: val => val })
   },
   curtain: {
-    isOpen: () => ({ code: 'EquipOffSet', value: val => (val ? 1 : 0) })
+    isOpen: () => ({ code: "EquipOffSet", value: val => (val ? 1 : 0) })
   },
   audio: {
     isOpen: item => ({ code: item.inCloudSetCode, value: val => (val ? 1 : 0) }),
@@ -21,8 +21,7 @@ const COMMAND_MAPPINGS = {
   },
   screen: {
     runStatus: item => ({ code: item.inCloudSetCode, value: val => val })
-  },
-
+  }
 }
 
 const assemblyCommand = type => (commandVal, command, data) => {
@@ -35,7 +34,7 @@ const assemblyCommand = type => (commandVal, command, data) => {
 
   return dataArray.map(item => {
     const commandConfig = COMMAND_MAPPINGS[type][command](item)
-    
+
     return {
       id: item.id,
       code: commandConfig.code,
@@ -45,40 +44,39 @@ const assemblyCommand = type => (commandVal, command, data) => {
 }
 
 // 组装设备的下发参数
-const assemblyAirCommand = assemblyCommand('air')
-const assemblyLampCommand = assemblyCommand('lamp')
-const assemblyCurtainCommand = assemblyCommand('curtain')
-const assemblyAudioCommand = assemblyCommand('audio')
-const assemblyScreenCommand = assemblyCommand('screen')
+const assemblyAirCommand = assemblyCommand("air")
+const assemblyLampCommand = assemblyCommand("lamp")
+const assemblyCurtainCommand = assemblyCommand("curtain")
+const assemblyAudioCommand = assemblyCommand("audio")
+const assemblyScreenCommand = assemblyCommand("screen")
 
 // 初始化下发指令
 const initDeviceCommand = data => {
-
-  let { lamps = [], curtains = [] } = data || {}
-  let commands = []
+  const { lamps = [], curtains = [] } = data || {}
+  const commands = []
   // 灯具指令
-//   lamps.forEach(item => {
-    // 开关指令---取到开关点位
-    // commands.push({
-    //   id: item.id,
-    //   code: item.codeSwitch,
-    //   value: item.valueSwitch
-    // })
+  //   lamps.forEach(item => {
+  // 开关指令---取到开关点位
+  // commands.push({
+  //   id: item.id,
+  //   code: item.codeSwitch,
+  //   value: item.valueSwitch
+  // })
 
-    // 亮度指令 默认80
-    // commands.push({
-    //   id: item.id,
-    //   code: item.codeBright,
-    //   value: item.valueBright
-    // })
+  // 亮度指令 默认80
+  // commands.push({
+  //   id: item.id,
+  //   code: item.codeBright,
+  //   value: item.valueBright
+  // })
 
-    // 色温指令
-    // commands.push({
-    //   id: item.id,
-    //   code: item.codeColorTemp,
-    //   value: item.valueColorTemp
-    // })
-//   })
+  // 色温指令
+  // commands.push({
+  //   id: item.id,
+  //   code: item.codeColorTemp,
+  //   value: item.valueColorTemp
+  // })
+  //   })
   // 窗帘指令
   curtains.forEach(item => {
     commands.push({
@@ -89,16 +87,29 @@ const initDeviceCommand = data => {
   })
   return commands
 }
-
+// 防抖函数
+const debounce = (func, delay) => {
+  let timer = null
+  return (...args) => {
+    if (timer) {
+      clearTimeout(timer)
+    }
+    timer = setTimeout(() => {
+      func(...args)
+      timer = null
+    }, delay)
+  }
+}
 export default function useDeviceControl() {
-  const sendCommands = params => {
+  const sendCommands = (params, cb) => {
     httpSetEnv(params).then(res => {
-      let { status, data } = res
+      const { status, data } = res
       if (status === 200) {
-        console.log('下发成功')
+        console.log("下发成功")
       } else {
-        console.log('下发失败')
+        console.log("下发失败")
       }
+      cb && cb(res)
     })
   }
   return {
@@ -108,6 +119,7 @@ export default function useDeviceControl() {
     assemblyAudioCommand,
     assemblyScreenCommand,
     sendCommands,
-    initDeviceCommand
+    initDeviceCommand,
+    debounce
   }
 }

+ 5 - 0
src/utils/eventBus.js

@@ -0,0 +1,5 @@
+import mitt from 'mitt';
+
+const eventBus = mitt();
+
+export default eventBus;

File diff suppressed because it is too large
+ 544 - 592
src/views/envmonitor/taiguv1/components/Air/AirMore.vue


+ 63 - 55
src/views/envmonitor/taiguv1/components/Air/index.vue

@@ -20,7 +20,7 @@
       <div class="air-info">
         <div class="left">
           <div class="text">{{ $t(`air.空调`) }}</div>
-          <div class="status">{{ $t('air.' + airSwitchStatus.statusText) }}</div>
+          <div class="status">{{ $t("air." + airSwitchStatus.statusText) }}</div>
         </div>
         <div class="temp" v-if="airData.isOpen">{{ airData.tempSet || 16 }}<sup>℃</sup></div>
       </div>
@@ -30,6 +30,7 @@
           v-model="airData.tempSet"
           :min="airData.minTempSet"
           :max="airData.maxTempSet"
+          @onStart="sendEvent(true)"
           @onEnd="setAirStatus('tempSet')"></Slider>
       </div>
 
@@ -63,21 +64,22 @@
 </template>
 
 <script setup>
-import AddIcon from '@/assets/taiguv1/svg/add_icon.svg'
-import AddIconActive from '@/assets/taiguv1/svg/add_icon_active.svg'
-import AutoIcon from '@/assets/taiguv1/svg/auto_icon.svg'
-import AutoIconActive from '@/assets/taiguv1/svg/auto_icon_active.svg'
-import MinusIcon from '@/assets/taiguv1/svg/minus_icon.svg'
-import MinusIconActive from '@/assets/taiguv1/svg/minus_icon_active.svg'
+import AddIcon from "@/assets/taiguv1/svg/add_icon.svg"
+import AddIconActive from "@/assets/taiguv1/svg/add_icon_active.svg"
+import AutoIcon from "@/assets/taiguv1/svg/auto_icon.svg"
+import AutoIconActive from "@/assets/taiguv1/svg/auto_icon_active.svg"
+import MinusIcon from "@/assets/taiguv1/svg/minus_icon.svg"
+import MinusIconActive from "@/assets/taiguv1/svg/minus_icon_active.svg"
 
-import FilterIcon from '@/assets/taiguv1/svg/filter_icon.svg'
-import Slider from '@/components/slider/Slider.vue'
-import SwitchButton from '@/components/switch-button/SwitchButton.vue'
-import useDeviceControl from '@/hooks/useDeviceControl'
-import { useStore } from '@/store'
-import { parseImgUrl } from '@/utils'
-import { nextTick } from 'process'
-import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
+import FilterIcon from "@/assets/taiguv1/svg/filter_icon.svg"
+import Slider from "@/components/slider/Slider.vue"
+import SwitchButton from "@/components/switch-button/SwitchButton.vue"
+import useDeviceControl from "@/hooks/useDeviceControl"
+import { useStore } from "@/store"
+import { parseImgUrl } from "@/utils"
+import { nextTick } from "process"
+import { computed, onMounted, onUnmounted, ref, watch } from "vue"
+import eventBus from "@/utils/eventBus"
 const store = useStore()
 const deviceControl = useDeviceControl()
 const controlBtn = ref([])
@@ -143,8 +145,8 @@ const compareStatus = data => {
   if (allAirStatus.value.all) {
     const { lastSwitchStatus } = allAirStatus.value.all
     if (lastSwitchStatus == data.runStatus) {
-      store.dispatch('taiguv1/setAirStatus', {
-        id: 'all',
+      store.dispatch("taiguv1/setAirStatus", {
+        id: "all",
         status: {
           loading: false,
           lastSwitchStatus: null
@@ -152,7 +154,7 @@ const compareStatus = data => {
       })
       updateAirData()
     } else if (lastSwitchStatus === null) {
-      console.log('debugger')
+      console.log("debugger")
       updateAirData()
     } else {
       airData.value = {
@@ -165,18 +167,18 @@ const compareStatus = data => {
   } else {
     updateAirData()
   }
-  emit('getStatus', airData.value.isOpen)
+  emit("getStatus", airData.value.isOpen)
 }
 
 const airSwitchStatus = computed(() => {
-  let statusText = ''
+  let statusText = ""
   let switchStatus = false
   let arr = props.equipList.filter(item => item.runStatus == 1)
   if (arr.length == 0) {
-    statusText = '已关闭'
+    statusText = "已关闭"
     switchStatus = false
   } else {
-    statusText = arr.length > 0 && arr.length < props.equipList.length ? '部分开启' : '已开启'
+    statusText = arr.length > 0 && arr.length < props.equipList.length ? "部分开启" : "已开启"
     switchStatus = true
   }
   return {
@@ -186,18 +188,20 @@ const airSwitchStatus = computed(() => {
 })
 const allAirStatus = computed(() => store.state.taiguv1.airSwtichStatus)
 
-const emit = defineEmits(['getStatus'])
+const emit = defineEmits(["getStatus"])
 
 const buttonStates = ref({
   minus: false,
   plus: false
 })
-
+const sendEvent = close => {
+  eventBus.emit("close_deviece_timer", { close })
+}
 onMounted(() => {
   nextTick(() => {
     nextTick(() => {
       controlBtn.value.forEach(button => {
-        button.addEventListener('touchstart', handleTouchStart)
+        button.addEventListener("touchstart", handleTouchStart)
       })
     })
   })
@@ -206,57 +210,61 @@ onMounted(() => {
 const handleTouchStart = event => {
   const button = event.currentTarget
   const type = button.dataset.type
-  button.classList.add('active')
+  button.classList.add("active")
   buttonStates.value[type] = true
 
   setTimeout(() => {
-    button.classList.remove('active')
+    button.classList.remove("active")
     buttonStates.value[type] = false
   }, 200)
 }
 
 onUnmounted(() => {
   controlBtn.value.forEach(button => {
-    button.removeEventListener('touchstart', handleTouchStart)
+    button.removeEventListener("touchstart", handleTouchStart)
   })
 })
+const debouncedSendEvent = deviceControl.debounce(sendEvent, 1500)
+const setAirStatus = type => {
+  if (type == "isOpen") {
+    store.dispatch("taiguv1/setAirStatus", {
+      id: "all",
+      status: {
+        loading: true,
+        lastSwitchStatus: airData.value.isOpen
+      }
+    })
+  }
+  const params = deviceControl.assemblyAirCommand(airData.value[type], type, props.equipList)
+  deviceControl.sendCommands(params, () => {
+    debouncedSendEvent(false)
+  })
+
+  emit("getStatus", airData.value.isOpen)
+}
+const debouncedSetAirStatus = deviceControl.debounce(setAirStatus, 1500)
 const handle = type => {
   if (!airData.value.gear) airData.value.gear = 1
-  if (type === 'minus') {
-    airData.value.gear = Math.max(airData.value.gear - 1, 1);
+  sendEvent(true)
+  if (type === "minus") {
+    airData.value.gear = Math.max(airData.value.gear - 1, 1)
     airData.value.isAutoGear = false
-    setAirStatus('gear')
-  } else if (type === 'plus') {
+    debouncedSetAirStatus("gear")
+  } else if (type === "plus") {
     airData.value.gear += 1
     if (airData.value.gear > 5) {
       airData.value.gear = 5
     }
     airData.value.isAutoGear = false
-    setAirStatus('gear')
-  } else if (type === 'auto') {
-  // TODO:自动风量
+    debouncedSetAirStatus("gear")
+  } else if (type === "auto") {
+    // TODO:自动风量
     airData.value.isAutoGear = true
-    setAirStatus('auto')
-  }
-}
-
-const setAirStatus = type => {
-  if (type == 'isOpen') {
-    store.dispatch('taiguv1/setAirStatus', {
-      id: 'all',
-      status: {
-        loading: true,
-        lastSwitchStatus: airData.value.isOpen
-      }
-    })
+    debouncedSetAirStatus("auto")
   }
-  const params = deviceControl.assemblyAirCommand(airData.value[type], type, props.equipList)
-  deviceControl.sendCommands(params)
-
-  emit('getStatus', airData.value.isOpen)
 }
 const searchMore = () => {
-  emit('showMore', 'air', true)
+  emit("showMore", "air", true)
 }
 </script>
 <style lang="scss" scoped>
@@ -358,8 +366,8 @@ const searchMore = () => {
 }
 .activeShow {
   background: rgba(255, 255, 255, 0.8);
-//   -webkit-backdrop-filter: blur(40px);
-//   backdrop-filter: blur(40px);
+  //   -webkit-backdrop-filter: blur(40px);
+  //   backdrop-filter: blur(40px);
   box-shadow: 0px 10px 20px 0px rgba(0, 20, 40, 0.1);
 
   .bottom {

+ 262 - 280
src/views/envmonitor/taiguv1/components/Lamp/LightMore.vue

@@ -1,118 +1,95 @@
 <template>
-    <div class="more-box">
-        <div class="light-more-top">
-            <div class="left">
-                <div class="light-box">
-                    <img
-                        :src="lampData.isOpen ? lampOpenIcon : lampCloseIcon"
-                        alt=""
-                        :style="lampData.isOpen ? { width: '58px', height: '62px' } : ''"
-                    />
-                </div>
-                <div class="light-name">{{ $t(`lamp.${lampData.lampStatusText}`) }}</div>
-            </div>
-            <div class="right">
-                <div
-                    class="control"
-                    :ref="setRef"
-                    @click="handleSwitch('isOpen', true)"
-                >{{ $t(`common.全开`) }}</div>
-                <div
-                    class="control"
-                    :ref="setRef"
-                    @click="handleSwitch('isOpen', false)"
-                >{{ $t(`common.全关`) }}</div>
-            </div>
+  <div class="more-box">
+    <div class="light-more-top">
+      <div class="left">
+        <div class="light-box">
+          <img
+            :src="lampData.isOpen ? lampOpenIcon : lampCloseIcon"
+            alt=""
+            :style="lampData.isOpen ? { width: '58px', height: '62px' } : ''" />
         </div>
-        <div
-            class="light-middle"
-            v-if="lampData.isOpen"
-        >
-            <div class="bright-slider">
-                <Slider
-                    :min="min"
-                    :max="max"
-                    v-model="lampData.brightValue"
-                    isFollow
-                    showValue
-                    suffixNormal
-                    suffix="%"
-                    @onEnd="setLampStatus('brightValue')"
-                />
-            </div>
-            <!-- <div class="temp-slider">
+        <div class="light-name">{{ $t(`lamp.${lampData.lampStatusText}`) }}</div>
+      </div>
+      <div class="right">
+        <div class="control" :ref="setRef" @click="handleSwitch('isOpen', true)">{{ $t(`common.全开`) }}</div>
+        <div class="control" :ref="setRef" @click="handleSwitch('isOpen', false)">{{ $t(`common.全关`) }}</div>
+      </div>
+    </div>
+    <div class="light-middle" v-if="lampData.isOpen">
+      <div class="bright-slider">
+        <Slider
+          :min="min"
+          :max="max"
+          v-model="lampData.brightValue"
+          isFollow
+          showValue
+          suffixNormal
+          suffix="%"
+          @onStart="sendEvent(true)"
+          @onEnd="setLampStatus('brightValue')" />
+      </div>
+      <!-- <div class="temp-slider">
         <LampSlider v-model="lampData.colorTempValue" @onEnd="setLampStatus('colorTempValue')" />
       </div> -->
-        </div>
+    </div>
 
-        <div
-            class="divider"
-            v-if="lampData.isOpen"
-        >
-            <img
-                src="@/assets/svg/line.svg"
-                alt=""
-            />
-        </div>
+    <div class="divider" v-if="lampData.isOpen">
+      <img src="@/assets/svg/line.svg" alt="" />
+    </div>
 
-        <div class="light-bottom">
-            <div
-                class="item-box"
-                :class="item.brightValue ? 'light-box-active' : ''"
-                v-for="(item, index) in lampList"
-            >
-                <div class="name">{{ item.localName }}</div>
-                <div style="width: 100rpx;">
-                    <SwitchButton
-                        :loading="allLampStatus[item.id]?.loading"
-                        v-model="item.isOpen"
-                        @change="sigleLampChange('isOpen', item, 'single')"
-                    />
-                </div>
-            </div>
+    <div class="light-bottom">
+      <div class="item-box" :class="item.brightValue ? 'light-box-active' : ''" v-for="(item, index) in lampList">
+        <div class="name">{{ item.localName }}</div>
+        <div style="width: 100rpx">
+          <SwitchButton
+            :loading="allLampStatus[item.id]?.loading"
+            v-model="item.isOpen"
+            @change="sigleLampChange('isOpen', item, 'single')" />
         </div>
+      </div>
     </div>
+  </div>
 </template>
 
 <script setup>
-import lampCloseIcon from '@/assets/taiguv1/svg/lamp_close_p_icon.svg'
-import lampOpenIcon from '@/assets/taiguv1/svg/lamp_open_p_icon.svg'
-import Slider from '@/components/slider/Slider.vue'
-import SwitchButton from '@/components/switch-button/SwitchButton.vue'
-import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
-
-import useDeviceControl from '@/hooks/useDeviceControl'
-import { useStore } from '@/store'
+import lampCloseIcon from "@/assets/taiguv1/svg/lamp_close_p_icon.svg"
+import lampOpenIcon from "@/assets/taiguv1/svg/lamp_open_p_icon.svg"
+import Slider from "@/components/slider/Slider.vue"
+import SwitchButton from "@/components/switch-button/SwitchButton.vue"
+import { computed, nextTick, onMounted, onUnmounted, ref, watch } from "vue"
+import eventBus from "@/utils/eventBus"
+import useDeviceControl from "@/hooks/useDeviceControl"
+import { useStore } from "@/store"
 const store = useStore()
 const deviceControl = useDeviceControl()
 const min = 0
 const max = 100
 // 接收父组件传递的初始状态
 const props = defineProps({
-    lampStatus: {
-        type: Object,
-        default: () => {
-            return {
-                isOpen: false,
-                brightValue: 0
-            }
-        }
-    },
-    equipList: {
-        type: Array,
-        default: () => {
-            return []
-        }
+  lampStatus: {
+    type: Object,
+    default: () => {
+      return {
+        isOpen: false,
+        brightValue: 0
+      }
     }
+  },
+  equipList: {
+    type: Array,
+    default: () => {
+      return []
+    }
+  }
 })
 
 const controlBtn = ref([])
 const setRef = el => {
-    if (el) {
-        if (!controlBtn.value.includes(el)) {
-            controlBtn.value.push(el)
-        }
+  if (el) {
+    if (!controlBtn.value.includes(el)) {
+      controlBtn.value.push(el)
     }
+  }
 }
 
 const lampList = ref(props.equipList || [])
@@ -137,28 +114,28 @@ const allLampStatus = computed(() => store.state.taiguv1.lampSwitchStatus)
 //   }
 // })
 watch(
-    () => props.lampStatus,
-    (newVal, oldVal) => {
-        if (!newVal) {
-            return
-        }
-        lampData.value = { ...newVal }
-    },
-    { deep: true } // 添加深度监听
+  () => props.lampStatus,
+  (newVal, oldVal) => {
+    if (!newVal) {
+      return
+    }
+    lampData.value = { ...newVal }
+  },
+  { deep: true } // 添加深度监听
 )
 watch(
-    () => props.equipList,
-    (newVal, oldVal) => {
-        compareStatus(newVal)
-    },
-    { deep: true }
+  () => props.equipList,
+  (newVal, oldVal) => {
+    compareStatus(newVal)
+  },
+  { deep: true }
 )
 
 // 对比和store中开关状态
 const compareStatus = data => {
-    lampList.value = data.map(item => {
+  lampList.value = data.map(item => {
     const currentStatus = allLampStatus.value[item.id]
-  let isOpen = item.brightValue!==0
+    let isOpen = item.brightValue !== 0
     // 基础状态对象
     const baseStatus = {
       ...item,
@@ -169,10 +146,9 @@ const compareStatus = data => {
       return baseStatus
     }
 
-
     // 如果最后切换状态与当前运行状态相同,重置状态
     if (currentStatus.lastSwitchStatus == isOpen) {
-      store.dispatch('taiguv1/setLampStatus', {
+      store.dispatch("taiguv1/setLampStatus", {
         id: item.id,
         status: {
           loading: false,
@@ -187,212 +163,218 @@ const compareStatus = data => {
       ...item,
       isOpen: currentStatus.lastSwitchStatus ?? isOpen
     }
-
-    })
+  })
 }
 // 整体开关
 const handleSwitch = (type, value) => {
-    lampData.value.isOpen = value
-    setLampStatus(type)
+  lampData.value.isOpen = value
+  setLampStatus(type)
 }
 
-// 单个空调开关
+// 单个开关
 const sigleLampChange = (type, source, all) => {
-    if (type == 'isOpen') {
-        store.dispatch('taiguv1/setLampStatus', {
-            id: source.id,
-            status: {
-                loading: true,
-                lastSwitchStatus: source.isOpen
-            }
-        })
-    }
-    if (all == 'single') {
-        const params = deviceControl.assemblyLampCommand(source[type], type, source)
-        deviceControl.sendCommands(params)
-    }
+  if (type == "isOpen") {
+    store.dispatch("taiguv1/setLampStatus", {
+      id: source.id,
+      status: {
+        loading: true,
+        lastSwitchStatus: source.isOpen
+      }
+    })
+  }
+  if (all == "single") {
+    const params = deviceControl.assemblyLampCommand(source[type], type, source)
+    deviceControl.sendCommands(params)
+  }
 }
 const setLampStatus = type => {
-    if (type == 'isOpen') {
-        store.dispatch('taiguv1/setLampStatus', {
-            id: 'all',
-            status: {
-                loading: true,
-                lastSwitchStatus: lampData.value.isOpen
-            }
-        })
-        lampList.value.forEach(item => {
-            item.isOpen = lampData.value.isOpen
-            sigleLampChange(type, item, 'all')
-        })
-    }
-    const params = deviceControl.assemblyLampCommand(lampData.value[type], type, lampList.value)
-    deviceControl.sendCommands(params)
+  if (type == "isOpen") {
+    store.dispatch("taiguv1/setLampStatus", {
+      id: "all",
+      status: {
+        loading: true,
+        lastSwitchStatus: lampData.value.isOpen
+      }
+    })
+    lampList.value.forEach(item => {
+      item.isOpen = lampData.value.isOpen
+      sigleLampChange(type, item, "all")
+    })
+  }
+  const params = deviceControl.assemblyLampCommand(lampData.value[type], type, lampList.value)
+  deviceControl.sendCommands(params, () => {
+    debouncedSendEvent(false)
+  })
+}
+const sendEvent = close => {
+  eventBus.emit("close_deviece_timer", { close })
 }
+const debouncedSendEvent = deviceControl.debounce(sendEvent, 1500)
+
 onMounted(() => {
-    nextTick(() => {
-        controlBtn.value.forEach(button => {
-            button.addEventListener('touchstart', handleTouchStart)
-        })
+  nextTick(() => {
+    controlBtn.value.forEach(button => {
+      button.addEventListener("touchstart", handleTouchStart)
     })
+  })
 })
 
 // 添加 touchstart 处理函数
 const handleTouchStart = event => {
-    const button = event.currentTarget
-    button.classList.add('active')
-    setTimeout(() => {
-        button.classList.remove('active')
-    }, 200)
+  const button = event.currentTarget
+  button.classList.add("active")
+  setTimeout(() => {
+    button.classList.remove("active")
+  }, 200)
 }
 // 添加 onUnmounted 钩子
 onUnmounted(() => {
-    controlBtn.value.forEach(button => {
-        button.removeEventListener('touchstart', handleTouchStart)
-    })
+  controlBtn.value.forEach(button => {
+    button.removeEventListener("touchstart", handleTouchStart)
+  })
 })
 </script>
 <style lang="scss" scoped>
 .more-box {
-    .light-more-top {
-        display: flex;
-        align-items: center;
-        margin-bottom: 36px;
-        .left {
-            margin-right: 36px;
-            .light-box {
-                width: 110px;
-                height: 110px;
-                background: rgba(255, 255, 255, 0.4);
-                border-radius: 50%;
-                text-align: center;
-                margin-right: 27px;
-                img {
-                    width: 36px;
-                    height: 36px;
-                    margin: 0 auto;
-                    margin-top: 37px;
-                }
-            }
-            .light-name {
-                //styleName: Chi/Body Large;
-                margin-top: 12px;
-                font-family: PingFang SC;
-                width: 110px;
-                font-size: 16px;
-                font-weight: 300;
-                line-height: 22px;
-                letter-spacing: 0.02em;
-                text-align: center;
-                color: rgba(0, 20, 40, 1);
-            }
+  .light-more-top {
+    display: flex;
+    align-items: center;
+    margin-bottom: 36px;
+    .left {
+      margin-right: 36px;
+      .light-box {
+        width: 110px;
+        height: 110px;
+        background: rgba(255, 255, 255, 0.4);
+        border-radius: 50%;
+        text-align: center;
+        margin-right: 27px;
+        img {
+          width: 36px;
+          height: 36px;
+          margin: 0 auto;
+          margin-top: 37px;
         }
-        .right {
-            height: 92px;
-            display: flex;
-            flex-direction: column;
-            justify-content: space-between;
+      }
+      .light-name {
+        //styleName: Chi/Body Large;
+        margin-top: 12px;
+        font-family: PingFang SC;
+        width: 110px;
+        font-size: 16px;
+        font-weight: 300;
+        line-height: 22px;
+        letter-spacing: 0.02em;
+        text-align: center;
+        color: rgba(0, 20, 40, 1);
+      }
+    }
+    .right {
+      height: 92px;
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
 
-            .control {
-                width: 100px;
-                height: 40px;
-                line-height: 40px;
-                border-radius: 50px;
-                border-radius: 50px;
-                background: #e1e1df;
-                box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.05);
-                color: #001428;
-                //styleName: Chi/Body Small;
-                font-family: PingFang SC;
-                font-size: 12px;
-                font-weight: 400;
-                letter-spacing: 0.04em;
-                text-align: center;
-            }
-            .control.active {
-                background: rgba(255, 255, 255, 1);
-                box-shadow: 0px 10px 20px 0px rgba(0, 20, 40, 0.1);
-            }
-        }
+      .control {
+        width: 100px;
+        height: 40px;
+        line-height: 40px;
+        border-radius: 50px;
+        border-radius: 50px;
+        background: #e1e1df;
+        box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.05);
+        color: #001428;
+        //styleName: Chi/Body Small;
+        font-family: PingFang SC;
+        font-size: 12px;
+        font-weight: 400;
+        letter-spacing: 0.04em;
+        text-align: center;
+      }
+      .control.active {
+        background: rgba(255, 255, 255, 1);
+        box-shadow: 0px 10px 20px 0px rgba(0, 20, 40, 0.1);
+      }
     }
-    .light-middle {
-        // height: 100px;
-        // background: #fff;
-        .bright-slider {
-            width: 100%;
-            height: 62px;
+  }
+  .light-middle {
+    // height: 100px;
+    // background: #fff;
+    .bright-slider {
+      width: 100%;
+      height: 62px;
 
-            background: rgba(255, 255, 255, 0.6);
-            margin-bottom: 12px;
-            border-radius: 12px;
-        }
-        .temp-slider {
-            width: 100%;
-            height: 58px;
-            padding: 2px;
-            border-radius: 12px;
-            background: var(--White-White-60, rgba(255, 255, 255, 0.6));
-            margin-bottom: 12px;
-        }
+      background: rgba(255, 255, 255, 0.6);
+      margin-bottom: 12px;
+      border-radius: 12px;
     }
-    .divider {
-        height: 24px;
-        display: flex;
-        align-items: center;
-        margin-bottom: 12px;
+    .temp-slider {
+      width: 100%;
+      height: 58px;
+      padding: 2px;
+      border-radius: 12px;
+      background: var(--White-White-60, rgba(255, 255, 255, 0.6));
+      margin-bottom: 12px;
     }
-    .light-bottom {
-        // margin-top: 36px;
-        .item-box {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            width: 300px;
-            height: 68px;
-            box-sizing: border-box;
-            padding: 20px 24px;
-            border-radius: 24px 24px 44px 24px;
-            background: rgba(255, 255, 255, 0.2);
-            box-shadow: 0px 10px 20px 0px rgba(0, 20, 40, 0.05);
-            margin-bottom: 12px;
-            .name {
-                //styleName: Chi/Body Regular;
-                font-family: PingFang SC;
-                font-size: 14px;
-                font-weight: 400;
-                line-height: 19px;
-                letter-spacing: 0.02em;
-                color: rgba(0, 20, 40, 1);
-            }
-        }
-        .light-box-active {
-            background: rgba(255, 255, 255, 0.6);
-        }
+  }
+  .divider {
+    height: 24px;
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+  }
+  .light-bottom {
+    // margin-top: 36px;
+    .item-box {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      width: 300px;
+      height: 68px;
+      box-sizing: border-box;
+      padding: 20px 24px;
+      border-radius: 24px 24px 44px 24px;
+      background: rgba(255, 255, 255, 0.2);
+      box-shadow: 0px 10px 20px 0px rgba(0, 20, 40, 0.05);
+      margin-bottom: 12px;
+      .name {
+        //styleName: Chi/Body Regular;
+        font-family: PingFang SC;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 19px;
+        letter-spacing: 0.02em;
+        color: rgba(0, 20, 40, 1);
+      }
     }
-    .switch-btn {
-        margin-top: 0;
-        width: 50px !important;
-        height: 28px !important;
-        border: none;
+    .light-box-active {
+      background: rgba(255, 255, 255, 0.6);
     }
+  }
+  .switch-btn {
+    margin-top: 0;
+    width: 50px !important;
+    height: 28px !important;
+    border: none;
+  }
 }
 </style>
 <style lang="scss">
 .more-box {
-    .van-loading__spinner {
-        color: $elActiveColor !important;
-    }
+  .van-loading__spinner {
+    color: $elActiveColor !important;
+  }
 
-    .van-switch__loading {
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        line-height: 1;
-    }
+  .van-switch__loading {
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    line-height: 1;
+  }
 
-    .van-switch--disabled {
-        opacity: 0.5;
-    }
+  .van-switch--disabled {
+    opacity: 0.5;
+  }
 }
 </style>

+ 35 - 22
src/views/envmonitor/taiguv1/components/Lamp/index.vue

@@ -29,23 +29,29 @@
       </div>
 
       <div class="lamp-slider" v-if="lampData.isOpen">
-        <Slider v-model="lampData.brightValue" :min="min" :max="max" @onEnd="setLampStatus('brightValue')"></Slider>
+        <Slider
+          v-model="lampData.brightValue"
+          :min="min"
+          :max="max"
+          @onStart="sendEvent(true)"
+          @onEnd="setLampStatus('brightValue')"></Slider>
       </div>
     </div>
   </div>
 </template>
 
 <script setup>
-import FilterIcon from '@/assets/taiguv1/svg/filter_icon.svg'
-import Slider from '@/components/slider/Slider.vue'
-import SwitchButton from '@/components/switch-button/SwitchButton.vue'
-import useDeviceControl from '@/hooks/useDeviceControl'
-import { useStore } from '@/store'
-import { parseImgUrl } from '@/utils'
-import { computed, ref, watch } from 'vue'
+import FilterIcon from "@/assets/taiguv1/svg/filter_icon.svg"
+import Slider from "@/components/slider/Slider.vue"
+import SwitchButton from "@/components/switch-button/SwitchButton.vue"
+import useDeviceControl from "@/hooks/useDeviceControl"
+import { useStore } from "@/store"
+import { parseImgUrl } from "@/utils"
+import { computed, ref, watch } from "vue"
+import eventBus from "@/utils/eventBus"
 const min = 0
 const max = 100
-const emit = defineEmits(['getStatus', 'showMore'])
+const emit = defineEmits(["getStatus", "showMore"])
 
 // 接收父组件传递的开关状态
 const props = defineProps({
@@ -71,7 +77,7 @@ const deviceControl = useDeviceControl()
 const allLampStatus = computed(() => store.state.taiguv1.lampSwitchStatus)
 
 const searchMore = () => {
-  emit('showMore', 'lamp', true)
+  emit("showMore", "lamp", true)
 }
 
 const lampData = ref({
@@ -99,8 +105,8 @@ const compareStatus = data => {
   }
   if (allLampStatus.value.all) {
     if (allLampStatus.value.all.lastSwitchStatus == data.isOpen) {
-      store.dispatch('taiguv1/setLampStatus', {
-        id: 'all',
+      store.dispatch("taiguv1/setLampStatus", {
+        id: "all",
         status: {
           loading: false,
           lastSwitchStatus: null
@@ -121,25 +127,31 @@ const compareStatus = data => {
       isOpen: data.isOpen
     }
   }
-  emit('getStatus', lampData.value.isOpen)
+  emit("getStatus", lampData.value.isOpen)
 }
+const sendEvent = close => {
+  eventBus.emit("close_deviece_timer", { close })
+}
+const debouncedSendEvent = deviceControl.debounce(sendEvent, 1500)
 
 const setLampStatus = type => {
-  if (type == 'isOpen') {
-    store.dispatch('taiguv1/setLampStatus', {
-      id: 'all',
+  if (type == "isOpen") {
+    store.dispatch("taiguv1/setLampStatus", {
+      id: "all",
       status: {
         loading: true,
         lastSwitchStatus: lampData.value.isOpen
       }
     })
   }
-  
+  sendEvent(true)
   const params = deviceControl.assemblyLampCommand(lampData.value[type], type, props.equipList)
 
-  deviceControl.sendCommands(params)
+  deviceControl.sendCommands(params, () => {
+    debouncedSendEvent(false)
+  })
 
-  emit('getStatus', lampData.value.isOpen)
+  emit("getStatus", lampData.value.isOpen)
 }
 </script>
 <style lang="scss" scoped>
@@ -208,7 +220,7 @@ const setLampStatus = type => {
       font-family: PingFang SC;
       font-size: 11px;
       font-weight: 400;
-      line-height: 14px;
+      line-height: 15px;
       letter-spacing: 0.02em;
       color: rgba(255, 255, 255, 0.4);
     }
@@ -231,6 +243,7 @@ const setLampStatus = type => {
       justify-content: end;
     }
     .lamp-slider {
+      margin-top: 8px;
       background: rgba(255, 255, 255, 0.6);
       width: 100%;
       height: 34px;
@@ -246,8 +259,8 @@ const setLampStatus = type => {
 }
 .active {
   background: rgba(255, 255, 255, 0.8);
-//   -webkit-backdrop-filter: blur(40px);
-//   backdrop-filter: blur(40px);
+  //   -webkit-backdrop-filter: blur(40px);
+  //   backdrop-filter: blur(40px);
   box-shadow: 0px 10px 20px 0px rgba(0, 20, 40, 0.1);
 
   .bottom {

+ 33 - 21
src/views/envmonitor/taiguv1/components/Volumn/index.vue

@@ -25,26 +25,32 @@
       </div>
 
       <div class="volumn-slider" v-if="audioData.isOpen">
-        <Slider :min="min" :max="max" v-model="audioData.volumnSet" @onEnd="setAudioStatus('volumnSet')"></Slider>
+        <Slider
+          :min="min"
+          :max="max"
+          v-model="audioData.volumnSet"
+          @onStart="sendEvent(true)"
+          @onEnd="setAudioStatus('volumnSet')"></Slider>
       </div>
     </div>
   </div>
 </template>
 
 <script setup>
-import speakerCloseIcon from '@/assets/taiguv1/svg/speaker_close_icon.svg'
-import speakerIcon from '@/assets/taiguv1/svg/speaker_icon.svg'
-import Slider from '@/components/slider/Slider.vue'
-import SwitchButton from '@/components/switch-button/SwitchButton.vue'
-import useDeviceControl from '@/hooks/useDeviceControl'
-import { useStore } from '@/store'
-import { customRound } from '@/utils'
-import { computed, ref, watch } from 'vue'
+import speakerCloseIcon from "@/assets/taiguv1/svg/speaker_close_icon.svg"
+import speakerIcon from "@/assets/taiguv1/svg/speaker_icon.svg"
+import Slider from "@/components/slider/Slider.vue"
+import SwitchButton from "@/components/switch-button/SwitchButton.vue"
+import useDeviceControl from "@/hooks/useDeviceControl"
+import { useStore } from "@/store"
+import { customRound } from "@/utils"
+import { computed, ref, watch } from "vue"
+import eventBus from "@/utils/eventBus"
 const min = 0
 const max = 100
 const store = useStore()
 
-const emit = defineEmits(['getStatus'])
+const emit = defineEmits(["getStatus"])
 const props = defineProps({
   audioStatus: {
     type: Object,
@@ -77,26 +83,28 @@ watch(
 )
 const deviceControl = useDeviceControl()
 const setAudioStatus = type => {
-  if (type == 'isOpen') {
-    store.dispatch('taiguv1/setAudioStatus', {
-      id: 'all',
+  if (type == "isOpen") {
+    store.dispatch("taiguv1/setAudioStatus", {
+      id: "all",
       status: {
         loading: true,
         lastSwitchStatus: audioData.value.isOpen
       }
     })
   } else {
-    store.dispatch('taiguv1/setAudioStatus', {
-      id: 'lastStatus',
+    store.dispatch("taiguv1/setAudioStatus", {
+      id: "lastStatus",
       status: {
         lastValue: audioData.value.volumnSet,
         paramsVaue: customRound(audioData.value.volumnSet)
       }
     })
   }
-
+  sendEvent(true)
   const params = deviceControl.assemblyAudioCommand(customRound(audioData.value[type]), type, props.equipList)
-  deviceControl.sendCommands(params)
+  deviceControl.sendCommands(params, () => {
+    debouncedSendEvent(false)
+  })
 }
 const compareStatus = data => {
   const updateAudioData = () => {
@@ -109,8 +117,8 @@ const compareStatus = data => {
   if (allAudioStatus.value.all) {
     const { lastSwitchStatus } = allAudioStatus.value.all
     if (lastSwitchStatus == data.isOpen) {
-      store.dispatch('taiguv1/setAudioStatus', {
-        id: 'all',
+      store.dispatch("taiguv1/setAudioStatus", {
+        id: "all",
         status: {
           loading: false,
           lastSwitchStatus: null
@@ -130,6 +138,10 @@ const compareStatus = data => {
     updateAudioData()
   }
 }
+const sendEvent = close => {
+  eventBus.emit("close_deviece_timer", { close })
+}
+const debouncedSendEvent = deviceControl.debounce(sendEvent, 1500)
 </script>
 <style lang="scss" scoped>
 .volumn-box {
@@ -217,8 +229,8 @@ const compareStatus = data => {
 }
 .active {
   background: rgba(255, 255, 255, 0.8);
-//   -webkit-backdrop-filter: blur(40px);
-//   backdrop-filter: blur(40px);
+  //   -webkit-backdrop-filter: blur(40px);
+  //   backdrop-filter: blur(40px);
   box-shadow: 0px 10px 20px 0px rgba(0, 20, 40, 0.1);
 
   .bottom {

+ 34 - 19
src/views/envmonitor/taiguv1/index.vue

@@ -10,8 +10,7 @@
       :poster="roomInfo.bg"
       :src="roomInfo.video"
       ref="videoRef"
-      @ended="restartVideo" 
-      ></video>
+      @ended="restartVideo"></video>
     <div
       class="video-model"
       v-if="
@@ -189,16 +188,17 @@ import { ENV_CONFIG, FORUMArr, lanageArr, roomSourceData } from "./const"
 const boxLine = require("@/assets/taiguv1/svg/box_line.png")
 // import "vue3-video-play/dist/style.css";
 import {
-findForServe,
-httpGetByMeetingId,
-HttpGetSpaceInfo,
-queryAirStatus,
-queryAudioStatus,
-queryLampStatus,
-queryScreenCastingStatus
+  findForServe,
+  httpGetByMeetingId,
+  HttpGetSpaceInfo,
+  queryAirStatus,
+  queryAudioStatus,
+  queryLampStatus,
+  queryScreenCastingStatus
 } from "@/apis/taiguv1"
 import useDeviceControl from "@/hooks/useDeviceControl"
 import { useStore } from "@/store"
+import eventBus from "@/utils/eventBus"
 const type = ref(localStorage.getItem("lang") || "zh-CN")
 const route = useRoute()
 const router = useRouter()
@@ -264,18 +264,26 @@ const hasExecutedDefault = ref(false)
 const hasExecutedModeScene = ref(false)
 const store = useStore()
 
-const videoRef = ref(null); // 创建一个 ref 用于引用视频元素
+const videoRef = ref(null) // 创建一个 ref 用于引用视频元素
 const restartVideo = () => {
   if (videoRef.value) {
     // console.log('视频播放结束,重新开始播放');
-    
-    videoRef.value.currentTime = 0; // 将视频播放位置设置为起始点
-    videoRef.value.play(); // 重新播放视频
+
+    videoRef.value.currentTime = 0 // 将视频播放位置设置为起始点
+    videoRef.value.play() // 重新播放视频
+  }
+}
+const handleCustomEvent = data => {
+  // 处理接收到的数据
+  if (data.close) {
+    deviceStatusPolling && deviceStatusPolling.stop()
+  } else {
+    deviceStatusPolling && deviceStatusPolling.start()
   }
-};
+}
 onMounted(async () => {
   console.log("========重新执行了")
-
+  eventBus.on("close_deviece_timer", handleCustomEvent)
   //   TODO: 切换语言
   type.value = localStorage.getItem("lang") || "zh-CN"
   locale.value = type.value
@@ -432,6 +440,7 @@ const initSpace = () => {
 
 // 切换场景模式
 const changeMode = type => {
+  if (type == modeType.value) return
   modeType.value = type
   if (modeType.value == 3) {
     spaceDevice.value.custom = true
@@ -510,7 +519,7 @@ const getDeviceStatus = () => {
         updateScreenStatus(res.data)
       }
     })
-  }, 1000 * 2)
+  }, 1000 * 3)
 
   deviceStatusPolling.start()
 }
@@ -603,13 +612,14 @@ const getAirStatus = status => {
 
 const createPollingTask = (callback, interval = 3000) => {
   let timer = null
-  const start = firstCallbackDone => {
+  const start = (firstCallbackDone, immdate = true) => {
     clearTimeout(timer)
     timer = null
 
     const poll = async () => {
       try {
         await callback()
+
         if (firstCallbackDone) {
           firstCallbackDone()
           firstCallbackDone = null // 确保只执行一次
@@ -617,10 +627,14 @@ const createPollingTask = (callback, interval = 3000) => {
       } catch (error) {
         console.error("轮询任务执行出错:", error)
       }
+
+      timer = setTimeout(poll, interval)
+    }
+    if (immdate) {
+      poll()
+    } else {
       timer = setTimeout(poll, interval)
     }
-
-    poll()
   }
 
   const stop = () => {
@@ -1034,6 +1048,7 @@ onUnmounted(() => {
   .dialog-box-content {
     position: relative;
     padding: 40px 90px;
+    min-height: 100%;
     &::before {
       content: "";
       position: absolute;