feat:DeviceDetailsLog DeviceDetailsSimulator
							parent
							
								
									77e0a76389
								
							
						
					
					
						commit
						61ebe5b9a2
					
				
							
								
								
									
										12621
									
								
								pnpm-lock.yaml
								
								
								
								
							
							
						
						
									
										12621
									
								
								pnpm-lock.yaml
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,168 @@ | |||
| <template> | ||||
|   <ContentWrap> | ||||
|     <!-- 搜索区域 --> | ||||
|     <el-form :model="queryParams" inline> | ||||
|       <el-form-item> | ||||
|         <el-select v-model="queryParams.type" placeholder="所有" class="!w-120px"> | ||||
|           <el-option label="所有" value="" /> | ||||
|           <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.keyword" 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 v-model="autoRefresh" class="ml-10px" /> 定时刷新 | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
| 
 | ||||
|     <!-- 日志列表 --> | ||||
|     <el-table v-loading="loading" :data="logList" :stripe="true" class="whitespace-nowrap"> | ||||
|       <el-table-column label="时间" align="center" prop="time" width="180"> | ||||
|         <template #default="scope"> | ||||
|           {{ 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="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" | ||||
|         :total="total" | ||||
|         :page-sizes="[10, 20, 50, 100]" | ||||
|         small | ||||
|         background | ||||
|         layout="total, sizes, prev, pager, next, jumper" | ||||
|         @size-change="handleQuery" | ||||
|         @current-change="handleQuery" | ||||
|       /> | ||||
|     </div> | ||||
|   </ContentWrap> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { DeviceApi } from '@/api/iot/device/device' | ||||
| import { DICT_TYPE } from '@/utils/dict' | ||||
| import { formatDate } from '@/utils/formatTime' | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|   deviceId: number | ||||
| }>() | ||||
| 
 | ||||
| // 查询参数 | ||||
| const queryParams = reactive({ | ||||
|   type: '', | ||||
|   keyword: '', | ||||
|   pageNo: 1, | ||||
|   pageSize: 20 | ||||
| }) | ||||
| 
 | ||||
| // 列表数据 | ||||
| const loading = ref(false) | ||||
| const total = ref(0) | ||||
| const logList = ref([]) | ||||
| const autoRefresh = ref(false) | ||||
| let timer: any = null | ||||
| 
 | ||||
| // 类型映射 | ||||
| const typeMap = { | ||||
|   lifetime: '生命周期', | ||||
|   state: '设备状态', | ||||
|   property: '属性', | ||||
|   event: '事件', | ||||
|   service: '服务' | ||||
| } | ||||
| 
 | ||||
| /** 查询日志列表 */ | ||||
| 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 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 获取日志名称 */ | ||||
| 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 | ||||
|   } | ||||
| }) | ||||
| 
 | ||||
| /** 监听设备ID变化 */ | ||||
| watch(() => props.deviceId, (newValue) => { | ||||
|   if (newValue) { | ||||
|     handleQuery() | ||||
|   } | ||||
| }) | ||||
| 
 | ||||
| /** 组件卸载时清除定时器 */ | ||||
| onBeforeUnmount(() => { | ||||
|   if (timer) { | ||||
|     clearInterval(timer) | ||||
|   } | ||||
| }) | ||||
| 
 | ||||
| /** 初始化 */ | ||||
| onMounted(() => { | ||||
|   if (props.deviceId) { | ||||
|     getLogList() | ||||
|   } | ||||
| }) | ||||
| </script> | ||||
|  | @ -0,0 +1,192 @@ | |||
| <template> | ||||
|   <ContentWrap> | ||||
|     <el-row :gutter="20"> | ||||
|       <!-- 左侧指令调试区域 --> | ||||
|       <el-col :span="12"> | ||||
|         <el-tabs v-model="activeTab" type="border-card"> | ||||
|           <!-- 上行指令调试 --> | ||||
|           <el-tab-pane label="上行指令调试" name="up"> | ||||
|             <el-tabs v-model="subTab" v-if="activeTab === 'up'"> | ||||
|               <!-- 属性上报 --> | ||||
|               <el-tab-pane label="属性上报" name="property"> | ||||
|                 <ContentWrap> | ||||
|                   <el-table v-loading="loading" :data="propertyList" :stripe="true"> | ||||
|                     <el-table-column label="值" align="center" width="80"> | ||||
|                       <template #default="scope"> | ||||
|                         <el-input v-model="scope.row.value" class="!w-60px" /> | ||||
|                       </template> | ||||
|                     </el-table-column> | ||||
|                     <el-table-column label="功能名称" align="center" prop="name" /> | ||||
|                     <el-table-column label="标识符" align="center" prop="identifier" /> | ||||
|                     <el-table-column label="数据类型" align="center" prop="dataType" /> | ||||
|                     <el-table-column label="数据定义" align="center" prop="specs" :show-overflow-tooltip="true" /> | ||||
|                   </el-table> | ||||
|                   <div class="mt-10px"> | ||||
|                     <el-button type="primary" @click="handlePropertyReport">发送</el-button> | ||||
|                   </div> | ||||
|                 </ContentWrap> | ||||
|               </el-tab-pane> | ||||
| 
 | ||||
