index.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import { withDirectives as _withDirectives, vShow as _vShow, resolveDirective as _resolveDirective, createVNode as _createVNode } from "vue";
  4. import LoadingOutlined from "@ant-design/icons-vue/es/icons/LoadingOutlined";
  5. import PaperClipOutlined from "@ant-design/icons-vue/es/icons/PaperClipOutlined";
  6. import PictureTwoTone from "@ant-design/icons-vue/es/icons/PictureTwoTone";
  7. import FileTwoTone from "@ant-design/icons-vue/es/icons/FileTwoTone";
  8. import { uploadListProps } from '../interface';
  9. import { previewImage, isImageUrl } from '../utils';
  10. import Button from '../../button';
  11. import ListItem from './ListItem';
  12. import { triggerRef, watch, computed, defineComponent, onMounted, shallowRef, watchEffect } from 'vue';
  13. import { filterEmpty, initDefaultProps, isValidElement } from '../../_util/props-util';
  14. import useConfigInject from '../../config-provider/hooks/useConfigInject';
  15. import { getTransitionGroupProps, TransitionGroup } from '../../_util/transition';
  16. import collapseMotion from '../../_util/collapseMotion';
  17. const HackSlot = (_, _ref) => {
  18. let {
  19. slots
  20. } = _ref;
  21. var _a;
  22. return filterEmpty((_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots))[0];
  23. };
  24. export default defineComponent({
  25. compatConfig: {
  26. MODE: 3
  27. },
  28. name: 'AUploadList',
  29. props: initDefaultProps(uploadListProps(), {
  30. listType: 'text',
  31. progress: {
  32. strokeWidth: 2,
  33. showInfo: false
  34. },
  35. showRemoveIcon: true,
  36. showDownloadIcon: false,
  37. showPreviewIcon: true,
  38. previewFile: previewImage,
  39. isImageUrl,
  40. items: [],
  41. appendActionVisible: true
  42. }),
  43. setup(props, _ref2) {
  44. let {
  45. slots,
  46. expose
  47. } = _ref2;
  48. const motionAppear = shallowRef(false);
  49. onMounted(() => {
  50. motionAppear.value == true;
  51. });
  52. const mergedItems = shallowRef([]);
  53. watch(() => props.items, function () {
  54. let val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  55. mergedItems.value = val.slice();
  56. }, {
  57. immediate: true,
  58. deep: true
  59. });
  60. watchEffect(() => {
  61. if (props.listType !== 'picture' && props.listType !== 'picture-card') {
  62. return;
  63. }
  64. let hasUpdate = false;
  65. (props.items || []).forEach((file, index) => {
  66. if (typeof document === 'undefined' || typeof window === 'undefined' || !window.FileReader || !window.File || !(file.originFileObj instanceof File || file.originFileObj instanceof Blob) || file.thumbUrl !== undefined) {
  67. return;
  68. }
  69. file.thumbUrl = '';
  70. if (props.previewFile) {
  71. props.previewFile(file.originFileObj).then(previewDataUrl => {
  72. // Need append '' to avoid dead loop
  73. const thumbUrl = previewDataUrl || '';
  74. if (thumbUrl !== file.thumbUrl) {
  75. mergedItems.value[index].thumbUrl = thumbUrl;
  76. hasUpdate = true;
  77. }
  78. });
  79. }
  80. });
  81. if (hasUpdate) {
  82. triggerRef(mergedItems);
  83. }
  84. });
  85. // ============================= Events =============================
  86. const onInternalPreview = (file, e) => {
  87. if (!props.onPreview) {
  88. return;
  89. }
  90. e === null || e === void 0 ? void 0 : e.preventDefault();
  91. return props.onPreview(file);
  92. };
  93. const onInternalDownload = file => {
  94. if (typeof props.onDownload === 'function') {
  95. props.onDownload(file);
  96. } else if (file.url) {
  97. window.open(file.url);
  98. }
  99. };
  100. const onInternalClose = file => {
  101. var _a;
  102. (_a = props.onRemove) === null || _a === void 0 ? void 0 : _a.call(props, file);
  103. };
  104. const internalIconRender = _ref3 => {
  105. let {
  106. file
  107. } = _ref3;
  108. const iconRender = props.iconRender || slots.iconRender;
  109. if (iconRender) {
  110. return iconRender({
  111. file,
  112. listType: props.listType
  113. });
  114. }
  115. const isLoading = file.status === 'uploading';
  116. const fileIcon = props.isImageUrl && props.isImageUrl(file) ? _createVNode(PictureTwoTone, null, null) : _createVNode(FileTwoTone, null, null);
  117. let icon = isLoading ? _createVNode(LoadingOutlined, null, null) : _createVNode(PaperClipOutlined, null, null);
  118. if (props.listType === 'picture') {
  119. icon = isLoading ? _createVNode(LoadingOutlined, null, null) : fileIcon;
  120. } else if (props.listType === 'picture-card') {
  121. icon = isLoading ? props.locale.uploading : fileIcon;
  122. }
  123. return icon;
  124. };
  125. const actionIconRender = opt => {
  126. const {
  127. customIcon,
  128. callback,
  129. prefixCls,
  130. title
  131. } = opt;
  132. const btnProps = {
  133. type: 'text',
  134. size: 'small',
  135. title,
  136. onClick: () => {
  137. callback();
  138. },
  139. class: `${prefixCls}-list-item-action`
  140. };
  141. if (isValidElement(customIcon)) {
  142. return _createVNode(Button, btnProps, {
  143. icon: () => customIcon
  144. });
  145. }
  146. return _createVNode(Button, btnProps, {
  147. default: () => [_createVNode("span", null, [customIcon])]
  148. });
  149. };
  150. expose({
  151. handlePreview: onInternalPreview,
  152. handleDownload: onInternalDownload
  153. });
  154. const {
  155. prefixCls,
  156. rootPrefixCls
  157. } = useConfigInject('upload', props);
  158. const listClassNames = computed(() => ({
  159. [`${prefixCls.value}-list`]: true,
  160. [`${prefixCls.value}-list-${props.listType}`]: true
  161. }));
  162. const transitionGroupProps = computed(() => {
  163. const motion = _extends({}, collapseMotion(`${rootPrefixCls.value}-motion-collapse`));
  164. delete motion.onAfterAppear;
  165. delete motion.onAfterEnter;
  166. delete motion.onAfterLeave;
  167. const motionConfig = _extends(_extends({}, getTransitionGroupProps(`${prefixCls.value}-${props.listType === 'picture-card' ? 'animate-inline' : 'animate'}`)), {
  168. class: listClassNames.value,
  169. appear: motionAppear.value
  170. });
  171. return props.listType !== 'picture-card' ? _extends(_extends({}, motion), motionConfig) : motionConfig;
  172. });
  173. return () => {
  174. const {
  175. listType,
  176. locale,
  177. isImageUrl: isImgUrl,
  178. showPreviewIcon,
  179. showRemoveIcon,
  180. showDownloadIcon,
  181. removeIcon,
  182. previewIcon,
  183. downloadIcon,
  184. progress,
  185. appendAction,
  186. itemRender,
  187. appendActionVisible
  188. } = props;
  189. const appendActionDom = appendAction === null || appendAction === void 0 ? void 0 : appendAction();
  190. const items = mergedItems.value;
  191. return _createVNode(TransitionGroup, _objectSpread(_objectSpread({}, transitionGroupProps.value), {}, {
  192. "tag": "div"
  193. }), {
  194. default: () => [items.map(file => {
  195. const {
  196. uid: key
  197. } = file;
  198. return _createVNode(ListItem, {
  199. "key": key,
  200. "locale": locale,
  201. "prefixCls": prefixCls.value,
  202. "file": file,
  203. "items": items,
  204. "progress": progress,
  205. "listType": listType,
  206. "isImgUrl": isImgUrl,
  207. "showPreviewIcon": showPreviewIcon,
  208. "showRemoveIcon": showRemoveIcon,
  209. "showDownloadIcon": showDownloadIcon,
  210. "onPreview": onInternalPreview,
  211. "onDownload": onInternalDownload,
  212. "onClose": onInternalClose,
  213. "removeIcon": removeIcon,
  214. "previewIcon": previewIcon,
  215. "downloadIcon": downloadIcon,
  216. "itemRender": itemRender
  217. }, _extends(_extends({}, slots), {
  218. iconRender: internalIconRender,
  219. actionIconRender
  220. }));
  221. }), appendAction ? _withDirectives(_createVNode(HackSlot, {
  222. "key": "__ant_upload_appendAction"
  223. }, {
  224. default: () => appendActionDom
  225. }), [[_vShow, !!appendActionVisible]]) : null]
  226. });
  227. };
  228. }
  229. });