Browse Source

feat(device/pole): 优化灯杆详情页面布局和功能

- 重构了灯杆详情页面的布局,增加了更多视觉元素和信息展示
- 添加了灯杆状态、电力信息、使用信息等详细数据展示
- 实现了一键开关灯功能
- 优化了亮度调节滑块的样式和交互
- 增加了数据刷新功能和加载状态展示
- 使用 Element Plus 组件和 Lucide 图标库提升了用户体验
nahida 1 year ago
parent
commit
956d0650f3
2 changed files with 308 additions and 28 deletions
  1. 1 1
      src/views/device/pole/index.vue
  2. 307 27
      src/views/device/pole/pole-detail.vue

+ 1 - 1
src/views/device/pole/index.vue

@@ -499,7 +499,7 @@ onMounted(() => {
 /* 详情对话框样式 */
 .detail-dialog-content {
   padding: 20px;
-  height: calc(100vh - 120px);
+  height: calc(100vh - 160px);
   overflow-y: auto;
 }
 

+ 307 - 27
src/views/device/pole/pole-detail.vue

@@ -1,67 +1,347 @@
 <script setup>
-import {clientGet} from "@/utils/apiClient.js";
-import {ElLoading, ElMessage} from "element-plus";
+import {computed, onMounted, ref} from 'vue'
+import {clientGet} from "@/utils/apiClient.js"
+import {ElButton, ElCard, ElLoading, ElMessage, ElSkeleton, ElSkeletonItem, ElSlider} from "element-plus"
+import {Battery, Clock, Gauge, Lightbulb, Power, Wifi, WifiOff, Zap} from 'lucide-vue-next'
 
 const props = defineProps({
-  deviceNumber:{
+  deviceNumber: {
     type: String,
     default: ''
   }
 })
 
-const brightness = ref('');
+const brightness = ref('')
+const loading = ref(true)
+const refreshing = ref(false)
+
 const poleInfo = ref({
-  light_num: '', //灯杆编号
-  brightness: '', //灯杆当前亮度
-  flag: 0, //0是关 1是开 (灯杆当前状态)
-  voltage: '', //电压
-  current: '', //电流
-  power: '', //功率
-  power_quantity: '', //电量
-  light_total_time: '',//累计开的时间
-  onlineStatus: 0//0离线 1在线 在线状态
-});
-
-const controlPole = async (brightness) => {
+  light_num: '', // 灯杆编号
+  brightness: '', // 灯杆当前亮度 (如果亮度为0则当前关闭 否则为开启)
+  voltage: '', // 电压
+  current: '', // 电流
+  power: '', // 功率
+  power_quantity: '', // 电量
+  light_total_time: '', // 累计开的时间
+  onlineStatus: 0 // 0离线 1在线 在线状态
+})
+
+const isOnline = computed(() => poleInfo.value.onlineStatus === 1)
+const lightStatus = computed(() => Number(poleInfo.value.brightness) > 0 ? '开启' : '关闭')
+const statusColor = computed(() => isOnline.value ? 'text-green-500' : 'text-red-500')
+const lightStatusColor = computed(() => Number(poleInfo.value.brightness) > 0 ? 'text-amber-400' : 'text-gray-400')
+
+// 格式化数字为两位小数
+const formatNumber = (num) => {
+  if (!num) return '0.00'
+  return Number(num).toFixed(2)
+}
+
+const controlPole = async (brightnessValue) => {
   const loadingInstance = ElLoading.service({
     target: '.slider-container',
-    text: 'Loading',
+    text: '调整中...',
     background: 'rgba(0, 0, 0, 0.7)'
-  });
+  })
 
   try {
     const res = await clientGet("/pole/instruct/issued/reportEnvironmentalData", {
       params: {
         cmd: '6011',
-        brightness: brightness?.toString(),
+        brightness: brightnessValue?.toString(),
         packageId: '1050',
         lightNums: props.deviceNumber,
       }
-    });
+    })
+
+    if (res.code !== 200) {
+      ElMessage.error(res.msg)
+    } else {
+      ElMessage.success('亮度调整成功')
+      // 更新后重新获取信息
+      await getPoleInfo()
+    }
+  } catch (error) {
+    ElMessage.error('操作失败,请重试')
+  } finally {
+    loadingInstance.close()
+  }
+}
+
+const getPoleInfo = async () => {
+  try {
+    refreshing.value = true
+    const res = await clientGet('/pole/instruct/issued/equipmentStatus', {
+      params: {
+        cmd: 6012,
+        lightNums: props.deviceNumber,
+        packageId: '1050'
+      }
+    })
+
     if (res.code !== 200) {
-      ElMessage.error(res.msg);
+      ElMessage.error(res.msg)
+      return
     }
 
+    const data = JSON.parse(JSON.parse(res.msg).params)
+
+    if (data.length < 1) {
+      ElMessage.error('获取灯杆信息失败')
+      return
+    }
+
+    poleInfo.value = {
+      light_num: data[0].light_num,
+      brightness: data[0].brightness,
+      voltage: data[0].voltage,
+      current: data[0].current,
+      power: data[0].power,
+      power_quantity: data[0].power_quantity,
+      light_total_time: data[0].light_total_time,
+      onlineStatus: data[0].onlineStatus
+    }
+
+    // 同步滑块值
+    brightness.value = Number(poleInfo.value.brightness)
   } catch (error) {
-    ElMessage.error('An error occurred');
+    ElMessage.error('获取灯杆信息失败')
   } finally {
-    loadingInstance.close();
+    loading.value = false
+    refreshing.value = false
   }
 }
 
 const control = () => {
-  controlPole(brightness.value);
+  controlPole(brightness.value)
 }
 
