Commit c9e00d97 by alwayssuper

feat:deviceLog and deviceSimulator

parent b71fa84a
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
"source.fixAll.stylelint": "explicit" "source.fixAll.stylelint": "explicit"
}, },
"[vue]": { "[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "octref.vetur"
}, },
"i18n-ally.localesPaths": ["src/locales"], "i18n-ally.localesPaths": ["src/locales"],
"i18n-ally.keystyle": "nested", "i18n-ally.keystyle": "nested",
......
...@@ -69,7 +69,7 @@ export interface SimulatorDataVO { ...@@ -69,7 +69,7 @@ export interface SimulatorDataVO {
deviceKey: string deviceKey: string
type: string type: string
subType: string subType: string
reportTime: string reportTime: number // 时间戳
content: string // 存储 JSON 字符串 content: string // 存储 JSON 字符串
} }
...@@ -151,5 +151,9 @@ export const DeviceApi = { ...@@ -151,5 +151,9 @@ export const DeviceApi = {
// 模拟设备 // 模拟设备
simulatorDevice: async (data: SimulatorDataVO) => { simulatorDevice: async (data: SimulatorDataVO) => {
return await request.post({ url: `/iot/device/data/simulator`, data }) 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 })
} }
} }
...@@ -18,6 +18,13 @@ export interface ThingModelData { ...@@ -18,6 +18,13 @@ export interface ThingModelData {
} }
/** /**
* IoT 模拟设备
*/
export interface SimulatorData extends ThingModelData {
simulateValue?: string | number // 用于存储模拟值
}
/**
* ThingModelProperty 类型 * ThingModelProperty 类型
*/ */
export interface ThingModelProperty { export interface ThingModelProperty {
......
...@@ -29,27 +29,18 @@ ...@@ -29,27 +29,18 @@
{{ formatDate(scope.row.time) }} {{ formatDate(scope.row.time) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="类型" align="center" prop="type" width="120"> <el-table-column label="类型" align="center" prop="type" width="120" />
<template #default="scope"> <el-table-column label="名称(标识符)" align="center" prop="subType" width="120" />
<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-column label="内容" align="center" prop="content" :show-overflow-tooltip="true" />
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<div class="mt-10px flex justify-end"> <div class="mt-10px flex justify-end">
<el-pagination <Pagination
v-model:current-page="queryParams.pageNo"
v-model:page-size="queryParams.pageSize"
:total="total" :total="total"
:page-sizes="[10, 20, 50, 100]" v-model:page="queryParams.pageNo"
small v-model:limit="queryParams.pageSize"
background @pagination="getLogList"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleQuery"
@current-change="handleQuery"
/> />
</div> </div>
</ContentWrap> </ContentWrap>
...@@ -61,15 +52,17 @@ import { DICT_TYPE } from '@/utils/dict' ...@@ -61,15 +52,17 @@ import { DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime' import { formatDate } from '@/utils/formatTime'
const props = defineProps<{ const props = defineProps<{
deviceId: number deviceKey: number
}>() }>()
//TODO:后续看看使用什么查询条件 目前后端是留了时间范围 type subType
// 查询参数 // 查询参数
const queryParams = reactive({ const queryParams = reactive({
type: '', deviceKey: props.deviceKey,
keyword: '', // type: '',
// keyword: '',
pageNo: 1, pageNo: 1,
pageSize: 20 pageSize: 10
}) })
// 列表数据 // 列表数据
...@@ -90,23 +83,24 @@ const typeMap = { ...@@ -90,23 +83,24 @@ const typeMap = {
/** 查询日志列表 */ /** 查询日志列表 */
const getLogList = async () => { const getLogList = async () => {
// if (!props.deviceId) return if (!props.deviceKey) return
// loading.value = true loading.value = true
// try { try {
// const res = await DeviceApi.getDeviceLogs(props.deviceId, queryParams) const res = await DeviceApi.getDeviceLogPage(queryParams)
// total.value = res.total total.value = res.total
// logList.value = res.list.map((item: any) => { logList.value = res.list.map((item: any) => {
// const log = { const log = {
// time: item.time, time: item.reportTime,
// type: typeMap[item.type as keyof typeof typeMap] || item.type, type: item.type,
// name: getLogName(item), subType: item.subType,
// content: item.content content: item.content
// } }
// return log return log
// }) })
// } finally { console.log(logList.value)
// loading.value = false } finally {
// } loading.value = false
}
} }
/** 获取日志名称 */ /** 获取日志名称 */
...@@ -146,11 +140,14 @@ watch(autoRefresh, (newValue) => { ...@@ -146,11 +140,14 @@ watch(autoRefresh, (newValue) => {
}) })
/** 监听设备ID变化 */ /** 监听设备ID变化 */
watch(() => props.deviceId, (newValue) => { watch(
() => props.deviceKey,
(newValue) => {
if (newValue) { if (newValue) {
handleQuery() handleQuery()
} }
}) }
)
/** 组件卸载时清除定时器 */ /** 组件卸载时清除定时器 */
onBeforeUnmount(() => { onBeforeUnmount(() => {
...@@ -161,7 +158,7 @@ onBeforeUnmount(() => { ...@@ -161,7 +158,7 @@ onBeforeUnmount(() => {
/** 初始化 */ /** 初始化 */
onMounted(() => { onMounted(() => {
if (props.deviceId) { if (props.deviceKey) {
getLogList() getLogList()
} }
}) })
......
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
<!-- 事件上报 --> <!-- 事件上报 -->
<el-tab-pane label="事件上报" name="event"> <el-tab-pane label="事件上报" name="event">
<ContentWrap> <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="name" />
<el-table-column label="标识符" align="center" prop="identifier" /> <el-table-column label="标识符" align="center" prop="identifier" />
<el-table-column label="数据类型" align="center" prop="dataType" /> <el-table-column label="数据类型" align="center" prop="dataType" />
...@@ -115,7 +115,7 @@ ...@@ -115,7 +115,7 @@
</el-table> </el-table>
<div class="mt-10px"> <div class="mt-10px">
<el-button type="primary" @click="handleEventReport">发送</el-button> <el-button type="primary" @click="handleEventReport">发送</el-button>
</div> </div> -->
</ContentWrap> </ContentWrap>
</el-tab-pane> </el-tab-pane>
...@@ -141,7 +141,7 @@ ...@@ -141,7 +141,7 @@
<!-- 属性调试 --> <!-- 属性调试 -->
<el-tab-pane label="属性调试" name="propertyDebug"> <el-tab-pane label="属性调试" name="propertyDebug">
<ContentWrap> <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="name" />
<el-table-column label="标识符" align="center" prop="identifier" /> <el-table-column label="标识符" align="center" prop="identifier" />
<el-table-column label="数据类型" align="center" prop="dataType" /> <el-table-column label="数据类型" align="center" prop="dataType" />
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
</el-table> </el-table>
<div class="mt-10px"> <div class="mt-10px">
<el-button type="primary" @click="handlePropertyGet">获取</el-button> <el-button type="primary" @click="handlePropertyGet">获取</el-button>
</div> </div> -->
</ContentWrap> </ContentWrap>
</el-tab-pane> </el-tab-pane>
...@@ -178,7 +178,7 @@ ...@@ -178,7 +178,7 @@
<el-col :span="12"> <el-col :span="12">
<el-tabs type="border-card"> <el-tabs type="border-card">
<el-tab-pane label="设备日志"> <el-tab-pane label="设备日志">
<DeviceDetailsLog :device-id="device.id" /> <DeviceDetailsLog :deviceKey="device.deviceKey" />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-col> </el-col>
...@@ -188,7 +188,7 @@ ...@@ -188,7 +188,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ProductVO } from '@/api/iot/product/product' 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 { DeviceApi, DeviceVO,SimulatorDataVO } from '@/api/iot/device/device'
import DeviceDetailsLog from './DeviceDetailsLog.vue' import DeviceDetailsLog from './DeviceDetailsLog.vue'
import { import {
...@@ -212,9 +212,6 @@ const dataTypeOptionsLabel = computed(() => (value: string) => getDataTypeOption ...@@ -212,9 +212,6 @@ const dataTypeOptionsLabel = computed(() => (value: string) => getDataTypeOption
const props = defineProps<{ product: ProductVO; device: DeviceVO }>() const props = defineProps<{ product: ProductVO; device: DeviceVO }>()
const list = ref<SimulatorData[]>([]) // 物模型列表的数据 const list = ref<SimulatorData[]>([]) // 物模型列表的数据
interface SimulatorData extends ThingModelData {
simulateValue?: string | number // 用于存储模拟值
}
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
...@@ -231,33 +228,33 @@ const getList = async () => { ...@@ -231,33 +228,33 @@ const getList = async () => {
} }
} }
// 功能列表数据结构定义 // // 功能列表数据结构定义
interface TableItem { // interface TableItem {
name: string // name: string
identifier: string // identifier: string
value: string | number // value: string | number
} // }
// 添加计算属性来过滤物模型数据 // // 添加计算属性来过滤物模型数据
const propertyList = computed(() => { // const propertyList = computed(() => {
return list.value // return list.value
.filter((item) => item.type === 'property') // .filter((item) => item.type === 'property')
.map((item) => ({ // .map((item) => ({
name: item.name, // name: item.name,
identifier: item.identifier, // identifier: item.identifier,
value: '' // value: ''
})) // }))
}) // })
const eventList = computed(() => { // const eventList = computed(() => {
return list.value // return list.value
.filter((item) => item.type === 'event') // .filter((item) => item.type === 'event')
.map((item) => ({ // .map((item) => ({
name: item.name, // name: item.name,
identifier: item.identifier, // identifier: item.identifier,
value: '' // value: ''
})) // }))
}) // })
// 监听标签页变化 todo:后续改成查询字典 // 监听标签页变化 todo:后续改成查询字典
watch( watch(
...@@ -291,16 +288,16 @@ watch( ...@@ -291,16 +288,16 @@ watch(
{ immediate: true } { immediate: true }
) )
interface ReportData { // interface ReportData {
productKey: string // productKey: string
deviceKey: string // deviceKey: string
type: string // type: string
subType: string // subType: string
reportTime: string // reportTime: string
content: string // 改为 string 类型,存储 JSON 字符串 // content: string // 改为 string 类型,存储 JSON 字符串
} // }
// 处理属性上报 // 处理属性上报 TODO:数据类型效验
const handlePropertyReport = async () => { const handlePropertyReport = async () => {
const contentObj: Record<string, any> = {} const contentObj: Record<string, any> = {}
list.value.forEach((item) => { list.value.forEach((item) => {
...@@ -315,71 +312,67 @@ const handlePropertyReport = async () => { ...@@ -315,71 +312,67 @@ const handlePropertyReport = async () => {
deviceKey: props.device.deviceKey, deviceKey: props.device.deviceKey,
type: 'property', type: 'property',
subType: 'report', subType: 'report',
reportTime: new Date().toISOString(), reportTime: Date.now(), // 将 reportTime 变为数字类型的时间戳
content: JSON.stringify(contentObj) // 转换为 JSON 字符串 content: JSON.stringify(contentObj) // 转换为 JSON 字符串
} }
try { try {
// TODO: 调用API发送数据 await DeviceApi.simulatorDevice(reportData)
console.log('上报数据:', reportData) message.success('属性上报成功')
console.log('reportData.content', reportData.content)
const data = await DeviceApi.simulatorDevice(reportData)
console.log(data)
message.success('属性上报成功123')
} catch (error) { } catch (error) {
message.error('属性上报失败') message.error('属性上报失败')
} }
} }
// 处理事件上报 // // 处理事件上报
const handleEventReport = async () => { // const handleEventReport = async () => {
const contentObj: Record<string, any> = {} // const contentObj: Record<string, any> = {}
list.value // list.value
.filter(item => item.type === 'event') // .filter(item => item.type === 'event')
.forEach((item) => { // .forEach((item) => {
if (item.simulateValue !== undefined && item.simulateValue !== '') { // if (item.simulateValue !== undefined && item.simulateValue !== '') {
contentObj[item.identifier] = item.simulateValue // contentObj[item.identifier] = item.simulateValue
} // }
}) // })
const reportData: ReportData = { // const reportData: ReportData = {
productKey: props.product.productKey, // productKey: props.product.productKey,
deviceKey: props.device.deviceKey, // deviceKey: props.device.deviceKey,
type: 'event', // type: 'event',
subType: list.value.find(item => item.type === 'event')?.identifier || '', // subType: list.value.find(item => item.type === 'event')?.identifier || '',
reportTime: new Date().toISOString(), // reportTime: new Date().toISOString(),
content: JSON.stringify(contentObj) // 转换为 JSON 字符串 // content: JSON.stringify(contentObj) // 转换为 JSON 字符串
} // }
try { // try {
// TODO: 调用API发送数据 // // TODO: 调用API发送数据
console.log('上报数据:', reportData) // console.log('上报数据:', reportData)
message.success('事件上报成功') // message.success('事件上报成功')
} catch (error) { // } catch (error) {
message.error('事件上报失败') // message.error('事件上报失败')
} // }
} // }
// 处理设备状态变更 // // 处理设备状态变更
const handleDeviceState = async (state: 'online' | 'offline') => { // const handleDeviceState = async (state: 'online' | 'offline') => {
const reportData: ReportData = { // const reportData: ReportData = {
productKey: props.product.productKey, // productKey: props.product.productKey,
deviceKey: props.device.deviceKey, // deviceKey: props.device.deviceKey,
type: 'status', // type: 'status',
subType: state, // subType: state,
reportTime: new Date().toISOString(), // reportTime: new Date().toISOString(),
content: JSON.stringify({ status: state }) // 转换为 JSON 字符串 // content: JSON.stringify({ status: state }) // 转换为 JSON 字符串
} // }
try { // try {
// TODO: 调用API发送数据 // // TODO: 调用API发送数据
console.log('状态变更数据:', reportData) // console.log('状态变更数据:', reportData)
console.log('reportData.content111111111', reportData.content) // console.log('reportData.content111111111', reportData.content)
message.success(`设备${state === 'online' ? '上线' : '下线'}成功`) // message.success(`设备${state === 'online' ? '上线' : '下线'}成功`)
} catch (error) { // } catch (error) {
message.error(`设备${state === 'online' ? '上线' : '下线'}失败`) // message.error(`设备${state === 'online' ? '上线' : '下线'}失败`)
} // }
} // }
// 处理属性获取 // 处理属性获取
const handlePropertyGet = async () => { const handlePropertyGet = async () => {
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<el-tab-pane label="子设备管理" v-if="product.deviceType === DeviceTypeEnum.GATEWAY" /> <el-tab-pane label="子设备管理" v-if="product.deviceType === DeviceTypeEnum.GATEWAY" />
<el-tab-pane label="设备影子" /> <el-tab-pane label="设备影子" />
<el-tab-pane label="设备日志" name="log"> <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>
<el-tab-pane label="模拟设备" name="simulator"> <el-tab-pane label="模拟设备" name="simulator">
<DeviceDetailsSimulator v-if="activeTab === 'simulator'" :product="product" :device="device" /> <DeviceDetailsSimulator v-if="activeTab === 'simulator'" :product="product" :device="device" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment