فهرست منبع

refactor(DimensionActivities): redesign card UI with cover gradient and badge layout

openhands 2 ماه پیش
والد
کامیت
d05e785370
2فایلهای تغییر یافته به همراه547 افزوده شده و 397 حذف شده
  1. 301 85
      cfc-frontend/components/DimensionActivities.vue
  2. 246 312
      cfc-frontend/pages/wealth/index.vue

+ 301 - 85
cfc-frontend/components/DimensionActivities.vue

@@ -1,28 +1,87 @@
 <template>
   <view class="section">
+    <!-- 头部 -->
     <view class="section-header">
-      <text class="section-title">🔥 推荐活动</text>
-      <text class="section-more" @click="$emit('moreActivities')">更多 ›</text>
+      <view class="section-header-left">
+        <view class="section-icon-wrap">
+          <text class="section-icon">{{ dimensionIcon }}</text>
+        </view>
+        <text class="section-title">推荐活动</text>
+      </view>
+      <view class="section-more" @click="$emit('moreActivities')">
+        <text class="section-more-text">更多</text>
+        <text class="section-more-arrow">&#x203A;</text>
+      </view>
     </view>
+
+    <!-- 空状态 -->
     <view v-if="!displayActivities || displayActivities.length === 0" class="empty-state">
+      <text class="empty-icon">{{ dimensionIcon }}</text>
       <text class="empty-tip">{{ isLoggedIn ? '暂无相关活动' : '登录后查看更多活动' }}</text>
     </view>
+
+    <!-- 活动卡片列表 -->
     <view class="activity-list" v-if="displayActivities && displayActivities.length > 0">
-      <view class="activity-card" v-for="act in displayActivities" :key="act.id" @click.stop="$emit('activityClick', act)">
-        <image class="activity-cover" :src="act.coverImage || '/static/default-activity.png'" mode="aspectFill" />
-        <view class="activity-info">
-          <text class="activity-name line-clamp-1">{{ act.title }}</text>
-          <view class="weight-badges" v-if="act._badges && act._badges.length">
-            <text class="weight-badge" v-for="badge in act._badges" :key="badge.name" :style="{ background: badge.color + '20', color: badge.color }">{{ badge.name }}{{ badge.weight }}%</text>
+      <view
+        class="activity-card"
+        v-for="(act, index) in displayActivities"
+        :key="act.id"
+        @click.stop="$emit('activityClick', act)"
+      >
+        <!-- 封面图区域 -->
+        <view class="card-cover">
+          <image
+            class="card-cover-img"
+            :src="act.coverImage || '/static/default-activity.png'"
+            mode="aspectFill"
+          />
+          <!-- 渐变遮罩 -->
+          <view class="card-cover-mask"></view>
+          <!-- 序号标签 -->
+          <view class="card-rank" v-if="displayActivities.length > 1">
+            <text class="card-rank-num">{{ index + 1 }}</text>
           </view>
-          <view class="activity-meta">
-            <text class="activity-time">{{ act.startTime }}</text>
+          <!-- 状态标签 -->
+          <view class="card-status" :class="'status-' + (act.status || 'upcoming')">
+            <text class="card-status-dot" v-if="act.status === 'ongoing'"></text>
+            <text class="card-status-text">{{ statusText(act.status) }}</text>
           </view>
-          <view class="activity-bottom">
-            <text class="activity-status" :class="'status-' + (act.status || 'upcoming')">{{ statusText(act.status) }}</text>
-            <text class="activity-fee" v-if="act.priceLabel">{{ act.priceLabel }}</text>
-            <text class="activity-fee" v-else-if="act.price && act.price > 0">{{ formatPriceWithSymbol(act.price) }}</text>
-            <text class="activity-fee fee-free" v-else>免费</text>
+          <!-- 标题 -->
+          <view class="card-title-wrap">
+            <text class="card-title">{{ act.title }}</text>
+          </view>
+        </view>
+
+        <!-- 内容区域 -->
+        <view class="card-content">
+          <!-- 时间和维度标签 -->
+          <view class="card-meta-row">
+            <view class="card-time">
+              <text class="meta-icon">&#x1F552;</text>
+              <text class="meta-text">{{ formatTime(act.startTime) }}</text>
+            </view>
+            <view class="card-badges" v-if="act._badges && act._badges.length">
+              <text
+                class="card-badge"
+                v-for="badge in act._badges"
+                :key="badge.name"
+                :style="{ color: badge.color, borderColor: badge.color + '40' }"
+              >
+                {{ badge.name }}
+              </text>
+            </view>
+          </view>
+
+          <!-- 底部:价格和按钮 -->
+          <view class="card-footer">
+            <view class="card-price-wrap">
+              <text class="card-price" v-if="act.priceLabel">{{ act.priceLabel }}</text>
+              <text class="card-price" v-else-if="act.price && act.price > 0">{{ formatPriceWithSymbol(act.price) }}</text>
+              <text class="card-price-free" v-else>免费</text>
+            </view>
+            <view class="card-action-btn">
+              <text class="card-action-text">了解详情</text>
+            </view>
           </view>
         </view>
       </view>
