<template>
  <ArtTableFullScreen>
    <div class="device-list-page" id="table-full-screen">
      <!-- 搜索栏 -->
      <ArtSearchBar
        v-model:filter="searchForm"
        :items="searchFormItems"
        @reset="handleReset"
        @search="handleSearch"
      ></ArtSearchBar>

      <ElCard shadow="never" class="art-table-card">
        <!-- 表格头部 -->
        <ArtTableHeader
          :columnList="columnOptions"
          v-model:columns="columnChecks"
          @refresh="handleRefresh"
        >
          <template #left>
            <ElButton
              type="primary"
              @click="handleBatchAllocate"
              :disabled="!selectedDevices.length"
              v-permission="'device:batch_allocate'"
            >
              批量分配
            </ElButton>
            <ElButton
              @click="handleBatchRecall"
              :disabled="!selectedDevices.length"
              v-permission="'device:batch_recall'"
            >
              批量回收
            </ElButton>
            <ElButton
              type="info"
              @click="handleBatchSetSeries"
              :disabled="!selectedDevices.length"
              v-permission="'device:batch_set_series'"
            >
              批量设置套餐系列
            </ElButton>
          </template>
        </ArtTableHeader>

        <!-- 表格 -->
        <ArtTable
          ref="tableRef"
          row-key="id"
          :loading="loading"
          :data="deviceList"
          :currentPage="pagination.page"
          :pageSize="pagination.pageSize"
          :total="pagination.total"
          :marginTop="10"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          @selection-change="handleSelectionChange"
          @row-contextmenu="handleRowContextMenu"
        >
          <template #default>
            <ElTableColumn type="selection" width="55" />
            <ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
          </template>
        </ArtTable>

        <!-- 批量分配对话框 -->
        <ElDialog v-model="allocateDialogVisible" title="批量分配设备" width="600px">
          <ElForm
            ref="allocateFormRef"
            :model="allocateForm"
            :rules="allocateRules"
            label-width="120px"
          >
            <ElFormItem label="已选设备数">
              <span style="font-weight: bold; color: #409eff">{{ selectedDevices.length }}</span> 台
            </ElFormItem>
            <ElFormItem label="目标店铺" prop="target_shop_id">
              <ElTreeSelect
                v-model="allocateForm.target_shop_id"
                :data="shopTreeData"
                :props="{ label: 'shop_name', value: 'id', children: 'children' }"
                placeholder="请选择目标店铺"
                clearable
                filterable
                check-strictly
                style="width: 100%"
              />
            </ElFormItem>
            <ElFormItem label="备注">
              <ElInput
                v-model="allocateForm.remark"
                type="textarea"
                :rows="3"
                placeholder="请输入备注信息（选填）"
              />
            </ElFormItem>
          </ElForm>

          <!-- 分配结果 -->
          <div v-if="allocateResult" style="margin-top: 20px">
            <ElAlert
              :type="allocateResult.fail_count === 0 ? 'success' : 'warning'"
              :closable="false"
              style="margin-bottom: 10px"
            >
              <template #title>
                成功分配 {{ allocateResult.success_count }} 台，失败
                {{ allocateResult.fail_count }} 台
              </template>
            </ElAlert>
            <div v-if="allocateResult.failed_items && allocateResult.failed_items.length > 0">
              <div style="margin-bottom: 10px; font-weight: bold">失败详情：</div>
              <div
                v-for="item in allocateResult.failed_items"
                :key="item.device_id"
                style="margin-bottom: 8px; font-size: 12px; color: #f56c6c"
              >
                设备号: {{ item.device_no }} - {{ item.reason }}
              </div>
            </div>
          </div>

          <template #footer>
            <div class="dialog-footer">
              <ElButton @click="handleCloseAllocateDialog">
                {{ allocateResult ? '关闭' : '取消' }}
              </ElButton>
              <ElButton
                v-if="!allocateResult"
                type="primary"
                @click="handleConfirmAllocate"
                :loading="allocateLoading"
              >
                确认分配
              </ElButton>
            </div>
          </template>
        </ElDialog>

        <!-- 批量回收对话框 -->
        <ElDialog v-model="recallDialogVisible" title="批量回收设备" width="600px">
          <ElForm ref="recallFormRef" :model="recallForm" label-width="120px">
            <ElFormItem label="已选设备数">
              <span style="font-weight: bold; color: #e6a23c">{{ selectedDevices.length }}</span> 台
            </ElFormItem>
            <ElFormItem label="备注">
              <ElInput
                v-model="recallForm.remark"
                type="textarea"
                :rows="3"
                placeholder="请输入备注信息（选填）"
              />
            </ElFormItem>
          </ElForm>

          <!-- 回收结果 -->
          <div v-if="recallResult" style="margin-top: 20px">
            <ElAlert
              :type="recallResult.fail_count === 0 ? 'success' : 'warning'"
              :closable="false"
              style="margin-bottom: 10px"
            >
              <template #title>
                成功回收 {{ recallResult.success_count }} 台，失败 {{ recallResult.fail_count }} 台
              </template>
            </ElAlert>
            <div v-if="recallResult.failed_items && recallResult.failed_items.length > 0">
              <div style="margin-bottom: 10px; font-weight: bold">失败详情：</div>
              <div
                v-for="item in recallResult.failed_items"
                :key="item.device_id"
                style="margin-bottom: 8px; font-size: 12px; color: #f56c6c"
              >
                设备号: {{ item.device_no }} - {{ item.reason }}
              </div>
            </div>
          </div>

          <template #footer>
            <div class="dialog-footer">
              <ElButton @click="handleCloseRecallDialog">
                {{ recallResult ? '关闭' : '取消' }}
              </ElButton>
              <ElButton
                v-if="!recallResult"
                type="primary"
                @click="handleConfirmRecall"
                :loading="recallLoading"
              >
                确认回收
              </ElButton>
            </div>
          </template>
        </ElDialog>

        <!-- 批量设置套餐系列绑定对话框 -->
        <ElDialog
          v-model="seriesBindingDialogVisible"
          title="批量设置设备套餐系列绑定"
          width="600px"
        >
          <ElForm
            ref="seriesBindingFormRef"
            :model="seriesBindingForm"
            :rules="seriesBindingRules"
            label-width="120px"
          >
            <ElFormItem label="已选设备数">
              <span style="font-weight: bold; color: #409eff">{{ selectedDevices.length }}</span> 台
            </ElFormItem>
            <ElFormItem label="套餐系列" prop="series_id">
              <ElSelect
                v-model="seriesBindingForm.series_id"
                placeholder="请选择或搜索套餐系列"
                style="width: 100%"
                filterable
                remote
                reserve-keyword
                :remote-method="searchPackageSeries"
                :loading="seriesLoading"
                clearable
              >
                <ElOption label="清除关联" :value="0" />
                <ElOption
                  v-for="series in packageSeriesList"
                  :key="series.id"
                  :label="series.series_name"
                  :value="series.id"
                  :disabled="series.status !== 1"
                />
              </ElSelect>
            </ElFormItem>
          </ElForm>

          <!-- 设置结果 -->
          <div v-if="seriesBindingResult" style="margin-top: 20px">
            <ElAlert
              :type="seriesBindingResult.fail_count === 0 ? 'success' : 'warning'"
              :closable="false"
              style="margin-bottom: 10px"
            >
              <template #title>
                成功设置 {{ seriesBindingResult.success_count }} 台，失败
                {{ seriesBindingResult.fail_count }} 台
              </template>
            </ElAlert>
            <div
              v-if="seriesBindingResult.failed_items && seriesBindingResult.failed_items.length > 0"
            >
              <div style="margin-bottom: 10px; font-weight: bold">失败详情：</div>
              <div
                v-for="item in seriesBindingResult.failed_items"
                :key="item.device_id"
                style="margin-bottom: 8px; font-size: 12px; color: #f56c6c"
              >
                设备号: {{ item.device_no }} - {{ item.reason }}
              </div>
            </div>
          </div>

          <template #footer>
            <div class="dialog-footer">
              <ElButton @click="handleCloseSeriesBindingDialog">
                {{ seriesBindingResult ? '关闭' : '取消' }}
              </ElButton>
              <ElButton
                v-if="!seriesBindingResult"
                type="primary"
                @click="handleConfirmSeriesBinding"
                :loading="seriesBindingLoading"
              >
                确认设置
              </ElButton>
            </div>
          </template>
        </ElDialog>

        <!-- 设备详情弹窗 -->
        <ElDialog v-model="deviceDetailDialogVisible" title="设备详情" width="1000px">
          <div v-if="deviceDetailLoading" style="text-align: center; padding: 40px 0">
            <ElIcon class="is-loading" :size="40"><Loading /></ElIcon>
          </div>
          <div v-else-if="currentDeviceDetail">
            <!-- 设备基本信息 -->
            <ElDescriptions :column="3" border style="margin-bottom: 20px">
              <ElDescriptionsItem label="设备ID">{{ currentDeviceDetail.id }}</ElDescriptionsItem>
              <ElDescriptionsItem label="设备号" :span="2">{{
                currentDeviceDetail.device_no
              }}</ElDescriptionsItem>

              <ElDescriptionsItem label="设备名称">{{
                currentDeviceDetail.device_name || '--'
              }}</ElDescriptionsItem>
              <ElDescriptionsItem label="设备型号">{{
                currentDeviceDetail.device_model || '--'
              }}</ElDescriptionsItem>
              <ElDescriptionsItem label="设备类型">{{
                currentDeviceDetail.device_type || '--'
              }}</ElDescriptionsItem>

              <ElDescriptionsItem label="制造商">{{
                currentDeviceDetail.manufacturer || '--'
              }}</ElDescriptionsItem>
              <ElDescriptionsItem label="最大插槽数">{{
                currentDeviceDetail.max_sim_slots
              }}</ElDescriptionsItem>
              <ElDescriptionsItem label="已绑定卡数量">{{
                currentDeviceDetail.bound_card_count
              }}</ElDescriptionsItem>

              <ElDescriptionsItem label="状态">
                <ElTag :type="getDeviceStatusTagType(currentDeviceDetail.status)">
                  {{ currentDeviceDetail.status_name }}
                </ElTag>
              </ElDescriptionsItem>
              <ElDescriptionsItem label="批次号" :span="2">{{
                currentDeviceDetail.batch_no || '--'
              }}</ElDescriptionsItem>

              <ElDescriptionsItem label="创建时间" :span="3">{{
                formatDateTime(currentDeviceDetail.created_at) || '--'
              }}</ElDescriptionsItem>
            </ElDescriptions>
          </div>
        </ElDialog>

        <!-- 绑定卡片列表弹窗 -->
        <ElDialog v-model="deviceCardsDialogVisible" title="绑定的卡片" width="900px">
          <div style="margin-bottom: 10px; text-align: right">
            <ElButton type="primary" @click="handleBindCard">绑定新卡</ElButton>
          </div>
          <div v-if="deviceCardsLoading" style="text-align: center; padding: 40px 0">
            <ElIcon class="is-loading" :size="40"><Loading /></ElIcon>
          </div>
          <div v-else>
            <ElTable :data="deviceCards" border style="width: 100%">
              <ElTableColumn prop="slot_position" label="插槽位置" width="100" align="center" />
              <ElTableColumn prop="iccid" label="ICCID" min-width="180" />
              <ElTableColumn prop="msisdn" label="接入号" width="140" />
              <ElTableColumn prop="status" label="状态" width="100" align="center">
                <template #default="{ row }">
                  <ElTag :type="getCardStatusTagType(row.status)">
                    {{ getCardStatusText(row.status) }}
                  </ElTag>
                </template>
              </ElTableColumn>
              <ElTableColumn prop="bind_time" label="绑定时间" width="180">
                <template #default="{ row }">
                  {{ formatDateTime(row.bind_time) || '--' }}
                </template>
              </ElTableColumn>
              <ElTableColumn label="操作" width="100" fixed="right" align="center">
                <template #default="{ row }">
                  <ElButton type="danger" size="small" link @click="handleUnbindCard(row)">
                    解绑
                  </ElButton>
                </template>
              </ElTableColumn>
            </ElTable>
            <div
              v-if="deviceCards.length === 0"
              style="text-align: center; padding: 20px; color: #909399"
            >
              暂无绑定的卡片
            </div>
          </div>
        </ElDialog>

        <!-- 设备操作右键菜单 -->
        <ArtMenuRight
          ref="deviceOperationMenuRef"
          :menu-items="deviceOperationMenuItems"
          :menu-width="140"
          @select="handleDeviceOperationMenuSelect"
        />

        <!-- 绑定卡弹窗 -->
        <ElDialog v-model="bindCardDialogVisible" title="绑定卡到设备" width="500px">
          <ElForm
            ref="bindCardFormRef"
            :model="bindCardForm"
            :rules="bindCardRules"
            label-width="100px"
          >
            <ElFormItem label="IoT卡" prop="iot_card_id">
              <ElSelect
                v-model="bindCardForm.iot_card_id"
                placeholder="请选择或搜索IoT卡（支持ICCID搜索）"
                filterable
                remote
                reserve-keyword
                :remote-method="searchIotCards"
                :loading="iotCardSearchLoading"
                clearable
                style="width: 100%"
              >
                <ElOption
                  v-for="card in iotCardList"
                  :key="card.id"
                  :label="`${card.iccid} ${card.msisdn ? '(' + card.msisdn + ')' : ''}`"
                  :value="card.id"
                />
              </ElSelect>
            </ElFormItem>
            <ElFormItem label="插槽位置" prop="slot_position">
              <ElSelect
                v-model="bindCardForm.slot_position"
                placeholder="请选择插槽位置"
                style="width: 100%"
              >
                <ElOption
                  v-for="i in currentDeviceDetail?.max_sim_slots || 4"
                  :key="i"
                  :label="`插槽 ${i}`"
                  :value="i"
                />
              </ElSelect>
            </ElFormItem>
          </ElForm>
          <template #footer>
            <ElButton @click="bindCardDialogVisible = false">取消</ElButton>
            <ElButton type="primary" @click="handleConfirmBindCard" :loading="bindCardLoading">
              确认绑定
            </ElButton>
          </template>
        </ElDialog>

        <!-- 设置限速对话框 -->
        <ElDialog v-model="speedLimitDialogVisible" title="设置限速" width="500px">
          <ElForm
            ref="speedLimitFormRef"
            :model="speedLimitForm"
            :rules="speedLimitRules"
            label-width="120px"
          >
            <ElFormItem label="设备号">
              <span style="font-weight: bold; color: #409eff">{{ currentOperatingDevice }}</span>
            </ElFormItem>
            <ElFormItem label="下行速率" prop="download_speed">
              <ElInputNumber
                v-model="speedLimitForm.download_speed"
                :min="1"
                :step="128"
                controls-position="right"
                style="width: 100%"
              />
              <div style="color: #909399; font-size: 12px; margin-top: 4px">单位: KB/s</div>
            </ElFormItem>
            <ElFormItem label="上行速率" prop="upload_speed">
              <ElInputNumber
                v-model="speedLimitForm.upload_speed"
                :min="1"
                :step="128"
                controls-position="right"
                style="width: 100%"
              />
              <div style="color: #909399; font-size: 12px; margin-top: 4px">单位: KB/s</div>
            </ElFormItem>
          </ElForm>
          <template #footer>
            <ElButton @click="speedLimitDialogVisible = false">取消</ElButton>
            <ElButton type="primary" @click="handleConfirmSpeedLimit" :loading="speedLimitLoading">
              确认设置
            </ElButton>
          </template>
        </ElDialog>

        <!-- 切换SIM卡对话框 -->
        <ElDialog v-model="switchCardDialogVisible" title="切换SIM卡" width="500px">
          <ElForm
            ref="switchCardFormRef"
            :model="switchCardForm"
            :rules="switchCardRules"
            label-width="120px"
          >
            <ElFormItem label="设备号">
              <span style="font-weight: bold; color: #409eff">{{ currentOperatingDevice }}</span>
            </ElFormItem>
            <ElFormItem label="目标ICCID" prop="target_iccid">
              <ElInput
                v-model="switchCardForm.target_iccid"
                placeholder="请输入要切换到的目标ICCID"
                clearable
              />
            </ElFormItem>
          </ElForm>
          <template #footer>
            <ElButton @click="switchCardDialogVisible = false">取消</ElButton>
            <ElButton type="primary" @click="handleConfirmSwitchCard" :loading="switchCardLoading">
              确认切换
            </ElButton>
          </template>
        </ElDialog>

        <!-- 设置WiFi对话框 -->
        <ElDialog v-model="setWiFiDialogVisible" title="设置WiFi" width="500px">
          <ElForm
            ref="setWiFiFormRef"
            :model="setWiFiForm"
            :rules="setWiFiRules"
            label-width="120px"
          >
            <ElFormItem label="设备号">
              <span style="font-weight: bold; color: #409eff">{{ currentOperatingDevice }}</span>
            </ElFormItem>
            <ElFormItem label="WiFi状态" prop="enabled">
              <ElRadioGroup v-model="setWiFiForm.enabled">
                <ElRadio :value="1">启用</ElRadio>
                <ElRadio :value="0">禁用</ElRadio>
              </ElRadioGroup>
            </ElFormItem>
            <ElFormItem label="WiFi名称" prop="ssid">
              <ElInput
                v-model="setWiFiForm.ssid"
                placeholder="请输入WiFi名称（1-32个字符）"
                maxlength="32"
                show-word-limit
                clearable
              />
            </ElFormItem>
            <ElFormItem label="WiFi密码" prop="password">
              <ElInput
                v-model="setWiFiForm.password"
                type="password"
                placeholder="请输入WiFi密码（8-63个字符）"
                maxlength="63"
                show-word-limit
                show-password
                clearable
              />
            </ElFormItem>
          </ElForm>
          <template #footer>
            <ElButton @click="setWiFiDialogVisible = false">取消</ElButton>
            <ElButton type="primary" @click="handleConfirmSetWiFi" :loading="setWiFiLoading">
              确认设置
            </ElButton>
          </template>
        </ElDialog>
      </ElCard>
    </div>
  </ArtTableFullScreen>
