add-train-popup.vue 5.51 KB
<template>
  <!-- 添加自助训练底部弹窗 -->
  <up-popup
    :show="visible"
    mode="bottom"
    round="24rpx"
    bg-color="#1a1a1a"
    :close-on-click-overlay="true"
    :safe-area-inset-bottom="true"
    @close="close"
  >
    <view class="add-train-popup">
      <!-- 拖拽指示条 -->
      <view class="popup-indicator" />

      <!-- 菜单选项列表 -->
      <view class="popup-menu">
        <!-- 从训练计划中添加 -->
        <view
          v-if="planListCount > 0"
          class="menu-item"
          @click="handleAddFromPlan"
        >
          <view class="menu-icon">
            <up-icon name="file-text-fill" color="#040000" size="24" />
          </view>
          <view class="menu-text">
            <text class="menu-title">从训练计划中添加</text>
            <text class="menu-desc">从我的训练计划中添加</text>
          </view>
        </view>

        <!-- 使用训练模板 -->
        <view class="menu-item" @click="handleAddFromTemplate">
          <view class="menu-icon">
            <up-icon name="grid-fill" color="#040000" size="24" />
          </view>
          <view class="menu-text">
            <text class="menu-title">使用训练模板</text>
            <text class="menu-desc">官方训练模板和自定义模板</text>
          </view>
        </view>

        <!-- 自由训练 -->
        <view class="menu-item" @click="handleFreeTraining">
          <view class="menu-icon">
            <up-icon name="clock-fill" color="#040000" size="24" />
          </view>
          <view class="menu-text">
            <text class="menu-title">自由训练</text>
            <text class="menu-desc">新建空白训练</text>
          </view>
        </view>
      </view>

      <!-- 关闭按钮 -->
      <view class="close-btn" @click="close">
        <up-icon name="close" color="#000" size="22" />
      </view>
    </view>
  </up-popup>

  <!-- 我的计划添加弹窗(放在外部避免弹窗嵌套) -->
  <WodeJihuaTianjiaTancuang
    v-model:visible="showPlanPopup"
    @get-plan-list-length="getPlanListLength"
    :is-add="true"
    :plan-id="lastPlanId"
    :is-my-plan="true"
  />
</template>

<script setup>
import { ref, onMounted, computed } from 'vue'
import WodeJihuaTianjiaTancuang from '@/pages/xunji/components/wode-jihua-tianjia-tancuang.vue'
import QueryPlanApi from '@/sheep/api/plan/queryplan'

// ==================== Props & Emits ====================
const props = defineProps({
  visible: {
    type: Boolean,
    default: false,
  },
})

const emit = defineEmits(['update:visible'])

// ==================== 响应式状态 ====================
const showPlanPopup = ref(false)
const planListCount = ref(0)
const planList = ref([])

// ==================== 计算属性 ====================
/** 获取计划列表最后一条的 id,无数据返回 null */
const lastPlanId = computed(() => {
  if (!Array.isArray(planList.value) || planList.value.length === 0) return null
  return planList.value.at(-1)?.id ?? null
})

// ==================== 方法 ====================
/** 关闭弹窗 */
const close = () => {
  emit('update:visible', false)
}

/** 获取子组件传递的计划列表长度 */
const getPlanListLength = (len) => {
  planListCount.value = len
}

/** 从训练计划中添加:打开计划选择弹窗 */
const handleAddFromPlan = () => {
  showPlanPopup.value = true
}

/** 使用训练模板:跳转模板选择页 */
const handleAddFromTemplate = () => {
  uni.navigateTo({ url: '/pages4/pages/xunji/xunji-rili-tianjia-moban' })
  close()
}

/** 自由训练:跳转动作练习页 */
const handleFreeTraining = () => {
  uni.navigateTo({ url: '/pages4/pages/xunji/xunji-dongzuo-lianxi?isTraining=true' })
  close()
}

/** 获取我的全部训练计划 */
const fetchMyPlanList = async () => {
  try {
    const res = await QueryPlanApi.getMyPlan()
    if (res.code === 0 && res.data) {
      planList.value = res.data
    } else {
      uni.showToast({ title: '获取计划失败', icon: 'none' })
    }
  } catch (err) {
    console.error('获取计划列表报错:', err)
    uni.showToast({ title: '网络异常', icon: 'none' })
  }
}

// ==================== 生命周期 ====================
onMounted(() => {
  fetchMyPlanList()
})
</script>

<style lang="scss" scoped>
.add-train-popup {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 30rpx 40rpx;

  // 顶部拖拽指示条
  .popup-indicator {
    width: 72rpx;
    height: 8rpx;
    border-radius: 4rpx;
    background: rgba(255, 255, 255, 0.3);
    margin: 16rpx 0 32rpx;
  }

  // 菜单选项列表
  .popup-menu {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 16rpx;

    .menu-item {
      display: flex;
      align-items: center;
      gap: 24rpx;
      padding: 24rpx 30rpx;
      border-radius: 16rpx;
    }

    .menu-icon {
      width: 80rpx;
      height: 80rpx;
      border-radius: 50%;
      background: #ffd60a;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
    }

    .menu-text {
      display: flex;
      flex-direction: column;
      gap: 8rpx;

      .menu-title {
        font-size: 32rpx;
        color: #fff;
        font-weight: 500;
      }

      .menu-desc {
        font-size: 26rpx;
        color: rgba(255, 255, 255, 0.7);
      }
    }
  }

  // 底部关闭按钮
  .close-btn {
    margin-top: 60rpx;
    width: 88rpx;
    height: 88rpx;
    border-radius: 50%;
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>