file-row.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <template>
  2. <div class="file-row" >
  3. <span class="file-row__file-name">{{file.name}}</span>
  4. <!-- 进度条仅在当前页面上传的文件中显示-->
  5. <template v-if="file.status !== 'success' && file.percentage <= 100">
  6. <el-progress style="flex-grow: 2" :percentage="file.percentage" :status="file.status"></el-progress>
  7. <div>
  8. ({{parseFileSize(file.loaded)}}/{{parseFileSize(file.total)}})
  9. <cip-table-button v-if="!file.status" type="danger" @click="cancelUpload(file)">取消</cip-table-button>
  10. </div>
  11. </template>
  12. <template v-else>
  13. <div class="handle-button-wrapper">
  14. <cip-table-button size="medium" :type="isPreview?'visited':undefined" :loading="previewLoading" v-if="previewAble" @click="previewFile">
  15. 预览
  16. </cip-table-button>
  17. <cip-table-button size="medium" :type="isDownload?'visited':undefined" :loading="downloadLoading" v-if="downloadAble" @click="downloadFile">
  18. 下载
  19. </cip-table-button>
  20. <template v-if="removable">
  21. <cip-table-button size="medium" @click="remove" :loading="removeLoading">
  22. 删除
  23. </cip-table-button>
  24. </template>
  25. </div>
  26. </template>
  27. </div>
  28. </template>
  29. <script>
  30. import { computed, ref } from 'vue'
  31. import { ElMessageBox, ElProgress } from 'element-plus'
  32. import CipTableButton from '@cip/components/cip-table-button'
  33. import { download } from './upload'
  34. import { isEmpty } from '@cip/utils/util'
  35. export default {
  36. components: { CipTableButton, ElProgress },
  37. props: {
  38. file: {
  39. type: Object,
  40. default: () => { return {} }
  41. },
  42. config: Object,
  43. dependOnValues: Object,
  44. removable: Boolean
  45. },
  46. setup (props, { emit }) {
  47. const previewLoading = ref(false)
  48. const downloadLoading = ref(false)
  49. const removeLoading = ref(false)
  50. const fileValue = computed(() => {
  51. return props.file
  52. })
  53. // 根据文件大小 显示 B kb mb
  54. const parseFileSize = (size) => {
  55. let unit = 'k'
  56. if (size > 1024) {
  57. size = size / 1024
  58. unit = 'kb'
  59. }
  60. if (size > 1024) {
  61. size = size / 1024
  62. unit = 'mb'
  63. }
  64. return `${Math.floor(size)}${unit}`
  65. }
  66. const cancelUpload = (file) => {
  67. file.abort()
  68. }
  69. const previewAble = computed(() => {
  70. if (typeof props.config.previewAble === 'boolean') return props.config.previewAble
  71. return props.config.previewAble?.(props.dependOnValues)
  72. })
  73. const isPreview = computed(() => {
  74. return !!props.file.read
  75. })
  76. const isDownload = computed(() => {
  77. return !!props.file.download
  78. })
  79. const previewFile = async () => {
  80. previewLoading.value = true
  81. try {
  82. await props.config.previewFile?.(fileValue.value)
  83. } finally {
  84. previewLoading.value = false
  85. }
  86. }
  87. const downloadAble = computed(() => {
  88. if (isEmpty(props.config.downloadAble)) return true
  89. if (typeof props.config.downloadAble === 'boolean') return props.config.downloadAble
  90. return props.config.downloadAble(props.dependOnValues)
  91. })
  92. const downloadFile = async () => {
  93. try {
  94. downloadLoading.value = true
  95. if (isEmpty(props.config.downloadFile)) {
  96. await download(fileValue.value)
  97. } else {
  98. await props.config.downloadFile(fileValue.value)
  99. }
  100. } finally {
  101. downloadLoading.value = false
  102. }
  103. }
  104. const remove = async () => {
  105. removeLoading.value = true
  106. try {
  107. await ElMessageBox.confirm(`确认删除《${fileValue.value.name}》`, '警告', { type: 'warning' })
  108. if (props.config.deleteFile) {
  109. await props.config.deleteFile?.(fileValue.value)
  110. }
  111. emit('after-remove', fileValue.value)
  112. } catch (e) {
  113. } finally {
  114. removeLoading.value = false
  115. }
  116. }
  117. return {
  118. parseFileSize,
  119. cancelUpload,
  120. previewAble,
  121. previewLoading,
  122. previewFile,
  123. downloadAble,
  124. downloadLoading,
  125. downloadFile,
  126. remove,
  127. removeLoading,
  128. isPreview,
  129. isDownload
  130. }
  131. }
  132. }
  133. </script>
  134. <style lang="less">
  135. .file-row{
  136. width: 100%;
  137. font-size: 14px;
  138. //line-height: 1.1em;
  139. line-height: @formItemLineHeight;
  140. padding: 4px 6px;
  141. /*display: flex;*/
  142. /*justify-content: space-between;*/
  143. /*align-items: center;*/
  144. flex-wrap: nowrap;
  145. position: relative;
  146. overflow: hidden;
  147. &:hover{
  148. background: #e6f7ff;
  149. .handle-button-wrapper{
  150. visibility: visible;
  151. top:0;
  152. left: 0;
  153. bottom: 0;
  154. }
  155. }
  156. &__file-name{
  157. display: inline-block;
  158. margin-left: 8px;
  159. text-overflow: ellipsis;
  160. white-space: nowrap;
  161. }
  162. &__process{
  163. display: flex;
  164. align-items: center;
  165. justify-content: space-between;
  166. }
  167. .handle-button-wrapper{
  168. display: flex;
  169. align-items: center;
  170. position: absolute;
  171. left: -100%;
  172. background: rgba(255,255,255,0.8);
  173. visibility: hidden;
  174. opacity: 0.9;
  175. transition: all 0.3s;
  176. padding: 0 8px;
  177. .el-button{
  178. padding: 0 4px;
  179. + .el-button{
  180. margin-left: 4px;
  181. }
  182. }
  183. }
  184. &__button{
  185. cursor: pointer;
  186. flex-shrink: 0;
  187. &+.file-row__button{
  188. margin-left:4px;
  189. }
  190. }
  191. }
  192. </style>