|               <!-- 事件上报 --> | ||||
|               <el-tab-pane label="事件上报" name="event"> | ||||
|                 <ContentWrap> | ||||
|                   <el-table v-loading="loading" :data="eventList" :stripe="true"> | ||||
|                     <el-table-column label="值" align="center" width="80"> | ||||
|                       <template #default="scope"> | ||||
|                         <el-input v-model="scope.row.value" class="!w-60px" /> | ||||
|                       </template> | ||||
|                     </el-table-column> | ||||
|                     <el-table-column label="功能名称" align="center" prop="name" /> | ||||
|                     <el-table-column label="标识符" align="center" prop="identifier" /> | ||||
|                     <el-table-column label="数据类型" align="center" prop="dataType" /> | ||||
|                     <el-table-column label="数据定义" align="center" prop="specs" :show-overflow-tooltip="true" /> | ||||
|                   </el-table> | ||||
|                   <div class="mt-10px"> | ||||
|                     <el-button type="primary" @click="handleEventReport">发送</el-button> | ||||
|                   </div> | ||||
|                 </ContentWrap> | ||||
|               </el-tab-pane> | ||||
| 
 | ||||
|               <!-- 状态变更 --> | ||||
|               <el-tab-pane label="状态变更" name="status"> | ||||
|                 <ContentWrap> | ||||
|                   <div class="flex gap-4"> | ||||
|                     <el-button type="primary" @click="handleDeviceState('online')">设备上线</el-button> | ||||
|                     <el-button type="primary" @click="handleDeviceState('offline')">设备下线</el-button> | ||||
|                   </div> | ||||
|                 </ContentWrap> | ||||
|               </el-tab-pane> | ||||
|             </el-tabs> | ||||
|           </el-tab-pane> | ||||
| 
 | ||||
|           <!-- 下行指令调试 --> | ||||
|           <el-tab-pane label="下行指令调试" name="down"> | ||||
|             <el-tabs v-model="subTab" v-if="activeTab === 'down'"> | ||||
|               <!-- 属性调试 --> | ||||
|               <el-tab-pane label="属性调试" name="propertyDebug"> | ||||
|                 <ContentWrap> | ||||
|                   <el-table v-loading="loading" :data="propertyList" :stripe="true"> | ||||
|                     <el-table-column label="值" align="center" width="80"> | ||||
|                       <template #default="scope"> | ||||
|                         <el-input v-model="scope.row.value" class="!w-60px" /> | ||||
|                       </template> | ||||
|                     </el-table-column> | ||||
|                     <el-table-column label="功能名称" align="center" prop="name" /> | ||||
|                     <el-table-column label="标识符" align="center" prop="identifier" /> | ||||
|                     <el-table-column label="数据类型" align="center" prop="dataType" /> | ||||
|                     <el-table-column label="数据定义" align="center" prop="specs" :show-overflow-tooltip="true" /> | ||||
|                   </el-table> | ||||
|                   <div class="mt-10px"> | ||||
|                     <el-button type="primary" @click="handlePropertyGet">获取</el-button> | ||||
|                   </div> | ||||
|                 </ContentWrap> | ||||
|               </el-tab-pane> | ||||
| 
 | ||||
|               <!-- 服务调用 --> | ||||
|               <el-tab-pane label="服务调用" name="service"> | ||||
|                 <ContentWrap> | ||||
|                   <!-- 服务调用相关内容 --> | ||||
|                 </ContentWrap> | ||||
|               </el-tab-pane> | ||||
|             </el-tabs> | ||||
|           </el-tab-pane> | ||||
|         </el-tabs> | ||||
|       </el-col> | ||||
| 
 | ||||
