feat:iothome
parent
feab54c11e
commit
89a8b25f17
|
|
@ -16,10 +16,15 @@ export interface IotStatisticsSummaryRespVO {
|
|||
productCategoryDeviceCounts: Record<string, number>
|
||||
}
|
||||
|
||||
/** 时间戳-数值的键值对类型 */
|
||||
interface TimeValueItem {
|
||||
[key: string]: number
|
||||
}
|
||||
|
||||
/** IoT 消息统计数据类型 */
|
||||
export interface IotStatisticsDeviceMessageSummaryRespVO {
|
||||
upstreamCounts: Record<number, number>
|
||||
downstreamCounts: Record<number, number>
|
||||
upstreamCounts: TimeValueItem[]
|
||||
downstreamCounts: TimeValueItem[]
|
||||
}
|
||||
|
||||
// IoT 数据统计 API
|
||||
|
|
|
|||
|
|
@ -330,3 +330,30 @@ export function getDateRange(
|
|||
dayjs(endDate).endOf('d').format('YYYY-MM-DD HH:mm:ss')
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定小时前的时间戳
|
||||
* @param hours 小时数
|
||||
* @returns 返回指定小时前的时间戳(毫秒)
|
||||
*/
|
||||
export function getHoursAgo(hours: number): number {
|
||||
return dayjs().subtract(hours, 'hour').valueOf()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标准时间范围的时间戳
|
||||
* @param range 时间范围,支持 '8h' | '24h' | '7d'
|
||||
* @returns 返回开始时间戳(毫秒)
|
||||
*/
|
||||
export function getTimeRangeStart(range: '8h' | '24h' | '7d'): number {
|
||||
switch (range) {
|
||||
case '8h':
|
||||
return getHoursAgo(8)
|
||||
case '24h':
|
||||
return getHoursAgo(24)
|
||||
case '7d':
|
||||
return dayjs().subtract(7, 'day').valueOf()
|
||||
default:
|
||||
return dayjs().valueOf()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,9 @@ import { CanvasRenderer } from 'echarts/renderers'
|
|||
import { GridComponent, LegendComponent, TooltipComponent } from 'echarts/components'
|
||||
import { UniversalTransition } from 'echarts/features'
|
||||
import { IotStatisticsDeviceMessageSummaryRespVO } from '@/api/iot/statistics'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { formatDate, getTimeRangeStart } from '@/utils/formatTime'
|
||||
import type { PropType } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
/** 消息趋势统计卡片 */
|
||||
defineOptions({ name: 'MessageTrendCard' })
|
||||
|
|
@ -48,27 +49,14 @@ const props = defineProps({
|
|||
const emit = defineEmits(['timeRangeChange'])
|
||||
|
||||
const timeRange = ref('7d')
|
||||
const dateRange = ref<[Date, Date] | null>(null)
|
||||
const dateRange = ref<any>(null)
|
||||
const messageChartRef = ref()
|
||||
|
||||
// TODO @super:这个的计算,看看能不能结合 dayjs 简化。因为 1h、24h、7d 感觉是比较标准的。如果没有,抽到 utils/formatTime.ts 作为一个工具方法
|
||||
// 处理快捷时间范围选择
|
||||
const handleTimeRangeChange = (range: string) => {
|
||||
const now = Date.now()
|
||||
let startTime: number
|
||||
|
||||
switch (range) {
|
||||
case '8h':
|
||||
startTime = now - 8 * 60 * 60 * 1000
|
||||
break
|
||||
case '24h':
|
||||
startTime = now - 24 * 60 * 60 * 1000
|
||||
break
|
||||
case '7d':
|
||||
startTime = now - 7 * 24 * 60 * 60 * 1000
|
||||
break
|
||||
default:
|
||||
return
|
||||
}
|
||||
const now = dayjs().valueOf()
|
||||
const startTime = getTimeRangeStart(range as '8h' | '24h' | '7d')
|
||||
|
||||
dateRange.value = null
|
||||
emit('timeRangeChange', { startTime, endTime: now })
|
||||
|
|
@ -96,31 +84,75 @@ const initChart = () => {
|
|||
UniversalTransition
|
||||
])
|
||||
|
||||
const timestamps = Array.from(
|
||||
new Set([
|
||||
...props.messageStats.upstreamCounts.map((item) => Number(Object.keys(item)[0])),
|
||||
...props.messageStats.downstreamCounts.map((item) => Number(Object.keys(item)[0]))
|
||||
])
|
||||
).sort((a, b) => a - b) // 确保时间戳从小到大排序
|
||||
|
||||
// 准备数据
|
||||
const xdata = timestamps.map((ts) => formatDate(ts, 'YYYY-MM-DD HH:mm'))
|
||||
const upData = timestamps.map((ts) => {
|
||||
const item = props.messageStats.upstreamCounts.find(
|
||||
(count) => Number(Object.keys(count)[0]) === ts
|
||||
)
|
||||
return item ? Object.values(item)[0] : 0
|
||||
})
|
||||
const downData = timestamps.map((ts) => {
|
||||
const item = props.messageStats.downstreamCounts.find(
|
||||
(count) => Number(Object.keys(count)[0]) === ts
|
||||
)
|
||||
return item ? Object.values(item)[0] : 0
|
||||
})
|
||||
// 检查数据格式并转换
|
||||
const upstreamCounts = Array.isArray(props.messageStats.upstreamCounts)
|
||||
? props.messageStats.upstreamCounts
|
||||
: Object.entries(props.messageStats.upstreamCounts || {}).map(([key, value]) => ({ [key]: value }))
|
||||
|
||||
const downstreamCounts = Array.isArray(props.messageStats.downstreamCounts)
|
||||
? props.messageStats.downstreamCounts
|
||||
: Object.entries(props.messageStats.downstreamCounts || {}).map(([key, value]) => ({ [key]: value }))
|
||||
|
||||
// 获取所有时间戳并排序
|
||||
let timestamps: number[] = []
|
||||
|
||||
try {
|
||||
// 尝试从数组中提取时间戳
|
||||
if (Array.isArray(upstreamCounts) && upstreamCounts.length > 0) {
|
||||
timestamps = Array.from(
|
||||
new Set([
|
||||
...upstreamCounts.map(item => Number(Object.keys(item)[0])),
|
||||
...downstreamCounts.map(item => Number(Object.keys(item)[0]))
|
||||
])
|
||||
).sort((a, b) => a - b)
|
||||
} else {
|
||||
// 如果数组为空或不是数组,尝试从对象中提取时间戳
|
||||
const upKeys = Object.keys(props.messageStats.upstreamCounts || {}).map(Number)
|
||||
const downKeys = Object.keys(props.messageStats.downstreamCounts || {}).map(Number)
|
||||
timestamps = Array.from(new Set([...upKeys, ...downKeys])).sort((a, b) => a - b)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提取时间戳出错:', error)
|
||||
timestamps = []
|
||||
}
|
||||
|
||||
|
||||
// 准备数据
|
||||
const xdata = timestamps.map((ts) => formatDate(dayjs(ts).toDate(), 'YYYY-MM-DD HH:mm'))
|
||||
|
||||
let upData: number[] = []
|
||||
let downData: number[] = []
|
||||
|
||||
try {
|
||||
// 尝试从数组中提取数据
|
||||
if (Array.isArray(upstreamCounts) && upstreamCounts.length > 0) {
|
||||
upData = timestamps.map((ts) => {
|
||||
const item = upstreamCounts.find(count =>
|
||||
Number(Object.keys(count)[0]) === ts
|
||||
)
|
||||
return item ? Number(Object.values(item)[0]) : 0
|
||||
})
|
||||
|
||||
downData = timestamps.map((ts) => {
|
||||
const item = downstreamCounts.find(count =>
|
||||
Number(Object.keys(count)[0]) === ts
|
||||
)
|
||||
return item ? Number(Object.values(item)[0]) : 0
|
||||
})
|
||||
} else {
|
||||
// 如果数组为空或不是数组,尝试从对象中提取数据
|
||||
const upstreamObj = props.messageStats.upstreamCounts || {}
|
||||
const downstreamObj = props.messageStats.downstreamCounts || {}
|
||||
upData = timestamps.map((ts) => Number(upstreamObj[ts as keyof typeof upstreamObj] || 0))
|
||||
downData = timestamps.map((ts) => Number(downstreamObj[ts as keyof typeof downstreamObj] || 0))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提取数据出错:', error)
|
||||
upData = []
|
||||
downData = []
|
||||
}
|
||||
|
||||
console.log(xdata, upData, downData)
|
||||
|
||||
// 配置图表
|
||||
const chart = echarts.init(messageChartRef.value)
|
||||
|
|
|
|||
|
|
@ -124,6 +124,8 @@ const getStats = async () => {
|
|||
statsData.value = await ProductCategoryApi.getIotStatisticsSummary()
|
||||
// 获取消息统计数据
|
||||
messageStats.value = await ProductCategoryApi.getIotStatisticsDeviceMessageSummary(queryParams)
|
||||
console.log('statsData', statsData.value)
|
||||
console.log('messageStats', messageStats.value)
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue