原型图转前端Code — 执行协议 v1.1
0. 核心约束(先读这段,违反任何一条就是返工)
一次看全 → 一份规格单 → 一次写完 → 一张对比图 → 只修差异。
- 同一张原型图最多 3 次视觉解析:1 次全图 + 至多 2 次局部放大。
- 测量的目标是"比例和层级对得上",±2px 的差异一律不修。
- 动手写代码前必须有规格单(第 2 节 S2 模板),没有就不许开始写。
- 不要给用户出选择题,技术栈/样式/交互按第 5 节默认值定,交付时声明即可。
- 时间基线:一张 1920 宽的后台页面,从读图到交付 6–8 分钟。超过 10 分钟,说明在第 0 条上走偏了(通常是反复量同一张图,或在 1px 上打转)。
1. 适用 / 不适用
适用:用户给了界面截图 / 原型图 / 线框图 / Figma 导出图,要求"照着还原""转成网页/页面/组件""1:1 还原"。
不适用:只有口头描述没有图(→ 直接写页面);给的是已有代码要改(→ 常规改代码);给的是 PDF/文档(→ 走文档解析)。
2. 阶段协议(按序执行,不要跳)
S1 读全图 —— 1 次调用,约 1 分钟
调用 ViewImage,一次问完,不要问"这是什么界面"这类开放问题。提问模板(照抄,按图替换):
> 精确描述这个界面,用于前端代码还原:
> 1) 整体布局:顶栏/侧栏/主区/底部如何分区,各自的宽高比例,分隔线位置
> 2) 全部可见文字:按区块逐条列出(logo 文字、面包屑、菜单项、标签页、表单标签、按钮、提示语),保持原文,不要概括、不要翻译
> 3) 组件清单:按区域列出输入框/按钮/表格/标签/下拉等,标注数量和相对位置
> 4) 视觉层级:哪一项是选中/激活状态,用什么方式表达(底色/文字色/下划线/左侧竖条)
> 5) 读不准的字直接说"看不清",不要猜
之后只在两种情况下追加放大(最多 2 次):关键文案会影响功能语义;有图标必须画对。
局部放大姿势(不要整图重复解析,只裁那一小块):
python -m pip install pillow -q # 缺 Pillow 时
python -c "from PIL import Image; im=Image.open(r'<图片绝对路径>').convert('RGB'); im.crop((x0,y0,x1,y1)).resize(((x1-x0)*3,(y1-y0)*3), Image.LANCZOS).save('_crop/zoom.png')"
S2 写规格单 —— 必须落成文本,约 2 分钟
在回复里先给出这份单子(用户看得到,也是你写码的依据),缺项当场补:
【画布】截图 W×H / 推断视口 ? / 缩放 k=?
【骨架】header 高 ? / sidebar 宽 ? / tabbar 高 ? / 内容 padding ?
【色板】primary #? / btn-primary #? / text-1 #? / text-2 #? / text-3 #?
border #? / bg-sidebar #? / active-bg #?
【字号】正文 ? / 标题 ? / 表单标签 ? / 辅助 ?
【控件】input W×H / button W×H / 菜单行高 / 圆角档位
【文案】<逐条列出,直接作为代码里的字面量>
【组件】<组件树;标出可复用项 + 三种状态:default / hover / active>
【缺口】图里没有但交互需要的部分 → 采用第 6 节哪条默认策略
S3 一次写完 —— 约 2 分钟
文件结构三选一,选定不换:
| 场景 | 结构 |
|---|---|
| 单页静态、无框架要求 | index.html + styles.css + script.js |
| 需要组件复用 / 多状态 | React 或 Vue + 单文件组件 |
| 用户点名 | 从用户 |
硬性要求:
- CSS 变量集中定义在
:root,颜色/间距/字号不许散落魔法值 - 图标用内联 SVG symbol 精灵,一个图标一个
<symbol>,用<use href="#id">引用。不引 CDN(离线打开会空白) - 表单控件必须有
<label>或aria-label;图标按钮必须有aria-label - 一次成型,不要"先搭空壳再补样式再返工"三轮
S4 截图自检 —— 1 张对比图,约 1 分钟
不截图就交付 = 交付未验证的代码。
# Windows (Git Bash)
"/c/Program Files/Google/Chrome/Application/chrome.exe" --headless=new --disable-gpu \
--hide-scrollbars --window-size=<与原图同宽>,<同高> \
--screenshot="$PWD/_check.png" "file:///<项目绝对路径>/index.html"
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless=new --disable-gpu \
--hide-scrollbars --window-size=<W>,<H> --screenshot="$PWD/_check.png" "file://$PWD/index.html"
用 ViewImage 看这张图,只回答三个问题:有没有错位 / 换行 / 缺失 / 截断 / 多余的空白块。只修看得见的差异,不重排页面。
交付前删掉 _check.png 和裁切目录。
S5 交付 —— 固定 6 段,控制在 50 行内
见第 8 节模板。
3. 尺度推断(省时间的关键,别跳过)
截图不会告诉你 DPR 或浏览器缩放。用已知控件的标准尺寸反推,而不是量遍每个元素:
| 控件 | 常见基准值 |
|---|---|
| 输入框高 | 32(antd / element 默认)/ 34 / 36 / 40(大号) |
| 按钮高 | 32 / 40 |
| 菜单行高 | 40 / 44 / 48 / 50 |
| 顶栏高 | 48 / 56 / 64 |
| 标签栏高 | 40 / 48 / 56 |
| 表格行高 | 40 / 48 |
| 正文字号 | 12 / 13 / 14 / 16 |
做法:量一个最确定的控件(例如第一个输入框的上下边框间距 = 高度 h),拿 h 比基准值 → 得到缩放 k → 其它尺寸用 k 折算后四舍五入到最近的档位。
- k ≈ 1:直接按像素取整用。
- 截图宽度是 1917、1913 这种非整数:正常现象(滚动条 / 显示缩放),不要因此怀疑比例。
- 判断 DPR:截图宽度 ÷ 1280 / 1440 / 1536 / 1920,接近 1 / 1.25 / 1.5 / 2 的那个就是缩放比。
结论先行:目标是"比例与层级一致 + 视觉接近",不是还原到小数点。中途发现自己在纠结 1.775 还是 1.8,立刻停下,按基准值取整。
4. 取样规范(要量什么,不要量什么)
一次性批量取样,别一个颜色一次调用:
python - <<'EOF'
from PIL import Image
im = Image.open(r'<图片绝对路径>').convert('RGB'); px = im.load()
for name, (x, y) in {"header": (900, 20), "sidebar": (200, 900), "btn": (360, 400), "text": (290, 150)}.items():
r, g, b = px[x, y]
print(f'{name:8s} #{r:02X}{g:02X}{b:02X}')
EOF
必量:主色、按钮色、正文/次要/辅助文字色、边框色、侧栏底色、激活底色;顶栏/菜单行/标签栏高度;输入框与按钮尺寸;容器宽度。
不必量(直接用档位):
- 圆角 → 4 / 6 / 8 三档取近(后台类默认 4)
- 阴影 → 两档:
0 2px 8px rgba(0,0,0,.08)(卡片)/0 6px 20px rgba(0,0,0,.14)(浮层) - 图标 → 16 / 18 / 20,stroke 1.6–1.8,
linecap: round - 分隔线 → 1px,
#EEEFF1系
取色规则:取"面积最大的那个纯色"(用 Counter 统计),不要取边缘抗锯齿像素;文字色取笔画最深处,取不到就用 #1D2129 / #4E5969 / #86909C 三档。
同一色系不要纠结超过 1 次:#1677FF 和 #1E98D7 肉眼差一点点,以面积最大处为准写进 token,交付时说一句"取自原图取样"即可。
5. 默认决策表(别问用户,直接定,交付时声明)
| 项 | 默认选择 |
|---|---|
| 技术栈 | 无框架要求 → 纯 HTML/CSS/JS;需组件复用/多页 → React |
| 样式方案 | 纯 HTML → 原生 CSS + 变量;React/Vue → CSS Modules(用户提过 Tailwind 则用 Tailwind) |
| 组件库 | 不引。原型若是自研设计语言,引 antd/element 只会让样式对不上 |
| 图标 | 内联 SVG,Lucide 风格(stroke 1.7,圆端点);能识别语义就用同名图标 |
| 字体 | -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif |
| 图片/头像/logo | 缺失时:纯色块 + 首字母,或按形状近似矢量重绘,交付时明确说明 |
| 交互 | 默认实现:菜单切换、tab 切换、hover/focus、表单校验 + 提交反馈、侧栏收起 |
| 只有一屏 / 一个 tab 有设计 | 其它 tab 给空态占位(一句说明 + 轻图标),不要编造表单字段 |
| 移动端 | 默认做:≤900px 侧栏变抽屉 + 遮罩,表单标签换行堆叠,宽内容横向滚动 |
| 列表/表格数据 | 用与界面同语境的示例数据(不要 Lorem ipsum),行数够撑满一屏 |
6. 问用户标准
只有三种情况,且一次问清(≤2 个问题):
- 技术栈有强约束,选错要重写(例如用户项目里已有 Vue 工程)
- 图上信息互相矛盾,且影响信息架构(不是视觉细节)
- 必须拿到真实素材才能达标(品牌 logo 矢量、产品实拍图)
其余情况:做默认选择 + 交付时标注假设。用户改一句话比等你回答更快。
7. 自检清单(12 条,逐条过)
- [ ] 布局分区、区域宽高、区块顺序与原图一致
- [ ] 主色/文字色/背景色取自取样值,不是"我觉得好看"
- [ ] 字号层级与控件尺寸都落在档位上,无 13.5px 这类野值
- [ ] 间距有节奏(4/8/12/16/24 档位),无随意 margin
- [ ] 激活态(菜单/tab)有底色 + 指示条,hover 有反馈
- [ ] CSS 变量覆盖所有颜色与间距,无散落魔法值
- [ ] 无重复组件、无未使用代码、无 console 残留
- [ ] 交互可点:菜单、tab、表单校验、按钮反馈都能用
- [ ] 1100 / 900 / 640 三个断点下不错乱
- [ ]
img alt/ 控件 label / 图标按钮 aria-label 齐全,:focus-visible可见 - [ ]
[hidden]陷阱:任何自身写了display:flex / grid / block的元素,只要会用hidden属性控制显隐,必须在 CSS 里补[hidden]{display:none!important}。原生hidden会被类选择器覆盖,症状是"该藏的东西一直在" - [ ] 截图验证过一遍,临时文件已清理
8. 交付模板(6 段,≤50 行)
1. 文件结构与运行方式(双击 index.html 即可,无依赖)
2. 设计 Token 表:主色/字号/关键尺寸 + 一句"取自原图取样"
3. 已还原项:3–5 条,说清还原到什么程度
4. 交互清单:点得动的全部列出来
5. 待确认 / 采用的假设:缺口、占位图、猜的文案
6. 改法提示:一处最可能被改的地方("标签字号在 styles.css 第 N 行")
9. 反模式(踩过的坑,直接抄结论)
- ❌ 边看边写:没看全就写第一版,后面全靠改。必须先出规格单。
- ❌ 反复解析同一张图:视口/缩放来回纠结。用第 3 节基准值反推,一次定死。
- ❌ 给用户一堆选择题:"要 React 还是 Vue?要 Tailwind 吗?"——除非第 6 节命中,否则默认值 + 声明。
- ❌ 为 1–2px 反复截图:容差内不修。截图只用来发现"看得见的问题"。
- ❌ 引 CDN 图标库/字体:离线打开一片空白,改成本地内联 SVG。
- ❌ 编造原图里没有的内容:多余的菜单项、子菜单、字段。缺口给空态并在交付里说明。
- ❌ 只交代码不交截图:未验证 = 未完成。
- ❌ 把整段源码贴进回复:文件已落盘就只给结构和关键片段,用户要的是能跑的东西。
10. 提示词模板(可以告诉用户这样提问更快)
> 照着这张图还原成前端页面。
> 技术栈:<纯 HTML / React / Vue,不写默认纯 HTML>
> 交互:<只要静态展示 / 要能切换和提交>
> 目标宽度:<1920 / 1440 / 自适应>
> 备注:<例如"这是我们线上系统,logo 后面给";"文字以图为准别改">
三行都不给也能做(走第 5 节默认值),给了能少一轮确认。