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}, {field: 'search_day', title: '每月日号', visible: false, searchable: true, operate: '=', style: 'width:80px;', extend: 'min="1" max="31" placeholder="1-31"'} ] ] }); 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-specialhotcold').on('click', '.btn-specialhotcold', function () { Controller.api.showSpecialHotColdDialog(); }); // 综合统计面板按钮事件 $(document).off('click', '.btn-dashboard').on('click', '.btn-dashboard', function () { Controller.api.showDashboard(); }); // 筛号器按钮事件 $(document).off('click', '.btn-numberfilter').on('click', '.btn-numberfilter', function () { Controller.api.showNumberFilterDialog(); }); // 预测号码按钮事件 $(document).off('click', '.btn-predict').on('click', '.btn-predict', function () { Controller.api.showPredictDialog(); }); // 正码关联预测按钮事件 $(document).off('click', '.btn-normal-relation').on('click', '.btn-normal-relation', function () { Controller.api.showNormalRelationDialog(); }); }, 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 = '
' + '' + value + ''; if (animal) { html += '
' + animal + '
'; } html += '
'; return html; } }, /** * 显示冷热分析弹窗 */ showHotColdDialog: function () { var html = '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + '
'; 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('
' + __('Loading') + '
'); $.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('
' + (ret.msg || __('Query failed')) + '
'); } }, error: function () { $('#hc-result', layero).html('
' + __('Query failed') + '
'); }, 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 = '

' + icon + ' ' + title + '

