Просмотр исходного кода

fix(report): 修正周报上周期边界与图表标签定位

Made-with: Cursor
yemeishu 1 месяц назад
Родитель
Сommit
ef1a18f231
1 измененных файлов с 42 добавлено и 13 удалено
  1. 42 13
      scripts/report_teacher_weekly_stats.php

+ 42 - 13
scripts/report_teacher_weekly_stats.php

@@ -29,7 +29,7 @@ $endCurrent = now()->timezone($tz);
 $todayStart = $endCurrent->copy()->startOfDay();
 $startCurrent = $todayStart->copy()->subDays($reportPeriodDays - 1);
 $startPrev = $todayStart->copy()->subDays(2 * $reportPeriodDays - 1);
-$endPrev = $todayStart->copy()->subDays($reportPeriodDays);
+$endPrev = $todayStart->copy()->subDays($reportPeriodDays - 1);
 
 $db = \Illuminate\Support\Facades\DB::class;
 
@@ -347,12 +347,13 @@ $buildDualChartsHtml = static function (array $curDaily, array $prevDaily): stri
         string $legPrev
     ): string {
         $maxY = max(1, ...$cur, ...$prev);
-        $W = 248;
-        $H = 206;
-        $padL = 38;
-        $padR = 8;
-        $padT = 14;
-        $padB = 38;
+        $W = 296;
+        $H = 256;
+        $padL = 42;
+        /** 右侧、顶部留白:数值标签 text-anchor=middle 时不依赖末列特殊锚点 */
+        $padR = 62;
+        $padT = 72;
+        $padB = 56;
         $gw = $W - $padL - $padR;
         $gh = $H - $padT - $padB;
         $n = max(1, count($labelsCur));
@@ -382,16 +383,43 @@ $buildDualChartsHtml = static function (array $curDaily, array $prevDaily): stri
             return '<polyline fill="none" stroke="'.$stroke.'" stroke-width="'.$sw.'"'.$dashAttr.' points="'.$poly.'" />'.$circles;
         };
 
+        /** 标签:每列只放一条「本/上」,y = 最高点y - 固定偏移(以 dominant-baseline=middle 作为中心y) */
+        $labelFillCur = $strokeCur === '#2563eb' ? '#1d4ed8' : '#c2410c';
+        $labelFillPrev = $strokePrev === '#93c5fd' ? '#475569' : '#78716c';
+        $valueLabels = '<g font-family="sun-exta,sans-serif">';
+        $labelOffset = 22; // 标签中心到点的固定上移像素
+        for ($vi = 0; $vi < $n; $vi++) {
+            $xv = $xAt($vi);
+            $yCv = $yAt((int) $cur[$vi]);
+            $yPv = $yAt((int) $prev[$vi]);
+            $vC = (int) $cur[$vi];
+            $vP = (int) $prev[$vi];
+            $yUpper = min($yCv, $yPv);
+            // 允许跑到绘图区上方的留白里;只在极端情况下防止贴到 SVG 顶边
+            $baseY = max(14, $yUpper - $labelOffset);
+            $valueLabels .= sprintf(
+                '<text x="%.1f" y="%.1f" text-anchor="middle" dominant-baseline="middle" font-size="9" font-family="sun-exta,sans-serif"><tspan fill="%s">%d</tspan><tspan fill="#94a3b8">/</tspan><tspan fill="%s">%d</tspan></text>',
+                $xv,
+                $baseY,
+                $labelFillCur,
+                $vC,
+                $labelFillPrev,
+                $vP
+            );
+        }
+        $valueLabels .= '</g>';
+
         $xAxisY = $padT + $gh;
         $tickTxt = '';
+        $axisRowY = $H - 48;
         for ($i = 0; $i < $n; $i++) {
             $x = $xAt($i);
             $lc = htmlspecialchars((string) ($labelsCur[$i] ?? ''), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
             $lp = htmlspecialchars((string) ($labelsPrev[$i] ?? ''), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
             $tickTxt .= sprintf(
-                '<text x="%.1f" y="%d" text-anchor="middle" font-size="7" fill="#374151" font-family="sun-exta,sans-serif">%s/%s</text>',
+                '<text x="%.1f" y="%d" text-anchor="middle" font-size="8" font-family="sun-exta,sans-serif"><tspan fill="#111827">%s</tspan><tspan fill="#94a3b8">/</tspan><tspan fill="#475569">%s</tspan></text>',
                 $x,
-                $H - 9,
+                $axisRowY,
                 $lc,
                 $lp
             );
@@ -409,16 +437,16 @@ $buildDualChartsHtml = static function (array $curDaily, array $prevDaily): stri
                 $y
             );
             $yTick .= sprintf(
-                '<text x="%d" y="%.1f" font-size="7.5" fill="#6b7280" font-family="sun-exta,sans-serif">%d</text>',
+                '<text x="%d" y="%.1f" font-size="8" fill="#6b7280" font-family="sun-exta,sans-serif">%d</text>',
                 2,
                 $y + 3,
                 $v
             );
         }
 
-        $legend = '<g font-family="sun-exta,sans-serif" font-size="8.5">';
-        $lx = max($padL + 4, $padL + $gw - 118);
-        $ly = $padT + 2;
+        $legend = '<g font-family="sun-exta,sans-serif" font-size="9">';
+        $lx = $padL + 4;
+        $ly = $H - 26;
         $items = [
             [$strokeCur, $legCur, ''],
             [$strokePrev, $legPrev, '6,4'],
@@ -453,6 +481,7 @@ $buildDualChartsHtml = static function (array $curDaily, array $prevDaily): stri
         $svg .= sprintf('<line x1="%d" y1="%.1f" x2="%.1f" y2="%.1f" stroke="#9ca3af" stroke-width="1"/>', $padL, $xAxisY, $padL + $gw, $xAxisY);
         $svg .= $lineWithDots($prev, $strokePrev, '6,4', 1.4);
         $svg .= $lineWithDots($cur, $strokeCur, '', 1.8);
+        $svg .= $valueLabels;
         $svg .= $tickTxt;
         $svg .= $legend;
         $svg .= '</svg>';