index.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <template>
  2. <view class="profile-page">
  3. <view class="header">
  4. <text class="title">我的</text>
  5. </view>
  6. <view class="section" v-if="!activeGoal">
  7. <view class="section-title">设置减脂目标</view>
  8. <view class="form">
  9. <view class="form-item">
  10. <text class="label">起始体重(kg)</text>
  11. <input class="input" type="digit" v-model="goal.startWeight" placeholder="请输入起始体重" />
  12. </view>
  13. <view class="form-item">
  14. <text class="label">目标体重(kg)</text>
  15. <input class="input" type="digit" v-model="goal.targetWeight" placeholder="请输入目标体重" />
  16. </view>
  17. <view class="form-item">
  18. <text class="label">目标体脂率(%)</text>
  19. <input class="input" type="digit" v-model="goal.targetBodyFat" placeholder="选填" />
  20. </view>
  21. <view class="form-item">
  22. <text class="label">开始日期</text>
  23. <picker mode="date" :value="goal.startDate" @change="onStartDateChange">
  24. <view class="picker">{{ goal.startDate }}</view>
  25. </picker>
  26. </view>
  27. <view class="form-item">
  28. <text class="label">目标日期</text>
  29. <picker mode="date" :value="goal.targetDate" @change="onTargetDateChange">
  30. <view class="picker">{{ goal.targetDate }}</view>
  31. </picker>
  32. </view>
  33. </view>
  34. <button class="submit-btn" @click="createGoal">保存目标</button>
  35. </view>
  36. <view class="section" v-else>
  37. <view class="section-title">当前目标</view>
  38. <view class="goal-info">
  39. <view class="info-row">
  40. <text class="info-label">起始体重</text>
  41. <text class="info-value">{{ activeGoal.startWeight }} kg</text>
  42. </view>
  43. <view class="info-row">
  44. <text class="info-label">目标体重</text>
  45. <text class="info-value">{{ activeGoal.targetWeight }} kg</text>
  46. </view>
  47. <view class="info-row" v-if="activeGoal.targetBodyFat">
  48. <text class="info-label">目标体脂率</text>
  49. <text class="info-value">{{ activeGoal.targetBodyFat }} %</text>
  50. </view>
  51. <view class="info-row">
  52. <text class="info-label">开始日期</text>
  53. <text class="info-value">{{ formatDate(activeGoal.startDate) }}</text>
  54. </view>
  55. <view class="info-row" v-if="activeGoal.targetDate">
  56. <text class="info-label">目标日期</text>
  57. <text class="info-value">{{ formatDate(activeGoal.targetDate) }}</text>
  58. </view>
  59. </view>
  60. <view class="btn-group">
  61. <button class="btn" size="mini" @click="complete">完成目标</button>
  62. <button class="btn btn-abandon" size="mini" @click="abandon">放弃目标</button>
  63. </view>
  64. </view>
  65. </view>
  66. </template>
  67. <script>
  68. import { getActiveGoal, createGoal, completeGoal, abandonGoal } from '../../utils/api.js'
  69. import { today, formatDate } from '../../utils/format.js'
  70. export default {
  71. data() {
  72. return {
  73. activeGoal: null,
  74. goal: {
  75. startWeight: '',
  76. targetWeight: '',
  77. targetBodyFat: '',
  78. startDate: today(),
  79. targetDate: today()
  80. }
  81. }
  82. },
  83. onShow() {
  84. this.loadGoal()
  85. },
  86. methods: {
  87. formatDate(date) {
  88. return formatDate(date)
  89. },
  90. loadGoal() {
  91. getActiveGoal().then(res => {
  92. if (res.data) this.activeGoal = res.data
  93. })
  94. },
  95. onStartDateChange(e) {
  96. this.goal.startDate = e.detail.value
  97. },
  98. onTargetDateChange(e) {
  99. this.goal.targetDate = e.detail.value
  100. },
  101. createGoal() {
  102. if (!this.goal.startWeight || !this.goal.targetWeight) {
  103. uni.showToast({ title: '请填写必填项', icon: 'none' })
  104. return
  105. }
  106. var data = {
  107. startWeight: this.goal.startWeight,
  108. targetWeight: this.goal.targetWeight,
  109. startDate: this.goal.startDate
  110. }
  111. if (this.goal.targetBodyFat) data.targetBodyFat = this.goal.targetBodyFat
  112. if (this.goal.targetDate) data.targetDate = this.goal.targetDate
  113. createGoal(data).then(() => {
  114. uni.showToast({ title: '保存成功', icon: 'success' })
  115. this.loadGoal()
  116. })
  117. },
  118. complete() {
  119. uni.showModal({
  120. title: '提示',
  121. content: '确定完成当前目标吗?',
  122. success: (res) => {
  123. if (res.confirm && this.activeGoal) {
  124. completeGoal(this.activeGoal.id).then(() => {
  125. this.loadGoal()
  126. })
  127. }
  128. }
  129. })
  130. },
  131. abandon() {
  132. uni.showModal({
  133. title: '提示',
  134. content: '确定放弃当前目标吗?',
  135. success: (res) => {
  136. if (res.confirm && this.activeGoal) {
  137. abandonGoal(this.activeGoal.id).then(() => {
  138. this.loadGoal()
  139. })
  140. }
  141. }
  142. })
  143. }
  144. }
  145. }
  146. </script>
  147. <style>
  148. .profile-page { padding: 30rpx; }
  149. .header { margin-bottom: 30rpx; }
  150. .title { font-size: 36rpx; font-weight: 600; }
  151. .section { background: #fff; padding: 30rpx; border-radius: 16rpx; margin-bottom: 30rpx; }
  152. .section-title { font-size: 32rpx; font-weight: 600; margin-bottom: 30rpx; }
  153. .form-item { display: flex; align-items: center; padding: 24rpx 0; border-bottom: 1rpx solid #f5f5f5; }
  154. .label { width: 220rpx; color: #333; }
  155. .input { flex: 1; text-align: right; }
  156. .picker { flex: 1; text-align: right; color: #333; }
  157. .submit-btn { background: #F97316; color: #fff; border-radius: 40rpx; margin-top: 30rpx; }
  158. .goal-info { margin-bottom: 30rpx; }
  159. .info-row { display: flex; justify-content: space-between; padding: 20rpx 0; border-bottom: 1rpx solid #f5f5f5; }
  160. .info-label { color: #666; }
  161. .info-value { color: #333; font-weight: 600; }
  162. .btn-group { display: flex; gap: 20rpx; }
  163. .btn { flex: 1; background: #F97316; color: #fff; border-radius: 40rpx; }
  164. .btn-abandon { background: #999; }
  165. </style>