---
name: prototype-specification
when: '原型, 设计稿, UI规范, 前端实现, 页面交互, 交互规约, Figma Make导出源码, 原型源码zip, React/Vite原型'
scope:
  - frontend
products:
  - '*'
id: ka-artifact_template-prototype-specification
asset_kind: acceptance_template
lifecycle_status: active
owner_mechanism_id: mc-generic-artifact
authority: supporting
routes:
  - '*'
primary_triggers:
  - 原型
  - 原型说明
  - prototype
  - 设计稿
  - UI规范
  - 前端实现
  - 页面交互
  - 交互规约
  - Figma Make导出源码
  - 原型源码zip
  - React/Vite原型
priority: P2
specificity: 3
version: 1.1.0
last_reviewed: '2026-06-01'
consumes: []
emits:
  - acceptance_report
secondary_triggers: []
negative_triggers: []
type: acceptance_template
artifact_schema:
  kind: prototype_spec
  required_sections:
    - 源码提取约束
    - 页面元数据
    - 设计令牌
    - 页面布局树
    - 组件数据绑定
    - 交互流转
    - 组件视觉状态
    - 响应式断点
    - 动效规范
    - 边界与异常分支
  required_tables:
    - 色彩令牌表
    - 间距与圆角表
    - 字体令牌表
    - 字段映射表
    - 组件视觉状态表
    - 响应式断点表
    - 动效规范表
  required_fields:
    色彩令牌表:
      - 令牌名
      - 色值
      - 用途
    间距与圆角表:
      - 令牌名
      - 值
      - 用途
    字体令牌表:
      - 令牌名
      - 值
      - 用途
    字段映射表:
      - UI 元素
      - 绑定字段
      - 格式化规则
      - 动态行为
    组件视觉状态表:
      - 组件
      - 状态
      - 视觉变化
    响应式断点表:
      - 断点
      - 宽度范围
      - 布局变化
    动效规范表:
      - 交互
      - 动效
      - 时长
      - 缓动函数
  forbidden_gaps:
    - 空功能描述
    - 空章节标题
process_rules:
  extract:
    instructions:
      - 从原型源码包（Figma Make 导出）中提取页面结构、设计令牌、交互逻辑
      - 设计令牌（色彩/间距/字体）必须从源码 CSS 变量中提取
      - 组件数据绑定必须映射到源码中的实际字段名
    constraints:
      - 只能从源码包提取，不得凭空编造
      - 每个组件必须有源码文件对应
  review:
    instructions:
      - 逐章节与原型源码包对比，标记偏差项和遗漏项
      - 偏差判定依据：章节缺失、表格数据与源码不一致、交互流程与源码行为不符
    constraints:
      - 不得删除模版要求的任何章节
      - 每个偏差项必须指出具体位置和源码参照
  fix:
    instructions:
      - 仅修改已标注的偏差项，保持已正确内容不变
    constraints:
      - 不得引入源码包中不存在的内容
stages: ["需求分析"]
---

# [页面名称] 原型与交互规约

## 0. 源码提取约束
> **硬性约束：** 原型说明只能从 Figma Make 导出的源码包（如 React/Vite zip）或已解压源码目录中提取。禁止使用 Figma MCP、浏览器运行态、站点截图或纯 Design 文件补充原型信息。若未提供源码包或源码目录，必须停止并要求补充源码输入。

