Pārlūkot izejas kodu

docs(frontend): 共餐食谱美化实现计划(暖灶主题)

iwt 3 nedēļas atpakaļ
vecāks
revīzija
e5742c2434

+ 497 - 0
cfc-frontend/docs/superpowers/plans/2026-08-28-diet-redesign.md

@@ -0,0 +1,497 @@
+# 共餐 & 食谱页面美化 实现计划
+
+> **面向 AI 代理的工作者:** 必需子技能:使用 superpowers:subagent-driven-development(推荐)或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框(`- [ ]`)语法来跟踪进度。
+
+**目标:** 按「🍳 暖灶 · 家的味道」设计重做三个活跃页面:`pages/diet/index.vue`(饮食首页)、`pages/diet/meal-config.vue`(共餐配置)、`pages/diet/recommendation.vue`(食谱推荐)。纯样式/布局/文案重做,零接口与业务逻辑改动。
+
+**架构:** 每个 `.vue` 在 scoped `<style>` 顶部定义页面级 CSS 令牌变量(主橙 `#FF8C42` 渐变、米底 `#FFF7ED`、深橙 `#C2410C`、嫩绿 `#10B981`),template 结构调整为新的视觉区块,methods/data 逻辑保持不变。
+
+**技术栈:** uni-app Vue 2(Options API),微信小程序目标;flexbox 布局;无新依赖。
+
+**规格文档:** `cfc-frontend/docs/superpowers/specs/2026-08-28-diet-redesign.md`(唯一视觉契约,本节不重复细节,务必对照实现)
+
+---
+
+## 文件结构
+
+| 文件 | 职责 | 变更类型 |
+|------|------|----------|
+| `cfc-frontend/pages/diet/index.vue` | 饮食首页:今日餐桌主视觉 + 今日菜篮 + 厨房导航 + 本周饮食 | 修改 template + style |
+| `cfc-frontend/pages/diet/meal-config.vue` | 共餐配置:胶囊 tabs + 渐变餐次卡 + 成员 chips | 修改 template + style |
+| `cfc-frontend/pages/diet/recommendation.vue` | 食谱推荐:空态插图 + 餐次菜单卡 + 营养汇总 | 修改 template + style |
+
+> 三个页面相互独立、无共享状态,可并行实现(同一文件多处改动时避免并发冲突,按任务顺序在各自 commit 边界内操作)。
+
+## 全局校验命令(每个任务提交前必跑)
+
+```bash
+# 1) 提取 .vue 的 <script> 块做 JS 语法校验(在 cfc-frontend 下)
+node -e "
+const fs=require('fs');
+const s=fs.readFileSync(process.argv[1],'utf8');
+const m=s.match(/<script>([\s\S]*?)<\/script>/);
+if(!m){console.log('no script');process.exit(0)}
+new Function(m[1].replace(/import\s[^;]+;/g,'').replace(/export\s+default/,'return'));
+console.log('script OK');
+" pages/diet/index.vue
+
+# 2) 禁止模式扫描(输出应为空)
+grep -nE '\?\.|display:\s*grid|:key="[^"]*(\|\||&&|\+)' pages/diet/index.vue pages/diet/meal-config.vue pages/diet/recommendation.vue
+
+# 3) 中文类名扫描(输出应为空)
+grep -nE 'class="[^"]*[\u4e00-\u9fa5]|\.\w*[\u4e00-\u9fa5]' pages/diet/index.vue pages/diet/meal-config.vue pages/diet/recommendation.vue
+```
+
+> 注意:代理禁止执行 `npm run build:mp-weixin` / `npm run dev:mp-weixin`(项目规范),打包由用户用 HBuilderX 完成。
+
+---
+
+## 任务 1:`diet/index.vue` — 今日餐桌主视觉(替换原 page-header + 今日共餐卡片)
+
+**文件:** 修改 `cfc-frontend/pages/diet/index.vue`
+
+- [ ] **步骤 1:重写页面顶部 template(保留数据绑定,改造区块)**
+
+将原 `<view class="page-header">...</view>` + 「今日共餐」`<view class="card">` 合并为一个暖橙渐变主视觉大卡:
+
+```html
+<!-- ===== 今日餐桌主视觉 ===== -->
+<view class="dining-hero">
+  <view class="hero-top">
+    <view class="hero-icon-wrap"><text class="hero-icon">🍳</text></view>
+    <view class="hero-text">
+      <text class="hero-title">今日共餐</text>
+      <text class="hero-subtitle">{{ heroSubtitle }}</text>
+    </view>
+  </view>
+  <view class="hero-meals" v-if="hasMealConfig">
+    <view class="hero-meal" v-for="m in heroMeals" :key="m.key">
+      <text class="hero-meal-emoji">{{ m.emoji }}</text>
+      <text class="hero-meal-label">{{ m.label }}</text>
+      <text class="hero-meal-count">{{ m.count || '—' }}</text>
+    </view>
+  </view>
+  <view class="hero-empty" v-else @tap="navTo('/pages/diet/meal-config')">
+    <text class="hero-empty-text">还没设置共餐?点这里安排家人一起吃饭</text>
+    <view class="hero-empty-btn">去设置共餐</view>
+  </view>
+</view>
+```
+
+- [ ] **步骤 2:在 `<script>` 增加 `heroSubtitle` / `heroMeals` / `hasMealConfig` 计算字段(不改接口)**
+
+在 `computed` 中新增(`methods` 原有逻辑不动):
+
+```js
+computed: {
+  heroSubtitle: function() {
+    var self = this
+    return (self.isWeekend(new Date()) ? '周末' : '工作日') + ' · 全家一起吃饭'
+  },
+  heroMeals: function() {
+    var defs = [
+      { key: 'breakfast', label: '早餐', emoji: '🌅' },
+      { key: 'lunch', label: '午餐', emoji: '☀️' },
+      { key: 'dinner', label: '晚餐', emoji: '🌙' }
+    ]
+    var self = this
+    return defs.map(function(d) {
+      return { key: d.key, label: d.label, emoji: d.emoji, count: self.mealSummary[d.key] || '' }
+    })
+  },
+  hasMealConfig: function() {
+    return !!(this.mealSummary.breakfast || this.mealSummary.lunch || this.mealSummary.dinner)
+  }
+}
+```
+
+- [ ] **步骤 3:新增今日餐桌主视觉样式(在 `<style scoped>` 顶部先定义页面令牌)**
+
+```css
+/* ===== 页面令牌(暖灶·家的味道) ===== */
+.diet-page {
+  min-height: 100vh;
+  background: linear-gradient(180deg, #FFF7ED 0%, #FFF3E6 100%);
+  overflow: hidden;
+}
+.dining-hero {
+  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  border-radius: 32rpx;
+  padding: 36rpx 32rpx;
+  margin-bottom: 24rpx;
+  box-shadow: 0 8rpx 32rpx rgba(255, 140, 66, 0.25);
+}
+.hero-top { display: flex; align-items: center; margin-bottom: 24rpx; }
+.hero-icon-wrap {
+  width: 88rpx; height: 88rpx; border-radius: 50%;
+  background: rgba(255,255,255,0.22);
+  display: flex; align-items: center; justify-content: center;
+  margin-right: 20rpx; flex-shrink: 0;
+}
+.hero-icon { font-size: 44rpx; }
+.hero-title { font-size: 38rpx; font-weight: 700; color: #FFFFFF; display: block; }
+.hero-subtitle { font-size: 24rpx; color: rgba(255,255,255,0.85); margin-top: 6rpx; display: block; }
+.hero-meals { display: flex; }
+.hero-meal {
+  flex: 1; margin: 0 8rpx;
+  background: rgba(255,255,255,0.18);
+  border-radius: 20rpx; padding: 20rpx 8rpx;
+  display: flex; flex-direction: column; align-items: center;
+}
+.hero-meal:first-child { margin-left: 0; }
+.hero-meal:last-child { margin-right: 0; }
+.hero-meal-emoji { font-size: 40rpx; margin-bottom: 8rpx; }
+.hero-meal-label { font-size: 24rpx; color: #FFFFFF; }
+.hero-meal-count { font-size: 22rpx; color: rgba(255,255,255,0.9); margin-top: 6rpx; font-weight: 600; }
+.hero-empty { display: flex; flex-direction: column; align-items: center; padding: 12rpx 0; }
+.hero-empty-text { font-size: 26rpx; color: #FFFFFF; margin-bottom: 20rpx; }
+.hero-empty-btn {
+  background: #FFFFFF; color: #C2410C; font-size: 28rpx; font-weight: 600;
+  padding: 18rpx 44rpx; border-radius: 999rpx;
+}
+```
+
+- [ ] **步骤 4:运行全局校验命令(见上文「全局校验命令」)确认无脚本语法错误、无禁止模式**
+
+- [ ] **步骤 5:Commit**
+
+```bash
+git add cfc-frontend/pages/diet/index.vue
+git commit -m "feat(frontend): 饮食首页今日餐桌主视觉(暖灶主题)"
+```
+
+---
+
+## 任务 2:`diet/index.vue` — 今日菜篮 + 厨房导航 + 本周饮食
+
+**文件:** 修改 `cfc-frontend/pages/diet/index.vue`(承接任务 1)
+
+- [ ] **步骤 1:改造「今日食材推荐」卡为「今日菜篮」**
+
+template 头部改为(保留 `action-bar` 三个按钮的绑定与事件不动):
+
+```html
+<view class="card">
+  <view class="card-header">
+    <view class="card-basket-icon"><text class="card-basket-emoji">🧺</text></view>
+    <text class="card-title">今日菜篮</text>
+  </view>
+  <view class="card-body">
+    <!-- 三个按钮:class 更新,事件绑定原样 -->
+    <view class="action-bar">
+      <view class="action-btn" @tap="refreshIngredients">
+        <text class="action-btn-text">🔄 换一批</text>
+      </view>
+      <view class="action-btn action-btn-primary" @tap="showFoodPicker">
+        <text class="action-btn-text-primary">+ 添加食材</text>
+      </view>
+      <view class="action-btn action-btn-accent" @tap="generateRecipe"
+        :class="{'action-btn-disabled': selectedIngredients.length === 0}">
+        <text class="action-btn-text-accent">✨ 生成食谱</text>
+      </view>
+    </view>
+    <!-- 食材列表保留现有 v-for 结构 -->
+  </view>
+</view>
+```
+
+- [ ] **步骤 2:更新食材列表项与按钮样式(嫩绿生成按钮 + 淡橙选中态)**
+
+在 `<style scoped>` 中替换/新增:
+
+```css
+.card-basket-icon {
+  width: 64rpx; height: 64rpx; border-radius: 18rpx;
+  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  display: flex; align-items: center; justify-content: center;
+  margin-right: 16rpx; flex-shrink: 0;
+}
+.card-basket-emoji { font-size: 32rpx; }
+.action-btn-accent { background: linear-gradient(135deg, #10B981, #34D399); }
+.action-btn-text-accent { color: #FFFFFF; }
+.ingredient-item:active { background: #FFF9F0; }
+.ingredient-badge {
+  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  /* 保留现有圆角方块结构与其余属性 */
+}
+```
+
+- [ ] **步骤 3:厨房导航 5 格改暖橙系深浅渐变(保留 20% 网格与跳转)**
+
+替换 `nav-icon-*` 五个背景为暖调(可整体替换五个类名背景值,类名保留以免改 template):
+
+```css
+.nav-icon-green { background: linear-gradient(135deg, #FFF1E6, #FFE0C0); }
+.nav-icon-blue  { background: linear-gradient(135deg, #FFF7ED, #FFEEDD); }
+.nav-icon-orange{ background: linear-gradient(135deg, #FF8C42, #FFB366); }
+.nav-icon-purple{ background: linear-gradient(135deg, #FFE8D6, #FFD4B0); }
+.nav-icon-red   { background: linear-gradient(135deg, #E8F8F1, #C8F0E0); }
+.nav-item:active .nav-icon-wrap { transform: scale(0.92); }
+.nav-icon-wrap { transition: transform 0.15s ease; }
+```
+
+- [ ] **步骤 4:本周饮食卡暖化(分隔线浅橙 + 大数字橙字已具,改分隔线)**
+
+```css
+.trend-divider { background: #FDE8D0; }
+```
+
+- [ ] **步骤 5:运行全局校验命令确认无禁止模式**
+
+- [ ] **步骤 6:Commit**
+
+```bash
+git add cfc-frontend/pages/diet/index.vue
+git commit -m "feat(frontend): 饮食首页菜篮/导航/趋势暖灶主题化"
+```
+
+---
+
+## 任务 3:`diet/meal-config.vue` — 共餐配置页美化
+
+**文件:** 修改 `cfc-frontend/pages/diet/meal-config.vue`
+
+- [ ] **步骤 1:日期切换改两段式胶囊 tabs**
+
+template 的 `date-tabs` 保留结构,样式整体替换:
+
+```html
+<view class="date-tabs">
+  <view class="tab-item" :class="{'tab-active': dateType === 'weekday'}" @tap="switchDateType('weekday')">
+    <text class="tab-text">工作日</text>
+  </view>
+  <view class="tab-item" :class="{'tab-active': dateType === 'weekend'}" @tap="switchDateType('weekend')">
+    <text class="tab-text">周末</text>
+  </view>
+</view>
+```
+
+```css
+.date-tabs {
+  display: flex; background: #FFF1E6; border-radius: 999rpx;
+  padding: 6rpx; margin-bottom: 30rpx;
+}
+.tab-item {
+  flex: 1; text-align: center; padding: 18rpx 0;
+  border-radius: 999rpx; font-size: 28rpx; color: #C2410C;
+}
+.tab-active {
+  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  color: #FFFFFF; font-weight: 600;
+  box-shadow: 0 4rpx 12rpx rgba(255, 140, 66, 0.3);
+}
+```
+
+- [ ] **步骤 2:餐次卡 icon 渐变圆底 + 已选人数角标**
+
+template 的 `meal-header` 增加已选人数:
+
+```html
+<view class="meal-header">
+  <view class="meal-icon-wrap" :class="'meal-icon-' + meal.value"><text class="meal-icon">{{ meal.icon }}</text></view>
+  <text class="meal-name">{{ meal.label }}</text>
+  <text class="meal-count" v-if="meal.selectedCount > 0">已选 {{ meal.selectedCount }} 人</text>
+</view>
+```
+
+同步在 `computed.mealGroups` 的返回对象中增加 `selectedCount: ids.length`。
+
+```css
+.meal-icon-wrap { width: 72rpx; height: 72rpx; border-radius: 22rpx; display: flex; align-items: center; justify-content: center; margin-right: 16rpx; }
+.meal-icon-breakfast { background: linear-gradient(135deg, #FFB366, #FFD48A); }
+.meal-icon-lunch     { background: linear-gradient(135deg, #FBBF24, #FCD34D); }
+.meal-icon-dinner    { background: linear-gradient(135deg, #A78BFA, #C4B5FD); }
+.meal-count { font-size: 24rpx; color: #C2410C; }
+```
+
+- [ ] **步骤 3:成员 chips 选中态 + 彩色渐变字母圈**
+
+替换 `member-avatar` / `member-selected` 样式:
+
+```css
+.member-item {
+  box-sizing: border-box; position: relative;
+  display: flex; flex-direction: column; align-items: center; justify-content: center;
+  padding: 16rpx 20rpx; border: 2rpx solid #E0E0E0; border-radius: 20rpx;
+  background: #FAFAFA; min-width: 132rpx;
+  transition: all 0.15s ease;
+}
+.member-selected {
+  border-color: #FF8C42; border-width: 3rpx;
+  background: #FFF5EB; box-shadow: 0 0 0 4rpx rgba(255, 140, 66, 0.18);
+}
+.member-avatar {
+  width: 60rpx; height: 60rpx; border-radius: 50%;
+  color: #FFFFFF; display: flex; align-items: center; justify-content: center;
+  font-size: 24rpx; font-weight: 600; margin-bottom: 8rpx;
+}
+/* 底色按 gender:需在 template 的成员对象上加 _avatarCls,methods 中根据 m.gender 映射 */
+.member-avatar-male   { background: linear-gradient(135deg, #5B9BD5, #8FC5E8); }
+.member-avatar-female { background: linear-gradient(135deg, #F472B6, #F9A8D4); }
+.member-avatar-unknown{ background: linear-gradient(135deg, #FF8C42, #FFB366); }
+```
+
+> 注意:`gender` 在 `meal.members` 数据中来自 `/api/family/member/list` 的 `member.gender`。在 `computed.mealGroups` 组装时给每个成员加 `_avatarCls`(用 `m.gender === 'male' ? 'member-avatar-male' : (m.gender === 'female' ? 'member-avatar-female' : 'member-avatar-unknown')`),template 用 `:class="member._avatarCls"`。**禁止在 template 内调用方法返回类名。**
+
+- [ ] **步骤 4:提示条暖橙化 + 保存按钮渐变**
+
+```css
+.tip-card { background: #FFF1E6; border-radius: 16rpx; padding: 24rpx 30rpx; margin-bottom: 30rpx; }
+.tip-text { font-size: 24rpx; color: #C2410C; line-height: 1.6; }
+.save-btn {
+  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  color: #FFFFFF; text-align: center; padding: 28rpx 0; border-radius: 999rpx;
+  font-size: 30rpx; font-weight: 600;
+  box-shadow: 0 6rpx 20rpx rgba(255, 140, 66, 0.25);
+}
+```
+
+- [ ] **步骤 5:运行全局校验命令确认无禁止模式**
+
+- [ ] **步骤 6:Commit**
+
+```bash
+git add cfc-frontend/pages/diet/meal-config.vue
+git commit -m "feat(frontend): 共餐配置页暖灶主题美化"
+```
+
+---
+
+## 任务 4:`diet/recommendation.vue` — 食谱推荐页美化
+
+**文件:** 修改 `cfc-frontend/pages/diet/recommendation.vue`
+
+- [ ] **步骤 1:空态改插图式(暖橙渐变圆 + 主文案 + 生成按钮)**
+
+template 替换空态区块:
+
+```html
+<view class="empty-state" v-if="!recommendation">
+  <view class="empty-icon-wrap"><text class="empty-icon">🍽️</text></view>
+  <text class="empty-title">今日菜单空着</text>
+  <text class="empty-sub">点击生成今日三餐食谱</text>
+  <view class="generate-btn" @tap="generateRecipe">
+    <text>生成食谱</text>
+  </view>
+</view>
+```
+
+```css
+.empty-state { display: flex; flex-direction: column; align-items: center; padding: 120rpx 40rpx; }
+.empty-icon-wrap {
+  width: 160rpx; height: 160rpx; border-radius: 50%;
+  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  display: flex; align-items: center; justify-content: center;
+  box-shadow: 0 10rpx 30rpx rgba(255, 140, 66, 0.3);
+  margin-bottom: 40rpx;
+}
+.empty-icon { font-size: 72rpx; }
+.empty-title { font-size: 34rpx; font-weight: 700; color: #333; display: block; margin-bottom: 16rpx; }
+.empty-sub { font-size: 26rpx; color: #999; display: block; margin-bottom: 48rpx; }
+.generate-btn {
+  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  color: #FFFFFF; padding: 28rpx 60rpx; border-radius: 999rpx;
+  font-size: 30rpx; font-weight: 600;
+  box-shadow: 0 6rpx 20rpx rgba(255, 140, 66, 0.25);
+}
+```
+
+- [ ] **步骤 2:日期卡 + 状态徽章 + 餐次菜单卡(渐变 icon + 淡橙菜品块)**
+
+`card-accent` 改为橙渐变竖条、`meal-header` 增加渐变 icon 圆底(复用任务 3 的三餐配色类)、`dish-item` 改淡橙底块:
+
+```css
+.card-accent { width: 8rpx; background: linear-gradient(180deg, #FF8C42, #FFB366); flex-shrink: 0; }
+.status-pending { background: #FFF1E6; color: #C2410C; }
+.meal-header { display: flex; align-items: center; padding: 24rpx 30rpx; border-bottom: 1rpx solid #FDE8D0; }
+.meal-icon-wrap { width: 64rpx; height: 64rpx; border-radius: 20rpx; display: flex; align-items: center; justify-content: center; margin-right: 16rpx; }
+.meal-icon-breakfast { background: linear-gradient(135deg, #FFB366, #FFD48A); }
+.meal-icon-lunch     { background: linear-gradient(135deg, #FBBF24, #FCD34D); }
+.meal-icon-dinner    { background: linear-gradient(135deg, #A78BFA, #C4B5FD); }
+.dish-item { padding: 24rpx; border-radius: 20rpx; background: #FFF9F0; margin-bottom: 16rpx; }
+.dish-item:last-child { margin-bottom: 0; }
+.dish-name { font-size: 28rpx; font-weight: 600; color: #333; }
+.dish-cal { font-size: 24rpx; color: #C2410C; font-weight: 600; }
+```
+
+> 注意:餐次 icon 需要 `meal.type` 映射(`breakfast/lunch/dinner`)。在 `parseMenu()` 组装 `self.meals` 时给每个 meal 加 `iconCls` 字段(如 `'meal-icon-' + meal.type`),template 用 `:class="meal.iconCls"`。**禁止在 template 内方法调用。**
+
+- [ ] **步骤 3:操作按钮升级为图标+文字胶囊**
+
+template 的 `dish-actions` 三个按钮改为「图标 + 文字」(保留 `@tap` 事件绑定):
+
+```html
+<view class="dish-actions">
+  <view class="action-btn like-btn" @tap="likeDish(meal.name, dIndex)">👍 好吃</view>
+  <view class="action-btn swap-btn" @tap="swapDish(meal.name, dIndex)">🔄 替换</view>
+  <view class="action-btn skip-btn" @tap="skipDish(meal.name, dIndex)">✕ 跳过</view>
+</view>
+```
+
+```css
+.dish-actions { display: flex; gap: 16rpx; margin-top: 8rpx; }
+.action-btn { padding: 12rpx 26rpx; border-radius: 999rpx; font-size: 24rpx; }
+.like-btn { background: #E8F5E9; color: #4CAF50; }
+.swap-btn { background: #E8F1FB; color: #2196F3; }
+.skip-btn { background: #FFEBEE; color: #F44336; }
+```
+
+- [ ] **步骤 4:营养汇总卡浅暖底 + 宫格分隔浅橙**
+
+```css
+.nutrition-card .card-body { background: #FFF9F0; border-radius: 0 0 20rpx 20rpx; }
+.nutrition-value { font-size: 40rpx; font-weight: 700; color: #C2410C; display: block; }
+```
+
+- [ ] **步骤 5:底部操作(重新生成描边 / 标记完成渐变)**
+
+```css
+.btn-secondary {
+  flex: 1; padding: 28rpx 0; background: #FFFFFF;
+  border: 2rpx solid #FF8C42; border-radius: 999rpx;
+  text-align: center; font-size: 28rpx; color: #C2410C;
+}
+.btn-primary {
+  flex: 1; padding: 28rpx 0;
+  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  border-radius: 999rpx; text-align: center;
+  font-size: 28rpx; color: #FFFFFF; font-weight: 600;
+  box-shadow: 0 6rpx 20rpx rgba(255, 140, 66, 0.25);
+}
+```
+
+- [ ] **步骤 6:运行全局校验命令确认无禁止模式**
+
+- [ ] **步骤 7:Commit**
+
+```bash
+git add cfc-frontend/pages/diet/recommendation.vue
+git commit -m "feat(frontend): 食谱推荐页暖灶主题美化"
+```
+
+---
+
+## 任务 5:跨页一致性复核 + 收尾
+
+**文件:** 全部三个页面(只读复核)
+
+- [ ] **步骤 1:核对规格 §设计令牌 的色值在三个页面 scoped 样式中的使用是否统一**(主橙 `#FF8C42`、深橙 `#C2410C`、米底 `#FFF7ED`、嫩绿 `#10B981` 出现位置与规格一致)
+
+- [ ] **步骤 2:复核业务逻辑零改动**:`git diff` 三个文件,确认 `methods`/`data`/`onLoad`/`onShow` 仅新增 computed 字段与类映射字段,未改任何接口调用、参数、跳转路径
+
+- [ ] **步骤 3:跑一次全量校验命令(三文件同时)确认最终无禁止模式**
+
+- [ ] **步骤 4:Commit(若有遗漏修正)**
+
+```bash
+git add cfc-frontend/pages/diet/index.vue cfc-frontend/pages/diet/meal-config.vue cfc-frontend/pages/diet/recommendation.vue
+git commit -m "fix(frontend): 饮食三页暖灶主题一致性复核修正"
+```
+
+---
+
+## 自检记录
+
+- [ ] **规格覆盖度**:规格 §1(index 四区块)→ 任务1+2;§2(meal-config 五小节)→ 任务3;§3(recommendation 五小节)→ 任务4;令牌/约束 → 各任务样式与校验
+- [ ] **占位符扫描**:无 TODO/待定;每个样式步骤含实际 CSS 代码
+- [ ] **类型一致性**:`meal.iconCls`、`member._avatarCls`、`heroMeals[].key` 等字段在对应 computed 中定义后才在 template 使用