Эх сурвалжийг харах

fix: 修复首页10个实现问题(主页风险修复计划)

实施了 docs/superpowers/plans/2026-06-19-homepage-risk-fix.md 中的全部任务:

- A1: FamilyEnergyBar 成员导航 — 页面已存在且已注册,无需修改
- A6: 修复 parent-index.vue 模板孤立 @moreProducts 标签
- A4: child-index.vue onDomainClick 追加 childId 参数
- A5: 补充运动类/艺术类/家务类成就徽章解锁逻辑
- A2: 移除 DimensionActivities 组件自加载 API(父组件已传 prop)
- A3: 移除 DimensionProducts 组件自加载 API(父组件已传 prop)
- A7: wuxing-sandbox preview 模式缓存随机值(Storage 持久化)
- A8: FamilyMemberCard roleLabel 增加前端兜底显示
- A9: 收紧 parent-index 降级路径成员过滤条件,移除 !c.role
- A10: FamilyMemberStrip scroll-view 增加固定高度 160rpx
Sisyphus 3 сар өмнө
parent
commit
c1ade35b5d

+ 1 - 16
cfc-frontend/components/DimensionActivities.vue

@@ -36,32 +36,17 @@ export default {
   },
   data: function() {
     return {
-      activitiesData: []
     }
   },
   computed: {
     displayActivities: function() {
-      return this.activitiesData.length > 0 ? this.activitiesData : this.activities
+      return this.activities
     }
   },
-  created: function() {
-    this.loadActivities()
-  },
   methods: {
     statusText: function(status) {
       var map = { upcoming: '即将开始', ongoing: '进行中', ended: '已结束', cancelled: '已取消' }
       return map[status] || '即将开始'
-    },
-    loadActivities: function() {
-      var self = this
-      import('@/utils/api.js').then(function(api) {
-        api.getActivityList({ dimensionCode: self.dimensionCode, page: 1, size: 6 }).then(function(res) {
-          var records = (res.data && res.data.records) ? res.data.records : []
-          self.activitiesData = records
-        }).catch(function() {
-          // silently fail
-        })
-      })
     }
   }
 }

+ 1 - 16
cfc-frontend/components/DimensionProducts.vue

@@ -28,29 +28,14 @@ export default {
   },
   data: function() {
     return {
-      productsData: []
     }
   },
   computed: {
     displayProducts: function() {
-      return this.productsData.length > 0 ? this.productsData : this.products
+      return this.products
     }
   },
-  created: function() {
-    this.loadProducts()
-  },
   methods: {
-    loadProducts: function() {
-      var self = this
-      import('@/utils/api.js').then(function(api) {
-        api.getProductsByDomain(self.dimensionCode, 1, 6).then(function(res) {
-          var records = (res.data && res.data.records) ? res.data.records : (res.data || [])
-          self.productsData = records
-        }).catch(function() {
-          // silently fail, use props as fallback
-        })
-      })
-    }
   }
 }
 </script>

+ 1 - 1
cfc-frontend/components/FamilyMemberCard.vue

@@ -6,7 +6,7 @@
     </view>
     <text class="member-card__name">{{ member.nickname }}</text>
     <view class="member-card__tags">
-      <text class="member-card__role">{{ member.roleLabel }}</text>
+      <text class="member-card__role">{{ member.roleLabel || (member.memberType === 'child' ? '孩子' : '家长') }}</text>
       <text v-if="member.danLevel" class="member-card__dan">{{ member.danLevel }}</text>
     </view>
     <view v-if="isSelected" class="member-card__check">

+ 1 - 0
cfc-frontend/components/FamilyMemberStrip.vue

@@ -10,6 +10,7 @@
       :scroll-with-animation="true"
       :enhanced="true"
       :show-scrollbar="false"
+      style="height: 160rpx;"
     >
       <view class="member-strip__inner">
         <!-- "全家" 选项 -->

