feat: enhance sidebar quota display with progress bar and improve upload modal UX

- Replace percentage-based quota with point-based display in sidebar
- Add visual progress bar for remaining quota with gradient styling
- Implement upload progress tracking in material upload modal
- Add loading indicators and progress information during file uploads
- Prevent modal interaction while uploading by disabling close controls
- Show current upload status including file index and completion percentage
This commit is contained in:
2026-03-03 22:15:06 +08:00
parent 2c8664b41e
commit 7b32191987
4 changed files with 329 additions and 67 deletions

View File

@@ -241,8 +241,8 @@
<MaterialUploadModal
v-model:visible="uploadModalVisible"
:group-id="selectedGroupId"
:uploading="uploadLoading"
@confirm="handleFileUpload"
:file-category="activeCategory === 'DIGITAL_HUMAN' ? 'digital_human' : 'video'"
@complete="handleUploadComplete"
/>
<!-- 新建分组弹窗 -->
@@ -284,7 +284,6 @@ import {
import { message, Modal } from 'ant-design-vue';
import MaterialUploadModal from '@/components/material/MaterialUploadModal.vue';
import MaterialService, { MaterialGroupService } from '@/api/material';
import { useUpload } from '@/composables/useUpload';
import FullWidthLayout from '@/layouts/components/FullWidthLayout.vue';
import { useUserStore } from '@/stores/user';
@@ -302,7 +301,6 @@ const searchKeyword = ref('')
// 模态框状态
const uploadModalVisible = ref(false)
const uploadLoading = ref(false)
const createGroupModalVisible = ref(false)
// 表单数据
@@ -329,9 +327,6 @@ const pagination = reactive({
total: 0
})
// Hooks
const { upload } = useUpload()
// 方法
const handleCategoryChange = async (category) => {
activeCategory.value = category
@@ -557,46 +552,15 @@ const handleOpenUploadModal = () => {
uploadModalVisible.value = true
}
const handleFileUpload = async (filesWithCover, category, groupId) => {
try {
uploadLoading.value = true
// 根据当前分类确定 fileCategory
// 混剪素材用 video数字人素材用 digital_human
const fileCategory = activeCategory.value === 'DIGITAL_HUMAN' ? 'digital_human' : 'video'
// 数字人素材不关联分组
const uploadGroupId = activeCategory.value === 'DIGITAL_HUMAN' ? null : groupId
for (const fileWithCover of filesWithCover) {
await upload(fileWithCover.file, {
fileCategory,
groupId: uploadGroupId,
coverBase64: fileWithCover.coverBase64,
onStart: () => {},
onProgress: () => {},
onSuccess: (id) => {
console.log('文件上传成功:', id)
},
onError: (error) => {
message.error(error.message || '上传失败')
}
})
}
message.success(`成功上传 ${filesWithCover.length} 个文件`)
uploadModalVisible.value = false
await loadFileList()
// 刷新存储配额
await userStore.fetchUserProfile()
// 混剪素材才刷新分组列表
if (activeCategory.value === 'MIX') {
await loadGroupList()
}
} catch (error) {
console.error("文件上传失败:", error)
message.error("文件上传失败: " + (error.message || "未知错误"))
} finally {
uploadLoading.value = false
// 上传完成后的回调
const handleUploadComplete = async ({ successCount, failCount }) => {
// 刷新文件列表
await loadFileList()
// 刷新存储配额
await userStore.fetchUserProfile()
// 混剪素材才刷新分组列表
if (activeCategory.value === 'MIX') {
await loadGroupList()
}
}