以下就是我们今天用codex生成的小程序:
今天和历史工具箱
本文不讲理论。
只讲一件事:
一个完整微信小程序,是怎么从 0 被 Codex 做出来的
项目名称:
包含 6 个功能:
1. 一个空的微信小程序原生项目2. 小程序名称:今日趣测工具箱3. AppID,如果没有就先用测试号4. 已有 API 信息: - 历史上的今天 API - 汇率 API - 车牌归属地 API - 随机句子 API5. 百家姓完整数据文件6. 你希望遵守的开发规则
API我是让ChatGPT去网络上帮我搜索的免费接口😂。百家姓的数据也是我给的json规则让ChatGPT帮我生成的😂。一、开始之前:先把 Context 喂饱
还记得上一篇文章的核心结论吗?Context 决定 Agent 的上限第 1 步:让 Codex 读取规则并创建 AGENTS.md请按照 AGENTS.md 和 docs/ui-style-guide.md,创建微信小程序基础目录结构。需要创建这些页面:pages/index/indexpages/license-plate/license-platepages/exchange/exchangepages/exchange-pair/exchange-pairpages/history/historypages/zodiac/zodiacpages/surname/surnamepages/mbti/mbti每个页面都需要:- .js- .wxml- .wxss- .json还需要创建:utils/api.jsutils/currency.jsutils/history.jsutils/lunar.jsutils/mbti.jsdata/baijiaxing_complete.js并配置:- app.js- app.json- app.wxss暂时只写基础结构和占位页面,不实现具体业务。
codex开始生成:
请创建 docs/ui-style-guide.md,写入本项目的 UI 基础规范。要求:项目风格:- 简洁- 现代- 轻量卡片式- 不使用第三方 UI 库- 首页直接展示工具入口,不做营销页全局样式:- 页面背景:#f7f8fb- 主色:#2563eb- 正文颜色:#111827- 辅助文字:#6b7280- 边框:#dbe4f0- 卡片背景:#ffffff- 卡片圆角:20rpx功能主题色:- 首页/历史:#2563eb- 车牌:#0f766e- 汇率:#059669- 星座生肖:#ea580c- 百家姓:#dc2626- MBTI:#7c3aed需要定义:- 页面标题规范- 分区标题规范- 卡片规范- 按钮规范- 输入框规范- 错误提示规范- 空状态规范- 首页工具入口布局规范只创建文档,不写页面代码。
第 3 步:创建基础项目结构
请按照 AGENTS.md 和 docs/ui-style-guide.md,创建微信小程序基础目录结构。需要创建这些页面:pages/index/indexpages/license-plate/license-platepages/exchange/exchangepages/exchange-pair/exchange-pairpages/history/historypages/zodiac/zodiacpages/surname/surnamepages/mbti/mbti每个页面都需要:- .js- .wxml- .wxss- .json还需要创建:utils/api.jsutils/currency.jsutils/history.jsutils/lunar.jsutils/mbti.jsdata/baijiaxing_complete.js并配置:- app.js- app.json- app.wxss暂时只写基础结构和占位页面,不实现具体业务。
codex开始生成:
第 4 步:实现 app.json / app.wxss / app.js
请实现小程序全局配置和基础样式。app.json 要求:- 注册所有页面- navigationBarTitleText 为“今日趣测工具箱”- navigationBarBackgroundColor 为 #f7f8fb- navigationBarTextStyle 为 black- backgroundColor 为 #f7f8fb- style 使用 v2- lazyCodeLoading 使用 requiredComponents- sitemapLocation 使用 sitemap.jsonapp.js 要求:- 只保留必要的 globalData- appName 为“今日趣测工具箱”app.wxss 要求实现这些通用类:- .page- .section- .section-title- .section-more- .card- .card-body- .muted- .primary-button- .ghost-button- .field- .empty- .notice不要写业务页面逻辑。
第 5 步:实现 API 封装
请实现 utils/api.js,作为整个微信小程序唯一的 API 请求封装文件。开发要求:- 所有 wx.request 只能出现在 utils/api.js- 页面不得直接调用 wx.request- request() 必须返回 Promise- 支持 GET/POST 等 method- 支持 data、header、showLoading、loadingText- HTTP 状态码 2xx 时 resolve- 非 2xx 时 reject,并返回 message 和 response- 网络失败时 reject,统一提示:网络连接失败,请稍后重试- showLoading 为 true 时调用 wx.showLoading,complete 后调用 wx.hideLoading- 不引入 npm 包- 不使用第三方库- 星座生肖和 MBTI 都是本地计算,不要为它们添加 API请在 utils/api.js 中定义:BASE_URLS:- xxapi: https://v2.xxapi.cn- exchange: https://api.frankfurter.dev/v1- exchangeFallback: https://open.er-api.com- yuanxi: https://yuanxiapi.cn/api/API_CONFIG:- yuanxiRandomSentenceApiId: 18- yuanxiRandomSentenceKey: 在这里放随机句子 API key- yuanxiLicensePlateApiId: 22- yuanxiLicensePlateKey: 在这里放车牌归属地 API key需要封装并导出以下方法:1. request(options)基础请求方法。2. getTodayHistory(options)接口:GET https://v2.xxapi.cn/api/history说明:- 用于“历史上的今天”- 直接返回接口响应数据3. getRandomSentence(options)接口:GET https://yuanxiapi.cn/api/参数:- id: xxxx- key: xxxx说明:- 用于首页随机句子4. getLicensePlateLocation(chepai, options)接口:GET https://yuanxiapi.cn/api/参数:- id: xxxx- key: xxxxx- chepai: 用户输入的车牌号校验:- chepai 需要 trim- 自动转大写- 少于 2 位时直接 Promise.reject- 错误提示:请输入至少前两位车牌号5. getExchangeRates(params, options)主接口:GET https://api.frankfurter.dev/v1/latest备用接口:GET https://open.er-api.com/v6/latest/{from}参数:- params.from 默认 USD- params.to 支持数组或逗号字符串- options.forceRefresh 支持强制刷新汇率处理规则:- 最终返回以 CNY 为 base 的 rates- 返回格式中 base 固定为 CNY- CNY 的 rate 固定为 1- 如果主接口 from=USD,返回 USD 到 CNY 和其他币种的 rates,需要换算成: 1 CNY = x 外币- 如果某些币种主接口缺失,使用备用接口补齐- 主接口和备用接口都失败时,尝试使用过期缓存缓存要求:- 缓存时间 10 分钟- 同时使用内存缓存和 wx.setStorageSync- 缓存 key 需要包含 from 和 to,避免不同币种组合互相污染- 未过期缓存直接返回,并标记 fromCache: true- 网络失败但存在过期缓存时返回缓存,并标记: fromCache: true offline: true- 正常请求成功时标记: fromCache: false offline: false- 返回 cachedAt 时间戳- 相同请求并发时复用同一个 Promise,避免重复请求getExchangeRates 返回结构建议:{ base: 'CNY', rates: {}, fallbackUsed: false, fromCache: false, offline: false, cachedAt: timestamp}发生离线缓存兜底时:{ base: 'CNY', rates: {}, fallbackUsed: false, fromCache: true, offline: true, cachedAt: timestamp, error}最后请导出:module.exports = { API_CONFIG, request, getTodayHistory, getRandomSentence, getLicensePlateLocation, getExchangeRates}注意:- 如果项目里已经有 utils/currency.js,并导出了 DEFAULT_CURRENCY_CODES,请从那里 import 使用- 如果没有,就在 api.js 内部临时定义默认币种列表- 不要实现页面逻辑- 不要修改其他文件
实现首页Prompt:
请实现 pages/index 首页。页面结构:1. 顶部 hero 区- 显示“今日”- 显示当前日期,例如 6月4日- 显示年份和星期- 显示随机句子- 有一个 MBTI 趣测入口按钮2. 历史上的今天预览- 标题:历史上的今天- 右侧按钮:更多- 点击更多进入 pages/history/history- 加载中显示骨架- 成功后横向滚动展示历史事件卡片- 失败时显示错误提示3. 功能工具箱- 2 列网格- 工具包括: 车牌归属地 汇率换算 历史上的今天 星座生肖 百家姓 MBTI趣测每个工具需要:- name- desc- icon,使用单字图标- color- path接口:- 调用 getTodayHistory()- 调用 getRandomSentence()- 历史数据使用 normalizeHistoryList()交互:- 点击工具跳转对应页面- 下拉刷新重新加载历史和随机句子- 随机句子失败时使用兜底: 真正有价值的事情,都不是轻松舒服就能完成的。请实现 index.js、index.wxml、index.wxss、index.json。
然后用微信开发者工具打开文件夹:今日趣测工具箱
模拟器可以看见效果:
三、车牌归属地模块(第一个真实功能)
请实现 pages/license-plate 车牌归属地页面。页面结构:1. 顶部标题- 小标题:车牌号归属地- 大标题:查询车辆所在地区2. 查询卡片- 输入框- 默认值:川A- maxlength: 8- 清空按钮- 查询按钮3. 快速示例- 横向滚动- 示例: 川A、京A、沪A、粤B、浙A、苏A、渝A、陕A4. 结果区- 成功显示: 查询结果 车牌前缀 所在地区- 无结果时显示说明卡片- 错误时显示错误提示接口:- 调用 getLicensePlateLocation(chepai)输入处理:- 去除空格- 转大写- 少于 2 位提示: 请输入至少前两位车牌号,例如 川A交互:- onLoad 默认查询 川A- 点击示例后立即查询- 输入框 confirm-type 为 search- 本页面不需要下拉刷新请实现 license-plate.js、license-plate.wxml、license-plate.wxss、license-plate.json。
然后在微信开发者工具上方刷新点击进入车牌归属地:

请实现 utils/currency.js 和 pages/exchange 汇率换算页面。utils/currency.js 需要包含币种:CNY 人民币USD 美元EUR 欧元GBP 英镑JPY 日元HKD 港币AUD 澳元CAD 加元CHF 瑞士法郎SGD 新加坡元KRW 韩元THB 泰铢MYR 马来西亚林吉特IDR 印尼盾INR 印度卢比BRL 巴西雷亚尔RUB 俄罗斯卢布MXN 墨西哥比索ZAR 南非兰特SEK 瑞典克朗NZD 新西兰元utils/currency.js 需要导出:- BASE_CURRENCY- DEFAULT_CURRENCIES- DEFAULT_CURRENCY_CODES- DEFAULT_SELECTED_CURRENCY_CODES- roundAmount()- createCurrencyList()- applyCurrencyRates()- syncCurrencyAmounts()- getSelectedCurrencies()- withDisplayRates()exchange 页面结构:1. 顶部- 标题:汇率换算- picker 选择当前显示基准,例如 当前基准:1 CNY- 状态标签: 更新中 离线模式 缓存2. 提示区- 离线提示:当前为离线模式,已使用本地缓存汇率- 缓存时间提示:汇率更新时间 HH:mm3. 币种列表- 每个币种一张卡片- 左侧显示 code 和中文名- 右侧输入金额- 下方显示汇率文本4. 底部固定按钮- 一对一换算- 点击进入 pages/exchange-pair/exchange-pair接口:- 调用 getExchangeRates({ from: 'USD', to: DEFAULT_CURRENCY_CODES })交互:- 输入金额后 300ms 防抖同步其他币种- 下拉刷新时 forceRefresh: true- API 失败提示:汇率加载失败,请检查网络后下拉刷新请实现 exchange.js、exchange.wxml、exchange.wxss、exchange.json。
点击进入汇率换算:
请实现 pages/exchange-pair 一对一汇率换算页面。页面结构:1. 顶部- 标题:一对一换算- 副标题:选择两个币种,输入任意一侧金额- 状态标签: 更新中 离线模式 缓存2. 上方换算卡片- picker 选择 from 币种- 输入 from 金额3. 中间交换按钮- 点击后交换 from 和 to 币种4. 下方换算卡片- picker 选择 to 币种- 输入 to 金额数据:- 复用 utils/currency.js- 复用 getExchangeRates()- 默认 from 为 CNY- 默认 to 为 USD- 默认 fromAmount 为 1交互:- 修改上方金额,同步下方金额- 修改下方金额,同步上方金额- 输入使用 300ms 防抖- 下拉刷新强制刷新汇率- 支持离线缓存提示- API 失败显示错误提示请实现 exchange-pair.js、exchange-pair.wxml、exchange-pair.wxss、exchange-pair.json。

