
最近在技术社区看到很多开发者对AI编程工具Cursor充满好奇但苦于缺乏一个完整的实战项目来系统掌握。恰好结合当下热门的“外卖”、“跑腿”类应用场景我们完全可以利用Cursor从零开始构建一个简化版的“死了么”APP。这不仅能让你深入理解Cursor在真实项目开发中的威力更能串联起前端、后端、数据库设计、API联调等全栈技能。本文将全程记录开发过程提供保姆级教学无论你是想学习Cursor还是想了解一个APP从想法到上线的完整流程都能在这里找到答案。1. 背景与核心概念为什么是Cursor与“死了么”在开始敲代码之前我们有必要厘清两个核心概念我们使用的工具Cursor和我们要构建的产品“死了么”APP。1.1 CursorAI驱动的下一代IDECursor不仅仅是一个代码编辑器它深度融合了GPT-4等大型语言模型将自然语言理解能力直接带入了编码环境。这意味着你可以通过对话的方式让AI帮你生成代码、解释代码、重构代码、修复Bug甚至编写测试用例。对于本教程而言Cursor将扮演“超级助手”的角色极大地提升我们从零搭建一个应用的原型速度和代码质量。核心优势对话式编程用中文或英文描述你的需求AI生成对应代码块。智能补全与重构基于上下文提供远超传统IDE的代码建议。内联聊天与编辑无需切换窗口直接在代码文件旁与AI讨论问题。项目级理解AI能理解你整个项目的结构提供更精准的建议。1.2 “死了么”APP一个经典的产品原型“死了么”是一个戏谑化的名称其本质是一个模仿“饿了么”、“美团外卖”的简化版外卖/服务订购平台。选择它作为实战项目原因如下业务场景熟悉用户、商家、订单、支付等核心模块清晰易于理解。技术栈全面涉及移动端前端、服务端后端、数据库、第三方API如地图、支付集成是一个典型的中小型全栈项目。需求明确功能列表容易定义便于我们分模块开发。高热度与实用性此类O2O应用开发经验在求职和实际工作中极具价值。核心功能模块用户端注册登录、商家浏览、商品展示、购物车、下单、订单跟踪、支付模拟、评价。商家端商品管理、订单管理、营业状态设置。平台端后台用户管理、商家审核、订单监控、数据统计简化。通过这个项目我们将演示如何利用Cursor将上述产品需求一步步转化为可运行的代码。2. 环境准备与版本说明工欲善其事必先利其器。在开始编码前请确保你的开发环境已就绪。2.1 核心工具安装与配置Cursor Editor下载访问Cursor官网下载对应操作系统Windows/macOS/Linux的安装包。安装按照向导完成安装。设置中文可选Cursor原生支持中文。如果界面是英文可以按Cmd/Ctrl Shift P打开命令面板输入Configure Display Language选择zh-cn并重启。这是很多新手关心的“cursor设置中文”问题。登录与模型选择启动Cursor后你需要登录注册时手机号填写按提示操作即可。在设置中确保已配置好AI模型如GPT-4。注意免费额度合理使用。Node.js npm我们的后端将使用Node.jsExpress框架前端使用React Native或Vue.js 小程序本文以React Native为例。版本建议安装LTS版本如Node.js 18.x 或 20.x。验证打开终端运行node -v和npm -v检查是否安装成功。数据库我们选择轻量且强大的MySQL作为主数据库并使用Redis作为缓存和会话存储。MySQL版本 8.0。可通过官网安装或使用Docker快速部署。Redis版本 6.x。同样推荐使用Docker安装。移动端开发环境React Native如果你选择开发原生APP需要配置React Native环境Android Studio / Xcode。考虑到教程的普适性我们将优先开发管理后台和API移动端UI部分主要用Cursor生成示例代码重点在于接口联调。你可以根据生成的代码在模拟器或真机上运行。API测试工具Postman或Insomnia用于测试我们编写的后端接口。2.2 项目初始化与结构预览我们将创建一个名为sileme的项目。打开终端执行以下命令# 创建项目根目录 mkdir sileme cd sileme # 初始化后端项目 (使用 Express 生成器快速搭建) npx express-generator server --no-view --git cd server npm install # 安装常用依赖 npm install mysql2 sequelize redis jsonwebtoken bcryptjs cors dotenv # mysql2: MySQL驱动 # sequelize: ORM工具用于操作数据库 # redis: Redis客户端 # jsonwebtoken: 用于生成JWT令牌 # bcryptjs: 密码加密 # cors: 处理跨域 # dotenv: 环境变量管理 # 回到根目录创建前端管理后台使用Vite React cd .. npm create vitelatest admin -- --template react cd admin npm install # 安装UI库和路由以Ant Design为例 npm install antd ant-design/icons axios react-router-dom至此我们的项目骨架已经建立。目录结构大致如下sileme/ ├── server/ # Node.js 后端服务 │ ├── app.js # Express应用主文件 │ ├── routes/ # 路由定义 │ ├── models/ # Sequelize 数据模型 │ ├── controllers/ # 控制器处理业务逻辑 │ ├── services/ # 服务层复杂业务封装 │ ├── utils/ # 工具函数如JWT、加密 │ ├── config/ # 配置文件数据库、Redis │ └── package.json ├── admin/ # React 管理后台前端 │ ├── src/ │ │ ├── pages/ # 页面组件 │ │ ├── components/ # 公共组件 │ │ ├── utils/ # 前端工具如请求封装 │ │ └── App.jsx │ └── package.json └── README.md3. 核心开发流程拆解与Cursor实战接下来我们将分模块开发。在每个环节我都会展示如何利用Cursor来辅助我们高效完成编码。3.1 数据库设计与模型定义首先我们需要设计数据库表。打开Cursor在server目录下新建一个docs/db_design.md文件用自然语言描述我们的需求。在Cursor中输入符号可以引用文件或选择代码后与AI对话“请根据一个外卖平台‘死了么’的需求设计MySQL数据库表。需要包含用户表users、商家表shops、商品表products、订单表orders、订单商品明细表order_items。请给出每个表的字段、类型、注释和主要索引。”Cursor可能会生成类似以下的设计-- 用户表 CREATE TABLE users ( id int NOT NULL AUTO_INCREMENT COMMENT 用户ID, username varchar(50) NOT NULL COMMENT 用户名, phone varchar(20) NOT NULL COMMENT 手机号, password_hash varchar(255) NOT NULL COMMENT 加密后的密码, avatar varchar(500) DEFAULT NULL COMMENT 头像URL, balance decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT 账户余额, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uniq_phone (phone), KEY idx_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci COMMENT用户表; -- 商家表 CREATE TABLE shops ( id int NOT NULL AUTO_INCREMENT COMMENT 商家ID, name varchar(100) NOT NULL COMMENT 店铺名称, description text COMMENT 店铺描述, address varchar(500) NOT NULL COMMENT 店铺地址, latitude decimal(10,8) DEFAULT NULL COMMENT 纬度, longitude decimal(11,8) DEFAULT NULL COMMENT 经度, status tinyint NOT NULL DEFAULT 1 COMMENT 状态0-休息1-营业, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci COMMENT商家表; -- ... 其他表设计得到SQL后我们可以在MySQL中执行。接着我们需要在Node.js项目中定义Sequelize模型。在server/models目录下我们可以让Cursor帮忙创建user.model.js。在user.model.js文件中选中注释区域按Cmd/Ctrl K调出AI指令框输入“根据上面的SQL用Sequelize定义一个User模型包含所有字段、数据类型和验证规则。”Cursor会生成类似代码// filepath: server/models/user.model.js const { DataTypes } require(sequelize); const sequelize require(../config/database); // 假设数据库配置在此 const User sequelize.define(User, { id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, comment: 用户ID }, username: { type: DataTypes.STRING(50), allowNull: false, comment: 用户名, validate: { notEmpty: true } }, phone: { type: DataTypes.STRING(20), allowNull: false, unique: true, comment: 手机号, validate: { is: /^1[3-9]\d{9}$/ // 简单的手机号格式验证 } }, passwordHash: { type: DataTypes.STRING(255), allowNull: false, comment: 加密后的密码, field: password_hash // 映射到数据库中的蛇形命名字段 }, avatar: { type: DataTypes.STRING(500), comment: 头像URL, validate: { isUrl: true } }, balance: { type: DataTypes.DECIMAL(10, 2), allowNull: false, defaultValue: 0.00, comment: 账户余额 } }, { tableName: users, timestamps: true, // 自动管理 createdAt 和 updatedAt createdAt: created_at, updatedAt: updated_at, comment: 用户表 }); module.exports User;用同样的方法我们可以快速生成其他模型Shop, Product, Order, OrderItem。3.2 后端API开发用户注册登录模块这是任何APP的起点。我们来实现POST /api/auth/register和POST /api/auth/login。步骤1创建路由和控制器在server/routes下创建auth.routes.js在server/controllers下创建auth.controller.js。步骤2利用Cursor编写控制器逻辑在auth.controller.js中我们可以这样向Cursor提问“请实现一个用户注册控制器。它需要1. 接收username, phone, password参数。2. 检查手机号是否已存在。3. 使用bcryptjs对密码进行哈希加密。4. 将用户数据存入数据库。5. 成功则返回用户基本信息不含密码和JWT token失败则返回相应错误信息。”Cursor生成的代码可能如下需稍作调整和补全// filepath: server/controllers/auth.controller.js const bcrypt require(bcryptjs); const jwt require(jsonwebtoken); const { User } require(../models); const register async (req, res) { try { const { username, phone, password } req.body; // 1. 基础验证 if (!username || !phone || !password) { return res.status(400).json({ message: 用户名、手机号和密码均为必填项 }); } // 2. 检查手机号是否已注册 const existingUser await User.findOne({ where: { phone } }); if (existingUser) { return res.status(409).json({ message: 该手机号已注册 }); } // 3. 加密密码 const salt await bcrypt.genSalt(10); const passwordHash await bcrypt.hash(password, salt); // 4. 创建用户 const newUser await User.create({ username, phone, passwordHash, balance: 0.00 }); // 5. 生成JWT Token (假设密钥存储在环境变量JWT_SECRET中) const token jwt.sign( { userId: newUser.id, phone: newUser.phone }, process.env.JWT_SECRET, { expiresIn: 7d } ); // 6. 返回成功响应剔除敏感信息 res.status(201).json({ message: 注册成功, user: { id: newUser.id, username: newUser.username, phone: newUser.phone, balance: newUser.balance }, token }); } catch (error) { console.error(注册错误:, error); res.status(500).json({ message: 服务器内部错误, error: error.message }); } }; const login async (req, res) { try { const { phone, password } req.body; // ... 类似的Cursor可以帮你完成登录逻辑查找用户、比对密码、生成token } catch (error) { // 错误处理 } }; module.exports { register, login };步骤3关联路由和全局配置在auth.routes.js中定义路由并在app.js中注册路由、配置JSON解析、CORS等中间件。这些结构化的代码都可以让Cursor协助生成。3.3 前端管理后台商家列表页面后端API完成后我们来快速搭建一个管理后台页面用于管理商家。我们将使用React Ant Design。在admin/src/pages/ShopList.jsx中我们可以向Cursor描述需求“创建一个商家管理页面使用Ant Design的Table组件。需要展示商家ID、名称、地址、状态营业/休息并提供操作列编辑和删除按钮。顶部有搜索框按名称搜索和一个‘新增商家’按钮。数据通过调用/api/shops接口获取使用axios。”Cursor会生成一个功能丰富的组件骨架// filepath: admin/src/pages/ShopList.jsx import React, { useState, useEffect } from react; import { Table, Button, Input, Space, Tag, message, Popconfirm } from antd; import { SearchOutlined, PlusOutlined, EditOutlined, DeleteOutlined } from ant-design/icons; import axios from axios; const ShopList () { const [data, setData] useState([]); const [loading, setLoading] useState(false); const [searchText, setSearchText] useState(); const [pagination, setPagination] useState({ current: 1, pageSize: 10, total: 0 }); const fetchShops async (params {}) { setLoading(true); try { const response await axios.get(/api/shops, { params }); setData(response.data.list || response.data); setPagination({ ...pagination, total: response.data.total || (response.data.list || []).length, }); } catch (error) { message.error(获取商家列表失败); console.error(error); } finally { setLoading(false); } }; useEffect(() { fetchShops(); }, []); const handleSearch (value) { setSearchText(value); fetchShops({ name: value, page: 1, pageSize: pagination.pageSize }); }; const handleDelete async (id) { try { await axios.delete(/api/shops/${id}); message.success(删除成功); fetchShops(); // 刷新列表 } catch (error) { message.error(删除失败); } }; const columns [ { title: ID, dataIndex: id, key: id, width: 80, }, { title: 店铺名称, dataIndex: name, key: name, }, { title: 地址, dataIndex: address, key: address, ellipsis: true, }, { title: 状态, dataIndex: status, key: status, render: (status) ( Tag color{status 1 ? green : red} {status 1 ? 营业中 : 已休息} /Tag ), }, { title: 操作, key: action, render: (_, record) ( Space sizemiddle Button typelink icon{EditOutlined /} onClick{() handleEdit(record)} 编辑 /Button Popconfirm title确定要删除这个商家吗 onConfirm{() handleDelete(record.id)} okText确定 cancelText取消 Button typelink danger icon{DeleteOutlined /} 删除 /Button /Popconfirm /Space ), }, ]; return ( div Space style{{ marginBottom: 16 }} Input placeholder搜索商家名称 prefix{SearchOutlined /} value{searchText} onChange{(e) setSearchText(e.target.value)} onPressEnter{(e) handleSearch(e.target.value)} style{{ width: 300 }} / Button typeprimary icon{PlusOutlined /} onClick{() {/* 跳转到新增页面 */}} 新增商家 /Button /Space Table columns{columns} dataSource{data} rowKeyid loading{loading} pagination{{ ...pagination, onChange: (page, pageSize) { setPagination({ ...pagination, current: page, pageSize }); fetchShops({ page, pageSize, name: searchText }); }, }} / /div ); }; export default ShopList;这个组件已经具备了列表、搜索、分页、删除等核心功能。你只需要补充handleEdit函数和新增页面的路由即可。4. 完整实战案例从下单到支付的业务流程让我们串联起核心业务用户下单。这个过程涉及多个模型和复杂的业务逻辑是检验我们设计的好机会。4.1 数据库事务与订单创建订单创建必须保证数据一致性库存检查、订单主表、明细表、用户余额等。我们使用Sequelize的事务Transaction来处理。在server/controllers/order.controller.js中我们可以这样利用Cursor选中代码区域输入“请实现一个创建订单的控制器。业务逻辑1. 从JWT token中获取用户ID。2. 接收参数商家ID配送地址商品列表含商品ID和数量。3. 开启一个Sequelize事务。4. 在事务内验证商家状态、验证每个商品的库存和价格、计算总金额、检查用户余额、扣减库存、扣减用户余额、创建订单主记录、创建订单明细记录。5. 所有步骤成功则提交事务返回订单信息任何一步失败则回滚事务返回错误。”Cursor会生成一个包含事务处理的复杂函数框架你需要根据你的模型名称进行调整。核心代码结构如下const createOrder async (req, res) { const t await sequelize.transaction(); // 获取事务对象 try { const userId req.user.userId; // 假设用户信息已通过中间件附加到req const { shopId, deliveryAddress, items } req.body; // 1. 验证商家 const shop await Shop.findByPk(shopId, { transaction: t }); if (!shop || shop.status ! 1) { await t.rollback(); return res.status(400).json({ message: 商家不存在或未营业 }); } // 2. 验证商品、计算总价、扣库存 let totalAmount 0; const orderItems []; for (const item of items) { const product await Product.findByPk(item.productId, { transaction: t, lock: t.LOCK.UPDATE }); // 加锁防止超卖 if (!product || product.stock item.quantity) { await t.rollback(); return res.status(400).json({ message: 商品 ${product?.name || item.productId} 库存不足或不存在 }); } totalAmount product.price * item.quantity; // 扣减库存 product.stock - item.quantity; await product.save({ transaction: t }); orderItems.push({ productId: product.id, quantity: item.quantity, price: product.price, productName: product.name, }); } // 3. 检查并扣减用户余额 const user await User.findByPk(userId, { transaction: t, lock: t.LOCK.UPDATE }); if (user.balance totalAmount) { await t.rollback(); return res.status(400).json({ message: 用户余额不足 }); } user.balance - totalAmount; await user.save({ transaction: t }); // 4. 创建订单 const order await Order.create({ userId, shopId, totalAmount, deliveryAddress, status: pending, // 待支付/待接单等 }, { transaction: t }); // 5. 创建订单明细 const itemsWithOrderId orderItems.map(it ({ ...it, orderId: order.id })); await OrderItem.bulkCreate(itemsWithOrderId, { transaction: t }); // 6. 提交事务 await t.commit(); // 7. 可能触发后续操作如发送通知可放入消息队列 // sendNotification(userId, 您的订单#${order.id}已创建成功); res.status(201).json({ message: 订单创建成功, orderId: order.id, totalAmount, }); } catch (error) { // 如果事务已开始则回滚 if (t !t.finished) { await t.rollback(); } console.error(创建订单失败:, error); res.status(500).json({ message: 创建订单失败, error: error.message }); } };4.2 模拟支付回调接口在真实场景中支付涉及与微信支付、支付宝等第三方对接。作为演示我们实现一个简单的模拟支付回调接口。在Cursor辅助下我们可以快速写出// filepath: server/controllers/payment.controller.js const { Order } require(../models); const mockPaymentCallback async (req, res) { try { const { orderId, payStatus } req.body; // payStatus: success or failed const order await Order.findByPk(orderId); if (!order) { return res.status(404).json({ message: 订单不存在 }); } if (order.status ! pending) { return res.status(400).json({ message: 订单状态不允许支付 }); } // 模拟支付处理 if (payStatus success) { order.status paid; // 更新为已支付 order.paidAt new Date(); await order.save(); // 这里可以触发商家接单逻辑 return res.json({ message: 支付成功, order }); } else { // 支付失败可能需要将用户余额加回去更复杂的业务需要另外处理 // 本例简化处理仅标记订单为支付失败 order.status payment_failed; await order.save(); return res.json({ message: 支付失败, order }); } } catch (error) { console.error(支付回调处理失败:, error); res.status(500).json({ message: 处理支付回调失败 }); } };5. 常见问题与排查思路Cursor帮你排错在开发过程中你一定会遇到各种错误。Cursor同样可以成为你的“调试助手”。问题现象可能原因Cursor辅助排查思路Error: connect ECONNREFUSED 127.0.0.1:3306MySQL服务未启动或连接配置错误。将错误信息复制给Cursor它会建议你1. 检查MySQL服务状态。2. 核对config/database.js中的host, port, username, password。3. 测试用命令行连接数据库。SequelizeUniqueConstraintError插入了重复的唯一键数据如已注册的手机号。Cursor会解释这个错误并建议你在控制器中添加唯一性校验或在数据库层面处理。JWT token is invalidToken过期、密钥不匹配、或未在请求头中正确传递。询问Cursor“Express中如何正确设置JWT验证中间件”它会给出完整的中间件代码示例并提醒你检查请求头Authorization: Bearer token。前端调用API跨域CORS错误后端未正确配置CORS。告诉Cursor“我的Express应用出现了CORS错误如何解决”它会指导你安装cors包并在app.js中正确使用app.use(cors())。React页面渲染时报Cannot read properties of undefined异步数据未加载完成时就尝试访问其属性。将组件代码和错误信息发给Cursor它会建议你使用可选链操作符?.或增加条件渲染{data Component data{data} /}。npm install时某些包安装失败网络问题、node版本不兼容、或包已废弃。将错误日志复制给Cursor它会分析原因并可能建议你使用npm cache clean --force切换npm源或检查package.json中的版本范围。如何使用Cursor排错复制完整的错误信息包括堆栈跟踪。在Cursor中将错误信息粘贴并描述你正在做什么。Cursor会分析错误给出可能的原因和修复步骤。对于复杂问题可以打开相关文件用Cmd/Ctrl L选中问题代码块再按Cmd/Ctrl K询问AI。6. 最佳实践与工程建议通过这个项目我们不仅学会了功能开发更要积累工程经验。6.1 代码组织与分层清晰的分层我们采用了routes - controllers - services - models的分层结构。控制器只负责接收请求和返回响应复杂的业务逻辑应放在services层。这使代码更易测试和维护。统一的响应格式建议创建一个中间件或工具函数统一API的响应格式如{ code: 200, data: {}, message: success }。错误处理中间件在Express中使用一个统一的错误处理中间件app.use((err, req, res, next) { ... })来捕获和处理所有未预期的错误避免服务器暴露内部信息。6.2 安全与性能密码存储务必使用bcryptjs等专业库进行哈希加盐存储绝对禁止明文存储密码。JWT安全Token应设置合理的过期时间并存储在HTTP Only的Cookie或安全的客户端存储中。敏感操作应使用刷新令牌机制。SQL注入使用Sequelize等ORM框架本身已通过参数化查询避免了大部分注入风险。切勿手动拼接SQL字符串。API限流与鉴权对登录、注册、下单等接口实施限流如使用express-rate-limit。所有需要身份验证的接口必须通过JWT中间件校验。事务使用对于涉及多表更新的核心业务如下单、支付必须使用数据库事务保证原子性。缓存策略商家列表、商品信息等不常变的数据可以使用Redis缓存显著降低数据库压力。6.3 利用Cursor提升效率的窍门生成测试数据可以让Cursor为你生成用于填充数据库的模拟数据脚本。编写API文档描述你的API让Cursor帮你生成符合OpenAPI规范的YAML或Markdown文档。代码重构选中一段冗长的函数让Cursor“将其重构得更简洁、可读性更高”。编写单元测试提供你的函数让Cursor为你生成对应的Jest或Mocha测试用例。解释复杂代码遇到看不懂的第三方库代码选中它让Cursor为你逐行解释。6.4 项目部署与上线考虑环境变量将数据库密码、JWT密钥、第三方API密钥等敏感信息存入.env文件并通过dotenv加载。切记将.env加入.gitignore。日志记录使用winston或morgan记录应用日志便于问题追踪。进程管理生产环境使用PM2来管理Node.js进程保证应用崩溃后自动重启。数据库备份建立定时的MySQL数据库备份机制。前端构建React管理后台使用npm run build生成静态文件并通过Nginx等Web服务器部署。从环境搭建、数据库设计、API开发、前端界面到部署上线我们利用Cursor完成了一个简化版“死了么”APP的核心开发流程。这个过程中Cursor极大地提升了代码编写、问题排查和知识查询的效率。但请记住AI是一个强大的助手而不是替代者。你对业务的理解、对架构的设计、对异常情况的处理才是项目的基石。建议你以本项目为起点尝试添加更多功能如实时订单推送WebSocket、智能推荐算法、数据分析看板等在实践中不断深化全栈开发能力。