This commit is contained in:
2025-11-29 21:53:17 +08:00
parent d9f3103304
commit 853bedcb23
12 changed files with 239 additions and 284 deletions

View File

@@ -12,6 +12,7 @@ import { InboxOutlined, SoundOutlined, LoadingOutlined } from '@ant-design/icons
import { VoiceService } from '@/api/voice'
import { MaterialService } from '@/api/material'
import { createDigitalHumanTask, getDigitalHumanTask, cancelTask, retryTask } from '@/api/digitalHuman'
import { extractVideoCover } from '@/utils/video-cover'
// 导入 voiceStore 用于获取用户音色
import { useVoiceCopyStore } from '@/stores/voiceCopy'
@@ -381,8 +382,22 @@ const handleVideoUpload = async (file) => {
try {
uploadedVideo.value = await toDataURL(file)
uploadedVideoFile.value = file // 保存文件对象
// 提取视频封面
try {
const cover = await extractVideoCover(file, {
maxWidth: 800,
quality: 0.8
})
uploadedVideoFile.value.coverBase64 = cover.base64 // 保存封面到文件对象
} catch (coverError) {
console.warn('视频封面提取失败:', coverError)
// 封面提取失败不影响主流程
}
message.success('视频上传成功')
} catch (error) {
console.error('视频上传失败:', error)
message.error('视频上传失败')
}
return false
@@ -489,7 +504,9 @@ const generateVideo = async () => {
// 上传视频文件到后端
const uploadVideoFile = async (file) => {
try {
const res = await MaterialService.uploadFile(file, 'video')
// 获取封面base64
const coverBase64 = file.coverBase64 || null
const res = await MaterialService.uploadFile(file, 'video', coverBase64)
if (res.code === 0) {
return res.data // res.data就是文件ID
} else {

View File

@@ -216,7 +216,6 @@ import MaterialBatchGroupModal from '@/components/material/MaterialBatchGroupMod
import MaterialMixModal from '@/components/material/MaterialMixModal.vue'
import { formatFileSize, formatDate } from '@/utils/file'
import { MixTaskService } from '@/api/mixTask'
import coverCache from '@/utils/coverCache'
// 数据
const loading = ref(false)
@@ -230,7 +229,6 @@ const mixing = ref(false)
// 分组相关
const groupModalVisible = ref(false)
const groupList = ref([])
const selectedGroupId = ref(null)
const groupingFileId = ref(null) // 当前正在分组的单个文件ID
// 获取单个文件分组的文件名
@@ -249,7 +247,6 @@ const getGroupName = (groupId) => {
// 混剪相关
const mixModalRef = ref(null) // 混剪模态框的 ref
const allAudioFiles = ref([]) // 所有音频文件
// 筛选条件
const filters = reactive({
@@ -293,52 +290,8 @@ const loadFileList = async () => {
if (res.code === 0) {
const files = res.data.list || []
// 优先从缓存获取封面避免重复请求OSS
const coverList = []
files.forEach(file => {
// 视频文件只使用缓存的coverBase64绝对不使用coverUrl
// 所有视频都不允许从OSS获取封面包括generate/其他分类)
if (file.isVideo) {
// 从缓存获取coverBase64
const cachedCover = coverCache.getCover(file.id)
if (cachedCover) {
file.coverBase64 = cachedCover
} else if (file.coverBase64) {
// 服务端返回了coverBase64保存到缓存
coverCache.setCover(file.id, file.coverBase64)
} else {
// 没有缓存和base64设置空值
file.coverBase64 = null
}
// 彻底删除coverUrl防止任何OSS请求
delete file.coverUrl
// 即使有previewUrl也不给视频使用
if (file.previewUrl && !file.coverBase64) {
delete file.previewUrl
}
}
// 收集有coverBase64的文件用于批量缓存
if (file.coverBase64) {
coverList.push({ fileId: file.id, base64: file.coverBase64 })
}
})
// 批量保存缓存(仅保存还没有缓存的文件)
if (coverList.length > 0) {
coverCache.batchSetCovers(coverList)
}
fileList.value = files
pagination.total = res.data.total || 0
// 输出缓存统计信息(开发环境)
if (process.env.NODE_ENV === 'development') {
const stats = coverCache.getStats()
console.log(`[MaterialList] 封面缓存统计: 总数${stats.total}, 有效${stats.valid}, 过期${stats.expired}`)
}
} else {
message.error(res.msg || '加载失败')
}
@@ -411,9 +364,6 @@ const handleBatchDelete = () => {
await MaterialService.deleteFiles(selectedFileIds.value)
message.success('删除成功')
// 清除所有封面缓存(简化处理)
coverCache.clearAll()
selectedFileIds.value = []
loadFileList()
} catch (error) {
@@ -453,6 +403,7 @@ const handleDeleteFile = (file) => {
// 下载文件
const handleDownloadFile = (file) => {
console.log('下载文件:', file)
if (!file?.previewUrl) {
message.warning('文件地址无效')
return
@@ -534,31 +485,12 @@ const handleOpenMixModal = async () => {
// 重置混剪表单(调用子组件方法)
mixModalRef.value?.resetForm()
// 加载所有音频文件和分组列表
await Promise.all([
loadAllAudioFiles(),
loadGroupList() // 重新加载分组列表,确保显示最新数据
])
// 加载分组列表
await loadGroupList()
mixModalVisible.value = true
}
// 加载所有音频文件
const loadAllAudioFiles = async () => {
try {
const res = await MaterialService.getFilePage({
pageNo: 1,
pageSize: 100,
fileCategory: 'audio'
})
if (res.code === 0) {
allAudioFiles.value = res.data.list || []
}
} catch (error) {
console.error('加载音频文件失败:', error)
}
}
const handleMixCancel = () => {
mixModalVisible.value = false
}
@@ -566,7 +498,16 @@ const handleMixCancel = () => {
const handleMixConfirm = async (params) => {
mixing.value = true
try {
const { data } = await MixTaskService.createTask(params)
// 纯画面模式:仅传入 title 和 videoUrls
const { title, videoUrls } = params
const taskParams = {
title,
videoUrls,
produceCount: 1 // 固定生成1个
}
const { data } = await MixTaskService.createTask(taskParams)
if (data) {
message.success('混剪任务提交成功,正在处理中...')
mixModalVisible.value = false
@@ -631,8 +572,8 @@ const handleSingleGroup = (file) => {
}
// 执行批量分组
const handleBatchGroup = async () => {
if (!selectedGroupId.value) {
const handleBatchGroup = async (groupId) => {
if (!groupId) {
message.warning('请选择分组')
return
}
@@ -653,13 +594,12 @@ const handleBatchGroup = async () => {
await MaterialGroupService.addFilesToGroups({
fileIds: fileIds,
groupIds: [selectedGroupId.value]
groupIds: [groupId]
})
message.success(successMessage)
// 重置状态
groupModalVisible.value = false
selectedGroupId.value = null
groupingFileId.value = null
// 如果是批量分组,清除选中状态
@@ -677,7 +617,6 @@ const handleBatchGroup = async () => {
// 取消分组操作
const handleGroupCancel = () => {
groupModalVisible.value = false
selectedGroupId.value = null
groupingFileId.value = null
}
</script>