# Codex Prompt: Phase D1 — 全库补齐 API 三表（Slots / Events）

Phase A 合规基线（[docs/internal/component-page-conformance-baseline-2026-04-28.md](../component-page-conformance-baseline-2026-04-28.md)）显示 18 / 22 个组件页缺 Slots / Events 显式表。本任务**批量补齐**——按 EP 模式，每个组件页 API 段必须有 Attributes / Slots / Events 三表，无内容时显式写 "None / 无" 行。

---

## 必读前置

1. [docs/internal/component-page-conformance-baseline-2026-04-28.md](../component-page-conformance-baseline-2026-04-28.md)（基线 + gap 分布）
2. [playground/docs/pages/BreadcrumbPage.vue](../../../playground/docs/pages/BreadcrumbPage.vue)（事实样板，API 段在 line 121-146）
3. [playground/docs/pages/InputNumberPage.vue](../../../playground/docs/pages/InputNumberPage.vue)（90 分参考，已有规范的 Attributes 表结构）

---

## 任务范围（精确 18 页）

按基线 A3 评分分两类：

### Class A：A3 = 0（缺 Slots **和** Events 两表，3 页）

1. `playground/docs/pages/NotificationPage.vue`
2. `playground/docs/pages/TooltipPage.vue`
3. `playground/docs/pages/PaginationPage.vue`

### Class B：A3 = 10（已有 Attributes，缺 Slots / Events 显式表，15 页）

4. `playground/docs/pages/ButtonPage.vue`
5. `playground/docs/pages/BadgePage.vue`
6. `playground/docs/pages/InputPage.vue`
7. `playground/docs/pages/InputNumberPage.vue`
8. `playground/docs/pages/CheckboxPage.vue`
9. `playground/docs/pages/RadioPage.vue`
10. `playground/docs/pages/SelectPage.vue`
11. `playground/docs/pages/DateTimePage.vue`
12. `playground/docs/pages/ProgressPage.vue`
13. `playground/docs/pages/SliderPage.vue`
14. `playground/docs/pages/RatingPage.vue`
15. `playground/docs/pages/TablePage.vue`
16. `playground/docs/pages/TopBarPage.vue`
17. `playground/docs/pages/PromptMessagePage.vue`
18. `playground/docs/pages/TabsPage.vue`

### 不在本任务范围（**禁止动**）

- Switch / Steps / FormItem / Breadcrumb（Steps 和 FormItem 是用户 WIP；Switch 和 Breadcrumb 已 A3 = 20 不需改）

---

## 任务 1：对每个 docs page 提取该组件的真实 slots / events

对 18 页中的每一页，先**只读**对应的 .vue 组件源文件提取：

### 1.1 Slots
- `<slot>` 标签的 `name=` 值（无 name 即 `default`）
- 每个 slot 出现的语义（hint：从周围模板看是 label / content / icon / default）

### 1.2 Events
- `defineEmits([...])` 中列举的事件名 + 参数类型
- 或 `defineEmits<{ ... }>()` TypeScript 形式
- 也包括 `<template>` 里直接 `@xxx` 透传的事件

### 1.3 文件位置查找规则

每个 docs page 通常 import 来自 `src/canonical/<X>.vue` 或 `src/components/<X>/<X>.vue`。读 docs page 顶部的 import 语句决定。

| docs page | 对应 .vue 源 |
|---|---|
| NotificationPage | `src/canonical/Notification.vue` |
| TooltipPage | `src/canonical/Tooltip.vue` |
| PaginationPage | `src/canonical/Pagination.vue` |
| ButtonPage | `src/canonical/ButtonBridge.vue` |
| BadgePage | `src/canonical/Badge.vue` |
| InputPage | `src/canonical/InputBoxLine.vue` + `InputBoxFilled.vue` |
| InputNumberPage | `src/canonical/InputNumber.vue` |
| CheckboxPage | `src/canonical/CheckBox.vue` |
| RadioPage | `src/canonical/Radio.vue` |
| SelectPage | `src/canonical/SelectBoxLine.vue` + `SelectBoxFilled.vue` + `DropDownListSelect.vue` |
| DateTimePage | `src/canonical/SelectBoxLine.vue` + `SelectBoxFilled.vue` |
| ProgressPage | `src/canonical/Progress.vue` |
| SliderPage | `src/canonical/Slider.vue` |
| RatingPage | `src/canonical/Rating.vue` |
| TablePage | `src/canonical/Table.vue` |
| TopBarPage | `src/canonical/TopBar.vue` |
| PromptMessagePage | `src/canonical/PromptMessage.vue` |
| TabsPage | `src/canonical/Tab.vue` + `TabItem.vue` + `TabList.vue` |

