feat:iothome
This commit is contained in:
@ -16,10 +16,15 @@ export interface IotStatisticsSummaryRespVO {
|
|||||||
productCategoryDeviceCounts: Record<string, number>
|
productCategoryDeviceCounts: Record<string, number>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 时间戳-数值的键值对类型 */
|
||||||
|
interface TimeValueItem {
|
||||||
|
[key: string]: number
|
||||||
|
}
|
||||||
|
|
||||||
/** IoT 消息统计数据类型 */
|
/** IoT 消息统计数据类型 */
|
||||||
export interface IotStatisticsDeviceMessageSummaryRespVO {
|
export interface IotStatisticsDeviceMessageSummaryRespVO {
|
||||||
upstreamCounts: Record<number, number>
|
upstreamCounts: TimeValueItem[]
|
||||||
downstreamCounts: Record<number, number>
|
downstreamCounts: TimeValueItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// IoT 数据统计 API
|
// IoT 数据统计 API
|
||||||
|
|||||||
@ -330,3 +330,30 @@ export function getDateRange(
|
|||||||
dayjs(endDate).endOf('d').format('YYYY-MM-DD HH:mm:ss')
|
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 { GridComponent, LegendComponent, TooltipComponent } from 'echarts/components'
|
||||||
import { UniversalTransition } from 'echarts/features'
|
import { UniversalTransition } from 'echarts/features'
|
||||||
import { IotStatisticsDeviceMessageSummaryRespVO } from '@/api/iot/statistics'
|
import { IotStatisticsDeviceMessageSummaryRespVO } from '@/api/iot/statistics'
|
||||||
import { formatDate } from '@/utils/formatTime'
|
import { formatDate, getTimeRangeStart } from '@/utils/formatTime'
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
/** 消息趋势统计卡片 */
|
/** 消息趋势统计卡片 */
|
||||||
defineOptions({ name: 'MessageTrendCard' })
|
defineOptions({ name: 'MessageTrendCard' })
|
||||||
@ -48,27 +49,14 @@ const props = defineProps({
|
|||||||
const emit = defineEmits(['timeRangeChange'])
|
const emit = defineEmits(['timeRangeChange'])
|
||||||
|
|
||||||
const timeRange = ref('7d')
|
const timeRange = ref('7d')
|
||||||
const dateRange = ref<[Date, Date] | null>(null)
|
const dateRange = ref<any>(null)
|
||||||
const messageChartRef = ref()
|
const messageChartRef = ref()
|
||||||
|
|
||||||
|
// TODO @super:这个的计算,看看能不能结合 dayjs 简化。因为 1h、24h、7d 感觉是比较标准的。如果没有,抽到 utils/formatTime.ts 作为一个工具方法
|
||||||
// 处理快捷时间范围选择
|
// 处理快捷时间范围选择
|
||||||
const handleTimeRangeChange = (range: string) => {
|
const handleTimeRangeChange = (range: string) => {
|
||||||
const now = Date.now()
|
const now = dayjs().valueOf()
|
||||||
let startTime: number
|
const startTime = getTimeRangeStart(range as '8h' | '24h' | '7d')
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
dateRange.value = null
|
dateRange.value = null
|
||||||
emit('timeRangeChange', { startTime, endTime: now })
|
emit('timeRangeChange', { startTime, endTime: now })
|
||||||
@ -96,31 +84,75 @@ const initChart = () => {
|
|||||||
UniversalTransition
|
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 upstreamCounts = Array.isArray(props.messageStats.upstreamCounts)
|
||||||
const upData = timestamps.map((ts) => {
|
? props.messageStats.upstreamCounts
|
||||||
const item = props.messageStats.upstreamCounts.find(
|
: Object.entries(props.messageStats.upstreamCounts || {}).map(([key, value]) => ({ [key]: value }))
|
||||||
(count) => Number(Object.keys(count)[0]) === ts
|
|
||||||
)
|
const downstreamCounts = Array.isArray(props.messageStats.downstreamCounts)
|
||||||
return item ? Object.values(item)[0] : 0
|
? props.messageStats.downstreamCounts
|
||||||
})
|
: Object.entries(props.messageStats.downstreamCounts || {}).map(([key, value]) => ({ [key]: value }))
|
||||||
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
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取所有时间戳并排序
|
// 获取所有时间戳并排序
|
||||||
|
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)
|
const chart = echarts.init(messageChartRef.value)
|
||||||
|
|||||||
@ -124,6 +124,8 @@ const getStats = async () => {
|
|||||||
statsData.value = await ProductCategoryApi.getIotStatisticsSummary()
|
statsData.value = await ProductCategoryApi.getIotStatisticsSummary()
|
||||||
// 获取消息统计数据
|
// 获取消息统计数据
|
||||||
messageStats.value = await ProductCategoryApi.getIotStatisticsDeviceMessageSummary(queryParams)
|
messageStats.value = await ProductCategoryApi.getIotStatisticsDeviceMessageSummary(queryParams)
|
||||||
|
console.log('statsData', statsData.value)
|
||||||
|
console.log('messageStats', messageStats.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
|
|||||||
Reference in New Issue
Block a user