import {useEffect,useState} from "react" import {request,ApiError} from "@/lib/auth" type Bar={date:string;open:string;high:string;low:string;close:string} type History={source:string;adjustment:string;received_at:string;bars:Bar[]} export function StockHistoryChart({symbol,exchange,onSessionExpired}:{symbol:string;exchange:string;onSessionExpired:()=>void}){ const [data,setData]=useState(null),[error,setError]=useState("") useEffect(()=>{const c=new AbortController();setData(null);setError("");const end=new Date(),start=new Date();start.setDate(start.getDate()-90);request(`/api/admin/v1/market/history?symbol=${symbol}&exchange=${exchange}&start=${start.toISOString().slice(0,10)}&end=${end.toISOString().slice(0,10)}`,{signal:c.signal}).then(result=>{if(!c.signal.aborted)setData(result)}).catch(e=>{if(c.signal.aborted)return;if(e instanceof ApiError&&e.status===401)onSessionExpired();else setError(e instanceof Error?e.message:"日线读取失败")});return()=>c.abort()},[symbol,exchange]) const bars=data?.bars.slice(-40)??[] // Integer cents for price parsing; division below only maps values to SVG pixels. const cents=(price:string)=>{const [whole,fraction=""]=price.split(".");return Number(whole)*100+Number(fraction.padEnd(2,"0"))} const values=bars.map(b=>cents(b.close)),min=Math.min(...values),max=Math.max(...values),range=max-min||1 const points=values.map((value,i)=>`${20+i*600/Math.max(values.length-1,1)},${150-(value-min)*120/range}`).join(" ") return
日线收盘走势未复权 · 最近 {bars.length} 个交易日
{error?

{error}

:!data?

正在获取真实日线…

:bars.length===0?

此范围没有可用日线。

:<>{bars[0].date}{bars[bars.length-1].date}

末日收盘 ¥{bars[bars.length-1].close} · 来源 {data.source} · 接收 {new Date(data.received_at).toLocaleTimeString("zh-CN")}

}
}