# TFDS 页面模板交互联动规范

> **作用域**：多个页面模板之间存在一级 → 二级承接关系时，用本文件定义触发条件、数据传递、模板切换与回退行为。生成整页时禁止把两级页面混写成单页，也禁止在二级页重复实现一级页的 NavBar / Hero。

---

## 1. AI 入口页 → AI 对话页（`chat-home-to-conversation`）

| 项 | 约定 |
| --- | --- |
| 一级页面 | `ChatHomePagePattern`（`chat-home-page` / recipe `chat-home`） |
| 二级页面 | `ChatConversationPattern`（`chat-conversation-page` / recipe `chat-conversation`） |
| 关系 | 入口页负责「从 0 发起」；对话页负责「已进入任务后的持续协作」 |

### 1.1 触发条件

| 触发源 | 用户动作 | 是否进入二级页 |
| --- | --- | --- |
| Hero `ChatInput` | 输入内容后点击发送 | ✅ 必须 |
| 模板 / 助手 `Card` | 点击整张卡片进入（`onAction`） | ✅ 推荐（以卡片标题作为首条任务描述） |
| 筛选区 `Input` | 搜索模板 | ❌ 仅筛选，不跳转 |
| 模板区 `Tabs` | 切换分类 | ❌ 仅筛选，不跳转 |

### 1.2 切换行为（视觉与结构）

1. **整页替换**：一级页的 `NavBar + Hero + 模板网格` 整体退场，二级页 `ChatConversationPattern` 全屏接管（二级页本身不带左侧 `NavBar`，这是设计约定）。
2. **首条消息自动发出**：一级页发送的文本必须通过 `bootstrapSendSignal` 传给二级页；二级页挂载后自动调用与底部输入相同的 `handleSend` 链路，用户无需在对话页再点一次发送。
3. **会话标题**：顶栏标题默认取首条用户输入的截断文案（`deriveConversationTitleFromPrompt`，默认最多 24 字）；空文本时显示「新会话」。
4. **平台名一致**：`platformName` 应与一级页 `NavBar.brandName` 保持一致（默认「体验与服务」），并同步用于二级页顶栏品牌区与 AI `header.name`。
5. **直接进入消息流**：有 `bootstrapSendSignal` 时，二级页跳过「新建会话欢迎屏」，直接进入 `chat` 阶段并播放首条用户气泡入场动效 + AI 回复编排。

### 1.3 数据契约（代码）

```js
import {
  buildChatHomeConversationHandoff,
  createBootstrapSendSignal,
  deriveConversationTitleFromPrompt,
} from '@tfdesign/b-end/page-flows/chat-home-conversation-flow';
// 包内路径：page-flows/chat-home-conversation-flow.js（随 _b_end_runtime 下发）

// 一级页发送后：
const handoff = buildChatHomeConversationHandoff({
  text,
  ctx, // ChatInput onSend 第二参数：agent / mentions / attachments / segments
  platformName: navBrandName,
});

// 二级页承接：
<ChatConversationPattern
  title={handoff.title}
  platformName={handoff.platformName}
  bootstrapSendSignal={handoff.bootstrapSendSignal}
  onBackToHome={() => /* 路由回一级或清空 handoff 状态 */}
/>
```

`bootstrapSendSignal` 结构：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `text` | `string` | 首条用户消息正文（trim 后非空） |
| `seed` | `number` | 每次 handoff 唯一，用于 `useEffect` 触发一次自动发送 |
| `source` | `string` | 可选，`chat-home-hero-send` / `chat-home-template-card`；用于开启入口演示自动编排 |

`ChatInput` 上下文通过 `handleSend(text, { source: 'chat-home-handoff', ...ctx })` 透传，二级页与用户在对话页手动发送走同一套关键词路由 / 自动编排。

### 1.4 业务接入模式

| 模式 | 用法 |
| --- | --- |
| **模板内置演示**（TFDS 预览） | `ChatHomePagePattern` 默认 `enableConversationHandoff={true}`，发送后内部 state 切到 `ChatConversationPattern` |
| **应用路由** | 一级页 `onEnterConversation(handoff)` 里 `navigate('/ai/chat', { state: handoff })`；二级页路由读取 state 传入 `bootstrapSendSignal` |
| **禁用内置切换** | `enableConversationHandoff={false}` + 仅使用 `onEnterConversation` 交给外层路由 |

### 1.5 回退

- 二级页提供 `onBackToHome` 时，顶栏左侧显示返回按钮。
- 回退后恢复一级页完整布局（含 `NavBar`、Hero、模板区），**不**保留未发送草稿除非业务自行持久化。
- 「新建会话」仍走 `ChatConversationPattern` 内置逻辑，清空当前线程并回到对话页欢迎屏；若需回到一级入口页，应额外绑定回退或业务路由。

### 1.6 演示文案与模拟编排（入口 / 对话共用）

一级页与二级页的**交互示意文案**必须来自同一事实源：`page-flows/chat-conversation-demo.js`。

| 常量 | 用途 |
| --- | --- |
| `CHAT_DEMO_PLATFORM_NAME` | 默认平台 / 助手名（「体验与服务」） |
| `CHAT_DEMO_PROMPT_SUGGESTIONS` | 对话页欢迎 chip（三条）；入口页不在 Hero 下重复展示 |
| `CHAT_DEMO_FEATURED_TEMPLATE_TITLE` | 入口首推模板卡标题（默认「智能服务近7天趋势分析」） |
| `resolveChatDemoStarterContext(text)` | 按首条用户输入切换演示上下文（账号 / 环境 / 产物列表） |

