Files
Chan/web/static/js/app/macd_ui.js
T
jackyu66gitandCursor 90499533fb fix(web): 分析/自动刷新后保留 K 线视窗位置
拆分手动分析与自动刷新拉数路径;全量重建用 logical 优先恢复视窗,
增量 recent 用 scroll+barDelta;避免 barSpacing 重锚与重复冻结导致往右跳。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-25 23:38:20 +08:00

270 lines
8.9 KiB
JavaScript

/* macd_ui.js */
function showMacdConfig() {
$.get('/api/macd_config', function(data) {
$('#macdFastPeriod').val(data.fast);
$('#macdSlowPeriod').val(data.slow);
$('#macdSignalPeriod').val(data.signal);
$('#macdConfigModal').css('display', 'flex');
});
}
function hideMacdConfig() {
$('#macdConfigModal').css('display', 'none');
}
function resetMacdConfig() {
$('#macdFastPeriod').val(24);
$('#macdSlowPeriod').val(52);
$('#macdSignalPeriod').val(9);
}
function saveMacdConfig() {
const fast = parseInt($('#macdFastPeriod').val());
const slow = parseInt($('#macdSlowPeriod').val());
const signal = parseInt($('#macdSignalPeriod').val());
if (fast >= slow) {
alert('快线周期必须小于慢线周期');
return;
}
if (fast < 2 || slow < 2 || signal < 2) {
alert('周期值必须大于等于2');
return;
}
$.ajax({
url: '/api/macd_config',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({ fast: fast, slow: slow, signal: signal }),
success: function() {
hideMacdConfig();
analyzeChart({ reason: 'macd-config-saved' });
},
error: function() {
alert('保存MACD参数失败');
}
});
}
$(document).on('click', '#macdConfigModal', function(e) {
if (e.target === this) hideMacdConfig();
});
// 添加原始K线复选框变更事件
$('#showOriginalKline').change(function() {
updateChartDisplay();
});
// 添加K线形态下拉变更事件(同步隐藏的原始K线开关并重绘)
$('#klineType').change(function() {
const type = $(this).val();
$('#showOriginalKline').prop('checked', type === 'candlestick');
updateChartDisplay();
});
// 添加笔复选框变更事件
$('#showMainBi').change(function() {
updateChartDisplay();
});
// 添加线段复选框变更事件
$('#showMainSeg').change(function() {
updateChartDisplay();
});
// 添加中枢复选框变更事件
$('#showMainZs').change(function() {
updateChartDisplay();
});
// 添加主周期BI中枢复选框变更事件(委托绑定,避免DOM更新后失效)
console.log('初始化BI中枢事件绑定');
$(document).on('change', '#showMainBiZs', function() {
console.log('主BI中枢切换为:', $('#showMainBiZs').is(':checked'));
updateChartDisplay();
});
// 结构价值区复选框变更事件
$(document).on('change', '#showMainStructureZone', function() {
const on = $('#showMainStructureZone').is(':checked');
console.log('结构区切换为:', on);
// 勾选后才向服务器请求多周期结构区数据;结构区叠层只在全量 init 里绘制,必须 incremental:false
if (on) {
analyzeChart({ incremental: false, reason: 'structure-zone-on' });
} else {
updateChartDisplay();
}
});
// 区间/阶段/时间/VP:与缠论笔开关一样,本地重绘
$(document).on(
'change',
'#showMainWrRange, #showMainWrPhases, #showMainWrEvents, #showMainWrVP,' +
'#showElementWrRange, #showElementWrPhases, #showElementWrEvents, #showElementWrVP,' +
'#showSubSubWrRange, #showSubSubWrPhases, #showSubSubWrEvents, #showSubSubWrVP',
function() {
updateChartDisplay();
}
);
// 添加趋势显示复选框变更事件(主/元素),变更后刷新主图
$('#showMainTrend').change(function() {
updateChartDisplay();
});
$('#showElementTrend').change(function() {
updateChartDisplay();
});
// 添加买卖点复选框变更事件
$('#showElementBi').change(function() {
updateChartDisplay();
});
// 添加线段复选框变更事件
$('#showElementSeg').change(function() {
updateChartDisplay();
});
// 添加中枢复选框变更事件
$('#showElementZs').change(function() {
updateChartDisplay();
});
// 添加次周期BI中枢复选框变更事件(委托绑定,避免DOM更新后失效)
$(document).on('change', '#showElementBiZs', function() {
console.log('次BI中枢切换为:', $('#showElementBiZs').is(':checked'));
updateChartDisplay();
});
// 次次周期显示开关变更事件
$('#showSubSubBi, #showSubSubSeg, #showSubSubZs, #showSubSubBiZs, #showSubSubKlcFxType, #showSubSubTrend, #showSubSubBsp').change(function() {
updateChartDisplay();
});
$(document).on('change', '#toggleUOnSubSub', function() {
window.showUOnSubSub = $('#toggleUOnSubSub').is(':checked');
updateChartDisplay();
});
// 买卖点复选框已移除
// 趋势开关已移除
// 添加K线周期切换事件监听器
$('input[name="klinePeriod"]').change(function() {
console.log('K线周期切换:', $(this).attr('id'), $(this).is(':checked'));
updateChartDisplay();
// 更新数据源信息
if (currentData) {
setupDataSourceInfo(currentData);
}
});
// 当选择不同的元素时间周期时
$('#elementTimeframe').change(function() {
const elementTimeframe = $(this).val();
const mainTimeframe = $('#timeframe').val();
// 检查选择的元素时间周期是否小于等于主周期
if (compareTimeframes(elementTimeframe, mainTimeframe) > 0) {
alert('元素时间周期必须小于或等于主图表时间周期。');
setSmallerOrEqualTimeframe(); // 重置为最大的小于等于时间周期
return;
}
// 次次周期必须小于等于次周期
ensureSubSubLteElement();
console.log(`当前选择的元素时间周期: ${elementTimeframe},需要点击分析按钮来应用更改`);
});
// 次次周期变更时校验 <= 次周期
$('#subSubTimeframe').change(function() {
const subSub = $(this).val();
const elementTf = $('#elementTimeframe').val();
if (compareTimeframes(subSub, elementTf) > 0) {
alert('次次周期必须小于或等于次周期。');
ensureSubSubLteElement();
return;
}
});
function ensureSubSubLteElement() {
const timeframes = window.AVAILABLE_TIMEFRAMES || [];
const elementTf = $('#elementTimeframe').val();
const subSubTf = $('#subSubTimeframe').val();
if (compareTimeframes(subSubTf, elementTf) > 0) {
const idxEl = timeframes.indexOf(elementTf);
const validSubSub = idxEl > 0 ? timeframes[idxEl - 1] : timeframes[0];
$('#subSubTimeframe').val(validSubSub || elementTf);
}
}
/** 应用 /api/chart_metadata 返回的周期列表(切换 crypto / A股 时拉取) */
function applyChartMetadata(meta) {
if (!meta || meta.error || !Array.isArray(meta.timeframe_keys) || meta.timeframe_keys.length === 0) {
return;
}
window.AVAILABLE_TIMEFRAMES = meta.timeframe_keys;
window.DEFAULT_MAIN_TIMEFRAME = meta.default_main;
window.DEFAULT_ELEMENT_TIMEFRAME = meta.default_element;
window.DEFAULT_SUB_SUB_TIMEFRAME = meta.default_sub_sub;
const labels = meta.timeframes || {};
function refill(selId, preferredVal) {
const $el = $(selId);
const cur = $el.val();
$el.empty();
meta.timeframe_keys.forEach(function(k) {
$el.append($('<option>', { value: k, text: labels[k] || k }));
});
const pick = (cur && meta.timeframe_keys.indexOf(cur) >= 0) ? cur : preferredVal;
if (pick && meta.timeframe_keys.indexOf(pick) >= 0) {
$el.val(pick);
} else {
$el.val(meta.timeframe_keys[0]);
}
}
refill('#timeframe', meta.default_main);
refill('#elementTimeframe', meta.default_element);
refill('#subSubTimeframe', meta.default_sub_sub);
const mainTf = $('#timeframe').val();
if (compareTimeframes($('#elementTimeframe').val(), mainTf) > 0) {
setSmallestLargerTimeframe(mainTf);
}
ensureSubSubLteElement();
}
// 比较两个时间周期的大小
function compareTimeframes(tf1, tf2) {
const v1 = window.timeframeToMs(tf1);
const v2 = window.timeframeToMs(tf2);
if (v1 === null || v2 === null) {
return 0;
}
return v1 - v2;
}
// 设置比主周期小的最大周期
function setSmallestLargerTimeframe(mainTimeframe) {
const timeframes = window.AVAILABLE_TIMEFRAMES || [];
const mainIndex = timeframes.indexOf(mainTimeframe);
if (mainIndex > 0) {
$('#elementTimeframe').val(timeframes[mainIndex - 1]);
} else {
$('#elementTimeframe').val(timeframes[0]);
}
}
// 设置小于或等于主周期的时间周期
function setSmallerOrEqualTimeframe(mainTimeframe) {
const timeframes = window.AVAILABLE_TIMEFRAMES || [];
const mainIndex = timeframes.indexOf(mainTimeframe);
// 默认选择相同的时间周期
$('#elementTimeframe').val(mainTimeframe);
}
// 当主时间周期变更时,确保分形元素时间周期、次次周期正确
$('#timeframe').change(function() {
const mainTimeframe = $(this).val();
const elementTimeframe = $('#elementTimeframe').val();
if (compareTimeframes(elementTimeframe, mainTimeframe) > 0) {
setSmallerOrEqualTimeframe(mainTimeframe);
}
ensureSubSubLteElement();
});
let _lastKlinePeriod = 'main';