Codex 很容易用一组写死的数组做出“看起来已经完成”的 UI,真正接接口时却会同时出现字段为空、加载闪烁、错误无处恢复和权限判断散落等问题。本教程把任务拆成七步:先确认接口契约,再建立状态矩阵和数据适配层,最后用 Playwright 模拟响应并回到真实后端验证。目标不是生成一个演示页,而是交付一个在真实数据下仍然可用、可测试、可维护的页面。

如果接口尚未确定、没有可访问的测试环境,先让后端提供 schema、示例响应和错误定义。Codex 可以帮助发现缺口,但不能替产品或后端决定字段语义。
把目标路由、现有组件、接口文档、一个脱敏的成功响应和常见错误响应交给 Codex。要求它只读检查调用链,并列出前端当前假设与后端事实的差异。Fetch 在 404 或 500 时通常不会自动 reject,因此还要明确哪些 HTTP 状态、业务码和网络异常分别如何处理。
先不要修改文件。阅读 AGENTS.md、目标页面、现有 API client、类型定义和测试。根据【接口文档链接或 schema】与脱敏响应,输出: 1. 页面当前依赖的字段;2. 字段类型、可空性和默认值; 3. HTTP 错误、业务错误与权限错误;4. 仍需产品或后端确认的问题。 不要发明字段,不要把 mock 数据当接口事实,不要输出任何凭证。
先按用户能看到和能恢复的状态设计,而不是只按请求是否完成写一个布尔值。至少覆盖 loading、empty、error、denied 和 success;列表还应考虑 partial、分页失败与旧数据刷新。每个状态都要定义触发条件、界面文案、可用操作和测试证据。
| 状态 | 触发条件 | 界面与操作 |
|---|---|---|
| loading | 首次请求未完成 | 保持结构稳定,骨架不伪造真实内容 |
| empty | 请求成功且数据为零 | 说明原因,给出创建或调整筛选入口 |
| error | 网络、HTTP 或业务错误 | 保留上下文,提供重试与可理解错误 |
| denied | 身份有效但无权限 | 说明权限边界和申请方式,不只禁用按钮 |
| success | 数据可展示 | 处理缺省字段、长文本、刷新与分页 |

不要让卡片、表格和图表各自解析原始响应。先保留后端类型,再写一个纯函数把它转换成页面需要的 ViewModel;日期、金额、空值、枚举和权限都在这里显式处理。这样既减少组件内的条件分支,也方便用小样本做单元测试。
type ApiProject = {
id: string;
title: string | null;
updated_at: string;
budget_cents: number | null;
permissions: { can_edit: boolean };
};
type ProjectCardVM = {
id: string;
title: string;
updatedLabel: string;
budgetLabel: string;
canEdit: boolean;
};
export function toProjectCardVM(item: ApiProject): ProjectCardVM {
return {
id: item.id,
title: item.title?.trim() || "未命名项目",
updatedLabel: formatDate(item.updated_at),
budgetLabel: item.budget_cents == null ? "未设置" : formatMoney(item.budget_cents),
canEdit: item.permissions.can_edit,
};
}
加载状态要尽量保持最终布局尺寸,避免内容出现时整体跳动;空状态不能复用错误图标;错误状态需要保留重试入口和必要的筛选上下文;成功状态也要验证缺省字段与长文本。权限状态则应区分“只读”和“完全不可见”,并由后端继续执行真正的权限校验。
请按已确认的状态矩阵实现目标页面。复用现有 EmptyState、ErrorState、Skeleton、Button 与 tokens;不要新增第二套基础组件。 - 首次加载:保留页面标题和筛选结构; - 空数据:显示与当前筛选匹配的说明和下一步; - 请求错误:显示可重试操作,不泄露服务端堆栈; - 只读权限:内容可见、编辑入口替换为权限说明; - 成功:处理 null、长标题、零值、分页和刷新。 完成后列出每个状态的触发方法和涉及文件。

OpenAI 的前端与 Figma 转代码用例都强调先让 Codex 理解项目、复用已有设计系统,并通过实际检查迭代。一个可执行任务应包含接口与页面输入、不能动的边界,以及完成后必须提供的证据。
任务:把 /projects 的 mock 数据接入现有 GET /api/projects。 输入:接口 schema、成功/空/401/403/500 脱敏响应、目标路由、现有组件路径。 边界:不改接口字段;不新增 UI 框架;不输出凭证;不做无关重构;权限不能只靠前端隐藏。 交付:adapter 与类型;五种页面状态;单元测试;Playwright 网络模拟;lint、typecheck、test、build 结果;仍未确认的问题。 先给最小修改计划,确认现有模式后再改文件。
Playwright 官方的网络能力可以拦截并模拟响应。对每个状态建立独立测试,避免测试环境恰好有数据时永远覆盖不到 empty,也避免用真实 500 才能测试错误页。路由匹配要足够精确,并在真实后端验证前关闭 mock。
import { test, expect } from "@playwright/test";
test("projects empty state", async ({ page }) => {
await page.route("**/api/projects?*", async route => {
await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ items: [] }) });
});
await page.goto("/projects");
await expect(page.getByRole("heading", { name: "还没有项目" })).toBeVisible();
await expect(page.getByRole("button", { name: "创建项目" })).toBeEnabled();
});

模拟测试通过不等于接口已经接通。最后用测试账号访问真实环境,确认请求 URL、认证、缓存、分页、时区和错误结构;检查控制台、失败请求、重复请求、资源 404 与横向滚动。前端要显示安全、可理解的信息,服务端日志则保留可追踪的请求标识。
关闭所有 page.route mock,使用项目现有安全登录流程验证真实 /projects。记录:请求状态和响应结构、adapter 未覆盖字段、控制台错误、失败资源、重复请求、权限差异、390/768/1440px 布局。不要输出 token、cookie 或完整用户数据。只修与本任务有关的问题,并重新运行 unit、Playwright、lint、typecheck 和 build。
用 Codex 把假数据 UI 接成真页面,最重要的不是把 fetch 写得更快,而是把接口事实、页面状态和验收证据放在同一条链上。先审计契约,再用 adapter 稳定数据边界;先模拟每个状态,再关闭 mock 回到真实后端。这样交付的才不是一张会动的效果图,而是能面对真实网络、真实权限和真实数据的产品界面。
本文由「设计创意1984」整理编辑,转载请注明出处。
关注设计创意1984,持续获取设计趋势、AI创作方法与创意灵感。


via:OpenAI Academy:Create frontend designs(OpenAI,官方)、OpenAI Academy:Turn Figma designs into code(OpenAI,官方)、Figma:How to move fast toward the right thing(Jake Albaugh)、Playwright:Network(官方文档)、MDN:Using the Fetch API(Mozilla Contributors)
本文由 设计创意1984 作者:admin 发表,转载请注明来源!