323 lines
9.7 KiB
TypeScript
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.

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { CourseApi } from '@/api/modules/course'
import type { Course as ApiCourse } from '@/api/types'
export type Course = ApiCourse
export interface Lesson {
id: number
courseId: number
title: string
description: string
videoUrl?: string
duration: string
order: number
isCompleted?: boolean
isFree?: boolean
}
export const useCourseStore = defineStore('course', () => {
// 状态
const courses = ref<Course[]>([])
const currentCourse = ref<Course | null>(null)
const lessons = ref<Lesson[]>([])
const enrolledCourses = ref<Course[]>([])
const isLoading = ref(false)
const searchQuery = ref('')
const selectedCategory = ref('')
const selectedLevel = ref('')
// 计算属性
const filteredCourses = computed(() => {
let filtered = courses.value
if (searchQuery.value) {
filtered = filtered.filter(course =>
course.title.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
course.description.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
course.instructor.name.toLowerCase().includes(searchQuery.value.toLowerCase())
)
}
if (selectedCategory.value) {
filtered = filtered.filter(course => course.category.name === selectedCategory.value)
}
if (selectedLevel.value) {
filtered = filtered.filter(course => course.level === selectedLevel.value)
}
return filtered
})
const categories = computed(() => {
const cats = courses.value.map(course => course.category)
return [...new Set(cats)]
})
// 方法
const fetchCourses = async () => {
isLoading.value = true
try {
console.log('尝试从API获取课程数据...')
const response = await CourseApi.getCourses()
console.log('API响应:', response)
courses.value = response.data.list
} catch (error) {
console.error('API调用失败使用模拟数据:', error)
// 如果API调用失败使用模拟数据作为后备
const mockCourses: Course[] = [
{
id: 1,
title: 'Vue.js 3 完整教程',
description: '从零开始学习Vue.js 3包括Composition API、TypeScript集成等现代开发技术',
content: '详细的Vue.js 3课程内容',
instructor: {
id: 1,
name: '李老师',
title: '前端开发专家',
bio: '资深前端开发工程师',
avatar: 'https://via.placeholder.com/50',
rating: 4.8,
studentsCount: 1234,
coursesCount: 5,
experience: '5年前端开发经验',
education: ['计算机科学学士'],
certifications: ['Vue.js认证']
},
thumbnail: 'https://via.placeholder.com/300x200',
coverImage: 'https://via.placeholder.com/300x200',
price: 299,
originalPrice: 399,
currency: 'CNY',
rating: 4.8,
ratingCount: 100,
studentsCount: 1234,
duration: '12小时',
level: 'intermediate',
category: {
id: 1,
name: '前端开发',
slug: 'frontend',
description: '前端开发相关课程'
},
tags: ['Vue.js', 'JavaScript', 'TypeScript'],
totalLessons: 20,
language: 'zh-CN',
skills: ['Vue.js', 'TypeScript', 'Composition API'],
requirements: ['JavaScript基础', 'HTML/CSS基础'],
objectives: ['掌握Vue.js 3核心概念', '学会使用Composition API', '理解TypeScript集成'],
status: 'published',
createdAt: '2024-01-01',
updatedAt: '2024-01-15',
publishedAt: '2024-01-01'
},
{
id: 2,
title: 'React 18 实战开发',
description: '掌握React 18的新特性包括并发渲染、Suspense等高级功能',
content: '详细的React 18课程内容',
instructor: {
id: 2,
name: '王老师',
title: 'React专家',
bio: '资深React开发工程师',
avatar: 'https://via.placeholder.com/50',
rating: 4.9,
studentsCount: 2156,
coursesCount: 8,
experience: '6年React开发经验',
education: ['软件工程硕士'],
certifications: ['React认证']
},
thumbnail: 'https://via.placeholder.com/300x200',
coverImage: 'https://via.placeholder.com/300x200',
price: 399,
originalPrice: 499,
currency: 'CNY',
rating: 4.9,
ratingCount: 200,
studentsCount: 2156,
duration: '15小时',
level: 'advanced',
category: {
id: 1,
name: '前端开发',
slug: 'frontend',
description: '前端开发相关课程'
},
tags: ['React', 'JavaScript', 'Hooks'],
totalLessons: 25,
language: 'zh-CN',
skills: ['React 18', 'Hooks', '并发渲染'],
requirements: ['JavaScript基础', 'React基础'],
objectives: ['掌握React 18新特性', '学会并发渲染', '理解Suspense'],
status: 'published',
createdAt: '2024-01-05',
updatedAt: '2024-01-20',
publishedAt: '2024-01-05'
},
{
id: 3,
title: 'Node.js 后端开发',
description: '学习Node.js后端开发包括Express、数据库操作、API设计等',
content: '详细的Node.js课程内容',
instructor: {
id: 3,
name: '张老师',
title: 'Node.js专家',
bio: '资深后端开发工程师',
avatar: 'https://via.placeholder.com/50',
rating: 4.7,
studentsCount: 987,
coursesCount: 6,
experience: '7年后端开发经验',
education: ['计算机科学硕士'],
certifications: ['Node.js认证']
},
thumbnail: 'https://via.placeholder.com/300x200',
coverImage: 'https://via.placeholder.com/300x200',
price: 349,
originalPrice: 449,
currency: 'CNY',
rating: 4.7,
ratingCount: 150,
studentsCount: 987,
duration: '18小时',
level: 'intermediate',
category: {
id: 2,
name: '后端开发',
slug: 'backend',
description: '后端开发相关课程'
},
tags: ['Node.js', 'Express', 'MongoDB'],
totalLessons: 30,
language: 'zh-CN',
skills: ['Node.js', 'Express', 'MongoDB', 'API设计'],
requirements: ['JavaScript基础', '编程基础'],
objectives: ['掌握Node.js后端开发', '学会Express框架', '理解数据库操作'],
status: 'published',
createdAt: '2024-01-10',
updatedAt: '2024-01-25',
publishedAt: '2024-01-10'
}
]
courses.value = mockCourses
} finally {
isLoading.value = false
}
}
const fetchCourseById = async (id: number) => {
isLoading.value = true
try {
const response = await CourseApi.getCourseById(id)
currentCourse.value = response.data
} catch (error) {
console.error('Failed to fetch course:', error)
// 如果API调用失败从本地数据中查找
const course = courses.value.find(c => c.id === id)
if (course) {
currentCourse.value = course
}
} finally {
isLoading.value = false
}
}
const fetchLessons = async (courseId: number) => {
isLoading.value = true
try {
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 500))
// 模拟课程章节数据
const mockLessons: Lesson[] = [
{
id: 1,
courseId,
title: '课程介绍',
description: '了解课程内容和学习目标',
duration: '10分钟',
order: 1,
isFree: true
},
{
id: 2,
courseId,
title: '环境搭建',
description: '配置开发环境和工具',
duration: '20分钟',
order: 2,
isFree: true
},
{
id: 3,
courseId,
title: '基础语法',
description: '学习基础语法和概念',
duration: '45分钟',
order: 3
}
]
lessons.value = mockLessons
} catch (error) {
console.error('Failed to fetch lessons:', error)
} finally {
isLoading.value = false
}
}
const enrollCourse = async (courseId: number) => {
isLoading.value = true
try {
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000))
const course = courses.value.find(c => c.id === courseId)
if (course) {
course.isEnrolled = true
course.progress = 0
enrolledCourses.value.push(course)
}
return { success: true, message: '报名成功' }
} catch (error) {
return { success: false, message: '报名失败' }
} finally {
isLoading.value = false
}
}
const updateProgress = async (courseId: number, progress: number) => {
const course = enrolledCourses.value.find(c => c.id === courseId)
if (course) {
course.progress = progress
}
}
return {
// 状态
courses,
currentCourse,
lessons,
enrolledCourses,
isLoading,
searchQuery,
selectedCategory,
selectedLevel,
// 计算属性
filteredCourses,
categories,
// 方法
fetchCourses,
fetchCourseById,
fetchLessons,
enrollCourse,
updateProgress
}
})