Преглед изворни кода

feat(zhdb): 添加电表数据统计功能

- 新增 dbtj.vue 组件,实现电表数据统计和展示
-集成 ECharts 图表库,用于展示各公司用电量对比
- 使用 ElStatistic 组件展示统计数值
- 添加数据表格展示详细电表读数信息
- 优化样式,增加卡片和表格的自定义样式
nahida пре 8 месеци
родитељ
комит
176f97e841
2 измењених фајлова са 344 додато и 0 уклоњено
  1. 2 0
      components.d.ts
  2. 342 0
      src/views/zhdb/dbtj.vue

+ 2 - 0
components.d.ts

@@ -35,6 +35,7 @@ declare module 'vue' {
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
     ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
+    ElStatistic: typeof import('element-plus/es')['ElStatistic']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
@@ -44,6 +45,7 @@ declare module 'vue' {
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
     ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
+    ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']
     IconDocumentation: typeof import('./src/components/icons/IconDocumentation.vue')['default']

+ 342 - 0
src/views/zhdb/dbtj.vue

@@ -0,0 +1,342 @@
+<script setup lang="ts">
+import { ref, onMounted, computed } from 'vue'
+import { ElMessage, ElCard, ElRow, ElCol, ElStatistic, ElTable, ElTableColumn } from 'element-plus'
+import * as echarts from 'echarts'
+import { Zap, Building2, Hash, TrendingUp, Activity, BarChart3 } from 'lucide-vue-next'
+import { clientGet } from '@/utils/request.ts'
+
+interface BaseResponse {
+  code: number
+  msg: string
+}
+
+interface ElectricDataResponse extends BaseResponse {
+  data: {
+    dailyElectricity: number
+    totalElectricity: number
+    electricNumber: string
+    companyName: string
+  }[]
+}
+
+const electricData = ref<ElectricDataResponse['data']>([])
+const loading = ref(true)
+const chartInstance = ref<echarts.ECharts>()
+
+// 模拟API调用 - 替换为你的实际API
+const getData = async () => {
+  try {
+    const res = await clientGet<null, ElectricDataResponse>("/infrared/infraredReadingMeter/dailyAndTotalMap")
+
+    if (res.code !== 200) {
+      ElMessage.error(res.msg)
+      return
+    }
+    console.log(res.data)
+    electricData.value = res.data
+    initChart()
+  } catch (error) {
+    ElMessage.error('获取数据失败')
+  } finally {
+    loading.value = false
+  }
+}
+
+// 计算统计数据
+const statistics = computed(() => {
+  const data = electricData.value
+  return {
+    totalCompanies: data.length,
+    totalDailyElectricity: data.reduce((sum, item) => sum + item.dailyElectricity, 0),
+    totalElectricitySum: data.reduce((sum, item) => sum + item.totalElectricity, 0),
+    avgDailyElectricity: data.length > 0 ? data.reduce((sum, item) => sum + item.dailyElectricity, 0) / data.length : 0
+  }
+})
+
+// 初始化图表
+const initChart = () => {
+  const chartDom = document.getElementById('electricChart')
+  if (!chartDom) return
+
+  chartInstance.value = echarts.init(chartDom)
+
+  const option = {
+    title: {
+      text: '各公司用电量对比',
+      left: 'center',
+      textStyle: {
+        color: '#333',
+        fontSize: 16,
+        fontWeight: 'bold'
+      }
+    },
+    tooltip: {
+      trigger: 'item',
+      formatter: (params: any) => {
+        const dataIndex = params.dataIndex
+        const companyData = electricData.value[dataIndex]
+        // 处理公司名为空的情况
+        const companyName = companyData.companyName || '未知公司'
+        return `
+          <div style="padding: 12px; border-radius: 6px;">
+            <div style="font-weight: bold; margin-bottom: 8px; color: #333;">${companyName}</div>
+            <div style="margin-bottom: 4px;"><span style="color: #409EFF;">电表号:</span> ${companyData.electricNumber}</div>
+            <div style="margin-bottom: 4px;"><span style="color: #67C23A;">当日用电量:</span> ${companyData.dailyElectricity} kWh</div>
+          </div>
+        `
+      }
+    },
+    // 让图表尽量占满
+    grid: {
+      top: 60,
+      left: '5%',
+      right: '5%',
+      bottom: '5%',
+      containLabel: true
+    },
+    // 用电量数值在 x 轴
+    xAxis: {
+      type: 'value',
+      name: '用电量 (kWh)',
+      axisLabel: {
+        formatter: '{value}'
+      }
+    },
+    // 公司名在 y 轴
+    yAxis: {
+      type: 'category',
+      data: electricData.value.map(item => item.companyName || '未知公司'),
+      axisLabel: {
+        fontSize: 12,
+        formatter: (value: string) => {
+          const maxLength = 8 // 每行最多 8 个字
+          if (value.length > maxLength) {
+            return value.match(new RegExp('.{1,' + maxLength + '}', 'g'))!.join('\n')
+          }
+          return value
+        }
+      }
+    },
+    series: [
+      {
+        name: '当日用电量',
+        type: 'bar',
+        data: electricData.value.map(item => item.dailyElectricity),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
+            { offset: 0, color: '#409EFF' },
+            { offset: 1, color: '#79bbff' }
+          ])
+        },
+        emphasis: {
+          itemStyle: {
+            color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
+              { offset: 0, color: '#337ecc' },
+              { offset: 1, color: '#409EFF' }
+            ])
+          }
+        }
+      }
+    ]
+  }
+
+  chartInstance.value.setOption(option)
+}
+
+
+onMounted(() => {
+  getData()
+})
+</script>
+
+<template>
+  <div class="electricity-dashboard p-6 bg-gray-50 min-h-screen">
+    <!-- 页面标题 -->
+    <div class="mb-6">
+      <h1 class="text-3xl font-bold text-gray-800 flex items-center gap-3">
+        <Zap class="text-yellow-500" :size="32" />
+        电表数据统计
+      </h1>
+      <p class="text-gray-600 mt-2">实时监控各公司用电情况</p>
+    </div>
+
+    <!-- 统计卡片 -->
+    <ElRow :gutter="20" class="mb-6">
+      <ElCol :xs="24" :sm="12" :md="6">
+        <ElCard class="stat-card">
+          <div class="flex items-center justify-between">
+            <div>
+              <ElStatistic
+                title="监控公司数量"
+                :value="statistics.totalCompanies"
+                suffix="家"
+                class="text-blue-600"
+              />
+            </div>
+            <Building2 class="text-blue-500" :size="40" />
+          </div>
+        </ElCard>
+      </ElCol>
+
+      <ElCol :xs="24" :sm="12" :md="6">
+        <ElCard class="stat-card">
+          <div class="flex items-center justify-between">
+            <div>
+              <ElStatistic
+                title="今日总用电量"
+                :value="statistics.totalDailyElectricity"
+                :precision="1"
+                suffix="kWh"
+                class="text-green-600"
+              />
+            </div>
+            <Activity class="text-green-500" :size="40" />
+          </div>
+        </ElCard>
+      </ElCol>
+
+      <ElCol :xs="24" :sm="12" :md="6">
+        <ElCard class="stat-card">
+          <div>
+            <ElStatistic
+              title="累计总用电量"
+              :value="statistics.totalElectricitySum"
+              :precision="1"
+              suffix="kWh"
+              class="text-purple-600"
+            />
+          </div>
+          <TrendingUp class="text-purple-500" :size="40" />
+        </ElCard>
+      </ElCol>
+
+      <ElCol :xs="24" :sm="12" :md="6">
+        <ElCard class="stat-card">
+          <div class="flex items-center justify-between">
+            <div>
+              <ElStatistic
+                title="日均用电量"
+                :value="statistics.avgDailyElectricity"
+                :precision="1"
+                suffix="kWh"
+                class="text-orange-600"
+              />
+            </div>
+            <BarChart3 class="text-orange-500" :size="40" />
+          </div>
+        </ElCard>
+      </ElCol>
+    </ElRow>
+
+    <!-- 图表区域 -->
+    <ElRow :gutter="20" class="mb-6">
+      <ElCol :span="24">
+        <ElCard>
+          <div id="electricChart" style="width: 100%; height: 400px;"></div>
+        </ElCard>
+      </ElCol>
+    </ElRow>
+
+    <!-- 数据表格 -->
+    <ElCard>
+      <template #header>
+        <div class="flex items-center gap-2">
+          <Hash class="text-gray-600" :size="20" />
+          <span class="font-semibold">详细数据列表</span>
+        </div>
+      </template>
+
+      <ElTable
+        :data="electricData"
+        :loading="loading"
+        stripe
+        style="width: 100%"
+        class="custom-table"
+      >
+        <ElTableColumn prop="companyName" label="公司名称" min-width="150">
+          <template #default="{ row }">
+            <div class="flex items-center gap-2">
+              <Building2 class="text-blue-500" :size="16" />
+              <!-- 处理公司名为空的情况 -->
+              <span class="font-medium">{{ row.companyName || '未知公司' }}</span>
+            </div>
+          </template>
+        </ElTableColumn>
+
+        <ElTableColumn prop="electricNumber" label="电表号" min-width="120">
+          <template #default="{ row }">
+            <div class="flex items-center gap-2">
+              <Hash class="text-gray-500" :size="16" />
+              <span class="font-mono text-sm">{{ row.electricNumber }}</span>
+            </div>
+          </template>
+        </ElTableColumn>
+
+        <ElTableColumn prop="dailyElectricity" label="当日用电量 (kWh)" min-width="140" sortable>
+          <template #default="{ row }">
+            <div class="flex items-center gap-2">
+              <Activity class="text-green-500" :size="16" />
+              <span class="font-semibold text-green-600">{{ row.dailyElectricity.toFixed(1) }}</span>
+            </div>
+          </template>
+        </ElTableColumn>
+
+        <ElTableColumn prop="totalElectricity" label="总用电量 (kWh)" min-width="140" sortable>
+          <template #default="{ row }">
+            <div class="flex items-center gap-2">
+              <TrendingUp class="text-purple-500" :size="16" />
+              <span class="font-semibold text-purple-600">{{ row.totalElectricity.toLocaleString() }}</span>
+            </div>
+          </template>
+        </ElTableColumn>
+      </ElTable>
+    </ElCard>
+  </div>
+</template>
+
+<style scoped>
+.electricity-dashboard {
+  font-family: 'Inter', sans-serif;
+}
+
+.stat-card {
+  transition: all 0.3s ease;
+  border: none;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+}
+
+.stat-card:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
+}
+
+.custom-table {
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+:deep(.el-card__body) {
+  padding: 20px;
+}
+
+:deep(.el-statistic__content) {
+  font-size: 24px;
+  font-weight: bold;
+}
+
+:deep(.el-statistic__title) {
+  font-size: 14px;
+  color: #666;
+  margin-bottom: 8px;
+}
+
+:deep(.el-table th) {
+  background-color: #f8fafc;
+  color: #374151;
+  font-weight: 600;
+}
+
+:deep(.el-table td) {
+  padding: 16px 0;
+}
+</style>