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

View File

@ -5,19 +5,10 @@ import type {
PaginationResponse,
Course,
CourseCategory,
BackendCourseCategory,
BackendCourseCategoryListResponse,
CourseSubject,
BackendCourseSubject,
BackendCourseSubjectListResponse,
CourseDifficulty,
BackendCourseDifficulty,
BackendCourseDifficultyListResponse,
CourseListQueryParams,
CourseDetailQueryParams,
BackendCourseItem,
BackendCourseListResponse,
BackendCourseDetailResponse,
Chapter,
Lesson,
LessonResource,
@ -29,8 +20,6 @@ import type {
LearningProgress,
SearchRequest,
Instructor,
BackendCourse,
CourseListRequest,
} 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 {
code: 500,
message: errorMessage,
data: {
list: [],
total: 0,
page: params?.page || 1,
pageSize: params?.pageSize || 10,
totalPages: 0
}
data: []
}
}
}
@ -581,13 +551,13 @@ export class CourseApi {
}
// 获取课程章节列表
static async getCourseSections(lessonId: number): Promise<ApiResponse<CourseSectionListResponse>> {
static async getCourseSections(lessonId: string): Promise<ApiResponse<CourseSectionListResponse>> {
try {
console.log('尝试从API获取课程章节数据课程ID:', lessonId)
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)
// 检查是否是axios响应格式还是我们的ApiResponse格式
@ -821,33 +791,7 @@ export class CourseApi {
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

View File

@ -249,6 +249,8 @@ export interface CourseListQueryParams {
categoryId?: string // 分类ID
difficulty?: string // 难度值
subject?: string // 专题值
page?: number // 页码
pageSize?: number // 每页数量
}
// 后端课程数据格式
@ -382,8 +384,8 @@ export interface BackendCourseSection {
// 前端使用的课程章节类型(适配后的数据结构)
export interface CourseSection {
id: number
lessonId: number
id: string // 改为string类型保持一致性
lessonId: string // 改为string类型与Course.id保持一致
outline: string // 章节大纲/内容链接从videoUrl适配
name: string // 章节名称
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 {
id: number
courseId: number
courseId: string // 改为string类型与Course.id保持一致
title: string
description: string
videoUrl?: string
@ -63,13 +63,13 @@ export const useCourseStore = defineStore('course', () => {
console.log('尝试从API获取课程数据...')
const response = await CourseApi.getCourses()
console.log('API响应:', response)
courses.value = response.data.list
courses.value = response.data
} catch (error) {
console.error('API调用失败使用模拟数据:', error)
// 如果API调用失败使用模拟数据作为后备
const mockCourses: Course[] = [
{
id: 1,
id: "1",
title: 'Vue.js 3 完整教程',
description: '从零开始学习Vue.js 3包括Composition API、TypeScript集成等现代开发技术',
content: '详细的Vue.js 3课程内容',
@ -114,7 +114,7 @@ export const useCourseStore = defineStore('course', () => {
publishedAt: '2024-01-01'
},
{
id: 2,
id: "2",
title: 'React 18 实战开发',
description: '掌握React 18的新特性包括并发渲染、Suspense等高级功能',
content: '详细的React 18课程内容',
@ -159,7 +159,7 @@ export const useCourseStore = defineStore('course', () => {
publishedAt: '2024-01-05'
},
{
id: 3,
id: "3",
title: 'Node.js 后端开发',
description: '学习Node.js后端开发包括Express、数据库操作、API设计等',
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
try {
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
try {
// 模拟API调用
@ -271,7 +271,7 @@ export const useCourseStore = defineStore('course', () => {
}
}
const enrollCourse = async (courseId: number) => {
const enrollCourse = async (courseId: string) => {
isLoading.value = true
try {
// 模拟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)
if (course) {
course.progress = progress

View File

@ -529,40 +529,40 @@ const groupedSections = ref<ChapterGroup[]>([])
const generateMockSections = (): CourseSection[] => {
return [
// - (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: 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: 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: "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: "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 },
// - (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: 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: 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: "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: "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: "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)
{ 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: 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: 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: "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: "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: "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 },
// - (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: 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: 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: "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: "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' },
// - (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: 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: "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: "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)
{ 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: "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' }
]
}
@ -597,20 +597,20 @@ const groupSectionsByChapter = (sections: CourseSection[]) => {
}
//
const generateChapterGroups = () => {
//
if (courseSections.value.length === 0) {
console.log('没有章节数据,生成模拟数据')
courseSections.value = generateMockSections()
}
console.log('开始生成章节分组,原始数据:', courseSections.value)
console.log('章节数据数量:', courseSections.value.length)
// 使
groupedSections.value = groupSectionsByChapter(courseSections.value)
console.log('生成的章节分组:', groupedSections.value)
}
// const generateChapterGroups = () => {
// //
// if (courseSections.value.length === 0) {
// console.log('')
// courseSections.value = generateMockSections()
// }
//
// console.log(':', courseSections.value)
// console.log(':', courseSections.value.length)
//
// // 使
// groupedSections.value = groupSectionsByChapter(courseSections.value)
// console.log(':', groupedSections.value)
// }
// 使groupSectionsByChapter
// const getChapterTitle = (chapterIndex: number): string => {
@ -813,9 +813,9 @@ const loadMockData = () => {
groupedSections.value = groupSectionsByChapter(mockSections)
//
const completed = mockSections.filter(section => section.completed).length
completedLessons.value = completed
progress.value = Math.round((completed / mockSections.length) * 100)
// const completed = mockSections.filter(section => section.completed).length
// completedLessons.value = completed
// progress.value = Math.round((completed / mockSections.length) * 100)
}
// /
@ -859,7 +859,7 @@ const formatLessonDuration = (section: CourseSection): string => {
]
// section.id
const durationIndex = section.id - 1
const durationIndex = parseInt(section.id) - 1
if (durationIndex >= 0 && durationIndex < durations.length) {
return durations[durationIndex] || ''
}

View File

@ -395,7 +395,7 @@ declare global {
const route = useRoute()
const router = useRouter()
const userStore = useUserStore()
const courseId = ref(Number(route.params.id))
const courseId = ref(route.params.id as string)
// false
const FORCE_LOCAL_VIDEO = true
@ -538,40 +538,40 @@ const displayComments = ref([
const generateMockSections = (): CourseSection[] => {
return [
// - (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: 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: 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: "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: "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 },
// - (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: 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: 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: "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: "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: "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)
{ 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: 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: 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: "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: "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: "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 },
// - (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: 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: 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: "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: "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' },
// - (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: 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: "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: "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)
{ 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: "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' }
]
}
@ -609,7 +609,7 @@ const groupSectionsByChapter = (sections: CourseSection[]) => {
const loadCourseDetail = async () => {
console.log('开始加载课程详情课程ID:', courseId.value)
if (!courseId.value || isNaN(courseId.value)) {
if (!courseId.value || courseId.value.trim() === '') {
error.value = '课程ID无效'
console.error('课程ID无效:', courseId.value)
return
@ -640,7 +640,7 @@ const loadCourseDetail = async () => {
//
const loadCourseSections = async () => {
if (!courseId.value || isNaN(courseId.value)) {
if (!courseId.value || courseId.value.trim() === '') {
sectionsError.value = '课程ID无效'
console.error('课程ID无效:', courseId.value)
return

View File

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

View File

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

View File

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

View File

@ -155,7 +155,7 @@ const isPlaying = ref(false)
const noteContent = ref('')
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 lessons = computed(() => courseStore.lessons)

View File

@ -128,7 +128,7 @@ const toggleFollow = () => {
}
import { useRouter } from 'vue-router'
import type { Course } from '@/api/types'
import { mockCourses } from '@/data/mockCourses'
// import { mockCourses } from '@/data/mockCourses'
const router = useRouter()
@ -201,7 +201,7 @@ const loadCourses = async () => {
await new Promise(resolve => setTimeout(resolve, 500))
//
let filteredCourses = [...mockCourses]
let filteredCourses: Course[] = [] // 使API
//
if (selectedSubject.value !== '全部') {
@ -234,7 +234,7 @@ const loadCourses = async () => {
});
} else {
// 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 =>
course.title.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 type { CourseSection } from '@/api/types'
const testLessonId = ref(1)
const testLessonId = ref("1")
const loading = ref(false)
const error = ref('')
const sections = ref<CourseSection[]>([])