|
|
@@ -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>
|