可视化大屏系列(5):设备状态面板与数据分析仪表盘
文章目录:
- 一、项目背景与功能概述
- 二、设备状态数据采集与接口设计
- 三、仪表盘组件封装与调用
- 四、工况统计图表设计与实现
- 五、告警与预警机制集成
- 六、视觉表现优化与交互细节
- 七、总结与后续优化方向
一、项目背景与功能概述
在智慧工地系统中,设备状态监测与工况统计是确保施工效率与安全的关键环节。本篇将围绕“设备状态可视化”与“数据仪表盘分析”,介绍如何基于 Vue3 + ECharts 打造高性能、易维护的数据展示面板,提升数据洞察与现场响应能力。
1. 项目代码结构
为了保持项目的整洁与可维护性,我们的代码结构应该符合常见的 Vue 3 项目规范,下面是完整的代码仓库结构示例:
├── src
│ ├── assets # 项目静态资源(图片、图标等)
│ ├── components # 可复用组件
│ │ ├── Dashboard
│ │ │ ├── EChartGauge.vue # 仪表盘组件
│ │ ├── DevicePanel.vue # 设备面板
│ ├── api # 请求接口封装
│ │ └── device.ts # 设备接口
│ ├── views # 页面组件
│ │ └── Dashboard.vue # 仪表盘展示页面
│ ├── utils # 工具类(如请求、格式化等)
│ │ └── request.ts # 请求封装
│ ├── App.vue # 根组件
│ └── main.ts # 入口文件
└── public
└── index.html # HTML入口文件
代码说明:
src/components/Dashboard/EChartGauge.vue
:封装的仪表盘组件。src/api/device.ts
:设备接口模块,负责设备状态数据的获取。src/views/Dashboard.vue
:仪表盘页面,展示设备状态的多个图表组件。src/utils/request.ts
:用于封装请求方法,简化接口调用。src/main.ts
:项目的入口文件,初始化 Vue 实例。
二、设备状态数据采集与接口设计
设备状态通常通过物联网采集网关(如 PLC、RTU、传感器集线器)上传,经过边缘网关汇总后推送至后端系统,前端通过定时轮询或 WebSocket 获取。
1. 数据结构定义
后端应设计清晰、可拓展的设备数据结构,例如:
// 接口返回示例(单设备)
{
deviceId: "DZ-001",
name: "塔吊 01",
status: "运行中", // 停止/故障/维修/离线...
voltage: 220,
temperature: 36.5,
runningTime: 315, // 单位分钟
lastUpdate: "2025-04-21 14:03:00"
}
2. 后端接口设计规范
推荐使用 RESTful 风格,接口统一前缀 /api/device
:
方法 | 接口地址 | 描述 |
---|---|---|
GET | /api/device/status/list | 获取设备状态列表 |
GET | /api/device/status/:id | 获取指定设备状态 |
GET | /api/device/stats/runtime | 获取运行时长统计数据 |
GET | /api/device/stats/alarm | 获取告警数据统计 |
3. 前端接口封装(/src/api/device.ts
)
为了便于调用和维护,封装成模块化接口:
// src/api/device.ts
import request from '@/utils/request'
// 获取所有设备当前状态
export const getDeviceStatusList = () => {
return request.get('/api/device/status/list')
}
// 获取单个设备状态详情
export const getDeviceStatusById = (id: string) => {
return request.get(`/api/device/status/${id}`)
}
// 获取设备运行时长统计数据
export const getDeviceRuntimeStats = () => {
return request.get('/api/device/stats/runtime')
}
4. 示例:获取设备状态列表并绑定图表组件
// src/views/dashboard/DevicePanel.vue
import { getDeviceStatusList } from '@/api/device'
import { ref, onMounted } from 'vue'
const deviceList = ref([])
const fetchDeviceStatus = async () => {
try {
const res = await getDeviceStatusList()
deviceList.value = res.data
} catch (error) {
console.error('设备状态获取失败:', error)
}
}
onMounted(() => {
fetchDeviceStatus()
})
5. 实时数据更新方案(定时轮询 + WebSocket)
✅ 方案 A:定时轮询刷新设备状态(适合中低频设备)
onMounted(() => {
fetchDeviceStatus()
setInterval(fetchDeviceStatus, 10000) // 每10秒刷新一次
})
✅ 方案 B:WebSocket 实时推送(适合状态变更频繁场景)
let ws = new WebSocket('wss://example.com/ws/device/status')
ws.onmessage = (msg) => {
const newStatus = JSON.parse(msg.data)
const index = deviceList.value.findIndex(d => d.deviceId === newStatus.deviceId)
if (index > -1) {
deviceList.value[index] = newStatus
} else {
deviceList.value.push(newStatus)
}
}
6. 异常状态字段说明与 UI 标识
设备的运行状态不仅是“运行/停止”,还可能包括异常、预警、维护中等状态,可定义状态枚举与颜色提示:
const statusMap = {
'运行中': 'success',
'停止': 'info',
'故障': 'danger',
'预警': 'warning',
'离线': 'gray'
}
配合 UI 展示:
<el-tag :type="statusMap[item.status]">{{ item.status }}</el-tag>
7. 最佳实践建议
- 每条设备数据应包含时间戳字段
lastUpdate
,用于判断是否超时或离线; - 为每种设备类型设置不同的图表模板与颜色;
- WebSocket 仅用于状态变更通知,详细数据仍可通过接口拉取;
- 可引入缓存策略减少频繁请求(如 Vue Query/SWR)。
好的,继续写 “三、仪表盘组件封装与调用”,并配合完整的代码仓库结构说明。
三、仪表盘组件封装与调用
1. 仪表盘组件封装
1.1 仪表盘组件设计
我们将使用 uView UI
和 ECharts
来实现一个通用的仪表盘组件。uView UI
提供了常用的 UI 控件,ECharts
可以帮助我们更好地呈现图表数据。
<!-- src/components/Dashboard/EChartGauge.vue -->
<template>
<div class="dashboard-container">
<div ref="chart" class="dashboard-chart"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'EChartGauge',
props: {
value: {
type: Number,
required: true
},
minValue: {
type: Number,
default: 0
},
maxValue: {
type: Number,
default: 100
},
title: {
type: String,
default: '设备状态'
}
},
mounted() {
this.renderChart()
},
watch: {
value() {
this.renderChart()
}
},
methods: {
renderChart() {
const chart = echarts.init(this.$refs.chart)
const option = {
title: {
text: this.title,
x: 'center',
y: 'center'
},
tooltip: {
formatter: '{a} <br/> {c} {b}'
},
series: [
{
name: '设备状态',
type: 'gauge',
detail: {
formatter: '{value} %'
},
data: [
{
value: this.value,
name: '状态'
}
],
axisLine: {
lineStyle: {
color: [
[0.2, '#ff4500'],
[0.8, '#ffb600'],
[1, '#62d500']
],
width: 30
}
}
}
]
}
chart.setOption(option)
}
}
}
</script>
<style scoped>
.dashboard-container {
width: 100%;
height: 300px;
}
.dashboard-chart {
width: 100%;
height: 100%;
}
</style>
1.2 组件解释
value
:仪表盘的当前值(例如设备的运行时长、电压等)。此值将动态变化,影响仪表盘的显示。minValue
和maxValue
:设定仪表盘的最小值与最大值,通常为设备的状态范围(如 0-100%)。title
:仪表盘的标题,默认显示“设备状态”。renderChart()
:使用ECharts
渲染仪表盘,通过设置gauge
类型来显示数据。
2. 仪表盘组件的封装与复用
这个组件非常通用,可以在不同的设备面板中使用。接下来,展示如何将其用于实际的设备状态面板中。
2.1 设备面板中引用仪表盘组件
<template>
<div class="device-panel">
<EChartGauge
:value="deviceData.voltage"
:minValue="0"
:maxValue="500"
title="设备电压"
/>
<EChartGauge
:value="deviceData.temperature"
:minValue="0"
:maxValue="100"
title="设备温度"
/>
</div>
</template>
<script>
import { ref, onMounted } from 'vue'
import { getDeviceStatusById } from '@/api/device'
import EChartGauge from '@/components/Dashboard/EChartGauge.vue'
export default {
components: {
EChartGauge
},
setup() {
const deviceData = ref({
voltage: 0,
temperature: 0
})
const fetchDeviceData = async (deviceId) => {
const res = await getDeviceStatusById(deviceId)
deviceData.value = res.data
}
onMounted(() => {
fetchDeviceData('DZ-001')
})
return {
deviceData
}
}
}
</script>
<style scoped>
.device-panel {
display: flex;
justify-content: space-around;
align-items: center;
margin-top: 20px;
}
</style>
2.2 组件使用解释
EChartGauge
:仪表盘组件在设备面板中被引用,分别用于展示设备的电压和温度。getDeviceStatusById
:前端通过接口获取设备状态数据,并动态更新到仪表盘中。- 通过
v-bind
绑定组件的value
属性,实时更新仪表盘的数值。
3. 仪表盘复用性与扩展
通过对 EChartGauge
组件的封装,我们可以在不同的地方复用它,只需传入不同的数值、最大值、最小值和标题即可。此外,随着项目的进展,我们可能需要为设备状态仪表盘增加更多功能,如:
- 支持多种图表样式:环形图、柱状图等;
- 提供详细的趋势分析;
- 集成历史数据查看功能。
四、工况统计图表设计与实现
使用 ECharts
来设计和实现各种工况统计图表,包括饼图、柱状图等。
1. 工况统计图表需求分析
工况统计图表的展示需求主要有以下几种类型:
- 设备运行状态统计:如设备的正常、异常、待修等状态比例。
- 工地人员工作状态:如人员在岗、离岗、休息等状态。
- 环境监测数据:如空气质量、温度、湿度等实时数据。
2. 工况统计图表设计
基于上述需求,我们设计了以下几种常见的统计图表:
- 饼图:用于显示状态比例(如设备正常与异常比例)。
- 柱状图:用于展示趋势变化(如温度、湿度等监测数据的变化)。
- 折线图:用于展示数据的时间变化趋势(如设备运行时长的变化)。
3. 使用 ECharts
实现工况统计图表
3.1 饼图(设备状态统计)
饼图非常适合展示各个状态的比例关系,例如设备的正常与异常状态。
<!-- src/components/Charts/PieChart.vue -->
<template>
<div ref="pieChart" class="chart-container"></div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'PieChart',
props: {
data: {
type: Array,
required: true
},
title: {
type: String,
default: '设备状态'
}
},
mounted() {
this.renderChart()
},
watch: {
data() {
this.renderChart()
}
},
methods: {
renderChart() {
const chart = echarts.init(this.$refs.pieChart)
const option = {
title: {
text: this.title,
left: 'center',
top: '10'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/> {b} : {c} ({d}%)'
},
series: [
{
name: '设备状态',
type: 'pie',
radius: '50%',
data: this.data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
chart.setOption(option)
}
}
}
</script>
<style scoped>
.chart-container {
width: 100%;
height: 300px;
}
</style>
3.2 柱状图(环境监测数据)
柱状图适合用于展示一段时间内的环境监测数据,如温度、湿度等的日常变化。
<!-- src/components/Charts/BarChart.vue -->
<template>
<div ref="barChart" class="chart-container"></div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'BarChart',
props: {
data: {
type: Array,
required: true
},
categories: {
type: Array,
required: true
},
title: {
type: String,
default: '环境监测'
}
},
mounted() {
this.renderChart()
},
watch: {
data() {
this.renderChart()
}
},
methods: {
renderChart() {
const chart = echarts.init(this.$refs.barChart)
const option = {
title: {
text: this.title,
left: 'center',
top: '10'
},
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' }
},
xAxis: {
type: 'category',
data: this.categories
},
yAxis: {
type: 'value'
},
series: [
{
name: '监测值',
type: 'bar',
data: this.data
}
]
}
chart.setOption(option)
}
}
}
</script>
<style scoped>
.chart-container {
width: 100%;
height: 300px;
}
</style>
3.3 折线图(设备运行时长趋势)
折线图适合用于展示设备运行时长的趋势,方便监控设备的持续运行情况。
<!-- src/components/Charts/LineChart.vue -->
<template>
<div ref="lineChart" class="chart-container"></div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'LineChart',
props: {
data: {
type: Array,
required: true
},
categories: {
type: Array,
required: true
},
title: {
type: String,
default: '设备运行时长'
}
},
mounted() {
this.renderChart()
},
watch: {
data() {
this.renderChart()
}
},
methods: {
renderChart() {
const chart = echarts.init(this.$refs.lineChart)
const option = {
title: {
text: this.title,
left: 'center',
top: '10'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
data: this.categories
},
yAxis: {
type: 'value'
},
series: [
{
name: '运行时长',
type: 'line',
data: this.data
}
]
}
chart.setOption(option)
}
}
}
</script>
<style scoped>
.chart-container {
width: 100%;
height: 300px;
}
</style>
4. 工况统计图表的集成
<!-- src/views/Dashboard.vue -->
<template>
<div class="dashboard">
<PieChart :data="deviceStatusData" title="设备状态" />
<BarChart :data="environmentData" :categories="environmentCategories" title="环境监测" />
<LineChart :data="deviceRunTimeData" :categories="runTimeCategories" title="设备运行时长" />
</div>
</template>
<script>
import PieChart from '@/components/Charts/PieChart.vue'
import BarChart from '@/components/Charts/BarChart.vue'
import LineChart from '@/components/Charts/LineChart.vue'
export default {
components: {
PieChart,
BarChart,
LineChart
},
data() {
return {
deviceStatusData: [
{ value: 70, name: '正常' },
{ value: 20, name: '异常' },
{ value: 10, name: '待修' }
],
environmentData: [45, 60, 80, 55, 30],
environmentCategories: ['空气质量', '温度', '湿度', '光照', '噪音'],
deviceRunTimeData: [10, 20, 30, 40, 50],
runTimeCategories: ['0:00', '1:00', '2:00', '3:00', '4:00']
}
}
}
</script>
<style scoped>
.dashboard {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
margin-top: 20px;
}
</style>
五、告警与预警机制集成
我们将详细介绍如何在系统中集成告警与预警机制,并通过合适的技术手段提升用户体验。
1. 告警与预警的基本原理
- 设备故障告警:例如设备温度过高、震动异常、状态不正常等。
- 环境异常告警:如空气质量差、气温过低/过高、湿度异常等。
- 人员安全告警:例如人员进入危险区域、未佩戴安全设备等。
2. 告警数据的采集与处理
使用 WebSocket 或 SSE(Server-Sent Events) 技术实现数据的实时传输,并在后端进行数据的实时处理与告警判断。
示例:告警数据采集与处理
// WebSocket 示例代码:设备状态数据推送
const socket = new WebSocket('ws://example.com/socket');
// 监听数据接收
socket.onmessage = (event) => {
const deviceData = JSON.parse(event.data);
// 假设设备数据包含设备ID、状态、温度、湿度等字段
if (deviceData.temperature > 70) {
// 温度异常,触发告警
triggerAlert('设备温度过高', deviceData.deviceId);
}
if (deviceData.status === 'FAULT') {
// 设备故障,触发告警
triggerAlert('设备故障', deviceData.deviceId);
}
};
// 告警触发函数
function triggerAlert(message, deviceId) {
// 发送告警消息
console.log(`告警:设备 ${deviceId} - ${message}`);
// 可以调用后端接口,或者通过 WebSocket 推送告警消息到前端
sendAlertToBackend(message, deviceId);
}
3. 告警触发与消息推送
- 推送通知:使用 WebSocket、长轮询或定时拉取的方式,实时推送告警消息到前端用户。
- 短信/邮件通知:对于重要的告警,可以使用短信、邮件等渠道推送给相关人员,确保他们能及时采取措施。
- 系统内通知:通过系统自带的通知栏、消息中心等,提醒用户查看告警。
示例:告警消息推送实现
// 使用 WebSocket 实时推送告警消息到前端
function sendAlertToBackend(message, deviceId) {
const alertMessage = {
type: 'ALERT',
message: message,
deviceId: deviceId,
timestamp: new Date().toISOString()
};
// 发送告警消息到后台
socket.send(JSON.stringify(alertMessage));
}
4. 告警规则与优先级管理
- 告警等级:为每种告警类型设置不同的级别,如:
信息
、警告
、严重
,并根据级别来决定是否推送告警。 - 重复告警限制:对于同一个设备的告警,可以设置 重复告警限制,避免重复发送相同的告警信息,降低告警频率。
- 告警规则管理:通过后台管理界面,允许管理员设置不同类型设备、传感器的告警阈值、条件及优先级。
示例:告警优先级与规则管理
// 假设我们定义一个告警规则对象
const alertRules = {
deviceTemperature: {
threshold: 70, // 温度阈值
priority: 'HIGH' // 高优先级
},
deviceStatus: {
threshold: 'FAULT',
priority: 'CRITICAL' // 严重级别
}
};
// 根据规则判断是否触发告警
function checkAlertCondition(deviceData) {
if (deviceData.temperature > alertRules.deviceTemperature.threshold) {
triggerAlert(`设备温度过高,温度:${deviceData.temperature}`, deviceData.deviceId, alertRules.deviceTemperature.priority);
}
if (deviceData.status === alertRules.deviceStatus.threshold) {
triggerAlert('设备故障', deviceData.deviceId, alertRules.deviceStatus.priority);
}
}
// 触发告警并根据优先级处理
function triggerAlert(message, deviceId, priority) {
const alert = {
message,
deviceId,
priority,
timestamp: new Date().toISOString()
};
// 根据优先级推送
if (priority === 'CRITICAL') {
sendCriticalAlert(alert);
} else {
sendRegularAlert(alert);
}
}
5. 告警界面与用户交互
- 告警列表:实时显示所有告警信息,支持按照时间、优先级等排序。
- 告警详情:用户可以点击告警,查看详细信息,包括设备信息、发生时间、告警内容等。
- 告警确认与处理:用户可以标记已处理或已确认的告警,确保管理人员及时跟进。
示例:告警信息展示与交互
<!-- 告警列表展示 -->
<template>
<div class="alert-list">
<div v-for="alert in alerts" :key="alert.id" class="alert-item" :class="alert.priority">
<span>{{ alert.message }}</span>
<button @click="acknowledgeAlert(alert.id)">确认</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
alerts: [] // 告警列表
};
},
methods: {
acknowledgeAlert(id) {
// 处理告警确认
this.alerts = this.alerts.filter(alert => alert.id !== id);
},
receiveAlert(alert) {
// 接收到新的告警,添加到列表
this.alerts.push(alert);
}
},
created() {
// 监听 WebSocket,接收告警
socket.onmessage = (event) => {
const alert = JSON.parse(event.data);
this.receiveAlert(alert);
};
}
};
</script>
六、视觉表现优化与交互细节
1. 视觉表现优化
视觉优化的目标是使系统界面更具现代感和可视化效果,同时提升用户的视觉舒适度。我们将从以下几个方面进行视觉优化:
1.1 主题色与配色方案
主题色的选择对于系统的视觉效果至关重要。通常来说,工地管理系统的配色方案应该简洁而有层次,常用的色彩包括蓝色(传达科技感与稳重)、绿色(代表安全和健康)、橙色(用于提醒和警示)。通过合理搭配主色调和辅色,可以提高界面的可读性和信息传递的效果。
/* src/assets/styles/variables.scss */
$primary-color: #4CAF50; /* 绿色,表示安全、健康 */
$secondary-color: #FF9800; /* 橙色,表示警示 */
$background-color: #F1F1F1; /* 背景色,柔和且不刺眼 */
$text-color: #333333; /* 文字色,适中、易读 */
$chart-bg-color: #FFFFFF; /* 图表背景色,确保数据清晰 */
1.2 动态效果与过渡动画
适当的动态效果和过渡动画可以使系统显得更加现代和高效。为图表、按钮和其他交互元素添加动画效果,不仅提升了视觉的流畅感,还增强了用户的操作反馈。
/* 按钮的过渡效果 */
.button {
transition: background-color 0.3s ease, transform 0.3s ease;
}
.button:hover {
background-color: $secondary-color;
transform: scale(1.05);
}
/* 图表加载动画 */
.chart-container {
animation: fadeIn 1s ease-in-out;
}
@keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
1.3 图表优化与美化
在图表的设计中,除了确保数据的准确呈现外,还要注重图表的美观性。例如,通过调整图表的边距、字体大小、数据标签的显示方式等来优化图表的外观,使其既美观又易于理解。
// 优化图表的样式设置,调整标签和字体大小等
const option = {
title: {
text: '设备状态',
left: 'center',
top: '10',
textStyle: {
fontSize: 18,
color: '#333'
}
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/> {b} : {c} ({d}%)',
backgroundColor: 'rgba(0, 0, 0, 0.7)',
textStyle: {
color: '#fff'
}
},
series: [
{
name: '设备状态',
type: 'pie',
radius: '50%',
data: this.data,
itemStyle: {
borderRadius: 10
},
label: {
fontSize: 14,
color: '#555'
}
}
]
}
1.4 自适应布局
由于不同设备的屏幕尺寸和分辨率不同,我们的界面需要做出自适应设计,以确保在各种设备上的良好显示效果。使用 Flexbox 布局可以轻松实现响应式布局,使得图表、表单和其他组件能够根据屏幕宽度自动调整大小。
/* 使用Flexbox布局来响应式设计 */
.dashboard {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
margin-top: 20px;
}
.dashboard .chart-container {
width: 100%;
max-width: 600px;
margin: 10px;
}
@media (max-width: 768px) {
.dashboard {
flex-direction: column;
}
.dashboard .chart-container {
width: 90%;
}
}
2. 交互细节设计
交互设计关注的是系统与用户之间的互动流畅度、反馈及时性和操作的易用性。我们将从以下几个方面提升交互体验。
2.1 交互反馈与提示
在系统中,操作的反馈至关重要,尤其是在用户进行数据输入或操作时。我们需要通过提示信息、进度条、加载动画等形式及时给用户反馈。常见的交互反馈包括数据加载成功、操作成功/失败提示等。
// 示例:操作成功提示
import { showToast } from 'uni-app';
showToast({
title: '操作成功',
icon: 'success',
duration: 2000
});
// 示例:数据加载中提示
showToast({
title: '加载中...',
icon: 'loading',
mask: true
});
2.2 数据更新与实时交互
智能工地系统需要实时更新数据,因此需要使用合适的方式进行数据推送。例如,使用 WebSocket
来接收后端推送的实时数据,并及时更新图表和状态。通过这种方式,用户能够实时看到数据变化,无需手动刷新页面。
// WebSocket 数据实时接收与更新
const socket = new WebSocket('ws://example.com/data');
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
// 更新图表数据
this.chartData = data;
};
// 发送数据
socket.send(JSON.stringify({ action: 'get_data' }));
2.3 手势操作与触控优化
在移动端设备上,用户习惯通过触摸屏进行操作,因此需要特别优化触控体验。例如,图表支持拖拽、缩放等手势操作,提升用户的交互感。
// 使用 `echarts` 实现图表的缩放与拖拽
const chart = echarts.init(this.$refs.chartContainer);
const option = {
toolbox: {
feature: {
dataZoom: {
yAxisIndex: 'none'
}
}
},
dataZoom: [{
type: 'slider',
show: true,
xAxisIndex: [0]
}]
}
chart.setOption(option);
七、总结与后续优化方向
本文总结了智能工地管理系统在实现过程中的优化方向,包括性能优化、安全性增强、用户体验提升、数据分析支持、移动端适配、跨平台功能等方面。未来,随着技术的不断进步与用户需求的不断变化,系统还会继续迭代更新,添加更多的功能和改进,以满足工地管理的需求。
通过这些优化,我们期望能够为用户提供更智能、更高效、更安全的工地管理系统,助力企业提升管理效率、保障工地安全、优化生产流程。如果您有任何问题或建议,欢迎与我们一起探讨。