1. 项目概述:微信小程序菜谱平台的创新实践
去年帮学弟评审毕业设计时,遇到一个典型的场景:烹饪爱好者想通过手机快速查阅菜谱,但现有APP要么广告泛滥,要么社交功能过于复杂。这正是我们开发"基于微信小程序的在线菜谱学习与分享平台"的初衷——打造一个轻量级但功能完整的厨艺交流社区。
这个13875号毕业设计项目(项目编号常见于高校毕设管理系统)采用微信小程序作为载体,相比原生APP具有三大天然优势:
- 无需安装即点即用,符合菜谱查阅"临时性"需求特征
- 微信社交链天然支持内容分享
- 开发成本低且跨平台,特别适合学生开发者
平台核心功能模块包括:
- 智能菜谱检索(支持食材、菜系、难度等多维度筛选)
- 分步骤图文教程(适配手机竖屏浏览)
- UGC内容发布系统(用户可上传原创菜谱)
- 社交互动(收藏、点赞、评论)
- 个人厨房管理(记录学习进度和作品)
提示:选择微信小程序而非H5的关键考量是调用微信原生API的能力,如获取用户头像、微信支付等,这对社交类应用至关重要。
2. 核心技术架构解析
2.1 微信小程序端设计要点
前端采用小程序原生框架+TypeScript开发,重要组件设计如下:
导航栏定制方案
javascript复制// app.json中配置自定义导航栏
"window": {
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
实测需处理iPhone X系列刘海屏适配,通过wx.getSystemInfoSync()获取状态栏高度动态计算布局:
typescript复制const systemInfo = wx.getSystemInfoSync()
this.setData({
statusBarHeight: systemInfo.statusBarHeight,
navBarHeight: systemInfo.platform === 'android' ? 48 : 44
})
图片懒加载优化
菜谱详情页常含多张高清步骤图,采用小程序<image>标签的lazy-load属性并配合CDN图片压缩:
html复制<image
src="{{imgUrl}}?imageView2/0/q/75"
mode="widthFix"
lazy-load
binderror="handleImageError"
/>
2.2 服务端关键技术选型
后端采用Node.js+Koa2框架,数据库选择MongoDB,主要考虑:
- 数据模型设计
javascript复制// 菜谱Schema
const recipeSchema = new Schema({
title: { type: String, required: true },
author: { type: Schema.Types.ObjectId, ref: 'User' },
ingredients: [{
name: String,
amount: String
}],
steps: [{
desc: String,
imgUrl: String,
timer: Number // 步骤计时功能
}],
difficulty: { type: Number, enum: [1,2,3] },
createdAt: { type: Date, default: Date.now }
})
- 文件存储方案
- 图片上传使用微信临时文件路径转存七牛云
- 核心上传逻辑:
javascript复制const qiniuUpload = (tempFilePath) => {
return new Promise((resolve, reject) => {
const form = new FormData()
form.append('file', fs.createReadStream(tempFilePath))
form.append('token', uploadToken)
axios.post('https://upload.qiniup.com', form, {
headers: form.getHeaders()
}).then(res => {
resolve(`https://cdn.yourdomain.com/${res.data.key}`)
})
})
}
2.3 性能优化实践
- 接口缓存策略
- 使用Redis缓存热门菜谱数据
- 采用ETag实现HTTP缓存协商
- 列表页分页优化
避免传统skip+limit的性能瓶颈,采用基于最后ID的游标分页:
javascript复制router.get('/recipes', async (ctx) => {
const { lastId, limit = 10 } = ctx.query
const query = lastId ? { _id: { $lt: new ObjectId(lastId) } } : {}
const recipes = await Recipe.find(query)
.sort({ _id: -1 })
.limit(Number(limit))
ctx.body = {
data: recipes,
lastId: recipes[recipes.length-1]?._id
}
})
3. 核心功能实现细节
3.1 菜谱发布流程设计
用户发布流程包含关键校验环节:
- 标题敏感词过滤(使用AC自动机算法)
- 食材标准化处理(对接百度UNIT实现食材识别)
- 步骤图片压缩(使用canvas进行客户端预处理)
mermaid复制graph TD
A[用户填写基础信息] --> B{敏感词检测}
B -->|通过| C[上传步骤图片]
B -->|拒绝| D[返回修改提示]
C --> E[食材自动识别]
E --> F[生成结构化数据]
F --> G[提交审核]
G --> H[入库发布]
3.2 智能搜索实现
采用Elasticsearch构建搜索服务,特色功能包括:
同义词扩展
json复制// ES同义词配置
"filter": {
"recipe_synonym": {
"type": "synonym",
"synonyms": [
"土豆,马铃薯",
"番茄,西红柿"
]
}
}
权重设置
json复制"query": {
"multi_match": {
"query": "{{keyword}}",
"fields": [
"title^3", // 标题权重最高
"ingredients.name^2",
"steps.desc"
]
}
}
3.3 社交互动功能
- 点赞防刷机制
- 使用Redis记录用户操作
- 限制同一用户每分钟点赞次数
javascript复制const isAllowed = await redis.set(
`like:${userId}:${recipeId}`,
1,
'EX', 60,
'NX' // 仅当key不存在时设置
)
if (!isAllowed) throw new Error('操作过于频繁')
- 评论树形结构
采用MongoDB嵌套文档设计:
javascript复制{
_id: "评论ID",
content: "正文",
user: "用户ID",
replies: [{
content: "回复内容",
user: "回复用户ID",
createdAt: Date
}]
}
4. 开发踩坑与解决方案
4.1 微信登录流程优化
初期直接使用wx.login获取code换token的方案存在安全隐患,改进为:
- 前端先调用
wx.checkSession验证session有效性 - 失效时重新登录并向后端发送code
- 后端通过微信接口服务获取openid
- 生成双token(access_token + refresh_token)
javascript复制// 双token生成示例
const generateTokens = (user) => {
const accessToken = jwt.sign(
{ userId: user._id },
process.env.JWT_SECRET,
{ expiresIn: '2h' }
)
const refreshToken = jwt.sign(
{ userId: user._id, type: 'refresh' },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
)
return { accessToken, refreshToken }
}
4.2 图片上传失败处理
常见问题及解决方案:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 安卓机上传失败 | 临时文件路径格式不同 | 统一处理路径前缀wxfile://转http:// |
| iOS图片旋转 | EXIF方向信息 | 使用canvas校正方向 |
| 大图上传超时 | 网络波动 | 分片上传+断点续传 |
4.3 列表卡顿优化
针对初期出现的列表滚动卡顿问题,采取以下措施:
- 虚拟列表技术
html复制<scroll-view
scroll-y
style="height: 100vh"
bindscroll="handleScroll"
>
<view
wx:for="{{visibleData}}"
wx:key="id"
style="height: {{item.height}}px"
>
<!-- 渲染可见项 -->
</view>
</scroll-view>
-
图片尺寸预计算
在发布时记录图片宽高,避免渲染时重排 -
数据分块加载
监听滚动事件动态加载数据:
javascript复制handleScroll() {
if (this.data.loading) return
const { scrollTop, scrollHeight } = e.detail
if (scrollHeight - scrollTop < 800) {
this.loadMoreData()
}
}
5. 项目部署与运维
5.1 小程序上线准备
- 域名备案
- 必须完成ICP备案(约20工作日)
- 微信小程序后台配置合法域名
- HTTPS配置
- 使用Let's Encrypt免费证书
- Nginx配置示例:
nginx复制server {
listen 443 ssl;
server_name api.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/privkey.pem;
location / {
proxy_pass http://localhost:3000;
}
}
5.2 监控体系建设
- 前端异常监控
使用微信小程序自带的wx.reportMonitor:
javascript复制wx.reportMonitor('1', 1) // 自定义业务指标
// 全局错误捕获
App({
onError(err) {
wx.request({
url: 'https://api.yourdomain.com/monitor',
data: { error: err }
})
}
})
- 后端性能监控
- 使用PM2内置监控
- 关键指标:
- API响应时间(P99 < 500ms)
- 数据库查询耗时
- 内存使用率
5.3 数据备份策略
采用MongoDB Atlas的自动备份+手动快照双保险:
- 每日自动备份保留7天
- 重大更新前执行手动快照
- 备份验证流程:
bash复制# 恢复测试
mongorestore --uri="mongodb://localhost:27017" \
--drop \
--archive=/backups/dump_20230701.gz
6. 源码解析与二次开发
6.1 项目结构说明
code复制├── client/ # 小程序端
│ ├── components/ # 通用组件
│ ├── models/ # 数据模型
│ ├── pages/ # 页面目录
│ └── utils/ # 工具类
├── server/ # 服务端
│ ├── config/ # 配置文件
│ ├── controllers/ # 控制器
│ ├── middlewares/ # 中间件
│ └── services/ # 业务逻辑
└── docs/ # 文档
6.2 关键代码片段
菜谱详情页数据加载
typescript复制Page({
data: {
recipe: null,
loading: true
},
async onLoad(options) {
try {
const res = await wx.request({
url: `https://api.yourdomain.com/recipes/${options.id}`,
header: { 'Authorization': `Bearer ${getToken()}` }
})
this.setData({
recipe: res.data,
loading: false
})
} catch (err) {
wx.showToast({ title: '加载失败', icon: 'error' })
}
}
})
JWT验证中间件
javascript复制const auth = async (ctx, next) => {
const token = ctx.header.authorization?.split(' ')[1]
if (!token) {
ctx.status = 401
return ctx.body = { code: 401, message: '未提供token' }
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET)
ctx.state.user = await User.findById(decoded.userId)
await next()
} catch (err) {
ctx.status = 401
ctx.body = { code: 401, message: '无效token' }
}
}
6.3 扩展建议
- 增加视频教程
- 使用微信
<live-player>组件 - 对接腾讯云点播服务
- 智能推荐系统
- 基于用户行为构建推荐模型
- 使用TensorFlow.js实现客户端预测
- 厨具电商对接
- 扩展微信小程序电商功能
- 接入微信支付分账系统
开发过程中最深的体会是:微信小程序在提供丰富能力的同时,也带来特有的限制。比如必须严格控制包体积(主包不能超过2MB),这要求我们对静态资源进行精细管理。我的做法是:
- 非必要图片全部走CDN
- 使用小程序分包加载技术
- 定期使用
webpack-bundle-analyzer分析依赖
对于想要基于此源码二次开发的同学,建议先从config.js文件入手修改基础配置,再根据业务需求扩展对应模块。这个项目已经预留了完善的插件机制,比如要增加第三方登录,只需在server/services/auth.js中实现新的策略类即可。
