|
|
@@ -7,18 +7,16 @@
|
|
|
:loading="uploading"
|
|
|
@click="handleFileUploadClick"
|
|
|
class="upload-btn"
|
|
|
- style="margin-right: 10px"
|
|
|
- >
|
|
|
+ style="margin-right: 10px">
|
|
|
<el-icon><Document /></el-icon>
|
|
|
{{ uploading ? '文件上传中...' : '选择文件' }}
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
- v-if="showFolderButton"
|
|
|
+ v-if="canShowFolderButton"
|
|
|
type="success"
|
|
|
:loading="uploading"
|
|
|
@click="handleFolderUploadClick"
|
|
|
- class="upload-btn"
|
|
|
- >
|
|
|
+ class="upload-btn">
|
|
|
<el-icon><Folder /></el-icon>
|
|
|
{{ uploading ? '文件夹上传中...' : '选择文件夹' }}
|
|
|
</el-button>
|
|
|
@@ -30,24 +28,15 @@
|
|
|
accept="*"
|
|
|
:webkitdirectory="isFolderMode"
|
|
|
:directory="isFolderMode"
|
|
|
- @change="handleFileChange"
|
|
|
- />
|
|
|
+ @change="handleFileChange" />
|
|
|
<p class="upload-hint">{{ uploadHintText }}</p>
|
|
|
</div>
|
|
|
|
|
|
<!-- 上传列表与进度 - 保持不变 -->
|
|
|
<el-card v-if="uploadList.length > 0" class="upload-list-card">
|
|
|
- <el-table
|
|
|
- :data="uploadList"
|
|
|
- border
|
|
|
- style="width: 100%; margin-bottom: 0px;"
|
|
|
- >
|
|
|
+ <el-table :data="uploadList" border style="width: 100%; margin-bottom: 0px">
|
|
|
<!-- 表格内容保持不变 -->
|
|
|
- <el-table-column
|
|
|
- prop="name"
|
|
|
- label="文件名/文件夹名"
|
|
|
- width="300"
|
|
|
- >
|
|
|
+ <el-table-column prop="name" label="文件名/文件夹名" width="300">
|
|
|
<template #default="scope">
|
|
|
<div class="file-name">
|
|
|
<el-icon v-if="scope.row.type === 'folder'"><Folder /></el-icon>
|
|
|
@@ -56,55 +45,37 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column
|
|
|
- prop="size"
|
|
|
- label="大小"
|
|
|
- width="120"
|
|
|
- :formatter="formatSize"
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- prop="type"
|
|
|
- label="类型"
|
|
|
- width="120"
|
|
|
- >
|
|
|
+ <el-table-column prop="size" label="大小" width="120" :formatter="formatSize" />
|
|
|
+ <el-table-column prop="type" label="类型" width="120">
|
|
|
<template #default="scope">
|
|
|
<el-tag size="small" :type="scope.row.type === 'folder' ? 'info' : 'primary'">
|
|
|
{{ scope.row.type || '文件夹' }}
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column
|
|
|
- prop="progress"
|
|
|
- label="进度"
|
|
|
- min-width="200"
|
|
|
- >
|
|
|
+ <el-table-column prop="progress" label="进度" min-width="200">
|
|
|
<template #default="scope">
|
|
|
<el-progress
|
|
|
:percentage="scope.row.progress"
|
|
|
:status="getProgressStatus(scope.row.status)"
|
|
|
- stroke-width="6"
|
|
|
- />
|
|
|
+ stroke-width="6" />
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="操作"
|
|
|
- width="120"
|
|
|
- >
|
|
|
+ <el-table-column label="操作" width="120">
|
|
|
<template #default="scope">
|
|
|
<el-button
|
|
|
v-if="scope.row.status === 'uploading'"
|
|
|
size="small"
|
|
|
type="text"
|
|
|
@click.stop="handleCancelUpload(scope.row)"
|
|
|
- text
|
|
|
- >
|
|
|
+ text>
|
|
|
取消
|
|
|
</el-button>
|
|
|
<el-icon v-if="scope.row.status === 'success'" color="#10b981">
|
|
|
-<!-- <CheckCircle />-->
|
|
|
+ <!-- <CheckCircle />-->
|
|
|
</el-icon>
|
|
|
<el-icon v-if="scope.row.status === 'error'" color="#ef4444">
|
|
|
-<!-- <CloseCircle />-->
|
|
|
+ <!-- <CloseCircle />-->
|
|
|
</el-icon>
|
|
|
<span v-if="scope.row.status === 'cancelled'">已取消</span>
|
|
|
</template>
|
|
|
@@ -113,11 +84,7 @@
|
|
|
</el-card>
|
|
|
|
|
|
<!-- 错误提示 - 保持不变 -->
|
|
|
- <el-dialog
|
|
|
- v-model="showErrorModal"
|
|
|
- title="上传错误"
|
|
|
- @close="showErrorModal = false"
|
|
|
- >
|
|
|
+ <el-dialog v-model="showErrorModal" title="上传错误" @close="showErrorModal = false">
|
|
|
<p>{{ errorMessage }}</p>
|
|
|
<template #footer>
|
|
|
<el-button @click="showErrorModal = false">确定</el-button>
|
|
|
@@ -127,17 +94,13 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, computed, onMounted } from 'vue';
|
|
|
-import {
|
|
|
- Upload,
|
|
|
- Folder,
|
|
|
- Document,
|
|
|
-} from '@element-plus/icons-vue';
|
|
|
+import { ref, computed, onMounted } from 'vue'
|
|
|
+import { Upload, Folder, Document } from '@element-plus/icons-vue'
|
|
|
|
|
|
// 组件参数 - 保持不变
|
|
|
const props = defineProps({
|
|
|
- deviceId:{
|
|
|
- type: String,
|
|
|
+ deviceId: {
|
|
|
+ type: String
|
|
|
},
|
|
|
allowFolderUpload: {
|
|
|
type: Boolean,
|
|
|
@@ -154,139 +117,142 @@ const props = defineProps({
|
|
|
},
|
|
|
uploadUrl: {
|
|
|
type: String,
|
|
|
- default: import.meta.env.VITE_BASE_URL+'/admin-api/rq/file/upload'
|
|
|
+ default: import.meta.env.VITE_BASE_URL + '/admin-api/rq/file/upload'
|
|
|
}
|
|
|
-});
|
|
|
+})
|
|
|
|
|
|
// 组件事件 - 保持不变
|
|
|
-const emit = defineEmits(['uploadSuccess', 'uploadError', 'uploadComplete']);
|
|
|
+const emit = defineEmits(['uploadSuccess', 'uploadError', 'uploadComplete'])
|
|
|
|
|
|
// 新增:用于区分当前是文件还是文件夹上传模式
|
|
|
-const isFolderMode = ref();
|
|
|
+const isFolderMode = ref()
|
|
|
|
|
|
// 状态管理 - 保持不变
|
|
|
-const fileInput = ref(null);
|
|
|
-const uploading = ref(false);
|
|
|
-const uploadList = ref([]);
|
|
|
-const showErrorModal = ref(false);
|
|
|
-const errorMessage = ref('');
|
|
|
-const uploadTasks = ref(new Map());
|
|
|
+const fileInput = ref(null)
|
|
|
+const uploading = ref(false)
|
|
|
+const uploadList = ref([])
|
|
|
+const showErrorModal = ref(false)
|
|
|
+const errorMessage = ref('')
|
|
|
+const uploadTasks = ref(new Map())
|
|
|
|
|
|
// 判断父组件是否传递了 showFolderButton 属性(而非判断其值)
|
|
|
-const hasShowFolderButton = Object.prototype.hasOwnProperty.call(props, 'showFolderButton');
|
|
|
+const hasShowFolderButton = Object.prototype.hasOwnProperty.call(props, 'showFolderButton')
|
|
|
+
|
|
|
+const canShowFolderButton = computed(() => {
|
|
|
+ return props.allowFolderUpload && props.showFolderButton
|
|
|
+})
|
|
|
|
|
|
// 根据是否传递属性决定显示的提示文本
|
|
|
const uploadHintText = computed(() => {
|
|
|
- return hasShowFolderButton
|
|
|
- ? '文件大小不能超过50M'
|
|
|
- : '单个文件夹总大小不能超过500M';
|
|
|
-});
|
|
|
+ return hasShowFolderButton ? '文件大小不能超过50M' : '单个文件夹总大小不能超过500M'
|
|
|
+})
|
|
|
|
|
|
// 获取进度条状态 - 保持不变
|
|
|
const getProgressStatus = (status) => {
|
|
|
- switch(status) {
|
|
|
+ switch (status) {
|
|
|
case 'success':
|
|
|
- return 'success';
|
|
|
+ return 'success'
|
|
|
case 'error':
|
|
|
- return 'exception';
|
|
|
+ return 'exception'
|
|
|
case 'uploading':
|
|
|
- return 'processing';
|
|
|
+ return 'processing'
|
|
|
default:
|
|
|
- return '';
|
|
|
+ return ''
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
// 格式化文件大小 - 保持不变
|
|
|
const formatSize = (row, column, bytes) => {
|
|
|
- if (bytes === 0) return '0 Bytes';
|
|
|
- const k = 1024;
|
|
|
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
|
- const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
|
-};
|
|
|
+ if (bytes === 0) return '0 Bytes'
|
|
|
+ const k = 1024
|
|
|
+ const sizes = ['Bytes', 'KB', 'MB', 'GB']
|
|
|
+ const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
|
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
|
|
+}
|
|
|
|
|
|
// 计算文件夹总大小 - 保持不变
|
|
|
const calculateFolderSize = (files) => {
|
|
|
- let totalSize = 0;
|
|
|
- files.forEach(file => {
|
|
|
- totalSize += file.size;
|
|
|
- });
|
|
|
- return totalSize;
|
|
|
-};
|
|
|
+ let totalSize = 0
|
|
|
+ files.forEach((file) => {
|
|
|
+ totalSize += file.size
|
|
|
+ })
|
|
|
+ return totalSize
|
|
|
+}
|
|
|
|
|
|
// 新增:文件上传按钮点击事件
|
|
|
const handleFileUploadClick = () => {
|
|
|
- if (uploading.value) return;
|
|
|
+ if (uploading.value) return
|
|
|
if (fileInput.value) {
|
|
|
- fileInput.value.value = '';
|
|
|
+ fileInput.value.value = ''
|
|
|
}
|
|
|
- isFolderMode.value = false; // 切换到文件模式
|
|
|
+ isFolderMode.value = false // 切换到文件模式
|
|
|
// 强制DOM更新后再触发点击
|
|
|
nextTick(() => {
|
|
|
- fileInput.value.click();
|
|
|
- });
|
|
|
-};
|
|
|
+ fileInput.value.click()
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
// 新增:文件夹上传按钮点击事件
|
|
|
const handleFolderUploadClick = () => {
|
|
|
- if (uploading.value) return;
|
|
|
+ if (uploading.value) return
|
|
|
if (fileInput.value) {
|
|
|
- fileInput.value.value = '';
|
|
|
+ fileInput.value.value = ''
|
|
|
}
|
|
|
- isFolderMode.value = true; // 切换到文件夹模式
|
|
|
+ isFolderMode.value = true // 切换到文件夹模式
|
|
|
if (!props.allowFolderUpload) {
|
|
|
- errorMessage.value = '不允许上传文件夹';
|
|
|
- showErrorModal.value = true;
|
|
|
- return;
|
|
|
+ errorMessage.value = '不允许上传文件夹'
|
|
|
+ showErrorModal.value = true
|
|
|
+ return
|
|
|
}
|
|
|
// 强制DOM更新后再触发点击
|
|
|
nextTick(() => {
|
|
|
- fileInput.value.click();
|
|
|
- });
|
|
|
-};
|
|
|
+ fileInput.value.click()
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
// 处理文件选择 - 保持不变
|
|
|
const handleFileChange = async (e) => {
|
|
|
- const files = Array.from(e.target.files);
|
|
|
- if (files.length === 0) return;
|
|
|
+ const files = Array.from(e.target.files)
|
|
|
+ if (files.length === 0) return
|
|
|
|
|
|
// 清空input值,允许重复选择同一文件
|
|
|
- e.target.value = '';
|
|
|
+ e.target.value = ''
|
|
|
|
|
|
// 检查是否包含文件夹(根据当前模式判断)
|
|
|
- const hasFolders = isFolderMode.value && files.some(file => file.webkitRelativePath.includes('/'));
|
|
|
+ const hasFolders =
|
|
|
+ isFolderMode.value && files.some((file) => file.webkitRelativePath.includes('/'))
|
|
|
|
|
|
if (hasFolders) {
|
|
|
// 按文件夹分组
|
|
|
- const folderMap = new Map();
|
|
|
+ const folderMap = new Map()
|
|
|
|
|
|
- files.forEach(file => {
|
|
|
+ files.forEach((file) => {
|
|
|
// 提取文件夹路径
|
|
|
- const relativePath = file.webkitRelativePath;
|
|
|
- const folderPath = relativePath.substring(0, relativePath.lastIndexOf('/') + 1);
|
|
|
+ const relativePath = file.webkitRelativePath
|
|
|
+ const folderPath = relativePath.substring(0, relativePath.lastIndexOf('/') + 1)
|
|
|
|
|
|
if (!folderMap.has(folderPath)) {
|
|
|
- folderMap.set(folderPath, []);
|
|
|
+ folderMap.set(folderPath, [])
|
|
|
}
|
|
|
- folderMap.get(folderPath).push(file);
|
|
|
- });
|
|
|
+ folderMap.get(folderPath).push(file)
|
|
|
+ })
|
|
|
|
|
|
// 检查每个文件夹大小
|
|
|
for (const [folderPath, folderFiles] of folderMap) {
|
|
|
- const folderSize = calculateFolderSize(folderFiles);
|
|
|
- const folderSizeMB = folderSize / (1024 * 1024);
|
|
|
+ const folderSize = calculateFolderSize(folderFiles)
|
|
|
+ const folderSizeMB = folderSize / (1024 * 1024)
|
|
|
|
|
|
if (folderSizeMB > props.maxFolderSize) {
|
|
|
- errorMessage.value = `文件夹 "${folderPath}" 大小超过${props.maxFolderSize}M限制,无法上传`;
|
|
|
- showErrorModal.value = true;
|
|
|
- return;
|
|
|
+ errorMessage.value = `文件夹 "${folderPath}" 大小超过${props.maxFolderSize}M限制,无法上传`
|
|
|
+ showErrorModal.value = true
|
|
|
+ return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 添加文件夹到上传列表
|
|
|
folderMap.forEach((folderFiles, folderPath) => {
|
|
|
- const folderSize = calculateFolderSize(folderFiles);
|
|
|
- const uid = Date.now() + Math.random().toString(36).substr(2, 9);
|
|
|
+ const folderSize = calculateFolderSize(folderFiles)
|
|
|
+ const uid = Date.now() + Math.random().toString(36).substr(2, 9)
|
|
|
|
|
|
uploadList.value.push({
|
|
|
uid,
|
|
|
@@ -296,11 +262,11 @@ const handleFileChange = async (e) => {
|
|
|
progress: 0,
|
|
|
status: 'wait',
|
|
|
files: folderFiles
|
|
|
- });
|
|
|
- });
|
|
|
+ })
|
|
|
+ })
|
|
|
} else {
|
|
|
// 单个或多个文件
|
|
|
- files.forEach(file => {
|
|
|
+ files.forEach((file) => {
|
|
|
uploadList.value.push({
|
|
|
uid: Date.now() + Math.random().toString(36).substr(2, 9),
|
|
|
name: file.name,
|
|
|
@@ -309,156 +275,155 @@ const handleFileChange = async (e) => {
|
|
|
progress: 0,
|
|
|
status: 'wait',
|
|
|
files: [file]
|
|
|
- });
|
|
|
- });
|
|
|
+ })
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
// 开始上传
|
|
|
- await startUpload();
|
|
|
-};
|
|
|
+ await startUpload()
|
|
|
+}
|
|
|
|
|
|
// 开始上传 - 保持不变
|
|
|
const startUpload = async () => {
|
|
|
- uploading.value = true;
|
|
|
+ uploading.value = true
|
|
|
|
|
|
// 过滤出等待上传的文件/文件夹
|
|
|
- const pendingFiles = uploadList.value.filter(item => item.status === 'wait');
|
|
|
+ const pendingFiles = uploadList.value.filter((item) => item.status === 'wait')
|
|
|
|
|
|
for (const fileItem of pendingFiles) {
|
|
|
try {
|
|
|
// 创建FormData
|
|
|
- const formData = new FormData();
|
|
|
+ const formData = new FormData()
|
|
|
|
|
|
// 添加文件
|
|
|
- fileItem.files.forEach(file => {
|
|
|
- formData.append('files', file, file.webkitRelativePath || file.name);
|
|
|
- });
|
|
|
+ fileItem.files.forEach((file) => {
|
|
|
+ formData.append('files', file, file.webkitRelativePath || file.name)
|
|
|
+ })
|
|
|
|
|
|
// 添加文件夹标识和路径
|
|
|
if (fileItem.type === 'folder') {
|
|
|
- formData.append('isFolder', 'true');
|
|
|
- formData.append('folderPath', fileItem.name);
|
|
|
+ formData.append('isFolder', 'true')
|
|
|
+ formData.append('folderPath', fileItem.name)
|
|
|
}
|
|
|
|
|
|
// 创建上传任务
|
|
|
- const xhr = new XMLHttpRequest();
|
|
|
- uploadTasks.value.set(fileItem.uid, xhr);
|
|
|
+ const xhr = new XMLHttpRequest()
|
|
|
+ uploadTasks.value.set(fileItem.uid, xhr)
|
|
|
|
|
|
// 监听进度
|
|
|
xhr.upload.addEventListener('progress', (e) => {
|
|
|
if (e.lengthComputable) {
|
|
|
- const percent = Math.round((e.loaded / e.total) * 100);
|
|
|
- const index = uploadList.value.findIndex(item => item.uid === fileItem.uid);
|
|
|
+ const percent = Math.round((e.loaded / e.total) * 100)
|
|
|
+ const index = uploadList.value.findIndex((item) => item.uid === fileItem.uid)
|
|
|
if (index !== -1) {
|
|
|
- uploadList.value[index].progress = percent;
|
|
|
- uploadList.value[index].status = 'uploading';
|
|
|
+ uploadList.value[index].progress = percent
|
|
|
+ uploadList.value[index].status = 'uploading'
|
|
|
}
|
|
|
}
|
|
|
- });
|
|
|
+ })
|
|
|
|
|
|
// 监听完成
|
|
|
xhr.addEventListener('load', () => {
|
|
|
- const index = uploadList.value.findIndex(item => item.uid === fileItem.uid);
|
|
|
+ const index = uploadList.value.findIndex((item) => item.uid === fileItem.uid)
|
|
|
if (index !== -1) {
|
|
|
if (xhr.status >= 200 && xhr.status < 300) {
|
|
|
- uploadList.value[index].status = 'success';
|
|
|
- uploadList.value[index].progress = 100;
|
|
|
+ uploadList.value[index].status = 'success'
|
|
|
+ uploadList.value[index].progress = 100
|
|
|
emit('uploadSuccess', {
|
|
|
uid: fileItem.uid,
|
|
|
name: fileItem.name,
|
|
|
response: JSON.parse(xhr.responseText)
|
|
|
- });
|
|
|
+ })
|
|
|
} else {
|
|
|
- uploadList.value[index].status = 'error';
|
|
|
+ uploadList.value[index].status = 'error'
|
|
|
emit('uploadError', {
|
|
|
uid: fileItem.uid,
|
|
|
name: fileItem.name,
|
|
|
error: new Error(`上传失败: ${xhr.statusText}`)
|
|
|
- });
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
- uploadTasks.value.delete(fileItem.uid);
|
|
|
- });
|
|
|
+ uploadTasks.value.delete(fileItem.uid)
|
|
|
+ })
|
|
|
|
|
|
// 监听错误
|
|
|
xhr.addEventListener('error', () => {
|
|
|
- const index = uploadList.value.findIndex(item => item.uid === fileItem.uid);
|
|
|
+ const index = uploadList.value.findIndex((item) => item.uid === fileItem.uid)
|
|
|
if (index !== -1) {
|
|
|
- uploadList.value[index].status = 'error';
|
|
|
+ uploadList.value[index].status = 'error'
|
|
|
emit('uploadError', {
|
|
|
uid: fileItem.uid,
|
|
|
name: fileItem.name,
|
|
|
error: new Error('网络错误,上传失败')
|
|
|
- });
|
|
|
+ })
|
|
|
}
|
|
|
- uploadTasks.value.delete(fileItem.uid);
|
|
|
- });
|
|
|
+ uploadTasks.value.delete(fileItem.uid)
|
|
|
+ })
|
|
|
|
|
|
// 发送请求
|
|
|
- xhr.open('POST', props.uploadUrl, true);
|
|
|
- xhr.setRequestHeader('tenant-id', 1);
|
|
|
- xhr.setRequestHeader('device-id', props.deviceId);
|
|
|
- xhr.send(formData);
|
|
|
-
|
|
|
+ xhr.open('POST', props.uploadUrl, true)
|
|
|
+ xhr.setRequestHeader('tenant-id', 1)
|
|
|
+ xhr.setRequestHeader('device-id', props.deviceId)
|
|
|
+ xhr.send(formData)
|
|
|
} catch (error) {
|
|
|
- console.error('上传失败', error);
|
|
|
- const index = uploadList.value.findIndex(item => item.uid === fileItem.uid);
|
|
|
+ console.error('上传失败', error)
|
|
|
+ const index = uploadList.value.findIndex((item) => item.uid === fileItem.uid)
|
|
|
if (index !== -1) {
|
|
|
- uploadList.value[index].status = 'error';
|
|
|
+ uploadList.value[index].status = 'error'
|
|
|
}
|
|
|
emit('uploadError', {
|
|
|
uid: fileItem.uid,
|
|
|
name: fileItem.name,
|
|
|
error
|
|
|
- });
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 检查是否所有上传都已完成
|
|
|
const checkUploadComplete = setInterval(() => {
|
|
|
- const allCompleted = uploadList.value.every(item =>
|
|
|
- item.status === 'success' || item.status === 'error' || item.status === 'cancelled'
|
|
|
- );
|
|
|
+ const allCompleted = uploadList.value.every(
|
|
|
+ (item) => item.status === 'success' || item.status === 'error' || item.status === 'cancelled'
|
|
|
+ )
|
|
|
|
|
|
if (allCompleted) {
|
|
|
- clearInterval(checkUploadComplete);
|
|
|
- uploading.value = false;
|
|
|
- emit('uploadComplete');
|
|
|
+ clearInterval(checkUploadComplete)
|
|
|
+ uploading.value = false
|
|
|
+ emit('uploadComplete')
|
|
|
}
|
|
|
- }, 1000);
|
|
|
-};
|
|
|
+ }, 1000)
|
|
|
+}
|
|
|
|
|
|
// 取消上传 - 保持不变
|
|
|
const handleCancelUpload = (fileItem) => {
|
|
|
- const xhr = uploadTasks.value.get(fileItem.uid);
|
|
|
+ const xhr = uploadTasks.value.get(fileItem.uid)
|
|
|
if (xhr) {
|
|
|
- xhr.abort();
|
|
|
- uploadTasks.value.delete(fileItem.uid);
|
|
|
+ xhr.abort()
|
|
|
+ uploadTasks.value.delete(fileItem.uid)
|
|
|
}
|
|
|
|
|
|
- const index = uploadList.value.findIndex(item => item.uid === fileItem.uid);
|
|
|
+ const index = uploadList.value.findIndex((item) => item.uid === fileItem.uid)
|
|
|
if (index !== -1) {
|
|
|
- uploadList.value[index].status = 'cancelled';
|
|
|
+ uploadList.value[index].status = 'cancelled'
|
|
|
}
|
|
|
|
|
|
// 检查是否还有正在上传的任务
|
|
|
- const hasUploading = uploadList.value.some(item => item.status === 'uploading');
|
|
|
+ const hasUploading = uploadList.value.some((item) => item.status === 'uploading')
|
|
|
if (!hasUploading) {
|
|
|
- uploading.value = false;
|
|
|
+ uploading.value = false
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
// 组件挂载时设置样式 - 保持不变
|
|
|
onMounted(() => {
|
|
|
- const container = document.querySelector('.file-upload-container');
|
|
|
+ const container = document.querySelector('.file-upload-container')
|
|
|
if (container) {
|
|
|
- container.style.height = '8vh';
|
|
|
- container.style.display = 'flex';
|
|
|
- container.style.flexDirection = 'column';
|
|
|
- container.style.padding = '20px';
|
|
|
- container.style.boxSizing = 'border-box';
|
|
|
+ container.style.height = '8vh'
|
|
|
+ container.style.display = 'flex'
|
|
|
+ container.style.flexDirection = 'column'
|
|
|
+ container.style.padding = '20px'
|
|
|
+ container.style.boxSizing = 'border-box'
|
|
|
}
|
|
|
-});
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|