如果 page 实际 import 的不是上面列的，**以 page 实际 import 为准**。如果 page 同时 import 多个组件，slots / events 表合并展示，每行注明属于哪个组件。

---

## 任务 2：在每页 API 段补齐 Slots 和 Events 表

### 2.1 表格格式（必须严格遵守，仿 Breadcrumb 样板）

#### Slots 表

```html
<div class="api-table-wrap">
  <h3 class="api-table-wrap__title">{{ t('<X> Slots', '<X> Slots 插槽') }}</h3>
  <table class="api-table">
    <thead>
      <tr>
        <th>{{ t('Name', '名称') }}</th>
        <th>{{ t('Description', '说明') }}</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="row in <x>SlotRows" :key="row.name">
        <td><code>{{ row.name }}</code></td>
        <td>{{ t(row.description[0], row.description[1]) }}</td>
      </tr>
    </tbody>
  </table>
</div>
```

#### Events 表

```html
<div class="api-table-wrap">
  <h3 class="api-table-wrap__title">{{ t('<X> Events', '<X> Events 事件') }}</h3>
  <table class="api-table">
    <thead>
      <tr>
        <th>{{ t('Name', '名称') }}</th>
        <th>{{ t('Description', '说明') }}</th>
        <th>{{ t('Parameters', '参数') }}</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="row in <x>EventRows" :key="row.name">
        <td><code>{{ row.name }}</code></td>
        <td>{{ t(row.description[0], row.description[1]) }}</td>
        <td><code>{{ row.parameters }}</code></td>
      </tr>
    </tbody>
  </table>
</div>
```

### 2.2 数据 ref 定义（在 `<script setup>`）

```ts
const <x>SlotRows = [
  { name: 'default', description: ['Default slot for content.', '默认插槽承载内容。'] },
  // ...
] as const

const <x>EventRows = [
  { name: 'close', description: ['Emitted when user clicks the close icon.', '用户点击关闭图标时触发。'], parameters: '(): void' },
  // ...
] as const
```

### 2.3 No-content 行（核心规则）

如果组件**没有任何** slot 或 event：

```ts
const <x>SlotRows = [
  { name: '—', description: ['None — this component has no exposed slots.', '无插槽。'] },
] as const

const <x>EventRows = [
  { name: '—', description: ['None — this component does not emit events.', '无事件。'] },
] as const
```

**禁止**：完全省略表格 / 表格空 tbody。无 slot/event 也要表格存在 + 显式 None 行。

### 2.4 插入位置

在每页 API section（已有 Attributes 表的那个 `<section class="docs-section">`）**内部**：

- 现有 Attributes 表后
- 新加 Slots 表
- 再新加 Events 表

不要新建第二个 `<section>`，所有 API 表共用一个 section。

---

## 任务 3：grep 验证

```bash
# 每个修改后的 page 必须三个表都存在
grep -c "api-table-wrap__title" playground/docs/pages/{Notification,Tooltip,Pagination,Button,Badge,Input,InputNumber,Checkbox,Radio,Select,DateTime,Progress,Slider,Rating,Table,TopBar,PromptMessage,Tabs}Page.vue

# 每个 page 应输出 ≥ 3（Attributes + Slots + Events）。多组件 page（如 SelectPage 含 Line+Filled+DropDown）可能 ≥ 6
```

如有页面输出 < 3，**STOP 报告**，列出哪页未补齐，等用户指令。

---

## 任务 4：自验

```bash
# focused：只跑 docs / canonical 相关测试
pnpm exec vitest run tests/RemainingCanonicalPages.test.ts tests/Canonical.test.ts 2>&1 | tail -15

# 不跑 pnpm test 全量（用户 WIP 可能让其它测试红，会混报）
```

期望：所跑测试全部通过。任一失败 STOP 报告。

---

## 任务 5：写 execution report

输出：`docs/internal/phase-D1-execution-report.md`

格式：

```markdown
# Phase D1 Execution Report

跑时间：YYYY-MM-DD HH:MM:SS

## 处理范围
- Class A（缺两表，3 页）：Notification / Tooltip / Pagination
- Class B（缺 Slots+Events 显式表，15 页）：[列出]

## 每页变更摘要

### NotificationPage
- 源组件：src/canonical/Notification.vue
- 提取 slots: [列出]
- 提取 events: [列出]
- API 段新增 Slots 表 + Events 表
- 行数变化: before X 行 → after Y 行

### TooltipPage
... [每页一段]

## 任务 3 grep 验证结果
- [每页 api-table-wrap__title 出现次数]

## 任务 4 自验
- pnpm exec vitest tests/RemainingCanonicalPages.test.ts tests/Canonical.test.ts: [N / N passed]

## 异常项（如有）
[空 / 描述]
```

