index.js 5.4 KB

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