ListItem.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import { withDirectives as _withDirectives, vShow as _vShow, createVNode as _createVNode } from "vue";
  3. import { computed, defineComponent, onBeforeUnmount, onMounted, shallowRef, watch } from 'vue';
  4. import EyeOutlined from "@ant-design/icons-vue/es/icons/EyeOutlined";
  5. import DeleteOutlined from "@ant-design/icons-vue/es/icons/DeleteOutlined";
  6. import DownloadOutlined from "@ant-design/icons-vue/es/icons/DownloadOutlined";
  7. import Tooltip from '../../tooltip';
  8. import Progress from '../../progress';
  9. import useConfigInject from '../../config-provider/hooks/useConfigInject';
  10. import Transition, { getTransitionProps } from '../../_util/transition';
  11. import { booleanType, stringType, functionType, arrayType, objectType } from '../../_util/type';
  12. export const listItemProps = () => {
  13. return {
  14. prefixCls: String,
  15. locale: objectType(undefined),
  16. file: objectType(),
  17. items: arrayType(),
  18. listType: stringType(),
  19. isImgUrl: functionType(),
  20. showRemoveIcon: booleanType(),
  21. showDownloadIcon: booleanType(),
  22. showPreviewIcon: booleanType(),
  23. removeIcon: functionType(),
  24. downloadIcon: functionType(),
  25. previewIcon: functionType(),
  26. iconRender: functionType(),
  27. actionIconRender: functionType(),
  28. itemRender: functionType(),
  29. onPreview: functionType(),
  30. onClose: functionType(),
  31. onDownload: functionType(),
  32. progress: objectType()
  33. };
  34. };
  35. export default defineComponent({
  36. compatConfig: {
  37. MODE: 3
  38. },
  39. name: 'ListItem',
  40. inheritAttrs: false,
  41. props: listItemProps(),
  42. setup(props, _ref) {
  43. let {
  44. slots,
  45. attrs
  46. } = _ref;
  47. var _a;
  48. const showProgress = shallowRef(false);
  49. const progressRafRef = shallowRef();
  50. onMounted(() => {
  51. progressRafRef.value = setTimeout(() => {
  52. showProgress.value = true;
  53. }, 300);
  54. });
  55. onBeforeUnmount(() => {
  56. clearTimeout(progressRafRef.value);
  57. });
  58. const mergedStatus = shallowRef((_a = props.file) === null || _a === void 0 ? void 0 : _a.status);
  59. watch(() => {
  60. var _a;
  61. return (_a = props.file) === null || _a === void 0 ? void 0 : _a.status;
  62. }, status => {
  63. if (status !== 'removed') {
  64. mergedStatus.value = status;
  65. }
  66. });
  67. const {
  68. rootPrefixCls
  69. } = useConfigInject('upload', props);
  70. const transitionProps = computed(() => getTransitionProps(`${rootPrefixCls.value}-fade`));
  71. return () => {
  72. var _a, _b;
  73. const {
  74. prefixCls,
  75. locale,
  76. listType,
  77. file,
  78. items,
  79. progress: progressProps,
  80. iconRender = slots.iconRender,
  81. actionIconRender = slots.actionIconRender,
  82. itemRender = slots.itemRender,
  83. isImgUrl,
  84. showPreviewIcon,
  85. showRemoveIcon,
  86. showDownloadIcon,
  87. previewIcon: customPreviewIcon = slots.previewIcon,
  88. removeIcon: customRemoveIcon = slots.removeIcon,
  89. downloadIcon: customDownloadIcon = slots.downloadIcon,
  90. onPreview,
  91. onDownload,
  92. onClose
  93. } = props;
  94. const {
  95. class: className,
  96. style
  97. } = attrs;
  98. // This is used for legacy span make scrollHeight the wrong value.
  99. // We will force these to be `display: block` with non `picture-card`
  100. const iconNode = iconRender({
  101. file
  102. });
  103. let icon = _createVNode("div", {
  104. "class": `${prefixCls}-text-icon`
  105. }, [iconNode]);
  106. if (listType === 'picture' || listType === 'picture-card') {
  107. if (mergedStatus.value === 'uploading' || !file.thumbUrl && !file.url) {
  108. const uploadingClassName = {
  109. [`${prefixCls}-list-item-thumbnail`]: true,
  110. [`${prefixCls}-list-item-file`]: mergedStatus.value !== 'uploading'
  111. };
  112. icon = _createVNode("div", {
  113. "class": uploadingClassName
  114. }, [iconNode]);
  115. } else {
  116. const thumbnail = (isImgUrl === null || isImgUrl === void 0 ? void 0 : isImgUrl(file)) ? _createVNode("img", {
  117. "src": file.thumbUrl || file.url,
  118. "alt": file.name,
  119. "class": `${prefixCls}-list-item-image`,
  120. "crossorigin": file.crossOrigin
  121. }, null) : iconNode;
  122. const aClassName = {
  123. [`${prefixCls}-list-item-thumbnail`]: true,
  124. [`${prefixCls}-list-item-file`]: isImgUrl && !isImgUrl(file)
  125. };
  126. icon = _createVNode("a", {
  127. "class": aClassName,
  128. "onClick": e => onPreview(file, e),
  129. "href": file.url || file.thumbUrl,
  130. "target": "_blank",
  131. "rel": "noopener noreferrer"
  132. }, [thumbnail]);
  133. }
  134. }
  135. const infoUploadingClass = {
  136. [`${prefixCls}-list-item`]: true,
  137. [`${prefixCls}-list-item-${mergedStatus.value}`]: true
  138. };
  139. const linkProps = typeof file.linkProps === 'string' ? JSON.parse(file.linkProps) : file.linkProps;
  140. const removeIcon = showRemoveIcon ? actionIconRender({
  141. customIcon: customRemoveIcon ? customRemoveIcon({
  142. file
  143. }) : _createVNode(DeleteOutlined, null, null),
  144. callback: () => onClose(file),
  145. prefixCls,
  146. title: locale.removeFile
  147. }) : null;
  148. const downloadIcon = showDownloadIcon && mergedStatus.value === 'done' ? actionIconRender({
  149. customIcon: customDownloadIcon ? customDownloadIcon({
  150. file
  151. }) : _createVNode(DownloadOutlined, null, null),
  152. callback: () => onDownload(file),
  153. prefixCls,
  154. title: locale.downloadFile
  155. }) : null;
  156. const downloadOrDelete = listType !== 'picture-card' && _createVNode("span", {
  157. "key": "download-delete",
  158. "class": [`${prefixCls}-list-item-actions`, {
  159. picture: listType === 'picture'
  160. }]
  161. }, [downloadIcon, removeIcon]);
  162. const listItemNameClass = `${prefixCls}-list-item-name`;
  163. const fileName = file.url ? [_createVNode("a", _objectSpread(_objectSpread({
  164. "key": "view",
  165. "target": "_blank",
  166. "rel": "noopener noreferrer",
  167. "class": listItemNameClass,
  168. "title": file.name
  169. }, linkProps), {}, {
  170. "href": file.url,
  171. "onClick": e => onPreview(file, e)
  172. }), [file.name]), downloadOrDelete] : [_createVNode("span", {
  173. "key": "view",
  174. "class": listItemNameClass,
  175. "onClick": e => onPreview(file, e),
  176. "title": file.name
  177. }, [file.name]), downloadOrDelete];
  178. const previewStyle = {
  179. pointerEvents: 'none',
  180. opacity: 0.5
  181. };
  182. const previewIcon = showPreviewIcon ? _createVNode("a", {
  183. "href": file.url || file.thumbUrl,
  184. "target": "_blank",
  185. "rel": "noopener noreferrer",
  186. "style": file.url || file.thumbUrl ? undefined : previewStyle,
  187. "onClick": e => onPreview(file, e),
  188. "title": locale.previewFile
  189. }, [customPreviewIcon ? customPreviewIcon({
  190. file
  191. }) : _createVNode(EyeOutlined, null, null)]) : null;
  192. const pictureCardActions = listType === 'picture-card' && mergedStatus.value !== 'uploading' && _createVNode("span", {
  193. "class": `${prefixCls}-list-item-actions`
  194. }, [previewIcon, mergedStatus.value === 'done' && downloadIcon, removeIcon]);
  195. const dom = _createVNode("div", {
  196. "class": infoUploadingClass
  197. }, [icon, fileName, pictureCardActions, showProgress.value && _createVNode(Transition, transitionProps.value, {
  198. default: () => [_withDirectives(_createVNode("div", {
  199. "class": `${prefixCls}-list-item-progress`
  200. }, ['percent' in file ? _createVNode(Progress, _objectSpread(_objectSpread({}, progressProps), {}, {
  201. "type": "line",
  202. "percent": file.percent
  203. }), null) : null]), [[_vShow, mergedStatus.value === 'uploading']])]
  204. })]);
  205. const listContainerNameClass = {
  206. [`${prefixCls}-list-item-container`]: true,
  207. [`${className}`]: !!className
  208. };
  209. const message = file.response && typeof file.response === 'string' ? file.response : ((_a = file.error) === null || _a === void 0 ? void 0 : _a.statusText) || ((_b = file.error) === null || _b === void 0 ? void 0 : _b.message) || locale.uploadError;
  210. const item = mergedStatus.value === 'error' ? _createVNode(Tooltip, {
  211. "title": message,
  212. "getPopupContainer": node => node.parentNode
  213. }, {
  214. default: () => [dom]
  215. }) : dom;
  216. return _createVNode("div", {
  217. "class": listContainerNameClass,
  218. "style": style
  219. }, [itemRender ? itemRender({
  220. originNode: item,
  221. file,
  222. fileList: items,
  223. actions: {
  224. download: onDownload.bind(null, file),
  225. preview: onPreview.bind(null, file),
  226. remove: onClose.bind(null, file)
  227. }
  228. }) : item]);
  229. };
  230. }
  231. });