Files
pj_admin_cloud/src/components/Upload/qnImages.vue
T
dzc fbf163e3f2
build / task (16.x, npm, macOS-latest) (push) Canceled after 0s
build / task (16.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, npm, windows-latest) (push) Canceled after 0s
build / task (16.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (16.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (16.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (16.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, yarn, windows-latest) (push) Canceled after 0s
build / task (18.x, npm, macOS-latest) (push) Canceled after 0s
build / task (18.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, npm, windows-latest) (push) Canceled after 0s
build / task (18.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (18.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (18.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (18.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, yarn, windows-latest) (push) Canceled after 0s
build / task (20.x, npm, macOS-latest) (push) Canceled after 0s
build / task (20.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, npm, windows-latest) (push) Canceled after 0s
build / task (20.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (20.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (20.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (20.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, yarn, windows-latest) (push) Canceled after 0s
fix:图片上传修改
2026-10-29 19:29:24 +08:00

279 lines
7.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="upload-box">
<el-upload v-model:file-list="fileList" list-type="picture-card" multiple :accept="fileType.join(',')"
:class="['upload', 'no-border', self_disabled ? 'disabled' : '']" :drag="true" :disabled="self_disabled"
:before-upload="beforeUpload" :on-preview="handlePictureCardPreview" :on-error="uploadError"
:on-remove="handleRemove" :on-success="uploadSuccess" :http-request="handleHttpUpload">
<el-icon>
<Plus />
</el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<img class="m-auto" w-full :src="$fileUrl(dialogImageUrl)" alt="Preview Image" @error="$fileRetry(dialogImageUrl)" />
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from "vue"
import { Plus } from "@element-plus/icons-vue"
import { ElUpload, ElDialog, UploadRequestOptions, ElNotification, UploadFile, UploadProps, formContextKey } from "element-plus"
import request from "/@/utils/request"
interface UploadFileProps {
disabled?: boolean
fileType?: string[]
fileSize?: number
height?: string
width?: string
borderRadius?: string
}
const props = withDefaults(defineProps<UploadFileProps>(), {
disabled: false,
fileType: () => ["image/jpeg", "image/png", "image/gif", "image/webp"],
fileSize: 5,
height: "150px",
width: "150px",
borderRadius: "8px",
})
const imageUrls = defineModel("modelValue", { default: "" })
const imageBaseUrl = import.meta.env.VITE_IMAGE_BASE_PATH
const dialogVisible = ref(false)
const fileList = ref<any>([])
const dialogImageUrl = ref("")
// 获取 el-form 组件上下文
const formContext = inject(formContextKey, void 0)
// 自定义上传方法
const handleHttpUpload = async (options: UploadRequestOptions) => {
let formData = new FormData()
formData.append("file", options.file)
const res = await request({
url: "/admin/sys-file/qn/upload",
method: "post",
headers: {
"Content-Type": "multipart/form-data",
},
data: formData,
})
if (res.code == 0) {
return res
}
}
/**
* @description 文件上传之前判断
* @param rawFile 选择的文件
* */
const beforeUpload: UploadProps["beforeUpload"] = (rawFile) => {
const imgSize = rawFile.size / 1024 / 1024 < props.fileSize
const imgType = props.fileType.includes(rawFile.type)
if (!imgType)
ElNotification({
title: "温馨提示",
message: "上传图片不符合所需的格式!",
type: "warning",
})
if (!imgSize)
setTimeout(() => {
ElNotification({
title: "温馨提示",
message: `上传图片大小不能超过 ${props.fileSize}M!`,
type: "warning",
})
}, 0)
return imgType && imgSize
}
/**
* @description 图片上传成功
* */
const uploadSuccess = (response: any, uploadFile: UploadFile, uploadFiles: any) => {
console.log("success", uploadFiles)
const urls = uploadFiles
.map((item: any) => {
// 处理新上传和已有的图片URL
return item.response ? item.response.data.url : item.fileUrl
})
.filter(Boolean)
.join(",")
imageUrls.value = urls
console.log("fileList.value", fileList.value)
console.log("urls", urls)
ElNotification({
title: "温馨提示",
message: "图片上传成功!",
type: "success",
})
}
// 预览
const handlePictureCardPreview = (uploadFile: any) => {
dialogImageUrl.value = uploadFile.url
dialogVisible.value = true
}
// 移除
const handleRemove = (uploadFile: any, uploadFiles: any[]) => {
const urls = uploadFiles
.map((item) => {
return item.response ? item.response.data.url : item.fileUrl
})
.filter(Boolean)
.join(",")
imageUrls.value = urls
}
/**
* @description 图片上传错误
* */
const uploadError = (error: any) => {
ElNotification({
title: "温馨提示",
message: error?.msg || error?.message || "图片上传失败,请您重新上传!",
type: "error",
})
}
// 判断是否禁用上传和删除
const self_disabled = computed(() => {
return props.disabled || formContext?.disabled
})
watch(
() => imageUrls.value,
(newValue) => {
if (!newValue || Object.prototype.toString.call(newValue) !== "[object String]") {
fileList.value = []
return
}
if (!newValue.match(/x-oss-process/g)) {
fileList.value = newValue
.split(",")
.map((item: string) => {
const url = item.startsWith("http") ? item : imageBaseUrl + item
return {
name: item.split("/").pop() || "",
url: url,
fileUrl: item,
}
})
.filter((item) => item.url)
console.log("fileList.value", fileList.value)
} else {
fileList.value = newValue
.split("?")
.filter(
(item) =>
item.endsWith(".jpg") || item.endsWith(".png") || item.endsWith(".gif") || item.endsWith(".jpeg") || item.endsWith(".webp"),
)
.map((item: string) => {
const url = item.startsWith("http") ? item : imageBaseUrl + item
return {
name: item.split("/").pop() || "",
url: url,
fileUrl: item,
}
})
.filter((item) => item.url)
console.log("fileList.value", fileList.value)
}
},
{ immediate: true },
)
</script>
<style scoped lang="scss">
.is-error {
.upload {
:deep(.el-upload),
:deep(.el-upload-dragger) {
border: 1px dashed var(--el-color-danger) !important;
&:hover {
border-color: var(--el-color-primary) !important;
}
}
}
}
:deep(.disabled) {
.el-upload,
.el-upload-dragger {
cursor: not-allowed !important;
background: var(--el-disabled-bg-color);
border: 1px dashed var(--el-border-color-darker) !important;
&:hover {
border: 1px dashed var(--el-border-color-darker) !important;
}
}
}
.upload-box {
overflow: hidden;
.no-border {
:deep(.el-upload) {
border: none !important;
}
}
:deep(.upload) {
.el-upload {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: v-bind(width);
height: v-bind(height);
overflow: hidden;
border: 1px dashed var(--el-border-color-darker);
border-radius: v-bind(borderRadius);
transition: var(--el-transition-duration-fast);
&:hover {
border-color: var(--el-color-primary);
.upload-handle {
opacity: 1;
}
}
.el-upload-dragger {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
padding: 0;
overflow: hidden;
background-color: transparent;
border: 1px dashed var(--el-border-color-darker);
border-radius: v-bind(borderRadius);
&:hover {
border: 1px dashed var(--el-color-primary);
}
}
.el-upload-dragger.is-dragover {
background-color: var(--el-color-primary-light-9);
border: 2px dashed var(--el-color-primary) !important;
}
}
}
}
</style>