|
64 | 64 | @change="handleAddFile" |
65 | 65 | accept="image/*" |
66 | 66 | /> |
67 | | - <button v-if="!uploading" @click="fileInput?.click()" type="button" class="group hover:border-gray-500 transition border-gray-300 flex items-center justify-center w-20 h-20 border-2 border-dashed rounded-md"> |
| 67 | + <button v-if="!uploading" @click="fileInput?.click()" type="button" class="relative group hover:border-gray-500 transition border-gray-300 flex items-center justify-center w-20 h-20 border-2 border-dashed rounded-md"> |
68 | 68 | <IconCloseOutline class="group-hover:text-gray-500 transition rotate-45 w-10 h-10 text-gray-300 hover:text-gray-300" /> |
| 69 | + <p class="text-gray-300 group-hover:text-gray-500 transition absolute bottom-0">Ctrl + v</p> |
69 | 70 | </button> |
70 | 71 | <Skeleton v-else type="image" class="w-20 h-20" /> |
71 | 72 | </div> |
|
201 | 202 |
|
202 | 203 | <script setup lang="ts"> |
203 | 204 |
|
204 | | -import { ref, onMounted, nextTick, Ref, h, computed, watch, reactive } from 'vue' |
| 205 | +import { ref, onMounted, nextTick, Ref, watch, onUnmounted } from 'vue' |
205 | 206 | import { Carousel } from 'flowbite'; |
206 | 207 | import { callAdminForthApi } from '@/utils'; |
207 | 208 | import { useI18n } from 'vue-i18n'; |
@@ -488,8 +489,11 @@ watch(zoomedImage, async (val) => { |
488 | 489 | } |
489 | 490 | }) |
490 | 491 |
|
491 | | -async function handleAddFile(event) { |
492 | | - const files = event.target.files; |
| 492 | +async function handleAddFile(event, clipboardFile = null) { |
| 493 | + if (clipboardFile) { |
| 494 | + clipboardFile = renameFile(clipboardFile, `pasted_image_${Date.now()}.png`); |
| 495 | + } |
| 496 | + const files = event?.target?.files || (clipboardFile ? [clipboardFile] : []); |
493 | 497 | for (let i = 0; i < files.length; i++) { |
494 | 498 | if (requestAttachmentFiles.value.find((f: any) => f.name === files[i].name)) { |
495 | 499 | adminforth.alert({ |
@@ -583,4 +587,30 @@ async function uploadFile(file: any): Promise<string> { |
583 | 587 | uploading.value = false; |
584 | 588 | return imgPreview; |
585 | 589 | } |
| 590 | +
|
| 591 | +async function uploadImageOnPaste(event) { |
| 592 | + const items = event.clipboardData?.items; |
| 593 | + if (!items) return; |
| 594 | +
|
| 595 | + for (let item of items) { |
| 596 | + if (item.type.startsWith('image/')) { |
| 597 | + const file = item.getAsFile(); |
| 598 | + if (file) { |
| 599 | + await handleAddFile(null, file); |
| 600 | + } |
| 601 | + } |
| 602 | + } |
| 603 | +} |
| 604 | +
|
| 605 | +function renameFile(file, newName) { |
| 606 | + return new File([file], newName, { type: file.type }); |
| 607 | +} |
| 608 | +
|
| 609 | +onMounted(() => { |
| 610 | + document.addEventListener('paste', uploadImageOnPaste); |
| 611 | +}); |
| 612 | +
|
| 613 | +onUnmounted(() => { |
| 614 | + document.removeEventListener('paste', uploadImageOnPaste); |
| 615 | +}); |
586 | 616 | </script> |
0 commit comments