'; html += '
'; for (var i = 0; i < items.length; i++) { var item = items[i]; var color = getColor(item.num); var animal = getAnimal(item.num); html += '
' + '' + item.num + '' + '
' + (animal ? animal + '
' : '') + '' + item.count + ' (' + item.percent + '%)
' + '
'; } html += '
'; return html; }; var html = '
' + renderSection('热号 Top 10', data.hot, '🔥') + renderSection('冷号 Top 10', data.cold, '') + '
'; $('#hc-result', layero).html(html); }, /** * 显示走势图弹窗 */ showTrendDialog: function () { var html = '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + '
'; 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('
' + __('Loading') + '
'); $.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('
' + (ret.msg || __('Query failed')) + '
'); } }, error: function () { $('#trend-result', layero).html('
' + __('Query failed') + '
'); }, 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('
' + __('No data available') + '
'); 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('
'); 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 + '
'; for (var i = 0; i < params.length; i++) { tip += params[i].seriesName + ': ' + params[i].data + '
'; } 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 = '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + '
'; 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('
' + __('Loading') + '
'); $.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('
' + (ret.msg || __('Query failed')) + '
'); } }, error: function () { $('#missing-result', layero).html('
' + __('Query failed') + '
'); }, complete: function () { $btn.prop('disabled', false); } }); }, /** * 渲染遗漏号码结果 */ renderMissingNum: function (data, periods, layero) { if (!data || data.length === 0) { $('#missing-result', layero).html('
' + __('No missing numbers found') + '
'); return; } var container = $('
'); 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 = $('
'); var $ball = $('').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 = $('
').append($ball); if (animal) { $content.append($('
').text(animal)); } $content.append($('
').text( __('Missing') + ' ' + data[i].omit + ' ' + __('periods') )); $item.append($content); container.append($item); } $('#missing-result', layero).html('').append(container); }, /** * 特码冷热列表(每期相对于前N期的冷热状态) */ showSpecialHotColdDialog: function () { var html = '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + '
'; Layer.open({ type: 1, title: '特码冷热列表', area: ['650px', '600px'], content: html, shadeClose: true, success: function (layero, index) { $('#btn-shc-query', layero).on('click', function () { var lookback = parseInt($('#shc-lookback', layero).val()) || 30; Controller.api.querySpecialHotCold(lookback, layero); }); // 打开时自动查询 var lookback = parseInt($('#shc-lookback', layero).val()) || 30; Controller.api.querySpecialHotCold(lookback, layero); } }); }, querySpecialHotCold: function (lookback, layero) { var $btn = $('#btn-shc-query', layero); $btn.prop('disabled', true); $('#shc-result', layero).html('
' + __('Loading') + '
'); $.ajax({ url: 'history/specialHotColdAction', type: 'GET', data: {lookback: lookback}, dataType: 'json', success: function (ret) { if (ret.code == 1) { Controller.api.renderSpecialHotCold(ret.data, lookback, layero); } else { $('#shc-result', layero).html('
' + (ret.msg || __('Query failed')) + '
'); } }, error: function () { $('#shc-result', layero).html('
' + __('Query failed') + '
'); }, complete: function () { $btn.prop('disabled', false); } }); }, renderSpecialHotCold: function (data, lookback, layero) { var getColor = function (num) { return Controller.api.getColorByNum(num); }; var statusTag = function (status) { var map = { 'hot': '🔥 热号', 'cold': '❄ 冷号', 'normal': '➜ 温号', 'unknown': '数据不足' }; return map[status] || ''; }; // 新接口返回 {list: [...], current: {hot: [], cold: [], warm: []}} var listData = data.list || data; var current = data.current || null; if (!listData || listData.length === 0) { $('#shc-result', layero).html('
暂无数据
'); return; } var html = '
'; // 当前冷热号汇总区域 if (current && (current.hot.length > 0 || current.cold.length > 0)) { var renderNumBall = function (item) { var color = getColor(item.num); return '' + item.num + ''; }; html += '
'; html += '
当前热号
'; html += '
'; for (var h = 0; h < current.hot.length; h++) { html += renderNumBall(current.hot[h]); } if (current.hot.length === 0) { html += '暂无热号'; } html += '
'; html += '
'; html += '
当前冷号
'; html += '
'; for (var c = 0; c < current.cold.length; c++) { html += renderNumBall(current.cold[c]); } if (current.cold.length === 0) { html += '暂无冷号'; } html += '
'; html += '
'; } // 历史记录表格 html += '' + '' + '' + '' + '' + '' + '' + '' + ''; for (var i = 0; i < listData.length; i++) { var item = listData[i]; var rowClass = ''; if (item.status === 'hot') rowClass = 'style="background:#fff5f5;"'; else if (item.status === 'cold') rowClass = 'style="background:#f5f8ff;"'; html += '' + '' + '' + '' + '' + '' + '' + ''; } html += '
期号特码冷热次数平均排名
' + item.expect + '' + '' + item.specialNum + '' + '' + statusTag(item.status) + '' + item.count + '' + item.avgCount + '' + item.rank + '
'; $('#shc-result', layero).html(html); }, /** * 筛号器弹窗 */ showNumberFilterDialog: function () { var html = '' + '
' + '
' + '
' + ' ' + ' ' + '
' + ' ' + '
' + '
' + '
' + ' ' + '
' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + '
' + '
' + '
' + ' ' + '
' + ' ' + ' ' + ' ' + '
' + '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + ' ' + ' ' + '
' + '
' + '
' + '
'; Layer.open({ type: 1, title: '筛号器', area: ['700px', '600px'], content: html, shadeClose: true, success: function (layero, index) { // 手动屏蔽的号码列表 var blockedNums = []; // 渲染号码网格 Controller.api.renderNumberFilterGrid(layero); // 号码点击屏蔽 $('#nf-numbers', layero).on('click', '.nf-number', function () { var num = parseInt($(this).data('num')); var idx = blockedNums.indexOf(num); if (idx === -1) { blockedNums.push(num); } else { blockedNums.splice(idx, 1); } Controller.api.applyNumberFilters(layero, blockedNums); }); // 新增尾号 $('.btn-nf-add-tail', layero).on('click', function () { Controller.api.addTailRow(layero, 0); Controller.api.applyNumberFilters(layero, blockedNums); }); // 尾号输入 & 删除事件委托 $('#nf-tail-list', layero).on('input change', '.nf-tail-select', function () { Controller.api.applyNumberFilters(layero, blockedNums); }); $('#nf-tail-list', layero).on('click', '.nf-tail-del', function () { $(this).closest('.nf-tail-row').remove(); Controller.api.applyNumberFilters(layero, blockedNums); }); // 生肖按钮点击 $('.nf-zodiac', layero).on('click', function () { var $btn = $(this); $btn.toggleClass('btn-default').toggleClass('btn-gray'); Controller.api.applyNumberFilters(layero, blockedNums); }); // 波色按钮点击 $('.nf-color-btn', layero).on('click', function () { var $btn = $(this); $btn.toggleClass('btn-default').toggleClass('btn-gray'); Controller.api.applyNumberFilters(layero, blockedNums); }); // 单双按钮点击 $('.nf-parity', layero).on('click', function () { var $btn = $(this); $btn.toggleClass('btn-default').toggleClass('btn-gray'); Controller.api.applyNumberFilters(layero, blockedNums); }); // 新增区间 $('.btn-nf-add-range', layero).on('click', function () { Controller.api.addRangeRow(layero, 1, 49, 'include'); Controller.api.applyNumberFilters(layero, blockedNums); }); // 区间输入 & 删除事件委托 $('#nf-range-list', layero).on('input change', '.nf-range-min, .nf-range-max', function () { Controller.api.applyNumberFilters(layero, blockedNums); }); $('#nf-range-list', layero).on('click', '.nf-range-mode', function () { var $btn = $(this); if ($btn.hasClass('btn-info')) { $btn.removeClass('btn-info').addClass('btn-default'); } else { $btn.removeClass('btn-default').addClass('btn-info'); } Controller.api.applyNumberFilters(layero, blockedNums); }); $('#nf-range-list', layero).on('click', '.nf-range-del', function () { $(this).closest('.nf-range-row').remove(); Controller.api.applyNumberFilters(layero, blockedNums); }); // 重置按钮 $('.btn-nf-reset', layero).on('click', function () { blockedNums = []; $('#nf-tail-list', layero).html(''); $('.nf-zodiac', layero).removeClass('btn-gray').addClass('btn-default'); $('.nf-color-btn', layero).removeClass('btn-gray').addClass('btn-default'); $('.nf-parity', layero).removeClass('btn-gray').addClass('btn-default'); $('#nf-range-list', layero).html(''); Controller.api.applyNumberFilters(layero, blockedNums); }); } }); }, /** * 新增一行尾号筛选 */ addTailRow: function (layero, value) { var rowId = 'nf-tail-' + Date.now() + Math.random().toString(36).substr(2, 5); var opts = ''; for (var t = 0; t <= 9; t++) { opts += ''; } var html = '
' + ' ' + ' ' + '
'; $('#nf-tail-list', layero).append(html); }, /** * 新增一行区间筛选 */ addRangeRow: function (layero, min, max, mode) { var rowId = 'nf-range-' + Date.now(); var isInclude = mode === 'include'; var html = '
' + ' ' + (isInclude ? '在区间' : '排除') + '' + ' ' + ' ' + ' ' + ' ' + ' ' + '
'; $('#nf-range-list', layero).append(html); }, /** * 渲染筛号器号码网格 */ renderNumberFilterGrid: function (layero) { var colorMap = Controller.api.colorMap; var html = ''; for (var num = 1; num <= 49; num++) { var colorHex = Controller.api.getColorByNum(num); var colorRaw = colorMap[num] || ''; var animal = Controller.api.getAnimalByNum(num); var colorLabel = ''; if (colorRaw.indexOf('红') !== -1) colorLabel = '红'; else if (colorRaw.indexOf('蓝') !== -1) colorLabel = '蓝'; else if (colorRaw.indexOf('绿') !== -1) colorLabel = '绿'; html += '
' + '' + num + '' + '
' + animal + '
' + '
'; } $('#nf-numbers', layero).html(html); }, /** * 应用筛号器过滤条件 * @param {object} layero Layer弹窗对象 * @param {Array} blockedNums 手动屏蔽的号码列表 */ applyNumberFilters: function (layero, blockedNums) { blockedNums = blockedNums || []; // 收集所有选中的尾号 var excludedTails = []; $('.nf-tail-select', layero).each(function () { var val = $(this).val(); if (val !== '' && excludedTails.indexOf(parseInt(val)) === -1) { excludedTails.push(parseInt(val)); } }); // 收集被点击(置灰)的生肖 var excludedZodiacs = []; $('.nf-zodiac.btn-gray', layero).each(function () { excludedZodiacs.push($(this).data('zodiac')); }); // 收集被点击(置灰)的波色 var excludedColors = []; $('.nf-color-btn.btn-gray', layero).each(function () { excludedColors.push($(this).data('color')); }); // 收集被点击(置灰)的单双 var excludedParities = []; $('.nf-parity.btn-gray', layero).each(function () { excludedParities.push($(this).data('parity')); }); // 收集所有区间 var ranges = []; $('.nf-range-row', layero).each(function () { var $row = $(this); var min = parseInt($row.find('.nf-range-min').val()) || 1; var max = parseInt($row.find('.nf-range-max').val()) || 49; var mode = $row.find('.nf-range-mode').hasClass('btn-info') ? 'include' : 'exclude'; ranges.push({min: min, max: max, mode: mode}); }); $('.nf-number', layero).each(function () { var $num = $(this); var num = parseInt($num.data('num')); var tail = $num.data('tail'); var animal = $num.data('animal'); var color = $num.data('color'); var parity = $num.data('parity'); var hidden = false; // 尾号筛选:选中多个尾号,任一命中即屏蔽 if (excludedTails.length > 0 && excludedTails.indexOf(tail) !== -1) { hidden = true; } // 单双筛选:选中单或双,匹配则屏蔽 if (excludedParities.indexOf(parity) !== -1) { hidden = true; } // 区间筛选:在区间=白名单(OR)、排除区间=黑名单(OR) if (!hidden) { var includeRanges = []; var excludeRanges = []; for (var r = 0; r < ranges.length; r++) { if (ranges[r].mode === 'include') { includeRanges.push(ranges[r]); } else { excludeRanges.push(ranges[r]); } } // 黑名单:任一排除区间命中则屏蔽 for (var r = 0; r < excludeRanges.length; r++) { if (num >= excludeRanges[r].min && num <= excludeRanges[r].max) { hidden = true; break; } } // 白名单:有在区间规则时,号码不在任一区间则屏蔽 if (!hidden && includeRanges.length > 0) { var inAnyInclude = false; for (var r = 0; r < includeRanges.length; r++) { if (num >= includeRanges[r].min && num <= includeRanges[r].max) { inAnyInclude = true; break; } } if (!inAnyInclude) { hidden = true; } } } // 排除的生肖 if (excludedZodiacs.indexOf(animal) !== -1) { hidden = true; } // 排除的波色 if (excludedColors.indexOf(color) !== -1) { hidden = true; } // 手动屏蔽的号码 if (blockedNums.indexOf(num) !== -1) { hidden = true; } if (hidden) { $num.css('opacity', '0.25').css('filter', 'grayscale(100%)'); } else { $num.css('opacity', '1').css('filter', 'none'); } }); }, 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 = '
'; if (hasType) { html += '
' + ' ' + ' ' + ' ' + '
'; } html += '
' + ' ' + ' ' + ' ' + '
' + '
' + '
'; 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('
' + __('Loading') + '
'); $.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('
渲染方法不存在: ' + renderFn + '
'); } } else { $('#analysis-result-' + analysisType, layero).html('
' + (ret.msg || __('Query failed')) + '
'); } }, error: function () { $('#analysis-result-' + analysisType, layero).html('
' + __('Query failed') + '
'); }, complete: function () { $btn.prop('disabled', false); } }); }, renderColorWaveAnalysis: function (data, layero) { var html = '
'; 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 += '
' + '
' + item.value + '
' + '
' + item.label + '
' + '
' + item.pct + '%
' + '
'; } html += '
总计: ' + data.total + ' 个号码
'; $('#analysis-result-colorWave', layero).html(html); }, renderZodiacAnalysis: function (data, layero) { var html = '
'; for (var i = 0; i < data.list.length; i++) { var item = data.list[i]; html += '
' + '
' + item.animal + '
' + '
' + item.count + ' (' + item.percent + '%)
' + '
'; } html += '
'; $('#analysis-result-zodiac', layero).html(html); }, renderOddEvenAnalysis: function (data, layero) { var html = '
'; html += '
' + '
' + data.odd + '
' + '
奇数
' + '
' + data.odd_pct + '%
'; html += '
' + '
' + data.even + '
' + '
偶数
' + '
' + data.even_pct + '%
'; html += '
'; $('#analysis-result-oddEven', layero).html(html); }, renderBigSmallAnalysis: function (data, layero) { var html = '
'; html += '
' + '
' + data.big + '
' + '
大数(25-49)
' + '
' + data.big_pct + '%
'; html += '
' + '
' + data.small + '
' + '
小数(1-24)
' + '
' + data.small_pct + '%
'; html += '
'; $('#analysis-result-bigSmall', layero).html(html); }, renderTailNumbers: function (data, layero) { var html = '
'; for (var i = 0; i < data.all.length; i++) { var item = data.all[i]; html += '
' + '
' + item.tail + '
' + '
' + item.count + ' (' + item.percent + '%)
'; } html += '
'; $('#analysis-result-tailNumbers', layero).html(html); }, /** * 和值分析弹窗 */ showSumDialog: function () { var html = '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + '
'; 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('
' + __('Loading') + '
'); $.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('
' + (ret.msg || __('Query failed')) + '
'); } }, error: function () { $('#sum-result', layero).html('
' + __('Query failed') + '
'); }, complete: function () { $btn.prop('disabled', false); } }); }, renderSum: function (data, layero) { var html = '
'; html += '
' + data.avg + '
平均和值
'; html += '
' + data.max + '
最大和值
'; html += '
' + data.min + '
最小和值
'; html += '
'; $('#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 = '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + '
'; 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('
' + __('Loading') + '
'); $.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('
' + (ret.msg || __('Query failed')) + '
'); } }, error: function () { $('#consecutive-result', layero).html('
' + __('Query failed') + '
'); }, complete: function () { $btn.prop('disabled', false); } }); }, renderConsecutive: function (data, layero) { var html = '
'; html += '

