feat;iothome
This commit is contained in:
87
src/views/iot/home/components/DeviceCountCard.vue
Normal file
87
src/views/iot/home/components/DeviceCountCard.vue
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<template>
|
||||||
|
<el-card class="chart-card" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="text-base font-medium text-gray-600">设备数量统计</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div ref="deviceCountChartRef" class="h-[240px]"></div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import * as echarts from 'echarts/core'
|
||||||
|
import { PieChart } from 'echarts/charts'
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers'
|
||||||
|
import { TooltipComponent, LegendComponent } from 'echarts/components'
|
||||||
|
import { LabelLayout } from 'echarts/features'
|
||||||
|
import { IotStatisticsSummaryRespVO } from '@/api/iot/statistics'
|
||||||
|
|
||||||
|
/** 设备数量统计卡片 */
|
||||||
|
defineOptions({ name: 'DeviceCountCard' })
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
statsData: {
|
||||||
|
type: Object as PropType<IotStatisticsSummaryRespVO>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const deviceCountChartRef = ref()
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
const initChart = () => {
|
||||||
|
echarts.use([TooltipComponent, LegendComponent, PieChart, CanvasRenderer, LabelLayout])
|
||||||
|
|
||||||
|
const chart = echarts.init(deviceCountChartRef.value)
|
||||||
|
chart.setOption({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: '5%',
|
||||||
|
right: '10%',
|
||||||
|
align: 'left',
|
||||||
|
orient: 'vertical',
|
||||||
|
icon: 'circle'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['50%', '80%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
center: ['30%', '50%'],
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'outside'
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: Object.entries(props.statsData.productCategoryDeviceCounts).map(([name, value]) => ({
|
||||||
|
name,
|
||||||
|
value
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听数据变化
|
||||||
|
watch(() => props.statsData, () => {
|
||||||
|
initChart()
|
||||||
|
}, { deep: true })
|
||||||
|
|
||||||
|
// 组件挂载时初始化图表
|
||||||
|
onMounted(() => {
|
||||||
|
initChart()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
119
src/views/iot/home/components/DeviceStateCountCard.vue
Normal file
119
src/views/iot/home/components/DeviceStateCountCard.vue
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
<template>
|
||||||
|
<el-card class="chart-card" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="text-base font-medium text-gray-600">设备状态统计</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-row class="h-[240px]">
|
||||||
|
<el-col :span="8" class="flex flex-col items-center">
|
||||||
|
<div ref="deviceOnlineCountChartRef" class="h-[160px] w-full"></div>
|
||||||
|
<div class="text-center mt-2">
|
||||||
|
<span class="text-sm text-gray-600">在线设备</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8" class="flex flex-col items-center">
|
||||||
|
<div ref="deviceOfflineChartRef" class="h-[160px] w-full"></div>
|
||||||
|
<div class="text-center mt-2">
|
||||||
|
<span class="text-sm text-gray-600">离线设备</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8" class="flex flex-col items-center">
|
||||||
|
<div ref="deviceActiveChartRef" class="h-[160px] w-full"></div>
|
||||||
|
<div class="text-center mt-2">
|
||||||
|
<span class="text-sm text-gray-600">待激活设备</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import * as echarts from 'echarts/core'
|
||||||
|
import { GaugeChart } from 'echarts/charts'
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers'
|
||||||
|
import { IotStatisticsSummaryRespVO } from '@/api/iot/statistics'
|
||||||
|
|
||||||
|
/** 设备状态统计卡片 */
|
||||||
|
defineOptions({ name: 'DeviceStateCountCard' })
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
statsData: {
|
||||||
|
type: Object as PropType<IotStatisticsSummaryRespVO>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const deviceOnlineCountChartRef = ref()
|
||||||
|
const deviceOfflineChartRef = ref()
|
||||||
|
const deviceActiveChartRef = ref()
|
||||||
|
|
||||||
|
// 初始化仪表盘图表
|
||||||
|
const initGaugeChart = (el: any, value: number, color: string) => {
|
||||||
|
echarts.use([GaugeChart, CanvasRenderer])
|
||||||
|
|
||||||
|
const chart = echarts.init(el)
|
||||||
|
chart.setOption({
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'gauge',
|
||||||
|
startAngle: 360,
|
||||||
|
endAngle: 0,
|
||||||
|
min: 0,
|
||||||
|
max: props.statsData.deviceCount || 100, // 使用设备总数作为最大值
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
width: 12,
|
||||||
|
itemStyle: {
|
||||||
|
color: color
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
width: 12,
|
||||||
|
color: [[1, '#E5E7EB']]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: { show: false },
|
||||||
|
splitLine: { show: false },
|
||||||
|
axisLabel: { show: false },
|
||||||
|
pointer: { show: false },
|
||||||
|
anchor: { show: false },
|
||||||
|
title: { show: false },
|
||||||
|
detail: {
|
||||||
|
valueAnimation: true,
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontFamily: 'Inter, sans-serif',
|
||||||
|
color: color,
|
||||||
|
offsetCenter: [0, '0'],
|
||||||
|
formatter: (value: number) => {
|
||||||
|
return `${value} 个`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [{ value: value }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化所有图表
|
||||||
|
const initCharts = () => {
|
||||||
|
// 在线设备统计
|
||||||
|
initGaugeChart(deviceOnlineCountChartRef.value, props.statsData.deviceOnlineCount, '#0d9')
|
||||||
|
// 离线设备统计
|
||||||
|
initGaugeChart(deviceOfflineChartRef.value, props.statsData.deviceOfflineCount, '#f50')
|
||||||
|
// 待激活设备统计
|
||||||
|
initGaugeChart(deviceActiveChartRef.value, props.statsData.deviceInactiveCount, '#05b')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听数据变化
|
||||||
|
watch(() => props.statsData, () => {
|
||||||
|
initCharts()
|
||||||
|
}, { deep: true })
|
||||||
|
|
||||||
|
// 组件挂载时初始化图表
|
||||||
|
onMounted(() => {
|
||||||
|
initCharts()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
0
src/views/iot/home/components/MessageTrendCard.vue
Normal file
0
src/views/iot/home/components/MessageTrendCard.vue
Normal file
@ -42,43 +42,10 @@
|
|||||||
<!-- 第二行:图表行 -->
|
<!-- 第二行:图表行 -->
|
||||||
<el-row :gutter="16" class="mb-4">
|
<el-row :gutter="16" class="mb-4">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-card class="chart-card" shadow="never">
|
<DeviceCountCard :statsData="statsData" />
|
||||||
<template #header>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<span class="text-base font-medium text-gray-600">设备数量统计</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div ref="deviceCountChartRef" class="h-[240px]"></div>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-card class="chart-card" shadow="never">
|
<DeviceStateCountCard :statsData="statsData" />
|
||||||
<template #header>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<span class="text-base font-medium text-gray-600">设备状态统计</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-row class="h-[240px]">
|
|
||||||
<el-col :span="8" class="flex flex-col items-center">
|
|
||||||
<div ref="deviceOnlineCountChartRef" class="h-[160px] w-full"></div>
|
|
||||||
<div class="text-center mt-2">
|
|
||||||
<span class="text-sm text-gray-600">在线设备</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8" class="flex flex-col items-center">
|
|
||||||
<div ref="deviceOfflineChartRef" class="h-[160px] w-full"></div>
|
|
||||||
<div class="text-center mt-2">
|
|
||||||
<span class="text-sm text-gray-600">离线设备</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8" class="flex flex-col items-center">
|
|
||||||
<div ref="deviceActiveChartRef" class="h-[160px] w-full"></div>
|
|
||||||
<div class="text-center mt-2">
|
|
||||||
<span class="text-sm text-gray-600">待激活设备</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
@ -134,6 +101,8 @@ import {
|
|||||||
} from '@/api/iot/statistics'
|
} from '@/api/iot/statistics'
|
||||||
import { formatDate } from '@/utils/formatTime'
|
import { formatDate } from '@/utils/formatTime'
|
||||||
import ComparisonCard from './components/ComparisonCard.vue'
|
import ComparisonCard from './components/ComparisonCard.vue'
|
||||||
|
import DeviceCountCard from './components/DeviceCountCard.vue'
|
||||||
|
import DeviceStateCountCard from './components/DeviceStateCountCard.vue'
|
||||||
|
|
||||||
// TODO @super:参考下 /Users/yunai/Java/yudao-ui-admin-vue3/src/views/mall/home/index.vue,拆一拆组件
|
// TODO @super:参考下 /Users/yunai/Java/yudao-ui-admin-vue3/src/views/mall/home/index.vue,拆一拆组件
|
||||||
|
|
||||||
@ -252,104 +221,10 @@ const getStats = async () => {
|
|||||||
|
|
||||||
/** 初始化图表 */
|
/** 初始化图表 */
|
||||||
const initCharts = () => {
|
const initCharts = () => {
|
||||||
// 设备数量统计
|
|
||||||
echarts.init(deviceCountChartRef.value).setOption({
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item'
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
top: '5%',
|
|
||||||
right: '10%',
|
|
||||||
align: 'left',
|
|
||||||
orient: 'vertical',
|
|
||||||
icon: 'circle'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'Access From',
|
|
||||||
type: 'pie',
|
|
||||||
radius: ['50%', '80%'],
|
|
||||||
avoidLabelOverlap: false,
|
|
||||||
center: ['30%', '50%'],
|
|
||||||
label: {
|
|
||||||
show: false,
|
|
||||||
position: 'outside'
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: 'bold'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: Object.entries(statsData.value.productCategoryDeviceCounts).map(([name, value]) => ({
|
|
||||||
name,
|
|
||||||
value
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
// 在线设备统计
|
|
||||||
initGaugeChart(deviceOnlineCountChartRef.value, statsData.value.deviceOnlineCount, '#0d9')
|
|
||||||
// 离线设备统计
|
|
||||||
initGaugeChart(deviceOfflineChartRef.value, statsData.value.deviceOfflineCount, '#f50')
|
|
||||||
// 待激活设备统计
|
|
||||||
initGaugeChart(deviceActiveChartRef.value, statsData.value.deviceInactiveCount, '#05b')
|
|
||||||
|
|
||||||
// 消息量统计
|
// 消息量统计
|
||||||
initMessageChart()
|
initMessageChart()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化仪表盘图表 */
|
|
||||||
const initGaugeChart = (el: any, value: number, color: string) => {
|
|
||||||
echarts.init(el).setOption({
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'gauge',
|
|
||||||
startAngle: 360,
|
|
||||||
endAngle: 0,
|
|
||||||
min: 0,
|
|
||||||
max: statsData.value.deviceCount || 100, // 使用设备总数作为最大值
|
|
||||||
progress: {
|
|
||||||
show: true,
|
|
||||||
width: 12,
|
|
||||||
itemStyle: {
|
|
||||||
color: color
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
width: 12,
|
|
||||||
color: [[1, '#E5E7EB']]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: { show: false },
|
|
||||||
splitLine: { show: false },
|
|
||||||
axisLabel: { show: false },
|
|
||||||
pointer: { show: false },
|
|
||||||
anchor: { show: false },
|
|
||||||
title: { show: false },
|
|
||||||
detail: {
|
|
||||||
valueAnimation: true,
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
fontFamily: 'Inter, sans-serif',
|
|
||||||
color: color,
|
|
||||||
offsetCenter: [0, '0'],
|
|
||||||
formatter: (value: number) => {
|
|
||||||
return `${value} 个`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [{ value: value }]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 初始化消息统计图表 */
|
/** 初始化消息统计图表 */
|
||||||
const initMessageChart = () => {
|
const initMessageChart = () => {
|
||||||
// 获取所有时间戳并排序
|
// 获取所有时间戳并排序
|
||||||
|
|||||||
Reference in New Issue
Block a user