2026-08-10 10:07:55 +08:00
|
|
|
import { Database, Search } from "lucide-react"
|
|
|
|
|
|
|
|
|
|
import { Badge } from "@/shared/ui/badge"
|
|
|
|
|
import { Card } from "@/shared/ui/card"
|
|
|
|
|
|
|
|
|
|
import type { SelectionSignal } from "../api/selection.types"
|
2026-08-27 13:17:51 +08:00
|
|
|
import { categoryToneClass, getCategoryLabel } from "./selection-presentation"
|
|
|
|
|
import { SignalDetails } from "./signal-details"
|
2026-08-10 10:07:55 +08:00
|
|
|
|
|
|
|
|
interface SignalDetailPanelProps {
|
|
|
|
|
signal: SelectionSignal | undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function SignalDetailPanel({ signal }: SignalDetailPanelProps) {
|
|
|
|
|
if (!signal) {
|
|
|
|
|
return (
|
|
|
|
|
<Card
|
|
|
|
|
aria-label="当前股票详情"
|
2026-08-10 16:58:16 +08:00
|
|
|
className="hidden min-h-0 overflow-auto rounded-md border-border/80 bg-card p-3 md:flex md:flex-col md:justify-center"
|
2026-08-10 10:07:55 +08:00
|
|
|
>
|
|
|
|
|
<div className="space-y-2 text-center">
|
|
|
|
|
<Search
|
|
|
|
|
className="mx-auto size-5 text-muted-foreground"
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
/>
|
|
|
|
|
<p className="font-medium">暂无选中信号</p>
|
|
|
|
|
<p className="text-xs leading-5 text-muted-foreground">
|
|
|
|
|
从左侧列表选择一条信号查看详情。
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</Card>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<aside
|
|
|
|
|
aria-label="当前股票详情"
|
2026-08-10 16:58:16 +08:00
|
|
|
className="hidden min-h-0 overflow-auto rounded-md border border-border/80 bg-card p-3 md:block"
|
2026-08-10 10:07:55 +08:00
|
|
|
>
|
|
|
|
|
<p className="text-[10px] font-bold tracking-[0.08em] text-muted-foreground uppercase">
|
|
|
|
|
Selected signal
|
|
|
|
|
</p>
|
|
|
|
|
<div className="mt-2 flex items-start justify-between gap-3">
|
|
|
|
|
<div className="min-w-0">
|
|
|
|
|
<h2 className="truncate text-xl font-semibold tracking-tight">
|
|
|
|
|
{signal.name}
|
|
|
|
|
</h2>
|
|
|
|
|
<p className="font-mono text-xs text-muted-foreground">
|
|
|
|
|
{signal.ts_code}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<Database
|
|
|
|
|
className="mt-1 size-4 shrink-0 text-muted-foreground"
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-08-10 13:42:53 +08:00
|
|
|
<p className="mt-4 text-3xl font-semibold tabular-nums tracking-tight">
|
2026-08-10 10:07:55 +08:00
|
|
|
¥ {signal.close.toFixed(2)}
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<Badge
|
|
|
|
|
className={`mt-3 ${categoryToneClass(signal.category)}`}
|
|
|
|
|
variant="outline"
|
|
|
|
|
>
|
|
|
|
|
{getCategoryLabel(signal.category)}
|
|
|
|
|
</Badge>
|
|
|
|
|
|
2026-08-27 13:17:51 +08:00
|
|
|
<dl className="mt-4 divide-y divide-border/60 border-y border-border/60 text-xs">
|
2026-08-10 10:07:55 +08:00
|
|
|
<div className="flex items-center justify-between gap-3 py-2.5">
|
|
|
|
|
<dt className="text-muted-foreground">目标交易日</dt>
|
|
|
|
|
<dd className="font-medium tabular-nums">
|
|
|
|
|
{signal.target_trade_date}
|
|
|
|
|
</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex items-center justify-between gap-3 py-2.5">
|
|
|
|
|
<dt className="text-muted-foreground">策略</dt>
|
|
|
|
|
<dd className="font-medium">知行 B1</dd>
|
|
|
|
|
</div>
|
|
|
|
|
</dl>
|
2026-08-27 13:17:51 +08:00
|
|
|
|
|
|
|
|
<section className="mt-4" aria-labelledby="signal-detail-metrics">
|
|
|
|
|
<h3
|
|
|
|
|
className="mb-2 text-xs font-medium text-muted-foreground"
|
|
|
|
|
id="signal-detail-metrics"
|
|
|
|
|
>
|
|
|
|
|
关键指标
|
|
|
|
|
</h3>
|
|
|
|
|
<SignalDetails details={signal.details} />
|
|
|
|
|
</section>
|
2026-08-10 10:07:55 +08:00
|
|
|
</aside>
|
|
|
|
|
)
|
|
|
|
|
}
|