1054 lines
57 KiB
JavaScript
1054 lines
57 KiB
JavaScript
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||
|
||
var Controller = {
|
||
index: function () {
|
||
Table.api.init({
|
||
extend: {
|
||
index_url: 'history/index' + location.search,
|
||
add_url: 'history/add',
|
||
edit_url: 'history/edit',
|
||
del_url: 'history/del',
|
||
multi_url: 'history/multi',
|
||
import_url: 'history/import',
|
||
table: 'history',
|
||
}
|
||
});
|
||
|
||
var table = $("#table");
|
||
|
||
// 从后端获取颜色和生肖映射
|
||
Controller.api.loadColorMap(function () {
|
||
Controller.api.loadAnimalMap(function () {
|
||
table.bootstrapTable({
|
||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||
pk: 'expect',
|
||
sortName: 'expect',
|
||
columns: [
|
||
[
|
||
{checkbox: true},
|
||
{field: 'expect', title: __('Expect')},
|
||
{field: 'num1', title: __('Num1'), formatter: Controller.api.formatter.numBall},
|
||
{field: 'num2', title: __('Num2'), formatter: Controller.api.formatter.numBall},
|
||
{field: 'num3', title: __('Num3'), formatter: Controller.api.formatter.numBall},
|
||
{field: 'num4', title: __('Num4'), formatter: Controller.api.formatter.numBall},
|
||
{field: 'num5', title: __('Num5'), formatter: Controller.api.formatter.numBall},
|
||
{field: 'num6', title: __('Num6'), formatter: Controller.api.formatter.numBall},
|
||
{field: 'num7', title: __('Num7'), formatter: Controller.api.formatter.numBall},
|
||
{field: 'openTime', title: __('OpenTime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
|
||
]
|
||
]
|
||
});
|
||
|
||
Table.api.bindevent(table);
|
||
});
|
||
});
|
||
|
||
// 遗漏号码按钮事件
|
||
$(document).off('click', '.btn-missingnum').on('click', '.btn-missingnum', function () {
|
||
Controller.api.showMissingNumDialog();
|
||
});
|
||
|
||
// 走势图按钮事件
|
||
$(document).off('click', '.btn-trend').on('click', '.btn-trend', function () {
|
||
Controller.api.showTrendDialog();
|
||
});
|
||
|
||
// 冷热分析按钮事件
|
||
$(document).off('click', '.btn-hotcold').on('click', '.btn-hotcold', function () {
|
||
Controller.api.showHotColdDialog();
|
||
});
|
||
|
||
// 波色分析按钮事件
|
||
$(document).off('click', '.btn-colorwave').on('click', '.btn-colorwave', function () {
|
||
Controller.api.showAnalysisDialog('colorWave');
|
||
});
|
||
// 生肖分析按钮事件
|
||
$(document).off('click', '.btn-zodiac').on('click', '.btn-zodiac', function () {
|
||
Controller.api.showAnalysisDialog('zodiac');
|
||
});
|
||
// 奇偶分析按钮事件
|
||
$(document).off('click', '.btn-oddeven').on('click', '.btn-oddeven', function () {
|
||
Controller.api.showAnalysisDialog('oddEven');
|
||
});
|
||
// 大小分析按钮事件
|
||
$(document).off('click', '.btn-bigsmall').on('click', '.btn-bigsmall', function () {
|
||
Controller.api.showAnalysisDialog('bigSmall');
|
||
});
|
||
// 和值分析按钮事件
|
||
$(document).off('click', '.btn-sumchart').on('click', '.btn-sumchart', function () {
|
||
Controller.api.showSumDialog();
|
||
});
|
||
// 连号分析按钮事件
|
||
$(document).off('click', '.btn-consecutive').on('click', '.btn-consecutive', function () {
|
||
Controller.api.showConsecutiveDialog();
|
||
});
|
||
// 尾数分析按钮事件
|
||
$(document).off('click', '.btn-tailnums').on('click', '.btn-tailnums', function () {
|
||
Controller.api.showAnalysisDialog('tailNumbers');
|
||
});
|
||
|
||
// 综合统计面板按钮事件
|
||
$(document).off('click', '.btn-dashboard').on('click', '.btn-dashboard', function () {
|
||
Controller.api.showDashboard();
|
||
});
|
||
},
|
||
add: function () {
|
||
Controller.api.bindevent();
|
||
},
|
||
edit: function () {
|
||
Controller.api.bindevent();
|
||
},
|
||
api: {
|
||
colorMap: {},
|
||
colorMapLoaded: false,
|
||
animalMap: {},
|
||
animalMapLoaded: false,
|
||
|
||
/**
|
||
* 从后端加载颜色映射并缓存
|
||
*/
|
||
loadColorMap: function (callback) {
|
||
if (Controller.api.colorMapLoaded) {
|
||
callback();
|
||
return;
|
||
}
|
||
$.ajax({
|
||
url: 'num/getColorMap',
|
||
type: 'GET',
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
Controller.api.colorMap = ret.msg;
|
||
}
|
||
Controller.api.colorMapLoaded = true;
|
||
callback();
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 从后端加载生肖映射并缓存
|
||
*/
|
||
loadAnimalMap: function (callback) {
|
||
if (Controller.api.animalMapLoaded) {
|
||
callback();
|
||
return;
|
||
}
|
||
$.ajax({
|
||
url: 'num/getAnimalMap',
|
||
type: 'GET',
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
Controller.api.animalMap = ret.msg;
|
||
}
|
||
Controller.api.animalMapLoaded = true;
|
||
callback();
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 根据数字从映射表中获取生肖
|
||
*/
|
||
getAnimalByNum: function (num) {
|
||
return Controller.api.animalMap[num] || '';
|
||
},
|
||
|
||
/**
|
||
* 根据数字从映射表中获取颜色
|
||
*/
|
||
getColorByNum: function (num) {
|
||
var color = Controller.api.colorMap[num];
|
||
if (!color) return '#95a5a6';
|
||
// 后端返回中文波色,前端映射为CSS颜色
|
||
if (color.indexOf('红') !== -1) return '#e74c3c';
|
||
if (color.indexOf('蓝') !== -1) return '#3498db';
|
||
if (color.indexOf('绿') !== -1) return '#2ecc71';
|
||
return '#95a5a6';
|
||
},
|
||
|
||
formatter: {
|
||
numBall: function (value, row, index) {
|
||
if (value === null || value === undefined || value === '') return '';
|
||
var num = parseInt(value);
|
||
var color = Controller.api.getColorByNum(num);
|
||
var animal = Controller.api.getAnimalByNum(num);
|
||
var html = '<div style="text-align:center;">' +
|
||
'<span class="num-ball" style="display:inline-block;width:32px;height:32px;line-height:32px;text-align:center;border-radius:50%;color:#fff;background-color:' + color + ';font-weight:bold;">' + value + '</span>';
|
||
if (animal) {
|
||
html += '<div style="font-size:10px;color:#666;line-height:1.2;">' + animal + '</div>';
|
||
}
|
||
html += '</div>';
|
||
return html;
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 显示冷热分析弹窗
|
||
*/
|
||
showHotColdDialog: function () {
|
||
var html = '<div style="padding:20px;">' +
|
||
'<div class="form-group" style="border-bottom:1px solid #eee;padding-bottom:10px;margin-bottom:10px;">' +
|
||
' <label style="margin-right:15px;">' + __('Query Type') + ':</label>' +
|
||
' <label class="radio-inline" style="margin-right:15px;">' +
|
||
' <input type="radio" name="hc-type" value="all" checked> ' + __('All Numbers') +
|
||
' </label>' +
|
||
' <label class="radio-inline">' +
|
||
' <input type="radio" name="hc-type" value="special"> ' + __('Special Only') +
|
||
' </label>' +
|
||
'</div>' +
|
||
'<div class="form-group">' +
|
||
' <label>' + __('Query Periods') + ':</label>' +
|
||
' <input type="number" id="hc-periods" class="form-control" value="30" min="10" max="100" style="width:120px;display:inline-block;">' +
|
||
' <button class="btn btn-primary" id="btn-hc-query" style="margin-left:10px;"><i class="fa fa-search"></i> ' + __('Query') + '</button>' +
|
||
'</div>' +
|
||
'<div id="hc-result" style="margin-top:15px;overflow-x:auto;"></div>' +
|
||
'</div>';
|
||
|
||
Layer.open({
|
||
type: 1,
|
||
title: __('Hot/Cold Analysis'),
|
||
area: ['700px', '600px'],
|
||
content: html,
|
||
shadeClose: true,
|
||
success: function (layero, index) {
|
||
$('#btn-hc-query', layero).on('click', function () {
|
||
var periods = parseInt($('#hc-periods', layero).val()) || 30;
|
||
var type = $('input[name="hc-type"]:checked', layero).val();
|
||
Controller.api.queryHotCold(periods, type, layero);
|
||
});
|
||
$('input[name="hc-type"]', layero).on('change', function () {
|
||
var periods = parseInt($('#hc-periods', layero).val()) || 30;
|
||
Controller.api.queryHotCold(periods, $(this).val(), layero);
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
queryHotCold: function (periods, type, layero) {
|
||
var $btn = $('#btn-hc-query', layero);
|
||
$btn.prop('disabled', true);
|
||
$('#hc-result', layero).html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> ' + __('Loading') + '</div>');
|
||
$.ajax({
|
||
url: 'history/hotColdNumbers',
|
||
type: 'GET',
|
||
data: {periods: periods, type: type},
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
Controller.api.renderHotCold(ret.data, layero);
|
||
} else {
|
||
$('#hc-result', layero).html('<div class="alert alert-danger">' + (ret.msg || __('Query failed')) + '</div>');
|
||
}
|
||
},
|
||
error: function () {
|
||
$('#hc-result', layero).html('<div class="alert alert-danger">' + __('Query failed') + '</div>');
|
||
},
|
||
complete: function () {
|
||
$btn.prop('disabled', false);
|
||
}
|
||
});
|
||
},
|
||
|
||
renderHotCold: function (data, layero) {
|
||
var getColor = function (num) {
|
||
var color = data.all.find(function (item) { return item.num === num; });
|
||
if (!color || !color.color) return '#95a5a6';
|
||
if (color.color.indexOf('红') !== -1) return '#e74c3c';
|
||
if (color.color.indexOf('蓝') !== -1) return '#3498db';
|
||
if (color.color.indexOf('绿') !== -1) return '#2ecc71';
|
||
return '#95a5a6';
|
||
};
|
||
|
||
var getAnimal = function (num) {
|
||
var item = data.all.find(function (item) { return item.num === num; });
|
||
return item ? (item.animal || '') : '';
|
||
};
|
||
|
||
var renderSection = function (title, items, icon) {
|
||
var html = '<div style="margin-bottom:15px;"><h4 style="margin:0 0 8px 0;border-bottom:1px solid #eee;padding-bottom:5px;">' + icon + ' ' + title + '</h4>';
|
||
html += '<div style="display:flex;flex-wrap:wrap;gap:8px;">';
|
||
for (var i = 0; i < items.length; i++) {
|
||
var item = items[i];
|
||
var color = getColor(item.num);
|
||
var animal = getAnimal(item.num);
|
||
html += '<div style="text-align:center;background:#f9f9f9;padding:8px;border-radius:6px;min-width:70px;">' +
|
||
'<span style="display:inline-block;width:36px;height:36px;line-height:36px;text-align:center;border-radius:50%;color:#fff;background-color:' + color + ';font-weight:bold;">' + item.num + '</span>' +
|
||
'<div style="margin-top:4px;font-size:10px;color:#666;">' + (animal ? animal + '<br>' : '') + '<b>' + item.count + '</b> (' + item.percent + '%)</div>' +
|
||
'</div>';
|
||
}
|
||
html += '</div></div>';
|
||
return html;
|
||
};
|
||
|
||
var html = '<div style="padding:10px;">' +
|
||
renderSection('热号 Top 10', data.hot, '<span style="color:#e74c3c;">🔥</span>') +
|
||
renderSection('冷号 Top 10', data.cold, '<span style="color:#3498db;">❄</span>') +
|
||
'</div>';
|
||
|
||
$('#hc-result', layero).html(html);
|
||
},
|
||
|
||
/**
|
||
* 显示走势图弹窗
|
||
*/
|
||
showTrendDialog: function () {
|
||
var html = '<div style="padding:20px;">' +
|
||
'<div class="form-group" style="border-bottom:1px solid #eee;padding-bottom:10px;margin-bottom:10px;">' +
|
||
' <label style="margin-right:15px;">' + __('Query Type') + ':</label>' +
|
||
' <label class="radio-inline" style="margin-right:15px;">' +
|
||
' <input type="radio" name="trend-type" value="all" checked> ' + __('All Numbers') +
|
||
' </label>' +
|
||
' <label class="radio-inline">' +
|
||
' <input type="radio" name="trend-type" value="special"> ' + __('Special Only') +
|
||
' </label>' +
|
||
'</div>' +
|
||
'<div class="form-group">' +
|
||
' <label>' + __('Query Periods') + ':</label>' +
|
||
' <input type="number" id="trend-periods" class="form-control" value="30" min="10" max="100" style="width:120px;display:inline-block;">' +
|
||
' <button class="btn btn-primary" id="btn-trend-query" style="margin-left:10px;"><i class="fa fa-search"></i> ' + __('Query') + '</button>' +
|
||
'</div>' +
|
||
'<div id="trend-result" style="margin-top:15px;overflow-x:auto;"></div>' +
|
||
'</div>';
|
||
|
||
Layer.open({
|
||
type: 1,
|
||
title: __('Trend Chart'),
|
||
area: ['90%', '80%'],
|
||
content: html,
|
||
shadeClose: false,
|
||
maxmin: true,
|
||
success: function (layero, index) {
|
||
$('#btn-trend-query', layero).on('click', function () {
|
||
var periods = parseInt($('#trend-periods', layero).val()) || 30;
|
||
var type = $('input[name="trend-type"]:checked', layero).val();
|
||
Controller.api.queryTrend(periods, type, layero);
|
||
});
|
||
$('input[name="trend-type"]', layero).on('change', function () {
|
||
var periods = parseInt($('#trend-periods', layero).val()) || 30;
|
||
Controller.api.queryTrend(periods, $(this).val(), layero);
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 查询走势图
|
||
*/
|
||
queryTrend: function (periods, type, layero) {
|
||
var $btn = $('#btn-trend-query', layero);
|
||
$btn.prop('disabled', true);
|
||
$('#trend-result', layero).html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> ' + __('Loading') + '</div>');
|
||
$.ajax({
|
||
url: 'history/trendData',
|
||
type: 'GET',
|
||
data: {periods: periods, type: type},
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
Controller.api.renderTrend(ret.data, type, layero);
|
||
} else {
|
||
$('#trend-result', layero).html('<div class="alert alert-danger">' + (ret.msg || __('Query failed')) + '</div>');
|
||
}
|
||
},
|
||
error: function () {
|
||
$('#trend-result', layero).html('<div class="alert alert-danger">' + __('Query failed') + '</div>');
|
||
},
|
||
complete: function () {
|
||
$btn.prop('disabled', false);
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 渲染走势图(ECharts 折线图)
|
||
*/
|
||
renderTrend: function (data, type, layero) {
|
||
var expects = data.expects;
|
||
var rows = data.data;
|
||
var colorMap = data.colorMap;
|
||
|
||
if (!expects || expects.length === 0) {
|
||
$('#trend-result', layero).html('<div class="alert alert-info">' + __('No data available') + '</div>');
|
||
return;
|
||
}
|
||
|
||
var getColor = function (num) {
|
||
var color = colorMap[num];
|
||
if (!color) return '#95a5a6';
|
||
if (color.indexOf('红') !== -1) return '#e74c3c';
|
||
if (color.indexOf('蓝') !== -1) return '#3498db';
|
||
if (color.indexOf('绿') !== -1) return '#2ecc71';
|
||
return '#95a5a6';
|
||
};
|
||
|
||
$('#trend-result', layero).html('<div id="trend-chart" style="width:100%;height:500px;"></div>');
|
||
|
||
var chartDom = document.getElementById('trend-chart');
|
||
var myChart = echarts.init(chartDom);
|
||
|
||
var series = [];
|
||
if (type === 'special') {
|
||
series = [{
|
||
name: '特码',
|
||
type: 'line',
|
||
data: rows.map(function (r) { return r.num7; }),
|
||
smooth: false,
|
||
symbol: 'circle',
|
||
symbolSize: 8,
|
||
lineStyle: { width: 2 },
|
||
itemStyle: {
|
||
color: function (params) {
|
||
var num = params.data;
|
||
return getColor(num);
|
||
}
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: 'top',
|
||
fontSize: 11,
|
||
color: '#333'
|
||
}
|
||
}];
|
||
} else {
|
||
var numFields = [];
|
||
for (var c = 1; c <= 7; c++) {
|
||
numFields.push('num' + c);
|
||
}
|
||
var colors = ['#e74c3c', '#3498db', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c', '#e67e22'];
|
||
for (var f = 0; f < numFields.length; f++) {
|
||
(function (idx) {
|
||
series.push({
|
||
name: '第' + (idx + 1) + '码',
|
||
type: 'line',
|
||
data: rows.map(function (r) { return r[numFields[idx]]; }),
|
||
smooth: false,
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
lineStyle: { width: 2 },
|
||
itemStyle: { color: colors[idx] },
|
||
label: {
|
||
show: true,
|
||
position: 'top',
|
||
fontSize: 10,
|
||
color: '#333'
|
||
}
|
||
});
|
||
})(f);
|
||
}
|
||
}
|
||
|
||
var option = {
|
||
title: { text: type === 'special' ? '特码走势' : '全部号码走势', left: 'center', textStyle: { fontSize: 14 } },
|
||
tooltip: { trigger: 'axis', formatter: function (params) {
|
||
var tip = '期号: ' + params[0].axisValueLabel + '<br/>';
|
||
for (var i = 0; i < params.length; i++) {
|
||
tip += params[i].seriesName + ': <b>' + params[i].data + '</b><br/>';
|
||
}
|
||
return tip;
|
||
}},
|
||
legend: { bottom: 10, data: series.map(function (s) { return s.name; }) },
|
||
grid: { left: 40, right: 20, bottom: 50, top: 40 },
|
||
xAxis: { type: 'category', data: expects, axisLabel: { rotate: 45, fontSize: 10 } },
|
||
yAxis: { type: 'value', min: 0, max: 50, splitLine: { show: true, lineStyle: { type: 'dashed' } } },
|
||
dataZoom: [{ type: 'slider', bottom: 30, height: 20, start: 0, end: 100 }],
|
||
series: series
|
||
};
|
||
|
||
myChart.setOption(option);
|
||
window.addEventListener('resize', function () { myChart.resize(); });
|
||
},
|
||
|
||
/**
|
||
* 显示遗漏号码分析弹窗
|
||
*/
|
||
showMissingNumDialog: function () {
|
||
var html = '<div style="padding:20px;">' +
|
||
'<div class="form-group" style="border-bottom:1px solid #eee;padding-bottom:10px;margin-bottom:10px;">' +
|
||
' <label style="margin-right:15px;">' + __('Query Type') + ':</label>' +
|
||
' <label class="radio-inline" style="margin-right:15px;">' +
|
||
' <input type="radio" name="missing-type" value="all" checked> ' + __('All Numbers') +
|
||
' </label>' +
|
||
' <label class="radio-inline">' +
|
||
' <input type="radio" name="missing-type" value="special"> ' + __('Special Only') +
|
||
' </label>' +
|
||
'</div>' +
|
||
'<div class="form-group">' +
|
||
' <label>' + __('Query Periods') + ':</label>' +
|
||
' <input type="number" id="missing-periods" class="form-control" value="10" min="1" max="100" style="width:120px;display:inline-block;">' +
|
||
' <button class="btn btn-primary" id="btn-missing-query" style="margin-left:10px;"><i class="fa fa-search"></i> ' + __('Query') + '</button>' +
|
||
'</div>' +
|
||
'<div id="missing-result" style="margin-top:15px;"></div>' +
|
||
'</div>';
|
||
|
||
Layer.open({
|
||
type: 1,
|
||
title: __('Missing Number Analysis'),
|
||
area: ['650px', '550px'],
|
||
content: html,
|
||
shadeClose: true,
|
||
success: function (layero, index) {
|
||
// 绑定查询按钮事件
|
||
$('#btn-missing-query', layero).on('click', function () {
|
||
var periods = parseInt($('#missing-periods', layero).val()) || 10;
|
||
var type = $('input[name="missing-type"]:checked', layero).val();
|
||
Controller.api.queryMissingNum(periods, type, layero);
|
||
});
|
||
// 切换类型时自动查询
|
||
$('input[name="missing-type"]', layero).on('change', function () {
|
||
var periods = parseInt($('#missing-periods', layero).val()) || 10;
|
||
Controller.api.queryMissingNum(periods, $(this).val(), layero);
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 查询遗漏号码
|
||
*/
|
||
queryMissingNum: function (periods, type, layero) {
|
||
// 确保颜色映射已加载
|
||
if (!Controller.api.colorMapLoaded) {
|
||
Controller.api.loadColorMap(function () {
|
||
Controller.api._doQueryMissingNum(periods, type, layero);
|
||
});
|
||
} else {
|
||
Controller.api._doQueryMissingNum(periods, type, layero);
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 执行遗漏号码查询(内部方法)
|
||
*/
|
||
_doQueryMissingNum: function (periods, type, layero) {
|
||
var $btn = $('#btn-missing-query', layero);
|
||
$btn.prop('disabled', true);
|
||
$('#missing-result', layero).html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> ' + __('Loading') + '</div>');
|
||
$.ajax({
|
||
url: 'history/missingNum',
|
||
type: 'GET',
|
||
data: {periods: periods, type: type},
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
Controller.api.renderMissingNum(ret.data, periods, layero);
|
||
} else {
|
||
$('#missing-result', layero).html('<div class="alert alert-danger">' + (ret.msg || __('Query failed')) + '</div>');
|
||
}
|
||
},
|
||
error: function () {
|
||
$('#missing-result', layero).html('<div class="alert alert-danger">' + __('Query failed') + '</div>');
|
||
},
|
||
complete: function () {
|
||
$btn.prop('disabled', false);
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 渲染遗漏号码结果
|
||
*/
|
||
renderMissingNum: function (data, periods, layero) {
|
||
if (!data || data.length === 0) {
|
||
$('#missing-result', layero).html('<div class="alert alert-info">' + __('No missing numbers found') + '</div>');
|
||
return;
|
||
}
|
||
var container = $('<div style="display:flex;flex-wrap:wrap;gap:12px;"></div>');
|
||
for (var i = 0; i < data.length; i++) {
|
||
var color = Controller.api.getColorByNum(data[i].num);
|
||
var animal = Controller.api.getAnimalByNum(data[i].num);
|
||
var $item = $('<div style="text-align:center;"></div>');
|
||
var $ball = $('<span class="num-ball"></span>').css({
|
||
'display': 'inline-block',
|
||
'width': '48px',
|
||
'height': '48px',
|
||
'line-height': '48px',
|
||
'text-align': 'center',
|
||
'border-radius': '50%',
|
||
'color': '#fff',
|
||
'background-color': color,
|
||
'font-weight': 'bold',
|
||
'font-size': '18px'
|
||
}).text(data[i].num);
|
||
var $content = $('<div></div>').append($ball);
|
||
if (animal) {
|
||
$content.append($('<div style="margin-top:3px;font-size:11px;color:#666;line-height:1.2;"></div>').text(animal));
|
||
}
|
||
$content.append($('<div style="margin-top:3px;font-size:12px;color:#666;"></div>').text(
|
||
__('Missing') + ' ' + data[i].omit + ' ' + __('periods')
|
||
));
|
||
$item.append($content);
|
||
container.append($item);
|
||
}
|
||
$('#missing-result', layero).html('').append(container);
|
||
},
|
||
|
||
bindevent: function () {
|
||
Form.api.bindevent($("form[role=form]"));
|
||
},
|
||
|
||
/**
|
||
* 通用分析弹窗(波色、生肖、奇偶、大小、尾数)
|
||
*/
|
||
showAnalysisDialog: function (type) {
|
||
var titles = {
|
||
colorWave: __('Color Wave'),
|
||
zodiac: __('Zodiac'),
|
||
oddEven: __('Odd/Even'),
|
||
bigSmall: __('Big/Small'),
|
||
tailNumbers: __('Tail Numbers')
|
||
};
|
||
var endpoints = {
|
||
colorWave: 'history/colorWaveAnalysis',
|
||
zodiac: 'history/zodiacAnalysis',
|
||
oddEven: 'history/oddEvenAnalysis',
|
||
bigSmall: 'history/bigSmallAnalysis',
|
||
tailNumbers: 'history/tailNumbers'
|
||
};
|
||
var hasType = ['colorWave', 'zodiac', 'oddEven', 'bigSmall', 'tailNumbers'].indexOf(type) !== -1;
|
||
|
||
var html = '<div style="padding:20px;">';
|
||
if (hasType) {
|
||
html += '<div class="form-group" style="border-bottom:1px solid #eee;padding-bottom:10px;margin-bottom:10px;">' +
|
||
' <label style="margin-right:15px;">' + __('Query Type') + ':</label>' +
|
||
' <label class="radio-inline" style="margin-right:15px;">' +
|
||
' <input type="radio" name="analysis-type-' + type + '" value="all" checked> ' + __('All Numbers') +
|
||
' </label>' +
|
||
' <label class="radio-inline">' +
|
||
' <input type="radio" name="analysis-type-' + type + '" value="special"> ' + __('Special Only') +
|
||
' </label>' +
|
||
'</div>';
|
||
}
|
||
html += '<div class="form-group">' +
|
||
' <label>' + __('Query Periods') + ':</label>' +
|
||
' <input type="number" id="analysis-periods-' + type + '" class="form-control" value="30" min="10" max="100" style="width:120px;display:inline-block;">' +
|
||
' <button class="btn btn-primary" id="btn-analysis-' + type + '" style="margin-left:10px;"><i class="fa fa-search"></i> ' + __('Query') + '</button>' +
|
||
'</div>' +
|
||
'<div id="analysis-result-' + type + '" style="margin-top:15px;overflow-x:auto;"></div>' +
|
||
'</div>';
|
||
|
||
Layer.open({
|
||
type: 1,
|
||
title: titles[type] || type,
|
||
area: ['650px', '550px'],
|
||
content: html,
|
||
shadeClose: true,
|
||
success: function (layero, index) {
|
||
$('#btn-analysis-' + type, layero).on('click', function () {
|
||
var periods = parseInt($('#analysis-periods-' + type, layero).val()) || 30;
|
||
var tp = hasType ? $('input[name="analysis-type-' + type + '"]:checked', layero).val() : 'all';
|
||
Controller.api.queryAnalysis(periods, tp, type, endpoints[type], layero);
|
||
});
|
||
if (hasType) {
|
||
$('input[name="analysis-type-' + type + '"]', layero).on('change', function () {
|
||
var periods = parseInt($('#analysis-periods-' + type, layero).val()) || 30;
|
||
Controller.api.queryAnalysis(periods, $(this).val(), type, endpoints[type], layero);
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
queryAnalysis: function (periods, type, analysisType, endpoint, layero) {
|
||
var $btn = $('#btn-analysis-' + analysisType, layero);
|
||
$btn.prop('disabled', true);
|
||
$('#analysis-result-' + analysisType, layero).html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> ' + __('Loading') + '</div>');
|
||
$.ajax({
|
||
url: endpoint,
|
||
type: 'GET',
|
||
data: {periods: periods, type: type},
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
var renderMap = {
|
||
colorWave: 'renderColorWaveAnalysis',
|
||
zodiac: 'renderZodiacAnalysis',
|
||
oddEven: 'renderOddEvenAnalysis',
|
||
bigSmall: 'renderBigSmallAnalysis',
|
||
tailNumbers: 'renderTailNumbers'
|
||
};
|
||
var renderFn = renderMap[analysisType];
|
||
if (renderFn && typeof Controller.api[renderFn] === 'function') {
|
||
Controller.api[renderFn](ret.data, layero);
|
||
} else {
|
||
$('#analysis-result-' + analysisType, layero).html('<div class="alert alert-danger">渲染方法不存在: ' + renderFn + '</div>');
|
||
}
|
||
} else {
|
||
$('#analysis-result-' + analysisType, layero).html('<div class="alert alert-danger">' + (ret.msg || __('Query failed')) + '</div>');
|
||
}
|
||
},
|
||
error: function () {
|
||
$('#analysis-result-' + analysisType, layero).html('<div class="alert alert-danger">' + __('Query failed') + '</div>');
|
||
},
|
||
complete: function () {
|
||
$btn.prop('disabled', false);
|
||
}
|
||
});
|
||
},
|
||
|
||
renderColorWaveAnalysis: function (data, layero) {
|
||
var html = '<div style="padding:15px;"><div style="display:flex;justify-content:space-around;">';
|
||
var items = [
|
||
{label: '红波', value: data.red, pct: data.red_pct, color: '#e74c3c'},
|
||
{label: '蓝波', value: data.blue, pct: data.blue_pct, color: '#3498db'},
|
||
{label: '绿波', value: data.green, pct: data.green_pct, color: '#2ecc71'}
|
||
];
|
||
for (var i = 0; i < items.length; i++) {
|
||
var item = items[i];
|
||
html += '<div style="text-align:center;padding:20px;border-radius:8px;background:#f5f5f5;min-width:120px;">' +
|
||
'<div style="width:60px;height:60px;line-height:60px;border-radius:50%;background-color:' + item.color + ';color:#fff;font-size:24px;font-weight:bold;margin:0 auto;">' + item.value + '</div>' +
|
||
'<div style="margin-top:10px;font-size:14px;color:#333;">' + item.label + '</div>' +
|
||
'<div style="font-size:12px;color:#999;">' + item.pct + '%</div>' +
|
||
'</div>';
|
||
}
|
||
html += '</div><div style="margin-top:15px;color:#999;font-size:12px;text-align:center;">总计: ' + data.total + ' 个号码</div></div>';
|
||
$('#analysis-result-colorWave', layero).html(html);
|
||
},
|
||
|
||
renderZodiacAnalysis: function (data, layero) {
|
||
var html = '<div style="padding:15px;"><div style="display:flex;flex-wrap:wrap;gap:8px;">';
|
||
for (var i = 0; i < data.list.length; i++) {
|
||
var item = data.list[i];
|
||
html += '<div style="text-align:center;background:#f9f9f9;padding:10px 15px;border-radius:6px;min-width:90px;">' +
|
||
'<div style="font-size:18px;font-weight:bold;color:#333;">' + item.animal + '</div>' +
|
||
'<div style="font-size:12px;color:#666;">' + item.count + ' (' + item.percent + '%)</div>' +
|
||
'</div>';
|
||
}
|
||
html += '</div></div>';
|
||
$('#analysis-result-zodiac', layero).html(html);
|
||
},
|
||
|
||
renderOddEvenAnalysis: function (data, layero) {
|
||
var html = '<div style="padding:15px;"><div style="display:flex;justify-content:space-around;margin-bottom:15px;">';
|
||
html += '<div style="text-align:center;padding:15px;border-radius:8px;background:#f5f5f5;min-width:140px;">' +
|
||
'<div style="font-size:28px;font-weight:bold;color:#e74c3c;">' + data.odd + '</div>' +
|
||
'<div style="font-size:14px;color:#333;">奇数</div>' +
|
||
'<div style="font-size:12px;color:#999;">' + data.odd_pct + '%</div></div>';
|
||
html += '<div style="text-align:center;padding:15px;border-radius:8px;background:#f5f5f5;min-width:140px;">' +
|
||
'<div style="font-size:28px;font-weight:bold;color:#3498db;">' + data.even + '</div>' +
|
||
'<div style="font-size:14px;color:#333;">偶数</div>' +
|
||
'<div style="font-size:12px;color:#999;">' + data.even_pct + '%</div></div>';
|
||
html += '</div></div>';
|
||
$('#analysis-result-oddEven', layero).html(html);
|
||
},
|
||
|
||
renderBigSmallAnalysis: function (data, layero) {
|
||
var html = '<div style="padding:15px;"><div style="display:flex;justify-content:space-around;margin-bottom:15px;">';
|
||
html += '<div style="text-align:center;padding:15px;border-radius:8px;background:#f5f5f5;min-width:140px;">' +
|
||
'<div style="font-size:28px;font-weight:bold;color:#f39c12;">' + data.big + '</div>' +
|
||
'<div style="font-size:14px;color:#333;">大数(25-49)</div>' +
|
||
'<div style="font-size:12px;color:#999;">' + data.big_pct + '%</div></div>';
|
||
html += '<div style="text-align:center;padding:15px;border-radius:8px;background:#f5f5f5;min-width:140px;">' +
|
||
'<div style="font-size:28px;font-weight:bold;color:#2ecc71;">' + data.small + '</div>' +
|
||
'<div style="font-size:14px;color:#333;">小数(1-24)</div>' +
|
||
'<div style="font-size:12px;color:#999;">' + data.small_pct + '%</div></div>';
|
||
html += '</div></div>';
|
||
$('#analysis-result-bigSmall', layero).html(html);
|
||
},
|
||
|
||
renderTailNumbers: function (data, layero) {
|
||
var html = '<div style="padding:15px;"><div style="display:flex;flex-wrap:wrap;gap:8px;">';
|
||
for (var i = 0; i < data.all.length; i++) {
|
||
var item = data.all[i];
|
||
html += '<div style="text-align:center;background:#f9f9f9;padding:10px 15px;border-radius:6px;min-width:70px;">' +
|
||
'<div style="font-size:22px;font-weight:bold;color:#333;">' + item.tail + '</div>' +
|
||
'<div style="font-size:12px;color:#666;">' + item.count + ' (' + item.percent + '%)</div></div>';
|
||
}
|
||
html += '</div></div>';
|
||
$('#analysis-result-tailNumbers', layero).html(html);
|
||
},
|
||
|
||
/**
|
||
* 和值分析弹窗
|
||
*/
|
||
showSumDialog: function () {
|
||
var html = '<div style="padding:20px;">' +
|
||
'<div class="form-group">' +
|
||
' <label>' + __('Query Periods') + ':</label>' +
|
||
' <input type="number" id="sum-periods" class="form-control" value="30" min="10" max="100" style="width:120px;display:inline-block;">' +
|
||
' <button class="btn btn-primary" id="btn-sum-query" style="margin-left:10px;"><i class="fa fa-search"></i> ' + __('Query') + '</button>' +
|
||
'</div>' +
|
||
'<div id="sum-result" style="margin-top:15px;"></div>' +
|
||
'</div>';
|
||
|
||
Layer.open({
|
||
type: 1,
|
||
title: __('Sum Chart'),
|
||
area: ['750px', '400px'],
|
||
content: html,
|
||
shadeClose: true,
|
||
success: function (layero, index) {
|
||
$('#btn-sum-query', layero).on('click', function () {
|
||
var periods = parseInt($('#sum-periods', layero).val()) || 30;
|
||
Controller.api.querySum(periods, layero);
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
querySum: function (periods, layero) {
|
||
var $btn = $('#btn-sum-query', layero);
|
||
$btn.prop('disabled', true);
|
||
$('#sum-result', layero).html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> ' + __('Loading') + '</div>');
|
||
$.ajax({
|
||
url: 'history/sumAnalysis',
|
||
type: 'GET',
|
||
data: {periods: periods},
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
Controller.api.renderSum(ret.data, layero);
|
||
} else {
|
||
$('#sum-result', layero).html('<div class="alert alert-danger">' + (ret.msg || __('Query failed')) + '</div>');
|
||
}
|
||
},
|
||
error: function () {
|
||
$('#sum-result', layero).html('<div class="alert alert-danger">' + __('Query failed') + '</div>');
|
||
},
|
||
complete: function () {
|
||
$btn.prop('disabled', false);
|
||
}
|
||
});
|
||
},
|
||
|
||
renderSum: function (data, layero) {
|
||
var html = '<div style="padding:15px;"><div style="display:flex;justify-content:space-around;margin-bottom:15px;">';
|
||
html += '<div style="text-align:center;padding:10px;"><div style="font-size:20px;font-weight:bold;color:#333;">' + data.avg + '</div><div style="font-size:12px;color:#999;">平均和值</div></div>';
|
||
html += '<div style="text-align:center;padding:10px;"><div style="font-size:20px;font-weight:bold;color:#e74c3c;">' + data.max + '</div><div style="font-size:12px;color:#999;">最大和值</div></div>';
|
||
html += '<div style="text-align:center;padding:10px;"><div style="font-size:20px;font-weight:bold;color:#3498db;">' + data.min + '</div><div style="font-size:12px;color:#999;">最小和值</div></div>';
|
||
html += '</div><div id="sum-chart" style="width:100%;height:250px;"></div></div>';
|
||
$('#sum-result', layero).html(html);
|
||
|
||
var chartDom = document.getElementById('sum-chart');
|
||
if (chartDom && typeof echarts !== 'undefined') {
|
||
var myChart = echarts.init(chartDom);
|
||
myChart.setOption({
|
||
xAxis: {type: 'category', data: data.expects, axisLabel: {rotate: 45, fontSize: 10}},
|
||
yAxis: {type: 'value'},
|
||
series: [{type: 'line', data: data.sums, smooth: true, itemStyle: {color: '#3498db'}, areaStyle: {color: 'rgba(52,152,219,0.1)'}}],
|
||
grid: {left: 40, right: 20, bottom: 40, top: 20}
|
||
});
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 连号分析弹窗
|
||
*/
|
||
showConsecutiveDialog: function () {
|
||
var html = '<div style="padding:20px;">' +
|
||
'<div class="form-group">' +
|
||
' <label>' + __('Query Periods') + ':</label>' +
|
||
' <input type="number" id="consecutive-periods" class="form-control" value="30" min="10" max="100" style="width:120px;display:inline-block;">' +
|
||
' <button class="btn btn-primary" id="btn-consecutive-query" style="margin-left:10px;"><i class="fa fa-search"></i> ' + __('Query') + '</button>' +
|
||
'</div>' +
|
||
'<div id="consecutive-result" style="margin-top:15px;overflow-x:auto;"></div>' +
|
||
'</div>';
|
||
|
||
Layer.open({
|
||
type: 1,
|
||
title: __('Consecutive'),
|
||
area: ['600px', '500px'],
|
||
content: html,
|
||
shadeClose: true,
|
||
success: function (layero, index) {
|
||
$('#btn-consecutive-query', layero).on('click', function () {
|
||
var periods = parseInt($('#consecutive-periods', layero).val()) || 30;
|
||
Controller.api.queryConsecutive(periods, layero);
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
queryConsecutive: function (periods, layero) {
|
||
var $btn = $('#btn-consecutive-query', layero);
|
||
$btn.prop('disabled', true);
|
||
$('#consecutive-result', layero).html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> ' + __('Loading') + '</div>');
|
||
$.ajax({
|
||
url: 'history/consecutiveNumbers',
|
||
type: 'GET',
|
||
data: {periods: periods},
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
Controller.api.renderConsecutive(ret.data, layero);
|
||
} else {
|
||
$('#consecutive-result', layero).html('<div class="alert alert-danger">' + (ret.msg || __('Query failed')) + '</div>');
|
||
}
|
||
},
|
||
error: function () {
|
||
$('#consecutive-result', layero).html('<div class="alert alert-danger">' + __('Query failed') + '</div>');
|
||
},
|
||
complete: function () {
|
||
$btn.prop('disabled', false);
|
||
}
|
||
});
|
||
},
|
||
|
||
renderConsecutive: function (data, layero) {
|
||
var html = '<div style="padding:15px;">';
|
||
html += '<h4 style="margin:0 0 10px 0;border-bottom:1px solid #eee;padding-bottom:5px;">连号对</h4>';
|
||
html += '<div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:15px;">';
|
||
var pairs = data.pairs;
|
||
if (pairs && Object.keys(pairs).length > 0) {
|
||
for (var pair in pairs) {
|
||
html += '<div style="background:#f5f5f5;padding:6px 12px;border-radius:4px;font-size:13px;">' + pair + ' <b>×' + pairs[pair] + '</b></div>';
|
||
}
|
||
} else {
|
||
html += '<div style="color:#999;font-size:13px;">暂无连号数据</div>';
|
||
}
|
||
html += '</div><h4 style="margin:0 0 10px 0;border-bottom:1px solid #eee;padding-bottom:5px;">三连号</h4>';
|
||
html += '<div style="display:flex;flex-wrap:wrap;gap:6px;">';
|
||
var triples = data.triples;
|
||
if (triples && Object.keys(triples).length > 0) {
|
||
for (var triple in triples) {
|
||
html += '<div style="background:#f5f5f5;padding:6px 12px;border-radius:4px;font-size:13px;">' + triple + ' <b>×' + triples[triple] + '</b></div>';
|
||
}
|
||
} else {
|
||
html += '<div style="color:#999;font-size:13px;">暂无三连号数据</div>';
|
||
}
|
||
html += '</div></div>';
|
||
$('#consecutive-result', layero).html(html);
|
||
},
|
||
|
||
/**
|
||
* 综合统计面板
|
||
*/
|
||
showDashboard: function () {
|
||
var html = '<div style="padding:20px;">' +
|
||
'<div class="form-group">' +
|
||
' <label>' + __('Query Periods') + ':</label>' +
|
||
' <input type="number" id="dash-periods" class="form-control" value="30" min="10" max="100" style="width:120px;display:inline-block;">' +
|
||
' <button class="btn btn-primary" id="btn-dash-query" style="margin-left:10px;"><i class="fa fa-search"></i> ' + __('Query') + '</button>' +
|
||
'</div>' +
|
||
'<div id="dash-result" style="margin-top:15px;"></div>' +
|
||
'</div>';
|
||
|
||
Layer.open({
|
||
type: 1,
|
||
title: __('Dashboard'),
|
||
area: ['90%', '90%'],
|
||
content: html,
|
||
shadeClose: false,
|
||
maxmin: true,
|
||
success: function (layero, index) {
|
||
$('#btn-dash-query', layero).on('click', function () {
|
||
var periods = parseInt($('#dash-periods', layero).val()) || 30;
|
||
Controller.api.queryDashboard(periods, layero);
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
queryDashboard: function (periods, layero) {
|
||
var $btn = $('#btn-dash-query', layero);
|
||
$btn.prop('disabled', true);
|
||
$('#dash-result', layero).html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> ' + __('Loading') + '</div>');
|
||
$.ajax({
|
||
url: 'history/dashboard',
|
||
type: 'GET',
|
||
data: {periods: periods},
|
||
dataType: 'json',
|
||
success: function (ret) {
|
||
if (ret.code == 1) {
|
||
Controller.api.renderDashboard(ret.data, layero);
|
||
} else {
|
||
$('#dash-result', layero).html('<div class="alert alert-danger">' + (ret.msg || __('Query failed')) + '</div>');
|
||
}
|
||
},
|
||
error: function () {
|
||
$('#dash-result', layero).html('<div class="alert alert-danger">' + __('Query failed') + '</div>');
|
||
},
|
||
complete: function () {
|
||
$btn.prop('disabled', false);
|
||
}
|
||
});
|
||
},
|
||
|
||
renderDashboard: function (data, layero) {
|
||
var getColor = function (color) {
|
||
if (!color) return '#95a5a6';
|
||
if (color.indexOf('红') !== -1) return '#e74c3c';
|
||
if (color.indexOf('蓝') !== -1) return '#3498db';
|
||
if (color.indexOf('绿') !== -1) return '#2ecc71';
|
||
return '#95a5a6';
|
||
};
|
||
|
||
var hc = data.hotcold;
|
||
var cw = data.colorwave;
|
||
var zo = data.zodiac;
|
||
var oe = data.oddeven;
|
||
var bs = data.bigsmall;
|
||
var sm = data.sum;
|
||
var tn = data.tailnumbers;
|
||
|
||
var ballHtml = function (item) {
|
||
return '<div style="text-align:center;display:inline-block;margin:3px;"><span style="display:inline-block;width:28px;height:28px;line-height:28px;text-align:center;border-radius:50%;color:#fff;background-color:' + getColor(item.color) + ';font-weight:bold;font-size:12px;">' + item.num + '</span><div style="font-size:9px;color:#666;">' + item.count + '</div></div>';
|
||
};
|
||
|
||
var html = '<div style="padding:10px;max-height:75vh;overflow-y:auto;">';
|
||
|
||
// 冷热号码
|
||
html += '<h4 style="border-bottom:1px solid #eee;padding-bottom:5px;">🔥❄️ 冷热号码</h4>';
|
||
html += '<div style="display:flex;"><div style="flex:1;padding:5px;"><b style="color:#e74c3c;">热号 Top5</b><div>';
|
||
for (var i = 0; i < 5; i++) html += ballHtml(hc.hot[i]);
|
||
html += '</div></div><div style="flex:1;padding:5px;"><b style="color:#3498db;">冷号 Top5</b><div>';
|
||
for (var i = 0; i < 5; i++) html += ballHtml(hc.cold[i]);
|
||
html += '</div></div></div>';
|
||
|
||
// 波色分析
|
||
html += '<h4 style="border-bottom:1px solid #eee;padding-bottom:5px;">🎨 波色比例</h4>';
|
||
html += '<div style="display:flex;gap:15px;">';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#fce4ec;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#e74c3c;">' + cw.red + '</div><div>红波 ' + cw.red_pct + '%</div></div>';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#e3f2fd;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#3498db;">' + cw.blue + '</div><div>蓝波 ' + cw.blue_pct + '%</div></div>';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#e8f5e9;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#2ecc71;">' + cw.green + '</div><div>绿波 ' + cw.green_pct + '%</div></div>';
|
||
html += '</div>';
|
||
|
||
// 生肖分析
|
||
html += '<h4 style="border-bottom:1px solid #eee;padding-bottom:5px;">⭐ 生肖排名</h4>';
|
||
html += '<div style="display:flex;flex-wrap:wrap;gap:5px;">';
|
||
for (var i = 0; i < Math.min(zo.list.length, 12); i++) {
|
||
var z = zo.list[i];
|
||
html += '<div style="text-align:center;background:#f5f5f5;padding:5px 10px;border-radius:4px;"><div style="font-size:14px;font-weight:bold;">' + z.animal + '</div><div style="font-size:10px;color:#666;">' + z.count + ' (' + z.percent + '%)</div></div>';
|
||
}
|
||
html += '</div>';
|
||
|
||
// 奇偶分析
|
||
html += '<h4 style="border-bottom:1px solid #eee;padding-bottom:5px;">⚖️ 奇偶分析</h4>';
|
||
html += '<div style="display:flex;gap:15px;">';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#f9f9f9;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#e74c3c;">' + oe.odd + ' (' + oe.odd_pct + '%)</div><div>奇数</div></div>';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#f9f9f9;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#3498db;">' + oe.even + ' (' + oe.even_pct + '%)</div><div>偶数</div></div>';
|
||
html += '</div>';
|
||
|
||
// 大小分析
|
||
html += '<h4 style="border-bottom:1px solid #eee;padding-bottom:5px;">📊 大小分析</h4>';
|
||
html += '<div style="display:flex;gap:15px;">';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#f9f9f9;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#f39c12;">' + bs.big + ' (' + bs.big_pct + '%)</div><div>大数(25-49)</div></div>';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#f9f9f9;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#2ecc71;">' + bs.small + ' (' + bs.small_pct + '%)</div><div>小数(1-24)</div></div>';
|
||
html += '</div>';
|
||
|
||
// 和值
|
||
html += '<h4 style="border-bottom:1px solid #eee;padding-bottom:5px;">📈 和值统计</h4>';
|
||
html += '<div style="display:flex;gap:15px;">';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#f9f9f9;border-radius:6px;"><div style="font-size:20px;font-weight:bold;">' + sm.avg + '</div><div>平均</div></div>';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#f9f9f9;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#e74c3c;">' + sm.max + '</div><div>最大</div></div>';
|
||
html += '<div style="flex:1;text-align:center;padding:8px;background:#f9f9f9;border-radius:6px;"><div style="font-size:20px;font-weight:bold;color:#3498db;">' + sm.min + '</div><div>最小</div></div>';
|
||
html += '</div>';
|
||
|
||
// 尾数
|
||
html += '<h4 style="border-bottom:1px solid #eee;padding-bottom:5px;">🔢 尾数频率</h4>';
|
||
html += '<div style="display:flex;flex-wrap:wrap;gap:5px;">';
|
||
for (var i = 0; i < tn.all.length; i++) {
|
||
var t = tn.all[i];
|
||
html += '<div style="text-align:center;background:#f5f5f5;padding:5px 10px;border-radius:4px;"><div style="font-size:16px;font-weight:bold;">' + t.tail + '</div><div style="font-size:10px;color:#666;">' + t.count + ' (' + t.percent + '%)</div></div>';
|
||
}
|
||
html += '</div>';
|
||
|
||
html += '</div>';
|
||
$('#dash-result', layero).html(html);
|
||
}
|
||
}
|
||
};
|
||
return Controller;
|
||
});
|