跳到主要内容

鲸鱼选股 (XuanGu) 前端页面布局规范

版本:1.2 | 更新日期:2026-10-09

设计参考:shadcn/ui · Ant Design 5.x · Tailwind CSS 4


一、设计原则​

1.1 核心理念​

原则说明
一致性相同类型的元素在所有页面保持统一的视觉表现和交互行为
层次感通过间距、字号、色彩建立清晰的信息层级
呼吸感适当留白,避免信息过载,提升可读性
响应式宽屏优先:充分适配 1280px ~ 2560px+ 显示器;移动端(小于 768px)按第九节降级
可访问性符合 WCAG 2.1 AA 标准,支持键盘导航与屏幕阅读器

1.2 设计系统架构​

CSS Custom Properties (globals.css)
↓ 设计令牌(颜色、间距、圆角、阴影)
Tailwind Config (tailwind.config.js)
↓ 令牌映射为工具类
shadcn/ui Primitives (src/components/ui/)
↓ 基础组件(Button, Card, Table...)
Layout Primitives (src/components/layout/)
↓ 布局组件(TitleBar, Sidebar, RightPanel)
Page Compositions (src/pages/)
↓ 页面组合

二、设计令牌 (Design Tokens)​

2.1 色彩系统​

语义色(CSS Custom Properties)​

令牌用途亮色模式暗色模式
--background页面背景220 20% 97%222 30% 9%
--card卡片表面0 0% 100%222 24% 13%
--primary主色调(可动态切换)228 86% 63%228 78% 62%
--muted-foreground次要文本220 10% 46%220 15% 55%
--border边框220 13% 91%222 20% 18%
--up涨(A 股红涨)354 78% 47%0 72% 55%
--down跌(A 股绿跌)146 76% 33%142 70% 45%
--success成功142 72% 40%142 70% 45%
--warning警告38 92% 50%38 88% 55%
--destructive危险/错误0 72% 51%0 62% 50%

色彩使用规则​

场景色彩说明
主操作按钮bg-primary仅用于页面最重要的 1~2 个操作
次要操作bg-secondary 或 border取消、返回等
危险操作bg-destructive删除、清空等不可逆操作
成功状态text-success / bg-success/10完成、通过
涨跌标识text-up / text-down严格遵循 A 股红涨绿跌

2.2 间距系统 (Spacing Scale)​

参考 Ant Design 的 8px 栅格系统,结合 Tailwind 默认值:

语义名Tailwind像素值用途
xsgap-1 / space-y-14px紧凑元素内部间距(徽章内、图标与文字)
smgap-2 / space-y-28px相关元素间距(表单项、按钮组)
mdgap-3 / space-y-312px卡片内部区块间距
basegap-4 / space-y-416px标准区块间距
lggap-5 / space-y-520px页面主要分区间距
xlgap-6 / space-y-624px顶级模块间距
2xlgap-8 / space-y-832px大区块分隔(首屏)

统一规则:

  • 页面内边距:p-5(20px)标准页 / p-6(24px)详情页
  • 区块间距:默认 space-y-5,卡片内 space-y-3
  • 表单元素间距:gap-3(12px)水平 / space-y-4(16px)垂直

2.3 圆角系统 (Border Radius)​

元素类型Tailwind像素值说明
大容器/卡片rounded-2xl / rounded-lg16px页面级容器、Card 组件
控件/按钮/输入框rounded-control9px交互控件统一圆角
徽章/标签rounded-md6pxBadge、Tag
小图标容器rounded-md6px24px 以下图标
头像/圆形按钮rounded-full50%用户头像、FAB

规则:glass-card 统一使用 rounded-2xl,不再使用 rounded-xl。

2.4 阴影系统 (Shadows)​

层级Tailwind用途
无阴影—扁平元素、内嵌区域
shadow-xs微阴影分割线替代、轻微抬升
shadow-sm小阴影卡片默认状态
shadow-md中阴影卡片悬停、下拉菜单
shadow-lg大阴影模态框、浮动面板
shadow-macmacOS 风格主要浮动层(Popover、Dialog)

2.5 字体系统 (Typography)​

层级Tailwind字号/行高用途
Displaytext-2xl font-bold24px / 32px页面大标题(极少使用)
H1 页面标题text-base font-semibold tracking-tight16px / 24pxPageHeader 标题(紧凑化)
H2 区块标题text-lg font-semibold18px / 28pxCard 标题、区块标题
H3 子标题text-base font-medium16px / 24px子区块标题
Body 正文text-sm14px / 22px默认正文(Tailwind default)
Body 小正文text-2sm13px / 20px次要正文
Caption 说明text-xs12px / 16px说明文字、时间戳
Overline 标注text-[10px] uppercase tracking-wider10px表头、标签

