Procházet zdrojové kódy

更新接口信息,井盖基础信息

丁烨烨 před 1 rokem
rodič
revize
c1c618ad78
52 změnil soubory, kde provedl 3087 přidání a 644 odebrání
  1. 3 0
      .env.development
  2. 8 0
      index.html
  3. 88 0
      public/jwdata.json
  4. 11 0
      src/api/ldzh/index.js
  5. binární
      src/assets/visualizationimg/1.png
  6. binární
      src/assets/visualizationimg/FZ.png
  7. binární
      src/assets/visualizationimg/GJXXDCL.png
  8. binární
      src/assets/visualizationimg/GJXXYCL.png
  9. binární
      src/assets/visualizationimg/HDT.png
  10. binární
      src/assets/visualizationimg/JW.png
  11. binární
      src/assets/visualizationimg/YS.png
  12. binární
      src/assets/visualizationimg/all.png
  13. binární
      src/assets/visualizationimg/boxTitle.png
  14. binární
      src/assets/visualizationimg/eject.png
  15. binární
      src/assets/visualizationimg/fault.png
  16. binární
      src/assets/visualizationimg/fg.png
  17. binární
      src/assets/visualizationimg/hd.png
  18. binární
      src/assets/visualizationimg/headg.png
  19. binární
      src/assets/visualizationimg/headgactive.png
  20. binární
      src/assets/visualizationimg/jklb.png
  21. binární
      src/assets/visualizationimg/kq.png
  22. binární
      src/assets/visualizationimg/offline.png
  23. binární
      src/assets/visualizationimg/onLine.png
  24. binární
      src/assets/visualizationimg/qs.png
  25. binární
      src/assets/visualizationimg/title.png
  26. binární
      src/assets/visualizationimg/warn.png
  27. 178 0
      src/components/baseEcharts/index.vue
  28. 108 0
      src/components/baseEcharts/pieChart.vue
  29. 178 0
      src/layout/components/baseEcharts/index.vue
  30. 108 0
      src/layout/components/baseEcharts/pieChart.vue
  31. 1 1
      src/layout/index.vue
  32. 29 0
      src/utils/apiClient.js
  33. 1 0
      src/views/device/manhole/ajbl/ajlzgl.vue
  34. 1 0
      src/views/device/manhole/ajbl/bjgd.vue
  35. 1 0
      src/views/device/manhole/ajbl/gdczgl.vue
  36. 1 0
      src/views/device/manhole/ajbl/jbgd.vue
  37. 0 335
      src/views/device/manhole/components/alarm-management.vue
  38. 0 268
      src/views/device/manhole/components/device-management.vue
  39. 1173 0
      src/views/device/manhole/home/home-index.vue
  40. 153 38
      src/views/device/manhole/index.vue
  41. 1 0
      src/views/device/manhole/ldzh/ajgz.vue
  42. 1 0
      src/views/device/manhole/ldzh/bjgl.vue
  43. 263 0
      src/views/device/manhole/ldzh/jgkl.vue
  44. 1 0
      src/views/device/manhole/ldzh/sgpb.vue
  45. 1 0
      src/views/device/manhole/sjfx/tjfx.vue
  46. 277 0
      src/views/device/manhole/zcgl/jgzcgl.vue
  47. 163 0
      src/views/device/manhole/zcgl/qxda.vue
  48. 327 0
      src/views/device/manhole/zcgl/znzdgl.vue
  49. 1 0
      src/views/device/manhole/zdyw/gzgl.vue
  50. 1 0
      src/views/device/manhole/zdyw/sjtj.vue
  51. 1 0
      src/views/device/manhole/zdyw/ywrwgl.vue
  52. 8 2
      vite.config.js

+ 3 - 0
.env.development

@@ -6,3 +6,6 @@ VITE_APP_ENV = 'development'
 
 # 若依管理系统/开发环境
 VITE_APP_BASE_API = '/dev-api'
+
+VITE_APP_BASE_API_OTHER = '/api'
+

+ 8 - 0
index.html

@@ -7,6 +7,14 @@
   <meta name="renderer" content="webkit">
   <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
   <link rel="icon" href="/favicon.ico">
+
+  <script
+	  type="text/javascript"
+	  src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=jWDCUpsk33htQsF6IEwk4ctkERTOFFH0"
+	></script>
+	<script src="https://unpkg.com/mapv-three@1.0.10/dist/mapvthree.umd.js"></script>
+	<script src="//mapv.baidu.com/build/mapv.min.js"></script>
+	<script src="https://code.bdstatic.com/npm/mapvgl@1.0.0-beta.189/dist/mapvgl.min.js"></script>
   <title>若依管理系统</title>
   <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
   <style>

+ 88 - 0
public/jwdata.json

@@ -0,0 +1,88 @@
+{
+	"list": [{
+			"state": "A",
+			"lng": 112.957380,
+			"lat": 28.172904
+		},
+		{
+			"state": "A",
+			"lng": 112.957585,
+			"lat": 28.172901
+		},
+		{
+			"state": "A",
+			"lng": 112.957759,
+			"lat": 28.172902
+		},
+		{
+			"state": "A",
+			"lng": 112.958069,
+			"lat": 28.172892
+		},
+		{
+			"state": "B",
+			"lng": 112.958188,
+			"lat": 28.172882
+		},
+		{
+			"state": "B",
+			"lng": 112.958372,
+			"lat": 28.172883
+		},
+		{
+			"state": "B",
+			"lng": 112.958235,
+			"lat": 28.172807
+		},
+		{
+			"state": "B",
+			"lng": 112.958235,
+			"lat": 28.172682
+		},
+		{
+			"state": "C",
+			"lng": 112.958240,
+			"lat": 28.172570
+		},
+		{
+			"state": "C",
+			"lng": 112.958372,
+			"lat": 28.172564
+		},
+		{
+			"state": "C",
+			"lng": 112.958370,
+			"lat": 28.172682
+		},
+		{
+			"state": "C",
+			"lng": 112.958363,
+			"lat": 28.172793
+		},
+		{
+			"state": "D",
+			"lng": 112.958472,
+			"lat": 28.172880
+		},
+		{
+			"state": "D",
+			"lng": 112.958593,
+			"lat": 28.172871
+		},
+		{
+			"state": "D",
+			"lng": 112.958705,
+			"lat": 28.172869
+		},
+		{
+			"state": "E",
+			"lng": 112.958235,
+			"lat": 28.173020
+		},
+		{
+			"state": "E",
+			"lng": 112.958240,
+			"lat": 28.173103
+		}
+	]
+}

+ 11 - 0
src/api/ldzh/index.js

@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// 查询井盖信息列表
+export function getManholeDataAll(query) {
+  return request({
+    url: '/base/devices/getAll',
+    method: 'get',
+    params: query
+  })
+}
+

binární
src/assets/visualizationimg/1.png


binární
src/assets/visualizationimg/FZ.png


binární
src/assets/visualizationimg/GJXXDCL.png


binární
src/assets/visualizationimg/GJXXYCL.png


binární
src/assets/visualizationimg/HDT.png


binární
src/assets/visualizationimg/JW.png


binární
src/assets/visualizationimg/YS.png


binární
src/assets/visualizationimg/all.png


binární
src/assets/visualizationimg/boxTitle.png


binární
src/assets/visualizationimg/eject.png


binární
src/assets/visualizationimg/fault.png


binární
src/assets/visualizationimg/fg.png


binární
src/assets/visualizationimg/hd.png


binární
src/assets/visualizationimg/headg.png


binární
src/assets/visualizationimg/headgactive.png


binární
src/assets/visualizationimg/jklb.png


binární
src/assets/visualizationimg/kq.png


binární
src/assets/visualizationimg/offline.png


binární
src/assets/visualizationimg/onLine.png


binární
src/assets/visualizationimg/qs.png


binární
src/assets/visualizationimg/title.png


binární
src/assets/visualizationimg/warn.png


+ 178 - 0
src/components/baseEcharts/index.vue

@@ -0,0 +1,178 @@
+<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
+    }
+})
+console.log(props);
+
+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 })
+}
+
+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>

+ 108 - 0
src/components/baseEcharts/pieChart.vue

@@ -0,0 +1,108 @@
+<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({
+		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)
+
+		// 当窗口发生变化时
+		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>

+ 178 - 0
src/layout/components/baseEcharts/index.vue

@@ -0,0 +1,178 @@
+<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
+    }
+})
+console.log(props);
+
+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 })
+}
+
+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>

+ 108 - 0
src/layout/components/baseEcharts/pieChart.vue

