fix(web): 自动刷新保留 K 线视窗;威科夫与图表增量更新
自动刷新改用 tail update 与 scrollToPosition 恢复视窗,避免 setData 后跳到最右;拆分 chart_tv 模块并扩展 analyze/recent API。同步威科夫分析、pipeline 增量构建及相关策略与配置。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+147
-37
@@ -22,8 +22,8 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- TradingView Widget BEGIN -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/lightweight-charts@4.0.1/dist/lightweight-charts.standalone.production.js"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/indicators.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/charts.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/indicators.js') }}?v=20260809i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/charts.js') }}?v=20260809i"></script>
|
||||
<!-- TradingView Widget END -->
|
||||
<script>
|
||||
window.AVAILABLE_TIMEFRAMES = JSON.parse('{{ timeframe_keys_json | safe }}');
|
||||
@@ -96,6 +96,81 @@
|
||||
position: relative;
|
||||
z-index: 1; /* 确保图表在数据面板之上 */
|
||||
}
|
||||
/* 挂在主图容器内:左下角 = K线主图左下,而非整图(含副图)底边 */
|
||||
.wyckoff-cycle-summary {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
bottom: 28px; /* 略抬高,避开主图时间轴 */
|
||||
top: auto;
|
||||
right: auto;
|
||||
z-index: 1100;
|
||||
min-width: 200px;
|
||||
max-width: 300px;
|
||||
max-height: calc(100% - 36px);
|
||||
overflow-y: auto;
|
||||
padding: 8px 10px;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
border: 1px solid #d0d7de;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
color: #24292f;
|
||||
display: none;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-block {
|
||||
padding: 6px 0;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-block + .wcs-block {
|
||||
border-top: 1px solid #eaeef2;
|
||||
margin-top: 6px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-block.wcs-main { border-left: 3px solid #3498db; padding-left: 8px; }
|
||||
.wyckoff-cycle-summary .wcs-block.wcs-element { border-left: 3px solid #e67e22; padding-left: 8px; }
|
||||
.wyckoff-cycle-summary .wcs-block.wcs-subsub { border-left: 3px solid #27ae60; padding-left: 8px; }
|
||||
.wyckoff-cycle-summary .wcs-title {
|
||||
font-weight: 650;
|
||||
font-size: 13px;
|
||||
margin-bottom: 6px;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-k {
|
||||
color: #656d76;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-v {
|
||||
text-align: right;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-active {
|
||||
margin-top: 2px;
|
||||
padding: 6px 0 4px;
|
||||
border-top: 1px solid #eaeef2;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-prev {
|
||||
margin-top: 6px;
|
||||
padding-top: 6px;
|
||||
border-top: 1px dashed #eaeef2;
|
||||
color: #656d76;
|
||||
font-size: 11px;
|
||||
}
|
||||
.wyckoff-cycle-summary .wcs-badge {
|
||||
display: inline-block;
|
||||
padding: 1px 6px;
|
||||
border-radius: 3px;
|
||||
background: #ddf4ff;
|
||||
color: #0969da;
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
}
|
||||
.chart-options {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
@@ -907,7 +982,7 @@
|
||||
<input type="datetime-local" id="end_time" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button class="btn btn-primary w-100" onclick="updateChart()" style="padding: 8px 6px; font-size: 14px;">
|
||||
<button class="btn btn-primary w-100" onclick="updateEndTimeToNow(); updateChart({ incremental: false, fullAnalyze: true })" style="padding: 8px 6px; font-size: 14px;">
|
||||
分析
|
||||
</button>
|
||||
</div>
|
||||
@@ -953,14 +1028,14 @@
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<label for="refreshInterval" class="form-label me-2 mb-0">自动刷新:</label>
|
||||
<select id="refreshInterval" class="form-select form-select-sm me-2" style="width: 80px;">
|
||||
<option value="0.0833">5秒</option>
|
||||
<option value="0.0833" selected>5秒</option>
|
||||
<option value="0.1667">10秒</option>
|
||||
<option value="0.25">15秒</option>
|
||||
<option value="0.5">30秒</option>
|
||||
<option value="1">1分钟</option>
|
||||
<option value="2">2分钟</option>
|
||||
<option value="3">3分钟</option>
|
||||
<option value="5" selected>5分钟</option>
|
||||
<option value="5">5分钟</option>
|
||||
<option value="10">10分钟</option>
|
||||
</select>
|
||||
<div class="form-check form-check-inline me-2">
|
||||
@@ -972,26 +1047,6 @@
|
||||
<label class="form-check-label" for="showMainStructureZone">结构区</label>
|
||||
</div>
|
||||
<input type="number" id="zoneKlLines" class="form-control form-control-sm" value="1000" min="100" max="5000" step="100" style="width:80px;" title="结构区K线数量">
|
||||
<div class="form-check form-check-inline me-1 ms-2">
|
||||
<input class="form-check-input" type="checkbox" id="showWyckoff">
|
||||
<label class="form-check-label" for="showWyckoff">威科夫</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline me-1">
|
||||
<input class="form-check-input" type="checkbox" id="showWyckoffRange" checked disabled>
|
||||
<label class="form-check-label" for="showWyckoffRange">区间</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline me-1">
|
||||
<input class="form-check-input" type="checkbox" id="showWyckoffPhases" checked disabled>
|
||||
<label class="form-check-label" for="showWyckoffPhases">阶段</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline me-1">
|
||||
<input class="form-check-input" type="checkbox" id="showWyckoffEvents" checked disabled>
|
||||
<label class="form-check-label" for="showWyckoffEvents">事件</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline me-1">
|
||||
<input class="form-check-input" type="checkbox" id="showWyckoffVP" checked disabled>
|
||||
<label class="form-check-label" for="showWyckoffVP">VP</label>
|
||||
</div>
|
||||
<span id="nextRefreshTime" class="text-muted" style="display:none;font-size:0.85rem;"></span>
|
||||
<div id="refreshLoadingSpinner" class="loading-spinner ms-2" style="display:none;"></div>
|
||||
</div>
|
||||
@@ -1037,6 +1092,22 @@
|
||||
<input class="form-check-input" type="checkbox" id="showMainBsp">
|
||||
<label class="form-check-label" for="showMainBsp">买卖点</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline ms-2">
|
||||
<input class="form-check-input" type="checkbox" id="showMainWrRange">
|
||||
<label class="form-check-label" for="showMainWrRange">区间</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showMainWrPhases">
|
||||
<label class="form-check-label" for="showMainWrPhases">阶段</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showMainWrEvents">
|
||||
<label class="form-check-label" for="showMainWrEvents">时间</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showMainWrVP">
|
||||
<label class="form-check-label" for="showMainWrVP">VP</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mt-1">
|
||||
<label class="form-label me-0 mb-0">次周期:</label>
|
||||
@@ -1079,6 +1150,22 @@
|
||||
<input class="form-check-input" type="checkbox" id="showElementBsp">
|
||||
<label class="form-check-label" for="showElementBsp">买卖点</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline ms-2">
|
||||
<input class="form-check-input" type="checkbox" id="showElementWrRange">
|
||||
<label class="form-check-label" for="showElementWrRange">区间</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showElementWrPhases">
|
||||
<label class="form-check-label" for="showElementWrPhases">阶段</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showElementWrEvents">
|
||||
<label class="form-check-label" for="showElementWrEvents">时间</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showElementWrVP">
|
||||
<label class="form-check-label" for="showElementWrVP">VP</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mt-1">
|
||||
<label class="form-label me-0 mb-0">次次周期:</label>
|
||||
@@ -1121,6 +1208,22 @@
|
||||
<input class="form-check-input" type="checkbox" id="showSubSubBsp">
|
||||
<label class="form-check-label" for="showSubSubBsp">买卖点</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline ms-2">
|
||||
<input class="form-check-input" type="checkbox" id="showSubSubWrRange">
|
||||
<label class="form-check-label" for="showSubSubWrRange">区间</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showSubSubWrPhases">
|
||||
<label class="form-check-label" for="showSubSubWrPhases">阶段</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showSubSubWrEvents">
|
||||
<label class="form-check-label" for="showSubSubWrEvents">时间</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showSubSubWrVP">
|
||||
<label class="form-check-label" for="showSubSubWrVP">VP</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1130,6 +1233,7 @@
|
||||
|
||||
<div class="chart-container">
|
||||
<div id="tradingview_chart"></div>
|
||||
<div id="wyckoffCycleSummary" class="wyckoff-cycle-summary" aria-live="polite"></div>
|
||||
<!-- 技术指标下拉菜单 -->
|
||||
<div class="indicator-dropdown dropdown">
|
||||
<button class="add-indicator-btn dropdown-toggle" type="button" id="indicatorDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
@@ -1279,18 +1383,24 @@
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script defer src="{{ url_for('static', filename='js/app/api_client.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/state.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/trend.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/macd_ui.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_format.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_view.js') }}?v=20260806a"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tv.js') }}?v=20260806a"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_sync.js') }}?v=20260806a"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tables.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/ui.js') }}?v=20260806a"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/overlays.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/main.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/api_client.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/state.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/trend.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/macd_ui.js') }}?v=20260808j"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_format.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_view.js') }}?v=20260809r"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tv_lifecycle.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tv_shell.js') }}?v=20260809j"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tv_indicators.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tv_chan.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tv_overlays.js') }}?v=20260809n"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tv_finalize.js') }}?v=20260809d"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tv.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_sync.js') }}?v=20260809r"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/chart_tables.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/ui.js') }}?v=20260809r"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/overlays.js') }}?v=20260808i"></script>
|
||||
<script defer src="{{ url_for('static', filename='js/app/main.js') }}?v=20260808i"></script>
|
||||
|
||||
<!-- 均线配置弹窗 -->
|
||||
<div id="maConfigModal" class="ma-config-modal">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user