模板代码:
定义变量:
文件限制的函数:
上传的函数:
样式函数:
完整代码:
<template>
<div class="dialog-upload" v-if="showUploadDialog">
<div class="dialog-upload__head">
<div class="title">上传图片</div>
<div class="close" @click="closeDialog"></div>
</div>
<div class="dialog-upload__body">
<div class="upload-box">
<span class="text">tab:</span>
<div class="pic-box">
<div v-for="(item,index) in imgUrl1" :key="index" class="pic-box__single">
<a-image class="pic" :src="item" />
<div @click="deleteImg('tab',item)" class="pic-delete"></div>
</div>
<a-upload
action="#"
:multiple="true"
list-type="picture"
:before-upload="beforeUpload"
:customRequest="handleChange"
:show-upload-list="false"
>
<div v-if="!imgUrl1.length || imgUrl1.length <5" class="img" @click="uploadImg('tab')"></div>
</a-upload>
</div>
</div>
<div class="upload-box">
<span class="text">tab1:</span>
<div class="pic-box">
<div v-for="(item,index) in imgUrl2" :key="index" class="pic-box__single">
<a-image class="pic" :src="item" />
<div @click="deleteImg('tab1',item)" class="pic-delete"></div>
</div>
<a-upload
action="#"
:multiple="true"
list-type="picture"
:before-upload="beforeUpload"
:customRequest="handleChange"
:show-upload-list="false"
>
<div v-if="!imgUrl2.length || imgUrl2.length <5" class="img" @click="uploadImg('tab1')"></div>
</a-upload>
</div>
</div>
</div>
<div class="dialog-upload__foot">
<span class="sure" @click="sure">确定</span>
<span class="cancle" @click="closeDialog">取消</span>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, watch, nextTick } from 'vue'
import { message } from 'ant-design-vue'
import request from '@/request/request'
import axios from 'axios'
export default defineComponent({
name: 'dialog',
props: {
showUploadDialog: {
type: Boolean,
default: false
},
activeTab: {
type: String,
default: 'tab'
},
imgUrl: {
type: Array,
default: () => {
return []
}
}
},
setup (props, { emit }) {
interface FileItem {
uid: string;
name?: string;
status?: string;
response?: string;
url?: string;
percent?:number;
type?:string;
}
interface FileInfo {
file: FileItem;
fileList: FileItem[];
}
const data = reactive({
dialogVisible: false,
imgUrl1: [] as Array<string> | any,
imgUrl2: [] as Array<string> | any,
imgUrl1List: [] as any,
imgUrl2List: [] as any,
uploadType: '',
limitError: false
})
watch(
() => props.showUploadDialog,
(val: boolean) => {
data.dialogVisible = !!val
},
{
immediate: true,
deep: true
}
)
watch(
() => props.activeTab,
(val: string) => {
const type = val === 'tab' ? 2 : 1
if (props.qyStoreId) {
nextTick(() => {
getPicUrl(type)
})
}
},
{
immediate: true,
deep: true
}
)
const handleChange = (info: FileInfo) => {
console.log('data.limitError',data.limitError)
if (!data.limitError) {
const formData = new FormData()
formData.append('file', info.file as any)
let params = {} as any
Object.keys(params).forEach(key => {
formData.append(key, params[key])
})
axios.post('/upload', formData).then((res: any) => {
if (res.data) {
let url = 'XXXX'
if (data.uploadType === 'tab') {
data.imgUrl1.push(url)
data.imgUrl1List= []
}
if (data.uploadType === 'tab1') {
data.imgUrl2.push(url)
data.imgUrl2List= []
}
} else {
message.error('报错')
}
})
}
}
const getPicUrl = (val:number) => {
let params = { } as any
request.then((res:any) => {
const { success, model } = res
if (success) {
if (props.activeTab === 'tab') {
data.imgUrl2= model.split(',')
}
if (props.activeTab === 'tab1') {
data.imgUrl1= model.split(',')
}
}
}).finally(() => {
if (props.activeTab === 'tab') {
data.imgUrl1= JSON.parse(JSON.stringify(props.imgUrl))
} else if (props.activeTab === 'tab1') {
data.imgUrl2= JSON.parse(JSON.stringify(props.imgUrl))
}
})
}
const closeDialog = () => {
emit('closeDialog', false)
}
const uploadImg = (type:string) => {
data.uploadType = type
}
const deleteImg = (type:string, item:string) => {
if (type === 'tab') {
if (data.imgUrl1&& data.imgUrl1.length) {
let index = data.imgUrl1.indexOf(item)
data.imgUrl1.splice(index,1)
}
}
if (type === 'tab1') {
if (data.imgUrl2&& data.imgUrl2.length) {
let index = data.imgUrl2.indexOf(item)
data.imgUrl2.splice(index,1)
}
}
}
const beforeUpload = (file: FileItem) => {
if (data.uploadType === 'tab') {
data.imgUrl1List.push(file)
data.limitError = (data.imgUrl1List.concat(...data.imgUrl1)).length > 5
}
if (data.uploadType === 'tab1') {
data.imgUrl2List.push(file)
data.limitError = (data.imgUrl2List.concat(...data.imgUrl2)).length > 5
}
console.log('data.limitError',data.limitError)
if (data.limitError) {
if (data.uploadType === 'tab') {
data.imgUrl1List= []
}
if (data.uploadType === 'tab1') {
data.imgUrl2List= []
}
message.error('每张图至多上传五张图片!')
}
return !data.limitError
}
const sure = () => {
let params = {} as any
request.then((res:any) => {
const { success } = res
if (success) {
message.success('上传成功!')
} else {
message.error('失败')
}
}).finally(() => {
emit('submitDialog', {
imgUrl1: data.imgUrl1,
imgUrl2: data.imgUrl2
})
})
}
return {
...toRefs(data),
closeDialog,
uploadImg,
sure,
handleChange,
beforeUpload,
deleteImg
}
}
})
</script>
<style lang="scss" scoped>
.dialog-upload {
width: 1056px;
height: 947px;
z-index: 200;
position: absolute;
top: 20%;
left: 40%;
background: url("@/assets/images/uploadDialog.png") no-repeat;
background-size: 100% 100%;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
&__head {
position: relative;
.title {
padding: 32px 0 77px 48px;
font-size: 44px;
font-weight: 600;
color: #ffffff;
line-height: 62px;
}
.close {
position: absolute;
top: 24px;
right: 24px;
cursor: pointer;
width: 32px;
height: 32px;
background: url("@/assets/images/close.png") no-repeat;
background-size: 32px auto;
}
}
&__body {
display: flex;
flex-direction: column;
.upload-box {
display: flex;
margin-bottom: 32px;
.text {
display: inline-block;
white-space: nowrap;
width: 236px;
flex: 1;
font-size: 28px;
font-weight: 400;
color: #fff;
text-align: right;
}
.img {
cursor: pointer;
width: 200px;
height: 122px;
background: url("@/assets/images/upload.png") no-repeat;
background-size: 200px auto;
}
}
.pic-box {
display: flex;
flex-wrap: wrap;
flex: 3;
&__single {
position: relative;
width: 200px;
height: 122px;
border: 2px dashed #4E93F8;
border-radius: 8px;
margin: 0 20px 24px 0;
.pic {
width: 200px;
height: 122px;
object-fit: contain;
border-radius: 8px;
}
.pic-delete {
cursor: pointer;
z-index: 200;
position: absolute;
z-index: 50;
top: -16px;
right: -12px;
width: 30px;
height: 30px;
background: url("@/assets/images/deleteImg.png") no-repeat;
background-size: 30px auto;
}
}
}
}
&__foot {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
.sure {
cursor: pointer;
display: inline-block;
background: #3196FA;
border: 2px solid #3196FA;
border-radius: 8px;
padding: 12px 41px;
margin-right: 44px;
font-size: 28px;
color: #fff;
}
.cancle {
cursor: pointer;
display: inline-block;
border: 2px solid #FFFFFF;
border-radius: 8px;
padding: 12px 41px;
font-size: 28px;
color: #fff;
}
}
}
</style>
<style lang="scss">
.dialog-upload {
.ant-image {
width: 196px;
height: 118px;
border-radius: 8px;
}
.ant-image-img {
width: 196px;
height: 118px;
object-fit: contain;
border-radius: 8px;
}
.ant-image-mask-info {
visibility: hidden;
font-size: 0;
}
.ant-image-mask-info span{
visibility: visible;
font-size: 48px;
}
}
</style>
最终效果: