feat:【IoT 物联网】物模型数据-设备属性,增加图表展示

This commit is contained in:
YunaiV
2025-06-18 19:41:36 +08:00
parent 814a8465b6
commit 5e9a798d0b
4 changed files with 154 additions and 41 deletions

View File

@ -130,12 +130,12 @@ export const DeviceApi = {
// 获取设备属性最新数据
getLatestDeviceProperties: async (params: any) => {
return await request.get({ url: `/iot/device/property/latest`, params })
return await request.get({ url: `/iot/device/property/get-latest`, params })
},
// 获取设备属性历史数据
getHistoryDevicePropertyPage: async (params: any) => {
return await request.get({ url: `/iot/device/property/history-page`, params })
getHistoryDevicePropertyList: async (params: any) => {
return await request.get({ url: `/iot/device/property/history-list`, params })
},
// 获取设备认证信息

View File

@ -13,6 +13,7 @@ import {
import {
AriaComponent,
DataZoomComponent,
GridComponent,
LegendComponent,
ParallelComponent,
@ -30,6 +31,7 @@ echarts.use([
TitleComponent,
TooltipComponent,
ToolboxComponent,
DataZoomComponent,
GridComponent,
PolarComponent,
AriaComponent,

View File

@ -1,6 +1,6 @@
<!-- 设备物模型 -> 运行状态 -> 查看数据设备的属性值历史-->
<template>
<Dialog title="查看数据" v-model="dialogVisible">
<Dialog title="查看数据" v-model="dialogVisible" width="1024px">
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
@ -10,52 +10,68 @@
:inline="true"
label-width="68px"
>
<el-form-item label="时间" prop="createTime">
<el-form-item label="" prop="createTime">
<el-date-picker
v-model="queryParams.times"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetimerange"
start-placeholder="开始日期"
end-placeholder="结束日期"
class="!w-350px"
class="!w-360px"
@change="handleTimeChange"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" />
搜索
</el-button>
<el-form-item class="float-right !mr-0 !mb-0">
<el-button-group>
<el-button
:type="viewMode === 'chart' ? 'primary' : 'default'"
@click="viewMode = 'chart'"
>
<Icon icon="ep:histogram" />
</el-button>
<el-button
:type="viewMode === 'list' ? 'primary' : 'default'"
@click="viewMode = 'list'"
>
<Icon icon="ep:list" />
</el-button>
</el-button-group>
</el-form-item>
</el-form>
</ContentWrap>
<!-- TODO @haohao可参考阿里云 IoT改成图标表格两个选项 -->
<!-- 列表 -->
<!-- 数据展示区域 -->
<ContentWrap>
<el-table v-loading="detailLoading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column
label="时间"
align="center"
prop="updateTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="属性值" align="center" prop="value" />
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 图表模式 -->
<div v-if="viewMode === 'chart'" class="chart-container">
<div v-if="sortedList.length === 0" class="text-center text-gray-500 py-20"> 暂无数据 </div>
<Echart v-else :options="echartsOption" height="400px" />
</div>
<!-- 表格模式 -->
<div v-else>
<el-table
v-loading="detailLoading"
:data="sortedList"
:stripe="true"
:show-overflow-tooltip="true"
>
<el-table-column label="时间" align="center" prop="time" width="180px">
<template #default="scope">
{{ formatDate(new Date(scope.row.updateTime)) }}
</template>
</el-table-column>
<el-table-column label="属性值" align="center" prop="value" />
</el-table>
</div>
</ContentWrap>
</Dialog>
</template>
<script setup lang="ts">
import { DeviceApi, DeviceHistoryDataVO, DeviceVO } from '@/api/iot/device/device'
import { ProductVO } from '@/api/iot/product/product'
import { beginOfDay, dateFormatter, endOfDay, formatDate } from '@/utils/formatTime'
import { beginOfDay, endOfDay, formatDate } from '@/utils/formatTime'
import { Echart } from '@/components/Echart'
defineProps<{ product: ProductVO; device: DeviceVO }>()
@ -64,12 +80,94 @@ defineOptions({ name: 'IoTDeviceDataDetail' })
const dialogVisible = ref(false) // 弹窗的是否展示
const detailLoading = ref(false)
const viewMode = ref<'chart' | 'list'>('chart') // 视图模式状态
const list = ref<DeviceHistoryDataVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
// 根据视图模式排序的数据
const sortedList = computed(() => {
if (!list.value || list.value.length === 0) return []
const sortedData = [...list.value]
if (viewMode.value === 'list') {
// 列表模式:按时间倒序(最新的在前)
return sortedData.sort((a, b) => b.time - a.time)
} else {
// 图表模式:按时间升序(最早的在前)
return sortedData.sort((a, b) => a.time - b.time)
}
})
// Echarts 配置
const echartsOption = reactive<any>({
title: {
text: '设备数据趋势',
left: 'center'
},
grid: {
left: 60,
right: 40,
bottom: 80,
top: 80,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
xAxis: {
type: 'time',
name: '时间',
axisLabel: {
formatter: (value: number) => formatDate(new Date(value), 'MM-DD HH:mm')
}
},
yAxis: {
type: 'value',
name: '属性值'
},
series: [
{
name: '属性值',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
width: 2,
color: '#1890FF'
},
itemStyle: {
color: '#1890FF'
},
data: []
}
],
dataZoom: [
{
type: 'inside'
},
{
type: 'slider',
height: 30
}
]
})
// 更新图表数据
const updateChartData = () => {
if (echartsOption.series && echartsOption.series[0]) {
echartsOption.series[0].data = sortedList.value.map((item) => [
item.updateTime,
parseFloat(item.value) || 0
])
debugger
}
}
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
deviceId: -1,
identifier: '',
times: [
@ -84,9 +182,12 @@ const queryFormRef = ref() // 搜索的表单
const getList = async () => {
detailLoading.value = true
try {
const data = await DeviceApi.getHistoryDevicePropertyPage(queryParams)
list.value = data.list
total.value = data.total
const data = await DeviceApi.getHistoryDevicePropertyList(queryParams)
list.value = data || []
// 数据获取后更新图表
nextTick(() => {
updateChartData()
})
} finally {
detailLoading.value = false
}
@ -100,11 +201,21 @@ const open = (deviceId: number, identifier: string) => {
getList()
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
/** 时间变化处理 */
const handleTimeChange = () => {
getList()
}
// 监听数据变化,更新图表
watch(
() => sortedList.value,
() => {
if (viewMode.value === 'chart') {
updateChartData()
}
},
{ deep: true }
)
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
</script>

View File

@ -213,7 +213,7 @@ watch(autoRefresh, (newValue) => {
if (newValue) {
autoRefreshTimer = setInterval(() => {
getList()
}, 5000) // 每5秒刷新一次
}, 5000) // 每 5 秒刷新一次
} else {
clearInterval(autoRefreshTimer)
autoRefreshTimer = null