Forráskód Böngészése

feat:【IoT 物联网】完善设备消息的查询

YunaiV 11 hónapja
szülő
commit
f17404615e

+ 2 - 2
src/api/iot/device/device/index.ts

@@ -157,8 +157,8 @@ export const DeviceApi = {
   },
 
   // 查询设备日志分页
-  getDeviceLogPage: async (params: any) => {
-    return await request.get({ url: `/iot/device/log/page`, params })
+  getDeviceMessagePage: async (params: any) => {
+    return await request.get({ url: `/iot/device/message/page`, params })
   },
 
   // 获取设备 MQTT 连接参数

+ 0 - 51
src/api/iot/plugin/index.ts

@@ -1,51 +0,0 @@
-import request from '@/config/axios'
-
-// IoT 插件配置 VO
-export interface PluginConfigVO {
-  id: number // 主键ID
-  pluginKey: string // 插件标识
-  name: string // 插件名称
-  description: string // 描述
-  deployType: number // 部署方式
-  fileName: string // 插件包文件名
-  version: string // 插件版本
-  type: number // 插件类型
-  protocol: string // 设备插件协议类型
-  status: number // 状态
-  configSchema: string // 插件配置项描述信息
-  config: string // 插件配置信息
-  script: string // 插件脚本
-}
-
-// IoT 插件配置 API
-export const PluginConfigApi = {
-  // 查询插件配置分页
-  getPluginConfigPage: async (params: any) => {
-    return await request.get({ url: `/iot/plugin-config/page`, params })
-  },
-
-  // 查询插件配置详情
-  getPluginConfig: async (id: number) => {
-    return await request.get({ url: `/iot/plugin-config/get?id=` + id })
-  },
-
-  // 新增插件配置
-  createPluginConfig: async (data: PluginConfigVO) => {
-    return await request.post({ url: `/iot/plugin-config/create`, data })
-  },
-
-  // 修改插件配置
-  updatePluginConfig: async (data: PluginConfigVO) => {
-    return await request.put({ url: `/iot/plugin-config/update`, data })
-  },
-
-  // 删除插件配置
-  deletePluginConfig: async (id: number) => {
-    return await request.delete({ url: `/iot/plugin-config/delete?id=` + id })
-  },
-
-  // 修改插件状态
-  updatePluginStatus: async (data: any) => {
-    return await request.put({ url: `/iot/plugin-config/update-status`, data })
-  }
-}

+ 0 - 11
src/router/modules/remaining.ts

@@ -733,17 +733,6 @@ const remainingRouter: AppRouteRecordRaw[] = [
           activeMenu: '/iot/device/device'
         },
         component: () => import('@/views/iot/device/device/detail/index.vue')
-      },
-      {
-        path: 'plugin/detail/:id',
-        name: 'IoTPluginDetail',
-        meta: {
-          title: '插件详情',
-          noCache: true,
-          hidden: true,
-          activeMenu: '/iot/plugin'
-        },
-        component: () => import('@/views/iot/plugin/detail/index.vue')
       }
     ]
   }

+ 0 - 166
src/views/iot/device/device/detail/DeviceDetailsLog.vue

@@ -1,166 +0,0 @@
-<!-- 设备日志 -->
-<template>
-  <ContentWrap>
-    <!-- 搜索区域 -->
-    <el-form :model="queryParams" inline>
-      <el-form-item>
-        <el-select v-model="queryParams.type" placeholder="所有" class="!w-160px">
-          <el-option label="所有" value="" />
-          <!-- TODO @super:搞成枚举 -->
-          <el-option label="状态" value="state" />
-          <el-option label="事件" value="event" />
-          <el-option label="属性" value="property" />
-          <el-option label="服务" value="service" />
-        </el-select>
-      </el-form-item>
-      <el-form-item>
-        <el-input v-model="queryParams.identifier" placeholder="日志识符" class="!w-200px" />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" @click="handleQuery">
-          <Icon icon="ep:search" class="mr-5px" /> 搜索
-        </el-button>
-        <el-switch
-          size="large"
-          width="80"
-          v-model="autoRefresh"
-          class="ml-20px"
-          inline-prompt
-          active-text="定时刷新"
-          inactive-text="定时刷新"
-          style="--el-switch-on-color: #13ce66"
-        />
-      </el-form-item>
-    </el-form>
-
-    <!-- 日志列表 -->
-    <el-table v-loading="loading" :data="list" :stripe="true" class="whitespace-nowrap">
-      <el-table-column label="时间" align="center" prop="ts" width="180">
-        <template #default="scope">
-          {{ formatDate(scope.row.ts) }}
-        </template>
-      </el-table-column>
-      <el-table-column label="类型" align="center" prop="type" width="120" />
-      <!-- TODO @super:标识符需要翻译 -->
-      <el-table-column label="标识符" align="center" prop="identifier" width="120" />
-      <el-table-column label="内容" align="center" prop="content" :show-overflow-tooltip="true" />
-    </el-table>
-
-    <!-- 分页 -->
-    <div class="mt-10px flex justify-end">
-      <Pagination
-        :total="total"
-        v-model:page="queryParams.pageNo"
-        v-model:limit="queryParams.pageSize"
-        @pagination="getLogList"
-      />
-    </div>
-  </ContentWrap>
-</template>
-
-<script setup lang="ts">
-import { DeviceApi } from '@/api/iot/device/device'
-import { formatDate } from '@/utils/formatTime'
-
-const props = defineProps<{
-  deviceKey: string
-}>()
-
-// 查询参数
-const queryParams = reactive({
-  deviceKey: props.deviceKey,
-  type: '',
-  identifier: '',
-  pageNo: 1,
-  pageSize: 10
-})
-
-// 列表数据
-const loading = ref(false)
-const total = ref(0)
-const list = ref([])
-const autoRefresh = ref(false)
-let timer: any = null // TODO @super:autoRefreshEnable,autoRefreshTimer;对应上
-
-// 类型映射 TODO @super:需要删除么?
-const typeMap = {
-  lifetime: '生命周期',
-  state: '设备状态',
-  property: '属性',
-  event: '事件',
-  service: '服务'
-}
-
-/** 查询日志列表 */
-const getLogList = async () => {
-  if (!props.deviceKey) return
-  loading.value = true
-  try {
-    const data = await DeviceApi.getDeviceLogPage(queryParams)
-    total.value = data.total
-    list.value = data.list
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 获取日志名称 */
-const getLogName = (log: any) => {
-  const { type, identifier } = log
-  let name = '未知'
-
-  if (type === 'property') {
-    if (identifier === 'set_reply') name = '设置回复'
-    else if (identifier === 'report') name = '上报'
-    else if (identifier === 'set') name = '设置'
-  } else if (type === 'state') {
-    name = identifier === 'online' ? '上线' : '下线'
-  } else if (type === 'lifetime') {
-    name = identifier === 'register' ? '注册' : name
-  }
-
-  return `${name}(${identifier})`
-}
-
-/** 搜索操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getLogList()
-}
-
-/** 监听自动刷新 */
-watch(autoRefresh, (newValue) => {
-  if (newValue) {
-    timer = setInterval(() => {
-      getLogList()
-    }, 5000)
-  } else {
-    clearInterval(timer)
-    timer = null
-  }
-})
-
-/** 监听设备标识变化 */
-watch(
-  () => props.deviceKey,
-  (newValue) => {
-    if (newValue) {
-      handleQuery()
-    }
-  }
-)
-
-/** 组件卸载时清除定时器 */
-onBeforeUnmount(() => {
-  if (timer) {
-    clearInterval(timer)
-  }
-})
-
-/** 初始化 */
-onMounted(() => {
-  if (props.deviceKey) {
-    getLogList()
-  }
-})
-</script>

+ 169 - 0
src/views/iot/device/device/detail/DeviceDetailsMessage.vue

@@ -0,0 +1,169 @@
+<!-- 设备消息列表 -->
+<template>
+  <ContentWrap>
+    <!-- 搜索区域 -->
+    <el-form :model="queryParams" inline>
+      <el-form-item>
+        <el-select v-model="queryParams.method" placeholder="所有方法" class="!w-160px" clearable>
+          <el-option v-for="item in methodOptions" :key="item.value" :label="item.label" :value="item.value" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-select v-model="queryParams.upstream" placeholder="上行/下行" class="!w-160px" clearable>
+          <el-option label="上行" value="true" />
+          <el-option label="下行" value="false" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="handleQuery">
+          <Icon icon="ep:search" class="mr-5px" /> 搜索
+        </el-button>
+        <el-switch
+          size="large"
+          width="80"
+          v-model="autoRefresh"
+          class="ml-20px"
+          inline-prompt
+          active-text="定时刷新"
+          inactive-text="定时刷新"
+          style="--el-switch-on-color: #13ce66"
+        />
+      </el-form-item>
+    </el-form>
+
+    <!-- 消息列表 -->
+    <el-table v-loading="loading" :data="list" :stripe="true" class="whitespace-nowrap">
+      <el-table-column label="请求编号" align="center" prop="requestId" width="300" />
+      <el-table-column label="时间" align="center" prop="ts" width="180">
+        <template #default="scope">
+          {{ formatDate(scope.row.ts) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="上行/下行" align="center" prop="upstream" width="140">
+        <template #default="scope">
+          <el-tag :type="scope.row.upstream ? 'primary' : 'success'">
+            {{ scope.row.upstream ? '上行' : '下行' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="是否回复" align="center" prop="reply" width="140">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.reply" />
+        </template>
+      </el-table-column>
+      <el-table-column label="请求方法" align="center" prop="method" width="140">
+        <template #default="scope">
+          {{ methodOptions.find(item => item.value === scope.row.method)?.label }}
+        </template>
+      </el-table-column>
+             <el-table-column label="请求/响应数据" align="center" prop="params" :show-overflow-tooltip="true">
+         <template #default="scope">
+           <span v-if="scope.row.reply">
+            {{ `{"code":${scope.row.code},"msg":"${scope.row.msg}","data":${scope.row.data}\}` }}
+          </span>
+           <span v-else>{{ scope.row.params }}</span>
+         </template>
+       </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <div class="mt-10px flex justify-end">
+      <Pagination
+        :total="total"
+        v-model:page="queryParams.pageNo"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getMessageList"
+      />
+    </div>
+  </ContentWrap>
+</template>
+
+<script setup lang="ts">
+import { DICT_TYPE } from '@/utils/dict'
+import { DeviceApi } from '@/api/iot/device/device'
+import { formatDate } from '@/utils/formatTime'
+import { IotDeviceMessageMethodEnum } from '@/views/iot/utils/constants'
+
+const props = defineProps<{
+  deviceId: number
+}>()
+
+// 查询参数
+const queryParams = reactive({
+  deviceId: props.deviceId,
+  method: undefined,
+  upstream: undefined,
+  pageNo: 1,
+  pageSize: 10
+})
+
+// 列表数据
+const loading = ref(false)
+const total = ref(0)
+const list = ref([])
+const autoRefresh = ref(false)
+let autoRefreshTimer: any = null // TODO @super:autoRefreshEnable,autoRefreshTimer;对应上
+
+// 消息方法选项
+const methodOptions = computed(() => {
+  return Object.values(IotDeviceMessageMethodEnum).map(item => ({
+    label: item.name,
+    value: item.method
+  }))
+})
+
+/** 查询消息列表 */
+const getMessageList = async () => {
+  if (!props.deviceId) return
+  loading.value = true
+  try {
+    const data = await DeviceApi.getDeviceMessagePage(queryParams)
+    total.value = data.total
+    list.value = data.list
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getMessageList()
+}
+
+/** 监听自动刷新 */
+watch(autoRefresh, (newValue) => {
+  if (newValue) {
+    autoRefreshTimer = setInterval(() => {
+      getMessageList()
+    }, 5000)
+  } else {
+    clearInterval(autoRefreshTimer)
+    autoRefreshTimer = null
+  }
+})
+
+/** 监听设备标识变化 */
+watch(
+  () => props.deviceId,
+  (newValue) => {
+    if (newValue) {
+      handleQuery()
+    }
+  }
+)
+
+/** 组件卸载时清除定时器 */
+onBeforeUnmount(() => {
+  if (autoRefreshTimer) {
+    clearInterval(autoRefreshTimer)
+  }
+})
+
+/** 初始化 */
+onMounted(() => {
+  if (props.deviceId) {
+    getMessageList()
+  }
+})
+</script>

+ 2 - 2
src/views/iot/device/device/detail/DeviceDetailsSimulator.vue

@@ -134,7 +134,7 @@
       <el-col :span="12">
         <el-tabs type="border-card">
           <el-tab-pane label="设备日志">
-            <DeviceDetailsLog :device-key="device.deviceKey" />
+            <DeviceDetailsMessage :device-id="device.id" />
           </el-tab-pane>
         </el-tabs>
       </el-col>
@@ -146,7 +146,7 @@
 import { ProductVO } from '@/api/iot/product/product'
 import { SimulatorData, ThingModelApi } from '@/api/iot/thingmodel'
 import { DeviceApi, DeviceStateEnum, DeviceVO } from '@/api/iot/device/device'
-import DeviceDetailsLog from './DeviceDetailsLog.vue'
+import DeviceDetailsMessage from './DeviceDetailsMessage.vue'
 import { getDataTypeOptionsLabel } from '@/views/iot/thingmodel/config'
 import { DataDefinition } from '@/views/iot/thingmodel/components'
 

+ 5 - 6
src/views/iot/device/device/detail/index.vue

@@ -10,14 +10,12 @@
       <el-tab-pane label="设备信息" name="info">
         <DeviceDetailsInfo v-if="activeTab === 'info'" :product="product" :device="device" />
       </el-tab-pane>
-      <el-tab-pane label="Topic 列表" />
       <el-tab-pane label="物模型数据" name="model">
         <DeviceDetailsModel v-if="activeTab === 'model'" :product="product" :device="device" />
       </el-tab-pane>
       <el-tab-pane label="子设备管理" v-if="product.deviceType === DeviceTypeEnum.GATEWAY" />
-      <el-tab-pane label="设备影子" />
-      <el-tab-pane label="设备日志" name="log">
-        <DeviceDetailsLog v-if="activeTab === 'log'" :device-key="device.deviceKey" />
+      <el-tab-pane label="设备消息" name="log">
+        <DeviceDetailsMessage v-if="activeTab === 'log'" :device-id="device.id" />
       </el-tab-pane>
       <el-tab-pane label="模拟设备" name="simulator">
         <DeviceDetailsSimulator
@@ -43,7 +41,7 @@ import { DeviceTypeEnum, ProductApi, ProductVO } from '@/api/iot/product/product
 import DeviceDetailsHeader from './DeviceDetailsHeader.vue'
 import DeviceDetailsInfo from './DeviceDetailsInfo.vue'
 import DeviceDetailsModel from './DeviceDetailsModel.vue'
-import DeviceDetailsLog from './DeviceDetailsLog.vue'
+import DeviceDetailsMessage from './DeviceDetailsMessage.vue'
 import DeviceDetailsSimulator from './DeviceDetailsSimulator.vue'
 import DeviceDetailConfig from './DeviceDetailConfig.vue'
 
@@ -75,7 +73,8 @@ const getProductData = async (id: number) => {
 
 /** 初始化 */
 const { delView } = useTagsViewStore() // 视图操作
-const { currentRoute } = useRouter() // 路由
+const router = useRouter() // 路由
+const { currentRoute } = router
 onMounted(async () => {
   if (!id) {
     message.warning('参数错误,产品不能为空!')

+ 36 - 0
src/views/iot/utils/constants.ts

@@ -2,3 +2,39 @@
 export const IOT_PROVIDE_KEY = {
   PRODUCT: 'IOT_PRODUCT'
 }
+
+/**
+ * IoT 设备消息的方法枚举
+ */
+export const IotDeviceMessageMethodEnum = {
+  // ========== 设备状态 ==========
+  STATE_ONLINE: {
+    method: 'thing.state.online',
+    name: '设备上线',
+    upstream: true
+  },
+  STATE_OFFLINE: {
+    method: 'thing.state.offline',
+    name: '设备下线',
+    upstream: true
+  },
+
+  // ========== 设备属性 ==========
+  PROPERTY_POST: {
+    method: 'thing.property.post',
+    name: '属性上报',
+    upstream: true
+  },
+  PROPERTY_SET: {
+    method: 'thing.property.set',
+    name: '属性设置',
+    upstream: false
+  },
+
+  // ========== 设备事件 ==========
+  EVENT_POST: {
+    method: 'thing.event.post',
+    name: '事件上报',
+    upstream: true
+  }
+}