FormItemUpload.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <template>
  2. <div class="form-item-dashed hover flex" @click="importModalClick">
  3. <div v-if="uploadValue" class="flex-1 truncate">{{ fileNameValue }}</div>
  4. <div v-else class="flex-1">点此上传文件</div>
  5. <div v-if="uploadValue" class="text-hover" @click.stop="previewClick">预览文件</div>
  6. </div>
  7. <!-- 上传 -->
  8. <hc-new-dialog v-model="importModal" :loading="uploadDisabled" save-text="确认上传" title="上传文件" widths="38rem" @close="importModalClose" @save="importModalYesClick">
  9. <el-upload
  10. ref="uploadRef" :accept="accept" :action="api + action" :auto-upload="false"
  11. :before-upload="beforeUpload" :data="uploadData" :disabled="uploadDisabled"
  12. :headers="getTokenHeader()" :limit="1"
  13. :on-change="uploadChange"
  14. :on-error="uploadError" :on-exceed="uploadExceed" :on-progress="uploadprogress"
  15. :on-success="uploadSuccess" :show-file-list="false" class="hc-upload-border approach" drag
  16. >
  17. <div v-loading="uploadDisabled" class="hc-upload-loading upload-file-info" element-loading-text="上传中...">
  18. <template v-if="uploadFileInfo?.name">
  19. <HcIcon class="upload-file-icon" name="file-text" />
  20. <div class="upload-file-name">{{ uploadFileInfo?.name }}</div>
  21. </template>
  22. <template v-else>
  23. <HcIcon class="upload-icon" name="upload-cloud" />
  24. <div class="el-upload__text">拖动文件到这里 或 <em>点击这里选择文件</em> 并上传</div>
  25. </template>
  26. </div>
  27. <template #tip>
  28. <div class="el-upload__tip">允许格式:{{ formatTip }}, 文件大小 小于 {{ size }}MB</div>
  29. </template>
  30. </el-upload>
  31. </hc-new-dialog>
  32. </template>
  33. <script setup>
  34. import { onMounted, ref, watch } from 'vue'
  35. import { getTokenHeader } from '~src/api/request/header'
  36. import { isFileSize } from 'js-fast-way'
  37. import { genFileId } from 'element-plus'
  38. const props = defineProps({
  39. modelValue: {
  40. type: String,
  41. default: '',
  42. },
  43. datas: {
  44. type: Object,
  45. default: () => ({}),
  46. },
  47. action: {
  48. type: String,
  49. default: 'upload-file',
  50. },
  51. accept: {
  52. type: String,
  53. default: 'image/png,image/jpg,image/jpeg,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/pdf,.doc,.docx,application/msword',
  54. },
  55. size: {
  56. type: Number,
  57. default: 20,
  58. },
  59. formatTip: {
  60. type: String,
  61. default: 'png/jpg/jpeg/excel/pdf/doc/docx',
  62. },
  63. fileName:{
  64. type: String,
  65. default: '',
  66. },
  67. })
  68. //事件
  69. const emit = defineEmits(['progress', 'change', 'update:modelValue'])
  70. //变量
  71. const uploadRef = ref(null)
  72. const uploadData = ref(props.datas)
  73. const uploadFileInfo = ref({})
  74. const uploadDisabled = ref(false)
  75. const uploadValue = ref(props.modelValue)
  76. const fileNameVal = ref(props.fileName)
  77. const api = '/api/blade-resource/oss/endpoint/'
  78. //监听
  79. watch(() => [
  80. props.datas,
  81. props.modelValue,
  82. props.fileName,
  83. ], ([datas, val, name]) => {
  84. uploadData.value = datas
  85. uploadValue.value = val
  86. // getFileName(val)
  87. fileNameVal.value = name
  88. })
  89. onMounted(() => {
  90. // getFileName(props.modelValue)
  91. fileNameValue.value = fileNameVal.value
  92. })
  93. //上传弹窗
  94. const importModal = ref(false)
  95. const importModalClick = () => {
  96. importModal.value = true
  97. }
  98. //确认上传
  99. const importModalYesClick = () => {
  100. uploadRef.value?.submit()
  101. }
  102. //关闭上传
  103. const importModalClose = () => {
  104. uploadRef.value?.clearFiles()
  105. importModal.value = false
  106. }
  107. //获取文件名
  108. const fileNameValue = ref('')
  109. const getFileName = (url) => {
  110. if (url) {
  111. let num = url.lastIndexOf('/') + 1
  112. fileNameValue.value = url.substring(num)
  113. } else {
  114. fileNameValue.value = ''
  115. }
  116. }
  117. //上传前
  118. const beforeUpload = async (file) => {
  119. if (isFileSize(file?.size, props.size)) {
  120. return true
  121. } else {
  122. window?.$message?.warning('文件大小, 不能过' + props.size + 'M!')
  123. return false
  124. }
  125. }
  126. //超出限制时
  127. const uploadExceed = (files) => {
  128. uploadRef.value?.clearFiles()
  129. const file = files[0]
  130. file.uid = genFileId()
  131. uploadRef.value?.handleStart(file)
  132. }
  133. //上传中
  134. const uploadprogress = () => {
  135. uploadDisabled.value = true
  136. emit('progress', true)
  137. }
  138. //上传完成
  139. const uploadSuccess = ({ code, data }) => {
  140. uploadDisabled.value = false
  141. emit('progress', false)
  142. // const pdfUrl = data?.pdfUrl ?? ''
  143. const pdfUrl = data
  144. if (code === 200 && pdfUrl) {
  145. uploadValue.value = pdfUrl
  146. window?.$message?.success('上传成功')
  147. importModal.value = false
  148. // getFileName(pdfUrl)
  149. fileNameValue.value = data?.originalName
  150. //事件
  151. emit('update:modelValue', data?.pdfUrl)
  152. emit('change', data?.pdfUrl)
  153. } else {
  154. window?.$message?.error('上传失败')
  155. }
  156. }
  157. //上传失败
  158. const uploadError = () => {
  159. uploadDisabled.value = false
  160. emit('progress', false)
  161. window?.$message?.error('上传失败')
  162. }
  163. //文件改变时
  164. const uploadChange = (file) => {
  165. uploadFileInfo.value = file
  166. }
  167. //预览文件
  168. const previewClick = () => {
  169. const pdfUrl = uploadValue.value ?? ''
  170. if (pdfUrl) window.open(pdfUrl, '_blank')
  171. }
  172. </script>
  173. <style lang="scss">
  174. .hc-upload-border.approach {
  175. .el-upload-dragger {
  176. padding: 24px;
  177. }
  178. .hc-upload-loading.upload-file-info {
  179. .hc-icon-i {
  180. font-size: 40px;
  181. }
  182. .upload-icon {
  183. color: var(--el-text-color-placeholder);
  184. }
  185. .upload-file-icon {
  186. color: var(--el-color-primary-light-5);
  187. }
  188. .el-upload__text {
  189. margin-top: 10px;
  190. }
  191. .upload-file-name {
  192. margin-top: 10px;
  193. font-size: 14px;
  194. text-align: center;
  195. color: var(--el-color-primary);
  196. }
  197. }
  198. .el-upload__tip {
  199. font-size: 14px;
  200. margin-top: 16px;
  201. color: var(--el-text-color-placeholder);
  202. }
  203. }
  204. </style>