Upload.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  2. import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
  3. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  4. import _typeof from "@babel/runtime/helpers/esm/typeof";
  5. import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
  6. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  7. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  8. var _excluded = ["class", "style"];
  9. import { createVNode as _createVNode, resolveDirective as _resolveDirective } from "vue";
  10. import _regeneratorRuntime from "@babel/runtime/regenerator";
  11. import VcUpload from '../vc-upload';
  12. import UploadList from './UploadList';
  13. import { uploadProps } from './interface';
  14. import { file2Obj, getFileItem, removeFileItem, updateFileList } from './utils';
  15. import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
  16. import defaultLocale from '../locale/default';
  17. import { computed, defineComponent, onMounted, ref, toRef } from 'vue';
  18. import { flattenChildren, initDefaultProps } from '../_util/props-util';
  19. import useMergedState from '../_util/hooks/useMergedState';
  20. import devWarning from '../vc-util/devWarning';
  21. import useConfigInject from '../_util/hooks/useConfigInject';
  22. import classNames from '../_util/classNames';
  23. import { useInjectFormItemContext } from '../form';
  24. export var LIST_IGNORE = "__LIST_IGNORE_".concat(Date.now(), "__");
  25. export default defineComponent({
  26. compatConfig: {
  27. MODE: 3
  28. },
  29. name: 'AUpload',
  30. inheritAttrs: false,
  31. props: initDefaultProps(uploadProps(), {
  32. type: 'select',
  33. multiple: false,
  34. action: '',
  35. data: {},
  36. accept: '',
  37. showUploadList: true,
  38. listType: 'text',
  39. disabled: false,
  40. supportServerRender: true
  41. }),
  42. setup: function setup(props, _ref) {
  43. var slots = _ref.slots,
  44. attrs = _ref.attrs,
  45. expose = _ref.expose;
  46. var formItemContext = useInjectFormItemContext();
  47. var _useMergedState = useMergedState(props.defaultFileList || [], {
  48. value: toRef(props, 'fileList'),
  49. postState: function postState(list) {
  50. var timestamp = Date.now();
  51. return (list !== null && list !== void 0 ? list : []).map(function (file, index) {
  52. if (!file.uid && !Object.isFrozen(file)) {
  53. file.uid = "__AUTO__".concat(timestamp, "_").concat(index, "__");
  54. }
  55. return file;
  56. });
  57. }
  58. }),
  59. _useMergedState2 = _slicedToArray(_useMergedState, 2),
  60. mergedFileList = _useMergedState2[0],
  61. setMergedFileList = _useMergedState2[1];
  62. var dragState = ref('drop');
  63. var upload = ref();
  64. onMounted(function () {
  65. devWarning(props.fileList !== undefined || attrs.value === undefined, 'Upload', '`value` is not a valid prop, do you mean `fileList`?');
  66. devWarning(props.transformFile === undefined, 'Upload', '`transformFile` is deprecated. Please use `beforeUpload` directly.');
  67. devWarning(props.remove === undefined, 'Upload', '`remove` props is deprecated. Please use `remove` event.');
  68. });
  69. var onInternalChange = function onInternalChange(file, changedFileList, event) {
  70. var _props$onUpdateFileL, _props$onChange;
  71. var cloneList = _toConsumableArray(changedFileList);
  72. // Cut to match count
  73. if (props.maxCount === 1) {
  74. cloneList = cloneList.slice(-1);
  75. } else if (props.maxCount) {
  76. cloneList = cloneList.slice(0, props.maxCount);
  77. }
  78. setMergedFileList(cloneList);
  79. var changeInfo = {
  80. file: file,
  81. fileList: cloneList
  82. };
  83. if (event) {
  84. changeInfo.event = event;
  85. }
  86. (_props$onUpdateFileL = props['onUpdate:fileList']) === null || _props$onUpdateFileL === void 0 ? void 0 : _props$onUpdateFileL.call(props, changeInfo.fileList);
  87. (_props$onChange = props.onChange) === null || _props$onChange === void 0 ? void 0 : _props$onChange.call(props, changeInfo);
  88. formItemContext.onFieldChange();
  89. };
  90. var mergedBeforeUpload = /*#__PURE__*/function () {
  91. var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(file, fileListArgs) {
  92. var beforeUpload, transformFile, parsedFile, result;
  93. return _regeneratorRuntime.wrap(function _callee$(_context) {
  94. while (1) {
  95. switch (_context.prev = _context.next) {
  96. case 0:
  97. beforeUpload = props.beforeUpload, transformFile = props.transformFile;
  98. parsedFile = file;
  99. if (!beforeUpload) {
  100. _context.next = 13;
  101. break;
  102. }
  103. _context.next = 5;
  104. return beforeUpload(file, fileListArgs);
  105. case 5:
  106. result = _context.sent;
  107. if (!(result === false)) {
  108. _context.next = 8;
  109. break;
  110. }
  111. return _context.abrupt("return", false);
  112. case 8:
  113. // Hack for LIST_IGNORE, we add additional info to remove from the list
  114. delete file[LIST_IGNORE];
  115. if (!(result === LIST_IGNORE)) {
  116. _context.next = 12;
  117. break;
  118. }
  119. Object.defineProperty(file, LIST_IGNORE, {
  120. value: true,
  121. configurable: true
  122. });
  123. return _context.abrupt("return", false);
  124. case 12:
  125. if (_typeof(result) === 'object' && result) {
  126. parsedFile = result;
  127. }
  128. case 13:
  129. if (!transformFile) {
  130. _context.next = 17;
  131. break;
  132. }
  133. _context.next = 16;
  134. return transformFile(parsedFile);
  135. case 16:
  136. parsedFile = _context.sent;
  137. case 17:
  138. return _context.abrupt("return", parsedFile);
  139. case 18:
  140. case "end":
  141. return _context.stop();
  142. }
  143. }
  144. }, _callee);
  145. }));
  146. return function mergedBeforeUpload(_x, _x2) {
  147. return _ref2.apply(this, arguments);
  148. };
  149. }();
  150. var onBatchStart = function onBatchStart(batchFileInfoList) {
  151. // Skip file which marked as `LIST_IGNORE`, these file will not add to file list
  152. var filteredFileInfoList = batchFileInfoList.filter(function (info) {
  153. return !info.file[LIST_IGNORE];
  154. });
  155. // Nothing to do since no file need upload
  156. if (!filteredFileInfoList.length) {
  157. return;
  158. }
  159. var objectFileList = filteredFileInfoList.map(function (info) {
  160. return file2Obj(info.file);
  161. });
  162. // Concat new files with prev files
  163. var newFileList = _toConsumableArray(mergedFileList.value);
  164. objectFileList.forEach(function (fileObj) {
  165. // Replace file if exist
  166. newFileList = updateFileList(fileObj, newFileList);
  167. });
  168. objectFileList.forEach(function (fileObj, index) {
  169. // Repeat trigger `onChange` event for compatible
  170. var triggerFileObj = fileObj;
  171. if (!filteredFileInfoList[index].parsedFile) {
  172. // `beforeUpload` return false
  173. var originFileObj = fileObj.originFileObj;
  174. var clone;
  175. try {
  176. clone = new File([originFileObj], originFileObj.name, {
  177. type: originFileObj.type
  178. });
  179. } catch (e) {
  180. clone = new Blob([originFileObj], {
  181. type: originFileObj.type
  182. });
  183. clone.name = originFileObj.name;
  184. clone.lastModifiedDate = new Date();
  185. clone.lastModified = new Date().getTime();
  186. }
  187. clone.uid = fileObj.uid;
  188. triggerFileObj = clone;
  189. } else {
  190. // Inject `uploading` status
  191. fileObj.status = 'uploading';
  192. }
  193. onInternalChange(triggerFileObj, newFileList);
  194. });
  195. };
  196. var onSuccess = function onSuccess(response, file, xhr) {
  197. try {
  198. if (typeof response === 'string') {
  199. response = JSON.parse(response);
  200. }
  201. } catch (e) {
  202. /* do nothing */
  203. }
  204. // removed
  205. if (!getFileItem(file, mergedFileList.value)) {
  206. return;
  207. }
  208. var targetItem = file2Obj(file);
  209. targetItem.status = 'done';
  210. targetItem.percent = 100;
  211. targetItem.response = response;
  212. targetItem.xhr = xhr;
  213. var nextFileList = updateFileList(targetItem, mergedFileList.value);
  214. onInternalChange(targetItem, nextFileList);
  215. };
  216. var onProgress = function onProgress(e, file) {
  217. // removed
  218. if (!getFileItem(file, mergedFileList.value)) {
  219. return;
  220. }
  221. var targetItem = file2Obj(file);
  222. targetItem.status = 'uploading';
  223. targetItem.percent = e.percent;
  224. var nextFileList = updateFileList(targetItem, mergedFileList.value);
  225. onInternalChange(targetItem, nextFileList, e);
  226. };
  227. var onError = function onError(error, response, file) {
  228. // removed
  229. if (!getFileItem(file, mergedFileList.value)) {
  230. return;
  231. }
  232. var targetItem = file2Obj(file);
  233. targetItem.error = error;
  234. targetItem.response = response;
  235. targetItem.status = 'error';
  236. var nextFileList = updateFileList(targetItem, mergedFileList.value);
  237. onInternalChange(targetItem, nextFileList);
  238. };
  239. var handleRemove = function handleRemove(file) {
  240. var currentFile;
  241. var mergedRemove = props.onRemove || props.remove;
  242. Promise.resolve(typeof mergedRemove === 'function' ? mergedRemove(file) : mergedRemove).then(function (ret) {
  243. // Prevent removing file
  244. if (ret === false) {
  245. return;
  246. }
  247. var removedFileList = removeFileItem(file, mergedFileList.value);
  248. if (removedFileList) {
  249. var _mergedFileList$value, _upload$value;
  250. currentFile = _objectSpread(_objectSpread({}, file), {}, {
  251. status: 'removed'
  252. });
  253. (_mergedFileList$value = mergedFileList.value) === null || _mergedFileList$value === void 0 ? void 0 : _mergedFileList$value.forEach(function (item) {
  254. var matchKey = currentFile.uid !== undefined ? 'uid' : 'name';
  255. if (item[matchKey] === currentFile[matchKey] && !Object.isFrozen(item)) {
  256. item.status = 'removed';
  257. }
  258. });
  259. (_upload$value = upload.value) === null || _upload$value === void 0 ? void 0 : _upload$value.abort(currentFile);
  260. onInternalChange(currentFile, removedFileList);
  261. }
  262. });
  263. };
  264. var onFileDrop = function onFileDrop(e) {
  265. dragState.value = e.type;
  266. if (e.type === 'drop') {
  267. var _props$onDrop;
  268. (_props$onDrop = props.onDrop) === null || _props$onDrop === void 0 ? void 0 : _props$onDrop.call(props, e);
  269. }
  270. };
  271. expose({
  272. onBatchStart: onBatchStart,
  273. onSuccess: onSuccess,
  274. onProgress: onProgress,
  275. onError: onError,
  276. fileList: mergedFileList,
  277. upload: upload
  278. });
  279. var _useConfigInject = useConfigInject('upload', props),
  280. prefixCls = _useConfigInject.prefixCls,
  281. direction = _useConfigInject.direction;
  282. var _useLocaleReceiver = useLocaleReceiver('Upload', defaultLocale.Upload, computed(function () {
  283. return props.locale;
  284. })),
  285. _useLocaleReceiver2 = _slicedToArray(_useLocaleReceiver, 1),
  286. locale = _useLocaleReceiver2[0];
  287. var renderUploadList = function renderUploadList(button, buttonVisible) {
  288. var removeIcon = props.removeIcon,
  289. previewIcon = props.previewIcon,
  290. downloadIcon = props.downloadIcon,
  291. previewFile = props.previewFile,
  292. onPreview = props.onPreview,
  293. onDownload = props.onDownload,
  294. disabled = props.disabled,
  295. isImageUrl = props.isImageUrl,
  296. progress = props.progress,
  297. itemRender = props.itemRender,
  298. iconRender = props.iconRender,
  299. showUploadList = props.showUploadList;
  300. var _ref3 = typeof showUploadList === 'boolean' ? {} : showUploadList,
  301. showDownloadIcon = _ref3.showDownloadIcon,
  302. showPreviewIcon = _ref3.showPreviewIcon,
  303. showRemoveIcon = _ref3.showRemoveIcon;
  304. return showUploadList ? _createVNode(UploadList, {
  305. "listType": props.listType,
  306. "items": mergedFileList.value,
  307. "previewFile": previewFile,
  308. "onPreview": onPreview,
  309. "onDownload": onDownload,
  310. "onRemove": handleRemove,
  311. "showRemoveIcon": !disabled && showRemoveIcon,
  312. "showPreviewIcon": showPreviewIcon,
  313. "showDownloadIcon": showDownloadIcon,
  314. "removeIcon": removeIcon,
  315. "previewIcon": previewIcon,
  316. "downloadIcon": downloadIcon,
  317. "iconRender": iconRender,
  318. "locale": locale.value,
  319. "isImageUrl": isImageUrl,
  320. "progress": progress,
  321. "itemRender": itemRender,
  322. "appendActionVisible": buttonVisible,
  323. "appendAction": button
  324. }, _objectSpread({}, slots)) : button === null || button === void 0 ? void 0 : button();
  325. };
  326. return function () {
  327. var _props$id, _classNames2, _slots$default2;
  328. var listType = props.listType,
  329. disabled = props.disabled,
  330. type = props.type;
  331. var className = attrs.class,
  332. styleName = attrs.style,
  333. transAttrs = _objectWithoutProperties(attrs, _excluded);
  334. var rcUploadProps = _objectSpread(_objectSpread(_objectSpread({
  335. onBatchStart: onBatchStart,
  336. onError: onError,
  337. onProgress: onProgress,
  338. onSuccess: onSuccess
  339. }, transAttrs), props), {}, {
  340. id: (_props$id = props.id) !== null && _props$id !== void 0 ? _props$id : formItemContext.id.value,
  341. prefixCls: prefixCls.value,
  342. beforeUpload: mergedBeforeUpload,
  343. onChange: undefined
  344. });
  345. delete rcUploadProps.remove;
  346. // Remove id to avoid open by label when trigger is hidden
  347. // !children: https://github.com/ant-design/ant-design/issues/14298
  348. // disabled: https://github.com/ant-design/ant-design/issues/16478
  349. // https://github.com/ant-design/ant-design/issues/24197
  350. if (!slots.default || disabled) {
  351. delete rcUploadProps.id;
  352. }
  353. if (type === 'drag') {
  354. var _classNames, _slots$default;
  355. var dragCls = classNames(prefixCls.value, (_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls.value, "-drag"), true), _defineProperty(_classNames, "".concat(prefixCls.value, "-drag-uploading"), mergedFileList.value.some(function (file) {
  356. return file.status === 'uploading';
  357. })), _defineProperty(_classNames, "".concat(prefixCls.value, "-drag-hover"), dragState.value === 'dragover'), _defineProperty(_classNames, "".concat(prefixCls.value, "-disabled"), disabled), _defineProperty(_classNames, "".concat(prefixCls.value, "-rtl"), direction.value === 'rtl'), _classNames), attrs.class);
  358. return _createVNode("span", null, [_createVNode("div", {
  359. "class": dragCls,
  360. "onDrop": onFileDrop,
  361. "onDragover": onFileDrop,
  362. "onDragleave": onFileDrop,
  363. "style": attrs.style
  364. }, [_createVNode(VcUpload, _objectSpread(_objectSpread({}, rcUploadProps), {}, {
  365. "ref": upload,
  366. "class": "".concat(prefixCls.value, "-btn")
  367. }), _objectSpread({
  368. default: function _default() {
  369. return [_createVNode("div", {
  370. "class": "".concat(prefixCls, "-drag-container")
  371. }, [(_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)])];
  372. }
  373. }, slots))]), renderUploadList()]);
  374. }
  375. var uploadButtonCls = classNames(prefixCls.value, (_classNames2 = {}, _defineProperty(_classNames2, "".concat(prefixCls.value, "-select"), true), _defineProperty(_classNames2, "".concat(prefixCls.value, "-select-").concat(listType), true), _defineProperty(_classNames2, "".concat(prefixCls.value, "-disabled"), disabled), _defineProperty(_classNames2, "".concat(prefixCls.value, "-rtl"), direction.value === 'rtl'), _classNames2));
  376. var children = flattenChildren((_slots$default2 = slots.default) === null || _slots$default2 === void 0 ? void 0 : _slots$default2.call(slots));
  377. var renderUploadButton = function renderUploadButton(uploadButtonStyle) {
  378. return _createVNode("div", {
  379. "class": uploadButtonCls,
  380. "style": uploadButtonStyle
  381. }, [_createVNode(VcUpload, _objectSpread(_objectSpread({}, rcUploadProps), {}, {
  382. "ref": upload
  383. }), slots)]);
  384. };
  385. if (listType === 'picture-card') {
  386. return _createVNode("span", {
  387. "class": classNames("".concat(prefixCls.value, "-picture-card-wrapper"), attrs.class)
  388. }, [renderUploadList(renderUploadButton, !!(children && children.length))]);
  389. }
  390. return _createVNode("span", {
  391. "class": attrs.class
  392. }, [renderUploadButton(children && children.length ? undefined : {
  393. display: 'none'
  394. }), renderUploadList()]);
  395. };
  396. }
  397. });