feat: 添加MinIO文件系统支持并优化外部连接器功能
- 添加MinIO用户文件系统配置选项(BEAVER_MINIO_ROOT_USER等) - 更新外部连接器配置结构,包括BASE_URL和认证令牌设置 - 改进connector provider支持更多类型(official, feishu_bot等) - 实现Mistral模型推理模式支持reasoning_effort参数 - 增强外部连接器策略配置和运行时配置管理 - 添加connector bridge事件验证和安全保护机制 - 优化任务路由逻辑,区分simple_chat和new_task场景 - 更新初始技能工具提示配置,分离authoring admin功能
This commit is contained in:
@ -0,0 +1,73 @@
|
||||
# Auto-Accept on New Topic Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Silently accept an awaiting Task before processing an unrelated new topic.
|
||||
|
||||
**Architecture:** Keep the existing Intent Agent actions. Treat `simple_chat` and `new_task` decisions made while a Task is active as new-topic boundaries, reuse `submit_acceptance()` for the old Task's latest run, and then continue the original routing decision.
|
||||
|
||||
**Tech Stack:** Python, pytest, Beaver TaskService and AgentService
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Lock the State Transition with Tests
|
||||
|
||||
**Files:**
|
||||
- Modify: `app-instance/backend/tests/unit/test_task_mode_feedback.py`
|
||||
|
||||
- [ ] Add a failing test proving an unrelated `simple_chat` message formally accepts the previous Task and does not append another run to it.
|
||||
- [ ] Add a failing test proving `new_task` formally accepts the previous Task before creating a separate Task.
|
||||
- [ ] Add tests proving `continue_task` and `revise_task` retain the existing active Task behavior.
|
||||
- [ ] Run:
|
||||
|
||||
```bash
|
||||
uv run pytest -q tests/unit/test_task_mode_feedback.py
|
||||
```
|
||||
|
||||
Expected before implementation: the new-topic tests fail because the previous Task remains `awaiting_acceptance`.
|
||||
|
||||
### Task 2: Implement New-Topic Auto-Accept
|
||||
|
||||
**Files:**
|
||||
- Modify: `app-instance/backend/beaver/services/agent_service.py`
|
||||
|
||||
- [ ] Add a focused async helper that accepts only an `awaiting_acceptance` Task with a latest run.
|
||||
- [ ] Call the helper after routing when the decision is `simple_chat` or starts a new Task.
|
||||
- [ ] Reuse `submit_acceptance()` so acceptance history, final accepted run, run memory, and learning behavior remain consistent.
|
||||
- [ ] Run:
|
||||
|
||||
```bash
|
||||
uv run pytest -q tests/unit/test_task_mode_feedback.py
|
||||
```
|
||||
|
||||
Expected: all task-mode feedback tests pass.
|
||||
|
||||
### Task 3: Clarify Intent Routing Guidance
|
||||
|
||||
**Files:**
|
||||
- Modify: `app-instance/backend/beaver/tasks/router.py`
|
||||
- Modify: `app-instance/backend/beaver/skills/builtin/intent-agent-router/SKILL.md`
|
||||
- Modify: `app-instance/backend/tests/unit/test_main_agent_router.py`
|
||||
|
||||
- [ ] Assert the generated routing prompt explicitly says unrelated lightweight conversation is `simple_chat`, not `revise_task`.
|
||||
- [ ] Update both routing guidance sources with the same rule and examples.
|
||||
- [ ] Run:
|
||||
|
||||
```bash
|
||||
uv run pytest -q tests/unit/test_main_agent_router.py
|
||||
```
|
||||
|
||||
Expected: all router tests pass.
|
||||
|
||||
### Task 4: Regression Verification
|
||||
|
||||
**Files:**
|
||||
- Verify only
|
||||
|
||||
- [ ] Run:
|
||||
|
||||
```bash
|
||||
uv run pytest -q tests/unit/test_main_agent_router.py tests/unit/test_task_mode_feedback.py tests/unit/test_active_task_api.py tests/unit/test_process_projection.py
|
||||
```
|
||||
|
||||
- [ ] Inspect the final diff to confirm no frontend confirmation or unrelated state changes were introduced.
|
||||
@ -0,0 +1,75 @@
|
||||
# Chat Task Timeline Consistency Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Render the active Task's canonical timeline in the chat progress sidebar and hide it when no active Task exists.
|
||||
|
||||
**Architecture:** Extract task-scoped process filtering into a shared frontend helper, use it in both Task detail and chat, and make the chat sidebar a responsive wrapper around the existing `TaskTimeline` component.
|
||||
|
||||
**Tech Stack:** React, Next.js, TypeScript, Vitest
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Extract Shared Task Process Selection
|
||||
|
||||
**Files:**
|
||||
- Create: `app-instance/frontend/lib/task-process.ts`
|
||||
- Create: `app-instance/frontend/lib/task-process.test.ts`
|
||||
- Modify: `app-instance/frontend/app/(app)/tasks/[taskId]/page.tsx`
|
||||
|
||||
- [ ] Write failing tests for merging persisted task process data with matching live process data.
|
||||
- [ ] Implement `selectTaskProcess()` returning task-scoped runs, events, and artifacts.
|
||||
- [ ] Replace the Task detail page's local filtering with the shared helper.
|
||||
- [ ] Run:
|
||||
|
||||
```bash
|
||||
npm test -- --run lib/task-process.test.ts lib/task-timeline.test.ts
|
||||
```
|
||||
|
||||
### Task 2: Replace Chat Progress View with Task Timeline
|
||||
|
||||
**Files:**
|
||||
- Modify: `app-instance/frontend/components/chat-workbench/CurrentSessionProgressSidebar.tsx`
|
||||
- Modify: `app-instance/frontend/app/(app)/page.tsx`
|
||||
|
||||
- [ ] Load full `BackendTask` detail whenever `activeTask` exists.
|
||||
- [ ] Clear full Task detail whenever active Task becomes `null` or the session changes.
|
||||
- [ ] Build chat timeline cards using `selectTaskProcess()` and `buildTaskTimelineCards()`.
|
||||
- [ ] Change `CurrentSessionProgressSidebar` to accept timeline cards and render `TaskTimeline` without acceptance controls.
|
||||
- [ ] Remove the chat page's use of `buildSessionProgressView()`.
|
||||
|
||||
### Task 3: Add Visibility and Consistency Tests
|
||||
|
||||
**Files:**
|
||||
- Modify: `app-instance/frontend/lib/task-process.test.ts`
|
||||
- Modify: `app-instance/frontend/lib/task-timeline.test.ts`
|
||||
- Delete if unused: `app-instance/frontend/lib/session-progress.test.ts`
|
||||
- Delete if unused: `app-instance/frontend/lib/session-progress.ts`
|
||||
|
||||
- [ ] Cover empty/no-active input behavior in the shared helper.
|
||||
- [ ] Confirm the same Task/process input creates the same timeline cards on both surfaces.
|
||||
- [ ] Remove the obsolete session-progress builder and tests if no imports remain.
|
||||
- [ ] Run:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
### Task 4: Frontend Verification
|
||||
|
||||
**Files:**
|
||||
- Verify only
|
||||
|
||||
- [ ] Run:
|
||||
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm run build
|
||||
```
|
||||
|
||||
- [ ] Validate the rendered chat flow with Playwright because the Browser plugin is not available:
|
||||
|
||||
```text
|
||||
chat page with active Task -> open current-session progress -> same timeline cards as Task detail
|
||||
Task closes -> current-session progress disappears
|
||||
```
|
||||
104
docs/superpowers/plans/2026-06-04-initial-multi-search-engine.md
Normal file
104
docs/superpowers/plans/2026-06-04-initial-multi-search-engine.md
Normal file
@ -0,0 +1,104 @@
|
||||
# Initial Multi Search Engine Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Replace the initial `web-operation` skill with SkillHub `multi-search-engine` while keeping `web_fetch` reliably available when the skill is selected.
|
||||
|
||||
**Architecture:** Initial skills are copied from the repository `skills/` directory into each instance workspace by `create-instance.sh` and `entrypoint.sh`. This change updates the seed catalog, not existing user workspace state.
|
||||
|
||||
**Tech Stack:** Python skill catalog storage, JSON seed metadata, Markdown `SKILL.md`, pytest.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Update Initial Skill Contract
|
||||
|
||||
**Files:**
|
||||
- Modify: `app-instance/backend/tests/unit/test_initial_skill_tool_hints.py`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
Change `EXPECTED_INITIAL_SKILL_TOOLS` so it expects:
|
||||
|
||||
```python
|
||||
"multi-search-engine": ["web_fetch"],
|
||||
```
|
||||
|
||||
and no longer expects:
|
||||
|
||||
```python
|
||||
"web-operation": ["web_fetch", "web_search"],
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd app-instance/backend
|
||||
pytest tests/unit/test_initial_skill_tool_hints.py -q
|
||||
```
|
||||
|
||||
Expected: FAIL because `skills/multi-search-engine/versions/v0001/SKILL.md` does not exist yet.
|
||||
|
||||
### Task 2: Replace Seed Skill
|
||||
|
||||
**Files:**
|
||||
- Create: `skills/multi-search-engine/current.json`
|
||||
- Create: `skills/multi-search-engine/skill.json`
|
||||
- Create: `skills/multi-search-engine/versions/v0001/SKILL.md`
|
||||
- Create: `skills/multi-search-engine/versions/v0001/version.json`
|
||||
- Create: `skills/multi-search-engine/versions/v0001/CHANGELOG.md`
|
||||
- Create: `skills/multi-search-engine/versions/v0001/CHANNELLOG.md`
|
||||
- Create: `skills/multi-search-engine/versions/v0001/config.json`
|
||||
- Create: `skills/multi-search-engine/versions/v0001/metadata.json`
|
||||
- Create: `skills/multi-search-engine/versions/v0001/references/advanced-search.md`
|
||||
- Create: `skills/multi-search-engine/versions/v0001/references/international-search.md`
|
||||
- Modify: `skills/_index/published.json`
|
||||
|
||||
- [ ] **Step 1: Add SkillHub content**
|
||||
|
||||
Fetch `global/multi-search-engine@20260413.065325` from SkillHub and store it as seed version `v0001`.
|
||||
|
||||
- [ ] **Step 2: Add tool hint**
|
||||
|
||||
Ensure `SKILL.md` frontmatter contains:
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
- web_fetch
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Update published index**
|
||||
|
||||
Remove `web-operation` and add `multi-search-engine`.
|
||||
|
||||
### Task 3: Verify
|
||||
|
||||
**Files:**
|
||||
- Test: `app-instance/backend/tests/unit/test_initial_skill_tool_hints.py`
|
||||
|
||||
- [ ] **Step 1: Run targeted tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd app-instance/backend
|
||||
pytest tests/unit/test_initial_skill_tool_hints.py tests/unit/test_marketplace_and_mcp.py -q
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 2: Inspect seed metadata**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
python - <<'PY'
|
||||
import json
|
||||
from pathlib import Path
|
||||
print(json.loads(Path('skills/_index/published.json').read_text())['items'])
|
||||
print(json.loads(Path('skills/multi-search-engine/versions/v0001/version.json').read_text())['tool_hints'])
|
||||
PY
|
||||
```
|
||||
|
||||
Expected: `multi-search-engine` is published, `web-operation` is absent, and tool hints are `["web_fetch"]`.
|
||||
@ -0,0 +1,60 @@
|
||||
# Auto-Accept Task When a New Topic Starts
|
||||
|
||||
## Goal
|
||||
|
||||
Prevent unrelated follow-up conversation from being appended to the previous
|
||||
Task. When the Intent Agent decides that the user's current message starts a
|
||||
new topic, Beaver should silently accept the previous Task before processing
|
||||
the current message.
|
||||
|
||||
## User Experience
|
||||
|
||||
- No confirmation dialog or extra assistant message is shown.
|
||||
- A related follow-up or requested change continues the existing Task.
|
||||
- An unrelated lightweight message is handled as `simple_chat`.
|
||||
- Unrelated work that needs Task capabilities is handled as `new_task`.
|
||||
- Before either new-topic path continues, the previous Task is formally
|
||||
accepted.
|
||||
|
||||
## Routing Rules
|
||||
|
||||
The existing Intent Agent actions remain unchanged:
|
||||
|
||||
- `continue_task` and `revise_task` belong to the active Task.
|
||||
- `close_task` and `abandon_task` keep their existing explicit semantics.
|
||||
- With an active Task, `simple_chat` means an unrelated lightweight new topic.
|
||||
- With an active Task, `new_task` means unrelated work that needs a separate
|
||||
Task.
|
||||
|
||||
The Intent Agent guidance must explicitly distinguish unrelated lightweight
|
||||
conversation from revisions. A message must not be classified as
|
||||
`revise_task` merely because an active Task is awaiting acceptance.
|
||||
|
||||
## State Transition
|
||||
|
||||
Before processing a `simple_chat` or `new_task` decision:
|
||||
|
||||
1. Check whether the active Task is `awaiting_acceptance`.
|
||||
2. Find its latest completed run.
|
||||
3. Record a normal `accept` acceptance against that run.
|
||||
4. Continue processing the current message using the original routing
|
||||
decision.
|
||||
|
||||
The normal acceptance path must be reused so that the Task becomes `closed`,
|
||||
`final_accepted_run_id` is recorded, acceptance events are persisted, run
|
||||
memory is updated, and skill-learning candidates can be generated.
|
||||
|
||||
Tasks without an acceptance-eligible completed run are left unchanged. Router
|
||||
failures retain the existing conservative `continue_task` fallback and must
|
||||
not auto-accept a Task.
|
||||
|
||||
## Testing
|
||||
|
||||
Backend tests must cover:
|
||||
|
||||
- An unrelated `simple_chat` message accepts the previous Task and is not
|
||||
appended as another Task run.
|
||||
- A `new_task` decision accepts the previous Task and creates a separate Task.
|
||||
- `continue_task` and `revise_task` do not auto-accept the active Task.
|
||||
- Router failure fallback does not auto-accept the active Task.
|
||||
- Auto-accept records the final accepted run and normal acceptance history.
|
||||
@ -0,0 +1,59 @@
|
||||
# Chat Current-Task Timeline Consistency
|
||||
|
||||
## Goal
|
||||
|
||||
Make the chat page's current-session progress panel show the same timeline
|
||||
content as the active Task's detail page.
|
||||
|
||||
## Visibility
|
||||
|
||||
- Show the chat-side timeline only while the current session has an active
|
||||
Task.
|
||||
- Hide the panel immediately when the Task is accepted, auto-accepted,
|
||||
abandoned, closed, or when the user switches sessions.
|
||||
- Do not show the most recently completed Task after it is no longer active.
|
||||
|
||||
## Shared Data Model
|
||||
|
||||
The Task detail page remains the canonical timeline behavior.
|
||||
|
||||
Both surfaces must:
|
||||
|
||||
1. Load the full `BackendTask` payload from `/api/tasks/{task_id}`.
|
||||
2. Combine the task's persisted process data with matching live process data.
|
||||
3. Use one shared task-process filtering helper.
|
||||
4. Build cards with `buildTaskTimelineCards()`.
|
||||
5. Render cards with `TaskTimeline`.
|
||||
|
||||
This keeps card types, ordering, fallback milestones, result history,
|
||||
acceptance history, tool status, and deduplication consistent.
|
||||
|
||||
## Chat Panel
|
||||
|
||||
`CurrentSessionProgressSidebar` becomes a responsive wrapper around
|
||||
`TaskTimeline`.
|
||||
|
||||
- Desktop keeps the existing right sidebar.
|
||||
- Smaller viewports keep the existing floating open button and drawer.
|
||||
- The panel title remains "当前会话的运行进度".
|
||||
- Timeline cards match the Task detail timeline.
|
||||
- Chat does not render duplicate acceptance controls inside the sidebar,
|
||||
because acceptance controls already exist on chat result messages.
|
||||
|
||||
## Data Refresh
|
||||
|
||||
- Whenever the active Task changes, the chat page loads its full Task detail.
|
||||
- Existing message, process, feedback, and WebSocket refresh paths reload both
|
||||
the active Task identity and its full detail.
|
||||
- If the active-task endpoint returns `null`, the cached active Task detail is
|
||||
cleared immediately and the sidebar disappears.
|
||||
- A task-detail load failure hides the sidebar rather than showing stale data.
|
||||
|
||||
## Testing
|
||||
|
||||
- Shared process filtering returns the same task-scoped runs, events, and
|
||||
artifacts for both surfaces.
|
||||
- The chat-side timeline cards are produced by `buildTaskTimelineCards()`.
|
||||
- No active Task produces no chat-side timeline.
|
||||
- Switching to a closed/no-active Task clears the chat-side timeline.
|
||||
- Frontend unit tests, typecheck, and production build pass.
|
||||
84
docs/ui-ux/README.md
Normal file
84
docs/ui-ux/README.md
Normal file
@ -0,0 +1,84 @@
|
||||
# Beaver UI/UX 页面维护文档
|
||||
|
||||
## 文档目的
|
||||
|
||||
本目录用于按页面持续维护 Beaver 前端的 UI/UX 结构与真实测试结论。
|
||||
|
||||
每一页需要记录:
|
||||
|
||||
- 页面、子页、详情页、弹窗和主要状态。
|
||||
- 组件层级关系、视觉位置和响应式变化。
|
||||
- 每个可操作控件的触发方式、状态变化、反馈、UX 目的和异常恢复逻辑。
|
||||
- 多视口下的越界、重叠、滚动、触控目标和可访问性结论。
|
||||
- 已发现问题、优先级、代码位置和后续验收标准。
|
||||
|
||||
文档描述的是当前真实实现。建议设计与当前实现不一致时,必须明确标记为“待修复”,不能混写为已实现行为。
|
||||
|
||||
## 测试原则
|
||||
|
||||
每个页面至少执行以下检查:
|
||||
|
||||
1. 页面身份、标题和首屏内容正确,无空白页或框架错误覆盖层。
|
||||
2. 在 `320px`、`375px`、`390px`、`768px`、`1024px`、`1365px` 和宽屏视口检查布局。
|
||||
3. 至少检查一个手机横屏视口。
|
||||
4. 检查横向越界、内容裁切、组件重叠、嵌套滚动和固定元素遮挡。
|
||||
5. 真实点击或键盘操作每个主要控件,并验证状态变化。
|
||||
6. 检查加载、成功、失败、空数据、禁用和权限不足状态。
|
||||
7. 检查键盘顺序、焦点可见性、可访问名称、错误播报和触控目标尺寸。
|
||||
8. 截图和临时测试脚本默认保存在 `/tmp`,不提交到仓库。
|
||||
|
||||
## 问题等级
|
||||
|
||||
| 等级 | 定义 |
|
||||
| --- | --- |
|
||||
| P0 | 阻断核心流程、页面不可用、数据安全或严重误操作风险 |
|
||||
| P1 | 核心流程明显受损、响应式严重异常、关键可访问性缺失 |
|
||||
| P2 | 可完成任务但体验、可发现性、触控或反馈质量不足 |
|
||||
| P3 | 视觉一致性、轻微布局或低风险优化项 |
|
||||
|
||||
## 页面清单
|
||||
|
||||
| 页面域 | 页面或状态 | 路由 | 文档 | 状态 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 认证门户 | 登录页 | `/login?next=...` | [登录页](./pages/auth-login.md) | 已修复并复测通过 |
|
||||
| 认证门户 | 注册页 | `/register?next=...` | 待创建 | 待测试 |
|
||||
| 认证门户 | 注册后的模型配置子页 | `/register?next=...` 注册成功后 | 待创建 | 待测试 |
|
||||
| 主应用认证入口 | 登录跳转页 | `/login?next=...` | 待创建 | 待测试 |
|
||||
| 主应用 | 对话工作台 | `/` | [对话工作台](./pages/chat-workbench.md) | 已修复并复测通过 |
|
||||
| 主应用 | 任务列表 | `/tasks` | [Task 任务页](./pages/task-management.md) | 已修复并复测通过 |
|
||||
| 主应用 | 任务详情 | `/tasks/[taskId]` | [Task 任务页](./pages/task-management.md) | 已修复并复测通过 |
|
||||
| 主应用 | 通知列表 | `/notifications` | [通知页](./pages/notifications.md) | 已修复并本地复测通过 |
|
||||
| 主应用 | 通知详情 | `/notifications/[scheduledRunId]` | [通知页](./pages/notifications.md) | 已修复并本地复测通过 |
|
||||
| 主应用 | 定时任务 | `/cron` | 待创建 | 待测试 |
|
||||
| 主应用 | 技能列表与详情 | `/skills` | [技能页](./pages/skills.md) | 已修复并复测通过 |
|
||||
| 主应用 | 文件管理与预览 | `/files` | [文件页](./pages/files.md) | 已修复并复测通过 |
|
||||
| 主应用 | MCP 工具管理 | `/mcp` | [工具页](./pages/mcp-tools.md) | 已修复并复测通过 |
|
||||
| 主应用 | 智能体管理 | `/agents` | 待创建 | 待测试 |
|
||||
| 主应用 | Outlook | `/outlook` | [Outlook 页](./pages/outlook.md) | 已修复并复测通过 |
|
||||
| 主应用 | 技能市场与详情 | `/marketplace` | [市场页](./pages/marketplace.md) | 已修复并复测通过 |
|
||||
| 主应用 | 配置 | `/settings` | [配置页](./pages/settings.md) | 已修复并复测通过 |
|
||||
| 主应用 | 系统状态 | `/status` | [配置页](./pages/settings.md) | 与配置页同实现,已复测通过 |
|
||||
| 主应用 | 日志 | `/logs` | 待创建 | 待测试 |
|
||||
|
||||
## 当前测试环境
|
||||
|
||||
- 浏览器自动化:Playwright Chromium。
|
||||
- Browser 插件:本轮不可用,使用 Playwright fallback。
|
||||
- 登录页测试日期:2026-06-04。
|
||||
- 登录页测试结果:自动化用例执行通过;所有实测视口无页面横向越界、无小点击目标、无首屏控件出界。
|
||||
- 对话工作台测试日期:2026-06-04。
|
||||
- 对话工作台测试结果:自动化用例 `4 passed`;使用模拟 API 数据完成真实浏览器点击、键盘、响应式测量和截图;所有实测视口无页面横向越界、无可见小点击目标。
|
||||
- Task 任务页测试日期:2026-06-04。
|
||||
- Task 任务页测试结果:自动化用例 `14 passed`;覆盖普通任务、定时任务、任务详情和缺省态;所有实测视口无页面横向越界、无可见小点击目标。
|
||||
- 通知页测试日期:2026-06-04。
|
||||
- 通知页测试结果:本地自动化用例 `4 passed`;覆盖通知列表、通知详情、空态、错误态和回复交互;所有实测视口无页面横向越界、无可见小点击目标。
|
||||
- 技能页测试日期:2026-06-04。
|
||||
- 技能页测试结果:本地与 `terminaltest` 自动化用例均 `3 passed`;覆盖候选操作、草稿评审操作和草稿页响应式;候选/草稿操作后不再回到已发布页,所有实测视口无页面横向越界、无可见小点击目标。
|
||||
- 文件页测试日期:2026-06-04。
|
||||
- 文件页测试结果:本地与 `terminaltest` 自动化用例均 `4 passed`;覆盖根目录空态、创建文件夹、目录切换、Markdown 预览、下载、删除、错误态和响应式;所有实测视口无页面横向越界、无可见小点击目标。
|
||||
- 工具页测试日期:2026-06-04。
|
||||
- 工具页测试结果:本地与 `terminaltest` 自动化用例均 `4 passed`;覆盖服务选择、工具详情、Tab 切换、Test、Add、Edit、Delete confirm、Refresh、JSON 错误、加载错误和响应式;所有实测视口无页面横向越界、无可见小点击目标。
|
||||
- Outlook 页测试日期:2026-06-04。
|
||||
- Outlook 页测试结果:本地与 `terminaltest` 自动化用例均 `4 passed`;覆盖已配置状态、overview 加载、Inbox、邮件详情、Calendar、日程详情、Settings、Test、Save、Disconnect confirm、状态错误和响应式;所有实测视口无页面横向越界、无可见小点击目标。
|
||||
- 市场页与配置页测试日期:2026-06-04。
|
||||
- 市场页与配置页测试结果:本地与 `terminaltest` 自动化用例均 `4 passed`;覆盖市场搜索、详情、文件预览、安装、配置页智能体保存、Provider 保存、Feishu 通道保存、重启确认、状态错误和响应式;所有实测视口无页面横向越界、无可见小点击目标。
|
||||
220
docs/ui-ux/pages/auth-login.md
Normal file
220
docs/ui-ux/pages/auth-login.md
Normal file
@ -0,0 +1,220 @@
|
||||
# 认证门户:登录页 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | 认证门户登录页 |
|
||||
| 真实页面路由 | `/login?next=<目标路径>` |
|
||||
| 页面实现 | `auth-portal/src/app/login/page.tsx` |
|
||||
| 样式实现 | `auth-portal/src/app/globals.css` |
|
||||
| API 客户端 | `auth-portal/src/lib/auth-client.ts` |
|
||||
| 主应用入口关系 | 主应用 `/login` 只显示跳转提示并重定向到认证门户,不承载登录表单 |
|
||||
| 核心任务 | 输入用户名和密码,完成认证后通过 handoff 返回目标工作区页面 |
|
||||
| 测试状态 | 已完成修复并复测通过;所有实测视口无横向越界、无小点击目标、无首屏控件出界 |
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
portal-page
|
||||
├── portal-toolbar 层级 z-index: 10,右上角
|
||||
│ └── LanguageSwitcher
|
||||
│ ├── Lang 标签
|
||||
│ ├── ZH 按钮
|
||||
│ └── EN 按钮
|
||||
└── auth-page 全屏背景层
|
||||
└── portal-panel 登录卡片定位容器
|
||||
└── auth-card.login-card 登录主容器,手机竖屏与横屏均做紧凑适配
|
||||
├── Boardware Logo
|
||||
├── 页面标题
|
||||
├── auth-form
|
||||
│ ├── 用户名字段
|
||||
│ │ ├── 可见 label
|
||||
│ │ ├── 用户图标
|
||||
│ │ └── 用户名 input
|
||||
│ ├── 密码字段
|
||||
│ │ ├── 可见 label
|
||||
│ │ ├── 锁图标
|
||||
│ │ ├── 密码 input
|
||||
│ │ └── 显示或隐藏密码按钮
|
||||
│ ├── 错误信息区域
|
||||
│ └── 登录提交按钮
|
||||
├── “或”分隔线
|
||||
└── 注册引导与注册链接
|
||||
```
|
||||
|
||||
### 层级关系
|
||||
|
||||
- 背景图属于最低视觉层,用于传达产品品牌和 Agent/Memory/Tools 等能力氛围。
|
||||
- 登录卡片是唯一主任务容器,具有半透明白色表面、边框和阴影。
|
||||
- 语言切换器脱离登录卡片,绝对定位在页面右上角,`z-index: 10`。
|
||||
- 表单错误位于密码字段与登录按钮之间,属于当前提交动作的内联反馈。
|
||||
- 页面无弹窗、抽屉或二级详情层。
|
||||
|
||||
## 3. 布局与大概位置
|
||||
|
||||
### 桌面与宽屏,大于 920px
|
||||
|
||||
- 页面占满视口,背景图居中并 `cover`。
|
||||
- 登录卡片位于页面右侧,垂直居中。
|
||||
- `portal-panel` 宽度使用 `clamp(360px, 34vw, 560px)`。
|
||||
- 页面右侧留白由 `clamp(24px, 8vw, 128px)` 控制。
|
||||
- 语言切换器固定在右上角,距顶部约 `20px`,距右侧约 `24px`。
|
||||
- 实测 `1365×900` 和 `1920×1080` 无横向越界、无组件重叠。
|
||||
|
||||
### 平板与中等宽度,小于等于 920px
|
||||
|
||||
- 登录卡片从右侧布局切换为水平居中、靠近页面底部。
|
||||
- 容器最大宽度约 `520px`。
|
||||
- 页面顶部保留品牌背景展示空间。
|
||||
- 实测 `768×1024` 和 `1024×768` 无横向越界、无组件重叠。
|
||||
|
||||
### 手机,小于等于 640px
|
||||
|
||||
- 页面左右边距约 `16px`。
|
||||
- 登录卡片在矮屏手机下进入紧凑节奏,缩小 Logo、标题和表单间距。
|
||||
- 输入框高度约 `54px`,字号 `16px`,可避免 iOS 输入自动缩放。
|
||||
- `320×568`、`375×667`、`390×844` 均可在首屏完整展示主要内容。
|
||||
|
||||
### 手机横屏
|
||||
|
||||
- 实测 `844×390` 时使用横屏紧凑布局,主要控件完整位于视口内。
|
||||
- 页面无横向越界,无双层滚动。
|
||||
|
||||
## 4. 页面状态
|
||||
|
||||
| 状态 | 当前表现 | UX 目的 | 测试结论 |
|
||||
| --- | --- | --- | --- |
|
||||
| 初始状态 | 显示 Logo、标题、空用户名和密码、登录按钮、注册入口 | 清晰建立品牌和唯一主任务 | 通过 |
|
||||
| 输入状态 | 输入框显示文本;密码默认掩码 | 防止密码旁观泄露 | 通过 |
|
||||
| 密码可见状态 | 点击眼睛按钮后,密码类型切换为 `text`,按钮名称同步变为“隐藏密码” | 降低密码输入错误 | 通过 |
|
||||
| 浏览器必填校验 | 空表单提交被浏览器阻止,并聚焦用户名 | 避免无效网络请求 | 通过 |
|
||||
| 提交中 | 登录按钮禁用,并显示“登录中...” | 防止重复提交,告知请求正在处理 | 通过 |
|
||||
| 登录失败 | 在密码字段下方显示友好错误,按钮恢复可用,错误区域可被播报并获得焦点 | 让用户修正凭据后重试 | 通过 |
|
||||
| 登录成功 | 构造 `/handoff?code=...&next=...` 并使用 `location.replace` 跳转 | 安全把认证结果交给目标工作区,并避免返回到已提交登录页 | 通过 |
|
||||
| 语言切换 | ZH/EN 立即更新字段、错误和辅助文案,并写入 cookie/localStorage | 支持中英文用户并保持选择 | 通过,刷新后保持 |
|
||||
| 注册跳转 | 跳转到 `/register` 并保留 `next` 参数 | 注册完成后仍返回原目标页 | 通过 |
|
||||
|
||||
## 5. 操作与 UX 逻辑
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 切换中文或英文 | 点击右上角 ZH/EN | 当前语言按钮高亮;页面文案立即更新;刷新后保持 | 降低语言理解成本 | 正常 |
|
||||
| 聚焦用户名或密码 | 点击或 Tab | 输入框边框、背景和外部阴影变化 | 明确当前输入位置 | 正常 |
|
||||
| 输入用户名 | 键盘输入 | 受控输入更新,支持 `autocomplete=username` | 减少重复输入 | 正常 |
|
||||
| 输入密码 | 键盘输入 | 默认掩码,支持 `autocomplete=current-password` | 保护敏感信息并支持密码管理器 | 正常 |
|
||||
| 显示或隐藏密码 | 点击眼睛图标 | `password/text` 类型切换,可访问名称同步切换 | 帮助用户核对密码 | 正常 |
|
||||
| 空表单提交 | 点击提交或按 Enter | 浏览器原生 required 校验阻止请求并聚焦用户名 | 及早阻止无效操作 | 正常 |
|
||||
| 有效表单提交 | 点击提交或在密码框按 Enter | 清空旧错误;按钮禁用;显示加载文案;发起登录请求 | 提供明确进度并防止重复提交 | 正常 |
|
||||
| 登录失败 | API 返回失败 | 显示本地化错误;按钮恢复可用;错误区域 `role="alert"`/`aria-live` 并获得焦点 | 支持修正后重试 | 正常 |
|
||||
| 登录成功 | API 返回 token 和 handoff code | 使用 `location.replace` 前往目标前端 handoff 页,保留 `next` | 完成认证并返回原任务 | 正常 |
|
||||
| 前往注册 | 点击注册链接 | 前往注册页并保留 `next` | 为无账号用户提供明确替代路径 | 正常 |
|
||||
|
||||
## 6. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。
|
||||
|
||||
| 视口 | 横向越界 | 页面纵向滚动 | 卡片内部滚动 | 卡片完整位于视口 | 结论 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `320×568` | 无 | 无 | 无 | 是 | 通过 |
|
||||
| `375×667` | 无 | 无 | 无 | 是 | 通过 |
|
||||
| `390×844` | 无 | 无 | 无 | 是 | 通过 |
|
||||
| `844×390` 横屏 | 无 | 无 | 无 | 是 | 通过 |
|
||||
| `768×1024` | 无 | 无 | 无 | 是 | 通过 |
|
||||
| `1024×768` | 无 | 无 | 无 | 是 | 通过 |
|
||||
| `1365×900` | 无 | 无 | 无 | 是 | 通过 |
|
||||
| `1920×1080` | 无 | 无 | 无 | 是 | 通过 |
|
||||
|
||||
## 7. 可访问性与触控检查
|
||||
|
||||
### 已通过
|
||||
|
||||
- 页面存在一个清晰的 `h1`。
|
||||
- Logo 有 `alt="Boardware logo"`。
|
||||
- 用户名和密码均存在与 input 关联的 label。
|
||||
- Tab 顺序符合 DOM 和视觉顺序:ZH → EN → 用户名 → 密码 → 显示密码 → 登录 → 注册。
|
||||
- 密码显示按钮具有动态可访问名称。
|
||||
- 用户名和密码支持浏览器自动填充。
|
||||
- 输入框、语言按钮、显示密码按钮、提交按钮和注册链接的实际命中区域均不小于 `44×44px`。
|
||||
- 登录按钮具有本地化可访问名称。
|
||||
- 登录失败错误使用 `role="alert"` 与 `aria-live`,并在失败后聚焦错误区域。
|
||||
|
||||
### 待继续观察
|
||||
|
||||
- 本轮未使用真实屏幕阅读器做端到端朗读,只通过 DOM、焦点和 Playwright 辅助信息验证。
|
||||
- 登录背景图片仍可继续做 WebP/AVIF 与响应式加载优化。
|
||||
|
||||
## 8. 已修复问题与遗留优化
|
||||
|
||||
### 已修复:手机横屏双层纵向滚动
|
||||
|
||||
- 复现:使用 `844×390` 访问登录页。
|
||||
- 用户看到:卡片底部超出首屏;页面可滚动,卡片内部也可滚动。
|
||||
- 影响:用户难以判断应滚动页面还是卡片;单独滚动卡片后仍无法看到注册链接。
|
||||
- 相关实现:
|
||||
- `.auth-page` 在 `<=920px` 时保留顶部和底部 padding。
|
||||
- `.auth-card.login-card` 同时设置基于 `100vh` 的 `max-height` 和 `overflow-y:auto`。
|
||||
- 复测结论:`844×390` 无横向越界、无双层滚动,提交和注册入口均在首屏可达。
|
||||
|
||||
### 已修复:登录按钮缺少可访问名称
|
||||
|
||||
- 复现:使用键盘 Tab 到登录按钮,或检查辅助功能树。
|
||||
- 用户影响:屏幕阅读器只能识别为无名称按钮。
|
||||
- 相关实现:提交按钮默认仅渲染箭头 SVG,SVG 为 `aria-hidden`。
|
||||
- 复测结论:按钮拥有本地化 `aria-label`,加载状态继续表达“登录中”。
|
||||
|
||||
### 已修复:错误反馈缺少可访问播报和焦点恢复
|
||||
|
||||
- 复现:提交错误凭据。
|
||||
- 当前反馈:显示“接口错误 401: 用户名或密码错误”,但无 `role="alert"`、无 `aria-live`,失败后焦点未落在错误或字段上。
|
||||
- 用户影响:技术错误码增加理解成本;屏幕阅读器和键盘用户可能不知道提交已经失败。
|
||||
- 复测结论:
|
||||
- 用户文案不暴露 HTTP 状态与“接口错误”前缀。
|
||||
- 文案说明原因和恢复方式,例如“用户名或密码错误,请检查后重试”。
|
||||
- 错误使用 `role="alert"`/`aria-live`,并聚焦错误摘要。
|
||||
|
||||
### 已修复:关键次级操作点击区域过小
|
||||
|
||||
- 影响范围:语言按钮、显示密码按钮、注册链接。
|
||||
- 复测结论:语言按钮、显示密码按钮、提交和注册链接实际命中区域均达到至少 `44×44px`。
|
||||
|
||||
### 遗留优化:登录背景资源偏大
|
||||
|
||||
- `login-background.png` 约 `1.3MB`,当前未提供 WebP/AVIF 或响应式尺寸。
|
||||
- 用户影响:弱网和移动网络下首屏背景显示较慢。
|
||||
- 建议验收标准:提供 WebP/AVIF,并根据视口加载合理尺寸;保留背景空间避免布局变化。
|
||||
|
||||
## 9. 当前实现的正向 UX
|
||||
|
||||
- 页面只有一个主操作,层级清晰。
|
||||
- 桌面使用背景品牌视觉和右侧卡片,主任务聚焦明确。
|
||||
- 手机输入字号为 `16px`,避免 iOS 自动放大。
|
||||
- 请求中禁用提交按钮,可防止重复登录。
|
||||
- 错误区域预留最小高度,错误出现时不会明显推动后续内容。
|
||||
- `next` 参数在注册跳转和成功 handoff 中均正确保留。
|
||||
- 语言选择刷新后保持。
|
||||
- 所有实测视口均无横向越界。
|
||||
|
||||
## 10. 后续验收清单
|
||||
|
||||
- [x] 修复横屏双层滚动后,重新测试 `844×390` 和更低高度视口。
|
||||
- [x] 为提交按钮添加本地化可访问名称。
|
||||
- [x] 改善登录失败文案、错误播报和焦点恢复。
|
||||
- [x] 扩大语言、显示密码和注册链接的触控区域。
|
||||
- [x] 评估并实现持续可见的字段标签。
|
||||
- [ ] 优化登录背景图片格式和响应式加载。
|
||||
- [ ] 在 Safari、iOS Safari 和 Android Chrome 验证动态地址栏与 `100vh` 行为。
|
||||
- [ ] 使用屏幕阅读器完成一次端到端登录测试。
|
||||
|
||||
## 11. 本轮测试证据
|
||||
|
||||
- 自动化结果:`/tmp/beaver-login-qa-results.json`
|
||||
- 截图目录:`/tmp/beaver-login-qa-shots`
|
||||
- 临时测试脚本:`/tmp/beaver-ui-qa-tests/login-page-qa.spec.js`
|
||||
- 测试命令:
|
||||
|
||||
```bash
|
||||
./node_modules/.bin/playwright test login-page-qa.spec.js \
|
||||
--config=/tmp/beaver-ui-qa-tests/pw.config.js \
|
||||
--workers=1
|
||||
```
|
||||
346
docs/ui-ux/pages/chat-workbench.md
Normal file
346
docs/ui-ux/pages/chat-workbench.md
Normal file
@ -0,0 +1,346 @@
|
||||
# 主应用:对话工作台 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | 对话工作台 |
|
||||
| 路由 | `/` |
|
||||
| 页面实现 | `app-instance/frontend/app/(app)/page.tsx` |
|
||||
| 全局外壳 | `components/AppShell.tsx`、`components/Header.tsx`、`components/AuthGuard.tsx`、`components/AppRuntimeBridge.tsx` |
|
||||
| 消息区 | `components/chat-workbench/ChatWorkbench.tsx`、`MessageList.tsx`、`AgentTeamBlock.tsx` |
|
||||
| 进度区 | `components/chat-workbench/CurrentSessionProgressSidebar.tsx` |
|
||||
| 核心任务 | 选择或创建会话,发送文本或附件,与 Assistant 协作并处理任务验收 |
|
||||
| 测试状态 | 已完成修复并复测通过;所有实测视口无页面横向越界、无小点击目标,核心交互可用 |
|
||||
|
||||
本页是主应用默认工作区。它同时承载全局导航、会话管理、消息时间线、Agent 运行过程、任务验收、附件上传、消息输入和当前任务进度。
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
AppShell
|
||||
├── Header 固定头部,z-index: 50,高 64px
|
||||
│ ├── Beaver 品牌入口
|
||||
│ ├── 桌面主导航:对话、Task、通知、技能、文件、工具、智能体、Outlook、市场、配置
|
||||
│ ├── 窄屏菜单按钮与移动导航面板
|
||||
│ ├── 连接状态
|
||||
│ ├── LanguageSwitcher
|
||||
│ └── 账号按钮
|
||||
│ └── Account Popover 浮层,含账号信息和退出登录
|
||||
└── main.pt-16
|
||||
└── AuthGuard
|
||||
├── AppRuntimeBridge 会话列表、WebSocket 与运行状态同步
|
||||
└── ChatPage 高度 calc(100vh - 4rem)
|
||||
├── Desktop Session Sidebar md 及以上左侧固定 280px
|
||||
│ ├── 新对话按钮
|
||||
│ └── 最近对话滚动列表
|
||||
│ └── 会话选择按钮 + 44px 归档按钮
|
||||
├── Mobile Session Drawer 手机最近对话抽屉
|
||||
├── Conversation Column 中央弹性宽度
|
||||
│ ├── ChatWorkbench
|
||||
│ │ └── MessageList
|
||||
│ │ ├── 空状态
|
||||
│ │ ├── 用户消息
|
||||
│ │ ├── Assistant Markdown 消息
|
||||
│ │ ├── 消息附件
|
||||
│ │ ├── 任务卡与查看任务链接
|
||||
│ │ ├── 验收操作与内联反馈面板
|
||||
│ │ ├── Agent Team / Subtask 卡片
|
||||
│ │ └── 思考中状态
|
||||
│ └── Composer
|
||||
│ ├── 当前任务或修改任务状态胶囊
|
||||
│ ├── 待上传附件列表
|
||||
│ └── 输入器
|
||||
│ ├── textarea
|
||||
│ ├── 添加附件
|
||||
│ ├── 思考模式
|
||||
│ └── 发送
|
||||
└── Current Session Progress
|
||||
├── >= xl:右侧固定 380px 侧栏
|
||||
└── < xl:右上角浮动按钮 + 右侧抽屉
|
||||
```
|
||||
|
||||
## 3. 布局、位置与层级
|
||||
|
||||
### 全局头部
|
||||
|
||||
- 固定在视口顶部,高度 `64px`,页面主体使用 `pt-16` 避免被遮挡。
|
||||
- 桌面宽屏显示品牌、完整主导航、连接状态、语言和账号。
|
||||
- `2xl` 以下收起完整导航,显示菜单按钮;点击后从左侧滑入独立导航抽屉。
|
||||
- 移动导航抽屉使用完全不透明的应用背景色、右侧阴影和独立滚动;抽屉外显示深色遮罩,底层页面不可交互且不会透过抽屉显示。
|
||||
- “对话、通知、技能”等导航项区域和每个导航项均显式使用不透明应用表面背景,不依赖底层页面或透明父容器。
|
||||
- 抽屉最大宽度为 `320px`,不会在平板或窄屏桌面退化为横向铺满的双列透明菜单。
|
||||
- 层级顺序为页面内容 < 遮罩 < 导航抽屉 < 固定头部;打开时锁定页面滚动。
|
||||
- 账号和语言入口在 `320px` 到宽屏范围内始终可达。
|
||||
|
||||
### 工作台主体
|
||||
|
||||
- 主体为横向 `flex`,高度 `calc(100vh - 4rem)`。
|
||||
- 左侧会话栏在 `md` 及以上显示;手机默认隐藏,使用“最近对话”按钮打开抽屉。
|
||||
- 中央对话列使用 `flex-1 min-w-0`,消息区占剩余高度,输入器固定在对话列底部。
|
||||
- 输入器外层在手机使用较小左右边距,`md` 及以上恢复桌面边距;textarea 高度范围为 `72px` 到 `200px`。
|
||||
- 当存在运行中任务时:
|
||||
- `xl` 及以上显示右侧固定 `380px` 进度栏。
|
||||
- 小于 `xl` 时显示右上角 `44×44px` 浮动按钮,点击后打开右侧抽屉。
|
||||
|
||||
### 消息与运行过程
|
||||
|
||||
- 消息时间线使用独立滚动区域,中央内容最大宽度 `5xl`。
|
||||
- 用户消息右对齐、深色圆角气泡;Assistant 消息左对齐、透明背景。
|
||||
- Assistant 创建任务后显示任务卡;待验收消息下方显示接受、需要修改、放弃。
|
||||
- Agent Team 作为较大的运行过程区块插入消息时间线,内部 Subtask 卡片可横向排列并点击选中。
|
||||
- 当前任务状态胶囊位于输入器上方,点击可前往任务详情。
|
||||
|
||||
### 弹层与覆盖层
|
||||
|
||||
| 层 | 触发入口 | 当前行为 |
|
||||
| --- | --- | --- |
|
||||
| 账号 Popover | 头部账号按钮 | 右对齐浮层;点击按钮打开;`Escape` 关闭;退出登录后跳往认证门户 |
|
||||
| 移动导航抽屉 | `2xl` 以下的汉堡菜单 | 左侧滑入不透明面板;显示背景遮罩;点击遮罩、导航项或按 `Escape` 关闭 |
|
||||
| 进度抽屉 | `< xl` 的右上角进度按钮 | 背景遮罩 + 右侧抽屉;点击遮罩或关闭按钮可关闭 |
|
||||
| 接受反馈面板 | 待验收消息的“接受” | 在消息下方内联展开,不遮挡页面 |
|
||||
| 修改任务状态 | 待验收消息的“需要修改” | 不打开弹窗;聚焦底部输入器并切换提示文案 |
|
||||
| 放弃确认弹窗 | 待验收消息的“放弃” | 先说明后果,确认后才提交 `abandon` |
|
||||
| 归档确认弹窗 | 会话行归档按钮 | 先说明会话将从最近对话移除,确认后归档 |
|
||||
|
||||
## 4. 页面状态
|
||||
|
||||
| 状态 | 当前表现 | UX 目的 | 测试结论 |
|
||||
| --- | --- | --- | --- |
|
||||
| 认证加载 | `AuthGuard` 显示加载中 | 避免未认证内容闪现 | 本轮未单独注入慢认证 |
|
||||
| 空会话 | 中央显示 Beaver 和“发送消息开始对话” | 给出明确起点 | 通过 |
|
||||
| 已加载会话 | 显示消息、任务卡和运行过程 | 恢复历史上下文 | 通过 |
|
||||
| 切换会话 | 更新消息、进度、当前任务和输入草稿 | 快速在多任务间切换 | 通过,逐会话草稿正常保留 |
|
||||
| 思考模式关闭或开启 | 按钮使用 `aria-pressed`,状态写入 localStorage | 让用户控制推理深度并保持偏好 | 通过 |
|
||||
| 输入与换行 | `Enter` 发送,`Shift+Enter` 换行 | 提高聊天输入效率 | 通过 |
|
||||
| 空输入 | 发送按钮禁用 | 防止无效提交 | 通过 |
|
||||
| 发送中或思考中 | 禁用发送,并显示思考中状态 | 防止重复发送并提供过程反馈 | HTTP 模拟流程通过;真实 WebSocket 流未测 |
|
||||
| 附件上传中 | 显示文件名、大小和进度条 | 表达上传进度 | 模拟上传通过 |
|
||||
| 附件就绪 | 显示“就绪”,可移除 | 发送前确认附件 | 通过,但移除按钮可访问性不合格 |
|
||||
| 待验收 | 显示接受、需要修改、放弃 | 让用户决定任务后续 | 三类操作均通过 |
|
||||
| 接受反馈展开 | 显示可选备注、取消和提交 | 支持带上下文验收 | 通过 |
|
||||
| 修改任务 | 输入器切换为修改要求并自动聚焦 | 降低修改路径成本 | 通过 |
|
||||
| 放弃任务 | 点击后打开确认弹窗,确认后提交并显示已放弃 | 防止误终止任务 | 通过 |
|
||||
| 进度侧栏或抽屉 | 显示整体进度、步骤和产物 | 在不离开对话的情况下理解执行状态 | 通过 |
|
||||
| 账号弹层 | 显示账号信息和退出按钮 | 提供会话级账号入口 | 打开、Escape 关闭、退出登录均通过 |
|
||||
|
||||
## 5. 操作与 UX 逻辑
|
||||
|
||||
### 全局头部
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 返回对话页 | 点击 Beaver 或“对话” | 导航到 `/` | 提供稳定主页入口 | 正常 |
|
||||
| 主导航切换 | 桌面点击导航项;窄屏点击菜单后选择导航项 | 前往对应主应用页面,当前项高亮 | 在产品模块间切换 | 正常 |
|
||||
| 切换 ZH/EN | 点击语言按钮 | 页面文案立即变化并持久化 | 支持中英文用户 | 正常 |
|
||||
| 打开账号弹层 | 点击账号按钮 | 显示账号信息与退出登录 | 集中账号操作 | 宽屏和移动端均正常 |
|
||||
| 关闭账号弹层 | 按 `Escape` 或点击外部 | 浮层关闭并返回原页面 | 提供清晰退出路径 | `Escape` 实测正常 |
|
||||
| 退出登录 | 点击退出登录 | 清除 access/refresh token,跳往认证门户 `/login?next=/` | 安全退出并保留返回路径 | 正常 |
|
||||
|
||||
### 会话栏
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 新对话 | 点击顶部主按钮 | 创建新 session、清空消息和输入、显示空状态 | 快速开始新任务 | 正常 |
|
||||
| 选择会话 | 点击会话按钮,或键盘聚焦后 Enter/Space | 切换消息、当前任务、运行进度和草稿 | 支持并行工作 | 正常 |
|
||||
| 保留草稿 | 在不同会话输入后切换 | 每个 session 恢复各自草稿 | 防止上下文切换丢失输入 | 正常 |
|
||||
| 归档会话 | 点击会话行右侧 44px 归档按钮并确认 | 归档后从列表移除;失败时插入 Assistant 错误消息 | 清理历史会话并降低误操作 | 正常 |
|
||||
|
||||
### 消息、任务与 Agent 过程
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 查看任务 | 点击消息任务卡或当前任务胶囊 | 前往 `/tasks/<taskId>` | 深入任务详情 | 路由实测正常 |
|
||||
| 查看消息附件 | 点击图片或文件链接 | 图片新窗口打开;文件下载 | 获取 Assistant 或用户提供的内容 | 本轮未连接真实文件服务 |
|
||||
| 选择 Agent 卡片 | 点击 Subtask 卡片 | 卡片出现选中 ring | 明确当前关注的运行单元 | 正常 |
|
||||
| 接受任务 | 点击“接受” | 展开可选备注面板 | 在提交前允许补充验收上下文 | 正常 |
|
||||
| 取消接受 | 点击反馈面板“取消” | 关闭面板并清空备注 | 避免误提交 | 正常 |
|
||||
| 提交接受 | 输入可选备注后点击“提交” | 提交 `accept`,显示“已接受” | 完成任务验收 | 正常 |
|
||||
| 请求修改 | 点击“需要修改” | 输入器自动聚焦并切换修改提示;发送后提交 `revise` | 让修改请求复用主输入器 | 正常 |
|
||||
| 放弃任务 | 点击“放弃”后确认 | 确认后提交 `abandon`,显示已放弃 | 终止不再需要的任务并降低误操作 | 正常 |
|
||||
|
||||
### 输入器与附件
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 输入消息 | 点击 textarea 并输入 | 自动增长,最大高度 `200px`;写入当前会话草稿 | 支持多行消息并防止输入丢失 | 正常 |
|
||||
| 换行 | `Shift+Enter` | 插入换行,不发送 | 支持结构化输入 | 正常 |
|
||||
| 键盘发送 | `Enter` | 清空输入、显示用户消息、等待回复 | 提高高频对话效率 | 正常 |
|
||||
| 点击发送 | 点击发送按钮 | 与键盘发送相同 | 为鼠标和触控提供明确入口 | 正常 |
|
||||
| 空输入发送 | 空输入时点击或按 Enter | 发送按钮禁用,无请求 | 防止无效提交 | 正常 |
|
||||
| 添加附件 | 点击加号并选择文件 | 上传并显示进度、错误或就绪状态 | 在对话中补充文件上下文 | 模拟上传正常 |
|
||||
| 超过 50MB 文件 | 选择过大文件 | 前端显示“最大 50MB”错误 | 及早阻止无效上传 | 代码路径确认;本轮未真实构造 50MB 文件 |
|
||||
| 移除待发送附件 | 点击附件行右侧 X | 从待发送列表移除 | 发送前修正附件选择 | 正常,按钮有文件名相关可访问名称 |
|
||||
| 切换思考模式 | 点击“思考” | `aria-pressed` 切换并持久化 | 让用户控制回答方式 | 正常 |
|
||||
|
||||
### 进度面板
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 查看桌面进度 | `xl` 及以上自动显示 | 右侧固定展示进度、步骤和产物 | 保持过程透明 | 正常 |
|
||||
| 打开进度抽屉 | `< xl` 点击右上角浮动按钮 | 打开遮罩和右侧抽屉 | 在较窄空间按需查看进度 | 正常 |
|
||||
| 关闭进度抽屉 | 点击 X 或遮罩 | 返回对话页 | 避免抽屉阻塞主任务 | 正常 |
|
||||
| 打开产物链接 | 点击产物行 | 有 URL 时新窗口打开 | 快速访问结果 | 本轮未访问外部 URL |
|
||||
|
||||
## 6. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。页面使用模拟 API 数据,所有布局渲染、点击、键盘操作和截图均在真实浏览器中执行。
|
||||
|
||||
| 视口 | 页面横向越界 | textarea 实测宽度 | 会话栏 | 进度展示 | 结论 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `320×568` | 无 | `262px` | 移动抽屉 | 抽屉可打开 | 通过 |
|
||||
| `375×667` | 无 | `317px` | 移动抽屉 | 抽屉可打开 | 通过 |
|
||||
| `390×844` | 无 | `332px` | 移动抽屉 | 抽屉可打开 | 通过 |
|
||||
| `844×390` 横屏 | 无 | `466px` | 固定 `280px` | 抽屉可打开 | 通过 |
|
||||
| `768×1024` | 无 | `390px` | 固定 `280px` | 抽屉可打开 | 通过 |
|
||||
| `1024×768` | 无 | `646px` | 固定 `280px` | 抽屉可打开 | 通过 |
|
||||
| `1365×900` | 无 | `607px` | 固定 `280px` | 固定右栏 `380px` | 通过 |
|
||||
| `1920×1080` | 无 | `990px` | 固定 `280px` | 固定右栏 `380px` | 通过 |
|
||||
|
||||
### 关键量化证据
|
||||
|
||||
- `320px`、`375px`、`390px` 手机竖屏均无页面横向越界。
|
||||
- 手机竖屏 textarea 实测宽度分别为 `262px`、`317px`、`332px`。
|
||||
- `390px` 手机宽度下,账号入口 `44×44px` 且完整位于视口内。
|
||||
- `1365px` 宽度下,账号入口完整位于视口内,完整导航收起为菜单入口。
|
||||
- 最终复测中抽样视口可见小目标数为 `0`。
|
||||
|
||||
## 7. 可访问性与触控检查
|
||||
|
||||
### 已通过
|
||||
|
||||
- 发送按钮具有本地化 `aria-label`。
|
||||
- 思考模式使用 `aria-pressed` 表达开关状态。
|
||||
- 归档按钮、进度按钮和进度关闭按钮具有可访问名称。
|
||||
- 账号 Popover 可使用 `Escape` 关闭。
|
||||
- 修改任务后焦点自动移动到主输入器。
|
||||
- 空输入时发送按钮使用原生 `disabled`。
|
||||
- 长连续文本在桌面消息气泡中正常换行,未引发页面横向越界。
|
||||
- 会话选择使用语义按钮,并通过 `aria-current` 表达当前会话。
|
||||
- 附件移除按钮具有包含文件名的可访问名称。
|
||||
- 主输入器和反馈输入器均有 label 关联。
|
||||
- 所有最终抽样视口中,可见可交互控件命中区域均不小于 `44×44px`。
|
||||
|
||||
### 已修复
|
||||
|
||||
| 等级 | 问题 | 证据与影响 | 建议验收标准 |
|
||||
| --- | --- | --- | --- |
|
||||
| P1 | 会话行不可键盘操作 | 已改为语义按钮 | 支持 Enter/Space,当前会话使用 `aria-current` |
|
||||
| P2 | 归档入口依赖悬停且目标过小 | 已改为 44px 归档按钮,并支持键盘焦点显示 | 触控环境可操作,目标至少 `44×44px` |
|
||||
| P2 | 待发送附件移除按钮无名称且过小 | 已添加“移除附件 <文件名>”名称并扩大到 44px | 屏幕阅读器和触控均可用 |
|
||||
| P2 | 多个关键操作小于 `44px` | 已扩大导航、语言、账号、任务链接、反馈、附件、思考模式等控件 | 最终抽样视口小目标数为 `0` |
|
||||
| P2 | 主输入器和反馈输入器仅使用 placeholder | 已补充 label | 输入后仍有稳定字段语义 |
|
||||
| P2 | 归档与放弃缺少确认或撤销 | 已补充站内确认弹窗 | 操作需确认后执行 |
|
||||
|
||||
## 8. 已修复问题与仍需观察项
|
||||
|
||||
### 已修复:手机竖屏下对话核心流程不可用
|
||||
|
||||
- 复现:使用 `320×568`、`375×667` 或 `390×844` 访问 `/`。
|
||||
- 用户看到:左侧 `280px` 会话栏占据绝大部分视口,中央消息与输入器被压缩到右侧细条;需要横向滚动。
|
||||
- 实测证据:文档宽度为 `549px`;textarea 可见宽度仅 `16px`。
|
||||
- 影响:用户无法正常阅读消息、输入内容或使用发送与反馈操作。
|
||||
- 相关实现:
|
||||
- `app/(app)/page.tsx` 的会话栏始终为 `w-[280px] shrink-0`。
|
||||
- 输入器始终保留 `px-8`。
|
||||
- 复测结论:
|
||||
- 手机竖屏无页面横向滚动。
|
||||
- 会话列表改为抽屉,默认优先显示对话内容。
|
||||
- 输入器在 `320px` 宽度仍可完整输入和发送。
|
||||
|
||||
### 已修复:全局头部缺少响应式策略
|
||||
|
||||
- 复现:在 `1365px` 及以下查看头部。
|
||||
- 用户看到:
|
||||
- `1365px` 时连接状态、语言和账号区域相互挤压,账号入口右侧被裁切。
|
||||
- `1024px`、`768px`、`390px` 时大量导航与账号入口位于视口外。
|
||||
- 实测证据:
|
||||
- `1365px` 时账号入口右边界 `1392px`。
|
||||
- `390px` 时账号入口起点 `x=1302px`。
|
||||
- 相关实现:`components/Header.tsx` 始终渲染 10 个完整文字导航项,并使用固定三列网格。
|
||||
- 复测结论:在 `320px` 到 `1365px` 提供可操作的移动或紧凑导航,账号、语言和当前模块入口始终可达。
|
||||
|
||||
### 已修复:会话选择不支持键盘
|
||||
|
||||
- 复现:使用 Tab 键尝试选择最近对话。
|
||||
- 当前结果:会话行是带 `onClick` 的 `div`,无 `role`、无 `tabIndex`,不会进入键盘焦点顺序。
|
||||
- 用户影响:键盘和部分辅助技术用户无法切换会话。
|
||||
- 相关实现:`app/(app)/page.tsx` 会话列表行。
|
||||
- 复测结论:会话项使用语义按钮,支持键盘操作,当前项具有 `aria-current`。
|
||||
|
||||
### 已修复:放弃任务立即执行,无确认或撤销
|
||||
|
||||
- 复现:点击待验收消息的“放弃”。
|
||||
- 当前结果:点击后先打开确认弹窗,确认后才提交 `abandon` 请求。
|
||||
- 用户影响:误触会直接终止任务,恢复路径不明确。
|
||||
- 相关实现:`MessageList.tsx` 的放弃按钮直接调用 `onFeedback(..., 'abandon')`。
|
||||
- 复测结论:放弃前明确说明后果并要求确认。
|
||||
|
||||
### 已修复:会话归档入口可发现性和误操作保护不足
|
||||
|
||||
- 归档按钮默认 `opacity-0`,只有悬停会话行才显示。
|
||||
- 按钮实测约 `18×18px`,触控设备不易发现和点击。
|
||||
- 点击后先打开确认弹窗,确认后归档。
|
||||
- 复测结论:触控环境可操作;命中区域至少 `44×44px`;归档前要求确认。
|
||||
|
||||
### 已修复:关键触控目标普遍偏小
|
||||
|
||||
- 影响范围:头部导航、语言切换、归档、查看任务、接受/修改/放弃、反馈取消/提交、附件、思考模式。
|
||||
- 用户影响:手机、平板和运动能力受限用户更容易误触或漏触。
|
||||
- 复测结论:最终抽样视口可见小目标数为 `0`。
|
||||
|
||||
### 已修复:待发送附件移除按钮缺少可访问名称
|
||||
|
||||
- 复现:添加附件并等待“就绪”。
|
||||
- 当前结果:右侧 X 为无文本、无 `aria-label`、无 `title` 的按钮,尺寸约 `14×14px`。
|
||||
- 复测结论:名称包含操作和文件名,命中区域至少 `44×44px`。
|
||||
|
||||
### 已修复:移动视口高度使用 `100vh`
|
||||
|
||||
- 工作台使用 `h-[calc(100vh-4rem)]`,没有使用动态视口单位。
|
||||
- 用户影响:iOS Safari 等动态地址栏环境中,底部输入器可能被浏览器 UI 遮挡或发生高度跳变。
|
||||
- 复测结论:工作台主体改用 `100dvh`。仍建议在移动真机验证输入法与地址栏变化。
|
||||
|
||||
## 9. 当前实现的正向 UX
|
||||
|
||||
- 新对话、会话切换、发送、修改、验收和进度查看形成完整工作流。
|
||||
- 每个会话独立保留输入草稿,切换后可恢复。
|
||||
- `Enter` 发送和 `Shift+Enter` 换行符合聊天产品惯例。
|
||||
- 空输入时禁用发送;异步发送时避免重复提交。
|
||||
- 修改任务会自动聚焦输入器并切换提示文案,路径清晰。
|
||||
- 接受任务先展开可选备注,允许取消后再提交。
|
||||
- 任务卡和当前任务胶囊均可直接进入任务详情。
|
||||
- 进度面板同时表达总体进度、步骤和产物;小于 `xl` 时抽屉打开与关闭正常。
|
||||
- 账号 Popover 支持 `Escape`,退出登录正确清除 token 并返回认证门户。
|
||||
- 本轮所有实测交互均未产生控制台错误或框架错误覆盖层。
|
||||
|
||||
## 10. 后续验收清单
|
||||
|
||||
- [x] 为手机和窄屏设计会话抽屉、紧凑头部和主对话优先布局。
|
||||
- [x] 修复 `320px`、`375px`、`390px` 横向越界并确保输入器完整可用。
|
||||
- [x] 修复 `1365px` 及以下头部挤压和账号入口越界。
|
||||
- [x] 将会话行改为完整的键盘与辅助技术可操作元素。
|
||||
- [x] 为放弃任务和归档会话增加确认。
|
||||
- [x] 扩大所有关键触控目标到至少 `44×44px`。
|
||||
- [x] 为附件移除按钮添加本地化可访问名称。
|
||||
- [x] 为主输入器和反馈输入器补充明确 label。
|
||||
- [ ] 使用真实 WebSocket、真实上传、网络失败和超时状态复测。
|
||||
- [ ] 测试 50MB 边界、上传失败、发送失败和反馈失败恢复路径。
|
||||
- [ ] 在 iOS Safari、Android Chrome 和桌面 Safari 复测动态视口与输入法。
|
||||
- [ ] 使用屏幕阅读器完成发送、切换会话和任务验收流程。
|
||||
|
||||
## 11. 本轮测试证据
|
||||
|
||||
- 自动化结果:`/tmp/beaver-chat-qa-results.json`
|
||||
- 截图目录:`/tmp/beaver-chat-qa-shots`
|
||||
- 临时测试脚本:`/tmp/beaver-ui-qa-tests/chat-page-qa.spec.js`
|
||||
- API 环境:使用确定性模拟数据;真实浏览器负责页面渲染、点击、键盘、路由、响应式测量与截图。
|
||||
- 自动化结果:`4 passed`。
|
||||
- 测试命令:
|
||||
|
||||
```bash
|
||||
/tmp/beaver-ui-qa-tests/node_modules/.bin/playwright test \
|
||||
/tmp/beaver-ui-qa-tests/chat-page-qa.spec.js \
|
||||
--config=/tmp/beaver-ui-qa-tests/pw.config.js \
|
||||
--workers=1
|
||||
```
|
||||
120
docs/ui-ux/pages/files.md
Normal file
120
docs/ui-ux/pages/files.md
Normal file
@ -0,0 +1,120 @@
|
||||
# 主应用:文件页 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | 文件管理 |
|
||||
| 路由 | `/files` |
|
||||
| 页面实现 | `app-instance/frontend/app/(app)/files/page.tsx` |
|
||||
| 关键组件 | `FilesPage`、`FilePreviewPanel`、`FileIcon`、`ScrollArea` |
|
||||
| 核心任务 | 浏览目录、创建文件夹、上传文件、预览文本/Markdown/图片/二进制文件、下载文件、删除文件或目录 |
|
||||
| 测试状态 | 已修复并复测通过;本地与 `terminaltest` 生产实例均通过 |
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
AppShell
|
||||
└── main.pt-16
|
||||
└── /files
|
||||
├── Page Header
|
||||
│ ├── h1 Files
|
||||
│ ├── New folder
|
||||
│ ├── Upload
|
||||
│ ├── hidden file input
|
||||
│ └── Refresh
|
||||
├── Breadcrumbs
|
||||
│ ├── Files root
|
||||
│ └── 当前路径 segments
|
||||
├── New directory form
|
||||
│ ├── Folder name input
|
||||
│ ├── Create
|
||||
│ └── Cancel
|
||||
└── Content grid
|
||||
├── File list panel
|
||||
│ ├── Loading state
|
||||
│ ├── Error state + Retry
|
||||
│ ├── Empty state
|
||||
│ └── File / Directory rows
|
||||
│ ├── Open / Preview primary button
|
||||
│ ├── Download
|
||||
│ └── Delete
|
||||
└── FilePreviewPanel
|
||||
├── Empty preview
|
||||
├── Loading preview
|
||||
├── Error preview
|
||||
├── File metadata
|
||||
├── Download
|
||||
├── Image preview
|
||||
├── Markdown preview
|
||||
├── Text preview
|
||||
└── Binary fallback
|
||||
```
|
||||
|
||||
## 3. 布局与响应式规则
|
||||
|
||||
- 页面外层使用 `max-w-7xl`,移动端内边距为 `16px`,桌面端为 `24px`。
|
||||
- 内容区默认单列,`lg` 以上改为左侧文件列表、右侧预览双栏。
|
||||
- 左侧文件列表和右侧预览都使用 `min-w-0`,避免长文件名、Markdown、代码块撑破页面。
|
||||
- 文件行移动端为上下结构:上方文件信息,下方下载/删除操作;`sm` 以上恢复横向布局。
|
||||
- 下载/删除在移动端始终可见,桌面端保留 hover 显示。
|
||||
- 根目录也允许创建文件夹和上传文件;空态文案与按钮行为一致。
|
||||
- 面包屑、文件行主按钮、下载、删除、创建、取消、刷新等主要可点击目标均为 `44px` 以上。
|
||||
|
||||
## 4. 操作与 UX 逻辑
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 刷新文件列表 | 点击 Refresh | 调用 browse 接口重新加载当前路径 | 获取最新目录状态 | 正常 |
|
||||
| 根目录新建文件夹 | 点击 New folder,输入名称,点击 Create | 调用 mkdir,成功后刷新列表 | 空 workspace 也能开始组织文件 | 正常 |
|
||||
| 根目录上传文件 | 点击 Upload,选择文件 | 调用 upload,显示进度并刷新列表 | 空 workspace 也能添加文件 | 正常 |
|
||||
| 进入目录 | 点击目录主区域 | 调用 browse,更新 breadcrumbs 和列表 | 浏览层级文件 | 正常 |
|
||||
| 返回上级或根目录 | 点击 breadcrumbs | 调用 browse 对应路径 | 快速导航 | 正常 |
|
||||
| 预览文件 | 点击文件主区域 | 调用 preview,右侧显示内容 | 快速查看文件 | 正常 |
|
||||
| 下载文件 | 点击文件行或预览区 Download | 调用 download,浏览器下载 blob | 获取原始文件 | 正常 |
|
||||
| 删除文件/目录 | 点击 Delete 并确认 | 调用 delete,成功后从列表移除 | 管理文件空间,防误删 | 正常 |
|
||||
| 加载失败 | browse 接口失败 | 显示错误、详情和 Retry | 明确异常恢复路径 | 正常 |
|
||||
| 二进制文件预览 | 文件不可预览 | 显示不可直接预览提示 | 避免乱码 | 正常 |
|
||||
|
||||
## 5. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。环境:本地 dev server `http://127.0.0.1:3080` 与生产实例 `terminaltest`;API 使用模拟数据,真实浏览器执行点击、上传入口、目录切换、预览、下载、删除确认和截图。
|
||||
|
||||
| 页面/状态 | 视口 | 横向越界 | 小触控目标 | 关键结论 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 根目录空态 | `390×844` | 无 | 0 | New folder 和 Upload 在根目录可用 |
|
||||
| 文件预览 | `390×844` | 无 | 0 | 可进入目录、预览 Markdown、下载、删除 |
|
||||
| 加载错误 | `390×844` | 无 | 0 | 错误和 Retry 可见 |
|
||||
| 文件预览 | `320×568` | 无 | 0 | 长文件名、操作按钮、Markdown 预览均未撑破页面 |
|
||||
| 文件预览 | `390×844` | 无 | 0 | 手机竖屏布局清晰 |
|
||||
| 文件预览 | `844×390` 横屏 | 无 | 0 | 横屏无页面级横向滚动 |
|
||||
| 文件预览 | `768×1024` | 无 | 0 | 平板布局稳定 |
|
||||
| 文件预览 | `1365×900` | 无 | 0 | 桌面双栏布局正常 |
|
||||
|
||||
### 关键量化证据
|
||||
|
||||
- 本地文件页 QA 自动化用例 `4 passed`。
|
||||
- 部署到 `terminaltest` 后,同一套文件页 QA 自动化用例 `4 passed`。
|
||||
- 根目录空态中 `New folder` 和 `Upload` 均为 enabled。
|
||||
- 创建文件夹调用 `/api/user-files/mkdir?path=docs`。
|
||||
- 下载调用 `/api/user-files/download`。
|
||||
- 删除调用 `/api/user-files/delete`,并经过浏览器确认。
|
||||
- 实测 `320×568`、`390×844`、`844×390`、`768×1024`、`1365×900` 均无页面级横向越界。
|
||||
- 所有实测视口可见小触控目标数为 `0`。
|
||||
|
||||
## 6. 已修复问题
|
||||
|
||||
| 等级 | 问题 | 修复 |
|
||||
| --- | --- | --- |
|
||||
| P1 | 根目录空态提示可上传/新建,但按钮被禁用 | 根目录允许 New folder 和 Upload |
|
||||
| P1 | `320px` 下文件列表被 `minmax(360px,440px)` 和长文件名撑破页面 | 默认单列改为 `minmax(0,1fr)`,列表和预览加 `min-w-0` |
|
||||
| P1 | 文件行里嵌套下载/删除 role button,移动端不可发现且触控小 | 改为主打开按钮 + 独立下载/删除按钮,移动端始终可见 |
|
||||
| P2 | 文件行长文件名与操作按钮互相挤压 | 移动端文件行改为信息在上、操作在下 |
|
||||
| P2 | Refresh 是 icon-only 且缺少可访问名称 | 补充 `aria-label/title`,命中区为 `44px` |
|
||||
| P2 | 面包屑按钮和文件主按钮触控高度不足 | 固定为 `44px` 以上 |
|
||||
| P2 | Markdown/text 预览长内容可能撑破页面 | 预览区增加容器内换行和 preserved long text 规则 |
|
||||
|
||||
## 7. 剩余观察项
|
||||
|
||||
- 本轮自动化使用模拟 API 数据覆盖常见文件类型;真实大文件、超大图片、深层目录和上传失败恢复仍需持续观察。
|
||||
- 浏览器原生下载行为只验证 download API 被调用,未校验操作系统保存结果。
|
||||
106
docs/ui-ux/pages/marketplace.md
Normal file
106
docs/ui-ux/pages/marketplace.md
Normal file
@ -0,0 +1,106 @@
|
||||
# 主应用:市场页 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | 技能市场 |
|
||||
| 路由 | `/marketplace` |
|
||||
| 页面实现 | `app-instance/frontend/app/(app)/marketplace/page.tsx` |
|
||||
| 关键组件 | `MarketplacePage`、`SkillDetailView`、`Tabs`、`Card`、`Button`、`Input` |
|
||||
| 核心任务 | 搜索 SkillHub 技能、排序筛选、打开详情、查看说明/文件/版本、安装或更新技能 |
|
||||
| 测试状态 | 已修复并复测通过;本地与 `terminaltest` 生产实例均通过 |
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
AppShell
|
||||
└── main.pt-16
|
||||
└── /marketplace
|
||||
├── Page Header
|
||||
│ ├── h1 Marketplace
|
||||
│ └── 页面说明
|
||||
├── Search Form
|
||||
│ ├── 搜索输入框
|
||||
│ └── Search
|
||||
├── Error Card
|
||||
├── Search Results
|
||||
│ ├── Sort Buttons
|
||||
│ ├── Starred only Filter
|
||||
│ ├── Skill Button Cards
|
||||
│ └── Pagination
|
||||
└── Skill Detail
|
||||
├── Back to search
|
||||
├── Detail Header
|
||||
│ ├── namespace/download/star/version badges
|
||||
│ ├── title/summary
|
||||
│ └── Install/Reinstall
|
||||
├── Overview Tab
|
||||
├── Files Tab
|
||||
│ ├── file list
|
||||
│ └── file preview
|
||||
└── Versions Tab
|
||||
└── version rows
|
||||
```
|
||||
|
||||
## 3. 布局与响应式规则
|
||||
|
||||
- 页面外层使用 `max-w-7xl`,移动端内边距为 `16px`,桌面端为 `24px`。
|
||||
- 搜索区在移动端垂直排列,桌面端输入框和 Search 按钮横向排列。
|
||||
- 结果卡片使用真正的 `button` 语义,而不是仅给 Card 绑定 click,键盘和读屏器都能识别为可操作项。
|
||||
- 技能名、namespace、版本号、文件路径、README markdown 和代码预览都允许在容器内断行。
|
||||
- 详情页文件列表和文件预览在桌面端左右分栏,移动端垂直排列。
|
||||
- Tabs、按钮、输入框和分页操作均满足 `44px` 触控目标。
|
||||
- Markdown 中的长代码、表格和链接不会撑出页面;表格在内容区内横向滚动。
|
||||
|
||||
## 4. 操作与 UX 逻辑
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 搜索技能 | 输入关键词后点击 Search 或提交表单 | 调用 SkillHub search,列表刷新 | 快速定位技能 | 正常 |
|
||||
| 切换排序 | 点击 Relevance/Downloads/Newest | 当前排序按钮进入选中态并重新加载 | 支持按不同意图浏览 | 正常 |
|
||||
| 只看收藏 | 点击 Starred only | 本地筛选 starCount 大于 0 的结果 | 聚焦已收藏技能 | 正常 |
|
||||
| 打开技能详情 | 点击技能卡片按钮 | 加载 detail、version list、SKILL.md | 进入安装前审阅 | 正常 |
|
||||
| 返回搜索 | 点击 Back to search | 清空详情状态并回到结果列表 | 提供明确退出路径 | 正常 |
|
||||
| 切换说明/文件/版本 | 点击 tab | 同页切换内容区 | 让审阅信息分层 | 正常 |
|
||||
| 打开文件 | Files tab 点击文件路径 | 加载并预览文件内容 | 审核技能代码或文档 | 正常 |
|
||||
| 切换版本 | Versions tab 点击版本行 | 加载指定版本详情和 README | 安装前比较版本 | 正常 |
|
||||
| 安装技能 | 点击 Install/Reinstall | 调用 install API,按钮 loading,成功后显示 installed | 完成技能接入 | 正常 |
|
||||
| 加载/安装失败 | API 返回错误 | 显示错误卡片,文本断行 | 明确失败原因并保留当前上下文 | 正常 |
|
||||
|
||||
## 5. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。环境:本地 dev server `http://127.0.0.1:3080` 与生产实例 `terminaltest`;API 使用模拟数据,真实浏览器执行点击、输入、详情打开、文件预览、安装和截图。
|
||||
|
||||
| 页面/状态 | 视口 | 横向越界 | 小触控目标 | 关键结论 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 搜索结果 + 详情 | `320×568` | 无 | 0 | 长 skill 名、namespace 和 summary 不撑破页面 |
|
||||
| 搜索结果 + 详情 | `390×844` | 无 | 0 | 可搜索、打开详情、切换文件并安装 |
|
||||
| 搜索结果 + 详情 | `844×390` 横屏 | 无 | 0 | 横屏内容可滚动,不产生页面级横向滚动 |
|
||||
| 搜索结果 + 详情 | `768×1024` | 无 | 0 | 平板详情布局稳定 |
|
||||
| 搜索结果 + 详情 | `1365×900` | 无 | 0 | 桌面分栏和卡片布局正常 |
|
||||
|
||||
### 关键量化证据
|
||||
|
||||
- 本地与 `terminaltest` 市场/配置组合 QA 自动化用例均 `4 passed`,其中覆盖市场流。
|
||||
- 覆盖搜索、详情、文件 tab、长路径文件预览、安装请求和响应式。
|
||||
- 实测 `320×568`、`390×844`、`844×390`、`768×1024`、`1365×900` 均无页面级横向越界。
|
||||
- 所有实测视口可见小触控目标数为 `0`。
|
||||
- 本地截图保存在 `/tmp/beaver-market-settings-qa-local-shots`,生产截图保存在 `/tmp/beaver-market-settings-qa-prod-shots`。
|
||||
|
||||
## 6. 已修复问题
|
||||
|
||||
| 等级 | 问题 | 修复 |
|
||||
| --- | --- | --- |
|
||||
| P1 | 结果卡片只有 Card click,没有按钮语义,键盘和辅助技术不可稳定操作 | 改为真实 `button` 卡片 |
|
||||
| P1 | 技能详情里的文件路径、版本号、markdown 代码块可能撑破移动端 | 增加 `min-w-0`、`break-all`、`break-words` 和 markdown 预览约束 |
|
||||
| P2 | 页面缺少清晰 `h1`,市场页身份不明确 | 增加语义化标题和说明 |
|
||||
| P2 | 搜索表单在窄屏可能挤压 | 移动端改为纵向布局 |
|
||||
| P2 | Tabs 触控高度不足 44px | 基础 `TabsTrigger` 调整为 `44px` |
|
||||
| P2 | 排序、筛选、返回、安装、分页等操作触控尺寸不统一 | 基础按钮和页面操作统一提升到 `44px` |
|
||||
| P3 | 长 namespace 和版本 badge 只截断或可能撑宽 | 改为容器内断行 |
|
||||
|
||||
## 7. 剩余观察项
|
||||
|
||||
- 本轮使用模拟 SkillHub 数据;真实市场里若存在复杂 HTML/Markdown 表格或超大文件,仍需持续抽样检查。
|
||||
- 当前安装成功后停留在详情页并更新 installed 状态,后续可考虑增加轻量 toast,增强成功反馈。
|
||||
114
docs/ui-ux/pages/mcp-tools.md
Normal file
114
docs/ui-ux/pages/mcp-tools.md
Normal file
@ -0,0 +1,114 @@
|
||||
# 主应用:工具页 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | 工具 / MCP 工具管理 |
|
||||
| 路由 | `/mcp` |
|
||||
| 页面实现 | `app-instance/frontend/app/(app)/mcp/page.tsx` |
|
||||
| 关键组件 | `MCPPage`、`Dialog`、`Tabs`、MCP 服务卡片、工具详情面板 |
|
||||
| 核心任务 | 查看本地/在线 MCP 服务、新增服务、编辑服务、测试连接、删除服务、查看已发现工具 |
|
||||
| 测试状态 | 已修复并复测通过;本地与 `terminaltest` 生产实例均通过 |
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
AppShell
|
||||
└── main.pt-16
|
||||
└── /mcp
|
||||
├── Page Header
|
||||
│ ├── h1 Tools
|
||||
│ ├── Refresh
|
||||
│ └── Add tool server
|
||||
├── Add / Edit MCP Dialog
|
||||
│ ├── ID
|
||||
│ ├── Tool timeout
|
||||
│ ├── Connection mode tabs
|
||||
│ │ ├── Remote MCP server
|
||||
│ │ │ ├── URL
|
||||
│ │ │ ├── Auth mode
|
||||
│ │ │ ├── AuthZ permissions preview
|
||||
│ │ │ └── Headers JSON
|
||||
│ │ └── Install and launch
|
||||
│ │ ├── Command
|
||||
│ │ └── Arguments
|
||||
│ └── Cancel / Save
|
||||
├── Error Card
|
||||
├── Tool kind tabs
|
||||
│ ├── Local tools
|
||||
│ └── Online tools
|
||||
└── Content grid
|
||||
├── MCP service list
|
||||
│ ├── Selectable service content
|
||||
│ └── Edit / Test / Delete
|
||||
└── Tool details panel
|
||||
├── Empty selection state
|
||||
├── Empty tools state
|
||||
└── Tool cards
|
||||
```
|
||||
|
||||
## 3. 布局与响应式规则
|
||||
|
||||
- 页面外层使用 `max-w-6xl`,移动端内边距为 `16px`,桌面端为 `24px`。
|
||||
- 移动端头部按钮自动换行,`Refresh` 和 `Add tool server` 均为 `44px` 高度。
|
||||
- 内容区默认单列;`xl` 以上变为左侧 MCP 服务列表、右侧工具详情双栏。
|
||||
- MCP 服务卡片的可选中区域和编辑/测试/删除按钮分离,避免卡片 role button 内嵌按钮。
|
||||
- 移动端服务卡片头部改为纵向布局,徽章不会挤出右侧边界。
|
||||
- 长 ID、URL、command、Audience、Scopes、last error 和工具描述都在容器内换行。
|
||||
- 新增/编辑弹窗限制在当前视口内,内容可滚动,底部 Cancel/Save 保持可达。
|
||||
- 页面主要按钮、Tab 和服务选择区域均满足 `44px` 触控目标。
|
||||
|
||||
## 4. 操作与 UX 逻辑
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 刷新工具服务 | 点击 Refresh | 重新拉取 MCP servers、tools、AuthZ 状态 | 获取最新连接和工具发现状态 | 正常 |
|
||||
| 切换本地/在线工具 | 点击 Local tools / Online tools | 切换服务列表,并清空右侧选中态 | 避免跨分类误看详情 | 正常 |
|
||||
| 选择服务 | 点击服务卡片内容区域或键盘 Enter/Space | 卡片高亮,右侧显示对应工具 | 查看该 MCP 暴露的工具 | 正常 |
|
||||
| 测试服务 | 点击 Test | 按钮显示 loading,成功后刷新状态 | 验证 MCP 当前可连接性 | 正常 |
|
||||
| 新增远程服务 | 点击 Add tool server,填写 URL/Auth/Header,点击 Save | 校验 ID、URL、timeout、Headers JSON,成功后关闭弹窗并刷新 | 接入已部署 MCP 服务 | 正常 |
|
||||
| 新增本地服务 | 弹窗中切换 Install and launch,填写 command/args,点击 Save | 校验 ID、command、timeout,成功后关闭弹窗并刷新 | 接入本地 stdio MCP 进程 | 正常 |
|
||||
| 编辑服务 | 点击 Edit | 打开同一弹窗并带入原配置,保存后刷新 | 修改用户自定义 MCP 配置 | 正常 |
|
||||
| 删除服务 | 点击 Delete,确认浏览器弹窗 | 确认后调用 delete,成功后取消选中并刷新 | 防止误删 MCP 配置 | 正常 |
|
||||
| JSON 输入错误 | Headers JSON 非对象或语法错误 | 页面错误卡显示解析错误,弹窗保持打开 | 保留用户输入并指出修复方向 | 正常 |
|
||||
| 加载失败 | servers 接口失败 | 显示错误卡,不阻断页面头部操作 | 明确异常原因并允许重新刷新 | 正常 |
|
||||
|
||||
## 5. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。环境:本地 dev server `http://127.0.0.1:3080` 与生产实例 `terminaltest`;API 使用模拟数据,真实浏览器执行点击、输入、确认弹窗和截图。
|
||||
|
||||
| 页面/状态 | 视口 | 横向越界 | 小触控目标 | 关键结论 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 本地服务详情 | `390×844` | 无 | 0 | 可选择服务、查看工具详情、测试连接 |
|
||||
| 在线服务详情 | `390×844` | 无 | 0 | 超长 ID、URL、Audience、错误信息未撑破页面 |
|
||||
| 加载错误 | `390×844` | 无 | 0 | 错误卡可读,头部操作仍可见 |
|
||||
| 在线服务详情 | `320×568` | 无 | 0 | 窄屏卡片徽章和长字符串均正常换行 |
|
||||
| 在线服务详情 | `390×844` | 无 | 0 | 手机竖屏可完成查看与操作 |
|
||||
| 在线服务详情 | `844×390` 横屏 | 无 | 0 | 横屏无页面级横向滚动 |
|
||||
| 在线服务详情 | `768×1024` | 无 | 0 | 平板单列布局稳定 |
|
||||
| 在线服务详情 | `1365×900` | 无 | 0 | 桌面双栏布局正常 |
|
||||
|
||||
### 关键量化证据
|
||||
|
||||
- 本地工具页 QA 自动化用例 `4 passed`。
|
||||
- 部署到 `terminaltest` 后,同一套工具页 QA 自动化用例 `4 passed`。
|
||||
- 覆盖服务选择、工具详情、Tab 切换、Test、Add、Edit、Delete confirm、Refresh、JSON 错误和加载错误。
|
||||
- 实测 `320×568`、`390×844`、`844×390`、`768×1024`、`1365×900` 均无页面级横向越界。
|
||||
- 所有实测视口可见小触控目标数为 `0`。
|
||||
|
||||
## 6. 已修复问题
|
||||
|
||||
| 等级 | 问题 | 修复 |
|
||||
| --- | --- | --- |
|
||||
| P1 | `320px` 下在线服务卡片徽章、Audience 长字符串和错误信息横向越界 | 卡片头部移动端纵向布局,所有长字段加 `break-all/min-w-0` |
|
||||
| P1 | 新增/编辑弹窗内容过高时 Save 按钮在移动端被挤出视口 | Dialog 限制 `max-height`、启用内部滚动,底部操作区 sticky |
|
||||
| P1 | 删除 MCP 服务没有确认,误删风险高 | 删除前增加浏览器确认弹窗 |
|
||||
| P2 | 服务卡片整体 `role=button` 内部嵌套 Edit/Test/Delete 按钮 | 改为内容区域可选中,操作按钮独立 |
|
||||
| P2 | Refresh、Add、Local/Online tabs 和卡片操作按钮触控高度不足 | 统一提升到 `44px` |
|
||||
| P2 | Headers JSON 错误只显示页面级错误,弹窗可能遮挡操作 | 错误卡可读,弹窗保持打开且操作按钮可达 |
|
||||
|
||||
## 7. 剩余观察项
|
||||
|
||||
- 本轮自动化使用模拟 MCP 与 AuthZ 数据;真实 MCP 连接超时、鉴权 403 和工具发现异常仍需在后续联测中观察。
|
||||
- 当前删除使用浏览器原生确认弹窗,后续可统一为应用内确认 Dialog,以保持视觉一致性。
|
||||
135
docs/ui-ux/pages/notifications.md
Normal file
135
docs/ui-ux/pages/notifications.md
Normal file
@ -0,0 +1,135 @@
|
||||
# 主应用:通知页 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | 通知中心 |
|
||||
| 通知列表路由 | `/notifications` |
|
||||
| 通知详情路由 | `/notifications/[scheduledRunId]` |
|
||||
| 页面实现 | `app-instance/frontend/app/(app)/notifications/page.tsx`、`app-instance/frontend/app/(app)/notifications/[scheduledRunId]/page.tsx` |
|
||||
| 关键组件 | `NotificationsPage`、`NotificationDetailPage`、`ChatWorkbench`、`MessageList`、`Button`、`Badge` |
|
||||
| 核心任务 | 查看定时任务生成的通知、进入通知详情、刷新通知、对通知结果提出本次修改或未来规则调整、打开已接入 Task |
|
||||
| 测试状态 | 已修复并复测通过;本地与 `terminaltest` 生产实例均通过 |
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
AppShell
|
||||
└── main.pt-16
|
||||
├── /notifications
|
||||
│ ├── Page Header
|
||||
│ │ ├── h1 Notifications
|
||||
│ │ ├── 页面说明
|
||||
│ │ └── 刷新按钮
|
||||
│ ├── Error Card
|
||||
│ └── Notification List Panel
|
||||
│ ├── Loading State
|
||||
│ ├── Empty State
|
||||
│ └── Notification Link Row/Card
|
||||
│ ├── 标题
|
||||
│ ├── 状态 Badge
|
||||
│ ├── 摘要
|
||||
│ ├── 生成时间
|
||||
│ ├── job 名称
|
||||
│ └── 桌面端箭头
|
||||
└── /notifications/[scheduledRunId]
|
||||
├── Detail Header
|
||||
│ ├── 返回通知列表
|
||||
│ ├── 标题
|
||||
│ ├── 状态 / 已接入 Task Badge
|
||||
│ ├── 生成时间
|
||||
│ ├── 刷新按钮
|
||||
│ └── 查看任务按钮
|
||||
├── Error Banner
|
||||
├── ChatWorkbench
|
||||
│ └── MessageList
|
||||
│ ├── 用户原始请求
|
||||
│ └── 通知生成结果
|
||||
└── Reply Panel
|
||||
├── 修改这次
|
||||
├── 以后按这样
|
||||
├── 已接入提示
|
||||
└── 回复输入框 + 发送
|
||||
```
|
||||
|
||||
## 3. 布局与响应式规则
|
||||
|
||||
### 通知列表
|
||||
|
||||
- 外层使用 `max-w-6xl`,移动端内边距为 `16px`,桌面端为 `24px`。
|
||||
- 列表区域是独立白色面板,内部垂直滚动,不产生页面级横向滚动。
|
||||
- 移动端列表项按单列卡片阅读:标题、摘要、时间和 job 名称上下排列。
|
||||
- `md` 及以上使用网格列展示摘要、时间、job 名称和箭头,方便桌面端扫描。
|
||||
- 长标题、长摘要和长 job 名称都使用容器内断行,避免 ID 或连续字符串撑破卡片。
|
||||
- 刷新按钮高度为 `44px`,满足移动端触控目标要求。
|
||||
|
||||
### 通知详情
|
||||
|
||||
- 页面整体高度为 `calc(100vh - 4rem)`,位于全局 header 下方。
|
||||
- 顶部详情 header 使用浅色背景和底部分隔线,承载返回、标题、状态、生成时间和操作按钮。
|
||||
- 移动端标题允许换行,不再只截断;长 scheduled run id 或长标题不会撑破页面。
|
||||
- 中间 `ChatWorkbench` 使用剩余高度展示消息流。
|
||||
- 底部回复区是独立面板,包含两个意图按钮和按需出现的输入框。
|
||||
- 回复输入框有可见 label,不依赖 placeholder 作为唯一说明。
|
||||
- 返回、刷新、查看任务、意图选择、发送等关键操作均为 `44px` 高度。
|
||||
|
||||
## 4. 操作与 UX 逻辑
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 刷新通知列表 | 点击列表页 Refresh | 调用 `GET /api/notifications`,列表重新渲染 | 获取最新定时通知 | 正常 |
|
||||
| 打开通知详情 | 点击通知列表项 | 跳转 `/notifications/[scheduledRunId]` | 查看通知完整上下文和结果 | 正常 |
|
||||
| 空通知状态 | 列表接口返回空数组 | 显示“暂无通知” | 明确没有可处理内容 | 正常 |
|
||||
| 列表加载失败 | 列表接口失败 | 显示错误卡片 | 让用户知道是接口异常而不是无数据 | 正常 |
|
||||
| 返回通知列表 | 详情页点击返回 | 跳转 `/notifications` | 提供明确退出路径 | 正常 |
|
||||
| 刷新通知详情 | 详情页点击 Refresh | 调用 `GET /api/notifications/[id]` | 重新获取当前通知状态 | 正常 |
|
||||
| 修改这次 | 点击 `Revise this` | 按钮进入选中态,显示“本次通知的修改说明”输入框 | 只影响本次通知结果 | 正常 |
|
||||
| 以后按这样 | 点击 `Apply going forward` | 按钮进入选中态,显示“以后这类通知的调整说明”输入框 | 将用户偏好表达为未来规则 | 正常 |
|
||||
| 发送修改说明 | 输入内容后点击 Send | 调用 `POST /api/chat`,携带 `reply_to_scheduled_run_id` 和 `scheduled_reply_intent` | 把通知反馈接回对话/任务处理流程 | 正常 |
|
||||
| 打开已接入 Task | 已存在 `task_id` 时点击 Open task | 跳转 `/tasks/[taskId]` | 从通知继续跟进任务 | 正常 |
|
||||
| 通知不存在 | 详情接口失败或无数据 | 显示错误信息和返回通知入口 | 提供异常恢复路径 | 正常 |
|
||||
|
||||
## 5. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。环境:本地 dev server `http://127.0.0.1:3080` 与生产实例 `terminaltest`;API 使用模拟数据,真实浏览器执行点击、输入、跳转和截图。
|
||||
|
||||
| 页面 | 视口 | 横向越界 | 小触控目标 | 关键结论 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 通知列表 | `320×568` | 无 | 0 | 长标题和长 job 名在卡片内换行 |
|
||||
| 通知列表 | `390×844` | 无 | 0 | 手机竖屏可刷新、进入详情 |
|
||||
| 通知列表 | `844×390` 横屏 | 无 | 0 | 横屏无页面级横向滚动 |
|
||||
| 通知列表 | `768×1024` | 无 | 0 | 平板列表布局稳定 |
|
||||
| 通知列表 | `1365×900` | 无 | 0 | 桌面网格列可扫描 |
|
||||
| 通知空态 | `390×844` | 无 | 0 | 空态居中显示 |
|
||||
| 通知错误态 | `390×844` | 无 | 0 | 错误信息在卡片内可读 |
|
||||
| 通知详情 | `320×568` | 无 | 0 | 顶部标题换行,回复区不遮挡 |
|
||||
| 通知详情 | `390×844` | 无 | 0 | 消息流和底部回复区分层清楚 |
|
||||
| 通知详情 | `768×1024` | 无 | 0 | 平板详情布局正常 |
|
||||
| 通知详情 | `1365×900` | 无 | 0 | 桌面详情布局正常 |
|
||||
| 通知详情错误态 | `390×844` | 无 | 0 | 返回通知入口可见 |
|
||||
|
||||
### 关键量化证据
|
||||
|
||||
- 本地通知页 QA 自动化用例 `4 passed`。
|
||||
- 部署到 `terminaltest` 后,同一套通知页 QA 自动化用例 `4 passed`。
|
||||
- 列表实测视口 `320×568`、`390×844`、`844×390`、`768×1024`、`1365×900` 均无页面级横向越界。
|
||||
- 详情实测视口 `320×568`、`390×844`、`768×1024`、`1365×900` 均无页面级横向越界。
|
||||
- 所有实测视口可见小触控目标数为 `0`。
|
||||
- 回复提交实测请求包含 `reply_to_scheduled_run_id` 和 `scheduled_reply_intent=revise_once`。
|
||||
|
||||
## 6. 已修复问题
|
||||
|
||||
| 等级 | 问题 | 修复 |
|
||||
| --- | --- | --- |
|
||||
| P1 | 通知列表长标题、长 job 名在移动端被右侧裁切或存在撑破风险 | 标题、摘要和 job 名增加容器内断行;列表项保留 `min-w-0` |
|
||||
| P2 | 列表 Refresh 按钮高度只有 36px,低于移动端触控标准 | 调整为 `44px` |
|
||||
| P2 | 详情页返回、Refresh、Revise、Apply going forward 等操作高度不足 44px | 统一调整为 `44px` |
|
||||
| P2 | 详情页标题只截断,移动端无法判断完整通知主题 | 改为可换行并控制在容器内 |
|
||||
| P2 | 详情回复输入框依赖 placeholder 表达含义 | 增加可见 label,并根据意图区分本次修改/未来调整 |
|
||||
| P3 | 意图按钮缺少明确 pressed 状态语义 | 增加 `aria-pressed` |
|
||||
|
||||
## 7. 剩余观察项
|
||||
|
||||
- 本地 mocked API 场景会出现 WebSocket 握手失败日志,因为测试 token 不对应真实后端 WS;该日志不影响通知页 HTTP 交互和布局结论。
|
||||
- 后续接入真实用户历史通知时,仍需持续观察第三方系统生成的异常长 Markdown、附件和错误文本。
|
||||
121
docs/ui-ux/pages/outlook.md
Normal file
121
docs/ui-ux/pages/outlook.md
Normal file
@ -0,0 +1,121 @@
|
||||
# 主应用:Outlook 页 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | Outlook |
|
||||
| 路由 | `/outlook` |
|
||||
| 页面实现 | `app-instance/frontend/app/(app)/outlook/page.tsx` |
|
||||
| 关键组件 | `OutlookPage`、`MessageCard`、`EventCard`、`Field`、邮件详情 Dialog、日程详情 Dialog |
|
||||
| 核心任务 | 配置 Outlook/EWS 连接、测试连接、保存启用、断开连接、查看收件箱/发件箱、分页、查看邮件详情、查看未来 7 天日程 |
|
||||
| 测试状态 | 已修复并复测通过;本地与 `terminaltest` 生产实例均通过 |
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
AppShell
|
||||
└── main.pt-16
|
||||
└── /outlook
|
||||
├── Status Header
|
||||
│ ├── h1 Outlook
|
||||
│ ├── connection / MCP / provider badges
|
||||
│ ├── mailbox / timezone / last refresh
|
||||
│ ├── Inbox / Sent / Calendar stats
|
||||
│ └── Refresh
|
||||
├── Error Card
|
||||
├── Warning Card
|
||||
├── View Tabs
|
||||
│ ├── Inbox
|
||||
│ ├── Sent
|
||||
│ ├── Calendar
|
||||
│ └── Settings
|
||||
├── Inbox / Sent
|
||||
│ ├── Mailbox header
|
||||
│ ├── Refresh / Previous / Next
|
||||
│ └── Message rows
|
||||
├── Calendar
|
||||
│ ├── Week header
|
||||
│ ├── Previous week / This week / Next week / Refresh
|
||||
│ └── Day cards
|
||||
├── Settings
|
||||
│ ├── Connection settings form
|
||||
│ ├── Test connection / Save and enable / Disconnect
|
||||
│ ├── Test result panel
|
||||
│ └── Connection status panel
|
||||
├── Message detail Dialog
|
||||
│ ├── metadata panel
|
||||
│ └── body preview
|
||||
└── Event detail Dialog
|
||||
├── organizer / location / attendees
|
||||
└── notes
|
||||
```
|
||||
|
||||
## 3. 布局与响应式规则
|
||||
|
||||
- 页面外层使用 `max-w-7xl`,移动端内边距为 `16px`,桌面端为 `24px`。
|
||||
- 顶部状态区有语义化 `h1`,长邮箱、时区和刷新时间允许容器内断行。
|
||||
- 已配置时显示 Inbox、Sent、Calendar、Settings;未配置时只显示 Settings。
|
||||
- 邮件列表和日程列表在移动端头部为上下布局,分页和刷新按钮可换行。
|
||||
- 邮件详情和日程详情 Dialog 在移动端使用 `left/right/top/bottom: 16px` 的独立面板,内容可滚动,不再被默认居中动画撑出视口。
|
||||
- 设置表单字段均有 `label htmlFor` 与 input `id` 绑定,支持可访问名称和自动化定位。
|
||||
- 输入框、主要按钮、分页按钮、刷新 icon、Dialog 关闭按钮均满足 `44px` 触控目标。
|
||||
- 邮件正文里的明文链接使用 `min-height: 44px` 的可点击区域,移动端更容易点击。
|
||||
|
||||
## 4. 操作与 UX 逻辑
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 初次加载已配置状态 | 打开 `/outlook` | 加载 status 后自动加载 overview | 顶部统计和 warning 不显示过期空值 | 正常 |
|
||||
| 刷新 Outlook | 点击 Refresh | 刷新 status/overview,并刷新当前 tab 数据 | 获取最新连接、邮件或日程状态 | 正常 |
|
||||
| 切换 Inbox/Sent/Calendar/Settings | 点击 tab | 切换视图,按需加载邮箱或日程数据 | 保持页面内工作流清晰 | 正常 |
|
||||
| 查看邮件详情 | 点击邮件行 | 打开邮件详情 Dialog,加载 message-detail | 阅读正文和收发件人信息 | 正常 |
|
||||
| 查看日程详情 | 点击日程卡片 | 打开日程详情 Dialog | 查看地点、参会人和说明 | 正常 |
|
||||
| 邮件分页 | 点击 Previous / Next | 使用当前 skip 加载上一页/下一页 | 浏览更多邮件 | 正常 |
|
||||
| 日程切周 | 点击 Previous week / This week / Next week | 更新 7 天范围并重新加载 events | 快速查看周视图 | 正常 |
|
||||
| 测试连接 | 填写必要字段后点击 Test connection | 显示 testing,成功后显示 sample 与 warning | 保存前验证配置可用 | 正常 |
|
||||
| 保存并启用 | 点击 Save and enable | 成功后清空密码、刷新状态并进入 Inbox | 完成 Outlook 接入 | 正常 |
|
||||
| 断开连接 | 点击 Disconnect 并确认 | 清空 overview、选中详情和分页缓存,回到 Settings | 防止误断开并恢复到配置状态 | 正常 |
|
||||
| 状态加载失败 | status 接口失败 | 显示错误卡 | 明确异常原因 | 正常 |
|
||||
|
||||
## 5. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。环境:本地 dev server `http://127.0.0.1:3080` 与生产实例 `terminaltest`;API 使用模拟数据,真实浏览器执行点击、输入、确认弹窗、分页、详情弹窗和截图。
|
||||
|
||||
| 页面/状态 | 视口 | 横向越界 | 小触控目标 | 关键结论 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 邮件详情 | `390×844` | 无 | 0 | 可打开邮件详情,长主题、收件人、正文和链接均可读 |
|
||||
| 日程详情 | `390×844` | 无 | 0 | 可打开日程详情,长地点和参会人可断行 |
|
||||
| 设置表单 | `390×844` | 无 | 0 | 字段可通过 label 操作,测试/保存/断开流程正常 |
|
||||
| 状态错误 | `390×844` | 无 | 0 | 错误卡可读 |
|
||||
| 邮件详情 + 设置 | `320×568` | 无 | 0 | 窄屏无页面级横向滚动,Dialog 可滚动 |
|
||||
| 邮件详情 + 设置 | `390×844` | 无 | 0 | 手机竖屏布局稳定 |
|
||||
| 邮件详情 + 设置 | `844×390` 横屏 | 无 | 0 | 横屏不出现页面级横向滚动 |
|
||||
| 邮件详情 + 设置 | `768×1024` | 无 | 0 | 平板布局稳定 |
|
||||
| 邮件详情 + 设置 | `1365×900` | 无 | 0 | 桌面布局正常 |
|
||||
|
||||
### 关键量化证据
|
||||
|
||||
- 本地 Outlook 页 QA 自动化用例 `4 passed`。
|
||||
- 部署到 `terminaltest` 后,同一套 Outlook 页 QA 自动化用例 `4 passed`。
|
||||
- 覆盖已配置状态、overview 加载、Inbox、邮件详情、Calendar、日程详情、Settings、Test、Save、Disconnect confirm、状态错误和响应式。
|
||||
- 实测 `320×568`、`390×844`、`844×390`、`768×1024`、`1365×900` 均无页面级横向越界。
|
||||
- 所有实测视口可见小触控目标数为 `0`。
|
||||
|
||||
## 6. 已修复问题
|
||||
|
||||
| 等级 | 问题 | 修复 |
|
||||
| --- | --- | --- |
|
||||
| P1 | 已配置 Outlook 初次进入页面不会主动加载 overview,顶部统计可能一直为 0 | `loadStatus` 在 configured 状态下自动加载 overview |
|
||||
| P1 | 设置表单 label 未绑定 input,辅助技术和自动化无法按字段名定位 | `Field` 增加 `htmlFor`,所有输入框增加稳定 `id` |
|
||||
| P1 | 邮件详情和日程详情 Dialog 在移动端会被默认居中/slide 动画撑出视口 | 移动端改为四边 inset 面板并覆盖 slide 偏移 |
|
||||
| P1 | 长邮箱、EWS URL、邮件主题、地点、参会人、warning 可能撑破布局 | 关键文本增加 `min-w-0`、`break-all` 或 `break-words` |
|
||||
| P2 | Refresh、分页、表单操作、Dialog 关闭等触控目标不足 | 统一提升到 `44px` |
|
||||
| P2 | 断开 Outlook 连接没有确认,误操作风险高 | Disconnect 前增加浏览器确认弹窗 |
|
||||
| P2 | 邮件正文中的明文链接触控高度过小 | 链接改为可换行的 `44px` 点击区域 |
|
||||
| P2 | 邮件/日程列表头部在移动端按钮挤压 | 头部改为移动端纵向布局,操作按钮可换行 |
|
||||
|
||||
## 7. 剩余观察项
|
||||
|
||||
- 本轮自动化使用模拟 Outlook API 数据;真实 EWS 超时、鉴权失败、HTML 邮件复杂表格和超大正文仍需持续观察。
|
||||
- 当前 Disconnect 使用浏览器原生确认弹窗,后续可统一为应用内确认 Dialog,以保持视觉一致性。
|
||||
120
docs/ui-ux/pages/settings.md
Normal file
120
docs/ui-ux/pages/settings.md
Normal file
@ -0,0 +1,120 @@
|
||||
# 主应用:配置页 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | 配置 |
|
||||
| 主路由 | `/settings` |
|
||||
| 同实现路由 | `/status` |
|
||||
| 页面实现 | `app-instance/frontend/app/(app)/settings/page.tsx` re-export `app-instance/frontend/app/(app)/status/page.tsx` |
|
||||
| 关键组件 | `StatusPage`、Provider Dialog、Channel Detail Dialog、Connector Dialog、Restart Dialog、`InfoRow`、`Field` |
|
||||
| 核心任务 | 查看实例运行信息、调整智能体参数、配置模型提供商、配置/连接通道、查看通道事件、重启实例 |
|
||||
| 测试状态 | 已修复并复测通过;本地与 `terminaltest` 生产实例均通过 |
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
AppShell
|
||||
└── main.pt-16
|
||||
└── /settings
|
||||
├── Page Header
|
||||
│ ├── h1 Settings
|
||||
│ ├── 页面说明
|
||||
│ └── Refresh
|
||||
├── Instance runtime Card
|
||||
│ ├── Runtime Logs
|
||||
│ ├── Restart instance
|
||||
│ └── config/workspace InfoRow
|
||||
├── Agent configuration Card
|
||||
│ ├── model InfoRow
|
||||
│ ├── max tokens / temperature / max tool iterations
|
||||
│ └── Save agent config
|
||||
├── Providers Card
|
||||
│ └── provider button cards
|
||||
├── Provider Dialog
|
||||
│ ├── enable switch
|
||||
│ ├── model / API key / API base / timeout
|
||||
│ └── Cancel / Save
|
||||
├── Channels Card
|
||||
│ └── connector/channel button cards
|
||||
├── Channel Detail Dialog
|
||||
│ ├── channel title and id
|
||||
│ ├── connection settings
|
||||
│ ├── credential fields
|
||||
│ ├── policy fields
|
||||
│ ├── channel state InfoRows
|
||||
│ └── recent events
|
||||
├── Connector Dialog
|
||||
│ ├── display name / domain / mode
|
||||
│ ├── QR or plugin session
|
||||
│ └── Close / Refresh / Start connection
|
||||
└── Restart Dialog
|
||||
├── warning text
|
||||
└── Cancel / Restart
|
||||
```
|
||||
|
||||
## 3. 布局与响应式规则
|
||||
|
||||
- `/settings` 和 `/status` 使用同一实现;当前文档按配置页维护。
|
||||
- 页面外层使用 `max-w-6xl`,移动端内边距为 `16px`,桌面端为 `24px`。
|
||||
- `InfoRow` 使用响应式网格,长配置路径、workspace、model、channel id 和 URL 都在容器内断行。
|
||||
- Provider 与 Channel 卡片是按钮语义,移动端单列,平板/桌面多列。
|
||||
- 所有 Dialog 移动端使用 `width: calc(100vw - 2rem)`、顶部 16px、最大高度 `calc(100vh - 2rem)`、内部滚动;桌面端保持居中面板。
|
||||
- Dialog 直接子元素统一 `min-w-0`,避免长标题或表单网格把弹窗撑出视口。
|
||||
- 输入框、按钮、下拉、tab、switch 等可见操作均满足 `44px` 触控目标。
|
||||
- 通道表单的 `Display name`、`Account ID` 等关键字段具备 label/input 绑定,可按标签点击和自动化定位。
|
||||
|
||||
## 4. 操作与 UX 逻辑
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 刷新配置 | 点击 Refresh | 重新调用 `/api/status` | 获取最新实例状态 | 正常 |
|
||||
| 打开运行日志 | 点击 Runtime Logs | 跳转 `/logs` | 进入运行排障入口 | 正常 |
|
||||
| 打开重启确认 | 点击 Restart instance | 打开确认 Dialog | 防止误重启 | 正常 |
|
||||
| 确认重启 | Dialog 点击 Restart | 调用 `/api/runtime/restart`,成功后关闭并延迟刷新 | 应用配置变更或恢复运行态 | 正常 |
|
||||
| 保存智能体配置 | 修改参数后点击 Save agent config | 校验数值并调用 `/api/agent-config` | 调整模型上下文和推理参数 | 正常 |
|
||||
| 打开 Provider | 点击 OpenAI/DeepSeek 等卡片 | 打开 Provider Dialog 并填入当前值 | 配置模型接入 | 正常 |
|
||||
| 保存 Provider | Dialog 点击 Save | 调用 `/api/providers/{id}/config`,成功后刷新 status | 启用或更新默认提供商 | 正常 |
|
||||
| 打开通道详情 | 点击已存在通道卡片 | 加载 `/api/channels/{id}/config` 和 events | 查看并编辑通道连接 | 正常 |
|
||||
| 保存通道配置 | Dialog 点击 Save channel config | 调用 `/api/channels/{id}/config`,必要时提示重启 | 更新 IM/终端通道配置 | 正常 |
|
||||
| 打开连接器 | 点击可启动的 Weixin/Feishu 卡片 | 打开连接器 Dialog | 启动扫码或插件接入流程 | 正常 |
|
||||
| 状态加载失败 | `/api/status` 失败 | 显示错误卡片和 Retry | 明确异常并提供恢复入口 | 正常 |
|
||||
|
||||
## 5. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。环境:本地 dev server `http://127.0.0.1:3080` 与生产实例 `terminaltest`;API 使用模拟数据,真实浏览器执行点击、输入、弹窗保存、重启确认和截图。
|
||||
|
||||
| 页面/状态 | 视口 | 横向越界 | 小触控目标 | 关键结论 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 配置页 + 飞书通道弹窗 | `320×568` | 无 | 0 | 长 config path、workspace、provider 名和 channel id 均不越界 |
|
||||
| 配置页 + 飞书通道弹窗 | `390×844` | 无 | 0 | 可保存智能体、Provider、通道配置并打开重启确认 |
|
||||
| 配置页 + 飞书通道弹窗 | `844×390` 横屏 | 无 | 0 | 横屏 Dialog 可滚动,不撑出页面 |
|
||||
| 配置页 + 飞书通道弹窗 | `768×1024` | 无 | 0 | 平板布局稳定 |
|
||||
| 配置页 + 飞书通道弹窗 | `1365×900` | 无 | 0 | 桌面卡片和 Dialog 布局正常 |
|
||||
| 状态错误 | `390×844` | 无 | 0 | 错误文案和 Retry 可读可点 |
|
||||
|
||||
### 关键量化证据
|
||||
|
||||
- 本地与 `terminaltest` 市场/配置组合 QA 自动化用例均 `4 passed`,其中覆盖配置流。
|
||||
- 覆盖智能体配置保存、OpenAI Provider 保存、Feishu 通道保存、重启确认、状态错误和响应式。
|
||||
- 实测 `320×568`、`390×844`、`844×390`、`768×1024`、`1365×900` 均无页面级横向越界。
|
||||
- 所有实测视口可见小触控目标数为 `0`。
|
||||
- 本地截图保存在 `/tmp/beaver-market-settings-qa-local-shots`,生产截图保存在 `/tmp/beaver-market-settings-qa-prod-shots`。
|
||||
|
||||
## 6. 已修复问题
|
||||
|
||||
| 等级 | 问题 | 修复 |
|
||||
| --- | --- | --- |
|
||||
| P1 | 配置页 Dialog 在移动端按桌面宽度居中,长内容会撑出或被裁切 | 基础 `DialogContent` 增加移动端 `calc(100vw - 2rem)` 宽度、最大高度、滚动和 `min-w-0` |
|
||||
| P1 | `InfoRow` 的长路径固定 `max-w-[400px] truncate`,在窄屏撑破页面 | 改为响应式网格和 `break-all` |
|
||||
| P1 | 通道表单关键 label 未绑定输入框,真实点击标签和自动化定位不稳定 | `Field` 支持 `htmlFor`,关键字段增加稳定 `id` |
|
||||
| P2 | Provider、Channel 卡片长名称和 channel id 可能撑宽 | 卡片内部增加 `min-w-0`、`break-all` 和可换行文本 |
|
||||
| P2 | Button/Input/Select/Tabs 触控高度不足或不统一 | 基础组件统一提升到 44px 级别 |
|
||||
| P2 | 通道最近事件时间和状态长文本可能挤压 | 改为移动端纵向布局并断行 |
|
||||
| P3 | 错误文案和保存提示可能被长文本撑开 | 增加 `break-words` |
|
||||
|
||||
## 7. 剩余观察项
|
||||
|
||||
- 本轮使用模拟 provider/channel 数据;真实第三方连接器返回超长错误、二维码图片或异常 instructions 时仍需抽样验证。
|
||||
- `/settings` 与 `/status` 共用同一实现,后续如果产品语义拆分,需要分别维护两份页面文档。
|
||||
121
docs/ui-ux/pages/skills.md
Normal file
121
docs/ui-ux/pages/skills.md
Normal file
@ -0,0 +1,121 @@
|
||||
# 主应用:技能页 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、候选和草稿状态转换;真实后端极端数据仍需在后续页面联测中持续观察。
|
||||
- 发布高风险草稿的确认分支没有在本轮自动化里实际确认发布,只验证了普通草稿审核路径。
|
||||
144
docs/ui-ux/pages/task-management.md
Normal file
144
docs/ui-ux/pages/task-management.md
Normal file
@ -0,0 +1,144 @@
|
||||
# 主应用:Task 任务页 UI/UX
|
||||
|
||||
## 1. 页面定义
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 页面名称 | Task 任务管理 |
|
||||
| 普通任务路由 | `/tasks` |
|
||||
| 定时任务子页 | `/tasks?tab=scheduled` |
|
||||
| 任务详情路由 | `/tasks/[taskId]` |
|
||||
| 页面实现 | `app-instance/frontend/app/(app)/tasks/page.tsx`、`app-instance/frontend/app/(app)/tasks/[taskId]/page.tsx` |
|
||||
| 关键组件 | `TaskManagementTabs`、`TaskLiveHeader`、`TaskTimeline`、`TaskTimelineCard`、`TaskSideRail`、`TaskAcceptanceControls` |
|
||||
| 核心任务 | 查看任务列表、进入任务详情、删除任务、管理定时任务、查看任务时间线、提交验收反馈 |
|
||||
| 测试状态 | 已修复并复测通过;普通任务、定时任务、任务详情和缺省态在实测视口均无横向越界 |
|
||||
|
||||
## 2. 信息架构与组件层级
|
||||
|
||||
```text
|
||||
AppShell
|
||||
└── main.pt-16
|
||||
├── /tasks
|
||||
│ ├── Page Header
|
||||
│ │ ├── h1 Tasks
|
||||
│ │ ├── 页面说明
|
||||
│ │ └── TaskManagementTabs
|
||||
│ ├── OrdinaryTasks
|
||||
│ │ ├── Loading Card
|
||||
│ │ ├── Empty Card
|
||||
│ │ ├── < xl:OrdinaryTaskCard 列表
|
||||
│ │ └── >= xl:任务表格
|
||||
│ └── ScheduledTasks
|
||||
│ ├── 辅助说明
|
||||
│ ├── 刷新 / 新建定时任务
|
||||
│ ├── AddJobForm
|
||||
│ ├── < xl:ScheduledJobCard 列表
|
||||
│ └── >= xl:定时任务表格
|
||||
└── /tasks/[taskId]
|
||||
├── TaskLiveHeader sticky top: 65px,避让全局头部
|
||||
└── main grid
|
||||
├── 主列
|
||||
│ ├── 删除任务
|
||||
│ └── TaskTimeline
|
||||
│ ├── 任务创建
|
||||
│ ├── 计划 / 工具 / Agent / 产物 / 结果卡片
|
||||
│ ├── Details JSON 展开区
|
||||
│ └── TaskAcceptanceControls
|
||||
└── TaskSideRail
|
||||
├── 任务状态
|
||||
├── 活跃运行
|
||||
├── 最新提醒
|
||||
├── Agent team
|
||||
└── 产物
|
||||
```
|
||||
|
||||
## 3. 布局与响应式规则
|
||||
|
||||
### 普通任务列表
|
||||
|
||||
- 页面外层使用 `max-w-7xl` 和响应式内边距。
|
||||
- `< xl` 视口显示任务卡片,不再显示宽表格;状态、来源、运行数、技能数、更新时间和操作全部在卡片内可见。
|
||||
- `>= xl` 视口显示完整表格,适合批量扫描和横向比较。
|
||||
- 加载状态显示独立 loading card,不会在接口返回前误显示“暂无普通任务”。
|
||||
- 删除任务前使用浏览器确认,取消后不改变列表,确认后从列表移除。
|
||||
|
||||
### 定时任务子页
|
||||
|
||||
- `< xl` 视口显示定时任务卡片,避免将“历史、状态、操作”藏在内部横向滚动表格右侧。
|
||||
- `>= xl` 视口显示表格。
|
||||
- 新建表单以内联卡片展示,包含任务名称、调度类型、调度参数、任务消息、来源会话说明、取消和创建。
|
||||
- 定时任务删除前需要确认,降低误删风险。
|
||||
- Switch、运行、删除、历史、刷新、新建等入口均有可访问名称和 44px 触控目标。
|
||||
|
||||
### 任务详情
|
||||
|
||||
- `TaskLiveHeader` 为 sticky,固定在全局头部下方 `65px`,避免与全局 header 的边框重叠。
|
||||
- 主内容在 `xl` 以下单列排列:时间线在前,侧栏在后。
|
||||
- `xl` 及以上使用 `minmax(0,1fr) + 360px` 双栏:左侧时间线,右侧状态和产物。
|
||||
- 主列、侧栏、卡片和 JSON 区均使用 `min-w-0`、`max-w-full` 和受控换行,防止长 run id、session id、JSON 或产物标题撑破页面。
|
||||
- `Details JSON` 的 summary 命中高度为 44px,支持触控展开。
|
||||
|
||||
## 4. 操作与 UX 逻辑
|
||||
|
||||
| 操作 | 触发方式 | 状态变化与反馈 | UX 目的 | 当前结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 切换普通/定时任务 | 点击 TaskManagementTabs | URL 在 `/tasks` 与 `/tasks?tab=scheduled` 间切换,当前 tab 高亮 | 区分用户任务和自动触发任务 | 正常 |
|
||||
| 普通任务进入详情 | 点击“进入任务 / Open task” | 跳转 `/tasks/[taskId]` | 查看时间线、运行过程和验收 | 正常 |
|
||||
| 删除普通任务 | 点击删除按钮后确认 | 取消不变;确认后调用 `DELETE /api/tasks/[id]` 并移除行/卡片 | 防止误删,保持列表干净 | 正常 |
|
||||
| 刷新定时任务 | 点击刷新 | 重新调用定时任务列表接口 | 获取最新调度状态 | 正常 |
|
||||
| 新建定时任务 | 点击新建,填写表单并创建 | 提交 `POST /api/cron/jobs`,成功后收起表单并刷新列表 | 创建自动提醒入口 | 正常 |
|
||||
| 切换定时任务启用 | 点击 Switch | 调用 toggle 接口,刷新列表 | 快速暂停/恢复自动任务 | 正常 |
|
||||
| 立即运行定时任务 | 点击播放按钮 | 调用 run 接口,刷新列表 | 手动触发一次计划任务 | 正常 |
|
||||
| 删除定时任务 | 点击删除按钮后确认 | 取消不变;确认后调用删除接口并刷新列表 | 防止误删自动任务 | 正常 |
|
||||
| 返回任务列表 | 详情页点击 Back to tasks | 返回 `/tasks` | 提供明确退出路径 | 正常 |
|
||||
| 返回对话 | 详情页点击 Chat | 返回 `/` | 回到任务来源工作台 | 正常 |
|
||||
| 跳到验收区 | 点击 Review | 定位到当前结果验收卡片 | 减少长时间线中的查找成本 | 正常 |
|
||||
| 展开 Details JSON | 点击 summary | 展开或收起 JSON 明细 | 为调试和审计保留细节 | 正常 |
|
||||
| 提交修改意见 | 填写验收说明,点击 Needs revision | 调用 `/api/chat/acceptance`,提交 `revise` 和 comment | 将验收反馈记录到当前 run | 正常 |
|
||||
| 下载产物 | 点击 Download | 对内联产物生成下载 | 获取任务输出 | 正常 |
|
||||
| 任务不存在 | 访问缺失 task id | 显示“任务不存在”和返回任务列表 | 明确异常恢复路径 | 正常 |
|
||||
|
||||
## 5. 响应式测试矩阵
|
||||
|
||||
测试日期:2026-06-04。浏览器:Playwright Chromium。环境:本地生产构建 `next build` + `next start` 以及实际 `terminaltest` 实例;API 使用模拟数据,所有布局和交互在真实浏览器中执行。
|
||||
|
||||
| 页面 | 视口 | 横向越界 | 小触控目标 | 关键结论 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 普通任务 | `320×568` | 无 | 0 | 卡片信息完整,操作可见 |
|
||||
| 普通任务 | `390×844` | 无 | 0 | 手机竖屏可直接进入和删除 |
|
||||
| 普通任务 | `844×390` 横屏 | 无 | 0 | 横屏不需要页面横向滚动 |
|
||||
| 普通任务 | `768×1024` | 无 | 0 | 平板单列卡片正常 |
|
||||
| 普通任务 | `1024×768` | 无 | 0 | 窄桌面单列卡片正常 |
|
||||
| 普通任务 | `1365×900` | 无 | 0 | 宽屏表格正常 |
|
||||
| 定时任务 | `390×844` | 无 | 0 | 定时任务卡片完整显示历史、状态和操作 |
|
||||
| 任务详情 | `320×568` | 无 | 0 | 长 session id、JSON、验收区均未撑破页面 |
|
||||
| 任务详情 | `390×844` | 无 | 0 | sticky 头部避让全局头部 |
|
||||
| 任务详情 | `768×1024` | 无 | 0 | 单列详情和侧栏顺序正常 |
|
||||
| 任务详情 | `1365×900` | 无 | 0 | 双栏详情正常,侧栏产物可下载 |
|
||||
|
||||
### 关键量化证据
|
||||
|
||||
- 普通任务所有实测视口 `scrollWidth === clientWidth`。
|
||||
- 定时任务 `390×844` 视口 `scrollWidth === clientWidth`。
|
||||
- 任务详情 `320×568`、`390×844`、`768×1024`、`1365×900` 均无页面级横向越界。
|
||||
- 任务详情 sticky 头部实测 `globalBottom=65`、`taskTop=65`、`overlapsGlobal=false`。
|
||||
- 最终复测中所有检查视口可见小触控目标数为 `0`。
|
||||
- 部署到 `terminaltest` 后,同一套 Task QA 自动化用例 `14 passed`。
|
||||
|
||||
## 6. 已修复问题
|
||||
|
||||
| 等级 | 问题 | 修复 |
|
||||
| --- | --- | --- |
|
||||
| P1 | 普通任务和定时任务在手机端只露出表格左侧,核心操作藏在内部横向滚动区 | `< xl` 改为卡片布局,宽屏保留表格 |
|
||||
| P1 | 任务详情在 `320px` 和 `390px` 被时间线内容撑到约 `626px`,产生页面级横向越界 | 主列、卡片、侧栏加入 `min-w-0/max-w-full`,控制长文本和 JSON |
|
||||
| P1 | 任务详情 sticky 头部滚动后与全局固定头部重叠 | sticky top 改为 `65px`,避让全局 header 和边框 |
|
||||
| P1 | React Strict Mode 下任务详情 `mountedRef` 清理后不恢复,详情可能停留在“任务不存在/加载中” | effect 挂载时重置 `mountedRef.current = true` |
|
||||
| P2 | 定时任务删除无确认 | 删除前增加确认弹窗 |
|
||||
| P2 | 定时任务播放/删除图标按钮无可访问名称且目标偏小 | 补充 `aria-label/title`,扩大到 44px |
|
||||
| P2 | tabs、summary、switch 等控件命中高度不足 44px | 统一提高到 44px 触控目标 |
|
||||
| P2 | 普通任务首次加载可能误显示空状态 | 增加 loading 状态 |
|
||||
|
||||
## 7. 剩余观察项
|
||||
|
||||
- 本轮自动化使用模拟 API 数据验证布局和交互;真实后端数据的极端状态仍需在后续页面联测中持续观察。
|
||||
- Playwright 报告中存在一次 404 控制台日志,来源为浏览器资源请求,不影响 Task 页面核心 API 与交互。
|
||||
Reference in New Issue
Block a user