Bladeren bron

Merge branch 'cfclub' of http://git.iwintrue.com/liaoxg/cfc into cfclub

iwt 1 maand geleden
bovenliggende
commit
dec0b6ca45

+ 2 - 2
cfc-frontend/components/PageBanner.vue

@@ -21,7 +21,7 @@
  *   心(mind/火): #FF6B35
  *   智(wisdom/金): #FFD700
  *   行(action/木): #4CAF50
- *   富(wealth/水): #42A5F5
+ *   富(wealth/水): #F59E0B
  */
 var THEME_STYLES = {
   home: {
@@ -49,7 +49,7 @@ var THEME_STYLES = {
     color: '#FFFFFF'
   },
   wealth: {
-    background: 'linear-gradient(135deg, #42A5F5 0%, #64B5F6 100%)',
+    background: 'linear-gradient(135deg, #F59E0B 0%, #FBBF24 100%)',
     color: '#FFFFFF'
   }
 }

+ 169 - 0
cfc-frontend/components/WealthEnergyRing.vue

@@ -0,0 +1,169 @@
+<template>
+  <view class="wealth-ring">
+    <view class="ring-wrap">
+      <!-- SVG 环形进度 -->
+      <svg class="ring-svg" viewBox="0 0 200 200">
+        <!-- 背景轨道 -->
+        <circle cx="100" cy="100" r="88" fill="none" stroke="#FEF3C7" stroke-width="14" />
+        <!-- 进度弧线 -->
+        <circle
+          class="ring-progress"
+          cx="100" cy="100" r="88" fill="none"
+          stroke="url(#ringGradient)" stroke-width="14" stroke-linecap="round"
+          :stroke-dasharray="circumference" :stroke-dashoffset="progressOffset" />
+        <defs>
+          <linearGradient id="ringGradient" x1="0%" y1="0%" x2="100%" y2="0%">
+            <stop offset="0%" stop-color="#F59E0B" />
+            <stop offset="100%" stop-color="#FBBF24" />
+          </linearGradient>
+        </defs>
+      </svg>
+      <!-- 中心文字 -->
+      <view class="ring-center">
+        <text class="ring-score">{{ score }}</text>
+        <text class="ring-total">/ 100</text>
+        <text class="ring-level">{{ levelText }}</text>
+      </view>
+      <!-- 水波纹 -->
+      <view class="ripple-1"></view>
+      <view class="ripple-2"></view>
+    </view>
+    <view class="ring-slogan">
+      <text class="ring-slogan-text">富足源于利他与坚持</text>
+      <text class="ring-delta" v-if="delta > 0">较上月 ↑ {{ delta }}%</text>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'WealthEnergyRing',
+  props: {
+    score: {
+      type: Number,
+      default: 0
+    },
+    delta: {
+      type: Number,
+      default: 0
+    }
+  },
+  computed: {
+    circumference() {
+      // 2 * Math.PI * 88 ≈ 552.92
+      return 552.92
+    },
+    progressOffset() {
+      var pct = Math.max(0, Math.min(100, this.score)) / 100
+      return Math.round(552.92 * (1 - pct))
+    },
+    levelText() {
+      var s = this.score
+      if (s >= 70) return '富足'
+      if (s >= 30) return '成长'
+      return '播种'
+    }
+  }
+}
+</script>
+
+<style scoped>
+.wealth-ring {
+  margin: 20rpx 30rpx;
+  background: linear-gradient(135deg, #FFF7ED 0%, #FEF3C7 100%);
+  border-radius: 24rpx;
+  padding: 40rpx 30rpx 30rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  box-shadow: 0 4rpx 16rpx rgba(245, 158, 11, 0.12);
+}
+.ring-wrap {
+  position: relative;
+  width: 360rpx;
+  height: 360rpx;
+}
+.ring-svg {
+  width: 360rpx;
+  height: 360rpx;
+  transform: rotate(-90deg);
+  position: relative;
+  z-index: 2;
+}
+.ring-progress {
+  transition: stroke-dashoffset 0.8s ease;
+  filter: drop-shadow(0 2rpx 4rpx rgba(245, 158, 11, 0.3));
+}
+.ring-center {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  z-index: 3;
+}
+.ring-score {
+  font-size: 72rpx;
+  font-weight: bold;
+  color: #92400E;
+  line-height: 1.1;
+}
+.ring-total {
+  font-size: 24rpx;
+  color: #B45309;
+  opacity: 0.7;
+}
+.ring-level {
+  margin-top: 8rpx;
+  font-size: 28rpx;
+  color: #F59E0B;
+  font-weight: 600;
+  letter-spacing: 2rpx;
+}
+.ripple-1,
+.ripple-2 {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 360rpx;
+  height: 360rpx;
+  border-radius: 50%;
+  border: 3rpx solid rgba(245, 158, 11, 0.25);
+  animation: ripple 3s ease-out infinite;
+  pointer-events: none;
+}
+.ripple-2 {
+  animation-delay: 1.5s;
+}
+@keyframes ripple {
+  0% {
+    opacity: 0.6;
+    transform: scale(0.9);
+  }
+  100% {
+    opacity: 0;
+    transform: scale(1.2);
+  }
+}
+.ring-slogan {
+  margin-top: 24rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.ring-slogan-text {
+  font-size: 26rpx;
+  color: #92400E;
+  letter-spacing: 2rpx;
+}
+.ring-delta {
+  margin-top: 8rpx;
+  font-size: 24rpx;
+  color: #F59E0B;
+  font-weight: 500;
+}
+</style>

+ 90 - 91
cfc-frontend/components/WealthSubScores.vue

@@ -1,45 +1,22 @@
 <template>
   <view class="wealth-sub-scores">
-    <view class="section-title">
-      <text class="title">{{ isParent ? '财富维度构成' : '富能量构成' }}</text>
+    <view class="section-header">
+      <text class="title">{{ isParent ? '💧 财富维度构成' : '💧 富能量构成' }}</text>
     </view>
-    
-    <!-- 家长三子维度 -->
-    <view class="sub-grid" v-if="isParent">
-      <view class="sub-item">
-        <view class="sub-label">金钱收入</view>
-        <view class="sub-value" :class="incomeClass">{{ income }}</view>
-        <view class="sub-weight">权重 50%</view>
-      </view>
-      <view class="sub-item">
-        <view class="sub-label">社会成就</view>
-        <view class="sub-value" :class="achievementClass">{{ achievement }}</view>
-        <view class="sub-weight">权重 30%</view>
-      </view>
-      <view class="sub-item">
-        <view class="sub-label">资源网络</view>
-        <view class="sub-value" :class="networkClass">{{ network }}</view>
-        <view class="sub-weight">权重 20%</view>
+
+    <view class="sub-grid">
+      <view class="drop-wrap" v-for="item in subItems" :key="item.key">
+        <view class="drop">
+          <view class="drop-fill" :style="{ height: item.score + '%' }"></view>
+          <text class="drop-score">{{ item.score }}</text>
+        </view>
+        <text class="drop-label">{{ item.label }}</text>
+        <text class="drop-weight">权重 {{ item.weight }}%</text>
       </view>
     </view>
-    
-    <!-- 孩子三子维度 -->
-    <view class="sub-grid" v-else>
-      <view class="sub-item">
-        <view class="sub-label">学业成绩</view>
-        <view class="sub-value" :class="educationClass">{{ education }}</view>
-        <view class="sub-weight">权重 30%</view>
-      </view>
-      <view class="sub-item">
-        <view class="sub-label">社交筹码</view>
-        <view class="sub-value" :class="socialClass">{{ social }}</view>
-        <view class="sub-weight">权重 20%</view>
-      </view>
-      <view class="sub-item">
-        <view class="sub-label">规则博弈</view>
-        <view class="sub-value" :class="pointsClass">{{ points }}</view>
-        <view class="sub-weight">权重 50%</view>
-      </view>
+
+    <view class="drop-tip" v-if="tipText">
+      <text class="drop-tip-text">{{ tipText }}</text>
     </view>
   </view>
 </template>
@@ -81,31 +58,34 @@ export default {
     isParent() {
       return this.role === 'parent'
     },
-    incomeClass() {
-      return this.getScoreClass(this.income)
+    subItems() {
+      if (this.isParent) {
+        return [
+          { key: 'income', label: '金钱收入', score: this.income, weight: 50 },
+          { key: 'achievement', label: '社会成就', score: this.achievement, weight: 30 },
+          { key: 'network', label: '资源网络', score: this.network, weight: 20 }
+        ]
+      }
+      return [
+        { key: 'education', label: '学业成绩', score: this.education, weight: 30 },
+        { key: 'social', label: '社交筹码', score: this.social, weight: 20 },
+        { key: 'points', label: '规则博弈', score: this.points, weight: 50 }
+      ]
     },
-    achievementClass() {
-      return this.getScoreClass(this.achievement)
-    },
-    networkClass() {
-      return this.getScoreClass(this.network)
-    },
-    educationClass() {
-      return this.getScoreClass(this.education)
-    },
-    socialClass() {
-      return this.getScoreClass(this.social)
-    },
-    pointsClass() {
-      return this.getScoreClass(this.points)
-    }
-  },
-  methods: {
-    getScoreClass(score) {
-      if (score >= 80) return 'score-excellent'
-      if (score >= 60) return 'score-good'
-      if (score >= 40) return 'score-average'
-      return 'score-poor'
+    tipText() {
+      var items = this.subItems
+      var filtered = items.filter(function(item) {
+        return item.score > 0
+      })
+      if (filtered.length < 2) return ''
+      var best = filtered.reduce(function(a, b) {
+        return a.score >= b.score ? a : b
+      })
+      var worst = filtered.reduce(function(a, b) {
+        return a.score <= b.score ? a : b
+      })
+      if (best.key === worst.key) return '均衡发展,继续保持!'
+      return best.label + '表现优秀,建议提升' + worst.label
     }
   }
 }
@@ -113,63 +93,82 @@ export default {
 
 <style scoped>
 .wealth-sub-scores {
-  margin: 20rpx;
+  margin: 20rpx 30rpx;
   padding: 24rpx;
   background: #fff;
-  border-radius: 12rpx;
+  border-radius: 20rpx;
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
 }
-.section-title {
+.section-header {
   margin-bottom: 20rpx;
 }
-.section-title .title {
+.title {
   font-size: 30rpx;
   font-weight: bold;
   color: #333;
 }
 .sub-grid {
   display: flex;
-  flex-direction: row;
   justify-content: space-between;
 }
-.sub-item {
+.drop-wrap {
   flex: 1;
-  text-align: center;
-  padding: 20rpx;
-  background: #f9f9f9;
-  border-radius: 8rpx;
   margin: 0 8rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
 }
-.sub-item:first-child {
+.drop-wrap:first-child {
   margin-left: 0;
 }
-.sub-item:last-child {
+.drop-wrap:last-child {
   margin-right: 0;
 }
-.sub-label {
-  font-size: 24rpx;
-  color: #666;
-  margin-bottom: 12rpx;
+.drop {
+  position: relative;
+  width: 120rpx;
+  height: 150rpx;
+  border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
+  background: #FEF3C7;
+  overflow: hidden;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.drop-fill {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  background: linear-gradient(180deg, #FBBF24 0%, #F59E0B 100%);
+  transition: height 0.8s ease;
 }
-.sub-value {
+.drop-score {
+  position: relative;
+  z-index: 1;
   font-size: 40rpx;
   font-weight: bold;
-  margin-bottom: 8rpx;
-}
-.score-excellent {
-  color: #52c41a;
-}
-.score-good {
-  color: #1890ff;
-}
-.score-average {
-  color: #faad14;
+  color: #92400E;
 }
-.score-poor {
-  color: #ff4d4f;
+.drop-label {
+  margin-top: 12rpx;
+  font-size: 24rpx;
+  color: #333;
+  font-weight: 500;
 }
-.sub-weight {
+.drop-weight {
   font-size: 20rpx;
   color: #999;
+  margin-top: 4rpx;
+}
+.drop-tip {
+  margin-top: 20rpx;
+  padding: 16rpx 20rpx;
+  background: #FFF7ED;
+  border-radius: 12rpx;
+}
+.drop-tip-text {
+  font-size: 24rpx;
+  color: #92400E;
 }
 </style>

+ 11 - 1
cfc-frontend/pages/index-home/index.vue

@@ -396,6 +396,7 @@ export default {
 
       // 会员状态(沙盘下方会员入口使用)
       isMember: false,
+      isLifetime: false,
       membershipDays: 0
     }
   },
@@ -424,6 +425,7 @@ export default {
     // 会员入口显示:非会员显示开通;会员剩余≤30天显示续费
     showMemberEntry: function() {
       if (!this.isLoggedIn()) return false
+      if (this.isLifetime) return false
       if (!this.isMember) return true
       return this.membershipDays > 0 && this.membershipDays <= 30
     },
@@ -431,14 +433,17 @@ export default {
       return (uni.getStorageSync('role') || 'parent') === 'child'
     },
     memberEntryTitle: function() {
+      if (this.isLifetime) return '终身会员 · 永久有效'
       if (!this.isMember) return '开通会员,解锁全部特权'
       return '会员即将到期,续费恢复权益'
     },
     memberEntryDesc: function() {
+      if (this.isLifetime) return '享全平台权益,无需续费'
       if (!this.isMember) return '享专属折扣 · 成长服务 · 规划指导'
       return '剩余 ' + this.membershipDays + ' 天,续费保持权益不中断'
     },
     memberEntryBtn: function() {
+      if (this.isLifetime) return '已拥有'
       return this.isMember ? '立即续费' : '立即开通'
     }
   },
@@ -810,10 +815,15 @@ export default {
       var that = this
       getMyMembership().then(function(res) {
         var m = res.data || {}
-        that.isMember = !!(m.memberLevel && m.memberLevel !== 'FREE') || !!(m.levelCode && m.levelCode !== 'FREE')
+        var level = m.memberLevel || m.levelCode || ''
+        that.isLifetime = (level === 'LIFETIME')
+        that.isMember = that.isLifetime || !!(level && level !== 'FREE')
         var mem = m.membership || m
         if (mem.daysRemaining != null) {
           that.membershipDays = mem.daysRemaining
+        } else if (that.isLifetime) {
+          // 终身会员:永久有效,不显示剩余天数
+          that.membershipDays = 0
         }
       }).catch(function() {})
     },

+ 30 - 7
cfc-frontend/pages/membership/upgrade.vue

@@ -160,13 +160,13 @@ export default {
       isFree: true,
       currentLevelName: '免费用户',
       compareData: [
-        { name: '商品折扣', free: '普通价格', family: '9折', premium: '8折' },
-        { name: '家庭管理', free: '基础功能', family: '全部功能', premium: '全部功能+优先响应' },
-        { name: '管家服务', free: '—', family: '—', premium: '每周一次' },
-        { name: '推荐佣金', free: '不可参与', family: '最高15%', premium: '最高20%' },
-        { name: '专属活动', free: '部分参与', family: '全部参与', premium: '优先参与' },
-        { name: '成长报告', free: '月度', family: '每周+深度', premium: '每日+深度+专家解读' },
-        { name: '任务配额', free: '每日5个', family: '不限量', premium: '不限量+优先审核' }
+        { name: '商品折扣', free: '普通价格', family: '9折', premium: '8折', lifetime: '全场最低价' },
+        { name: '家庭管理', free: '基础功能', family: '全部功能', premium: '全部功能+优先响应', lifetime: '全部功能+专属管家' },
+        { name: '管家服务', free: '—', family: '—', premium: '每周一次', lifetime: '专属管家7×24h' },
+        { name: '推荐佣金', free: '不可参与', family: '最高15%', premium: '最高20%', lifetime: '最高25%+团队分红' },
+        { name: '专属活动', free: '部分参与', family: '全部参与', premium: '优先参与', lifetime: 'VIP专属+定制活动' },
+        { name: '成长报告', free: '月度', family: '每周+深度', premium: '每日+深度+专家解读', lifetime: '实时+AI专家深度解读' },
+        { name: '任务配额', free: '每日5个', family: '不限量', premium: '不限量+优先审核', lifetime: '不限量+专属通道' }
       ],
       periods: [
         { key: 'monthly', label: '月度', unit: '/月' },
@@ -357,6 +357,10 @@ export default {
   background: rgba(255,255,255,0.3);
   color: #fff;
 }
+.badge-lifetime {
+  background: linear-gradient(135deg, #8B5CF6 0%, #A855F7 100%);
+  color: #fff;
+}
 .badge-icon {
   font-size: 20rpx;
   margin-right: 8rpx;
@@ -411,6 +415,13 @@ export default {
   text-align: center;
   display: block;
 }
+.lifetime-hint {
+  font-size: 26rpx;
+  color: #FEF3C7;
+  text-align: center;
+  display: block;
+  font-weight: 500;
+}
 
 /* ===== 升级/续费卡片 ===== */
 .upgrade-card {
@@ -558,6 +569,18 @@ export default {
   color: #8B5CF6;
   font-weight: 600;
 }
+.cell-lifetime {
+  background: #F5F5F5;
+  color: #999;
+}
+.cell-lifetime.disabled {
+  color: #999;
+}
+.header-row .cell-lifetime {
+  background: #F5F5F5;
+  color: #999;
+  font-weight: 600;
+}
 .header-row .compare-cell {
   font-size: 24rpx;
   font-weight: 600;

+ 308 - 265
cfc-frontend/pages/wealth/index.vue

@@ -30,23 +30,42 @@
         @select="onFamilyMemberSelect"
         @removed="loadFamilyMembersVisible" />
 
-      <!-- 模式切换 / 退出切换入口(家长未切时显示"切换到孩子视角";已切时显示"退出切换") -->
- <!-- 已切孩子态:点击"退出切换"回到家长模式 -->
- <view v-if="isSwitchedChild" class="exit-switch" @click="exitSwitch">
-   <text>🔄 退出切换</text>
- </view>
- <!-- 家长且未切孩子态:此处展示"切换到孩子视角",点击完成模式切换 -->
- <view v-else class="exit-switch" @click="onSwitchMode">
-   <text>👶 切换到孩子视角</text>
- </view>
-
       <!-- 身克富杠杆警告 -->
-      <body-wealth-alert 
-        :status="bodyWealthStatus" 
-        :message="bodyWealthMessage" 
+      <body-wealth-alert
+        :status="bodyWealthStatus"
+        :message="bodyWealthMessage"
         :showTip="true" />
 
-<!-- 财富子维度卡片 -->
+      <!-- 财富能量环 -->
+      <WealthEnergyRing
+        :score="wealthScore"
+        :delta="deltaPercent" />
+
+      <!-- 成长溪流 -->
+      <view class="section stream-section">
+        <view class="section-header">
+          <text class="section-title">📈 成长溪流</text>
+        </view>
+        <view class="stream-stages">
+          <view
+            class="stage-card"
+            :class="{ active: stage.key === currentStage }"
+            v-for="stage in streamStages"
+            :key="stage.key">
+            <text class="stage-icon">{{ stage.icon }}</text>
+            <text class="stage-name">{{ stage.name }}</text>
+            <text class="stage-desc">{{ stage.desc }}</text>
+            <text class="stage-range">{{ stage.range }}</text>
+          </view>
+        </view>
+        <view class="stream-water">
+          <view class="stream-water-fill" :style="{ width: wealthScore + '%' }"></view>
+        </view>
+        <text class="stream-percent">水位 {{ wealthScore }}%</text>
+        <text class="stream-tip">{{ streamTip }}</text>
+      </view>
+
+      <!-- 子维度水滴 -->
       <wealth-sub-scores
         :role="role"
         :income="wealthIncome"
@@ -56,52 +75,25 @@
         :social="wealthSocial"
         :points="wealthPoints" />
 
-      <!-- 心的子维度(仅孩子) -->
-      <view class="section" v-if="role !== 'parent'">
-        <view class="section-header">
-          <text class="section-title">🔥 心的子维度</text>
-        </view>
-        <view class="sub-dim-grid heart-sub-dim">
-          <view class="sub-dim-card" @click="childSubDimClick('emotion')">
-            <text class="sub-dim-score">{{ heartEmotionStable || '-' }}</text>
-            <text class="sub-dim-label">情绪稳定</text>
-            <text class="sub-dim-desc">EMI情绪管理</text>
-          </view>
-          <view class="sub-dim-card" @click="childSubDimClick('understanding')">
-            <text class="sub-dim-score">{{ heartUnderstanding || '-' }}</text>
-            <text class="sub-dim-label">理解包容</text>
-            <text class="sub-dim-desc">共情+社交适应</text>
-          </view>
-          <view class="sub-dim-card" @click="childSubDimClick('legacy')">
-            <text class="sub-dim-score">{{ heartLegacy || '-' }}</text>
-            <text class="sub-dim-label">传承传递</text>
-            <text class="sub-dim-desc">未来开放</text>
-          </view>
-        </view>
-      </view>
-
-      <!-- 财富数据(仅家长) -->
+      <!-- 财富数据卡(家长) -->
       <view class="section" v-if="role === 'parent'">
-        <view class="section-header">
-          <text class="section-title">💰 财富数据</text>
+        <view class="disc-card">
+          <text class="disc-label">💰 累计收益</text>
+          <text class="disc-value">¥{{ wealthData.totalEarnings || 0 }}</text>
+          <text class="disc-sub">较上月 ↑ {{ deltaPercent }}%</text>
         </view>
-        <view class="wealth-card">
-          <view class="wealth-item">
-            <text class="wealth-value">{{ wealthData.totalEarnings || 0 }}</text>
-            <text class="wealth-label">累计收益</text>
-          </view>
-          <view class="wealth-divider"></view>
-          <view class="wealth-item">
-            <text class="wealth-value">{{ wealthData.availableAmount || 0 }}</text>
-            <text class="wealth-label">可提现</text>
+        <view class="disc-sub-row">
+          <view class="disc-sub-card" @click="goToIncome">
+            <text class="disc-sub-label">可提现</text>
+            <text class="disc-sub-value">¥{{ wealthData.availableAmount || 0 }}</text>
+            <text class="disc-sub-action">提现 →</text>
           </view>
-          <view class="wealth-divider"></view>
-          <view class="wealth-item">
-            <text class="wealth-value">{{ wealthData.referralCount || 0 }}</text>
-            <text class="wealth-label">邀请人数</text>
+          <view class="disc-sub-card" @click="goToAchievements">
+            <text class="disc-sub-label">邀请人数</text>
+            <text class="disc-sub-value">{{ wealthData.referralCount || 0 }}人</text>
+            <text class="disc-sub-action">邀请 →</text>
           </view>
         </view>
-        <!-- 邀请码复制 -->
         <view class="referral-code-bar" v-if="wealthData.referralCode" @click="copyReferralCode">
           <text class="referral-code-label">我的邀请码</text>
           <text class="referral-code-value">{{ wealthData.referralCode }}</text>
@@ -109,44 +101,47 @@
         </view>
       </view>
 
-      <!-- 增值服务入口 -->
-      <view class="section">
-        <view class="section-header">
-          <text class="section-title">🚀 增值服务</text>
-        </view>
-        <view class="service-grid">
-          <view class="service-item" @click="goToCheckin">
-            <text class="service-icon">📝</text>
-            <text class="service-label">记账打卡</text>
+      <!-- 财富数据卡(孩子) -->
+      <view class="section" v-else>
+        <view class="child-wealth-card">
+          <view class="child-wealth-item">
+            <text class="child-wealth-icon">⭐</text>
+            <text class="child-wealth-value">{{ wealthPoints || 0 }}</text>
+            <text class="child-wealth-label">累计积分</text>
           </view>
-          <view class="service-item" @click="goToInsurance">
-            <text class="service-icon">🛡️</text>
-            <text class="service-label">保单管理</text>
+          <view class="child-wealth-item">
+            <text class="child-wealth-icon">📝</text>
+            <text class="child-wealth-value">{{ taskPercent }}%</text>
+            <text class="child-wealth-label">任务完成</text>
           </view>
-          <view class="service-item" @click="goToCreator">
-            <text class="service-icon">🎨</text>
-            <text class="service-label">创客中心</text>
+          <view class="child-wealth-item">
+            <text class="child-wealth-icon">🏆</text>
+            <text class="child-wealth-value">{{ badgeCount }}</text>
+            <text class="child-wealth-label">已获徽章</text>
+          </view>
+        </view>
+        <view class="child-trend">
+          <text class="child-trend-title">📊 本周成长趋势</text>
+          <view class="child-trend-bars">
+            <view class="trend-bar" v-for="(h, i) in weekTrend" :key="i" :style="{ height: h + '%' }"></view>
+          </view>
+          <view class="child-trend-days">
+            <text class="trend-day" v-for="(d, i) in weekDays" :key="i">{{ d }}</text>
           </view>
         </view>
       </view>
 
-      <!-- 消费中心 -->
+      <!-- 财富服务 8 宫格 -->
       <view class="section">
         <view class="section-header">
-          <text class="section-title">🛍️ 消费中心</text>
+          <text class="section-title">🚀 财富服务</text>
         </view>
         <view class="service-grid">
-          <view class="service-item" @click="goToShop">
-            <text class="service-icon">🏪</text>
-            <text class="service-label">商城首页</text>
-          </view>
-          <view class="service-item" @click="goToOrders">
-            <text class="service-icon">📋</text>
-            <text class="service-label">我的订单</text>
-          </view>
-          <view class="service-item" @click="goToAfterSales">
-            <text class="service-icon">🔄</text>
-            <text class="service-label">售后服务</text>
+          <view class="service-item" v-for="item in serviceList" :key="item.label" @click="onServiceClick(item.action)">
+            <view class="service-icon-wrap">
+              <text class="service-icon">{{ item.icon }}</text>
+            </view>
+            <text class="service-label">{{ item.label }}</text>
           </view>
         </view>
       </view>
@@ -157,10 +152,6 @@
           <text>👤 个人中心</text>
           <text class="arrow">›</text>
         </view>
-        <view class="menu-item" @click="goToPointsLogs">
-          <text>📊 积分记录</text>
-          <text class="arrow">›</text>
-        </view>
         <view class="menu-item logout-item" @click="logout">
           <text>🚪 退出登录</text>
           <text class="arrow">›</text>
@@ -173,11 +164,11 @@
 <script>
 import TabTransition from '../../components/tab-transition.vue'
 import PageBanner from '../../components/PageBanner.vue'
+import WealthEnergyRing from '../../components/WealthEnergyRing.vue'
 import WealthSubScores from '../../components/WealthSubScores.vue'
 import BodyWealthAlert from '../../components/BodyWealthAlert.vue'
 import FamilyMemberStrip from '../../components/FamilyMemberStrip.vue'
 import {
-  verifyPassword,
   getChildren,
   getWealthDetail,
   getReferralCode,
@@ -187,23 +178,14 @@ import {
 } from '../../utils/api.js'
 
 export default {
-  components: { TabTransition, PageBanner, WealthSubScores, BodyWealthAlert, FamilyMemberStrip },
+  components: { TabTransition, PageBanner, WealthEnergyRing, WealthSubScores, BodyWealthAlert, FamilyMemberStrip },
   data() {
     return {
       showTabTransition: true,
       isLoggedIn: false,
       role: 'parent',
-      isSwitchedChild: false,
       // 五维评分
-      bodyScore: 0,
-      mindScore: 0,
-      wisdomScore: 0,
-      actionScore: 0,
       wealthScore: 0,
-      // 心的子维度(仅孩子有真实数据)
-      heartEmotionStable: null,
-      heartUnderstanding: null,
-      heartLegacy: null,
       // 子维度 - parent
       wealthIncome: null,
       wealthAchievement: null,
@@ -222,10 +204,32 @@ export default {
         referralCount: 0,
         referralCode: ''
       },
+      // 成长溪流
+      deltaPercent: 5.2,
+      streamStages: [
+        { key: 'start', icon: '💧', name: '起步', desc: '新人阶段', range: '0-30%' },
+        { key: 'mid', icon: '🌊', name: '汇流', desc: '成长阶段', range: '30-70%' },
+        { key: 'surge', icon: '🌊🌊', name: '奔涌', desc: '达人阶段', range: '70-100%' }
+      ],
+      // 孩子数据
+      taskPercent: 0,
+      badgeCount: 0,
+      weekTrend: [30, 40, 35, 50, 60, 55, 70],
+      weekDays: ['一', '二', '三', '四', '五', '六', '日'],
+      // 服务列表
+      serviceList: [
+        { icon: '📝', label: '记账打卡', action: 'goToCheckin' },
+        { icon: '🛡️', label: '保单管理', action: 'goToInsurance' },
+        { icon: '🎨', label: '创客中心', action: 'goToCreator' },
+        { icon: '🏪', label: '商城首页', action: 'goToShop' },
+        { icon: '🛒', label: '购物车', action: 'goToCart' },
+        { icon: '📋', label: '我的订单', action: 'goToOrders' },
+        { icon: '🔄', label: '售后服务', action: 'goToAfterSales' },
+        { icon: '📊', label: '积分记录', action: 'goToPointsLogs' }
+      ],
       children: [],
       familyMembersVisible: [],
       selectedMemberId: null,
-      articlesLoading: false,
     }
   },
   computed: {
@@ -234,6 +238,18 @@ export default {
         return uni.getStorageSync('currentChildId')
       }
       return ''
+    },
+    currentStage() {
+      var s = this.wealthScore
+      if (s >= 70) return 'surge'
+      if (s >= 30) return 'mid'
+      return 'start'
+    },
+    streamTip() {
+      var s = this.wealthScore
+      if (s >= 70) return '🎉 已是富足达人,继续引领全家成长!'
+      if (s >= 30) return '💡 坚持分享,下一阶段"奔涌"在望'
+      return '🌱 从今天开始,迈出创富第一步'
     }
   },
   onShow() {
@@ -253,7 +269,6 @@ export default {
       return
     }
     this.role = currentRole
-    this.isSwitchedChild = uni.getStorageSync('isSwitchedChild') || false
 
     this.loadChildren()
     this.loadWealthDetail()
@@ -317,9 +332,6 @@ export default {
             this.wealthEducation = d.wealthEducation
             this.wealthSocial = d.wealthSocial
             this.wealthPoints = d.wealthPoints
-            this.heartEmotionStable = d.heartEmotionStable
-            this.heartUnderstanding = d.heartUnderstanding
-            this.heartLegacy = d.heartLegacy
           }
           // 身克富杠杆状态
           this.bodyWealthStatus = d.bodyWealthStatus || 'normal'
@@ -366,78 +378,6 @@ export default {
         }
       })
     },
-    onSwitchMode() {
-      if (this.role === 'child') {
-        this.exitSwitch()
-        return
-      }
-      // parent → switch to child
-      if (this.children.length === 0) {
-        this.loadChildren()
-        if (this.children.length === 0) {
-          uni.showModal({
-            title: '提示',
-            content: '您还没有添加孩子,请先在家庭成员中添加',
-            success: function(res) {
-              if (res.confirm) {
-                uni.navigateTo({ url: '/pages/profile-extra/family-members' })
-              }
-            }
-          })
-          return
-        }
-      }
-      if (this.children.length === 1) {
-        this.$store.commit('switchToChild', this.children[0].id)
-        this.role = 'child'
-        this.isSwitchedChild = true
-        uni.showToast({ title: '已切换为孩子模式', icon: 'success' })
-        return
-      }
-      var self = this
-      uni.showActionSheet({
-        itemList: this.children.map(function(c) { return c.nickname }),
-        success: function(res) {
-          var selectedChild = self.children[res.tapIndex]
-          self.$store.commit('switchToChild', selectedChild.id)
-          self.role = 'child'
-          self.isSwitchedChild = true
-          uni.showToast({ title: '已切换为' + selectedChild.nickname + '模式', icon: 'success' })
-        }
-      })
-    },
-    exitSwitch() {
-      if (!this.isSwitchedChild) return
-      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) {
-                uni.removeStorageSync('isSwitchedChild')
-                uni.removeStorageSync('currentChildId')
-                self.isSwitchedChild = false
-                self.role = 'parent'
-                if (self.$store && self.$store.commit) {
-                  self.$store.commit('switchBackToParent')
-                }
-                uni.showToast({ title: '已退出切换', icon: 'success' })
-                setTimeout(function() {
-                  uni.reLaunch({ url: '/pages/index-home/index' })
-                }, 1000)
-              } else {
-                uni.showToast({ title: '密码错误', icon: 'none' })
-              }
-            }).catch(function() {
-              uni.showToast({ title: '验证失败', icon: 'none' })
-            })
-          }
-        }
-      })
-    },
     logout() {
       uni.showModal({
         title: '退出登录',
@@ -483,18 +423,12 @@ export default {
     goToNetwork() {
       uni.navigateTo({ url: '/pages/promotion/team' })
     },
-    childSubDimClick(key) {
-      var routes = {
-        education: '/pages/assessment/results',
-        social: '/pages/activity/index',
-        points: '/pages/shop/index',
-        emotion: '/pages/mind-detail/emotion-report',
-        understanding: '/pages/mind-detail/emotion-trend',
-        legacy: '/pages/wishes/index'
-      }
-      var url = routes[key]
-      if (url) {
-        uni.navigateTo({ url: url })
+    goToCart() {
+      uni.navigateTo({ url: '/pages/shop/cart/cart' })
+    },
+    onServiceClick(action) {
+      if (this[action]) {
+        this[action]()
       }
     }
   }
@@ -527,49 +461,198 @@ export default {
   color: #999;
 }
 
-/* 切换区域 */
-.switch-section {
-  margin: 0 30rpx 20rpx;
+/* 成长溪流 */
+.stream-section {
+  background: #fff;
+  border-radius: 20rpx;
+  padding: 24rpx;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
 }
-.btn-switch {
-  background: linear-gradient(135deg, #F59E0B, #FBBF24);
-  color: #fff;
+.stream-stages {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 20rpx;
+}
+.stage-card {
+  flex: 1;
+  margin: 0 8rpx;
+  padding: 20rpx;
+  border-radius: 16rpx;
+  background: #F5F9FC;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.stage-card.active {
+  background: #FFF7ED;
+  border: 2rpx solid #FBBF24;
+}
+.stage-icon {
+  font-size: 44rpx;
+}
+.stage-name {
   font-size: 26rpx;
-  padding: 16rpx 0;
-  border-radius: 40rpx;
+  font-weight: bold;
+  color: #333;
+  margin-top: 8rpx;
+}
+.stage-desc {
+  font-size: 20rpx;
+  color: #999;
+  margin-top: 4rpx;
+}
+.stage-range {
+  font-size: 20rpx;
+  color: #F59E0B;
+  margin-top: 4rpx;
+}
+.stream-water {
+  height: 20rpx;
+  border-radius: 10rpx;
+  background: #FEF3C7;
+  overflow: hidden;
+}
+.stream-water-fill {
+  height: 100%;
+  border-radius: 10rpx;
+  background: linear-gradient(90deg, #F59E0B, #FBBF24);
+  transition: width 0.8s ease;
+}
+.stream-percent {
+  display: block;
+  text-align: right;
+  font-size: 22rpx;
+  color: #F59E0B;
+  margin-top: 8rpx;
+}
+.stream-tip {
+  display: block;
   text-align: center;
-  line-height: 1.5;
+  font-size: 24rpx;
+  color: #92400E;
+  margin-top: 12rpx;
 }
 
-/* 财富数据卡片 */
-.wealth-card {
-  background: #fff;
+/* 财富数据卡 */
+.disc-card {
+  background: linear-gradient(135deg, #FFF7ED, #FEF3C7);
   border-radius: 20rpx;
-  padding: 30rpx 20rpx;
+  padding: 30rpx;
+  margin-bottom: 16rpx;
   display: flex;
-  align-items: center;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
+  flex-direction: column;
+}
+.disc-label {
+  font-size: 26rpx;
+  color: #92400E;
 }
-.wealth-item {
+.disc-value {
+  font-size: 56rpx;
+  font-weight: bold;
+  color: #F59E0B;
+  margin-top: 8rpx;
+}
+.disc-sub {
+  font-size: 24rpx;
+  color: #B45309;
+  margin-top: 8rpx;
+}
+.disc-sub-row {
+  display: flex;
+  margin-bottom: 16rpx;
+}
+.disc-sub-card {
+  flex: 1;
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 24rpx;
+  display: flex;
+  flex-direction: column;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
+}
+.disc-sub-card:first-child {
+  margin-right: 8rpx;
+}
+.disc-sub-card:last-child {
+  margin-left: 8rpx;
+}
+.disc-sub-label {
+  font-size: 24rpx;
+  color: #999;
+}
+.disc-sub-value {
+  font-size: 36rpx;
+  font-weight: bold;
+  color: #333;
+  margin-top: 8rpx;
+}
+.disc-sub-action {
+  font-size: 22rpx;
+  color: #F59E0B;
+  margin-top: 8rpx;
+}
+
+/* 孩子财富卡 */
+.child-wealth-card {
+  display: flex;
+  background: #fff;
+  border-radius: 20rpx;
+  padding: 24rpx 0;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
+}
+.child-wealth-item {
   flex: 1;
   display: flex;
   flex-direction: column;
   align-items: center;
 }
-.wealth-value {
-  font-size: 40rpx;
+.child-wealth-icon {
+  font-size: 44rpx;
+}
+.child-wealth-value {
+  font-size: 36rpx;
   font-weight: bold;
-  color: #F97316;
+  color: #F59E0B;
+  margin-top: 8rpx;
 }
-.wealth-label {
-  font-size: 24rpx;
+.child-wealth-label {
+  font-size: 22rpx;
   color: #999;
+  margin-top: 4rpx;
+}
+.child-trend {
+  margin-top: 16rpx;
+  background: #fff;
+  border-radius: 20rpx;
+  padding: 24rpx;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
+}
+.child-trend-title {
+  font-size: 26rpx;
+  color: #333;
+  font-weight: bold;
+}
+.child-trend-bars {
+  display: flex;
+  align-items: flex-end;
+  height: 120rpx;
+  margin-top: 16rpx;
+}
+.trend-bar {
+  flex: 1;
+  margin: 0 6rpx;
+  background: linear-gradient(180deg, #FBBF24, #F59E0B);
+  border-radius: 6rpx 6rpx 0 0;
+}
+.child-trend-days {
+  display: flex;
   margin-top: 8rpx;
 }
-.wealth-divider {
-  width: 1rpx;
-  height: 60rpx;
-  background: #f0f0f0;
+.trend-day {
+  flex: 1;
+  text-align: center;
+  font-size: 20rpx;
+  color: #999;
 }
 
 /* 邀请码复制条 */
@@ -602,52 +685,14 @@ export default {
   border-radius: 20rpx;
 }
 
-/* 三子维度卡片 */
-.sub-dim-grid {
-  display: flex;
-}
-.sub-dim-card {
-  flex: 1;
-  margin-right: 16rpx;
-  background: #fff;
-  border-radius: 16rpx;
-  padding: 24rpx 16rpx;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
-}
-.sub-dim-card:last-child {
-  margin-right: 0;
-}
-.sub-dim-score {
-  font-size: 48rpx;
-  font-weight: bold;
-  color: #F59E0B;
-}
-.heart-sub-dim .sub-dim-score {
-  color: #FF6B9D;
-}
-.sub-dim-label {
-  font-size: 24rpx;
-  color: #333;
-  margin-top: 8rpx;
-  font-weight: 500;
-}
-.sub-dim-desc {
-  font-size: 20rpx;
-  color: #999;
-  margin-top: 4rpx;
-}
-
-/* 增值服务 */
+/* 服务入口 */
 .service-grid {
   display: flex;
   flex-wrap: wrap;
   background: #fff;
   border-radius: 20rpx;
   padding: 24rpx 16rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
 }
 .service-item {
   width: 25%;
@@ -656,10 +701,19 @@ export default {
   align-items: center;
   padding: 16rpx 0;
 }
-.service-icon {
-  font-size: 48rpx;
+.service-icon-wrap {
+  width: 88rpx;
+  height: 88rpx;
+  border-radius: 24rpx;
+  background: #FFF7ED;
+  display: flex;
+  align-items: center;
+  justify-content: center;
   margin-bottom: 8rpx;
 }
+.service-icon {
+  font-size: 40rpx;
+}
 .service-label {
   font-size: 22rpx;
   color: #666;
@@ -722,15 +776,4 @@ export default {
 .login-prompt .login-btn::after {
   border: none;
 }
-
-/* 退出切换 */
-.exit-switch {
-  margin: 20rpx 30rpx 0;
-  padding: 16rpx 24rpx;
-  background: #FEF3C7;
-  border-radius: 12rpx;
-  text-align: center;
-  font-size: 26rpx;
-  color: #92400E;
-}
 </style>

+ 7 - 4
docs/superpowers/PROJECT-OVERVIEW.md

@@ -1,8 +1,8 @@
 # 浠艾福 项目全景 — 阶段性需求与设计汇总
 
-**文档版本:** v2.6
-**日期:** 2026-08-08
-**状态:** 已确认(v2.1 Phase 2-4 全栈完成)+ 虚拟支付改造(Tasks 1-12 已完成,退款闭环实施中)+ 新用户注册引导(12 Tasks 全栈完成)+ 家庭成员关系条增强(✅ 已实施)+ **TabBar 重构(✅ 4Tab + 中间五维启动器,已提交)**
+**文档版本:** v2.7
+**日期:** 2026-08-09
+**状态:** 已确认(v2.1 Phase 2-4 全栈完成)+ 虚拟支付改造(Tasks 1-12 已完成,退款闭环实施中)+ 新用户注册引导(12 Tasks 全栈完成)+ 家庭成员关系条增强(✅ 已实施)+ TabBar 重构(✅ 4Tab + 中间五维启动器,已提交)+ **LIFETIME 终身会员(✅ 11 Tasks 全栈完成)**
 **维护:** 所有需求变更需更新本文档
 
 ---
@@ -197,13 +197,14 @@
 ### 4.3 家庭会员体系 ⭐ P2
 
 **阶段:** Phase 2
-**状态:** ✅ 全栈完成(MemberSubscriptionService + MembershipController + membership/ 3 前端页面,含 FREE/FAMILY/PREMIUM 三等级价格体系,价格通过 sys_config 可配置,商城升级提示通用化
+**状态:** ✅ 全栈完成(MemberSubscriptionService + MembershipController + membership/ 3 前端页面,含 FREE/FAMILY/PREMIUM/LIFETIME 四等级价格体系,价格通过 membership_levels 表内配置,商城升级提示通用化,**LIFETIME 不可购买仅管理员审核授予**
 
 | 功能 | 关联文档 |
 |------|---------|
 | 一生一世家庭会员(订阅制+推广返利) | `specs/2026-07-09-family-membership-design.md` |
 | 订阅+推广核心实施(P0) | `plans/2026-07-09-family-membership-core.md` |
 | AI健康管家+推荐引擎(P1) | `plans/2026-07-22-comprehensive-implementation.md`(Phase 2 Wave 3) |
+| **LIFETIME 终身会员(方案A:等级扩展+实时聚合+管理员审核)** | `specs/2026-08-07-xaf-partner-ppt-redesign-design.md` + `plans/2026-08-09-lifetime-membership.md` |
 
 ---
 
@@ -236,6 +237,7 @@
 | DAN测评执行记录双角色模型(assessor/planner分离) | 2026-07 | — |
 | 家庭成员辈分重构(全栈) | 2026-07 | `plans/2026-07-07-家庭成员辈分重构实施计划.md` |
 | 会员等级价格体系更新(FREE/FAMILY/PREMIUM) | 2026-07 | `plans/2026-07-28-membership-price-tier-update.md` |
+| **LIFETIME 终身会员(等级扩展+实时聚合+管理员审核)** | **2026-08** | **`plans/2026-08-09-lifetime-membership.md`** |
 
 ---
 
@@ -406,6 +408,7 @@
 | `2026-08-04-report-confirm-member-selector.md` | ✅ 已完成 | 被检测人选择面板整合实现计划(report-confirm.vue 单文件) |
 | `2026-08-04-family-challenge-custom.md` | 🟢 已实施 | 家庭挑战自定义管理(创建/编辑/删除/模板) |
 | `2026-08-08-family-challenge-participation.md` | ✅ 已实施(9 commits:迁移182-185/3实体/ChallengeScoreService/respond端点/评分配置页/小程序同意拒绝+成员多选) | 家庭挑战参与机制重构(任意成员发起/可选参与/同意后开始/方向性评分) |
+| `2026-08-09-lifetime-membership.md` | ✅ 已实施(11 Tasks:实体/DTO/迁移/Mapper/后端API/Web前端/小程序前端/文档) | LIFETIME 终身会员全栈实施计划(方案A:等级扩展+实时聚合+管理员审核) |
 
 ### 计划与设计文档(specs/)