8/1 限制前端输入字数
This commit is contained in:
@@ -73,17 +73,21 @@
|
||||
ref="uploadRef"
|
||||
:show-file-list="true"
|
||||
name="files"
|
||||
:on-exceed="handleExceed"
|
||||
:headers="headerToken()"
|
||||
:on-remove="handleAvatarRemove"
|
||||
:on-change="handleProgress"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
accept=".doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.gif,.bmp,.webp"
|
||||
accept=".doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.gif,.bmp,.webp,.zip"
|
||||
>
|
||||
<div class="uploadBtn flex flex-items-center">
|
||||
<el-icon><Upload /></el-icon>
|
||||
<span>上传文件</span>
|
||||
</div>
|
||||
<template #tip>仅支持doc/docx/xls/xlsx/jpg/png/gif等</template>
|
||||
<template #tip>
|
||||
<div>仅支持doc/docx/xls/xlsx/jpg/png/gif/bmp/webp/zip等格式</div>
|
||||
<span style="font-size: smaller">最多上传 {{ MAX_FILE_COUNT }} 个文件</span>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -108,7 +112,7 @@ import { addHandleLog, getHandleLog, updateHandleLog, uploadAttachments } from '
|
||||
import { UploadFiles, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Upload } from '@element-plus/icons-vue'; // 确保引入图标
|
||||
import { Upload } from '@element-plus/icons-vue'; // 确保引入图标组件╬╬╬
|
||||
|
||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/handleLog/uploadAttachments';
|
||||
const route = useRoute();
|
||||
@@ -152,33 +156,29 @@ const handleAvatarRemove: UploadProps['onRemove'] = (uploadFile: UploadUserFile,
|
||||
};
|
||||
|
||||
// 定义大小限制常量 (单位: MB)
|
||||
const MAX_SINGLE_FILE_SIZE = 10 * 1024 * 1024; // 10MB in bytes
|
||||
const MAX_TOTAL_FILE_SIZE = 20 * 1024 * 1024; // 20MB in bytes
|
||||
const MAX_SINGLE_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
||||
const MAX_TOTAL_FILE_SIZE = 20 * 1024 * 1024; // 20MB
|
||||
const MAX_FILE_COUNT = 9; // 最大上传文件数量
|
||||
const uploadRef = ref();
|
||||
// 添加一个锁,防止 on-change 递归调用导致重复提示
|
||||
const isChecking = ref(false);
|
||||
const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => {
|
||||
ElMessage.warning(`最多只能上传 ${MAX_FILE_COUNT} 个文件,当前已上传 ${uploadFiles.length} 个文件`);
|
||||
};
|
||||
const handleProgress: UploadProps['onChange'] = (uploadFile: UploadUserFile, uploadFiles: UploadFiles) => {
|
||||
// 如果正在校验中,直接返回,避免重复执行
|
||||
// 先校验当前触发的文件类型
|
||||
if (!beforeAvatarUpload(uploadFile)) {
|
||||
uploadRef.value.handleRemove(uploadFile);
|
||||
uploadRef.value?.handleRemove(uploadFile);
|
||||
return;
|
||||
}
|
||||
if (isChecking.value) return;
|
||||
// 加锁
|
||||
isChecking.value = true;
|
||||
// 创建一个新数组来存储校验通过的文件
|
||||
|
||||
const validFiles: CustomUploadFile[] = [];
|
||||
let newFilesTotalSize = 0;
|
||||
let hasError = false;
|
||||
let errorMsg = '';
|
||||
|
||||
// 1. 遍历所有文件,筛选出符合单文件大小要求的文件,并计算新文件总大小
|
||||
// 遍历所有文件,校验新文件
|
||||
for (const file of uploadFiles) {
|
||||
// 只校验新上传的文件 (有 raw 属性)
|
||||
if (file.raw) {
|
||||
// 检查单个文件大小
|
||||
if (file.raw.size > MAX_SINGLE_FILE_SIZE) {
|
||||
// 如果发现单个文件超标,标记错误,并不将该文件加入 validFiles
|
||||
if (!hasError) {
|
||||
errorMsg = `文件 ${file.name} 大小超过 10MB,已自动移除`;
|
||||
hasError = true;
|
||||
@@ -187,57 +187,37 @@ const handleProgress: UploadProps['onChange'] = (uploadFile: UploadUserFile, upl
|
||||
}
|
||||
newFilesTotalSize += file.raw.size;
|
||||
}
|
||||
// 将非超标文件(包括旧文件和未超标的新文件)暂时加入
|
||||
console.log(file);
|
||||
validFiles.push({
|
||||
...file,
|
||||
ossId: (file as CustomUploadFile).ossId ?? null
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 如果存在单文件超标的情况,先处理这部分逻辑
|
||||
if (hasError) {
|
||||
ElMessage.error(errorMsg);
|
||||
// 更新 fileList 为移除了超标文件的列表
|
||||
fileList.value = validFiles;
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 检查新文件总大小是否超过 20MB
|
||||
if (newFilesTotalSize > MAX_TOTAL_FILE_SIZE) {
|
||||
ElMessage.error(`所有新上传文件的总大小不能超过 20MB,当前已选新文件总大小约为 ${(newFilesTotalSize / 1024 / 1024).toFixed(2)}MB`);
|
||||
|
||||
// 策略:移除最后添加的那个导致超标的文件
|
||||
// 注意:这里需要找到最后添加的那个文件。uploadFile 参数就是当前触发的文件
|
||||
// 但如果是一次性选择多个文件,uploadFile 可能是其中一个。
|
||||
// 更稳妥的方式是:如果总和超标,则移除所有新文件中最后加入的那个,或者提示用户手动减少。
|
||||
// 这里我们尝试移除最后加入的一个新文件
|
||||
|
||||
// 找出所有新文件
|
||||
const newFiles = validFiles.filter((f) => f.raw);
|
||||
if (newFiles.length > 0) {
|
||||
// 移除最后一个新文件
|
||||
const lastNewFile = newFiles[newFiles.length - 1];
|
||||
const filteredFiles = validFiles.filter((f) => f.uid !== lastNewFile.uid);
|
||||
fileList.value = filteredFiles;
|
||||
} else {
|
||||
// 理论上不会走到这里,因为如果没有新文件,总大小不会增加
|
||||
fileList.value = validFiles;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 校验全部通过,更新 fileList
|
||||
// 只有当 validFiles 与当前 fileList 不同时才赋值,避免不必要的触发
|
||||
if (validFiles.length !== fileList.value.length || validFiles.some((f, i) => f.uid !== fileList.value[i]?.uid)) {
|
||||
// 只有文件列表真正变化时才更新,避免不必要的响应式触发
|
||||
const currentList = fileList.value;
|
||||
if (validFiles.length !== currentList.length || validFiles.some((f, i) => f.uid !== currentList[i]?.uid)) {
|
||||
fileList.value = validFiles;
|
||||
}
|
||||
|
||||
// 解锁,允许下一次变更触发校验
|
||||
// 使用 nextTick 或 setTimeout 确保 DOM 更新后再解锁,防止极快连续操作的问题
|
||||
setTimeout(() => {
|
||||
isChecking.value = false;
|
||||
}, 100);
|
||||
};
|
||||
|
||||
const blockedExts = ['.exe', '.bat', '.cmd', '.msi'];
|
||||
@@ -259,6 +239,8 @@ const allowExts = [
|
||||
'.gif',
|
||||
'.bmp',
|
||||
'.webp',
|
||||
// archive
|
||||
'.zip',
|
||||
// 专业/矢量图
|
||||
'.psd',
|
||||
'.ai',
|
||||
@@ -389,7 +371,7 @@ function handleBack() {
|
||||
width: 100%;
|
||||
}
|
||||
&:deep(.el-upload-list) {
|
||||
max-height: 200px;
|
||||
max-height: 250px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user