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