From 8d9161eb1a3c2f27a65b492228a0b19d94f2c707 Mon Sep 17 00:00:00 2001 From: leon <916117771@qq.com> Date: Sun, 26 Apr 2026 00:14:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(dashboard):=20=E6=B7=BB=E5=8A=A0=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E4=BB=AA=E8=A1=A8=E6=9D=BF=E5=8A=9F=E8=83=BD=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=95=B0=E6=8D=AE=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 dashboard.js 文件实现前端图表展示功能 - 添加彩球渲染和颜色映射功能 - 实现数据加载和渲染逻辑 - 添加多种统计图表包括冷热号码、比例分析、生肖排名等 - 重构区域转移动态数据方法 - 更新区域到区域颜色转移概率计算逻辑 - 优化转移概率数据结构和显示方式 - 添加热力图和各种统计图表的响应式支持 --- application/admin/model/History.php | 59 +++++++++++++-------------- public/assets/js/backend/dashboard.js | 21 +++++----- 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/application/admin/model/History.php b/application/admin/model/History.php index 92456e8..275b6e4 100644 --- a/application/admin/model/History.php +++ b/application/admin/model/History.php @@ -467,7 +467,7 @@ class History extends Model 'heatmap' => $this->getSpecialHeatmap($periods), 'zonetransition' => $this->getZoneTransition($periods), 'colorwavetransition' => $this->getColorWaveTransition($periods), - 'zonetocolortransition' => $this->getZoneToColorTransition($periods) + 'zonetocolortransition' => $this->getZoneToZoneColor($periods) ]; } @@ -797,12 +797,12 @@ class History extends Model } /** - * 区域→波色交叉转移概率 - * 统计上一期特码所在数字区域后,下一期特码波色(红/蓝/绿)的分布概率 + * 区域→区域转移矩阵,单元格内显示波色概率 + * 统计上一期特码所在区域后,下一期特码在各区域的分布,以及每个区域内的波色占比 * @param int $periods 查询最近多少期 - * @return array {zones: [], colors: [], matrix: [], probabilities: [], row_totals: [], total_transitions: int} + * @return array {zones: [], matrix: [[zone_count]], color_probs: [[{red, blue, green}]]} */ - public function getZoneToColorTransition($periods = 100) + public function getZoneToZoneColor($periods = 100) { $history = $this ->field('expect,num7,openTime') @@ -811,7 +811,7 @@ class History extends Model ->select(); if (empty($history) || count($history) < 2) { - return ['zones' => ['1-10','11-20','21-30','31-40','41-49'], 'colors' => ['红波','蓝波','绿波'], 'matrix' => [], 'probabilities' => [], 'row_totals' => [], 'total_transitions' => 0]; + return ['zones' => ['1-10','11-20','21-30','31-40','41-49'], 'matrix' => [], 'color_probs' => []]; } $history = array_reverse($history); @@ -819,9 +819,13 @@ class History extends Model $colorMap = $num_model->column('color', 'num'); $zoneLabels = ['1-10', '11-20', '21-30', '31-40', '41-49']; - $colorLabels = ['红波', '蓝波', '绿波']; - $matrix = array_fill(0, 5, array_fill(0, 3, 0)); - $rowTotals = array_fill(0, 5, 0); + $matrix = array_fill(0, 5, array_fill(0, 5, 0)); + $colorCounts = []; + for ($i = 0; $i < 5; $i++) { + for ($j = 0; $j < 5; $j++) { + $colorCounts[$i][$j] = ['red' => 0, 'blue' => 0, 'green' => 0]; + } + } $getZone = function ($num) { if ($num <= 10) return 0; @@ -831,43 +835,38 @@ class History extends Model return 4; }; - $getColorIdx = function ($num) use ($colorMap) { - $color = $colorMap[$num] ?? ''; - if (strpos($color, '红') !== false) return 0; - if (strpos($color, '蓝') !== false) return 1; - if (strpos($color, '绿') !== false) return 2; - return -1; - }; - - $totalTransitions = 0; for ($i = 0; $i < count($history) - 1; $i++) { $currentNum = (int)$history[$i]['num7']; $nextNum = (int)$history[$i + 1]['num7']; $from = $getZone($currentNum); - $to = $getColorIdx($nextNum); - if ($to < 0) continue; + $to = $getZone($nextNum); + $color = $colorMap[$nextNum] ?? ''; $matrix[$from][$to]++; - $rowTotals[$from]++; - $totalTransitions++; + if (strpos($color, '红') !== false) $colorCounts[$from][$to]['red']++; + elseif (strpos($color, '蓝') !== false) $colorCounts[$from][$to]['blue']++; + elseif (strpos($color, '绿') !== false) $colorCounts[$from][$to]['green']++; } - $probabilities = array_fill(0, 5, array_fill(0, 3, 0)); + // 计算每个单元格波色概率 + $colorProbs = array_fill(0, 5, array_fill(0, 5, ['red' => 0, 'blue' => 0, 'green' => 0])); for ($i = 0; $i < 5; $i++) { - if ($rowTotals[$i] > 0) { - for ($j = 0; $j < 3; $j++) { - $probabilities[$i][$j] = round($matrix[$i][$j] / $rowTotals[$i] * 100, 1); + for ($j = 0; $j < 5; $j++) { + $total = $matrix[$i][$j]; + if ($total > 0) { + $colorProbs[$i][$j] = [ + 'red' => round($colorCounts[$i][$j]['red'] / $total * 100, 1), + 'blue' => round($colorCounts[$i][$j]['blue'] / $total * 100, 1), + 'green' => round($colorCounts[$i][$j]['green'] / $total * 100, 1), + ]; } } } return [ 'zones' => $zoneLabels, - 'colors' => $colorLabels, 'matrix' => $matrix, - 'probabilities' => $probabilities, - 'row_totals' => $rowTotals, - 'total_transitions' => $totalTransitions + 'color_probs' => $colorProbs ]; } diff --git a/public/assets/js/backend/dashboard.js b/public/assets/js/backend/dashboard.js index e66502b..2df510b 100644 --- a/public/assets/js/backend/dashboard.js +++ b/public/assets/js/backend/dashboard.js @@ -131,24 +131,23 @@ define(['jquery'], function ($) { html += ''; } html += ''; - // 下方:区域→波色交叉转移 + // 下方:区域→区域转移矩阵,单元格内显示波色概率 var ztc = data.zonetocolortransition; if (ztc && ztc.matrix && ztc.matrix.length > 0) { - html += '
波色特码 | ';
- var cwColors2 = ['#e74c3c', '#3498db', '#2ecc71'];
- for (var z = 0; z < ztc.colors.length; z++) {
- html += '' + ztc.colors[z] + ' | '; + html += '
|---|
区域特码 | ';
+ for (var z = 0; z < ztc.zones.length; z++) {
+ html += '' + ztc.zones[z] + ' | '; } html += '|
|---|---|---|
| ' + ztc.zones[r] + ' | '; - for (var c = 0; c < 3; c++) { - var pct = ztc.probabilities[r][c]; + for (var c = 0; c < 5; c++) { var cnt = ztc.matrix[r][c]; - var bg = pct > 40 ? cwColors2[c] : pct > 20 ? cwColors2[c] + 'cc' : pct > 0 ? '#95a5a6' : '#f5f5f5'; - var txt = pct > 20 ? '#fff' : '#333'; - html += '' + cnt + '次 ' + pct + '% | ';
+ var cp = ztc.color_probs[r][c];
+ var bg = cnt > 0 ? '#fafafa' : '#fff';
+ var txt = (cp.red > 40 || cp.blue > 40 || cp.green > 40) ? '#fff' : '#333';
+ html += '红' + cp.red + '% 蓝' + cp.blue + '% 绿' + cp.green + '% (' + cnt + '次) | ';
}
html += '