<template>
  <a-spin :spinning="spinning">
    <div class="deviceDetail">
      <info-card
        title="实时点位"
        :class="[
          furnitureItems && furnitureItems.some((item) => item.type === 'bed') ? 'pointCard' : '',
        ]"
      >
        <template #extra>
          <a-space>
            <a-button type="primary" size="small" @click="roomConfigHandler('area')">
              区域配置
            </a-button>
            <div class="extraIcon"> <FullscreenOutlined @click="openFullView = true" /> </div>
          </a-space>
        </template>
        <a-alert
          v-if="areaAvailable"
          message="检测区域范围未配置或数值较小，请在设备配置调整参数！"
          banner
          style="margin-bottom: 10px"
        />
        <div class="pointMap">
          <div
            class="radarArea"
            :style="{
              width: `${detailState?.length || 400}px`,
              height: `${detailState?.width || 400}px`,
            }"
          >
            <furniture-icon
              v-for="(item, index) in furnitureItems"
              :key="index"
              :icon="item.type"
              :width="item.width"
              :height="item.length"
              :style="{
                left: `${item.left}px`,
                top: `${item.top}px`,
                position: 'absolute',
                rotate: `${item.rotate}deg`,
                cursor: 'default',
                pointerEvents: 'none',
              }"
              :draggable="false"
            />
          </div>

          <template v-if="targets && Object.keys(targets).length > 0">
            <template v-for="t in targets" :key="t.id">
              <div
                class="target-dot"
                :style="{
                  position: 'absolute',
                  width: '18px',
                  height: '18px',
                  background: t.id === 0 ? 'red' : t.id === 1 ? 'blue' : 'green',
                  borderRadius: '50%',
                  transform: `translate3d(${t.displayX + 200}px, ${-t.displayY + 200}px, 0) translate(-50%, -50%)`,
                  zIndex: 10,
                  transition: 'transform 1s linear',
                  willChange: 'transform',
                }"
              >
                <span
                  style="
                    color: #fff;
                    font-size: 12px;
                    font-weight: 600;
                    position: absolute;
                    left: 50%;
                    top: 50%;
                    transform: translate(-50%, -50%);
                    pointer-events: none;
                  "
                >
                  {{ t.id + 1 }}
                </span>
              </div>
            </template>
          </template>

          <div
            v-if="furnitureItems && furnitureItems.some((item) => item.type === 'bed')"
            class="breathLine"
          >
            <BreathLineChart :data="breathRpmList"></BreathLineChart>
          </div>
        </div>
      </info-card>

      <FullViewModal v-model:open="openFullView" :title="detailState.devName">
        <div class="fullView">
          <div class="pointTitle">实时点位图</div>
          <div class="pointMap">
            <div
              class="radarArea"
              :style="{
                width: `${detailState?.length || 400}px`,
                height: `${detailState?.width || 400}px`,
              }"
            >
              <furniture-icon
                v-for="(item, index) in furnitureItems"
                :key="index"
                :icon="item.type"
                :width="item.width"
                :height="item.length"
                :style="{
                  left: `${item.left}px`,
                  top: `${item.top}px`,
                  position: 'absolute',
                  rotate: `${item.rotate}deg`,
                  cursor: 'default',
                  pointerEvents: 'none',
                }"
                :draggable="false"
              />
            </div>

            <template v-if="targets && Object.keys(targets).length > 0">
              <template v-for="t in targets" :key="t.id">
                <div
                  class="target-dot"
                  :style="{
                    position: 'absolute',
                    width: '18px',
                    height: '18px',
                    background: t.id === 0 ? 'red' : t.id === 1 ? 'blue' : 'green',
                    borderRadius: '50%',
                    transform: `translate3d(${t.displayX + 200}px, ${-t.displayY + 200}px, 0) translate(-50%, -50%)`,
                    zIndex: 10,
                    transition: 'transform 1s linear',
                    willChange: 'transform',
                  }"
                >
                  <span
                    style="
                      color: #fff;
                      font-size: 12px;
                      font-weight: 600;
                      position: absolute;
                      left: 50%;
                      top: 50%;
                      transform: translate(-50%, -50%);
                      pointer-events: none;
                    "
                  >
                    {{ t.id + 1 }}
                  </span>
                </div>
              </template>
            </template>
          </div>

          <div
            v-if="furnitureItems && furnitureItems.some((item) => item.type === 'bed')"
            class="breathLine"
          >
            <BreathLineChart :data="breathRpmList"></BreathLineChart>
          </div>
        </div>
      </FullViewModal>

      <info-card>
        <info-item-group title="基本信息">
          <template #extra>
            <a-button type="primary" size="small" @click="roomConfigHandler('base')">
              设备配置
            </a-button>
          </template>
          <info-item label="设备ID">{{ detailState.clientId }}</info-item>
          <info-item label="设备名称">{{ detailState.devName }}</info-item>
          <info-item label="设备类型">{{ detailState.devType }}</info-item>
          <info-item label="固件版本号">{{ detailState.software }}</info-item>
          <info-item label="激活日期">{{ detailState.activeTime }}</info-item>
          <info-item label="在离线状态">
            <template v-if="detailState.clientId">
              <a-tag
                v-if="detailState.online === 0"
                :bordered="false"
                :color="deviceOnlineStateMap[detailState.online].color"
                >{{ deviceOnlineStateMap[detailState.online].name }}</a-tag
              >
              <a-tag
                v-if="detailState.online === 1"
                :bordered="false"
                :color="deviceOnlineStateMap[detailState.online].color"
                >{{ deviceOnlineStateMap[detailState.online].name }}</a-tag
              >
            </template>
          </info-item>
          <info-item label="归属租户">{{ detailState.tenantName }}</info-item>
          <info-item label="统计信息">
            <a-button
              v-if="detailState.clientId"
              type="link"
              size="small"
              @click="viewDeviceHistoryInfo"
            >
              查看详情
            </a-button>
          </info-item>
        </info-item-group>

        <info-item-group title="安装参数">
          <info-item label="安装高度">
            <template v-if="detailState.height"> {{ detailState.height }} cm</template>
          </info-item>
          <info-item label="检测区域">
            <template v-if="detailState.length || detailState.width">
              {{ detailState.length || 0 }} x {{ detailState.width || 0 }} cm
              {{ [detailState.xxStart, detailState.xxEnd, detailState.yyStart, detailState.yyEnd] }}
            </template>
          </info-item>
          <info-item label="安装位置">
            <template v-if="detailState.clientId">
              {{
                deviceInstallPositionNameMap[
                  detailState.installPosition as keyof typeof deviceInstallPositionNameMap
                ]
              }}
            </template>
          </info-item>
        </info-item-group>
      </info-card>

      <info-card>
        <info-item-group title="告警计划" class="alarmPlanGroup">
          <template #extra>
            <a-space>
              <a-button type="primary" size="small" @click="addPlanHandler"> 新增计划 </a-button>
            </a-space>
          </template>

          <ScrollContainer style="max-height: 450px">
            <a-spin :spinning="alarmPlanLoading">
              <div v-if="alarmPlans && alarmPlans.length" class="alarmPlan">
                <div class="alarmPlan-item" v-for="plan in alarmPlans" :key="plan.id">
                  <div class="alarmPlan-item-label"
                    ><a-badge :status="plan.enable ? 'success' : 'error'"
                  /></div>
                  <div class="alarmPlan-item-contant" :title="plan.name">{{ plan.name }}</div>
                  <div class="alarmPlan-item-action">
                    <a-space>
                      <a-popconfirm
                        :title="`确认${plan.enable ? '禁用' : '启用'}计划吗？`"
                        ok-text="确认"
                        cancel-text="取消"
                        @confirm="swtichAlarmItem(plan.id, plan.enable, plan)"
                      >
                        <a-switch :checked="plan.enable" size="small" :loading="plan.loading" />
                      </a-popconfirm>

                      <EditOutlined @click="editAlarmItem(plan.data as AlarmPlanItem)" />
                      <a-popconfirm
                        title="确认删除计划吗？"
                        ok-text="确认"
                        cancel-text="取消"
                        @confirm="deleteAlarmItem(plan.id)"
                      >
                        <DeleteOutlined />
                      </a-popconfirm>
                    </a-space>
                  </div>
                </div>
              </div>
              <div v-else class="alarmPlan-empty">
                <a-empty :image="simpleImage" />
              </div>
            </a-spin>
          </ScrollContainer>
        </info-item-group>
      </info-card>

      <deviceConfigDrawer
        v-model:open="configDrawerOpen"
        :data="{
          devId: (detailState.devId as string) || '',
          clientId: (detailState.clientId as string) || '',
          length: (detailState.length as number) || 0,
          width: (detailState.width as number) || 0,
          xStart: (detailState.xxStart as number) || 0,
          xEnd: (detailState.xxEnd as number) || 0,
          yStart: (detailState.yyStart as number) || 0,
          yEnd: (detailState.yyEnd as number) || 0,
        }"
        :mode="configDrawerMode"
        :room-id="deviceRoomId"
        :furniture-items="furnitureItems"
        :sub-region-items="subRegionItems"
        @success="saveConfigSuccess"
      ></deviceConfigDrawer>

      <deviceStatsDrawer
        v-model:open="statsDrawerOpen"
        :dev-id="`${detailState.devId as string}`"
        :title="`${detailState.devName || ''} 统计信息`"
      ></deviceStatsDrawer>

      <alarmPlanModal
        v-model:open="alarmPlanVisible"
        :title="alarmPlanTitle"
        type="plan"
        :client-id="clientId"
        :alarm-plan-id="alarmPlanId"
        :data="alarmPlanDataWithType"
        :area="{
          width: (detailState.width as number) ?? 0,
          height: (detailState.length as number) ?? 0,
          ranges: [
            (detailState.xxStart as number) ?? 0,
            (detailState.xxEnd as number) ?? 0,
            (detailState.yyStart as number) ?? 0,
            (detailState.yyEnd as number) ?? 0,
          ],
        }"
        @success="fetchAlarmPlanList"
      ></alarmPlanModal>
    </div>
  </a-spin>
