<!--故障管理-->
<template>
  <div class="device-maintenance">
    <!-- 页面头部 -->
    <div class="page-header">
      <div class="header-left">
        <el-icon><Monitor /></el-icon>
        <span class="title">智能终端设备运维中心</span>
        <el-tag type="danger" effect="dark">故障设备 {{ faultCount }}</el-tag>
      </div>
      <div class="header-right">
        <el-input
            v-model="searchKeyword"
            placeholder="搜索设备编号/名称/位置"
            clearable
            :prefix-icon="Search"
            style="width: 260px"
        />
        <el-select v-model="faultTypeFilter" placeholder="故障类型" clearable style="width: 140px">
          <el-option label="倾斜超标" value="tilt" />
          <el-option label="水位超限" value="water" />
          <el-option label="异常震动" value="vibration" />
          <el-option label="通讯故障" value="communication" />
          <el-option label="电池低电量" value="battery" />
        </el-select>
        <el-button type="primary" :icon="Refresh" @click="refreshData">刷新</el-button>
      </div>
    </div>

    <!-- 统计卡片 -->
    <div class="stats-cards">
      <div class="stat-card critical">
        <div class="stat-value">{{ criticalFaultCount }}</div>
        <div class="stat-label">严重故障</div>
      </div>
      <div class="stat-card warning">
        <div class="stat-value">{{ normalFaultCount }}</div>
        <div class="stat-label">一般故障</div>
      </div>
      <div class="stat-card">
        <div class="stat-value">{{ processingCount }}</div>
        <div class="stat-label">处置中</div>
      </div>
      <div class="stat-card">
        <div class="stat-value">{{ completedCount }}</div>
        <div class="stat-label">已完成</div>
      </div>
    </div>

    <!-- 主内容区：左侧地图 + 右侧列表 -->
    <div class="main-layout">
      <!-- 左侧GIS地图终端分布 -->
      <div class="map-panel">
        <div class="map-header">
          <span><el-icon><MapLocation /></el-icon> 终端分布地图</span>
          <div class="map-legend">
            <span><i class="legend-dot critical-dot"></i>严重故障</span>
            <span><i class="legend-dot warning-dot"></i>一般故障</span>
            <span><i class="legend-dot normal-dot"></i>正常</span>
            <span><i class="legend-dot processing-dot"></i>处置中</span>
          </div>
        </div>
        <div class="map-container" ref="mapContainer">
          <canvas id="deviceMapCanvas" ref="canvasRef" @click="onMapClick" @mousemove="onCanvasMouseMove"></canvas>
          <div v-if="hoverDevice" class="hover-card" :style="{ top: hoverY + 'px', left: hoverX + 'px' }">
            <div class="hover-title">{{ hoverDevice.name }}</div>
            <div>状态: {{ hoverDevice.statusText }}</div>
            <div>故障: {{ hoverDevice.faultTypeName }}</div>
            <div>位置: {{ hoverDevice.locationShort }}</div>
          </div>
        </div>
      </div>

      <!-- 右侧设备列表 -->
      <div class="device-list-panel">
        <div class="list-header">
          <span>故障设备列表</span>
          <el-radio-group v-model="listFilter" size="small">
            <el-radio-button label="all">全部故障</el-radio-button>
            <el-radio-button label="pending">待处置</el-radio-button>
            <el-radio-button label="processing">处置中</el-radio-button>
          </el-radio-group>
        </div>
        <div class="device-list">
          <div
              v-for="device in paginatedDevices"
              :key="device.id"
              class="device-item"
              :class="{
              selected: selectedDevice?.id === device.id,
              critical: device.faultLevel === 'critical',
              warning: device.faultLevel === 'normal'
            }"
              @click="selectDevice(device)"
          >
            <div class="device-header">
              <span class="device-code">{{ device.code }}</span>
              <el-tag :type="device.faultLevel === 'critical' ? 'danger' : 'warning'" size="small">
                {{ device.faultLevel === 'critical' ? '严重' : '一般' }}
              </el-tag>
            </div>
            <div class="device-location">
              <el-icon><Location /></el-icon> {{ device.locationShort }}
            </div>
            <div class="device-fault">{{ device.faultTypeName }}</div>
            <div class="device-status">
              <el-tag :type="getStatusTag(device.status)" size="small">{{ getStatusText(device.status) }}</el-tag>
            </div>
          </div>
        </div>
        <div class="pagination-area">
          <el-pagination
              small
              layout="prev, pager, next"
              :total="filteredDevices.length"
              :page-size="pageSize"
              v-model:current-page="currentPage"
          />
        </div>
      </div>
    </div>

    <!-- 设备详情与处置抽屉 -->
    <el-drawer v-model="detailDrawerVisible" :title="`设备运维 - ${selectedDevice?.code}`" size="500px" direction="rtl">
      <div v-if="selectedDevice" class="device-detail">
        <!-- 设备基本信息 -->
        <el-descriptions :column="1" border>
          <el-descriptions-item label="设备编号">{{ selectedDevice.code }}</el-descriptions-item>
          <el-descriptions-item label="设备名称">{{ selectedDevice.name }}</el-descriptions-item>
          <el-descriptions-item label="设备类型">{{ selectedDevice.deviceTypeName }}</el-descriptions-item>
          <el-descriptions-item label="设备型号">{{ selectedDevice.model }}</el-descriptions-item>
          <el-descriptions-item label="运维部门">{{ selectedDevice.maintenanceDept }}</el-descriptions-item>
          <el-descriptions-item label="详细地址">{{ selectedDevice.address }}</el-descriptions-item>
          <el-descriptions-item label="经纬度">{{ selectedDevice.lng }}, {{ selectedDevice.lat }}</el-descriptions-item>
          <el-descriptions-item label="故障类型">{{ selectedDevice.faultTypeName }}</el-descriptions-item>
          <el-descriptions-item label="故障描述">{{ selectedDevice.faultDesc }}</el-descriptions-item>
          <el-descriptions-item label="故障时间">{{ selectedDevice.faultTime }}</el-descriptions-item>
          <el-descriptions-item label="当前状态">
            <el-tag :type="getStatusTag(selectedDevice.status)">{{ getStatusText(selectedDevice.status) }}</el-tag>
          </el-descriptions-item>
        </el-descriptions>

        <!-- 处置操作区（仅待处置/处置中显示） -->
        <div class="operation-section" v-if="selectedDevice.status !== 'completed'">
          <div class="section-title">
            <span><el-icon><Tools /></el-icon> 现场处置操作</span>
            <span class="location-hint">
              <el-icon></el-icon>
              {{ getDistanceText(selectedDevice) }}
            </span>
          </div>

          <!-- 处置操作按钮组 -->
          <div class="operation-buttons">
            <el-button type="primary" @click="openOperationDialog('disassemble')" :disabled="selectedDevice.status === 'processing'">拆卸</el-button>
            <el-button type="warning" @click="openOperationDialog('return')" :disabled="selectedDevice.status === 'processing'">返厂</el-button>
            <el-button type="danger" @click="openOperationDialog('scrap')" :disabled="selectedDevice.status === 'processing'">报废</el-button>
          </div>

          <!-- 处置反馈区 -->
          <div class="feedback-section" v-if="selectedDevice.status === 'processing'">
            <div class="section-title"><el-icon><Picture /></el-icon> 处置反馈（APP拍照上传）</div>
            <div class="feedback-images" v-if="selectedDevice.feedbackImages?.length">
              <el-image
                  v-for="(img, idx) in selectedDevice.feedbackImages"
                  :key="idx"
                  :src="img"
                  fit="cover"
                  class="feedback-img"
                  :preview-src-list="selectedDevice.feedbackImages"
                  preview-teleported
              />
            </div>
            <el-input
                type="textarea"
                v-model="feedbackRemark"
                placeholder="请输入处置说明..."
                rows="2"
                style="margin: 12px 0"
            />
            <div class="upload-area" @click="simulatePhotoUpload">
              <el-icon><Camera /></el-icon>
              <span>点击拍照上传（模拟APP拍照）</span>
            </div>
            <el-button type="primary" style="margin-top: 12px" @click="submitFeedback">提交处置反馈</el-button>
          </div>
        </div>

        <!-- 完成状态展示 -->
        <div class="completed-section" v-else>
          <el-alert title="设备已处置完成" type="success" :closable="false" show-icon>
            <template #default>
              <div>处置方式: {{ selectedDevice.completedOperation }}</div>
              <div>完成时间: {{ selectedDevice.completeTime }}</div>
              <div>反馈说明: {{ selectedDevice.feedbackRemark }}</div>
            </template>
          </el-alert>
          <div class="completed-images" v-if="selectedDevice.feedbackImages?.length">
            <div class="sub-title">现场照片</div>
            <div class="feedback-images">
              <el-image v-for="(img, idx) in selectedDevice.feedbackImages" :key="idx" :src="img" fit="cover" class="feedback-img" />
            </div>
          </div>
        </div>

        <!-- 历史处置记录 -->
        <div class="history-section">
          <div class="section-title"><el-icon><Document /></el-icon> 历史处置记录</div>
          <el-timeline>
            <el-timeline-item
                v-for="record in selectedDevice.historyRecords"
                :key="record.id"
                :timestamp="record.time"
                :type="record.type"
            >
              {{ record.content }}
            </el-timeline-item>
            <el-timeline-item v-if="!selectedDevice.historyRecords?.length" timestamp="暂无记录" type="info">
              该设备尚无处置记录
            </el-timeline-item>
          </el-timeline>
        </div>
      </div>
    </el-drawer>

    <!-- 处置操作确认对话框 -->
    <el-dialog v-model="operationDialogVisible" :title="operationTitle" width="420px">
      <el-form>
        <el-form-item label="操作说明">
          <el-input type="textarea" v-model="operationRemark" :placeholder="operationPlaceholder" rows="3" />
        </el-form-item>
        <el-form-item label="定位信息确认">
          <div class="location-confirm">
            <el-icon><Location /></el-icon>
            {{ selectedDevice?.address }}
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="operationDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmOperation">确认执行</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { Monitor, Search, Refresh, MapLocation, Location, Tools, Picture, Camera, Document } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

