diff --git a/src/views/course/index.vue b/src/views/course/index.vue index a018762..de7c292 100644 --- a/src/views/course/index.vue +++ b/src/views/course/index.vue @@ -189,6 +189,65 @@ const formRules = { ] } +// 从URL中提取文件名 +const getFileNameFromUrl = (url) => { + if (!url) return '' + + // 移除重复的路径部分 + const cleanUrl = url.replace(/uploads\/courses\/(images|videos)\/uploads\/courses\/(images|videos)\//, 'uploads/courses/$1/') + + // 如果是完整URL,提取文件名 + if (cleanUrl.startsWith('http://') || cleanUrl.startsWith('https://')) { + // 移除域名和路径前缀,只保留文件名 + const matches = cleanUrl.match(/\/([^/]+)$/) + return matches ? matches[1] : cleanUrl + } + + // 如果包含域名但不是以http开头 + if (cleanUrl.includes('localhost:3000')) { + const matches = cleanUrl.match(/([^/]+)$/) + return matches ? matches[1] : cleanUrl + } + + // 如果已经是文件名,直接返回 + if (!cleanUrl.includes('/')) { + return cleanUrl + } + + // 其他情况,尝试获取最后一个斜杠后的内容 + return cleanUrl.split('/').pop() +} + +// 处理图片URL +const processImageUrl = (url) => { + if (!url) return '' + + // 如果已经是完整的正确URL,直接返回 + if (url.match(/^http:\/\/localhost:3000\/uploads\/courses\/images\/[^/]+$/)) { + return url + } + + // 获取文件名 + const fileName = getFileNameFromUrl(url) + // 构建完整URL + return `http://localhost:3000/uploads/courses/images/${fileName}` +} + +// 处理视频URL +const processVideoUrl = (url) => { + if (!url) return '' + + // 如果已经是完整的正确URL,直接返回 + if (url.match(/^http:\/\/localhost:3000\/uploads\/courses\/videos\/[^/]+$/)) { + return url + } + + // 获取文件名 + const fileName = getFileNameFromUrl(url) + // 构建完整URL + return `http://localhost:3000/uploads/courses/videos/${fileName}` +} + // 图片上传相关 const handleCoverError = (error) => { console.error('上传图片错误:', error) @@ -261,22 +320,78 @@ const handleAdd = () => { const handleEdit = (row) => { formMode.value = 'edit' dialogTitle.value = '编辑课程' + + // 从URL中提取文件名 + const getFileNameFromUrl = (url) => { + if (!url) return '' + + // 移除重复的路径部分 + const cleanUrl = url.replace(/uploads\/courses\/(images|videos)\/uploads\/courses\/(images|videos)\//, 'uploads/courses/$1/') + + // 如果是完整URL,提取文件名 + if (cleanUrl.startsWith('http://') || cleanUrl.startsWith('https://')) { + // 移除域名和路径前缀,只保留文件名 + const matches = cleanUrl.match(/\/([^/]+)$/) + return matches ? matches[1] : cleanUrl + } + + // 如果包含域名但不是以http开头 + if (cleanUrl.includes('localhost:3000')) { + const matches = cleanUrl.match(/([^/]+)$/) + return matches ? matches[1] : cleanUrl + } + + // 如果已经是文件名,直接返回 + if (!cleanUrl.includes('/')) { + return cleanUrl + } + + // 其他情况,尝试获取最后一个斜杠后的内容 + return cleanUrl.split('/').pop() + } + + // 处理图片URL + const processImageUrl = (url) => { + if (!url) return '' + + // 如果已经是完整的正确URL,直接返回 + if (url.match(/^http:\/\/localhost:3000\/uploads\/courses\/images\/[^/]+$/)) { + return url + } + + // 获取文件名 + const fileName = getFileNameFromUrl(url) + // 构建完整URL + return `http://localhost:3000/uploads/courses/images/${fileName}` + } + + // 处理视频URL + const processVideoUrl = (url) => { + if (!url) return '' + + // 如果已经是完整的正确URL,直接返回 + if (url.match(/^http:\/\/localhost:3000\/uploads\/courses\/videos\/[^/]+$/)) { + return url + } + + // 获取文件名 + const fileName = getFileNameFromUrl(url) + // 构建完整URL + return `http://localhost:3000/uploads/courses/videos/${fileName}` + } + + // 设置表单数据 + const fileName = getFileNameFromUrl(row.cover_image) + const videoFileName = getFileNameFromUrl(row.video) + form.value = { id: row.id, title: row.title, category: row.category, - cover_image: row.cover_image, - cover_image_url: row.cover_image ? ( - row.cover_image.startsWith('http') - ? row.cover_image - : `http://localhost:3000/uploads/courses/images/${row.cover_image}` - ) : '', - video: row.video || '', // 保存视频文件名 - video_url: row.video ? ( - row.video.startsWith('http') - ? row.video - : `http://localhost:3000/uploads/courses/videos/${row.video}` - ) : '', // 完整的视频URL用于预览 + cover_image: fileName, // 只保存文件名 + cover_image_url: `http://localhost:3000/uploads/courses/images/${fileName}`, // 完整URL用于预览 + video: videoFileName, // 只保存文件名 + video_url: `http://localhost:3000/uploads/courses/videos/${videoFileName}`, // 完整URL用于预览 video_duration: row.video_duration || 0, video_size: row.video_size || 0, description: row.description || '', @@ -285,7 +400,7 @@ const handleEdit = (row) => { imageInputType: 'upload', videoInputType: 'upload' } - console.log('编辑表单数据:', form.value) + dialogVisible.value = true } @@ -402,10 +517,27 @@ const handleImageTypeChange = () => { form.value.cover_image = '' } -// 处理图片错误 +// 修改图片错误处理函数 const handleImageError = (e) => { console.error('图片加载失败:', e) - ElMessage.warning('图片加载失败,但不影响保存') + const img = e.target + if (!img || !form.value.cover_image) return + + // 防止死循环:记录重试次数 + if (!img.dataset.retryCount) { + img.dataset.retryCount = '1' + } else if (Number(img.dataset.retryCount) >= 2) { + // 如果已经重试两次,就不再重试 + console.warn('图片加载失败,已达到最大重试次数') + return + } + + // 获取正确的文件名 + const fileName = getFileNameFromUrl(form.value.cover_image) + // 使用新的URL重试 + img.src = `http://localhost:3000/uploads/courses/images/${fileName}` + // 增加重试计数 + img.dataset.retryCount = String(Number(img.dataset.retryCount) + 1) } // 处理视频上传