3 Komitmen 2d25af7079 ... ceb635a02b

Pembuat SHA1 Pesan Tanggal
  yhfu ceb635a02b Merge branch 'lifeline_develop_siping' of http://116.142.80.13:3000/sooka_onest/visu_lifeline into lifeline_develop_siping 4 hari lalu
  yhfu 4e9d18ff3e Add - 应急中心界面完善 4 hari lalu
  yhfu 5175a78944 Add - 预警中心界面完善 4 hari lalu

TEMPAT SAMPAH
src/assets/images/emergencyTile.png


TEMPAT SAMPAH
src/assets/images/warningBg.png


+ 9 - 0
src/router/index.js

@@ -91,6 +91,15 @@ export const constantRoutesNew = [{
 				}
 			},
 			{
+				//哨兵应急中心
+				path: '/SentryEmergencyCenter',
+				name: 'SentryEmergencyCenter',
+				component: () => import('@/views/SentryEmergencyCenter'),
+				meta: {
+					title: '哨兵-应急中心'
+				}
+			},
+			{
 				//哨兵设备中心
 				path: '/SenEquipmentCenter',
 				name: 'SenEquipmentCenter',

+ 56 - 0
src/views/SenWarningCenter.vue

@@ -7,6 +7,31 @@
 
 <template>
     <div>
+        <div class="warning_left" style="top: 70px;">
+			<h4>可燃气体泄露预警</h4>
+            <h2>3056</h2>
+            <img src="@/assets/images/warningBg.png">
+		</div>
+        <div class="warning_left" style="top: 240px;">
+			<h4>位移预警</h4>
+            <h2>355</h2>
+            <img src="@/assets/images/warningBg.png">
+		</div>
+        <div class="warning_left" style="top: 410px;">
+			<h4>振动预警</h4>
+            <h2>937</h2>
+            <img src="@/assets/images/warningBg.png">
+		</div>
+        <div class="warning_left" style="top: 580px;">
+			<h4>水位预警</h4>
+            <h2>37</h2>
+            <img src="@/assets/images/warningBg.png">
+		</div>
+        <div class="warning_left" style="top: 747px;">
+			<h4>异常流量预警</h4>
+            <h2>86</h2>
+            <img src="@/assets/images/warningBg.png">
+		</div>
         <div class="con_right con_left_js" style="top: 70px;">
 			<div class="list_tit">可燃气体泄露预警说明</div>
 			<!-- 预警说明内容主体 -->
@@ -107,5 +132,36 @@ export default {
 		width: 400px !important;
 	}
 
+    .warning_left{
+        position: absolute;
+        z-index: 99;
+        left: 30px;
+        top: 100px;
+        width: 250px;
+        margin-top: 1%;
+        text-align: center;
+        padding: 0px 10px 20px 10px!important;
+
+        h4{
+            font-weight: 700;
+            color: transparent;
+            background: linear-gradient(to bottom, #fff, #7AC0CA);
+            -webkit-background-clip: text; /* 裁剪背景到文字 */
+            -webkit-text-fill-color: transparent; /* 让文字填充透明,显示背景 */
+        }
+
+        h2{
+            position: absolute;
+            width: 93%;
+            color: transparent;
+            background: linear-gradient(to bottom, #fff, #7AC0CA);
+            -webkit-background-clip: text; /* 裁剪背景到文字 */
+            -webkit-text-fill-color: transparent; /* 让文字填充透明,显示背景 */
+            font-family: 'ysbth';
+            letter-spacing: 2px;
+            transform: skewX(-16deg);
+        }
+    }
+
 
 </style>

+ 664 - 0
src/views/SentryEmergencyCenter.vue

@@ -0,0 +1,664 @@
+/*
+ *@description: 哨兵-应急中心
+ *@author: yh Fu
+ *@date: 2025-09-23 09:48:41
+ *@version: V1.0.5
+*/
+<template>
+	<div class="visual-con hz_body">
+		<!--主体-->
+		<div class="con_left" style="height: 83%;">
+			<div class="list_tit">应急中心</div>
+			<el-input
+					placeholder="请输入事件名称"
+					suffix-icon="el-icon-search"
+					v-model="listParams.deviceName">
+			   <template #append></template>
+            </el-input>
+			<dl class="sp_list">
+				<dt>
+					<span class="dt1">序号</span>
+					<span class="dt2">设备名称</span>
+					<span class="dt3">定位</span>
+				</dt>
+				<div class="hei_scroll hei56">
+					<dd v-for="(e,idx) in deviceListSearch" :key="idx" @click="dropLocation(e.latitude,e.longitude)">
+						<span class="dt1">{{ idx + 1 }}</span>
+						<span class="dt2">{{ e.deviceName }}</span>
+						<span class="dt3">
+							<img
+								style="cursor: pointer;"
+								src="../assets/images/sentinel/hz_list_d.png"
+							/>
+						</span>
+					</dd>
+				</div>
+			</dl>
+			<el-pagination
+					background
+                    style="justify-content: space-between;display: flex;"
+					layout="prev, pager, next"
+					:current-page.sync="listParams.pageNum"
+					@current-change="pageNumHasChanged"
+					:total="deviceTotal">
+			</el-pagination>
+		</div>
+		<div class="visual-body">
+			<!--弹框演示模板 开始-->
+			<!-- <img src="../assets/images/sentinel/hz_qy.png" class="qydw1"/>
+			<img src="../assets/images/sentinel/hz_qy.png" class="qydw2"/>
+			<img src="../assets/images/sentinel/hz_qy.png" class="qydw3"/> -->
+			<div class="tk_div" v-show="isDetailVisible">
+				<div class="tk1 tk_bor" style="width: 371px;height: 310px;">
+					<h1>
+						<span :title="detailInfo.deviceName || '--'" style="display: inline-block;overflow: hidden;width: 62%;text-overflow: ellipsis;">{{ detailInfo.deviceName || '--' }}</span>
+						<i class="el-icon el-icon-close" style="margin-left: 5%;cursor: pointer;" @click="closeDetail"></i>
+						<i>{{ detailInfo.workingStatus == '0' ? '在线' : '离线' }}</i>
+					</h1>
+					<p>设备名称:{{ detailInfo.deviceName || '--' }}</p>
+					<p>设备类型:{{ detailInfo.deviceTypeText || '--' }}</p>
+					<p>设备监测指标:{{ detailInfo.threshold || '--' }}</p>
+					<p>品牌:{{ detailInfo.brand || '--' }}</p>
+					<p>所在街道:{{ detailInfo.address || '--' }}</p>
+					<p>历史数值:<a  @click="toggleDisplay(detailInfo.deviceCode)">详情</a></p>
+				</div>
+				<div class="tk2 tk_bor"  v-if="isVisible" style="position: absolute;width: 466px;height: 455px;left: 98%;">
+					<h1>哨兵详情</h1>
+					<div id="sbxqChart" ref="MyChart"></div>
+				</div>
+			</div>
+			<!--弹框演示模板 结束-->
+
+
+			<!-- 地图 -->
+			<supermap ref="supermap" style="width: 100%;height: 100vh;" @preview="preview">
+			</supermap>
+		</div>
+        <div class="con_left" style="left: 1572px;height: 83%;">
+			<div class="list_tit">应急预案列表</div>
+			<el-input
+					placeholder="请输入应急预案名称"
+					suffix-icon="el-icon-search"
+					v-model="listParams.deviceName">
+			   <template #append></template>
+            </el-input>
+			<dl class="sp_list">
+				<div class="hei_scroll hei56">
+					<!-- <dd v-for="(e,idx) in deviceListSearch" :key="idx" @click="dropLocation(e.latitude,e.longitude)">
+						<span class="dt1">{{ idx + 1 }}</span>
+						<span class="dt2">{{ e.deviceName }}</span>
+						<span class="dt3">
+							<img
+								style="cursor: pointer;"
+								src="../assets/images/sentinel/hz_list_d.png"
+							/>
+						</span>
+					</dd> -->
+				</div>
+			</dl>
+		</div>
+
+        <!-- 应急事件详情弹窗 -->
+        <el-dialog
+            title="应急事件详情"
+            :visible.sync="dialogVisible"
+            custom-class="emergencyEventDialog"
+            style="margin-top: 5vh !important;"
+            >
+            <div class="transferBg d1">
+                <h4>事件基本信息</h4>
+                <div class="eventInfo_contain">
+                    <div>事件名称:超级大街燃气泄漏</div>
+                    <div>事件类型:燃气</div>
+                    <div>事件发起时间:2025/02/06 11:45:11</div>
+                    <div>事件发起人:张三</div>
+                    <div>事件发生位置:紫气大街19号5694</div>
+                    <div>事件发起原因:燃气管道泄漏</div>
+                </div>
+            </div>
+            <div class="transferBg d2">
+                <h4>事件处理流程</h4>
+            </div>
+            <div class="d3">
+                <div class="transferBg video">
+                    <h4>现场画面</h4>
+                </div>
+                <div class="mid">
+                    <div class="transferBg info"></div>
+                    <div class="transferBg pics"></div>
+                </div>
+                <div class="right transferBg">
+
+                </div>
+            </div>
+        </el-dialog>
+	</div>
+</template>
+
+<script>
+	import Cookies from 'js-cookie'
+	import supermap from '@/components/supermap-2.5d' //超图
+	import {getUserProfile} from "@/api/system/user";
+	import {
+		listDeviceAll,
+		selectBrandList,
+		selectByDeviceId,
+		selectDailyThreshold
+	} from "@/api/sentinel"
+
+	import '../assets/styles/sb_body.css';
+
+	import {
+		selectConfigKey
+	} from "@/api/system/config";
+	// import * as echarts from 'echarts'
+	let echarts = require("echarts");
+	export default {
+		name:'MyChart',
+		components: {
+			supermap,
+		},
+		metaInfo () {
+			return {
+				title:'四平市智慧哨兵监管平台',
+				meta:[{
+					charset: "utf-8"
+				},
+					{
+						name: "viewport",
+						content: "width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
+					}]
+			}
+		},
+		created() {
+			this.getListDeviceAll()
+			// 查询品牌
+			selectBrandList().then(res => {
+				if(res.data){
+					let brandoptions = []
+					res.data.forEach(e => {
+						brandoptions.push({
+							value:e,
+							label:e
+						})
+					})
+					this.options = brandoptions
+				}
+			})
+		},
+		mounted() {
+			// 初始化地图数据
+			// this.getSuperMapUrl();
+			setTimeout(() => {
+				this.title = '四平市智慧哨兵监管平台'
+			}, 1000);
+		},
+		data() {
+			return {
+				isVisible: false, // 初始时设置为false,不显示内容
+				input:'',
+				input1: '',
+				title:'四平市智慧哨兵监管平台',
+				deviceList:[],       		 	// 设备列表
+				deviceListSearch:[],        	// 设备列表检索
+        		deviceTotal:0,
+				listParams:{
+					brand:'',
+					deviceName:'',
+					pageNum: 1,
+        			pageSize: 10,
+				},								// 设备列表条件检索
+				options: [],
+				value: '',
+				isDetailVisible:false,          // 设备弹窗显隐flag
+				detailInfo:{},                  // 设备详情信息
+                dialogVisible:true
+			}
+		},
+		methods: {
+			closeDetail(){
+				this.isDetailVisible = false
+				this.isVisible = false
+			},
+			dropLocation(lat, lng) {
+				this.$parent.$refs.supermap.dropLocation(lat*1, lng*1)
+			},
+			pageNumHasChanged(e){
+				this.getListDeviceAll()
+			},
+			// 查询设备列表
+			getListDeviceAll(){
+				listDeviceAll(this.listParams).then(res => {
+					this.deviceList = res.rows
+					this.deviceListSearch = res.rows
+          			this.deviceTotal = res.total
+					let deviceMarkersList = []
+					// hz_qy
+					if (res.rows != null && res.rows.length > 0) {
+						for (let i = 0; i < res.rows.length; i++) {
+							console.log('设备信息',res.rows[i])
+							let markersMap = {
+							lng: 124.59,
+							lat: 43.02,
+							icon: "hzqy",
+							bindPopupHtml: "",
+							click: "preview",
+							parameter: {
+								id:res.rows[i].id || '',
+							},
+							keepBindPopup: false,
+							isAggregation: false,
+							};
+							markersMap.lng = res.rows[i].longitude*1;
+							markersMap.lat = res.rows[i].latitude*1;
+							markersMap.radius = res.rows[i].cameraRadius || '';
+							deviceMarkersList.push(markersMap);
+						}
+						setTimeout(() => {
+							this.$parent.$refs.supermap.clearM();
+							this.$parent.$refs.supermap.setMarkers(deviceMarkersList);
+						}, 3000);
+					} else {
+						setTimeout(() => {
+							this.$parent.$refs.supermap.clearM();
+							this.$parent.$refs.supermap.clearMRadius();
+						}, 1000);
+					}
+				})
+			},
+			preview(e){
+				selectByDeviceId({id:e.id}).then(res => {
+					this.detailInfo = res.data
+					console.log('this.detailInfo',this.detailInfo)
+					this.isDetailVisible = true
+				})
+			},
+			brandHasChanged(e){
+				this.getListDeviceAll()
+			},
+			/**
+			 * desc: 设备列表条件检索
+			 * @param {string} [val=''] 		// 设备名称
+			 * @param {string} [brandName=''] 	// 品牌
+			 * */
+			searchOptionHasChanged(val='',brandName=''){
+				this.deviceListSearch = [];
+				// 名称检索
+				for (let i in this.deviceList) {
+					if (this.deviceList[i].deviceName.indexOf(val) != -1) {
+						this.deviceListSearch.push(this.deviceList[i]);
+					}
+				}
+				// 品牌检索
+				if(brandName){
+					this.deviceListSearch = this.deviceListSearch.filter(v => v.brand == brandName)
+				}
+			},
+			getSuperMapUrl(){
+				getUserProfile().then(response => {
+					let mapDeptId=response.mapDeptId
+					let num = 0;
+					if (mapDeptId == "365") {
+						num = 0;
+					} else if (mapDeptId == "369") {
+						num = 1;
+					} else if (mapDeptId == "371") {
+						num = 2;
+					} else if (mapDeptId == "373") {
+						num = 3;
+					} else if (mapDeptId == "372") {
+						num = 4;
+					} else if (mapDeptId == "370") {
+						num = 5;
+					}
+					this.$parent.$refs.supermap.removeAllviewer(mapDeptId, -1);
+				});
+			},
+			toggleDisplay(deviceCode) {
+				this.isVisible = !this.isVisible; // 点击按钮时切换isVisible的值
+				if(this.isVisible){
+					selectDailyThreshold(deviceCode).then(res => {
+						this.initChart(res.data)
+					})
+				}
+			},
+			initChart(data){
+				// 基于准备好的dom,初始化echarts实例
+				const myChart = echarts.init(document.getElementById('sbxqChart'))
+				let xdata = data.time //x轴
+				let dataArr = data.value //value
+				let dashedArr = data.threshold
+				let titleName = "阈值";
+				let titleNames = "实际值";
+				let option = {
+					backgroundColor: "rgba(25,44,59,.4)",
+					grid: {
+						left: "5%",
+						bottom: "10%",
+						top: "18%",
+						containLabel: true,
+					},
+					tooltip: {
+						trigger: "axis",
+						axisPointer: {
+							type: "shadow",
+						},
+					},
+					legend: {
+						show: true,
+						x: "center",
+						y: 20,
+						textStyle: {
+							color: "#fff", // 图例文字颜色
+							fontSize: 16,
+						},
+					},
+					xAxis: {
+						type: "category",
+						boundaryGap: false,
+						data: xdata,
+						axisLabel: {
+							show: true,
+							textStyle: {
+								color: "#fff",
+							},
+						},
+						axisLine: {
+							lineStyle: {
+								color: "transparent",
+								width: 2, //这里是为了突出显示加上的
+							},
+						},
+					},
+					"dataZoom": [
+						{
+							"show": true,
+							"height": 12,
+							"xAxisIndex": [
+							0
+							],
+							"bottom": "8%",
+							"start": 0,
+							"end": 50,
+							"handleIcon": "path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z",
+							"handleSize": "110%",
+							"handleStyle": {
+							"color": "#d3dee5"
+							},
+							"textStyle": {
+							"color": "#fff"
+							},
+							"borderColor": "#90979c"
+						},
+						{
+							"type": "inside",
+							"show": true,
+							"height": 15,
+							"start": 1,
+							"end": 35
+						}
+					],
+					yAxis: [
+						{
+							type: "value",
+							name: "(%vol)",
+							nameTextStyle: {
+								color: "#fff",
+							},
+							axisLabel: {
+								formatter: "{value}",
+								textStyle: {
+									color: "#fff",
+								},
+							},
+							axisLine: {
+								lineStyle: {
+									color: "transparent",
+									width: 2, //这里是为了突出显示加上的
+								},
+							},
+							axisTick: {
+								show: false,
+							},
+							splitLine: {
+								show: true,
+								lineStyle: {
+									color: "#11366e",
+								},
+							},
+						},
+					],
+					series: [
+						{
+							name: titleName,
+							type: "line",
+							smooth: true,
+							symbol: "none",
+							itemStyle: {
+								normal: {
+									lineStyle: {
+										type: "dashed",
+									},
+									color: "#01F699", //拐点的颜色
+									borderColor: "#01F699", //拐点边框的颜色
+								},
+							},
+							data: dashedArr,
+						},
+						{
+							name: titleNames,
+							type: "line",
+							stack: "总量",
+							smooth: true, //平滑曲线显示
+							symbol: "circle", //标记的图形为实心圆
+							symbolSize: 8,
+							itemStyle: {
+								normal: {
+									color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+										{
+											offset: 0,
+											color: "rgba(3,191,255,1)",
+										},
+										{
+											offset: 1,
+											color: "rgba(18,93,236,1)",
+										},
+									]),
+									areaStyle: {
+										color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
+											{
+												offset: 0,
+												color: "rgba(3,191,255,.3)",
+											},
+											{
+												offset: 1,
+												color: "rgba(18,93,236,.3)",
+											},
+										]),
+									},
+								},
+							},
+							data: dataArr,
+						},
+					],
+				};
+				myChart.setOption(option);
+			}
+		},
+		watch:{
+			['listParams.deviceName'](){
+				this.getListDeviceAll()
+			}
+		}
+	}
+</script>
+<style rel="stylesheet/scss" lang="scss">
+	.visual-con .el-input__inner {
+		border: 1px solid #3bb8a4;
+		background-color: rgba(20, 107, 115, 0.3);
+		color: #fff;
+	}
+
+
+	.hz_body{
+		position: relative;
+	}
+	i,b,u{
+		font-style: normal;
+		text-decoration: none;
+	}
+
+    .emergencyEventDialog{
+        width: 97%;
+        height: 95%;
+        border-radius: 10px;
+        .el-dialog__body{
+            height: 93%;
+            color: #fff;
+        }
+        .transferBg{
+            background: linear-gradient(to bottom, rgba(29,57,58,.9) ,rgba(35,42,48,.9));
+            border-radius: 10px;
+        }
+        .d1{
+            height: 20%;
+        }
+        .d2{
+            height: 20%;
+            margin-top: 1%;
+        }
+        .d3{
+            display: flex;
+            height: 56%;
+            margin-top: 1%;
+            .video{
+                width: 38%;
+            }
+            .mid{
+                width: 30%;
+                margin-left: 1.5%;
+                .info{
+                    width: 100%;
+                    height: 48.5%;
+                }
+                .pics{
+                    width: 100%;
+                    height: 48.5%;
+                    margin-top: 2%;
+                }
+            }
+            .right{
+                width: 30%;
+                margin-left: 1.5%;
+            }
+        }
+    }
+
+
+	.qydw1{
+		position: absolute;
+		top: 60%;
+		left: 40%;
+		display: block;
+		width:54px ;
+		height: 77px;
+	}
+	.qydw2{
+		position: absolute;
+		top: 50%;
+		left: 70%;
+		display: block;
+		width:54px ;
+		height: 77px;
+	}
+	.qydw3{
+		position: absolute;
+		top: 40%;
+		left: 80%;
+		display: block;
+		width:54px ;
+		height: 77px;
+	}
+
+	.tk_div{
+		width: 21%;
+		height: 36%;
+		position: absolute;
+		top: 24%;
+		left: 32.2%;
+		z-index: 98;
+		display: flex;
+		flex-direction: row;
+	}
+	.tk_bor{
+		padding: 15px!important;
+		border: 3px solid #28727e;
+		box-shadow: 0px 0px 24px #28727e;
+		background: rgba(0,0,0,0.39);
+	}
+	.tk_bor h1{
+		padding-left: 20px;
+		background: url("../assets/images/sentinel/hz_k.png") no-repeat left;
+		font-size: 18px;
+		color: #e0e5fa;
+		font-weight: bold;
+		height: 38px;
+		line-height: 38px;
+	}
+	.tk_bor h1 i{
+		display: inline-block;
+		float: right;
+		background: #3bad96;
+		padding: 0px 10px;
+		color: #fff;
+		font-size: 16px;
+		height: 30px;
+		line-height: 30px;
+		position: relative;
+		border-radius: 4px;
+	}
+	.tk_bor h1 i::after{
+		display: block;
+		content: '';
+		border-bottom: 9px solid transparent;
+		border-right: 9px solid #3bad96;
+		border-top: 9px solid transparent;
+		position: absolute;
+		left:-8px;
+		top:8px;
+	}
+	.tk_bor p{
+		padding-left: 20px;
+		background: url("../assets/images/sentinel/hz_k.png") no-repeat left;
+		background-size: 12px;
+		font-size: 16px;
+		color: #fff;
+		line-height: 35px;
+	}
+	.tk_bor p a{
+		color: #6bf5f2;
+		text-underline-offset: 0.4em;
+		text-decoration: underline;
+	}
+	.tk_bor p a:hover{
+		color: #6bf5f2;
+		text-underline-offset: 0.4em;
+		text-decoration: underline;
+		cursor: pointer;
+	}
+	.tk1{
+		position: relative;
+		margin-right: 20px!important;
+	}
+
+	#sbxqChart{
+		width: 100%;
+		height: 91%;
+	}
+
+
+
+</style>
+<style rel="stylesheet/scss" lang="scss" scoped>
+	@import '@/assets/styles/base.scss';
+</style>

