<!--管线压力监测-->
<template>
  <div class="pressure-monitor">
    <!-- 页面头部 -->
    <div class="page-header">
      <div class="header-left">
        <el-icon><Odometer /></el-icon>
        <span class="title">管线压力监测</span>
        <div class="stats-badge">
          <span class="stat-item normal"><i class="dot"></i>正常 {{ normalCount }}</span>
          <span class="stat-item warning"><i class="dot"></i>预警 {{ warningCount }}</span>
          <span class="stat-item danger"><i class="dot"></i>告警 {{ dangerCount }}</span>
          <span class="stat-item offline"><i class="dot"></i>离线 {{ offlineCount }}</span>
        </div>
      </div>
      <div class="header-right">
        <el-input v-model="searchKeyword" placeholder="搜索测点名称/管线" clearable :prefix-icon="Search" style="width:200px" />
        <el-button type="primary" :icon="Refresh" @click="refreshData">刷新</el-button>
      </div>
    </div>

    <!-- 主内容区：左侧测点列表 + 右侧压力趋势 -->
    <div class="main-layout">
      <!-- 左侧：测点列表 -->
      <div class="point-list-panel">
        <div class="list-header">
          <span>压力监测点</span>
          <span class="total-num">共 {{ filteredPoints.length }} 个测点</span>
        </div>
        <div class="filter-row">
          <el-select v-model="pressureLevel" placeholder="压力等级" clearable size="small" style="width:100%">
            <el-option label="高压" value="high" />
            <el-option label="中压" value="medium" />
            <el-option label="低压" value="low" />
          </el-select>
        </div>
        <div class="filter-row">
          <el-select v-model="statusFilter" placeholder="运行状态" clearable size="small" style="width:100%">
            <el-option label="正常" value="normal" />
            <el-option label="预警" value="warning" />
            <el-option label="告警" value="danger" />
            <el-option label="离线" value="offline" />
          </el-select>
        </div>
        <div class="point-list">
          <div
            v-for="point in filteredPoints"
            :key="point.id"
            class="point-item"
            :class="{ active: selectedPoint?.id === point.id, [point.status]: true }"
            @click="selectPoint(point)"
          >
            <div class="point-header">
              <span class="point-name">{{ point.name }}</span>
              <el-tag :type="statusTagType(point.status)" size="small">{{ statusLabel(point.status) }}</el-tag>
            </div>
            <div class="point-pipeline">{{ point.pipelineName }}</div>
            <div class="point-value">
              <span class="val">{{ point.latestPressure }}</span>
              <span class="unit">kPa</span>
              <span class="threshold">阈值: {{ point.minPressure }}~{{ point.maxPressure }} kPa</span>
            </div>
            <div class="point-addr">{{ point.address }}</div>
            <div class="point-time">{{ point.latestTime }}</div>
          </div>
          <el-empty v-if="filteredPoints.length === 0" description="暂无匹配测点" :image-size="50" />
        </div>
      </div>

      <!-- 右侧：压力详情 -->
      <div class="detail-panel">
        <template v-if="selectedPoint">
          <!-- 测点信息卡片 -->
          <div class="detail-header">
            <div class="detail-title">
              <span class="point-name">{{ selectedPoint.name }}</span>
              <el-tag :type="statusTagType(selectedPoint.status)" size="small">{{ statusLabel(selectedPoint.status) }}</el-tag>
            </div>
            <div class="detail-meta">
              <span>所属管线：{{ selectedPoint.pipelineName }}</span>
              <span>压力等级：{{ pressureLevelLabel(selectedPoint.pressureLevel) }}</span>
              <span>安装位置：{{ selectedPoint.address }}</span>
              <span>监测单位：沅陵县燃气安全监测中心</span>
            </div>
          </div>

          <!-- 实时读数卡片 -->
          <div class="gauge-cards">
            <div class="gauge-card" :class="selectedPoint.status">
              <div class="gauge-label">当前压力</div>
              <div class="gauge-value">{{ selectedPoint.latestPressure }} <span class="unit">kPa</span></div>
              <div class="gauge-sub">采集时间 {{ selectedPoint.latestTime }}</div>
            </div>
            <div class="gauge-card">
              <div class="gauge-label">今日最高</div>
              <div class="gauge-value high">{{ todayMax }} <span class="unit">kPa</span></div>
              <div class="gauge-sub">近24小时</div>
            </div>
            <div class="gauge-card">
              <div class="gauge-label">今日最低</div>
              <div class="gauge-value low">{{ todayMin }} <span class="unit">kPa</span></div>
              <div class="gauge-sub">近24小时</div>
            </div>
            <div class="gauge-card">
              <div class="gauge-label">压力状态</div>
              <div class="gauge-status" :class="selectedPoint.status">{{ statusLabel(selectedPoint.status) }}</div>
              <div class="gauge-sub">阈值 {{ selectedPoint.minPressure }}~{{ selectedPoint.maxPressure }} kPa</div>
            </div>
          </div>

          <!-- 压力趋势图 -->
          <div class="chart-card">
            <div class="chart-header">
              <span>压力趋势（近10天）</span>
              <div class="chart-legend">
                <span class="leg-item"><i class="leg-dot pressure"></i> 实测压力</span>
                <span class="leg-item"><i class="leg-line max"></i> 上限</span>
                <span class="leg-item"><i class="leg-line min"></i> 下限</span>
              </div>
            </div>
            <div ref="chartRef" class="chart-container"></div>
          </div>

          <!-- 历史数据表格 -->
          <div class="table-card">
            <div class="table-header">
              <span>历史监测记录</span>
            </div>
            <el-table :data="pagedHistory" border stripe size="small">
              <el-table-column prop="time" label="采集时间" width="160" />
              <el-table-column prop="pressure" label="压力值(kPa)" width="120">
                <template #default="{ row }">
                  <span :style="{ color: row.pressure > selectedPoint.maxPressure || row.pressure < selectedPoint.minPressure ? '#f56c6c' : '#303133', fontWeight: row.pressure > selectedPoint.maxPressure || row.pressure < selectedPoint.minPressure ? '600' : '400' }">
                    {{ row.pressure }}
                  </span>
                </template>
              </el-table-column>
              <el-table-column prop="temperature" label="温度(°C)" width="100" />
              <el-table-column prop="status" label="状态" width="100">
                <template #default="{ row }">
                  <el-tag :type="row.pressure > selectedPoint.maxPressure || row.pressure < selectedPoint.minPressure ? 'danger' : 'success'" size="small">
                    {{ row.pressure > selectedPoint.maxPressure || row.pressure < selectedPoint.minPressure ? '异常' : '正常' }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="collector" label="采集设备" min-width="140" />
              <el-table-column prop="remark" label="备注" min-width="120" show-overflow-tooltip />
            </el-table>
            <el-pagination
                v-model:current-page="historyPage"
                v-model:page-size="historyPageSize"
                :total="historyData.length"
                layout="total, prev, pager, next"
                small
            />
          </div>

        </template>

        <!-- 未选中状态 -->
        <div v-else class="empty-detail">
          <el-empty description="请从左侧选择压力监测点查看详情" :image-size="100" />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'
import { Odometer, Search, Refresh } from '@element-plus/icons-vue'
import * as echarts from 'echarts'

// 筛选
const searchKeyword = ref('')
const pressureLevel = ref('')
const statusFilter = ref('')

// 选中测点
const selectedPoint = ref(null)

// 历史数据分页
const historyPage = ref(1)
const historyPageSize = ref(10)

// ECharts实例
const chartRef = ref(null)
let chartInstance = null

// ==================== 沅陵县管线压力测点数据 ====================
const mockPoints = ref([
  {
    id: 1, name: '辰州北路高压测点1#', pipelineName: '辰州北路高压段', pressureLevel: 'high',
    address: '沅陵县太常片区辰州北路与建设路交叉口北侧', lng: 110.3938, lat: 28.4692,
    latestPressure: 385, minPressure: 240, maxPressure: 420, status: 'normal', latestTime: '2026-06-13 15:32:18'
  },
  {
    id: 2, name: '辰州中路高压测点2#', pipelineName: '辰州中路高压段', pressureLevel: 'high',
    address: '沅陵县太常片区辰州中路与天宁路交叉口南侧', lng: 110.3935, lat: 28.4658,
    latestPressure: 432, minPressure: 240, maxPressure: 420, status: 'danger', latestTime: '2026-06-13 15:31:45'
  },
  {
    id: 3, name: '辰州南路高压测点3#', pipelineName: '辰州南路高压段', pressureLevel: 'high',
    address: '沅陵县太常片区辰州南路近滨江路口', lng: 110.3934, lat: 28.4580,
    latestPressure: 368, minPressure: 240, maxPressure: 420, status: 'normal', latestTime: '2026-06-13 15:32:05'
  },
  {
    id: 4, name: '古城北路中压测点1#', pipelineName: '古城北路中压段', pressureLevel: 'medium',
    address: '沅陵县太常片区古城北路与天宁路交叉口', lng: 110.3977, lat: 28.4741,
    latestPressure: 218, minPressure: 150, maxPressure: 250, status: 'normal', latestTime: '2026-06-13 15:30:22'
  },
  {
    id: 5, name: '古城中路中压测点2#', pipelineName: '古城中路中压段', pressureLevel: 'medium',
    address: '沅陵县太常片区古城中路太常安置区段', lng: 110.3970, lat: 28.4669,
    latestPressure: 142, minPressure: 150, maxPressure: 250, status: 'warning', latestTime: '2026-06-13 15:29:58'
  },
  {
    id: 6, name: '古城南路中压测点3#', pipelineName: '古城南路中压段', pressureLevel: 'medium',
    address: '沅陵县太常片区古城南路近建设路口', lng: 110.3963, lat: 28.4598,
    latestPressure: 205, minPressure: 150, maxPressure: 250, status: 'normal', latestTime: '2026-06-13 15:31:30'
  },
  {
    id: 7, name: '迎宾西路中压测点1#', pipelineName: '迎宾西路中压段', pressureLevel: 'medium',
    address: '沅陵县太常片区迎宾西路县政府西侧', lng: 110.3824, lat: 28.4645,
    latestPressure: 188, minPressure: 150, maxPressure: 250, status: 'normal', latestTime: '2026-06-13 15:28:15'
  },
  {
    id: 8, name: '迎宾东路中压测点2#', pipelineName: '迎宾东路中压段', pressureLevel: 'medium',
    address: '沅陵县太常片区迎宾东路城郊公交站东侧', lng: 110.4054, lat: 28.4630,
    latestPressure: 198, minPressure: 150, maxPressure: 250, status: 'normal', latestTime: '2026-06-13 15:30:50'
  },
  {
    id: 9, name: '建设路中压测点1#', pipelineName: '建设路中压段', pressureLevel: 'medium',
    address: '沅陵县太常片区建设路县政府南侧', lng: 110.3937, lat: 28.4582,
    latestPressure: 0, minPressure: 150, maxPressure: 250, status: 'offline', latestTime: '2026-06-13 12:05:00'
  },
  {
    id: 10, name: '建设西路中压测点2#', pipelineName: '建设西路中压段', pressureLevel: 'medium',
    address: '沅陵县太常片区建设西路人行道绿化带', lng: 110.3840, lat: 28.4588,
    latestPressure: 175, minPressure: 150, maxPressure: 250, status: 'normal', latestTime: '2026-06-13 15:29:30'
  },
  {
    id: 11, name: '滨江路低压测点1#', pipelineName: '滨江路段低压段', pressureLevel: 'low',
    address: '沅陵县太常片区滨江西路河堤段', lng: 110.3820, lat: 28.4568,
    latestPressure: 112, minPressure: 80, maxPressure: 150, status: 'normal', latestTime: '2026-06-13 15:31:10'
  },
  {
    id: 12, name: '滨江东路低压测点2#', pipelineName: '滨江东路低压段', pressureLevel: 'low',
    address: '沅陵县太常片区滨江东路与天宁东路交叉口', lng: 110.4066, lat: 28.4557,
    latestPressure: 78, minPressure: 80, maxPressure: 150, status: 'warning', latestTime: '2026-06-13 15:30:40'
  },
  {
    id: 13, name: '天宁西路低压测点1#', pipelineName: '天宁西路低压段', pressureLevel: 'low',
    address: '沅陵县太常片区天宁西路太常卫生院外墙', lng: 110.3850, lat: 28.4703,
    latestPressure: 128, minPressure: 80, maxPressure: 150, status: 'normal', latestTime: '2026-06-13 15:32:00'
  },
  {
    id: 14, name: '天宁东路低压测点2#', pipelineName: '天宁东路低压段', pressureLevel: 'low',
    address: '沅陵县太常片区天宁东路末端近滨江路', lng: 110.4088, lat: 28.4690,
    latestPressure: 136, minPressure: 80, maxPressure: 150, status: 'normal', latestTime: '2026-06-13 15:31:55'
  },
  {
    id: 15, name: '建设东路高压测点4#', pipelineName: '建设东路高压段', pressureLevel: 'high',
    address: '沅陵县太常片区建设东路工业园入口处', lng: 110.4050, lat: 28.4577,
    latestPressure: 410, minPressure: 240, maxPressure: 420, status: 'warning', latestTime: '2026-06-13 15:31:25'
  }
])

// 统计数据
const normalCount = computed(() => mockPoints.value.filter(p => p.status === 'normal').length)
const warningCount = computed(() => mockPoints.value.filter(p => p.status === 'warning').length)
const dangerCount = computed(() => mockPoints.value.filter(p => p.status === 'danger').length)
const offlineCount = computed(() => mockPoints.value.filter(p => p.status === 'offline').length)

// 筛选
const filteredPoints = computed(() => {
  let list = mockPoints.value
  if (searchKeyword.value) {
    const kw = searchKeyword.value.toLowerCase()
    list = list.filter(p => p.name.toLowerCase().includes(kw) || p.pipelineName.toLowerCase().includes(kw))
  }
  if (pressureLevel.value) list = list.filter(p => p.pressureLevel === pressureLevel.value)
  if (statusFilter.value) list = list.filter(p => p.status === statusFilter.value)
  return list
})

function statusTagType(status) {
  const map = { normal: 'success', warning: 'warning', danger: 'danger', offline: 'info' }
  return map[status] || 'info'
}
function statusLabel(status) {
  const map = { normal: '正常', warning: '预警', danger: '告警', offline: '离线' }
  return map[status] || '未知'
}
function pressureLevelLabel(level) {
  const map = { high: '高压 (0.4MPa)', medium: '中压 (0.2MPa)', low: '低压 (0.1MPa)' }
  return map[level] || level
}

// ==================== 近10天静态压力数据（每天6个时段: 0/4/8/12/16/20时） ====================
function generateHistory(point) {
  const baseP = point.latestPressure > 0 ? point.latestPressure : (point.minPressure + point.maxPressure) / 2
  // 模拟每日压力波动基准模式: 凌晨低、早高峰高、午间稳、晚高峰高
  const hourOffsets = [0, 4, 8, 12, 16, 20]
  const hourFactors = [0.92, 0.95, 1.08, 1.02, 1.06, 0.98]
  // 每点预设的压力日波动序列(10天，每天6个时段)
  const daySeeds = [
    [0, -3, 6, 2, 5, -1], [-2, -5, 4, -1, 3, -4], [1, 2, 8, 4, 6, 0], [-3, -2, 3, 0, 4, -2], [2, 1, 7, 3, 5, 1],
    [-1, -4, 5, 1, 2, -3], [3, 0, 9, 5, 7, 2], [-4, -1, 2, -2, 1, -5], [0, 3, 6, 2, 4, -1], [2, -2, 5, 3, 6, 0]
  ]
  const data = []
  const now = new Date()
  for (let d = 9; d >= 0; d--) {
    const dayIdx = 9 - d
    for (let hi = 0; hi < 6; hi++) {
      const h = hourOffsets[hi]
      const date = new Date(now)
      date.setDate(date.getDate() - d)
      date.setHours(h, 0, 0)
      const variation = baseP * (hourFactors[hi] - 1) + daySeeds[dayIdx][hi] * (point.maxPressure - point.minPressure) / 50
      const pressure = Math.round((baseP + variation) * 10) / 10
      const temp = (24 + (h < 6 ? 0 : h < 12 ? 3 : h < 18 ? 4 : 1)).toFixed(1)
      data.push({
        time: date.toISOString().replace('T', ' ').substring(0, 19),
        pressure,
        temperature: temp,
        collector: `YLCG-${String(point.id).padStart(3, '0')}`,
        remark: pressure > point.maxPressure ? '压力超上限' : pressure < point.minPressure ? '压力低于下限' : ''
      })
    }
  }
  return data
}

const historyData = ref([])
const pagedHistory = computed(() => {
  const start = (historyPage.value - 1) * historyPageSize.value
  return historyData.value.slice(start, start + historyPageSize.value)
})

// 今日极值
const todayMax = computed(() => {
  const today = historyData.value.filter(d => d.time.startsWith('2026-06-13'))
  if (!today.length) return '--'
  return Math.max(...today.map(d => d.pressure))
})
const todayMin = computed(() => {
  const today = historyData.value.filter(d => d.time.startsWith('2026-06-13'))
  if (!today.length) return '--'
  return Math.min(...today.map(d => d.pressure))
})

// ==================== 选择测点 ====================
function selectPoint(point) {
  selectedPoint.value = point
  historyPage.value = 1
  historyData.value = generateHistory(point)
  nextTick(() => renderChart())
}

// ==================== ECharts趋势图 ====================
function renderChart() {
  if (!chartRef.value || !selectedPoint.value) return
  if (!chartInstance) {
    chartInstance = echarts.init(chartRef.value)
  }
  const point = selectedPoint.value
  const times = historyData.value.map(d => d.time.substring(5, 16).replace(' ', '\n'))
  const pressures = historyData.value.map(d => d.pressure)

  chartInstance.setOption({
    tooltip: {
      trigger: 'axis',
      formatter: params => {
        const p = params[0]
        const val = p.value
        const status = val > point.maxPressure ? '⚠ 超上限' : val < point.minPressure ? '⚠ 低于下限' : '✓ 正常'
        return `${p.axisValue.replace('\n', ' ')}<br/>压力: <b>${val} kPa</b> ${status}`
      }
    },
    grid: { left: '3%', right: '5%', top: 20, bottom: 30, containLabel: true },
    xAxis: {
      type: 'category', data: times, boundaryGap: false,
      axisLine: { lineStyle: { color: '#ccc' } },
      axisTick: { show: false },
      axisLabel: { fontSize: 10, interval: 5 }
    },
    yAxis: {
      type: 'value', name: 'kPa',
      axisLine: { show: false }, axisTick: { show: false },
      splitLine: { lineStyle: { color: '#f0f0f0' } },
      min: Math.min(point.minPressure - 30, ...pressures) - 10,
      max: Math.max(point.maxPressure + 30, ...pressures) + 10
    },
    series: [
      {
        name: '实测压力', type: 'line', data: pressures,
        smooth: true, symbol: 'circle', symbolSize: 4,
        lineStyle: { width: 2, color: '#409eff' },
        itemStyle: { color: '#409eff' },
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: 'rgba(64,158,255,0.25)' },
            { offset: 1, color: 'rgba(64,158,255,0.02)' }
          ])
        },
        markLine: {
          silent: true,
          symbol: 'none',
          label: { fontSize: 11, formatter: '{b} {c} kPa' },
          data: [
            { name: '上限', yAxis: point.maxPressure, lineStyle: { color: '#f56c6c', type: 'dashed', width: 1.5 } },
            { name: '下限', yAxis: point.minPressure, lineStyle: { color: '#e6a23c', type: 'dashed', width: 1.5 } }
          ]
        }
      }
    ]
  })
}

