Browse Source

feat: replace user-facing '孩子' terminology with '成员'/'家庭成员' across frontend - assessment flow, family member pages, health questionnaires, activity pages, and UI text updates per product decision that system has no 'child' concept; users see only self + family members, child status derived from relationship; internal entity/DB references (Child entity, child_id columns) preserved unchanged

Sisyphus 15 hours ago
parent
commit
2886587a15
70 changed files with 182 additions and 170 deletions
  1. 42 31
      cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java
  2. 5 5
      cfc-frontend/pages/action-detail/index.vue
  3. 3 3
      cfc-frontend/pages/action-detail/member-action-detail.vue
  4. 1 1
      cfc-frontend/pages/activity/activity-detail/activity-detail.vue
  5. 2 2
      cfc-frontend/pages/activity/index.vue
  6. 17 17
      cfc-frontend/pages/ai/chat.vue
  7. 1 1
      cfc-frontend/pages/article-center/article-detail.vue
  8. 1 1
      cfc-frontend/pages/article-center/article-edit.vue
  9. 5 5
      cfc-frontend/pages/assessment/apply.vue
  10. 2 2
      cfc-frontend/pages/assessment/purchase.vue
  11. 1 1
      cfc-frontend/pages/assessment/results.vue
  12. 2 2
      cfc-frontend/pages/assessment/upload-report.vue
  13. 1 1
      cfc-frontend/pages/body-detail/checkin.vue
  14. 6 6
      cfc-frontend/pages/body-detail/index.vue
  15. 1 1
      cfc-frontend/pages/body-detail/member-body-detail.vue
  16. 1 1
      cfc-frontend/pages/child/tasks.vue
  17. 1 1
      cfc-frontend/pages/cognitive-test/language-test.vue
  18. 1 1
      cfc-frontend/pages/cognitive-test/perception-test.vue
  19. 1 1
      cfc-frontend/pages/cognitive-test/speed-test.vue
  20. 1 1
      cfc-frontend/pages/games/1a2b.vue
  21. 1 1
      cfc-frontend/pages/games/schulte.vue
  22. 1 1
      cfc-frontend/pages/games/sudoku.vue
  23. 4 4
      cfc-frontend/pages/growth/create.vue
  24. 1 1
      cfc-frontend/pages/growth/diet-checkin.vue
  25. 1 1
      cfc-frontend/pages/growth/exercise-checkin.vue
  26. 1 1
      cfc-frontend/pages/growth/sleep-checkin.vue
  27. 2 2
      cfc-frontend/pages/growth/upload.vue
  28. 3 3
      cfc-frontend/pages/health-main/index.vue
  29. 4 4
      cfc-frontend/pages/health/challenge-manage.vue
  30. 1 1
      cfc-frontend/pages/health/daily-checkin.vue
  31. 1 1
      cfc-frontend/pages/health/diet-index.vue
  32. 1 1
      cfc-frontend/pages/health/exercise-index.vue
  33. 1 1
      cfc-frontend/pages/health/gut-index.vue
  34. 1 1
      cfc-frontend/pages/health/health-plan-summary.vue
  35. 1 1
      cfc-frontend/pages/health/meditation-index.vue
  36. 11 11
      cfc-frontend/pages/health/report-survey.vue
  37. 2 2
      cfc-frontend/pages/health/sleep-index.vue
  38. 1 1
      cfc-frontend/pages/health/water-index.vue
  39. 1 1
      cfc-frontend/pages/home-pages/components/MicroActionCard.vue
  40. 1 1
      cfc-frontend/pages/home-pages/member-home-detail.vue
  41. 1 1
      cfc-frontend/pages/member-detail/member-detail.vue
  42. 1 1
      cfc-frontend/pages/membership/index.vue
  43. 1 1
      cfc-frontend/pages/membership/upgrade.vue
  44. 2 2
      cfc-frontend/pages/mind-detail/index.vue
  45. 1 1
      cfc-frontend/pages/mind-detail/member-mind-detail.vue
  46. 4 4
      cfc-frontend/pages/parent/child-detail.vue
  47. 1 1
      cfc-frontend/pages/parent/plans/detail.vue
  48. 1 1
      cfc-frontend/pages/parent/plans/index.vue
  49. 2 2
      cfc-frontend/pages/parent/wishes/index.vue
  50. 1 1
      cfc-frontend/pages/profile-extra/children.vue
  51. 2 2
      cfc-frontend/pages/profile-extra/create-child.vue
  52. 1 1
      cfc-frontend/pages/profile-extra/edit-child.vue
  53. 2 2
      cfc-frontend/pages/profile-main/profile.vue
  54. 1 1
      cfc-frontend/pages/profile/components/ProfileHeader.vue
  55. 1 0
      cfc-frontend/pages/promotion/index.vue
  56. 1 1
      cfc-frontend/pages/promotion/team.vue
  57. 1 1
      cfc-frontend/pages/rewards/badge.vue
  58. 4 4
      cfc-frontend/pages/rewards/rewards.vue
  59. 3 3
      cfc-frontend/pages/stats/completion-rate.vue
  60. 4 4
      cfc-frontend/pages/tasks/create-task.vue
  61. 2 2
      cfc-frontend/pages/tasks/review.vue
  62. 1 1
      cfc-frontend/pages/teacher/families.vue
  63. 1 1
      cfc-frontend/pages/tianpan/member-detail.vue
  64. 1 1
      cfc-frontend/pages/tianpan/relation-detail.vue
  65. 1 1
      cfc-frontend/pages/tianpan/traditional.vue
  66. 2 2
      cfc-frontend/pages/user-edit/user-edit.vue
  67. 1 1
      cfc-frontend/pages/wealth-detail/member-wealth-detail.vue
  68. 1 1
      cfc-frontend/pages/wealth-sub/insurance-planning.vue
  69. 1 1
      cfc-frontend/pages/wealth/index.vue
  70. 1 1
      cfc-frontend/pages/wisdom-detail/member-wisdom-detail.vue

+ 42 - 31
cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java

