<!--管线流量监测-->
<template>
  <div class="flow-monitor">
    <!-- 页面头部 -->
    <div class="page-header">
      <div class="header-left">
        <el-icon><TrendCharts /></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="pipeType" 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.latestFlow }}</span>
              <span class="unit">Nm³/h</span>
              <span class="threshold">量程: 0~{{ point.maxFlow }} Nm³/h</span>
            </div>
            <div class="point-sub" v-if="point.status !== 'offline'">
              <span>今日累计 <b>{{ point.todayTotal }}</b> Nm³</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>管线类型：{{ pipeTypeLabel(selectedPoint.pipeType) }}</span>
              <span>计量表型号：TBQZ-{{ selectedPoint.meterModel }}</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.latestFlow }} <span class="unit">Nm³/h</span></div>
              <div class="gauge-sub">采集时间 {{ selectedPoint.latestTime }}</div>
            </div>
            <div class="gauge-card">
              <div class="gauge-label">今日累计</div>
              <div class="gauge-value high">{{ selectedPoint.todayTotal }} <span class="unit">Nm³</span></div>
              <div class="gauge-sub">当日0时起累计</div>
            </div>
            <div class="gauge-card">
              <div class="gauge-label">昨日累计</div>
              <div class="gauge-value low">{{ selectedPoint.yesterdayTotal }} <span class="unit">Nm³</span></div>
              <div class="gauge-sub">较昨日 {{ selectedPoint.dodChange }}</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">量程 0~{{ selectedPoint.maxFlow }} Nm³/h</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 flow"></i> 瞬时流量</span>
                <span class="leg-item"><i class="leg-line max"></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="flow" label="瞬时流量(Nm³/h)" width="140">
                <template #default="{ row }">
                  <span :style="{ color: row.flow > selectedPoint.maxFlow ? '#f56c6c' : '#303133', fontWeight: row.flow > selectedPoint.maxFlow ? '600' : '400' }">
                    {{ row.flow }}
                  </span>
                </template>
              </el-table-column>
              <el-table-column prop="dailyTotal" label="日累计(Nm³)" width="130" />
              <el-table-column prop="temperature" label="温度(°C)" width="100" />
              <el-table-column prop="pressure" label="压力(kPa)" width="110" />
              <el-table-column prop="status" label="状态" width="100">
                <template #default="{ row }">
                  <el-tag :type="row.flow > selectedPoint.maxFlow ? 'danger' : 'success'" size="small">
                    {{ row.flow > selectedPoint.maxFlow ? '超限' : '正常' }}
                  </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 } from 'vue'
import { TrendCharts, Search, Refresh } from '@element-plus/icons-vue'
import * as echarts from 'echarts'

const searchKeyword = ref('')
const pipeType = ref('')
const statusFilter = ref('')
const selectedPoint = ref(null)
const historyPage = ref(1)
const historyPageSize = ref(10)

const chartRef = ref(null)
let chartInstance = null

