ソースを参照

修改井盖页面

丁烨烨 1 年間 前
コミット
c7cd227712

BIN
src/assets/visualizationimg/1.png


BIN
src/assets/visualizationimg/all.png


+ 118 - 153
src/components/baseEcharts/index.vue

@@ -1,178 +1,143 @@
 <template>
-    <div class="container-echart">
-        <div :id="'echart' + timeId" class="interface-echart"></div>
-    </div>
+  <div class="container-echart">
+    <div :id="'echart' + timeId" class="interface-echart"></div>
+  </div>
 </template>
 <script lang="ts" setup>
-import * as echarts from 'echarts'
-import { EChartsType } from 'echarts'
-import { onMounted, ref, watch, onBeforeUnmount, nextTick } from 'vue'
+import * as echarts from "echarts";
+import { EChartsType } from "echarts";
+import { onMounted, ref, watch, onBeforeUnmount, nextTick } from "vue";
 
 const props = defineProps({
-    NamechartData: {
-        // 柱形图x轴数据
-        type: Array,
-        default: true
-    },
-    ArrOneData: {
-        // 柱形图x轴数据
-        type: Array,
-        default: true
-    },
-    ArrTwoData: {
-        // 柱形图x轴数据
-        type: Array,
-        default: true
-    }
-})
-console.log(props);
+  NamechartData: {
+    // 柱形图x轴数据
+    type: Array,
+    default: true,
+  },
+  ArrOneData: {
+    // 柱形图x轴数据
+    type: Array,
+    default: true,
+  },
+  ArrTwoData: {
+    // 柱形图x轴数据
+    type: Array,
+    default: true,
+  },
+});
 
-let myEchart: EChartsType
+let myEchart: EChartsType;
 const timeId = ref(Math.floor(new Date().getTime() * Math.random())); // 使该图表保持唯id
 const myEchartData = () => {
-    const option = {
-        legend: {
-            //图标信息提示
-            type: 'scroll',
-            left: '40%',
-            top: 0,
-            align: 'auto',
-            icon: 'circle', 
-            textStyle: {
-                color: "white"
-            }
-        },
-        grid: {
-            //图表距离边框的偏离
-            right: '8%', //图表距离容器右侧距离
-            left: '12%',
-            top: '20%',
-            bottom: '20%'
-        },
-        tooltip: { trigger: 'axis' }, // 设置图案和容器的距离
-        xAxis: {
-            type: 'category',
-            nameLocation: 'end',
-            data: props.NamechartData
-        },
-        yAxis: {
-            type: 'value',
-            nameLocation: 'end',
-            // 坐标轴轴线
-            axisLine: {
-                show: false
-            },
-            // 坐标轴刻度
-            axisTick: {
-                show: false
-            },
-            min: 0,
-            splitLine: {
-                show: false // 不显示网格线
-            }
-            // axisLabel: { formatter: '{value} ' },
-        },
-        series: [
-            {
-                name: '2023',
-                type: 'bar',
-                data: props.ArrOneData
-            },
-            {
-                name: '2024',
-                type: 'bar',
-                data: props.ArrTwoData
-            }
-        ],
-        dataZoom: [
-            // 数据选择范围 最下面的范围拉条
-            {
-                type: 'slider', // 开启滑动条
-                show: true, // 显示缩放条
-                start: 0,
-                end: 100,
-                backgroundColor: '#26CAF026',
-                selectedDataBackground: {
-                    lineStyle: {
-                        type: 'dotted'
-                    },
-                    areaStyle: {
-                        color: '#26CAF0'
-                    }
-                },
-                bottom: '3%',
-                height: 14,
-                brushSelect: false,
-            }
-        ]
-    }
-    // { notMerge: true } 解决删除数据时,数据不刷新的问题
-    myEchart.setOption(option, { notMerge: true })
-}
+  const option = {
+    tooltip: {
+      trigger: "axis",
+    },
+    legend: {
+      data: ["翻转", "水浸", "水位"],
+    },
+    grid: {
+      left: "3%",
+      right: "4%",
+      bottom: "3%",
+      containLabel: true,
+    },
+    xAxis: {
+      type: "category",
+      boundaryGap: false,
+      data: ["一月", "二月", "三月", "四月", "五月", "六月", "七月"],
+    },
+    yAxis: {
+      type: "value",
+    },
+    series: [
+      {
+        name: "翻转",
+        type: "line",
+        stack: "Total",
+        data: [120, 132, 101, 134, 90, 230, 210],
+      },
+      {
+        name: "水浸",
+        type: "line",
+        stack: "Total",
+        data: [220, 182, 191, 234, 290, 330, 310],
+      },
+      {
+        name: "水位",
+        type: "line",
+        stack: "Total",
+        data: [150, 232, 201, 154, 190, 330, 410],
+      },
+    ],
+  };
+  // { notMerge: true } 解决删除数据时,数据不刷新的问题
+  myEchart.setOption(option, { notMerge: true });
+};
 
 watch(
-    //监控数据变化
-    () => props.NamechartData,
-    () => {
-        setTimeout(() => {
-            myEchartData()
-        }, 500)
-    },
-    { deep: true }
-)
+  //监控数据变化
+  () => props.NamechartData,
+  () => {
+    setTimeout(() => {
+      myEchartData();
+    }, 500);
+  },
+  { deep: true }
+);
 
 watch(
-    //监控数据变化
-    () => props.ArrOneData,
-    () => {
-        setTimeout(() => {
-            myEchartData()
-        }, 500)
-    },
-    { deep: true }
-)
+  //监控数据变化
+  () => props.ArrOneData,
+  () => {
+    setTimeout(() => {
+      myEchartData();
+    }, 500);
+  },
+  { deep: true }
+);
 
 watch(
-    //监控数据变化
-    () => props.ArrTwoData,
-    () => {
-        setTimeout(() => {
-            myEchartData()
-        }, 500)
-    },
-    { deep: true }
-)
+  //监控数据变化
+  () => props.ArrTwoData,
+  () => {
+    setTimeout(() => {
+      myEchartData();
+    }, 500);
+  },
+  { deep: true }
+);
 
 onMounted(() => {
-    setTimeout(() => {
-        const dom = document.getElementById(`echart${timeId.value}`) as any
-        myEchart = echarts.init(dom)
-        myEchartData()
-    }, 500)
+  setTimeout(() => {
+    const dom = document.getElementById(`echart${timeId.value}`) as any;
+    myEchart = echarts.init(dom);
+    myEchartData();
+  }, 500);
 
-    // 当窗口发生变化时
-    window.addEventListener('resize', () => {
-        myEchart.resize()
-    })
-})
+  // 当窗口发生变化时
+  window.addEventListener("resize", () => {
+    myEchart.resize();
+  });
+});
 onBeforeUnmount(() => {
-    window.removeEventListener('resize', () => {
-        myEchart.resize()
-    })
-})
+  window.removeEventListener("resize", () => {
+    myEchart.resize();
+  });
+});
 </script>
 <style scoped lang="scss">
 .container-echart {
-    width: 100%;
-    height: 100%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    overflow: hidden;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  overflow: hidden;
 }
 
 .interface-echart {
-    width: 100%;
-    height: 100%;
+  width: 100%;
+  height: 100%;
 }
