<!--监测设备一张图-->
<template>
  <div class="gis-monitor-dashboard">
    <!-- 顶部导航栏 -->
    <div class="dashboard-header">
      <div class="header-actions">
        <el-badge :value="onlineCount" type="primary">
          <el-button type="primary" plain :icon="Connection">在线设备</el-button>
        </el-badge>
        <el-badge :value="alertCount" type="danger">
          <el-button type="danger" plain :icon="WarningFilled">告警设备</el-button>
        </el-badge>
      </div>
    </div>

    <!-- 主体区域：左侧设备列表 + 右侧百度地图 -->
    <div class="main-layout">
      <!-- 左侧：设备列表 & 筛选 -->
      <div class="device-panel">
        <div class="panel-header">
          <span>监测设备列表</span>
          <el-input
              v-model="searchKeyword"
              placeholder="搜索设备名称/编号"
              clearable
              :prefix-icon="Search"
              size="small"
              @keyup.enter="handleSearch"
              @clear="handleSearch"
          />
        </div>
        <div class="filter-tabs">
          <el-radio-group v-model="typeFilter" size="small" @change="handleSearch">
            <el-radio-button label="all">全部</el-radio-button>
            <el-radio-button label="5">供水窨井</el-radio-button>
            <el-radio-button label="9">排水窨井</el-radio-button>
            <el-radio-button label="10">燃气窨井</el-radio-button>
          </el-radio-group>
        </div>
        <div class="device-list-scroll" v-loading="listLoading">
          <div
              v-for="device in devices"
              :key="device.id"
              class="device-item"
              :class="{ active: selectedDevice?.id === device.id }"
              @click="selectDevice(device)"
          >
            <div class="device-status-dot">
              <div class="status-icon" :style="{ backgroundColor: getStatusColor(device.status) }"></div>
            </div>
            <div class="device-info">
              <div class="device-name">{{ device.name }}</div>
              <div class="device-location">
                <el-icon><Location /></el-icon> {{ device.location || '未知位置' }}
              </div>
              <div class="device-meta">
                <el-tag size="small" :type="getStatusTag(device.status)">{{ getStatusText(device.status) }}</el-tag>
                <span class="device-time">{{ device.typeName }}</span>
              </div>
            </div>
          </div>
          <el-empty v-if="!listLoading && devices.length === 0" description="暂无设备数据" :image-size="80" />
          <!-- 分页 -->
          <div class="pagination-area">
            <el-pagination
                small
                background
                layout="prev, pager, next"
                :total="total"
                :page-size="pageSize"
                v-model:current-page="currentPage"
                @current-change="loadDevices"
            />
          </div>
        </div>
      </div>

      <!-- 右侧：百度地图展示区 -->
      <div class="gis-container">
        <div class="map-toolbar">
          <div class="tool-group">
            <span class="map-title">沅陵县窨井设备分布</span>
          </div>
          <div class="legend">
            <span><i class="legend-dot online"></i> 在线</span>
            <span><i class="legend-dot offline"></i> 离线</span>
            <span><i class="legend-dot selected"></i> 选中设备</span>
          </div>
        </div>

        <!-- 百度地图容器 -->
        <div class="map-area">
          <div id="deviceApictureMap" class="bmap-container"></div>
        </div>

        <!-- 右下角 选中设备详情卡片 -->
        <transition name="slide-fade">
          <div v-if="selectedDevice" class="detail-card">
            <div class="card-header">
              <strong>设备详情</strong>
              <el-icon class="close-icon" @click="clearSelected"><Close /></el-icon>
            </div>
            <div class="card-body">
              <el-descriptions :column="1" border size="small">
                <el-descriptions-item label="设备编号">{{ selectedDevice.code }}</el-descriptions-item>
                <el-descriptions-item label="设备名称">{{ selectedDevice.name }}</el-descriptions-item>
                <el-descriptions-item label="设备类型">{{ selectedDevice.typeName }}</el-descriptions-item>
                <el-descriptions-item label="运维状态">
                  <el-tag :type="getStatusTag(selectedDevice.status)" size="small">{{ getStatusText(selectedDevice.status) }}</el-tag>
                </el-descriptions-item>
                <el-descriptions-item label="经纬度" v-if="selectedDevice.lng">{{ selectedDevice.lng }}, {{ selectedDevice.lat }}</el-descriptions-item>
                <el-descriptions-item label="详细地址">{{ selectedDevice.location }}</el-descriptions-item>
                <el-descriptions-item label="最后通讯">{{ selectedDevice.lastTime }}</el-descriptions-item>
                <el-descriptions-item label="电池电量" v-if="selectedDevice.battery !== null && selectedDevice.battery !== undefined">{{ selectedDevice.battery }}%</el-descriptions-item>
              </el-descriptions>
            </div>
          </div>
        </transition>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { Location, Connection, WarningFilled, Search, Close } from '@element-plus/icons-vue'
import { getManholeDevicePage, getManholeAlarmDeviceList } from '@/api/pipeNetwork/basic'
import locationIcon from '@/assets/images/location.png'
import { ElMessage } from 'element-plus'

