Browse Source

fix(frontend): fix encoding corruption from directory rename and restore UTF-8

Root cause: PowerShell Get-Content/Set-Content used GBK encoding on UTF-8 files,
corrupting Chinese characters in 230+ files, causing Unterminated string errors.

Fix:
- Restore all files from e8fd4d05~1 (pre-corruption) via git checkout
- Re-apply directory rename (pages/index -> pages/home)
- Re-apply path replacements using Python with explicit UTF-8 encoding
- Fix tab icon references (tab-home -> tab-action) in custom-tab-bar
- Fix historical encoding issue in pages/games/1a2b.vue (pre-existing garbled text)
- Clean up duplicate pages/home/index/ directory created by git checkout
liaoxg 1 month ago
parent
commit
8e1ec265f1
100 changed files with 1670 additions and 1670 deletions
  1. 1 1
      cfc-frontend/custom-tab-bar/index.vue
  2. 10 10
      cfc-frontend/pages/action-detail/contact-detail.vue
  3. 7 7
      cfc-frontend/pages/action-detail/interaction-log.vue
  4. 5 5
      cfc-frontend/pages/action-detail/member-action-detail.vue
  5. 8 8
      cfc-frontend/pages/action-detail/relationship-questionnaire.vue
  6. 10 10
      cfc-frontend/pages/action/contact-detail.vue
  7. 16 16
      cfc-frontend/pages/action/index.vue
  8. 7 7
      cfc-frontend/pages/action/interaction-log.vue
  9. 5 5
      cfc-frontend/pages/action/member-action-detail.vue
  10. 8 8
      cfc-frontend/pages/action/relationship-questionnaire.vue
  11. 34 34
      cfc-frontend/pages/activity/activity-detail/activity-detail.vue
  12. 22 22
      cfc-frontend/pages/activity/create.vue
  13. 39 39
      cfc-frontend/pages/activity/index.vue
  14. 27 27
      cfc-frontend/pages/ai/chat.vue
  15. 20 20
      cfc-frontend/pages/article-center/article-detail.vue
  16. 20 20
      cfc-frontend/pages/article-center/article-edit.vue
  17. 23 23
      cfc-frontend/pages/article-center/index.vue
  18. 7 7
      cfc-frontend/pages/article-center/my-posts.vue
  19. 16 16
      cfc-frontend/pages/assessment/apply.vue
  20. 22 22
      cfc-frontend/pages/assessment/child-info.vue
  21. 7 7
      cfc-frontend/pages/assessment/order.vue
  22. 15 15
      cfc-frontend/pages/assessment/purchase.vue
  23. 7 7
      cfc-frontend/pages/assessment/quota.vue
  24. 18 18
      cfc-frontend/pages/assessment/record.vue
  25. 12 12
      cfc-frontend/pages/assessment/results.vue
  26. 5 5
      cfc-frontend/pages/assessment/upload-report.vue
  27. 13 13
      cfc-frontend/pages/body-detail/checkin.vue
  28. 24 24
      cfc-frontend/pages/body-detail/dimension-detail.vue
  29. 56 56
      cfc-frontend/pages/body-detail/dimension-questionnaire.vue
  30. 9 9
      cfc-frontend/pages/body-detail/health-dimensions.vue
  31. 28 28
      cfc-frontend/pages/body-detail/health-report.vue
  32. 5 5
      cfc-frontend/pages/body-detail/member-body-detail.vue
  33. 12 12
      cfc-frontend/pages/body/checkin.vue
  34. 24 24
      cfc-frontend/pages/body/dimension-detail.vue
  35. 56 56
      cfc-frontend/pages/body/dimension-questionnaire.vue
  36. 12 12
      cfc-frontend/pages/body/exercise-record.vue
  37. 13 13
      cfc-frontend/pages/body/food-list.vue
  38. 1 1
      cfc-frontend/pages/body/growth-curve.vue
  39. 9 9
      cfc-frontend/pages/body/health-dimensions.vue
  40. 27 27
      cfc-frontend/pages/body/health-report.vue
  41. 9 9
      cfc-frontend/pages/body/health-trend.vue
  42. 19 19
      cfc-frontend/pages/body/index.vue
  43. 11 11
      cfc-frontend/pages/body/meal-record.vue
  44. 5 5
      cfc-frontend/pages/body/member-body-detail.vue
  45. 15 15
      cfc-frontend/pages/body/recipe-recommend.vue
  46. 8 8
      cfc-frontend/pages/body/sleep-record.vue
  47. 4 4
      cfc-frontend/pages/body/water-record.vue
  48. 6 6
      cfc-frontend/pages/butler/apply.vue
  49. 8 8
      cfc-frontend/pages/child/rewards.vue
  50. 43 43
      cfc-frontend/pages/child/tasks.vue
  51. 16 16
      cfc-frontend/pages/dan-assessment/report-upload.vue
  52. 35 35
      cfc-frontend/pages/discover-detail/activity-detail/activity-detail.vue
  53. 10 10
      cfc-frontend/pages/discover-detail/product-detail/product-detail.vue
  54. 41 41
      cfc-frontend/pages/discover/activity-detail/activity-detail.vue
  55. 14 14
      cfc-frontend/pages/discover/index.vue
  56. 6 6
      cfc-frontend/pages/discover/product-detail/product-detail.vue
  57. 6 6
      cfc-frontend/pages/energy/detail.vue
  58. 21 21
      cfc-frontend/pages/family/add-member.vue
  59. 1 1
      cfc-frontend/pages/family/address-edit.vue
  60. 9 9
      cfc-frontend/pages/games/1a2b.vue
  61. 2 2
      cfc-frontend/pages/games/list.vue
  62. 7 7
      cfc-frontend/pages/games/records.vue
  63. 7 7
      cfc-frontend/pages/games/schulte.vue
  64. 13 13
      cfc-frontend/pages/games/stats.vue
  65. 11 11
      cfc-frontend/pages/games/sudoku.vue
  66. 5 5
      cfc-frontend/pages/growth/assessment-result.vue
  67. 10 10
      cfc-frontend/pages/growth/create.vue
  68. 14 14
      cfc-frontend/pages/growth/detail.vue
  69. 11 11
      cfc-frontend/pages/growth/index.vue
  70. 5 5
      cfc-frontend/pages/growth/supplement.vue
  71. 6 6
      cfc-frontend/pages/growth/upload.vue
  72. 18 18
      cfc-frontend/pages/guide/activities/detail.vue
  73. 12 12
      cfc-frontend/pages/guide/activities/index.vue
  74. 19 19
      cfc-frontend/pages/guide/bind/invite.vue
  75. 10 10
      cfc-frontend/pages/guide/hierarchy/index.vue
  76. 26 26
      cfc-frontend/pages/guide/invite/share.vue
  77. 7 7
      cfc-frontend/pages/guide/packages/create.vue
  78. 13 13
      cfc-frontend/pages/guide/packages/detail.vue
  79. 9 9
      cfc-frontend/pages/guide/packages/index.vue
  80. 9 9
      cfc-frontend/pages/guide/packages/share.vue
  81. 22 22
      cfc-frontend/pages/guide/register/index.vue
  82. 19 19
      cfc-frontend/pages/health/diet-index.vue
  83. 11 11
      cfc-frontend/pages/health/exercise-index.vue
  84. 36 36
      cfc-frontend/pages/health/gut-flora-detail.vue
  85. 6 6
      cfc-frontend/pages/health/gut-flora-foods-detail.vue
  86. 13 13
      cfc-frontend/pages/health/gut-flora-risks-detail.vue
  87. 15 15
      cfc-frontend/pages/health/gut-flora-species-detail.vue
  88. 22 22
      cfc-frontend/pages/health/gut-index.vue
  89. 6 6
      cfc-frontend/pages/health/meditation-index.vue
  90. 12 12
      cfc-frontend/pages/health/nutrition-profile.vue
  91. 26 26
      cfc-frontend/pages/health/physical-exam-detail.vue
  92. 37 37
      cfc-frontend/pages/health/report-confirm.vue
  93. 10 10
      cfc-frontend/pages/health/report-list.vue
  94. 68 68
      cfc-frontend/pages/health/report-survey.vue
  95. 44 44
      cfc-frontend/pages/health/report-upload.vue
  96. 13 13
      cfc-frontend/pages/health/sleep-index.vue
  97. 1 1
      cfc-frontend/pages/health/tongue-index.vue
  98. 88 88
      cfc-frontend/pages/home/child-index.vue
  99. 51 51
      cfc-frontend/pages/home/index.vue
  100. 9 9
      cfc-frontend/pages/home/member-home-detail.vue

+ 1 - 1
cfc-frontend/custom-tab-bar/index.vue

@@ -51,7 +51,7 @@ export default {
         { text: '富', pagePath: '/pages/profile/profile', icon: '/static/tab-profile.png', selectedIcon: '/static/tab-profile-active.png' }
       ],
       teacherTabs: [
-        { text: '首页', pagePath: '/pages/teacher/index', icon: '/static/tab-home.png', selectedIcon: '/static/tab-home-active.png' },
+        { text: '首页', pagePath: '/pages/teacher/index', icon: '/static/tab-action.png', selectedIcon: '/static/tab-action-active.png' },
         { text: '家庭', pagePath: '/pages/teacher/families', icon: '/static/tab-family.png', selectedIcon: '/static/tab-family-active.png' },
         { text: '团队', pagePath: '/pages/teacher/team', icon: '/static/tab-team.png', selectedIcon: '/static/tab-team-active.png' },
         { text: '成长档案', pagePath: '/pages/growth/index', icon: '/static/tab-growth.png', selectedIcon: '/static/tab-growth-active.png' },

+ 10 - 10
cfc-frontend/pages/action-detail/contact-detail.vue

@@ -3,7 +3,7 @@
     <!-- 头部 -->
     <view class="detail-header">
       <view class="header-top">
-        <text class="back-btn" @click="goBack">�返回</text>
+        <text class="back-btn" @click="goBack">â†è¿”回</text>
         <text class="page-title">关系详情</text>
         <text class="edit-btn" @click="toggleEdit">{{ isEditing ? '�消' : '编辑' }}</text>
       </view>
@@ -16,7 +16,7 @@
       <view class="header-intimacy">
         <text class="intimacy-heart">��</text>
         <text class="intimacy-num">{{ contact.intimacyLevel || 0 }}</text>
-        <text class="intimacy-label">亲密�/text>
+        <text class="intimacy-label">亲密度</text>
       </view>
     </view>
 
@@ -25,7 +25,7 @@
       <text class="section-title">基本信�</text>
       <view class="info-row" v-if="!isEditing">
         <text class="info-icon">📞</text>
-        <text class="info-value">{{ contact.phone || '未填� }}</text>
+        <text class="info-value">{{ contact.phone || '未填写' }}</text>
       </view>
       <view class="info-row" v-if="!isEditing && contact.birthdayLabel">
         <text class="info-icon">🎂</text>
@@ -38,7 +38,7 @@
         <text class="info-value">{{ contact.bio }}</text>
       </view>
       <view class="info-row" v-if="!isEditing && contact.tags">
-        <text class="info-icon">��/text>
+        <text class="info-icon">��</text>
         <text class="info-value">{{ contact.tags }}</text>
       </view>
       <view class="info-row" v-if="!isEditing && contact.notes">
@@ -53,7 +53,7 @@
           <input class="edit-input" v-model="editForm.name" />
         </view>
         <view class="edit-row">
-          <text class="edit-label">手机�/text>
+          <text class="edit-label">手机�</text>
           <input class="edit-input" v-model="editForm.phone" />
         </view>
         <view class="edit-row">
@@ -91,7 +91,7 @@
       <text class="section-title">互动记录</text>
       <view class="interaction-item" v-if="contact.lastContactAt">
         <text class="interaction-date">{{ formatDate(contact.lastContactAt) }}</text>
-        <text class="interaction-desc">标记了��/text>
+        <text class="interaction-desc">标记了�系</text>
       </view>
       <view class="interaction-item" v-if="contact.createdAt">
         <text class="interaction-date">{{ formatDate(contact.createdAt) }}</text>
@@ -105,7 +105,7 @@
 
     <!-- 删除 -->
     <view class="danger-section">
-      <button class="btn-delete" @click="confirmDelete">删除�系�/button>
+      <button class="btn-delete" @click="confirmDelete">删除�系人</button>
     </view>
   </view>
 </template>
@@ -211,7 +211,7 @@ export default {
       var self = this
       recordContactInteraction(this.contact.id).then(function(res) {
         if (res.code === 200) {
-          uni.showToast({ title: '已标记��, icon: 'success' })
+          uni.showToast({ title: '已标记�系', icon: 'success' })
           self.loadDetail()
         } else {
           uni.showToast({ title: res.message || '�作失败', icon: 'none' })
@@ -224,12 +224,12 @@ export default {
       var self = this
       uni.showModal({
         title: '确认删除',
-        content: '确定�删除该�系人��,
+        content: '确定�删除该�系人�?',
         success: function(r) {
           if (r.confirm) {
             deleteContact({ id: self.contact.id }).then(function(res) {
               if (res.code === 200) {
-                uni.showToast({ title: '已删�, icon: 'success' })
+                uni.showToast({ title: '已删除', icon: 'success' })
                 setTimeout(function() { uni.navigateBack() }, 500)
               } else {
                 uni.showToast({ title: res.message || '删除失败', icon: 'none' })

+ 7 - 7
cfc-frontend/pages/action-detail/interaction-log.vue

@@ -32,9 +32,9 @@
 
     <!-- 互动描述 -->
     <view class="form-section">
-      <text class="section-label">描述(选填��?/text>
+      <text class="section-label">描述(选填)</text>
       <textarea class="desc-input" v-model="description"
-                 placeholder="简单描述一下这次互��?.." maxlength="256"></textarea>
+                 placeholder="简单描述一下这次互动..." maxlength="256"></textarea>
     </view>
 
     <!-- 互动时间 -->
@@ -71,16 +71,16 @@ export default {
       timeType: 'now',
       customTime: '',
       interactionTypes: {
-        dining: '一起用��?,
+        dining: '一起用餐',
         outgoing: '外出活动',
         call: '电话联系',
         video: '视频通话',
         chat: '聊天交流',
-        play: '一起游��?,
-        gift: '赠送礼��?
+        play: '一起游戏',
+        gift: '赠送礼物'
       },
       typeIcons: {
-        dining: '🍽��?,
+        dining: '🍽️',
         outgoing: '🚗',
         call: '📞',
         video: '📹',
@@ -120,7 +120,7 @@ export default {
     },
     async onSubmit() {
       if (!this.canSubmit) {
-        uni.showToast({ title: '请选择对象和类��?, icon: 'none' })
+        uni.showToast({ title: '请选择对象和类型', icon: 'none' })
         return
       }
       try {

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

@@ -5,19 +5,19 @@
       <view class="nav-back" @click="goBack">
         <text class="nav-back-icon">&#x2190;</text>
       </view>
-      <text class="nav-title">�· �员详情</text>
+      <text class="nav-title">行 · �员详情</text>
     </view>
 
-    <!-- 五维能��-->
+    <!-- 五维能�� -->
     <FamilyEnergyBar
       dimensionCode="action"
       :sandboxData="sandboxData"
       :dualDimension="dualDimension" />
 
-    <!-- �员信��-->
+    <!-- �员信�� -->
     <view class="member-card" v-if="memberInfo">
       <view class="member-avatar action-avatar">
-        <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || 'å­? }}</text>
+        <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || 'å­©' }}</text>
       </view>
       <view class="member-info">
         <text class="member-name">{{ memberInfo.name || 'å­©å­�' }}</text>
@@ -25,7 +25,7 @@
       </view>
       <view class="member-score" v-if="dualDimension">
         <text class="score-value action-score">{{ dualDimension.energy || 0 }}</text>
-        <text class="score-label">能��/text>
+        <text class="score-label">能�值</text>
       </view>
     </view>
 

+ 8 - 8
cfc-frontend/pages/action-detail/relationship-questionnaire.vue

@@ -2,10 +2,10 @@
   <view class="container">
     <view class="page-header">
       <text class="page-title">关系问�</text>
-      <text class="page-subtitle" v-if="memberName">为「{{ memberName }}�评估关系质�/text>
+      <text class="page-subtitle" v-if="memberName">为「{{ memberName }}�评估关系质�</text>
     </view>
 
-    <!-- 加载状�-->
+    <!-- 加载状æ€-->
     <view v-if="loading" class="loading-wrap">
       <text class="loading-text">AI 正在生�问�...</text>
     </view>
@@ -32,10 +32,10 @@
       </view>
     </view>
 
-    <!-- 无问�-->
+    <!-- 无问� -->
     <view v-else class="empty-wrap">
       <text class="empty-text">暂无�用问�</text>
-      <button class="btn-generate" @click="generateQuestionnaire">生�新问�/button>
+      <button class="btn-generate" @click="generateQuestionnaire">生�新问�</button>
     </view>
 
     <!-- 结果展示 -->
@@ -58,7 +58,7 @@
             <text class="result-score-value">{{ Math.round(result.intimacyScore || 0) }}</text>
           </view>
           <view class="result-score-item">
-            <text class="result-score-label">沟�/text>
+            <text class="result-score-label">沟通</text>
             <view class="result-bar-bg">
               <view class="result-bar-fill communication" :style="{width: (result.communicationScore || 0) + '%'}"></view>
             </view>
@@ -88,7 +88,7 @@ export default {
       dimensionLabels: {
         trust: 'ä¿¡ä»»',
         intimacy: '亲密',
-        communication: '沟�
+        communication: '沟通'
       },
       optionLetters: ['A', 'B', 'C', 'D', 'E']
     }
@@ -121,7 +121,7 @@ export default {
             this.questions = []
           }
         } else {
-          // 没有问�,生�新�
+          // 没有问å�·ï¼Œç”Ÿæˆ�æ–°çš
           await this.generateQuestionnaire()
         }
       } catch (e) {
@@ -157,7 +157,7 @@ export default {
     },
     async onSubmit() {
       if (!this.allAnswered || !this.snapshotId) {
-        uni.showToast({ title: '请回答所有问�, icon: 'none' })
+        uni.showToast({ title: '请回答所有问题', icon: 'none' })
         return
       }
       try {

+ 10 - 10
cfc-frontend/pages/action/contact-detail.vue

@@ -3,7 +3,7 @@
     <!-- 头部 -->
     <view class="detail-header">
       <view class="header-top">
-        <text class="back-btn" @click="goBack">�返回</text>
+        <text class="back-btn" @click="goBack">â†è¿”回</text>
         <text class="page-title">关系详情</text>
         <text class="edit-btn" @click="toggleEdit">{{ isEditing ? '�消' : '编辑' }}</text>
       </view>
@@ -16,7 +16,7 @@
       <view class="header-intimacy">
         <text class="intimacy-heart">��</text>
         <text class="intimacy-num">{{ contact.intimacyLevel || 0 }}</text>
-        <text class="intimacy-label">亲密�/text>
+        <text class="intimacy-label">亲密度</text>
       </view>
     </view>
 
@@ -25,7 +25,7 @@
       <text class="section-title">基本信�</text>
       <view class="info-row" v-if="!isEditing">
         <text class="info-icon">📞</text>
-        <text class="info-value">{{ contact.phone || '未填� }}</text>
+        <text class="info-value">{{ contact.phone || '未填写' }}</text>
       </view>
       <view class="info-row" v-if="!isEditing && contact.birthdayLabel">
         <text class="info-icon">🎂</text>
@@ -38,7 +38,7 @@
         <text class="info-value">{{ contact.bio }}</text>
       </view>
       <view class="info-row" v-if="!isEditing && contact.tags">
-        <text class="info-icon">��/text>
+        <text class="info-icon">��</text>
         <text class="info-value">{{ contact.tags }}</text>
       </view>
       <view class="info-row" v-if="!isEditing && contact.notes">
@@ -53,7 +53,7 @@
           <input class="edit-input" v-model="editForm.name" />
         </view>
         <view class="edit-row">
-          <text class="edit-label">手机�/text>
+          <text class="edit-label">手机�</text>
           <input class="edit-input" v-model="editForm.phone" />
         </view>
         <view class="edit-row">
@@ -91,7 +91,7 @@
       <text class="section-title">互动记录</text>
       <view class="interaction-item" v-if="contact.lastContactAt">
         <text class="interaction-date">{{ formatDate(contact.lastContactAt) }}</text>
-        <text class="interaction-desc">标记了��/text>
+        <text class="interaction-desc">标记了�系</text>
       </view>
       <view class="interaction-item" v-if="contact.createdAt">
         <text class="interaction-date">{{ formatDate(contact.createdAt) }}</text>
@@ -105,7 +105,7 @@
 
     <!-- 删除 -->
     <view class="danger-section">
-      <button class="btn-delete" @click="confirmDelete">删除�系�/button>
+      <button class="btn-delete" @click="confirmDelete">删除�系人</button>
     </view>
   </view>
 </template>
@@ -211,7 +211,7 @@ export default {
       var self = this
       recordContactInteraction(this.contact.id).then(function(res) {
         if (res.code === 200) {
-          uni.showToast({ title: '已标记��, icon: 'success' })
+          uni.showToast({ title: '已标记�系', icon: 'success' })
           self.loadDetail()
         } else {
           uni.showToast({ title: res.message || '�作失败', icon: 'none' })
@@ -224,12 +224,12 @@ export default {
       var self = this
       uni.showModal({
         title: '确认删除',
-        content: '确定�删除该�系人��,
+        content: '确定�删除该�系人�?',
         success: function(r) {
           if (r.confirm) {
             deleteContact({ id: self.contact.id }).then(function(res) {
               if (res.code === 200) {
-                uni.showToast({ title: '已删�, icon: 'success' })
+                uni.showToast({ title: '已删除', icon: 'success' })
                 setTimeout(function() { uni.navigateBack() }, 500)
               } else {
                 uni.showToast({ title: res.message || '删除失败', icon: 'none' })

+ 16 - 16
cfc-frontend/pages/action/index.vue

@@ -1,39 +1,39 @@
 <template>
   <view class="container">
-    <!-- Tabbar ��揢餈�腹憿?-->
+    <!-- Tabbar ��揢餈�腹憿-->
     <tab-transition v-if="showTabTransition" dimCode="action" waitingFor="action" />
 
     <!-- ���憭湧� -->
     <PageBanner theme="action"
       tagline="�亥���� 繚 敹思��鞾鵭"
-      quote="���銋贝�嚗��鈭舘雲銝? />
+      quote="���銋贝�嚗��鈭舘雲銝�" />
 
-    <!-- 摰嗅滬�𣂼��㗇𥋘�?-->
+    <!-- 摰嗅滬�𣂼��㗇𥋘�-->
     <FamilyMemberStrip
       v-if="isLoggedIn"
       :members="familyMembersVisible"
       :selectedMemberId="selectedMemberId"
       @select="onFamilyMemberSelect" />
 
-    <!-- 皜詨恥�餃�撘訫紡�?-->
+    <!-- 皜詨恥�餃�撘訫紡�-->
     <template v-if="!isLoggedIn">
       <LoginGuideCard
         title="�餃��擧䰻�衤遙�∪�瘣餃𢆡霈啣�"
         :items="[
-          '�亦�隞𦠜𠯫隞餃𦛚嚗���鞉��∟繮�𤥁��刻��?,
-          '�亙�����剝秄瘣餃𢆡嚗諹扇敶閙��輯雲餈?,
-          '�亦�銝枏�����峕暑�其遠�?
+          '�亦�隞𦠜𠯫隞餃𦛚嚗���鞉��∟繮�𤥁��刻���',
+          '�亙�����剝秄瘣餃𢆡嚗諹扇敶閙��輯雲餈�',
+          '�亦�銝枏�����峕暑�其遠��'
         ]" />
     </template>
 
-    <!-- �餃��𠬍�鈭𠉛輕�賡��?-->
+    <!-- �餃��𠬍�鈭𠉛輕�賡��-->
     <FamilyEnergyBar
       v-if="isLoggedIn"
       dimensionCode="action"
       :sandboxData="sandboxData"
       :dualDimension="dualDimension" />
 
-    <!-- �賡�瘝嗵�嚗�蒈敶訫��航�嚗?�?Canvas 鈭磰��笔㦛 -->
+    <!-- �賡�瘝嗵�嚗�蒈敶訫��航�嚗� �� Canvas 鈭磰��笔㦛 -->
     <WuxingSandbox
       v-if="isLoggedIn && sandboxData"
       mode="live"
@@ -49,7 +49,7 @@
       showDimensionBar
       starHeight="480rpx" />
 
-    <!-- �喟頂�曇停嚗�蒈敶訫��航�嚗?�?摰嗅滬�喟頂蝵𤑳� -->
+    <!-- �喟頂�曇停嚗�蒈敶訫��航�嚗� �� 摰嗅滬�喟頂蝵𤑳� -->
     <FamilyRelationGraph
       v-if="isLoggedIn && familyMembersVisible.length > 0"
       dimensionCode="action"
@@ -95,7 +95,7 @@
           :healthAlerts="healthAlerts"
           :isLoggedIn="isLoggedIn" />
 
-    <!-- �蠘��亙藁嚗?銝迎�瘣餃𢆡�������紋蝔页� -->
+    <!-- �蠘��亙藁嚗�4銝迎�瘣餃𢆡�������紋蝔页� -->
     <view class="func-section" v-if="sectionVisible('func_entries')">
       <view class="func-grid">
         <view class="func-item" v-for="item in funcList" :key="item.label" @click="onFuncClick(item)">
@@ -107,7 +107,7 @@
       </view>
     </view>
 
-    <!-- 撖澆��𠉛頂鈭箏撕蝒?-->
+    <!-- 撖澆��𠉛頂鈭箏撕蝒-->
     <ContactImport
       :visible="showImportModal"
       @close="onCloseImport"
@@ -218,7 +218,7 @@ export default {
       this.loadFamilyMembersVisible()
       this.loadRelationshipHealth()
     }
-    // 皜詨恥銋蠘�瘚讛�瘣餃𢆡����?
+    // 皜詨恥銋蠘�瘚讛�瘣餃𢆡����
     this.loadDimensionActivities()
     this.loadDimensionProducts()
     // 皜詨恥銋蠘�瘚讛����
@@ -261,7 +261,7 @@ export default {
               break
             }
           }
-          // FIX: 銝滚��芸𢆡�㗇𥋘蝚砌�銝芸酋摮?
+          // FIX: 銝滚��芸𢆡�㗇𥋘蝚砌�銝芸酋摮
           if (found) {
             self.loadDimensionData()
           }
@@ -339,7 +339,7 @@ export default {
           self.contactList = Array.isArray(res.data) ? res.data : []
         }
       }).catch(function(e) {
-        console.log('�瑕��𠉛頂鈭箏仃韐?, e)
+        console.log('�瑕��𠉛頂鈭箏仃韐�', e)
       })
     },
     onContactClick: function(item) {
@@ -361,7 +361,7 @@ export default {
     onChildChanged: function(child) {
       this.currentChildId = child.childId
       this.currentChildName = child.name || child.nickname || '摮拙�'
-      // FIX: �峕郊�𣂷漱�?Vuex store
+      // FIX: �峕郊�𣂷漱�Vuex store
       this.$store.commit('switchToChild', child.childId)
       this.loadDimensionData()
     },

+ 7 - 7
cfc-frontend/pages/action/interaction-log.vue

@@ -32,9 +32,9 @@
 
     <!-- 互动描述 -->
     <view class="form-section">
-      <text class="section-label">描述(选填��?/text>
+      <text class="section-label">描述(选填)</text>
       <textarea class="desc-input" v-model="description"
-                 placeholder="简单描述一下这次互��?.." maxlength="256"></textarea>
+                 placeholder="简单描述一下这次互动..." maxlength="256"></textarea>
     </view>
 
     <!-- 互动时间 -->
@@ -71,16 +71,16 @@ export default {
       timeType: 'now',
       customTime: '',
       interactionTypes: {
-        dining: '一起用��?,
+        dining: '一起用餐',
         outgoing: '外出活动',
         call: '电话联系',
         video: '视频通话',
         chat: '聊天交流',
-        play: '一起游��?,
-        gift: '赠送礼��?
+        play: '一起游戏',
+        gift: '赠送礼物'
       },
       typeIcons: {
-        dining: '🍽��?,
+        dining: '🍽️',
         outgoing: '🚗',
         call: '📞',
         video: '📹',
@@ -120,7 +120,7 @@ export default {
     },
     async onSubmit() {
       if (!this.canSubmit) {
-        uni.showToast({ title: '请选择对象和类��?, icon: 'none' })
+        uni.showToast({ title: '请选择对象和类型', icon: 'none' })
         return
       }
       try {

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

@@ -5,19 +5,19 @@
       <view class="nav-back" @click="goBack">
         <text class="nav-back-icon">&#x2190;</text>
       </view>
-      <text class="nav-title">�· �员详情</text>
+      <text class="nav-title">行 · �员详情</text>
     </view>
 
-    <!-- 五维能��-->
+    <!-- 五维能�� -->
     <FamilyEnergyBar
       dimensionCode="action"
       :sandboxData="sandboxData"
       :dualDimension="dualDimension" />
 
-    <!-- �员信��-->
+    <!-- �员信�� -->
     <view class="member-card" v-if="memberInfo">
       <view class="member-avatar action-avatar">
-        <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || 'å­? }}</text>
+        <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || 'å­©' }}</text>
       </view>
       <view class="member-info">
         <text class="member-name">{{ memberInfo.name || 'å­©å­�' }}</text>
@@ -25,7 +25,7 @@
       </view>
       <view class="member-score" v-if="dualDimension">
         <text class="score-value action-score">{{ dualDimension.energy || 0 }}</text>
-        <text class="score-label">能��/text>
+        <text class="score-label">能�值</text>
       </view>
     </view>
 

+ 8 - 8
cfc-frontend/pages/action/relationship-questionnaire.vue

@@ -2,10 +2,10 @@
   <view class="container">
     <view class="page-header">
       <text class="page-title">关系问�</text>
-      <text class="page-subtitle" v-if="memberName">为「{{ memberName }}�评估关系质�/text>
+      <text class="page-subtitle" v-if="memberName">为「{{ memberName }}�评估关系质�</text>
     </view>
 
-    <!-- 加载状�-->
+    <!-- 加载状æ€-->
     <view v-if="loading" class="loading-wrap">
       <text class="loading-text">AI 正在生�问�...</text>
     </view>
@@ -32,10 +32,10 @@
       </view>
     </view>
 
-    <!-- 无问�-->
+    <!-- 无问� -->
     <view v-else class="empty-wrap">
       <text class="empty-text">暂无�用问�</text>
-      <button class="btn-generate" @click="generateQuestionnaire">生�新问�/button>
+      <button class="btn-generate" @click="generateQuestionnaire">生�新问�</button>
     </view>
 
     <!-- 结果展示 -->
@@ -58,7 +58,7 @@
             <text class="result-score-value">{{ Math.round(result.intimacyScore || 0) }}</text>
           </view>
           <view class="result-score-item">
-            <text class="result-score-label">沟�/text>
+            <text class="result-score-label">沟通</text>
             <view class="result-bar-bg">
               <view class="result-bar-fill communication" :style="{width: (result.communicationScore || 0) + '%'}"></view>
             </view>
@@ -88,7 +88,7 @@ export default {
       dimensionLabels: {
         trust: 'ä¿¡ä»»',
         intimacy: '亲密',
-        communication: '沟�
+        communication: '沟通'
       },
       optionLetters: ['A', 'B', 'C', 'D', 'E']
     }
@@ -121,7 +121,7 @@ export default {
             this.questions = []
           }
         } else {
-          // 没有问�,生�新�
+          // 没有问å�·ï¼Œç”Ÿæˆ�æ–°çš
           await this.generateQuestionnaire()
         }
       } catch (e) {
@@ -157,7 +157,7 @@ export default {
     },
     async onSubmit() {
       if (!this.allAnswered || !this.snapshotId) {
-        uni.showToast({ title: '请回答所有问�, icon: 'none' })
+        uni.showToast({ title: '请回答所有问题', icon: 'none' })
         return
       }
       try {

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

@@ -1,12 +1,12 @@
 <template>
   <view class="container">
-    <!-- 加载状��?-->
+    <!-- 加载状-->
     <view v-if="loading" class="loading-wrap">
       <view class="loading-spinner"></view>
-      <text class="loading-text">加载��?..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
-    <!-- 错误状��?-->
+    <!-- 错误状-->
     <view v-else-if="error" class="error-wrap">
       <text class="error-icon">📋</text>
       <text class="error-text">{{ errorMsg }}</text>
@@ -15,7 +15,7 @@
 
     <!-- 活动内容 -->
     <scroll-view v-else-if="activity.id" scroll-y class="content">
-      <!-- 封面��?-->
+      <!-- 封面-->
       <image
         v-if="activity.coverImage"
         class="cover"
@@ -27,12 +27,12 @@
       <view class="info-section">
         <text class="activity-title">{{ activity.title }}</text>
 
-        <!-- 活动状态标��?-->
+        <!-- 活动状态标-->
         <view class="status-row">
           <text class="status-tag" :class="'status-' + (activity.status || 'upcoming')">{{ statusText(activity.status) }}</text>
         </view>
 
-        <!-- 活动元信��?-->
+        <!-- 活动元信-->
         <view class="meta-list">
           <view class="meta-item" v-if="activity.startTime">
             <text class="meta-icon">🕐</text>
@@ -44,7 +44,7 @@
           </view>
           <view class="meta-item" v-if="activity.maxParticipants">
             <text class="meta-icon">👥</text>
-            <text class="meta-text">{{ activity.currentParticipants || 0 }} / {{ activity.maxParticipants }} ��?/text>
+            <text class="meta-text">{{ activity.currentParticipants || 0 }} / {{ activity.maxParticipants }} 人</text>
           </view>
           <view class="meta-item">
             <text class="meta-icon">💰</text>
@@ -52,20 +52,20 @@
           </view>
         </view>
 
-        <!-- 活动简��?-->
+        <!-- 活动简-->
         <view class="desc-section" v-if="activity.description">
           <text class="section-title">活动介绍</text>
           <text class="desc-text">{{ activity.description }}</text>
         </view>
 
-        <!-- 付费不退费说��?-->
+        <!-- 付费不退费说-->
         <view class="refund-notice" v-if="activity.price > 0">
           <text class="refund-notice-icon">⚠️</text>
-          <text class="refund-notice-text">本活动为付费活动,报名成功后不支持退��?/text>
+          <text class="refund-notice-text">本活动为付费活动,报名成功后不支持退费</text>
         </view>
       </view>
 
-      <!-- 底部操作��?-->
+      <!-- 底部操作-->
       <view class="bottom-bar">
         <view class="price-info">
           <text class="bottom-type">活动</text>
@@ -80,8 +80,8 @@
             :disabled="registrationLoading || paying"
             @click="onRegister"
           >
-            <text v-if="registrationLoading">报名��?..</text>
-            <text v-else-if="paying">支付��?..</text>
+            <text v-if="registrationLoading">报名中...</text>
+            <text v-else-if="paying">支付中...</text>
             <text v-else-if="activity.price > 0">¥{{ activity.price }} 立即报名</text>
             <text v-else>立即报名</text>
           </button>
@@ -92,7 +92,7 @@
             class="btn-register-done"
             disabled
           >
-            <text>报名待审��?/text>
+            <text>报名待审核</text>
           </button>
           
           <!-- 已报名可取消 -->
@@ -112,8 +112,8 @@
             :disabled="checkinLoading || checkinDone"
             @click="onCheckin"
           >
-            <text v-if="checkinLoading">签到��?..</text>
-            <text v-else-if="checkinDone">已签��?��?/text>
+            <text v-if="checkinLoading">签到中...</text>
+            <text v-else-if="checkinDone">已签到 ✓</text>
             <text v-else>签到</text>
           </button>
         </view>
@@ -122,16 +122,16 @@
       <!-- 能量扣减提示弹窗 -->
       <modal v-if="showPenaltyModal" class="penalty-modal" :show="showPenaltyModal" @close="showPenaltyModal = false">
         <view class="penalty-content">
-          <text class="penalty-title">签到成功但已扣能��?/text>
-          <text class="penalty-desc">您未报名参加此活动,已被扣除 {{ penaltyAmount }} 点能量��?/text>
+          <text class="penalty-title">签到成功但已扣能量</text>
+          <text class="penalty-desc">您未报名参加此活动,已被扣除 {{ penaltyAmount }} 点能量值</text>
           <button class="penalty-btn" @click="showPenaltyModal = false">我知道了</button>
         </view>
       </modal>
     </scroll-view>
 
-    <!-- 空状��?-->
+    <!-- 空状-->
     <view v-else class="empty-wrap">
-      <text class="empty-text">活动不存在或已下��?/text>
+      <text class="empty-text">活动不存在或已下架</text>
     </view>
   </view>
 </template>
@@ -186,7 +186,7 @@ export default {
       var h12 = hour % 12
       if (h12 === 0) h12 = 12
       var minStr = minute < 10 ? '0' + minute : minute
-      return year + '��? + month + '��? + day + '��?' + ampm + h12 + ':' + minStr
+      return year + '年' + month + '月' + day + '日 ' + ampm + h12 + ':' + minStr
     },
     loadDetail: function(id) {
       var self = this
@@ -224,7 +224,7 @@ export default {
       })
     },
     statusText: function(status) {
-      var map = { draft: '草稿', published: '进行��?, ended: '已结��? }
+      var map = { draft: '草稿', published: '进行中', ended: '已结束' }
       return map[status] || '未知'
     },
     onCheckin: function() {
@@ -250,7 +250,7 @@ export default {
           }
           if (res.data.alreadyCompleted) {
             self.checkinDone = true
-            uni.showToast({ title: '已签��?, icon: 'success' })
+            uni.showToast({ title: '已签到', icon: 'success' })
           } else if (res.data.pointsEarned && res.data.pointsEarned > 0) {
             self.checkinDone = true
             self.checkinPoints = res.data.pointsEarned
@@ -261,7 +261,7 @@ export default {
           }
         } else {
           var msg = (res && res.message) || '签到失败'
-          // 如果是报名待审核,提示用��?
+          // 如果是报名待审核,提示用
           if (msg.indexOf('报名') !== -1 || msg.indexOf('审核') !== -1) {
             uni.showModal({ title: '提示', content: msg, showCancel: false })
           } else {
@@ -281,13 +281,13 @@ export default {
         return
       }
 
-      // 付费活动 ��?先确认支��?
+      // 付费活动 → 先确认支付
       if (self.activity && self.activity.price > 0) {
         uni.showModal({
           title: '确认报名',
           content: '该活动需支付 ¥' + self.activity.price + ',报名成功后不支持退费。是否继续?',
           confirmText: '确认支付',
-          cancelText: '再想��?,
+          cancelText: '再想想',
           success: function(confirmRes) {
             if (confirmRes.confirm) {
               self.doRegister(childId)
@@ -323,7 +323,7 @@ export default {
       var self = this
       uni.showModal({
         title: '提示',
-        content: '确定要取消报名吗��?,
+        content: '确定要取消报名吗?',
         success: function(res) {
           if (res.confirm) {
             var childId = uni.getStorageSync('currentChildId')
@@ -332,7 +332,7 @@ export default {
               self.registrationLoading = false
               if (res && res.code === 200) {
                 self.registrationStatus = null
-                uni.showToast({ title: '已取消报��?, icon: 'success' })
+                uni.showToast({ title: '已取消报名', icon: 'success' })
               } else {
                 uni.showToast({ title: (res && res.message) || '取消失败', icon: 'none' })
               }
@@ -354,7 +354,7 @@ export default {
   background: #FFF7ED;
 }
 
-/* 加载 / 错误 / 空状��?*/
+/* 加载 / 错误 / 空状*/
 .loading-wrap,
 .error-wrap,
 .empty-wrap {
@@ -397,7 +397,7 @@ export default {
   line-height: 1.5;
 }
 
-/* 内容��?*/
+/* 内容*/
 .content {
   height: 100vh;
   padding-bottom: 120rpx;
@@ -411,7 +411,7 @@ export default {
   background: #f0f0f0;
 }
 
-/* 信息��?*/
+/* 信息*/
 .info-section {
   padding: 30rpx;
 }
@@ -435,7 +435,7 @@ export default {
 .status-ended { background: #F5F5F5; color: #999; }
 .status-upcoming { background: #FFF7ED; color: #F97316; }
 
-/* 元信息列��?*/
+/* 元信息列*/
 .meta-list {
   margin-top: 24rpx;
   background: #fff;
@@ -484,7 +484,7 @@ export default {
   line-height: 1.6;
 }
 
-/* 付费不退费说��?*/
+/* 付费不退费说*/
 .refund-notice {
   margin-top: 20rpx;
   margin-left: 30rpx;
@@ -509,7 +509,7 @@ export default {
   line-height: 1.4;
 }
 
-/* 底部操作��?*/
+/* 底部操作*/
 .bottom-bar {
   position: fixed;
   left: 0;

+ 22 - 22
cfc-frontend/pages/activity/create.vue

@@ -6,12 +6,12 @@
       <!-- 活动标题 -->
       <view class="form-item">
         <text class="form-label">活动标题 *</text>
-        <input class="form-input" v-model="form.title" placeholder="请输入活动标� maxlength="50" />
+        <input class="form-input" v-model="form.title" placeholder="请输入活动标题" maxlength="50" />
       </view>
 
       <!-- 活动维度 -->
       <view class="form-item">
-        <text class="form-label">所属维�*</text>
+        <text class="form-label">所属维度 *</text>
         <picker class="form-picker" :value="dimIdx" :range="dimensionOptions" range-key="label" @change="onDimChange">
           <text class="picker-text">{{ form.dimensionCode ? dimLabel(form.dimensionCode) : '请选择维度' }}</text>
         </picker>
@@ -25,9 +25,9 @@
         </picker>
       </view>
 
-      <!-- 开始时�-->
+      <!-- 开始时间 -->
       <view class="form-item">
-        <text class="form-label">开始时�*</text>
+        <text class="form-label">开始时间 *</text>
         <picker class="form-picker" mode="date" :value="datePart" @change="onStartDateChange">
           <text class="picker-text">{{ datePart || '选择日期' }}</text>
         </picker>
@@ -50,17 +50,17 @@
       <!-- 活动地点 -->
       <view class="form-item">
         <text class="form-label">活动地点</text>
-        <input class="form-input" v-model="form.location" placeholder="请输入活动地� maxlength="100" />
+        <input class="form-input" v-model="form.location" placeholder="请输入活动地点" maxlength="100" />
       </view>
 
       <!-- 人数 + 价格 -->
       <view class="form-item-row">
         <view class="form-item half">
-          <text class="form-label">最大人�/text>
+          <text class="form-label">最大人数</text>
           <input class="form-input" type="number" v-model="maxParticipantsStr" placeholder="0=��" />
         </view>
         <view class="form-item half">
-          <text class="form-label">价格(元�/text>
+          <text class="form-label">价格(元)</text>
           <input class="form-input" type="digit" v-model="priceYuan" placeholder="0=�费" />
         </view>
       </view>
@@ -77,24 +77,24 @@
       <!-- 活动�述 -->
       <view class="form-item">
         <text class="form-label">活动�述</text>
-        <textarea class="form-textarea" v-model="form.description" placeholder="请输入活动详细介� maxlength="500"
+        <textarea class="form-textarea" v-model="form.description" placeholder="请输入活动详细介�" maxlength="500"
           auto-height />
       </view>
 
       <!-- �作按钮 -->
       <view class="form-actions">
         <view class="btn-save" @click="handleSave">
-          <text>�存为��/text>
+          <text>�存为�稿</text>
         </view>
         <view class="btn-publish" @click="handlePublish">
-          <text>�存并��/text>
+          <text>�存并�布</text>
         </view>
       </view>
     </view>
 
     <view class="loading" v-if="loading">
       <view class="loading-spinner"></view>
-      <text>加载�..</text>
+      <text>加载中...</text>
     </view>
   </view>
 </template>
@@ -139,11 +139,11 @@ export default {
       dimIdx: 0,
       typeIdx: 0,
       dimensionOptions: [
-        { key: 'body', label: '�· 主动�康' },
-        { key: 'mind', label: '�· 情感丰盈' },
-        { key: 'wisdom', label: '�· 赋能未�' },
-        { key: 'action', label: '�· 知行�一' },
-        { key: 'wealth', label: '�· 物质精神' }
+        { key: 'body', label: '身 · 主动�康' },
+        { key: 'mind', label: '心 · 情感丰盈' },
+        { key: 'wisdom', label: '智 · 赋能未�' },
+        { key: 'action', label: '行 · 知行�一' },
+        { key: 'wealth', label: '富 · 物质精神' }
       ],
       typeOptions: [
         { key: 'offline', label: '线下活动' },
@@ -280,11 +280,11 @@ export default {
     },
     validate() {
       if (!this.form.title) {
-        uni.showToast({ title: '请输入活动标�, icon: 'none' })
+        uni.showToast({ title: '请输入活动标题', icon: 'none' })
         return false
       }
       if (!this.form.dimensionCode) {
-        uni.showToast({ title: '请选择所属维�, icon: 'none' })
+        uni.showToast({ title: '请选择所属维度', icon: 'none' })
         return false
       }
       if (!this.form.activityType) {
@@ -292,7 +292,7 @@ export default {
         return false
       }
       if (!this.datePart || !this.timePart) {
-        uni.showToast({ title: '请选择开始时�, icon: 'none' })
+        uni.showToast({ title: '请选择开始时间', icon: 'none' })
         return false
       }
       return true
@@ -322,7 +322,7 @@ export default {
         adminPublishActivity(id).then(function(r) {
           self.loading = false
           if (r && r.code === 200) {
-            uni.showToast({ title: '已��, icon: 'success' })
+            uni.showToast({ title: '已�布', icon: 'success' })
             setTimeout(function() {
               uni.navigateBack()
             }, 1200)
@@ -343,7 +343,7 @@ export default {
               doPublish(newId)
             } else {
               self.loading = false
-              uni.showToast({ title: '已�存��, icon: 'success' })
+              uni.showToast({ title: '已�存�稿', icon: 'success' })
               setTimeout(function() { uni.navigateBack() }, 1200)
             }
           } else {
@@ -361,7 +361,7 @@ export default {
               doPublish(self.activityId)
             } else {
               self.loading = false
-              uni.showToast({ title: '已��, icon: 'success' })
+              uni.showToast({ title: '已�存', icon: 'success' })
               setTimeout(function() { uni.navigateBack() }, 1200)
             }
           } else {

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

@@ -66,7 +66,7 @@
               <text class="card-meta" v-if="act.location">� {{ act.location }}</text>
               <view class="card-bottom">
                 <text class="card-status" :class="'status-' + (act._cls || 'upcoming')">
-                  {{ act._txt || '待开� }}
+                  {{ act._txt || '待开始' }}
                 </text>
                 <text class="card-price" v-if="act.price > 0">Â¥{{ formatPrice(act.price) }}</text>
                 <text class="card-price free" v-else>�费</text>
@@ -86,20 +86,20 @@
         <!-- Empty state for mine -->
         <view class="empty-state" v-else-if="!mineLoading">
           <text class="empty-icon">📋</text>
-          <text class="empty-title">暂无报�的活�/text>
-          <text class="empty-desc">去�现页探索精彩活动�/text>
-          <button class="empty-btn" @click="switchToDiscover">去�现活�/button>
+          <text class="empty-title">暂无报�的活动</text>
+          <text class="empty-desc">去�现页探索精彩活动�</text>
+          <button class="empty-btn" @click="switchToDiscover">去�现活动</button>
         </view>
 
         <!-- Loading state -->
         <view class="loading-state" v-if="mineLoading">
           <view class="loading-spinner"></view>
-          <text class="loading-text">加载�..</text>
+          <text class="loading-text">加载中...</text>
         </view>
 
         <!-- Load more tip -->
         <view class="load-more-tip" v-if="myActivities.length > 0 && !hasMore && currentTab === 'mine'">
-          <text class="load-more-text">没有更多�/text>
+          <text class="load-more-text">没有更多了</text>
         </view>
       </view>
 
@@ -138,7 +138,7 @@
               <text class="card-meta">{{ act.startTime }}</text>
               <text class="card-meta" v-if="act.location">� {{ act.location }}</text>
               <view class="card-bottom">
-                <text class="card-status status-published">进行�/text>
+                <text class="card-status status-published">进行中</text>
                 <text class="card-price" v-if="act.price > 0">Â¥{{ formatPrice(act.price) }}</text>
                 <text class="card-price free" v-else>�费</text>
               </view>
@@ -150,18 +150,18 @@
         <view class="empty-state" v-else-if="!discoverLoading">
           <text class="empty-icon">�</text>
           <text class="empty-title">暂无活动</text>
-          <text class="empty-desc">����看看�/text>
+          <text class="empty-desc">����看看�</text>
         </view>
 
         <!-- Loading state -->
         <view class="loading-state" v-if="discoverLoading">
           <view class="loading-spinner"></view>
-          <text class="loading-text">加载�..</text>
+          <text class="loading-text">加载中...</text>
         </view>
 
         <!-- Load more tip -->
         <view class="load-more-tip" v-if="discoverActivities.length > 0 && !hasMore && currentTab === 'discover'">
-          <text class="load-more-text">没有更多�/text>
+          <text class="load-more-text">没有更多了</text>
         </view>
       </view>
 
@@ -200,7 +200,7 @@
               <text class="card-meta">{{ act.startTime }}</text>
               <text class="card-meta" v-if="act.location">� {{ act.location }}</text>
               <view class="card-bottom">
-                <text class="card-status status-ended">已结�/text>
+                <text class="card-status status-ended">已结�</text>
                 <text class="card-price" v-if="act.price > 0">Â¥{{ formatPrice(act.price) }}</text>
                 <text class="card-price free" v-else>�费</text>
               </view>
@@ -218,12 +218,12 @@
         <!-- Loading state -->
         <view class="loading-state" v-if="historyLoading">
           <view class="loading-spinner"></view>
-          <text class="loading-text">加载�..</text>
+          <text class="loading-text">加载中...</text>
         </view>
 
         <!-- Load more tip -->
         <view class="load-more-tip" v-if="historyActivities.length > 0 && !hasMore && currentTab === 'history'">
-          <text class="load-more-text">没有更多�/text>
+          <text class="load-more-text">没有更多了</text>
         </view>
       </view>
 
@@ -237,7 +237,7 @@
           </view>
           <view class="manage-stat-card">
             <text class="manage-stat-num manage-published">{{ manageStats.published }}</text>
-            <text class="manage-stat-label">已��/text>
+            <text class="manage-stat-label">已�布</text>
           </view>
           <view class="manage-stat-card">
             <text class="manage-stat-num manage-draft">{{ manageStats.draft }}</text>
@@ -245,14 +245,14 @@
           </view>
           <view class="manage-stat-card">
             <text class="manage-stat-num manage-ended">{{ manageStats.ended }}</text>
-            <text class="manage-stat-label">已结�/text>
+            <text class="manage-stat-label">已结�</text>
           </view>
         </view>
 
         <!-- Quick actions -->
         <view class="manage-actions">
           <view class="manage-action-btn" @click="goCreate">
-            <text class="manage-action-icon">ï¼?/text>
+            <text class="manage-action-icon">+</text>
             <text class="manage-action-text">创建活动</text>
           </view>
         </view>
@@ -290,12 +290,12 @@
         </view>
         <view class="empty-state" v-else-if="!manageLoading">
           <text class="empty-icon">📊</text>
-          <text class="empty-title">暂无管�的活�/text>
-          <text class="empty-desc">点击上方「创建活动�开�/text>
+          <text class="empty-title">暂无管�的活动</text>
+          <text class="empty-desc">点击上方「创建活动�开始</text>
         </view>
         <view class="loading-state" v-if="manageLoading">
           <view class="loading-spinner"></view>
-          <text class="loading-text">加载�..</text>
+          <text class="loading-text">加载中...</text>
         </view>
       </view>
     </scroll-view>
@@ -323,17 +323,17 @@ export default {
       currentTab: 'mine',
       mineFilters: [
         { label: '全部', value: '' },
-        { label: '待开�, value: 'upcoming' },
-        { label: '待审�, value: 'pending' },
-        { label: '已签�, value: 'checked_in' }
+        { label: '待开始', value: 'upcoming' },
+        { label: '待审核', value: 'pending' },
+        { label: '已签到', value: 'checked_in' }
       ],
       dimensionFilters: [
         { label: '全部', value: '' },
-        { label: '�, value: 'body' },
-        { label: 'å¿?, value: 'mind' },
-        { label: 'æ™?, value: 'wisdom' },
-        { label: 'è¡?, value: 'action' },
-        { label: '�, value: 'wealth' }
+        { label: '身', value: 'body' },
+        { label: '心', value: 'mind' },
+        { label: '智', value: 'wisdom' },
+        { label: '行', value: 'action' },
+        { label: '富', value: 'wealth' }
       ],
       currentMineFilter: '',
       currentDimension: '',
@@ -433,9 +433,9 @@ export default {
     statusLabel: function(status) {
       var map = {
         draft: '�稿',
-        published: '进行�,
-        ended: '已结�,
-        cancelled: '已��
+        published: '进行中',
+        ended: '已结�',
+        cancelled: '已�消'
       }
       return map[status] || status
     },
@@ -443,10 +443,10 @@ export default {
       var self = this
       uni.showModal({
         title: '�示',
-        content: '确认�布此活动�?�布�将对外���,
+        content: '确认�布此活动�?�布�将对外��。',
         success: function(res) {
           if (res.confirm) {
-            uni.showLoading({ title: '�布�..' })
+            uni.showLoading({ title: '�布中...' })
             setTimeout(function() {
               uni.hideLoading()
               uni.showToast({ title: '�布�功', icon: 'success' })
@@ -460,10 +460,10 @@ export default {
       var self = this
       uni.showModal({
         title: '�示',
-        content: '确认结�此活动�?结����接�新�与者�,
+        content: '确认结�此活动�?结����接�新�与者。',
         success: function(res) {
           if (res.confirm) {
-            uni.showLoading({ title: '�作�..' })
+            uni.showLoading({ title: '�作中...' })
             setTimeout(function() {
               uni.hideLoading()
               uni.showToast({ title: '�作�功', icon: 'success' })
@@ -662,19 +662,19 @@ export default {
     decorateActivity: function(act) {
       if (act.status) {
         act._cls = act.status
-        var map = { pending: '待审�, approved: '报��功', rejected: '已拒�, cancelled: '已��, checked_in: '已签� }
+        var map = { pending: '待审核', approved: '报��功', rejected: '已拒�', cancelled: '已�消', checked_in: '已签到' }
         act._txt = map[act.status] || act.status
       } else {
         if (act.endTime) {
           var endTime = new Date(act.endTime.replace(/-/g, '/'))
           if (endTime < new Date()) {
             act._cls = 'ended'
-            act._txt = '已结�
+            act._txt = '已结�'
             return act
           }
         }
         act._cls = 'upcoming'
-        act._txt = '待开�
+        act._txt = '待开始'
       }
       return act
     },
@@ -700,7 +700,7 @@ export default {
       var self = this
       uni.showModal({
         title: '�示',
-        content: '确定��消报���,
+        content: '确定��消报��?',
         success: function(res) {
           if (res.confirm) {
             var childId = uni.getStorageSync('currentChildId')
@@ -710,7 +710,7 @@ export default {
             }
             cancelActivityRegistration({ id: act.activityId || act.id, childId: childId }).then(function(res) {
               if (res && res.code === 200) {
-                uni.showToast({ title: '已�消报�, icon: 'success' })
+                uni.showToast({ title: '已�消报�', icon: 'success' })
                 self.loadMyActivities(true)
               } else {
                 uni.showToast({ title: (res && res.message) || '�消失败', icon: 'none' })

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

@@ -1,9 +1,9 @@
 <template>
   <view class="chat-container">
-    <!-- 导航�?-->
+    <!-- 导航-->
     <view class="chat-nav" :class="'mascot-' + mascotCode">
       <view class="nav-back" @click="goBack">
-        <text class="nav-back-icon">�?/text>
+        <text class="nav-back-icon">‹</text>
       </view>
       <text class="nav-title">{{ isNutrition ? '精准营养助手' : 'AI 家庭助手' }}</text>
       <view class="nav-actions">
@@ -11,7 +11,7 @@
           <text class="mascot-badge-icon">{{ mascotIcon }}</text>
           <text class="mascot-badge-name">{{ mascotName }}</text>
         </view>
-        <text class="nav-action" @click="showConversations = !showConversations" v-else>�?/text>
+        <text class="nav-action" @click="showConversations = !showConversations" v-else>☰</text>
       </view>
     </view>
 
@@ -20,13 +20,13 @@
     <view class="conv-sidebar" :class="{ 'conv-sidebar-open': showConversations }">
       <view class="conv-header">
         <text class="conv-header-title">会话列表</text>
-        <text class="conv-header-new" @click="newConversation">+ 新会�?/text>
+        <text class="conv-header-new" @click="newConversation">+ 新会话</text>
       </view>
       <scroll-view class="conv-list" scroll-y>
         <view class="conv-item" v-for="conv in conversations" :key="conv.id"
           :class="{ 'conv-item-active': conv.id === currentConversationId }"
           @click="switchConversation(conv.id)">
-          <text class="conv-item-name">{{ conv.name || '新会�? }}</text>
+          <text class="conv-item-name">{{ conv.name || '新会话' }}</text>
           <text class="conv-item-time">{{ formatTime(conv.updated_at) }}</text>
         </view>
         <BaseEmpty v-if="conversations.length === 0" text="暂无会话" icon="💬" />
@@ -39,7 +39,7 @@
       <view class="message-list-inner">
         <view class="welcome-card" v-if="messages.length === 0 && !sending">
           <view class="welcome-icon">{{ mascotIcon || (isNutrition ? '🥗' : '🤖') }}</view>
-          <text class="welcome-title">{{ isNutrition ? '你好!我是精准营养助�? : ('你好!我�? + (mascotName || '家庭助手')) }}</text>
+          <text class="welcome-title">{{ isNutrition ? '你好!我是精准营养助手' : ('你好!我是' + (mascotName || '家庭助手')) }}</text>
           <text class="welcome-desc">{{ welcomeSubtitle }}</text>
           <view class="welcome-suggestions">
             <view class="welcome-suggestion" v-if="!isNutrition" @click="quickQuestion('小明最近任务完成怎么样?')">
@@ -47,20 +47,20 @@
               <text class="suggestion-text">小明最近任务完成怎么样?</text>
             </view>
             <view class="welcome-suggestion" v-if="!isNutrition" @click="quickQuestion('我家孩子的能量评分怎么样?')">
-              <text class="suggestion-icon">�?/text>
+              <text class="suggestion-icon">⚡</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 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="isNutrition" @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>
         </view>
@@ -99,7 +99,7 @@
           </view>
         </view>
 
-        <!-- 加载�?-->
+        <!-- 加载-->
         <view class="message message-ai" v-if="sending">
           <view class="message-avatar">{{ mascotIcon || '🤖' }}</view>
           <view class="message-bubble ai-bubble typing">
@@ -113,7 +113,7 @@
       </view>
     </scroll-view>
 
-    <!-- 输入�?-->
+    <!-- 输入-->
     <view class="chat-input-area">
       <view class="chat-input-wrap">
         <input class="chat-input" v-model="inputText" placeholder="问我关于家庭和孩子的问题..."
@@ -121,7 +121,7 @@
       </view>
       <view class="chat-send-btn" :class="{ 'chat-send-active': inputText.trim() }"
         @click="sendMessage">
-        <text class="send-icon">�?/text>
+        <text class="send-icon">➤</text>
       </view>
     </view>
   </view>
@@ -164,19 +164,19 @@ export default {
       }
       if (this.fromPage) {
         var pageNames = {
-          'pages/body/index': '�?,
-          'pages/wisdom/index': '�?,
-          'pages/mind/index': '�?,
-'pages/home/index': '首页',
-  'pages/home/parent-index': '首页',
-  'pages/home/child-index': '首页',
+          'pages/body/index': '身',
+          'pages/wisdom/index': '智',
+          'pages/mind/index': '心',
+          'pages/index/index': '首页',
+          'pages/index/parent-index': '首页',
+          'pages/index/child-index': '首页',
           'pages/profile/profile': '我的',
           'pages/profile/children': '我的',
           'pages/shop/index': '商城',
           'pages/discover/index': '发现'
         }
         var pageName = pageNames[this.fromPage] || this.fromPage
-        return '�?' + pageName + ' 发起,我可以帮你了解�?
+        return '从 ' + pageName + ' 发起,我可以帮你了解:'
       }
       return '我可以帮你了解孩子的成长情况,比如:'
     }
@@ -202,7 +202,7 @@ export default {
       }
     }
     this.loadConversations()
-    // 如果有预填消息,自动发�?
+    // 如果有预填消息,自动发
     var self = this
     if (this.pendingFirstMessage) {
       this.$nextTick(function() {
@@ -317,7 +317,7 @@ export default {
         }
       }
 
-      // 更新 conversationId(新建会话时 Dify 返回�?
+      // 更新 conversationId(新建会话时 Dify 返回
       if (data.conversationId && !this.currentConversationId) {
         this.currentConversationId = data.conversationId
         // 刷新会话列表
@@ -327,7 +327,7 @@ export default {
         // 显示错误
         const lastMsg = this.messages[this.messages.length - 1]
         if (lastMsg) {
-          lastMsg.answer = '抱歉,我暂时无法回答,请稍后再试�?
+          lastMsg.answer = '抱歉,我暂时无法回答,请稍后再试。'
         }
       } finally {
         this.sending = false
@@ -379,7 +379,7 @@ export default {
   position: relative;
 }
 
-/* 导航�?*/
+/* 导航*/
 .chat-nav {
   display: flex;
   align-items: center;
@@ -652,7 +652,7 @@ export default {
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
 }
 
-/* 输入�?*/
+/* 输入*/
 .chat-input-area {
   display: flex;
   align-items: center;

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

@@ -3,10 +3,10 @@
     <!-- loading -->
     <view v-if="loading" class="loading-wrap">
       <view class="loading-spinner"></view>
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
-    <!-- 错误状�-->
+    <!-- 错误状æ€-->
     <view v-else-if="error" class="error-wrap">
       <text class="error-icon">📄</text>
       <text class="error-text">{{ errorMsg }}</text>
@@ -14,15 +14,15 @@
     </view>
 
     <template v-else-if="article">
-      <!-- 文章内容�-->
+      <!-- 文章内容区 -->
       <scroll-view scroll-y class="content-scroll" @scrolltolower="onScrollToBottom" v-if="!showQuiz && !showResult">
         <!-- �� -->
         <image v-if="article.coverImage" class="detail-cover" :src="article.coverImage" mode="widthFix" />
         <!-- 标题 -->
         <text class="detail-title">{{ article.title }}</text>
-        <!-- 元信�-->
+        <!-- 元信� -->
         <view class="detail-meta">
-          <text class="meta-author">{{ article.author || '浠艾� }}</text>
+          <text class="meta-author">{{ article.author || '浠艾�' }}</text>
           <text class="meta-sep">|</text>
           <text class="meta-date">{{ formatDate(article.publishedAt) }}</text>
           <text class="meta-sep">|</text>
@@ -39,7 +39,7 @@
             <text class="dim-label">{{ dim.name }}</text>
           </view>
         </view>
-        <!-- 分割�-->
+        <!-- 分割线 -->
         <view class="divider"></view>
         <!-- 正文 -->
         <view class="detail-body">
@@ -60,8 +60,8 @@
       <!-- AI 答题界� -->
       <view v-if="showQuiz" class="quiz-container">
         <view class="quiz-header">
-          <text class="quiz-title">阅读�测�/text>
-          <text class="quiz-desc">回答以下问题,巩固阅读收�/text>
+          <text class="quiz-title">阅读�测验</text>
+          <text class="quiz-desc">回答以下问题,巩固阅读收获</text>
         </view>
         <view v-if="quizLoading" class="quiz-loading">
           <view class="loading-spinner"></view>
@@ -73,7 +73,7 @@
         </view>
         <template v-else-if="quizQuestions.length > 0">
           <view v-for="(q, idx) in quizQuestions" :key="idx" class="quiz-question">
-            <text class="q-title">第{{ idx + 1 }}�/text>
+            <text class="q-title">第{{ idx + 1 }}题</text>
             <text class="q-text">{{ q.question }}</text>
             <view
               v-for="(opt, optIdx) in q.options"
@@ -97,7 +97,7 @@
       <view v-if="showResult" class="result-container">
         <view class="result-card">
           <text class="result-icon">{{ resultScore === resultTotal ? '🎉' : '💪' }}</text>
-          <text class="result-title">{{ resultScore === resultTotal ? '全部答对� : '继续加油� }}</text>
+          <text class="result-title">{{ resultScore === resultTotal ? '全部答对�' : '继续加油�' }}</text>
           <text class="result-score">{{ resultScore }} / {{ resultTotal }}</text>
           <text v-if="resultPoints > 0" class="result-points">+{{ resultPoints }} 积分</text>
         </view>
@@ -163,7 +163,7 @@ export default {
           this.article = res.data
         } else {
           this.error = true
-          this.errorMsg = '文章�存在或无��查�
+          this.errorMsg = '文章�存在或无��查看'
         }
       } catch (e) {
         this.error = true
@@ -180,11 +180,11 @@ export default {
     parseDimensions(str) {
       if (!str) return []
       var dimMap = {
-        body: { code: 'body', color: '#FF8C42', name: '�, weight: 20 },
-        mind: { code: 'mind', color: '#6366F1', name: 'æ™?, weight: 20 },
-        wisdom: { code: 'wisdom', color: '#FF6B9D', name: 'å¿?, weight: 20 },
-        action: { code: 'action', color: '#10B981', name: 'è¡?, weight: 20 },
-        wealth: { code: 'wealth', color: '#F59E0B', name: '�, weight: 20 }
+        body: { code: 'body', color: '#FF8C42', name: '身', weight: 20 },
+        mind: { code: 'mind', color: '#6366F1', name: '智', weight: 20 },
+        wisdom: { code: 'wisdom', color: '#FF6B9D', name: '心', weight: 20 },
+        action: { code: 'action', color: '#10B981', name: '行', weight: 20 },
+        wealth: { code: 'wealth', color: '#F59E0B', name: '富', weight: 20 }
       }
       var codes = str.split(',').map(function(s) { return s.trim().toLowerCase() })
       return codes.filter(function(c) { return dimMap[c] }).map(function(c) { return dimMap[c] })
@@ -203,10 +203,10 @@ export default {
       this.$forceUpdate()
     },
     onScrollToBottom() {
-      // 滚动到底�
+      // 滚动到底部
     },
     async onReadComplete() {
-      // 计时器已移除,直接进入答�
+      // 计时器已移除,直接进入答题
       this.showQuiz = true
       this.loadQuiz()
     },
@@ -300,7 +300,7 @@ export default {
 .detail-footer { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; padding: 20rpx 30rpx; display: flex; align-items: center; box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.06); z-index: 10; }
 .read-btn { flex: 1; 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; }
 .read-btn::after { border: none; }
-/* 答题�*/
+/* 答题区 */
 .quiz-container { padding: 30rpx; }
 .quiz-header { text-align: center; margin-bottom: 40rpx; }
 .quiz-title { font-size: 34rpx; font-weight: bold; color: #333; display: block; }
@@ -320,7 +320,7 @@ export default {
 .submit-btn { width: 100%; height: 88rpx; line-height: 88rpx; background: linear-gradient(135deg, #F97316, #EA580C); color: #fff; font-size: 32rpx; font-weight: bold; border-radius: 44rpx; text-align: center; border: none; margin-top: 20rpx; }
 .submit-btn[disabled] { opacity: 0.4; }
 .submit-btn::after { border: none; }
-/* 结果�*/
+/* 结果页 */
 .result-container { display: flex; flex-direction: column; align-items: center; padding: 120rpx 30rpx; }
 .result-card { background: #fff; border-radius: 24rpx; padding: 60rpx 80rpx; text-align: center; box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.08); margin-bottom: 60rpx; }
 .result-icon { font-size: 100rpx; display: block; margin-bottom: 20rpx; }

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

@@ -1,19 +1,19 @@
 <template>
   <view class="edit-container">
-    <!-- 自定义导�-->
+    <!-- 自定义导航 -->
     <view class="edit-header">
       <view class="header-left" @click="onBack">
-        <text class="back-icon">�/text>
+        <text class="back-icon">�</text>
         <text class="back-text">返回</text>
       </view>
-      <text class="header-title">写�长记�/text>
+      <text class="header-title">写�长记录</text>
       <view class="header-right" @click="goMyPosts">
         <text class="history-text">历�</text>
       </view>
     </view>
 
     <scroll-view scroll-y class="edit-form">
-      <!-- ���-->
+      <!-- ��图 -->
       <view class="form-cover" @click="chooseCover">
         <image v-if="coverImage" :src="coverImage" mode="aspectFill" class="cover-preview" />
         <view v-else class="cover-placeholder">
@@ -30,7 +30,7 @@
         <input
           class="form-input title-input"
           v-model="title"
-          placeholder="给这篇记录�个标�
+          placeholder="给这篇记录�个标题"
           maxlength="50"
         />
         <text class="char-count">{{ title.length }}/50</text>
@@ -38,7 +38,7 @@
 
       <!-- 维度选择 -->
       <view class="form-group">
-        <text class="form-label">关�维度(选填�/text>
+        <text class="form-label">关�维度(选填)</text>
         <view class="dimension-chips">
           <view
             v-for="dim in dimensionList"
@@ -57,7 +57,7 @@
         <textarea
           class="form-textarea"
           v-model="content"
-          placeholder="记录孩�的�长点�.."
+          placeholder="记录孩�的�长点滴..."
           maxlength="2000"
         />
         <text class="char-count">{{ content.length }}/2000</text>
@@ -72,8 +72,8 @@
             @click="visibility = 'private'"
           >
             <text class="vis-icon">�</text>
-            <text class="vis-text">仅家�/text>
-            <text class="vis-desc">仅家庭�员��/text>
+            <text class="vis-text">仅家庭</text>
+            <text class="vis-desc">仅家庭�员��</text>
           </view>
           <view
             :class="['vis-option', visibility === 'public' ? 'active' : '']"
@@ -88,7 +88,7 @@
 
       <!-- �布按钮 -->
       <button class="publish-btn" :disabled="!canPublish" @click="onPublish">
-        {{ publishing ? '�布�..' : '�布' }}
+        {{ publishing ? '�布中...' : '�布' }}
       </button>
       <view style="height: 60rpx;"></view>
     </scroll-view>
@@ -109,11 +109,11 @@ export default {
       selectedDimensions: [],
       publishing: false,
       dimensionList: [
-        { code: 'body', name: '�, color: '#FF8C42' },
-        { code: 'mind', name: 'æ™?, color: '#6366F1' },
-        { code: 'wisdom', name: 'å¿?, color: '#FF6B9D' },
-        { code: 'action', name: 'è¡?, color: '#10B981' },
-        { code: 'wealth', name: '�, color: '#F59E0B' }
+        { code: 'body', name: '身', color: '#FF8C42' },
+        { code: 'mind', name: '智', color: '#6366F1' },
+        { code: 'wisdom', name: '心', color: '#FF6B9D' },
+        { code: 'action', name: '行', color: '#10B981' },
+        { code: 'wealth', name: '富', color: '#F59E0B' }
       ]
     }
   },
@@ -172,7 +172,7 @@ export default {
         var self = this
         uni.showModal({
           title: '�示',
-          content: '是��存�稿�,
+          content: '是��存�稿?',
           success: function(res) {
             if (res.confirm) {
               uni.setStorageSync('article_draft', {
@@ -206,8 +206,8 @@ export default {
         })
         if (res.code === 200) {
           var msg = this.visibility === 'public'
-            ? '�布�功,等待审�
-            : '�布�功,已对家庭��
+            ? '�布�功,等待审核'
+            : '�布�功,已对家庭��'
           uni.showToast({ title: msg, icon: 'success', duration: 2000 })
           uni.removeStorageSync('article_draft')
           var self = this
@@ -289,7 +289,7 @@ export default {
   border-radius: 20rpx;
   font-size: 22rpx;
 }
-/* 表��*/
+/* 表å�•ç»*/
 .form-group {
   background: #fff;
   border-radius: 16rpx;
@@ -316,7 +316,7 @@ export default {
   color: #666;
 }
 .dim-chip.active { color: #fff; border-color: transparent; }
-/* 文本�*/
+/* 文本æ¡*/
 .form-textarea {
   width: 100%;
   height: 300rpx;

+ 23 - 23
cfc-frontend/pages/article-center/index.vue

@@ -12,7 +12,7 @@
       </view>
     </view>
 
-    <!-- �索�(�焦时展开�-->
+    <!-- æ�œç´¢æ �(è�šç„¦æ—¶å±•å¼€ï¼-->
     <view v-if="searchFocused || searchKeyword" class="ac-search-bar">
       <input
         class="ac-search-input"
@@ -25,7 +25,7 @@
       <text class="ac-search-cancel" @click="searchKeyword = ''; searchFocused = false; onSearch()">�消</text>
     </view>
 
-    <!-- Tab 导航(�丸��-->
+    <!-- Tab 导航(è�¯ä¸¸å¼�ï¼-->
     <view class="ac-tabs">
       <scroll-view scroll-x show-scrollbar="false" class="ac-tab-scroll">
         <view
@@ -42,7 +42,7 @@
 
     <!-- 文章列表区域 -->
     <scroll-view scroll-y class="ac-scroll" @scrolltolower="onLoadMore">
-      <!-- 骨架�-->
+      <!-- 骨架å±-->
       <view v-if="loading && articles.length === 0" class="ac-skeleton-wrap">
         <view v-for="n in 3" :key="n" class="sk-card">
           <view class="sk-cover"></view>
@@ -55,7 +55,7 @@
         </view>
       </view>
 
-      <!-- 空状�-->
+      <!-- 空状æ€-->
       <view v-else-if="articles.length === 0" class="ac-empty">
         <image class="ac-empty-img" src="/static/empty-article.png" mode="aspectFit"></image>
         <text class="ac-empty-text">暂无文章</text>
@@ -93,7 +93,7 @@
             <text class="ac-card-title">{{ item.title }}</text>
             <text class="ac-card-summary" v-if="item.summary">{{ item.summary }}</text>
             <view class="ac-card-footer">
-              <text class="ac-card-author">{{ item.author || '浠艾� }}</text>
+              <text class="ac-card-author">{{ item.author || '浠艾�' }}</text>
               <text class="ac-card-sep">|</text>
               <text class="ac-card-date">{{ formatDate(item.publishedAt) }}</text>
               <text class="ac-card-fav">&#x2B50; {{ item.favCount || 0 }}</text>
@@ -104,10 +104,10 @@
 
       <!-- 加载更多 / 没有更多 -->
       <view v-if="loadingMore" class="ac-loading-more">
-        <text class="ac-loading-text">加载�..</text>
+        <text class="ac-loading-text">加载中...</text>
       </view>
       <view v-if="noMore && articles.length > 0" class="ac-no-more">
-        <text class="ac-no-more-text">�没有更多��/text>
+        <text class="ac-no-more-text">— 没有更多了 —</text>
       </view>
       <view class="ac-bottom-gap"></view>
     </scroll-view>
@@ -126,11 +126,11 @@ export default {
     return {
       tabList: [
         { code: '', name: '全部', color: '#F97316' },
-        { code: 'body', name: '�, color: '#FF8C42' },
-        { code: 'mind', name: 'å¿?, color: '#FF6B9D' },
-        { code: 'wisdom', name: 'æ™?, color: '#6366F1' },
-        { code: 'action', name: 'è¡?, color: '#10B981' },
-        { code: 'wealth', name: '�, color: '#F59E0B' }
+        { code: 'body', name: '身', color: '#FF8C42' },
+        { code: 'mind', name: '心', color: '#FF6B9D' },
+        { code: 'wisdom', name: '智', color: '#6366F1' },
+        { code: 'action', name: '行', color: '#10B981' },
+        { code: 'wealth', name: '富', color: '#F59E0B' }
       ],
       currentTab: '',
       articles: [],
@@ -146,7 +146,7 @@ export default {
     }
   },
   onLoad(options) {
-    // 支�从外部传�dimension �数,默认选中对应 tab
+    // 支�从外部传入 dimension �数,默认选中对应 tab
     if (options && options.dimension) {
       this.currentTab = options.dimension
     }
@@ -227,11 +227,11 @@ export default {
     parseDimensions(str) {
       if (!str) return []
       var dimMap = {
-        body: { code: 'body', color: '#FF8C42', name: '� },
-        mind: { code: 'mind', color: '#FF6B9D', name: 'å¿? },
-        wisdom: { code: 'wisdom', color: '#6366F1', name: 'æ™? },
-        action: { code: 'action', color: '#10B981', name: 'è¡? },
-        wealth: { code: 'wealth', color: '#F59E0B', name: '� }
+        body: { code: 'body', color: '#FF8C42', name: '身' },
+        mind: { code: 'mind', color: '#FF6B9D', name: '心' },
+        wisdom: { code: 'wisdom', color: '#6366F1', name: '智' },
+        action: { code: 'action', color: '#10B981', name: '行' },
+        wealth: { code: 'wealth', color: '#F59E0B', name: '富' }
       }
       var codes = str.split(',').map(function(s) { return s.trim().toLowerCase() })
       return codes.filter(function(c) { return dimMap[c] }).map(function(c) { return dimMap[c] })
@@ -259,7 +259,7 @@ export default {
 
 <style scoped>
 /* ====================================
-   知识中心 ��设�
+   知识中心 — �设计
    白色导航 + �丸Tab + 精装�片
    ==================================== */
 
@@ -317,7 +317,7 @@ export default {
   line-height: 1;
 }
 
-/* ---- �索展开�---- */
+/* ---- �索展开� ---- */
 .ac-search-bar {
   display: flex;
   align-items: center;
@@ -377,7 +377,7 @@ export default {
   height: calc(100vh - 200rpx);
 }
 
-/* ---- 骨架�---- */
+/* ---- 骨架å±---- */
 .ac-skeleton-wrap { padding: 24rpx 28rpx; }
 .sk-card {
   background: #fff;
@@ -410,7 +410,7 @@ export default {
   100% { background-position: 200% 0; }
 }
 
-/* ---- 空状�---- */
+/* ---- 空状æ€---- */
 .ac-empty {
   display: flex;
   flex-direction: column;
@@ -470,7 +470,7 @@ export default {
   font-weight: 500;
   line-height: 1.4;
 }
-/* 正文�*/
+/* 正文区 */
 .ac-card-body {
   padding: 24rpx 24rpx 28rpx;
 }

+ 7 - 7
cfc-frontend/pages/article-center/my-posts.vue

@@ -2,13 +2,13 @@
   <view class="posts-container">
     <scroll-view scroll-y class="posts-list" @scrolltolower="onLoadMore">
       <view v-if="loading && posts.length === 0" class="loading-wrap">
-        <text class="loading-text">加载�..</text>
+        <text class="loading-text">加载中...</text>
       </view>
 
       <view v-else-if="posts.length === 0" class="empty-wrap">
         <text class="empty-icon">�</text>
         <text class="empty-text">还没有�布过记录</text>
-        <button class="write-btn" @click="goEdit">写一�/button>
+        <button class="write-btn" @click="goEdit">写一篇</button>
       </view>
 
       <view v-else class="post-list">
@@ -37,10 +37,10 @@
       </view>
 
       <view v-if="loadingMore" class="loading-more">
-        <text class="loading-text">加载�..</text>
+        <text class="loading-text">加载中...</text>
       </view>
       <view v-if="noMore && posts.length > 0" class="no-more">
-        <text class="no-more-text">�没有更多��/text>
+        <text class="no-more-text">— 没有更多了 —</text>
       </view>
     </scroll-view>
   </view>
@@ -106,10 +106,10 @@ export default {
     },
     getStatusText(item) {
       if (item.status === 'draft' && (!item.auditStatus || item.auditStatus === 'pending')) {
-        return '审核�
+        return '审核中'
       }
-      if (item.auditStatus === 'rejected') return '已驳�
-      if (item.status === 'published') return '已��
+      if (item.auditStatus === 'rejected') return '已驳回'
+      if (item.status === 'published') return '已�布'
       return '�稿'
     },
     getStatusClass(item) {

+ 16 - 16
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测评,了解孩子的专注力发展</text>
     </view>
 
     <!-- 成长规划师选择(可选) -->
@@ -18,10 +18,10 @@
             <text>🤝</text>
           </view>
           <view class="guide-info">
-            <text class="guide-name">由系统安��?/text>
-            <text class="guide-price">购买后客服对��?/text>
+            <text class="guide-name">由系统安排</text>
+            <text class="guide-price">购买后客服对接</text>
           </view>
-          <view class="guide-check" v-if="selectedGuideId === null">��?/view>
+          <view class="guide-check" v-if="selectedGuideId === null">✓</view>
         </view>
         <view 
           class="guide-item" 
@@ -35,7 +35,7 @@
             <text class="guide-name">{{ guide.guideName }}</text>
             <text class="guide-price">{{ formatPriceWithSymbol(guide.price) }}</text>
           </view>
-          <view class="guide-check" v-if="selectedGuideId === guide.guideId">��?/view>
+          <view class="guide-check" v-if="selectedGuideId === guide.guideId">✓</view>
         </view>
       </view>
     </view>
@@ -65,7 +65,7 @@
         <picker mode="date" :value="appointmentDate" @change="onDateChange">
           <view class="picker-value">
             <text>{{ appointmentDate || '选择日期' }}</text>
-            <text class="picker-arrow">��?/text>
+            <text class="picker-arrow">›</text>
           </view>
         </picker>
       </view>
@@ -73,7 +73,7 @@
         <picker mode="time" :value="appointmentTime" @change="onTimeChange">
           <view class="picker-value">
             <text>{{ appointmentTime || '选择时间' }}</text>
-            <text class="picker-arrow">��?/text>
+            <text class="picker-arrow">›</text>
           </view>
         </picker>
       </view>
@@ -92,10 +92,10 @@
         >
           <view class="child-avatar">{{ child.nickname ? child.nickname[0] : '?' }}</view>
           <view class="child-info">
-            <text class="child-name">{{ child.nickname || '未命��? }}</text>
-            <text class="child-age">{{ child.age || 0 }}��?/text>
+            <text class="child-name">{{ child.nickname || '未命名' }}</text>
+            <text class="child-age">{{ child.age || 0 }}岁</text>
           </view>
-          <view class="child-check" v-if="selectedChildId === child.id">��?/view>
+          <view class="child-check" v-if="selectedChildId === child.id">✓</view>
         </view>
       </view>
     </view>
@@ -104,9 +104,9 @@
     <view class="section" v-if="quotaId">
       <view class="section-title">额度信息</view>
       <view class="quota-info">
-        <text class="quota-label">本次将消��?1 次测评额��?/text>
+        <text class="quota-label">本次将消耗 1 次测评额度</text>
         <text class="quota-remaining" v-if="quotaRemaining !== null">
-          剩余 {{ quotaRemaining }} ��?
+          剩余 {{ quotaRemaining }} 
         </text>
       </view>
     </view>
@@ -120,7 +120,7 @@
           <text class="price-value">{{ formatPriceWithSymbol(totalPrice) }}</text>
         </view>
         <view class="price-row">
-          <text class="price-label">成长规划��?/text>
+          <text class="price-label">成长规划师</text>
           <text class="price-value">{{ selectedGuideName }}</text>
         </view>
         <view class="price-row" v-if="inviteCodeInfo">
@@ -131,7 +131,7 @@
     </view>
 
     <!-- 提交按钮 -->
-    <button class="btn-submit" @click="submit">{{ quotaId ? '消耗额度预��? : '提交申请' }}</button>
+    <button class="btn-submit" @click="submit">{{ quotaId ? '消耗额度预约' : '提交申请' }}</button>
   </view>
 </template>
 
@@ -200,7 +200,7 @@ export default {
           }
         }
       } catch (e) {
-        console.error('获取成长规划师列表失��?, e)
+        console.error('获取成长规划师列表失败', e)
       }
     },
 
@@ -289,7 +289,7 @@ export default {
       }
 
       try {
-        uni.showLoading({ title: '提交��?..' })
+        uni.showLoading({ title: '提交中...' })
 
         if (this.quotaId) {
           const res = await createAssessmentAppointmentWithQuota({

+ 22 - 22
cfc-frontend/pages/assessment/child-info.vue

@@ -2,7 +2,7 @@
   <view class="container">
     <view class="header">
       <text class="title">孩�信�</text>
-      <text class="subtitle">请填写孩�的详细信�,用于测评档�/text>
+      <text class="subtitle">请填写孩�的详细信�,用于测评档案</text>
     </view>
 
     <!-- 基本信� -->
@@ -10,7 +10,7 @@
       <view class="section-title">基本信�</view>
       <view class="form-group">
         <view class="form-label">孩�姓�</view>
-        <input class="form-input" v-model="form.childName" placeholder="请输入孩�姓� />
+        <input class="form-input" v-model="form.childName" placeholder="请输入孩�姓�" />
       </view>
       <view class="form-group">
         <view class="form-label">出生日期</view>
@@ -22,12 +22,12 @@
         <view class="form-label">性别</view>
         <radio-group @change="onGenderChange">
           <label class="radio-item">
-            <radio value="ç”? :checked="form.childGender === 'ç”?" />
-            <text>ç”?/text>
+            <radio value="ç”·" :checked="form.childGender === 'ç”·'" />
+            <text>ç”·</text>
           </label>
           <label class="radio-item">
-            <radio value="� :checked="form.childGender === '�" />
-            <text>�/text>
+            <radio value="女" :checked="form.childGender === '女'" />
+            <text>女</text>
           </label>
         </radio-group>
       </view>
@@ -42,7 +42,7 @@
       <view class="section-title">学校信�</view>
       <view class="form-group">
         <view class="form-label">学校�称</view>
-        <input class="form-input" v-model="form.school" placeholder="请输入学校�� />
+        <input class="form-input" v-model="form.school" placeholder="请输入学校�称" />
       </view>
       <view class="form-group">
         <view class="form-label">年级</view>
@@ -50,7 +50,7 @@
       </view>
       <view class="form-group">
         <view class="form-label">�级</view>
-        <input class="form-input" v-model="form.gradeClass" placeholder="如:3� />
+        <input class="form-input" v-model="form.gradeClass" placeholder="如:3�" />
       </view>
       <view class="form-group">
         <view class="form-label">在校�绩</view>
@@ -64,8 +64,8 @@
             <text>良好</text>
           </label>
           <label class="radio-item">
-            <radio value="一� :checked="form.schoolScore === '一�" />
-            <text>一�/text>
+            <radio value="一般" :checked="form.schoolScore === '一般'" />
+            <text>一般</text>
           </label>
           <label class="radio-item">
             <radio value="较差" :checked="form.schoolScore === '较差'" />
@@ -98,11 +98,11 @@
         <input class="form-input" v-model="form.familyStatus" placeholder="如:�亲家庭/�亲家庭" />
       </view>
       <view class="form-group">
-        <view class="form-label">父�最高学�/view>
+        <view class="form-label">父�最高学历</view>
         <radio-group @change="onParentDegreeChange">
           <label class="radio-item">
-            <radio value="高中�以� :checked="form.parentDegree === '高中�以�" />
-            <text>高中�以�/text>
+            <radio value="高中�以下" :checked="form.parentDegree === '高中�以下'" />
+            <text>高中�以下</text>
           </label>
           <label class="radio-item">
             <radio value="大专" :checked="form.parentDegree === '大专'" />
@@ -130,12 +130,12 @@
         <view class="form-label">是�独生�女</view>
         <radio-group @change="onSingleChildChange">
           <label class="radio-item">
-            <radio value="� :checked="form.singleChild === '�" />
-            <text>�/text>
+            <radio value="是" :checked="form.singleChild === '是'" />
+            <text>是</text>
           </label>
           <label class="radio-item">
-            <radio value="� :checked="form.singleChild === '�" />
-            <text>�/text>
+            <radio value="�" :checked="form.singleChild === '�'" />
+            <text>�</text>
           </label>
         </radio-group>
       </view>
@@ -146,15 +146,15 @@
       <view class="section-title">地�信�</view>
       <view class="form-group">
         <view class="form-label">�份</view>
-        <input class="form-input" v-model="form.province" placeholder="请输入�� />
+        <input class="form-input" v-model="form.province" placeholder="请输入�份" />
       </view>
       <view class="form-group">
         <view class="form-label">城市</view>
-        <input class="form-input" v-model="form.city" placeholder="请输入城� />
+        <input class="form-input" v-model="form.city" placeholder="请输入城市" />
       </view>
       <view class="form-group">
         <view class="form-label">区县</view>
-        <input class="form-input" v-model="form.district" placeholder="请输入区� />
+        <input class="form-input" v-model="form.district" placeholder="请输入区县" />
       </view>
       <view class="form-group">
         <view class="form-label">详细地�</view>
@@ -175,7 +175,7 @@
       </view>
     </view>
 
-    <button class="btn-submit" @click="submit">下一�/button>
+    <button class="btn-submit" @click="submit">下一步</button>
   </view>
 </template>
 
@@ -251,7 +251,7 @@ export default {
         url: '/pages/assessment/order?guideId=' + (f.guideId || '') +
           '&guideName=' + encodeURIComponent(f.guideName || '') +
           '&packageId=' + (f.packageId || '') +
-          '&packageName=' + encodeURIComponent(f.packageName || 'DAN专注力测�) +
+          '&packageName=' + encodeURIComponent(f.packageName || 'DAN专注力测评') +
           '&childId=' + (f.childId || '') +
           '&appointmentDate=' + (f.appointmentDate || '') +
           '&appointmentTime=' + (f.appointmentTime || '') +

+ 7 - 7
cfc-frontend/pages/assessment/order.vue

@@ -13,7 +13,7 @@
         <text class="info-value">{{ packageName }}</text>
       </view>
       <view class="info-row">
-        <text class="info-label">�长规划�/text>
+        <text class="info-label">�长规划师</text>
         <text class="info-value">{{ guideName }}</text>
       </view>
       <view class="info-row">
@@ -56,7 +56,7 @@
         </view>
         <view class="pay-method-item" :class="{ active: payMethod === 'alipay' }" @click="payMethod = 'alipay'">
           <text class="pay-icon">🔷</text>
-          <text class="pay-name">支付�/text>
+          <text class="pay-name">支付�</text>
           <view class="pay-radio" v-if="payMethod === 'alipay'">
             <view class="radio-inner" />
           </view>
@@ -88,7 +88,7 @@ export default {
     }
   },
   onLoad(options) {
-    this.packageName = decodeURIComponent(options.packageName || 'DAN专注力测�)
+    this.packageName = decodeURIComponent(options.packageName || 'DAN专注力测评')
     this.guideName = decodeURIComponent(options.guideName || '')
     this.appointmentDate = options.appointmentDate || ''
     this.appointmentTime = options.appointmentTime || ''
@@ -102,11 +102,11 @@ export default {
   methods: {
     async handlePay() {
       if (!this.guideId) {
-        uni.showToast({ title: '请选择�长规划�, icon: 'none' })
+        uni.showToast({ title: '请选择�长规划师', icon: 'none' })
         return
       }
       try {
-        uni.showLoading({ title: '创建订��..' })
+        uni.showLoading({ title: '创建订�中...' })
         const res = await createAssessmentAppointment({
           childId: this.childId,
           guideId: this.guideId,
@@ -125,7 +125,7 @@ export default {
           return
         }
         const orderNo = res.data.orderNo
-        uni.showLoading({ title: '支付�..' })
+        uni.showLoading({ title: '支付中...' })
         const payRes = await payAssessmentOrder(orderNo, this.payMethod)
         uni.hideLoading()
         if (payRes.code === 200) {
@@ -133,7 +133,7 @@ export default {
           uni.removeStorageSync('assessmentChildInfo')
           uni.showModal({
             title: '支付�功',
-            content: '您的测评订�已支付,请按时�加测�,
+            content: '您的测评订�已支付,请按时�加测评',
             showCancel: false,
             success: () => {
               uni.redirectTo({ url: '/pages/assessment/results' })

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

@@ -2,12 +2,12 @@
   <view class="container">
     <view class="header">
       <text class="title">选择测评任务模�</text>
-      <text class="subtitle">选择适�孩�的测评任务模�/text>
+      <text class="subtitle">选择适�孩�的测评任务模�</text>
     </view>
 
     <!-- �长规划师选择 -->
     <view class="section" v-if="!guideId">
-      <view class="section-title">选择�长规划�/view>
+      <view class="section-title">选择�长规划师</view>
       <view class="guide-selector">
         <view 
           class="guide-item" 
@@ -21,7 +21,7 @@
             <text class="guide-name">{{ guide.guideName }}</text>
             <text class="guide-price">{{ formatPriceWithSymbol(guide.price) }}</text>
           </view>
-          <view class="guide-check" v-if="selectedGuideId === guide.guideId">�/view>
+          <view class="guide-check" v-if="selectedGuideId === guide.guideId">✓</view>
         </view>
       </view>
     </view>
@@ -47,11 +47,11 @@
           <view class="package-desc">{{ pkg.description }}</view>
           <view class="package-features">
             <view class="feature-item" v-for="(feature, index) in pkg.features" :key="index">
-              <text class="feature-icon">�/text>
+              <text class="feature-icon">✓</text>
               <text class="feature-text">{{ feature }}</text>
             </view>
           </view>
-          <view class="package-check" v-if="selectedPackageId === pkg.id">�/view>
+          <view class="package-check" v-if="selectedPackageId === pkg.id">✓</view>
         </view>
       </view>
     </view>
@@ -65,7 +65,7 @@
           <text class="price-value">{{ formatPriceWithSymbol(selectedPackage.price) }}</text>
         </view>
         <view class="price-row" v-if="selectedGuideId">
-          <text class="price-label">�长规划师费�/text>
+          <text class="price-label">�长规划师费用</text>
           <text class="price-value">{{ formatPriceWithSymbol(guidePrice) }}</text>
         </view>
         <view class="price-row" v-if="discountAmount > 0">
@@ -105,7 +105,7 @@ export default {
     }
   },
   onLoad(options) {
-    // 如果有邀请��数,自动填�
+    // 如果有邀请ç �å�‚数,自动填å…
     if (options.inviteCode) {
       this.inviteCode = options.inviteCode
       this.validateInviteCode()
@@ -122,7 +122,7 @@ export default {
   methods: {
     async loadPackages() {
       try {
-        // TODO: 从�端获�任务模�列�
+        // TODO: 从�端获�任务模�列表
         // 这里简化处�,使用模拟数�
         this.packages = [
           {
@@ -131,15 +131,15 @@ export default {
             description: '包�注�力�专注力�记忆力三项基础测评',
             price: 299,
             originalPrice: 399,
-            features: ['注�力测�, '专注力测�, '记忆力测�, '测评报告', '�长建议']
+            features: ['注�力测评', '专注力测评', '记忆力测评', '测评报告', '�长建议']
           },
           {
             id: 2,
             name: '全�测评任务模�',
-            description: '包�五项全�测评,�供详细分�报�,
+            description: '包�五项全�测评,�供详细分�报告',
             price: 499,
             originalPrice: 699,
-            features: ['注�力测�, '专注力测�, '记忆力测�, '逻辑�维测评', '综�分�报告', '个性化�长建议', '�续跟踪']
+            features: ['注�力测评', '专注力测评', '记忆力测评', '逻辑�维测评', '综�分�报告', '个性化�长建议', '�续跟踪']
           },
           {
             id: 3,
@@ -148,7 +148,7 @@ export default {
             description: '包�所有测评项目,�供专家一对一解读',
             price: 799,
             originalPrice: 999,
-            features: ['所有测评项�, '专家一对一解读', '详细分�报告', '个性化�长方案', '�续跟踪�务', '家长指导建议']
+            features: ['所有测评项目', '专家一对一解读', '详细分�报告', '个性化�长方案', '�续跟踪�务', '家长指导建议']
           }
         ]
       } catch (e) {
@@ -178,7 +178,7 @@ export default {
           }
         }
       } catch (e) {
-        console.error('获��长规划师列表失�, e)
+        console.error('获��长规划师列表失败', e)
       }
     },
 
@@ -248,7 +248,7 @@ export default {
       }
 
       try {
-        uni.showLoading({ title: '创建订��..' })
+        uni.showLoading({ title: '创建订�中...' })
 
         const userId = uni.getStorageSync('userId')
         const familyId = uni.getStorageSync('familyId')
@@ -266,7 +266,7 @@ export default {
         uni.hideLoading()
 
         if (res.code === 200) {
-          // 跳转到支付页�
+          // 跳转到支付页�
           uni.navigateTo({
             url: `/pages/assessment/purchase?orderNo=${res.data.orderNo}&totalPrice=${this.totalPrice}`
           })

+ 7 - 7
cfc-frontend/pages/assessment/quota.vue

@@ -10,25 +10,25 @@
         <view class="card-top">
           <text class="product-name">{{ item.productName }}</text>
           <text class="status-tag" :class="item.status === 'active' ? 'active' : 'used'">
-            {{ item.status === 'active' ? '�用' : '已用� }}
+            {{ item.status === 'active' ? '�用' : '已用完' }}
           </text>
         </view>
         <view class="progress-section">
           <view class="progress-bar-bg">
             <view class="progress-bar-fill" :style="{ width: progressPercent(item) + '%' }"></view>
           </view>
-          <text class="progress-text">{{ item.usedSessions }}/{{ item.totalSessions }} �/text>
+          <text class="progress-text">{{ item.usedSessions }}/{{ item.totalSessions }} 次</text>
         </view>
         <view class="card-info">
           <view class="info-row">
             <text class="info-label">剩余</text>
-            <text class="info-value highlight">{{ item.remainingSessions }} �/text>
+            <text class="info-value highlight">{{ item.remainingSessions }} 次</text>
           </view>
           <view class="info-row" v-if="item.validityEnd">
             <text class="info-label">有效期至</text>
             <text class="info-value" :class="{ expired: item.expired }">
               {{ formatDate(item.validityEnd) }}
-              <text v-if="item.expired">(已过期�/text>
+              <text v-if="item.expired">(已过期)</text>
             </text>
           </view>
         </view>
@@ -40,8 +40,8 @@
 
     <view class="empty" v-else>
       <text class="empty-icon">📋</text>
-      <text class="empty-text">暂无�用的测评��/text>
-      <button class="btn-buy" @click="goBuy">去购买任务模�/button>
+      <text class="empty-text">暂无�用的测评�度</text>
+      <button class="btn-buy" @click="goBuy">去购买任务模�</button>
     </view>
   </view>
 </template>
@@ -61,7 +61,7 @@ export default {
   methods: {
     async loadQuotas() {
       try {
-        uni.showLoading({ title: '加载�..' })
+        uni.showLoading({ title: '加载中...' })
         const res = await getAssessmentQuotas()
         uni.hideLoading()
         if (res.code === 200) {

+ 18 - 18
cfc-frontend/pages/assessment/record.vue

@@ -2,7 +2,7 @@
 <view class="container">
   <view class="header">
     <text class="title">录入测评结果</text>
-    <text class="subtitle">专业的DAN测评,记录孩子的专注力评估结��?/text>
+    <text class="subtitle">专业的DAN测评,记录孩子的专注力评估结果</text>
   </view>
 
   <!-- 孩子信息 -->
@@ -11,11 +11,11 @@
     <view class="info-card">
       <view class="info-row">
         <text class="info-label">姓名</text>
-        <text class="info-value">{{ childName || '未填��? }}</text>
+        <text class="info-value">{{ childName || '未填写' }}</text>
       </view>
       <view class="info-row">
         <text class="info-label">年龄</text>
-        <text class="info-value">{{ age || '-' }}��?/text>
+        <text class="info-value">{{ age || '-' }}岁</text>
       </view>
       <view class="info-row">
         <text class="info-label">学校</text>
@@ -30,7 +30,7 @@
     <view class="score-group">
       <view class="score-item">
         <view class="score-header">
-          <text class="score-label">注意��?/text>
+          <text class="score-label">注意力</text>
           <text class="score-value">{{ form.attentionScore }}</text>
         </view>
         <slider
@@ -46,7 +46,7 @@
       </view>
       <view class="score-item">
         <view class="score-header">
-          <text class="score-label">专注��?/text>
+          <text class="score-label">专注力</text>
           <text class="score-value">{{ form.focusScore }}</text>
         </view>
         <slider
@@ -62,7 +62,7 @@
       </view>
       <view class="score-item">
         <view class="score-header">
-          <text class="score-label">记忆��?/text>
+          <text class="score-label">记忆力</text>
           <text class="score-value">{{ form.memoryScore }}</text>
         </view>
         <slider
@@ -78,7 +78,7 @@
       </view>
       <view class="score-item">
         <view class="score-header">
-          <text class="score-label">逻辑��?/text>
+          <text class="score-label">逻辑力</text>
           <text class="score-value">{{ form.logicScore }}</text>
         </view>
         <slider
@@ -111,7 +111,7 @@
       <picker mode="date" :value="form.assessmentDate" @change="onAssessmentDateChange">
         <view class="picker-value">
           <text>{{ form.assessmentDate || '选择日期' }}</text>
-          <text class="picker-arrow">��?/text>
+          <text class="picker-arrow">›</text>
         </view>
       </picker>
     </view>
@@ -121,7 +121,7 @@
         class="form-input"
         type="number"
         v-model="form.durationMinutes"
-        placeholder="请输入测评时��?
+        placeholder="请输入测评时长"
       />
     </view>
   </view>
@@ -137,7 +137,7 @@
         :key="index"
       >
         <image class="media-image" :src="img" mode="aspectFill" />
-        <view class="media-remove" @click="removeMedia(index)">��?/view>
+        <view class="media-remove" @click="removeMedia(index)">✕</view>
       </view>
       <view class="media-add" @click="chooseMedia" v-if="mediaList.length < 9">
         <text class="media-add-icon">+</text>
@@ -176,7 +176,7 @@
     <picker mode="date" :value="form.nextReviewDate" @change="onNextReviewDateChange">
       <view class="picker-value">
         <text>{{ form.nextReviewDate || '选择复查日期' }}</text>
-        <text class="picker-arrow">��?/text>
+        <text class="picker-arrow">›</text>
       </view>
     </picker>
   </view>
@@ -187,7 +187,7 @@
     <textarea
       class="form-textarea form-textarea-short"
       v-model="form.resultDescription"
-      placeholder="请简要描述测评结��?
+      placeholder="请简要描述测评结果"
       :maxlength="500"
     />
     <text class="char-count">{{ resultDescriptionLen }}/500</text>
@@ -259,7 +259,7 @@ export default {
     if (options.school) {
       this.school = decodeURIComponent(options.school)
     }
-    // 默认测评日期为今��?
+    // 默认测评日期为今
     var now = new Date()
     var year = now.getFullYear()
     var month = String(now.getMonth() + 1).padStart(2, '0')
@@ -317,7 +317,7 @@ export default {
         return false
       }
       if (!this.form.analysisReport || !this.form.analysisReport.trim()) {
-        uni.showToast({ title: '请填写分析报��?, icon: 'none' })
+        uni.showToast({ title: '请填写分析报告', icon: 'none' })
         return false
       }
       return true
@@ -352,7 +352,7 @@ export default {
       }
 
       try {
-        uni.showLoading({ title: '保存��?..' })
+        uni.showLoading({ title: '保存中...' })
         this.submitting = true
 
         var data = this.buildRequestData('draft')
@@ -362,7 +362,7 @@ export default {
         this.submitting = false
 
         if (res.code === 200) {
-          uni.showToast({ title: '草稿已保��?, icon: 'success' })
+          uni.showToast({ title: '草稿已保存', icon: 'success' })
         } else {
           uni.showToast({ title: res.message || '保存失败', icon: 'none' })
         }
@@ -379,7 +379,7 @@ export default {
       }
 
       try {
-        uni.showLoading({ title: '提交��?..' })
+        uni.showLoading({ title: '提交中...' })
         this.submitting = true
 
         var data = this.buildRequestData('completed')
@@ -391,7 +391,7 @@ export default {
         if (res.code === 200) {
           uni.showModal({
             title: '提交成功',
-            content: '测评结果已提交,家长将收到评估报��?,
+            content: '测评结果已提交,家长将收到评估报告',
             showCancel: false,
             success: function() {
               uni.navigateBack()

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

@@ -5,7 +5,7 @@
       <text class="subtitle">�亦�銝讠漣�鞾鵭閫��撣��瘚贝��亙�</text>
     </view>
 
-    <!-- ��倌憿?-->
+    <!-- ��倌憿-->
     <view class="tabs">
       <view 
         class="tab-item" 
@@ -34,7 +34,7 @@
           @click="viewReportDetail(report)"
         >
           <view class="report-header">
-            <text class="report-child">{{ report.childName || '�芸𦶢�? }}</text>
+            <text class="report-child">{{ report.childName || '�芸𦶢��' }}</text>
             <text class="report-date">{{ formatDate(report.assessmentDate) }}</text>
           </view>
           <view class="report-scores">
@@ -50,7 +50,7 @@
       </view>
       <view class="empty-state" v-else>
         <text class="empty-icon">��</text>
-        <text class="empty-text">餈䀹瓷�㗇�霂�𥁒�?/text>
+        <text class="empty-text">餈䀹瓷�㗇�霂�𥁒��</text>
         <text class="empty-hint">摰峕�瘚贝��𦒘�����亙�</text>
       </view>
     </view>
@@ -66,9 +66,9 @@
           @click="viewReportDetail(report)"
         >
           <view class="report-header">
-            <text class="report-child">{{ report.childName || '�芸𦶢�? }}</text>
+            <text class="report-child">{{ report.childName || '�芸𦶢��' }}</text>
             <text class="report-date">{{ formatDate(report.assessmentDate) }}</text>
-            <text class="report-guide">�鞾鵭閫��撣? {{ report.guideName || '�芰䰻' }}</text>
+            <text class="report-guide">�鞾鵭閫��撣�: {{ report.guideName || '�芰䰻' }}</text>
           </view>
           <view class="report-scores">
             <view class="score-item">
@@ -83,8 +83,8 @@
       </view>
       <view class="empty-state" v-else>
         <text class="empty-icon">��</text>
-        <text class="empty-text">餈䀹瓷�劐�蝥扳��輯��鍦���𥁒�?/text>
-        <text class="empty-hint">銝讠漣�鞾鵭閫��撣���鞉�霂��隡𡁏遬蝷?/text>
+        <text class="empty-text">餈䀹瓷�劐�蝥扳��輯��鍦���𥁒��</text>
+        <text class="empty-hint">銝讠漣�鞾鵭閫��撣���鞉�霂��隡𡁏遬蝷�</text>
       </view>
     </view>
 
@@ -93,7 +93,7 @@
       <view class="modal-content" @click.stop>
         <view class="modal-header">
           <text class="modal-title">瘚贝��亙�霂行�</text>
-          <text class="modal-close" @click="showReportModal = false">�?/text>
+          <text class="modal-close" @click="showReportModal = false">��</text>
         </view>
         
         <view class="report-detail">
@@ -101,7 +101,7 @@
             <text class="detail-title">�箸𧋦靽⊥�</text>
             <view class="detail-row">
               <text class="detail-label">摮拙�憪枏�</text>
-              <text class="detail-value">{{ currentReport.childName || '�芸𦶢�? }}</text>
+              <text class="detail-value">{{ currentReport.childName || '�芸𦶢��' }}</text>
             </view>
             <view class="detail-row">
               <text class="detail-label">瘚贝��交�</text>
@@ -116,15 +116,15 @@
           <view class="detail-section">
             <text class="detail-title">DAN瘚贝�蝏𤘪�</text>
             <view class="detail-row">
-              <text class="detail-label">瘜冽��𥕦��?/text>
+              <text class="detail-label">瘜冽��𥕦���</text>
               <text class="detail-value">{{ currentReport.attentionScore }}</text>
             </view>
             <view class="detail-row">
-              <text class="detail-label">銝𤘪釣�𥕦��?/text>
+              <text class="detail-label">銝𤘪釣�𥕦���</text>
               <text class="detail-value">{{ currentReport.focusScore }}</text>
             </view>
             <view class="detail-row">
-              <text class="detail-label">霈啣��𥕦��?/text>
+              <text class="detail-label">霈啣��𥕦���</text>
               <text class="detail-value">{{ currentReport.memoryScore }}</text>
             </view>
             <view class="detail-row">

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

@@ -12,8 +12,8 @@
           :class="{ selected: selectedChildId === child.id }"
           v-for="child in children" :key="child.id"
           @click="selectedChildId = child.id">
-          <text class="child-name">{{ child.nickname || '未命��? }}</text>
-          <text class="child-check" v-if="selectedChildId === child.id">��?/text>
+          <text class="child-name">{{ child.nickname || '未命名' }}</text>
+          <text class="child-check" v-if="selectedChildId === child.id">✓</text>
         </view>
       </view>
     </view>
@@ -32,7 +32,7 @@
     </view>
 
     <button class="btn-submit" :disabled="!canSubmit" @click="submitUpload">
-      {{ uploading ? '上传��?..' : '提交报告' }}
+      {{ uploading ? '上传中...' : '提交报告' }}
     </button>
   </view>
 </template>
@@ -85,14 +85,14 @@ export default {
     async submitUpload() {
       if (!this.canSubmit) return
       this.uploading = true
-      uni.showLoading({ title: '上传��?..' })
+      uni.showLoading({ title: '上传中...' })
       try {
         const res = await uploadAssessmentReport(this.file, this.selectedChildId, this.notes)
         uni.hideLoading()
         if (res.code === 200) {
           uni.showModal({
             title: '上传成功',
-            content: '报告已提交,等待成长规划师确��?,
+            content: '报告已提交,等待成长规划师确认',
             showCancel: false,
             success: () => uni.navigateBack()
           })

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

@@ -2,15 +2,15 @@
   <view class="checkin-container">
     <!-- 顶部导航 -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">��?返回</text>
+      <text class="nav-back" @click="goBack">返回</text>
       <text class="nav-title">健康打卡</text>
       <view class="nav-placeholder"></view>
     </view>
 
     <!-- 能量奖励提示 -->
     <view class="energy-tip">
-      <text class="tip-icon">��?/text>
-      <text class="tip-text">每次打卡可获��?5 能量��?/text>
+      <text class="tip-icon">⚡</text>
+      <text class="tip-text">每次打卡可获得 5 能量值</text>
     </view>
 
     <!-- 打卡表单 -->
@@ -22,7 +22,7 @@
         <text class="form-label">打卡日期</text>
         <view class="date-display" @click="pickDate">
           <text>{{ checkinDate }}</text>
-          <text class="date-arrow">��?/text>
+          <text class="date-arrow">›</text>
         </view>
       </view>
 
@@ -61,7 +61,7 @@
 
       <!-- 备注 -->
       <view class="form-item">
-        <text class="form-label">备注(选填��?/text>
+        <text class="form-label">备注(选填)</text>
         <textarea
           class="note-input"
           v-model="note"
@@ -89,7 +89,7 @@
           </view>
           <view class="history-right">
             <text class="history-mood">{{ getMoodEmoji(item.mood) }}</text>
-            <text class="history-energy">+{{ item.earnedEnergy || 5 }}��?/text>
+            <text class="history-energy">+{{ item.earnedEnergy || 5 }}⚡</text>
           </view>
         </view>
         <view class="history-empty" v-if="checkinList.length === 0 && !loadingHistory">
@@ -148,20 +148,20 @@ export default {
         { label: '户外活动', value: '户外活动2小时' },
         { label: '视力保护', value: '视力保护' },
         { label: '情绪愉快', value: '情绪愉快' },
-        { label: '无零��?, value: '无零��? }
+        { label: '无零食', value: '无零食' }
       ],
       moodOptions: [
-        { label: '开��?, value: 'happy', emoji: '😊' },
+        { label: '开心', value: 'happy', emoji: '😊' },
         { label: '平静', value: 'normal', emoji: '😐' },
         { label: '低落', value: 'sad', emoji: '😔' },
         { label: '烦躁', value: 'angry', emoji: '😤' },
-        { label: '不��?, value: 'sick', emoji: '🤒' }
+        { label: '不适', value: 'sick', emoji: '🤒' }
       ]
     }
   },
   onLoad: function(options) {
     this.childId = options.childId ? parseInt(options.childId) : null
-    // 如果没有��?childId,尝试从 storage 读取
+    // 如果没有childId,尝试从 storage 读取
     if (!this.childId) {
       var savedChildId = uni.getStorageSync('currentChildId')
       if (savedChildId) this.childId = parseInt(savedChildId)
@@ -192,7 +192,7 @@ export default {
     },
     doCheckin: function() {
       if (this.selectedBehaviors.length === 0) {
-        uni.showToast({ title: '请至少选择一项健康行��?, icon: 'none' })
+        uni.showToast({ title: '请至少选择一项健康行为', icon: 'none' })
         return
       }
       if (!this.childId) {
@@ -200,7 +200,7 @@ export default {
         return
       }
       var self = this
-      uni.showLoading({ title: '提交��?..' })
+      uni.showLoading({ title: '提交中...' })
       healthRequest('/api/health/checkin/create', {
         childId: this.childId,
         checkinDate: this.checkinDate,
@@ -288,7 +288,7 @@ export default {
   padding-bottom: 60rpx;
 }
 
-/* ===== 导航��?===== */
+/* ===== 导航===== */
 .nav-bar {
   position: sticky;
   top: 0;

+ 24 - 24
cfc-frontend/pages/body-detail/dimension-detail.vue

@@ -2,7 +2,7 @@
   <view class="dd-container">
     <!-- Loading -->
     <view class="dd-loading" v-if="loading">
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
     <template v-else>
@@ -10,7 +10,7 @@
       <view class="dd-header">
         <view class="dd-score-ring">
           <text class="dd-score-value">{{ currentScore || '--' }}</text>
-          <text class="dd-score-label">�/text>
+          <text class="dd-score-label">分</text>
         </view>
         <text class="dd-dim-name">{{ dimLabel }}</text>
         <text class="dd-dim-level" :class="'level-' + (dimLevel || 'fair')">{{ levelText }}</text>
@@ -24,7 +24,7 @@
         </view>
         <view class="dd-empty" v-else>
           <text class="empty-text">暂无历�数�</text>
-          <text class="empty-sub">完�评估或上传报告��查看趋�/text>
+          <text class="empty-sub">完�评估或上传报告��查看趋势</text>
         </view>
       </view>
 
@@ -33,7 +33,7 @@
         <text class="dd-section-title">常模对比</text>
         <view class="dd-percentile-wrap">
           <text class="dd-percentile-value">{{ percentile }}%</text>
-          <text class="dd-percentile-label">超过�龄�性别 {{ percentile }}% 的人�/text>
+          <text class="dd-percentile-label">超过�龄�性别 {{ percentile }}% 的人群</text>
         </view>
       </view>
 
@@ -82,45 +82,45 @@ import { getDimensionHistory, getDimensionOverview, getProductsByDomain } from '
 var SUGGESTIONS = {
   growth: [
     '���日充足的蛋白质和钙摄入,牛奶�鸡蛋�豆制�是优质选择',
-    '�周至少3次户外活动,跳绳�篮�等纵��动有助于骨骼��,
-    '定期记录身高体�,关注生长曲线是�在正常范围�,
+    '�周至少3次户外活动,跳绳�篮�等纵��动有助于骨骼�育',
+    '定期记录身高体�,关注生长曲线是�在正常范围内',
     '��充足�眠,生长激素在夜间深�期分泌最旺盛'
   ],
   sleep: [
-    '建立固定的��程�:洗热水澡�读故事�调暗��,
-    '�室��安��黑暗�凉爽,温度控制�8-22°C',
-    '��1�时��使用电�设备,�光会抑制褪黑素分�,
+    '建立固定的��程�:洗热水澡�读故事�调暗�光',
+    '�室��安��黑暗�凉爽,温度控制在18-22°C',
+    '��1�时��使用电�设备,�光会抑制褪黑素分泌',
     '��规律的作�时间,周末与平日差异�超过1�时'
   ],
   vision: [
-    '�循"20-20-20"法则:�20分钟�0英尺�0�,
-    '�日��至少2�时户外活动,自然光有助于预防近�,
-    '��正确读写姿势:眼离书本一尺�胸离桌沿一�,
+    '�循"20-20-20"法则:�20分钟看20英尺外20秒',
+    '�日��至少2�时户外活动,自然光有助于预防近视',
+    '��正确读写姿势:眼离书本一尺�胸离桌沿一拳',
     '��年进行一次视力检查,建立视力�育档案'
   ],
   immunity: [
     '�衡饮食,确�蛋白质�维生素C�锌等�疫�养素摄入',
-    '适度�动增强体质,但��过度训练导致�疫力下�,
-    '��充足�眠,�眠�足会影��疫细胞活�,
-    '注�手部�生,但�过度消毒,适度接触微生物有助�疫系统��
+    '适度�动增强体质,但��过度训练导致�疫力下�',
+    '��充足�眠,�眠�足会影��疫细胞活性',
+    '注�手部�生,但�过度消毒,适度接触微生物有助�疫系统�育'
   ],
   nutrition: [
-    '�天摄入12�以上食�,�周25�以上,确��养多样�,
-    '�少加工食�和高糖饮料,增加全谷物�蔬��水果比�,
+    '�天摄入12�以上食�,�周25�以上,确��养多样性',
+    '�少加工食�和高糖饮料,增加全谷物�蔬��水果比例',
     '关注��钙�维生素D等易缺��养素的摄入',
     '培养自主进食能力,�造愉快的就�氛围'
   ],
   gut: [
     '增加膳食纤维摄入,全谷物�蔬��水果是优质��',
     '适�补充益生�食物:酸奶��酵食�等',
-    '��规律排便习惯,�时�应便�,
+    '��规律排便习惯,�时�应便�',
     '�少油炸�辛辣等刺激性食物,�轻肠胃负担'
   ],
   exercise: [
-    '�天至少60分钟中高强度�动,�分多次完�,
-    '�动类型多样化:有氧+力�+柔韧性训练结�,
+    '�天至少60分钟中高强度�动,�分多次完�',
+    '�动类型多样化:有氧+力�+柔韧性训练结�',
     '让�动�得有趣:�类游��游泳�骑自行车都是好选择',
-    '家长以身作则,全家一起�动效果更�
+    '家长以身作则,全家一起�动效果更好'
   ]
 }
 
@@ -141,8 +141,8 @@ export default {
   },
   computed: {
     levelText: function() {
-      var map = { excellent: '优秀', good: '良好', fair: '一�, poor: '较差' }
-      return map[this.dimLevel] || '一�
+      var map = { excellent: '优秀', good: '良好', fair: '一般', poor: '较差' }
+      return map[this.dimLevel] || '一般'
     }
   },
   onLoad: function(options) {
@@ -163,7 +163,7 @@ export default {
         growth: '生长�育',
         sleep: '�眠质�',
         vision: '视力�康',
-        immunity: '�疫�,
+        immunity: '�疫力',
         nutrition: '�养�衡',
         gut: '肠胃�康',
         exercise: '�动活力'

+ 56 - 56
cfc-frontend/pages/body-detail/dimension-questionnaire.vue

@@ -2,7 +2,7 @@
   <view class="qd-container">
     <!-- Loading -->
     <view class="qd-loading" v-if="loading">
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
     <template v-else>
@@ -10,7 +10,7 @@
       <view v-if="step === 1" class="qd-step">
         <view class="qd-header">
           <text class="qd-title">选择�康维度</text>
-          <text class="qd-desc">请选择一个维度进行评�/text>
+          <text class="qd-desc">请选择一个维度进行评估</text>
         </view>
         <view class="qd-dim-list">
           <view
@@ -22,11 +22,11 @@
           >
             <text class="qd-dim-icon">{{ dim.icon }}</text>
             <text class="qd-dim-label">{{ dim.label }}</text>
-            <text class="qd-dim-check" v-if="selectedDimension === dim.code">�/text>
+            <text class="qd-dim-check" v-if="selectedDimension === dim.code">✓</text>
           </view>
         </view>
         <view class="qd-footer">
-          <button class="qd-btn" :disabled="!selectedDimension" @click="startQuestions">开始答�/button>
+          <button class="qd-btn" :disabled="!selectedDimension" @click="startQuestions">开始答题</button>
         </view>
       </view>
 
@@ -51,15 +51,15 @@
               @click="currentAnswer = opt.value"
             >
               <text class="qd-opt-label">{{ opt.label }}</text>
-              <text class="qd-opt-check" v-if="currentAnswer === opt.value">�/text>
+              <text class="qd-opt-check" v-if="currentAnswer === opt.value">✓</text>
             </view>
           </view>
         </view>
 
         <view class="qd-footer">
-          <button class="qd-btn qd-btn-prev" @click="prevQuestion" v-if="currentQIndex > 0">上一�/button>
+          <button class="qd-btn qd-btn-prev" @click="prevQuestion" v-if="currentQIndex > 0">上一题</button>
           <button class="qd-btn" @click="nextQuestion" :disabled="!currentAnswer">
-            {{ currentQIndex < currentQuestions.length - 1 ? '下一� : '�交评估' }}
+            {{ currentQIndex < currentQuestions.length - 1 ? '下一题' : '�交评估' }}
           </button>
         </view>
       </view>
@@ -68,8 +68,8 @@
       <view v-if="step === 3" class="qd-step">
         <view class="qd-result" v-if="result">
           <text class="qd-result-icon">{{ resultIcon }}</text>
-          <text class="qd-result-title">评估完��/text>
-          <text class="qd-result-score">{{ currentDimLabel }}:{{ result.score }}�/text>
+          <text class="qd-result-title">评估完��</text>
+          <text class="qd-result-score">{{ currentDimLabel }}:{{ result.score }}分</text>
           <view class="qd-result-level" :class="'level-' + (result.level || 'fair')">
             {{ levelText(result.level) }}
           </view>
@@ -95,8 +95,8 @@ export default {
       dimensions: [
         { code: 'growth', label: '生长�育', icon: '📈' },
         { code: 'sleep', label: '�眠质�', icon: '🛌' },
-        { code: 'vision', label: '视力�康', icon: '�� },
-        { code: 'immunity', label: '�疫�, icon: '🛡� },
+        { code: 'vision', label: '视力�康', icon: '��' },
+        { code: 'immunity', label: '�疫力', icon: '🛡�' },
         { code: 'nutrition', label: '�养�衡', icon: '🥗' },
         { code: 'gut', label: '肠胃�康', icon: '🌿' },
         { code: 'exercise', label: '�动活力', icon: '💪' }
@@ -104,39 +104,39 @@ export default {
       selectedDimension: '',
       questions: {
         growth: [
-          { question: '孩�的身高体�在�龄人中属于�, options: [
+          { question: '孩�的身高体�在�龄人中属于?', options: [
             { label: '�高/�壮', value: 'tall' },
             { label: '正常范围', value: 'normal' },
             { label: '�矮/�瘦', value: 'short' },
-            { label: '�清�, value: 'unknown' }
+            { label: '�清楚', value: 'unknown' }
           ]},
-          { question: '过去�年身高增长情况�, options: [
+          { question: '过去�年身高增长情况?', options: [
             { label: '�续增长,速度正常', value: 'steady' },
             { label: '增长缓慢', value: 'slow' },
             { label: '没有明显�化', value: 'none' },
-            { label: '没留�, value: 'unknown' }
+            { label: '没留�', value: 'unknown' }
           ]}
         ],
         sleep: [
-          { question: '孩�平��天�眠时长�, options: [
+          { question: '孩�平��天�眠时长?', options: [
             { label: '�足6�时', value: 'lt6' },
             { label: '6-8�时', value: '6to8' },
             { label: '8-10�时', value: '8to10' },
             { label: '超过10�时', value: 'gt10' }
           ]},
-          { question: '孩��眠质�如何�, options: [
+          { question: '孩��眠质�如何?', options: [
             { label: '很好,倒头就�', value: 'good' },
             { label: '一般,�尔翻�覆去', value: 'fair' },
-            { label: '较差,频�夜�难入�, value: 'poor' }
+            { label: '较差,频�夜醒/难入�', value: 'poor' }
           ]},
-          { question: '孩�是�有规律的作�时间�, options: [
-            { label: '作�很规�, value: 'regular' },
+          { question: '孩�是�有规律的作�时间?', options: [
+            { label: '作�很规律', value: 'regular' },
             { label: '基本规律', value: 'mostly' },
             { label: '�太规律', value: 'irregular' }
           ]}
         ],
         vision: [
-          { question: '孩�目�是�佩戴眼镜�, options: [
+          { question: '孩�目�是�佩戴眼镜?', options: [
             { label: '�戴眼镜', value: 'no' },
             { label: '已戴眼镜', value: 'yes' }
           ]},
@@ -148,73 +148,73 @@ export default {
           ]}
         ],
         immunity: [
-          { question: '过去�年孩�生病次数�, options: [
-            { label: '0次,基本�生�, value: 'zero' },
+          { question: '过去�年孩�生病次数?', options: [
+            { label: '0次,基本�生病', value: 'zero' },
             { label: '1-2次,�尔感冒', value: 'few' },
             { label: '3-5次,�常生病', value: 'some' },
             { label: '6次以上,频�生病', value: 'many' }
           ]},
-          { question: '生病严�程度如何�, options: [
-            { label: '从未�院,��就�, value: 'mild' },
-            { label: '�尔需�输�雾化', value: 'moderate' },
-            { label: '曾�院治�, value: 'severe' }
+          { question: '生病严�程度如何?', options: [
+            { label: '从未�院,��就好', value: 'mild' },
+            { label: '�尔需�输液/雾化', value: 'moderate' },
+            { label: '曾�院治疗', value: 'severe' }
           ]},
-          { question: '孩�是�有过���, options: [
+          { question: '孩�是�有过��?', options: [
             { label: '没有过�', value: 'none' },
             { label: '有轻微过�(花粉/尘螨等)', value: 'mild' },
-            { label: '有食��物过�', value: 'severe' }
+            { label: '有食物/�物过�', value: 'severe' }
           ]}
         ],
         nutrition: [
-          { question: '孩�挑食/�食程度�, options: [
-            { label: '�挑食,什么都�, value: 'none' },
+          { question: '孩�挑食/�食程度?', options: [
+            { label: '�挑食,什么都�', value: 'none' },
             { label: '挑几样特定的食物', value: 'mild' },
-            { label: '严�挑食,�类很�, value: 'severe' }
+            { label: '严�挑食,�类很少', value: 'severe' }
           ]},
-          { question: '�周大概�多少���食��, options: [
+          { question: '�周大概�多少���食�?', options: [
             { label: '超过20�,饮食多样', value: 'diverse' },
             { label: '10-20�,比较丰富', value: 'moderate' },
             { label: '少于10�,比较�一', value: 'limited' }
           ]},
-          { question: '孩�是�在使用�养补充剂�, options: [
+          { question: '孩�是�在使用�养补充剂?', options: [
             { label: '按医嘱使用多�补充剂', value: 'multiple' },
-            { label: '使用维生素D/钙等基础补充�, value: 'basic' },
+            { label: '使用维生素D/钙等基础补充剂', value: 'basic' },
             { label: '�使用任何补充剂', value: 'none' }
           ]}
         ],
         gut: [
-          { question: '孩�最近消化舒适度如何�, options: [
-            { label: '很好,消化顺�, value: 'good' },
-            { label: '一般,�尔肚��舒�, value: 'fair' },
-            { label: '较差,�常腹�腹胀/腹泻', value: 'poor' }
+          { question: '孩�最近消化舒适度如何?', options: [
+            { label: '很好,消化顺畅', value: 'good' },
+            { label: '一般,�尔肚��舒�', value: 'fair' },
+            { label: '较差,�常腹痛/腹胀/腹泻', value: 'poor' }
           ]},
-          { question: '孩�排便频率�, options: [
+          { question: '孩�排便频率?', options: [
             { label: '�天1-2次,规律', value: 'regular' },
             { label: '隔天一次,基本规律', value: 'mostly' },
-            { label: '�规律,�常便秘或腹�, value: 'irregular' }
+            { label: '�规律,�常便秘或腹泻', value: 'irregular' }
           ]},
           { question: '孩�是�有肠胃相关诊断?', options: [
             { label: '没有肠胃问题', value: 'none' },
-            { label: '有��性消化��, value: 'mild' },
-            { label: '有确诊肠胃问�, value: 'diagnosed' }
+            { label: '有��性消化�良', value: 'mild' },
+            { label: '有确诊肠胃问题', value: 'diagnosed' }
           ]}
         ],
         exercise: [
-          { question: '孩��周�动频率�, options: [
+          { question: '孩��周�动频率?', options: [
             { label: '�天�动', value: 'daily' },
-            { label: '�周3-5�, value: 'often' },
-            { label: '�周1-2�, value: 'sometimes' },
-            { label: '基本���, value: 'rarely' }
+            { label: '�周3-5次', value: 'often' },
+            { label: '�周1-2次', value: 'sometimes' },
+            { label: '基本��动', value: 'rarely' }
           ]},
-          { question: '孩��次�动时长�, options: [
+          { question: '孩��次�动时长?', options: [
             { label: '超过1�时', value: 'gt1h' },
-            { label: '30分钟��时', value: '30to1h' },
+            { label: '30分钟到1�时', value: '30to1h' },
             { label: '少于30分钟', value: 'lt30m' }
           ]},
           { question: '孩�喜欢的�动类型?', options: [
             { label: '�类/田径等竞技�动', value: 'competitive' },
-            { label: '游泳/骑行等有氧��, value: 'aerobic' },
-            { label: '跳绳/体�等�活性��, value: 'flexibility' },
+            { label: '游泳/骑行等有氧�动', value: 'aerobic' },
+            { label: '跳绳/体�等�活性�动', value: 'flexibility' },
             { label: '�太喜欢�动', value: 'sedentary' }
           ]}
         ]
@@ -237,7 +237,7 @@ export default {
       return this.currentQuestions[this.currentQIndex] || {}
     },
     resultIcon: function() {
-      if (!this.result) return '�
+      if (!this.result) return '✅'
       var level = this.result.level
       if (level === 'excellent') return '🌟'
       if (level === 'good') return '�'
@@ -302,19 +302,19 @@ export default {
           _this.result = {
             score: 70,
             level: 'good',
-            suggestion: '�根�评估结果关注相关�康维度�
+            suggestion: '�根�评估结果关注相关�康维度。'
           }
           _this.step = 3
         }
       }).catch(function() {
         _this.loading = false
-        _this.result = { score: 70, level: 'good', suggestion: '�交�功,�根�评估结果关注相关�康维度� }
+        _this.result = { score: 70, level: 'good', suggestion: '�交�功,�根�评估结果关注相关�康维度。' }
         _this.step = 3
       })
     },
     levelText: function(level) {
-      var map = { excellent: '优秀', good: '良好', fair: '一�, poor: '较差' }
-      return map[level] || '一�
+      var map = { excellent: '优秀', good: '良好', fair: '一般', poor: '较差' }
+      return map[level] || '一般'
     },
     goToDimensions: function() {
       uni.navigateTo({ url: '/pages/body-detail/health-dimensions?childId=' + this.activeChildId })

+ 9 - 9
cfc-frontend/pages/body-detail/health-dimensions.vue

@@ -2,7 +2,7 @@
   <view class="hd-container">
     <view class="hd-header">
       <text class="hd-title">健康维度全景</text>
-      <text class="hd-subtitle" v-if="memberName">{{ memberName }}的健康档��?/text>
+      <text class="hd-subtitle" v-if="memberName">{{ memberName }}的健康档案</text>
     </view>
 
     <view class="hd-health-index" v-if="healthData && healthData.healthIndex">
@@ -46,7 +46,7 @@
       >
         <view class="dim-header">
           <text class="dim-label">{{ dim.label }}</text>
-          <text class="dim-score" :class="'score-' + dim.level">{{ dim.score || '--' }}��?/text>
+          <text class="dim-score" :class="'score-' + dim.level">{{ dim.score || '--' }}分</text>
         </view>
         <view class="dim-bar-wrap">
           <view class="dim-bar-bg">
@@ -62,18 +62,18 @@
         </view>
         <view class="dim-footer">
           <text class="dim-level-tag" :class="'tag-' + dim.level">{{ getLevelText(dim.level) }}</text>
-          <text class="dim-source" v-if="dim.trend">{{ dim.trend === 'up' ? '��?上升' : dim.trend === 'down' ? '��?下降' : '��?稳定' }}</text>
+          <text class="dim-source" v-if="dim.trend">{{ dim.trend === 'up' ? '↑ 上升' : dim.trend === 'down' ? '↓ 下降' : '→ 稳定' }}</text>
         </view>
       </view>
     </view>
 
     <view class="hd-empty" v-if="!healthData && !loading">
       <text class="empty-tip">暂无维度数据</text>
-      <text class="empty-sub">上传健康报告或填写问卷后可查��?/text>
+      <text class="empty-sub">上传健康报告或填写问卷后可查看</text>
     </view>
 
     <view class="loading-wrap" v-if="loading">
-      <text class="loading-text">加载��?..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
     <view class="fab-upload" @click="showUploadModal">
@@ -106,7 +106,7 @@
               class="form-input"
               type="number"
               v-model="uploadForm.score"
-              placeholder="请输入评��?
+              placeholder="请输入评分"
               min="0"
               max="100"
             />
@@ -156,7 +156,7 @@ export default {
         { code: 'growth', label: '生长发育' },
         { code: 'sleep', label: '睡眠质量' },
         { code: 'vision', label: '视力健康' },
-        { code: 'immunity', label: '免疫��? },
+        { code: 'immunity', label: '免疫力' },
         { code: 'nutrition', label: '营养均衡' },
         { code: 'gut', label: '肠胃健康' },
         { code: 'exercise', label: '运动活力' }
@@ -220,7 +220,7 @@ export default {
       var map = {
         'excellent': '优秀',
         'good': '良好',
-        'fair': '一��?,
+        'fair': '一般',
         'poor': '较差',
         'none': '暂无数据'
       }
@@ -257,7 +257,7 @@ export default {
         return
       }
       if (!this.uploadForm.score || this.uploadForm.score < 0 || this.uploadForm.score > 100) {
-        uni.showToast({ title: '评分需��?-100之间', icon: 'none' })
+        uni.showToast({ title: '评分需在0-100之间', icon: 'none' })
         return
       }
       if (!this.uploadForm.dataSource) {

+ 28 - 28
cfc-frontend/pages/body-detail/health-report.vue

@@ -2,7 +2,7 @@
   <view class="report-container">
     <!-- 顶部导航 -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">��?返回</text>
+      <text class="nav-back" @click="goBack">返回</text>
       <text class="nav-title">健康报告详情</text>
       <view class="nav-placeholder"></view>
     </view>
@@ -14,14 +14,14 @@
         <view class="score-item">
           <view class="score-circle-lg">
             <text class="score-num">{{ report.overallScore || '--' }}</text>
-            <text class="score-unit">��?/text>
+            <text class="score-unit">分</text>
           </view>
           <text class="score-label">综合评分</text>
         </view>
         <view class="score-item" v-if="report.gutHealthScore">
           <view class="score-circle-lg score-circle-green">
             <text class="score-num">{{ report.gutHealthScore }}</text>
-            <text class="score-unit">��?/text>
+            <text class="score-unit">分</text>
           </view>
           <text class="score-label">肠道健康</text>
         </view>
@@ -33,7 +33,7 @@
       <text class="report-date">报告日期:{{ formatDate(report.reportDate) }}</text>
     </view>
 
-    <!-- ===== 评分可视化面��?(仅菌群报��? ===== -->
+    <!-- ===== 评分可视化面板 (仅菌群报告) ===== -->
     <view class="score-dashboard" v-if="report && report.reportType === 'gut_flora'">
       <view class="main-scores">
         <view class="main-score-item" v-for="item in mainScores" :key="item.key">
@@ -42,7 +42,7 @@
               <circle cx="60" cy="60" r="50" fill="none" stroke="#EEEEEE" stroke-width="8"/>
               <circle cx="60" cy="60" r="50" fill="none" v-bind:stroke="item.color" stroke-width="8" v-bind:stroke-dasharray="item.circumference" v-bind:stroke-dashoffset="item.offset" stroke-linecap="round" transform="rotate(-90 60 60)"/>
               <text x="60" y="52" text-anchor="middle" font-size="32" font-weight="bold" fill="#333">{{ item.score }}</text>
-              <text x="60" y="72" text-anchor="middle" font-size="14" fill="#999">��?/text>
+              <text x="60" y="72" text-anchor="middle" font-size="14" fill="#999">分</text>
             </svg>
           </view>
           <text class="main-score-label">{{ item.label }}</text>
@@ -62,14 +62,14 @@
     <view class="section">
       <view class="section-title">
         <text>指标明细</text>
-        <text class="section-sub">��?{{ indicators.length }} ��?/text>
+        <text class="section-sub">共 {{ indicators.length }} 项</text>
       </view>
 
-      <!-- 按分类分��?-->
+      <!-- 按分类分-->
       <view class="category-group" v-for="group in groupedIndicators" :key="group.name">
         <view class="category-header">
           <text class="category-name">{{ group.name }}</text>
-          <text class="category-count">{{ group.items.length }}��?/text>
+          <text class="category-count">{{ group.items.length }}项</text>
         </view>
         <view class="indicator-card" v-for="ind in group.items" :key="ind._idx">
           <view class="ind-header">
@@ -97,7 +97,7 @@
     <view class="section" v-if="deficiencyRecords && deficiencyRecords.length > 0">
       <view class="section-title">
         <text>🔬 营养缺乏分析</text>
-        <text class="section-sub">{{ deficiencyRecords.length }}��?/text>
+        <text class="section-sub">{{ deficiencyRecords.length }}项</text>
       </view>
       <view class="deficiency-list">
         <view class="deficiency-card" v-for="dr in deficiencyRecords" :key="dr.nutrient">
@@ -114,11 +114,11 @@
             <text class="severity-val">{{ dr.severity }}</text>
           </view>
           <view class="deficiency-meta" v-if="dr.indicatorName">
-            <text class="meta-label">关联指标��?/text>
+            <text class="meta-label">关联指标:</text>
             <text class="meta-value">{{ dr.indicatorName }} ({{ dr.indicatorValue }})</text>
           </view>
           <view class="deficiency-foods" v-if="dr.foodSuggestions">
-            <text class="foods-label">推荐食物��?/text>
+            <text class="foods-label">推荐食物:</text>
             <text class="foods-value">{{ dr.foodSuggestions }}</text>
           </view>
         </view>
@@ -129,7 +129,7 @@
     <view class="section" v-if="foods && foods.length > 0">
       <view class="section-title">
         <text>🥗 食材推荐</text>
-        <text class="section-sub">��?{{ foods.length }} ��?/text>
+        <text class="section-sub">共 {{ foods.length }} 项</text>
       </view>
       <view class="food-list">
         <view class="food-card" v-for="food in foods" :key="food.id">
@@ -148,7 +148,7 @@
               <text class="n-value">{{ food.energyKj }} kJ</text>
             </view>
             <view class="nutrition-item" v-if="food.protein">
-              <text class="n-label">蛋白��?/text>
+              <text class="n-label">蛋白质</text>
               <text class="n-value">{{ food.protein }}g</text>
             </view>
             <view class="nutrition-item" v-if="food.fat">
@@ -164,10 +164,10 @@
       </view>
     </view>
 
-    <!-- ===== 五维雷达��?(菌群报告) ===== -->
+    <!-- ===== 五维雷达(菌群报告) ===== -->
     <view class="section" v-if="report && report.reportType === 'gut_flora' && radarDimensions.length > 0">
       <view class="section-title">
-        <text>五维雷达��?/text>
+        <text>五维雷达图</text>
       </view>
       <view class="radar-wrap">
         <canvas canvas-id="radarCanvas" id="radarCanvas" class="radar-canvas" @touchstart.prevent></canvas>
@@ -230,9 +230,9 @@ export default {
   computed: {
     reportTypeLabel: function() {
       if (!this.report) return ''
-      return this.report.reportType === 'gut_flora' ? '肠道检测报��? : '体检报告'
+      return this.report.reportType === 'gut_flora' ? '肠道检测报告' : '体检报告'
     },
-    // 预计算分组,每个指标附加 _cls (CSS��? ��?_label (显示标签)
+    // 预计算分组,每个指标附加 _cls (CSS类) 和 _label (显示标签)
     groupedIndicators: function() {
       var result = []
       var groupMap = {}
@@ -251,7 +251,7 @@ export default {
         } else if (s.indexOf('偏低') !== -1 || s.indexOf('过低') !== -1 || s.indexOf('注意') !== -1 || s.indexOf('warning') !== -1) {
           cls = 'status-warn'
           label = '偏低'
-        } else if (s.indexOf('正常') !== -1 || s.indexOf('normal') !== -1 || s.indexOf('低风��?) !== -1) {
+        } else if (s.indexOf('正常') !== -1 || s.indexOf('normal') !== -1 || s.indexOf('低风险') !== -1) {
           cls = 'status-normal'
           label = '正常'
         } else if (status) {
@@ -302,9 +302,9 @@ export default {
       var items = []
       var pairs = [
         {key:'balance', label:'菌群平衡', score: r.balanceScore},
-        {key:'diversity', label:'菌群多样��?, score: r.diversityScore},
-        {key:'beneficial', label:'有益��?, score: r.beneficialScore},
-        {key:'harmful', label:'有害��?, score: r.harmfulScore},
+        {key:'diversity', label:'菌群多样性', score: r.diversityScore},
+        {key:'beneficial', label:'有益菌', score: r.beneficialScore},
+        {key:'harmful', label:'有害菌', score: r.harmfulScore},
         {key:'coreGenus', label:'核心菌属', score: r.coreGenusScore}
       ]
       for (var i = 0; i < pairs.length; i++) {
@@ -336,7 +336,7 @@ export default {
     var reportId = options.reportId
     this.childId = childId ? parseInt(childId) : null
     this.reportId = reportId ? parseInt(reportId) : null
-    // 如果没有��?childId,尝试从 storage 读取(可能是家长自己的)
+    // 如果没有childId,尝试从 storage 读取(可能是家长自己的)
     if (!this.childId) {
       var savedChildId = uni.getStorageSync('currentChildId')
       if (savedChildId) this.childId = parseInt(savedChildId)
@@ -351,7 +351,7 @@ export default {
   methods: {
     loadData: function() {
       var self = this
-      uni.showLoading({ title: '加载��?..' })
+      uni.showLoading({ title: '加载中...' })
       // Load report + indicators in parallel
       var promises = []
       if (this.reportId) {
@@ -407,7 +407,7 @@ export default {
     goNutritionChat: function() {
       if (!this.reportId) return
       uni.navigateTo({
-        url: '/pages/ai/chat?mode=nutrition&reportId=' + this.reportId + '&firstMessage=' + encodeURIComponent('请根据这份菌群检测报告,分析我孩子的营养状况并提出建��?)
+        url: '/pages/ai/chat?mode=nutrition&reportId=' + this.reportId + '&firstMessage=' + encodeURIComponent('请根据这份菌群检测报告,分析我孩子的营养状况并提出建议')
       })
     },
     loadDeficiencyRecords: function() {
@@ -428,8 +428,8 @@ export default {
     getDeficiencyTypeLabel: function(type) {
       if (type === 'deficiency') return '缺乏'
       if (type === 'excess') return '偏高'
-      if (type === 'borderline') return '边界��?
-      return '未分��?
+      if (type === 'borderline') return '边界值'
+      return '未分类'
     },
     getSeverityColor: function(severity) {
       if (severity >= 0.7) return '#EF4444'
@@ -532,7 +532,7 @@ export default {
   background: #f5f7fa;
 }
 
-/* ===== 导航��?===== */
+/* ===== 导航===== */
 .nav-bar {
   position: sticky;
   top: 0;
@@ -921,7 +921,7 @@ export default {
   color: #2E7D32;
 }
 
-/* ===== 雷达��?===== */
+/* ===== 雷达===== */
 .radar-wrap {
   display: flex;
   justify-content: center;

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

@@ -5,19 +5,19 @@
       <view class="nav-back" @click="goBack">
         <text class="nav-back-icon">&#x2190;</text>
       </view>
-      <text class="nav-title">�· �员详情</text>
+      <text class="nav-title">身 · �员详情</text>
     </view>
 
-    <!-- 五维能��-->
+    <!-- 五维能�� -->
     <FamilyEnergyBar
       dimensionCode="body"
       :sandboxData="sandboxData"
       :dualDimension="dualDimension" />
 
-    <!-- �员信��-->
+    <!-- �员信�� -->
     <view class="member-card" v-if="memberInfo">
       <view class="member-avatar">
-        <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || 'å­? }}</text>
+        <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || 'å­©' }}</text>
       </view>
       <view class="member-info">
         <text class="member-name">{{ memberInfo.name || 'å­©å­�' }}</text>
@@ -25,7 +25,7 @@
       </view>
       <view class="member-score" v-if="dualDimension">
         <text class="score-value">{{ dualDimension.energy || 0 }}</text>
-        <text class="score-label">能��/text>
+        <text class="score-label">能�值</text>
       </view>
     </view>
 

+ 12 - 12
cfc-frontend/pages/body/checkin.vue

@@ -2,15 +2,15 @@
   <view class="checkin-container">
     <!-- 顶部导航 -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">��?返回</text>
+      <text class="nav-back" @click="goBack">返回</text>
       <text class="nav-title">健康打卡</text>
       <view class="nav-placeholder"></view>
     </view>
 
     <!-- 能量奖励提示 -->
     <view class="energy-tip">
-      <text class="tip-icon">��?/text>
-      <text class="tip-text">每次打卡可获��?5 能量��?/text>
+      <text class="tip-icon">⚡</text>
+      <text class="tip-text">每次打卡可获得 5 能量值</text>
     </view>
 
     <!-- 打卡表单 -->
@@ -22,7 +22,7 @@
         <text class="form-label">打卡日期</text>
         <view class="date-display" @click="pickDate">
           <text>{{ checkinDate }}</text>
-          <text class="date-arrow">��?/text>
+          <text class="date-arrow">›</text>
         </view>
       </view>
 
@@ -61,7 +61,7 @@
 
       <!-- 备注 -->
       <view class="form-item">
-        <text class="form-label">备注(选填��?/text>
+        <text class="form-label">备注(选填)</text>
         <textarea
           class="note-input"
           v-model="note"
@@ -89,7 +89,7 @@
           </view>
           <view class="history-right">
             <text class="history-mood">{{ getMoodEmoji(item.mood) }}</text>
-            <text class="history-energy">+{{ item.earnedEnergy || 5 }}��?/text>
+            <text class="history-energy">+{{ item.earnedEnergy || 5 }}⚡</text>
           </view>
         </view>
         <view class="history-empty" v-if="checkinList.length === 0 && !loadingHistory">
@@ -148,14 +148,14 @@ export default {
         { label: '户外活动', value: '户外活动2小时' },
         { label: '视力保护', value: '视力保护' },
         { label: '情绪愉快', value: '情绪愉快' },
-        { label: '无零��?, value: '无零��? }
+        { label: '无零食', value: '无零食' }
       ],
       moodOptions: [
-        { label: '开��?, value: 'happy', emoji: '😊' },
+        { label: '开心', value: 'happy', emoji: '😊' },
         { label: '平静', value: 'normal', emoji: '😐' },
         { label: '低落', value: 'sad', emoji: '😔' },
         { label: '烦躁', value: 'angry', emoji: '😤' },
-        { label: '不��?, value: 'sick', emoji: '🤒' }
+        { label: '不适', value: 'sick', emoji: '🤒' }
       ]
     }
   },
@@ -187,7 +187,7 @@ export default {
     },
     doCheckin: function() {
       if (this.selectedBehaviors.length === 0) {
-        uni.showToast({ title: '请至少选择一项健康行��?, icon: 'none' })
+        uni.showToast({ title: '请至少选择一项健康行为', icon: 'none' })
         return
       }
       if (!this.childId) {
@@ -195,7 +195,7 @@ export default {
         return
       }
       var self = this
-      uni.showLoading({ title: '提交��?..' })
+      uni.showLoading({ title: '提交中...' })
       healthRequest('/api/health/checkin/create', {
         childId: this.childId,
         checkinDate: this.checkinDate,
@@ -283,7 +283,7 @@ export default {
   padding-bottom: 60rpx;
 }
 
-/* ===== 导航��?===== */
+/* ===== 导航===== */
 .nav-bar {
   position: sticky;
   top: 0;

+ 24 - 24
cfc-frontend/pages/body/dimension-detail.vue

@@ -2,7 +2,7 @@
   <view class="dd-container">
     <!-- Loading -->
     <view class="dd-loading" v-if="loading">
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
     <template v-else>
@@ -10,7 +10,7 @@
       <view class="dd-header">
         <view class="dd-score-ring">
           <text class="dd-score-value">{{ currentScore || '--' }}</text>
-          <text class="dd-score-label">�/text>
+          <text class="dd-score-label">分</text>
         </view>
         <text class="dd-dim-name">{{ dimLabel }}</text>
         <text class="dd-dim-level" :class="'level-' + (dimLevel || 'fair')">{{ levelText }}</text>
@@ -24,7 +24,7 @@
         </view>
         <view class="dd-empty" v-else>
           <text class="empty-text">暂无历�数�</text>
-          <text class="empty-sub">完�评估或上传报告��查看趋�/text>
+          <text class="empty-sub">完�评估或上传报告��查看趋势</text>
         </view>
       </view>
 
@@ -33,7 +33,7 @@
         <text class="dd-section-title">常模对比</text>
         <view class="dd-percentile-wrap">
           <text class="dd-percentile-value">{{ percentile }}%</text>
-          <text class="dd-percentile-label">超过�龄�性别 {{ percentile }}% 的人�/text>
+          <text class="dd-percentile-label">超过�龄�性别 {{ percentile }}% 的人群</text>
         </view>
       </view>
 
@@ -82,45 +82,45 @@ import { getDimensionHistory, getDimensionOverview, getProductsByDomain } from '
 var SUGGESTIONS = {
   growth: [
     '���日充足的蛋白质和钙摄入,牛奶�鸡蛋�豆制�是优质选择',
-    '�周至少3次户外活动,跳绳�篮�等纵��动有助于骨骼��,
-    '定期记录身高体�,关注生长曲线是�在正常范围�,
+    '�周至少3次户外活动,跳绳�篮�等纵��动有助于骨骼�育',
+    '定期记录身高体�,关注生长曲线是�在正常范围内',
     '��充足�眠,生长激素在夜间深�期分泌最旺盛'
   ],
   sleep: [
-    '建立固定的��程�:洗热水澡�读故事�调暗��,
-    '�室��安��黑暗�凉爽,温度控制�8-22°C',
-    '��1�时��使用电�设备,�光会抑制褪黑素分�,
+    '建立固定的��程�:洗热水澡�读故事�调暗�光',
+    '�室��安��黑暗�凉爽,温度控制在18-22°C',
+    '��1�时��使用电�设备,�光会抑制褪黑素分泌',
     '��规律的作�时间,周末与平日差异�超过1�时'
   ],
   vision: [
-    '�循"20-20-20"法则:�20分钟�0英尺�0�,
-    '�日��至少2�时户外活动,自然光有助于预防近�,
-    '��正确读写姿势:眼离书本一尺�胸离桌沿一�,
+    '�循"20-20-20"法则:�20分钟看20英尺外20秒',
+    '�日��至少2�时户外活动,自然光有助于预防近视',
+    '��正确读写姿势:眼离书本一尺�胸离桌沿一拳',
     '��年进行一次视力检查,建立视力�育档案'
   ],
   immunity: [
     '�衡饮食,确�蛋白质�维生素C�锌等�疫�养素摄入',
-    '适度�动增强体质,但��过度训练导致�疫力下�,
-    '��充足�眠,�眠�足会影��疫细胞活�,
-    '注�手部�生,但�过度消毒,适度接触微生物有助�疫系统��
+    '适度�动增强体质,但��过度训练导致�疫力下�',
+    '��充足�眠,�眠�足会影��疫细胞活性',
+    '注�手部�生,但�过度消毒,适度接触微生物有助�疫系统�育'
   ],
   nutrition: [
-    '�天摄入12�以上食�,�周25�以上,确��养多样�,
-    '�少加工食�和高糖饮料,增加全谷物�蔬��水果比�,
+    '�天摄入12�以上食�,�周25�以上,确��养多样性',
+    '�少加工食�和高糖饮料,增加全谷物�蔬��水果比例',
     '关注��钙�维生素D等易缺��养素的摄入',
     '培养自主进食能力,�造愉快的就�氛围'
   ],
   gut: [
     '增加膳食纤维摄入,全谷物�蔬��水果是优质��',
     '适�补充益生�食物:酸奶��酵食�等',
-    '��规律排便习惯,�时�应便�,
+    '��规律排便习惯,�时�应便�',
     '�少油炸�辛辣等刺激性食物,�轻肠胃负担'
   ],
   exercise: [
-    '�天至少60分钟中高强度�动,�分多次完�,
-    '�动类型多样化:有氧+力�+柔韧性训练结�,
+    '�天至少60分钟中高强度�动,�分多次完�',
+    '�动类型多样化:有氧+力�+柔韧性训练结�',
     '让�动�得有趣:�类游��游泳�骑自行车都是好选择',
-    '家长以身作则,全家一起�动效果更�
+    '家长以身作则,全家一起�动效果更好'
   ]
 }
 
@@ -141,8 +141,8 @@ export default {
   },
   computed: {
     levelText: function() {
-      var map = { excellent: '优秀', good: '良好', fair: '一�, poor: '较差' }
-      return map[this.dimLevel] || '一�
+      var map = { excellent: '优秀', good: '良好', fair: '一般', poor: '较差' }
+      return map[this.dimLevel] || '一般'
     }
   },
   onLoad: function(options) {
@@ -163,7 +163,7 @@ export default {
         growth: '生长�育',
         sleep: '�眠质�',
         vision: '视力�康',
-        immunity: '�疫�,
+        immunity: '�疫力',
         nutrition: '�养�衡',
         gut: '肠胃�康',
         exercise: '�动活力'

+ 56 - 56
cfc-frontend/pages/body/dimension-questionnaire.vue

@@ -2,7 +2,7 @@
   <view class="qd-container">
     <!-- Loading -->
     <view class="qd-loading" v-if="loading">
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
     <template v-else>
@@ -10,7 +10,7 @@
       <view v-if="step === 1" class="qd-step">
         <view class="qd-header">
           <text class="qd-title">选择�康维度</text>
-          <text class="qd-desc">请选择一个维度进行评�/text>
+          <text class="qd-desc">请选择一个维度进行评估</text>
         </view>
         <view class="qd-dim-list">
           <view
@@ -22,11 +22,11 @@
           >
             <text class="qd-dim-icon">{{ dim.icon }}</text>
             <text class="qd-dim-label">{{ dim.label }}</text>
-            <text class="qd-dim-check" v-if="selectedDimension === dim.code">�/text>
+            <text class="qd-dim-check" v-if="selectedDimension === dim.code">✓</text>
           </view>
         </view>
         <view class="qd-footer">
-          <button class="qd-btn" :disabled="!selectedDimension" @click="startQuestions">开始答�/button>
+          <button class="qd-btn" :disabled="!selectedDimension" @click="startQuestions">开始答题</button>
         </view>
       </view>
 
@@ -51,15 +51,15 @@
               @click="currentAnswer = opt.value"
             >
               <text class="qd-opt-label">{{ opt.label }}</text>
-              <text class="qd-opt-check" v-if="currentAnswer === opt.value">�/text>
+              <text class="qd-opt-check" v-if="currentAnswer === opt.value">✓</text>
             </view>
           </view>
         </view>
 
         <view class="qd-footer">
-          <button class="qd-btn qd-btn-prev" @click="prevQuestion" v-if="currentQIndex > 0">上一�/button>
+          <button class="qd-btn qd-btn-prev" @click="prevQuestion" v-if="currentQIndex > 0">上一题</button>
           <button class="qd-btn" @click="nextQuestion" :disabled="!currentAnswer">
-            {{ currentQIndex < currentQuestions.length - 1 ? '下一� : '�交评估' }}
+            {{ currentQIndex < currentQuestions.length - 1 ? '下一题' : '�交评估' }}
           </button>
         </view>
       </view>
@@ -68,8 +68,8 @@
       <view v-if="step === 3" class="qd-step">
         <view class="qd-result" v-if="result">
           <text class="qd-result-icon">{{ resultIcon }}</text>
-          <text class="qd-result-title">评估完��/text>
-          <text class="qd-result-score">{{ currentDimLabel }}:{{ result.score }}�/text>
+          <text class="qd-result-title">评估完��</text>
+          <text class="qd-result-score">{{ currentDimLabel }}:{{ result.score }}分</text>
           <view class="qd-result-level" :class="'level-' + (result.level || 'fair')">
             {{ levelText(result.level) }}
           </view>
@@ -95,8 +95,8 @@ export default {
       dimensions: [
         { code: 'growth', label: '生长�育', icon: '📈' },
         { code: 'sleep', label: '�眠质�', icon: '🛌' },
-        { code: 'vision', label: '视力�康', icon: '�� },
-        { code: 'immunity', label: '�疫�, icon: '🛡� },
+        { code: 'vision', label: '视力�康', icon: '��' },
+        { code: 'immunity', label: '�疫力', icon: '🛡�' },
         { code: 'nutrition', label: '�养�衡', icon: '🥗' },
         { code: 'gut', label: '肠胃�康', icon: '🌿' },
         { code: 'exercise', label: '�动活力', icon: '💪' }
@@ -104,39 +104,39 @@ export default {
       selectedDimension: '',
       questions: {
         growth: [
-          { question: '孩�的身高体�在�龄人中属于�, options: [
+          { question: '孩�的身高体�在�龄人中属于?', options: [
             { label: '�高/�壮', value: 'tall' },
             { label: '正常范围', value: 'normal' },
             { label: '�矮/�瘦', value: 'short' },
-            { label: '�清�, value: 'unknown' }
+            { label: '�清楚', value: 'unknown' }
           ]},
-          { question: '过去�年身高增长情况�, options: [
+          { question: '过去�年身高增长情况?', options: [
             { label: '�续增长,速度正常', value: 'steady' },
             { label: '增长缓慢', value: 'slow' },
             { label: '没有明显�化', value: 'none' },
-            { label: '没留�, value: 'unknown' }
+            { label: '没留�', value: 'unknown' }
           ]}
         ],
         sleep: [
-          { question: '孩�平��天�眠时长�, options: [
+          { question: '孩�平��天�眠时长?', options: [
             { label: '�足6�时', value: 'lt6' },
             { label: '6-8�时', value: '6to8' },
             { label: '8-10�时', value: '8to10' },
             { label: '超过10�时', value: 'gt10' }
           ]},
-          { question: '孩��眠质�如何�, options: [
+          { question: '孩��眠质�如何?', options: [
             { label: '很好,倒头就�', value: 'good' },
             { label: '一般,�尔翻�覆去', value: 'fair' },
-            { label: '较差,频�夜�难入�, value: 'poor' }
+            { label: '较差,频�夜醒/难入�', value: 'poor' }
           ]},
-          { question: '孩�是�有规律的作�时间�, options: [
-            { label: '作�很规�, value: 'regular' },
+          { question: '孩�是�有规律的作�时间?', options: [
+            { label: '作�很规律', value: 'regular' },
             { label: '基本规律', value: 'mostly' },
             { label: '�太规律', value: 'irregular' }
           ]}
         ],
         vision: [
-          { question: '孩�目�是�佩戴眼镜�, options: [
+          { question: '孩�目�是�佩戴眼镜?', options: [
             { label: '�戴眼镜', value: 'no' },
             { label: '已戴眼镜', value: 'yes' }
           ]},
@@ -148,73 +148,73 @@ export default {
           ]}
         ],
         immunity: [
-          { question: '过去�年孩�生病次数�, options: [
-            { label: '0次,基本�生�, value: 'zero' },
+          { question: '过去�年孩�生病次数?', options: [
+            { label: '0次,基本�生病', value: 'zero' },
             { label: '1-2次,�尔感冒', value: 'few' },
             { label: '3-5次,�常生病', value: 'some' },
             { label: '6次以上,频�生病', value: 'many' }
           ]},
-          { question: '生病严�程度如何�, options: [
-            { label: '从未�院,��就�, value: 'mild' },
-            { label: '�尔需�输�雾化', value: 'moderate' },
-            { label: '曾�院治�, value: 'severe' }
+          { question: '生病严�程度如何?', options: [
+            { label: '从未�院,��就好', value: 'mild' },
+            { label: '�尔需�输液/雾化', value: 'moderate' },
+            { label: '曾�院治疗', value: 'severe' }
           ]},
-          { question: '孩�是�有过���, options: [
+          { question: '孩�是�有过��?', options: [
             { label: '没有过�', value: 'none' },
             { label: '有轻微过�(花粉/尘螨等)', value: 'mild' },
-            { label: '有食��物过�', value: 'severe' }
+            { label: '有食物/�物过�', value: 'severe' }
           ]}
         ],
         nutrition: [
-          { question: '孩�挑食/�食程度�, options: [
-            { label: '�挑食,什么都�, value: 'none' },
+          { question: '孩�挑食/�食程度?', options: [
+            { label: '�挑食,什么都�', value: 'none' },
             { label: '挑几样特定的食物', value: 'mild' },
-            { label: '严�挑食,�类很�, value: 'severe' }
+            { label: '严�挑食,�类很少', value: 'severe' }
           ]},
-          { question: '�周大概�多少���食��, options: [
+          { question: '�周大概�多少���食�?', options: [
             { label: '超过20�,饮食多样', value: 'diverse' },
             { label: '10-20�,比较丰富', value: 'moderate' },
             { label: '少于10�,比较�一', value: 'limited' }
           ]},
-          { question: '孩�是�在使用�养补充剂�, options: [
+          { question: '孩�是�在使用�养补充剂?', options: [
             { label: '按医嘱使用多�补充剂', value: 'multiple' },
-            { label: '使用维生素D/钙等基础补充�, value: 'basic' },
+            { label: '使用维生素D/钙等基础补充剂', value: 'basic' },
             { label: '�使用任何补充剂', value: 'none' }
           ]}
         ],
         gut: [
-          { question: '孩�最近消化舒适度如何�, options: [
-            { label: '很好,消化顺�, value: 'good' },
-            { label: '一般,�尔肚��舒�, value: 'fair' },
-            { label: '较差,�常腹�腹胀/腹泻', value: 'poor' }
+          { question: '孩�最近消化舒适度如何?', options: [
+            { label: '很好,消化顺畅', value: 'good' },
+            { label: '一般,�尔肚��舒�', value: 'fair' },
+            { label: '较差,�常腹痛/腹胀/腹泻', value: 'poor' }
           ]},
-          { question: '孩�排便频率�, options: [
+          { question: '孩�排便频率?', options: [
             { label: '�天1-2次,规律', value: 'regular' },
             { label: '隔天一次,基本规律', value: 'mostly' },
-            { label: '�规律,�常便秘或腹�, value: 'irregular' }
+            { label: '�规律,�常便秘或腹泻', value: 'irregular' }
           ]},
           { question: '孩�是�有肠胃相关诊断?', options: [
             { label: '没有肠胃问题', value: 'none' },
-            { label: '有��性消化��, value: 'mild' },
-            { label: '有确诊肠胃问�, value: 'diagnosed' }
+            { label: '有��性消化�良', value: 'mild' },
+            { label: '有确诊肠胃问题', value: 'diagnosed' }
           ]}
         ],
         exercise: [
-          { question: '孩��周�动频率�, options: [
+          { question: '孩��周�动频率?', options: [
             { label: '�天�动', value: 'daily' },
-            { label: '�周3-5�, value: 'often' },
-            { label: '�周1-2�, value: 'sometimes' },
-            { label: '基本���, value: 'rarely' }
+            { label: '�周3-5次', value: 'often' },
+            { label: '�周1-2次', value: 'sometimes' },
+            { label: '基本��动', value: 'rarely' }
           ]},
-          { question: '孩��次�动时长�, options: [
+          { question: '孩��次�动时长?', options: [
             { label: '超过1�时', value: 'gt1h' },
-            { label: '30分钟��时', value: '30to1h' },
+            { label: '30分钟到1�时', value: '30to1h' },
             { label: '少于30分钟', value: 'lt30m' }
           ]},
           { question: '孩�喜欢的�动类型?', options: [
             { label: '�类/田径等竞技�动', value: 'competitive' },
-            { label: '游泳/骑行等有氧��, value: 'aerobic' },
-            { label: '跳绳/体�等�活性��, value: 'flexibility' },
+            { label: '游泳/骑行等有氧�动', value: 'aerobic' },
+            { label: '跳绳/体�等�活性�动', value: 'flexibility' },
             { label: '�太喜欢�动', value: 'sedentary' }
           ]}
         ]
@@ -237,7 +237,7 @@ export default {
       return this.currentQuestions[this.currentQIndex] || {}
     },
     resultIcon: function() {
-      if (!this.result) return '�
+      if (!this.result) return '✅'
       var level = this.result.level
       if (level === 'excellent') return '🌟'
       if (level === 'good') return '�'
@@ -302,19 +302,19 @@ export default {
           _this.result = {
             score: 70,
             level: 'good',
-            suggestion: '�根�评估结果关注相关�康维度�
+            suggestion: '�根�评估结果关注相关�康维度。'
           }
           _this.step = 3
         }
       }).catch(function() {
         _this.loading = false
-        _this.result = { score: 70, level: 'good', suggestion: '�交�功,�根�评估结果关注相关�康维度� }
+        _this.result = { score: 70, level: 'good', suggestion: '�交�功,�根�评估结果关注相关�康维度。' }
         _this.step = 3
       })
     },
     levelText: function(level) {
-      var map = { excellent: '优秀', good: '良好', fair: '一�, poor: '较差' }
-      return map[level] || '一�
+      var map = { excellent: '优秀', good: '良好', fair: '一般', poor: '较差' }
+      return map[level] || '一般'
     },
     goToDimensions: function() {
       uni.navigateTo({ url: '/pages/body/health-dimensions?childId=' + this.activeChildId })

+ 12 - 12
cfc-frontend/pages/body/exercise-record.vue

@@ -1,14 +1,14 @@
 <template>
   <view class="exercise-container">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�返回</text>
+      <text class="nav-back" @click="goBack">‹ 返回</text>
       <text class="nav-title">�动记录</text>
       <view class="nav-placeholder"></view>
     </view>
 
     <!-- �员选择 -->
     <view class="member-selector-card">
-      <text class="member-label">记录�/text>
+      <text class="member-label">记录人</text>
       <picker mode="selector" :range="memberOptions" :value="selectedMemberIndex" @change="onMemberChange">
         <view class="picker-display">{{ memberOptions[selectedMemberIndex] }}</view>
       </picker>
@@ -32,13 +32,13 @@
       <view class="input-row">
         <text class="input-label">强度</text>
         <view class="intensity-options">
-          <text class="intensity-item" v-for="v in ['�,'�,'�]" :key="v"
+          <text class="intensity-item" v-for="v in ['低','中','高']" :key="v"
             :class="{ 'intensity-active': intensity === v }" @click="intensity = v">{{ v }}</text>
         </view>
       </view>
       <view class="input-row">
         <text class="input-label">备注</text>
-        <input class="input-field" v-model="remark" placeholder="�� />
+        <input class="input-field" v-model="remark" placeholder="�选" />
       </view>
 
       <view class="submit-btn" @click="submitExercise">�存记录</view>
@@ -59,7 +59,7 @@
           <text class="history-icon">{{ getTypeIcon(item.exerciseType) }}</text>
           <view class="history-info">
             <text class="history-name">{{ item.exerciseType }}</text>
-            <text class="history-meta">{{ item.durationMinutes }}分钟 · {{ item.intensity || '� }}强度</text>
+            <text class="history-meta">{{ item.durationMinutes }}分钟 · {{ item.intensity || '中' }}强度</text>
           </view>
           <text class="history-time">{{ item.createdAt ? item.createdAt.substring(5,16) : '' }}</text>
         </view>
@@ -80,11 +80,11 @@ export default {
     return {
       childId: null,
       selectedMemberIndex: 0,
-      memberOptions: ['我自�],
+      memberOptions: ['我自己'],
       memberIds: [],
       selectedType: 'running',
       duration: '',
-      intensity: '�,
+      intensity: '中',
       remark: '',
       exerciseHistory: [],
       exerciseTypes: [
@@ -92,7 +92,7 @@ export default {
         { icon: '🚴', label: '骑行', value: 'cycling' },
         { icon: '�', label: '游泳', value: 'swimming' },
         { icon: '🤸', label: '跳绳', value: 'jumping_rope' },
-        { icon: '�, label: '�类', value: 'ball_games' },
+        { icon: '⚽', label: '�类', value: 'ball_games' },
         { icon: '🧘', label: '拉伸', value: 'stretching' }
       ]
     }
@@ -112,7 +112,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.childId })
-          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() {})
     },
@@ -127,7 +127,7 @@ export default {
     },
     submitExercise: function() {
       if (!this.duration || parseInt(this.duration) <= 0) {
-        uni.showToast({ title: '请输入有效时�, icon: 'none' })
+        uni.showToast({ title: '请输入有效时长', icon: 'none' })
         return
       }
       var data = {
@@ -140,7 +140,7 @@ export default {
         data.childId = this.childId
         data.memberId = this.childId
       }
-      uni.showLoading({ title: '�存�..' })
+      uni.showLoading({ title: '�存中...' })
       healthRequest('/api/health/exercise/create', data).then(function() {
         uni.hideLoading()
         uni.showToast({ title: '�存�功', icon: 'success' })
@@ -161,7 +161,7 @@ export default {
       }).catch(function() { self.exerciseHistory = [] })
     },
     getTypeIcon: function(type) {
-      var map = { running: '�', cycling: '🚴', swimming: '�', jumping_rope: '🤸', ball_games: '�, stretching: '🧘' }
+      var map = { running: '�', cycling: '🚴', swimming: '�', jumping_rope: '🤸', ball_games: '⚽', stretching: '🧘' }
       return map[type] || '�'
     },
     goBack: function() { uni.navigateBack() }

+ 13 - 13
cfc-frontend/pages/body/food-list.vue

@@ -2,7 +2,7 @@
   <view class="food-list-container">
     <!-- 顶部导航 -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�返回</text>
+      <text class="nav-back" @click="goBack">‹ 返回</text>
       <text class="nav-title">食�推�</text>
       <view class="nav-placeholder"></view>
     </view>
@@ -10,7 +10,7 @@
     <!-- Tab切� -->
     <view class="tab-bar">
       <text class="tab-item" :class="{'active': activeTab === 'total'}" @click="switchTab('total')">全部食�</text>
-      <text class="tab-item" :class="{'active': activeTab === 'byMember'}" @click="switchTab('byMember')">按��/text>
+      <text class="tab-item" :class="{'active': activeTab === 'byMember'}" @click="switchTab('byMember')">按�员</text>
     </view>
 
     <!-- 全部食�模� -->
@@ -19,7 +19,7 @@
         <view class="food-header">
           <text class="food-name">{{ food.name }}</text>
           <view class="food-score" :class="'score-' + getScoreLevel(food.score)">
-            <text>{{ food.score || '--' }}�/text>
+            <text>{{ food.score || '--' }}分</text>
           </view>
           <view class="rec-score" :class="'rec-' + getRecScoreLevel(food.recommendIndex)" v-if="food.recommendIndex != null">
             <text>推� {{ food.recommendIndex }}</text>
@@ -28,12 +28,12 @@
         <text class="food-category" v-if="food.category">{{ food.category }}</text>
         <view class="food-nutrition" v-if="hasNutrition(food)">
           <text class="nutri-item" v-if="food.energyKj">能�: {{ food.energyKj }}kJ</text>
-          <text class="nutri-item" v-if="food.protein">蛋白� {{ food.protein }}g</text>
+          <text class="nutri-item" v-if="food.protein">蛋白质: {{ food.protein }}g</text>
           <text class="nutri-item" v-if="food.fat">脂肪: {{ food.fat }}g</text>
           <text class="nutri-item" v-if="food.carbs">碳水: {{ food.carbs }}g</text>
           <text class="nutri-item" v-if="food.fiber">膳食纤维: {{ food.fiber }}g</text>
-          <text class="nutri-item" v-if="food.starch">淀� {{ food.starch }}g</text>
-          <text class="nutri-item" v-if="food.cholesterol">胆固� {{ food.cholesterol }}mg</text>
+          <text class="nutri-item" v-if="food.starch">淀粉: {{ food.starch }}g</text>
+          <text class="nutri-item" v-if="food.cholesterol">胆固醇: {{ food.cholesterol }}mg</text>
         </view>
       </view>
       <view class="empty-state" v-if="totalFoods.length === 0 && !loading">
@@ -42,18 +42,18 @@
       </view>
     </view>
 
-    <!-- 按�员模�-->
+    <!-- 按æˆ�员模å¼-->
     <view v-if="activeTab === 'byMember'" class="food-section">
       <view v-for="(foods, childId) in byMemberFoods" :key="childId" class="member-group">
         <view class="member-header">
           <text class="member-name">{{ getMemberName(childId) }}</text>
-          <text class="member-count">{{ foods.length }}é¡?/text>
+          <text class="member-count">{{ foods.length }}项</text>
         </view>
         <view class="food-card" v-for="food in foods" :key="food.id">
           <view class="food-header">
             <text class="food-name">{{ food.name }}</text>
           <view class="food-score" :class="'score-' + getScoreLevel(food.score)">
-            <text>{{ food.score || '--' }}�/text>
+            <text>{{ food.score || '--' }}分</text>
           </view>
           <view class="rec-score" :class="'rec-' + getRecScoreLevel(food.recommendIndex)" v-if="food.recommendIndex != null">
             <text>推� {{ food.recommendIndex }}</text>
@@ -62,12 +62,12 @@
         <text class="food-category" v-if="food.category">{{ food.category }}</text>
         <view class="food-nutrition" v-if="hasNutrition(food)">
           <text class="nutri-item" v-if="food.energyKj">能�: {{ food.energyKj }}kJ</text>
-          <text class="nutri-item" v-if="food.protein">蛋白� {{ food.protein }}g</text>
+          <text class="nutri-item" v-if="food.protein">蛋白质: {{ food.protein }}g</text>
           <text class="nutri-item" v-if="food.fat">脂肪: {{ food.fat }}g</text>
           <text class="nutri-item" v-if="food.carbs">碳水: {{ food.carbs }}g</text>
           <text class="nutri-item" v-if="food.fiber">膳食纤维: {{ food.fiber }}g</text>
-          <text class="nutri-item" v-if="food.starch">淀� {{ food.starch }}g</text>
-          <text class="nutri-item" v-if="food.cholesterol">胆固� {{ food.cholesterol }}mg</text>
+          <text class="nutri-item" v-if="food.starch">淀粉: {{ food.starch }}g</text>
+          <text class="nutri-item" v-if="food.cholesterol">胆固醇: {{ food.cholesterol }}mg</text>
         </view>
       </view>
     </view>
@@ -132,7 +132,7 @@ export default {
         uni.showToast({ title: '缺少familyId', icon: 'none' })
         return
       }
-      uni.showLoading({ title: '加载�..' })
+      uni.showLoading({ title: '加载中...' })
       healthRequest('/api/health/foods/by-family', { familyId: this.familyId }).then(function(res) {
         uni.hideLoading()
         if (res.data) {

+ 1 - 1
cfc-frontend/pages/body/growth-curve.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="growth-container">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�返回</text>
+      <text class="nav-back" @click="goBack">‹ 返回</text>
       <text class="nav-title">生长曲线</text>
       <view class="nav-placeholder"></view>
     </view>

+ 9 - 9
cfc-frontend/pages/body/health-dimensions.vue

@@ -2,7 +2,7 @@
   <view class="hd-container">
     <view class="hd-header">
       <text class="hd-title">健康维度全景</text>
-      <text class="hd-subtitle" v-if="memberName">{{ memberName }}的健康档��?/text>
+      <text class="hd-subtitle" v-if="memberName">{{ memberName }}的健康档案</text>
     </view>
 
     <view class="hd-health-index" v-if="healthData && healthData.healthIndex">
@@ -46,7 +46,7 @@
       >
         <view class="dim-header">
           <text class="dim-label">{{ dim.label }}</text>
-          <text class="dim-score" :class="'score-' + dim.level">{{ dim.score || '--' }}��?/text>
+          <text class="dim-score" :class="'score-' + dim.level">{{ dim.score || '--' }}分</text>
         </view>
         <view class="dim-bar-wrap">
           <view class="dim-bar-bg">
@@ -62,18 +62,18 @@
         </view>
         <view class="dim-footer">
           <text class="dim-level-tag" :class="'tag-' + dim.level">{{ getLevelText(dim.level) }}</text>
-          <text class="dim-source" v-if="dim.trend">{{ dim.trend === 'up' ? '��?上升' : dim.trend === 'down' ? '��?下降' : '��?稳定' }}</text>
+          <text class="dim-source" v-if="dim.trend">{{ dim.trend === 'up' ? '↑ 上升' : dim.trend === 'down' ? '↓ 下降' : '→ 稳定' }}</text>
         </view>
       </view>
     </view>
 
     <view class="hd-empty" v-if="!healthData && !loading">
       <text class="empty-tip">暂无维度数据</text>
-      <text class="empty-sub">上传健康报告或填写问卷后可查��?/text>
+      <text class="empty-sub">上传健康报告或填写问卷后可查看</text>
     </view>
 
     <view class="loading-wrap" v-if="loading">
-      <text class="loading-text">加载��?..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
     <view class="fab-upload" @click="showUploadModal">
@@ -106,7 +106,7 @@
               class="form-input"
               type="number"
               v-model="uploadForm.score"
-              placeholder="请输入评��?
+              placeholder="请输入评分"
               min="0"
               max="100"
             />
@@ -156,7 +156,7 @@ export default {
         { code: 'growth', label: '生长发育' },
         { code: 'sleep', label: '睡眠质量' },
         { code: 'vision', label: '视力健康' },
-        { code: 'immunity', label: '免疫��? },
+        { code: 'immunity', label: '免疫力' },
         { code: 'nutrition', label: '营养均衡' },
         { code: 'gut', label: '肠胃健康' },
         { code: 'exercise', label: '运动活力' }
@@ -220,7 +220,7 @@ export default {
       var map = {
         'excellent': '优秀',
         'good': '良好',
-        'fair': '一��?,
+        'fair': '一般',
         'poor': '较差',
         'none': '暂无数据'
       }
@@ -257,7 +257,7 @@ export default {
         return
       }
       if (!this.uploadForm.score || this.uploadForm.score < 0 || this.uploadForm.score > 100) {
-        uni.showToast({ title: '评分需��?-100之间', icon: 'none' })
+        uni.showToast({ title: '评分需在0-100之间', icon: 'none' })
         return
       }
       if (!this.uploadForm.dataSource) {

+ 27 - 27
cfc-frontend/pages/body/health-report.vue

@@ -2,7 +2,7 @@
   <view class="report-container">
     <!-- 顶部导航 -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">��?返回</text>
+      <text class="nav-back" @click="goBack">返回</text>
       <text class="nav-title">健康报告详情</text>
       <view class="nav-placeholder"></view>
     </view>
@@ -14,14 +14,14 @@
         <view class="score-item">
           <view class="score-circle-lg">
             <text class="score-num">{{ report.overallScore || '--' }}</text>
-            <text class="score-unit">��?/text>
+            <text class="score-unit">分</text>
           </view>
           <text class="score-label">综合评分</text>
         </view>
         <view class="score-item" v-if="report.gutHealthScore">
           <view class="score-circle-lg score-circle-green">
             <text class="score-num">{{ report.gutHealthScore }}</text>
-            <text class="score-unit">��?/text>
+            <text class="score-unit">分</text>
           </view>
           <text class="score-label">肠道健康</text>
         </view>
@@ -33,7 +33,7 @@
       <text class="report-date">报告日期:{{ formatDate(report.reportDate) }}</text>
     </view>
 
-    <!-- ===== 评分可视化面��?(仅菌群报��? ===== -->
+    <!-- ===== 评分可视化面板 (仅菌群报告) ===== -->
     <view class="score-dashboard" v-if="report && report.reportType === 'gut_flora'">
       <view class="main-scores">
         <view class="main-score-item" v-for="item in mainScores" :key="item.key">
@@ -42,7 +42,7 @@
               <circle cx="60" cy="60" r="50" fill="none" stroke="#EEEEEE" stroke-width="8"/>
               <circle cx="60" cy="60" r="50" fill="none" v-bind:stroke="item.color" stroke-width="8" v-bind:stroke-dasharray="item.circumference" v-bind:stroke-dashoffset="item.offset" stroke-linecap="round" transform="rotate(-90 60 60)"/>
               <text x="60" y="52" text-anchor="middle" font-size="32" font-weight="bold" fill="#333">{{ item.score }}</text>
-              <text x="60" y="72" text-anchor="middle" font-size="14" fill="#999">��?/text>
+              <text x="60" y="72" text-anchor="middle" font-size="14" fill="#999">分</text>
             </svg>
           </view>
           <text class="main-score-label">{{ item.label }}</text>
@@ -62,14 +62,14 @@
     <view class="section">
       <view class="section-title">
         <text>指标明细</text>
-        <text class="section-sub">��?{{ indicators.length }} ��?/text>
+        <text class="section-sub">共 {{ indicators.length }} 项</text>
       </view>
 
-      <!-- 按分类分��?-->
+      <!-- 按分类分-->
       <view class="category-group" v-for="group in groupedIndicators" :key="group.name">
         <view class="category-header">
           <text class="category-name">{{ group.name }}</text>
-          <text class="category-count">{{ group.items.length }}��?/text>
+          <text class="category-count">{{ group.items.length }}项</text>
         </view>
         <view class="indicator-card" v-for="ind in group.items" :key="ind._idx">
           <view class="ind-header">
@@ -97,7 +97,7 @@
     <view class="section" v-if="deficiencyRecords && deficiencyRecords.length > 0">
       <view class="section-title">
         <text>🔬 营养缺乏分析</text>
-        <text class="section-sub">{{ deficiencyRecords.length }}��?/text>
+        <text class="section-sub">{{ deficiencyRecords.length }}项</text>
       </view>
       <view class="deficiency-list">
         <view class="deficiency-card" v-for="dr in deficiencyRecords" :key="dr.nutrient">
@@ -114,11 +114,11 @@
             <text class="severity-val">{{ dr.severity }}</text>
           </view>
           <view class="deficiency-meta" v-if="dr.indicatorName">
-            <text class="meta-label">关联指标��?/text>
+            <text class="meta-label">关联指标:</text>
             <text class="meta-value">{{ dr.indicatorName }} ({{ dr.indicatorValue }})</text>
           </view>
           <view class="deficiency-foods" v-if="dr.foodSuggestions">
-            <text class="foods-label">推荐食物��?/text>
+            <text class="foods-label">推荐食物:</text>
             <text class="foods-value">{{ dr.foodSuggestions }}</text>
           </view>
         </view>
@@ -129,7 +129,7 @@
     <view class="section" v-if="foods && foods.length > 0">
       <view class="section-title">
         <text>🥗 食材推荐</text>
-        <text class="section-sub">��?{{ foods.length }} ��?/text>
+        <text class="section-sub">共 {{ foods.length }} 项</text>
       </view>
       <view class="food-list">
         <view class="food-card" v-for="food in foods" :key="food.id">
@@ -148,7 +148,7 @@
               <text class="n-value">{{ food.energyKj }} kJ</text>
             </view>
             <view class="nutrition-item" v-if="food.protein">
-              <text class="n-label">蛋白��?/text>
+              <text class="n-label">蛋白质</text>
               <text class="n-value">{{ food.protein }}g</text>
             </view>
             <view class="nutrition-item" v-if="food.fat">
@@ -164,10 +164,10 @@
       </view>
     </view>
 
-    <!-- ===== 五维雷达��?(菌群报告) ===== -->
+    <!-- ===== 五维雷达(菌群报告) ===== -->
     <view class="section" v-if="report && report.reportType === 'gut_flora' && radarDimensions.length > 0">
       <view class="section-title">
-        <text>五维雷达��?/text>
+        <text>五维雷达图</text>
       </view>
       <view class="radar-wrap">
         <canvas canvas-id="radarCanvas" id="radarCanvas" class="radar-canvas" @touchstart.prevent></canvas>
@@ -230,9 +230,9 @@ export default {
   computed: {
     reportTypeLabel: function() {
       if (!this.report) return ''
-      return this.report.reportType === 'gut_flora' ? '肠道检测报��? : '体检报告'
+      return this.report.reportType === 'gut_flora' ? '肠道检测报告' : '体检报告'
     },
-    // 预计算分组,每个指标附加 _cls (CSS��? ��?_label (显示标签)
+    // 预计算分组,每个指标附加 _cls (CSS类) 和 _label (显示标签)
     groupedIndicators: function() {
       var result = []
       var groupMap = {}
@@ -251,7 +251,7 @@ export default {
         } else if (s.indexOf('偏低') !== -1 || s.indexOf('过低') !== -1 || s.indexOf('注意') !== -1 || s.indexOf('warning') !== -1) {
           cls = 'status-warn'
           label = '偏低'
-        } else if (s.indexOf('正常') !== -1 || s.indexOf('normal') !== -1 || s.indexOf('低风��?) !== -1) {
+        } else if (s.indexOf('正常') !== -1 || s.indexOf('normal') !== -1 || s.indexOf('低风险') !== -1) {
           cls = 'status-normal'
           label = '正常'
         } else if (status) {
@@ -302,9 +302,9 @@ export default {
       var items = []
       var pairs = [
         {key:'balance', label:'菌群平衡', score: r.balanceScore},
-        {key:'diversity', label:'菌群多样��?, score: r.diversityScore},
-        {key:'beneficial', label:'有益��?, score: r.beneficialScore},
-        {key:'harmful', label:'有害��?, score: r.harmfulScore},
+        {key:'diversity', label:'菌群多样性', score: r.diversityScore},
+        {key:'beneficial', label:'有益菌', score: r.beneficialScore},
+        {key:'harmful', label:'有害菌', score: r.harmfulScore},
         {key:'coreGenus', label:'核心菌属', score: r.coreGenusScore}
       ]
       for (var i = 0; i < pairs.length; i++) {
@@ -346,7 +346,7 @@ export default {
   methods: {
     loadData: function() {
       var self = this
-      uni.showLoading({ title: '加载��?..' })
+      uni.showLoading({ title: '加载中...' })
       // Load report + indicators in parallel
       var promises = []
       if (this.reportId) {
@@ -402,7 +402,7 @@ export default {
     goNutritionChat: function() {
       if (!this.reportId) return
       uni.navigateTo({
-        url: '/pages/ai/chat?mode=nutrition&reportId=' + this.reportId + '&firstMessage=' + encodeURIComponent('请根据这份菌群检测报告,分析我孩子的营养状况并提出建��?)
+        url: '/pages/ai/chat?mode=nutrition&reportId=' + this.reportId + '&firstMessage=' + encodeURIComponent('请根据这份菌群检测报告,分析我孩子的营养状况并提出建议')
       })
     },
     loadDeficiencyRecords: function() {
@@ -423,8 +423,8 @@ export default {
     getDeficiencyTypeLabel: function(type) {
       if (type === 'deficiency') return '缺乏'
       if (type === 'excess') return '偏高'
-      if (type === 'borderline') return '边界��?
-      return '未分��?
+      if (type === 'borderline') return '边界值'
+      return '未分类'
     },
     getSeverityColor: function(severity) {
       if (severity >= 0.7) return '#EF4444'
@@ -527,7 +527,7 @@ export default {
   background: #f5f7fa;
 }
 
-/* ===== 导航��?===== */
+/* ===== 导航===== */
 .nav-bar {
   position: sticky;
   top: 0;
@@ -916,7 +916,7 @@ export default {
   color: #2E7D32;
 }
 
-/* ===== 雷达��?===== */
+/* ===== 雷达===== */
 .radar-wrap {
   display: flex;
   justify-content: center;

+ 9 - 9
cfc-frontend/pages/body/health-trend.vue

@@ -1,17 +1,17 @@
 <template>
   <view class="trend-container">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�返回</text>
+      <text class="nav-back" @click="goBack">‹ 返回</text>
       <text class="nav-title">�康趋势</text>
       <view class="nav-placeholder"></view>
     </view>
 
     <view class="date-tabs">
-      <text class="date-tab" :class="{ 'date-tab-active': activeTab === '7d' }" @click="switchDateRange('7d')">��/text>
-      <text class="date-tab" :class="{ 'date-tab-active': activeTab === '30d' }" @click="switchDateRange('30d')">�0�/text>
+      <text class="date-tab" :class="{ 'date-tab-active': activeTab === '7d' }" @click="switchDateRange('7d')">近7天</text>
+      <text class="date-tab" :class="{ 'date-tab-active': activeTab === '30d' }" @click="switchDateRange('30d')">近30天</text>
     </view>
 
-    <!-- 平�分概�-->
+    <!-- 平�分概览 -->
     <view class="summary-section" v-if="averages">
       <view class="summary-title">平�评分</view>
       <view class="summary-grid">
@@ -22,12 +22,12 @@
       </view>
     </view>
 
-    <!-- 趋势�-->
+    <!-- 趋势图 -->
     <view class="chart-section">
       <view class="chart-category" v-for="cat in chartCategories" :key="cat.key">
         <view class="chart-header">
           <text class="chart-label">{{ cat.label }}</text>
-          <text class="chart-avg" :style="{ color: cat.color }">{{ currentAvg(cat.key) }}�/text>
+          <text class="chart-avg" :style="{ color: cat.color }">{{ currentAvg(cat.key) }}分</text>
         </view>
         <view class="chart-bars">
           <view class="chart-bar-col" v-for="(day, idx) in trendData" :key="idx">
@@ -40,12 +40,12 @@
       </view>
     </view>
 
-    <!-- 加载状�-->
+    <!-- 加载状æ€-->
     <view class="loading-state" v-if="loading">
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
-    <!-- 空状�-->
+    <!-- 空状æ€-->
     <view class="empty-state" v-if="!loading && trendData.length === 0">
       <text class="empty-icon">📊</text>
       <text class="empty-text">暂无趋势数�</text>

+ 19 - 19
cfc-frontend/pages/body/index.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="body-container">
-    <!-- Tabbar ��揢餈�腹憿?-->
+    <!-- Tabbar ��揢餈�腹憿-->
     <tab-transition v-if="showTabTransition" dimCode="body" />
 
     <!-- ���憭湧� -->
@@ -8,7 +8,7 @@
       tagline="蝘穃郎蝞∠��典振�亙熒"
       quote="頨思��亙熒�臬兢蝳讐��箇�" />
 
-    <!-- 摰嗅滬�𣂼��㗇𥋘�?-->
+    <!-- 摰嗅滬�𣂼��㗇𥋘�-->
     <FamilyMemberStrip
       v-if="isLoggedIn"
       :members="familyMembersVisible"
@@ -18,23 +18,23 @@
     <!-- 皜詨恥銝枏��箏� -->
     <template v-if="!isLoggedIn">
       <LoginGuideCard
-        title="�餃��擧䰻�见�摰嗅�摨瑟㺭�?
+        title="�餃��擧䰻�见�摰嗅�摨瑟㺭��"
         :items="[
-          '�亦��典振頨思��賡��唳旿���摨瑟𥁒�?,
-          '霈啣�瘥𤩺𠯫�亙熒�枏㨃嚗諹繮�𤥁澈雿栞��?,
-          '�亦�銝枏��亙熒����峕暑�其遠�?
+          '�亦��典振頨思��賡��唳旿���摨瑟𥁒��',
+          '霈啣�瘥𤩺𠯫�亙熒�枏㨃嚗諹繮�𤥁澈雿栞���',
+          '�亦�銝枏��亙熒����峕暑�其遠��'
         ]" />
       <HealthTips dimension="body" />
     </template>
 
-    <!-- �餃��𠬍�鈭𠉛輕�賡��?-->
+    <!-- �餃��𠬍�鈭𠉛輕�賡��-->
     <FamilyEnergyBar
       v-if="isLoggedIn"
       dimensionCode="body"
       :sandboxData="sandboxData"
       :dualDimension="dualDimension" />
 
-    <!-- �喟頂�曇停嚗�蒈敶訫��航�嚗?-->
+    <!-- �喟頂�曇停嚗�蒈敶訫��航�嚗-->
     <FamilyRelationGraph
       v-if="isLoggedIn && familyMembersVisible.length > 0"
       dimensionCode="body"
@@ -49,14 +49,14 @@
       v-if="isLoggedIn && activeChildId"
       :childId="activeChildId" />
 
-      <!-- �瑁噢�?-->
+      <!-- �瑁噢�-->
       <view class="section" v-if="dimensionData">
         <view class="section-header" v-if="dimensionData.isAverage">
-          <text class="section-title">銝�輕�亙熒�?/text>
-          <text class="avg-badge">�屸��峕�批像���?繚 銝𠹺��亙��擧遬蝷箔葵鈭箸㺭�?/text>
+          <text class="section-title">銝�輕�亙熒��</text>
+          <text class="avg-badge">�屸��峕�批像���� 繚 銝𠹺��亙��擧遬蝷箔葵鈭箸㺭��</text>
         </view>
         <view class="section-header" v-else>
-          <text class="section-title">銝�輕�亙熒�?/text>
+          <text class="section-title">銝�輕�亙熒��</text>
         </view>
         <RadarChart
           v-if="radarDimensions && radarDimensions.length >= 3"
@@ -89,7 +89,7 @@
       </view>
     </view>
 
-    <!-- ===== 蝎曉��亙�嚗��隡䭾𥁒�?鈭批�+���嚗?===== -->
+    <!-- ===== 蝎曉��亙�嚗��隡䭾𥁒��+鈭批�+���嚗� ===== -->
     <view class="section nutrition-section" v-if="isLoggedIn">
       <view class="section-header">
         <text class="section-title">�� 蝎曉��亙�</text>
@@ -105,11 +105,11 @@
           <text class="nutrition-desc">銝𠹺�雿𤘪��亙��𤥁��𤘪�瘚𧢲𥁒�𠺪�AI�箄�閫�粉���嚗諹繮�碶葵�批��亙��寞�</text>
           <view class="nutrition-report-tags">
             <text class="tag">雿𤘪��亙�</text>
-            <text class="tag">�𣳇�璉�瘚?/text>
+            <text class="tag">�𣳇�璉�瘚�</text>
             <text class="tag">AI閫�粉</text>
           </view>
         </view>
-        <text class="nutrition-arrow">�?/text>
+        <text class="nutrition-arrow">��</text>
       </view>
 
       </view>
@@ -194,7 +194,7 @@ export default {
       dimensionProducts: [],
       bodyArticles: [],
       dimensionData: null,
-      /** Mock 撟喳��潘�7蝏湛�嚗𡁶��踹��?�∠�韐券�/閫���亙熒/�滨𢥫�?�亙���﹛/�㰘��亙熒/餈𣂼𢆡瘣餃� */
+      /** Mock 撟喳��潘�7蝏湛�嚗𡁶��踹���/�∠�韐券�/閫���亙熒/�滨𢥫��/�亙���﹛/�㰘��亙熒/餈𣂼𢆡瘣餃� */
       radarAvgScores: [72, 68, 75, 70, 73, 69, 71],
       funcList: [
         { icon: '\u{1F3C3}', label: '餈𣂼𢆡', needLogin: true, page: '/pages/body/exercise-record' },
@@ -223,7 +223,7 @@ export default {
     intimacyMapForGraph: function() {
       return {}
     },
-    /** 銝�輕�瑁噢�橘�蝏游漲��倌嚗��摰?AGENTS.md 蝳�迫璅⊥踎��䲮瘜閗��剁�雿輻鍂 computed 蝻枏�嚗?*/
+    /** 銝�輕�瑁噢�橘�蝏游漲��倌嚗��摰� AGENTS.md 蝳�迫璅⊥踎��䲮瘜閗��剁�雿輻鍂 computed 蝻枏�嚗� */
     radarDimensions: function() {
       var dims = this.dimensionData && this.dimensionData.dimensions
       if (!dims) return []
@@ -235,7 +235,7 @@ export default {
       }
       return result
     },
-    /** 銝�輕�瑁噢�橘����潘�撖?null/NaN �𡁜�銝��吔��踹� Canvas 霈∠� NaN �䠷�憭梯揖嚗?*/
+    /** 銝�輕�瑁噢�橘����潘�撖� null/NaN �𡁜�銝��吔��踹� Canvas 霈∠� NaN �䠷�憭梯揖嚗� */
     radarScores: function() {
       var dims = this.dimensionData && this.dimensionData.dimensions
       if (!dims) return []
@@ -264,7 +264,7 @@ export default {
       this.loadChildren()
       this.loadFamilyMembersVisible()
     }
-    // 皜詨恥銋蠘�瘚讛�瘣餃𢆡����?
+    // 皜詨恥銋蠘�瘚讛�瘣餃𢆡����
     this.loadDimensionActivities()
     this.loadDimensionProducts()
     // 皜詨恥銋蠘�瘚讛����

+ 11 - 11
cfc-frontend/pages/body/meal-record.vue

@@ -1,14 +1,14 @@
 <template>
   <view class="meal-container">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�返回</text>
+      <text class="nav-back" @click="goBack">‹ 返回</text>
       <text class="nav-title">饮食记录</text>
       <view class="nav-placeholder"></view>
     </view>
 
     <!-- �员选择 -->
     <view class="member-selector-card">
-      <text class="member-label">记录�/text>
+      <text class="member-label">记录人</text>
       <picker mode="selector" :range="memberOptions" :value="selectedMemberIndex" @change="onMemberChange">
         <view class="picker-display">{{ memberOptions[selectedMemberIndex] }}</view>
       </picker>
@@ -31,11 +31,11 @@
         </view>
         <view class="input-row">
           <text class="input-label">份�</text>
-          <input class="input-field" v-model="foodAmount" placeholder="如:1碗�00g" />
+          <input class="input-field" v-model="foodAmount" placeholder="如:1碗�200g" />
         </view>
         <view class="input-row" v-if="foodName">
           <text class="input-label">预估热�</text>
-          <input class="input-field" v-model="calories" type="number" placeholder="�� />
+          <input class="input-field" v-model="calories" type="number" placeholder="�选" />
         </view>
         <view class="add-food-btn" @click="addFood">添加食物</view>
       </view>
@@ -47,7 +47,7 @@
             <text class="food-amount">{{ food.foodAmount }}</text>
           </view>
           <text class="food-cal" v-if="food.calories">{{ food.calories }} kcal</text>
-          <text class="food-del" @click="todayFoods.splice(idx, 1)">�/text>
+          <text class="food-del" @click="todayFoods.splice(idx, 1)">✕</text>
         </view>
         <view class="food-empty" v-if="todayFoods.length === 0">
           <text>暂未添加食物</text>
@@ -86,7 +86,7 @@ export default {
     return {
       childId: null,
       selectedMemberIndex: 0,
-      memberOptions: ['我自�],
+      memberOptions: ['我自己'],
       memberIds: [],
       activeMealType: 'breakfast',
       foodName: '',
@@ -113,7 +113,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.childId })
-          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() {})
     },
@@ -128,13 +128,13 @@ export default {
     },
     addFood: function() {
       if (!this.foodName.trim()) {
-        uni.showToast({ title: '请输入食物��, icon: 'none' })
+        uni.showToast({ title: '请输入食物�称', icon: 'none' })
         return
       }
       this.todayFoods.push({
         mealType: this.activeMealType,
         foodName: this.foodName.trim(),
-        foodAmount: this.foodAmount.trim() || '1ä»?,
+        foodAmount: this.foodAmount.trim() || '1份',
         calories: this.calories ? parseInt(this.calories) : null
       })
       this.foodName = ''
@@ -143,10 +143,10 @@ export default {
     },
     submitMeal: function() {
       if (this.todayFoods.length === 0) {
-        uni.showToast({ title: '请至少添加一个食�, icon: 'none' })
+        uni.showToast({ title: '请至少添加一个食物', icon: 'none' })
         return
       }
-      uni.showLoading({ title: '�存�..' })
+      uni.showLoading({ title: '�存中...' })
       var self = this
       var promises = this.todayFoods.map(function(food) {
         var data = {

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

@@ -5,19 +5,19 @@
       <view class="nav-back" @click="goBack">
         <text class="nav-back-icon">&#x2190;</text>
       </view>
-      <text class="nav-title">�· �员详情</text>
+      <text class="nav-title">身 · �员详情</text>
     </view>
 
-    <!-- 五维能��-->
+    <!-- 五维能�� -->
     <FamilyEnergyBar
       dimensionCode="body"
       :sandboxData="sandboxData"
       :dualDimension="dualDimension" />
 
-    <!-- �员信��-->
+    <!-- �员信�� -->
     <view class="member-card" v-if="memberInfo">
       <view class="member-avatar">
-        <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || 'å­? }}</text>
+        <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || 'å­©' }}</text>
       </view>
       <view class="member-info">
         <text class="member-name">{{ memberInfo.name || 'å­©å­�' }}</text>
@@ -25,7 +25,7 @@
       </view>
       <view class="member-score" v-if="dualDimension">
         <text class="score-value">{{ dualDimension.energy || 0 }}</text>
-        <text class="score-label">能��/text>
+        <text class="score-label">能�值</text>
       </view>
     </view>
 

+ 15 - 15
cfc-frontend/pages/body/recipe-recommend.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="recipe-container">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">鈥?杩斿洖</text>
+      <text class="nav-back" @click="goBack">鈥杩斿洖</text>
       <text class="nav-title">椋熻氨鎺ㄨ崘</text>
       <view class="nav-placeholder"></view>
     </view>
@@ -22,7 +22,7 @@
       </view>
       <view class="recommend-btn" :class="{ 'recommend-btn-loading': loading }" @click="doRecommend">
         <text class="recommend-btn-text">{{ loading ? 'AI鎬濊€冧腑...' : '鐢熸垚浠婃棩椋熻氨' }}</text>
-        <text class="recommend-btn-icon">鉁?/text>
+        <text class="recommend-btn-icon">鉁�</text>
       </view>
     </view>
 
@@ -38,7 +38,7 @@
           </view>
           <text class="meal-reason" v-if="meal.reason">{{ meal.reason }}</text>
           <view class="meal-ingredients" v-if="meal.ingredients">
-            <text class="ingredient-label">椋熸潗锛?/text>
+            <text class="ingredient-label">椋熸潗锛�</text>
             <text class="ingredient-text">{{ meal.ingredients }}</text>
           </view>
           <text class="meal-tips" v-if="meal.tips">馃挕 {{ meal.tips }}</text>
@@ -53,13 +53,13 @@
     <view class="section-card" v-if="recipeResult">
       <view class="card-header">
         <text class="card-title">馃攧 椋熸潗鏇挎崲寤鸿�</text>
-        <text class="card-subtitle">涓€閿�浛鎹㈡帹鑽愰�鏉?/text>
+        <text class="card-subtitle">涓€閿�浛鎹㈡帹鑽愰�鏉�</text>
       </view>
       <view class="replace-options">
         <view class="replace-item" v-for="(food, idx) in replaceOptions" :key="idx" @click="replaceFood(food.id)">
           <text class="replace-name">{{ food.name }}</text>
-          <text class="replace-score" v-if="food.score">{{ food.score }}鍒?/text>
-          <text class="replace-icon">鈫?/text>
+          <text class="replace-score" v-if="food.score">{{ food.score }}鍒�</text>
+          <text class="replace-icon">鈫�</text>
         </view>
         <view class="replace-empty" v-if="!replaceOptions || replaceOptions.length === 0">
           <text>鏆傛棤鏇挎崲寤鸿�</text>
@@ -101,7 +101,7 @@ export default {
       mealTypes: [
         { label: '姣忔棩', value: 'daily', icon: '馃搮' },
         { label: '鏃╅�', value: 'breakfast', icon: '馃寘' },
-        { label: '鍗堥�', value: 'lunch', icon: '鈽€锔? },
+        { label: '鍗堥�', value: 'lunch', icon: '鈽€锔�' },
         { label: '鏅氶�', value: 'dinner', icon: '馃寵' },
         { label: '鍔犻�', value: 'snack', icon: '馃崻' }
       ]
@@ -154,15 +154,15 @@ export default {
         var mockData = {
           answer: JSON.stringify({
             dailyMeals: [
-              { mealType: '鏃╅�', recipeName: '鍏ㄩ害涓夋槑娌?鐗涘ザ', reason: '鎼�厤浼樿川纰虫按+铔嬬櫧璐?, ingredients: '鍏ㄩ害闈㈠寘2鐗囥€侀浮铔?涓�€佺敓鑿?鐗囥€佺墰濂?00ml', tips: '鍏ㄩ害闈㈠寘鎻愪緵鑶抽�绾ょ淮锛岀墰濂惰ˉ鍏呴挋璐? },
-              { mealType: '鍗堥�', recipeName: '娓呰捀楸?鏉傜伯楗?, reason: '浼樿川铔嬬櫧+澶嶅悎纰虫按', ingredients: '椴堥奔150g銆佽タ鍏拌姳100g銆佹潅绮�背50g', tips: '楸肩被瀵屽惈DHA锛屾湁鍔╀簬澶ц剳鍙戣偛' },
-              { mealType: '鏅氶�', recipeName: '鐣�寗楦¤倝鎰忛潰', reason: '鍧囪 钀ュ吇鏄撴秷鍖?, ingredients: '楦¤兏鑲?00g銆佺暘鑼?涓�€佹剰闈?0g', tips: '鏅氶�閫傞噺鍑忓皯纰虫按閲? }
+              { mealType: '鏃╅�', recipeName: '鍏ㄩ害涓夋槑娌�+鐗涘ザ', reason: '鎼�厤浼樿川纰虫按+铔嬬櫧璐�', ingredients: '鍏ㄩ害闈㈠寘2鐗囥€侀浮铔�1涓�€佺敓鑿�2鐗囥€佺墰濂�200ml', tips: '鍏ㄩ害闈㈠寘鎻愪緵鑶抽�绾ょ淮锛岀墰濂惰ˉ鍏呴挋璐�' },
+              { mealType: '鍗堥�', recipeName: '娓呰捀楸�+鏉傜伯楗�', reason: '浼樿川铔嬬櫧+澶嶅悎纰虫按', ingredients: '椴堥奔150g銆佽タ鍏拌姳100g銆佹潅绮�背50g', tips: '楸肩被瀵屽惈DHA锛屾湁鍔╀簬澶ц剳鍙戣偛' },
+              { mealType: '鏅氶�', recipeName: '鐣�寗楦¤倝鎰忛潰', reason: '鍧囪 钀ュ吇鏄撴秷鍖�', ingredients: '楦¤兏鑲�100g銆佺暘鑼�1涓�€佹剰闈�80g', tips: '鏅氶�閫傞噺鍑忓皯纰虫按閲�' }
             ],
-            nutritionTip: '寤鸿�姣忔棩鎽勫叆锛氳泲鐧借川50-60g锛岀⒊姘?50-200g锛岃敩鏋?00g浠ヤ笂'
+            nutritionTip: '寤鸿�姣忔棩鎽勫叆锛氳泲鐧借川50-60g锛岀⒊姘�150-200g锛岃敩鏋�500g浠ヤ笂'
           }),
           conversationId: '',
-          replaceOptions: [{ id: 1, name: '楦¤兏鑲?, score: 85 }, { id: 2, name: '涓夋枃楸?, score: 90 }, { id: 3, name: '璞嗚厫', score: 75 }],
-          nutritionSummary: { 铔嬬櫧璐? '55g', 纰虫按: '180g', 鑴傝偑: '40g', 鑶抽�绾ょ淮: '15g', 鐑�噺: '1450kcal' }
+          replaceOptions: [{ id: 1, name: '楦¤兏鑲�', score: 85 }, { id: 2, name: '涓夋枃楸�', score: 90 }, { id: 3, name: '璞嗚厫', score: 75 }],
+          nutritionSummary: { 铔嬬櫧璐�: '55g', 纰虫按: '180g', 鑴傝偑: '40g', 鑶抽�绾ょ淮: '15g', 鐑�噺: '1450kcal' }
         }
         self.recipeResult = mockData
         self.replaceOptions = mockData.replaceOptions
@@ -180,8 +180,8 @@ export default {
       })
     },
     mealTypeIcon: function(type) {
-      var map = { '鏃╅�': '馃寘', '鍗堥�': '鈽€锔?, '鏅氶�': '馃寵', '鍔犻�': '馃崻', 'breakfast': '馃寘', 'lunch': '鈽€锔?, 'dinner': '馃寵', 'snack': '馃崻' }
-      return map[type] || '馃嵔锔?
+      var map = { '鏃╅�': '馃寘', '鍗堥�': '鈽€锔�', '鏅氶�': '馃寵', '鍔犻�': '馃崻', 'breakfast': '馃寘', 'lunch': '鈽€锔�', 'dinner': '馃寵', 'snack': '馃崻' }
+      return map[type] || '馃嵔锔�'
     },
     goBack: function() { uni.navigateBack() }
   }

+ 8 - 8
cfc-frontend/pages/body/sleep-record.vue

@@ -1,14 +1,14 @@
 <template>
   <view class="sleep-container">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�返回</text>
+      <text class="nav-back" @click="goBack">‹ 返回</text>
       <text class="nav-title">作�记录</text>
       <view class="nav-placeholder"></view>
     </view>
 
     <!-- �员选择 -->
     <view class="member-selector-card">
-      <text class="member-label">记录�/text>
+      <text class="member-label">记录人</text>
       <picker mode="selector" :range="memberOptions" :value="selectedMemberIndex" @change="onMemberChange">
         <view class="picker-display">{{ memberOptions[selectedMemberIndex] }}</view>
       </picker>
@@ -40,7 +40,7 @@
       </view>
       <view class="input-row">
         <text class="input-label">备注</text>
-        <input class="input-field" v-model="remark" placeholder="�� />
+        <input class="input-field" v-model="remark" placeholder="�选" />
       </view>
       <view class="submit-btn" @click="submitSleep">�存记录</view>
     </view>
@@ -69,7 +69,7 @@
         <view class="history-item" v-for="item in sleepHistory" :key="item.id">
           <view class="history-info">
             <text class="history-date">{{ item.createdAt ? item.createdAt.substring(0,10) : '' }}</text>
-            <text class="history-detail">{{ item.sleepTime ? item.sleepTime.substring(11,16) : '--' }} �{{ item.wakeTime ? item.wakeTime.substring(11,16) : '--' }}</text>
+            <text class="history-detail">{{ item.sleepTime ? item.sleepTime.substring(11,16) : '--' }} â†{{ item.wakeTime ? item.wakeTime.substring(11,16) : '--' }}</text>
           </view>
           <view class="history-quality">
             <text>{{ getQualityEmoji(item.qualityScore) }}</text>
@@ -93,7 +93,7 @@ export default {
     return {
       childId: null,
       selectedMemberIndex: 0,
-      memberOptions: ['我自�],
+      memberOptions: ['我自己'],
       memberIds: [],
       sleepTime: '',
       wakeTime: '',
@@ -106,7 +106,7 @@ export default {
       qualityOptions: [
         { label: '很好', value: 'excellent', emoji: '😴' },
         { label: '还行', value: 'good', emoji: '🙂' },
-        { label: '一�, value: 'fair', emoji: '�' },
+        { label: '一般', value: 'fair', emoji: '�' },
         { label: '很差', value: 'poor', emoji: '😫' }
       ]
     }
@@ -122,7 +122,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.childId })
-          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() {})
     },
@@ -159,7 +159,7 @@ export default {
         data.childId = this.childId
         data.memberId = this.childId
       }
-      uni.showLoading({ title: '�存�..' })
+      uni.showLoading({ title: '�存中...' })
       healthRequest('/api/health/sleep/create', data).then(function() {
         uni.hideLoading()
         uni.showToast({ title: '�存�功', icon: 'success' })

+ 4 - 4
cfc-frontend/pages/body/water-record.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="water-container">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">��?返回</text>
+      <text class="nav-back" @click="goBack">返回</text>
       <text class="nav-title">饮水记录</text>
       <view class="nav-placeholder"></view>
     </view>
@@ -24,7 +24,7 @@
         <text class="quick-btn" @click="addWater(500)">+500ml</text>
       </view>
       <view class="input-row">
-        <text class="input-label">自定��?/text>
+        <text class="input-label">自定义</text>
         <input class="input-field" v-model="customAmount" type="number" placeholder="输入ml" />
         <text class="input-unit" @click="addWater(parseInt(customAmount))">添加</text>
       </view>
@@ -38,7 +38,7 @@
           <text class="record-amount">{{ r.amountMl }}ml</text>
           <text class="record-time">{{ r.createdAt ? r.createdAt.substring(11,16) : '' }}</text>
         </view>
-        <view class="record-empty" v-if="todayRecords.length === 0"><text>今天还没喝水,快去喝水吧��?/text></view>
+        <view class="record-empty" v-if="todayRecords.length === 0"><text>今天还没喝水,快去喝水吧!</text></view>
       </view>
     </view>
 
@@ -84,7 +84,7 @@ export default {
   methods: {
     addWater: function(ml) {
       if (!ml || ml <= 0) return
-      uni.showLoading({ title: '记录��?..' })
+      uni.showLoading({ title: '记录中...' })
       healthRequest('/api/health/water/create', {
         childId: this.childId,
         memberId: this.childId,

+ 6 - 6
cfc-frontend/pages/butler/apply.vue

@@ -8,11 +8,11 @@
     <view class="form">
       <view class="form-item">
         <text class="label">�笔�憪枏�</text>
-        <input class="input" v-model="formData.realName" placeholder="霂瑁��亦�摰𧼮��? />
+        <input class="input" v-model="formData.realName" placeholder="霂瑁��亦�摰𧼮���" />
       </view>
 
       <view class="form-item">
-        <text class="label">�𧢲㦤�?/text>
+        <text class="label">�𧢲㦤��</text>
         <input class="input" v-model="formData.phone" type="number" placeholder="霂瑁��交��箏噡" maxlength="11" />
       </view>
 
@@ -22,7 +22,7 @@
           <view class="picker">
             <text v-if="formData.tier">{{ getTierLabel(formData.tier) }}</text>
             <text v-else class="placeholder">霂琿�㗇𥋘蝞∪振蝑厩漣</text>
-            <text class="arrow">�?/text>
+            <text class="arrow">��</text>
           </view>
         </picker>
       </view>
@@ -34,7 +34,7 @@
       </view>
 
       <button class="btn-submit" :disabled="submitting" @click="handleSubmit">
-        {{ submitting ? '�𣂷漱銝?..' : '�𣂷漱�唾窈' }}
+        {{ submitting ? '�𣂷漱銝�...' : '�𣂷漱�唾窈' }}
       </button>
     </view>
   </view>
@@ -71,7 +71,7 @@ export default {
     },
     async handleSubmit() {
       if (!this.formData.realName) {
-        uni.showToast({ title: '霂瑁��亦�摰𧼮��?, icon: 'none' })
+        uni.showToast({ title: '霂瑁��亦�摰𧼮���', icon: 'none' })
         return
       }
       if (!this.formData.phone) {
@@ -87,7 +87,7 @@ export default {
         if (res.code === 200) {
           uni.showModal({
             title: '�唾窈�𣂼�',
-            content: '�函�蝞∪振�唾窈撌脫�鈭歹�霂瑞�敺�恣�?,
+            content: '�函�蝞∪振�唾窈撌脫�鈭歹�霂瑞�敺�恣��',
             showCancel: false,
             success: () => uni.navigateBack()
           })

+ 8 - 8
cfc-frontend/pages/child/rewards.vue

@@ -1,8 +1,8 @@
 <template>
   <view class="container">
-    <!-- 退出切�按�-->
+    <!-- 退出切�按钮 -->
     <view class="exit-switch" v-if="isSwitchedChild" @click="exitSwitch">
-      <text>🔄 退出切�/text>
+      <text>🔄 退出切�</text>
     </view>
     
     <view class="reward-list" v-if="rewards.length > 0">
@@ -18,7 +18,7 @@
     </view>
 
     <view class="empty" v-else>
-      <text>暂无心愿�,快去添加�/text>
+      <text>暂无心愿�,快去添加�</text>
     </view>
 
     <button class="btn-primary add-btn" @click="showAddModal = true">+ 添加心愿</button>
@@ -28,7 +28,7 @@
         <view class="modal-title">添加心愿</view>
         <view class="form-item">
           <view class="form-label">心愿�称 <text class="required">*</text></view>
-          <input v-model="newReward.title" placeholder="请输入心愿�� />
+          <input v-model="newReward.title" placeholder="请输入心愿�称" />
         </view>
         <view class="form-tip">
           <text>孩�创建心愿�,需�家长填写所需积分�能生效</text>
@@ -78,12 +78,12 @@ export default {
         const res = await getWishlist(currentChild.id)
         this.rewards = res.data || []
       } catch (e) {
-        console.error('加载心愿�失�, e)
+        console.error('加载心愿�失败', e)
       }
     },
     async createChildReward() {
       if (!this.newReward.title) {
-        uni.showToast({ title: '请填写心愿��, icon: 'none' })
+        uni.showToast({ title: '请填写心愿�称', icon: 'none' })
         return
       }
       try {
@@ -100,8 +100,8 @@ export default {
       if (!this.isSwitchedChild) return
       
       uni.showModal({
-        title: '退出切�,
-        content: '请输入家长密�以确认退�,
+        title: '退出切�',
+        content: '请输入家长密�以确认退出',
         editable: true,
         success: async (res) => {
           if (res.confirm && res.content) {

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

@@ -1,12 +1,12 @@
 <template>
   <view class="page-bg">
-    <!-- 退出切�(家长切�到孩�状�时显示�-->
+    <!-- 退出切æ�¢ï¼ˆå®¶é•¿åˆ‡æ�¢åˆ°å­©å­�状æ€�时显示ï¼-->
     <view class="exit-switch" v-if="isSwitchedChild" @click="exitSwitch">
       <text class="exit-switch__icon">🔄</text>
-      <text class="exit-switch__text">退出切�/text>
+      <text class="exit-switch__text">退出切�</text>
     </view>
 
-    <!-- 顶部标签�-->
+    <!-- 顶部标签æ -->
     <view class="tab-bar clay-card">
       <view
         v-for="tab in tabs"
@@ -21,8 +21,8 @@
       </view>
     </view>
 
-    <!-- 加载状�-->
-    <BaseLoading :loading="loading" text="�助�正在准备任�.." />
+    <!-- 加载状æ€-->
+    <BaseLoading :loading="loading" text="�助�正在准备任务..." />
 
     <!-- 任务列表 -->
     <view class="task-list" v-if="!loading && filteredTasks.length > 0">
@@ -40,7 +40,7 @@
             'task-card--completing': completingTaskId === task.id
           }"
         >
-          <!-- 完�时庆���-->
+          <!-- 完�时庆��罩 -->
           <view class="task-card__celebrate" v-if="completingTaskId === task.id">
             <text class="task-card__celebrate-icon">🎉</text>
           </view>
@@ -56,26 +56,26 @@
               <view class="task-title">{{ task.title }}</view>
               <view class="task-meta">
                 <BaseBadge variant="warning" size="xs">
-                  <text class="points-text">+{{ task.points }} â­?/text>
+                  <text class="points-text">+{{ task.points }} â­�</text>
                 </BaseBadge>
                 <text
                   class="task-time"
                   v-if="task.status === 'pending' && !getIsOverdue(task)"
                 >
-                  �{{ getTimeLeft(task) }}
+                  � {{ getTimeLeft(task) }}
                 </text>
                 <text
                   class="task-time task-time--overdue"
                   v-if="getIsOverdue(task)"
                 >
-                  �已超时{{ getOverdueDays(task) }}
+                  � 已超时{{ getOverdueDays(task) }}
                 </text>
               </view>
             </view>
 
             <!-- �侧�作 -->
             <view class="task-action">
-              <!-- 待完�任�-->
+              <!-- 待完�任务 -->
               <template v-if="task.status === 'pending' && !getIsOverdue(task)">
                 <PlayfulButton
                   variant="clay"
@@ -83,25 +83,25 @@
                   :disabled="completingTaskId === task.id"
                   @click="handleTaskClick(task)"
                 >
-                  <text v-if="task.category === '�游�类'">🎮 开始游�/text>
-                  <text v-else>�完��</text>
+                  <text v-if="task.category === '�游�类'">🎮 开始游�</text>
+                  <text v-else>✅ 完�了!</text>
                 </PlayfulButton>
               </template>
 
-              <!-- 已超时且未完�的任务,显示已超时状�-->
+              <!-- 已超时且未完æˆ�的任务,显示已超时状æ€-->
               <view
                 class="status-badge status-badge--overdue"
                 v-if="getIsOverdue(task) && task.status !== 'completed'"
               >
-                <text class="status-badge__text">�已超�/text>
+                <text class="status-badge__text">� 已超时</text>
               </view>
 
-              <!-- 已完�任�-->
+              <!-- 已完�任务 -->
               <view
                 class="status-badge status-badge--completed"
                 v-if="task.status === 'completed'"
               >
-                <text class="status-badge__text">�已完�/text>
+                <text class="status-badge__text">✅ 已完�</text>
               </view>
             </view>
           </view>
@@ -109,7 +109,7 @@
       </view>
     </view>
 
-    <!-- 空状�-->
+    <!-- 空状æ€-->
     <view class="empty-wrapper" v-if="!loading && filteredTasks.length === 0">
       <BaseEmpty
         :icon="emptyIcon"
@@ -157,9 +157,9 @@ export default {
         }
       }
       return [
-        { key: 'pending', label: '📋 待完�, count: pending },
-        { key: 'completed', label: '�已完�, count: completed },
-        { key: 'overdue', label: '�已超�, count: overdue }
+        { key: 'pending', label: '📋 待完�', count: pending },
+        { key: 'completed', label: '✅ 已完�', count: completed },
+        { key: 'overdue', label: '� 已超时', count: overdue }
       ]
     },
     filteredTasks() {
@@ -193,9 +193,9 @@ export default {
     },
     emptyTitle() {
       var titles = {
-        pending: '暂无待完�任�,
-        completed: '还没有已完�的任�,
-        overdue: '太棒了,没有超时任务�
+        pending: '暂无待完�任务',
+        completed: '还没有已完�的任务',
+        overdue: '太棒了,没有超时任务�'
       }
       return titles[this.activeTab] || ''
     },
@@ -281,17 +281,17 @@ export default {
     },
     getCategoryIcon(category) {
       var icons = {
-        '学习�: '📚',
-        '生活�: '�',
-        '�动�: '�,
+        '学习类': '📚',
+        '生活类': '�',
+        '�动类': '⚽',
         '�游�类': '🎮',
-        'å…¶ä»–': 'â­?
+        'å…¶ä»–': 'â­�'
       }
       return icons[category] || '�'
     },
     getTimeLeft(task) {
       var deadline, now, diff, hours, minutes, days
-      if (!task.deadline) return '无截止时�
+      if (!task.deadline) return '无截止时间'
       deadline = new Date(task.deadline)
       now = new Date()
       diff = deadline - now
@@ -300,7 +300,7 @@ export default {
       minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
       if (hours > 24) {
         days = Math.floor(hours / 24)
-        return '还剩 ' + days + ' �
+        return '还剩 ' + days + ' 天'
       }
       if (hours > 0) return '还剩 ' + hours + ' �时'
       if (minutes > 0) return '还剩 ' + minutes + ' 分钟'
@@ -321,7 +321,7 @@ export default {
       now = new Date()
       diff = now - deadline
       days = Math.floor(diff / (1000 * 60 * 60 * 24))
-      if (days > 0) return ' ' + days + '�
+      if (days > 0) return ' ' + days + '天'
       hours = Math.floor(diff / (1000 * 60 * 60))
       if (hours > 0) return ' ' + hours + '�时'
       return ''
@@ -333,8 +333,8 @@ export default {
       var self = this
       if (!self.isSwitchedChild) return
       uni.showModal({
-        title: '退出切�,
-        content: '请输入家长密�以确认退�,
+        title: '退出切�',
+        content: '请输入家长密�以确认退出',
         editable: true,
         success: function(res) {
           if (res.confirm && res.content) {
@@ -379,7 +379,7 @@ export default {
 }
 
 /* =============================================
-   退出切�横�
+   退出切æ�¢æ¨ªå¹
    ============================================= */
 .exit-switch {
   display: flex;
@@ -410,7 +410,7 @@ export default {
 }
 
 /* =============================================
-   顶部标签�
+   顶部标签æ 
    ============================================= */
 .tab-bar {
   display: flex;
@@ -485,7 +485,7 @@ export default {
 }
 
 /* =============================================
-   任务�片(Claymorphism 风格�
+   任务å�¡ç‰‡ï¼ˆClaymorphism 风格ï¼
    ============================================= */
 .task-card {
   position: relative;
@@ -499,7 +499,7 @@ export default {
   transform: scale(0.98);
 }
 
-/* --- 已完�状�--- */
+/* --- 已完æˆ�状æ€--- */
 .task-card--completed {
   opacity: 0.7;
   border-color: var(--color-success, #22C55E);
@@ -508,7 +508,7 @@ export default {
     3rpx 3rpx 10rpx rgba(34, 197, 94, 0.08);
 }
 
-/* --- 超时状�--- */
+/* --- 超时状æ€--- */
 .task-card--overdue {
   border-color: var(--color-error, #EF4444);
   background: linear-gradient(145deg, #FEF2F2, #FEE2E2);
@@ -516,7 +516,7 @@ export default {
     3rpx 3rpx 10rpx rgba(239, 68, 68, 0.08);
 }
 
-/* --- 完�中动�--- */
+/* --- 完�中动画 --- */
 .task-card--completing {
   animation: cardComplete 0.6s ease forwards;
   pointer-events: none;
@@ -577,7 +577,7 @@ export default {
 }
 
 /* =============================================
-   任务内容�
+   任务内容区
    ============================================= */
 .task-content {
   flex: 1;
@@ -625,7 +625,7 @@ export default {
 }
 
 /* =============================================
-   �侧�作�
+   �侧�作区
    ============================================= */
 .task-action {
   flex-shrink: 0;
@@ -633,7 +633,7 @@ export default {
 }
 
 /* =============================================
-   状�徽�
+   状�徽章
    ============================================= */
 .status-badge {
   display: flex;
@@ -662,14 +662,14 @@ export default {
 }
 
 /* =============================================
-   空状�
+   空状æ€
    ============================================= */
 .empty-wrapper {
   padding-top: 60rpx;
 }
 
 /* =============================================
-   关键帧动�
+   关键帧动画
    ============================================= */
 @keyframes cardComplete {
   0% {

+ 16 - 16
cfc-frontend/pages/dan-assessment/report-upload.vue

@@ -16,12 +16,12 @@
           <view
             :class="['dimension-option', dimension === 'mind' ? 'active' : '']"
             @click="selectDimension('mind')">
-            <text class="dimension-name">&#x2764; 心维��?(A2)</text>
+            <text class="dimension-name">&#x2764; 心维(A2)</text>
           </view>
           <view
             :class="['dimension-option', dimension === 'wisdom' ? 'active' : '']"
             @click="selectDimension('wisdom')">
-            <text class="dimension-name">&#x1F9E0; 智维��?(B4)</text>
+            <text class="dimension-name">&#x1F9E0; 智维(B4)</text>
           </view>
         </view>
       </view>
@@ -30,7 +30,7 @@
       <view class="purchase-section" v-if="recommendedProducts.length > 0">
         <view class="purchase-header">
           <text class="purchase-icon">📦</text>
-          <text class="purchase-title">为家人购买检测服��?/text>
+          <text class="purchase-title">为家人购买检测服务</text>
         </view>
         <scroll-view class="purchase-scroll" scroll-x enable-flex show-scrollbar="false">
           <view
@@ -43,7 +43,7 @@
             <text class="purchase-name">{{ item.name }}</text>
             <text class="purchase-price">{{ formatPriceWithSymbol(item.price) }}</text>
             <view class="purchase-btn">
-              <text class="purchase-btn-text">去购��?/text>
+              <text class="purchase-btn-text">去购买</text>
             </view>
           </view>
         </scroll-view>
@@ -54,12 +54,12 @@
         <view class="upload-icon" v-else>&#x2705;</view>
         <text class="upload-text" v-if="!selectedFile">点击上传 PDF 文件</text>
         <text class="upload-text" v-else>{{ selectedFile.name }}</text>
-        <text class="upload-hint">支持 PDF 格式��?DAN 测评报告</text>
+        <text class="upload-hint">支持 PDF 格式DAN 测评报告</text>
       </view>
 
       <view class="action-bar">
         <view class="upload-btn" @click="startUpload" v-if="selectedFile">
-          <text class="upload-btn-text">上传并解��?/text>
+          <text class="upload-btn-text">上传并解析</text>
         </view>
       </view>
     </view>
@@ -68,23 +68,23 @@
     <view class="section" v-if="step === 2">
       <view class="preview-header">
         <text class="preview-title">解析预览</text>
-        <text class="preview-desc">请确认以下数据是否准��?/text>
+        <text class="preview-desc">请确认以下数据是否准确</text>
       </view>
 
       <view class="preview-card" v-if="previewData">
         <view class="preview-row">
           <text class="preview-label">维度</text>
-          <text class="preview-value">{{ dimension === 'mind' ? '心维��?(A2)' : '智维��?(B4)' }}</text>
+          <text class="preview-value">{{ dimension === 'mind' ? '心维度 (A2)' : '智维度 (B4)' }}</text>
         </view>
         <view class="preview-row">
           <text class="preview-label">解析概要</text>
-          <text class="preview-value">{{ previewData.summary || '��? }}</text>
+          <text class="preview-value">{{ previewData.summary || '无' }}</text>
         </view>
       </view>
 
-      <!-- 解析项列��?-->
+      <!-- 解析项列-->
       <view class="items-section" v-if="previewData && previewData.items && previewData.items.length > 0">
-        <text class="items-title">数据��?({{ previewData.items.length }})</text>
+        <text class="items-title">数据({{ previewData.items.length }})</text>
         <view class="item-card" v-for="(item, idx) in previewData.items" :key="idx">
           <view class="item-header">
             <text class="item-name">{{ item.name || item.code }}</text>
@@ -105,10 +105,10 @@
 
       <view class="action-bar">
         <view class="confirm-btn" @click="doConfirm" v-if="!confirming">
-          <text class="confirm-btn-text">确认并保��?/text>
+          <text class="confirm-btn-text">确认并保存</text>
         </view>
         <view class="confirm-btn disabled" v-else>
-          <text class="confirm-btn-text">保存��?..</text>
+          <text class="confirm-btn-text">保存中...</text>
         </view>
         <view class="retry-btn" @click="resetUpload">
           <text class="retry-btn-text">重新上传</text>
@@ -120,7 +120,7 @@
     <view class="section" v-if="step === 3">
       <view class="success-card">
         <text class="success-icon">&#x2705;</text>
-        <text class="success-title">报告已保��?/text>
+        <text class="success-title">报告已保存</text>
         <text class="success-desc">DAN 测评数据已更新至五维能量体系</text>
       </view>
       <view class="action-bar">
@@ -133,7 +133,7 @@
     <!-- Loading -->
     <view class="loading-overlay" v-if="loading">
       <view class="loading-box">
-        <text class="loading-text">解析��?..</text>
+        <text class="loading-text">解析中...</text>
       </view>
     </view>
   </view>
@@ -180,7 +180,7 @@ export default {
           }
         },
         fail: function() {
-          // 降级:使用相��?相机
+          // 降级:使用相册/相机
           uni.chooseImage({
             count: 1,
             success: function(res) {

+ 35 - 35
cfc-frontend/pages/discover-detail/activity-detail/activity-detail.vue

@@ -1,12 +1,12 @@
 <template>
   <view class="container">
-    <!-- 加载状��?-->
+    <!-- 加载状-->
     <view v-if="loading" class="loading-wrap">
       <view class="loading-spinner"></view>
-      <text class="loading-text">加载��?..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
-    <!-- 错误状��?-->
+    <!-- 错误状-->
     <view v-else-if="error" class="error-wrap">
       <text class="error-icon">📋</text>
       <text class="error-text">{{ errorMsg }}</text>
@@ -15,7 +15,7 @@
 
     <!-- 活动内容 -->
     <scroll-view v-else-if="activity.id" scroll-y class="content">
-      <!-- 封面��?-->
+      <!-- 封面-->
       <image
         v-if="activity.coverImage"
         class="cover"
@@ -27,12 +27,12 @@
       <view class="info-section">
         <text class="activity-title">{{ activity.title }}</text>
 
-        <!-- 活动状态标��?-->
+        <!-- 活动状态标-->
         <view class="status-row">
           <text class="status-tag" :class="'status-' + (activity.status || 'upcoming')">{{ statusText(activity.status) }}</text>
         </view>
 
-        <!-- 活动元信��?-->
+        <!-- 活动元信-->
         <view class="meta-list">
           <view class="meta-item" v-if="activity.startTime">
             <text class="meta-icon">🕐</text>
@@ -44,7 +44,7 @@
           </view>
           <view class="meta-item" v-if="activity.maxParticipants">
             <text class="meta-icon">👥</text>
-            <text class="meta-text">{{ activity.currentParticipants || 0 }} / {{ activity.maxParticipants }} ��?/text>
+            <text class="meta-text">{{ activity.currentParticipants || 0 }} / {{ activity.maxParticipants }} 人</text>
           </view>
           <view class="meta-item">
             <text class="meta-icon">💰</text>
@@ -52,20 +52,20 @@
           </view>
         </view>
 
-        <!-- 活动简��?-->
+        <!-- 活动简-->
         <view class="desc-section" v-if="activity.description">
           <text class="section-title">活动介绍</text>
           <text class="desc-text">{{ activity.description }}</text>
         </view>
 
-        <!-- 付费不退费说��?-->
+        <!-- 付费不退费说-->
         <view class="refund-notice" v-if="activity.price > 0">
           <text class="refund-notice-icon">⚠️</text>
-          <text class="refund-notice-text">本活动为付费活动,报名成功后不支持退��?/text>
+          <text class="refund-notice-text">本活动为付费活动,报名成功后不支持退费</text>
         </view>
       </view>
 
-      <!-- 底部操作��?-->
+      <!-- 底部操作-->
       <view class="bottom-bar">
         <view class="price-info">
           <text class="bottom-type">活动</text>
@@ -80,8 +80,8 @@
             :disabled="registrationLoading || paying"
             @click="onRegister"
           >
-            <text v-if="registrationLoading">报名��?..</text>
-            <text v-else-if="paying">支付��?..</text>
+            <text v-if="registrationLoading">报名中...</text>
+            <text v-else-if="paying">支付中...</text>
             <text v-else-if="activity.price > 0">¥{{ activity.price }} 立即报名</text>
             <text v-else>立即报名</text>
           </button>
@@ -92,7 +92,7 @@
             class="btn-register-done"
             disabled
           >
-            <text>报名待审��?/text>
+            <text>报名待审核</text>
           </button>
           
           <!-- 已报名可取消 -->
@@ -113,8 +113,8 @@
             :disabled="checkinLoading || checkinDone"
             @click="onCheckin"
           >
-            <text v-if="checkinLoading">签到��?..</text>
-            <text v-else-if="checkinDone">已签��?��?/text>
+            <text v-if="checkinLoading">签到中...</text>
+            <text v-else-if="checkinDone">已签到 ✓</text>
             <text v-else>签到</text>
           </button>
         </view>
@@ -123,16 +123,16 @@
       <!-- 能量扣减提示弹窗 -->
       <modal v-if="showPenaltyModal" class="penalty-modal" :show="showPenaltyModal" @close="showPenaltyModal = false">
         <view class="penalty-content">
-          <text class="penalty-title">签到成功但已扣能��?/text>
-          <text class="penalty-desc">您未报名参加此活动,已被扣除 {{ penaltyAmount }} 点能量��?/text>
+          <text class="penalty-title">签到成功但已扣能量</text>
+          <text class="penalty-desc">您未报名参加此活动,已被扣除 {{ penaltyAmount }} 点能量值</text>
           <button class="penalty-btn" @click="showPenaltyModal = false">我知道了</button>
         </view>
       </modal>
     </scroll-view>
 
-    <!-- 空状��?-->
+    <!-- 空状-->
     <view v-else class="empty-wrap">
-      <text class="empty-text">活动不存在或已下��?/text>
+      <text class="empty-text">活动不存在或已下架</text>
     </view>
   </view>
 </template>
@@ -187,7 +187,7 @@ export default {
       var h12 = hour % 12
       if (h12 === 0) h12 = 12
       var minStr = minute < 10 ? '0' + minute : minute
-      return year + '��? + month + '��? + day + '��?' + ampm + h12 + ':' + minStr
+      return year + '年' + month + '月' + day + '日 ' + ampm + h12 + ':' + minStr
     },
     loadDetail: function(id) {
       var self = this
@@ -225,14 +225,14 @@ export default {
       })
     },
     statusText: function(status) {
-      var map = { draft: '草稿', published: '进行��?, ended: '已结��? }
+      var map = { draft: '草稿', published: '进行中', ended: '已结束' }
       return map[status] || '未知'
     },
     onCheckin: function() {
       var self = this
       if (self.checkinLoading || self.checkinDone) return
 
-      // 需报名的活动:未审核通过不允许签��?
+      // 需报名的活动:未审核通过不允许签
       if (self.activity.requireRegistration === 1 && self.registrationStatus !== 'approved') {
         uni.showToast({ title: '请先报名活动', icon: 'none' })
         return
@@ -257,7 +257,7 @@ export default {
           }
           if (res.data.alreadyCompleted) {
             self.checkinDone = true
-            uni.showToast({ title: '已签��?, icon: 'success' })
+            uni.showToast({ title: '已签到', icon: 'success' })
           } else if (res.data.pointsEarned && res.data.pointsEarned > 0) {
             self.checkinDone = true
             self.checkinPoints = res.data.pointsEarned
@@ -268,7 +268,7 @@ export default {
           }
         } else {
           var msg = (res && res.message) || '签到失败'
-          // 如果是报名待审核,提示用��?
+          // 如果是报名待审核,提示用
           if (msg.indexOf('报名') !== -1 || msg.indexOf('审核') !== -1) {
             uni.showModal({ title: '提示', content: msg, showCancel: false })
           } else {
@@ -288,13 +288,13 @@ export default {
         return
       }
 
-      // 付费活动 ��?先确认支��?
+      // 付费活动 → 先确认支付
       if (self.activity && self.activity.price > 0) {
         uni.showModal({
           title: '确认报名',
           content: '该活动需支付 ¥' + self.activity.price + ',报名成功后不支持退费。是否继续?',
           confirmText: '确认支付',
-          cancelText: '再想��?,
+          cancelText: '再想想',
           success: function(confirmRes) {
             if (confirmRes.confirm) {
               self.doRegister(childId)
@@ -330,7 +330,7 @@ export default {
       var self = this
       uni.showModal({
         title: '提示',
-        content: '确定要取消报名吗��?,
+        content: '确定要取消报名吗?',
         success: function(res) {
           if (res.confirm) {
             var childId = uni.getStorageSync('currentChildId')
@@ -339,7 +339,7 @@ export default {
               self.registrationLoading = false
               if (res && res.code === 200) {
                 self.registrationStatus = null
-                uni.showToast({ title: '已取消报��?, icon: 'success' })
+                uni.showToast({ title: '已取消报名', icon: 'success' })
               } else {
                 uni.showToast({ title: (res && res.message) || '取消失败', icon: 'none' })
               }
@@ -361,7 +361,7 @@ export default {
   background: #FFF7ED;
 }
 
-/* 加载 / 错误 / 空状��?*/
+/* 加载 / 错误 / 空状*/
 .loading-wrap,
 .error-wrap,
 .empty-wrap {
@@ -404,7 +404,7 @@ export default {
   line-height: 1.5;
 }
 
-/* 内容��?*/
+/* 内容*/
 .content {
   height: 100vh;
   padding-bottom: 120rpx;
@@ -418,7 +418,7 @@ export default {
   background: #f0f0f0;
 }
 
-/* 信息��?*/
+/* 信息*/
 .info-section {
   padding: 30rpx;
 }
@@ -442,7 +442,7 @@ export default {
 .status-ended { background: #F5F5F5; color: #999; }
 .status-upcoming { background: #FFF7ED; color: #F97316; }
 
-/* 元信息列��?*/
+/* 元信息列*/
 .meta-list {
   margin-top: 24rpx;
   background: #fff;
@@ -491,7 +491,7 @@ export default {
   line-height: 1.6;
 }
 
-/* 付费不退费说��?*/
+/* 付费不退费说*/
 .refund-notice {
   margin-top: 20rpx;
   margin-left: 30rpx;
@@ -516,7 +516,7 @@ export default {
   line-height: 1.4;
 }
 
-/* 底部操作��?*/
+/* 底部操作*/
 .bottom-bar {
   position: fixed;
   left: 0;

+ 10 - 10
cfc-frontend/pages/discover-detail/product-detail/product-detail.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="container">
     <view v-if="loading" class="loading-wrap">
-      <text class="loading-text">�㰘蝸銝?..</text>
+      <text class="loading-text">�㰘蝸銝�...</text>
     </view>
     <scroll-view v-else-if="product.id" scroll-y class="content">
       <image
@@ -16,7 +16,7 @@
         </view>
         <view class="price-row">
           <text class="price">{{ formatPriceWithSymbol(product.price) }}</text>
-          <text v-if="product.memberPrice" class="member-price">隡𡁜�隞?{{ formatPriceWithSymbol(product.memberPrice) }}</text>
+          <text v-if="product.memberPrice" class="member-price">隡𡁜�隞{{ formatPriceWithSymbol(product.memberPrice) }}</text>
         </view>
         <view class="meta-row">
           <text class="meta-item" v-if="product.productType">{{ typeLabel }}</text>
@@ -46,14 +46,14 @@
         </view>
         <view class="action-btns">
           <view class="action-extra">
-            <button class="btn-cart" @click="onAddToCart">�惩�韐剔�頧?/button>
+            <button class="btn-cart" @click="onAddToCart">�惩�韐剔�頧�</button>
           </view>
           <button class="btn-buy" @click="onBuy">蝡见朖韐凋僭</button>
         </view>
       </view>
     </scroll-view>
     <view v-else class="empty-wrap">
-      <text class="empty-text">���銝滚��冽�撌脖��?/text>
+      <text class="empty-text">���銝滚��冽�撌脖���</text>
     </view>
   </view>
 </template>
@@ -97,7 +97,7 @@ export default {
   },
   methods: {
     onImageError(e) {
-      // �曄��㰘蝸憭梯揖�塚�雿輻鍂�牐��橘�default-activity.png 撌脣��其� static/嚗?
+      // �曄��㰘蝸憭梯揖�塚�雿輻鍂�牐��橘�default-activity.png 撌脣��其� static/嚗
       this.product.coverImage = '/static/default-activity.png'
     },
     loadDetail(id) {
@@ -117,7 +117,7 @@ export default {
         uni.navigateTo({ url: '/pages/login/login' })
         return
       }
-      // 頝唾蓮蝏梶�憿菟𢒰嚗䔶��鍦���縑�?
+      // 頝唾蓮蝏梶�憿菟𢒰嚗䔶��鍦���縑�
       const price = this.product.price
       const productData = {
         productId: this.product.id,
@@ -126,7 +126,7 @@ export default {
         unitPrice: price,
         quantity: 1
       }
-      // ����典� storage嚗稪heckout 憿菟𢒰隡朞粉�?
+      // ����典� storage嚗稪heckout 憿菟𢒰隡朞粉�
       uni.setStorageSync('checkoutItems', [productData])
       uni.navigateTo({
         url: '/pages/shop/checkout/checkout?from=product&id=' + this.product.id
@@ -138,7 +138,7 @@ export default {
         uni.navigateTo({ url: '/pages/login/login' })
         return
       }
-      uni.showLoading({ title: '�惩�韐剔�頧?..' })
+      uni.showLoading({ title: '�惩�韐剔�頧�...' })
       cartAdd({
         userId: userId,
         productId: this.product.id,
@@ -148,7 +148,7 @@ export default {
         if (res.code === 200) {
           uni.showToast({ title: '撌脣��亥揚�抵膠', icon: 'success' })
         } else {
-          uni.showToast({ title: res.message || '�惩�韐剔�頧血仃韐?, icon: 'none' })
+          uni.showToast({ title: res.message || '�惩�韐剔�頧血仃韐�', icon: 'none' })
         }
       }).catch(() => {
         uni.hideLoading()
@@ -156,7 +156,7 @@ export default {
       })
     },
     doPay(orderNo) {
-      uni.showLoading({ title: '�臭�銝?..' })
+      uni.showLoading({ title: '�臭�銝�...' })
       productOrderPay({ orderNo }).then(res => {
         uni.hideLoading()
         if (res.code === 200) {

+ 41 - 41
cfc-frontend/pages/discover/activity-detail/activity-detail.vue

@@ -1,12 +1,12 @@
 <template>
   <view class="container">
-    <!-- 加载状��?-->
+    <!-- 加载状-->
     <view v-if="loading" class="loading-wrap">
       <view class="loading-spinner"></view>
-      <text class="loading-text">加载��?..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
-    <!-- 错误状��?-->
+    <!-- 错误状-->
     <view v-else-if="error" class="error-wrap">
       <text class="error-icon">📋</text>
       <text class="error-text">{{ errorMsg }}</text>
@@ -15,7 +15,7 @@
 
     <!-- 活动内容 -->
     <scroll-view v-else-if="activity.id" scroll-y class="content">
-      <!-- 封面��?-->
+      <!-- 封面-->
       <image
         v-if="activity.coverImage"
         class="cover"
@@ -27,12 +27,12 @@
       <view class="info-section">
         <text class="activity-title">{{ activity.title }}</text>
 
-        <!-- 活动状态标��?-->
+        <!-- 活动状态标-->
         <view class="status-row">
           <text class="status-tag" :class="'status-' + (activity.status || 'upcoming')">{{ statusText(activity.status) }}</text>
         </view>
 
-        <!-- 活动元信��?-->
+        <!-- 活动元信-->
         <view class="meta-list">
           <view class="meta-item" v-if="activity.startTime">
             <text class="meta-icon">🕐</text>
@@ -44,7 +44,7 @@
           </view>
           <view class="meta-item" v-if="activity.maxParticipants">
             <text class="meta-icon">👥</text>
-            <text class="meta-text">{{ activity.currentParticipants || 0 }} / {{ activity.maxParticipants }} ��?/text>
+            <text class="meta-text">{{ activity.currentParticipants || 0 }} / {{ activity.maxParticipants }} 人</text>
           </view>
           <view class="meta-item">
             <text class="meta-icon">💰</text>
@@ -52,27 +52,27 @@
           </view>
         </view>
 
-        <!-- 活动简��?-->
+        <!-- 活动简-->
         <view class="desc-section" v-if="activity.description">
           <text class="section-title">活动介绍</text>
           <text class="desc-text">{{ activity.description }}</text>
         </view>
 
-        <!-- 付费不退费说��?-->
+        <!-- 付费不退费说-->
         <view class="refund-notice" v-if="hasPrice">
           <text class="refund-notice-icon">⚠️</text>
-          <text class="refund-notice-text">本活动为付费活动,报名成功后不支持退��?/text>
+          <text class="refund-notice-text">本活动为付费活动,报名成功后不支持退费</text>
         </view>
       </view>
 
-      <!-- 底部操作��?-->
+      <!-- 底部操作-->
       <view class="bottom-bar">
         <view class="price-info">
           <text class="bottom-type">活动</text>
           <text class="bottom-vendor" v-if="activity.vendorName">{{ activity.vendorName }}</text>
         </view>
         <view class="action-btns">
-          <!-- 未报��?��?显示报名按钮 -->
+          <!-- 未报名 → 显示报名按钮 -->
           <button
             v-if="!registrationStatus && activity.requireRegistration !== 0"
             class="btn-register"
@@ -80,8 +80,8 @@
             :disabled="registrationLoading || paying"
             @click="onRegister"
           >
-            <text v-if="registrationLoading">报名��?..</text>
-            <text v-else-if="paying">支付��?..</text>
+            <text v-if="registrationLoading">报名中...</text>
+            <text v-else-if="paying">支付中...</text>
             <text v-else-if="hasPrice">¥{{ activity.price }} 立即报名</text>
             <text v-else>立即报名</text>
           </button>
@@ -92,17 +92,17 @@
             class="btn-register-done"
             disabled
           >
-            <text>审核��?/text>
+            <text>审核中</text>
           </button>
 
-          <!-- 已报名(approved)→ 显示"已报��? + "签到" -->
+          <!-- 已报名(approved)→ 显示"已报名" + "签到" -->
           <template v-if="registrationStatus === 'approved'">
             <button
               class="btn-registered"
               :disabled="registrationLoading"
               @click="onCancelRegistration"
             >
-              <text>已报��?/text>
+              <text>已报名</text>
             </button>
             <button
               class="btn-checkin"
@@ -110,27 +110,27 @@
               :disabled="checkinLoading || checkinDone"
               @click="onCheckin"
             >
-              <text v-if="checkinLoading">签到��?..</text>
-              <text v-else-if="checkinDone">已签��?��?/text>
+              <text v-if="checkinLoading">签到中...</text>
+              <text v-else-if="checkinDone">已签到 ✓</text>
               <text v-else>签到</text>
             </button>
           </template>
 
-          <!-- 已签到(无报名流程的活动��?-->
+          <!-- 已签到(无报名流程的活动-->
           <button
             v-if="registrationStatus === 'approved' && checkinDone"
             class="btn-checkin btn-checkin-done"
             disabled
           >
-            <text>已签��?��?/text>
+            <text>已签到 ✓</text>
           </button>
         </view>
       </view>
     </scroll-view>
 
-    <!-- 空状��?-->
+    <!-- 空状-->
     <view v-else class="empty-wrap">
-      <text class="empty-text">活动不存在或已下��?/text>
+      <text class="empty-text">活动不存在或已下架</text>
     </view>
   </view>
 </template>
@@ -138,7 +138,7 @@
 <script>
 import { getActivityDetail, activityCheckin, registerActivity, getMyActivityRegistrations, cancelActivityRegistration } from '@/utils/api.js'
 
-var WEEKDAYS = ['星期��?, '星期一', '星期��?, '星期��?, '星期��?, '星期��?, '星期��?]
+var WEEKDAYS = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
 
 export default {
   data() {
@@ -192,7 +192,7 @@ export default {
       var h12 = hour % 12
       if (h12 === 0) h12 = 12
       var minStr = minute < 10 ? '0' + minute : minute
-      return year + '��? + month + '��? + day + '��?' + ampm + h12 + ':' + minStr
+      return year + '年' + month + '月' + day + '日 ' + ampm + h12 + ':' + minStr
     },
 
     // ===== 数据加载 =====
@@ -204,7 +204,7 @@ export default {
         self.loading = false
         if (res && res.code === 200 && res.data) {
           self.activity = res.data
-          // 加载详情后检查报名状��?
+          // 加载详情后检查报名状
           self.loadRegistrationStatus(id)
         } else {
           self.error = true
@@ -217,7 +217,7 @@ export default {
       })
     },
     statusText: function(status) {
-      var map = { draft: '草稿', published: '进行��?, ended: '已结��? }
+      var map = { draft: '草稿', published: '进行中', ended: '已结束' }
       return map[status] || '未知'
     },
 
@@ -257,13 +257,13 @@ export default {
         return
       }
 
-      // 付费活动 ��?先确认支��?
+      // 付费活动 → 先确认支付
       if (self.hasPrice) {
         uni.showModal({
           title: '确认报名',
           content: '该活动需支付 ¥' + self.activity.price + ',报名成功后不支持退费。是否继续?',
           confirmText: '确认支付',
-          cancelText: '再想��?,
+          cancelText: '再想想',
           success: function(confirmRes) {
             if (confirmRes.confirm) {
               self.doRegister(childId)
@@ -271,12 +271,12 @@ export default {
           }
         })
       } else {
-        // 免费活动 ��?直接报名
+        // 免费活动 直接报名
         uni.showModal({
           title: '确认报名',
           content: '确认报名该活动?',
           confirmText: '立即报名',
-          cancelText: '再想��?,
+          cancelText: '再想想',
           success: function(confirmRes) {
             if (confirmRes.confirm) {
               self.doRegister(childId)
@@ -302,7 +302,7 @@ export default {
           self.registrationStatus = 'pending'
           self.registrationId = res.data && res.data.id
           uni.showToast({ title: '报名成功', icon: 'success' })
-          // 重新加载详情获取最新人��?
+          // 重新加载详情获取最新人
           self.loadDetail(self.activityId)
         } else {
           msg = (res && res.message) || '报名失败'
@@ -320,7 +320,7 @@ export default {
 
       uni.showModal({
         title: '取消报名',
-        content: '确定取消报名��?,
+        content: '确定取消报名?',
         confirmText: '确认取消',
         confirmColor: '#EF4444',
         success: function(confirmRes) {
@@ -339,7 +339,7 @@ export default {
         if (res && res.code === 200) {
           self.registrationStatus = ''
           self.registrationId = null
-          uni.showToast({ title: '已取消报��?, icon: 'success' })
+          uni.showToast({ title: '已取消报名', icon: 'success' })
           // 重新加载详情
           self.loadDetail(self.activityId)
         } else {
@@ -370,7 +370,7 @@ export default {
         if (res && res.code === 200 && res.data) {
           if (res.data.alreadyCompleted) {
             self.checkinDone = true
-            uni.showToast({ title: '已签��?, icon: 'success' })
+            uni.showToast({ title: '已签到', icon: 'success' })
           } else if (res.data.pointsEarned && res.data.pointsEarned > 0) {
             self.checkinDone = true
             self.checkinPoints = res.data.pointsEarned
@@ -398,7 +398,7 @@ export default {
   background: #FFF7ED;
 }
 
-/* 加载 / 错误 / 空状��?*/
+/* 加载 / 错误 / 空状*/
 .loading-wrap,
 .error-wrap,
 .empty-wrap {
@@ -441,7 +441,7 @@ export default {
   line-height: 1.5;
 }
 
-/* 内容��?*/
+/* 内容*/
 .content {
   height: 100vh;
   padding-bottom: 120rpx;
@@ -455,7 +455,7 @@ export default {
   background: #f0f0f0;
 }
 
-/* 信息��?*/
+/* 信息*/
 .info-section {
   padding: 30rpx;
 }
@@ -479,7 +479,7 @@ export default {
 .status-ended { background: #F5F5F5; color: #999; }
 .status-upcoming { background: #FFF7ED; color: #F97316; }
 
-/* 元信息列��?*/
+/* 元信息列*/
 .meta-list {
   margin-top: 24rpx;
   background: #fff;
@@ -528,7 +528,7 @@ export default {
   line-height: 1.6;
 }
 
-/* 付费不退费说��?*/
+/* 付费不退费说*/
 .refund-notice {
   margin-top: 20rpx;
   background: #FEF2F2;
@@ -550,7 +550,7 @@ export default {
   line-height: 1.4;
 }
 
-/* 底部操作��?*/
+/* 底部操作*/
 .bottom-bar {
   position: fixed;
   left: 0;

+ 14 - 14
cfc-frontend/pages/discover/index.vue

@@ -2,7 +2,7 @@
   <view class="discover-container">
     <!-- ���憭湧� -->
     <PageBanner theme="home"
-      tagline="摰嗅滬�亙熒�鞾鵭靽曹��?
+      tagline="摰嗅滬�亙熒�鞾鵭靽曹���"
       quote="蝏坔�摰嗥�銝�蝡坔�撟貊��鞉�" />
 
     <!-- 鈭磰�瘝嗵�憸�� -->
@@ -12,7 +12,7 @@
     <view class="recommend-section">
       <view class="section-header">
         <text class="section-title">�𤣳 �剝秄�刻�</text>
-        <text class="section-more" @click="goShop">�亦��游� �?/text>
+        <text class="section-more" @click="goShop">�亦��游� ��</text>
       </view>
       <scroll-view scroll-x enable-flex show-scrollbar="false" class="type-filter-scroll">
         <view
@@ -25,10 +25,10 @@
         </view>
       </scroll-view>
       <view v-if="loading" class="loading-state">
-        <text class="loading-text">�㰘蝸銝?..</text>
+        <text class="loading-text">�㰘蝸銝�...</text>
       </view>
       <view v-else-if="products.length === 0" class="empty-state">
-        <text class="empty-text">������嚗�縧����讠��?/text>
+        <text class="empty-text">������嚗�縧����讠���</text>
       </view>
       <view v-else class="product-grid">
         <view
@@ -54,11 +54,11 @@
       <view class="member-card-bg">
         <text class="member-card-icon">��</text>
         <view class="member-card-texts">
-          <text class="member-card-title">撘��𡁜振摨凋��?/text>
-          <text class="member-card-desc">鈭思�撅墧��?繚 �鞾鵭�滚𦛚 繚 閫����紡</text>
+          <text class="member-card-title">撘��𡁜振摨凋���</text>
+          <text class="member-card-desc">鈭思�撅墧��繚 �鞾鵭�滚𦛚 繚 閫����紡</text>
         </view>
         <view class="member-card-action">
-          <text class="member-card-btn">蝡见朖撘��?/text>
+          <text class="member-card-btn">蝡见朖撘���</text>
         </view>
       </view>
     </view>
@@ -67,7 +67,7 @@
     <view class="article-section">
       <view class="section-header">
         <text class="section-title">�� �亥�銝剖�</text>
-        <text class="section-more" @click="goKnowledgeCenter">�亦��券� �?/text>
+        <text class="section-more" @click="goKnowledgeCenter">�亦��券� ��</text>
       </view>
       <view class="article-list">
         <view v-for="(item, index) in featuredArticles" :key="item.id" class="article-card" @click="goArticleDetail(item.id)">
@@ -83,10 +83,10 @@
       </view>
     </view>
 
-    <!-- 銝箔��㗇𥋘瘚㰘𪄳蝳?-->
+    <!-- 銝箔��㗇𥋘瘚㰘𪄳蝳-->
     <view class="why-section">
       <view class="section-header">
-        <text class="section-title">�働 銝箔�銋��㗇𥋘瘚㰘𪄳蝳?/text>
+        <text class="section-title">�働 銝箔�銋��㗇𥋘瘚㰘𪄳蝳�</text>
       </view>
       <view class="feature-grid">
         <view class="feature-item">
@@ -96,13 +96,13 @@
         </view>
         <view class="feature-item">
           <text class="feature-icon">��</text>
-          <text class="feature-title">蝘臬�瞈��?/text>
+          <text class="feature-title">蝘臬�瞈���</text>
           <text class="feature-desc">摰峕�隞餃𦛚敺㛖妖����烐揢敹��</text>
         </view>
         <view class="feature-item">
-          <text class="feature-icon">�𪂹�㵵�抽�㵵�把�㵵�?/text>
+          <text class="feature-icon">�𪂹�㵵�抽�㵵�把�㵵��</text>
           <text class="feature-title">摰嗅滬���</text>
-          <text class="feature-desc">�典振銝�韏瑁�霂���踵�銝�甇?/text>
+          <text class="feature-desc">�典振銝�韏瑁�霂���踵�銝�甇�</text>
         </view>
         <view class="feature-item">
           <text class="feature-icon">��</text>
@@ -115,7 +115,7 @@
     <!-- 摨閖��餃��厰僼 -->
     <view class="login-footer">
       <button class="login-btn" @click="handleLogin">�餃� / 瘜典�</button>
-      <text class="login-footer-text">�餃��唾”蝷箏��譌�羓鍂�瑕�霈柴�见��𢠃�蝘�錇蝑硔�?/text>
+      <text class="login-footer-text">�餃��唾”蝷箏��譌�羓鍂�瑕�霈柴�见��𢠃�蝘�錇蝑硔��</text>
     </view>
 
     <!-- 摨閖��牐� -->

+ 6 - 6
cfc-frontend/pages/discover/product-detail/product-detail.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="container">
     <view v-if="loading" class="loading-wrap">
-      <text class="loading-text">加载��?..</text>
+      <text class="loading-text">加载中...</text>
     </view>
     <scroll-view v-else-if="product.id" scroll-y class="content">
       <image
@@ -15,12 +15,12 @@
         </view>
         <view class="price-row">
           <text class="price">{{ formatPriceWithSymbol(displayPrice) }}</text>
-          <text v-if="product.memberPrice" class="member-price">会员��?{{ formatPriceWithSymbol(product.memberPrice) }}</text>
+          <text v-if="product.memberPrice" class="member-price">会员{{ formatPriceWithSymbol(product.memberPrice) }}</text>
         </view>
         <!-- Member upgrade banner -->
         <view v-if="showMemberBanner" class="member-banner" @click="goUpgrade">
-          <text class="member-banner-text">开通会员立��?<text class="member-banner-saving">{{ formatPriceWithSymbol(product.price - product.memberPrice) }}</text>,享会员专享��?/text>
-          <text class="member-banner-arrow">��?/text>
+          <text class="member-banner-text">开通会员立<text class="member-banner-saving">{{ formatPriceWithSymbol(product.price - product.memberPrice) }}</text>,享会员专享价</text>
+          <text class="member-banner-arrow">›</text>
         </view>
         <view v-if="effectivePpointText" class="ppoint-row">
           <text class="ppoint-label">可分配利润:</text>
@@ -79,13 +79,13 @@
             <text class="cart-icon">🛒</text>
             <text v-if="cartCount > 0" class="cart-badge">{{ cartCount > 99 ? '99+' : cartCount }}</text>
           </view>
-          <button class="btn-cart" @click="onAddToCart">加入购物��?/button>
+          <button class="btn-cart" @click="onAddToCart">加入购物车</button>
           <button class="btn-buy" @click="onBuy">立即购买</button>
         </view>
       </view>
     </scroll-view>
     <view v-else class="empty-wrap">
-      <text class="empty-text">商品不存在或已下��?/text>
+      <text class="empty-text">商品不存在或已下架</text>
     </view>
   </view>
 </template>

+ 6 - 6
cfc-frontend/pages/energy/detail.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="container">
-    <!-- 头部:维度信�-->
+    <!-- 头部:维度信� -->
     <view class="dim-header" v-if="dimInfo">
       <view class="dim-icon-wrap" :class="'dim-icon--' + elementColor">
         <text class="dim-icon">{{ dimInfo.icon }}</text>
@@ -9,12 +9,12 @@
       <text class="dim-element">{{ dimInfo.element }} · {{ dimInfo.code }}</text>
       <view class="dim-energy">
         <text class="dim-energy-value">{{ dimEnergy }}</text>
-        <text class="dim-energy-label">能��/text>
+        <text class="dim-energy-label">能�值</text>
       </view>
     </view>
 
-    <!-- 加载状�-->
-    <BaseLoading :loading="loading" text="加载�.." />
+    <!-- 加载状æ€-->
+    <BaseLoading :loading="loading" text="加载中..." />
 
     <!-- �水列表 -->
     <view class="logs-section" v-if="!loading">
@@ -35,7 +35,7 @@
         </view>
       </view>
 
-      <BaseEmpty v-if="logs.length === 0" icon="💧" title="暂无能��水" description="完�任务�以获�能�� />
+      <BaseEmpty v-if="logs.length === 0" icon="💧" title="暂无能��水" description="完�任务�以获�能�值" />
 
       <view class="load-more" v-if="hasMore" @click="loadMore">
         <text>加载更多...</text>
@@ -76,7 +76,7 @@ export default {
       this.code = options.code
       this.elementColor = ELEMENT_MAP[options.code] || 'fire'
     }
-    // 如果有传�dimData(URL编�的JSON),解�维度信�
+    // 如果有传入 dimData(URL编�的JSON),解�维度信�
     if (options.dimData) {
       try {
         var parsed = JSON.parse(decodeURIComponent(options.dimData))

+ 21 - 21
cfc-frontend/pages/family/add-member.vue

@@ -6,10 +6,10 @@
 <!-- 昵称(必填) -->
 <view class="form-item required">
 <text class="label"><text class="required-mark">*</text>�员昵称</text>
-<input class="input" v-model="form.nickname" placeholder="请输入�员昵� maxlength="20" />
+<input class="input" v-model="form.nickname" placeholder="请输入�员昵称" maxlength="20" />
 </view>
 
-<!-- 辈分关系(必填,替代关系类型�-->
+<!-- 辈分关系(必填,替代关系类型ï¼-->
 <view class="form-item required">
 <text class="label"><text class="required-mark">*</text>辈分关系</text>
 <generation-picker ref="generationPicker" v-model:generationLevel="form.generationLevel" v-model:peerType="form.peerType" :showLabel="false" />
@@ -41,9 +41,9 @@
 <view class="age-display">{{ calculatedAge || '根�出生日期自动计算' }}</view>
 </view>
 
-<!-- 出生时辰(选填�-->
+<!-- 出生时辰(选填ï¼-->
 <view class="form-item">
-<text class="label">出生时辰(选填�/text>
+<text class="label">出生时辰(选填)</text>
 <picker :range="birthHourOptions" @change="onBirthHourChange">
 <view class="picker">
 {{ form.birthHourName || '请选择出生时辰' }}
@@ -51,21 +51,21 @@
 </picker>
 </view>
 
-<!-- 出生体�(选填�-->
+<!-- 出生体é‡�(选填ï¼-->
 <view class="form-item">
-<text class="label">出生体�(选填,克�/text>
-<input class="input" type="number" v-model="form.birthWeight" placeholder="� 3500" maxlength="5" />
+<text class="label">出生体�(选填,克)</text>
+<input class="input" type="number" v-model="form.birthWeight" placeholder="如: 3500" maxlength="5" />
 </view>
 
-<!-- 出生地(选填�-->
+<!-- 出生地(选填ï¼-->
 <view class="form-item">
-<text class="label">出生地(选填�/text>
-<input class="input" v-model="form.birthPlace" placeholder="� 北京� maxlength="30" />
+<text class="label">出生地(选填)</text>
+<input class="input" v-model="form.birthPlace" placeholder="如: 北京市" maxlength="30" />
 </view>
 
-<!-- 是�剖腹产(选填�-->
+<!-- 是å�¦å‰–腹产(选填ï¼-->
 <view class="form-item">
-<text class="label">是�剖腹产(选填�/text>
+<text class="label">是�剖腹产(选填)</text>
 <picker :range="cesareanOptions" range-key="label" @change="onCesareanChange">
 <view class="picker">
 {{ form.cesareanLabel || '请选择' }}
@@ -73,9 +73,9 @@
 </picker>
 </view>
 
-<!-- 手机�(选填�-->
+<!-- 手机å�·ï¼ˆé€‰å¡«ï¼-->
 <view class="form-item">
-<text class="label">手机�(选填�/text>
+<text class="label">手机�(选填)</text>
 <input class="input" type="number" v-model="form.phone" placeholder="填写手机��关�已有账�" maxlength="11" />
 <text class="hint">若手机�已注册,将自动关�该账�</text>
 </view>
@@ -110,13 +110,13 @@ isCesarean: null,
 cesareanLabel: ''
 },
 genderOptions: [
-{ value: 'male', label: 'ç”? },
-{ value: 'female', label: '� }
+{ value: 'male', label: 'ç”·' },
+{ value: 'female', label: '女' }
 ],
-birthHourOptions: ['', '�时(23-1�', '丑时(1-3�', '寅时(3-5�', '�时(5-7�', '辰时(7-9�', '巳时(9-11�', '�时(11-13�', '未时(13-15�', '申时(15-17�', '酉时(17-19�', '戌时(19-21�', '亥时(21-23�'],
+birthHourOptions: ['', '�时(23-1点)', '丑时(1-3点)', '寅时(3-5点)', '�时(5-7点)', '辰时(7-9点)', '巳时(9-11点)', '�时(11-13点)', '未时(13-15点)', '申时(15-17点)', '酉时(17-19点)', '戌时(19-21点)', '亥时(21-23点)'],
 cesareanOptions: [
 { value: 0, label: '顺产' },
-{ value: 1, label: '剖腹� }
+{ value: 1, label: '剖腹产' }
 ],
 todayDate: ''
 }
@@ -135,7 +135,7 @@ var monthDiff = today.getMonth() - birth.getMonth()
 if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
 age--
 }
-return age >= 0 ? age + 'å²? : ''
+return age >= 0 ? age + '�' : ''
 }
 },
 onLoad() {
@@ -166,7 +166,7 @@ this.form.cesareanLabel = this.cesareanOptions[idx].label
 },
 async submit() {
 if (!this.form.nickname || !this.form.nickname.trim()) {
-uni.showToast({ title: '请输入�员昵�, icon: 'none' })
+uni.showToast({ title: '请输入�员昵称', icon: 'none' })
 return
 }
 if (!this.$refs.generationPicker || !this.$refs.generationPicker.selectedGen) {
@@ -182,7 +182,7 @@ uni.showToast({ title: '请选择出生日期', icon: 'none' })
 return
 }
 if (this.form.phone && !/^1[3-9]\d{9}$/.test(this.form.phone)) {
-uni.showToast({ title: '请输入正确的手机�, icon: 'none' })
+uni.showToast({ title: '请输入正确的手机�', icon: 'none' })
 return
 }
 

+ 1 - 1
cfc-frontend/pages/family/address-edit.vue

@@ -3,7 +3,7 @@
     <view class="page-title">家庭地�设置</view>
     
     <view class="form-section">
-      <view class="section-title">所在街�/view>
+      <view class="section-title">所在街�</view>
       <address-picker 
         v-model="formData.streetId" 
         @change="onAddressChange" 

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

@@ -1,16 +1,16 @@
 <template>
   <view class="game-container">
     <view class="game-header">
-      <text class="game-title">猜数��?/text>
+      <text class="game-title">猜数字</text>
       <view class="game-stats">
         <text>剩余次数: {{ remainingGuesses }}</text>
       </view>
     </view>
     
     <view class="instructions" v-if="!isPlaying">
-      <text class="info-text">电脑会生成一��?位不重复数字</text>
+      <text class="info-text">电脑会生成一个4位不重复数字</text>
       <text class="info-text">A = 数字和位置都正确</text>
-      <text class="info-text">B = 数字正确但位置错��?/text>
+      <text class="info-text">B = 数字正确但位置错误</text>
       <text class="info-text">请在{{ maxGuesses }}次内猜出正确答案</text>
     </view>
     
@@ -22,7 +22,7 @@
         maxlength="4" 
         placeholder="输入4位不重复数字"
       />
-      <button class="start-btn" @click="startGame">开始游��?/button>
+      <button class="start-btn" @click="startGame">开始游戏</button>
     </view>
     
     <view class="history" v-if="history.length > 0">
@@ -45,10 +45,10 @@
     
     <view class="result-modal" v-if="gameOver">
       <view class="result-content">
-        <text class="result-title">{{ isWin ? '猜对��?' : '游戏结束' }}</text>
-        <text class="result-info">答案��? {{ answer }}</text>
+        <text class="result-title">{{ isWin ? '猜对了!' : '游戏结束' }}</text>
+        <text class="result-info">答案是: {{ answer }}</text>
         <text class="result-score">获得积分: {{ score }}</text>
-        <button class="restart-btn" @click="resetGame">再玩一��?/button>
+        <button class="restart-btn" @click="resetGame">再玩一次</button>
       </view>
     </view>
   </view>
@@ -115,7 +115,7 @@ export default {
     },
     startGame() {
       if (this.userGuess.length !== 4 || !this.isUnique(this.userGuess)) {
-        uni.showToast({ title: '请输��?位不重��数��?, icon: 'none' })
+        uni.showToast({ title: '请输入4位不重复数字', icon: 'none' })
         return
       }
       this.answer = this.generateAnswer()
@@ -142,7 +142,7 @@ export default {
     },
     makeGuess() {
       if (this.userGuess.length !== 4 || !this.isUnique(this.userGuess)) {
-        uni.showToast({ title: '请输��?位不重复数字', icon: 'none' })
+        uni.showToast({ title: '请输入4位不重复数字', icon: 'none' })
         return
       }
       const result = this.checkGuess(this.userGuess)

+ 2 - 2
cfc-frontend/pages/games/list.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="container">
     <view class="header">
-      <text class="title">🎮 益智�游�/text>
+      <text class="title">🎮 益智�游�</text>
       <text class="subtitle">完�游�获得积分奖励</text>
     </view>
 
@@ -29,7 +29,7 @@
           <text class="game-desc">{{ game.description }}</text>
           <view class="game-meta">
             <text class="duration">�� {{ game.defaultDuration }}分钟</text>
-            <text class="points">�{{ game.defaultPoints }}积分</text>
+            <text class="points">â­{{ game.defaultPoints }}积分</text>
           </view>
         </view>
       </view>

+ 7 - 7
cfc-frontend/pages/games/records.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="records-container">
     <view class="header">
-      <text class="back-btn" @click="goBack">�返回</text>
+      <text class="back-btn" @click="goBack">‹ 返回</text>
       <text class="title">训练记录</text>
     </view>
 
@@ -17,7 +17,7 @@
     </view>
 
     <view v-if="loading" class="loading-state">
-      <text>加载�..</text>
+      <text>加载中...</text>
     </view>
 
     <view v-else-if="records.length === 0" class="empty-state">
@@ -35,7 +35,7 @@
           <text class="record-meta">{{ formatTime(item.playedAt) }}</text>
         </view>
         <view class="record-right">
-          <text class="score-text">{{ item.score }}�/text>
+          <text class="score-text">{{ item.score }}分</text>
           <text class="points-text">+{{ item.pointsEarned }}积分</text>
         </view>
       </view>
@@ -61,13 +61,13 @@ export default {
       loading: false,
       gameFilters: [
         { code: '', label: '全部' },
-        { code: 'schulte', label: '舒尔� },
-        { code: '1a2b', label: '猜数� },
+        { code: 'schulte', label: '舒尔特' },
+        { code: '1a2b', label: '猜数字' },
         { code: 'sudoku', label: '数独' }
       ],
       gameNameMap: {
-        'schulte': '舒尔特方�,
-        '1a2b': '猜数�,
+        'schulte': '舒尔特方格',
+        '1a2b': '猜数字',
         'sudoku': '数独'
       },
       iconMap: {

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

@@ -1,9 +1,9 @@
 <template>
   <view class="game-container">
     <view class="game-header">
-      <text class="game-title">🎯 舒尔特方��?/text>
+      <text class="game-title">🎯 舒尔特方格</text>
       <view class="game-stats">
-        <text>时间: {{ time }}��?/text>
+        <text>时间: {{ time }}秒</text>
         <text>得分: {{ score }}</text>
       </view>
     </view>
@@ -21,16 +21,16 @@
     </view>
     
     <view class="game-controls" v-if="!isPlaying">
-      <button class="start-btn" @click="startGame">开始游��?/button>
+      <button class="start-btn" @click="startGame">开始游戏</button>
       <text class="tip">请按顺序点击1-25,计时开始后不可暂停</text>
     </view>
     
     <view class="result-modal" v-if="showResult">
       <view class="result-content">
         <text class="result-title">🎉 恭喜完成!</text>
-        <text class="result-score">用时: {{ time }}��?/text>
+        <text class="result-score">用时: {{ time }}秒</text>
         <text class="result-score">获得积分: {{ score }}</text>
-        <button class="restart-btn" @click="startGame">再来一��?/button>
+        <button class="restart-btn" @click="startGame">再来一次</button>
       </view>
     </view>
   </view>
@@ -57,7 +57,7 @@ export default {
     }
   },
   onLoad(options) {
-    // 支持从任务跳转过��?
+    // 支持从任务跳转过
     if (options.taskId) {
       this.taskId = parseInt(options.taskId)
     }
@@ -71,7 +71,7 @@ export default {
   },
   methods: {
     initGrid() {
-      // 生成1-25的随机排��?
+      // 生成1-25的随机排
       let nums = []
       for (let i = 1; i <= 25; i++) {
         nums.push(i)

+ 13 - 13
cfc-frontend/pages/games/stats.vue

@@ -1,12 +1,12 @@
 <template>
   <view class="stats-container">
     <view class="header">
-      <text class="back-btn" @click="goBack">�返回</text>
+      <text class="back-btn" @click="goBack">‹ 返回</text>
       <text class="title">训练统计</text>
     </view>
 
     <view v-if="loading" class="loading-state">
-      <text>加载�..</text>
+      <text>加载中...</text>
     </view>
 
     <template v-else>
@@ -15,7 +15,7 @@
         <view class="overview-card">
           <view class="overview-item">
             <text class="overview-num">{{ stats.totalGames || 0 }}</text>
-            <text class="overview-label">总训练次�/text>
+            <text class="overview-label">总训练次数</text>
           </view>
           <view class="overview-item">
             <text class="overview-num">{{ stats.totalPoints || 0 }}</text>
@@ -28,15 +28,15 @@
         </view>
       </view>
 
-      <!-- �游�最佳��-->
+      <!-- �游�最佳�绩 -->
       <view class="section">
-        <text class="section-title">�游���/text>
+        <text class="section-title">�游��绩</text>
         <view class="best-card" v-for="item in bestScores" :key="item.game_code">
           <text class="best-icon">{{ iconMap[item.game_code] || '🎮' }}</text>
           <view class="best-info">
             <text class="best-name">{{ gameNameMap[item.game_code] || item.game_code }}</text>
             <text class="best-stats">
-              最�{{ item.best_score }}�· �{{ item.total_plays }}�· 累计 {{ item.total_points }}�
+              最佳 {{ item.best_score }}分 · 共 {{ item.total_plays }}次 · 累计 {{ item.total_points }}分
             </text>
           </view>
           <text class="best-score">{{ item.best_score }}</text>
@@ -46,9 +46,9 @@
         </view>
       </view>
 
-      <!-- 排行�-->
+      <!-- 排行榜 -->
       <view class="section">
-        <text class="section-title">游�排行�/text>
+        <text class="section-title">游�排行榜</text>
         <view class="leaderboard-tabs" v-if="gameCodes.length > 0">
           <view
             v-for="code in gameCodes"
@@ -63,11 +63,11 @@
           <view class="lb-item" v-for="(entry, idx) in leaderboard" :key="idx">
             <text :class="['lb-rank', idx < 3 ? 'top' : '']">{{ idx + 1 }}</text>
             <text class="lb-name">{{ entry.child_name || '未知' }}</text>
-            <text class="lb-score">{{ entry.score }}�/text>
+            <text class="lb-score">{{ entry.score }}分</text>
           </view>
         </view>
         <view class="no-data" v-if="leaderboard.length === 0">
-          <text>排行榜暂无数�/text>
+          <text>排行榜暂无数�</text>
         </view>
       </view>
     </template>
@@ -87,8 +87,8 @@ export default {
       currentLb: 'schulte',
       gameCodes: ['schulte', '1a2b', 'sudoku'],
       gameNameMap: {
-        'schulte': '舒尔特方�,
-        '1a2b': '猜数�,
+        'schulte': '舒尔特方格',
+        '1a2b': '猜数字',
         'sudoku': '数独'
       },
       iconMap: {
@@ -126,7 +126,7 @@ export default {
         const res = await getGameLeaderboard({ gameCode: this.currentLb, limit: 10 })
         this.leaderboard = res.data || []
       } catch (e) {
-        console.error('加载排行榜失�, e)
+        console.error('加载排行榜失败', e)
       }
     },
     onLeaderboardChange(code) {

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

@@ -3,7 +3,7 @@
     <view class="game-header">
       <text class="game-title">🔳 数独</text>
       <view class="game-stats">
-        <text>æ—¶é—´: {{ time }}ç§?/text>
+        <text>æ—¶é—´: {{ time }}ç§’</text>
       </view>
     </view>
     
@@ -50,13 +50,13 @@
     </view>
     
     <view class="controls" v-if="!isPlaying">
-      <button class="start-btn" @click="startGame">开始游�/button>
+      <button class="start-btn" @click="startGame">开始游�</button>
     </view>
     
     <view class="result-modal" v-if="showResult">
       <view class="result-content">
         <text class="result-title">🎉 数独完�!</text>
-        <text class="result-score">用时: {{ time }}�/text>
+        <text class="result-score">用时: {{ time }}秒</text>
         <text class="result-score">获得积分: {{ score }}</text>
         <button class="restart-btn" @click="resetGame">��一局</button>
       </view>
@@ -87,7 +87,7 @@ function generateSudoku(level) {
   const holes = { easy: 30, medium: 40, hard: 50 }
   const count = holes[level] || 30
   
-  // �制并打�
+  // �制并打乱
   let board = JSON.parse(JSON.stringify(base))
   
   // �机交�行和列�打乱
@@ -131,12 +131,12 @@ function checkSolution(board) {
       if (board[r][c] === 0) return false
     }
   }
-  // 检查��
+  // 检查�行
   for (let r = 0; r < 9; r++) {
     const nums = new Set(board[r])
     if (nums.size !== 9) return false
   }
-  // 检查��
+  // 检查æ¯�åˆ
   for (let c = 0; c < 9; c++) {
     const nums = new Set()
     for (let r = 0; r < 9; r++) {
@@ -144,7 +144,7 @@ function checkSolution(board) {
     }
     if (nums.size !== 9) return false
   }
-  // 检�x3宫格
+  // 检查3x3宫格
   for (let boxRow = 0; boxRow < 9; boxRow += 3) {
     for (let boxCol = 0; boxCol < 9; boxCol += 3) {
       const nums = new Set()
@@ -172,7 +172,7 @@ export default {
       score: 0,
       selectedLevel: 'easy',
       levels: [
-        { label: '简�, value: 'easy' },
+        { label: '简�', value: 'easy' },
         { label: '中等', value: 'medium' },
         { label: 'å›°éš¾', value: 'hard' }
       ],
@@ -240,7 +240,7 @@ export default {
       const { row, col } = this.selectedCell
       this.board[row][col].value = num === 0 ? '' : num
       
-      // 检查是�完�
+      // 检查是å�¦å®Œæˆ
       if (this.checkWin()) {
         this.finishGame()
       }
@@ -254,11 +254,11 @@ export default {
       this.isPlaying = false
       this.showResult = true
       
-      // 分数计算:基础�+ 时间加�
+      // 分数计算:基础åˆ+ 时间加æˆ�
       const baseScore = { easy: 60, medium: 75, hard: 90 }
       const base = baseScore[this.selectedLevel] || 60
       
-      // 用时越短加�分越�
+      // 用时越短加�分越高
       const timeBonus = Math.max(40 - Math.floor(this.time / 10), 0)
       this.score = base + timeBonus
       

+ 5 - 5
cfc-frontend/pages/growth/assessment-result.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="container">
-    <view class="loading" v-if="loading">加载�..</view>
+    <view class="loading" v-if="loading">加载中...</view>
 
     <template v-if="result">
       <view class="header-card">
@@ -8,18 +8,18 @@
       </view>
 
       <view class="score-card">
-        <text class="card-title">�维度得�/text>
+        <text class="card-title">�维度得分</text>
         <view class="score-grid">
           <view class="score-item">
-            <text class="score-label">注��/text>
+            <text class="score-label">注�力</text>
             <text class="score-value">{{ result.attentionScore || 0 }}</text>
           </view>
           <view class="score-item">
-            <text class="score-label">专注�/text>
+            <text class="score-label">专注力</text>
             <text class="score-value">{{ result.focusScore || 0 }}</text>
           </view>
           <view class="score-item">
-            <text class="score-label">记忆�/text>
+            <text class="score-label">记忆力</text>
             <text class="score-value">{{ result.memoryScore || 0 }}</text>
           </view>
           <view class="score-item">

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

@@ -29,22 +29,22 @@
         <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-arrow">鈥?/text>
+          <text class="select-arrow">鈥�</text>
         </view>
       </view>
 
       <view class="form-item">
         <text class="label">妗f�鏍囬�</text>
-        <input class="input" v-model="formData.recordTitle" placeholder="渚嬪�锛?026骞?鏈堟垚闀胯�褰? />
+        <input class="input" v-model="formData.recordTitle" placeholder="渚嬪�锛�2026骞�5鏈堟垚闀胯�褰�" />
       </view>
 
       <view class="form-row">
         <view class="form-item half">
-          <text class="label">韬�珮锛坈m锛?/text>
+          <text class="label">韬�珮锛坈m锛�</text>
           <input class="input" v-model="formData.height" type="number" placeholder="閫夊~" />
         </view>
         <view class="form-item half">
-          <text class="label">浣撻噸锛坘g锛?/text>
+          <text class="label">浣撻噸锛坘g锛�</text>
           <input class="input" v-model="formData.weight" type="number" placeholder="閫夊~" />
         </view>
       </view>
@@ -83,7 +83,7 @@
       </view>
 
       <view class="form-item">
-        <text class="label">瀛︽牎鎵€鍦ㄨ�閬?/text>
+        <text class="label">瀛︽牎鎵€鍦ㄨ�閬�</text>
         <input class="input" v-model="formData.schoolStreet" placeholder="閫夊~" />
       </view>
 
@@ -92,14 +92,14 @@
 
     <view class="redirect-section" v-if="sourceType === 'upload'">
       <view class="redirect-card">
-        <text class="redirect-desc">涓婁紶PDF鏍煎紡鐨凞AN娴嬭瘎鎶ュ憡锛岀郴缁熷皢鑷�姩瑙f瀽鎶ュ憡鍐呭�骞跺垱寤烘垚闀挎。妗堛€?/text>
+        <text class="redirect-desc">涓婁紶PDF鏍煎紡鐨凞AN娴嬭瘎鎶ュ憡锛岀郴缁熷皢鑷�姩瑙f瀽鎶ュ憡鍐呭�骞跺垱寤烘垚闀挎。妗堛€�</text>
         <button class="btn-submit" @click="goUpload">涓婁紶娴嬭瘎鎶ュ憡</button>
       </view>
     </view>
 
     <view class="redirect-section" v-if="sourceType === 'assessment'">
       <view class="redirect-card">
-        <text class="redirect-desc">璐�拱DAN娴嬭瘎鏈嶅姟鍚庯紝瑙勫垝甯堝畬鎴愭祴璇勫綍鍏ュ皢鑷�姩鍒涘缓鎴愰暱妗f�锛屾棤闇€鎵嬪姩濉�啓銆?/text>
+        <text class="redirect-desc">璐�拱DAN娴嬭瘎鏈嶅姟鍚庯紝瑙勫垝甯堝畬鎴愭祴璇勫綍鍏ュ皢鑷�姩鍒涘缓鎴愰暱妗f�锛屾棤闇€鎵嬪姩濉�啓銆�</text>
         <button class="btn-submit" @click="goPurchase">璐�拱娴嬭瘎鏈嶅姟</button>
       </view>
     </view>
@@ -116,7 +116,7 @@ export default {
       children: [],
       selectedChild: null,
       targetChildId: '',
-      gradeOptions: ['涓€骞寸骇','浜屽勾绾?,'涓夊勾绾?,'鍥涘勾绾?,'浜斿勾绾?,'鍏�勾绾?,'鍒濅竴','鍒濅簩','鍒濅笁','楂樹竴','楂樹簩','楂樹笁'],
+      gradeOptions: ['涓€骞寸骇','浜屽勾绾�','涓夊勾绾�','鍥涘勾绾�','浜斿勾绾�','鍏�勾绾�','鍒濅竴','鍒濅簩','鍒濅笁','楂樹竴','楂樹簩','楂樹笁'],
       formData: {
         childId: null,
         recordTitle: '',
@@ -145,7 +145,7 @@ export default {
   methods: {
     getCurrentDate() {
       var d = new Date()
-      return d.getFullYear() + '骞? + (d.getMonth() + 1) + '鏈?
+      return d.getFullYear() + '骞�' + (d.getMonth() + 1) + '鏈�'
     },
     async loadChildren() {
       try {
@@ -191,7 +191,7 @@ export default {
         return
       }
 
-      uni.showLoading({ title: '鍒涘缓涓?..' })
+      uni.showLoading({ title: '鍒涘缓涓�...' })
       try {
         var familyId = uni.getStorageSync('familyId')
         var submitData = {

+ 14 - 14
cfc-frontend/pages/growth/detail.vue

@@ -1,13 +1,13 @@
 <template>
   <view class="container">
-    <view class="loading" v-if="loading">加载�..</view>
+    <view class="loading" v-if="loading">加载中...</view>
 
     <template v-if="record">
       <view class="header-card">
         <view class="header-top">
           <text class="record-title">{{ record.recordTitle || '�长档案' }}</text>
           <text class="record-tag" :class="record.status === 'completed' ? 'tag-completed' : 'tag-pending'">
-            {{ record.status === 'completed' ? '已完� : '待�� }}
+            {{ record.status === 'completed' ? '已完�' : '待�步' }}
           </text>
         </view>
         <view class="header-badges">
@@ -72,27 +72,27 @@
             <text class="score-value">{{ record.overallScore }}</text>
           </view>
           <view class="score-item" v-if="record.attentionScore">
-            <text class="score-label">注��/text>
+            <text class="score-label">注�力</text>
             <text class="score-value">{{ record.attentionScore }}</text>
           </view>
           <view class="score-item" v-if="record.focusScore">
-            <text class="score-label">专注�/text>
+            <text class="score-label">专注力</text>
             <text class="score-value">{{ record.focusScore }}</text>
           </view>
           <view class="score-item" v-if="record.memoryScore">
-            <text class="score-label">记忆�/text>
+            <text class="score-label">记忆力</text>
             <text class="score-value">{{ record.memoryScore }}</text>
           </view>
           <view class="score-item" v-if="record.logicScore">
-            <text class="score-label">逻辑�/text>
+            <text class="score-label">逻辑力</text>
             <text class="score-value">{{ record.logicScore }}</text>
           </view>
           <view class="score-item" v-if="record.perceptionScore">
-            <text class="score-label">感知�/text>
+            <text class="score-label">感知力</text>
             <text class="score-value">{{ record.perceptionScore }}</text>
           </view>
           <view class="score-item" v-if="record.spatialScore">
-            <text class="score-label">空间�/text>
+            <text class="score-label">空间力</text>
             <text class="score-value">{{ record.spatialScore }}</text>
           </view>
           <view class="score-item" v-if="record.processingSpeedScore">
@@ -100,11 +100,11 @@
             <text class="score-value">{{ record.processingSpeedScore }}</text>
           </view>
           <view class="score-item" v-if="record.emotionScore">
-            <text class="score-label">情绪�/text>
+            <text class="score-label">情绪力</text>
             <text class="score-value">{{ record.emotionScore }}</text>
           </view>
           <view class="score-item" v-if="record.resilienceScore">
-            <text class="score-label">抗挫�/text>
+            <text class="score-label">抗挫力</text>
             <text class="score-value">{{ record.resilienceScore }}</text>
           </view>
         </view>
@@ -129,7 +129,7 @@
       <view class="section-card" v-if="supplements.length > 0">
         <view class="card-title-row">
           <text class="card-title">补充�料</text>
-          <text class="supplement-count">{{ supplements.length }}�/text>
+          <text class="supplement-count">{{ supplements.length }}�</text>
         </view>
         <view class="supplement-card" v-for="item in supplements" :key="item.id" @click="viewSupplement(item)">
           <view class="supplement-header">
@@ -161,7 +161,7 @@ export default {
       record: null,
       recordId: null,
       supplements: [],
-      gradeNames: {1:'一年级',2:'二年�,3:'三年�,4:'四年�,5:'五年�,6:'六年�,7:'�一',8:'�二',9:'�三',10:'高一',11:'高二',12:'高三'}
+      gradeNames: {1:'一年级',2:'二年级',3:'三年级',4:'四年级',5:'五年级',6:'六年级',7:'�一',8:'�二',9:'�三',10:'高一',11:'高二',12:'高三'}
     }
   },
   computed: {
@@ -234,7 +234,7 @@ export default {
         uni.setClipboardData({
           data: this.record.sourceFileUrl,
           success: function() {
-            uni.showToast({ title: '链接已��, icon: 'success' })
+            uni.showToast({ title: '链接已�制', icon: 'success' })
           }
         })
       }
@@ -245,7 +245,7 @@ export default {
         content: '删除�无法��,确定�删除此�长档案�?',
         success: async function(res) {
           if (res.confirm) {
-            uni.showLoading({ title: '删除�..' })
+            uni.showLoading({ title: '删除中...' })
             try {
               var result = await deleteGrowthRecord(this.recordId)
               uni.hideLoading()

+ 11 - 11
cfc-frontend/pages/growth/index.vue

@@ -2,29 +2,29 @@
   <view class="container">
     <view class="header">
       <text class="title">鎴愰暱妗f�</text>
-      <text class="subtitle">璁板綍瀛╁瓙鐨勬瘡涓€娆℃垚闀?/text>
+      <text class="subtitle">璁板綍瀛╁瓙鐨勬瘡涓€娆℃垚闀�</text>
     </view>
 
     <view class="children-list" v-if="!childId">
       <view class="child-card" v-for="child in children" :key="child.id" @click="viewChildRecords(child)">
         <view class="child-info">
           <text class="child-name">{{ child.nickname || child.name }}</text>
-          <text class="child-age" v-if="child.age">骞撮緞锛歿{ child.age }}宀?/text>
+          <text class="child-age" v-if="child.age">骞撮緞锛歿{ child.age }}宀�</text>
         </view>
         <view class="arrow">
-          <text class="arrow-icon">鈥?/text>
+          <text class="arrow-icon">鈥�</text>
         </view>
       </view>
       <view class="empty-state" v-if="children.length === 0 && !loading">
         <text class="empty-icon">馃搵</text>
-        <text class="empty-text">杩樻病鏈夋坊鍔犲�瀛?/text>
-        <text class="empty-hint">璇峰厛鍦?鎴戠殑"椤甸潰娣诲姞瀛╁瓙</text>
+        <text class="empty-text">杩樻病鏈夋坊鍔犲�瀛�</text>
+        <text class="empty-hint">璇峰厛鍦�"鎴戠殑"椤甸潰娣诲姞瀛╁瓙</text>
       </view>
     </view>
 
     <view class="records-section" v-if="selectedChild">
       <view class="section-header">
-        <text class="section-title">{{ selectedChildName }} 鐨勬垚闀挎。妗?/text>
+        <text class="section-title">{{ selectedChildName }} 鐨勬垚闀挎。妗�</text>
       </view>
 
       <view class="filter-tabs">
@@ -51,7 +51,7 @@
           <view class="record-badges">
             <text class="record-source-tag" v-if="record.sourceType">{{ sourceTypeLabel(record.sourceType) }}</text>
             <text class="record-tag" :class="record.status === 'completed' ? 'tag-completed' : 'tag-pending'">
-              {{ record.status === 'completed' ? '宸插畬鎴? : '寰呭悓姝? }}
+              {{ record.status === 'completed' ? '宸插畬鎴�' : '寰呭悓姝�' }}
             </text>
           </view>
         </view>
@@ -62,7 +62,7 @@
         </view>
       </view>
       <view class="empty-state" v-if="filteredRecords.length === 0 && records.length > 0">
-        <text class="empty-text">璇ョ被鍨嬫殏鏃犺�褰?/text>
+        <text class="empty-text">璇ョ被鍨嬫殏鏃犺�褰�</text>
       </view>
       <view class="empty-state" v-if="records.length === 0">
         <text class="empty-text">鏆傛棤鎴愰暱妗f�璁板綍</text>
@@ -174,7 +174,7 @@ export default {
       try {
         var familyId = uni.getStorageSync('familyId')
         if (!familyId) {
-          uni.showToast({ title: '鎮ㄦ殏鏈�姞鍏ュ�搴?, icon: 'none' })
+          uni.showToast({ title: '鎮ㄦ殏鏈�姞鍏ュ�搴�', icon: 'none' })
           return
         }
         var userInfo = uni.getStorageSync('userInfo')
@@ -182,12 +182,12 @@ export default {
         var res = await generateInviteCard('guide', familyId)
         var code = res.data.code
         this.shareData = {
-          title: (userInfo && userInfo.nickname ? userInfo.nickname : '瀹堕暱') + ' 閭€璇蜂綘鎴愪负鎴愰暱瑙勫垝甯?,
+          title: (userInfo && userInfo.nickname ? userInfo.nickname : '瀹堕暱') + ' 閭€璇蜂綘鎴愪负鎴愰暱瑙勫垝甯�',
           path: '/pages/login/login?invite_code=' + code
         }
         uni.showToast({ title: '鐐瑰嚮鍙充笂瑙掕浆鍙戠粰TA', icon: 'none' })
       } catch (e) {
-        uni.showToast({ title: e.message || '鐢熸垚閭€璇峰け璐?, icon: 'none' })
+        uni.showToast({ title: e.message || '鐢熸垚閭€璇峰け璐�', icon: 'none' })
       }
     }
   }

+ 5 - 5
cfc-frontend/pages/growth/supplement.vue

@@ -2,7 +2,7 @@
   <view class="container">
     <view class="header">
       <text class="title">琛ュ厖娴嬭瘎鏉愭枡</text>
-      <text class="subtitle">涓哄凡鏈夋垚闀挎。妗堣ˉ鍏呴�澶栨姤鍛?/text>
+      <text class="subtitle">涓哄凡鏈夋垚闀挎。妗堣ˉ鍏呴�澶栨姤鍛�</text>
     </view>
 
     <view class="form" v-if="step === 1">
@@ -23,11 +23,11 @@
       </view>
 
       <view class="form-item">
-        <text class="label">缁煎悎寰楀垎锛堥€夊~锛?/text>
+        <text class="label">缁煎悎寰楀垎锛堥€夊~锛�</text>
         <input class="input" v-model="formData.overallScore" type="number" placeholder="0-100" />
       </view>
 
-      <button class="btn-submit" @click="uploadAndParse" :disabled="!canUpload">涓婁紶骞惰В鏋?/button>
+      <button class="btn-submit" @click="uploadAndParse" :disabled="!canUpload">涓婁紶骞惰В鏋�</button>
     </view>
 
     <view class="form" v-else-if="step === 2">
@@ -108,7 +108,7 @@ export default {
     },
     async uploadAndParse() {
       if (!this.canUpload) return
-      uni.showLoading({ title: '涓婁紶瑙f瀽涓?..' })
+      uni.showLoading({ title: '涓婁紶瑙f瀽涓�...' })
       try {
         var res = await uploadAndParseReport(this.filePath)
         uni.hideLoading()
@@ -128,7 +128,7 @@ export default {
       }
     },
     async confirmCreate() {
-      uni.showLoading({ title: '鍒涘缓涓?..' })
+      uni.showLoading({ title: '鍒涘缓涓�...' })
       try {
         var submitData = {
           parentRecordId: this.parentRecordId,

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

@@ -2,7 +2,7 @@
   <view class="container">
     <view class="header">
       <text class="title">上传测评报告</text>
-      <text class="subtitle">上传PDF测评报告,自动解析数��?/text>
+      <text class="subtitle">上传PDF测评报告,自动解析数据</text>
     </view>
 
     <view class="form" v-if="step === 1">
@@ -11,7 +11,7 @@
         <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-arrow">��?/text>
+          <text class="select-arrow">›</text>
         </view>
       </view>
 
@@ -24,7 +24,7 @@
         </view>
       </view>
 
-      <button class="btn-submit" @click="uploadAndParse" :disabled="!canUpload">上传并解��?/button>
+      <button class="btn-submit" @click="uploadAndParse" :disabled="!canUpload">上传并解析</button>
     </view>
 
     <view class="form" v-if="step === 2">
@@ -140,7 +140,7 @@ export default {
     },
     async uploadAndParse() {
       if (!this.canUpload) return
-      uni.showLoading({ title: '上传解析��?..' })
+      uni.showLoading({ title: '上传解析中...' })
       try {
         var res = await uploadAndParseReport(this.filePath)
         uni.hideLoading()
@@ -163,10 +163,10 @@ export default {
     async confirmCreate() {
       var reportDate = this.manualDate || this.reportDateStr
       if (!reportDate && (!this.parsedData || !this.parsedData.reportDate)) {
-        uni.showToast({ title: '请输入报告日��?, icon: 'none' })
+        uni.showToast({ title: '请输入报告日期', icon: 'none' })
         return
       }
-      uni.showLoading({ title: '创建��?..' })
+      uni.showLoading({ title: '创建中...' })
       try {
         var submitData = {
           childId: this.selectedChild.id,

+ 18 - 18
cfc-frontend/pages/guide/activities/detail.vue

@@ -7,7 +7,7 @@
 
         <view class="form-item">
           <text class="form-label">活动标题 *</text>
-          <input class="form-input" v-model="form.title" placeholder="请输入活动标� :disabled="readonly" />
+          <input class="form-input" v-model="form.title" placeholder="请输入活动标题" :disabled="readonly" />
         </view>
 
         <view class="form-item">
@@ -21,22 +21,22 @@
         <view class="form-item">
           <text class="form-label">活动日期时间 *</text>
           <view class="form-date-picker" @click="showDatePicker">
-            <text class="picker-text">{{ form.activityDate ? formatDate(form.activityDate) : '请选择日期和时� }}</text>
+            <text class="picker-text">{{ form.activityDate ? formatDate(form.activityDate) : '请选择日期和时间' }}</text>
           </view>
         </view>
 
         <view class="form-item">
           <text class="form-label">活动地点</text>
-          <input class="form-input" v-model="form.location" placeholder="请输入活动地� />
+          <input class="form-input" v-model="form.location" placeholder="请输入活动地点" />
         </view>
 
         <view class="form-item-row">
           <view class="form-item half">
-            <text class="form-label">最大人�/text>
+            <text class="form-label">最大人数</text>
             <input class="form-input" type="number" v-model="form.maxParticipants" placeholder="20" />
           </view>
           <view class="form-item half">
-            <text class="form-label">价格(元�/text>
+            <text class="form-label">价格(元)</text>
             <input class="form-input" type="digit" v-model="priceYuan" placeholder="0表示�费" />
           </view>
         </view>
@@ -51,7 +51,7 @@
 
         <view class="form-item">
           <text class="form-label">活动�述</text>
-          <textarea class="form-textarea" v-model="form.description" placeholder="请输入活动详细介� />
+          <textarea class="form-textarea" v-model="form.description" placeholder="请输入活动详细介�" />
         </view>
 
         <view class="form-actions">
@@ -59,13 +59,13 @@
             <text>�存</text>
           </view>
           <view class="btn-publish" v-if="form.status === 'draft'" @click="handlePublish">
-            <text>�存并��/text>
+            <text>�存并�布</text>
           </view>
         </view>
       </view>
     </view>
 
-    <!-- �读模�(已�布/已��已完�) -->
+    <!-- �读模�(已�布/已�消/已完�) -->
     <view class="detail-section" v-else>
       <view class="detail-cover" v-if="form.coverImage">
         <image class="cover-img" :src="form.coverImage" mode="aspectFill" />
@@ -94,14 +94,14 @@
         <view class="detail-stats">
           <view class="stat-box">
             <text class="stat-val">{{ form.currentParticipants || 0 }}</text>
-            <text class="stat-label">已报�/text>
+            <text class="stat-label">已报�</text>
           </view>
           <view class="stat-box">
             <text class="stat-val">{{ form.maxParticipants || 20 }}</text>
-            <text class="stat-label">最大人�/text>
+            <text class="stat-label">最大人数</text>
           </view>
           <view class="stat-box">
-            <text class="stat-val">{{ form.price > 0 ? (form.price / 100 + '�) : '�费' }}</text>
+            <text class="stat-val">{{ form.price > 0 ? (form.price / 100 + '元') : '�费' }}</text>
             <text class="stat-label">ä»·æ ¼</text>
           </view>
         </view>
@@ -119,7 +119,7 @@
       </view>
     </view>
 
-    <view class="loading" v-if="loading"><text class="loading-text">加载�..</text></view>
+    <view class="loading" v-if="loading"><text class="loading-text">加载中...</text></view>
   </view>
 </template>
 
@@ -204,14 +204,14 @@ export default {
     },
     handleSave() {
       if (!this.form.title) {
-        uni.showToast({ title: '请输入活动标�, icon: 'none' })
+        uni.showToast({ title: '请输入活动标题', icon: 'none' })
         return
       }
       this.save(false)
     },
     handlePublish() {
       if (!this.form.title) {
-        uni.showToast({ title: '请输入活动标�, icon: 'none' })
+        uni.showToast({ title: '请输入活动标题', icon: 'none' })
         return
       }
       this.save(true)
@@ -227,7 +227,7 @@ export default {
         if (publishAfterSave && self.form.status === 'draft') {
           publishActivity(self.form.id || self.activityId).then(function(r) {
             if (r.code === 200) {
-              uni.showToast({ title: '已��, icon: 'success' })
+              uni.showToast({ title: '已�布', icon: 'success' })
               setTimeout(function() {
                 uni.redirectTo({ url: '/pages/guide/activities/index' })
               }, 1000)
@@ -251,7 +251,7 @@ export default {
             if (publishAfterSave) {
               publishActivity(res.data).then(function(r) {
                 if (r.code === 200) {
-                  uni.showToast({ title: '已��, icon: 'success' })
+                  uni.showToast({ title: '已�布', icon: 'success' })
                   setTimeout(function() {
                     uni.redirectTo({ url: '/pages/guide/activities/index' })
                   }, 1000)
@@ -273,7 +273,7 @@ export default {
             if (publishAfterSave) {
               publishActivity(payload.id).then(function(r) {
                 if (r.code === 200) {
-                  uni.showToast({ title: '已��, icon: 'success' })
+                  uni.showToast({ title: '已�布', icon: 'success' })
                   setTimeout(function() {
                     uni.redirectTo({ url: '/pages/guide/activities/index' })
                   }, 1000)
@@ -302,7 +302,7 @@ export default {
       return map[category] || '&#x1F3E0;'
     },
     statusText(status) {
-      var map = { draft: '�稿', published: '已��, cancelled: '已��, completed: '已完� }
+      var map = { draft: '�稿', published: '已�布', cancelled: '已�消', completed: '已完�' }
       return map[status] || status || '�稿'
     },
     formatDate(dateStr) {

+ 12 - 12
cfc-frontend/pages/guide/activities/index.vue

@@ -31,7 +31,7 @@
         </view>
         <view class="act-body">
           <view class="act-header">
-            <text class="act-title">{{ act.title || '未命�活� }}</text>
+            <text class="act-title">{{ act.title || '未命�活动' }}</text>
             <text class="act-status" :class="'status-' + act.status">{{ statusText(act.status) }}</text>
           </view>
           <view class="act-meta">
@@ -44,8 +44,8 @@
           </view>
           <view class="act-desc" v-if="act.description">{{ act.description }}</view>
           <view class="act-stats">
-            <text class="stat-item">&#x1F465; {{ act.currentParticipants || 0 }}/{{ act.maxParticipants || 20 }}�/text>
-            <text class="stat-item" v-if="act.price > 0">&#x1F4B0; {{ act.price / 100 }}å…?/text>
+            <text class="stat-item">&#x1F465; {{ act.currentParticipants || 0 }}/{{ act.maxParticipants || 20 }}人</text>
+            <text class="stat-item" v-if="act.price > 0">&#x1F4B0; {{ act.price / 100 }}å…ƒ</text>
             <text class="stat-item free" v-else>�费</text>
           </view>
           <view class="act-actions" @click.stop>
@@ -76,7 +76,7 @@
     </view>
 
     <view class="loading" v-if="loading">
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
   </view>
 </template>
@@ -93,9 +93,9 @@ export default {
       filterOptions: [
         { value: '', label: '全部' },
         { value: 'draft', label: '�稿' },
-        { value: 'published', label: '已�� },
-        { value: 'cancelled', label: '已�� },
-        { value: 'completed', label: '已完� }
+        { value: 'published', label: '已�布' },
+        { value: 'cancelled', label: '已�消' },
+        { value: 'completed', label: '已完�' }
       ]
     }
   },
@@ -132,7 +132,7 @@ export default {
         content: '�布�活动将对外展示,是�继续?',
         success: function(res) {
           if (res.confirm) {
-            uni.showLoading({ title: '�布�..' })
+            uni.showLoading({ title: '�布中...' })
             publishActivity(activityId).then(function(res) {
               uni.hideLoading()
               if (res.code === 200) {
@@ -158,7 +158,7 @@ export default {
           if (res.confirm) {
             cancelActivity(activityId).then(function(r) {
               if (r.code === 200) {
-                uni.showToast({ title: '已��, icon: 'success' })
+                uni.showToast({ title: '已�消', icon: 'success' })
                 self.loadActivities()
               } else {
                 uni.showToast({ title: r.message || '�作失败', icon: 'none' })
@@ -172,12 +172,12 @@ export default {
       var self = this
       uni.showModal({
         title: '确认删除',
-        content: '删除�无法��,是�确定删除�,
+        content: '删除�无法��,是�确定删除?',
         success: function(res) {
           if (res.confirm) {
             deleteActivity(activityId).then(function(r) {
               if (r.code === 200) {
-                uni.showToast({ title: '已删�, icon: 'success' })
+                uni.showToast({ title: '已删除', icon: 'success' })
                 self.loadActivities()
               } else {
                 uni.showToast({ title: r.message || '删除失败', icon: 'none' })
@@ -188,7 +188,7 @@ export default {
       })
     },
     statusText(status) {
-      var map = { draft: '�稿', published: '已��, cancelled: '已��, completed: '已完� }
+      var map = { draft: '�稿', published: '已�布', cancelled: '已�消', completed: '已完�' }
       return map[status] || status || '�稿'
     },
     categoryIcon(category) {

+ 19 - 19
cfc-frontend/pages/guide/bind/invite.vue

@@ -1,11 +1,11 @@
 <template>
   <view class="container">
-    <!-- 邀请信��?-->
+    <!-- 邀请信-->
     <view class="invite-card" v-if="guideInfo">
-      <view class="guide-avatar">{{ guideInfo.guideName ? guideInfo.guideName[0] : '��? }}</view>
+      <view class="guide-avatar">{{ guideInfo.guideName ? guideInfo.guideName[0] : '师' }}</view>
       <text class="guide-name">{{ guideInfo.guideName }}</text>
       <text class="invite-desc">邀请您绑定家庭关系</text>
-      <text class="expire-text">邀请有效期��?{{ formatDate(guideInfo.expireTime) }}</text>
+      <text class="expire-text">邀请有效期{{ formatDate(guideInfo.expireTime) }}</text>
     </view>
 
     <!-- 绑定表单 -->
@@ -30,36 +30,36 @@
 
       <view class="form-item">
         <text class="label">服务价格</text>
-        <input class="input" type="digit" v-model="servicePrice" placeholder="请输入服务价��? />
+        <input class="input" type="digit" v-model="servicePrice" placeholder="请输入服务价格" />
       </view>
 
       <button class="btn-confirm" @click="confirmBind">确认绑定</button>
     </view>
 
-    <!-- 已绑定提��?-->
+    <!-- 已绑定提-->
     <view class="bound-card" v-else>
-      <text class="success-icon">��?/text>
+      <text class="success-icon">✓</text>
       <text class="success-text">绑定成功</text>
-      <text class="success-desc">您已成功绑定成长规划��?/text>
+      <text class="success-desc">您已成功绑定成长规划师</text>
       <button class="btn-go" @click="goHome">返回首页</button>
     </view>
 
-    <!-- 分享邀��?-->
+    <!-- 分享邀-->
     <view class="share-section" v-if="isGuide">
-      <text class="section-title">邀请家长绑��?/text>
+      <text class="section-title">邀请家长绑定</text>
       <view class="invite-url">
         <text selectable>{{ inviteUrl }}</text>
       </view>
-      <button class="btn-copy" @click="copyUrl">复制邀请链��?/button>
-      <button class="btn-qrcode" @click="showQrcode">生成二维��?/button>
+      <button class="btn-copy" @click="copyUrl">复制邀请链接</button>
+      <button class="btn-qrcode" @click="showQrcode">生成二维码</button>
     </view>
 
-    <!-- 二维码弹��?-->
+    <!-- 二维码弹-->
     <uni-popup ref="qrPopup" type="center">
       <view class="qr-popup">
         <text class="qr-title">扫码绑定</text>
         <image class="qr-image" :src="qrcodeUrl" mode="widthFix" />
-        <text class="qr-desc">微信扫一扫绑��?/text>
+        <text class="qr-desc">微信扫一扫绑定</text>
         <text class="close-btn" @click="closeQrcode">关闭</text>
       </view>
     </uni-popup>
@@ -109,7 +109,7 @@ export default {
   },
   methods: {
     loadGuideInfo() {
-      // 从服务器获取成长规划师信��?
+      // 从服务器获取成长规划师信
       uni.request({
         url: `${getApp().globalData.baseUrl}/api/guide/bind/validate`,
         data: { token: this.inviteToken },
@@ -144,7 +144,7 @@ export default {
         return
       }
       
-      uni.showLoading({ title: '绑定��?..' })
+      uni.showLoading({ title: '绑定中...' })
       try {
         await uni.request({
           url: `${getApp().globalData.baseUrl}/api/bind/accept`,
@@ -177,11 +177,11 @@ export default {
     },
     copyUrl() {
       uni.setClipboardData({ data: this.inviteUrl })
-      uni.showToast({ title: '已复��? })
+      uni.showToast({ title: '已复制' })
     },
     async showQrcode() {
       if (!this.inviteUrl) {
-        uni.showToast({ title: '请先生成邀��?, icon: 'none' })
+        uni.showToast({ title: '请先生成邀请', icon: 'none' })
         return
       }
       try {
@@ -189,11 +189,11 @@ export default {
         if (res.code === 200 && res.data) {
           this.qrcodeUrl = res.data.qrCodeBase64
         } else {
-          uni.showToast({ title: res.message || '生成二维码失��?, icon: 'none' })
+          uni.showToast({ title: res.message || '生成二维码失败', icon: 'none' })
           return
         }
       } catch (e) {
-        uni.showToast({ title: '生成二维码失��?, icon: 'none' })
+        uni.showToast({ title: '生成二维码失败', icon: 'none' })
         return
       }
       this.$refs.qrPopup.open()

+ 10 - 10
cfc-frontend/pages/guide/hierarchy/index.vue

@@ -1,11 +1,11 @@
 <template>
   <view class="container">
     <view class="header">
-      <text class="title">我的下级�长规划�/text>
+      <text class="title">我的下级�长规划师</text>
       <text class="subtitle">查看和管�下级�长规划师</text>
     </view>
 
-    <!-- 下级�长规划师列�-->
+    <!-- 下级�长规划师列表 -->
     <view class="section">
       <view class="section-title">直接下级</view>
       <view class="guide-list" v-if="childGuides.length > 0">
@@ -17,7 +17,7 @@
         >
           <image class="guide-avatar" :src="guide.avatar || '/static/default-avatar.png'" />
           <view class="guide-info">
-            <text class="guide-name">{{ guide.nickname || '未命� }}</text>
+            <text class="guide-name">{{ guide.nickname || '未命�' }}</text>
             <text class="guide-stats">�务家庭: {{ guide.familyCount || 0 }}</text>
             <text class="guide-stats">测评次数: {{ guide.assessmentCount || 0 }}</text>
           </view>
@@ -45,7 +45,7 @@
         >
           <image class="guide-avatar" :src="guide.avatar || '/static/default-avatar.png'" />
           <view class="guide-info">
-            <text class="guide-name">{{ guide.nickname || '未命� }}</text>
+            <text class="guide-name">{{ guide.nickname || '未命�' }}</text>
             <text class="guide-stats">�务家庭: {{ guide.familyCount || 0 }}</text>
             <text class="guide-stats">测评次数: {{ guide.assessmentCount || 0 }}</text>
           </view>
@@ -56,14 +56,14 @@
       </view>
     </view>
 
-    <!-- 上级�长规划�-->
+    <!-- 上级�长规划师 -->
     <view class="section" v-if="parentGuide">
-      <view class="section-title">我的上级�长规划�/view>
+      <view class="section-title">我的上级�长规划师</view>
       <view class="parent-guide-card">
         <image class="guide-avatar" :src="parentGuide.avatar || '/static/default-avatar.png'" />
         <view class="guide-info">
-          <text class="guide-name">{{ parentGuide.nickname || '未命� }}</text>
-          <text class="guide-desc">我的上级�长规划�/text>
+          <text class="guide-name">{{ parentGuide.nickname || '未命�' }}</text>
+          <text class="guide-desc">我的上级�长规划师</text>
         </view>
       </view>
     </view>
@@ -126,8 +126,8 @@ export default {
 
     viewGuideDetail(guide) {
       uni.showModal({
-        title: '�长规划师详�,
-        content: `姓�: ${guide.nickname || '未命�}\n�务家庭: ${guide.familyCount || 0}\n测评次数: ${guide.assessmentCount || 0}`,
+        title: '�长规划师详情',
+        content: `姓�: ${guide.nickname || '未命�'}\n�务家庭: ${guide.familyCount || 0}\n测评次数: ${guide.assessmentCount || 0}`,
         showCancel: false
       })
     },

+ 26 - 26
cfc-frontend/pages/guide/invite/share.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="container">
     <view class="header">
-      <text class="title">邀请分��?/text>
+      <text class="title">邀请分享</text>
       <text class="subtitle">邀请家长或新成长规划师加入</text>
     </view>
 
@@ -21,7 +21,7 @@
             </text>
           </view>
           <view class="code-stats">
-            <text class="stat">已使��? {{ code.useCount }}/{{ code.maxUseCount }}</text>
+            <text class="stat">已使用: {{ code.useCount }}/{{ code.maxUseCount }}</text>
             <text class="stat" v-if="code.expireAt">过期: {{ formatDate(code.expireAt) }}</text>
           </view>
         </view>
@@ -37,30 +37,30 @@
       <view class="share-item" @click="copyInviteLink">
         <view class="share-icon">🔗</view>
         <view class="share-content">
-          <text class="share-title">复制邀请链��?/text>
+          <text class="share-title">复制邀请链接</text>
           <text class="share-desc">分享链接给家长或新成长规划师</text>
         </view>
-        <text class="share-arrow">��?/text>
+        <text class="share-arrow">›</text>
       </view>
 
-      <!-- 生成二维��?-->
+      <!-- 生成二维-->
       <view class="share-item" @click="showQrcode">
         <view class="share-icon">📱</view>
         <view class="share-content">
-          <text class="share-title">生成二维��?/text>
+          <text class="share-title">生成二维码</text>
           <text class="share-desc">扫码即可加入</text>
         </view>
-        <text class="share-arrow">��?/text>
+        <text class="share-arrow">›</text>
       </view>
 
-      <!-- 转发给朋��?-->
+      <!-- 转发给朋-->
       <view class="share-item" @click="shareToFriend">
         <view class="share-icon">📤</view>
         <view class="share-content">
-          <text class="share-title">转发给朋��?/text>
-          <text class="share-desc">直接分享到微��?/text>
+          <text class="share-title">转发给朋友</text>
+          <text class="share-desc">直接分享到微信</text>
         </view>
-        <text class="share-arrow">��?/text>
+        <text class="share-arrow">›</text>
       </view>
     </view>
 
@@ -70,7 +70,7 @@
       <view class="tips-list">
         <view class="tip-item">
           <text class="tip-icon">💡</text>
-          <text class="tip-text">家长通过邀请码注册后,会自动关联到��?/text>
+          <text class="tip-text">家长通过邀请码注册后,会自动关联到您</text>
         </view>
         <view class="tip-item">
           <text class="tip-icon">💡</text>
@@ -78,21 +78,21 @@
         </view>
         <view class="tip-item">
           <text class="tip-icon">💡</text>
-          <text class="tip-text">您可以查看所有下级成长规划师的测评报��?/text>
+          <text class="tip-text">您可以查看所有下级成长规划师的测评报告</text>
         </view>
         <view class="item">
           <text class="tip-icon">💡</text>
-          <text class="tip-text">邀请码可以设置使用次数和过期时��?/text>
+          <text class="tip-text">邀请码可以设置使用次数和过期时间</text>
         </view>
       </view>
     </view>
 
-    <!-- 二维码弹��?-->
+    <!-- 二维码弹-->
     <view class="qrcode-modal" v-if="showQrcodeModal" @click="showQrcodeModal = false">
       <view class="modal-content" @click.stop>
         <view class="modal-header">
           <text class="modal-title">邀请二维码</text>
-          <text class="modal-close" @click="showQrcodeModal = false">��?/text>
+          <text class="modal-close" @click="showQrcodeModal = false">✕</text>
         </view>
         <view class="qrcode-container">
           <canvas canvas-id="qrcodeCanvas" class="qrcode-canvas"></canvas>
@@ -129,7 +129,7 @@ export default {
         const res = await getInviteCodes()
         if (res.code === 200) {
           this.inviteCodes = res.data || []
-          // 如果有可用的邀请码,使用第一��?
+          // 如果有可用的邀请码,使用第一
           const activeCode = this.inviteCodes.find(code => code.status === 'active')
           if (activeCode) {
             this.currentInviteCode = activeCode
@@ -142,7 +142,7 @@ export default {
 
     async generateInviteCode() {
       try {
-        uni.showLoading({ title: '生成��?..' })
+        uni.showLoading({ title: '生成中...' })
         const res = await generateInviteCode()
         uni.hideLoading()
 
@@ -183,7 +183,7 @@ export default {
         data: inviteUrl,
         success: () => {
           uni.showToast({
-            title: '链接已复��?,
+            title: '链接已复制',
             icon: 'success'
           })
         }
@@ -210,7 +210,7 @@ export default {
       const code = this.currentInviteCode.code
       const pagePath = '/pages/guide/register/index?inviteCode=' + code
 
-      // 通过后端生成真实二维��?
+      // 通过后端生成真实二维
       let qrBase64 = ''
       try {
         const res = await generateQrCodeFromText(pagePath)
@@ -218,7 +218,7 @@ export default {
           qrBase64 = res.data.qrCodeBase64
         }
       } catch (e) {
-        console.error('生成二维码失��?, e)
+        console.error('生成二维码失败', e)
       }
 
       const ctx = uni.createCanvasContext('qrcodeCanvas')
@@ -229,7 +229,7 @@ export default {
       ctx.fillRect(0, 0, canvasWidth, canvasHeight)
 
       if (qrBase64) {
-        // ��?base64 写入临时文件,再绘制��?Canvas
+        // 将 base64 写入临时文件,再绘制到 Canvas
         const rawBase64 = qrBase64.indexOf('base64,') >= 0 ? qrBase64.split('base64,')[1] : qrBase64
         const fsm = uni.getFileSystemManager()
         const tempPath = wx.env.USER_DATA_PATH + '/qr_invite_' + Date.now() + '.png'
@@ -293,7 +293,7 @@ export default {
         provider: 'weixin',
         scene: {
           type: 0,
-          title: '成为成长规划��?,
+          title: '成为成长规划师',
           path: inviteUrl
         },
         success: () => {
@@ -314,8 +314,8 @@ export default {
     getStatusText(status) {
       const statusMap = {
         'active': '可用',
-        'used': '已用��?,
-        'expired': '已过��?
+        'used': '已用完',
+        'expired': '已过期'
       }
       return statusMap[status] || status
     },
@@ -323,7 +323,7 @@ export default {
     formatDate(dateStr) {
       if (!dateStr) return ''
       const date = new Date(dateStr)
-      return `${date.getMonth() + 1}��?{date.getDate()}日`
+      return `${date.getMonth() + 1}月${date.getDate()}日`
     }
   }
 }

+ 7 - 7
cfc-frontend/pages/guide/packages/create.vue

@@ -3,7 +3,7 @@
     <view class="form">
       <view class="form-item">
         <text class="label">任务模��称</text>
-        <input class="input" v-model="form.name" placeholder="如:21天养�学习习� />
+        <input class="input" v-model="form.name" placeholder="如:21天养�学习习惯" />
       </view>
 
       <view class="form-item">
@@ -26,12 +26,12 @@
       </view>
 
       <view class="form-item">
-        <text class="label">ä»·æ ¼ (å…?</text>
+        <text class="label">ä»·æ ¼ (å…ƒ)</text>
         <input class="input" type="digit" v-model="form.price" placeholder="0 表示�费" />
       </view>
 
       <view class="form-item">
-        <text class="label">���/text>
+        <text class="label">��图</text>
         <view class="cover-upload" @click="chooseImage">
           <image v-if="form.coverImage" :src="form.coverImage" mode="aspectFill" class="cover-image"></image>
           <text v-else class="upload-icon">+</text>
@@ -41,7 +41,7 @@
       <view class="form-item">
         <text class="label">是�公开</text>
         <switch v-model="form.isPublic" :checked="form.isPublic" @change="onPublicChange" />
-        <text class="switch-label">{{ form.isPublic ? '公开到市� : '仅分享链� }}</text>
+        <text class="switch-label">{{ form.isPublic ? '公开到市场' : '仅分享链接' }}</text>
       </view>
 
       <button class="btn-submit" @click="submit">�存</button>
@@ -84,15 +84,15 @@ export default {
     },
     async submit() {
       if (!this.form.name) {
-        uni.showToast({ title: '请输入任务模���, icon: 'none' })
+        uni.showToast({ title: '请输入任务模��称', icon: 'none' })
         return
       }
       if (!this.form.cycleDays) {
-        uni.showToast({ title: '请输入周期天�, icon: 'none' })
+        uni.showToast({ title: '请输入周期天数', icon: 'none' })
         return
       }
 
-      uni.showLoading({ title: '�存�..' })
+      uni.showLoading({ title: '�存中...' })
       try {
         await createPackage({
           ...this.form,

+ 13 - 13
cfc-frontend/pages/guide/packages/detail.vue

@@ -7,20 +7,20 @@
         <text class="status" :class="pkg.status">{{ getStatusText(pkg.status) }}</text>
       </view>
       <view class="info-row">
-        <text>周期: {{ pkg.cycleDays }}�/text>
+        <text>周期: {{ pkg.cycleDays }}天</text>
         <text>ä»·æ ¼: {{ formatPriceWithSymbol(pkg.price) }}</text>
       </view>
       <view class="info-desc">{{ pkg.description }}</view>
       <view class="share-code" v-if="pkg.shareCode">
-        <text>分享� {{ pkg.shareCode }}</text>
+        <text>分享�: {{ pkg.shareCode }}</text>
         <text class="copy" @click="copyCode">�制</text>
       </view>
     </view>
 
-    <!-- 任务项列�-->
+    <!-- 任务项列表 -->
     <view class="section">
       <view class="section-header">
-        <text class="section-title">任务�/text>
+        <text class="section-title">任务项</text>
         <button class="btn-add" @click="showAddItem">添加</button>
       </view>
       
@@ -32,7 +32,7 @@
         >
           <view class="item-header">
             <text class="item-name">{{ item.taskName }}</text>
-            <text class="item-required" v-if="item.isRequired">必�/text>
+            <text class="item-required" v-if="item.isRequired">必选</text>
           </view>
           <view class="item-info">
             <text>积分: {{ item.points }}</text>
@@ -47,15 +47,15 @@
       </view>
 
       <view class="empty-items" v-if="items.length === 0">
-        <text>暂无任务项,请添�/text>
+        <text>暂无任务项,请添加</text>
       </view>
     </view>
 
-    <!-- 添加/编辑任务项弹�-->
+    <!-- 添加/编辑任务项弹çª-->
     <uni-popup ref="itemPopup" type="bottom">
       <view class="popup-content">
         <view class="popup-header">
-          <text>{{ editingItem ? '编辑任务� : '添加任务� }}</text>
+          <text>{{ editingItem ? '编辑任务项' : '添加任务项' }}</text>
           <text class="close" @click="closePopup">×</text>
         </view>
         <view class="popup-form">
@@ -82,7 +82,7 @@
             <input class="input" type="number" v-model="itemForm.duration" />
           </view>
           <view class="form-item">
-            <text class="label">必�/text>
+            <text class="label">必选</text>
             <switch v-model="itemForm.isRequired" />
           </view>
           <button class="btn-save" @click="saveItem">�存</button>
@@ -142,12 +142,12 @@ export default {
       }
     },
     getStatusText(status) {
-      const map = { 'draft': '�稿', 'pending': '待审�, 'approved': '已��, 'rejected': '已拒� }
+      const map = { 'draft': '�稿', 'pending': '待审核', 'approved': '已�布', 'rejected': '已拒�' }
       return map[status] || status
     },
     copyCode() {
       uni.setClipboardData({ data: this.pkg.shareCode })
-      uni.showToast({ title: '已�� })
+      uni.showToast({ title: '已�制' })
     },
     showAddItem() {
       this.editingItem = null
@@ -167,7 +167,7 @@ export default {
     },
     async saveItem() {
       if (!this.itemForm.taskName) {
-        uni.showToast({ title: '请输入任务��, icon: 'none' })
+        uni.showToast({ title: '请输入任务�称', icon: 'none' })
         return
       }
       try {
@@ -192,7 +192,7 @@ export default {
           if (res.confirm) {
             try {
               await deletePackageItem(id)
-              uni.showToast({ title: '已删� })
+              uni.showToast({ title: '已删除' })
               this.loadItems()
             } catch (e) {
               uni.showToast({ title: '删除失败', icon: 'none' })

+ 9 - 9
cfc-frontend/pages/guide/packages/index.vue

@@ -19,7 +19,7 @@
           <text class="package-status" :class="pkg.status">{{ getStatusText(pkg.status) }}</text>
         </view>
         <view class="package-info">
-          <text class="info-item">周期: {{ pkg.cycleDays }}�/text>
+          <text class="info-item">周期: {{ pkg.cycleDays }}天</text>
           <text class="info-item">ä»·æ ¼: {{ formatPriceWithSymbol(pkg.price) }}</text>
         </view>
         <view class="package-desc">{{ pkg.description || '暂无�述' }}</view>
@@ -38,7 +38,7 @@
       </view>
     </view>
 
-    <!-- 空状�-->
+    <!-- 空状æ€-->
     <view class="empty" v-else>
       <text class="empty-text">暂无任务模�,快去创建一个�</text>
     </view>
@@ -69,10 +69,10 @@ export default {
     getStatusText(status) {
       const map = {
         'draft': '�稿',
-        'pending': '待审�,
-        'approved': '已��,
-        'rejected': '已拒�,
-        'offline': '已下�
+        'pending': '待审核',
+        'approved': '已�布',
+        'rejected': '已拒�',
+        'offline': '已下架'
       }
       return map[status] || status
     },
@@ -87,7 +87,7 @@ export default {
       })
     },
     async submitReview(id) {
-      uni.showLoading({ title: '�交�..' })
+      uni.showLoading({ title: '�交中...' })
       try {
         await submitPackageForReview(id)
         uni.showToast({ title: '�交�功' })
@@ -100,10 +100,10 @@ export default {
     },
     async togglePublish(pkg) {
       const publish = pkg.status === 'offline'
-      uni.showLoading({ title: publish ? '�布�..' : '下架�..' })
+      uni.showLoading({ title: publish ? '�布中...' : '下架中...' })
       try {
         await publishPackage(pkg.id, publish)
-        uni.showToast({ title: publish ? '�布�功' : '已下� })
+        uni.showToast({ title: publish ? '�布�功' : '已下架' })
         this.loadPackages()
       } catch (e) {
         uni.showToast({ title: '�作失败', icon: 'none' })

+ 9 - 9
cfc-frontend/pages/guide/packages/share.vue

@@ -7,7 +7,7 @@
         <text class="name">{{ pkg.name }}</text>
         <text class="desc">{{ pkg.description }}</text>
         <view class="meta">
-          <text>{{ pkg.cycleDays }}�/text>
+          <text>{{ pkg.cycleDays }}天</text>
           <text class="price">{{ formatPriceWithSymbol(pkg.price) }}</text>
         </view>
       </view>
@@ -15,15 +15,15 @@
 
     <!-- 分享选项 -->
     <view class="share-options">
-      <text class="section-title">分享给家�/text>
+      <text class="section-title">分享给家长</text>
       
       <view class="option-item" @click="copyShareCode">
         <text class="option-icon">📋</text>
-        <text class="option-text">�制分享�/text>
+        <text class="option-text">�制分享�</text>
       </view>
       
       <view class="option-item" @click="generatePoster">
-        <text class="option-icon">🖼�/text>
+        <text class="option-icon">🖼�</text>
         <text class="option-text">生�分享海报</text>
       </view>
       
@@ -40,7 +40,7 @@
         <canvas canvas-id="posterCanvas" class="poster-canvas"></canvas>
         <view class="poster-actions">
           <button class="btn-save" @click="savePoster">�存图片</button>
-          <button class="btn-share" open-type="share">转�给朋�/button>
+          <button class="btn-share" open-type="share">转�给朋�</button>
         </view>
         <text class="close-btn" @click="closePoster">关闭</text>
       </view>
@@ -102,7 +102,7 @@ export default {
         ctx.fillText(desc.substring(30, 60), 30, 430)
       }
       
-      // 周期和价�
+      // 周期和价格
       ctx.setFillStyle('#333333')
       ctx.setFontSize(28)
       ctx.fillText(`${this.pkg.cycleDays}天`, 30, 480)
@@ -110,10 +110,10 @@ export default {
       ctx.setFontSize(36)
       ctx.fillText(this.formatPriceWithSymbol(this.pkg.price), 30, 520)
       
-      // 分享�
+      // 分享ç 
       ctx.setFillStyle('#4CAF50')
       ctx.setFontSize(24)
-      ctx.fillText('分享� ' + this.shareCode, 30, 580)
+      ctx.fillText('分享�: ' + this.shareCode, 30, 580)
       
       // �示文字
       ctx.setFillStyle('#999999')
@@ -123,7 +123,7 @@ export default {
       // �牌标识
       ctx.setFillStyle('#cccccc')
       ctx.setFontSize(16)
-      ctx.fillText('浠艾�, 480, 880)
+      ctx.fillText('浠艾�', 480, 880)
       
       ctx.draw()
       

+ 22 - 22
cfc-frontend/pages/guide/register/index.vue

@@ -1,8 +1,8 @@
 <template>
   <view class="container">
     <view class="header">
-      <text class="title">�𣂷蛹�鞾鵭閫��撣?/text>
-      <text class="subtitle">��澈銝㮖��亥�嚗�葬�拇凒憭𡁜振摨?/text>
+      <text class="title">�𣂷蛹�鞾鵭閫��撣�</text>
+      <text class="subtitle">��澈銝㮖��亥�嚗�葬�拇凒憭𡁜振摨�</text>
     </view>
 
     <view class="form">
@@ -24,13 +24,13 @@
         <input 
           class="input" 
           v-model="formData.realName" 
-          placeholder="霂瑁��亦�摰𧼮��?
+          placeholder="霂瑁��亦�摰𧼮���"
         />
       </view>
 
-      <!-- �𧢲㦤�?-->
+      <!-- �𧢲㦤�-->
       <view class="form-item">
-        <text class="label">�𧢲㦤�?/text>
+        <text class="label">�𧢲㦤��</text>
         <input 
           class="input" 
           v-model="formData.phone" 
@@ -46,7 +46,7 @@
         <input 
           class="input" 
           v-model="formData.idCard" 
-          placeholder="霂瑁��亥澈隞質��?
+          placeholder="霂瑁��亥澈隞質���"
           maxlength="18"
         />
       </view>
@@ -61,35 +61,35 @@
         />
       </view>
 
-      <!-- �嗉��∪噡嚗��匧‵嚗?-->
+      <!-- �嗉��∪噡嚗��匧‵嚗-->
       <view class="form-item">
         <text class="label">�嗉��∪噡 <text class="optional">嚗��匧‵嚗𣬚鍂鈭𦒘膛�𤑳�蝞梹�</text></text>
         <input 
           class="input" 
           v-model="formData.bankCard" 
-          placeholder="霂瑁��仿𣂎銵�㨃�?
+          placeholder="霂瑁��仿𣂎銵�㨃��"
           maxlength="30"
         />
       </view>
 
-      <!-- 撘��瑁�嚗��匧‵嚗?-->
+      <!-- 撘��瑁�嚗��匧‵嚗-->
       <view class="form-item">
-        <text class="label">撘��瑁� <text class="optional">嚗��匧‵嚗?/text></text>
+        <text class="label">撘��瑁� <text class="optional">嚗��匧‵嚗�</text></text>
         <input 
           class="input" 
           v-model="formData.bankName" 
-          placeholder="霂瑁��亙��瑁��滨妍嚗��嚗帋葉�賢極��𣂎銵�嘀撌𧼮予瘝單𣈲銵?
+          placeholder="霂瑁��亙��瑁��滨妍嚗��嚗帋葉�賢極��𣂎銵�嘀撌𧼮予瘝單𣈲銵�"
         />
       </view>
 
-      <!-- �鞾鵭閫��撣�恕霂�縑�荔��匧‵嚗?-->
+      <!-- �鞾鵭閫��撣�恕霂�縑�荔��匧‵嚗-->
       <view class="section-divider">
-        <text class="divider-text">�鞾鵭閫��撣�恕霂�縑�荔��匧‵嚗?/text>
+        <text class="divider-text">�鞾鵭閫��撣�恕霂�縑�荔��匧‵嚗�</text>
       </view>
 
       <!-- �鞾鵭閫��撣��銋血噡 -->
       <view class="form-item">
-        <text class="label">�鞾鵭閫��撣��銋血噡 <text class="optional">嚗��匧‵嚗?/text></text>
+        <text class="label">�鞾鵭閫��撣��銋血噡 <text class="optional">嚗��匧‵嚗�</text></text>
         <input 
           class="input" 
           v-model="formData.teacherNo" 
@@ -97,9 +97,9 @@
         />
       </view>
 
-      <!-- �鞾鵭閫��撣���?-->
+      <!-- �鞾鵭閫��撣���-->
       <view class="form-item">
-        <text class="label">�鞾鵭閫��撣���?<text class="optional">嚗��匧‵嚗?/text></text>
+        <text class="label">�鞾鵭閫��撣���� <text class="optional">嚗��匧‵嚗�</text></text>
         <view class="upload-section">
           <image 
             v-if="formData.teacherPhoto" 
@@ -116,7 +116,7 @@
 
       <!-- 霂�髡�抒� -->
       <view class="form-item">
-        <text class="label">霂�髡�抒� <text class="optional">嚗��匧‵嚗?/text></text>
+        <text class="label">霂�髡�抒� <text class="optional">嚗��匧‵嚗�</text></text>
         <view class="upload-section">
           <image 
             v-if="formData.certificateImage" 
@@ -159,7 +159,7 @@ export default {
     }
   },
   onLoad(options) {
-    // 憒���厰�霂瑞���㺭嚗諹䌊�典‵�?
+    // 憒���厰�霂瑞���㺭嚗諹䌊�典‵�
     if (options.inviteCode) {
       this.formData.inviteCode = options.inviteCode
       this.validateInviteCode()
@@ -209,7 +209,7 @@ export default {
     },
 
     uploadImage(field, filePath) {
-      uni.showLoading({ title: '銝𠹺�銝?..' })
+      uni.showLoading({ title: '銝𠹺�銝�...' })
       
       // TODO: 摰鮋�摨磰砲銝𠹺��唳��∪膥
       // 餈䠷�蝞��硋�����湔𦻖雿輻鍂�砍𧑐頝臬�
@@ -226,7 +226,7 @@ export default {
     async submit() {
       // 撉諹�銵典�
       if (!this.formData.realName) {
-        uni.showToast({ title: '霂瑁��亦�摰𧼮��?, icon: 'none' })
+        uni.showToast({ title: '霂瑁��亦�摰𧼮���', icon: 'none' })
         return
       }
 
@@ -236,12 +236,12 @@ export default {
       }
 
       if (!this.formData.idCard) {
-        uni.showToast({ title: '霂瑁��亥澈隞質��?, icon: 'none' })
+        uni.showToast({ title: '霂瑁��亥澈隞質���', icon: 'none' })
         return
       }
 
       try {
-        uni.showLoading({ title: '�𣂷漱銝?..' })
+        uni.showLoading({ title: '�𣂷漱銝�...' })
         
         const userId = uni.getStorageSync('userId')
         const res = await registerGuide({

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

@@ -2,7 +2,7 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">窶?霑泌屓</text>
+        <text class="back-text">窶霑泌屓</text>
       </view>
       <text class="nav-title">鬣ョ鬟�</text>
     </view>
@@ -14,20 +14,20 @@
           <text class="card-title">蝮�。。閹ウ鬟滓欠蜊�</text>
           <view class="info-list">
             <view class="info-item">
-              <text class="info-age">�言 隹キ迚ゥ邀?/text>
-              <text class="info-desc">豈城、仙コ疲怏騾る㍼荳サ鬟滂シ御シ伜�騾画叫蜈ィ隹キ迚ゥ蜥梧揩邊ョ�悟ヲらウ咏アウ縲∫√鮗ヲ縲∝�鮗ヲ髱「蛹�シ梧署萓帶戟扈ュ閭ス驥上€?/text>
+              <text class="info-age">�言 隹キ迚ゥ邀サ</text>
+              <text class="info-desc">豈城、仙コ疲怏騾る㍼荳サ鬟滂シ御シ伜�騾画叫蜈ィ隹キ迚ゥ蜥梧揩邊ョ�悟ヲらウ咏アウ縲∫√鮗ヲ縲∝�鮗ヲ髱「蛹�シ梧署萓帶戟扈ュ閭ス驥上€�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">�・ゥ 陋狗區雍?/text>
-              <text class="info-desc">豈丞、ゥ鞫��雜ウ驥丈シ倩エィ陋狗區�梧擂貅仙桁諡ャ魍シ縲∫ヲス閧峨€∬寞縲∬ア�宛蜩∝柱螂カ蛻カ蜩�シ御ソ�ソ帷函髟ソ蜿題ご縲?/text>
+              <text class="info-age">�・ゥ 陋狗區雍ィ</text>
+              <text class="info-desc">豈丞、ゥ鞫��雜ウ驥丈シ倩エィ陋狗區�梧擂貅仙桁諡ャ魍シ縲∫ヲス閧峨€∬寞縲∬ア�宛蜩∝柱螂カ蛻カ蜩�シ御ソ�ソ帷函髟ソ蜿題ご縲�</text>
             </view>
             <view class="info-item">
               <text class="info-age">�・ヲ 阡ャ闖懈ーエ譫�</text>
-              <text class="info-desc">豈丞、ゥ蜷?5 莉ス莉・荳願溌闖懈ーエ譫懶シ御ク榊酔鬚懆牡謳ュ驟搾シ瑚執蜿紋クー蟇檎噪扈エ逕溽エ�縲∫涸迚ゥ雍ィ蜥瑚�鬟溽コ、扈エ縲?/text>
+              <text class="info-desc">豈丞、ゥ蜷5 莉ス莉・荳願溌闖懈ーエ譫懶シ御ク榊酔鬚懆牡謳ュ驟搾シ瑚執蜿紋クー蟇檎噪扈エ逕溽エ�縲∫涸迚ゥ雍ィ蜥瑚�鬟溽コ、扈エ縲�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">�・� 螂カ蛻カ蜩?/text>
-              <text class="info-desc">豈丞、ゥ 300-500ml 螂カ蛻カ蜩�シ悟ヲら央螂カ縲��螂カ縲∝・カ驟ェ�瑚。・蜈�貯雍ィ蜥瑚寞逋ス雍ィ�悟シコ蛛・鬪ィ鬪シ縲?/text>
+              <text class="info-age">�・� 螂カ蛻カ蜩�</text>
+              <text class="info-desc">豈丞、ゥ 300-500ml 螂カ蛻カ蜩�シ悟ヲら央螂カ縲��螂カ縲∝・カ驟ェ�瑚。・蜈�貯雍ィ蜥瑚寞逋ス雍ィ�悟シコ蛛・鬪ィ鬪シ縲�</text>
             </view>
           </view>
         </view>
@@ -39,20 +39,20 @@
           <text class="card-title">蜆ソ遶・關・蜈サ隕∫せ</text>
           <view class="info-list">
             <view class="info-item">
-              <text class="info-age">髓?/text>
-              <text class="info-desc">菫�ソ幃ェィ鬪シ蜥檎甥鮨ソ蜿題ご縲よ擂貅撰シ夂央螂カ縲��螂カ縲∬ア��縲∫サソ蜿カ阡ャ闖懊€∝ー城アシ蟷イ縲?/text>
+              <text class="info-age">髓�</text>
+              <text class="info-desc">菫�ソ幃ェィ鬪シ蜥檎甥鮨ソ蜿題ご縲よ擂貅撰シ夂央螂カ縲��螂カ縲∬ア��縲∫サソ蜿カ阡ャ闖懊€∝ー城アシ蟷イ縲�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">體?/text>
-              <text class="info-desc">鬚�亟雍ォ陦€�御ソ晁ッ∝、ァ閼台セ帶ーァ縲よ擂貅撰シ夂コ「閧峨€∝勘迚ゥ閧晁э縲∬匠闖懊€∬ア�アサ縲∝シコ蛹冶ーキ迚ゥ縲?/text>
+              <text class="info-age">體�</text>
+              <text class="info-desc">鬚�亟雍ォ陦€�御ソ晁ッ∝、ァ閼台セ帶ーァ縲よ擂貅撰シ夂コ「閧峨€∝勘迚ゥ閧晁э縲∬匠闖懊€∬ア�アサ縲∝シコ蛹冶ーキ迚ゥ縲�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">陋狗區雍?/text>
-              <text class="info-desc">霄ォ菴鍋サ�サ�柱扈��逧�渕遑€譚先侭縲よ擂貅撰シ夐ク。陋九€�アシ閧峨€�ク。閭ク閧峨€∫央螂カ縲∬ア�宛蜩√€?/text>
+              <text class="info-age">陋狗區雍ィ</text>
+              <text class="info-desc">霄ォ菴鍋サ�サ�柱扈��逧�渕遑€譚先侭縲よ擂貅撰シ夐ク。陋九€�アシ閧峨€�ク。閭ク閧峨€∫央螂カ縲∬ア�宛蜩√€�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">扈エ逕溽エ?/text>
-              <text class="info-desc">扈エ謖∝�逍ォ蜉帛柱譁ー髯井サ」隹「縲よ擂貅撰シ壼推邀サ阡ャ闖懈ーエ譫懶シ檎音蛻ォ譏ッ讖吝ュ舌€∬Γ關晏骨縲∬・ソ蜈ー闃ア縲?/text>
+              <text class="info-age">扈エ逕溽エ�</text>
+              <text class="info-desc">扈エ謖∝�逍ォ蜉帛柱譁ー髯井サ」隹「縲よ擂貅撰シ壼推邀サ阡ャ闖懈ーエ譫懶シ檎音蛻ォ譏ッ讖吝ュ舌€∬Γ關晏骨縲∬・ソ蜈ー闃ア縲�</text>
             </view>
           </view>
         </view>
@@ -65,15 +65,15 @@
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">驥崎ァ�掠鬢�</text>
-              <text class="info-desc">譌ゥ鬢先署萓帛�螟ゥ 25-30% 逧��驥擾シ御ソ晁ッ∬ーキ迚ゥ縲∬寞逋ス雍ィ縲∵ーエ譫懈政驟搾シ悟シ€蜷ッ豢サ蜉帑ク€螟ゥ縲?/text>
+              <text class="info-desc">譌ゥ鬢先署萓帛�螟ゥ 25-30% 逧��驥擾シ御ソ晁ッ∬ーキ迚ゥ縲∬寞逋ス雍ィ縲∵ーエ譫懈政驟搾シ悟シ€蜷ッ豢サ蜉帑ク€螟ゥ縲�</text>
             </view>
             <view class="info-item">
               <text class="info-age">蜃丞ー醍ウ門�</text>
-              <text class="info-desc">謗ァ蛻カ蜷ォ邉夜・ョ譁吝柱髮カ鬟滓槍蜈・�悟㍼蟆鷹セ矩スソ蜥瑚ぇ閭夜」朱勦�悟淹蜈サ貂�キ。蜿」蜻ウ縲?/text>
+              <text class="info-desc">謗ァ蛻カ蜷ォ邉夜・ョ譁吝柱髮カ鬟滓槍蜈・�悟㍼蟆鷹セ矩スソ蜥瑚ぇ閭夜」朱勦�悟淹蜈サ貂�キ。蜿」蜻ウ縲�</text>
             </view>
             <view class="info-item">
               <text class="info-age">蜈�カウ鬣ョ豌エ</text>
-              <text class="info-desc">豈丞、ゥ鬣ョ豌エ 800-1400ml�域�ケ謐ョ蟷エ鮴�シ会シ御サ・逋ス蠑€豌エ荳コ荳サ�悟ー鷹㍼螟壽ャ。�御ソ晄戟霄ォ菴捺ーエ蛻�ケウ陦。縲?/text>
+              <text class="info-desc">豈丞、ゥ鬣ョ豌エ 800-1400ml�域�ケ謐ョ蟷エ鮴�シ会シ御サ・逋ス蠑€豌エ荳コ荳サ�悟ー鷹㍼螟壽ャ。�御ソ晄戟霄ォ菴捺ーエ蛻�ケウ陦。縲�</text>
             </view>
           </view>
         </view>

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

@@ -2,7 +2,7 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">�?餈𥪜�</text>
+        <text class="back-text">�餈𥪜�</text>
       </view>
       <text class="nav-title">餈𣂼𢆡</text>
     </view>
@@ -15,15 +15,15 @@
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">3-6 撗��摮阡��㵪�</text>
-              <text class="info-desc">瘥誩予�喳� 60 ���銝剔�撘箏漲餈𣂼𢆡嚗䔶誑皜豢��諹閎�單暑�其蛹銝鳴�憒��甇乓��歲頝����蝐餅虜�譌�?/text>
+              <text class="info-desc">瘥誩予�喳� 60 ���銝剔�撘箏漲餈𣂼𢆡嚗䔶誑皜豢��諹閎�單暑�其蛹銝鳴�憒��甇乓��歲頝����蝐餅虜�譌��</text>
             </view>
             <view class="info-item">
               <text class="info-age">6-12 撗��摮阡����</text>
-              <text class="info-desc">瘥誩予 60 ���隞乩�銝剔�撘箏漲餈𣂼𢆡嚗峕��刻秐撠?3 甈⊿�撘箏漲�㗇飢餈𣂼𢆡嚗��皜豢陶����芾�頧艾��歲蝏喋�?/text>
+              <text class="info-desc">瘥誩予 60 ���隞乩�銝剔�撘箏漲餈𣂼𢆡嚗峕��刻秐撠3 甈⊿�撘箏漲�㗇飢餈𣂼𢆡嚗��皜豢陶����芾�頧艾��歲蝏喋��</text>
             </view>
             <view class="info-item">
               <text class="info-age">12-18 撗���鍦�撟湛�</text>
-              <text class="info-desc">瘥誩予 60 ���銝剝�撘箏漲餈𣂼𢆡嚗峕��?3 甈∪��讛悌蝏���孵�蝏�澈餈𣂼𢆡銋䭾��?/text>
+              <text class="info-desc">瘥誩予 60 ���銝剝�撘箏漲餈𣂼𢆡嚗峕��� 3 甈∪��讛悌蝏���孵�蝏�澈餈𣂼𢆡銋䭾���</text>
             </view>
           </view>
         </view>
@@ -36,15 +36,15 @@
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">�� �㗇飢餈𣂼𢆡</text>
-              <text class="info-desc">�鞾�敹���蠘�嚗��撘箄�𣂼���綫�琜�頝烐郊��虜瘜喋����芾�頧艾��歲蝏喋���蝐餉��具�?/text>
+              <text class="info-desc">�鞾�敹���蠘�嚗��撘箄�𣂼���綫�琜�頝烐郊��虜瘜喋����芾�頧艾��歲蝏喋���蝐餉��具��</text>
             </view>
             <view class="info-item">
               <text class="info-age">�傁 �偦�霈剔�</text>
-              <text class="info-desc">憓𧼮撩�諹��偦��屸爸撉澆�摨艾��綫�琜�靽臬擀�㻫��趕�扯絲�僐��楛頩脯��撕�𥕦蒂霈剔��?/text>
+              <text class="info-desc">憓𧼮撩�諹��偦��屸爸撉澆�摨艾��綫�琜�靽臬擀�㻫��趕�扯絲�僐��楛頩脯��撕�𥕦蒂霈剔���</text>
             </view>
             <view class="info-item">
-              <text class="info-age">�� �娪榀�扯悌蝏?/text>
-              <text class="info-desc">�孵�頨思��菜暑�改�憸�俈餈𣂼𢆡�煺慾��綫�琜��劐撓���隡賬���頩�����溻�?/text>
+              <text class="info-age">�� �娪榀�扯悌蝏�</text>
+              <text class="info-desc">�孵�頨思��菜暑�改�憸�俈餈𣂼𢆡�煺慾��綫�琜��劐撓���隡賬���頩�����溻��</text>
             </view>
           </view>
         </view>
@@ -57,15 +57,15 @@
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">�𡁜末�剛澈</text>
-              <text class="info-desc">餈𣂼𢆡�滩�銵?5-10 ����冽���頨恬�憒��頝㻫�����暑�剁�憸�俈�諹��劐慾�?/text>
+              <text class="info-desc">餈𣂼𢆡�滩�銵5-10 ����冽���頨恬�憒��頝㻫�����暑�剁�憸�俈�諹��劐慾��</text>
             </view>
             <view class="info-item">
               <text class="info-age">銵亙�瘞游�</text>
-              <text class="info-desc">餈𣂼𢆡�滢葉�𡡞���擖格偌嚗峕� 15-20 ���銵亙� 100-150ml 瘞湛��踹��望偌�?/text>
+              <text class="info-desc">餈𣂼𢆡�滢葉�𡡞���擖格偌嚗峕� 15-20 ���銵亙� 100-150ml 瘞湛��踹��望偌��</text>
             </view>
             <view class="info-item">
               <text class="info-age">甇�&憪踹飵</text>
-              <text class="info-desc">靽脲�甇�&餈𣂼𢆡憪踹飵嚗屸��滩�摨西悌蝏�����劐�����喳�甇g�敹���嗅停�颯�?/text>
+              <text class="info-desc">靽脲�甇�&餈𣂼𢆡憪踹飵嚗屸��滩�摨西悌蝏�����劐�����喳�甇g�敹���嗅停�颯��</text>
             </view>
           </view>
         </view>

+ 36 - 36
cfc-frontend/pages/health/gut-flora-detail.vue

@@ -2,7 +2,7 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">��?返回</text>
+        <text class="back-text">返回</text>
       </view>
       <text class="nav-title">肠道菌群报告</text>
     </view>
@@ -10,11 +10,11 @@
     <scroll-view class="content" scroll-y>
       <!-- 报告头部 -->
       <view class="report-header">
-        <text class="report-title">肠道菌群检测报��?/text>
+        <text class="report-title">肠道菌群检测报告</text>
         <view class="report-meta">
           <text class="meta-item" v-if="report.personName">{{ report.personName }}</text>
           <text class="meta-item" v-if="report.gender">{{ report.gender }}</text>
-          <text class="meta-item" v-if="report.age">{{ report.age }}��?/text>
+          <text class="meta-item" v-if="report.age">{{ report.age }}岁</text>
         </view>
         <view class="report-meta">
           <text class="meta-item" v-if="report.reportDate">日期: {{ report.reportDate }}</text>
@@ -40,41 +40,41 @@
         </view>
       </scroll-view>
 
-      <!-- 快速跳��?-->
+      <!-- 快速跳-->
       <view class="quick-nav">
         <view class="nav-card" @tap="goToSpecies">
           <text class="nav-icon">🦠</text>
           <text class="nav-label">菌群详情</text>
-          <text class="nav-count">{{ floraCount }}��?/text>
+          <text class="nav-count">{{ floraCount }}种</text>
         </view>
         <view class="nav-card" @tap="goToPathogen">
           <text class="nav-icon">🔬</text>
-          <text class="nav-label">病原��?/text>
-          <text class="nav-count">{{ pathogenCount }}��?/text>
+          <text class="nav-label">病原菌</text>
+          <text class="nav-count">{{ pathogenCount }}项</text>
         </view>
         <view class="nav-card" @tap="goToTaxonomy">
           <text class="nav-icon">📊</text>
           <text class="nav-label">菌群层级</text>
-          <text class="nav-count">5��?/text>
+          <text class="nav-count">5级</text>
         </view>
         <view class="nav-card" @tap="goToRisks">
           <text class="nav-icon">⚠️</text>
           <text class="nav-label">疾病风险</text>
-          <text class="nav-count">{{ riskCount }}��?/text>
+          <text class="nav-count">{{ riskCount }}项</text>
         </view>
         <view class="nav-card" @tap="goToFoods">
-          <text class="nav-icon">🍽��?/text>
+          <text class="nav-icon">🍽️</text>
           <text class="nav-label">饮食推荐</text>
-          <text class="nav-count">{{ foodCount }}��?/text>
+          <text class="nav-count">{{ foodCount }}项</text>
         </view>
         <view class="nav-card" @tap="goToIndicators">
           <text class="nav-icon">📋</text>
           <text class="nav-label">全部指标</text>
-          <text class="nav-count">{{ indicatorCount }}��?/text>
+          <text class="nav-count">{{ indicatorCount }}项</text>
         </view>
       </view>
 
-      <!-- 肠道功能手风��?-->
+      <!-- 肠道功能手风-->
       <view class="accordion-section">
         <view class="accordion-header" @tap="toggleAccordion('gut')">
           <text class="accordion-title">肠道功能与代谢物</text>
@@ -85,9 +85,9 @@
             <view class="indicator-row">
               <text class="indicator-name" @tap="showKnowledge(indicatorType(item), item.indicatorName)">
                 {{ item.indicatorName }}
-                <text class="arrow-up" v-if="item.status === '偏高' || item.status === '过多'"> ��?/text>
-                <text class="arrow-down" v-else-if="item.status === '偏低' || item.status === '缺乏' || item.status === '不足'"> ��?/text>
-                <text class="arrow-warn" v-else-if="item.status === '异常'"> ��?/text>
+                <text class="arrow-up" v-if="item.status === '偏高' || item.status === '过多'"> ↑</text>
+                <text class="arrow-down" v-else-if="item.status === '偏低' || item.status === '缺乏' || item.status === '不足'"> ↓</text>
+                <text class="arrow-warn" v-else-if="item.status === '异常'"> ⚠</text>
               </text>
               <view class="indicator-value" v-if="!isEditing">
                 <text :class="'val-text val-' + (item._cssClass || 'normal')">{{ item.indicatorValue || '--' }}</text>
@@ -99,13 +99,13 @@
                 </picker>
               </view>
             </view>
-            <text class="indicator-range" v-if="item.refRange">参��? {{ item.refRange }}</text>
+            <text class="indicator-range" v-if="item.refRange">参考: {{ item.refRange }}</text>
           </view>
           <view class="empty-hint" v-if="gutIndicators.length === 0">暂无数据</view>
         </view>
       </view>
 
-      <!-- 营养指标手风��?-->
+      <!-- 营养指标手风-->
       <view class="accordion-section">
         <view class="accordion-header" @tap="toggleAccordion('nutri')">
           <text class="accordion-title">营养指标</text>
@@ -118,9 +118,9 @@
               <view class="indicator-row">
                 <text class="indicator-name" @tap="showKnowledge(indicatorType(item), item.indicatorName)">
                   {{ item.indicatorName }}
-                  <text class="arrow-up" v-if="item.status === '偏高' || item.status === '过多'"> ��?/text>
-                  <text class="arrow-down" v-else-if="item.status === '偏低' || item.status === '缺乏' || item.status === '不足'"> ��?/text>
-                  <text class="arrow-warn" v-else-if="item.status === '异常'"> ��?/text>
+                  <text class="arrow-up" v-if="item.status === '偏高' || item.status === '过多'"> ↑</text>
+                  <text class="arrow-down" v-else-if="item.status === '偏低' || item.status === '缺乏' || item.status === '不足'"> ↓</text>
+                  <text class="arrow-warn" v-else-if="item.status === '异常'"> ⚠</text>
                 </text>
                 <view class="indicator-value" v-if="!isEditing">
                   <text :class="'val-text val-' + (item._cssClass || 'normal')">{{ item.indicatorValue || '--' }}</text>
@@ -132,7 +132,7 @@
                   </picker>
                 </view>
               </view>
-              <text class="indicator-range" v-if="item.refRange">参��? {{ item.refRange }}</text>
+              <text class="indicator-range" v-if="item.refRange">参考: {{ item.refRange }}</text>
             </view>
           </view>
           <view class="empty-hint" v-if="nutritionGroups.length === 0">暂无数据</view>
@@ -142,7 +142,7 @@
       <view class="feedback-section" @tap="openFeedback">
         <text class="feedback-icon">💬</text>
         <text class="feedback-text">对这个报告有疑问或建议?告诉我们</text>
-        <text class="feedback-arrow">��?/text>
+        <text class="feedback-arrow">›</text>
       </view>
 
       <view class="bottom-spacer"></view>
@@ -168,13 +168,13 @@ import HealthKnowledgePopup from '../../components/health-knowledge-popup.vue'
 import FeedbackPopup from '../../components/feedback-popup.vue'
 
 var INDICATOR_TYPE_MAP = {
-  '维生��?: 'vitamin',
-  '氨基��?: 'amino_acid',
+  '维生素': 'vitamin',
+  '氨基酸': 'amino_acid',
   '微量元素': 'indicator',
   '肠道屏障与代谢物': 'indicator',
-  '短链脂肪��?: 'indicator',
-  '神经递质与激��?: 'indicator',
-  '抗生素风险评��?: 'indicator'
+  '短链脂肪酸': 'indicator',
+  '神经递质与激素': 'indicator',
+  '抗生素风险评估': 'indicator'
 }
 
 export default {
@@ -210,7 +210,7 @@ export default {
   },
   methods: {
     goBack: function() { uni.navigateBack() },
-    /** 中文状��?��?CSS安全英文 */
+    /** 中文状态 → CSS安全英文 */
     _cssForStatus: function(s) {
       var map = { '偏高': 'high', '过多': 'excess', '偏低': 'low', '缺乏': 'deficient', '不足': 'insufficient', '异常': 'abnormal', '注意': 'warning' }
       return map[s] || 'normal'
@@ -245,9 +245,9 @@ export default {
         { key: 'chronicDiseaseScore', label: '慢病控制', color: '#F59E0B' },
         { key: 'nutritionScore', label: '营养均衡', color: '#FF8C42' },
         { key: 'gutBalanceScore', label: '平衡', color: '#6366F1' },
-        { key: 'gutDiversityScore', label: '多样��?, color: '#FF6B9D' },
-        { key: 'beneficialBacteriaScore', label: '有益��?, color: '#10B981' },
-        { key: 'harmfulBacteriaScore', label: '有害��?, color: '#C62828' },
+        { key: 'gutDiversityScore', label: '多样性', color: '#FF6B9D' },
+        { key: 'beneficialBacteriaScore', label: '有益菌', color: '#10B981' },
+        { key: 'harmfulBacteriaScore', label: '有害菌', color: '#C62828' },
         { key: 'coreSpeciesScore', label: '核心菌属', color: '#4A9BD7' }
       ]
       for (var i = 0; i < scoreFields.length; i++) {
@@ -266,7 +266,7 @@ export default {
         item._cssClass = self._cssForStatus(item.status)
       })
       this.allIndicators = indicators
-      var gutCategories = ['肠道屏障与代谢物', '短链脂肪��?, '神经递质与激��?, '抗生素风险评��?]
+      var gutCategories = ['肠道屏障与代谢物', '短链脂肪酸', '神经递质与激素', '抗生素风险评估']
       this.gutIndicators = indicators.filter(function(item) {
         return gutCategories.indexOf(item.category) >= 0
       })
@@ -312,7 +312,7 @@ export default {
           self.knowledgeData = {
             itemName: v3['名称'] || name,
             category: v3['说明'] || '',
-            description: (high ? '偏高影响��? + high + '\n' : '') + (low ? '偏低影响��? + low : ''),
+            description: (high ? '偏高影响:' + high + '\n' : '') + (low ? '偏低影响:' + low : ''),
             suggestion: v3['调整建议'] || ''
           }
           self.knowledgeVisible = true
@@ -363,7 +363,7 @@ export default {
       }
       editHealthReport(this.reportId, payload, 0).then(function(res) {
         if (res.code === 200) {
-          uni.showToast({ title: '已保��?, icon: 'success' })
+          uni.showToast({ title: '已保存', icon: 'success' })
           self.isEditing = false
           self.loadData()
         } else {
@@ -392,7 +392,7 @@ export default {
     goAIChat: function() {
       if (!this.reportId) return
       uni.navigateTo({
-        url: '/pages/ai/chat?mode=nutrition&reportId=' + this.reportId + '&firstMessage=' + encodeURIComponent('请根据这份肠道菌群检测报告,分析我孩子的肠道健康状况并提出建��?)
+        url: '/pages/ai/chat?mode=nutrition&reportId=' + this.reportId + '&firstMessage=' + encodeURIComponent('请根据这份肠道菌群检测报告,分析我孩子的肠道健康状况并提出建议')
       })
     }
   }

+ 6 - 6
cfc-frontend/pages/health/gut-flora-foods-detail.vue

@@ -2,7 +2,7 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">��?返回</text>
+        <text class="back-text">返回</text>
       </view>
       <text class="nav-title">饮食推荐</text>
       <text class="nav-edit" @tap="toggleEdit">{{ isEditing ? '完成' : '编辑' }}</text>
@@ -17,8 +17,8 @@
     </scroll-view>
 
     <view class="sort-bar">
-      <text class="sort-text" @tap="sortDesc = !sortDesc">排序: {{ sortDesc ? '推荐��? : '推荐��? }}</text>
-      <text class="sort-text" @tap="showRecommendedOnly = !showRecommendedOnly">{{ showRecommendedOnly ? '全部' : '仅推��? }}</text>
+      <text class="sort-text" @tap="sortDesc = !sortDesc">排序: {{ sortDesc ? '推荐↓' : '推荐↑' }}</text>
+      <text class="sort-text" @tap="showRecommendedOnly = !showRecommendedOnly">{{ showRecommendedOnly ? '全部' : '仅推荐' }}</text>
     </view>
 
     <scroll-view class="content" scroll-y>
@@ -107,7 +107,7 @@ export default {
       var self = this
       Promise.all([
         getReportDetail(this.reportId),
-        getKnowledgeSection('食物��?)
+        getKnowledgeSection('食物库')
       ]).then(function(results) {
         var reportRes = results[0]
         var kbRes = results[1]
@@ -125,7 +125,7 @@ export default {
         if (reportRes.code === 200 && reportRes.data) {
           self.reportData = reportRes.data
           var reportFoods = reportRes.data.foods || []
-          // 合并 KB 营养数据(个��?JSON 只保存名称和推荐指数,营养数据从 KB 查)
+          // 合并 KB 营养数据(个JSON 只保存名称和推荐指数,营养数据从 KB 查)
           self.foods = reportFoods.map(function(item) {
             var name = item.foodName || item.name
             var kb = kbFoodMap[name] || {}
@@ -156,7 +156,7 @@ export default {
       var self = this
       editHealthReport(self.reportId, { foods: self.editFoods }, 0).then(function(res) {
         if (res.code === 200) {
-          uni.showToast({ title: '已保��?, icon: 'success' })
+          uni.showToast({ title: '已保存', icon: 'success' })
           self.isEditing = false
           self.loadData()
         } else {

+ 13 - 13
cfc-frontend/pages/health/gut-flora-risks-detail.vue

@@ -2,7 +2,7 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">�返回</text>
+        <text class="back-text">‹ 返回</text>
       </view>
       <text class="nav-title">疾病风险</text>
       <text class="nav-edit" @tap="toggleEdit">{{ isEditing ? '完�' : '编辑' }}</text>
@@ -19,11 +19,11 @@
           </text>
         </view>
         <view class="risk-detail-row" v-if="!isEditing">
-          <text class="risk-value">风险� {{ item.riskValue || '--' }}</text>
+          <text class="risk-value">风险值: {{ item.riskValue || '--' }}</text>
           <text class="risk-level-text">等级: {{ item.riskLevel || '--' }}</text>
         </view>
         <view class="risk-edit-row" v-if="isEditing">
-          <text class="edit-label">风险�</text>
+          <text class="edit-label">风险值:</text>
           <input class="edit-input" type="text" v-model="item.riskValue" />
           <text class="edit-label">等级:</text>
           <picker :value="riskLevelIndex(item.riskLevel)" :range="riskLevels" @change="onRiskLevelChange($event, item)">
@@ -42,11 +42,11 @@
           </text>
         </view>
         <view class="risk-detail-row" v-if="!isEditing">
-          <text class="risk-value">风险� {{ item.riskValue || '--' }}</text>
+          <text class="risk-value">风险值: {{ item.riskValue || '--' }}</text>
           <text class="risk-level-text">等级: {{ item.riskLevel || '--' }}</text>
         </view>
         <view class="risk-edit-row" v-if="isEditing">
-          <text class="edit-label">风险�</text>
+          <text class="edit-label">风险值:</text>
           <input class="edit-input" type="text" v-model="item.riskValue" />
           <text class="edit-label">等级:</text>
           <picker :value="riskLevelIndex(item.riskLevel)" :range="riskLevels" @change="onRiskLevelChange($event, item)">
@@ -80,7 +80,7 @@ export default {
       risks: [],
       isEditing: false,
       editRisks: [],
-      riskLevels: ['低风�, '需注�', '高风�, '异常'],
+      riskLevels: ['低风险', '需注�', '高风险', '异常'],
       knowledgeVisible: false,
       knowledgeData: {}
     }
@@ -89,13 +89,13 @@ export default {
     importantRisks: function() {
       return this.getRisks().filter(function(item) {
         var level = item.riskLevel || ''
-        return level === '需注�' || level === '高风� || level === '异常'
+        return level === '需注�' || level === '高风险' || level === '异常'
       })
     },
     normalRisks: function() {
       return this.getRisks().filter(function(item) {
         var level = item.riskLevel || ''
-        return level !== '需注�' && level !== '高风� && level !== '异常'
+        return level !== '需注�' && level !== '高风险' && level !== '异常'
       })
     }
   },
@@ -107,9 +107,9 @@ export default {
   },
   methods: {
     goBack: function() { uni.navigateBack() },
-    /** 中文风险等级 �CSS安全英文 */
+    /** 中文风险等级 â†CSS安全英文 */
     _cssForRiskLevel: function(level) {
-      var map = { '低风�: 'low', '需注�': 'warning', '高风�: 'high', '异常': 'abnormal' }
+      var map = { '低风险': 'low', '需注�': 'warning', '高风险': 'high', '异常': 'abnormal' }
       return map[level] || 'low'
     },
     getRisks: function() {
@@ -139,7 +139,7 @@ export default {
       var self = this
       editHealthReport(self.reportId, { diseaseRisks: self.editRisks }, 0).then(function(res) {
         if (res.code === 200) {
-          uni.showToast({ title: '已��, icon: 'success' })
+          uni.showToast({ title: '已�存', icon: 'success' })
           self.isEditing = false
           self.loadData()
         } else {
@@ -148,7 +148,7 @@ export default {
       })
     },
     riskBadgeText: function(level) {
-      var map = { '低风�: '��, '需注�': '�注�', '高风�: '��, '异常': '�异常' }
+      var map = { '低风险': '✓ 低', '需注�': '⚠ 注�', '高风险': '⚠ 高', '异常': '⚠ 异常' }
       return map[level] || level || ''
     },
     riskLevelIndex: function(level) {
@@ -169,7 +169,7 @@ export default {
           self.knowledgeData = {
             itemName: v3['�称'] || name,
             category: v3['说明'] || '',
-            description: (high ? '�高影�� + high + '\n' : '') + (low ? '�低影�� + low : ''),
+            description: (high ? '�高影�:' + high + '\n' : '') + (low ? '�低影�:' + low : ''),
             suggestion: v3['调整建议'] || ''
           }
           self.knowledgeVisible = true

+ 15 - 15
cfc-frontend/pages/health/gut-flora-species-detail.vue

@@ -2,7 +2,7 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">��?返回</text>
+        <text class="back-text">返回</text>
       </view>
       <text class="nav-title">菌群详情</text>
       <text class="nav-edit" @tap="toggleEdit">{{ isEditing ? '完成' : '编辑' }}</text>
@@ -22,25 +22,25 @@
           <text class="flora-name" :class="'status-' + (item._cssClass || 'normal')"
                 @tap="showKnowledge('bacteria', item.bacteriaName)">
             {{ item.bacteriaName }}
-            <text class="arrow-up" v-if="item.status === '偏高' || item.status === '过多'"> ��?/text>
-            <text class="arrow-down" v-else-if="item.status === '偏低' || item.status === '缺乏' || item.status === '不足'"> ��?/text>
+            <text class="arrow-up" v-if="item.status === '偏高' || item.status === '过多'"> ↑</text>
+            <text class="arrow-down" v-else-if="item.status === '偏低' || item.status === '缺乏' || item.status === '不足'"> ↓</text>
           </text>
           <text class="flora-level-tag" v-if="item.level && item.level !== 'GENUS'">{{ item.level }}</text>
         </view>
         <view class="flora-details" v-if="!isEditing">
           <text class="detail-text">丰度 {{ item.bacteriaValue || '--' }} | 正常 {{ item.normalRange || '--' }}</text>
-          <text class="detail-text">人群 {{ item.populationLevel || '--' }} | 检��?{{ item.detectionRate || '--' }}</text>
+          <text class="detail-text">人群 {{ item.populationLevel || '--' }} | 检{{ item.detectionRate || '--' }}</text>
         </view>
         <view class="flora-edit-row" v-if="isEditing">
           <text class="edit-label">丰度:</text>
           <input class="edit-input" type="text" v-model="item.bacteriaValue" />
-          <text class="edit-label">状��?</text>
+          <text class="edit-label">状态:</text>
           <picker :value="floraStatusIndex(item.status)" :range="floraStatuses" @change="onFloraStatusChange($event, item)">
             <text class="edit-picker">{{ item.status || '正常' }}</text>
           </picker>
         </view>
       </view>
-      <view class="empty-hint" v-if="filteredFlora.length === 0">暂无该分类菌属数��?/view>
+      <view class="empty-hint" v-if="filteredFlora.length === 0">暂无该分类菌属数据</view>
       <view class="bottom-spacer"></view>
     </scroll-view>
 
@@ -73,11 +73,11 @@ export default {
       knowledgeData: {},
       tabs: [
         { key: 'core', label: '核心菌属' },
-        { key: 'probiotic', label: '益生��? },
-        { key: 'harmful', label: '有害��? },
+        { key: 'probiotic', label: '益生菌' },
+        { key: 'harmful', label: '有害菌' },
         { key: 'other', label: '其它菌属' },
         { key: 'pathogen_genus', label: '病原菌属' },
-        { key: 'pathogen_detection', label: '病原菌检��? },
+        { key: 'pathogen_detection', label: '病原菌检出' },
         { key: 'taxonomy_class', label: '菌纲' },
         { key: 'taxonomy_order', label: '菌目' },
         { key: 'taxonomy_family', label: '菌科' },
@@ -138,7 +138,7 @@ export default {
   },
   methods: {
     goBack: function() { uni.navigateBack() },
-    /** 中文状��?��?CSS安全英文 */
+    /** 中文状态 → CSS安全英文 */
     _cssForStatus: function(s) {
       var map = { '偏高': 'high', '过多': 'excess', '偏低': 'low', '缺乏': 'deficient', '不足': 'insufficient' }
       return map[s] || 'normal'
@@ -171,7 +171,7 @@ export default {
       var self = this
       editHealthReport(self.reportId, { gutFlora: self.editFlora }, 0).then(function(res) {
         if (res.code === 200) {
-          uni.showToast({ title: '已保��?, icon: 'success' })
+          uni.showToast({ title: '已保存', icon: 'success' })
           self.isEditing = false
           self.loadData()
         } else {
@@ -196,12 +196,12 @@ export default {
           var low = v3['偏低影响'] || ''
           var direction = v3['调整方向'] || ''
           var suggestion = ''
-          if (high) suggestion += '偏高影响��? + high + '\n'
-          if (low) suggestion += '偏低影响��? + low + '\n'
-          if (direction) suggestion += '调整方向��? + direction
+          if (high) suggestion += '偏高影响:' + high + '\n'
+          if (low) suggestion += '偏低影响:' + low + '\n'
+          if (direction) suggestion += '调整方向:' + direction
           self.knowledgeData = {
             itemName: v3['学名'] || name,
-            category: (v3['中文��?] ? v3['中文��?] + ' ' : '') + (v3['分组'] || ''),
+            category: (v3['中文名'] ? v3['中文名'] + ' ' : '') + (v3['分组'] || ''),
             description: v3['功能说明'] || '',
             suggestion: suggestion.trim()
           }

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

@@ -2,7 +2,7 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">窶?霑泌屓</text>
+        <text class="back-text">窶霑泌屓</text>
       </view>
       <text class="nav-title">闖檎セ、</text>
     </view>
@@ -12,19 +12,19 @@
         <view class="card-accent"></view>
         <view class="card-body">
           <text class="card-title">隶、隸�あ驕楢曙鄒、</text>
-          <text class="card-desc">閧�驕楢曙鄒、譏ッ逕滓エサ蝨ィ莠コ菴楢あ驕灘�逧�セョ逕溽黄鄒、關ス�瑚「ォ遘ー荳コ莠コ菴鍋噪"隨ャ莠悟渕蝗�扈?縲ょョ�サャ蟇ケ蛛・蠎キ襍キ逹€閾ウ蜈ウ驥崎ヲ∫噪菴懃畑��</text>
+          <text class="card-desc">閧�驕楢曙鄒、譏ッ逕滓エサ蝨ィ莠コ菴楢あ驕灘�逧�セョ逕溽黄鄒、關ス�瑚「ォ遘ー荳コ莠コ菴鍋噪"隨ャ莠悟渕蝗�扈�"縲ょョ�サャ蟇ケ蛛・蠎キ襍キ逹€閾ウ蜈ウ驥崎ヲ∫噪菴懃畑��</text>
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">蟶ョ蜉ゥ豸亥喧蜷ク謾カ</text>
-              <text class="info-desc">蛻�ァ」鬟溽黄荳ュ逧�コ、扈エ邏��悟粋謌千サエ逕溽エ?K 蜥?B 譌冗サエ逕溽エ��御ソ�ソ幄是蜈サ蜷ク謾カ縲?/text>
+              <text class="info-desc">蛻�ァ」鬟溽黄荳ュ逧�コ、扈エ邏��悟粋謌千サエ逕溽エ� K 蜥� B 譌冗サエ逕溽エ��御ソ�ソ幄是蜈サ蜷ク謾カ縲�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">蠅槫シコ蜈咲稔蜉?/text>
-              <text class="info-desc">隹�鰍蜈咲稔邉サ扈溷粥閭ス�梧慣謚玲怏螳ウ闖悟�萓オ�悟㍼蟆題ソ�撫蜥梧─譟馴」朱勦縲?/text>
+              <text class="info-age">蠅槫シコ蜈咲稔蜉�</text>
+              <text class="info-desc">隹�鰍蜈咲稔邉サ扈溷粥閭ス�梧慣謚玲怏螳ウ闖悟�萓オ�悟㍼蟆題ソ�撫蜥梧─譟馴」朱勦縲�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">蠖ア蜩肴ュ扈ェ蜥瑚ョ、遏?/text>
-              <text class="info-desc">騾夊ソ�"閧�閼題ス?蠖ア蜩咲・樒サ城€定エィ莠ァ逕滂シ悟ッケ諠�サェ縲∝視蜉帛柱逹。逵�譛蛾㍾隕∽ス懃畑縲?/text>
+              <text class="info-age">蠖ア蜩肴ュ扈ェ蜥瑚ョ、遏・</text>
+              <text class="info-desc">騾夊ソ�"閧�閼題スエ"蠖ア蜩咲・樒サ城€定エィ莠ァ逕滂シ悟ッケ諠�サェ縲∝視蜉帛柱逹。逵�譛蛾㍾隕∽ス懃畑縲�</text>
             </view>
           </view>
         </view>
@@ -33,23 +33,23 @@
       <view class="card">
         <view class="card-accent"></view>
         <view class="card-body">
-          <text class="card-title">譛臥寢闖碁」溽�?/text>
+          <text class="card-title">譛臥寢闖碁」溽黄</text>
           <view class="info-list">
             <view class="info-item">
-              <text class="info-age">�・� 蜿鷹�荵ウ蛻カ蜩?/text>
-              <text class="info-desc">驟ク螂カ縲∝シ€闖イ蟆斐€∝書驟オ荵ウ蟇悟性逶顔函闖鯉シ檎峩謗・陦・蜈�あ驕捺怏逶願曙鄒、縲?/text>
+              <text class="info-age">�・� 蜿鷹�荵ウ蛻カ蜩�</text>
+              <text class="info-desc">驟ク螂カ縲∝シ€闖イ蟆斐€∝書驟オ荵ウ蟇悟性逶顔函闖鯉シ檎峩謗・陦・蜈�あ驕捺怏逶願曙鄒、縲�</text>
             </view>
             <view class="info-item">
               <text class="info-age">�・� 蜿鷹�阡ャ闖�</text>
-              <text class="info-desc">豕。闖懊€��闖懊€∫コウ雎�ュ牙書驟オ鬟溷刀蜷ォ譛我クー蟇檎寢逕溯曙蜥碁��御ソ�ソ幄あ驕灘▼蠎キ縲?/text>
+              <text class="info-desc">豕。闖懊€��闖懊€∫コウ雎�ュ牙書驟オ鬟溷刀蜷ォ譛我クー蟇檎寢逕溯曙蜥碁��御ソ�ソ幄あ驕灘▼蠎キ縲�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">�諺 鬮倡コ、扈エ鬟溽�?/text>
-              <text class="info-desc">辯暮コヲ縲�ヲ呵負縲∵エ玖続縲∝、ァ闥懊€∬寒隨狗ュ牙ッ悟性逶顔函蜈�シ御クコ譛臥寢闖梧署萓帛�譁吶€?/text>
+              <text class="info-age">�諺 鬮倡コ、扈エ鬟溽黄</text>
+              <text class="info-desc">辯暮コヲ縲�ヲ呵負縲∵エ玖続縲∝、ァ闥懊€∬寒隨狗ュ牙ッ悟性逶顔函蜈�シ御クコ譛臥寢闖梧署萓帛�譁吶€�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">�克 螟夐�邀サ鬟溽�?/text>
-              <text class="info-desc">闢晁雌縲∝庄蜿ッ縲∫サソ闌カ縲∵�ク譯�ッ悟性螟夐��御ソ�ソ帶怏逶願曙逕滄柄�梧椛蛻カ譛牙ョウ闖後€?/text>
+              <text class="info-age">�克 螟夐�邀サ鬟溽黄</text>
+              <text class="info-desc">闢晁雌縲∝庄蜿ッ縲∫サソ闌カ縲∵�ク譯�ッ悟性螟夐��御ソ�ソ帶怏逶願曙逕滄柄�梧椛蛻カ譛牙ョウ闖後€�</text>
             </view>
           </view>
         </view>
@@ -62,19 +62,19 @@
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">蝮�。。鬣ョ鬟�</text>
-              <text class="info-desc">螟壽�キ蛹夜・ョ鬟滂シ悟、壼帥阡ャ闖懈ーエ譫懷柱蜈ィ隹キ迚ゥ�御クコ閧�驕楢曙鄒、謠蝉セ帑クー蟇檎噪關・蜈サ譚・貅舌€?/text>
+              <text class="info-desc">螟壽�キ蛹夜・ョ鬟滂シ悟、壼帥阡ャ闖懈ーエ譫懷柱蜈ィ隹キ迚ゥ�御クコ閧�驕楢曙鄒、謠蝉セ帑クー蟇檎噪關・蜈サ譚・貅舌€�</text>
             </view>
             <view class="info-item">
               <text class="info-age">蜈�カウ豌エ蛻�</text>
-              <text class="info-desc">豈丞、ゥ鬣ョ逕ィ雜ウ螟溽噪豌エ�御ソ�ソ幄あ驕楢�募勘�悟クョ蜉ゥ豸亥喧蜥梧賜萓ソ縲?/text>
+              <text class="info-desc">豈丞、ゥ鬣ョ逕ィ雜ウ螟溽噪豌エ�御ソ�ソ幄あ驕楢�募勘�悟クョ蜉ゥ豸亥喧蜥梧賜萓ソ縲�</text>
             </view>
             <view class="info-item">
               <text class="info-age">隗�セ玖ソ仙勘</text>
-              <text class="info-desc">騾ょコヲ霑仙勘菫�ソ幄あ驕楢�募勘�悟「槫刈閧�驕楢曙鄒、螟壽�キ諤ァ�梧隼蝟�あ驕鍋識蠅�€?/text>
+              <text class="info-desc">騾ょコヲ霑仙勘菫�ソ幄あ驕楢�募勘�悟「槫刈閧�驕楢曙鄒、螟壽�キ諤ァ�梧隼蝟�あ驕鍋識蠅�€�</text>
             </view>
             <view class="info-item">
-              <text class="info-age">蜷育炊菴ソ逕ィ謚礼函邏?/text>
-              <text class="info-desc">謚礼函邏�莨夂�エ蝮剰あ驕楢曙鄒、蟷ウ陦。�碁�蛹サ蝌ア菴ソ逕ィ�悟ソ�ヲ∵慮陦・蜈�寢逕溯曙縲?/text>
+              <text class="info-age">蜷育炊菴ソ逕ィ謚礼函邏�</text>
+              <text class="info-desc">謚礼函邏�莨夂�エ蝮剰あ驕楢曙鄒、蟷ウ陦。�碁�蛹サ蝌ア菴ソ逕ィ�悟ソ�ヲ∵慮陦・蜈�寢逕溯曙縲�</text>
             </view>
           </view>
         </view>
@@ -82,7 +82,7 @@
 
       <view class="action-section">
         <view class="action-btn" @tap="goToReportUpload">
-          <text class="action-btn-text">荳贋シ�譽€豬区冠蜻?/text>
+          <text class="action-btn-text">荳贋シ�譽€豬区冠蜻�</text>
         </view>
         <view class="action-btn-secondary" @tap="goToMyReport">
           <text class="action-btn-secondary-text">譟・逵区�逧�曙鄒、謚・蜻�</text>
@@ -141,7 +141,7 @@ export default {
         childId = userId
       }
       if (!childId) {
-        uni.showToast({ title: '譛ェ謇セ蛻ー蟄ゥ蟄蝉ソ。諱?, icon: 'none' })
+        uni.showToast({ title: '譛ェ謇セ蛻ー蟄ゥ蟄蝉ソ。諱ッ', icon: 'none' })
         return
       }
       healthRequest('/api/health/report/latest', { childId: childId }).then(function(res) {

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

@@ -2,14 +2,14 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">�返回</text>
+        <text class="back-text">‹ 返回</text>
       </view>
       <text class="nav-title">冥想记录</text>
     </view>
 
     <!-- �员选择 -->
     <view class="member-selector-card">
-      <text class="member-label">记录�/text>
+      <text class="member-label">记录人</text>
       <picker mode="selector" :range="memberOptions" :value="selectedMemberIndex" @change="onMemberChange">
         <view class="picker-display">{{ memberOptions[selectedMemberIndex] }}</view>
       </picker>
@@ -69,7 +69,7 @@ export default {
     return {
       childId: null,
       selectedMemberIndex: 0,
-      memberOptions: ['我自�],
+      memberOptions: ['我自己'],
       memberIds: [],
       meditationType: 'breathing',
       duration: '',
@@ -94,7 +94,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.childId })
-          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() {})
     },
@@ -109,7 +109,7 @@ export default {
     },
     submitMeditation: function() {
       if (!this.duration || parseInt(this.duration) <= 0) {
-        uni.showToast({ title: '请输入有效时�, icon: 'none' })
+        uni.showToast({ title: '请输入有效时长', icon: 'none' })
         return
       }
       var data = {
@@ -121,7 +121,7 @@ export default {
         data.childId = this.childId
         data.memberId = this.childId
       }
-      uni.showLoading({ title: '�存�..' })
+      uni.showLoading({ title: '�存中...' })
       healthRequest('/api/health/meditation/create', data).then(function() {
         uni.hideLoading()
         uni.showToast({ title: '�存�功', icon: 'success' })

+ 12 - 12
cfc-frontend/pages/health/nutrition-profile.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="nutrition-profile">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">��?返回</text>
+      <text class="nav-back" @click="goBack">返回</text>
       <text class="nav-title">营养档案</text>
       <view class="nav-placeholder"></view>
     </view>
@@ -9,7 +9,7 @@
     <view class="profile-header" v-if="childName">
       <view class="child-info">
         <text class="child-name">{{ childName }}</text>
-        <text class="child-age" v-if="childAge">{{ childAge }}��?/text>
+        <text class="child-age" v-if="childAge">{{ childAge }}岁</text>
       </view>
     </view>
 
@@ -47,14 +47,14 @@
       <text class="empty-title">暂无健康报告</text>
       <text class="empty-desc">完成首次健康检测后,这里将展示您的营养档案</text>
       <view class="empty-btn" @click="goToAssessment">
-        <text class="empty-btn-text">预约健康检��?/text>
+        <text class="empty-btn-text">预约健康检测</text>
       </view>
     </view>
 
     <view class="section" v-if="abnormalIndicators && abnormalIndicators.length > 0">
       <view class="section-title-wrap">
         <text class="section-title">⚠️ 需关注指标</text>
-        <text class="section-count">{{ abnormalIndicators.length }}��?/text>
+        <text class="section-count">{{ abnormalIndicators.length }}项</text>
       </view>
       <view class="indicator-list">
         <view class="indicator-item" v-for="item in abnormalIndicators" :key="item.id">
@@ -68,7 +68,7 @@
         </view>
       </view>
       <view class="section-more" @click="goToIndicators">
-        <text class="section-more-text">查看全部指标 ��?/text>
+        <text class="section-more-text">查看全部指标 →</text>
       </view>
     </view>
 
@@ -94,7 +94,7 @@
     <view class="section" v-if="deficiencyRecords && deficiencyRecords.length > 0">
       <view class="section-title-wrap">
         <text class="section-title">🔬 营养缺乏分析</text>
-        <text class="section-count">{{ deficiencyRecords.length }}��?/text>
+        <text class="section-count">{{ deficiencyRecords.length }}项</text>
       </view>
       <view class="deficiency-list">
         <view class="deficiency-item" v-for="record in deficiencyRecords" :key="record.nutrient">
@@ -124,7 +124,7 @@
           </view>
           <view class="report-item-score">
             <text class="report-score-val">{{ r.overallScore || '--' }}</text>
-            <text class="report-score-label">��?/text>
+            <text class="report-score-label">分</text>
           </view>
         </view>
       </view>
@@ -176,7 +176,7 @@ export default {
     loadProfile: function() {
       var self = this
       self.loading = true
-      uni.showLoading({ title: '加载��?..' })
+      uni.showLoading({ title: '加载中...' })
       getChildNutritionProfile(self.childId).then(function(res) {
         uni.hideLoading()
         self.loading = false
@@ -262,8 +262,8 @@ export default {
         return '轻度不足'
       }
       if (record.deficiencyType === 'excess') return '偏高'
-      if (record.deficiencyType === 'borderline') return '边界��?
-      return '未分��?
+      if (record.deficiencyType === 'borderline') return '边界值'
+      return '未分类'
     },
     getSeverityColor: function(severity) {
       if (severity >= 0.7) return '#EF4444'
@@ -271,9 +271,9 @@ export default {
       return '#10B981'
     },
     getReportTypeName: function(type) {
-      if (type === 'gut_flora') return '肠道检��?
+      if (type === 'gut_flora') return '肠道检测'
       if (type === 'physical_exam') return '体检报告'
-      if (type === 'blood') return '血液检��?
+      if (type === 'blood') return '血液检测'
       return type || '健康报告'
     },
     formatDate: function(dateStr) {

+ 26 - 26
cfc-frontend/pages/health/physical-exam-detail.vue

@@ -1,15 +1,15 @@
 <template>
   <view class="detail-container">
-    <!-- 导航�-->
+    <!-- 导航æ -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�返回</text>
+      <text class="nav-back" @click="goBack">‹ 返回</text>
       <text class="nav-title">体检报告详情</text>
       <view class="nav-placeholder"></view>
     </view>
 
-    <!-- 加载状�-->
+    <!-- 加载状æ€-->
     <view class="loading-wrap" v-if="loading">
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
     <template v-else>
@@ -26,7 +26,7 @@
           </view>
           <view class="summary-row">
             <text class="summary-label">综�评分</text>
-            <text class="summary-score" :class="scoreClass">{{ report.overallScore || '--' }}<text class="score-unit">�/text></text>
+            <text class="summary-score" :class="scoreClass">{{ report.overallScore || '--' }}<text class="score-unit">分</text></text>
           </view>
           <view class="summary-row">
             <text class="summary-label">报告编�</text>
@@ -34,7 +34,7 @@
           </view>
           <view class="summary-row">
             <text class="summary-label">备注</text>
-            <text class="summary-value">{{ report.remark || 'æ—? }}</text>
+            <text class="summary-value">{{ report.remark || 'æ— ' }}</text>
           </view>
         </view>
       </view>
@@ -44,14 +44,14 @@
         <view class="group-header">
           <text class="group-icon">{{ getCategoryIcon(groupName) }}</text>
           <text class="group-title">{{ groupName }}</text>
-          <text class="group-count">{{ group.length }}é¡?/text>
+          <text class="group-count">{{ group.length }}项</text>
         </view>
 
         <view class="indicator-list">
           <view class="indicator-item" v-for="(ind, idx) in group" :key="idx">
             <view class="indicator-left">
               <text class="indicator-name">{{ ind.indicatorName }}</text>
-              <text class="indicator-range" v-if="ind.refRange">�考� {{ ind.refRange }}</text>
+              <text class="indicator-range" v-if="ind.refRange">�考值: {{ ind.refRange }}</text>
             </view>
             <view class="indicator-right">
               <text class="indicator-value" :class="ind.statusClass">{{ ind.indicatorValue }}</text>
@@ -62,7 +62,7 @@
         </view>
       </view>
 
-      <!-- 空状�-->
+      <!-- 空状æ€-->
       <view class="empty-wrap" v-if="!loading && indicators.length === 0">
         <text class="empty-icon">📋</text>
         <text class="empty-text">暂无指标数�</text>
@@ -103,8 +103,8 @@ export default {
         groups[cat].push(ind)
       })
       // 按分类排�,常用分类在�
-      var priority = ['血常规', '�功�, '肾功�, '血�, '血�, '尿常�, '便常�,
-        '甲状腺功�, '肿瘤标志�, '维生�, '微�元素', '�养状况', '炎症指标',
+      var priority = ['血常规', '�功能', '肾功能', '血脂', '血糖', '尿常规', '便常规',
+        '甲状腺功能', '肿瘤标志物', '维生素', '微�元素', '�养状况', '炎症指标',
         '�疫指标', '其他指标']
       var sorted = {}
       priority.forEach(function(p) {
@@ -168,34 +168,34 @@ export default {
     getCategoryIcon: function(cat) {
       var icons = {
         '血常规': '🩸',
-        '�功�: '�',
-        '肾功�: '🫘',
-        '血�: '🫧',
-        '血�: '�',
-        '尿常�: '💧',
-        '便常�: '💩',
-        '甲状腺功�: '🦋',
-        '肿瘤标志�: '🔬',
-        '维生�: '�',
+        '�功能': '�',
+        '肾功能': '🫘',
+        '血脂': '🫧',
+        '血糖': '�',
+        '尿常规': '💧',
+        '便常规': '💩',
+        '甲状腺功能': '🦋',
+        '肿瘤标志物': '🔬',
+        '维生素': '�',
         '微�元素': '⚗�',
         '�养状况': '🥗',
         '炎症指标': '🔥',
-        '�疫指标': '🛡�,
+        '�疫指标': '🛡�',
       }
       return icons[cat] || '📊'
     },
     getStatusClass: function(ind) {
       var status = (ind.status || '').toLowerCase()
-      if (status.indexOf('�高') !== -1 || status.indexOf('�) !== -1 || status.indexOf('过多') !== -1) {
+      if (status.indexOf('�高') !== -1 || status.indexOf('高') !== -1 || status.indexOf('过多') !== -1) {
         return 'status-high'
       }
-      if (status.indexOf('�低') !== -1 || status.indexOf('�) !== -1 || status.indexOf('缺�') !== -1) {
+      if (status.indexOf('�低') !== -1 || status.indexOf('低') !== -1 || status.indexOf('缺�') !== -1) {
         return 'status-low'
       }
       if (status.indexOf('注�') !== -1 || status.indexOf('风险') !== -1) {
         return 'status-warn'
       }
-      if (status.indexOf('正常') !== -1 || status.indexOf('未检�) !== -1) {
+      if (status.indexOf('正常') !== -1 || status.indexOf('未检出') !== -1) {
         return 'status-normal'
       }
       return ''
@@ -322,13 +322,13 @@ goBack: function() {
 .indicator-unit { font-size: 22rpx; color: #999; }
 .indicator-status { font-size: 20rpx; padding: 2rpx 10rpx; border-radius: 10rpx; }
 
-/* 状�颜�*/
+/* 状�颜色 */
 .status-high { color: #C62828; }
 .status-low { color: #E65100; }
 .status-warn { color: #F57F17; }
 .status-normal { color: #2E7D32; }
 
-/* 空状�*/
+/* 空状æ€*/
 .empty-wrap {
   display: flex;
   flex-direction: column;

+ 37 - 37
cfc-frontend/pages/health/report-confirm.vue

@@ -1,20 +1,20 @@
 <template>
   <view class="confirm-container">
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�?餈𥪜�</text>
+      <text class="nav-back" @click="goBack">�餈𥪜�</text>
       <text class="nav-title">蝖株恕�亙熒�亙�</text>
       <view class="nav-placeholder"></view>
     </view>
 
     <view class="tip-banner">
-      <text class="tip-icon">�?/text>
+      <text class="tip-icon">��</text>
       <text class="tip-text">霂瑟瓲撖嫣誑銝贝圾�𣂼�摰對��臭耨�孵�蝖株恕�亙�</text>
     </view>
 
-    <!-- �寥��臭縑摨?-->
+    <!-- �寥��臭縑摨-->
     <view class="confidence-card" v-if="confidenceLevelClass">
       <view class="confidence-header">
-        <text class="confidence-label">�寥��臭縑摨?/text>
+        <text class="confidence-label">�寥��臭縑摨�</text>
         <text class="confidence-badge" :class="'badge-' + confidenceLevelClass">{{ confidenceLevelText }}</text>
       </view>
       <view class="confidence-bar-track">
@@ -29,12 +29,12 @@
         <view class="card-title">�箸𧋦靽⊥�</view>
         <view class="field-row">
           <text class="field-label">鋡急�瘚衤犖</text>
-          <text class="field-value" v-if="!needBind">{{ extractedName || '�芾��? }}</text>
+          <text class="field-value" v-if="!needBind">{{ extractedName || '�芾���' }}</text>
           <text class="field-value binding-required" v-else>���见𢆡蝏穃�</text>
         </view>
         <view class="field-row" v-if="extractedGender">
           <text class="field-label">�批�</text>
-          <text class="field-value">{{ extractedGender === 'male' ? '�? : extractedGender === 'female' ? '憟? : extractedGender }}</text>
+          <text class="field-value">{{ extractedGender === 'male' ? '��' : extractedGender === 'female' ? '憟�' : extractedGender }}</text>
         </view>
         <view class="field-row" v-if="extractedAge">
           <text class="field-label">撟湧�</text>
@@ -46,7 +46,7 @@
         </view>
         <view class="field-row" v-if="payload.summary && payload.type !== 'tongue'">
           <text class="field-label">�亙��交�</text>
-          <input class="field-input" type="text" v-model="payload.summary.reportDate" placeholder="憒? 2025-06-15" />
+          <input class="field-input" type="text" v-model="payload.summary.reportDate" placeholder="憒�: 2025-06-15" />
         </view>
         <view class="field-row" v-if="payload.summary && payload.type !== 'tongue'">
           <text class="field-label">�亙��䁅�</text>
@@ -58,9 +58,9 @@
       <view class="card" v-if="needBind">
         <view class="card-title">�㗇𥋘摰嗅滬�𣂼�</view>
 
-        <!-- �䠷�匧龪�滚�銵剁��厩蔭靽∪漲�鍦�嚗?-->
+        <!-- �䠷�匧龪�滚�銵剁��厩蔭靽∪漲�鍦�嚗-->
         <view class="candidate-section" v-if="candidates.length > 0">
-          <text class="candidate-section-hint">隞乩��𣂼�銝擧𥁒�𠹺縑�臬龪�㵪�霂琿�㗇𥋘嚗?/text>
+          <text class="candidate-section-hint">隞乩��𣂼�銝擧𥁒�𠹺縑�臬龪�㵪�霂琿�㗇𥋘嚗�</text>
           <view
             class="candidate-item"
             v-for="(cand, idx) in candidates"
@@ -72,7 +72,7 @@
               <text class="candidate-avatar">{{ (cand.nickname || cand.name || '?').substring(0, 1) }}</text>
               <view class="candidate-info">
                 <text class="candidate-name">{{ cand.nickname || cand.name || '�芰䰻' }}</text>
-                <text class="candidate-detail" v-if="cand.gender || cand.age">{{ genderText(cand.gender) }}{{ cand.age ? ' 繚 ' + cand.age + '撗? : '' }}</text>
+                <text class="candidate-detail" v-if="cand.gender || cand.age">{{ genderText(cand.gender) }}{{ cand.age ? ' 繚 ' + cand.age + '撗�' : '' }}</text>
                 <text class="candidate-fields" v-if="cand.matchFields">�寥�: {{ cand.matchFields }}</text>
               </view>
             </view>
@@ -101,7 +101,7 @@
 
         <!-- �啣遣�𣂼��亙藁 -->
         <view class="create-member-entry" @click="toggleAutoCreate">
-          <text class="create-member-icon">嚗?/text>
+          <text class="create-member-icon">嚗�</text>
           <text class="create-member-text">{{ showAutoCreateForm ? '�嗉絲�啣遣銵典�' : '銝滚銁�𡑒”銝哨��啣遣摰嗅滬�𣂼�' }}</text>
         </view>
       </view>
@@ -111,21 +111,21 @@
         <view class="card-title">�啣遣摰嗅滬�𣂼�</view>
         <view class="form-item">
           <text class="form-item-label">憪枏�</text>
-          <input class="form-item-input" v-model="newMember.name" placeholder="霂瑁��亙��? />
+          <input class="form-item-input" v-model="newMember.name" placeholder="霂瑁��亙���" />
         </view>
         <view class="form-item">
           <text class="form-item-label">�批�</text>
           <view class="gender-selector">
-            <text class="gender-option" :class="{ 'gender-selected': newMember.gender === 'male' }" @click="newMember.gender = 'male'">�?/text>
-            <text class="gender-option" :class="{ 'gender-selected': newMember.gender === 'female' }" @click="newMember.gender = 'female'">憟?/text>
+            <text class="gender-option" :class="{ 'gender-selected': newMember.gender === 'male' }" @click="newMember.gender = 'male'">��</text>
+            <text class="gender-option" :class="{ 'gender-selected': newMember.gender === 'female' }" @click="newMember.gender = 'female'">憟�</text>
           </view>
         </view>
         <view class="form-item">
           <text class="form-item-label">撟湧�</text>
-          <input class="form-item-input" type="number" v-model="newMember.age" placeholder="霂瑁��亙僑樴? />
+          <input class="form-item-input" type="number" v-model="newMember.age" placeholder="霂瑁��亙僑樴�" />
         </view>
         <view class="btn-create-submit" :class="{ 'btn-disabled': creatingMember }" @click="doAutoCreate">
-          <text v-if="creatingMember">�𥕦遣銝?..</text>
+          <text v-if="creatingMember">�𥕦遣銝�...</text>
           <text v-else>蝖株恕�𥕦遣</text>
         </view>
       </view>
@@ -154,7 +154,7 @@
             <input class="ind-value" v-model="payload.indicators[idx].value" />
           </view>
           <view class="ind-detail" v-if="payload.indicators[idx].unit || payload.indicators[idx].referenceRange">
-            <text class="ind-ref" v-if="payload.indicators[idx].referenceRange">���? {{ payload.indicators[idx].referenceRange }}</text>
+            <text class="ind-ref" v-if="payload.indicators[idx].referenceRange">����: {{ payload.indicators[idx].referenceRange }}</text>
             <text class="ind-unit" v-if="payload.indicators[idx].unit">{{ payload.indicators[idx].unit }}</text>
           </view>
           <view class="ind-symptoms" v-if="payload.indicators[idx].symptoms">
@@ -207,7 +207,7 @@
           <text>�曉�</text>
         </view>
         <view class="btn-confirm" :class="{ 'btn-disabled': !canConfirm }" @click="doConfirm">
-          <text v-if="confirming">蝖株恕銝?..</text>
+          <text v-if="confirming">蝖株恕銝�...</text>
           <text v-else>蝖株恕�亙�</text>
         </view>
       </view>
@@ -243,7 +243,7 @@ export default {
       selectedMemberId: null,
       familyMembers: [],
       confirming: false,
-      // Phase 2: �寥��臭縑摨虫��䠷�?
+      // Phase 2: �寥��臭縑摨虫��䠷�
       matchConfidence: null,
       matchLabel: '',
       candidates: [],
@@ -273,7 +273,7 @@ export default {
       return 'none'
     },
     confidenceLevelText() {
-      var map = { high: '擃?, medium: '銝?, low: '雿?, none: '�芸龪�? }
+      var map = { high: '擃�', medium: '銝�', low: '雿�', none: '�芸龪��' }
       return map[this.confidenceLevelClass] || ''
     },
     confidencePercent() {
@@ -282,9 +282,9 @@ export default {
     },
     confidenceDesc() {
       if (this.matchLabel === 'exact') return '�寞旿憪枏����批���僑樴�䌊�函移蝖桀龪�滚�摰嗅滬�𣂼�'
-      if (this.matchLabel === 'fuzzy') return '�典�摮埈挾�寥�嚗諹窈蝖株恕�臬炏銝箔誑銝见振摨剜��?
+      if (this.matchLabel === 'fuzzy') return '�典�摮埈挾�寥�嚗諹窈蝖株恕�臬炏銝箔誑銝见振摨剜���'
       if (this.matchLabel === 'profile_match') return '�寞旿獢��靽⊥��冽��寥�嚗諹窈�见𢆡蝖株恕'
-      if (this.matchLabel === 'no_match') return '�䭾��寥��啁緵�匧振摨剜��矋��舀鰵撱箸��?
+      if (this.matchLabel === 'no_match') return '�䭾��寥��啁緵�匧振摨剜��矋��舀鰵撱箸���'
       return ''
     }
   },
@@ -313,7 +313,7 @@ export default {
     this.extractedAge = options.extractedAge || ''
     this.matchedMemberId = options.matchedMemberId ? parseInt(options.matchedMemberId) : null
 
-    // 隞舘圾�鞟��𨅯‵��𥁒�𦠜𠯫�?
+    // 隞舘圾�鞟��𨅯‵��𥁒�𦠜𠯫�
     var extractedReportDate = options.extractedReportDate || ''
     if (extractedReportDate && this.payload.summary) {
       this.payload.summary.reportDate = extractedReportDate
@@ -322,7 +322,7 @@ export default {
     this.matchConfidence = options.matchConfidence ? parseFloat(options.matchConfidence) : null
     this.matchLabel = decodeURIComponent(options.matchLabel || '')
 
-    // 閫���䠷�㗇��睃�銵?
+    // 閫���䠷�㗇��睃�銵
     var candidatesStr = decodeURIComponent(options.candidates || '')
     if (candidatesStr) {
       try {
@@ -332,14 +332,14 @@ export default {
       }
     }
 
-    // �匧�䠷�㗇𧒄隡睃�撅閧內�䠷�匧�銵?
+    // �匧�䠷�㗇𧒄隡睃�撅閧內�䠷�匧�銵
     if (this.candidates.length > 0) {
       this.showCandidatesOnly = true
     }
 
     if (this.needBind) {
       this.loadFamilyMembers()
-      // 擃条蔭靽∪漲銝𥪜歇�寥� �?�湔𦻖�劐葉
+      // 擃条蔭靽∪漲銝𥪜歇�寥� ��湔𦻖�劐葉
       if (this.matchedMemberId && this.matchConfidence >= 0.8) {
         this.selectedMemberId = this.matchedMemberId
       }
@@ -368,8 +368,8 @@ export default {
     },
     // === Phase 2: �䠷�匧龪�滢��啣遣�𣂼� ===
     genderText(gender) {
-      if (gender === 'male') return '�?
-      if (gender === 'female') return '憟?
+      if (gender === 'male') return '��'
+      if (gender === 'female') return '憟�'
       return gender || ''
     },
     selectCandidate(candidate) {
@@ -388,7 +388,7 @@ export default {
     doAutoCreate() {
       var self = this
       if (!this.newMember.name) {
-        uni.showToast({ title: '霂瑁��交��睃��?, icon: 'none' })
+        uni.showToast({ title: '霂瑁��交��睃���', icon: 'none' })
         return
       }
       self.creatingMember = true
@@ -425,9 +425,9 @@ export default {
       return '甇�虜'
     },
     riskLevelText(level) {
-      if (level === 'high') return '擃㗛��?
-      if (level === 'medium' || level === 'moderate') return '銝剝��?
-      return '雿𡡞��?
+      if (level === 'high') return '擃㗛���'
+      if (level === 'medium' || level === 'moderate') return '銝剝���'
+      return '雿𡡞���'
     },
     doConfirm() {
       if (!this.canConfirm) return
@@ -439,7 +439,7 @@ export default {
         draftId: self.draftId,
         payload: self.payload
       }
-      // 隡睃�蝥? 撌脤�㗇��?> �啣遣�𣂼� > �芸𢆡�寥�(擃条蔭靽∪漲) > 摮躶D
+      // 隡睃�蝥�: 撌脤�㗇��� > �啣遣�𣂼� > �芸𢆡�寥�(擃条蔭靽∪漲) > 摮躶D
       if (self.selectedMemberId) {
         postData.subjectId = self.selectedMemberId
       } else if (self.createdMemberId) {
@@ -483,12 +483,12 @@ export default {
       var self = this
       uni.showModal({
         title: '蝖株恕�曉�',
-        content: '�曉��舘圾�鞉㺭�桀�鋡怠��歹���閬���唬�隡?,
+        content: '�曉��舘圾�鞉㺭�桀�鋡怠��歹���閬���唬�隡�',
         success: function(res) {
           if (res.confirm) {
             var discardFn = self.payload.type === 'tongue' ? discardTongue : discardReportDraft
             discardFn({ draftId: self.draftId }).then(function() {
-              uni.showToast({ title: '撌脫𦆮撘?, icon: 'none' })
+              uni.showToast({ title: '撌脫𦆮撘�', icon: 'none' })
               setTimeout(function() { uni.navigateBack() }, 500)
             }).catch(function() {
               uni.showToast({ title: '�滢�憭梯揖', icon: 'none' })
@@ -829,7 +829,7 @@ export default {
 
 .bottom-spacer { height: 80rpx; }
 
-/* ===== Phase 2: �寥��臭縑摨?===== */
+/* ===== Phase 2: �寥��臭縑摨===== */
 .confidence-card {
   margin: 0 30rpx 20rpx;
   background: #fff;
@@ -883,7 +883,7 @@ export default {
   line-height: 1.4;
 }
 
-/* ===== Phase 2: �䠷�㗇��睃�銵?===== */
+/* ===== Phase 2: �䠷�㗇��睃�銵===== */
 .candidate-section {
   margin-bottom: 16rpx;
 }

+ 10 - 10
cfc-frontend/pages/health/report-list.vue

@@ -2,14 +2,14 @@
   <view class="list-container">
     <!-- 顶部导航 -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�返回</text>
+      <text class="nav-back" @click="goBack">‹ 返回</text>
       <text class="nav-title">�康报告</text>
       <view class="nav-placeholder"></view>
     </view>
 
-    <!-- 加载状�-->
+    <!-- 加载状æ€-->
     <view class="loading-wrap" v-if="loading">
-      <text class="loading-text">加载�..</text>
+      <text class="loading-text">加载中...</text>
     </view>
 
     <!-- 报告列表 -->
@@ -22,18 +22,18 @@
       >
         <view class="report-card-left">
           <view class="report-type-badge" :class="'badge-' + (item.reportType === 'gut_flora' ? 'gut' : item.reportType === 'tongue' ? 'tongue' : 'exam')">
-            <text>{{ item.reportType === 'gut_flora' ? '肠�检� : item.reportType === 'tongue' ? '舌诊' : '体检报告' }}</text>
+            <text>{{ item.reportType === 'gut_flora' ? '肠�检测' : item.reportType === 'tongue' ? '舌诊' : '体检报告' }}</text>
           </view>
           <text class="report-date">{{ formatDate(item.reportDate) }}</text>
         </view>
         <view class="report-card-right">
-          <text class="report-score">{{ item.overallScore || '--' }}<text class="score-unit">�/text></text>
-          <text class="report-arrow">�/text>
+          <text class="report-score">{{ item.overallScore || '--' }}<text class="score-unit">分</text></text>
+          <text class="report-arrow">›</text>
         </view>
       </view>
     </view>
 
-    <!-- 空状�-->
+    <!-- 空状æ€-->
     <view class="empty-wrap" v-else>
       <text class="empty-icon">📋</text>
       <text class="empty-title">暂无�康报告</text>
@@ -111,7 +111,7 @@ export default {
   background: #F5F7FA;
 }
 
-/* ===== 导航�===== */
+/* ===== 导航æ ===== */
 .nav-bar {
   position: sticky;
   top: 0;
@@ -137,7 +137,7 @@ export default {
   width: 80rpx;
 }
 
-/* ===== 加载状�===== */
+/* ===== 加载状æ€===== */
 .loading-wrap {
   display: flex;
   justify-content: center;
@@ -215,7 +215,7 @@ export default {
   color: #CCC;
 }
 
-/* ===== 空状�===== */
+/* ===== 空状æ€===== */
 .empty-wrap {
   display: flex;
   flex-direction: column;

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

@@ -2,12 +2,12 @@
   <view class="survey-container">
     <!-- 瀵艰埅 -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">鈥?杩斿洖</text>
+      <text class="nav-back" @click="goBack">鈥杩斿洖</text>
       <text class="nav-title">鍋ュ悍璋冪爺闂�嵎</text>
       <view class="nav-placeholder"></view>
     </view>
 
-    <!-- 杩涘害鏉?-->
+    <!-- 杩涘害鏉-->
     <view class="progress-bar">
       <view class="progress-fill" :style="{ width: progressPercent + '%' }"></view>
     </view>
@@ -21,7 +21,7 @@
     <!-- 琛ㄥ崟 -->
     <view class="form-section">
 
-      <!-- ===================== 绗�竴閮ㄥ垎锛氱敓娲讳範鎯?===================== -->
+      <!-- ===================== 绗�竴閮ㄥ垎锛氱敓娲讳範鎯===================== -->
       <view class="section-header">
         <text class="section-icon">馃崥</text>
         <text class="section-title">鐢熸椿涔犳儻</text>
@@ -34,11 +34,11 @@
         <view class="q-options">
           <view class="q-option" :class="{ 'q-selected': survey.diet === 'balanced' }" @click="survey.diet = 'balanced'">
             <text class="q-icon">馃�</text>
-            <text class="q-text">鍧囪 楗��锛岃崵绱犳惌閰?/text>
+            <text class="q-text">鍧囪 楗��锛岃崵绱犳惌閰�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.diet === 'meat' }" @click="survey.diet = 'meat'">
             <text class="q-icon">馃ォ</text>
-            <text class="q-text">鍋忚崵椋燂紝鐖卞悆鑲?/text>
+            <text class="q-text">鍋忚崵椋燂紝鐖卞悆鑲�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.diet === 'veggie' }" @click="survey.diet = 'veggie'">
             <text class="q-icon">馃ガ</text>
@@ -54,11 +54,11 @@
       <!-- Q2: 娑堝寲鐘跺喌 -->
       <view class="question-card">
         <text class="q-number">2/12</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>
-            <text class="q-text">姝e父锛屾秷鍖栬壇濂?/text>
+            <text class="q-text">姝e父锛屾秷鍖栬壇濂�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.digestion === 'constipation' }" @click="survey.digestion = 'constipation'">
             <text>馃槪</text>
@@ -93,7 +93,7 @@
             <text class="q-text">缈绘潵瑕嗗幓鐫′笉瀹夌ǔ</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.sleep === 'short' }" @click="survey.sleep = 'short'">
-            <text>鈴?/text>
+            <text>鈴�</text>
             <text class="q-text">鐫$湢鏃堕棿涓嶈冻</text>
           </view>
         </view>
@@ -102,15 +102,15 @@
       <!-- Q4: 杩愬姩涔犳儻 -->
       <view class="question-card">
         <text class="q-number">4/12</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>
-            <text class="q-text">缁忓父杩愬姩锛?娆′互涓?鍛�級</text>
+            <text class="q-text">缁忓父杩愬姩锛�3娆′互涓�/鍛�級</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.exercise === 'moderate' }" @click="survey.exercise = 'moderate'">
             <text>馃毝</text>
-            <text class="q-text">鍋跺皵杩愬姩锛?-2娆?鍛�級</text>
+            <text class="q-text">鍋跺皵杩愬姩锛�1-2娆�/鍛�級</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.exercise === 'rare' }" @click="survey.exercise = 'rare'">
             <text>馃獞</text>
@@ -126,15 +126,15 @@
         <view class="q-options">
           <view class="q-option" :class="{ 'q-selected': survey.water === 'enough' }" @click="survey.water = 'enough'">
             <text>馃挧</text>
-            <text class="q-text">鍏呰冻锛堬紴1500ml锛?/text>
+            <text class="q-text">鍏呰冻锛堬紴1500ml锛�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.water === 'moderate' }" @click="survey.water = 'moderate'">
             <text>馃イ</text>
-            <text class="q-text">涓€鑸�紙500-1500ml锛?/text>
+            <text class="q-text">涓€鑸�紙500-1500ml锛�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.water === 'little' }" @click="survey.water = 'little'">
             <text>馃槬</text>
-            <text class="q-text">鍋忓皯锛堬紲500ml锛?/text>
+            <text class="q-text">鍋忓皯锛堬紲500ml锛�</text>
           </view>
         </view>
       </view>
@@ -145,19 +145,19 @@
         <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">鎶楃敓绱狅紙杩?涓�湀鍐呬娇鐢ㄨ繃锛?/text>
+            <text class="q-text">鎶楃敓绱狅紙杩�3涓�湀鍐呬娇鐢ㄨ繃锛�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasMedication('probiotic') }" @click="toggleMedication('probiotic')">
-            <text class="q-text">鐩婄敓鑿?鐩婄敓鍏?/text>
+            <text class="q-text">鐩婄敓鑿�/鐩婄敓鍏�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasMedication('cold') }" @click="toggleMedication('cold')">
-            <text class="q-text">鎰熷啋鑽?閫€鐑ц嵂</text>
+            <text class="q-text">鎰熷啋鑽�/閫€鐑ц嵂</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasMedication('stomach') }" @click="toggleMedication('stomach')">
-            <text class="q-text">鑲犺儍鑽?/text>
+            <text class="q-text">鑲犺儍鑽�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasMedication('none') }" @click="toggleMedication('none')">
-            <text class="q-text">鏃犵壒娈婄敤鑽?/text>
+            <text class="q-text">鏃犵壒娈婄敤鑽�</text>
           </view>
         </view>
       </view>
@@ -165,22 +165,22 @@
       <!-- ===================== 绗�簩閮ㄥ垎锛氱柧鐥呭彶 ===================== -->
       <view class="section-header">
         <text class="section-icon">馃彞</text>
-        <text class="section-title">鐤剧梾鍙?/text>
+        <text class="section-title">鐤剧梾鍙�</text>
       </view>
 
-      <!-- Q7: 鎱㈡€х梾/绯荤粺鎬х柧鐥?-->
+      <!-- Q7: 鎱㈡€х梾/绯荤粺鎬х柧鐥-->
       <view class="question-card">
         <text class="q-number">7/12</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>
+            <text class="q-text">鏃犲凡鐭ョ柧鐥�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasChronic('asthma') }" @click="toggleChronic('asthma')">
-            <text class="q-text">鍝�枠/杩囨晱鎬ч蓟鐐?/text>
+            <text class="q-text">鍝�枠/杩囨晱鎬ч蓟鐐�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasChronic('eczema') }" @click="toggleChronic('eczema')">
-            <text class="q-text">婀跨柟/鐗瑰簲鎬х毊鐐?/text>
+            <text class="q-text">婀跨柟/鐗瑰簲鎬х毊鐐�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasChronic('anemia') }" @click="toggleChronic('anemia')">
             <text class="q-text">璐��</text>
@@ -192,29 +192,29 @@
             <text class="q-text">鍋忕槮/钀ュ吇涓嶈壇</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasChronic('thyroid') }" @click="toggleChronic('thyroid')">
-            <text class="q-text">鐢茬姸鑵洪棶棰?/text>
+            <text class="q-text">鐢茬姸鑵洪棶棰�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasChronic('digestive') }" @click="toggleChronic('digestive')">
-            <text class="q-text">娑堝寲绯荤粺鐤剧梾锛堣儍鐐?鑲犵値绛夛級</text>
+            <text class="q-text">娑堝寲绯荤粺鐤剧梾锛堣儍鐐�/鑲犵値绛夛級</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': hasChronic('other') }" @click="toggleChronic('other')">
             <text class="q-text">鍏朵粬锛堣�鍦ㄥ�娉ㄨ�鏄庯級</text>
           </view>
         </view>
         <!-- 鍏朵粬鐤剧梾鎻忚堪 -->
-        <textarea v-if="hasChronic('other')" class="extra-input" v-model="survey.diseaseHistory.otherDesc" placeholder="璇锋弿杩板叾浠栫柧鐥呮儏鍐?.." maxlength="200" />
+        <textarea v-if="hasChronic('other')" class="extra-input" v-model="survey.diseaseHistory.otherDesc" placeholder="璇锋弿杩板叾浠栫柧鐥呮儏鍐�..." maxlength="200" />
       </view>
 
-      <!-- Q8: 杩囨晱鍙?-->
+      <!-- Q8: 杩囨晱鍙-->
       <view class="question-card">
         <text class="q-number">8/12</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>
+            <text class="q-text">鏃犳槑鏄捐繃鏁�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.allergies.indexOf('food') !== -1 }" @click="toggleAllergy('food')">
-            <text class="q-text">椋熺墿杩囨晱锛堢墰濂?楦¤泲/娴烽矞绛夛級</text>
+            <text class="q-text">椋熺墿杩囨晱锛堢墰濂�/楦¤泲/娴烽矞绛夛級</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.allergies.indexOf('drug') !== -1 }" @click="toggleAllergy('drug')">
             <text class="q-text">鑽�墿杩囨晱</text>
@@ -223,26 +223,26 @@
             <text class="q-text">鑺辩矇/灏樿灗杩囨晱</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.allergies.indexOf('skin') !== -1 }" @click="toggleAllergy('skin')">
-            <text class="q-text">鐨�偆杩囨晱/鑽ㄩ夯鐤?/text>
+            <text class="q-text">鐨�偆杩囨晱/鑽ㄩ夯鐤�</text>
           </view>
         </view>
         <!-- 杩囨晱璇︽儏 -->
-        <textarea v-if="survey.allergies.length > 0 && survey.allergies.indexOf('none') === -1" class="extra-input" v-model="survey.allergyDetail" placeholder="璇疯ˉ鍏呰繃鏁忚�鎯咃紙杩囨晱鍘熴€佺棁鐘剁瓑锛?.." maxlength="200" />
+        <textarea v-if="survey.allergies.length > 0 && survey.allergies.indexOf('none') === -1" class="extra-input" v-model="survey.allergyDetail" placeholder="璇疯ˉ鍏呰繃鏁忚�鎯咃紙杩囨晱鍘熴€佺棁鐘剁瓑锛�..." maxlength="200" />
       </view>
 
-      <!-- Q9: 鎵嬫湳/浣忛櫌鍙?-->
+      <!-- Q9: 鎵嬫湳/浣忛櫌鍙-->
       <view class="question-card">
         <text class="q-number">9/12</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>
+            <text class="q-text">鏃�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.surgery === 'yes' }" @click="survey.surgery = 'yes'">
-            <text class="q-text">鏈?/text>
+            <text class="q-text">鏈�</text>
           </view>
         </view>
-        <textarea v-if="survey.surgery === 'yes'" class="extra-input" v-model="survey.surgeryDetail" placeholder="璇锋弿杩版墜鏈?浣忛櫌鍘熷洜鍜屾椂闂?.." maxlength="200" />
+        <textarea v-if="survey.surgery === 'yes'" class="extra-input" v-model="survey.surgeryDetail" placeholder="璇锋弿杩版墜鏈�/浣忛櫌鍘熷洜鍜屾椂闂�..." maxlength="200" />
       </view>
 
       <!-- ===================== 绗�笁閮ㄥ垎锛氬�鏃忓彶 ===================== -->
@@ -301,39 +301,39 @@
         </view>
       </view>
 
-      <!-- Q11: 绁栫埗姣嶇梾鍙?-->
+      <!-- Q11: 绁栫埗姣嶇梾鍙-->
       <view class="question-card">
         <text class="q-number">11/12</text>
-        <text class="q-title">绁栫埗姣?澶栫�鐖舵瘝鏄�惁鏈変互涓嬬柧鐥呭彶锛燂紙鍙��閫夛級</text>
+        <text class="q-title">绁栫埗姣�/澶栫�鐖舵瘝鏄�惁鏈変互涓嬬柧鐥呭彶锛燂紙鍙��閫夛級</text>
         <view class="q-options multi">
           <view class="q-option" :class="{ 'q-selected': survey.grandparentHistory.indexOf('unknown') !== -1 }" @click="toggleGrandparent('unknown')">
-            <text class="q-text">涓嶆竻妤?/text>
+            <text class="q-text">涓嶆竻妤�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.grandparentHistory.indexOf('hypertension') !== -1 }" @click="toggleGrandparent('hypertension')">
-            <text class="q-text">楂樿�鍘?/text>
+            <text class="q-text">楂樿�鍘�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.grandparentHistory.indexOf('diabetes') !== -1 }" @click="toggleGrandparent('diabetes')">
-            <text class="q-text">绯栧翱鐥?/text>
+            <text class="q-text">绯栧翱鐥�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.grandparentHistory.indexOf('heart') !== -1 }" @click="toggleGrandparent('heart')">
-            <text class="q-text">蹇冭剰鐥?/text>
+            <text class="q-text">蹇冭剰鐥�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.grandparentHistory.indexOf('stroke') !== -1 }" @click="toggleGrandparent('stroke')">
-            <text class="q-text">鑴戝崚涓?/text>
+            <text class="q-text">鑴戝崚涓�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.grandparentHistory.indexOf('cancer') !== -1 }" @click="toggleGrandparent('cancer')">
             <text class="q-text">鐧岀棁</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.grandparentHistory.indexOf('autoimmune') !== -1 }" @click="toggleGrandparent('autoimmune')">
-            <text class="q-text">鑷�韩鍏嶇柅鐥?/text>
+            <text class="q-text">鑷�韩鍏嶇柅鐥�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.grandparentHistory.indexOf('none') !== -1 }" @click="toggleGrandparent('none')">
-            <text class="q-text">鏃犳槑鏄剧柧鐥?/text>
+            <text class="q-text">鏃犳槑鏄剧柧鐥�</text>
           </view>
         </view>
       </view>
 
-      <!-- ===================== 绗�洓閮ㄥ垎锛氬仴搴风洰鏍?===================== -->
+      <!-- ===================== 绗�洓閮ㄥ垎锛氬仴搴风洰鏍===================== -->
       <view class="section-header">
         <text class="section-icon">馃幆</text>
         <text class="section-title">鍋ュ悍鐩�爣</text>
@@ -345,8 +345,8 @@
         <text class="q-title">鎮ㄥ笇鏈涢€氳繃鏈��鍋ュ悍绠$悊鏀瑰杽浠€涔堬紵锛堝彲澶氶€夛級</text>
         <view class="q-options multi">
           <view class="q-option" :class="{ 'q-selected': survey.goals.indexOf('immunity') !== -1 }" @click="toggleGoal('immunity')">
-            <text>馃洝锔?/text>
-            <text class="q-text">澧炲己鍏嶇柅鍔?/text>
+            <text>馃洝锔�</text>
+            <text class="q-text">澧炲己鍏嶇柅鍔�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.goals.indexOf('digestion') !== -1 }" @click="toggleGoal('digestion')">
             <text>馃尶</text>
@@ -358,7 +358,7 @@
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.goals.indexOf('focus') !== -1 }" @click="toggleGoal('focus')">
             <text>馃幆</text>
-            <text class="q-text">鎻愬崌涓撴敞鍔?/text>
+            <text class="q-text">鎻愬崌涓撴敞鍔�</text>
           </view>
           <view class="q-option" :class="{ 'q-selected': survey.goals.indexOf('sleep') !== -1 }" @click="toggleGoal('sleep')">
             <text>馃槾</text>
@@ -381,8 +381,8 @@
 
       <!-- 鎻愪氦鎸夐挳 -->
       <view class="submit-btn" :class="{ 'btn-disabled': !canSubmit }" @click="doSubmit">
-        <text v-if="submitting">鎻愪氦涓?..</text>
-        <text v-else>鎻愪氦骞惰繘鍏?AI 瑙h�</text>
+        <text v-if="submitting">鎻愪氦涓�...</text>
+        <text v-else>鎻愪氦骞惰繘鍏AI 瑙h�</text>
       </view>
     </view>
 
@@ -407,7 +407,7 @@ export default {
         exercise: '',
         water: '',
         medications: [],
-        // 鐤剧梾鍙?
+        // 鐤剧梾鍙
         diseaseHistory: {
           chronic: [],
           otherDesc: ''
@@ -416,7 +416,7 @@ export default {
         allergyDetail: '',
         surgery: '',
         surgeryDetail: '',
-        // 瀹舵棌鍙?
+        // 瀹舵棌鍙
         familyHistory: {
           father: [],
           mother: [],
@@ -427,14 +427,14 @@ export default {
         goals: []
       },
       familyDiseaseOptions: [
-        { value: 'none', label: '鏃? },
-        { value: 'hypertension', label: '楂樿�鍘? },
-        { value: 'diabetes', label: '绯栧翱鐥? },
-        { value: 'heart', label: '蹇冭剰鐥? },
-        { value: 'stroke', label: '鑴戝崚涓? },
+        { value: 'none', label: '鏃�' },
+        { value: 'hypertension', label: '楂樿�鍘�' },
+        { value: 'diabetes', label: '绯栧翱鐥�' },
+        { value: 'heart', label: '蹇冭剰鐥�' },
+        { value: 'stroke', label: '鑴戝崚涓�' },
         { value: 'cancer', label: '鐧岀棁' },
-        { value: 'allergy', label: '杩囨晱鎬х柧鐥? },
-        { value: 'autoimmune', label: '鑷�韩鍏嶇柅鐥? },
+        { value: 'allergy', label: '杩囨晱鎬х柧鐥�' },
+        { value: 'autoimmune', label: '鑷�韩鍏嶇柅鐥�' },
         { value: 'mental', label: '绮剧�/蹇冪悊鐤剧梾' },
         { value: 'obesity', label: '鑲ヨ儢' },
       ],
@@ -495,10 +495,10 @@ export default {
           self.surveyId = res.data.id
         }
       }).catch(function(e) {
-        console.log('鍒濆�鍖栭棶鍗峰け璐?, e)
+        console.log('鍒濆�鍖栭棶鍗峰け璐�', e)
       })
     },
-    // === 鐢ㄨ嵂澶氶€?===
+    // === 鐢ㄨ嵂澶氶€===
     hasMedication: function(val) {
       return this.survey.medications.indexOf(val) !== -1
     },
@@ -519,7 +519,7 @@ export default {
         }
       }
     },
-    // === 鎱㈡€х梾澶氶€?===
+    // === 鎱㈡€х梾澶氶€===
     hasChronic: function(val) {
       return this.survey.diseaseHistory.chronic.indexOf(val) !== -1
     },
@@ -541,7 +541,7 @@ export default {
         }
       }
     },
-    // === 杩囨晱澶氶€?===
+    // === 杩囨晱澶氶€===
     toggleAllergy: function(val) {
       var idx = this.survey.allergies.indexOf(val)
       if (val === 'none') {
@@ -581,7 +581,7 @@ export default {
         }
       }
     },
-    // === 绁栫埗姣嶇梾鍙?===
+    // === 绁栫埗姣嶇梾鍙===
     toggleGrandparent: function(val) {
       var idx = this.survey.grandparentHistory.indexOf(val)
       if (val === 'unknown') {
@@ -615,7 +615,7 @@ export default {
       if (!this.canSubmit || this.submitting) return
       var self = this
       self.submitting = true
-      uni.showLoading({ title: '鎻愪氦涓?..' })
+      uni.showLoading({ title: '鎻愪氦涓�...' })
 
       var doSubmit = function() {
         submitReportSurvey(self.surveyId, JSON.stringify(self.survey)).then(function(res) {
@@ -623,7 +623,7 @@ export default {
           if (res.code === 200) {
             uni.showToast({ title: '鎻愪氦鎴愬姛', icon: 'success' })
             setTimeout(function() {
-              var params = 'reportId=' + self.reportId + '&surveyId=' + self.surveyId + '&firstMessage=' + encodeURIComponent('璇锋牴鎹�姤鍛婂拰闂�嵎淇℃伅锛屾彁渚涗釜鎬у寲鐨勫仴搴峰缓璁?)
+              var params = 'reportId=' + self.reportId + '&surveyId=' + self.surveyId + '&firstMessage=' + encodeURIComponent('璇锋牴鎹�姤鍛婂拰闂�嵎淇℃伅锛屾彁渚涗釜鎬у寲鐨勫仴搴峰缓璁�')
               uni.redirectTo({ url: '/pages/ai/chat?' + params })
             }, 500)
           } else {
@@ -773,7 +773,7 @@ export default {
 .q-icon { font-size: 32rpx; flex-shrink: 0; }
 .q-text { font-size: 26rpx; color: #333; }
 
-/* 瀹舵棌鍙茬綉鏍?*/
+/* 瀹舵棌鍙茬綉鏍*/
 .family-grid {
   display: flex;
   flex-direction: column;

+ 44 - 44
cfc-frontend/pages/health/report-upload.vue

@@ -2,7 +2,7 @@
   <view class="upload-container">
     <!-- 憿園�撖潸⏛ -->
     <view class="nav-bar">
-      <text class="nav-back" @click="goBack">�?餈𥪜�</text>
+      <text class="nav-back" @click="goBack">�餈𥪜�</text>
       <text class="nav-title">銝𠹺��亙熒�亙�</text>
       <view class="nav-placeholder"></view>
     </view>
@@ -28,14 +28,14 @@
         <text class="parsed-label">�亙��交�</text>
         <text class="parsed-value">{{ parsedInfo.reportDate }}</text>
       </view>
-      <!-- �寥��嗆�?-->
+      <!-- �寥��嗆�-->
       <view class="match-status" v-if="parsedInfo.needManualSelect">
         <text class="match-icon">�𩤃�</text>
         <text class="match-text">�䭾��芸𢆡�寥��啣振摨剜��矋�霂瑟��券�㗇𥋘</text>
       </view>
       <view class="match-status success" v-else-if="parsedInfo.matchedMemberName">
-        <text class="match-icon">�?/text>
-        <text class="match-text">撌脰䌊�典龪�? {{ parsedInfo.matchedMemberName }}</text>
+        <text class="match-icon">��</text>
+        <text class="match-text">撌脰䌊�典龪��: {{ parsedInfo.matchedMemberName }}</text>
       </view>
     </view>
 
@@ -55,7 +55,7 @@
         </view>
       </view>
       <view class="add-member-btn" v-if="parsedInfo && parsedInfo.personName" @click="chooseRelationAndAdd">
-        <text class="add-member-text">+ 撠��庙{ parsedInfo.personName }}�齿溶�牐蛹�唳��?/text>
+        <text class="add-member-text">+ 撠��庙{ parsedInfo.personName }}�齿溶�牐蛹�唳���</text>
       </view>
     </view>
 
@@ -79,7 +79,7 @@
             @click="selectType('gut_flora')"
           >
             <text class="type-icon">�𥈡</text>
-            <text class="type-name">�𣳇�璉�瘚?/text>
+            <text class="type-name">�𣳇�璉�瘚�</text>
           </view>
           <view
             class="type-option"
@@ -96,7 +96,7 @@
       <view class="purchase-section" v-if="recommendedProducts.length > 0">
         <view class="purchase-header">
           <text class="purchase-icon">�𣑐</text>
-          <text class="purchase-title">銝箏振鈭箄揚銋唳�瘚𧢲��?/text>
+          <text class="purchase-title">銝箏振鈭箄揚銋唳�瘚𧢲���</text>
         </view>
         <scroll-view class="purchase-scroll" scroll-x enable-flex show-scrollbar="false">
           <view
@@ -109,13 +109,13 @@
             <text class="purchase-name">{{ item.name }}</text>
             <text class="purchase-price">{{ formatPriceWithSymbol(item.price) }}</text>
             <view class="purchase-btn">
-              <text class="purchase-btn-text">�餉揚銋?/text>
+              <text class="purchase-btn-text">�餉揚銋�</text>
             </view>
           </view>
         </scroll-view>
       </view>
 
-      <!-- �諹��滨�嚗�� tongue 蝐餃��曄內嚗?-->
+      <!-- �諹��滨�嚗�� tongue 蝐餃��曄內嚗-->
       <view class="form-item" v-if="isTongue">
         <text class="form-label">�齿��諹情</text>
         <view class="photo-area">
@@ -126,7 +126,7 @@
           </view>
           <image class="photo-preview" v-else-if="photoPath && !analyzing" :src="photoPath" mode="aspectFit" @click="takePhoto"></image>
           <view class="photo-analyzing" v-else>
-            <text class="analyzing-text">AI �諹情���銝?..</text>
+            <text class="analyzing-text">AI �諹情���銝�...</text>
           </view>
         </view>
         <view class="photo-retake" v-if="photoPath && !analyzing">
@@ -134,9 +134,9 @@
         </view>
       </view>
 
-      <!-- PDF��辣銝𠹺�嚗���諹�蝐餃��曄內嚗?-->
+      <!-- PDF��辣銝𠹺�嚗���諹�蝐餃��曄內嚗-->
       <view class="form-item" v-if="!isTongue">
-        <text class="form-label">銝𠹺�PDF��辣嚗��匧‵嚗?/text>
+        <text class="form-label">銝𠹺�PDF��辣嚗��匧‵嚗�</text>
         <view class="file-upload-area" @click="pickFile">
           <view class="file-upload-placeholder" v-if="!selectedFile">
             <text class="file-upload-icon">��</text>
@@ -144,11 +144,11 @@
             <text class="file-upload-hint">�舀�隞舘�憭抵扇敶蓥葉�㗇𥋘</text>
           </view>
           <view class="file-uploading" v-else>
-            <text class="file-upload-icon">�?/text>
+            <text class="file-upload-icon">��</text>
             <text class="file-upload-text">甇�銁閫��...</text>
           </view>
         </view>
-        <!-- 撌脤�㗇𥋘���隞?-->
+        <!-- 撌脤�㗇𥋘���隞-->
         <view class="file-info" v-if="selectedFile && !parsingPreview">
           <text class="file-name">{{ selectedFile.name }}</text>
           <text class="file-size">{{ formatFileSize(selectedFile.size) }}</text>
@@ -161,13 +161,13 @@
         <text class="form-label">�亙��交�</text>
         <view class="date-display" @click="showDatePicker = true">
           <text>{{ form.reportDate || '霂琿�㗇𥋘�交�' }}</text>
-          <text class="date-arrow">�?/text>
+          <text class="date-arrow">��</text>
         </view>
       </view>
 
       <!-- 蝏澆�霂�� -->
       <view class="form-item">
-        <text class="form-label">蝏澆�霂��嚗��匧‵嚗?/text>
+        <text class="form-label">蝏澆�霂��嚗��匧‵嚗�</text>
         <view class="score-input-wrap">
           <slider
             class="score-slider"
@@ -182,13 +182,13 @@
             block-size="16"
             show-value
           />
-          <text class="score-value">{{ form.overallScore || 0 }}�?/text>
+          <text class="score-value">{{ form.overallScore || 0 }}��</text>
         </view>
       </view>
 
       <!-- 憭�釣 -->
       <view class="form-item">
-        <text class="form-label">憭�釣嚗��匧‵嚗?/text>
+        <text class="form-label">憭�釣嚗��匧‵嚗�</text>
         <textarea
           class="note-input"
           v-model="form.description"
@@ -199,9 +199,9 @@
 
       <!-- �𣂷漱�厰僼 -->
       <view class="submit-btn" :class="{ 'btn-disabled': !canSubmit }" @click="doSubmit">
-        <text v-if="analyzing">���銝?..</text>
-        <text v-else-if="isTongue">撘�憪见��?/text>
-        <text v-else-if="submitting">�𣂷漱銝?..</text>
+        <text v-if="analyzing">���銝�...</text>
+        <text v-else-if="isTongue">撘�憪见���</text>
+        <text v-else-if="submitting">�𣂷漱銝�...</text>
         <text v-else>�𣂷漱�亙�</text>
       </view>
     </view>
@@ -215,7 +215,7 @@
 import { createHealthReport, parseReportPreview, productList, getFamilyMembers, addFamilyMember } from '../../utils/api.js'
 import config from '@/config.js'
 
-// �亙�蝐餃� �?蝏游漲�惩�嚗�鍂鈭擧綫�𣂼����
+// �亙�蝐餃� �蝏游漲�惩�嚗�鍂鈭擧綫�𣂼����
 var REPORT_DOMAIN_MAP = {
   physical_exam: 'body',
   gut_flora: 'body',
@@ -268,11 +268,11 @@ export default {
       this.form.reportType = options.reportType
     }
     this.loadRecommendProducts(this.form.reportType)
-    // 銝漤�霈文‵��𠯫�?�?敺�圾�𣂼�隞擧𥁒�𠹺葉�𣂼�
+    // 銝漤�霈文‵��𠯫�� �� 敺�圾�𣂼�隞擧𥁒�𠹺葉�𣂼�
     this.form.reportDate = ''
   },
   onShow: function() {
-    // 瘥𤩺活�曄內�嗡�store�瑕�familyId��振摨剜��?
+    // 瘥𤩺活�曄內�嗡�store�瑕�familyId��振摨剜��
     this.loadFamilyInfo()
   },
   methods: {
@@ -280,7 +280,7 @@ export default {
       if (this.form.reportType === type) return
       this.form.reportType = type
       this.loadRecommendProducts(type)
-      // ��掩�𧢲𧒄皜���嗡�蝐餃���𠶖�?
+      // ��掩�𧢲𧒄皜���嗡�蝐餃���𠶖�
       if (type === 'tongue') {
         this.selectedFile = null
         this.parsedInfo = null
@@ -292,7 +292,7 @@ export default {
     },
     loadFamilyInfo() {
       var self = this
-      // 隞竚uex�瑕�familyId��振摨剜��?
+      // 隞竚uex�瑕�familyId��振摨剜��
       var userInfo = uni.getStorageSync('userInfo')
       if (userInfo) {
         try {
@@ -374,7 +374,7 @@ export default {
     },
     pickFile() {
       var self = this
-      // �滨蔭閫���嗆�?
+      // �滨蔭閫���嗆�
       this.parsedInfo = null
       this.showMemberSelector = false
       this.selectedMemberId = null
@@ -395,7 +395,7 @@ export default {
           }
         },
         fail: function(e) {
-          console.log('�㗇𥋘��辣�𡝗��硋仃韐?, e)
+          console.log('�㗇𥋘��辣�𡝗��硋仃韐�', e)
         }
       })
     },
@@ -420,7 +420,7 @@ export default {
           matchLabel: detail.matchLabel,
           candidates: detail.candidates || []
         }
-        // 隞舘圾�鞟��𡏭䌊�典‵��𥁒�𦠜𠯫�?
+        // 隞舘圾�鞟��𡏭䌊�典‵��𥁒�𦠜𠯫�
         if (detail.extractedReportDate) {
           self.form.reportDate = detail.extractedReportDate
         }
@@ -432,7 +432,7 @@ export default {
             self.promptAddParsedMember()
           }
         }
-        // 隞舘圾�鞟��𡏭䌊�典‵��𥁒�𦠜𠯫�?
+        // 隞舘圾�鞟��𡏭䌊�典‵��𥁒�𦠜𠯫�
         if (detail.extractedReportDate) {
           self.form.reportDate = detail.extractedReportDate
         }
@@ -463,17 +463,17 @@ export default {
     selectMember(member) {
       this.selectedMemberId = member.id || member.userId
       this.parsedInfo = this.parsedInfo || {}
-      // �见𢆡�㗇𥋘����㗛�朞� matchedMemberId 隡𣳇�垍�蝖株恕憿?
+      // �见𢆡�㗇𥋘����㗛�朞� matchedMemberId 隡𣳇�垍�蝖株恕憿
       this.parsedInfo.matchedMemberId = this.selectedMemberId
       this.parsedInfo.needManualSelect = false
       this.showMemberSelector = false
     },
     genderText(gender) {
-      if (gender === 'male') return '�?
-      if (gender === 'female') return '憟?
+      if (gender === 'male') return '��'
+      if (gender === 'female') return '憟�'
       return ''
     },
-    // 霂a䔮�臬炏撠�圾�𣂼���犖瘛餃�銝箏振摨剜��?
+    // 霂a䔮�臬炏撠�圾�𣂼���犖瘛餃�銝箏振摨剜��
     promptAddParsedMember() {
       var self = this
       if (!this.parsedInfo || !this.parsedInfo.personName) return
@@ -482,11 +482,11 @@ export default {
       var extra = []
       var g = this.genderText(this.parsedInfo.extractedGender)
       if (g) extra.push(g)
-      if (this.parsedInfo.extractedAge) extra.push(this.parsedInfo.extractedAge + '撗?)
-      if (extra.length > 0) desc = name + '嚗? + extra.join('嚗?) + '嚗?
+      if (this.parsedInfo.extractedAge) extra.push(this.parsedInfo.extractedAge + '撗�')
+      if (extra.length > 0) desc = name + '嚗�' + extra.join('嚗�') + '嚗�'
       uni.showModal({
         title: '�芸龪�滚�摰嗅滬�𣂼�',
-        content: '�臬炏撠�圾�𣂼����? + desc + '�齿溶�牐蛹摰嗅滬�𣂼�嚗?,
+        content: '�臬炏撠�圾�𣂼�����' + desc + '�齿溶�牐蛹摰嗅滬�𣂼�嚗�',
         confirmText: '瘛餃�',
         cancelText: '�见𢆡�㗇𥋘',
         success: function(res) {
@@ -505,7 +505,7 @@ export default {
         { label: '�滚�', generationLevel: 'peer', peerType: 'spouse' },
         { label: '�嗆�', generationLevel: 'parent' },
         { label: '���憪𣂼此', generationLevel: 'peer', peerType: 'sibling' },
-        { label: '蟡𣇉�瘥?, generationLevel: 'grandparent' }
+        { label: '蟡𣇉�瘥�', generationLevel: 'grandparent' }
       ]
       uni.showActionSheet({
         itemList: relOptions.map(function(o) { return o.label }),
@@ -527,7 +527,7 @@ export default {
         generationLevel: rel.generationLevel
       }
       if (rel.peerType) dto.peerType = rel.peerType
-      // �勗僑樴�綫蝞堒之�游枂�笔僑隞踝��其�撅閧內嚗𣬚鍂�瑕�蝏剖虾靽格㺿嚗?
+      // �勗僑樴�綫蝞堒之�游枂�笔僑隞踝��其�撅閧內嚗𣬚鍂�瑕�蝏剖虾靽格㺿嚗
       var age = parseInt(this.parsedInfo.extractedAge)
       if (!isNaN(age) && age > 0 && age < 130) {
         dto.birthday = (new Date().getFullYear() - age) + '-01-01'
@@ -648,7 +648,7 @@ export default {
       }
 
       self.submitting = true
-      uni.showLoading({ title: '�𣂷漱銝?..' })
+      uni.showLoading({ title: '�𣂷漱銝�...' })
       createHealthReport({
         reportType: self.form.reportType,
         reportDate: self.form.reportDate,
@@ -697,7 +697,7 @@ uni.showToast({ title: '�𣂷漱�𣂼�', icon: 'success' })
   background: #F5F7FA;
 }
 
-/* ===== 撖潸⏛�?===== */
+/* ===== 撖潸⏛�===== */
 .nav-bar {
   position: sticky;
   top: 0;
@@ -723,7 +723,7 @@ uni.showToast({ title: '�𣂷漱�𣂼�', icon: 'success' })
   width: 80rpx;
 }
 
-/* ===== �鞟內�?===== */
+/* ===== �鞟內�===== */
 .tip-banner {
   display: flex;
   flex-direction: row;
@@ -973,7 +973,7 @@ uni.showToast({ title: '�𣂷漱�𣂼�', icon: 'success' })
   color: #2E7D32;
 }
 
-/* ===== 摰嗅滬�𣂼��㗇𥋘�?===== */
+/* ===== 摰嗅滬�𣂼��㗇𥋘�===== */
 .member-selector {
   margin: 0 30rpx 20rpx;
 }
@@ -1027,7 +1027,7 @@ uni.showToast({ title: '�𣂷漱�𣂼�', icon: 'success' })
   color: #4caf50;
 }
 
-/* ===== �諹��滨��?===== */
+/* ===== �諹��滨��===== */
 .photo-area {
   display: flex;
   justify-content: center;

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

@@ -2,7 +2,7 @@
   <view class="page">
     <view class="nav-bar">
       <view class="nav-back" @tap="goBack">
-        <text class="back-text">�?餈𥪜�</text>
+        <text class="back-text">�餈𥪜�</text>
       </view>
       <text class="nav-title">雿𨀣�</text>
     </view>
@@ -15,15 +15,15 @@
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">3-5 撗��摮阡��㵪�</text>
-              <text class="info-desc">瘥誩予�刻� 10-13 撠𤩺𧒄�∠�嚗�鉄��辺嚗㚁��餅��箏�雿𨀣�嚗䔶�餈𥕦之�穃�頨思��𤏸��?/text>
+              <text class="info-desc">瘥誩予�刻� 10-13 撠𤩺𧒄�∠�嚗�鉄��辺嚗㚁��餅��箏�雿𨀣�嚗䔶�餈𥕦之�穃�頨思��𤏸���</text>
             </view>
             <view class="info-item">
               <text class="info-age">6-12 撗��摮阡����</text>
-              <text class="info-desc">瘥誩予�刻� 9-11 撠𤩺𧒄�∠�嚗䔶�霂��頞喃��荔��𣂼�摮虫�瘜冽��𥕦�霈啣��䜘�?/text>
+              <text class="info-desc">瘥誩予�刻� 9-11 撠𤩺𧒄�∠�嚗䔶�霂��頞喃��荔��𣂼�摮虫�瘜冽��𥕦�霈啣��䜘��</text>
             </view>
             <view class="info-item">
               <text class="info-age">13-18 撗���鍦�撟湛�</text>
-              <text class="info-desc">瘥誩予�刻� 8-10 撠𤩺𧒄�∠�嚗�葬�抵澈雿𤘪�憭滚�瞈�蝝㰘����蝏湔��臬末蝎曄��嗆���?/text>
+              <text class="info-desc">瘥誩予�刻� 8-10 撠𤩺𧒄�∠�嚗�葬�抵澈雿𤘪�憭滚�瞈�蝝㰘����蝏湔��臬末蝎曄��嗆����</text>
             </view>
           </view>
         </view>
@@ -36,19 +36,19 @@
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">�箏�雿𨀣��園𡢿</text>
-              <text class="info-desc">瘥誩予�䔶��園𡢿銝𠰴��諹絲摨𠺪���𡠺�冽錰嚗�葬�抵澈雿枏遣蝡讠迅摰𡁶��毺��麄�?/text>
+              <text class="info-desc">瘥誩予�䔶��園𡢿銝𠰴��諹絲摨𠺪���𡠺�冽錰嚗�葬�抵澈雿枏遣蝡讠迅摰𡁶��毺��麄��</text>
             </view>
             <view class="info-item">
               <text class="info-age">�∪��暹𠹭隞芸�</text>
-              <text class="info-desc">�∪�銝匧����餈𥡝�摰厰�瘣餃𢆡嚗����粉��𨯬頧駁𨺗銋僐��楛�澆𢙺嚗諹悟頨怠��鞉��暹𠹭�?/text>
+              <text class="info-desc">�∪�銝匧����餈𥡝�摰厰�瘣餃𢆡嚗����粉��𨯬頧駁𨺗銋僐��楛�澆𢙺嚗諹悟頨怠��鞉��暹𠹭��</text>
             </view>
             <view class="info-item">
               <text class="info-age">�誩�撅誩��園𡢿</text>
-              <text class="info-desc">�∪� 1 撠𤩺𧒄�𨀣迫雿輻鍂�萄�霈曉�嚗諹��劐��穃�銴芷�蝝惩�瘜䕘�敶勗��亦辺�?/text>
+              <text class="info-desc">�∪� 1 撠𤩺𧒄�𨀣迫雿輻鍂�萄�霈曉�嚗諹��劐��穃�銴芷�蝝惩�瘜䕘�敶勗��亦辺��</text>
             </view>
             <view class="info-item">
-              <text class="info-age">�㘾��辺�删㴓憓?/text>
-              <text class="info-desc">靽脲��批恕摰厰�����𨰜����踝��㗇𥋘�㘾���摨𠰴𠿭�峕�憭湛��仿�㰘�憟賜��∠�瘞𥕦凒�?/text>
+              <text class="info-age">�㘾��辺�删㴓憓�</text>
+              <text class="info-desc">靽脲��批恕摰厰�����𨰜����踝��㗇𥋘�㘾���摨𠰴𠿭�峕�憭湛��仿�㰘�憟賜��∠�瘞𥕦凒��</text>
             </view>
           </view>
         </view>
@@ -61,15 +61,15 @@
           <view class="info-list">
             <view class="info-item">
               <text class="info-age">���雿𨀣�獢�沲</text>
-              <text class="info-desc">隞?21:00-7:00 銝箏���辺�䭾𧒄畾蛛��寞旿撟湧�靚�㟲嚗䔶�霂��摮行𠯫銝舘���𠯫雿𨀣�銝��氬�?/text>
+              <text class="info-desc">隞21:00-7:00 銝箏���辺�䭾𧒄畾蛛��寞旿撟湧�靚�㟲嚗䔶�霂��摮行𠯫銝舘���𠯫雿𨀣�銝��氬��</text>
             </view>
             <view class="info-item">
               <text class="info-age">��辺閬���漲</text>
-              <text class="info-desc">摮阡��滚�蝡亙虾��辺 1-2 撠𤩺𧒄嚗�郎樴��憒����閬�綉�嗅銁 30 �������踹�敶勗�憭𣈯𡢿�∠��?/text>
+              <text class="info-desc">摮阡��滚�蝡亙虾��辺 1-2 撠𤩺𧒄嚗�郎樴��憒����閬�綉�嗅銁 30 �������踹�敶勗�憭𣈯𡢿�∠���</text>
             </view>
             <view class="info-item">
-              <text class="info-age">餈�腹�蠘��?/text>
-              <text class="info-desc">����亙��𡡞�鞉�靚�㟲雿𨀣�嚗峕�甈∟��?15-30 ���嚗諹悟摮拙�撟喟迅餈�腹嚗屸��滨辺�删�銋晞�?/text>
+              <text class="info-age">餈�腹�蠘���</text>
+              <text class="info-desc">����亙��𡡞�鞉�靚�㟲雿𨀣�嚗峕�甈∟��� 15-30 ���嚗諹悟摮拙�撟喟迅餈�腹嚗屸��滨辺�删�銋晞��</text>
             </view>
           </view>
         </view>

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

@@ -3,7 +3,7 @@
 </template>
 
 <script>
-// 废弃 �舌诊功能已�移到 report-upload?reportType=tongue
+// 废弃 â€èˆŒè¯ŠåŠŸèƒ½å·²è¿�移到 report-upload?reportType=tongue
 export default {
   onLoad: function() {
     uni.redirectTo({ url: '/pages/health/report-upload?reportType=tongue' })

+ 88 - 88
cfc-frontend/pages/home/child-index.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="container">
-    <!-- 加载状�-->
+    <!-- 加载状æ€-->
     <BaseLoading :loading="loading" text="正在加载..." />
 
     <!-- 撒花庆� -->
@@ -12,25 +12,25 @@
       :show="showOnboarding"
       @close="showOnboarding = false" />
 
-    <!-- 空状�- 无孩�-->
+    <!-- 空状� - 无孩� -->
     <BaseEmpty
       v-if="!loading && !hasChildren"
       icon="🌈"
-      title="欢迎�到知心益家�
-      description="让爸爸妈妈帮你添加,开始快��长之�
+      title="欢迎�到知心益家�"
+      description="让爸爸妈妈帮你添加,开始快��长之旅"
     >
       <template #action>
         <PlayfulButton variant="clay" size="lg" @click="goToAddChild">
-          �添加�
+          ➕ 添加我
         </PlayfulButton>
       </template>
     </BaseEmpty>
 
-<!-- ====== 主内容(有孩�时�====== -->
+<!-- ====== 主内容(有孩å­�æ—¶ï¼====== -->
 <view class="main-content" v-if="!loading && hasChildren">
 <!-- ===== A) 顶部 Banner ===== -->
 <PageBanner theme="home"
-  tagline="家庭�康�长俱��
+  tagline="家庭�康�长俱�部"
   quote="给全家的一站�幸��案" />
 
 <!-- 五维能�沙盘 -->
@@ -63,12 +63,12 @@ hover-class="streak-pressed"
 <text class="streak-fire">🔥</text>
 <view class="streak-info">
 <text class="streak-days">{{ streakDays }}</text>
-<text class="streak-unit">天��/text>
+<text class="streak-unit">天��</text>
 </view>
 </view>
 
 <!-- ============================================================
-B) 积分�片 �Claymorphism 暖橙�土风格
+B) 积分å�¡ç‰‡ â€Claymorphism æš–æ©™é»�土风格
 ============================================================ -->
       <view
         class="points-card animate-bounce-in"
@@ -92,10 +92,10 @@ B) 积分�片 
 
         <view class="points-progress">
           <text class="progress-hint" v-if="pointsToNext > 0">
-            还差 <text class="progress-hint-num">{{ pointsToNext }}</text> 颗星星��{{ nextLevelName }}
+            还差 <text class="progress-hint-num">{{ pointsToNext }}</text> 颗星星�到 {{ nextLevelName }}
           </text>
           <text class="progress-hint" v-else>
-            🎉 已�是最高等级啦�
+            🎉 å·²ç»�是最高等级啦ï¼
           </text>
           <view class="progress-track">
             <view
@@ -107,12 +107,12 @@ B) 积分�片 
       </view>
 
       <!-- ============================================================
-      C) 今日任务 ��水平滑动的�土�片
+      C) 今日任务 â€å�¯æ°´å¹³æ»‘动的é»�土å�¡ç‰‡
       ============================================================ -->
       <view class="tasks-section animate-slide-up animate-stagger-3">
         <view class="section-header">
           <text class="section-title">📋 今日任务</text>
-          <text class="section-link" @click="goToTasks">查看全部 �/text>
+          <text class="section-link" @click="goToTasks">查看全部 →</text>
         </view>
 
         <scroll-view
@@ -134,7 +134,7 @@ B) 积分�片 
               <text class="task-card-icon">{{ getTaskIcon(task) }}</text>
             </view>
             <text class="task-card-name">{{ task.title }}</text>
-            <text class="task-card-points" v-if="task.points">+{{ task.points }}â­?/text>
+            <text class="task-card-points" v-if="task.points">+{{ task.points }}â­�</text>
             <view class="task-card-badge">
               <BaseBadge :variant="getBadgeVariant(task)" size="xs">
                 {{ getStatusText(task) }}
@@ -143,16 +143,16 @@ B) 积分�片 
           </view>
         </scroll-view>
 
-        <!-- 今日任务空状�-->
+        <!-- 今日任务空状æ€-->
         <view class="tasks-empty" v-else @click="goToTasks">
           <view class="tasks-empty-icon">🎯</view>
-          <text class="tasks-empty-title">今天没有任务�/text>
-          <text class="tasks-empty-desc">让爸爸妈妈给你布置任务��/text>
+          <text class="tasks-empty-title">今天没有任务哦</text>
+          <text class="tasks-empty-desc">让爸爸妈妈给你布置任务�~</text>
         </view>
       </view>
 
       <!-- ============================================================
-      D) 快��作 �2×2 �土按钮网格
+      D) å¿«æ�·æ“�作 â€2×2 é»�土按钮网格
       ============================================================ -->
       <view class="quick-section animate-slide-up animate-stagger-4">
         <view class="section-header">
@@ -176,7 +176,7 @@ B) 积分�片 
             hover-class="quick-btn-pressed"
           >
             <view class="quick-btn-icon quick-icon--rewards">
-              <text class="quick-emoji">â­?/text>
+              <text class="quick-emoji">â­�</text>
             </view>
             <text class="quick-btn-label">心愿商城</text>
           </view>
@@ -200,20 +200,20 @@ B) 积分�片 
             <view class="quick-btn-icon quick-icon--games">
               <text class="quick-emoji">🎮</text>
             </view>
-            <text class="quick-btn-label">�游�/text>
+            <text class="quick-btn-label">�游�</text>
           </view>
         </view>
       </view>
 
       <!-- ============================================================
-      E) 最近���水平滚动徽章
+      E) 最近�就 — 水平滚动徽章
       ============================================================ -->
       <view
         class="achievement-section animate-slide-up animate-stagger-5"
         v-if="earnedBadges.length > 0"
       >
         <view class="section-header">
-          <text class="section-title">� 最近��/text>
+          <text class="section-title">� 最近�就</text>
         </view>
         <scroll-view
           class="achievement-scroll"
@@ -248,17 +248,17 @@ B) 积分�片 
       </view>
 
       <!-- ============================================================
-      F) 最近能���
+      F) 最近能��动
       ============================================================ -->
       <view class="energy-log-section animate-slide-up animate-stagger-6" v-if="energyLogs.length > 0">
         <view class="section-header">
-          <text class="section-title">💧 最近能���/text>
-          <text class="section-link" @click="goToEnergyDetail">查看详情 �/text>
+          <text class="section-title">💧 最近能��动</text>
+          <text class="section-link" @click="goToEnergyDetail">查看详情 →</text>
         </view>
         <view class="energy-log-list">
           <view class="energy-log-item" v-for="log in energyLogs" :key="log.id">
             <view class="log-icon-wrap" :class="'log-icon--' + ((log.amount || 0) >= 0 ? 'up' : 'down')">
-              <text class="log-icon">{{ (log.amount || 0) >= 0 ? '� : '� }}</text>
+              <text class="log-icon">{{ (log.amount || 0) >= 0 ? '⬆' : '⬇' }}</text>
             </view>
             <view class="log-info">
               <text class="log-title">{{ log.reason || log.description }}</text>
@@ -271,7 +271,7 @@ B) 积分�片 
         </view>
       </view>
 
-      <!-- ===== 推�商�+活动(混�信���===== -->
+      <!-- ===== 推è��商å“�+活动(混å�ˆä¿¡æ�¯æµ�ï¼===== -->
       <RecommendedFeed
         v-if="hasChildren"
         :products="dimensionProducts"
@@ -300,27 +300,27 @@ import OnboardingGuide from '../../components/OnboardingGuide.vue'
 import ConfettiCelebration from '../../components/ConfettiCelebration.vue'
 
 /**
- * 等级�置�
- * 星星��(0) �月亮�朋�200) �太阳�天�500) �宇宙�英�1000)
+ * 等级�置表
+ * 星星��(0) → 月亮�朋�(200) → 太阳�天使(500) → 宇宙�英雄(1000)
  */
 var LEVELS = [
-  { min: 0,    max: 200,  name: '星星��',   nextName: '月亮�朋�, emoji: '� },
-  { min: 200,  max: 500,  name: '月亮�朋�, nextName: '太阳�天�, emoji: '🌙' },
-  { min: 500,  max: 1000, name: '太阳�天�, nextName: '宇宙�英�, emoji: '☀� },
-  { min: 1000, max: Infinity, name: '宇宙�英�, nextName: '👑 MAX', emoji: '🦸' }
+  { min: 0,    max: 200,  name: '星星��',   nextName: '月亮�朋�', emoji: '�' },
+  { min: 200,  max: 500,  name: '月亮�朋�', nextName: '太阳�天使', emoji: '🌙' },
+  { min: 500,  max: 1000, name: '太阳�天使', nextName: '宇宙�英雄', emoji: '☀�' },
+  { min: 1000, max: Infinity, name: '宇宙�英雄', nextName: '👑 MAX', emoji: '🦸' }
 ]
 
 /**
- * 任务分类 �图标映射
+ * 任务分类 â†å›¾æ ‡æ˜ å°„
  */
 var TASK_ICONS = {
-  '学习�: '📚',
-  '阅读�: '📖',
-  '生活�: '�',
-  '�动�: '�,
-  '家务�: '🧹',
-  '艺术�: '🎨',
-  'å…¶ä»–': 'â­?
+  '学习类': '📚',
+  '阅读类': '📖',
+  '生活类': '�',
+  '�动类': '⚽',
+  '家务类': '🧹',
+  '艺术类': '🎨',
+  'å…¶ä»–': 'â­�'
 }
 
 export default {
@@ -350,11 +350,11 @@ export default {
       totalTaskCount: 0,
       todayTasks: [],
       badges: [
-        { id: 1, icon: '🌟', name: '早起�, unlocked: false },
-        { id: 2, icon: '📚', name: '阅读�达�, unlocked: false },
+        { id: 1, icon: '🌟', name: '早起鸟', unlocked: false },
+        { id: 2, icon: '📚', name: '阅读�达人', unlocked: false },
         { id: 3, icon: '�', name: '�动�将', unlocked: false },
         { id: 4, icon: '🎨', name: '�艺术家', unlocked: false },
-        { id: 5, icon: '🧹', name: '家务�能�, unlocked: false }
+        { id: 5, icon: '🧹', name: '家务�能手', unlocked: false }
       ],
       _mounted: false,
       energyDimensions: [],
@@ -438,11 +438,11 @@ export default {
       const hour = new Date().getHours()
       if (hour < 6) return '🌛 夜深了,还没�呀'
       if (hour < 9) return '🌅 早安�新的一天开始啦'
-      if (hour < 12) return '☀�上�好�今天也�加油�
-      if (hour < 14) return '🌤�中�好��饱了�有力�
-      if (hour < 18) return '🌻 下�好�继续��好状�
+      if (hour < 12) return '☀� 上�好�今天也�加油哦'
+      if (hour < 14) return '🌤� 中�好��饱了�有力气'
+      if (hour < 18) return '🌻 下�好�继续��好状�'
       if (hour < 21) return '🌆 晚上好�今天过得开心�'
-      return '🌛 该休�啦,明天继续加�
+      return '🌛 该休�啦,明天继续加油'
     },
 
     // ---------- �就徽章 ----------
@@ -478,7 +478,7 @@ export default {
           uni.switchTab({ url: '/pages/home/index' })
           return
         }
-        this.nickname = (userInfo && userInfo.nickname) ? userInfo.nickname : '�朋�
+        this.nickname = (userInfo && userInfo.nickname) ? userInfo.nickname : '�朋�'
 
         const childrenRes = await getChildren()
         const children = childrenRes.data || []
@@ -507,28 +507,28 @@ export default {
           this.unlockBadge(2)
         }
 
-        // 按类别统计已完�任务次数,解�对应徽�
-        var categoryCompletedCount = { '�动�: 0, '艺术�: 0, '家务�: 0 }
+        // 按类别统计已完�任务次数,解�对应徽章
+        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 (cat === '�动类') {
+              categoryCompletedCount['�动类']++
+            } else if (cat === '艺术类') {
+              categoryCompletedCount['艺术类']++
+            } else if (cat === '家务类') {
+              categoryCompletedCount['家务类']++
             }
           }
         }
-        if (categoryCompletedCount['�动�] >= 5) {
+        if (categoryCompletedCount['�动类'] >= 5) {
           this.unlockBadge(3)
         }
-        if (categoryCompletedCount['艺术�] >= 5) {
+        if (categoryCompletedCount['艺术类'] >= 5) {
           this.unlockBadge(4)
         }
-        if (categoryCompletedCount['家务�] >= 5) {
+        if (categoryCompletedCount['家务类'] >= 5) {
           this.unlockBadge(5)
         }
 
@@ -547,7 +547,7 @@ export default {
           }
         }
 
-        // 加载最近能���
+        // 加载最近能��动
         if (energyChildId) {
           try {
             var logsRes = await getEnergyLogs(energyChildId, '', 1, 5)
@@ -636,7 +636,7 @@ export default {
     },
     showStreakDetail() {
       this.$emit('navigate', { page: 'streak-detail' })
-      uni.showToast({ title: '连续打� ' + this.streakDays + ' 天啦�太棒了�, icon: 'none' })
+      uni.showToast({ title: '连续打� ' + this.streakDays + ' 天啦�太棒了�', icon: 'none' })
     },
     goToEnergyDetail() {
       if (this.childId) {
@@ -661,7 +661,7 @@ export default {
       uni.showToast({ title: '�将上线', icon: 'none' })
     },
     goToEnergyDetail(code) {
-      // 跳转到能�详情页(T10 创建�
+      // 跳转到能é‡�详情页(T10 创建ï¼
       var childId = this.childId
       if (!childId || !code) return
       uni.navigateTo({
@@ -669,7 +669,7 @@ export default {
       })
     },
 
-    // ======================== 推�信��========================
+    // ======================== 推è��ä¿¡æ�¯æµ========================
     onFeedItemClick: function(item) {
       if (item.type === 'product') {
         uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + item.id })
@@ -686,15 +686,15 @@ export default {
       if (!task || !task.id) return
       this.$emit('navigate', { page: 'task-detail', taskId: task.id })
 
-      // 如果任务尚未完�,弹出确认完�
+      // 如果任务尚未完æˆ�,弹出确认完æˆ
       if (task.status !== 'completed' && task.status !== 'overdue') {
         uni.showModal({
           title: '完�任务',
-          content: '确定完�� + task.title + '���,
+          content: '确定完�「' + task.title + '��?',
           success: function(res) {
             if (res.confirm) {
               task.status = 'completed'
-              // �新计算完��
+              // �新计算完�数
               this.completedCount = this.todayTasks.filter(function(t) { return t.status === 'completed' }).length
               if (task.points) {
                 uni.showToast({ title: '🎉 获得 ' + task.points + ' 颗星星�', icon: 'success' })
@@ -715,12 +715,12 @@ export default {
       if (!task) return 'default'
       var cat = task.category || 'å…¶ä»–'
       var map = {
-        '学习�: 'study',
-        '阅读�: 'reading',
-        '生活�: 'life',
-        '�动�: 'sports',
-        '家务�: 'chores',
-        '艺术�: 'art'
+        '学习类': 'study',
+        '阅读类': 'reading',
+        '生活类': 'life',
+        '�动类': 'sports',
+        '家务类': 'chores',
+        '艺术类': 'art'
       }
       return map[cat] || 'default'
     },
@@ -730,9 +730,9 @@ export default {
     },
     getStatusText(task) {
       var status = this.getTaskStatus(task)
-      if (status === 'completed') return '�已完�
-      if (status === 'overdue') return '�已超�
-      return '�待完�
+      if (status === 'completed') return '✅ 已完�'
+      if (status === 'overdue') return '� 已超时'
+      return '� 待完�'
     },
     getBadgeVariant(task) {
       var status = this.getTaskStatus(task)
@@ -749,7 +749,7 @@ export default {
 
 <style scoped>
 /* ============================================================
-   知心益家 �孩�端首�Flat Rounded 设计系统
+   知心益家 — 孩�端首页 Flat Rounded 设计系统
    色彩体系:�牌�(#5B9BD5)+浅�(#8FC5E8) | ��阴影 | 4rpx边框
    �考:uni.scss --color-primary, --bg, --shadow-clay, --radius-md
    ============================================================ */
@@ -771,7 +771,7 @@ export default {
   height: 48rpx;
 }
 
-/* 连续打�徽章 �独立�*/
+/* 连续打�徽章 — 独立行 */
 .streak-badge-wrap {
 display: flex;
 align-items: center;
@@ -825,7 +825,7 @@ padding-top: 4rpx;
 }
 
 /* ----------------------------------------------------------
-   积分�片 �Flat Rounded �色��
+   积分å�¡ç‰‡ â€Flat Rounded è“�色æ¸�å�˜
    ---------------------------------------------------------- */
 .points-card {
   position: relative;
@@ -847,7 +847,7 @@ padding-top: 4rpx;
               4rpx 4rpx 16rpx rgba(91,155,213,0.18);
 }
 
-/* 装饰�*/
+/* 装饰åœ*/
 .points-deco {
   position: absolute;
   border-radius: 50%;
@@ -921,7 +921,7 @@ padding-top: 4rpx;
   margin-top: 4rpx;
 }
 
-/* 进度�*/
+/* 进度� */
 .points-progress {
   position: relative;
   z-index: 1;
@@ -956,7 +956,7 @@ padding-top: 4rpx;
 }
 
 /* ----------------------------------------------------------
-   任务区域 �水平滚动�土�片
+   任务区域 â€æ°´å¹³æ»šåЍé»�土å�¡ç‰‡
    ---------------------------------------------------------- */
 .tasks-section {
   margin-bottom: 28rpx;
@@ -1075,7 +1075,7 @@ padding-top: 4rpx;
   min-height: 36rpx;
 }
 
-/* 任务空状�*/
+/* 任务空状æ€*/
 .tasks-empty {
   display: flex;
   flex-direction: column;
@@ -1111,7 +1111,7 @@ padding-top: 4rpx;
 }
 
 /* ----------------------------------------------------------
-   快��作 �2×2 �土按钮网格
+   å¿«æ�·æ“�作 â€2×2 é»�土按钮网格
    ---------------------------------------------------------- */
 .quick-section {
   margin-bottom: 28rpx;
@@ -1167,7 +1167,7 @@ padding-top: 4rpx;
   line-height: 1;
 }
 
-/* �按钮图标色�*/
+/* �按钮图标色彩 */
 .quick-icon--tasks   { background: rgba(14,165,233,0.15); border-color: #BAE6FD; }
 .quick-icon--rewards { background: rgba(245,158,11,0.15); border-color: #FDE68A; }
 .quick-icon--growth  { background: rgba(91,155,213,0.15); border-color: #CBD5E1; }
@@ -1180,7 +1180,7 @@ padding-top: 4rpx;
 }
 
 /* ----------------------------------------------------------
-   �就区域 �水平滚动徽章
+   æˆ�就区域 â€æ°´å¹³æ»šåŠ¨å¾½ç« 
    ---------------------------------------------------------- */
 .achievement-section {
   margin-bottom: 28rpx;
@@ -1292,12 +1292,12 @@ padding-top: 4rpx;
 .log-amount--up { color: #10B981; }
 .log-amount--down { color: #EF4444; }
 
-/* 连续打�徽章的浮动动��使用 uni.scss 全局 float keyframe */
+/* 连续打�徽章的浮动动画 — 使用 uni.scss 全局 float keyframe */
 .streak-badge {
   animation: float 3s ease-in-out infinite;
 }
 
-/* 等级标签的金色光��使用 uni.scss 全局 pulseGlow keyframe */
+/* 等级标签的金色光晕 — 使用 uni.scss 全局 pulseGlow keyframe */
 .points-level-tag {
   animation: pulseGlow 2.5s ease-in-out infinite;
 }

+ 51 - 51
cfc-frontend/pages/home/index.vue

@@ -1,6 +1,6 @@
 <template>
 <view>
-  <!-- �瑕鍳�?splash overlay �?閬��擐㚚△�游��唳旿�㰘蝸摰峕�嚗ōab ����嗡��曄內嚗?-->
+  <!-- �瑕鍳�� splash overlay �� 閬��擐㚚△�游��唳旿�㰘蝸摰峕�嚗ōab ����嗡��曄內嚗� -->
   <view class="splash-overlay" :class="{'fade-out': splashOverlayFading}" v-if="splashOverlay || splashOverlayFading">
     <view class="splash-overlay-bg">
       <view class="bg-circle bg-circle-1"></view>
@@ -11,28 +11,28 @@
       <view class="splash-logo-wrap">
         <image class="splash-logo-img" src="/static/logo.png" mode="aspectFit" />
       </view>
-      <text class="splash-brand-name">瘚㰘𪄳蝳?/text>
+      <text class="splash-brand-name">瘚㰘𪄳蝳�</text>
       <text class="splash-brand-en">Care Family</text>
       <view class="splash-dims-row">
         <view class="splash-dim-item">
           <view class="splash-dim-circle" style="background:rgba(255,140,66,0.3);"><text class="splash-dim-icon">��</text></view>
-          <text class="splash-dim-label">頨?/text>
+          <text class="splash-dim-label">頨�</text>
         </view>
         <view class="splash-dim-item">
           <view class="splash-dim-circle" style="background:rgba(255,107,157,0.3);"><text class="splash-dim-icon">�𤣳</text></view>
-          <text class="splash-dim-label">敹?/text>
+          <text class="splash-dim-label">敹�</text>
         </view>
         <view class="splash-dim-item">
-          <view class="splash-dim-circle" style="background:rgba(99,102,241,0.3);"><text class="splash-dim-icon">�?/text></view>
-          <text class="splash-dim-label">�?/text>
+          <view class="splash-dim-circle" style="background:rgba(99,102,241,0.3);"><text class="splash-dim-icon">��</text></view>
+          <text class="splash-dim-label">��</text>
         </view>
         <view class="splash-dim-item">
           <view class="splash-dim-circle" style="background:rgba(16,185,129,0.3);"><text class="splash-dim-icon">�鈡</text></view>
-          <text class="splash-dim-label">銵?/text>
+          <text class="splash-dim-label">銵�</text>
         </view>
         <view class="splash-dim-item">
           <view class="splash-dim-circle" style="background:rgba(245,158,11,0.3);"><text class="splash-dim-icon">�佂</text></view>
-          <text class="splash-dim-label">撖?/text>
+          <text class="splash-dim-label">撖�</text>
         </view>
       </view>
       <text class="splash-tagline">蝏坔�摰嗥�銝�蝡坔�撟貊��鞉�</text>
@@ -44,14 +44,14 @@
     </view>
   </view>
 
-  <!-- Tabbar ��揢餈�腹憿?-->
+  <!-- Tabbar ��揢餈�腹憿-->
   <tab-transition v-if="showTabTransition" dimCode="action" />
 
-  <!-- �芰蒈敶閙�?�?�𤑳緵憿?撘閙���捆嚗𣬚凒�亙�撋䕘�銝滩歲頧?-->
+  <!-- �芰蒈敶閙�� �� �𤑳緵憿�/撘閙���捆嚗𣬚凒�亙�撋䕘�銝滩歲頧� -->
   <view v-if="!currentRole" class="discover-container">
     <!-- ���憭湧� -->
     <PageBanner theme="home"
-      tagline="摰嗅滬�亙熒�鞾鵭靽曹��?
+      tagline="摰嗅滬�亙熒�鞾鵭靽曹���"
       quote="蝏坔�摰嗥�銝�蝡坔�撟貊��鞉�" />
 
     <!-- 鈭磰�瘝嗵�憸�� -->
@@ -61,7 +61,7 @@
     <view class="recommend-section">
       <view class="section-header">
         <text class="section-title">�𤣳 �剝秄�刻�</text>
-        <text class="section-more" @click="goShop">�亦��游� �?/text>
+        <text class="section-more" @click="goShop">�亦��游� ��</text>
       </view>
       <scroll-view scroll-x enable-flex show-scrollbar="false" class="type-filter-scroll">
         <view
@@ -74,10 +74,10 @@
         </view>
       </scroll-view>
       <view v-if="loading" class="loading-state">
-        <text class="loading-text">�㰘蝸銝?..</text>
+        <text class="loading-text">�㰘蝸銝�...</text>
       </view>
       <view v-else-if="products.length === 0" class="empty-state">
-        <text class="empty-text">������嚗�縧����讠��?/text>
+        <text class="empty-text">������嚗�縧����讠���</text>
       </view>
       <view v-else class="product-grid">
         <view
@@ -90,7 +90,7 @@
           <view class="product-info">
             <text class="product-name">{{ item.name }}</text>
             <view class="product-price-row">
-              <!-- 皜詨恥銝齿遬蝷箔遠�?-->
+              <!-- 皜詨恥銝齿遬蝷箔遠�-->
               <text class="product-price-login">�餃��亦�</text>
             </view>
           </view>
@@ -98,11 +98,11 @@
       </view>
     </view>
 
-    <!-- �剝秄瘣餃𢆡嚗���∩辣撅閧內嚗?-->
+    <!-- �剝秄瘣餃𢆡嚗���∩辣撅閧內嚗-->
     <view class="section">
       <view class="section-header">
         <text class="section-title">�𤣳 �剝秄瘣餃𢆡</text>
-        <text class="section-more" @click="goActivities">�亦��游� �?/text>
+        <text class="section-more" @click="goActivities">�亦��游� ��</text>
       </view>
       <view v-if="dimensionActivities.length === 0" class="empty-state" style="padding: 40rpx 0;">
         <text class="empty-text">���瘣餃𢆡</text>
@@ -116,7 +116,7 @@
               <text class="activity-time">{{ act.startTime }}</text>
             </view>
             <view class="activity-bottom">
-              <text class="activity-status" :class="'status-' + (act.status || 'upcoming')">{{ act.status === 'ongoing' ? '餈𥡝�銝? : act.status === 'ended' ? '撌脩��? : '�喳�撘�憪? }}</text>
+              <text class="activity-status" :class="'status-' + (act.status || 'upcoming')">{{ act.status === 'ongoing' ? '餈𥡝�銝�' : act.status === 'ended' ? '撌脩���' : '�喳�撘�憪�' }}</text>
               <text class="activity-fee" v-if="act.price && act.price > 0">瞼{{ (act.price / 100).toFixed(0) }}</text>
               <text class="activity-fee fee-free" v-else>�滩晶</text>
             </view>
@@ -125,15 +125,15 @@
       </view>
     </view>
 
-    <!-- �刻���粉嚗���∩辣撅閧內嚗?-->
+    <!-- �刻���粉嚗���∩辣撅閧內嚗-->
     <view class="section">
       <view class="section-header">
         <text class="section-title">�� �刻���粉</text>
-        <text class="section-more" @click="goArticles">�游� �?/text>
+        <text class="section-more" @click="goArticles">�游� ��</text>
       </view>
       <view class="article-list">
         <view v-if="articlesLoading" class="loading-state" style="padding: 40rpx 0;">
-          <text class="loading-text">�㰘蝸銝?..</text>
+          <text class="loading-text">�㰘蝸銝�...</text>
         </view>
         <!-- �䭾㺭�格𧒄�曄內�牐��∠� -->
         <template v-else-if="indexArticles.length === 0">
@@ -142,7 +142,7 @@
               <text class="article-category-text">�刻����</text>
             </view>
             <text class="article-title">����刻����</text>
-            <text class="article-summary">蝎曉蔗��捆�喳�銝羓瑪嚗峕𨯵霂瑟�敺?/text>
+            <text class="article-summary">蝎曉蔗��捆�喳�銝羓瑪嚗峕𨯵霂瑟�敺�</text>
             <view class="article-meta">
               <view class="meta-item">
                 <text class="meta-icon">&#x1F4D6;</text>
@@ -175,7 +175,7 @@
     <!-- 鈭𠉛輕�冽艶撟貊��拚猐 -->
     <view class="why-section">
       <view class="section-header">
-        <text class="section-title">�� 鈭𠉛輕�冽艶撟貊��拚猐 �?蝏坔�摰嗥�銝�蝡坔�撟貊��鞉�</text>
+        <text class="section-title">�� 鈭𠉛輕�冽艶撟貊��拚猐 �蝏坔�摰嗥�銝�蝡坔�撟貊��鞉�</text>
       </view>
       <view class="dim-matrix">
         <view
@@ -191,7 +191,7 @@
           <text class="dim-desc">{{ dim.desc }}</text>
         </view>
       </view>
-      <!-- 鈭𠉛輕�賡��航�擖?-->
+      <!-- 鈭𠉛輕�賡��航�擖-->
       <view class="dim-energy-row">
         <view
           v-for="c in energyDotColors" :key="c"
@@ -204,14 +204,14 @@
     <!-- 摨閖��餃��厰僼 -->
     <view class="login-footer">
       <button class="login-btn" @click="handleLogin">�餃� / 瘜典�</button>
-      <text class="login-footer-text">�餃��唾”蝷箏��譌�羓鍂�瑕�霈柴�见��𢠃�蝘�錇蝑硔�?/text>
+      <text class="login-footer-text">�餃��唾”蝷箏��譌�羓鍂�瑕�霈柴�见��𢠃�蝘�錇蝑硔��</text>
     </view>
 
     <!-- 摨閖��牐� -->
     <view style="height: 120rpx;"></view>
   </view>
 
-  <!-- �餃��?�?撌脰�蝘餃� home ���嚗屸�朞� redirectTo 頝唾蓮嚗䔶��漤���葡�?-->
+  <!-- �餃��� �� 撌脰�蝘餃� home ���嚗屸�朞� redirectTo 頝唾蓮嚗䔶��漤���葡�� -->
 </view>
 </template>
 
@@ -222,11 +222,11 @@ import TabTransition from '../../components/tab-transition.vue'
 import { acceptParentInvite, productList, getActivityList, getFeaturedArticles } from '../../utils/api.js'
 
 var DIMENSIONS = [
-  { code: 'body', name: '頨?, icon: '��', color: '#8D6E63', bgColor: 'rgba(141,110,99,0.15)', title: '銝餃𢆡�亙熒', desc: '�冽������䲮瘜𤏪�隞擧覔皞鞱���振鈭箔�韐剁���澈擃䁅捶�誯鵭撖輻�瘣? },
-  { code: 'mind', name: '敹?, icon: '�𤣳', color: '#FF6B35', bgColor: 'rgba(255,107,53,0.15)', title: '憭抒�隡䭾㗁', desc: '撠�鵭颲�臁�文��𦒘蛹摰嗆�蝥賢蒂嚗諹悟摰園�皜拇�隞�誨�訾�' },
-  { code: 'wisdom', name: '�?, icon: '�?, color: '#FFD700', bgColor: 'rgba(255,215,0,0.15)', title: '韏贝��芣䔉', desc: '銝㮖�瘚贝�銝𡒊�韐典畺�鳴�撘��臬酋摮鞾𢒰�烐𧊋�亦�憭扳惣�? },
-  { code: 'action', name: '銵?, icon: '�鈡', color: '#4CAF50', bgColor: 'rgba(76,175,80,0.15)', title: '�亥����', desc: '�其熔摮鞉�憭碶�瘝䠷�銝哨�霈拙�摨瑞�瘣餅䲮撘讐�甇�䰻銵��銝�' },
-  { code: 'wealth', name: '撖?, icon: '�佂', color: '#42A5F5', bgColor: 'rgba(66,165,245,0.15)', title: '�拐��𥕦�', desc: '靘脲��𥕦恥������典⏚隞硋�鈭思葉摰䂿緵摰嗅滬蝚砌��嗅��脩瑪' }
+  { code: 'body', name: '頨�', icon: '��', color: '#8D6E63', bgColor: 'rgba(141,110,99,0.15)', title: '銝餃𢆡�亙熒', desc: '�冽������䲮瘜𤏪�隞擧覔皞鞱���振鈭箔�韐剁���澈擃䁅捶�誯鵭撖輻�瘣�' },
+  { code: 'mind', name: '敹�', icon: '�𤣳', color: '#FF6B35', bgColor: 'rgba(255,107,53,0.15)', title: '憭抒�隡䭾㗁', desc: '撠�鵭颲�臁�文��𦒘蛹摰嗆�蝥賢蒂嚗諹悟摰園�皜拇�隞�誨�訾�' },
+  { code: 'wisdom', name: '��', icon: '��', color: '#FFD700', bgColor: 'rgba(255,215,0,0.15)', title: '韏贝��芣䔉', desc: '銝㮖�瘚贝�銝𡒊�韐典畺�鳴�撘��臬酋摮鞾𢒰�烐𧊋�亦�憭扳惣��' },
+  { code: 'action', name: '銵�', icon: '�鈡', color: '#4CAF50', bgColor: 'rgba(76,175,80,0.15)', title: '�亥����', desc: '�其熔摮鞉�憭碶�瘝䠷�銝哨�霈拙�摨瑞�瘣餅䲮撘讐�甇�䰻銵��銝�' },
+  { code: 'wealth', name: '撖�', icon: '�佂', color: '#42A5F5', bgColor: 'rgba(66,165,245,0.15)', title: '�拐��𥕦�', desc: '靘脲��𥕦恥������典⏚隞硋�鈭思葉摰䂿緵摰嗅滬蝚砌��嗅��脩瑪' }
 ]
 
 export default {
@@ -236,17 +236,17 @@ export default {
     TabTransition
   },
   data() {
-    // 隞?storage 憸���餃��?閫坿𠧧嚗𣬚&靽嗪�甈⊥葡�枏朖甇�&嚗ÁeChat 皜脫�撅?�餉�撅��蝳餅沲��� onLoad �扯��滚歇皜脫�嚗?
+    // 隞� storage 憸���餃���/閫坿𠧧嚗𣬚&靽嗪�甈⊥葡�枏朖甇�&嚗ÁeChat 皜脫�撅�/�餉�撅��蝳餅沲��� onLoad �扯��滚歇皜脫�嚗�
     var _token = uni.getStorageSync('token')
     var _currentRole = ''
     if (_token) {
       _currentRole = uni.getStorageSync('currentRole') || uni.getStorageSync('role') || ''
     }
-    // �瑕鍳�冽�霈堆��?App.vue onLaunch 霈曄蔭嚗䔶��典��臬𢆡�嗅��剁�
+    // �瑕鍳�冽�霈堆��App.vue onLaunch 霈曄蔭嚗䔶��典��臬𢆡�嗅��剁�
     var _isFirstLaunch = (uni.getStorageSync('_showSplashOverlay') === '1')
     return {
       currentRole: _currentRole,
-      // TabTransition 憪讠�暺䁅恕 true嚗𣬚&靽嗪�甈⊥葡�枏朖�箇緵嚗𥕦��臬𢆡�嗉◤ splash overlay 閬��銝滚虾閫?
+      // TabTransition 憪讠�暺䁅恕 true嚗𣬚&靽嗪�甈⊥葡�枏朖�箇緵嚗𥕦��臬𢆡�嗉◤ splash overlay 閬��銝滚虾閫
       showTabTransition: true,
 
       // splash loading overlay嚗���臬𢆡�嗅�蝷綽��唳旿�㰘蝸摰���哨�
@@ -281,25 +281,25 @@ export default {
     this._doInit(options)
   },
   onShow() {
-    // splash overlay 撌脣銁 data() 銝剜覔�?storage ��扇�嘥��吔�甇文��芷��滨蔭�喲𡡒�∩辣
+    // splash overlay 撌脣銁 data() 銝剜覔�storage ��扇�嘥��吔�甇文��芷��滨蔭�喲𡡒�∩辣
     if (this.splashOverlay) {
       uni.removeStorageSync('_showSplashOverlay')
       this._splashLoadCount = 0
       this._splashMinPassed = false
 
       var self = this
-      // ��雿𤾸�蝷?800ms
+      // ��雿𤾸�蝷800ms
       setTimeout(function() {
         self._splashMinPassed = true
         self._tryHideSplash()
       }, 800)
-      // ��憭𡁜�蝷?5s
+      // ��憭𡁜�蝷5s
       setTimeout(function() {
         if (self.splashOverlay) self._hideSplashOverlay()
       }, 5000)
     } else {
       // tab ���嚗関abTransition 撌脣銁 data() 銝凋蛹 true嚗𣬚&靽嗪�甈⊥葡�枏朖�箇緵
-      // 雿��隞嗥�摮睃��齿活����嗅虾�賢歇鋡?_watchPageReady 蝵桐蛹 false嚗屸�閬��蝵?
+      // 雿��隞嗥�摮睃��齿活����嗅虾�賢歇鋡� _watchPageReady 蝵桐蛹 false嚗屸�閬��蝵�
       this.showTabTransition = true
       this._watchPageReady()
     }
@@ -316,17 +316,17 @@ export default {
       if (this.splashOverlayFading) return
       if (!this._splashMinPassed) return
       if (this.isLoggedIn()) {
-        // �餃��冽�嚗𡁶�敺��蝏�辣�?ready 靽∪噡
+        // �餃��冽�嚗𡁶�敺��蝏�辣�ready 靽∪噡
         if (this._splashReady) this._hideSplashOverlay()
       } else {
-        // 皜詨恥嚗𡁶�敺?3 銝?API �券�餈𥪜�
+        // 皜詨恥嚗𡁶�敺� 3 銝� API �券�餈𥪜�
         if (this._splashLoadCount >= 3) this._hideSplashOverlay()
       }
     },
     _hideSplashOverlay() {
       if (this.splashOverlayFading) return
       this.splashOverlayFading = true
-      // splash �喲𡡒�嗅��園��?TabTransition嚗�俈甇?splash 蝏𤘪��𡡞緾�啗�皜⊿△嚗?
+      // splash �喲𡡒�嗅��園��� TabTransition嚗�俈甇� splash 蝏𤘪��𡡞緾�啗�皜⊿△嚗�
       this.showTabTransition = false
       var self = this
       setTimeout(function() {
@@ -339,7 +339,7 @@ export default {
       // 撌脣�撘���餃��冽�銝滚��朞�甇日△�X葡�枏�蝏�辣
     },
 
-    // 擐㚚△ TabTransition �冽����哨�璉�瘚见��桀�摰寞糓�血停蝏?
+    // 擐㚚△ TabTransition �冽����哨�璉�瘚见��桀�摰寞糓�血停蝏
     _watchPageReady() {
       var self = this
       var unwatch = this.$watch(function() {
@@ -385,7 +385,7 @@ export default {
         uni.removeStorageSync('inviteType')
         return
       }
-      // �餃��冽�嚗朞歲頧砍� home ���憿菟𢒰嚗䔶��漤���葡�梶�隞?
+      // �餃��冽�嚗朞歲頧砍� home ���憿菟𢒰嚗䔶��漤���葡�梶�隞
       var targetUrl = this.currentRole === 'child'
         ? '/pages/home/child-index'
         : '/pages/home/parent-index'
@@ -407,7 +407,7 @@ export default {
         return role
       }
 
-      // �芣�摰園鵭韐血噡��捂��揢�啣酋摮鞱�閫?
+      // �芣�摰園鵭韐血噡��捂��揢�啣酋摮鞱�閫
       if (currentRole === 'child' && role !== 'parent') {
         return role
       }
@@ -418,7 +418,7 @@ export default {
       this.currentRole = this.normalizeCurrentRole()
       uni.setStorageSync('currentRole', this.currentRole)
     },
-    // ===== �𤑳緵憿?/ �芰蒈敶閙��䲮瘜?=====
+    // ===== �𤑳緵憿� / �芰蒈敶閙��䲮瘜� =====
     loadProducts: function() {
       this.loading = true
       var params = { page: 1, size: 10 }
@@ -512,7 +512,7 @@ export default {
       uni.navigateTo({ url: '/pages/login/login?redirect=' + encodeURIComponent('/pages/home/index') })
     },
     async handleParentInvite(code) {
-      // 撱嗉��曄內嚗𣬚�敺�蒈敶訫��?
+      // 撱嗉��曄內嚗𣬚�敺�蒈敶訫��
       setTimeout(async () => {
         const hasToken = uni.getStorageSync('token')
         if (!hasToken) {
@@ -522,14 +522,14 @@ export default {
           })
           return
         }
-        // 撌脩蒈敶𤏪��曄內蝖株恕獢?
+        // 撌脩蒈敶𤏪��曄內蝖株恕獢
         uni.showModal({
           title: '�惩�摰嗅滬',
-          content: '�典歇鋡恍�霂瑕��亙振摨哨��臬炏�亙�嚗?,
+          content: '�典歇鋡恍�霂瑕��亙振摨哨��臬炏�亙�嚗�',
           success: async (res) => {
             if (res.confirm) {
               try {
-                uni.showLoading({ title: '�惩�銝?..' })
+                uni.showLoading({ title: '�惩�銝�...' })
                 const result = await acceptParentInvite(code)
                 uni.hideLoading()
                 if (result.code === 200) {
@@ -732,7 +732,7 @@ export default {
   -webkit-box-orient: vertical;
   overflow: hidden;
 }
-/* 鈭𠉛輕�賡��?*/
+/* 鈭𠉛輕�賡��*/
 .dim-energy-row {
   display: flex;
   justify-content: center;
@@ -971,7 +971,7 @@ export default {
   color: #bbb;
 }
 
-/* ===== Splash Loading Overlay嚗���臬𢆡�蹱踎嚗峕䔉�?merge splash.vue嚗?===== */
+/* ===== Splash Loading Overlay嚗���臬𢆡�蹱踎嚗峕䔉�� merge splash.vue嚗� ===== */
 .splash-overlay {
   position: fixed;
   top: 0; left: 0; right: 0; bottom: 0;

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

@@ -8,11 +8,11 @@
       <text class="nav-title">�员详情</text>
     </view>
 
-    <!-- 加载�-->
-    <view class="loading" v-if="loading">加载�..</view>
+    <!-- 加载中 -->
+    <view class="loading" v-if="loading">加载中...</view>
 
     <template v-if="!loading">
-      <!-- �员信��-->
+      <!-- �员信�� -->
       <view class="member-card" v-if="memberInfo">
         <view class="member-avatar">
           <text class="avatar-text">{{ memberInfo.name && memberInfo.name.charAt(0) || '?' }}</text>
@@ -108,16 +108,16 @@ export default {
       return {}
     },
     childId: function() {
-      // 仅当�员是孩�时�返�childId
+      // 仅当�员是孩�时�返回 childId
       return this.memberType === 'child' ? this.memberId : null
     },
     energyList: function() {
       var dims = [
-        { code: 'body', icon: '�', label: '�, color: '#8D6E63' },
-        { code: 'mind', icon: '🔥', label: '�, color: '#FF6B35' },
-        { code: 'wisdom', icon: '⚔�', label: '�, color: '#F59E0B' },
-        { code: 'action', icon: '🌿', label: '�, color: '#4CAF50' },
-        { code: 'wealth', icon: '💧', label: '�, color: '#3B82F6' }
+        { code: 'body', icon: '�', label: '身', color: '#8D6E63' },
+        { code: 'mind', icon: '🔥', label: '心', color: '#FF6B35' },
+        { code: 'wisdom', icon: '⚔�', label: '智', color: '#F59E0B' },
+        { code: 'action', icon: '🌿', label: '行', color: '#4CAF50' },
+        { code: 'wealth', icon: '💧', label: '富', color: '#3B82F6' }
       ]
       var self = this
       return dims.map(function(d) {

Some files were not shown because too many files changed in this diff