feat(selection): 收紧执行状态交互与页面布局
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{"file":".trellis/spec/frontend/index.md","reason":"检查前端 feature 边界、同源 API 契约和开发/质量入口。"}
|
||||
{"file":".trellis/spec/frontend/component-guidelines.md","reason":"检查抽屉、table 语义、交互元素和响应式样式是否符合规范。"}
|
||||
{"file":".trellis/spec/frontend/state-management.md","reason":"检查局部抽屉状态、React Query 数据和 URL 分页状态边界。"}
|
||||
{"file":".trellis/spec/frontend/type-safety.md","reason":"检查 SelectionFailure 类型复用和严格类型约束。"}
|
||||
{"file":".trellis/spec/frontend/quality-guidelines.md","reason":"执行最终格式、lint、类型、测试、构建和审查门禁。"}
|
||||
@@ -0,0 +1,71 @@
|
||||
# 选股执行状态抽屉与紧凑布局技术设计
|
||||
|
||||
## 1. Boundaries
|
||||
|
||||
本任务的产品边界在 `zhixing-web`:
|
||||
|
||||
- `SelectionResultsPage` 继续拥有执行状态、当前结果和局部抽屉开关状态。
|
||||
- `features/selection/components` 新增执行状态抽屉与未完成评估表格,组件只消费 `SelectionFailure` 等 feature 类型。
|
||||
- `PageLayout` 负责收紧跨页面的内容节奏;选股页面负责工作台内部的密度和滚动边界。
|
||||
- `shared/ui/dialog.tsx` 作为底层弹层 primitive 复用,不新增后端或全局状态。
|
||||
|
||||
不改变 API adapter、query key、TanStack Query 状态和路由 search 参数。
|
||||
|
||||
## 2. Component Shape
|
||||
|
||||
建议的组件关系:
|
||||
|
||||
```text
|
||||
SelectionResultsPage
|
||||
├─ PageLayout
|
||||
│ ├─ ExecutionToolbar
|
||||
│ ├─ ResultMetrics(onOpenExecutionStatus)
|
||||
│ └─ ResultState
|
||||
│ └─ SelectionResultsWorkbench
|
||||
└─ ExecutionStatusDrawer
|
||||
├─ status summary
|
||||
└─ IncompleteEvaluationTable
|
||||
```
|
||||
|
||||
`FailureList` 从 `ResultState` 移除。`ResultMetrics` 的执行状态入口通过回调通知页面,不把 Dialog 状态放进 Zustand,也不把失败列表复制到本地 state。
|
||||
|
||||
抽屉使用 `Dialog` 的受控 `open/onOpenChange`,通过 feature 局部 class 将 popup 定位到右侧、设置 `width: min(600px, 100vw)`、`height: 100svh` 和紧凑边框圆角。这样保留 Base UI 的焦点陷阱、Escape 和遮罩语义,同时避免为一次性业务交互新增浅层 shared primitive。
|
||||
|
||||
## 3. Data Flow
|
||||
|
||||
```text
|
||||
SelectionResults.failures
|
||||
│
|
||||
├─ ResultMetrics: failure count/status trigger
|
||||
└─ ExecutionStatusDrawer: read-only props
|
||||
└─ IncompleteEvaluationTable: rows
|
||||
```
|
||||
|
||||
抽屉不请求数据、不轮询、不修改 URL。抽屉展示的每一行直接对应 `SelectionFailure`,状态和原因只做前端文案格式化;缺失原因显示 `—`。
|
||||
|
||||
## 4. Layout and Density
|
||||
|
||||
### Desktop
|
||||
|
||||
- `AppLayout → main → PageLayout → ResultState → workbench` 保持连续的 `flex: 1`、`min-height: 0` 高度链。
|
||||
- 操作区、指标区、筛选栏、分页均使用 `shrink-0`。
|
||||
- 主从工作台使用剩余空间;表格 `overflow-auto`,分页留在面板底部。
|
||||
- 页面 gutter 由当前 24px 收紧为 16px 级别;内部 panel/filter/detail 使用 8–16px 级别的间距。
|
||||
|
||||
### Mobile
|
||||
|
||||
- 保留日期、策略、执行按钮的语义和触控尺寸,不为了压缩而降低到桌面 32px。
|
||||
- 内容容器采用紧凑 gutter 和较小 section gap;页面恢复自然滚动。
|
||||
- 抽屉宽度随视口收缩,不产生横向溢出;表格必要时只在抽屉内部横向处理长文本,优先让原因换行。
|
||||
|
||||
## 5. Compatibility and Rollback
|
||||
|
||||
- 旧结果结构仍可直接渲染;只有失败列表的呈现位置改变。
|
||||
- 若 Drawer 样式影响 Base UI Dialog,可回退为同一受控 Dialog 的居中呈现,不影响数据流和页面其他交互。
|
||||
- 若高度链修复造成无结果/错误状态被压缩,保留这些状态的最小可读高度,并只让成功结果工作台承担剩余高度。
|
||||
|
||||
## 6. Verification Strategy
|
||||
|
||||
- 页面测试:抽屉打开、表格内容、空表状态、关闭和焦点入口;确认主页面不再直接渲染失败卡片。
|
||||
- 质量门禁:Prettier、ESLint、TypeScript、Vitest、Vite build。
|
||||
- 浏览器:使用可控 mock 结果验证 1440×900、1280×800、390×844、375×812;检查抽屉宽度、分页底部位置、数据区滚动和无水平溢出。
|
||||
@@ -0,0 +1,5 @@
|
||||
{"file":".trellis/spec/frontend/index.md","reason":"前端开发前检查、feature 边界、API 与布局约束。"}
|
||||
{"file":".trellis/spec/frontend/component-guidelines.md","reason":"抽屉、表格、组件组合、可访问性和 Tailwind 样式规范。"}
|
||||
{"file":".trellis/spec/frontend/state-management.md","reason":"抽屉开关属于局部瞬时状态,服务器结果继续由 TanStack Query 管理。"}
|
||||
{"file":".trellis/spec/frontend/type-safety.md","reason":"复用 SelectionFailure 类型并保持严格 TypeScript/API 边界。"}
|
||||
{"file":".trellis/spec/frontend/quality-guidelines.md","reason":"实现后的格式、lint、类型、测试和构建门禁。"}
|
||||
@@ -0,0 +1,63 @@
|
||||
# 选股执行状态抽屉与紧凑布局执行计划
|
||||
|
||||
## Scope
|
||||
|
||||
只修改 `zhixing-web` 前端;后端接口、数据库和原型 HTML 不在本任务中变更。
|
||||
|
||||
## Ordered Checklist
|
||||
|
||||
### 1. 开发前上下文
|
||||
|
||||
- [x] 读取 `trellis-before-dev` 指定的前端规格和当前工作区状态。
|
||||
- [x] 确认任务文件、用户现有改动和目标文件边界。
|
||||
|
||||
### 2. 执行状态抽屉
|
||||
|
||||
- [x] 新增 `selection` feature 内的执行状态抽屉组件,复用 `Dialog` primitive,桌面宽度固定 600px,移动端自适应。
|
||||
- [x] 新增未完成评估 table 组件,展示名称、代码、状态、原因和空状态。
|
||||
- [x] 将 `ResultMetrics` 的执行状态改为抽屉触发入口,移除主页面下方的 `FailureList`。
|
||||
- [x] 保持 Escape、遮罩、关闭按钮和焦点返回行为。
|
||||
|
||||
### 3. 紧凑与有界布局
|
||||
|
||||
- [x] 收紧 `PageLayout` 的 gutter、区块 padding 和 vertical rhythm。
|
||||
- [x] 收紧选股执行工具栏、指标、筛选栏、详情面板、分页和状态卡。
|
||||
- [x] 修复成功结果工作台的 `flex/min-h-0` 高度链,确保数据区填满剩余高度、分页固定底部。
|
||||
- [x] 保持移动端触控尺寸和自然页面滚动。
|
||||
|
||||
### 4. 测试与验证
|
||||
|
||||
- [x] 为抽屉、表格、空状态和主页面移除内联列表补充 Testing Library 测试。
|
||||
- [x] 运行 `pnpm format:check`、`pnpm lint`、`pnpm typecheck`、`pnpm test`、`pnpm build`。
|
||||
- [x] 用浏览器 mock 数据检查桌面和移动视口、抽屉宽度、滚动边界、分页位置及水平溢出。
|
||||
|
||||
## Verification Notes
|
||||
|
||||
- `pnpm lint`、`pnpm typecheck`、`pnpm test`(4 files / 22 tests)和 `pnpm build` 通过。
|
||||
- 本次改动文件的 Prettier 检查通过;全量 `pnpm format:check` 仅因未修改的 `DESIGN.md` 未格式化而失败。
|
||||
- 浏览器 mock 已验证 600px 桌面抽屉、移动端无水平溢出、关闭/Escape/遮罩/焦点恢复和工作台高度链。
|
||||
|
||||
## Validation Commands
|
||||
|
||||
在 `zhixing-web/` 下运行:
|
||||
|
||||
```bash
|
||||
pnpm format:check
|
||||
pnpm lint
|
||||
pnpm typecheck
|
||||
pnpm test
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Risky Files and Rollback Points
|
||||
|
||||
- `src/features/selection/pages/selection-results-page.tsx`:页面状态和内联失败列表迁移;可单独回退组件接线。
|
||||
- `src/features/selection/components/*execution*` / `*evaluation*`:新增抽屉与表格;删除新文件即可回退。
|
||||
- `src/app/layout/page-layout.tsx`:跨页面密度和滚动边界;若影响 Home,回退该文件的密度 class,再保留 Selection 局部修复。
|
||||
- `src/features/selection/components/selection-results-workbench.tsx`:高度链和数据滚动;回退时保留原筛选、分页和主从逻辑。
|
||||
|
||||
## Review Gates Before Start
|
||||
|
||||
- [x] `prd.md`、`design.md`、`implement.md` 已按最终范围收敛。
|
||||
- [x] `implement.jsonl` 与 `check.jsonl` 已填入真实前端规格上下文。
|
||||
- [x] 用户已批准本规划摘要后,才运行 `task.py start`。
|
||||
@@ -0,0 +1,69 @@
|
||||
# 收紧选股执行状态交互与页面布局
|
||||
|
||||
## Goal
|
||||
|
||||
让选股策略页面把“未完成评估”从主工作区移出,改成由执行状态触发的右侧抽屉;抽屉内用紧凑表格查看明细。同时收紧页面各模块的内外间距,让桌面工作台填满可用高度,移动端保持可操作性。
|
||||
|
||||
本任务只修改前端交互和布局,不新增或修改后端接口。现有 API 返回的 `SelectionResults.failures` 作为抽屉数据源,接口扩展留给后续业务需求迭代。
|
||||
|
||||
## Confirmed Facts
|
||||
|
||||
- 当前 [selection-results-page.tsx](zhixing-web/src/features/selection/pages/selection-results-page.tsx) 在 `ResultState` 下方直接渲染 `FailureList`,标题为“未完成评估”,每条记录是独立卡片(约第 458–491 行)。
|
||||
- 当前 `ResultMetrics` 已展示“执行状态”,但它只是 Badge,不承担交互(约第 290–315 行)。
|
||||
- 当前选股结果工作台使用 `min-h-[420px] shrink-0` 包裹,导致桌面端数据面板不能填满页面剩余高度(约第 430–441 行)。
|
||||
- 当前项目已有基于 Base UI Dialog 的可访问弹层 primitive,可复用其焦点管理、Escape 和遮罩行为;尚无 Drawer/Sheet primitive。
|
||||
- 当前 `SelectionResults` 已包含 `failures`,字段为股票代码、名称、状态和原因;本任务不需要后端改契约。
|
||||
- 当前分页、筛选和主从详情已经存在,本任务保留其行为。
|
||||
|
||||
## Requirements
|
||||
|
||||
### R1. 执行状态抽屉
|
||||
|
||||
- 主页面不再直接渲染“未完成评估”卡片或明细列表。
|
||||
- “执行状态”成为可操作入口;点击后从右侧打开执行状态抽屉,并把当前结果的未完成评估列表传入抽屉。
|
||||
- 抽屉标题和说明要明确表达当前策略、目标交易日、执行状态及未完成数量。
|
||||
- 桌面端抽屉宽度固定为 `600px`;视口小于该宽度时退化为不产生水平溢出的全宽/近全宽布局。
|
||||
- 抽屉支持关闭按钮、遮罩点击、Escape 和焦点返回;打开后焦点进入抽屉。
|
||||
- 没有未完成评估时仍可查看执行状态,抽屉显示空表状态,不创建无意义的空卡片。
|
||||
|
||||
### R2. 未完成评估表格
|
||||
|
||||
- 抽屉中的明细必须使用语义化 `table` 组件,不使用逐条卡片替代。
|
||||
- 表格至少展示:股票名称、股票代码、评估状态、失败原因。
|
||||
- 表头、单元格和行间距使用紧凑密度;长原因可换行,不撑破抽屉宽度。
|
||||
- 表格提供 caption/可访问名称;无数据时显示可读的空状态。
|
||||
- 表格属于 `selection` feature,不把策略字段或业务格式化下沉到 `shared/ui`。
|
||||
|
||||
### R3. 页面紧凑布局
|
||||
|
||||
- 收紧 `PageLayout` 的页面 gutter、操作区/指标区内边距和纵向间距;页面内容在桌面端尽量使用主区域宽度。
|
||||
- 收紧选股页执行工具栏、指标区、筛选栏、详情面板、分页和各状态卡的 padding/margin/gap。
|
||||
- 修复 bounded workspace 的连续高度链:操作区、指标区、筛选栏、分页不参与数据滚动,主表格数据区占满剩余高度并独立滚动。
|
||||
- 保留移动端至少 `44px` 的主要触控命中区域;移动端改为自然页面滚动,不引入嵌套水平滚动。
|
||||
- 不改变现有路由、筛选 URL 状态、分页行为、策略执行/轮询行为和主从选中行为。
|
||||
|
||||
### R4. 页面状态边界
|
||||
|
||||
- 请求加载、请求错误、无结果和执行失败等请求级状态仍可在主页面就地表达。
|
||||
- 仅将“未完成评估”的结果明细从主页面迁移至抽屉,不把后端接口缺失伪装成前端数据。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 不新增或修改 FastAPI endpoint、Pydantic response model、数据库表或策略执行逻辑。
|
||||
- 不实现行情数据、同步任务、全局搜索、个股研究详情或新的置信度接口。
|
||||
- 不改变 `SelectionResults` API 的字段含义,不为“信号置信度”虚构数据。
|
||||
- 不重写原型 HTML 的交互状态;原型继续作为视觉基线,正式页面以本任务的紧凑布局为准。
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [x] 有失败结果时,主页面不出现“未完成评估”明细卡片;执行状态入口可见且可操作。
|
||||
- [x] 点击执行状态后,右侧打开宽度为 `600px` 的抽屉;抽屉内存在可访问的 `table`,并正确展示所有失败记录。
|
||||
- [x] 抽屉可以通过关闭按钮、遮罩、Escape 关闭,关闭后焦点返回执行状态入口。
|
||||
- [x] 无失败记录时,执行状态入口仍能打开抽屉,表格显示空状态。
|
||||
- [x] 1440×900 桌面视口下,选股工作台的数据面板填满操作区/指标区后的剩余高度,分页固定在面板底部,只有数据行区域滚动。
|
||||
- [x] 390×844 与 375×812 移动视口下无页面级水平溢出,底部导航不遮挡可滚动内容,主要控件命中区域不低于 `44px`。
|
||||
- [x] 前端格式、lint、类型检查、单元测试和构建通过;浏览器验证覆盖抽屉交互、紧凑布局和桌面/移动视口。
|
||||
|
||||
## Open Questions
|
||||
|
||||
无。抽屉触发入口采用现有“执行状态”指标;本次不扩展后端接口。
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "selection-status-drawer-compact-layout",
|
||||
"name": "selection-status-drawer-compact-layout",
|
||||
"title": "收紧选股执行状态交互与页面布局",
|
||||
"description": "",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "yuxuanhui",
|
||||
"assignee": "yuxuanhui",
|
||||
"createdAt": "2026-08-10",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user