954 lines
30 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

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

// 课程相关API接口
import { ApiRequest } from '../request'
import type {
ApiResponse,
PaginationResponse,
Course,
CourseCategory,
CourseSubject,
CourseDifficulty,
CourseListQueryParams,
BackendCourseItem,
Chapter,
Lesson,
LessonResource,
CourseSection,
CourseSectionListResponse,
BackendCourseSection,
BackendInstructor,
BackendSectionVideo,
SectionVideo,
VideoQuality,
Quiz,
LearningProgress,
SearchRequest,
Instructor,
} from '../types'
/**
* 课程API模块
*/
export class CourseApi {
/**
* 格式化时间戳为ISO字符串
*/
private static formatTimestamp(timestamp: number | string | null | undefined): string {
if (!timestamp) {
return new Date().toISOString()
}
try {
// 如果是字符串,尝试解析
if (typeof timestamp === 'string') {
const date = new Date(timestamp)
return isNaN(date.getTime()) ? new Date().toISOString() : date.toISOString()
}
// 如果是数字时间戳
if (timestamp <= 0) {
return new Date().toISOString()
}
// 如果时间戳是秒级的,转换为毫秒级
const ms = timestamp < 10000000000 ? timestamp * 1000 : timestamp
const date = new Date(ms)
// 检查日期是否有效
if (isNaN(date.getTime())) {
return new Date().toISOString()
}
return date.toISOString()
} catch (error) {
console.error('时间戳格式化失败:', error)
return new Date().toISOString()
}
}
/**
* 映射后端难度值到前端级别
*/
private static mapDifficultyToLevel(difficulty: number): string {
switch (difficulty) {
case 0: return '零基础'
case 1: return '初级'
case 2: return '进阶'
case 3: return '高阶'
default: return '未知'
}
}
/**
* 映射后端难度值到标准级别
*/
private static mapDifficultyToStandardLevel(difficulty: number): 'beginner' | 'intermediate' | 'advanced' {
switch (difficulty) {
case 0: return 'beginner'
case 1: return 'beginner'
case 2: return 'intermediate'
case 3: return 'advanced'
default: return 'beginner'
}
}
// 获取课程列表 - 适配后端接口
static async getCourses(params?: CourseListQueryParams): Promise<ApiResponse<Course[]>> {
try {
console.log('🚀 调用课程列表API参数:', params)
// 构建查询参数根据API文档的参数名称
const queryParams: any = {}
if (params?.categoryId) queryParams.categoryId = params.categoryId
if (params?.difficulty) queryParams.difficulty = params.difficulty
if (params?.subject) queryParams.subject = params.subject
console.log('🔍 查询参数:', queryParams)
// 调用后端API
const response = await ApiRequest.get<any>('/biz/course/list', queryParams)
console.log('🔍 课程列表API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success && response.data.result) {
// 转换后端数据格式为前端格式
const courses: Course[] = response.data.result.map((item: BackendCourseItem) => ({
id: item.id, // 保持字符串格式,不转换为数字
title: item.name || '',
description: item.description || '',
instructor: item.school || '未知讲师',
duration: item.arrangement || '待定',
level: this.mapDifficultyToLevel(item.difficulty),
category: item.subject || '其他',
thumbnail: item.cover || '',
price: 0, // 后端没有价格字段设为0
rating: 0, // 后端没有评分字段设为0
studentsCount: item.enrollCount || 0,
lessonsCount: 0, // 后端没有课程数量字段设为0
tags: [],
isEnrolled: false,
progress: 0,
createdAt: this.formatTimestamp(item.createTime),
updatedAt: this.formatTimestamp(item.updateTime),
status: item.status === 1 ? 'published' : 'draft',
enrollmentCount: item.enrollCount || 0,
maxEnrollment: item.maxEnroll || 0,
startDate: item.startTime || '',
endDate: item.endTime || '',
outline: item.outline || '',
prerequisite: item.prerequisite || '',
reference: item.reference || '',
target: item.target || '',
question: item.question || '',
video: item.video || ''
}))
return {
code: 200,
message: '获取成功',
data: courses
}
} else {
console.warn('⚠️ 课程列表API返回格式异常:', response)
return {
code: 500,
message: response.data?.message || '获取课程列表失败',
data: []
}
}
} catch (error: any) {
console.error('课程API调用失败:', error)
let errorMessage = '获取课程列表失败'
if (error.code === 'ECONNABORTED') {
errorMessage = '请求超时,请检查网络连接'
} else if (error.message === 'Network Error') {
errorMessage = '网络连接失败,请检查网络设置'
} else if (error.message?.includes('网络')) {
errorMessage = error.message
}
// 返回空数据而不是抛出错误,确保应用不会崩溃
return {
code: 500,
message: errorMessage,
data: []
}
}
}
// 获取课程详情 - 适配后端接口
static async getCourseDetail(id: string): Promise<ApiResponse<Course>> {
try {
console.log('🚀 调用课程详情API课程ID:', id)
// 调用后端API
const response = await ApiRequest.get<any>('/biz/course/detail', { id })
console.log('🔍 课程详情API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success) {
// 检查result是否为null或空
if (!response.data.result) {
console.warn('⚠️ 课程详情为空,可能课程不存在或已删除')
return {
code: 404,
message: '课程不存在或已删除',
data: {} as Course
}
}
// 转换后端数据格式为前端格式
const item: BackendCourseItem = response.data.result
const course: Course = {
id: item.id, // 保持字符串格式,不转换为数字
title: item.name || '',
description: item.description || '',
thumbnail: item.cover || '',
price: 0, // 后端没有价格字段设为0
currency: 'CNY',
rating: 0, // 后端没有评分字段设为0
ratingCount: 0,
studentsCount: item.enrollCount || 0,
duration: item.arrangement || '待定',
totalLessons: 0,
level: this.mapDifficultyToStandardLevel(item.difficulty),
language: 'zh-CN',
category: {
id: 1,
name: item.subject || '其他',
slug: 'other'
},
tags: [],
skills: [],
requirements: item.prerequisite ? [item.prerequisite] : [],
objectives: item.target ? [item.target] : [],
instructor: {
id: 1,
name: item.school || '未知讲师',
title: '讲师',
bio: '',
avatar: '',
rating: 4.5,
studentsCount: 0,
coursesCount: 0,
experience: '',
education: [],
certifications: []
},
status: item.status === 1 ? 'published' : 'draft',
isEnrolled: false,
progress: 0,
createdAt: this.formatTimestamp(item.createTime),
updatedAt: this.formatTimestamp(item.updateTime)
}
return {
code: 200,
message: '获取成功',
data: course
}
} else {
console.warn('⚠️ 课程详情API返回格式异常:', response)
return {
code: 500,
message: response.data?.message || '获取课程详情失败',
data: {} as Course
}
}
} catch (error: any) {
console.error('❌ 获取课程详情失败:', error)
return {
code: 500,
message: error.message || '获取课程详情失败',
data: {} as Course
}
}
}
// 搜索课程
static searchCourses(params: SearchRequest): Promise<ApiResponse<PaginationResponse<Course>>> {
return ApiRequest.get('/courses/search', params)
}
// 获取热门课程
static getPopularCourses(limit?: number): Promise<ApiResponse<Course[]>> {
return ApiRequest.get('/courses/popular', { limit })
}
// 获取最新课程
static getLatestCourses(limit?: number): Promise<ApiResponse<Course[]>> {
return ApiRequest.get('/courses/latest', { limit })
}
// 获取推荐课程
static getRecommendedCourses(userId?: number, limit?: number): Promise<ApiResponse<Course[]>> {
return ApiRequest.get('/courses/recommended', { userId, limit })
}
// 获取课程详情 - 适配后端接口
static async getCourseById(id: string): Promise<ApiResponse<Course>> {
try {
// 调用后端课程详情接口
const response = await ApiRequest.get<any>('/biz/course/detail', { id })
console.log('🔍 课程详情API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success) {
// 检查result是否为null或空
if (!response.data.result) {
console.warn('⚠️ 课程详情为空,可能课程不存在或已删除')
return {
code: 404,
message: '课程不存在或已删除',
data: {} as Course
}
}
// 转换后端数据格式为前端格式
const item: BackendCourseItem = response.data.result
const course: Course = {
id: item.id, // 保持字符串格式,不转换为数字
title: item.name || '',
description: item.description || '',
thumbnail: item.cover || '',
price: 0, // 后端没有价格字段设为0
currency: 'CNY',
rating: 0, // 后端没有评分字段设为0
ratingCount: 0,
studentsCount: item.enrollCount || 0,
duration: item.arrangement || '待定',
totalLessons: 0,
level: this.mapDifficultyToStandardLevel(item.difficulty),
language: 'zh-CN',
category: {
id: 1,
name: item.subject || '其他',
slug: 'other'
},
tags: [],
skills: [],
requirements: item.prerequisite ? [item.prerequisite] : [],
objectives: item.target ? [item.target] : [],
instructor: {
id: 1,
name: item.school || '未知讲师',
title: '讲师',
bio: '',
avatar: '',
rating: 4.5,
studentsCount: 0,
coursesCount: 0,
experience: '',
education: [],
certifications: []
},
status: item.status === 1 ? 'published' : 'draft',
isEnrolled: false,
progress: 0,
createdAt: this.formatTimestamp(item.createTime),
updatedAt: this.formatTimestamp(item.updateTime)
}
return {
code: 200,
message: '获取成功',
data: course
}
} else {
console.warn('⚠️ 课程详情API返回格式异常:', response)
return {
code: 500,
message: response.data?.message || '获取课程详情失败',
data: {} as Course
}
}
} catch (error: any) {
console.error('❌ 获取课程详情失败:', error)
return {
code: 500,
message: error.message || '获取课程详情失败',
data: {} as Course
}
}
}
// 获取课程章节
static getCourseChapters(courseId: number): Promise<ApiResponse<Chapter[]>> {
return ApiRequest.get(`/courses/${courseId}/chapters`)
}
// 获取课程所有课时
static getCourseLessons(courseId: number): Promise<ApiResponse<Lesson[]>> {
return ApiRequest.get(`/courses/${courseId}/lessons`)
}
// 获取章节详情
static getChapterById(id: number): Promise<ApiResponse<Chapter>> {
return ApiRequest.get(`/chapters/${id}`)
}
// 获取课时详情
static getLessonById(id: number): Promise<ApiResponse<Lesson>> {
return ApiRequest.get(`/lessons/${id}`)
}
// 获取课时资源
static getLessonResources(lessonId: number): Promise<ApiResponse<LessonResource[]>> {
return ApiRequest.get(`/lessons/${lessonId}/resources`)
}
// 获取课程分类
static async getCategories(): Promise<ApiResponse<CourseCategory[]>> {
try {
console.log('🚀 获取课程分类列表')
// 调用后端API不需要token
const response = await ApiRequest.get<any>('/biz/course/category/list')
console.log('🔍 分类API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success && response.data.result) {
// 转换后端数据格式为前端格式
const categories: CourseCategory[] = response.data.result.map((item: any) => ({
id: parseInt(item.id) || 0,
name: item.name || '',
slug: item.name?.toLowerCase().replace(/\s+/g, '-') || '',
description: '',
sortOrder: item.sortOrder || 0
}))
return {
code: 200,
message: '获取成功',
data: categories
}
} else {
console.warn('⚠️ 分类API返回格式异常:', response)
return {
code: 500,
message: response.data?.message || '获取分类失败',
data: []
}
}
} catch (error: any) {
console.error('❌ 获取课程分类失败:', error)
return {
code: 500,
message: error.message || '获取分类失败',
data: []
}
}
}
// 获取课程专题列表
static async getSubjects(): Promise<ApiResponse<CourseSubject[]>> {
try {
console.log('🚀 获取课程专题列表')
// 调用后端API不需要token
const response = await ApiRequest.get<any>('/biz/course/subject/list')
console.log('🔍 专题API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success && response.data.result) {
// 转换后端数据格式为前端格式专题接口返回的是value和label字段
const subjects: CourseSubject[] = response.data.result.map((item: any, index: number) => ({
id: item.value || '0', // 保持原始的value值字符串格式
name: item.label || '',
slug: item.label?.toLowerCase().replace(/\s+/g, '-') || '',
description: '',
sortOrder: index
}))
return {
code: 200,
message: '获取成功',
data: subjects
}
} else {
console.warn('⚠️ 专题API返回格式异常:', response)
return {
code: 500,
message: response.data?.message || '获取专题失败',
data: []
}
}
} catch (error: any) {
console.error('❌ 获取课程专题失败:', error)
return {
code: 500,
message: error.message || '获取专题失败',
data: []
}
}
}
// 获取课程难度列表
static async getDifficulties(): Promise<ApiResponse<CourseDifficulty[]>> {
try {
console.log('🚀 获取课程难度列表')
// 调用后端API不需要token
const response = await ApiRequest.get<any>('/biz/course/difficulty/list')
console.log('🔍 难度API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success && response.data.result) {
// 转换后端数据格式为前端格式难度接口返回的是value和label字段
const difficulties: CourseDifficulty[] = response.data.result.map((item: any, index: number) => ({
id: item.value || '0', // 保持原始的value值字符串格式
name: item.label || '',
slug: item.label?.toLowerCase().replace(/\s+/g, '-') || '',
description: '',
sortOrder: index
}))
return {
code: 200,
message: '获取成功',
data: difficulties
}
} else {
console.warn('⚠️ 难度API返回格式异常:', response)
return {
code: 500,
message: response.data?.message || '获取难度失败',
data: []
}
}
} catch (error: any) {
console.error('❌ 获取课程难度失败:', error)
return {
code: 500,
message: error.message || '获取难度失败',
data: []
}
}
}
// 获取分类下的课程
static getCoursesByCategory(categoryId: number, params?: {
page?: number
pageSize?: number
sortBy?: string
}): Promise<ApiResponse<PaginationResponse<Course>>> {
return ApiRequest.get(`/categories/${categoryId}/courses`, params)
}
// 报名课程
static enrollCourse(courseId: number): Promise<ApiResponse<{
enrollmentId: number
message: string
}>> {
return ApiRequest.post(`/courses/${courseId}/enroll`)
}
// 取消报名
static unenrollCourse(courseId: number): Promise<ApiResponse<null>> {
return ApiRequest.delete(`/courses/${courseId}/enroll`)
}
// 获取课程章节列表
static async getCourseSections(courseId: string): Promise<ApiResponse<CourseSectionListResponse>> {
try {
console.log('🔍 获取课程章节数据课程ID:', courseId)
console.log('🔍 API请求URL: /biz/course/' + courseId + '/section')
const response = await ApiRequest.get<any>(`/biz/course/${courseId}/section`)
console.log('🔍 章节API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success && response.data.result) {
console.log('✅ 响应状态码:', response.data.code)
console.log('✅ 响应消息:', response.data.message)
console.log('✅ 原始章节数据:', response.data.result)
console.log('✅ 章节数据数量:', response.data.result.length || 0)
// 适配数据格式
const adaptedSections: CourseSection[] = response.data.result.map((section: BackendCourseSection) => ({
id: section.id,
lessonId: section.courseId, // 使用courseId作为lessonId
outline: '', // 暂时为空根据type可以设置不同的内容
name: section.name,
type: section.type, // 保持原值可能为null
parentId: section.parentId || '', // 如果parentId为空字符串保持为空字符串
sort: section.sortOrder,
level: section.level,
revision: 1, // 默认版本号
createdAt: section.createTime ? new Date(section.createTime).getTime() : null,
updatedAt: section.updateTime ? new Date(section.updateTime).getTime() : null,
deletedAt: null,
completed: false,
duration: undefined
}))
console.log('✅ 适配后的章节数据:', adaptedSections)
return {
code: response.data.code,
message: response.data.message,
data: {
list: adaptedSections,
timestamp: Date.now(),
traceId: response.data.timestamp?.toString() || ''
}
}
} else {
console.warn('⚠️ API返回的数据结构不正确:', response.data)
return {
code: 500,
message: '数据格式错误',
data: {
list: [],
timestamp: Date.now(),
traceId: ''
}
}
}
} catch (error) {
console.error('❌ 章节API调用失败:', error)
console.error('❌ 错误详情:', {
message: (error as Error).message,
stack: (error as Error).stack,
response: (error as any).response?.data,
status: (error as any).response?.status,
statusText: (error as any).response?.statusText
})
// 重新抛出错误,不使用模拟数据
throw error
}
}
// 获取我的课程
static getMyCourses(params?: {
page?: number
pageSize?: number
status?: 'all' | 'in_progress' | 'completed'
}): Promise<ApiResponse<PaginationResponse<Course>>> {
return ApiRequest.get('/my-courses', params)
}
// 获取学习进度
static getLearningProgress(courseId: number): Promise<ApiResponse<LearningProgress>> {
return ApiRequest.get(`/courses/${courseId}/progress`)
}
// 更新学习进度
static updateLearningProgress(data: {
courseId: number
lessonId: number
progress: number
timeSpent?: number
}): Promise<ApiResponse<LearningProgress>> {
return ApiRequest.post('/learning-progress', data)
}
// 标记课时完成
static markLessonCompleted(lessonId: number): Promise<ApiResponse<null>> {
return ApiRequest.post(`/lessons/${lessonId}/complete`)
}
// 获取课程测验
static getCourseQuizzes(courseId: number): Promise<ApiResponse<Quiz[]>> {
return ApiRequest.get(`/courses/${courseId}/quizzes`)
}
// 获取测验详情
static getQuizById(id: number): Promise<ApiResponse<Quiz>> {
return ApiRequest.get(`/quizzes/${id}`)
}
// 提交测验答案
static submitQuizAnswers(quizId: number, answers: Array<{
questionId: number
answer: string | string[]
}>): Promise<ApiResponse<{
score: number
totalScore: number
passed: boolean
correctAnswers: number
totalQuestions: number
results: Array<{
questionId: number
correct: boolean
userAnswer: string | string[]
correctAnswer: string | string[]
}>
}>> {
return ApiRequest.post(`/quizzes/${quizId}/submit`, { answers })
}
// 获取测验结果
static getQuizResults(quizId: number): Promise<ApiResponse<{
attempts: Array<{
id: number
score: number
totalScore: number
passed: boolean
submittedAt: string
}>
bestScore: number
averageScore: number
totalAttempts: number
}>> {
return ApiRequest.get(`/quizzes/${quizId}/results`)
}
// 下载课程资源
static downloadResource(resourceId: number): Promise<void> {
return ApiRequest.download(`/resources/${resourceId}/download`)
}
// 获取讲师信息
static getInstructorById(id: number): Promise<ApiResponse<Instructor>> {
return ApiRequest.get(`/instructors/${id}`)
}
// 获取讲师的课程
static getInstructorCourses(instructorId: number, params?: {
page?: number
pageSize?: number
}): Promise<ApiResponse<PaginationResponse<Course>>> {
return ApiRequest.get(`/instructors/${instructorId}/courses`, params)
}
// 关注讲师
static followInstructor(instructorId: number): Promise<ApiResponse<null>> {
return ApiRequest.post(`/instructors/${instructorId}/follow`)
}
// 取消关注讲师
static unfollowInstructor(instructorId: number): Promise<ApiResponse<null>> {
return ApiRequest.delete(`/instructors/${instructorId}/follow`)
}
// 获取课程统计信息
static getCourseStats(courseId: number): Promise<ApiResponse<{
totalStudents: number
totalLessons: number
totalDuration: string
averageRating: number
completionRate: number
enrollmentTrend: Array<{
date: string
count: number
}>
}>> {
return ApiRequest.get(`/courses/${courseId}/stats`)
}
// 预览课程(免费课时)
static previewCourse(courseId: number): Promise<ApiResponse<{
freeLessons: Lesson[]
previewVideo?: string
}>> {
return ApiRequest.get(`/courses/${courseId}/preview`)
}
// 获取相关课程推荐
static getRelatedCourses(courseId: number, limit?: number): Promise<ApiResponse<Course[]>> {
return ApiRequest.get(`/courses/${courseId}/related`, { limit })
}
// 检查课程访问权限
static checkCourseAccess(courseId: number): Promise<ApiResponse<{
hasAccess: boolean
reason?: string
expiresAt?: string
}>> {
return ApiRequest.get(`/courses/${courseId}/access`)
}
// 获取课程讲师列表
static async getCourseInstructors(courseId: string): Promise<ApiResponse<Instructor[]>> {
try {
console.log('🔍 获取课程讲师数据课程ID:', courseId)
console.log('🔍 API请求URL: /biz/course/' + courseId + '/teachers')
const response = await ApiRequest.get<any>(`/biz/course/${courseId}/teachers`)
console.log('🔍 讲师API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success && response.data.result) {
console.log('✅ 响应状态码:', response.data.code)
console.log('✅ 响应消息:', response.data.message)
console.log('✅ 原始讲师数据:', response.data.result)
console.log('✅ 讲师数据数量:', response.data.result.length || 0)
// 适配数据格式
const adaptedInstructors: Instructor[] = response.data.result.map((instructor: BackendInstructor) => ({
id: parseInt(instructor.id) || 0, // 转换为数字ID
name: instructor.name,
title: instructor.title,
bio: instructor.tag || '', // 使用tag作为bio
avatar: instructor.avatar,
rating: 4.8, // 默认评分
studentsCount: 1000, // 默认学生数
coursesCount: 10, // 默认课程数
experience: '5年教学经验', // 默认经验
education: ['计算机科学硕士'], // 默认教育背景
certifications: ['高级讲师认证'] // 默认认证
}))
console.log('✅ 适配后的讲师数据:', adaptedInstructors)
return {
code: response.data.code,
message: response.data.message,
data: adaptedInstructors
}
} else {
console.warn('⚠️ API返回的数据结构不正确:', response.data)
return {
code: 500,
message: '数据格式错误',
data: []
}
}
} catch (error) {
console.error('❌ 讲师API调用失败:', error)
console.error('❌ 错误详情:', {
message: (error as Error).message,
stack: (error as Error).stack,
response: (error as any).response?.data,
status: (error as any).response?.status,
statusText: (error as any).response?.statusText
})
// 重新抛出错误,不使用模拟数据
throw error
}
}
// 获取章节视频列表
static async getSectionVideos(courseId: string, sectionId: string): Promise<ApiResponse<SectionVideo[]>> {
try {
console.log('🔍 获取章节视频数据课程ID:', courseId, '章节ID:', sectionId)
console.log('🔍 API请求URL: /biz/course/' + courseId + '/section_video/' + sectionId)
const response = await ApiRequest.get<any>(`/biz/course/${courseId}/section_video/${sectionId}`)
console.log('🔍 章节视频API响应:', response)
// 处理后端响应格式
if (response.data && response.data.success && response.data.result) {
console.log('✅ 响应状态码:', response.data.code)
console.log('✅ 响应消息:', response.data.message)
console.log('✅ 原始视频数据:', response.data.result)
console.log('✅ 视频数据数量:', response.data.result.length || 0)
// 适配数据格式
const adaptedVideos: SectionVideo[] = response.data.result.map((video: BackendSectionVideo) => {
// 解析fileUrl中的多个清晰度URL
const qualities = this.parseVideoQualities(video.fileUrl)
return {
id: video.id,
name: video.name,
description: video.description,
type: video.type,
thumbnailUrl: video.thumbnailUrl,
duration: video.duration,
fileSize: video.fileSize,
qualities: qualities,
defaultQuality: '360', // 默认360p
currentQuality: '360' // 当前选中360p
}
})
console.log('✅ 适配后的视频数据:', adaptedVideos)
return {
code: response.data.code,
message: response.data.message,
data: adaptedVideos
}
} else {
console.warn('⚠️ API返回的数据结构不正确:', response.data)
return {
code: 500,
message: '数据格式错误',
data: []
}
}
} catch (error) {
console.error('❌ 章节视频API调用失败:', error)
console.error('❌ 错误详情:', {
message: (error as Error).message,
stack: (error as Error).stack,
response: (error as any).response?.data,
status: (error as any).response?.status,
statusText: (error as any).response?.statusText
})
// 重新抛出错误,不使用模拟数据
throw error
}
}
// 解析视频URL逗号分隔的多个清晰度URL
private static parseVideoQualities(fileUrl: string): VideoQuality[] {
const qualities: VideoQuality[] = []
try {
if (!fileUrl || fileUrl.trim() === '') {
console.warn('视频URL为空')
return qualities
}
// 按逗号分割URL
const urls = fileUrl.split(',').map(url => url.trim()).filter(url => url.length > 0)
console.log('🔍 分割后的视频URL:', urls)
// 支持的清晰度列表(按优先级排序)
const supportedQualities = [
{ value: '1080', label: '1080p' },
{ value: '720', label: '720p' },
{ value: '480', label: '480p' },
{ value: '360', label: '360p' }
]
// 根据URL数量分配清晰度
// 假设URL按清晰度从高到低排列1080p, 720p, 480p, 360p
urls.forEach((url, index) => {
if (index < supportedQualities.length) {
qualities.push({
label: supportedQualities[index].label,
value: supportedQualities[index].value,
url: url
})
}
})
// 如果没有解析到任何清晰度使用第一个URL作为360p
if (qualities.length === 0 && urls.length > 0) {
qualities.push({
label: '360p',
value: '360',
url: urls[0]
})
}
console.log('✅ 解析后的视频清晰度:', qualities)
} catch (error) {
console.warn('解析视频清晰度失败使用原始URL:', error)
// 如果解析失败将整个fileUrl作为360p使用
qualities.push({
label: '360p',
value: '360',
url: fileUrl
})
}
return qualities
}
}
export default CourseApi