简单的更换头像并不是什么难事,难的是更换头像的时候可编辑头像展示区域,如下图所示
下面是简单的实现
<el-upload
class="avatar-uploader"
ref="fileUpload"
action=""
:show-file-list="false"
:before-upload="beforeAvatarUpload"
:http-request="fileUpload"
>
<el-avatar class="vertical-align-middle el-avatar-default img-size" :src="circleUrl"></el-avatar>
</el-upload>
<dialog-cropper :cropper-show.sync="cropperShow" :cropperImg="cropperImg" @upload="fileUpload"></dialog-cropper>
<script>
import * as uploadApi from "@/api/uploader";
import dialogCropper from "@/components/dialogCropper";
export default() {
components: {dialogCropper},
data() {
return {
circleUrl: "",
cropperShow: false,
cropperImg: "",
}
},
methods: {
beforeAvatarUpload(file) {
this.cropperImg = URL.createObjectURL(file);
this.cropperShow = true;
return false;
},
//更换头像
fileUpload(res) {
let file = event.file;
let fileType = 1; // 图片1,音频2,视频3,文件4
uploadApi
.simpleUploader(res.data, res.type, 1)
.then((res) => {
this.circleUrl = res.url;
})
.catch((err) => {
this.$message.error("上传失败,请重新上传");
})
.finally(() => {
this.cropperShow = false;
});
}
}
}
</script>
upload.js
import request from "@/utils/request";
const getAliOSSCreds = (params) => {
return request({
url: "admin/base/getOssToken",
method: "get",
params
});
};
export const getUploadToken = ossType => {
return getAliOSSCreds({
type: ossType
});
};
const generateUUID = () => {
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); // use high-precision timer if available
}
var uuid = "xxxxxxxxxxxxxxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
});
return uuid;
};
export const simpleUploader = (data, fileType, ossType) => {
return new Promise((resolve, reject) => {
getUploadToken(ossType)
.then(res => {
const oss = require("ali-oss");
let client = new oss({
region: res.region,
secure: true,
accessKeyId: res.accessKeyId,
accessKeySecret: res.accessKeySecret,
stsToken: res.securityToken,
bucket: res.bucket,
endpoint: res.endpoint
});
let key = res.dir + "/" + generateUUID() + "." + fileType;
client
.put(key, dataURLtoBlob(data))
.then(res => {
resolve(res);
})
.catch(res => {
reject(res);
});
})
.catch(res => {
reject(res);
});
});
};
export const dataURLtoBlob = dataurl => {
let arr = dataurl.split(",");
//注意base64的最后面中括号和引号是不转译的
let _arr = arr[1].substring(0, arr[1].length - 2);
let mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(_arr),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
};
export default {
simpleUploader
};
/components/dialogCropper 目录下的 dialogCropper.vue文件
<template>
<el-dialog
:visible="cropperShow"
width="440px"
:close-on-click-modal="false"
:show-close="false"
@open="onOpenDialogHandle"
>
<h3 slot="title">上传头像</h3>
<div class="vue-cropper-layer">
<vueCropper
ref="cropper"
class="cropper"
autoCrop
centerBox
fixed
:img="cropperImg"
autoCropWidth="200px"
autoCropHeight="200px"
outputType="jpeg"
></vueCropper>
</div>
<div class="cropper-btn">
<el-button type="primary" @click="confirm" :loading="loading">上传</el-button>
<el-button @click="cancel" :disabled="loading">取消</el-button>
</div>
</el-dialog>
</template>
<script>
import {VueCropper} from "vue-cropper";
export default {
name: "dialogCropper",
components: {
VueCropper
},
props: {
cropperShow: {
default: true,
type: Boolean
},
cropperImg: {}
},
data() {
return {
option: {
size: 0,
outputType: "",
centerBox: false
},
loading: false
};
},
methods: {
confirm() {
this.$refs.cropper.getCropData(data => {
this.$emit("upload", {
data,
type: "jpg"
});
this.loading = true;
});
},
// 取消
cancel() {
this.$emit("update:cropperShow", false);
},
onOpenDialogHandle() {
this.loading = false;
}
}
};
</script>
<style scoped>
.vue-cropper-layer {
width: 400px;
height: 400px;
margin: 0 0 15px;
}
.cropper-btn {
text-align: center;
}
</style>