</template>

<script setup lang="ts">
import infoCard from './components/infoCard/index.vue'
import infoItem from './components/infoItem/index.vue'
import infoItemGroup from './components/infoItemGroup/index.vue'
import { ref, reactive, onMounted, onUnmounted, computed } from 'vue'
import { useRoute } from 'vue-router'
import { message } from 'ant-design-vue'
import * as roomApi from '@/api/room'
import type { Furniture } from '@/api/room/types'
import mqtt, { MqttClient } from 'mqtt'
import * as deviceApi from '@/api/device'
import type { DeviceDetailData } from '@/api/device/types'
import { deviceOnlineStateMap, deviceInstallPositionNameMap } from '@/const/device'
import deviceConfigDrawer from './components/deviceConfig/index.vue'
import deviceStatsDrawer from './components/deviceStatsDrawer/index.vue'
import BreathLineChart from './components/breathLineChart/index.vue'
import { formatDateTime } from '@/utils'
import { FullscreenOutlined } from '@ant-design/icons-vue'
import FullViewModal from './components/fullViewModal/index.vue'
import alarmPlanModal from './components/alarmPlanModal/index.vue'
import { EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import * as alarmApi from '@/api/alarm'
import { Empty } from 'ant-design-vue'
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE
import { getOriginPosition } from '@/utils'

defineOptions({
  name: 'DeviceDetail',
})

const route = useRoute()
// const router = useRouter()
const devId = ref<string>((route.query.devId as string) || '') // 设备id
const clientId = ref<string>((route.query.clientId as string) || '') // 设备id

interface BlockItem {
  startXx: number // 屏蔽子区域X开始
  stopXx: number // 屏蔽子区域X结束
  startYy: number // 屏蔽子区域Y开始
  stopYy: number // 屏蔽子区域Y结束
  startZz: number // 屏蔽子区域Z开始
  stopZz: number // 屏蔽子区域Z结束
  isLowSnr: number // 默认0
  isDoor: number // 是否是门 0-否,1-是 默认0
  presenceEnterDuration: number // 	人员进入时间 默认3
  presenceExitDuration: number // 人员离开时间 默认3
  trackPresence: number // 是否开启区域跟踪存在 0-否,1-是
  excludeFalling: number // 是否屏蔽区域跌倒检测 0-否,1-是
}

const deviceRoomId = ref<string>('')
const furnitureItems = ref<Furniture[]>([])
const subRegionItems = ref<BlockItem[]>([])
/**
 * 获取房间布局
 */
const fetchRoomLayout = async () => {
  console.log('fetchRoomLayout', devId.value)
  if (!devId.value) {
    message.error('设备ID不能为空')
    return
  }
  try {
    const res = await roomApi.queryRoomInfo({
      devId: devId.value,
    })
    console.log('✅获取到房间布局信息', res)
    if (!res) return
    const { furnitures, roomId, subRegions } = res.data
    if (furnitures) {
      // 添加接口返回的家具数据
      furnitures!.forEach((item) => {
        furnitureItems.value.push({
          ...item,
          width: item.width || 45,
          length: item.length || 45,
          top: item.top || 0,
          left: item.left || 0,
          rotate: item.rotate || 0,
          x: item.x || 0,
          y: item.y || 0,
        })
      })
    }
    deviceRoomId.value = roomId || ''
    subRegionItems.value = subRegions || []
  } catch (error) {
    console.error('❌获取房间布局信息失败', error)
  }
}
fetchRoomLayout()

const detailState = ref<DeviceDetailData>({
  devId: '',
  clientId: '',
  userId: '',
  devName: '',
  devType: '',
  online: 0,
  devWarn: 0,
  software: '',
  hardware: '',
  wifiName: '',
  wifiPassword: '',
  ip: '',
  mountPlain: 'Wall',
  installPosition: 'Toilet',
  xxStart: 0,
  xxEnd: 0,
  yyStart: 0,
  yyEnd: 0,
  zzStart: 0,
  zzEnd: 0,
  height: 0,
  length: 0,
  width: 0,
  targetPoints: [],
  signalTime: 0,
  northAngle: 0,
  activeTime: '',
  statusLight: 0,
  createId: '',
  updateId: '',
  createTime: '',
  updateTime: '',
  tenantName: '',
  tenantId: '',
  fallingConfirm: null,
})

const spinning = ref(false)
// 获取设备详情
const fetchDeviceDetail = async () => {
  console.log('fetchDeviceDetail', devId.value)
  if (!devId.value) {
    message.error('设备ID不能为空')
    return
  }
  try {
    spinning.value = true
    const res = await deviceApi.getDeviceDetailByDevId({
      devId: devId.value,
    })
    console.log('✅获取到设备详情', res)
    detailState.value = res.data
    spinning.value = false

    // 获取雷达图标尺寸
    const { radarX, radarY, radarWidth, radarHeight, originOffsetX, originOffsetY } =
      getOriginPosition(
        [
          res.data.xxStart as number,
          res.data.xxEnd as number,
          res.data.yyStart as number,
          res.data.yyEnd as number,
        ],
        [0, 0]
      )

    // 添加雷达图标
    furnitureItems.value.unshift({
      name: '雷达',
      type: 'radar',
      width: radarWidth,
      length: radarHeight,
      top: radarY,
      left: radarX,
      x: originOffsetX,
      y: originOffsetY,
      rotate: 0,
    })
  } catch (error) {
    console.error('❌获取设备详情失败', error)
    spinning.value = false
  }
}
fetchDeviceDetail()

const saveConfigSuccess = () => {
  setTimeout(() => {
    fetchDeviceDetail()
    fetchRoomLayout()
  }, 1000)
}

const configDrawerOpen = ref(false)
const configDrawerMode = ref<'base' | 'area'>('base')
const roomConfigHandler = (type: 'base' | 'area') => {
  configDrawerMode.value = type
  configDrawerOpen.value = true
}

const statsDrawerOpen = ref(false)
// 查看设备历史信息
const viewDeviceHistoryInfo = () => {
  console.log('viewDeviceHistoryInfo')
  statsDrawerOpen.value = true
}

interface TargetInfo {
  x: number
  y: number
  z: number
  id: number
  displayX: number
  displayY: number
  lastX: number
  lastY: number
}

const targets = reactive<Record<number, TargetInfo>>({}) // 以id为key
const THRESHOLD = 2 // 去抖阈值

let mqttClient: MqttClient | null = null
let mqttTimeout: number | null = null
const MQTT_TIMEOUT_MS = 1000 // 调整为1秒

const resetMqttTimeout = () => {
  if (mqttTimeout) clearTimeout(mqttTimeout)
  mqttTimeout = window.setTimeout(() => {
    Object.keys(targets).forEach((key) => delete targets[Number(key)])
    breathRpmList.value = []
    console.log('MQTT超时未收到新消息，隐藏所有目标点')
  }, MQTT_TIMEOUT_MS)
}

// 呼吸率
const breathRpmList = ref<number[]>([])

onMounted(() => {
  console.log('onMounted', mqttClient)
  const mqttConfig = {
    host: import.meta.env.VITE_MQTT_HOST_POINT,
    username: import.meta.env.VITE_MQTT_USERNAME,
    password: import.meta.env.VITE_MQTT_PASSWORD,
    clientId: `mqtt_client_${Math.random().toString(16).slice(2, 8)}`,
  }
  mqttClient = mqtt.connect(mqttConfig.host, {
    clientId: mqttConfig.clientId,
    username: mqttConfig.username,
    password: mqttConfig.password,
  })
  console.log('⌛️ mqttClient connect ready', mqttClient)
  mqttClient.on('connect', () => {
    console.log('✅ MQTT已连接')
    // 订阅所有设备的主题
    // const sub = `/dev/${clientId.value}/dsp_data`
    const sub = `/dev/${clientId.value}/tracker_targets`
    mqttClient?.subscribe(sub, (err) => {
      if (err) {
        console.error('❌ MQTT订阅失败', err)
      } else {
        console.log(`⚛️ 已订阅主题 ${sub}`)
      }
    })
  })
  mqttClient.on('error', (err) => {
    console.error('❌ MQTT连接错误', err)
  })
  mqttClient.on('message', (topic: string, message: Uint8Array) => {
    resetMqttTimeout()
    // const subMatch = /^\/dev\/(.+)\/dsp_data$/
    const subMatch = /^\/dev\/(.+)\/tracker_targets$/
    const match = topic.match(subMatch)
    if (!match) return
    const msgDevId = match[1]
    if (msgDevId !== clientId.value) return // 只处理当前设备
    try {
      const data = JSON.parse(message.toString())
      const targetPoints = data?.tracker_targets || [] // 点位图数据
      const breathRpm = data.health?.breath_rpm || 0 // 呼吸率数据
      if (breathRpm) {
        breathRpmList.value.push(Math.floor(breathRpm || 0))
      } else {
        breathRpmList.value = []
      }
      console.log(`🚀 收到MQTT消息 ${formatDateTime(new Date())}`, {
        '🔴 目标人数': targetPoints.length,
        '🟢 呼吸率': breathRpm,
        '🟡 点位图': targetPoints,
        '🔵 接口数据': data,
      })
      if (
        Array.isArray(targetPoints) &&
        targetPoints.length > 0 &&
        Array.isArray(targetPoints[0])
      ) {
        // 记录本次出现的所有id
        const currentIds = new Set<number>()
        targetPoints.forEach((item: number[]) => {
          if (item.length < 4) return
          const [x, y, z, id] = item
          currentIds.add(id)
          if (!(id in targets)) {
            targets[id] = { x, y, z, id, displayX: x, displayY: y, lastX: x, lastY: y }
          }
          // 去抖动
          const dx = x - targets[id].lastX
          const dy = y - targets[id].lastY
          if (Math.sqrt(dx * dx + dy * dy) > THRESHOLD) {
            targets[id].x = x
            targets[id].y = y
            targets[id].z = z
            targets[id].lastX = x
            targets[id].lastY = y
            targets[id].displayX = x
            targets[id].displayY = y
            // console.log(`🔄 更新目标点: id=${id}, x=${x}, y=${y}`, targets[id])
          } else {
            // 距离太小，忽略本次更新
            // console.log(`忽略微小抖动 id=${id}`)
          }
        })
        // 删除本次未出现的id
        Object.keys(targets).forEach((key) => {
          const id = Number(key)
          if (!currentIds.has(id)) {
            delete targets[id]
            // console.log(`ID=${id} 消失，隐藏对应红点`)
          }
        })
      } else {
        // 没有目标时，隐藏所有红点
        Object.keys(targets).forEach((key) => delete targets[Number(key)])
        breathRpmList.value = []
      }
    } catch (e) {
      console.error('MQTT消息解析失败', e)
    }
  })
})

// setInterval(() => {
//   breathRpmList.value.push(Math.floor(Math.random() * 30))
// }, 100)

const areaAvailable = computed(() => {
  const { length, width } = detailState.value
  return Number(length) < 50 || Number(width) < 50
})

onUnmounted(() => {
  if (mqttClient) mqttClient.end()
  if (mqttTimeout) clearTimeout(mqttTimeout)
})

const openFullView = ref(false) // 全屏展示点位图

const alarmPlanVisible = ref(false) // 告警计划弹窗
const alarmPlanTitle = ref('新增告警计划') // 告警计划弹窗标题
const alarmPlanId = ref<number | null>(null) // 当前编辑的告警计划id
const alarmPlanLoading = ref(false) // 告警计划加载中
const alarmPlans = ref<
  { id: number; name: string; enable: boolean; loading: boolean; data: object }[]
>([])
// 获取告警计划列表
const fetchAlarmPlanList = async () => {
  try {
    alarmPlanLoading.value = true
    await alarmApi
      .getAlarmPlanList({
        clientId: clientId.value,
      })
      .then((res) => {
        console.log('获取告警计划列表成功✅', res)
        const data = res.data
        if (Array.isArray(data) && data.length) {
          alarmPlans.value = data.map((item) => ({
            id: item.id || '',
            name: item.name || '',
            enable: item.enable === 1,
            loading: false,
            data: item,
          }))
        } else {
          alarmPlans.value = []
        }
      })
      .catch((err) => {
        console.log('获取告警计划列表失败❌', err)
      })
      .finally(() => {
        alarmPlanLoading.value = false
      })
  } catch (err) {
    console.log('获取告警计划列表失败❌', err)
  }
}
fetchAlarmPlanList()

type AlarmPlan = {
  id: number
  uuid: ID
  name: string
  clientId: string
  enable: SwitchType
  region: string
  eventVal: number
  alarmTimePlanId: ID
  thresholdTime: ID
  mergeTime: ID
  param: string
  createTime: string
  updateTime: string
  remark: string | null
  alarmTimePlan: {
    createId: ID
    updateId: ID
    createTime: ID
    updateTime: ID
    isDeleted: SwitchType | null
    remark: ID
    id: ID
    startDate: string
    stopDate: string
    timeRange: string
    monthDays: string
    weekdays: string
  }
}

interface AlarmPlanItem {
  id?: number
  loading?: boolean
  [key: string]: unknown
}
const alarmPlanData = ref<AlarmPlanItem | undefined>(undefined)
const alarmPlanDataWithType = computed(() => alarmPlanData.value as AlarmPlan)

// 编辑告警计划
const editAlarmItem = async (item: AlarmPlanItem) => {
  console.log('editAlarmItem', item)
  alarmPlanVisible.value = true
  alarmPlanTitle.value = '编辑告警计划'
  alarmPlanData.value = item
  alarmPlanId.value = item?.id ?? null
}

// 添加告警计划
const addPlanHandler = () => {
  alarmPlanVisible.value = true
  alarmPlanTitle.value = '新增告警计划'
  alarmPlanData.value = undefined
  alarmPlanId.value = null
}

// 删除告警计划
const deleteAlarmItem = async (id: number) => {
  console.log('deleteAlarmItem', id)
  try {
    alarmApi.deleteAlarmPlan({ id }).then(() => {
      message.success('删除成功')
      fetchAlarmPlanList()
    })
  } catch (err) {
    console.log('删除告警计划失败❌', err)
    message.error('删除失败')
  }
}

// 启用/禁用告警计划
const swtichAlarmItem = async (id: number, swtich: boolean, item: AlarmPlanItem) => {
  console.log('swtichAlarmItem', id, swtich, item)
  try {
    item.loading = true
    alarmApi
      .enableAlarmPlan({ id, enable: Number(!swtich) as 0 | 1 })
      .then(() => {
        message.success('变更成功')
        item.loading = false
        fetchAlarmPlanList()
      })
      .catch((err) => {
        console.log('启用/禁用告警计划失败❌', err)
        item.loading = false
        message.error('操作失败')
      })
  } catch (err) {
    console.log('启用/禁用告警计划失败❌', err)
    message.error('变更失败')
  }
}
</script>

<style scoped lang="less">
.deviceDetail {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.info.pointCard {
  min-width: 800px;
}

.pointCloudMap {
  width: 770px;
  height: 100%;
  height: 500px;
}

.pointMap {
  flex-shrink: 0;
  min-width: 400px;
  min-height: 400px;
  border-radius: 10px;
  display: flex;
  flex-direction: row;
}

.radarArea {
  position: relative;
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),
    linear-gradient(to right, rgba(0, 0, 0, 0.1) 1px, transparent 1px);
  background-size: 20px 20px;
  border: 1px solid rgba(0, 0, 0, 0.8);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  flex-shrink: 0;

  .furniture-item {
    position: absolute;
    user-select: none;
    cursor: move;
    width: 30px;
    height: 30px;
  }
}

.extraIcon {
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  &:hover {
    color: #1890ff;
  }
}

.fullView {
  margin-top: 50px;
  display: flex;
  flex-direction: column;
  .pointMap {
    min-height: auto;
    margin: auto;
  }
  .breathLine {
    margin-left: 0;
  }

  .pointTitle {
    font-size: 16px;
    font-weight: 600;
    margin-bottom: 10px;
    text-align: center;
  }
}

.breathLine {
  margin-left: 16px;
  flex-shrink: 0;
  flex-grow: 1;
  flex-basis: 350px;
  position: relative;
}

.alarmPlanGroup {
  :deep(.info-item-group-content) {
    padding: 12px 0 !important;
    overflow-y: auto;
    max-height: 500px;
  }
  .alarmPlan {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    width: 100%;
    color: #555;
    &-empty {
      padding: 50px 0;
    }

    .alarmPlan-item {
      display: flex;
      align-items: center;
      flex: 1;
      padding: 8px 12px;
      &:hover {
        border-radius: 8px;
        background: #f5f5f5;
      }
    }
    .alarmPlan-item-label {
      text-align: right;
      flex-shrink: 0;
    }
    .alarmPlan-item-contant {
      font-size: 14px;
      flex-grow: 1;
      max-width: 250px;
      word-break: break-all;
      line-height: 1.5;
      padding: 0 12px;
      // 超出一行显示省略号
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      cursor: default;
    }
    .alarmPlan-item-action {
      flex-shrink: 0;
      color: #888;
      :deep(.ant-space) {
        cursor: pointer;
        .ant-space-item:hover {
          color: #40a9ff;
        }
      }
    }
  }
}
</style>