连号对

'; html += '
'; var pairs = data.pairs; if (pairs && Object.keys(pairs).length > 0) { for (var pair in pairs) { html += '
' + pair + ' ×' + pairs[pair] + '
'; } } else { html += '
暂无连号数据
'; } html += '

三连号

'; html += '
'; var triples = data.triples; if (triples && Object.keys(triples).length > 0) { for (var triple in triples) { html += '
' + triple + ' ×' + triples[triple] + '
'; } } else { html += '
暂无三连号数据
'; } html += '
'; $('#consecutive-result', layero).html(html); }, /** * 综合统计面板 */ showDashboard: function () { var html = '
' + '
' + ' ' + ' ' + ' ' + '
' + '
' + '
'; 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('
' + __('Loading') + '
'); $.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('
' + (ret.msg || __('Query failed')) + '
'); } }, error: function () { $('#dash-result', layero).html('
' + __('Query failed') + '
'); }, 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 '
' + item.num + '
' + item.count + '
'; }; var html = '
'; // 冷热号码 html += '

🔥❄️ 冷热号码

'; html += '
热号 Top5
'; for (var i = 0; i < 5; i++) html += ballHtml(hc.hot[i]); html += '
冷号 Top5
'; for (var i = 0; i < 5; i++) html += ballHtml(hc.cold[i]); html += '
'; // 波色分析 html += '

