Преглед изворни кода

feat(mini-program font): wire 15 pages to fontScale + calc conversions

Root binding :style="{ '--font-scale': fontScale }" on first <view|scroll-view class="...">
Add import fontScaleMixin + mixins: [fontScaleMixin] to each page script block
Convert font-size: XXrpx to calc(XXrpx * var(--font-scale, 1)) in <style> blocks
Excluded: btn/price/tag/badge/icon/arrow/score/stat/count/kcal/chip/nav/label

Pages:
  mind-detail/index, shop/checkout/checkout, home-pages/parent-index,
  health-main/index, index-home/index, wealth/index, growth-main/index,
  health/challenge-manage, wisdom-detail/index, profile-main/profile,
  family/self-check-result, body-detail/index, profile-extra/family-members,
  shop/cart/cart, wealth-sub/insurance-planning

Bug fix: [regex]::Replace(..., 1) in PS patch script was silently bound to
RegexOptions.IgnoreCase, replacing all 54 matches instead of just the root
occurrence. Fixed by using Match + Result + Substring concatenation.

Audit: duplicate-api-calls 0 errors / mp-antipatterns 0 errors
E2E Test Bot пре 4 дана
родитељ
комит
7e1b205150

+ 34 - 32
cfc-frontend/pages/body-detail/index.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="body-container">
+  <view class="body-container" :style="{ '--font-scale': fontScale }">
     <!-- 登录浮层(全局组件,页面内弹出底部登录) -->
     <!-- 登录浮层(全局组件,页面内弹出底部登录) -->
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <!-- Tabbar 切换过渡页 -->
     <!-- Tabbar 切换过渡页 -->
