
AI 辅助 UI 生成与设计系统自动化实践别让演示效果骗了你演示里给大语言模型一句描述很快就能得到一个能看的 React 卡片。但能渲染不等于能维护。生成代码常见的问题是层级过深、内联样式过多以及绕开现有 Token。先把“能生成”拆成可检查的条件把生成代码接入项目之前先在独立预览页检查 DOM 数量、最大嵌套深度、内联样式和 Token 使用情况。下面的脚本可作为本地诊断起点阈值应按组件类型和项目基线设定。# 诊断命令使用 puppeteer 抓取生成页面的 DOM 节点数与层级深度 node --eval const puppeteer require(puppeteer); (async () { const browser await puppeteer.launch(); const page await browser.newPage(); await page.goto(http://localhost:3000/generated-ui-preview); const metrics await page.evaluate(() { const all document.querySelectorAll(*); let maxDepth 0; all.forEach(el { let depth 0, p el; while (p.parentElement) { depth; p p.parentElement; } if (depth maxDepth) maxDepth depth; }); return { totalNodes: all.length, maxDepth }; }); console.log(DOM Total Nodes:, metrics.totalNodes); console.log(Max Hierarchy Depth:, metrics.maxDepth); await browser.close(); })(); 输出只用于定位结构问题。若一个本应简单的组件出现大量包裹节点就回到组件边界和布局规则而不是继续叠 Prompt。让模型遵守已有组件和 Token模型不会天然知道项目的组件边界也不会主动遵守 Token 命名。它生成style{{ padding: 13px, color: #3a86ff }}这类代码时等于绕过了既有的样式约束。提示词可以提供方向提交前仍要用规则校验。用 AST 校验把关下图展示了我们在 CI/CD 流水线中加入的确定性 UI 治理架构。模型生成原始代码后绝不直接写入代码库或渲染到客户端而是强制经过 AST 校验引擎与 Token 匹配器。flowchart TD UserPrompt[自然语言 Prompt / 视觉稿输入] -- LLMEngine[LLM 代码生成引擎] LLMEngine -- RawCode[原始生成代码 (React/JSX)] RawCode -- ASTParser[AST 语法树解析器 (Babel Parser)] ASTParser -- CheckDepth{DOM 深度 6层?} CheckDepth -- 否 -- RejectRule[拒绝并触发退回重试 / 降级模板] CheckDepth -- 是 -- CheckToken{符合 Design Token 规范?} CheckToken -- 否 -- TokenFixer[Token 强行映射与硬编码替换器] CheckToken -- 否 -- FixFail{自动修剪失败?} FixFail -- 是 -- RejectRule TokenFixer -- StandardCode[标准合规组件代码] CheckToken -- 是 -- StandardCode StandardCode -- Bundler[Vite / Webpack 编译产物] RejectRule -- SafeFallback[预设安全设计组件 (Design Fallback)]一个可落地的 TypeScript 检查器为了把上述逻辑落实到工程中我们基于babel/parser和babel/traverse写了一个 Node.js 检查工具。它可以在构建期拦截 DOM 过深、硬编码颜色值以及无意义外层包裹。import * as parser from babel/parser; import traverse from babel/traverse; import * as t from babel/types; interface ASTValidationResult { valid: boolean; maxDepth: number; hardcodedColors: string[]; errors: string[]; } const APPROVED_TOKENS new Set([ var(--primary-color), var(--neutral-100), var(--spacing-md), ]); export function validateGeneratedUI(code: string): ASTValidationResult { const result: ASTValidationResult { valid: true, maxDepth: 0, hardcodedColors: [], errors: [], }; try { const ast parser.parse(code, { sourceType: module, plugins: [jsx, typescript], }); let currentDepth 0; traverse(ast, { JSXElement: { enter(path) { currentDepth; if (currentDepth result.maxDepth) { result.maxDepth currentDepth; } if (currentDepth 8) { result.errors.push(DOM 深度超过限制: 达到 ${currentDepth} 层); } }, exit() { currentDepth--; }, }, JSXAttribute(path) { // 专门审计 style 内联属性中的硬编码 Hex 颜色 if (path.node.name.name style) { const attrVal path.node.value; if (t.isJSXExpressionContainer(attrVal) t.isObjectExpression(attrVal.expression)) { attrVal.expression.properties.forEach((prop) { if (t.isObjectProperty(prop) t.isStringLiteral(prop.value)) { const val prop.value.value; if (/^#([0-9a-fA-F]{3}){1,2}$/.test(val)) { result.hardcodedColors.push(val); result.errors.push(不合规硬编码颜色: ${val}); } } }); } } }, }); if (result.errors.length 0) { result.valid false; } } catch (err: any) { result.valid false; result.errors.push(AST 解析报错: ${err.message}); } return result; }这段代码把生成内容当作外部输入处理。解析失败、结构超过约束或出现未允许的样式值时阻止它进入主分支并回退到人工确认过的模板。上线前检查什么把生成结果放入灰度或预览环境持续观察以下项目并与项目原有基线比较项目目的首帧与交互性能防止额外节点和样式计算拖慢页面DOM 数量与嵌套避免无意义的包裹层进入组件库Token 命中情况保证主题切换和设计更新仍然有效降级路径校验失败时始终有稳定的默认组件可用AI UI 生成适合产出草稿工程规则负责决定草稿能否合入。先限定输入和组件范围再用 AST 与 Token 校验收口维护成本会低很多。