img.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <template>
  2. <div v-if="!src" class="upload d-flex align-center justify-center flex-column" @click="openFileInput">
  3. <v-icon color="#ccc" :size="tips ? 30 : 50">mdi-plus</v-icon>
  4. <div class="font-size-12 color-999">{{ tips }}</div>
  5. <input
  6. type="file"
  7. ref="fileInput"
  8. accept="image/*"
  9. style="display: none;"
  10. @change="handleUploadFile"
  11. />
  12. </div>
  13. <div v-else class="" style="position: relative;">
  14. <v-icon color="error" class="close" @click="handleClose">mdi-close-circle</v-icon>
  15. <v-img :src="src" width="100" height="100" rounded class="imgBox" :class="{'cursor-pointer': showCursor}" @click="emit('imgClick')"></v-img>
  16. <div @click="emit('imgClick')" class="color-primary cursor-pointer text-center text-decoration-underline">点击预览</div>
  17. </div>
  18. </template>
  19. <script setup>
  20. // 图片上传
  21. defineOptions({ name: 'upload-img'})
  22. import { ref } from 'vue'
  23. import { uploadFile } from '@/api/common'
  24. import { useI18n } from '@/hooks/web/useI18n'
  25. import Snackbar from '@/plugins/snackbar'
  26. const emit = defineEmits(['success', 'delete', 'imgClick'])
  27. const props = defineProps({
  28. value: String,
  29. tips: String,
  30. showCursor: Boolean
  31. })
  32. const { t } = useI18n()
  33. const src = ref('')
  34. if (props.value) src.value = props.value
  35. // 选择文件
  36. const fileInput = ref()
  37. const clicked = ref(false)
  38. const openFileInput = () => {
  39. if (clicked.value) return
  40. clicked.value = true
  41. fileInput.value.click()
  42. clicked.value = false
  43. }
  44. // 文件上传
  45. const handleUploadFile = async (e) => {
  46. const file = e.target.files[0]
  47. const size = file.size
  48. if (size / (1024*1024) > 10) {
  49. Snackbar.warning(t('common.fileSizeExceed'))
  50. return
  51. }
  52. const formData = new FormData()
  53. formData.append('file', file)
  54. const { data } = await uploadFile(formData)
  55. if (!data) return Snackbar.error('上传失败')
  56. src.value = data
  57. Snackbar.success(t('common.uploadSucMsg'))
  58. emit('success', data)
  59. }
  60. const handleClose = () => {
  61. src.value = ''
  62. emit('delete')
  63. }
  64. </script>
  65. <style scoped lang="scss">
  66. .upload {
  67. width: 100px;
  68. height: 100px;
  69. border: 1px solid #ccc;
  70. border-radius: 4px;
  71. cursor: pointer;
  72. }
  73. .imgBox {
  74. position: relative;
  75. border: 1px solid #ccc;
  76. border-radius: 4px;
  77. padding: 5px;
  78. }
  79. .close {
  80. position: absolute;
  81. top: -10px;
  82. right: -10px;
  83. cursor: pointer;
  84. z-index: 9;
  85. }
  86. </style>