去年为一个健身工作室开发健康管理系统时,我深刻体会到饮食管理的重要性。传统的手工记录方式效率低下,于是萌生了开发智能菜谱系统的想法。这个基于Node.js和Vue.js的个人健康菜谱生成系统,核心目标是解决三大痛点:个性化推荐缺失、营养计算繁琐、菜谱调整不便。
技术选型上,我选择了Node.js + Vue.js的全JavaScript技术栈。这个组合有几个显著优势:
提示:选择MySQL而非MongoDB是因为营养数据需要严格的关系约束,比如食材与营养素的对应关系必须精确到毫克
后端采用经典的MVC模式,但有几个特别设计:
javascript复制// 示例:菜谱生成路由的分片处理
router.use('/generate',
authMiddleware,
rateLimiter(100), // 限流防止恶意请求
splitRoute({
'breakfast': breakfastRouter,
'lunch': lunchRouter,
'dinner': dinnerRouter
})
);
前端架构上做了这些优化:
RecipeCard.vue、NutritionChart.vue等原子组件javascript复制// store模块化示例
const store = new Vuex.Store({
modules: {
user: userModule, // 用户身高体重等数据
recipes: recipeModule, // 菜谱相关数据
system: systemModule // 加载状态等
}
});
菜谱生成的核心算法经历了三次迭代:
算法关键参数:
markdown复制| 参数名 | 说明 | 取值范围 | 默认值 |
|--------------|--------------------------|----------|--------|
| healthScore | 健康程度权重 | 0-1 | 0.7 |
| tasteWeight | 用户口味偏好权重 | 0-1 | 0.3 |
| varietyFactor | 菜品多样性系数 | 1-3 | 1.5 |
营养计算采用分级处理:
重要提示:计算铁元素吸收时要考虑维生素C的促进效果,这是很多系统忽略的细节
sql复制CREATE TABLE `ingredients` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`protein_per_100g` DECIMAL(5,2) NOT NULL,
`carbs_per_100g` DECIMAL(5,2) NOT NULL,
-- 其他营养字段...
PRIMARY KEY (`id`),
UNIQUE INDEX `name_UNIQUE` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
docker-compose.yml关键配置:
yaml复制services:
app:
image: node:14
working_dir: /app
volumes:
- ./backend:/app
ports:
- "3000:3000"
depends_on:
- db
command: ["npm", "run", "prod"]
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
初期遇到的CORS问题不止是简单的配置问题:
最终解决方案:
javascript复制const corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1 || !origin) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
credentials: true,
optionsSuccessStatus: 200
}
app.use(cors(corsOptions));
通过以下步骤定位到问题:
修复方案:实现缓存自动过期机制
可以尝试的方向:
这个项目从构思到上线历时6个月,最大的体会是:健康领域的系统开发必须平衡科学性和用户体验。比如营养计算要精确到毫克级,但界面展示要简化成易懂的百分比。技术实现上,Vue的响应式特性与Node的高效计算配合得天衣无缝,让我完成了从理论到实践的完整闭环。