Initial commit
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-09-29 19:56:44
|
||||
* @LastEditors: Administrator admin@example.com
|
||||
* @LastEditTime: 2024-11-19 10:14:08
|
||||
-->
|
||||
<template>
|
||||
<!-- 使用方法 <UploadImg @changeImgUrl='changeMobileAvatar' :img='form.mobileAvatar' :width='"100px"' :height='"100px"'></UploadImg>
|
||||
changeMobileAvatar(data) {
|
||||
this.form.mobileAvatar = data
|
||||
}, -->
|
||||
<el-upload
|
||||
class="avatar-uploader"
|
||||
:action="action"
|
||||
:show-file-list="false"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:data="{ appId: $store.getters.appId }"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:disabled="displayOnly">
|
||||
<div ref="uploader">
|
||||
<img v-if="newImg" :src="newImg" class="avatar" />
|
||||
<i v-if="imageUrl && !displayOnly" @click.stop="handleRemove" class="el-icon-delete"></i>
|
||||
<i v-if="!newImg && !displayOnly" class="el-icon-plus avatar-uploader-icon"></i>
|
||||
</div>
|
||||
</el-upload>
|
||||
</template>
|
||||
<script>
|
||||
import { handleVerAutoImg } from '@/utils/index.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
imageUrl: '',
|
||||
newImg: ''
|
||||
}
|
||||
},
|
||||
props: {
|
||||
img: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '180px'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '180px'
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
showIndex: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: '/media/web/upload/image'
|
||||
},
|
||||
domain: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
displayOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentDomain() {
|
||||
return this.domain || this.$store.getters.getSystemConfig.imgWebCdn || ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
img: function(val, oldval) {
|
||||
this.imageUrl = val
|
||||
},
|
||||
imageUrl: async function(val, oldval) {
|
||||
if (!val) {
|
||||
this.newImg = ''
|
||||
return
|
||||
}
|
||||
const a = await handleVerAutoImg(this.buildImageUrl(val))
|
||||
this.newImg = a
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$refs['uploader'].style.width = this.width
|
||||
this.$refs['uploader'].style.height = this.height
|
||||
this.$refs['uploader'].style.lineHeight = this.height
|
||||
if (this.img) {
|
||||
this.imageUrl = this.img
|
||||
} else {
|
||||
this.imageUrl = ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildImageUrl(path) {
|
||||
if (!path) return ''
|
||||
if (/^(blob:|https?:\/\/|data:)/.test(path)) return path
|
||||
const base = this.currentDomain || ''
|
||||
if (!base) return path
|
||||
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`
|
||||
return `${normalizedBase}${normalizedPath}`
|
||||
},
|
||||
async changeImg(url) {
|
||||
|
||||
},
|
||||
handleAvatarSuccess(res, file) {
|
||||
if (res.code === 200) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '上传成功!'
|
||||
})
|
||||
|
||||
this.imageUrl = res.data.path
|
||||
this.changeImgUrl()
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '上传失败!'
|
||||
})
|
||||
this.imageUrl = ''
|
||||
}
|
||||
},
|
||||
changeImgUrl() {
|
||||
if (this.showIndex) {
|
||||
this.$emit('changeImgUrl', { url: this.imageUrl, index: this.index })
|
||||
} else {
|
||||
this.$emit('changeImgUrl', this.imageUrl)
|
||||
}
|
||||
},
|
||||
handleRemove() {
|
||||
this.imageUrl = ''
|
||||
this.changeImgUrl()
|
||||
if (this.showIndex) {
|
||||
this.$emit('onRemove', { key: '', index: this.index })
|
||||
} else {
|
||||
this.$emit('onRemove')
|
||||
}
|
||||
},
|
||||
// 上传前进行压缩
|
||||
beforeAvatarUpload(file) {
|
||||
const isJPG =
|
||||
file.type === 'image/jpeg' ||
|
||||
file.type === 'image/png' ||
|
||||
file.type === 'image/gif' ||
|
||||
file.type === 'image/webp'
|
||||
// const isLt2M = file.size / 1024 / 1024 < 2
|
||||
if (!isJPG) {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '上传图片只能是 JPG 格式!!'
|
||||
})
|
||||
}
|
||||
// if (!isLt2M) {
|
||||
// this.$message({
|
||||
// type: 'error',
|
||||
// message: '上传图片大小不能超过 2MB!!'
|
||||
// })
|
||||
// }
|
||||
return isJPG
|
||||
},
|
||||
|
||||
// 图片等比压缩
|
||||
handleCompressImage(file, type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = (e) => {
|
||||
const image = new Image()
|
||||
image.src = e.target.result
|
||||
image.onload = () => {
|
||||
if (image.width > 720) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const context = canvas.getContext('2d')
|
||||
const imageWidth = 720
|
||||
const imageHeight = (720 / image.width) * image.height
|
||||
canvas.width = imageWidth
|
||||
canvas.height = imageHeight
|
||||
context.drawImage(image, 0, 0, imageWidth, imageHeight)
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
resolve(new Blob([blob], { type: type }))
|
||||
},
|
||||
'image/jpeg',
|
||||
0.9
|
||||
)
|
||||
} else {
|
||||
resolve(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.avatar-uploader {
|
||||
.el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #d9d9d9;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
.el-icon-delete {
|
||||
z-index: 9999999;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user