index.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <template>
  2. <view class="container">
  3. <view class="header">
  4. <text class="title">我的计划</text>
  5. </view>
  6. <!-- 计划列表 -->
  7. <view class="plan-list" v-if="plans.length > 0">
  8. <view
  9. class="plan-card"
  10. v-for="plan in plans"
  11. :key="plan.id"
  12. @click="goToDetail(plan.id)"
  13. >
  14. <view class="plan-header">
  15. <text class="plan-name">{{ plan.name }}</text>
  16. <text class="plan-status" :class="plan.status">{{ getStatusText(plan.status) }}</text>
  17. </view>
  18. <view class="plan-progress">
  19. <progress :percent="getProgress(plan)" :stroke-width="8" backgroundColor="#e0e0e0" activeColor="#4CAF50" />
  20. <text class="progress-text">{{ plan.completedDays }} / {{ plan.totalDays }} 天</text>
  21. </view>
  22. <view class="plan-dates">
  23. <text>{{ formatDate(plan.startDate) }} - {{ formatDate(plan.endDate) }}</text>
  24. </view>
  25. <view class="plan-actions" v-if="plan.status === 'active'">
  26. <button class="btn-cancel" @click.stop="cancelPlan(plan.id)">取消</button>
  27. </view>
  28. </view>
  29. </view>
  30. <!-- 空状态 -->
  31. <view class="empty" v-else>
  32. <text class="empty-text">暂无计划,快去应用任务模板吧</text>
  33. <button class="btn-go" @click="goToMarket">去市场</button>
  34. </view>
  35. </view>
  36. </template>
  37. <script>
  38. import { getMyPlans, cancelPlan as cancelPlanApi } from '@/utils/api.js'
  39. export default {
  40. data() {
  41. return {
  42. plans: []
  43. }
  44. },
  45. onShow() {
  46. this.loadPlans()
  47. },
  48. methods: {
  49. async loadPlans() {
  50. try {
  51. const res = await getMyPlans()
  52. this.plans = res.data || []
  53. } catch (e) {
  54. console.error(e)
  55. }
  56. },
  57. getStatusText(status) {
  58. const map = { 'active': '进行中', 'completed': '已完成', 'cancelled': '已取消' }
  59. return map[status] || status
  60. },
  61. getProgress(plan) {
  62. if (!plan.totalDays) return 0
  63. return Math.round(plan.completedDays / plan.totalDays * 100)
  64. },
  65. formatDate(date) {
  66. if (!date) return ''
  67. const d = new Date(date)
  68. return `${d.getMonth() + 1}-${d.getDate()}`
  69. },
  70. goToDetail(id) {
  71. uni.navigateTo({
  72. url: `/pages/parent/plans/detail?id=${id}`
  73. })
  74. },
  75. goToMarket() {
  76. uni.navigateTo({
  77. url: '/pages/parent/market/index'
  78. })
  79. },
  80. async cancelPlan(id) {
  81. uni.showModal({
  82. title: '确认取消',
  83. content: '确定要取消这个计划吗?',
  84. success: async (res) => {
  85. if (res.confirm) {
  86. try {
  87. await cancelPlanApi(id)
  88. uni.showToast({ title: '已取消' })
  89. this.loadPlans()
  90. } catch (e) {
  91. uni.showToast({ title: '取消失败', icon: 'none' })
  92. }
  93. }
  94. }
  95. })
  96. }
  97. }
  98. }
  99. </script>
  100. <style scoped>
  101. .container { min-height: 100vh; background: #f5f5f5; padding: 30rpx; }
  102. .header { margin-bottom: 30rpx; }
  103. .title { font-size: 36rpx; font-weight: bold; color: #333; }
  104. .plan-list { display: flex; flex-direction: column; gap: 20rpx; }
  105. .plan-card { background: #fff; border-radius: 16rpx; padding: 30rpx; box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.05); }
  106. .plan-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20rpx; }
  107. .plan-name { font-size: 32rpx; font-weight: bold; color: #333; }
  108. .plan-status { font-size: 24rpx; padding: 8rpx 16rpx; border-radius: 20rpx; }
  109. .plan-status.active { background: #e8f5e9; color: #4CAF50; }
  110. .plan-status.completed { background: #e3f2fd; color: #2196F3; }
  111. .plan-status.cancelled { background: #f5f5f5; color: #999; }
  112. .plan-progress { display: flex; align-items: center; gap: 16rpx; margin-bottom: 16rpx; }
  113. .plan-progress progress { flex: 1; }
  114. .progress-text { font-size: 24rpx; color: #666; }
  115. .plan-dates { font-size: 24rpx; color: #999; margin-bottom: 16rpx; }
  116. .plan-actions { display: flex; justify-content: flex-end; }
  117. .btn-cancel { background: #f5f5f5; color: #666; font-size: 24rpx; padding: 12rpx 24rpx; border-radius: 24rpx; }
  118. .empty { display: flex; flex-direction: column; align-items: center; padding: 100rpx; }
  119. .empty-text { color: #999; font-size: 28rpx; margin-bottom: 30rpx; }
  120. .btn-go { background: #4CAF50; color: #fff; }
  121. </style>