CourseDetailPage.vue 12.7 KB
<template>
  <AppLayout title="课程详情" :rightContent="rightContent">
    <div class="pb-24">
      <!-- Course Header -->
      <div class="bg-gradient-to-b from-red-500 to-red-600 p-4 mb-4 rounded-b-3xl shadow-lg">
        <div class="bg-white/10 backdrop-blur-sm rounded-lg p-3 mb-3 inline-block">
          <div class="text-white font-semibold">{{ course?.subtitle?.split(' ')[0] }}</div>
        </div>
        <h1 class="text-2xl text-white font-bold mb-1">{{ course?.title }}</h1>
        <h2 class="text-lg text-white/90">{{ course?.subtitle }}</h2>
        <div class="mt-4 flex justify-between items-center">
          <div class="text-orange-300 font-bold text-2xl">¥{{ course?.price }}</div>
          <div class="bg-orange-500/30 text-orange-100 text-xs px-3 py-1 rounded-full">
            限时优惠
          </div>
        </div>
        <div class="flex justify-between text-xs text-white/80 mt-3">
          <div>已更新{{ course?.updatedLessons }}期</div>
          <div>{{ course?.subscribers }}人订阅</div>
        </div>
        <div v-if="course?.expireDate" class="text-xs text-white/80 mt-1">
          有效期: {{ course?.expireDate }}
        </div>
      </div>

      <!-- Course Main Content -->
      <div class="px-4">
        <!-- Course Details -->
        <FrostedGlass class="mb-4 p-4 rounded-xl">
          <h3 class="text-lg font-bold text-gray-800 mb-3">本课程介绍</h3>
          <p class="text-gray-700 whitespace-pre-line">
            {{ course?.description }}
          </p>
        </FrostedGlass>

        <!-- Course Image -->
        <div class="mb-6">
          <img
            :src="course?.imageUrl"
            :alt="course?.title"
            class="w-full h-auto rounded-xl shadow-md"
          />
        </div>

        <!-- Tab Navigation -->
        <FrostedGlass class="mb-6 rounded-xl overflow-hidden">
          <div class="border-b border-gray-200">
            <div class="flex">
              <button
                v-for="(item, index) in curriculumItems"
                :key="index"
                @click="activeTab = item.title"
                :class="[
                  'flex-1 py-3 font-medium text-center',
                  activeTab === item.title
                    ? 'text-green-600 border-b-2 border-green-600 bg-green-50/50'
                    : 'text-gray-500'
                ]"
              >
                {{ item.title }}
              </button>
            </div>
          </div>

          <!-- Tab Content -->
          <div class="p-4">
            <div v-if="activeTab === '课程特色'">
              <ul class="list-disc pl-5 space-y-2 text-gray-700">
                <li>小班授课,更多关注</li>
                <li>名师授课,经验丰富</li>
                <li>随堂练习,巩固知识</li>
                <li>及时反馈,调整教学</li>
              </ul>
            </div>

            <div v-if="activeTab === '课程大纲'">
              <div class="space-y-4">
                <div class="border-l-2 border-green-500 pl-3">
                  <h4 class="font-medium text-gray-800">第一章:心态准备</h4>
                  <p class="text-sm text-gray-600 mt-1">45分钟 · 3个小节</p>
                </div>
                <div class="border-l-2 border-gray-300 pl-3">
                  <h4 class="font-medium text-gray-800">第二章:考前减压</h4>
                  <p class="text-sm text-gray-600 mt-1">60分钟 · 4个小节</p>
                </div>
                <div class="border-l-2 border-gray-300 pl-3">
                  <h4 class="font-medium text-gray-800">第三章:家庭支持</h4>
                  <p class="text-sm text-gray-600 mt-1">50分钟 · 3个小节</p>
                </div>
              </div>
            </div>

            <div v-if="activeTab === '课程亮点'">
              <div class="space-y-3 text-gray-700">
                <p>✓ 专业的心理辅导</p>
                <p>✓ 系统化的学习方法</p>
                <p>✓ 实用的家庭沟通技巧</p>
                <p>✓ 定制的减压活动推荐</p>
              </div>
            </div>

            <div v-if="activeTab === '学习目标'">
              <div class="space-y-3 text-gray-700">
                <p>1. 帮助家长理解考前压力来源</p>
                <p>2. 掌握有效的情绪管理技巧</p>
                <p>3. 建立积极的家庭支持系统</p>
                <p>4. 培养考前良好的心态和信心</p>
              </div>
            </div>
          </div>
        </FrostedGlass>

        <!-- Teacher Introduction -->
        <FrostedGlass class="mb-6 p-4 rounded-xl">
          <h3 class="text-lg font-bold text-gray-800 mb-3">主讲老师</h3>
          <div class="flex items-center">
            <div class="w-16 h-16 rounded-full overflow-hidden mr-4">
              <img
                src="https://cdn.ipadbiz.cn/mlaj/images/teacher-avatar.jpg"
                alt="Teacher"
                class="w-full h-full object-cover"
                @error="handleImageError"
              />
            </div>
            <div>
              <h4 class="font-bold text-gray-900">张明睿</h4>
              <p class="text-sm text-gray-600">教育心理学博士</p>
              <p class="text-xs text-gray-500 mt-1">10年家庭教育培训经验</p>
            </div>
          </div>
        </FrostedGlass>

        <!-- Student Reviews -->
        <FrostedGlass class="mb-6 p-4 rounded-xl">
          <h3 class="text-lg font-bold text-gray-800 mb-3">学员评价</h3>
          <div class="flex items-center mb-3">
            <div class="flex text-yellow-400 mr-2">
              <svg
                v-for="star in 5"
                :key="star"
                xmlns="http://www.w3.org/2000/svg"
                class="h-5 w-5"
                viewBox="0 0 20 20"
                fill="currentColor"
              >
                <path
                  d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"
                />
              </svg>
            </div>
            <div class="text-gray-700">4.9 (126条评论)</div>
          </div>

          <div class="space-y-4">
            <div class="border-b border-gray-100 pb-3">
              <div class="flex justify-between">
                <div class="font-medium text-gray-800">王小明</div>
                <div class="text-xs text-gray-500">2024-06-15</div>
              </div>
              <p class="text-sm text-gray-600 mt-1">
                课程内容非常实用,老师讲解清晰,帮助我和孩子度过了考前紧张期。
              </p>
            </div>

            <div class="border-b border-gray-100 pb-3">
              <div class="flex justify-between">
                <div class="font-medium text-gray-800">李晓华</div>
                <div class="text-xs text-gray-500">2024-06-10</div>
              </div>
              <p class="text-sm text-gray-600 mt-1">
                老师提供的减压方法很有效,孩子学习状态明显改善,感谢这个课程!
              </p>
            </div>
          </div>

          <button
            @click="router.push(`/courses/${course?.id}/reviews`)"
            class="w-full text-center text-green-600 mt-3 text-sm"
          >
            查看全部评价
          </button>
        </FrostedGlass>
      </div>

      <!-- Bottom Action Bar -->
      <div class="fixed bottom-16 left-0 right-0 bg-white shadow-lg p-3 flex justify-between items-center">
        <div class="flex space-x-4">
          <!-- <button class="flex flex-col items-center text-gray-500 text-xs">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              class="h-6 w-6"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
              />
            </svg>
            咨询
          </button> -->
          <!-- <button class="flex flex-col items-center text-gray-500 text-xs">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              class="h-6 w-6"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"
              />
            </svg>
            分享
          </button> -->
          <button class="flex flex-col items-center text-gray-500 text-xs" @click="toggleFavorite">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              class="h-6 w-6"
              :fill="isFavorite ? 'red' : 'none'"
              viewBox="0 0 24 24"
              :stroke="isFavorite ? 'red' : 'currentColor'"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
              />
            </svg>
            收藏
          </button>
        </div>
        <div class="flex items-center">
          <div class="mr-2">
            <div class="text-red-500 font-bold">¥{{ course?.price }}</div>
            <div class="text-xs text-gray-400 line-through">
              ¥{{ Math.round(course?.price * 1.2) }}
            </div>
          </div>
          <button
            @click="handlePurchase"
            class="bg-gradient-to-r from-green-500 to-green-600 text-white px-6 py-2 rounded-full text-sm font-medium shadow-md"
          >
            立即购买
          </button>
        </div>
      </div>
    </div>
  </AppLayout>