// ==================== 分页查询（接口数据） ====================
const searchKeyword = ref('')
const typeFilter = ref('all')
const currentPage = ref(1)
const pageSize = 8
const devices = ref([])
const total = ref(0)
const listLoading = ref(false)

// 顶部统计：在线设备数 / 告警设备数
const onlineCount = ref(0)
const alertCount = ref(0)

// 加载分页设备列表（同时重建地图标记）
async function loadDevices() {
  listLoading.value = true
  try {
    const res = await getManholeDevicePage({
      pageNum: currentPage.value,
      pageSize,
      deviceName: searchKeyword.value.trim() || null,
      equipmentTypeId: typeFilter.value === 'all' ? null : typeFilter.value,
      isQueryManholeData: true
    })
    const rows = res.data?.records || []
    devices.value = rows.map(d => ({
      id: d.equipmentId,
      code: d.equipmentCode,
      name: d.equipmentName,
      equipmentTypeId: d.equipmentTypeId,
      typeName: d.equipmentTypeName,
      location: d.equipmentLocation,
      status: Number(d.equipmentStatus?.onlineStatus) === 1 ? 'online' : 'offline',
      lng: d.longitude != null ? Number(d.longitude) : null,
      lat: d.latitude != null ? Number(d.latitude) : null,
      battery: d.manholeData?.batteryLevel ?? null,
      lastTime: d.manholeData?.uploadTime || d.manholeData?.createTime || '-'
    }))
    total.value = res.data?.total || rows.length
    refreshMarkers()
  } catch (e) {
    ElMessage.error('设备列表加载失败')
  } finally {
    listLoading.value = false
  }
}

// 顶部统计：全量在线数 + 待处理告警设备数
async function loadOverview() {
  try {
    const [onlineRes, alarmRes] = await Promise.all([
      getManholeDevicePage({ pageNum: 1, pageSize: 1000, isQueryManholeData: false }),
      getManholeAlarmDeviceList({ alarmStatus: 1, isQueryManholeData: true })
    ])
    const rows = onlineRes.data?.records || []
    onlineCount.value = rows.filter(d => Number(d.equipmentStatus?.onlineStatus) === 1).length
    alertCount.value = alarmRes.data?.records?.length || 0
  } catch (e) {
    onlineCount.value = 0
    alertCount.value = 0
  }
}

const handleSearch = () => {
  currentPage.value = 1
  loadDevices()
}

// ==================== 选中设备 ====================
const selectedDevice = ref(null)

function selectDevice(device) {
  selectedDevice.value = device
  // 地图中心定位到该设备（无坐标则不移动）
  if (mapInstance && device.lng && device.lat) {
    mapInstance.centerAndZoom(new BMapGL.Point(device.lng, device.lat), 16)
  }
  highlightMarker(device.id)
}

function clearSelected() {
  selectedDevice.value = null
  clearMarkerHighlight()
}

// ==================== 百度地图（BMapGL，中心定位沅陵县） ====================
let mapInstance = null
const markerMap = new Map()

// 沅陵县中心坐标
const YUANLING_CENTER = { lng: 110.393, lat: 28.452 }

function initMap() {
  const container = document.getElementById('deviceApictureMap')
  if (!container || typeof BMapGL === 'undefined') {
    console.warn('BMapGL 未加载或容器不存在')
    return
  }
  try {
    mapInstance = new BMapGL.Map('deviceApictureMap')
    mapInstance.centerAndZoom(new BMapGL.Point(YUANLING_CENTER.lng, YUANLING_CENTER.lat), 13)
    mapInstance.enableScrollWheelZoom(true)
  } catch (e) {
    console.error('百度地图初始化失败：', e)
  }
}

function getStatusColor(status) {
  if (status === 'online') return '#67C23A'
  if (status === 'offline') return '#909399'
  return '#E6A23C'
}

// 添加设备地图标记（状态色名称气泡 + 定位图标）
function addMapMarker(device) {
  if (!mapInstance || device.lng == null || device.lat == null) return
  const color = getStatusColor(device.status)
  const bPoint = new BMapGL.Point(device.lng, device.lat)

  const html = `<div style="text-align:center;cursor:pointer;">
    <div style="color:#fff;background:${color};border-radius:4px;padding:2px 8px;font-size:11px;white-space:nowrap;display:inline-block;margin-bottom:2px;box-shadow:0 1px 4px rgba(0,0,0,0.3);">
      ${device.name}
    </div>
    <div><img src="${locationIcon}" style="width:28px;height:28px;display:block;margin:0 auto;"/></div>
  </div>`

  const label = new BMapGL.Label(html, {
    position: bPoint,
    offset: new BMapGL.Size(-30, -50)
  })
  label.setStyle({
    border: 'none',
    background: 'transparent',
    padding: '0',
    zIndex: '10'
  })
  label.addEventListener('click', function () {
    selectDevice(device)
  })
  mapInstance.addOverlay(label)
  markerMap.set(device.id, label)
}

// 重建地图标记（跟随分页/筛选/搜索结果）
function refreshMarkers() {
  if (!mapInstance) return
  markerMap.forEach(label => mapInstance.removeOverlay(label))
  markerMap.clear()
  devices.value.forEach(device => addMapMarker(device))
}

