ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

15 分钟,无代码,我用 Cursor 开发了一款微信小程序:TaoToken 统一 Key 接入实录

15 分钟,无代码,我用 Cursor 开发了一款微信小程序:TaoToken 统一 Key 接入实录

1. 零前端经验也能跑通:Cursor 写微信小程序到底靠不靠谱

先说结论:Cursor 写微信小程序,对零前端经验的产品和运营同学来说,是当前门槛最低的一条路。它不是一个"帮你写代码"的玩具,而是一个能读懂你项目目录、能改多个文件、能自己跑命令的编程助手。你只要把需求说清楚,它就能把pages/index/index.wxml、index.js、index.wxss这些文件一次性生成出来。

微信小程序本身的结构其实很固定:一个app.json管全局页面注册,一个app.js管生命周期,每个页面由四个文件组成——结构(wxml)、样式(wxss)、逻辑(js)、配置(json)。这套东西对程序员来说是常识,但对没写过前端的人来说,光记住这四个后缀就够头疼的。Cursor 的价值就在于,你不需要记这些,你只需要描述"我要一个能选日期、显示今日宜忌的页面",它会把四个文件都补齐。

我这次做的 Demo 是一个"程序员老黄历"小程序:打开后显示今天的日期,下面列出"宜写代码""忌改需求"这类条目,还能点按钮切换日期查看不同结果。整个流程从建项目到真机预览跑通,实测 15 分钟左右。这里面唯一需要你动手配置的,是 AI 能力的接入——因为 Cursor 内置的对话模型和你要在小程序里调用的模型是两回事。小程序里如果要生成"今日宜忌"这种动态内容,需要一个稳定的 API 入口,我用的是 TaoToken 的统一 Key,一个 Base URL 加一个 Key 就能切换不同模型,省得在小程序里到处改配置。

这篇文章会给你三样能直接抄的东西:一份 Cursor 项目规则文件、一套小程序目录结构模板、一段 TaoToken 的 Base URL 配置片段。目标很明确——15 分钟内,你能在自己电脑上跑出一个能点、能切日期、能调接口的小程序 Demo。

适合谁看:做过产品文档、写过运营活动页、但没碰过前端工程的同学。你不需要懂 JavaScript 的闭包,也不需要懂小程序的双线程架构,跟着步骤走就行。踩过的坑我会在第 5 节列出来,包括 401、local proxy failed 这些真实报错怎么处理。

2. 前置准备:Cursor 项目规则文件与 TaoToken 统一 Key 配置

这一节解决两个问题:让 Cursor 知道"这是个微信小程序项目,别乱写",以及让小程序有一个能调用的模型入口。

先说 Cursor 这边。Cursor 默认不知道你在写小程序,它可能给你生成 React 或者 Vue 的代码。解决办法是在项目根目录放一个规则文件。Cursor 支持.cursorrules文件,也支持在设置里配 Project Rules。我习惯用.cursorrules,因为跟着项目走,换电脑也不会丢。内容如下,直接复制到项目根目录:

# 项目类型:微信小程序(原生,非 uni-app / taro) # 技术约束 - 所有页面必须使用原生小程序语法:wxml / wxss / js / json - 禁止使用 React、Vue、TypeScript、npm 包 - 页面逻辑写在 Page({}) 中,组件写在 Component({}) 中 - 网络请求统一使用 wx.request,禁止使用 fetch / axios - 样式单位使用 rpx,设计稿按 750px 宽度换算 # 目录约定 - 页面放在 pages/ 下,每个页面一个文件夹 - 公共逻辑放在 utils/ 下 - 全局配置写在 app.json # 输出要求 - 每次修改后,把改动说明追加到 readme.md 的「开发日志」章节 - 生成代码时给出完整文件内容,不要用省略号代替

这个文件的作用是给 Cursor 划边界。没有它,你让它"加个按钮",它可能给你写个<button onClick={}>,那是 React 语法,小程序根本不认。

再说 TaoToken。小程序里要生成"今日宜忌"这种内容,需要一个模型接口。TaoToken 的定位是统一 Key 接入层:你注册后拿到一个 Key,配一个 Base URL,就能调用它支持的多个模型,不用为每个模型单独申请账号、单独改代码。对小程序这种要频繁切换模型试效果的项目来说,这点很省事。

配置片段如下,放在utils/config.js里:

// utils/config.js // TaoToken 统一 Key 配置 // 官网:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= // API 地址:https://taotoken.net/api const TAOTOKEN_CONFIG = { baseUrl: 'https://taotoken.net/api', apiKey: 'sk-你的Key填这里', // 在控制台创建:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite model: 'claude-sonnet-4-5', // 可换成其他模型 ID timeout: 30000 }; module.exports = TAOTOKEN_CONFIG;

这里三个字段要记牢:Base URL、Key、Model ID。后面不管你是用 Cursor 内置对话、还是在小程序里发请求,都是这三件套。Key 的创建入口在控制台的 API Keys 页面,文档在接入文档里,两个链接我都放在第 6 节。

有一点要注意:小程序的wx.request对域名有白名单要求。开发阶段你可以在微信开发者工具里勾选"不校验合法域名",但真机预览和上线必须把https://taotoken.net加到小程序后台的 request 合法域名里。这一步不做,真机上请求会直接失败,报错是request:fail url not in domain list。

3. 可复制配置:小程序目录结构模板与 Cursor Composer 提示词

这一节给你两样能直接用的东西:目录结构模板,和一段能让 Cursor 一次性生成页面的提示词。

先建项目。打开微信开发者工具,新建项目,填名称、选目录、开发模式选"小程序",模板选"不使用模板"或者"JavaScript-基础模板"都行。创建完之后,目录大概是这样:

miniprogram-demo/ ├── app.js ├── app.json ├── app.wxss ├── project.config.json ├── sitemap.json ├── pages/ │ └── index/ │ ├── index.wxml │ ├── index.wxss │ ├── index.js │ └── index.json └── utils/ └── config.js

然后把这个目录用 Cursor 打开。在根目录新建.cursorrules(内容用上一节的),再新建readme.md,把需求写进去。需求文档我建议按这个结构写,Cursor 读起来最顺:

# 程序员老黄历小程序 ## 功能概述 - 首页显示当前日期 - 显示今日「宜」和「忌」各三条 - 提供日期选择器,切换日期后重新生成内容 - 内容由 AI 接口生成,接口配置见 utils/config.js ## 内容示例 宜:写单元测试、重构旧代码、提交 PR 忌:改需求、上线、开会 ## UI 需求 - 顶部大号显示日期 - 中间卡片显示宜忌,宜用绿色,忌用红色 - 底部一个「换一天」按钮 - 整体居中,留白充足,字体不小于 28rpx ## 开发日志 (每次修改后在此追加)

写完保存,按Ctrl+I(Mac 是Cmd+I)调出 Composer,输入:

根据 readme.md 中的需求,帮我实现这个微信小程序。 要求: 1. 使用原生小程序语法,不要用任何框架 2. 网络请求写在 utils/request.js 里,统一从 utils/config.js 读配置 3. 接口调用失败时要有兜底文案,不能白屏 4. 完成后把改动追加到 readme.md 的开发日志

Composer 会开始生成文件。它一般会先建utils/request.js,再改pages/index/下的四个文件,最后更新app.json注册页面。生成过程中你能看到它逐个文件写入,不用你手动复制粘贴。

这里有个细节值得说:为什么要把请求单独抽到utils/request.js?因为小程序里wx.request是回调式的,写多了容易乱。抽出来之后,页面里只调request({...}),返回 Promise,逻辑清爽。Cursor 默认可能把请求直接写在页面里,你在提示词里明确要求抽出来,它就会照做。

配置片段再贴一次,这次是utils/request.js的核心部分:

// utils/request.js const config = require('./config'); function request(messages) { return new Promise((resolve, reject) => { wx.request({ url: `${config.baseUrl}/v1/messages`, method: 'POST', timeout: config.timeout, header: { 'Content-Type': 'application/json', 'x-api-key': config.apiKey, 'anthropic-version': '2023-06-01' }, data: { model: config.model, max_tokens: 512, messages: messages }, success: (res) => { if (res.statusCode === 200) { resolve(res.data); } else { reject(new Error(`HTTP ${res.statusCode}: ${JSON.stringify(res.data)}`)); } }, fail: (err) => reject(err) }); }); } module.exports = request;

注意 header 里的x-api-key和anthropic-version,这是调用 Claude 系列模型时的标准写法。如果你换成别的模型,header 可能要调整,具体看接入文档。Model ID 也要和 header 匹配,用claude-sonnet-4-5就配 Anthropic 格式,用别的模型就换对应的字段名。

4. 验证请求:真机预览与接口连通性检查

代码生成完,先别急着高兴,得验证两件事:页面能不能正常渲染,接口能不能通。

第一步,在微信开发者工具里点"编译"。如果app.json里页面路径注册对了,模拟器里应该能看到首页。这时候大概率会看到内容区域是空的或者显示兜底文案,因为接口还没通。这是正常的,说明页面逻辑跑起来了,只是数据没回来。

第二步,验证接口。在开发者工具的"调试器"里切到 Console,手动跑一段:

const request = require('./utils/request'); request([{ role: 'user', content: '生成今日宜忌,各三条,用 JSON 返回' }]) .then(res => console.log('成功', res)) .catch(err => console.error('失败', err));

如果返回 200 并且res.content里有内容,说明 Base URL、Key、Model ID 三件套都对。如果报 401,看第 5 节。如果报url not in domain list,去开发者工具右上角"详情"→"本地设置"里勾上"不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书"。

第三步,把接口返回的内容接到页面上。这一步 Cursor 一般已经写好了,你只需要确认pages/index/index.js里的onLoad和按钮点击事件都调了request。如果它把返回结果直接setData了,但页面没更新,检查一下setData的字段名和 wxml 里绑定的名字是否一致——这是新手最容易踩的坑,{{yiji}}和{{yiJi}}大小写不一样,页面就是不动。

第四步,真机预览。点开发者工具上的"预览",用微信扫码。真机上要注意两点:一是合法域名必须配好,二是手机和电脑要在同一个网络环境下调试(如果你用了本地代理)。真机跑通后,你会看到日期、宜忌卡片、按钮都能正常交互,点"换一天"会重新请求接口并刷新内容。

实测下来,从建项目到真机跑通,15 分钟是够的,前提是 Key 和域名配置一次到位。如果卡在接口上,多半是域名白名单或者 header 格式的问题,不是代码逻辑的问题。

5. 常见报错排查:401、local proxy failed、reading choices、OAuth

这一节列四个真实会遇到的报错,以及怎么处理。

401 Unauthorized。这个最常见,意思是 Key 不对或者没带上。检查三处:utils/config.js里的apiKey是不是完整复制了(有没有多余空格);header 里的字段名是不是x-api-key(有些模型用Authorization: Bearer,别混);Key 是不是在控制台被删了或者过期了。如果三处都对还是 401,去控制台重新创建一个 Key 试试。

local proxy failed。这个报错通常出现在你本地开了代理工具的时候。小程序开发者工具的网络请求走的是系统代理,如果代理配置有问题,请求会直接失败。处理办法:关掉本地代理工具,或者在开发者工具设置里把代理模式改成"不使用任何代理"。注意,这里说的是本地开发工具的代理设置,不是让你去搞什么网络工具,纯粹是开发者工具的一个配置项。

reading 'choices'。这个报错说明你调用的接口返回格式和代码里解析的格式不匹配。比如你按 OpenAI 的格式解析res.data.choices[0],但实际返回的是 Anthropic 格式res.data.content[0].text。解决办法:先在 Console 里console.log(res.data)看真实结构,再改解析代码。Model ID 和返回格式是绑定的,换模型要同步改解析逻辑。

OAuth 相关报错。如果你在 Cursor 里登录账号时遇到 OAuth 失败,先检查网络是否正常,再检查 Cursor 版本是不是太旧。这类问题多半和账号登录态有关,退出重新登录一般能解决。如果是在小程序里调接口遇到 OAuth 字样,那说明你调的那个接口需要额外的鉴权流程,不是简单的 Key 能搞定的,换一个不需要 OAuth 的模型 ID 即可。

排查顺序建议:先看 HTTP 状态码,再看返回体,最后看代码解析。状态码 401 是鉴权问题,404 是路径问题,500 是服务端问题。返回体里通常有error.message,直接读那句话,比猜有用。

另外提醒一句:不要把 Key 硬编码在小程序前端代码里然后上传发布。开发阶段本地调试没问题,但上线前一定要把 Key 放到你自己的后端服务里,小程序只调你的后端,由后端去调模型接口。前端代码是可以被反编译的,Key 暴露了别人就能拿去用。

6. 后续怎么用:从 Demo 到可用小程序的路径

Demo 跑通之后,你手里其实已经有了一套可复用的骨架:目录结构、请求封装、配置管理、Cursor 规则文件。接下来要做的,是把"老黄历"换成你真正想做的功能。

如果你要继续用 Cursor 开发,建议把.cursorrules和readme.md当成项目资产维护。每加一个功能,先在 readme 里写清楚需求和验收标准,再让 Composer 动手。这样 Cursor 的产出会稳定很多,不会东一榔头西一棒子。

如果你要长期做编码类项目,或者想让 AI 帮你处理更复杂的 Agent 任务,可以了解一下 Coding Plan,它比按次调用更适合高频使用的场景。如果只是想先验证模型效果、试试不同模型的输出差异,直接用模型对话页面最方便,不用写代码就能对比。

接入过程中遇到配置问题,优先看接入文档,里面把 Base URL、Key、Model ID 的对应关系写得很清楚。Key 的管理和创建在 API Keys 页面,建议给不同项目建不同的 Key,方便排查和停用。

最后说一个实用技巧:小程序开发阶段,把utils/config.js里的model字段做成可切换的,配合 Cursor 的对话能力,你可以快速对比不同模型生成"今日宜忌"的效果。哪个模型输出的内容更有趣、更符合你的产品调性,就用哪个。这个对比过程不需要改任何页面代码,只改一个字符串。

真机预览通过之后,上传代码的入口在开发者工具右上角"上传"按钮。填版本号和备注,提交后在微信公众平台的"版本管理"里可以看到。如果只是自己玩,提交体验版就够了,不用走完整审核流程。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进