sa-uploader.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. const SaUploader = {
  2. template: `
  3. <div class="sa-uploader">
  4. <draggable class="sa-flex sa-flex-wrap" v-model="urlList" :animation="300" item-key="element"
  5. handle=".sortable-drag" @end="emit('update:modelValue', multiple ? urlList : urlList.join(','))">
  6. <template #item="{ element, index }">
  7. <div class="sa-uploader-item" :style="itemStyle">
  8. <template v-if="element.includes('.avi') || element.includes('.mov') || element.includes('.rmvb') || element.includes('.rm')
  9. || element.includes('.flv') || element.includes('.mp4') || element.includes('.3gp')
  10. ">
  11. <el-dialog class="sa-dialog-video sa-dialog" v-model="previewVisible" fullscreen>123
  12. <video :src="Fast.api.cdnurl(element)" controls></video>
  13. </el-dialog>
  14. <video class="sa-video" :src="Fast.api.cdnurl(element)" @click.stop="previewVisible = true"></video>
  15. </template>
  16. <el-image v-else :ref="'imageRef_'+index" :src="Fast.api.cdnurl(element)" fit="contain"
  17. :preview-src-list="[Fast.api.cdnurl(element)]" :preview-teleported="true"
  18. @load="onImageLoaded"
  19. >
  20. <template #error>
  21. <el-icon>
  22. <Picture />
  23. </el-icon>
  24. </template>
  25. </el-image>
  26. <div class="mask">
  27. <el-icon v-if="multiple" class="sortable-drag">
  28. <Rank />
  29. </el-icon>
  30. <el-icon @click="onDeleteFile(index)">
  31. <CircleCloseFilled />
  32. </el-icon>
  33. </div>
  34. </div>
  35. </template>
  36. </draggable>
  37. <div v-if="multiple || (!multiple && urlList.length==0)" class="sa-uploader-item add" :style="itemStyle"
  38. @click="onSelectFile">
  39. <el-image fit="contain">
  40. <template #error>
  41. <el-icon>
  42. <Plus />
  43. </el-icon>
  44. </template>
  45. </el-image>
  46. </div>
  47. </div>`,
  48. emit: ['update:modelValue', 'success'],
  49. props: {
  50. modelValue: {
  51. type: [Array, String],
  52. default: ''
  53. },
  54. size: {
  55. type: [String, Number],
  56. default: ''
  57. },
  58. multiple: {
  59. type: Boolean,
  60. default: false
  61. },
  62. type: {
  63. type: String,
  64. default: ''
  65. },
  66. },
  67. setup(props, { emit }) {
  68. const { ref, computed, watch, nextTick, getCurrentInstance } = Vue
  69. const { proxy } = getCurrentInstance();
  70. const urlList = ref(props.modelValue ? isArray(props.modelValue) ? props.modelValue : props.modelValue.split(',') : [])
  71. watch(() => props.modelValue, () => {
  72. urlList.value = props.modelValue ? isArray(props.modelValue) ? props.modelValue : props.modelValue.split(',') : []
  73. })
  74. const itemStyle = computed(() => ({
  75. width: `${props.size}px`,
  76. height: `${props.size}px`
  77. }))
  78. const previewVisible = ref(false)
  79. // 图片加载完毕
  80. function onImageLoaded() {
  81. nextTick(() => {
  82. if (props.type === 'size') {
  83. emit('success', { image_width: proxy.$refs.imageRef_0._.refs.container.firstChild.naturalWidth, image_height: proxy.$refs.imageRef_0._.refs.container.firstChild.naturalHeight })
  84. }
  85. })
  86. }
  87. function onSelectFile() {
  88. Fast.api.open(`general/attachment/select?multiple=${props.multiple}`, "选择", {
  89. callback: function (data) {
  90. data.url.split(',').forEach(item => {
  91. urlList.value.push(item)
  92. });
  93. emit('update:modelValue', props.multiple ? urlList.value : urlList.value.join(','))
  94. }
  95. });
  96. }
  97. function onDeleteFile(index) {
  98. urlList.value.splice(index, 1)
  99. emit('update:modelValue', props.multiple ? urlList.value : urlList.value.join(','))
  100. }
  101. return {
  102. Fast,
  103. props,
  104. emit,
  105. urlList,
  106. itemStyle,
  107. previewVisible,
  108. onSelectFile,
  109. onDeleteFile,
  110. onImageLoaded
  111. }
  112. }
  113. }