// 模拟设备数据（含故障信息）
const mockDevices = ref([
  {
    id: 1, code: 'DEV-1001', name: '人民路智能井盖', deviceType: 'smart', deviceTypeName: '智能井盖',
    model: 'WATCHMAN-S2', maintenanceDept: '市政维修一队', faultLevel: 'critical',
    faultType: 'tilt', faultTypeName: '倾斜超标', faultDesc: '倾斜角度14.2°，超过阈值8°，有跌落风险',
    faultTime: '2025-04-02 14:23:15', status: 'pending', statusText: '待处置',
    lng: 121.487, lat: 31.249, address: '人民路与解放路口东50m', locationShort: '人民路口',
    historyRecords: [],
    feedbackImages: [], feedbackRemark: '', completedOperation: null, completeTime: null
  },
  {
    id: 2, code: 'DEV-1002', name: '滨江路防爆井盖', deviceType: 'explosion', deviceTypeName: '防爆井盖',
    model: 'WATCHMAN-EX', maintenanceDept: '水务抢修队', faultLevel: 'critical',
    faultType: 'water', faultTypeName: '水位超限', faultDesc: '水位62cm，超过阈值40cm，溢水风险',
    faultTime: '2025-04-02 13:55:02', status: 'pending', statusText: '待处置',
    lng: 121.502, lat: 31.235, address: '滨江路化工园区南门', locationShort: '滨江园区',
    historyRecords: [],
    feedbackImages: [], feedbackRemark: '', completedOperation: null, completeTime: null
  },
  {
    id: 3, code: 'DEV-1003', name: '古城街井盖', deviceType: 'smart', deviceTypeName: '智能井盖',
    model: 'WATCHMAN-S1', maintenanceDept: '市政维修二队', faultLevel: 'normal',
    faultType: 'vibration', faultTypeName: '异常震动', faultDesc: '异常震动112mg，超过阈值80mg',
    faultTime: '2025-04-02 12:10:33', status: 'processing', statusText: '处置中',
    lng: 121.478, lat: 31.258, address: '古城街北段树下', locationShort: '古城街',
    historyRecords: [
      { id: 1, time: '2025-04-02 13:00:00', type: 'primary', content: '维修人员已出发前往现场' }
    ],
    feedbackImages: [], feedbackRemark: '', completedOperation: null, completeTime: null
  },
  {
    id: 4, code: 'DEV-1004', name: '南港路井盖', deviceType: 'smart', deviceTypeName: '智能井盖',
    model: 'WATCHMAN-S2', maintenanceDept: '市政维修一队', faultLevel: 'normal',
    faultType: 'communication', faultTypeName: '通讯故障', faultDesc: '设备离线，最后通讯时间超过2小时',
    faultTime: '2025-04-02 11:45:20', status: 'pending', statusText: '待处置',
    lng: 121.495, lat: 31.228, address: '南港路旧车站段', locationShort: '南港路',
    historyRecords: [],
    feedbackImages: [], feedbackRemark: '', completedOperation: null, completeTime: null
  },
  {
    id: 5, code: 'DEV-1005', name: '石化区防爆井盖', deviceType: 'explosion', deviceTypeName: '防爆井盖',
    model: 'WATCHMAN-EX', maintenanceDept: '应急抢修队', faultLevel: 'critical',
    faultType: 'battery', faultTypeName: '电池低电量', faultDesc: '电池电量仅剩12%，需及时更换',
    faultTime: '2025-04-02 10:30:45', status: 'completed', statusText: '已完成',
    lng: 121.524, lat: 31.239, address: '石化大道南侧', locationShort: '石化大道',
    historyRecords: [
      { id: 1, time: '2025-04-02 11:00:00', type: 'primary', content: '维修人员到达现场' },
      { id: 2, time: '2025-04-02 11:30:00', type: 'success', content: '已完成电池更换，设备恢复正常' }
    ],
    feedbackImages: ['https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg'],
    feedbackRemark: '已更换新电池，设备测试正常', completedOperation: '电池更换', completeTime: '2025-04-02 11:30:00'
  },
  {
    id: 6, code: 'DEV-1006', name: '高新区智能井盖', deviceType: 'smart', deviceTypeName: '智能井盖',
    model: 'WATCHMAN-S2', maintenanceDept: '市政维修二队', faultLevel: 'normal',
    faultType: 'tilt', faultTypeName: '倾斜超标', faultDesc: '倾斜角度5.6°，超过阈值5°',
    faultTime: '2025-04-02 09:20:00', status: 'pending', statusText: '待处置',
    lng: 121.512, lat: 31.242, address: '高新大道云计算中心旁', locationShort: '高新区',
    historyRecords: [],
    feedbackImages: [], feedbackRemark: '', completedOperation: null, completeTime: null
  }
])

