index.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <view class="index-page">
  3. <view class="header">
  4. <view class="greeting">
  5. <text class="hi">Hi,</text>
  6. <text class="nickname">{{ nickname || '健康达人' }}</text>
  7. </view>
  8. </view>
  9. <view class="summary-card" v-if="activeGoal">
  10. <view class="summary-item">
  11. <text class="label">起始体重</text>
  12. <text class="value">{{ activeGoal.startWeight }} kg</text>
  13. </view>
  14. <view class="summary-item">
  15. <text class="label">目标体重</text>
  16. <text class="value">{{ activeGoal.targetWeight }} kg</text>
  17. </view>
  18. <view class="summary-item">
  19. <text class="label">已记录</text>
  20. <text class="value">{{ weightCount }} 次</text>
  21. </view>
  22. </view>
  23. <view class="empty-goal" v-else>
  24. <text>还没有减脂目标</text>
  25. <button class="set-goal-btn" size="mini" @click="goToProfile">去设置</button>
  26. </view>
  27. <view class="quick-actions">
  28. <view class="action-item" @click="goWeight">
  29. <text class="icon">📝</text>
  30. <text class="text">体重记录</text>
  31. </view>
  32. <view class="action-item" @click="goDiet">
  33. <text class="icon">🍽️</text>
  34. <text class="text">饮食记录</text>
  35. </view>
  36. <view class="action-item" @click="goExercise">
  37. <text class="icon">🏃</text>
  38. <text class="text">运动记录</text>
  39. </view>
  40. <view class="action-item" @click="goAI">
  41. <text class="icon">🤖</text>
  42. <text class="text">AI教练</text>
  43. </view>
  44. </view>
  45. <view class="today-stats">
  46. <view class="stat-box">
  47. <text class="stat-label">今日摄入</text>
  48. <text class="stat-value">{{ todayCalories }} kcal</text>
  49. </view>
  50. <view class="stat-box">
  51. <text class="stat-label">最新体重</text>
  52. <text class="stat-value">{{ latestWeight }} kg</text>
  53. </view>
  54. </view>
  55. </view>
  56. </template>
  57. <script>
  58. import { getActiveGoal, getWeightList, getCaloriesSummary } from '../../utils/api.js'
  59. import { today } from '../../utils/format.js'
  60. export default {
  61. data() {
  62. return {
  63. nickname: '',
  64. activeGoal: null,
  65. weightList: [],
  66. todayCalories: 0,
  67. latestWeight: '--'
  68. }
  69. },
  70. computed: {
  71. weightCount() {
  72. return this.weightList ? this.weightList.length : 0
  73. }
  74. },
  75. onLoad() {
  76. var userInfo = uni.getStorageSync('userInfo')
  77. this.nickname = userInfo && userInfo.nickname ? userInfo.nickname : ''
  78. },
  79. onShow() {
  80. this.loadData()
  81. },
  82. methods: {
  83. loadData() {
  84. getActiveGoal().then(res => {
  85. if (res.data) this.activeGoal = res.data
  86. })
  87. getWeightList().then(res => {
  88. if (res.data && res.data.length > 0) {
  89. this.weightList = res.data
  90. var sorted = [...res.data].sort((a,b) => {
  91. var ta = new Date(a.measureDate || a.createTime).getTime()
  92. var tb = new Date(b.measureDate || b.createTime).getTime()
  93. return tb - ta
  94. })
  95. this.latestWeight = sorted[0].weight
  96. } else {
  97. this.weightList = []
  98. }
  99. })
  100. getCaloriesSummary(today()).then(res => {
  101. if (res.data) this.todayCalories = res.data
  102. })
  103. },
  104. goToProfile() {
  105. uni.navigateTo({ url: '/pages/profile/index' })
  106. },
  107. goWeight() {
  108. uni.switchTab({ url: '/pages/weight/index' })
  109. },
  110. goDiet() {
  111. uni.switchTab({ url: '/pages/diet/index' })
  112. },
  113. goExercise() {
  114. uni.switchTab({ url: '/pages/exercise/index' })
  115. },
  116. goAI() {
  117. uni.switchTab({ url: '/pages/ai-coach/index' })
  118. }
  119. }
  120. }
  121. </script>
  122. <style>
  123. .index-page { padding: 30rpx; }
  124. .header { margin-bottom: 30rpx; }
  125. .greeting { font-size: 36rpx; font-weight: 600; }
  126. .nickname { color: #F97316; }
  127. .summary-card { display: flex; justify-content: space-between; background: #fff; padding: 30rpx; border-radius: 16rpx; margin-bottom: 30rpx; box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05); }
  128. .summary-item { display: flex; flex-direction: column; align-items: center; }
  129. .label { font-size: 24rpx; color: #666; margin-bottom: 8rpx; }
  130. .value { font-size: 32rpx; font-weight: 600; color: #333; }
  131. .empty-goal { background: #fff; padding: 30rpx; border-radius: 16rpx; display: flex; align-items: center; justify-content: space-between; margin-bottom: 30rpx; }
  132. .set-goal-btn { background: #F97316; color: #fff; border-radius: 40rpx; }
  133. .quick-actions { display: flex; justify-content: space-between; background: #fff; padding: 30rpx 20rpx; border-radius: 16rpx; margin-bottom: 30rpx; }
  134. .action-item { display: flex; flex-direction: column; align-items: center; flex: 1; }
  135. .icon { font-size: 50rpx; margin-bottom: 8rpx; }
  136. .text { font-size: 24rpx; color: #333; }
  137. .today-stats { display: flex; justify-content: space-between; }
  138. .stat-box { background: #fff; padding: 30rpx; border-radius: 16rpx; flex: 1; margin: 0 10rpx; }
  139. .stat-label { font-size: 24rpx; color: #666; margin-bottom: 8rpx; display: block; }
  140. .stat-value { font-size: 36rpx; font-weight: 600; color: #F97316; }
  141. </style>