index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. exports.__esModule = true;
  4. exports.default = void 0;
  5. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  6. var _utils = require("../utils");
  7. var _utils2 = require("./utils");
  8. var _field = require("../mixins/field");
  9. var _icon = _interopRequireDefault(require("../icon"));
  10. var _image = _interopRequireDefault(require("../image"));
  11. var _loading = _interopRequireDefault(require("../loading"));
  12. var _imagePreview = _interopRequireDefault(require("../image-preview"));
  13. // Utils
  14. // Mixins
  15. // Components
  16. var _createNamespace = (0, _utils.createNamespace)('uploader'),
  17. createComponent = _createNamespace[0],
  18. bem = _createNamespace[1];
  19. var _default2 = createComponent({
  20. inheritAttrs: false,
  21. mixins: [_field.FieldMixin],
  22. model: {
  23. prop: 'fileList'
  24. },
  25. props: {
  26. disabled: Boolean,
  27. readonly: Boolean,
  28. lazyLoad: Boolean,
  29. uploadText: String,
  30. afterRead: Function,
  31. beforeRead: Function,
  32. beforeDelete: Function,
  33. previewSize: [Number, String],
  34. previewOptions: Object,
  35. name: {
  36. type: [Number, String],
  37. default: ''
  38. },
  39. accept: {
  40. type: String,
  41. default: 'image/*'
  42. },
  43. fileList: {
  44. type: Array,
  45. default: function _default() {
  46. return [];
  47. }
  48. },
  49. maxSize: {
  50. type: [Number, String, Function],
  51. default: Number.MAX_VALUE
  52. },
  53. maxCount: {
  54. type: [Number, String],
  55. default: Number.MAX_VALUE
  56. },
  57. deletable: {
  58. type: Boolean,
  59. default: true
  60. },
  61. showUpload: {
  62. type: Boolean,
  63. default: true
  64. },
  65. previewImage: {
  66. type: Boolean,
  67. default: true
  68. },
  69. previewFullImage: {
  70. type: Boolean,
  71. default: true
  72. },
  73. imageFit: {
  74. type: String,
  75. default: 'cover'
  76. },
  77. resultType: {
  78. type: String,
  79. default: 'dataUrl'
  80. },
  81. uploadIcon: {
  82. type: String,
  83. default: 'photograph'
  84. }
  85. },
  86. computed: {
  87. previewSizeWithUnit: function previewSizeWithUnit() {
  88. return (0, _utils.addUnit)(this.previewSize);
  89. },
  90. // for form
  91. value: function value() {
  92. return this.fileList;
  93. }
  94. },
  95. methods: {
  96. getDetail: function getDetail(index) {
  97. if (index === void 0) {
  98. index = this.fileList.length;
  99. }
  100. return {
  101. name: this.name,
  102. index: index
  103. };
  104. },
  105. onChange: function onChange(event) {
  106. var _this = this;
  107. var files = event.target.files;
  108. if (this.disabled || !files.length) {
  109. return;
  110. }
  111. files = files.length === 1 ? files[0] : [].slice.call(files);
  112. if (this.beforeRead) {
  113. var response = this.beforeRead(files, this.getDetail());
  114. if (!response) {
  115. this.resetInput();
  116. return;
  117. }
  118. if ((0, _utils.isPromise)(response)) {
  119. response.then(function (data) {
  120. if (data) {
  121. _this.readFile(data);
  122. } else {
  123. _this.readFile(files);
  124. }
  125. }).catch(this.resetInput);
  126. return;
  127. }
  128. }
  129. this.readFile(files);
  130. },
  131. readFile: function readFile(files) {
  132. var _this2 = this;
  133. var oversize = (0, _utils2.isOversize)(files, this.maxSize);
  134. if (Array.isArray(files)) {
  135. var maxCount = this.maxCount - this.fileList.length;
  136. if (files.length > maxCount) {
  137. files = files.slice(0, maxCount);
  138. }
  139. Promise.all(files.map(function (file) {
  140. return (0, _utils2.readFile)(file, _this2.resultType);
  141. })).then(function (contents) {
  142. var fileList = files.map(function (file, index) {
  143. var result = {
  144. file: file,
  145. status: '',
  146. message: ''
  147. };
  148. if (contents[index]) {
  149. result.content = contents[index];
  150. }
  151. return result;
  152. });
  153. _this2.onAfterRead(fileList, oversize);
  154. });
  155. } else {
  156. (0, _utils2.readFile)(files, this.resultType).then(function (content) {
  157. var result = {
  158. file: files,
  159. status: '',
  160. message: ''
  161. };
  162. if (content) {
  163. result.content = content;
  164. }
  165. _this2.onAfterRead(result, oversize);
  166. });
  167. }
  168. },
  169. onAfterRead: function onAfterRead(files, oversize) {
  170. var _this3 = this;
  171. this.resetInput();
  172. var validFiles = files;
  173. if (oversize) {
  174. var oversizeFiles = files;
  175. if (Array.isArray(files)) {
  176. oversizeFiles = [];
  177. validFiles = [];
  178. files.forEach(function (item) {
  179. if (item.file) {
  180. if ((0, _utils2.isOversize)(item.file, _this3.maxSize)) {
  181. oversizeFiles.push(item);
  182. } else {
  183. validFiles.push(item);
  184. }
  185. }
  186. });
  187. } else {
  188. validFiles = null;
  189. }
  190. this.$emit('oversize', oversizeFiles, this.getDetail());
  191. }
  192. var isValidFiles = Array.isArray(validFiles) ? Boolean(validFiles.length) : Boolean(validFiles);
  193. if (isValidFiles) {
  194. this.$emit('input', [].concat(this.fileList, (0, _utils2.toArray)(validFiles)));
  195. if (this.afterRead) {
  196. this.afterRead(validFiles, this.getDetail());
  197. }
  198. }
  199. },
  200. onDelete: function onDelete(file, index) {
  201. var _file$beforeDelete,
  202. _this4 = this;
  203. var beforeDelete = (_file$beforeDelete = file.beforeDelete) != null ? _file$beforeDelete : this.beforeDelete;
  204. if (beforeDelete) {
  205. var response = beforeDelete(file, this.getDetail(index));
  206. if (!response) {
  207. return;
  208. }
  209. if ((0, _utils.isPromise)(response)) {
  210. response.then(function () {
  211. _this4.deleteFile(file, index);
  212. }).catch(_utils.noop);
  213. return;
  214. }
  215. }
  216. this.deleteFile(file, index);
  217. },
  218. deleteFile: function deleteFile(file, index) {
  219. var fileList = this.fileList.slice(0);
  220. fileList.splice(index, 1);
  221. this.$emit('input', fileList);
  222. this.$emit('delete', file, this.getDetail(index));
  223. },
  224. resetInput: function resetInput() {
  225. /* istanbul ignore else */
  226. if (this.$refs.input) {
  227. this.$refs.input.value = '';
  228. }
  229. },
  230. onClickUpload: function onClickUpload(event) {
  231. this.$emit('click-upload', event);
  232. },
  233. onPreviewImage: function onPreviewImage(item) {
  234. var _this5 = this;
  235. if (!this.previewFullImage) {
  236. return;
  237. }
  238. var imageFiles = this.fileList.filter(function (item) {
  239. return (0, _utils2.isImageFile)(item);
  240. });
  241. var imageContents = imageFiles.map(function (item) {
  242. return item.content || item.url;
  243. });
  244. this.imagePreview = (0, _imagePreview.default)((0, _extends2.default)({
  245. images: imageContents,
  246. startPosition: imageFiles.indexOf(item),
  247. onClose: function onClose() {
  248. _this5.$emit('close-preview');
  249. }
  250. }, this.previewOptions));
  251. },
  252. // @exposed-api
  253. closeImagePreview: function closeImagePreview() {
  254. if (this.imagePreview) {
  255. this.imagePreview.close();
  256. }
  257. },
  258. // @exposed-api
  259. chooseFile: function chooseFile() {
  260. if (this.disabled) {
  261. return;
  262. }
  263. /* istanbul ignore else */
  264. if (this.$refs.input) {
  265. this.$refs.input.click();
  266. }
  267. },
  268. genPreviewMask: function genPreviewMask(item) {
  269. var h = this.$createElement;
  270. var status = item.status,
  271. message = item.message;
  272. if (status === 'uploading' || status === 'failed') {
  273. var MaskIcon = status === 'failed' ? h(_icon.default, {
  274. "attrs": {
  275. "name": "close"
  276. },
  277. "class": bem('mask-icon')
  278. }) : h(_loading.default, {
  279. "class": bem('loading')
  280. });
  281. var showMessage = (0, _utils.isDef)(message) && message !== '';
  282. return h("div", {
  283. "class": bem('mask')
  284. }, [MaskIcon, showMessage && h("div", {
  285. "class": bem('mask-message')
  286. }, [message])]);
  287. }
  288. },
  289. genPreviewItem: function genPreviewItem(item, index) {
  290. var _item$deletable,
  291. _this6 = this,
  292. _item$previewSize,
  293. _item$imageFit;
  294. var h = this.$createElement;
  295. var deleteAble = (_item$deletable = item.deletable) != null ? _item$deletable : this.deletable;
  296. var showDelete = item.status !== 'uploading' && deleteAble;
  297. var DeleteIcon = showDelete && h("div", {
  298. "class": bem('preview-delete'),
  299. "on": {
  300. "click": function click(event) {
  301. event.stopPropagation();
  302. _this6.onDelete(item, index);
  303. }
  304. }
  305. }, [h(_icon.default, {
  306. "attrs": {
  307. "name": "cross"
  308. },
  309. "class": bem('preview-delete-icon')
  310. })]);
  311. var PreviewCoverContent = this.slots('preview-cover', (0, _extends2.default)({
  312. index: index
  313. }, item));
  314. var PreviewCover = PreviewCoverContent && h("div", {
  315. "class": bem('preview-cover')
  316. }, [PreviewCoverContent]);
  317. var previewSize = (_item$previewSize = item.previewSize) != null ? _item$previewSize : this.previewSize;
  318. var imageFit = (_item$imageFit = item.imageFit) != null ? _item$imageFit : this.imageFit;
  319. var Preview = (0, _utils2.isImageFile)(item) ? h(_image.default, {
  320. "attrs": {
  321. "fit": imageFit,
  322. "src": item.content || item.url,
  323. "width": previewSize,
  324. "height": previewSize,
  325. "lazyLoad": this.lazyLoad
  326. },
  327. "class": bem('preview-image'),
  328. "on": {
  329. "click": function click() {
  330. _this6.onPreviewImage(item);
  331. }
  332. }
  333. }, [PreviewCover]) : h("div", {
  334. "class": bem('file'),
  335. "style": {
  336. width: this.previewSizeWithUnit,
  337. height: this.previewSizeWithUnit
  338. }
  339. }, [h(_icon.default, {
  340. "class": bem('file-icon'),
  341. "attrs": {
  342. "name": "description"
  343. }
  344. }), h("div", {
  345. "class": [bem('file-name'), 'van-ellipsis']
  346. }, [item.file ? item.file.name : item.url]), PreviewCover]);
  347. return h("div", {
  348. "class": bem('preview'),
  349. "on": {
  350. "click": function click() {
  351. _this6.$emit('click-preview', item, _this6.getDetail(index));
  352. }
  353. }
  354. }, [Preview, this.genPreviewMask(item), DeleteIcon]);
  355. },
  356. genPreviewList: function genPreviewList() {
  357. if (this.previewImage) {
  358. return this.fileList.map(this.genPreviewItem);
  359. }
  360. },
  361. genUpload: function genUpload() {
  362. var h = this.$createElement;
  363. if (this.fileList.length >= this.maxCount || !this.showUpload) {
  364. return;
  365. }
  366. var slot = this.slots();
  367. var Input = this.readonly ? null : h("input", {
  368. "attrs": (0, _extends2.default)({}, this.$attrs, {
  369. "type": "file",
  370. "accept": this.accept,
  371. "disabled": this.disabled
  372. }),
  373. "ref": "input",
  374. "class": bem('input'),
  375. "on": {
  376. "change": this.onChange
  377. }
  378. });
  379. if (slot) {
  380. return h("div", {
  381. "class": bem('input-wrapper'),
  382. "key": "input-wrapper",
  383. "on": {
  384. "click": this.onClickUpload
  385. }
  386. }, [slot, Input]);
  387. }
  388. var style;
  389. if (this.previewSize) {
  390. var size = this.previewSizeWithUnit;
  391. style = {
  392. width: size,
  393. height: size
  394. };
  395. }
  396. return h("div", {
  397. "class": bem('upload', {
  398. readonly: this.readonly
  399. }),
  400. "style": style,
  401. "on": {
  402. "click": this.onClickUpload
  403. }
  404. }, [h(_icon.default, {
  405. "attrs": {
  406. "name": this.uploadIcon
  407. },
  408. "class": bem('upload-icon')
  409. }), this.uploadText && h("span", {
  410. "class": bem('upload-text')
  411. }, [this.uploadText]), Input]);
  412. }
  413. },
  414. render: function render() {
  415. var h = arguments[0];
  416. return h("div", {
  417. "class": bem()
  418. }, [h("div", {
  419. "class": bem('wrapper', {
  420. disabled: this.disabled
  421. })
  422. }, [this.genPreviewList(), this.genUpload()])]);
  423. }
  424. });
  425. exports.default = _default2;