소스 검색

feat: 设备离线不允许保存设备信息(基础信息、区域信息、告警计划)

liujia 1 개월 전
부모
커밋
40d81060b6

+ 34 - 0
src/directives/disabled.ts

@@ -0,0 +1,34 @@
+import type { DirectiveBinding, ObjectDirective } from 'vue'
+
+const disabled: ObjectDirective = {
+  mounted(el: HTMLElement, binding: DirectiveBinding) {
+    updateDisabled(el, binding.value)
+  },
+  updated(el: HTMLElement, binding: DirectiveBinding) {
+    updateDisabled(el, binding.value)
+  },
+}
+
+function updateDisabled(el: HTMLElement, value: boolean) {
+  if (value) {
+    if ('disabled' in el) {
+      el.disabled = true
+    } else {
+      el.setAttribute('disabled', 'true')
+      el.style.pointerEvents = 'none'
+      el.style.opacity = '0.6'
+      el.style.cursor = 'not-allowed'
+    }
+  } else {
+    if ('disabled' in el) {
+      el.disabled = false
+    } else {
+      el.removeAttribute('disabled')
+      el.style.pointerEvents = ''
+      el.style.opacity = ''
+      el.style.cursor = ''
+    }
+  }
+}
+
+export default disabled

+ 2 - 0
src/main.ts

@@ -7,12 +7,14 @@ import '@/styles/index.css'
 import App from './App.vue'
 import router from './router'
 import pinia from '@/stores/index'
+import disabled from '@/directives/disabled'
 
 const app = createApp(App)
 
 app.config.globalProperties.$http = request
 app.use(pinia)
 app.use(router)
