feat(phase-4 to 10): add all remaining analysis features - color wave, zodiac, odd/even, big/small, sum, consecutive, tail numbers
This commit is contained in:
@@ -57,6 +57,35 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
||||
$(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');
|
||||
});
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
@@ -552,6 +581,317 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
||||
|
||||
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) {
|
||||
Controller.api['render' + analysisType.charAt(0).toUpperCase() + analysisType.slice(1)](ret.data, layero);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user