-</style>
+</style>

+ 99 - 99
src/components/baseEcharts/pieChart.vue

@@ -1,108 +1,108 @@
 <template>
-	<div class="container-echart">
-		<div :id="'echart' + timeId" class="interface-echart"></div>
-	</div>
+  <div class="container-echart">
+    <div :id="'echart' + timeId" class="interface-echart"></div>
+  </div>
 </template>
 <script lang="ts" setup>
-	import * as echarts from 'echarts'
-	import { EChartsType } from 'echarts'
-	import { onMounted, ref, watch, onBeforeUnmount, nextTick } from 'vue'
+import * as echarts from "echarts";
+import { EChartsType } from "echarts";
+import { onMounted, ref, watch, onBeforeUnmount, nextTick } from "vue";
 
-	const props = defineProps({
-		message: {
-			type: Array,
-			default: true
-		}
-	})
+const props = defineProps({
+  message: {
+    type: Array,
+    default: true,
+  },
+});
 
-	let myEchart : EChartsType
-	const timeId = ref(Math.floor(new Date().getTime() * Math.random())); // 使该图表保持唯id
-	const myEchartData = () => {
-		const option = {
-			tooltip: {
-				show: true,
-				trigger: 'item',
-				formatter: "{b}: {c}台   ({d}%)"
-			},
-			title: {
-				text: '设备数量',
-				subtext: '451',
-				x: 'center',
-				y: '100',
-				textStyle: {
-					fontWeight: 'bold',
-					fontSize: 20,
-					color: 'white'
-				},
-				subtextStyle:{
-					fontSize: 22,
-					color: 'white'
-				}
-			},
-			series: [
-				{
-					name: 'Access From',
-					type: 'pie',
-					radius: ['60%', '80%'],
-					avoidLabelOverlap: false,
-					itemStyle: {
-						borderRadius: 10,
-						borderWidth: 2
-					},
-					label: {
-						show: false,
-						position: 'center'
-					},
-					labelLine: {
-						show: false
-					},
-					data: props.message
-				}
-			]
-		};
-		// { notMerge: true } 解决删除数据时,数据不刷新的问题
-		myEchart.setOption(option, { notMerge: true })
-	}
-	watch(
-		//监控数据变化
-		() => props.message,
-		() => {
-			setTimeout(() => {
-				myEchartData()
-			}, 500)
-		},
-		{ deep: true }
-	)
-	onMounted(() => {
-		setTimeout(() => {
-			const dom = document.getElementById(`echart${timeId.value}`) as any
-			myEchart = echarts.init(dom)
-			myEchartData()
-		}, 500)
+let myEchart: EChartsType;
+const timeId = ref(Math.floor(new Date().getTime() * Math.random())); // 使该图表保持唯id
+const myEchartData = () => {
+  const option = {
+    tooltip: {
+      show: true,
+      trigger: "item",
+      formatter: "{b}: {c}台   ({d}%)",
+    },
+    // title: {
+    //   text: "设备数量",
+    //   subtext: "451",
+    //   x: "center",
+    //   y: "100",
+    //   textStyle: {
+    //     fontWeight: "bold",
+    //     fontSize: 20,
+    //     color: "white",
+    //   },
+    //   subtextStyle: {
+    //     fontSize: 22,
+    //     color: "white",
+    //   },
+    // },
+    series: [
+      {
+        name: "Access From",
+        type: "pie",
+        // radius: ['60%', '80%'],
+        avoidLabelOverlap: false,
+        itemStyle: {
+          borderRadius: 10,
+          borderWidth: 2,
+        },
+        label: {
+          show: false,
+          position: "center",
+        },
+        labelLine: {
+          show: false,
+        },
+        data: props.message,
+      },
+    ],
+  };
+  // { notMerge: true } 解决删除数据时,数据不刷新的问题
+  myEchart.setOption(option, { notMerge: true });
+};
+watch(
+  //监控数据变化
+  () => props.message,
+  () => {
+    setTimeout(() => {
+      myEchartData();
+    }, 500);
+  },
+  { deep: true }
+);
+onMounted(() => {
+  setTimeout(() => {
+    const dom = document.getElementById(`echart${timeId.value}`) as any;
+    myEchart = echarts.init(dom);
+    myEchartData();
+  }, 500);
 
-		// 当窗口发生变化时
-		window.addEventListener('resize', () => {
-			myEchart.resize()
-		})
-	})
-	onBeforeUnmount(() => {
-		window.removeEventListener('resize', () => {
-			myEchart.resize()
-		})
-	})
+  // 当窗口发生变化时
+  window.addEventListener("resize", () => {
+    myEchart.resize();
+  });
+});
+onBeforeUnmount(() => {
+  window.removeEventListener("resize", () => {
+    myEchart.resize();
+  });
+});
 </script>
 <style scoped lang="scss">
-	.container-echart {
-		width: 100%;
-		height: 100%;
-		display: flex;
-		justify-content: center;
-		align-items: center;
-		overflow: hidden;
-	}
+.container-echart {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  overflow: hidden;
+}
 
