diff --git a/manual_trading_hub/static/app.css b/manual_trading_hub/static/app.css index 506b560..d2fc344 100644 --- a/manual_trading_hub/static/app.css +++ b/manual_trading_hub/static/app.css @@ -1,8 +1,14 @@ -:root { +:root, +html[data-theme="dark"] { --bg: #050810; --bg-elevated: #0a1018; --panel: rgba(12, 20, 32, 0.82); --panel-hover: rgba(18, 28, 44, 0.9); + --panel-solid: #141a2a; + --panel-solid-border: #2a3150; + --nav-bg: rgba(0, 0, 0, 0.35); + --overlay: rgba(0, 0, 0, 0.45); + --chart-surface: #0a1018; --text: #e8f4ff; --muted: #6b8aa8; --border: rgba(0, 212, 255, 0.22); @@ -19,6 +25,31 @@ --display: "Orbitron", var(--font); --mono: var(--font); --layout-max: 1520px; + color-scheme: dark; +} + +html[data-theme="light"] { + --bg: #e8eef5; + --bg-elevated: #ffffff; + --panel: rgba(255, 255, 255, 0.94); + --panel-hover: rgba(248, 252, 255, 0.98); + --panel-solid: #ffffff; + --panel-solid-border: #c8d4e4; + --nav-bg: rgba(255, 255, 255, 0.88); + --overlay: rgba(15, 35, 60, 0.35); + --chart-surface: #f4f7fb; + --text: #152030; + --muted: #5a6f85; + --border: rgba(0, 120, 170, 0.28); + --border-soft: rgba(0, 90, 140, 0.14); + --green: #0a8f5c; + --red: #c93552; + --accent: #007aa8; + --accent-2: #5b4fc7; + --accent-dim: rgba(0, 122, 168, 0.1); + --glow: 0 0 18px rgba(0, 122, 168, 0.12); + --shadow: 0 8px 28px rgba(20, 50, 90, 0.1); + color-scheme: light; } * { @@ -171,10 +202,51 @@ a:hover { } } +.theme-toggle { + display: inline-flex; + align-items: center; + gap: 2px; + padding: 3px; + border-radius: var(--radius); + border: 1px solid var(--border-soft); + background: var(--nav-bg); + backdrop-filter: blur(8px); +} + +.theme-toggle-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 34px; + height: 32px; + padding: 0; + border: none; + border-radius: 7px; + background: transparent; + color: var(--muted); + cursor: pointer; + transition: background 0.15s, color 0.15s, box-shadow 0.15s; +} + +.theme-toggle-btn:hover { + color: var(--text); + background: var(--panel-hover); +} + +.theme-toggle-btn.is-active { + color: var(--accent); + background: var(--accent-dim); + box-shadow: inset 0 0 0 1px var(--border); +} + +.theme-toggle-btn .theme-icon { + display: block; +} + .top-nav { display: flex; gap: 4px; - background: rgba(0, 0, 0, 0.35); + background: var(--nav-bg); padding: 4px; border-radius: var(--radius); border: 1px solid var(--border-soft); @@ -1335,8 +1407,8 @@ body.market-chart-fs-open { } .hub-trend-plan-card.plan-position-card { - background: #141a2a; - border: 1px solid #2a3150; + background: var(--panel-solid); + border: 1px solid var(--panel-solid-border); border-radius: 12px; padding: 12px 14px; } @@ -2108,12 +2180,23 @@ button.btn-sm { /* —— 登录页 —— */ body.login-page { display: flex; + flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; padding: 24px; } +.login-theme-bar { + position: relative; + z-index: 2; + width: 100%; + max-width: 400px; + display: flex; + justify-content: flex-end; + margin-bottom: 10px; +} + .login-panel { position: relative; z-index: 1; @@ -2512,7 +2595,7 @@ body.login-page { min-height: 380px; border: 1px solid var(--border-soft); border-radius: var(--radius); - background: #0a1018; + background: var(--chart-surface); overflow: hidden; } @@ -2951,3 +3034,81 @@ body.login-page { border-color: rgba(0, 255, 157, 0.45); background: rgba(0, 255, 157, 0.1); } + +/* —— 亮色主题:背景与局部硬编码色 —— */ +html[data-theme="light"] .app-bg, +html[data-theme="light"] .login-bg { + background: + linear-gradient(rgba(0, 100, 150, 0.06) 1px, transparent 1px), + linear-gradient(90deg, rgba(0, 100, 150, 0.06) 1px, transparent 1px), + radial-gradient(ellipse 80% 50% at 50% -20%, rgba(0, 140, 200, 0.1), transparent), + radial-gradient(ellipse 60% 40% at 100% 100%, rgba(90, 80, 200, 0.06), transparent); + background-size: 48px 48px, 48px 48px, auto, auto; +} + +html[data-theme="light"] .app-bg::after, +html[data-theme="light"] .login-bg::after { + opacity: 0.15; +} + +html[data-theme="light"] .market-ind-options { + background: rgba(255, 255, 255, 0.98); + box-shadow: var(--shadow); +} + +html[data-theme="light"] .market-price-auto { + background: rgba(255, 255, 255, 0.95); +} + +html[data-theme="light"] .market-price-auto.is-on { + color: var(--green); + background: rgba(10, 143, 92, 0.12); +} + +html[data-theme="light"] .hub-trend-plan-card .plan-card-meta, +html[data-theme="light"] .hub-trend-plan-card .plan-cell .lbl, +html[data-theme="light"] .hub-trend-plan-card .plan-dca-title { + color: var(--muted); +} + +html[data-theme="light"] .hub-trend-plan-card .plan-card-meta .accent { + color: var(--accent); +} + +html[data-theme="light"] .hub-trend-plan-card .plan-cell .val { + color: var(--text); +} + +html[data-theme="light"] .hub-trend-plan-card .plan-dca-table th { + color: var(--muted); +} + +html[data-theme="light"] .hub-trend-plan-card .plan-dca-table th, +html[data-theme="light"] .hub-trend-plan-card .plan-dca-table td { + border-bottom-color: var(--border-soft); +} + +html[data-theme="light"] .hub-trend-plan-card .hub-plan-be-input { + background: var(--bg-elevated); + border-color: var(--border-soft); + color: var(--text); +} + +html[data-theme="light"] .exchange-fullscreen-panel, +html[data-theme="light"] .modal-panel { + box-shadow: var(--shadow); +} + +html[data-theme="light"] input, +html[data-theme="light"] select, +html[data-theme="light"] textarea { + background: var(--bg-elevated); + color: var(--text); + border-color: var(--border-soft); +} + +html[data-theme="light"] .hub-tile, +html[data-theme="light"] .hub-pos-card, +html[data-theme="light"] .settings-row { + box-shadow: 0 2px 12px rgba(20, 50, 90, 0.06); +} diff --git a/manual_trading_hub/static/app.js b/manual_trading_hub/static/app.js index 76363a4..fcd31ea 100644 --- a/manual_trading_hub/static/app.js +++ b/manual_trading_hub/static/app.js @@ -2645,6 +2645,9 @@ initInstanceFrame(); initFullscreen(); initMobileLayout(); + if (globalThis.HubTheme && typeof HubTheme.initToggleUI === "function") { + HubTheme.initToggleUI(); + } function initShellNav() { document.querySelectorAll(".top-nav a[href^='/']").forEach((a) => { diff --git a/manual_trading_hub/static/chart.js b/manual_trading_hub/static/chart.js index f179508..fd66023 100644 --- a/manual_trading_hub/static/chart.js +++ b/manual_trading_hub/static/chart.js @@ -1286,13 +1286,58 @@ return candleByTime[t] || null; } + function chartThemePalette() { + const light = document.documentElement.getAttribute("data-theme") === "light"; + return light + ? { + bg: "#f4f7fb", + text: "#5a6f85", + border: "#c8d4e4", + up: "#0a8f5c", + down: "#c93552", + volUp: "rgba(10, 143, 92, 0.45)", + volDown: "rgba(201, 53, 82, 0.45)", + } + : { + bg: "#0a1018", + text: "#b8d4e8", + border: "#2a4058", + up: "#00ff9d", + down: "#ff4d6d", + volUp: "rgba(0, 255, 157, 0.5)", + volDown: "rgba(255, 77, 109, 0.5)", + }; + } + + function applyChartTheme() { + if (!chart) return; + const p = chartThemePalette(); + chart.applyOptions({ + layout: { background: { color: p.bg }, textColor: p.text }, + rightPriceScale: { borderColor: p.border }, + timeScale: { borderColor: p.border }, + }); + if (candleSeries) { + candleSeries.applyOptions({ + upColor: p.up, + downColor: p.down, + wickUpColor: p.up, + wickDownColor: p.down, + }); + } + if (volumeSeries && lastCandles.length) { + volumeSeries.setData(buildVolumeData(lastCandles)); + } + } + function buildVolumeData(candles) { + const p = chartThemePalette(); return (candles || []).map(function (c) { const up = Number(c.close) >= Number(c.open); return { time: c.time, value: Number(c.volume) || 0, - color: up ? "rgba(0, 255, 157, 0.5)" : "rgba(255, 77, 109, 0.5)", + color: up ? p.volUp : p.volDown, }; }); } @@ -1306,15 +1351,16 @@ } return false; } + const tp = chartThemePalette(); chart = LightweightCharts.createChart(chartHost, { - layout: { background: { color: "#0a1018" }, textColor: "#b8d4e8" }, + layout: { background: { color: tp.bg }, textColor: tp.text }, grid: { vertLines: { visible: false }, horzLines: { visible: false }, }, - rightPriceScale: { borderColor: "#2a4058", autoScale: true }, + rightPriceScale: { borderColor: tp.border, autoScale: true }, timeScale: { - borderColor: "#2a4058", + borderColor: tp.border, timeVisible: true, secondsVisible: false, rightOffset: RIGHT_OFFSET_BARS, @@ -1327,11 +1373,11 @@ }); const candleOpts = { - upColor: "#00ff9d", - downColor: "#ff4d6d", + upColor: tp.up, + downColor: tp.down, borderVisible: false, - wickUpColor: "#00ff9d", - wickDownColor: "#ff4d6d", + wickUpColor: tp.up, + wickDownColor: tp.down, lastValueVisible: false, priceLineVisible: false, priceFormat: SAFE_PRICE_FORMAT, @@ -1757,6 +1803,10 @@ stopPriceTagTimer: stopPriceTagTimer, }; + document.addEventListener("hub-theme-change", function () { + applyChartTheme(); + }); + if ( document.getElementById("page-market") && !document.getElementById("page-market").classList.contains("hidden") diff --git a/manual_trading_hub/static/index.html b/manual_trading_hub/static/index.html index 9df4b43..12aa2fa 100644 --- a/manual_trading_hub/static/index.html +++ b/manual_trading_hub/static/index.html @@ -1,7 +1,8 @@ - + + @@ -14,7 +15,7 @@ - + @@ -28,6 +29,19 @@
+
+ + +
SYNC