从零开发年夜饭菜单推荐系统:AI+传统节日的融合
前言
我想分享一下自己开发的年夜饭菜单推荐系统。这个项目将AI技术与传统节日文化完美结合,既解决了年夜饭菜单规划的痛点,又通过精美的灯笼装饰烘托了节日氛围。
项目起源
痛点: 每年春节,年夜饭菜单规划都是个难题
- 人多菜少怕不够,人少菜多怕浪费
- 老人、小孩、年轻人各有口味偏好
- 预算有限,想做到丰富又不铺张
- 菜品要有好寓意,但年年都是那几道,缺乏新意
灵感: 既然现在AI这么强大,为什么不让AI来推荐年夜饭菜单呢?
目标:
- 根据人数、口味、预算、特殊需求智能推荐菜品
- 每道菜都附上美好寓意
- 自动生成采购清单
- 最好还能导出精美的菜单卡片,方便分享到家庭群
技术选型
AI平台选择:iflow
我选择了 iflow 作为AI模型提供商,主要考虑:
- 模型丰富:支持Qwen系列、DeepSeek、Kimi、GLM等27+模型
- API友好:标准OpenAI兼容格式,集成简单
- 响应速度快:国内服务器,延迟低
- 价格合理:性价比高,适合个人项目
- 稳定性好:服务稳定,文档完善
iflow CLI体验:
# 安装iflow CLI(如果提供的话)
npm install -g iflow-cli
# 配置API Key
iflow config set api_key YOUR_API_KEY
# 测试模型调用
iflow chat "介绍5道年夜饭菜品" --model Qwen3-Max
(注:实际使用中我是通过HTTP API调用的)
技术栈
- 前端:纯HTML + CSS + JavaScript(无框架依赖)
- AI调用:RESTful API(OpenAI兼容格式)
- 导出功能:html2canvas + jsPDF
- 界面设计:艺术化中国新年主题
开发过程分享
第一阶段:核心功能开发(Day 1)
1. API集成
首先是接入iflow的API,参考官方文档:
async function callIflowAPI(apiKey, model, prompt) {
const response = await fetch('https://apis.iflow.cn/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
model: model,
messages: [
{
role: 'user',
content: prompt
}
],
temperature: 0.7,
max_tokens: 4096
})
});
const data = await response.json();
return data.choices[0].message.content;
}
踩坑与解决:
问题1:响应格式不统一
- iflow有时返回标准OpenAI格式:
{choices: [...]} - 有时返回自定义格式:
{status: "200", body: {choices: [...]}}
解决方案: 编写兼容性解析器
function parseJSONResponse(content) {
// 尝试提取JSON
const jsonMatch = content.match(/\{[\s\S]*\}/);
if (jsonMatch) {
try {
return JSON.parse(jsonMatch[0]);
} catch (e) {
console.error('JSON解析失败,使用fallback数据');
}
}
// 返回演示数据作为fallback
return getFallbackMenuData();
}
问题2:AI返回的JSON格式不规范
- AI有时会在JSON前后添加文字说明
- 有时会返回markdown代码块包裹的JSON
解决方案: 使用正则提取第一个完整JSON
const jsonMatch = content.match(/\{[\s\S]*\}/);
2. Prompt工程
要让AI返回结构化数据,Prompt设计很关键:
const prompt = `你是一位专业的年夜饭菜单规划师。请根据以下信息生成一份完整的年夜饭菜单:
用餐人数:${peopleCount}人
地域口味:${cuisineType}
人均预算:${budget}元
特殊需求:${specialNeeds || '无'}
请按照以下JSON格式返回结果:
{
"dishes": [
{
"name": "菜名",
"icon": "emoji表情",
"meaning": "寓意",
"ingredients": "主要食材",
"difficulty": "制作难度(简单/中等/困难)",
"category": "类别(凉菜/热菜/汤品/主食)"
}
],
"shoppingList": {
"肉类": ["食材1", "食材2"],
"蔬菜": ["食材3", "食材4"]
},
"cookingSchedule": "烹饪时间安排建议"
}
要求:
1. 菜品数量根据人数合理搭配
2. 每道菜都要有美好的寓意
3. 考虑到预算和口味偏好
4. 食材搭配营养均衡
5. 只返回JSON,不要其他文字说明`;
Prompt优化技巧:
- 明确角色定位(“专业的年夜饭菜单规划师”)
- 提供具体示例(JSON格式)
- 强调约束条件(“只返回JSON”)
- 考虑文化元素(寓意、营养均衡)
第二阶段:UI设计与开发
1. 设计理念
我想打造既有艺术感又具生活气息的界面:
阅了大量春节主题设计- 参考了中国传统色彩(红、金)
- 加入动态元素(灯笼、祥云、雪花)
2. 色彩方案
最终选择了红金渐变作为主色调:
background: linear-gradient(135deg,
#8B0000 0%, /* 深红 */
#DC143C 25%, /* 猩红 */
#FF4500 50%, /* 橙红 */
#DC143C 75%, /* 猩红 */
#8B0000 100% /* 深红 */
);
3. 灯笼系统设计
这是最出彩的部分!我参考了多个开源灯笼项目,最终实现了:
核心技术:
- CSS动画(摆动效果)
- 滚动监听(变淡效果)
- 动态样式生成(可定制)
摆动动画:
@keyframes swing-enhanced {
0% { transform: rotate(-4deg) }
50% { transform: rotate(4deg) }
100% { transform: rotate(-4deg) }
}
滚动交互:
window.addEventListener('scroll', () => {
const scrollPercent = Math.min(window.pageYOffset / 500, 1);
const newScale = 1 - (scrollPercent * 0.5); // 1.0 → 0.5
const newOpacity = 1 - (scrollPercent * 0.7); // 1.0 → 0.3
container.style.opacity = newOpacity.toString();
lanterns.forEach(l => l.style.transform = `scale(${newScale})`);
});
难点与解决:
问题:灯笼遮挡标题
- 灯笼高度约145px,标题被挡住了
解决方案:
- 减小灯笼尺寸:120px→100px
- 调整标题间距:margin-top: 0 → 180px
- 最终达到完美布局
第三阶段:导出功能
用户反馈想要导出菜单卡片分享到家庭群,所以我实现了:
1. 图片导出(html2canvas)
async function exportAsImage() {
const canvas = await html2canvas(exportCard, {
scale: 2, // 高清
backgroundColor: '#ffffff'
});
canvas.toBlob((blob) => {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = `年夜饭菜单_${Date.now()}.png`;
link.href = url;
link.click();
}, 'image/png');
}
2. PDF导出(jsPDF)
async function exportAsPDF() {
const canvas = await html2canvas(exportCard, { scale: 2 });
const imgData = canvas.toDataURL('image/png');
const { jsPDF } = window.jspdf;
const pdf = new jsPDF();
const pdfWidth = pdf.internal.pageSize.getWidth();
// 计算图片在PDF中的尺寸
const imgWidth = canvas.width;
const ratio = pdfWidth / imgWidth;
pdf.addImage(imgData, 'PNG', 0, 10, pdfWidth, imgWidth * ratio);
pdf.save(`年夜饭菜单_${Date.now()}.pdf`);
}
3. 导出模板设计
卡片包含:
装饰元素(灯笼、红包)
自动日期
祝福语(“恭贺新禧·万事如意”)
菜单内容(双列布局)
红金配色主题
项目亮点
1. 完整的AI集成
双平台支持(iflow、火山引擎)
27+模型可选
测试模式(输入"test"即可体验)
智能Prompt工程
2. 精美UI设计
中国新年主题
红金渐变背景
动态灯笼装饰
响应式布局
3. 实用功能
自动生成采购清单
菜品寓意解说
PDF/图片导出
家庭群分享友好
4. 用户体验
一键生成菜单
配置自动保存(localStorage)
完整的使用文档
错误处理和调试信息
部署方式
方式1:直接访问
克隆项目后,用浏览器打开 index.html 即可使用:
git clone https://github.com/9527wow/spring-festival-menu.git
cd spring-festival-menu
# 用浏览器打开 index.html
方式2:本地服务器(推荐)
# 使用Python
python -m http.server 8000
# 使用Node.js
npx http-server
# 访问 http://localhost:8000
方式3:GitHub Pages(免费托管)
- 在GitHub仓库Settings中启用GitHub Pages
- 选择 main分支作为源
开发心得与技巧
1. Prompt工程很重要
经验: 明确的格式要求 + 具体示例 = 更好的结果
// ❌ 不好的Prompt
"帮我推荐5道年夜饭菜"
// ✅ 好的Prompt
"你是年夜饭菜单规划师,请为4人推荐家常菜,预算100-200元,要求每道菜都有美好寓意,按JSON格式返回..."
2. 错误处理要完善
原则: 永远不要相信API会100%成功
try {
const data = await callAPI(...);
return parseResponse(data);
} catch (error) {
console.error('API失败,使用fallback数据');
return getFallbackData();
}
3. UI细节决定品质
对比:
普通红背景 vs
红金渐变动画
静态灯笼 vs
动态摆动+滚动交互
纯文字展示 vs
精美卡片+emoji图标
4. 用户体验优先
考虑:
- 加载状态提示
- 错误信息友好
- 配置自动保存
- 移动端适配
项目数据
| 指标 | 数据 |
|---|---|
| 开发时间 | 4天 |
| 代码行数 | ~3,500行 |
| 文件数量 | 8个 |
| 支持模型 | 27+ |
| 颜色主题 | 3种 |
| 导出格式 | 2种 |
未来改进方向
功能扩展
- 菜品烹饪教程链接
- 营养价值分析
- 食材价格估算
- 多语言菜单(英文、日文等)
技术优化
- PWA支持(离线使用)
- 后端缓存(减少API调用)
- 数据统计分析
- 用户评价系统
总结
这个项目从想法到实现,整个过程非常顺利,主要得益于:
- iflow API的优秀性能:响应快、模型多、文档全
- 清晰的开发规划:分阶段实现,逐步完善
- 注重用户体验:每个细节都反复打磨
- 开源社区的力量:参考了多个优秀项目的设计
最大的收获:
- 学会了如何将AI技术落地到实际应用
- 掌握了前端动画和交互设计
- 理解了用户需求的重要性
给想开发类似项目的建议:
- 从小处着手,逐步扩展
- 不要忽视UI/UX设计
- 多测试、多收集用户反馈
- 善用开源资源和社区力量
相关链接
- 项目地址:GitHub - 9527wow/spring-festival-menu: AI-powered Chinese New Year Eve Dinner Menu Recommendation System with beautiful lantern decorations and export functionality.
- iflow官网:https://platform.iflow.cn
- 在线体验:(https://9527wow.github.io/spring-festival-menu/)
欢迎大家试用和反馈!如果觉得有帮助,请给个Star支持一下!![]()
![]()
![]()
愿这顿年夜饭,温暖全家心 ![]()
![]()
![]()