From 440f11bade4901ea4bb6e935019e01748c193ad0 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 13 八月 2025 15:55:09 +0800
Subject: [PATCH] 安全监控页面添加

---
 src/views/productionManagement/safetyMonitoring/index.vue |  873 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 873 insertions(+), 0 deletions(-)

diff --git a/src/views/productionManagement/safetyMonitoring/index.vue b/src/views/productionManagement/safetyMonitoring/index.vue
new file mode 100644
index 0000000..8416914
--- /dev/null
+++ b/src/views/productionManagement/safetyMonitoring/index.vue
@@ -0,0 +1,873 @@
+<template>
+	<div class="safety-monitoring">
+		<el-row :gutter="20">
+			<!-- 宸︿晶锛氬疄鏃剁洃鎺у尯鍩� -->
+			<el-col :span="16">
+				<el-card class="monitoring-card">
+					<div slot="header" class="card-header">
+						<span>瀹炴椂姘斾綋娴撳害鐩戞帶</span>
+						<el-tag :type="systemStatus === 'normal' ? 'success' : 'danger'">
+							{{ systemStatus === 'normal' ? '绯荤粺姝e父' : '绯荤粺鍛婅' }}
+						</el-tag>
+					</div>
+					
+					<!-- 鍌ㄧ綈鍖虹洃鎺� -->
+					<div class="monitoring-section">
+						<h3>鍌ㄧ綈鍖虹洃鎺�</h3>
+						<div class="sensor-grid">
+							<div class="sensor-item" v-for="sensor in tankSensors" :key="sensor.id">
+								<div class="sensor-header">
+									<span>{{ sensor.name }}</span>
+									<el-tag :type="sensor.status === 'normal' ? 'success' : 'danger'" size="small">
+										{{ sensor.status === 'normal' ? '姝e父' : '瓒呮爣' }}
+									</el-tag>
+								</div>
+								<div class="sensor-data">
+									<div class="data-item">
+										<span>鐢茬兎: {{ sensor.methane.toFixed(2) }}%</span>
+										<el-progress
+											:percentage="Math.min(Math.round(sensor.methane * 40 * 100) / 100, 100)"
+											:color="getProgressColor(Math.min(Math.round(sensor.methane * 40 * 100) / 100, 100), 80)"
+											:format="formatProgress"
+											:stroke-width="8"
+										/>
+									</div>
+									<div class="data-item">
+										<span>纭寲姘�: {{ sensor.h2s.toFixed(2) }}ppm</span>
+										<el-progress
+											:percentage="Math.min(Math.round((sensor.h2s / 20) * 100 * 100) / 100, 100)"
+											:color="getProgressColor(Math.min(Math.round((sensor.h2s / 20) * 100 * 100) / 100, 100), 80)"
+											:format="formatProgress"
+											:stroke-width="8"
+										/>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+					
+					<!-- 浜曞彛鍘嬬缉鏈虹洃鎺� -->
+					<div class="monitoring-section">
+						<h3>浜曞彛鍘嬬缉鏈虹洃鎺�</h3>
+						<div class="sensor-grid">
+							<div class="sensor-item" v-for="sensor in compressorSensors" :key="sensor.id">
+								<div class="sensor-header">
+									<span>{{ sensor.name }}</span>
+									<el-tag :type="sensor.status === 'normal' ? 'success' : 'danger'" size="small">
+										{{ sensor.status === 'normal' ? '姝e父' : '瓒呮爣' }}
+									</el-tag>
+								</div>
+								<div class="sensor-data">
+									<div class="data-item">
+										<span>鐢茬兎: {{ sensor.methane.toFixed(2) }}%</span>
+										<el-progress
+											:percentage="Math.min(Math.round(sensor.methane * 40 * 100) / 100, 100)"
+											:color="getProgressColor(sensor.methane, 2.5)"
+											:format="formatProgress"
+											:stroke-width="8"
+										/>
+									</div>
+									<div class="data-item">
+										<span>纭寲姘�: {{ sensor.h2s.toFixed(2) }}ppm</span>
+										<el-progress
+											:percentage="Math.min(Math.round((sensor.h2s / 20) * 100 * 100) / 100, 100)"
+											:color="getProgressColor(sensor.h2s, 10)"
+											:format="formatProgress"
+											:stroke-width="8"
+										/>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+					
+					<!-- 瀹炴椂鏇茬嚎鍥� -->
+					<div class="chart-section">
+						<h3>瀹炴椂娴撳害鏇茬嚎</h3>
+						<div class="chart-container">
+							<div ref="chart" class="chart"></div>
+						</div>
+					</div>
+				</el-card>
+			</el-col>
+			
+			<!-- 鍙充晶锛氭帶鍒堕潰鏉� -->
+			<el-col :span="8">
+				<el-card class="control-card">
+					<div slot="header" class="card-header">
+						<span>搴旀�ユ帶鍒堕潰鏉�</span>
+					</div>
+					
+					<!-- 鍠锋穻鐘舵�� -->
+					<div class="control-section">
+						<h4>鍠锋穻绯荤粺鐘舵��</h4>
+						<div class="status-grid">
+							<div class="status-item" v-for="sprinkler in sprinklerSystems" :key="sprinkler.id">
+								<div class="status-indicator" :class="sprinkler.status">
+									<i class="el-icon-circle-check" v-if="sprinkler.status === 'active'"></i>
+									<i class="el-icon-circle-close" v-else></i>
+								</div>
+								<span>{{ sprinkler.name }}</span>
+								<el-tag :type="sprinkler.status === 'active' ? 'success' : 'info'" size="small">
+									{{ sprinkler.status === 'active' ? '杩愯涓�' : '寰呮満' }}
+								</el-tag>
+							</div>
+						</div>
+					</div>
+					
+					<!-- 搴旀�ヨ褰曟寜閽� -->
+					<h4>搴旀�ョ鐞�</h4>
+					
+					<div class="control-section1">
+						<el-button type="primary" @click="showEmergencyRecords" style="margin-bottom: 10px;">
+							搴旀�ヨ褰�
+						</el-button>
+						<el-button type="warning" @click="triggerEmergency" :disabled="!hasEmergency">
+							瑙﹀彂搴旀�ュ搷搴�
+						</el-button>
+					</div>
+					
+					<!-- 绯荤粺鏃ュ織 -->
+					<div class="control-section">
+						<h4>绯荤粺鏃ュ織</h4>
+						<div class="log-container">
+							<div class="log-item" v-for="log in systemLogs" :key="log.id">
+								<span class="log-time">{{ log.time }}</span>
+								<span class="log-content">{{ log.content }}</span>
+							</div>
+						</div>
+					</div>
+				</el-card>
+			</el-col>
+		</el-row>
+		
+		<!-- 娉勬紡棰勮寮圭獥 -->
+		<el-dialog
+			title="鈿狅笍 娉勬紡棰勮"
+			:visible.sync="leakWarningVisible"
+			width="500px"
+			:close-on-click-modal="false"
+			:close-on-press-escape="false"
+			class="leak-warning-dialog"
+		>
+			<div class="warning-content">
+				<div class="warning-icon">
+					<i class="el-icon-warning"></i>
+				</div>
+				<div class="warning-text">
+					<h3>妫�娴嬪埌姘斾綋娴撳害瓒呮爣锛�</h3>
+					<p>浣嶇疆锛歿{ currentWarning.location }}</p>
+					<p>瓒呮爣姘斾綋锛歿{ currentWarning.gas }}</p>
+					<p>褰撳墠娴撳害锛歿{ currentWarning.value }}</p>
+				</div>
+			</div>
+			<div slot="footer" class="dialog-footer">
+				<el-button type="danger" @click="acknowledgeWarning">纭鍛婅</el-button>
+				<el-button type="primary" @click="viewDetails">鏌ョ湅璇︽儏</el-button>
+			</div>
+		</el-dialog>
+		
+		<!-- 搴旀�ヨ褰曞脊绐� -->
+		<el-dialog
+			title="搴旀�ヨ褰�"
+			:visible.sync="emergencyRecordsVisible"
+			width="800px"
+		>
+			<el-table :data="emergencyRecords" style="width: 100%">
+				<el-table-column prop="time" label="鏃堕棿" width="180"></el-table-column>
+				<el-table-column prop="location" label="浣嶇疆" width="150"></el-table-column>
+				<el-table-column prop="type" label="绫诲瀷" width="120"></el-table-column>
+				<el-table-column prop="status" label="鐘舵��" width="100">
+					<template slot-scope="scope">
+						<el-tag :type="scope.row.status === 'resolved' ? 'success' : 'warning'">
+							{{ scope.row.status === 'resolved' ? '宸茶В鍐�' : '澶勭悊涓�' }}
+						</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="description" label="鎻忚堪"></el-table-column>
+				<el-table-column label="鎿嶄綔" width="120">
+					<template slot-scope="scope">
+						<el-button type="text" @click="viewBlockchainDetails(scope.row)">
+							鍖哄潡閾捐鎯�
+						</el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+		</el-dialog>
+		
+		<!-- 鍖哄潡閾惧瓨璇佽鎯呭脊绐� -->
+		<el-dialog
+			title="鍖哄潡閾惧瓨璇佽鎯�"
+			:visible.sync="blockchainDetailsVisible"
+			width="900px"
+		>
+			<div class="blockchain-details">
+				<el-descriptions :column="2" border>
+					<el-descriptions-item label="浜嬩欢ID">{{ currentEvent.id }}</el-descriptions-item>
+					<el-descriptions-item label="鏃堕棿鎴�">{{ currentEvent.timestamp }}</el-descriptions-item>
+					<el-descriptions-item label="浣嶇疆">{{ currentEvent.location }}</el-descriptions-item>
+					<el-descriptions-item label="浜嬩欢绫诲瀷">{{ currentEvent.type }}</el-descriptions-item>
+				</el-descriptions>
+				
+				<div class="sensor-data-section">
+					<h4>浼犳劅鍣ㄦ暟鎹�</h4>
+					<el-table :data="currentEvent.sensorData" style="width: 100%">
+						<el-table-column prop="sensor" label="浼犳劅鍣�"></el-table-column>
+						<el-table-column prop="methane" label="鐢茬兎娴撳害"></el-table-column>
+						<el-table-column prop="h2s" label="纭寲姘㈡祿搴�"></el-table-column>
+						<el-table-column prop="timestamp" label="璁板綍鏃堕棿"></el-table-column>
+					</el-table>
+				</div>
+				
+				<div class="action-log-section">
+					<h4>澶勭疆鍔ㄤ綔璁板綍</h4>
+					<el-timeline>
+						<el-timeline-item
+							v-for="action in currentEvent.actions"
+							:key="action.id"
+							:timestamp="action.timestamp"
+							:type="action.type === 'emergency' ? 'danger' : 'primary'"
+						>
+							{{ action.description }}
+						</el-timeline-item>
+					</el-timeline>
+				</div>
+				
+				<div class="blockchain-info">
+					<h4>鍖哄潡閾句俊鎭�</h4>
+					<el-descriptions :column="1" border>
+						<el-descriptions-item label="鍖哄潡鍝堝笇">{{ currentEvent.blockHash }}</el-descriptions-item>
+						<el-descriptions-item label="浜ゆ槗鍝堝笇">{{ currentEvent.txHash }}</el-descriptions-item>
+						<el-descriptions-item label="纭鏁�">{{ currentEvent.confirmations }}</el-descriptions-item>
+					</el-descriptions>
+				</div>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+
+export default {
+	name: 'SafetyMonitoring',
+	data() {
+		return {
+			systemStatus: 'normal',
+			leakWarningVisible: false,
+			emergencyRecordsVisible: false,
+			blockchainDetailsVisible: false,
+			currentWarning: {},
+			currentEvent: {},
+			hasEmergency: false,
+			
+			// 鍌ㄧ綈鍖轰紶鎰熷櫒鏁版嵁
+			tankSensors: [
+				{ id: 1, name: '鍌ㄧ綈T-001', methane: 1.20, h2s: 2.10, status: 'normal' },
+				{ id: 2, name: '鍌ㄧ綈T-002', methane: 0.80, h2s: 1.50, status: 'normal' },
+				{ id: 3, name: '鍌ㄧ綈T-003', methane: 3.20, h2s: 8.50, status: 'warning' },
+				{ id: 4, name: '鍌ㄧ綈T-004', methane: 0.60, h2s: 0.80, status: 'normal' }
+			],
+			
+			// 浜曞彛鍘嬬缉鏈轰紶鎰熷櫒鏁版嵁
+			compressorSensors: [
+				{ id: 5, name: '鍘嬬缉鏈篊-001', methane: 2.10, h2s: 3.20, status: 'normal' },
+				{ id: 6, name: '鍘嬬缉鏈篊-002', methane: 4.80, h2s: 12.50, status: 'warning' },
+				{ id: 7, name: '鍘嬬缉鏈篊-003', methane: 1.80, h2s: 2.80, status: 'normal' }
+			],
+			
+			// 鍠锋穻绯荤粺鐘舵��
+			sprinklerSystems: [
+				{ id: 1, name: '鍌ㄧ綈鍖哄柗娣�', status: 'active' },
+				{ id: 2, name: '鍘嬬缉鏈哄尯鍠锋穻', status: 'standby' },
+				{ id: 3, name: '绱ф�ュ柗娣�', status: 'standby' }
+			],
+			
+			// 绯荤粺鏃ュ織
+			systemLogs: [
+				{ id: 1, time: '14:30:25', content: '绯荤粺鍚姩瀹屾垚锛屾墍鏈変紶鎰熷櫒姝e父' },
+				{ id: 2, time: '14:35:12', content: '鍌ㄧ綈T-003鐢茬兎娴撳害瓒呮爣锛岃Е鍙戦璀�' },
+				{ id: 3, time: '14:35:15', content: '鍚姩鍌ㄧ綈鍖哄柗娣嬬郴缁�' },
+				{ id: 4, time: '14:35:20', content: '鍙戦�佺揣鎬ョ枏鏁e箍鎾�' }
+			],
+			
+			// 搴旀�ヨ褰�
+			emergencyRecords: [
+				{
+					id: 'EM001',
+					time: '2024-01-15 14:35:12',
+					location: '鍌ㄧ綈T-003',
+					type: '鐢茬兎瓒呮爣',
+					status: 'resolved',
+					description: '鍌ㄧ綈T-003鐢茬兎娴撳害杈惧埌3.2%锛岃秴杩囧畨鍏ㄩ槇鍊�2.5%'
+				},
+				{
+					id: 'EM002',
+					time: '2024-01-15 14:35:15',
+					location: '鍘嬬缉鏈篊-002',
+					type: '纭寲姘㈣秴鏍�',
+					status: 'processing',
+					description: '鍘嬬缉鏈篊-002纭寲姘㈡祿搴﹁揪鍒�12.5ppm锛岃秴杩囧畨鍏ㄩ槇鍊�10ppm'
+				}
+			],
+			
+			// 鍥捐〃瀹炰緥
+			chart: null,
+			
+			// 瀹氭椂鍣�
+			timer: null
+		}
+	},
+	
+	mounted() {
+		this.initChart()
+		this.startDataRefresh()
+		this.checkEmergencyStatus()
+	},
+	
+	beforeDestroy() {
+		if (this.timer) {
+			clearInterval(this.timer)
+		}
+		if (this.chart) {
+			this.chart.dispose()
+		}
+	},
+	
+	methods: {
+		// 缁熶竴杩涘害鏉℃牸寮忓寲涓轰袱浣嶅皬鏁帮紝閬垮厤娴偣璇樊鏄剧ず
+		formatProgress(percentage) {
+			if (percentage == null || isNaN(percentage)) return '0.00%'
+			const val = Math.round(Number(percentage) * 100) / 100
+			return `${val.toFixed(2)}%`
+		},
+		// 鍒濆鍖栧浘琛�
+		initChart() {
+			this.chart = echarts.init(this.$refs.chart)
+			this.updateChart()
+		},
+		
+		// 鏇存柊鍥捐〃鏁版嵁
+		updateChart() {
+			const option = {
+				title: {
+					text: '瀹炴椂姘斾綋娴撳害鐩戞帶',
+					left: 'center'
+				},
+				tooltip: {
+					trigger: 'axis',
+					axisPointer: {
+						type: 'cross'
+					}
+				},
+				legend: {
+					data: ['鍌ㄧ綈鍖虹敳鐑�', '鍌ㄧ綈鍖虹~鍖栨阿', '鍘嬬缉鏈虹敳鐑�', '鍘嬬缉鏈虹~鍖栨阿'],
+					top: 30
+				},
+				grid: {
+					left: '3%',
+					right: '4%',
+					bottom: '3%',
+					top: '15%',
+					containLabel: true
+				},
+				xAxis: {
+					type: 'category',
+					data: this.generateTimeData()
+				},
+				yAxis: [
+					{
+						type: 'value',
+						name: '鐢茬兎娴撳害(%)',
+						position: 'left'
+					},
+					{
+						type: 'value',
+						name: '纭寲姘㈡祿搴�(ppm)',
+						position: 'right'
+					}
+				],
+				series: [
+					{
+						name: '鍌ㄧ綈鍖虹敳鐑�',
+						type: 'line',
+						data: this.generateRandomData(20, 0.5, 3.5),
+						smooth: true,
+						yAxisIndex: 0
+					},
+					{
+						name: '鍌ㄧ綈鍖虹~鍖栨阿',
+						type: 'line',
+						data: this.generateRandomData(20, 0.5, 12),
+						smooth: true,
+						yAxisIndex: 1
+					},
+					{
+						name: '鍘嬬缉鏈虹敳鐑�',
+						type: 'line',
+						data: this.generateRandomData(20, 1.0, 5.0),
+						smooth: true,
+						yAxisIndex: 0
+					},
+					{
+						name: '鍘嬬缉鏈虹~鍖栨阿',
+						type: 'line',
+						data: this.generateRandomData(20, 1.0, 15),
+						smooth: true,
+						yAxisIndex: 1
+					}
+				]
+			}
+			
+			this.chart.setOption(option)
+		},
+		
+		// 鐢熸垚鏃堕棿鏁版嵁
+		generateTimeData() {
+			const times = []
+			const now = new Date()
+			for (let i = 19; i >= 0; i--) {
+				const time = new Date(now.getTime() - i * 5 * 60 * 1000)
+				times.push(time.toLocaleTimeString('zh-CN', { hour12: false }))
+			}
+			return times
+		},
+		
+		// 鐢熸垚闅忔満鏁版嵁
+		generateRandomData(count, min, max) {
+			const data = []
+			for (let i = 0; i < count; i++) {
+				data.push(+(Math.random() * (max - min) + min).toFixed(2))
+			}
+			return data
+		},
+		
+		// 寮�濮嬫暟鎹埛鏂�
+		startDataRefresh() {
+			this.timer = setInterval(() => {
+				this.refreshSensorData()
+				this.updateChart()
+				this.checkEmergencyStatus()
+			}, 5000) // 姣�5绉掑埛鏂颁竴娆�
+		},
+		
+		// 鍒锋柊浼犳劅鍣ㄦ暟鎹�
+		refreshSensorData() {
+			// 鏇存柊鍌ㄧ綈鍖轰紶鎰熷櫒鏁版嵁
+			this.tankSensors.forEach(sensor => {
+				sensor.methane = +(Math.random() * 4).toFixed(2)
+				sensor.h2s = +(Math.random() * 15).toFixed(2)
+				sensor.status = this.getSensorStatus(sensor.methane, sensor.h2s)
+			})
+			
+			// 鏇存柊鍘嬬缉鏈轰紶鎰熷櫒鏁版嵁
+			this.compressorSensors.forEach(sensor => {
+				sensor.methane = +(Math.random() * 6).toFixed(2)
+				sensor.h2s = +(Math.random() * 20).toFixed(2)
+				sensor.status = this.getSensorStatus(sensor.methane, sensor.h2s)
+			})
+			
+			// 妫�鏌ユ槸鍚﹂渶瑕佽Е鍙戦璀�
+			this.checkLeakWarning()
+		},
+		
+		// 鑾峰彇浼犳劅鍣ㄧ姸鎬�
+		getSensorStatus(methane, h2s) {
+			const methanePct = Math.min(Math.round(methane * 40 * 100) / 100, 100)
+			const h2sPct = Math.min(Math.round((h2s / 20) * 100 * 100) / 100, 100)
+			if (methanePct >= 80 || h2sPct >= 80) {
+				return 'warning'
+			}
+			return 'normal'
+		},
+		
+		// 妫�鏌ユ硠婕忛璀�
+		checkLeakWarning() {
+			const allSensors = [...this.tankSensors, ...this.compressorSensors]
+			const warningSensor = allSensors.find(sensor => this.getSensorStatus(sensor.methane, sensor.h2s) === 'warning')
+			
+			if (warningSensor && !this.leakWarningVisible) {
+				this.triggerLeakWarning(warningSensor)
+			}
+		},
+		
+		// 瑙﹀彂娉勬紡棰勮
+		triggerLeakWarning(sensor) {
+			const methanePct = Math.min(Math.round(sensor.methane * 40 * 100) / 100, 100)
+			const h2sPct = Math.min(Math.round((sensor.h2s / 20) * 100 * 100) / 100, 100)
+			const isMethaneMajor = methanePct >= h2sPct
+			const overGas = isMethaneMajor ? '鐢茬兎' : '纭寲姘�'
+			const percent = (isMethaneMajor ? methanePct : h2sPct).toFixed(2)
+			this.currentWarning = {
+				location: sensor.name,
+				gas: overGas,
+				value: `${percent}%`
+			}
+			
+			this.leakWarningVisible = true
+			this.hasEmergency = true
+			
+			// 鑷姩瑙﹀彂搴旀�ュ搷搴�
+			this.autoEmergencyResponse(sensor)
+			
+			// 娣诲姞绯荤粺鏃ュ織
+			this.addSystemLog(`妫�娴嬪埌${sensor.name}姘斾綋娴撳害瓒呮爣锛岃Е鍙戞硠婕忛璀)
+		},
+		
+		// 鑷姩搴旀�ュ搷搴�
+		autoEmergencyResponse(sensor) {
+			// 鍚姩鍠锋穻绯荤粺
+			if (sensor.name.includes('鍌ㄧ綈')) {
+				this.sprinklerSystems[0].status = 'active'
+			} else if (sensor.name.includes('鍘嬬缉鏈�')) {
+				this.sprinklerSystems[1].status = 'active'
+			}
+			
+			// 娣诲姞绯荤粺鏃ュ織
+			this.addSystemLog(`鍚姩${sensor.name}鍖哄煙鍠锋穻绯荤粺`)
+			this.addSystemLog(`鍙戦�佺揣鎬ョ枏鏁e箍鎾璥)
+			
+			// 鍒涘缓搴旀�ヨ褰�
+			this.createEmergencyRecord(sensor)
+		},
+		
+		// 娣诲姞绯荤粺鏃ュ織
+		addSystemLog(content) {
+			const now = new Date()
+			const time = now.toLocaleTimeString('zh-CN', { hour12: false })
+			
+			this.systemLogs.unshift({
+				id: Date.now(),
+				time: time,
+				content: content
+			})
+			
+			// 淇濇寔鏈�澶�20鏉℃棩蹇�
+			if (this.systemLogs.length > 20) {
+				this.systemLogs = this.systemLogs.slice(0, 20)
+			}
+		},
+		
+		// 鍒涘缓搴旀�ヨ褰�
+		createEmergencyRecord(sensor) {
+			const now = new Date()
+			const record = {
+				id: `EM${Date.now()}`,
+				time: now.toLocaleString('zh-CN'),
+				location: sensor.name,
+				type: sensor.methane > 2.5 ? '鐢茬兎瓒呮爣' : '纭寲姘㈣秴鏍�',
+				status: 'processing',
+				description: `${sensor.name}妫�娴嬪埌${sensor.methane > 2.5 ? '鐢茬兎' : '纭寲姘�'}娴撳害瓒呮爣`
+			}
+			
+			this.emergencyRecords.unshift(record)
+		},
+		
+		// 鑾峰彇杩涘害鏉¢鑹�
+		getProgressColor(value, threshold) {
+			if (value > threshold) {
+				return '#F56C6C'
+			} else if (value > threshold * 0.8) {
+				return '#E6A23C'
+			}
+			return '#67C23A'
+		},
+		
+		// 妫�鏌ュ簲鎬ョ姸鎬�
+		checkEmergencyStatus() {
+			const allSensors = [...this.tankSensors, ...this.compressorSensors]
+			const has = allSensors.some(sensor => this.getSensorStatus(sensor.methane, sensor.h2s) === 'warning')
+			this.hasEmergency = has
+			this.systemStatus = has ? 'warning' : 'normal'
+		},
+		
+		// 纭鍛婅
+		acknowledgeWarning() {
+			this.leakWarningVisible = false
+			this.addSystemLog('娉勬紡棰勮宸茬‘璁�')
+		},
+		
+		// 鏌ョ湅璇︽儏
+		viewDetails() {
+			this.leakWarningVisible = false
+			// 杩欓噷鍙互璺宠浆鍒拌缁嗛〉闈㈡垨鏄剧ず鏇村淇℃伅
+		},
+		
+		// 鏄剧ず搴旀�ヨ褰�
+		showEmergencyRecords() {
+			this.emergencyRecordsVisible = true
+		},
+		
+		// 鏌ョ湅鍖哄潡閾捐鎯�
+		viewBlockchainDetails(record) {
+			this.currentEvent = {
+				id: record.id,
+				timestamp: record.time,
+				location: record.location,
+				type: record.type,
+				sensorData: [
+					{
+						sensor: '鐢茬兎浼犳劅鍣�',
+						methane: '3.2%',
+						h2s: '8.5ppm',
+						timestamp: record.time
+					},
+					{
+						sensor: '纭寲姘紶鎰熷櫒',
+						methane: '2.8%',
+						h2s: '12.5ppm',
+						timestamp: record.time
+					}
+				],
+				actions: [
+					{
+						id: 1,
+						timestamp: record.time,
+						type: 'emergency',
+						description: '妫�娴嬪埌姘斾綋娴撳害瓒呮爣锛岃Е鍙戦璀�'
+					},
+					{
+						id: 2,
+						timestamp: new Date(new Date(record.time).getTime() + 3000).toLocaleString('zh-CN'),
+						type: 'action',
+						description: '鍚姩鍠锋穻绯荤粺闄嶆俯'
+					},
+					{
+						id: 3,
+						timestamp: new Date(new Date(record.time).getTime() + 5000).toLocaleString('zh-CN'),
+						type: 'action',
+						description: '鍙戦�佺揣鎬ョ枏鏁e箍鎾�'
+					}
+				],
+				blockHash: '0x1234567890abcdef...',
+				txHash: '0xabcdef1234567890...',
+				confirmations: 12
+			}
+			
+			this.emergencyRecordsVisible = false
+			this.blockchainDetailsVisible = true
+		},
+		
+		// 瑙﹀彂搴旀�ュ搷搴�
+		triggerEmergency() {
+			this.$message.success('搴旀�ュ搷搴斿凡瑙﹀彂')
+			this.addSystemLog('鎵嬪姩瑙﹀彂搴旀�ュ搷搴�')
+		}
+	}
+}
+</script>
+
+<style scoped>
+.safety-monitoring {
+	padding: 20px;
+	background-color: #f5f7fa;
+	min-height: calc(100vh - 84px);
+}
+
+.monitoring-card, .control-card {
+	margin-bottom: 20px;
+}
+
+.card-header {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+.monitoring-section {
+	margin-bottom: 30px;
+}
+
+.monitoring-section h3 {
+	color: #303133;
+	margin-bottom: 15px;
+	padding-bottom: 8px;
+	border-bottom: 2px solid #409EFF;
+}
+
+.sensor-grid {
+	display: grid;
+	grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+	gap: 15px;
+}
+
+.sensor-item {
+	background: #fff;
+	border: 1px solid #e4e7ed;
+	border-radius: 8px;
+	padding: 15px;
+	box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+}
+
+.sensor-header {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	margin-bottom: 15px;
+	font-weight: bold;
+}
+
+.sensor-data .data-item {
+	margin-bottom: 12px;
+}
+
+.sensor-data .data-item span {
+	display: block;
+	margin-bottom: 5px;
+	font-size: 14px;
+	color: #606266;
+}
+
+.chart-section {
+	margin-top: 30px;
+}
+
+.chart-section h3 {
+	color: #303133;
+	margin-bottom: 15px;
+	padding-bottom: 8px;
+	border-bottom: 2px solid #409EFF;
+}
+
+.chart-container {
+	background: #fff;
+	border-radius: 8px;
+	padding: 20px;
+}
+
+.chart {
+	width: 100%;
+	height: 400px;
+}
+
+.control-section {
+	margin-bottom: 25px;
+}
+.control-section1 {
+	display: flex;
+}
+
+.control-section h4 {
+	color: #303133;
+	margin-bottom: 15px;
+	font-size: 16px;
+}
+
+.status-grid {
+	display: grid;
+	gap: 10px;
+}
+
+.status-item {
+	display: flex;
+	align-items: center;
+	gap: 10px;
+	padding: 10px;
+	background: #f8f9fa;
+	border-radius: 6px;
+}
+
+.status-indicator {
+	width: 20px;
+	height: 20px;
+	border-radius: 50%;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.status-indicator.active {
+	color: #67C23A;
+}
+
+.status-indicator.standby {
+	color: #909399;
+}
+
+.log-container {
+	max-height: 200px;
+	overflow-y: auto;
+	background: #f8f9fa;
+	border-radius: 6px;
+	padding: 10px;
+}
+
+.log-item {
+	display: flex;
+	gap: 10px;
+	margin-bottom: 8px;
+	font-size: 12px;
+}
+
+.log-time {
+	color: #909399;
+	min-width: 60px;
+}
+
+.log-content {
+	color: #606266;
+}
+
+/* 娉勬紡棰勮寮圭獥鏍峰紡 */
+.leak-warning-dialog {
+	background: #fff5f5;
+}
+
+.warning-content {
+	text-align: center;
+	padding: 20px 0;
+}
+
+.warning-icon {
+	font-size: 60px;
+	color: #F56C6C;
+	margin-bottom: 20px;
+}
+
+.warning-text h3 {
+	color: #F56C6C;
+	margin-bottom: 15px;
+}
+
+.warning-text p {
+	margin: 8px 0;
+	color: #606266;
+}
+
+/* 鍖哄潡閾捐鎯呮牱寮� */
+.blockchain-details {
+	padding: 20px 0;
+}
+
+.sensor-data-section, .action-log-section, .blockchain-info {
+	margin-top: 25px;
+}
+
+.sensor-data-section h4, .action-log-section h4, .blockchain-info h4 {
+	color: #303133;
+	margin-bottom: 15px;
+	padding-bottom: 8px;
+	border-bottom: 1px solid #e4e7ed;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1200px) {
+	.sensor-grid {
+		grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+	}
+}
+
+@media (max-width: 768px) {
+	.safety-monitoring {
+		padding: 10px;
+	}
+	
+	.sensor-grid {
+		grid-template-columns: 1fr;
+	}
+	
+	.chart {
+		height: 300px;
+	}
+}
+</style>

--
Gitblit v1.9.3