# 主应用：技能页 UI/UX

## 1. 页面定义

| 项目 | 内容 |
| --- | --- |
| 页面名称 | 技能管理 |
| 主路由 | `/skills` |
| 候选子页 | `/skills?tab=candidates` |
| 草稿评审子页 | `/skills?tab=drafts` |
| 页面实现 | `app-instance/frontend/app/(app)/skills/page.tsx` |
| 关键组件 | `PublishedSkillsTable`、`CandidateCard`、`DraftCard`、`SafetyReportPanel`、`EvalReportPanel`、`RawDetails`、`UploadSkillForm` |
| 核心任务 | 查看已发布技能、打开技能详情、上传技能、处理学习候选、生成草稿、提交/批准/拒绝/复检/发布草稿 |
| 测试状态 | 已修复并复测通过；本地与 `terminaltest` 生产实例均通过 |

## 2. 信息架构与组件层级

```text
AppShell
└── main.pt-16
    └── /skills
        ├── Page Header
        │   ├── h1 Skills
        │   ├── Refresh
        │   └── Upload skill
        ├── Error Card
        ├── UploadSkillForm
        ├── SkillDetailView
        │   ├── Overview
        │   ├── Files
        │   ├── Versions
        │   └── Download / Rollback / Disable / Delete
        └── Tabs
            ├── Published
            │   ├── < md：技能卡片列表
            │   └── >= md：技能表格
            ├── Candidates
            │   └── CandidateCard
            │       ├── 状态、风险、置信度
            │       ├── 候选理由和影响范围
            │       ├── 原始候选数据
            │       └── Ignore / Synthesize draft / Regenerate
            └── Draft review
                └── DraftCard
                    ├── 状态、safety、eval badge
                    ├── 草稿说明和元数据
                    ├── Submit / Approve / Reject / Recheck / Publish
                    ├── Proposed skill body
                    ├── Publish gates
                    ├── Raw draft payload
                    ├── Safety report
                    └── Eval report
```

## 3. 布局与响应式规则

- 页面外层使用 `max-w-6xl` 和响应式内边距：移动端 `16px`，桌面端 `24px`。
- tabs 是受控状态，并同步到 URL：候选为 `?tab=candidates`，草稿评审为 `?tab=drafts`。
- `runAction -> load()` 后不会再把候选或草稿评审重置到 Published。
- 移动端 Published 不显示宽表格，改为技能卡片；桌面端保留表格以便扫描。
- Candidates 和 Draft review 的卡片、Markdown、JSON、长 id 都使用容器内断行和 `min-w-0/max-w-full`。
- 草稿评审的 eval replay cases 在移动端显示卡片，桌面端显示表格。
- 原始数据 `details/summary` 的点击高度为 `44px`。
- 主要操作按钮均达到 `44px` 触控目标。

## 4. 操作与 UX 逻辑

| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
| --- | --- | --- | --- | --- |
| 切换 Published | 点击 Published tab | URL 移除 `tab` 参数 | 回到已发布技能列表 | 正常 |
| 切换 Candidates | 点击 Candidates tab | URL 变为 `/skills?tab=candidates` | 处理学习候选 | 正常 |
| 切换 Draft review | 点击 Draft review tab | URL 变为 `/skills?tab=drafts` | 审核和发布草稿 | 正常 |
| 刷新技能页 | 点击 Refresh | 重新拉取已发布、候选、草稿数据 | 获取最新技能状态 | 正常 |
| 上传技能 | 点击 Upload skill | 展开上传表单，上传成功后刷新 | 将本地技能包进入草稿评审 | 正常 |
| 打开技能详情 | 点击 Published 技能 | 显示 `SkillDetailView` | 查看版本、文件和内容 | 正常 |
| 生成草稿 | Candidates 点击 Synthesize draft | 调用候选 draft 接口，刷新数据后仍停留 Candidates | 不打断候选处理上下文 | 正常 |
| 忽略候选 | Candidates 点击 Ignore | 本地隐藏该候选 | 快速清理不处理候选 | 正常 |
| 送审草稿 | Draft review 点击 Submit | 调用 submit 接口，刷新后仍停留 Draft review | 进入人工评审流程 | 正常 |
| 批准草稿 | Draft review 点击 Approve | 调用 approve 接口，刷新后仍停留 Draft review | 满足发布门禁前置 | 正常 |
| 拒绝草稿 | Draft review 点击 Reject | 调用 reject 接口，刷新后仍停留 Draft review | 阻止不合格草稿继续发布 | 正常 |
| 复检安全 | Draft review 点击 Recheck | 调用 safety 接口，刷新后仍停留 Draft review | 获取最新安全结论 | 正常 |
| 发布草稿 | Draft review 点击 Publish | 满足门禁后调用 publish；高风险需要确认 | 将草稿转为已发布技能 | 正常 |
| 展开原始数据 | 点击 Raw details summary | 展开/收起 JSON | 为审核提供可追溯原始数据 | 正常 |