@@ -267,8 +267,10 @@ import {
   getLatestIndicators,
   getLatestIndicators,
   kickFamilyMemberById,
   kickFamilyMemberById,
 } from '../../utils/api.js'
 } from '../../utils/api.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   components: { TabTransition, PageBanner, FamilyEnergyBar, RadarChart, FloatingAvatar, DimensionMemberTabs, DimensionIntroCard, DimensionVisitorCard, DimensionPageSkeleton },
   components: { TabTransition, PageBanner, FamilyEnergyBar, RadarChart, FloatingAvatar, DimensionMemberTabs, DimensionIntroCard, DimensionVisitorCard, DimensionPageSkeleton },
   data() {
   data() {
     return {
     return {
@@ -749,7 +751,7 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .overview-title {
 .overview-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $dim-body;
   color: $dim-body;
   margin-bottom: 4rpx;
   margin-bottom: 4rpx;
@@ -757,7 +759,7 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .overview-sub {
 .overview-sub {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
 }
 }
 
 
@@ -802,20 +804,20 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .overview-name {
 .overview-name {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   display: block;
   display: block;
   margin-bottom: 4rpx;
   margin-bottom: 4rpx;
 }
 }
 
 
 .overview-value {
 .overview-value {
-  font-size: 40rpx;
+  font-size: calc(40rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $dim-body;
   color: $dim-body;
 }
 }
 
 
 .overview-placeholder {
 .overview-placeholder {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-border;
   color: $app-border;
 }
 }
 
 
@@ -836,7 +838,7 @@ $c-tint-warm: #FFF5EE;
 .trend-stable { color: $app-text-muted; }
 .trend-stable { color: $app-text-muted; }
 
 
 .trend-desc {
 .trend-desc {
-  font-size: 18rpx;
+  font-size: calc(18rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   overflow: hidden;
   overflow: hidden;
   text-overflow: ellipsis;
   text-overflow: ellipsis;
@@ -925,14 +927,14 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .section-title {
 .section-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $app-text;
   color: $app-text;
 }
 }
 
 
 .section-more {
 .section-more {
   position: relative;
   position: relative;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $dim-body;
   color: $dim-body;
   font-weight: 500;
   font-weight: 500;
   margin-left: auto;
   margin-left: auto;
@@ -989,12 +991,12 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .indicator-name {
 .indicator-name {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
 }
 }
 
 
 .indicator-unit {
 .indicator-unit {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
 }
 }
 
 
@@ -1013,18 +1015,18 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .indicator-value {
 .indicator-value {
-  font-size: 40rpx;
+  font-size: calc(40rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $dim-body;
   color: $dim-body;
 }
 }
 
 
 .indicator-placeholder {
 .indicator-placeholder {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-border;
   color: $app-border;
 }
 }
 
 
 .indicator-footer {
 .indicator-footer {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   text-align: right;
   text-align: right;
 }
 }
@@ -1046,7 +1048,7 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .gut-summary-text {
 .gut-summary-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-body;
   color: $dim-body;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -1060,7 +1062,7 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .gut-group-title {
 .gut-group-title {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
   display: block;
   display: block;
@@ -1078,7 +1080,7 @@ $c-tint-warm: #FFF5EE;
   padding: 10rpx 16rpx;
   padding: 10rpx 16rpx;
   background-color: $app-surface-subtle;
   background-color: $app-surface-subtle;
   border-radius: 16rpx;
   border-radius: 16rpx;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
 }
 }
 
 
 .gut-item-name {
 .gut-item-name {
@@ -1096,13 +1098,13 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .gut-item-value {
 .gut-item-value {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   font-weight: 500;
   font-weight: 500;
 }
 }
 
 
 .gut-item-status {
 .gut-item-status {
-  font-size: 18rpx;
+  font-size: calc(18rpx * var(--font-scale, 1));
   font-weight: 500;
   font-weight: 500;
 }
 }
 
 
@@ -1114,7 +1116,7 @@ $c-tint-warm: #FFF5EE;
   padding: 40rpx 24rpx;
   padding: 40rpx 24rpx;
   text-align: center;
   text-align: center;
   color: $app-text-muted;
   color: $app-text-muted;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
 }
 }
 
 
 .gut-upload-link {
 .gut-upload-link {
@@ -1149,7 +1151,7 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .risk-name {
 .risk-name {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
 }
 }
 
 
@@ -1158,13 +1160,13 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .risk-value {
 .risk-value {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $status-danger;
   color: $status-danger;
 }
 }
 
 
 .risk-level {
 .risk-level {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   margin-top: 2rpx;
   margin-top: 2rpx;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -1183,7 +1185,7 @@ $c-tint-warm: #FFF5EE;
   border: 2rpx solid rgba(255, 140, 66, 0.1);
   border: 2rpx solid rgba(255, 140, 66, 0.1);
 }
 }
 .portrait-tier {
 .portrait-tier {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-body;
   color: $dim-body;
   font-weight: bold;
   font-weight: bold;
   margin-left: 16rpx;
   margin-left: 16rpx;
@@ -1192,7 +1194,7 @@ $c-tint-warm: #FFF5EE;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .portrait-desc {
 .portrait-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   line-height: 1.6;
   line-height: 1.6;
   display: block;
   display: block;
@@ -1219,12 +1221,12 @@ $c-tint-warm: #FFF5EE;
   font-size: 22rpx;
   font-size: 22rpx;
 }
 }
 .portrait-dim-name {
 .portrait-dim-name {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   flex: 1;
   flex: 1;
 }
 }
 .portrait-dim-score {
 .portrait-dim-score {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $dim-body;
   color: $dim-body;
   margin-right: 16rpx;
   margin-right: 16rpx;
@@ -1242,7 +1244,7 @@ $c-tint-warm: #FFF5EE;
   transition: width 0.3s ease;
   transition: width 0.3s ease;
 }
 }
 .portrait-dim-desc {
 .portrait-dim-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   display: block;
   display: block;
 }
 }
@@ -1253,7 +1255,7 @@ $c-tint-warm: #FFF5EE;
   border-left: 8rpx solid $dim-body;
   border-left: 8rpx solid $dim-body;
 }
 }
 .portrait-tip-text {
 .portrait-tip-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
@@ -1273,7 +1275,7 @@ $c-tint-warm: #FFF5EE;
 }
 }
 
 
 .guidance-text {
 .guidance-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $dim-body;
   color: $dim-body;
 }
 }
 
 
@@ -1285,7 +1287,7 @@ $c-tint-warm: #FFF5EE;
   padding: 20rpx 24rpx;
   padding: 20rpx 24rpx;
 }
 }
 .brand-strap-text {
 .brand-strap-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-body;
   color: $dim-body;
   font-weight: 600;
   font-weight: 600;
 }
 }
@@ -1294,4 +1296,4 @@ $c-tint-warm: #FFF5EE;
   flex: 1;
   flex: 1;
   height: 120rpx;
   height: 120rpx;
 }
 }
-</style>
+</style>

+ 43 - 41
cfc-frontend/pages/family/self-check-result.vue

@@ -1,5 +1,5 @@
-<template>
-  <view class="scr-page">
+<template>
+  <view class="scr-page" :style="{ '--font-scale': fontScale }">
     <!-- Loading -->
     <!-- Loading -->
     <view class="scr-loading" v-if="loading">
     <view class="scr-loading" v-if="loading">
       <text class="scr-loading-text">加载中...</text>
       <text class="scr-loading-text">加载中...</text>
@@ -154,8 +154,10 @@
 import { getSelfCheckLatest, getSelfCheckHistory, generateSelfCheckPlan } from '@/utils/api'
 import { getSelfCheckLatest, getSelfCheckHistory, generateSelfCheckPlan } from '@/utils/api'
 import { microActionToday, microActionComplete } from '@/utils/api'
 import { microActionToday, microActionComplete } from '@/utils/api'
 import { parseDate } from '@/utils/format.js'
 import { parseDate } from '@/utils/format.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   data() {
   data() {
     return {
     return {
       loading: true,
       loading: true,
@@ -337,7 +339,7 @@ export default {
   height: 60vh;
   height: 60vh;
 }
 }
 .scr-loading-text {
 .scr-loading-text {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 
 
@@ -355,7 +357,7 @@ export default {
   align-items: center;
   align-items: center;
 }
 }
 .scr-hero-title {
 .scr-hero-title {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: rgba(255, 255, 255, 0.9);
   color: rgba(255, 255, 255, 0.9);
 }
 }
 .scr-hero-score-row {
 .scr-hero-score-row {
@@ -364,12 +366,12 @@ export default {
   margin-top: 10rpx;
   margin-top: 10rpx;
 }
 }
 .scr-hero-score {
 .scr-hero-score {
-  font-size: 88rpx;
+  font-size: calc(88rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $app-surface;
   color: $app-surface;
 }
 }
 .scr-hero-total {
 .scr-hero-total {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   color: rgba(255, 255, 255, 0.7);
   color: rgba(255, 255, 255, 0.7);
   margin-left: 6rpx;
   margin-left: 6rpx;
 }
 }
@@ -377,7 +379,7 @@ export default {
   margin-top: 14rpx;
   margin-top: 14rpx;
   padding: 8rpx 28rpx;
   padding: 8rpx 28rpx;
   border-radius: 24rpx;
   border-radius: 24rpx;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   background: rgba(255, 255, 255, 0.92);
   background: rgba(255, 255, 255, 0.92);
 }
 }
@@ -387,7 +389,7 @@ export default {
 .scr-hero-date {
 .scr-hero-date {
   display: block;
   display: block;
   text-align: center;
   text-align: center;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: rgba(255, 255, 255, 0.8);
   color: rgba(255, 255, 255, 0.8);
   margin-top: 16rpx;
   margin-top: 16rpx;
 }
 }
@@ -407,12 +409,12 @@ export default {
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .scr-card-title-text {
 .scr-card-title-text {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .scr-card-sub {
 .scr-card-sub {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 
 
@@ -443,12 +445,12 @@ export default {
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
 .scr-dim-name {
 .scr-dim-name {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .scr-dim-element {
 .scr-dim-element {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-left: 10rpx;
   margin-left: 10rpx;
 }
 }
@@ -457,11 +459,11 @@ export default {
   align-items: baseline;
   align-items: baseline;
 }
 }
 .scr-dim-score {
 .scr-dim-score {
-  font-size: 40rpx;
+  font-size: calc(40rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
 }
 }
 .scr-dim-score-max {
 .scr-dim-score-max {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-ghost-light;
   color: $facade-text-ghost-light;
 }
 }
 .scr-dim-bar {
 .scr-dim-bar {
@@ -482,7 +484,7 @@ export default {
   margin-top: 12rpx;
   margin-top: 12rpx;
 }
 }
 .scr-dim-level {
 .scr-dim-level {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   padding: 4rpx 16rpx;
   padding: 4rpx 16rpx;
   border-radius: 16rpx;
   border-radius: 16rpx;
   margin-right: 14rpx;
   margin-right: 14rpx;
@@ -504,12 +506,12 @@ export default {
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .scr-guide-title {
 .scr-guide-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $brand-primary;
   color: $brand-primary;
 }
 }
 .scr-guide-desc {
 .scr-guide-desc {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-faint;
   color: $facade-text-faint;
   line-height: 1.6;
   line-height: 1.6;
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
@@ -520,13 +522,13 @@ export default {
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .scr-guide-total-label {
 .scr-guide-total-label {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
 .scr-guide-total-text {
 .scr-guide-total-text {
-  font-size: 48rpx;
+  font-size: calc(48rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $brand-primary;
   color: $brand-primary;
 }
 }
@@ -551,7 +553,7 @@ export default {
 .lg-attention { background: $mat-amber-strong; }
 .lg-attention { background: $mat-amber-strong; }
 .lg-tense { background: $status-danger-strong-2; }
 .lg-tense { background: $status-danger-strong-2; }
 .scr-guide-legend-text {
 .scr-guide-legend-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-deep;
   color: $facade-text-deep;
   margin-left: 10rpx;
   margin-left: 10rpx;
 }
 }
@@ -559,7 +561,7 @@ export default {
   margin-top: 16rpx;
   margin-top: 16rpx;
 }
 }
 .scr-guide-steps-title {
 .scr-guide-steps-title {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
   display: block;
   display: block;
@@ -570,13 +572,13 @@ export default {
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
 }
 }
 .scr-guide-step-num {
 .scr-guide-step-num {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   margin-right: 12rpx;
   margin-right: 12rpx;
   min-width: 20rpx;
   min-width: 20rpx;
 }
 }
 .scr-guide-step-text {
 .scr-guide-step-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   flex: 1;
   flex: 1;
 }
 }
@@ -586,14 +588,14 @@ export default {
 
 
 .scr-dim-summary {
 .scr-dim-summary {
   flex: 1;
   flex: 1;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-faint;
   color: $facade-text-faint;
   line-height: 1.4;
   line-height: 1.4;
 }
 }
 
 
 /* 寻源建议 */
 /* 寻源建议 */
 .scr-advice-intro {
 .scr-advice-intro {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
   line-height: 1.6;
   line-height: 1.6;
   background: $uni-primary-pale;
   background: $uni-primary-pale;
@@ -623,17 +625,17 @@ export default {
   border-radius: 20rpx;
   border-radius: 20rpx;
 }
 }
 .scr-advice-dim-name {
 .scr-advice-dim-name {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $app-surface;
   color: $app-surface;
   margin-right: 8rpx;
   margin-right: 8rpx;
 }
 }
 .scr-advice-dim-elem {
 .scr-advice-dim-elem {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: rgba(255, 255, 255, 0.9);
   color: rgba(255, 255, 255, 0.9);
 }
 }
 .scr-advice-dim-score {
 .scr-advice-dim-score {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $status-danger-strong-2;
   color: $status-danger-strong-2;
 }
 }
@@ -656,7 +658,7 @@ export default {
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .scr-flow-label {
 .scr-flow-label {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
@@ -668,7 +670,7 @@ export default {
 }
 }
 .scr-flow-action {
 .scr-flow-action {
   flex: 1;
   flex: 1;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
@@ -682,7 +684,7 @@ export default {
 }
 }
 .scr-advice-action-label {
 .scr-advice-action-label {
   flex-shrink: 0;
   flex-shrink: 0;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $brand-primary;
   color: $brand-primary;
   margin-right: 12rpx;
   margin-right: 12rpx;
@@ -690,7 +692,7 @@ export default {
 }
 }
 .scr-advice-action-text {
 .scr-advice-action-text {
   flex: 1;
   flex: 1;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
@@ -716,7 +718,7 @@ export default {
 .scr-micro-done {
 .scr-micro-done {
   flex: 1;
   flex: 1;
   text-align: center;
   text-align: center;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $status-success;
   color: $status-success;
   background: #E8F8F1;
   background: #E8F8F1;
   border-radius: 12rpx;
   border-radius: 12rpx;
@@ -735,7 +737,7 @@ export default {
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .scr-all-healthy-text {
 .scr-all-healthy-text {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
 }
 }
 
 
@@ -776,7 +778,7 @@ export default {
 }
 }
 .scr-advice-interpretation {
 .scr-advice-interpretation {
   display: block;
   display: block;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-deep;
   color: $facade-text-deep;
   line-height: 1.6;
   line-height: 1.6;
   margin: 16rpx 0;
   margin: 16rpx 0;
@@ -787,12 +789,12 @@ export default {
   margin-top: 12rpx;
   margin-top: 12rpx;
 }
 }
 .scr-advice-action-label {
 .scr-advice-action-label {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $brand-primary;
   color: $brand-primary;
 }
 }
 .scr-advice-action {
 .scr-advice-action {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-deep;
   color: $facade-text-deep;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
@@ -804,14 +806,14 @@ export default {
 }
 }
 .scr-family-insight-label {
 .scr-family-insight-label {
   display: block;
   display: block;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $brand-primary;
   color: $brand-primary;
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
 }
 }
 .scr-family-insight-text {
 .scr-family-insight-text {
   display: block;
   display: block;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-deep;
   color: $facade-text-deep;
   line-height: 1.6;
   line-height: 1.6;
 }
 }
@@ -823,7 +825,7 @@ export default {
   text-align: center;
   text-align: center;
 }
 }
 .scr-fallback text {
 .scr-fallback text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
-</style>
+</style>

+ 43 - 41
cfc-frontend/pages/growth-main/index.vue

@@ -1,5 +1,5 @@
-<template>
-  <view class="container">
+<template>
+  <view class="container" :style="{ '--font-scale': fontScale }">
     <login-sheet ref="loginSheet" @success="onLoginSuccess" />
     <login-sheet ref="loginSheet" @success="onLoginSuccess" />
     <view v-if="!isLoggedIn">
     <view v-if="!isLoggedIn">
       <!-- Hero 品牌区 -->
       <!-- Hero 品牌区 -->
@@ -289,7 +289,9 @@ import DimensionProducts from '../../components/DimensionProducts.vue'
 import ArticleBookshelf from '../../components/ArticleBookshelf.vue'
 import ArticleBookshelf from '../../components/ArticleBookshelf.vue'
 import { healthCheckinList, getHealthMealList, getFoodCautionList, getGrowthRecommendations, getExerciseRecords, getSleepRecords, getEmotionCheckinList, getCheckinList, getTodayTasks, reportAppEnter } from '../../utils/api.js'
 import { healthCheckinList, getHealthMealList, getFoodCautionList, getGrowthRecommendations, getExerciseRecords, getSleepRecords, getEmotionCheckinList, getCheckinList, getTodayTasks, reportAppEnter } from '../../utils/api.js'
 import { parseDate } from '../../utils/format.js'
 import { parseDate } from '../../utils/format.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 export default {
 export default {
+  mixins: [fontScaleMixin],
   components: { LoginGuideCard, DimensionActivities, DimensionProducts, ArticleBookshelf },
   components: { LoginGuideCard, DimensionActivities, DimensionProducts, ArticleBookshelf },
   data() { return { memberId: '', todayDate: '', hasIncomplete: false, incompleteCount: 0, progressItems: [], recentTasks: [], streakDays: 0, activeChallenges: 0, completeness: 0, cautionCount: 0,
   data() { return { memberId: '', todayDate: '', hasIncomplete: false, incompleteCount: 0, progressItems: [], recentTasks: [], streakDays: 0, activeChallenges: 0, completeness: 0, cautionCount: 0,
       healthArticles: [],
       healthArticles: [],
@@ -529,7 +531,7 @@ $c-danger-ink:       $status-danger-deep;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .card-head-title {
 .card-head-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
   flex: 1;
   flex: 1;
@@ -558,18 +560,18 @@ $c-danger-ink:       $status-danger-deep;
   display: flex; flex-direction: column; gap: 12rpx;
   display: flex; flex-direction: column; gap: 12rpx;
 }
 }
 .hero-eyebrow {
 .hero-eyebrow {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   opacity: 0.85;
   opacity: 0.85;
   letter-spacing: 2rpx;
   letter-spacing: 2rpx;
   text-transform: uppercase;
   text-transform: uppercase;
 }
 }
 .hero-title {
 .hero-title {
-  font-size: 44rpx;
+  font-size: calc(44rpx * var(--font-scale, 1));
   font-weight: 800;
   font-weight: 800;
   line-height: 1.2;
   line-height: 1.2;
 }
 }
 .hero-desc {
 .hero-desc {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   opacity: 0.92;
   opacity: 0.92;
   line-height: 1.7;
   line-height: 1.7;
 }
 }
@@ -577,14 +579,14 @@ $c-danger-ink:       $status-danger-deep;
 .case-card { margin-bottom: 20rpx; }
 .case-card { margin-bottom: 20rpx; }
 .case-body { padding: 4rpx 0; }
 .case-body { padding: 4rpx 0; }
 .case-name {
 .case-name {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
   display: block;
   display: block;
   margin-bottom: 4rpx;
   margin-bottom: 4rpx;
 }
 }
 .case-change {
 .case-change {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
   display: block;
   display: block;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
@@ -605,24 +607,24 @@ $c-danger-ink:       $status-danger-deep;
   border: 1rpx solid rgba($dim-action, 0.12);
   border: 1rpx solid rgba($dim-action, 0.12);
 }
 }
 .metric-value {
 .metric-value {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
 }
 }
 .metric-value.up { color: $dim-action; }
 .metric-value.up { color: $dim-action; }
 .metric-label {
 .metric-label {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-top: 4rpx;
   margin-top: 4rpx;
 }
 }
 .case-note {
 .case-note {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-faint;
   color: $facade-text-faint;
   display: block;
   display: block;
 }
 }
 
 
 .section-title-row { margin: 28rpx 24rpx 12rpx; }
 .section-title-row { margin: 28rpx 24rpx 12rpx; }
 .section-title-text {
 .section-title-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-muted;
   color: $facade-text-muted;
   letter-spacing: 1rpx;
   letter-spacing: 1rpx;
@@ -650,14 +652,14 @@ $c-danger-ink:       $status-danger-deep;
 .feat-card:active { opacity: 0.88; transform: scale(0.98); }
 .feat-card:active { opacity: 0.88; transform: scale(0.98); }
 .feat-icon { font-size: 48rpx; display: block; margin-bottom: 10rpx; }
 .feat-icon { font-size: 48rpx; display: block; margin-bottom: 10rpx; }
 .feat-title {
 .feat-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
   display: block;
   display: block;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .feat-desc {
 .feat-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   line-height: 1.5;
   line-height: 1.5;
   display: block;
   display: block;
@@ -668,7 +670,7 @@ $c-danger-ink:       $status-danger-deep;
   background: $app-surface;
   background: $app-surface;
 }
 }
 .wuxing-desc {
 .wuxing-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   text-align: center;
   text-align: center;
   display: block;
   display: block;
@@ -677,7 +679,7 @@ $c-danger-ink:       $status-danger-deep;
 .wuxing-relations { margin-top: 8rpx; }
 .wuxing-relations { margin-top: 8rpx; }
 .rel-group { margin-bottom: 18rpx; }
 .rel-group { margin-bottom: 18rpx; }
 .rel-title {
 .rel-title {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
@@ -691,17 +693,17 @@ $c-danger-ink:       $status-danger-deep;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .rel-item {
 .rel-item {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   padding: 4rpx 10rpx;
   padding: 4rpx 10rpx;
   border-radius: 8rpx;
   border-radius: 8rpx;
   background: $facade-fill-cool;
   background: $facade-fill-cool;
   color: $facade-text-deep;
   color: $facade-text-deep;
 }
 }
 .rel-arrow { font-size: 20rpx; color: $dim-action; font-weight: bold; }
 .rel-arrow { font-size: 20rpx; color: $dim-action; font-weight: bold; }
-.rel-op { font-size: 20rpx; color: $c-danger-ink; font-weight: bold; }
-.rel-dot { font-size: 20rpx; color: $facade-text-ghost; }
+.rel-op { font-size: calc(20rpx * var(--font-scale, 1)); color: $c-danger-ink; font-weight: bold; }
+.rel-dot { font-size: calc(20rpx * var(--font-scale, 1)); color: $facade-text-ghost; }
 .rel-hint {
 .rel-hint {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   line-height: 1.5;
   line-height: 1.5;
   display: block;
   display: block;
@@ -726,7 +728,7 @@ $c-danger-ink:       $status-danger-deep;
 .wc-icon { font-size: 36rpx; margin-right: 16rpx; flex-shrink: 0; }
 .wc-icon { font-size: 36rpx; margin-right: 16rpx; flex-shrink: 0; }
 .wc-info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
 .wc-info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
 .wc-name {
 .wc-name {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   display: block;
   display: block;
   white-space: nowrap;
   white-space: nowrap;
@@ -734,7 +736,7 @@ $c-danger-ink:       $status-danger-deep;
   text-overflow: ellipsis;
   text-overflow: ellipsis;
 }
 }
 .wc-text {
 .wc-text {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   display: block;
   display: block;
   margin-top: 4rpx;
   margin-top: 4rpx;
@@ -765,7 +767,7 @@ $c-danger-ink:       $status-danger-deep;
   justify-content: space-between;
   justify-content: space-between;
   box-shadow: 0 2rpx 12rpx rgba(249,115,22,0.08);
   box-shadow: 0 2rpx 12rpx rgba(249,115,22,0.08);
 }
 }
-.reminder-text { font-size: 24rpx; color: $c-danger-ink; font-weight: 500; }
+.reminder-text { font-size: calc(24rpx * var(--font-scale, 1)); color: $c-danger-ink; font-weight: 500; }
 .reminder-close { font-size: 28rpx; color: $facade-text-muted; }
 .reminder-close { font-size: 28rpx; color: $facade-text-muted; }
 
 
 // ---- 里程碑 ----
 // ---- 里程碑 ----
@@ -783,12 +785,12 @@ $c-danger-ink:       $status-danger-deep;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .milestone-title {
 .milestone-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .milestone-sub {
 .milestone-sub {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .milestone-grid {
 .milestone-grid {
@@ -812,14 +814,14 @@ $c-danger-ink:       $status-danger-deep;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .milestone-tile-value {
 .milestone-tile-value {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 800;
   font-weight: 800;
   color: $c-growth-hero-from;
   color: $c-growth-hero-from;
   line-height: 1;
   line-height: 1;
   margin-bottom: 4rpx;
   margin-bottom: 4rpx;
 }
 }
 .milestone-tile-label {
 .milestone-tile-label {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 
 
@@ -837,12 +839,12 @@ $c-danger-ink:       $status-danger-deep;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .progress-title {
 .progress-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .progress-footer-text {
 .progress-footer-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -888,14 +890,14 @@ $c-danger-ink:       $status-danger-deep;
 .color-checkin { border-color: rgba($dim-wealth, 0.18); background: rgba($dim-wealth, 0.04); }
 .color-checkin { border-color: rgba($dim-wealth, 0.18); background: rgba($dim-wealth, 0.04); }
 .color-checkin .progress-tile-icon-wrap { background: $dim-wealth-tint; }
 .color-checkin .progress-tile-icon-wrap { background: $dim-wealth-tint; }
 .progress-tile-label {
 .progress-tile-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   font-weight: 500;
   font-weight: 500;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
   text-align: center;
   text-align: center;
 }
 }
 .progress-tile-status {
 .progress-tile-status {
-  font-size: 18rpx;
+  font-size: calc(18rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   padding: 4rpx 12rpx;
   padding: 4rpx 12rpx;
   border-radius: 999rpx;
   border-radius: 999rpx;
@@ -952,13 +954,13 @@ $c-danger-ink:       $status-danger-deep;
 .action-icon { font-size: 36rpx; }
 .action-icon { font-size: 36rpx; }
 .action-info { flex: 1; min-width: 0; }
 .action-info { flex: 1; min-width: 0; }
 .action-title {
 .action-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
   display: block;
   display: block;
 }
 }
 .action-desc {
 .action-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-top: 4rpx;
   margin-top: 4rpx;
   display: block;
   display: block;
@@ -979,12 +981,12 @@ $c-danger-ink:       $status-danger-deep;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .task-preview-title {
 .task-preview-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .task-preview-more {
 .task-preview-more {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
 }
 }
 .task-preview-list { display: flex; flex-direction: column; }
 .task-preview-list { display: flex; flex-direction: column; }
@@ -997,7 +999,7 @@ $c-danger-ink:       $status-danger-deep;
 .task-preview-item:last-child { border-bottom: none; }
 .task-preview-item:last-child { border-bottom: none; }
 .task-preview-left { flex: 1; min-width: 0; }
 .task-preview-left { flex: 1; min-width: 0; }
 .task-preview-name {
 .task-preview-name {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   display: block;
   display: block;
   white-space: nowrap;
   white-space: nowrap;
@@ -1011,11 +1013,11 @@ $c-danger-ink:       $status-danger-deep;
   margin-top: 6rpx;
   margin-top: 6rpx;
 }
 }
 .task-preview-points {
 .task-preview-points {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 700;
   font-weight: 700;
 }
 }
-.task-preview-deadline { font-size: 20rpx; color: $facade-text-muted; }
+.task-preview-deadline { font-size: calc(20rpx * var(--font-scale, 1)); color: $facade-text-muted; }
 .task-preview-arrow {
 .task-preview-arrow {
   font-size: 28rpx;
   font-size: 28rpx;
   color: $facade-text-ghost;
   color: $facade-text-ghost;
@@ -1030,8 +1032,8 @@ $c-danger-ink:       $status-danger-deep;
   align-items: center;
   align-items: center;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
-.section-title { font-size: 28rpx; font-weight: 600; color: $facade-text-strong; }
-.section-more { font-size: 24rpx; color: $brand-primary; }
+.section-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: 600; color: $facade-text-strong; }
+.section-more { font-size: calc(24rpx * var(--font-scale, 1)); color: $brand-primary; }
 
 
 .bottom-spacer { height: 40rpx; }
 .bottom-spacer { height: 40rpx; }
-</style>
+</style>

+ 47 - 45
cfc-frontend/pages/health-main/index.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="container">
+  <view class="container" :style="{ '--font-scale': fontScale }">
     <!-- 通用登录浮层 -->
     <!-- 通用登录浮层 -->
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <block v-if="!isLoggedIn">
     <block v-if="!isLoggedIn">
@@ -242,8 +242,10 @@ import RadarChart from '../../components/RadarChart.vue'
 import ArticleBookshelf from '../../components/ArticleBookshelf.vue'
 import ArticleBookshelf from '../../components/ArticleBookshelf.vue'
 import ReportUploadCard from '../../components/report-upload-card.vue'
 import ReportUploadCard from '../../components/report-upload-card.vue'
 import { parseDate } from '../../utils/format.js'
 import { parseDate } from '../../utils/format.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   components: { LoginGuideCard, RadarChart, ArticleBookshelf, ReportUploadCard },
   components: { LoginGuideCard, RadarChart, ArticleBookshelf, ReportUploadCard },
   data() {
   data() {
     return {
     return {
@@ -663,41 +665,41 @@ export default {
 .tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 12rpx 0; position: relative; border-radius: 12rpx; }
 .tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 12rpx 0; position: relative; border-radius: 12rpx; }
 .tab-item.active { background: $facade-brand-tint; }
 .tab-item.active { background: $facade-brand-tint; }
 .tab-icon { font-size: 32rpx; margin-bottom: 4rpx; }
 .tab-icon { font-size: 32rpx; margin-bottom: 4rpx; }
-.tab-label { font-size: 26rpx; color: $facade-text-body; font-weight: 500; }
+.tab-label { font-size: calc(26rpx * var(--font-scale, 1)); color: $facade-text-body; font-weight: 500; }
 .tab-item.active .tab-label { color: $facade-text-strong; font-weight: bold; }
 .tab-item.active .tab-label { color: $facade-text-strong; font-weight: bold; }
 .tab-underline { width: 40rpx; height: 4rpx; border-radius: 2rpx; margin-top: 6rpx; }
 .tab-underline { width: 40rpx; height: 4rpx; border-radius: 2rpx; margin-top: 6rpx; }
 .section-chart { position: relative; margin: 0 24rpx 16rpx; }
 .section-chart { position: relative; margin: 0 24rpx 16rpx; }
 .chart-empty { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; z-index: 3; background: rgba($app-surface, 0.85); border-radius: 12rpx; padding: 20rpx 30rpx; }
 .chart-empty { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; z-index: 3; background: rgba($app-surface, 0.85); border-radius: 12rpx; padding: 20rpx 30rpx; }
-.chart-empty .empty-text { font-size: 28rpx; color: $facade-text-strong; font-weight: 500; display: block; }
-.chart-empty .empty-sub { font-size: 22rpx; color: $facade-text-muted; display: block; margin-top: 4rpx; }
+.chart-empty .empty-text { font-size: calc(28rpx * var(--font-scale, 1)); color: $facade-text-strong; font-weight: 500; display: block; }
+.chart-empty .empty-sub { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; display: block; margin-top: 4rpx; }
 .section-dc-header { margin: 20rpx 24rpx 8rpx; }
 .section-dc-header { margin: 20rpx 24rpx 8rpx; }
 .dc-title-row { display: flex; align-items: center; }
 .dc-title-row { display: flex; align-items: center; }
 .dc-icon { font-size: 32rpx; margin-right: 8rpx; }
 .dc-icon { font-size: 32rpx; margin-right: 8rpx; }
-.dc-title { font-size: 32rpx; font-weight: bold; color: $facade-text-strong; }
+.dc-title { font-size: calc(32rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; }
 .section-data-collect { margin: 8rpx 24rpx; }
 .section-data-collect { margin: 8rpx 24rpx; }
 .data-card { display: flex; align-items: center; background: $app-surface; border-radius: 20rpx; padding: 24rpx; margin-bottom: 12rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .data-card { display: flex; align-items: center; background: $app-surface; border-radius: 20rpx; padding: 24rpx; margin-bottom: 12rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .data-card-icon { width: 88rpx; height: 88rpx; border-radius: 20rpx; display: flex; align-items: center; justify-content: center; margin-right: 20rpx; font-size: 40rpx; }
 .data-card-icon { width: 88rpx; height: 88rpx; border-radius: 20rpx; display: flex; align-items: center; justify-content: center; margin-right: 20rpx; font-size: 40rpx; }
 .data-card-info { flex: 1; }
 .data-card-info { flex: 1; }
-.data-card-title { font-size: 28rpx; font-weight: bold; color: $facade-text-strong; display: block; margin-bottom: 6rpx; }
-.data-card-desc { font-size: 22rpx; color: $facade-text-muted; }
+.data-card-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; display: block; margin-bottom: 6rpx; }
+.data-card-desc { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; }
 .data-card-arrow { font-size: 36rpx; color: $facade-text-ghost; }
 .data-card-arrow { font-size: 36rpx; color: $facade-text-ghost; }
 .data-card-assessment { flex-direction: column; align-items: stretch; padding: 24rpx; }
 .data-card-assessment { flex-direction: column; align-items: stretch; padding: 24rpx; }
 .data-card-head { display: flex; align-items: center; margin-bottom: 16rpx; }
 .data-card-head { display: flex; align-items: center; margin-bottom: 16rpx; }
-.data-card-subtitle { font-size: 22rpx; color: $facade-text-muted; margin-left: 12rpx; }
+.data-card-subtitle { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; margin-left: 12rpx; }
 .quiz-item { display: flex; align-items: center; padding: 16rpx 0; border-top: 1rpx solid $facade-fill; }
 .quiz-item { display: flex; align-items: center; padding: 16rpx 0; border-top: 1rpx solid $facade-fill; }
 .quiz-item:first-of-type { border-top: none; }
 .quiz-item:first-of-type { border-top: none; }
 .quiz-info { display: flex; align-items: center; flex: 1; }
 .quiz-info { display: flex; align-items: center; flex: 1; }
 .quiz-icon { font-size: 36rpx; margin-right: 16rpx; }
 .quiz-icon { font-size: 36rpx; margin-right: 16rpx; }
-.quiz-label { font-size: 28rpx; color: $facade-text-strong; }
+.quiz-label { font-size: calc(28rpx * var(--font-scale, 1)); color: $facade-text-strong; }
 .quiz-score { display: flex; align-items: baseline; margin-right: 16rpx; }
 .quiz-score { display: flex; align-items: baseline; margin-right: 16rpx; }
-.score-value { font-size: 36rpx; font-weight: bold; color: $brand-primary; }
-.score-unit { font-size: 22rpx; color: $facade-text-muted; margin-left: 4rpx; }
+.score-value { font-size: calc(36rpx * var(--font-scale, 1)); font-weight: bold; color: $brand-primary; }
+.score-unit { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; margin-left: 4rpx; }
 
 
 .quiz-btn { background: $brand-primary; color: $app-surface; font-size: 24rpx; border: none; border-radius: 20rpx; padding: 10rpx 30rpx; height: 56rpx; line-height: 36rpx; margin: 0; }
 .quiz-btn { background: $brand-primary; color: $app-surface; font-size: 24rpx; border: none; border-radius: 20rpx; padding: 10rpx 30rpx; height: 56rpx; line-height: 36rpx; margin: 0; }
 .section-data-view { margin: 16rpx 24rpx; }
 .section-data-view { margin: 16rpx 24rpx; }
 .section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12rpx; }
 .section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12rpx; }
-.section-title { font-size: 28rpx; font-weight: bold; color: $facade-text-strong; }
-.section-more { font-size: 24rpx; color: $brand-primary; }
+.section-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; }
+.section-more { font-size: calc(24rpx * var(--font-scale, 1)); color: $brand-primary; }
 .report-card { display: flex; align-items: center; background: $app-surface; border-radius: 16rpx; padding: 16rpx 20rpx; margin-bottom: 10rpx; }
 .report-card { display: flex; align-items: center; background: $app-surface; border-radius: 16rpx; padding: 16rpx 20rpx; margin-bottom: 10rpx; }
 .report-type-badge { font-size: 20rpx; padding: 4rpx 12rpx; border-radius: 8rpx; margin-right: 12rpx; flex-shrink: 0; font-weight: 600; }
 .report-type-badge { font-size: 20rpx; padding: 4rpx 12rpx; border-radius: 8rpx; margin-right: 12rpx; flex-shrink: 0; font-weight: 600; }
 .report-type-badge.badge-gut { background: rgba($brand-primary, 0.12); color: $brand-primary; }
 .report-type-badge.badge-gut { background: rgba($brand-primary, 0.12); color: $brand-primary; }
@@ -706,82 +708,82 @@ export default {
 .report-type-badge.badge-blood { background: rgba($status-danger, 0.12); color: $status-danger; }
 .report-type-badge.badge-blood { background: rgba($status-danger, 0.12); color: $status-danger; }
 .report-type-badge.badge-default { background: rgba($facade-text-slate, 0.12); color: $facade-text-slate; }
 .report-type-badge.badge-default { background: rgba($facade-text-slate, 0.12); color: $facade-text-slate; }
 .report-info { flex: 1; min-width: 0; }
 .report-info { flex: 1; min-width: 0; }
-.report-name { font-size: 26rpx; color: $facade-text-strong; font-weight: 600; display: block; margin-bottom: 4rpx; }
-.report-meta { font-size: 20rpx; color: $facade-text-muted; display: block; }
+.report-name { font-size: calc(26rpx * var(--font-scale, 1)); color: $facade-text-strong; font-weight: 600; display: block; margin-bottom: 4rpx; }
+.report-meta { font-size: calc(20rpx * var(--font-scale, 1)); color: $facade-text-muted; display: block; }
 .report-score-wrap { display: flex; flex-direction: column; align-items: flex-end; margin-right: 8rpx; flex-shrink: 0; }
 .report-score-wrap { display: flex; flex-direction: column; align-items: flex-end; margin-right: 8rpx; flex-shrink: 0; }
-.report-score { font-size: 32rpx; font-weight: bold; color: $brand-primary; line-height: 1; }
-.report-status { font-size: 20rpx; margin-top: 4rpx; }
+.report-score { font-size: calc(32rpx * var(--font-scale, 1)); font-weight: bold; color: $brand-primary; line-height: 1; }
+.report-status { font-size: calc(20rpx * var(--font-scale, 1)); margin-top: 4rpx; }
 .report-status.status-resolved { color: $dim-action; }
 .report-status.status-resolved { color: $dim-action; }
 .report-status.status-pending { color: $dim-wealth; }
 .report-status.status-pending { color: $dim-wealth; }
 .report-arrow { font-size: 28rpx; color: $facade-text-ghost; }
 .report-arrow { font-size: 28rpx; color: $facade-text-ghost; }
 .empty-hint { text-align: center; padding: 30rpx 0; background: $app-surface; border-radius: 16rpx; }
 .empty-hint { text-align: center; padding: 30rpx 0; background: $app-surface; border-radius: 16rpx; }
-.empty-hint .empty-text { font-size: 26rpx; color: $facade-text-muted; display: block; }
-.empty-hint .empty-sub { font-size: 22rpx; color: $facade-text-ghost; display: block; margin-top: 6rpx; }
+.empty-hint .empty-text { font-size: calc(26rpx * var(--font-scale, 1)); color: $facade-text-muted; display: block; }
+.empty-hint .empty-sub { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-ghost; display: block; margin-top: 6rpx; }
 .section-plan { margin: 8rpx 24rpx 16rpx; }
 .section-plan { margin: 8rpx 24rpx 16rpx; }
 .plan-card { background: $app-surface; border-radius: 20rpx; padding: 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .plan-card { background: $app-surface; border-radius: 20rpx; padding: 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .plan-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
 .plan-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
-.plan-title { font-size: 28rpx; font-weight: bold; color: $facade-text-strong; }
+.plan-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; }
 .plan-btn { background: linear-gradient(135deg, $brand-primary, $brand-primary-light); color: $app-surface; font-size: 24rpx; border: none; border-radius: 20rpx; padding: 10rpx 28rpx; height: 56rpx; line-height: 36rpx; margin: 0; }
 .plan-btn { background: linear-gradient(135deg, $brand-primary, $brand-primary-light); color: $app-surface; font-size: 24rpx; border: none; border-radius: 20rpx; padding: 10rpx 28rpx; height: 56rpx; line-height: 36rpx; margin: 0; }
-.plan-goal { font-size: 24rpx; color: $facade-text-body; line-height: 1.5; display: block; margin-top: 12rpx; }
-.plan-hint { font-size: 22rpx; color: $facade-text-muted; display: block; margin-top: 12rpx; }
+.plan-goal { font-size: calc(24rpx * var(--font-scale, 1)); color: $facade-text-body; line-height: 1.5; display: block; margin-top: 12rpx; }
+.plan-hint { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; display: block; margin-top: 12rpx; }
 /* ===== 游客态样式 ===== */
 /* ===== 游客态样式 ===== */
 .brand-strap { margin: 0 24rpx 16rpx; background: linear-gradient(135deg, $facade-brand-tint, rgba($brand-primary, 0.08)); border-radius: 16rpx; padding: 20rpx 24rpx; }
 .brand-strap { margin: 0 24rpx 16rpx; background: linear-gradient(135deg, $facade-brand-tint, rgba($brand-primary, 0.08)); border-radius: 16rpx; padding: 20rpx 24rpx; }
-.brand-strap-text { font-size: 26rpx; color: $brand-primary; font-weight: 600; }
+.brand-strap-text { font-size: calc(26rpx * var(--font-scale, 1)); color: $brand-primary; font-weight: 600; }
 .pain-card { margin: 0 24rpx 16rpx; background: $app-surface; border-radius: 20rpx; padding: 28rpx; border-left: 6rpx solid $brand-primary; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .pain-card { margin: 0 24rpx 16rpx; background: $app-surface; border-radius: 20rpx; padding: 28rpx; border-left: 6rpx solid $brand-primary; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
-.pain-quote { font-size: 32rpx; font-weight: bold; color: $facade-text-strong; display: block; margin-bottom: 8rpx; }
-.pain-desc { font-size: 26rpx; color: $facade-text-faint; display: block; }
+.pain-quote { font-size: calc(32rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; display: block; margin-bottom: 8rpx; }
+.pain-desc { font-size: calc(26rpx * var(--font-scale, 1)); color: $facade-text-faint; display: block; }
 .guest-features { display: flex; flex-wrap: wrap; justify-content: space-between; margin: 0 24rpx 16rpx; }
 .guest-features { display: flex; flex-wrap: wrap; justify-content: space-between; margin: 0 24rpx 16rpx; }
 .feat-card { width: 48.5%; box-sizing: border-box; background: $app-surface; border-radius: 20rpx; padding: 24rpx 20rpx; margin-bottom: 16rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .feat-card { width: 48.5%; box-sizing: border-box; background: $app-surface; border-radius: 20rpx; padding: 24rpx 20rpx; margin-bottom: 16rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .feat-icon { font-size: 44rpx; display: block; margin-bottom: 10rpx; }
 .feat-icon { font-size: 44rpx; display: block; margin-bottom: 10rpx; }
-.feat-title { font-size: 26rpx; font-weight: 600; color: $facade-text-strong; display: block; margin-bottom: 4rpx; }
-.feat-desc { font-size: 22rpx; color: $facade-text-muted; display: block; }
+.feat-title { font-size: calc(26rpx * var(--font-scale, 1)); font-weight: 600; color: $facade-text-strong; display: block; margin-bottom: 4rpx; }
+.feat-desc { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; display: block; }
 .self-test-card { margin: 0 24rpx 16rpx; background: linear-gradient(135deg, $brand-primary, $brand-primary-light); border-radius: 20rpx; padding: 24rpx 28rpx; }
 .self-test-card { margin: 0 24rpx 16rpx; background: linear-gradient(135deg, $brand-primary, $brand-primary-light); border-radius: 20rpx; padding: 24rpx 28rpx; }
 .self-test-head { display: flex; align-items: center; }
 .self-test-head { display: flex; align-items: center; }
 .self-test-icon { font-size: 40rpx; margin-right: 16rpx; }
 .self-test-icon { font-size: 40rpx; margin-right: 16rpx; }
 .self-test-info { flex: 1; }
 .self-test-info { flex: 1; }
-.self-test-title { font-size: 28rpx; font-weight: bold; color: $app-surface; display: block; }
-.self-test-sub { font-size: 22rpx; color: rgba($app-surface, 0.8); display: block; margin-top: 4rpx; }
+.self-test-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: bold; color: $app-surface; display: block; }
+.self-test-sub { font-size: calc(22rpx * var(--font-scale, 1)); color: rgba($app-surface, 0.8); display: block; margin-top: 4rpx; }
 .ai-q-entry { margin: 0 24rpx 16rpx; background: linear-gradient(135deg, $brand-primary, $dim-wealth); border-radius: 20rpx; padding: 24rpx 28rpx; }
 .ai-q-entry { margin: 0 24rpx 16rpx; background: linear-gradient(135deg, $brand-primary, $dim-wealth); border-radius: 20rpx; padding: 24rpx 28rpx; }
 .reminder-icon { font-size: 40rpx; margin-right: 16rpx; flex-shrink: 0; }
 .reminder-icon { font-size: 40rpx; margin-right: 16rpx; flex-shrink: 0; }
 .reminder-body { flex: 1; min-width: 0; }
 .reminder-body { flex: 1; min-width: 0; }
-.reminder-text { font-size: 26rpx; font-weight: 600; color: $facade-text-strong; display: block; }
-.reminder-sub { font-size: 22rpx; color: $facade-text-muted; margin-top: 4rpx; display: block; line-height: 1.4; }
+.reminder-text { font-size: calc(26rpx * var(--font-scale, 1)); font-weight: 600; color: $facade-text-strong; display: block; }
+.reminder-sub { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; margin-top: 4rpx; display: block; line-height: 1.4; }
 .reminder-arrow { font-size: 28rpx; color: $brand-primary; flex-shrink: 0; }
 .reminder-arrow { font-size: 28rpx; color: $brand-primary; flex-shrink: 0; }
 .ai-q-head { display: flex; align-items: center; }
 .ai-q-head { display: flex; align-items: center; }
 .ai-q-icon { font-size: 40rpx; margin-right: 16rpx; }
 .ai-q-icon { font-size: 40rpx; margin-right: 16rpx; }
 .ai-q-info { flex: 1; }
 .ai-q-info { flex: 1; }
-.q-title { font-size: 28rpx; font-weight: bold; color: $app-surface; display: block; }
-.ai-q-sub { font-size: 22rpx; color: rgba($app-surface, 0.85); display: block; margin-top: 4rpx; }
+.q-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: bold; color: $app-surface; display: block; }
+.ai-q-sub { font-size: calc(22rpx * var(--font-scale, 1)); color: rgba($app-surface, 0.85); display: block; margin-top: 4rpx; }
 .self-test-arrow { font-size: 36rpx; color: rgba($app-surface, 0.7); }
 .self-test-arrow { font-size: 36rpx; color: rgba($app-surface, 0.7); }
 .demo-section { margin: 0 24rpx 16rpx; }
 .demo-section { margin: 0 24rpx 16rpx; }
 .demo-section-head { margin-bottom: 8rpx; }
 .demo-section-head { margin-bottom: 8rpx; }
-.demo-section-title { font-size: 30rpx; font-weight: bold; color: $facade-text-strong; display: block; }
-.demo-section-sub { font-size: 22rpx; color: $facade-text-muted; display: block; margin-top: 4rpx; }
+.demo-section-title { font-size: calc(30rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; display: block; }
+.demo-section-sub { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; display: block; margin-top: 4rpx; }
 .demo-chart-title-row { display: flex; align-items: center; justify-content: space-between; margin: 8rpx 8rpx 0; padding: 0 8rpx; }
 .demo-chart-title-row { display: flex; align-items: center; justify-content: space-between; margin: 8rpx 8rpx 0; padding: 0 8rpx; }
-.demo-chart-name { font-size: 26rpx; font-weight: 600; color: $facade-text-strong; }
+.demo-chart-name { font-size: calc(26rpx * var(--font-scale, 1)); font-weight: 600; color: $facade-text-strong; }
 .demo-chart-tag { font-size: 20rpx; color: $brand-primary; background: rgba($brand-primary, 0.1); border-radius: 8rpx; padding: 4rpx 12rpx; }
 .demo-chart-tag { font-size: 20rpx; color: $brand-primary; background: rgba($brand-primary, 0.1); border-radius: 8rpx; padding: 4rpx 12rpx; }
 .login-guide-section { margin: 0 24rpx 24rpx; }
 .login-guide-section { margin: 0 24rpx 24rpx; }
 
 
 /* ===== 五维闭环体系样式 ===== */
 /* ===== 五维闭环体系样式 ===== */
 .wuxing-section { margin: 0 24rpx 16rpx; background: $app-surface; border-radius: 20rpx; padding: 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .wuxing-section { margin: 0 24rpx 16rpx; background: $app-surface; border-radius: 20rpx; padding: 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
-.wuxing-title { font-size: 30rpx; font-weight: bold; color: $facade-text-strong; text-align: center; margin-bottom: 6rpx; }
-.wuxing-desc { font-size: 22rpx; color: $facade-text-muted; text-align: center; margin-bottom: 20rpx; }
+.wuxing-title { font-size: calc(30rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; text-align: center; margin-bottom: 6rpx; }
+.wuxing-desc { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; text-align: center; margin-bottom: 20rpx; }
 .wuxing-diagram { position: relative; height: 320rpx; margin: 0 auto 20rpx; }
 .wuxing-diagram { position: relative; height: 320rpx; margin: 0 auto 20rpx; }
 .wuxing-relations { margin-top: 8rpx; }
 .wuxing-relations { margin-top: 8rpx; }
 .rel-group { margin-bottom: 16rpx; }
 .rel-group { margin-bottom: 16rpx; }
-.rel-title { font-size: 24rpx; font-weight: bold; color: $facade-text-strong; margin-bottom: 8rpx; display: block; }
+.rel-title { font-size: calc(24rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; margin-bottom: 8rpx; display: block; }
 .rel-chain { display: flex; flex-wrap: wrap; align-items: center; gap: 4rpx; margin-bottom: 6rpx; }
 .rel-chain { display: flex; flex-wrap: wrap; align-items: center; gap: 4rpx; margin-bottom: 6rpx; }
-.rel-item { font-size: 22rpx; padding: 4rpx 10rpx; border-radius: 8rpx; background: $facade-fill-cool; color: $facade-text-deep; }
+.rel-item { font-size: calc(22rpx * var(--font-scale, 1)); padding: 4rpx 10rpx; border-radius: 8rpx; background: $facade-fill-cool; color: $facade-text-deep; }
 .rel-arrow { font-size: 20rpx; color: $brand-primary; font-weight: bold; }
 .rel-arrow { font-size: 20rpx; color: $brand-primary; font-weight: bold; }
-.rel-dot { font-size: 20rpx; color: $facade-text-ghost; }
-.rel-hint { font-size: 20rpx; color: $facade-text-muted; line-height: 1.5; display: block; }
+.rel-dot { font-size: calc(20rpx * var(--font-scale, 1)); color: $facade-text-ghost; }
+.rel-hint { font-size: calc(20rpx * var(--font-scale, 1)); color: $facade-text-muted; line-height: 1.5; display: block; }
 .wuxing-cards { display: flex; flex-direction: column; gap: 10rpx; margin-top: 16rpx; }
 .wuxing-cards { display: flex; flex-direction: column; gap: 10rpx; margin-top: 16rpx; }
 .wc-card { display: flex; align-items: center; padding: 16rpx 20rpx; border-radius: 16rpx; border: 2rpx solid $facade-fill; }
 .wc-card { display: flex; align-items: center; padding: 16rpx 20rpx; border-radius: 16rpx; border: 2rpx solid $facade-fill; }
 .wc-card:active { opacity: 0.85; }
 .wc-card:active { opacity: 0.85; }
 .wc-icon { font-size: 36rpx; margin-right: 16rpx; flex-shrink: 0; }
 .wc-icon { font-size: 36rpx; margin-right: 16rpx; flex-shrink: 0; }
 .wc-info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
 .wc-info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
-.wc-name { font-size: 24rpx; font-weight: 600; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
-.wc-text { font-size: 20rpx; color: $facade-text-muted; display: block; margin-top: 4rpx; white-space: normal; }
+.wc-name { font-size: calc(24rpx * var(--font-scale, 1)); font-weight: 600; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.wc-text { font-size: calc(20rpx * var(--font-scale, 1)); color: $facade-text-muted; display: block; margin-top: 4rpx; white-space: normal; }
 .wc-body { border-color: rgba($dim-body, 0.3); background: rgba($dim-body, 0.04); border-left: 8rpx solid $dim-body; }
 .wc-body { border-color: rgba($dim-body, 0.3); background: rgba($dim-body, 0.04); border-left: 8rpx solid $dim-body; }
 .wc-body .wc-name { color: $dim-body; }
 .wc-body .wc-name { color: $dim-body; }
 .wc-wisdom { border-color: rgba($dim-wisdom, 0.3); background: rgba($dim-wisdom, 0.04); border-left: 8rpx solid $dim-wisdom; }
 .wc-wisdom { border-color: rgba($dim-wisdom, 0.3); background: rgba($dim-wisdom, 0.04); border-left: 8rpx solid $dim-wisdom; }
@@ -793,4 +795,4 @@ export default {
 .wc-mind { border-color: rgba($dim-mind, 0.3); background: rgba($dim-mind, 0.04); border-left: 8rpx solid $dim-mind; }
 .wc-mind { border-color: rgba($dim-mind, 0.3); background: rgba($dim-mind, 0.04); border-left: 8rpx solid $dim-mind; }
 .wc-mind .wc-name { color: $dim-mind; }
 .wc-mind .wc-name { color: $dim-mind; }
 .survey-pending-tag { flex-shrink: 0; font-size: 20rpx; color: $app-surface; background: $brand-primary; padding: 6rpx 16rpx; border-radius: 999rpx; }
 .survey-pending-tag { flex-shrink: 0; font-size: 20rpx; color: $app-surface; background: $brand-primary; padding: 6rpx 16rpx; border-radius: 999rpx; }
-</style>
+</style>

+ 35 - 33
cfc-frontend/pages/health/challenge-manage.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="page">
+  <view class="page" :style="{ '--font-scale': fontScale }">
     <BaseLoading :loading="loading" text="加载中..." />
     <BaseLoading :loading="loading" text="加载中..." />
 
 
     <!-- 顶部双 Tab:共同挑战 / 个人目标 -->
     <!-- 顶部双 Tab:共同挑战 / 个人目标 -->
@@ -331,8 +331,10 @@
 <script>
 <script>
 import { getChallengeList, getChallengeHistory, createChallenge, updateChallenge, deleteChallenge, getChallengeTemplates, getFamilyMemberList, getMyMembership, respondChallenge } from '../../utils/api.js'
 import { getChallengeList, getChallengeHistory, createChallenge, updateChallenge, deleteChallenge, getChallengeTemplates, getFamilyMemberList, getMyMembership, respondChallenge } from '../../utils/api.js'
 import store from '../../store/index.js'
 import store from '../../store/index.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   data() {
   data() {
     return {
     return {
       loading: true,
       loading: true,
@@ -726,7 +728,7 @@ export default {
   flex: 1;
   flex: 1;
   text-align: center;
   text-align: center;
   padding: 20rpx 0;
   padding: 20rpx 0;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $uni-text-color-secondary;
   color: $uni-text-color-secondary;
   background: $app-surface;
   background: $app-surface;
@@ -761,7 +763,7 @@ export default {
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .overview-title {
 .overview-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $status-warning-strong;
   color: $status-warning-strong;
 }
 }
@@ -783,12 +785,12 @@ export default {
   padding: 16rpx 20rpx;
   padding: 16rpx 20rpx;
 }
 }
 .active-item-title {
 .active-item-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $mat-orange-900;
   color: $mat-orange-900;
 }
 }
 .active-item-meta {
 .active-item-meta {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $status-warning-strong-2;
   color: $status-warning-strong-2;
 }
 }
 
 
@@ -826,12 +828,12 @@ export default {
   align-items: center;
   align-items: center;
 }
 }
 .section-title {
 .section-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
 .group-label {
 .group-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $uni-text-color-secondary;
   color: $uni-text-color-secondary;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
@@ -860,12 +862,12 @@ export default {
   margin-bottom: 10rpx;
   margin-bottom: 10rpx;
 }
 }
 .card-title {
 .card-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
 .card-status {
 .card-status {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   padding: 4rpx 12rpx;
   padding: 4rpx 12rpx;
   border-radius: 20rpx;
   border-radius: 20rpx;
 }
 }
@@ -883,7 +885,7 @@ export default {
   flex-wrap: wrap;
   flex-wrap: wrap;
 }
 }
 .meta-item {
 .meta-item {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $uni-text-color-secondary;
   color: $uni-text-color-secondary;
   background: $facade-fill-slate-50;
   background: $facade-fill-slate-50;
   padding: 4rpx 12rpx;
   padding: 4rpx 12rpx;
@@ -916,8 +918,8 @@ export default {
   padding: 80rpx 0;
   padding: 80rpx 0;
 }
 }
 .empty-icon { font-size: 80rpx; margin-bottom: 16rpx; }
 .empty-icon { font-size: 80rpx; margin-bottom: 16rpx; }
-.empty-title { font-size: 32rpx; font-weight: 700; color: $uni-text-color; }
-.empty-desc { font-size: 26rpx; color: $app-text-subtle; margin: 8rpx 0 32rpx; }
+.empty-title { font-size: calc(32rpx * var(--font-scale, 1)); font-weight: 700; color: $uni-text-color; }
+.empty-desc { font-size: calc(26rpx * var(--font-scale, 1)); color: $app-text-subtle; margin: 8rpx 0 32rpx; }
 .btn-empty {
 .btn-empty {
   background: $status-success;
   background: $status-success;
   color: $app-surface;
   color: $app-surface;
@@ -954,7 +956,7 @@ export default {
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .modal-title {
 .modal-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
@@ -980,7 +982,7 @@ export default {
   margin-bottom: 4rpx;
   margin-bottom: 4rpx;
 }
 }
 .tpl-label {
 .tpl-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-slate-deep;
   color: $facade-text-slate-deep;
   font-weight: 600;
   font-weight: 600;
   white-space: nowrap;
   white-space: nowrap;
@@ -1008,7 +1010,7 @@ export default {
   background: $status-success-soft-2;
   background: $status-success-soft-2;
 }
 }
 .tpl-icon { font-size: 32rpx; }
 .tpl-icon { font-size: 32rpx; }
-.tpl-name { font-size: 22rpx; color: $facade-text-slate-deep; font-weight: 500; }
+.tpl-name { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-slate-deep; font-weight: 500; }
 .tpl-item.active .tpl-name { color: $status-success-strong-2; }
 .tpl-item.active .tpl-name { color: $status-success-strong-2; }
 
 
 /* 表单字段 */
 /* 表单字段 */
@@ -1018,7 +1020,7 @@ export default {
   gap: 8rpx;
   gap: 8rpx;
 }
 }
 .field-label {
 .field-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-slate-deep;
   color: $facade-text-slate-deep;
   font-weight: 600;
   font-weight: 600;
 }
 }
@@ -1028,7 +1030,7 @@ export default {
   border: 1rpx solid $uni-border-color-light;
   border: 1rpx solid $uni-border-color-light;
   border-radius: 12rpx;
   border-radius: 12rpx;
   padding: 16rpx 18rpx;
   padding: 16rpx 18rpx;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
 .field-textarea {
 .field-textarea {
@@ -1036,7 +1038,7 @@ export default {
   border: 1rpx solid $uni-border-color-light;
   border: 1rpx solid $uni-border-color-light;
   border-radius: 12rpx;
   border-radius: 12rpx;
   padding: 16rpx 18rpx;
   padding: 16rpx 18rpx;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $uni-text-color;
   color: $uni-text-color;
   height: 100rpx;
   height: 100rpx;
   width: 100%;
   width: 100%;
@@ -1077,7 +1079,7 @@ export default {
 .member-item {
 .member-item {
   padding: 10rpx 22rpx;
   padding: 10rpx 22rpx;
   border-radius: 24rpx;
   border-radius: 24rpx;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-slate-deep;
   color: $facade-text-slate-deep;
   background: $facade-fill-slate;
   background: $facade-fill-slate;
   border: 2rpx solid transparent;
   border: 2rpx solid transparent;
@@ -1105,7 +1107,7 @@ export default {
   border-bottom: 2rpx solid $uni-border-color-light;
   border-bottom: 2rpx solid $uni-border-color-light;
 }
 }
 .detail-modal .modal-title {
 .detail-modal .modal-title {
-  font-size: 34rpx;
+  font-size: calc(34rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
@@ -1118,7 +1120,7 @@ export default {
   color: $status-danger-deep;
   color: $status-danger-deep;
 }
 }
 .detail-body {
 .detail-body {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   line-height: 1.6;
   line-height: 1.6;
   color: $facade-text-slate-deep;
   color: $facade-text-slate-deep;
 }
 }
@@ -1129,7 +1131,7 @@ export default {
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
 .detail-header .detail-title {
 .detail-header .detail-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
@@ -1144,7 +1146,7 @@ export default {
 .detail-header .status-cancelled { background: $status-danger-soft; color: $status-danger-deep; }
 .detail-header .status-cancelled { background: $status-danger-soft; color: $status-danger-deep; }
 .detail-header .status-not-launched { background: $facade-gray-200; color: $facade-text-slate; }
 .detail-header .status-not-launched { background: $facade-gray-200; color: $facade-text-slate; }
 .detail-desc {
 .detail-desc {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $uni-text-color-secondary;
   color: $uni-text-color-secondary;
   line-height: 1.4;
   line-height: 1.4;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
@@ -1159,17 +1161,17 @@ export default {
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
 }
 }
 .detail-row .detail-label {
 .detail-row .detail-label {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: #647489;
   color: #647489;
   font-weight: 500;
   font-weight: 500;
 }
 }
 .detail-row .detail-value {
 .detail-row .detail-value {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $status-success;
   color: $status-success;
   font-weight: 600;
   font-weight: 600;
 }
 }
 .detail-row .detail-value-danger {
 .detail-row .detail-value-danger {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $status-danger-deep;
   color: $status-danger-deep;
 }
 }
 .detail-progress {
 .detail-progress {
@@ -1178,7 +1180,7 @@ export default {
   border-top: 2rpx solid $uni-border-color-light;
   border-top: 2rpx solid $uni-border-color-light;
 }
 }
 .detail-progress-title {
 .detail-progress-title {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $uni-text-color-secondary;
   color: $uni-text-color-secondary;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
@@ -1198,7 +1200,7 @@ export default {
 .detail-progress-text {
 .detail-progress-text {
   display: flex;
   display: flex;
   justify-content: space-between;
   justify-content: space-between;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $uni-text-color-secondary;
   color: $uni-text-color-secondary;
 }
 }
 .detail-member-list {
 .detail-member-list {
@@ -1210,7 +1212,7 @@ export default {
   align-items: center;
   align-items: center;
   padding: 8rpx 0;
   padding: 8rpx 0;
   border-bottom: 1rpx solid $facade-fill-slate;
   border-bottom: 1rpx solid $facade-fill-slate;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
 }
 }
 .detail-member-name {
 .detail-member-name {
   color: $uni-text-color;
   color: $uni-text-color;
@@ -1223,7 +1225,7 @@ export default {
 .detail-member-status {
 .detail-member-status {
   padding: 2rpx 6rpx;
   padding: 2rpx 6rpx;
   border-radius: 999rpx;
   border-radius: 999rpx;
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   font-weight: 400;
   font-weight: 400;
 }
 }
 .detail-member-pending { background: $status-warning-soft; color: $status-warning-strong-2; }
 .detail-member-pending { background: $status-warning-soft; color: $status-warning-strong-2; }
@@ -1307,15 +1309,15 @@ export default {
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .prompt-title {
 .prompt-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
 .prompt-desc {
 .prompt-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $uni-text-color-secondary;
   color: $uni-text-color-secondary;
   text-align: center;
   text-align: center;
   line-height: 1.6;
   line-height: 1.6;
 }
 }
-</style>
+</style>

+ 50 - 48
cfc-frontend/pages/home-pages/parent-index.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-<view class="container">
+<view class="container" :style="{ '--font-scale': fontScale }">
 <!-- 加载状态 -->
 <!-- 加载状态 -->
 <BaseLoading :loading="loading" text="正在加载..." />
 <BaseLoading :loading="loading" text="正在加载..." />
 
 
@@ -520,8 +520,10 @@ import OnboardingProgressBar from '../../components/OnboardingProgressBar.vue'
 import GateLock from '../../components/gate-lock.vue'
 import GateLock from '../../components/gate-lock.vue'
 import GateGuideBar from '@/pages/home-pages/components/gate-guide-bar.vue'
 import GateGuideBar from '@/pages/home-pages/components/gate-guide-bar.vue'
 import feedbackEngine from '../../utils/feedback-engine.js'
 import feedbackEngine from '../../utils/feedback-engine.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   components: { RecommendedFeed, PlayfulCard, PlayfulButton, BaseBadge, BaseEmpty, BaseLoading, FamilyRelationGraph, WuxingSandbox, ContactCard, ContactImport, FamilyMemberStrip, MicroActionCard, FeedbackToast, MilestoneCelebration, DailySummary, HealthAlertBanner, FamilyHealthRanking, FamilyChallengeCard, CircleRanking, ArticleBookshelf, OnboardingProgressBar, GateLock, GateGuideBar, AdBanner },
   components: { RecommendedFeed, PlayfulCard, PlayfulButton, BaseBadge, BaseEmpty, BaseLoading, FamilyRelationGraph, WuxingSandbox, ContactCard, ContactImport, FamilyMemberStrip, MicroActionCard, FeedbackToast, MilestoneCelebration, DailySummary, HealthAlertBanner, FamilyHealthRanking, FamilyChallengeCard, CircleRanking, ArticleBookshelf, OnboardingProgressBar, GateLock, GateGuideBar, AdBanner },
   data() {
   data() {
     return {
     return {
@@ -1317,7 +1319,7 @@ export default {
    区块标题
    区块标题
    ======================================== */
    ======================================== */
 .section-title {
 .section-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: var(--text, $uni-text-color);
   color: var(--text, $uni-text-color);
   margin-bottom: var(--space-md);
   margin-bottom: var(--space-md);
@@ -1375,7 +1377,7 @@ export default {
 }
 }
 
 
 .stat-label-header {
 .stat-label-header {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: var(--text, $uni-text-color);
   color: var(--text, $uni-text-color);
 }
 }
@@ -1393,12 +1395,12 @@ export default {
 }
 }
 
 
 .compare-label {
 .compare-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: var(--text-secondary, $uni-text-color-secondary);
   color: var(--text-secondary, $uni-text-color-secondary);
 }
 }
 
 
 .compare-value {
 .compare-value {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
 }
 }
 
 
@@ -1426,14 +1428,14 @@ export default {
 .gold-color { color: $dim-wealth; }
 .gold-color { color: $dim-wealth; }
 
 
 .stat-more {
 .stat-more {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: var(--color-accent, $uni-info);
   color: var(--color-accent, $uni-info);
   font-weight: 500;
   font-weight: 500;
   display: block;
   display: block;
 }
 }
 
 
 .stat-encourage {
 .stat-encourage {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $status-success;
   color: $status-success;
   font-weight: 500;
   font-weight: 500;
   margin-top: 8rpx;
   margin-top: 8rpx;
@@ -1458,7 +1460,7 @@ export default {
 }
 }
 
 
 .today-label {
 .today-label {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: var(--text, $uni-text-color);
   color: var(--text, $uni-text-color);
 }
 }
@@ -1499,7 +1501,7 @@ export default {
 .dot-color-4 { background: var(--color-error, $status-danger); }
 .dot-color-4 { background: var(--color-error, $status-danger); }
 
 
 .task-title {
 .task-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: var(--text, $uni-text-color);
   color: var(--text, $uni-text-color);
 }
 }
 
 
@@ -1508,7 +1510,7 @@ export default {
   justify-content: flex-end;
   justify-content: flex-end;
   align-items: center;
   align-items: center;
   color: var(--text-secondary, $uni-text-color-secondary);
   color: var(--text-secondary, $uni-text-color-secondary);
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   padding-top: 16rpx;
   padding-top: 16rpx;
   border-top: 1rpx solid var(--border-light, $uni-border-color-light);
   border-top: 1rpx solid var(--border-light, $uni-border-color-light);
 }
 }
@@ -1559,7 +1561,7 @@ export default {
 .milestone-sparkle { background: rgba(16, 185, 129, 0.12); }
 .milestone-sparkle { background: rgba(16, 185, 129, 0.12); }
 
 
 .milestone-text {
 .milestone-text {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: var(--text, $uni-text-color);
   color: var(--text, $uni-text-color);
 }
 }
 
 
@@ -1593,10 +1595,10 @@ export default {
 .pending-icon--pink { background: rgba(236,72,153,0.12); }
 .pending-icon--pink { background: rgba(236,72,153,0.12); }
 .pending-icon--green { background: rgba(16,185,129,0.12); }
 .pending-icon--green { background: rgba(16,185,129,0.12); }
 .pending-icon--orange { background: rgba(249,115,22,0.12); }
 .pending-icon--orange { background: rgba(249,115,22,0.12); }
-.pending-emoji { font-size: 32rpx; }
+.pending-emoji { font-size: calc(32rpx * var(--font-scale, 1)); }
 .pending-info { flex: 1; min-width: 0; }
 .pending-info { flex: 1; min-width: 0; }
 .pending-count { font-size: 36rpx; font-weight: 800; display: block; }
 .pending-count { font-size: 36rpx; font-weight: 800; display: block; }
-.pending-label { font-size: 22rpx; color: $facade-text-body; margin-top: 4rpx; display: block; }
+.pending-label { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-body; margin-top: 4rpx; display: block; }
 .pink-color { color: $accent-pink; }
 .pink-color { color: $accent-pink; }
 .orange-color { color: $brand-primary; }
 .orange-color { color: $brand-primary; }
 
 
@@ -1617,8 +1619,8 @@ export default {
 }
 }
 .advice-icon { font-size: 28rpx; }
 .advice-icon { font-size: 28rpx; }
 .advice-text-wrap { flex: 1; min-width: 0; }
 .advice-text-wrap { flex: 1; min-width: 0; }
-.advice-title { font-size: 28rpx; font-weight: 600; color: $facade-text-strong; display: block; }
-.advice-desc { font-size: 24rpx; color: $facade-text-muted; margin-top: 4rpx; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.advice-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: 600; color: $facade-text-strong; display: block; }
+.advice-desc { font-size: calc(24rpx * var(--font-scale, 1)); color: $facade-text-muted; margin-top: 4rpx; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
 .advice-arrow { font-size: 36rpx; color: $facade-text-ghost; margin-left: 12rpx; }
 .advice-arrow { font-size: 36rpx; color: $facade-text-ghost; margin-left: 12rpx; }
 
 
 /* ========================================
 /* ========================================
@@ -1649,14 +1651,14 @@ export default {
 }
 }
 
 
 .review-info .task-name {
 .review-info .task-name {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: var(--text, $uni-text-color);
   color: var(--text, $uni-text-color);
   display: block;
   display: block;
   margin-bottom: 4rpx;
   margin-bottom: 4rpx;
 }
 }
 
 
 .review-info .task-child {
 .review-info .task-child {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: var(--muted, $app-text-subtle);
   color: var(--muted, $app-text-subtle);
 }
 }
 
 
@@ -1717,7 +1719,7 @@ export default {
 .act-invite { background: rgba(139, 92, 246, 0.12); }
 .act-invite { background: rgba(139, 92, 246, 0.12); }
 
 
 .action-label {
 .action-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: var(--text-secondary, $uni-text-color-secondary);
   color: var(--text-secondary, $uni-text-color-secondary);
   font-weight: 500;
   font-weight: 500;
   text-align: center;
   text-align: center;
@@ -1735,7 +1737,7 @@ export default {
   border: 1rpx dashed $uni-border-color-light;
   border: 1rpx dashed $uni-border-color-light;
 }
 }
 .error-state-text {
 .error-state-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-subtle;
   color: $app-text-subtle;
   text-align: center;
   text-align: center;
 }
 }
@@ -1751,7 +1753,7 @@ export default {
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .contact-section-title {
 .contact-section-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
@@ -1761,7 +1763,7 @@ export default {
   align-items: center;
   align-items: center;
 }
 }
 .contact-more {
 .contact-more {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .contact-import-btn {
 .contact-import-btn {
@@ -1806,7 +1808,7 @@ export default {
   color: $facade-text-ghost;
   color: $facade-text-ghost;
 }
 }
 .add-card-label {
 .add-card-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .contact-empty {
 .contact-empty {
@@ -1814,7 +1816,7 @@ export default {
   text-align: center;
   text-align: center;
 }
 }
 .contact-empty-text {
 .contact-empty-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-ghost;
   color: $facade-text-ghost;
 }
 }
 
 
@@ -1832,7 +1834,7 @@ export default {
   margin-bottom: 0;
   margin-bottom: 0;
 }
 }
 .article-more {
 .article-more {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: var(--color-primary, $brand-primary);
   color: var(--color-primary, $brand-primary);
 }
 }
 .article-list {
 .article-list {
@@ -1856,12 +1858,12 @@ export default {
   margin-bottom: 10rpx;
   margin-bottom: 10rpx;
 }
 }
 .article-category-text {
 .article-category-text {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-surface;
   color: $app-surface;
 }
 }
 .article-title {
 .article-title {
   display: block;
   display: block;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
@@ -1869,7 +1871,7 @@ export default {
 }
 }
 .article-summary {
 .article-summary {
   display: block;
   display: block;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-faint;
   color: $facade-text-faint;
   line-height: 1.5;
   line-height: 1.5;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
@@ -1893,11 +1895,11 @@ export default {
   font-size: 24rpx;
   font-size: 24rpx;
 }
 }
 .meta-text {
 .meta-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .article-date {
 .article-date {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-ghost-light;
   color: $facade-text-ghost-light;
 }
 }
 
 
@@ -1912,12 +1914,12 @@ export default {
   margin: 0 20rpx 12rpx;
   margin: 0 20rpx 12rpx;
 }
 }
 .challenge-section-title {
 .challenge-section-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
 .challenge-section-action {
 .challenge-section-action {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $status-success;
   color: $status-success;
   font-weight: 600;
   font-weight: 600;
 }
 }
@@ -1957,14 +1959,14 @@ export default {
 }
 }
 .circle-card-title {
 .circle-card-title {
   display: block;
   display: block;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
   line-height: 1.4;
   line-height: 1.4;
 }
 }
 .circle-card-subtitle {
 .circle-card-subtitle {
   display: block;
   display: block;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-slate;
   color: $facade-text-slate;
   margin-top: 2rpx;
   margin-top: 2rpx;
 }
 }
@@ -1988,12 +1990,12 @@ export default {
 }
 }
 .circle-rank-family {
 .circle-rank-family {
   flex: 1;
   flex: 1;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-gray-700;
   color: $facade-text-gray-700;
   font-weight: 500;
   font-weight: 500;
 }
 }
 .circle-rank-score {
 .circle-rank-score {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 600;
   font-weight: 600;
 }
 }
@@ -2002,7 +2004,7 @@ export default {
   justify-content: flex-end;
   justify-content: flex-end;
 }
 }
 .circle-action-text {
 .circle-action-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -2023,18 +2025,18 @@ export default {
   margin-bottom: 4rpx;
   margin-bottom: 4rpx;
 }
 }
 .circle-invite-title {
 .circle-invite-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $status-success-strong;
   color: $status-success-strong;
 }
 }
 .circle-invite-desc {
 .circle-invite-desc {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-slate;
   color: $facade-text-slate;
   text-align: center;
   text-align: center;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
 .circle-invite-cta {
 .circle-invite-cta {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 600;
   font-weight: 600;
   margin-top: 4rpx;
   margin-top: 4rpx;
@@ -2090,14 +2092,14 @@ export default {
 }
 }
 .selfcheck-title {
 .selfcheck-title {
   display: block;
   display: block;
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
   line-height: 1.4;
   line-height: 1.4;
 }
 }
 .selfcheck-subtitle {
 .selfcheck-subtitle {
   display: block;
   display: block;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-slate;
   color: $facade-text-slate;
   margin-top: 4rpx;
   margin-top: 4rpx;
 }
 }
@@ -2142,7 +2144,7 @@ export default {
 }
 }
 
 
 .qr-code-modal-title {
 .qr-code-modal-title {
-  font-size: 36rpx;
+  font-size: calc(36rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
@@ -2191,14 +2193,14 @@ export default {
 }
 }
 
 
 .qr-code-label {
 .qr-code-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $uni-text-color-secondary;
   color: $uni-text-color-secondary;
   font-weight: 500;
   font-weight: 500;
 }
 }
 
 
 .qr-code-code {
 .qr-code-code {
   flex: 1;
   flex: 1;
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $uni-text-color;
   color: $uni-text-color;
   word-break: break-all;
   word-break: break-all;
@@ -2206,7 +2208,7 @@ export default {
 }
 }
 
 
 .qr-code-copy {
 .qr-code-copy {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 500;
   font-weight: 500;
   padding: 8rpx 16rpx;
   padding: 8rpx 16rpx;
@@ -2236,13 +2238,13 @@ export default {
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .empty-family-title {
 .empty-family-title {
-  font-size: 34rpx;
+  font-size: calc(34rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $mat-orange-deep;
   color: $mat-orange-deep;
   margin-bottom: 10rpx;
   margin-bottom: 10rpx;
 }
 }
 .empty-family-desc {
 .empty-family-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-bottom: 28rpx;
   margin-bottom: 28rpx;
 }
 }
@@ -2261,4 +2263,4 @@ export default {
   border: none;
   border: none;
 }
 }
 
 
-</style>
+</style>

+ 46 - 44
cfc-frontend/pages/index-home/index.vue

@@ -3,7 +3,7 @@
   <!-- 通用登录浮层 -->
   <!-- 通用登录浮层 -->
   <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
   <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
   <!-- 冷启动 splash overlay — 覆盖首页直到数据加载完毕(tab 切回时不显示) -->
   <!-- 冷启动 splash overlay — 覆盖首页直到数据加载完毕(tab 切回时不显示) -->
-  <view class="splash-overlay" :class="{'fade-out': splashOverlayFading}" v-if="splashOverlay || splashOverlayFading">
+  <view class="splash-overlay" :style="{ '--font-scale': fontScale }" :class="{'fade-out': splashOverlayFading}" v-if="splashOverlay || splashOverlayFading">
     <view class="splash-overlay-bg">
     <view class="splash-overlay-bg">
       <view class="bg-circle bg-circle-1"></view>
       <view class="bg-circle bg-circle-1"></view>
       <view class="bg-circle bg-circle-2"></view>
       <view class="bg-circle bg-circle-2"></view>
@@ -436,8 +436,10 @@ import { findAppByKey, getShortcutableApps } from '../../utils/app-library.js'
 import nav from '../../utils/nav.js'
 import nav from '../../utils/nav.js'
 import config from '@/config.js'
 import config from '@/config.js'
 import { parseDate } from '../../utils/format.js'
 import { parseDate } from '../../utils/format.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
 components: {
 components: {
     WuxingSandbox,
     WuxingSandbox,
     GateLock,
     GateLock,
@@ -2076,7 +2078,7 @@ $c-warm-tint:     #FFF3E7;
 
 
 .hero-name {
 .hero-name {
   display: block;
   display: block;
-  font-size: 48rpx;
+  font-size: calc(48rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $c-brand-ink;
   color: $c-brand-ink;
   margin-top: 16rpx;
   margin-top: 16rpx;
@@ -2085,7 +2087,7 @@ $c-warm-tint:     #FFF3E7;
 
 
 .hero-identity {
 .hero-identity {
   display: block;
   display: block;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   margin-top: 12rpx;
   margin-top: 12rpx;
@@ -2094,7 +2096,7 @@ $c-warm-tint:     #FFF3E7;
 
 
 .hero-slogan {
 .hero-slogan {
   display: block;
   display: block;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $c-brand-ink-2;
   color: $c-brand-ink-2;
   margin-top: 8rpx;
   margin-top: 8rpx;
   font-weight: 500;
   font-weight: 500;
@@ -2102,7 +2104,7 @@ $c-warm-tint:     #FFF3E7;
 
 
 .hero-powered {
 .hero-powered {
   display: block;
   display: block;
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: rgba($c-brand-ink, 0.45);
   color: rgba($c-brand-ink, 0.45);
   margin-top: 10rpx;
   margin-top: 10rpx;
 }
 }
@@ -2126,11 +2128,11 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 
 
 .hero-dim-emoji {
 .hero-dim-emoji {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
 }
 }
 
 
 .hero-dim-label {
 .hero-dim-label {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $c-brand-ink;
   color: $c-brand-ink;
   font-weight: 500;
   font-weight: 500;
   white-space: nowrap;
   white-space: nowrap;
@@ -2139,7 +2141,7 @@ $c-warm-tint:     #FFF3E7;
 /* ===== 未登录态 Hero 副标语 / CTA ===== */
 /* ===== 未登录态 Hero 副标语 / CTA ===== */
 .hero-sub-slogan {
 .hero-sub-slogan {
   display: block;
   display: block;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary-dark;
   color: $brand-primary-dark;
   margin-top: 18rpx;
   margin-top: 18rpx;
   font-weight: 500;
   font-weight: 500;
@@ -2170,7 +2172,7 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 .value-prop-title {
 .value-prop-title {
   display: block;
   display: block;
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
   text-align: center;
   text-align: center;
@@ -2206,12 +2208,12 @@ $c-warm-tint:     #FFF3E7;
   min-width: 0;
   min-width: 0;
 }
 }
 .value-prop-name {
 .value-prop-name {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .value-prop-desc {
 .value-prop-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-top: 8rpx;
   margin-top: 8rpx;
   line-height: 1.5;
   line-height: 1.5;
@@ -2227,7 +2229,7 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 .how-it-works-title {
 .how-it-works-title {
   display: block;
   display: block;
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
   text-align: center;
   text-align: center;
@@ -2252,20 +2254,20 @@ $c-warm-tint:     #FFF3E7;
   border-radius: 50%;
   border-radius: 50%;
   background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
   background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
   color: $app-surface;
   color: $app-surface;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   text-align: center;
   text-align: center;
   box-shadow: 0 4rpx 12rpx rgba($brand-primary, 0.3);
   box-shadow: 0 4rpx 12rpx rgba($brand-primary, 0.3);
 }
 }
 .step-name {
 .step-name {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   font-weight: 500;
   font-weight: 500;
   margin-top: 12rpx;
   margin-top: 12rpx;
   text-align: center;
   text-align: center;
 }
 }
 .step-sub {
 .step-sub {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-top: 4rpx;
   margin-top: 4rpx;
   text-align: center;
   text-align: center;
@@ -2287,7 +2289,7 @@ $c-warm-tint:     #FFF3E7;
   border-left: 4rpx solid $brand-primary;
   border-left: 4rpx solid $brand-primary;
 }
 }
 .brand-strap-text {
 .brand-strap-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $c-brand-ink-2;
   color: $c-brand-ink-2;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -2322,12 +2324,12 @@ $c-warm-tint:     #FFF3E7;
   min-width: 0;
   min-width: 0;
 }
 }
 .member-entry-title {
 .member-entry-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-surface;
   color: $app-surface;
 }
 }
 .member-entry-desc {
 .member-entry-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: rgba($app-surface, 0.85);
   color: rgba($app-surface, 0.85);
   margin-top: 4rpx;
   margin-top: 4rpx;
   overflow: hidden;
   overflow: hidden;
@@ -2356,7 +2358,7 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 .loading-text,
 .loading-text,
 .empty-text {
 .empty-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 
 
@@ -2386,7 +2388,7 @@ $c-warm-tint:     #FFF3E7;
   border: none;
   border: none;
 }
 }
 .login-footer-text {
 .login-footer-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   margin-top: 16rpx;
   margin-top: 16rpx;
   font-weight: 500;
   font-weight: 500;
@@ -2425,12 +2427,12 @@ $c-warm-tint:     #FFF3E7;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .section-title {
 .section-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .section-more {
 .section-more {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
 }
 }
 .empty-state {
 .empty-state {
@@ -2439,7 +2441,7 @@ $c-warm-tint:     #FFF3E7;
   padding: 60rpx 0;
   padding: 60rpx 0;
 }
 }
 .empty-text {
 .empty-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 
 
@@ -2474,7 +2476,7 @@ $c-warm-tint:     #FFF3E7;
   justify-content: space-between;
   justify-content: space-between;
 }
 }
 .activity-name {
 .activity-name {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
@@ -2490,7 +2492,7 @@ $c-warm-tint:     #FFF3E7;
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
 }
 }
 .activity-time {
 .activity-time {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .activity-bottom {
 .activity-bottom {
@@ -2499,7 +2501,7 @@ $c-warm-tint:     #FFF3E7;
   gap: 12rpx;
   gap: 12rpx;
 }
 }
 .activity-status {
 .activity-status {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   padding: 2rpx 10rpx;
   padding: 2rpx 10rpx;
   border-radius: 8rpx;
   border-radius: 8rpx;
   background: $c-success-tint;
   background: $c-success-tint;
@@ -2514,7 +2516,7 @@ $c-warm-tint:     #FFF3E7;
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .activity-fee {
 .activity-fee {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: bold;
   font-weight: bold;
 }
 }
@@ -2544,12 +2546,12 @@ $c-warm-tint:     #FFF3E7;
   margin-bottom: 10rpx;
   margin-bottom: 10rpx;
 }
 }
 .article-category-text {
 .article-category-text {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-surface;
   color: $app-surface;
 }
 }
 .article-title {
 .article-title {
   display: block;
   display: block;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
@@ -2557,7 +2559,7 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 .article-summary {
 .article-summary {
   display: block;
   display: block;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-faint;
   color: $facade-text-faint;
   line-height: 1.5;
   line-height: 1.5;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
@@ -2581,11 +2583,11 @@ $c-warm-tint:     #FFF3E7;
   font-size: 24rpx;
   font-size: 24rpx;
 }
 }
 .meta-text {
 .meta-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .article-date {
 .article-date {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-ghost-light;
   color: $facade-text-ghost-light;
 }
 }
 
 
@@ -2675,13 +2677,13 @@ $c-warm-tint:     #FFF3E7;
 
 
 /* ---- brand ---- */
 /* ---- brand ---- */
 .splash-brand-name {
 .splash-brand-name {
-  font-size: 64rpx; font-weight: 800;
+  font-size: calc(64rpx * var(--font-scale, 1)); font-weight: 800;
   color: $c-brand-ink;
   color: $c-brand-ink;
   letter-spacing: 10rpx;
   letter-spacing: 10rpx;
   margin-bottom: 2rpx;
   margin-bottom: 2rpx;
 }
 }
 .splash-brand-en {
 .splash-brand-en {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: rgba($c-brand-ink, 0.5);
   color: rgba($c-brand-ink, 0.5);
   letter-spacing: 6rpx;
   letter-spacing: 6rpx;
   margin-bottom: 30rpx;
   margin-bottom: 30rpx;
@@ -2710,7 +2712,7 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 .splash-dim-icon { font-size: 36rpx; line-height: 1; }
 .splash-dim-icon { font-size: 36rpx; line-height: 1; }
 .splash-dim-label {
 .splash-dim-label {
-  font-size: 22rpx; font-weight: 500;
+  font-size: calc(22rpx * var(--font-scale, 1)); font-weight: 500;
   color: rgba($c-brand-ink, 0.75);
   color: rgba($c-brand-ink, 0.75);
   line-height: 1;
   line-height: 1;
 }
 }
@@ -2765,8 +2767,8 @@ $c-warm-tint:     #FFF3E7;
 .self-test-head { display: flex; align-items: center; }
 .self-test-head { display: flex; align-items: center; }
 .self-test-icon { font-size: 40rpx; margin-right: 16rpx; }
 .self-test-icon { font-size: 40rpx; margin-right: 16rpx; }
 .self-test-info { flex: 1; }
 .self-test-info { flex: 1; }
-.self-test-title { font-size: 28rpx; font-weight: bold; color: $app-surface; display: block; }
-.self-test-sub { font-size: 22rpx; color: rgba($app-surface, 0.8); display: block; margin-top: 4rpx; }
+.self-test-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: bold; color: $app-surface; display: block; }
+.self-test-sub { font-size: calc(22rpx * var(--font-scale, 1)); color: rgba($app-surface, 0.8); display: block; margin-top: 4rpx; }
 .self-test-arrow { font-size: 36rpx; color: rgba($app-surface, 0.7); }
 .self-test-arrow { font-size: 36rpx; color: rgba($app-surface, 0.7); }
 
 
 /* ===== ①.b 行动引导条 — Next Best Action ===== */
 /* ===== ①.b 行动引导条 — Next Best Action ===== */
@@ -2791,8 +2793,8 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 .guide-bar-icon { font-size: 34rpx; }
 .guide-bar-icon { font-size: 34rpx; }
 .guide-bar-info { flex: 1; min-width: 0; }
 .guide-bar-info { flex: 1; min-width: 0; }
-.guide-bar-title { font-size: 27rpx; font-weight: bold; display: block; }
-.guide-bar-sub { font-size: 21rpx; margin-top: 3rpx; display: block; }
+.guide-bar-title { font-size: calc(27rpx * var(--font-scale, 1)); font-weight: bold; display: block; }
+.guide-bar-sub { font-size: calc(21rpx * var(--font-scale, 1)); margin-top: 3rpx; display: block; }
 .guide-bar-btn {
 .guide-bar-btn {
   flex-shrink: 0;
   flex-shrink: 0;
   margin-left: 12rpx;
   margin-left: 12rpx;
@@ -2867,7 +2869,7 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 
 
 .quick-item .quick-label {
 .quick-item .quick-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
 }
 }
 
 
@@ -2897,14 +2899,14 @@ $c-warm-tint:     #FFF3E7;
 }
 }
 
 
 .task-quick-title {
 .task-quick-title {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   font-weight: 500;
   font-weight: 500;
   line-height: 1.4;
   line-height: 1.4;
 }
 }
 
 
 .task-quick-meta {
 .task-quick-meta {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   margin-top: 4rpx;
   margin-top: 4rpx;
   font-weight: bold;
   font-weight: bold;
@@ -2961,7 +2963,7 @@ $c-warm-tint:     #FFF3E7;
   line-height: 1;
   line-height: 1;
 }
 }
 .challenge-empty-text {
 .challenge-empty-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
@@ -2980,4 +2982,4 @@ $c-warm-tint:     #FFF3E7;
   border: none;
   border: none;
 }
 }
 .self-test-badge { display: inline-block; align-self: flex-start; margin-top: 8rpx; font-size: 20rpx; color: $brand-primary; background: rgba($brand-primary, 0.1); padding: 4rpx 14rpx; border-radius: 999rpx; }
 .self-test-badge { display: inline-block; align-self: flex-start; margin-top: 8rpx; font-size: 20rpx; color: $brand-primary; background: rgba($brand-primary, 0.1); padding: 4rpx 14rpx; border-radius: 999rpx; }
-</style>
+</style>

+ 82 - 80
cfc-frontend/pages/mind-detail/index.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="container">
+  <view class="container" :style="{ '--font-scale': fontScale }">
     <!-- 通用登录浮层 -->
     <!-- 通用登录浮层 -->
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <!-- Tabbar 切换过渡页 -->
     <!-- Tabbar 切换过渡页 -->
@@ -273,8 +273,10 @@ import { getVisibleSections, getEmiReport, getFamilyEnergySandbox, getEnergySand
 import nav from '../../utils/nav.js'
 import nav from '../../utils/nav.js'
 import config from '../../config.js'
 import config from '../../config.js'
 import { parseDate } from '../../utils/format.js'
 import { parseDate } from '../../utils/format.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
 components: { TabTransition, PageBanner, RadarChart, FamilyEnergyBar, PsychCrisisBanner, FloatingAvatar, FamilyTianpanCard, DimensionMemberTabs, DimensionIntroCard, DimensionVisitorCard, DimensionPageSkeleton },
 components: { TabTransition, PageBanner, RadarChart, FamilyEnergyBar, PsychCrisisBanner, FloatingAvatar, FamilyTianpanCard, DimensionMemberTabs, DimensionIntroCard, DimensionVisitorCard, DimensionPageSkeleton },
   data() {
   data() {
     return {
     return {
@@ -1332,7 +1334,7 @@ $tint-cyan: #F0F6F7;
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
 .section-title-text {
 .section-title-text {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-surface;
   color: $app-surface;
 }
 }
@@ -1368,14 +1370,14 @@ $tint-cyan: #F0F6F7;
   flex: 1;
   flex: 1;
 }
 }
 .mind-report-title {
 .mind-report-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-violet-deep;
   color: $facade-violet-deep;
   display: block;
   display: block;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .mind-report-desc {
 .mind-report-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-violet-light-2;
   color: $facade-violet-light-2;
   line-height: 1.5;
   line-height: 1.5;
   display: block;
   display: block;
@@ -1423,17 +1425,17 @@ $tint-cyan: #F0F6F7;
   margin-right: 14rpx;
   margin-right: 14rpx;
 }
 }
 .mind-report-item-name {
 .mind-report-item-name {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   flex: 1;
   flex: 1;
 }
 }
 .mind-report-item-date {
 .mind-report-item-date {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-right: 14rpx;
   margin-right: 14rpx;
 }
 }
 .mind-report-item-status {
 .mind-report-item-status {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   padding: 2rpx 12rpx;
   padding: 2rpx 12rpx;
   border-radius: 20rpx;
   border-radius: 20rpx;
 }
 }
@@ -1458,7 +1460,7 @@ $tint-cyan: #F0F6F7;
   margin-right: 10rpx;
   margin-right: 10rpx;
 }
 }
 .mind-report-empty-text {
 .mind-report-empty-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-border;
   color: $app-border;
 }
 }
 
 
@@ -1505,7 +1507,7 @@ $tint-cyan: #F0F6F7;
   box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.06);
   box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.06);
 }
 }
 .emi-card-title {
 .emi-card-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
   display: block;
   display: block;
@@ -1534,7 +1536,7 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .emi-bar-label {
 .emi-bar-label {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   width: 120rpx;
   width: 120rpx;
   flex-shrink: 0;
   flex-shrink: 0;
@@ -1553,7 +1555,7 @@ $tint-cyan: #F0F6F7;
   transition: width 0.5s;
   transition: width 0.5s;
 }
 }
 .emi-bar-score {
 .emi-bar-score {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
   width: 60rpx;
   width: 60rpx;
@@ -1561,7 +1563,7 @@ $tint-cyan: #F0F6F7;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .emi-bar-level {
 .emi-bar-level {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   width: 80rpx;
   width: 80rpx;
   text-align: right;
   text-align: right;
   flex-shrink: 0;
   flex-shrink: 0;
@@ -1580,7 +1582,7 @@ $tint-cyan: #F0F6F7;
   border-top: 1rpx solid $app-surface-subtle;
   border-top: 1rpx solid $app-surface-subtle;
 }
 }
 .emi-overall {
 .emi-overall {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $mind-accent;
   color: $mind-accent;
 }
 }
@@ -1590,7 +1592,7 @@ $tint-cyan: #F0F6F7;
   align-items: center;
   align-items: center;
 }
 }
 .emi-link-text {
 .emi-link-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $mind-accent;
   color: $mind-accent;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -1612,7 +1614,7 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .emi-title {
 .emi-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
   display: block;
   display: block;
@@ -1628,7 +1630,7 @@ $tint-cyan: #F0F6F7;
   color: $app-surface;
   color: $app-surface;
 }
 }
 .emi-overall-label {
 .emi-overall-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .emi-overall-value {
 .emi-overall-value {
@@ -1637,7 +1639,7 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .emi-overall-level {
 .emi-overall-level {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   padding: 4rpx 16rpx;
   padding: 4rpx 16rpx;
   border-radius: 12rpx;
   border-radius: 12rpx;
   background: rgba(255,255,255,0.2);
   background: rgba(255,255,255,0.2);
@@ -1659,7 +1661,7 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
 }
 }
 .emi-dim-label {
 .emi-dim-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
 }
 }
 .emi-dim-values {
 .emi-dim-values {
@@ -1668,13 +1670,13 @@ $tint-cyan: #F0F6F7;
   align-items: center;
   align-items: center;
 }
 }
 .emi-dim-score {
 .emi-dim-score {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $mind-accent;
   color: $mind-accent;
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
 .emi-dim-level {
 .emi-dim-level {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   padding: 2rpx 12rpx;
   padding: 2rpx 12rpx;
   border-radius: 8rpx;
   border-radius: 8rpx;
 }
 }
@@ -1698,7 +1700,7 @@ $tint-cyan: #F0F6F7;
   margin-top: 20rpx;
   margin-top: 20rpx;
 }
 }
 .emi-footer-text {
 .emi-footer-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -1735,13 +1737,13 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .placeholder-title {
 .placeholder-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .placeholder-desc {
 .placeholder-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   text-align: center;
   text-align: center;
   line-height: 1.6;
   line-height: 1.6;
@@ -1778,12 +1780,12 @@ $tint-cyan: #F0F6F7;
   margin-right: 10rpx;
   margin-right: 10rpx;
 }
 }
 .culture-card-title {
 .culture-card-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $app-text;
   color: $app-text;
 }
 }
 .culture-card-body {
 .culture-card-body {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   line-height: 1.6;
   line-height: 1.6;
 }
 }
@@ -1799,12 +1801,12 @@ $tint-cyan: #F0F6F7;
   align-items: center;
   align-items: center;
 }
 }
 .bazi-pillar-label {
 .bazi-pillar-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .bazi-pillar-value {
 .bazi-pillar-value {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $brand-primary;
   color: $brand-primary;
   background: $facade-violet-tint;
   background: $facade-violet-tint;
@@ -1823,7 +1825,7 @@ $tint-cyan: #F0F6F7;
   gap: 12rpx;
   gap: 12rpx;
 }
 }
 .wuxing-label {
 .wuxing-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   width: 44rpx;
   width: 44rpx;
   text-align: center;
   text-align: center;
@@ -1840,7 +1842,7 @@ $tint-cyan: #F0F6F7;
   border-radius: 10rpx;
   border-radius: 10rpx;
 }
 }
 .wuxing-value {
 .wuxing-value {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   width: 56rpx;
   width: 56rpx;
   text-align: right;
   text-align: right;
@@ -1890,7 +1892,7 @@ $tint-cyan: #F0F6F7;
 }
 }
 
 
 .energy-label {
 .energy-label {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   background: linear-gradient(135deg, $dim-wealth, $dim-mind);
   background: linear-gradient(135deg, $dim-wealth, $dim-mind);
   -webkit-background-clip: text;
   -webkit-background-clip: text;
@@ -1907,7 +1909,7 @@ $tint-cyan: #F0F6F7;
 }
 }
 
 
 .energy-quote {
 .energy-quote {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-border-subtle;
   color: $app-border-subtle;
   line-height: 1.8;
   line-height: 1.8;
   display: block;
   display: block;
@@ -1930,7 +1932,7 @@ $tint-cyan: #F0F6F7;
 }
 }
 
 
 .energy-advice {
 .energy-advice {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-subtle;
   color: $app-text-subtle;
   line-height: 1.7;
   line-height: 1.7;
   display: block;
   display: block;
@@ -1983,12 +1985,12 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
 }
 }
 .culture-dual-label {
 .culture-dual-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .culture-dual-value {
 .culture-dual-value {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $brand-primary;
   color: $brand-primary;
 }
 }
@@ -1996,7 +1998,7 @@ $tint-cyan: #F0F6F7;
   text-align: center;
   text-align: center;
   padding: 30rpx 0;
   padding: 30rpx 0;
   color: $app-border;
   color: $app-border;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
 }
 }
 
 
 /* ===== 每日心理 ===== */
 /* ===== 每日心理 ===== */
@@ -2018,14 +2020,14 @@ $tint-cyan: #F0F6F7;
   padding: 28rpx 24rpx;
   padding: 28rpx 24rpx;
 }
 }
 .tip-title {
 .tip-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $dim-mind;
   color: $dim-mind;
   display: block;
   display: block;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
 .tip-content {
 .tip-content {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   line-height: 1.6;
   line-height: 1.6;
   display: block;
   display: block;
@@ -2037,7 +2039,7 @@ $tint-cyan: #F0F6F7;
   justify-content: flex-end;
   justify-content: flex-end;
 }
 }
 .tip-source {
 .tip-source {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-border;
   color: $app-border;
 }
 }
 
 
@@ -2049,7 +2051,7 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .section-title {
 .section-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
 }
 }
@@ -2073,19 +2075,19 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 14rpx;
   margin-bottom: 14rpx;
 }
 }
 .article-category-text {
 .article-category-text {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-surface;
   color: $app-surface;
   font-weight: 500;
   font-weight: 500;
 }
 }
 .article-title {
 .article-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
   display: block;
   display: block;
   margin-bottom: 10rpx;
   margin-bottom: 10rpx;
 }
 }
 .article-summary {
 .article-summary {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   line-height: 1.5;
   line-height: 1.5;
   display: block;
   display: block;
@@ -2108,11 +2110,11 @@ $tint-cyan: #F0F6F7;
   margin-right: 4rpx;
   margin-right: 4rpx;
 }
 }
 .meta-text {
 .meta-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-border;
   color: $app-border;
 }
 }
 .article-date {
 .article-date {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-border;
   color: $app-border;
   margin-left: auto;
   margin-left: auto;
 }
 }
@@ -2155,7 +2157,7 @@ $tint-cyan: #F0F6F7;
   font-size: 40rpx;
   font-size: 40rpx;
 }
 }
 .func-label {
 .func-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -2169,17 +2171,17 @@ $tint-cyan: #F0F6F7;
 .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 { 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-card.no-data { opacity: 0.5; }
 .indicator-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
 .indicator-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
-.indicator-name { font-size: 26rpx; color: $app-text-secondary; font-weight: 500; }
-.indicator-unit { font-size: 22rpx; color: $app-text-muted; }
+.indicator-name { font-size: calc(26rpx * var(--font-scale, 1)); color: $app-text-secondary; font-weight: 500; }
+.indicator-unit { font-size: calc(22rpx * var(--font-scale, 1)); color: $app-text-muted; }
 .indicator-body { margin-bottom: 8rpx; }
 .indicator-body { margin-bottom: 8rpx; }
-.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: $app-border; }
+.indicator-value { font-size: calc(40rpx * var(--font-scale, 1)); font-weight: bold; color: $dim-mind; }
+.indicator-placeholder { font-size: calc(26rpx * var(--font-scale, 1)); color: $app-border; }
+.indicator-range { font-size: calc(20rpx * var(--font-scale, 1)); color: $app-border; }
 .bottom-spacer { height: 120rpx; }
 .bottom-spacer { height: 120rpx; }
 
 
 /* ===== 肠脑轴 ===== */
 /* ===== 肠脑轴 ===== */
 .gut-insight-text {
 .gut-insight-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
   padding: 12rpx 16rpx;
   padding: 12rpx 16rpx;
@@ -2202,13 +2204,13 @@ $tint-cyan: #F0F6F7;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .gut-indicator-name {
 .gut-indicator-name {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   font-weight: 500;
   font-weight: 500;
   display: block;
   display: block;
 }
 }
 .gut-indicator-impact {
 .gut-indicator-impact {
-  font-size: 18rpx;
+  font-size: calc(18rpx * var(--font-scale, 1));
   color: $dim-mind;
   color: $dim-mind;
   display: block;
   display: block;
   margin-top: 2rpx;
   margin-top: 2rpx;
@@ -2226,13 +2228,13 @@ $tint-cyan: #F0F6F7;
   transition: width 0.3s;
   transition: width 0.3s;
 }
 }
 .gut-indicator-value {
 .gut-indicator-value {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   width: 60rpx;
   width: 60rpx;
   text-align: right;
   text-align: right;
 }
 }
 .gut-indicator-status {
 .gut-indicator-status {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   padding: 2rpx 12rpx;
   padding: 2rpx 12rpx;
   border-radius: 10rpx;
   border-radius: 10rpx;
   width: 60rpx;
   width: 60rpx;
@@ -2269,7 +2271,7 @@ $tint-cyan: #F0F6F7;
   margin-right: 8rpx;
   margin-right: 8rpx;
 }
 }
 .key-info-title {
 .key-info-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $app-text;
   color: $app-text;
 }
 }
@@ -2286,7 +2288,7 @@ $tint-cyan: #F0F6F7;
   min-width: 0;
   min-width: 0;
 }
 }
 .ki-subtitle {
 .ki-subtitle {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
   font-weight: 500;
   font-weight: 500;
@@ -2301,7 +2303,7 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 0;
   margin-bottom: 0;
 }
 }
 .ki-label {
 .ki-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-right: 8rpx;
   margin-right: 8rpx;
   white-space: nowrap;
   white-space: nowrap;
@@ -2314,13 +2316,13 @@ $tint-cyan: #F0F6F7;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .ki-valuel {
 .ki-valuel {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   font-weight: 500;
   font-weight: 500;
   white-space: nowrap;
   white-space: nowrap;
 }
 }
 .ki-valued {
 .ki-valued {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -2333,12 +2335,12 @@ $tint-cyan: #F0F6F7;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .ki-num {
 .ki-num {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $dim-mind;
   color: $dim-mind;
 }
 }
 .ki-fortune {
 .ki-fortune {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   padding: 2rpx 12rpx;
   padding: 2rpx 12rpx;
   border-radius: 10rpx;
   border-radius: 10rpx;
@@ -2377,7 +2379,7 @@ $tint-cyan: #F0F6F7;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .ki-insight-text {
 .ki-insight-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $mind-insight-ink;
   color: $mind-insight-ink;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
@@ -2385,7 +2387,7 @@ $tint-cyan: #F0F6F7;
   margin-top: 16rpx;
   margin-top: 16rpx;
   text-align: center;
   text-align: center;
   padding: 12rpx;
   padding: 12rpx;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 500;
   font-weight: 500;
   background: $facade-violet-tint-2;
   background: $facade-violet-tint-2;
@@ -2410,11 +2412,11 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
 .dan-report-date {
 .dan-report-date {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
 }
 }
 .dan-status {
 .dan-status {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   padding: 4rpx 16rpx;
   padding: 4rpx 16rpx;
   border-radius: 8rpx;
   border-radius: 8rpx;
 }
 }
@@ -2427,7 +2429,7 @@ $tint-cyan: #F0F6F7;
   color: $status-warning-strong;
   color: $status-warning-strong;
 }
 }
 .dan-report-desc {
 .dan-report-desc {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   font-weight: 500;
   font-weight: 500;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
@@ -2437,7 +2439,7 @@ $tint-cyan: #F0F6F7;
   text-align: right;
   text-align: right;
 }
 }
 .dan-view-link {
 .dan-view-link {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-wisdom;
   color: $dim-wisdom;
 }
 }
 .section-header {
 .section-header {
@@ -2447,13 +2449,13 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .section-title {
 .section-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: 700;
   font-weight: 700;
   color: $app-text;
   color: $app-text;
 }
 }
 .section-more {
 .section-more {
   position: relative;
   position: relative;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-wisdom;
   color: $dim-wisdom;
   padding: 8rpx 16rpx;
   padding: 8rpx 16rpx;
 }
 }
@@ -2476,7 +2478,7 @@ $tint-cyan: #F0F6F7;
   border-left: 8rpx solid $dim-mind;
   border-left: 8rpx solid $dim-mind;
 }
 }
 .brand-strap-text {
 .brand-strap-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $c-mind-ink;
   color: $c-mind-ink;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -2494,7 +2496,7 @@ $tint-cyan: #F0F6F7;
 }
 }
 .guidance-icon { font-size: 32rpx; }
 .guidance-icon { font-size: 32rpx; }
 .guidance-text {
 .guidance-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $c-mind-ink;
   color: $c-mind-ink;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -2502,7 +2504,7 @@ $tint-cyan: #F0F6F7;
 /* 雷达图分组 */
 /* 雷达图分组 */
 .radar-group { margin-bottom: 30rpx; }
 .radar-group { margin-bottom: 30rpx; }
 .radar-group-label {
 .radar-group-label {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $c-mind-ink;
   color: $c-mind-ink;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
@@ -2519,7 +2521,7 @@ $tint-cyan: #F0F6F7;
   border: 2rpx solid rgba(255, 107, 157, 0.1);
   border: 2rpx solid rgba(255, 107, 157, 0.1);
 }
 }
 .portrait-tier {
 .portrait-tier {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-mind;
   color: $dim-mind;
   font-weight: bold;
   font-weight: bold;
   margin-left: 16rpx;
   margin-left: 16rpx;
@@ -2528,7 +2530,7 @@ $tint-cyan: #F0F6F7;
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .portrait-desc {
 .portrait-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   line-height: 1.6;
   line-height: 1.6;
   display: block;
   display: block;
@@ -2555,12 +2557,12 @@ $tint-cyan: #F0F6F7;
   font-size: 20rpx;
   font-size: 20rpx;
 }
 }
 .portrait-dim-name {
 .portrait-dim-name {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   flex: 1;
   flex: 1;
 }
 }
 .portrait-dim-score {
 .portrait-dim-score {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $dim-mind;
   color: $dim-mind;
   margin-right: 12rpx;
   margin-right: 12rpx;
@@ -2579,7 +2581,7 @@ $tint-cyan: #F0F6F7;
   transition: width 0.3s ease;
   transition: width 0.3s ease;
 }
 }
 .portrait-dim-desc {
 .portrait-dim-desc {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   display: block;
   display: block;
 }
 }
@@ -2591,8 +2593,8 @@ $tint-cyan: #F0F6F7;
   margin-top: 16rpx;
   margin-top: 16rpx;
 }
 }
 .portrait-tip-text {
 .portrait-tip-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
-</style>
+</style>

+ 25 - 23
cfc-frontend/pages/profile-extra/family-members.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="container">
+  <view class="container" :style="{ '--font-scale': fontScale }">
     <!-- ===== 家庭信息头部 ===== -->
     <!-- ===== 家庭信息头部 ===== -->
     <view class="family-header">
     <view class="family-header">
       <view class="family-header-content">
       <view class="family-header-content">
@@ -184,8 +184,10 @@ import {
 } from '../../utils/api.js'
 } from '../../utils/api.js'
 import store from '../../store/index.js'
 import store from '../../store/index.js'
 import GenerationPicker from '@/components/GenerationPicker.vue'
 import GenerationPicker from '@/components/GenerationPicker.vue'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   components: { GenerationPicker },
   components: { GenerationPicker },
   data() {
   data() {
     return {
     return {
@@ -825,7 +827,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   text-align: center;
   text-align: center;
 }
 }
 .family-name {
 .family-name {
-  font-size: 36rpx;
+  font-size: calc(36rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   display: block;
   display: block;
 }
 }
@@ -868,7 +870,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .jr-title {
 .jr-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
@@ -895,13 +897,13 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   min-width: 0;
   min-width: 0;
 }
 }
 .jr-name {
 .jr-name {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
   display: block;
   display: block;
 }
 }
 .jr-meta {
 .jr-meta {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-top: 4rpx;
   margin-top: 4rpx;
   display: block;
   display: block;
@@ -940,7 +942,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   min-width: 0;
   min-width: 0;
 }
 }
 .member-name {
 .member-name {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   display: block;
   display: block;
   color: $facade-text-strong;
   color: $facade-text-strong;
@@ -982,13 +984,13 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .empty-title {
 .empty-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
   display: block;
   display: block;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
 .empty-desc {
 .empty-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   display: block;
   display: block;
   margin-bottom: 40rpx;
   margin-bottom: 40rpx;
@@ -1095,12 +1097,12 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   flex: 1;
   flex: 1;
 }
 }
 .detail-name {
 .detail-name {
-  font-size: 34rpx;
+  font-size: calc(34rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   display: block;
   display: block;
 }
 }
 .detail-relation {
 .detail-relation {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   margin-top: 4rpx;
   margin-top: 4rpx;
   display: block;
   display: block;
@@ -1122,7 +1124,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   border-bottom: 1rpx solid $facade-fill;
   border-bottom: 1rpx solid $facade-fill;
 }
 }
 .detail-meta-item {
 .detail-meta-item {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-faint;
   color: $facade-text-faint;
 }
 }
 
 
@@ -1131,7 +1133,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .detail-section-title {
 .detail-section-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   display: block;
   display: block;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
@@ -1146,7 +1148,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
 }
 }
 .detail-score-label {
 .detail-score-label {
   width: 56rpx;
   width: 56rpx;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-faint;
   color: $facade-text-faint;
 }
 }
 .detail-score-bar-bg {
 .detail-score-bar-bg {
@@ -1166,7 +1168,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
 .detail-score-bar-fill.communication { background: $dim-wisdom; }
 .detail-score-bar-fill.communication { background: $dim-wisdom; }
 .detail-score-value {
 .detail-score-value {
   width: 44rpx;
   width: 44rpx;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-deep;
   color: $facade-text-deep;
   text-align: right;
   text-align: right;
@@ -1191,7 +1193,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
 .perm-title {
 .perm-title {
-  font-size: 34rpx;
+  font-size: calc(34rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
@@ -1201,12 +1203,12 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   padding: 0 12rpx;
   padding: 0 12rpx;
 }
 }
 .perm-subtitle {
 .perm-subtitle {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-slate-deep;
   color: $facade-text-slate-deep;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .perm-desc {
 .perm-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-subtle;
   color: $app-text-subtle;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
@@ -1214,7 +1216,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .perm-section-title {
 .perm-section-title {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-slate-700;
   color: $facade-text-slate-700;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
@@ -1237,7 +1239,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   border-bottom: none;
   border-bottom: none;
 }
 }
 .perm-granted-name {
 .perm-granted-name {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $uni-text-color;
   color: $uni-text-color;
 }
 }
 .perm-revoke-btn {
 .perm-revoke-btn {
@@ -1246,7 +1248,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   padding: 4rpx 12rpx;
   padding: 4rpx 12rpx;
 }
 }
 .perm-empty {
 .perm-empty {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-subtle;
   color: $app-text-subtle;
   padding: 20rpx 0;
   padding: 20rpx 0;
   text-align: center;
   text-align: center;
@@ -1263,7 +1265,7 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   border: 1rpx solid $uni-border-color-light;
   border: 1rpx solid $uni-border-color-light;
   border-radius: 12rpx;
   border-radius: 12rpx;
   padding: 16rpx 20rpx;
   padding: 16rpx 20rpx;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-slate-700;
   color: $facade-text-slate-700;
 }
 }
 .perm-add-btn {
 .perm-add-btn {
@@ -1328,13 +1330,13 @@ $c-elm-danger-text:  $el-danger; // Element UI 危险文字
   padding: 60rpx 0;
   padding: 60rpx 0;
 }
 }
 .loading-text {
 .loading-text {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .empty-tip {
 .empty-tip {
   text-align: center;
   text-align: center;
   padding: 60rpx 0;
   padding: 60rpx 0;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 </style>
 </style>

+ 1424 - 1421
cfc-frontend/pages/profile-main/profile.vue

@@ -1,1421 +1,1424 @@
-<template>
-  <view class="container">
-    <!-- 登录浮层(全局组件,页面内弹出底部登录) -->
-    <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
-    <!-- 未登录 -->
-    <view v-if="!isLoggedIn">
-      <view class="login-prompt">
-        <text class="prompt-icon">👤</text>
-        <text class="prompt-title">登录浠艾福</text>
-        <text class="prompt-desc">登录后查看个人资料、积分记录、能量数据与家庭管理</text>
-        <button class="login-btn" @click="goLogin">登录 / 注册</button>
-        <text class="skip-link" @click="goSkip">暂不登录,先逛逛 ›</text>
-      </view>
-
-      <view class="philosophy-card">
-        <text class="philosophy-title">照顾家庭,从照顾好自己开始</text>
-        <text class="philosophy-desc">你的状态,就是家的状态。先安顿好自己,才有余力温暖家人。</text>
-      </view>
-    </view>
-
-    <!-- 已登录 -->
-    <template v-else>
-      <!-- 退出切换 -->
-      <view class="exit-switch" v-if="isSwitchedChild" @click="onExitSwitch">
-        <text>🔄 退出切换</text>
-      </view>
-
-      <!-- 身份卡 -->
-      <view class="user-card">
-        <view class="user-card-left">
-          <view class="avatar-wrap" @click="goToEditInfo">
-            <image v-if="userInfo.avatar" class="avatar-img" :src="userInfo.avatar" mode="aspectFill" />
-            <text v-else class="avatar-text">{{ nickname.charAt(0) || '👤' }}</text>
-          </view>
-          <view class="user-meta">
-            <view class="user-name-row">
-              <text class="nickname">{{ nickname || '未设置昵称' }}</text>
-              <text v-if="roleLabel" class="role-tag">{{ roleLabel }}</text>
-            </view>
-            <view class="user-sub" v-if="memberLevel">
-              <view class="level-badge" :class="'level-' + memberLevel">{{ memberLevelText }}</view>
-              <text v-if="isLifetime" class="days-left">永久有效</text>
-              <text v-else-if="membershipDays > 0 && membershipDays <= 30" class="days-left">剩余 {{ membershipDays }} 天</text>
-              <view v-if="hasUpgradeSpace" class="upgrade-btn" @click="goUpgrade">
-                <text class="upgrade-btn-text">{{ upgradeBtnText }}</text>
-              </view>
-            </view>
-            <view class="user-sub" v-else>
-              <text class="days-left">开通会员解锁更多权益</text>
-              <view class="upgrade-btn" @click="goUpgrade">
-                <text class="upgrade-btn-text">立即开通</text>
-              </view>
-            </view>
-          </view>
-        </view>
-        <view class="user-card-right" @click="goToPoints">
-          <text class="points-num">{{ totalPoints }}</text>
-          <text class="points-label">积分</text>
-        </view>
-      </view>
-
-      <!-- 我的分享海报浮动按钮(纯 CSS 二维码图标,避免 emoji 渲染成计算器) -->
-      <view class="share-qr-float" @click="showShareQr">
-        <view class="qr-glyph">
-          <view class="qr-eye qr-eye-tl"></view>
-          <view class="qr-eye qr-eye-tr"></view>
-          <view class="qr-eye qr-eye-bl"></view>
-          <view class="qr-mid"></view>
-          <view class="qr-cluster">
-            <view class="qr-pip"></view>
-            <view class="qr-pip"></view>
-            <view class="qr-pip"></view>
-            <view class="qr-pip"></view>
-          </view>
-        </view>
-      </view>
-
-      <!-- 家族成员速览 -->
-      <view class="family-strip" v-if="familyMembers.length > 0">
-        <view class="family-strip-header">
-          <text class="family-strip-title">我的家庭</text>
-          <text class="family-strip-count">{{ familyMembers.length }} 位成员</text>
-        </view>
-        <view class="family-avatars">
-          <view
-            v-for="member in familyMembers"
-            :key="member.id"
-            class="family-avatar-item"
-            @click="goMemberDetail(member)"
-          >
-            <view class="family-avatar-wrap">
-              <image v-if="member.avatar" class="family-avatar-img" :src="member.avatar" mode="aspectFill" />
-              <text v-else class="family-avatar-text">{{ member.nickname ? member.nickname.charAt(0) : '?' }}</text>
-              <view class="family-avatar-tag" :class="'tag-' + (member.effectiveRole || member.source || 'member')">{{ member.roleLabel || memberRoleLabel(member.effectiveRole) }}</view>
-            </view>
-            <text class="family-avatar-name">{{ member.nickname || member.realName || '成员' }}</text>
-          </view>
-          <view class="family-avatar-item" @click="goToFamily">
-            <view class="family-avatar-wrap family-avatar-add">
-              <text class="family-avatar-plus">+</text>
-            </view>
-            <text class="family-avatar-name">添加</text>
-          </view>
-        </view>
-      </view>
-
-      <!-- 个人成就统计 -->
-      <view class="achievement-section">
-        <view class="section-header-row">
-          <text class="section-title">🏆 我的成就</text>
-          <text class="section-sub">持续成长,看见改变</text>
-        </view>
-        <view class="achievement-grid">
-          <view class="ach-item" @click="goToPoints">
-            <view class="ach-icon-wrap" style="background:rgba(249,115,22,0.12)">
-              <text class="ach-icon">💰</text>
-            </view>
-            <text class="ach-num">{{ totalPoints }}</text>
-            <text class="ach-label">累计积分</text>
-          </view>
-          <view class="ach-item" @click="goToStreak">
-            <view class="ach-icon-wrap" style="background:rgba(255,140,66,0.12)">
-              <text class="ach-icon">🔥</text>
-            </view>
-            <text class="ach-num">{{ streakDays }}</text>
-            <text class="ach-label">连续打卡</text>
-          </view>
-          <view class="ach-item" @click="goToTasks">
-            <view class="ach-icon-wrap" style="background:rgba(99,102,241,0.12)">
-              <text class="ach-icon">✅</text>
-            </view>
-            <text class="ach-num">{{ completedTasks }}</text>
-            <text class="ach-label">完成任务</text>
-          </view>
-          <view class="ach-item" @click="goToWishes">
-            <view class="ach-icon-wrap" style="background:rgba(245,158,11,0.12)">
-              <text class="ach-icon">🎁</text>
-            </view>
-            <text class="ach-num">{{ rewardsEarned }}</text>
-            <text class="ach-label">获得奖励</text>
-          </view>
-          <view class="ach-item" @click="goToBadges">
-            <view class="ach-icon-wrap" style="background:rgba(236,72,153,0.12)">
-              <text class="ach-icon">🏅</text>
-            </view>
-            <text class="ach-num">{{ badgesCollected }}</text>
-            <text class="ach-label">收集勋章</text>
-          </view>
-          <view class="ach-item" @click="goToGrowth">
-            <view class="ach-icon-wrap" style="background:rgba(16,185,129,0.12)">
-              <text class="ach-icon">📈</text>
-            </view>
-            <text class="ach-num">{{ growthRecords }}</text>
-            <text class="ach-label">成长记录</text>
-          </view>
-          <view class="ach-item" @click="goToChallenges">
-            <view class="ach-icon-wrap" style="background:rgba(255,107,157,0.12)">
-              <text class="ach-icon">🎯</text>
-            </view>
-            <text class="ach-num">{{ challengesJoined }}</text>
-            <text class="ach-label">参加挑战</text>
-          </view>
-          <view class="ach-item" @click="goToHealthReports">
-            <view class="ach-icon-wrap" style="background:rgba(14,165,233,0.12)">
-              <text class="ach-icon">📋</text>
-            </view>
-            <text class="ach-num">{{ healthReports }}</text>
-            <text class="ach-label">上传报告</text>
-          </view>
-          <view class="ach-item" @click="goToWealthCenter">
-            <view class="ach-icon-wrap" style="background:rgba(245,158,11,0.12)">
-              <text class="ach-icon">💰</text>
-            </view>
-            <text class="ach-num">{{ referralEarnings }}</text>
-            <text class="ach-label">推广收益</text>
-          </view>
-          <view class="ach-item" @click="goTeamTree">
-            <view class="ach-icon-wrap" style="background:rgba(16,185,129,0.12)">
-              <text class="ach-icon">🌳</text>
-            </view>
-            <text class="ach-num">{{ teamMembers }}</text>
-            <text class="ach-label">我的团队</text>
-          </view>
-        </view>
-      </view>
-
-      <!-- 我的订单(电商风格) -->
-      <view class="order-section">
-        <view class="order-section-header">
-          <text class="section-title">🛒 我的订单</text>
-          <text class="order-all-link" @click="goToOrders">全部订单 ›</text>
-        </view>
-        <view class="order-card">
-          <view class="order-grid">
-            <view class="order-grid-item" @click="goToOrderStatus('pending')">
-              <view class="order-icon-wrap">
-                <text class="order-icon">💳</text>
-                <text class="order-badge" v-if="orderPending > 0">{{ orderPending }}</text>
-              </view>
-              <text class="order-grid-text">待付款</text>
-            </view>
-            <view class="order-grid-item" @click="goToOrderStatus('paid')">
-              <view class="order-icon-wrap">
-                <text class="order-icon">📦</text>
-                <text class="order-badge" v-if="orderUnpaid > 0">{{ orderUnpaid }}</text>
-              </view>
-              <text class="order-grid-text">待发货</text>
-            </view>
-            <view class="order-grid-item" @click="goToOrderStatus('shipped')">
-              <view class="order-icon-wrap">
-                <text class="order-icon">🚚</text>
-                <text class="order-badge" v-if="orderShipped > 0">{{ orderShipped }}</text>
-              </view>
-              <text class="order-grid-text">待收货</text>
-            </view>
-            <view class="order-grid-item" @click="goToOrderStatus('refunding')">
-              <view class="order-icon-wrap">
-                <text class="order-icon">🔧</text>
-                <text class="order-badge" v-if="orderAfterSale > 0">{{ orderAfterSale }}</text>
-              </view>
-              <text class="order-grid-text">售后</text>
-            </view>
-            <view class="order-grid-item" @click="goToOrders">
-              <view class="order-icon-wrap">
-                <text class="order-icon">📋</text>
-              </view>
-              <text class="order-grid-text">全部</text>
-            </view>
-          </view>
-          <view class="order-extra-row">
-            <view class="order-extra-item" @click="goToCart">
-              <text class="order-extra-icon">🛒</text>
-              <text class="order-extra-text">购物车</text>
-              <text class="order-extra-badge" v-if="cartCount > 0">{{ cartCount > 99 ? '99+' : cartCount }}</text>
-            </view>
-            <view class="order-extra-divider"></view>
-            <view class="order-extra-item" @click="goToAddress">
-              <text class="order-extra-icon">📍</text>
-              <text class="order-extra-text">收货地址</text>
-            </view>
-          </view>
-        </view>
-      </view>
-
-      <!-- 规划师服务中心入口(仅规划师可见) -->
-      <view class="service-center-section" v-if="role === 'teacher' && teacherStatus === 'approved'">
-        <view class="service-center-card" @click="goToServiceCenter">
-          <view class="service-center-icon">👨‍🏫</view>
-          <view class="service-center-info">
-            <text class="service-center-title">服务中心</text>
-            <text class="service-center-desc">待处理任务:{{ pendingTasks }} 条 · 消息:{{ unreadMessages }} 条</text>
-          </view>
-          <text class="service-center-arrow">›</text>
-        </view>
-      </view>
-
-      <!-- 规划师待审核提示 -->
-      <view class="service-center-section" v-if="role === 'teacher' && teacherStatus !== 'approved'">
-        <view class="service-center-card disabled-card">
-          <view class="service-center-icon">👨‍🏫</view>
-          <view class="service-center-info">
-            <text class="service-center-title">服务中心</text>
-            <text class="service-center-desc">{{ teacherStatus === 'pending' ? '申请审核中,暂未开放' : teacherStatus === 'rejected' ? '申请未通过,请联系管理员' : '规划师服务' }}</text>
-          </view>
-        </view>
-      </view>
-
-      <!-- 设置 + 退出 -->
-      <view class="bottom-menu-section">
-        <view class="menu-row" @click="goToMessageHistory">
-          <text class="menu-row-icon">📨</text>
-          <text class="menu-row-text">历史消息</text>
-          <text class="menu-row-arrow">›</text>
-        </view>
-        <view class="menu-row" @click="goToSettings">
-          <text class="menu-row-icon">⚙️</text>
-          <text class="menu-row-text">设置</text>
-          <text class="menu-row-arrow">›</text>
-        </view>
-        <view class="logout-btn" @click="logout">
-          <text class="logout-text">退出登录</text>
-        </view>
-      </view>
-
-      </template>
-    <!-- 我的分享海报:复用文章/活动/商品同一套 ContentSharePoster 组件(canvas 绘制 + 保存到相册) -->
-    <ContentSharePoster
-      :show="showSharePoster"
-      :title="shareHeadline"
-      :energyData="posterEnergyData"
-      :brandFallback="true"
-      :qrCodeBase64="posterQrCode || ''"
-      typeLabel="邀友加入"
-      :summary="posterSummary"
-      ctaText="长按识别二维码 · 加入浠艾福"
-      :inviteText="posterInviteText"
-      @close="closeSharePoster"
-    />
-    <FloatingAvatar />
-  </view>
-</template>
-
-<script>
-import FloatingAvatar from '../../components/AIFloatingAvatar.vue'
-import ContentSharePoster from '../../components/ContentSharePoster.vue'
-import {
-  getChildren, getFamilyMemberList,
-  getTodayTasksByCategory, getChallengeList, getMyMembership,
-  verifyPassword, getPointsBalance, getUserInfo,
-  cartCount, getOrderCounts, getReferralSummary,
-  getProfileStats, getMyReferrer, getTeamConsumption,
-  getTeacherInfo, getTeacherPendingTasks, getTeacherUnreadCount,
-  getReferralCode, extractReferralCode, getShareQrCode, getEnergySandbox,
-  vendorStatus
-} from '../../utils/api.js'
-import { BrandColors } from '../../utils/brand-colors.js'
-
-export default {
-  components: { FloatingAvatar, ContentSharePoster },
-  data() {
-    return {
-      nickname: '',
-      role: 'parent',
-      isSwitchedChild: false,
-      userInfo: {},
-      memberLevel: null,
-      membershipDays: 0,
-      totalPoints: 0,
-      referralEarnings: 0,
-      teamMembers: 0,
-      // 个人成就
-      completedTasks: 0,
-      streakDays: 0,
-      rewardsEarned: 0,
-      badgesCollected: 0,
-      growthRecords: 0,
-      challengesJoined: 0,
-      healthReports: 0,
-      // 家庭
-      familyMembers: [],
-      // 商城
-      orderPending: 0,
-      orderUnpaid: 0,
-      orderShipped: 0,
-      orderAfterSale: 0,
-      cartCount: 0,
-      // 待办
-      pendingTasks: 0,
-      unreadMessages: 0,
-      teacherStatus: 'pending',
-      isVendor: false,
-      profileProgress: 0,
-      myReferrer: null,
-      // 分享推广码
-      showSharePoster: false,
-      referralCode: '',
-      posterQrCode: '',
-      posterEnergyData: null,
-      referralCodeLoaded: false,
-    }
-  },
-  computed: {
-    isLoggedIn() {
-      return !!uni.getStorageSync('token')
-    },
-    roleLabel() {
-      var map = { parent: '', child: '成员', teacher: '规划师' }
-      return map[this.role] || '用户'
-    },
-    memberLevelText() {
-      var map = { FREE: '免费用户', BASIC: '体验会员', FAMILY: '家庭会员', PREMIUM: '高级会员', LIFETIME: '终身会员' }
-      return map[this.memberLevel] || this.memberLevel || ''
-    },
-    isLifetime() {
-      return this.memberLevel === 'LIFETIME'
-    },
-    hasUpgradeSpace() {
-      return this.memberLevel === 'FREE' || this.memberLevel === 'FAMILY'
-    },
-    upgradeBtnText() {
-      return this.hasUpgradeSpace ? '升级' : '立即开通'
-    },
-    // 分享海报标题:XXX邀请你关注家庭健康(昵称过长自动截断)
-    shareHeadline() {
-      var name = (this.nickname || '').trim()
-      if (!name) return '邀请你关注家庭健康'
-      if (name.length > 8) name = name.substring(0, 8) + '…'
-      return name + '邀请你关注家庭健康'
-    },
-    posterSummary() {
-      return '身体 · 心理 · 智慧 · 行动 · 财富,一家专注全家健康的成长平台'
-    },
-    posterInviteText() {
-      var name = (this.nickname || '').trim()
-      if (!name) return '扫码加入浠艾福,一起照顾好这个家'
-      if (name.length > 8) name = name.substring(0, 8) + '…'
-      return '「' + name + '」邀请你加入浠艾福'
-    }
-  },
-  onShow() {
-    if (!this.isLoggedIn) {
-      return
-    }
-    var role = uni.getStorageSync('currentRole') || uni.getStorageSync('role') || 'parent'
-    this.role = role
-    this.isSwitchedChild = uni.getStorageSync('isSwitchedChild') || false
-    this.nickname = (uni.getStorageSync('userInfo') || {}).nickname || ''
-
-    // 服务商身份判断(成就区「我的团队」入口按此分发)
-    this.checkVendorStatus()
-
-    // 规划师加载额外数据
-    if (role === 'teacher') {
-      this.loadTeacherStatus()
-      this.loadTeacherData()
-    } else {
-      this.loadAllData()
-      this.loadMyReferrer()
-    }
-  },
-  methods: {
-    // 服务商身份:vendorStatus 返回 approved 即为已通过审核的服务商
-    checkVendorStatus() {
-      var self = this
-      vendorStatus().then(function(res) {
-        self.isVendor = !!(res && res.data && res.data.vendorStatus === 'approved')
-      }).catch(function() {
-        self.isVendor = false
-      })
-    },
-    loadTeacherStatus() {
-      var self = this
-      getTeacherInfo().then(function(res) {
-        if (res && res.code === 200 && res.data) {
-          self.teacherStatus = res.data.verificationStatus || res.data.status || 'pending'
-        }
-      }).catch(function() {})
-    },
-    loadTeacherData() {
-      var self = this
-      // 并行加载待处理任务和未读消息
-      getTeacherPendingTasks().then(function(res) {
-        if (res && res.data && Array.isArray(res.data)) {
-          self.pendingTasks = res.data.length
-        } else if (res && res.data && res.data.pendingCount != null) {
-          self.pendingTasks = res.data.pendingCount
-        }
-      }).catch(function() {})
-      getTeacherUnreadCount().then(function(res) {
-        if (res && res.data != null) {
-          self.unreadMessages = res.data
-        }
-      }).catch(function() {})
-    },
-    loadAllData() {
-      this.loadUserInfo()
-      this.loadMembership()
-      this.loadPoints()
-      this.loadFamily()
-      this.loadTasks()
-      this.loadChallenges()
-      this.loadOrderCounts()
-      this.loadCartCount()
-      this.loadProfileStats()
-      this.loadReferralEarnings()
-      this.loadTeamInfo()
-    },
-    loadUserInfo() {
-      var self = this
-      getUserInfo().then(function(res) {
-        if (res && res.code === 200 && res.data) {
-          self.userInfo = res.data
-          if (!self.nickname) self.nickname = res.data.nickname || ''
-        }
-      }).catch(function() {})
-    },
-    loadMembership() {
-      var self = this
-      getMyMembership().then(function(res) {
-        if (res && res.data) {
-          self.memberLevel = res.data.memberLevel || res.data.levelCode || null
-          self.membershipDays = res.data.membershipDays || res.data.daysRemaining || 0
-        }
-      }).catch(function() {})
-    },
-    loadPoints() {
-      // 累计积分由 loadProfileStats 汇总家庭成员积分,此处不再单独覆盖
-    },
-    loadFamily() {
-      var self = this
-      getFamilyMemberList({ visibleOnly: true }).then(function(res) {
-        var data = res && res.data ? res.data : []
-        self.familyMembers = Array.isArray(data) ? data : []
-      }).catch(function() {
-        self.familyMembers = []
-      })
-    },
-    loadTasks() {
-      var self = this
-      var memberId = uni.getStorageSync('currentChildId') || uni.getStorageSync('userId')
-      if (!memberId) return
-      getTodayTasksByCategory(memberId, 'action').then(function(res) {
-        if (res && res.data) {
-          self.pendingTasks = Array.isArray(res.data) ? res.data.length : 0
-        }
-      }).catch(function() {})
-      // fallback to storage
-      if (!self.pendingTasks) {
-        self.pendingTasks = parseInt(uni.getStorageSync('pendingTaskCount') || 0)
-      }
-    },
-    loadChallenges() {
-      var self = this
-      getChallengeList({}).then(function(res) {
-        if (res && res.data) {
-          // 不在此处使用,仅确保请求
-        }
-      }).catch(function() {})
-    },
-    loadOrderCounts() {
-      var self = this
-      getOrderCounts().then(function(res) {
-        if (res && res.data) {
-          self.orderPending = res.data.pending || 0
-          self.orderUnpaid = res.data.paid || 0
-          self.orderShipped = res.data.shipped || 0
-          self.orderAfterSale = res.data.refunding || 0
-        }
-      }).catch(function() {})
-    },
-    loadCartCount() {
-      var self = this
-      cartCount().then(function(res) {
-        if (res && res.data != null) {
-          self.cartCount = res.data || 0
-        }
-      }).catch(function() {})
-    },
-    loadProfileStats() {
-      var self = this
-      getProfileStats().then(function(res) {
-        if (res && res.code === 200 && res.data) {
-          var d = res.data
-          if (d.totalPoints != null) self.totalPoints = d.totalPoints
-          if (d.streakDays != null) self.streakDays = d.streakDays
-          if (d.completedTasks != null) self.completedTasks = d.completedTasks
-          if (d.rewardsEarned != null) self.rewardsEarned = d.rewardsEarned
-          if (d.badgesCollected != null) self.badgesCollected = d.badgesCollected
-          if (d.growthRecords != null) self.growthRecords = d.growthRecords
-          if (d.challengesJoined != null) self.challengesJoined = d.challengesJoined
-          if (d.healthReports != null) self.healthReports = d.healthReports
-        }
-      }).catch(function() {})
-    },
-
-    loadReferralEarnings() {
-      var self = this
-      getReferralSummary().then(function(res) {
-        if (res && res.code === 200 && res.data) {
-          self.referralEarnings = res.data.totalEarnings || 0
-        }
-      }).catch(function() {})
-    },
-    loadTeamInfo() {
-      var self = this
-      getTeamConsumption(3).then(function(res) {
-        if (res && res.data && res.data.totalMembers != null) {
-          self.teamMembers = res.data.totalMembers
-        }
-      }).catch(function() {})
-    },
-    async loadMyReferrer() {
-      try {
-        var memberId = uni.getStorageSync('currentMemberId') || uni.getStorageSync('currentChildId') || 0
-        var res = await getMyReferrer(memberId)
-        if (res && res.code === 200 && res.data && res.data.hasReferrer) {
-          this.myReferrer = res.data
-        }
-      } catch (e) {
-        console.error('获取推荐人失败', e)
-      }
-    },
-    // ===== 分享海报(复用 ContentSharePoster,与文章/活动/商品同一套生成逻辑)=====
-    async showShareQr() {
-      uni.showLoading({ title: '生成海报中...' })
-      try {
-        if (!this.referralCodeLoaded) {
-          await this.loadReferralCode()
-        }
-        var scene = 'ref=' + (this.referralCode || '')
-        if (scene.length > 32) {
-          scene = scene.substring(0, 32)
-        }
-        // 首页路径,扫码后进入首页并绑定推荐人
-        // 注意:微信 getwxacodeunlimit 的 page 不能带前导斜杠,否则报 errcode 41030 invalid page rid
-        var res = await getShareQrCode('pages/index-home/index', scene)
-        if (res && res.code === 200 && res.data && res.data.qrCodeBase64) {
-          this.posterQrCode = res.data.qrCodeBase64
-          // 必须在 showSharePoster=true 之前取到数据:组件 watch 到 show 后 300ms 即开始绘制
-          await this.loadPosterEnergy()
-          this.showSharePoster = true
-        } else {
-          uni.showToast({ title: '生成失败,请重试', icon: 'none' })
-        }
-      } catch (e) {
-        console.error('生成分享海报失败', e)
-        uni.showToast({ title: '生成失败,请重试', icon: 'none' })
-      } finally {
-        uni.hideLoading()
-      }
-    },
-    closeSharePoster() {
-      this.showSharePoster = false
-    },
-    // 五维能量数据卡数据(方案C):家庭聚合视角;未解锁全景/取数失败时置空,海报降级为品牌卡
-    loadPosterEnergy() {
-      var self = this
-      return getEnergySandbox('family').then(function(res) {
-        self.posterEnergyData = self.mapPosterEnergy(res)
-      }).catch(function(e) {
-        console.error('获取五维能量失败,海报降级为品牌卡', e)
-        self.posterEnergyData = null
-      })
-    },
-    mapPosterEnergy(res) {
-      if (!res || res.code !== 200 || !res.data) return null
-      // locked=true 表示用户未解锁全景,此时不展示任何数据,改为品牌卡
-      if (res.data.locked) return null
-      // 只认家庭聚合视角;仅当接口返回的是裸 DTO(无 personalData/familyData 包装)时才直接取 res.data
-      var d = res.data.familyData || null
-      if (!d) {
-        if (res.data.personalData) return null
-        d = res.data
-      }
-      if (!d || typeof d !== 'object') return null
-      var defs = [
-        { key: 'body', label: '身', color: BrandColors.body },
-        { key: 'mind', label: '心', color: BrandColors.mind },
-        { key: 'wisdom', label: '智', color: BrandColors.wisdom },
-        { key: 'action', label: '行', color: BrandColors.action },
-        { key: 'wealth', label: '富', color: BrandColors.wealth }
-      ]
-      var dims = []
-      var sum = 0
-      for (var i = 0; i < defs.length; i++) {
-        var raw = d[defs[i].key + 'Score']
-        if (raw === null || raw === undefined || raw === '' || isNaN(raw)) continue
-        var n = Number(raw)
-        if (n < 0) n = 0
-        if (n > 100) n = 100
-        sum += n
-        dims.push({ key: defs[i].key, label: defs[i].label, score: n, color: defs[i].color })
-      }
-      if (dims.length === 0) return null
-      var overall = d.overallScore
-      if (overall === null || overall === undefined || overall === '' || isNaN(overall)) {
-        overall = Math.round(sum / dims.length)
-      }
-      return { label: '我们家的能量', overall: Number(overall), dims: dims }
-    },
-
-    async loadReferralCode() {
-      if (this.referralCodeLoaded) return
-      var self = this
-      try {
-        var res = await getReferralCode()
-        self.referralCode = extractReferralCode(res) || ''
-      } catch (e) {
-        console.error('获取推广码失败', e)
-      } finally {
-        self.referralCodeLoaded = true
-      }
-    },
-    goToServiceCenter() {
-      uni.navigateTo({ url: '/pages/service-center/index' })
-    },
-    goTeamTree() {
-      // 服务商 → 服务商团队;非服务商 → 引导申请
-      if (this.isVendor) {
-        uni.navigateTo({ url: '/pages/vendor/team-system/team-system' })
-        return
-      }
-      uni.showModal({
-        title: '提示',
-        content: '您尚未申请任何服务角色,是否立即申请?',
-        confirmText: '去申请',
-        cancelText: '取消',
-        success: function(res) {
-          if (res.confirm) {
-            uni.navigateTo({ url: '/pages/profile/service-role-apply' })
-          }
-        }
-      })
-    },
-    goLogin: function() {
-      this.openLoginSheet()
-    },
-    // 登录浮层成功回调:刷新个人资料与登录后数据
-    onLoginSuccess: function() {
-      if (this.loadUserInfo) this.loadUserInfo()
-    },
-    goSkip: function() {
-      uni.switchTab({ url: '/pages/index-home/index' })
-    },
-    goToEditInfo: function() {
-      uni.navigateTo({ url: '/pages/user-edit/user-edit' })
-    },
-    goToPoints: function() {
-      uni.navigateTo({ url: '/pages/points/points' })
-    },
-    goToStreak: function() {
-      var memberId = uni.getStorageSync('currentMemberId') || uni.getStorageSync('currentChildId')
-      var url = '/pages/stats/completion-rate'
-      if (memberId) {
-        url += '?memberId=' + memberId
-      } else {
-        url += '?familyView=1'
-      }
-      uni.navigateTo({ url: url })
-    },
-    goToTasks: function() {
-      uni.navigateTo({ url: '/pages/tasks/tasks' })
-    },
-    goToWishes: function() {
-      uni.navigateTo({ url: '/pages/wishes/index' })
-    },
-    goToBadges: function() {
-      uni.navigateTo({ url: '/pages/rewards/badge' })
-    },
-    goToGrowth: function() {
-      uni.navigateTo({ url: '/pages/growth-main/index' })
-    },
-    goToChallenges: function() {
-      uni.navigateTo({ url: '/pages/health/challenge-manage' })
-    },
-    goToHealthReports: function() {
-      uni.navigateTo({ url: '/pages/health/report-list' })
-    },
-    goToWealthCenter: function() {
-      uni.navigateTo({ url: '/pages/promotion/index' })
-    },
-    goUpgrade: function() {
-      uni.navigateTo({ url: '/pages/membership/upgrade' })
-    },
-    goToFamily: function() {
-      uni.navigateTo({ url: '/pages/profile-extra/family-members' })
-    },
-    goMemberDetail: function(member) {
-      uni.navigateTo({ url: '/pages/home-pages/member-home-detail?memberId=' + member.id })
-    },
-    goToAppointments: function() {
-      uni.navigateTo({ url: '/pages/parent/appointments' })
-    },
-    goToOrders: function() {
-      uni.navigateTo({ url: '/pages/shop/order-list/order-list' })
-    },
-    goToOrderStatus: function(status) {
-      uni.navigateTo({ url: '/pages/shop/order-list/order-list?status=' + status })
-    },
-    goToCart: function() {
-      uni.navigateTo({ url: '/pages/shop/cart/cart' })
-    },
-    goToAddress: function() {
-      uni.navigateTo({ url: '/pages/shop/address/address' })
-    },
-    goToMessageHistory: function() {
-      uni.navigateTo({ url: '/pages/profile/message-history' })
-    },
-    goToSettings: function() {
-      uni.showActionSheet({
-        itemList: ['完善信息', '家庭成员', '隐私政策', '用户协议', '我的画像', '提醒设置'],
-        success: function(res) {
-          var urls = {
-            0: '/pages/user-edit/user-edit',
-            1: '/pages/profile-extra/family-members',
-            2: '/pages/policy/privacy',
-            3: '/pages/policy/agreement',
-            4: '/pages/profile/portrait-edit',
-            5: '/pages/reminder-config/index'
-          }
-          if (urls[res.tapIndex]) {
-            uni.navigateTo({ url: urls[res.tapIndex] })
-          }
-        }
-      })
-    },
-    memberRoleLabel: function(role) {
-      var map = { parent: '家长', child: '成员', teacher: '规划师' }
-      return map[role] || '成员'
-    },
-    onExitSwitch: function() {
-      var self = this
-      uni.showModal({
-        title: '退出切换',
-        content: '请输入家长密码以确认退出',
-        editable: true,
-        success: function(res) {
-          if (res.confirm && res.content) {
-            verifyPassword(res.content).then(function(result) {
-              if (result.code === 200) {
-                self.$store.commit('switchBackToParent')
-                self.isSwitchedChild = false
-                self.role = 'parent'
-                uni.showToast({ title: '已退出切换', icon: 'success' })
-                uni.reLaunch({ url: '/pages/index-home/index' })
-              } else {
-                uni.showToast({ title: '密码错误', icon: 'none' })
-              }
-            }).catch(function() {
-              uni.showToast({ title: '验证失败', icon: 'none' })
-            })
-          }
-        }
-      })
-    },
-    logout: function() {
-      uni.showModal({
-        title: '确认退出',
-        content: '确定要退出登录吗?',
-        success: function(res) {
-          if (res.confirm) {
-            this.$store.commit('logout')
-            uni.reLaunch({ url: '/pages/index-home/index' })
-          }
-        }.bind(this)
-      })
-    }
-  }
-}
-</script>
-
-<style scoped lang="scss">
-// ===== 页面级局部调色板(单页专有色阶;同值才映射全局令牌,约定见 uni.scss §14) =====
-$c-text-gray-400:   $facade-text-gray-400;
-$c-fill-2b:         #F2F2F2;

-.container {
-  min-height: 100vh;
-  background: $facade-fill-warm-gray;
-  padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
-}
-
-/* 登录引导 */
-.login-prompt {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding: 200rpx 60rpx;
-}
-.prompt-icon { font-size: 100rpx; margin-bottom: 30rpx; }
-.prompt-title { font-size: 40rpx; font-weight: bold; color: $facade-text-strong; margin-bottom: 16rpx; }
-.prompt-desc { font-size: 26rpx; color: $facade-text-muted; margin-bottom: 20rpx; }
-.login-btn {
-  background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
-  color: $app-surface;
-  border-radius: 50rpx;
-  font-size: 30rpx;
-  padding: 24rpx 80rpx;
-}
-.skip-link {
-  font-size: 26rpx;
-  color: $facade-text-muted;
-  margin-top: 24rpx;
-  text-decoration: underline;
-}
-.philosophy-card {
-  margin: 0 40rpx 48rpx;
-  background: linear-gradient(135deg, $facade-brand-tint, rgba($brand-primary, 0.06));
-  border-radius: 20rpx;
-  padding: 28rpx 32rpx;
-  border-left: 6rpx solid $brand-primary;
-}
-.philosophy-title {
-  font-size: 28rpx;
-  font-weight: bold;
-  color: $facade-text-strong;
-  display: block;
-  margin-bottom: 8rpx;
-}
-.philosophy-desc {
-  font-size: 24rpx;
-  color: $facade-text-faint;
-  line-height: 1.6;
-  display: block;
-}
-
-/* 退出切换 */
-.exit-switch {
-  margin: 0 30rpx 16rpx;
-  background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
-  color: $app-surface;
-  padding: 16rpx;
-  border-radius: 12rpx;
-  text-align: center;
-  font-size: 26rpx;
-}
-
-/* 身份卡 */
-.user-card {
-  margin: 24rpx 30rpx 20rpx;
-  background: linear-gradient(135deg, $brand-primary 0%, $brand-primary-light 100%);
-  border-radius: 24rpx;
-  padding: 32rpx 32rpx;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  box-shadow: 0 8rpx 32rpx rgba($accent-indigo, 0.3);
-}
-.user-card-left {
-  display: flex;
-  align-items: center;
-  flex: 1;
-}
-.avatar-wrap {
-  width: 100rpx;
-  height: 100rpx;
-  border-radius: 50%;
-  background: rgba($app-surface, 0.2);
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-right: 20rpx;
-  overflow: hidden;
-  border: 3rpx solid rgba($app-surface, 0.3);
-}
-.avatar-img {
-  width: 100rpx;
-  height: 100rpx;
-  border-radius: 50%;
-}
-.avatar-text {
-  font-size: 44rpx;
-  color: $app-surface;
-}
-.user-meta { flex: 1; }
-.user-name-row {
-  display: flex;
-  align-items: center;
-  gap: 12rpx;
-  margin-bottom: 8rpx;
-}
-.nickname {
-  font-size: 34rpx;
-  font-weight: bold;
-  color: $app-surface;
-}
-.role-tag {
-  font-size: 20rpx;
-  background: rgba($app-surface, 0.2);
-  color: $app-surface;
-  padding: 4rpx 14rpx;
-  border-radius: 20rpx;
-}
-.referrer-line {
-  font-size: 24rpx;
-  color: rgba($app-surface, 0.7);
-  margin-bottom: 6rpx;
-}
-.user-sub {
-  display: flex;
-  align-items: center;
-  gap: 12rpx;
-}
-.level-badge {
-  font-size: 22rpx;
-  padding: 6rpx 20rpx;
-  border-radius: 22rpx;
-  font-weight: bold;
-  border: 2rpx solid rgba($app-surface, 0.35);
-  display: flex;
-  align-items: center;
-  gap: 6rpx;
-  box-sizing: border-box;
-  height: 40rpx;
-}
-.level-badge::before {
-  content: '👑';
-  font-size: 18rpx;
-}
-.level-FREE { background: linear-gradient(135deg, $c-text-gray-400, $facade-text-slate); color: $app-surface; }
-.level-FREE::before { content: ''; }
-.level-FAMILY { background: linear-gradient(135deg, $dim-wealth, $status-warning-deep); color: $app-surface; }
-.level-PREMIUM { background: linear-gradient(135deg, $dim-wisdom, $dim-wisdom-deep); color: $app-surface; }
-.level-LIFETIME {
-  background: linear-gradient(135deg, $accent-pink, $accent-pink-deep);
-  color: $app-surface;
-  box-shadow: 0 4rpx 16rpx rgba($accent-pink, 0.45);
-  border-color: rgba($app-surface, 0.55);
-}
-.days-left {
-  font-size: 20rpx;
-  color: rgba($app-surface, 0.85);
-}
-.upgrade-btn {
-  background: rgba($app-surface, 0.22);
-  border: 2rpx solid rgba($app-surface, 0.6);
-  border-radius: 20rpx;
-  padding: 6rpx 20rpx;
-  flex-shrink: 0;
-  box-sizing: border-box;
-  height: 40rpx;
-  display: flex;
-  align-items: center;
-}
-.upgrade-btn-text {
-  font-size: 20rpx;
-  font-weight: bold;
-  color: $app-surface;
-  line-height: 1;
-}
-.user-card-right {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  gap: 6rpx;
-  background: rgba($app-surface, 0.15);
-  padding: 12rpx 24rpx;
-  border-radius: 14rpx;
-}
-.points-num {
-  font-size: 36rpx;
-  font-weight: bold;
-  color: $app-surface;
-}
-.points-label {
-  font-size: 20rpx;
-  color: rgba($app-surface, 0.7);
-}
-
-/* 家庭成员速览 */
-.family-strip {
-  margin: 0 30rpx 20rpx;
-  background: $app-surface;
-  border-radius: 20rpx;
-  padding: 20rpx 24rpx 16rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
-}
-.family-strip-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 14rpx;
-}
-.family-strip-title {
-  font-size: 26rpx;
-  font-weight: bold;
-  color: $facade-text-strong;
-}
-.family-strip-count {
-  font-size: 22rpx;
-  color: $facade-text-muted;
-}
-.family-avatars {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  gap: 16rpx;
-  overflow-x: auto;
-  padding-bottom: 4rpx;
-}
-.family-avatar-item {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  gap: 6rpx;
-  flex-shrink: 0;
-}
-.family-avatar-wrap {
-  width: 72rpx;
-  height: 72rpx;
-  border-radius: 50%;
-  background: $facade-fill;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  overflow: hidden;
-  position: relative;
-}
-.family-avatar-img {
-  width: 72rpx;
-  height: 72rpx;
-  border-radius: 50%;
-}
-.family-avatar-text {
-  font-size: 28rpx;
-  color: $facade-text-body;
-}
-.family-avatar-wrap.family-avatar-add {
-  background: $facade-fill-warm-gray;
-  border: 2rpx dashed $facade-text-ghost;
-}
-.family-avatar-plus {
-  font-size: 36rpx;
-  color: $facade-text-muted;
-}
-.family-avatar-tag {
-  position: absolute;
-  bottom: -4rpx;
-  right: -4rpx;
-  font-size: 14rpx;
-  padding: 2rpx 6rpx;
-  border-radius: 8rpx;
-  color: $app-surface;
-}
-.family-avatar-tag.tag-parent { background: $dim-wisdom; }
-.family-avatar-tag.tag-child { background: $brand-primary; }
-.family-avatar-tag.tag-teacher { background: $dim-action; }
-.family-avatar-tag.tag-member { background: $c-text-gray-400; }
-.family-avatar-name {
-  font-size: 20rpx;
-  color: $facade-text-body;
-  white-space: nowrap;
-}
-
-/* 个人成就 */
-.achievement-section {
-  margin: 0 30rpx 20rpx;
-  background: $app-surface;
-  border-radius: 20rpx;
-  padding: 24rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
-}
-.section-header-row {
-  display: flex;
-  justify-content: space-between;
-  align-items: baseline;
-  margin-bottom: 16rpx;
-}
-.section-title {
-  font-size: 28rpx;
-  font-weight: bold;
-  color: $facade-text-strong;
-}
-.section-sub {
-  font-size: 22rpx;
-  color: $facade-text-muted;
-}
-.achievement-grid {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 0;
-}
-.ach-item {
-  width: 25%;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  gap: 6rpx;
-  padding: 10rpx 0;
-}
-.ach-icon-wrap {
-  width: 64rpx;
-  height: 64rpx;
-  border-radius: 50%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-bottom: 4rpx;
-}
-.ach-icon {
-  font-size: 32rpx;
-  line-height: 1;
-}
-.ach-num {
-  font-size: 28rpx;
-  font-weight: bold;
-  color: $facade-text-strong;
-  line-height: 1;
-}
-.ach-label {
-  font-size: 20rpx;
-  color: $facade-text-muted;
-  line-height: 1;
-}
-
-/* 我的订单(电商风格) */
-.order-section {
-  margin: 0 30rpx 20rpx;
-}
-.order-section-header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  margin-bottom: 14rpx;
-}
-.order-all-link {
-  font-size: 24rpx;
-  color: $facade-text-muted;
-}
-.order-card {
-  background: $app-surface;
-  border-radius: 20rpx;
-  padding: 24rpx 12rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
-}
-.order-grid {
-  display: flex;
-  flex-wrap: wrap;
-}
-.order-grid-item {
-  width: 20%;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  gap: 10rpx;
-  padding: 8rpx 0;
-}
-.order-icon-wrap {
-  position: relative;
-  width: 64rpx;
-  height: 64rpx;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-.order-icon {
-  font-size: 40rpx;
-  line-height: 1;
-}
-.order-badge {
-  position: absolute;
-  top: -8rpx;
-  right: -14rpx;
-  min-width: 30rpx;
-  height: 30rpx;
-  line-height: 30rpx;
-  border-radius: 15rpx;
-  background: $status-danger-2;
-  color: $app-surface;
-  font-size: 18rpx;
-  text-align: center;
-  padding: 0 6rpx;
-}
-.order-grid-text {
-  font-size: 22rpx;
-  color: $facade-text-body;
-  line-height: 1;
-}
-.order-extra-row {
-  display: flex;
-  align-items: center;
-  margin-top: 20rpx;
-  padding-top: 20rpx;
-  border-top: 1rpx solid $c-fill-2b;
-}
-.order-extra-item {
-  flex: 1;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  gap: 8rpx;
-}
-.order-extra-icon {
-  font-size: 28rpx;
-}
-.order-extra-text {
-  font-size: 24rpx;
-  color: $facade-text-strong;
-}
-.order-extra-badge {
-  min-width: 30rpx;
-  height: 30rpx;
-  line-height: 30rpx;
-  border-radius: 15rpx;
-  background: $brand-primary;
-  color: $app-surface;
-  font-size: 18rpx;
-  text-align: center;
-  padding: 0 6rpx;
-}
-.order-extra-divider {
-  width: 1rpx;
-  height: 30rpx;
-  background: $c-fill-2b;
-}
-
-/* 规划师服务中心入口 */
-.service-center-section {
-  margin: 0 30rpx 20rpx;
-}
-.service-center-card {
-  background: linear-gradient(135deg, $brand-primary 0%, $brand-primary-light 100%);
-  border-radius: 20rpx;
-  padding: 24rpx;
-  display: flex;
-  align-items: center;
-  gap: 20rpx;
-  box-shadow: 0 4rpx 16rpx rgba($brand-primary, 0.25);
-}
-.service-center-card.disabled-card {
-  background: linear-gradient(135deg, $uni-border-color-light, $app-text-subtle);
-  box-shadow: none;
-  opacity: 0.8;
-}
-.service-center-icon {
-  font-size: 48rpx;
-}
-.service-center-info {
-  flex: 1;
-}
-.service-center-title {
-  font-size: 30rpx;
-  font-weight: bold;
-  color: $app-surface;
-  display: block;
-}
-.service-center-desc {
-  font-size: 22rpx;
-  color: rgba($app-surface, 0.8);
-  margin-top: 6rpx;
-  display: block;
-}
-.service-center-card.disabled-card .service-center-title {
-  color: $app-surface;
-}
-.service-center-card.disabled-card .service-center-desc {
-  color: rgba($app-surface, 0.9);
-}
-.service-center-arrow {
-  font-size: 40rpx;
-  color: $app-surface;
-}
-
-/* 设置 + 退出 */
-.bottom-menu-section {
-  margin: 0 30rpx;
-  padding-bottom: 20rpx;
-}
-.menu-row {
-  width: 100%;
-  background: $app-surface;
-  border-radius: 16rpx;
-  padding: 24rpx;
-  display: flex;
-  align-items: center;
-  gap: 14rpx;
-  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
-  margin-bottom: 20rpx;
-}
-.menu-row-icon {
-  font-size: 30rpx;
-}
-.menu-row-text {
-  flex: 1;
-  font-size: 26rpx;
-  color: $facade-text-strong;
-}
-.menu-row-arrow {
-  font-size: 28rpx;
-  color: $facade-text-ghost;
-}
-.logout-btn {
-  width: 100%;
-  background: $app-surface;
-  border-radius: 16rpx;
-  padding: 24rpx;
-  text-align: center;
-  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
-}
-.logout-text {
-  font-size: 26rpx;
-  color: $status-danger-2;
-  font-weight: 500;
-}
-
-/* 分享推广码浮动按钮 */
-.share-qr-float {
-  position: fixed;
-  top: 180rpx;
-  right: 30rpx;
-  width: 80rpx;
-  height: 80rpx;
-  border-radius: 50%;
-  background: $app-surface;
-  box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.15);
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  z-index: 99;
-}
-/* 二维码图标(纯 CSS 绘制,不依赖 emoji 字体) */
-.qr-glyph {
-  position: relative;
-  width: 46rpx;
-  height: 46rpx;
-}
-.qr-eye {
-  position: absolute;
-  width: 16rpx;
-  height: 16rpx;
-  border: 4rpx solid $uni-text-color;
-  border-radius: 3rpx;
-  box-sizing: border-box;
-}
-.qr-eye-tl { left: 0; top: 0; }
-.qr-eye-tr { right: 0; top: 0; }
-.qr-eye-bl { left: 0; bottom: 0; }
-.qr-mid {
-  position: absolute;
-  left: 20rpx;
-  top: 20rpx;
-  width: 7rpx;
-  height: 7rpx;
-  background: $uni-text-color;
-  border-radius: 1rpx;
-}
-.qr-cluster {
-  position: absolute;
-  right: 0;
-  bottom: 0;
-  width: 18rpx;
-  display: flex;
-  flex-wrap: wrap;
-}
-.qr-pip {
-  width: 7rpx;
-  height: 7rpx;
-  margin: 1rpx;
-  background: $uni-text-color;
-  border-radius: 1rpx;
-}
-</style>
+<template>
+  <view class="container" :style="{ '--font-scale': fontScale }">
+    <!-- 登录浮层(全局组件,页面内弹出底部登录) -->
+    <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
+    <!-- 未登录 -->
+    <view v-if="!isLoggedIn">
+      <view class="login-prompt">
+        <text class="prompt-icon">👤</text>
+        <text class="prompt-title">登录浠艾福</text>
+        <text class="prompt-desc">登录后查看个人资料、积分记录、能量数据与家庭管理</text>
+        <button class="login-btn" @click="goLogin">登录 / 注册</button>
+        <text class="skip-link" @click="goSkip">暂不登录,先逛逛 ›</text>
+      </view>
+
+      <view class="philosophy-card">
+        <text class="philosophy-title">照顾家庭,从照顾好自己开始</text>
+        <text class="philosophy-desc">你的状态,就是家的状态。先安顿好自己,才有余力温暖家人。</text>
+      </view>
+    </view>
+
+    <!-- 已登录 -->
+    <template v-else>
+      <!-- 退出切换 -->
+      <view class="exit-switch" v-if="isSwitchedChild" @click="onExitSwitch">
+        <text>🔄 退出切换</text>
+      </view>
+
+      <!-- 身份卡 -->
+      <view class="user-card">
+        <view class="user-card-left">
+          <view class="avatar-wrap" @click="goToEditInfo">
+            <image v-if="userInfo.avatar" class="avatar-img" :src="userInfo.avatar" mode="aspectFill" />
+            <text v-else class="avatar-text">{{ nickname.charAt(0) || '👤' }}</text>
+          </view>
+          <view class="user-meta">
+            <view class="user-name-row">
+              <text class="nickname">{{ nickname || '未设置昵称' }}</text>
+              <text v-if="roleLabel" class="role-tag">{{ roleLabel }}</text>
+            </view>
+            <view class="user-sub" v-if="memberLevel">
+              <view class="level-badge" :class="'level-' + memberLevel">{{ memberLevelText }}</view>
+              <text v-if="isLifetime" class="days-left">永久有效</text>
+              <text v-else-if="membershipDays > 0 && membershipDays <= 30" class="days-left">剩余 {{ membershipDays }} 天</text>
+              <view v-if="hasUpgradeSpace" class="upgrade-btn" @click="goUpgrade">
+                <text class="upgrade-btn-text">{{ upgradeBtnText }}</text>
+              </view>
+            </view>
+            <view class="user-sub" v-else>
+              <text class="days-left">开通会员解锁更多权益</text>
+              <view class="upgrade-btn" @click="goUpgrade">
+                <text class="upgrade-btn-text">立即开通</text>
+              </view>
+            </view>
+          </view>
+        </view>
+        <view class="user-card-right" @click="goToPoints">
+          <text class="points-num">{{ totalPoints }}</text>
+          <text class="points-label">积分</text>
+        </view>
+      </view>
+
+      <!-- 我的分享海报浮动按钮(纯 CSS 二维码图标,避免 emoji 渲染成计算器) -->
+      <view class="share-qr-float" @click="showShareQr">
+        <view class="qr-glyph">
+          <view class="qr-eye qr-eye-tl"></view>
+          <view class="qr-eye qr-eye-tr"></view>
+          <view class="qr-eye qr-eye-bl"></view>
+          <view class="qr-mid"></view>
+          <view class="qr-cluster">
+            <view class="qr-pip"></view>
+            <view class="qr-pip"></view>
+            <view class="qr-pip"></view>
+            <view class="qr-pip"></view>
+          </view>
+        </view>
+      </view>
+
+      <!-- 家族成员速览 -->
+      <view class="family-strip" v-if="familyMembers.length > 0">
+        <view class="family-strip-header">
+          <text class="family-strip-title">我的家庭</text>
+          <text class="family-strip-count">{{ familyMembers.length }} 位成员</text>
+        </view>
+        <view class="family-avatars">
+          <view
+            v-for="member in familyMembers"
+            :key="member.id"
+            class="family-avatar-item"
+            @click="goMemberDetail(member)"
+          >
+            <view class="family-avatar-wrap">
+              <image v-if="member.avatar" class="family-avatar-img" :src="member.avatar" mode="aspectFill" />
+              <text v-else class="family-avatar-text">{{ member.nickname ? member.nickname.charAt(0) : '?' }}</text>
+              <view class="family-avatar-tag" :class="'tag-' + (member.effectiveRole || member.source || 'member')">{{ member.roleLabel || memberRoleLabel(member.effectiveRole) }}</view>
+            </view>
+            <text class="family-avatar-name">{{ member.nickname || member.realName || '成员' }}</text>
+          </view>
+          <view class="family-avatar-item" @click="goToFamily">
+            <view class="family-avatar-wrap family-avatar-add">
+              <text class="family-avatar-plus">+</text>
+            </view>
+            <text class="family-avatar-name">添加</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 个人成就统计 -->
+      <view class="achievement-section">
+        <view class="section-header-row">
+          <text class="section-title">🏆 我的成就</text>
+          <text class="section-sub">持续成长,看见改变</text>
+        </view>
+        <view class="achievement-grid">
+          <view class="ach-item" @click="goToPoints">
+            <view class="ach-icon-wrap" style="background:rgba(249,115,22,0.12)">
+              <text class="ach-icon">💰</text>
+            </view>
+            <text class="ach-num">{{ totalPoints }}</text>
+            <text class="ach-label">累计积分</text>
+          </view>
+          <view class="ach-item" @click="goToStreak">
+            <view class="ach-icon-wrap" style="background:rgba(255,140,66,0.12)">
+              <text class="ach-icon">🔥</text>
+            </view>
+            <text class="ach-num">{{ streakDays }}</text>
+            <text class="ach-label">连续打卡</text>
+          </view>
+          <view class="ach-item" @click="goToTasks">
+            <view class="ach-icon-wrap" style="background:rgba(99,102,241,0.12)">
+              <text class="ach-icon">✅</text>
+            </view>
+            <text class="ach-num">{{ completedTasks }}</text>
+            <text class="ach-label">完成任务</text>
+          </view>
+          <view class="ach-item" @click="goToWishes">
+            <view class="ach-icon-wrap" style="background:rgba(245,158,11,0.12)">
+              <text class="ach-icon">🎁</text>
+            </view>
+            <text class="ach-num">{{ rewardsEarned }}</text>
+            <text class="ach-label">获得奖励</text>
+          </view>
+          <view class="ach-item" @click="goToBadges">
+            <view class="ach-icon-wrap" style="background:rgba(236,72,153,0.12)">
+              <text class="ach-icon">🏅</text>
+            </view>
+            <text class="ach-num">{{ badgesCollected }}</text>
+            <text class="ach-label">收集勋章</text>
+          </view>
+          <view class="ach-item" @click="goToGrowth">
+            <view class="ach-icon-wrap" style="background:rgba(16,185,129,0.12)">
+              <text class="ach-icon">📈</text>
+            </view>
+            <text class="ach-num">{{ growthRecords }}</text>
+            <text class="ach-label">成长记录</text>
+          </view>
+          <view class="ach-item" @click="goToChallenges">
+            <view class="ach-icon-wrap" style="background:rgba(255,107,157,0.12)">
+              <text class="ach-icon">🎯</text>
+            </view>
+            <text class="ach-num">{{ challengesJoined }}</text>
+            <text class="ach-label">参加挑战</text>
+          </view>
+          <view class="ach-item" @click="goToHealthReports">
+            <view class="ach-icon-wrap" style="background:rgba(14,165,233,0.12)">
+              <text class="ach-icon">📋</text>
+            </view>
+            <text class="ach-num">{{ healthReports }}</text>
+            <text class="ach-label">上传报告</text>
+          </view>
+          <view class="ach-item" @click="goToWealthCenter">
+            <view class="ach-icon-wrap" style="background:rgba(245,158,11,0.12)">
+              <text class="ach-icon">💰</text>
+            </view>
+            <text class="ach-num">{{ referralEarnings }}</text>
+            <text class="ach-label">推广收益</text>
+          </view>
+          <view class="ach-item" @click="goTeamTree">
+            <view class="ach-icon-wrap" style="background:rgba(16,185,129,0.12)">
+              <text class="ach-icon">🌳</text>
+            </view>
+            <text class="ach-num">{{ teamMembers }}</text>
+            <text class="ach-label">我的团队</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 我的订单(电商风格) -->
+      <view class="order-section">
+        <view class="order-section-header">
+          <text class="section-title">🛒 我的订单</text>
+          <text class="order-all-link" @click="goToOrders">全部订单 ›</text>
+        </view>
+        <view class="order-card">
+          <view class="order-grid">
+            <view class="order-grid-item" @click="goToOrderStatus('pending')">
+              <view class="order-icon-wrap">
+                <text class="order-icon">💳</text>
+                <text class="order-badge" v-if="orderPending > 0">{{ orderPending }}</text>
+              </view>
+              <text class="order-grid-text">待付款</text>
+            </view>
+            <view class="order-grid-item" @click="goToOrderStatus('paid')">
+              <view class="order-icon-wrap">
+                <text class="order-icon">📦</text>
+                <text class="order-badge" v-if="orderUnpaid > 0">{{ orderUnpaid }}</text>
+              </view>
+              <text class="order-grid-text">待发货</text>
+            </view>
+            <view class="order-grid-item" @click="goToOrderStatus('shipped')">
+              <view class="order-icon-wrap">
+                <text class="order-icon">🚚</text>
+                <text class="order-badge" v-if="orderShipped > 0">{{ orderShipped }}</text>
+              </view>
+              <text class="order-grid-text">待收货</text>
+            </view>
+            <view class="order-grid-item" @click="goToOrderStatus('refunding')">
+              <view class="order-icon-wrap">
+                <text class="order-icon">🔧</text>
+                <text class="order-badge" v-if="orderAfterSale > 0">{{ orderAfterSale }}</text>
+              </view>
+              <text class="order-grid-text">售后</text>
+            </view>
+            <view class="order-grid-item" @click="goToOrders">
+              <view class="order-icon-wrap">
+                <text class="order-icon">📋</text>
+              </view>
+              <text class="order-grid-text">全部</text>
+            </view>
+          </view>
+          <view class="order-extra-row">
+            <view class="order-extra-item" @click="goToCart">
+              <text class="order-extra-icon">🛒</text>
+              <text class="order-extra-text">购物车</text>
+              <text class="order-extra-badge" v-if="cartCount > 0">{{ cartCount > 99 ? '99+' : cartCount }}</text>
+            </view>
+            <view class="order-extra-divider"></view>
+            <view class="order-extra-item" @click="goToAddress">
+              <text class="order-extra-icon">📍</text>
+              <text class="order-extra-text">收货地址</text>
+            </view>
+          </view>
+        </view>
+      </view>
+
+      <!-- 规划师服务中心入口(仅规划师可见) -->
+      <view class="service-center-section" v-if="role === 'teacher' && teacherStatus === 'approved'">
+        <view class="service-center-card" @click="goToServiceCenter">
+          <view class="service-center-icon">👨‍🏫</view>
+          <view class="service-center-info">
+            <text class="service-center-title">服务中心</text>
+            <text class="service-center-desc">待处理任务:{{ pendingTasks }} 条 · 消息:{{ unreadMessages }} 条</text>
+          </view>
+          <text class="service-center-arrow">›</text>
+        </view>
+      </view>
+
+      <!-- 规划师待审核提示 -->
+      <view class="service-center-section" v-if="role === 'teacher' && teacherStatus !== 'approved'">
+        <view class="service-center-card disabled-card">
+          <view class="service-center-icon">👨‍🏫</view>
+          <view class="service-center-info">
+            <text class="service-center-title">服务中心</text>
+            <text class="service-center-desc">{{ teacherStatus === 'pending' ? '申请审核中,暂未开放' : teacherStatus === 'rejected' ? '申请未通过,请联系管理员' : '规划师服务' }}</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 设置 + 退出 -->
+      <view class="bottom-menu-section">
+        <view class="menu-row" @click="goToMessageHistory">
+          <text class="menu-row-icon">📨</text>
+          <text class="menu-row-text">历史消息</text>
+          <text class="menu-row-arrow">›</text>
+        </view>
+        <view class="menu-row" @click="goToSettings">
+          <text class="menu-row-icon">⚙️</text>
+          <text class="menu-row-text">设置</text>
+          <text class="menu-row-arrow">›</text>
+        </view>
+        <view class="logout-btn" @click="logout">
+          <text class="logout-text">退出登录</text>
+        </view>
+      </view>
+
+      </template>
+    <!-- 我的分享海报:复用文章/活动/商品同一套 ContentSharePoster 组件(canvas 绘制 + 保存到相册) -->
+    <ContentSharePoster
+      :show="showSharePoster"
+      :title="shareHeadline"
+      :energyData="posterEnergyData"
+      :brandFallback="true"
+      :qrCodeBase64="posterQrCode || ''"
+      typeLabel="邀友加入"
+      :summary="posterSummary"
+      ctaText="长按识别二维码 · 加入浠艾福"
+      :inviteText="posterInviteText"
+      @close="closeSharePoster"
+    />
+    <FloatingAvatar />
+  </view>
+</template>
+
+<script>
+import FloatingAvatar from '../../components/AIFloatingAvatar.vue'
+import ContentSharePoster from '../../components/ContentSharePoster.vue'
+import {
+  getChildren, getFamilyMemberList,
+  getTodayTasksByCategory, getChallengeList, getMyMembership,
+  verifyPassword, getPointsBalance, getUserInfo,
+  cartCount, getOrderCounts, getReferralSummary,
+  getProfileStats, getMyReferrer, getTeamConsumption,
+  getTeacherInfo, getTeacherPendingTasks, getTeacherUnreadCount,
+  getReferralCode, extractReferralCode, getShareQrCode, getEnergySandbox,
+  vendorStatus
+} from '../../utils/api.js'
+import { BrandColors } from '../../utils/brand-colors.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
+
+export default {
+  mixins: [fontScaleMixin],
+  components: { FloatingAvatar, ContentSharePoster },
+  data() {
+    return {
+      nickname: '',
+      role: 'parent',
+      isSwitchedChild: false,
+      userInfo: {},
+      memberLevel: null,
+      membershipDays: 0,
+      totalPoints: 0,
+      referralEarnings: 0,
+      teamMembers: 0,
+      // 个人成就
+      completedTasks: 0,
+      streakDays: 0,
+      rewardsEarned: 0,
+      badgesCollected: 0,
+      growthRecords: 0,
+      challengesJoined: 0,
+      healthReports: 0,
+      // 家庭
+      familyMembers: [],
+      // 商城
+      orderPending: 0,
+      orderUnpaid: 0,
+      orderShipped: 0,
+      orderAfterSale: 0,
+      cartCount: 0,
+      // 待办
+      pendingTasks: 0,
+      unreadMessages: 0,
+      teacherStatus: 'pending',
+      isVendor: false,
+      profileProgress: 0,
+      myReferrer: null,
+      // 分享推广码
+      showSharePoster: false,
+      referralCode: '',
+      posterQrCode: '',
+      posterEnergyData: null,
+      referralCodeLoaded: false,
+    }
+  },
+  computed: {
+    isLoggedIn() {
+      return !!uni.getStorageSync('token')
+    },
+    roleLabel() {
+      var map = { parent: '', child: '成员', teacher: '规划师' }
+      return map[this.role] || '用户'
+    },
+    memberLevelText() {
+      var map = { FREE: '免费用户', BASIC: '体验会员', FAMILY: '家庭会员', PREMIUM: '高级会员', LIFETIME: '终身会员' }
+      return map[this.memberLevel] || this.memberLevel || ''
+    },
+    isLifetime() {
+      return this.memberLevel === 'LIFETIME'
+    },
+    hasUpgradeSpace() {
+      return this.memberLevel === 'FREE' || this.memberLevel === 'FAMILY'
+    },
+    upgradeBtnText() {
+      return this.hasUpgradeSpace ? '升级' : '立即开通'
+    },
+    // 分享海报标题:XXX邀请你关注家庭健康(昵称过长自动截断)
+    shareHeadline() {
+      var name = (this.nickname || '').trim()
+      if (!name) return '邀请你关注家庭健康'
+      if (name.length > 8) name = name.substring(0, 8) + '…'
+      return name + '邀请你关注家庭健康'
+    },
+    posterSummary() {
+      return '身体 · 心理 · 智慧 · 行动 · 财富,一家专注全家健康的成长平台'
+    },
+    posterInviteText() {
+      var name = (this.nickname || '').trim()
+      if (!name) return '扫码加入浠艾福,一起照顾好这个家'
+      if (name.length > 8) name = name.substring(0, 8) + '…'
+      return '「' + name + '」邀请你加入浠艾福'
+    }
+  },
+  onShow() {
+    if (!this.isLoggedIn) {
+      return
+    }
+    var role = uni.getStorageSync('currentRole') || uni.getStorageSync('role') || 'parent'
+    this.role = role
+    this.isSwitchedChild = uni.getStorageSync('isSwitchedChild') || false
+    this.nickname = (uni.getStorageSync('userInfo') || {}).nickname || ''
+
+    // 服务商身份判断(成就区「我的团队」入口按此分发)
+    this.checkVendorStatus()
+
+    // 规划师加载额外数据
+    if (role === 'teacher') {
+      this.loadTeacherStatus()
+      this.loadTeacherData()
+    } else {
+      this.loadAllData()
+      this.loadMyReferrer()
+    }
+  },
+  methods: {
+    // 服务商身份:vendorStatus 返回 approved 即为已通过审核的服务商
+    checkVendorStatus() {
+      var self = this
+      vendorStatus().then(function(res) {
+        self.isVendor = !!(res && res.data && res.data.vendorStatus === 'approved')
+      }).catch(function() {
+        self.isVendor = false
+      })
+    },
+    loadTeacherStatus() {
+      var self = this
+      getTeacherInfo().then(function(res) {
+        if (res && res.code === 200 && res.data) {
+          self.teacherStatus = res.data.verificationStatus || res.data.status || 'pending'
+        }
+      }).catch(function() {})
+    },
+    loadTeacherData() {
+      var self = this
+      // 并行加载待处理任务和未读消息
+      getTeacherPendingTasks().then(function(res) {
+        if (res && res.data && Array.isArray(res.data)) {
+          self.pendingTasks = res.data.length
+        } else if (res && res.data && res.data.pendingCount != null) {
+          self.pendingTasks = res.data.pendingCount
+        }
+      }).catch(function() {})
+      getTeacherUnreadCount().then(function(res) {
+        if (res && res.data != null) {
+          self.unreadMessages = res.data
+        }
+      }).catch(function() {})
+    },
+    loadAllData() {
+      this.loadUserInfo()
+      this.loadMembership()
+      this.loadPoints()
+      this.loadFamily()
+      this.loadTasks()
+      this.loadChallenges()
+      this.loadOrderCounts()
+      this.loadCartCount()
+      this.loadProfileStats()
+      this.loadReferralEarnings()
+      this.loadTeamInfo()
+    },
+    loadUserInfo() {
+      var self = this
+      getUserInfo().then(function(res) {
+        if (res && res.code === 200 && res.data) {
+          self.userInfo = res.data
+          if (!self.nickname) self.nickname = res.data.nickname || ''
+        }
+      }).catch(function() {})
+    },
+    loadMembership() {
+      var self = this
+      getMyMembership().then(function(res) {
+        if (res && res.data) {
+          self.memberLevel = res.data.memberLevel || res.data.levelCode || null
+          self.membershipDays = res.data.membershipDays || res.data.daysRemaining || 0
+        }
+      }).catch(function() {})
+    },
+    loadPoints() {
+      // 累计积分由 loadProfileStats 汇总家庭成员积分,此处不再单独覆盖
+    },
+    loadFamily() {
+      var self = this
+      getFamilyMemberList({ visibleOnly: true }).then(function(res) {
+        var data = res && res.data ? res.data : []
+        self.familyMembers = Array.isArray(data) ? data : []
+      }).catch(function() {
+        self.familyMembers = []
+      })
+    },
+    loadTasks() {
+      var self = this
+      var memberId = uni.getStorageSync('currentChildId') || uni.getStorageSync('userId')
+      if (!memberId) return
+      getTodayTasksByCategory(memberId, 'action').then(function(res) {
+        if (res && res.data) {
+          self.pendingTasks = Array.isArray(res.data) ? res.data.length : 0
+        }
+      }).catch(function() {})
+      // fallback to storage
+      if (!self.pendingTasks) {
+        self.pendingTasks = parseInt(uni.getStorageSync('pendingTaskCount') || 0)
+      }
+    },
+    loadChallenges() {
+      var self = this
+      getChallengeList({}).then(function(res) {
+        if (res && res.data) {
+          // 不在此处使用,仅确保请求
+        }
+      }).catch(function() {})
+    },
+    loadOrderCounts() {
+      var self = this
+      getOrderCounts().then(function(res) {
+        if (res && res.data) {
+          self.orderPending = res.data.pending || 0
+          self.orderUnpaid = res.data.paid || 0
+          self.orderShipped = res.data.shipped || 0
+          self.orderAfterSale = res.data.refunding || 0
+        }
+      }).catch(function() {})
+    },
+    loadCartCount() {
+      var self = this
+      cartCount().then(function(res) {
+        if (res && res.data != null) {
+          self.cartCount = res.data || 0
+        }
+      }).catch(function() {})
+    },
+    loadProfileStats() {
+      var self = this
+      getProfileStats().then(function(res) {
+        if (res && res.code === 200 && res.data) {
+          var d = res.data
+          if (d.totalPoints != null) self.totalPoints = d.totalPoints
+          if (d.streakDays != null) self.streakDays = d.streakDays
+          if (d.completedTasks != null) self.completedTasks = d.completedTasks
+          if (d.rewardsEarned != null) self.rewardsEarned = d.rewardsEarned
+          if (d.badgesCollected != null) self.badgesCollected = d.badgesCollected
+          if (d.growthRecords != null) self.growthRecords = d.growthRecords
+          if (d.challengesJoined != null) self.challengesJoined = d.challengesJoined
+          if (d.healthReports != null) self.healthReports = d.healthReports
+        }
+      }).catch(function() {})
+    },
+
+    loadReferralEarnings() {
+      var self = this
+      getReferralSummary().then(function(res) {
+        if (res && res.code === 200 && res.data) {
+          self.referralEarnings = res.data.totalEarnings || 0
+        }
+      }).catch(function() {})
+    },
+    loadTeamInfo() {
+      var self = this
+      getTeamConsumption(3).then(function(res) {
+        if (res && res.data && res.data.totalMembers != null) {
+          self.teamMembers = res.data.totalMembers
+        }
+      }).catch(function() {})
+    },
+    async loadMyReferrer() {
+      try {
+        var memberId = uni.getStorageSync('currentMemberId') || uni.getStorageSync('currentChildId') || 0
+        var res = await getMyReferrer(memberId)
+        if (res && res.code === 200 && res.data && res.data.hasReferrer) {
+          this.myReferrer = res.data
+        }
+      } catch (e) {
+        console.error('获取推荐人失败', e)
+      }
+    },
+    // ===== 分享海报(复用 ContentSharePoster,与文章/活动/商品同一套生成逻辑)=====
+    async showShareQr() {
+      uni.showLoading({ title: '生成海报中...' })
+      try {
+        if (!this.referralCodeLoaded) {
+          await this.loadReferralCode()
+        }
+        var scene = 'ref=' + (this.referralCode || '')
+        if (scene.length > 32) {
+          scene = scene.substring(0, 32)
+        }
+        // 首页路径,扫码后进入首页并绑定推荐人
+        // 注意:微信 getwxacodeunlimit 的 page 不能带前导斜杠,否则报 errcode 41030 invalid page rid
+        var res = await getShareQrCode('pages/index-home/index', scene)
+        if (res && res.code === 200 && res.data && res.data.qrCodeBase64) {
+          this.posterQrCode = res.data.qrCodeBase64
+          // 必须在 showSharePoster=true 之前取到数据:组件 watch 到 show 后 300ms 即开始绘制
+          await this.loadPosterEnergy()
+          this.showSharePoster = true
+        } else {
+          uni.showToast({ title: '生成失败,请重试', icon: 'none' })
+        }
+      } catch (e) {
+        console.error('生成分享海报失败', e)
+        uni.showToast({ title: '生成失败,请重试', icon: 'none' })
+      } finally {
+        uni.hideLoading()
+      }
+    },
+    closeSharePoster() {
+      this.showSharePoster = false
+    },
+    // 五维能量数据卡数据(方案C):家庭聚合视角;未解锁全景/取数失败时置空,海报降级为品牌卡
+    loadPosterEnergy() {
+      var self = this
+      return getEnergySandbox('family').then(function(res) {
+        self.posterEnergyData = self.mapPosterEnergy(res)
+      }).catch(function(e) {
+        console.error('获取五维能量失败,海报降级为品牌卡', e)
+        self.posterEnergyData = null
+      })
+    },
+    mapPosterEnergy(res) {
+      if (!res || res.code !== 200 || !res.data) return null
+      // locked=true 表示用户未解锁全景,此时不展示任何数据,改为品牌卡
+      if (res.data.locked) return null
+      // 只认家庭聚合视角;仅当接口返回的是裸 DTO(无 personalData/familyData 包装)时才直接取 res.data
+      var d = res.data.familyData || null
+      if (!d) {
+        if (res.data.personalData) return null
+        d = res.data
+      }
+      if (!d || typeof d !== 'object') return null
+      var defs = [
+        { key: 'body', label: '身', color: BrandColors.body },
+        { key: 'mind', label: '心', color: BrandColors.mind },
+        { key: 'wisdom', label: '智', color: BrandColors.wisdom },
+        { key: 'action', label: '行', color: BrandColors.action },
+        { key: 'wealth', label: '富', color: BrandColors.wealth }
+      ]
+      var dims = []
+      var sum = 0
+      for (var i = 0; i < defs.length; i++) {
+        var raw = d[defs[i].key + 'Score']
+        if (raw === null || raw === undefined || raw === '' || isNaN(raw)) continue
+        var n = Number(raw)
+        if (n < 0) n = 0
+        if (n > 100) n = 100
+        sum += n
+        dims.push({ key: defs[i].key, label: defs[i].label, score: n, color: defs[i].color })
+      }
+      if (dims.length === 0) return null
+      var overall = d.overallScore
+      if (overall === null || overall === undefined || overall === '' || isNaN(overall)) {
+        overall = Math.round(sum / dims.length)
+      }
+      return { label: '我们家的能量', overall: Number(overall), dims: dims }
+    },
+
+    async loadReferralCode() {
+      if (this.referralCodeLoaded) return
+      var self = this
+      try {
+        var res = await getReferralCode()
+        self.referralCode = extractReferralCode(res) || ''
+      } catch (e) {
+        console.error('获取推广码失败', e)
+      } finally {
+        self.referralCodeLoaded = true
+      }
+    },
+    goToServiceCenter() {
+      uni.navigateTo({ url: '/pages/service-center/index' })
+    },
+    goTeamTree() {
+      // 服务商 → 服务商团队;非服务商 → 引导申请
+      if (this.isVendor) {
+        uni.navigateTo({ url: '/pages/vendor/team-system/team-system' })
+        return
+      }
+      uni.showModal({
+        title: '提示',
+        content: '您尚未申请任何服务角色,是否立即申请?',
+        confirmText: '去申请',
+        cancelText: '取消',
+        success: function(res) {
+          if (res.confirm) {
+            uni.navigateTo({ url: '/pages/profile/service-role-apply' })
+          }
+        }
+      })
+    },
+    goLogin: function() {
+      this.openLoginSheet()
+    },
+    // 登录浮层成功回调:刷新个人资料与登录后数据
+    onLoginSuccess: function() {
+      if (this.loadUserInfo) this.loadUserInfo()
+    },
+    goSkip: function() {
+      uni.switchTab({ url: '/pages/index-home/index' })
+    },
+    goToEditInfo: function() {
+      uni.navigateTo({ url: '/pages/user-edit/user-edit' })
+    },
+    goToPoints: function() {
+      uni.navigateTo({ url: '/pages/points/points' })
+    },
+    goToStreak: function() {
+      var memberId = uni.getStorageSync('currentMemberId') || uni.getStorageSync('currentChildId')
+      var url = '/pages/stats/completion-rate'
+      if (memberId) {
+        url += '?memberId=' + memberId
+      } else {
+        url += '?familyView=1'
+      }
+      uni.navigateTo({ url: url })
+    },
+    goToTasks: function() {
+      uni.navigateTo({ url: '/pages/tasks/tasks' })
+    },
+    goToWishes: function() {
+      uni.navigateTo({ url: '/pages/wishes/index' })
+    },
+    goToBadges: function() {
+      uni.navigateTo({ url: '/pages/rewards/badge' })
+    },
+    goToGrowth: function() {
+      uni.navigateTo({ url: '/pages/growth-main/index' })
+    },
+    goToChallenges: function() {
+      uni.navigateTo({ url: '/pages/health/challenge-manage' })
+    },
+    goToHealthReports: function() {
+      uni.navigateTo({ url: '/pages/health/report-list' })
+    },
+    goToWealthCenter: function() {
+      uni.navigateTo({ url: '/pages/promotion/index' })
+    },
+    goUpgrade: function() {
+      uni.navigateTo({ url: '/pages/membership/upgrade' })
+    },
+    goToFamily: function() {
+      uni.navigateTo({ url: '/pages/profile-extra/family-members' })
+    },
+    goMemberDetail: function(member) {
+      uni.navigateTo({ url: '/pages/home-pages/member-home-detail?memberId=' + member.id })
+    },
+    goToAppointments: function() {
+      uni.navigateTo({ url: '/pages/parent/appointments' })
+    },
+    goToOrders: function() {
+      uni.navigateTo({ url: '/pages/shop/order-list/order-list' })
+    },
+    goToOrderStatus: function(status) {
+      uni.navigateTo({ url: '/pages/shop/order-list/order-list?status=' + status })
+    },
+    goToCart: function() {
+      uni.navigateTo({ url: '/pages/shop/cart/cart' })
+    },
+    goToAddress: function() {
+      uni.navigateTo({ url: '/pages/shop/address/address' })
+    },
+    goToMessageHistory: function() {
+      uni.navigateTo({ url: '/pages/profile/message-history' })
+    },
+    goToSettings: function() {
+      uni.showActionSheet({
+        itemList: ['完善信息', '家庭成员', '隐私政策', '用户协议', '我的画像', '提醒设置'],
+        success: function(res) {
+          var urls = {
+            0: '/pages/user-edit/user-edit',
+            1: '/pages/profile-extra/family-members',
+            2: '/pages/policy/privacy',
+            3: '/pages/policy/agreement',
+            4: '/pages/profile/portrait-edit',
+            5: '/pages/reminder-config/index'
+          }
+          if (urls[res.tapIndex]) {
+            uni.navigateTo({ url: urls[res.tapIndex] })
+          }
+        }
+      })
+    },
+    memberRoleLabel: function(role) {
+      var map = { parent: '家长', child: '成员', teacher: '规划师' }
+      return map[role] || '成员'
+    },
+    onExitSwitch: function() {
+      var self = this
+      uni.showModal({
+        title: '退出切换',
+        content: '请输入家长密码以确认退出',
+        editable: true,
+        success: function(res) {
+          if (res.confirm && res.content) {
+            verifyPassword(res.content).then(function(result) {
+              if (result.code === 200) {
+                self.$store.commit('switchBackToParent')
+                self.isSwitchedChild = false
+                self.role = 'parent'
+                uni.showToast({ title: '已退出切换', icon: 'success' })
+                uni.reLaunch({ url: '/pages/index-home/index' })
+              } else {
+                uni.showToast({ title: '密码错误', icon: 'none' })
+              }
+            }).catch(function() {
+              uni.showToast({ title: '验证失败', icon: 'none' })
+            })
+          }
+        }
+      })
+    },
+    logout: function() {
+      uni.showModal({
+        title: '确认退出',
+        content: '确定要退出登录吗?',
+        success: function(res) {
+          if (res.confirm) {
+            this.$store.commit('logout')
+            uni.reLaunch({ url: '/pages/index-home/index' })
+          }
+        }.bind(this)
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+// ===== 页面级局部调色板(单页专有色阶;同值才映射全局令牌,约定见 uni.scss §14) =====
+$c-text-gray-400:   $facade-text-gray-400;
+$c-fill-2b:         #F2F2F2;
+
+.container {
+  min-height: 100vh;
+  background: $facade-fill-warm-gray;
+  padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
+}
+
+/* 登录引导 */
+.login-prompt {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 200rpx 60rpx;
+}
+.prompt-icon { font-size: 100rpx; margin-bottom: 30rpx; }
+.prompt-title { font-size: calc(40rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; margin-bottom: 16rpx; }
+.prompt-desc { font-size: calc(26rpx * var(--font-scale, 1)); color: $facade-text-muted; margin-bottom: 20rpx; }
+.login-btn {
+  background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
+  color: $app-surface;
+  border-radius: 50rpx;
+  font-size: 30rpx;
+  padding: 24rpx 80rpx;
+}
+.skip-link {
+  font-size: calc(26rpx * var(--font-scale, 1));
+  color: $facade-text-muted;
+  margin-top: 24rpx;
+  text-decoration: underline;
+}
+.philosophy-card {
+  margin: 0 40rpx 48rpx;
+  background: linear-gradient(135deg, $facade-brand-tint, rgba($brand-primary, 0.06));
+  border-radius: 20rpx;
+  padding: 28rpx 32rpx;
+  border-left: 6rpx solid $brand-primary;
+}
+.philosophy-title {
+  font-size: calc(28rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $facade-text-strong;
+  display: block;
+  margin-bottom: 8rpx;
+}
+.philosophy-desc {
+  font-size: calc(24rpx * var(--font-scale, 1));
+  color: $facade-text-faint;
+  line-height: 1.6;
+  display: block;
+}
+
+/* 退出切换 */
+.exit-switch {
+  margin: 0 30rpx 16rpx;
+  background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
+  color: $app-surface;
+  padding: 16rpx;
+  border-radius: 12rpx;
+  text-align: center;
+  font-size: calc(26rpx * var(--font-scale, 1));
+}
+
+/* 身份卡 */
+.user-card {
+  margin: 24rpx 30rpx 20rpx;
+  background: linear-gradient(135deg, $brand-primary 0%, $brand-primary-light 100%);
+  border-radius: 24rpx;
+  padding: 32rpx 32rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  box-shadow: 0 8rpx 32rpx rgba($accent-indigo, 0.3);
+}
+.user-card-left {
+  display: flex;
+  align-items: center;
+  flex: 1;
+}
+.avatar-wrap {
+  width: 100rpx;
+  height: 100rpx;
+  border-radius: 50%;
+  background: rgba($app-surface, 0.2);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 20rpx;
+  overflow: hidden;
+  border: 3rpx solid rgba($app-surface, 0.3);
+}
+.avatar-img {
+  width: 100rpx;
+  height: 100rpx;
+  border-radius: 50%;
+}
+.avatar-text {
+  font-size: calc(44rpx * var(--font-scale, 1));
+  color: $app-surface;
+}
+.user-meta { flex: 1; }
+.user-name-row {
+  display: flex;
+  align-items: center;
+  gap: 12rpx;
+  margin-bottom: 8rpx;
+}
+.nickname {
+  font-size: calc(34rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $app-surface;
+}
+.role-tag {
+  font-size: 20rpx;
+  background: rgba($app-surface, 0.2);
+  color: $app-surface;
+  padding: 4rpx 14rpx;
+  border-radius: 20rpx;
+}
+.referrer-line {
+  font-size: calc(24rpx * var(--font-scale, 1));
+  color: rgba($app-surface, 0.7);
+  margin-bottom: 6rpx;
+}
+.user-sub {
+  display: flex;
+  align-items: center;
+  gap: 12rpx;
+}
+.level-badge {
+  font-size: 22rpx;
+  padding: 6rpx 20rpx;
+  border-radius: 22rpx;
+  font-weight: bold;
+  border: 2rpx solid rgba($app-surface, 0.35);
+  display: flex;
+  align-items: center;
+  gap: 6rpx;
+  box-sizing: border-box;
+  height: 40rpx;
+}
+.level-badge::before {
+  content: '👑';
+  font-size: 18rpx;
+}
+.level-FREE { background: linear-gradient(135deg, $c-text-gray-400, $facade-text-slate); color: $app-surface; }
+.level-FREE::before { content: ''; }
+.level-FAMILY { background: linear-gradient(135deg, $dim-wealth, $status-warning-deep); color: $app-surface; }
+.level-PREMIUM { background: linear-gradient(135deg, $dim-wisdom, $dim-wisdom-deep); color: $app-surface; }
+.level-LIFETIME {
+  background: linear-gradient(135deg, $accent-pink, $accent-pink-deep);
+  color: $app-surface;
+  box-shadow: 0 4rpx 16rpx rgba($accent-pink, 0.45);
+  border-color: rgba($app-surface, 0.55);
+}
+.days-left {
+  font-size: calc(20rpx * var(--font-scale, 1));
+  color: rgba($app-surface, 0.85);
+}
+.upgrade-btn {
+  background: rgba($app-surface, 0.22);
+  border: 2rpx solid rgba($app-surface, 0.6);
+  border-radius: 20rpx;
+  padding: 6rpx 20rpx;
+  flex-shrink: 0;
+  box-sizing: border-box;
+  height: 40rpx;
+  display: flex;
+  align-items: center;
+}
+.upgrade-btn-text {
+  font-size: 20rpx;
+  font-weight: bold;
+  color: $app-surface;
+  line-height: 1;
+}
+.user-card-right {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 6rpx;
+  background: rgba($app-surface, 0.15);
+  padding: 12rpx 24rpx;
+  border-radius: 14rpx;
+}
+.points-num {
+  font-size: calc(36rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $app-surface;
+}
+.points-label {
+  font-size: calc(20rpx * var(--font-scale, 1));
+  color: rgba($app-surface, 0.7);
+}
+
+/* 家庭成员速览 */
+.family-strip {
+  margin: 0 30rpx 20rpx;
+  background: $app-surface;
+  border-radius: 20rpx;
+  padding: 20rpx 24rpx 16rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
+}
+.family-strip-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 14rpx;
+}
+.family-strip-title {
+  font-size: calc(26rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $facade-text-strong;
+}
+.family-strip-count {
+  font-size: 22rpx;
+  color: $facade-text-muted;
+}
+.family-avatars {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  gap: 16rpx;
+  overflow-x: auto;
+  padding-bottom: 4rpx;
+}
+.family-avatar-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 6rpx;
+  flex-shrink: 0;
+}
+.family-avatar-wrap {
+  width: 72rpx;
+  height: 72rpx;
+  border-radius: 50%;
+  background: $facade-fill;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  overflow: hidden;
+  position: relative;
+}
+.family-avatar-img {
+  width: 72rpx;
+  height: 72rpx;
+  border-radius: 50%;
+}
+.family-avatar-text {
+  font-size: calc(28rpx * var(--font-scale, 1));
+  color: $facade-text-body;
+}
+.family-avatar-wrap.family-avatar-add {
+  background: $facade-fill-warm-gray;
+  border: 2rpx dashed $facade-text-ghost;
+}
+.family-avatar-plus {
+  font-size: calc(36rpx * var(--font-scale, 1));
+  color: $facade-text-muted;
+}
+.family-avatar-tag {
+  position: absolute;
+  bottom: -4rpx;
+  right: -4rpx;
+  font-size: 14rpx;
+  padding: 2rpx 6rpx;
+  border-radius: 8rpx;
+  color: $app-surface;
+}
+.family-avatar-tag.tag-parent { background: $dim-wisdom; }
+.family-avatar-tag.tag-child { background: $brand-primary; }
+.family-avatar-tag.tag-teacher { background: $dim-action; }
+.family-avatar-tag.tag-member { background: $c-text-gray-400; }
+.family-avatar-name {
+  font-size: calc(20rpx * var(--font-scale, 1));
+  color: $facade-text-body;
+  white-space: nowrap;
+}
+
+/* 个人成就 */
+.achievement-section {
+  margin: 0 30rpx 20rpx;
+  background: $app-surface;
+  border-radius: 20rpx;
+  padding: 24rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
+}
+.section-header-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: baseline;
+  margin-bottom: 16rpx;
+}
+.section-title {
+  font-size: calc(28rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $facade-text-strong;
+}
+.section-sub {
+  font-size: calc(22rpx * var(--font-scale, 1));
+  color: $facade-text-muted;
+}
+.achievement-grid {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 0;
+}
+.ach-item {
+  width: 25%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 6rpx;
+  padding: 10rpx 0;
+}
+.ach-icon-wrap {
+  width: 64rpx;
+  height: 64rpx;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 4rpx;
+}
+.ach-icon {
+  font-size: 32rpx;
+  line-height: 1;
+}
+.ach-num {
+  font-size: calc(28rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $facade-text-strong;
+  line-height: 1;
+}
+.ach-label {
+  font-size: calc(20rpx * var(--font-scale, 1));
+  color: $facade-text-muted;
+  line-height: 1;
+}
+
+/* 我的订单(电商风格) */
+.order-section {
+  margin: 0 30rpx 20rpx;
+}
+.order-section-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 14rpx;
+}
+.order-all-link {
+  font-size: calc(24rpx * var(--font-scale, 1));
+  color: $facade-text-muted;
+}
+.order-card {
+  background: $app-surface;
+  border-radius: 20rpx;
+  padding: 24rpx 12rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
+}
+.order-grid {
+  display: flex;
+  flex-wrap: wrap;
+}
+.order-grid-item {
+  width: 20%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 10rpx;
+  padding: 8rpx 0;
+}
+.order-icon-wrap {
+  position: relative;
+  width: 64rpx;
+  height: 64rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.order-icon {
+  font-size: 40rpx;
+  line-height: 1;
+}
+.order-badge {
+  position: absolute;
+  top: -8rpx;
+  right: -14rpx;
+  min-width: 30rpx;
+  height: 30rpx;
+  line-height: 30rpx;
+  border-radius: 15rpx;
+  background: $status-danger-2;
+  color: $app-surface;
+  font-size: 18rpx;
+  text-align: center;
+  padding: 0 6rpx;
+}
+.order-grid-text {
+  font-size: calc(22rpx * var(--font-scale, 1));
+  color: $facade-text-body;
+  line-height: 1;
+}
+.order-extra-row {
+  display: flex;
+  align-items: center;
+  margin-top: 20rpx;
+  padding-top: 20rpx;
+  border-top: 1rpx solid $c-fill-2b;
+}
+.order-extra-item {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 8rpx;
+}
+.order-extra-icon {
+  font-size: 28rpx;
+}
+.order-extra-text {
+  font-size: calc(24rpx * var(--font-scale, 1));
+  color: $facade-text-strong;
+}
+.order-extra-badge {
+  min-width: 30rpx;
+  height: 30rpx;
+  line-height: 30rpx;
+  border-radius: 15rpx;
+  background: $brand-primary;
+  color: $app-surface;
+  font-size: 18rpx;
+  text-align: center;
+  padding: 0 6rpx;
+}
+.order-extra-divider {
+  width: 1rpx;
+  height: 30rpx;
+  background: $c-fill-2b;
+}
+
+/* 规划师服务中心入口 */
+.service-center-section {
+  margin: 0 30rpx 20rpx;
+}
+.service-center-card {
+  background: linear-gradient(135deg, $brand-primary 0%, $brand-primary-light 100%);
+  border-radius: 20rpx;
+  padding: 24rpx;
+  display: flex;
+  align-items: center;
+  gap: 20rpx;
+  box-shadow: 0 4rpx 16rpx rgba($brand-primary, 0.25);
+}
+.service-center-card.disabled-card {
+  background: linear-gradient(135deg, $uni-border-color-light, $app-text-subtle);
+  box-shadow: none;
+  opacity: 0.8;
+}
+.service-center-icon {
+  font-size: 48rpx;
+}
+.service-center-info {
+  flex: 1;
+}
+.service-center-title {
+  font-size: calc(30rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $app-surface;
+  display: block;
+}
+.service-center-desc {
+  font-size: calc(22rpx * var(--font-scale, 1));
+  color: rgba($app-surface, 0.8);
+  margin-top: 6rpx;
+  display: block;
+}
+.service-center-card.disabled-card .service-center-title {
+  color: $app-surface;
+}
+.service-center-card.disabled-card .service-center-desc {
+  color: rgba($app-surface, 0.9);
+}
+.service-center-arrow {
+  font-size: 40rpx;
+  color: $app-surface;
+}
+
+/* 设置 + 退出 */
+.bottom-menu-section {
+  margin: 0 30rpx;
+  padding-bottom: 20rpx;
+}
+.menu-row {
+  width: 100%;
+  background: $app-surface;
+  border-radius: 16rpx;
+  padding: 24rpx;
+  display: flex;
+  align-items: center;
+  gap: 14rpx;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
+  margin-bottom: 20rpx;
+}
+.menu-row-icon {
+  font-size: 30rpx;
+}
+.menu-row-text {
+  flex: 1;
+  font-size: calc(26rpx * var(--font-scale, 1));
+  color: $facade-text-strong;
+}
+.menu-row-arrow {
+  font-size: 28rpx;
+  color: $facade-text-ghost;
+}
+.logout-btn {
+  width: 100%;
+  background: $app-surface;
+  border-radius: 16rpx;
+  padding: 24rpx;
+  text-align: center;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
+}
+.logout-text {
+  font-size: calc(26rpx * var(--font-scale, 1));
+  color: $status-danger-2;
+  font-weight: 500;
+}
+
+/* 分享推广码浮动按钮 */
+.share-qr-float {
+  position: fixed;
+  top: 180rpx;
+  right: 30rpx;
+  width: 80rpx;
+  height: 80rpx;
+  border-radius: 50%;
+  background: $app-surface;
+  box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.15);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 99;
+}
+/* 二维码图标(纯 CSS 绘制,不依赖 emoji 字体) */
+.qr-glyph {
+  position: relative;
+  width: 46rpx;
+  height: 46rpx;
+}
+.qr-eye {
+  position: absolute;
+  width: 16rpx;
+  height: 16rpx;
+  border: 4rpx solid $uni-text-color;
+  border-radius: 3rpx;
+  box-sizing: border-box;
+}
+.qr-eye-tl { left: 0; top: 0; }
+.qr-eye-tr { right: 0; top: 0; }
+.qr-eye-bl { left: 0; bottom: 0; }
+.qr-mid {
+  position: absolute;
+  left: 20rpx;
+  top: 20rpx;
+  width: 7rpx;
+  height: 7rpx;
+  background: $uni-text-color;
+  border-radius: 1rpx;
+}
+.qr-cluster {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  width: 18rpx;
+  display: flex;
+  flex-wrap: wrap;
+}
+.qr-pip {
+  width: 7rpx;
+  height: 7rpx;
+  margin: 1rpx;
+  background: $uni-text-color;
+  border-radius: 1rpx;
+}
+</style>

+ 26 - 24
cfc-frontend/pages/shop/cart/cart.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="container">
+  <view class="container" :style="{ '--font-scale': fontScale }">
     <scroll-view
     <scroll-view
       scroll-y
       scroll-y
       class="cart-list"
       class="cart-list"
@@ -142,8 +142,10 @@
 <script>
 <script>
 import config from '@/config.js'
 import config from '@/config.js'
 import { getMyMembership, getGiftMembershipProgress } from '@/utils/api.js'
 import { getMyMembership, getGiftMembershipProgress } from '@/utils/api.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   data() {
   data() {
     return {
     return {
       items: [],
       items: [],
@@ -461,7 +463,7 @@ export default {
   padding-top: 200rpx;
   padding-top: 200rpx;
 }
 }
 .loading-text {
 .loading-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .empty-icon {
 .empty-icon {
@@ -469,7 +471,7 @@ export default {
   margin-bottom: 30rpx;
   margin-bottom: 30rpx;
 }
 }
 .empty-text {
 .empty-text {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .select-all-row {
 .select-all-row {
@@ -490,7 +492,7 @@ export default {
   align-items: center;
   align-items: center;
   justify-content: center;
   justify-content: center;
   margin-right: 12rpx;
   margin-right: 12rpx;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-surface;
   color: $app-surface;
 }
 }
 .checkbox.checked {
 .checkbox.checked {
@@ -502,7 +504,7 @@ export default {
   font-weight: bold;
   font-weight: bold;
 }
 }
 .select-all-text {
 .select-all-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .cart-item-card {
 .cart-item-card {
@@ -535,7 +537,7 @@ export default {
 }
 }
 .item-name {
 .item-name {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   overflow: hidden;
   overflow: hidden;
   text-overflow: ellipsis;
   text-overflow: ellipsis;
@@ -543,14 +545,14 @@ export default {
   margin-left: 4rpx;
   margin-left: 4rpx;
 }
 }
 .item-spec {
 .item-spec {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   display: block;
   display: block;
   margin-top: 4rpx;
   margin-top: 4rpx;
   flex-basis: 100%;
   flex-basis: 100%;
 }
 }
 .item-supplier {
 .item-supplier {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $uni-info;
   color: $uni-info;
   display: block;
   display: block;
   margin-top: 2rpx;
   margin-top: 2rpx;
@@ -593,13 +595,13 @@ export default {
   height: 48rpx;
   height: 48rpx;
   text-align: center;
   text-align: center;
   line-height: 48rpx;
   line-height: 48rpx;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   border-left: 1rpx solid $facade-hairline;
   border-left: 1rpx solid $facade-hairline;
   border-right: 1rpx solid $facade-hairline;
   border-right: 1rpx solid $facade-hairline;
 }
 }
 .item-subtotal {
 .item-subtotal {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   text-align: right;
   text-align: right;
   margin-top: 8rpx;
   margin-top: 8rpx;
@@ -628,11 +630,11 @@ export default {
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
 .total-amount-label {
 .total-amount-label {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
 }
 }
 .total-amount {
 .total-amount {
-  font-size: 36rpx;
+  font-size: calc(36rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: bold;
   font-weight: bold;
 }
 }
@@ -670,11 +672,11 @@ export default {
 }
 }
 .member-hint-text {
 .member-hint-text {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
 }
 }
 .member-hint-action {
 .member-hint-action {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -725,12 +727,12 @@ export default {
 }
 }
 .gift-progress-title {
 .gift-progress-title {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   font-weight: 500;
   font-weight: 500;
 }
 }
 .gift-progress-percent {
 .gift-progress-percent {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: bold;
   font-weight: bold;
 }
 }
@@ -752,17 +754,17 @@ export default {
   justify-content: space-between;
   justify-content: space-between;
 }
 }
 .gift-progress-accumulated {
 .gift-progress-accumulated {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $mat-orange-deep;
   color: $mat-orange-deep;
 }
 }
 .gift-progress-remaining {
 .gift-progress-remaining {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   font-weight: 500;
   font-weight: 500;
 }
 }
 .gift-progress-level {
 .gift-progress-level {
   margin-top: 12rpx;
   margin-top: 12rpx;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
 }
 }
 /* Gift promo section */
 /* Gift promo section */
@@ -782,7 +784,7 @@ export default {
 }
 }
 .gift-promo-title {
 .gift-promo-title {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $status-warning-strong;
   color: $status-warning-strong;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -799,11 +801,11 @@ export default {
   border-radius: 8rpx;
   border-radius: 8rpx;
 }
 }
 .gift-promo-remaining {
 .gift-promo-remaining {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $status-warning-strong;
   color: $status-warning-strong;
 }
 }
 .gift-promo-reached {
 .gift-promo-reached {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $status-warning-deep;
   color: $status-warning-deep;
   font-weight: bold;
   font-weight: bold;
 }
 }
@@ -820,7 +822,7 @@ export default {
 }
 }
 .gift-granted-text {
 .gift-granted-text {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: #15803D;
   color: #15803D;
 }
 }
-</style>
+</style>

+ 54 - 52
cfc-frontend/pages/shop/checkout/checkout.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="container">
+  <view class="container" :style="{ '--font-scale': fontScale }">
     <view v-if="loading" class="loading-wrap">
     <view v-if="loading" class="loading-wrap">
       <text class="loading-text">加载中...</text>
       <text class="loading-text">加载中...</text>
     </view>
     </view>
@@ -488,8 +488,10 @@ import { getCouponList, getCouponCheckoutList, addressList, getProductRequiredFi
 import { parseDate } from '@/utils/format.js'
 import { parseDate } from '@/utils/format.js'
 import CountdownTag from '@/pages/shop/components/countdown-tag.vue'
 import CountdownTag from '@/pages/shop/components/countdown-tag.vue'
 import HandSignature from '@/components/hand-signature/hand-signature.vue'
 import HandSignature from '@/components/hand-signature/hand-signature.vue'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   components: {
   components: {
     CountdownTag,
     CountdownTag,
     HandSignature
     HandSignature
@@ -1220,7 +1222,7 @@ showOnlineSlotPicker: function() {
   padding-top: 200rpx;
   padding-top: 200rpx;
 }
 }
 .loading-text {
 .loading-text {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .content {
 .content {
@@ -1233,7 +1235,7 @@ showOnlineSlotPicker: function() {
   padding: 24rpx;
   padding: 24rpx;
 }
 }
 .section-title {
 .section-title {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
@@ -1251,13 +1253,13 @@ showOnlineSlotPicker: function() {
   margin-bottom: 10rpx;
   margin-bottom: 10rpx;
 }
 }
 .receiver-name {
 .receiver-name {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
   margin-right: 20rpx;
   margin-right: 20rpx;
 }
 }
 .receiver-phone {
 .receiver-phone {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
 }
 }
 .default-badge {
 .default-badge {
@@ -1269,7 +1271,7 @@ showOnlineSlotPicker: function() {
   margin-left: 12rpx;
   margin-left: 12rpx;
 }
 }
 .address-detail {
 .address-detail {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
@@ -1293,7 +1295,7 @@ showOnlineSlotPicker: function() {
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
 .address-empty-text {
 .address-empty-text {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .order-item {
 .order-item {
@@ -1319,7 +1321,7 @@ showOnlineSlotPicker: function() {
   min-width: 0;
   min-width: 0;
 }
 }
 .item-name {
 .item-name {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   overflow: hidden;
   overflow: hidden;
   text-overflow: ellipsis;
   text-overflow: ellipsis;
@@ -1327,19 +1329,19 @@ showOnlineSlotPicker: function() {
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .item-spec-desc {
 .item-spec-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   display: block;
   display: block;
   margin-top: 2rpx;
   margin-top: 2rpx;
 }
 }
 .item-supplier-name {
 .item-supplier-name {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $uni-info;
   color: $uni-info;
   display: block;
   display: block;
   margin-top: 2rpx;
   margin-top: 2rpx;
 }
 }
 .item-qty {
 .item-qty {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .item-price {
 .item-price {
@@ -1355,17 +1357,17 @@ showOnlineSlotPicker: function() {
   padding: 8rpx 0;
   padding: 8rpx 0;
 }
 }
 .info-label {
 .info-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .info-value {
 .info-value {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 .remark-input {
 .remark-input {
   flex: 1;
   flex: 1;
   text-align: right;
   text-align: right;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
 
 
@@ -1412,12 +1414,12 @@ showOnlineSlotPicker: function() {
 }
 }
 
 
 .placeholder-text {
 .placeholder-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-ghost;
   color: $facade-text-ghost;
 }
 }
 
 
 .total-original {
 .total-original {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-ghost-light;
   color: $facade-text-ghost-light;
   text-decoration: line-through;
   text-decoration: line-through;
   margin-left: 8rpx;
   margin-left: 8rpx;
@@ -1437,7 +1439,7 @@ showOnlineSlotPicker: function() {
 }
 }
 .member-upgrade-text {
 .member-upgrade-text {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -1464,7 +1466,7 @@ showOnlineSlotPicker: function() {
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
 .hint-text {
 .hint-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -1500,7 +1502,7 @@ showOnlineSlotPicker: function() {
 }
 }
 
 
 .picker-title {
 .picker-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
@@ -1537,7 +1539,7 @@ showOnlineSlotPicker: function() {
 }
 }
 
 
 .picker-item-value {
 .picker-item-value {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $brand-primary;
   color: $brand-primary;
 }
 }
@@ -1548,14 +1550,14 @@ showOnlineSlotPicker: function() {
 }
 }
 
 
 .picker-item-name {
 .picker-item-name {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   display: block;
   display: block;
   margin-bottom: 4rpx;
   margin-bottom: 4rpx;
 }
 }
 
 
 .picker-item-condition {
 .picker-item-condition {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 
 
@@ -1579,7 +1581,7 @@ showOnlineSlotPicker: function() {
 .picker-empty {
 .picker-empty {
   text-align: center;
   text-align: center;
   padding: 60rpx 0;
   padding: 60rpx 0;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 
 
@@ -1621,11 +1623,11 @@ showOnlineSlotPicker: function() {
   align-items: baseline;
   align-items: baseline;
 }
 }
 .total-label {
 .total-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
 }
 }
 .total-amount {
 .total-amount {
-  font-size: 36rpx;
+  font-size: calc(36rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: bold;
   font-weight: bold;
 }
 }
@@ -1648,7 +1650,7 @@ showOnlineSlotPicker: function() {
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .points-balance {
 .points-balance {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
 }
 }
 .points-input-row {
 .points-input-row {
@@ -1661,14 +1663,14 @@ showOnlineSlotPicker: function() {
 .points-input {
 .points-input {
   flex: 1;
   flex: 1;
   height: 60rpx;
   height: 60rpx;
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   background: $facade-fill-ghost-2;
   background: $facade-fill-ghost-2;
   border-radius: 8rpx;
   border-radius: 8rpx;
   padding: 0 16rpx;
   padding: 0 16rpx;
 }
 }
 .points-hint {
 .points-hint {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-left: 12rpx;
   margin-left: 12rpx;
   min-width: 100rpx;
   min-width: 100rpx;
@@ -1678,11 +1680,11 @@ showOnlineSlotPicker: function() {
   margin-top: 8rpx;
   margin-top: 8rpx;
 }
 }
 .points-tip-text {
 .points-tip-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $facade-text-ghost-light;
   color: $facade-text-ghost-light;
 }
 }
 .total-original {
 .total-original {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-ghost-light;
   color: $facade-text-ghost-light;
   text-decoration: line-through;
   text-decoration: line-through;
   margin-left: 8rpx;
   margin-left: 8rpx;
@@ -1699,7 +1701,7 @@ showOnlineSlotPicker: function() {
   border-bottom: none;
   border-bottom: none;
 }
 }
 .purchase-field-label {
 .purchase-field-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   width: 160rpx;
   width: 160rpx;
   flex-shrink: 0;
   flex-shrink: 0;
@@ -1709,7 +1711,7 @@ showOnlineSlotPicker: function() {
 }
 }
 .purchase-field-input {
 .purchase-field-input {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   text-align: right;
   text-align: right;
   padding: 8rpx 0;
   padding: 8rpx 0;
@@ -1719,7 +1721,7 @@ showOnlineSlotPicker: function() {
   color: $facade-text-muted;
   color: $facade-text-muted;
 }
 }
 .purchase-field-prefill {
 .purchase-field-prefill {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $el-success;
   color: $el-success;
   margin-left: 8rpx;
   margin-left: 8rpx;
 }
 }
@@ -1728,7 +1730,7 @@ showOnlineSlotPicker: function() {
   margin-top: 24rpx;
   margin-top: 24rpx;
 }
 }
 .purchase-signature-title {
 .purchase-signature-title {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   font-weight: bold;
   font-weight: bold;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
@@ -1752,12 +1754,12 @@ showOnlineSlotPicker: function() {
   border-bottom: none;
   border-bottom: none;
 }
 }
 .picker-value {
 .picker-value {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   flex: 1;
   flex: 1;
 }
 }
 .picker-placeholder {
 .picker-placeholder {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   flex: 1;
   flex: 1;
 }
 }
@@ -1793,7 +1795,7 @@ showOnlineSlotPicker: function() {
   border-bottom: 1rpx solid $facade-hairline-2;
   border-bottom: 1rpx solid $facade-hairline-2;
 }
 }
 .picker-modal .picker-title {
 .picker-modal .picker-title {
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $facade-text-strong;
   color: $facade-text-strong;
 }
 }
@@ -1825,18 +1827,18 @@ showOnlineSlotPicker: function() {
   min-width: 0;
   min-width: 0;
 }
 }
 .picker-modal .picker-item-name {
 .picker-modal .picker-item-name {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-strong;
   color: $facade-text-strong;
   display: block;
   display: block;
 }
 }
 .picker-modal .picker-item-addr {
 .picker-modal .picker-item-addr {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-top: 6rpx;
   margin-top: 6rpx;
   display: block;
   display: block;
 }
 }
 .picker-modal .picker-item-desc {
 .picker-modal .picker-item-desc {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $facade-text-muted;
   color: $facade-text-muted;
   margin-top: 4rpx;
   margin-top: 4rpx;
   display: block;
   display: block;
@@ -1851,7 +1853,7 @@ showOnlineSlotPicker: function() {
 .picker-modal .picker-item-check {
 .picker-modal .picker-item-check {
   margin-left: 16rpx;
   margin-left: 16rpx;
   color: $brand-primary;
   color: $brand-primary;
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
 }
 }
 /* Gift membership progress */
 /* Gift membership progress */
 .gift-progress-section {
 .gift-progress-section {
@@ -1870,12 +1872,12 @@ showOnlineSlotPicker: function() {
 }
 }
 .gift-progress-title {
 .gift-progress-title {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   font-weight: 500;
   font-weight: 500;
 }
 }
 .gift-progress-percent {
 .gift-progress-percent {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: bold;
   font-weight: bold;
 }
 }
@@ -1896,23 +1898,23 @@ showOnlineSlotPicker: function() {
   justify-content: space-between;
   justify-content: space-between;
 }
 }
 .gift-progress-accumulated {
 .gift-progress-accumulated {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $mat-orange-deep;
   color: $mat-orange-deep;
 }
 }
 .gift-progress-remaining {
 .gift-progress-remaining {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   font-weight: 500;
   font-weight: 500;
 }
 }
 .gift-progress-level {
 .gift-progress-level {
   margin-top: 12rpx;
   margin-top: 12rpx;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
 }
 }
 .gift-progress-note {
 .gift-progress-note {
   display: block;
   display: block;
   margin-top: 8rpx;
   margin-top: 8rpx;
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $mat-orange-deep;
   color: $mat-orange-deep;
 }
 }
 .gift-granted-section {
 .gift-granted-section {
@@ -1930,7 +1932,7 @@ showOnlineSlotPicker: function() {
 }
 }
 .gift-granted-text {
 .gift-granted-text {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: #15803D;
   color: #15803D;
 }
 }
 .gift-promo-section {
 .gift-promo-section {
@@ -1953,18 +1955,18 @@ showOnlineSlotPicker: function() {
   flex: 1;
   flex: 1;
 }
 }
 .gift-promo-title {
 .gift-promo-title {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   font-weight: 500;
   font-weight: 500;
 }
 }
 .gift-promo-desc {
 .gift-promo-desc {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $mat-orange-deep;
   color: $mat-orange-deep;
   margin-top: 4rpx;
   margin-top: 4rpx;
 }
 }
 .gift-promo-save {
 .gift-promo-save {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
 }
 }
 /* 保持原有样式向下延伸 */
 /* 保持原有样式向下延伸 */
-</style>
+</style>

+ 30 - 28
cfc-frontend/pages/wealth-sub/insurance-planning.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <scroll-view class="container" scroll-y>
+  <scroll-view class="container" :style="{ '--font-scale': fontScale }" scroll-y>
 
 
     <!-- 加载状态 -->
     <!-- 加载状态 -->
     <view v-if="loading" class="loading-state">
     <view v-if="loading" class="loading-state">
@@ -189,8 +189,10 @@
 
 
 <script>
 <script>
 import { getInsurancePlanning, ensureFamily } from '../../utils/api'
 import { getInsurancePlanning, ensureFamily } from '../../utils/api'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   data() {
   data() {
     return {
     return {
       loading: true,
       loading: true,
@@ -321,7 +323,7 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   padding: 120rpx 0;
   padding: 120rpx 0;
 }
 }
 .loading-icon { font-size: 64rpx; margin-bottom: 24rpx; }
 .loading-icon { font-size: 64rpx; margin-bottom: 24rpx; }
-.loading-text { font-size: 28rpx; color: $facade-text-muted; }
+.loading-text { font-size: calc(28rpx * var(--font-scale, 1)); color: $facade-text-muted; }
 
 
 /* 综合评分卡 */
 /* 综合评分卡 */
 .score-card {
 .score-card {
@@ -337,9 +339,9 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   align-items: center;
   align-items: center;
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
-.score-title { font-size: 30rpx; font-weight: bold; }
+.score-title { font-size: calc(30rpx * var(--font-scale, 1)); font-weight: bold; }
 .score-status {
 .score-status {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   padding: 6rpx 20rpx;
   padding: 6rpx 20rpx;
   border-radius: 20rpx;
   border-radius: 20rpx;
   background: rgba(255,255,255,0.2);
   background: rgba(255,255,255,0.2);
@@ -360,8 +362,8 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .score-ring-inner { text-align: center; }
 .score-ring-inner { text-align: center; }
-.score-value { font-size: 56rpx; font-weight: bold; display: block; }
-.score-max { font-size: 24rpx; opacity: 0.7; }
+.score-value { font-size: calc(56rpx * var(--font-scale, 1)); font-weight: bold; display: block; }
+.score-max { font-size: calc(24rpx * var(--font-scale, 1)); opacity: 0.7; }
 
 
 .score-dims { flex: 1; }
 .score-dims { flex: 1; }
 .dim-row {
 .dim-row {
@@ -370,7 +372,7 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .dim-label {
 .dim-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   width: 36rpx;
   width: 36rpx;
   color: rgba(255,255,255,0.8);
   color: rgba(255,255,255,0.8);
 }
 }
@@ -390,7 +392,7 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
 .mind-fill { background: $dim-mind; }
 .mind-fill { background: $dim-mind; }
 .wisdom-fill { background: $dim-wisdom; }
 .wisdom-fill { background: $dim-wisdom; }
 .dim-value {
 .dim-value {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   width: 70rpx;
   width: 70rpx;
   text-align: right;
   text-align: right;
   color: rgba(255,255,255,0.9);
   color: rgba(255,255,255,0.9);
@@ -419,7 +421,7 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   display: block;
   display: block;
   color: $app-surface;
   color: $app-surface;
 }
 }
-.gap-stat-label { font-size: 22rpx; color: rgba(255,255,255,0.7); }
+.gap-stat-label { font-size: calc(22rpx * var(--font-scale, 1)); color: rgba(255,255,255,0.7); }
 
 
 /* 整体建议 */
 /* 整体建议 */
 .recommend-card {
 .recommend-card {
@@ -428,8 +430,8 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   padding: 24rpx;
   padding: 24rpx;
   border-left: 6rpx solid $status-warning-2;
   border-left: 6rpx solid $status-warning-2;
 }
 }
-.recommend-title { font-size: 28rpx; font-weight: bold; color: $status-warning-strong; display: block; margin-bottom: 12rpx; }
-.recommend-text { font-size: 26rpx; color: $c-warning-ink; line-height: 1.6; }
+.recommend-title { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: bold; color: $status-warning-strong; display: block; margin-bottom: 12rpx; }
+.recommend-text { font-size: calc(26rpx * var(--font-scale, 1)); color: $c-warning-ink; line-height: 1.6; }
 
 
 /* Section */
 /* Section */
 .section { margin-bottom: 24rpx; }
 .section { margin-bottom: 24rpx; }
@@ -439,8 +441,8 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   align-items: center;
   align-items: center;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
-.section-title { font-size: 30rpx; font-weight: bold; color: $facade-text-strong; }
-.section-sub { font-size: 24rpx; color: $facade-text-muted; }
+.section-title { font-size: calc(30rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; }
+.section-sub { font-size: calc(24rpx * var(--font-scale, 1)); color: $facade-text-muted; }
 
 
 /* 成员卡片 */
 /* 成员卡片 */
 .member-list {}
 .member-list {}
@@ -462,7 +464,7 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   border-radius: 50%;
   border-radius: 50%;
   background: linear-gradient(135deg, $accent-indigo, $accent-indigo-deep);
   background: linear-gradient(135deg, $accent-indigo, $accent-indigo-deep);
   color: $app-surface;
   color: $app-surface;
-  font-size: 32rpx;
+  font-size: calc(32rpx * var(--font-scale, 1));
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
   justify-content: center;
   justify-content: center;
@@ -470,8 +472,8 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .member-info { flex: 1; }
 .member-info { flex: 1; }
-.member-name { font-size: 30rpx; font-weight: bold; color: $facade-text-strong; display: block; }
-.member-role { font-size: 24rpx; color: $facade-text-muted; }
+.member-name { font-size: calc(30rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; display: block; }
+.member-role { font-size: calc(24rpx * var(--font-scale, 1)); color: $facade-text-muted; }
 .member-policy-badge {
 .member-policy-badge {
   font-size: 22rpx;
   font-size: 22rpx;
   background: $status-success-soft-2;
   background: $status-success-soft-2;
@@ -493,8 +495,8 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   border-bottom: 1rpx solid $facade-fill-2;
   border-bottom: 1rpx solid $facade-fill-2;
 }
 }
 .member-dim-item { text-align: center; flex: 1; }
 .member-dim-item { text-align: center; flex: 1; }
-.mdim-label { font-size: 22rpx; color: $facade-text-muted; display: block; }
-.mdim-val { font-size: 32rpx; font-weight: bold; color: $facade-text-strong; }
+.mdim-label { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-muted; display: block; }
+.mdim-val { font-size: calc(32rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; }
 
 
 /* 覆盖状态芯片 */
 /* 覆盖状态芯片 */
 .coverage-chips {
 .coverage-chips {
@@ -535,25 +537,25 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   gap: 12rpx;
   gap: 12rpx;
 }
 }
 .gap-priority {
 .gap-priority {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   padding: 4rpx 12rpx;
   padding: 4rpx 12rpx;
   border-radius: 8rpx;
   border-radius: 8rpx;
 }
 }
 .gap-priority.priority-high { background: $status-danger-tint-3; color: $c-danger-deep; }
 .gap-priority.priority-high { background: $status-danger-tint-3; color: $c-danger-deep; }
 .gap-priority.priority-medium { background: $brand-primary-tint-2; color: $c-warning-deep; }
 .gap-priority.priority-medium { background: $brand-primary-tint-2; color: $c-warning-deep; }
 .gap-priority.priority-low { background: $status-success-tint-3; color: $c-success-deep; }
 .gap-priority.priority-low { background: $status-success-tint-3; color: $c-success-deep; }
-.gap-member { font-size: 28rpx; font-weight: bold; color: $facade-text-strong; }
-.gap-type { font-size: 26rpx; color: $facade-text-body; }
+.gap-member { font-size: calc(28rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; }
+.gap-type { font-size: calc(26rpx * var(--font-scale, 1)); color: $facade-text-body; }
 .gap-desc {
 .gap-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $facade-text-deep;
   color: $facade-text-deep;
   line-height: 1.5;
   line-height: 1.5;
   display: block;
   display: block;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
 .gap-products { margin-bottom: 12rpx; }
 .gap-products { margin-bottom: 12rpx; }
-.gap-products-label { font-size: 24rpx; color: $facade-text-muted; }
-.gap-products-list { font-size: 24rpx; color: $status-warning-2; font-weight: 500; }
+.gap-products-label { font-size: calc(24rpx * var(--font-scale, 1)); color: $facade-text-muted; }
+.gap-products-list { font-size: calc(24rpx * var(--font-scale, 1)); color: $status-warning-2; font-weight: 500; }
 .gap-actions { display: flex; justify-content: flex-end; }
 .gap-actions { display: flex; justify-content: flex-end; }
 .gap-add-btn {
 .gap-add-btn {
   font-size: 24rpx;
   font-size: 24rpx;
@@ -573,8 +575,8 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   border: 2rpx solid $c-success-soft;
   border: 2rpx solid $c-success-soft;
 }
 }
 .all-covered-icon { font-size: 64rpx; display: block; margin-bottom: 16rpx; }
 .all-covered-icon { font-size: 64rpx; display: block; margin-bottom: 16rpx; }
-.all-covered-title { font-size: 30rpx; font-weight: bold; color: $c-success-deep; display: block; margin-bottom: 12rpx; }
-.all-covered-desc { font-size: 26rpx; color: $status-success-3; }
+.all-covered-title { font-size: calc(30rpx * var(--font-scale, 1)); font-weight: bold; color: $c-success-deep; display: block; margin-bottom: 12rpx; }
+.all-covered-desc { font-size: calc(26rpx * var(--font-scale, 1)); color: $status-success-3; }
 
 
 /* 保单管理入口 */
 /* 保单管理入口 */
 .action-btn {
 .action-btn {
@@ -598,6 +600,6 @@ $c-warning-mid: #FFA940; // gold-6 警示中档(单页专有)
   padding: 120rpx 0;
   padding: 120rpx 0;
 }
 }
 .empty-icon { font-size: 80rpx; margin-bottom: 24rpx; }
 .empty-icon { font-size: 80rpx; margin-bottom: 24rpx; }
-.empty-title { font-size: 32rpx; font-weight: bold; color: $facade-text-strong; margin-bottom: 12rpx; }
-.empty-desc { font-size: 26rpx; color: $facade-text-muted; }
+.empty-title { font-size: calc(32rpx * var(--font-scale, 1)); font-weight: bold; color: $facade-text-strong; margin-bottom: 12rpx; }
+.empty-desc { font-size: calc(26rpx * var(--font-scale, 1)); color: $facade-text-muted; }
 </style>
 </style>

+ 37 - 35
cfc-frontend/pages/wealth/index.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="container">
+  <view class="container" :style="{ '--font-scale': fontScale }">
     <!-- 通用登录浮层 -->
     <!-- 通用登录浮层 -->
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <!-- TabTransition overlay -->
     <!-- TabTransition overlay -->
@@ -295,8 +295,10 @@ import {
 } from '../../utils/api.js'
 } from '../../utils/api.js'
 import nav from '../../utils/nav.js'
 import nav from '../../utils/nav.js'
 import config from '../../config.js'
 import config from '../../config.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   components: { TabTransition, WealthEnergyRing, WealthSubScores, BodyWealthAlert, DimensionMemberTabs, FamilyEnergyBar, DimensionIntroCard, DimensionVisitorCard, DimensionSubDims, DimensionPageSkeleton },
   components: { TabTransition, WealthEnergyRing, WealthSubScores, BodyWealthAlert, DimensionMemberTabs, FamilyEnergyBar, DimensionIntroCard, DimensionVisitorCard, DimensionSubDims, DimensionPageSkeleton },
   data() {
   data() {
     return {
     return {
@@ -914,13 +916,13 @@ export default {
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
 .section-title {
 .section-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
 }
 }
 .section-more {
 .section-more {
   position: relative;
   position: relative;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
 }
 }
 /* 触摸目标扩展至 88rpx(微信最小可点区域):文字链 ~34rpx -> 88rpx,视觉零变化 */
 /* 触摸目标扩展至 88rpx(微信最小可点区域):文字链 ~34rpx -> 88rpx,视觉零变化 */
@@ -993,14 +995,14 @@ export default {
 .stream-percent {
 .stream-percent {
   display: block;
   display: block;
   text-align: right;
   text-align: right;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $dim-wealth;
   color: $dim-wealth;
   margin-top: 8rpx;
   margin-top: 8rpx;
 }
 }
 .stream-tip {
 .stream-tip {
   display: block;
   display: block;
   text-align: center;
   text-align: center;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $status-warning-strong;
   color: $status-warning-strong;
   margin-top: 12rpx;
   margin-top: 12rpx;
 }
 }
@@ -1015,17 +1017,17 @@ export default {
   flex-direction: column;
   flex-direction: column;
 }
 }
 .disc-label {
 .disc-label {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $status-warning-strong;
   color: $status-warning-strong;
 }
 }
 .disc-value {
 .disc-value {
-  font-size: 56rpx;
+  font-size: calc(56rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $dim-wealth;
   color: $dim-wealth;
   margin-top: 8rpx;
   margin-top: 8rpx;
 }
 }
 .disc-sub {
 .disc-sub {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $status-warning-strong;
   color: $status-warning-strong;
   margin-top: 8rpx;
   margin-top: 8rpx;
 }
 }
@@ -1049,17 +1051,17 @@ export default {
   margin-left: 8rpx;
   margin-left: 8rpx;
 }
 }
 .disc-sub-label {
 .disc-sub-label {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
 }
 }
 .disc-sub-value {
 .disc-sub-value {
-  font-size: 36rpx;
+  font-size: calc(36rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
   margin-top: 8rpx;
   margin-top: 8rpx;
 }
 }
 .disc-sub-action {
 .disc-sub-action {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $dim-wealth;
   color: $dim-wealth;
   margin-top: 8rpx;
   margin-top: 8rpx;
 }
 }
@@ -1082,13 +1084,13 @@ export default {
   font-size: 44rpx;
   font-size: 44rpx;
 }
 }
 .child-wealth-value {
 .child-wealth-value {
-  font-size: 36rpx;
+  font-size: calc(36rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $dim-wealth;
   color: $dim-wealth;
   margin-top: 8rpx;
   margin-top: 8rpx;
 }
 }
 .child-wealth-label {
 .child-wealth-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-top: 4rpx;
   margin-top: 4rpx;
 }
 }
@@ -1100,7 +1102,7 @@ export default {
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
 }
 }
 .child-trend-title {
 .child-trend-title {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   font-weight: bold;
   font-weight: bold;
 }
 }
@@ -1123,7 +1125,7 @@ export default {
 .trend-day {
 .trend-day {
   flex: 1;
   flex: 1;
   text-align: center;
   text-align: center;
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
 }
 }
 
 
@@ -1157,7 +1159,7 @@ export default {
   font-size: 40rpx;
   font-size: 40rpx;
 }
 }
 .service-label {
 .service-label {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
 }
 }
 
 
@@ -1179,7 +1181,7 @@ export default {
   border-left: 8rpx solid $dim-wealth;
   border-left: 8rpx solid $dim-wealth;
 }
 }
 .brand-strap-text {
 .brand-strap-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $status-warning-strong;
   color: $status-warning-strong;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -1209,7 +1211,7 @@ export default {
 .product-name {
 .product-name {
   display: block;
   display: block;
   padding: 12rpx 12rpx 4rpx;
   padding: 12rpx 12rpx 4rpx;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   overflow: hidden;
   overflow: hidden;
   text-overflow: ellipsis;
   text-overflow: ellipsis;
@@ -1237,7 +1239,7 @@ export default {
   padding: 40rpx 0;
   padding: 40rpx 0;
 }
 }
 .insurance-empty-icon { font-size: 60rpx; }
 .insurance-empty-icon { font-size: 60rpx; }
-.insurance-empty-text { font-size: 24rpx; color: $app-text-muted; margin-top: 12rpx; }
+.insurance-empty-text { font-size: calc(24rpx * var(--font-scale, 1)); color: $app-text-muted; margin-top: 12rpx; }
 .insurance-item {
 .insurance-item {
   padding: 16rpx 0;
   padding: 16rpx 0;
   border-bottom: 1rpx solid $app-surface-subtle;
   border-bottom: 1rpx solid $app-surface-subtle;
@@ -1250,12 +1252,12 @@ export default {
   margin-bottom: 8rpx;
   margin-bottom: 8rpx;
 }
 }
 .insurance-item-name {
 .insurance-item-name {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $app-text;
   color: $app-text;
 }
 }
 .insurance-item-status {
 .insurance-item-status {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   padding: 4rpx 12rpx;
   padding: 4rpx 12rpx;
   border-radius: 8rpx;
   border-radius: 8rpx;
 }
 }
@@ -1267,8 +1269,8 @@ export default {
   justify-content: space-between;
   justify-content: space-between;
   padding: 4rpx 0;
   padding: 4rpx 0;
 }
 }
-.insurance-item-label { font-size: 22rpx; color: $app-text-muted; }
-.insurance-item-value { font-size: 22rpx; color: $app-text-secondary; }
+.insurance-item-label { font-size: calc(22rpx * var(--font-scale, 1)); color: $app-text-muted; }
+.insurance-item-value { font-size: calc(22rpx * var(--font-scale, 1)); color: $app-text-secondary; }
 
 
 /* ===== 财富强项与提升卡片 ===== */
 /* ===== 财富强项与提升卡片 ===== */
 .wealth-insight {
 .wealth-insight {
@@ -1280,7 +1282,7 @@ export default {
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .insight-group-title {
 .insight-group-title {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $app-text;
   color: $app-text;
   margin-bottom: 10rpx;
   margin-bottom: 10rpx;
@@ -1296,11 +1298,11 @@ export default {
 }
 }
 .insight-item-name {
 .insight-item-name {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
 }
 }
 .insight-item-score {
 .insight-item-score {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
@@ -1324,7 +1326,7 @@ export default {
   border-radius: 12rpx;
   border-radius: 12rpx;
 }
 }
 .insight-tip-text {
 .insight-tip-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $dim-wealth;
   color: $dim-wealth;
 }
 }
 
 
@@ -1338,7 +1340,7 @@ export default {
   border: 2rpx solid rgba(245, 158, 11, 0.1);
   border: 2rpx solid rgba(245, 158, 11, 0.1);
 }
 }
 .portrait-tier {
 .portrait-tier {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-wealth;
   color: $dim-wealth;
   font-weight: bold;
   font-weight: bold;
   margin-left: 16rpx;
   margin-left: 16rpx;
@@ -1347,7 +1349,7 @@ export default {
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .portrait-desc {
 .portrait-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   line-height: 1.6;
   line-height: 1.6;
   display: block;
   display: block;
@@ -1375,12 +1377,12 @@ export default {
   background: linear-gradient(135deg, $dim-wealth-tint, $dim-body-tint);
   background: linear-gradient(135deg, $dim-wealth-tint, $dim-body-tint);
 }
 }
 .portrait-dim-name {
 .portrait-dim-name {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   flex: 1;
   flex: 1;
 }
 }
 .portrait-dim-score {
 .portrait-dim-score {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $dim-wealth;
   color: $dim-wealth;
   margin-right: 12rpx;
   margin-right: 12rpx;
@@ -1399,7 +1401,7 @@ export default {
   transition: width 0.3s ease;
   transition: width 0.3s ease;
 }
 }
 .portrait-dim-desc {
 .portrait-dim-desc {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   display: block;
   display: block;
 }
 }
@@ -1411,7 +1413,7 @@ export default {
   margin-top: 16rpx;
   margin-top: 16rpx;
 }
 }
 .portrait-tip-text {
 .portrait-tip-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $brand-primary-deep;
   color: $brand-primary-deep;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
@@ -1427,5 +1429,5 @@ export default {
   gap: 12rpx;
   gap: 12rpx;
 }
 }
 .guidance-icon { font-size: 32rpx; flex-shrink: 0; }
 .guidance-icon { font-size: 32rpx; flex-shrink: 0; }
-.guidance-text { font-size: 26rpx; color: $dim-wealth; font-weight: 500; }
-</style>
+.guidance-text { font-size: calc(26rpx * var(--font-scale, 1)); color: $dim-wealth; font-weight: 500; }
+</style>

+ 39 - 37
cfc-frontend/pages/wisdom-detail/index.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <view class="wisdom-container">
+  <view class="wisdom-container" :style="{ '--font-scale': fontScale }">
     <!-- 通用登录浮层 -->
     <!-- 通用登录浮层 -->
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <login-sheet ref="loginSheet" @success="onSheetLoginSuccess" />
     <!-- Tabbar 切换过渡页 -->
     <!-- Tabbar 切换过渡页 -->
@@ -251,8 +251,10 @@ import DimensionPageSkeleton from '../../components/DimensionPageSkeleton.vue'
 import DimensionMemberTabs from '../../components/DimensionMemberTabs.vue'
 import DimensionMemberTabs from '../../components/DimensionMemberTabs.vue'
 import { getVisibleSections, getChildren, getFamilyEnergySandbox, getEnergySandbox, getAssessmentLatestResult, getDanReportByChild, getGutCognitionIndicators, getLatestIndicators, getRadarData, getFamilyMemberList, kickFamilyMemberById } from '../../utils/api.js'
 import { getVisibleSections, getChildren, getFamilyEnergySandbox, getEnergySandbox, getAssessmentLatestResult, getDanReportByChild, getGutCognitionIndicators, getLatestIndicators, getRadarData, getFamilyMemberList, kickFamilyMemberById } from '../../utils/api.js'
 import { parseDate } from '../../utils/format.js'
 import { parseDate } from '../../utils/format.js'
+import fontScaleMixin from '@/mixins/font-scale.js'
 
 
 export default {
 export default {
+  mixins: [fontScaleMixin],
   components: { TabTransition, RadarChart, FamilyEnergyBar, FloatingAvatar, DimensionMemberTabs, DimensionIntroCard, DimensionVisitorCard, DimensionPageSkeleton },
   components: { TabTransition, RadarChart, FamilyEnergyBar, FloatingAvatar, DimensionMemberTabs, DimensionIntroCard, DimensionVisitorCard, DimensionPageSkeleton },
   data() {
   data() {
     return {
     return {
@@ -883,7 +885,7 @@ $c-ink-strong: #1D1D1F;
 }
 }
 
 
 .func-label {
 .func-label {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   font-weight: 500;
   font-weight: 500;
 }
 }
@@ -902,7 +904,7 @@ $c-ink-strong: #1D1D1F;
 }
 }
 
 
 .section-title {
 .section-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
 }
 }
@@ -910,7 +912,7 @@ $c-ink-strong: #1D1D1F;
 /* 页面说明(独占一行,避免与标题挤在同一行) */
 /* 页面说明(独占一行,避免与标题挤在同一行) */
 .section-sub {
 .section-sub {
   flex: 1 1 100%;
   flex: 1 1 100%;
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-subtle;
   color: $app-text-subtle;
   line-height: 1.4;
   line-height: 1.4;
   margin-top: 6rpx;
   margin-top: 6rpx;
@@ -920,7 +922,7 @@ $c-ink-strong: #1D1D1F;
 .section-more {
 .section-more {
   position: relative;
   position: relative;
   flex-shrink: 0;
   flex-shrink: 0;
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $dim-wisdom;
   color: $dim-wisdom;
 }
 }
 /* 触摸目标扩展至 88rpx(微信最小可点区域):文字链 ~34rpx -> 88rpx,视觉零变化 */
 /* 触摸目标扩展至 88rpx(微信最小可点区域):文字链 ~34rpx -> 88rpx,视觉零变化 */
@@ -951,12 +953,12 @@ $c-ink-strong: #1D1D1F;
   margin-right: 10rpx;
   margin-right: 10rpx;
 }
 }
 .explain-title {
 .explain-title {
-  font-size: 30rpx;
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $app-text;
   color: $app-text;
 }
 }
 .explain-text {
 .explain-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   line-height: 1.6;
   line-height: 1.6;
   display: block;
   display: block;
@@ -985,12 +987,12 @@ $c-ink-strong: #1D1D1F;
 .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 { 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-card.no-data { opacity: 0.5; }
 .indicator-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
 .indicator-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
-.indicator-name { font-size: 26rpx; color: $app-text-secondary; font-weight: 500; }
-.indicator-unit { font-size: 22rpx; color: $app-text-muted; }
+.indicator-name { font-size: calc(26rpx * var(--font-scale, 1)); color: $app-text-secondary; font-weight: 500; }
+.indicator-unit { font-size: calc(22rpx * var(--font-scale, 1)); color: $app-text-muted; }
 .indicator-body { margin-bottom: 8rpx; }
 .indicator-body { margin-bottom: 8rpx; }
-.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: $app-border; }
+.indicator-value { font-size: calc(40rpx * var(--font-scale, 1)); font-weight: bold; color: $dim-wisdom; }
+.indicator-placeholder { font-size: calc(26rpx * var(--font-scale, 1)); color: $app-border; }
+.indicator-range { font-size: calc(20rpx * var(--font-scale, 1)); color: $app-border; }
 .bottom-spacer { height: 120rpx; }
 .bottom-spacer { height: 120rpx; }
 
 
 /* DAN 报告卡片 */
 /* DAN 报告卡片 */
@@ -1008,11 +1010,11 @@ $c-ink-strong: #1D1D1F;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
 }
 }
 .dan-report-date {
 .dan-report-date {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
 }
 }
 .dan-status {
 .dan-status {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   padding: 4rpx 16rpx;
   padding: 4rpx 16rpx;
   border-radius: 8rpx;
   border-radius: 8rpx;
 }
 }
@@ -1025,7 +1027,7 @@ $c-ink-strong: #1D1D1F;
   color: $status-warning-strong;
   color: $status-warning-strong;
 }
 }
 .dan-report-desc {
 .dan-report-desc {
-  font-size: 28rpx;
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   font-weight: 500;
   font-weight: 500;
   margin-bottom: 12rpx;
   margin-bottom: 12rpx;
@@ -1035,7 +1037,7 @@ $c-ink-strong: #1D1D1F;
   text-align: right;
   text-align: right;
 }
 }
 .dan-view-link {
 .dan-view-link {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-wisdom;
   color: $dim-wisdom;
 }
 }
 .dan-empty {
 .dan-empty {
@@ -1045,7 +1047,7 @@ $c-ink-strong: #1D1D1F;
   text-align: center;
   text-align: center;
 }
 }
 .dan-empty-text {
 .dan-empty-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
 }
 }
 .avg-badge {
 .avg-badge {
@@ -1066,7 +1068,7 @@ $c-ink-strong: #1D1D1F;
   box-shadow: 0 2rpx 12rpx rgba(99,102,241,0.12);
   box-shadow: 0 2rpx 12rpx rgba(99,102,241,0.12);
 }
 }
 .brand-strap-text {
 .brand-strap-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-wisdom-ink;
   color: $dim-wisdom-ink;
   font-weight: bold;
   font-weight: bold;
   line-height: 1.5;
   line-height: 1.5;
@@ -1085,14 +1087,14 @@ $c-ink-strong: #1D1D1F;
 }
 }
 .guidance-icon { font-size: 32rpx; }
 .guidance-icon { font-size: 32rpx; }
 .guidance-text {
 .guidance-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-wisdom-ink;
   color: $dim-wisdom-ink;
   font-weight: 500;
   font-weight: 500;
 }
 }
 
 
 /* ===== 肠胃与认知卡片 ===== */
 /* ===== 肠胃与认知卡片 ===== */
 .gut-cog-subtitle {
 .gut-cog-subtitle {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $dim-wisdom;
   color: $dim-wisdom;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
   display: block;
   display: block;
@@ -1112,13 +1114,13 @@ $c-ink-strong: #1D1D1F;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
 .gut-indicator-name {
 .gut-indicator-name {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   font-weight: 500;
   font-weight: 500;
   display: block;
   display: block;
 }
 }
 .gut-indicator-impact {
 .gut-indicator-impact {
-  font-size: 18rpx;
+  font-size: calc(18rpx * var(--font-scale, 1));
   color: $dim-wisdom;
   color: $dim-wisdom;
   display: block;
   display: block;
   margin-top: 2rpx;
   margin-top: 2rpx;
@@ -1136,13 +1138,13 @@ $c-ink-strong: #1D1D1F;
   transition: width 0.3s;
   transition: width 0.3s;
 }
 }
 .gut-indicator-value {
 .gut-indicator-value {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   width: 60rpx;
   width: 60rpx;
   text-align: right;
   text-align: right;
 }
 }
 .gut-indicator-status {
 .gut-indicator-status {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   padding: 2rpx 12rpx;
   padding: 2rpx 12rpx;
   border-radius: 10rpx;
   border-radius: 10rpx;
   width: 60rpx;
   width: 60rpx;
@@ -1171,7 +1173,7 @@ $c-ink-strong: #1D1D1F;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .gut-empty-text {
 .gut-empty-text {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
@@ -1192,7 +1194,7 @@ $c-ink-strong: #1D1D1F;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
 .insight-group-title {
 .insight-group-title {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: $app-text;
   color: $app-text;
   margin-bottom: 10rpx;
   margin-bottom: 10rpx;
@@ -1208,11 +1210,11 @@ $c-ink-strong: #1D1D1F;
 }
 }
 .insight-item-name {
 .insight-item-name {
   flex: 1;
   flex: 1;
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
 }
 }
 .insight-item-score {
 .insight-item-score {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
@@ -1236,7 +1238,7 @@ $c-ink-strong: #1D1D1F;
   border-radius: 12rpx;
   border-radius: 12rpx;
 }
 }
 .insight-tip-text {
 .insight-tip-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $dim-wisdom;
   color: $dim-wisdom;
 }
 }
 .insight-empty {
 .insight-empty {
@@ -1246,7 +1248,7 @@ $c-ink-strong: #1D1D1F;
   padding: 30rpx 0;
   padding: 30rpx 0;
 }
 }
 .insight-empty-text {
 .insight-empty-text {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
@@ -1272,7 +1274,7 @@ $c-ink-strong: #1D1D1F;
   border: 2rpx solid rgba(99, 102, 241, 0.1);
   border: 2rpx solid rgba(99, 102, 241, 0.1);
 }
 }
 .portrait-tier {
 .portrait-tier {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $dim-wisdom;
   color: $dim-wisdom;
   font-weight: bold;
   font-weight: bold;
   margin-left: 16rpx;
   margin-left: 16rpx;
@@ -1281,7 +1283,7 @@ $c-ink-strong: #1D1D1F;
   margin-bottom: 24rpx;
   margin-bottom: 24rpx;
 }
 }
 .portrait-desc {
 .portrait-desc {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   color: $app-text-secondary;
   color: $app-text-secondary;
   line-height: 1.6;
   line-height: 1.6;
   display: block;
   display: block;
@@ -1308,12 +1310,12 @@ $c-ink-strong: #1D1D1F;
   font-size: 20rpx;
   font-size: 20rpx;
 }
 }
 .portrait-dim-name {
 .portrait-dim-name {
-  font-size: 24rpx;
+  font-size: calc(24rpx * var(--font-scale, 1));
   color: $app-text;
   color: $app-text;
   flex: 1;
   flex: 1;
 }
 }
 .portrait-dim-score {
 .portrait-dim-score {
-  font-size: 26rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $dim-wisdom;
   color: $dim-wisdom;
   margin-right: 12rpx;
   margin-right: 12rpx;
@@ -1332,7 +1334,7 @@ $c-ink-strong: #1D1D1F;
   transition: width 0.3s ease;
   transition: width 0.3s ease;
 }
 }
 .portrait-dim-desc {
 .portrait-dim-desc {
-  font-size: 20rpx;
+  font-size: calc(20rpx * var(--font-scale, 1));
   color: $app-text-muted;
   color: $app-text-muted;
   display: block;
   display: block;
 }
 }
@@ -1344,8 +1346,8 @@ $c-ink-strong: #1D1D1F;
   margin-top: 16rpx;
   margin-top: 16rpx;
 }
 }
 .portrait-tip-text {
 .portrait-tip-text {
-  font-size: 22rpx;
+  font-size: calc(22rpx * var(--font-scale, 1));
   color: $c-ink-strong;
   color: $c-ink-strong;
   line-height: 1.5;
   line-height: 1.5;
 }
 }
-</style>
+</style>