请实现 utils/history.js 和 pages/history 页面。utils/history.js 要求:- 提供 parseHistoryItem(item, index)- 提供 normalizeHistoryList(res)- 兼容接口返回: 数组 res.data res.data.list res.result- 兼容字符串格式: 1999年1月1日 事件内容- 输出字段: id year month day title details pic- 按年份倒序排序history 页面结构:1. 顶部- 小标题:历史上的今天- 当前日期,例如 6月4日- 分享按钮2. 内容- 加载中显示时间线骨架- 成功后用时间线展示事件- 每条显示 year、title、details- 如果有 pic,则显示图片- 空数据提示:今天的历史数据暂时为空- 失败提示:历史事件加载失败,请稍后下拉刷新交互:- onLoad 加载数据- 下拉刷新重新加载- 支持 onShareAppMessage请实现 history.js、history.wxml、history.wxss、history.json。
点击进入历史上的今天:

请实现 pages/zodiac 星座生肖页面。要求:- 不调用网络 API- 使用 utils/lunar.js 本地计算- utils/lunar.js 需要导出 Solar页面结构:1. 顶部- 小标题:本地日历计算- 大标题:星座生肖查询2. 日期选择卡片- 显示当前 birthday- 使用 picker mode="date"- 日期范围:1900-01-01 到 2099-12-313. 生肖横向选择- 鼠、牛、虎、兔、龙、蛇、马、羊、猴、鸡、狗、猪- 图标用地支:子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥- 当前生肖高亮4. 主结果卡片- 生肖- 星座- 农历日期- 干支八字5. 信息网格- 星座- 农历- 干支- 年纳音6. 详情卡片- 上一节气- 下一节气- 今日所宜- 今日所忌交互:- onLoad 默认使用今天- 修改生日后重新计算- 点击生肖时,自动选择最近一个对应生肖年份的日期- 下拉刷新重新计算- 日期解析失败提示:日期解析失败,请重新选择生日请实现 zodiac.js、zodiac.wxml、zodiac.wxss、zodiac.json。
点击进入星座生肖:

请实现 pages/surname 百家姓页面。数据:- 使用 data/baijiaxing_complete.js- 数据字段: id surname pinyin rank_song type origin junwang celebrities description页面结构:1. 顶部- 小标题:百家姓- 大标题:查姓氏来源- 统计: 共 X 个姓氏,单姓 X 个,复姓 X 个2. 搜索卡片- 输入框 placeholder: 输入姓氏、拼音或序号3. 推荐区- 标题:推荐20个- 横向滚动显示前 20 个姓氏- 显示姓氏和拼音- 当前选中项高亮4. 拼音首字母区- 标题:按拼音首字母- 横向滚动首字母 tab- 点击 tab 展示该首字母下的姓氏5. 详情卡片- 姓氏大字- 拼音- 百家姓排名- 类型:单姓/复姓- 姓氏来源- 郡望- 代表人物- 简介搜索规则:- 支持汉字- 支持带音调拼音- 支持不带音调拼音- 支持 rank_song- 支持 id错误提示:没有找到这个姓氏,可输入汉字、拼音或百家姓序号交互:- 默认选中第一个姓氏- 输入时实时搜索- 点击推荐姓氏更新详情- 点击首字母切换列表- 下拉刷新回到第一个姓氏请实现 surname.js、surname.wxml、surname.wxss、surname.json。
点击进入百家姓:
八、MBTI趣测
MBTI趣测Prompt:
请实现 utils/mbti.js 和 pages/mbti MBTI 趣测页面。测试规则:- 共 32 道题- 四个维度: EI SN TF JP- 每题原始两个方向- 页面展示四个选项: A 非常像我:左侧方向,权重 2 B 有点像我:左侧方向,权重 1 C 有点像我:右侧方向,权重 1 D 非常像我:右侧方向,权重 2utils/mbti.js 需要导出:- questions- typeDescriptions- calculateResult(answers)calculateResult 输出:- type- scores- detail.title- detail.summary- detail.tags页面结构:1. 答题状态- 顶部显示 MBTI趣测- 标题:选择更像你的答案- 右侧显示进度,例如 1/32- 进度条- 问题卡片- 2 列选项卡片2. 结果状态- 结果类型,例如 INFP- 类型标题- 简介- tags- 四维度得分- 重新测试按钮- 分享结果按钮交互:- 点击选项后高亮 180ms- 自动进入下一题- 最后一题后计算结果- 下拉刷新重置测试- 支持 onShareAppMessage- 分享标题: 有结果时:我的MBTI趣测结果是 XXXX 无结果时:来测测你的MBTI倾向请实现 mbti.js、mbti.wxml、mbti.wxss、mbti.json。
点击进入MBTI趣测:
最终检查Prompt:
请完整检查当前微信小程序项目,并只修复必要问题。检查内容:1. app.json 是否注册所有页面2. 每个页面目录是否都有 js/wxml/wxss/json3. 是否没有 package.json 和 npm 依赖4. 是否没有第三方 UI 库5. 是否所有 wx.request 都只在 utils/api.js6. 首页所有入口是否能跳转到对应页面7. WXML 中绑定的方法是否都在 JS 中存在8. require 的工具函数是否都正确导出9. API 失败时是否都有错误提示10. 空数据时是否有空状态11. 下拉刷新是否调用 wx.stopPullDownRefresh12. 汇率是否有缓存和离线兜底13. 页面样式是否符合 docs/ui-style-guide.md14. 不要自动提交 Git15. 不做无关重构
十、 最后开发过程的真实总结
核心原则是:先规则,再结构,再 API,再首页,再逐个功能页,最后检查。最重要的不是 Prompt,而是 AGENTS.md
它决定了:
定义系统 → 分模块 → 逐个Prompt → 验收
你不是在“写代码”你是在: 指挥一个开发团队(Codex)
当然对于Prompt可以不用写得这么详细。我是为了节约token😂。