Upload.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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) switch (_context.prev = _context.next) {
  95. case 0:
  96. beforeUpload = props.beforeUpload, transformFile = props.transformFile;
  97. parsedFile = file;
  98. if (!beforeUpload) {
  99. _context.next = 13;
  100. break;
  101. }
  102. _context.next = 5;
  103. return beforeUpload(file, fileListArgs);
  104. case 5:
  105. result = _context.sent;
  106. if (!(result === false)) {
  107. _context.next = 8;
  108. break;
  109. }
  110. return _context.abrupt("return", false);
  111. case 8:
  112. // Hack for LIST_IGNORE, we add additional info to remove from the list
  113. delete file[LIST_IGNORE];
  114. if (!(result === LIST_IGNORE)) {
  115. _context.next = 12;
  116. break;
  117. }
  118. Object.defineProperty(file, LIST_IGNORE, {
  119. value: true,
  120. configurable: true
  121. });
  122. return _context.abrupt("return", false);
  123. case 12:
  124. if (_typeof(result) === 'object' && result) {
  125. parsedFile = result;
  126. }
  127. case 13:
  128. if (!transformFile) {
  129. _context.next = 17;
  130. break;
  131. }
  132. _context.next = 16;
  133. return transformFile(parsedFile);
  134. case 16:
  135. parsedFile = _context.sent;
  136. case 17:
  137. return _context.abrupt("return", parsedFile);
  138. case 18:
  139. case "end":
  140. return _context.stop();
  141. }
  142. }, _callee);
  143. }));
  144. return function mergedBeforeUpload(_x, _x2) {
  145. return _ref2.apply(this, arguments);
  146. };
  147. }();
  148. var onBatchStart = function onBatchStart(batchFileInfoList) {
  149. // Skip file which marked as `LIST_IGNORE`, these file will not add to file list
  150. var filteredFileInfoList = batchFileInfoList.filter(function (info) {
  151. return !info.file[LIST_IGNORE];
  152. });
  153. // Nothing to do since no file need upload
  154. if (!filteredFileInfoList.length) {
  155. return;
  156. }
  157. var objectFileList = filteredFileInfoList.map(function (info) {
  158. return file2Obj(info.file);
  159. });
  160. // Concat new files with prev files
  161. var newFileList = _toConsumableArray(mergedFileList.value);
  162. objectFileList.forEach(function (fileObj) {
  163. // Replace file if exist
  164. newFileList = updateFileList(fileObj, newFileList);
  165. });
  166. objectFileList.forEach(function (fileObj, index) {
  167. // Repeat trigger `onChange` event for compatible
  168. var triggerFileObj = fileObj;
  169. if (!filteredFileInfoList[index].parsedFile) {
  170. // `beforeUpload` return false
  171. var originFileObj = fileObj.originFileObj;
  172. var clone;
  173. try {
  174. clone = new File([originFileObj], originFileObj.name, {
  175. type: originFileObj.type
  176. });
  177. } catch (e) {
  178. clone = new Blob([originFileObj], {
  179. type: originFileObj.type
  180. });
  181. clone.name = originFileObj.name;
  182. clone.lastModifiedDate = new Date();
  183. clone.lastModified = new Date().getTime();
  184. }
  185. clone.uid = fileObj.uid;
  186. triggerFileObj = clone;
  187. } else {
  188. // Inject `uploading` status
  189. fileObj.status = 'uploading';
  190. }
  191. onInternalChange(triggerFileObj, newFileList);
  192. });
  193. };
  194. var onSuccess = function onSuccess(response, file, xhr) {
  195. try {
  196. if (typeof response === 'string') {
  197. response = JSON.parse(response);
  198. }
  199. } catch (e) {
  200. /* do nothing */
  201. }
  202. // removed
  203. if (!getFileItem(file, mergedFileList.value)) {
  204. return;
  205. }
  206. var targetItem = file2Obj(file);
  207. targetItem.status = 'done';
  208. targetItem.percent = 100;
  209. targetItem.response = response;
  210. targetItem.xhr = xhr;
  211. var nextFileList = updateFileList(targetItem, mergedFileList.value);
  212. onInternalChange(targetItem, nextFileList);
  213. };
  214. var onProgress = function onProgress(e, file) {
  215. // removed
  216. if (!getFileItem(file, mergedFileList.value)) {
  217. return;
  218. }
  219. var targetItem = file2Obj(file);
  220. targetItem.status = 'uploading';
  221. targetItem.percent = e.percent;
  222. var nextFileList = updateFileList(targetItem, mergedFileList.value);
  223. onInternalChange(targetItem, nextFileList, e);
  224. };
  225. var onError = function onError(error, response, file) {
  226. // removed
  227. if (!getFileItem(file, mergedFileList.value)) {
  228. return;
  229. }
  230. var targetItem = file2Obj(file);
  231. targetItem.error = error;
  232. targetItem.response = response;
  233. targetItem.status = 'error';
  234. var nextFileList = updateFileList(targetItem, mergedFileList.value);
  235. onInternalChange(targetItem, nextFileList);
  236. };
  237. var handleRemove = function handleRemove(file) {
  238. var currentFile;
  239. var mergedRemove = props.onRemove || props.remove;
  240. Promise.resolve(typeof mergedRemove === 'function' ? mergedRemove(file) : mergedRemove).then(function (ret) {
  241. // Prevent removing file
  242. if (ret === false) {
  243. return;
  244. }
  245. var removedFileList = removeFileItem(file, mergedFileList.value);
  246. if (removedFileList) {
  247. var _mergedFileList$value, _upload$value;
  248. currentFile = _objectSpread(_objectSpread({}, file), {}, {
  249. status: 'removed'
  250. });
  251. (_mergedFileList$value = mergedFileList.value) === null || _mergedFileList$value === void 0 ? void 0 : _mergedFileList$value.forEach(function (item) {
  252. var matchKey = currentFile.uid !== undefined ? 'uid' : 'name';
  253. if (item[matchKey] === currentFile[matchKey] && !Object.isFrozen(item)) {
  254. item.status = 'removed';
  255. }
  256. });
  257. (_upload$value = upload.value) === null || _upload$value === void 0 ? void 0 : _upload$value.abort(currentFile);
  258. onInternalChange(currentFile, removedFileList);
  259. }
  260. });
  261. };
  262. var onFileDrop = function onFileDrop(e) {
  263. dragState.value = e.type;
  264. if (e.type === 'drop') {
  265. var _props$onDrop;
  266. (_props$onDrop = props.onDrop) === null || _props$onDrop === void 0 ? void 0 : _props$onDrop.call(props, e);
  267. }
  268. };
  269. expose({
  270. onBatchStart: onBatchStart,
  271. onSuccess: onSuccess,
  272. onProgress: onProgress,
  273. onError: onError,
  274. fileList: mergedFileList,
  275. upload: upload
  276. });
  277. var _useConfigInject = useConfigInject('upload', props),
  278. prefixCls = _useConfigInject.prefixCls,
  279. direction = _useConfigInject.direction;
  280. var _useLocaleReceiver = useLocaleReceiver('Upload', defaultLocale.Upload, computed(function () {
  281. return props.locale;
  282. })),
  283. _useLocaleReceiver2 = _slicedToArray(_useLocaleReceiver, 1),
  284. locale = _useLocaleReceiver2[0];
  285. var renderUploadList = function renderUploadList(button, buttonVisible) {
  286. var removeIcon = props.removeIcon,
  287. previewIcon = props.previewIcon,
  288. downloadIcon = props.downloadIcon,
  289. previewFile = props.previewFile,
  290. onPreview = props.onPreview,
  291. onDownload = props.onDownload,
  292. disabled = props.disabled,
  293. isImageUrl = props.isImageUrl,
  294. progress = props.progress,
  295. itemRender = props.itemRender,
  296. iconRender = props.iconRender,
  297. showUploadList = props.showUploadList;
  298. var _ref3 = typeof showUploadList === 'boolean' ? {} : showUploadList,
  299. showDownloadIcon = _ref3.showDownloadIcon,
  300. showPreviewIcon = _ref3.showPreviewIcon,
  301. showRemoveIcon = _ref3.showRemoveIcon;
  302. return showUploadList ? _createVNode(UploadList, {
  303. "listType": props.listType,
  304. "items": mergedFileList.value,
  305. "previewFile": previewFile,
  306. "onPreview": onPreview,
  307. "onDownload": onDownload,
  308. "onRemove": handleRemove,
  309. "showRemoveIcon": !disabled && showRemoveIcon,
  310. "showPreviewIcon": showPreviewIcon,
  311. "showDownloadIcon": showDownloadIcon,
  312. "removeIcon": removeIcon,
  313. "previewIcon": previewIcon,
  314. "downloadIcon": downloadIcon,
  315. "iconRender": iconRender,
  316. "locale": locale.value,
  317. "isImageUrl": isImageUrl,
  318. "progress": progress,
  319. "itemRender": itemRender,
  320. "appendActionVisible": buttonVisible,
  321. "appendAction": button
  322. }, _objectSpread({}, slots)) : button === null || button === void 0 ? void 0 : button();
  323. };
  324. return function () {
  325. var _props$id, _classNames2, _slots$default2;
  326. var listType = props.listType,
  327. disabled = props.disabled,
  328. type = props.type;
  329. var className = attrs.class,
  330. styleName = attrs.style,
  331. transAttrs = _objectWithoutProperties(attrs, _excluded);
  332. var rcUploadProps = _objectSpread(_objectSpread(_objectSpread({
  333. onBatchStart: onBatchStart,
  334. onError: onError,
  335. onProgress: onProgress,
  336. onSuccess: onSuccess
  337. }, transAttrs), props), {}, {
  338. id: (_props$id = props.id) !== null && _props$id !== void 0 ? _props$id : formItemContext.id.value,
  339. prefixCls: prefixCls.value,
  340. beforeUpload: mergedBeforeUpload,
  341. onChange: undefined
  342. });
  343. delete rcUploadProps.remove;
  344. // Remove id to avoid open by label when trigger is hidden
  345. // !children: https://github.com/ant-design/ant-design/issues/14298
  346. // disabled: https://github.com/ant-design/ant-design/issues/16478
  347. // https://github.com/ant-design/ant-design/issues/24197
  348. if (!slots.default || disabled) {
  349. delete rcUploadProps.id;
  350. }
  351. if (type === 'drag') {
  352. var _classNames, _slots$default;
  353. 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) {
  354. return file.status === 'uploading';
  355. })), _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);
  356. return _createVNode("span", null, [_createVNode("div", {
  357. "class": dragCls,
  358. "onDrop": onFileDrop,
  359. "onDragover": onFileDrop,
  360. "onDragleave": onFileDrop,
  361. "style": attrs.style
  362. }, [_createVNode(VcUpload, _objectSpread(_objectSpread({}, rcUploadProps), {}, {
  363. "ref": upload,
  364. "class": "".concat(prefixCls.value, "-btn")
  365. }), _objectSpread({
  366. default: function _default() {
  367. return [_createVNode("div", {
  368. "class": "".concat(prefixCls.value, "-drag-container")
  369. }, [(_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)])];
  370. }
  371. }, slots))]), renderUploadList()]);
  372. }
  373. 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));
  374. var children = flattenChildren((_slots$default2 = slots.default) === null || _slots$default2 === void 0 ? void 0 : _slots$default2.call(slots));
  375. var renderUploadButton = function renderUploadButton(uploadButtonStyle) {
  376. return _createVNode("div", {
  377. "class": uploadButtonCls,
  378. "style": uploadButtonStyle
  379. }, [_createVNode(VcUpload, _objectSpread(_objectSpread({}, rcUploadProps), {}, {
  380. "ref": upload
  381. }), slots)]);
  382. };
  383. if (listType === 'picture-card') {
  384. return _createVNode("span", {
  385. "class": classNames("".concat(prefixCls.value, "-picture-card-wrapper"), attrs.class)
  386. }, [renderUploadList(renderUploadButton, !!(children && children.length))]);
  387. }
  388. return _createVNode("span", {
  389. "class": attrs.class
  390. }, [renderUploadButton(children && children.length ? undefined : {
  391. display: 'none'
  392. }), renderUploadList()]);
  393. };
  394. }
  395. });