数字字体:所有数字使用 font-variant-numeric: tabular-nums(.nums 类),确保对齐。


三、布局系统​

3.1 页面分类​

所有页面归为 5 类,每类规定标准结构:

类型适用场景标准外层结构
A. 标准内容页信息展示、列表、报告见 3.2
B. 工作台页筛选 + 可滚动主体见 3.3
C. 详情页单标的/单记录详情见 3.4
D. 双面板页主内容 + 辅助面板见 3.5
E. 全屏沉浸页图表密集、特殊交互见 3.6

3.2 标准内容页 (Type A)​

适用于:Backtest、NlPick、Notifications、GlobalMarket 等信息展示页。

<div className="h-full overflow-y-auto scrollbar-thin">
<div className="mx-auto w-[98%] max-w-[2200px] space-y-5 p-5">
<PageHeader icon={Icon} title="页面标题" description="说明" />

{/* 内容区块 */}
<Card className="rounded-2xl p-5">
{/* ... */}
</Card>
</div>
</div>

规格:

  • 外层:h-full overflow-y-auto scrollbar-thin
  • 内容区:mx-auto w-[98%] max-w-[2200px] space-y-5 p-5
  • 卡片:rounded-2xl p-5

3.3 工作台页 (Type B)​

适用于:Screener、SmartPick、FactorPick、PatternSelect、EarningsWindow、ChokepointSelect 等需要固定头部的页面。

标准 flush 模式(无筛选栏或筛选栏在滚动区内)​

<div className="flex h-full flex-col overflow-hidden">
{/* PageHeader 直接置顶,自带 border-b */}
<PageHeader icon={Icon} title="页面标题" description="说明" />

{/* 可滚动主体 */}
<div className="flex-1 overflow-y-auto scrollbar-thin">
<div className="mx-auto w-[98%] max-w-[2200px] space-y-4 p-5">
{/* 内容 */}
</div>
</div>
</div>

带固定筛选栏模式​

<div className="flex h-full flex-col overflow-hidden">
{/* 固定头部:PageHeader + FilterBar */}
<div className="flex-shrink-0 border-b border-border bg-card">
<PageHeader icon={Icon} title="页面标题" />
<FilterBar>
{/* 筛选控件 */}
</FilterBar>
</div>

{/* 可滚动主体 */}
<div className="flex-1 overflow-y-auto scrollbar-thin">
<div className="mx-auto w-[98%] max-w-[2200px] space-y-4 p-5">
{/* 内容 */}
</div>
</div>
</div>

规格:

  • 外层:flex h-full flex-col overflow-hidden(页面不自带滚动,由内部容器处理)
  • PageHeader 直接置顶(flush),无需额外 flex-shrink-0 包裹(组件自带 border-b)
  • 带固定筛选栏时:flex-shrink-0 border-b border-border bg-card 包裹 PageHeader + FilterBar
  • 主体滚动:flex-1 overflow-y-auto scrollbar-thin
  • 内容区:w-[98%] max-w-[2200px] space-y-4 p-5

3.4 详情页 (Type C)​

适用于:FinancialDetail、EtfDetail、SectorDetail 等单记录详情页。

<div className="h-full overflow-y-auto scrollbar-thin">
<div className="mx-auto w-[98%] max-w-[2200px] space-y-5 p-6">
<DetailBackButton />

{/* 详情头部 */}
<div className="space-y-2">
<h1 className="text-2xl font-bold tracking-tight">标题</h1>
<p className="text-sm text-muted-foreground">描述</p>
</div>

{/* 详情内容 */}
<Card className="rounded-2xl p-6">
{/* ... */}
</Card>
</div>
</div>

规格:

  • 内容区:p-6(详情页留白更多)
  • 卡片:p-6
  • 标题:text-2xl font-bold

3.5 双面板页 (Type D)​

适用于:Analysis、TrendDiscovery、RealtimeMarket 等主辅信息并排页。

标准 flush 模式(PageHeader 置顶)​

<div className="flex h-full flex-col overflow-hidden">
<PageHeader icon={Icon} title="页面标题" description="说明" />
<div className="flex-1 overflow-hidden">
<div className="flex h-full flex-row">
{/* 主内容区 */}
<div className="flex min-h-0 flex-1 flex-col overflow-y-auto scrollbar-thin p-5">
{/* 主内容 */}
</div>

{/* 辅助面板 */}
<RightPanel resizable collapsible defaultWidth={420}>
{/* 辅助信息 */}
</RightPanel>
</div>
</div>
</div>

规格:

  • PageHeader:flush 置顶,与 Type B 一致
  • 主内容:flex min-h-0 flex-1 flex-col overflow-y-auto scrollbar-thin p-5
  • 辅助面板:RightPanel 组件,宽度 320~720px 可调

3.6 全屏沉浸页 (Type E)​

适用于:MarketTreemap、CrowdingDetail 等图表密集页。

<div className="flex h-full flex-col overflow-hidden">
{/* 精简头部 */}
<div className="flex-shrink-0 flex items-center justify-between border-b border-border px-5 py-3">
<h1 className="text-lg font-semibold">标题</h1>
<div className="flex items-center gap-2">
{/* 操作 */}
</div>
</div>

{/* 全屏内容 */}
<div className="flex-1 overflow-hidden">
{/* 图表/可视化内容 */}
</div>
</div>

规格:

  • 头部精简:px-5 py-3,不使用 PageHeader
  • 内容区:flex-1 overflow-hidden,无内边距

3.7 内容宽度规范​

场景宽度类名说明
标准页面w-[98%] max-w-[2200px]充分适配宽屏
阅读/文章w-[96%] max-w-5xlNewsDetail 等长文阅读
全屏图表w-fullMarketTreemap 等

规则:

  • 最大宽度从 1920px 提升到 2200px,适配 2K/4K 显示器
  • 宽度百分比从 96% 提升到 98%,减少两侧空白

四、组件规范​

4.1 页面头部 (PageHeader)​

所有非详情页 必须 使用 PageHeader 组件,且 必须置顶齐平(紧贴应用 header 与侧边栏,无间距)。

<div className="flex h-full flex-col overflow-hidden">
<PageHeader
icon={TrendingUp} // Lucide 图标
title="智能选股" // 必填
description="基于多因子模型的量化选股" // 可选
actions={ // 右侧操作区
<Button size="sm">新建策略</Button>
}
meta={ // 元信息(标题右侧,可选)
<span className="text-[11px] text-muted-foreground">
更新于 5 分钟前
</span>
}
/>

{/* 可滚动主体 */}
<div className="flex-1 overflow-y-auto scrollbar-thin">
<div className="mx-auto w-[98%] max-w-[2200px] space-y-4 p-5">
{/* 内容 */}
</div>
</div>
</div>

视觉规格:

元素样式
容器px-6 py-2.5 border-b border-border
图标容器h-8 w-8 rounded-control bg-accent text-primary flex items-center justify-center
图标h-4 w-4
标题text-base font-semibold tracking-tight
描述text-[11px] text-muted-foreground truncate mt-0
元信息text-[11px] text-muted-foreground(标题右侧)
操作区flex items-center gap-2
整体间距gap-2(各层级)

布局规则:

  • 外层容器:flex h-full flex-col overflow-hidden
  • PageHeader 直接作为第一个子元素(无卡片样式、无额外 padding)
  • 滚动容器:flex-1 overflow-y-auto scrollbar-thin
  • 内容区:mx-auto w-[98%] max-w-[2200px] space-y-4 p-5

禁止:

  • 手写内联页面头部样式
  • 将 PageHeader 放在滚动容器内部(必须置顶齐平)
  • 使用 text-xl font-bold 替代 text-base font-semibold
  • 图标不使用容器直接放置
  • 外层容器缺少 overflow-hidden(会导致滚动穿透)

已统一页面:

  • 规则选股 (SmartPick)
  • 量化选股 (FactorPick)
  • 形态选股 (PatternSelect)
  • 财报选股 (EarningsWindow)
  • 条件选股 (Screener)
  • 卡脖子选股 (ChokepointSelect)
  • 今日信号 (TacticSignalsDashboard)
  • 自选股 (Favorites)
  • 监控中心 (MonitorCenter)
  • 持仓中心 (PositionCenter)
  • 可转债 (ConvertibleBond)
  • 热门股票 (HotTrending)
  • 数据可信度 (DataTrustCenter)
  • AI 使用统计 (AiUsage)
  • 持仓体检 (PortfolioInspection)
  • 掌握度 (Mastery)
  • 社区 (Community)
  • 商品中心 (CommodityCenter)
  • 另类数据源 (AltSources)

4.2 卡片 (Card)​

标准卡片​

<Card className="rounded-2xl p-5">
<CardHeader>
<CardTitle>标题</CardTitle>
<CardDescription>描述</CardDescription>
</CardHeader>
<CardContent className="p-5 pt-0">
{/* 内容 */}
</CardContent>
</Card>

紧凑卡片(KPI、统计)​

<Card className="rounded-2xl p-4">
<div className="flex items-center justify-between">
<span className="text-xs text-muted-foreground">标签</span>
<Icon className="h-4 w-4 text-muted-foreground" />
</div>
<div className="mt-2 text-2xl font-bold nums">1,234</div>
<div className="mt-1 text-xs text-up">+2.5%</div>
</Card>

玻璃态卡片​

<div className="glass-card rounded-2xl p-5">
{/* 内容 */}
</div>

规则:

  • 标准卡片:p-5
  • 紧凑卡片:p-4
  • 宽松卡片(详情页):p-6
  • 玻璃态:统一 rounded-2xl
  • 同一页面内,同类型卡片内边距必须一致

4.3 表格 (Table)​

选型指南​

数据量推荐组件配置
< 50 行DataTable标准模式
50~500 行DataTabledense 紧凑模式
> 500 行VirtualTable虚拟滚动
只读展示 < 20 行Table 原语轻量

禁止:原生 <table> HTML。

标准表格样式​

<DataTable
columns={columns}
data={data}
// 标准模式(默认)
// 或 dense 紧凑模式
/>

统一规格:

属性标准模式紧凑模式
表头背景bg-secondary/50同左
表头字重font-medium text-xs text-muted-foreground同左
表头高度h-9(36px)h-8(32px)
单元格内边距px-3 py-2(12px × 8px)px-2 py-1.5(8px × 6px)
行高h-10(40px)h-8(32px)
行悬停hover:bg-secondary/60同左
行边框border-b border-border/60同左
交替行默认关闭默认关闭

表头样式​

<TableHead className="bg-secondary/50 font-medium text-xs text-muted-foreground uppercase tracking-wider">
列名
</TableHead>

规则:

  • 表头使用大写字母(uppercase)
  • 字间距加宽(tracking-wider)
  • 数字列右对齐(text-right)
  • 金额列使用 .nums 类确保数字对齐

结果集表(DbAdmin / SQL 工作台,借鉴 dbx)​

数据库管理页的结果集浏览(src/pages/DbAdmin/ResultTable.tsx,SQL 工作台与表数据 tab 共用)不适用上述 DataTable 规范:列多、行长、需要看列类型与排序态,按数据库客户端密度设计,不要按通用规范"统一"它。

属性规格
表头多行式最多三行按需渲染:列名行(text-xs font-semibold text-foreground + 排序方块 size-4,未排灰色双箭头,激活 bg-primary 白箭头)/ 类型行(font-mono text-[10px],按类型族着色,见 shared.ts::TYPE_TEXT_CLASS)/ 注释行(text-[10px] text-muted-foreground,非等宽——中文在 mono 下发虚;长注释 truncate + hover 由 tooltip 补全)。缺哪行省哪行:无类型无注释时退化为单行 29px,全齐约 57px
注释放行判据统一走 shared.ts::columnComment():trim 后非空、且不等于列名才显示(中文字段名表里「注释 == 列名」很常见,重复印一遍纯属噪音)。表头 / tooltip / 列设置面板 / 转置视图四处同源,不各写一遍
来源注释来自 POST /dbadmin/query 的表元数据补齐(仅简单 SELECT 的指名列表/星号;别名/UNION 等无源列查询不返回 type/comment,表头如实退化)
表头底色bg-muted(比表体 bg-background 略深),sticky top-0 吸顶
列间分隔border-r border-border/60 形成竖线栅格
行高h-7(28px),单元格 font-mono text-xs,数值列 text-right(ResultColumn.numeric 或 isNumericType(col.type) 判定,不按值猜)
布局契约结果区 flex min-h-0 flex-col 铺满剩余高度,滚动发生在表格容器内部(sticky 表头才有意义);结果面板自身不滚动

4.4 筛选栏 (FilterBar)​

<FilterBar title="筛选条件">
<FilterSelect
label="市场"
options={marketOptions}
value={market}
onChange={setMarket}
/>
<FilterSelect
label="行业"
options={industryOptions}
value={industry}
onChange={setIndustry}
/>
<FilterBar.Divider />
<FilterSelect
label="排序"
options={sortOptions}
value={sort}
onChange={setSort}
/>
</FilterBar>

统一规格:

属性值
容器内边距px-6 py-2.5
控件间距gap-2(8px)
控件高度(标准)h-7(28px)
控件高度(紧凑)h-6(24px)
标签字号text-xs text-muted-foreground

规则:

  • 标准场景使用 h-7(sm)
  • 空间紧凑时使用 h-6(xs)
  • 不使用其他高度值

4.5 按钮 (Button)​

变体 (Variants)​

变体用途示例
default主操作提交、保存
secondary次要操作取消、返回
outline边框按钮更多操作
ghost幽灵按钮工具栏图标按钮
destructive危险操作删除
link链接样式跳转

尺寸 (Sizes)​

尺寸高度用途
smh-8(32px)标准按钮
defaulth-9(36px)表单提交
lgh-10(40px)主要 CTA
iconh-8 w-8图标按钮

规则:

  • 同一操作区,按钮尺寸保持一致
  • 主操作使用 default 变体,每页不超过 2 个
  • 图标按钮使用 ghost + icon 尺寸

4.6 徽章 (Badge)​

变体​

变体用途样式
default默认标签bg-primary text-primary-foreground
secondary次要标签bg-secondary text-secondary-foreground
outline边框标签border text-foreground
success成功bg-success/10 text-success
warning警告bg-warning/10 text-warning
destructive错误bg-destructive/10 text-destructive
up涨bg-up/10 text-up
down跌bg-down/10 text-down

规格:

  • 圆角:rounded-md(6px)
  • 内边距:px-2 py-0.5
  • 字号:text-xs

4.7 表单 (Form)​

布局​

<form className="space-y-4">
<div className="space-y-2">
<Label htmlFor="field">字段名</Label>
<Input id="field" placeholder="请输入" />
</div>

<div className="flex items-center gap-3">
<Button type="submit">提交</Button>
<Button type="button" variant="secondary">取消</Button>
</div>
</form>

规格:

  • 表单项间距:space-y-4(16px)
  • 标签与输入框间距:space-y-2(8px)
  • 按钮组间距:gap-3(12px)

输入框 (Input)​

属性值
高度h-9(36px)
内边距px-3 py-2
圆角rounded-control(9px)
边框border border-input
焦点focus:ring-2 focus:ring-primary/20

日期选择 (DatePicker / DateRangePicker)​

日期输入一律用日期选择器(禁止裸 <input> 或手输 YYYY-MM-DD 文本输入), 视觉对齐 shadcn v4 date-picker(Popover + Calendar,月/年下拉标题;项目未引入 react-day-picker 依赖,日历由自研 ui/calendar.tsx 实现):

  • 单日:<DatePicker>(src/components/ui/date-picker.tsx)
  • 区间:<DateRangePicker>(src/components/ui/date-range-picker.tsx,presets 可加「近 N 天」快捷侧栏)
属性说明
value / from+toYYYY-MM-DD 字符串或 null(null 语义由调用方定:如涨停板=恢复自动、回溯面板=回到最新)
onChange单日 (date: string | null)(再点已选日期=取消选择);区间 (from, to)
min / max可选日期边界(如回溯面板限定最早~最新快照日)
clearable单日弹层底部「清空」按钮(仅 value 非空时显示)
className透传触发按钮;默认紧凑档 h-8 text-xs(区间为 h-7 text-[11px])

尺寸档位:筛选条/工具栏用默认紧凑档;表单内与相邻 Input 同高同宽 (如 className="h-auto w-full rounded-xl px-3 py-2 text-sm",rounded-xl 在 级联中晚于 Button 基类 rounded-control,直接写即可覆盖,无需 !)。

4.8 板块分类卡片骨架 (SectorClassCard)​

板块中心多种分类视图(东财行业+概念 / 申万一二级 / 同花顺行业)共享统一卡片骨架 src/components/sector/SectorClassCard.tsx,通过插槽注入差异数据。

<SectorClassCard
name="半导体"
badge="行业"
code="BK0491"
pct={2.35}
rightMetric={<>成交 123.45亿</>}
action={<StarIcon />} // 操作区(与 chevron 互斥)
// chevron // 或详情跳转箭头
onClick={() => navigate(...)}
>
{/* 扩展区:涨跌家数 / 价格位置分位条 / 成交占比等 */}
</SectorClassCard>

视觉规格:

元素样式
容器glass-card rounded-2xl p-3.5
悬停hover:-translate-y-0.5 hover:border-primary/40 hover:shadow-mac
名称text-sm font-semibold
徽标text-[9px] bordered label (rounded border border-border/60 bg-muted/30 px-1 py-0.5)
代码text-[10px] tabular-nums
涨跌幅text-xl font-bold leading-none tabular-nums + pctTone 语义色
右侧指标text-[11px] tabular-nums text-muted-foreground
扩展区border-t border-border/40 pt-2 space-y-1.5

规则:

  • 新增板块分类视图必须使用 SectorClassCard 骨架,不另起内联布局
  • 同花顺行业因 master-detail 交互保留列表行(ThsIndustryPanel.RankRow),但字号/间距/徽标与骨架对齐
  • action 与 chevron 互斥:收藏场景用 action,详情跳转用 chevron

五、页面类型对照表​

5.1 全量页面分类​

页面路由类型当前问题优化动作
Home/E自定义布局保持
Analysis/analysis/:codeD—保持
SmartPick/rule-pickB—✅ 已添加 PageHeader(挂可信度徽章 + 数据体检入口卡)
Screener/screenerB—✅ 已添加 PageHeader
Favorites/favoritesB原生 table✅ 已添加 PageHeader;待迁移 DataTable
MarketCenter/market-centerB原生 table + 手写虚拟滚动待迁移 VirtualTable
EtfCenter/etf-centerB原生 table待迁移 DataTable
Zhangtingban/zhangtingbanA—保持(Type A 标准内容页)
FactorPick/factor-pickB—✅ 已添加 PageHeader(flush 置顶)
PatternSelect/patternsB—✅ 已添加 PageHeader(flush 置顶)
EarningsWindow/earningsB—✅ 已添加 PageHeader(flush 置顶)
Backtest/backtestA—保持
NlPick/nl-pickA—保持
GlobalMarket/global-marketA—✅ 已改为 2200px
DataTrustCenter/data-trustA—✅ 新建页,Type A 规格(p-5 / 2200px);5 区块:可信度评分 / 数据源目录 / 源状态 / 新鲜度 / 降级时间线 / 主动探测
Notifications/notificationsA—保持
LimitUpReason/limit-up-reasonA—保持
NewsRadar/news-radarA—保持
HotTrending/hot-trendingB—✅ 已添加 PageHeader
MonitorCenter/monitor-centerB—✅ 已添加 PageHeader
ThesisTracker/thesisB—保持
CatalystCalendar/catalystB—保持
TradeJournal/trade-journalA—保持
ConvertibleBond/bondsA—保持
Debate/rule-pick/debateA卡片内边距不一致(p-4/p-5 混用)统一 p-5
ChokepointSelect/chokepointB—✅ 已添加 PageHeader(flush 置顶)
TrendDiscovery/trend-discoveryD—✅ 已添加 PageHeader(flush 置顶)
RealtimeMarket/realtimeD—保持
MorningNote/morning-note自定义双面板布局保持
DailyReview/daily-review自定义双面板布局保持
DimensionAnalysis/dimension/:dimKey自定义卡片内边距不一致(p-4/p-6 混用)统一
SectorCenter/sector-centerA—✅ 板块分类卡片统一为 SectorClassCard 骨架(东财行业+概念 / 申万一二级 / 同花顺行业)
GlobalMacro/global-macro薄包装—保持
PolicyRates/policy-rates薄包装—保持
TacticSignals/tacticsB—✅ 已添加 PageHeader(flush 置顶)
PositionCenter/position-centerC—✅ 已添加 PageHeader
PatternSimilarity/pattern-similarityC—保持
FinancialDetail/analysis/:code/financeC—✅ 已统一 p-6
EtfDetail/etf/:codeC—✅ 已统一 p-6
IndexDetail/index-detail/:codeC—✅ 已统一 p-6
IndexConstituents/index-constituents/:codeC—保持
SectorDetail/sector-center/:codeC—保持
ConceptDetail/sector-center/concept/:codeC—保持
IndustryDetail/sector-center/sw/:system/:codeC—保持
NewsDetail/news/:source/:newsKeyC—保持
StockModuleDetail/analysis/:code/module/:moduleC—✅ 已统一 p-6
Checklist/checklist/*C—保持
SmartPickDetail/rule-pick/:strategyIdB—保持
LimitLadder/limit-ladderA—保持
CrowdingDetail/crowding-detailE—✅ 已统一 p-6
AnnualHeatmapDetail/annual-heatmap-detailE—✅ 已统一 p-6
MarketTreemap/market-treemapE—保持
Auction/auctionA—保持
AIChat/ai-chat自定义聊天界面保持
DataManager/datamgr管理—保持
DbAdmin/dbadmin管理—保持
TaskCenter/tasks管理—保持
Settings/settings/*管理—保持

5.2 优化优先级​

优先级任务影响页面数工作量
P0原生 <table> 迁移到 DataTable/VirtualTable3中
P1添加 PageHeader 到缺失页面~10小
P1统一卡片内边距(消除同页多种 padding)3小
P2统一页面内边距(p-5 / p-6)全部中
P2统一区块间距(space-y-5)全部小
P2内容宽度从 1920px 提升到 2200px全部小
P3glass-card 圆角统一为 rounded-2xl~15小

六、实施计划​

Phase 1:基础设施(1~2 天)​

任务文件说明
1.1 扩展 PageHeader 组件src/components/ui/page-header.tsx增加更多 slots
1.2 统一 Table 原语样式src/components/ui/table.tsx表头、行高、悬停
1.3 统一 DataTable 样式src/components/ui/data-table.tsx标准/紧凑模式
1.4 更新内容宽度常量src/components/ui/detail-page.tsx1920px → 2200px

Phase 2:页面迁移(3~5 天)​

优先级页面改动状态
P0MarketCenter原生 table → VirtualTable⏳ 待办
P0EtfCenter原生 table → DataTable⏳ 待办
P0Favorites原生 table → DataTable⏳ 待办(PageHeader 已完成)
P1Screener, SmartPick, HotTrending, MonitorCenter, PositionCenter添加 PageHeader✅ 已完成
P1FactorPick, PatternSelect, EarningsWindow, ChokepointSelect, TacticSignals添加 PageHeader(flush 置顶)✅ 已完成
P1Zhangtingban添加 PageHeader⏳ 待办
P1DimensionAnalysis, Debate统一卡片内边距⏳ 待办
P2FinancialDetail, StockModuleDetail, IndexDetail, EtfDetail, CrowdingDetail, AnnualHeatmapDetail统一 p-6 + space-y-4✅ 已完成
P2GlobalMarketmax-w-[1600px] → max-w-[2200px]✅ 已完成
P2所有标准内容页统一 p-5 + space-y-5⏳ 待办
P3所有 glass-cardrounded-xl → rounded-2xl⏳ 待办

Phase 3:验证(1 天)​

任务说明
视觉走查逐页面对比,确认一致性
响应式测试1280px / 1920px / 2560px 三档
更新文档将规范写入 AGENTS.md

七、速查表​

┌─────────────────────────────────────────────────────────────────┐
│ 页面布局规范速查 │
├─────────────────────────────────────────────────────────────────┤
│ 内容宽度 w-[98%] max-w-[2200px] │
│ 页面内边距 p-5(标准)/ p-6(详情页) │
│ 区块间距 space-y-5(默认)/ space-y-3(卡片内) │
│ 页面头部 PageHeader 组件(必须) │
│ 卡片圆角 rounded-2xl(glass-card 统一) │
│ 卡片内边距 p-5(标准)/ p-4(紧凑)/ p-6(宽松) │
│ 表格单元格 px-3 py-2(标准)/ px-2 py-1.5(紧凑) │
│ 表格行高 h-10(标准)/ h-8(紧凑) │
│ 筛选栏 FilterBar + FilterSelect,gap-2 │
│ 控件圆角 rounded-control(9px) │
│ 控件高度 h-9(输入框)/ h-7(FilterSelect)/ h-8(Button) │
│ 移动端断点 md: 以下(<768px),JS 用 useIsMobile() │
│ 移动端标题 长标题(≥7字)且右侧有内容 → short 模式 │
│ 移动端表格 overflow-x-auto + min-w-[520px] 横向滚动 │
│ 移动端抽屉 fixed w-80 max-w-[85vw] + translate-x 过渡 │
└─────────────────────────────────────────────────────────────────┘

八、参考资源​

资源链接说明
shadcn/uihttps://ui.shadcn.com组件设计参考
Ant Design 5.xhttps://ant.design间距、排版参考
Tailwind CSShttps://tailwindcss.com工具类文档
Tailwind CSS 4https://tailwindcss.com/docs本项目使用版本

九、移动端适配​

适用视口:小于 768px(手机竖屏为主,参考 390×844,内容宽 ≈358px)。 桌面优先的布局规范在手机上按本节降级;只改视觉与布局,不改变数据流与功能逻辑。

9.1 断点约定​

手段值说明
CSS 断点md:(768px)以下视为移动端Tailwind 默认断点,统一以 md 为界,不引入自定义断点
JS 判定useIsMobile()(src/hooks/useIsMobile.ts)matchMedia (max-width: 767px) + 事件驱动;轻量场景可用同文件 useMediaQuery(query)
参考视口390×844手机竖屏;设计时按内容宽 ≈358px 校验

选择规则:

  • 纯样式差异(宽度、列数、间距)优先用 md: 前缀——无 JS、无二次渲染、SSR 友好;
  • 需要结构差异(挂载/卸载、双布局只渲染其一、条件传参)才用 useIsMobile();
  • 两个分支必须互斥且各只挂载一份,避免重复请求与重复监听。

9.2 卡片标题 short 模式​

共享组件 SectionTitle(src/components/market/dashboard/primitives.tsx)与 DataModuleHeader(src/components/ui/data-module-header.tsx)支持 short?: string:

<SectionTitle title="指数年度涨跌热力图" short="年度涨跌热力图" />
<DataModuleHeader title="阶段涨跌幅" short="阶段涨跌" hint="近 5 日区间收益" />
  • 组件内部自行调用 useIsMobile():移动端渲染 short,桌面端渲染 title,调用方不做任何判断;
  • short 由人工甄选核心语义,不是自动截断(例:阶段涨跌幅→阶段涨跌、指数年度涨跌热力图→年度涨跌热力图)。

甄选规则(需同时满足 1+2):

条件说明
① 标题 ≥7 个显示字符短标题(≤6 字)移动端放得下,不动
② 与右侧内容共享一行右侧有 hint/action/extra 挤压标题时才降字;独占整行的静态 h2/h3 跳过,即使 9~12 字
— 动态标题跳过{card.name}、{activeTab.label} 等运行时取值无法人工甄选

9.3 网格与表格​

  • KPI/统计网格降列:grid-cols-2 sm:grid-cols-3 md:grid-cols-4(移动端两列起步,桌面恢复完整列数)。
  • 宽表格不缩列、不换行:外包 overflow-x-auto,给表格容器显式最小宽度(min-w-[520px] / min-w-[640px],按表格实际列数定),移动端横向滚动查看。
  • 🔴 禁止在移动端隐藏表格列来「适配」——列的取舍是信息设计问题,横向滚动是布局问题,后者才是移动端的正解。

9.4 抽屉模式(移动端侧栏)​

参考实现:src/pages/MorningNote.tsx(配置面板)。

{/* 触发按钮:仅移动端显示 */}
<Button variant="outline" size="icon" className="h-8 w-8 md:hidden"
onClick={() => setConfigOpen(true)}>
<Settings2 className="h-3.5 w-3.5" />
</Button>

