OL-LearnPlatform/src/views/LearningPaths.vue
2025-07-22 20:59:46 +08:00

733 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="learning-paths-page">
<!-- 页面标题区域 -->
<div class="page-header">
<div class="container">
<div class="header-content">
<h1 class="page-title">学习路径</h1>
<p class="page-subtitle">成就卓越的学习之路开启智慧之门</p>
</div>
<div class="header-decoration">
<!-- 装饰图片暂时隐藏 -->
</div>
</div>
</div>
<!-- 主要内容区域 -->
<div class="main-content">
<div class="container">
<div class="content-layout">
<!-- 左侧筛选栏 -->
<div class="filter-sidebar">
<!-- 所有路径标题 - 无背景样式 -->
<h3 class="filter-title">所有路径</h3>
<div class="filter-section">
<div class="filter-options">
<div class="filter-option active" :class="{ active: selectedCategory === 'psychology' }" @click="selectCategory('psychology')">
<span class="option-icon blue-icon"></span>
<span class="option-text">数据心理学</span>
</div>
<div class="filter-option" :class="{ active: selectedCategory === 'ai' }" @click="selectCategory('ai')">
<span class="option-icon gray-icon"></span>
<span class="option-text">AI 时代生存指南从工程师到架构师...</span>
</div>
<div class="filter-option" :class="{ active: selectedCategory === 'english1' }" @click="selectCategory('english1')">
<span class="option-icon gray-icon"></span>
<span class="option-text">新视野英语训练营</span>
</div>
<div class="filter-option" :class="{ active: selectedCategory === 'english2' }" @click="selectCategory('english2')">
<span class="option-icon gray-icon"></span>
<span class="option-text">新视野英语训练营</span>
</div>
<div class="filter-option" :class="{ active: selectedCategory === 'learning' }" @click="selectCategory('learning')">
<span class="option-icon gray-icon"></span>
<span class="option-text">科学学习方法 | 强化记忆</span>
</div>
<div class="filter-option" :class="{ active: selectedCategory === 'health' }" @click="selectCategory('health')">
<span class="option-icon gray-icon"></span>
<span class="option-text">运动与健康</span>
</div>
<div class="filter-option" :class="{ active: selectedCategory === 'education' }" @click="selectCategory('education')">
<span class="option-icon gray-icon"></span>
<span class="option-text">数师教育学科技能体系</span>
</div>
</div>
</div>
</div>
<!-- 右侧内容区域 -->
<div class="content-main">
<!-- 课程标题 - 无背景样式 -->
<h3 class="content-title">课程</h3>
<!-- 统计信息和筛选行 -->
<div class="content-header">
<div class="result-info">
<span class="result-stats"> 34 | 567 课程 | 1243 小时</span>
</div>
<div class="sort-options">
<span class="sort-label">难度等级</span>
<select v-model="sortBy" class="sort-select">
<option value="default">全部</option>
<option value="beginner">初级</option>
<option value="intermediate">中级</option>
<option value="advanced">高级</option>
</select>
</div>
</div>
<!-- 学习路径列表 -->
<div class="paths-list">
<div class="path-card" v-for="path in paginatedPaths" :key="path.id" @click="goToPath(path.id)">
<div class="card-image">
<div class="image-placeholder"></div>
<div class="card-badge">热门</div>
</div>
<div class="card-content">
<h3 class="card-title">{{ path.title }}</h3>
<div class="card-meta">
<span class="meta-item">{{ path.level }}</span>
<span class="meta-item">{{ path.duration }}</span>
<span class="meta-item">免费</span>
</div>
<p class="card-description">{{ path.description }}</p>
<div class="card-footer">
<div class="card-stats">
<span class="stat-item">{{ path.studentsCount }}人学习</span>
<span class="stat-item">{{ path.lessonsCount }}个课程</span>
</div>
<div class="card-rating">
<span class="rating-icon">👍</span>
<span class="rating-text">5.0</span>
</div>
</div>
</div>
</div>
</div>
<!-- 分页 -->
<div class="pagination">
<button class="page-btn" :disabled="currentPage === 1" @click="goToPage(currentPage - 1)">
上一页
</button>
<button
class="page-btn"
:class="{ active: page === currentPage }"
v-for="page in visiblePages"
:key="page"
@click="goToPage(page)"
>
{{ page }}
</button>
<button class="page-btn" :disabled="currentPage === totalPages" @click="goToPage(currentPage + 1)">
下一页
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
// 筛选状态
const selectedCategory = ref('psychology')
const sortBy = ref('default')
// 分页状态
const currentPage = ref(1)
const pageSize = 8
// 学习路径数据
const learningPaths = ref([
{
id: 1,
title: '数据心理学的起源',
description: '本课程深度解析,让您一次性掌握数据分析的心理学基础。适合希望从心理学角度理解数据的学习者。这是一门综合性的课程,涵盖了数据分析的各个方面。通过本课程的学习,您将能够掌握数据分析的核心技能,并能够在实际工作中应用这些技能。',
image: 'https://images.unsplash.com/photo-1635070041078-e363dbe005cb?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',
category: 'psychology',
level: '数学基础',
duration: '免费',
studentsCount: 1234,
lessonsCount: 24,
badge: '热门'
},
{
id: 2,
title: '数据心理学的发展历程',
description: '本课程深度解析,让您一次性掌握数据分析的心理学基础。适合希望从心理学角度理解数据的学习者。这是一门综合性的课程,涵盖了数据分析的各个方面。通过本课程的学习,您将能够掌握数据分析的核心技能。',
image: 'https://images.unsplash.com/photo-1509228468518-180dd4864904?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',
category: 'psychology',
level: '数学基础',
duration: '免费',
studentsCount: 856,
lessonsCount: 30,
badge: '热门'
},
{
id: 3,
title: '研究情境性环境的影响',
description: '本课程深度解析,让您一次性掌握数据分析的心理学基础。适合希望从心理学角度理解数据的学习者。这是一门综合性的课程,涵盖了数据分析的各个方面。通过本课程的学习,您将能够掌握数据分析的核心技能。',
image: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',
category: 'psychology',
level: '数学基础',
duration: '免费',
studentsCount: 678,
lessonsCount: 36,
badge: '热门'
},
{
id: 4,
title: '研究学习环境设计和有效教学模式',
description: '本课程深度解析,让您一次性掌握数据分析的心理学基础。适合希望从心理学角度理解数据的学习者。这是一门综合性的课程,涵盖了数据分析的各个方面。通过本课程的学习,您将能够掌握数据分析的核心技能。',
image: 'https://images.unsplash.com/photo-1551650975-87deedd944c3?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',
category: 'psychology',
level: '数学基础',
duration: '免费',
studentsCount: 945,
lessonsCount: 30,
badge: '热门'
},
{
id: 5,
title: '数据心理学的起源',
description: '本课程深度解析,让您一次性掌握数据分析的心理学基础。适合希望从心理学角度理解数据的学习者。这是一门综合性的课程,涵盖了数据分析的各个方面。通过本课程的学习,您将能够掌握数据分析的核心技能。',
image: 'https://images.unsplash.com/photo-1596495578065-6e0763fa1178?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',
category: 'psychology',
level: '数学基础',
duration: '免费',
studentsCount: 1567,
lessonsCount: 18,
badge: '热门'
},
])
// 计算属性
const filteredPaths = computed(() => {
let filtered = learningPaths.value
if (selectedCategory.value) {
filtered = filtered.filter(path => path.category === selectedCategory.value)
}
return filtered
})
const totalPages = computed(() => Math.ceil(filteredPaths.value.length / pageSize))
const paginatedPaths = computed(() => {
const start = (currentPage.value - 1) * pageSize
const end = start + pageSize
return filteredPaths.value.slice(start, end)
})
const visiblePages = computed(() => {
const pages = []
const total = totalPages.value
const current = currentPage.value
for (let i = Math.max(1, current - 2); i <= Math.min(total, current + 2); i++) {
pages.push(i)
}
return pages
})
// 方法
const selectCategory = (category: string) => {
selectedCategory.value = category
currentPage.value = 1
}
const goToPage = (page: number) => {
currentPage.value = page
}
const goToPath = (pathId: number) => {
router.push(`/learning-path/${pathId}`)
}
onMounted(() => {
// 页面加载时的初始化逻辑
console.log('学习路径页面加载完成')
})
</script>
<style scoped>
.learning-paths-page {
min-height: 100vh;
background-color: #f8f9fa;
}
/* 页面标题区域 */
.page-header {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
padding: 60px 0;
position: relative;
overflow: hidden;
}
.page-header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, rgba(255,255,255,0.1) 25%, transparent 25%),
linear-gradient(-45deg, rgba(255,255,255,0.1) 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, rgba(255,255,255,0.1) 75%),
linear-gradient(-45deg, transparent 75%, rgba(255,255,255,0.1) 75%);
background-size: 20px 20px;
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
opacity: 0.1;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
position: relative;
}
.header-content {
text-align: center;
color: white;
}
.page-title {
font-size: 48px;
font-weight: 700;
margin: 0 0 16px 0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.page-subtitle {
font-size: 18px;
font-weight: 400;
margin: 0;
opacity: 0.9;
}
.header-decoration {
position: absolute;
right: 50px;
top: 50%;
transform: translateY(-50%);
}
.decoration-image {
width: 200px;
height: auto;
opacity: 0.8;
}
/* 主要内容区域 */
.main-content {
padding: 40px 0 80px;
background-color: rgb(246, 246, 246);
}
.content-layout {
display: flex;
gap: 30px;
align-items: flex-start;
}
/* 左侧筛选栏 */
.filter-sidebar {
width: 280px;
flex-shrink: 0;
}
.filter-section {
background: white;
border-radius: 8px;
padding: 20px;
margin-bottom: 0;
box-shadow: none;
border: 1px solid #e9ecef;
}
.filter-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin: 0 0 20px 0;
padding: 0;
/* 所有路径标题直接显示在灰色背景上,无背景样式 */
}
.filter-options {
display: flex;
flex-direction: column;
gap: 0;
}
.filter-option {
display: flex;
align-items: center;
padding: 10px 0;
border-radius: 0;
cursor: pointer;
transition: all 0.2s;
border: none;
border-bottom: 1px solid #e9ecef;
background: transparent;
}
.filter-option:last-child {
border-bottom: none;
}
.filter-option:hover {
background-color: transparent;
}
.filter-option.active .option-text {
color: #1976d2;
font-weight: 500;
}
.filter-option.active .blue-icon {
color: #1976d2;
}
.option-icon {
display: inline-block;
margin-right: 8px;
font-size: 12px;
width: 12px;
height: 12px;
line-height: 1;
flex-shrink: 0;
}
.blue-icon {
color: #1976d2;
}
.gray-icon {
color: #999;
}
.option-text {
font-size: 14px;
font-weight: 400;
color: #666;
line-height: 1.4;
word-wrap: break-word;
word-break: break-word;
flex: 1;
}
/* 右侧内容区域 */
.content-main {
flex: 1;
}
.content-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin: 0 0 20px 0;
padding: 0;
/* 课程标题直接显示在灰色背景上,无背景样式 */
}
.content-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 0;
width: 100%;
}
.result-info {
color: #666;
font-size: 14px;
}
.result-stats {
font-weight: 400;
color: #666;
}
.sort-options {
display: flex;
align-items: center;
gap: 8px;
}
.sort-label {
font-size: 14px;
color: #666;
}
.sort-select {
padding: 4px 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
background: white;
cursor: pointer;
color: #666;
}
/* 学习路径列表 */
.paths-list {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 40px;
}
.path-card {
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
transition: all 0.2s;
cursor: pointer;
display: flex;
min-height: 120px;
}
.path-card:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.card-image {
position: relative;
width: 160px;
flex-shrink: 0;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
}
.image-placeholder {
width: 100%;
height: 100%;
background: #e0e0e0;
display: flex;
align-items: center;
justify-content: center;
}
.card-badge {
position: absolute;
top: 8px;
left: 8px;
background: #ff6b35;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 11px;
font-weight: 500;
}
.card-content {
padding: 16px 20px;
flex: 1;
display: flex;
flex-direction: column;
}
.card-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin: 0 0 8px 0;
line-height: 1.3;
}
.card-meta {
display: flex;
gap: 8px;
margin-bottom: 8px;
}
.meta-item {
font-size: 12px;
color: #666;
background: #f8f9fa;
padding: 2px 6px;
border-radius: 3px;
}
.card-description {
font-size: 13px;
color: #666;
line-height: 1.5;
margin: 0 0 12px 0;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: auto;
}
.card-stats {
display: flex;
gap: 12px;
}
.stat-item {
font-size: 12px;
color: #999;
}
.card-rating {
display: flex;
align-items: center;
gap: 4px;
}
.rating-icon {
font-size: 14px;
}
.rating-text {
font-size: 12px;
color: #666;
font-weight: 500;
}
/* 分页样式 */
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
margin-top: 40px;
}
.page-btn {
padding: 8px 16px;
border: 1px solid #ddd;
background: white;
color: #666;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
min-width: 40px;
}
.page-btn:hover:not(:disabled) {
border-color: #2196f3;
color: #2196f3;
}
.page-btn.active {
background: #2196f3;
border-color: #2196f3;
color: white;
}
.page-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* 响应式设计 */
@media (max-width: 1024px) {
.content-layout {
flex-direction: column;
}
.filter-sidebar {
width: 100%;
}
.filter-options {
flex-direction: row;
flex-wrap: wrap;
gap: 12px;
}
.filter-option {
flex: 0 0 auto;
}
}
@media (max-width: 768px) {
.page-header {
padding: 40px 0;
}
.page-title {
font-size: 32px;
}
.page-subtitle {
font-size: 16px;
}
.header-decoration {
display: none;
}
.paths-list {
grid-template-columns: 1fr;
gap: 16px;
}
.content-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.sort-options {
align-self: flex-end;
}
}
@media (max-width: 480px) {
.container {
padding: 0 16px;
}
.main-content {
padding: 20px 0 40px;
}
.filter-section {
padding: 16px;
}
.card-content {
padding: 16px;
}
.pagination {
gap: 4px;
}
.page-btn {
padding: 6px 12px;
font-size: 12px;
min-width: 32px;
}
}
</style>