diff --git a/application/admin/controller/History.php b/application/admin/controller/History.php index dc1f0b0..5ff1533 100644 --- a/application/admin/controller/History.php +++ b/application/admin/controller/History.php @@ -22,7 +22,7 @@ class History extends Backend * 无需额外权限检查的方法(但仍在 admin 模块内,需要 admin 登录) * @var array */ - protected $noNeedRight = ['missingNum', 'trendData', 'hotColdNumbers', 'colorWaveAnalysis', 'zodiacAnalysis', 'oddEvenAnalysis', 'bigSmallAnalysis', 'sumAnalysis', 'consecutiveNumbers', 'tailNumbers', 'dashboard']; + protected $noNeedRight = ['missingNum', 'trendData', 'hotColdNumbers', 'colorWaveAnalysis', 'zodiacAnalysis', 'oddEvenAnalysis', 'bigSmallAnalysis', 'specialTrend', 'consecutiveNumbers', 'tailNumbers', 'dashboard']; public function _initialize() { @@ -169,16 +169,16 @@ class History extends Backend } /** - * 和值分析 + * 特码走势 */ - public function sumAnalysis() + public function specialTrend() { if ($this->request->isAjax()) { $periods = $this->request->get('periods', 30, 'intval'); if ($periods < 10 || $periods > 100) { $this->error('期数范围必须在 10-100 之间'); } - $result = $this->model->getSumAnalysis($periods); + $result = $this->model->getSpecialTrend($periods); $this->success('查询成功', null, $result); } } diff --git a/application/admin/model/History.php b/application/admin/model/History.php index 6b2827a..305ec16 100644 --- a/application/admin/model/History.php +++ b/application/admin/model/History.php @@ -366,22 +366,24 @@ class History extends Model } /** - * 和值分析 + * 特码走势 */ - public function getSumAnalysis($periods = 30) + public function getSpecialTrend($periods = 30) { - $history = $this->field('expect,num1,num2,num3,num4,num5,num6,num7')->order('openTime', 'asc')->limit($periods)->select(); - if (empty($history)) return ['expects' => [], 'sums' => []]; + $history = $this->field('expect,num7')->order('openTime', 'asc')->limit($periods)->select(); + if (empty($history)) return ['expects' => [], 'specials' => [], 'colors' => []]; - $expects = []; $sums = []; + $num_model = new Num(); + $colorMap = $num_model->column('color', 'num'); + + $expects = []; $specials = []; $colors = []; foreach ($history as $row) { $expects[] = (string)$row['expect']; - $sum = (int)$row['num1'] + (int)$row['num2'] + (int)$row['num3'] + (int)$row['num4'] + (int)$row['num5'] + (int)$row['num6'] + (int)$row['num7']; - $sums[] = $sum; + $num = (int)$row['num7']; + $specials[] = $num; + $colors[] = $colorMap[$num] ?? ''; } - $avg = round(array_sum($sums) / count($sums), 1); - $max = max($sums); $min = min($sums); - return ['expects' => $expects, 'sums' => $sums, 'avg' => $avg, 'max' => $max, 'min' => $min]; + return ['expects' => $expects, 'specials' => $specials, 'colors' => $colors]; } /** @@ -457,7 +459,7 @@ class History extends Model 'zodiac' => $this->getZodiacAnalysis($periods, $type), 'oddeven' => $this->getOddEvenAnalysis($periods, $type), 'bigsmall' => $this->getBigSmallAnalysis($periods, $type), - 'sum' => $this->getSumAnalysis($periods), + 'special' => $this->getSpecialTrend($periods), 'tailnumbers' => $this->getTailNumbers($periods, $type) ]; } diff --git a/public/assets/js/backend/dashboard.js b/public/assets/js/backend/dashboard.js index 75d468e..b451ad2 100644 --- a/public/assets/js/backend/dashboard.js +++ b/public/assets/js/backend/dashboard.js @@ -39,7 +39,7 @@ define(['jquery'], function ($) { function render(data) { var hc = data.hotcold, cw = data.colorwave, zo = data.zodiac; - var oe = data.oddeven, bs = data.bigsmall, sm = data.sum, tn = data.tailnumbers; + var oe = data.oddeven, bs = data.bigsmall, sp = data.special, tn = data.tailnumbers; var html = ''; @@ -70,42 +70,71 @@ define(['jquery'], function ($) { html += ''; html += ''; - html += '

⭐ 生肖排名

'; - for (var i = 0; i < Math.min(zo.list.length, 12); i++) { - var z = zo.list[i]; - html += '
' + z.animal + '
' + z.count + ' (' + z.percent + '%)
'; - } - html += '
'; + html += '

⭐ 生肖排名

'; - html += '

📈 和值统计

'; - html += '
' + sm.avg + '
平均和值
'; - html += '
' + sm.max + '
最大和值
'; - html += '
' + sm.min + '
最小和值
'; - html += '
'; + html += '

📈 特码走势

'; - html += '

🔢 尾数频率

'; - for (var i = 0; i < tn.all.length; i++) { - var t = tn.all[i]; - html += '
' + t.tail + '
' + t.count + ' (' + t.percent + '%)
'; - } - html += '
'; + html += '

🔢 尾数频率

'; $('#dash-content').html(html); - if (typeof echarts !== 'undefined' && sm.expects && sm.expects.length > 0) { - var chartDom = document.getElementById('dash-chart'); + // 生肖柱状图 + if (typeof echarts !== 'undefined' && zo.list && zo.list.length > 0) { + var zDom = document.getElementById('zodiac-chart'); + if (zDom) { + var zChart = echarts.init(zDom); + zChart.setOption({ + tooltip: {trigger: 'axis', axisPointer: {type: 'shadow'}}, + grid: {left: 50, right: 20, bottom: 30, top: 10}, + xAxis: {type: 'category', data: zo.list.map(function(z){return z.animal;})}, + yAxis: {type: 'value'}, + series: [{type: 'bar', data: zo.list.map(function(z){return z.count;}), itemStyle: {color: '#626c91'}}] + }); + $(window).on('resize', function(){ zChart.resize(); }); + } + } + + // 特码走势 + if (typeof echarts !== 'undefined' && sp.expects && sp.expects.length > 0) { + var chartDom = document.getElementById('special-chart'); if (chartDom) { var chart = echarts.init(chartDom); + var colorMap = {'红': '#e74c3c', '蓝': '#3498db', '绿': '#2ecc71'}; + var itemColors = sp.colors.map(function(c) { + if (c.indexOf('红') !== -1) return colorMap['红']; + if (c.indexOf('蓝') !== -1) return colorMap['蓝']; + if (c.indexOf('绿') !== -1) return colorMap['绿']; + return '#95a5a6'; + }); chart.setOption({ - tooltip: {trigger: 'axis'}, - xAxis: {type: 'category', data: sm.expects, axisLabel: {rotate: 45, fontSize: 10}}, - yAxis: {type: 'value'}, - series: [{type: 'line', data: sm.sums, smooth: true, itemStyle: {color: '#3498db'}, areaStyle: {color: 'rgba(52,152,219,0.1)'}}], + tooltip: {trigger: 'axis', formatter: function(p) { + return '期号: ' + p[0].axisValue + '
特码: ' + p[0].data + ''; + }}, + xAxis: {type: 'category', data: sp.expects, axisLabel: {rotate: 45, fontSize: 10}}, + yAxis: {type: 'value', min: 0, max: 50}, + series: [{type: 'line', data: sp.specials, smooth: true, symbolSize: 8, itemStyle: {color: function(p) { return itemColors[p.dataIndex]; }}, areaStyle: {color: 'rgba(52,152,219,0.05)'}}], grid: {left: 50, right: 20, bottom: 50, top: 20} }); $(window).on('resize', function () { chart.resize(); }); } } + + // 尾数柱状图 + if (typeof echarts !== 'undefined' && tn.all && tn.all.length > 0) { + var tDom = document.getElementById('tail-chart'); + if (tDom) { + var tChart = echarts.init(tDom); + var sorted = tn.all.slice().sort(function(a,b){return a.tail - b.tail;}); + tChart.setOption({ + tooltip: {trigger: 'axis', axisPointer: {type: 'shadow'}}, + grid: {left: 50, right: 20, bottom: 30, top: 10}, + xAxis: {type: 'category', data: sorted.map(function(t){return t.tail;})}, + yAxis: {type: 'value'}, + series: [{type: 'bar', data: sorted.map(function(t){return t.count;}), itemStyle: {color: '#23b7e5'}}] + }); + $(window).on('resize', function(){ tChart.resize(); }); + } + } } $('#btn-dash-refresh').on('click', loadData);