增加K线

This commit is contained in:
dekun
2026-05-30 10:42:54 +08:00
parent 53959a9008
commit e9f1a6a46f
2 changed files with 25 additions and 64 deletions
+19 -29
View File
@@ -1,4 +1,4 @@
/** 多周期 K 线 · SQLite 后端 + localStorage · 弹窗全屏 Lightweight Charts */ /** 多周期 K 线 · SQLite 后端 + localStorage · 弹窗大图 Lightweight Charts */
const CHART_INTERVALS = ["5m", "15m", "30m", "1h", "4h", "1d", "1w"]; const CHART_INTERVALS = ["5m", "15m", "30m", "1h", "4h", "1d", "1w"];
const INTERVAL_LIMITS = { const INTERVAL_LIMITS = {
@@ -30,6 +30,8 @@ const COLORS = {
}; };
const MINI_SIZE = { w: 380, h: 100 }; const MINI_SIZE = { w: 380, h: 100 };
/** 弹窗图表最小尺寸;实际按视口放大(带鱼屏可接近全宽) */
const MODAL_CHART_MIN = { w: 1280, h: 560 };
const DEFAULT_MINI_INTERVAL = "1d"; const DEFAULT_MINI_INTERVAL = "1d";
let chartModalSymbol = ""; let chartModalSymbol = "";
@@ -47,15 +49,12 @@ function limitForInterval(interval) {
return INTERVAL_LIMITS[interval] || 500; return INTERVAL_LIMITS[interval] || 500;
} }
function modalSize() { function modalChartSize() {
const fs = document.fullscreenElement; const padX = 32;
if (fs) { const chromeY = 150;
return { const w = Math.max(MODAL_CHART_MIN.w, window.innerWidth - padX * 2);
w: Math.max(800, window.innerWidth - 48), const h = Math.max(MODAL_CHART_MIN.h, window.innerHeight - chromeY);
h: Math.max(480, window.innerHeight - 160), return { w, h };
};
}
return { w: 1280, h: 680 };
} }
function loadKlineFromLS(symbol, interval) { function loadKlineFromLS(symbol, interval) {
@@ -171,7 +170,7 @@ function drawCandlestickChart(canvas, candles, options = {}) {
if (!canvas || !candles.length) return; if (!canvas || !candles.length) return;
const large = options.large === true; const large = options.large === true;
const size = large ? modalSize() : MINI_SIZE; const size = large ? modalChartSize() : MINI_SIZE;
const volRatio = large ? 0.22 : 0.32; const volRatio = large ? 0.22 : 0.32;
const pad = large const pad = large
? { t: 16, r: 16, b: 28, l: 56 } ? { t: 16, r: 16, b: 28, l: 56 }
@@ -298,7 +297,7 @@ async function loadMiniChart(box) {
drawCandlestickChart(canvas, candles, { large: false }); drawCandlestickChart(canvas, candles, { large: false });
box.dataset.loaded = "1"; box.dataset.loaded = "1";
if (status) status.textContent = `${candles.length}日·${sourceLabel(source)}`; if (status) status.textContent = `${candles.length}日·${sourceLabel(source)}`;
box.title = `${symbol} 日K ${candles.length}根 (${sourceLabel(source)}),点击全屏`; box.title = `${symbol} 日K ${candles.length}根 (${sourceLabel(source)}),点击查看大图`;
} catch (e) { } catch (e) {
if (status) status.textContent = "—"; if (status) status.textContent = "—";
box.title = `${symbol}: ${e.message}`; box.title = `${symbol}: ${e.message}`;
@@ -328,7 +327,7 @@ function ensureLwcChart(container) {
} }
destroyLwcChart(); destroyLwcChart();
const { w, h } = modalSize(); const { w, h } = modalChartSize();
container.style.width = `${w}px`; container.style.width = `${w}px`;
container.style.height = `${h}px`; container.style.height = `${h}px`;
@@ -407,7 +406,7 @@ function updateModalMeta(candles, source, interval) {
title.textContent = `${chartModalSymbol} · ${interval.toUpperCase()} K线`; title.textContent = `${chartModalSymbol} · ${interval.toUpperCase()} K线`;
} }
if (hint) { if (hint) {
hint.textContent = `${candles.length} 根 · ${sourceLabel(source)} · 滚轮缩放 · 拖拽平移 · 十字线 · Esc 退出`; hint.textContent = `${candles.length} 根 · ${sourceLabel(source)} · 滚轮缩放 · 拖拽平移 · 十字线 · Esc 或点击遮罩关闭`;
} }
} }
@@ -439,9 +438,6 @@ function closeChartModal() {
modal.classList.add("hidden"); modal.classList.add("hidden");
destroyLwcChart(); destroyLwcChart();
chartModalSymbol = ""; chartModalSymbol = "";
if (document.fullscreenElement) {
document.exitFullscreen?.().catch(() => {});
}
} }
async function openChartModal(symbol) { async function openChartModal(symbol) {
@@ -465,12 +461,6 @@ async function openChartModal(symbol) {
if (container) container.innerHTML = ""; if (container) container.innerHTML = "";
await loadModalChart(DEFAULT_MINI_INTERVAL); await loadModalChart(DEFAULT_MINI_INTERVAL);
const inner = modal.querySelector(".chart-modal-inner");
const req = inner.requestFullscreen || inner.webkitRequestFullscreen;
if (req) {
req.call(inner).catch(() => {});
}
} }
function setupChartModal() { function setupChartModal() {
@@ -514,14 +504,14 @@ function setupChartModal() {
document.addEventListener("keydown", (e) => { document.addEventListener("keydown", (e) => {
if (e.key === "Escape") closeChartModal(); if (e.key === "Escape") closeChartModal();
}); });
document.addEventListener("fullscreenchange", () => { window.addEventListener("resize", () => {
if (!chartModalSymbol || !lwcChart) return; if (!chartModalSymbol || !lwcChart) return;
const container = document.getElementById("chart-modal-container"); const container = document.getElementById("chart-modal-container");
if (!container) return; if (!container?.isConnected) return;
const rect = container.getBoundingClientRect(); const { w, h } = modalChartSize();
if (rect.width > 0 && rect.height > 0) { container.style.width = `${w}px`;
lwcChart.applyOptions({ width: rect.width, height: rect.height }); container.style.height = `${h}px`;
} lwcChart.applyOptions({ width: w, height: h });
}); });
} }
+6 -35
View File
@@ -334,34 +334,11 @@ button:hover {
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 12px; border-radius: 12px;
padding: 1.25rem 1.5rem 1.5rem; padding: 1.25rem 1.5rem 1.5rem;
max-width: 96vw; width: calc(100vw - 2rem);
max-width: none;
max-height: 96vh; max-height: 96vh;
overflow: auto; overflow: auto;
} box-shadow: 0 16px 48px rgba(0, 0, 0, 0.45);
.chart-modal-inner:fullscreen {
width: 100vw;
height: 100vh;
max-width: none;
max-height: none;
border-radius: 0;
display: flex;
flex-direction: column;
}
.chart-modal-inner:fullscreen .chart-modal-canvas-wrap {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 0;
}
.chart-modal-inner:fullscreen .chart-lwc-container {
flex: 1;
width: 100% !important;
height: 100% !important;
min-height: 0;
} }
.chart-modal-head { .chart-modal-head {
@@ -402,7 +379,9 @@ button:hover {
.chart-lwc-container { .chart-lwc-container {
width: 100%; width: 100%;
min-height: 480px; min-width: 1280px;
min-height: 560px;
margin: 0 auto;
} }
.chart-lwc-fallback { .chart-lwc-fallback {
@@ -411,14 +390,6 @@ button:hover {
color: var(--muted); color: var(--muted);
} }
.chart-modal-inner:fullscreen .chart-modal-head {
flex-shrink: 0;
}
.chart-modal-inner:fullscreen .chart-modal-hint {
flex-shrink: 0;
}
.stats-table .stats-total-vol { .stats-table .stats-total-vol {
font-weight: 600; font-weight: 600;
white-space: nowrap; white-space: nowrap;