// 筛选条件
const searchKeyword = ref('')
const faultTypeFilter = ref('')
const listFilter = ref('all')
const currentPage = ref(1)
const pageSize = 6

// 选择与详情
const selectedDevice = ref(null)
const detailDrawerVisible = ref(false)

// 处置相关
const operationDialogVisible = ref(false)
const operationType = ref('')
const operationRemark = ref('')
const feedbackRemark = ref('')

// GIS地图相关
const canvasRef = ref(null)
const mapContainer = ref(null)
let ctx = null
let mapWidth = 0, mapHeight = 0
let mapZoom = 1
let offsetX = 0, offsetY = 0
const bounds = { minLng: 121.45, maxLng: 121.55, minLat: 31.22, maxLat: 31.28 }

// 悬浮信息
const hoverDevice = ref(null)
const hoverX = ref(0), hoverY = ref(0)

// 计算属性
const faultDevices = computed(() => mockDevices.value.filter(d => d.status !== 'completed' || listFilter.value === 'all'))
const filteredDevices = computed(() => {
  let list = mockDevices.value
  if (listFilter.value === 'pending') list = list.filter(d => d.status === 'pending')
  else if (listFilter.value === 'processing') list = list.filter(d => d.status === 'processing')

  if (searchKeyword.value) {
    const kw = searchKeyword.value.toLowerCase()
    list = list.filter(d =>
        d.code.toLowerCase().includes(kw) ||
        d.name.toLowerCase().includes(kw) ||
        d.address.toLowerCase().includes(kw)
    )
  }
  if (faultTypeFilter.value) {
    list = list.filter(d => d.faultType === faultTypeFilter.value)
  }
  return list
})

