feat: rewrite dashboard page as lottery data dashboard with all analysis metrics
This commit is contained in:
@@ -2,83 +2,18 @@
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\Admin;
|
||||
use app\admin\model\User;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\model\Attachment;
|
||||
use fast\Date;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 控制台
|
||||
* 控制台 - 六合彩数据分析
|
||||
*
|
||||
* @icon fa fa-dashboard
|
||||
* @remark 用于展示当前系统中的统计数据、统计报表及重要实时数据
|
||||
*/
|
||||
class Dashboard extends Backend
|
||||
{
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
try {
|
||||
\think\Db::execute("SET @@sql_mode='';");
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
$column = [];
|
||||
$starttime = Date::unixtime('day', -6);
|
||||
$endtime = Date::unixtime('day', 0, 'end');
|
||||
$joinlist = Db("user")->where('jointime', 'between time', [$starttime, $endtime])
|
||||
->field('jointime, status, COUNT(*) AS nums, DATE_FORMAT(FROM_UNIXTIME(jointime), "%Y-%m-%d") AS join_date')
|
||||
->group('join_date')
|
||||
->select();
|
||||
for ($time = $starttime; $time <= $endtime;) {
|
||||
$column[] = date("Y-m-d", $time);
|
||||
$time += 86400;
|
||||
}
|
||||
$userlist = array_fill_keys($column, 0);
|
||||
foreach ($joinlist as $k => $v) {
|
||||
$userlist[$v['join_date']] = $v['nums'];
|
||||
}
|
||||
|
||||
$dbTableList = Db::query("SHOW TABLE STATUS");
|
||||
$addonList = get_addon_list();
|
||||
$totalworkingaddon = 0;
|
||||
$totaladdon = count($addonList);
|
||||
foreach ($addonList as $index => $item) {
|
||||
if ($item['state']) {
|
||||
$totalworkingaddon += 1;
|
||||
}
|
||||
}
|
||||
$this->view->assign([
|
||||
'totaluser' => User::count(),
|
||||
'totaladdon' => $totaladdon,
|
||||
'totaladmin' => Admin::count(),
|
||||
'totalcategory' => \app\common\model\Category::count(),
|
||||
'todayusersignup' => User::whereTime('jointime', 'today')->count(),
|
||||
'todayuserlogin' => User::whereTime('logintime', 'today')->count(),
|
||||
'sevendau' => User::whereTime('jointime|logintime|prevtime', '-7 days')->count(),
|
||||
'thirtydau' => User::whereTime('jointime|logintime|prevtime', '-30 days')->count(),
|
||||
'threednu' => User::whereTime('jointime', '-3 days')->count(),
|
||||
'sevendnu' => User::whereTime('jointime', '-7 days')->count(),
|
||||
'dbtablenums' => count($dbTableList),
|
||||
'dbsize' => array_sum(array_map(function ($item) {
|
||||
return $item['Data_length'] + $item['Index_length'];
|
||||
}, $dbTableList)),
|
||||
'totalworkingaddon' => $totalworkingaddon,
|
||||
'attachmentnums' => Attachment::count(),
|
||||
'attachmentsize' => Attachment::sum('filesize'),
|
||||
'picturenums' => Attachment::where('mimetype', 'like', 'image/%')->count(),
|
||||
'picturesize' => Attachment::where('mimetype', 'like', 'image/%')->sum('filesize'),
|
||||
]);
|
||||
|
||||
$this->assignconfig('column', array_keys($userlist));
|
||||
$this->assignconfig('userdata', array_values($userlist));
|
||||
|
||||
$this->assign('periods', 30);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,4 +26,5 @@ return [
|
||||
'Consecutive' => '连号分析',
|
||||
'Tail Numbers' => '尾数分析',
|
||||
'Dashboard' => '综合统计面板',
|
||||
'Refresh' => '刷新',
|
||||
];
|
||||
|
||||
@@ -1,403 +1,155 @@
|
||||
<style type="text/css">
|
||||
.sm-st {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sm-st-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
display: inline-block;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
background: #eee;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sm-st-info {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.sm-st-info span {
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.orange {
|
||||
background: #fa8564 !important;
|
||||
}
|
||||
|
||||
.tar {
|
||||
background: #45cf95 !important;
|
||||
}
|
||||
|
||||
.sm-st .green {
|
||||
background: #86ba41 !important;
|
||||
}
|
||||
|
||||
.pink {
|
||||
background: #AC75F0 !important;
|
||||
}
|
||||
|
||||
.yellow-b {
|
||||
background: #fdd752 !important;
|
||||
}
|
||||
|
||||
.stat-elem {
|
||||
|
||||
background-color: #fff;
|
||||
padding: 18px;
|
||||
border-radius: 40px;
|
||||
|
||||
}
|
||||
|
||||
.stat-info {
|
||||
text-align: center;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
margin-top: -5px;
|
||||
padding: 8px;
|
||||
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.st-red {
|
||||
background-color: #F05050;
|
||||
}
|
||||
|
||||
.st-green {
|
||||
background-color: #27C24C;
|
||||
}
|
||||
|
||||
.st-violet {
|
||||
background-color: #7266ba;
|
||||
}
|
||||
|
||||
.st-blue {
|
||||
background-color: #23b7e5;
|
||||
}
|
||||
|
||||
.stats .stat-icon {
|
||||
color: #28bb9c;
|
||||
display: inline-block;
|
||||
font-size: 26px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
width: 50px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.stat {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.stat .value {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.stat .name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.stat.lg .value {
|
||||
font-size: 26px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.stat-col {
|
||||
margin:0 0 10px 0;
|
||||
}
|
||||
.stat.lg .name {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.stat-col .progress {
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.stat-col .progress-bar {
|
||||
line-height: 2px;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 30px 0;
|
||||
}
|
||||
|
||||
|
||||
#statistics .panel {
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
#statistics .panel h5 {
|
||||
font-size: 14px;
|
||||
}
|
||||
.dash-section { margin-bottom: 20px; }
|
||||
.dash-section h4 { border-bottom: 1px solid #eee; padding-bottom: 8px; margin-bottom: 12px; font-size: 15px; color: #333; }
|
||||
.dash-card { background: #f9f9f9; border-radius: 6px; padding: 12px; text-align: center; }
|
||||
.dash-card .big-num { font-size: 28px; font-weight: bold; color: #333; }
|
||||
.dash-card .label-text { font-size: 12px; color: #999; margin-top: 4px; }
|
||||
.num-ball-sm { display: inline-block; width: 32px; height: 32px; line-height: 32px; text-align: center; border-radius: 50%; color: #fff; font-weight: bold; font-size: 13px; }
|
||||
.mini-card { text-align: center; background: #f5f5f5; padding: 8px 12px; border-radius: 5px; display: inline-block; margin: 3px; min-width: 65px; }
|
||||
.mini-card .name { font-size: 14px; font-weight: bold; color: #333; }
|
||||
.mini-card .val { font-size: 11px; color: #666; }
|
||||
#dash-chart { width: 100%; height: 280px; }
|
||||
</style>
|
||||
|
||||
<div class="panel panel-default panel-intro">
|
||||
<div class="panel-heading">
|
||||
{:build_heading(null, false)}
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a href="#one" data-toggle="tab">{:__('Dashboard')}</a></li>
|
||||
<li><a href="#two" data-toggle="tab">{:__('Custom')}</a></li>
|
||||
</ul>
|
||||
<div style="float:right;">
|
||||
<div class="form-inline">
|
||||
<label>{:__('Query Periods')}:</label>
|
||||
<input type="number" id="dash-periods" class="form-control input-sm" value="{$periods|htmlentities}" min="10" max="100" style="width:80px;display:inline-block;">
|
||||
<button class="btn btn-sm btn-primary" id="btn-dash-refresh"><i class="fa fa-refresh"></i> {:__('Refresh')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="myTabContent" class="tab-content">
|
||||
<div class="tab-pane fade active in" id="one">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-red"><i class="fa fa-users"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$totaluser|htmlentities}</span>
|
||||
{:__('Total user')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-violet"><i class="fa fa-magic"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$totaladdon|htmlentities}</span>
|
||||
{:__('Total addon')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-blue"><i class="fa fa-leaf"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$attachmentnums|htmlentities}</span>
|
||||
{:__('Total attachment')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-green"><i class="fa fa-user"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$totaladmin|htmlentities}</span>
|
||||
{:__('Total admin')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div id="echart" class="btn-refresh" style="height:300px;width:100%;"></div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="card sameheight-item stats">
|
||||
<div class="card-block">
|
||||
<div class="row row-sm stats-container">
|
||||
<div class="col-xs-6 stat-col">
|
||||
<div class="stat-icon"><i class="fa fa-rocket"></i></div>
|
||||
<div class="stat">
|
||||
<div class="value"> {$todayusersignup|htmlentities}</div>
|
||||
<div class="name"> {:__('Today user signup')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
<div class="stat-icon"><i class="fa fa-vcard"></i></div>
|
||||
<div class="stat">
|
||||
<div class="value"> {$todayuserlogin|htmlentities}</div>
|
||||
<div class="name"> {:__('Today user login')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
<div class="stat-icon"><i class="fa fa-calendar"></i></div>
|
||||
<div class="stat">
|
||||
<div class="value"> {$threednu|htmlentities}</div>
|
||||
<div class="name"> {:__('Three dnu')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
<div class="stat-icon"><i class="fa fa-calendar-plus-o"></i></div>
|
||||
<div class="stat">
|
||||
<div class="value"> {$sevendnu|htmlentities}</div>
|
||||
<div class="name"> {:__('Seven dnu')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
<div class="stat-icon"><i class="fa fa-user-circle"></i></div>
|
||||
<div class="stat">
|
||||
<div class="value"> {$sevendau|htmlentities}</div>
|
||||
<div class="name"> {:__('Seven dau')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
<div class="stat-icon"><i class="fa fa-user-circle-o"></i></div>
|
||||
<div class="stat">
|
||||
<div class="value"> {$thirtydau|htmlentities}</div>
|
||||
<div class="name"> {:__('Thirty dau')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="margin-top:15px;" id="statistics">
|
||||
|
||||
<div class="col-lg-12">
|
||||
</div>
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="panel bg-blue-gradient no-border">
|
||||
<div class="panel-body">
|
||||
<div class="panel-title">
|
||||
<span class="label label-primary pull-right">{:__('Real time')}</span>
|
||||
<h5>{:__('Working addon count')}</h5>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1 class="no-margins">{$totalworkingaddon|htmlentities}</h1>
|
||||
<div class="font-bold"><i class="fa fa-magic"></i>
|
||||
<small>{:__('Working addon count tips')}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="panel bg-teal-gradient no-border">
|
||||
<div class="panel-body">
|
||||
<div class="ibox-title">
|
||||
<span class="label label-primary pull-right">{:__('Real time')}</span>
|
||||
<h5>{:__('Database count')}</h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h1 class="no-margins">{$dbtablenums|htmlentities}</h1>
|
||||
<div class="font-bold"><i class="fa fa-database"></i>
|
||||
<small>{:__('Database table nums')}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h1 class="no-margins">{$dbsize|format_bytes=###,'',0}</h1>
|
||||
<div class="font-bold"><i class="fa fa-filter"></i>
|
||||
<small>{:__('Database size')}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="panel bg-purple-gradient no-border">
|
||||
<div class="panel-body">
|
||||
<div class="ibox-title">
|
||||
<span class="label label-primary pull-right">{:__('Real time')}</span>
|
||||
<h5>{:__('Attachment count')}</h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h1 class="no-margins">{$attachmentnums|htmlentities}</h1>
|
||||
<div class="font-bold"><i class="fa fa-files-o"></i>
|
||||
<small>{:__('Attachment nums')}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h1 class="no-margins">{$attachmentsize|format_bytes=###,'',0}</h1>
|
||||
<div class="font-bold"><i class="fa fa-filter"></i>
|
||||
<small>{:__('Attachment size')}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="panel bg-green-gradient no-border">
|
||||
<div class="panel-body">
|
||||
<div class="ibox-title">
|
||||
<span class="label label-primary pull-right">{:__('Real time')}</span>
|
||||
<h5>{:__('Picture count')}</h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h1 class="no-margins">{$picturenums|htmlentities}</h1>
|
||||
<div class="font-bold"><i class="fa fa-picture-o"></i>
|
||||
<small>{:__('Picture nums')}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h1 class="no-margins">{$picturesize|format_bytes=###,'',0}</h1>
|
||||
<div class="font-bold"><i class="fa fa-filter"></i>
|
||||
<small>{:__('Picture size')}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="two">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
{:__('Custom zone')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dash-content">
|
||||
<div class="text-center" style="padding:60px;"><i class="fa fa-spinner fa-spin fa-2x"></i><br><span class="text-muted">{:__('Loading')}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
var getColor = function (color) {
|
||||
if (!color || color === '—') return '#95a5a6';
|
||||
if (color.indexOf('红') !== -1) return '#e74c3c';
|
||||
if (color.indexOf('蓝') !== -1) return '#3498db';
|
||||
if (color.indexOf('绿') !== -1) return '#2ecc71';
|
||||
return '#95a5a6';
|
||||
};
|
||||
|
||||
var ball = function (num, color) {
|
||||
return '<span class="num-ball-sm" style="background-color:' + getColor(color) + ';">' + num + '</span>';
|
||||
};
|
||||
|
||||
function loadData() {
|
||||
var periods = parseInt($('#dash-periods').val()) || 30;
|
||||
if (periods < 10) periods = 10;
|
||||
if (periods > 100) periods = 100;
|
||||
$('#dash-content').html('<div class="text-center" style="padding:60px;"><i class="fa fa-spinner fa-spin fa-2x"></i><br><span class="text-muted">{:__("Loading")}</span></div>');
|
||||
|
||||
$.ajax({
|
||||
url: 'history/dashboard',
|
||||
type: 'GET',
|
||||
data: {periods: periods},
|
||||
dataType: 'json',
|
||||
success: function (ret) {
|
||||
if (ret.code != 1) {
|
||||
$('#dash-content').html('<div class="alert alert-danger">' + (ret.msg || '加载失败') + '</div>');
|
||||
return;
|
||||
}
|
||||
render(ret.data);
|
||||
},
|
||||
error: function () {
|
||||
$('#dash-content').html('<div class="alert alert-danger">请求失败,请重试</div>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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 html = '';
|
||||
|
||||
// 冷热号码
|
||||
html += '<div class="dash-section"><h4>🔥❄️ 冷热号码</h4><div class="row">';
|
||||
html += '<div class="col-sm-6"><div class="dash-card" style="border-left:3px solid #e74c3c;"><div style="color:#e74c3c;font-weight:bold;margin-bottom:8px;">热号 Top 5</div>';
|
||||
for (var i = 0; i < 5; i++) html += ball(hc.hot[i].num, hc.hot[i].color) + ' ';
|
||||
html += '</div></div>';
|
||||
html += '<div class="col-sm-6"><div class="dash-card" style="border-left:3px solid #3498db;"><div style="color:#3498db;font-weight:bold;margin-bottom:8px;">冷号 Top 5</div>';
|
||||
for (var i = 0; i < 5; i++) html += ball(hc.cold[i].num, hc.cold[i].color) + ' ';
|
||||
html += '</div></div></div></div>';
|
||||
|
||||
// 波色 & 奇偶 & 大小
|
||||
html += '<div class="dash-section"><h4>📊 比例分析</h4><div class="row">';
|
||||
|
||||
// 波色
|
||||
html += '<div class="col-sm-4"><div class="dash-card"><div style="font-weight:bold;margin-bottom:8px;">🎨 波色</div>';
|
||||
html += '<div style="display:flex;justify-content:space-around;">';
|
||||
html += '<div><div style="font-size:24px;font-weight:bold;color:#e74c3c;">' + cw.red + '</div><div class="label-text">红波 ' + cw.red_pct + '%</div></div>';
|
||||
html += '<div><div style="font-size:24px;font-weight:bold;color:#3498db;">' + cw.blue + '</div><div class="label-text">蓝波 ' + cw.blue_pct + '%</div></div>';
|
||||
html += '<div><div style="font-size:24px;font-weight:bold;color:#2ecc71;">' + cw.green + '</div><div class="label-text">绿波 ' + cw.green_pct + '%</div></div>';
|
||||
html += '</div></div></div>';
|
||||
|
||||
// 奇偶
|
||||
html += '<div class="col-sm-4"><div class="dash-card"><div style="font-weight:bold;margin-bottom:8px;">⚖️ 奇偶</div>';
|
||||
html += '<div style="display:flex;justify-content:space-around;">';
|
||||
html += '<div><div style="font-size:24px;font-weight:bold;color:#e74c3c;">' + oe.odd + '</div><div class="label-text">奇数 ' + oe.odd_pct + '%</div></div>';
|
||||
html += '<div><div style="font-size:24px;font-weight:bold;color:#3498db;">' + oe.even + '</div><div class="label-text">偶数 ' + oe.even_pct + '%</div></div>';
|
||||
html += '</div></div></div>';
|
||||
|
||||
// 大小
|
||||
html += '<div class="col-sm-4"><div class="dash-card"><div style="font-weight:bold;margin-bottom:8px;">📏 大小</div>';
|
||||
html += '<div style="display:flex;justify-content:space-around;">';
|
||||
html += '<div><div style="font-size:24px;font-weight:bold;color:#f39c12;">' + bs.big + '</div><div class="label-text">大数 ' + bs.big_pct + '%</div></div>';
|
||||
html += '<div><div style="font-size:24px;font-weight:bold;color:#2ecc71;">' + bs.small + '</div><div class="label-text">小数 ' + bs.small_pct + '%</div></div>';
|
||||
html += '</div></div></div>';
|
||||
|
||||
html += '</div></div>';
|
||||
|
||||
// 生肖
|
||||
html += '<div class="dash-section"><h4>⭐ 生肖排名</h4><div style="display:flex;flex-wrap:wrap;">';
|
||||
for (var i = 0; i < Math.min(zo.list.length, 12); i++) {
|
||||
var z = zo.list[i];
|
||||
html += '<div class="mini-card"><div class="name">' + z.animal + '</div><div class="val">' + z.count + ' (' + z.percent + '%)</div></div>';
|
||||
}
|
||||
html += '</div></div>';
|
||||
|
||||
// 和值
|
||||
html += '<div class="dash-section"><h4>📈 和值统计</h4><div class="row">';
|
||||
html += '<div class="col-sm-4"><div class="dash-card"><div class="big-num">' + sm.avg + '</div><div class="label-text">平均和值</div></div></div>';
|
||||
html += '<div class="col-sm-4"><div class="dash-card"><div class="big-num" style="color:#e74c3c;">' + sm.max + '</div><div class="label-text">最大和值</div></div></div>';
|
||||
html += '<div class="col-sm-4"><div class="dash-card"><div class="big-num" style="color:#3498db;">' + sm.min + '</div><div class="label-text">最小和值</div></div></div>';
|
||||
html += '</div><div id="dash-chart" style="margin-top:15px;"></div></div>';
|
||||
|
||||
// 尾数
|
||||
html += '<div class="dash-section"><h4>🔢 尾数频率</h4><div style="display:flex;flex-wrap:wrap;">';
|
||||
for (var i = 0; i < tn.all.length; i++) {
|
||||
var t = tn.all[i];
|
||||
html += '<div class="mini-card"><div class="name">' + t.tail + '</div><div class="val">' + t.count + ' (' + t.percent + '%)</div></div>';
|
||||
}
|
||||
html += '</div></div>';
|
||||
|
||||
$('#dash-content').html(html);
|
||||
|
||||
// 和值折线图
|
||||
if (typeof echarts !== 'undefined' && sm.expects && sm.expects.length > 0) {
|
||||
var chart = echarts.init(document.getElementById('dash-chart'));
|
||||
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)'}}],
|
||||
grid: {left: 50, right: 20, bottom: 50, top: 20}
|
||||
});
|
||||
$(window).on('resize', function () { chart.resize(); });
|
||||
}
|
||||
}
|
||||
|
||||
$('#btn-dash-refresh').on('click', loadData);
|
||||
loadData();
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user