AI生成UI代码混乱?用DESIGN.md建立视觉契约
1. 为什么 AI 写 UI 代码会越写越乱——不是模型不行是缺了“视觉契约”你有没有过这种体验在 Cursor 或 Codex 里输入一句“帮我写个登录页现代简约风带邮箱输入框和密码输入框”回车之后AI 真的给你吐出了一堆 HTML Tailwind 代码——但打开浏览器一看按钮悬浮在左上角、输入框宽度忽宽忽窄、字体大小跳变三次、阴影层级全乱套连对齐都靠肉眼估摸更糟的是你改完第一版让它“把按钮改成蓝色”它可能重写整个表单结构把原本好好的响应式断点删了还顺手把 label 的for属性改成了随机字符串。这不是模型退化也不是你提示词写得不够狠。这是视觉层缺乏可执行的约束协议。我过去半年深度用 Codex 做内部中后台系统重构累计让 AI 生成了 127 个独立 UI 模块含表格、弹窗、筛选器、图表容器等踩过所有你能想到的坑。最开始我也迷信“多加形容词”“请用 Ant Design 风格深色模式兼容移动端优先间距严格遵循 8px 基准字体使用 Inter按钮圆角 6px禁用内联样式”。结果呢AI 确实照做了——但它把“Ant Design 风格”理解成“用了ant-btn类名”把“8px 基准”理解成“所有margin都写0.5rem”却完全无视组件间垂直节奏的一致性它甚至会把一个div的padding设为12px非 8 的倍数只因它觉得“这里看起来更舒服”。问题根源在于当前所有主流 AI 编程助手Codex / Cursor / GitHub Copilot的 UI 生成能力本质上是“文本补全”而非“设计执行”。它们没有视觉语义理解能力无法识别“这个卡片容器的 padding 应该与内部标题行高形成节奏关系”也无法判断“这个按钮组的水平间距是否与页面栅格列宽匹配”。而 DESIGN.md 就是给 AI 下达的第一份可解析、可验证、可继承的视觉契约。它不是设计规范文档Design System Documentation而是专为 AI 编程环境定制的机器可读 UI 约束说明书。它的核心价值不是告诉设计师“应该怎么做”而是告诉 AI 模型“当你要生成任何 UI 组件时必须从以下 7 个维度校验输出否则视为无效”。提示DESIGN.md 不是放在项目根目录就自动生效的魔法文件。它必须被显式引用进你的提示词中例如“请严格依据项目根目录下的 DESIGN.md 规范生成 React 组件禁止引入未声明的 CSS 类、禁止使用内联 style、所有尺寸单位必须为 rem且数值必须是 0.125 的整数倍”。我见过太多团队把 DESIGN.md 当成“锦上添花的文档”结果 AI 依然自由发挥。真正起效的前提是你把这份文件当成与 AI 协作的宪法级输入——每次生成前你都要把它作为上下文喂给模型。这就像给厨师一份精确到克的食谱而不是说“做一道好吃的川菜”。这套模板我们已在三个真实项目中落地一个金融风控后台日均 AI 生成 UI 代码量 320 行、一个 SaaS 客户管理平台UI 模块复用率提升 64%、一个教育类小程序设计还原度从 73% 提升至 98%。它不依赖任何特定框架React/Vue/Svelte 全适配也不要求你更换现有设计系统Ant Design / Element Plus / 自研 UI 库均可无缝对接。它解决的是 AI 在 UI 层最根本的“失控感”——那种你明明写了提示词却像在放养一只没 leash 的狗的感觉。2. DESIGN.md 的七维校验体系不是教 AI 做设计是给它划不可逾越的线DESIGN.md 的威力不在于它写了多少设计原则而在于它用可量化、可枚举、可程序化校验的方式把模糊的“视觉一致性”拆解成 AI 能理解的原子指令。我们不谈“优雅”“和谐”“呼吸感”这类人话只定义七条硬性规则每一条都对应一个具体检查点。下面逐条拆解其设计逻辑、技术实现方式以及我在实战中发现的致命陷阱。2.1 尺寸系统为什么必须用 rem 而非 px且数值必须是 0.125 的整数倍很多人第一反应是“用 rem 多麻烦直接写 px 不香吗”——这恰恰是混乱的起点。px 是绝对单位当用户缩放页面或切换设备像素比DPR时px 值不会变化导致视觉比例失真。而 rem 是相对于根元素字体大小的相对单位配合html { font-size: 62.5%; }即 1rem 10px既能保证设计稿像素值直译如设计稿 16px 字体 → 1.6rem又天然支持缩放与响应式。但仅用 rem 还不够。我们强制规定所有尺寸值padding/margin/width/height/font-size 等必须是 0.125 的整数倍即 1/8rem 1.25px。原因有三节奏控制0.125 是 8px 基准系统的最小增量单位8px ÷ 64 0.125rem。强制使用它等于锁死了所有间距、尺寸的节奏网格。比如padding: 1.25rem10px、margin: 2.5rem20px、font-size: 1.6rem16px全部落在同一节奏线上。防误操作AI 极易生成margin: 13px这类“看起来差不多”的值。而 13px ÷ 10 1.3rem1.3 不是 0.125 的整数倍1.3 ÷ 0.125 10.4直接触发校验失败。CSS 可维护性所有尺寸值可被预编译为 CSS 自定义属性如--space-xs: 0.125rem; --space-sm: 0.25rem; --space-md: 0.5rem;AI 生成代码时只能引用这些变量杜绝硬编码。注意不要在 DESIGN.md 中写“请使用 CSS 变量”。AI 不会主动查变量表。正确写法是“所有间距必须从以下列表中选择0.125rem,0.25rem,0.375rem,0.5rem,0.625rem,0.75rem,0.875rem,1rem,1.125rem,1.25rem,1.375rem,1.5rem,1.625rem,1.75rem,1.875rem,2rem。禁止使用其他数值。”我在金融后台项目中曾允许0.1rem1px作为例外结果 AI 在生成边框border时疯狂使用1px solid #eee导致高 DPR 设备下线条发虚。后来彻底禁用所有非 0.125 倍数问题消失。2.2 色彩系统不是给色值而是给“色彩角色”和“使用上下文”DESIGN.md 从不直接写#1890ff。它定义的是色彩角色Color Role和使用约束Usage Constraint。例如- **Primary**: 主要操作色仅用于按钮、链接、重要状态标识。 - 默认值hsl(208, 92%, 53%)对应 #1890ff - 禁止用于背景、文字、边框除非明确标注“Primary Background” - 在深色模式下自动映射为 hsl(208, 92%, 40%) - **Surface**: 容器背景色仅用于 Card、Modal、Sidebar 等区块背景。 - 默认值hsl(0, 0%, 100%)纯白 - 在深色模式下自动映射为 hsl(0, 0%, 12%) - 禁止用于文字、边框、图标填充为什么这么做因为 AI 对“#1890ff 是按钮色”没有概念但它能理解“Primary 是按钮色Surface 是容器背景色”。更重要的是“使用上下文”约束了 AI 的泛化冲动——它不会再把 Primary 色用在表格奇数行背景上因为规则明确写了“仅用于按钮、链接、重要状态标识”。我们还加入了色彩对比度自动校验条款“所有文字颜色与其背景色的对比度必须 ≥ 4.5:1小字号或 ≥ 3:1大字号使用 WCAG 2.1 AA 标准计算。若生成代码中出现color: var(--text-primary)与background-color: var(--surface-primary)组合必须通过 WebAIM Contrast Checker 验证。” 这条规则让 AI 在生成深色模式适配代码时不再随意降低文字透明度来“凑数”。2.3 排版层级用“标题等级”替代“字体大小”让 AI 理解信息权重DESIGN.md 不写h1 { font-size: 2.5rem; }而是定义- **Heading 1 (H1)**: 页面主标题代表最高信息权重每个页面仅允许 1 个。 - 视觉表现font-size: 2.5rem; font-weight: 700; line-height: 1.2; - 禁止用于导航菜单、侧边栏标题、卡片标题 - **Heading 2 (H2)**: 区块标题用于划分页面主要功能区如“用户列表”、“操作日志”。 - 视觉表现font-size: 1.75rem; font-weight: 600; line-height: 1.3; - 禁止用于表格列头、按钮文字、标签页文字关键在于“每个页面仅允许 1 个 H1”和“禁止用于...”这类强约束。AI 生成代码时如果看到你提示“写一个用户管理页面”它会本能地生成h1用户管理/h1但如果提示是“写一个用户列表表格”它就必须用h2用户列表/h2因为 H1 已被主页面占用。这种基于语义层级的约束比单纯限制字体大小更能防止视觉噪音。我们在教育小程序中发现AI 常把课程卡片里的“课程名称”设为h3导致整个页面 H3 数量爆炸。加入“卡片标题必须使用div classcard-title禁用所有 heading 标签”后问题根除。2.4 组件边界明确定义“什么算一个组件”切断嵌套污染链这是最常被忽视却最致命的一条。DESIGN.md 必须清晰界定组件的物理边界和职责边界。例如- **Button 组件**: - 物理边界单个 button 元素或包裹 button 的 span仅用于图标文字组合 - 职责边界仅处理点击行为、加载状态、禁用态。禁止包含 • 表单提交逻辑应由 Form 组件处理 • 图标渲染逻辑图标必须作为独立子组件传入 • 文字换行控制文字内容必须为单行超长用 text-ellipsis - **Form 组件**: - 物理边界form 元素及其直接子元素input, select, button typesubmit - 职责边界处理表单提交、校验状态、错误提示。禁止包含 • 输入框的 label 渲染label 必须由调用方提供 • 按钮组布局按钮组必须作为 slot 传入为什么重要因为 AI 的“组件意识”极弱。它看到“登录表单”可能直接生成一个div classlogin-form里面塞满 input、label、button再加一堆 div 做布局。这种“大杂烩组件”无法复用无法测试更无法被 AI 后续精准修改你让它“把登录按钮改成绿色”它可能重写整个 div 结构。通过明确定义边界我们强制 AI 输出“乐高式组件”每个组件职责单一、接口清晰、物理隔离。你在提示词里说“用 Button 组件”AI 就只输出button相关代码说“用 Form 组件”它就只输出form及其子元素。组件间的耦合被降到最低。2.5 响应式断点不是写媒体查询是定义“视口状态机”DESIGN.md 不写media (max-width: 768px) { ... }而是定义一套视口状态机Viewport State Machine- **State: Mobile** - 触发条件视口宽度 ≤ 480px - 行为约束 • 所有栅格列宽必须为 col-12100% 宽度 • 导航菜单必须折叠为汉堡菜单 • 表格必须转换为卡片式垂直布局tr → div classcard - **State: Tablet** - 触发条件481px ≤ 视口宽度 ≤ 1024px - 行为约束 • 栅格系统启用 col-6 / col-4 • 导航菜单可展开但最多显示 5 项其余收进“更多”下拉 • 表格保持横向但列数 ≤ 4AI 对“媒体查询”语法的理解是碎片化的但它对“状态”和“行为”的理解是可靠的。当你在提示词里说“生成一个响应式用户列表”AI 会根据状态机规则在 Mobile 状态下输出卡片布局在 Tablet 状态下输出 4 列表格。我们甚至在状态机里加入了降级策略“当 AI 无法确定当前状态时默认采用 Mobile 状态”确保底线安全。2.6 动效规范用“动效类型”替代“CSS transition”让交互动词可执行DESIGN.md 禁止出现任何transition: all 0.3s ease这类万金油写法。它只定义三种动效类型- **Feedback Animation**: 用户交互即时反馈如按钮点击涟漪、输入框聚焦边框变色。 - 要求必须使用 transform 或 opacity禁止 width/height/left/top - 时长0.15s ~ 0.25s - 缓动cubic-bezier(0.4, 0, 0.2, 1)标准 Material Easing - **Navigation Animation**: 页面/模块切换如路由跳转、弹窗打开。 - 要求必须使用 transform: translateX() 或 opacity禁止 display: none - 时长0.3s ~ 0.4s - 缓动cubic-bezier(0.25, 0.46, 0.45, 0.94)标准 Navigation EasingAI 生成动效时如果提示词里说“按钮要有点击反馈”它就会输出符合 Feedback Animation 规范的代码如果说“弹窗要滑入”它就输出 Navigation Animation。我们甚至在规范里写了禁用清单“禁止使用transition: all、禁止使用keyframes定义复杂动画、禁止在非交互场景添加动效如页面加载时自动旋转图标”。这直接砍掉了 80% 的无意义动效垃圾。2.7 无障碍基础不是“建议”是“必须通过的准入检查”DESIGN.md 把无障碍a11y从“加分项”变成“准入门槛”。每条规则都带可验证的检查点- **所有交互元素必须有明确的角色role和名称name** • button 必须有 aria-label 或可见文字内容 • div rolebutton 必须有 tabindex0 和 aria-label • 图标按钮必须同时提供 aria-hiddentrue图标和 aria-label功能描述 - **所有表单控件必须关联 label** • input 必须有 id且对应 label forid • 禁止使用 placeholder 替代 label • 错误状态必须通过 aria-invalidtrue 和 aria-describedby 关联错误消息这条规则的效果立竿见影。以前 AI 生成的表单input常常没有idlabel用for指向一个不存在的 id或者干脆用placeholder当 label。现在只要它生成的代码不满足上述任一检查点我们就拒绝合并。团队成员甚至开玩笑说“DESIGN.md 是我们最严厉的 Code Reviewer”。3. 一份可直接复制粘贴的 DESIGN.md 模板去掉所有废话只留能跑通的代码下面这份 DESIGN.md 模板是我们经过 127 次 UI 生成迭代、3 次大版本重构后沉淀下来的最小可行版本MVP。它不追求大而全只确保每一条都能被 AI 理解、被开发者验证、被 CI/CD 流水线自动检查。你可以直接复制到项目根目录然后在 Cursor/Codex 的提示词里引用它。# DESIGN.md - UI 视觉契约v1.2 ## 1. 尺寸系统 - 所有尺寸单位必须为 rem - 所有尺寸数值必须是 0.125 的整数倍即 0.125rem, 0.25rem, 0.375rem, ..., 2rem - 禁止使用 px, em, %, vh, vw100vh 除外仅用于全屏容器 - 禁止使用 !important 覆盖尺寸 ## 2. 色彩系统 - 使用 HSL 颜色模型格式hsl(h, s%, l%) - 色彩角色及取值 - Primary: hsl(208, 92%, 53%) — 仅用于按钮、链接、状态标识 - Secondary: hsl(210, 12%, 65%) — 仅用于次要文字、边框、图标 - Surface: hsl(0, 0%, 100%) — 仅用于容器背景Card, Modal, Sidebar - Text Primary: hsl(0, 0%, 12%) — 仅用于主文字 - Text Secondary: hsl(0, 0%, 45%) — 仅用于辅助文字、占位符 - 深色模式映射 - Surface → hsl(0, 0%, 12%) - Text Primary → hsl(0, 0%, 92%) - Text Secondary → hsl(0, 0%, 65%) - 所有文字与背景对比度必须 ≥ 4.5:1小字号或 ≥ 3:1大字号 ## 3. 排版层级 - 标题必须使用语义化 HTML 标签 - 页面主标题h1每个页面仅 1 个 - 区块标题h2每个区块仅 1 个 - 卡片/列表项标题h3每个卡片/列表项仅 1 个 - 禁止使用 h4 及以下禁止用 div 模拟标题 - 字体家族Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, sans-serif - 行高line-height必须为 1.2H1/H2、1.4正文、1.5辅助文字 ## 4. 组件边界 - **Button 组件** - 必须为 button 元素或 span 包裹 button - 禁止包含表单逻辑、图标渲染、文字换行控制 - **Form 组件** - 必须为 form 元素直接子元素仅限 input, select, textarea, button typesubmit - 禁止包含 label 渲染、按钮组布局 - **Card 组件** - 必须为 article classcard 或 div classcard - 内部结构固定.card-header, .card-body, .card-footer可选 - 禁止在 .card-body 内嵌套其他 .card ## 5. 响应式断点 - **Mobile (≤480px)** - 所有栅格列宽col-12 - 导航菜单汉堡菜单 - 表格转换为卡片式垂直布局tr → div classcard - **Tablet (481px–1024px)** - 栅格列宽col-6, col-4, col-3 - 导航菜单最多显示 5 项其余收进“更多” - 表格最多 4 列 - **Desktop (1024px)** - 栅格列宽col-4, col-3, col-2 - 导航菜单完整展开 - 表格按设计稿列数显示 ## 6. 动效规范 - **Feedback Animation**按钮点击、输入聚焦 - 属性transform, opacity - 时长0.2s - 缓动cubic-bezier(0.4, 0, 0.2, 1) - **Navigation Animation**弹窗、路由切换 - 属性transform: translateX(), opacity - 时长0.35s - 缓动cubic-bezier(0.25, 0.46, 0.45, 0.94) - 禁止transition: all, keyframes, 非交互场景动效 ## 7. 无障碍基础 - 所有 button 必须有可见文字或 aria-label - 所有 input 必须有 id 和对应 label forid - 所有图标按钮图标 i 加 aria-hiddentrue容器加 aria-label - 所有错误状态input aria-invalidtrue div iderror-id input aria-describedbyerror-id - 禁止placeholder 替代 labeldisplay: none 隐藏重要内容注意这份模板的每一行都是我们用真实项目数据验证过的。比如col-12/col-6这些栅格类名是我们自研 CSS 框架的约定你换成grid-cols-12/grid-cols-6Tailwind或el-col-12/el-col-6Element Plus即可。关键是类名背后的行为约束而不是类名本身。我把这份模板放在 GitHub Gist 上团队新人入职第一天任务就是1把 DESIGN.md 复制进项目2用 Codex 生成一个符合全部七条规则的“用户资料卡片”组件3用 axe DevTools 扫描生成的 HTML确认无障碍通过率 100%。三个小时90% 的人能完成。这就是可落地的力量。4. 如何让 Codex / Cursor 真正“读懂” DESIGN.md提示词工程与工作流改造有了 DESIGN.md不等于万事大吉。很多团队把文件放进去AI 还是乱写——问题出在你怎么喂给 AI。Codex 和 Cursor 的上下文窗口有限Codex 约 8K tokensCursor Pro 约 12K而一份完整的 DESIGN.md含注释可能超过 2K tokens。如果直接把整个文件塞进提示词有效信息密度暴跌AI 更容易抓取到无关细节。我们必须做两件事提示词分层注入和工作流强制校验。4.1 提示词分层注入把 DESIGN.md 拆成“核心指令”和“扩展参考”我们绝不把 DESIGN.md 原文扔进提示词。而是提炼出三层指令L1 核心指令必填≤200 字“请严格依据项目 DESIGN.md 规范生成代码。重点遵守1所有尺寸用 rem且为 0.125 的整数倍2色彩仅使用 Primary/Secondary/Surface/Text Primary/Text Secondary 角色3标题必须用h1/h2/h3禁止h44按钮必须为button禁止嵌套表单逻辑5Mobile 断点下表格转卡片6动效仅用 transform/opacityFeedback 0.2sNavigation 0.35s7所有button有aria-label所有input有id和label。”L2 场景指令按需≤100 字“本次生成用户资料卡片组件。要求包含头像、姓名、职位、部门、联系方式。Mobile 下垂直堆叠Tablet 起分两列头像基本信息 / 联系方式。使用 Surface 背景Primary 用于‘编辑’按钮。”L3 扩展参考仅当需要时用代码块引用## 4. 组件边界 - **Card 组件** - 必须为 article classcard 或 div classcard - 内部结构固定.card-header, .card-body, .card-footer可选这样做的好处是L1 确保 AI 记住底线规则L2 锁定本次任务的具体形态L3 只在需要澄清边界时才提供片段避免信息过载。我在 Cursor 中测试过同样生成“用户列表”用分层提示词的代码合规率是 92%而直接粘贴完整 DESIGN.md 是 63%。4.2 工作流强制校验让机器代替人盯 DESIGN.md再完美的提示词也有漏网之鱼。我们必须建立自动化校验流水线让机器在代码合并前自动检查是否违反 DESIGN.md。我们用一个轻量级 Node.js 脚本design-checker.js实现// design-checker.js const fs require(fs); const glob require(glob); // 检查尺寸单位 function checkRemUnits(content) { const remRegex /(\d(\.\d)?)rem/g; let match; while ((match remRegex.exec(content)) ! null) { const value parseFloat(match[1]); if (Math.abs(value % 0.125) 0.001) { // 允许浮点误差 throw new Error(尺寸 ${value}rem 不是 0.125 的整数倍); } } } // 检查色彩角色 function checkColorRoles(content) { const hslRegex /hsl\((\d),\s*(\d)%,\s*(\d)%\)/g; let match; while ((match hslRegex.exec(content)) ! null) { const [_, h, s, l] match; // 检查是否在预设的 HSL 值范围内简化版实际用查表 if (!isAllowedHSL(h, s, l)) { throw new Error(HSL(${h}, ${s}%, ${l}%) 不在 DESIGN.md 允许的色彩角色中); } } } // 主函数 function runCheck() { const files glob.sync(src/**/*.{js,jsx,ts,tsx,html,vue}); for (const file of files) { const content fs.readFileSync(file, utf8); checkRemUnits(content); checkColorRoles(content); // ... 其他检查 } console.log(✅ DESIGN.md 校验通过); }这个脚本被集成进pre-commit钩子和 CI/CD 流程。每次git commit或 PR 提交它都会自动运行。一旦发现违规比如某个margin: 1.3rem立即报错并中断流程。团队成员很快养成习惯写完代码先本地跑一遍npm run design-check再提交。校验不是为了惩罚而是把 DESIGN.md 从纸面规范变成肌肉记忆。4.3 团队协作中的“DESIGN.md 时刻”每周一次的视觉对齐会技术工具只是骨架真正的灵魂在于人。我们坚持每周五下午 30 分钟开一个叫“DESIGN.md 时刻”的短会。流程极其简单一人分享本周用 AI 生成的 1 个 UI 组件展示原始提示词、AI 输出代码、浏览器效果截图。集体校验所有人对照 DESIGN.md 七条逐条打钩。哪条没做到为什么没做到是提示词没写清楚还是 AI 理解偏差更新模板如果发现规范有漏洞比如某次 AI 把col-12用在了不该用的地方当场讨论更新 DESIGN.md并同步到所有项目。这个会不开技术方案不谈架构只盯着“这一行代码是否符合契约”。三个月下来团队对 DESIGN.md 的熟悉度远超任何设计文档。新来的实习生第一次参会就能指出“这里用了px违反第 1 条”而不是问“px 是什么”。5. 超越 UIDESIGN.md 如何重塑你与 AI 的协作关系用 DESIGN.md 解决 AI 写 UI 乱的问题只是冰山一角。它真正改变的是我们与 AI 协作的底层范式——从“命令-执行”走向“契约-共治”。过去我们把 AI 当成一个超级实习生你给它详细指令“用 Ant Design蓝色按钮16px 字体左边距 20px”它努力去执行但总有偏差。你疲于纠正它困惑于“为什么上次可以这次不行”。这是一种消耗性的、单向的关系。而 DESIGN.md 把 AI 变成了一个持证上岗的合作伙伴。它不是在执行你的临时指令而是在履行一份双方签署的、可验证的契约。你提供契约DESIGN.md它提供符合契约的产出你负责契约的演进每周更新它负责契约的严格执行。关系变得清晰、稳定、可预期。这种转变带来三个质的提升第一提示词成本断崖式下降。以前写一个“用户列表”提示词要 200 字“请用 React 函数组件使用 Ant Design Table列包括姓名、邮箱、部门、状态状态列用 Tag绿色表示激活红色表示禁用表格有分页每页 10 条搜索框在顶部按钮用 Primary 色…”现在提示词只需 30 字“生成用户列表组件符合 DESIGN.md 规范Mobile 下垂直堆叠。” 因为所有细节——色彩、尺寸、响应式、无障碍——都在契约里写死了。AI 不需要你重复唠叨它只看契约。第二代码审查Code Review焦点转移。以前 CR 重点是“这个 margin 是不是写错了”“这个颜色是不是该用 Primary”“这个按钮有没有 aria-label”——全是 DESIGN.md 覆盖的基础项。现在 CR 重点变成“这个交互流程是否符合业务逻辑”“这个错误处理是否覆盖了所有边界情况”“这个性能优化是否必要”——回归到真正需要人类智慧的领域。工程师的时间终于从“校对机器”解放出来去思考“为什么”。第三设计系统Design System真正活起来。很多团队花大力气建设计系统但前端工程师嫌麻烦AI 更是直接无视。DESIGN.md 把设计系统的约束翻译成 AI 能吃的“数字饲料”。当 AI 每次生成代码都自动使用--space-md、--color-primary、--text-primary设计系统就不再是挂在 Confluence 上的 PDF而是流淌在每一行代码里的血液。我们甚至发现设计师开始主动参与 DESIGN.md 的修订——因为他们看到自己定的规则真的被机器一丝不苟地执行