-onMounted(() => {
+// 一键开启功能 - 设置亮度为100
+const turnOn = () => {
+  brightness.value = 100
+  controlPole(100)
+}
 
+// 一键关闭功能 - 设置亮度为0
+const turnOff = () => {
+  brightness.value = 0
+  controlPole(0)
+}
+
+const refreshData = () => {
+  getPoleInfo()
+}
+
+const formatTime = (minutes) => {
+  if (!minutes) return '0小时0分钟'
+  const hours = Math.floor(minutes / 60)
+  const mins = minutes % 60
+  return `${hours}小时${mins}分钟`
+}
+
+onMounted(() => {
+  getPoleInfo()
 })
 </script>
 
 <template>
-  <el-slider v-model="brightness" :step="10" :max="100" :min="0" @change="control"/>
+  <div class="light-pole-detail w-full h-full">
+    <!-- 标题和刷新按钮 -->
+    <div class="flex justify-between items-center mb-4">
+      <h2 class="text-xl font-bold flex items-center gap-2">
+        <Lightbulb class="text-amber-500" />
+        灯杆控制详情
+      </h2>
+      <button
+          @click="refreshData"
+          class="flex items-center gap-1 px-3 py-1.5 rounded bg-gray-100 hover:bg-gray-200 transition-colors"
+          :disabled="refreshing"
+      >
+        <div class="i-lucide-refresh-cw" :class="{ 'animate-spin': refreshing }"></div>
+        刷新
+      </button>
+    </div>
+
+    <!-- 加载状态 -->
+    <ElSkeleton :loading="loading" animated>
+      <template #template>
+        <div class="grid grid-cols-1 gap-4">
+          <ElSkeletonItem variant="p" style="height: 200px" />
+          <ElSkeletonItem variant="p" style="height: 200px" />
+        </div>
+      </template>
+
+      <!-- 实际内容 -->
+      <template #default>
+        <!-- 状态卡片 -->
+        <ElCard class="mb-4 shadow-sm">
+          <div class="flex items-center justify-between mb-4">
+            <div class="flex items-center gap-2">
+              <div class="text-lg font-medium">灯杆编号: {{ poleInfo.light_num || props.deviceNumber }}</div>
+              <div :class="['flex items-center gap-1', statusColor]">
+                <component :is="isOnline ? Wifi : WifiOff" class="w-4 h-4" />
+                <span>{{ isOnline ? '在线' : '离线' }}</span>
+              </div>
+            </div>
+            <div :class="['flex items-center gap-1', lightStatusColor]">
+              <Power class="w-5 h-5" />
+              <span>{{ lightStatus }}</span>
+            </div>
+          </div>
+
+          <!-- 一键开关按钮 -->
+          <div class="flex gap-3 mb-4">
+            <ElButton
+                type="success"
+                :disabled="!isOnline"
+                @click="turnOn"
+                class="flex-1"
+            >
+              <div class="flex items-center justify-center gap-1">
+                <Lightbulb class="w-4 h-4" />
+                一键开启
+              </div>
+            </ElButton>
+            <ElButton
+                type="danger"
+                :disabled="!isOnline"
+                @click="turnOff"
+                class="flex-1"
+            >
+              <div class="flex items-center justify-center gap-1">
+                <Power class="w-4 h-4" />
+                一键关闭
+              </div>
+            </ElButton>
+          </div>
+
+          <!-- 亮度控制 -->
+          <div class="slider-container bg-gray-50 p-4 rounded-lg mb-4">
+            <div class="flex items-center gap-2 mb-2">
+              <Lightbulb :class="Number(brightness) > 0 ? 'text-amber-400' : 'text-gray-400'" />
+              <span class="font-medium">亮度控制</span>
+              <span class="ml-auto text-lg font-bold">{{ brightness }}%</span>
+            </div>
+            <ElSlider
+                v-model="brightness"
+                :step="10"
+                :max="100"
+                :min="0"
+                @change="control"
+                :disabled="!isOnline"
+                class="mt-4"
+            />
+            <div class="flex justify-between text-xs text-gray-500 mt-1">
+              <span>关闭</span>
+              <span>最大亮度</span>
+            </div>
+          </div>
+        </ElCard>
+
+        <!-- 详细信息卡片 -->
+        <ElCard class="shadow-sm">
+          <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+            <!-- 电力信息 -->
+            <div>
+              <h3 class="text-base font-medium mb-4 flex items-center gap-2">
+                <Zap class="text-yellow-500" />
+                电力信息
+              </h3>
+              <div class="grid grid-cols-2 gap-4">
+                <div class="flex flex-col">
+                  <div class="text-sm text-gray-500">电压</div>
+                  <div class="text-lg font-medium flex items-center gap-1">
+                    <Gauge class="w-4 h-4 text-blue-500" />
+                    {{ formatNumber(poleInfo.voltage) }} V
+                  </div>
+                </div>
+                <div class="flex flex-col">
+                  <div class="text-sm text-gray-500">电流</div>
+                  <div class="text-lg font-medium flex items-center gap-1">
+                    <Zap class="w-4 h-4 text-orange-500" />
+                    {{ formatNumber(poleInfo.current) }} A
+                  </div>
+                </div>
+                <div class="flex flex-col">
+                  <div class="text-sm text-gray-500">功率</div>
+                  <div class="text-lg font-medium flex items-center gap-1">
+                    <Power class="w-4 h-4 text-red-500" />
+                    {{ formatNumber(poleInfo.power) }} W
+                  </div>
+                </div>
+                <div class="flex flex-col">
+                  <div class="text-sm text-gray-500">电量</div>
+                  <div class="text-lg font-medium flex items-center gap-1">
+                    <Battery class="w-4 h-4 text-green-500" />
+                    {{ formatNumber(poleInfo.power_quantity) }} kWh
+                  </div>
+                </div>
+              </div>
+            </div>
+
+            <!-- 使用信息 -->
+            <div>
+              <h3 class="text-base font-medium mb-4 flex items-center gap-2">
+                <Clock class="text-purple-500" />
+                使用信息
+              </h3>
+              <div class="flex flex-col gap-4">
+                <div class="flex flex-col">
+                  <div class="text-sm text-gray-500">累计开启时间</div>
+                  <div class="text-lg font-medium flex items-center gap-1">
+                    <Clock class="w-4 h-4 text-blue-500" />
+                    {{ formatTime(poleInfo.light_total_time) }}
+                  </div>
+                </div>
+                <div class="flex flex-col">
+                  <div class="text-sm text-gray-500">当前亮度</div>
+                  <div class="text-lg font-medium flex items-center gap-1">
+                    <Lightbulb :class="Number(poleInfo.brightness) > 0 ? 'text-amber-400 w-4 h-4' : 'text-gray-400 w-4 h-4'" />
+                    {{ poleInfo.brightness || '0' }}%
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </ElCard>
+      </template>
+    </ElSkeleton>
+  </div>
 </template>
 
-<style scoped lang="scss">
+<style scoped>
+.light-pole-detail {
+  display: flex;
+  flex-direction: column;
+}
+
+.light-pole-detail .el-card {
+  margin-bottom: 16px;
+}
+
+.light-pole-detail .el-slider__runway {
+  height: 8px;
+  border-radius: 4px;
+}
+
+.light-pole-detail .el-slider__bar {
+  height: 8px;
+  border-radius: 4px;
+  background-color: #f59e0b;
+}
+
+.light-pole-detail .el-slider__button {
+  width: 20px;
+  height: 20px;
+  border: 2px solid #f59e0b;
+}
 
+/* 确保内容铺满整个dialog */
+.light-pole-detail .el-card__body {
+  padding: 16px;
+}
+
+.light-pole-detail .el-button {
+  font-weight: 500;
+}
 </style>