+ 10 - 10
src/views/SentryPage.vue

@@ -9,18 +9,18 @@
 
  <template>
     <div class="visual-con hz_body">
-    <router-view ref="senEventCenter"></router-view>
+    <!-- <router-view ref="senEventCenter"></router-view> -->
 		<div class="s_header">
 			<div class="head_btn">
-        <div @click="jumpTo('/SentryCockpit',0)" :class="routerIdx == 0 ? 'on' : ''">
-            <i>驾驶舱</i>
-        </div>
-        <div @click="jumpTo('/SenEquipmentCenter',1)" :class="routerIdx == 1 ? 'on' : ''">
-            <i>设备中心</i>
-        </div>
-        <div @click="jumpTo('???')" :class="routerIdx == 1 ? 'on' : ''">
-            <i>应急中心</i>
-        </div>
+          <div @click="jumpTo('/SentryCockpit',0)" :class="routerIdx == 0 ? 'on' : ''">
+              <i>驾驶舱</i>
+          </div>
+		  <div @click="jumpTo('/SentryEmergencyCenter',5)" :class="routerIdx == 5 ? 'on' : ''">
+              <i>应急中心</i>
+          </div>
+          <div @click="jumpTo('/SenEquipmentCenter',1)" :class="routerIdx == 1 ? 'on' : ''">
+              <i>设备中心</i>
+          </div>
       </div>
       <div class="header_tit"><i>{{title}}</i></div>
       <div class="head_btn">