mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 21:24:16 +08:00
- lib/theme.ts: localStorage 持久化 + useTheme hook (本页/跨标签页
同步) + ChartTheme 图表调色板 (ECharts/lightweight-charts 画布
不吃 CSS 变量, 统一从这里取色)
- index.html: 去掉写死的 class=dark, 换预渲染内联脚本 (默认暗色,
切过亮色则保持), 避免首屏闪烁
- Layout: 侧边栏底部亮/暗切换按钮 (设置入口上方)
- 图表主题化 (切换即时生效, 无需刷新):
· EChartsIntraday / EChartsCandlestick / CandlestickChart
(lightweight-charts applyOptions) / AnalysisKChart
· 回测 4 图 (StrategyNav/FactorIC/FactorGroupNav/ReturnDistribution)
· Sentiment 页双图
序列颜色 (红涨绿跌/MA线) 双主题通用保持不变; 轴/网格/十字线/
tooltip/信息栏背景按主题切换
CSS 变量亮色板 index.css 里本就有 (:root), 首次真正启用
122 lines
3.7 KiB
TypeScript
122 lines
3.7 KiB
TypeScript
// 主题管理 — 暗色(默认) / 亮色切换
|
|
//
|
|
// 机制:
|
|
// - 状态存 localStorage('tf-theme'), 默认 dark (保持老用户体验不变)
|
|
// - 生效方式: html.dark class (index.css 的 CSS variables + Tailwind darkMode:class)
|
|
// - index.html 里有预渲染内联脚本, 首屏前就设好 class, 避免闪烁 (FOUC)
|
|
// - UI token (bg-surface/text-foreground 等) 自动跟随;
|
|
// 图表画布不吃 CSS 变量, 统一走 useChartTheme() 取调色板
|
|
import { useEffect, useState } from 'react'
|
|
|
|
const KEY = 'tf-theme'
|
|
const EVENT = 'tf-theme-change'
|
|
|
|
export type Theme = 'dark' | 'light'
|
|
|
|
export function getTheme(): Theme {
|
|
try {
|
|
return localStorage.getItem(KEY) === 'light' ? 'light' : 'dark'
|
|
} catch {
|
|
return 'dark'
|
|
}
|
|
}
|
|
|
|
export function setTheme(theme: Theme) {
|
|
try { localStorage.setItem(KEY, theme) } catch { /* ignore */ }
|
|
document.documentElement.classList.toggle('dark', theme === 'dark')
|
|
window.dispatchEvent(new CustomEvent(EVENT, { detail: theme }))
|
|
}
|
|
|
|
export function toggleTheme(): Theme {
|
|
const next: Theme = getTheme() === 'dark' ? 'light' : 'dark'
|
|
setTheme(next)
|
|
return next
|
|
}
|
|
|
|
/** 订阅当前主题 (本页切换 + 其他标签页切换均同步)。 */
|
|
export function useTheme(): Theme {
|
|
const [theme, set] = useState<Theme>(getTheme)
|
|
useEffect(() => {
|
|
const onChange = () => set(getTheme())
|
|
window.addEventListener(EVENT, onChange)
|
|
window.addEventListener('storage', onChange) // 跨标签页同步
|
|
return () => {
|
|
window.removeEventListener(EVENT, onChange)
|
|
window.removeEventListener('storage', onChange)
|
|
}
|
|
}, [])
|
|
return theme
|
|
}
|
|
|
|
// ================================================================
|
|
// 图表调色板 — ECharts / lightweight-charts 画布不吃 CSS 变量,
|
|
// 所有图表组件统一从这里取色, 主题切换时依赖 useTheme 重建 option。
|
|
// bull/bear/accent 等语义色双主题一致, 不在此重复定义。
|
|
// ================================================================
|
|
|
|
export interface ChartTheme {
|
|
/** 轴刻度/图例等常规文字 */
|
|
text: string
|
|
/** 信息条/图例里的强调文字 */
|
|
textStrong: string
|
|
/** 网格线 */
|
|
grid: string
|
|
/** 轴线/边框 */
|
|
border: string
|
|
/** 十字光标线 */
|
|
crosshair: string
|
|
/** 十字光标轴标签背景 */
|
|
crosshairLabelBg: string
|
|
/** tooltip 背景 */
|
|
tooltipBg: string
|
|
/** tooltip 边框 */
|
|
tooltipBorder: string
|
|
/** tooltip 文字 */
|
|
tooltipText: string
|
|
/** 半透明信息条背景 (K线图左上角 OHLC 条) */
|
|
infoBarBg: string
|
|
/** dataZoom 滑块填充 */
|
|
zoomFill: string
|
|
/** 分时图均价线以外的弱填充 */
|
|
fillSubtle: string
|
|
}
|
|
|
|
const DARK: ChartTheme = {
|
|
text: '#A1A1AA',
|
|
textStrong: '#E4E4E7',
|
|
grid: 'rgba(255,255,255,0.06)',
|
|
border: '#27272A',
|
|
crosshair: 'rgba(255,255,255,0.25)',
|
|
crosshairLabelBg: '#333',
|
|
tooltipBg: 'rgba(24,24,27,0.95)',
|
|
tooltipBorder: 'rgba(255,255,255,0.1)',
|
|
tooltipText: '#E4E4E7',
|
|
infoBarBg: 'rgba(39,39,42,0.6)',
|
|
zoomFill: 'rgba(255,255,255,0.06)',
|
|
fillSubtle: 'rgba(255,255,255,0.04)',
|
|
}
|
|
|
|
const LIGHT: ChartTheme = {
|
|
text: '#71717A',
|
|
textStrong: '#27272A',
|
|
grid: 'rgba(0,0,0,0.06)',
|
|
border: '#E4E4E7',
|
|
crosshair: 'rgba(0,0,0,0.3)',
|
|
crosshairLabelBg: '#52525B',
|
|
tooltipBg: 'rgba(255,255,255,0.97)',
|
|
tooltipBorder: 'rgba(0,0,0,0.1)',
|
|
tooltipText: '#27272A',
|
|
infoBarBg: 'rgba(244,244,245,0.85)',
|
|
zoomFill: 'rgba(0,0,0,0.06)',
|
|
fillSubtle: 'rgba(0,0,0,0.04)',
|
|
}
|
|
|
|
export function chartTheme(theme: Theme): ChartTheme {
|
|
return theme === 'dark' ? DARK : LIGHT
|
|
}
|
|
|
|
/** hook: 当前主题的图表调色板 (主题切换自动触发重渲染)。 */
|
|
export function useChartTheme(): ChartTheme {
|
|
return chartTheme(useTheme())
|
|
}
|