🎨 波色比例

'; html += '
'; html += '
' + cw.red + '
红波 ' + cw.red_pct + '%
'; html += '
' + cw.blue + '
蓝波 ' + cw.blue_pct + '%
'; html += '
' + cw.green + '
绿波 ' + cw.green_pct + '%
'; 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 += '
' + oe.odd + ' (' + oe.odd_pct + '%)
奇数
'; html += '
' + oe.even + ' (' + oe.even_pct + '%)
偶数
'; html += '
'; // 大小分析 html += '

📊 大小分析

'; html += '
'; html += '
' + bs.big + ' (' + bs.big_pct + '%)
大数(25-49)
'; html += '
' + bs.small + ' (' + bs.small_pct + '%)
小数(1-24)
'; 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-result', layero).html(html); }, /** * 预测号码弹窗 */ showPredictDialog: function () { var html = '
' + '
' + '
预测算法说明
' + '
' + ' V1版本:基于转移概率分析(区域、生肖、尾号、首号、波色转移 + 冷热系数)
' + ' V2版本:基于统计回归分析(遗漏回归、频率回归、区域平衡、波色平衡等)+ 历史回测验证
' + ' V3版本(推荐):多维度综合预测,新增转移概率(马尔可夫链)、单双规律、大小规律、走势方向分析' + '
' + '
' + '
' + ' ' + ' ' + ' ' + ' ' + '
' + '
' + ' ' + ' ' + ' 留空则预测下一期' + '
' + '
' + ' ' + ' ' + ' 建议200期以上' + '
' + // V3权重配置 '
' + ' ' + '
' + '
遗漏回归:
' + '
频率回归:
' + '
转移概率:
' + '
单双平衡:
' + '
大小平衡:
' + '
走势方向:
' + '
区域平衡:
' + '
波色平衡:
' + '
' + '
' + // V2权重配置 '' + // V1权重配置 '' + '
' + ' ' + '
' + '
' + '
'; Layer.open({ type: 1, title: '🎯 智能预测号码', area: ['850px', '750px'], content: html, shadeClose: true, success: function (layero, index) { // 切换版本时显示对应权重配置 $('input[name="predict-version"]', layero).on('change', function () { var val = $(this).val(); $('#predict-v3-weights', layero).hide(); $('#predict-v2-weights', layero).hide(); $('#predict-v1-weights', layero).hide(); if (val === 'v3') { $('#predict-v3-weights', layero).show(); $('#predict-periods', layero).val(200); } else if (val === 'v2') { $('#predict-v2-weights', layero).show(); $('#predict-periods', layero).val(200); } else { $('#predict-v1-weights', layero).show(); $('#predict-periods', layero).val(100); } }); $('#btn-predict-query', layero).on('click', function () { Controller.api.queryPredict(layero); }); } }); }, /** * 查询预测结果 */ queryPredict: function (layero) { var $btn = $('#btn-predict-query', layero); $btn.prop('disabled', true); $('#predict-result', layero).html('
正在分析历史数据...
'); var version = $('input[name="predict-version"]:checked', layero).val(); var periods = parseInt($('#predict-periods', layero).val()) || 200; var targetExpect = $('#predict-target', layero).val().trim(); var weights = {}; // 根据版本获取权重 if (version === 'v3') { $('.predict-weight-v3', layero).each(function () { var key = $(this).data('key'); var val = parseFloat($(this).val()) || 0; weights[key] = val; }); } else if (version === 'v2') { $('.predict-weight-v2', layero).each(function () { var key = $(this).data('key'); var val = parseFloat($(this).val()) || 0; weights[key] = val; }); } else { $('.predict-weight', layero).each(function () { var key = $(this).data('key'); var val = parseFloat($(this).val()) || 0; weights[key] = val; }); } // 根据版本选择URL var url = 'history/predict'; if (version === 'v3') { url = 'history/predictV3'; } else if (version === 'v2') { url = 'history/predictV2'; } $.ajax({ url: url, type: 'GET', data: { periods: periods, weights: JSON.stringify(weights), target_expect: targetExpect }, dataType: 'json', success: function (ret) { if (ret.code == 1) { Controller.api.renderPredict(ret.data, layero, version); } else { $('#predict-result', layero).html('
' + (ret.msg || '预测失败') + '
'); } }, error: function () { $('#predict-result', layero).html('
预测请求失败
'); }, complete: function () { $btn.prop('disabled', false); } }); }, /** * 渲染预测结果 */ renderPredict: function (data, layero, version) { var predictions = data.predictions || []; var analysis = data.analysis || {}; var hitInfo = data.hit_info || null; var actualResult = data.actual_result || null; var backtest = data.backtest || null; var confidence = data.confidence || null; if (predictions.length === 0) { $('#predict-result', layero).html('
暂无预测结果
'); return; } // 上期特码信息 var lastSpecial = analysis.last_special || 0; var lastExpect = analysis.last_expect || ''; var lastColor = Controller.api.getColorByNum(lastSpecial); var lastAnimal = Controller.api.getAnimalByNum(lastSpecial); // 版本名称映射 var versionNames = { 'v1': 'V1(转移概率)', 'v2': 'V2(统计回归)', 'v3': 'V3(多维度综合)' }; var html = '
'; // 基准期号标题 html += '
基于期号 ' + lastExpect + '(特码 ' + lastSpecial + ')进行预测 | 算法版本: ' + versionNames[version] + '
'; // 置信度评估展示(V2和V3版本) if (confidence && (version === 'v2' || version === 'v3')) { html += '
'; html += '
预测置信度评估
'; // 数据警告提示(数据不足时显示) if (confidence.data_warning) { html += '
' + confidence.data_warning + '
'; } html += '
'; html += '
' + confidence.overall_confidence + '%
整体置信度
'; // 各排名置信度(使用得分集中度维度) if (confidence.confidence_scores && confidence.confidence_scores.length > 0) { html += '
'; for (var i = 0; i < confidence.confidence_scores.length; i++) { var cs = confidence.confidence_scores[i]; // 阈值定义:>=70%高(绿)、50-70%中(橙)、<50%低(红) var confLevel = cs.confidence >= 70 ? '高' : (cs.confidence >= 50 ? '中' : '低'); var confColor = cs.confidence >= 70 ? '#4caf50' : (cs.confidence >= 50 ? '#ff9800' : '#f44336'); html += '
'; html += '
' + cs.confidence + '%
'; html += '
#' + cs.rank + '
'; html += '
'; } html += '
'; } html += '
'; } // 回测验证结果(V2和V3版本) if (backtest && (version === 'v2' || version === 'v3')) { html += '
'; html += '
历史回测验证(最近' + backtest.total_tests + '期)
'; // 回测数据警告提示 if (backtest.data_warning) { html += '
' + backtest.data_warning + '
'; } html += '
'; html += '
' + backtest.hit_rate + '%
命中率(Top5)
'; html += '
' + backtest.total_hits + '/' + backtest.total_tests + '
命中次数
'; html += '
' + (backtest.avg_rank || '—') + '
平均排名
'; // 新增指标:NDCG@5 和 MRR(百分比展示) if (backtest.ndcg_5 !== undefined) { html += '
' + (backtest.ndcg_5 * 100).toFixed(1) + '%
NDCG@5
'; } if (backtest.mrr !== undefined) { html += '
' + (backtest.mrr * 100).toFixed(1) + '%
MRR
'; } // 转移概率阶数显示(来自analysis.transition_order字段) if (analysis && analysis.transition_order !== undefined) { html += '
' + analysis.transition_order + '阶
转移概率
'; } html += '
'; // 命中分布柱状图(使用rank_1..rank_5键名) if (backtest.hit_distribution && Object.keys(backtest.hit_distribution).length > 0) { var distribution = backtest.hit_distribution; var maxHit = 0; // 找最大值用于计算柱状图高度比例 for (var r = 1; r <= 5; r++) { var key = 'rank_' + r; if (distribution[key] > maxHit) { maxHit = distribution[key]; } } html += '
命中分布(各排名命中次数):
'; html += '
'; for (var r = 1; r <= 5; r++) { var key = 'rank_' + r; var hitCount = distribution[key] || 0; var barHeight = maxHit > 0 ? (hitCount / maxHit * 45) : 0; var barColor = hitCount > 0 ? '#4caf50' : '#e0e0e0'; html += '
'; html += '
'; html += '
#' + r + '
'; html += '
' + hitCount + '
'; html += '
'; } html += '
'; } // 回测详情 if (backtest.details && backtest.details.length > 0) { html += '
最近' + backtest.details.length + '期验证详情:
'; html += '
'; for (var i = 0; i < backtest.details.length; i++) { var bd = backtest.details[i]; var hitTag = bd.hit ? '' : ''; html += '
期号' + bd.expect + ': 实际' + bd.actual + ' ' + hitTag + ' 预测[' + bd.predictions.join(',') + ']
'; } html += '
'; } html += '
'; } // V3版本特有的分析信息 if (version === 'v3' && analysis) { html += '
'; html += '
V3多维度分析
'; // 单双统计 if (analysis.oddeven_stats) { var oe = analysis.oddeven_stats; html += '
单双规律: 单号' + oe.odd_pct + '% / 双号' + oe.even_pct + '%'; if (oe.recent_streak >= 2) { html += ' | 近期连续' + (oe.recent_type === 'odd' ? '单号' : '双号') + oe.recent_streak + '期'; html += '(平均连续' + (oe.recent_type === 'odd' ? oe.avg_odd_streak : oe.avg_even_streak) + '期)'; } html += '
'; } // 大小统计 if (analysis.bigsmall_stats) { var bs = analysis.bigsmall_stats; html += '
大小规律: 大号' + bs.big_pct + '% / 小号' + bs.small_pct + '%'; if (bs.recent_streak >= 2) { html += ' | 近期连续' + (bs.recent_type === 'big' ? '大号' : '小号') + bs.recent_streak + '期'; html += '(平均连续' + (bs.recent_type === 'big' ? bs.avg_big_streak : bs.avg_small_streak) + '期)'; } html += '
'; } // 走势方向 if (analysis.trend_direction) { var td = analysis.trend_direction; var trendNames = { 'ascending': '上升(号码减小)', 'descending': '下降(号码增大)', 'jump': '跳跃震荡' }; html += '
走势方向: ' + trendNames[td.trend_type]; html += ' | 强度' + (td.trend_strength * 100).toFixed(0) + '% | 平均变化' + td.avg_change + '
'; } // 上期属性 html += '
上期属性: 区域[' + (analysis.last_zone || '') + '] 尾数[' + (analysis.last_tail || '') + '] 首号[' + (analysis.last_head || '') + ']
'; html += '
'; } // 遗漏统计信息(V2和V3版本) if (analysis.omit_stats && (version === 'v2' || version === 'v3')) { html += '
'; html += '遗漏值统计: 平均遗漏 ' + (analysis.omit_stats.avg || 0).toFixed(1) + ' 期 | 最大遗漏 ' + (analysis.omit_stats.max || 0) + ' 期 | 期望频率 ' + analysis.expected_freq + ''; html += '
'; } // 命中结果(验证模式下显示) if (hitInfo && actualResult) { var hitBgColor = hitInfo.hit ? '#d4edda' : '#f8d7da'; var hitBorderColor = hitInfo.hit ? '#28a745' : '#dc3545'; var hitTitleColor = hitInfo.hit ? '#155724' : '#721c24'; var actualColorHex = Controller.api.getColorByNum(hitInfo.actual_num); html += '
'; html += '
'; if (hitInfo.hit) { html += ' 预测命中!排名第 ' + hitInfo.rank + ' 位'; } else { html += ' 未命中(实际号码不在预测Top' + predictions.length + '中)'; } html += '
'; html += '
'; html += '
期号 ' + hitInfo.actual_expect + ' 实际开奖:
'; html += '' + hitInfo.actual_num + ''; html += '
' + hitInfo.actual_animal + ' / ' + hitInfo.actual_color + '
'; html += '
'; } // 预测号码列表 var topCount = predictions.length; html += '
'; html += '
预测推荐号码(Top ' + topCount + ')
'; html += '
'; for (var i = 0; i < predictions.length; i++) { var p = predictions[i]; var colorHex = Controller.api.getColorByNum(p.num); var animal = Controller.api.getAnimalByNum(p.num); // 验证模式下,命中号码高亮 var isHit = hitInfo && hitInfo.hit && p.num === hitInfo.actual_num; var cardBg = isHit ? '#fffacd' : '#fff'; var cardBorder = isHit ? '2px solid #f39c12' : 'none'; var rankBadge = i < 3 ? '' + (i + 1) + '' : ''; // 根据版本显示不同的详情信息 var detailInfo = ''; if (p.detail) { if (version === 'v3') { // V3版本显示更多维度信息 var omitInfo = p.detail.omit || 0; var transScore = p.detail.trans_score || 0; var oddevenScore = p.detail.oddeven_score || 0; var bigsmallScore = p.detail.bigsmall_score || 0; var trendScore = p.detail.trend_score || 0; detailInfo = '
'; detailInfo += '遗漏:' + omitInfo + '期 | '; detailInfo += '转移:' + transScore + ' | '; detailInfo += (p.detail.is_odd ? '单' : '双') + ':' + oddevenScore + ' | '; detailInfo += (p.detail.is_big ? '大' : '小') + ':' + bigsmallScore; detailInfo += '
'; } else if (version === 'v2') { var omitInfo = p.detail.omit || 0; detailInfo = '
遗漏:' + omitInfo + '期
'; } } html += '
' + rankBadge; html += '' + p.num + ''; html += '
' + animal + '
'; html += '
得分:' + p.score + '
'; // 显示置信度(V3版本) if (version === 'v3' && confidence && confidence.confidence_scores) { var csForNum = confidence.confidence_scores.find(function(c) { return c.num === p.num; }); if (csForNum) { // 阈值定义:>=70%高(绿)、50-70%中(橙)、<50%低(红) var confLevel = csForNum.confidence >= 70 ? '高' : (csForNum.confidence >= 50 ? '中' : '低'); var confColor = csForNum.confidence >= 70 ? '#4caf50' : (csForNum.confidence >= 50 ? '#ff9800' : '#f44336'); html += '
置信度:' + confLevel + ' (' + csForNum.confidence + '%)
'; } } html += detailInfo; html += '
'; } html += '
'; html += '
'; $('#predict-result', layero).html(html); }, /** * 显示正码关联预测弹窗(修正版) * 核心规律:上期正码 → 当期特码 */ showNormalRelationDialog: function () { var html = '
' + '
' + '
正码关联预测算法(修正版)
' + '
' + ' 核心逻辑:用上期正码(num1-6)预测当期特码(num7)
' + ' 1. 覆盖区间规律(91.44%):当期特码在上期正码覆盖的细区间内
' + ' 2. 特码区间转移(77.54%):基于上期特码区间预测当期特码大区间
' + ' 3. 双波色预测(69.52%):当期特码波色在上期正码前2种主导波色内
' + ' 4. 正码±3距离(59.36%):当期特码与上期正码某号码距离≤3
' + ' 5. 尾数±2(50%):上期正码和值尾数与当期特码尾数差≤2
' + ' 6. 平均值±10(41.98%):当期特码在上期正码平均值±10范围' + '
' + '
' + '
' + ' ' + ' ' + ' ' + ' ' + ' ' + '
' + '
' + '
'; Layer.open({ type: 1, title: '正码关联预测(上期正码→当期特码)', area: ['900px', '750px'], content: html, shadeClose: true, success: function (layero, index) { $('#btn-nr-query', layero).on('click', function () { Controller.api.queryNormalRelation(layero); }); // 自动执行一次查询 Controller.api.queryNormalRelation(layero); } }); }, /** * 查询正码关联预测 */ queryNormalRelation: function (layero) { var $btn = $('#btn-nr-query', layero); $btn.prop('disabled', true); $('#nr-result', layero).html('
正在分析...
'); var periods = parseInt($('#nr-periods', layero).val()) || 100; var targetExpect = $('#nr-target', layero).val().trim(); $.ajax({ url: 'history/predictByNormalRelation', type: 'GET', data: { periods: periods, target_expect: targetExpect }, dataType: 'json', success: function (ret) { if (ret.code == 1) { Controller.api.renderNormalRelation(ret.data, layero); } else { $('#nr-result', layero).html('
' + (ret.msg || '查询失败') + '
'); } }, error: function () { $('#nr-result', layero).html('
查询失败
'); }, complete: function () { $btn.prop('disabled', false); } }); }, /** * 渲染正码关联预测结果 */ renderNormalRelation: function (data, layero) { if (!data || !data.predictions || data.predictions.length === 0) { $('#nr-result', layero).html('
无预测结果
'); return; } var analysis = data.analysis || {}; var predictions = data.predictions; var hitInfo = data.hit_info; var backtest = data.backtest; var html = ''; // 分析信息 html += '
'; html += '
上期开奖信息(预测基准)
'; html += '
'; html += '期号:' + analysis.last_expect + ' | '; html += '正码:' + analysis.last_normals.join(', ') + ' | '; html += '特码:' + analysis.last_special + '
'; html += '正码范围:' + analysis.normal_min + ' ~ ' + analysis.normal_max + ' | '; html += '平均值:' + analysis.normal_avg + ' | '; html += '和值:' + analysis.normal_sum + '
'; html += '正码波色:' + (analysis.top2_colors || analysis.normal_colors || []).join('/') + ' | '; html += '覆盖区间:' + (analysis.normal_fine_zones || analysis.normal_zones || []).map(function(z) { return ['1-10','11-20','21-30','31-40','41-49'][z]; }).join(','); html += '
'; // 预测号码展示 html += '
'; html += '
推荐号码(Top 15)
'; html += '
'; for (var i = 0; i < predictions.length; i++) { var p = predictions[i]; var colorHex = Controller.api.getColorByNum(p.num); var animal = Controller.api.animalMap[p.num] || ''; var bgColor = '#fff'; var borderColor = '1px solid #ddd'; if (i < 5) { bgColor = '#fff8e1'; borderColor = '2px solid #ffc107'; } html += '
'; html += '' + p.num + ''; html += '
' + animal + '
'; html += '
得分:' + p.score + '
'; html += '
'; html += (p.color_in_top2 || p.color_match) ? '✓波色 ' : ''; html += '距离' + (p.min_distance || 0); html += '
'; html += '
'; } html += '
'; // 规律命中情况(如果有回测) if (backtest) { html += '
'; html += '
回测验证(最近' + backtest.periods + '期)
'; html += '
'; html += '命中率(Top15内):' + backtest.hit_rate + '% (' + backtest.hits + '/' + backtest.periods + ')
'; html += '平均排名:' + backtest.avg_rank + ' / 49
'; html += '注:命中率越高越好,平均排名越低越好'; html += '
'; // 显示前50期命中详情表格 if (backtest.details && backtest.details.length > 0) { html += '
'; html += ''; html += ''; html += ''; for (var d = 0; d < backtest.details.length; d++) { var det = backtest.details[d]; var hitBadge = det.hit ? '' : ''; var rankColor = det.rank <= 5 ? '#2e7d32' : (det.rank <= 15 ? '#ff9800' : '#c62828'); html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; } html += '
期号特码排名命中
' + det.expect + '' + det.actual + '' + det.rank + '' + hitBadge + '
'; html += '
'; } html += '
'; } // 实际命中情况(如果有目标期号) if (hitInfo) { var hitBg = hitInfo.hit ? '#e8f5e9' : '#ffebee'; var hitColor = hitInfo.hit ? '#2e7d32' : '#c62828'; html += '
'; html += '
'; html += hitInfo.hit ? '✓ 命中!排名:' + hitInfo.rank_in_top + ' / 15' : '✗ 未命中,排名:' + hitInfo.rank_in_all + ' / 49'; html += '
'; html += '
实际特码:' + hitInfo.actual_num + ' (' + hitInfo.actual_color + '/' + hitInfo.actual_animal + ') 期号:' + hitInfo.actual_expect + '
'; html += '
'; } // 规律说明表 if (analysis.rules) { html += '
'; html += '
规律命中率表
'; html += ''; html += ''; for (var r = 0; r < analysis.rules.length; r++) { var rule = analysis.rules[r]; html += ''; } html += '
规律名称命中率说明
' + rule.name + '' + rule.rate + '' + rule.desc + '
'; } $('#nr-result', layero).html(html); } } }; return Controller; });