Sfoglia il codice sorgente

相位图数据优化:条纹3-5s随机、黄灯3s、全红2s,符合现实信号灯规则;各阶段按0.3/0.2/0.3/0.2比例分配,绿灯由剩余时间倒推;P1-P4文本显示阶段总时长;路口图相位格式改为"相位X: 时间";圆饼图同步使用阶段总时长

画安 2 settimane fa
parent
commit
9e21eac448

+ 12 - 9
src/components/ui/CrossingDetailPanel.vue

@@ -249,13 +249,13 @@ export default {
 
             this.$set(this.intersectionData, 'signals', {
                 ns: {
-                    phaseName: nsGreen ? (phaseName || '南北') : (this.intersectionData.signals?.ns?.phaseName || '南北'),
+                    phaseName: nsGreen ? (phaseName ? `相位${phaseName.replace('P', '')}` : '南北') : (this.intersectionData.signals?.ns?.phaseName || '南北'),
                     time: remaining,
                     isGreen: nsGreen,
                     activeArrowTypes: nsGreen ? activeArrowTypes : []
                 },
                 ew: {
-                    phaseName: ewGreen ? (phaseName || '东西') : (this.intersectionData.signals?.ew?.phaseName || '东西'),
+                    phaseName: ewGreen ? (phaseName ? `相位${phaseName.replace('P', '')}` : '东西') : (this.intersectionData.signals?.ew?.phaseName || '东西'),
                     time: remaining,
                     isGreen: ewGreen,
                     activeArrowTypes: ewGreen ? activeArrowTypes : []
@@ -273,13 +273,16 @@ export default {
 
             // 提取 track 0 的绿灯相位(每阶段的第一个 green)
             const greenPhases = phaseData.filter(p => p[0] === 0 && p[5] === 'green');
-            const stages = greenPhases.slice(0, 4).map((p, i) => ({
-                label: stageLabels[i] || `阶段${i + 1}`,
-                value: p[4],  // 绿灯时长
-                start: p[1],  // 阶段开始时间
-                end: p[2],    // 绿灯结束时间
-                color: stageColors[i]
-            }));
+            const stages = greenPhases.slice(0, 4).map((p, i) => {
+                const total = p[8] || Math.floor(this.cycleLength / 4);
+                return {
+                    label: stageLabels[i] || `阶段${i + 1}`,
+                    value: total,           // 阶段总时长
+                    start: p[1],            // 阶段开始时间(从绿灯起始)
+                    end: p[1] + total,      // 阶段结束时间
+                    color: stageColors[i]
+                };
+            });
             this.phaseStages = stages;
 
             // 实时方案:已走时长 + 4个阶段

+ 5 - 4
src/components/ui/SignalTimingChart.vue

@@ -48,10 +48,10 @@ const COLORS = {
 
 // 绘制条纹图案用于绿闪/预警
 const stripeCanvas = document.createElement('canvas');
-stripeCanvas.width = 6; stripeCanvas.height = 20;
+stripeCanvas.width = 4; stripeCanvas.height = 20;
 const ctx = stripeCanvas.getContext('2d');
-ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, 6, 20);
-ctx.fillStyle = COLORS.STRIPE_GREEN; ctx.fillRect(0, 0, 3, 20); 
+ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, 4, 20);
+ctx.fillStyle = COLORS.STRIPE_GREEN; ctx.fillRect(0, 0, 2, 20); 
 const stripePattern = { image: stripeCanvas, repeat: 'repeat' };
 
 const IMAGE_MAP = {
@@ -282,6 +282,7 @@ export default {
       const duration = api.value(4);
       const type = api.value(5);
       const iconValue = api.value(6);
+      const stageTotal = api.value(8); // 阶段总时长(含绿灯+条纹+黄灯+红灯)
 
       let fillStyle = COLORS.GREEN_LIGHT;
       if (type === 'stripe') fillStyle = stripePattern;
@@ -444,7 +445,7 @@ export default {
           innerGroup.children.push({
             type: 'text',
             style: {
-              text: `${phaseName}\n${duration}`,
+              text: `${phaseName}\n${stageTotal || duration}`,
               x: textStartX,
               y: midY,
               fill: COLORS.TEXT_DARK,

+ 15 - 12
src/mock/api.js

@@ -158,7 +158,11 @@ function _makeIntersectionConfig(id, name, { fixedNsGreen, iconMode = 'default'
  */
 function _makePhaseData(cycleLength = 140, isTwoRows = true, iconMode = 'default') {
   const n = 4; // 4个阶段 (S1-S4)
-  const stageTime = Math.floor(cycleLength / n);
+  // 各阶段按比例分配时间,P1/P3较长,P2/P4较短
+  const ratios = [0.3, 0.2, 0.3, 0.2];
+  const stageTimes = ratios.map(r => Math.floor(cycleLength * r));
+  // 把余数补到第一个阶段,确保总和 = cycleLength
+  stageTimes[0] += cycleLength - stageTimes.reduce((a, b) => a + b, 0);
   const pd = [];
 
   // ==========================================
@@ -185,20 +189,22 @@ function _makePhaseData(cycleLength = 140, isTwoRows = true, iconMode = 'default
   let t = 0;
   for (let i = 0; i < n; i++) {
     const stageStart = t;
+    const stageTime = stageTimes[i];
     const stageEnd = stageStart + stageTime;
     const { icon: stageIcon, direction } = phaseConfig[i];
 
     const pushTrackData = (trackIdx, phaseNamePrefix) => {
       const icon = stageIcon;
       const phaseName = `${phaseNamePrefix}${i + 1}`;
-      const g = Math.floor(Math.random() * 11) + 20; // 绿灯 20-30s
-      const s = 3; // 闪烁/条纹 3s
-      const y = 2; // 黄灯 2s
+      const s = Math.floor(Math.random() * 3) + 3; // 绿闪/条纹 3-5s
+      const y = 3; // 黄灯固定 3s
+      const r = 2; // 全红间隔 2s
+      const g = stageTime - s - y - r; // 绿灯 = 阶段总时长 - 条纹 - 黄灯 - 红灯
 
       let curT = stageStart;
 
-      // 1. 绿灯 (第6个索引项传入组装好的成对 icon 字符串, 第7个索引项标记方向)
-      pd.push([trackIdx, curT, curT + g, phaseName, g, 'green', icon, direction]);
+      // 1. 绿灯 (phase[8]存阶段总时长,用于显示)
+      pd.push([trackIdx, curT, curT + g, phaseName, g, 'green', icon, direction, stageTime]);
       curT += g;
       // 2. 绿闪/条纹
       pd.push([trackIdx, curT, curT + s, '', s, 'stripe', null, direction]);
@@ -206,11 +212,8 @@ function _makePhaseData(cycleLength = 140, isTwoRows = true, iconMode = 'default
       // 3. 黄灯
       pd.push([trackIdx, curT, curT + y, '', y, 'yellow', null, direction]);
       curT += y;
-      // 4. 红灯补齐 (确保阶段对齐)
-      let remainRed = stageEnd - curT;
-      if (remainRed > 0) {
-        pd.push([trackIdx, curT, stageEnd, '', remainRed, 'red', null, direction]);
-      }
+      // 4. 红灯固定
+      pd.push([trackIdx, curT, curT + r, '', r, 'red', null, direction]);
     };
 
     pushTrackData(0, 'P'); // 生成第一排 (P1-P4)
@@ -218,7 +221,7 @@ function _makePhaseData(cycleLength = 140, isTwoRows = true, iconMode = 'default
       pushTrackData(1, 'P'); // 生成第二排 (P5-P8,由于逻辑相同,名称可根据需要改为 i+5)
     }
 
-    t = stageEnd; 
+    t = stageEnd;
   }
   return pd;
 }