氛围编程——实现全栈Web项目

274 阅读23分钟

❓什么是氛围编程

氛围编程(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格式输出,结构清晰,合理使用标题、列表、代码块等增强可读性。

如涉及流程,可用文字描述流程图逻辑(无需图像,但需清晰表达)。

文档整体控制在 15003000字 之间,重点突出,避免冗余。

请根据以上模板,结合我提供的具体功能描述,生成一份完整的产品需求文档。

示例输入(你可替换为实际需求):

功能名称:用户注册页优化

目标:提升新用户注册转化率,减少表单填写流失

核心改动:增加手机号一键登录、优化表单校验提示、新增第三方登录入口(微信、Apple ID

需求文档

手势飞机大战PRD.pdf

视觉交互设计

工具: 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模块导入
- 注释全部使用中文

框架搭建

提示词:“ 根据项目规则搭建基础的前端框架”

  1. 搭建过程
  2. 项目概览

业务开发

提示词:“ 下面开始业务开发,我会给你需求文档,你需要仔细阅读需求文档后按顺序开发功能块,每次开发前都需要询问我,因为我会给你设计稿或者一些要求,每个功能模块开发完成,需要我调整确认无误之后,再开启下一个功能模块的开发,你可以先根据需求文档按顺序详细的列出功能模块,需求文档如下 需求文档.md”

  1. 功能模块顺序
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次
      • 提供暂停结束按钮逻辑
      • 渐变色调整
    • 最终效果
  1. 手势识别与控制系统

    • 达预期调试: 21次
    • 人为引导: 6次
      • hooks封装
      • 使用Tensorflow.js来实现手势识别
      • 摄像头开启关闭业务逻辑
      • 摄像头镜像
      • 手势识别关键点追踪展示
      • 布局优化
    • 最终效果
  2. 游戏核心玩法模块&积分与排行榜系统

    • 达预期调试: 68次
    • 人为引导: 7次
      • 方向控制(方法重复)
      • 素材替换
      • 图片引入方式使用ES6模块化导入
      • 暂停手势置信度阈值
      • 头部难度提示居中
      • 计时问题修复
      • 雷达预测功能
    • 最终效果
  3. 非功能性模块

    • 路由懒加载优化
    • 达预期调试: 2次
      • 人为引导: 0次
      • 优化内容: 将所有页面组件改为懒加载
      • 技术实现: 使用 React.lazy() 和 Suspense
      • 性能提升: 减少初始包体积,提升首屏加载速度
    • Vite构建配置优化
      • 达预期调试: 1次
      • 人为引导: 0次
      • 代码分割: 手动分包策略,将React、UI库、手势识别库分别打包
      • 压缩优化: 启用Terser压缩,生产环境移除console和debugger
      • 资源管理: 按类型分类静态资源(图片、字体、媒体文件)
      • 依赖预构建: 优化开发时的依赖加载
    • 组件性能优化
      • 达预期调试: 1次
      • 人为引导: 0次
      • React.memo: 为CameraPreview组件添加memo包装
      • useCallback: 优化事件处理函数,减少不必要的重渲染

工程化

  1. 自动化测试(核心模块单元测试、集成测试)

    • 核心模块单元测试(手势识别、手势控制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次
      • 覆盖情况:
  2. 分支管理(Git Flow)

    • 达预期调试: 6次
    • 人为引导: 0次
  3. 代码提交(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辅助决策,持续迭代) ❗️❗️❗️
    • 明确的技术选型
    • 合理的目录结构
    • 清晰的开发规范