Cursor 编辑器完整教程
目录
Cursor简介与核心优势
什么是 Cursor
Cursor 是一款基于 VS Code 深度分叉(fork)的 AI 原生代码编辑器。它不是简单地在 编辑器上叠加 AI 插件,而是将 AI 能力深度融入编辑器的每一个交互环节。Cursor 支持 GPT-4、Claude 等多种大模型,提供了代码补全、内联编辑(Cmd+K)、智能对话(Chat)、 多文件编辑(Composer)等核心功能。
核心架构
┌─────────────────────────────────────────────────────────────────┐
│ Cursor 编辑器架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 用户界面层 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 代码编辑 │ │ Cmd+K │ │ Chat │ │ Composer │ │ │
│ │ │ (补全) │ │ (内联) │ │ (对话) │ │ (多文件) │ │ │
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
│ └───────┼──────────────┼──────────────┼──────────────┼───────┘ │
│ v v v v │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ AI 引擎层 │ │
│ │ ┌──────────────────────────────────────────────────────┐ │ │
│ │ │ 上下文引擎 │ │ │
│ │ │ - 代码库索引 (全项目语义搜索) │ │ │
│ │ │ - 打开文件分析 │ │ │
│ │ │ - Git 历史追踪 │ │ │
│ │ │ - 符号/引用解析 │ │ │
│ │ └──────────────────────────────────────────────────────┘ │ │
│ │ ┌──────────────────────────────────────────────────────┐ │ │
│ │ │ 模型路由 │ │ │
│ │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ │
│ │ │ │ GPT-4o │ │ Claude │ │ cursor-small │ │ │ │
│ │ │ │ (对话) │ │ (编辑) │ │ (快速补全) │ │ │ │
│ │ │ └──────────┘ └──────────┘ └──────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ VS Code 基础层 │ │
│ │ 扩展系统 | 文件系统 | 终端 | 调试器 | Git 集成 │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘Cursor 三大核心功能
┌────────────────────────────────────────────────────────────────┐
│ Cursor 三大核心功能对比 │
├──────────────┬──────────────┬──────────────┬──────────────────┤
│ 维度 │ Cmd+K │ Chat │ Composer │
├──────────────┼──────────────┼──────────────┼──────────────────┤
│ 触发方式 │ Ctrl+K │ Ctrl+L │ Ctrl+Shift+I │
│ 操作范围 │ 选中代码/ │ 整个项目 │ 多个文件 │
│ │ 当前位置 │ │ │
│ 交互模式 │ 单次指令 │ 多轮对话 │ 任务式编排 │
│ 适用场景 │ 局部修改 │ 问答/分析 │ 跨文件重构 │
│ 上下文 │ 当前文件 │ @引用 │ 自动检测 │
│ 输出方式 │ 原地替换 │ 侧边面板 │ diff 预览 │
├──────────────┴──────────────┴──────────────┴──────────────────┤
│ 使用频率建议: │
│ Cmd+K (60%) > Chat (25%) > Composer (15%) │
│ 日常小修改用Cmd+K, 问问题用Chat, 大改动用Composer │
└────────────────────────────────────────────────────────────────┘安装与配置
安装流程
┌──────────────────────────────────────────────────────────────┐
│ Cursor 安装配置流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 下载安装 │
│ ┌────────────────────────────────────┐ │
│ │ 访问 cursor.com │ │
│ │ 下载对应平台安装包 │ │
│ │ (Windows / macOS / Linux) │ │
│ └──────────────┬─────────────────────┘ │
│ v │
│ Step 2: 迁移 VS Code 配置 │
│ ┌────────────────────────────────────┐ │
│ │ 首次启动时会提示: │ │
│ │ - 导入 VS Code 扩展 │ │
│ │ - 导入 VS Code 设置 │ │
│ │ - 导入 VS Code 快捷键 │ │
│ │ 建议: 全部导入, 无缝切换 │ │
│ └──────────────┬─────────────────────┘ │
│ v │
│ Step 3: 登录 Cursor 账号 │
│ ┌────────────────────────────────────┐ │
│ │ 支持: GitHub / Google / Email │ │
│ │ 免费版: 每月 2000 次补全 │ │
│ │ Pro版: $20/月, 无限补全+GPT-4 │ │
│ └──────────────┬─────────────────────┘ │
│ v │
│ Step 4: 配置 AI 模型偏好 │
│ ┌────────────────────────────────────┐ │
│ │ Settings > Models │ │
│ │ 选择默认模型 (GPT-4o / Claude) │ │
│ │ 可以按功能分别设置模型 │ │
│ └────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘核心设置推荐
json
// Cursor Settings (settings.json)
{
// ===== AI 功能配置 =====
// 开启代码库索引(让AI理解整个项目)
"cursor.codebaseIndexing.enabled": true,
// Tab 补全行为
"cursor.autocomplete.enabled": true,
"cursor.autocomplete.alwaysSuggest": true,
// 自动导入建议
"cursor.autocomplete.autoImport": true,
// ===== 编辑器优化 =====
// 内联建议样式
"editor.inlineSuggest.enabled": true,
"editor.suggest.preview": true,
// 保存时自动格式化
"editor.formatOnSave": true,
// ===== 模型选择 =====
// 可在 Cursor Settings > Models 中配置
// 推荐:
// Chat: claude-3.5-sonnet (推理更强)
// Edit: gpt-4o (编辑更快)
// Autocomplete: cursor-small (速度优先)
// ===== 隐私设置 =====
// 隐私模式: 代码不会被用于训练
"cursor.privacy.mode": "privacy"
}快捷键体系
┌────────────────────────────────────────────────────────────────┐
│ Cursor 快捷键完整速查表 │
├────────────────────┬───────────────────────────────────────────┤
│ 功能 │ 快捷键 (Win/Linux) │
├────────────────────┼───────────────────────────────────────────┤
│ │ === AI 核心功能 === │
│ Cmd+K 内联编辑 │ Ctrl + K │
│ Chat 对话面板 │ Ctrl + L │
│ Composer 多文件 │ Ctrl + Shift + I │
│ 接受 AI 建议 │ Tab │
│ 拒绝 AI 建议 │ Esc │
│ 查看下一个建议 │ Alt + ] │
│ │ │
│ │ === Chat 操作 === │
│ 新建 Chat │ Ctrl + L (无选中代码时) │
│ 添加代码到 Chat │ 选中代码后 Ctrl + L │
│ 添加文件到 Chat │ 在Chat中输入 @file │
│ 添加文档到 Chat │ 在Chat中输入 @doc │
│ 添加代码库到 Chat │ 在Chat中输入 @codebase │
│ │ │
│ │ === 编辑器标准 === │
│ 命令面板 │ Ctrl + Shift + P │
│ 文件搜索 │ Ctrl + P │
│ 全局搜索 │ Ctrl + Shift + F │
│ 终端切换 │ Ctrl + ` │
├────────────────────┴───────────────────────────────────────────┤
│ 提示: macOS 用户将 Ctrl 替换为 Cmd │
└────────────────────────────────────────────────────────────────┘Cmd+K 内联编辑
工作原理
Cmd+K(Windows 上为 Ctrl+K)是 Cursor 最高频使用的功能。它允许你在编辑器内直接 用自然语言描述你想要的修改,AI 会在原位生成或替换代码。
┌────────────────────────────────────────────────────────────────┐
│ Cmd+K 工作流程 │
├────────────────────────────────────────────────────────────────┤
│ │
│ 模式A: 无选中代码 (生成新代码) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. 将光标放在想插入代码的位置 │ │
│ │ 2. 按 Ctrl+K │ │
│ │ 3. 输入指令: "创建一个用户注册的Express路由" │ │
│ │ 4. AI 在光标位置生成代码 │ │
│ │ 5. 按 Tab 接受 / Esc 拒绝 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 模式B: 有选中代码 (修改现有代码) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. 选中要修改的代码块 │ │
│ │ 2. 按 Ctrl+K │ │
│ │ 3. 输入指令: "添加错误处理和输入验证" │ │
│ │ 4. AI 显示 diff 对比(红色删除/绿色新增) │ │
│ │ 5. 按 Tab 接受 / Esc 拒绝 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 模式C: 终端中使用 (生成命令) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. 在终端中按 Ctrl+K │ │
│ │ 2. 输入: "查找所有大于100MB的日志文件并删除" │ │
│ │ 3. AI 生成对应的 shell 命令 │ │
│ │ 4. 按 Enter 执行 │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘Cmd+K 实战示例
python
# ============================================================
# 示例1: 生成新代码
# 光标放在这里, 按 Ctrl+K, 输入:
# "创建一个FastAPI路由, 实现用户CRUD, 包含分页和搜索"
# ============================================================
from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel, EmailStr
from typing import Optional, List
from datetime import datetime
app = FastAPI(title="用户管理API")
# 用户数据模型
class UserCreate(BaseModel):
username: str
email: EmailStr
full_name: Optional[str] = None
class UserResponse(BaseModel):
id: int
username: str
email: str
full_name: Optional[str]
created_at: datetime
is_active: bool
class UserUpdate(BaseModel):
email: Optional[EmailStr] = None
full_name: Optional[str] = None
is_active: Optional[bool] = None
# 模拟数据库
users_db: dict = {}
next_id = 1
# 创建用户
@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
global next_id
# 检查用户名是否已存在
for existing in users_db.values():
if existing["username"] == user.username:
raise HTTPException(status_code=409, detail="用户名已存在")
user_data = {
"id": next_id,
"username": user.username,
"email": user.email,
"full_name": user.full_name,
"created_at": datetime.now(),
"is_active": True
}
users_db[next_id] = user_data
next_id += 1
return user_data
# 获取用户列表(支持分页和搜索)
@app.get("/users", response_model=List[UserResponse])
async def list_users(
page: int = Query(1, ge=1, description="页码"),
size: int = Query(10, ge=1, le=100, description="每页数量"),
search: Optional[str] = Query(None, description="搜索关键词")
):
all_users = list(users_db.values())
# 搜索过滤
if search:
all_users = [
u for u in all_users
if search.lower() in u["username"].lower()
or search.lower() in (u.get("full_name") or "").lower()
]
# 分页
start = (page - 1) * size
end = start + size
return all_users[start:end]
# 获取单个用户
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="用户不存在")
return users_db[user_id]
# 更新用户
@app.patch("/users/{user_id}", response_model=UserResponse)
async def update_user(user_id: int, user_update: UserUpdate):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="用户不存在")
user_data = users_db[user_id]
update_dict = user_update.dict(exclude_unset=True)
user_data.update(update_dict)
return user_data
# 删除用户
@app.delete("/users/{user_id}", status_code=204)
async def delete_user(user_id: int):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="用户不存在")
del users_db[user_id]python
# ============================================================
# 示例2: 选中代码后用 Cmd+K 重构
# 选中下面的函数, 按 Ctrl+K, 输入:
# "重构为async, 添加超时控制和重试逻辑"
# ============================================================
import asyncio
import aiohttp
from typing import Optional
# 重构前的简单版本:
def fetch_data_simple(url: str) -> dict:
import requests
response = requests.get(url)
return response.json()
# Cmd+K 重构后的完整版本:
async def fetch_data(
url: str,
timeout: int = 30,
max_retries: int = 3,
retry_delay: float = 1.0
) -> Optional[dict]:
"""
异步获取远程数据,支持超时和重试。
Args:
url: 请求URL
timeout: 超时时间(秒)
max_retries: 最大重试次数
retry_delay: 重试间隔(秒), 每次翻倍
Returns:
JSON响应数据, 失败返回None
"""
for attempt in range(max_retries):
try:
async with aiohttp.ClientSession() as session:
async with session.get(
url,
timeout=aiohttp.ClientTimeout(total=timeout)
) as response:
if response.status == 200:
return await response.json()
elif response.status >= 500:
# 服务端错误,可以重试
raise aiohttp.ClientError(f"服务端错误: {response.status}")
else:
# 客户端错误,不重试
print(f"请求失败: HTTP {response.status}")
return None
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
if attempt < max_retries - 1:
wait_time = retry_delay * (2 ** attempt)
print(f"第{attempt + 1}次请求失败, {wait_time}秒后重试: {e}")
await asyncio.sleep(wait_time)
else:
print(f"所有{max_retries}次请求均失败: {e}")
return None
return NoneChat 智能对话
Chat 功能详解
┌────────────────────────────────────────────────────────────────┐
│ Cursor Chat 功能架构 │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 上下文引用系统 │ │
│ │ │ │
│ │ @file 引用指定文件 │ │
│ │ @folder 引用整个文件夹 │ │
│ │ @codebase 搜索整个代码库 (语义搜索) │ │
│ │ @doc 引用外部文档 URL │ │
│ │ @git 引用 Git 变更记录 │ │
│ │ @web 联网搜索最新信息 │ │
│ │ @definitions 引用符号定义 │ │
│ │ 选中代码 自动作为上下文 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Chat 使用场景 │ │
│ │ │ │
│ │ [1] 代码理解 "解释这个函数的作用和潜在问题" │ │
│ │ [2] Bug 排查 "这段代码为什么输出和预期不一致?" │ │
│ │ [3] 方案设计 "@codebase 如何给这个项目添加缓存层?" │ │
│ │ [4] 学习提问 "这里用到了什么设计模式? 为什么?" │ │
│ │ [5] 代码审查 "审查这个PR的代码质量和安全性" │ │
│ │ [6] 性能分析 "@file:api.ts 这个文件有什么性能瓶颈?" │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Apply 按钮 │ │
│ │ │ │
│ │ Chat 回复中的代码块旁边有 "Apply" 按钮 │ │
│ │ 点击后自动将代码应用到对应文件,显示 diff 预览 │ │
│ │ 流程: Chat建议 -> Apply -> diff预览 -> Accept/Reject │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘Chat 对话示例
python
# ============================================================
# 场景: 在 Chat 中输入以下内容进行项目分析
# ============================================================
# 用户输入: "@codebase 帮我分析这个项目的数据库访问模式,
# 是否存在 N+1 查询问题?"
# Cursor Chat 会:
# 1. 扫描整个代码库的数据库相关代码
# 2. 识别 ORM 查询模式
# 3. 指出潜在的 N+1 问题
# 4. 给出修复建议
# 示例: Chat 发现的 N+1 问题
# ---- 有问题的代码 ----
class OrderService:
def get_orders_with_items(self, user_id: int):
"""获取用户的所有订单及商品 - 存在 N+1 问题"""
orders = Order.query.filter_by(user_id=user_id).all() # 1次查询
result = []
for order in orders:
items = OrderItem.query.filter_by(order_id=order.id).all() # N次查询!
result.append({
"order": order,
"items": items
})
return result # 总共 N+1 次数据库查询
# ---- Chat 建议的修复 ----
class OrderServiceOptimized:
def get_orders_with_items(self, user_id: int):
"""获取用户的所有订单及商品 - 使用 eager loading 优化"""
# 使用 joinedload 一次性加载关联数据, 只需1次查询
orders = (
Order.query
.options(joinedload(Order.items))
.filter_by(user_id=user_id)
.all()
)
return [
{"order": order, "items": order.items}
for order in orders
] # 总共只需 1 次数据库查询@doc 引用外部文档
typescript
// ============================================================
// 场景: 引用第三方库文档来生成代码
// Chat 输入: "@doc https://docs.stripe.com/api/charges
// 帮我用 Node.js 实现 Stripe 支付流程"
// ============================================================
// Cursor 会阅读 Stripe 文档并生成符合最新 API 的代码:
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16'
});
interface PaymentParams {
amount: number; // 金额(分)
currency: string; // 货币类型
customerId: string; // 客户ID
description?: string; // 描述
}
// 创建支付意图 (Payment Intent)
async function createPayment(params: PaymentParams) {
try {
const paymentIntent = await stripe.paymentIntents.create({
amount: params.amount,
currency: params.currency,
customer: params.customerId,
description: params.description,
automatic_payment_methods: {
enabled: true, // 自动启用可用的支付方式
},
});
return {
success: true,
clientSecret: paymentIntent.client_secret,
paymentIntentId: paymentIntent.id,
status: paymentIntent.status
};
} catch (error) {
if (error instanceof Stripe.errors.StripeCardError) {
return { success: false, error: '卡片被拒绝', code: error.code };
}
throw error;
}
}
// 确认支付
async function confirmPayment(paymentIntentId: string) {
const paymentIntent = await stripe.paymentIntents.retrieve(paymentIntentId);
if (paymentIntent.status === 'succeeded') {
return { success: true, message: '支付成功' };
} else if (paymentIntent.status === 'requires_action') {
return { success: false, message: '需要额外验证', requiresAction: true };
} else {
return { success: false, message: `支付状态: ${paymentIntent.status}` };
}
}
// Webhook 处理支付事件
async function handleWebhook(payload: string, signature: string) {
const event = stripe.webhooks.constructEvent(
payload,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
switch (event.type) {
case 'payment_intent.succeeded':
console.log('支付成功:', event.data.object);
break;
case 'payment_intent.payment_failed':
console.log('支付失败:', event.data.object);
break;
default:
console.log('未处理的事件类型:', event.type);
}
}Composer 多文件编辑
Composer 工作原理
┌────────────────────────────────────────────────────────────────┐
│ Composer 多文件编辑流程 │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Step 1: 打开 Composer (Ctrl+Shift+I) │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ 描述你的需求: │ │ │
│ │ │ "给这个Express项目添加JWT认证中间件, │ │ │
│ │ │ 需要修改路由文件、创建中间件文件、 │ │ │
│ │ │ 更新配置文件和添加相关测试" │ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Step 2: Composer 分析项目结构 │ │
│ │ ┌────────────────┐ ┌────────────────┐ │ │
│ │ │ 扫描文件结构 │ │ 理解依赖关系 │ │ │
│ │ │ src/ │ │ routes -> auth │ │ │
│ │ │ ├── routes/ │ │ auth -> config │ │ │
│ │ │ ├── middleware/ │ │ test -> all │ │ │
│ │ │ ├── config/ │ │ │ │ │
│ │ │ └── tests/ │ │ │ │ │
│ │ └────────────────┘ └────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Step 3: 生成多文件变更计划 │ │
│ │ │ │
│ │ [新建] src/middleware/auth.js 认证中间件 │ │
│ │ [修改] src/routes/api.js 添加认证保护 │ │
│ │ [修改] src/config/index.js 添加JWT配置 │ │
│ │ [修改] package.json 添加jsonwebtoken依赖 │ │
│ │ [新建] src/tests/auth.test.js 认证测试 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Step 4: 逐文件预览和确认 │ │
│ │ │ │
│ │ 每个文件显示 diff 对比: │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ - const express = require('express'); │ │ │
│ │ │ + const express = require('express'); │ │ │
│ │ │ + const { authenticate } = require( │ │ │
│ │ │ + '../middleware/auth' │ │ │
│ │ │ + ); │ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ [Accept All] [Accept File] [Reject] [Edit] │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘Composer 实战: 添加认证系统
javascript
// ============================================================
// Composer 生成的文件1: src/middleware/auth.js
// ============================================================
const jwt = require('jsonwebtoken');
const { JWT_SECRET, JWT_EXPIRES_IN } = require('../config');
/**
* JWT 认证中间件
* 验证请求头中的 Bearer Token
*/
function authenticate(req, res, next) {
// 从 Authorization 头获取 token
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({
error: '未提供认证令牌',
code: 'AUTH_TOKEN_MISSING'
});
}
const token = authHeader.split(' ')[1];
try {
// 验证 token
const decoded = jwt.verify(token, JWT_SECRET);
req.user = decoded; // 将用户信息附加到请求对象
next();
} catch (error) {
if (error.name === 'TokenExpiredError') {
return res.status(401).json({
error: '令牌已过期',
code: 'AUTH_TOKEN_EXPIRED'
});
}
return res.status(403).json({
error: '无效的认证令牌',
code: 'AUTH_TOKEN_INVALID'
});
}
}
/**
* 角色授权中间件
* 检查用户是否拥有指定角色
*/
function authorize(...roles) {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ error: '未认证' });
}
if (!roles.includes(req.user.role)) {
return res.status(403).json({
error: '权限不足',
required: roles,
current: req.user.role
});
}
next();
};
}
/**
* 生成 JWT 令牌
*/
function generateToken(payload) {
return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN });
}
module.exports = { authenticate, authorize, generateToken };javascript
// ============================================================
// Composer 生成的文件2: src/routes/auth.js
// ============================================================
const express = require('express');
const bcrypt = require('bcryptjs');
const { generateToken, authenticate } = require('../middleware/auth');
const router = express.Router();
// 模拟用户数据库
const users = new Map();
// POST /auth/register - 用户注册
router.post('/register', async (req, res) => {
try {
const { username, email, password } = req.body;
// 参数验证
if (!username || !email || !password) {
return res.status(400).json({ error: '缺少必填字段' });
}
// 检查用户是否已存在
if (users.has(email)) {
return res.status(409).json({ error: '邮箱已注册' });
}
// 加密密码
const salt = await bcrypt.genSalt(12);
const hashedPassword = await bcrypt.hash(password, salt);
// 存储用户
const user = {
id: users.size + 1,
username,
email,
password: hashedPassword,
role: 'user',
createdAt: new Date()
};
users.set(email, user);
// 生成令牌
const token = generateToken({
userId: user.id,
email: user.email,
role: user.role
});
res.status(201).json({
message: '注册成功',
token,
user: { id: user.id, username, email, role: user.role }
});
} catch (error) {
res.status(500).json({ error: '服务器内部错误' });
}
});
// POST /auth/login - 用户登录
router.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
const user = users.get(email);
if (!user) {
return res.status(401).json({ error: '邮箱或密码错误' });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(401).json({ error: '邮箱或密码错误' });
}
const token = generateToken({
userId: user.id,
email: user.email,
role: user.role
});
res.json({
message: '登录成功',
token,
user: { id: user.id, username: user.username, email, role: user.role }
});
} catch (error) {
res.status(500).json({ error: '服务器内部错误' });
}
});
// GET /auth/me - 获取当前用户信息(需要认证)
router.get('/me', authenticate, (req, res) => {
const user = users.get(req.user.email);
if (!user) {
return res.status(404).json({ error: '用户不存在' });
}
res.json({
id: user.id,
username: user.username,
email: user.email,
role: user.role
});
});
module.exports = router;与GitHub Copilot对比
功能对比矩阵
┌────────────────────────────────────────────────────────────────────┐
│ Cursor vs GitHub Copilot 深度对比 │
├────────────────┬────────────────────┬──────────────────────────────┤
│ 对比维度 │ Cursor │ GitHub Copilot │
├────────────────┼────────────────────┼──────────────────────────────┤
│ 产品形态 │ 独立编辑器(VS Code │ IDE 插件 │
│ │ 分叉) │ │
│ AI 模型 │ GPT-4o / Claude / │ OpenAI Codex (专用) │
│ │ 可选模型 │ │
│ 代码补全 │ Tab 补全 │ Tab 补全 (更成熟) │
│ 内联编辑 │ Cmd+K (核心优势) │ 无 │
│ Chat 功能 │ Ctrl+L (强) │ Copilot Chat (强) │
│ 多文件编辑 │ Composer (核心优势)│ 无 │
│ 代码库理解 │ @codebase 索引 │ @workspace (较弱) │
│ 外部文档 │ @doc URL引用 │ 无 │
│ 联网搜索 │ @web 支持 │ 无 │
│ 终端集成 │ Ctrl+K in Terminal │ @terminal │
│ 隐私模式 │ 支持 │ 企业版支持 │
│ 价格 │ $20/月 (Pro) │ $10/月 (Individual) │
│ 学习曲线 │ 需要适应新编辑器 │ 在现有IDE中使用 │
├────────────────┴────────────────────┴──────────────────────────────┤
│ │
│ 选择建议: │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 选 Cursor 如果: │ │
│ │ - 需要频繁的代码重构和多文件修改 │ │
│ │ - 想要更强的代码库级别理解 │ │
│ │ - 愿意尝试 AI 原生的编辑器体验 │ │
│ │ - 需要引用外部文档生成代码 │ │
│ │ │ │
│ │ 选 Copilot 如果: │ │
│ │ - 不想离开熟悉的 IDE (特别是JetBrains用户) │ │
│ │ - 主要需求是代码补全 │ │
│ │ - 已有 GitHub 企业版订阅 │ │
│ │ - 团队统一使用 Copilot 且有组织策略管控需求 │ │
│ └──────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────┘高级技巧与工作流
.cursorrules 项目规则
┌────────────────────────────────────────────────────────────────┐
│ .cursorrules 项目级AI规则配置 │
├────────────────────────────────────────────────────────────────┤
│ │
│ 在项目根目录创建 .cursorrules 文件 │
│ Cursor 会在每次 AI 请求时自动注入这些规则 │
│ 相当于给 AI 一份"项目编码规范手册" │
│ │
│ 作用: │
│ - 统一团队的AI输出风格 │
│ - 减少重复的Prompt说明 │
│ - 确保生成代码符合项目架构 │
│ - 强制安全和最佳实践 │
└────────────────────────────────────────────────────────────────┘markdown
<!-- 示例 .cursorrules 文件内容 -->
# 项目规范
## 技术栈
- 后端: Python 3.11 + FastAPI + SQLAlchemy 2.0
- 前端: React 18 + TypeScript + TailwindCSS
- 数据库: PostgreSQL 15
- 缓存: Redis
## 编码规范
- Python 使用 Google 风格的 docstring
- 所有函数必须有类型提示
- 使用 async/await 而非同步代码
- 错误处理使用自定义异常类, 不要用通用 Exception
- 变量命名使用 snake_case, 类名使用 PascalCase
## 项目结构
- API 路由放在 src/routes/ 目录
- 业务逻辑放在 src/services/ 目录
- 数据模型放在 src/models/ 目录
- 工具函数放在 src/utils/ 目录
## 安全要求
- 所有用户输入必须验证和清洗
- 数据库查询必须使用参数化查询
- 敏感配置必须从环境变量读取
- API 响应不得泄露内部实现细节
## 测试要求
- 每个 Service 函数都要有对应的单元测试
- 测试文件命名: test_[模块名].py
- 使用 pytest + pytest-asyncio高效工作流模式
┌────────────────────────────────────────────────────────────────┐
│ Cursor 日常开发工作流 │
├────────────────────────────────────────────────────────────────┤
│ │
│ 阶段1: 需求理解 (Chat) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ "@codebase 当前项目的架构是什么? │ │
│ │ 我需要添加一个通知系统, 应该如何设计?" │ │
│ └──────────────────────────────────────────────────────────┘ │
│ | │
│ v │
│ 阶段2: 代码生成 (Composer) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ "根据刚才的设计方案, 创建通知服务相关的所有文件: │ │
│ │ 模型、服务层、路由、测试" │ │
│ └──────────────────────────────────────────────────────────┘ │
│ | │
│ v │
│ 阶段3: 细节调整 (Cmd+K) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 选中生成的代码, Cmd+K: │ │
│ │ "添加邮件和短信两种通知渠道" │ │
│ │ "给这个函数添加限流逻辑, 每用户每分钟最多10条" │ │
│ └──────────────────────────────────────────────────────────┘ │
│ | │
│ v │
│ 阶段4: 审查优化 (Chat) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 选中所有新增代码, Ctrl+L: │ │
│ │ "审查这段代码的安全性、性能和可维护性" │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘实战项目案例
用 Composer 搭建 REST API 脚手架
python
# ============================================================
# Composer 指令:
# "创建一个完整的 FastAPI 项目结构, 包含:
# 1. 用户认证 (JWT)
# 2. 数据库模型 (SQLAlchemy)
# 3. CRUD 路由
# 4. 请求验证 (Pydantic)
# 5. 错误处理中间件
# 6. 日志配置"
#
# Composer 会一次性生成以下所有文件:
# ============================================================
# --- 文件: src/models/user.py ---
from sqlalchemy import Column, Integer, String, Boolean, DateTime
from sqlalchemy.sql import func
from src.database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True, nullable=False, index=True)
email = Column(String(100), unique=True, nullable=False, index=True)
hashed_password = Column(String(255), nullable=False)
full_name = Column(String(100))
is_active = Column(Boolean, default=True)
is_admin = Column(Boolean, default=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
# --- 文件: src/schemas/user.py ---
from pydantic import BaseModel, EmailStr
from typing import Optional
from datetime import datetime
class UserBase(BaseModel):
username: str
email: EmailStr
full_name: Optional[str] = None
class UserCreate(UserBase):
password: str
class UserUpdate(BaseModel):
email: Optional[EmailStr] = None
full_name: Optional[str] = None
is_active: Optional[bool] = None
class UserResponse(UserBase):
id: int
is_active: bool
created_at: datetime
class Config:
from_attributes = True
# --- 文件: src/middleware/error_handler.py ---
from fastapi import Request
from fastapi.responses import JSONResponse
import logging
logger = logging.getLogger(__name__)
class AppException(Exception):
"""自定义应用异常基类"""
def __init__(self, status_code: int, detail: str, error_code: str = None):
self.status_code = status_code
self.detail = detail
self.error_code = error_code
class NotFoundError(AppException):
def __init__(self, resource: str):
super().__init__(404, f"{resource}不存在", "NOT_FOUND")
class ConflictError(AppException):
def __init__(self, message: str):
super().__init__(409, message, "CONFLICT")
class UnauthorizedError(AppException):
def __init__(self, message: str = "未授权"):
super().__init__(401, message, "UNAUTHORIZED")
async def app_exception_handler(request: Request, exc: AppException):
logger.warning(f"AppException: {exc.detail} | Path: {request.url.path}")
return JSONResponse(
status_code=exc.status_code,
content={
"error": exc.detail,
"code": exc.error_code,
"path": str(request.url.path)
}
)总结
本教程涵盖了 Cursor 编辑器的核心内容:
- 核心优势: AI 原生编辑器,三大核心功能(Cmd+K / Chat / Composer)深度融合
- 安装配置: 从 VS Code 无缝迁移,模型选择和隐私设置
- Cmd+K: 最高频功能,无选中生成代码/选中修改代码/终端命令生成
- Chat: @上下文引用系统(@codebase/@file/@doc/@web),Apply一键应用
- Composer: 多文件编辑的核心武器,适合大规模代码变更和项目脚手架搭建
- 与Copilot对比: Cursor 在多文件编辑和代码库理解方面优势明显
- 高级技巧: .cursorrules 项目规则、四阶段工作流、上下文管理
参考资源
创建时间: 2024-01-15 最后更新: 2024-01-15
💬 讨论
使用 GitHub 账号登录后即可参与讨论