-	.interface-echart {
-		width: 100%;
-		height: 100%;
-	}
-</style>
+.interface-echart {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 286 - 0
src/components/baseEcharts/riEcharts.vue

@@ -0,0 +1,286 @@
+<template>
+  <div class="container-echart">
+    <div :id="'echart' + timeId" class="interface-echart"></div>
+  </div>
+</template>
+<script lang="ts" setup>
+import * as echarts from "echarts";
+import { EChartsType } from "echarts";
+import { onMounted, ref, watch, onBeforeUnmount, nextTick } from "vue";
+
+const props = defineProps({
+  NamechartData: {
+    // 柱形图x轴数据
+    type: Array,
+    default: true,
+  },
+  ArrOneData: {
+    // 柱形图x轴数据
+    type: Array,
+    default: true,
+  },
+  ArrTwoData: {
+    // 柱形图x轴数据
+    type: Array,
+    default: true,
+  },
+});
+
+let myEchart: EChartsType;
+const timeId = ref(Math.floor(new Date().getTime() * Math.random())); // 使该图表保持唯id
+const myEchartData = () => {
+  const option = {
+    tooltip: {
+      trigger: "axis",
+    },
+    legend: {
+      data: ["翻转", "水浸", "水位"],
+    },
+    grid: {
+      left: "3%",
+      right: "4%",
+      bottom: "3%",
+      containLabel: true,
+    },
+    xAxis: {
+      type: "category",
+      boundaryGap: false,
+      data: [
+        "01",
+        "02",
+        "03",
+        "04",
+        "05",
+        "06",
+        "07",
+        "08",
+        "09",
+        "12",
+        "11",
+        "12",
+        "13",
+        "14",
+        "15",
+        "16",
+        "17",
+        "18",
+        "19",
+        "20",
+        "22",
+        "22",
+        "23",
+        "24",
+        "25",
+        "26",
+        "27",
+        "28",
+        "29",
+        "30",
+        "31",
+      ],
+    },
+    yAxis: {
+      type: "value",
+    },
+    series: [
+      {
+        name: "翻转",
+        type: "bar",
+        stack: "total",
+        data: [
+          2.0,
+          4.9,
+          7.0,
+          23.2,
+          25.6,
+          76.7,
+          135.6,
+          162.2,
+          32.6,
+          20.0,
+          6.4,
+          3.3,
+          2.0,
+          4.9,
+          7.0,
+          23.2,
+          25.6,
+          76.7,
+          135.6,
+          162.2,
+          32.6,
+          20.0,
+          6.4,
+          3.3,
+          2.0,
+          4.9,
+          7.0,
+          23.2,
+          25.6,
+          76.7,
+          135.6,
+          162.2,
+          32.6,
+          20.0,
+          6.4,
+          3.3,
+        ],
+      },
+      {
+        name: "水浸",
+        type: "bar",
+        stack: "total",
+        data: [
+          2.6,
+          5.9,
+          9.0,
+          26.4,
+          28.7,
+          70.7,
+          175.6,
+          182.2,
+          48.7,
+          18.8,
+          6.0,
+          2.3,
+          2.0,
+          4.9,
+          7.0,
+          23.2,
+          25.6,
+          76.7,
+          135.6,
+          162.2,
+          32.6,
+          20.0,
+          6.4,
+          3.3,
+          2.0,
+          4.9,
+          7.0,
+          23.2,
+          25.6,
+          76.7,
+          135.6,
+          162.2,
+          32.6,
+          20.0,
+          6.4,
+          3.3,
+        ],
+      },
+      {
+        name: "水位",
+        type: "bar",
+        stack: "total",
+        data: [
+          2.6,
+          5.9,
+          9.0,
+          26.4,
+          28.7,
+          70.7,
+          175.6,
+          182.2,
+          48.7,
+          18.8,
+          6.0,
+          2.3,
+          2.0,
+          4.9,
+          7.0,
+          23.2,
+          25.6,
+          76.7,
+          135.6,
+          162.2,
+          32.6,
+          20.0,
+          6.4,
+          3.3,
+          2.0,
+          4.9,
+          7.0,
+          23.2,
+          25.6,
+          76.7,
+          135.6,
+          162.2,
+          32.6,
+          20.0,
+          6.4,
+          3.3,
+        ],
+      },
+    ],
+  };
+  // { notMerge: true } 解决删除数据时,数据不刷新的问题
+  myEchart.setOption(option, { notMerge: true });
+};
+
+watch(
+  //监控数据变化
+  () => props.NamechartData,
+  () => {
+    setTimeout(() => {
+      myEchartData();
+    }, 500);
+  },
+  { deep: true }
+);
+
+watch(
+  //监控数据变化
+  () => props.ArrOneData,
+  () => {
+    setTimeout(() => {
+      myEchartData();
+    }, 500);
+  },
+  { deep: true }
+);
+
+watch(
+  //监控数据变化
+  () => props.ArrTwoData,
+  () => {
+    setTimeout(() => {
+      myEchartData();
+    }, 500);
+  },
+  { deep: true }
+);
+
+onMounted(() => {
+  setTimeout(() => {
+    const dom = document.getElementById(`echart${timeId.value}`) as any;
+    myEchart = echarts.init(dom);
+    myEchartData();
+  }, 500);
+
+  // 当窗口发生变化时
+  window.addEventListener("resize", () => {
+    myEchart.resize();
+  });
+});
+onBeforeUnmount(() => {
+  window.removeEventListener("resize", () => {
+    myEchart.resize();
+  });
+});
+</script>
+<style scoped lang="scss">
+.container-echart {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  overflow: hidden;
+}
+
+.interface-echart {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 21 - 18
src/views/device/electricity/index.vue

@@ -3,10 +3,10 @@
     <el-container class="h-90vh">
       <el-aside class="bg-gray-100 w-60">
         <el-menu
-            :default-active="activeMenu"
-            mode="vertical"
-            @select="handleMenuSelect"
-            class="h-full border-r-0"
+          :default-active="activeMenu"
+          mode="vertical"
+          @select="handleMenuSelect"
+          class="h-full border-r-0"
         >
           <el-menu-item index="deviceList">
             <template #title>
@@ -17,17 +17,20 @@
         </el-menu>
       </el-aside>
       <el-main class="p-0">
-        <component :is="currentComponent" @show-details="showElectricityDetails"></component>
+        <component
+          :is="currentComponent"
+          @show-details="showElectricityDetails"
+        ></component>
       </el-main>
     </el-container>
 
     <!-- Full-screen dialog for electricity details -->
     <el-dialog
-        v-model="dialogVisible"
-        :fullscreen="true"
-        :show-close="true"
-        :destroy-on-close="false"
-        class="electricity-detail-dialog"
+      v-model="dialogVisible"
+      :fullscreen="true"
+      :show-close="true"
+      :destroy-on-close="false"
+      class="electricity-detail-dialog"
     >
       <template #header>
         <div class="flex items-center justify-between w-full">
@@ -44,24 +47,24 @@
 </template>
 
 <script setup>
-import {ref} from 'vue';
-import electricityDetail from './components/electricity-detail.vue';
-import deviceList from './components/device-list.vue';
-import {List, X} from 'lucide-vue-next';
+import { ref } from "vue";
+import electricityDetail from "./components/electricity-detail.vue";
+import deviceList from "./components/device-list.vue";
+import { List, X } from "lucide-vue-next";
 
 // 定义当前激活的菜单索引
-const activeMenu = ref('deviceList');
+const activeMenu = ref("deviceList");
 // 定义当前要显示的组件
 const currentComponent = ref(deviceList);
 
 // 对话框控制
 const dialogVisible = ref(false);
-const selectedTableNumber = ref('');
+const selectedTableNumber = ref("");
 
 // 处理菜单选择事件
 const handleMenuSelect = (index) => {
   activeMenu.value = index;
-  if (index === 'deviceList') {
+  if (index === "deviceList") {
     currentComponent.value = deviceList;
   }
 };
@@ -85,4 +88,4 @@ const showElectricityDetails = (tableNumber) => {
   padding: 16px 20px;
   border-bottom: 1px solid #e4e7ed;
 }
-</style>
+</style>

+ 25 - 0
src/views/device/manhole/ldzh/fzbj.vue

@@ -14,6 +14,30 @@
       <el-button type="primary" @click="search">搜索</el-button>
     </div>
 
+    <div>
+      <el-card shadow="hover" class="mb-4">
+        <template #header>
+          <div class="flex justify-between items-center">
+            <span class="font-bold">井盖统计</span>
+          </div>
+        </template>
+        <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
+          <div class="stat-card bg-blue-50 p-4 rounded-lg">
+            <div class="text-blue-500 text-lg font-medium">当年报警数</div>
+            <div class="text-2xl font-bold mt-2">1</div>
+          </div>
+          <div class="stat-card bg-green-50 p-4 rounded-lg">
+            <div class="text-green-500 text-lg font-medium">当月报警数</div>
+            <div class="text-2xl font-bold mt-2">1</div>
+          </div>
+          <div class="stat-card bg-red-50 p-4 rounded-lg">
+            <div class="text-red-500 text-lg font-medium">当天报警数</div>
+            <div class="text-2xl font-bold mt-2">0</div>
+          </div>
+        </div>
+      </el-card>
+    </div>
+
     <el-table :data="tableData" v-loading="tableLoading" border stripe>
       <el-table-column prop="imeiCardNumber" label="设备编号" width="200" />
       <el-table-column prop="batteryLevel" label="电池电量" />
@@ -78,6 +102,7 @@ const buildQueryParams = () => ({
 
 // 获取数据
 const getManholeAllData = async () => {
+  console.log(12321, parseTime(dateRange.value[0]), parseTime(dateRange.value[1]));
   try {
     tableLoading.value = true;
     const res = await getflipalarmDataAll(buildQueryParams());

+ 429 - 281
src/views/device/manhole/ldzh/jgkl.vue

@@ -1,327 +1,405 @@
 <script setup>
-import {computed, onMounted, ref, watch} from 'vue'
-import {AlertTriangle, Plus, RefreshCw, Search, Trash2, Wifi, WifiOff} from 'lucide-vue-next'
-import {ElMessage, ElMessageBox} from 'element-plus'
-import request from "@/utils/request.js"
-import {getDicts} from "@/api/system/dict/data.js";
-
+import { computed, onMounted, ref, watch } from "vue";
+import {
+  AlertTriangle,
+  Plus,
+  RefreshCw,
+  Search,
+  Trash2,
+  Wifi,
+  WifiOff,
+} from "lucide-vue-next";
+import { ElMessage, ElMessageBox } from "element-plus";
+import request from "@/utils/request.js";
+import { getDicts } from "@/api/system/dict/data.js";
+
+import EchartsTyp from "@/components/baseEcharts/index.vue";
+import pieChart from "@/components/baseEcharts/pieChart.vue";
+import riEcharts from "@/components/baseEcharts/riEcharts.vue";
 // Data
-const deviceArr = ref([])
+const deviceArr = ref([]);
 const search = ref({
-  deviceName: ""
-})
-const loading = ref(false)
-const total = ref(0)
-const currentPage = ref(1)
-const pageSize = ref(10)
+  deviceName: "",
+});
+const loading = ref(false);
+const total = ref(0);
+const currentPage = ref(1);
+const pageSize = ref(10);
 const deviceType = ref({});
 
+const PieChartDataTwo = ref([]);
 
 // 预览对话框
-const previewDialogVisible = ref(false)
-const currentDevice = ref({})
+const previewDialogVisible = ref(false);
+const currentDevice = ref({});
 
 // 编辑对话框
-const editDialogVisible = ref(false)
+const editDialogVisible = ref(false);
 const editForm = ref({
-  id: '',
-  deviceName: '',
-  location: '',
-  remarks: ''
-})
+  id: "",
+  deviceName: "",
+  location: "",
+  remarks: "",
+});
 
 // 新增对话框
-const addDialogVisible = ref(false)
+const addDialogVisible = ref(false);
 const addForm = ref({
-  deviceName: '',
-  deviceNumber: '',
-  type: '1', // 默认值为1,根据之前的查询条件
-  model: '',
-  location: '',
-  remarks: ''
-})
+  deviceName: "",
+  deviceNumber: "",
+  type: "1", // 默认值为1,根据之前的查询条件
+  model: "",
+  location: "",
+  remarks: "",
+});
 const addFormRules = {
-  deviceName: [
-    { required: true, message: '请输入设备名称', trigger: 'blur' }
-  ],
-  deviceNumber: [
-    { required: true, message: '请输入设备编号', trigger: 'blur' }
-  ],
-  model: [
-    { required: true, message: '请输入设备型号', trigger: 'blur' }
-  ],
-  type: [
-    { required: true, message: '请输入设备类型', trigger: 'blur' }
-  ]
-}
-const addFormRef = ref(null)
+  deviceName: [{ required: true, message: "请输入设备名称", trigger: "blur" }],
+  deviceNumber: [{ required: true, message: "请输入设备编号", trigger: "blur" }],
+  model: [{ required: true, message: "请输入设备型号", trigger: "blur" }],
+  type: [{ required: true, message: "请输入设备类型", trigger: "blur" }],
+};
+const addFormRef = ref(null);
 
 // 多选相关