### 0.1 输入来源
- **[Source Code]** 原型源码包路径：[如：/Downloads/xxx.zip；解压后 src/app/pages、routes.tsx、theme.css、imports/*.md]
- **[Requirement Doc]** PRD/需求说明：[如：docs/xxx.md]

### 0.2 必须读取的源码材料
1. `package.json`、`vite.config.*`、`src/main.*`、`src/app/App.*`：识别原型入口和运行框架。
2. `src/app/routes.*`：提取路由、页面清单和入口关系。
3. `src/app/pages/**/*`：提取页面结构、组件层级、文案、表单字段和业务模块。
4. `src/app/components/**/*`：提取复用组件、弹窗、菜单、表格、卡片和交互控件。
5. `src/styles/**/*`、`theme.css`、Tailwind 配置：提取颜色、字体、间距、圆角、阴影等设计令牌。
6. `src/imports/**/*`、`docs/**/*`：提取 Figma Make 导入的业务说明、图片和补充文档。

### 0.3 禁止使用的来源
- 禁止使用 Figma MCP 作为原型信息来源。
- 禁止使用 Playwright/浏览器访问 Figma Make 或 `.figma.site` 来补充交互。
- 禁止从截图、肉眼观察或 Design 文件臆测源码中不存在的状态。
- 源码中无法确认的信息必须标记为 `[Manual Confirm]`。

### 0.4 证据标记
- `[Source Code]` 来自原型源码、路由、组件、hooks、样式或导入文档。
- `[Source Doc]` 来自源码包内的 imports/docs/README/Markdown 文档。
- `[Source Asset]` 来自源码包内图片、图标或静态资源。
- `[Manual Confirm]` 需要人工确认。

## 1. 页面元数据
- **所属模块/端**：[如：移动端应用 / Web 管理端 / 运营后台]
- **关联 PRD 节点**：[如：3.2.1 业务流程 - A.2 操作步骤]
- **页面核心目标**：[一句话描述]
- **页面路由路径**：[如：/admin/items]
- **入口来源**：[如：首页推荐卡片点击 / 侧边栏菜单]
- **提取依据**：[Source Code / Source Doc / Source Asset / Manual Confirm]

---

## 2. 设计令牌 (Design Tokens)
> **说明：** 只能从 `theme.css`、`globals.css`、Tailwind 配置、组件 className 和内联样式提取。AI 实现时必须引用这些令牌而非硬编码数值。

### 2.1 色彩
| 令牌名 | 色值 | 用途 |
|--------|------|------|
| --color-primary | #1890FF | 主色/主按钮/链接 |
| --color-danger | #FF4D4F | 错误/删除/警告 |
| --color-success | #52C41A | 成功/已通过 |
| --color-warning | #FAAD14 | 提醒/待处理 |
| --color-text-primary | #262626 | 主文本 |
| --color-text-secondary | #8C8C8C | 次要文本/标签 |
| --color-bg-page | #F5F5F5 | 页面背景 |
| --color-bg-card | #FFFFFF | 卡片背景 |
| --color-border | #E8E8E8 | 分割线/边框 |

### 2.2 间距与圆角
| 令牌名 | 值 | 用途 |
|--------|------|------|
| --spacing-xs | 4px | 紧凑间距 |
| --spacing-sm | 8px | 元素内间距 |
| --spacing-md | 16px | 卡片内边距 |
| --spacing-lg | 24px | 区块间距 |
| --spacing-xl | 32px | 页面边距 |
| --radius-sm | 4px | 小圆角（标签） |
| --radius-md | 8px | 中圆角（卡片） |
| --radius-lg | 12px | 大圆角（弹窗） |

### 2.3 字体
| 令牌名 | 值 | 用途 |
|--------|------|------|
| --font-size-xs | 12px | 辅助文字/标签 |
| --font-size-sm | 14px | 正文 |
| --font-size-md | 16px | 小标题 |
| --font-size-lg | 20px | 区块标题 |
| --font-size-xl | 24px | 页面标题 |
| --font-weight-normal | 400 | 正文 |
| --font-weight-medium | 500 | 标签/强调 |
| --font-weight-bold | 700 | 标题/金额 |

---

## 3. 页面布局树
> **说明：** 请严格按此层级结构和 Flex/Grid 布局参数构建 DOM 树。

### 3.1 整体布局
- **布局方式**：Flex Column，height: 100vh
- **[Header]** 顶部导航栏：高度 48px，position: sticky top: 0，z-index: 100
  - 内部布局：Flex Row，align-items: center，padding: 0 16px
  - 返回按钮：左侧，width: 24px
  - 页面标题：居中，font-size: var(--font-size-md)
- **[FilterBar]** 筛选区：高度 auto，padding: 12px 16px，background: var(--color-bg-card)
  - 内部布局：Flex Row，gap: 12px，flex-wrap: wrap
  - 每个筛选器：width: calc(33.3% - 8px)
- **[ContentArea]** 主体内容区：flex: 1，overflow-y: auto，padding: 16px
  - 内部布局：Flex Column，gap: 12px
  - **[CardItem]** 卡片组件：循环渲染，见 3.2
- **[Footer]** 底部操作区：高度 64px，position: sticky bottom: 0，padding: 12px 16px
  - 内部布局：Flex Row，justify-content: center
  - 主按钮：width: 100%，max-width: 375px

### 3.2 [CardItem] 卡片组件布局
- 外层：border: 1px solid var(--color-border)，border-radius: var(--radius-md)，padding: var(--spacing-md)
- 内部：Flex Column，gap: 12px
  - **头部行**：Flex Row，justify-content: space-between
    - 标题：font-size: var(--font-size-md)，font-weight: var(--font-weight-bold)
    - 价格：color: var(--color-danger)，font-weight: var(--font-weight-bold)
  - **标签行**：Flex Row，gap: 8px，flex-wrap: wrap
    - 每个标签：padding: 2px 8px，border-radius: var(--radius-sm)，font-size: var(--font-size-xs)
  - **操作行**：Flex Row，justify-content: flex-end

---

## 4. 组件数据绑定与渲染逻辑

### 4.1 [CardItem] 字段映射
| UI 元素 | 绑定字段 | 格式化规则 | 动态行为 |
|---------|---------|-----------|---------|
| 卡片标题 | 机构资料.机构名称 | 单行，超出 text-overflow: ellipsis | 无 |
| 价格标签 | 服务资料.收费标准 | 红色加粗 + "元/月" | 无 |
| 特色标签 | 机构资料.特色标签数组 | 最多显示前 3 个 | 数组为空则隐藏整行 |
| 无余量徽标 | 资源底数.当前可用 | 右上角绝对定位 | 值=0 时显示 |

### 4.2 动态渲染规则
- **售罄/无余量**：`当前可用 == 0` → 卡片整体 opacity: 0.6，右上角叠加"无余量"徽标
- **选中状态**：选中时 border-color: var(--color-primary)，左侧显示蓝色竖条 3px
- **加载中**：显示 Skeleton 占位，3 行高度分别为 24px/16px/16px，间距 12px

---

## 5. 交互流转与状态机

### 5.1 事件：点击底部 [发起协调] 按钮

```
[初始状态] → 点击 → [前置校验] 
                        ├─ 未选中 → Toast "请先选择目标机构" → [初始状态]
                        └─ 已选中 → [执行动作]
                                      ├─ 按钮: "提交中..." + disabled
                                      ├─ 调用 POST /api/v1/coordination/init
                                      └─ 等待响应
                                            ├─ 200 成功 → Toast "发起成功" → 跳转 /payment?coordId={id}
                                            ├─ 400 参数错误 → Modal 展示错误详情
                                            ├─ 409 冲突 → Toast "该机构已有进行中的协调"
                                            └─ 5xx 服务异常 → Modal "服务繁忙，请稍后重试"
```

### 5.2 事件：筛选器变更
- 触发方式：下拉选择器 onChange
- 行为：重置分页到第 1 页，调用列表查询接口，ContentArea 显示 Loading
- 防抖：300ms

---

## 6. 组件视觉状态

| 组件 | 状态 | 视觉变化 |
|------|------|---------|
| [CardItem] | 默认 | 白底，1px 灰色边框 |
| [CardItem] | 悬停 | 轻微阴影 elevation +2 |
| [CardItem] | 选中 | 左侧蓝色竖条 + 蓝色边框 |
| [CardItem] | 无余量 | 整体 opacity: 0.6 + 右上角"无余量"标 |
| 主按钮 | 默认 | 蓝色背景，白色文字 |
| 主按钮 | 悬停 | 背景色加深 10% |
| 主按钮 | 加载中 | 禁用 + 旋转图标 + "提交中..." |
| 主按钮 | 禁用 | 灰色背景，cursor: not-allowed |
| 筛选器 | 展开 | 蓝色边框 + 下拉面板 |
| 筛选器 | 已选 | 文字变蓝色 + 右侧清除图标 |

---

## 7. 响应式断点

| 断点 | 宽度范围 | 布局变化 |
|------|---------|---------|
| Mobile | < 768px | 卡片全宽，筛选器纵向堆叠，底部固定 |
| Tablet | 768px - 1024px | 卡片双列，筛选器横向，底部固定 |
| Desktop | > 1024px | 卡片三列，ContentArea max-width: 1200px 居中 |

---

## 8. 动效规范

| 交互 | 动效 | 时长 | 缓动函数 |
|------|------|------|---------|
| 卡片选中/取消 | 边框颜色 + 阴影变化 | 200ms | ease-out |
| 页面路由切换 | 右滑入/左滑出 | 300ms | ease-in-out |
| Toast 显示/隐藏 | 从顶部滑入，自动消失 | 300ms / 2000ms | ease-out |
| Modal 弹出 | 淡入 + 轻微缩放(0.95→1) | 200ms | ease-out |
| Skeleton 消失 | 淡出 | 150ms | ease-in |

---

## 9. 边界与异常分支

- **空状态**：列表接口返回空数组 → ContentArea 渲染缺省组件：插画 + "暂无符合条件的机构" + "重置筛选条件"按钮
- **网络异常**：接口超时或 50x → 展示错误占位页：图标 + "加载失败" + 重试按钮
- **数据截断**：机构名称超一行 → text-overflow: ellipsis，鼠标悬停显示完整名称（Tooltip）
- **数据加载**：首次加载 → Skeleton 占位（3 张卡片形状）；下拉刷新 → 顶部 Loading 条
- **无权限**：接口返回 403 → 全屏提示 "无访问权限" + 返回按钮
- **并发操作**：卡片被其他用户选满 → 接口返回 409 → 自动刷新列表 + Toast 提示