{/* 遮罩 */}
{configOpen && (
<div
className="fixed inset-x-0 bottom-0 top-[56px] z-40 bg-black/40 backdrop-blur-sm md:hidden"
onClick={() => setConfigOpen(false)}
/>
)}

{/* 抽屉面板:fixed + transform 过渡 */}
<aside
className={cn(
"fixed bottom-0 left-0 top-[56px] z-50 flex w-80 max-w-[85vw] flex-col border-r border-border bg-card transition-transform duration-300 ease-out md:hidden",
configOpen ? "translate-x-0" : "-translate-x-full"
)}
>
{configPanel}
</aside>

规格:

元素样式
面板fixed bottom-0 left-0 top-[56px] z-50 w-80 max-w-[85vw] + transition-transform duration-300
遮罩z-40 bg-black/40 backdrop-blur-sm,点击关闭
开合translate-x-0 / -translate-x-full 切换,关着也要挂载(保留过渡动画)
滚动锁定打开时锁定背景滚动,关闭恢复
桌面端同一内容走原侧栏布局,与 md:hidden 分支互斥

9.5 搜索框与下拉面板​

  • 标题栏搜索框宽度分档:w-28 sm:w-48 xl:w-56 2xl:w-64 3xl:w-72(移动端收窄,给图标区让位)。
  • StockSearch 下拉面板移动端不走窄面板:改视口级全宽 fixed inset-x-2 top-[60px],桌面仍 absolute right-0 mt-2 w-[340px] max-w-[calc(100vw-2rem)]。
  • fixed 面板仍渲染在 containerRef 内,外点关闭的 contains 判定不受影响。
  • 下拉仅在有内容时渲染(历史/关键词/结果三者其一非空),空关键词聚焦不弹空面板。

9.6 其他​

场景规则
K线图高度移动端 280px(桌面保持原有更大高度),useIsMobile() 条件传参
Dialog移动端 max-w-[calc(100vw-2rem)],不超视口
双布局页面Analysis 等页面移动端/桌面两套布局只挂载其一
触控目标可点击控件 ≥ 32px(h-8),避免纯 24px 图标热区

本规范由 AI 辅助生成,经人工审核后生效。如有疑问或建议,请联系开发团队。

相关文档​