-const multipleSelection = ref([])
-const hasSelected = computed(() => multipleSelection.value.length > 0)
+const multipleSelection = ref([]);
+const hasSelected = computed(() => multipleSelection.value.length > 0);
 
 // Methods
 const getAllDeviceInfo = async () => {
-  loading.value = true
+  loading.value = true;
   try {
     const arr = [
       {
         column: "type",
         type: "eq",
-        value: "1"
-      }
-    ]
+        value: "1",
+      },
+    ];
 
     if (search.value.deviceName) {
       arr.push({
         column: "device_name",
         type: "like",
-        value: search.value.deviceName
-      })
+        value: search.value.deviceName,
+      });
     }
 
     const res = await request.get("/base/devices/findByPage", {
       params: {
         conditionJson: encodeURIComponent(JSON.stringify(arr)),
         pageNum: currentPage.value,
-        pageSize: pageSize.value
-      }
-    })
+        pageSize: pageSize.value,
+      },
+    });
 
     if (res.code !== 200) {
-      ElMessage.error(res.msg)
-      return
+      ElMessage.error(res.msg);
+      return;
     }
 
-    deviceArr.value = res.data.records
-    total.value = res.data.total
+    deviceArr.value = res.data.records;
+    total.value = res.data.total;
   } catch (error) {
-    ElMessage.error('获取设备数据失败')
-    console.error(error)
+    ElMessage.error("获取设备数据失败");
+    console.error(error);
   } finally {
-    loading.value = false
+    loading.value = false;
   }