@@ -478,42 +478,46 @@ public class CommissionService {
         Map<String, Object> result = new HashMap<>();
         List<Map<String, Object>> records = new ArrayList<>();
 
-        LambdaQueryWrapper<CommissionRecord> wrapper = new LambdaQueryWrapper<CommissionRecord>()
-                .eq(CommissionRecord::getReferrerId, userId);
-
-        if ("L1".equals(level)) {
-            wrapper.eq(CommissionRecord::getLevel, 1);
-        } else if ("L2".equals(level)) {
-            wrapper.eq(CommissionRecord::getLevel, 2);
+        // 成员来源:users.referrer_id(与 getTeamStats/getTotalTeamSize 口径一致)
+        // 以前用 commission_records,只包含消费过的成员;现在用 users.referrer_id 包含全部推荐关系
+        List<User> memberUsers = new ArrayList<>();
+        if ("L2".equals(level)) {
+            // L2:先查 L1(直接推荐人),再查 L2(L1 成员的推荐人)
+            List<User> l1Users = userMapper.selectList(
+                    new LambdaQueryWrapper<User>().eq(User::getReferrerId, userId));
+            List<Long> l1Ids = new ArrayList<>();
+            for (User u : l1Users) {
+                if (u.getId() != null) {
+                    l1Ids.add(u.getId());
+                }
+            }
+            if (!l1Ids.isEmpty()) {
+                memberUsers = userMapper.selectList(
+                        new LambdaQueryWrapper<User>().in(User::getReferrerId, l1Ids));
+            }
+        } else {
+            // L1 或 ALL:直接推荐人
+            memberUsers = userMapper.selectList(
+                    new LambdaQueryWrapper<User>().eq(User::getReferrerId, userId));
         }
 
-        SortUtil.applySort(wrapper);
-        List<CommissionRecord> allRecords = commissionRecordMapper.selectList(wrapper);
-
+        // 组装成员基础信息
         Map<Long, Map<String, Object>> memberMap = new LinkedHashMap<>();
-        for (CommissionRecord record : allRecords) {
-            Long buyerId = record.getBuyerId();
-            if (buyerId == null) continue;
-
-            if (!memberMap.containsKey(buyerId)) {
-                User member = userMapper.selectById(buyerId);
-                if (member == null) continue;
-
-                Map<String, Object> memberInfo = new HashMap<>();
-                memberInfo.put("userId", buyerId);
-                memberInfo.put("nickname", member.getNickname() != null ? member.getNickname() : "微信用户");
-                memberInfo.put("avatarUrl", member.getAvatar() != null ? member.getAvatar() : "");
-                memberInfo.put("createdAt", member.getCreatedAt());
-                memberInfo.put("orderCount", 0);
-                memberInfo.put("commissionEarned", 0);
-                memberMap.put(buyerId, memberInfo);
-            }
+        for (User member : memberUsers) {
+            if (member.getId() == null) continue;
+            Map<String, Object> memberInfo = new HashMap<>();
+            memberInfo.put("userId", member.getId());
+            memberInfo.put("nickname", member.getNickname() != null ? member.getNickname() : "微信用户");
+            memberInfo.put("avatarUrl", member.getAvatar() != null ? member.getAvatar() : "");
+            memberInfo.put("createdAt", member.getCreatedAt());
+            memberInfo.put("orderCount", 0);
+            memberInfo.put("commissionEarned", 0);
+            memberMap.put(member.getId(), memberInfo);
         }
 
-        // 批量预取成员汇总(避免 N+1):已完成履约订单总额 + 非cancelled佣金总额,循环内直接取用
+        // 批量预取消费订单总额(已履约)
         List<Long> buyerIds = new ArrayList<>(memberMap.keySet());
         Map<Long, Integer> consumptionMap = new HashMap<>();
-        Map<Long, Integer> cfEarnedMap = new HashMap<>();
         if (!buyerIds.isEmpty()) {
             LambdaQueryWrapper<ProductOrder> consumptionWrapper = new LambdaQueryWrapper<ProductOrder>()
                     .in(ProductOrder::getBuyerId, buyerIds)
@@ -522,7 +526,11 @@ public class CommissionService {
                 if (order.getBuyerId() == null || order.getTotalAmount() == null) continue;
                 consumptionMap.merge(order.getBuyerId(), order.getTotalAmount(), Integer::sum);
             }
+        }
 
+        // 批量预取佣金总额(非 cancel 的)
+        Map<Long, Integer> cfEarnedMap = new HashMap<>();
+        if (!buyerIds.isEmpty()) {
             LambdaQueryWrapper<CommissionRecord> cfWrapper = new LambdaQueryWrapper<CommissionRecord>()
                     .eq(CommissionRecord::getReferrerId, userId)
                     .in(CommissionRecord::getBuyerId, buyerIds)
@@ -533,10 +541,12 @@ public class CommissionService {
             }
         }
 
+        // 为每位成员补充层级过滤后的订单数和佣金总额
         for (Map.Entry<Long, Map<String, Object>> entry : memberMap.entrySet()) {
             Long buyerId = entry.getKey();
             Map<String, Object> memberInfo = entry.getValue();
 
+            // 订单数(按层级过滤 commission_records)
             LambdaQueryWrapper<CommissionRecord> orderWrapper = new LambdaQueryWrapper<CommissionRecord>()
                     .eq(CommissionRecord::getReferrerId, userId)
                     .eq(CommissionRecord::getBuyerId, buyerId);
@@ -545,13 +555,14 @@ public class CommissionService {
             } else if ("L2".equals(level)) {
                 orderWrapper.eq(CommissionRecord::getLevel, 2);
             }
-            SortUtil.applySort(orderWrapper);
             Long orderCount = commissionRecordMapper.selectCount(orderWrapper);
             memberInfo.put("orderCount", orderCount != null ? orderCount.intValue() : 0);
 
+            // 佣金总额(按层级过滤)
             LambdaQueryWrapper<CommissionRecord> commissionWrapper = new LambdaQueryWrapper<CommissionRecord>()
                     .eq(CommissionRecord::getReferrerId, userId)
-                    .eq(CommissionRecord::getBuyerId, buyerId);
+                    .eq(CommissionRecord::getBuyerId, buyerId)
+                    .ne(CommissionRecord::getStatus, "cancelled");
             if ("L1".equals(level)) {
                 commissionWrapper.eq(CommissionRecord::getLevel, 1);
             } else if ("L2".equals(level)) {

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

@@ -296,10 +296,10 @@ export default {
       var messages = [
         '一月:新年伊始,增进家庭沟通',
         '二月:春节团聚,珍惜亲子时光',
-        '三月:春暖花开,多陪伴孩子',
+        '三月:春暖花开,多陪伴成员',
         '四月:清明踏青,共享家庭活动',
         '五月:劳动教育,培养家庭责任感',
-        '六月:儿童节,倾听孩子心声',
+        '六月:儿童节,倾听成员心声',
         '七月:暑期陪伴,增进亲子关系',
         '八月:开学准备,共同规划',
         '九月:新学期,建立家庭规则',
@@ -442,14 +442,14 @@ export default {
           for (var i = 0; i < self.children.length; i++) {
             if (self.children[i].memberId === savedChildId) {
               self.activeChildId = savedChildId
-              self.activeChildName = self.children[i].name || self.children[i].nickname || '孩子'
+              self.activeChildName = self.children[i].name || self.children[i].nickname || '成员'
               found = true
               break
             }
           }
           if (!found && self.children.length > 0) {
             self.activeChildId = self.children[0].memberId
-            self.activeChildName = self.children[0].name || self.children[0].nickname || '孩子'
+            self.activeChildName = self.children[0].name || self.children[0].nickname || '成员'
             uni.setStorageSync('currentChildId', self.activeChildId)
           }
           if (self.activeChildId) {
@@ -458,7 +458,7 @@ export default {
         }
         self.childrenChecked = true
       }).catch(function(e) {
-        console.log('获取孩子列表失败', e)
+        console.log('获取成员列表失败', e)
         self.childrenChecked = true
       })
     },

+ 3 - 3
cfc-frontend/pages/action-detail/member-action-detail.vue

@@ -26,7 +26,7 @@
           <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || '孩' }}</text>
         </view>
         <view class="member-info">
-          <text class="member-name">{{ memberInfo.name || '孩子' }}</text>
+          <text class="member-name">{{ memberInfo.name || '成员' }}</text>
           <text class="member-role">行动维度</text>
         </view>
         <view class="member-score" v-if="dualDimension">
@@ -140,10 +140,10 @@ export default {
       var messages = [
         '一月:新年伊始,增进家庭沟通',
         '二月:春节团聚,珍惜亲子时光',
-        '三月:春暖花开,多陪伴孩子',
+        '三月:春暖花开,多陪伴成员',
         '四月:清明踏青,共享家庭活动',
         '五月:劳动教育,培养家庭责任感',
-        '六月:儿童节,倾听孩子心声',
+        '六月:儿童节,倾听成员心声',
         '七月:暑期陪伴,增进亲子关系',
         '八月:开学准备,共同规划',
         '九月:新学期,建立家庭规则',

+ 1 - 1
cfc-frontend/pages/activity/activity-detail/activity-detail.vue

@@ -435,7 +435,7 @@ export default {
 
       var memberId = uni.getStorageSync('currentChildId') || self.registrationChildId
       if (!memberId) {
-        uni.showToast({ title: '请选择孩子身份', icon: 'none' })
+        uni.showToast({ title: '请选择家庭成员身份', icon: 'none' })
         return
       }
 

+ 2 - 2
cfc-frontend/pages/activity/index.vue

@@ -725,7 +725,7 @@ export default {
       var self = this
       var memberId = uni.getStorageSync('currentChildId')
       if (!memberId) {
-        uni.showToast({ title: '请先选择孩子身份', icon: 'none' })
+        uni.showToast({ title: '请先选择家庭成员身份', icon: 'none' })
         return
       }
       activityCheckin({ id: act.activityId || act.id, memberId: memberId }).then(function(res) {
@@ -748,7 +748,7 @@ export default {
           if (res.confirm) {
             var memberId = uni.getStorageSync('currentChildId')
             if (!memberId) {
-              uni.showToast({ title: '请先选择孩子身份', icon: 'none' })
+uni.showToast({ title: '请先选择家庭成员身份', icon: 'none' })
               return
             }
             cancelActivityRegistration({ id: act.activityId || act.id, memberId: memberId }).then(function(res) {

+ 17 - 17
cfc-frontend/pages/ai/chat.vue

@@ -45,41 +45,41 @@
               <text class="suggestion-icon">📋</text>
               <text class="suggestion-text">小明最近任务完成怎么样?</text>
             </view>
-            <view class="welcome-suggestion" v-if="!isNutrition && !isHealthCoach" @click="quickQuestion('我家孩子的能量评分怎么样?')">
+            <view class="welcome-suggestion" v-if="!isNutrition && !isHealthCoach" @click="quickQuestion('我家家庭成员的能量评分怎么样?')">
               <text class="suggestion-icon">⚡</text>
-              <text class="suggestion-text">孩子的能量评分怎么样?</text>
+              <text class="suggestion-text">家庭成员的能量评分怎么样?</text>
             </view>
             <view class="welcome-suggestion" v-if="!isNutrition && !isHealthCoach" @click="quickQuestion('今天有什么需要我做的事情?')">
               <text class="suggestion-icon">✅</text>
               <text class="suggestion-text">今天有什么需要我做的事情?</text>
             </view>
-            <view class="welcome-suggestion" v-if="isNutrition" @click="quickQuestion('根据报告,我的孩子需要补充哪些营养?')">
+            <view class="welcome-suggestion" v-if="isNutrition" @click="quickQuestion('根据报告,家庭成员需要补充哪些营养?')">
               <text class="suggestion-icon">🥦</text>
-              <text class="suggestion-text">根据报告,我的孩子需要补充哪些营养?</text>
+              <text class="suggestion-text">根据报告,家庭成员需要补充哪些营养?</text>
             </view>
             <view class="welcome-suggestion" v-if="isNutrition" @click="quickQuestion('有哪些食物或产品推荐?')">
               <text class="suggestion-icon">🛒</text>
               <text class="suggestion-text">有哪些食物或产品推荐?</text>
             </view>
-            <view class="welcome-suggestion" v-if="isHealthCoach" @click="quickQuestion('孩子挑食怎么办?')">
+            <view class="welcome-suggestion" v-if="isHealthCoach" @click="quickQuestion('家人挑食怎么办?')">
               <text class="suggestion-icon">🍽️</text>
-              <text class="suggestion-text">孩子挑食怎么办?</text>
+              <text class="suggestion-text">家人挑食怎么办?</text>
             </view>
-            <view class="welcome-suggestion" v-if="isHealthCoach" @click="quickQuestion('孩子总生病,是不是抵抗力差?')">
+            <view class="welcome-suggestion" v-if="isHealthCoach" @click="quickQuestion('家人总生病,是不是抵抗力差?')">
               <text class="suggestion-icon">🤧</text>
-              <text class="suggestion-text">孩子总生病,是不是抵抗力差?</text>
+              <text class="suggestion-text">家人总生病,是不是抵抗力差?</text>
             </view>
-            <view class="welcome-suggestion" v-if="isHealthCoach" @click="quickQuestion('怎么知道孩子是什么体质?')">
+            <view class="welcome-suggestion" v-if="isHealthCoach" @click="quickQuestion('怎么知道家人是什么体质?')">
               <text class="suggestion-icon">🔍</text>
-              <text class="suggestion-text">怎么知道孩子是什么体质?</text>
+              <text class="suggestion-text">怎么知道家人是什么体质?</text>
             </view>
-            <view class="welcome-suggestion" v-if="isButler" @click="quickQuestion('我家孩子肠道菌群怎么样?')">
+            <view class="welcome-suggestion" v-if="isButler" @click="quickQuestion('我家成员肠道菌群怎么样?')">
               <text class="suggestion-icon">🦠</text>
-              <text class="suggestion-text">我家孩子肠道菌群怎么样?</text>
+              <text class="suggestion-text">我家成员肠道菌群怎么样?</text>
             </view>
-            <view class="welcome-suggestion" v-if="isButler" @click="quickQuestion('怎么改善孩子挑食问题?')">
+            <view class="welcome-suggestion" v-if="isButler" @click="quickQuestion('怎么改善家人挑食问题?')">
               <text class="suggestion-icon">🥗</text>
-              <text class="suggestion-text">怎么改善孩子挑食问题?</text>
+              <text class="suggestion-text">怎么改善家人挑食问题?</text>
             </view>
             <view class="welcome-suggestion" v-if="isButler" @click="quickQuestion('需要补充什么营养素?')">
               <text class="suggestion-icon">💊</text>
@@ -139,7 +139,7 @@
 <!-- 输入区 -->
      <view class="chat-input-area">
        <view class="chat-input-wrap">
-         <input class="chat-input" v-model="inputText" placeholder="问我关于家庭和孩子的问题..."
+         <input class="chat-input" v-model="inputText" placeholder="问我关于家庭和成员的问题..."
            :disabled="sending" @confirm="sendMessage" confirm-type="send" />
        </view>
        <view class="chat-voice-btn" :class="{ 'voice-recording': isRecording }" @touchstart="startVoiceRecord" @touchend="stopVoiceRecord">
@@ -210,7 +210,7 @@ export default {
         return '我可以基于菌群检测报告,为你提供个性化的营养建议和推荐'
       }
       if (this.isHealthCoach) {
-        return '陪伴孩子健康成长,用提问帮你找到答案'
+        return '陪伴家庭成员健康成长,用提问帮你找到答案'
       }
       if (this.isButler) {
         return '专属健康管家,基于知识库提供个性化健康建议'
@@ -231,7 +231,7 @@ export default {
         var pageName = pageNames[this.fromPage] || this.fromPage
         return '从 ' + pageName + ' 发起,我可以帮你了解:'
       }
-      return '我可以帮你了解孩子的成长情况,比如:'
+      return '我可以帮你了解家庭成员的成长情况,比如:'
     }
   },
   onLoad: function(options) {

+ 1 - 1
cfc-frontend/pages/article-center/article-detail.vue

@@ -137,7 +137,7 @@ export default {
   onShow() {
     var memberId = uni.getStorageSync('currentChildId')
     if (!this.article || this.error) return
-    // 已登录用户(家长/孩子/规划师)均可计时,匿名用户不计时
+    // 已登录用户(家长/成员/规划师)均可计时,匿名用户不计时
     if (this.isLogin) this.startNewReadingSession()
   },
   onHide() { this.pauseReadingTimer() },

+ 1 - 1
cfc-frontend/pages/article-center/article-edit.vue

@@ -57,7 +57,7 @@
         <textarea
           class="form-textarea"
           v-model="content"
-          placeholder="记录孩子的成长点滴..."
+          placeholder="记录成员的成长点滴..."
           maxlength="2000"
         />
         <text class="char-count">{{ content.length }}/2000</text>

+ 5 - 5
cfc-frontend/pages/assessment/apply.vue

@@ -2,7 +2,7 @@
   <view class="container">
     <view class="header">
       <text class="title">申请测评</text>
-      <text class="subtitle">专业的DAN测评,了解孩子的专注力发展</text>
+      <text class="subtitle">专业的DAN测评,助力家庭成员专注力 development</text>
     </view>
 
     <!-- 成长规划师选择(可选) -->
@@ -79,9 +79,9 @@
       </view>
     </view>
 
-    <!-- 孩子选择 -->
+    <!-- 测评人选择 -->
     <view class="section">
-      <view class="section-title">选择孩子</view>
+      <view class="section-title">选择测评人</view>
       <view class="child-selector">
         <view 
           class="child-item" 
@@ -218,7 +218,7 @@ export default {
           }
         }
       } catch (e) {
-        console.error('获取孩子列表失败', e)
+        console.error('获取测评人列表失败', e)
       }
     },
 
@@ -289,7 +289,7 @@ export default {
         return
       }
       if (!this.selectedChildId) {
-        uni.showToast({ title: '请选择孩子', icon: 'none' })
+        uni.showToast({ title: '请先选择测评人', icon: 'none' })
         return
       }
 

+ 2 - 2
cfc-frontend/pages/assessment/purchase.vue

@@ -2,7 +2,7 @@
   <view class="container">
     <view class="header">
       <text class="title">选择测评任务模板</text>
-      <text class="subtitle">选择适合孩子的测评任务模板</text>
+      <text class="subtitle">选择适合测评人的测评任务模板</text>
     </view>
 
     <!-- 家庭数据区 -->
@@ -256,7 +256,7 @@ export default {
       }
       var memberId = uni.getStorageSync('currentChildId')
       if (!memberId) {
-        uni.showToast({ title: '请先选择孩子', icon: 'none' })
+        uni.showToast({ title: '请先选择测评人', icon: 'none' })
         return
       }
 

+ 1 - 1
cfc-frontend/pages/assessment/results.vue

@@ -101,7 +101,7 @@
           <view class="detail-section">
             <text class="detail-title">基本信息</text>
             <view class="detail-row">
-              <text class="detail-label">孩子姓名</text>
+              <text class="detail-label">测评人姓名</text>
               <text class="detail-value">{{ currentReport.childName || '未命名' }}</text>
             </view>
             <view class="detail-row">

+ 2 - 2
cfc-frontend/pages/assessment/upload-report.vue

@@ -6,7 +6,7 @@
     </view>
 
     <view class="section">
-      <view class="section-title">选择孩子</view>
+      <view class="section-title">选择测评人</view>
       <view class="child-selector">
         <view class="child-item"
           :class="{ selected: selectedChildId === child.id }"
@@ -70,7 +70,7 @@ export default {
           }
         }
       } catch (e) {
-        console.error('获取孩子列表失败', e)
+        console.error('获取测评人列表失败', e)
       }
     },
     chooseFile() {

+ 1 - 1
cfc-frontend/pages/body-detail/checkin.vue

@@ -192,7 +192,7 @@ export default {
         return
       }
       if (!this.memberId) {
-        uni.showToast({ title: '孩子ID无效', icon: 'none' })
+        uni.showToast({ title: '成员ID无效', icon: 'none' })
         return
       }
       var self = this

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

@@ -286,7 +286,7 @@ export default {
         '六月:夏日来临,关注肠胃健康',
         '七月:暑期到来,规律运动不可少',
         '八月:秋前调养,提升免疫力',
-        '九月:开学季,关注孩子生长发育',
+        '九月:开学季,关注家庭成员生长发育',
         '十月:国庆长假,注意饮食控制',
         '十一月:秋冬交替,保暖防寒',
         '十二月:年终总结,规划来年健康'
@@ -342,14 +342,14 @@ export default {
           for (var i = 0; i < self.children.length; i++) {
             if (self.children[i].memberId === savedChildId) {
               self.activeChildId = savedChildId
-              self.activeChildName = self.children[i].name || self.children[i].nickname || '孩子'
+              self.activeChildName = self.children[i].name || self.children[i].nickname || '成员'
               found = true
               break
             }
           }
           if (!found && self.children.length > 0) {
             self.activeChildId = self.children[0].memberId
-            self.activeChildName = self.children[0].name || self.children[0].nickname || '孩子'
+            self.activeChildName = self.children[0].name || self.children[0].nickname || '成员'
             uni.setStorageSync('currentChildId', self.activeChildId)
           }
           if (self.activeChildId) {
@@ -358,7 +358,7 @@ export default {
         }
         self.childrenChecked = true
       }).catch(function(e) {
-        console.log('获取孩子列表失败', e)
+        console.log('获取成员列表失败', e)
         self.childrenChecked = true
       })
     },
@@ -465,7 +465,7 @@ export default {
     },
     onChildChanged: function(child) {
       this.activeChildId = child.memberId
-      this.activeChildName = child.name || child.nickname || '孩子'
+      this.activeChildName = child.name || child.nickname || '成员'
       this.loadDashboardData()
     },
     loadFamilyMembersVisible: function() {
@@ -498,7 +498,7 @@ export default {
       }
       if (item.page === 'health-dimensions') {
         if (!this.activeChildId) {
-          uni.showToast({ title: '请先选择孩子', icon: 'none' })
+          uni.showToast({ title: '请先选择家庭成员', icon: 'none' })
           return
         }
         uni.navigateTo({ url: '/pages/body-detail/health-dimensions?memberId=' + this.activeChildId })

+ 1 - 1
cfc-frontend/pages/body-detail/member-body-detail.vue

@@ -14,7 +14,7 @@
         <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || '孩' }}</text>
       </view>
       <view class="member-info">
-        <text class="member-name">{{ memberInfo.name || '孩子' }}</text>
+        <text class="member-name">{{ memberInfo.name || '成员' }}</text>
         <text class="member-role">身体维度</text>
       </view>
       <view class="member-score" v-if="dualDimension">

+ 1 - 1
cfc-frontend/pages/child/tasks.vue

@@ -240,7 +240,7 @@ export default {
         res = await getTodayTasks(currentChild.id)
         this.tasks = res.data || []
       } catch (e) {
-        console.error('加载孩子任务失败', e)
+        console.error('加载成员任务失败', e)
       } finally {
         this.loading = false
       }

+ 1 - 1
cfc-frontend/pages/cognitive-test/language-test.vue

@@ -220,7 +220,7 @@ export default {
     submitResult: function() {
       var memberId = this.memberId || uni.getStorageSync('currentChildId') || ''
       if (!memberId) {
-        uni.showToast({ title: '请先选择孩子', icon: 'none' })
+        uni.showToast({ title: '请先选择家庭成员', icon: 'none' })
         return
       }
       submitCognitiveSelfTest(memberId, 'languageScore', this.score)

+ 1 - 1
cfc-frontend/pages/cognitive-test/perception-test.vue

@@ -219,7 +219,7 @@ export default {
     submitResult: function() {
       var memberId = this.memberId || uni.getStorageSync('currentChildId') || ''
       if (!memberId) {
-        uni.showToast({ title: '请先选择孩子', icon: 'none' })
+        uni.showToast({ title: '请先选择家庭成员', icon: 'none' })
         return
       }
       submitCognitiveSelfTest(memberId, 'perceptionScore', this.score)

+ 1 - 1
cfc-frontend/pages/cognitive-test/speed-test.vue

@@ -298,7 +298,7 @@ export default {
       if (this.submitting) return
       var memberId = this.memberId || uni.getStorageSync('currentChildId') || ''
       if (!memberId) {
-        uni.showToast({ title: '请先选择孩子', icon: 'none' })
+        uni.showToast({ title: '请先选择家庭成员', icon: 'none' })
         return
       }
       this.submitting = true

+ 1 - 1
cfc-frontend/pages/games/1a2b.vue

@@ -100,7 +100,7 @@ export default {
           }
         }
       } catch (e) {
-        console.error('获取孩子ID失败', e)
+        console.error('获取成员ID失败', e)
       }
     },
     generateAnswer() {

+ 1 - 1
cfc-frontend/pages/games/schulte.vue

@@ -92,7 +92,7 @@ export default {
         }
       }
     } catch (e) {
-      console.error('获取孩子ID失败', e)
+      console.error('获取成员ID失败', e)
     }
   },
     startGame() {

+ 1 - 1
cfc-frontend/pages/games/sudoku.vue

@@ -204,7 +204,7 @@ export default {
           }
         }
       } catch (e) {
-        console.error('获取孩子ID失败', e)
+        console.error('获取成员ID失败', e)
       }
     },
     isCellSelected(row, col) {

+ 4 - 4
cfc-frontend/pages/growth/create.vue

@@ -9,7 +9,7 @@
         <view class="source-card" :class="sourceType === 'manual' ? 'source-active' : ''" @click="sourceType = 'manual'">
           <text class="source-icon">📝</text>
           <text class="source-name">手动创建</text>
-          <text class="source-desc">填写孩子基本信息</text>
+          <text class="source-desc">填写成员基本信息</text>
         </view>
         <view class="source-card" :class="sourceType === 'upload' ? 'source-active' : ''" @click="sourceType = 'upload'">
           <text class="source-icon">📄</text>
@@ -25,10 +25,10 @@
 
       <view class="form" v-if="sourceType === 'manual'">
       <view class="form-item">
-        <text class="label">孩子</text>
+        <text class="label">成员</text>
         <view class="child-select" @click="selectChild">
           <text class="select-text" v-if="selectedChild">{{ selectedChild.nickname || selectedChild.name }}</text>
-          <text class="select-placeholder" v-else>请选择孩子</text>
+          <text class="select-placeholder" v-else>请选择成员</text>
           <text class="select-arrow">›</text>
         </view>
       </view>
@@ -189,7 +189,7 @@ export default {
     },
     async submitManual() {
       if (!this.formData.memberId) {
-        uni.showToast({ title: '请选择孩子', icon: 'none' })
+        uni.showToast({ title: '请选择成员', icon: 'none' })
         return
       }
 

+ 1 - 1
cfc-frontend/pages/growth/diet-checkin.vue

@@ -338,7 +338,7 @@ export default {
       var hasPhoto = self.form.photos && self.form.photos.length > 0
       var hasVoice = self.form.voicePath || (self.form.voiceText && self.form.voiceText.trim())
       if (!hasText && !hasPhoto && !hasVoice) { uni.showToast({ title: '请填写内容或添加图片/语音', icon: 'none' }); return }
-      if (!self.memberId) { uni.showToast({ title: '孩子ID无效', icon: 'none' }); return }
+      if (!self.memberId) { uni.showToast({ title: '成员ID无效', icon: 'none' }); return }
       self.submitting = true
       try {
         var photoUrls = []

+ 1 - 1
cfc-frontend/pages/growth/exercise-checkin.vue

@@ -425,7 +425,7 @@ export default {
       var hasPhoto = self.form.photos && self.form.photos.length > 0
       var hasVoice = self.form.voicePath || (self.form.voiceText && self.form.voiceText.trim())
       if (!hasDuration && !hasPhoto && !hasVoice) { uni.showToast({ title: '请填写运动时长或添加图片/语音', icon: 'none' }); return }
-      if (!self.memberId) { uni.showToast({ title: '孩子ID无效', icon: 'none' }); return }
+      if (!self.memberId) { uni.showToast({ title: '成员ID无效', icon: 'none' }); return }
       self.submitting = true
       try {
         var photoUrls = []

+ 1 - 1
cfc-frontend/pages/growth/sleep-checkin.vue

@@ -151,7 +151,7 @@ export default {
       if (!self.form.sleepTime) { uni.showToast({ title: '请选择入睡时间', icon: 'none' }); return }
       if (!self.form.wakeTime) { uni.showToast({ title: '请选择醒来时间', icon: 'none' }); return }
       if (self.form.sleepTime === self.form.wakeTime) { uni.showToast({ title: '入睡和醒来时间不能相同', icon: 'none' }); return }
-      if (!self.memberId) { uni.showToast({ title: '孩子ID无效', icon: 'none' }); return }
+      if (!self.memberId) { uni.showToast({ title: '成员ID无效', icon: 'none' }); return }
       self.submitting = true
       try {
         var sleepParts = self.form.sleepTime.split(':')

+ 2 - 2
cfc-frontend/pages/growth/upload.vue

@@ -7,10 +7,10 @@
 
     <view class="form" v-if="step === 1">
       <view class="form-item">
-        <text class="label">孩子</text>
+        <text class="label">成员</text>
         <view class="child-select" @click="selectChild">
           <text class="select-text" v-if="selectedChild">{{ selectedChild.nickname || selectedChild.name }}</text>
-          <text class="select-placeholder" v-else>请选择孩子</text>
+          <text class="select-placeholder" v-else>请选择成员</text>
           <text class="select-arrow">›</text>
         </view>
       </view>

+ 3 - 3
cfc-frontend/pages/health-main/index.vue

@@ -6,7 +6,7 @@
       <!-- 痛点卡 -->
       <view class="pain-card">
         <text class="pain-quote">指标正常 ≠ 健康</text>
-        <text class="pain-desc">孩子反复生病,你扛了多少次了?</text>
+        <text class="pain-desc">家人反复生病,你扛了多少次了?</text>
       </view>
       <!-- 自测入口 -->
       <view class="self-test-card" @click="goSelfTest">
@@ -97,7 +97,7 @@
             <text class="wc-icon">⚡</text>
             <view class="wc-info">
               <text class="wc-name">智 · 赋能未来</text>
-              <text class="wc-text">一次测评,看见孩子真实的专注与潜能</text>
+              <text class="wc-text">一次测评,看见成员真实的专注与潜能</text>
             </view>
           </view>
           <view class="wc-card wc-wealth" @click="goPage('/pages/wealth/index')">
@@ -587,7 +587,7 @@ export default {
             self.relationshipEmpty = true
           }
         }).catch(function() { self.relationshipEmpty = true })
-        // 财富子维度:沙盘里家长用 userId,孩子用 family_members.id,不能混用 currentMemberId
+        // 财富子维度:沙盘里家长用 userId,成员用 family_members.id,不能混用 currentMemberId
         var childId = uni.getStorageSync('currentChildId')
         var wealthMemberId = childId || uni.getStorageSync('userId')
         var wealthMemberType = childId ? 'child' : 'parent'

+ 4 - 4
cfc-frontend/pages/health/challenge-manage.vue

@@ -307,7 +307,7 @@
       </view>
     </view>
 
-    <!-- 免费会员引导添加孩子弹窗 -->
+    <!-- 免费会员引导添加成员弹窗 -->
     <view class="overlay" v-if="showAddChildPrompt" @click="showAddChildPrompt = false">
       <view class="modal prompt-modal" @click.stop>
         <view class="modal-header">
@@ -316,12 +316,12 @@
         </view>
         <view class="prompt-content">
           <text class="prompt-icon">👶</text>
-          <text class="prompt-title">需先添加孩子成员</text>
-          <text class="prompt-desc">免费会员只能添加 1 位孩子成员,添加后即可创建家庭挑战。<br/>挑战创建后,可切换到孩子身份同意参与。</text>
+          <text class="prompt-title">需先添加成员</text>
+          <text class="prompt-desc">免费会员只能添加 1 位成员成员,添加后即可创建家庭挑战。<br/>挑战创建后,可切换到成员身份同意参与。</text>
         </view>
         <view class="modal-footer">
           <button class="btn-cancel" @click="showAddChildPrompt = false">暂不添加</button>
-          <button class="btn-submit" @click="goToAddChild">去添加孩子</button>
+          <button class="btn-submit" @click="goToAddMember">去添加成员</button>
         </view>
       </view>
     </view>

+ 1 - 1
cfc-frontend/pages/health/daily-checkin.vue

@@ -147,7 +147,7 @@ export default {
     doCheckin: function() {
       var self = this
       if (!self.memberId) {
-        uni.showToast({ title: '孩子ID无效', icon: 'none' })
+        uni.showToast({ title: '成员ID无效', icon: 'none' })
         return
       }
       self.submitting = true

+ 1 - 1
cfc-frontend/pages/health/diet-index.vue

@@ -196,7 +196,7 @@ export default {
         return
       }
       if (!self.memberId) {
-        uni.showToast({ title: '孩子ID无效', icon: 'none' })
+        uni.showToast({ title: '成员ID无效', icon: 'none' })
         return
       }
       self.submitting = true

+ 1 - 1
cfc-frontend/pages/health/exercise-index.vue

@@ -210,7 +210,7 @@ export default {
         return
       }
       if (!self.memberId) {
-        uni.showToast({ title: '孩子ID无效', icon: 'none' })
+        uni.showToast({ title: '成员ID无效', icon: 'none' })
         return
       }
       self.submitting = true

+ 1 - 1
cfc-frontend/pages/health/gut-index.vue

@@ -133,7 +133,7 @@ export default {
         memberId = userId
       }
       if (!memberId) {
-        uni.showToast({ title: '未找到孩子信息', icon: 'none' })
+        uni.showToast({ title: '未找到成员信息', icon: 'none' })
         return
       }
       healthRequest('/api/health/report/latest', { memberId: memberId }).then(function(res) {

+ 1 - 1
cfc-frontend/pages/health/health-plan-summary.vue

@@ -25,7 +25,7 @@
       />
       <view class="section-title" style="margin-top:20rpx">健康目标</view>
       <view class="hint-text">描述您希望改善的方向,AI将为您定制方案</view>
-      <textarea class="goal-textarea" v-model="userGoal" placeholder="例如:孩子最近睡眠不好,希望改善睡眠质量,同时提升免疫力..."
+      <textarea class="goal-textarea" v-model="userGoal" placeholder="例如:成员最近睡眠不好,希望改善睡眠质量,同时提升免疫力..."
                 :maxlength="300" auto-height :disabled="loading" @input="onGoalInput"></textarea>
       <view class="goal-footer">
         <text class="goal-count">{{ goalLen }}/300</text>

+ 1 - 1
cfc-frontend/pages/health/meditation-index.vue

@@ -87,7 +87,7 @@ export default {
       getChildren().then(function(res) {
         if (res.code === 200 && res.data && res.data.length > 0) {
           self.memberIds = res.data.map(function(c) { return c.memberId })
-          self.memberOptions = ['我自己'].concat(res.data.map(function(c) { return c.name || c.nickname || '孩子' }))
+          self.memberOptions = ['我自己'].concat(res.data.map(function(c) { return c.name || c.nickname || '成员' }))
         }
       }).catch(function() {})
     },

+ 11 - 11
cfc-frontend/pages/health/report-survey.vue

@@ -10,7 +10,7 @@
     <!-- 提示说明 -->
     <view class="tip-banner">
       <text class="tip-icon">💡</text>
-      <text class="tip-text">请根据孩子和家庭的实际情况填写,帮助AI更准确地解读报告</text>
+      <text class="tip-text">请根据成员和家庭的实际情况填写,帮助AI更准确地解读报告</text>
     </view>
 
     <!-- 表单 -->
@@ -25,7 +25,7 @@
       <!-- Q1: 饮食结构 -->
       <view class="question-card">
         <text class="q-number">1/15</text>
-        <text class="q-title">孩子平时的饮食结构是怎样的?</text>
+        <text class="q-title">成员平时的饮食结构是怎样的?</text>
         <view class="q-options">
           <view class="q-option" :class="{ 'q-selected': survey.diet === 'balanced' }" @click="survey.diet = 'balanced'">
             <text class="q-icon">🥗</text>
@@ -49,7 +49,7 @@
       <!-- Q1b: 绝对忌口(必填) -->
       <view class="question-card">
         <text class="q-number">1b/15</text>
-        <text class="q-title">孩子有哪些绝对不能吃/喝的食物?(必填,含过敏原)</text>
+        <text class="q-title">成员有哪些绝对不能吃/喝的食物?(必填,含过敏原)</text>
         <view class="q-options multi">
           <view class="q-option" :class="{ 'q-selected': survey.absoluteAvoid.indexOf('牛奶') !== -1 }" @click="toggleAbsAvoid('牛奶')">
             <text class="q-text">牛奶/乳制品</text>
@@ -125,7 +125,7 @@
       <!-- Q2: 消化状况 -->
       <view class="question-card">
         <text class="q-number">2/15</text>
-        <text class="q-title">孩子近期消化状况如何?</text>
+        <text class="q-title">成员近期消化状况如何?</text>
         <view class="q-options">
           <view class="q-option" :class="{ 'q-selected': survey.digestion === 'good' }" @click="survey.digestion = 'good'">
             <text>😊</text>
@@ -149,7 +149,7 @@
       <!-- Q3: 睡眠质量 -->
       <view class="question-card">
         <text class="q-number">3/15</text>
-        <text class="q-title">孩子近期的睡眠质量如何?</text>
+        <text class="q-title">成员近期的睡眠质量如何?</text>
         <view class="q-options">
           <view class="q-option" :class="{ 'q-selected': survey.sleep === 'good' }" @click="survey.sleep = 'good'">
             <text>😴</text>
@@ -173,7 +173,7 @@
       <!-- Q4: 运动习惯 -->
       <view class="question-card">
         <text class="q-number">4/15</text>
-        <text class="q-title">孩子每周运动情况?</text>
+        <text class="q-title">成员每周运动情况?</text>
         <view class="q-options">
           <view class="q-option" :class="{ 'q-selected': survey.exercise === 'frequent' }" @click="survey.exercise = 'frequent'">
             <text>🏃</text>
@@ -193,7 +193,7 @@
       <!-- Q5: 饮水习惯 -->
       <view class="question-card">
         <text class="q-number">5/15</text>
-        <text class="q-title">孩子每日饮水量如何?</text>
+        <text class="q-title">成员每日饮水量如何?</text>
         <view class="q-options">
           <view class="q-option" :class="{ 'q-selected': survey.water === 'enough' }" @click="survey.water = 'enough'">
             <text>💧</text>
@@ -213,7 +213,7 @@
       <!-- Q6: 用药情况 -->
       <view class="question-card">
         <text class="q-number">6/15</text>
-        <text class="q-title">孩子近期是否有以下用药情况?(可多选)</text>
+        <text class="q-title">成员近期是否有以下用药情况?(可多选)</text>
         <view class="q-options multi">
           <view class="q-option" :class="{ 'q-selected': hasMedication('antibiotic') }" @click="toggleMedication('antibiotic')">
             <text class="q-text">抗生素(近3个月内使用过)</text>
@@ -242,7 +242,7 @@
       <!-- Q7: 慢性病/系统性疾病 -->
       <view class="question-card">
         <text class="q-number">7/15</text>
-        <text class="q-title">孩子是否有以下慢性或系统性疾病?(可多选)</text>
+        <text class="q-title">成员是否有以下慢性或系统性疾病?(可多选)</text>
         <view class="q-options multi">
           <view class="q-option" :class="{ 'q-selected': hasChronic('none') }" @click="toggleChronic('none')">
             <text class="q-text">无已知疾病</text>
@@ -279,7 +279,7 @@
       <!-- Q8: 过敏史 -->
       <view class="question-card">
         <text class="q-number">8/15</text>
-        <text class="q-title">孩子是否有以下过敏情况?(可多选)</text>
+        <text class="q-title">成员是否有以下过敏情况?(可多选)</text>
         <view class="q-options multi">
           <view class="q-option" :class="{ 'q-selected': survey.allergies.indexOf('none') !== -1 }" @click="toggleAllergy('none')">
             <text class="q-text">无明显过敏</text>
@@ -304,7 +304,7 @@
       <!-- Q9: 手术/住院史 -->
       <view class="question-card">
         <text class="q-number">9/15</text>
-        <text class="q-title">孩子是否有手术或住院史?</text>
+        <text class="q-title">成员是否有手术或住院史?</text>
         <view class="q-options">
           <view class="q-option" :class="{ 'q-selected': survey.surgery === 'none' }" @click="survey.surgery = 'none'">
             <text class="q-text">无</text>

+ 2 - 2
cfc-frontend/pages/health/sleep-index.vue

@@ -61,7 +61,7 @@
             </view>
             <view class="info-item">
               <text class="info-age">过渡期调整</text>
-              <text class="info-desc">节假日前后逐渐调整作息,每次调整 15-30 分钟,让孩子平稳过渡,避免睡眠紊乱。</text>
+              <text class="info-desc">节假日前后逐渐调整作息,每次调整 15-30 分钟,让成员平稳过渡,避免睡眠紊乱。</text>
             </view>
           </view>
         </view>
@@ -196,7 +196,7 @@ export default {
         return
       }
       if (!self.memberId) {
-        uni.showToast({ title: '孩子ID无效', icon: 'none' })
+        uni.showToast({ title: '成员ID无效', icon: 'none' })
         return
       }
       self.submitting = true

+ 1 - 1
cfc-frontend/pages/health/water-index.vue

@@ -166,7 +166,7 @@ export default {
         return
       }
       if (!self.memberId) {
-        uni.showToast({ title: '孩子ID无效', icon: 'none' })
+        uni.showToast({ title: '成员ID无效', icon: 'none' })
         return
       }
       self.submitting = true

+ 1 - 1
cfc-frontend/pages/home-pages/components/MicroActionCard.vue

@@ -71,7 +71,7 @@ export default {
     },
     doComplete: function() {
       if (!this.memberId) {
-        uni.showToast({ title: '请先选择孩子', icon: 'none' })
+        uni.showToast({ title: '请先选择家庭成员', icon: 'none' })
         return
       }
       if (!this.action) return

+ 1 - 1
cfc-frontend/pages/home-pages/member-home-detail.vue

@@ -190,7 +190,7 @@ export default {
             }
           }
         }).catch(function(e) {
-          console.log('获取孩子列表失败', e)
+          console.log('获取成员列表失败', e)
         })
       }
 

+ 1 - 1
cfc-frontend/pages/member-detail/member-detail.vue

@@ -177,7 +177,7 @@ export default {
       // 回退:根据 memberType 推断
       if (this.memberType === 'parent') return '家长'
       if (this.memberType === 'elderly') return '长辈'
-      return '孩子'
+      return '成员'
     },
     overallScore: function() {
       if (!this.memberInfo) return null

+ 1 - 1
cfc-frontend/pages/membership/index.vue

@@ -93,7 +93,7 @@ export default {
       features: ['折扣购物', '家庭管理', '推荐佣金', '专属活动', '任务特权', '成长报告'],
       compareData: [
         { name: '商品折扣', free: '普通价格', basic: '会员折扣', family: '会员折扣', premium: '会员折扣' },
-        { name: '家庭管理', free: '基础功能', basic: '3个孩子', family: '10个孩子', premium: '20个孩子' },
+        { name: '家庭管理', free: '基础功能', basic: '3位成员', family: '10位成员', premium: '20位成员' },
         { name: 'AI健康顾问', free: '—', basic: '3次/月', family: '不限', premium: '不限' },
         { name: '报告解读', free: '—', basic: '1次/月', family: '不限', premium: '深度解读' },
         { name: '测评预约', free: '仅查看', basic: '1次/月', family: '不限', premium: '优先' },

+ 1 - 1
cfc-frontend/pages/membership/upgrade.vue

@@ -114,7 +114,7 @@ export default {
       currentLevelName: '免费用户',
       compareData: [
         { name: '商品折扣', free: '普通价格', basic: '会员折扣', family: '会员折扣', premium: '会员折扣', lifetime: '会员折扣' },
-        { name: '家庭管理', free: '基础功能', basic: '3个孩子', family: '10个孩子', premium: '20个孩子', lifetime: '全部功能+专属管家' },
+        { name: '家庭管理', free: '基础功能', basic: '3位成员', family: '10位成员', premium: '20位成员', lifetime: '全部功能+专属管家' },
         { name: 'AI健康顾问', free: '—', basic: '3次/月', family: '不限', premium: '不限', lifetime: '不限' },
         { name: '报告解读', free: '—', basic: '1次/月', family: '每周+深度', premium: '每日+深度+专家解读', lifetime: '实时+专家深度解读' },
         { name: '健康报告上传', free: '—', basic: '2份/月', family: '不限', premium: '不限', lifetime: '不限' },

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

@@ -332,7 +332,7 @@ components: { TabTransition, PageBanner, RadarChart, FamilyEnergyBar, PsychCrisi
         '六月:中考高考季,减压情绪管理',
         '七月:暑期到来,培养情绪调节能力',
         '八月:夏末秋初,回顾情绪成长',
-        '九月:开学季,关注孩子心理适应',
+        '九月:开学季,关注家庭成员心理适应',
         '十月:国庆假期,增进亲子沟通',
         '十一月:秋冬交替,预防情绪低落',
         '十二月:年终总结,规划心理成长'
@@ -824,7 +824,7 @@ var descList = descMap[this.dominantElement] || descMap.wood
           }
         }
       }).catch(function(e) {
-        console.log('获取孩子列表失败', e)
+        console.log('获取成员列表失败', e)
       })
     },
     loadDimensionData: function() {

+ 1 - 1
cfc-frontend/pages/mind-detail/member-mind-detail.vue

@@ -14,7 +14,7 @@
         <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || '孩' }}</text>
       </view>
       <view class="member-info">
-        <text class="member-name">{{ memberInfo.name || '孩子' }}</text>
+        <text class="member-name">{{ memberInfo.name || '成员' }}</text>
         <text class="member-role">心智维度</text>
       </view>
       <view class="member-score" v-if="dualDimension">

+ 4 - 4
cfc-frontend/pages/parent/child-detail.vue

@@ -135,7 +135,7 @@ export default {
   },
   onLoad(options) {
     this.memberId = options.memberId || ''
-    this.childName = options.childName ? decodeURIComponent(options.childName) : '孩子'
+    this.childName = options.childName ? decodeURIComponent(options.childName) : '成员'
     this.loadChildData()
   },
   methods: {
@@ -148,8 +148,8 @@ export default {
         const matched = children.find(c => String(c.id) === String(this.memberId))
         if (matched) {
           this.childInfo = matched
-          if (!this.childName || this.childName === '孩子') {
-            this.childName = matched.nickname || matched.name || '孩子'
+if (!this.childName || this.childName === '成员') {
+    this.childName = matched.nickname || matched.name || '成员'
           }
         }
 
@@ -172,7 +172,7 @@ export default {
         const allWishes = wishRes.data || []
         this.pendingWishes = allWishes.filter(w => String(w.memberId) === String(this.memberId)).slice(0, 5)
       } catch (e) {
-        console.error('加载孩子详情失败', e)
+        console.error('加载成员详情失败', e)
         uni.showToast({ title: '加载失败', icon: 'none' })
       } finally {
         this.loading = false

+ 1 - 1
cfc-frontend/pages/parent/plans/detail.vue

@@ -20,7 +20,7 @@
       </view>
 
       <view class="info-card">
-        <text class="info-label">孩子</text>
+        <text class="info-label">成员</text>
         <text class="info-value">{{ plan.childName || '--' }}</text>
       </view>
 

+ 1 - 1
cfc-frontend/pages/parent/plans/index.vue

@@ -28,7 +28,7 @@
         </view>
         <text class="plan-desc" v-if="plan.description">{{ plan.description }}</text>
         <view class="card-meta">
-          <text class="meta-item">孩子:{{ plan.childName || '--' }}</text>
+          <text class="meta-item">成员:{{ plan.childName || '--' }}</text>
           <text class="meta-item">创建时间:{{ plan.createTime || '--' }}</text>
         </view>
       </view>

+ 2 - 2
cfc-frontend/pages/parent/wishes/index.vue

@@ -183,7 +183,7 @@ export default {
   onLoad(options) {
     if (options.memberId) {
       this.memberId = options.memberId
-      this.childName = options.childName || '该孩子'
+      this.childName = options.childName || '该成员'
     }
   },
   methods: {
@@ -193,7 +193,7 @@ export default {
         const pendingRes = await getPendingWishes()
         let wishes = pendingRes.data || []
 
-        // 如果指定了 memberId,按孩子过滤
+        // 如果指定了 memberId,按成员过滤
         if (this.memberId) {
           wishes = wishes.filter(w => String(w.memberId) === String(this.memberId))
         }

+ 1 - 1
cfc-frontend/pages/profile-extra/children.vue

@@ -3,7 +3,7 @@
     <view class="redirect-card">
       <text class="redirect-icon">👪</text>
       <text class="redirect-title">已将孩子管理整合到家庭成员</text>
-      <text class="redirect-desc">孩子的信息请在「家庭成员」中添加和管理</text>
+      <text class="redirect-desc">成员信息请在「家庭成员」中添加和管理</text>
       <button class="redirect-btn" @click="goToFamilyMembers">前往家庭成员</button>
     </view>
   </view>

+ 2 - 2
cfc-frontend/pages/profile-extra/create-child.vue

@@ -2,8 +2,8 @@
   <view class="redirect-container">
     <view class="redirect-card">
       <text class="redirect-icon">👪</text>
-      <text class="redirect-title">请通过「家庭成员」添加孩子</text>
-      <text class="redirect-desc">现在孩子的信息统一在家庭成员中管理,添加时填写出生日期即可自动识别为孩子</text>
+      <text class="redirect-title">请通过「家庭成员」添加成员</text>
+      <text class="redirect-desc">现在成员信息统一在家庭成员中管理,添加时填写出生日期即可</text>
       <button class="redirect-btn" @click="goToFamilyMembers">前往家庭成员</button>
     </view>
   </view>

+ 1 - 1
cfc-frontend/pages/profile-extra/edit-child.vue

@@ -3,7 +3,7 @@
     <view class="redirect-card">
       <text class="redirect-icon">👪</text>
       <text class="redirect-title">请在「家庭成员」中编辑信息</text>
-      <text class="redirect-desc">孩子的信息编辑已整合到家庭成员管理中</text>
+      <text class="redirect-desc">成员信息编辑已整合到家庭成员管理中</text>
       <button class="redirect-btn" @click="goToFamilyMembers">前往家庭成员</button>
     </view>
   </view>

+ 2 - 2
cfc-frontend/pages/profile-main/profile.vue

@@ -360,7 +360,7 @@ export default {
       return !!uni.getStorageSync('token')
     },
     roleLabel() {
-      var map = { parent: '', child: '孩子', teacher: '规划师' }
+      var map = { parent: '', child: '成员', teacher: '规划师' }
       return map[this.role] || '用户'
     },
     memberLevelText() {
@@ -705,7 +705,7 @@ export default {
       })
     },
     memberRoleLabel: function(role) {
-      var map = { parent: '家长', child: '孩子', teacher: '规划师' }
+      var map = { parent: '家长', child: '成员', teacher: '规划师' }
       return map[role] || '成员'
     },
     onExitSwitch: function() {

+ 1 - 1
cfc-frontend/pages/profile/components/ProfileHeader.vue

@@ -51,7 +51,7 @@ export default {
         const res = await getChildren()
         this.children = res.data || []
       } catch (e) {
-        console.error('获取孩子列表失败', e)
+        console.error('获取成员列表失败', e)
       }
     },
     onSwitchMode() {

+ 1 - 0
cfc-frontend/pages/promotion/index.vue

@@ -547,6 +547,7 @@ export default {
   padding: 30rpx;
   min-height: 100vh;
   background: #FFF7ED;
+  box-sizing: border-box;
 }
 .invite-card {
   background: linear-gradient(135deg, #F97316, #EA580C);

+ 1 - 1
cfc-frontend/pages/promotion/team.vue

@@ -111,7 +111,7 @@
 </template>
 
 <script>
-import { getCfRate, getTeamList } from '../../utils/api.js'
+import { getCfRate, getTeamList, getTeamGrowthCurve, getTeamAllMembersConsumptionCurve, getTeamL1ConsumptionCurve } from '../../utils/api.js'
 import { parseDate } from '../../utils/format.js'
 
 export default {

+ 1 - 1
cfc-frontend/pages/rewards/badge.vue

@@ -26,7 +26,7 @@
           <text class="ranking-avatar-placeholder" v-else>{{ item.memberName ? item.memberName.substring(0,1) : '?' }}</text>
           <view class="ranking-info">
             <text class="ranking-name">{{ item.memberName || '未知' }}</text>
-            <text class="ranking-role">{{ item.role === 'child' ? '孩子' : '家长' }}</text>
+            <text class="ranking-role">{{ item.role === 'child' ? '成员' : '家长' }}</text>
           </view>
           <view class="ranking-count">
             <text class="ranking-num">{{ item.badgeCount || 0 }}</text>

+ 4 - 4
cfc-frontend/pages/rewards/rewards.vue

@@ -42,7 +42,7 @@
           <input v-model="newReward.title" placeholder="请输入心愿名称" />
         </view>
         
-        <!-- 家长模式可以填写积分,孩子模式不需要填写积分 -->
+        <!-- 家长模式可以填写积分,成员模式不需要填写积分 -->
         <view class="form-item" v-if="currentRole === 'parent'">
           <view class="form-label">所需积分 <text class="required">*</text></view>
           <input v-model="newReward.pointsRequired" type="number" placeholder="请输入所需积分" />
@@ -50,7 +50,7 @@
         
         <!-- 孩子模式提示 -->
         <view class="form-tip" v-if="currentRole === 'child'">
-          <text>孩子创建心愿后,需要家长填写所需积分才能生效</text>
+          <text>成员创建心愿后,需要家长填写所需积分才能生效</text>
         </view>
         
         <view class="modal-btns">
@@ -109,7 +109,7 @@ export default {
           const userInfo = await this.getUserInfo()
           this.currentPoints = userInfo.totalPoints || 0
         } else {
-          // 孩子模式:使用孩子心愿单API
+          // 成员模式:使用成员心愿单API
           const childrenRes = await getChildren()
           const children = childrenRes.data
           if (children && children.length > 0) {
@@ -188,7 +188,7 @@ export default {
           })
           uni.showToast({ title: '添加成功', icon: 'success' })
         } else {
-          // 孩子模式:创建孩子心愿,积分为0,等待家长填写
+          // 成员模式:创建成员心愿,积分为0,等待家长填写
           await createRewardApi({
             title: this.newReward.title,
             memberId: this.currentChildId

+ 3 - 3
cfc-frontend/pages/stats/completion-rate.vue

@@ -79,14 +79,14 @@
           <text class="alert-icon">⚠️</text>
           <view class="alert-body">
             <text class="alert-title">有 {{ stats.overdueTasks }} 个任务已逾期</text>
-            <text class="alert-desc">请督促孩子尽快完成,避免影响成长积分</text>
+            <text class="alert-desc">请督促成员尽快完成,避免影响成长积分</text>
           </view>
         </view>
 
-        <!-- 按孩子对比 (仅家庭维度) -->
+        <!-- 按成员对比 (仅家庭维度) -->
         <view class="section-block" v-if="stats.byChild && stats.byChild.length > 1">
           <view class="section-header">
-            <text class="section-title">孩子对比</text>
+            <text class="section-title">成员对比</text>
           </view>
           <view class="child-compare">
             <view class="compare-bar-wrapper" v-for="child in stats.byChild" :key="child.memberId">

+ 4 - 4
cfc-frontend/pages/tasks/create-task.vue

@@ -12,7 +12,7 @@
 </view>
 
 <view class="form-item">
-<text class="label">选择孩子(可多选)</text>
+<text class="label">选择成员(可多选)</text>
 <checkbox-group @change="onChildrenChange">
 <label class="child-checkbox" v-for="child in children" :key="child.id">
 <checkbox :value="String(child.id)" :checked="selectedChildIds.includes(String(child.id))" />
@@ -218,7 +218,7 @@ methods: {
       try {
         const res = await getChildren()
         this.children = res.data || []
-        // 如果有 preselect memberId,自动选中该孩子
+        // 如果有 preselect memberId,自动选中该成员
         if (preselectedChildId && this.children.length > 0) {
           const matched = this.children.find(c => String(c.id) === String(preselectedChildId))
           if (matched) {
@@ -408,7 +408,7 @@ onStartRequiredChange(e) {
         return
       }
       if (this.form.memberIds.length === 0) {
-        uni.showToast({ title: '请选择至少一个孩子', icon: 'none' })
+        uni.showToast({ title: '请选择至少一个成员', icon: 'none' })
         return
       }
       if (!this.form.deadline) {
@@ -460,7 +460,7 @@ onStartRequiredChange(e) {
       }
 
       if (failCount === 0) {
-        uni.showToast({ title: `已为${successCount}个孩子创建任务`, icon: 'success' })
+        uni.showToast({ title: `已为${successCount}个成员创建任务`, icon: 'success' })
         setTimeout(() => uni.navigateBack(), 1500)
       } else if (successCount > 0) {
         uni.showToast({ title: `${successCount}个成功,${failCount}个失败`, icon: 'none' })

+ 2 - 2
cfc-frontend/pages/tasks/review.vue

@@ -26,7 +26,7 @@
             <text class="card-title">{{ task.title }}</text>
             <text class="card-desc">{{ task.description }}</text>
             <view class="card-meta-row">
-              <text class="card-provider">提供者: {{ task.creatorRole === 'parent' ? '家长' : '孩子' }}</text>
+              <text class="card-provider">提供者: {{ task.creatorRole === 'parent' ? '家长' : '成员' }}</text>
               <text class="card-points">⭐ +{{ task.points }}</text>
             </view>
           </view>
@@ -47,7 +47,7 @@
             </view>
             <text class="card-desc">{{ task.description }}</text>
             <view class="card-meta-row">
-              <text class="card-provider">提供者: {{ task.creatorRole === 'parent' ? '家长' : '孩子' }}</text>
+              <text class="card-provider">提供者: {{ task.creatorRole === 'parent' ? '家长' : '成员' }}</text>
               <text class="card-points">⭐ +{{ task.points }}</text>
             </view>
             <text class="card-time" v-if="task.reviewTime">审核时间: {{ task.reviewTime }}</text>

+ 1 - 1
cfc-frontend/pages/teacher/families.vue

@@ -18,7 +18,7 @@
           <text class="family-status">{{ family.status === 'active' ? '服务中' : '已暂停' }}</text>
         </view>
         <view class="family-info">
-          <text class="info-item">👶 {{ family.childrenCount || 0 }}个孩子</text>
+          <text class="info-item">👶 {{ family.childrenCount || 0 }}位成员</text>
           <text class="info-item">📍 {{ family.address || '未设置地址' }}</text>
         </view>
         <view class="family-tasks">

+ 1 - 1
cfc-frontend/pages/tianpan/member-detail.vue

@@ -193,7 +193,7 @@ export default {
     getRoleText: function(role) {
       var roleMap = {
         'parent': '家长',
-        'child': '孩子',
+        'child': '成员',
         'teacher': '规划师'
       }
       return roleMap[role] || role

+ 1 - 1
cfc-frontend/pages/tianpan/relation-detail.vue

@@ -384,7 +384,7 @@ export default {
     getRoleText: function(role) {
       var roleMap = {
         'parent': '家长',
-        'child': '孩子',
+        'child': '成员',
         'teacher': '规划师'
       }
       return roleMap[role] || role

+ 1 - 1
cfc-frontend/pages/tianpan/traditional.vue

@@ -158,7 +158,7 @@ export default {
     },
 
     getRoleLabel: function(type) {
-      var labels = { parent: '家长', child: '孩子', teacher: '规划师' }
+      var labels = { parent: '家长', child: '成员', teacher: '规划师' }
       return labels[type] || type
     },
 

+ 2 - 2
cfc-frontend/pages/user-edit/user-edit.vue

@@ -14,7 +14,7 @@
 			>
 				<text class="role-icon">👨‍👩‍👧</text>
 				<text class="role-name">家长</text>
-				<text class="role-desc">管理孩子任务、审核奖励</text>
+				<text class="role-desc">管理家庭成员任务、审核奖励</text>
 			</view>
 			
 			<view 
@@ -23,7 +23,7 @@
 				@click="selectRole('child')"
 			>
 				<text class="role-icon">👶</text>
-				<text class="role-name">孩子</text>
+				<text class="role-name">成员</text>
 				<text class="role-desc">执行任务、赚取积分</text>
 			</view>
 			

+ 1 - 1
cfc-frontend/pages/wealth-detail/member-wealth-detail.vue

@@ -12,7 +12,7 @@
         <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || '孩' }}</text>
       </view>
       <view class="member-info">
-        <text class="member-name">{{ memberInfo.name || '孩子' }}</text>
+        <text class="member-name">{{ memberInfo.name || '成员' }}</text>
         <text class="member-role">财富维度</text>
       </view>
       <view class="member-score" v-if="dualDimension">

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

@@ -83,7 +83,7 @@
               <view class="member-avatar">{{ (m.name || '未知').substring(0, 1) }}</view>
               <view class="member-info">
                 <text class="member-name">{{ m.name || '未知' }}</text>
-                <text class="member-role">{{ m.familyRole || (m.memberType === 'parent' ? '家长' : '孩子') }}</text>
+                <text class="member-role">{{ m.familyRole || (m.memberType === 'parent' ? '家长' : '成员') }}</text>
               </view>
               <view class="member-policy-badge" v-if="m.policyCount > 0">
                 <text>{{ m.policyCount }}份保单</text>

+ 1 - 1
cfc-frontend/pages/wealth/index.vue

@@ -446,7 +446,7 @@ export default {
         var res = await getChildren()
         this.children = res.data || []
       } catch (e) {
-        console.error('获取孩子列表失败', e)
+        console.error('获取成员列表失败', e)
       }
     },
     async loadWealthDetail() {

+ 1 - 1
cfc-frontend/pages/wisdom-detail/member-wisdom-detail.vue

@@ -14,7 +14,7 @@
         <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || '孩' }}</text>
       </view>
       <view class="member-info">
-        <text class="member-name">{{ memberInfo.name || '孩子' }}</text>
+        <text class="member-name">{{ memberInfo.name || '成员' }}</text>
         <text class="member-role">智慧维度</text>
       </view>
       <view class="member-score" v-if="dualDimension">