
TL;DR :用 AI 分批次生成一个 15 页的 B 端系统原型,结果导航栏出现了 3 种风格、4 种分组结构。本文总结了一套"先定义一致性,再拆分任务"的方法论,包含五层防御体系,让 AI 辅助开发不再产生一致性漂移。
前几个月,我尝试用 AI 辅助编程(俗称 Vibe Coding)快速构建一个 B 端管理系统的原型。需求很明确:一个包含仪表盘、配置管理、数据字典、业务规则等模块的完整前端原型,总共 15 个页面。
Vibe Coding 的爽点:
但痛点在哪?
当我分三批让 AI 生成完所有页面后,打开浏览器逐一检查时,眼前的场景让我意识到问题大了:

更严重的是:
用户看到原型后,严厉批评道:"这看起来像是 15 个完全不同的系统拼凑在一起,而不是一个完整的产品。"
经过复盘,我意识到这不是 AI 的锅,也不是开发者懒惰,而是一个更深层的问题:分治开发天然产生一致性漂移(Consistency Drift)。
当你把一个大任务拆分成多个子任务(无论是给 AI 还是给人类团队),每个子任务独立执行时,对"共享元素应该怎么实现"的理解会逐渐偏离。这不是错误,而是熵增——系统天然趋向于混乱。
漂移类型 | 表现 | 根因 |
|---|---|---|
视觉漂移 | 图标风格不一致、间距微小差异 | 无共享 Design Token |
结构漂移 | 导航分组不同、组件层级不同 | 无共享 Layout 定义 |
语义漂移 | 同一概念叫不同名字("参数配置" vs "系统参数配置") | 无共享命名规范 |
链接漂移 | 页面间无法跳转、面包屑无指向 | 无共享路由映射 |
一致性问题的本质是单源真相(Single Source of Truth, SSOT)缺失。
当同一份信息(比如"导航栏应该有哪些项目")被多个独立任务各自复制实现时,不一致是必然结果。就像"打电话传话"游戏——信息每传递一次,就会失真一点。
受微前端设计系统、Atlassian 的 SSOT 方法论、以及模板引擎实践的启发,我总结出一套五层防御体系。核心是:一致性不能靠人的纪律,必须靠架构约束和自动化校验。

关键原则:从下往上,每一层都在减少"需要人工保持一致"的地方。到了第 4 层,一致性已经由架构保障;第 5 层是最后的闸门。
做什么:在拆分任务之前,写一份 CONSISTENCY-RULES.md,作为后续所有自动化校验的判决依据。
## 命名规范
- 导航项:仪表盘 / 系统配置 / 数据管理 / 业务规则 / ...
- 分组:概览 / 基础管理 / 高级管理 / 系统监控
## 路由映射表
| 导航项 | 文件名 |
|-----------------|------------------------|
| 仪表盘 | 01-dashboard.html |
| 系统配置 | 02-config.html |
| ... | ... |
## 图标规范
- 统一使用 SVG inline 图标(见 icons/ 目录)
- 禁止使用 emoji 作为图标
## 链接规范
- 所有 nav-item 必须是 <a href="xx.html">
- 面包屑首级 → 01-dashboard.html
- 列表页「查看详情」→ 详情页?id=xxx为什么不能跳过:这不是文档装饰,而是后续所有自动化校验的判决依据。没有约定,就无法判定什么是对的。
做什么:提取所有视觉常量为 CSS 变量或 JSON Token。
/* tokens.css - 单源真相 */
:root {
--color-primary: #1565c0;
--color-primary-dark: #0d47a1;
--nav-width: 200px;
--nav-bg: var(--color-primary-dark);
--nav-item-height: 40px;
--nav-active-border: 3px solid #ff9800;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
}关键:Token 文件是单源的——所有页面 @import 同一个文件,不许各自重写。一旦修改 Token,所有页面同步生效。
做什么:把反复出现的 UI 结构抽为独立组件文件。
components/
├── sidebar.html ← 整个侧边栏
├── topbar.html ← 顶栏+面包屑
├── filter-bar.html ← 通用筛选栏
└── pagination.html ← 分页器为什么:在之前的 15 页原型中,侧边栏分别是 15 份独立实现——任何修改要改 15 遍。抽成 1 份后,修改只需 1 处。
做什么:用模板引擎或构建脚本,将共享组件在构建时注入每个页面,而非手动复制粘贴。
方案 | 适用场景 | 实现复杂度 | 一致性保障 | 真实浏览 |
|---|---|---|---|---|
客户端 Fetch 注入 | 纯静态原型(无 Node) | ⭐ 最低 | ⚠️ 弱(需本地服务器) | ✅ 直接打开 HTML |
构建时模板继承 | 中大型原型(Eleventy/Nunjucks) | ⭐⭐ 中等 | ✅ 强(build 即一致) | ⚠️ 需 build 步骤 |
SPA 组件路由 | React/Vue 前端项目 | ⭐⭐⭐ 高 | ✅ 最强 | ❌ 不适合原型 |
build/
├── templates/
│ └── layout.html ← 含 sidebar + topbar 的完整壳
├── pages/
│ ├── 01-dashboard.njk ← 只写内容区
│ └── 02-config.njk
└── build.js ← nunjucks 渲染 → 输出 static HTMLlayout.html 定义完整骨架:
<div class="layout">
<div class="sidebar">
{% include "sidebar.html" %}
</div>
<div class="main">
<div class="topbar">{% include "topbar.html" %}</div>
<div class="content">
{% block content %}{% endblock %}
</div>
</div>
</div>每个页面只写 {% block content %} 内的内容,导航自动一致。
优点:输出纯 HTML,可直接浏览器打开,一致性有架构保障
缺点:需要一次 node build.js 步骤
如果团队不想引入构建步骤,可以用客户端 Fetch:
<!-- 每个页面只需: -->
<body>
<div id="app-layout"></div>
<script>
fetch('components/sidebar.html')
.then(r => r.text())
.then(html => {
document.getElementById('app-layout').innerHTML = html;
// 根据当前文件名标记 active
const page = location.pathname.split('/').pop();
document.querySelector(`[data-page="${page}"]`)?.classList.add('active');
});
</script>
</body>优点:零构建步骤,改一处全局生效
缺点:不能直接 file:// 打开,需 Live Server
做什么:写一个校验脚本,在交付前自动检查一致性规则。
# check-consistency.py
import os
import re
from bs4 import BeautifulSoup
rules = {
"nav_items_count": 14, # 必须正好14个导航项
"nav_item_names": [...], # 名称精确匹配
"svg_icons_only": True, # 禁止emoji图标
"all_nav_have_href": True, # 所有nav-item必须有href
"active_count": 1, # 每页恰好1个active
}
def check_html_file(file_path, rules):
with open(file_path, 'r', encoding='utf-8') as f:
soup = BeautifulSoup(f.read(), 'html.parser')
errors = []
# 检查导航项数量
nav_items = soup.select('.nav-item')
if len(nav_items) != rules['nav_items_count']:
errors.append(f"导航项数量错误: {len(nav_items)} != {rules['nav_items_count']}")
# 检查是否使用 emoji 图标
if rules['svg_icons_only']:
for item in nav_items:
if re.search(r'[\U0001F600-\U0001F64F]', item.text):
errors.append("发现 emoji 图标,应使用 SVG")
# 检查 active 标记数量
active_items = soup.select('.nav-item.active')
if len(active_items) != rules['active_count']:
errors.append(f"active 标记数量错误: {len(active_items)} != {rules['active_count']}")
return errors
# 遍历所有 HTML 文件
html_files = [f for f in os.listdir('.') if f.endswith('.html')]
all_errors = {}
for file in html_files:
errors = check_html_file(file, rules)
if errors:
all_errors[file] = errors
# 输出结果
if all_errors:
print("❌ 一致性检查失败!")
for file, errors in all_errors.items():
print(f"\n{file}:")
for error in errors:
print(f" - {error}")
exit(1)
else:
print("✅ 一致性检查通过!")
exit(0)关键:这个脚本不是锦上添花,而是交付前的必过闸门。一致性违规 = 不允许交付。

关键洞察:Step 0-3 是前置投资,不能跳过。跳过的后果就是 15 页原型各自漂移、事后修 15 遍。
当我接手那个" 15 个页面像不同系统"的原型时,问题清单如下:
□ 导航项名称:7 种变体("参数配置" / "系统参数" / "参数设置" / ...)
□ 导航分组:4 种不同逻辑
□ 图标:混合使用 SVG + Emoji + 纯文本
□ 链接:60% 的导航项没有有效 href
□ 面包屑:每页自己实现,互不兼容
□ 侧边栏:15 份独立实现,修改要改 15 遍Day 1:制定规范
CONSISTENCY-RULES.md(包含 14 个导航项的精确名称、4 个分组的定义、路由映射表)tokens.css(从 15 个页面中归纳出共同的视觉常量)Day 2:抽离组件
components/sidebar.html(统一定义侧边栏结构)components/topbar.html(统一顶栏和面包屑)Day 3:引入构建脚本
.html 改为 .njk,只保留内容区)build.js 生成最终 HTMLDay 4:编写校验脚本
check-consistency.pypretest 钩子结果:
□ CONSISTENCY-RULES.md 已写?
包含:命名表、路由映射、图标规范、链接规范
□ Design Token 单源?
所有页面是否 import 同一份 token 文件?
□ 共享组件已抽离?
侧边栏/顶栏/分页器等是否只有一份源码?
□ 注入机制已选定?
Fetch / Nunjucks / React Router?
□ 一致性校验脚本已写?
交付前自动跑?
□ 路由映射表完整?
每个页面都有所有其他页面的链接?如果以上任何一项为 No,就不应该开始拆分任务。
一致性不是靠审美的纪律,而是靠架构的约束。undefined先定义单源真相,再拆分任务;让不一致成为不可能,而非靠人来避免。
Vibe Coding(AI 辅助编程)的最大陷阱是:以为快 = 好。
实际上,AI 生成代码的速度越快,一致性漂移的风险越高。因为:
正确的 Vibe Coding 姿势:
这样,你才能真正享受 Vibe Coding 的爽点,而不用事后花 3 倍时间修一致性。
作者注:本文总结的方法论已从具体项目中抽象出来,适用于任何需要分治开发的场景——无论是 AI 辅助编程,还是多人协作开发。核心思想只有一个:让架构保证一致性,而非依赖人的纪律。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。