Commit 36f6d06a by lijiabin

【需求 20331】 perf: 优化上传视频相关的内容

parent 44b3ef9d
......@@ -36,24 +36,26 @@
</div>
<!-- 上传完成 -->
<div v-if="videoInfo && !uploading" class="upload-success">
<div class="video-preview">
<video
:src="videoInfo.url"
poster="@/assets/img/culture/ask.png"
class="video-thumbnail"
muted
></video>
<div class="video-overlay">
<el-button type="primary" size="small" @click="replaceVideo"> 重新选择 </el-button>
<div v-if="videoInfo && !uploading" class="upload-success-optimized">
<div class="video-info-display">
<div class="video-icon-wrapper">
<el-icon class="video-preview-icon"><IEpVideoCamera /></el-icon>
</div>
<div class="video-details-text">
<p class="video-name">{{ videoInfo.name }}</p>
<p class="video-meta">
{{ formatFileSize(videoInfo.size) }} · {{ videoInfo.duration }} ·
{{ videoInfo.resolution }}
</p>
</div>
</div>
<div class="video-details">
<p class="video-name">{{ videoInfo.name }}</p>
<p class="video-meta">
{{ formatFileSize(videoInfo.size) }} · {{ videoInfo.duration }} ·
{{ videoInfo.resolution }}
</p>
<div class="video-actions">
<el-button type="primary" @click="replaceVideo">
<el-icon class="mr-2"><IEpRefresh /></el-icon> 重新选择
</el-button>
<el-button type="success" @click="previewVideo">
<el-icon class="mr-2"><IEpView /></el-icon> 预览播放
</el-button>
</div>
</div>
</el-upload>
......@@ -71,6 +73,7 @@
import { uploadFile as uploadFileApi } from '@/api/common'
import type { UploadFile } from 'element-plus'
import type { UploadVideoProps } from './types'
import { getVideoMetadata } from '@/utils'
interface VideoInfo {
url: string
......@@ -108,30 +111,6 @@ const formatFileSize = (bytes: number): string => {
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
// 获取视频时长和分辨率
const getVideoMetadata = (file: File): Promise<{ duration: string; resolution: string }> => {
return new Promise((resolve) => {
const video = document.createElement('video')
video.preload = 'metadata'
video.onloadedmetadata = () => {
const duration = formatDuration(video.duration)
const resolution = `${video.videoWidth}x${video.videoHeight}`
URL.revokeObjectURL(video.src)
resolve({ duration, resolution })
}
video.src = URL.createObjectURL(file)
})
}
// 格式化时长
const formatDuration = (seconds: number): string => {
const mins = Math.floor(seconds / 60)
const secs = Math.floor(seconds % 60)
return `${mins}:${secs.toString().padStart(2, '0')}`
}
// 上传前验证
const beforeUpload = (file: File): boolean => {
uploadError.value = ''
......@@ -185,7 +164,7 @@ const startUpload = async () => {
console.log(data)
// 获取视频元数据
const metadata = await getVideoMetadata(currentFile.value)
const metadata = await getVideoMetadata(data.filePath)
// 根据你的 API 返回结构调整
const videoData: VideoInfo = {
......@@ -235,6 +214,11 @@ const replaceVideo = () => {
currentFile.value = null
}
// 预览播放
const previewVideo = () => {
window.open(videoInfo.value?.url, '_blank')
}
// 重试上传
const retryUpload = () => {
uploadError.value = ''
......@@ -472,4 +456,52 @@ defineExpose({
height: 90px;
}
}
.upload-success-optimized {
display: flex;
flex-direction: column; /* Stack video info and actions vertically */
align-items: center; /* Center content horizontally */
justify-content: center;
padding: 20px 40px; /* Add some internal padding */
gap: 15px; /* Space between video info and actions */
}
.video-info-display {
display: flex;
align-items: center; /* Vertically align icon and text */
gap: 15px; /* Space between icon and text */
}
.video-icon-wrapper {
font-size: 48px; /* Larger icon size */
color: #6366f1;
}
.video-details-text {
text-align: left; /* Align text within its container */
}
.video-name {
font-size: 16px;
font-weight: bold;
color: #303133; /* Darker color for prominence */
margin-bottom: 5px;
word-break: break-all; /* Ensure long file names wrap */
}
.video-meta {
font-size: 13px;
color: #909399; /* Lighter color for secondary info */
}
.video-actions {
display: flex;
gap: 10px; /* Space between buttons */
margin-top: 10px; /* Space above buttons if stacked below video info */
}
.upload-success-optimized {
flex-direction: row;
justify-content: space-between;
}
</style>
......@@ -85,3 +85,34 @@ export function jumpToArticleDetailPage({ type, id }: { type: ArticleTypeEnum; i
window.open(`/articleDetail/${id}`)
}
}
// 根据oss视频链接获取视频元信息
export function getVideoMetadata(url: string): Promise<{
duration: string
resolution: string
}> {
return new Promise((resolve, reject) => {
const video = document.createElement('video')
video.src = url
video.preload = 'metadata'
video.addEventListener('loadedmetadata', () => {
const duration = formatDuration(video.duration)
const resolution = `${video.videoWidth}x${video.videoHeight}`
resolve({
duration,
resolution,
})
})
video.addEventListener('error', () => {
reject(new Error('视频加载失败'))
})
})
}
// 格式化视频时长
export function formatDuration(seconds: number): string {
const mins = Math.floor(seconds / 60)
const secs = Math.floor(seconds % 60)
return `${mins}:${secs.toString().padStart(2, '0')}`
}
......@@ -105,7 +105,7 @@
主标签
<el-tooltip content="主标签最多添加一个" placement="top">
<el-icon class="text-gray-400 cursor-help">
<QuestionFilled />
<IEpQuestionFilled />
</el-icon>
</el-tooltip>
</label>
......@@ -119,7 +119,7 @@
副标签
<el-tooltip content="副标签最多添加3个" placement="top">
<el-icon class="text-gray-400 cursor-help">
<QuestionFilled />
<IEpQuestionFilled />
</el-icon>
</el-tooltip>
</label>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment