index.js 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { VantComponent } from '../common/component';
  2. import { isImageFile, chooseFile, isVideoFile } from './utils';
  3. import { chooseImageProps, chooseVideoProps } from './shared';
  4. import { isBoolean, isPromise } from '../common/validator';
  5. VantComponent({
  6. props: Object.assign(Object.assign({ disabled: Boolean, multiple: Boolean, uploadText: String, useBeforeRead: Boolean, afterRead: null, beforeRead: null, previewSize: {
  7. type: null,
  8. value: 80,
  9. }, name: {
  10. type: null,
  11. value: '',
  12. }, accept: {
  13. type: String,
  14. value: 'image',
  15. }, fileList: {
  16. type: Array,
  17. value: [],
  18. observer: 'formatFileList',
  19. }, maxSize: {
  20. type: Number,
  21. value: Number.MAX_VALUE,
  22. }, maxCount: {
  23. type: Number,
  24. value: 100,
  25. }, deletable: {
  26. type: Boolean,
  27. value: true,
  28. }, showUpload: {
  29. type: Boolean,
  30. value: true,
  31. }, previewImage: {
  32. type: Boolean,
  33. value: true,
  34. }, previewFullImage: {
  35. type: Boolean,
  36. value: true,
  37. }, imageFit: {
  38. type: String,
  39. value: 'scaleToFill',
  40. }, uploadIcon: {
  41. type: String,
  42. value: 'photograph',
  43. } }, chooseImageProps), chooseVideoProps),
  44. data: {
  45. lists: [],
  46. isInCount: true,
  47. },
  48. methods: {
  49. formatFileList() {
  50. const { fileList = [], maxCount } = this.data;
  51. const lists = fileList.map((item) => (Object.assign(Object.assign({}, item), { isImage: isImageFile(item), isVideo: isVideoFile(item), deletable: isBoolean(item.deletable) ? item.deletable : true })));
  52. this.setData({ lists, isInCount: lists.length < maxCount });
  53. },
  54. getDetail(index) {
  55. return {
  56. name: this.data.name,
  57. index: index == null ? this.data.fileList.length : index,
  58. };
  59. },
  60. startUpload() {
  61. const { maxCount, multiple, lists, disabled } = this.data;
  62. if (disabled)
  63. return;
  64. chooseFile(Object.assign(Object.assign({}, this.data), { maxCount: maxCount - lists.length }))
  65. .then((res) => {
  66. this.onBeforeRead(multiple ? res : res[0]);
  67. })
  68. .catch((error) => {
  69. this.$emit('error', error);
  70. });
  71. },
  72. onBeforeRead(file) {
  73. const { beforeRead, useBeforeRead } = this.data;
  74. let res = true;
  75. if (typeof beforeRead === 'function') {
  76. res = beforeRead(file, this.getDetail());
  77. }
  78. if (useBeforeRead) {
  79. res = new Promise((resolve, reject) => {
  80. this.$emit('before-read', Object.assign(Object.assign({ file }, this.getDetail()), { callback: (ok) => {
  81. ok ? resolve() : reject();
  82. } }));
  83. });
  84. }
  85. if (!res) {
  86. return;
  87. }
  88. if (isPromise(res)) {
  89. res.then((data) => this.onAfterRead(data || file));
  90. }
  91. else {
  92. this.onAfterRead(file);
  93. }
  94. },
  95. onAfterRead(file) {
  96. const { maxSize, afterRead } = this.data;
  97. const oversize = Array.isArray(file)
  98. ? file.some((item) => item.size > maxSize)
  99. : file.size > maxSize;
  100. if (oversize) {
  101. this.$emit('oversize', Object.assign({ file }, this.getDetail()));
  102. return;
  103. }
  104. if (typeof afterRead === 'function') {
  105. afterRead(file, this.getDetail());
  106. }
  107. this.$emit('after-read', Object.assign({ file }, this.getDetail()));
  108. },
  109. deleteItem(event) {
  110. const { index } = event.currentTarget.dataset;
  111. this.$emit('delete', Object.assign(Object.assign({}, this.getDetail(index)), { file: this.data.fileList[index] }));
  112. },
  113. onPreviewImage(event) {
  114. if (!this.data.previewFullImage)
  115. return;
  116. const { index } = event.currentTarget.dataset;
  117. const { lists } = this.data;
  118. const item = lists[index];
  119. wx.previewImage({
  120. urls: lists.filter((item) => isImageFile(item)).map((item) => item.url),
  121. current: item.url,
  122. fail() {
  123. wx.showToast({ title: '预览图片失败', icon: 'none' });
  124. },
  125. });
  126. },
  127. onPreviewVideo(event) {
  128. if (!this.data.previewFullImage)
  129. return;
  130. const { index } = event.currentTarget.dataset;
  131. const { lists } = this.data;
  132. wx.previewMedia({
  133. sources: lists
  134. .filter((item) => isVideoFile(item))
  135. .map((item) => (Object.assign(Object.assign({}, item), { type: 'video' }))),
  136. current: index,
  137. fail() {
  138. wx.showToast({ title: '预览视频失败', icon: 'none' });
  139. },
  140. });
  141. },
  142. onPreviewFile(event) {
  143. const { index } = event.currentTarget.dataset;
  144. wx.openDocument({
  145. filePath: this.data.lists[index].url,
  146. showMenu: true,
  147. });
  148. },
  149. onClickPreview(event) {
  150. const { index } = event.currentTarget.dataset;
  151. const item = this.data.lists[index];
  152. this.$emit('click-preview', Object.assign(Object.assign({}, item), this.getDetail(index)));
  153. },
  154. },
  155. });