// ==================== 沅陵县管线流量测点数据 ====================
const mockPoints = ref([
  {
    id: 1, name: '辰州北路流量计1#', pipelineName: '辰州北路高压段', pipeType: 'high',
    address: '沅陵县太常片区辰州北路门站出口计量间', lng: 110.3938, lat: 28.4695,
    meterModel: 'IIIC-150', latestFlow: 1850, maxFlow: 2500, status: 'normal', latestTime: '2026-06-13 15:32:18',
    todayTotal: '36,420', yesterdayTotal: '38,150', dodChange: '-4.5%'
  },
  {
    id: 2, name: '辰州中路流量计2#', pipelineName: '辰州中路高压段', pipeType: 'high',
    address: '沅陵县太常片区辰州中路调压站进口侧', lng: 110.3935, lat: 28.4665,
    meterModel: 'IIIC-150', latestFlow: 2620, maxFlow: 2500, status: 'danger', latestTime: '2026-06-13 15:31:45',
    todayTotal: '48,920', yesterdayTotal: '42,300', dodChange: '+15.6%'
  },
  {
    id: 3, name: '辰州南路流量计3#', pipelineName: '辰州南路高压段', pipeType: 'high',
    address: '沅陵县太常片区辰州南路滨江路口计量柜', lng: 110.3934, lat: 28.4575,
    meterModel: 'IIIC-100', latestFlow: 1120, maxFlow: 2000, status: 'normal', latestTime: '2026-06-13 15:32:05',
    todayTotal: '22,180', yesterdayTotal: '23,050', dodChange: '-3.8%'
  },
  {
    id: 4, name: '古城北路流量计1#', pipelineName: '古城北路中压段', pipeType: 'medium',
    address: '沅陵县太常片区古城北路与天宁路交叉口', lng: 110.3977, lat: 28.4741,
    meterModel: 'IIIC-80', latestFlow: 580, maxFlow: 800, status: 'normal', latestTime: '2026-06-13 15:30:22',
    todayTotal: '11,350', yesterdayTotal: '12,100', dodChange: '-6.2%'
  },
  {
    id: 5, name: '古城中路流量计2#', pipelineName: '古城中路中压段', pipeType: 'medium',
    address: '沅陵县太常片区古城中路太常安置区段', lng: 110.3970, lat: 28.4669,
    meterModel: 'IIIC-80', latestFlow: 820, maxFlow: 800, status: 'danger', latestTime: '2026-06-13 15:29:58',
    todayTotal: '16,840', yesterdayTotal: '13,500', dodChange: '+24.7%'
  },
  {
    id: 6, name: '古城南路流量计3#', pipelineName: '古城南路中压段', pipeType: 'medium',
    address: '沅陵县太常片区古城南路近建设路口', lng: 110.3963, lat: 28.4598,
    meterModel: 'IIIC-80', latestFlow: 420, maxFlow: 800, status: 'normal', latestTime: '2026-06-13 15:31:30',
    todayTotal: '8,920', yesterdayTotal: '9,450', dodChange: '-5.6%'
  },
  {
    id: 7, name: '迎宾西路流量计1#', pipelineName: '迎宾西路中压段', pipeType: 'medium',
    address: '沅陵县太常片区迎宾西路县政府对面', lng: 110.3870, lat: 28.4642,
    meterModel: 'IIIC-65', latestFlow: 310, maxFlow: 500, status: 'normal', latestTime: '2026-06-13 15:28:15',
    todayTotal: '6,180', yesterdayTotal: '6,540', dodChange: '-5.5%'
  },
  {
    id: 8, name: '迎宾东路流量计2#', pipelineName: '迎宾东路中压段', pipeType: 'medium',
    address: '沅陵县太常片区迎宾东路商贸城北侧', lng: 110.4054, lat: 28.4630,
    meterModel: 'IIIC-65', latestFlow: 280, maxFlow: 500, status: 'normal', latestTime: '2026-06-13 15:30:50',
    todayTotal: '5,650', yesterdayTotal: '5,980', dodChange: '-5.5%'
  },
  {
    id: 9, name: '建设路流量计1#', pipelineName: '建设路中压段', pipeType: 'medium',
    address: '沅陵县太常片区建设路县政府南侧计量站', lng: 110.3937, lat: 28.4582,
    meterModel: 'IIIC-80', latestFlow: 0, maxFlow: 800, status: 'offline', latestTime: '2026-06-13 08:15:00',
    todayTotal: '--', yesterdayTotal: '14,200', dodChange: '--'
  },
  {
    id: 10, name: '建设西路流量计2#', pipelineName: '建设西路中压段', pipeType: 'medium',
    address: '沅陵县太常片区建设西路工业园计量站', lng: 110.3840, lat: 28.4588,
    meterModel: 'IIIC-100', latestFlow: 680, maxFlow: 1000, status: 'normal', latestTime: '2026-06-13 15:29:30',
    todayTotal: '13,520', yesterdayTotal: '14,080', dodChange: '-4.0%'
  },
  {
    id: 11, name: '滨江路流量计1#', pipelineName: '滨江路段低压段', pipeType: 'low',
    address: '沅陵县太常片区滨江西路住宅区调压柜后', lng: 110.3820, lat: 28.4568,
    meterModel: 'IIIC-50', latestFlow: 95, maxFlow: 200, status: 'normal', latestTime: '2026-06-13 15:31:10',
    todayTotal: '1,850', yesterdayTotal: '1,920', dodChange: '-3.6%'
  },
  {
    id: 12, name: '滨江东路流量计2#', pipelineName: '滨江东路低压段', pipeType: 'low',
    address: '沅陵县太常片区滨江东路商业街调压柜后', lng: 110.4066, lat: 28.4557,
    meterModel: 'IIIC-50', latestFlow: 210, maxFlow: 200, status: 'danger', latestTime: '2026-06-13 15:30:40',
    todayTotal: '4,320', yesterdayTotal: '3,650', dodChange: '+18.4%'
  },
  {
    id: 13, name: '天宁西路流量计1#', pipelineName: '天宁西路低压段', pipeType: 'low',
    address: '沅陵县太常片区天宁西路太常卫生院旁', lng: 110.3850, lat: 28.4703,
    meterModel: 'IIIC-50', latestFlow: 75, maxFlow: 200, status: 'normal', latestTime: '2026-06-13 15:32:00',
    todayTotal: '1,520', yesterdayTotal: '1,650', dodChange: '-7.9%'
  },
  {
    id: 14, name: '天宁东路流量计2#', pipelineName: '天宁东路低压段', pipeType: 'low',
    address: '沅陵县太常片区天宁东路末端近滨江路', lng: 110.4088, lat: 28.4690,
    meterModel: 'IIIC-50', latestFlow: 88, maxFlow: 200, status: 'normal', latestTime: '2026-06-13 15:31:55',
    todayTotal: '1,760', yesterdayTotal: '1,840', dodChange: '-4.3%'
  },
  {
    id: 15, name: '建设东路流量计3#', pipelineName: '建设东路高压段', pipeType: 'high',
    address: '沅陵县太常片区建设东路工业园入口处', lng: 110.4050, lat: 28.4577,
    meterModel: 'IIIC-150', latestFlow: 2380, maxFlow: 2500, status: 'warning', latestTime: '2026-06-13 15:31:25',
    todayTotal: '42,150', yesterdayTotal: '38,600', dodChange: '+9.2%'
  }
])

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 (pipeType.value) list = list.filter(p => p.pipeType === pipeType.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 pipeTypeLabel(type) {
  const map = { high: '高压', medium: '中压', low: '低压' }
  return map[type] || type
}

// ==================== 近10天静态流量数据（每天4时段: 6/12/18/23时, 模拟用气高峰） ====================
function generateHistory(point) {
  const baseFlow = point.latestFlow > 0 ? point.latestFlow : Math.round(point.maxFlow * 0.5)
  // 用气高峰因子: 早6点、午12点、晚18点为高峰，23点为低谷
  const hourFactors = { 6: 1.25, 12: 1.45, 18: 1.35, 23: 0.65 }
  // 每点预设的日波动序列(10天)
  const daySeeds = [
    { 6: 0, 12: 5, 18: 3, 23: -2 }, { 6: -2, 12: 2, 18: 0, 23: -4 },
    { 6: 3, 12: 8, 18: 5, 23: 0 }, { 6: -1, 12: 4, 18: 2, 23: -3 },
    { 6: 2, 12: 6, 18: 4, 23: 1 }, { 6: -3, 12: 1, 18: -1, 23: -5 },
    { 6: 1, 12: 7, 18: 6, 23: -1 }, { 6: 0, 12: 3, 18: 1, 23: -2 },
    { 6: -2, 12: 5, 18: 3, 23: -3 }, { 6: 4, 12: 9, 18: 6, 23: 0 }
  ]
  const data = []
  const now = new Date()
  let cumulative = 0
  const hours = [6, 12, 18, 23]
  for (let d = 9; d >= 0; d--) {
    const dayIdx = 9 - d
    for (const h of hours) {
      const date = new Date(now)
      date.setDate(date.getDate() - d)
      date.setHours(h, 0, 0)
      const factor = hourFactors[h] || 1
      const seed = (daySeeds[dayIdx] && daySeeds[dayIdx][h]) || 0
      const variation = baseFlow * (factor - 1) + seed * (point.maxFlow / 50)
      const flow = Math.round((baseFlow + variation) * 10) / 10
      const dailyCumulative = Math.round(Math.abs(flow) * 6)
      cumulative += dailyCumulative
      const temp = (24 + (h < 8 ? 1 : h < 14 ? 3 : h < 20 ? 4 : 0)).toFixed(1)
      const pressure = point.pipeType === 'high' ? (380 + h * 0.5).toFixed(1) :
                      point.pipeType === 'medium' ? (190 + h * 0.3).toFixed(1) :
                      (110 + h * 0.2).toFixed(1)
      data.push({
        time: date.toISOString().replace('T', ' ').substring(0, 19),
        flow,
        dailyTotal: Math.round(cumulative).toLocaleString(),
        temperature: temp,
        pressure,
        collector: `YLLL-${String(point.id).padStart(3, '0')}`,
        remark: flow > point.maxFlow ? '流量超量程上限' : ''
      })
    }
  }
  return data
}

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

// ==================== 选择测点 ====================
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 flows = historyData.value.map(d => d.flow)

  chartInstance.setOption({
    tooltip: {
      trigger: 'axis',
      formatter: params => {
        const p = params[0]
        const val = p.value
        const status = val > point.maxFlow ? '⚠ 超量程上限' : '✓ 正常'
        return `${p.axisValue.replace('\n', ' ')}<br/>瞬时流量: <b>${val} Nm³/h</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: 3 }
    },
    yAxis: {
      type: 'value', name: 'Nm³/h',
      axisLine: { show: false }, axisTick: { show: false },
      splitLine: { lineStyle: { color: '#f0f0f0' } },
      min: 0,
      max: Math.max(point.maxFlow + 300, ...flows) + 100
    },
    series: [
      {
        name: '瞬时流量', type: 'line', data: flows,
        smooth: true, symbol: 'circle', symbolSize: 4,
        lineStyle: { width: 2, color: '#52c41a' },
        itemStyle: { color: '#52c41a' },
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: 'rgba(82,196,26,0.25)' },
            { offset: 1, color: 'rgba(82,196,26,0.02)' }
          ])
        },
        markLine: {
          silent: true,
          symbol: 'none',
          label: { fontSize: 11, formatter: '{b} {c} Nm³/h' },
          data: [
            { name: '量程上限', yAxis: point.maxFlow, lineStyle: { color: '#f56c6c', type: 'dashed', width: 1.5 } }
          ]
        }
      }
    ]
  })
}

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

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>
.flow-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: 370px;
  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-sub { font-size: 12px; color: #606266; margin-bottom: 2px; }
.point-sub b { color: #1f2d3d; }
.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: #1890ff; }
.gauge-value.low { color: #52c41a; }
.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.flow { background: #52c41a; }
.leg-line { width: 20px; height: 2px; display: inline-block; }
.leg-line.max { background: repeating-linear-gradient(90deg, #f56c6c 0, #f56c6c 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>