function refreshData() {
  historyData.value = selectedPoint.value ? generateHistory(selectedPoint.value) : []
  nextTick(() => renderChart())
}

watch(pressureLevel, () => {})
watch(statusFilter, () => {})

onMounted(() => {
  window.addEventListener('resize', () => { try { chartInstance?.resize() } catch {} })
  // 默认选中第一条数据
  if (mockPoints.value.length > 0) {
    selectPoint(mockPoints.value[0])
  }
})

onBeforeUnmount(() => {
  try { chartInstance?.dispose() } catch {}
  chartInstance = null
})
</script>

<style scoped>
.pressure-monitor {
  background: #f0f2f6;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.page-header {
  background: #fff;
  padding: 12px 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #e9ecef;
  flex-shrink: 0;
}
.header-left { display: flex; align-items: center; gap: 20px; }
.header-left .title { font-size: 1.25rem; font-weight: 600; color: #1f2d3d; }
.stats-badge { display: flex; gap: 20px; }
.stat-item { font-size: 13px; display: flex; align-items: center; gap: 6px; }
.stat-item .dot { width: 8px; height: 8px; border-radius: 50%; }
.stat-item.normal { color: #67c23a; } .stat-item.normal .dot { background: #67c23a; }
.stat-item.warning { color: #e6a23c; } .stat-item.warning .dot { background: #e6a23c; }
.stat-item.danger { color: #f56c6c; } .stat-item.danger .dot { background: #f56c6c; }
.stat-item.offline { color: #909399; } .stat-item.offline .dot { background: #909399; }
.header-right { display: flex; gap: 12px; }

.main-layout {
  display: flex;
  flex: 1;
  overflow: hidden;
  padding: 12px;
  gap: 12px;
}

/* 左侧测点列表 */
.point-list-panel {
  width: 360px;
  background: #fff;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex-shrink: 0;
}
.list-header {
  padding: 14px 16px;
  border-bottom: 1px solid #e9ecef;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
}
.total-num { font-size: 12px; color: #909399; font-weight: 400; }
.filter-row { padding: 6px 16px; }
.point-list { flex: 1; overflow-y: auto; padding: 4px 8px 8px; }
.point-item {
  padding: 12px;
  margin-bottom: 6px;
  border-radius: 12px;
  background: #fafbfc;
  cursor: pointer;
  transition: all 0.2s;
  border: 1px solid #e9ecef;
}
.point-item:hover { background: #f0f5ff; }
.point-item.active { background: #ecf5ff; border-color: #409eff; }
.point-item.danger { border-left: 3px solid #f56c6c; }
.point-item.warning { border-left: 3px solid #e6a23c; }
.point-item.offline { opacity: 0.65; }
.point-header { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.point-name { font-weight: 600; font-size: 14px; flex: 1; }
.point-pipeline { font-size: 12px; color: #909399; margin-bottom: 6px; }
.point-value { display: flex; align-items: baseline; gap: 6px; margin-bottom: 4px; }
.point-value .val { font-size: 24px; font-weight: 700; color: #1f2d3d; }
.point-value .unit { font-size: 12px; color: #909399; }
.point-value .threshold { font-size: 11px; color: #c0c4cc; margin-left: auto; }
.point-addr { font-size: 11px; color: #909399; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.point-time { font-size: 11px; color: #c0c4cc; margin-top: 2px; }

/* 右侧详情面板 */
.detail-panel {
  flex: 1;
  background: #fff;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.empty-detail {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.detail-header {
  padding: 16px 20px;
  border-bottom: 1px solid #e9ecef;
}
.detail-title { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.detail-title .point-name { font-size: 18px; font-weight: 600; }
.detail-meta { display: flex; flex-wrap: wrap; gap: 0 24px; font-size: 13px; color: #909399; }

/* 读数卡片 */
.gauge-cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  padding: 16px 20px;
}
.gauge-card {
  background: #f8f9fc;
  border-radius: 12px;
  padding: 16px;
  text-align: center;
}
.gauge-card.danger { background: #fef0f0; }
.gauge-card.warning { background: #fdf6ec; }
.gauge-label { font-size: 12px; color: #909399; margin-bottom: 8px; }
.gauge-value { font-size: 28px; font-weight: 700; color: #1f2d3d; }
.gauge-value .unit { font-size: 13px; font-weight: 400; color: #909399; }
.gauge-value.high { color: #f56c6c; }
.gauge-value.low { color: #67c23a; }
.gauge-status { font-size: 20px; font-weight: 700; }
.gauge-status.normal { color: #67c23a; }
.gauge-status.warning { color: #e6a23c; }
.gauge-status.danger { color: #f56c6c; }
.gauge-status.offline { color: #909399; }
.gauge-sub { font-size: 11px; color: #c0c4cc; margin-top: 6px; }

/* 趋势图 */
.chart-card {
  margin: 0 20px 16px;
  padding: 16px;
  background: #fafbfc;
  border-radius: 12px;
}
.chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  font-weight: 600;
}
.chart-legend { display: flex; gap: 16px; font-size: 12px; font-weight: 400; }
.leg-item { display: flex; align-items: center; gap: 4px; }
.leg-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.leg-dot.pressure { background: #409eff; }
.leg-line { width: 20px; height: 2px; display: inline-block; }
.leg-line.max { background: #f56c6c; background: repeating-linear-gradient(90deg, #f56c6c 0, #f56c6c 4px, transparent 4px, transparent 7px); }
.leg-line.min { background: #e6a23c; background: repeating-linear-gradient(90deg, #e6a23c 0, #e6a23c 4px, transparent 4px, transparent 7px); }
.chart-container { width: 100%; height: 300px; }

/* 历史表格 */
.table-card {
  margin: 0 20px 16px;
  padding: 16px;
  background: #fafbfc;
  border-radius: 12px;
  flex: 1;
  overflow: auto;
}
.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  font-weight: 600;
}
</style>
