Browse Source

Merge remote-tracking branch 'origin/cfclub' into cfclub

Sisyphus 1 week ago
parent
commit
ae6adc3d13
40 changed files with 2319 additions and 691 deletions
  1. 5 1
      cfc-frontend/components/RecommendedFeed.vue
  2. 121 0
      cfc-frontend/docs/dimension-pages-login-state-plan.md
  3. 12 0
      cfc-frontend/pages.json
  4. 34 34
      cfc-frontend/pages/action-detail/index.vue
  5. 5 3
      cfc-frontend/pages/activity/activity-detail/activity-detail.vue
  6. 5 3
      cfc-frontend/pages/activity/index.vue
  7. 5 1
      cfc-frontend/pages/ai/chat.vue
  8. 5 1
      cfc-frontend/pages/article-center/index.vue
  9. 5 1
      cfc-frontend/pages/article-center/my-posts.vue
  10. 5 1
      cfc-frontend/pages/body-detail/dimension-detail.vue
  11. 65 65
      cfc-frontend/pages/body-detail/index.vue
  12. 5 1
      cfc-frontend/pages/discover/index.vue
  13. 12 3
      cfc-frontend/pages/growth/upload.vue
  14. 12 3
      cfc-frontend/pages/guide/activities/detail.vue
  15. 12 3
      cfc-frontend/pages/guide/activities/index.vue
  16. 12 3
      cfc-frontend/pages/guide/packages/share.vue
  17. 12 3
      cfc-frontend/pages/index-home/index.vue
  18. 12 3
      cfc-frontend/pages/meal/recipe-detail.vue
  19. 12 3
      cfc-frontend/pages/mind-detail/articles.vue
  20. 76 76
      cfc-frontend/pages/mind-detail/index.vue
  21. 12 3
      cfc-frontend/pages/promotion/material.vue
  22. 12 3
      cfc-frontend/pages/shop/cart/cart.vue
  23. 12 3
      cfc-frontend/pages/shop/checkout/checkout.vue
  24. 12 3
      cfc-frontend/pages/shop/index/index.vue
  25. 12 3
      cfc-frontend/pages/shop/order-detail/order-detail.vue
  26. 12 3
      cfc-frontend/pages/shop/order-list/order-list.vue
  27. 29 17
      cfc-frontend/pages/teacher/families.vue
  28. 166 0
      cfc-frontend/pages/teacher/plan-create.vue
  29. 231 0
      cfc-frontend/pages/teacher/plan-list.vue
  30. 5 1
      cfc-frontend/pages/vendor/products/products.vue
  31. 56 51
      cfc-frontend/pages/wealth/index.vue
  32. 46 46
      cfc-frontend/pages/wisdom-detail/index.vue
  33. 64 1
      cfc-frontend/uni.scss
  34. 12 38
      docs/参考资料/530010234-侯.json
  35. 36 62
      docs/参考资料/547982403.json
  36. 29 59
      docs/参考资料/556168709-mi.json
  37. 13 80
      docs/参考资料/儿童示例.json
  38. 355 27
      docs/参考资料/朱评估报告.json
  39. 642 58
      docs/参考资料/知识库/菌群营养知识库.json
  40. 131 25
      docs/参考资料/知识库/菌群营养知识库.md

+ 5 - 1
cfc-frontend/components/RecommendedFeed.vue

@@ -128,7 +128,11 @@ export default {
       return map[status] || ''
     },
     getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     }
   }
 }

+ 121 - 0
cfc-frontend/docs/dimension-pages-login-state-plan.md

@@ -0,0 +1,121 @@
+# 五维主页面 · 登录前 / 登录后 显示规划
+
+> **范围**:`pages/body-detail`(身)、`pages/wisdom-detail`(智)、`pages/mind-detail`(心)、`pages/wealth`(富)、`pages/action-detail`(行)
+> **目的**:固化五个维度详情页在「登录前(游客态)」与「登录后」各自应显示的内容与顺序,作为开发与验收的唯一依据
+> **版本**:V1.0 · 2026-10-12
+> **已确认决策**(廖总拍板):① 心页 PageBanner 维持「心智合一」双色;② 身 / 智保留 `preview-text`(统一五页骨架文案);③ `body-detail` 游客卡 DOM 位置上移至 monthly-guidance 之后。
+
+---
+
+## 一、统一设计原则
+
+1. **价值前置**:登录前先让用户"看见登录后能得到什么"——能自然预览的直接展示,无自然预览的用虚线占位,**不硬塞假数据**。
+2. **维度身份**:PageBanner / 品牌色 / CTA 严格走维度色令牌;**唯一例外是心维持双色**(品牌意图,见 §四)。
+3. **转化漏斗**:每个登录前页面必须有 **1 个维度色主登录 CTA + 1 个次级动作**(先逛 / 先看介绍),统一由 `DimensionVisitorCard` 承载。
+4. **一致中允许差异**:骨架统一、各维度预览形态允许不同(由业务内容决定,见 §四豁免说明)。
+
+---
+
+## 二、登录前(游客态)统一骨架
+
+自上而下五层:
+
+| 序 | 层 | 显示条件 | 说明 |
+|---|---|---|---|
+| ① | `PageBanner` | 始终 | 维度头部;心页用 `mind-wisdom` 双色,其余单维度色 |
+| ② | `brand-strap` | `v-if="!isLoggedIn"` | 维度定位语一句话 |
+| ③ | 自然预览 | 按维度(见下) | 能预览真实感的直接展示 |
+| ④ | `monthly-guidance` | `v-if="!isLoggedIn"` | 每月引导语(🌿/⚡/🔥/💧/🌿) |
+| ⑤ | `DimensionVisitorCard` | `v-if="!isLoggedIn"` | 价值卡 + 维度色主 CTA + 次级动作 + 虚线占位 |
+
+---
+
+## 三、各维度:登录前 / 登录后显示清单
+
+### 身 `body-detail`
+
+**登录前**:PageBanner(橙 `#FF8C42`) → brand-strap「科学管理全家健康」→ **健康概览卡(空态槽位:身高体重 / 血压 / 心率 = 暂无数据)** → monthly-guidance → `DimensionVisitorCard`
+- card-title:身体维度 · 全家健康管理
+- benefits:身高体重血压心率趋势 / 肠道菌群与疾病风险预警 / 家庭成员健康画像对比
+- CTA:立即登录查看健康概览 / 次级:查看健康报告 → `/pages/health/report-list`
+- preview-text:登录后展示你的健康概览 · 趋势曲线
+
+**登录后**:身维度画像 → 健康概览(真实值 + 趋势)→ 健康趋势分析 `RadarChart`(个人数据)→ 身体指标卡 → 肠道菌群(无报告时显示上传引导)→ 疾病风险 → 家庭成员选择条 → 五维能量条 → `DimensionIntroCard body` → 功能入口网格
+
+### 智 `wisdom-detail`
+
+**登录前**:PageBanner(靛 `#6366F1`) → brand-strap「提升全家认知能力与学习效率」→ **学习能力评估 `RadarChart`(同龄平均值;"查看详情"仅登录后可点)** → monthly-guidance → `DimensionVisitorCard`
+- card-title:智维度 · 认知赋能 / CTA:登录做认知测评 / 次级:了解认知维度 → `dimension-intro`
+- preview-text:登录后展示你的认知能力雷达图
+
+**登录后**:家庭成员选择条 → 五维能量条 → 认知指标卡 → 学习解读 → 认知强项与提升 → `DimensionIntroCard wisdom`
+
+### 心 `mind-detail`
+
+**登录前**:PageBanner(**`mind-wisdom` 双色**) → brand-strap「关注全家心理健康与情绪成长」→ monthly-guidance → `DimensionVisitorCard`
+- card-title:心维度 · 心理成长 / CTA:登录查看心理画像 / 次级:了解心理维度 → `dimension-intro`
+- preview-text:登录后展示你的心理画像与情绪关联
+- 注:**登录前无数据预览内容**(天盘 / 成员条 / 心理报告均登录后才出现),仅虚线占位
+
+**登录后**:家庭天盘 `FamilyTianpanCard` → 家庭成员选择条 → 五维能量条 → 心理指标卡 → EMI 心理测评报告 → 心维度画像 → `DimensionIntroCard mind`
+
+### 富 `wealth`
+
+**登录前**:PageBanner(琥珀 `#F59E0B`) → brand-strap「分享价值,收获财富」→ monthly-guidance → `DimensionVisitorCard` → **商城精选横滑(真实商品)**
+- card-title:富维度 · 利他创富 / CTA:登录解锁财富能量 / 次级:逛逛商城 → `/pages/shop/index/index`
+- **无 preview-text**(豁免:已有商城精选真实预览,避免重复占位)
+
+**登录后**:家庭成员选择条 → 五维能量条 → 身克富杠杆警告 → 财富能量环 → 财富成长(水位)→ 子维度水滴 → 子维度评分 → 财富强项与提升 → 富维度画像 → `DimensionIntroCard wealth`
+
+### 行 `action-detail`
+
+**登录前**:PageBanner(绿 `#10B981`) → brand-strap「改善全家关系与沟通能力」→ monthly-guidance → `DimensionVisitorCard`
+- card-title:行维度 · 关系滋养 / CTA:登录绘制关系网络 / 次级:了解关系维度 → `dimension-intro`
+- preview-text:登录后绘制你的家庭关系网络图
+- 注:**登录前无数据预览内容**(关系图 / 章鱼图 / 成员条均登录后才出现),仅虚线占位
+
+**登录后**:家庭成员选择条 → 五维能量条 → 关系解读 → 行维度画像 → 关系六维 → 家庭关系图 `FamilyRelationGraph` → 章鱼图 `OctopusDiagram` → 珍珠图 / 能力图 → `DimensionIntroCard action`
+
+---
+
+## 四、维度差异与豁免说明
+
+| 项 | 决策 | 理由 |
+|---|---|---|
+| 心 PageBanner `mind-wisdom` 双色 | **保留**(已确认) | 「心智合一」品牌意图,非 bug;与单维度色规则是刻意例外 |
+| 富 不加 `preview-text` | 豁免 | 已有「商城精选」真实预览,虚线占位会重复 |
+| 身 / 智 保留 `preview-text` | **保留**(已确认) | 虽有自然预览,仍保留虚线文案以统一五页骨架表述 |
+| 身 健康概览卡「始终显示」 | 豁免 | 登录前展示空槽位 = 天然的结构预览 |
+| 智 认知雷达「始终显示」 | 豁免 | 登录前显示同龄平均值 = 天然预览,且"查看详情"入口登录后才出现 |
+| 心 / 行 无自然预览 | 豁免 | 业务上无无需登录即可展示的内容,故仅虚线占位 |
+
+---
+
+## 五、组件职责边界(重要 · 历史事故防线)
+
+| 组件 | 归属 | props | 禁止 |
+|---|---|---|---|
+| `DimensionVisitorCard` | **登录前游客态** | `dimCode / cardTitle / benefits / ctaText / secondaryText / secondaryUrl / previewText` | 禁止用于 `isLoggedIn` 分支 |
+| `DimensionIntroCard` | **登录后** | `dimCode / learnMoreText / learnMoreUrl` | 禁止承载登录 CTA(它无 CTA 能力) |
+
+> **历史事故**:曾有提交(`490e69e90`,"修复 DimensionVisitorCard 幽灵引用")因组件文件缺失,把五页机械替换为 `DimensionIntroCard`,但未适配 props,导致登录前登录 CTA / benefits 全部失效。二者**不可互换**,修改时按上表核对。
+
+---
+
+## 六、验收清单
+
+- [ ] 五页登录前骨架一致(①~⑤,仅维度内容差异)
+- [ ] 每页登录前均有**维度色主登录 CTA**,点击可唤起登录浮层(`openLoginSheet`)
+- [ ] 每页登录前均有次级动作且不要求登录(健康报告 / 维度介绍 / 商城)
+- [ ] 登录后各页显示真实数据模块,不再出现游客卡
+- [ ] 心页 PageBanner 双色、富页无虚线占位、身 / 智保留虚线占位
+- [ ] `body-detail` 游客卡位于 monthly-guidance 之后
+- [ ] `npm run build:mp-weixin` 编译通过
+
+---
+
+## 七、待办
+
+1. ⏳ 编译验证:`npm run build:mp-weixin`(阻塞项 `pages/vendor/team-system/team-system.vue` 可选链已按 AGENTS.md 规范改为 `&&`,待跑通确认)
+2. ⏳ 真机核对:登录前五页骨架与 CTA 可点;登录后数据与占位的切换
+3. ⏳ 所有改动尚未提交 git

+ 12 - 0
cfc-frontend/pages.json

@@ -113,6 +113,18 @@
             "navigationBarTitleText": "方案详情"
           }
         },
+        {
+          "path": "plan-list",
+          "style": {
+            "navigationBarTitleText": "我的方案"
+          }
+        },
+        {
+          "path": "plan-create",
+          "style": {
+            "navigationBarTitleText": "新建方案"
+          }
+        },
         {
           "path": "team",
           "style": {

+ 34 - 34
cfc-frontend/pages/action-detail/index.vue

@@ -842,10 +842,10 @@ export default {
 }
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .container {
   min-height: 100vh;
-  background: linear-gradient(180deg, #F0FFF4 0%, #F5F7FA 40%);
+  background: linear-gradient(180deg, #F0FFF4 0%, $app-bg 40%);
   padding-bottom: 120rpx;
 }
 
@@ -853,7 +853,7 @@ export default {
 .brand-strap {
   margin: 24rpx 30rpx 0;
   padding: 28rpx 32rpx;
-  background: linear-gradient(135deg, #10B981 0%, #34D399 50%, #6EE7B7 100%);
+  background: linear-gradient(135deg, $dim-action 0%, #34D399 50%, #6EE7B7 100%);
   border-radius: 24rpx;
   box-shadow: 0 8rpx 24rpx rgba(16, 185, 129, 0.25);
   position: relative;
@@ -881,7 +881,7 @@ export default {
 }
 .brand-strap-text {
   font-size: 30rpx;
-  color: #FFFFFF;
+  color: $app-surface;
   font-weight: 600;
   text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
   position: relative;
@@ -892,7 +892,7 @@ export default {
 .monthly-guidance {
   margin: 20rpx 30rpx 0;
   padding: 24rpx 28rpx;
-  background: linear-gradient(135deg, #FFFFFF 0%, #F0FFF4 100%);
+  background: linear-gradient(135deg, $app-surface 0%, #F0FFF4 100%);
   border-radius: 20rpx;
   border: 1rpx solid rgba(16, 185, 129, 0.15);
   box-shadow: 0 4rpx 16rpx rgba(16, 185, 129, 0.08);
@@ -920,7 +920,7 @@ export default {
   right: 24rpx;
   height: 3rpx;
   border-radius: 3rpx 3rpx 0 0;
-  background: linear-gradient(90deg, #10B981, #34D399);
+  background: linear-gradient(90deg, $dim-action, #34D399);
   opacity: 0.7;
 }
 .section-header {
@@ -935,7 +935,7 @@ export default {
   flex-direction: row;
   align-items: center;
   gap: 8rpx;
-  border-left: 8rpx solid #10B981;
+  border-left: 8rpx solid $dim-action;
   padding-left: 16rpx;
 }
 .help-icon {
@@ -949,12 +949,12 @@ export default {
   align-items: center;
   justify-content: center;
   flex-shrink: 0;
-  transition: all 0.2s;
-  background: #FFFFFF;
+  transition: opacity 0.2s $ease-standard, transform 0.2s $ease-standard;
+  background: $app-surface;
 }
 .help-icon:active {
-  border-color: #10B981;
-  color: #10B981;
+  border-color: $dim-action;
+  color: $dim-action;
   background: #F0FFF4;
   transform: scale(1.1);
 }
@@ -978,7 +978,7 @@ export default {
   font-size: 24rpx;
   font-weight: 500;
   white-space: nowrap;
-  transition: all 0.2s;
+  transition: opacity 0.2s $ease-standard, transform 0.2s $ease-standard;
   box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
 }
 .section-link:active {
@@ -987,40 +987,40 @@ export default {
 }
 .section-link-octopus {
   background: linear-gradient(135deg, #F97316, #FB923C);
-  color: #fff;
+  color: $app-surface;
   box-shadow: 0 4rpx 16rpx rgba(249,115,22,0.3);
 }
 .section-link-pearl {
   background: linear-gradient(135deg, #0EA5E9, #38BDF8);
-  color: #fff;
+  color: $app-surface;
   box-shadow: 0 4rpx 16rpx rgba(14,165,233,0.3);
 }
 .section-link-ability {
-  background: linear-gradient(135deg, #10B981, #34D399);
-  color: #fff;
+  background: linear-gradient(135deg, $dim-action, #34D399);
+  color: $app-surface;
   box-shadow: 0 4rpx 16rpx rgba(16,185,129,0.3);
 }
 
 /* 关系解读卡片 — 状态色 */
 .score-explain-card {
-  background: linear-gradient(135deg, #FFFFFF 0%, #F0FFF4 100%);
+  background: linear-gradient(135deg, $app-surface 0%, #F0FFF4 100%);
   border-radius: 20rpx;
   padding: 28rpx 32rpx;
   border: 1rpx solid rgba(16, 185, 129, 0.12);
   box-shadow: 0 4rpx 16rpx rgba(16, 185, 129, 0.08);
 }
 .score-explain-good {
-  background: linear-gradient(135deg, #FFFFFF 0%, #D1FAE5 100%);
+  background: linear-gradient(135deg, $app-surface 0%, #D1FAE5 100%);
   border-color: rgba(16, 185, 129, 0.25);
   box-shadow: 0 4rpx 20rpx rgba(16, 185, 129, 0.15);
 }
 .score-explain-warn {
-  background: linear-gradient(135deg, #FFFFFF 0%, #FEF3C7 100%);
+  background: linear-gradient(135deg, $app-surface 0%, #FEF3C7 100%);
   border-color: rgba(245, 158, 11, 0.25);
   box-shadow: 0 4rpx 20rpx rgba(245, 158, 11, 0.12);
 }
 .score-explain-bad {
-  background: linear-gradient(135deg, #FFFFFF 0%, #FEE2E2 100%);
+  background: linear-gradient(135deg, $app-surface 0%, #FEE2E2 100%);
   border-color: rgba(239, 68, 68, 0.25);
   box-shadow: 0 4rpx 20rpx rgba(239, 68, 68, 0.12);
 }
@@ -1042,12 +1042,12 @@ export default {
   transition: transform 0.2s;
 }
 .explain-icon-wrap:active { transform: scale(0.95); }
-.explain-icon-good { background: linear-gradient(135deg, #10B981, #34D399); box-shadow: 0 4rpx 12rpx rgba(16,185,129,0.3); }
+.explain-icon-good { background: linear-gradient(135deg, $dim-action, #34D399); box-shadow: 0 4rpx 12rpx rgba(16,185,129,0.3); }
 .explain-icon-warn { background: linear-gradient(135deg, #F59E0B, #FBBF24); box-shadow: 0 4rpx 12rpx rgba(245,158,11,0.3); }
 .explain-icon-bad { background: linear-gradient(135deg, #EF4444, #F87171); box-shadow: 0 4rpx 12rpx rgba(239,68,68,0.3); }
 .explain-icon {
   font-size: 28rpx;
-  color: #FFFFFF;
+  color: $app-surface;
   font-weight: 700;
 }
 .explain-info {
@@ -1066,7 +1066,7 @@ export default {
   line-height: 1;
   letter-spacing: -2rpx;
 }
-.score-explain-good .explain-score { color: #10B981; }
+.score-explain-good .explain-score { color: $dim-action; }
 .score-explain-warn .explain-score { color: #D97706; }
 .score-explain-bad .explain-score { color: #DC2626; }
 .explain-score-unit {
@@ -1096,7 +1096,7 @@ export default {
   z-index: 999;
 }
 .help-dialog {
-  background: #FFFFFF;
+  background: $app-surface;
   border-radius: 24rpx;
   width: 85%;
   max-width: 520rpx;
@@ -1110,7 +1110,7 @@ export default {
   align-items: center;
   padding: 28rpx 32rpx 20rpx;
   border-bottom: 1rpx solid #F1F5F9;
-  background: linear-gradient(135deg, #F0FFF4, #FFFFFF);
+  background: linear-gradient(135deg, #F0FFF4, $app-surface);
 }
 .help-dialog-title {
   font-size: 32rpx;
@@ -1147,7 +1147,7 @@ export default {
   display: flex;
   flex-direction: row;
   justify-content: space-around;
-  background: linear-gradient(135deg, #FFFFFF 0%, #F0FFF4 100%);
+  background: linear-gradient(135deg, $app-surface 0%, #F0FFF4 100%);
   border-radius: 24rpx;
   padding: 32rpx 16rpx;
   box-shadow: 0 8rpx 24rpx rgba(16, 185, 129, 0.1);
@@ -1170,7 +1170,7 @@ export default {
   justify-content: center;
   margin-bottom: 12rpx;
   box-shadow: 0 4rpx 12rpx rgba(16, 185, 129, 0.15);
-  transition: all 0.2s;
+  transition: opacity 0.2s $ease-standard, transform 0.2s $ease-standard;
 }
 .func-item:active .func-icon-wrap {
   transform: scale(0.95);
@@ -1192,7 +1192,7 @@ export default {
 /* 维度画像样式 */
 .dimension-portrait-section {
   margin: 24rpx 30rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 32rpx 24rpx;
   box-shadow: 0 4rpx 20rpx rgba(16, 185, 129, 0.12);
@@ -1200,7 +1200,7 @@ export default {
 }
 .portrait-tier {
   font-size: 26rpx;
-  color: #10B981;
+  color: $dim-action;
   font-weight: bold;
   margin-left: 16rpx;
 }
@@ -1209,7 +1209,7 @@ export default {
 }
 .portrait-desc {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
   line-height: 1.6;
   display: block;
 }
@@ -1237,13 +1237,13 @@ export default {
 }
 .portrait-dim-name {
   font-size: 24rpx;
-  color: #333;
+  color: $app-text;
   flex: 1;
 }
 .portrait-dim-score {
   font-size: 26rpx;
   font-weight: bold;
-  color: #10B981;
+  color: $dim-action;
   margin-right: 12rpx;
 }
 .portrait-dim-bar-track {
@@ -1261,14 +1261,14 @@ export default {
 }
 .portrait-dim-desc {
   font-size: 20rpx;
-  color: #666;
+  color: $app-text-secondary;
   display: block;
 }
 .portrait-tip {
   padding: 16rpx 20rpx;
   background: linear-gradient(135deg, #F0FFF4, #E6FFF2);
   border-radius: 12rpx;
-  border-left: 8rpx solid #10B981;
+  border-left: 8rpx solid $dim-action;
   margin-top: 16rpx;
 }
 .portrait-tip-text {

+ 5 - 3
cfc-frontend/pages/activity/activity-detail/activity-detail.vue

@@ -358,9 +358,11 @@ export default {
   methods: {
     // ===== 工具方法 =====
     getImageUrl: function(path) {
-      if (!path) return ''
-      if (path.indexOf('http://') === 0 || path.indexOf('https://') === 0) return path
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     },
     checkMemberStatus: function() {
       var that = this

+ 5 - 3
cfc-frontend/pages/activity/index.vue

@@ -376,9 +376,11 @@ export default {
   },
   methods: {
     getImageUrl: function(path) {
-      if (!path) return ''
-      if (path.indexOf('http://') === 0 || path.indexOf('https://') === 0) return path
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     },
     onTabChange: function(key) {
       this.currentTab = key

+ 5 - 1
cfc-frontend/pages/ai/chat.vue

@@ -498,7 +498,11 @@ export default {
       return (d.getMonth() + 1) + '/' + d.getDate()
     },
     getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     }
   }
 }

+ 5 - 1
cfc-frontend/pages/article-center/index.vue

@@ -317,7 +317,11 @@ onLoad(options) {
       uni.navigateBack()
     },
     getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     }
   }
 }

+ 5 - 1
cfc-frontend/pages/article-center/my-posts.vue

@@ -120,7 +120,11 @@ export default {
       return 'status-draft'
     },
     getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     }
   }
 }

+ 5 - 1
cfc-frontend/pages/body-detail/dimension-detail.vue

@@ -329,7 +329,11 @@ export default {
       }
     },
     getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     }
   }
 }

+ 65 - 65
cfc-frontend/pages/body-detail/index.vue

@@ -102,6 +102,21 @@
       <text class="guidance-text">{{ monthlyGuidance }}</text>
     </view>
 
+    <!-- 游客价值卡(统一组件:维度色 CTA + 价值预览) -->
+    <DimensionVisitorCard
+      v-if="!isLoggedIn"
+      dimCode="body"
+      card-title="身体维度 · 全家健康管理"
+      :benefits="[
+        '身高体重 / 血压 / 心率趋势一目了然',
+        '肠道菌群健康与疾病风险预警',
+        '家庭成员健康画像对比'
+      ]"
+      cta-text="立即登录查看健康概览"
+      secondary-text="查看健康报告"
+      secondary-url="/pages/health/report-list"
+      preview-text="登录后展示你的健康概览 · 趋势曲线" />
+
     <!-- 已登录用户区域 -->
     <view v-if="isLoggedIn">
       <!-- 身体指标卡片 -->
@@ -212,21 +227,6 @@
       </view>
     </view>
 
-    <!-- 游客价值卡(统一组件:维度色 CTA + 价值预览) -->
-<DimensionVisitorCard
-  v-if="!isLoggedIn"
-  dimCode="body"
-  card-title="身体维度 · 全家健康管理"
-  :benefits="[
-    '身高体重 / 血压 / 心率趋势一目了然',
-    '肠道菌群健康与疾病风险预警',
-    '家庭成员健康画像对比'
-  ]"
-  cta-text="立即登录查看健康概览"
-  secondary-text="查看健康报告"
-  secondary-url="/pages/health/report-list"
-  preview-text="登录后展示你的健康概览 · 趋势曲线" />
-
     <view class="bottom-spacer"></view>
     <FloatingAvatar />
   </view>
@@ -624,17 +624,17 @@ export default {
 }
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .body-container {
   min-height: 100vh;
-  background-color: #F5F7FA;
+  background-color: $app-bg;
   display: flex;
   flex-direction: column;
 }
 
 /* ─── 健康概览卡片 ─── */
 .health-overview-card {
-  background-color: #FFFFFF;
+  background-color: $app-surface;
   border-radius: 24rpx;
   margin: 20rpx 20rpx 12rpx;
   box-shadow: 0 4rpx 16rpx rgba(255, 140, 66, 0.12);
@@ -649,14 +649,14 @@ export default {
 .overview-title {
   font-size: 32rpx;
   font-weight: 700;
-  color: #FF8C42;
+  color: $dim-body;
   margin-bottom: 4rpx;
   display: block;
 }
 
 .overview-sub {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
 }
 
 .overview-grid {
@@ -683,7 +683,7 @@ export default {
   width: 52rpx;
   height: 52rpx;
   border-radius: 50%;
-  background: linear-gradient(135deg, #FF8C42, #FFB366);
+  background: linear-gradient(135deg, $dim-body, #FFB366);
   display: flex;
   align-items: center;
   justify-content: center;
@@ -701,7 +701,7 @@ export default {
 
 .overview-name {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   display: block;
   margin-bottom: 4rpx;
 }
@@ -709,12 +709,12 @@ export default {
 .overview-value {
   font-size: 40rpx;
   font-weight: 700;
-  color: #FF8C42;
+  color: $dim-body;
 }
 
 .overview-placeholder {
   font-size: 22rpx;
-  color: #ccc;
+  color: $app-border;
 }
 
 .overview-trend {
@@ -731,11 +731,11 @@ export default {
 
 .trend-up { color: #10B981; }
 .trend-down { color: #FF6B6B; }
-.trend-stable { color: #999; }
+.trend-stable { color: $app-text-muted; }
 
 .trend-desc {
   font-size: 18rpx;
-  color: #888;
+  color: $app-text-muted;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
@@ -753,14 +753,14 @@ export default {
   display: flex;
   align-items: center;
   justify-content: center;
-  background: linear-gradient(135deg, #FF8C42, #FF6B1A);
+  background: linear-gradient(135deg, $dim-body, #FF6B1A);
   border-radius: 48rpx;
   padding: 20rpx 0;
   box-shadow: 0 4rpx 16rpx rgba(255, 107, 26, 0.35);
 }
 
 .overview-nav-btn-text {
-  color: #FFFFFF;
+  color: $app-surface;
   font-size: 26rpx;
   font-weight: 600;
 }
@@ -770,14 +770,14 @@ export default {
   display: flex;
   align-items: center;
   justify-content: center;
-  background-color: #FFFFFF;
+  background-color: $app-surface;
   border-radius: 48rpx;
   padding: 20rpx 0;
-  border: 2rpx solid #FF8C42;
+  border: 2rpx solid $dim-body;
 }
 
 .overview-nav-btn-secondary-text {
-  color: #FF8C42;
+  color: $dim-body;
   font-size: 26rpx;
   font-weight: 600;
 }
@@ -787,7 +787,7 @@ export default {
 .indicator-section,
 .gut-section,
 .risk-section {
-  background-color: #FFFFFF;
+  background-color: $app-surface;
   border-radius: 24rpx;
   margin: 0 20rpx 16rpx;
   box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
@@ -798,19 +798,19 @@ export default {
   display: flex;
   align-items: center;
   padding: 24rpx 24rpx 16rpx;
-  border-bottom: 1rpx solid #F5F5F5;
-  border-left: 8rpx solid #FF8C42;
+  border-bottom: 1rpx solid $app-surface-subtle;
+  border-left: 8rpx solid $dim-body;
 }
 
 .section-title {
   font-size: 30rpx;
   font-weight: 600;
-  color: #333;
+  color: $app-text;
 }
 
 .section-more {
   font-size: 24rpx;
-  color: #FF8C42;
+  color: $dim-body;
   font-weight: 500;
   margin-left: auto;
   padding-left: 16rpx;
@@ -819,7 +819,7 @@ export default {
 .avg-badge {
   display: block;
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   padding: 0 24rpx 16rpx;
 }
 
@@ -845,7 +845,7 @@ export default {
 }
 
 .indicator-card.no-data {
-  background: #F8F8F8;
+  background: $app-surface-subtle;
   border-color: #eee;
 }
 
@@ -858,12 +858,12 @@ export default {
 
 .indicator-name {
   font-size: 24rpx;
-  color: #666;
+  color: $app-text-secondary;
 }
 
 .indicator-unit {
   font-size: 20rpx;
-  color: #999;
+  color: $app-text-muted;
 }
 
 .indicator-body {
@@ -873,23 +873,23 @@ export default {
 .indicator-value {
   font-size: 40rpx;
   font-weight: 700;
-  color: #FF8C42;
+  color: $dim-body;
 }
 
 .indicator-placeholder {
   font-size: 24rpx;
-  color: #ccc;
+  color: $app-border;
 }
 
 .indicator-footer {
   font-size: 20rpx;
-  color: #999;
+  color: $app-text-muted;
   text-align: right;
 }
 
 /* ─── 肠道菌群 ─── */
 .gut-section {
-  background-color: #FFFFFF;
+  background-color: $app-surface;
   border-radius: 24rpx;
   margin: 0 20rpx 16rpx;
   box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
@@ -905,7 +905,7 @@ export default {
 
 .gut-summary-text {
   font-size: 26rpx;
-  color: #FF8C42;
+  color: $dim-body;
   font-weight: 500;
 }
 
@@ -919,7 +919,7 @@ export default {
 
 .gut-group-title {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-bottom: 12rpx;
   display: block;
 }
@@ -934,13 +934,13 @@ export default {
   display: flex;
   align-items: center;
   padding: 10rpx 16rpx;
-  background-color: #F8F8F8;
+  background-color: $app-surface-subtle;
   border-radius: 16rpx;
   font-size: 22rpx;
 }
 
 .gut-item-name {
-  color: #333;
+  color: $app-text;
   flex: 1;
   max-width: 120rpx;
   overflow: hidden;
@@ -955,7 +955,7 @@ export default {
 
 .gut-item-value {
   font-size: 20rpx;
-  color: #333;
+  color: $app-text;
   font-weight: 500;
 }
 
@@ -971,19 +971,19 @@ export default {
 .gut-empty-hint {
   padding: 40rpx 24rpx;
   text-align: center;
-  color: #999;
+  color: $app-text-muted;
   font-size: 24rpx;
 }
 
 .gut-upload-link {
-  color: #FF8C42;
+  color: $dim-body;
   margin-left: 8rpx;
   font-weight: 500;
 }
 
 /* ─── 疾病风险 ─── */
 .risk-section {
-  background-color: #FFFFFF;
+  background-color: $app-surface;
   border-radius: 24rpx;
   margin: 0 20rpx 16rpx;
   box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
@@ -999,7 +999,7 @@ export default {
   justify-content: space-between;
   align-items: center;
   padding: 16rpx 0;
-  border-bottom: 1rpx solid #f5f5f5;
+  border-bottom: 1rpx solid $app-surface-subtle;
 }
 
 .risk-item:last-child {
@@ -1008,7 +1008,7 @@ export default {
 
 .risk-name {
   font-size: 26rpx;
-  color: #333;
+  color: $app-text;
 }
 
 .risk-right {
@@ -1028,13 +1028,13 @@ export default {
 }
 
 .risk-severe .risk-level { color: #FF6B6B; }
-.risk-attention .risk-level { color: #FF8C42; }
-.risk-normal .risk-level { color: #999; }
+.risk-attention .risk-level { color: $dim-body; }
+.risk-normal .risk-level { color: $app-text-muted; }
 
 /* ─── 月引导语 ─── */
 .dimension-portrait-section {
   margin: 20rpx 30rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 28rpx 24rpx;
   box-shadow: 0 4rpx 20rpx rgba(255, 140, 66, 0.12);
@@ -1042,7 +1042,7 @@ export default {
 }
 .portrait-tier {
   font-size: 26rpx;
-  color: #FF8C42;
+  color: $dim-body;
   font-weight: bold;
   margin-left: 16rpx;
 }
@@ -1051,7 +1051,7 @@ export default {
 }
 .portrait-desc {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
   line-height: 1.6;
   display: block;
 }
@@ -1078,13 +1078,13 @@ export default {
 }
 .portrait-dim-name {
   font-size: 26rpx;
-  color: #333;
+  color: $app-text;
   flex: 1;
 }
 .portrait-dim-score {
   font-size: 28rpx;
   font-weight: bold;
-  color: #FF8C42;
+  color: $dim-body;
   margin-right: 16rpx;
 }
 .portrait-dim-bar-track {
@@ -1101,14 +1101,14 @@ export default {
 }
 .portrait-dim-desc {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   display: block;
 }
 .portrait-tip {
   padding: 16rpx 20rpx;
   background: linear-gradient(135deg, #FFF7ED, #FFF0E4);
   border-radius: 12rpx;
-  border-left: 8rpx solid #FF8C42;
+  border-left: 8rpx solid $dim-body;
 }
 .portrait-tip-text {
   font-size: 24rpx;
@@ -1132,7 +1132,7 @@ export default {
 
 .guidance-text {
   font-size: 24rpx;
-  color: #FF8C42;
+  color: $dim-body;
 }
 
 /* ─── 品牌定位语(登录前) ─── */
@@ -1144,7 +1144,7 @@ export default {
 }
 .brand-strap-text {
   font-size: 26rpx;
-  color: #FF8C42;
+  color: $dim-body;
   font-weight: 600;
 }
 

+ 5 - 1
cfc-frontend/pages/discover/index.vue

@@ -229,7 +229,11 @@ export default {
       uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     },
     getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     },
     goKnowledgeCenter() {
       uni.navigateTo({ url: '/pages/article-center/index' })

+ 12 - 3
cfc-frontend/pages/growth/upload.vue

@@ -273,9 +273,18 @@ export default {
     formatPrice: function(cents) {
       if (cents === null || cents === undefined) return '¥0'
       return '¥' + (cents / 100).toFixed(2)
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/guide/activities/detail.vue

@@ -318,9 +318,18 @@ export default {
       var h = ('0' + d.getHours()).slice(-2)
       var mi = ('0' + d.getMinutes()).slice(-2)
       return y + '-' + m + '-' + day + ' ' + h + ':' + mi
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/guide/activities/index.vue

@@ -207,9 +207,18 @@ export default {
       var h = ('0' + d.getHours()).slice(-2)
       var mi = ('0' + d.getMinutes()).slice(-2)
       return y + '-' + m + '-' + day + ' ' + h + ':' + mi
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/guide/packages/share.vue

@@ -154,9 +154,18 @@ export default {
     },
     closePoster() {
       this.$refs.posterPopup.close()
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/index-home/index.vue

@@ -1968,9 +1968,18 @@ title: '添加家庭成员',
         self.referralCode = extractReferralCode(res)
       }).catch(function() {})
       self.referralCodeLoaded = true
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     },
     /** 转发给朋友/群(不指定 imageUrl,微信自动截取当前页面截图作缩略图;static/share-cover.png 不存在会导致卡片空白) */
     onShareAppMessage: function() {

+ 12 - 3
cfc-frontend/pages/meal/recipe-detail.vue

@@ -147,9 +147,18 @@ export default {
       } catch (e) {
         this.stepList = str.split(/[;;\n]/).filter(function(s) { return s.trim() })
       }
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/mind-detail/articles.vue

@@ -254,9 +254,18 @@ onShow: function() {
         .replace(/&quot;/gi, '"')
         .replace(/\s+/g, ' ')
         .trim()
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 76 - 76
cfc-frontend/pages/mind-detail/index.vue

@@ -1187,10 +1187,10 @@ var descList = descMap[this.dominantElement] || descMap.wood
   }
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .container {
   min-height: 100vh;
-  background: #f5f7fa;
+  background: $app-bg;
   padding-bottom: 120rpx;
 }
 
@@ -1207,13 +1207,13 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .section-title-icon {
   font-size: 32rpx;
-  color: #fff;
+  color: $app-surface;
   margin-right: 12rpx;
 }
 .section-title-text {
   font-size: 32rpx;
   font-weight: bold;
-  color: #fff;
+  color: $app-surface;
 }
 
 /* ===== 心理报告上传卡片 ===== */
@@ -1288,7 +1288,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   display: flex;
   flex-direction: row;
   align-items: center;
-  background: #fff;
+  background: $app-surface;
   border-radius: 14rpx;
   padding: 20rpx 20rpx;
   margin-bottom: 8rpx;
@@ -1303,12 +1303,12 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .mind-report-item-name {
   font-size: 26rpx;
-  color: #333;
+  color: $app-text;
   flex: 1;
 }
 .mind-report-item-date {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-right: 14rpx;
 }
 .mind-report-item-status {
@@ -1321,8 +1321,8 @@ var descList = descMap[this.dominantElement] || descMap.wood
   background: #F3E8FF;
 }
 .mind-report-item-status.pending {
-  color: #999;
-  background: #F5F5F5;
+  color: $app-text-muted;
+  background: $app-surface-subtle;
 }
 .mind-report-empty {
   display: flex;
@@ -1346,7 +1346,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   display: flex;
   flex-direction: row;
   margin: 20rpx 30rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx 16rpx;
   box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
@@ -1365,11 +1365,11 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .badge-value {
   font-size: 36rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
 }
 .badge-label {
   font-size: 20rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-top: 4rpx;
 }
 
@@ -1378,7 +1378,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   margin: 20rpx 30rpx;
 }
 .emi-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 30rpx;
   box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.06);
@@ -1386,7 +1386,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .emi-card-title {
   font-size: 30rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
   display: block;
 }
 .personality-header {
@@ -1403,7 +1403,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .test-btn-text {
   font-size: 24rpx;
-  color: #fff;
+  color: $app-surface;
   font-weight: 500;
 }
 .emi-bar-item {
@@ -1414,7 +1414,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .emi-bar-label {
   font-size: 24rpx;
-  color: #666;
+  color: $app-text-secondary;
   width: 120rpx;
   flex-shrink: 0;
 }
@@ -1434,7 +1434,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .emi-bar-score {
   font-size: 26rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
   width: 60rpx;
   text-align: right;
   flex-shrink: 0;
@@ -1482,7 +1482,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 /* ===== EMI 心理报告卡片 ===== */
 .emi-card {
   margin: 30rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 30rpx;
   box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.06);
@@ -1493,7 +1493,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .emi-title {
   font-size: 30rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
   display: block;
 }
 .emi-overall-wrap {
@@ -1504,7 +1504,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   background: linear-gradient(135deg, #FF6B35, #FFD700);
   border-radius: 16rpx;
   margin: 20rpx 0;
-  color: #fff;
+  color: $app-surface;
 }
 .emi-overall-label {
   font-size: 26rpx;
@@ -1539,7 +1539,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .emi-dim-label {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
 }
 .emi-dim-values {
   display: flex;
@@ -1601,7 +1601,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 /* ===== 占位卡 ===== */
 .placeholder-card {
   margin: 30rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 60rpx 40rpx;
   display: flex;
@@ -1616,19 +1616,19 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .placeholder-title {
   font-size: 32rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
   margin-bottom: 16rpx;
 }
 .placeholder-desc {
   font-size: 26rpx;
-  color: #999;
+  color: $app-text-muted;
   text-align: center;
   line-height: 1.6;
   margin-bottom: 30rpx;
 }
 .placeholder-btn {
   background: linear-gradient(135deg, #FF6B35, #FFD700);
-  color: #fff;
+  color: $app-surface;
   font-size: 28rpx;
   font-weight: bold;
   padding: 16rpx 64rpx;
@@ -1641,7 +1641,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   margin: 20rpx 30rpx;
 }
 .culture-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx;
   box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.04);
@@ -1659,11 +1659,11 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .culture-card-title {
   font-size: 28rpx;
   font-weight: 600;
-  color: #333;
+  color: $app-text;
 }
 .culture-card-body {
   font-size: 24rpx;
-  color: #666;
+  color: $app-text-secondary;
   line-height: 1.6;
 }
 /* 八字四柱 */
@@ -1679,7 +1679,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .bazi-pillar-label {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-bottom: 6rpx;
 }
 .bazi-pillar-value {
@@ -1720,7 +1720,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .wuxing-value {
   font-size: 22rpx;
-  color: #666;
+  color: $app-text-secondary;
   width: 56rpx;
   text-align: right;
 }
@@ -1771,7 +1771,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .energy-label {
   font-size: 28rpx;
   font-weight: 700;
-  background: linear-gradient(135deg, #F59E0B, #FF6B9D);
+  background: linear-gradient(135deg, #F59E0B, $dim-mind);
   -webkit-background-clip: text;
   -webkit-text-fill-color: transparent;
   background-clip: text;
@@ -1787,7 +1787,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 
 .energy-quote {
   font-size: 26rpx;
-  color: #E2E8F0;
+  color: $app-border-subtle;
   line-height: 1.8;
   display: block;
   margin-bottom: 14rpx;
@@ -1804,7 +1804,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   top: 4rpx;
   bottom: 4rpx;
   width: 4rpx;
-  background: linear-gradient(180deg, #F59E0B, #FF6B9D);
+  background: linear-gradient(180deg, #F59E0B, $dim-mind);
   border-radius: 2rpx;
 }
 
@@ -1849,7 +1849,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .culture-dual-item {
   flex: 1;
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 20rpx;
   box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.04);
@@ -1863,7 +1863,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .culture-dual-label {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-bottom: 6rpx;
 }
 .culture-dual-value {
@@ -1880,7 +1880,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 
 /* ===== 每日心理 ===== */
 .tip-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
   display: flex;
@@ -1888,8 +1888,8 @@ var descList = descMap[this.dominantElement] || descMap.wood
   overflow: hidden;
 }
 .tip-left-bar {
-  width: 6rpx;
-  background: linear-gradient(180deg, #5B9BD5, #8FC5E8);
+  width: 8rpx;
+  background: $dim-mind;
   flex-shrink: 0;
 }
 .tip-body {
@@ -1899,13 +1899,13 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .tip-title {
   font-size: 28rpx;
   font-weight: bold;
-  color: #5B9BD5;
+  color: $dim-mind;
   display: block;
   margin-bottom: 12rpx;
 }
 .tip-content {
   font-size: 24rpx;
-  color: #666;
+  color: $app-text-secondary;
   line-height: 1.6;
   display: block;
   margin-bottom: 16rpx;
@@ -1930,7 +1930,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .section-title {
   font-size: 30rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
 }
 
 /* ===== 推荐阅读 ===== */
@@ -1939,7 +1939,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   flex-direction: column;
 }
 .article-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 28rpx 24rpx;
   box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
@@ -1953,19 +1953,19 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .article-category-text {
   font-size: 20rpx;
-  color: #fff;
+  color: $app-surface;
   font-weight: 500;
 }
 .article-title {
   font-size: 28rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
   display: block;
   margin-bottom: 10rpx;
 }
 .article-summary {
   font-size: 24rpx;
-  color: #888;
+  color: $app-text-muted;
   line-height: 1.5;
   display: block;
   margin-bottom: 20rpx;
@@ -2004,7 +2004,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   display: flex;
   flex-direction: column;
   gap: 16rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx 16rpx;
   box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
@@ -2035,7 +2035,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .func-label {
   font-size: 22rpx;
-  color: #666;
+  color: $app-text-secondary;
   font-weight: 500;
 }
 .func-item:active {
@@ -2045,21 +2045,21 @@ var descList = descMap[this.dominantElement] || descMap.wood
 /* ===== 底部 ===== */
 .indicator-cards-section { margin: 20rpx 30rpx; }
 .indicator-cards { display: flex; flex-direction: row; flex-wrap: wrap; gap: 16rpx; }
-.indicator-card { width: calc(50% - 8rpx); background: #fff; border-radius: 20rpx; padding: 24rpx 20rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.indicator-card { width: calc(50% - 8rpx); background: $app-surface; border-radius: 20rpx; padding: 24rpx 20rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .indicator-card.no-data { opacity: 0.5; }
 .indicator-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
-.indicator-name { font-size: 26rpx; color: #666; font-weight: 500; }
-.indicator-unit { font-size: 22rpx; color: #999; }
+.indicator-name { font-size: 26rpx; color: $app-text-secondary; font-weight: 500; }
+.indicator-unit { font-size: 22rpx; color: $app-text-muted; }
 .indicator-body { margin-bottom: 8rpx; }
-.indicator-value { font-size: 40rpx; font-weight: bold; color: #FF6B9D; }
-.indicator-placeholder { font-size: 26rpx; color: #ccc; }
+.indicator-value { font-size: 40rpx; font-weight: bold; color: $dim-mind; }
+.indicator-placeholder { font-size: 26rpx; color: $app-border; }
 .indicator-range { font-size: 20rpx; color: #bbb; }
 .bottom-spacer { height: 120rpx; }
 
 /* ===== 肠脑轴 ===== */
 .gut-insight-text {
   font-size: 24rpx;
-  color: #666;
+  color: $app-text-secondary;
   margin-bottom: 16rpx;
   padding: 12rpx 16rpx;
   background: #F0FFF4;
@@ -2082,13 +2082,13 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .gut-indicator-name {
   font-size: 22rpx;
-  color: #666;
+  color: $app-text-secondary;
   font-weight: 500;
   display: block;
 }
 .gut-indicator-impact {
   font-size: 18rpx;
-  color: #FF6B9D;
+  color: $dim-mind;
   display: block;
   margin-top: 2rpx;
 }
@@ -2106,7 +2106,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .gut-indicator-value {
   font-size: 22rpx;
-  color: #666;
+  color: $app-text-secondary;
   width: 60rpx;
   text-align: right;
 }
@@ -2132,7 +2132,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 
 /* ===== 关键信息(家庭+个人) ===== */
 .key-info-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx;
   margin-top: 20rpx;
@@ -2150,7 +2150,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .key-info-title {
   font-size: 28rpx;
   font-weight: 600;
-  color: #333;
+  color: $app-text;
 }
 .key-info-body {
   display: flex;
@@ -2166,7 +2166,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .ki-subtitle {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-bottom: 12rpx;
   font-weight: 500;
 }
@@ -2181,7 +2181,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .ki-label {
   font-size: 22rpx;
-  color: #888;
+  color: $app-text-muted;
   margin-right: 8rpx;
   white-space: nowrap;
 }
@@ -2194,13 +2194,13 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .ki-valuel {
   font-size: 24rpx;
-  color: #333;
+  color: $app-text;
   font-weight: 500;
   white-space: nowrap;
 }
 .ki-valued {
   font-size: 24rpx;
-  color: #333;
+  color: $app-text;
   font-weight: 500;
 }
 .ki-swatch {
@@ -2214,7 +2214,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .ki-num {
   font-size: 30rpx;
   font-weight: 700;
-  color: #FF6B9D;
+  color: $dim-mind;
 }
 .ki-fortune {
   font-size: 24rpx;
@@ -2276,7 +2276,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 
 /* DAN 报告卡片 */
 .dan-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 16rpx;
   padding: 24rpx;
   margin-bottom: 16rpx;
@@ -2290,7 +2290,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .dan-report-date {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
 }
 .dan-status {
   font-size: 22rpx;
@@ -2307,7 +2307,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .dan-report-desc {
   font-size: 28rpx;
-  color: #333;
+  color: $app-text;
   font-weight: 500;
   margin-bottom: 12rpx;
   display: block;
@@ -2328,7 +2328,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 .section-title {
   font-size: 32rpx;
   font-weight: 700;
-  color: #333;
+  color: $app-text;
 }
 .section-more {
   font-size: 26rpx;
@@ -2342,7 +2342,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   padding: 20rpx 28rpx;
   background: linear-gradient(135deg, #FFF0F5, rgba(255,107,157,0.12));
   border-radius: 16rpx;
-  border-left: 8rpx solid #FF6B9D;
+  border-left: 8rpx solid $dim-mind;
 }
 .brand-strap-text {
   font-size: 26rpx;
@@ -2356,7 +2356,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
   padding: 20rpx 28rpx;
   background: linear-gradient(135deg, #FFF0F5, rgba(255,107,157,0.08));
   border-radius: 16rpx;
-  border-left: 8rpx solid #FF6B9D;
+  border-left: 8rpx solid $dim-mind;
   display: flex;
   align-items: center;
   gap: 12rpx;
@@ -2381,7 +2381,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 /* 维度画像样式 */
 .dimension-portrait-section {
   margin: 24rpx 30rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 32rpx 24rpx;
   box-shadow: 0 4rpx 20rpx rgba(255, 107, 157, 0.12);
@@ -2389,7 +2389,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .portrait-tier {
   font-size: 26rpx;
-  color: #FF6B9D;
+  color: $dim-mind;
   font-weight: bold;
   margin-left: 16rpx;
 }
@@ -2398,7 +2398,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .portrait-desc {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
   line-height: 1.6;
   display: block;
 }
@@ -2425,13 +2425,13 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .portrait-dim-name {
   font-size: 24rpx;
-  color: #333;
+  color: $app-text;
   flex: 1;
 }
 .portrait-dim-score {
   font-size: 26rpx;
   font-weight: bold;
-  color: #FF6B9D;
+  color: $dim-mind;
   margin-right: 12rpx;
 }
 .portrait-dim-bar-track {
@@ -2449,14 +2449,14 @@ var descList = descMap[this.dominantElement] || descMap.wood
 }
 .portrait-dim-desc {
   font-size: 20rpx;
-  color: #999;
+  color: $app-text-muted;
   display: block;
 }
 .portrait-tip {
   padding: 16rpx 20rpx;
   background: linear-gradient(135deg, #FFF0F5, #FDF2F7);
   border-radius: 12rpx;
-  border-left: 8rpx solid #FF6B9D;
+  border-left: 8rpx solid $dim-mind;
   margin-top: 16rpx;
 }
 .portrait-tip-text {

+ 12 - 3
cfc-frontend/pages/promotion/material.vue

@@ -220,9 +220,18 @@ export default {
           uni.showToast({ title: '下载失败', icon: 'none' })
         }
         })
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/shop/cart/cart.vue

@@ -422,9 +422,18 @@ export default {
     formatPriceWithSymbol(price) {
       if (price === null || price === undefined) return '0.00'
       return (Number(price) / 100).toFixed(2)
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/shop/checkout/checkout.vue

@@ -1115,9 +1115,18 @@ showOnlineSlotPicker: function() {
     selectServicePerson: function(person) {
       this.selectedServicePerson = person
       this.showServicePersonModal = false
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/shop/index/index.vue

@@ -315,9 +315,18 @@ export default {
     formatPriceWithSymbol(price) {
       if (price === null || price === undefined) return ''
       return '¥' + (Number(price) / 100).toFixed(2)
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 12 - 3
cfc-frontend/pages/shop/order-detail/order-detail.vue

@@ -290,9 +290,18 @@ export default {
     formatPriceWithSymbol(price) {
       if (!price && price !== 0) return '-'
       return '¥' + (price / 100).toFixed(2)
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     },
     // 履约状态标签
     fulfillStatusLabel: function(status) {

+ 12 - 3
cfc-frontend/pages/shop/order-list/order-list.vue

@@ -356,9 +356,18 @@ export default {
     },
     onImgError(e, item) {
       item.coverImage = ''
-    },
-    getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+    },getImageUrl: function(path) {
+
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+
+      var s = String(path).trim()
+
+      if (!s || s === 'null' || s === '/null') return ''
+
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
+
     }
   }
 }

+ 29 - 17
cfc-frontend/pages/teacher/families.vue

@@ -5,6 +5,11 @@
       <text class="family-meta">查看待审核方案与任务</text>
     </view>
 
+    <view class="family-card entry" @click="goPlanList">
+      <text class="family-name">我的方案</text>
+      <text class="family-meta">查看和管理已制定的训练方案</text>
+    </view>
+
     <view class="filter-bar">
       <view class="filter-item" :class="{ active: filterType === 'all' }" @click="changeFilter('all')">全部</view>
       <view class="filter-item" :class="{ active: filterType === 'active' }" @click="changeFilter('active')">活跃</view>
@@ -12,23 +17,27 @@
     </view>
 
     <view class="family-list">
-      <view class="family-card" v-for="family in families" :key="family.id" @click="viewFamily(family)">
-        <view class="family-header">
-          <text class="family-name">{{ family.familyName || '家庭' + family.familyId }}</text>
-          <text class="family-status">{{ family.status === 'active' ? '服务中' : '已暂停' }}</text>
-        </view>
-        <view class="family-info">
-          <text class="info-item">👶 {{ family.childrenCount || 0 }}位成员</text>
-          <text class="info-item">📍 {{ family.address || '未设置地址' }}</text>
-        </view>
-        <view class="family-tasks">
-          <text class="task-info">今日任务: {{ family.todayTaskCount || 0 }}/{{ family.totalTaskCount || 0 }}</text>
-        </view>
-        <view class="family-actions">
-          <button class="btn-action" size="mini" @click.stop="viewDetail(family)">查看详情</button>
-          <!-- 聊天功能已隐藏(临时): <button class="btn-action primary" size="mini" @click.stop="sendMessage(family)">发消息</button> -->
-        </view>
-      </view>
+<view class="family-card" v-for="family in families" :key="family.id" @click="viewFamily(family)">
+         <view class="family-header">
+           <text class="family-name">{{ family.familyName || '家庭' + family.familyId }}</text>
+           <text class="family-status">{{ family.status === 'active' ? '服务中' : '已暂停' }}</text>
+         </view>
+         <view class="family-info">
+           <text class="info-item">👶 {{ family.childrenCount || 0 }}位成员</text>
+           <text class="info-item">📍 {{ family.address || '未设置地址' }}</text>
+         </view>
+         <view class="family-tasks">
+           <text class="task-info">今日任务: {{ family.todayTaskCount || 0 }}/{{ family.totalTaskCount || 0 }}</text>
+         </view>
+         <view class="family-actions">
+           <button class="btn-action" size="mini" @click.stop="viewDetail(family)">查看详情</button>
+            <view class="family-card plan-card-entry" v-if="family.id !== null" @click="viewPlanList">
+             <view class="family-header">
+               <text class="family-name">方案管理</text>
+             </view>
+           </view>
+         </view>
+       </view>
       <view class="empty-tip" v-if="families.length === 0">
         <text>暂无服务家庭</text>
       </view>
@@ -78,6 +87,9 @@ export default {
     },
     goWorkbench() {
       uni.navigateTo({ url: '/pages/teacher/review-workbench' })
+    },
+    goPlanList() {
+      uni.navigateTo({ url: '/pages/teacher/plan-list' })
     }
   }
 }

+ 166 - 0
cfc-frontend/pages/teacher/plan-create.vue

@@ -0,0 +1,166 @@
+<template>
+  <view class="page">
+    <view class="card">
+      <view class="form-group">
+        <text class="label">方案标题 <text class="required">*</text></text>
+        <input
+          class="input"
+          v-model="title"
+          placeholder="请输入方案标题"
+        />
+      </view>
+
+      <view class="form-group">
+        <text class="label">方案描述</text>
+        <textarea
+          class="textarea"
+          v-model="description"
+          placeholder="请输入方案描述(可选)"
+          :maxlength="-1"
+        />
+      </view>
+    </view>
+
+    <view class="actions">
+      <button class="btn-primary" :disabled="submitting" @click="submitPlan">
+        {{ submitting ? '提交中...' : '保存方案' }}
+      </button>
+      <button class="btn-cancel" @click="goBack">取消</button>
+    </view>
+  </view>
+</template>
+
+<script>
+import { createTrainingPlan } from '@/utils/api.js'
+
+export default {
+  data() {
+    return {
+      title: '',
+      description: '',
+      submitting: false
+    }
+  },
+  methods: {
+    submitPlan() {
+      if (!this.title || !this.title.trim()) {
+        uni.showToast({ title: '请输入方案标题', icon: 'none' })
+        return
+      }
+
+      this.submitting = true
+
+      // 创建方案(memberId 留空,由后端关联当前用户)
+      createTrainingPlan(null, this.title.trim(), this.description.trim() || '')
+        .then(res => {
+          this.submitting = false
+          if (res && res.code === 200) {
+            uni.showToast({ title: '创建成功', icon: 'success' })
+            // 延迟跳转,让用户看到成功提示
+            setTimeout(() => {
+              uni.navigateBack()
+            }, 1000)
+          } else {
+            uni.showToast({ title: (res && res.message) || '创建失败', icon: 'none' })
+          }
+        })
+        .catch(err => {
+          this.submitting = false
+          console.error('创建方案失败', err)
+          uni.showToast({ title: '创建失败', icon: 'none' })
+        })
+    },
+    goBack() {
+      uni.navigateBack()
+    }
+  }
+}
+</script>
+
+<style scoped>
+.page {
+  padding: 24rpx;
+  background: #F5FAFE;
+  min-height: 100vh;
+}
+
+.card {
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 30rpx;
+  margin-bottom: 20rpx;
+}
+
+.form-group {
+  margin-bottom: 30rpx;
+}
+
+.form-group:last-child {
+  margin-bottom: 0;
+}
+
+.label {
+  font-size: 28rpx;
+  color: #1F2D3D;
+  display: block;
+  margin-bottom: 12rpx;
+  font-weight: 500;
+}
+
+.required {
+  color: #F44336;
+}
+
+.input {
+  width: 100%;
+  height: 80rpx;
+  background: #F7F9FC;
+  border-radius: 12rpx;
+  padding: 0 20rpx;
+  font-size: 28rpx;
+  color: #1F2D3D;
+  box-sizing: border-box;
+}
+
+.textarea {
+  width: 100%;
+  min-height: 200rpx;
+  background: #F7F9FC;
+  border-radius: 12rpx;
+  padding: 20rpx;
+  font-size: 28rpx;
+  color: #1F2D3D;
+  box-sizing: border-box;
+}
+
+.actions {
+  display: flex;
+  flex-direction: column;
+  gap: 16rpx;
+}
+
+.btn-primary {
+  width: 100%;
+  background: #4A9BD7;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: 600;
+  padding: 24rpx 0;
+  border-radius: 12rpx;
+  border: none;
+}
+
+.btn-primary:disabled {
+  background: #ccc;
+}
+
+.btn-cancel {
+  width: 100%;
+  background: #F2F4F7;
+  color: #5A6478;
+  font-size: 30rpx;
+  padding: 24rpx 0;
+  border-radius: 12rpx;
+  border: none;
+}
+</style>

+ 231 - 0
cfc-frontend/pages/teacher/plan-list.vue

@@ -0,0 +1,231 @@
+<template>
+  <view class="page">
+    <view class="header">
+      <text class="title">我的方案</text>
+      <text class="subtitle">查看和管理已制定的训练方案</text>
+    </view>
+
+    <view class="action-bar">
+      <button class="btn-primary" @click="goCreatePlan">+ 新建方案</button>
+    </view>
+
+    <!-- 加载状态 -->
+    <view class="loading" v-if="loading">
+      <text class="loading-text">加载中...</text>
+    </view>
+
+    <!-- 空状态 -->
+    <view class="empty" v-else-if="plans.length === 0">
+      <text class="empty-icon">📋</text>
+      <text class="empty-title">暂无方案</text>
+      <text class="empty-desc">点击上方按钮创建第一个训练方案</text>
+    </view>
+
+    <!-- 方案列表 -->
+    <view class="plan-list" v-else>
+      <view
+        class="plan-card"
+        v-for="plan in plans"
+        :key="plan.id"
+        @click="goDetail(plan.id)"
+      >
+        <view class="card-top">
+          <text class="plan-title">{{ plan.title || '未命名方案' }}</text>
+          <view class="plan-status" :class="'status-' + (plan.status || 0)">
+            <text>{{ statusText(plan.status) }}</text>
+          </view>
+        </view>
+        <text class="plan-desc" v-if="plan.description">{{ plan.description }}</text>
+        <view class="card-meta">
+          <text class="meta-item">成员:{{ plan.memberName || '--' }}</text>
+          <text class="meta-item">创建时间:{{ formatTime(plan.createdAt) }}</text>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import { getTrainingPlanList } from '@/utils/api.js'
+
+export default {
+  data() {
+    return {
+      loading: false,
+      plans: []
+    }
+  },
+  onLoad() {
+    this.loadPlans()
+  },
+  onShow() {
+    this.loadPlans()
+  },
+  methods: {
+    loadPlans() {
+      this.loading = true
+      var self = this
+      getTrainingPlanList().then(function(res) {
+        self.loading = false
+        if (res && res.code === 200) {
+          self.plans = res.data || []
+        } else {
+          uni.showToast({ title: (res && res.message) || '加载失败', icon: 'none' })
+          self.plans = []
+        }
+      }).catch(function(err) {
+        self.loading = false
+        console.error('加载方案列表失败', err)
+        uni.showToast({ title: '加载失败', icon: 'none' })
+        self.plans = []
+      })
+    },
+    goDetail(planId) {
+      uni.navigateTo({ url: '/pages/teacher/plan-detail?planId=' + planId })
+    },
+    goCreatePlan() {
+      uni.navigateTo({ url: '/pages/teacher/plan-create' })
+    },
+    statusText(status) {
+      var map = { 0: '草稿', 1: '进行中', 2: '已完成', 3: '已取消' }
+      return map[status] || '未知'
+    },
+    formatTime(t) {
+      if (!t) return '-'
+      // 项目统一时间格式:取前19位并把 ISO 的 T 换成空格,避免 toLocaleString 的浏览器差异
+      return String(t).substring(0, 19).replace('T', ' ')
+    }
+  }
+}
+</script>
+
+<style scoped>
+.page {
+  min-height: 100vh;
+  background: #F5FAFE;
+  padding-bottom: 30rpx;
+}
+
+.header {
+  padding: 40rpx 30rpx 20rpx;
+}
+
+.title {
+  font-size: 36rpx;
+  font-weight: bold;
+  color: #1F2D3D;
+  display: block;
+}
+
+.subtitle {
+  font-size: 26rpx;
+  color: #8A94A6;
+  margin-top: 8rpx;
+  display: block;
+}
+
+.action-bar {
+  padding: 0 30rpx 20rpx;
+}
+
+.btn-primary {
+  width: 100%;
+  background: #4A9BD7;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: 600;
+  padding: 24rpx 0;
+  border-radius: 12rpx;
+  border: none;
+}
+
+.loading, .empty {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 100rpx 0;
+}
+
+.loading-text {
+  font-size: 28rpx;
+  color: #8A94A6;
+}
+
+.empty-icon {
+  font-size: 80rpx;
+}
+
+.empty-title {
+  font-size: 32rpx;
+  font-weight: bold;
+  color: #333;
+  margin-top: 20rpx;
+}
+
+.empty-desc {
+  font-size: 26rpx;
+  color: #999;
+  margin-top: 10rpx;
+  text-align: center;
+}
+
+.plan-list {
+  padding: 0 30rpx;
+}
+
+.plan-card {
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 30rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
+}
+
+.plan-card:active {
+  opacity: 0.8;
+}
+
+.card-top {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.plan-title {
+  font-size: 30rpx;
+  font-weight: bold;
+  color: #333;
+  flex: 1;
+}
+
+.plan-status {
+  font-size: 22rpx;
+  padding: 4rpx 16rpx;
+  border-radius: 20rpx;
+}
+
+.status-0 { background: #FFF3E0; color: #F97316; }
+.status-1 { background: #E8F5E9; color: #4CAF50; }
+.status-2 { background: #E3F2FD; color: #2196F3; }
+.status-3 { background: #F5F5F5; color: #999; }
+
+.plan-desc {
+  font-size: 26rpx;
+  color: #666;
+  margin-top: 12rpx;
+  display: block;
+  line-height: 1.5;
+}
+
+.card-meta {
+  display: flex;
+  flex-direction: column;
+  margin-top: 16rpx;
+  gap: 6rpx;
+}
+
+.meta-item {
+  font-size: 24rpx;
+  color: #bbb;
+}
+</style>

+ 5 - 1
cfc-frontend/pages/vendor/products/products.vue

@@ -146,7 +146,11 @@ export default {
       return map[status] || status
     },
     getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     }
   }
 }

+ 56 - 51
cfc-frontend/pages/wealth/index.vue

@@ -729,7 +729,11 @@ export default {
       uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + id })
     },
     getImageUrl: function(path) {
-      return config.API_BASE_URL + path
+      if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
+      var s = String(path).trim()
+      if (!s || s === 'null' || s === '/null') return ''
+      if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
+      return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
     },
     onServiceClick(action) {
       if (this[action]) {
@@ -796,10 +800,10 @@ export default {
   color: rgba(255,255,255,0.8);
   line-height: 1.6;
 }
-<style scoped>
+<style scoped lang="scss">
 .container {
   min-height: 100vh;
-  background: #f5f7fa;
+  background: $app-bg;
   padding-bottom: 120rpx;
 }
 
@@ -815,16 +819,16 @@ export default {
 .section-title {
   font-size: 30rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
 }
 .section-more {
   font-size: 24rpx;
-  color: #999;
+  color: $app-text-muted;
 }
 
 /* 财富成长 */
 .stream-section {
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx;
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
@@ -839,7 +843,7 @@ export default {
   margin: 0 8rpx;
   padding: 20rpx;
   border-radius: 16rpx;
-  background: #F5F9FC;
+  background: $app-bg;
   display: flex;
   flex-direction: column;
   align-items: center;
@@ -854,17 +858,17 @@ export default {
 .stage-name {
   font-size: 26rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
   margin-top: 8rpx;
 }
 .stage-desc {
   font-size: 20rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-top: 4rpx;
 }
 .stage-range {
   font-size: 20rpx;
-  color: #F59E0B;
+  color: $dim-wealth;
   margin-top: 4rpx;
 }
 .stream-water {
@@ -876,14 +880,14 @@ export default {
 .stream-water-fill {
   height: 100%;
   border-radius: 10rpx;
-  background: linear-gradient(90deg, #F59E0B, #FBBF24);
+  background: linear-gradient(90deg, $dim-wealth, #FBBF24);
   transition: width 0.8s ease;
 }
 .stream-percent {
   display: block;
   text-align: right;
   font-size: 22rpx;
-  color: #F59E0B;
+  color: $dim-wealth;
   margin-top: 8rpx;
 }
 .stream-tip {
@@ -910,7 +914,7 @@ export default {
 .disc-value {
   font-size: 56rpx;
   font-weight: bold;
-  color: #F59E0B;
+  color: $dim-wealth;
   margin-top: 8rpx;
 }
 .disc-sub {
@@ -924,7 +928,7 @@ export default {
 }
 .disc-sub-card {
   flex: 1;
-  background: #fff;
+  background: $app-surface;
   border-radius: 16rpx;
   padding: 24rpx;
   display: flex;
@@ -939,24 +943,24 @@ export default {
 }
 .disc-sub-label {
   font-size: 24rpx;
-  color: #999;
+  color: $app-text-muted;
 }
 .disc-sub-value {
   font-size: 36rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
   margin-top: 8rpx;
 }
 .disc-sub-action {
   font-size: 22rpx;
-  color: #F59E0B;
+  color: $dim-wealth;
   margin-top: 8rpx;
 }
 
 /* 孩子财富卡 */
 .child-wealth-card {
   display: flex;
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx 0;
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
@@ -973,24 +977,24 @@ export default {
 .child-wealth-value {
   font-size: 36rpx;
   font-weight: bold;
-  color: #F59E0B;
+  color: $dim-wealth;
   margin-top: 8rpx;
 }
 .child-wealth-label {
   font-size: 22rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-top: 4rpx;
 }
 .child-trend {
   margin-top: 16rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx;
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
 }
 .child-trend-title {
   font-size: 26rpx;
-  color: #333;
+  color: $app-text;
   font-weight: bold;
 }
 .child-trend-bars {
@@ -1002,7 +1006,7 @@ export default {
 .trend-bar {
   flex: 1;
   margin: 0 6rpx;
-  background: linear-gradient(180deg, #FBBF24, #F59E0B);
+  background: linear-gradient(180deg, #FBBF24, $dim-wealth);
   border-radius: 6rpx 6rpx 0 0;
 }
 .child-trend-days {
@@ -1013,14 +1017,14 @@ export default {
   flex: 1;
   text-align: center;
   font-size: 20rpx;
-  color: #999;
+  color: $app-text-muted;
 }
 
 /* 服务入口 */
 .service-grid {
   display: flex;
   flex-wrap: wrap;
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx 16rpx;
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
@@ -1047,7 +1051,7 @@ export default {
 }
 .service-label {
   font-size: 22rpx;
-  color: #666;
+  color: $app-text-secondary;
 }
 
 .logout-item {
@@ -1065,7 +1069,7 @@ export default {
   padding: 20rpx 28rpx;
   background: linear-gradient(135deg, #FFFBEB, rgba(245,158,11,0.12));
   border-radius: 16rpx;
-  border-left: 8rpx solid #F59E0B;
+  border-left: 8rpx solid $dim-wealth;
 }
 .brand-strap-text {
   font-size: 26rpx;
@@ -1085,7 +1089,7 @@ export default {
 .product-card {
   width: 220rpx;
   flex-shrink: 0;
-  background: #fff;
+  background: $app-surface;
   border-radius: 16rpx;
   overflow: hidden;
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
@@ -1093,13 +1097,13 @@ export default {
 .product-img {
   width: 220rpx;
   height: 220rpx;
-  background: #f5f5f5;
+  background: $app-surface-subtle;
 }
 .product-name {
   display: block;
   padding: 12rpx 12rpx 4rpx;
   font-size: 24rpx;
-  color: #333;
+  color: $app-text;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
@@ -1109,12 +1113,12 @@ export default {
   padding: 4rpx 12rpx 12rpx;
   font-size: 26rpx;
   font-weight: bold;
-  color: #F59E0B;
+  color: $dim-wealth;
 }
 
 /* 保单管理 */
 .insurance-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx;
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
@@ -1126,10 +1130,10 @@ export default {
   padding: 40rpx 0;
 }
 .insurance-empty-icon { font-size: 60rpx; }
-.insurance-empty-text { font-size: 24rpx; color: #999; margin-top: 12rpx; }
+.insurance-empty-text { font-size: 24rpx; color: $app-text-muted; margin-top: 12rpx; }
 .insurance-item {
   padding: 16rpx 0;
-  border-bottom: 1rpx solid #f5f5f5;
+  border-bottom: 1rpx solid $app-surface-subtle;
 }
 .insurance-item:last-child { border-bottom: none; }
 .insurance-item-header {
@@ -1141,7 +1145,7 @@ export default {
 .insurance-item-name {
   font-size: 26rpx;
   font-weight: 600;
-  color: #333;
+  color: $app-text;
 }
 .insurance-item-status {
   font-size: 20rpx;
@@ -1150,18 +1154,18 @@ export default {
 }
 .insurance-item-status.status-active { background: #DCFCE7; color: #16A34A; }
 .insurance-item-status.status-expired { background: #FEF2F2; color: #DC2626; }
-.insurance-item-status.status-cancelled { background: #F5F5F5; color: #999; }
+.insurance-item-status.status-cancelled { background: $app-surface-subtle; color: $app-text-muted; }
 .insurance-item-row {
   display: flex;
   justify-content: space-between;
   padding: 4rpx 0;
 }
-.insurance-item-label { font-size: 22rpx; color: #999; }
-.insurance-item-value { font-size: 22rpx; color: #666; }
+.insurance-item-label { font-size: 22rpx; color: $app-text-muted; }
+.insurance-item-value { font-size: 22rpx; color: $app-text-secondary; }
 
 /* ===== 财富强项与提升卡片 ===== */
 .wealth-insight {
-  background: #fff;
+  background: $app-surface;
   border-radius: 20rpx;
   padding: 24rpx;
 }
@@ -1171,7 +1175,7 @@ export default {
 .insight-group-title {
   font-size: 26rpx;
   font-weight: 600;
-  color: #333;
+  color: $app-text;
   margin-bottom: 10rpx;
   display: block;
 }
@@ -1186,11 +1190,11 @@ export default {
 .insight-item-name {
   flex: 1;
   font-size: 26rpx;
-  color: #333;
+  color: $app-text;
 }
 .insight-item-score {
   font-size: 24rpx;
-  color: #666;
+  color: $app-text-secondary;
   margin-right: 12rpx;
 }
 .insight-item-tag {
@@ -1214,13 +1218,13 @@ export default {
 }
 .insight-tip-text {
   font-size: 22rpx;
-  color: #F59E0B;
+  color: $dim-wealth;
 }
 
 /* 维度画像样式 */
 .dimension-portrait-section {
   margin: 24rpx 30rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 32rpx 24rpx;
   box-shadow: 0 4rpx 20rpx rgba(245, 158, 11, 0.12);
@@ -1228,7 +1232,7 @@ export default {
 }
 .portrait-tier {
   font-size: 26rpx;
-  color: #F59E0B;
+  color: $dim-wealth;
   font-weight: bold;
   margin-left: 16rpx;
 }
@@ -1237,7 +1241,7 @@ export default {
 }
 .portrait-desc {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
   line-height: 1.6;
   display: block;
 }
@@ -1265,13 +1269,13 @@ export default {
 }
 .portrait-dim-name {
   font-size: 24rpx;
-  color: #333;
+  color: $app-text;
   flex: 1;
 }
 .portrait-dim-score {
   font-size: 26rpx;
   font-weight: bold;
-  color: #F59E0B;
+  color: $dim-wealth;
   margin-right: 12rpx;
 }
 .portrait-dim-bar-track {
@@ -1289,14 +1293,14 @@ export default {
 }
 .portrait-dim-desc {
   font-size: 20rpx;
-  color: #666;
+  color: $app-text-secondary;
   display: block;
 }
 .portrait-tip {
   padding: 16rpx 20rpx;
   background: linear-gradient(135deg, #FFF7ED, #FFF3E8);
   border-radius: 12rpx;
-  border-left: 8rpx solid #F59E0B;
+  border-left: 8rpx solid $dim-wealth;
   margin-top: 16rpx;
 }
 .portrait-tip-text {
@@ -1316,4 +1320,5 @@ export default {
   gap: 12rpx;
 }
 .guidance-icon { font-size: 32rpx; flex-shrink: 0; }
-.guidance-text { font-size: 26rpx; color: #F59E0B; font-weight: 500; }
+.guidance-text { font-size: 26rpx; color: $dim-wealth; font-weight: 500; }
+</style>

+ 46 - 46
cfc-frontend/pages/wisdom-detail/index.vue

@@ -739,10 +739,10 @@ export default {
 }
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .wisdom-container {
   min-height: 100vh;
-  background: #f5f7fa;
+  background: $app-bg;
   padding-bottom: 120rpx;
 }
 
@@ -751,7 +751,7 @@ export default {
 }
 
 .func-grid {
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 30rpx 16rpx;
   display: flex;
@@ -786,7 +786,7 @@ export default {
 
 .func-label {
   font-size: 24rpx;
-  color: #333;
+  color: $app-text;
   font-weight: 500;
 }
 
@@ -806,7 +806,7 @@ export default {
 .section-title {
   font-size: 30rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
 }
 
 /* 页面说明(独占一行,避免与标题挤在同一行) */
@@ -822,15 +822,15 @@ export default {
 .section-more {
   flex-shrink: 0;
   font-size: 24rpx;
-  color: #6366F1;
+  color: $dim-wisdom;
 }
 
 /* 得分解读卡片 */
 .score-explain-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 28rpx 24rpx;
-  border-left: 8rpx solid #6366F1;
+  border-left: 8rpx solid $dim-wisdom;
   box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
 }
 .explain-header {
@@ -845,19 +845,19 @@ export default {
 .explain-title {
   font-size: 30rpx;
   font-weight: bold;
-  color: #333;
+  color: $app-text;
 }
 .explain-text {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
   line-height: 1.6;
   display: block;
 }
 
 /* 主按钮 */
 .primary-btn {
-  background: linear-gradient(135deg, #6366F1, #4F46E5);
-  color: #fff;
+  background: linear-gradient(135deg, $dim-wisdom, #4F46E5);
+  color: $app-surface;
   font-size: 26rpx;
   font-weight: bold;
   border: none;
@@ -874,20 +874,20 @@ export default {
 /* ===== 底部占位 ===== */
 .indicator-cards-section { margin: 20rpx 30rpx; }
 .indicator-cards { display: flex; flex-direction: row; flex-wrap: wrap; gap: 16rpx; }
-.indicator-card { width: calc(50% - 8rpx); background: #fff; border-radius: 20rpx; padding: 24rpx 20rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.indicator-card { width: calc(50% - 8rpx); background: $app-surface; border-radius: 20rpx; padding: 24rpx 20rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .indicator-card.no-data { opacity: 0.5; }
 .indicator-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
-.indicator-name { font-size: 26rpx; color: #666; font-weight: 500; }
-.indicator-unit { font-size: 22rpx; color: #999; }
+.indicator-name { font-size: 26rpx; color: $app-text-secondary; font-weight: 500; }
+.indicator-unit { font-size: 22rpx; color: $app-text-muted; }
 .indicator-body { margin-bottom: 8rpx; }
-.indicator-value { font-size: 40rpx; font-weight: bold; color: #6366F1; }
-.indicator-placeholder { font-size: 26rpx; color: #ccc; }
+.indicator-value { font-size: 40rpx; font-weight: bold; color: $dim-wisdom; }
+.indicator-placeholder { font-size: 26rpx; color: $app-border; }
 .indicator-range { font-size: 20rpx; color: #bbb; }
 .bottom-spacer { height: 120rpx; }
 
 /* DAN 报告卡片 */
 .dan-card {
-  background: #fff;
+  background: $app-surface;
   border-radius: 16rpx;
   padding: 24rpx;
   margin-bottom: 16rpx;
@@ -901,7 +901,7 @@ export default {
 }
 .dan-report-date {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
 }
 .dan-status {
   font-size: 22rpx;
@@ -918,7 +918,7 @@ export default {
 }
 .dan-report-desc {
   font-size: 28rpx;
-  color: #333;
+  color: $app-text;
   font-weight: 500;
   margin-bottom: 12rpx;
   display: block;
@@ -928,17 +928,17 @@ export default {
 }
 .dan-view-link {
   font-size: 26rpx;
-  color: #6366F1;
+  color: $dim-wisdom;
 }
 .dan-empty {
-  background: #fff;
+  background: $app-surface;
   border-radius: 16rpx;
   padding: 40rpx 24rpx;
   text-align: center;
 }
 .dan-empty-text {
   font-size: 24rpx;
-  color: #999;
+  color: $app-text-muted;
 }
 .avg-badge {
   flex: 1 1 100%;
@@ -954,7 +954,7 @@ export default {
   padding: 24rpx 28rpx;
   background: linear-gradient(135deg, #F0F0FF, rgba(99,102,241,0.16));
   border-radius: 16rpx;
-  border-left: 8rpx solid #6366F1;
+  border-left: 8rpx solid $dim-wisdom;
   box-shadow: 0 2rpx 12rpx rgba(99,102,241,0.12);
 }
 .brand-strap-text {
@@ -970,7 +970,7 @@ export default {
   padding: 20rpx 28rpx;
   background: linear-gradient(135deg, #F0F0FF, rgba(99,102,241,0.08));
   border-radius: 16rpx;
-  border-left: 8rpx solid #6366F1;
+  border-left: 8rpx solid $dim-wisdom;
   display: flex;
   align-items: center;
   gap: 12rpx;
@@ -985,7 +985,7 @@ export default {
 /* ===== 肠胃与认知卡片 ===== */
 .gut-cog-subtitle {
   font-size: 24rpx;
-  color: #6366F1;
+  color: $dim-wisdom;
   margin-bottom: 16rpx;
   display: block;
 }
@@ -1005,13 +1005,13 @@ export default {
 }
 .gut-indicator-name {
   font-size: 22rpx;
-  color: #666;
+  color: $app-text-secondary;
   font-weight: 500;
   display: block;
 }
 .gut-indicator-impact {
   font-size: 18rpx;
-  color: #6366F1;
+  color: $dim-wisdom;
   display: block;
   margin-top: 2rpx;
 }
@@ -1029,7 +1029,7 @@ export default {
 }
 .gut-indicator-value {
   font-size: 22rpx;
-  color: #666;
+  color: $app-text-secondary;
   width: 60rpx;
   text-align: right;
 }
@@ -1064,12 +1064,12 @@ export default {
 }
 .gut-empty-text {
   font-size: 26rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-bottom: 24rpx;
 }
 .gut-upload-btn {
-  background: linear-gradient(135deg, #6366F1, #818CF8);
-  color: #fff;
+  background: linear-gradient(135deg, $dim-wisdom, #818CF8);
+  color: $app-surface;
   font-size: 26rpx;
   font-weight: 600;
   border: none;
@@ -1086,7 +1086,7 @@ export default {
 .insight-group-title {
   font-size: 26rpx;
   font-weight: 600;
-  color: #333;
+  color: $app-text;
   margin-bottom: 10rpx;
   display: block;
 }
@@ -1101,11 +1101,11 @@ export default {
 .insight-item-name {
   flex: 1;
   font-size: 26rpx;
-  color: #333;
+  color: $app-text;
 }
 .insight-item-score {
   font-size: 24rpx;
-  color: #666;
+  color: $app-text-secondary;
   margin-right: 12rpx;
 }
 .insight-item-tag {
@@ -1129,7 +1129,7 @@ export default {
 }
 .insight-tip-text {
   font-size: 22rpx;
-  color: #6366F1;
+  color: $dim-wisdom;
 }
 .insight-empty {
   display: flex;
@@ -1139,12 +1139,12 @@ export default {
 }
 .insight-empty-text {
   font-size: 24rpx;
-  color: #999;
+  color: $app-text-muted;
   margin-bottom: 20rpx;
 }
 .insight-btn {
-  background: linear-gradient(135deg, #6366F1, #818CF8);
-  color: #fff;
+  background: linear-gradient(135deg, $dim-wisdom, #818CF8);
+  color: $app-surface;
   font-size: 26rpx;
   font-weight: 600;
   border: none;
@@ -1157,7 +1157,7 @@ export default {
 /* 维度画像样式 */
 .dimension-portrait-section {
   margin: 24rpx 30rpx;
-  background: #fff;
+  background: $app-surface;
   border-radius: 24rpx;
   padding: 32rpx 24rpx;
   box-shadow: 0 4rpx 20rpx rgba(99, 102, 241, 0.12);
@@ -1165,7 +1165,7 @@ export default {
 }
 .portrait-tier {
   font-size: 26rpx;
-  color: #6366F1;
+  color: $dim-wisdom;
   font-weight: bold;
   margin-left: 16rpx;
 }
@@ -1174,7 +1174,7 @@ export default {
 }
 .portrait-desc {
   font-size: 26rpx;
-  color: #666;
+  color: $app-text-secondary;
   line-height: 1.6;
   display: block;
 }
@@ -1201,13 +1201,13 @@ export default {
 }
 .portrait-dim-name {
   font-size: 24rpx;
-  color: #333;
+  color: $app-text;
   flex: 1;
 }
 .portrait-dim-score {
   font-size: 26rpx;
   font-weight: bold;
-  color: #6366F1;
+  color: $dim-wisdom;
   margin-right: 12rpx;
 }
 .portrait-dim-bar-track {
@@ -1225,14 +1225,14 @@ export default {
 }
 .portrait-dim-desc {
   font-size: 20rpx;
-  color: #999;
+  color: $app-text-muted;
   display: block;
 }
 .portrait-tip {
   padding: 16rpx 20rpx;
   background: linear-gradient(135deg, #F0F4FF, #E8F1FE);
   border-radius: 12rpx;
-  border-left: 8rpx solid #6366F1;
+  border-left: 8rpx solid $dim-wisdom;
   margin-top: 16rpx;
 }
 .portrait-tip-text {

+ 64 - 1
cfc-frontend/uni.scss

@@ -338,4 +338,67 @@ $uni-transition-slow: 0.3s ease;
 .skeleton-block {
   @include skeleton;
   height: 160rpx;
-}
+}
+
+
+// ============================================================
+// 12. 五维 + 品牌运行时令牌(对齐真实线上视觉)
+// ============================================================
+// 背景:原 $uni-primary(#5B9BD5 蓝) 与线上实际主色不一致,且五维色长期硬编码在页面里。
+// 本段补齐「真实在用」的语义令牌;页面改用这些名字,避免逐个硬编码。
+// 注意:mp-weixin 对 CSS var(--x) 运行时解析不稳定,故统一用 SCSS 变量(编译期内联,零运行时风险)。
+
+/* 品牌主色 —— 与 pages.json tabBar.selectedColor 一致 */
+$brand-primary: #F97316;
+$brand-primary-dark: #EA580C;
+$brand-primary-soft: rgba(249, 115, 22, 0.12);
+
+/* 五维身份色:页面 PageBanner / 分段左条 / CTA / 价值卡浅底统一取用 */
+$dim-body:   #FF8C42;
+$dim-mind:   #FF6B9D;
+$dim-wisdom: #6366F1;
+$dim-action: #10B981;
+$dim-wealth: #F59E0B;
+
+$dim-body-soft:   rgba(255, 140, 66, 0.15);
+$dim-mind-soft:   rgba(255, 107, 157, 0.15);
+$dim-wisdom-soft: rgba(99, 102, 241, 0.15);
+$dim-action-soft: rgba(16, 185, 129, 0.15);
+$dim-wealth-soft: rgba(245, 158, 11, 0.15);
+
+/* 语义角色(与应用真实观感一致) */
+$app-bg:             #F5F7FA;
+$app-surface:        #FFFFFF;
+$app-surface-subtle: #F7F8FA;
+$app-text:           #17181C;
+$app-text-secondary: #606875;
+$app-text-muted:     #8A94A3;
+$app-border-subtle:  #E7EBF0;
+$app-border:         #CBD5E1;
+
+/* 状态:按压/禁用用透明度与语言表达,不新增多套颜色 */
+$press-opacity:    0.85;
+$disabled-opacity: 0.45;
+
+/* 动效令牌:只声明稳定属性,禁止 transition: all */
+$ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
+$dur-press:      0.12s;
+$dur-state:      0.2s;
+$dur-structural: 0.26s;
+
+/* 可复用 mixin */
+@mixin dim-card($radius: $uni-radius-md) {
+  background: $app-surface;
+  border-radius: $radius;
+  box-shadow: $uni-shadow-sm;
+}
+
+@mixin press-scale {
+  transition: opacity $dur-press $ease-standard, transform $dur-press $ease-standard;
+  &:active { opacity: $press-opacity; }
+}
+
+@mixin touch-target($size: 88rpx) {
+  min-height: $size;
+  min-width: $size;
+}

File diff suppressed because it is too large
+ 12 - 38
docs/参考资料/530010234-侯.json


File diff suppressed because it is too large
+ 36 - 62
docs/参考资料/547982403.json


File diff suppressed because it is too large
+ 29 - 59
docs/参考资料/556168709-mi.json


File diff suppressed because it is too large
+ 13 - 80
docs/参考资料/儿童示例.json


File diff suppressed because it is too large
+ 355 - 27
docs/参考资料/朱评估报告.json


File diff suppressed because it is too large
+ 642 - 58
docs/参考资料/知识库/菌群营养知识库.json


+ 131 - 25
docs/参考资料/知识库/菌群营养知识库.md

@@ -28,22 +28,22 @@
 
 ## 一、食物营养含量库
 
-食材数:**226** 种。
+食材数:**332** 种。
 
 | 食材 | 分类 | 能量(kJ) | 蛋白(g) | 脂肪(g) | 碳水(g) | 淀粉(g) | 膳食纤维(g) | 胆固醇(mg) |
 | --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
-| 三文鱼 | 水产品 | 594.0 | 19.0 | 6.0 |  |  |  | 55.0 |
-| 冰淇淋 | 乳制品 | 690.0 | 1.0 | 3.0 | 32.0 |  |  | 8.0 |
+| 三文鱼 | 水产品 | 594.0 | 19.0 | 6.0 |  |  | 0 | 55.0 |
+| 冰淇淋 | 乳制品 | 690.0 | 1.0 | 3.0 | 32.0 |  | 0 | 8.0 |
 | 凤尾鱼 | 水产品 | 548.0 | 20.0 | 4.0 |  |  |  | 60.0 |
 | 利马豆 | 豆类及豆制品 | 1414.0 | 21.0 |  | 63.0 |  | 19.0 |  |
-| 南瓜 | 蔬菜 | 109.0 | 1.0 |  | 6.0 |  |  |  |
+| 南瓜 | 蔬菜 | 109.0 | 1.0 |  | 6.0 |  | 1.5 |  |
 | 卷心菜 | 蔬菜 | 103.0 | 1.0 |  | 5.0 |  | 2.0 |  |
-| 哈密瓜 | 水果 | 141.0 |  |  | 8.0 |  |  |  |
+| 哈密瓜 | 水果 | 141.0 |  |  | 8.0 |  | 0.2 |  |
 | 四季豆 | 蔬菜 | 131.0 | 1.0 |  | 6.0 |  | 2.0 |  |
 | 土豆 | 蔬菜 | 322.0 | 2.0 |  | 17.0 | 15.0 | 2.0 |  |
 | 土豆蔬菜汤 | 汤 | 126.0 | 1.0 | 1.0 | 3.0 |  |  | 1.0 |
 | 土豆面粉 | 蔬菜 | 1493.0 | 6.0 |  | 83.0 |  | 5.0 |  |
-| 墨鱼 | 水产品 | 331.0 | 16.0 |  |  |  |  | 112.0 |
+| 墨鱼 | 水产品 | 331.0 | 16.0 |  |  |  | 0 | 112.0 |
 | 大比目鱼 | 水产品 | 267.0 | 19.0 | 28.0 |  |  |  | 49.0 |
 | 大氏目鱼 | 水产品 | 382.0 | 18.0 | 1.0 |  |  |  | 49.0 |
 | 大白菜 | 蔬菜 | 55.0 | 1.0 |  | 2.0 |  | 1.0 |  |
@@ -53,8 +53,8 @@
 | 大豆面粉 | 豆类及豆制品 | 1816.0 | 37.0 | 20.0 | 31.0 |  | 9.0 |  |
 | 大麦 | 主食 | 1481.0 | 12.0 | 2.0 | 73.0 |  | 17.0 |  |
 | 奶油 | 乳制品 | 515.0 | 3.0 | 10.0 | 4.0 |  |  | 35.0 |
-| 奶酪 | 乳制品 | 1552.0 | 23.0 | 29.0 | 2.0 |  |  | 94.0 |
-| 嫩豆腐 | 豆类及豆制品 | 253.0 | 7.0 | 3.0 | 1.0 |  |  |  |
+| 奶酪 | 乳制品 | 1552.0 | 23.0 | 29.0 | 2.0 |  | 0 | 94.0 |
+| 嫩豆腐 | 豆类及豆制品 | 253.0 | 7.0 | 3.0 | 1.0 |  | 0.5 |  |
 | 小南瓜 | 蔬菜 | 69.0 | 1.0 |  | 3.0 |  | 1.0 |  |
 | 小米 | 主食 | 1582.0 | 11.0 | 4.0 | 72.0 |  | 8.0 |  |
 | 小萝卜 | 蔬菜 | 76.0 |  |  | 4.0 |  | 1.0 |  |
@@ -63,11 +63,11 @@
 | 小龙虾 | 水产品 | 322.0 | 15.0 |  |  |  |  | 114.0 |
 | 山核桃 | 干果 | 2889.0 | 9.0 | 71.0 | 13.0 |  | 9.0 |  |
 | 山核桃干 | 干果 | 2749.0 | 12.0 | 64.0 | 18.0 |  | 6.0 |  |
-| 山药 | 蔬菜 | 343.0 | 1.0 |  | 20.0 |  |  |  |
+| 山药 | 蔬菜 | 343.0 | 1.0 |  | 20.0 |  | 1.4 |  |
 | 开心果 | 干果 | 2392.0 | 21.0 | 45.0 | 28.0 | 1.0 | 10.0 |  |
 | 意大利面 | 主食 | 386.0 | 1.0 | 3.0 | 13.0 |  | 2.0 |  |
 | 扁豆 | 豆类及豆制品 | 1473.0 | 24.0 | 1.0 | 63.0 | 49.0 | 10.0 |  |
-| 扇贝 | 水产品 | 289.0 | 12.0 |  | 3.0 | 2.0 |  | 24.0 |
+| 扇贝 | 水产品 | 289.0 | 12.0 |  | 3.0 | 2.0 | 0 | 24.0 |
 | 无花果 | 水果 | 310.0 |  |  | 19.0 |  | 2.0 |  |
 | 木薯 | 蔬菜 | 667.0 | 1.0 |  | 38.0 |  | 1.0 |  |
 | 李子 | 水果 | 192.0 |  |  | 11.0 |  | 1.0 |  |
@@ -118,13 +118,13 @@
 | 牛肉肥 | 肉类 | 2845.0 | 10.0 | 70.0 |  |  |  | 95.0 |
 | 牛蒡根 | 蔬菜 | 302.0 | 1.0 |  | 17.0 |  | 3.0 |  |
 | 牛蛙 | 肉类 | 305.0 | 16.0 |  |  |  |  | 50.0 |
-| 牡蛎 | 水产品 | 339.0 | 9.0 | 2.0 | 4.0 |  |  | 50.0 |
+| 牡蛎 | 水产品 | 339.0 | 9.0 | 2.0 | 4.0 |  | 0 | 50.0 |
 | 猕猴桃 | 水果 | 255.0 | 1.0 |  | 14.0 |  | 3.0 |  |
 | 猪培根 | 肉类 | 1744.0 | 12.0 | 39.0 | 1.0 |  |  | 66.0 |
 | 猪头肉 | 肉类 | 658.0 | 13.0 | 10.0 |  |  |  | 69.0 |
 | 猪瘦肉 | 肉类 | 562.0 | 21.0 | 4.0 |  |  |  | 64.0 |
 | 猪耳朵 | 肉类 | 695.0 | 15.0 | 10.0 |  |  |  | 90.0 |
-| 猪肝 | 肉类 | 690.0 | 26.0 | 4.0 | 3.0 |  |  | 355.0 |
+| 猪肝 | 肉类 | 690.0 | 26.0 | 4.0 | 3.0 |  | 0 | 355.0 |
 | 猪脑 | 肉类 | 577.0 | 12.0 | 9.0 |  |  |  | 2552.0 |
 | 猪蹄 | 肉类 | 889.0 | 23.0 | 12.0 |  |  |  | 88.0 |
 | 玉米粒 | 主食 | 298.0 | 1.0 |  | 14.0 | 14.0 |  |  |
@@ -154,7 +154,7 @@
 | 素食蔬菜汤 | 汤 | 119.0 |  |  | 4.0 |  |  |  |
 | 红心萝卜 | 蔬菜 | 132.0 | 1.0 |  | 7.0 |  | 3.0 |  |
 | 红苹果 | 水果 | 247.0 |  |  | 14.0 |  | 2.0 |  |
-| 红豆 | 蔬菜 | 121.0 | 4.0 |  | 4.0 |  |  |  |
+| 红豆 | 蔬菜 | 121.0 | 4.0 |  | 4.0 |  | 7.7 |  |
 | 纳豆 | 豆类及豆制品 | 883.0 | 19.0 | 11.0 | 12.0 |  | 5.0 |  |
 | 绿豆 | 蔬菜 | 126.0 | 3.0 |  | 5.0 |  | 1.0 |  |
 | 羽扇豆 | 豆类及豆制品 | 1554.0 | 36.0 | 9.0 | 40.0 |  | 18.0 |  |
@@ -178,7 +178,7 @@
 | 花生酱 | 豆类及豆制品 | 2464.0 | 24.0 | 49.0 | 21.0 | 4.0 | 8.0 |  |
 | 芹菜 | 蔬菜 | 67.0 |  |  | 2.0 |  | 1.0 |  |
 | 苋菜叶 | 蔬菜 | 97.0 | 2.0 |  | 4.0 |  |  |  |
-| 苦瓜 | 蔬菜 | 126.0 | 5.0 |  | 3.0 |  |  |  |
+| 苦瓜 | 蔬菜 | 126.0 | 5.0 |  | 3.0 |  | 1.4 |  |
 | 苹果 | 水果 | 218.0 |  |  | 13.0 |  | 2.0 |  |
 | 苹果汁 | 水果 | 191.0 |  |  | 11.0 |  |  |  |
 | 茄子 | 蔬菜 | 104.0 |  |  | 5.0 |  | 3.0 |  |
@@ -191,7 +191,7 @@
 | 菠菜 | 蔬菜 | 97.0 | 2.0 |  | 3.0 |  | 2.0 |  |
 | 菠萝 | 水果 | 209.0 |  |  | 13.0 |  | 1.0 |  |
 | 菠萝蜜 | 水果 | 397.0 | 1.0 |  | 23.0 | 1.0 | 1.0 |  |
-| 葡萄 | 水果 | 280.0 |  |  | 17.0 |  |  |  |
+| 葡萄 | 水果 | 280.0 |  |  | 17.0 |  | 0.4 |  |
 | 葡萄干 | 水果 | 264.0 | 1.0 |  | 15.0 |  |  |  |
 | 葡萄干浆即食谷物 | 主食 | 1354.0 | 7.0 | 1.0 | 78.0 |  | 13.0 |  |
 | 葡萄柚 | 水果 | 134.0 |  |  | 8.0 |  | 1.0 |  |
@@ -201,12 +201,12 @@
 | 蕨类 | 蔬菜 | 143.0 | 4.0 |  | 5.0 |  |  |  |
 | 藜 | 蔬菜 | 180.0 | 4.0 |  | 7.0 |  | 4.0 |  |
 | 蘑菇 | 蔬菜 | 141.0 | 2.0 |  | 6.0 |  | 2.0 |  |
-| 虾 | 水产品 | 297.0 | 13.0 | 1.0 |  |  |  | 126.0 |
+| 虾 | 水产品 | 297.0 | 13.0 | 1.0 |  |  | 0 | 126.0 |
 | 蚕豆 | 豆类及豆制品 | 1425.0 | 26.0 | 1.0 | 58.0 |  | 25.0 |  |
 | 蛤蜊 | 水产品 | 360.0 | 14.0 |  | 3.0 | 1.0 |  | 30.0 |
-| 蟹 | 水产品 | 364.0 | 18.0 | 1.0 |  |  |  | 78.0 |
+| 蟹 | 水产品 | 364.0 | 18.0 | 1.0 |  |  | 0 | 78.0 |
 | 西兰花 | 蔬菜 | 141.0 | 2.0 |  | 6.0 |  | 2.0 |  |
-| 西瓜 | 水果 | 127.0 |  |  | 7.0 |  |  |  |
+| 西瓜 | 水果 | 127.0 |  |  | 7.0 |  | 0.4 |  |
 | 西红柿 | 蔬菜 | 74.0 |  |  | 3.0 |  | 1.0 |  |
 | 覆盆子 | 水果 | 220.0 | 1.0 |  | 11.0 |  | 6.0 |  |
 | 豆浆 | 豆类及豆制品 | 226.0 | 3.0 | 1.0 | 6.0 |  |  |  |
@@ -223,8 +223,8 @@
 | 香菇 | 蔬菜 | 160.0 | 1.0 |  | 6.0 |  | 3.0 |  |
 | 香蕉 | 水果 | 371.0 | 1.0 |  | 22.0 | 5.0 | 2.0 |  |
 | 鱼子酱 | 水产品 | 1105.0 | 24.0 | 17.0 | 4.0 |  |  | 588.0 |
-| 鱿鱼 | 水产品 | 385.0 | 15.0 | 1.0 | 3.0 |  |  | 233.0 |
-| 鲈鱼 | 水产品 | 381.0 | 19.0 |  |  |  |  | 90.0 |
+| 鱿鱼 | 水产品 | 385.0 | 15.0 | 1.0 | 3.0 |  | 0 | 233.0 |
+| 鲈鱼 | 水产品 | 381.0 | 19.0 |  |  |  | 0 | 90.0 |
 | 鲍鱼 | 水产品 | 439.0 | 17.0 |  | 6.0 |  |  | 85.0 |
 | 鲟鱼 | 水产品 | 439.0 | 16.0 | 4.0 |  |  |  | 60.0 |
 | 鲤鱼 | 水产品 | 531.0 | 17.0 | 5.0 |  |  |  | 66.0 |
@@ -234,30 +234,136 @@
 | 鲷鱼 | 水产品 | 418.0 | 20.0 | 1.0 |  |  |  | 37.0 |
 | 鲽鱼 | 水产品 | 294.0 | 12.0 | 1.0 |  |  |  | 45.0 |
 | 鳄梨 | 水果 | 670.0 | 2.0 | 14.0 | 8.0 |  | 6.0 |  |
-| 鳕鱼 | 水产品 | 364.0 | 18.0 |  |  |  |  | 41.0 |
+| 鳕鱼 | 水产品 | 364.0 | 18.0 |  |  |  | 0 | 41.0 |
 | 鳗鱼 | 水产品 | 770.0 | 18.0 | 11.0 |  |  |  | 126.0 |
 | 鳟鱼 | 水产品 | 619.0 | 20.0 | 6.0 |  |  |  | 58.0 |
 | 鸡心 | 肉类 | 640.0 | 15.0 | 9.0 |  |  |  | 136.0 |
 | 鸡汤 | 肉类 | 26.0 |  |  |  |  |  | 2.0 |
 | 鸡米花 | 快餐 | 1469.0 | 17.0 | 21.0 | 21.0 | 18.0 | 1.0 | 40.0 |
-| 鸡肉 | 肉类 | 604.0 | 28.0 | 3.0 |  |  |  | 86.0 |
+| 鸡肉 | 肉类 | 604.0 | 28.0 | 3.0 |  |  | 0 | 86.0 |
 | 鸡肝 | 肉类 | 496.0 | 16.0 | 4.0 |  |  |  | 345.0 |
-| 鸡蛋 | 蛋类 | 599.0 | 12.0 | 9.0 |  |  |  | 372.0 |
+| 鸡蛋 | 蛋类 | 599.0 | 12.0 | 9.0 |  |  | 0 | 372.0 |
 | 鸡蛋白 | 蛋类 | 216.0 | 10.0 |  |  |  |  |  |
 | 鸡蛋面包 | 主食 | 1201.0 | 9.0 | 6.0 | 47.0 |  | 2.0 | 51.0 |
 | 鸡蛋黄 | 蛋类 | 1346.0 | 15.0 | 26.0 | 3.0 |  |  | 1085.0 |
 | 鹅肝 | 肉类 | 556.0 | 16.0 | 4.0 | 6.0 |  |  | 515.0 |
 | 鹌鹑 | 肉类 | 803.0 | 19.0 | 12.0 |  |  |  | 76.0 |
-| 鹌鹑蛋 | 蛋类 | 663.0 | 13.0 | 11.0 |  |  |  | 844.0 |
+| 鹌鹑蛋 | 蛋类 | 663.0 | 13.0 | 11.0 |  |  | 0 | 844.0 |
 | 鹰嘴豆 | 豆类及豆制品 | 1581.0 | 20.0 | 6.0 | 62.0 |  | 12.0 |  |
 | 黄尾 | 水产品 | 611.0 | 23.0 | 5.0 |  |  |  | 55.0 |
 | 黄油 | 乳制品 | 2999.0 |  | 81.0 |  |  |  | 215.0 |
-| 黄瓜 | 蔬菜 | 65.0 |  |  | 3.0 |  |  |  |
+| 黄瓜 | 蔬菜 | 65.0 |  |  | 3.0 |  | 0.5 |  |
 | 黄豆 | 豆类及豆制品 | 1443.0 | 22.0 | 2.0 | 60.0 |  | 25.0 |  |
 | 黑莓 | 水果 | 181.0 | 1.0 |  | 9.0 |  | 5.0 |  |
 | 黑麦面包 | 主食 | 1188.0 | 9.0 | 3.0 | 53.0 |  | 6.0 |  |
 | 龙眼 | 水果 | 251.0 | 1.0 |  | 15.0 |  | 1.0 |  |
 | 龙虾 | 水产品 | 324.0 | 16.0 |  |  |  |  | 127.0 |
+| 白米饭 | 主食谷物 |  |  |  |  |  | — |  |
+| 糙米饭 | 主食谷物 |  |  |  |  |  | 3.5 |  |
+| 胚芽米饭 | 主食谷物 |  |  |  |  |  | 2.0 |  |
+| 小米粥 | 主食谷物 |  |  |  |  |  | 1.6 |  |
+| 燕麦饭 | 主食谷物 |  |  |  |  |  | 6.0 |  |
+| 即食燕麦片 | 主食谷物 |  |  |  |  |  | 6.0 |  |
+| 钢切燕麦 | 主食谷物 |  |  |  |  |  | 6.0 |  |
+| 藜麦 | 主食谷物 |  |  |  |  |  | 7.0 |  |
+| 荞麦 | 主食谷物 |  |  |  |  |  | 6.5 |  |
+| 荞麦面 | 主食谷物 |  |  |  |  |  | 4.0 |  |
+| 玉米面粥 | 主食谷物 |  |  |  |  |  | 2.0 |  |
+| 黑米(饭) | 主食谷物 |  |  |  |  |  | 3.9 |  |
+| 薏米 | 主食谷物 |  |  |  |  |  | 2.0 |  |
+| 高粱米 | 主食谷物 |  |  |  |  |  | 4.3 |  |
+| 青稞 | 主食谷物 |  |  |  |  |  | 9.0 |  |
+| 莜面 | 主食谷物 |  |  |  |  |  | 8.0 |  |
+| 全麦面包 | 主食谷物 |  |  |  |  |  | 6.0 |  |
+| 白面包 | 主食谷物 |  |  |  |  |  | 2.7 |  |
+| 白馒头 | 主食谷物 |  |  |  |  |  | 1.5 |  |
+| 挂面(煮) | 主食谷物 |  |  |  |  |  | 2.0 |  |
+| 米粉/米线 | 主食谷物 |  |  |  |  |  | 1.0 |  |
+| 绿豆粉丝 | 主食谷物 |  |  |  |  |  | 1.1 |  |
+| 红薯(蒸) | 主食谷物 |  |  |  |  |  | 3.0 |  |
+| 烤红薯 | 主食谷物 |  |  |  |  |  | 3.0 |  |
+| 紫薯(蒸) | 主食谷物 |  |  |  |  |  | 2.5 |  |
+| 土豆泥 | 主食谷物 |  |  |  |  |  | 1.8 |  |
+| 莲藕(煮) | 主食谷物 |  |  |  |  |  | 2.2 |  |
+| 冷却米饭(隔夜) | 主食谷物 |  |  |  |  |  | 1.0 |  |
+| 青香蕉 | 主食谷物 |  |  |  |  |  | 2.6 |  |
+| 黑豆(煮) | 豆类及豆制品 |  |  |  |  |  | 10.2 |  |
+| 芸豆(煮) | 豆类及豆制品 |  |  |  |  |  | 9.8 |  |
+| 北豆腐(老豆腐) | 豆类及豆制品 |  |  |  |  |  | 0.8 |  |
+| 无糖豆浆 | 豆类及豆制品 |  |  |  |  |  | 1.1 |  |
+| 豆干 | 豆类及豆制品 |  |  |  |  |  | 1.6 |  |
+| 天贝 | 豆类及豆制品 |  |  |  |  |  | 8.0 |  |
+| 毛豆(煮) | 豆类及豆制品 |  |  |  |  |  | 4.0 |  |
+| 油菜 | 蔬菜 |  |  |  |  |  | 1.1 |  |
+| 油麦菜 | 蔬菜 |  |  |  |  |  | 0.6 |  |
+| 空心菜 | 蔬菜 |  |  |  |  |  | 1.4 |  |
+| 苋菜 | 蔬菜 |  |  |  |  |  | 2.2 |  |
+| 芥蓝 | 蔬菜 |  |  |  |  |  | 1.6 |  |
+| 菜心 | 蔬菜 |  |  |  |  |  | 1.7 |  |
+| 茼蒿 | 蔬菜 |  |  |  |  |  | 1.2 |  |
+| 菜花 | 蔬菜 |  |  |  |  |  | 2.0 |  |
+| 番茄(鲜) | 蔬菜 |  |  |  |  |  | 0.5 |  |
+| 圣女果 | 蔬菜 |  |  |  |  |  | 1.8 |  |
+| 青椒/甜椒 | 蔬菜 |  |  |  |  |  | 1.4 |  |
+| 菊芋(洋姜) | 蔬菜 |  |  |  |  |  | 4.3 |  |
+| 冬瓜 | 蔬菜 |  |  |  |  |  | 0.7 |  |
+| 丝瓜 | 蔬菜 |  |  |  |  |  | 0.6 |  |
+| 茭白 | 蔬菜 |  |  |  |  |  | 1.9 |  |
+| 莴笋 | 蔬菜 |  |  |  |  |  | 0.6 |  |
+| 蒜苔 | 蔬菜 |  |  |  |  |  | 2.5 |  |
+| 平菇 | 蔬菜 |  |  |  |  |  | 2.3 |  |
+| 金针菇 | 蔬菜 |  |  |  |  |  | 2.7 |  |
+| 木耳(水发) | 蔬菜 |  |  |  |  |  | 2.6 |  |
+| 海带 | 蔬菜 |  |  |  |  |  | 3.0 |  |
+| 紫菜 | 蔬菜 |  |  |  |  |  | 21.6 |  |
+| 南瓜尖/红薯叶 | 蔬菜 |  |  |  |  |  | 2.0 |  |
+| 树莓 | 水果 |  |  |  |  |  | 6.5 |  |
+| 橙子 | 水果 |  |  |  |  |  | 2.4 |  |
+| 柚子 | 水果 |  |  |  |  |  | 0.4 |  |
+| 甜瓜/香瓜 | 水果 |  |  |  |  |  | 0.4 |  |
+| 木瓜 | 水果 |  |  |  |  |  | 0.8 |  |
+| 火龙果 | 水果 |  |  |  |  |  | 1.6 |  |
+| 山竹 | 水果 |  |  |  |  |  | 1.5 |  |
+| 椰子(椰肉) | 水果 |  |  |  |  |  | 4.7 |  |
+| 牛油果 | 水果 |  |  |  |  |  | 6.7 |  |
+| 番石榴(芭乐) | 水果 |  |  |  |  |  | 5.9 |  |
+| 干枣/红枣 | 水果 |  |  |  |  |  | 6.2 |  |
+| 枇杷 | 水果 |  |  |  |  |  | 0.8 |  |
+| 杨梅 | 水果 |  |  |  |  |  | 1.0 |  |
+| 百香果 | 水果 |  |  |  |  |  | 10.4 |  |
+| 猪肉(瘦) | 畜禽肉蛋 |  |  |  |  |  | 0 |  |
+| 牛肉(瘦) | 畜禽肉蛋 |  |  |  |  |  | 0 |  |
+| 羊肉(瘦) | 畜禽肉蛋 |  |  |  |  |  | 0 |  |
+| 鸭肉 | 畜禽肉蛋 |  |  |  |  |  | 0 |  |
+| 鸭蛋 | 畜禽肉蛋 |  |  |  |  |  | 0 |  |
+| 牛肉干(原味) | 畜禽肉蛋 |  |  |  |  |  | 0 |  |
+| 带鱼 | 水产品 |  |  |  |  |  | 0 |  |
+| 黄花鱼 | 水产品 |  |  |  |  |  | 0 |  |
+| 鲫鱼 | 水产品 |  |  |  |  |  | 0 |  |
+| 海带/裙带菜 | 水产品 |  |  |  |  |  | 3.0 |  |
+| 纯牛奶(全脂) | 乳制品及发酵 |  |  |  |  |  | 0 |  |
+| 无糖酸奶 | 乳制品及发酵 |  |  |  |  |  | 0 |  |
+| 调味/风味酸奶 | 乳制品及发酵 |  |  |  |  |  | 0 |  |
+| 开菲尔(发酵乳) | 乳制品及发酵 |  |  |  |  |  | 0 |  |
+| 奶粉(婴幼儿配方) | 乳制品及发酵 |  |  |  |  |  | 0 |  |
+| 无糖泡菜 | 乳制品及发酵 |  |  |  |  |  | 2.0 |  |
+| 味噌(汤) | 乳制品及发酵 |  |  |  |  |  | 2.5 |  |
+| 豆豉 | 乳制品及发酵 |  |  |  |  |  | 5.0 |  |
+| 康普茶(无糖) | 乳制品及发酵 |  |  |  |  |  | 0 |  |
+| 巴旦木(美国大杏仁) | 坚果种子 |  |  |  |  |  | 12.0 |  |
+| 南瓜子 | 坚果种子 |  |  |  |  |  | 6.0 |  |
+| 奇亚籽 | 坚果种子 |  |  |  |  |  | 34.0 |  |
+| 亚麻籽(熟) | 坚果种子 |  |  |  |  |  | 27.0 |  |
+| 板栗(鲜) | 坚果种子 |  |  |  |  |  | 1.7 |  |
+| 无糖绿茶 | 饮品零食调味 |  |  |  |  |  | 0 |  |
+| 黑咖啡(无糖) | 饮品零食调味 |  |  |  |  |  | 0 |  |
+| 纯可可粉/黑巧(70%+) | 饮品零食调味 |  |  |  |  |  | 11.0 |  |
+| 蜂蜜 | 饮品零食调味 |  |  |  |  |  | 0 |  |
+| 可乐等含糖汽水 | 饮品零食调味 |  |  |  |  |  | 0 |  |
+| 纯果汁(橙汁) | 饮品零食调味 |  |  |  |  |  | 0.2 |  |
+| 白粥 | 饮品零食调味 |  |  |  |  |  | 0.3 |  |
+| 藕粉 | 饮品零食调味 |  |  |  |  |  | 0.1 |  |
+| 麦芽糖/饴糖 | 饮品零食调味 |  |  |  |  |  | 0 |  |
 
 ## 二、菌-疾病关联知识库
 

Some files were not shown because too many files changed in this diff