diff --git a/.scratch/ui-consistency/issues/09-final-regression.md b/.scratch/ui-consistency/issues/09-final-regression.md index 9de5f53..22fcb01 100644 --- a/.scratch/ui-consistency/issues/09-final-regression.md +++ b/.scratch/ui-consistency/issues/09-final-regression.md @@ -7,6 +7,6 @@ **Acceptance criteria:** - [ ] 全部 9 页 t480 逐页走查一遍(golden path + keep-alive 切 tab 状态不丢) - [ ] 基准页(IntelligentEvals)重走 P0 全流程确认无回归 -- [ ] `tsc --noEmit` + 后端 pytest 全绿 -- [ ] AGENTS.md 前端章节更新(新增交互标准说明、清理过时描述) -- [ ] 本 spec 与票据验收项勾选归档 +- [x] `tsc --noEmit` + 后端 pytest 全绿 +- [x] AGENTS.md 前端章节更新(新增交互标准说明、清理过时描述) +- [x] 本 spec 与票据验收项勾选归档 diff --git a/AGENTS.md b/AGENTS.md index 6b68c52..6895827 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -126,10 +126,18 @@ SPA 由 FastAPI 托管(`GET /{full_path:path}` → `index.html`)。`frontend **路由采用 keep-alive 标签页模式**(非标准 ``):所有页面同时挂载在 DOM 中,通过 `display: block/none` 切换可见性,保证页面状态在切 tab 时不丢失。路由配置集中在 `App.tsx` 的 `routeConfigs` 数组中,Zustand `tabStore` 管理标签页的打开/关闭/激活状态,`react-router` 仅用于 URL 同步。 **三种状态管理策略**: -- **Zustand**(`stores/tabStore.ts`):全局标签页状态,唯一一个 store +- **Zustand**(`stores/tabStore.tsx`):全局标签页状态,唯一一个 store - **useReducer**(`hooks/sessionReducer.ts`):评测会话状态(cases/turns/results/progress),纯 reducer 无副作用,hook 负责 WS/REST 副作用 - **useState**:各页面本地数据,无全局缓存(不使用 SWR/React Query) +**UI 交互一致性标准**(ADR-0005,全部管理页必须遵守): +- 页壳:`PageWrapper inline fullHeight`;详情页用页内 view 切换(非新路由) +- 表格:`Empty` 空态;超过 20 行才分页(pageSize 20);禁止 `scroll.y` calc hack,外层 div `overflowY: auto` +- 表单:`components/FormDrawer.tsx`(宽 640、页脚取消/确定、`submitting` loading、`destroyOnClose`) +- 危险操作(删除/取消/停止):`Popconfirm` +- 反馈:axios 拦截器统一 message,页面不重复弹错 +- 活动状态轮询:`usePolling(fn, ms, enabled)` 5 秒静默轮询(`reload(true)`) + **Vite 开发代理**:dev server 端口 3000,`/api`、`/ws`、`/openclaw` 全部代理到 `localhost:8000`;生产构建时 `dist/` 由 FastAPI 直接托管。 **Ant Design CSS-in-JS 冲突**:Ant Design v5 的 emotion 运行时注入会覆盖静态 CSS 的 `flex`/`height` 规则。Runs 页采用"导航与内容分离"方案——Tabs 组件仅用于渲染导航头(`.nav-only-tabs` CSS 隐藏 `.ant-tabs-content-holder`),实际内容 div 由 flex 直接控制高度,绕过 Ant Design 内部 DOM。