|
|
@@ -374,6 +374,15 @@ export default {
|
|
|
// 更新实时方案圆饼图的已走时长
|
|
|
this.updateRealtimeDonut(activeTime);
|
|
|
|
|
|
+ // 非手动模式下,根据扫描线位置自动切换当前阶段高亮
|
|
|
+ if (!this.isManualMode && this.phaseStages.length > 0) {
|
|
|
+ const idx = this.phaseStages.findIndex(s => activeTime >= s.start && activeTime < s.end);
|
|
|
+ if (idx >= 0) {
|
|
|
+ const newStage = String(idx + 1);
|
|
|
+ if (this.currentStage !== newStage) this.currentStage = newStage;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 双相位图模式:检测周期 wrap-around,触发 refetch 让后端把刚结束的周期作为 lastCycle 返回
|
|
|
if (this.isDual) {
|
|
|
if (this._prevTick != null && activeTime < this._prevTick - 1) {
|
|
|
@@ -393,22 +402,22 @@ export default {
|
|
|
this._refetching = false;
|
|
|
}
|
|
|
},
|
|
|
- // 从 phaseData 解析4个阶段的绿灯时长,构建圆饼图数据
|
|
|
+ // 从 phaseData 解析所有阶段的绿灯时长,构建圆饼图数据
|
|
|
buildDonutFromPhaseData() {
|
|
|
const phaseData = this.mockPhaseData || [];
|
|
|
- const stageColors = ['#3b82f6', '#a855f7', '#14b8a6', '#f59e0b'];
|
|
|
+ const stageColors = ['#3b82f6', '#a855f7', '#14b8a6', '#f59e0b', '#ec4899', '#06b6d4', '#84cc16', '#f97316'];
|
|
|
const stageLabels = ['1-南北直行', '2-南北左转', '3-东西直行', '4-东西左转'];
|
|
|
|
|
|
- // 提取 track 0 的绿灯相位(每阶段的第一个 green)
|
|
|
+ // 提取 track 0 的绿灯相位
|
|
|
const greenPhases = phaseData.filter(p => p[0] === 0 && p[5] === 'green');
|
|
|
- const stages = greenPhases.slice(0, 4).map((p, i) => {
|
|
|
- const total = p[8] || Math.floor(this.cycleLength / 4);
|
|
|
+ const stages = greenPhases.map((p, i) => {
|
|
|
+ const total = p[8] || Math.floor(this.cycleLength / greenPhases.length);
|
|
|
return {
|
|
|
label: stageLabels[i] || `阶段${i + 1}`,
|
|
|
value: total, // 阶段总时长
|
|
|
start: p[1], // 阶段开始时间(从绿灯起始)
|
|
|
end: p[1] + total, // 阶段结束时间
|
|
|
- color: stageColors[i]
|
|
|
+ color: stageColors[i % stageColors.length]
|
|
|
};
|
|
|
});
|
|
|
this.phaseStages = stages;
|
|
|
@@ -450,8 +459,8 @@ export default {
|
|
|
}))
|
|
|
];
|
|
|
},
|
|
|
- // 观察首个 stage-item-wrapper, 算出 2 行高度(含行间 gap) 写到 CSS 变量。
|
|
|
- // grid 的 height 锁在 2 行高度: 不足 8 个时下排留白; 超 8 个时按行滚动。
|
|
|
+ // 观察首个 stage-item-wrapper, 算出 1 行高度写到 CSS 变量。
|
|
|
+ // grid 的 height 锁在 1 行高度: 超 4 个时按行滚动。
|
|
|
// 防 ResizeObserver loop 警告: rAF 推到下一帧 + 值比较切断"测量→撑大→再测"循环。
|
|
|
_observeFirstStageItem() {
|
|
|
const grid = this.$refs.stageGrid;
|
|
|
@@ -472,7 +481,7 @@ export default {
|
|
|
if (rowH <= 0) return;
|
|
|
const cs = window.getComputedStyle(grid);
|
|
|
const gap = parseFloat(cs.rowGap || cs.gap || '0') || 0;
|
|
|
- const reservedH = rowH * 2 + gap;
|
|
|
+ const reservedH = rowH;
|
|
|
if (this._lastRowH === rowH && this._lastReservedH === reservedH) return;
|
|
|
this._lastRowH = rowH;
|
|
|
this._lastReservedH = reservedH;
|
|
|
@@ -1143,7 +1152,7 @@ export default {
|
|
|
opacity: 0;
|
|
|
}
|
|
|
|
|
|
-/* 4 列固定网格; 始终锁 2 行 + 行间 gap (不足 8 阶段时第 2 行留白); 超 8 滚动 */
|
|
|
+/* 4 列固定网格; 锁 1 行高度; 超 4 阶段纵向滚动 */
|
|
|
.current-stage {
|
|
|
margin-bottom: clamp(4px, calc(var(--s) * 10px), 20px);
|
|
|
display: grid;
|