|       <!-- 右侧设备日志区域 --> | ||||
|       <el-col :span="12"> | ||||
|         <el-tabs type="border-card"> | ||||
|           <el-tab-pane label="设备日志"> | ||||
|             <DeviceDetailsLog :device-id="device.id" /> | ||||
|           </el-tab-pane> | ||||
|         </el-tabs> | ||||
|       </el-col> | ||||
|     </el-row> | ||||
|   </ContentWrap> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { ProductVO } from '@/api/iot/product/product' | ||||
| import { DeviceApi, DeviceVO } from '@/api/iot/device/device' | ||||
| import DeviceDetailsLog from './DeviceDetailsLog.vue' | ||||
| 
 | ||||
| const message = useMessage() // 消息弹窗 | ||||
| const loading = ref(false) | ||||
| const activeTab = ref('up') | ||||
| const subTab = ref('property') | ||||
| 
 | ||||
| const props = defineProps<{ product: ProductVO; device: DeviceVO }>() | ||||
| 
 | ||||
| // 功能列表数据结构定义 | ||||
| interface TableItem { | ||||
|   name: string | ||||
|   identifier: string | ||||
|   dataType: string | ||||
|   specs: string | ||||
|   value: string | number | ||||
| } | ||||
| 
 | ||||
| // 属性列表数据 | ||||
| const propertyList = ref<TableItem[]>([ | ||||
|   { | ||||
|     name: '电量', | ||||
|     identifier: 'power', | ||||
|     dataType: 'int32', | ||||
|     specs: '', | ||||
|     value: '' | ||||
|   }, | ||||
|   { | ||||
|     name: '设备型号', | ||||
|     identifier: 'DeviceType', | ||||
|     dataType: 'text', | ||||
|     specs: '{ "length": "128" }', | ||||
|     value: '' | ||||
|   }, | ||||
|   { | ||||
|     name: '信号强度', | ||||
|     identifier: 'rssi', | ||||
|     dataType: 'int32', | ||||
|     specs: '{ "min": "-127", "max": "127" }', | ||||
|     value: '' | ||||
|   }, | ||||
|   { | ||||
|     name: '门状态', | ||||
|     identifier: 'doorStatus', | ||||
|     dataType: 'enum', | ||||
|     specs: '{ "0": "关", "1": "开" }', | ||||
|     value: '' | ||||
|   } | ||||
| ]) | ||||
| 
 | ||||
| // 事件列表数据 | ||||
| const eventList = ref<TableItem[]>([]) | ||||
| 
 | ||||
| // 处理属性上报 | ||||
| const handlePropertyReport = async () => { | ||||
|   // TODO: 实现属性上报逻辑 | ||||
|   message.success('属性上报成功') | ||||
| } | ||||
| 
 | ||||
| // 处理事件上报 | ||||
| const handleEventReport = async () => { | ||||
|   // TODO: 实现事件上报逻辑 | ||||
|   message.success('事件上报成功') | ||||
| } | ||||
| 
 | ||||
| // 处理设备状态变更 | ||||
| const handleDeviceState = async (state: 'online' | 'offline') => { | ||||
|   // TODO: 实现设备状态变更逻辑 | ||||
|   message.success(`设备${state === 'online' ? '上线' : '下线'}成功`) | ||||
| } | ||||
| 
 | ||||
| // 处理属性获取 | ||||
| const handlePropertyGet = async () => { | ||||
|   // TODO: 实现属性获取逻辑 | ||||
|   message.success('属性获取成功') | ||||
| } | ||||
| 
 | ||||
| // 初始化 | ||||
| onMounted(() => { | ||||
|   // TODO: 获取初始数据 | ||||
| }) | ||||
| </script> | ||||
|  | @ -16,6 +16,12 @@ | |||
|       </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'" :product="product" :device="device" /> | ||||
|       </el-tab-pane> | ||||
|       <el-tab-pane label="模拟设备" name="simulator"> | ||||
|         <DeviceDetailsSimulator v-if="activeTab === 'simulator'" :product="product" :device="device" /> | ||||
|      </el-tab-pane> | ||||
|     </el-tabs> | ||||
|   </el-col> | ||||
| </template> | ||||
|  | @ -26,7 +32,8 @@ 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 DeviceDetailsSimulator from './DeviceDetailsSimulator.vue' | ||||
| defineOptions({ name: 'IoTDeviceDetail' }) | ||||
| 
 | ||||
| const route = useRoute() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 alwayssuper
						alwayssuper