## 5. 响应式测试矩阵

测试日期：2026-06-04。浏览器：Playwright Chromium。环境：本地 dev server `http://127.0.0.1:3080` 与生产实例 `terminaltest`；API 使用模拟数据，真实浏览器执行点击、输入、跳转和截图。

| 页面 | 视口 | 横向越界 | 小触控目标 | 关键结论 |
| --- | --- | --- | --- | --- |
| Candidates | `390×844` | 无 | 0 | 生成草稿后仍停留候选页 |
| Draft review | `390×844` | 无 | 0 | 送审和批准后仍停留草稿评审页 |
| Draft review | `320×568` | 无 | 0 | 长 draft id、Markdown、eval cases 均未撑破页面 |
| Draft review | `390×844` | 无 | 0 | 手机竖屏可完成审核操作 |
| Draft review | `844×390` 横屏 | 无 | 0 | 横屏不出现页面级横向滚动 |
| Draft review | `768×1024` | 无 | 0 | 平板布局稳定 |
| Draft review | `1365×900` | 无 | 0 | 桌面布局正常 |

### 关键量化证据

- 本地技能页 QA 自动化用例 `3 passed`。
- 部署到 `terminaltest` 后，同一套技能页 QA 自动化用例 `3 passed`。
- 候选页点击 `Synthesize draft` 后 active tab 仍为 `Candidates`。
- 草稿评审点击 `Submit` 和 `Approve` 后 active tab 仍为 `Draft review`。
- Draft review 实测 `320×568`、`390×844`、`844×390`、`768×1024`、`1365×900` 均无页面级横向越界。
- 所有实测视口可见小触控目标数为 `0`。

## 6. 已修复问题

| 等级 | 问题 | 修复 |
| --- | --- | --- |
| P1 | Candidates 和 Draft review 中执行任意异步操作后会回到 Published | tabs 从 `defaultValue` 改为受控 `value`，并同步 URL `tab` 参数 |
| P1 | 草稿页 `320px` 下长 draft id、Markdown、评估表格会造成横向撑开风险 | 卡片、Markdown、JSON、长文本统一加容器内断行；eval cases 小屏改卡片 |
| P2 | Published 移动端使用宽表格，操作列容易隐藏 | `< md` 改为技能卡片，`>= md` 保留表格 |
| P2 | 多个按钮、icon 操作和 Raw details summary 触控高度不足 | 统一提升到 `44px`，icon-only 按钮补充可访问名称 |
| P2 | 候选/草稿 tab 无 URL 状态，刷新或分享不能保留子页 | 增加 `?tab=candidates` 和 `?tab=drafts` |

## 7. 剩余观察项

- 本轮自动化使用模拟数据覆盖长 id、长 Markdown、候选和草稿状态转换；真实后端极端数据仍需在后续页面联测中持续观察。
- 发布高风险草稿的确认分支没有在本轮自动化里实际确认发布，只验证了普通草稿审核路径。