// 高亮选中标记（放大地图标记气泡）
function highlightMarker(id) {
  markerMap.forEach((label, key) => {
    const dom = label.getContentContainer ? label.getContentContainer() : null
    if (dom) {
      const isSelected = key === id
      dom.style.zIndex = isSelected ? '999' : '10'
      const title = dom.querySelector('div')
      if (title) {
        title.style.transform = isSelected ? 'scale(1.15)' : 'scale(1)'
        title.style.transition = 'transform 0.2s'
        title.style.boxShadow = isSelected ? '0 0 0 2px #409eff' : '0 1px 4px rgba(0,0,0,0.3)'
      }
    }
  })
}

function clearMarkerHighlight() {
  markerMap.forEach((label, key) => {
    const dom = label.getContentContainer ? label.getContentContainer() : null
    if (dom) {
      dom.style.zIndex = '10'
      const title = dom.querySelector('div')
      if (title) {
        title.style.transform = 'scale(1)'
        title.style.boxShadow = '0 1px 4px rgba(0,0,0,0.3)'
      }
    }
  })
}

// 地图自适应窗口变化
const handleResize = () => {
  mapInstance && mapInstance.resize && mapInstance.resize()
}

// ==================== 状态文案 ====================
function getStatusText(status) {
  const map = { online: '在线', offline: '离线' }
  return map[status] || status
}
function getStatusTag(status) {
  const map = { online: 'success', offline: 'info' }
  return map[status] || ''
}

// ==================== 生命周期 ====================
onMounted(async () => {
  await nextTick()
  initMap()
  window.addEventListener('resize', handleResize)
  loadOverview()
  loadDevices()
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize)
  if (mapInstance) {
    mapInstance.clearOverlays && mapInstance.clearOverlays()
    mapInstance = null
  }
  markerMap.clear()
})
</script>

<style scoped>
* {
  box-sizing: border-box;
}
.gis-monitor-dashboard {
  background: #f0f2f6;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-family: 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
}
.dashboard-header {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  background: white;
  padding: 8px 24px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
  z-index: 10;
}
.header-actions {
  display: flex;
  gap: 16px;
  align-items: center;
}
.main-layout {
  flex: 1;
  display: flex;
  gap: 16px;
  padding: 16px;
  overflow: hidden;
}
.device-panel {
  width: 320px;
  background: white;
  border-radius: 16px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex-shrink: 0;
}
.panel-header {
  padding: 14px 16px;
  border-bottom: 1px solid #eaeef2;
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}
.filter-tabs {
  padding: 10px 12px;
  border-bottom: 1px solid #eceef5;
}
.device-list-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}
.device-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px;
  margin-bottom: 8px;
  background: #fafbfc;
  border-radius: 12px;
  transition: all 0.2s;
  cursor: pointer;
  border: 1px solid transparent;
}
.device-item.active {
  background: #ecf5ff;
  border-color: #409eff;
  box-shadow: 0 2px 6px rgba(64,158,255,0.2);
}
.device-status-dot .status-icon {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin-top: 6px;
}
.device-info {
  flex: 1;
  min-width: 0;
}
.device-name {
  font-weight: 600;
  margin-bottom: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.device-location {
  font-size: 12px;
  color: #606266;
  display: flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.device-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 6px;
  font-size: 11px;
  color: #909399;
}
.gis-container {
  flex: 1;
  background: #fff;
  border-radius: 20px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.06);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
}
.map-toolbar {
  padding: 10px 16px;
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid #efefef;
  background: white;
  z-index: 2;
}
.map-title {
  font-weight: 600;
  color: #303133;
  font-size: 14px;
}
.legend {
  display: flex;
  gap: 16px;
  font-size: 12px;
  align-items: center;
}
.legend-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 10px;
  margin-right: 4px;
}
.legend-dot.online { background-color: #67C23A; }
.legend-dot.offline { background-color: #909399; }
.legend-dot.selected { background-color: #409eff; box-shadow: 0 0 0 2px rgba(64,158,255,0.4); }
.map-area {
  flex: 1;
  position: relative;
  min-height: 0;
}
.bmap-container {
  width: 100%;
  height: 100%;
}
.detail-card {
  position: absolute;
  bottom: 20px;
  right: 20px;
  width: 280px;
  background: white;
  border-radius: 16px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);
  z-index: 20;
  backdrop-filter: blur(2px);
  border: 1px solid #e0e4e8;
  overflow: hidden;
}
.card-header {
  display: flex;
  justify-content: space-between;
  padding: 12px 16px;
  background: #f8fafc;
  border-bottom: 1px solid #e9edf2;
  font-weight: 600;
}
.close-icon {
  cursor: pointer;
}
.card-body {
  padding: 12px;
}
.slide-fade-enter-active {
  transition: all 0.3s ease-out;
}
.slide-fade-leave-active {
  transition: all 0.2s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter-from, .slide-fade-leave-to {
  transform: translateX(20px);
  opacity: 0;
}
.pagination-area {
  padding: 8px 0 4px;
  display: flex;
  justify-content: center;
}
</style>
