hookehuyr

feat(课程详情页): 重构课程详情页布局和交互逻辑

- 将课程介绍移至标签页并设为默认标签
- 新增主讲教师标签页展示讲师信息
- 优化课程大纲交互,增加点击跳转功能
- 调整底部操作按钮逻辑,区分购买和查看课程状态
- 移除冗余代码,简化页面结构
<template>
<AppLayout :rightContent="rightContent" :has-title="false">
<div class="pb-24">
<div class="pb-24 mb-6">
<!-- Course Image -->
<div class="mb-4">
<img :src="course?.cover || 'https://cdn.ipadbiz.cn/mlaj/images/default_block.png'" :alt="course?.title"
......@@ -34,10 +34,10 @@
<!-- Course Main Content -->
<div class="px-4">
<!-- Course Details -->
<FrostedGlass class="mb-4 p-4 rounded-xl" v-if="course?.introduce">
<!-- <FrostedGlass class="mb-4 p-4 rounded-xl" v-if="course?.introduce">
<h3 class="text-lg font-bold text-gray-800 mb-3">本课程介绍</h3>
<p v-html="course?.introduce" class="text-gray-700 whitespace-pre-line"></p>
</FrostedGlass>
</FrostedGlass> -->
<!-- Tab Navigation -->
<FrostedGlass class="mb-6 rounded-xl overflow-hidden">
......@@ -56,13 +56,31 @@
<!-- Tab Content -->
<div class="p-4">
<div v-if="activeTab === '课程特色'">
<!-- <div v-if="activeTab === '课程特色'">
<div v-html="course?.feature"></div>
</div> -->
<div v-if="activeTab === '课程介绍'">
<p v-html="course?.introduce" class="text-gray-700 whitespace-pre-line"></p>
</div>
<div v-if="activeTab === '主讲教师'">
<div v-for="(item, index) in lecturers" :key="index" class="flex items-center" style="margin-bottom: 1rem;">
<div class="w-16 h-16 rounded-full overflow-hidden mr-4">
<img :src="item?.photo || 'https://cdn.ipadbiz.cn/mlaj/images/default_block.png'" alt="lecturer"
class="w-full h-full object-cover" @error="handleImageError" />
</div>
<div>
<h4 class="font-bold text-gray-900">{{ item?.name }}</h4>
<p class="text-sm text-gray-600">{{ item?.educational }}</p>
<p class="text-xs text-gray-500 mt-1">{{ item?.introduce }}</p>
</div>
</div>
</div>
<div v-if="activeTab === '课程大纲'">
<div class="space-y-4">
<div v-for="(item, index) in displayedSchedule" :key="index" class="border-l-2 border-green-500 pl-3">
<div v-for="(item, index) in displayedSchedule" :key="index" class="border-l-2 border-green-500 pl-3" @click="goToStudyDetail(item)">
<h4 class="font-medium text-gray-800">{{ item.title }}</h4>
<p class="text-sm text-gray-600 mt-1">{{ item.duration }}分钟 · {{ item.schedule_time }}个小节</p>
</div>
......@@ -76,22 +94,22 @@
</div>
</div>
<div v-if="activeTab === '课程亮点'">
<!-- <div v-if="activeTab === '课程亮点'">
<div class="space-y-3 text-gray-700">
<div v-html="course?.highlights"></div>
</div>
</div>
</div> -->
<div v-if="activeTab === '学习目标'">
<!-- <div v-if="activeTab === '学习目标'">
<div class="space-y-3 text-gray-700">
<div v-html="course?.learning_goal"></div>
</div>
</div>
</div> -->
</div>
</FrostedGlass>
<!-- lecturers Introduction -->
<FrostedGlass class="mb-6 p-4 rounded-xl" v-if="lecturers.length">
<!-- <FrostedGlass class="mb-6 p-4 rounded-xl" v-if="lecturers.length">
<h3 class="text-lg font-bold text-gray-800 mb-3">主讲老师</h3>
<div v-for="(item, index) in lecturers" :key="index" class="flex items-center" style="margin-bottom: 1rem;">
<div class="w-16 h-16 rounded-full overflow-hidden mr-4">
......@@ -104,11 +122,25 @@
<p class="text-xs text-gray-500 mt-1">{{ item?.introduce }}</p>
</div>
</div>
</FrostedGlass>
</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 justify-between items-center mb-3">
<h3 class="text-lg font-bold text-gray-800">学员评价</h3>
<!-- 立即评论按钮 - 仅在已购买但未评价时显示 -->
<van-button
v-if="isPurchased && !isReviewed"
@click="showReviewPopup = true"
size="small"
round
color="linear-gradient(to right, #3b82f6, #2563eb)"
class="shadow-sm text-xs px-4 py-1.5 min-w-[80px] hover:shadow-md transition-all duration-200"
>
<van-icon name="edit" size="12" class="mr-1" />
立即评论
</van-button>
</div>
<div class="flex items-center mb-3">
<div class="flex items-center mr-2">
<van-rate v-model="commentScore" readonly allow-half color="#facc15" void-color="#e5e7eb" size="20" />
......@@ -182,7 +214,7 @@
</button>
</div>
<div class="flex items-center">
<div class="mr-2">
<div v-if="!course?.is_buy" class="mr-2">
<div class="text-red-500 font-bold">¥{{ course?.price || 0 }}</div>
<div class="text-xs text-gray-400 line-through">
¥{{ Math.round((course?.price || 0) * 1.2) }}
......@@ -192,13 +224,9 @@
color="linear-gradient(to right, #22c55e, #16a34a)" class="shadow-md">
{{ course?.price !== '0.00' ? '立即' : '免费' }}购买
</van-button>
<van-button v-else-if="!isReviewed" @click="showReviewPopup = true" round block
color="linear-gradient(to right, #3b82f6, #2563eb)" class="shadow-md">
立即评论
</van-button>
<van-button v-else @click="router.push(`/courses/${course?.id}/reviews`)" round block
color="linear-gradient(to right, #6b7280, #4b5563)" class="shadow-md">
查看评论
<van-button v-else @click="router.push(`/studyCourse/${course?.id}`)" round block
color="linear-gradient(to right, #22c55e, #16a34a)" class="shadow-md">
查看课程
</van-button>
</div>
</div>
......@@ -235,7 +263,7 @@ const { currentUser } = useAuth()
const course = ref(null)
const lecturers = ref([])
const activeTab = ref('课程特色')
const activeTab = ref('课程介绍')
// 是否收藏状态
const isFavorite = ref(false)
// 是否已购买状态
......@@ -273,10 +301,11 @@ const curriculumItems = computed(() => {
if (!course.value) return [];
return [
{ title: '课程特色', active: activeTab.value === '课程特色', show: !!course.value.feature },
{ title: '课程介绍', active: activeTab.value === '课程介绍', show: !!course.value.introduce },
{ title: '主讲教师', active: activeTab.value === '主讲教师', show: !!(lecturers.value && lecturers.value.length > 0) },
{ title: '课程大纲', active: activeTab.value === '课程大纲', show: !!(course.value.schedule && course.value.schedule.length > 0) },
{ title: '课程亮点', active: activeTab.value === '课程亮点', show: !!course.value.highlights },
{ title: '学习目标', active: activeTab.value === '学习目标', show: !!course.value.learning_goal },
// { title: '课程亮点', active: activeTab.value === '课程亮点', show: !!course.value.highlights },
// { title: '学习目标', active: activeTab.value === '学习目标', show: !!course.value.learning_goal },
].filter(item => item.show);
});
......@@ -409,6 +438,17 @@ const displayedSchedule = computed(() => {
const toggleSchedule = () => {
isScheduleExpanded.value = !isScheduleExpanded.value
}
// 跳转课程大纲
const goToStudyDetail = (item) => {
console.warn(course.value);
// 如果没有购买过, 禁止操作
if (!course.value.is_buy) {
return;
}
// 跳转详情
router.push(`/studyDetail/${item.id}`)
}
</script>
<style scoped>
......