HealthDimensionsSection.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <view class="health-dimensions-section">
  3. <view class="section-header">
  4. <text class="section-title">七维健康全景</text>
  5. <text class="section-more" @click="goHealthDimensions">查看详情 ›</text>
  6. </view>
  7. <!-- 加载态 -->
  8. <view v-if="!healthData" class="loading-state">
  9. <text class="loading-text">加载中...</text>
  10. </view>
  11. <!-- 维度列表(无数据时显示7项默认值,分数为0) -->
  12. <view v-else class="dimension-grid">
  13. <view
  14. class="dimension-item"
  15. v-for="dim in displayDimensions"
  16. :key="dim.dimension || dim.key"
  17. @click="goDimensionDetail(dim)">
  18. <text class="dimension-icon">{{ getDimIcon(dim.dimension || dim.key) }}</text>
  19. <text class="dimension-name">{{ dim.label }}</text>
  20. <view class="dimension-score-bar">
  21. <view
  22. class="dimension-score-fill"
  23. :style="'width:' + Math.min(100, (dim.score || 0)) + '%'"></view>
  24. </view>
  25. <text class="dimension-score">{{ dim.score || 0 }}分</text>
  26. </view>
  27. </view>
  28. </view>
  29. </template>
  30. <script>
  31. var DIM_ICONS = {
  32. growth: '\u{1F4AA}',
  33. sleep: '\u{1F634}',
  34. vision: '\u{1F441}',
  35. immunity: '\u{1F6E1}',
  36. nutrition: '\u{1F966}',
  37. gut: '\u{1F9A9}',
  38. exercise: '\u{1F3C3}',
  39. body: '\u{1F3C3}',
  40. mind: '\u{1F9E0}',
  41. wisdom: '\u{1F4D6}',
  42. action: '\u{1F331}',
  43. wealth: '\u{1F4B0}',
  44. social: '\u{1F91D}',
  45. family: '\u{1F46A}'
  46. }
  47. var DEFAULT_DIMENSIONS = [
  48. { dimension: 'growth', label: '成长发育', score: 0 },
  49. { dimension: 'sleep', label: '睡眠', score: 0 },
  50. { dimension: 'vision', label: '视力', score: 0 },
  51. { dimension: 'immunity', label: '免疫力', score: 0 },
  52. { dimension: 'nutrition', label: '营养', score: 0 },
  53. { dimension: 'gut', label: '肠道', score: 0 },
  54. { dimension: 'exercise', label: '运动', score: 0 }
  55. ]
  56. export default {
  57. props: {
  58. healthData: { type: Object, default: null },
  59. activeChildId: { type: [Number, String], default: null }
  60. },
  61. computed: {
  62. displayDimensions: function() {
  63. if (this.healthData && this.healthData.dimensions && this.healthData.dimensions.length > 0) {
  64. return this.healthData.dimensions
  65. }
  66. return DEFAULT_DIMENSIONS
  67. }
  68. },
  69. methods: {
  70. getDimIcon: function(key) {
  71. return DIM_ICONS[key] || '\u{2B50}'
  72. },
  73. goHealthDimensions: function() {
  74. if (!this.activeChildId) {
  75. uni.showToast({ title: '请先选择孩子', icon: 'none' })
  76. return
  77. }
  78. uni.navigateTo({ url: '/pages/body-detail/health-dimensions?childId=' + this.activeChildId })
  79. },
  80. goDimensionDetail: function(dim) {
  81. var key = dim.dimension || dim.key
  82. if (!key) return
  83. uni.navigateTo({ url: '/pages/body-detail/dimension-detail?dimension=' + key + '&childId=' + this.activeChildId })
  84. }
  85. }
  86. }
  87. </script>
  88. <style scoped>
  89. .health-dimensions-section {
  90. margin: 20rpx 20rpx;
  91. background: #FFFFFF;
  92. border-radius: 24rpx;
  93. padding: 24rpx 24rpx 32rpx;
  94. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
  95. }
  96. .section-header {
  97. display: flex;
  98. justify-content: space-between;
  99. align-items: center;
  100. margin-bottom: 24rpx;
  101. }
  102. .section-title {
  103. font-size: 30rpx;
  104. font-weight: bold;
  105. color: #333;
  106. }
  107. .section-more {
  108. font-size: 24rpx;
  109. color: #FF8C42;
  110. }
  111. .loading-state, .empty-state {
  112. display: flex;
  113. justify-content: center;
  114. padding: 40rpx 0;
  115. }
  116. .loading-text, .empty-tip {
  117. font-size: 24rpx;
  118. color: #999;
  119. }
  120. .dimension-grid {
  121. display: flex;
  122. flex-wrap: wrap;
  123. gap: 20rpx;
  124. }
  125. .dimension-item {
  126. width: calc(33.33% - 14rpx);
  127. display: flex;
  128. flex-direction: column;
  129. align-items: center;
  130. padding: 16rpx 0;
  131. }
  132. .dimension-icon {
  133. font-size: 40rpx;
  134. margin-bottom: 8rpx;
  135. }
  136. .dimension-name {
  137. font-size: 24rpx;
  138. color: #333;
  139. font-weight: 500;
  140. margin-bottom: 10rpx;
  141. }
  142. .dimension-score-bar {
  143. width: 100%;
  144. height: 8rpx;
  145. background: #F5F5F5;
  146. border-radius: 4rpx;
  147. overflow: hidden;
  148. margin-bottom: 6rpx;
  149. }
  150. .dimension-score-fill {
  151. height: 100%;
  152. background: linear-gradient(90deg, #FF8C42, #FFB088);
  153. border-radius: 4rpx;
  154. transition: width 0.3s;
  155. }
  156. .dimension-score {
  157. font-size: 22rpx;
  158. color: #FF8C42;
  159. font-weight: 500;
  160. }
  161. </style>