浏览代码

feat:deviceLog and deviceSimulator

alwayssuper 7 月之前
父节点
当前提交
c9e00d97eb

+ 1 - 1
.vscode/settings.json

@@ -87,7 +87,7 @@
     "source.fixAll.stylelint": "explicit"
   },
   "[vue]": {
-    "editor.defaultFormatter": "esbenp.prettier-vscode"
+    "editor.defaultFormatter": "octref.vetur"
   },
   "i18n-ally.localesPaths": ["src/locales"],
   "i18n-ally.keystyle": "nested",

+ 5 - 1
src/api/iot/device/device/index.ts

@@ -69,7 +69,7 @@ export interface SimulatorDataVO {
   deviceKey: string
   type: string
   subType: string
-  reportTime: string
+  reportTime: number // 时间戳
   content: string  // 存储 JSON 字符串
 }
 
@@ -151,5 +151,9 @@ export const DeviceApi = {
   // 模拟设备
   simulatorDevice: async (data: SimulatorDataVO) => {
     return await request.post({ url: `/iot/device/data/simulator`, data })
+  },
+  //查询设备日志分页
+  getDeviceLogPage: async (params: any) => {
+    return await request.get({ url: `/iot/device/data/log/page`, params })
   }
 }

+ 7 - 0
src/api/iot/thingmodel/index.ts

@@ -17,6 +17,13 @@ export interface ThingModelData {
   service?: ThingModelService // 服务
 }
 
+/**
+ * IoT 模拟设备
+ */
+export interface SimulatorData extends ThingModelData {
+  simulateValue?: string | number // 用于存储模拟值
+}
+
 /**
  * ThingModelProperty 类型
  */

+ 41 - 44
src/views/iot/device/device/detail/DeviceDetailsLog.vue

@@ -29,27 +29,18 @@
           {{ formatDate(scope.row.time) }}
         </template>
       </el-table-column>
-      <el-table-column label="类型" align="center" prop="type" width="120">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.IOT_MESSAGE_TYPE" :value="scope.row.type" />
-        </template>
-      </el-table-column>
-      <el-table-column label="名称(标识符)" align="center" prop="name" />
+      <el-table-column label="类型" align="center" prop="type" width="120" />
+      <el-table-column label="名称(标识符)" align="center" prop="subType" width="120" />
       <el-table-column label="内容" align="center" prop="content" :show-overflow-tooltip="true" />
     </el-table>
 
     <!-- 分页 -->
     <div class="mt-10px flex justify-end">
-      <el-pagination
-        v-model:current-page="queryParams.pageNo"
-        v-model:page-size="queryParams.pageSize"
+      <Pagination
         :total="total"
-        :page-sizes="[10, 20, 50, 100]"
-        small
-        background
-        layout="total, sizes, prev, pager, next, jumper"
-        @size-change="handleQuery"
-        @current-change="handleQuery"
+        v-model:page="queryParams.pageNo"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getLogList"
       />
     </div>
   </ContentWrap>
@@ -61,15 +52,17 @@ import { DICT_TYPE } from '@/utils/dict'
 import { formatDate } from '@/utils/formatTime'
 
 const props = defineProps<{
-  deviceId: number
+  deviceKey: number
 }>()
 
-// 查询参数
+//TODO:后续看看使用什么查询条件  目前后端是留了时间范围  type  subType
+// 查询参数 
 const queryParams = reactive({
-  type: '',
-  keyword: '',
+  deviceKey: props.deviceKey,
+  // type: '',
+  // keyword: '',
   pageNo: 1,
-  pageSize: 20
+  pageSize: 10
 })
 
 // 列表数据
@@ -90,30 +83,31 @@ const typeMap = {
 
 /** 查询日志列表 */
 const getLogList = async () => {
-  // if (!props.deviceId) return
-  // loading.value = true
-  // try {
-  //   const res = await DeviceApi.getDeviceLogs(props.deviceId, queryParams)
-  //   total.value = res.total
-  //   logList.value = res.list.map((item: any) => {
-  //     const log = {
-  //       time: item.time,
-  //       type: typeMap[item.type as keyof typeof typeMap] || item.type,
-  //       name: getLogName(item),
-  //       content: item.content
-  //     }
-  //     return log
-  //   })
-  // } finally {
-  //   loading.value = false
-  // }
+  if (!props.deviceKey) return
+  loading.value = true
+  try {
+    const res = await DeviceApi.getDeviceLogPage(queryParams)
+    total.value = res.total
+    logList.value = res.list.map((item: any) => {
+      const log = {
+        time: item.reportTime,
+        type: item.type,
+        subType: item.subType,
+        content: item.content
+      }
+      return log
+    })
+    console.log(logList.value)
+  } 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 = '上报'
@@ -123,7 +117,7 @@ const getLogName = (log: any) => {
   } else if (type === 'lifetime') {
     name = identifier === 'register' ? '注册' : name
   }
-  
+
   return `${name}(${identifier})`
 }
 
@@ -146,11 +140,14 @@ watch(autoRefresh, (newValue) => {
 })
 
 /** 监听设备ID变化 */
-watch(() => props.deviceId, (newValue) => {
-  if (newValue) {
-    handleQuery()
+watch(
+  () => props.deviceKey,
+  (newValue) => {
+    if (newValue) {
+      handleQuery()
+    }
   }
-})
+)
 
 /** 组件卸载时清除定时器 */
 onBeforeUnmount(() => {
@@ -161,7 +158,7 @@ onBeforeUnmount(() => {
 
 /** 初始化 */
 onMounted(() => {
-  if (props.deviceId) {
+  if (props.deviceKey) {
     getLogList()
   }
 })

+ 88 - 95
src/views/iot/device/device/detail/DeviceDetailsSimulator.vue

@@ -97,7 +97,7 @@
               <!-- 事件上报 -->
               <el-tab-pane label="事件上报" name="event">
                 <ContentWrap>
-                  <el-table v-loading="loading" :data="eventList" :stripe="true">
+                  <!-- <el-table v-loading="loading" :data="eventList" :stripe="true">
                     <el-table-column label="功能名称" align="center" prop="name" />
                     <el-table-column label="标识符" align="center" prop="identifier" />
                     <el-table-column label="数据类型" align="center" prop="dataType" />
@@ -115,7 +115,7 @@
                   </el-table>
                   <div class="mt-10px">
                     <el-button type="primary" @click="handleEventReport">发送</el-button>
-                  </div>
+                  </div> -->
                 </ContentWrap>
               </el-tab-pane>
 
@@ -141,7 +141,7 @@
               <!-- 属性调试 -->
               <el-tab-pane label="属性调试" name="propertyDebug">
                 <ContentWrap>
-                  <el-table v-loading="loading" :data="propertyList" :stripe="true">
+                  <!-- <el-table v-loading="loading" :data="propertyList" :stripe="true">
                     <el-table-column label="功能名称" align="center" prop="name" />
                     <el-table-column label="标识符" align="center" prop="identifier" />
                     <el-table-column label="数据类型" align="center" prop="dataType" />
@@ -159,7 +159,7 @@
                   </el-table>
                   <div class="mt-10px">
                     <el-button type="primary" @click="handlePropertyGet">获取</el-button>
-                  </div>
+                  </div> -->
                 </ContentWrap>
               </el-tab-pane>
 
@@ -178,7 +178,7 @@
       <el-col :span="12">
         <el-tabs type="border-card">
           <el-tab-pane label="设备日志">
-            <DeviceDetailsLog :device-id="device.id" />
+            <DeviceDetailsLog :deviceKey="device.deviceKey" />
           </el-tab-pane>
         </el-tabs>
       </el-col>
@@ -188,7 +188,7 @@
 
 <script setup lang="ts">
 import { ProductVO } from '@/api/iot/product/product'
-import { ThingModelApi, ThingModelData } from '@/api/iot/thingmodel'
+import { ThingModelApi, ThingModelData,SimulatorData } from '@/api/iot/thingmodel'
 import { DeviceApi, DeviceVO,SimulatorDataVO } from '@/api/iot/device/device'
 import DeviceDetailsLog from './DeviceDetailsLog.vue'
 import {
@@ -212,9 +212,6 @@ const dataTypeOptionsLabel = computed(() => (value: string) => getDataTypeOption
 const props = defineProps<{ product: ProductVO; device: DeviceVO }>()
 const list = ref<SimulatorData[]>([]) // 物模型列表的数据
 
-interface SimulatorData extends ThingModelData {
-  simulateValue?: string | number // 用于存储模拟值
-}
 /** 查询列表 */
 const getList = async () => {
   loading.value = true
@@ -231,33 +228,33 @@ const getList = async () => {
   }
 }
 
-// 功能列表数据结构定义
-interface TableItem {
-  name: string
-  identifier: string
-  value: string | number
-}
+// // 功能列表数据结构定义
+// interface TableItem {
+//   name: string
+//   identifier: string
+//   value: string | number
+// }
 
-// 添加计算属性来过滤物模型数据
-const propertyList = computed(() => {
-  return list.value
-    .filter((item) => item.type === 'property')
-    .map((item) => ({
-      name: item.name,
-      identifier: item.identifier,
-      value: ''
-    }))
-})
+// // 添加计算属性来过滤物模型数据
+// const propertyList = computed(() => {
+//   return list.value
+//     .filter((item) => item.type === 'property')
+//     .map((item) => ({
+//       name: item.name,
+//       identifier: item.identifier,
+//       value: ''
+//     }))
+// })
 
-const eventList = computed(() => {
-  return list.value
-    .filter((item) => item.type === 'event')
-    .map((item) => ({
-      name: item.name,
-      identifier: item.identifier,
-      value: ''
-    }))
-})
+// const eventList = computed(() => {
+//   return list.value
+//     .filter((item) => item.type === 'event')
+//     .map((item) => ({
+//       name: item.name,
+//       identifier: item.identifier,
+//       value: ''
+//     }))
+// })
 
 // 监听标签页变化 todo:后续改成查询字典
 watch(
@@ -291,16 +288,16 @@ watch(
   { immediate: true }
 )
 
-interface ReportData {
-  productKey: string
-  deviceKey: string
-  type: string
-  subType: string
-  reportTime: string
-  content: string  // 改为 string 类型,存储 JSON 字符串
-}
+// interface ReportData {
+//   productKey: string
+//   deviceKey: string
+//   type: string
+//   subType: string
+//   reportTime: string
+//   content: string  // 改为 string 类型,存储 JSON 字符串
+// }
 
-// 处理属性上报
+// 处理属性上报    TODO:数据类型效验
 const handlePropertyReport = async () => {
   const contentObj: Record<string, any> = {}
   list.value.forEach((item) => {
@@ -315,71 +312,67 @@ const handlePropertyReport = async () => {
     deviceKey: props.device.deviceKey,
     type: 'property',
     subType: 'report',
-    reportTime: new Date().toISOString(),
+    reportTime: Date.now(), // 将 reportTime 变为数字类型的时间戳
     content: JSON.stringify(contentObj)  // 转换为 JSON 字符串
   }
 
   try {
-    // TODO: 调用API发送数据
-    console.log('上报数据:', reportData)
-    console.log('reportData.content', reportData.content)
-    const data = await DeviceApi.simulatorDevice(reportData)
-    console.log(data)
-    message.success('属性上报成功123')
+    await DeviceApi.simulatorDevice(reportData)
+    message.success('属性上报成功')
   } catch (error) {
     message.error('属性上报失败')
   }
 }
 
-// 处理事件上报
-const handleEventReport = async () => {
-  const contentObj: Record<string, any> = {}
-  list.value
-    .filter(item => item.type === 'event')
-    .forEach((item) => {
-      if (item.simulateValue !== undefined && item.simulateValue !== '') {
-        contentObj[item.identifier] = item.simulateValue
-      }
-    })
+// // 处理事件上报
+// const handleEventReport = async () => {
+//   const contentObj: Record<string, any> = {}
+//   list.value
+//     .filter(item => item.type === 'event')
+//     .forEach((item) => {
+//       if (item.simulateValue !== undefined && item.simulateValue !== '') {
+//         contentObj[item.identifier] = item.simulateValue
+//       }
+//     })
 
-  const reportData: ReportData = {
-    productKey: props.product.productKey,
-    deviceKey: props.device.deviceKey,
-    type: 'event',
-    subType: list.value.find(item => item.type === 'event')?.identifier || '',
-    reportTime: new Date().toISOString(),
-    content: JSON.stringify(contentObj)  // 转换为 JSON 字符串
-  }
+//   const reportData: ReportData = {
+//     productKey: props.product.productKey,
+//     deviceKey: props.device.deviceKey,
+//     type: 'event',
+//     subType: list.value.find(item => item.type === 'event')?.identifier || '',
+//     reportTime: new Date().toISOString(),
+//     content: JSON.stringify(contentObj)  // 转换为 JSON 字符串
+//   }
 
-  try {
-    // TODO: 调用API发送数据
-    console.log('上报数据:', reportData)
-    message.success('事件上报成功')
-  } catch (error) {
-    message.error('事件上报失败')
-  }
-}
+//   try {
+//     // TODO: 调用API发送数据
+//     console.log('上报数据:', reportData)
+//     message.success('事件上报成功')
+//   } catch (error) {
+//     message.error('事件上报失败')
+//   }
+// }
 
-// 处理设备状态变更
-const handleDeviceState = async (state: 'online' | 'offline') => {
-  const reportData: ReportData = {
-    productKey: props.product.productKey,
-    deviceKey: props.device.deviceKey,
-    type: 'status',
-    subType: state,
-    reportTime: new Date().toISOString(),
-    content: JSON.stringify({ status: state })  // 转换为 JSON 字符串
-  }
+// // 处理设备状态变更
+// const handleDeviceState = async (state: 'online' | 'offline') => {
+//   const reportData: ReportData = {
+//     productKey: props.product.productKey,
+//     deviceKey: props.device.deviceKey,
+//     type: 'status',
+//     subType: state,
+//     reportTime: new Date().toISOString(),
+//     content: JSON.stringify({ status: state })  // 转换为 JSON 字符串
+//   }
 
-  try {
-    // TODO: 调用API发送数据
-    console.log('状态变更数据:', reportData)
-    console.log('reportData.content111111111', reportData.content)
-    message.success(`设备${state === 'online' ? '上线' : '下线'}成功`)
-  } catch (error) {
-    message.error(`设备${state === 'online' ? '上线' : '下线'}失败`)
-  }
-}
+//   try {
+//     // TODO: 调用API发送数据
+//     console.log('状态变更数据:', reportData)
+//     console.log('reportData.content111111111', reportData.content)
+//     message.success(`设备${state === 'online' ? '上线' : '下线'}成功`)
+//   } catch (error) {
+//     message.error(`设备${state === 'online' ? '上线' : '下线'}失败`)
+//   }
+// }
 
 // 处理属性获取
 const handlePropertyGet = async () => {

+ 1 - 1
src/views/iot/device/device/detail/index.vue

@@ -17,7 +17,7 @@
       <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'" :product="product" :device="device" />
+        <DeviceDetailsLog v-if="activeTab === 'log'"  :deviceKey="device.deviceKey" />
       </el-tab-pane>
       <el-tab-pane label="模拟设备" name="simulator">
         <DeviceDetailsSimulator v-if="activeTab === 'simulator'" :product="product" :device="device" />