mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-11-04 20:28:45 +08:00 
			
		
		
		
	【新增】 IOT 设备管理,设备详情
This commit is contained in:
		@@ -15,6 +15,7 @@ export interface DeviceVO {
 | 
			
		||||
  lastOnlineTime: Date // 最后上线时间
 | 
			
		||||
  lastOfflineTime: Date // 最后离线时间
 | 
			
		||||
  activeTime: Date // 设备激活时间
 | 
			
		||||
  createTime: Date // 创建时间
 | 
			
		||||
  ip: string // 设备的 IP 地址
 | 
			
		||||
  firmwareVersion: string // 设备的固件版本
 | 
			
		||||
  deviceSecret: string // 设备密钥,用于设备认证,需安全存储
 | 
			
		||||
 
 | 
			
		||||
@@ -622,6 +622,17 @@ const remainingRouter: AppRouteRecordRaw[] = [
 | 
			
		||||
          activeMenu: '/iot/product'
 | 
			
		||||
        },
 | 
			
		||||
        component: () => import('@/views/iot/product/detail/index.vue')
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: 'device/detail/:id',
 | 
			
		||||
        name: 'IoTDeviceDetail',
 | 
			
		||||
        meta: {
 | 
			
		||||
          title: '设备详情',
 | 
			
		||||
          noCache: true,
 | 
			
		||||
          hidden: true,
 | 
			
		||||
          activeMenu: '/iot/device'
 | 
			
		||||
        },
 | 
			
		||||
        component: () => import('@/views/iot/device/detail/index.vue')
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										114
									
								
								src/views/iot/device/detail/DeviceDetailsHeader.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/views/iot/device/detail/DeviceDetailsHeader.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div class="flex items-start justify-between">
 | 
			
		||||
      <div>
 | 
			
		||||
        <el-col>
 | 
			
		||||
          <el-row>
 | 
			
		||||
            <span class="text-xl font-bold">{{ device.deviceName }}</span>
 | 
			
		||||
          </el-row>
 | 
			
		||||
        </el-col>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div>
 | 
			
		||||
        <!-- 右上:按钮 -->
 | 
			
		||||
        <el-button
 | 
			
		||||
          @click="openForm('update', device.id)"
 | 
			
		||||
          v-hasPermi="['iot:device:update']"
 | 
			
		||||
          v-if="product.status === 0"
 | 
			
		||||
        >
 | 
			
		||||
          编辑
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <ContentWrap class="mt-10px">
 | 
			
		||||
    <el-descriptions :column="5" direction="horizontal">
 | 
			
		||||
      <el-descriptions-item label="产品">
 | 
			
		||||
        <el-link @click="goToProductDetail(product.id)">{{ product.name }}</el-link>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="ProductKey">
 | 
			
		||||
        {{ product.productKey }}
 | 
			
		||||
        <el-button @click="copyToClipboard(product.productKey)">复制</el-button>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
  </ContentWrap>
 | 
			
		||||
  <!-- 表单弹窗:添加/修改 -->
 | 
			
		||||
  <DeviceForm ref="formRef" @success="emit('refresh')" />
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ref } from 'vue'
 | 
			
		||||
import DeviceForm from '@/views/iot/device/DeviceForm.vue'
 | 
			
		||||
import { ProductVO } from '@/api/iot/product'
 | 
			
		||||
import { DeviceVO } from '@/api/iot/device'
 | 
			
		||||
import { useRouter } from 'vue-router'
 | 
			
		||||
 | 
			
		||||
const message = useMessage()
 | 
			
		||||
const router = useRouter()
 | 
			
		||||
 | 
			
		||||
// 操作修改
 | 
			
		||||
const formRef = ref()
 | 
			
		||||
