index.js 6.4 KB

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