feat(web): 完成响应式工作台原型设计
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
{"file":".trellis/spec/frontend/directory-structure.md","reason":"检查原型没有污染生产 feature 边界,目标 layout 设计没有形成 shared → feature 反向依赖。"}
|
||||||
|
{"file":".trellis/spec/frontend/component-guidelines.md","reason":"检查语义 HTML、键盘操作、状态文案、focus 与触控交互是否完整。"}
|
||||||
|
{"file":".trellis/spec/frontend/state-management.md","reason":"检查 variant、分页、弹层和响应式状态的归属是否符合 URL/局部状态约定。"}
|
||||||
|
{"file":".trellis/spec/frontend/quality-guidelines.md","reason":"核对前端格式、lint、typecheck、test 和 build 的实际结果。"}
|
||||||
|
{"file":".trellis/spec/guides/code-reuse-thinking-guide.md","reason":"检查 layout/pagination 设计提供真实复用与 locality,没有为了形式增加浅层封装。"}
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
# 响应式前端交互体系技术设计
|
||||||
|
|
||||||
|
## 1. 设计目标
|
||||||
|
|
||||||
|
本任务先交付可交互 HTML 原型和可执行的目标架构设计,不直接重写生产页面。原型回答两个问题:
|
||||||
|
|
||||||
|
1. 暖白、炭黑、白色浮层和克制圆角能否形成适合量化研究工作台的高密度组件语言;
|
||||||
|
2. 同一套页面语义能否通过一个 layout 模块在桌面、平板和移动端形成不同但一致的交互布局。
|
||||||
|
|
||||||
|
生产实现必须等原型方案被选定后另行执行;原型代码不直接提升为生产组件。
|
||||||
|
|
||||||
|
## 2. 当前约束与证据
|
||||||
|
|
||||||
|
- `src/features/home/components/home-shell.tsx` 同时承担品牌、导航、搜索、用户入口和内容容器,并要求页面传入 `activeSection`。它位于 `home` feature,却被 `selection` feature 反向使用,说明应用壳 seam 放置不当。
|
||||||
|
- 当前窄屏只是把侧栏从 256px 缩到 80px,没有移动端主导航、底部安全区或触控密度策略。
|
||||||
|
- `SignalTable` 以 `min-width: 720px` + `overflow-x-auto` 处理窄屏,没有分页,也没有移动端信息优先级。
|
||||||
|
- Button/Input 默认 32px 高度适合桌面紧凑密度,但移动触控需单独的最小命中区域。
|
||||||
|
- 前端规范要求业务留在 feature、跨 feature 能力进入 shared/app,路由只负责映射和组合,URL 状态由 TanStack Router 承担。
|
||||||
|
- TanStack Router 官方资料确认:code-based routing 可用只有 `id`、没有 `path` 的 pathless layout route 包裹子路由,并通过 `<Outlet />` 共享应用壳;`validateSearch` 可为分页和原型 variant 提供类型化 URL 状态。
|
||||||
|
|
||||||
|
## 3. Target Architecture
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/
|
||||||
|
├── app/
|
||||||
|
│ └── layout/
|
||||||
|
│ ├── app-layout.tsx # 应用品牌、响应式主导航、工具区、Outlet
|
||||||
|
│ ├── navigation.ts # 应用级导航模型与可用状态
|
||||||
|
│ └── page-layout.tsx # 页头、操作区、内容宽度与纵向节奏
|
||||||
|
├── routes/
|
||||||
|
│ └── route-tree.tsx # pathless workspace route + child routes
|
||||||
|
├── features/
|
||||||
|
│ └── selection/
|
||||||
|
│ └── components/
|
||||||
|
│ └── signal-results.tsx # 业务列定义与移动卡片呈现
|
||||||
|
└── shared/
|
||||||
|
└── ui/
|
||||||
|
└── pagination.tsx # 无业务语义的分页 primitive
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.1 Layout seam
|
||||||
|
|
||||||
|
外部 seam 位于 pathless workspace route 与所有业务 child route 之间。路由树只挂载一次 `AppLayout`,页面不再 import 应用壳,也不再传 `activeSection`。
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const workspaceRoute = createRoute({
|
||||||
|
getParentRoute: () => rootRoute,
|
||||||
|
id: "workspace",
|
||||||
|
component: AppLayout,
|
||||||
|
});
|
||||||
|
|
||||||
|
const indexRoute = createRoute({
|
||||||
|
getParentRoute: () => workspaceRoute,
|
||||||
|
path: "/",
|
||||||
|
component: HomePage,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
`AppLayout` 的 interface 对页面保持极小:页面只作为 `<Outlet />` 内容进入。当前导航项由 Router Link 的 active 状态得出,不再由页面手工声明。
|
||||||
|
|
||||||
|
### 3.2 Page layout interface
|
||||||
|
|
||||||
|
页面仅通过稳定的页面语义描述页头,不知道断点、侧栏宽度和安全区:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
interface PageLayoutProps {
|
||||||
|
mode?: "document" | "bounded-workspace";
|
||||||
|
actions?: React.ReactNode;
|
||||||
|
metrics?: React.ReactNode;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`PageLayout` 内部集中处理:
|
||||||
|
|
||||||
|
- 视口 gutter、最大内容宽度与内容密度;
|
||||||
|
- 操作区和指标区在窄屏的换行/堆叠;
|
||||||
|
- 页面区块的紧凑纵向节奏;
|
||||||
|
- sticky header 预留和移动底部安全区;
|
||||||
|
- `bounded-workspace` 模式下的连续高度链与唯一滚动区域;
|
||||||
|
- 跳过导航链接与语义化 `<main>`。
|
||||||
|
|
||||||
|
页面不再通过 `PageLayout` 渲染独立的大标题、眉题和说明区。当前页面名称与路由上下文由 `AppLayout` 顶栏提供;`PageLayout` 的首个内容区直接承载页面操作、指标和业务数据,避免在紧凑工作台中重复表达同一上下文。
|
||||||
|
|
||||||
|
删除该模块会使上述规则重新散落到每个页面,因此它提供真实 Depth 与 Locality,而不是 className 转发层。
|
||||||
|
|
||||||
|
`document` 是普通详情页、表单页的默认模式,由应用内容区自然滚动。`bounded-workspace` 只用于表格、树表和主从研究台:`AppLayout → main → PageLayout → business panel` 连续使用确定高度、`min-height: 0` 与 Flex 剩余空间;操作区、指标、筛选栏和分页不可收缩,纵向滚动权收敛到表格数据区或详情正文。实现不得依赖 `calc(100vh - Npx)` 或 JavaScript 测量固定区域高度。
|
||||||
|
|
||||||
|
移动断点下不强制延续桌面有界模式。主从区域转为纵向单列时,`PageLayout` 恢复自然高度和页面滚动,避免记录卡、分页与底部导航之间形成嵌套滚动。
|
||||||
|
|
||||||
|
### 3.3 Navigation model
|
||||||
|
|
||||||
|
`navigation.ts` 保存应用级、只读导航模型:`id`、`label`、`to`、`icon`、`availability`。它不读取 feature 数据,也不保存当前激活项。
|
||||||
|
|
||||||
|
- Desktop(≥1024px):232px 固定侧栏;品牌、四个主入口、底部低频入口。
|
||||||
|
- Tablet(768–1023px):64px 图标 rail;标签通过 tooltip/可访问名称提供。
|
||||||
|
- Mobile(<768px):顶部只保留当前页面标题和低频操作;底部 4 项主导航,其他入口进入“更多”sheet。
|
||||||
|
- 底部导航高度 60px,并使用 `padding-bottom: env(safe-area-inset-bottom)`;页面内容 padding 同步包含该占位。
|
||||||
|
- 响应式切换以 CSS media/container rules 为主,不在 React render 中读取 `window.innerWidth`,避免双树渲染和水合差异。
|
||||||
|
|
||||||
|
## 4. Visual and Interaction Tokens
|
||||||
|
|
||||||
|
### 4.1 视觉层级
|
||||||
|
|
||||||
|
- Canvas:`#f5f1ec`,作为应用背景。
|
||||||
|
- Surface:`#ffffff`,用于卡片、表格和浮层。
|
||||||
|
- Ink:`#111111`,作为主文本和主操作颜色。
|
||||||
|
- Muted Ink:`#626260`;Hairline:`#d3cec6`。
|
||||||
|
- 不使用阴影建立常规层级;只允许 dialog、popover、prototype switcher 使用必要浮层阴影。
|
||||||
|
- `DESIGN.md` 的 Fin Orange 不进入通用主操作,因为本产品没有 Fin 语义;涨跌、成功、警告等颜色只承担数据或语义状态。
|
||||||
|
- 字体使用 Inter/system fallback;桌面工作台不采用营销页 40–72px display 字号。
|
||||||
|
|
||||||
|
### 4.2 密度
|
||||||
|
|
||||||
|
| Token | Desktop | Touch/Mobile | Usage |
|
||||||
|
| -------------- | ------: | ---------------: | -------------------------- |
|
||||||
|
| control-height | 32px | 44px | input、select、常规 button |
|
||||||
|
| icon-target | 32px | 44px | 仅图标按钮 |
|
||||||
|
| page-gutter | 24px | 16px | 主内容边距 |
|
||||||
|
| card-padding | 16px | 14px | 默认卡片 |
|
||||||
|
| table-row | 44px | 不适用 | 桌面表格行 |
|
||||||
|
| bottom-nav | 不适用 | 60px + safe area | 移动主导航 |
|
||||||
|
|
||||||
|
触控尺寸由 layout/touch capability token 控制,不要求每个页面选择 `mobile` variant。hover 样式仅在支持 hover 的设备启用;所有交互同时提供 focus-visible 和 pressed 状态。
|
||||||
|
|
||||||
|
### 4.3 组件覆盖
|
||||||
|
|
||||||
|
原型展示并验证以下状态:
|
||||||
|
|
||||||
|
- Button:primary、secondary、ghost、destructive、disabled、loading;
|
||||||
|
- Form:input、search、select、date、focus、filled、disabled;
|
||||||
|
- Badge/Status:neutral、success、warning、error;
|
||||||
|
- Card:基础、metric、empty、error;
|
||||||
|
- Overlay:确认 dialog、移动“更多”sheet、toast;
|
||||||
|
- Data:筛选工具条、桌面表格、移动记录卡、分页;
|
||||||
|
- Feedback:skeleton、空结果、请求失败、执行中、成功提示。
|
||||||
|
|
||||||
|
## 5. Responsive Data and Pagination
|
||||||
|
|
||||||
|
### 5.1 同一数据,两种呈现
|
||||||
|
|
||||||
|
`selection` feature 持有字段优先级和业务格式化:
|
||||||
|
|
||||||
|
- Desktop:列式 table,优先显示股票、子信号、收盘价、关键详情;面板消费页面剩余高度,筛选栏与分页不可收缩,表头在数据滚动区内吸顶。
|
||||||
|
- Mobile:每条信号变为紧凑记录卡;首行显示股票与价格,第二行显示信号 badge,关键详情默认折叠后按需展开。
|
||||||
|
|
||||||
|
两种呈现消费同一页数据和同一分页状态,不复制请求或业务判断。共享层不尝试理解 `SelectionSignal`。
|
||||||
|
|
||||||
|
### 5.2 Pagination interface
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
interface PaginationProps {
|
||||||
|
page: number;
|
||||||
|
pageSize: number;
|
||||||
|
total: number;
|
||||||
|
pageSizeOptions?: readonly number[];
|
||||||
|
onPageChange: (page: number) => void;
|
||||||
|
onPageSizeChange: (pageSize: number) => void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
分页 primitive 负责总数、当前范围、页码、上一页/下一页、每页数量、禁用和 aria 文案;feature 负责数据切片或 query 参数。
|
||||||
|
|
||||||
|
首版生产迁移可对当前已加载 `signals` 使用客户端分页,`page`/`pageSize` 使用 selection route 的 validated search params,使链接可复现。若真实数据规模要求服务端分页,保持 Pagination interface 不变,只替换 feature 内数据 adapter。
|
||||||
|
|
||||||
|
## 6. HTML Prototype
|
||||||
|
|
||||||
|
### 6.1 Artifact shape
|
||||||
|
|
||||||
|
- 文件:`zhixing-web/prototypes/responsive-workbench.html`。
|
||||||
|
- 单文件 HTML/CSS/JS,无后端、无 CDN、无持久化,双击即可运行。
|
||||||
|
- 通过 `?variant=a|b|c` 分享方案;底部浮动切换器支持按钮和左右方向键。
|
||||||
|
- 增加 Desktop/Mobile 预览切换,同时保留真实 media query,便于无需开发者工具评审。
|
||||||
|
- 使用内存 mock 数据演示搜索、筛选、分页、page size、dialog、sheet、toast 和折叠详情。
|
||||||
|
|
||||||
|
### 6.2 Three structural variants
|
||||||
|
|
||||||
|
1. **A — 紧凑工作台**:完整侧栏 + 轻量工具栏 + 分区卡片;默认推荐,迁移成本最低。
|
||||||
|
2. **B — 数据账本**:窄图标 rail + 表格主画布 + 吸顶筛选/操作条;信息密度最高,但首次理解成本更高。
|
||||||
|
3. **C — 主从研究台**:导航侧栏 + 结果列表/详情双栏;适合研究钻取,但在简单页面上占用更多结构。
|
||||||
|
|
||||||
|
三者必须改变信息层级与主操作位置,不能只改变颜色。移动端都遵循已确认的底部导航,但分别比较页头、筛选和记录详情的收纳方式。
|
||||||
|
|
||||||
|
### 6.3 Selected direction
|
||||||
|
|
||||||
|
用户选定 A+C 组合:保留 A 的完整工作台侧栏、顶栏和紧凑指标区,引入 C 的结果列表/研究详情双栏。原型默认打开该组合;A、B 仅保留为对比参考。
|
||||||
|
|
||||||
|
内容区不再渲染页面大标题、眉题或说明文案。操作按钮以紧凑 action row 呈现,其后立即进入指标与数据区域;移动端沿用同一信息顺序。
|
||||||
|
|
||||||
|
业务页面不展示用于设计评审的“状态语义 / 加载反馈”样例区。状态组件仍可在独立组件预览弹窗中评审;实际页面只在对应请求状态发生时就地呈现 loading、empty 或 error 反馈。
|
||||||
|
|
||||||
|
## 7. State and Data Flow
|
||||||
|
|
||||||
|
```text
|
||||||
|
URL route/search
|
||||||
|
├─ active route ──> AppLayout navigation presentation
|
||||||
|
├─ page/pageSize ─> selection feature pagination state
|
||||||
|
└─ variant ───────> prototype-only variant renderer
|
||||||
|
|
||||||
|
Query data ──> feature view model ──> current page slice
|
||||||
|
├─ desktop table
|
||||||
|
└─ mobile record cards
|
||||||
|
```
|
||||||
|
|
||||||
|
- 响应式视口不是业务状态,不进入 Zustand。
|
||||||
|
- 服务器结果继续由 TanStack Query 管理,不复制进 layout 或 UI store。
|
||||||
|
- 移动“更多”sheet、dialog、展开行属于局部瞬时状态。
|
||||||
|
- 原型 state 全部保存在内存或 URL,不写 localStorage。
|
||||||
|
|
||||||
|
## 8. Compatibility, Rollout, and Rollback
|
||||||
|
|
||||||
|
- 本任务只新增原型和规划文档,不改变现有路由、API 或生产 bundle。
|
||||||
|
- 原型选型后,生产迁移按“pathless layout → 首页 → selection 页面 → shared pagination”的顺序进行,每步保持路由 URL 不变。
|
||||||
|
- `HomeShell` 在所有页面迁移完成前保留;最终一次性删除,避免两套壳长期并存。
|
||||||
|
- 若新 layout 出现回归,可将 child routes 的 parent 恢复为 root route,并恢复页面外层 `HomeShell`,不涉及数据回滚。
|
||||||
|
|
||||||
|
## 9. Risks and Deferred Items
|
||||||
|
|
||||||
|
- `DESIGN.md` 源自营销站分析,若直接套用会造成工作台留白和字号过大;原型明确以数据密度重新校准。
|
||||||
|
- 当前 signals API 返回完整列表,客户端分页只改善渲染与浏览,不降低传输量;服务端分页在数据规模证明确有需要后单独设计。
|
||||||
|
- 生产 dark mode、表格排序/列配置、虚拟滚动、离线支持不在本任务范围。
|
||||||
|
- 原型为 throwaway code;选中方案必须按生产质量重新实现并补测试,不能直接复制粘贴上线。
|
||||||
|
|
||||||
|
## 10. Research References
|
||||||
|
|
||||||
|
- [TanStack Router routing concepts](https://github.com/tanstack/router/blob/main/docs/router/routing/routing-concepts.md)
|
||||||
|
- [TanStack Router code-based routing](https://github.com/tanstack/router/blob/main/docs/router/routing/code-based-routing.md)
|
||||||
|
- [TanStack Router search params](https://github.com/tanstack/router/blob/main/docs/router/guide/search-params.md)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{"file":".trellis/spec/frontend/index.md","reason":"实现原型前确认前端技术栈、feature 边界和完整质量入口。"}
|
||||||
|
{"file":".trellis/spec/frontend/directory-structure.md","reason":"保持 app layout、shared UI 与 feature 业务呈现的依赖方向,避免把业务逻辑放入 shared。"}
|
||||||
|
{"file":".trellis/spec/frontend/component-guidelines.md","reason":"原型和后续设计遵循语义元素、可访问性、组合与现有样式约定。"}
|
||||||
|
{"file":".trellis/spec/frontend/state-management.md","reason":"将 URL、服务器、跨页偏好与局部交互状态放在正确位置,不以 Zustand 保存视口或请求数据。"}
|
||||||
|
{"file":".trellis/spec/frontend/quality-guidelines.md","reason":"执行格式、lint、类型、测试与构建门禁,确认原型未破坏现有应用。"}
|
||||||
|
{"file":".trellis/spec/guides/code-reuse-thinking-guide.md","reason":"仅抽取有真实跨 feature 复用价值的 layout/pagination interface,避免新建浅 helper。"}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
# 响应式前端交互体系执行计划
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
本任务只实现可评审的单文件 HTML 原型,并完成目标 layout 架构设计;不改生产 React 页面、路由或后端。原型选型后的生产迁移另开任务。
|
||||||
|
|
||||||
|
## Ordered Checklist
|
||||||
|
|
||||||
|
### 1. 建立原型骨架
|
||||||
|
|
||||||
|
- [x] 新增 `zhixing-web/prototypes/responsive-workbench.html`,顶部注释明确标注 THROWAWAY PROTOTYPE 与验证问题。
|
||||||
|
- [x] 定义颜色、字体、间距、圆角、控件密度、触控尺寸和安全区 CSS variables。
|
||||||
|
- [x] 加入 `?variant=a|b|c` 路由状态、浮动方案切换器和 Desktop/Mobile 预览切换。
|
||||||
|
- [x] 让真实 viewport media query 与强制预览模式得到相同行为。
|
||||||
|
|
||||||
|
### 2. 实现三个结构方案
|
||||||
|
|
||||||
|
- [x] A「紧凑工作台」:完整侧栏、工具栏、分区卡片与分页表格。
|
||||||
|
- [x] B「数据账本」:图标 rail、吸顶筛选、以表格为主画布。
|
||||||
|
- [x] C「主从研究台」:结果列表与详情面板并置。
|
||||||
|
- [x] 验证三者在信息层级、主操作位置和数据钻取方式上有实质差异。
|
||||||
|
- [x] 三个方案的移动端均使用 4 项底部导航 + 更多 sheet,并留出 safe-area 空间。
|
||||||
|
|
||||||
|
### 3. 补齐组件和交互状态
|
||||||
|
|
||||||
|
- [x] 展示按钮、表单、badge、card、feedback、overlay 和 data patterns。
|
||||||
|
- [x] 使用 mock signals 实现搜索、筛选、分页、每页数量与记录范围。
|
||||||
|
- [x] 桌面呈现 table,移动端呈现优先级重排后的记录卡及折叠详情。
|
||||||
|
- [x] 实现确认 dialog、更多 sheet、toast 和 loading/disabled/empty/error 示例。
|
||||||
|
- [x] 支持键盘方向键切换 variant,且输入框聚焦时不劫持按键。
|
||||||
|
|
||||||
|
### 4. 可访问性与响应式检查
|
||||||
|
|
||||||
|
- [x] 使用 nav/main/table/button/dialog 等语义元素和清晰 aria label。
|
||||||
|
- [x] 键盘可完成导航、筛选、分页、开关弹层与关闭弹层。
|
||||||
|
- [x] 检查 1440×900、1280×800、768×1024、390×844、375×812。
|
||||||
|
- [x] 移动端无页面级水平溢出,底部导航不遮挡内容,触控目标 ≥44px。
|
||||||
|
- [x] 验证 reduced-motion 下关闭非必要动画。
|
||||||
|
|
||||||
|
### 5. 评审交付
|
||||||
|
|
||||||
|
- [x] 输出三个可分享 URL:`?variant=a`、`?variant=b`、`?variant=c`。
|
||||||
|
- [x] 截取三种方案的桌面与移动端画面作为视觉验证证据。
|
||||||
|
- [x] 记录每个方案的适用场景和明确取舍,等待用户选择或混合方案。
|
||||||
|
- [x] 不把原型代码直接迁入生产模块。
|
||||||
|
|
||||||
|
## Validation Commands
|
||||||
|
|
||||||
|
在 `zhixing-web/` 下执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm exec prettier --check prototypes/responsive-workbench.html
|
||||||
|
pnpm check
|
||||||
|
pnpm build
|
||||||
|
```
|
||||||
|
|
||||||
|
浏览器验证:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m http.server 4173 -d zhixing-web
|
||||||
|
```
|
||||||
|
|
||||||
|
随后使用真实浏览器逐一检查三个 variant 的桌面/移动截图、URL 刷新稳定性、分页、page size、dialog、更多 sheet、键盘切换和水平溢出。
|
||||||
|
|
||||||
|
## Risky Files and Rollback Points
|
||||||
|
|
||||||
|
- `zhixing-web/prototypes/responsive-workbench.html` 是唯一产品目录新增物;删除该文件即可完全回滚运行时影响。
|
||||||
|
- `.trellis/tasks/08-09-responsive-frontend-design/` 只记录规划与验证,不进入生产 bundle。
|
||||||
|
- 本任务不得修改 `src/routes/route-tree.tsx`、`HomeShell`、shared UI 或 API 类型;若实现中发现必须修改,应回到规划并请求扩展范围。
|
||||||
|
|
||||||
|
## Review Gates
|
||||||
|
|
||||||
|
- [x] 原型三个方案均可运行且结构差异明显。
|
||||||
|
- [x] PRD 中所有验收标准均有对应验证证据。
|
||||||
|
- [x] `design.md` 的 layout seam 与现有 feature 依赖方向一致。
|
||||||
|
- [x] 检查未修改现有未提交变更或扩大到生产重构。
|
||||||
|
- [x] 用户看过最终规划摘要并在后续消息中明确批准开始实现。
|
||||||
|
|
||||||
|
## Validation Results
|
||||||
|
|
||||||
|
- `pnpm exec prettier --check prototypes/responsive-workbench.html`:通过。
|
||||||
|
- `pnpm lint`:通过。
|
||||||
|
- `pnpm typecheck`:通过。
|
||||||
|
- `pnpm test`:通过,3 个测试文件、16 项测试。
|
||||||
|
- `pnpm build`:通过。
|
||||||
|
- `pnpm check`:未完整运行;在第一步被用户新增且未格式化的 `zhixing-web/DESIGN.md` 拦截,本任务未修改该文件。其余子门禁已分别通过。
|
||||||
|
- Playwright:A/B/C 三方案在 1440×900、1280×800、768×1024、390×844、375×812 下检查通过;移动端 `body.scrollWidth === viewport width`,底部导航命中高度 50px。
|
||||||
|
- Playwright:分页 1–5 → 6–10、page size、搜索空状态、移动记录展开、更多 sheet、确认 dialog、toast、URL variant、方向键切换、Esc 关闭、Tab/Shift+Tab 焦点循环均验证通过;浏览器控制台 0 error / 0 warning。
|
||||||
|
|
||||||
|
## Selected Direction Follow-up
|
||||||
|
|
||||||
|
- [x] 将默认方案调整为 A 工作台壳 + C 研究详情面板。
|
||||||
|
- [x] 删除内容区大标题、眉题和说明模块,仅保留紧凑操作行。
|
||||||
|
- [x] 验证桌面与移动端内容均直接从操作、指标和业务数据开始。
|
||||||
|
|
||||||
|
Follow-up validation:默认无 query 时渲染 `variant-ac`;桌面 1440px 与移动 390px 均不存在 `.page-header` 或 `main h1`,内容顺序为 action row → metrics → A+C master-detail data;移动端无水平溢出,浏览器控制台 0 error / 0 warning。
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# 设计响应式前端交互体系
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
为知行量化建立一套可持续扩展的前端组件风格、交互风格和响应式布局体系,使高密度研究工作台在桌面端保持紧凑高效,在移动端仍可清晰导航、查询数据并完成关键操作;通过可交互 HTML 原型先验证视觉方向与布局行为,再进入生产实现。
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
- `zhixing-web/DESIGN.md` 给出了暖白画布、炭黑主色、白色浮层卡片、细边框、克制圆角和 Inter/Geist 替代字体等视觉方向;其原始参考偏营销页面,本任务需要将其收敛为高密度数据工作台语言。
|
||||||
|
- 当前应用为 React 19 + TypeScript + Vite,使用 TanStack Router、TanStack Query、Zustand、Tailwind CSS 4 与 Base UI;代码采用 feature 垂直切片,共享 UI 位于 `src/shared/ui/`。
|
||||||
|
- `zhixing-web/src/features/home/components/home-shell.tsx` 直接承载侧栏、顶栏和内容容器,且归属 `home` feature;窄屏仍保留 80px 侧栏,没有面向触控设备的独立导航模式。
|
||||||
|
- `zhixing-web/src/features/selection/pages/selection-results-page.tsx` 的信号表设置 `min-width: 720px` 并依赖横向滚动,当前没有分页。
|
||||||
|
- `zhixing-web/src/shared/ui/button.tsx` 与 `input.tsx` 的默认控件高度为 32px,适合紧凑桌面界面,但不足以直接作为移动端触控规格。
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### R1. 统一视觉与组件语言
|
||||||
|
|
||||||
|
- 将 `DESIGN.md` 的视觉方向转译为适合量化研究工作台的设计 token 和组件规范。
|
||||||
|
- 覆盖按钮、输入框、选择器、标签、卡片、表格、分页、弹窗、提示反馈、空状态、加载状态与错误状态。
|
||||||
|
- 桌面布局保持紧凑,但不能以牺牲信息层级、键盘操作或可读性为代价。
|
||||||
|
- 移动端交互控件采用适合触控的命中区域,不能机械复用桌面端 32px 高度。
|
||||||
|
|
||||||
|
### R2. 响应式 Layout
|
||||||
|
|
||||||
|
- 将应用壳从 `home` feature 中抽离为跨 feature 的 layout 模块,页面不得各自实现断点和导航切换逻辑。
|
||||||
|
- layout 的 interface 只暴露页面需要声明的稳定信息,例如页面标题区、页面操作区与内容;激活导航由路由状态推导,断点、导航形态、内容宽度、滚动策略、移动安全区和触控适配留在实现内部。
|
||||||
|
- 桌面端支持高密度侧栏 + 顶部工具区 + 有最大宽度的内容区。
|
||||||
|
- 移动端使用底部导航承载四个核心入口,低频功能进入“更多”菜单;同时提供紧凑标题区、内容单列化与底部安全区处理。
|
||||||
|
- 页面内容在布局切换时保持功能与语义一致,不维护两套业务页面。
|
||||||
|
- 业务页面不重复展示大标题、眉题和说明模块;当前页面上下文由应用顶栏承担,内容区直接展示操作、指标与业务数据。
|
||||||
|
- 桌面数据工作台采用有界布局:从应用壳到业务数据区连续传递可用高度,页面外层不参与纵向滚动;移动端解除有界高度,恢复自然页面滚动。
|
||||||
|
|
||||||
|
### R3. 表格与分页
|
||||||
|
|
||||||
|
- 数据表格提供可理解的总数、当前范围、页码和每页数量交互。
|
||||||
|
- 桌面端保留列式高密度浏览;移动端为关键信息设计专门呈现策略,而非仅依赖横向滚动。
|
||||||
|
- 桌面表格消费操作区、指标区之后的全部剩余高度,仅数据行视口滚动;筛选栏、表头和分页保持可见,分页固定在数据面板底部。
|
||||||
|
- 分页控件同时支持鼠标、键盘和触控,并清楚表达禁用、当前页及加载状态。
|
||||||
|
- 首版原型使用内存数据演示分页;生产实现是否采用服务端分页由后续数据规模和接口契约决定。
|
||||||
|
|
||||||
|
### R4. HTML 交互原型
|
||||||
|
|
||||||
|
- 提供无需后端即可运行或直接打开的 HTML 原型。
|
||||||
|
- 原型至少包含桌面与移动视口切换、主导航、代表性研究页、表格分页以及关键组件状态。
|
||||||
|
- 原型用于评审设计,不作为生产代码直接合入正式路由。
|
||||||
|
- 原型要能展示布局状态和当前交互状态,使评审者看得见导航、分页、弹窗等行为变化。
|
||||||
|
|
||||||
|
### R5. 架构落点
|
||||||
|
|
||||||
|
- 应用级布局归入 `app/layout`,无业务语义的 UI primitive 归入 `shared/ui`;业务页面与业务数据呈现留在各自 feature。
|
||||||
|
- layout 模块应形成高杠杆的 interface:删除它会使响应式、导航和滚动复杂度重新散落到多个页面,而不是成为只转发 `className` 的浅模块。
|
||||||
|
- 保持现有 TanStack Router、Tailwind CSS 4、Base UI 与 feature 依赖方向,不在本迭代引入第二套组件框架。
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] HTML 原型可在桌面与移动视口间切换,并清晰展示两种布局形态。
|
||||||
|
- [ ] 桌面端在常见 1280px/1440px 宽度下呈现紧凑侧栏、工具区和数据内容,无不必要的大面积留白。
|
||||||
|
- [ ] 移动端在 375px/390px 宽度下无页面级水平溢出,主要操作可单手触达,内容不被导航或安全区遮挡。
|
||||||
|
- [ ] 原型包含统一的按钮、表单、标签、卡片、反馈、弹窗、表格与分页视觉和交互状态。
|
||||||
|
- [ ] 表格可实际翻页、切换每页数量,并展示总数、当前记录范围、当前页与禁用状态。
|
||||||
|
- [ ] 桌面端表格填满剩余视口高度,长列表仅滚动数据区,分页不随数据行滚出面板;页面不出现竞争或嵌套纵向滚动条。
|
||||||
|
- [ ] 移动端表格可读取并操作关键信息,不以整页横向滚动作为唯一方案。
|
||||||
|
- [ ] 技术设计明确 layout 模块的 seam、interface、内部职责、路由集成方式和页面迁移策略。
|
||||||
|
- [ ] 技术设计明确桌面密度与移动触控尺寸的 token/variant 关系,避免页面内散落设备判断。
|
||||||
|
- [ ] 规划说明 HTML 原型哪些决策会进入正式组件,哪些仅为验证用途。
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
|
||||||
|
- 本轮规划不修改后端接口、业务计算或数据同步流程。
|
||||||
|
- 原型阶段不实现完整生产组件库、不接入真实后端、不承诺暗色模式。
|
||||||
|
- 不照搬 `DESIGN.md` 中面向营销站的超大展示字号、定价卡片或产品截图布局。
|
||||||
|
- 未经单独确认,不提交、不推送、不发布原型。
|
||||||
|
|
||||||
|
## Product Decisions
|
||||||
|
|
||||||
|
- 移动端主导航采用“底部导航 + 更多菜单”,不使用顶部菜单按钮作为唯一主导航。该选择优先保证高频模块切换和单手可达性,并接受底部导航占用约 56–64px 视口空间的代价。
|
||||||
|
- 最终视觉结构采用 A「紧凑工作台」的应用壳与 C「主从研究台」的详情面板组合。
|
||||||
|
- 删除各页面内容区内重复的标题说明模块;桌面端由顶栏显示路由上下文,移动端由紧凑顶栏显示当前页面,内容区从按钮和核心数据开始。
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"id": "responsive-frontend-design",
|
||||||
|
"name": "responsive-frontend-design",
|
||||||
|
"title": "设计响应式前端交互体系",
|
||||||
|
"description": "",
|
||||||
|
"status": "in_progress",
|
||||||
|
"dev_type": null,
|
||||||
|
"scope": null,
|
||||||
|
"package": null,
|
||||||
|
"priority": "P2",
|
||||||
|
"creator": "yuxuanhui",
|
||||||
|
"assignee": "yuxuanhui",
|
||||||
|
"createdAt": "2026-08-09",
|
||||||
|
"completedAt": null,
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "main",
|
||||||
|
"worktree_path": null,
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": null,
|
||||||
|
"relatedFiles": [],
|
||||||
|
"notes": "",
|
||||||
|
"meta": {}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user