Bläddra i källkod

优化一桌菜模式

liuziting 7 månader sedan
förälder
incheckning
7c764a9521
2 ändrade filer med 366 tillägg och 220 borttagningar
  1. 26 3
      src/services/aiService.ts
  2. 340 217
      src/views/TableDesign.vue

+ 26 - 3
src/services/aiService.ts

@@ -129,6 +129,7 @@ export const generateRecipe = async (ingredients: string[], cuisine: CuisineType
  */
 export const generateTableMenu = async (config: {
     dishCount: number
+    flexibleCount: boolean
     tastes: string[]
     cuisineStyle: string
     diningScene: string
@@ -169,23 +170,45 @@ export const generateTableMenu = async (config: {
         }
 
         let prompt = `请为我设计一桌菜,要求如下:
-- 菜品数量:${config.dishCount}道菜
+- ${config.flexibleCount ? `参考菜品数量:${config.dishCount}道菜(可以根据实际情况智能调整,重点是搭配合理)` : `菜品数量:${config.dishCount}道菜(请严格按照这个数量生成)`}
 - 口味偏好:${tasteText}
 - 菜系风格:${styleMap[config.cuisineStyle] || '混合菜系'}
 - 用餐场景:${sceneMap[config.diningScene] || '家庭聚餐'}
 - 营养搭配:${nutritionMap[config.nutritionFocus] || '营养均衡'}`
 
         if (config.customDishes.length > 0) {
-            prompt += `\n- 必须包含的菜品:${config.customDishes.join('、')}`
+            prompt += `\n- ${config.flexibleCount ? '优先考虑的菜品' : '必须包含的菜品'}:${config.customDishes.join('、')}${
+                config.flexibleCount ? '(可以作为参考,根据搭配需要决定是否全部包含)' : '(请确保这些菜品都包含在菜单中)'
+            }`
         }
 
         if (config.customRequirement) {
             prompt += `\n- 特殊要求:${config.customRequirement}`
         }
 
+        if (config.flexibleCount) {
+            prompt += `
+
+智能搭配原则:
+1. 菜品数量可以灵活调整(建议在${Math.max(2, config.dishCount - 2)}-${config.dishCount + 2}道之间),重点是搭配合理、营养均衡
+2. 每道菜应该有独特的特色,避免食材和口味重复过多
+3. 如果指定的菜品较少或重复度高,可以适当减少总菜品数量,确保每道菜都有特色
+4. 优先考虑菜品的多样性和营养搭配,而不是强制凑够指定数量
+5. 合理搭配不同类型的菜品:主菜、素菜、汤品、凉菜、主食等
+6. 避免出现重复搭配,每道菜都应该有独特价值`
+        } else {
+            prompt += `
+
+固定数量原则:
+1. 严格按照${config.dishCount}道菜的数量生成菜单
+2. 确保菜品搭配合理,营养均衡
+3. 每道菜都有独特特色,尽量避免食材重复
+4. 合理分配不同类型的菜品:主菜、素菜、汤品、凉菜、主食等`
+        }
+
         prompt += `
 
-请按照以下JSON格式返回菜单,确保菜品搭配合理,营养均衡:
+请按照以下JSON格式返回菜单:
 {
   "dishes": [
     {

+ 340 - 217
src/views/TableDesign.vue

@@ -31,257 +31,342 @@
             </div>
         </div>
 
-        <div class="max-w-7xl mx-auto py-6">
-            <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-10 mt-2">
-                <!-- 步骤1: 配置菜品数量 -->
-                <div class="mb-6 mt-4">
-                    <div class="bg-pink-400 text-white px-4 py-2 rounded-t-lg border-2 border-black border-b-0 inline-block">
-                        <span class="font-bold">1. 配置菜品数量</span>
+        <div class="max-w-7xl mx-auto">
+            <!-- 步骤1和2: 左右布局 -->
+            <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
+                <!-- 左侧: 步骤1 菜品配置 -->
+                <div class="mt-6">
+                    <div class="bg-gradient-to-r from-orange-400 to-pink-400 text-white px-4 py-2 rounded-t-lg border-2 border-black border-b-0 inline-block">
+                        <span class="font-bold">1. 菜品配置</span>
                     </div>
-                    <div class="bg-white border-2 border-black rounded-lg rounded-tl-none p-4 md:p-6 h-full">
-                        <div class="text-center mb-6">
-                            <div class="w-16 h-16 bg-black rounded-lg flex items-center justify-center mx-auto mb-4">
-                                <span class="text-white text-2xl">🍽️</span>
-                            </div>
-                            <h2 class="text-xl font-bold text-dark-800 mb-2">选择菜品数量</h2>
-                            <p class="text-gray-600 text-sm">根据用餐人数和场合选择合适的菜品数量</p>
-                        </div>
-
-                        <!-- 预设数量按钮 -->
-                        <div class="flex justify-center gap-2 flex-wrap mb-4">
-                            <button
-                                v-for="count in [2, 4, 6, 8]"
-                                :key="count"
-                                @click="config.dishCount = count"
-                                :class="[
-                                    'px-4 py-2 rounded-lg font-bold border-2 border-black transition-all duration-200 transform hover:scale-105 text-sm',
-                                    config.dishCount === count ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
-                                ]"
-                            >
-                                {{ count }}道菜
-                            </button>
-                        </div>
-
-                        <!-- 自定义数量输入 -->
-                        <div class="max-w-xs mx-auto">
-                            <div class="text-center mb-3">
-                                <span class="text-sm text-gray-600">或自定义数量</span>
-                            </div>
-                            <div class="flex justify-center">
-                                <div class="relative">
-                                    <input
-                                        v-model.number="config.dishCount"
-                                        @input="validateDishCount"
-                                        type="number"
-                                        min="1"
-                                        max="20"
-                                        class="w-20 px-3 py-2 text-center border-2 border-black rounded-lg font-bold text-base focus:outline-none focus:ring-2 focus:ring-pink-400"
-                                    />
-                                    <span class="absolute -right-10 top-1/2 transform -translate-y-1/2 text-sm text-gray-500 whitespace-nowrap">道菜</span>
-                                </div>
-                            </div>
-                            <div class="text-center mt-2">
-                                <span class="text-xs text-gray-500">建议1-20道菜</span>
+                    <div class="bg-white border-2 border-black rounded-lg rounded-tl-none p-4 h-full">
+                        <!-- 生成模式选择 - 紧凑布局 -->
+                        <div class="mb-4">
+                            <h3 class="text-lg font-bold text-dark-800 mb-3 flex items-center gap-2">
+                                <span class="text-xl">🍽️</span>
+                                <span>选择生成模式</span>
+                            </h3>
+                            <div class="grid grid-cols-1 gap-3">
+                                <button
+                                    @click="config.flexibleCount = false"
+                                    :class="[
+                                        'px-4 py-3 rounded-lg font-bold border-2 border-black transition-all duration-200 text-left flex items-center gap-3',
+                                        !config.flexibleCount ? 'bg-yellow-400 text-dark-800 shadow-lg' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+                                    ]"
+                                >
+                                    <span class="text-xl">🎯</span>
+                                    <div>
+                                        <div class="font-bold text-sm">固定数量模式</div>
+                                        <div class="text-xs opacity-75">指定确切菜品数量</div>
+                                    </div>
+                                </button>
+                                <button
+                                    @click="config.flexibleCount = true"
+                                    :class="[
+                                        'px-4 py-3 rounded-lg font-bold border-2 border-black transition-all duration-200 text-left flex items-center gap-3',
+                                        config.flexibleCount ? 'bg-yellow-400 text-dark-800 shadow-lg' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+                                    ]"
+                                >
+                                    <span class="text-xl">✨</span>
+                                    <div>
+                                        <div class="font-bold text-sm">智能搭配模式</div>
+                                        <div class="text-xs opacity-75">AI智能决定数量和搭配</div>
+                                    </div>
+                                </button>
                             </div>
                         </div>
-                    </div>
-                </div>
 
-                <!-- 步骤2: 指定菜品 -->
-                <div class="mb-6 mt-4">
-                    <div class="bg-orange-400 text-white px-4 py-2 rounded-t-lg border-2 border-black border-b-0 inline-block">
-                        <span class="font-bold">2. 指定菜品(可选)</span>
-                    </div>
-                    <div class="bg-white border-2 border-black rounded-lg rounded-tl-none p-4 md:p-6 h-full">
-                        <!-- 右侧:指定菜品 -->
-                        <div>
-                            <div class="text-center mb-6">
-                                <div class="w-16 h-16 bg-orange-500 rounded-lg flex items-center justify-center mx-auto mb-4">
-                                    <span class="text-white text-2xl">🥘</span>
+                        <!-- 配置内容 - 紧凑布局 -->
+                        <div class="space-y-4">
+                            <!-- 固定数量模式配置 -->
+                            <div v-if="!config.flexibleCount">
+                                <!-- 数量选择 -->
+                                <div class="bg-gray-50 rounded-lg p-3 border-2 border-gray-200">
+                                    <h5 class="text-sm font-bold text-gray-700 mb-2 flex items-center gap-1">🍽️ 菜品数量</h5>
+                                    <div class="flex items-center gap-3 flex-wrap">
+                                        <div class="flex gap-2">
+                                            <button
+                                                v-for="count in [2, 4, 6, 8]"
+                                                :key="count"
+                                                @click="config.dishCount = count"
+                                                :class="[
+                                                    'px-3 py-1 rounded-lg font-bold border-2 border-black transition-all duration-200 text-sm',
+                                                    config.dishCount === count ? 'bg-yellow-400 text-dark-800' : 'bg-white text-gray-700 hover:bg-gray-100'
+                                                ]"
+                                            >
+                                                {{ count }}道
+                                            </button>
+                                        </div>
+                                        <div class="h-4 w-px bg-gray-300"></div>
+                                        <div class="flex items-center gap-2">
+                                            <span class="text-sm text-gray-600">自定义</span>
+                                            <input
+                                                v-model.number="config.dishCount"
+                                                @input="validateDishCount"
+                                                type="number"
+                                                min="1"
+                                                max="20"
+                                                class="w-14 px-2 py-1 text-center border-2 border-black rounded-lg font-bold text-sm focus:outline-none focus:ring-2 focus:ring-pink-400"
+                                            />
+                                            <span class="text-sm text-gray-600">道</span>
+                                        </div>
+                                    </div>
                                 </div>
-                                <h2 class="text-xl font-bold text-dark-800 mb-2">指定想要的菜品</h2>
-                                <p class="text-gray-600 text-sm">可以指定一些您特别想要的菜品,AI会优先考虑</p>
-                            </div>
 
-                            <!-- 已添加的自定义菜品 -->
-                            <div v-if="config.customDishes.length > 0" class="mb-4">
-                                <div class="flex flex-wrap gap-2 justify-center">
-                                    <div
-                                        v-for="dish in config.customDishes"
-                                        :key="dish"
-                                        class="inline-flex items-center gap-2 bg-yellow-400 text-dark-800 px-3 py-2 rounded-full text-sm font-medium border-2 border-black"
-                                    >
-                                        {{ dish }}
-                                        <button @click="removeCustomDish(dish)" class="hover:bg-yellow-500 rounded-full p-1 transition-colors">
-                                            <span class="text-xs">✕</span>
+                                <!-- 可选菜品 -->
+                                <div class="bg-gray-50 rounded-lg p-3 border-2 border-gray-200">
+                                    <h5 class="text-sm font-bold text-gray-700 mb-2 flex items-center gap-1">🥘 指定菜品(可选)</h5>
+                                    <div v-if="config.customDishes.length > 0" class="mb-3">
+                                        <div class="flex flex-wrap gap-2">
+                                            <div
+                                                v-for="dish in config.customDishes"
+                                                :key="dish"
+                                                class="inline-flex items-center gap-1 bg-yellow-400 text-dark-800 px-2 py-1 rounded-full text-sm font-medium border-2 border-black"
+                                            >
+                                                {{ dish }}
+                                                <button @click="removeCustomDish(dish)" class="hover:bg-yellow-500 rounded-full p-1 transition-colors">
+                                                    <span class="text-xs">✕</span>
+                                                </button>
+                                            </div>
+                                        </div>
+                                    </div>
+                                    <div class="relative">
+                                        <input
+                                            v-model="currentCustomDish"
+                                            @keyup.enter="addCustomDish"
+                                            placeholder="输入菜品名称,按回车添加..."
+                                            class="w-full p-2 border-2 border-black rounded-lg text-sm font-medium focus:outline-none focus:ring-2 focus:ring-pink-400"
+                                        />
+                                        <button
+                                            @click="addCustomDish"
+                                            :disabled="!currentCustomDish.trim() || config.customDishes.length >= 10"
+                                            class="absolute right-2 top-1/2 transform -translate-y-1/2 px-2 py-1 bg-pink-400 hover:bg-pink-500 disabled:bg-gray-300 text-white rounded text-xs font-bold transition-colors disabled:cursor-not-allowed"
+                                        >
+                                            添加
                                         </button>
                                     </div>
+                                    <div class="flex justify-between items-center mt-1 text-xs text-gray-500">
+                                        <span>💡 例如:红烧肉、清蒸鱼</span>
+                                        <span>{{ config.customDishes.length }}/10</span>
+                                    </div>
                                 </div>
                             </div>
 
-                            <!-- 菜品输入框 -->
-                            <div class="max-w-md mx-auto">
-                                <div class="relative">
-                                    <input
-                                        v-model="currentCustomDish"
-                                        @keyup.enter="addCustomDish"
-                                        placeholder="输入菜品名称,按回车添加..."
-                                        class="w-full p-3 border-2 border-black rounded-lg text-sm font-medium focus:outline-none focus:ring-2 focus:ring-pink-400"
-                                    />
-                                    <button
-                                        @click="addCustomDish"
-                                        :disabled="!currentCustomDish.trim() || config.customDishes.length >= 10"
-                                        class="absolute right-2 top-1/2 transform -translate-y-1/2 px-3 py-1 bg-pink-400 hover:bg-pink-500 disabled:bg-gray-300 text-white rounded text-xs font-bold transition-colors disabled:cursor-not-allowed"
-                                    >
-                                        添加
-                                    </button>
-                                </div>
-                                <div class="flex justify-between items-center mt-2 text-xs text-gray-500">
-                                    <span>💡 例如:红烧肉、清蒸鱼、麻婆豆腐</span>
-                                    <span>{{ config.customDishes.length }}/10</span>
+                            <!-- 智能搭配模式配置 -->
+                            <div v-else>
+                                <div class="bg-gray-50 rounded-lg p-3 border-2 border-gray-200">
+                                    <h5 class="text-sm font-bold text-gray-700 mb-2 flex items-center gap-1">🥘 输入想要的菜品</h5>
+                                    <div v-if="config.customDishes.length === 0" class="mb-3 p-2 bg-orange-50 border-2 border-orange-200 rounded-lg">
+                                        <p class="text-xs text-orange-700">
+                                            <span class="font-medium">⚠️ 智能搭配模式需要您先输入至少一道菜品</span>
+                                        </p>
+                                    </div>
+                                    <div v-if="config.customDishes.length > 0" class="mb-3">
+                                        <div class="flex flex-wrap gap-2">
+                                            <div
+                                                v-for="dish in config.customDishes"
+                                                :key="dish"
+                                                class="inline-flex items-center gap-1 bg-green-400 text-dark-800 px-2 py-1 rounded-full text-sm font-medium border-2 border-black"
+                                            >
+                                                {{ dish }}
+                                                <button @click="removeCustomDish(dish)" class="hover:bg-green-500 rounded-full p-1 transition-colors">
+                                                    <span class="text-xs">✕</span>
+                                                </button>
+                                            </div>
+                                        </div>
+                                    </div>
+                                    <div class="relative">
+                                        <input
+                                            v-model="currentCustomDish"
+                                            @keyup.enter="addCustomDish"
+                                            placeholder="输入菜品名称,按回车添加..."
+                                            class="w-full p-2 border-2 border-black rounded-lg text-sm font-medium focus:outline-none focus:ring-2 focus:ring-green-400"
+                                        />
+                                        <button
+                                            @click="addCustomDish"
+                                            :disabled="!currentCustomDish.trim() || config.customDishes.length >= 10"
+                                            class="absolute right-2 top-1/2 transform -translate-y-1/2 px-2 py-1 bg-green-400 hover:bg-green-500 disabled:bg-gray-300 text-white rounded text-xs font-bold transition-colors disabled:cursor-not-allowed"
+                                        >
+                                            添加
+                                        </button>
+                                    </div>
+                                    <div class="flex justify-between items-center mt-1 text-xs text-gray-500">
+                                        <span>💡 例如:包菜、娃娃菜、土豆</span>
+                                        <span>{{ config.customDishes.length }}/10</span>
+                                    </div>
                                 </div>
                             </div>
-
-                            <!-- 提示信息 -->
-                            <div class="mt-4 p-3 bg-blue-50 border-2 border-blue-200 rounded-lg">
-                                <p class="text-sm text-blue-700 text-center">
-                                    <span class="font-medium">提示:</span>
-                                    指定的菜品会优先出现在菜单中,剩余菜品由AI根据您的口味和风格偏好自动搭配
-                                </p>
-                            </div>
                         </div>
                     </div>
                 </div>
-            </div>
 
-            <!-- 步骤2和3: 左右布局 -->
-            <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
-                <!-- 步骤2: 选择口味和风格 -->
-                <div>
-                    <div class="bg-green-400 text-white px-4 py-2 rounded-t-lg border-2 border-black border-b-0 inline-block">
-                        <span class="font-bold">3. 选择口味和风格</span>
+                <!-- 右侧: 步骤2 偏好设置(可选) -->
+                <div class="md:mt-6 mt-10">
+                    <div class="bg-gradient-to-r from-green-400 to-blue-400 text-white px-4 py-2 rounded-t-lg border-2 border-black border-b-0 inline-block">
+                        <span class="font-bold">2. 偏好设置(可选)</span>
                     </div>
-                    <div class="bg-white border-2 border-black rounded-lg rounded-tl-none p-4 md:p-6 h-full">
-                        <!-- 口味偏好 -->
-                        <div class="mb-6">
-                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">👅 口味偏好</h5>
-                            <div class="grid grid-cols-2 gap-2">
-                                <button
-                                    v-for="taste in tasteOptions"
-                                    :key="taste.id"
-                                    @click="toggleTaste(taste.id)"
-                                    :class="[
-                                        'p-2 rounded-lg border-2 border-black font-medium text-xs transition-all duration-200 flex items-center justify-center gap-1',
-                                        config.tastes.includes(taste.id) ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
-                                    ]"
-                                >
-                                    <span>{{ taste.icon }}</span>
-                                    <span>{{ taste.name }}</span>
-                                </button>
-                            </div>
+                    <div class="bg-white border-2 border-black rounded-lg rounded-tl-none p-4 h-full">
+                        <!-- 提示信息 -->
+                        <div class="mb-4 p-3 bg-blue-50 border-2 border-blue-200 rounded-lg">
+                            <p class="text-sm text-blue-700">
+                                <span class="font-medium">💡 可选配置:</span>
+                                以下设置为可选项,不设置也能生成精彩菜单。
+                            </p>
                         </div>
 
-                        <!-- 菜系风格 -->
-                        <div class="mb-6">
-                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">🌍 菜系风格</h5>
-                            <div class="grid grid-cols-2 gap-2">
+                        <!-- 可折叠的配置选项 -->
+                        <div class="space-y-4">
+                            <!-- 口味和风格设置 -->
+                            <div class="border-2 border-gray-200 rounded-lg">
                                 <button
-                                    v-for="style in cuisineStyles"
-                                    :key="style.id"
-                                    @click="config.cuisineStyle = style.id"
-                                    :class="[
-                                        'p-2 rounded-lg border-2 border-black font-medium text-xs transition-all duration-200 flex items-center justify-center gap-1',
-                                        config.cuisineStyle === style.id ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
-                                    ]"
+                                    @click="showTasteSettings = !showTasteSettings"
+                                    class="w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 rounded-lg font-medium text-left flex items-center justify-between transition-colors"
                                 >
-                                    <span>{{ style.icon }}</span>
-                                    <span>{{ style.name }}</span>
+                                    <div class="flex items-center gap-2">
+                                        <span class="text-lg">🍽️</span>
+                                        <span class="font-bold text-gray-800">口味和风格设置</span>
+                                    </div>
+                                    <span class="text-gray-500 transform transition-transform" :class="{ 'rotate-180': showTasteSettings }">▼</span>
                                 </button>
-                            </div>
-                        </div>
 
-                        <!-- 用餐场景 -->
-                        <div>
-                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">🎭 用餐场景</h5>
-                            <div class="grid grid-cols-2 gap-2">
-                                <button
-                                    v-for="scene in diningScenes"
-                                    :key="scene.id"
-                                    @click="config.diningScene = scene.id"
-                                    :class="[
-                                        'p-2 rounded-lg border-2 border-black font-medium text-xs transition-all duration-200 flex items-center justify-center gap-1',
-                                        config.diningScene === scene.id ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
-                                    ]"
-                                >
-                                    <span>{{ scene.icon }}</span>
-                                    <span>{{ scene.name }}</span>
-                                </button>
+                                <Transition name="collapse">
+                                    <div v-show="showTasteSettings" class="p-4 border-t-2 border-gray-200 space-y-6">
+                                        <!-- 口味偏好 -->
+                                        <div>
+                                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">👅 口味偏好</h5>
+                                            <div class="grid grid-cols-2 md:grid-cols-3 gap-2">
+                                                <button
+                                                    v-for="taste in tasteOptions"
+                                                    :key="taste.id"
+                                                    @click="toggleTaste(taste.id)"
+                                                    :class="[
+                                                        'p-2 rounded-lg border-2 border-black font-medium text-xs transition-all duration-200 flex items-center justify-center gap-1',
+                                                        config.tastes.includes(taste.id) ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+                                                    ]"
+                                                >
+                                                    <span>{{ taste.icon }}</span>
+                                                    <span>{{ taste.name }}</span>
+                                                </button>
+                                            </div>
+                                        </div>
+
+                                        <!-- 菜系风格 -->
+                                        <div>
+                                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">🌍 菜系风格</h5>
+                                            <div class="grid grid-cols-2 md:grid-cols-4 gap-2">
+                                                <button
+                                                    v-for="style in cuisineStyles"
+                                                    :key="style.id"
+                                                    @click="config.cuisineStyle = style.id"
+                                                    :class="[
+                                                        'p-2 rounded-lg border-2 border-black font-medium text-xs transition-all duration-200 flex items-center justify-center gap-1',
+                                                        config.cuisineStyle === style.id ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+                                                    ]"
+                                                >
+                                                    <span>{{ style.icon }}</span>
+                                                    <span>{{ style.name }}</span>
+                                                </button>
+                                            </div>
+                                        </div>
+
+                                        <!-- 用餐场景 -->
+                                        <div>
+                                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">🎭 用餐场景</h5>
+                                            <div class="grid grid-cols-2 md:grid-cols-3 gap-2">
+                                                <button
+                                                    v-for="scene in diningScenes"
+                                                    :key="scene.id"
+                                                    @click="config.diningScene = scene.id"
+                                                    :class="[
+                                                        'p-2 rounded-lg border-2 border-black font-medium text-xs transition-all duration-200 flex items-center justify-center gap-1',
+                                                        config.diningScene === scene.id ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+                                                    ]"
+                                                >
+                                                    <span>{{ scene.icon }}</span>
+                                                    <span>{{ scene.name }}</span>
+                                                </button>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </Transition>
                             </div>
-                        </div>
-                    </div>
-                </div>
 
-                <!-- 步骤3: 营养搭配和特殊要求 -->
-                <div class="max-sm:mt-10">
-                    <div class="bg-orange-400 text-white px-4 py-2 rounded-t-lg border-2 border-black border-b-0 inline-block">
-                        <span class="font-bold">4. 营养搭配和特殊要求</span>
-                    </div>
-                    <div class="bg-white border-2 border-black rounded-lg rounded-tl-none p-4 md:p-6 h-full">
-                        <!-- 营养搭配 -->
-                        <div class="mb-6">
-                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">⚖️ 营养搭配</h5>
-                            <div class="grid grid-cols-2 gap-2">
+                            <!-- 营养和特殊要求设置 -->
+                            <div class="border-2 border-gray-200 rounded-lg">
                                 <button
-                                    v-for="nutrition in nutritionOptions"
-                                    :key="nutrition.id"
-                                    @click="config.nutritionFocus = nutrition.id"
-                                    :class="[
-                                        'p-2 rounded-lg border-2 border-black font-medium text-xs transition-all duration-200 flex items-center justify-center gap-1',
-                                        config.nutritionFocus === nutrition.id ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
-                                    ]"
+                                    @click="showNutritionSettings = !showNutritionSettings"
+                                    class="w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 rounded-lg font-medium text-left flex items-center justify-between transition-colors"
                                 >
-                                    <span>{{ nutrition.icon }}</span>
-                                    <span>{{ nutrition.name }}</span>
+                                    <div class="flex items-center gap-2">
+                                        <span class="text-lg">⚖️</span>
+                                        <span class="font-bold text-gray-800">营养和特殊要求</span>
+                                    </div>
+                                    <span class="text-gray-500 transform transition-transform" :class="{ 'rotate-180': showNutritionSettings }">▼</span>
                                 </button>
-                            </div>
-                        </div>
 
-                        <!-- 特殊要求 -->
-                        <div class="flex-1">
-                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">💭 特殊要求</h5>
-                            <textarea
-                                v-model="config.customRequirement"
-                                placeholder="例如:不要太油腻,适合老人小孩,有一道汤..."
-                                class="w-full p-3 border-2 border-black rounded-lg text-sm resize-none focus:outline-none focus:ring-2 focus:ring-pink-400"
-                                rows="4"
-                                maxlength="200"
-                            ></textarea>
-                            <div class="text-xs text-gray-500 mt-1 text-right">{{ config.customRequirement.length }}/200</div>
+                                <Transition name="collapse">
+                                    <div v-show="showNutritionSettings" class="p-4 border-t-2 border-gray-200 space-y-6">
+                                        <!-- 营养搭配 -->
+                                        <div>
+                                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">⚖️ 营养搭配</h5>
+                                            <div class="grid grid-cols-2 md:grid-cols-5 gap-2">
+                                                <button
+                                                    v-for="nutrition in nutritionOptions"
+                                                    :key="nutrition.id"
+                                                    @click="config.nutritionFocus = nutrition.id"
+                                                    :class="[
+                                                        'p-2 rounded-lg border-2 border-black font-medium text-xs transition-all duration-200 flex items-center justify-center gap-1',
+                                                        config.nutritionFocus === nutrition.id ? 'bg-yellow-400 text-dark-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+                                                    ]"
+                                                >
+                                                    <span>{{ nutrition.icon }}</span>
+                                                    <span>{{ nutrition.name }}</span>
+                                                </button>
+                                            </div>
+                                        </div>
+
+                                        <!-- 特殊要求 -->
+                                        <div>
+                                            <h5 class="text-sm font-bold text-gray-700 mb-3 flex items-center gap-1">💭 特殊要求</h5>
+                                            <textarea
+                                                v-model="config.customRequirement"
+                                                placeholder="例如:不要太油腻,适合老人小孩,有一道汤..."
+                                                class="w-full p-3 border-2 border-black rounded-lg text-sm resize-none focus:outline-none focus:ring-2 focus:ring-pink-400"
+                                                rows="3"
+                                                maxlength="200"
+                                            ></textarea>
+                                            <div class="text-xs text-gray-500 mt-1 text-right">{{ config.customRequirement.length }}/200</div>
+                                        </div>
+                                    </div>
+                                </Transition>
+                            </div>
                         </div>
 
-                        <!-- 当前配置预览 -->
-                        <div class="bg-gray-50 rounded-lg p-3 mt-4">
+                        <!-- 当前配置预览(简化版) -->
+                        <div class="bg-gray-50 rounded-lg p-3 mt-6">
                             <h6 class="font-bold text-sm text-gray-700 mb-2 flex items-center gap-2">
                                 <span>📋</span>
                                 <span>当前配置</span>
                             </h6>
                             <div class="text-xs text-gray-600 space-y-1">
-                                <div>菜品数量:{{ config.dishCount }}道菜</div>
-                                <div v-if="config.customDishes.length > 0">指定菜品:{{ config.customDishes.join('、') }}</div>
+                                <div>生成模式:{{ config.flexibleCount ? '✨ 智能搭配' : '🎯 固定数量' }}</div>
+                                <div v-if="!config.flexibleCount">菜品数量:{{ config.dishCount }}道菜</div>
+                                <div v-if="config.customDishes.length > 0">{{ config.flexibleCount ? '输入菜品' : '指定菜品' }}:{{ config.customDishes.join('、') }}</div>
                                 <div v-if="config.tastes.length > 0">口味:{{ config.tastes.map(t => tasteOptions.find(opt => opt.id === t)?.name).join('、') }}</div>
-                                <div>风格:{{ cuisineStyles.find(s => s.id === config.cuisineStyle)?.name }}</div>
-                                <div>场景:{{ diningScenes.find(s => s.id === config.diningScene)?.name }}</div>
-                                <div>营养:{{ nutritionOptions.find(n => n.id === config.nutritionFocus)?.name }}</div>
+                                <div v-if="config.cuisineStyle !== 'mixed'">风格:{{ cuisineStyles.find(s => s.id === config.cuisineStyle)?.name }}</div>
+                                <div v-if="config.diningScene !== 'family'">场景:{{ diningScenes.find(s => s.id === config.diningScene)?.name }}</div>
+                                <div v-if="config.nutritionFocus !== 'balanced'">营养:{{ nutritionOptions.find(n => n.id === config.nutritionFocus)?.name }}</div>
+                                <div v-if="config.customRequirement">特殊要求:{{ config.customRequirement }}</div>
                             </div>
                         </div>
                     </div>
                 </div>
             </div>
 
-            <!-- 步骤4: 生成一桌菜 -->
+            <!-- 步骤2: 生成一桌菜 -->
             <div class="mb-6 mt-16">
                 <div class="bg-dark-800 text-white px-4 py-2 rounded-t-lg border-2 border-black border-b-0 inline-block">
-                    <span class="font-bold">5. 生成一桌菜</span>
+                    <span class="font-bold">3. 生成一桌菜</span>
                 </div>
                 <div class="bg-white border-2 border-black rounded-lg rounded-tl-none p-4 md:p-6">
                     <!-- 生成按钮区域 -->
@@ -295,7 +380,7 @@
                         <div class="space-y-3">
                             <button
                                 @click="generateTableMenuAction"
-                                :disabled="isGenerating"
+                                :disabled="isGenerating || (config.flexibleCount && config.customDishes.length === 0)"
                                 class="w-full bg-gradient-to-r from-orange-500 to-red-500 hover:from-orange-600 hover:to-red-600 disabled:from-gray-400 disabled:to-gray-400 text-white px-6 py-3 rounded-lg font-bold text-base md:text-lg border-2 border-black transition-all duration-300 transform disabled:scale-100 disabled:cursor-not-allowed shadow-lg"
                             >
                                 <span class="flex items-center gap-2 justify-center">
@@ -303,6 +388,13 @@
                                     <span>生成一桌菜</span>
                                 </span>
                             </button>
+
+                            <!-- 智能搭配模式提示 -->
+                            <div v-if="config.flexibleCount && config.customDishes.length === 0" class="mt-3 p-3 bg-orange-50 border-2 border-orange-200 rounded-lg">
+                                <p class="text-sm text-orange-700 text-center">
+                                    <span class="font-medium">⚠️ 请先在步骤1中输入至少一道菜品</span>
+                                </p>
+                            </div>
                         </div>
                     </div>
 
@@ -324,7 +416,7 @@
                                 @click="resetConfig"
                                 class="px-4 py-2 bg-gray-500 hover:bg-gray-600 text-white rounded-lg font-bold border-2 border-black transition-all duration-200 text-sm"
                             >
-                                🔄 重新配置
+                                🔄 重新生成
                             </button>
                         </div>
 
@@ -345,7 +437,12 @@
                                     <button
                                         @click="generateDishRecipeAction(dish, index)"
                                         :disabled="dish.isGeneratingRecipe"
-                                        class="px-3 py-2 bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600 text-white rounded-lg text-sm font-bold border-2 border-black transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed"
+                                        :class="[
+                                            'px-3 py-2 text-white rounded-lg text-sm font-bold border-2 border-black transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed',
+                                            dish.recipe
+                                                ? 'bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600'
+                                                : 'bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600'
+                                        ]"
                                     >
                                         <span v-if="dish.isGeneratingRecipe" class="flex items-center gap-1">
                                             <div class="w-3 h-3 border border-white border-t-transparent rounded-full animate-spin"></div>
@@ -361,6 +458,13 @@
                 </div>
             </div>
         </div>
+
+        <!-- 底部 -->
+        <footer class="bg-white border-4 border-black max-w-7xl mx-auto px-2 mb-4 rounded-lg p-4 text-center">
+            <p class="text-sm text-gray-600">
+                © 2025 一饭封神 | <a href="https://github.com/liu-ziting/what-to-eat" target="_blank" class="text-retro-blue hover:underline">Powered by Liuziting</a>
+            </p>
+        </footer>
     </div>
 
     <!-- 菜谱弹窗 -->
@@ -396,7 +500,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, Teleport, onMounted, onUnmounted } from 'vue'
+import { ref, reactive, Teleport, Transition, onMounted, onUnmounted } from 'vue'
 import type { Recipe } from '@/types'
 import RecipeCard from '@/components/RecipeCard.vue'
 import { generateTableMenu, generateDishRecipe, testAIConnection } from '@/services/aiService'
@@ -404,6 +508,7 @@ import { generateTableMenu, generateDishRecipe, testAIConnection } from '@/servi
 // 配置选项
 interface TableConfig {
     dishCount: number
+    flexibleCount: boolean
     tastes: string[]
     cuisineStyle: string
     diningScene: string
@@ -428,9 +533,14 @@ const generatingText = ref('正在生成菜单...')
 const generatedDishes = ref<DishInfo[]>([])
 const selectedRecipe = ref<Recipe | null>(null)
 
+// 折叠状态管理
+const showTasteSettings = ref(false)
+const showNutritionSettings = ref(false)
+
 // 配置
 const config = reactive<TableConfig>({
     dishCount: 6,
+    flexibleCount: true, // 默认开启智能搭配模式
     tastes: [],
     cuisineStyle: 'mixed',
     diningScene: 'family',
@@ -659,16 +769,10 @@ onUnmounted(() => {
 
 // 重置配置
 const resetConfig = () => {
+    // 只清除生成的结果,保留用户的配置选择
     generatedDishes.value = []
     selectedRecipe.value = null
-    config.dishCount = 6
-    config.tastes = []
-    config.cuisineStyle = 'mixed'
-    config.diningScene = 'family'
-    config.nutritionFocus = 'balanced'
-    config.customRequirement = ''
-    config.customDishes = []
-    currentCustomDish.value = ''
+    // 不重置用户的配置选择,让用户可以基于当前配置重新生成
 }
 </script>
 
@@ -756,4 +860,23 @@ const resetConfig = () => {
 .scrollbar-hide::-webkit-scrollbar {
     display: none; /* Chrome, Safari and Opera */
 }
+
+/* 折叠动画 */
+.collapse-enter-active,
+.collapse-leave-active {
+    transition: all 0.3s ease;
+    overflow: hidden;
+}
+
+.collapse-enter-from,
+.collapse-leave-to {
+    max-height: 0;
+    opacity: 0;
+}
+
+.collapse-enter-to,
+.collapse-leave-from {
+    max-height: 500px;
+    opacity: 1;
+}
 </style>