fix:mock数据后端返回不匹配类型报错

This commit is contained in:
小张 2025-08-15 13:58:25 +08:00
parent 13113e1bbc
commit 0e1a73192f
13 changed files with 112 additions and 829 deletions

View File

@ -73,15 +73,14 @@ export const getCoursesExample = async () => {
const response = await CourseApi.getCourses({ const response = await CourseApi.getCourses({
page: 1, page: 1,
pageSize: 20, pageSize: 20,
categoryId: 1, categoryId: '1',
difficulty: 1, difficulty: '1'
sortBy: 'createdAt'
}) })
if (response.code === 200) { if (response.code === 200) {
const { list, total } = response.data const courses = response.data
console.log('课程列表:', list) console.log('课程列表:', courses)
console.log('总数:', total) console.log('总数:', courses.length)
return response.data return response.data
} }
} catch (error) { } catch (error) {
@ -113,7 +112,7 @@ export const searchCoursesExample = async () => {
} }
// 获取课程详情示例 // 获取课程详情示例
export const getCourseDetailExample = async (courseId: number) => { export const getCourseDetailExample = async (courseId: string) => {
try { try {
const response = await CourseApi.getCourseById(courseId) const response = await CourseApi.getCourseById(courseId)
if (response.code === 200) { if (response.code === 200) {

View File

@ -5,19 +5,10 @@ import type {
PaginationResponse, PaginationResponse,
Course, Course,
CourseCategory, CourseCategory,
BackendCourseCategory,
BackendCourseCategoryListResponse,
CourseSubject, CourseSubject,
BackendCourseSubject,
BackendCourseSubjectListResponse,
CourseDifficulty, CourseDifficulty,
BackendCourseDifficulty,
BackendCourseDifficultyListResponse,
CourseListQueryParams, CourseListQueryParams,
CourseDetailQueryParams,
BackendCourseItem, BackendCourseItem,
BackendCourseListResponse,
BackendCourseDetailResponse,
Chapter, Chapter,
Lesson, Lesson,
LessonResource, LessonResource,
@ -29,8 +20,6 @@ import type {
LearningProgress, LearningProgress,
SearchRequest, SearchRequest,
Instructor, Instructor,
BackendCourse,
CourseListRequest,
} from '../types' } from '../types'
/** /**
@ -74,20 +63,7 @@ export class CourseApi {
} }
} }
/**
*
*/
private static calculateDuration(startTime: string, endTime: string): string {
try {
const start = new Date(startTime)
const end = new Date(endTime)
const diffMs = end.getTime() - start.getTime()
const diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24))
return `${diffDays}`
} catch (error) {
return '待定'
}
}
/** /**
* *
@ -194,13 +170,7 @@ export class CourseApi {
return { return {
code: 500, code: 500,
message: errorMessage, message: errorMessage,
data: { data: []
list: [],
total: 0,
page: params?.page || 1,
pageSize: params?.pageSize || 10,
totalPages: 0
}
} }
} }
} }
@ -581,13 +551,13 @@ export class CourseApi {
} }
// 获取课程章节列表 // 获取课程章节列表
static async getCourseSections(lessonId: number): Promise<ApiResponse<CourseSectionListResponse>> { static async getCourseSections(lessonId: string): Promise<ApiResponse<CourseSectionListResponse>> {
try { try {
console.log('尝试从API获取课程章节数据课程ID:', lessonId) console.log('尝试从API获取课程章节数据课程ID:', lessonId)
console.log('API请求URL: /lesson/section/list') console.log('API请求URL: /lesson/section/list')
console.log('API请求参数:', { lesson_id: lessonId.toString() }) console.log('API请求参数:', { lesson_id: lessonId })
const backendResponse = await ApiRequest.get<BackendCourseSectionListResponse>('/lesson/section/list', { lesson_id: lessonId.toString() }) const backendResponse = await ApiRequest.get<BackendCourseSectionListResponse>('/lesson/section/list', { lesson_id: lessonId })
console.log('章节API响应:', backendResponse) console.log('章节API响应:', backendResponse)
// 检查是否是axios响应格式还是我们的ApiResponse格式 // 检查是否是axios响应格式还是我们的ApiResponse格式
@ -821,33 +791,7 @@ export class CourseApi {
return ApiRequest.get(`/courses/${courseId}/access`) return ApiRequest.get(`/courses/${courseId}/access`)
} }
// 辅助方法:映射难度等级
private static mapDifficulty(difficulty: number): 'beginner' | 'intermediate' | 'advanced' {
switch (difficulty) {
case 0:
return 'beginner'
case 1:
return 'intermediate'
case 2:
return 'advanced'
default:
return 'beginner'
}
}
// 辅助方法:获取分类名称
private static getCategoryName(categoryId: number): string {
// 这里可以根据categoryId返回对应的分类名称
// 暂时返回默认值后续可以通过分类API获取
const categoryMap: { [key: number]: string } = {
1: '信息技术',
2: '数学',
3: '物理',
4: '化学',
5: '生物'
}
return categoryMap[categoryId] || '其他'
}
} }
export default CourseApi export default CourseApi

View File

@ -249,6 +249,8 @@ export interface CourseListQueryParams {
categoryId?: string // 分类ID categoryId?: string // 分类ID
difficulty?: string // 难度值 difficulty?: string // 难度值
subject?: string // 专题值 subject?: string // 专题值
page?: number // 页码
pageSize?: number // 每页数量
} }
// 后端课程数据格式 // 后端课程数据格式
@ -382,8 +384,8 @@ export interface BackendCourseSection {
// 前端使用的课程章节类型(适配后的数据结构) // 前端使用的课程章节类型(适配后的数据结构)
export interface CourseSection { export interface CourseSection {
id: number id: string // 改为string类型保持一致性
lessonId: number lessonId: string // 改为string类型与Course.id保持一致
outline: string // 章节大纲/内容链接从videoUrl适配 outline: string // 章节大纲/内容链接从videoUrl适配
name: string // 章节名称 name: string // 章节名称
parentId: number // 父章节ID parentId: number // 父章节ID

View File

@ -1,661 +0,0 @@
// 课程模拟数据
import type { Course } from '@/api/types'
export const mockCourses: Course[] = [
{
"id": 1,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities5.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 2,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities4.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 3,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities3.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 4,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course5.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 5,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities1.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 6,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities5.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 7,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities4.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 8,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities4.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 9,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities5.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 10,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities4.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 11,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities5.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 12,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities4.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 13,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities4.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 14,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities5.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
},
{
"id": 15,
"title": "暑期名师领学,提高班级教学质量!高效冲分指南",
"description": "本课程深度聚焦问题让每一位教师了解并学习使用DeepSeek结合办公自动化职业岗位标准以实际工作任务为引导强调课程内容的易用性和岗位要求的匹配性。",
"thumbnail": "/images/courses/course-activities4.png",
"price": 99,
"originalPrice": 199,
"currency": "CNY",
"rating": 4.8,
"ratingCount": 324,
"studentsCount": 324,
"duration": "12小时43分钟",
"totalLessons": 54,
"level": "beginner",
"language": "zh-CN",
"category": {
"id": 1,
"name": "教育培训",
"slug": "education"
},
"tags": ["教学质量", "高效学习", "名师指导"],
"skills": ["教学方法", "课堂管理", "学习指导"],
"requirements": ["具备基本的计算机操作能力"],
"objectives": ["掌握核心技能,能够在实际工作中熟练应用"],
"instructor": {
"id": 1,
"name": "刘莹",
"avatar": "https://via.placeholder.com/100",
"bio": "资深教育专家",
"title": "高级讲师",
"rating": 4.8,
"studentsCount": 1200,
"coursesCount": 15,
"experience": "10年教学经验",
"education": ["教育学博士", "计算机科学硕士"],
"certifications": ["高级讲师认证", "教学质量奖"]
},
"status": "published",
"createdAt": "2025-01-26T10:13:17Z",
"updatedAt": "2025-01-26T10:13:17Z"
}
]
// 根据ID获取课程
export const getCourseById = (id: number): Course | undefined => {
return mockCourses.find(course => course.id === id)
}
// 获取热门课程前5个
export const getPopularCourses = (): Course[] => {
return mockCourses.slice(0, 4)
}
// 根据分类筛选课程
export const getCoursesByCategory = (categoryName: string): Course[] => {
if (categoryName === '全部') return mockCourses
return mockCourses.filter(course => course.category.name === categoryName)
}
// 根据难度筛选课程
export const getCoursesByLevel = (level: string): Course[] => {
const levelMap: { [key: string]: string } = {
'初级': 'beginner',
'中级': 'intermediate',
'高级': 'advanced'
}
const targetLevel = levelMap[level]
if (!targetLevel) return mockCourses
return mockCourses.filter(course => course.level === targetLevel)
}
// 搜索课程
export const searchCourses = (keyword: string): Course[] => {
if (!keyword) return mockCourses
const lowerKeyword = keyword.toLowerCase()
return mockCourses.filter(course =>
course.title.toLowerCase().includes(lowerKeyword) ||
course.description.toLowerCase().includes(lowerKeyword) ||
course.tags.some(tag => tag.toLowerCase().includes(lowerKeyword)) ||
course.skills.some(skill => skill.toLowerCase().includes(lowerKeyword))
)
}

View File

@ -7,7 +7,7 @@ export type Course = ApiCourse
export interface Lesson { export interface Lesson {
id: number id: number
courseId: number courseId: string // 改为string类型与Course.id保持一致
title: string title: string
description: string description: string
videoUrl?: string videoUrl?: string
@ -63,13 +63,13 @@ export const useCourseStore = defineStore('course', () => {
console.log('尝试从API获取课程数据...') console.log('尝试从API获取课程数据...')
const response = await CourseApi.getCourses() const response = await CourseApi.getCourses()
console.log('API响应:', response) console.log('API响应:', response)
courses.value = response.data.list courses.value = response.data
} catch (error) { } catch (error) {
console.error('API调用失败使用模拟数据:', error) console.error('API调用失败使用模拟数据:', error)
// 如果API调用失败使用模拟数据作为后备 // 如果API调用失败使用模拟数据作为后备
const mockCourses: Course[] = [ const mockCourses: Course[] = [
{ {
id: 1, id: "1",
title: 'Vue.js 3 完整教程', title: 'Vue.js 3 完整教程',
description: '从零开始学习Vue.js 3包括Composition API、TypeScript集成等现代开发技术', description: '从零开始学习Vue.js 3包括Composition API、TypeScript集成等现代开发技术',
content: '详细的Vue.js 3课程内容', content: '详细的Vue.js 3课程内容',
@ -114,7 +114,7 @@ export const useCourseStore = defineStore('course', () => {
publishedAt: '2024-01-01' publishedAt: '2024-01-01'
}, },
{ {
id: 2, id: "2",
title: 'React 18 实战开发', title: 'React 18 实战开发',
description: '掌握React 18的新特性包括并发渲染、Suspense等高级功能', description: '掌握React 18的新特性包括并发渲染、Suspense等高级功能',
content: '详细的React 18课程内容', content: '详细的React 18课程内容',
@ -159,7 +159,7 @@ export const useCourseStore = defineStore('course', () => {
publishedAt: '2024-01-05' publishedAt: '2024-01-05'
}, },
{ {
id: 3, id: "3",
title: 'Node.js 后端开发', title: 'Node.js 后端开发',
description: '学习Node.js后端开发包括Express、数据库操作、API设计等', description: '学习Node.js后端开发包括Express、数据库操作、API设计等',
content: '详细的Node.js课程内容', content: '详细的Node.js课程内容',
@ -210,7 +210,7 @@ export const useCourseStore = defineStore('course', () => {
} }
} }
const fetchCourseById = async (id: number) => { const fetchCourseById = async (id: string) => {
isLoading.value = true isLoading.value = true
try { try {
const response = await CourseApi.getCourseById(id) const response = await CourseApi.getCourseById(id)
@ -227,7 +227,7 @@ export const useCourseStore = defineStore('course', () => {
} }
} }
const fetchLessons = async (courseId: number) => { const fetchLessons = async (courseId: string) => {
isLoading.value = true isLoading.value = true
try { try {
// 模拟API调用 // 模拟API调用
@ -271,7 +271,7 @@ export const useCourseStore = defineStore('course', () => {
} }
} }
const enrollCourse = async (courseId: number) => { const enrollCourse = async (courseId: string) => {
isLoading.value = true isLoading.value = true
try { try {
// 模拟API调用 // 模拟API调用
@ -292,7 +292,7 @@ export const useCourseStore = defineStore('course', () => {
} }
} }
const updateProgress = async (courseId: number, progress: number) => { const updateProgress = async (courseId: string, progress: number) => {
const course = enrolledCourses.value.find(c => c.id === courseId) const course = enrolledCourses.value.find(c => c.id === courseId)
if (course) { if (course) {
course.progress = progress course.progress = progress

View File

@ -529,40 +529,40 @@ const groupedSections = ref<ChapterGroup[]>([])
const generateMockSections = (): CourseSection[] => { const generateMockSections = (): CourseSection[] => {
return [ return [
// - (4) // - (4)
{ id: 1, lessonId: courseId.value, name: '开课彩蛋:新开始新征程', outline: 'https://example.com/video1.m3u8', parentId: 0, sort: 1, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '01:03:56' }, { id: "1", lessonId: courseId.value, name: '开课彩蛋:新开始新征程', outline: 'https://example.com/video1.m3u8', parentId: 0, sort: 1, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '01:03:56' },
{ id: 2, lessonId: courseId.value, name: '课程定位与目标', outline: 'https://example.com/video2.m3u8', parentId: 0, sort: 2, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:44:05' }, { id: "2", lessonId: courseId.value, name: '课程定位与目标', outline: 'https://example.com/video2.m3u8', parentId: 0, sort: 2, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:44:05' },
{ id: 3, lessonId: courseId.value, name: '教学安排及学习建议', outline: 'https://example.com/video3.m3u8', parentId: 0, sort: 3, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:52:22' }, { id: "3", lessonId: courseId.value, name: '教学安排及学习建议', outline: 'https://example.com/video3.m3u8', parentId: 0, sort: 3, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:52:22' },
{ id: 4, lessonId: courseId.value, name: '课前准备PPT', outline: 'https://example.com/ppt1.ppt', parentId: 0, sort: 4, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "4", lessonId: courseId.value, name: '课前准备PPT', outline: 'https://example.com/ppt1.ppt', parentId: 0, sort: 4, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
// - (5) // - (5)
{ id: 5, lessonId: courseId.value, name: '第一课 程序设计入门', outline: 'https://example.com/video4.m3u8', parentId: 0, sort: 5, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:52:22' }, { id: "5", lessonId: courseId.value, name: '第一课 程序设计入门', outline: 'https://example.com/video4.m3u8', parentId: 0, sort: 5, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:52:22' },
{ id: 6, lessonId: courseId.value, name: '操作PPT', outline: 'https://example.com/ppt2.ppt', parentId: 0, sort: 6, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "6", lessonId: courseId.value, name: '操作PPT', outline: 'https://example.com/ppt2.ppt', parentId: 0, sort: 6, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 7, lessonId: courseId.value, name: '第二课 循环结构', outline: 'https://example.com/video5.m3u8', parentId: 0, sort: 7, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '01:03:56' }, { id: "7", lessonId: courseId.value, name: '第二课 循环结构', outline: 'https://example.com/video5.m3u8', parentId: 0, sort: 7, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '01:03:56' },
{ id: 8, lessonId: courseId.value, name: '函数&循环', outline: 'https://example.com/video5.m3u8', parentId: 0, sort: 8, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "8", lessonId: courseId.value, name: '函数&循环', outline: 'https://example.com/video5.m3u8', parentId: 0, sort: 8, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 9, lessonId: courseId.value, name: '第三课 条件结构', outline: 'https://example.com/video6.m3u8', parentId: 0, sort: 9, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:45:30' }, { id: "9", lessonId: courseId.value, name: '第三课 条件结构', outline: 'https://example.com/video6.m3u8', parentId: 0, sort: 9, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:45:30' },
// - (6) // - (6)
{ id: 10, lessonId: courseId.value, name: '项目一:计算器开发', outline: 'https://example.com/video7.m3u8', parentId: 0, sort: 10, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:20:15' }, { id: "10", lessonId: courseId.value, name: '项目一:计算器开发', outline: 'https://example.com/video7.m3u8', parentId: 0, sort: 10, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:20:15' },
{ id: 11, lessonId: courseId.value, name: '项目源码下载', outline: 'https://example.com/source1.zip', parentId: 0, sort: 11, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "11", lessonId: courseId.value, name: '项目源码下载', outline: 'https://example.com/source1.zip', parentId: 0, sort: 11, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 12, lessonId: courseId.value, name: '项目二:数据管理系统', outline: 'https://example.com/video8.m3u8', parentId: 0, sort: 12, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:45:20' }, { id: "12", lessonId: courseId.value, name: '项目二:数据管理系统', outline: 'https://example.com/video8.m3u8', parentId: 0, sort: 12, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:45:20' },
{ id: 13, lessonId: courseId.value, name: '作业:完成个人项目', outline: '', parentId: 0, sort: 13, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "13", lessonId: courseId.value, name: '作业:完成个人项目', outline: '', parentId: 0, sort: 13, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 14, lessonId: courseId.value, name: '项目三Web应用开发', outline: 'https://example.com/video9.m3u8', parentId: 0, sort: 14, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '02:10:45' }, { id: "14", lessonId: courseId.value, name: '项目三Web应用开发', outline: 'https://example.com/video9.m3u8', parentId: 0, sort: 14, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '02:10:45' },
{ id: 15, lessonId: courseId.value, name: '期末考试', outline: '', parentId: 0, sort: 15, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "15", lessonId: courseId.value, name: '期末考试', outline: '', parentId: 0, sort: 15, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
// - (4) // - (4)
{ id: 16, lessonId: courseId.value, name: '高级特性介绍', outline: 'https://example.com/video10.m3u8', parentId: 0, sort: 16, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:55:30' }, { id: "16", lessonId: courseId.value, name: '高级特性介绍', outline: 'https://example.com/video10.m3u8', parentId: 0, sort: 16, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:55:30' },
{ id: 17, lessonId: courseId.value, name: '性能优化技巧', outline: 'https://example.com/video11.m3u8', parentId: 0, sort: 17, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:15:20' }, { id: "17", lessonId: courseId.value, name: '性能优化技巧', outline: 'https://example.com/video11.m3u8', parentId: 0, sort: 17, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:15:20' },
{ id: 18, lessonId: courseId.value, name: '部署与发布', outline: 'https://example.com/video12.m3u8', parentId: 0, sort: 18, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:40:15' }, { id: "18", lessonId: courseId.value, name: '部署与发布', outline: 'https://example.com/video12.m3u8', parentId: 0, sort: 18, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:40:15' },
{ id: 19, lessonId: courseId.value, name: '课程总结', outline: 'https://example.com/video13.m3u8', parentId: 0, sort: 19, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:30:10' }, { id: "19", lessonId: courseId.value, name: '课程总结', outline: 'https://example.com/video13.m3u8', parentId: 0, sort: 19, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:30:10' },
// - (3) // - (3)
{ id: 20, lessonId: courseId.value, name: '行业发展趋势', outline: 'https://example.com/video14.m3u8', parentId: 0, sort: 20, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:35:45' }, { id: "20", lessonId: courseId.value, name: '行业发展趋势', outline: 'https://example.com/video14.m3u8', parentId: 0, sort: 20, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:35:45' },
{ id: 21, lessonId: courseId.value, name: '学习资源推荐', outline: 'https://example.com/resources.pdf', parentId: 0, sort: 21, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "21", lessonId: courseId.value, name: '学习资源推荐', outline: 'https://example.com/resources.pdf', parentId: 0, sort: 21, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 22, lessonId: courseId.value, name: '结业证书申请', outline: '', parentId: 0, sort: 22, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "22", lessonId: courseId.value, name: '结业证书申请', outline: '', parentId: 0, sort: 22, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
// - (2) // - (2)
{ id: 23, lessonId: courseId.value, name: '常见问题解答', outline: 'https://example.com/video15.m3u8', parentId: 0, sort: 23, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:25:30' }, { id: "23", lessonId: courseId.value, name: '常见问题解答', outline: 'https://example.com/video15.m3u8', parentId: 0, sort: 23, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:25:30' },
{ id: 24, lessonId: courseId.value, name: '在线答疑直播', outline: 'https://example.com/live1.m3u8', parentId: 0, sort: 24, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:30:00' } { id: "24", lessonId: courseId.value, name: '在线答疑直播', outline: 'https://example.com/live1.m3u8', parentId: 0, sort: 24, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:30:00' }
] ]
} }
@ -597,20 +597,20 @@ const groupSectionsByChapter = (sections: CourseSection[]) => {
} }
// //
const generateChapterGroups = () => { // const generateChapterGroups = () => {
// // //
if (courseSections.value.length === 0) { // if (courseSections.value.length === 0) {
console.log('没有章节数据,生成模拟数据') // console.log('')
courseSections.value = generateMockSections() // courseSections.value = generateMockSections()
} // }
//
console.log('开始生成章节分组,原始数据:', courseSections.value) // console.log(':', courseSections.value)
console.log('章节数据数量:', courseSections.value.length) // console.log(':', courseSections.value.length)
//
// 使 // // 使
groupedSections.value = groupSectionsByChapter(courseSections.value) // groupedSections.value = groupSectionsByChapter(courseSections.value)
console.log('生成的章节分组:', groupedSections.value) // console.log(':', groupedSections.value)
} // }
// 使groupSectionsByChapter // 使groupSectionsByChapter
// const getChapterTitle = (chapterIndex: number): string => { // const getChapterTitle = (chapterIndex: number): string => {
@ -813,9 +813,9 @@ const loadMockData = () => {
groupedSections.value = groupSectionsByChapter(mockSections) groupedSections.value = groupSectionsByChapter(mockSections)
// //
const completed = mockSections.filter(section => section.completed).length // const completed = mockSections.filter(section => section.completed).length
completedLessons.value = completed // completedLessons.value = completed
progress.value = Math.round((completed / mockSections.length) * 100) // progress.value = Math.round((completed / mockSections.length) * 100)
} }
// / // /
@ -859,7 +859,7 @@ const formatLessonDuration = (section: CourseSection): string => {
] ]
// section.id // section.id
const durationIndex = section.id - 1 const durationIndex = parseInt(section.id) - 1
if (durationIndex >= 0 && durationIndex < durations.length) { if (durationIndex >= 0 && durationIndex < durations.length) {
return durations[durationIndex] || '' return durations[durationIndex] || ''
} }

View File

@ -395,7 +395,7 @@ declare global {
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const userStore = useUserStore() const userStore = useUserStore()
const courseId = ref(Number(route.params.id)) const courseId = ref(route.params.id as string)
// false // false
const FORCE_LOCAL_VIDEO = true const FORCE_LOCAL_VIDEO = true
@ -538,40 +538,40 @@ const displayComments = ref([
const generateMockSections = (): CourseSection[] => { const generateMockSections = (): CourseSection[] => {
return [ return [
// - (4) // - (4)
{ id: 1, lessonId: courseId.value, name: '开课彩蛋:新开始新征程', outline: 'https://example.com/video1.m3u8', parentId: 0, sort: 1, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '01:03:56' }, { id: "1", lessonId: courseId.value, name: '开课彩蛋:新开始新征程', outline: 'https://example.com/video1.m3u8', parentId: 0, sort: 1, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '01:03:56' },
{ id: 2, lessonId: courseId.value, name: '课程定位与目标', outline: 'https://example.com/video2.m3u8', parentId: 0, sort: 2, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:44:05' }, { id: "2", lessonId: courseId.value, name: '课程定位与目标', outline: 'https://example.com/video2.m3u8', parentId: 0, sort: 2, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:44:05' },
{ id: 3, lessonId: courseId.value, name: '教学安排及学习建议', outline: 'https://example.com/video3.m3u8', parentId: 0, sort: 3, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:52:22' }, { id: "3", lessonId: courseId.value, name: '教学安排及学习建议', outline: 'https://example.com/video3.m3u8', parentId: 0, sort: 3, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:52:22' },
{ id: 4, lessonId: courseId.value, name: '课前准备PPT', outline: 'https://example.com/ppt1.ppt', parentId: 0, sort: 4, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "4", lessonId: courseId.value, name: '课前准备PPT', outline: 'https://example.com/ppt1.ppt', parentId: 0, sort: 4, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
// - (5) // - (5)
{ id: 5, lessonId: courseId.value, name: '第一课 程序设计入门', outline: 'https://example.com/video4.m3u8', parentId: 0, sort: 5, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:52:22' }, { id: "5", lessonId: courseId.value, name: '第一课 程序设计入门', outline: 'https://example.com/video4.m3u8', parentId: 0, sort: 5, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '00:52:22' },
{ id: 6, lessonId: courseId.value, name: '操作PPT', outline: 'https://example.com/ppt2.ppt', parentId: 0, sort: 6, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "6", lessonId: courseId.value, name: '操作PPT', outline: 'https://example.com/ppt2.ppt', parentId: 0, sort: 6, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 7, lessonId: courseId.value, name: '第二课 循环结构', outline: 'https://example.com/video5.m3u8', parentId: 0, sort: 7, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '01:03:56' }, { id: "7", lessonId: courseId.value, name: '第二课 循环结构', outline: 'https://example.com/video5.m3u8', parentId: 0, sort: 7, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: true, duration: '01:03:56' },
{ id: 8, lessonId: courseId.value, name: '函数&循环', outline: 'https://example.com/video5.m3u8', parentId: 0, sort: 8, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "8", lessonId: courseId.value, name: '函数&循环', outline: 'https://example.com/video5.m3u8', parentId: 0, sort: 8, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 9, lessonId: courseId.value, name: '第三课 条件结构', outline: 'https://example.com/video6.m3u8', parentId: 0, sort: 9, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:45:30' }, { id: "9", lessonId: courseId.value, name: '第三课 条件结构', outline: 'https://example.com/video6.m3u8', parentId: 0, sort: 9, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:45:30' },
// - (6) // - (6)
{ id: 10, lessonId: courseId.value, name: '项目一:计算器开发', outline: 'https://example.com/video7.m3u8', parentId: 0, sort: 10, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:20:15' }, { id: "10", lessonId: courseId.value, name: '项目一:计算器开发', outline: 'https://example.com/video7.m3u8', parentId: 0, sort: 10, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:20:15' },
{ id: 11, lessonId: courseId.value, name: '项目源码下载', outline: 'https://example.com/source1.zip', parentId: 0, sort: 11, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "11", lessonId: courseId.value, name: '项目源码下载', outline: 'https://example.com/source1.zip', parentId: 0, sort: 11, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 12, lessonId: courseId.value, name: '项目二:数据管理系统', outline: 'https://example.com/video8.m3u8', parentId: 0, sort: 12, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:45:20' }, { id: "12", lessonId: courseId.value, name: '项目二:数据管理系统', outline: 'https://example.com/video8.m3u8', parentId: 0, sort: 12, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:45:20' },
{ id: 13, lessonId: courseId.value, name: '作业:完成个人项目', outline: '', parentId: 0, sort: 13, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "13", lessonId: courseId.value, name: '作业:完成个人项目', outline: '', parentId: 0, sort: 13, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 14, lessonId: courseId.value, name: '项目三Web应用开发', outline: 'https://example.com/video9.m3u8', parentId: 0, sort: 14, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '02:10:45' }, { id: "14", lessonId: courseId.value, name: '项目三Web应用开发', outline: 'https://example.com/video9.m3u8', parentId: 0, sort: 14, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '02:10:45' },
{ id: 15, lessonId: courseId.value, name: '期末考试', outline: '', parentId: 0, sort: 15, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "15", lessonId: courseId.value, name: '期末考试', outline: '', parentId: 0, sort: 15, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
// - (4) // - (4)
{ id: 16, lessonId: courseId.value, name: '高级特性介绍', outline: 'https://example.com/video10.m3u8', parentId: 0, sort: 16, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:55:30' }, { id: "16", lessonId: courseId.value, name: '高级特性介绍', outline: 'https://example.com/video10.m3u8', parentId: 0, sort: 16, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:55:30' },
{ id: 17, lessonId: courseId.value, name: '性能优化技巧', outline: 'https://example.com/video11.m3u8', parentId: 0, sort: 17, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:15:20' }, { id: "17", lessonId: courseId.value, name: '性能优化技巧', outline: 'https://example.com/video11.m3u8', parentId: 0, sort: 17, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:15:20' },
{ id: 18, lessonId: courseId.value, name: '部署与发布', outline: 'https://example.com/video12.m3u8', parentId: 0, sort: 18, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:40:15' }, { id: "18", lessonId: courseId.value, name: '部署与发布', outline: 'https://example.com/video12.m3u8', parentId: 0, sort: 18, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:40:15' },
{ id: 19, lessonId: courseId.value, name: '课程总结', outline: 'https://example.com/video13.m3u8', parentId: 0, sort: 19, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:30:10' }, { id: "19", lessonId: courseId.value, name: '课程总结', outline: 'https://example.com/video13.m3u8', parentId: 0, sort: 19, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:30:10' },
// - (3) // - (3)
{ id: 20, lessonId: courseId.value, name: '行业发展趋势', outline: 'https://example.com/video14.m3u8', parentId: 0, sort: 20, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:35:45' }, { id: "20", lessonId: courseId.value, name: '行业发展趋势', outline: 'https://example.com/video14.m3u8', parentId: 0, sort: 20, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:35:45' },
{ id: 21, lessonId: courseId.value, name: '学习资源推荐', outline: 'https://example.com/resources.pdf', parentId: 0, sort: 21, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "21", lessonId: courseId.value, name: '学习资源推荐', outline: 'https://example.com/resources.pdf', parentId: 0, sort: 21, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
{ id: 22, lessonId: courseId.value, name: '结业证书申请', outline: '', parentId: 0, sort: 22, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined }, { id: "22", lessonId: courseId.value, name: '结业证书申请', outline: '', parentId: 0, sort: 22, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: undefined },
// - (2) // - (2)
{ id: 23, lessonId: courseId.value, name: '常见问题解答', outline: 'https://example.com/video15.m3u8', parentId: 0, sort: 23, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:25:30' }, { id: "23", lessonId: courseId.value, name: '常见问题解答', outline: 'https://example.com/video15.m3u8', parentId: 0, sort: 23, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '00:25:30' },
{ id: 24, lessonId: courseId.value, name: '在线答疑直播', outline: 'https://example.com/live1.m3u8', parentId: 0, sort: 24, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:30:00' } { id: "24", lessonId: courseId.value, name: '在线答疑直播', outline: 'https://example.com/live1.m3u8', parentId: 0, sort: 24, level: 1, revision: 1, createdAt: Date.now(), updatedAt: Date.now(), deletedAt: null, completed: false, duration: '01:30:00' }
] ]
} }
@ -609,7 +609,7 @@ const groupSectionsByChapter = (sections: CourseSection[]) => {
const loadCourseDetail = async () => { const loadCourseDetail = async () => {
console.log('开始加载课程详情课程ID:', courseId.value) console.log('开始加载课程详情课程ID:', courseId.value)
if (!courseId.value || isNaN(courseId.value)) { if (!courseId.value || courseId.value.trim() === '') {
error.value = '课程ID无效' error.value = '课程ID无效'
console.error('课程ID无效:', courseId.value) console.error('课程ID无效:', courseId.value)
return return
@ -640,7 +640,7 @@ const loadCourseDetail = async () => {
// //
const loadCourseSections = async () => { const loadCourseSections = async () => {
if (!courseId.value || isNaN(courseId.value)) { if (!courseId.value || courseId.value.trim() === '') {
sectionsError.value = '课程ID无效' sectionsError.value = '课程ID无效'
console.error('课程ID无效:', courseId.value) console.error('课程ID无效:', courseId.value)
return return

View File

@ -368,7 +368,7 @@ import type { Course, CourseSection } from '@/api/types'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const courseId = ref(Number(route.params.id)) const courseId = ref(route.params.id as string)
// URL // URL
const currentVideoUrl = ref(route.query.videoUrl ? decodeURIComponent(route.query.videoUrl as string) : '') const currentVideoUrl = ref(route.query.videoUrl ? decodeURIComponent(route.query.videoUrl as string) : '')
@ -385,7 +385,7 @@ console.log('- 路由查询参数:', route.query)
// //
const course = ref<Course | null>(null) const course = ref<Course | null>(null)
const courseSections = ref<CourseSection[]>([]) const courseSections = ref<CourseSection[]>([])
const currentLessonId = ref(currentSectionId.value || 1) const currentLessonId = ref(currentSectionId.value ? currentSectionId.value.toString() : "1")
// //
const isPlaying = ref(false) const isPlaying = ref(false)
@ -476,12 +476,12 @@ const sortedChapters = computed(() => {
const hasPrevious = computed(() => { const hasPrevious = computed(() => {
// //
return currentLessonId.value > 1 return parseInt(currentLessonId.value) > 1
}) })
const hasNext = computed(() => { const hasNext = computed(() => {
// //
return currentLessonId.value < totalLessons.value return parseInt(currentLessonId.value) < totalLessons.value
}) })
const isCurrentLessonCompleted = computed(() => { const isCurrentLessonCompleted = computed(() => {
@ -498,7 +498,7 @@ watch(() => route.query, (newQuery) => {
currentVideoTitle.value = decodeURIComponent(newQuery.sectionName as string) currentVideoTitle.value = decodeURIComponent(newQuery.sectionName as string)
} }
if (newQuery.sectionId) { if (newQuery.sectionId) {
currentLessonId.value = Number(newQuery.sectionId) currentLessonId.value = newQuery.sectionId.toString()
} }
}) })
@ -537,7 +537,7 @@ const generateChapterGroups = () => {
title: '课前准备', title: '课前准备',
lessons: [ lessons: [
{ {
id: 1, id: "1",
lessonId: courseId.value, lessonId: courseId.value,
outline: currentVideoUrl.value, outline: currentVideoUrl.value,
name: currentVideoTitle.value || '开课彩蛋:新开始新征程', name: currentVideoTitle.value || '开课彩蛋:新开始新征程',
@ -556,7 +556,7 @@ const generateChapterGroups = () => {
} else { } else {
parentSections.forEach((parentSection, index) => { parentSections.forEach((parentSection, index) => {
const childSections = courseSections.value.filter(section => const childSections = courseSections.value.filter(section =>
section.level === 1 && section.parentId === parentSection.id section.level === 1 && section.parentId === parseInt(parentSection.id)
) )
groups.push({ groups.push({

View File

@ -174,8 +174,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, onMounted } from 'vue' import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import type { Course, CourseCategory, CourseSubject, CourseDifficulty, CourseListQueryParams } from '@/api/types' import type { Course, CourseCategory, CourseSubject, CourseDifficulty } from '@/api/types'
import { mockCourses } from '@/data/mockCourses'
import { CourseApi } from '@/api' import { CourseApi } from '@/api'
const router = useRouter() const router = useRouter()

View File

@ -528,7 +528,7 @@ import { useCourseStore } from '@/stores/course'
import { useAuth } from '@/composables/useAuth' import { useAuth } from '@/composables/useAuth'
import LoginModal from '@/components/auth/LoginModal.vue' import LoginModal from '@/components/auth/LoginModal.vue'
import RegisterModal from '@/components/auth/RegisterModal.vue' import RegisterModal from '@/components/auth/RegisterModal.vue'
import { getPopularCourses } from '@/data/mockCourses' // import { getPopularCourses } from '@/data/mockCourses'
const { t, locale } = useI18n() const { t, locale } = useI18n()
const router = useRouter() const router = useRouter()
@ -554,8 +554,8 @@ const bannerAlt = computed(() => {
// //
const popularCourses = computed(() => { const popularCourses = computed(() => {
const courses = getPopularCourses() const courses = courseStore.courses.slice(0, 4) // 4
return courses.map(course => ({ return courses.map((course: any) => ({
id: course.id, id: course.id,
title: course.title, title: course.title,
thumbnail: course.thumbnail, thumbnail: course.thumbnail,
@ -719,12 +719,12 @@ const partners = computed(() => [
// ]) // ])
// //
const goToCourseDetail = (courseId: number) => { const goToCourseDetail = (courseId: string) => {
router.push(`/course/${courseId}`) router.push(`/course/${courseId}`)
} }
// - // -
const handleEnrollCourse = (courseId: number) => { const handleEnrollCourse = (courseId: string) => {
// //
router.push(`/course/${courseId}`) router.push(`/course/${courseId}`)
} }

View File

@ -155,7 +155,7 @@ const isPlaying = ref(false)
const noteContent = ref('') const noteContent = ref('')
const progress = ref(0) const progress = ref(0)
const courseId = computed(() => Number(route.params.id)) const courseId = computed(() => route.params.id as string)
const course = computed(() => courseStore.currentCourse) const course = computed(() => courseStore.currentCourse)
const lessons = computed(() => courseStore.lessons) const lessons = computed(() => courseStore.lessons)

View File

@ -128,7 +128,7 @@ const toggleFollow = () => {
} }
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import type { Course } from '@/api/types' import type { Course } from '@/api/types'
import { mockCourses } from '@/data/mockCourses' // import { mockCourses } from '@/data/mockCourses'
const router = useRouter() const router = useRouter()
@ -201,7 +201,7 @@ const loadCourses = async () => {
await new Promise(resolve => setTimeout(resolve, 500)) await new Promise(resolve => setTimeout(resolve, 500))
// //
let filteredCourses = [...mockCourses] let filteredCourses: Course[] = [] // 使API
// //
if (selectedSubject.value !== '全部') { if (selectedSubject.value !== '全部') {
@ -234,7 +234,7 @@ const loadCourses = async () => {
}); });
} else { } else {
// ID // ID
filteredCourses.sort((a, b) => a.id - b.id); filteredCourses.sort((a, b) => a.id.localeCompare(b.id));
} }
// //
@ -242,7 +242,7 @@ const loadCourses = async () => {
filteredCourses = filteredCourses.filter(course => filteredCourses = filteredCourses.filter(course =>
course.title.includes(selectedMajor.value) || course.title.includes(selectedMajor.value) ||
course.description.includes(selectedMajor.value) || course.description.includes(selectedMajor.value) ||
course.tags.some(tag => tag.includes(selectedMajor.value)) course.tags?.some((tag: string) => tag.includes(selectedMajor.value))
) )
} }

View File

@ -52,7 +52,7 @@ import { ref } from 'vue'
import { CourseApi } from '@/api/modules/course' import { CourseApi } from '@/api/modules/course'
import type { CourseSection } from '@/api/types' import type { CourseSection } from '@/api/types'
const testLessonId = ref(1) const testLessonId = ref("1")
const loading = ref(false) const loading = ref(false)
const error = ref('') const error = ref('')
const sections = ref<CourseSection[]>([]) const sections = ref<CourseSection[]>([])