const paginatedDevices = computed(() => {
  const start = (currentPage.value - 1) * pageSize
  return filteredDevices.value.slice(start, start + pageSize)
})

const faultCount = computed(() => mockDevices.value.filter(d => d.status !== 'completed').length)
const criticalFaultCount = computed(() => mockDevices.value.filter(d => d.faultLevel === 'critical' && d.status !== 'completed').length)
const normalFaultCount = computed(() => mockDevices.value.filter(d => d.faultLevel === 'normal' && d.status !== 'completed').length)
const processingCount = computed(() => mockDevices.value.filter(d => d.status === 'processing').length)
const completedCount = computed(() => mockDevices.value.filter(d => d.status === 'completed').length)

const operationTitle = computed(() => {
  const map = { disassemble: '拆卸设备', return: '返厂维修', scrap: '报废处理' }
  return map[operationType.value] || '操作确认'
})
const operationPlaceholder = computed(() => {
  const map = { disassemble: '请填写拆卸原因及后续安排', return: '请填写返厂原因及运输信息', scrap: '请填写报废原因及设备编号' }
  return map[operationType.value] || '请填写操作说明'
})

// 方法
const getStatusTag = (status) => {
  const map = { pending: 'danger', processing: 'warning', completed: 'success' }
  return map[status] || 'info'
}
const getStatusText = (status) => {
  const map = { pending: '待处置', processing: '处置中', completed: '已完成' }
  return map[status] || status
}
const getDistanceText = (device) => {
  // 模拟距离计算
  return `距离当前位置约 ${Math.floor(Math.random() * 5) + 1}km`
}

