1. 项目概述
作为一名长期从事全栈开发的技术博主,今天想和大家分享一个基于Node.js的大众点评美食版小程序开发经验。这个项目是我最近指导的一位计算机专业学生的毕业设计作品,包含了完整的前后端代码、说明文档和论文,非常适合作为课程设计或毕业设计的参考案例。
这个小程序主要实现了美食点餐下单的核心功能,采用了前后端分离的架构设计。前端使用微信小程序原生框架开发,后端基于Node.js构建,数据库选用MySQL。整个项目从需求分析到最终上线测试,完整覆盖了软件开发的整个生命周期。
2. 技术架构设计
2.1 整体架构设计
系统采用典型的三层架构设计:
- 表现层:微信小程序前端界面
- 业务逻辑层:Node.js后端服务
- 数据访问层:MySQL数据库
这种分层架构使得系统各组件职责明确,便于维护和扩展。前后端通过RESTful API进行通信,数据格式采用JSON。
2.2 前端技术选型
前端选择微信小程序原生框架开发,主要考虑以下几点:
- 开发效率高:小程序提供了丰富的组件和API,可以快速实现功能
- 用户体验好:小程序在微信生态内运行流畅,无需安装
- 跨平台:一套代码可同时运行在iOS和Android平台
2.3 后端技术选型
后端选用Node.js作为主要技术栈,具体包括:
- Express框架:轻量级的Web应用框架
- Sequelize ORM:用于操作MySQL数据库
- JWT认证:实现用户登录鉴权
- Redis缓存:提升系统性能
选择Node.js主要基于其非阻塞I/O模型和高并发处理能力,非常适合餐饮类应用的高并发场景。
3. 核心功能实现
3.1 用户系统模块
用户系统是整个小程序的基础,实现了以下功能:
- 注册登录:支持手机号+验证码和微信一键登录两种方式
- 个人信息管理:用户可以修改昵称、头像等基本信息
- 地址管理:保存常用配送地址
javascript复制// 用户注册接口示例
router.post('/register', async (req, res) => {
try {
const { phone, code, password } = req.body;
// 验证短信验证码
const isValid = await verifySmsCode(phone, code);
if (!isValid) {
return res.status(400).json({ message: '验证码错误' });
}
// 创建用户
const user = await User.create({
phone,
password: bcrypt.hashSync(password, 10)
});
res.json(user);
} catch (error) {
res.status(500).json({ message: error.message });
}
});
3.2 商家展示模块
商家展示是小程序的核心功能之一:
- 商家列表:按距离、评分、销量等排序
- 商家详情:展示商家信息、菜品、评价等
- 搜索功能:支持关键词搜索和分类筛选
javascript复制// 获取附近商家接口
router.get('/restaurants/nearby', async (req, res) => {
const { longitude, latitude, page = 1, pageSize = 10 } = req.query;
const offset = (page - 1) * pageSize;
const restaurants = await Restaurant.findAll({
where: sequelize.where(
sequelize.fn('ST_Distance_Sphere',
sequelize.col('location'),
sequelize.fn('ST_GeomFromText', `POINT(${longitude} ${latitude})`)
),
{ [sequelize.Op.lte]: 5000 } // 5公里范围内
),
order: [['rating', 'DESC']],
limit: parseInt(pageSize),
offset: parseInt(offset)
});
res.json(restaurants);
});
3.3 点餐下单模块
点餐下单是系统的核心业务流程:
- 购物车管理:添加、删除、修改菜品
- 订单创建:选择配送地址、支付方式
- 订单支付:集成微信支付接口
- 订单状态跟踪:实时更新订单状态
javascript复制// 创建订单接口
router.post('/orders', auth, async (req, res) => {
const { restaurantId, items, addressId, remark } = req.body;
const userId = req.user.id;
// 计算总价
const restaurant = await Restaurant.findByPk(restaurantId);
const menuItems = await MenuItem.findAll({
where: { id: items.map(item => item.id) }
});
let total = 0;
const orderItems = items.map(item => {
const menuItem = menuItems.find(m => m.id === item.id);
total += menuItem.price * item.quantity;
return {
menuItemId: item.id,
quantity: item.quantity,
price: menuItem.price
};
});
// 创建订单
const order = await Order.create({
userId,
restaurantId,
addressId,
total,
status: 'pending',
remark
});
// 添加订单项
await OrderItem.bulkCreate(
orderItems.map(item => ({
...item,
orderId: order.id
}))
);
res.json(order);
});
4. 数据库设计
4.1 主要数据表结构
系统设计了以下核心数据表:
- 用户表(users):存储用户基本信息
- 商家表(restaurants):记录商家信息
- 菜品表(menu_items):存储菜单项
- 订单表(orders):记录订单主信息
- 订单项表(order_items):记录订单明细
4.2 关键表字段设计
商家表(restaurants)设计:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | INT | 主键 |
| name | VARCHAR(100) | 商家名称 |
| address | VARCHAR(255) | 商家地址 |
| phone | VARCHAR(20) | 联系电话 |
| rating | DECIMAL(2,1) | 评分 |
| location | POINT | 地理位置坐标 |
| business_hours | VARCHAR(100) | 营业时间 |
| delivery_fee | DECIMAL(10,2) | 配送费 |
| min_order_amount | DECIMAL(10,2) | 最低起送价 |
订单表(orders)设计:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | INT | 主键 |
| user_id | INT | 用户ID |
| restaurant_id | INT | 商家ID |
| address_id | INT | 配送地址ID |
| total | DECIMAL(10,2) | 订单总金额 |
| status | ENUM | 订单状态 |
| payment_method | VARCHAR(20) | 支付方式 |
| transaction_id | VARCHAR(100) | 支付交易号 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
5. 项目部署与测试
5.1 开发环境搭建
-
前端环境:
- 微信开发者工具
- Node.js 16+
- npm/yarn包管理器
-
后端环境:
- Node.js 16+
- MySQL 8.0+
- Redis
-
安装依赖:
bash复制# 前端
cd client
npm install
# 后端
cd server
npm install
5.2 数据库初始化
- 创建MySQL数据库:
sql复制CREATE DATABASE food_delivery CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- 执行数据迁移:
bash复制npx sequelize-cli db:migrate
- 初始化基础数据:
bash复制npx sequelize-cli db:seed:all
5.3 系统测试
5.3.1 单元测试
使用Jest框架编写单元测试:
javascript复制describe('User Service', () => {
it('should create a new user', async () => {
const userData = {
phone: '13800138000',
password: '123456'
};
const user = await UserService.createUser(userData);
expect(user).toHaveProperty('id');
expect(user.phone).toBe(userData.phone);
});
});
5.3.2 接口测试
使用Postman进行接口测试,主要测试点:
- 用户注册登录接口
- 商家列表接口
- 下单流程接口
- 支付回调接口
5.3.3 性能测试
使用JMeter进行压力测试,模拟高并发场景:
- 100并发用户查询商家列表
- 50并发用户同时下单
- 持续30分钟的稳定性测试
6. 开发经验与技巧
6.1 微信小程序开发技巧
-
优化页面加载速度:
- 使用分包加载
- 图片懒加载
- 数据预加载
-
提升用户体验:
- 添加骨架屏
- 实现下拉刷新和上拉加载
- 优化表单验证
-
调试技巧:
- 使用微信开发者工具的云开发能力
- 利用真机调试功能
- 监控小程序性能
6.2 Node.js后端开发经验
- 错误处理:
javascript复制// 统一错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
code: 500,
message: process.env.NODE_ENV === 'development'
? err.message
: 'Internal Server Error'
});
});
-
性能优化:
- 使用Redis缓存热点数据
- 数据库查询优化
- 启用Gzip压缩
-
安全防护:
- 参数校验
- SQL注入防护
- XSS防护
- CSRF防护
6.3 常见问题解决方案
-
微信登录失败:
- 检查AppID和AppSecret配置
- 确保域名已加入微信白名单
- 检查服务器时间是否准确
-
支付回调问题:
- 确保回调地址可外网访问
- 处理重复通知
- 验证签名
-
数据库连接问题:
- 检查连接池配置
- 监控连接泄漏
- 设置合理的超时时间
7. 项目扩展方向
这个基础版本的美食点餐小程序还可以进一步扩展:
- 会员系统:积分、优惠券、会员等级
- 评价系统:用户评价、商家回复
- 营销功能:满减活动、限时折扣
- 配送跟踪:实时显示骑手位置
- 多平台支持:H5、APP端
在实际开发过程中,我建议采用迭代开发的方式,先实现核心功能,再逐步添加扩展功能。同时要注意代码的可维护性和可扩展性,为后续功能扩展预留接口。