-}
+};
+
+// 工具方法:生成标准化时间范围
+const generateYearDateRange = () => {
+  const currentYear = new Date().getFullYear();
+  return {
+    start: `${currentYear}-01-01 00:00:00`,
+    end: `${currentYear}-${String(new Date().getMonth() + 1).padStart(2, "0")}-${String(
+      new Date().getDate()
+    ).padStart(2, "0")} 23:59:59`,
+  };
+};
+
+// 工具方法:创建通用查询条件
+const createCondition = (column, status, dateRange) => [
+  { column: column, type: "ne", value: status },
+  {
+    column: "create_time",
+    type: "between",
+    value: `${dateRange.start},${dateRange.end}`,
+  },
+];
+
+// 核心请求方法
+const fetchAlarmData = async (condition) => {
+  const { data } = await request.get("/manholeData/getAll", {
+    params: {
+      conditionJson: encodeURIComponent(JSON.stringify(condition)),
+    },
+  });
+  return data;
+};
+
+// 主方法
+const getyearAllDeviceInfo = () => {
+  try {
+    const { start, end } = generateYearDateRange();
+
+    // 定义报警类型配置
+    const alarmTypes = [
+      { column: "alarm_status", name: "翻转" },
+      { column: "water_infiltration_alarm_status", name: "水浸" },
+      { column: "water_level_alarm_status", name: "水位" },
+    ];
+
+    // 并行发送所有请求
+    Promise.all(
+      alarmTypes.map(async ({ column }) =>
+        fetchAlarmData(createCondition(column, "0", { start, end }))
+      )
+    )
+      .then((res) => {
+        PieChartDataTwo.value = res.map((res, index) => {
+          return {
+            value: res.length,
+            name: alarmTypes[index].name,
+          };
+        });
+      })
+      .catch((error) => {
+        ElMessage.error("获取数据失败");
+      });
+    // 构建图表数据
+  } catch (error) {
+    ElMessage.error("获取设备数据失败");
+    console.error("API Error:", error);
+  } finally {
+    loading.value = false;
+  }
+};
+
+getyearAllDeviceInfo();
 
 const handleSearch = () => {
-  currentPage.value = 1
-  getAllDeviceInfo()
-}
+  currentPage.value = 1;
+  getAllDeviceInfo();
+};
 
 const handleReset = () => {
-  search.value.deviceName = ""
-  currentPage.value = 1
-  getAllDeviceInfo()
-}
+  search.value.deviceName = "";
+  currentPage.value = 1;
+  getAllDeviceInfo();
+};
 
 const handleSizeChange = (val) => {
-  pageSize.value = val
-  getAllDeviceInfo()
-}
+  pageSize.value = val;
+  getAllDeviceInfo();
+};
 
 const handleCurrentChange = (val) => {
-  currentPage.value = val
-  getAllDeviceInfo()
-}
+  currentPage.value = val;
+  getAllDeviceInfo();
+};
 
 // Format date
 const formatDate = (dateString) => {
-  if (!dateString) return '-'
-  const date = new Date(dateString)
-  return date.toLocaleString()
-}
+  if (!dateString) return "-";
+  const date = new Date(dateString);
+  return date.toLocaleString();
+};
 
 // Watch for search changes
-watch(() => search.value.deviceName, (newVal, oldVal) => {
-  if (newVal === '' && oldVal !== '') {
-    handleSearch()
+watch(
+  () => search.value.deviceName,
+  (newVal, oldVal) => {
+    if (newVal === "" && oldVal !== "") {
+      handleSearch();
+    }
   }
-})
+);
 
 // 预览设备信息
 const handlePreview = async (id) => {
   try {
-    const res = await request.get("/base/devices/getById/" + id)
+    const res = await request.get("/base/devices/getById/" + id);
     if (res.code !== 200) {
-      ElMessage.error(res.msg)
-      return
+      ElMessage.error(res.msg);
+      return;
     }
-    currentDevice.value = res.data
-    previewDialogVisible.value = true
+    currentDevice.value = res.data;
+    previewDialogVisible.value = true;
   } catch (error) {
-    ElMessage.error('获取设备详情失败')
-    console.error(error)
+    ElMessage.error("获取设备详情失败");
+    console.error(error);
   }
-}
+};
 
 // 打开编辑对话框
 const openEditDialog = async (id) => {
   try {
-    const res = await request.get("/base/devices/getById/" + id)
+    const res = await request.get("/base/devices/getById/" + id);
     if (res.code !== 200) {
-      ElMessage.error(res.msg)
-      return
+      ElMessage.error(res.msg);
+      return;
     }
 
     editForm.value = {
       id: res.data.id,
       deviceName: res.data.deviceName,
       location: res.data.location,
-      remarks: res.data.remarks
-    }
+      remarks: res.data.remarks,
+    };
 
-    editDialogVisible.value = true
+    editDialogVisible.value = true;
   } catch (error) {
-    ElMessage.error('获取设备详情失败')
-    console.error(error)
+    ElMessage.error("获取设备详情失败");
+    console.error(error);
   }
-}
+};
 
 // 提交编辑表单
 const handleEdit = async () => {
   try {
-    const res = await request.post('/base/devices/update', editForm.value)
+    const res = await request.post("/base/devices/update", editForm.value);
     if (res.code !== 200) {
-      ElMessage.error(res.msg)
-      return
+      ElMessage.error(res.msg);
+      return;
     }
 
-    ElMessage.success('修改成功')
-    editDialogVisible.value = false
-    getAllDeviceInfo() // 刷新列表
+    ElMessage.success("修改成功");
+    editDialogVisible.value = false;
+    getAllDeviceInfo(); // 刷新列表
   } catch (error) {
-    ElMessage.error('修改设备信息失败')
-    console.error(error)
+    ElMessage.error("修改设备信息失败");
+    console.error(error);
   }
-}
+};
 
 // 打开新增对话框
 const openAddDialog = () => {
   addForm.value = {
-    deviceName: '',
-    deviceNumber: '',
-    type: '1',
-    model: '',
-    location: '',
-    remarks: ''
-  }
-  addDialogVisible.value = true
-}
+    deviceName: "",
+    deviceNumber: "",
+    type: "1",
+    model: "",
+    location: "",
+    remarks: "",
+  };
+  addDialogVisible.value = true;
+};
 
 // 提交新增表单
 const handleAdd = async () => {
-  if (!addFormRef.value) return
+  if (!addFormRef.value) return;
 
   addFormRef.value.validate(async (valid) => {
-    if (!valid) return
+    if (!valid) return;
 
     try {
-      const res = await request.post('/base/devices/save', addForm.value)
+      const res = await request.post("/base/devices/save", addForm.value);
 
       if (res.code !== 200) {
-        ElMessage.error(res.msg)
-        return
+        ElMessage.error(res.msg);
+        return;
       }
 
-      ElMessage.success('新增设备成功')
-      addDialogVisible.value = false
-      getAllDeviceInfo() // 刷新列表
+      ElMessage.success("新增设备成功");
+      addDialogVisible.value = false;
+      getAllDeviceInfo(); // 刷新列表
     } catch (error) {
-      ElMessage.error('新增设备失败')
-      console.error(error)
+      ElMessage.error("新增设备失败");
+      console.error(error);
     }
-  })
-}
+  });
+};
 
 // 处理多选
 const handleSelectionChange = (val) => {
-  multipleSelection.value = val
-}
+  multipleSelection.value = val;
+};
 
 // 删除单个设备
 const handleDelete = async (id) => {
   try {
-    await ElMessageBox.confirm('确认删除该设备吗?此操作不可恢复', '警告', {
-      confirmButtonText: '确认',
-      cancelButtonText: '取消',
-      type: 'warning'
-    })
+    await ElMessageBox.confirm("确认删除该设备吗?此操作不可恢复", "警告", {
+      confirmButtonText: "确认",
+      cancelButtonText: "取消",
+      type: "warning",
+    });
 
-    const res = await request.delete('/base/devices/delete', {
-      data: [id]
-    })
+    const res = await request.delete("/base/devices/delete", {
+      data: [id],
+    });
 
     if (res.code !== 200) {
-      ElMessage.error(res.msg)
-      return
+      ElMessage.error(res.msg);
+      return;
     }
 
-    ElMessage.success('删除成功')
-    getAllDeviceInfo() // 刷新列表
+    ElMessage.success("删除成功");
+    getAllDeviceInfo(); // 刷新列表
   } catch (error) {
-    if (error !== 'cancel') {
-      ElMessage.error('删除设备失败')
-      console.error(error)
+    if (error !== "cancel") {
+      ElMessage.error("删除设备失败");
+      console.error(error);
     }
   }
-}
+};
 
 // 批量删除设备
 const handleBatchDelete = async () => {
   if (multipleSelection.value.length === 0) {
-    ElMessage.warning('请至少选择一个设备')
-    return
+    ElMessage.warning("请至少选择一个设备");
+    return;
   }
 
   try {
     await ElMessageBox.confirm(
-        `确认删除选中的 ${multipleSelection.value.length} 个设备吗?此操作不可恢复`,
-        '警告',
-        {
-          confirmButtonText: '确认',
-          cancelButtonText: '取消',
-          type: 'warning'
-        }
-    )
+      `确认删除选中的 ${multipleSelection.value.length} 个设备吗?此操作不可恢复`,
+      "警告",
+      {
+        confirmButtonText: "确认",
+        cancelButtonText: "取消",
+        type: "warning",
+      }
+    );
 
-    const ids = multipleSelection.value.map(item => item.id)
+    const ids = multipleSelection.value.map((item) => item.id);
 
-    const res = await request.delete('/base/devices/delete', {
-      data: ids
-    })
+    const res = await request.delete("/base/devices/delete", {
+      data: ids,
+    });
 
     if (res.code !== 200) {
-      ElMessage.error(res.msg)
-      return
+      ElMessage.error(res.msg);
+      return;
     }
 
-    ElMessage.success('批量删除成功')
-    getAllDeviceInfo() // 刷新列表
+    ElMessage.success("批量删除成功");
+    getAllDeviceInfo(); // 刷新列表
   } catch (error) {
-    if (error !== 'cancel') {
-      ElMessage.error('批量删除设备失败')
-      console.error(error)
+    if (error !== "cancel") {
+      ElMessage.error("批量删除设备失败");
+      console.error(error);
     }
   }
-}
+};
 
 const getDeviceType = async () => {
-  const res = await getDicts('device_type');
-  if(res.code !== 200){
-    ElMessage.error(res.msg)
+  const res = await getDicts("device_type");
+  if (res.code !== 200) {
+    ElMessage.error(res.msg);
     return;
   }
   deviceType.value = res.data?.reduce((acc, cur) => {
     acc[cur.dictValue] = cur.dictLabel;
     return acc;
-  },{})
-  console.log(deviceType.value);
-}
+  }, {});
+  // console.log(deviceType.value);
+};
 
 onMounted(() => {
   getAllDeviceInfo();
   getDeviceType();
-})
+});
 </script>
 
 <template>
