imageUpload.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. <template>
  2. <div class="upload-order-file">
  3. <el-upload
  4. size="mini"
  5. ref="upload"
  6. :on-success="fileUploadSuccess"
  7. :before-upload="beforeFileUpload"
  8. :on-preview="onPreview"
  9. :on-remove="fileRemove"
  10. :on-error="onError"
  11. name="file"
  12. :file-list="fileList"
  13. :action="fileUploadHost"
  14. :data="fileUploadData"
  15. :headers="headers"
  16. list-type="picture-card"
  17. :limit="0"
  18. accept="image/*"
  19. >
  20. <template #default>
  21. <div class="default-slot">
  22. <slot name="default">
  23. <el-icon class="default-icon">
  24. <plus/>
  25. </el-icon>
  26. </slot>
  27. </div>
  28. </template>
  29. </el-upload>
  30. <el-dialog v-model="showPreview" top="5vh">
  31. <el-image :src="showImage" class="preview-image" fit="contain"></el-image>
  32. </el-dialog>
  33. </div>
  34. </template>
  35. <script>
  36. import { defineComponent, ref, computed, reactive, unref, readonly, toRefs } from 'vue'
  37. import { Plus, ZoomIn, Delete, ArrowLeft, ArrowRight, Check } from '@element-plus/icons'
  38. import { useOss } from '@/components/form/upload/oss'
  39. import { ElMessage } from 'element-plus'
  40. import { useLocal } from '@/components/form/upload/local'
  41. export default defineComponent({
  42. name: 'imageUpload',
  43. props: {
  44. limit: {
  45. type: Number,
  46. default: 0,
  47. },
  48. beforeUpload: {
  49. type: Function,
  50. default: function () {
  51. return true
  52. },
  53. },
  54. host: {
  55. type: String,
  56. default: import.meta.env.VITE_BASE_API + '/file/upload',
  57. },
  58. modelValue: {
  59. type: String,
  60. default: '',
  61. },
  62. type: {
  63. type: String,
  64. default: 'local', //local oss
  65. },
  66. width: {
  67. type: String,
  68. default: '148px',
  69. },
  70. },
  71. components: { Plus, ZoomIn, Delete, ArrowLeft, ArrowRight, Check },
  72. setup (props, context) {
  73. const showPreview = ref(false)
  74. const showImage = ref('')
  75. let fileList = computed(() => props.modelValue ? [{ url: props.modelValue, status: 'success' }] : [])
  76. let fileUpload = reactive({
  77. fileUploadHost: '',
  78. fileUploadData: {},
  79. beforeFileUpload: null,
  80. headers: {},
  81. })
  82. if (props.type === 'oss') {
  83. fileUpload = useOss(props.beforeUpload, props.multiple)
  84. } else {
  85. fileUpload = useLocal(props.beforeUpload, props.host)
  86. }
  87. function removeImage (file) {
  88. let fList = unref(fileList)
  89. const index = fList.findIndex(f => f.url === file.url)
  90. fList.splice(index, 1)
  91. updateValue(fList)
  92. }
  93. function updateValue (_fileList) {
  94. let fList = unref(_fileList)
  95. context.emit(
  96. 'update:modelValue',
  97. fList.length ? fList[0].url : '',
  98. )
  99. }
  100. function fileRemove (file, _fileList) {
  101. updateValue(_fileList)
  102. }
  103. function onError () {
  104. }
  105. function fileUploadSuccess (response, file, _fileList) {
  106. file.url = response?.data?.url || file.url
  107. if (_fileList.length > 1) {
  108. _fileList.splice(0, 1)
  109. }
  110. if (_fileList.every(f => f.status === 'success')) {
  111. updateValue(_fileList)
  112. }
  113. }
  114. function onPreview (file) {
  115. showImage.value = file.url
  116. showPreview.value = true
  117. }
  118. return {
  119. fileList,
  120. ...toRefs(fileUpload),
  121. fileRemove,
  122. onError,
  123. fileUploadSuccess,
  124. onPreview,
  125. removeImage,
  126. showPreview,
  127. showImage,
  128. }
  129. },
  130. })
  131. </script>
  132. <style scoped lang="scss">
  133. .upload-order-file {
  134. ::v-deep(.el-upload-list__item-thumbnail) {
  135. object-fit: contain;
  136. }
  137. ::v-deep(.el-upload--picture-card) {
  138. width: v-bind(width);
  139. height: v-bind(width);
  140. }
  141. ::v-deep(.el-upload-list__item) {
  142. width: v-bind(width);
  143. height: v-bind(width);
  144. }
  145. ::v-deep(.el-progress) {
  146. width: v-bind(width) !important;
  147. height: v-bind(width) !important;
  148. }
  149. ::v-deep(.el-progress-circle) {
  150. width: v-bind(width) !important;
  151. height: v-bind(width) !important;
  152. }
  153. .default-slot {
  154. height: 100%;
  155. width: 100%;
  156. display: flex;
  157. justify-content: center;
  158. align-items: center;
  159. .default-icon {
  160. margin-top: 0;
  161. }
  162. }
  163. }
  164. .preview-image {
  165. width: 100%;
  166. ::v-deep(img) {
  167. max-height: 700px;
  168. }
  169. }
  170. </style>