innate-trajectory.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <template>
  2. <view class="trajectory-container">
  3. <view class="loading-state" v-if="loading">
  4. <text>加载中...</text>
  5. </view>
  6. <template v-if="!loading && trajectory">
  7. <view class="section">
  8. <view class="section-title">先天 vs 后天</view>
  9. <view class="compare-row">
  10. <view class="compare-item">
  11. <text class="compare-label">先天心能量</text>
  12. <text class="compare-value">{{ trajectory.innateVsCurrent.mindInnate || 0 }}</text>
  13. </view>
  14. <view class="compare-item">
  15. <text class="compare-label">当前心能量</text>
  16. <text class="compare-value">{{ trajectory.innateVsCurrent.mindCurrent || 0 }}</text>
  17. </view>
  18. <view class="compare-item">
  19. <text class="compare-label">成长</text>
  20. <text class="compare-value" :style="{ color: growthColor }">{{ trajectory.innateVsCurrent.growth || '0' }}</text>
  21. </view>
  22. </view>
  23. </view>
  24. <view class="section" v-if="hasInnateScores">
  25. <view class="section-title">五维先天基础分</view>
  26. <view class="dim-row" v-for="(score, dim) in trajectory.innateDimensionScores" :key="dim">
  27. <text class="dim-label">{{ dimLabel(dim) }}</text>
  28. <view class="dim-track">
  29. <view class="dim-fill" :style="{ width: score + '%' }"></view>
  30. </view>
  31. <text class="dim-value">{{ score }}</text>
  32. </view>
  33. </view>
  34. <view class="section" v-if="trajectory.growthTrend">
  35. <view class="section-title">成长趋势</view>
  36. <text class="trend-text">{{ trajectory.growthTrend }}</text>
  37. </view>
  38. <view class="section" v-if="trajectory.advice">
  39. <view class="section-title">成长建议</view>
  40. <text class="advice-text">{{ trajectory.advice }}</text>
  41. </view>
  42. </template>
  43. <view class="empty-state" v-if="!loading && !trajectory && loadError">
  44. <text>{{ loadError }}</text>
  45. </view>
  46. </view>
  47. </template>
  48. <script>
  49. import { getInnateTrajectory } from '../../utils/api'
  50. export default {
  51. data() {
  52. return {
  53. memberId: null,
  54. memberType: 'child',
  55. familyId: null,
  56. loading: false,
  57. trajectory: null,
  58. loadError: '',
  59. dimNames: { body: '身', mind: '心', wisdom: '智', action: '行', wealth: '富' }
  60. }
  61. },
  62. computed: {
  63. hasInnateScores() {
  64. return !!this.trajectory && !!this.trajectory.innateDimensionScores
  65. },
  66. growthColor() {
  67. if (!this.trajectory || !this.trajectory.innateVsCurrent) return '#999'
  68. var g = this.trajectory.innateVsCurrent.growth || '0'
  69. if (g.indexOf('-') === 0) return '#f56c6c'
  70. return '#07c160'
  71. }
  72. },
  73. onLoad(options) {
  74. this.memberId = options.memberId ? Number(options.memberId) : null
  75. this.memberType = options.memberType || 'child'
  76. this.familyId = options.familyId ? Number(options.familyId) : null
  77. if (!this.memberId) {
  78. this.loadError = '缺少成员ID'
  79. return
  80. }
  81. this.load()
  82. },
  83. methods: {
  84. load() {
  85. var self = this
  86. self.loading = true
  87. getInnateTrajectory({ memberId: self.memberId, memberType: self.memberType, familyId: self.familyId }).then(function (res) {
  88. self.loading = false
  89. if (res && res.code === 200) {
  90. self.trajectory = res.data
  91. } else {
  92. self.loadError = (res && res.message) || '加载失败'
  93. }
  94. }).catch(function () {
  95. self.loading = false
  96. self.loadError = '网络异常'
  97. })
  98. },
  99. dimLabel(dim) {
  100. return this.dimNames[dim] || dim
  101. }
  102. }
  103. }
  104. </script>
  105. <style scoped>
  106. .trajectory-container {
  107. min-height: 100vh;
  108. background: #F8F6F0;
  109. padding-bottom: 60rpx;
  110. }
  111. .loading-state {
  112. display: flex;
  113. align-items: center;
  114. justify-content: center;
  115. padding: 120rpx 0;
  116. color: #999;
  117. font-size: 28rpx;
  118. }
  119. .section {
  120. margin: 24rpx 32rpx;
  121. background: #fff;
  122. border-radius: 20rpx;
  123. padding: 28rpx;
  124. box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.04);
  125. }
  126. .section-title {
  127. font-size: 30rpx;
  128. font-weight: 600;
  129. color: #333;
  130. margin-bottom: 20rpx;
  131. }
  132. .compare-row {
  133. display: flex;
  134. justify-content: space-around;
  135. }
  136. .compare-item {
  137. display: flex;
  138. flex-direction: column;
  139. align-items: center;
  140. }
  141. .compare-label {
  142. font-size: 24rpx;
  143. color: #999;
  144. margin-bottom: 8rpx;
  145. }
  146. .compare-value {
  147. font-size: 48rpx;
  148. font-weight: 700;
  149. color: #333;
  150. }
  151. .dim-row {
  152. display: flex;
  153. align-items: center;
  154. margin-bottom: 16rpx;
  155. }
  156. .dim-label {
  157. font-size: 28rpx;
  158. font-weight: 600;
  159. width: 48rpx;
  160. text-align: center;
  161. }
  162. .dim-track {
  163. flex: 1;
  164. height: 24rpx;
  165. background: #F0F0F0;
  166. border-radius: 12rpx;
  167. overflow: hidden;
  168. margin: 0 16rpx;
  169. }
  170. .dim-fill {
  171. height: 100%;
  172. border-radius: 12rpx;
  173. background: linear-gradient(90deg, #FF6B9D, #FF8C42);
  174. }
  175. .dim-value {
  176. font-size: 24rpx;
  177. color: #666;
  178. width: 60rpx;
  179. text-align: right;
  180. }
  181. .trend-text, .advice-text {
  182. font-size: 28rpx;
  183. color: #444;
  184. line-height: 1.8;
  185. }
  186. .empty-state {
  187. display: flex;
  188. align-items: center;
  189. justify-content: center;
  190. padding: 120rpx 0;
  191. color: #999;
  192. font-size: 28rpx;
  193. }
  194. </style>