Doubao_Creation/index.html
2025-11-22 15:38:21 +08:00

1651 lines
70 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>今天吃什么 - 随机菜单抽取器</title>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Font Awesome -->
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- Tailwind 配置 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#FF6B6B',
secondary: '#4ECDC4',
accent: '#FFE66D',
light: '#F7FFF7',
dark: '#1A535C'
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
animation: {
'spin-slow': 'spin 3s linear infinite',
'bounce-slow': 'bounce 2s infinite',
}
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.text-shadow {
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}
.card-hover {
@apply transition-all duration-300 hover:shadow-lg hover:-translate-y-1;
}
.btn-primary {
@apply bg-primary text-white font-bold py-3 px-6 rounded-lg shadow-md hover:bg-opacity-90 transition-all duration-300 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-opacity-50;
}
.btn-secondary {
@apply bg-secondary text-white font-bold py-2 px-4 rounded-lg shadow-md hover:bg-opacity-90 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-secondary focus:ring-opacity-50;
}
.input-field {
@apply w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent;
}
.badge {
@apply inline-block px-2 py-1 text-xs font-semibold rounded-full;
}
.badge-primary {
@apply bg-primary bg-opacity-20 text-primary;
}
.badge-secondary {
@apply bg-secondary bg-opacity-20 text-secondary;
}
.badge-accent {
@apply bg-accent bg-opacity-20 text-dark;
}
}
/* 自定义动画 */
@keyframes spin-wheel {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spin-wheel-animation {
animation: spin-wheel 3s cubic-bezier(0.5, 0, 0.5, 1) forwards;
}
/* 转盘样式 */
.wheel-container {
position: relative;
width: 300px;
height: 300px;
margin: 0 auto;
}
.wheel {
width: 100%;
height: 100%;
border-radius: 50%;
position: relative;
overflow: hidden;
transition: transform 3s cubic-bezier(0.5, 0, 0.5, 1);
}
.wheel-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background-color: white;
border-radius: 50%;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}
.wheel-pointer {
position: absolute;
top: -10px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 25px solid #FF6B6B;
z-index: 10;
}
/* 菜品卡片样式 */
.meal-card {
@apply bg-white rounded-xl shadow-md overflow-hidden card-hover;
}
/* 加载动画 */
.loading {
@apply inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-primary;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<!-- 导航栏 -->
<nav class="bg-white shadow-md">
<div class="container mx-auto px-4 py-3 flex justify-between items-center">
<div class="flex items-center space-x-2">
<img src="https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/rc/pc/super_tool/7bededf640e748eb98cc85f945aa5f41~tplv-a9rns2rl98-image.image?rcl=20251122135701E64BCA52CB770CFFFE61&amp;rk3s=8e244e95&amp;rrcfp=f06b921b&amp;x-expires=1766383039&amp;x-signature=jbkwsTYX7ACM3iPbPDTWLdmr7Dw%3D" alt="Logo" class="w-10 h-10">
<h1 class="text-2xl font-bold text-dark">今天吃什么</h1>
</div>
<div>
<button id="helpBtn" class="btn-secondary flex items-center">
<i class="fa fa-question-circle mr-2"></i> 使用帮助
</button>
</div>
</div>
</nav>
<!-- 主内容区 -->
<main class="container mx-auto px-4 py-8">
<!-- 加载状态提示 -->
<div id="loadingIndicator" class="mb-6 flex justify-center items-center hidden">
<div class="loading mr-2"></div>
<span>正在加载菜单数据...</span>
</div>
<!-- JSON文件加载状态提示 -->
<div id="jsonLoadStatus" class="mb-6 hidden">
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative" role="alert">
<strong class="font-bold">成功!</strong>
<span class="block sm:inline" id="jsonLoadMessage">已从menu.json加载菜品数据</span>
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
<button onclick="document.getElementById('jsonLoadStatus').classList.add('hidden')" class="text-green-700 hover:text-green-900"><i class="fa fa-times"></i></button>
</span>
</div>
</div>
<!-- 菜品管理区域 -->
<section class="mb-10">
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-4 gap-4">
<h2 class="text-xl font-bold text-dark flex items-center">
<i class="fa fa-cutlery text-primary mr-2"></i> 菜品管理
</h2>
<div class="flex flex-wrap gap-2">
<button id="toggleAddFormBtn" class="btn-primary flex items-center">
<i class="fa fa-plus mr-2"></i> 添加菜品
</button>
<button id="batchAddBtn" class="btn-secondary flex items-center">
<i class="fa fa-list-ol mr-2"></i> 批量添加
</button>
<label for="jsonFileInput" class="btn-secondary flex items-center cursor-pointer">
<i class="fa fa-upload mr-2"></i> 导入JSON
</label>
<input type="file" id="jsonFileInput" accept=".json" class="hidden">
<button id="clearBtn" class="bg-gray-200 text-gray-700 font-bold py-2 px-4 rounded-lg shadow-sm hover:bg-gray-300 transition-all duration-300 focus:outline-none">
<i class="fa fa-trash mr-2"></i> 清空菜单
</button>
</div>
</div>
<!-- 添加菜品表单 -->
<div id="addMealForm" class="mb-6 p-4 bg-gray-50 rounded-lg hidden">
<h3 class="font-bold mb-3 text-dark">添加菜品</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">菜品名称 <span class="text-red-500">*</span></label>
<input type="text" id="mealName" class="input-field" placeholder="请输入菜品名称">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">分类 <span class="text-red-500">*</span></label>
<select id="mealCategory" class="input-field">
<option value="主食">主食</option>
<option value="荤菜">荤菜</option>
<option value="素菜">素菜</option>
<option value="汤品">汤品</option>
<option value="其他">其他</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">备注</label>
<input type="text" id="mealNote" class="input-field" placeholder="可选">
</div>
</div>
<div class="mt-4 flex justify-end space-x-2">
<button id="cancelAddBtn" class="bg-gray-200 text-gray-700 font-bold py-2 px-4 rounded-lg shadow-sm hover:bg-gray-300 transition-all duration-300 focus:outline-none">
取消
</button>
<button id="confirmAddBtn" class="btn-secondary">
确认添加
</button>
</div>
</div>
<!-- 批量添加菜品表单 -->
<div id="batchAddForm" class="mb-6 p-4 bg-gray-50 rounded-lg hidden">
<h3 class="font-bold mb-3 text-dark">批量添加菜品</h3>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">菜品列表 <span class="text-red-500">*</span></label>
<textarea id="batchMealNames" class="input-field" rows="6" placeholder="请输入菜品名称,每行一个"></textarea>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">分类 <span class="text-red-500">*</span></label>
<select id="batchMealCategory" class="input-field">
<option value="主食">主食</option>
<option value="荤菜">荤菜</option>
<option value="素菜">素菜</option>
<option value="汤品">汤品</option>
<option value="其他">其他</option>
</select>
</div>
<div class="mt-4 flex justify-end space-x-2">
<button id="cancelBatchAddBtn" class="bg-gray-200 text-gray-700 font-bold py-2 px-4 rounded-lg shadow-sm hover:bg-gray-300 transition-all duration-300 focus:outline-none">
取消
</button>
<button id="confirmBatchAddBtn" class="btn-secondary">
确认添加
</button>
</div>
</div>
</div>
</section>
<!-- 菜单列表区域 -->
<section class="mb-10">
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-dark flex items-center">
<i class="fa fa-list text-primary mr-2"></i> 菜单列表
</h2>
<div class="flex items-center space-x-2">
<div class="relative">
<input type="text" id="searchInput" placeholder="搜索菜品..." class="input-field pr-10">
<i class="fa fa-search absolute right-3 top-3 text-gray-400"></i>
</div>
<select id="categoryFilter" class="input-field">
<option value="all">全部分类</option>
</select>
</div>
</div>
<div id="menuList" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 max-h-96 overflow-y-auto p-2">
<!-- 菜单列表将通过 JavaScript 动态生成 -->
<div class="col-span-full text-center py-10 text-gray-500" id="emptyMenuMsg">
<i class="fa fa-info-circle text-3xl mb-3"></i>
<p>暂无菜单数据,请点击上方"添加菜品"按钮添加</p>
</div>
</div>
<div class="mt-4 flex justify-end items-center">
<div class="text-sm text-gray-500">
<span id="totalMeals">0</span> 个菜品
</div>
</div>
</div>
</section>
<!-- 随机抽取区域 -->
<section class="mb-10">
<div class="bg-white rounded-xl shadow-md p-6">
<h2 class="text-xl font-bold mb-4 text-dark flex items-center">
<i class="fa fa-random text-primary mr-2"></i> 随机抽取
</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- 左侧:转盘 -->
<div class="flex flex-col items-center justify-center">
<div class="wheel-container">
<div class="wheel-pointer"></div>
<div id="wheel" class="wheel">
<!-- 转盘内容将通过 JavaScript 动态生成 -->
<img src="https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/rc/pc/super_tool/32352db51cfe4b978936ee83db986dc1~tplv-a9rns2rl98-image.image?rcl=20251122135701E64BCA52CB770CFFFE61&amp;rk3s=8e244e95&amp;rrcfp=f06b921b&amp;x-expires=1766383052&amp;x-signature=eeKdGn2fh3DIiXJ%2B%2FWpgP9UFJPE%3D" alt="转盘" class="w-full h-full object-cover opacity-50" id="wheelPlaceholder">
</div>
<div class="wheel-center">
<i class="fa fa-cutlery text-2xl text-primary"></i>
</div>
</div>
<div class="mt-6 w-full max-w-xs">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">抽取数量</label>
<div class="flex items-center">
<button id="decreaseCount" class="bg-gray-200 text-gray-700 w-10 h-10 rounded-l-lg flex items-center justify-center hover:bg-gray-300 transition-all duration-300">
<i class="fa fa-minus"></i>
</button>
<input type="number" id="drawCount" min="1" value="1" class="input-field text-center border-l-0 border-r-0 rounded-none">
<button id="increaseCount" class="bg-gray-200 text-gray-700 w-10 h-10 rounded-r-lg flex items-center justify-center hover:bg-gray-300 transition-all duration-300">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">抽取方式</label>
<div class="flex space-x-2">
<button id="normalDrawBtn" class="btn-primary flex-1">
<i class="fa fa-random mr-2"></i> 随机抽取
</button>
<button id="smartDrawBtn" class="btn-secondary flex-1">
<i class="fa fa-lightbulb-o mr-2"></i> 智能推荐
</button>
</div>
</div>
</div>
</div>
<!-- 右侧:结果展示 -->
<div>
<div class="bg-gray-50 rounded-lg p-6 min-h-[300px] flex flex-col">
<h3 class="font-bold mb-4 text-dark">抽取结果</h3>
<div id="resultContainer" class="flex-1">
<!-- 未抽取时的提示 -->
<div id="noResultMsg" class="flex flex-col items-center justify-center h-full text-gray-500">
<i class="fa fa-hand-pointer-o text-4xl mb-3"></i>
<p>点击上方按钮开始抽取</p>
</div>
<!-- 抽取结果列表 -->
<div id="resultList" class="hidden">
<!-- 结果将通过 JavaScript 动态生成 -->
</div>
</div>
<div class="mt-4 flex justify-between">
<button id="saveResultBtn" class="btn-secondary flex items-center hidden">
<i class="fa fa-save mr-2"></i> 保存结果
</button>
<button id="shareResultBtn" class="btn-secondary flex items-center hidden">
<i class="fa fa-share-alt mr-2"></i> 分享结果
</button>
</div>
</div>
<!-- 历史记录 -->
<div class="mt-6">
<h3 class="font-bold mb-3 text-dark flex items-center">
<i class="fa fa-history text-primary mr-2"></i> 历史记录
</h3>
<div id="historyList" class="bg-gray-50 rounded-lg p-4 max-h-40 overflow-y-auto">
<!-- 历史记录将通过 JavaScript 动态生成 -->
<div class="text-center py-3 text-gray-500 text-sm">
暂无历史记录
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- 页脚 -->
<footer class="bg-dark text-white py-6">
<div class="container mx-auto px-4 text-center">
<p>© 2025 今天吃什么 - 随机菜单抽取器</p>
<p class="text-sm text-gray-400 mt-2">解决您的选择困难症</p>
</div>
</footer>
<!-- 帮助模态框 -->
<div id="helpModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl max-w-2xl w-full max-h-[80vh] overflow-y-auto">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-dark">使用帮助</h2>
<button id="closeHelpBtn" class="text-gray-500 hover:text-gray-700">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<div class="space-y-4">
<div>
<h3 class="font-bold text-primary mb-2">1. 添加菜品</h3>
<p>您可以通过以下三种方式添加菜品:</p>
<ul class="list-disc pl-5 mt-2">
<li><strong>单个添加</strong>:点击"添加菜品"按钮,填写菜品名称、分类和备注信息</li>
<li><strong>批量添加</strong>:点击"批量添加"按钮,在文本框中每行输入一个菜品名称</li>
<li><strong>导入JSON</strong>:点击"导入JSON"按钮选择包含菜品数据的JSON文件</li>
<li><strong>自动加载</strong>页面会自动加载同目录下的menu.json文件</li>
</ul>
<p class="mt-2">JSON文件支持两种格式</p>
<ul class="list-disc pl-5 mt-2">
<li>简单格式:<code>["菜品1", "菜品2", "菜品3"]</code></li>
<li>对象格式:<code>[{"name": "菜品1", "category": "分类", "note": "备注"}, ...]</code></li>
</ul>
<p class="mt-2">对象格式支持的字段包括name/title/dish/food名称、category/type/kind分类、note/remark/description备注</p>
</div>
<div>
<h3 class="font-bold text-primary mb-2">2. 菜单管理</h3>
<p>导入菜单后,您可以:</p>
<ul class="list-disc pl-5 mt-2">
<li>使用搜索框搜索菜品</li>
<li>使用分类筛选器筛选菜品</li>
<li>点击"添加菜品"按钮手动添加菜品</li>
<li>点击菜品卡片上的编辑或删除按钮修改或删除菜品</li>
</ul>
</div>
<div>
<h3 class="font-bold text-primary mb-2">3. 随机抽取</h3>
<p>设置抽取数量后,点击以下按钮之一进行抽取:</p>
<ul class="list-disc pl-5 mt-2">
<li><strong>随机抽取</strong>:完全随机地从菜单中抽取指定数量的菜品</li>
<li><strong>智能推荐</strong>:基于历史抽取记录,优先推荐较少出现的菜品</li>
</ul>
<p class="mt-2">抽取结果将显示在右侧的结果区域,您可以保存或分享结果。</p>
</div>
<div>
<h3 class="font-bold text-primary mb-2">4. 数据存储</h3>
<p>本应用使用浏览器的本地存储功能保存您的菜单数据和历史记录,数据仅存储在您的设备上,不会上传到服务器。</p>
<p class="mt-2">清除浏览器缓存或使用隐私模式可能会导致数据丢失,请定期备份您的 Excel 文件。</p>
</div>
</div>
</div>
</div>
</div>
<!-- 编辑菜品模态框 -->
<div id="editModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl max-w-md w-full">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-dark">编辑菜品</h2>
<button id="closeEditBtn" class="text-gray-500 hover:text-gray-700">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">菜品名称</label>
<input type="text" id="editMealName" class="input-field">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">分类</label>
<select id="editMealCategory" class="input-field">
<option value="主食">主食</option>
<option value="荤菜">荤菜</option>
<option value="素菜">素菜</option>
<option value="汤品">汤品</option>
<option value="其他">其他</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">备注</label>
<input type="text" id="editMealNote" class="input-field">
</div>
<div class="flex justify-end space-x-2 mt-6">
<button id="cancelEditBtn" class="bg-gray-200 text-gray-700 font-bold py-2 px-4 rounded-lg shadow-sm hover:bg-gray-300 transition-all duration-300 focus:outline-none">
取消
</button>
<button id="confirmEditBtn" class="btn-secondary">
确认修改
</button>
</div>
</div>
</div>
</div>
</div>
<!-- 分享结果模态框 -->
<div id="shareModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl max-w-md w-full">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-dark">分享结果</h2>
<button id="closeShareBtn" class="text-gray-500 hover:text-gray-700">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">分享文本</label>
<textarea id="shareText" class="input-field" rows="4" readonly=""></textarea>
</div>
<div class="flex justify-between space-x-2 mt-6">
<button id="copyShareBtn" class="btn-secondary flex-1">
<i class="fa fa-copy mr-2"></i> 复制文本
</button>
<button id="shareWechatBtn" class="btn-secondary flex-1">
<i class="fa fa-wechat mr-2"></i> 分享到微信
</button>
</div>
</div>
</div>
</div>
</div>
<script>
// 全局变量
let mealData = [];
let filteredMeals = [];
let currentEditIndex = -1;
let drawHistory = [];
let categories = ['主食', '荤菜', '素菜', '汤品', '其他'];
// DOM 元素
const clearBtn = document.getElementById('clearBtn');
const menuList = document.getElementById('menuList');
const emptyMenuMsg = document.getElementById('emptyMenuMsg');
const totalMeals = document.getElementById('totalMeals');
const searchInput = document.getElementById('searchInput');
const categoryFilter = document.getElementById('categoryFilter');
const toggleAddFormBtn = document.getElementById('toggleAddFormBtn');
const addMealForm = document.getElementById('addMealForm');
const cancelAddBtn = document.getElementById('cancelAddBtn');
const confirmAddBtn = document.getElementById('confirmAddBtn');
const mealName = document.getElementById('mealName');
const mealCategory = document.getElementById('mealCategory');
const mealNote = document.getElementById('mealNote');
const decreaseCount = document.getElementById('decreaseCount');
const increaseCount = document.getElementById('increaseCount');
const drawCount = document.getElementById('drawCount');
const normalDrawBtn = document.getElementById('normalDrawBtn');
const smartDrawBtn = document.getElementById('smartDrawBtn');
const resultContainer = document.getElementById('resultContainer');
const noResultMsg = document.getElementById('noResultMsg');
const resultList = document.getElementById('resultList');
const saveResultBtn = document.getElementById('saveResultBtn');
const shareResultBtn = document.getElementById('shareResultBtn');
const historyList = document.getElementById('historyList');
const helpBtn = document.getElementById('helpBtn');
const helpModal = document.getElementById('helpModal');
const closeHelpBtn = document.getElementById('closeHelpBtn');
const editModal = document.getElementById('editModal');
const closeEditBtn = document.getElementById('closeEditBtn');
const cancelEditBtn = document.getElementById('cancelEditBtn');
const confirmEditBtn = document.getElementById('confirmEditBtn');
const editMealName = document.getElementById('editMealName');
const editMealCategory = document.getElementById('editMealCategory');
const editMealNote = document.getElementById('editMealNote');
const shareModal = document.getElementById('shareModal');
const closeShareBtn = document.getElementById('closeShareBtn');
const copyShareBtn = document.getElementById('copyShareBtn');
const shareWechatBtn = document.getElementById('shareWechatBtn');
const shareText = document.getElementById('shareText');
const wheel = document.getElementById('wheel');
const wheelPlaceholder = document.getElementById('wheelPlaceholder');
const loadingIndicator = document.getElementById('loadingIndicator');
const jsonLoadStatus = document.getElementById('jsonLoadStatus');
const jsonLoadMessage = document.getElementById('jsonLoadMessage');
// 初始化
function init() {
console.log('初始化应用');
// 显示加载状态
loadingIndicator.classList.remove('hidden');
// 加载本地存储的数据
loadFromLocalStorage();
// 优先读取本地JSON文件
loadMealsFromJsonFile()
.then(() => {
// 隐藏加载状态
loadingIndicator.classList.add('hidden');
// 更新菜单列表
updateMenuList();
// 更新分类筛选器
updateCategoryFilter();
// 更新历史记录
updateHistoryList();
// 更新转盘
updateWheel();
})
.catch(error => {
console.log('JSON文件加载失败:', error);
// 隐藏加载状态
loadingIndicator.classList.add('hidden');
// 即使JSON加载失败也要初始化界面
updateMenuList();
updateCategoryFilter();
updateHistoryList();
updateWheel();
});
// 事件监听
clearBtn.addEventListener('click', clearMenu);
searchInput.addEventListener('input', handleSearch);
categoryFilter.addEventListener('change', handleCategoryFilter);
toggleAddFormBtn.addEventListener('click', toggleAddForm);
cancelAddBtn.addEventListener('click', toggleAddForm);
confirmAddBtn.addEventListener('click', addMeal);
// 批量添加相关事件
const batchAddBtn = document.getElementById('batchAddBtn');
const cancelBatchAddBtn = document.getElementById('cancelBatchAddBtn');
const confirmBatchAddBtn = document.getElementById('confirmBatchAddBtn');
batchAddBtn.addEventListener('click', toggleBatchAddForm);
cancelBatchAddBtn.addEventListener('click', toggleBatchAddForm);
confirmBatchAddBtn.addEventListener('click', batchAddMeals);
// JSON导入相关事件
const jsonFileInput = document.getElementById('jsonFileInput');
jsonFileInput.addEventListener('change', handleJsonFileImport);
// 抽取相关事件
decreaseCount.addEventListener('click', decreaseDrawCount);
increaseCount.addEventListener('click', increaseDrawCount);
normalDrawBtn.addEventListener('click', () => drawMeals(false));
smartDrawBtn.addEventListener('click', () => drawMeals(true));
// 结果相关事件
saveResultBtn.addEventListener('click', saveResult);
shareResultBtn.addEventListener('click', showShareModal);
// 模态框相关事件
helpBtn.addEventListener('click', showHelpModal);
closeHelpBtn.addEventListener('click', hideHelpModal);
closeEditBtn.addEventListener('click', hideEditModal);
cancelEditBtn.addEventListener('click', hideEditModal);
confirmEditBtn.addEventListener('click', updateMeal);
closeShareBtn.addEventListener('click', hideShareModal);
copyShareBtn.addEventListener('click', copyShareText);
shareWechatBtn.addEventListener('click', shareToWechat);
}
// 批量添加菜品
function batchAddMeals() {
console.log('执行批量添加菜品');
const batchMealNames = document.getElementById('batchMealNames');
const batchMealCategory = document.getElementById('batchMealCategory');
const namesText = batchMealNames.value.trim();
const category = batchMealCategory.value;
console.log('菜品名称文本:', namesText);
console.log('分类:', category);
// 验证输入
if (!namesText) {
console.log('错误: 菜品名称文本为空');
alert('请输入菜品名称');
batchMealNames.focus();
return;
}
// 按行分割
const names = namesText.split('\n').filter(name => name.trim());
console.log('解析后的菜品名称:', names);
if (names.length === 0) {
console.log('错误: 未找到有效的菜品名称');
alert('未找到有效的菜品名称');
batchMealNames.focus();
return;
}
// 检查重复
const duplicates = [];
names.forEach(name => {
if (mealData.some(meal => meal.name === name.trim())) {
duplicates.push(name.trim());
}
});
console.log('重复的菜品:', duplicates);
if (duplicates.length > 0) {
const confirmMsg = `以下菜品已存在,是否仍然添加其他菜品?\n${duplicates.join('\n')}`;
if (!confirm(confirmMsg)) {
console.log('用户取消添加');
return;
}
}
// 添加菜品
let addedCount = 0;
names.forEach(name => {
const trimmedName = name.trim();
if (trimmedName && !mealData.some(meal => meal.name === trimmedName)) {
const newMeal = {
name: trimmedName,
category: category,
note: '',
count: 0
};
console.log('添加新菜品:', newMeal);
mealData.push(newMeal);
addedCount++;
}
});
console.log('成功添加的菜品数量:', addedCount);
// 添加新分类
if (!categories.includes(category)) {
console.log('添加新分类:', category);
categories.push(category);
updateCategoryFilter();
}
// 更新界面
console.log('更新菜单列表');
updateMenuList();
updateWheel();
saveToLocalStorage();
// 显示成功消息
console.log('批量添加完成');
alert(`成功添加 ${addedCount} 个菜品`);
// 隐藏表单
toggleBatchAddForm();
}
// 切换批量添加菜品表单
function toggleBatchAddForm() {
const batchAddForm = document.getElementById('batchAddForm');
const addMealForm = document.getElementById('addMealForm');
// 隐藏单个添加表单
addMealForm.classList.add('hidden');
// 切换批量添加表单
batchAddForm.classList.toggle('hidden');
// 如果显示表单,清空输入
if (!batchAddForm.classList.contains('hidden')) {
document.getElementById('batchMealNames').value = '';
document.getElementById('batchMealNames').focus();
}
}
// 清空菜单
function clearMenu() {
if (mealData.length === 0) return;
if (confirm('确定要清空所有菜单数据吗?此操作不可撤销。')) {
mealData = [];
filteredMeals = [];
updateMenuList();
updateCategoryFilter();
updateWheel();
saveToLocalStorage();
}
}
// 更新菜单列表
function updateMenuList() {
// 如果没有数据,显示空消息
if (mealData.length === 0) {
emptyMenuMsg.classList.remove('hidden');
menuList.innerHTML = '';
menuList.appendChild(emptyMenuMsg);
totalMeals.textContent = '0';
return;
}
// 隐藏空消息
emptyMenuMsg.classList.add('hidden');
// 更新总数
totalMeals.textContent = mealData.length;
// 过滤数据
filteredMeals = mealData.filter(meal => {
const matchesSearch = meal.name.toLowerCase().includes(searchInput.value.toLowerCase()) ||
meal.note.toLowerCase().includes(searchInput.value.toLowerCase());
const matchesCategory = categoryFilter.value === 'all' || meal.category === categoryFilter.value;
return matchesSearch && matchesCategory;
});
// 清空列表
menuList.innerHTML = '';
// 添加菜品卡片
filteredMeals.forEach((meal, index) => {
const card = document.createElement('div');
card.className = 'meal-card';
// 获取分类对应的颜色
const categoryColor = getCategoryColor(meal.category);
card.innerHTML = `
<div class="p-4">
<div class="flex justify-between items-start">
<h3 class="font-bold text-lg">${meal.name}</h3>
<span class="badge ${categoryColor}">${meal.category}</span>
</div>
${meal.note ? `<p class="text-gray-600 text-sm mt-1">${meal.note}</p>` : ''}
<div class="flex justify-end mt-3 space-x-2">
<button class="text-gray-500 hover:text-primary" onclick="editMeal(${index})">
<i class="fa fa-pencil"></i>
</button>
<button class="text-gray-500 hover:text-red-500" onclick="deleteMeal(${index})">
<i class="fa fa-trash"></i>
</button>
</div>
</div>
`;
menuList.appendChild(card);
});
}
// 获取分类对应的颜色
function getCategoryColor(category) {
switch (category) {
case '主食': return 'badge-primary';
case '荤菜': return 'badge-secondary';
case '素菜': return 'badge-accent';
case '汤品': return 'badge-primary';
default: return 'badge-secondary';
}
}
// 更新分类筛选器
function updateCategoryFilter() {
// 清空现有选项
categoryFilter.innerHTML = '<option value="all">全部分类</option>';
// 添加分类选项
categories.forEach(category => {
const option = document.createElement('option');
option.value = category;
option.textContent = category;
categoryFilter.appendChild(option);
});
}
// 处理搜索
function handleSearch() {
updateMenuList();
}
// 处理分类筛选
function handleCategoryFilter() {
updateMenuList();
}
// 切换添加菜品表单
function toggleAddForm() {
console.log('切换添加菜品表单');
// 隐藏批量添加表单
const batchAddForm = document.getElementById('batchAddForm');
batchAddForm.classList.add('hidden');
// 切换单个添加表单
addMealForm.classList.toggle('hidden');
// 如果显示表单,清空输入并聚焦
if (!addMealForm.classList.contains('hidden')) {
console.log('显示添加菜品表单');
mealName.value = '';
mealNote.value = '';
mealName.focus();
} else {
console.log('隐藏添加菜品表单');
}
}
// 添加菜品
function addMeal() {
console.log('执行添加菜品');
const name = mealName.value.trim();
const category = mealCategory.value;
const note = mealNote.value.trim();
console.log('菜品名称:', name);
console.log('分类:', category);
console.log('备注:', note);
// 验证输入
if (!name) {
console.log('错误: 菜品名称为空');
alert('请输入菜品名称');
mealName.focus();
return;
}
// 检查重复
if (mealData.some(meal => meal.name === name)) {
console.log('错误: 菜品名称已存在');
alert('菜品名称已存在');
mealName.focus();
return;
}
// 添加菜品
const newMeal = {
name,
category,
note,
count: 0
};
console.log('添加新菜品:', newMeal);
mealData.push(newMeal);
// 添加新分类
if (!categories.includes(category)) {
console.log('添加新分类:', category);
categories.push(category);
updateCategoryFilter();
}
// 更新界面
console.log('更新菜单列表');
updateMenuList();
updateWheel();
saveToLocalStorage();
// 显示成功消息
console.log('菜品添加成功');
alert(`菜品"${name}"添加成功!`);
// 隐藏表单
toggleAddForm();
}
// 编辑菜品
function editMeal(index) {
currentEditIndex = index;
const meal = filteredMeals[index];
// 填充表单
editMealName.value = meal.name;
editMealCategory.value = meal.category;
editMealNote.value = meal.note;
// 显示模态框
editModal.classList.remove('hidden');
}
// 隐藏编辑模态框
function hideEditModal() {
editModal.classList.add('hidden');
currentEditIndex = -1;
}
// 更新菜品
function updateMeal() {
if (currentEditIndex === -1) return;
const name = editMealName.value.trim();
const category = editMealCategory.value;
const note = editMealNote.value.trim();
// 验证输入
if (!name) {
alert('请输入菜品名称');
editMealName.focus();
return;
}
// 检查重复(排除当前菜品)
const originalIndex = mealData.findIndex(meal => meal === filteredMeals[currentEditIndex]);
if (mealData.some((meal, index) => meal.name === name && index !== originalIndex)) {
alert('菜品名称已存在');
editMealName.focus();
return;
}
// 更新菜品
const meal = mealData[originalIndex];
meal.name = name;
// 如果分类改变,更新分类列表
if (meal.category !== category) {
meal.category = category;
if (!categories.includes(category)) {
categories.push(category);
updateCategoryFilter();
}
}
meal.note = note;
// 更新界面
updateMenuList();
updateWheel();
saveToLocalStorage();
// 隐藏模态框
hideEditModal();
}
// 删除菜品
function deleteMeal(index) {
const meal = filteredMeals[index];
if (confirm(`确定要删除菜品"${meal.name}"吗?`)) {
// 找到原始索引
const originalIndex = mealData.findIndex(m => m === meal);
// 删除菜品
mealData.splice(originalIndex, 1);
// 更新界面
updateMenuList();
updateCategoryFilter();
updateWheel();
saveToLocalStorage();
}
}
// 减少抽取数量
function decreaseDrawCount() {
const count = parseInt(drawCount.value);
if (count > 1) {
drawCount.value = count - 1;
}
}
// 增加抽取数量
function increaseDrawCount() {
const count = parseInt(drawCount.value);
if (count < mealData.length) {
drawCount.value = count + 1;
}
}
// 抽取菜品
function drawMeals(smart = false) {
// 检查是否有菜品
if (mealData.length === 0) {
alert('请先导入菜单或添加菜品');
return;
}
const count = parseInt(drawCount.value);
// 检查抽取数量
if (count > mealData.length) {
alert(`菜单中只有 ${mealData.length} 个菜品,无法抽取 ${count}`);
drawCount.value = mealData.length;
return;
}
// 显示转盘动画
showWheelAnimation();
// 延迟显示结果,模拟转盘旋转
setTimeout(() => {
// 抽取菜品
let selectedMeals;
if (smart) {
// 智能推荐:优先选择抽取次数少的菜品
selectedMeals = smartDraw(count);
} else {
// 随机抽取
selectedMeals = randomDraw(count);
}
// 更新抽取次数
selectedMeals.forEach(meal => {
meal.count++;
});
// 显示结果
showResult(selectedMeals);
// 保存历史记录
saveDrawHistory(selectedMeals);
// 保存到本地存储
saveToLocalStorage();
}, 3000);
}
// 随机抽取
function randomDraw(count) {
const result = [];
const availableMeals = [...mealData];
for (let i = 0; i < count; i++) {
if (availableMeals.length === 0) break;
const randomIndex = Math.floor(Math.random() * availableMeals.length);
result.push(availableMeals[randomIndex]);
availableMeals.splice(randomIndex, 1);
}
return result;
}
// 智能推荐
function smartDraw(count) {
// 按抽取次数排序
const sortedMeals = [...mealData].sort((a, b) => a.count - b.count);
// 选择抽取次数最少的菜品
return sortedMeals.slice(0, count);
}
// 显示转盘动画
function showWheelAnimation() {
// 如果没有菜品,显示占位图
if (mealData.length === 0) {
wheelPlaceholder.classList.remove('hidden');
return;
}
// 隐藏占位图
wheelPlaceholder.classList.add('hidden');
// 创建转盘分区
createWheelSegments();
// 添加动画类
wheel.classList.add('spin-wheel-animation');
// 动画结束后移除类
setTimeout(() => {
wheel.classList.remove('spin-wheel-animation');
}, 3000);
}
// 创建转盘分区
function createWheelSegments() {
// 清空转盘
wheel.innerHTML = '';
// 如果没有菜品,返回
if (mealData.length === 0) return;
// 计算每个分区的角度
const angle = 360 / mealData.length;
// 创建分区
mealData.forEach((meal, index) => {
const segment = document.createElement('div');
segment.className = 'absolute';
segment.style.width = '50%';
segment.style.height = '50%';
segment.style.transformOrigin = '100% 100%';
segment.style.transform = `rotate(${index * angle}deg)`;
segment.style.backgroundColor = getSegmentColor(index);
segment.style.display = 'flex';
segment.style.alignItems = 'center';
segment.style.justifyContent = 'center';
segment.style.padding = '10px';
segment.style.boxSizing = 'border-box';
// 创建菜品名称
const name = document.createElement('div');
name.className = 'text-white font-bold text-center';
name.style.transform = 'rotate(45deg)';
name.style.width = '100px';
name.style.overflow = 'hidden';
name.style.textOverflow = 'ellipsis';
name.style.whiteSpace = 'nowrap';
name.textContent = meal.name;
segment.appendChild(name);
wheel.appendChild(segment);
});
}
// 获取分区颜色
function getSegmentColor(index) {
const colors = [
'#FF6B6B', '#4ECDC4', '#FFE66D', '#1A535C', '#FF9F1C',
'#7B287D', '#00B4D8', '#0077B6', '#2EC4B6', '#E76F51'
];
return colors[index % colors.length];
}
// 显示结果
function showResult(selectedMeals) {
// 隐藏无结果提示
noResultMsg.classList.add('hidden');
// 显示结果列表
resultList.classList.remove('hidden');
// 清空结果列表
resultList.innerHTML = '';
// 添加结果卡片
selectedMeals.forEach((meal, index) => {
const card = document.createElement('div');
card.className = 'bg-white rounded-lg shadow-sm p-4 mb-3 border-l-4 border-primary';
const categoryColor = getCategoryColor(meal.category);
card.innerHTML = `
<div class="flex justify-between items-start">
<div>
<div class="flex items-center">
<span class="text-lg font-bold mr-2">${index + 1}. ${meal.name}</span>
<span class="badge ${categoryColor}">${meal.category}</span>
</div>
${meal.note ? `<p class="text-gray-600 text-sm mt-1">${meal.note}</p>` : ''}
</div>
<span class="text-gray-500 text-sm">已抽取 ${meal.count} 次</span>
</div>
`;
resultList.appendChild(card);
});
// 显示保存和分享按钮
saveResultBtn.classList.remove('hidden');
shareResultBtn.classList.remove('hidden');
}
// 保存结果
function saveResult() {
// 创建日期字符串
const date = new Date();
const dateStr = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
// 获取当前结果
const resultItems = resultList.querySelectorAll('.bg-white');
let resultText = '菜品名称,分类,备注\n';
resultItems.forEach(item => {
const name = item.querySelector('.font-bold').textContent.split('. ')[1];
const category = item.querySelector('.badge').textContent;
const note = item.querySelector('.text-gray-600')?.textContent || '';
// 转义CSV特殊字符
const escapeCSV = (str) => `"${str.replace(/"/g, '""')}"`;
resultText += `${escapeCSV(name)},${escapeCSV(category)},${escapeCSV(note)}\n`;
});
// 创建Blob对象
const blob = new Blob([resultText], { type: 'text/csv;charset=utf-8;' });
// 创建下载链接
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', `抽取结果_${dateStr}.csv`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// 显示分享模态框
function showShareModal() {
// 获取当前结果
const resultItems = resultList.querySelectorAll('.bg-white');
let shareContent = '今天吃什么 - 抽取结果\n\n';
resultItems.forEach((item, index) => {
const name = item.querySelector('.font-bold').textContent;
const category = item.querySelector('.badge').textContent;
shareContent += `${name} [${category}]\n`;
});
// 添加日期
const date = new Date();
shareContent += `\n抽取时间: ${date.toLocaleString('zh-CN')}`;
// 设置分享文本
shareText.value = shareContent;
// 显示模态框
shareModal.classList.remove('hidden');
}
// 隐藏分享模态框
function hideShareModal() {
shareModal.classList.add('hidden');
}
// 复制分享文本
function copyShareText() {
shareText.select();
document.execCommand('copy');
// 显示提示
alert('文本已复制到剪贴板');
}
// 分享到微信
function shareToWechat() {
alert('请手动复制文本,然后粘贴到微信中分享');
}
// 保存抽取历史
function saveDrawHistory(selectedMeals) {
// 创建历史记录
const history = {
date: new Date(),
meals: selectedMeals.map(meal => ({
name: meal.name,
category: meal.category
}))
};
// 添加到历史记录
drawHistory.unshift(history);
// 限制历史记录数量
if (drawHistory.length > 10) {
drawHistory.pop();
}
// 更新历史记录列表
updateHistoryList();
}
// 更新历史记录列表
function updateHistoryList() {
// 如果没有历史记录,显示提示
if (drawHistory.length === 0) {
historyList.innerHTML = `
<div class="text-center py-3 text-gray-500 text-sm">
暂无历史记录
</div>
`;
return;
}
// 清空历史记录列表
historyList.innerHTML = '';
// 添加历史记录
drawHistory.forEach((history, index) => {
const item = document.createElement('div');
item.className = 'bg-white rounded-lg shadow-sm p-3 mb-2';
// 格式化日期
const dateStr = history.date.toLocaleString('zh-CN');
// 创建菜品列表
const mealList = history.meals.map(meal => meal.name).join('、');
item.innerHTML = `
<div class="flex justify-between items-start">
<div>
<p class="font-medium">${mealList}</p>
<p class="text-xs text-gray-500">${dateStr}</p>
</div>
<button class="text-primary hover:text-primary-dark" onclick="loadHistory(${index})">
<i class="fa fa-refresh"></i>
</button>
</div>
`;
historyList.appendChild(item);
});
}
// 加载历史记录
function loadHistory(index) {
const history = drawHistory[index];
// 查找菜品
const selectedMeals = history.meals.map(meal => {
return mealData.find(m => m.name === meal.name) || meal;
});
// 显示结果
showResult(selectedMeals);
}
// 显示帮助模态框
function showHelpModal() {
helpModal.classList.remove('hidden');
}
// 隐藏帮助模态框
function hideHelpModal() {
helpModal.classList.add('hidden');
}
// 保存到本地存储
function saveToLocalStorage() {
localStorage.setItem('mealData', JSON.stringify(mealData));
localStorage.setItem('categories', JSON.stringify(categories));
localStorage.setItem('drawHistory', JSON.stringify(drawHistory));
}
// 从本地存储加载
function loadFromLocalStorage() {
const savedMealData = localStorage.getItem('mealData');
const savedCategories = localStorage.getItem('categories');
const savedDrawHistory = localStorage.getItem('drawHistory');
if (savedMealData) {
mealData = JSON.parse(savedMealData);
}
if (savedCategories) {
categories = JSON.parse(savedCategories);
}
if (savedDrawHistory) {
drawHistory = JSON.parse(savedDrawHistory);
// 转换日期字符串为 Date 对象
drawHistory.forEach(history => {
history.date = new Date(history.date);
});
}
}
// 从本地JSON文件加载菜品数据返回Promise
async function loadMealsFromJsonFile() {
console.log('尝试从本地JSON文件加载菜品数据');
try {
// 首先尝试加载menu.json
const response = await fetch('menu.json', {
method: 'GET',
cache: 'no-cache'
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const jsonData = await response.json();
console.log('成功读取menu.json文件');
// 处理JSON数据
const addedCount = processJsonData(jsonData);
// 显示成功提示
if (addedCount > 0) {
jsonLoadMessage.textContent = `已从menu.json加载 ${addedCount} 个菜品`;
jsonLoadStatus.classList.remove('hidden');
}
return true;
} catch (error) {
console.log('无法加载menu.json文件:', error.message);
// 尝试加载其他可能的JSON文件名
const alternativeFiles = ['meals.json', 'dishes.json', 'food.json'];
for (const filename of alternativeFiles) {
try {
console.log(`尝试加载${filename}`);
const response = await fetch(filename, {
method: 'GET',
cache: 'no-cache'
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const jsonData = await response.json();
console.log(`成功读取${filename}文件`);
// 处理JSON数据
const addedCount = processJsonData(jsonData);
// 显示成功提示
if (addedCount > 0) {
jsonLoadMessage.textContent = `已从${filename}加载 ${addedCount} 个菜品`;
jsonLoadStatus.classList.remove('hidden');
}
return true;
} catch (altError) {
console.log(`加载${filename}失败:`, altError.message);
continue;
}
}
// 如果所有文件都加载失败,抛出错误
throw new Error('未找到可用的JSON菜单文件');
}
}
// 处理JSON数据返回添加的菜品数量
function processJsonData(jsonData) {
console.log('处理JSON数据');
// 验证JSON格式
if (!Array.isArray(jsonData)) {
console.log('错误: JSON格式不正确应为数组');
alert('JSON文件格式错误应为数组格式');
return 0;
}
// 处理导入的菜品数据
let addedCount = 0;
let duplicateCount = 0;
jsonData.forEach(item => {
// 支持不同的JSON格式
let name, category, note;
if (typeof item === 'string') {
// 简单格式: ["菜品1", "菜品2", ...]
name = item.trim();
category = '其他'; // 默认分类
note = '';
} else if (typeof item === 'object' && item !== null) {
// 对象格式: [{name: "菜品1", category: "分类", note: "备注"}, ...]
name = item.name || item.title || item.dish || item.food || '';
name = name ? name.trim() : '';
category = item.category || item.type || item.kind || '其他';
note = item.note || item.remark || item.description || '';
}
// 验证菜品名称
if (!name) {
console.log('跳过无效菜品:', item);
return;
}
// 检查重复
if (mealData.some(meal => meal.name === name)) {
console.log('跳过重复菜品:', name);
duplicateCount++;
return;
}
// 添加菜品
mealData.push({
name,
category,
note,
count: 0
});
// 添加新分类
if (!categories.includes(category)) {
categories.push(category);
}
addedCount++;
});
console.log(`处理完成: 添加${addedCount}个菜品, 跳过${duplicateCount}个重复菜品`);
// 如果有新菜品添加,保存到本地存储
if (addedCount > 0) {
saveToLocalStorage();
}
return addedCount;
}
// 处理JSON文件导入
function handleJsonFileImport(event) {
console.log('处理JSON文件导入');
const file = event.target.files[0];
if (!file) {
console.log('未选择文件');
return;
}
if (file.type !== 'application/json' && !file.name.endsWith('.json')) {
console.log('错误: 不是JSON文件');
alert('请选择JSON格式的文件');
return;
}
const reader = new FileReader();
reader.onload = function(e) {
try {
console.log('读取文件完成');
const jsonData = JSON.parse(e.target.result);
const addedCount = processJsonData(jsonData);
// 更新界面
updateCategoryFilter();
updateMenuList();
updateWheel();
// 显示成功消息
alert(`JSON文件导入成功共添加 ${addedCount} 个新菜品`);
} catch (error) {
console.error('解析JSON文件出错:', error);
alert('解析JSON文件出错请检查文件格式');
}
};
reader.onerror = function() {
console.error('读取文件出错');
alert('读取文件出错,请重试');
};
reader.readAsText(file, 'UTF-8');
// 重置文件输入,允许重新选择相同文件
event.target.value = '';
}
// 更新转盘(空实现,确保函数存在)
function updateWheel() {
// 如果有菜品,创建转盘分区
if (mealData.length > 0) {
wheelPlaceholder.classList.add('hidden');
createWheelSegments();
} else {
wheelPlaceholder.classList.remove('hidden');
}
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>