From 089bf5d2378b3c4a61d795b2a92bede2c193b771 Mon Sep 17 00:00:00 2001
From: admin <344137771@qq.com>
Date: Tue, 06 Jan 2026 11:22:58 +0800
Subject: [PATCH] 1
---
src/components/layout/AvatarCropper.vue | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 255 insertions(+), 0 deletions(-)
diff --git a/src/components/layout/AvatarCropper.vue b/src/components/layout/AvatarCropper.vue
new file mode 100644
index 0000000..b129288
--- /dev/null
+++ b/src/components/layout/AvatarCropper.vue
@@ -0,0 +1,255 @@
+<template>
+ <div class="lum-dialog-mask">
+ <el-container class="lum-dialog-box">
+ <el-header class="header" height="50px">
+ <p>选择头像</p>
+ <p class="tools">
+ <i class="el-icon-close" @click="$emit('close', 0)" />
+ </p>
+ </el-header>
+ <el-main class="main">
+ <el-container class="full-height">
+ <el-aside width="400px">
+ <div class="cropper-box">
+ <vue-cropper
+ ref="cropper"
+ mode="cover"
+ :img="option.img"
+ :output-size="option.size"
+ :output-type="option.outputType"
+ :info="true"
+ :full="option.full"
+ :fixed="fixed"
+ :fixed-number="fixedNumber"
+ :can-move="option.canMove"
+ :can-move-box="option.canMoveBox"
+ :fixed-box="option.fixedBox"
+ :original="option.original"
+ :auto-crop="option.autoCrop"
+ :auto-crop-width="option.autoCropWidth"
+ :auto-crop-height="option.autoCropHeight"
+ :center-box="option.centerBox"
+ :high="option.high"
+ @real-time="realTime"
+ />
+ <input
+ type="file"
+ id="uploads"
+ ref="fileInput"
+ accept="image/png, image/jpeg, image/jpg"
+ style="display: none"
+ @change="uploadImg($event, 1)"
+ />
+ </div>
+ <div class="tools tools-flex">
+ <el-button
+ size="small"
+ plain
+ icon="el-icon-upload"
+ @click="clickUpload"
+ >上传图片
+ </el-button>
+ <el-button
+ size="small"
+ plain
+ icon="el-icon-refresh"
+ @click="refreshCrop"
+ >刷新
+ </el-button>
+ <el-button
+ size="small"
+ plain
+ icon="el-icon-refresh-left"
+ @click="rotateLeft"
+ >左转
+ </el-button>
+ <el-button
+ size="small"
+ plain
+ icon="el-icon-refresh-right"
+ @click="rotateRight"
+ >右转
+ </el-button>
+ </div>
+ </el-aside>
+ <el-main class="no-padding">
+ <div class="cropper-box">
+ <div class="preview-img">
+ <img v-if="cusPreviewsImg" :src="cusPreviewsImg" />
+ </div>
+ </div>
+ <div class="tools">
+ <el-button type="primary" size="small" @click="uploadService">
+ 保存图片
+ </el-button>
+ </div>
+ </el-main>
+ </el-container>
+ </el-main>
+ </el-container>
+ </div>
+</template>
+<script>
+import { VueCropper } from 'vue-cropper'
+import { ServeUploadAvatar } from '@/api/upload'
+
+export default {
+ name: 'AvatarCropper',
+ components: {
+ VueCropper,
+ },
+ data() {
+ return {
+ cusPreviewsImg: '',
+ previews: {},
+ option: {
+ img: '',
+ size: 1,
+ full: false,
+ outputType: 'png',
+ canMove: true,
+ fixedBox: true,
+ original: false,
+ canMoveBox: true,
+ autoCrop: true,
+ // 只有自动截图开启 宽度高度才生效
+ autoCropWidth: 200,
+ autoCropHeight: 150,
+ centerBox: false,
+ high: true,
+ },
+ fixed: true,
+ fixedNumber: [1, 1],
+ }
+ },
+ methods: {
+ clickUpload() {
+ this.$refs.fileInput.click()
+ },
+ clearCrop() {
+ if (!this.cusPreviewsImg) return false
+ this.$refs.cropper.clearCrop()
+ },
+ refreshCrop() {
+ if (!this.cusPreviewsImg) return false
+ this.$refs.cropper.refresh()
+ },
+ rotateLeft() {
+ if (!this.cusPreviewsImg) return false
+ this.$refs.cropper.rotateLeft()
+ },
+ rotateRight() {
+ if (!this.cusPreviewsImg) return false
+ this.$refs.cropper.rotateRight()
+ },
+ // 实时预览函数
+ realTime() {
+ this.$refs.cropper.getCropData(img => {
+ this.cusPreviewsImg = img
+ })
+ },
+
+ // 上传回调事件
+ uploadImg(e, num) {
+ let file = e.target.files[0]
+ if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
+ this.$message('图片类型必须是.gif,jpeg,jpg,png,bmp中的一种')
+ return false
+ }
+
+ let reader = new FileReader()
+ reader.onload = e => {
+ let data
+ if (typeof e.target.result === 'object') {
+ // 把Array Buffer转化为blob 如果是base64不需要
+ data = window.URL.createObjectURL(new Blob([e.target.result]))
+ } else {
+ data = e.target.result
+ }
+ if (num === 1) {
+ this.option.img = data
+ } else if (num === 2) {
+ this.example2.img = data
+ }
+ }
+ // 转化为base64
+ // reader.readAsDataURL(file)
+ // 转化为blob
+ reader.readAsArrayBuffer(file)
+ },
+
+ // 上传图片到服务器
+ uploadService() {
+ if (this.cusPreviewsImg == '') return
+
+ this.$refs.cropper.getCropBlob(blob => {
+ let file = new File([blob], 'avatar.png', {
+ type: blob.type,
+ lastModified: Date.now(),
+ })
+
+ const form = new FormData()
+ form.append('file', file)
+
+ ServeUploadAvatar(form)
+ .then(res => {
+ if (res.code == 200) {
+ this.$emit('close', 1, res.data.avatar)
+ } else {
+ this.$message('文件上传失败,请稍后再试...')
+ }
+ })
+ .catch(() => {
+ this.$message('文件上传失败,请稍后再试...')
+ })
+ })
+ },
+ },
+}
+</script>
+
+<style lang="less" scoped>
+.lum-dialog-box {
+ height: 550px;
+ max-width: 800px;
+
+ .main {
+ .cropper-box {
+ height: 400px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ .preview-img {
+ width: 180px;
+ height: 180px;
+ border-radius: 50%;
+ overflow: hidden;
+ box-shadow: 0 0 4px #ccc;
+
+ img {
+ width: 100%;
+ height: 100%;
+ }
+ }
+ }
+
+ .tools {
+ height: 40px;
+ margin-top: 20px;
+ text-align: center;
+
+ button {
+ border-radius: 1px;
+ }
+ }
+
+ .tools-flex {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ }
+ }
+}
+</style>
--
Gitblit v1.9.3