feat(phase-3): add hot/cold number analysis with period filter

This commit is contained in:
2026-04-21 23:41:39 +08:00
parent 7e4b6a3443
commit f36410dcc6
5 changed files with 197 additions and 1 deletions
+21 -1
View File
@@ -22,7 +22,7 @@ class History extends Backend
* 无需额外权限检查的方法(但仍在 admin 模块内,需要 admin 登录)
* @var array
*/
protected $noNeedRight = ['missingNum', 'trendData'];
protected $noNeedRight = ['missingNum', 'trendData', 'hotColdNumbers'];
public function _initialize()
{
@@ -72,5 +72,25 @@ class History extends Backend
}
}
/**
* 获取冷热号码
* @return void
*/
public function hotColdNumbers()
{
if ($this->request->isAjax()) {
$periods = $this->request->get('periods', 30, 'intval');
if ($periods < 10 || $periods > 100) {
$this->error('期数范围必须在 10-100 之间');
}
$type = $this->request->get('type', 'all');
if (!in_array($type, ['all', 'special'])) {
$this->error('查询类型不正确');
}
$result = $this->model->getHotColdNumbers($periods, $type);
$this->success('查询成功', null, $result);
}
}
}
+1
View File
@@ -17,4 +17,5 @@ return [
'Special Only' => '仅特码',
'Trend Chart' => '走势图',
'No data available' => '暂无数据',
'Hot/Cold Analysis' => '冷热分析',
];
+63
View File
@@ -74,6 +74,69 @@ class History extends Model
];
}
/**
* 获取冷热号码
* @param int $periods 查询最近多少期
* @param string $type 查询类型 all=全部号码 special=仅特码
* @return array {hot: [], cold: [], all: []}
*/
public function getHotColdNumbers($periods = 30, $type = 'all')
{
$num_model = new Num();
$colorMap = $num_model->column('color', 'num');
$animalMap = $num_model->column('animal', 'num');
$history = $this
->field('expect,num1,num2,num3,num4,num5,num6,num7,openTime')
->order('openTime', 'desc')
->limit($periods)
->select();
if (empty($history)) {
return ['hot' => [], 'cold' => [], 'all' => []];
}
$fields = ($type === 'special') ? ['num7'] : ['num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7'];
// 统计每个号码的出现次数
$count = array_fill(1, 49, 0);
$totalAppearances = 0;
foreach ($history as $row) {
foreach ($fields as $field) {
$num = (int)$row[$field];
if ($num >= 1 && $num <= 49) {
$count[$num]++;
$totalAppearances++;
}
}
}
$all = [];
for ($num = 1; $num <= 49; $num++) {
$percent = $totalAppearances > 0 ? round($count[$num] / $totalAppearances * 100, 1) : 0;
$all[] = [
'num' => $num,
'count' => $count[$num],
'percent' => $percent,
'color' => $colorMap[$num] ?? '—',
'animal' => $animalMap[$num] ?? '—'
];
}
// 按出现次数降序排序
$sorted = $all;
usort($sorted, function ($a, $b) {
return $b['count'] - $a['count'];
});
// 热号: top 10, 冷号: bottom 10
$hot = array_slice($sorted, 0, 10);
$cold = array_slice($sorted, -10);
$cold = array_reverse($cold);
return ['hot' => $hot, 'cold' => $cold, 'all' => $all];
}
/**
* 计算遗漏号码
* @param int $periods 查询最近多少期
@@ -9,6 +9,7 @@
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-warning btn-missingnum" title="{:__('Missing Number Analysis')}"><i class="fa fa-search"></i> {:__('Missing Number Analysis')}</a>
<a href="javascript:;" class="btn btn-info btn-trend" title="{:__('Trend Chart')}"><i class="fa fa-area-chart"></i> {:__('Trend Chart')}</a>
<a href="javascript:;" class="btn btn-danger btn-hotcold" title="{:__('Hot/Cold Analysis')}"><i class="fa fa-fire"></i> {:__('Hot/Cold Analysis')}</a>
<!-- <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('history/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>-->
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"