约定：

1. 入口页 Hero 发送、模板卡点击，handoff 后二级页**自动**走与对话页直进相同的 `handleSend` → 深度思考 → 人工澄清（演示态自动确认）→ 任务执行流 → 产物卡编排；禁止停在「深度思考中」无后续。
2. 禁止在一级页内手写 `ChatMessage` 流做「假对话」；示意必须在二级页完成（见 §1.7）。
3. TFDS 预览在 handoff 后内容区已是 `ChatConversationPattern`，顶栏 pattern 名称可能仍显示「AI 入口页」——属预览外壳行为，业务路由应切换到 `chat-conversation-page`。

### 1.7 禁止项

- ⛔ 禁止在 `ChatHomePagePattern` 内手写消息流、`ChatMessage` 列表冒充二级页。
- ⛔ 禁止在 `ChatConversationPattern` 内重新放置一级页的模板 `Card` 网格或 Hero 大标题。
- ⛔ 禁止 handoff 时只改 URL 不传 `bootstrapSendSignal`，导致用户到二级页还要再发一次。
- ⛔ 禁止二级页为了「像入口页」加回左侧 `NavBar`（两级信息架构不同）。

---

## 2. AI 对话页 · 产物卡 → 产物详情分栏（`chat-conversation-artifact-detail`）

| 项 | 约定 |
| --- | --- |
| 触发 | 点击 `ChatMessage` 消息流中的产物卡（`resultArtifacts` / `ResultArtifactCard`） |
| 布局 | 顶栏不变；页面四周边距统一 **16px**（顶栏 + 内容区）；其下 `ChatArtifactSplitLayout` 默认产物区约 **70%**；**左侧对话区 `flex-1` 自适应**，**右侧产物区固定像素宽**；产物容器**左缘**拖拽把手调整产物宽度（向左拖宽产物、向右拖窄），可见竖线 **2px**，左右各自最窄 **300px**；两栏间距 **24px**；左侧 `ChatInput` 仅 `pt-2`，与右侧产物详情底对齐（同 Copilot 助手模版） |
| 详情面板 | 复用 `CopilotArtifactDetailPanel`：`blueGrey-50` header；**标题与左上角图标同左侧选中产物卡**；header 右侧「编辑」+ 关闭（`x-close-stroked`） |
| 收起 | 点击 header 关闭按钮、再次点击同一产物卡，或「新建会话」时清空选中态 |

```jsx
<CopilotArtifactDetailPanel
  artifact={selectedArtifact}
  onClose={() => setSelectedArtifact(null)}
>
  {renderArtifactDetailContent(selectedArtifact)}
</CopilotArtifactDetailPanel>
```

业务侧通过 `ChatMessage` 的 `onArtifactSelect` / `selectedArtifactId` 接入；模板预览由 `ChatConversationPattern` 内置 state 驱动。

### 2.1 产物详情正文槽位（`artifact-detail-content-slot`）

右侧白卡 = **固定 Header + 可滚动 Body 通用槽**。Header 只表达产物身份与操作，**不同类型产物的 UI 差异全部放在 Body**。

| 区域 | 职责 | 禁止 |
| --- | --- | --- |
| Header | `ArtifactIcon` + 标题（与左侧产物卡一致）+「编辑」+ 关闭 | 把表格/编辑器塞进 Header |
| Body | `children` 注入 TFDS 组件组合 | 裸 div 拼整页；槽位内再套全高 `overflow-hidden` 双滚动 |

**按 `artifact.type` 选型（与 `ChatMessage` / `file-type-assets` 图标类型对齐）**

| type | 推荐正文组件 | 典型场景 |
| --- | --- | --- |
| `webpage` / `web` | `FormTitle` + 只读 `TextArea` / 富文本区 | 政策网页、说明页预览 |
| `code` | `TextArea variant="code" fillHeight resize="none"` | 规则脚本、Prompt |
| `table` / `feishu-sheet` | `Table`（可选 `Filter`） | 判责对照表、多维表 |
| `strategy` / `knowledge` | `Card type="info3"` 列表 + `Tag` | 策略条目、知识片段 |
| `document` / `pdf` | 文档预览占位 + 元信息 | PDF / Word 预览 |
| `batch-report` | `Table` + `FormTitle` 小节 | 批测报告 |
| `conversation` | 只读消息摘录 | 会话上下文（非可编辑聊天） |
| 其它 / 未识别 | `FormTitle` + `Empty` 或业务自定义 `children` | 兜底 |

**实现约定**

- 事实源：`page-patterns/shared/artifact-detail-content.jsx`（`ARTIFACT_DETAIL_CONTENT_BY_TYPE`、`resolveArtifactDetailDemoContent`）
- 模板预览：按选中产物 type 自动渲染差异化演示正文；业务接入用 `children` 覆盖
- 空槽：未传 `children` 时显示「业务内容区域」占位，表示待填充
- Copilot 工作台右侧主产物区与 AI 对话分栏右侧 **共用同一槽位规则**，仅 Header 可扩展 Tab/Switch

---

## 3. 与其他模板的边界

| 场景 | 正确模板 |
| --- | --- |
| 从 0 输入需求 / 选模板 | `ChatHomePagePattern` |
| 已进入 AI 任务持续追问 | `ChatConversationPattern` |
| 右侧主产物编辑 + 侧栏 AI | `CopilotPagePattern`（不是本联动） |
| 真人客服 / 私信 | `IMConversationPattern`（不是本联动） |

选型详见 [PAGE_ARCHETYPES.md](./PAGE_ARCHETYPES.md) §0.1。
