DropFile.vue 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. const isDragging = ref(false)
  4. const files = ref([])
  5. const fileInputRef = ref(null)
  6. function onChange() {
  7. files.value = [...fileInputRef.value.files]
  8. }
  9. function dragover(e) {
  10. e.preventDefault()
  11. isDragging.value = true
  12. }
  13. function dragleave() {
  14. isDragging.value = false
  15. }
  16. function drop(e) {
  17. e.preventDefault()
  18. fileInputRef.value.files = e.dataTransfer.files
  19. onChange()
  20. isDragging.value = false
  21. }
  22. function remove(i) {
  23. files.value.splice(i, 1);
  24. }
  25. function generateURL(file) {
  26. let fileSrc = URL.createObjectURL(file);
  27. setTimeout(() => {
  28. URL.revokeObjectURL(fileSrc);
  29. }, 1000);
  30. return fileSrc;
  31. }
  32. </script>
  33. <template>
  34. <div class="main">
  35. <div
  36. class="dropzone-container"
  37. @dragover="dragover"
  38. @dragleave="dragleave"
  39. @drop="drop"
  40. >
  41. <input
  42. type="file"
  43. multiple
  44. name="file"
  45. id="fileInput"
  46. class="hidden-input"
  47. @change="onChange"
  48. ref="fileInputRef"
  49. accept=".pdf,.jpg,.jpeg,.png"
  50. />
  51. <label for="fileInput" class="file-label">
  52. <div v-if="isDragging">释放以将文件放到此处。</div>
  53. <div v-else>将文件拖到此处或单击此处上传。</div>
  54. </label>
  55. <div class="preview-container mt-4" v-if="files.length">
  56. <div v-for="file in files" :key="file.name" class="preview-card">
  57. <div>
  58. <img class="preview-img" :src="generateURL(file)" />
  59. <p>
  60. {{ file.name }}
  61. </p>
  62. </div>
  63. <div>
  64. <button
  65. class="ml-2"
  66. type="button"
  67. @click="remove(files.indexOf(file))"
  68. title="Remove file"
  69. >
  70. <b>×</b>
  71. </button>
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </template>
  78. <style scoped>
  79. </style>