多图上传推拽排序
前期准备
注意
安装 npm i vuedraggable@next -S
上传的接口里面 一定要写好 headers: {"Content-Type": "multipart/form-data",},
组件代码
vue
<template>
<div>
<el-upload
v-if="(!multiple && myFileList.length < 1) || multiple"
ref="upload"
class="upload-demo"
accept="image/png, image/jpg, image/jpeg, image/gif"
action=""
:show-file-list="false"
:list-type="listType"
:multiple="multiple"
:before-upload="beforeUpload"
:http-request="upload"
:file-list="myFileList"
>
<el-button size="small" type="primary" plain>{{ btnText }}</el-button>
</el-upload>
<draggable
v-show="myFileList.length > 0"
v-model="myFileList"
:disabled="multiple === false ? true : false"
class="my-file-list"
item-key="index"
>
<template #item="{ element, index }" :key="index">
<div>
<div class="my-file-list-item">
<span
v-if="element.status === 'uploading'"
class="el-icon-document"
></span>
<div v-if="element.status === 'success'" class="item-img">
<img :src="element.url" />
</div>
<div class="item-pro-name">
<div class="name">{{ element.name }}</div>
<el-progress
v-if="element.status === 'uploading'"
:stroke-width="3"
:percentage="element.percentage"
></el-progress>
</div>
<span class="el-icon-close" @click="removeFileByUid(element.uid)"
>X</span
>
</div>
</div>
</template>
</draggable>
</div>
</template>
<script setup>
import draggable from "vuedraggable";
import { defineProps, defineEmits } from "vue";
const emits = defineEmits(["update:value"]);
const props = defineProps({
value: {
type: [Array, String],
required: true,
},
multiple: {
type: Boolean,
default: false,
},
api: {
type: Function,
defult: () => {},
},
listType: {
type: String,
default: "picture",
},
btnText: {
type: String,
default: "选择文件",
},
module: {
type: String,
default: "meeting",
},
});
const myFileList = ref([]);
// 上传以前
const beforeUpload = (file) => {
if (!props.multiple) {
myFileList.value = [];
}
myFileList.value.push({
uid: file.uid,
name: file.name,
url: "",
status: "uploading",
percentage: 0,
});
};
// 上传文件
const upload = (obj) => {
let data = new FormData();
data.append("image", obj.file);
// 你自己的其他参数
data.append("module", props.module);
let api = props.api ? props.api : "你自己引入的上传API方法";
api(data, (progress) => {
myFileList.value.map((item, index) => {
if (item.uid === data.get("image").uid) {
item.percentage = Math.ceil((progress.loaded / progress.total) * 99);
}
});
})
.then((res) => {
if (res.code === 200) {
myFileList.value.map((item, index) => {
if (item.uid == obj.file.uid) {
myFileList.value[index] = {
uid: obj.file.uid,
name: obj.file.name,
url: res.data.path_real,
status: "success",
percentage: 100,
};
}
});
console.log(100);
console.log(myFileList.value);
} else {
removeFileByUid(obj.file.uid);
}
})
.catch(() => {
removeFileByUid(obj.file.uid);
});
};
// 删除文件
const removeFileByUid = (uid) => {
myFileList.value.map((item, index) => {
if (item.uid == uid) {
myFileList.value.splice(index, 1);
}
});
};
// 设置文件列表
const setFileList = (arr) => {
if (!arr) {
myFileList.value = [];
}
if (
myFileList.value.length == 0 ||
(myFileList.value.length > 0 && myFileList.value[0].uid <= 9999999999)
) {
myFileList.value = [];
if (typeof arr === "string") {
arr = arr != "" ? [arr] : [];
}
arr.forEach((item) => {
myFileList.value.push({
uid: Math.ceil(Math.random() * 1000000000),
name: item.substr(item.lastIndexOf("/") + 1),
url: item,
status: "success",
percentage: 100,
});
});
}
};
watch(
() => {
return props.value;
},
(arr, oldArr) => {
if (
(typeof arr === "string" && arr === oldArr) ||
(typeof arr !== "string" && oldArr && arr.join("") === oldArr.join(""))
) {
return false;
}
if (typeof arr === "string" && arr != "") {
arr = [arr];
}
setFileList(arr);
},
{
deep: true,
immediate: true,
}
);
watch(
() => {
return myFileList.value;
},
(val) => {
let data;
if (!props.multiple) {
data = val.length > 0 ? val[0].url : "";
} else {
data = [];
for (let i in val) {
data.push(val[i].url);
}
}
emits("update:value", data);
},
{
deep: true,
immediate: true,
}
);
onMounted(() => {
if (props.value.length > 0) {
setFileList(props.value);
}
});
</script>
<style lang="scss" scoped>
/*.upload-demo {
margin-bottom: 20px;
}*/
.my-file-list {
margin-top: 20px;
width: 100%;
height: auto;
overflow: hidden;
.my-file-list-item {
width: 360px;
height: 90px;
margin-bottom: 10px;
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
border: 1px solid #ccc;
border-radius: 10px;
padding-left: 10px;
.el-icon-document {
font-size: 50px;
}
.item-img {
width: 70px;
height: 70px;
min-width: 70px;
border: 1px solid #ccc;
img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
}
.item-pro-name {
width: 240px;
line-height: 14px;
.name {
width: 100%;
height: 15px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
::v-deep(.el-progress) {
margin-top: 10px;
.el-progress-bar {
width: 100%;
}
}
}
.el-icon-close {
font-size: 18px;
cursor: pointer;
align-self: flex-start;
margin: 5px 5px 0 0;
}
}
}
</style>
父元素调用
vue
<template>
<div>
<div>多图上传</div>
<UploadVue3
v-model:value="form.image"
module="meeting"
:multiple="multipleflag"
:btnText="btnText"
:api="systemUploadMoreImageAPI"
></UploadVue3>
</div>
</template>
<script setup>
import UploadVue3 from "@/components/Upload/UploadImg3";
import {
systemUploadImageAPI,
systemUploadMoreImageAPI,
} from "@/api/study/study.js";
const form = ref({
image: "",
});
watch(
() => {
return form.value;
},
(newval, oldval) => {
console.log("watch里面的");
console.log(newval);
},
{ deep: true, immediate: true }
);
// 是否多图
const multipleflag = ref(true);
// 上传按钮的文字
const btnText = ref("多图上传");
</script>
<style lang="scss" scoped></style>