From f1ee0aa9d6c6c89ee9f0e5d845cd3c64f161aeaf Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期二, 16 十二月 2025 20:03:08 +0800
Subject: [PATCH] 代码调整6
---
src/views/monitoring/RealTimeMonitoring.vue | 515 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 515 insertions(+), 0 deletions(-)
diff --git a/src/views/monitoring/RealTimeMonitoring.vue b/src/views/monitoring/RealTimeMonitoring.vue
new file mode 100644
index 0000000..c449958
--- /dev/null
+++ b/src/views/monitoring/RealTimeMonitoring.vue
@@ -0,0 +1,515 @@
+<template>
+ <div class="real-time-monitoring-container">
+ <!-- 璁惧閫夋嫨 -->
+ <el-card shadow="hover" style="margin-bottom: 20px;">
+ <el-form :inline="true" :model="deviceSelectForm" class="device-select-form">
+ <el-form-item label="璁惧">
+ <el-select v-model="deviceSelectForm.deviceId" placeholder="璇烽�夋嫨璁惧" @change="handleDeviceChange">
+ <el-option
+ v-for="device in devices"
+ :key="device.id"
+ :label="device.name"
+ :value="device.id"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏃堕棿鑼冨洿">
+ <el-date-picker
+ v-model="timeRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ :default-time="['00:00:00', '23:59:59']"
+ ></el-date-picker>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleHistoryQuery">鏌ヨ鍘嗗彶鏁版嵁</el-button>
+ </el-form-item>
+ </el-form>
+ </el-card>
+
+ <!-- 瀹炴椂鍙傛暟鍗$墖 -->
+ <el-row :gutter="20" style="margin-bottom: 20px;">
+ <el-col :span="8" v-for="param in realTimeParams" :key="param.name">
+ <el-card class="param-card" :shadow="param.isAlarm ? 'always' : 'hover'" :class="{ 'alarm-card': param.isAlarm }">
+ <div class="param-content">
+ <div class="param-title">
+ <span>{{ param.name }}</span>
+ <el-tag v-if="param.isAlarm" type="danger">鍛婅</el-tag>
+ </div>
+ <div class="param-value">{{ param.value }} {{ param.unit }}</div>
+ <div class="param-range">
+ 姝e父鑼冨洿锛歿{ param.min }} - {{ param.max }} {{ param.unit }}
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 鍛婅鎻愮ず -->
+ <el-card shadow="hover" v-if="alarmList.length > 0" style="margin-bottom: 20px;">
+ <template #header>
+ <div class="card-header">
+ <span>鍛婅鎻愮ず</span>
+ </div>
+ </template>
+ <el-scrollbar height="200px">
+ <div class="alarm-item" v-for="alarm in alarmList" :key="alarm.id">
+ <el-alert
+ :title="alarm.message"
+ :type="alarm.level === 'high' ? 'error' : alarm.level === 'medium' ? 'warning' : 'info'"
+ show-icon
+ closable
+ @close="handleAlarmClose(alarm.id)"
+ >
+ <template #default>
+ <div class="alarm-detail">
+ <span>璁惧锛歿{ alarm.deviceName }}</span>
+ <span>鏃堕棿锛歿{ alarm.time }}</span>
+ </div>
+ </template>
+ </el-alert>
+ </div>
+ </el-scrollbar>
+ </el-card>
+
+ <!-- 鍘嗗彶鏁版嵁瓒嬪娍鍥� -->
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>鍘嗗彶鏁版嵁瓒嬪娍</span>
+ <div class="param-tabs">
+ <el-radio-group v-model="activeParam" size="small" @change="handleParamChange">
+ <el-radio-button v-for="param in historyParams" :key="param" :label="param">
+ {{ param }}
+ </el-radio-button>
+ </el-radio-group>
+ </div>
+ </div>
+ </template>
+ <div ref="historyChartRef" class="chart-container"></div>
+ </el-card>
+
+ <!-- 鍗曡澶囧弬鏁拌鎯呴〉 -->
+ <el-dialog v-model="deviceDetailVisible" title="璁惧鍙傛暟璇︽儏" width="800px">
+ <div class="device-detail-content">
+ <h3>{{ selectedDevice.name }} - 瀹炴椂鍙傛暟</h3>
+ <el-row :gutter="20" style="margin-bottom: 20px;">
+ <el-col :span="12" v-for="param in realTimeParams" :key="param.name">
+ <div class="detail-param-item">
+ <span class="param-label">{{ param.name }}锛�</span>
+ <span class="param-value" :class="{ 'alarm-value': param.isAlarm }">
+ {{ param.value }} {{ param.unit }}
+ </span>
+ <span class="param-range">
+ 锛坽{ param.min }} - {{ param.max }} {{ param.unit }}锛�
+ </span>
+ </div>
+ </el-col>
+ </el-row>
+
+ <h3>鍙傛暟闃堝�艰缃�</h3>
+ <el-form :model="thresholdForm" label-width="100px" style="margin-top: 20px;">
+ <el-form-item v-for="param in realTimeParams" :key="param.name" :label="param.name">
+ <el-input-number
+ v-model="thresholdForm[param.name + 'Min']"
+ :min="0"
+ :max="1000"
+ size="small"
+ style="width: 120px; margin-right: 10px;"
+ placeholder="鏈�灏忓��"
+ ></el-input-number>
+ <span style="margin: 0 10px;">-</span>
+ <el-input-number
+ v-model="thresholdForm[param.name + 'Max']"
+ :min="0"
+ :max="1000"
+ size="small"
+ style="width: 120px; margin-right: 10px;"
+ placeholder="鏈�澶у��"
+ ></el-input-number>
+ <span>{{ param.unit }}</span>
+ </el-form-item>
+ </el-form>
+ </div>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="deviceDetailVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="saveThresholds">淇濆瓨璁剧疆</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted, computed } from 'vue'
+import * as echarts from 'echarts'
+
+// 璁惧鍒楄〃
+const devices = ref([
+ { id: 'D001', name: '绌哄帇鏈篈-001' },
+ { id: 'D002', name: '鍐峰嵈濉擝-002' },
+ { id: 'D003', name: '姘存车C-003' },
+ { id: 'D004', name: '鍙戠數鏈篋-004' },
+ { id: 'D005', name: '鍙樺帇鍣‥-005' }
+])
+
+// 璁惧閫夋嫨琛ㄥ崟
+const deviceSelectForm = ref({
+ deviceId: 'D001' // 榛樿閫夋嫨绗竴涓澶�
+})
+
+// 鏃堕棿鑼冨洿
+const timeRange = ref([])
+
+// 褰撳墠閫変腑鐨勮澶�
+const selectedDevice = ref(devices.value[0])
+
+// 瀹炴椂鍙傛暟鏁版嵁
+const realTimeParams = ref([
+ { name: '娓╁害', value: 45, unit: '鈩�', min: 0, max: 60, isAlarm: false },
+ { name: '鍘嬪姏', value: 0.85, unit: 'MPa', min: 0.5, max: 0.8, isAlarm: true },
+ { name: '杞��', value: 1450, unit: 'rpm', min: 1000, max: 1500, isAlarm: false },
+ { name: '鎸姩', value: 3.2, unit: 'mm/s', min: 0, max: 2.5, isAlarm: true },
+ { name: '鐢垫祦', value: 25.6, unit: 'A', min: 0, max: 30, isAlarm: false },
+ { name: '鐢靛帇', value: 380, unit: 'V', min: 360, max: 400, isAlarm: false }
+])
+
+// 鍛婅鍒楄〃
+const alarmList = ref([
+ { id: 1, deviceName: '绌哄帇鏈篈-001', message: '鍘嬪姏瓒呮爣', level: 'high', time: '2024-12-16 14:32:15' },
+ { id: 2, deviceName: '绌哄帇鏈篈-001', message: '鎸姩杩囧ぇ', level: 'medium', time: '2024-12-16 14:30:45' },
+ { id: 3, deviceName: '鍐峰嵈濉擝-002', message: '娓╁害寮傚父', level: 'warning', time: '2024-12-16 14:28:30' }
+])
+
+// 鍘嗗彶鍙傛暟閫夐」
+const historyParams = ref(['娓╁害', '鍘嬪姏', '杞��', '鎸姩', '鐢垫祦', '鐢靛帇'])
+const activeParam = ref('娓╁害')
+
+// 鍘嗗彶鏁版嵁
+const historyData = ref({
+ dates: [],
+ values: []
+})
+
+// 鍥捐〃寮曠敤
+const historyChartRef = ref(null)
+let historyChart = null
+
+// 璁惧璇︽儏瀵硅瘽妗�
+const deviceDetailVisible = ref(false)
+
+// 闃堝�艰缃〃鍗�
+const thresholdForm = ref({})
+
+// 鍒濆鍖栭槇鍊艰〃鍗�
+const initThresholdForm = () => {
+ const form = {}
+ realTimeParams.value.forEach(param => {
+ form[param.name + 'Min'] = param.min
+ form[param.name + 'Max'] = param.max
+ })
+ thresholdForm.value = form
+}
+
+// 澶勭悊璁惧鍙樻洿
+const handleDeviceChange = (deviceId) => {
+ selectedDevice.value = devices.value.find(device => device.id === deviceId) || devices.value[0]
+ // 妯℃嫙鍒囨崲璁惧鍚庢洿鏂板疄鏃跺弬鏁�
+ updateRealTimeParams()
+ // 鍒锋柊鍘嗗彶鏁版嵁鍥捐〃
+ initHistoryChart()
+}
+
+// 鏇存柊瀹炴椂鍙傛暟锛堟ā鎷燂級
+const updateRealTimeParams = () => {
+ realTimeParams.value = realTimeParams.value.map(param => {
+ // 鐢熸垚闅忔満鍊硷紝閮ㄥ垎鍙傛暟鍙兘瑙﹀彂鍛婅
+ const randomFactor = Math.random() * 0.2 - 0.1 // -0.1 鍒� 0.1 涔嬮棿鐨勯殢鏈烘暟
+ const baseValue = (param.min + param.max) / 2
+ const newValue = baseValue + baseValue * randomFactor
+ const isAlarm = newValue < param.min || newValue > param.max
+
+ return {
+ ...param,
+ value: Number(newValue.toFixed(2)),
+ isAlarm
+ }
+ })
+}
+
+// 澶勭悊鍘嗗彶鏁版嵁鏌ヨ
+const handleHistoryQuery = () => {
+ // 妯℃嫙鏌ヨ鍘嗗彶鏁版嵁
+ generateHistoryData()
+ initHistoryChart()
+ ElMessage.success('鍘嗗彶鏁版嵁鏌ヨ鎴愬姛')
+}
+
+// 鐢熸垚鍘嗗彶鏁版嵁锛堟ā鎷燂級
+const generateHistoryData = () => {
+ const dates = []
+ const values = []
+
+ // 鐢熸垚杩囧幓7澶╃殑鏃ユ湡鍜屽搴旀暟鎹�
+ for (let i = 6; i >= 0; i--) {
+ const date = new Date()
+ date.setDate(date.getDate() - i)
+ dates.push(date.toLocaleDateString())
+
+ // 鐢熸垚闅忔満鍊�
+ const baseValue = (realTimeParams.value.find(p => p.name === activeParam.value).min +
+ realTimeParams.value.find(p => p.name === activeParam.value).max) / 2
+ const randomValue = baseValue + (Math.random() - 0.5) * baseValue * 0.4
+ values.push(Number(randomValue.toFixed(2)))
+ }
+
+ historyData.value = {
+ dates,
+ values
+ }
+}
+
+// 鍒濆鍖栧巻鍙叉暟鎹秼鍔垮浘
+const initHistoryChart = () => {
+ if (historyChartRef.value) {
+ historyChart = echarts.init(historyChartRef.value)
+
+ // 濡傛灉娌℃湁鍘嗗彶鏁版嵁锛岀敓鎴愭ā鎷熸暟鎹�
+ if (historyData.value.dates.length === 0) {
+ generateHistoryData()
+ }
+
+ const paramConfig = realTimeParams.value.find(p => p.name === activeParam.value)
+ const option = {
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ label: {
+ backgroundColor: '#6a7985'
+ }
+ }
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ data: historyData.value.dates
+ },
+ yAxis: {
+ type: 'value',
+ name: `${activeParam.value}(${paramConfig.unit})`,
+ min: paramConfig.min * 0.9,
+ max: paramConfig.max * 1.1
+ },
+ series: [
+ {
+ name: activeParam.value,
+ type: 'line',
+ stack: '鎬婚噺',
+ areaStyle: {},
+ emphasis: {
+ focus: 'series'
+ },
+ data: historyData.value.values,
+ itemStyle: {
+ color: '#409eff'
+ },
+ lineStyle: {
+ width: 3
+ }
+ }
+ ]
+ }
+ historyChart.setOption(option)
+ }
+}
+
+// 澶勭悊鍙傛暟鍒囨崲
+const handleParamChange = () => {
+ // 鐢熸垚鏂板弬鏁扮殑鍘嗗彶鏁版嵁
+ generateHistoryData()
+ initHistoryChart()
+}
+
+// 澶勭悊鍛婅鍏抽棴
+const handleAlarmClose = (alarmId) => {
+ const index = alarmList.value.findIndex(alarm => alarm.id === alarmId)
+ if (index !== -1) {
+ alarmList.value.splice(index, 1)
+ }
+}
+
+// 鎵撳紑璁惧璇︽儏椤�
+const openDeviceDetail = () => {
+ initThresholdForm()
+ deviceDetailVisible.value = true
+}
+
+// 淇濆瓨闃堝�艰缃�
+const saveThresholds = () => {
+ // 妯℃嫙淇濆瓨闃堝��
+ realTimeParams.value = realTimeParams.value.map(param => {
+ return {
+ ...param,
+ min: thresholdForm.value[param.name + 'Min'],
+ max: thresholdForm.value[param.name + 'Max']
+ }
+ })
+ deviceDetailVisible.value = false
+ ElMessage.success('闃堝�艰缃繚瀛樻垚鍔�')
+}
+
+// 鐩戝惉绐楀彛澶у皬鍙樺寲锛岃皟鏁村浘琛ㄥぇ灏�
+const handleResize = () => {
+ historyChart?.resize()
+}
+
+// 姣�5绉掓洿鏂颁竴娆″疄鏃跺弬鏁帮紙妯℃嫙锛�
+let updateTimer = null
+const startRealTimeUpdate = () => {
+ updateTimer = setInterval(() => {
+ updateRealTimeParams()
+ }, 5000)
+}
+
+onMounted(() => {
+ // 鍒濆鍖栧浘琛�
+ initHistoryChart()
+ // 鍒濆鍖栭槇鍊艰〃鍗�
+ initThresholdForm()
+ // 寮�濮嬪疄鏃舵洿鏂�
+ startRealTimeUpdate()
+ // 鐩戝惉绐楀彛澶у皬鍙樺寲
+ window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+ // 娓呴櫎瀹氭椂鍣�
+ if (updateTimer) {
+ clearInterval(updateTimer)
+ }
+ // 閿�姣佸浘琛�
+ historyChart?.dispose()
+ // 绉婚櫎浜嬩欢鐩戝惉
+ window.removeEventListener('resize', handleResize)
+})
+</script>
+
+<style scoped>
+.real-time-monitoring-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
+}
+
+.device-select-form {
+ margin-bottom: 0;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.param-tabs {
+ display: flex;
+ gap: 10px;
+}
+
+.param-card {
+ transition: all 0.3s;
+}
+
+.alarm-card {
+ border-left: 4px solid #f56c6c;
+ box-shadow: 0 2px 12px 0 rgba(245, 108, 108, 0.1);
+}
+
+.param-content {
+ text-align: center;
+}
+
+.param-title {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 10px;
+ font-size: 16px;
+ color: #606266;
+ margin-bottom: 10px;
+}
+
+.param-value {
+ font-size: 32px;
+ font-weight: bold;
+ color: #303133;
+ margin-bottom: 10px;
+ display: block;
+}
+
+.alarm-value {
+ color: #f56c6c;
+}
+
+.param-range {
+ font-size: 14px;
+ color: #909399;
+}
+
+.alarm-item {
+ margin-bottom: 10px;
+}
+
+.alarm-detail {
+ display: flex;
+ justify-content: space-between;
+ margin-top: 5px;
+ font-size: 14px;
+ color: #606266;
+}
+
+.chart-container {
+ width: 100%;
+ height: 400px;
+}
+
+.device-detail-content {
+ padding: 10px 0;
+}
+
+.device-detail-content h3 {
+ margin-bottom: 20px;
+ color: #303133;
+}
+
+.detail-param-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 15px;
+ padding: 10px;
+ background-color: #fafafa;
+ border-radius: 4px;
+}
+
+.param-label {
+ font-size: 14px;
+ color: #606266;
+ width: 80px;
+}
+
+.param-range {
+ font-size: 12px;
+ color: #909399;
+ margin-left: 10px;
+}
+</style>
\ No newline at end of file
--
Gitblit v1.9.3