</template>

<script setup lang="ts">
  import { h } from 'vue'
  import { useRouter } from 'vue-router'
  import { DeviceService, ShopService, CardService, PackageSeriesService } from '@/api/modules'
  import {
    ElMessage,
    ElMessageBox,
    ElTag,
    ElSwitch,
    ElIcon,
    ElTreeSelect,
    ElInputNumber,
    ElRadioGroup,
    ElRadio
  } from 'element-plus'
  import { Loading } from '@element-plus/icons-vue'
  import type { FormInstance, FormRules } from 'element-plus'
  import type {
    Device,
    DeviceStatus,
    AllocateDevicesResponse,
    RecallDevicesResponse,
    BatchSetDeviceSeriesBindingResponse
  } from '@/types/api'
  import type { SearchFormItem } from '@/types'
  import { useCheckedColumns } from '@/composables/useCheckedColumns'
  import { useAuth } from '@/composables/useAuth'
  import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
  import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
  import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
  import { formatDateTime } from '@/utils/business/format'
  import { CommonStatus, getStatusText } from '@/config/constants'
  import type { PackageSeriesResponse } from '@/types/api'

  defineOptions({ name: 'DeviceList' })

  const { hasAuth } = useAuth()
  const router = useRouter()
  const loading = ref(false)
  const allocateLoading = ref(false)
  const recallLoading = ref(false)
  const tableRef = ref()
  const allocateFormRef = ref<FormInstance>()
  const recallFormRef = ref<FormInstance>()
  const allocateDialogVisible = ref(false)
  const recallDialogVisible = ref(false)
  const selectedDevices = ref<Device[]>([])
  const shopTreeData = ref<any[]>([])
  const allocateResult = ref<AllocateDevicesResponse | null>(null)
  const recallResult = ref<RecallDevicesResponse | null>(null)

  // 套餐系列绑定相关
  const seriesBindingDialogVisible = ref(false)
  const seriesBindingLoading = ref(false)
  const seriesBindingFormRef = ref<FormInstance>()
  const seriesLoading = ref(false)
  const packageSeriesList = ref<PackageSeriesResponse[]>([])
  const seriesBindingForm = reactive({
    series_id: undefined as number | undefined
  })
  const seriesBindingRules = reactive<FormRules>({
    series_id: [{ required: true, message: '请选择套餐系列', trigger: 'change' }]
  })
  const seriesBindingResult = ref<BatchSetDeviceSeriesBindingResponse | null>(null)

  // 设备详情弹窗相关
  const deviceDetailDialogVisible = ref(false)
  const deviceDetailLoading = ref(false)
  const currentDeviceDetail = ref<any>(null)
  const deviceCards = ref<any[]>([])
  const deviceCardsLoading = ref(false)
  const deviceCardsDialogVisible = ref(false)

  // 绑定卡相关
  const bindCardDialogVisible = ref(false)
  const bindCardLoading = ref(false)
  const bindCardFormRef = ref<FormInstance>()
  const iotCardList = ref<any[]>([])
  const iotCardSearchLoading = ref(false)
  const bindCardForm = reactive({
    iot_card_id: undefined as number | undefined,
    slot_position: 1
  })
  const bindCardRules = reactive<FormRules>({
    iot_card_id: [{ required: true, message: '请选择IoT卡', trigger: 'change' }],
    slot_position: [{ required: true, message: '请选择插槽位置', trigger: 'change' }]
  })

  // 设备操作相关对话框
  const speedLimitDialogVisible = ref(false)
  const speedLimitLoading = ref(false)
  const speedLimitFormRef = ref<FormInstance>()
  const speedLimitForm = reactive({
    download_speed: 1024,
    upload_speed: 512
  })
  const speedLimitRules = reactive<FormRules>({
    download_speed: [
      { required: true, message: '请输入下行速率', trigger: 'blur' },
      { type: 'number', min: 1, message: '速率不能小于1KB/s', trigger: 'blur' }
    ],
    upload_speed: [
      { required: true, message: '请输入上行速率', trigger: 'blur' },
      { type: 'number', min: 1, message: '速率不能小于1KB/s', trigger: 'blur' }
    ]
  })
  const currentOperatingDevice = ref<string>('')

  // 设备操作右键菜单
  const deviceOperationMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
  const currentOperatingDeviceNo = ref<string>('')

  const switchCardDialogVisible = ref(false)
  const switchCardLoading = ref(false)
  const switchCardFormRef = ref<FormInstance>()
  const switchCardForm = reactive({
    target_iccid: ''
  })
  const switchCardRules = reactive<FormRules>({
    target_iccid: [{ required: true, message: '请输入目标ICCID', trigger: 'blur' }]
  })

  const setWiFiDialogVisible = ref(false)
  const setWiFiLoading = ref(false)
  const setWiFiFormRef = ref<FormInstance>()
  const setWiFiForm = reactive({
    enabled: 1,
    ssid: '',
    password: ''
  })
  const setWiFiRules = reactive<FormRules>({
    ssid: [
      { required: true, message: '请输入WiFi名称', trigger: 'blur' },
      { min: 1, max: 32, message: 'WiFi名称长度为1-32个字符', trigger: 'blur' }
    ],
    password: [
      { required: true, message: '请输入WiFi密码', trigger: 'blur' },
      { min: 8, max: 63, message: 'WiFi密码长度为8-63个字符', trigger: 'blur' }
    ]
  })

  // 搜索表单初始值
  const initialSearchState = {
    device_no: '',
    device_name: '',
    status: undefined as DeviceStatus | undefined,
    batch_no: '',
    device_type: '',
    manufacturer: ''
  }

  // 搜索表单
  const searchForm = reactive({ ...initialSearchState })

  // 搜索表单配置
  const searchFormItems: SearchFormItem[] = [
    {
      label: '设备号',
      prop: 'device_no',
      type: 'input',
      config: {
        clearable: true,
        placeholder: '请输入设备号'
      }
    },
    {
      label: '设备名称',
      prop: 'device_name',
      type: 'input',
      config: {
        clearable: true,
        placeholder: '请输入设备名称'
      }
    },
    {
      label: '状态',
      prop: 'status',
      type: 'select',
      config: {
        clearable: true,
        placeholder: '请选择状态'
      },
      options: () => [
        { label: '在库', value: 1 },
        { label: '已分销', value: 2 },
        { label: '已激活', value: 3 },
        { label: '已停用', value: 4 }
      ]
    },
    {
      label: '批次号',
      prop: 'batch_no',
      type: 'input',
      config: {
        clearable: true,
        placeholder: '请输入批次号'
      }
    },
    {
      label: '设备类型',
      prop: 'device_type',
      type: 'input',
      config: {
        clearable: true,
        placeholder: '请输入设备类型'
      }
    },
    {
      label: '制造商',
      prop: 'manufacturer',
      type: 'input',
      config: {
        clearable: true,
        placeholder: '请输入制造商'
      }
    }
  ]

  // 分页
  const pagination = reactive({
    page: 1,
    pageSize: 20,
    total: 0
  })

  // 列配置
  const columnOptions = [
    { label: '设备号', prop: 'device_no' },
    { label: '设备名称', prop: 'device_name' },
    { label: '设备型号', prop: 'device_model' },
    { label: '设备类型', prop: 'device_type' },
    { label: '制造商', prop: 'manufacturer' },
    { label: '最大插槽数', prop: 'max_sim_slots' },
    { label: '已绑定卡数', prop: 'bound_card_count' },
    { label: '状态', prop: 'status' },
    { label: '批次号', prop: 'batch_no' },
    { label: '创建时间', prop: 'created_at' },
    { label: '操作', prop: 'operation' }
  ]

  const deviceList = ref<Device[]>([])

  // 分配表单
  const allocateForm = reactive({
    target_shop_id: undefined as number | undefined,
    remark: ''
  })

  // 分配表单验证规则
  const allocateRules = reactive<FormRules>({
    target_shop_id: [{ required: true, message: '请选择目标店铺', trigger: 'change' }]
  })

  // 回收表单
  const recallForm = reactive({
    remark: ''
  })

  // 跳转到设备详情页面
  const goToDeviceSearchDetail = (deviceNo: string) => {
    router.push({
      path: '/asset-management/device-detail',
      query: {
        device_no: deviceNo
      }
    })
  }

  // 查看设备绑定的卡片
  const handleViewCards = async (device: Device) => {
    currentDeviceDetail.value = device
    deviceCards.value = []
    deviceCardsDialogVisible.value = true
    await loadDeviceCards(device.id)
  }

  // 加载设备绑定的卡列表
  const loadDeviceCards = async (deviceId: number) => {
    deviceCardsLoading.value = true
    try {
      const res = await DeviceService.getDeviceCards(deviceId)
      if (res.code === 0 && res.data) {
        deviceCards.value = res.data.bindings || []
      }
    } catch (error) {
      console.error('获取设备绑定的卡列表失败:', error)
    } finally {
      deviceCardsLoading.value = false
    }
  }

  // 打开绑定卡弹窗
  const handleBindCard = async () => {
    bindCardForm.iot_card_id = undefined
    bindCardForm.slot_position = 1
    bindCardDialogVisible.value = true
    // 加载默认的IoT卡列表
    await loadDefaultIotCards()
  }

  // 加载默认的IoT卡列表
  const loadDefaultIotCards = async () => {
    iotCardSearchLoading.value = true
    try {
      const res = await CardService.getStandaloneIotCards({
        page: 1,
        page_size: 20
      })
      if (res.code === 0 && res.data?.items) {
        iotCardList.value = res.data.items
      }
    } catch (error) {
      console.error('获取IoT卡列表失败:', error)
    } finally {
      iotCardSearchLoading.value = false
    }
  }

  // 搜索IoT卡（根据ICCID）
  const searchIotCards = async (query: string) => {
    if (!query) {
      await loadDefaultIotCards()
      return
    }
    iotCardSearchLoading.value = true
    try {
      const res = await CardService.getStandaloneIotCards({
        page: 1,
        page_size: 20,
        iccid: query
      })
      if (res.code === 0 && res.data?.items) {
        iotCardList.value = res.data.items
      }
    } catch (error) {
      console.error('搜索IoT卡失败:', error)
    } finally {
      iotCardSearchLoading.value = false
    }
  }

  // 确认绑定卡
  const handleConfirmBindCard = async () => {
    if (!bindCardFormRef.value || !currentDeviceDetail.value) return

    await bindCardFormRef.value.validate(async (valid) => {
      if (valid) {
        bindCardLoading.value = true
        try {
          const res = await DeviceService.bindCard(currentDeviceDetail.value.id, {
            iot_card_id: bindCardForm.iot_card_id!,
            slot_position: bindCardForm.slot_position
          })
          if (res.code === 0) {
            ElMessage.success('绑定成功')
            bindCardDialogVisible.value = false
            // 重新加载卡列表
            await loadDeviceCards(currentDeviceDetail.value.id)
            // 刷新设备详情以更新绑定卡数量
            const detailRes = await DeviceService.getDeviceByImei(
              currentDeviceDetail.value.device_no
            )
            if (detailRes.code === 0 && detailRes.data) {
              currentDeviceDetail.value = detailRes.data
            }
          } else {
            ElMessage.error(res.message || '绑定失败')
          }
        } catch (error: any) {
          console.error('绑定卡失败:', error)
          ElMessage.error(error?.message || '绑定失败')
        } finally {
          bindCardLoading.value = false
        }
      }
    })
  }

  // 解绑卡
  const handleUnbindCard = (row: any) => {
    ElMessageBox.confirm(`确定要解绑 ICCID: ${row.iccid} 吗？`, '解绑确认', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(async () => {
        try {
          const res = await DeviceService.unbindCard(currentDeviceDetail.value.id, row.iot_card_id)
          if (res.code === 0) {
            ElMessage.success('解绑成功')
            // 重新加载卡列表
            await loadDeviceCards(currentDeviceDetail.value.id)
            // 刷新设备详情以更新绑定卡数量
            const detailRes = await DeviceService.getDeviceByImei(
              currentDeviceDetail.value.device_no
            )
            if (detailRes.code === 0 && detailRes.data) {
              currentDeviceDetail.value = detailRes.data
            }
          } else {
            ElMessage.error(res.message || '解绑失败')
          }
        } catch (error: any) {
          console.error('解绑卡失败:', error)
          ElMessage.error(error?.message || '解绑失败')
        }
      })
      .catch(() => {
        // 用户取消
      })
  }

  // 获取卡状态标签类型
  const getCardStatusTagType = (status: number) => {
    const typeMap: Record<number, any> = {
      1: 'info', // 在库
      2: 'warning', // 已分销
      3: 'success', // 已激活
      4: 'danger' // 已停用
    }
    return typeMap[status] || 'info'
  }

  // 获取卡状态文本
  const getCardStatusText = (status: number) => {
    const textMap: Record<number, string> = {
      1: '在库',
      2: '已分销',
      3: '已激活',
      4: '已停用'
    }
    return textMap[status] || '未知'
  }

  // 获取设备状态标签类型
  const getDeviceStatusTagType = (status: number) => {
    const typeMap: Record<number, any> = {
      1: 'info', // 在库
      2: 'warning', // 已分销
      3: 'success', // 已激活
      4: 'danger' // 已停用
    }
    return typeMap[status] || 'info'
  }

  // 动态列配置
  const { columnChecks, columns } = useCheckedColumns(() => [
    {
      prop: 'device_no',
      label: '设备号',
      minWidth: 150,
      showOverflowTooltip: true,
      formatter: (row: Device) => {
        return h(
          'span',
          {
            style: 'color: var(--el-color-primary); cursor: pointer; text-decoration: underline;',
            onClick: (e: MouseEvent) => {
              e.stopPropagation()
              goToDeviceSearchDetail(row.device_no)
            }
          },
          row.device_no
        )
      }
    },
    {
      prop: 'device_name',
      label: '设备名称',
      minWidth: 120
    },
    {
      prop: 'device_model',
      label: '设备型号',
      minWidth: 120
    },
    {
      prop: 'device_type',
      label: '设备类型',
      width: 120
    },
    {
      prop: 'manufacturer',
      label: '制造商',
      minWidth: 120
    },
    {
      prop: 'max_sim_slots',
      label: '最大插槽数',
      width: 100,
      align: 'center'
    },
    {
      prop: 'bound_card_count',
      label: '已绑定卡数',
      width: 110,
      align: 'center',
      formatter: (row: Device) => {
        const color = row.bound_card_count > 0 ? '#67c23a' : '#909399'
        return h('span', { style: { color, fontWeight: 'bold' } }, row.bound_card_count)
      }
    },
    {
      prop: 'status',
      label: '状态',
      width: 100,
      formatter: (row: Device) => {
        const statusMap: Record<number, { text: string; type: any }> = {
          1: { text: '在库', type: 'info' },
          2: { text: '已分销', type: 'primary' },
          3: { text: '已激活', type: 'success' },
          4: { text: '已停用', type: 'danger' }
        }
        const status = statusMap[row.status] || { text: '未知', type: 'info' }
        return h(ElTag, { type: status.type }, () => status.text)
      }
    },
    {
      prop: 'batch_no',
      label: '批次号',
      minWidth: 180,
      formatter: (row: Device) => row.batch_no || '-'
    },
    {
      prop: 'created_at',
      label: '创建时间',
      width: 180,
      formatter: (row: Device) => formatDateTime(row.created_at)
    }
  ])

  onMounted(() => {
    getTableData()
    loadShopTree()
  })

  // 当页面被 keep-alive 激活时自动刷新数据
  onActivated(() => {
    getTableData()
  })

  // 加载店铺树形数据
  const loadShopTree = async () => {
    try {
      const res = await ShopService.getShops({
        page: 1,
        page_size: 9999, // 获取所有数据用于构建树形结构
        status: 1 // 只获取启用的店铺
      })
      if (res.code === 0) {
        shopTreeData.value = buildShopTree(res.data.items || [])
      }
    } catch (error) {
      console.error('获取店铺列表失败:', error)
    }
  }

  // 构建店铺树形结构
  const buildShopTree = (shops: any[]) => {
    const map = new Map<number, any>()
    const tree: any[] = []

    // 先将所有项放入 map
    shops.forEach((shop) => {
      map.set(shop.id, { ...shop, children: [] })
    })

    // 构建树形结构
    shops.forEach((shop) => {
      const node = map.get(shop.id)!
      if (shop.parent_id && map.has(shop.parent_id)) {
        // 有父节点，添加到父节点的 children 中
        const parent = map.get(shop.parent_id)!
        if (!parent.children) parent.children = []
        parent.children.push(node)
      } else {
        // 没有父节点或父节点不存在，作为根节点
        tree.push(node)
      }
    })

    return tree
  }

  // 获取设备列表
  const getTableData = async () => {
    loading.value = true
    try {
      const params = {
        page: pagination.page,
        page_size: pagination.pageSize,
        device_no: searchForm.device_no || undefined,
        device_name: searchForm.device_name || undefined,
        status: searchForm.status,
        batch_no: searchForm.batch_no || undefined,
        device_type: searchForm.device_type || undefined,
        manufacturer: searchForm.manufacturer || undefined
      }
      const res = await DeviceService.getDevices(params)
      if (res.code === 0 && res.data) {
        deviceList.value = res.data.items || []
        pagination.total = res.data.total || 0
      }
    } catch (error) {
      console.error(error)
      ElMessage.error('获取设备列表失败')
    } finally {
      loading.value = false
    }
  }

  // 重置搜索
  const handleReset = () => {
    Object.assign(searchForm, { ...initialSearchState })
    pagination.page = 1
    getTableData()
  }

  // 搜索
  const handleSearch = () => {
    pagination.page = 1
    getTableData()
  }

  // 刷新表格
  const handleRefresh = () => {
    getTableData()
  }

  // 处理表格分页变化
  const handleSizeChange = (newPageSize: number) => {
    pagination.pageSize = newPageSize
    getTableData()
  }

  const handleCurrentChange = (newCurrentPage: number) => {
    pagination.page = newCurrentPage
    getTableData()
  }

  // 处理选择变化
  const handleSelectionChange = (selection: Device[]) => {
    selectedDevices.value = selection
  }

  // 删除设备
  const deleteDevice = (row: Device) => {
    ElMessageBox.confirm(`确定删除设备 ${row.device_no} 吗？删除后将自动解绑所有卡。`, '删除确认', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'error'
    })
      .then(async () => {
        try {
          await DeviceService.deleteDevice(row.id)
          ElMessage.success('删除成功')
          await getTableData()
        } catch (error) {
          console.error(error)
          ElMessage.error('删除失败')
        }
      })
      .catch(() => {
        // 用户取消删除
      })
  }

  // 批量分配
  const handleBatchAllocate = async () => {
    if (selectedDevices.value.length === 0) {
      ElMessage.warning('请先选择要分配的设备')
      return
    }
    allocateForm.target_shop_id = undefined
    allocateForm.remark = ''
    allocateResult.value = null
    allocateDialogVisible.value = true
  }

  // 确认批量分配
  const handleConfirmAllocate = async () => {
    if (!allocateFormRef.value) return

    await allocateFormRef.value.validate(async (valid) => {
      if (valid) {
        allocateLoading.value = true
        try {
          const data = {
            device_ids: selectedDevices.value.map((d) => d.id),
            target_shop_id: allocateForm.target_shop_id!,
            remark: allocateForm.remark
          }
          const res = await DeviceService.allocateDevices(data)
          if (res.code === 0) {
            allocateResult.value = res.data
            if (res.data.fail_count === 0) {
              ElMessage.success('全部分配成功')
              setTimeout(() => {
                handleCloseAllocateDialog()
                getTableData()
              }, 1500)
            } else {
              ElMessage.warning(`部分分配失败，请查看失败详情`)
            }
          }
        } catch (error) {
          console.error(error)
          ElMessage.error('分配失败')
        } finally {
          allocateLoading.value = false
        }
      }
    })
  }

  // 关闭分配对话框
  const handleCloseAllocateDialog = () => {
    allocateDialogVisible.value = false
    allocateResult.value = null
    if (allocateFormRef.value) {
      allocateFormRef.value.resetFields()
    }
  }

  // 批量回收
  const handleBatchRecall = () => {
    if (selectedDevices.value.length === 0) {
      ElMessage.warning('请先选择要回收的设备')
      return
    }
    recallForm.remark = ''
    recallResult.value = null
    recallDialogVisible.value = true
  }

  // 确认批量回收
  const handleConfirmRecall = async () => {
    recallLoading.value = true
    try {
      const data = {
        device_ids: selectedDevices.value.map((d) => d.id),
        remark: recallForm.remark
      }
      const res = await DeviceService.recallDevices(data)
      if (res.code === 0) {
        recallResult.value = res.data
        if (res.data.fail_count === 0) {
          ElMessage.success('全部回收成功')
          setTimeout(() => {
            handleCloseRecallDialog()
            getTableData()
          }, 1500)
        } else {
          ElMessage.warning(`部分回收失败，请查看失败详情`)
        }
      }
    } catch (error) {
      console.error(error)
      ElMessage.error('回收失败')
    } finally {
      recallLoading.value = false
    }
  }

  // 关闭回收对话框
  const handleCloseRecallDialog = () => {
    recallDialogVisible.value = false
    recallResult.value = null
    recallForm.remark = ''
  }

  // 批量设置套餐系列
  const handleBatchSetSeries = async () => {
    if (selectedDevices.value.length === 0) {
      ElMessage.warning('请先选择要设置的设备')
      return
    }
    seriesBindingForm.series_id = undefined
    seriesBindingResult.value = null
    await loadPackageSeriesList()
    seriesBindingDialogVisible.value = true
  }

  // 加载套餐系列列表（支持名称搜索，默认20条）
  const loadPackageSeriesList = async (seriesName?: string) => {
    seriesLoading.value = true
    try {
      const params: any = {
        page: 1,
        page_size: 20,
        status: 1 // 只获取启用的
      }
      if (seriesName) {
        params.series_name = seriesName
      }
      const res = await PackageSeriesService.getPackageSeries(params)
      if (res.code === 0 && res.data.items) {
        packageSeriesList.value = res.data.items
      }
    } catch (error) {
      console.error('获取套餐系列列表失败:', error)
      ElMessage.error('获取套餐系列列表失败')
    } finally {
      seriesLoading.value = false
    }
  }

  // 搜索套餐系列
  const searchPackageSeries = async (query: string) => {
    await loadPackageSeriesList(query || undefined)
  }

  // 确认设置套餐系列绑定
  const handleConfirmSeriesBinding = async () => {
    if (!seriesBindingFormRef.value) return

    await seriesBindingFormRef.value.validate(async (valid) => {
      if (valid) {
        seriesBindingLoading.value = true
        try {
          const data = {
            device_ids: selectedDevices.value.map((d) => d.id),
            series_id: seriesBindingForm.series_id!
          }
          const res = await DeviceService.batchSetDeviceSeriesBinding(data)
          if (res.code === 0) {
            seriesBindingResult.value = res.data
            if (res.data.fail_count === 0) {
              ElMessage.success('全部设置成功')
              setTimeout(() => {
                handleCloseSeriesBindingDialog()
                getTableData()
              }, 1500)
            } else {
              ElMessage.warning(`部分设置失败，请查看失败详情`)
            }
          }
        } catch (error) {
          console.error(error)
        } finally {
          seriesBindingLoading.value = false
        }
      }
    })
  }

  // 关闭套餐系列绑定对话框
  const handleCloseSeriesBindingDialog = () => {
    seriesBindingDialogVisible.value = false
    seriesBindingResult.value = null
    if (seriesBindingFormRef.value) {
      seriesBindingFormRef.value.resetFields()
    }
  }

  // ========== 设备操作相关 ==========

  // 设备操作路由
  const handleDeviceOperation = (command: string, deviceNo: string) => {
    switch (command) {
      case 'view-cards':
        handleViewCardsByDeviceNo(deviceNo)
        break
      case 'reboot':
        handleRebootDevice(deviceNo)
        break
      case 'reset':
        handleResetDevice(deviceNo)
        break
      case 'speed-limit':
        showSpeedLimitDialog(deviceNo)
        break
      case 'switch-card':
        showSwitchCardDialog(deviceNo)
        break
      case 'set-wifi':
        showSetWiFiDialog(deviceNo)
        break
      case 'delete':
        handleDeleteDeviceByNo(deviceNo)
        break
    }
  }

  // 通过设备号查看卡片
  const handleViewCardsByDeviceNo = (deviceNo: string) => {
    const device = deviceList.value.find((d) => d.device_no === deviceNo)
    if (device) {
      handleViewCards(device)
    } else {
      ElMessage.error('未找到该设备')
    }
  }

  // 通过设备号删除设备
  const handleDeleteDeviceByNo = async (deviceNo: string) => {
    // 先根据设备号找到设备对象
    const device = deviceList.value.find((d) => d.device_no === deviceNo)
    if (device) {
      deleteDevice(device)
    } else {
      ElMessage.error('未找到该设备')
    }
  }

  // 重启设备
  const handleRebootDevice = (imei: string) => {
    ElMessageBox.confirm(`确定要重启设备 ${imei} 吗？`, '重启确认', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(async () => {
        try {
          const res = await DeviceService.rebootDevice(imei)
          if (res.code === 0) {
            ElMessage.success('重启指令已发送')
          } else {
            ElMessage.error(res.message || '重启失败')
          }
        } catch (error: any) {
          console.error('重启设备失败:', error)
          ElMessage.error(error?.message || '重启失败')
        }
      })
      .catch(() => {
        // 用户取消
      })
  }

  // 恢复出厂设置
  const handleResetDevice = (imei: string) => {
    ElMessageBox.confirm(
      `确定要恢复设备 ${imei} 的出厂设置吗？此操作将清除所有配置和数据！`,
      '恢复出厂设置确认',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'error'
      }
    )
      .then(async () => {
        try {
          const res = await DeviceService.resetDevice(imei)
          if (res.code === 0) {
            ElMessage.success('恢复出厂设置指令已发送')
          } else {
            ElMessage.error(res.message || '操作失败')
          }
        } catch (error: any) {
          console.error('恢复出厂设置失败:', error)
          ElMessage.error(error?.message || '操作失败')
        }
      })
      .catch(() => {
        // 用户取消
      })
  }

  // 显示设置限速对话框
  const showSpeedLimitDialog = (imei: string) => {
    currentOperatingDevice.value = imei
    speedLimitForm.download_speed = 1024
    speedLimitForm.upload_speed = 512
    speedLimitDialogVisible.value = true
  }

  // 确认设置限速
  const handleConfirmSpeedLimit = async () => {
    if (!speedLimitFormRef.value) return

    await speedLimitFormRef.value.validate(async (valid) => {
      if (valid) {
        speedLimitLoading.value = true
        try {
          const res = await DeviceService.setSpeedLimit(currentOperatingDevice.value, {
            download_speed: speedLimitForm.download_speed,
            upload_speed: speedLimitForm.upload_speed
          })
          if (res.code === 0) {
            ElMessage.success('限速设置成功')
            speedLimitDialogVisible.value = false
          } else {
            ElMessage.error(res.message || '设置失败')
          }
        } catch (error: any) {
          console.error('设置限速失败:', error)
          ElMessage.error(error?.message || '设置失败')
        } finally {
          speedLimitLoading.value = false
        }
      }
    })
  }

  // 显示切换SIM卡对话框
  const showSwitchCardDialog = (imei: string) => {
    currentOperatingDevice.value = imei
    switchCardForm.target_iccid = ''
    switchCardDialogVisible.value = true
  }

  // 确认切换SIM卡
  const handleConfirmSwitchCard = async () => {
    if (!switchCardFormRef.value) return

    await switchCardFormRef.value.validate(async (valid) => {
      if (valid) {
        switchCardLoading.value = true
        try {
          const res = await DeviceService.switchCard(currentOperatingDevice.value, {
            target_iccid: switchCardForm.target_iccid
          })
          if (res.code === 0) {
            ElMessage.success('切换SIM卡指令已发送')
            switchCardDialogVisible.value = false
          } else {
            ElMessage.error(res.message || '切换失败')
          }
        } catch (error: any) {
          console.error('切换SIM卡失败:', error)
          ElMessage.error(error?.message || '切换失败')
        } finally {
          switchCardLoading.value = false
        }
      }
    })
  }

  // 显示设置WiFi对话框
  const showSetWiFiDialog = (imei: string) => {
    currentOperatingDevice.value = imei
    setWiFiForm.enabled = 1
    setWiFiForm.ssid = ''
    setWiFiForm.password = ''
    setWiFiDialogVisible.value = true
  }

  // 确认设置WiFi
  const handleConfirmSetWiFi = async () => {
    if (!setWiFiFormRef.value) return

    await setWiFiFormRef.value.validate(async (valid) => {
      if (valid) {
        setWiFiLoading.value = true
        try {
          const res = await DeviceService.setWiFi(currentOperatingDevice.value, {
            enabled: setWiFiForm.enabled,
            ssid: setWiFiForm.ssid,
            password: setWiFiForm.password
          })
          if (res.code === 0) {
            ElMessage.success('WiFi设置成功')
            setWiFiDialogVisible.value = false
          } else {
            ElMessage.error(res.message || '设置失败')
          }
        } catch (error: any) {
          console.error('设置WiFi失败:', error)
          ElMessage.error(error?.message || '设置失败')
        } finally {
          setWiFiLoading.value = false
        }
      }
    })
  }

  // 设备操作菜单项配置
  const deviceOperationMenuItems = computed((): MenuItemType[] => {
    const items: MenuItemType[] = []

    // 添加查看卡片到菜单最前面
    if (hasAuth('device:view_cards')) {
      items.push({
        key: 'view-cards',
        label: '查看卡片'
      })
    }

    if (hasAuth('device:reboot')) {
      items.push({
        key: 'reboot',
        label: '重启设备'
      })
    }

    if (hasAuth('device:factory_reset')) {
      items.push({
        key: 'reset',
        label: '恢复出厂'
      })
    }

    if (hasAuth('device:set_speed_limit')) {
      items.push({
        key: 'speed-limit',
        label: '设置限速'
      })
    }

    if (hasAuth('device:switch_sim')) {
      items.push({
        key: 'switch-card',
        label: '切换SIM卡'
      })
    }

    if (hasAuth('device:set_wifi')) {
      items.push({
        key: 'set-wifi',
        label: '设置WiFi'
      })
    }

    if (hasAuth('device:delete')) {
      items.push({
        key: 'delete',
        label: '删除设备'
      })
    }

    return items
  })

  // 显示设备操作菜单
  const showDeviceOperationMenu = (e: MouseEvent, deviceNo: string) => {
    e.preventDefault()
    e.stopPropagation()
    currentOperatingDeviceNo.value = deviceNo
    deviceOperationMenuRef.value?.show(e)
  }

  // 处理设备操作菜单选择
  const handleDeviceOperationMenuSelect = (item: MenuItemType) => {
    const deviceNo = currentOperatingDeviceNo.value
    if (!deviceNo) return

    handleDeviceOperation(item.key, deviceNo)
  }

  // 处理表格行右键菜单
  const handleRowContextMenu = (row: Device, column: any, event: MouseEvent) => {
    showDeviceOperationMenu(event, row.device_no)
  }
</script>

<style scoped lang="scss">
  .device-list-page {
    height: 100%;
  }
</style>
