❓什么是氛围编程
氛围编程(vibe coding)是 AI 研究员 Karpathy 于 2025 年提出的一种新型开发方式。开发者通过自然语言描述意图,AI 负责生成、优化和调试代码,让编程更专注于“做什么”,而非“怎么做”。相比传统的 AI 辅助开发,氛围编程更强调对代码实现的“忘却”,依赖 AI 完成大部分工作。
这不算真正的编程,我只是看看东西,说说东西,运行东西,然后复制粘贴东西,而且它大多都能工作。
— Andrej Karpathy
❓如何运作
🆚 传统编程
| 功能 | 传统编程 | 氛围编程 (vibe coding) |
|---|---|---|
| 代码创建 | 逐行手动编码 | AI 根据自然语言提示生成 |
| Developer 角色 | 架构师、实现者、调试者 | 提示者、引导者、测试者、优化者 |
| 需要编码专业知识 | 较高(编程语言和语法知识) | 较低(了解所需的功能) |
| 主要输入 | 精确的代码 | 自然语言提示 |
| 开发速度 | 通常较慢,有条不紊 | 可能更快,特别是对于原型设计更简单的任务 |
| 错误处理 | 根据代码理解进行手动调试 | 迭代式 AI 反馈;调试复杂的 AI 代码可能很困难 |
| 学习曲线 | 往往很陡 | 上手可能更容易 |
| 代码可维护性 | 依赖于开发者技能和既定做法 | 可能严重依赖 AI 输出质量和用户评价 |
🔧 实际应用策略
- 需求拆解:
把大需求拆成小任务,逐个交给 AI 实现。必要时可先让 AI 出原型图,逐步细化。 - 渐进引导:
从简单功能开始,逐步搭建更复杂模块,避免混乱,像 “搭积木” 一样构建系统。 - 错误反馈:
出错就直接把报错信息给 AI,让其尝试修复,实现初步的“自我纠错”。 - 功能验证:
每个功能都要频繁运行和测试,不要等所有功能做完才整体测试,避免隐藏问题。
👣 开始实践
通过“氛围编程”的方式实现一个web应用,让我们开始吧!
项目简介
📌 项目名称: 手势飞机大战
💻 目标平台: PC端 Web 浏览器(支持主流浏览器)
👤 游玩人数: 单人模式
🎮 游戏类型: 像素风射击类网页游戏
📷 交互方式: 基于摄像头的手势识别控制(移动与攻击)
🏆 核心玩法: 玩家通过手势操控飞机在屏幕中移动、发射子弹,击败敌机与 Boss,拾取道具,闯关升级。
📈 附加功能: 积分系统、历史排行榜、关卡进度存档。
需求文档
工具: Manus
LLM: 未知
提示词
我要开发一个web应用,需要你出一份需求文档,这个应用是一个游戏,主要功能是通过手势控制飞机移动和发弹,
游戏具体规则参考市面上的飞机大战,请根据我的描述按照以下要求,生成一份专业、标准、符合互联网大厂(如
阿里、腾讯、字节、美团等)规范的产品需求文档(Product Requirements Document, PRD)。文档需结构
完整、逻辑清晰、语言严谨,具备可执行性和可评审性,适用于产品、研发、设计、测试等多角色协同:
一、背景与目标
产品背景:简要说明当前业务背景、用户痛点或市场机会,解释为什么需要这个功能或产品。
目标用户:明确核心用户群体(如角色、画像、使用场景)。
项目目标:量化产品目标(如提升转化率10%、降低用户操作步骤至3步以内等)。
成功指标(Success Metrics):列出可衡量的关键指标(如DAU、留存率、点击率、任务完成率等)。
二、功能需求
功能概述:用一句话概括本功能的核心价值。
用户故事(User Story):以“作为[用户角色],我希望[功能],以便[价值]”格式描述。
功能详述:
分模块或页面详细描述功能逻辑。
包含前置条件、操作流程、系统响应、异常处理。
使用文字清晰描述关键流程(如:用户点击“提交” → 系统校验表单 → 校验通过 → 跳转成功页)。
权限与角色:如有不同用户角色(如管理员、普通用户),需明确权限差异。
三、交互与界面要求
关键页面原型说明:描述主要界面布局、核心元素(如按钮、输入框、提示文案)。
交互逻辑:说明弹窗、跳转、加载、错误提示等交互行为。
状态说明:列举各页面或组件的不同状态(如正常、禁用、加载中、空状态、错误状态)。
四、非功能需求
性能要求:如页面加载时间 ≤ 1s,接口响应时间 < 500ms。
兼容性:支持的设备、浏览器、操作系统(如iOS 12+、Android 8+、Chrome/Firefox)。
安全性:涉及用户数据时需说明加密、权限控制、防刷策略等。
可扩展性:是否支持未来功能扩展(如多语言、多端适配)。
五、埋点与数据需求
列出关键用户行为埋点(如“点击注册按钮”、“完成支付”)。
每个埋点需包含:事件名称、触发条件、上报字段(如用户ID、页面来源、时间戳)。
六、测试与验收标准
验收标准(Acceptance Criteria):以“Given-When-Then”格式描述(如:Given用户已登录,When点击提交订单,Then显示支付成功页)。
边界与异常场景:网络中断、重复提交、非法输入等处理方式。
测试重点:指出需要重点测试的功能模块或流程。
七、项目信息(可选)
优先级:P0/P1/P2
预计上线时间:YYYY-MM-DD
相关方:产品、研发、设计、测试负责人
输出要求
使用中文撰写,语言简洁、专业,避免口语化。
采用PDF格式输出,结构清晰,合理使用标题、列表、代码块等增强可读性。
如涉及流程,可用文字描述流程图逻辑(无需图像,但需清晰表达)。
文档整体控制在 1500–3000字 之间,重点突出,避免冗余。
请根据以上模板,结合我提供的具体功能描述,生成一份完整的产品需求文档。
示例输入(你可替换为实际需求):
功能名称:用户注册页优化
目标:提升新用户注册转化率,减少表单填写流失
核心改动:增加手机号一键登录、优化表单校验提示、新增第三方登录入口(微信、Apple ID)
需求文档
视觉交互设计
工具: Readdy
LLM: 未知
提示词
需求文档的功能需求和交互与界面要求作为提示词
交互设计稿
地址: Readdy
定版迭代次数: 50次
视觉稿:
前后端开发
工具: TRAE - Collaborate with Intelligence
LLM: GPT-4.1/Claude-4-Sonnet
前端开发
项目规则(Trae需要遵循的开发规范)
提示词:“ 我现在要开发一个前端项目,以大厂的前端架构为标准来制定项目规则供智能体使用,需要在项目规则中加上项目的技术选型,框架结构等”
### 一、项目简介
- 📌 项目名称:手势飞机大战
- 💻 目标平台:PC端 Web 浏览器(支持主流浏览器)
- 👤 游玩人数:单人模式
- 🎮 游戏类型:像素风射击类网页游戏
- 📷 交互方式:基于摄像头的手势识别控制(移动与攻击)
- 🏆 核心玩法:玩家通过手势操控飞机在屏幕中移动、发射子弹,击败敌机与 Boss,拾取道具,闯关升级。
- 📈 附加功能:积分系统、历史排行榜、关卡进度存档。
### 二、技术选型
- 主语言 :TypeScript(强类型,提升可维护性)
- 核心框架 :React 18
- 状态管理 :Zustand
- 路由管理 :React Router v6
- UI 组件库 :Ant Design
- HTTP 请求 :Axios(统一请求封装,支持拦截器)
- 构建工具 :Vite
- 代码规范 :ESLint + Prettier + Stylelint(统一团队代码风格)
- 单元测试 :Jest + React Testing Library
- 端到端测试 :Cypress
- CI/CD :GitHub Actions
- 包管理 :pnpm
### 三、目录结构
- 组件/页面文件需与其对应的样式文件同名且放置在同一位置
```
├── public/ # 公共资源
├── mock/ # mock数据
├── src/
│ ├── assets/ # 静态资源(图片、字体、样式)
│ ├── components/ # 通用基础组件
│ ├── pages/ # 页面级组件
│ ├── layouts/ # 页面布局组件
│ ├── services/ # API 请求与数据处理
│ ├── store/ # 状态管理(Redux/Pinia)
│ ├── hooks/ # 自定义 hooks
│ ├── utils/ # 工具函数
│ ├── router/ # 路由配置
│ ├── constants/ # 常量定义
│ ├── types/ # TypeScript 类型定义
│ └── App.tsx # 应用入口
├── tests/ # 测试用例
├── .husky/ # Git 钩子
├── .github/ # CI/CD 配置
├── .env* # 环境变量
└── package.json
```
### 四、开发规范
- 组件开发 :原子化、低耦合、高复用,优先函数组件,Hooks 优先
- TS规范 :严格定义类型,避免 any 类型,使用泛型增强类型安全,非必要不使用@ts-ignore
- 样式管理 :Less,禁止全局污染,非必要不使用行内样式
- 请求管理 :使用async/await处理异步请求
- 接口管理 :统一 API 封装,错误码与异常处理机制标准化,统一处理异常
- 权限体系 :无权限
- 国际化 :i18n
- 响应式设计 :只需适配PC端
- 性能优化 :懒加载、代码分割、图片压缩
- 安全规范 :XSS/CSRF 防护、依赖安全扫描
### 五、工程化与协作
- 分支管理 :Git Flow
- 代码提交 :Commitlint + Husky,强制规范化提交信息
- 自动化测试 :PR 必须通过单元测试与端到端测试
- 持续集成 :自动化构建、测试、部署
- 代码审查 :强制 Code Review,主干保护
### 六、其他约定
- 环境变量管理 :区分 dev、test、prod 环境
- 页面需要自适应,不需要考虑移动端
- 禁止自行进行大规模的UI设计改动
- 图片导入采用ES6模块导入
- 注释全部使用中文
框架搭建
提示词:“ 根据项目规则搭建基础的前端框架”
- 搭建过程
- 项目概览
业务开发
提示词:“ 下面开始业务开发,我会给你需求文档,你需要仔细阅读需求文档后按顺序开发功能块,每次开发前都需要询问我,因为我会给你设计稿或者一些要求,每个功能模块开发完成,需要我调整确认无误之后,再开启下一个功能模块的开发,你可以先根据需求文档按顺序详细的列出功能模块,需求文档如下 需求文档.md”
- 功能模块顺序
1. 手势识别与控制系统
○ 摄像头权限获取与异常处理
○ 手势识别模型加载与初始化
○ 实时手势检测与指令映射(移动、发射、暂停、确认)
○ 手势识别状态指示与反馈
2. 游戏核心玩法
○ 飞机移动与碰撞检测
○ 子弹发射与敌机逻辑
○ 关卡与Boss设计
○ 道具与分数系统
○ 游戏暂停、继续、结束等状态管理
3. 积分与排行榜系统
○ 实时计分与历史最高分
○ 单局统计与累计成就
○ 全球/本周/好友排行榜
○ 本地与云端数据存储
4. 用户界面与交互
○ 启动页、游戏主界面、排行榜页
○ 弹窗交互(暂停、结算)
○ 状态指示器与反馈动画
~~5. 设置与个性化~~
~~○ 手势灵敏度、音效、画质、摄像头等设置~~
~~○ 用户信息与自定义外观(如实现注册登录~~
~~6. 埋点与数据统计~~
~~○ 页面访问、游戏操作、结果、性能、错误等埋点~~
~~○ 数据上报与本地/云端存储~~
7. 非功能性模块
○ 性能优化(加载、帧率、延迟)
○ 兼容性适配(浏览器、设备、分辨率)
○ 安全与隐私保护(本地处理、加密、权限控制)
~~○ 可扩展性预留(多语言、移动端、VR、多人模式等)~~
2. 用户界面与交互
-
启动页
- 达预期调试: 15次
- 人为引导: 2次
- 提供飞机图片资源
- 图片引入方式使用ES6模块化导入
- 最终效果:
-
排行榜页
- 达预期调试: 34次
- 人为引导: 5次
- 安装mockjs的类型声明包@types/mockjs
- 添加mockjs使用说明
- node结合express提供后端服务模拟数据请求
- package.json中添加启动mock服务命令
- 数据请求页面添加缺省状态
- 最终效果
* 游戏主界面
- 达预期调试: 24次
- 人为引导: 2次
- 提供暂停结束按钮逻辑
- 渐变色调整
- 最终效果
-
手势识别与控制系统
- 达预期调试: 21次
- 人为引导: 6次
- hooks封装
- 使用Tensorflow.js来实现手势识别
- 摄像头开启关闭业务逻辑
- 摄像头镜像
- 手势识别关键点追踪展示
- 布局优化
- 最终效果
-
游戏核心玩法模块&积分与排行榜系统
- 达预期调试: 68次
- 人为引导: 7次
- 方向控制(方法重复)
- 素材替换
- 图片引入方式使用ES6模块化导入
- 暂停手势置信度阈值
- 头部难度提示居中
- 计时问题修复
- 雷达预测功能
- 最终效果
-
非功能性模块
- 路由懒加载优化
- 达预期调试: 2次
- 人为引导: 0次
- 优化内容: 将所有页面组件改为懒加载
- 技术实现: 使用 React.lazy() 和 Suspense
- 性能提升: 减少初始包体积,提升首屏加载速度
- Vite构建配置优化
- 达预期调试: 1次
- 人为引导: 0次
- 代码分割: 手动分包策略,将React、UI库、手势识别库分别打包
- 压缩优化: 启用Terser压缩,生产环境移除console和debugger
- 资源管理: 按类型分类静态资源(图片、字体、媒体文件)
- 依赖预构建: 优化开发时的依赖加载
- 组件性能优化
- 达预期调试: 1次
- 人为引导: 0次
- React.memo: 为CameraPreview组件添加memo包装
- useCallback: 优化事件处理函数,减少不必要的重渲染
工程化
-
自动化测试(核心模块单元测试、集成测试)
- 核心模块单元测试(手势识别、手势控制Hook、相机组件、工具函数)
- 达预期调试: 9次
- 人为引导: 1次
- 测试用例显示详细名称
- 覆盖情况:
- 集成测试(Game 页面、手势识别 + 游戏控制、模态框组件、手势可视化组件、页面间导航)
- 达预期调试: 10次
- 人为引导: 1次
- 补充测试方法(无法正确获取终端报错信息)
- 覆盖情况:
- 测试覆盖率优化
- 待优化文件
- src/router/index.tsx : 0% 覆盖率
- src/services/request.ts : 0% 覆盖率
- src/utils/gestureUtils.ts : 50.92% 覆盖率
- src/utils/cameraManager.ts : 69.04% 覆盖率
- src/pages/Start/index.tsx : 0% 覆盖率
- src/pages/Rank/index.tsx : 0% 覆盖率
- 达预期调试: 5次
- 人为引导: 0次
- 覆盖情况:
- 待优化文件
- 核心模块单元测试(手势识别、手势控制Hook、相机组件、工具函数)
-
分支管理(Git Flow)
- 达预期调试: 6次
- 人为引导: 0次
-
代码提交(Commitlint + Husky,强制规范化提交信息)
- 达预期调试: 5次
- 人为引导: 1次
- 提交前lint校验和单测
后端开发
项目规则(Trae需要遵循的开发规范)
提示词:“ 根据目前的前端mock服务,提供对应的后端项目的项目规则,主要技术栈为Express+MongoDB”
## 一、项目简介
- 📌 **项目名称**:手势飞机大战后端服务
- 🎯 **项目目标**:为前端游戏提供数据存储、排行榜、统计分析等后端服务
- 👤 **用户模式**:游客模式(基于设备ID标识用户)
- 🔐 **认证方式**:设备指纹识别,无需注册登录
- 📊 **核心功能**:游戏记录存储、排行榜管理、数据统计、离线数据同步
- 🚀 **部署方式**:Serverless 架构,支持自动扩缩容
## 二、技术选型
### 2.1 核心技术栈
- **主语言**:TypeScript(强类型,提升可维护性)
- **运行时**:Node.js 18+
- **Web框架**:Express.js + Serverless Functions
- **数据库**:MongoDB(主库)+ Redis(缓存)
- **ODM**:Mongoose(类型安全的MongoDB访问)
- **部署平台**:Vercel(Serverless Functions)
- **数据库服务**:MongoDB Atlas(云端MongoDB服务)
- **缓存服务**:Upstash Redis(Serverless Redis)
### 2.2 开发工具
- **包管理**:pnpm
- **代码规范**:ESLint + Prettier
- **类型检查**:TypeScript strict mode
- **测试框架**:Jest + Supertest
- **API文档**:OpenAPI
- **监控日志**:Vercel Analytics + Winston
### 2.3 第三方服务
- **CDN**:Vercel Edge Network
- **监控**:Sentry(错误追踪)
- **分析**:Vercel Analytics
## 三、目录结构
```
backend/
├── api/ # Vercel Serverless Functions
│ ├── game/
│ │ ├── submit.ts # 提交游戏成绩
│ │ ├── history/[deviceId].ts # 获取个人历史记录
│ │ ├── stats/[deviceId].ts # 获取个人统计数据
│ │ └── ranking.ts # 获取排行榜
│ ├── health.ts # 健康检查
│ └── sync.ts # 数据同步接口
├── lib/ # 核心业务逻辑
│ ├── database/
│ │ ├── connection.ts # MongoDB连接配置
│ │ ├── models/ # Mongoose数据模型
│ │ │ ├── GameRecord.ts # 游戏记录模型
│ │ │ ├── DeviceStats.ts # 设备统计模型
│ │ │ └── RankingCache.ts # 排行榜缓存模型
│ │ └── schemas/ # MongoDB Schema定义
│ ├── services/
│ │ ├── gameService.ts # 游戏数据服务
│ │ ├── rankingService.ts # 排行榜服务
│ │ ├── statsService.ts # 统计服务
│ │ └── cacheService.ts # 缓存服务
│ ├── utils/
│ │ ├── deviceId.ts # 设备ID验证工具
│ │ ├── validation.ts # 数据验证工具
│ │ ├── response.ts # 统一响应格式
│ │ └── logger.ts # 日志工具
│ └── types/
│ ├── api.ts # API类型定义
│ ├── game.ts # 游戏数据类型
│ └── database.ts # 数据库类型
├── config/
│ ├── database.ts # MongoDB配置
│ └── seed.ts # 数据库种子数据
├── tests/ # 测试文件
│ ├── api/ # API测试
│ ├── services/ # 服务层测试
│ ├── utils/ # 工具函数测试
│ └── setup.ts # 测试环境配置
├── docs/ # 项目文档
│ ├── api.md # API文档
│ ├── database.md # 数据库设计文档
│ └── deployment.md # 部署文档
├── .env.example # 环境变量示例
├── .env.local # 本地环境变量
├── vercel.json # Vercel配置
├── package.json
├── tsconfig.json
├── jest.config.js
├── mongoose.config.js
└── README.md
```
## 四、数据库设计规范
### 4.1 核心数据模型
#### 4.1.1 游戏记录集合 (gameRecords)
```javascript
// MongoDB文档结构
{
_id: ObjectId, // MongoDB自动生成的ID
deviceId: String, // 设备ID(32位哈希值)
score: Number, // 游戏分数
createdAt: Date // 创建时间
}
// 索引配置
db.gameRecords.createIndex({ deviceId: 1 })
db.gameRecords.createIndex({ score: -1 })
db.gameRecords.createIndex({ createdAt: -1 })
db.gameRecords.createIndex({ deviceId: 1, score: -1 })
```
#### 4.1.2 设备统计集合 (deviceStats)
```javascript
// MongoDB文档结构
{
_id: String, // 设备ID作为主键
deviceId: String, // 设备ID(冗余字段,便于查询)
bestScore: Number, // 最高分数
createdAt: Date, // 创建时间
updatedAt: Date // 更新时间
}
// 索引配置
db.deviceStats.createIndex({ bestScore: -1 })
db.deviceStats.createIndex({ createdAt: -1 })
```
#### 4.1.3 排行榜缓存集合 (rankingCache)
```javascript
// MongoDB文档结构
{
_id: ObjectId, // MongoDB自动生成的ID
deviceId: String, // 设备ID
score: Number, // 分数
rankPosition: Number, // 排名位置
cachedAt: Date, // 缓存时间
expiresAt: Date // 过期时间
}
// 索引配置
db.rankingCache.createIndex({ deviceId: 1 }, { unique: true })
db.rankingCache.createIndex({ rankPosition: 1 })
db.rankingCache.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 })
db.rankingCache.createIndex({ score: -1 })
```
### 4.2 Mongoose Schema 定义
```typescript
// src/models/GameRecord.ts
import mongoose, { Schema, Document } from 'mongoose';
export interface IGameRecord extends Document {
deviceId: string;
score: number;
createdAt: Date;
}
const GameRecordSchema: Schema = new Schema({
deviceId: {
type: String,
required: true,
index: true,
validate: {
validator: (v: string) => /^[a-f0-9]{32}$/.test(v),
message: '设备ID格式不正确'
}
},
score: {
type: Number,
required: true,
min: 0,
index: true
}
}, {
timestamps: { createdAt: true, updatedAt: false },
collection: 'gameRecords'
});
// 复合索引
GameRecordSchema.index({ deviceId: 1, score: -1 });
export default mongoose.model<IGameRecord>('GameRecord', GameRecordSchema);
// src/models/DeviceStats.ts
import mongoose, { Schema, Document } from 'mongoose';
export interface IDeviceStats extends Document {
_id: string; // 使用deviceId作为主键
deviceId: string;
bestScore: number;
createdAt: Date;
updatedAt: Date;
}
const DeviceStatsSchema: Schema = new Schema({
_id: {
type: String,
required: true
},
deviceId: {
type: String,
required: true,
unique: true,
validate: {
validator: (v: string) => /^[a-f0-9]{32}$/.test(v),
message: '设备ID格式不正确'
}
},
bestScore: {
type: Number,
default: 0,
min: 0,
index: true
}
}, {
timestamps: true,
collection: 'deviceStats',
_id: false // 使用自定义_id
});
export default mongoose.model<IDeviceStats>('DeviceStats', DeviceStatsSchema);
// src/models/RankingCache.ts
import mongoose, { Schema, Document } from 'mongoose';
export interface IRankingCache extends Document {
deviceId: string;
score: number;
rankPosition: number;
cachedAt: Date;
expiresAt: Date;
}
const RankingCacheSchema: Schema = new Schema({
deviceId: {
type: String,
required: true,
unique: true,
validate: {
validator: (v: string) => /^[a-f0-9]{32}$/.test(v),
message: '设备ID格式不正确'
}
},
score: {
type: Number,
required: true,
min: 0,
index: true
},
rankPosition: {
type: Number,
required: true,
min: 1,
index: true
},
cachedAt: {
type: Date,
default: Date.now
},
expiresAt: {
type: Date,
required: true,
index: true
}
}, {
collection: 'rankingCache'
});
// 索引配置
RankingCacheSchema.index({ score: -1 });
RankingCacheSchema.index({ rankPosition: 1 });
// TTL索引,自动删除过期文档
RankingCacheSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
export default mongoose.model<IRankingCache>('RankingCache', RankingCacheSchema);
```
## 五、开发规范
### 5.1 API 开发规范
#### 5.1.1 统一响应格式
```typescript
interface ApiResponse<T> {
success: boolean;
data: T;
message?: string;
timestamp: number;
requestId?: string;
}
interface ErrorResponse {
success: false;
error: {
code: string;
message: string;
details?: any;
};
timestamp: number;
requestId?: string;
}
```
#### 5.1.2 设备ID验证规范
```typescript
// 设备ID格式:32位十六进制字符串
const DEVICE_ID_PATTERN = /^[a-f0-9]{32}$/;
function validateDeviceId(deviceId: string): boolean {
return DEVICE_ID_PATTERN.test(deviceId);
}
```
#### 5.1.3 数据验证规范
```typescript
import { z } from 'zod';
// 游戏记录提交验证
const GameRecordSchema = z.object({
deviceId: z.string().length(32).regex(/^[a-f0-9]+$/),
score: z.number().int().min(0).max(999999)
});
```
### 5.2 TypeScript 规范
#### 5.2.1 类型定义
```typescript
// 游戏数据类型
export interface GameRecord {
_id: string;
deviceId: string;
score: number;
createdAt: Date;
}
// 排行榜项目类型
export interface RankingItem {
deviceId: string;
score: number;
rank: number;
createdAt: Date;
}
// 设备统计类型
export interface DeviceStatistics {
deviceId: string;
bestScore: number;
rank: number;
createdAt: Date;
updatedAt: Date;
}
```
#### 5.2.2 错误处理规范
```typescript
// 自定义错误类型
export class GameApiError extends Error {
constructor(
public code: string,
message: string,
public statusCode: number = 400,
public details?: any
) {
super(message);
this.name = 'GameApiError';
}
}
// 错误码定义
export const ErrorCodes = {
INVALID_DEVICE_ID: 'INVALID_DEVICE_ID',
INVALID_GAME_DATA: 'INVALID_GAME_DATA',
DATABASE_ERROR: 'DATABASE_ERROR',
RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
DEVICE_NOT_FOUND: 'DEVICE_NOT_FOUND',
} as const;
```
### 5.3 数据库连接配置
#### 5.3.1 MongoDB 连接配置
```typescript
// lib/database/connection.ts
import mongoose from 'mongoose';
interface ConnectionOptions {
maxPoolSize?: number;
serverSelectionTimeoutMS?: number;
socketTimeoutMS?: number;
bufferCommands?: boolean;
}
class DatabaseConnection {
private static instance: DatabaseConnection;
private isConnected: boolean = false;
private constructor() {}
public static getInstance(): DatabaseConnection {
if (!DatabaseConnection.instance) {
DatabaseConnection.instance = new DatabaseConnection();
}
return DatabaseConnection.instance;
}
public async connect(): Promise<void> {
if (this.isConnected) {
return;
}
try {
const options: ConnectionOptions = {
maxPoolSize: 10, // 连接池最大连接数
serverSelectionTimeoutMS: 5000, // 服务器选择超时
socketTimeoutMS: 45000, // Socket超时
bufferCommands: false, // 禁用命令缓冲
};
await mongoose.connect(process.env.MONGODB_URI!, options);
this.isConnected = true;
console.log('✅ MongoDB连接成功');
// 监听连接事件
mongoose.connection.on('error', (error) => {
console.error('❌ MongoDB连接错误:', error);
this.isConnected = false;
});
mongoose.connection.on('disconnected', () => {
console.warn('⚠️ MongoDB连接断开');
this.isConnected = false;
});
} catch (error) {
console.error('❌ MongoDB连接失败:', error);
throw error;
}
}
public async disconnect(): Promise<void> {
if (!this.isConnected) {
return;
}
await mongoose.disconnect();
this.isConnected = false;
console.log('✅ MongoDB连接已关闭');
}
public getConnectionStatus(): boolean {
return this.isConnected && mongoose.connection.readyState === 1;
}
}
export default DatabaseConnection;
// 使用示例
export const connectDatabase = async () => {
const db = DatabaseConnection.getInstance();
await db.connect();
};
```
### 5.4 缓存策略规范
#### 5.4.1 Redis 缓存键命名
```typescript
const CacheKeys = {
// 排行榜缓存 (TTL: 5分钟)
RANKING_GLOBAL: 'ranking:global',
RANKING_DAILY: 'ranking:daily',
RANKING_WEEKLY: 'ranking:weekly',
// 设备统计缓存 (TTL: 1小时)
DEVICE_STATS: (deviceId: string) => `stats:${deviceId}`,
// 设备排名缓存 (TTL: 10分钟)
DEVICE_RANK: (deviceId: string) => `rank:${deviceId}`,
// API限流缓存 (TTL: 1分钟)
RATE_LIMIT: (deviceId: string) => `limit:${deviceId}`,
} as const;
```
#### 5.4.2 缓存更新策略
- **排行榜**:写入时更新,5分钟TTL
- **设备统计**:写入时更新,1小时TTL
- **设备排名**:查询时计算并缓存,10分钟TTL
#### 5.4.3 MongoDB 查询优化
```typescript
// 使用聚合管道优化排行榜查询
const getRankingPipeline = (cacheType: string, limit: number = 50) => [
{ $match: { cacheType } },
{ $sort: { score: -1, createdAt: 1 } },
{ $limit: limit },
{ $lookup: {
from: 'deviceStats',
localField: 'deviceId',
foreignField: '_id',
as: 'playerStats'
}},
{ $project: {
deviceId: 1,
score: 1,
level: 1,
rankPosition: 1,
playerData: 1,
totalGames: { $arrayElemAt: ['$playerStats.totalGames', 0] },
avgScore: { $arrayElemAt: ['$playerStats.avgScore', 0] }
}}
];
// 使用索引提示优化查询
const findGameRecords = async (deviceId: string, limit: number = 20) => {
return await GameRecord
.find({ deviceId })
.sort({ score: -1, createdAt: -1 })
.limit(limit)
.hint({ deviceId: 1, score: -1 }) // 使用复合索引
.lean(); // 返回普通对象,提升性能
};
```
## 六、工程化与协作
### 6.1 分支管理
- **主分支**:`main`(生产环境)
- **开发分支**:`develop`(开发环境)
- **功能分支**:`feature/功能名称`
- **修复分支**:`hotfix/问题描述`
### 6.2 代码提交规范
```bash
# 提交格式
<type>(<scope>): <description>
# 示例
feat(api): 添加游戏记录提交接口
fix(database): 修复排行榜查询性能问题
docs(readme): 更新API文档
test(game): 添加游戏服务单元测试
```
### 6.3 自动化测试
- **单元测试**:覆盖率 ≥ 80%
- **集成测试**:API接口测试
- **性能测试**:数据库查询性能
- **安全测试**:输入验证和SQL注入防护
### 6.4 持续集成
```yaml
# .github/workflows/ci.yml
name: CI/CD Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: pnpm install
- run: pnpm test
- run: pnpm build
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: vercel --prod
```
## 七、其他约定
### 7.1 环境变量管理
```bash
# .env.example
# MongoDB配置
MONGODB_URI="mongodb+srv://username:password@cluster.mongodb.net/gamedb?retryWrites=true&w=majority"
MONGODB_DB_NAME="gamedb"
# Redis配置
REDIS_URL="redis://localhost:6379"
UPSTASH_REDIS_REST_URL="https://your-redis.upstash.io"
UPSTASH_REDIS_REST_TOKEN="your_redis_token"
# Vercel配置
VERCEL_TOKEN="your_vercel_token"
# 第三方服务
SENTRY_DSN="your_sentry_dsn"
# 安全配置
API_RATE_LIMIT="100" # 每分钟请求限制
# 功能开关
ENABLE_ANALYTICS="true"
ENABLE_CACHE="true"
DEBUG_MODE="false"
# MongoDB Atlas配置
ATLAS_PUBLIC_KEY="your_atlas_public_key"
ATLAS_PRIVATE_KEY="your_atlas_private_key"
ATLAS_PROJECT_ID="your_project_id"
```
### 7.2 性能要求
- **API响应时间**:< 200ms (P95)
- **数据库查询**:< 100ms (P95)
- **缓存命中率**:> 90%
- **并发处理**:支持1000+ QPS
### 7.3 安全规范
- **输入验证**:所有用户输入必须验证
- **NoSQL注入防护**:使用Mongoose参数化查询
- **XSS防护**:输出转义
- **CORS配置**:限制允许的域名
- **API限流**:防止恶意刷分
### 7.4 监控与日志
- **错误监控**:Sentry集成
- **性能监控**:Vercel Analytics
- **日志级别**:ERROR, WARN, INFO, DEBUG
- **关键指标**:QPS、响应时间、错误率、缓存命中率
### 7.5 数据备份与恢复
- **数据库备份**:每日自动备份
- **备份保留**:30天
- **恢复测试**:每月一次
- **灾难恢复**:RTO < 1小时,RPO < 15分钟
## 八、核心API设计
### 8.1 游戏记录API
#### 8.1.1 提交游戏成绩
```typescript
POST /api/game/submit
Content-Type: application/json
{
"deviceId": "abc123def456...",
"score": 15800
}
// 响应
{
"success": true,
"data": {
"recordId": "507f1f77bcf86cd799439011",
"rank": 15,
"isNewBest": true,
"bestScore": 15000
}
}
```
#### 8.1.2 获取个人历史记录
```typescript
GET /api/game/history/{deviceId}?limit=20&offset=0
// 响应
{
"success": true,
"data": {
"records": [...],
"total": 156,
"hasMore": true
},
"timestamp": 1703123456789
}
```
### 8.2 排行榜API
#### 8.2.1 获取全球排行榜
```typescript
GET /api/game/ranking?limit=50
// 响应
{
"success": true,
"data": {
"rankings": [
{
"rank": 1,
"deviceId": "device_hash_1",
"score": 25000,
"createdAt": "2024-01-15T10:30:00Z"
}
],
"total": 1000
},
"timestamp": 1703123456789
}
```
### 8.3 统计数据API
#### 8.3.1 获取设备统计
```typescript
GET /api/game/stats/{deviceId}
// 响应
{
"success": true,
"data": {
"deviceId": "abc123def456...",
"bestScore": 25600,
"rank": 15,
"recentGames": [
{
"score": 18000,
"createdAt": "2024-01-15T09:00:00Z"
}
]
},
"timestamp": 1703123456789
}
```
框架搭建
提示词: “根据项目规则,按照以下要求,生成后端源码框架: - 项目初始化和环境配置 - MongoDB Atlas集群创建和配置 - Mongoose ODM配置和数据模型定义 - 基础API框架搭建(Express + Serverless) - 设备ID管理系统 - 基础测试环境和数据库连接测试”
- 达预期调试: 10次
- 人为引导: 3次
- 包管理器使用项目规则中指定的pnpm
- 连接MongoDB,生成数据库种子脚本
- 精简业务代码
提示词: “现在需要缩减业务代码,本项目只需要:
1.通过用户的设备ID来记录每次对应的分数和分数创建时间,如果同一设备有更高分数则只保留最高分数;
2.可以获取周榜和总榜的前十个分数;
其余多余业务代码都不需要,修改对应代码和文档”
业务开发
提示词: “现在开始第二部分开发, 游戏记录提交API(MongoDB写入优化)、 排行榜查询API(聚合管道优化)、 MongoDB索引优化和查询性能调优、 单元测试和集成测试编写。 ”
- 达预期调试: 4次
- 人为引导: 0次
性能优化
提示词:“现在开始第三部分优化 MongoDB性能优化和分片策略、API安全加固和限流机制、MongoDB Atlas监控和告警配置、自动化备份和恢复策略。“
- 达预期调试: 3次
- 人为引导: 0次
前后端联调
后端
提示词: “根据后端业务代码生成API文档供前端联调使用”
- 达预期调试: 2次
- 人为引导: 1次
- 同一设备的分数只有在被超过时才进行数据的记录更新
前端
提示词: “根据API文档进行数据的获取与更新”
- 达预期调试: 5次
- 人为引导: 1次
- 被动结束游戏时也需要触发提交游戏数据的请求
部署
前端部署
提示词: “现在要开始正式的部署阶段,我打算使用Vercel,先帮我列出接下来前端部署的详细步骤”
🔧 第一步:创建 Vercel 配置文件
🌍 第二步:配置生产环境变量
📦 第三步:添加部署脚本
🔨 第四步:安装构建依赖
✅ 第五步:验证构建
📚 第六步:创建部署文档
- 达预期调试: 15次
- 人为引导: 2次
- 配置CI/CD流程
- 环境变量配置
服务端部署
提示词: “现在要开始正式的部署阶段,我打算使用Render,先帮我列出接下来前端部署的详细步骤”
🔧 第一步:创建 Render 配置文件
- 在项目根目录创建 render.yaml 配置文件
- 配置 Node.js 运行环境和构建命令
- 设置健康检查端点和自动部署规则
- 配置服务类型为 Web Service
🌍 第二步:配置生产环境变量
- 在 Render 控制台设置 MONGODB_URI (MongoDB Atlas 连接字符串)
- 配置 NODE_ENV=production
- 设置 PORT 环境变量(Render 自动提供)
- 添加 CORS_ORIGINS 配置允许的前端域名
📦 第三步:添加部署脚本
- 在 package.json 中添加 build 脚本进行 TypeScript 编译
- 配置 start 脚本启动生产服务器
- 创建 scripts/deploy-render.sh 自动化部署脚本
- 设置 Git hooks 确保代码质量
🔨 第四步:安装构建依赖
- 安装 TypeScript 编译器和类型定义
- 配置 tsconfig.json 生产环境编译选项
- 安装 Express、Mongoose、CORS 等核心依赖
- 配置 ESLint 和 Prettier 代码规范工具
✅ 第五步:验证构建
- 本地运行 npm run build 验证 TypeScript 编译
- 使用 npm start 测试生产环境启动
- 验证 MongoDB Atlas 连接和 CORS 配置
- 测试 API 端点响应和错误处理
📚 第六步:创建部署文档
- 编写 README-DEPLOYMENT.md 部署指南
- 创建 docs/render-deployment-guide.md 详细部署文档
- 记录环境变量配置和常见问题解决方案
- 提供 API 快速参考和前端集成指南
- 达预期调试: 40次
- 人为引导: 2次
- 跨域配置
- 环境变量配置
项目成功上线 🎉
后端地址: GitHub - Archer-SQ/vibe-coding-backend at main
前端地址: GitHub - Archer-SQ/vibe-coding-frontend: 氛围编程demo
线上地址(vpn访问): https://vibe-coding-frontend.vercel.app/rank
Trae使用总结
使用情况
使用次数:545次
-
项目开始
-
项目结束
模型思考达上限次数:8次
崩溃次数:3次(服务器异常)
经验总结
- 理清项目的生命周期(AI辅助决策)
- 不同生命周期的核心需求拆解(AI辅助决策)
- 提供合理的项目规范,增加可控性(AI辅助决策,持续迭代) ❗️❗️❗️
- 明确的技术选型
- 合理的目录结构
- 清晰的开发规范
- 保持提交粒度清晰,功能与提交一一对应,确保开发不偏航
- The New Code — Sean Grove, OpenAI : 规范驱动开发