const openForm = (type: string, id?: number) => {
 | 
			
		||||
  formRef.value.open(type, id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const { product, device } = defineProps<{ product: ProductVO; device: DeviceVO }>()
 | 
			
		||||
const emit = defineEmits(['refresh'])
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 将文本复制到剪贴板
 | 
			
		||||
 *
 | 
			
		||||
 * @param text 需要复制的文本
 | 
			
		||||
 */
 | 
			
		||||
const copyToClipboard = async (text: string) => {
 | 
			
		||||
  if (!navigator.clipboard) {
 | 
			
		||||
    // 浏览器不支持 Clipboard API,使用回退方法
 | 
			
		||||
    const textarea = document.createElement('textarea')
 | 
			
		||||
    textarea.value = text
 | 
			
		||||
    // 防止页面滚动
 | 
			
		||||
    textarea.style.position = 'fixed'
 | 
			
		||||
    textarea.style.top = '0'
 | 
			
		||||
    textarea.style.left = '0'
 | 
			
		||||
    textarea.style.width = '2em'
 | 
			
		||||
    textarea.style.height = '2em'
 | 
			
		||||
    textarea.style.padding = '0'
 | 
			
		||||
    textarea.style.border = 'none'
 | 
			
		||||
    textarea.style.outline = 'none'
 | 
			
		||||
    textarea.style.boxShadow = 'none'
 | 
			
		||||
    textarea.style.background = 'transparent'
 | 
			
		||||
    document.body.appendChild(textarea)
 | 
			
		||||
    textarea.focus()
 | 
			
		||||
    textarea.select()
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      const successful = document.execCommand('copy')
 | 
			
		||||
      if (successful) {
 | 
			
		||||
        message.success('复制成功!')
 | 
			
		||||
      } else {
 | 
			
		||||
        message.error('复制失败,请手动复制')
 | 
			
		||||
      }
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      console.error('Fallback: Oops, unable to copy', err)
 | 
			
		||||
      message.error('复制失败,请手动复制')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    document.body.removeChild(textarea)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    await navigator.clipboard.writeText(text)
 | 
			
		||||
    message.success('复制成功!')
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.error('Async: Could not copy text: ', err)
 | 
			
		||||
    message.error('复制失败,请手动复制')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 跳转到产品详情页面
 | 
			
		||||
 *
 | 
			
		||||
 * @param productId 产品 ID
 | 
			
		||||
 */
 | 
			
		||||
const goToProductDetail = (productId: number) => {
 | 
			
		||||
  router.push({ name: 'IoTProductDetail', params: { id: productId } })
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										175
									
								
								src/views/iot/device/detail/DeviceDetailsInfo.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								src/views/iot/device/detail/DeviceDetailsInfo.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,175 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <el-collapse v-model="activeNames">
 | 
			
		||||
      <el-descriptions :column="3" title="设备信息">
 | 
			
		||||
        <el-descriptions-item label="产品名称">{{ product.name }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="ProductKey"
 | 
			
		||||
          >{{ product.productKey }}
 | 
			
		||||
          <el-button @click="copyToClipboard(product.productKey)">复制</el-button>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="设备类型">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE" :value="product.deviceType" />
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="DeviceName"
 | 
			
		||||
          >{{ device.deviceName }}
 | 
			
		||||
          <el-button @click="copyToClipboard(device.deviceName)">复制</el-button>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="备注名称">{{ device.nickname }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="创建时间">{{
 | 
			
		||||
          formatDate(device.createTime)
 | 
			
		||||
        }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="激活时间">{{
 | 
			
		||||
          formatDate(device.activeTime)
 | 
			
		||||
        }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="最后上线时间">{{
 | 
			
		||||
          formatDate(device.lastOnlineTime)
 | 
			
		||||
        }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="当前状态">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.IOT_DEVICE_STATUS" :value="device.status" />
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="最后离线时间" :span="3">{{
 | 
			
		||||
          formatDate(device.lastOfflineTime)
 | 
			
		||||
        }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="MQTT 连接参数">
 | 
			
		||||
          <el-button type="primary" @click="openMqttParams">查看</el-button>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
    </el-collapse>
 | 
			
		||||
 | 
			
		||||
    <!-- MQTT 连接参数弹框 -->
 | 
			
		||||
    <Dialog
 | 
			
		||||
      title="MQTT 连接参数"
 | 
			
		||||
      v-model="mqttDialogVisible"
 | 
			
		||||
      width="50%"
 | 
			
		||||
      :before-close="handleCloseMqttDialog"
 | 
			
		||||
    >
 | 
			
		||||
      <el-form :model="mqttParams" label-width="120px">
 | 
			
		||||
        <el-form-item label="clientId">
 | 
			
		||||
          <el-input v-model="mqttParams.mqttClientId" readonly>
 | 
			
		||||
            <template #append>
 | 
			
		||||
              <el-button @click="copyToClipboard(mqttParams.mqttClientId)" type="primary">
 | 
			
		||||
                <Icon icon="ph:copy" />
 | 
			
		||||
              </el-button>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="username">
 | 
			
		||||
          <el-input v-model="mqttParams.mqttUsername" readonly>
 | 
			
		||||
            <template #append>
 | 
			
		||||
              <el-button @click="copyToClipboard(mqttParams.mqttUsername)" type="primary">
 | 
			
		||||
                <Icon icon="ph:copy" />
 | 
			
		||||
              </el-button>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="passwd">
 | 
			
		||||
          <el-input v-model="mqttParams.mqttPassword" readonly type="password">
 | 
			
		||||
            <template #append>
 | 
			
		||||
              <el-button @click="copyToClipboard(mqttParams.mqttPassword)" type="primary">
 | 
			
		||||
                <Icon icon="ph:copy" />
 | 
			
		||||
              </el-button>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <template #footer>
 | 
			
		||||
        <el-button @click="mqttDialogVisible = false">关闭</el-button>
 | 
			
		||||
      </template>
 | 
			
		||||
    </Dialog>
 | 
			
		||||
  </ContentWrap>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ref } from 'vue'
 | 
			
		||||
import { DICT_TYPE } from '@/utils/dict'
 | 
			
		||||
import { ProductVO } from '@/api/iot/product'
 | 
			
		||||
import { formatDate } from '@/utils/formatTime'
 | 
			
		||||
import { DeviceVO } from '@/api/iot/device'
 | 
			
		||||
 | 
			
		||||
// 消息提示
 | 
			
		||||
const message = useMessage()
 | 
			
		||||
 | 
			
		||||
// 路由实例
 | 
			
		||||
const router = useRouter()
 | 
			
		||||
 | 
			
		||||
// 定义 Props
 | 
			
		||||
const { product, device } = defineProps<{ product: ProductVO; device: DeviceVO }>()
 | 
			
		||||
 | 
			
		||||
// 定义 Emits
 | 
			
		||||
const emit = defineEmits(['refresh'])
 | 
			
		||||
 | 
			
		||||
// 展示的折叠面板
 | 
			
		||||
const activeNames = ref(['basicInfo'])
 | 
			
		||||
 | 
			
		||||
// 复制到剪贴板方法
 | 
			
		||||
const copyToClipboard = async (text: string) => {
 | 
			
		||||
  if (!navigator.clipboard) {
 | 
			
		||||
    // 浏览器不支持 Clipboard API,使用回退方法
 | 
			
		||||
    const textarea = document.createElement('textarea')
 | 
			
		||||
    textarea.value = text
 | 
			
		||||
    // 防止页面滚动
 | 
			
		||||
    textarea.style.position = 'fixed'
 | 
			
		||||
    textarea.style.top = '0'
 | 
			
		||||
    textarea.style.left = '0'
 | 
			
		||||
    textarea.style.width = '2em'
 | 
			
		||||
    textarea.style.height = '2em'
 | 
			
		||||
    textarea.style.padding = '0'
 | 
			
		||||
    textarea.style.border = 'none'
 | 
			
		||||
    textarea.style.outline = 'none'
 | 
			
		||||
    textarea.style.boxShadow = 'none'
 | 
			
		||||
    textarea.style.background = 'transparent'
 | 
			
		||||
    document.body.appendChild(textarea)
 | 
			
		||||
    textarea.focus()
 | 
			
		||||
    textarea.select()
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      const successful = document.execCommand('copy')
 | 
			
		||||
      if (successful) {
 | 
			
		||||
        message.success('复制成功!')
 | 
			
		||||
      } else {
 | 
			
		||||
        message.error('复制失败,请手动复制')
 | 
			
		||||
      }
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      console.error('Fallback: Oops, unable to copy', err)
 | 
			
		||||
      message.error('复制失败,请手动复制')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    document.body.removeChild(textarea)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    await navigator.clipboard.writeText(text)
 | 
			
		||||
    message.success('复制成功!')
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.error('Async: Could not copy text: ', err)
 | 
			
		||||
    message.error('复制失败,请手动复制')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 定义 MQTT 弹框的可见性
 | 
			
		||||
const mqttDialogVisible = ref(false)
 | 
			
		||||
 | 
			
		||||
// 定义 MQTT 参数对象
 | 
			
		||||
const mqttParams = ref({
 | 
			
		||||
  mqttClientId: '',
 | 
			
		||||
  mqttUsername: '',
 | 
			
		||||
  mqttPassword: ''
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
// 打开 MQTT 参数弹框的方法
 | 
			
		||||
const openMqttParams = () => {
 | 
			
		||||
  mqttParams.value = {
 | 
			
		||||
    mqttClientId: device.mqttClientId || 'N/A',
 | 
			
		||||
    mqttUsername: device.mqttUsername || 'N/A',
 | 
			
		||||
    mqttPassword: device.mqttPassword || 'N/A'
 | 
			
		||||
  }
 | 
			
		||||
  mqttDialogVisible.value = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 关闭 MQTT 弹框的方法
 | 
			
		||||
const handleCloseMqttDialog = () => {
 | 
			
		||||
  mqttDialogVisible.value = false
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										66
									
								
								src/views/iot/device/detail/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/views/iot/device/detail/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <DeviceDetailsHeader
 | 
			
		||||
    :loading="loading"
 | 
			
		||||
    :product="product"
 | 
			
		||||
    :device="device"
 | 
			
		||||
    @refresh="getDeviceData(id)"
 | 
			
		||||
  />
 | 
			
		||||
  <el-col>
 | 
			
		||||
    <el-tabs>
 | 
			
		||||
      <el-tab-pane label="设备信息">
 | 
			
		||||
        <DeviceDetailsInfo :product="product" :device="device" />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="Topic 列表" />
 | 
			
		||||
      <el-tab-pane label="物模型数据" />
 | 
			
		||||
      <el-tab-pane label="子设备管理" />
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
  </el-col>
 | 
			
		||||
</template>
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { useTagsViewStore } from '@/store/modules/tagsView'
 | 
			
		||||
import { DeviceApi, DeviceVO } from '@/api/iot/device'
 | 
			
		||||
import { ProductApi, ProductVO } from '@/api/iot/product'
 | 
			
		||||
import DeviceDetailsHeader from '@/views/iot/device/detail/DeviceDetailsHeader.vue'
 | 
			
		||||
import DeviceDetailsInfo from '@/views/iot/device/detail/DeviceDetailsInfo.vue'
 | 
			
		||||
 | 
			
		||||
defineOptions({ name: 'IoTDeviceDetail' })
 | 
			
		||||
 | 
			
		||||
const route = useRoute()
 | 
			
		||||
const message = useMessage()
 | 
			
		||||
const id = Number(route.params.id) // 编号
 | 
			
		||||
const loading = ref(true) // 加载中
 | 
			
		||||
const product = ref<ProductVO>({} as ProductVO) // 产品详情
 | 
			
		||||
const device = ref<DeviceVO>({} as DeviceVO) // 设备详情
 | 
			
		||||
 | 
			
		||||
/** 获取设备详情 */
 | 
			
		||||
const getDeviceData = async (id: number) => {
 | 
			
		||||
  loading.value = true
 | 
			
		||||
  try {
 | 
			
		||||
    device.value = await DeviceApi.getDevice(id)
 | 
			
		||||
    console.log(product.value)
 | 
			
		||||
    await getProductData(device.value.productId)
 | 
			
		||||
  } finally {
 | 
			
		||||
    loading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 获取产品详情 */
 | 
			
		||||
const getProductData = async (id: number) => {
 | 
			
		||||
  product.value = await ProductApi.getProduct(id)
 | 
			
		||||
  console.log(product.value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 获取物模型 */
 | 
			
		||||
 | 
			
		||||
/** 初始化 */
 | 
			
		||||
const { delView } = useTagsViewStore() // 视图操作
 | 
			
		||||
const { currentRoute } = useRouter() // 路由
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
  if (!id) {
 | 
			
		||||
    message.warning('参数错误,产品不能为空!')
 | 
			
		||||
    delView(unref(currentRoute))
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  await getDeviceData(id)
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
@@ -96,7 +96,11 @@
 | 
			
		||||
  <!-- 列表 -->
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
 | 
			
		||||
      <el-table-column label="DeviceName" align="center" prop="deviceName" />
 | 
			
		||||
      <el-table-column label="DeviceName" align="center" prop="deviceName">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <el-link @click="openDetail(scope.row.id)">{{ scope.row.deviceName }}</el-link>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="备注名称" align="center" prop="nickname" />
 | 
			
		||||
      <el-table-column label="设备所属产品" align="center" prop="productId">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
@@ -122,6 +126,14 @@
 | 
			
		||||
      />
 | 
			
		||||
      <el-table-column label="操作" align="center" min-width="120px">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <el-button
 | 
			
		||||
            link
 | 
			
		||||
            type="primary"
 | 
			
		||||
            @click="openDetail(scope.row.id)"
 | 
			
		||||
            v-hasPermi="['iot:product:query']"
 | 
			
		||||
          >
 | 
			
		||||
            查看
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button
 | 
			
		||||
            link
 | 
			
		||||
            type="primary"
 | 
			
		||||
@@ -157,8 +169,7 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 | 
			
		||||
import { dateFormatter } from '@/utils/formatTime'
 | 
			
		||||
import download from '@/utils/download'
 | 
			
		||||
import { DeviceApi, DeviceUpdateStatusVO, DeviceVO } from '@/api/iot/device'
 | 
			
		||||
import { DeviceApi, DeviceVO } from '@/api/iot/device'
 | 
			
		||||
import DeviceForm from './DeviceForm.vue'
 | 
			
		||||
import { ProductApi } from '@/api/iot/product'
 | 
			
		||||
 | 
			
		||||
@@ -223,6 +234,12 @@ const openForm = (type: string, id?: number) => {
 | 
			
		||||
  formRef.value.open(type, id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 打开详情 */
 | 
			
		||||
const { currentRoute, push } = useRouter()
 | 
			
		||||
const openDetail = (id: number) => {
 | 
			
		||||
  push({ name: 'IoTDeviceDetail', params: { id } })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 删除按钮操作 */
 | 
			
		||||
const handleDelete = async (id: number) => {
 | 
			
		||||
  try {
 | 
			
		||||
@@ -235,21 +252,6 @@ const handleDelete = async (id: number) => {
 | 
			
		||||
    await getList()
 | 
			
		||||
  } catch {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 导出按钮操作 */
 | 
			
		||||
const handleExport = async () => {
 | 
			
		||||
  try {
 | 
			
		||||
    // 导出的二次确认
 | 
			
		||||
    await message.exportConfirm()
 | 
			
		||||
    // 发起导出
 | 
			
		||||
    exportLoading.value = true
 | 
			
		||||
    const data = await DeviceApi.exportDevice(queryParams)
 | 
			
		||||
    download.excel(data, '设备.xls')
 | 
			
		||||
  } catch {
 | 
			
		||||
  } finally {
 | 
			
		||||
    exportLoading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
/** 查询字典下拉列表 */
 | 
			
		||||
const products = ref()
 | 
			
		||||
const getProducts = async () => {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user