第 8 篇:与 AI 协作的工作流 + 完整案例
本篇目标
把前面七篇串成一条可复用的工作流:你提需求 → AI 只返回 Schema → 贴进项目出页面 。
并给出两个完整案例和常见坑排查。
1. 工作流总览
1. 你说需求(要什么字段、什么类型)
↓
2. AI 只返回一份 Schema JSON(字段名/类型/校验/选项)
↓
3. 你把 Schema 存到 pages/xxx.schema.json
↓
4. 页面壳(第 4 篇)+ SchemaForm(第 6 篇)自动渲染
↓
5. 样式、布局永远不变,变的只是字段
2. 提示词模板(核心资产)
把下面这段存成一个固定文件(比如 AI_SCHEMA_PROMPT.md),每次复制使用。
关键:约束 AI 只输出 JSON、只允许 8 种类型,从根上杜绝它乱写。
text
# 角色
你是我的表单配置助手。我有一个配置驱动的 Vue3 表单系统:
页面 UI 由固定渲染器(SchemaForm)生成,你只需要输出字段配置,不输出任何代码或解释。
# 硬性规则(违反任一则重来)
1. 只输出一个 JSON,不要 markdown 代码块标记,不要任何额外文字。
2. 字段 type 只能是这 8 个之一:
input / textarea / number / select / radio / checkbox / switch / date
3. select / radio 的选项用 options: [{"label":"中文名","value":"英文值"}, ...]
4. 必填加 "required": true;正则校验加 "pattern"(字符串形式,注意转义 \)。
5. name 用英文小驼峰,label 用中文;没有的属性一律省略。
6. 输出格式:
{
"title": "页面标题",
"columns": 2,
"fields": [
{ "name": "xxx", "label": "中文名", "type": "input", "required": true }
]
}
# 本次需求
<在这里粘贴你的需求>
3. 完整案例 1:客户资料页
需求:做一个客户资料录入,有姓名、性别、出生日期、手机号、部门、是否启用、备注。
把需求贴进提示词模板,AI 应返回(与第 5 篇一致,已验证能渲染):
json
{
"title": "客户资料",
"columns": 2,
"fields": [
{ "name": "name", "label": "姓名", "type": "input", "required": true, "placeholder": "请输入姓名" },
{ "name": "gender", "label": "性别", "type": "radio", "options": [ { "label": "男", "value": "male" }, { "label": "女", "value": "female" } ] },
{ "name": "birth", "label": "出生日期", "type": "date" },
{ "name": "phone", "label": "手机号", "type": "input", "pattern": "^1\\d{10}$", "placeholder": "11 位手机号" },
{ "name": "dept", "label": "部门", "type": "select", "options": [ { "label": "研发", "value": "rd" }, { "label": "产品", "value": "pm" } ] },
{ "name": "active", "label": "启用", "type": "switch", "default": true },
{ "name": "remark", "label": "备注", "type": "textarea", "span": 2 }
]
}
落地 :存为 src/pages/customer.schema.json,页面代码复用第 6 篇的 CustomerPage.vue
(把 schema 从内联改为 import JSON 即可,改动最小)。
ts
import customerSchema from './customer.schema.json'
// 注意:Vite 默认支持 JSON import;要类型就加 resolveJsonModule 或手动 as PageSchema
4. 完整案例 2:设备台账页
需求:设备台账,有编号、型号、安装位置、状态(在用/闲置/报废)、标签(多选)、采购日期、备注。
AI 应返回:
json
{
"title": "设备台账",
"columns": 2,
"fields": [
{ "name": "code", "label": "设备编号", "type": "input", "required": true, "placeholder": "如 DEV-0001" },
{ "name": "model", "label": "型号", "type": "input", "placeholder": "如 R-Pipe-X3" },
{ "name": "location","label": "安装位置", "type": "input", "placeholder": "如 3 号管线 12km 处" },
{ "name": "status", "label": "状态", "type": "select", "default": "active",
"options": [ { "label": "在用", "value": "active" }, { "label": "闲置", "value": "idle" }, { "label": "报废", "value": "scrapped" } ] },
{ "name": "tags", "label": "标签", "type": "checkbox", "help": "多选标记" },
{ "name": "purchase","label": "采购日期", "type": "date" },
{ "name": "remark", "label": "备注", "type": "textarea", "span": 2 }
]
}
再配一个第 7 篇的 DataList 展示台账列表,页面即完整。
两个案例对比可见:壳和代码完全一样,只有 schema 不同------这就是整个系列要的效果。
5. 常见坑与排查
| 现象 | 原因 | 处理 |
|---|---|---|
| AI 返回了代码块标记(```json) | 提示词没约束住 | 让它只输出 JSON,或你手动去标记;本系列页面读的是纯 JSON |
AI 用了第 9 种 type(如 time、upload) |
枚举没约束住 | 提示词里加粗「只允许 8 个」,或按下方「加字段类型」流程扩展 |
| select 选项没显示 | options 缺 value 或结构不对 | 检查为 { "label": "...", "value": "..." } |
| date 显示英文/格式乱 | 原生 date 的显示由浏览器决定 | 接受默认,或用 Calendar 自封装(第 7 篇提到) |
| schema 改了页面没变 | 浏览器缓存 / 未保存 | 刷新;确认 import 的是同一个文件 |
| 渲染器没识别某字段 | 字段类型不在映射表 | 对照第 6 篇字段分支检查拼写 |
6. 扩展:加一个新字段类型(如 file 上传)
流程固定四步,可复现:
schema.ts的FieldType加'file'。- 装好对应组件(
pnpm dlx shadcn-vue@latest add <组件名>)。 SchemaForm.vue加一个v-else-if="field.type === 'file'"分支。- 更新提示词模板的「8 个类型」为 9 个,并在第 5 篇的类型表里登记。
提醒:加类型 = 改渲染器,属于「固定层」变更,要做就要回归测试一遍全部既有页面。
所以宁可少而稳,不要频繁加。
7. 维护演进(长期视角)
- 加页面:只用加一份 schema(最日常的操作,不碰代码)。
- 改样式:改 Tokens 或布局组件,全局生效,无需逐页改。
- 加能力:走第 6 节四步流程,改一处渲染器 + 更新文档与提示词。
- 兜底 :个别页面确实需要特殊交互(超出 8 种类型),单独手写一个页面组件,
不强行塞进 schema 体系------诚实承认边界,避免把渲染器改成怪物。
8. 系列收官:你最终得到的东西
my-ui-kit/
├─ schema-form/ # 写一次:SchemaForm.vue + schema.ts
├─ layouts/ # 写一次:PageShell / PageHeader / SectionCard / FormGrid
├─ components/ui/ # 写一次:shadcn-vue 组件源码
├─ styles/tokens.css # 写一次:设计变量
└─ pages/ # 每次只加:xxx.schema.json + 一行壳页面
从此「让 AI 做个页面」=「让 AI 列字段」+「贴一行 JSON」。
样式、布局、组件全都由你写死的固定层兜底,AI 不再有机会弄坏它们。