@@ -0,0 +1,108 @@
+<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({
+		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)
+
+		// 当窗口发生变化时
+		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>

+ 1 - 1
src/layout/index.vue

@@ -43,7 +43,7 @@
         <tags-view v-if="needTagsView" />
       </div>
       <app-main />
-      <settings ref="settingRef" />
+      <settings ref="settingRef" />   
     </div>
   </div>
 </template>

+ 29 - 0
src/utils/apiClient.js

@@ -0,0 +1,29 @@
+// apiClient.js
+import axios from 'axios';
+
+// 创建一个自定义的axios实例
+const apiClient = axios.create({
+  baseURL: import.meta.env.VITE_APP_BASE_API_OTHER, // 你的基础URL
+  timeout: 10000,
+  headers: {'Content-Type': 'application/json'}
+});
+
+console.log(import.meta.env.VITE_APP_BASE_API_OTHER);
+
+// 对外暴露的方法
+
+export function clientGet(endpoint, config = {}) {
+  return apiClient.get(endpoint, config);
+}
+
+export function clientPost(endpoint, data, config = {}) {
+  return apiClient.post(endpoint, data, config);
+}
+
+export function clientPut(endpoint, data, config = {}) {
+  return apiClient.put(endpoint, data, config);
+}
+
+export function clientDelete(endpoint, config = {}) { // 'delete'是保留字,因此使用'del'
+  return apiClient.delete(endpoint, config);
+}

+ 1 - 0
src/views/device/manhole/ajbl/ajlzgl.vue

@@ -0,0 +1 @@
+<template>案件流转管理</template>

+ 1 - 0
src/views/device/manhole/ajbl/bjgd.vue

@@ -0,0 +1 @@
+<template>办结工单</template>

+ 1 - 0
src/views/device/manhole/ajbl/gdczgl.vue

@@ -0,0 +1 @@
+<template>工单处置管理</template>

+ 1 - 0
src/views/device/manhole/ajbl/jbgd.vue

@@ -0,0 +1 @@
+<template>经办工单</template>

+ 0 - 335
src/views/device/manhole/components/alarm-management.vue

@@ -1,335 +0,0 @@
-<script setup>
-import { ref, reactive, computed } from 'vue'
-import { Search, Delete, Warning, InfoFilled, CircleCheckFilled } from '@element-plus/icons-vue'
-
-// 模拟报警数据
-const alarmData = ref([
-  {
-    id: 1,
-    deviceId: 'MH-001',
-    location: '市中心路口A区',
-    type: '井盖移位',
-    level: 'high',
-    status: 'pending',
-    time: '2023-05-15 08:30:22',
-    description: '井盖位置偏移超过预警阈值',
-  },
-  {
-    id: 2,
-    deviceId: 'MH-003',
-    location: '西湖公园C区',
-    type: '电池电量低',
-    level: 'medium',
-    status: 'processing',
-    time: '2023-05-15 09:15:47',
-    description: '设备电池电量低于30%',
-  },
-  {
-    id: 3,
-    deviceId: 'MH-002',
-    location: '东区商业街B区',
-    type: '通信中断',
-    level: 'high',
-    status: 'pending',
-    time: '2023-05-15 10:22:36',
-    description: '设备通信中断超过24小时',
-  },
-  {
-    id: 4,
-    deviceId: 'MH-005',
-    location: '北区住宅区E区',
-    type: '水位异常',
-    level: 'critical',
-    status: 'pending',
-    time: '2023-05-15 11:05:11',
-    description: '井内水位超过警戒线',
-  },
-  {
-    id: 5,
-    deviceId: 'MH-004',
-    location: '南山工业园D区',
-    type: '井盖打开',
-    level: 'medium',
-    status: 'resolved',
-    time: '2023-05-14 13:45:29',
-    description: '井盖被打开但未授权',
-  },
-])
-
-// 搜索和筛选
-const searchQuery = ref('')
-const filterLevel = ref('')
-const filterStatus = ref('')
-const dateRange = ref([])
-
-// 分页
-const pagination = reactive({
-  currentPage: 1,
-  pageSize: 10,
-  total: alarmData.value.length,
-})
-
-// 报警级别标签样式
-const getLevelType = (level) => {
-  switch (level) {
-    case 'critical': return 'danger'
-    case 'high': return 'error'
-    case 'medium': return 'warning'
-    case 'low': return 'info'
-    default: return 'info'
-  }
-}
-
-const getLevelText = (level) => {
-  switch (level) {
-    case 'critical': return '紧急'
-    case 'high': return '高级'
-    case 'medium': return '中级'
-    case 'low': return '低级'
-    default: return '未知'
-  }
-}
-
-// 报警状态标签样式
-const getStatusType = (status) => {
-  switch (status) {
-    case 'pending': return 'danger'
-    case 'processing': return 'warning'
-    case 'resolved': return 'success'
-    default: return 'info'
-  }
-}
-
-const getStatusText = (status) => {
-  switch (status) {
-    case 'pending': return '待处理'
-    case 'processing': return '处理中'
-    case 'resolved': return '已解决'
-    default: return '未知'
-  }
-}
-
-// 处理报警处理
-const handleProcess = (index, row) => {
-  console.log('处理报警', index, row)
-  // 实际应用中这里会打开处理对话框
-}
-
-// 处理报警删除
-const handleDelete = (index, row) => {
-  console.log('删除报警', index, row)
-  // 实际应用中这里会显示确认对话框
-}
-
-// 过滤后的报警列表
-const filteredAlarms = computed(() => {
-  return alarmData.value.filter(alarm => {
-    const matchesSearch = searchQuery.value === '' ||
-        alarm.deviceId.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
-        alarm.location.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
-        alarm.type.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
-        alarm.description.toLowerCase().includes(searchQuery.value.toLowerCase())
-
-    const matchesLevel = filterLevel.value === '' || alarm.level === filterLevel.value
-    const matchesStatus = filterStatus.value === '' || alarm.status === filterStatus.value
-
-    let matchesDate = true
-    if (dateRange.value && dateRange.value.length === 2) {
-      const alarmDate = new Date(alarm.time)
-      const startDate = new Date(dateRange.value[0])
-      const endDate = new Date(dateRange.value[1])
-      endDate.setHours(23, 59, 59, 999) // 设置为当天结束时间
-
-      matchesDate = alarmDate >= startDate && alarmDate <= endDate
-    }
-
-    return matchesSearch && matchesLevel && matchesStatus && matchesDate
-  })
-})
-</script>
-
-<template>
-  <div>
-    <!-- 操作栏 -->
-    <div class="mb-4 flex flex-wrap gap-4">
-      <el-input
-          v-model="searchQuery"
-          placeholder="搜索设备ID/位置/类型/描述"
-          class="w-64"
-          clearable
-      >
-        <template #prefix>
-          <el-icon><Search /></el-icon>
-        </template>
-      </el-input>
-
-      <el-select v-model="filterLevel" placeholder="报警级别" clearable class="w-32">
-        <el-option label="全部" value="" />
-        <el-option label="紧急" value="critical" />
-        <el-option label="高级" value="high" />
-        <el-option label="中级" value="medium" />
-        <el-option label="低级" value="low" />
-      </el-select>
-
-      <el-select v-model="filterStatus" placeholder="处理状态" clearable class="w-32">
-        <el-option label="全部" value="" />
-        <el-option label="待处理" value="pending" />
-        <el-option label="处理中" value="processing" />
-        <el-option label="已解决" value="resolved" />
-      </el-select>
-
-      <el-date-picker
-          v-model="dateRange"
-          type="daterange"
-          range-separator="至"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-          format="YYYY-MM-DD"
-          value-format="YYYY-MM-DD"
-      />
-    </div>
-
-    <!-- 报警概览卡片 -->
-    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
-      <el-card shadow="hover" class="bg-gradient-to-r from-red-50 to-red-100">
-        <div class="flex items-center">
-          <el-icon class="text-4xl text-red-500 mr-4"><Warning /></el-icon>
-          <div>
-            <div class="text-gray-500 text-sm">总报警数</div>
-            <div class="text-2xl font-bold">{{ alarmData.length }}</div>
-          </div>
-        </div>
-      </el-card>
-
-      <el-card shadow="hover" class="bg-gradient-to-r from-orange-50 to-orange-100">
-        <div class="flex items-center">
-          <div class="w-12 h-12 rounded-full bg-orange-100 flex items-center justify-center mr-4">
-            <div class="w-8 h-8 rounded-full bg-orange-500"></div>
-          </div>
-          <div>
-            <div class="text-gray-500 text-sm">待处理</div>
-            <div class="text-2xl font-bold">{{ alarmData.filter(a => a.status === 'pending').length }}</div>
-          </div>
-        </div>
-      </el-card>
-
-      <el-card shadow="hover" class="bg-gradient-to-r from-yellow-50 to-yellow-100">
-        <div class="flex items-center">
-          <div class="w-12 h-12 rounded-full bg-yellow-100 flex items-center justify-center mr-4">
-            <div class="w-8 h-8 rounded-full bg-yellow-500"></div>
-          </div>
-          <div>
-            <div class="text-gray-500 text-sm">处理中</div>
-            <div class="text-2xl font-bold">{{ alarmData.filter(a => a.status === 'processing').length }}</div>
-          </div>
-        </div>
-      </el-card>
-
-      <el-card shadow="hover" class="bg-gradient-to-r from-green-50 to-green-100">
-        <div class="flex items-center">
-          <div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mr-4">
-            <div class="w-8 h-8 rounded-full bg-green-500"></div>
-          </div>
-          <div>
-            <div class="text-gray-500 text-sm">已解决</div>
-            <div class="text-2xl font-bold">{{ alarmData.filter(a => a.status === 'resolved').length }}</div>
-          </div>
-        </div>
-      </el-card>
-    </div>
-
-    <!-- 报警表格 -->
-    <el-card shadow="hover">
-      <template #header>
-        <div class="flex justify-between items-center">
-          <span>报警记录列表</span>
-          <el-button type="primary" plain>导出报表</el-button>
-        </div>
-      </template>
-
-      <el-table :data="filteredAlarms" stripe style="width: 100%" border>
-        <el-table-column type="expand">
-          <template #default="props">
-            <div class="p-4">
-              <p class="mb-2"><strong>详细描述:</strong> {{ props.row.description }}</p>
-              <p><strong>处理建议:</strong> 根据报警类型和级别,请按照标准操作流程进行处理。</p>
-            </div>
-          </template>
-        </el-table-column>
-
-        <el-table-column prop="deviceId" label="设备ID" width="120" />
-        <el-table-column prop="location" label="位置" min-width="180" />
-        <el-table-column prop="type" label="报警类型" width="120" />
-        <el-table-column label="报警级别" width="100">
-          <template #default="scope">
-            <el-tag :type="getLevelType(scope.row.level)">
-              {{ getLevelText(scope.row.level) }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="处理状态" width="100">
-          <template #default="scope">
-            <el-tag :type="getStatusType(scope.row.status)">
-              {{ getStatusText(scope.row.status) }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="time" label="报警时间" width="180" sortable />
-        <el-table-column label="操作" width="150" fixed="right">
-          <template #default="scope">
-            <el-button
-                v-if="scope.row.status !== 'resolved'"
-                size="small"
-                type="primary"
-                @click="handleProcess(scope.$index, scope.row)"
-            >
-              处理
-            </el-button>
-            <el-button
-                size="small"
-                type="danger"
-                @click="handleDelete(scope.$index, scope.row)"
-            >
-              删除
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <div class="mt-4 flex justify-end">
-        <el-pagination
-            v-model:current-page="pagination.currentPage"
-            v-model:page-size="pagination.pageSize"
-            :page-sizes="[10, 20, 50, 100]"
-            layout="total, sizes, prev, pager, next, jumper"
-            :total="filteredAlarms.length"
-        />
-      </div>
-    </el-card>
-
-    <!-- 报警趋势图 -->
-    <el-card shadow="hover" class="mt-4">
-      <template #header>
-        <div class="flex justify-between items-center">
-          <span>报警趋势分析</span>
-          <el-radio-group v-model="chartTimeRange" size="small">
-            <el-radio-button label="day">日</el-radio-button>
-            <el-radio-button label="week">周</el-radio-button>
-            <el-radio-button label="month">月</el-radio-button>
-          </el-radio-group>
-        </div>
-      </template>
-
-      <div class="h-64 flex items-center justify-center bg-gray-50">
-        <p class="text-gray-400">此处将显示报警趋势图表</p>
-        <!-- 实际项目中这里会使用ECharts等图表库 -->
-      </div>
-    </el-card>
-  </div>
-</template>
-
-<script>
-// 图表时间范围选择
-const chartTimeRange = ref('week')
-</script>
-

+ 0 - 268
src/views/device/manhole/components/device-management.vue

@@ -1,268 +0,0 @@
-<script setup>
-import { ref, reactive } from 'vue'
-import { Search, Plus, Edit, Delete, Download, Refresh, Location } from '@element-plus/icons-vue'
-
-// 模拟设备数据
-const deviceData = ref([
-  {
-    id: 1,
-    deviceId: 'MH-001',
-    location: '市中心路口A区',
-    status: 'online',
-    battery: 85,
-    lastUpdate: '2023-05-15 14:30:22',
-    type: '智能井盖A型',
-  },
-  {
-    id: 2,
-    deviceId: 'MH-002',
-    location: '东区商业街B区',
-    status: 'offline',
-    battery: 15,
-    lastUpdate: '2023-05-14 09:15:47',
-    type: '智能井盖B型',
-  },
-  {
-    id: 3,
-    deviceId: 'MH-003',
-    location: '西湖公园C区',
-    status: 'warning',
-    battery: 45,
-    lastUpdate: '2023-05-15 11:22:36',
-    type: '智能井盖A型',
-  },
-  {
-    id: 4,
-    deviceId: 'MH-004',
-    location: '南山工业园D区',
-    status: 'online',
-    battery: 92,
-    lastUpdate: '2023-05-15 16:05:11',
-    type: '智能井盖C型',
-  },
-  {
-    id: 5,
-    deviceId: 'MH-005',
-    location: '北区住宅区E区',
-    status: 'online',
-    battery: 78,
-    lastUpdate: '2023-05-15 13:45:29',
-    type: '智能井盖B型',
-  },
-])
-
-// 搜索和筛选
-const searchQuery = ref('')
-const filterStatus = ref('')
-
-// 分页
-const pagination = reactive({
-  currentPage: 1,
-  pageSize: 10,
-  total: deviceData.value.length,
-})
-
-// 设备状态标签样式
-const getStatusType = (status) => {
-  switch (status) {
-    case 'online': return 'success'
-    case 'offline': return 'danger'
-    case 'warning': return 'warning'
-    default: return 'info'
-  }
-}
-
-const getStatusText = (status) => {
-  switch (status) {
-    case 'online': return '在线'
-    case 'offline': return '离线'
-    case 'warning': return '警告'
-    default: return '未知'
-  }
-}
-
-// 电池电量样式
-const getBatteryType = (level) => {
-  if (level > 70) return 'success'
-  if (level > 30) return 'warning'
-  return 'exception'
-}
-
-// 处理设备编辑
-const handleEdit = (index, row) => {
-  console.log('编辑设备', index, row)
-  // 实际应用中这里会打开编辑对话框
-}
-
-// 处理设备删除
-const handleDelete = (index, row) => {
-  console.log('删除设备', index, row)
-  // 实际应用中这里会显示确认对话框
-}
-
-// 处理查看位置
-const handleViewLocation = (index, row) => {
-  console.log('查看位置', index, row)
-  // 实际应用中这里会显示地图或位置详情
-}
-
-// 过滤后的设备列表
-const filteredDevices = computed(() => {
-  return deviceData.value.filter(device => {
-    const matchesSearch = searchQuery.value === '' ||
-        device.deviceId.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
-        device.location.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
-        device.type.toLowerCase().includes(searchQuery.value.toLowerCase())
-
-    const matchesStatus = filterStatus.value === '' || device.status === filterStatus.value
-
-    return matchesSearch && matchesStatus
-  })
-})
-</script>
-
-<template>
-  <div>
-    <!-- 操作栏 -->
-    <div class="mb-4 flex justify-between items-center">
-      <div class="flex gap-4">
-        <el-input
-            v-model="searchQuery"
-            placeholder="搜索设备ID/位置/类型"
-            class="w-64"
-            clearable
-        >
-          <template #prefix>
-            <el-icon><Search /></el-icon>
-          </template>
-        </el-input>
-
-        <el-select v-model="filterStatus" placeholder="设备状态" clearable class="w-32">
-          <el-option label="全部" value="" />
-          <el-option label="在线" value="online" />
-          <el-option label="离线" value="offline" />
-          <el-option label="警告" value="warning" />
-        </el-select>
-      </div>
-
-      <div class="flex gap-2">
-        <el-button type="primary" :icon="Plus">添加设备</el-button>
-        <el-button type="success" :icon="Download">导出数据</el-button>
-        <el-button :icon="Refresh">刷新</el-button>
-      </div>
-    </div>
-
-    <!-- 设备表格 -->
-    <el-card shadow="hover" class="mb-4">
-      <el-table :data="filteredDevices" stripe style="width: 100%" border>
-        <el-table-column prop="deviceId" label="设备ID" width="120" />
-        <el-table-column prop="type" label="设备类型" width="150" />
-        <el-table-column prop="location" label="安装位置" min-width="200" />
-        <el-table-column label="设备状态" width="120">
-          <template #default="scope">
-            <el-tag :type="getStatusType(scope.row.status)">
-              {{ getStatusText(scope.row.status) }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="电池电量" width="180">
-          <template #default="scope">
-            <el-progress
-                :percentage="scope.row.battery"
-                :status="getBatteryType(scope.row.battery)"
-            />
-          </template>
-        </el-table-column>
-        <el-table-column prop="lastUpdate" label="最后更新时间" width="180" />
-        <el-table-column label="操作" width="200" fixed="right">
-          <template #default="scope">
-            <el-button
-                size="small"
-                type="primary"
-                :icon="Location"
-                circle
-                @click="handleViewLocation(scope.$index, scope.row)"
-                title="查看位置"
-            />
-            <el-button
-                size="small"
-                type="primary"
-                :icon="Edit"
-                circle
-                @click="handleEdit(scope.$index, scope.row)"
-                title="编辑"
-            />
-            <el-button
-                size="small"
-                type="danger"
-                :icon="Delete"
-                circle
-                @click="handleDelete(scope.$index, scope.row)"
-                title="删除"
-            />
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <div class="mt-4 flex justify-end">
-        <el-pagination
-            v-model:current-page="pagination.currentPage"
-            v-model:page-size="pagination.pageSize"
-            :page-sizes="[10, 20, 50, 100]"
-            layout="total, sizes, prev, pager, next, jumper"
-            :total="filteredDevices.length"
-        />
-      </div>
-    </el-card>
-
-    <!-- 设备概览卡片 -->
-    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
-      <el-card shadow="hover" class="bg-gradient-to-r from-blue-50 to-blue-100">
-        <div class="flex items-center">
-          <el-icon class="text-4xl text-blue-500 mr-4"><Monitor /></el-icon>
-          <div>
-            <div class="text-gray-500 text-sm">设备总数</div>
-            <div class="text-2xl font-bold">{{ deviceData.length }}</div>
-          </div>
-        </div>
-      </el-card>
-
-      <el-card shadow="hover" class="bg-gradient-to-r from-green-50 to-green-100">
-        <div class="flex items-center">
-          <div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mr-4">
-            <div class="w-8 h-8 rounded-full bg-green-500"></div>
-          </div>
-          <div>
-            <div class="text-gray-500 text-sm">在线设备</div>
-            <div class="text-2xl font-bold">{{ deviceData.filter(d => d.status === 'online').length }}</div>
-          </div>
-        </div>
-      </el-card>
-
-      <el-card shadow="hover" class="bg-gradient-to-r from-red-50 to-red-100">
-        <div class="flex items-center">
-          <div class="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mr-4">
-            <div class="w-8 h-8 rounded-full bg-red-500"></div>
-          </div>
-          <div>
-            <div class="text-gray-500 text-sm">离线设备</div>
-            <div class="text-2xl font-bold">{{ deviceData.filter(d => d.status === 'offline').length }}</div>
-          </div>
-        </div>
-      </el-card>
-
-      <el-card shadow="hover" class="bg-gradient-to-r from-yellow-50 to-yellow-100">
-        <div class="flex items-center">
-          <div class="w-12 h-12 rounded-full bg-yellow-100 flex items-center justify-center mr-4">
-            <div class="w-8 h-8 rounded-full bg-yellow-500"></div>
-          </div>
-          <div>
-            <div class="text-gray-500 text-sm">警告设备</div>
-            <div class="text-2xl font-bold">{{ deviceData.filter(d => d.status === 'warning').length }}</div>
-          </div>
-        </div>
-      </el-card>
-    </div>
-  </div>
-</template>
-

+ 1173 - 0
src/views/device/manhole/home/home-index.vue

@@ -0,0 +1,1173 @@
+<template>
+  <div class="Vbox">
+    <div class="head">
+      <!-- <div class="VisTitle"></div> -->
+    </div>
+    <div class="container">
+      <div class="center">
+        <div ref="mapContainer" class="allmap"></div>
+      </div>
+      <div class="left">
+        <div class="rightParkBox">
+          <div class="rightParkTtile">
+            <div>设备状态</div>
+            <div @click="dialogTableVisible = true">设备列表></div>
+          </div>
+          <div class="rightParkContent">
+            <div class="SBZT_right">
+              <div class="SBZT_onLine">
+                <img src="../../../../assets/visualizationimg/onLine.png" alt="" />
+                <div style="color: #44eefb; font-size: 20px; font-weight: bold">
+                  在线:351
+                </div>
+              </div>
+              <div class="SBZT_onLine">
+                <img src="../../../../assets/visualizationimg/offline.png" alt="" />
+                <div style="color: #ccc; font-size: 20px; font-weight: bold">离线:20</div>
+              </div>
+            </div>
+            <div class="SBZT_center">
+              <PieEcharts :message="PieChartData"></PieEcharts>
+            </div>
+            <div class="SBZT_left">
+              <div class="SBZT_onLine">
+                <img src="../../../../assets/visualizationimg/warn.png" alt="" />
+                <div style="color: #5470c6; font-size: 20px; font-weight: bold">
+                  告警:50
+                </div>
+              </div>
+              <div class="SBZT_onLine">
+                <img src="../../../../assets/visualizationimg/fault.png" alt="" />
+                <div style="color: #5470c6; font-size: 20px; font-weight: bold">
+                  故障:30
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="leftTwoBox">
+          <div class="leftGDPTitle">井盖监控</div>
+          <div class="leftGDPContent">
+            <div class="jgjk_box">
+              <div class="Jklb_table">
+                <div
+                  class="JKlb_name"
+                  v-for="(item, index) in JgjkData"
+                  :key="index"
+                  :class="{ JGJKActive: jgjkactiveTab === index }"
+                  @click="JgjksetActiveTab(index, item)"
+                >
+                  {{ item.name }}
+                </div>
+              </div>
+              <div class="JKLB_Video">
+                <video class="Video_url" controls :src="videoSource"></video>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="leftThreeBox">
+          <div class="leftTaxationTitle">告警信息</div>
+          <el-scrollbar height="calc(100% - 40px)">
+            <div class="leftTaxationContent">
+              <div class="GJXX_table">
+                <div
+                  class="GJXX_name"
+                  v-for="(item, index) in GJXXData"
+                  :style="{ backgroundImage: 'url(' + item.img + ')' }"
+                >
+                  <div class="">
+                    {{ item.id }}
+                  </div>
+                  <div class="">
+                    {{ item.text }}
+                  </div>
+                  <div class="" style="cursor: pointer">
+                    {{ item.stateData }}
+                  </div>
+                </div>
+              </div>
+            </div>
+          </el-scrollbar>
+        </div>
+      </div>
+
+      <div class="boxBottom">
+        <div class="Vgradation">
+          <div
+            class="tab"
+            v-for="(item, index) in gradationMun"
+            :key="index"
+            :class="{ active: activeTab === index }"
+            @click="setActiveTab(index, item)"
+          >
+            {{ item.name }}
+          </div>
+        </div>
+      </div>
+
+      <div class="right">
+        <div class="leftOneBox">
+          <div class="leftOBTitle">运行状态</div>
+          <div class="leftOBContent">
+            <div class="SBZT_right">
+              <div class="SBZT_onLine">
+                <img src="../../../../assets/visualizationimg/kq.png" alt="" />
+                <div style="color: #44eefb; font-size: 20px; font-weight: bold">
+                  开启:351
+                </div>
+              </div>
+              <div class="SBZT_onLine">
+                <img src="../../../../assets/visualizationimg/hd.png" alt="" />
+                <div style="color: #ccc; font-size: 20px; font-weight: bold">晃动:20</div>
+              </div>
+            </div>
+            <div class="SBZT_center">
+              <PieEcharts :message="PieChartDataTwo"></PieEcharts>
+            </div>
+            <div class="SBZT_left">
+              <div class="SBZT_onLine">
+                <img src="../../../../assets/visualizationimg/qs.png" alt="" />
+                <div style="color: #5470c6; font-size: 20px; font-weight: bold">
+                  潜水:50
+                </div>
+              </div>
+              <div class="SBZT_onLine">
+                <img src="../../../../assets/visualizationimg/fg.png" alt="" />
+                <div style="color: #5470c6; font-size: 20px; font-weight: bold">
+                  翻盖:30
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="leftTwo_GDCL">
+          <div class="leftOBTitle">工单处理</div>
+          <el-scrollbar height="calc(100% - 90px)">
+            <div class="GJXX_table">
+              <div
+                class="GJXX_name"
+                v-for="(item, index) in GDCLData"
+                :key="index"
+                :class="{ active: item.stateNumber === 0 }"
+                :style="{ backgroundImage: 'url(' + item.img + ')' }"
+              >
+                <div class="">
+                  {{ item.id }}
+                </div>
+                <div class="">
+                  {{ item.text }}
+                </div>
+                <div class="">
+                  {{ item.stateData }}
+                </div>
+              </div>
+            </div>
+          </el-scrollbar>
+        </div>
+      </div>
+    </div>
+  </div>
+  <el-dialog v-model="dialogTableVisible" title="设备列表">
+    <el-table ref="tableRef" row-key="date" :data="tableData" style="width: 100%">
+      <el-table-column prop="id" label="序号" width="80" />
+      <el-table-column prop="SBBH" label="设备编号" />
+      <el-table-column prop="address" label="地址" width="300" />
+      <el-table-column
+        prop="tag"
+        label="状态"
+        :filters="[
+          { text: '在线', value: 'onLine' },
+          { text: '离线', value: 'offLine' },
+          { text: '故障', value: 'fault' },
+          { text: '告警', value: 'alarm' },
+        ]"
+        :filter-method="filterTag"
+        filter-placement="bottom-end"
+      >
+        <template #default="scope">
+          <el-tag v-if="scope.row.tag === 'onLine'" type="success" disable-transitions>{{
+            scope.row.tagtext
+          }}</el-tag>
+          <el-tag v-if="scope.row.tag === 'offLine'" type="info" disable-transitions>{{
+            scope.row.tagtext
+          }}</el-tag>
+          <el-tag v-if="scope.row.tag === 'fault'" type="error" disable-transitions>{{
+            scope.row.tagtext
+          }}</el-tag>
+          <el-tag v-if="scope.row.tag === 'alarm'" type="warning" disable-transitions>{{
+            scope.row.tagtext
+          }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column
+        prop="date"
+        label="时间"
+        sortable
+        column-key="date"
+        :filters="[
+          { text: '2016-05-01', value: '2016-05-01' },
+          { text: '2016-05-02', value: '2016-05-02' },
+          { text: '2016-05-03', value: '2016-05-03' },
+          { text: '2016-05-04', value: '2016-05-04' },
+        ]"
+        :filter-method="filterHandler"
+      />
+      <!-- <el-table-column prop="address" label="操作" /> -->
+    </el-table>
+  </el-dialog>
+</template>
+
+<script setup>
+import { onMounted, ref } from "vue";
+import PieEcharts from "@/components/baseEcharts/pieChart.vue";
+
+import GJXXYCL from "@/assets/visualizationimg/GJXXYCL.png";
+import GJXXDCL from "@/assets/visualizationimg/GJXXDCL.png";
+import ALL from "@/assets/visualizationimg/all.png";
+import FZ from "@/assets/visualizationimg/FZ.png";
+import HDT from "@/assets/visualizationimg/HDT.png";
+import YS from "@/assets/visualizationimg/YS.png";
+import JW from "@/assets/visualizationimg/JW.png";
+const mapContainer = ref(null);
+const dialogTableVisible = ref(false);
+
+const filterTag = (value, row) => {
+  return row.tag === value;
+};
+const filterHandler = (value, row, column) => {
+  const property = column["property"];
+  return row[property] === value;
+};
+
+const tableData = [
+  {
+    id: 1,
+    SBBH: "ZTD95588",
+    address: "东方大道与三号路交叉处",
+    state: "0",
+    date: "2016-05-03",
+    CLState: "",
+    tagtext: "在线",
+    tag: "onLine",
+  },
+  {
+    id: 1,
+    SBBH: "ZTD95588",
+    address: "东方大道与三号路交叉处",
+    state: "0",
+    date: "2016-05-03",
+    CLState: "",
+    tagtext: "离线",
+    tag: "offLine",
+  },
+  {
+    id: 1,
+    SBBH: "ZTD95588",
+    address: "东方大道与三号路交叉处",
+    state: "0",
+    date: "2016-05-03",
+    CLState: "",
+    tagtext: "故障",
+    tag: "fault",
+  },
+  {
+    id: 1,
+    SBBH: "ZTD95588",
+    address: "东方大道与三号路交叉处",
+    state: "0",
+    date: "2016-05-03",
+    CLState: "",
+    tagtext: "告警",
+    tag: "alarm",
+  },
+];
+const gradationMun = [
+  {
+    name: "全部",
+    state: 3,
+    type: "A",
+  },
+  {
+    name: "翻转",
+    state: 2,
+    type: "B",
+  },
+  {
+    name: "晃动",
+    state: 1,
+    type: "C",
+  },
+  {
+    name: "溢水",
+    state: 4,
+    type: "D",
+  },
+  {
+    name: "甲烷",
+    state: 5,
+    type: "E",
+  },
+];
+
+const PieChartData = [
+  {
+    value: 351,
+    name: "在线",
+  },
+  {
+    value: 20,
+    name: "离线",
+  },
+  {
+    value: 50,
+    name: "故障",
+  },
+  {
+    value: 30,
+    name: "报警",
+  },
+];
+
+const PieChartDataTwo = [
+  {
+    value: 50,
+    name: "潜水",
+  },
+  {
+    value: 20,
+    name: "晃动",
+  },
+  {
+    value: 351,
+    name: "开启",
+  },
+  {
+    value: 30,
+    name: "翻盖",
+  },
+];
+
+const JgjkData = [
+  {
+    value: 351,
+    name: "一号监控",
+  },
+  {
+    value: 20,
+    name: "二号监控",
+  },
+  {
+    value: 50,
+    name: "三号监控",
+  },
+  {
+    value: 30,
+    name: "四号监控",
+  },
+  {
+    value: 30,
+    name: "五号监控",
+  },
+];
+const GJXXData = [
+  {
+    id: 1,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXDCL,
+  },
+  {
+    id: 2,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXDCL,
+  },
+  {
+    id: 3,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXDCL,
+  },
+  {
+    id: 4,
+    stateData: "查看详情",
+    stateNumber: 0,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 5,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXDCL,
+  },
+  {
+    id: 6,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXDCL,
+  },
+  {
+    id: 7,
+    stateData: "查看详情",
+    stateNumber: 0,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 8,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXDCL,
+  },
+  {
+    id: 9,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXDCL,
+  },
+];
+
+const GDCLData = [
+  {
+    id: 1,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 2,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 3,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 4,
+    stateData: "已处理",
+    stateNumber: 0,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 5,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 6,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 7,
+    stateData: "已处理",
+    stateNumber: 0,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 8,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 9,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 10,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 11,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 12,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 13,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 14,
+    stateData: "已处理",
+    stateNumber: 0,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 15,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 16,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 17,
+    stateData: "已处理",
+    stateNumber: 0,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 18,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+  {
+    id: 19,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: GJXXYCL,
+  },
+  {
+    id: 20,
+    stateData: "待处理",
+    stateNumber: 1,
+    text: "江景路223号Z23232井盖发生人为挪动进行检修",
+    img: "",
+  },
+];
+const activeTab = ref(0); // 默认激活第一个tab
+const jgjkactiveTab = ref(0); // 默认激活第一个tab
+let IMGICon = null;
+const setActiveTab = (index, value) => {
+  var allOverlay = map.getOverlays();
+  for (var i = 0; i < allOverlay.length; i++) {
+    if (allOverlay[i].toString() == "Marker") {
+      map.removeOverlay(allOverlay[i]);
+    }
+  }
+  console.log(value.type);
+  switch (value.type) {
+    case "A":
+      IMGICon = ALL;
+      console.log(value);
+      getImgType(0, 17);
+      break;
+    case "B":
+      IMGICon = FZ;
+      getImgType(4, 8);
+      break;
+    case "C":
+      IMGICon = HDT;
+      getImgType(8, 12);
+      break;
+    case "D":
+      IMGICon = YS;
+      getImgType(12, 15);
+      break;
+    case "E":
+      IMGICon = JW;
+      getImgType(15, 17);
+      break;
+  }
+
+  activeTab.value = index;
+};
+
+const getImgType = (start, end) => {
+  fetch("../jwdata.json")
+    .then((response) => response.json())
+    .then((data) => {
+      var points = data.list;
+      // for (var j = 0; j < points.length; j++) {
+      for (var j = start; j < end; j++) {
+        var lng = points[j].lng;
+        var lat = points[j].lat;
+        const markers = new BMapGL.Point(lng, lat);
+        let dayOfWeek = new Date().getDay();
+        switch (points[j].state) {
+          case "A":
+            IMGICon = ALL;
+            break;
+          case "B":
+            IMGICon = FZ;
+            break;
+          case "C":
+            IMGICon = HDT;
+            break;
+          case "D":
+            IMGICon = YS;
+            break;
+          case "E":
+            IMGICon = JW;
+            break;
+        }
+        var icon = new BMapGL.Icon(IMGICon, new BMapGL.Size(23, 25), {
+          anchor: new BMapGL.Size(10, 25),
+        });
+        marker = new BMapGL.Marker(markers, {
+          icon: icon,
+        });
+        // 创建信息窗口
+        var opts = {
+          width: 300,
+          // height: 100,
+          title: "TOI-23472[0123456789]",
+        };
+        var infoWindow = new BMapGL.InfoWindow(
+          "倾斜角度:" +
+            "188deg" +
+            "<br/>" +
+            "电池电压:" +
+            "3.6V" +
+            "<br/>" +
+            "信噪比:" +
+            "16db" +
+            "<br/>" +
+            "负责人:" +
+            "张三" +
+            "<br/>" +
+            "联系方式:" +
+            "121234564",
+          opts
+        );
+        // 点标记添加点击事件
+        marker.addEventListener("click", function () {
+          map.openInfoWindow(infoWindow, markers); // 开启信息窗口
+        });
+        map.addOverlay(marker);
+      }
+    });
+};
+
+const JgjksetActiveTab = (index, value) => {
+  jgjkactiveTab.value = index;
+};
+let map = null;
+let marker = null;
+onMounted(async () => {
+  // 初始化地图
+  map = new BMapGL.Map(mapContainer.value);
+  var point = new BMapGL.Point(112.957987, 28.172891);
+  map.centerAndZoom(point, 19); // 初始化地图,设置中心点坐标和地图级别
+  map.enableScrollWheelZoom(true);
+  map.setMinZoom(15);
+  map.setMaxZoom(22);
+  map.setMapStyleV2({
+    styleId: "62ce43ad2a1362c23e612b783d7406e7",
+  });
+  map.setTilt(50);
+  map.disableInertialDragging();
+
+  // // 定义允许的拖拽范围
+  // const allowedBounds = new BMapGL.Bounds(
+  // 	new BMapGL.Point(109.90207672119142, 27.365250190931242), // 西南角
+  // 	new BMapGL.Point(109.97014045715333, 27.422461872492594) // 东北角
+  // );
+
+  // // 监听拖拽结束事件
+  // map.addEventListener('dragend', function() {
+  // 	// 获取当前地图的中心点
+  // 	const center = map.getCenter();
+  // 	// 检查中心点是否在允许的范围内
+  // 	if (!allowedBounds.containsPoint(center)) {
+  // 		// 如果不在范围内,将地图中心调整回允许范围的中心点
+  // 		const adjustCenter = allowedBounds.getCenter();
+  // 		map.panTo(adjustCenter);
+  // 	}
+  // });
+  // 导入JSON文件
+  try {
+    getImgType(0, 17);
+  } catch (error) {
+    // console.error('Error loading JSON data:', error);
+  }
+});
+</script>
+
+<style lang="scss">
+.BMap_bubble_pop {
+  border: 0px !important;
+  border-radius: 0 !important;
+  background-image: url("../../../../assets/visualizationimg/eject.png");
+  background-size: 100% 100%;
+  background-color: rgba(0, 0, 0, 0) !important;
+  padding: 0 20px !important;
+  width: auto !important;
+  .BMap_bubble_top {
+    margin-top: 10px !important;
+    .BMap_bubble_title {
+      color: white !important;
+      font-size: 20px;
+    }
+  }
+
+  .BMap_bubble_center {
+    margin-bottom: 10px !important;
+    .BMap_bubble_content {
+      color: white !important;
+    }
+  }
+  img {
+    display: none !important;
+  }
+}
+</style>
+
+<style lang="scss">
+.Vbox {
+  height: 100vh;
+  overflow: hidden;
+
+  .head {
+    height: 120px;
+    top: 0;
+    width: 100%;
+    position: absolute;
+    z-index: 999;
+    // background-color: rgba($color: #0e2a41, $alpha: .5);
+
+    .VisTitle {
+      height: 60px;
+      background-image: url("../../../../assets/visualizationimg/title.png");
+    }
+  }
+
+  .container {
+    height: 100%;
+    position: relative;
+
+    .left {
+      display: none;
+      left: 20px;
+      float: left;
+      position: relative;
+      margin-left: -100%;
+      width: 26vw;
+      height: 100%;
+      top: 20px;
+      z-index: 999;
+
+      .rightParkBox {
+        height: 30%;
+        background-color: rgba($color: #000000, $alpha: 0.3);
+        margin-bottom: 14px;
+
+        .rightParkTtile {
+          height: 40px;
+          color: white;
+          line-height: 40px;
+          padding-left: 40px;
+          font-weight: bold;
+          background-image: url("../../../../assets/visualizationimg/boxTitle.png");
+          background-size: 100% 100%;
+          display: flex;
+          justify-content: space-between;
+
+          div:nth-child(2) {
+            margin-right: 20px;
+            font-size: 14px;
+            cursor: pointer;
+          }
+        }
+
+        .leftOBTitle,
+        .RICBTitle {
+          height: 40px;
+          color: white;
+          line-height: 40px;
+          padding-left: 40px;
+          font-weight: bold;
+          background-image: url("../../../../assets/visualizationimg/boxTitle.png");
+          background-size: 100% 100%;
+        }
+
+        .leftOBContent {
+          height: calc(100% - 40px);
+
+          .HTB_CB_List {
+            width: 100%;
+          }
+        }
+
+        .rightParkContent {
+          height: calc(100% - 40px);
+          display: flex;
+
+          .SBZT_right,
+          .SBZT_left {
+            flex: 1;
+            display: flex;
+            justify-content: space-around;
+            flex-direction: column;
+
+            .SBZT_onLine {
+              text-align: center;
+
+              img {
+                width: 30px;
+                height: 30px;
+              }
+            }
+          }
+
+          .SBZT_center {
+            flex: 2;
+          }
+
+          .SBZT_left {
+            flex: 1;
+          }
+        }
+
+        .RICBTContent {
+          height: calc(100% - 40px);
+          display: grid;
+          grid-template-columns: repeat(1, 100%);
+          grid-template-rows: repeat(2, 50%);
+          align-items: center;
+          justify-content: center;
+        }
+      }
+
+      .leftTwoBox {
+        height: 30%;
+        background-color: rgba($color: #000000, $alpha: 0.3);
+        margin-bottom: 14px;
+
+        .leftOBTitle,
+        .leftGDPTitle,
+        .leftTaxationTitle {
+          height: 40px;
+          color: white;
+          line-height: 40px;
+          padding-left: 40px;
+          font-weight: bold;
+          background-image: url("../../../../assets/visualizationimg/boxTitle.png");
+          background-size: 100% 100%;
+        }
+
+        .leftOBContent {
+          height: calc(100% - 40px);
+        }
+
+        .leftGDPContent {
+          height: calc(100% - 40px);
+
+          .jgjk_box {
+            padding: 10px;
+            display: flex;
+            height: 100%;
+
+            .Jklb_table {
+              width: 30%;
+              display: flex;
+              flex-direction: column;
+              justify-content: space-around;
+
+              .JKlb_name {
+                text-align: center;
+                color: white;
+                padding: 7px 10px;
+                background-image: url("../../../../assets/visualizationimg/jklb.png");
+                background-size: 100% 100%;
+              }
+
+              .JGJKActive {
+                background-color: #efb336;
+                color: #000000;
+              }
+            }
+
+            .JKLB_Video {
+              width: 70%;
+              padding: 7px;
+
+              .Video_url {
+                width: 100%;
+                height: 100%;
+              }
+            }
+          }
+        }
+      }
+
+      .leftOneBox,
+      .leftThreeBox {
+        height: 30%;
+        background-color: rgba($color: #000000, $alpha: 0.3);
+        margin-bottom: 14px;
+
+        .leftOBTitle,
+        .leftGDPTitle,
+        .leftTaxationTitle {
+          height: 40px;
+          color: white;
+          line-height: 40px;
+          padding-left: 40px;
+          font-weight: bold;
+          background-image: url("../../../../assets/visualizationimg/boxTitle.png");
+          background-size: 100% 100%;
+        }
+
+        .leftOBContent,
+        .leftGDPContent {
+          height: calc(100% - 40px);
+        }
+
+        .leftTaxationContent {
+          height: calc(100% - 40px);
+
+          .GJXX_table {
+            display: flex;
+            flex-direction: column;
+            justify-content: space-around;
+
+            .GJXX_name {
+              text-align: center;
+              font-size: 14px;
+              color: white;
+              padding: 5px 5px;
+              background-image: url("../../../../assets/visualizationimg/jklb.png");
+              background-size: 100% 100%;
+              display: flex;
+              flex-direction: row;
+              justify-content: space-between;
+
+              div:nth-child(1) {
+                margin-left: 10px;
+              }
+
+              div:nth-child(3) {
+                margin-right: 10px;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    .boxBottom {
+      position: absolute;
+      z-index: 999;
+      // bottom: 0;
+      width: 45vw;
+      left: 20vw;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      .Vgradation {
+        display: flex;
+
+        .tab {
+          width: 150px;
+          height: 60px;
+          margin: 0 10px;
+          text-align: center;
+          line-height: 60px;
+          color: white;
+          font-weight: 500;
+          font-size: 0.9vw;
+          background-image: url("../../../../assets/visualizationimg/headg.png");
+          background-size: 100% 100%;
+        }
+
+        .active {
+          background-image: url("../../../../assets/visualizationimg/headgactive.png");
+          background-size: 100% 100%;
+        }
+      }
+    }
+
+    .center {
+      float: left;
+      height: 100%;
+      width: 100%;
+      background-color: green;
+
+      .allmap {
+        /* // 注意给dom宽高,不然地图不出来 */
+        width: 100vw;
+        height: 100%;
+        margin: auto;
+        padding: 0;
+      }
+    }
+
+    .right {
+      display: none;
+      //right: 20px;
+      left: 73vw;
+      float: left;
+      position: absolute;
+      //margin-left: -500px;
+      width: 26.5vw;
+      // background-color: rgba($color: #000000, $alpha: 0.2);
+      height: 100%;
+      top: 10px;
+      z-index: 999;
+      // display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+
+      .leftOneBox {
+        height: 30%;
+        background-color: rgba($color: #000000, $alpha: 0.3);
+        margin-bottom: 14px;
+
+        .leftOBTitle,
+        .RICBTitle {
+          height: 40px;
+          color: white;
+          line-height: 40px;
+          padding-left: 40px;
+          font-weight: bold;
+          background-image: url("../../../../assets/visualizationimg/boxTitle.png");
+          background-size: 100% 100%;
+        }
+
+        .leftOBContent {
+          height: calc(100% - 40px);
+
+          display: flex;
+
+          .SBZT_right,
+          .SBZT_left {
+            flex: 1;
+            display: flex;
+            justify-content: space-around;
+            flex-direction: column;
+
+            .SBZT_onLine {
+              text-align: center;
+
+              img {
+                width: 30px;
+                height: 30px;
+              }
+            }
+          }
+
+          .SBZT_center {
+            flex: 2;
+          }
+
+          .SBZT_left {
+            flex: 1;
+          }
+
+          .HTB_CB_List {
+            width: 100%;
+          }
+        }
+
+        .rightParkContent {
+          height: calc(100% - 40px);
+          display: grid;
+          grid-template-columns: repeat(3, 33.33%);
+          grid-template-rows: repeat(2, 50%);
+          align-items: center;
+        }
+
+        .RICBTContent {
+          height: calc(100% - 40px);
+          display: grid;
+          grid-template-columns: repeat(1, 100%);
+          grid-template-rows: repeat(2, 50%);
+          align-items: center;
+          justify-content: center;
+        }
+      }
+
+      .leftTwo_GDCL {
+        height: calc(70% - 20px);
+        background-color: rgba($color: #000000, $alpha: 0.3);
+        margin-bottom: 14px;
+
+        .leftOBTitle {
+          height: 40px;
+          color: white;
+          line-height: 40px;
+          padding-left: 40px;
+          font-weight: bold;
+          background-image: url("../../../../assets/visualizationimg/boxTitle.png");
+          background-size: 100% 100%;
+        }
+
+        .GJXX_table {
+          display: flex;
+          flex-direction: column;
+          justify-content: space-around;
+
+          .GJXX_name {
+            text-align: center;
+            font-size: 14px;
+            color: #efb336;
+            padding: 14px 5px;
+            background-image: url("../../../../assets/visualizationimg/jklb.png");
+            background-size: 100% 100%;
+            display: flex;
+            flex-direction: row;
+            justify-content: space-between;
+
+            div:nth-child(1) {
+              margin-left: 10px;
+            }
+
+            div:nth-child(3) {
+              margin-right: 10px;
+            }
+          }
+
+          .active {
+            color: aqua;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 153 - 38
src/views/device/manhole/index.vue

@@ -1,70 +1,185 @@
 <script setup>
-import { ref } from 'vue'
-import { Menu as IconMenu, Monitor, Bell, Location, Setting } from '@element-plus/icons-vue'
-import DeviceManagement from './components/device-management.vue'
-import AlarmManagement from './components/alarm-management.vue'
+import { ref } from "vue";
+import {
+  Menu as IconMenu,
+  House,
+  Monitor,
+  Bell,
+  Location,
+  Setting,
+} from "@element-plus/icons-vue";
+import HomeIndex from "./home/home-index.vue";
+//资产管理
+import znzdgl from "./zcgl/znzdgl.vue";
+import qxda from "./zcgl/qxda.vue";
+import jgzcgl from "./zcgl/jgzcgl.vue";
+
+//联动指挥
+import jgkl from "./ldzh/jgkl.vue";
+import bjgl from "./ldzh/bjgl.vue";
+import angz from "./ldzh/ajgz.vue";
+import sgpb from "./ldzh/sgpb.vue";
+
+//案件办理
+import ajlzgl from "./ajbl/ajlzgl.vue";
+import gdczgl from "./ajbl/gdczgl.vue";
+import jbgd from "./ajbl/jbgd.vue";
+import bjgd from "./ajbl/bjgd.vue";
+//终端运维
+import ywrwgl from "./zdyw/ywrwgl.vue";
+import gzgl from "./zdyw/gzgl.vue";
+import sjtj from "./zdyw/sjtj.vue";
+//数据分析
+import tjfx from "./sjfx/tjfx.vue";
 
 const componentsMap = {
-  DeviceManagement,
-  AlarmManagement
-}
+  HomeIndex,
+  znzdgl,
+  qxda,
+  jgzcgl,
+  jgkl,
+  bjgl,
+  angz,
+  sgpb,
+  ajlzgl,
+  gdczgl,
+  jbgd,
+  bjgd,
+  ywrwgl,
+  gzgl,
+  sjtj,
+  tjfx,
+};
+
+const isCollapse = ref(false);
+const currentComponent = ref(HomeIndex);
 
-const isCollapse = ref(false)
-const activeIndex = ref('1')
-const currentComponent = ref(DeviceManagement)
+const componentMapping = {
+  1: "HomeIndex",
+  "2-1": "znzdgl",
+  "2-2": "qxda",
+  "2-3": "jgzcgl",
+  "3-1": "jgkl",
+  "3-2": "bjgl",
+  "3-3": "angz",
+  "3-4": "sgpb",
+  "4-1": "ajlzgl",
+  "4-2": "gdczgl",
+  "4-3": "jbgd",
+  "4-4": "bjgd",
+  "5-1": "ywrwgl",
+  "5-2": "gzgl",
+  "5-3": "sjtj",
+  "6-1": "tjfx",
+};
 
 const handleSelect = (key) => {
-  if (key === '1') {
-    currentComponent.value = componentsMap.DeviceManagement
-  } else if (key === '2') {
-    currentComponent.value = componentsMap.AlarmManagement
+  const componentName = componentMapping[key];
+  if (componentName) {
+    currentComponent.value = componentsMap[componentName];
   }
-}
+};
 </script>
 
 <template>
   <div class="flex h-screen bg-gray-100">
     <!-- Sidebar -->
     <div
-        class="bg-dark transition-all duration-300 text-white"
-        :class="isCollapse ? 'w-16' : 'w-64'"
+      class="bg-dark transition-all duration-300 text-white"
+      :class="isCollapse ? 'w-16' : 'w-64'"
     >
       <div class="p-4 flex items-center justify-between border-b border-gray-700">
         <h1 v-if="!isCollapse" class="text-xl font-bold">智能井盖管理</h1>
-        <el-button
-            type="text"
-            @click="isCollapse = !isCollapse"
-            class="text-white"
-        >
-          <el-icon><IconMenu /></el-icon>
+        <el-button type="text" @click="isCollapse = !isCollapse" class="text-white">
+          <el-icon>
+            <IconMenu />
+          </el-icon>
         </el-button>
       </div>
 
       <el-menu
-          default-active="1"
-          class="border-none"
-          :collapse="isCollapse"
-          background-color="#1f2937"
-          text-color="#fff"
-          active-text-color="#409EFF"
-          @select="handleSelect"
+        default-active="0"
+        class="border-none"
+        :collapse="isCollapse"
+        background-color="#1f2937"
+        text-color="#fff"
+        active-text-color="#409EFF"
+        @select="handleSelect"
       >
         <el-menu-item index="1">
-          <el-icon><Monitor /></el-icon>
-          <template #title>设备管理</template>
-        </el-menu-item>
-        <el-menu-item index="2">
-          <el-icon><Bell /></el-icon>
-          <template #title>报警管理</template>
+          <el-icon>
+            <location />
+          </el-icon>
+          <template #title>首页</template>
         </el-menu-item>
+
+        <!-- <el-sub-menu index="2">
+          <template #title>
+            <el-icon>
+              <location />
+            </el-icon>
+            <span>资产管理</span>
+          </template>
+          <el-menu-item index="2-1">智能终端管理</el-menu-item>
+          <el-menu-item index="2-2">全息档案</el-menu-item>
+          <el-menu-item index="2-3">井盖资产管理</el-menu-item>
+        </el-sub-menu> -->
+
+        <el-sub-menu index="3">
+          <template #title
+            ><el-icon>
+              <location />
+            </el-icon>
+            <span>联动指挥</span>
+          </template>
+          <el-menu-item index="3-1">井盖概览</el-menu-item>
+          <el-menu-item index="3-2">报警管理</el-menu-item>
+          <el-menu-item index="3-3">案件跟踪</el-menu-item>
+          <el-menu-item index="3-4">施工屏蔽</el-menu-item>
+        </el-sub-menu>
+
+        <!-- <el-sub-menu index="4">
+          <template #title
+            ><el-icon>
+              <location />
+            </el-icon>
+            <span>案件办理</span>
+          </template>
+          <el-menu-item index="4-1">案件流转管理</el-menu-item>
+          <el-menu-item index="4-2">工单处置管理</el-menu-item>
+          <el-menu-item index="4-3">经办工单</el-menu-item>
+          <el-menu-item index="4-4">办结工单</el-menu-item>
+        </el-sub-menu>
+
+        <el-sub-menu index="5">
+          <template #title
+            ><el-icon>
+              <location />
+            </el-icon>
+            <span>终端运维</span>
+          </template>
+          <el-menu-item index="5-1">运维任务管理</el-menu-item>
+          <el-menu-item index="5-2">故障管理</el-menu-item>
+          <el-menu-item index="5-3">数据统计</el-menu-item>
+        </el-sub-menu>
+
+        <el-sub-menu index="6">
+          <template #title
+            ><el-icon>
+              <location />
+            </el-icon>
+            <span>数据分析</span>
+          </template>
+          <el-menu-item index="6-1">统计分析</el-menu-item>
+        </el-sub-menu> -->
       </el-menu>
     </div>
 
     <!-- Main Content -->
     <div class="flex-1 overflow-auto">
-      <div class="p-6">
+      <div class="">
         <component :is="currentComponent"></component>
       </div>
     </div>
   </div>
-</template>
+</template>

+ 1 - 0
src/views/device/manhole/ldzh/ajgz.vue

@@ -0,0 +1 @@
+<template>案件跟踪</template>

+ 1 - 0
src/views/device/manhole/ldzh/bjgl.vue

@@ -0,0 +1 @@
+<template>报警管理</template>

+ 263 - 0
src/views/device/manhole/ldzh/jgkl.vue

@@ -0,0 +1,263 @@
+<script setup>
+import { getManholeDataAll } from "@/api/ldzh/index";
+import { computed, ref } from "vue";
+// 表格数据
+const tableData = ref();
+
+// 搜索条件
+const searchForm = ref({
+  id: "",
+  name: "",
+  district: "",
+  street: "",
+  road: "",
+  location: "",
+});
+
+// 是否显示详情弹窗
+const dialogVisible = ref(false);
+
+// 当前选中的井盖信息
+const selectedCover = ref({});
+
+// 根据搜索条件过滤数据
+const filteredTableData = computed(() => {
+  if (!Object.values(searchForm.value).some((value) => value)) {
+    return tableData.value;
+  }
+
+  return tableData.value.filter((row) => {
+    const matches = [
+      searchForm.value.id && row.id.includes(searchForm.value.id),
+      searchForm.value.name && row.name.includes(searchForm.value.name),
+      searchForm.value.district && row.district.includes(searchForm.value.district),
+      searchForm.value.street && row.street.includes(searchForm.value.street),
+      searchForm.value.road && row.road.includes(searchForm.value.road),
+      searchForm.value.location && row.location.includes(searchForm.value.location),
+    ];
+    return matches.some((match) => match);
+  });
+});
+
+// 搜索逻辑
+function search() {}
+
+// 显示详情
+function showDetail(row) {
+  selectedCover.value = row;
+  dialogVisible.value = true;
+}
+// 新增井盖表单数据
+const addForm = ref({
+  deviceName: "",
+  deviceNumber: "",
+  location: "排水",
+  model: "水务局",
+  remarks: "",
+  type: "",
+});
+
+// 控制新增井盖表单的显示与隐藏
+const addDialogVisible = ref(false);
+
+// 处理新增井盖表单提交
+function handleAddSubmit() {
+  if (
+    addForm.value.id &&
+    addForm.value.name &&
+    addForm.value.installationDate &&
+    addForm.value.district &&
+    addForm.value.street &&
+    addForm.value.road
+  ) {
+    tableData.value.push({ ...addForm.value });
+    addDialogVisible.value = false;
+  }
+}
+
+// 清空新增井盖表单
+function resetAddForm() {
+  addForm.value = {
+    id: "",
+    name: "",
+    purpose: "排水",
+    owner: "水务局",
+    installationDate: "",
+    district: "",
+    street: "",
+    road: "",
+    location: "",
+    status: "正常",
+    enabled: true,
+  };
+}
+
+function test() {
+  getManholeDataAll().then((res) => {
+    console.log(res);
+    tableData.value = res.data;
+  });
+}
+test();
+</script>
+
+<template>
+  <div>
+    <!-- 搜索表单 -->
+    <el-form :model="searchForm" label-width="80px">
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-form-item label="井盖编号">
+            <el-input v-model="searchForm.id" placeholder="请输入井盖编号"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="井盖名称">
+            <el-input v-model="searchForm.name" placeholder="请输入井盖名称"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="区">
+            <el-input v-model="searchForm.district" placeholder="请输入区"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="街道">
+            <el-input v-model="searchForm.street" placeholder="请输入街道"></el-input>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-form-item label="道路">
+            <el-input v-model="searchForm.road" placeholder="请输入道路"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="辅助定位">
+            <el-input
+              v-model="searchForm.location"
+              placeholder="请输入辅助定位地址"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item>
+            <el-button type="primary" @click="search">搜索</el-button>
+            <el-button type="success" @click="addDialogVisible = true"
+              >添加井盖</el-button
+            >
+            <el-button type="warning" @click="">导入</el-button>
+            <el-button type="danger" @click="">导出</el-button>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <!-- 表格 -->
+    <el-table :data="filteredTableData" style="width: 100%">
+      <!-- <el-table-column prop="id" label="井盖编号" width="180"></el-table-column>
+      <el-table-column prop="name" label="井盖名称" width="180"></el-table-column> -->
+      <el-table-column prop="alarmStatus" label="	报警状态"></el-table-column>
+      <el-table-column prop="createTime" label="创建时间"></el-table-column>
+      <el-table-column prop="deviceName" label="设备名称"></el-table-column>
+
+      <el-table-column prop="deviceNumber" label="设备编号"></el-table-column>
+      <el-table-column prop="id" label="主键"></el-table-column>
+      <el-table-column prop="location" label="位置"></el-table-column>
+      <el-table-column prop="model" label="设备型号"></el-table-column>
+      <el-table-column prop="onlineStatus" label="在线状态"></el-table-column>
+
+      <!-- <el-table-column prop="temperatureValue" label="温度值"></el-table-column> -->
+      <el-table-column prop="remarks" label="	备注"></el-table-column>
+      <el-table-column prop="type" label="设备类型"></el-table-column>
+      <el-table-column prop="updateTime" label="修改时间"></el-table-column>
+
+      <!-- <el-table-column prop="enabled" label="启用状态">
+        <template #default="scope">
+          <el-tag :type="scope.row.enabled ? 'success' : 'danger'">{{
+            scope.row.enabled ? "启用" : "禁用"
+          }}</el-tag>
+        </template>
+      </el-table-column> -->
+      <!-- <el-table-column label="操作">
+        <template #default="scope">
+          <el-button size="small" type="primary" @click="showDetail(scope.row)"
+            >查看详情</el-button
+          >
+        </template>
+      </el-table-column> -->
+    </el-table>
+
+    <!-- 查看详情弹窗 -->
+    <el-dialog title="井盖详情" v-model="dialogVisible">
+      <el-descriptions :column="1">
+        <el-descriptions-item label="井盖编号">{{
+          selectedCover.id
+        }}</el-descriptions-item>
+        <el-descriptions-item label="井盖名称">{{
+          selectedCover.name
+        }}</el-descriptions-item>
+        <el-descriptions-item label="井盖用途">{{
+          selectedCover.purpose
+        }}</el-descriptions-item>
+        <el-descriptions-item label="权属单位">{{
+          selectedCover.owner
+        }}</el-descriptions-item>
+        <el-descriptions-item label="安装时间">{{
+          selectedCover.installationDate
+        }}</el-descriptions-item>
+        <el-descriptions-item label="区">{{
+          selectedCover.district
+        }}</el-descriptions-item>
+        <el-descriptions-item label="街道">{{
+          selectedCover.street
+        }}</el-descriptions-item>
+        <el-descriptions-item label="道路">{{ selectedCover.road }}</el-descriptions-item>
+        <el-descriptions-item label="辅助定位地址">{{
+          selectedCover.location
+        }}</el-descriptions-item>
+        <el-descriptions-item label="井盖状态">{{
+          selectedCover.status
+        }}</el-descriptions-item>
+        <el-descriptions-item label="启用状态">{{
+          selectedCover.enabled ? "启用" : "禁用"
+        }}</el-descriptions-item>
+      </el-descriptions>
+    </el-dialog>
+    <!-- 添加井盖弹窗 -->
+    <el-dialog title="添加井盖" v-model="addDialogVisible" width="50%">
+      <el-form :model="addForm" label-width="80px">
+        <el-form-item label="设备名称">
+          <el-input v-model="addForm.name" placeholder="请输入井盖设备名称"></el-input>
+        </el-form-item>
+        <el-form-item label="设备编号">
+          <el-input
+            v-model="addForm.deviceNumber"
+            placeholder="请输入井盖设备编号"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="位置">
+          <el-input v-model="addForm.location" placeholder="请输入井盖位置"></el-input>
+        </el-form-item>
+        <el-form-item label="设备型号">
+          <el-input v-model="addForm.model" placeholder="请输入井盖设备型号"></el-input>
+        </el-form-item>
+        <el-form-item label="备注">
+          <el-input v-model="addForm.remarks" placeholder="请输入井盖备注"></el-input>
+        </el-form-item>
+        <el-form-item label="设备类型">
+          <el-input v-model="addForm.type" placeholder="请输入井盖设备类型"></el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="resetAddForm">取消</el-button>
+          <el-button type="primary" @click="handleAddSubmit">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<style scoped lang="scss"></style>

+ 1 - 0
src/views/device/manhole/ldzh/sgpb.vue

@@ -0,0 +1 @@
+<template>施工屏蔽</template>

+ 1 - 0
src/views/device/manhole/sjfx/tjfx.vue

@@ -0,0 +1 @@
+<template>统计分析</template>

+ 277 - 0
src/views/device/manhole/zcgl/jgzcgl.vue

@@ -0,0 +1,277 @@
+<script setup>
+import { getManholeDataAll } from "@/api/ldzh/index";
+import { computed, ref } from "vue";
+// 表格数据
+const tableData = ref();
+
+// 搜索条件
+const searchForm = ref({
+  id: "",
+  name: "",
+  district: "",
+  street: "",
+  road: "",
+  location: "",
+});
+
+// 是否显示详情弹窗
+const dialogVisible = ref(false);
+
+// 当前选中的井盖信息
+const selectedCover = ref({});
+
+// 根据搜索条件过滤数据
+const filteredTableData = computed(() => {
+  if (!Object.values(searchForm.value).some((value) => value)) {
+    return tableData.value;
+  }
+
+  return tableData.value.filter((row) => {
+    const matches = [
+      searchForm.value.id && row.id.includes(searchForm.value.id),
+      searchForm.value.name && row.name.includes(searchForm.value.name),
+      searchForm.value.district && row.district.includes(searchForm.value.district),
+      searchForm.value.street && row.street.includes(searchForm.value.street),
+      searchForm.value.road && row.road.includes(searchForm.value.road),
+      searchForm.value.location && row.location.includes(searchForm.value.location),
+    ];
+    return matches.some((match) => match);
+  });
+});
+
+// 搜索逻辑
+function search() {}
+
+// 显示详情
+function showDetail(row) {
+  selectedCover.value = row;
+  dialogVisible.value = true;
+}
+// 新增井盖表单数据
+const addForm = ref({
+  id: "",
+  name: "",
+  purpose: "排水",
+  owner: "水务局",
+  installationDate: "",
+  district: "",
+  street: "",
+  road: "",
+  location: "",
+  status: "正常",
+  enabled: true,
+});
+
+// 控制新增井盖表单的显示与隐藏
+const addDialogVisible = ref(false);
+
+// 处理新增井盖表单提交
+function handleAddSubmit() {
+  if (
+    addForm.value.id &&
+    addForm.value.name &&
+    addForm.value.installationDate &&
+    addForm.value.district &&
+    addForm.value.street &&
+    addForm.value.road
+  ) {
+    tableData.value.push({ ...addForm.value });
+    addDialogVisible.value = false;
+  }
+}
+
+// 清空新增井盖表单
+function resetAddForm() {
+  addForm.value = {
+    id: "",
+    name: "",
+    purpose: "排水",
+    owner: "水务局",
+    installationDate: "",
+    district: "",
+    street: "",
+    road: "",
+    location: "",
+    status: "正常",
+    enabled: true,
+  };
+}
+
+function test() {
+  getManholeDataAll().then((res) => {
+    console.log(res);
+  });
+}
+
+// import { clientGet } from "../../../../utils/apiClient";
+
+// const test = async () => {
+//   const res = await clientGet("/background/base/devices/getAll");
+//   console.log(res.data.data);
+//   tableData.value = res.data.data;
+// };
+test();
+</script>
+
+<template>
+  <div>
+    <!-- 搜索表单 -->
+    <el-form :model="searchForm" label-width="80px">
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-form-item label="井盖编号">
+            <el-input v-model="searchForm.id" placeholder="请输入井盖编号"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="井盖名称">
+            <el-input v-model="searchForm.name" placeholder="请输入井盖名称"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="区">
+            <el-input v-model="searchForm.district" placeholder="请输入区"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="街道">
+            <el-input v-model="searchForm.street" placeholder="请输入街道"></el-input>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-form-item label="道路">
+            <el-input v-model="searchForm.road" placeholder="请输入道路"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="辅助定位">
+            <el-input
+              v-model="searchForm.location"
+              placeholder="请输入辅助定位地址"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item>
+            <el-button type="primary" @click="search">搜索</el-button>
+            <el-button type="success" @click="addDialogVisible = true"
+              >添加井盖</el-button
+            >
+            <el-button type="warning" @click="">导入</el-button>
+            <el-button type="danger" @click="">导出</el-button>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <!-- 表格 -->
+    <el-table :data="filteredTableData" style="width: 100%">
+      <!-- <el-table-column prop="id" label="井盖编号" width="180"></el-table-column>
+      <el-table-column prop="name" label="井盖名称" width="180"></el-table-column> -->
+      <el-table-column prop="activationStatus" label="激活状态"></el-table-column>
+      <el-table-column prop="alarmStatus" label="报警状态"></el-table-column>
+      <el-table-column prop="angleAlarmThreshold" label="角度报警阈值"></el-table-column>
+
+      <el-table-column prop="batteryLevel" label="电池电量"></el-table-column>
+      <el-table-column prop="createTime" label="创建时间"></el-table-column>
+      <el-table-column prop="imeiCardNumber" label="IMEI卡号"></el-table-column>
+      <el-table-column prop="signalStrength" label="信号强度"></el-table-column>
+      <el-table-column prop="simCardNumber" label="SIM卡号"></el-table-column>
+
+      <!-- <el-table-column prop="temperatureValue" label="温度值"></el-table-column> -->
+      <el-table-column prop="tiltAngle" label="倾斜角度"></el-table-column>
+      <el-table-column prop="uploadTime" label="上传时间"></el-table-column>
+      <el-table-column prop="versionNumber" label="版本号"></el-table-column>
+
+      <!-- <el-table-column prop="enabled" label="启用状态">
+        <template #default="scope">
+          <el-tag :type="scope.row.enabled ? 'success' : 'danger'">{{
+            scope.row.enabled ? "启用" : "禁用"
+          }}</el-tag>
+        </template>
+      </el-table-column> -->
+      <!-- <el-table-column label="操作">
+        <template #default="scope">
+          <el-button size="small" type="primary" @click="showDetail(scope.row)"
+            >查看详情</el-button
+          >
+        </template>
+      </el-table-column> -->
+    </el-table>
+
+    <!-- 查看详情弹窗 -->
+    <el-dialog title="井盖详情" v-model="dialogVisible">
+      <el-descriptions :column="1">
+        <el-descriptions-item label="井盖编号">{{
+          selectedCover.id
+        }}</el-descriptions-item>
+        <el-descriptions-item label="井盖名称">{{
+          selectedCover.name
+        }}</el-descriptions-item>
+        <el-descriptions-item label="井盖用途">{{
+          selectedCover.purpose
+        }}</el-descriptions-item>
+        <el-descriptions-item label="权属单位">{{
+          selectedCover.owner
+        }}</el-descriptions-item>
+        <el-descriptions-item label="安装时间">{{
+          selectedCover.installationDate
+        }}</el-descriptions-item>
+        <el-descriptions-item label="区">{{
+          selectedCover.district
+        }}</el-descriptions-item>
+        <el-descriptions-item label="街道">{{
+          selectedCover.street
+        }}</el-descriptions-item>
+        <el-descriptions-item label="道路">{{ selectedCover.road }}</el-descriptions-item>
+        <el-descriptions-item label="辅助定位地址">{{
+          selectedCover.location
+        }}</el-descriptions-item>
+        <el-descriptions-item label="井盖状态">{{
+          selectedCover.status
+        }}</el-descriptions-item>
+        <el-descriptions-item label="启用状态">{{
+          selectedCover.enabled ? "启用" : "禁用"
+        }}</el-descriptions-item>
+      </el-descriptions>
+    </el-dialog>
+    <!-- 添加井盖弹窗 -->
+    <el-dialog title="添加井盖" v-model="addDialogVisible" width="50%">
+      <el-form :model="addForm" label-width="80px">
+        <el-form-item label="井盖编号">
+          <el-input v-model="addForm.id" placeholder="请输入井盖编号"></el-input>
+        </el-form-item>
+        <el-form-item label="井盖名称">
+          <el-input v-model="addForm.name" placeholder="请输入井盖名称"></el-input>
+        </el-form-item>
+        <el-form-item label="安装时间">
+          <el-date-picker
+            v-model="addForm.installationDate"
+            type="date"
+            placeholder="选择日期"
+            value-format="yyyy-MM-dd"
+          ></el-date-picker>
+        </el-form-item>
+        <el-form-item label="区">
+          <el-input v-model="addForm.district" placeholder="请输入区"></el-input>
+        </el-form-item>
+        <el-form-item label="街道">
+          <el-input v-model="addForm.street" placeholder="请输入街道"></el-input>
+        </el-form-item>
+        <el-form-item label="道路">
+          <el-input v-model="addForm.road" placeholder="请输入道路"></el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="resetAddForm">取消</el-button>
+          <el-button type="primary" @click="handleAddSubmit">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<style scoped lang="scss"></style>

+ 163 - 0
src/views/device/manhole/zcgl/qxda.vue

@@ -0,0 +1,163 @@
+<script setup>
+import { ref, computed } from "vue";
+import { ElMessage, ElMessageBox, ElDialog } from "element-plus";
+
+// 示例数据
+const data = [
+  {
+    id: 1,
+    name: "井盖A",
+    number: "JG-001",
+    purpose: "雨水排放",
+    ownership: "水务局",
+    location: "朝阳区建国路1号",
+    status: "正常",
+    smart: true,
+    area: "朝阳区",
+    street: "建国路",
+    road: "1号",
+    address: "1号",
+    problems: ["裂缝", "下沉"],
+    installationDate: "2022-01-01",
+  },
+  {
+    id: 2,
+    name: "井盖B",
+    number: "JG-001",
+    purpose: "雨水排放",
+    ownership: "水务局",
+    location: "朝阳区建国路1号",
+    status: "正常",
+    smart: true,
+    area: "朝阳区",
+    street: "建国路",
+    road: "1号",
+    address: "1号",
+    problems: ["裂缝", "下沉"],
+    installationDate: "2022-01-01",
+  },
+  // 更多数据...
+];
+
+// 表格数据
+const tableData = ref(data);
+
+// 搜索条件
+const searchForm = ref({
+  name: "",
+  installationDate: "",
+});
+
+// 根据搜索条件过滤数据
+const filteredTableData = computed(() => {
+  return tableData.value.filter((item) => {
+    const { name, installationDate } = searchForm.value;
+    const matchesName = !name || item.name.includes(name);
+    const matchesInstallationDate =
+      !installationDate || item.installationDate === installationDate;
+
+    return matchesName && matchesInstallationDate;
+  });
+});
+
+// 显示详情
+const detailVisible = ref(false);
+const detail = ref({});
+
+function showDetail(row) {
+  detail.value = row;
+  detailVisible.value = true;
+}
+
+// 重置搜索条件
+function resetSearchForm() {
+  Object.assign(searchForm.value, {
+    name: "",
+    installationDate: "",
+  });
+  ElMessage.success("搜索条件已重置");
+}
+</script>
+
+<template>
+  <div>
+    <!-- 搜索表单 -->
+    <el-form :model="searchForm" label-width="80px" inline>
+      <el-form-item label="井盖名称">
+        <el-input v-model="searchForm.name" placeholder="请输入井盖名称"></el-input>
+      </el-form-item>
+      <el-form-item label="安装日期">
+        <el-date-picker
+          v-model="searchForm.installationDate"
+          type="date"
+          placeholder="选择日期"
+          value-format="yyyy-MM-dd"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="resetSearchForm">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 表格 -->
+    <el-table :data="filteredTableData" style="width: 100%" stripe>
+      <el-table-column prop="name" label="井盖设备名称" width="180"> </el-table-column>
+      <el-table-column prop="number" label="井盖设备编号" width="180"> </el-table-column>
+      <el-table-column prop="purpose" label="井盖设备用途" width="180"> </el-table-column>
+      <el-table-column prop="ownership" label="权属单位" width="180"> </el-table-column>
+      <el-table-column prop="location" label="井盖设备位置"> </el-table-column>
+      <el-table-column prop="status" label="井盖设备状态" width="180"> </el-table-column>
+      <el-table-column prop="smart" label="是否智能井盖设备" width="180">
+        <template #default="{ row }">
+          <el-tag :type="row.smart ? 'success' : 'danger'">{{
+            row.smart ? "是" : "否"
+          }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column fixed="right" label="操作" width="100">
+        <template #default="{ row }">
+          <el-button size="small" type="primary" @click="showDetail(row)">查看</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 查看详情对话框 -->
+    <el-dialog v-model="detailVisible" title="井盖设备详情" width="50%">
+      <el-form label-position="top">
+        <el-form-item label="井盖设备名称">
+          {{ detail.name }}
+        </el-form-item>
+        <el-form-item label="井盖设备编号">
+          {{ detail.number }}
+        </el-form-item>
+        <el-form-item label="井盖设备用途">
+          {{ detail.purpose }}
+        </el-form-item>
+        <el-form-item label="权属单位">
+          {{ detail.ownership }}
+        </el-form-item>
+        <el-form-item label="井盖设备位置">
+          {{ detail.location }}
+        </el-form-item>
+        <el-form-item label="井盖设备状态">
+          {{ detail.status }}
+        </el-form-item>
+        <el-form-item label="是否智能井盖设备">
+          <el-tag :type="detail.smart ? 'success' : 'danger'">{{
+            detail.smart ? "是" : "否"
+          }}</el-tag>
+        </el-form-item>
+        <el-form-item label="问题">
+          <ul>
+            <li v-for="(problem, index) in detail.problems" :key="index">
+              {{ problem }}
+            </li>
+          </ul>
+        </el-form-item>
+        <el-form-item label="安装日期">
+          {{ detail.installationDate }}
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+  </div>
+</template>

+ 327 - 0
src/views/device/manhole/zcgl/znzdgl.vue

@@ -0,0 +1,327 @@
+<script setup>
+import { ref, computed } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+
+// 表格数据
+const tableData = ref([
+  {
+    id: "001",
+    name: "终端A",
+    type: "智能井盖",
+    imei: "123456789012345",
+    maintenanceUnit: "水务局",
+    installationDate: "2023-01-01",
+    capabilitySet: "通信,定位,报警",
+    status: "正常",
+    enabled: true,
+  },
+  {
+    id: "002",
+    name: "终端B",
+    type: "智能井盖",
+    imei: "098765432109876",
+    maintenanceUnit: "水务局",
+    installationDate: "2023-02-01",
+    capabilitySet: "通信,报警",
+    status: "正常",
+    enabled: true,
+  },
+  // 更多数据...
+]);
+
+// 搜索条件
+const searchForm = ref({
+  search: "",
+});
+
+// 是否显示详情弹窗
+const dialogVisible = ref(false);
+
+// 当前选中的终端信息
+const selectedTerminal = ref({});
+
+// 根据搜索条件过滤数据
+const filteredTableData = computed(() => {
+  return tableData.value.filter((item) => {
+    const searchValue = searchForm.value.search.toLowerCase();
+    return (
+      item.id.toLowerCase().includes(searchValue) ||
+      item.name.toLowerCase().includes(searchValue) ||
+      item.imei.toLowerCase().includes(searchValue) ||
+      item.capabilitySet.toLowerCase().includes(searchValue)
+    );
+  });
+});
+
+// 显示详情
+function showDetail(row) {
+  selectedTerminal.value = row;
+  dialogVisible.value = true;
+}
+
+// 新增终端表单数据
+const addForm = ref({
+  id: "",
+  name: "",
+  type: "",
+  imei: "",
+  maintenanceUnit: "",
+  installationDate: "",
+  capabilitySet: "",
+});
+
+// 控制新增终端表单的显示与隐藏
+const addDialogVisible = ref(false);
+
+// 处理新增终端表单提交
+function handleAddSubmit() {
+  if (
+    addForm.value.id &&
+    addForm.value.name &&
+    addForm.value.type &&
+    addForm.value.imei &&
+    addForm.value.maintenanceUnit &&
+    addForm.value.installationDate &&
+    addForm.value.capabilitySet
+  ) {
+    tableData.value.push({ ...addForm.value });
+    addDialogVisible.value = false;
+    ElMessage.success("终端添加成功");
+  } else {
+    ElMessage.error("请确保所有必填项都已填写");
+  }
+}
+
+// 清空新增终端表单
+function resetAddForm() {
+  addForm.value = {
+    id: "",
+    name: "",
+    type: "",
+    imei: "",
+    maintenanceUnit: "",
+    installationDate: "",
+    capabilitySet: "",
+  };
+}
+
+// 编辑终端表单数据
+const editForm = ref({
+  id: "",
+  name: "",
+  type: "",
+  imei: "",
+  maintenanceUnit: "",
+  installationDate: "",
+  capabilitySet: "",
+});
+
+// 控制编辑终端表单的显示与隐藏
+const editDialogVisible = ref(false);
+
+// 处理编辑终端表单提交
+function handleEditSubmit() {
+  if (
+    editForm.value.name &&
+    editForm.value.type &&
+    editForm.value.imei &&
+    editForm.value.maintenanceUnit &&
+    editForm.value.installationDate &&
+    editForm.value.capabilitySet
+  ) {
+    const index = tableData.value.findIndex((item) => item.id === editForm.value.id);
+    if (index !== -1) {
+      tableData.value[index] = { ...tableData.value[index], ...editForm.value };
+      editDialogVisible.value = false;
+      ElMessage.success("终端信息更新成功");
+    } else {
+      ElMessage.error("未找到指定终端");
+    }
+  } else {
+    ElMessage.error("请确保所有必填项都已填写");
+  }
+}
+
+// 清空编辑终端表单
+function resetEditForm() {
+  editForm.value = {
+    id: "",
+    name: "",
+    type: "",
+    imei: "",
+    maintenanceUnit: "",
+    installationDate: "",
+    capabilitySet: "",
+  };
+}
+
+// 显示编辑弹窗
+function showEdit(row) {
+  editForm.value = { ...row };
+  editDialogVisible.value = true;
+}
+</script>
+
+<template>
+  <div>
+    <!-- 搜索表单 -->
+    <el-form :model="searchForm" label-width="80px">
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-form-item label="搜索">
+            <el-input
+              v-model="searchForm.search"
+              placeholder="请输入终端编号、名称、IMEI号或能力集"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-form-item>
+        <el-button type="primary" @click="search">搜索</el-button
+        ><!-- 添加终端按钮 -->
+        <el-button type="success" @click="addDialogVisible = true">添加终端</el-button>
+        <el-button type="warning" @click="">导入</el-button>
+        <el-button type="danger" @click="">导出</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 表格 -->
+    <el-table :data="filteredTableData" style="width: 100%">
+      <el-table-column prop="id" label="终端编号" sortable></el-table-column>
+      <el-table-column prop="name" label="终端名称" sortable></el-table-column>
+      <el-table-column prop="type" label="终端类型" sortable></el-table-column>
+      <el-table-column prop="imei" label="终端IMEI号" sortable></el-table-column>
+      <el-table-column prop="maintenanceUnit" label="运维单位" sortable></el-table-column>
+      <el-table-column
+        prop="installationDate"
+        label="安装时间"
+        sortable
+      ></el-table-column>
+      <el-table-column prop="capabilitySet" label="能力集" sortable></el-table-column>
+      <el-table-column label="操作">
+        <template #default="scope">
+          <el-button size="small" type="primary" @click="showDetail(scope.row)"
+            >查看详情</el-button
+          >
+          <el-button size="small" type="success" @click="showEdit(scope.row)"
+            >编辑</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 查看详情弹窗 -->
+    <el-dialog title="智能终端详情" v-model="dialogVisible">
+      <el-form label-width="80px">
+        <el-form-item label="终端编号">
+          <span>{{ selectedTerminal.id }}</span>
+        </el-form-item>
+        <el-form-item label="终端名称">
+          <span>{{ selectedTerminal.name }}</span>
+        </el-form-item>
+        <el-form-item label="终端类型">
+          <span>{{ selectedTerminal.type }}</span>
+        </el-form-item>
+        <el-form-item label="终端IMEI号">
+          <span>{{ selectedTerminal.imei }}</span>
+        </el-form-item>
+        <el-form-item label="运维单位">
+          <span>{{ selectedTerminal.maintenanceUnit }}</span>
+        </el-form-item>
+        <el-form-item label="安装时间">
+          <span>{{ selectedTerminal.installationDate }}</span>
+        </el-form-item>
+        <el-form-item label="能力集">
+          <span>{{ selectedTerminal.capabilitySet }}</span>
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+    <!-- 添加终端弹窗 -->
+    <el-dialog title="添加智能终端" v-model="addDialogVisible" width="50%">
+      <el-form :model="addForm" label-width="80px">
+        <el-form-item label="终端编号">
+          <el-input v-model="addForm.id" placeholder="请输入终端编号"></el-input>
+        </el-form-item>
+        <el-form-item label="终端名称">
+          <el-input v-model="addForm.name" placeholder="请输入终端名称"></el-input>
+        </el-form-item>
+        <el-form-item label="终端类型">
+          <el-input v-model="addForm.type" placeholder="请输入终端类型"></el-input>
+        </el-form-item>
+        <el-form-item label="终端IMEI号">
+          <el-input v-model="addForm.imei" placeholder="请输入终端IMEI号"></el-input>
+        </el-form-item>
+        <el-form-item label="运维单位">
+          <el-input
+            v-model="addForm.maintenanceUnit"
+            placeholder="请输入运维单位"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="安装时间">
+          <el-date-picker
+            v-model="addForm.installationDate"
+            type="date"
+            placeholder="选择日期"
+            value-format="yyyy-MM-dd"
+          ></el-date-picker>
+        </el-form-item>
+        <el-form-item label="能力集">
+          <el-input v-model="addForm.capabilitySet" placeholder="请输入能力集"></el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="resetAddForm">取消</el-button>
+          <el-button type="primary" @click="handleAddSubmit">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    <!-- 编辑终端弹窗 -->
+    <el-dialog title="编辑智能终端" v-model="editDialogVisible" width="50%">
+      <el-form :model="editForm" label-width="80px">
+        <el-form-item label="终端编号">
+          <el-input
+            v-model="editForm.id"
+            disabled
+            placeholder="终端编号不可修改"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="终端名称">
+          <el-input v-model="editForm.name" placeholder="请输入终端名称"></el-input>
+        </el-form-item>
+        <el-form-item label="终端类型">
+          <el-input v-model="editForm.type" placeholder="请输入终端类型"></el-input>
+        </el-form-item>
+        <el-form-item label="终端IMEI号">
+          <el-input v-model="editForm.imei" placeholder="请输入终端IMEI号"></el-input>
+        </el-form-item>
+        <el-form-item label="运维单位">
+          <el-input
+            v-model="editForm.maintenanceUnit"
+            placeholder="请输入运维单位"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="安装时间">
+          <el-date-picker
+            v-model="editForm.installationDate"
+            type="date"
+            placeholder="选择日期"
+            value-format="yyyy-MM-dd"
+          ></el-date-picker>
+        </el-form-item>
+        <el-form-item label="能力集">
+          <el-input
+            v-model="editForm.capabilitySet"
+            placeholder="请输入能力集"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="resetEditForm">取消</el-button>
+          <el-button type="primary" @click="handleEditSubmit">保存</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>

+ 1 - 0
src/views/device/manhole/zdyw/gzgl.vue

@@ -0,0 +1 @@
+<template>故障管理</template>

+ 1 - 0
src/views/device/manhole/zdyw/sjtj.vue

@@ -0,0 +1 @@
+<template>数据统计</template>

+ 1 - 0
src/views/device/manhole/zdyw/ywrwgl.vue

@@ -0,0 +1 @@
+<template>运维任务管理</template>

+ 8 - 2
vite.config.js

@@ -29,12 +29,18 @@ export default defineConfig(({ mode, command }) => {
       host: true,
       open: true,
       proxy: {
+        '/api': {
+          target: 'http://192.168.110.235:8100/',
+          changeOrigin: true,
+          rewrite: (p) => p.replace(/^\/api/, '')
+        },
         // https://cn.vitejs.dev/config/#server-proxy
         '/dev-api': {
-          target: 'http://192.168.110.93:8080',
+          target: 'http://192.168.110.235:8100/background',
           changeOrigin: true,
           rewrite: (p) => p.replace(/^\/dev-api/, '')
-        }
+        },
+        
       }
     },
     //fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file