|
|
@@ -676,7 +676,8 @@ export default {
|
|
|
statusColor: config.color || '#999',
|
|
|
statusLabel: isAbnormal ? config.name : "正常运行",
|
|
|
road: config.road || '规划路口',
|
|
|
- time: new Date().toLocaleString('zh-CN')
|
|
|
+ timestamp: Date.now(),
|
|
|
+ time: this.formatEventTime(Date.now())
|
|
|
}
|
|
|
});
|
|
|
|
|
|
@@ -699,6 +700,9 @@ export default {
|
|
|
|
|
|
const infoWindowId = `info-window-${Date.now()}`;
|
|
|
const isAbnormal = ["离线", "降级", "故障"].includes(data.name);
|
|
|
+ const deviceStatusText = isAbnormal ? data.name : '正常';
|
|
|
+ const alarmInfoText = isAbnormal ? this.getAlarmInfoText(data.name) : '';
|
|
|
+ const eventTimeText = this.formatEventTime(data.timestamp || data.time);
|
|
|
let statusDotContent = '';
|
|
|
|
|
|
if (isAbnormal) {
|
|
|
@@ -712,15 +716,25 @@ export default {
|
|
|
<div class="custom-info-card" id="${infoWindowId}">
|
|
|
<div class="close-btn" data-id="${infoWindowId}">✕</div>
|
|
|
<div class="card-header">
|
|
|
- <div class="status-dot" style="background: ${isAbnormal ? 'transparent' : data.statusColor}; border: ${isAbnormal ? 'none' : ''}">
|
|
|
+ <div class="status-dot ${isAbnormal ? 'breathe' : ''}" style="background: ${isAbnormal ? 'transparent' : data.statusColor}; border: ${isAbnormal ? 'none' : ''}">
|
|
|
${statusDotContent}
|
|
|
</div>
|
|
|
<span class="status-text">${data.statusLabel}</span>
|
|
|
</div>
|
|
|
<div class="card-body">
|
|
|
- <div class="info-line"><span class="label">路口:</span><span class="value">${data.road}</span></div>
|
|
|
- <div class="info-line"><span class="label">路口编号:</span><span class="value digital">${data.id || 'N/A'}</span></div>
|
|
|
- <div class="info-line"><span class="label">发生时间:</span><span class="value digital">${data.time}</span></div>
|
|
|
+ ${isAbnormal
|
|
|
+ ? `
|
|
|
+ <div class="info-line"><span class="label">路口名称:</span><span class="value">${data.road}</span></div>
|
|
|
+ <div class="info-line"><span class="label">设备状态:</span><span class="value digital">${deviceStatusText}</span></div>
|
|
|
+ <div class="info-line"><span class="label">报警信息:</span><span class="value">${alarmInfoText}</span></div>
|
|
|
+ <div class="info-line"><span class="label">发生时间:</span><span class="value digital">${eventTimeText}</span></div>
|
|
|
+ `
|
|
|
+ : `
|
|
|
+ <div class="info-line"><span class="label">中(干/勤/定/感/自/手/特):</span><span class="value">${data.name}</span></div>
|
|
|
+ <div class="info-line"><span class="label">路口名称:</span><span class="value">${data.road}</span></div>
|
|
|
+ <div class="info-line"><span class="label">设备状态:</span><span class="value digital">${deviceStatusText}</span></div>
|
|
|
+ `
|
|
|
+ }
|
|
|
</div>
|
|
|
</div>
|
|
|
`;
|
|
|
@@ -746,6 +760,30 @@ export default {
|
|
|
}, 100);
|
|
|
},
|
|
|
|
|
|
+ getAlarmInfoText(statusName) {
|
|
|
+ if (statusName === '离线') return '通讯中断设备离线';
|
|
|
+ if (statusName === '降级') return '降级定周期控制';
|
|
|
+ if (statusName === '故障') return '东向左转信号灯红绿同亮';
|
|
|
+ return '设备异常';
|
|
|
+ },
|
|
|
+
|
|
|
+ formatEventTime(input) {
|
|
|
+ let d = null;
|
|
|
+ if (input instanceof Date) d = input;
|
|
|
+ else if (typeof input === 'number') d = new Date(input);
|
|
|
+ else if (typeof input === 'string') {
|
|
|
+ const t = Date.parse(input);
|
|
|
+ if (!Number.isNaN(t)) d = new Date(t);
|
|
|
+ }
|
|
|
+ if (!d || Number.isNaN(d.getTime())) d = new Date();
|
|
|
+ const y = d.getFullYear();
|
|
|
+ const m = d.getMonth() + 1;
|
|
|
+ const day = d.getDate();
|
|
|
+ const hh = String(d.getHours()).padStart(2, '0');
|
|
|
+ const mm = String(d.getMinutes()).padStart(2, '0');
|
|
|
+ return `${y}.${m}.${day} ${hh}:${mm}`;
|
|
|
+ },
|
|
|
+
|
|
|
toggleAll() {
|
|
|
const targetState = !this.isAllSelected;
|
|
|
if (!this.isMapReady()) return;
|
|
|
@@ -920,22 +958,33 @@ export default {
|
|
|
}
|
|
|
|
|
|
::v-deep .status-dot {
|
|
|
- width: 18px;
|
|
|
- height: 18px;
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
border-radius: 50%;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
margin-right: 8px;
|
|
|
- font-size: 12px;
|
|
|
- padding: 12px;
|
|
|
+ font-size: 14px;
|
|
|
+ padding: 0;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
+::v-deep .status-dot.breathe {
|
|
|
+ animation: light-breathe 2s infinite ease-in-out;
|
|
|
+}
|
|
|
+
|
|
|
::v-deep .status-dot span {
|
|
|
transform: scale(0.75);
|
|
|
}
|
|
|
|
|
|
+::v-deep .status-dot img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ object-fit: contain;
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+
|
|
|
::v-deep .status-text {
|
|
|
font-size: 15px;
|
|
|
font-weight: bold;
|