图片裁剪

This commit is contained in:
陈红丽 2024-09-02 17:19:46 +08:00
parent 1b7d40d2cc
commit 77d12a249c
3 changed files with 61 additions and 26 deletions

View File

@ -2,20 +2,38 @@
<div class="img-cropper" :class="{ 'img-cropper-auto': $slots.default, circled: circled }"> <div class="img-cropper" :class="{ 'img-cropper-auto': $slots.default, circled: circled }">
<slot name="default"></slot> <slot name="default"></slot>
<template v-if="!$slots.default"> <template v-if="!$slots.default">
<template v-if="src">
<div class="img-cropper-img" @click="openCropper"> <div class="img-cropper-img" @click="openCropper">
<img :src="src" :class="{ circled: circled }" v-if="src"/> <img :src="src" :class="{ circled: circled }"/>
<div class="addImg" v-else> <div class="mask" :class="{ circled: circled }" @click.stop>
<div class="handle-icon" @click="openCropper">
<el-icon >
<Edit />
</el-icon>
</div>
<div class="handle-icon" @click="viewImg">
<el-icon>
<ZoomIn />
</el-icon>
</div>
<div class="handle-icon" @click="deleteImg">
<el-icon>
<Delete />
</el-icon>
</div>
</div>
</div>
</template>
<template v-else>
<div class="img-cropper-img" @click="openCropper">
<div class="addImg">
<el-icon> <el-icon>
<plus /> <plus />
</el-icon> </el-icon>
</div> </div>
<div class="mask" :class="{ circled: circled }">
<el-icon class="el-input__icon">
<UploadOutlined />
</el-icon>
</div>
</div> </div>
</template> </template>
</template>
<CropperModal <CropperModal
ref="cropperRef" ref="cropperRef"
:title="title" :title="title"
@ -30,7 +48,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref } from 'vue';
import CropperModal from './CropperModal.vue'; import CropperModal from './CropperModal.vue';
import { UploadOutlined } from '@vicons/antd';
import { cssUnit } from '@/utils'; import { cssUnit } from '@/utils';
const cropperRef = ref(); const cropperRef = ref();
@ -39,7 +56,7 @@
title: { type: String, default: '图片上传' }, title: { type: String, default: '图片上传' },
src: { type: String, required: true }, src: { type: String, required: true },
circled: { type: Boolean, default: false }, circled: { type: Boolean, default: false },
width: { type: [String, Number], default: 200 }, width: { type: [String, Number], default: 150 },
uploadApi: { uploadApi: {
type: Function as PropType<(params) => Promise<any>>, type: Function as PropType<(params) => Promise<any>>,
}, },
@ -50,9 +67,15 @@
const iconSize = cssUnit(Math.ceil(parseInt(getWidth) / 4)); const iconSize = cssUnit(Math.ceil(parseInt(getWidth) / 4));
const emit = defineEmits(['uploadSuccess']); const emit = defineEmits(['uploadSuccess']);
function handleSuccess(value){ const viewImg =()=>{
window.open(props.src)
}
const deleteImg = () => {
emit('uploadSuccess', {fileUrl:''});
};
function handleSuccess(value){
emit('uploadSuccess',value) emit('uploadSuccess',value)
} }
function openCropper() { function openCropper() {
cropperRef.value.showModal(); cropperRef.value.showModal();
} }
@ -100,11 +123,19 @@ function handleSuccess(value){
left: 0; left: 0;
top: 0; top: 0;
opacity: 0; opacity: 0;
padding: 0 6%;
transition: opacity 0.4s; transition: opacity 0.4s;
.handle-icon {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 6%;
color: aliceblue;
.el-icon { .el-icon {
color: #fff; color: #fff;
font-size: v-bind(iconSize); font-size:20px;
}
} }
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<basicModal ref="modalRef" @register="modalRegister" @ok="handleOk"> <basicModal ref="modalRef" @register="modalRegister" @ok="handleOk" @close="handleClose">
<template #default> <template #default>
<div class="cropper-box"> <div class="cropper-box">
<div class="cropper-box-left"> <div class="cropper-box-left">
@ -17,7 +17,7 @@
<el-upload <el-upload
:show-file-list="false" :show-file-list="false"
accept="image/*" accept="image/*"
action="http://www.mocky.io/v2/5e4bafc63100007100d8b70f" :http-request="handleHttpUpload"
:before-upload="beforeUpload" :before-upload="beforeUpload"
style="width: auto" style="width: auto"
> >
@ -212,7 +212,8 @@
function showModal() { function showModal() {
openModal(); openModal();
} }
function handleHttpUpload(){
}
// //
function beforeUpload(file) { function beforeUpload(file) {
const reader = new FileReader(); const reader = new FileReader();
@ -265,6 +266,10 @@
} }
} }
} }
function handleClose(){
src.value =''
previewSource.value=''
}
return { return {
src, src,
@ -273,10 +278,12 @@
previewSource, previewSource,
showModal, showModal,
beforeUpload, beforeUpload,
handleHttpUpload,
handleCropend, handleCropend,
handleReady, handleReady,
handlerToolbar, handlerToolbar,
handleOk, handleOk,
handleClose
}; };
}, },
}); });

View File

@ -105,7 +105,7 @@
v-model:image-url="formData.avatar"> v-model:image-url="formData.avatar">
<template v-slot:tip>支持扩展名: jpg png jpeg;文件大小不超过200M</template> <template v-slot:tip>支持扩展名: jpg png jpeg;文件大小不超过200M</template>
</UploadImg> --> </UploadImg> -->
<Cropper ref="cropperCircled" :src="formData.avatar" :uploadApi="upload" title="矩形头像上传" @uploadSuccess="uploadSuccess"> <Cropper ref="cropperCircled" :src="formData.avatar" :uploadApi="upload" title="头像上传" @uploadSuccess="uploadSuccess">
<template #avatar> <template #avatar>
</template> </template>
</Cropper> </Cropper>
@ -193,6 +193,7 @@ const passwordConfirmValidator = (
const uploadSuccess =(data)=>{ const uploadSuccess =(data)=>{
formData.avatar = data.fileUrl formData.avatar = data.fileUrl
formRef.value?.validateField("avatar");
} }
const dialogClose = () => { const dialogClose = () => {
emit("update:visible", false); emit("update:visible", false);
@ -250,10 +251,6 @@ const getAllDict = async () => {
list = await getPositionAllList(); list = await getPositionAllList();
optionData.positionList = list ? list : []; optionData.positionList = list ? list : [];
}; };
function cropperCircledImg() {
cropperCircled.value.openCropper();
}
onMounted(() => { onMounted(() => {
getAllDict() getAllDict()
if (props.userId) { if (props.userId) {