@@ -32,11 +91,11 @@
 
 <script>
 var DIMENSION_MAP = {
-  body: { name: '身', color: '#FF8C42' },
-  mind: { name: '心', color: '#FF6B9D' },
-  wisdom: { name: '智', color: '#6366F1' },
-  action: { name: '行', color: '#10B981' },
-  wealth: { name: '富', color: '#F59E0B' }
+  body: { name: '身', color: '#FF8C42', icon: '🌏' },
+  mind: { name: '心', color: '#FF6B9D', icon: '🔥' },
+  wisdom: { name: '智', color: '#6366F1', icon: '⚡' },
+  action: { name: '行', color: '#10B981', icon: '🌿' },
+  wealth: { name: '富', color: '#F59E0B', icon: '💧' }
 }
 
 export default {
@@ -46,8 +105,7 @@ export default {
     isLoggedIn: { type: Boolean, default: false }
   },
   data: function() {
-    return {
-    }
+    return {}
   },
   computed: {
     displayActivities: function() {
@@ -56,6 +114,10 @@ export default {
         item._badges = self.parseWeights(item.dimensionWeights)
         return item
       })
+    },
+    dimensionIcon: function() {
+      var map = { body: '🌏', mind: '🔥', wisdom: '⚡', action: '🌿', wealth: '💧' }
+      return map[this.dimensionCode] || '🎯'
     }
   },
   methods: {
@@ -77,6 +139,20 @@ export default {
     statusText: function(status) {
       var map = { upcoming: '即将开始', ongoing: '进行中', ended: '已结束', cancelled: '已取消' }
       return map[status] || '即将开始'
+    },
+    formatTime: function(timeStr) {
+      if (!timeStr) return '待定'
+      var d = new Date(timeStr)
+      if (isNaN(d.getTime())) return timeStr
+      var month = d.getMonth() + 1
+      var day = d.getDate()
+      var hour = d.getHours()
+      var minute = d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes()
+      return month + '月' + day + '日 ' + hour + ':' + minute
+    },
+    formatPriceWithSymbol: function(price) {
+      if (price == null) return '免费'
+      return '¥' + (Number(price) / 100).toFixed(0)
     }
   }
 }
