# MicroApps Console Demo — 设计 Spec

- **日期**：2026-05-09
- **作者**：Nancy + Claude（plan owner）
- **状态**：Draft，待 user review
- **产物**：单 HTML 文件 demo，给 PM 看效果用

---

## 1. 目标

把 Figma 文件 `Micro-Apps-20250923` 中的两张设计稿——**MicroApps · Master Console** 与 **MicroApps · My Sessions**——实现成**一个可交互的单 HTML 文件 demo**，供 PM 直接打开查看效果，无需 build / install / 部署。

### Figma 真源

- 文件：[Micro-Apps-20250923](https://www.figma.com/design/DtZcMkhNy6qh6jbQQnhreQ/Micro-Apps-20250923?node-id=2956-4544)
- Master Console：1920 variant `3278:1835` / 1440 variant `3289:2530`
- My Sessions：1920 variant `3289:2726` / 1440 variant `3289:2922`
- 默认参考 1440 variant 实现，1920 用于扩展端验证

---

## 2. 范围（Scope）

### In scope

- 两张页面（Master Console、My Sessions）的视觉与交互实现
- 顶部导航 + 筛选栏 + 可折叠 App 卡片 + Sessions 表格
- 状态管理的轻交互（搜索/状态过滤/排序/折叠 真实生效）
- Clone session、URL inline 编辑、Stop 确认弹窗、Open 新 tab 4 项真实操作
- 1200–2400px 流式响应
- Dark theme，按 Figma 1:1
- Mock 数据：Figma 已展开的 4 个 App 用真数据 + 另 4 个 App 补合理 mock 行
- 持久化范围：折叠状态用 sessionStorage（刷新保持），其他不持久化

### Out of scope

- 测试（Demo 性质）
- 无障碍审计 / WCAG 校对
- 真实后端 / API 接入 / 鉴权
- Light theme（Figma 设计稿是 dark only）
- 多语言 / i18n
- vue-router / Pinia / build 工具链

---

## 3. 架构决策

| 决策项 | 选定方案 | 理由 |
|---|---|---|
| 产物形态 | **单 HTML 文件** | PM 双击打开，可直接上传分享 |
| 框架 | Vue 3 via CDN（`vue.global.prod.js`） | 状态管理简单；无 build；~33KB gzip |
| 路由 | hash 路由（`#/master-console`、`#/my-sessions`），自实现 | 不增加 vue-router 依赖；URL 可分享 |
| 状态 | Vue `ref` / `computed`，inline | 2 页 demo 不需要 Pinia |
| tvu-design-system 依赖 | **不依赖** | 单 HTML 文件不能消费 npm 包；视觉/token 参 Figma 真源 |
| 构建工具 | **无** | 直接写 HTML/CSS/JS |
| 类型系统 | **无 TS**（纯 JS） | 单文件浏览器直跑 |

---

## 4. 文件结构

```
/Users/nancy/Documents/AICoding/VS_Code/MicroApps Console/
├── docs/
│   └── 2026-05-09-design.md           # 本文档
├── microapps-console-demo.html        # 唯一交付物，自包含
└── (可选) assets/
    └── open-placeholder.png           # 后续用户提供 demo 图替换
```

预估 HTML 体量：~1500–2500 行（含内联 CSS 与 mock 数据）。

---

## 5. 数据模型

### 5.1 App

```js
// JS 对象（JSDoc 类型注释）
/**
 * @typedef {Object} App
 * @property {string} id           - kebab-case 唯一键，如 'av-sync'
 * @property {string} name         - 展示名，如 'AV Sync'
 * @property {string} iconColor    - Figma 每 App 头部彩色圆形图标的 hex 色值
 * @property {string|null} tag     - 可选 App 级标签（如 "+ Cluster"），未在 Figma
 *                                   完全确认前用 null；implementation 阶段从
 *                                   Figma get_design_context 取真值
 */
```

### 5.2 Session

```js
/**
 * @typedef {'on-air' | 'preview' | 'analyzing' | 'inactive'} SessionStatus
 * @typedef {'healthy' | 'warning' | 'error'} SessionHealth
 *
 * @typedef {Object} Session
 * @property {string} id                  - 唯一 ID
 * @property {string} appId               - 归属 App
 * @property {string} objectId            - 长 UUID，UI 截断显示
 * @property {string} source              - 创建人/源（如 '@john.doe'）
 * @property {string} eventName           - 事件名
 * @property {string} inputUrl            - 输入流 URL（可 inline 编辑）
 * @property {SessionStatus} status       - 状态
 * @property {SessionHealth} health       - 健康度
 * @property {number|null} startedAt      - Unix ms；status === 'inactive' 时为 null
 * @property {string|null} errorMessage   - health === 'error' 时填充，tooltip 显示
 */
```

### 5.3 派生数据

- `activeDuration = now - startedAt`（仅 status ≠ 'inactive' 时显示，格式 `02:14:32`）
- `visibleApps = applyFilters(APPS, FILTERS)`（搜索 + 状态过滤 + 排序）
- `expandedApps = Set<appId>`（持久化到 sessionStorage）

### 5.4 全局 Filter

```js
{
  search: '',                                       // 文本输入
  activeOnly: 'all' | 'active' | 'inactive',        // 仅 Master Console
  statuses: { 'on-air': true, preview: true, analyzing: true, inactive: true },
  sort: 'app-az' | 'updated-desc' | 'sessions-desc',
}
```

切换 Master Console / My Sessions 时 filter state **保留**（除 `activeOnly` 仅 Master Console 可见）。

### 5.5 Mock 数据

- Figma 已展开的 4 个 App（AV Sync / Color Correction / Media Analyzer / Test Pattern Generator）→ Object ID / Source / Event Name / Input URL / Status / health 1:1 抠 Figma
- 未展开的 4 个 App（Audio Remapping / Graphics Insertion / SCTE Insertion / Standard Conversion）→ 每个补 2-3 行同风格 mock，覆盖至少 2 种 status + 至少 1 个 error health

---

## 6. 组件分解

10 个 Vue inline 组件，全部定义在同一 `<script>` 块：

| 组件 | 职责 | 关键 props/state |
|---|---|---|
| `App` | 根容器，挂 TopBar + Page + Toast portal | currentPage（来自 hash） |
| `TopBar` | logo + 页面 tab 导航（Master Console / My Sessions）+ 状态指示器 + 用户区 | currentPage, onNavigate |
| `MasterConsolePage` | Master Console 视图 | apps, filter |
| `MySessionsPage` | My Sessions 视图（与 MasterConsolePage 多数共用，仅 FilterBar 配置不同） | apps, filter |
| `FilterBar` | 搜索 + (可选)分段 + 状态 chip 组 + 排序 + 视图切换 | filter, showActiveSegment |
| `StatusChipGroup` | 4 个状态 chip 组合，含计数 + 勾选 | counts, selected |
| `AppCard` | 折叠卡（头部 + 折叠区 sessions table），头部点击切折叠 | app, sessions, expanded |
| `SessionRow` | 单行 session（5–6 列 + 操作图标） | session, onClone/onEditUrl/onOpen/onStop |
| `StatusBadge` | 状态徽章 + health 小图标 | status, health, errorMessage |
| `ConfirmDialog` | Stop 操作的确认弹窗（按 Figma 设计） | open, title, body, confirmText, cancelText |
| `Toast` | 顶部右下角短暂浮层 | queue（多条排列） |

---

## 7. 页面差异

| 项 | Master Console | My Sessions |
|---|---|---|
| TopBar 当前 tab | "Master Console" 高亮 | "My Sessions" 高亮 |
| FilterBar 分段控件 | ✅ 显示 All / Active / Inactive | ❌ 隐藏 |
| Sessions 数据范围 | 显示**所有用户**的 sessions | 仅显示**当前用户**的 sessions |
| 其他 | 一致 | 一致 |

> **设计假设**（非 Figma 真源）：当前用户 = `@john.doe`。Figma 截图里两页内容看起来一致，但语义上 "My Sessions" 应当过滤当前用户，否则两页只剩一个分段控件的差别没有 PM-meaningful 信息量。Mock 数据里 `source === '@john.doe'` 的 session 在 My Sessions 显示，其余隐藏。如 user 否决该假设，可在实施阶段改为"两页同数据"。

---

## 8. 交互行为（Truth Table）

### 8.1 真实生效

| 触发 | 行为 |
|---|---|
| TopBar 点击 "Master Console" / "My Sessions" | 改 `window.location.hash`，hashchange 监听更新 currentPage，视图切换 |
| 搜索框输入 | 实时过滤 sessions（match `objectId` / `source` / `eventName` / `inputUrl`，case-insensitive） |
| 状态 chip 勾选/取消 | 过滤对应状态 sessions（取消 = 隐藏） |
| 排序下拉切换 | 重排 apps 显示顺序 |
| Master Console All/Active/Inactive 分段 | 过滤 App：'active' 仅展示有任何活跃 session 的 App，'inactive' 反之 |
| AppCard 头部点击 | 切折叠状态，写 sessionStorage |
| **SessionRow Clone** | 复制本行，**插入到该 App sessions 数组顶部**；新 ID 形如 `<原ID>-clone-<timestamp>`。字段处理：`status` 一律重置为 `'preview'`（新建 session 默认非 on-air）；`health` 重置为 `'healthy'`；`errorMessage` 清空；`startedAt` 重置为 `Date.now()`；其他字段（objectId / source / eventName / inputUrl）保持原值 |
| **SessionRow URL 单元格点击** | 切换为 `<input>`：autofocus，blur 或 Enter 提交，Esc 取消（恢复原值） |
| **SessionRow Stop** | 打开 ConfirmDialog；确认后该 session.status → 'inactive'，`startedAt` 清除 |
| **SessionRow Open** | `window.open(OPEN_TARGET, '_blank')`；`OPEN_TARGET` 默认 `about:blank`，后续替换为用户提供的 demo 图 URL（assets/open-placeholder.png 或外链） |

### 8.2 Toast 占位（点击仅弹气泡，3s 自动消失）

- **"+ New Session" 按钮**——每张 AppCard 头部右侧各一个；Figma 未见全局新建按钮，本 demo 也不补
- **SessionRow 上 Clone / URL / Stop / Open 以外的其他图标**（如可能的 Edit / Delete / Settings 等，待 implementation 阶段对 Figma `get_design_context` 确认实际图标集）
- **TopBar 用户头像菜单**点击
- 任意未实现的小操作

### 8.3 视觉反馈

- AppCard 头部 hover：背景微高亮（+4% lightness）
- SessionRow hover：背景微高亮 + 操作图标淡入（默认半透明）
- 操作图标 hover：tooltip 显示功能名（"Clone" / "Open" / "Stop" 等）
- 空过滤结果：列表区显示 "No sessions match the current filter" 占位
- Stop 确认中、Clone 完成、URL 编辑保存：briefly highlight 行（300ms 背景闪一下）

---

## 9. 响应式策略

| 视口宽度 | 行为 |
|---|---|
| `< 1200px` | 不专门支持，浏览器横向滚动（不在 demo 范围内） |
| `1200–1400px` | 隐藏 inputUrl 列；objectId 截短；FilterBar 排序+视图切换允许换行 |
| `1400–1700px` | 标准布局（Figma 1440 基线） |
| `1700–2000px` | content 容器最大宽度 1800，水平居中 |
| `2000–2400px` | 同上，留白增加；不拉伸内容 |
| `> 2400px` | 不专门支持（content 居中即可） |

实现要点：
- 容器横向 padding 用 `clamp(16px, 2vw, 32px)`
- Sessions 表格列宽用 `minmax()` grid，按视口收放
- 字号不响应式（保持设计稿尺寸）

---

## 10. 视觉 Token

> 以下是 implementation 起手 baseline；实施时会用 `get_design_context` 取 Figma 真值校准。

```css
:root {
  /* 背景 */
  --bg-canvas: #0B0F1A;
  --bg-card: #141925;
  --bg-card-header: #1A2030;
  --bg-elevated: #1E2535;       /* dialog, dropdown */

  /* 边界 / 描边 */
  --border-subtle: rgba(255,255,255,0.06);
  --border-default: rgba(255,255,255,0.10);
  --border-strong: rgba(255,255,255,0.18);

  /* 文本 */
  --text-primary: #E6EAF2;
  --text-secondary: #8B95A7;
  --text-tertiary: #5A6478;

  /* 状态 */
  --status-on-air: #FF4D4F;
  --status-preview: #FAAD14;
  --status-analyzing: #1890FF;
  --status-inactive: #5A6478;

  /* 健康状态 */
  --health-healthy: #22C55E;
  --health-warning: #FAAD14;
  --health-error: #FF4D4F;

  /* Accent */
  --accent-primary: #2E5BFF;
  --accent-primary-hover: #4F77FF;

  /* 字号 */
  --fs-page-title: 18px;
  --fs-section-title: 16px;
  --fs-body: 14px;
  --fs-caption: 12px;

  /* 字重 */
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;

  /* 间距（8 倍数） */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;

  /* 圆角 */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
}
```

---

## 11. Open Items（待实施阶段从 Figma 取真源）

implementation 起手必须做的 3 件事：

1. **Stop 确认弹窗**：调 `get_design_context` 找到 confirm modal 节点，取实际样式 + 文字。spec 此处仅占位，不预设确认/取消按钮文字。
2. **SessionRow 操作图标完整集**：调 `get_design_context` 拿到 1440 variant 的 SessionRow 节点，列出所有图标的真实集合（Clone / URL / Open / Stop 是已知 4 个，其余可能还有 Edit / Delete / Settings 等需对齐）。
3. **Color tokens 校准**：用 `get_variable_defs` 或 `get_design_context` 对 Figma 真源 hex 取值，覆盖 §10 的 baseline。

---

## 12. 验证标准

implementation 完成判定：

1. **可打开**：双击 `microapps-console-demo.html` 在 Chrome / Safari / Firefox 至少 Chrome 能正常渲染（PM 主用 Chrome）
2. **路由**：URL hash 切换 `#/master-console` ↔ `#/my-sessions` 视图切换；刷新保持当前页
3. **交互真实**：搜索 / 状态 chip / 排序 / 折叠 / Clone / URL inline 编辑 / Stop 确认 / Open 新 tab 全部按 §8.1 工作
4. **视觉对齐**：在 1440 / 1920 视口下与 Figma 截图对比无明显视觉差（颜色 / 间距 / 字号 / 圆角）
5. **流式响应**：在 1200 / 1440 / 1700 / 1920 / 2400 五档视口宽度下视觉无破溃，无横向滚动（< 1200 除外）
6. **占位 Toast**：未实现操作点击 → toast 出现 → 3s 后自动消失
7. **持久化**：folded apps 状态在刷新后保持；其他状态（filter / search）不保持

---

## 13. 风险 & 注意事项

- **Vue CDN 联网依赖**：首次打开需联网拿 Vue。若 PM 在飞行/限网环境，会白屏。**已知 trade-off**，user 已确认接受。
- **tvu-design-system 视觉漂移**：本 demo 不依赖 tvu，token 各取各的。如果 tvu 后续改了主色，demo 不会自动同步。**已知**，demo 不算 tvu 下游。
- **Open 占位**：`about:blank` 用户体验不佳，但等 user 提供 demo 图后替换。中间态可用一段简单 HTML（"This is a placeholder for the live monitor view"）作为兜底。
- **mock 数据规模**：8 apps × ~3-5 sessions = ~30 行。filter 过快应无性能问题。如后续要扩到 100+ 行需考虑虚拟滚动（**不在 demo 范围**）。

---

## 14. 后续步骤

1. user review 本 spec → 提反馈或批准
2. 转入 `superpowers:writing-plans` 出实施计划（task 拆分 + 依赖 + 验证 step）
3. implementation 阶段（按 plan 执行）
