c-upload.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <template>
  2. <div id="c-upload">
  3. <el-upload
  4. v-if="url"
  5. ref="upload"
  6. :action="url"
  7. :limit="limit"
  8. :accept="accept"
  9. :file-list="list"
  10. :list-type="listType"
  11. :on-exceed="outLimit"
  12. :on-preview="filePreview"
  13. :on-success="onSuccess"
  14. :before-remove="onRemove"
  15. >
  16. <el-button type="primary">选择文件</el-button>
  17. <template #tip v-if="tip">
  18. <p style="color: #ff0000">{{ tip }}</p>
  19. </template>
  20. </el-upload>
  21. <el-dialog v-model="dialog.show" append-to-body>
  22. <img width="100%" :src="dialog.url" alt="" />
  23. </el-dialog>
  24. </div>
  25. </template>
  26. <script setup lang="ts">
  27. import type { Ref } from 'vue';
  28. import { ref, toRefs } from 'vue';
  29. import { ElMessage } from 'element-plus';
  30. import _ from 'lodash';
  31. // #region
  32. interface ListItem {
  33. errcode?: string | number;
  34. errmsg?: string;
  35. uri?: string;
  36. name?: string;
  37. url?: string;
  38. id?: any;
  39. }
  40. let dialog: Ref<{ show: boolean; url: string }> = ref({ show: false, url: '' });
  41. const props = defineProps({
  42. url: { type: String, default: () => '' },
  43. limit: { type: Number, default: () => 6 },
  44. accept: { type: String, default: () => 'image/png, image/jpeg' },
  45. listType: { type: String, default: () => 'text' }, //'text' | 'picture' | 'picture-card'
  46. tip: { type: String, default: () => undefined },
  47. list: { type: Array<ListItem>, default: () => [] },
  48. model: { type: String, default: () => '' }
  49. });
  50. // 图片上传地址
  51. const { url } = toRefs(props);
  52. // 可上传文件数目
  53. const { limit } = toRefs(props);
  54. // 接收上传的文件类型
  55. const { accept } = toRefs(props);
  56. // 文件列表的类型--picture-card---picture
  57. const { listType } = toRefs(props);
  58. // 文件提醒
  59. const { tip } = toRefs(props);
  60. // 已有数据,赋值,预览
  61. const { list } = toRefs(props);
  62. const { model } = toRefs(props);
  63. // const list = ref<UploadUserFile[]>([]);
  64. const emit = defineEmits(['change']);
  65. // 图片预览
  66. const filePreview = (file: { url: string }) => {
  67. // this.dialog = { show: true, url: file.url };
  68. window.open(file.url);
  69. };
  70. // 只允许上传多少个文件
  71. const outLimit = () => {
  72. ElMessage.error(`只允许上传${limit.value}个文件`);
  73. };
  74. // 上传成功,response:成功信息,file:图片信息,fileList:图片列表
  75. const onSuccess = (response: { errcode: string | number; errmsg: string; uri: any }, file: { name: string }) => {
  76. if (response.errcode !== 0) {
  77. ElMessage({ type: 'error', message: '删除成功' });
  78. return;
  79. }
  80. let ponse = _.omit(response, ['errcode', 'errmsg']);
  81. let arr: Ref<ListItem[]> = _.cloneDeep(list);
  82. if (_.isArray(list.value)) {
  83. arr.value.push({ ...ponse, name: file.name, url: `${import.meta.env.VITE_APP_HOST}${response.uri}` });
  84. } else {
  85. arr.value = [{ ...ponse, name: file.name, url: `${import.meta.env.VITE_APP_HOST}${response.uri}` }];
  86. }
  87. emit('change', { model: model.value, value: arr.value });
  88. };
  89. // 删除图片
  90. // file: { id: any; uri: string }, fileList: any
  91. const onRemove = () => {
  92. // let arr: Ref<ListItem[]> = _.cloneDeep(list);
  93. // let info = arr.value.filter((f) => f.id != file.id);
  94. // emit('change', info);
  95. return true;
  96. };
  97. // #endregion
  98. </script>
  99. <style lang="scss" scoped>
  100. #c-upload {
  101. width: 100%;
  102. }
  103. </style>