@@ -331,22 +409,22 @@ onMounted(() => {
       <div class="text-xl font-bold">设备管理</div>
       <div class="flex gap-2">
         <el-input
-            v-model="search.deviceName"
-            placeholder="搜索设备名称"
-            class="w-64"
-            clearable
-            @keyup.enter="handleSearch"
+          v-model="search.deviceName"
+          placeholder="搜索设备名称"
+          class="w-64"
+          clearable
+          @keyup.enter="handleSearch"
         >
           <template #prefix>
-            <Search class="w-4 h-4 text-gray-400"/>
+            <Search class="w-4 h-4 text-gray-400" />
           </template>
         </el-input>
         <el-button type="primary" @click="handleSearch" class="flex items-center">
-          <Search class="w-4 h-4 mr-1"/>
+          <Search class="w-4 h-4 mr-1" />
           搜索
         </el-button>
         <el-button @click="handleReset" class="flex items-center">
-          <RefreshCw class="w-4 h-4 mr-1"/>
+          <RefreshCw class="w-4 h-4 mr-1" />
           重置
         </el-button>
       </div>
@@ -355,62 +433,101 @@ onMounted(() => {
     <!-- 操作按钮 -->
     <div class="mb-4 flex justify-between">
       <div class="flex gap-2">
-        <el-button
-            type="primary"
-            @click="openAddDialog"
-            class="flex items-center"
-        >
-          <Plus class="w-4 h-4 mr-1"/>
+        <el-button type="primary" @click="openAddDialog" class="flex items-center">
+          <Plus class="w-4 h-4 mr-1" />
           新增设备
         </el-button>
 
         <el-button
-            type="danger"
-            :disabled="!hasSelected"
-            @click="handleBatchDelete"
-            class="flex items-center"
+          type="danger"
+          :disabled="!hasSelected"
+          @click="handleBatchDelete"
+          class="flex items-center"
         >
-          <Trash2 class="w-4 h-4 mr-1"/>
+          <Trash2 class="w-4 h-4 mr-1" />
           批量删除
         </el-button>
         <span class="ml-2 text-gray-500 flex items-center" v-if="hasSelected">
           已选择 {{ multipleSelection.length }} 项
         </span>
       </div>
-
+    </div>
+    <div>
+      <el-card shadow="hover" class="mb-4">
+        <template #header>
+          <div class="flex justify-between items-center">
+            <span class="font-bold">井盖统计</span>
+          </div>
+        </template>
+        <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
+          <div class="stat-card bg-blue-50 p-4 rounded-lg">
+            <div class="text-blue-500 text-lg font-medium">报警年统计</div>
+            <div class="h-80">
+              <!-- <EchartsTyp></EchartsTyp> -->
+              <pieChart :message="PieChartDataTwo"></pieChart>
+            </div>
+          </div>
+          <div class="stat-card bg-green-50 p-4 rounded-lg">
+            <div class="text-green-500 text-lg font-medium">报警月统计</div>
+            <EchartsTyp></EchartsTyp>
+          </div>
+          <div class="stat-card bg-red-50 p-4 rounded-lg">
+            <div class="text-red-500 text-lg font-medium">报警日统计</div>
+            <riEcharts></riEcharts>
+          </div>
+        </div>
+      </el-card>
     </div>
 
     <!-- Table -->
     <el-table
-        :data="deviceArr"
-        border
-        stripe
-        style="width: 100%"
-        v-loading="loading"
-        class="mb-4"
-        @selection-change="handleSelectionChange"
+      :data="deviceArr"
+      border
+      stripe
+      style="width: 100%"
+      v-loading="loading"
+      class="mb-4"
+      @selection-change="handleSelectionChange"
     >
-      <el-table-column type="selection" width="55" align="center"/>
-      <el-table-column type="index" label="序号" width="60" align="center"/>
-      <el-table-column prop="deviceName" label="设备名称" min-width="150" show-overflow-tooltip/>
-      <el-table-column prop="deviceNumber" label="设备编号" min-width="150" show-overflow-tooltip/>
-      <el-table-column prop="model" label="型号" min-width="150" show-overflow-tooltip/>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column type="index" label="序号" width="60" align="center" />
+      <el-table-column
+        prop="deviceName"
+        label="设备名称"
+        min-width="150"
+        show-overflow-tooltip
+      />
+      <el-table-column
+        prop="deviceNumber"
+        label="设备编号"
+        min-width="150"
+        show-overflow-tooltip
+      />
+      <el-table-column prop="model" label="型号" min-width="150" show-overflow-tooltip />
       <el-table-column prop="type" label="类型" min-width="120" show-overflow-tooltip>
-        <template #default="{row}">
-          {{deviceType[row.type]}}
+        <template #default="{ row }">
+          {{ deviceType[row.type] }}
         </template>
       </el-table-column>
-      <el-table-column prop="location" label="位置" min-width="150" show-overflow-tooltip/>
+      <el-table-column
+        prop="location"
+        label="位置"
+        min-width="150"
+        show-overflow-tooltip
+      />
 
       <el-table-column label="在线状态" width="120" align="center">
         <template #default="scope">
           <div class="flex items-center justify-center">
-            <span v-if="scope.row.onlineStatus === 1" class="flex items-center text-green-500">
-              <Wifi class="w-4 h-4 mr-1"/>
+            <span
+              v-if="scope.row.onlineStatus === 1"
+              class="flex items-center text-green-500"
+            >
+              <Wifi class="w-4 h-4 mr-1" />
               在线
             </span>
             <span v-else class="flex items-center text-gray-500">
-              <WifiOff class="w-4 h-4 mr-1"/>
+              <WifiOff class="w-4 h-4 mr-1" />
               离线
             </span>
           </div>
@@ -419,16 +536,24 @@ onMounted(() => {
 
       <el-table-column label="告警状态" width="120" align="center">
         <template #default="scope">
-          <el-tag :type="scope.row.alarmStatus === 0 ? 'success' : 'danger'" effect="dark">
+          <el-tag
+            :type="scope.row.alarmStatus === 0 ? 'success' : 'danger'"
+            effect="dark"
+          >
             <div class="flex items-center">
-              <AlertTriangle v-if="scope.row.alarmStatus === 1" class="w-4 h-4 mr-1"/>
-              {{ scope.row.alarmStatus === 0 ? '正常' : '告警' }}
+              <AlertTriangle v-if="scope.row.alarmStatus === 1" class="w-4 h-4 mr-1" />
+              {{ scope.row.alarmStatus === 0 ? "正常" : "告警" }}
             </div>
           </el-tag>
         </template>
       </el-table-column>
 
-      <el-table-column prop="remarks" label="备注" min-width="150" show-overflow-tooltip/>
+      <el-table-column
+        prop="remarks"
+        label="备注"
+        min-width="150"
+        show-overflow-tooltip
+      />
 
       <el-table-column label="创建时间" min-width="180" show-overflow-tooltip>
         <template #default="scope">
@@ -444,9 +569,19 @@ onMounted(() => {
 
       <el-table-column label="操作" fixed="right" width="220" align="center">
         <template #default="scope">
-          <el-button type="primary" link size="small" @click="handlePreview(scope.row.id)">预览</el-button>
-          <el-button type="primary" link size="small" @click="openEditDialog(scope.row.id)">编辑</el-button>
-          <el-button type="danger" link size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+          <el-button type="primary" link size="small" @click="handlePreview(scope.row.id)"
+            >预览</el-button
+          >
+          <el-button
+            type="primary"
+            link
+            size="small"
+            @click="openEditDialog(scope.row.id)"
+            >编辑</el-button
+          >
+          <el-button type="danger" link size="small" @click="handleDelete(scope.row.id)"
+            >删除</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
@@ -454,55 +589,70 @@ onMounted(() => {
     <!-- Pagination -->
     <div class="flex justify-end">
       <el-pagination
-          v-model:current-page="currentPage"
-          v-model:page-size="pageSize"
-          :page-sizes="[10, 20, 50, 100]"
-          layout="total, sizes, prev, pager, next, jumper"
-          :total="total"
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-          background
+        v-model:current-page="currentPage"
+        v-model:page-size="pageSize"
+        :page-sizes="[10, 20, 50, 100]"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        background
       />
     </div>
 
     <!-- 预览对话框 -->
-    <el-dialog
-        v-model="previewDialogVisible"
-        title="设备详情"
-        width="50%"
-    >
+    <el-dialog v-model="previewDialogVisible" title="设备详情" width="50%">
       <el-descriptions :column="2" border>
-        <el-descriptions-item label="设备名称">{{ currentDevice.deviceName }}</el-descriptions-item>
-        <el-descriptions-item label="设备编号">{{ currentDevice.deviceNumber }}</el-descriptions-item>
-        <el-descriptions-item label="类型">{{ deviceType[currentDevice.type] }}</el-descriptions-item>
-        <el-descriptions-item label="位置">{{ currentDevice.location }}</el-descriptions-item>
-        <el-descriptions-item label="型号">{{ currentDevice.model }}</el-descriptions-item>
+        <el-descriptions-item label="设备名称">{{
+          currentDevice.deviceName
+        }}</el-descriptions-item>
+        <el-descriptions-item label="设备编号">{{
+          currentDevice.deviceNumber
+        }}</el-descriptions-item>
+        <el-descriptions-item label="类型">{{
+          deviceType[currentDevice.type]
+        }}</el-descriptions-item>
+        <el-descriptions-item label="位置">{{
+          currentDevice.location
+        }}</el-descriptions-item>
+        <el-descriptions-item label="型号">{{
+          currentDevice.model
+        }}</el-descriptions-item>
         <el-descriptions-item label="在线状态">
-          <span v-if="currentDevice.onlineStatus === 1" class="flex items-center text-green-500">
-            <Wifi class="w-4 h-4 mr-1"/>
+          <span
+            v-if="currentDevice.onlineStatus === 1"
+            class="flex items-center text-green-500"
+          >
+            <Wifi class="w-4 h-4 mr-1" />
             在线
           </span>
           <span v-else class="flex items-center text-gray-500">
-            <WifiOff class="w-4 h-4 mr-1"/>
+            <WifiOff class="w-4 h-4 mr-1" />
             离线
           </span>
         </el-descriptions-item>
         <el-descriptions-item label="告警状态">
-          <el-tag :type="currentDevice.alarmStatus === 0 ? 'success' : 'danger'" effect="dark">
+          <el-tag
+            :type="currentDevice.alarmStatus === 0 ? 'success' : 'danger'"
+            effect="dark"
+          >
             <div class="flex items-center">
-              <AlertTriangle v-if="currentDevice.alarmStatus === 1" class="w-4 h-4 mr-1"/>
-              {{ currentDevice.alarmStatus === 0 ? '正常' : '告警' }}
+              <AlertTriangle
+                v-if="currentDevice.alarmStatus === 1"
+                class="w-4 h-4 mr-1"
+              />
+              {{ currentDevice.alarmStatus === 0 ? "正常" : "告警" }}
             </div>
           </el-tag>
         </el-descriptions-item>
-        <el-descriptions-item label="备注" :span="2">{{ currentDevice.remarks }}</el-descriptions-item>
-        <el-descriptions-item label="创建时间" :span="2">{{
-            formatDate(currentDevice.createTime)
-          }}
+        <el-descriptions-item label="备注" :span="2">{{
+          currentDevice.remarks
+        }}</el-descriptions-item>
+        <el-descriptions-item label="创建时间" :span="2"
+          >{{ formatDate(currentDevice.createTime) }}
         </el-descriptions-item>
-        <el-descriptions-item label="更新时间" :span="2">{{
-            formatDate(currentDevice.updateTime)
-          }}
+        <el-descriptions-item label="更新时间" :span="2"
+          >{{ formatDate(currentDevice.updateTime) }}
         </el-descriptions-item>
       </el-descriptions>
       <template #footer>
@@ -513,20 +663,19 @@ onMounted(() => {
     </el-dialog>
 
     <!-- 编辑对话框 -->
-    <el-dialog
-        v-model="editDialogVisible"
-        title="编辑设备"
-        width="40%"
-    >
+    <el-dialog v-model="editDialogVisible" title="编辑设备" width="40%">
       <el-form :model="editForm" label-width="100px">
         <el-form-item label="设备名称">
-          <el-input v-model="editForm.deviceName" placeholder="请输入设备名称"/>
+          <el-input v-model="editForm.deviceName" placeholder="请输入设备名称" />
         </el-form-item>
         <el-form-item label="位置">
-          <el-input v-model="editForm.location" placeholder="请输入位置 例如(xxxxx-xxxxx)"/>
+          <el-input
+            v-model="editForm.location"
+            placeholder="请输入位置 例如(xxxxx-xxxxx)"
+          />
         </el-form-item>
         <el-form-item label="备注">
-          <el-input v-model="editForm.remarks" type="textarea" placeholder="请输入备注"/>
+          <el-input v-model="editForm.remarks" type="textarea" placeholder="请输入备注" />
         </el-form-item>
       </el-form>
       <template #footer>
@@ -538,42 +687,41 @@ onMounted(() => {
     </el-dialog>
 
     <!-- 新增对话框 -->
-    <el-dialog
-        v-model="addDialogVisible"
-        title="新增设备"
-        width="40%"
-    >
+    <el-dialog v-model="addDialogVisible" title="新增设备" width="40%">
       <el-form
-          ref="addFormRef"
-          :model="addForm"
-          :rules="addFormRules"
-          label-width="100px"
+        ref="addFormRef"
+        :model="addForm"
+        :rules="addFormRules"
+        label-width="100px"
       >
         <el-form-item label="设备名称" prop="deviceName">
-          <el-input v-model="addForm.deviceName" placeholder="请输入设备名称"/>
+          <el-input v-model="addForm.deviceName" placeholder="请输入设备名称" />
         </el-form-item>
         <el-form-item label="设备编号" prop="deviceNumber">
-          <el-input v-model="addForm.deviceNumber" placeholder="请输入设备编号"/>
+          <el-input v-model="addForm.deviceNumber" placeholder="请输入设备编号" />
         </el-form-item>
         <el-form-item label="型号" prop="model">
-          <el-input v-model="addForm.model" placeholder="请输入型号"/>
+          <el-input v-model="addForm.model" placeholder="请输入型号" />
         </el-form-item>
         <el-form-item label="类型" prop="model">
           <el-select v-model="addForm.type" placeholder="请输入设备型号">
             <el-option
-                v-for="(item,index) in deviceType"
-                :key="item.value"
-                :label="item"
-                :value="index"
-                :disabled="index !== '1'"
+              v-for="(item, index) in deviceType"
+              :key="item.value"
+              :label="item"
+              :value="index"
+              :disabled="index !== '1'"
             />
           </el-select>
         </el-form-item>
         <el-form-item label="位置">
-          <el-input v-model="addForm.location" placeholder="请输入位置 例如(xxxxx-xxxxx)"/>
+          <el-input
+            v-model="addForm.location"
+            placeholder="请输入位置 例如(xxxxx-xxxxx)"
+          />
         </el-form-item>
         <el-form-item label="备注">
-          <el-input v-model="addForm.remarks" type="textarea" placeholder="请输入备注"/>
+          <el-input v-model="addForm.remarks" type="textarea" placeholder="请输入备注" />
         </el-form-item>
       </el-form>
       <template #footer>
@@ -592,4 +740,4 @@ onMounted(() => {
   border-radius: 8px;
   box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
 }
-</style>
+</style>

+ 23 - 1
src/views/device/manhole/ldzh/sqbj.vue

@@ -13,7 +13,29 @@
       />
       <el-button type="primary" @click="search">搜索</el-button>
     </div>
-
+    <div>
+      <el-card shadow="hover" class="mb-4">
+        <template #header>
+          <div class="flex justify-between items-center">
+            <span class="font-bold">井盖统计</span>
+          </div>
+        </template>
+        <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
+          <div class="stat-card bg-blue-50 p-4 rounded-lg">
+            <div class="text-blue-500 text-lg font-medium">当年报警数</div>
+            <div class="text-2xl font-bold mt-2">1</div>
+          </div>
+          <div class="stat-card bg-green-50 p-4 rounded-lg">
+            <div class="text-green-500 text-lg font-medium">当月报警数</div>
+            <div class="text-2xl font-bold mt-2">1</div>
+          </div>
+          <div class="stat-card bg-red-50 p-4 rounded-lg">
+            <div class="text-red-500 text-lg font-medium">当天报警数</div>
+            <div class="text-2xl font-bold mt-2">0</div>
+          </div>
+        </div>
+      </el-card>
+    </div>
     <el-table :data="tableData" v-loading="tableLoading" border stripe>
       <el-table-column prop="imeiCardNumber" label="设备编号" width="200" />
       <el-table-column prop="batteryLevel" label="电池电量" />

+ 23 - 1
src/views/device/manhole/ldzh/swbj.vue

@@ -13,7 +13,29 @@
       />
       <el-button type="primary" @click="search">搜索</el-button>
     </div>
-
+    <div>
+      <el-card shadow="hover" class="mb-4">
+        <template #header>
+          <div class="flex justify-between items-center">
+            <span class="font-bold">井盖统计</span>
+          </div>
+        </template>
+        <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
+          <div class="stat-card bg-blue-50 p-4 rounded-lg">
+            <div class="text-blue-500 text-lg font-medium">当年报警数</div>
+            <div class="text-2xl font-bold mt-2">1</div>
+          </div>
+          <div class="stat-card bg-green-50 p-4 rounded-lg">
+            <div class="text-green-500 text-lg font-medium">当月报警数</div>
+            <div class="text-2xl font-bold mt-2">1</div>
+          </div>
+          <div class="stat-card bg-red-50 p-4 rounded-lg">
+            <div class="text-red-500 text-lg font-medium">当天报警数</div>
+            <div class="text-2xl font-bold mt-2">0</div>
+          </div>
+        </div>
+      </el-card>
+    </div>
     <el-table :data="tableData" v-loading="tableLoading" border stripe>
       <el-table-column prop="imeiCardNumber" label="设备编号" width="200" />
       <el-table-column prop="batteryLevel" label="电池电量" />