871 lines
22 KiB
Vue
871 lines
22 KiB
Vue
<template>
|
||
<div class="teacher-course-detail">
|
||
<!-- 顶部图片 -->
|
||
<div class="top-image-container" v-if="showTopImage">
|
||
<img src="/images/teacher/顶部.png" alt="顶部图片" class="top-image">
|
||
<button class="close-button" @click="handleClose">关闭</button>
|
||
</div>
|
||
|
||
<!-- 顶部导航 -->
|
||
<div class="top-navigation">
|
||
<n-button text @click="goBack" class="back-button">
|
||
返回
|
||
</n-button>
|
||
</div>
|
||
|
||
<!-- 主要内容区域 -->
|
||
<div class="main-content">
|
||
<!-- 加载状态 -->
|
||
<div v-if="loading" class="loading-container">
|
||
<div class="loading-content">
|
||
<p>正在加载课程详情...</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 错误状态 -->
|
||
<div v-else-if="error" class="error-container">
|
||
<div class="error-content">
|
||
<p>{{ error }}</p>
|
||
<button @click="loadCourseDetail" class="retry-btn">重试</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 课程内容 -->
|
||
<template v-else>
|
||
<!-- 左侧课程图片 -->
|
||
<div class="course-image-section">
|
||
<img :src="courseInfo.thumbnail || '/images/teacher/fj.png'" :alt="courseInfo.title" class="course-image" />
|
||
</div>
|
||
|
||
<!-- 右侧课程信息 -->
|
||
<div class="course-info-section">
|
||
<h1 class="course-title">{{ courseInfo.title }}</h1>
|
||
<div class="course-description" v-html="cleanHtmlContent(courseInfo.description)"></div>
|
||
|
||
<!-- 课程关键信息 -->
|
||
<div class="course-metrics">
|
||
<div class="metric-item">
|
||
<span class="metric-label">课程时间:</span>
|
||
<span class="metric-value">{{ courseInfo.courseTime }}</span>
|
||
</div>
|
||
<div class="metric-item">
|
||
<span class="metric-label">课程分类:</span>
|
||
<span class="metric-value">{{ courseInfo.category }}</span>
|
||
</div>
|
||
<div class="metric-item">
|
||
<span class="metric-label">课时:</span>
|
||
<span class="metric-value">{{ courseInfo.duration }}</span>
|
||
</div>
|
||
<div class="metric-item">
|
||
<span class="metric-label">课程讲师:</span>
|
||
<span class="metric-value">
|
||
<span v-if="instructorsLoading">加载中...</span>
|
||
<span v-else>{{ courseInfo.instructor }}</span>
|
||
</span>
|
||
</div>
|
||
<div class="metric-item">
|
||
<span class="metric-label">教师团队:</span>
|
||
<span class="metric-value">
|
||
<span v-if="instructorsLoading">加载中...</span>
|
||
<span v-else>{{ courseInfo.teacherCount }}人</span>
|
||
</span>
|
||
</div>
|
||
<div class="metric-item">
|
||
<span class="metric-label">课程积分:</span>
|
||
<span class="metric-value">{{ courseInfo.credits }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 开课学期选择 -->
|
||
<div class="semester-section">
|
||
<span class="semester-label">开课1学期</span>
|
||
<n-select v-model:value="selectedSemester" :options="semesterOptions" class="semester-select"
|
||
size="small" />
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
|
||
<!-- 底部统计数据 -->
|
||
<div class="bottom-stats-section">
|
||
<div class="stats-container">
|
||
<div class="stat-item">
|
||
<div class="stat-label">累计课程浏览量</div>
|
||
<div class="stat-value">{{ courseStats.views }}人</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-label">累计报名人数</div>
|
||
<div class="stat-value">{{ courseStats.enrollments }}人</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-label">累计章节学习人数</div>
|
||
<div class="stat-value">{{ courseStats.learners }}人</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-label">累计互动评论人数</div>
|
||
<div class="stat-value">{{ courseStats.comments }}人</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 分割线 -->
|
||
<div class="divider"></div>
|
||
|
||
<!-- 进入课程按钮 -->
|
||
<div class="action-section">
|
||
<n-button type="primary" size="large" class="enter-course-btn">
|
||
进入课程
|
||
</n-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 课程标签页 -->
|
||
<div class="course-tabs">
|
||
<div class="tab-nav">
|
||
<button class="tab-btn" :class="{ active: activeTab === 'intro' }" @click="activeTab = 'intro'">课程介绍</button>
|
||
<button class="tab-btn" :class="{ active: activeTab === 'team' }" @click="activeTab = 'team'">教学团队</button>
|
||
<button class="tab-btn" :class="{ active: activeTab === 'chapters' }"
|
||
@click="activeTab = 'chapters'">章节目录</button>
|
||
<button class="tab-btn" :class="{ active: activeTab === 'comments' }"
|
||
@click="activeTab = 'comments'">评论</button>
|
||
</div>
|
||
|
||
<!-- 标签页内容区域 -->
|
||
<div class="tab-content">
|
||
<transition name="tab-fade" mode="out-in">
|
||
<!-- 课程介绍内容 -->
|
||
<div v-if="activeTab === 'intro'" key="intro" class="tab-pane">
|
||
<CourseIntro />
|
||
</div>
|
||
|
||
<!-- 教学团队内容 -->
|
||
<div v-else-if="activeTab === 'team'" key="team" class="tab-pane">
|
||
<TeachingTeam />
|
||
</div>
|
||
|
||
<!-- 章节目录内容 -->
|
||
<div v-else-if="activeTab === 'chapters'" key="chapters" class="tab-pane">
|
||
<ChapterList />
|
||
</div>
|
||
|
||
<!-- 评论内容 -->
|
||
<div v-else-if="activeTab === 'comments'" key="comments" class="tab-pane">
|
||
<CourseComments />
|
||
</div>
|
||
</transition>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, onMounted } from 'vue'
|
||
import { useRouter, useRoute } from 'vue-router'
|
||
import { NButton, NSelect } from 'naive-ui'
|
||
import { CourseApi } from '@/api/modules/course'
|
||
import { TeachCourseApi } from '@/api/modules/teachCourse'
|
||
import CourseIntro from './tabs/CourseIntro.vue'
|
||
import TeachingTeam from './tabs/TeachingTeam.vue'
|
||
import ChapterList from './tabs/ChapterList.vue'
|
||
import CourseComments from './tabs/CourseComments.vue'
|
||
|
||
const router = useRouter()
|
||
const route = useRoute()
|
||
const courseId = ref(route.params.id as string)
|
||
|
||
// 顶部图片控制
|
||
const showTopImage = ref(false) // 控制顶部图片显示/隐藏
|
||
|
||
// 课程信息
|
||
const courseInfo = ref({
|
||
title: '课程名称课程名称课',
|
||
description: '本课程旨在带领学生系统地学习【课程核心领域】的知识。我们将从【最基础的概念】讲起,逐步深入到【高级主题或应用】。通过理论与实践相结合的方式,学生不仅能够掌握【具体的理论知识】,还能获得【具体的实践技能,如解决XX问题、开发XX应用等】。',
|
||
courseTime: '2025-08-25-2026.08-25',
|
||
category: '分类名称',
|
||
duration: '4小时28分钟',
|
||
instructor: '王建国',
|
||
teacherCount: 1,
|
||
credits: 60,
|
||
thumbnail: '/images/teacher/fj.png'
|
||
})
|
||
|
||
// 课程数据状态
|
||
const loading = ref(false)
|
||
const error = ref('')
|
||
|
||
// 教师团队数据
|
||
const instructors = ref<any[]>([])
|
||
const instructorsLoading = ref(false)
|
||
|
||
// 课程统计数据
|
||
const courseStats = ref({
|
||
views: 0,
|
||
enrollments: 0,
|
||
learners: 0,
|
||
comments: 0
|
||
})
|
||
|
||
// 学期选择
|
||
const selectedSemester = ref('2025-2026-1')
|
||
const semesterOptions = [
|
||
{ label: '2025-2026第一学期', value: '2025-2026-1' },
|
||
{ label: '2025-2026第二学期', value: '2025-2026-2' }
|
||
]
|
||
|
||
// 标签页状态
|
||
const activeTab = ref('intro')
|
||
|
||
// 方法
|
||
const goBack = () => {
|
||
if (window.history.length > 1) {
|
||
router.go(-1)
|
||
} else {
|
||
router.push('/teacher/course-management')
|
||
}
|
||
}
|
||
|
||
const handleClose = () => {
|
||
showTopImage.value = false // 隐藏顶部图片容器
|
||
}
|
||
|
||
// 加载课程详情
|
||
const loadCourseDetail = async () => {
|
||
console.log('🚀 开始加载教师课程详情,课程ID:', courseId.value)
|
||
|
||
if (!courseId.value || courseId.value.trim() === '') {
|
||
error.value = '课程ID无效'
|
||
console.error('❌ 课程ID无效:', courseId.value)
|
||
return
|
||
}
|
||
|
||
try {
|
||
loading.value = true
|
||
error.value = ''
|
||
|
||
console.log('📡 调用课程详情API...')
|
||
const response = await CourseApi.getCourseDetail(courseId.value)
|
||
console.log('📊 课程详情API响应:', response)
|
||
|
||
if (response.code === 0 || response.code === 200) {
|
||
const course = response.data
|
||
console.log('✅ 课程数据设置成功:', course)
|
||
console.log('📋 课程基本信息:', {
|
||
id: course?.id,
|
||
title: course?.title,
|
||
description: course?.description,
|
||
thumbnail: course?.thumbnail,
|
||
category: course?.category,
|
||
instructor: course?.instructor,
|
||
duration: course?.duration,
|
||
studentsCount: course?.studentsCount,
|
||
createdAt: course?.createdAt,
|
||
updatedAt: course?.updatedAt
|
||
})
|
||
|
||
// 更新课程信息
|
||
courseInfo.value = {
|
||
title: course?.title || '课程名称课程名称课',
|
||
description: course?.description || '本课程旨在带领学生系统地学习【课程核心领域】的知识。我们将从【最基础的概念】讲起,逐步深入到【高级主题或应用】。通过理论与实践相结合的方式,学生不仅能够掌握【具体的理论知识】,还能获得【具体的实践技能,如解决XX问题、开发XX应用等】。',
|
||
courseTime: formatCourseTime(course?.createdAt, course?.updatedAt),
|
||
category: course?.category?.name || '分类名称',
|
||
duration: course?.duration || '4小时28分钟',
|
||
instructor: course?.instructor?.name || '王建国',
|
||
teacherCount: 1, // 暂时固定为1
|
||
credits: 60, // 暂时固定为60
|
||
thumbnail: course?.thumbnail || '/images/teacher/fj.png'
|
||
}
|
||
|
||
// 尝试从课程管理API获取分类信息
|
||
await loadCourseCategoryFromManagementAPI()
|
||
|
||
// 更新统计数据(这里可以根据实际API调整)
|
||
courseStats.value = {
|
||
views: course?.studentsCount || 0,
|
||
enrollments: course?.studentsCount || 0,
|
||
learners: Math.floor((course?.studentsCount || 0) * 0.8),
|
||
comments: Math.floor((course?.studentsCount || 0) * 0.3)
|
||
}
|
||
|
||
console.log('🎯 课程信息更新完成:', courseInfo.value)
|
||
console.log('📈 统计数据更新完成:', courseStats.value)
|
||
} else {
|
||
error.value = response.message || '获取课程详情失败'
|
||
console.error('❌ API返回错误:', response)
|
||
}
|
||
} catch (err) {
|
||
console.error('❌ 加载课程详情失败:', err)
|
||
error.value = '网络错误,请稍后重试'
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 加载教师团队信息
|
||
const loadCourseInstructors = async () => {
|
||
console.log('👥 开始加载课程教师团队,课程ID:', courseId.value)
|
||
|
||
if (!courseId.value || courseId.value.trim() === '') {
|
||
console.error('❌ 课程ID无效,无法加载教师团队')
|
||
return
|
||
}
|
||
|
||
try {
|
||
instructorsLoading.value = true
|
||
console.log('📡 调用教师团队API...')
|
||
|
||
const response = await CourseApi.getCourseInstructors(courseId.value)
|
||
console.log('📊 教师团队API响应:', response)
|
||
|
||
if (response.code === 0 || response.code === 200) {
|
||
instructors.value = response.data || []
|
||
console.log('✅ 教师团队数据设置成功:', instructors.value)
|
||
console.log('👥 教师团队数量:', instructors.value.length)
|
||
|
||
// 更新课程信息中的教师团队人数
|
||
courseInfo.value.teacherCount = instructors.value.length
|
||
console.log('🎯 更新教师团队人数:', courseInfo.value.teacherCount)
|
||
|
||
// 从教师团队中获取所有教师名字(按sortOrder排序)
|
||
if (instructors.value.length > 0) {
|
||
// 按sortOrder排序,如果没有sortOrder则按原始顺序
|
||
const sortedInstructors = [...instructors.value].sort((a, b) => {
|
||
const aOrder = a.sortOrder || 0
|
||
const bOrder = b.sortOrder || 0
|
||
return aOrder - bOrder
|
||
})
|
||
// 将所有教师名字用逗号连接
|
||
const allInstructorNames = sortedInstructors.map(teacher => teacher.name).join('、')
|
||
courseInfo.value.instructor = allInstructorNames || '王建国'
|
||
console.log('👨🏫 更新所有教师:', courseInfo.value.instructor)
|
||
console.log('📋 教师团队排序:', sortedInstructors.map(t => ({ name: t.name, sortOrder: t.sortOrder })))
|
||
}
|
||
} else {
|
||
console.warn('⚠️ 教师团队API返回错误:', response)
|
||
// 保持默认值
|
||
courseInfo.value.teacherCount = 1
|
||
}
|
||
} catch (err) {
|
||
console.error('❌ 加载教师团队失败:', err)
|
||
// 保持默认值
|
||
courseInfo.value.teacherCount = 1
|
||
} finally {
|
||
instructorsLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 格式化课程时间
|
||
const formatCourseTime = (createdAt?: string, updatedAt?: string) => {
|
||
if (createdAt && updatedAt) {
|
||
const startDate = new Date(createdAt).toLocaleDateString('zh-CN')
|
||
const endDate = new Date(updatedAt).toLocaleDateString('zh-CN')
|
||
return `${startDate}-${endDate}`
|
||
}
|
||
return '2025-08-25-2026.08-25'
|
||
}
|
||
|
||
// 清理HTML内容,确保安全显示
|
||
const cleanHtmlContent = (content: string) => {
|
||
if (!content) return ''
|
||
|
||
// 如果内容包含HTML标签,直接返回(假设后端已经处理过安全性)
|
||
// 这里可以添加更多的HTML清理逻辑,比如移除script标签等
|
||
return content
|
||
}
|
||
|
||
// 从课程管理API获取分类信息
|
||
const loadCourseCategoryFromManagementAPI = async () => {
|
||
try {
|
||
// 调用课程管理API获取课程信息(包含categoryId)
|
||
const response = await TeachCourseApi.getTeacherCourseList({})
|
||
|
||
if (response.data && response.data.result && response.data.result.length > 0) {
|
||
// 从所有课程中找到匹配当前课程ID的课程
|
||
const courseData = response.data.result.find(course => course.id === courseId.value)
|
||
|
||
if (!courseData) {
|
||
// 备选方案:直接获取分类列表,显示第一个分类作为示例
|
||
try {
|
||
const categoryResponse = await CourseApi.getCategories()
|
||
if (categoryResponse.code === 200 && categoryResponse.data && categoryResponse.data.length > 0) {
|
||
const firstCategory = categoryResponse.data[0]
|
||
courseInfo.value.category = firstCategory.name
|
||
}
|
||
} catch (error) {
|
||
console.error('❌ 备选方案失败:', error)
|
||
}
|
||
return
|
||
}
|
||
|
||
if (courseData.categoryId) {
|
||
// 获取分类列表
|
||
const categoryResponse = await CourseApi.getCategories()
|
||
|
||
if (categoryResponse.code === 200 && categoryResponse.data) {
|
||
// 解析categoryId(可能是逗号分隔的字符串)
|
||
const categoryIds = courseData.categoryId.toString().split(',').map((id: string) => parseInt(id.trim())).filter((id: number) => !isNaN(id))
|
||
|
||
// 根据ID匹配分类名称
|
||
const categoryNames = categoryIds.map((id: number) => {
|
||
const category = categoryResponse.data.find(cat => cat.id === id)
|
||
return category ? category.name : `未知分类${id}`
|
||
}).filter(Boolean)
|
||
|
||
// 更新课程信息中的分类
|
||
if (categoryNames.length > 0) {
|
||
courseInfo.value.category = categoryNames.join('、')
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('❌ 获取分类信息失败:', error)
|
||
}
|
||
}
|
||
|
||
// 组件挂载时加载数据
|
||
onMounted(async () => {
|
||
console.log('🎬 教师课程详情页面加载完成,课程ID:', courseId.value)
|
||
|
||
// 并行加载课程详情和教师团队信息
|
||
await Promise.all([
|
||
loadCourseDetail(),
|
||
loadCourseInstructors()
|
||
])
|
||
|
||
console.log('🎉 所有数据加载完成')
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.teacher-course-detail {
|
||
background: #fff;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
/* 顶部图片容器 */
|
||
.top-image-container {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 130px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.top-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
object-fit: cover;
|
||
}
|
||
|
||
/* 关闭按钮样式 */
|
||
.close-button {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 15px;
|
||
width: 30px;
|
||
height: 20px;
|
||
background-color: #7192DC;
|
||
color: white;
|
||
border: none;
|
||
font-size: 10px;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 10;
|
||
transition: background-color 0.3s ease;
|
||
}
|
||
|
||
.close-button:hover {
|
||
background-color: #999999;
|
||
}
|
||
|
||
/* 顶部导航 */
|
||
.top-navigation {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 25px 30px;
|
||
background: #fff;
|
||
border-bottom: 1.5px solid #e6e6e6;
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
.back-button {
|
||
margin-right: 16px;
|
||
color: #333;
|
||
background: #F7F8FA;
|
||
border-radius: 4px;
|
||
padding: 8px 16px;
|
||
font-size: 14px;
|
||
min-width: 74px;
|
||
height: 34px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.back-button:hover {
|
||
color: #0288D1;
|
||
background: #e3f2fd;
|
||
}
|
||
|
||
.page-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
/* 主要内容区域 */
|
||
.main-content {
|
||
display: flex;
|
||
gap: 40px;
|
||
max-width: 1420px;
|
||
margin: 25px auto;
|
||
}
|
||
|
||
/* 加载和错误状态 */
|
||
.loading-container,
|
||
.error-container {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
min-height: 400px;
|
||
text-align: center;
|
||
width: 100%;
|
||
}
|
||
|
||
.loading-content p,
|
||
.error-content p {
|
||
font-size: 16px;
|
||
color: #666;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.retry-btn {
|
||
background: #0C99DA;
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 16px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
transition: background-color 0.3s;
|
||
}
|
||
|
||
.retry-btn:hover {
|
||
background: #0A8BC7;
|
||
}
|
||
/* 左侧课程图片 */
|
||
.course-image-section {
|
||
flex: 0 0 305px;
|
||
}
|
||
|
||
.course-image {
|
||
width: 100%;
|
||
height: 215px;
|
||
object-fit: cover;
|
||
}
|
||
|
||
/* 右侧课程信息 */
|
||
.course-info-section {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 15px;
|
||
}
|
||
|
||
.course-title {
|
||
font-size: 22px;
|
||
font-weight: 500;
|
||
color: #333;
|
||
margin: 0;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.course-description {
|
||
font-size: 14px;
|
||
color: #666;
|
||
line-height: 1.6;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
/* 课程关键信息 */
|
||
.course-metrics {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 12px;
|
||
}
|
||
|
||
.metric-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
|
||
.metric-label {
|
||
font-size: 14px;
|
||
color: #666;
|
||
min-width: 80px;
|
||
}
|
||
|
||
.metric-value {
|
||
font-size: 14px;
|
||
color: #666666;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 开课学期选择 */
|
||
.semester-section {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20px;
|
||
margin-top: 8px;
|
||
}
|
||
|
||
.semester-label {
|
||
font-size: 18px;
|
||
color: #333;
|
||
}
|
||
|
||
.semester-select {
|
||
width: 181px;
|
||
}
|
||
|
||
/* 学期选择器样式 */
|
||
.semester-select :deep(.n-base-selection-label) {
|
||
background-color: #0C99DA !important;
|
||
padding: 4px 4px;
|
||
border: none !important;
|
||
color: white !important;
|
||
font-size: 14px !important;
|
||
width: 181px !important;
|
||
height: 37px !important;
|
||
}
|
||
|
||
.semester-select :deep(.n-base-selection-input__content) {
|
||
color: white !important;
|
||
font-size: 14px !important;
|
||
}
|
||
|
||
.semester-select :deep(.n-base-suffix__arrow) {
|
||
color: white !important;
|
||
}
|
||
|
||
.semester-select :deep(.n-base-suffix__arrow svg) {
|
||
fill: white !important;
|
||
}
|
||
|
||
/* 底部统计数据 */
|
||
.bottom-stats-section {
|
||
background: #F1F3F4;
|
||
width: 1420px;
|
||
margin: 35px auto;
|
||
padding: 15px 55px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.stats-container {
|
||
display: flex;
|
||
gap: 200px;
|
||
}
|
||
|
||
/* 分割线 */
|
||
.divider {
|
||
width: 1px;
|
||
height: 40px;
|
||
background-color: #E0E0E0;
|
||
margin: 0 20px;
|
||
}
|
||
|
||
.stat-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 5px;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 12px;
|
||
color: #999;
|
||
text-align: left;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
color: #333;
|
||
}
|
||
|
||
/* 操作区域 */
|
||
.action-section {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.enter-course-btn {
|
||
width: 136px !important;
|
||
height: 37px !important;
|
||
font-size: 14px !important;
|
||
font-weight: 600 !important;
|
||
border-radius: 2px !important;
|
||
background: #0C99DA !important;
|
||
border: none !important;
|
||
color: #fff !important;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.enter-course-btn:hover {
|
||
background: #0A8BC7 !important;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(12, 153, 218, 0.3);
|
||
}
|
||
|
||
/* 课程标签页 */
|
||
.course-tabs {
|
||
background: #fff;
|
||
margin-top: 40px;
|
||
max-width: 1420px;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
|
||
.tab-nav {
|
||
display: flex;
|
||
justify-content: center;
|
||
border-bottom: 1px solid #E6E6E6;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.tab-btn {
|
||
background: none;
|
||
border: none;
|
||
padding: 12px 0;
|
||
margin-right: 54px;
|
||
font-size: 16px;
|
||
color: #333;
|
||
cursor: pointer;
|
||
position: relative;
|
||
transition: color 0.3s;
|
||
}
|
||
|
||
.tab-btn.active {
|
||
color: #0C99DA;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.tab-btn.active::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: -1px;
|
||
left: 0;
|
||
right: 0;
|
||
height: 3px;
|
||
background: #0C99DA;
|
||
}
|
||
|
||
.tab-btn:hover {
|
||
color: #0C99DA;
|
||
}
|
||
|
||
.tab-content {
|
||
min-height: 300px;
|
||
padding: 0 0 24px 0;
|
||
}
|
||
|
||
/* Tab切换过渡动画 */
|
||
.tab-fade-enter-active,
|
||
.tab-fade-leave-active {
|
||
transition: all 0.1s ease;
|
||
}
|
||
|
||
.tab-fade-enter-from {
|
||
opacity: 0;
|
||
transform: translateX(20px);
|
||
}
|
||
|
||
.tab-fade-leave-to {
|
||
opacity: 0;
|
||
transform: translateX(-20px);
|
||
}
|
||
|
||
.tab-pane {
|
||
animation: fadeIn 0.1s ease;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(10px);
|
||
}
|
||
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.top-image-container {
|
||
height: 100px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.top-image-container {
|
||
height: 80px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 1024px) {
|
||
.main-content {
|
||
flex-direction: column;
|
||
padding: 20px;
|
||
}
|
||
|
||
.course-image-section {
|
||
flex: none;
|
||
}
|
||
|
||
.course-image {
|
||
height: 250px;
|
||
}
|
||
|
||
.bottom-stats-section {
|
||
flex-direction: column;
|
||
gap: 24px;
|
||
padding: 24px 20px;
|
||
}
|
||
|
||
.stats-container {
|
||
gap: 32px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.stats-container {
|
||
flex-wrap: wrap;
|
||
gap: 24px;
|
||
}
|
||
|
||
.stat-item {
|
||
flex: 1;
|
||
min-width: 120px;
|
||
}
|
||
|
||
.course-title {
|
||
font-size: 24px;
|
||
}
|
||
|
||
.course-description {
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
</style>
|