feat: 详情页K线增加技术指标 MA/MACD/RSI/KDJ

- 新增 indicators.ts 指标计算库:SMA/EMA/MACD(12,26,9)/RSI(14)/KDJ(9,3,3)
- KLineChart 支持指标开关:MA(5/10/20/30) 主图叠加、MACD/RSI/KDJ 独立副图 pane
- 图表高度随指标 pane 数量动态增长(主图 300 + 每个副图 95),主图不被压缩
- 指标全部前端本地计算,无需后端
This commit is contained in:
Sakurasan
2026-08-28 12:05:37 +08:00
parent 25c179dc06
commit 0743014f1a
3 changed files with 344 additions and 24 deletions
+23
View File
@@ -87,6 +87,9 @@ function StockDetail() {
const [dailyTableDays, setDailyTableDays] = useState<number>(7);
const [chartRange, setChartRange] = useState(90); // 默认近3月
const [chartMode, setChartMode] = useState<"line" | "candle">("candle"); // 折线/蜡烛,默认蜡烛
const [indicators, setIndicators] = useState({ ma: true, macd: true, rsi: false, kdj: false });
const toggleIndicator = (key: keyof typeof indicators) =>
setIndicators((prev) => ({ ...prev, [key]: !prev[key] }));
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [inCollection, setInCollection] = useState(false);
@@ -542,6 +545,25 @@ function StockDetail() {
</button>
))}
</div>
{/* 指标开关:MA / MACD / RSI / KDJ */}
<div className="flex gap-0.5 text-xs border rounded-md overflow-hidden">
{([
{ key: "ma", label: "MA" },
{ key: "macd", label: "MACD" },
{ key: "rsi", label: "RSI" },
{ key: "kdj", label: "KDJ" },
] as const).map((it) => (
<button
key={it.key}
onClick={() => toggleIndicator(it.key)}
className={`px-2.5 py-1 transition-colors ${
indicators[it.key] ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground"
}`}
>
{it.label}
</button>
))}
</div>
{/* 时间范围:3月 / 6月 / 1年 */}
<div className="flex gap-0.5 text-xs border rounded-md overflow-hidden">
{[
@@ -588,6 +610,7 @@ function StockDetail() {
}))}
mode={chartMode}
hasAddedDate={inCollection}
indicators={indicators}
/>
</>
)}