index.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  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. created: function created() {
  96. this.urls = [];
  97. },
  98. beforeDestroy: function beforeDestroy() {
  99. this.urls.forEach(function (url) {
  100. return URL.revokeObjectURL(url);
  101. });
  102. },
  103. methods: {
  104. getDetail: function getDetail(index) {
  105. if (index === void 0) {
  106. index = this.fileList.length;
  107. }
  108. return {
  109. name: this.name,
  110. index: index
  111. };
  112. },
  113. onChange: function onChange(event) {
  114. var _this = this;
  115. var files = event.target.files;
  116. if (this.disabled || !files.length) {
  117. return;
  118. }
  119. files = files.length === 1 ? files[0] : [].slice.call(files);
  120. if (this.beforeRead) {
  121. var response = this.beforeRead(files, this.getDetail());
  122. if (!response) {
  123. this.resetInput();
  124. return;
  125. }
  126. if ((0, _utils.isPromise)(response)) {
  127. response.then(function (data) {
  128. if (data) {
  129. _this.readFile(data);
  130. } else {
  131. _this.readFile(files);
  132. }
  133. }).catch(this.resetInput);
  134. return;
  135. }
  136. }
  137. this.readFile(files);
  138. },
  139. readFile: function readFile(files) {
  140. var _this2 = this;
  141. var oversize = (0, _utils2.isOversize)(files, this.maxSize);
  142. if (Array.isArray(files)) {
  143. var maxCount = this.maxCount - this.fileList.length;
  144. if (files.length > maxCount) {
  145. files = files.slice(0, maxCount);
  146. }
  147. Promise.all(files.map(function (file) {
  148. return (0, _utils2.readFile)(file, _this2.resultType);
  149. })).then(function (contents) {
  150. var fileList = files.map(function (file, index) {
  151. var result = {
  152. file: file,
  153. status: '',
  154. message: ''
  155. };
  156. if (contents[index]) {
  157. result.content = contents[index];
  158. }
  159. return result;
  160. });
  161. _this2.onAfterRead(fileList, oversize);
  162. });
  163. } else {
  164. (0, _utils2.readFile)(files, this.resultType).then(function (content) {
  165. var result = {
  166. file: files,
  167. status: '',
  168. message: ''
  169. };
  170. if (content) {
  171. result.content = content;
  172. }
  173. _this2.onAfterRead(result, oversize);
  174. });
  175. }
  176. },
  177. onAfterRead: function onAfterRead(files, oversize) {
  178. var _this3 = this;
  179. this.resetInput();
  180. var validFiles = files;
  181. if (oversize) {
  182. var oversizeFiles = files;
  183. if (Array.isArray(files)) {
  184. oversizeFiles = [];
  185. validFiles = [];
  186. files.forEach(function (item) {
  187. if (item.file) {
  188. if ((0, _utils2.isOversize)(item.file, _this3.maxSize)) {
  189. oversizeFiles.push(item);
  190. } else {
  191. validFiles.push(item);
  192. }
  193. }
  194. });
  195. } else {
  196. validFiles = null;
  197. }
  198. this.$emit('oversize', oversizeFiles, this.getDetail());
  199. }
  200. var isValidFiles = Array.isArray(validFiles) ? Boolean(validFiles.length) : Boolean(validFiles);
  201. if (isValidFiles) {
  202. this.$emit('input', [].concat(this.fileList, (0, _utils2.toArray)(validFiles)));
  203. if (this.afterRead) {
  204. this.afterRead(validFiles, this.getDetail());
  205. }
  206. }
  207. },
  208. onDelete: function onDelete(file, index) {
  209. var _file$beforeDelete,
  210. _this4 = this;
  211. var beforeDelete = (_file$beforeDelete = file.beforeDelete) != null ? _file$beforeDelete : this.beforeDelete;
  212. if (beforeDelete) {
  213. var response = beforeDelete(file, this.getDetail(index));
  214. if (!response) {
  215. return;
  216. }
  217. if ((0, _utils.isPromise)(response)) {
  218. response.then(function () {
  219. _this4.deleteFile(file, index);
  220. }).catch(_utils.noop);
  221. return;
  222. }
  223. }
  224. this.deleteFile(file, index);
  225. },
  226. deleteFile: function deleteFile(file, index) {
  227. var fileList = this.fileList.slice(0);
  228. fileList.splice(index, 1);
  229. this.$emit('input', fileList);
  230. this.$emit('delete', file, this.getDetail(index));
  231. },
  232. resetInput: function resetInput() {
  233. /* istanbul ignore else */
  234. if (this.$refs.input) {
  235. this.$refs.input.value = '';
  236. }
  237. },
  238. onClickUpload: function onClickUpload(event) {
  239. this.$emit('click-upload', event);
  240. },
  241. onPreviewImage: function onPreviewImage(item) {
  242. var _this5 = this;
  243. if (!this.previewFullImage) {
  244. return;
  245. }
  246. var imageFiles = this.fileList.filter(function (item) {
  247. return (0, _utils2.isImageFile)(item);
  248. });
  249. var imageContents = imageFiles.map(function (item) {
  250. if (item.file && !item.url && item.status !== 'failed') {
  251. item.url = URL.createObjectURL(item.file);
  252. _this5.urls.push(item.url);
  253. }
  254. return item.url;
  255. });
  256. this.imagePreview = (0, _imagePreview.default)((0, _extends2.default)({
  257. images: imageContents,
  258. startPosition: imageFiles.indexOf(item),
  259. onClose: function onClose() {
  260. _this5.$emit('close-preview');
  261. }
  262. }, this.previewOptions));
  263. },
  264. // @exposed-api
  265. closeImagePreview: function closeImagePreview() {
  266. if (this.imagePreview) {
  267. this.imagePreview.close();
  268. }
  269. },
  270. // @exposed-api
  271. chooseFile: function chooseFile() {
  272. if (this.disabled) {
  273. return;
  274. }
  275. /* istanbul ignore else */
  276. if (this.$refs.input) {
  277. this.$refs.input.click();
  278. }
  279. },
  280. genPreviewMask: function genPreviewMask(item) {
  281. var h = this.$createElement;
  282. var status = item.status,
  283. message = item.message;
  284. if (status === 'uploading' || status === 'failed') {
  285. var MaskIcon = status === 'failed' ? h(_icon.default, {
  286. "attrs": {
  287. "name": "close"
  288. },
  289. "class": bem('mask-icon')
  290. }) : h(_loading.default, {
  291. "class": bem('loading')
  292. });
  293. var showMessage = (0, _utils.isDef)(message) && message !== '';
  294. return h("div", {
  295. "class": bem('mask')
  296. }, [MaskIcon, showMessage && h("div", {
  297. "class": bem('mask-message')
  298. }, [message])]);
  299. }
  300. },
  301. genPreviewItem: function genPreviewItem(item, index) {
  302. var _item$deletable,
  303. _this6 = this,
  304. _item$previewSize,
  305. _item$imageFit;
  306. var h = this.$createElement;
  307. var deleteAble = (_item$deletable = item.deletable) != null ? _item$deletable : this.deletable;
  308. var showDelete = item.status !== 'uploading' && deleteAble;
  309. var DeleteIcon = showDelete && h("div", {
  310. "class": bem('preview-delete'),
  311. "on": {
  312. "click": function click(event) {
  313. event.stopPropagation();
  314. _this6.onDelete(item, index);
  315. }
  316. }
  317. }, [h(_icon.default, {
  318. "attrs": {
  319. "name": "cross"
  320. },
  321. "class": bem('preview-delete-icon')
  322. })]);
  323. var PreviewCoverContent = this.slots('preview-cover', (0, _extends2.default)({
  324. index: index
  325. }, item));
  326. var PreviewCover = PreviewCoverContent && h("div", {
  327. "class": bem('preview-cover')
  328. }, [PreviewCoverContent]);
  329. var previewSize = (_item$previewSize = item.previewSize) != null ? _item$previewSize : this.previewSize;
  330. var imageFit = (_item$imageFit = item.imageFit) != null ? _item$imageFit : this.imageFit;
  331. var Preview = (0, _utils2.isImageFile)(item) ? h(_image.default, {
  332. "attrs": {
  333. "fit": imageFit,
  334. "src": item.content || item.url,
  335. "width": previewSize,
  336. "height": previewSize,
  337. "lazyLoad": this.lazyLoad
  338. },
  339. "class": bem('preview-image'),
  340. "on": {
  341. "click": function click() {
  342. _this6.onPreviewImage(item);
  343. }
  344. }
  345. }, [PreviewCover]) : h("div", {
  346. "class": bem('file'),
  347. "style": {
  348. width: this.previewSizeWithUnit,
  349. height: this.previewSizeWithUnit
  350. }
  351. }, [h(_icon.default, {
  352. "class": bem('file-icon'),
  353. "attrs": {
  354. "name": "description"
  355. }
  356. }), h("div", {
  357. "class": [bem('file-name'), 'van-ellipsis']
  358. }, [item.file ? item.file.name : item.url]), PreviewCover]);
  359. return h("div", {
  360. "class": bem('preview'),
  361. "on": {
  362. "click": function click() {
  363. _this6.$emit('click-preview', item, _this6.getDetail(index));
  364. }
  365. }
  366. }, [Preview, this.genPreviewMask(item), DeleteIcon]);
  367. },
  368. genPreviewList: function genPreviewList() {
  369. if (this.previewImage) {
  370. return this.fileList.map(this.genPreviewItem);
  371. }
  372. },
  373. genUpload: function genUpload() {
  374. var h = this.$createElement;
  375. if (this.fileList.length >= this.maxCount) {
  376. return;
  377. }
  378. var slot = this.slots();
  379. var Input = this.readonly ? null : h("input", {
  380. "attrs": (0, _extends2.default)({}, this.$attrs, {
  381. "type": "file",
  382. "accept": this.accept,
  383. "disabled": this.disabled
  384. }),
  385. "ref": "input",
  386. "class": bem('input'),
  387. "on": {
  388. "change": this.onChange
  389. }
  390. });
  391. if (slot) {
  392. return h("div", {
  393. "class": bem('input-wrapper'),
  394. "key": "input-wrapper",
  395. "on": {
  396. "click": this.onClickUpload
  397. }
  398. }, [slot, Input]);
  399. }
  400. var style;
  401. if (this.previewSize) {
  402. var size = this.previewSizeWithUnit;
  403. style = {
  404. width: size,
  405. height: size
  406. };
  407. }
  408. return h("div", {
  409. "directives": [{
  410. name: "show",
  411. value: this.showUpload
  412. }],
  413. "class": bem('upload', {
  414. readonly: this.readonly
  415. }),
  416. "style": style,
  417. "on": {
  418. "click": this.onClickUpload
  419. }
  420. }, [h(_icon.default, {
  421. "attrs": {
  422. "name": this.uploadIcon
  423. },
  424. "class": bem('upload-icon')
  425. }), this.uploadText && h("span", {
  426. "class": bem('upload-text')
  427. }, [this.uploadText]), Input]);
  428. }
  429. },
  430. render: function render() {
  431. var h = arguments[0];
  432. return h("div", {
  433. "class": bem()
  434. }, [h("div", {
  435. "class": bem('wrapper', {
  436. disabled: this.disabled
  437. })
  438. }, [this.genPreviewList(), this.genUpload()])]);
  439. }
  440. });
  441. exports.default = _default2;