@@ -84,111 +160,251 @@ export default {
 
 <style scoped>
 .section {
-  margin: 20rpx 20rpx;
+  margin: 24rpx 20rpx;
 }
+
+/* ===== 头部 ===== */
 .section-header {
   display: flex;
+  flex-direction: row;
   justify-content: space-between;
   align-items: center;
-  margin-bottom: 20rpx;
+  margin-bottom: 24rpx;
+}
+.section-header-left {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+.section-icon-wrap {
+  width: 44rpx;
+  height: 44rpx;
+  border-radius: 12rpx;
+  background: linear-gradient(135deg, #FF6B9D, #FF8FB1);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 12rpx;
+}
+.section-icon {
+  font-size: 24rpx;
 }
 .section-title {
-  font-size: 30rpx;
-  font-weight: bold;
-  color: #333;
+  font-size: 32rpx;
+  font-weight: 700;
+  color: #1E293B;
+  letter-spacing: 1rpx;
 }
 .section-more {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  padding: 8rpx 20rpx;
+  background: #F1F5F9;
+  border-radius: 24rpx;
+}
+.section-more-text {
   font-size: 24rpx;
-  color: #999;
+  color: #64748B;
+  margin-right: 4rpx;
+}
+.section-more-arrow {
+  font-size: 20rpx;
+  color: #94A3B8;
+}
+
+/* ===== 空状态 ===== */
+.empty-state {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 60rpx 0;
+}
+.empty-icon {
+  font-size: 64rpx;
+  margin-bottom: 16rpx;
+}
+.empty-tip {
+  font-size: 26rpx;
+  color: #94A3B8;
 }
+
+/* ===== 活动列表 ===== */
 .activity-list {
   display: flex;
   flex-direction: column;
+  gap: 24rpx;
 }
+
+/* ===== 活动卡片 ===== */
 .activity-card {
-  display: flex;
-  flex-direction: row;
-  background: #fff;
-  border-radius: 16rpx;
+  background: #FFFFFF;
+  border-radius: 24rpx;
+  overflow: hidden;
+  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06), 0 1rpx 3rpx rgba(0, 0, 0, 0.04);
+  transition: transform 0.2s ease;
+}
+.activity-card:active {
+  transform: scale(0.98);
+}
+
+/* 封面图 */
+.card-cover {
+  position: relative;
+  width: 100%;
+  height: 320rpx;
   overflow: hidden;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
-  margin-bottom: 20rpx;
 }
-.activity-card:active { opacity: 0.8; }
-.activity-cover {
-  width: 220rpx;
+.card-cover-img {
+  width: 100%;
+  height: 100%;
+  background: #F1F5F9;
+}
+.card-cover-mask {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
   height: 200rpx;
-  flex-shrink: 0;
-  background: #f0f0f0;
+  background: linear-gradient(to top, rgba(0, 0, 0, 0.5), transparent);
 }
-.activity-info {
-  flex: 1;
-  padding: 16rpx 20rpx;
+.card-rank {
+  position: absolute;
+  top: 16rpx;
+  left: 16rpx;
+  width: 48rpx;
+  height: 48rpx;
+  border-radius: 14rpx;
+  background: rgba(0, 0, 0, 0.5);
+  backdrop-filter: blur(10rpx);
   display: flex;
-  flex-direction: column;
-  justify-content: space-between;
+  align-items: center;
+  justify-content: center;
 }
-.activity-name {
-  font-size: 28rpx;
-  color: #333;
-  font-weight: 500;
+.card-rank-num {
+  font-size: 24rpx;
+  font-weight: 700;
+  color: #FFFFFF;
 }
-.weight-badges {
+.card-status {
+  position: absolute;
+  top: 16rpx;
+  right: 16rpx;
   display: flex;
   flex-direction: row;
-  flex-wrap: wrap;
-  gap: 6rpx;
-  margin-top: 6rpx;
+  align-items: center;
+  padding: 6rpx 16rpx;
+  border-radius: 20rpx;
+  background: rgba(0, 0, 0, 0.4);
+  backdrop-filter: blur(10rpx);
+}
+.card-status-dot {
+  width: 8rpx;
+  height: 8rpx;
+  border-radius: 50%;
+  background: #22C55E;
+  margin-right: 6rpx;
+  animation: pulse 2s infinite;
+}
+@keyframes pulse {
+  0%, 100% { opacity: 1; }
+  50% { opacity: 0.4; }
 }
-.weight-badge {
-  font-size: 18rpx;
-  padding: 2rpx 10rpx;
-  border-radius: 8rpx;
+.card-status-text {
+  font-size: 22rpx;
+  color: #FFFFFF;
   font-weight: 500;
 }
-.activity-meta {
-  margin-top: 8rpx;
+.card-title-wrap {
+  position: absolute;
+  bottom: 16rpx;
+  left: 20rpx;
+  right: 20rpx;
 }
-.activity-time {
-  font-size: 24rpx;
-  color: #999;
+.card-title {
+  font-size: 32rpx;
+  font-weight: 700;
+  color: #FFFFFF;
+  text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3);
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  overflow: hidden;
 }
-.activity-bottom {
+
+/* 内容区域 */
+.card-content {
+  padding: 20rpx;
+}
+.card-meta-row {
   display: flex;
   flex-direction: row;
-  justify-content: space-between;
   align-items: center;
-  margin-top: 12rpx;
+  margin-bottom: 16rpx;
 }
-.activity-status {
+.card-time {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-right: 16rpx;
+}
+.meta-icon {
   font-size: 22rpx;
-  padding: 4rpx 12rpx;
-  border-radius: 8rpx;
+  margin-right: 6rpx;
 }
-.status-upcoming { background: #FFF7ED; color: #F97316; }
-.status-ongoing { background: #F0FDF4; color: #22C55E; }
-.status-ended { background: #F5F5F5; color: #999; }
-.status-cancelled { background: #FEE2E2; color: #EF4444; }
-.activity-fee {
+.meta-text {
   font-size: 24rpx;
-  color: #F97316;
+  color: #64748B;
+}
+.card-badges {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  gap: 8rpx;
+}
+.card-badge {
+  font-size: 20rpx;
+  padding: 4rpx 12rpx;
+  border-radius: 20rpx;
+  border: 1rpx solid;
   font-weight: 500;
 }
-.fee-free {
-  color: #22C55E;
+
+/* 底部 */
+.card-footer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  padding-top: 16rpx;
+  border-top: 1rpx solid #F1F5F9;
 }
-.empty-state {
+.card-price-wrap {
   display: flex;
-  justify-content: center;
-  padding: 40rpx 0;
+  flex-direction: row;
+  align-items: baseline;
 }
-.empty-tip {
-  font-size: 24rpx;
-  color: #999;
+.card-price {
+  font-size: 30rpx;
+  font-weight: 700;
+  color: #FF6B9D;
 }
-.line-clamp-1 {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
+.card-price-free {
+  font-size: 28rpx;
+  font-weight: 600;
+  color: #22C55E;
+}
+.card-action-btn {
+  padding: 10rpx 24rpx;
+  background: linear-gradient(135deg, #FF6B9D, #FF8FB1);
+  border-radius: 24rpx;
+}
+.card-action-text {
+  font-size: 22rpx;
+  color: #FFFFFF;
+  font-weight: 600;
+}
+.card-action-btn:active {
+  opacity: 0.8;
 }
 </style>

+ 246 - 312
cfc-frontend/pages/wealth/index.vue

@@ -3,184 +3,158 @@
     <!-- TabTransition overlay -->
     <tab-transition v-if="showTabTransition" dimCode="wealth" />
 
-    <!-- 未登录 -->
-    <view v-if="!isLoggedIn" class="login-prompt">
-      <view class="prompt-icon">👤</view>
-      <text class="prompt-title">登录浠艾福</text>
-      <text class="prompt-desc">登录后查看财富能量详情</text>
-      <button class="login-btn" @click="goLogin">登录 / 注册</button>
-    </view>
+    <!-- 品牌头部(始终显示) -->
+    <PageBanner theme="wealth"
+      tagline="利他创富 · 价值共享"
+      quote="富足源于利他与坚持" />
 
-    <template v-else>
-      <!-- 品牌头部 -->
-      <PageBanner theme="wealth"
-        tagline="利他创富 · 价值共享"
-        quote="富足源于利他与坚持" />
+    <!-- 游客专属区块 -->
+    <template v-if="!isLoggedIn">
+      <LoginGuideCard
+        title="登录后查看财富能量详情"
+        :items="[
+          '查看家庭财富能量与子维度评分',
+          '查看专属财富商品和活动推荐',
+          '查看创客中心和推广收益'
+        ]" />
+    </template>
 
-      <!-- 退出切换按钮 -->
-      <view class="exit-switch" v-if="isSwitchedChild" @click="exitSwitch">
-        <text>🔄 退出切换</text>
-      </view>
+    <!-- 登录后:五维能量条 -->
+    <FamilyEnergyBar
+      v-if="isLoggedIn"
+      dimensionCode="wealth"
+      :sandboxData="sandboxData"
+      :dualDimension="dualDimension" />
 
-      <!-- 用户卡片 -->
-      <view class="user-card" @click="goToProfile">
-        <view class="avatar">👤</view>
-        <view class="user-info">
-          <text class="nickname">{{ nickname || '未设置昵称' }}</text>
-          <text class="role">{{ role === 'parent' ? '家长模式' : (role === 'child' ? '孩子模式' : '成长规划师模式') }}</text>
-        </view>
-        <text class="card-arrow">›</text>
-      </view>
+    <!-- 退出切换按钮 -->
+    <view class="exit-switch" v-if="isLoggedIn && isSwitchedChild" @click="exitSwitch">
+      <text>🔄 退出切换</text>
+    </view>
 
-      <!-- 切换按钮(家长模式 + 未切换状态) -->
-      <view class="switch-section" v-if="role === 'parent' && !isSwitchedChild">
-        <button class="btn-switch" @click="onSwitchMode">切换到孩子视角</button>
-      </view>
+    <!-- 切换按钮(家长模式 + 未切换状态) -->
+    <view class="switch-section" v-if="isLoggedIn && role === 'parent' && !isSwitchedChild">
+      <button class="btn-switch" @click="onSwitchMode">切换到孩子视角</button>
+    </view>
 
-      <!-- 财富子维度卡片 -->
-      <view class="section">
-        <view class="section-header">
-          <text class="section-title">💎 财富子维度</text>
+    <!-- 财富子维度卡片 -->
+    <view class="section" v-if="isLoggedIn">
+      <view class="section-header">
+        <text class="section-title">💎 财富子维度</text>
+      </view>
+      <!-- 家长版 -->
+      <view class="sub-dim-grid" v-if="role === 'parent'">
+        <view class="sub-dim-card" @click="goToIncome">
+          <text class="sub-dim-score">{{ wealthIncome || '-' }}</text>
+          <text class="sub-dim-label">金钱收入</text>
+          <text class="sub-dim-desc">累计佣金</text>
         </view>
-        <!-- 家长版 -->
-        <view class="sub-dim-grid" v-if="role === 'parent'">
-          <view class="sub-dim-card" @click="goToIncome">
-            <text class="sub-dim-score">{{ wealthIncome || '-' }}</text>
-            <text class="sub-dim-label">金钱收入</text>
-            <text class="sub-dim-desc">累计佣金</text>
-          </view>
-          <view class="sub-dim-card" @click="goToAchievements">
-            <text class="sub-dim-score">{{ wealthAchievement || '-' }}</text>
-            <text class="sub-dim-label">个人成就</text>
-            <text class="sub-dim-desc">认证成就</text>
-          </view>
-          <view class="sub-dim-card" @click="goToNetwork">
-            <text class="sub-dim-score">{{ wealthNetwork || '-' }}</text>
-            <text class="sub-dim-label">资源网络</text>
-            <text class="sub-dim-desc">推荐关系</text>
-          </view>
+        <view class="sub-dim-card" @click="goToAchievements">
+          <text class="sub-dim-score">{{ wealthAchievement || '-' }}</text>
+          <text class="sub-dim-label">个人成就</text>
+          <text class="sub-dim-desc">认证成就</text>
         </view>
-        <!-- 孩子版 -->
-        <view class="sub-dim-grid" v-else>
-          <view class="sub-dim-card" @click="childSubDimClick('education')">
-            <text class="sub-dim-score">{{ wealthEducation || '-' }}</text>
-            <text class="sub-dim-label">学业成绩</text>
-            <text class="sub-dim-desc">测评综合</text>
-          </view>
-          <view class="sub-dim-card" @click="childSubDimClick('social')">
-            <text class="sub-dim-score">{{ wealthSocial || '-' }}</text>
-            <text class="sub-dim-label">社交筹码</text>
-            <text class="sub-dim-desc">活动参与</text>
-          </view>
-          <view class="sub-dim-card" @click="childSubDimClick('points')">
-            <text class="sub-dim-score">{{ wealthPoints || '-' }}</text>
-            <text class="sub-dim-label">规则博弈</text>
-            <text class="sub-dim-desc">积分效率</text>
-          </view>
+        <view class="sub-dim-card" @click="goToNetwork">
+          <text class="sub-dim-score">{{ wealthNetwork || '-' }}</text>
+          <text class="sub-dim-label">资源网络</text>
+          <text class="sub-dim-desc">推荐关系</text>
         </view>
       </view>
-
-      <!-- 心的子维度(仅孩子) -->
-      <view class="section" v-if="role !== 'parent'">
-        <view class="section-header">
-          <text class="section-title">🔥 心的子维度</text>
+      <!-- 孩子版 -->
+      <view class="sub-dim-grid" v-else>
+        <view class="sub-dim-card" @click="childSubDimClick('education')">
+          <text class="sub-dim-score">{{ wealthEducation || '-' }}</text>
+          <text class="sub-dim-label">学业成绩</text>
+          <text class="sub-dim-desc">测评综合</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 class="sub-dim-card" @click="childSubDimClick('social')">
+          <text class="sub-dim-score">{{ wealthSocial || '-' }}</text>
+          <text class="sub-dim-label">社交筹码</text>
+          <text class="sub-dim-desc">活动参与</text>
+        </view>
+        <view class="sub-dim-card" @click="childSubDimClick('points')">
+          <text class="sub-dim-score">{{ wealthPoints || '-' }}</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="section" v-if="isLoggedIn && role === 'parent'">
+      <view class="section-header">
+        <text class="section-title">💰 财富数据</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-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>
-          <view class="wealth-divider"></view>
-          <view class="wealth-item">
-            <text class="wealth-value">{{ wealthData.referralCount || 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>
-        <!-- 邀请码复制 -->
-        <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>
-          <text class="referral-code-copy">复制</text>
+        <view class="wealth-divider"></view>
+        <view class="wealth-item">
+          <text class="wealth-value">{{ wealthData.referralCount || 0 }}</text>
+          <text class="wealth-label">邀请人数</text>
         </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>
-          <view class="service-item" @click="goToInsurance">
-            <text class="service-icon">🛡️</text>
-            <text class="service-label">保单管理</text>
-          </view>
-          <view class="service-item" @click="goToCreator">
-            <text class="service-icon">🎨</text>
-            <text class="service-label">创客中心</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>
+        <text class="referral-code-copy">复制</text>
       </view>
+    </view>
 
-      <!-- 商品推荐 -->
-      <DimensionProductList
-        v-if="isLoggedIn"
-        dimensionCode="wealth"
-        :familyId="activeChildId"
-        title="为你推荐" />
-
-      <!-- 底部菜单 -->
-      <view class="menu-list">
-        <view class="menu-item" @click="goToProfile">
-          <text>👤 个人中心</text>
-          <text class="arrow">›</text>
-        </view>
-        <view class="menu-item" @click="goToPointsLogs">
-          <text>📊 积分记录</text>
-          <text class="arrow">›</text>
+    <!-- 增值服务入口 -->
+    <view class="section" v-if="isLoggedIn">
+      <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>
-        <view class="menu-item" @click="goToPromotion">
-          <text>📣 推广中心</text>
-          <text class="arrow">›</text>
+        <view class="service-item" @click="goToInsurance">
+          <text class="service-icon">🛡️</text>
+          <text class="service-label">保单管理</text>
         </view>
-        <view class="menu-item logout-item" @click="logout">
-          <text>🚪 退出登录</text>
-          <text class="arrow">›</text>
+        <view class="service-item" @click="goToCreator">
+          <text class="service-icon">🎨</text>
+          <text class="service-label">创客中心</text>
         </view>
       </view>
-    </template>
+    </view>
+
+    <!-- 维度活动 -->
+    <DimensionActivities
+      dimensionCode="wealth"
+      :activities="dimensionActivities"
+      :isLoggedIn="isLoggedIn"
+      @activityClick="goActivityDetail"
+      @moreActivities="goMoreActivities" />
+
+    <!-- 商品推荐 -->
+    <DimensionProductList
+      v-if="isLoggedIn"
+      dimensionCode="wealth"
+      :familyId="activeChildId"
+      title="为你推荐" />
+
+    <!-- 推荐阅读 -->
+    <DimensionArticles
+      dimensionCode="wealth"
+      :articles="wealthArticles"
+      :isLoggedIn="isLoggedIn"
+      @articleClick="goArticleDetail"
+      @moreArticles="goMoreArticles" />
+
+    <!-- 底部占位 -->
+    <view class="bottom-spacer"></view>
+    <AIFloatingAvatar />
   </view>
 </template>
 
@@ -188,20 +162,39 @@
 import TabTransition from '../../components/tab-transition.vue'
 import PageBanner from '../../components/PageBanner.vue'
 import DimensionProductList from '../../components/DimensionProductList.vue'
+import DimensionActivities from '../../components/DimensionActivities.vue'
+import DimensionArticles from '../../components/DimensionArticles.vue'
+import FamilyEnergyBar from '../../components/FamilyEnergyBar.vue'
+import LoginGuideCard from '../../components/LoginGuideCard.vue'
+import AIFloatingAvatar from '../../components/AIFloatingAvatar.vue'
 import {
   verifyPassword,
   getChildren,
   getWealthDetail,
   getReferralCode,
   getReferralSummary,
-  getCommissionSummary
+  getCommissionSummary,
+  getFamilyEnergySandbox,
+  getEnergyOverview,
+  getActivityList,
+  getFeaturedArticles
 } from '../../utils/api.js'
 
 export default {
-  components: { TabTransition, PageBanner, DimensionProductList },
+  components: {
+    TabTransition,
+    PageBanner,
+    DimensionProductList,
+    DimensionActivities,
+    DimensionArticles,
+    FamilyEnergyBar,
+    LoginGuideCard,
+    AIFloatingAvatar
+  },
   data() {
     return {
       showTabTransition: true,
+      isLoggedIn: false,
       role: 'parent',
       isSwitchedChild: false,
       nickname: '',
@@ -211,10 +204,6 @@ export default {
       wisdomScore: 0,
       actionScore: 0,
       wealthScore: 0,
-      // 心的子维度(仅孩子有真实数据)
-      heartEmotionStable: null,
-      heartUnderstanding: null,
-      heartLegacy: null,
       // 子维度 - parent
       wealthIncome: null,
       wealthAchievement: null,
@@ -230,13 +219,16 @@ export default {
         referralCount: 0,
         referralCode: ''
       },
-      children: []
+      children: [],
+      // 能量条相关
+      sandboxData: null,
+      dualDimension: null,
+      // 维度活动和文章
+      dimensionActivities: [],
+      wealthArticles: []
     }
   },
   computed: {
-    isLoggedIn() {
-      return !!uni.getStorageSync('token')
-    },
     activeChildId() {
       if (this.role === 'child') {
         return uni.getStorageSync('currentChildId')
@@ -246,8 +238,9 @@ export default {
   },
   onShow() {
     this.showTabTransition = true
+    this.isLoggedIn = !!uni.getStorageSync('token')
 
-    if (!uni.getStorageSync('token')) {
+    if (!this.isLoggedIn) {
       this._watchPageReady()
       return
     }
@@ -266,12 +259,13 @@ export default {
     this.loadChildren()
     this.loadWealthDetail()
     this.loadWealthData()
+    this.loadSandboxData()
+    // 游客也能浏览活动和文章
+    this.loadDimensionActivities()
+    this.loadFeaturedArticles()
     this._watchPageReady()
   },
   methods: {
-    goLogin() {
-      uni.navigateTo({ url: '/pages/login/login' })
-    },
     _watchPageReady() {
       var self = this
       this.$nextTick(function() {
@@ -315,9 +309,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
           }
         }
       } catch (e) {
@@ -352,6 +343,69 @@ export default {
         console.error('获取佣金统计失败', e)
       }
     },
+    loadSandboxData() {
+      var self = this
+      getFamilyEnergySandbox().then(function(res) {
+        if (res && res.data) {
+          self.sandboxData = res.data
+        }
+      }).catch(function(e) {
+        console.log('获取沙盘数据失败', e)
+      })
+      // 加载双维度(财富与关系)
+      var childId = this.activeChildId
+      if (childId) {
+        getEnergyOverview(childId).then(function(res) {
+          if (res && res.data && res.data.dimensions) {
+            var dims = res.data.dimensions
+            for (var i = 0; i < dims.length; i++) {
+              if (dims[i].code === 'wealth') {
+                self.dualDimension = dims[i]
+                break
+              }
+            }
+          }
+        }).catch(function(e) {
+          console.log('获取能量概览失败', e)
+        })
+      }
+    },
+    loadDimensionActivities() {
+      var self = this
+      getActivityList({ dimensionCode: 'wealth', page: 1, size: 3 }).then(function(res) {
+        if (res && res.data) {
+          var list = Array.isArray(res.data) ? res.data : (res.data.records || [])
+          self.dimensionActivities = list.slice(0, 3)
+        }
+      }).catch(function() { self.dimensionActivities = [] })
+    },
+    loadFeaturedArticles() {
+      var self = this
+      getFeaturedArticles({ size: 5 }).then(function(res) {
+        if (res && res.code === 200 && res.data) {
+          var gradientColors = [
+            'linear-gradient(135deg, #F59E0B, #FBBF24)',
+            'linear-gradient(135deg, #42A5F5, #64B5F6)',
+            'linear-gradient(135deg, #FF8C42, #FFB074)',
+            'linear-gradient(135deg, #FF6B9D, #FF9DBD)',
+            'linear-gradient(135deg, #6366F1, #818CF8)'
+          ]
+          var list = Array.isArray(res.data) ? res.data : (res.data.records || [])
+          self.wealthArticles = list.map(function(item, index) {
+            return {
+              id: item.id,
+              category: item.categoryName || '财富创富',
+              categoryColor: gradientColors[index % gradientColors.length],
+              title: item.title || '',
+              summary: item.summary || '',
+              dimensionWeights: item.dimensionWeights || null,
+              views: item.viewCount ? String(item.viewCount) : '0',
+              date: item.publishedAt ? item.publishedAt.slice(0, 10) : ''
+            }
+          })
+        }
+      }).catch(function() {})
+    },
     copyReferralCode() {
       if (!this.wealthData.referralCode) return
       uni.setClipboardData({
@@ -433,21 +487,6 @@ export default {
         }
       })
     },
-    logout() {
-      uni.showModal({
-        title: '退出登录',
-        content: '确定要退出登录吗?',
-        success: function(res) {
-          if (res.confirm) {
-            uni.clearStorageSync()
-            uni.reLaunch({ url: '/pages/login/login' })
-          }
-        }
-      })
-    },
-    goToProfile() {
-      uni.navigateTo({ url: '/pages/profile/profile' })
-    },
     goToCheckin() {
       uni.navigateTo({ url: '/pages/wealth-sub/checkin' })
     },
@@ -457,12 +496,6 @@ export default {
     goToCreator() {
       uni.navigateTo({ url: '/pages/promotion/index' })
     },
-    goToPointsLogs() {
-      uni.navigateTo({ url: '/pages/points/points' })
-    },
-    goToPromotion() {
-      uni.navigateTo({ url: '/pages/promotion/index' })
-    },
     goToIncome() {
       uni.navigateTo({ url: '/pages/promotion/commission' })
     },
@@ -476,15 +509,26 @@ export default {
       var routes = {
         education: '/pages/assessment/results',
         social: '/pages/activity/index',
-        points: '/pages/points/mall',
-        emotion: '/pages/mind-detail/emotion-report',
-        understanding: '/pages/mind-detail/emotion-trend',
-        legacy: '/pages/wishes/index'
+        points: '/pages/points/mall'
       }
       var url = routes[key]
       if (url) {
         uni.navigateTo({ url: url })
       }
+    },
+    goActivityDetail(act) {
+      if (!act || !act.id) return
+      uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+    },
+    goMoreActivities() {
+      uni.navigateTo({ url: '/pages/activity/index' })
+    },
+    goArticleDetail(article) {
+      var id = article.id || article
+      uni.navigateTo({ url: '/pages/mind-detail/article-detail?id=' + id })
+    },
+    goMoreArticles() {
+      uni.navigateTo({ url: '/pages/article-center/index?dimension=wealth' })
     }
   }
 }
@@ -516,47 +560,6 @@ export default {
   color: #999;
 }
 
-/* 用户卡片 */
-.user-card {
-  display: flex;
-  align-items: center;
-  background: #fff;
-  margin: 0 30rpx 20rpx;
-  border-radius: 20rpx;
-  padding: 30rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
-}
-.avatar {
-  width: 100rpx;
-  height: 100rpx;
-  border-radius: 50%;
-  background: linear-gradient(135deg, #F59E0B, #FBBF24);
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: 48rpx;
-  margin-right: 24rpx;
-  flex-shrink: 0;
-}
-.user-info {
-  flex: 1;
-}
-.nickname {
-  font-size: 34rpx;
-  font-weight: bold;
-  color: #333;
-  margin-bottom: 8rpx;
-}
-.role {
-  font-size: 24rpx;
-  color: #999;
-}
-.card-arrow {
-  color: #ccc;
-  font-size: 40rpx;
-  margin-left: 16rpx;
-}
-
 /* 切换区域 */
 .switch-section {
   margin: 0 30rpx 20rpx;
@@ -655,9 +658,6 @@ export default {
   font-weight: bold;
   color: #F59E0B;
 }
-.heart-sub-dim .sub-dim-score {
-  color: #FF6B9D;
-}
 .sub-dim-label {
   font-size: 24rpx;
   color: #333;
@@ -695,77 +695,6 @@ export default {
   color: #666;
 }
 
-/* 底部菜单 */
-.menu-list {
-  margin: 30rpx 30rpx 0;
-  background: #fff;
-  border-radius: 16rpx;
-}
-.menu-item {
-  padding: 30rpx;
-  border-bottom: 1rpx solid #f0f0f0;
-  display: flex;
-  justify-content: space-between;
-  font-size: 28rpx;
-}
-.menu-item:last-child {
-  border-bottom: none;
-}
-.arrow {
-  color: #ccc;
-  font-size: 32rpx;
-}
-.logout-item {
-  color: #EF4444;
-}
-
-/* 未登录 */
-.login-prompt {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  min-height: 80vh;
-  padding: 60rpx;
-}
-.prompt-icon {
-  font-size: 120rpx;
-  margin-bottom: 30rpx;
-  width: 160rpx;
-  height: 160rpx;
-  line-height: 160rpx;
-  text-align: center;
-  background: #f5f5f5;
-  border-radius: 50%;
-}
-.prompt-title {
-  font-size: 36rpx;
-  font-weight: bold;
-  color: #333;
-  margin-bottom: 16rpx;
-}
-.prompt-desc {
-  font-size: 26rpx;
-  color: #999;
-  text-align: center;
-  margin-bottom: 40rpx;
-}
-.login-prompt .login-btn {
-  width: 60%;
-  height: 80rpx;
-  line-height: 80rpx;
-  background: linear-gradient(135deg, #5B9BD5, #3A7CC4);
-  color: #fff;
-  font-size: 30rpx;
-  font-weight: bold;
-  border-radius: 40rpx;
-  text-align: center;
-  border: none;
-}
-.login-prompt .login-btn::after {
-  border: none;
-}
-
 /* 退出切换 */
 .exit-switch {
   margin: 20rpx 30rpx 0;
@@ -776,4 +705,9 @@ export default {
   font-size: 26rpx;
   color: #92400E;
 }
+
+/* 底部占位 */
+.bottom-spacer {
+  height: 120rpx;
+}
 </style>