问题:实现图片列表的拖拽排序 更方便调整图片位置--如果用的v2我文章也有
技术:vue3 + vuedraggable(4.1.0) + element plus的el-upload 代码如下
<template>
<div>
// v-model 绑定的是图片列表 我的数据是[{address:'图片地址'}] item-key绑定唯一的值 不然拖拽会抖动
<draggable v-model="obj.attr_value" class="drag_img" item-key="address">
// draggable 版本语法 通过插槽获取到元素的每一项
<template #item="{ element }">
<div class="img_item">
<img :src="element.address" alt="" style="width: 100%;height: 100%;">
// 图片的遮罩 预览 和 删除
<div class="shade">
<div class="img_operate">
<el-icon>
<ZoomIn @click="handlePictureCardPreview(element)" style="cursor:pointer;" />
</el-icon>
<el-icon style="margin: 0 10px;">
<DeleteFilled @click="handleRemove(element)" style="cursor: pointer;" />
</el-icon>
</div>
</div>
</div>
</template>
</draggable>
</div>
// 图片上传 obj.那些 改为你们对应的数据 :show-file-list="false"这个必须有 别的看你们需求了
<el-upload :file-list="obj.attr_value" :action="uploadUrl" list-type="picture-card"
:on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="handleUploadSuccess"
:before-upload="beforeUpload" :limit="obj.attr_limit || imgLimit" :on-exceed="handleExceed"
:accept="obj.attr_accept || uploadImgAccepts.join(',')" :auto-upload="true" v-loading="loading" :multiple="true"
:show-file-list="false">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</template>
// 样式也很简单 需要的可以直接带走
<style scoped lang='scss'>
.drag_img {
display: flex;
width: 100%;
flex-wrap: wrap;
.img_item {
height: 148px;
width: 148px;
padding: 0px 10px 10px 0;
box-sizing: border-box;
position: relative;
}
}
.shade {
position: absolute;
left: 0;
top: 0;
right: 10px;
bottom: 10px;
cursor: default;
text-align: center;
padding: 0 10px 10px 0;
color: #fff;
opacity: 0;
box-sizing: border-box;
font-size: 20px;
background-color: rgba(0, 0, 0, 0.5);
-webkit-transition: opacity 0.3s;
transition: opacity 0.3s;
display: flex;
justify-content: center;
align-items: center;
.img_operate {
padding: 10px 0 0 10px;
}
&:hover {
opacity: 1;
}
}
</style>
// 最不重要的部分 处理的方法 参考一下就行
<script lang="ts" setup>
import { baseURL } from '@/service/index';
import { uploadImgAccepts } from '@/utils/constants';
import { Plus, ZoomIn } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { computed, onMounted, ref } from "vue";
import draggable from "vuedraggable";
const props = defineProps({
obj: {
type: Object,
default: () => ({}),
},
prop: {
type: String,
default: "",
},
});
const uploadUrl = computed(() => {
return baseURL + '/minio/upload'
})
const maxUpload = 10 // M
const imgLimit = props.obj.attr_limit ?? 50
let { obj } = props;
const loading = ref(false)
const rules = [
{
required: obj.attr_isRequired === 1,
validator: obj["validator"],
trigger: "change",
},
];
const dialogImageUrl = ref("");
const dialogRef = ref();
const handleUploadSuccess = (response) => {
if (response.code === 200) {
const data = response.data
obj.attr_value.push({ ...data, url: data.address, name: data.originalFileName })
} else {
ElMessage.error(response.message)
}
loading.value = false
};
const handleRemove = (uploadFile) => {
// console.log(toRaw(uploadFile));
if (uploadFile.response && uploadFile.status === "success") {
const address = uploadFile.response.data.address
obj.attr_value = props.obj.attr_value.filter(i => i.address !== address)
} else if (uploadFile.address) {
obj.attr_value = props.obj.attr_value.filter(i => i.address !== uploadFile.address)
}
};
const handlePictureCardPreview = (uploadFile) => {
dialogImageUrl.value = uploadFile.url;
dialogRef.value.openModal();
};
const handleExceed = () => {
ElMessage.warning(`上传图片不能超过${imgLimit}张`);
};
const beforeUpload = (rawFile) => {
if (rawFile.size / 1024 / 1024 > maxUpload) {
ElMessage.warning(`上传的图片不能超过${maxUpload}M`);
return false;
}
loading.value = true
return true;
};
onMounted(() => { });
</script>