const refreshData = () => { ElMessage.success('数据已刷新') }

const selectDevice = (device) => {
  selectedDevice.value = device
  detailDrawerVisible.value = true
  feedbackRemark.value = ''
}

// GIS地图绘制
function worldToCanvas(lng, lat) {
  const px = (lng - bounds.minLng) / (bounds.maxLng - bounds.minLng) * mapWidth
  const py = (1 - (lat - bounds.minLat) / (bounds.maxLat - bounds.minLat)) * mapHeight
  const cx = mapWidth / 2, cy = mapHeight / 2
  return { x: (px - cx) * mapZoom + cx + offsetX, y: (py - cy) * mapZoom + cy + offsetY }
}

function drawBaseMap() {
  if (!ctx) return
  ctx.fillStyle = '#eaf2e6'
  ctx.fillRect(0, 0, mapWidth, mapHeight)
  ctx.strokeStyle = '#c8ddc4'
  ctx.lineWidth = 1
  for (let i = 0; i < 10; i++) {
    ctx.beginPath()
    ctx.moveTo((i / 10) * mapWidth, 0)
    ctx.lineTo((i / 10) * mapWidth, mapHeight)
    ctx.stroke()
    ctx.beginPath()
    ctx.moveTo(0, (i / 10) * mapHeight)
    ctx.lineTo(mapWidth, (i / 10) * mapHeight)
    ctx.stroke()
  }
}

function drawDevices() {
  if (!ctx) return
  mockDevices.value.forEach(device => {
    const { x, y } = worldToCanvas(device.lng, device.lat)
    if (x < -30 || x > mapWidth + 30 || y < -30 || y > mapHeight + 30) return

    let color = '#67C23A'
    let size = 12
    if (device.status === 'pending') {
      color = device.faultLevel === 'critical' ? '#F56C6C' : '#E6A23C'
      size = 14
    } else if (device.status === 'processing') {
      color = '#409EFF'
      size = 14
    } else if (device.status === 'completed') {
      color = '#67C23A'
    }

    ctx.beginPath()
    ctx.arc(x, y, size, 0, 2 * Math.PI)
    ctx.fillStyle = color
    ctx.fill()
    ctx.strokeStyle = '#fff'
    ctx.lineWidth = 2
    ctx.stroke()

    if (device.status === 'pending' && device.faultLevel === 'critical') {
      ctx.beginPath()
      ctx.arc(x, y, size + 4, 0, 2 * Math.PI)
      ctx.fillStyle = 'rgba(245,108,108,0.3)'
      ctx.fill()
    }
  })
}

function renderMap() {
  if (!canvasRef.value || !mapContainer.value) return
  const canvas = canvasRef.value
  mapWidth = mapContainer.value.clientWidth
  mapHeight = mapContainer.value.clientHeight
  canvas.width = mapWidth
  canvas.height = mapHeight
  ctx = canvas.getContext('2d')
  drawBaseMap()
  drawDevices()
}

function onMapClick(e) {
  const rect = canvasRef.value.getBoundingClientRect()
  const mouseX = (e.clientX - rect.left) * (mapWidth / rect.width)
  const mouseY = (e.clientY - rect.top) * (mapHeight / rect.height)
  let minDist = 20, hit = null
  mockDevices.value.forEach(device => {
    const { x, y } = worldToCanvas(device.lng, device.lat)
    const dist = Math.hypot(mouseX - x, mouseY - y)
    if (dist < minDist) { minDist = dist; hit = device }
  })
  if (hit) {
    selectedDevice.value = hit
    detailDrawerVisible.value = true
  }
}

function onCanvasMouseMove(e) {
  const rect = canvasRef.value.getBoundingClientRect()
  const mouseX = (e.clientX - rect.left) * (mapWidth / rect.width)
  const mouseY = (e.clientY - rect.top) * (mapHeight / rect.height)
  let minDist = 18, hit = null
  mockDevices.value.forEach(device => {
    const { x, y } = worldToCanvas(device.lng, device.lat)
    const dist = Math.hypot(mouseX - x, mouseY - y)
    if (dist < minDist) { minDist = dist; hit = device }
  })
  if (hit) {
    hoverDevice.value = hit
    hoverX.value = e.clientX + 12
    hoverY.value = e.clientY - 40
  } else {
    hoverDevice.value = null
  }
}

// 处置操作
const openOperationDialog = (type) => {
  if (selectedDevice.value.status !== 'pending') {
    ElMessage.warning('该设备已在处置中或已完成，无法重复操作')
    return
  }
  operationType.value = type
  operationRemark.value = ''
  operationDialogVisible.value = true
}

const confirmOperation = () => {
  if (!operationRemark.value) {
    ElMessage.warning('请填写操作说明')
    return
  }
  const device = selectedDevice.value
  device.status = 'processing'
  device.statusText = '处置中'
  const operationName = { disassemble: '拆卸', return: '返厂', scrap: '报废' }[operationType.value]
  device.historyRecords.unshift({
    id: Date.now(),
    time: new Date().toLocaleString(),
    type: 'primary',
    content: `${operationName}操作已启动，${operationRemark.value}`
  })
  ElMessage.success(`${operationName}操作已记录，请现场处置后提交反馈`)
  operationDialogVisible.value = false
}

// APP拍照反馈
const simulatePhotoUpload = () => {
  // 模拟拍照上传
  const mockImage = 'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg'
  if (!selectedDevice.value.feedbackImages) selectedDevice.value.feedbackImages = []
  selectedDevice.value.feedbackImages.push(mockImage)
  ElMessage.success('已添加现场照片（模拟APP拍照）')
}

const submitFeedback = () => {
  if (!feedbackRemark.value && (!selectedDevice.value.feedbackImages?.length)) {
    ElMessage.warning('请填写处置说明或上传照片')
    return
  }
  const device = selectedDevice.value
  device.status = 'completed'
  device.statusText = '已完成'
  device.completeTime = new Date().toLocaleString()
  device.feedbackRemark = feedbackRemark.value
  device.completedOperation = device.historyRecords[0]?.content.split('操作')[0] + '操作'
  device.historyRecords.unshift({
    id: Date.now(),
    time: new Date().toLocaleString(),
    type: 'success',
    content: `处置完成，反馈说明：${feedbackRemark.value || '无'}`
  })
  ElMessage.success('处置反馈已提交，工单完成')
  detailDrawerVisible.value = false
  renderMap()
}