+ 12 - 5
cfc-frontend/components/wuxing-sandbox.vue

@@ -300,13 +300,20 @@ export default {
   mounted: function() {
     var self = this
 
-    // 预览模式:生成随机五维值
+    // 预览模式:生成随机五维值(缓存以避免每次 mount 重算)
     if (this.isPreview) {
-      var scores = []
-      for (var i = 0; i < 5; i++) {
-        scores.push(Math.floor(Math.random() * 51) + 35)
+      var cacheKey = '_wuxing_preview_scores'
+      var cached = uni.getStorageSync(cacheKey)
+      if (cached && Array.isArray(cached) && cached.length === 5) {
+        this.previewScores = cached
+      } else {
+        var scores = []
+        for (var i = 0; i < 5; i++) {
+          scores.push(Math.floor(Math.random() * 51) + 35)
+        }
+        this.previewScores = scores
+        uni.setStorageSync(cacheKey, scores)
       }
-      this.previewScores = scores
     }
 
     // 等待 DOM 就绪后初始化 Canvas

+ 27 - 2
cfc-frontend/pages/index/child-index.vue

@@ -503,6 +503,31 @@ export default {
           this.unlockBadge(2)
         }
 
+        // 按类别统计已完成任务次数,解锁对应徽章
+        var categoryCompletedCount = { '运动类': 0, '艺术类': 0, '家务类': 0 }
+        for (var i = 0; i < rawTasks.length; i++) {
+          var task = rawTasks[i]
+          if (task.status === 'completed') {
+            var cat = task.category || '其他'
+            if (cat === '运动类') {
+              categoryCompletedCount['运动类']++
+            } else if (cat === '艺术类') {
+              categoryCompletedCount['艺术类']++
+            } else if (cat === '家务类') {
+              categoryCompletedCount['家务类']++
+            }
+          }
+        }
+        if (categoryCompletedCount['运动类'] >= 5) {
+          this.unlockBadge(3)
+        }
+        if (categoryCompletedCount['艺术类'] >= 5) {
+          this.unlockBadge(4)
+        }
+        if (categoryCompletedCount['家务类'] >= 5) {
+          this.unlockBadge(5)
+        }
+
         // 加载五维能量概览
         var energyChildId = this.childId
         if (energyChildId) {
@@ -579,9 +604,9 @@ export default {
     // ======================== 导航方法 ========================
     onDomainClick(evt) {
       var code = evt && evt.code
-      if (!code) return
+      if (!code || !this.childId) return
       uni.navigateTo({
-        url: '/pages/energy/detail?code=' + code
+        url: '/pages/energy/detail?childId=' + this.childId + '&code=' + code
       })
     },
     goToRewards() {

+ 3 - 3
cfc-frontend/pages/index/parent-index.vue

@@ -222,11 +222,11 @@
       <DimensionProducts
         dimensionCode="all"
         :products="recommendedProducts"
-        @productClick="goProductDetail" />
+        @productClick="goProductDetail"
+        @moreProducts="goMoreProducts" />
       <view class="error-state" v-if="errorProducts">
         <text class="error-state-text">商品推荐加载失败</text>
       </view>
-        @moreProducts="goMoreProducts" />
 
       <!-- ===== h) 待审核任务 ===== -->
       <view class="review-section animate-fade-in animate-stagger-11" v-if="pendingReviewTasks.length > 0">
@@ -430,7 +430,7 @@ export default {
           // 过滤:仅保留孩子角色成员,排除家长/本人
           var currentUserId = uni.getStorageSync('userId')
           var filteredChildren = dashChildren.filter(function(c) {
-            return c && c.id && c.id !== currentUserId && (c.role === 'child' || c.memberType === 'child' || !c.role)
+            return c && c.id && c.id !== currentUserId && (c.role === 'child' || c.memberType === 'child')
           })
           if (filteredChildren.length > 0) {
             this.children = filteredChildren