+app.directive('disabled', disabled)
 
 const components = import.meta.glob('./components/**/*.vue', { eager: true })
 Object.entries(components).forEach(([path, module]) => {

+ 4 - 0
src/views/device/detail/components/deviceAreaConfig/index.vue

@@ -22,10 +22,12 @@
         </div>
         <div class="viewer-header-extra">
           <a-space>
+            <span v-if="props.online === 0" style="color: red">⚠️设备离线,不允许编辑保存</span>
             <a-switch
               :checked="isEditDraggable"
               checked-children="启用"
               un-checked-children="禁用"
+              :disabled="props.online === 0"
               @change="isEditDraggable = !isEditDraggable"
             />
             <a-button
@@ -379,6 +381,7 @@ type Props = {
   length: number
   width: number
   ranges: number[] // 区域范围
+  online?: SwitchType // 设备在线状态,用于判断是否可以保存配置
 }
 const emit = defineEmits<{
   (e: 'success', value: void): void
@@ -388,6 +391,7 @@ const props = withDefaults(defineProps<Props>(), {
   length: 0, // 区域宽度
   width: 0, // 区域高度
   ranges: () => [], // 区域范围
+  online: 0,
 })
 
 const deviceRoomId = ref('')

+ 8 - 1
src/views/device/detail/components/deviceBaseConfig/index.vue

@@ -213,9 +213,14 @@
 
       <div class="footer" :style="{ marginLeft: '100px' }">
         <a-space>
-          <a-button type="primary" :loading="saveBaseLoading" @click="saveBaseConfig"
+          <a-button
+            type="primary"
+            :loading="saveBaseLoading"
+            :disabled="props.online === 0"
+            @click="saveBaseConfig"
             >保存配置</a-button
           >
+          <span v-if="props.online === 0" style="color: red">⚠️设备离线,不允许编辑保存</span>
         </a-space>
       </div>
     </a-form>
@@ -239,6 +244,7 @@ defineOptions({
 type Props = {
   devId: string // 设备id 查询使用
   clientId: string // 设备id 更新使用
+  online: SwitchType // 设备是否在线
 }
 const emit = defineEmits<{
   (e: 'success', value: void): void
@@ -246,6 +252,7 @@ const emit = defineEmits<{
 const props = withDefaults(defineProps<Props>(), {
   devId: '',
   clientId: '',
+  online: 0,
 })
 
 const userStore = useUserStore()

+ 4 - 0
src/views/device/detail/components/deviceConfig/index.vue

@@ -19,6 +19,7 @@
       <deviceBaseConfig
         :dev-id="props.data.devId"
         :client-id="props.data.clientId"
+        :online="props.online"
         @success="deviceAreaConfigSuccess"
       ></deviceBaseConfig>
     </template>
@@ -29,6 +30,7 @@
         :length="props.data.length"
         :width="props.data.width"
         :ranges="[props.data.xStart, props.data.xEnd, props.data.yStart, props.data.yEnd]"
+        :online="props.online"
         @success="deviceAreaConfigSuccess"
       ></deviceAreaConfig>
     </template>
@@ -58,6 +60,7 @@ type Props = {
     yStart: number
     yEnd: number
   }
+  online?: SwitchType
 }
 
 const emit = defineEmits<{
@@ -78,6 +81,7 @@ const props = withDefaults(defineProps<Props>(), {
     yStart: 0,
     yEnd: 0,
   }),
+  online: 0,
 })
 
 const modeRadio = ref<'base' | 'area'>(props.mode)

+ 28 - 5
src/views/device/detail/index.vue

@@ -230,7 +230,9 @@
         <info-item-group title="告警计划" class="alarmPlanGroup">
           <template #extra>
             <a-space>
-              <a-button type="primary" size="small" @click="addPlanHandler"> 新增计划 </a-button>
+              <a-button type="primary" size="small" :disabled="!isOnline" @click="addPlanHandler">
+                新增计划
+              </a-button>
             </a-space>
           </template>
 
@@ -243,24 +245,34 @@
                   /></div>
                   <div class="alarmPlan-item-contant" :title="plan.name">{{ plan.name }}</div>
                   <div class="alarmPlan-item-action">
-                    <a-space>
+                    <a-space :class="!isOnline && 'offline'">
                       <a-popconfirm
                         :title="`确认${plan.enable ? '禁用' : '启用'}计划吗?`"
                         ok-text="确认"
                         cancel-text="取消"
+                        :disabled="!isOnline"
                         @confirm="swtichAlarmItem(plan.id, plan.enable, plan)"
                       >
-                        <a-switch :checked="plan.enable" size="small" :loading="plan.loading" />
+                        <a-switch
+                          :checked="plan.enable"
+                          size="small"
+                          :loading="plan.loading"
+                          :disabled="!isOnline"
+                        />
                       </a-popconfirm>
 
-                      <EditOutlined @click="editAlarmItem(plan.data as AlarmPlanItem)" />
+                      <EditOutlined
+                        v-disabled="!isOnline"
+                        @click="editAlarmItem(plan.data as AlarmPlanItem)"
+                      />
                       <a-popconfirm
                         title="确认删除计划吗?"
                         ok-text="确认"
                         cancel-text="取消"
+                        :disabled="!isOnline"
                         @confirm="deleteAlarmItem(plan.id)"
                       >
-                        <DeleteOutlined />
+                        <DeleteOutlined v-disabled="!isOnline" />
                       </a-popconfirm>
                     </a-space>
                   </div>
@@ -290,6 +302,7 @@
         :room-id="deviceRoomId"
         :furniture-items="furnitureItems"
         :sub-region-items="subRegionItems"
+        :online="detailState.online"
         @success="saveConfigSuccess"
       ></deviceConfigDrawer>
 
@@ -664,6 +677,9 @@ const areaAvailable = computed(() => {
   return Number(length) < 50 || Number(width) < 50
 })
 
+// 设备是否在线
+const isOnline = computed(() => detailState.value.online === 1)
+
 onUnmounted(() => {
   if (mqttClient) mqttClient.end()
   if (mqttTimeout) clearTimeout(mqttTimeout)
@@ -945,6 +961,13 @@ const swtichAlarmItem = async (id: number, swtich: boolean, item: AlarmPlanItem)
           color: #40a9ff;
         }
       }
+
+      :deep(.ant-space.offline) {
+        cursor: not-allowed;
+        .ant-space-item:hover {
+          color: #888;
+        }
+      }
     }
   }
 }