refactor(web): adjust layout and styling for improved responsiveness and visual consistency #25
@@ -37,7 +37,7 @@ export function AppLayout() {
|
|||||||
const [moreOpen, setMoreOpen] = useState(false)
|
const [moreOpen, setMoreOpen] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-svh min-h-0 flex-col overflow-hidden bg-background text-foreground md:grid md:grid-cols-[64px_minmax(0,1fr)] lg:grid-cols-[232px_minmax(0,1fr)]">
|
<div className="flex h-svh min-h-0 flex-col overflow-hidden bg-background text-foreground md:grid md:grid-cols-[64px_minmax(0,1fr)] lg:grid-cols-[192px_minmax(0,1fr)]">
|
||||||
<DesktopSidebar activePath={activePath} />
|
<DesktopSidebar activePath={activePath} />
|
||||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||||
<TopBar
|
<TopBar
|
||||||
@@ -64,7 +64,7 @@ function DesktopSidebar({ activePath }: { activePath: string }) {
|
|||||||
return (
|
return (
|
||||||
<aside
|
<aside
|
||||||
aria-label="主导航"
|
aria-label="主导航"
|
||||||
className="hidden shrink-0 flex-col border-r border-border bg-card/95 px-2 py-4 md:flex md:w-16 lg:w-[232px] lg:px-3.5"
|
className="hidden shrink-0 flex-col border-r border-border bg-card/95 px-2 py-4 md:flex md:w-16 lg:w-48 lg:px-3"
|
||||||
>
|
>
|
||||||
<Brand />
|
<Brand />
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,10 @@ export function PatternScoreSummary({ score }: PatternScoreProps) {
|
|||||||
return <Badge variant="destructive">评分暂不可用</Badge>
|
return <Badge variant="destructive">评分暂不可用</Badge>
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span className="space-y-0.5">
|
<span className="inline-flex min-w-0 items-center gap-1">
|
||||||
<strong className="block tabular-nums text-primary">
|
<strong className="tabular-nums text-primary">
|
||||||
{formatScore(score.value)} 分
|
{formatScore(score.value)} 分
|
||||||
</strong>
|
</strong>
|
||||||
<span className="block text-[10px] text-muted-foreground">
|
|
||||||
{score.case?.name ?? "最佳案例未知"}
|
|
||||||
</span>
|
|
||||||
{score.status === "below_threshold" ? (
|
{score.status === "below_threshold" ? (
|
||||||
<Badge variant="outline">低于阈值</Badge>
|
<Badge variant="outline">低于阈值</Badge>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export function SelectionResultsWorkbench({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col gap-2 overflow-hidden md:grid md:grid-cols-[minmax(0,1fr)_minmax(0,3fr)]">
|
<div className="flex min-h-0 min-w-0 flex-1 flex-col gap-2 overflow-hidden md:grid md:grid-cols-[320px_minmax(0,1fr)]">
|
||||||
<section className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-md border border-border/80 bg-card">
|
<section className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-md border border-border/80 bg-card">
|
||||||
<div className="flex shrink-0 flex-wrap items-center gap-1.5 border-b border-border/60 p-2.5">
|
<div className="flex shrink-0 flex-wrap items-center gap-1.5 border-b border-border/60 p-2.5">
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@@ -81,24 +81,23 @@ export function SignalRecordList({
|
|||||||
data-selected={selected}
|
data-selected={selected}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className="min-h-11 w-full text-left outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
|
className="flex min-h-11 w-full flex-col gap-1 text-left outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
|
||||||
onClick={() => onSelect(stock)}
|
onClick={() => onSelect(stock)}
|
||||||
onKeyDown={(event) => handleSelectKeyDown(event, stock)}
|
onKeyDown={(event) => handleSelectKeyDown(event, stock)}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span className="flex flex-wrap items-baseline gap-x-2 gap-y-0.5">
|
<span className="flex min-w-0 items-baseline gap-x-2">
|
||||||
<span className="font-medium text-foreground">
|
<span className="min-w-0 truncate font-medium text-foreground">
|
||||||
{stock.name}
|
{stock.name}
|
||||||
</span>
|
</span>
|
||||||
<span className="font-mono text-[10px] text-muted-foreground">
|
<span className="shrink-0 font-mono text-[10px] text-muted-foreground">
|
||||||
{stock.ts_code}
|
{stock.ts_code}
|
||||||
</span>
|
</span>
|
||||||
<span className="ml-auto font-medium tabular-nums text-foreground">
|
<span className="ml-auto shrink-0 font-medium tabular-nums text-foreground">
|
||||||
¥ {stock.close.toFixed(2)}
|
¥ {stock.close.toFixed(2)}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs">
|
<span className="flex min-w-0 flex-wrap gap-1">
|
||||||
<span className="flex flex-wrap gap-1">
|
|
||||||
{stock.signals.map((signal) => (
|
{stock.signals.map((signal) => (
|
||||||
<Badge
|
<Badge
|
||||||
key={signal.category}
|
key={signal.category}
|
||||||
@@ -109,8 +108,9 @@ export function SignalRecordList({
|
|||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
</span>
|
</span>
|
||||||
|
<span className="flex items-center gap-x-2 text-xs">
|
||||||
<PatternScoreSummary score={stock.score} />
|
<PatternScoreSummary score={stock.score} />
|
||||||
<span className="tabular-nums text-muted-foreground">
|
<span className="ml-auto shrink-0 tabular-nums text-muted-foreground">
|
||||||
J
|
J
|
||||||
<strong className="font-semibold text-foreground">
|
<strong className="font-semibold text-foreground">
|
||||||
{getStockJValue(stock)}
|
{getStockJValue(stock)}
|
||||||
|
|||||||
@@ -182,7 +182,6 @@ describe("SelectionResultsPage", () => {
|
|||||||
expect(within(record).getByText("12")).toBeInTheDocument()
|
expect(within(record).getByText("12")).toBeInTheDocument()
|
||||||
expect(within(record).queryByText("13")).not.toBeInTheDocument()
|
expect(within(record).queryByText("13")).not.toBeInTheDocument()
|
||||||
expect(within(record).getByText("¥ 10.50")).toBeInTheDocument()
|
expect(within(record).getByText("¥ 10.50")).toBeInTheDocument()
|
||||||
expect(within(record).getByText("华纳药厂")).toBeInTheDocument()
|
|
||||||
expect(screen.getByRole("button", { name: /平安银行/ })).toBeInTheDocument()
|
expect(screen.getByRole("button", { name: /平安银行/ })).toBeInTheDocument()
|
||||||
expect(
|
expect(
|
||||||
screen.queryByRole("button", { name: "查看详情" }),
|
screen.queryByRole("button", { name: "查看详情" }),
|
||||||
|
|||||||
Reference in New Issue
Block a user