组件:
<template>
<div ref="past-contener" class="past-contener" :contenteditable="contenteditable" @input="onInput" :style="style"
placeholder="粘在这里"></div>
<a-button class="reset-btn" v-show="showResetBtn" @click="resetUp">重新上传</a-button>
</template>
<script lang="ts" setup>
/**
* @author 全易
* @time 2024-09-10 15:54:07 星期二
* @description 粘贴式上传图片框
* @use
**/
import { message } from 'ant-design-vue'
import { ref, reactive, onMounted, watch, getCurrentInstance, nextTick } from 'vue'
const props = defineProps({
// 可以传几张
limit: {
type: Number,
default: 3
},
// 图片类型
type: {
type: String,
default: '',
validator(value) {
return ['png', 'jpeg', 'jpg', 'gif'].includes(value)
}
},
// 粘贴框的行高
rows: {
type: Number,
default: 5
}
})
const instance = getCurrentInstance()
const contenteditable = ref(true)
const showResetBtn = ref(false)
const emits = defineEmits(['change'])
let imageInp: HTMLElement;
const style = reactive({
'min-height': props.rows + 'px'
})
watch(
() => props.rows,
(now) => {
style['min-height'] = `${now * 20}px`
},
{ immediate: true }
)
onMounted(() => {
imageInp = instance.proxy.$refs['past-contener']
imageInp.addEventListener('paste', onPaste)
})
// 粘贴事件
async function onPaste(e) {
let file = null
const items = (e.clipboardData || window.clipboardData).items
if (!items?.length) {
return
}
for (var i = 0; i < items.length; i++) {
if (!items[i].type.includes(`image/${props.type}`)) {
break
}
file = items[i].getAsFile()
}
if (file) {
console.log('文件:', file)
const imgElement = document.createElement('img');
imgElement.src = URL.createObjectURL(file);
imageInp.appendChild(imgElement)
emits('change', file)
}
}
// 监听past-contener值变化
function onInput(e) {
nextTick(() => {
if (e.target.lastChild && e.target.lastChild?.tagName !== 'IMG') {
message.destroy()
message.warning('请粘贴图片')
return
}
const childNodes = imageInp.childNodes
if (childNodes.length >= props.limit) {
imageInp.removeEventListener('paste', onPaste)
contenteditable.value = false
if (props.limit !== 1) {
message.destroy()
message.warning(`最多${props.limit}张`)
}
}
for (const node of childNodes) {
node.style.width = '80%'
}
showResetBtn.value = true
})
}
// 重新上传
function resetUp() {
imageInp.innerHTML = ''
imageInp.focus()
showResetBtn.value = false
contenteditable.value = true
imageInp.addEventListener('paste', onPaste)
}
</script>
<style scoped lang="scss">
.past-contener {
border: 1px solid #d9d9d9;
border-radius: 16px;
padding: 4px 11px;
cursor: text;
display: grid;
gap: 12px;
grid-template-columns: 25% 25% 25% 25%;
justify-content: space-between;
&:empty::before {
font-size: 14px;
content: attr(placeholder);
color: #d9d9d9;
}
&:hover,
&:focus-visible {
border-color: #4096ff;
box-shadow: 0 0 0 2px rgba(5, 145, 255, 0.1);
border-inline-end-width: 1px;
outline: 0;
}
}
.reset-btn {
margin: 15px 0 0 auto;
display: block;
}
</style>
使用:
<template>
<MCvImg />
</template>
<script setup>
/**
* @author 全易
* @time 2024-09-06 13:46:18 星期五
* @description 测试页面
**/
import { computed, ref, watch } from 'vue'
import MCvImg from '@/apps/file-storage/components/upload/MCvImg.vue'
</script>
<style scoped lang="scss"></style>
存在的问题:
复制粘贴没问题
但是截图粘贴有问题