
1. Cursor 写 uniapp 为什么总跑偏用 Cursor 写 uni-app 项目最让人抓狂的不是它不会写而是它写得太“自由”。你让它加一个商品详情页它给你返回一堆div和pxscript setup和export default混着来条件编译#ifdef一个都不带最后你还得手动把px全改成rpx、把div换成view。这不是 AI 能力不行而是它根本不知道你们团队的规范长什么样。Cursor 默认的补全逻辑是基于通用 Web 开发的语料训练的它天然倾向于 React/Vue3 的写法对 uni-app 这套“Vue 语法 小程序组件 条件编译”的混合体系并不敏感。你每次在 Chat 里手动补一句“用 rpx、用 view、加条件编译”它这次记住了下次新开一个文件又忘了。真正能解决这个问题的是把规范固化成一个 Cursor 能持续读取的 rule 文件让它在每次生成代码前先“读一遍团队手册”。这篇面向的是用 Cursor 开发小程序和 H5 的前端同学尤其是团队里已经有一套 uni-app 编码约定、但每次都要靠 code review 去纠正 AI 输出的情况。我会给出一份可以直接复制的.cursorrules骨架覆盖页面结构、rpx 单位、条件编译这三块最容易跑偏的地方然后演示在 Cursor 里新建 rule 文件后怎么触发补全、怎么对比配置前后的生成差异。整个流程不需要你改项目构建配置纯粹是给 AI 加一层“行为约束”。需要说明的是rule 文件解决的是“生成规范”问题它不替代你对 uni-app 生命周期、平台差异的理解。AI 按规范写出来的代码仍然需要你在真机或模拟器上验证。下面先从 rule 文件该放在哪、Cursor 怎么读它讲起。2. 前置rule 文件放哪、Cursor 怎么读Cursor 读取项目级规则有两种常见方式一种是项目根目录的.cursorrules文件另一种是.cursor/rules/目录下的多个.mdc文件。对于 uni-app 这种规范相对固定的项目我建议先用单个.cursorrules起步内容集中、维护成本低等团队规范拆分成“页面规范”“组件规范”“请求规范”多块之后再迁移到.cursor/rules/目录。.cursorrules的本质是一段会随每次请求一起发给模型的系统提示。它不参与编译不影响manifest.json和pages.json你把它当成“给 AI 看的 README”就行。文件放在项目根目录和package.json、pages.json同级Cursor 打开这个项目时会自动加载。这里有个容易踩的坑很多人把.cursorrules写成了“项目介绍”洋洋洒洒几百行讲业务背景结果 AI 反而不遵守具体规范。rule 文件要写成约束条款用“必须/禁止/优先”这种明确措辞而不是“我们一般会……”。另外rule 文件不是越长越好超过 500 行后模型对中间部分的注意力会下降把最关键的页面结构、单位、条件编译放在前 100 行。如果你团队用的是 Cursor 的 Team 计划还可以把规则同步到云端但个人版用本地.cursorrules完全够用。下面这份骨架就是按“约束条款”思路写的你可以直接复制到项目根目录再按自己团队的习惯微调。3. 可复制的 .cursorrules 骨架这份骨架分四块技术栈声明、页面结构约定、单位与样式约定、条件编译约定。每一块都用“必须/禁止”开头避免 AI 自由发挥。注意里面的组件名和 API 都是 uni-app 官方支持的不涉及任何平台私有写法。# uni-app 项目编码规范Cursor Rule ## 技术栈 - 必须使用 Vue2 语法options API禁止使用 Vue3 的 script setup。 - 必须使用 uni-app 内置组件view、text、image、scroll-view、swiper、button、input。 - 禁止使用 HTML 标签div、span、p、img、ul、li。 - 页面文件必须放在 pages/ 目录下组件放在 components/ 目录下。 ## 页面结构 - 每个页面必须包含 template、script、style 三个块顺序固定。 - script 中必须 export default包含 data、onLoad、methods 三个基础字段。 - 页面根节点必须是 view classpage-xxxxxx 为页面名。 - 列表渲染必须使用 v-for 并绑定 :keykey 用唯一 id禁止用 index。 - 事件绑定统一用 tap禁止用 clickH5 端 click 有 300ms 延迟。 ## 单位与样式 - 所有尺寸单位必须使用 rpx禁止使用 px、rem、em。 - 字体大小用 rpx最小 24rpx正文默认 28rpx。 - style 必须加 scoped禁止全局样式污染。 - 颜色值统一用 # 十六进制禁止 rgb() 和颜色单词。 - 布局优先用 flex禁止用 float。 ## 条件编译 - 涉及平台差异的代码必须加条件编译注释。 - 仅微信小程序// #ifdef MP-WEIXIN ... // #endif - 仅 H5// #ifdef H5 ... // #endif - 非 H5 平台// #ifndef H5 ... // #endif - 条件编译必须成对出现禁止嵌套超过两层。 ## 代码质量 - 请求统一走封装的 request 方法禁止在页面里直接调 uni.request。 - 错误处理必须用 try/catch 或 fail 回调禁止空 catch。 - 禁止留 TODO、占位符、未实现的空函数。把这份文件保存到项目根目录后重启 Cursor 或新开一个 Chat 会话让它生效。这里要提醒一句.cursorrules对 Cursor 的 Tab 补全和 Chat 都生效但对已经打开的旧会话不一定立即刷新建议新开一个文件再测试。如果你在团队里用 TaoToken 做模型接入可以把这份 rule 和你的 API Key 一起管理。TaoToken 的 API 地址是https://taotoken.net/api兼容 OpenAI 风格的调用方式Cursor 里配置自定义模型时填这个地址即可。API Key 在控制台的 API Keys 页面生成具体接入方式可以参考官方文档这里不展开。4. 验证配置前后生成结果对比rule 文件写好了怎么确认它真的生效最直接的办法是让 Cursor 生成同一个页面对比配置前后的输出。我拿一个“商品列表页”做测试提示词完全一样“帮我写一个商品列表页展示商品图片、名称、价格点击跳转详情”。配置前Cursor 大概率会返回这样的代码template div classgoods-list div classgoods-item v-for(item, index) in list :keyindex clickgoDetail(item.id) img :srcitem.image / p{{ item.name }}/p span{{ item.price }}/span /div /div /template问题很明显用了div、img、p、spanclick而不是tapkey用了index单位默认会是px。这份代码在 H5 端能跑但到小程序端组件不识别而且不符合团队规范。配置后同样的提示词Cursor 会按 rule 输出template view classpage-goods view classgoods-item v-foritem in list :keyitem.id tapgoDetail(item.id) image :srcitem.image modeaspectFill / text classgoods-name{{ item.name }}/text text classgoods-price{{ item.price }}/text /view /view /template script export default { data() { return { list: [] }; }, onLoad() { this.loadList(); }, methods: { async loadList() { try { const res await this.$request(/api/goods); this.list res.data; } catch (e) { uni.showToast({ title: 加载失败, icon: none }); } }, goDetail(id) { uni.navigateTo({ url: /pages/goods/detail?id${id} }); } } }; /script style scoped .page-goods { display: flex; flex-direction: column; padding: 24rpx; } .goods-item { display: flex; flex-direction: row; align-items: center; margin-bottom: 24rpx; } .goods-name { font-size: 28rpx; color: #333333; } .goods-price { font-size: 32rpx; color: #ff5500; } /style对比下来组件名、事件名、单位、key 绑定、请求封装全部按 rule 走了。这里的关键验证动作是新开一个.vue文件输入同样的提示词看 Cursor 的补全是否直接给出view和rpx。如果它还在给div说明 rule 没加载检查文件是否在根目录、是否重启了 Cursor。再测一个条件编译场景提示词“写一段只在微信小程序里执行的分享逻辑”。配置后 Cursor 应该输出// #ifdef MP-WEIXIN onShareAppMessage() { return { title: 好物推荐, path: /pages/goods/list }; } // #endif如果它没加条件编译直接在 rule 里把“涉及平台差异必须加条件编译”这条往前挪或者补一句“微信小程序 API 必须包裹在 #ifdef MP-WEIXIN 中”。5. 本篇常见错排查rule 不生效AI 还是给 div。先确认.cursorrules在项目根目录不是放在src/或pages/下。然后新开一个 Chat 会话旧会话的上下文里可能还残留着之前的生成习惯。如果用的是.cursor/rules/目录检查文件后缀是不是.mdc普通.md不会被加载。rpx 和 px 混用。有些第三方组件库内部用 px你在页面里引用时 AI 可能跟着用 px。rule 里可以补一句“引用第三方组件时外层容器仍用 rpx组件内部样式不强制”。另外border的1px是常见例外可以单独说明“1px 边框允许保留 px”。条件编译注释被格式化插件删掉。有些 Prettier 配置会把// #ifdef当成普通注释合并或删除。在.prettierignore里排除*.vue或者用!-- #ifdef MP-WEIXIN --的模板写法这种 HTML 注释不会被 JS 格式化影响。AI 生成的请求直接调 uni.request。说明 rule 里“请求统一走封装方法”这条没被重视。把这条提到 rule 最前面并且给出封装方法的名字比如“必须调用this.$request”AI 对具体名字的遵守度比抽象描述高。Cursor 补全和 Chat 行为不一致。Tab 补全用的是轻量模型对 rule 的遵守程度不如 Chat。重要页面建议用 Chat 生成或者用CmdK内联生成这两种方式对 rule 的读取更完整。rule 文件太长导致后半段失效。把“页面结构、单位、条件编译”这三块放在前 100 行业务相关的规范放后面。如果确实需要很多规则拆成.cursor/rules/下的多个文件按需加载。6. 把 rule 和模型接入串起来rule 文件解决的是“生成规范”但 Cursor 背后调用的模型能力决定了它能不能稳定遵守这些规范。如果你发现即使 rule 写得很清楚AI 还是偶尔跑偏可以考虑在 Cursor 里接入更擅长指令遵循的模型。TaoToken 提供了兼容 OpenAI 风格的接口模型对话、Coding Plan、API Keys 和接入文档都可以在官网找到对应入口。对于长期用 Cursor 写 uni-app 的团队建议把.cursorrules纳入代码仓库和pages.json一起做版本管理。每次团队规范更新改 rule 文件比口头同步有效得多。新同学拉下代码Cursor 自动按规范生成code review 里关于“用 view 还是 div”的争论能少一大半。最后留一个实操建议rule 文件写完后别只测一个页面。拿三个典型场景各测一次——列表页、表单页、带条件编译的分享逻辑。三个都过了这份 rule 才算真正可用。后面遇到新的跑偏案例就往 rule 里补一条约束慢慢就养成了你们团队自己的 AI 编码规范。