Files
l2-g30/src/views/l2/track/components/FurCurrent.vue
砂糖 98678cc043 feat: 添加PDF和图片生成库并优化打印功能
refactor(FurCurrent): 重构参数显示逻辑,优化闪烁效果
style(FurnaceHistoryPanel): 调整表格列宽和溢出处理
feat(LabelPrint): 使用dom-to-image提升打印质量
feat(QualityCertificate): 添加生产过程曲线图表
feat: 新增ParamEcharts组件用于统一图表渲染
refactor(line): 使用ParamEcharts重构监控图表组件
2026-01-03 13:37:27 +08:00

179 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 炉火参数表单 -->
<div class="app-container">
<!-- flex布局容器开启自动换行 -->
<div class="params-list">
<!-- 遍历筛选后的驱动数据键值对 -->
<div
v-for="[key, value] in filteredDriveData"
:key="key"
:class="['param-item', { blink: blinkKeyMap[key] }]"
>
<!-- 上方label -->
<span class="param-label">{{ formatLabel(key) }}</span>
<!-- 下方value -->
<span class="param-value">{{ formatValue(value) }}</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'FurCurrent',
props: {
driveData: {
type: Object,
default: () => ({})
}
},
data() {
return {
prevDriveData: {}, // 存储上一次的驱动数据,用于对比变化
blinkKeyMap: {}, // 每个key独立的闪烁状态对象形式{ key1: true, key2: false }
timerMap: {} // 每个key独立的定时器缓存用于清除旧定时器
}
},
// 筛选包含Actual不区分大小写的键值对
computed: {
filteredDriveData() {
// 校验
if (!this.driveData || typeof this.driveData !== 'object') {
return [];
}
return Object.entries(this.driveData).filter(([key]) => {
return key.toLowerCase().includes('actual');
});
}
},
watch: {
driveData: {
handler(newVal) {
if (Object.keys(this.prevDriveData).length === 0) {
// 首次加载数据,仅缓存数据,不触发闪烁
this.prevDriveData = JSON.parse(JSON.stringify(newVal));
return;
}
// 对比新值和旧值,找出变化的属性名
Object.entries(newVal).forEach(([key, value]) => {
// 仅对比已有属性的变化且仅处理筛选后的key包含Actual
if (this.prevDriveData.hasOwnProperty(key) && key.toLowerCase().includes('actual')) {
if (this.prevDriveData[key] !== value) {
this.triggerBlink(key); // 为每个变化的key单独触发闪烁
}
}
});
// 更新缓存的旧数据
this.prevDriveData = JSON.parse(JSON.stringify(newVal));
},
deep: true
}
},
methods: {
// 单独触发某个key的闪烁核心优化独立控制
triggerBlink(key) {
// 清除该key的旧定时器避免1秒内多次更新导致定时器叠加
if (this.timerMap[key]) {
clearTimeout(this.timerMap[key]);
}
// 设置当前key为闪烁状态触发动画
this.$set(this.blinkKeyMap, key, true);
// 单独为该key设置定时器到期后关闭闪烁状态
this.timerMap[key] = setTimeout(() => {
this.$set(this.blinkKeyMap, key, false);
// 定时器执行后清除缓存的定时器ID
delete this.timerMap[key];
}, 500); // 闪烁时长可自定义1秒
},
// 格式化标签名(将驼峰命名转为中文式分段,提升可读性)
formatLabel(key) {
if (!key) return '';
// 驼峰命名转空格分隔
const result = key.replace(/([A-Z])/g, ' $1');
// 首字母大写
return result.charAt(0).toUpperCase() + result.slice(1);
},
// 格式化值数字类型保留4位小数提升展示美观度
formatValue(value) {
if (typeof value === 'number') {
return value.toFixed(4);
}
return value;
}
},
// 组件销毁时清除所有定时器,避免内存泄漏
beforeUnmount() {
Object.values(this.timerMap).forEach(timer => {
clearTimeout(timer);
});
}
}
</script>
<style scoped>
.app-container {
border-radius: 8px;
min-height: 100vh;
}
/* flex布局容器 - 开启换行 */
.params-list {
display: flex;
flex-wrap: wrap; /* flex自动换行核心属性 */
gap: 16px; /* 项目之间的间距(水平+垂直) */
margin-top: 20px;
}
/* 固定宽度的参数项 - 内部上下布局 */
.param-item {
width: 200px; /* 固定宽度,可根据需求调整 */
padding: 12px 16px;
background-color: #ffffff;
border: 2px solid #e6e6e6;
border-radius: 6px;
transition: all 0.3s ease;
display: flex; /* 内部flex垂直布局 */
flex-direction: column; /* 垂直排列label在上value在下 */
align-items: flex-start; /* 左对齐可改为center居中 */
gap: 8px; /* label和value之间的垂直间距 */
}
.param-label {
font-weight: 500;
color: #333333;
font-size: 14px;
word-wrap: break-word; /* 超长label自动换行 */
}
.param-value {
color: #666666;
font-family: 'Courier New', monospace; /* 等宽字体,数字对齐更美观 */
font-size: 15px;
}
/* 闪烁动画定义(保留原有动画效果,优化触发逻辑) */
@keyframes borderBlink {
0% {
border-color: #4cd964; /* 初始绿色 */
box-shadow: 0 0 0 0 rgba(76, 217, 100, 0.2);
}
50% {
border-color: #28a745; /* 深绿色 */
box-shadow: 0 0 8px 2px rgba(76, 217, 100, 0.5);
}
100% {
border-color: #4cd964; /* 恢复初始绿色 */
box-shadow: 0 0 0 0 rgba(76, 217, 100, 0.2);
}
}
/* 闪烁样式每次blink类添加时动画重新触发 */
.blink {
border: 2px solid #4cd964; /* 绿色边框 */
animation: borderBlink 0.5s ease-in-out 1; /* 强制执行1次动画避免叠加 */
}
</style>