onMounted(() => {
  nextTick(() => {
    renderMap()
    window.addEventListener('resize', renderMap)
  })
})
onUnmounted(() => window.removeEventListener('resize', renderMap))
</script>

<style scoped>
.device-maintenance {
  background: #f0f2f6;
  min-height: 100vh;
  padding: 20px;
}

.page-header {
  background: white;
  border-radius: 16px;
  padding: 16px 24px;
  margin-bottom: 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}

.header-left { display: flex; align-items: center; gap: 12px; }
.header-left .title { font-size: 20px; font-weight: 600; }
.header-right { display: flex; gap: 12px; flex-wrap: wrap; }

.stats-cards {
  display: flex;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.stat-card {
  background: white;
  border-radius: 12px;
  padding: 12px 24px;
  text-align: center;
  min-width: 110px;
}
.stat-card.critical .stat-value { color: #f56c6c; }
.stat-card.warning .stat-value { color: #e6a23c; }
.stat-value { font-size: 28px; font-weight: bold; }
.stat-label { font-size: 13px; color: #606266; margin-top: 4px; }

.main-layout {
  display: flex;
  gap: 20px;
}

.map-panel {
  flex: 2;
  background: white;
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.map-header {
  padding: 16px;
  border-bottom: 1px solid #e9ecef;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
}

.map-legend { display: flex; gap: 16px; font-size: 12px; }
.legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 10px; margin-right: 4px; }
.critical-dot { background: #f56c6c; }
.warning-dot { background: #e6a23c; }
.normal-dot { background: #67c23a; }
.processing-dot { background: #409eff; }

.map-container {
  flex: 1;
  position: relative;
  min-height: 500px;
}
canvas { width: 100%; height: 100%; display: block; cursor: crosshair; }

.hover-card {
  position: fixed;
  background: rgba(0,0,0,0.8);
  color: white;
  padding: 8px 12px;
  border-radius: 12px;
  font-size: 12px;
  pointer-events: none;
  z-index: 200;
}

.device-list-panel {
  width: 380px;
  background: white;
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.list-header {
  padding: 16px;
  border-bottom: 1px solid #e9ecef;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
}

.device-list {
  flex: 1;
  overflow-y: auto;
  padding: 12px;
  max-height: calc(100vh - 300px);
}

.device-item {
  padding: 12px;
  margin-bottom: 10px;
  border-radius: 12px;
  background: #fafbfc;
  border: 1px solid #e9ecef;
  cursor: pointer;
  transition: all 0.2s;
}

.device-item.selected { background: #ecf5ff; border-color: #409eff; }
.device-item.critical { border-left: 3px solid #f56c6c; }
.device-item.warning { border-left: 3px solid #e6a23c; }

.device-header { display: flex; justify-content: space-between; margin-bottom: 6px; }
.device-code { font-weight: 600; }
.device-location { font-size: 12px; color: #6c757d; display: flex; align-items: center; gap: 4px; margin-bottom: 4px; }
.device-fault { font-size: 12px; color: #f56c6c; margin-bottom: 4px; }

.device-detail { padding: 8px; }
.section-title {
  font-weight: 600;
  font-size: 15px;
  margin: 20px 0 12px 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.operation-buttons { display: flex; gap: 12px; margin: 16px 0; }
.upload-area {
  border: 1px dashed #ddd;
  border-radius: 8px;
  padding: 12px;
  text-align: center;
  cursor: pointer;
  background: #fafbfc;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.feedback-images { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.feedback-img { width: 80px; height: 70px; border-radius: 8px; object-fit: cover; }
.location-confirm { background: #f5f7fa; padding: 8px; border-radius: 8px; display: flex; align-items: center; gap: 8px; }

.pagination-area { padding: 12px; text-align: center; border-top: 1px solid #eee; }
</style>