) {
this
.
$refs
.
cropper
.
rotateRight
();
changeScale
(
num
) {
num = num ||
1
;
this
.
$refs
.
cropper
.
changeScale
(num);
previewImg
(
data
) {
this
.
preview
= data;
goUpload
(
) {
this
.$emit(
"upAgain"
);
uploadImg
(
) {
let
self =
this
;
this
.
$refs
.
cropper
.
getCropData
(
(
data
) =>
{
let
file =
this
.
dataURLtoFile
(data,
"photo.png"
);
this
.$emit(
"getFile"
, file);
</
script
>
<
style
lang
=
"scss"
scoped
>
.el-dialog__wrapper
{
display
: flex;
align-items
: center;
justify-content
: center;
.cropper_model_dlg
{
.cropper_content
{
margin
:
0
auto;
width
:
650px
;
height
:
650px
;
display
: flex;
justify-content
: space-between;
align-items
: flex-start;
.cropper
{
width
:
600px
;
height
:
600px
;
background
: yellow;
.cropper_right
{
width
:
300px
;
text-align
: center;
.cropper_preview
{
margin
:
0
auto;
display
: inline-block;
border
:
1px
solid
#ddd
;
.cropper_btns
{
margin-top
:
20px
;
.previewImg
{
width
:
100%
;
height
:
100%
;
</
style
>
2.2 图片拖拽交换位置组件:components -> dragImgItem -> index.vue
<template>
<!-- 图片拖拽交换位置组件 -->
class="imgItem"
@dragstart="dragStartHandler"
@dragover.prevent="dragOverHandler"
@dragenter="dragEnterHandler"
@dragend="dragEndHandler"
:style="{
width: imgWidth,
height: imgHeight,
class="bgImg"
:src="imgSrc"
alt=""
:width="imgWidth"
:height="imgHeight"
<em class="imgClose" @click="removeImg"></em>
</div>
</template>
<script>
export default {
name: "dragImgItem",
props: {
index: {
type: Number,
required: true,
imgSrc: {
type: String,
required: true,
imgWidth: {
default: "150px",
imgHeight: {
default: "150px",
methods: {
dragStartHandler() {
this.$emit("setCurDragImg", this.index);
dragEndHandler(e) {
this.$emit("clearCurDragImg");
dragOverHandler(e) {
e.dataTransfer.dropEffect = "move";
dragEnterHandler(e) {
console.log("e", e);
e.dataTransfer.effectAllowed = "move";
this.$emit("dragImg", this.index);
removeImg() {
this.$emit("removeImg");
</script>
<style scoped lang="scss">
.imgItem {
position: relative;
height: 150px;
width: 150px;
display: inline-block;
border-radius: 5px;
float: left;
margin: 0 15px 15px 0;
.bgImg {
height: 150px;
width: 150px;
object-fit: cover;
border: 1px solid #dcdfe6;
border-radius: 5px;
.imgClose {
position: absolute;
top: 0;
right: 0;
width: 30px;
height: 30px;
margin-top: -13px;
margin-right: -13px;
cursor: pointer;
background: url("~@/assets/images/imgClose.png") top left
no-repeat;
background-size: cover;
</style>
三、在页面中上传图片
<template>
<div class="imgUploadDemo">
<el-form
:model="form"
ref="ruleForm"
label-width="180px"
class="form"
size="small"
<el-form-item label="商品列表封面图:" prop="default_image">
<div class="imgUpload">
<el-upload
ref="defaultImgUpload"
action
:auto-upload="false"
:show-file-list="false"
list-type="picture-card"
:on-change="handleDefaultSuccess"
v-if="form.default_image"
:src="form.default_image"
class="defaultImg"
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<div class="imgSize">
(建议尺寸为220像素*220像素长宽比例1:1的图片)
</div>
</div>
</el-form-item>
<el-form-item label="商户详情页头部轮播图:" prop="swiperList">
<div class="imgUpload">
<div class="merchantDetailImg imgDiv">
<viewer :images="form.swiperList">
<dragImgItem
class="imgItem"
v-for="(item, index) of form.swiperList"
:key="index"
:index="index"
:imgSrc="item"
@setCurDragImg="setCurDragImg(index, 1)"
@clearCurDragImg="clearCurDragImg(1)"
@dragImg="dragSwiperImg(index, 1)"
@removeImg="removeSwiper(item)"
</dragImgItem>
</viewer>
</div>
<div class="merchantDetailUpload">
<el-upload
action
ref="upload"
:auto-upload="false"
:show-file-list="false"
list-type="picture-card"
:on-change="handleSwiperSuccess"
<i class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</div>
<div style="clear: both"></div>
<div class="imgSize">
(建议尺寸为600像素*600像素长宽比例1:1的图片),支持长按鼠标左键拖拽图片交换位置
</div>
</el-form-item>
</el-form>
<ImgCropper
ref="myCropper"
:imgCropperOptions="imgCropperOptions"
@getFile="getFile"
@upAgain="upAgain"
></ImgCropper>
</div>
</template>
<script>
import dragImgItem from "@/components/dragImgItem";
import ImgCropper from "@/components/cropper";
import Vue from "vue";
import Viewer from "v-viewer";
import "viewerjs/dist/viewer.css";
Vue.use(Viewer);
export default {
name: "imgUploadDemo",
components: {
dragImgItem,
ImgCropper,
data() {
return {
imgCropperOptions: {
autoCropWidth: 600,
autoCropHeight: 600,
maximgSize: 600,
form: {
default_image: "",
swiperList: [
"https://circle.sutpay.cn/youhuiquanyi/6083782831/goods_image463321.png",
"https://circle.sutpay.cn/youhuiquanyi/6083782831/goods_image296439.png",
"https://circle.sutpay.cn/youhuiquanyi/6083782831/goods_image144881.png",
"https://circle.sutpay.cn/youhuiquanyi/6083782831/goods_image098233.png",
curSwiperImgIndex: null,
imgUploadType: 1,
methods: {
setCurDragImg(index, type) {
console.log("正在被拖动的图片-index", index);
this.curSwiperImgIndex = index;
clearCurDragImg(type) {
console.log("clearCurDragImg-type", type);
this.curSwiperImgIndex = null;
dragSwiperImg(index) {
if (index === this.curSwiperImgIndex) return;
let newList = [...this.form.swiperList];
let curImg = this.form.swiperList[this.curSwiperImgIndex];
let hitImg = this.form.swiperList[index];
console.log("商户详情页头部轮播图-curImg", curImg);
console.log("商户详情页头部轮播图-hitImg", hitImg);
if (curImg) {
newList.splice(this.curSwiperImgIndex, 1, hitImg);
newList.splice(index, 1, curImg);
this.curSwiperImgIndex = index;
this.form.swiperList = newList;
console.log("this.form.swiperList", this.form.swiperList);
} else {
this.$message.error("仅支持同类型的的图片拖拽交换位置!");
setImgCropperOptions(size) {
console.log("设置图片裁剪弹窗参数size", size);
this.imgCropperOptions.autoCropWidth = size;
this.imgCropperOptions.autoCropHeight = size;
async handleSwiperSuccess(res, file) {
this.imgUploadType = 2;
await this.setImgCropperOptions(600);
this.$nextTick(() => {
this.$refs.myCropper.open(res.raw || res);
async handleDefaultSuccess(res, file) {
this.imgUploadType = 1;
await this.setImgCropperOptions(220);
this.$nextTick(() => {
this.$refs.myCropper.open(res.raw || res);
removeSwiper(itemImg) {
console.log("删除商品详情页头部轮播图-itemImg", itemImg);
this.form.swiperList = this.form.swiperList.filter(
(item, index) => {
return item != itemImg;
console.log("this.form.swiperList", this.form.swiperList);
upAgain() {
if (this.imgUploadType == 1) {
this.$refs["defaultImgUpload"].$refs[
"upload-inner"
].handleClick();
} else if (this.imgUploadType == 2) {
this.$refs["upload"].$refs["upload-inner"].handleClick();
getFile(file) {
console.log("file", file);
console.log("url", URL.createObjectURL(file));
if (this.imgUploadType == 1) {
this.form.default_image = URL.createObjectURL(file);
} else if (this.imgUploadType == 2) {
this.form.swiperList.push(URL.createObjectURL(file));
this.$refs.myCropper.close();
uploadImage(res, imgUploadType) {
const isImgType =
res.type === "image/bmp" ||
"image/png" ||
"image/jpeg" ||
"image/jpg";
if (!isImgType) {
return this.$message.error(
"上传图片只能是bmp/image/jpeg/png/jpg格式!"
let formdata = new FormData();
formdata.append("img", res);
this.$refs.myCropper.loading = true;
this.$axios
.post(`/xx/upload_image/`, formdata)
.then((res) => {
if (imgUploadType == 1) {
this.form.default_image = res.img_id;
} else if (imgUploadType == 2) {
this.form.swiperList.push(res.img_id);
this.$refs.myCropper.close();
.catch((err) => {
if (err.response) {
this.$message.error(
err.response.data.error || err.response.data.detail
.finally(() => {
this.$refs.myCropper.loading = false;
</script>
<style scoped lang="scss">
.imgUploadDemo {
padding: 100px;
.merchantDetailImg {
margin: 10px 0;
.imgItem {
position: relative;
height: 150px;
width: 150px;
display: inline-block;
border-radius: 5px;
float: left;
margin: 0 15px 15px 0;
.bgImg {
height: 150px;
width: 150px;
object-fit: cover;
border: 1px solid #dcdfe6;
border-radius: 5px;
.imgClose {
position: absolute;
top: 0;
right: 0;
width: 30px;
margin-top: -13px;
margin-right: -13px;
cursor: pointer;
.imgSize {
font-size: 12px;
line-height: 12px;
margin-top: 0;
float: left;
.defaultImg {
height: 150px;
width: 150px;
object-fit: cover;
border-radius: 5px;
.imgUploadDemo ::v-deep .el-upload--picture-card {
margin-bottom: 15px;
border: 1px solid #c0ccda;
border-radius: 5px;
overflow: hidden;
</style>