---

## 任务 6：自己 commit

由你（Codex）自己 commit 本轮改动。

### commit 范围（精确）

包含：
- 18 个修改的 docs page（playground/docs/pages/*.vue）
- `docs/internal/phase-D1-execution-report.md`
- `docs/internal/_prompts/phase-D1-add-api-three-tables.prompt.md`（本 prompt 归档）

不要 commit：
- 任何 `src/` 下文件
- 用户 WIP 的 8 个 dirty 文件（FormItemPage / StepsPage / Steps / StepItem / PromptMessage / RemainingCanonicalPages.test）
- `figma-data/published/icons/manifest.json`（如出现，git restore）
- `docs/internal/published-vs-code-audit.md` / `figma-data/normalized/published-vs-code.audit.json`（如出现，audit 副作用，git restore）

### 关键：与用户 WIP 共存

工作区有用户 dirty WIP（非本任务相关）：
```
M playground/docs/pages/FormItemPage.vue
M playground/docs/pages/StepsPage.vue
M src/canonical/StepItem.vue
M src/canonical/Steps.vue
M src/components/PromptMessage/PromptMessage.vue
M src/components/Steps/StepItem.vue
M src/components/Steps/Steps.vue
M tests/RemainingCanonicalPages.test.ts
```

**禁止 `git add .` 或 `git commit -a`**——会把用户 WIP 一起 commit 进 D1。
**必须显式 `git add <file>` 每个 D1 改的文件**。

如果 D1 范围正好包含 PromptMessagePage（确实在 18 页范围里），但用户的 PromptMessage runtime 也是 dirty——本轮**只**改 PromptMessagePage（docs），不动 PromptMessage runtime（src）。

### commit message

```
docs(api): add Slots/Events tables to 18 component pages (Phase D1)

Phase A baseline showed 18/22 component pages missing explicit
Slots and/or Events tables in their API section. EP-style docs
require all three tables (Attributes / Slots / Events), with
"None" rows where applicable.

Class A (3 pages, both Slots+Events missing):
- NotificationPage / TooltipPage / PaginationPage

Class B (15 pages, Slots+Events display missing):
- Button / Badge / Input / InputNumber / Checkbox / Radio
- Select / DateTime / Progress / Slider / Rating / Table
- TopBar / PromptMessage / Tabs

Per page: read corresponding canonical/runtime .vue source,
extract real <slot> names + defineEmits, render as bilingual
api-table format matching BreadcrumbPage.vue:121-146 sample.
Components with no slots/events get explicit "—" None rows.

Verified: api-table-wrap__title count ≥ 3 per page;
focused vitest tests/RemainingCanonicalPages.test.ts +
tests/Canonical.test.ts all green.

Co-Authored-By: Codex
```

---

## 三段式自报告（提交前必须输出）

按 [docs/docs-site-dx-parity-spec.md](../../docs-site-dx-parity-spec.md) §7 要求：

```markdown
## 已动手
- 改了 [N] 个 docs page，每页加 Slots + Events 表
- 写了 D1 execution report

## 仅诊断未动手
- [如有：发现某页 API 段结构异常但本轮未修，列出]

## 已知未解决
- [如有：某测试失败但与本轮无关，列出原因]
```

---

## 禁止

- ❌ 不动任何 `src/` 下文件
- ❌ 不动用户 WIP 的 8 个 dirty 文件
- ❌ 不动 Switch / Breadcrumb / Steps / FormItem 这 4 页（已合规或属用户 WIP）
- ❌ 不要把表格放在新 section 里——必须在已有 API section 内
- ❌ 不要省略 None 行——无 slot/event 也要写 "—" 行
- ❌ 不要跑 `pnpm test` 全量（会混入用户 WIP 引起的失败）
- ❌ 不要修 `figma-sync/` 任何脚本（这是审计脚本任务，不是本轮范围）
- ❌ 不要 sneak D2/D3/D4 的工作进来

---

## 完成后

1. 报告 + 自 commit 完成后 STOP
2. 把执行报告路径告诉用户
3. 等主 Session 决定是否进 D2 / D3

完成后 STOP。
