feat:图片压缩

This commit is contained in:
yangmf_0726 committed 2025-10-16 16:34:24 +08:00
1 parent 72e9ded8e2
commit 21fde5a6e4
6 files changed
+130 -59

No files matched your search

+24 -21
View File
@@ -1,19 +1,8 @@
<template>
<div class="upload-box">
<el-upload
:id="uuid"
:accept="fileType.join(',')"
:action="uploadUrl"
:before-upload="beforeUpload"
:class="['upload', drag ? 'no-border' : '']"
:disabled="disabled"
:drag="drag"
:http-request="httpRequest"
:multiple="false"
:on-error="uploadError"
:on-success="uploadSuccess"
:show-file-list="false"
>
<el-upload :id="uuid" :accept="fileType.join(',')" :action="uploadUrl" :before-upload="beforeUpload"
:class="['upload', drag ? 'no-border' : '']" :disabled="disabled" :drag="drag" :http-request="httpRequest"
:multiple="false" :on-error="uploadError" :on-success="uploadSuccess" :show-file-list="false">
<template v-if="modelValue">
<img :src="modelValue" class="upload-image" />
<div class="upload-handle" @click.stop>
@@ -52,7 +41,7 @@ import type { UploadProps } from 'element-plus'
import { generateUUID } from '@/utils'
import { propTypes } from '@/utils/propTypes'
import { createImageViewer } from '@/components/ImageViewer'
import { useUpload } from '@/components/UploadFile/src/useUpload'
import { compressImage, useUpload } from '@/components/UploadFile/src/useUpload'
defineOptions({ name: 'UploadImg' })
@@ -106,15 +95,27 @@ const editImg = () => {
dom && dom.dispatchEvent(new MouseEvent('click'))
}
const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
const beforeUpload: UploadProps['beforeUpload'] = async (rawFile) => {
const imgSize = rawFile.size / 1024 / 1024 < props.fileSize
const imgType = props.fileType
if (!imgType.includes(rawFile.type as FileTypes))
message.notifyWarning('上传图片不符合所需的格式!')
if (!imgSize) message.notifyWarning(`上传图片大小不能超过 ${props.fileSize}M!`)
return imgType.includes(rawFile.type as FileTypes) && imgSize
}
if (!imgType.includes(rawFile.type as FileTypes)) {
message.notifyWarning('上传图片不符合所需的格式!')
return false
}
if (!imgSize) {
message.notifyWarning(`上传图片大小不能超过 ${props.fileSize}M!`)
return false
}
// ===== 新增:压缩图片 =====
try {
const compressed = await compressImage(rawFile, 0.8)
return compressed
} catch {
return rawFile // 失败则用原图
}
}
// 图片上传成功提示
const uploadSuccess: UploadProps['onSuccess'] = (res: any): void => {
message.success('上传成功')
@@ -129,6 +130,7 @@ const uploadError = () => {
<style lang="scss" scoped>
.is-error {
.upload {
:deep(.el-upload),
:deep(.el-upload-dragger) {
border: 1px dashed var(--el-color-danger) !important;
@@ -141,6 +143,7 @@ const uploadError = () => {
}
:deep(.disabled) {
.el-upload,
.el-upload-dragger {
cursor: not-allowed !important;
+24 -21
View File
@@ -1,21 +1,9 @@
<template>
<div class="upload-box">
<el-upload
v-model:file-list="fileList"
:accept="fileType.join(',')"
:action="uploadUrl"
:before-upload="beforeUpload"
:class="['upload', drag ? 'no-border' : '']"
:disabled="disabled"
:drag="drag"
:http-request="httpRequest"
:limit="limit"
:multiple="true"
:on-error="uploadError"
:on-exceed="handleExceed"
:on-success="uploadSuccess"
list-type="picture-card"
>
<el-upload v-model:file-list="fileList" :accept="fileType.join(',')" :action="uploadUrl"
:before-upload="beforeUpload" :class="['upload', drag ? 'no-border' : '']" :disabled="disabled" :drag="drag"
:http-request="httpRequest" :limit="limit" :multiple="true" :on-error="uploadError" :on-exceed="handleExceed"
:on-success="uploadSuccess" list-type="picture-card">
<div class="upload-empty">
<slot name="empty">
<Icon icon="ep:plus" />
@@ -47,7 +35,7 @@ import { ElNotification } from 'element-plus'
import { createImageViewer } from '@/components/ImageViewer'
import { propTypes } from '@/utils/propTypes'
import { useUpload } from '@/components/UploadFile/src/useUpload'
import { compressImage, useUpload } from '@/components/UploadFile/src/useUpload'
defineOptions({ name: 'UploadImgs' })
@@ -93,23 +81,36 @@ const uploadList = ref<UploadUserFile[]>([])
* @description 文件上传之前判断
* @param rawFile 上传的文件
* */
const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
const beforeUpload: UploadProps['beforeUpload'] = async (rawFile) => {
const imgSize = rawFile.size / 1024 / 1024 < props.fileSize
const imgType = props.fileType
if (!imgType.includes(rawFile.type as FileTypes))
if (!imgType.includes(rawFile.type as FileTypes)) {
ElNotification({
title: '温馨提示',
message: '上传图片不符合所需的格式!',
type: 'warning'
})
if (!imgSize)
return false
}
if (!imgSize) {
ElNotification({
title: '温馨提示',
message: `上传图片大小不能超过 ${props.fileSize}M!`,
type: 'warning'
})
return false
}
uploadNumber.value++
return imgType.includes(rawFile.type as FileTypes) && imgSize
// ===== 新增:压缩图片 =====
try {
const compressed = await compressImage(rawFile, 0.8)
return compressed
} catch {
return rawFile // 失败则用原图
}
}
// 图片上传成功
@@ -186,6 +187,7 @@ const handleExceed = () => {
<style lang="scss" scoped>
.is-error {
.upload {
:deep(.el-upload--picture-card),
:deep(.el-upload-dragger) {
border: 1px dashed var(--el-color-danger) !important;
@@ -198,6 +200,7 @@ const handleExceed = () => {
}
:deep(.disabled) {
.el-upload--picture-card,
.el-upload-dragger {
cursor: not-allowed;
@@ -2,6 +2,7 @@ import * as FileApi from '@/api/infra/file'
import CryptoJS from 'crypto-js'
import { UploadRawFile, UploadRequestOptions } from 'element-plus/es/components/upload/src/upload'
import axios from 'axios'
import Compressor from 'compressorjs'
/**
* 获得上传 URL
@@ -104,3 +105,29 @@ enum UPLOAD_TYPE {
// 客户端发送到后端上传
SERVER = 'server'
}
export const compressImage = (file: File, quality = 0.6): Promise<File> => {
return new Promise((resolve, reject) => {
new Compressor(file, {
quality,
maxWidth: 1920,
maxHeight: 1920,
mimeType: 'image/jpeg',
convertSize: 5 * 1024 * 1024,
checkOrientation: true,
success(result) {
const compressedFile = new File([result], file.name, {
type: result.type,
lastModified: Date.now()
})
console.log(`压缩: ${(file.size / 1024).toFixed(2)}KB → ${(compressedFile.size / 1024).toFixed(2)}KB`)
resolve(compressedFile)
},
error(err) {
console.error('压缩失败:', err)
reject(err)
}
})
})
}
+25 -17
View File
@@ -1,21 +1,9 @@
<template>
<Dialog v-model="dialogVisible" title="上传文件">
<el-upload
ref="uploadRef"
v-model:file-list="fileList"
:action="uploadUrl"
:auto-upload="false"
:data="data"
:disabled="formLoading"
:limit="1"
:on-change="handleFileChange"
:on-error="submitFormError"
:on-exceed="handleExceed"
:on-success="submitFormSuccess"
:http-request="httpRequest"
accept=".jpg, .png, .gif"
drag
>
<el-upload ref="uploadRef" v-model:file-list="fileList" :action="uploadUrl" :auto-upload="false"
:before-upload="beforeUpload" :data="data" :disabled="formLoading" :limit="1" :on-change="handleFileChange"
:on-error="submitFormError" :on-exceed="handleExceed" :on-success="submitFormSuccess" :http-request="httpRequest"
accept=".jpg, .png, .gif" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em></div>
<template #tip>
@@ -31,7 +19,8 @@
</Dialog>
</template>
<script lang="ts" setup>
import { useUpload } from '@/components/UploadFile/src/useUpload'
import { useUpload, compressImage } from '@/components/UploadFile/src/useUpload'
import type { UploadProps, UploadRawFile } from 'element-plus'
defineOptions({ name: 'InfraFileForm' })
@@ -53,6 +42,25 @@ const open = async () => {
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 文件上传之前进行压缩 */
const beforeUpload: UploadProps['beforeUpload'] = async (file: UploadRawFile) => {
// 验证文件类型
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif']
if (!allowedTypes.includes(file.type)) {
message.error('仅允许上传 jpg、png、gif 格式文件!')
return false
}
// 压缩图片
try {
const compressed = await compressImage(file, 0.8)
return compressed
} catch (error) {
message.warning('图片压缩失败,将使用原图上传')
return file
}
}
/** 处理上传的文件发生变化 */
const handleFileChange = (file) => {
data.value.path = file.name