</template>

<script setup lang="jsx">
import { ref, onMounted, defineComponent, h } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import AppLayout from '@/components/layout/AppLayout.vue'
import FrostedGlass from '@/components/ui/FrostedGlass.vue'
import { courses } from '@/utils/mockData'
import { useCart } from '@/contexts/cart'
import { useTitle } from '@vueuse/core';
const $route = useRoute();
const $router = useRouter();
useTitle($route.meta.title);
const route = useRoute()
const router = useRouter()
const course = ref(null)
const activeTab = ref('课程特色')
const isFavorite = ref(false)
const { addToCart, proceedToCheckout } = useCart()

// Handle favorite toggle
const toggleFavorite = () => {
  isFavorite.value = !isFavorite.value
  // TODO: 后续对接收藏接口
}

// Curriculum items
const curriculumItems = [
  { title: '课程特色', active: true },
  { title: '课程大纲', active: false },
  { title: '课程亮点', active: false },
  { title: '学习目标', active: false },
]

// Handle image error
const handleImageError = (e) => {
  e.target.src = 'https://via.placeholder.com/150?text=Teacher'
}

// Right content component
const RightContent = defineComponent({
  setup() {
    return () => (
      <button class="p-2">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          class="h-6 w-6 text-gray-700"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"
          />
        </svg>
      </button>
    )
  },
})

const rightContent = h(RightContent)

// Handle purchase
const handlePurchase = () => {
  if (course.value) {
    addToCart({
      id: course.value.id,
      type: 'course',
      title: course.value.title,
      price: course.value.price,
      imageUrl: course.value.imageUrl
    })
    proceedToCheckout()
  }
}

// Fetch course data
onMounted(() => {
  const id = route.params.id
  const foundCourse = courses.find(c => c.id === id)
  if (foundCourse) {
    course.value = foundCourse
  } else {
    // Course not found, redirect to courses page
    router.push('/courses')
  }
})
</script>